Initial check in

Bug: 137197907
diff --git a/src/test/ui/E0501.ast.nll.stderr b/src/test/ui/E0501.ast.nll.stderr
new file mode 100644
index 0000000..74f14beb
--- /dev/null
+++ b/src/test/ui/E0501.ast.nll.stderr
@@ -0,0 +1,31 @@
+error[E0501]: cannot borrow `*a` as mutable because previous closure requires unique access
+  --> $DIR/E0501.rs:18:23
+   |
+LL |     let bar = || {
+   |               -- closure construction occurs here
+LL |         inside_closure(a)
+   |                        - first borrow occurs due to use of `a` in closure
+LL |     };
+LL |     outside_closure_1(a);
+   |                       ^ second borrow occurs here
+...
+LL |     drop(bar);
+   |          --- first borrow later used here
+
+error[E0501]: cannot borrow `*a` as immutable because previous closure requires unique access
+  --> $DIR/E0501.rs:21:23
+   |
+LL |     let bar = || {
+   |               -- closure construction occurs here
+LL |         inside_closure(a)
+   |                        - first borrow occurs due to use of `a` in closure
+...
+LL |     outside_closure_2(a);
+   |                       ^ second borrow occurs here
+...
+LL |     drop(bar);
+   |          --- first borrow later used here
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0501`.
diff --git a/src/test/ui/E0501.ast.stderr b/src/test/ui/E0501.ast.stderr
new file mode 100644
index 0000000..e2f54c6
--- /dev/null
+++ b/src/test/ui/E0501.ast.stderr
@@ -0,0 +1,31 @@
+error[E0501]: cannot borrow `*a` as mutable because previous closure requires unique access
+  --> $DIR/E0501.rs:18:23
+   |
+LL |     let bar = || {
+   |               -- closure construction occurs here
+LL |         inside_closure(a)
+   |                        - previous borrow occurs due to use of `a` in closure
+LL |     };
+LL |     outside_closure_1(a);
+   |                       ^ borrow occurs here
+...
+LL | }
+   | - borrow from closure ends here
+
+error[E0501]: cannot borrow `*a` as immutable because previous closure requires unique access
+  --> $DIR/E0501.rs:21:23
+   |
+LL |     let bar = || {
+   |               -- closure construction occurs here
+LL |         inside_closure(a)
+   |                        - previous borrow occurs due to use of `a` in closure
+...
+LL |     outside_closure_2(a);
+   |                       ^ borrow occurs here
+...
+LL | }
+   | - borrow from closure ends here
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0501`.
diff --git a/src/test/ui/E0501.mir.stderr b/src/test/ui/E0501.mir.stderr
new file mode 100644
index 0000000..74f14beb
--- /dev/null
+++ b/src/test/ui/E0501.mir.stderr
@@ -0,0 +1,31 @@
+error[E0501]: cannot borrow `*a` as mutable because previous closure requires unique access
+  --> $DIR/E0501.rs:18:23
+   |
+LL |     let bar = || {
+   |               -- closure construction occurs here
+LL |         inside_closure(a)
+   |                        - first borrow occurs due to use of `a` in closure
+LL |     };
+LL |     outside_closure_1(a);
+   |                       ^ second borrow occurs here
+...
+LL |     drop(bar);
+   |          --- first borrow later used here
+
+error[E0501]: cannot borrow `*a` as immutable because previous closure requires unique access
+  --> $DIR/E0501.rs:21:23
+   |
+LL |     let bar = || {
+   |               -- closure construction occurs here
+LL |         inside_closure(a)
+   |                        - first borrow occurs due to use of `a` in closure
+...
+LL |     outside_closure_2(a);
+   |                       ^ second borrow occurs here
+...
+LL |     drop(bar);
+   |          --- first borrow later used here
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0501`.
diff --git a/src/test/ui/E0501.rs b/src/test/ui/E0501.rs
new file mode 100644
index 0000000..a710e23
--- /dev/null
+++ b/src/test/ui/E0501.rs
@@ -0,0 +1,28 @@
+// ignore-tidy-linelength
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+fn inside_closure(x: &mut i32) {
+}
+
+fn outside_closure_1(x: &mut i32) {
+}
+
+fn outside_closure_2(x: &i32) {
+}
+
+fn foo(a: &mut i32) {
+    let bar = || {
+        inside_closure(a)
+    };
+    outside_closure_1(a); //[ast]~ ERROR cannot borrow `*a` as mutable because previous closure requires unique access
+    //[mir]~^ ERROR cannot borrow `*a` as mutable because previous closure requires unique access
+
+    outside_closure_2(a); //[ast]~ ERROR cannot borrow `*a` as immutable because previous closure requires unique access
+    //[mir]~^ ERROR cannot borrow `*a` as immutable because previous closure requires unique access
+
+    drop(bar);
+}
+
+fn main() {
+}
diff --git a/src/test/ui/E0506.ast.nll.stderr b/src/test/ui/E0506.ast.nll.stderr
new file mode 100644
index 0000000..6e2d634
--- /dev/null
+++ b/src/test/ui/E0506.ast.nll.stderr
@@ -0,0 +1,14 @@
+error[E0506]: cannot assign to `fancy_num` because it is borrowed
+  --> $DIR/E0506.rs:11:5
+   |
+LL |     let fancy_ref = &fancy_num;
+   |                     ---------- borrow of `fancy_num` occurs here
+LL |     fancy_num = FancyNum { num: 6 };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `fancy_num` occurs here
+...
+LL |     println!("Num: {}, Ref: {}", fancy_num.num, fancy_ref.num);
+   |                                                 ------------- borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/E0506.ast.stderr b/src/test/ui/E0506.ast.stderr
new file mode 100644
index 0000000..3e3001f
--- /dev/null
+++ b/src/test/ui/E0506.ast.stderr
@@ -0,0 +1,11 @@
+error[E0506]: cannot assign to `fancy_num` because it is borrowed
+  --> $DIR/E0506.rs:11:5
+   |
+LL |     let fancy_ref = &fancy_num;
+   |                      --------- borrow of `fancy_num` occurs here
+LL |     fancy_num = FancyNum { num: 6 };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `fancy_num` occurs here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/E0506.mir.stderr b/src/test/ui/E0506.mir.stderr
new file mode 100644
index 0000000..6e2d634
--- /dev/null
+++ b/src/test/ui/E0506.mir.stderr
@@ -0,0 +1,14 @@
+error[E0506]: cannot assign to `fancy_num` because it is borrowed
+  --> $DIR/E0506.rs:11:5
+   |
+LL |     let fancy_ref = &fancy_num;
+   |                     ---------- borrow of `fancy_num` occurs here
+LL |     fancy_num = FancyNum { num: 6 };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `fancy_num` occurs here
+...
+LL |     println!("Num: {}, Ref: {}", fancy_num.num, fancy_ref.num);
+   |                                                 ------------- borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/E0506.rs b/src/test/ui/E0506.rs
new file mode 100644
index 0000000..04aaa00
--- /dev/null
+++ b/src/test/ui/E0506.rs
@@ -0,0 +1,15 @@
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+struct FancyNum {
+    num: u8,
+}
+
+fn main() {
+    let mut fancy_num = FancyNum { num: 5 };
+    let fancy_ref = &fancy_num;
+    fancy_num = FancyNum { num: 6 }; //[ast]~ ERROR E0506
+                                     //[mir]~^ ERROR [E0506]
+
+    println!("Num: {}, Ref: {}", fancy_num.num, fancy_ref.num);
+}
diff --git a/src/test/ui/E0508-fail.ast.nll.stderr b/src/test/ui/E0508-fail.ast.nll.stderr
new file mode 100644
index 0000000..972b84e
--- /dev/null
+++ b/src/test/ui/E0508-fail.ast.nll.stderr
@@ -0,0 +1,12 @@
+error[E0508]: cannot move out of type `[NonCopy; 1]`, a non-copy array
+  --> $DIR/E0508-fail.rs:8:18
+   |
+LL |     let _value = array[0];
+   |                  ^^^^^^^^
+   |                  |
+   |                  cannot move out of here
+   |                  help: consider borrowing here: `&array[0]`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0508`.
diff --git a/src/test/ui/E0508-fail.ast.stderr b/src/test/ui/E0508-fail.ast.stderr
new file mode 100644
index 0000000..8b24983
--- /dev/null
+++ b/src/test/ui/E0508-fail.ast.stderr
@@ -0,0 +1,12 @@
+error[E0508]: cannot move out of type `[NonCopy; 1]`, a non-copy array
+  --> $DIR/E0508-fail.rs:8:18
+   |
+LL |     let _value = array[0];
+   |                  ^^^^^^^^
+   |                  |
+   |                  cannot move out of here
+   |                  help: consider using a reference instead: `&array[0]`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0508`.
diff --git a/src/test/ui/E0508-fail.mir.stderr b/src/test/ui/E0508-fail.mir.stderr
new file mode 100644
index 0000000..972b84e
--- /dev/null
+++ b/src/test/ui/E0508-fail.mir.stderr
@@ -0,0 +1,12 @@
+error[E0508]: cannot move out of type `[NonCopy; 1]`, a non-copy array
+  --> $DIR/E0508-fail.rs:8:18
+   |
+LL |     let _value = array[0];
+   |                  ^^^^^^^^
+   |                  |
+   |                  cannot move out of here
+   |                  help: consider borrowing here: `&array[0]`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0508`.
diff --git a/src/test/ui/E0508-fail.rs b/src/test/ui/E0508-fail.rs
new file mode 100644
index 0000000..20eac6c
--- /dev/null
+++ b/src/test/ui/E0508-fail.rs
@@ -0,0 +1,10 @@
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+struct NonCopy;
+
+fn main() {
+    let array = [NonCopy; 1];
+    let _value = array[0];  //[ast]~ ERROR [E0508]
+                            //[mir]~^ ERROR [E0508]
+}
diff --git a/src/test/ui/E0508.nll.stderr b/src/test/ui/E0508.nll.stderr
new file mode 100644
index 0000000..983062e
--- /dev/null
+++ b/src/test/ui/E0508.nll.stderr
@@ -0,0 +1,12 @@
+error[E0508]: cannot move out of type `[NonCopy; 1]`, a non-copy array
+  --> $DIR/E0508.rs:5:18
+   |
+LL |     let _value = array[0];
+   |                  ^^^^^^^^
+   |                  |
+   |                  cannot move out of here
+   |                  help: consider borrowing here: `&array[0]`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0508`.
diff --git a/src/test/ui/E0508.rs b/src/test/ui/E0508.rs
new file mode 100644
index 0000000..072c3d6
--- /dev/null
+++ b/src/test/ui/E0508.rs
@@ -0,0 +1,6 @@
+struct NonCopy;
+
+fn main() {
+    let array = [NonCopy; 1];
+    let _value = array[0];  //~ ERROR [E0508]
+}
diff --git a/src/test/ui/E0508.stderr b/src/test/ui/E0508.stderr
new file mode 100644
index 0000000..ba6cff8
--- /dev/null
+++ b/src/test/ui/E0508.stderr
@@ -0,0 +1,12 @@
+error[E0508]: cannot move out of type `[NonCopy; 1]`, a non-copy array
+  --> $DIR/E0508.rs:5:18
+   |
+LL |     let _value = array[0];
+   |                  ^^^^^^^^
+   |                  |
+   |                  cannot move out of here
+   |                  help: consider using a reference instead: `&array[0]`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0508`.
diff --git a/src/test/ui/E0583.rs b/src/test/ui/E0583.rs
new file mode 100644
index 0000000..969de79
--- /dev/null
+++ b/src/test/ui/E0583.rs
@@ -0,0 +1,4 @@
+mod module_that_doesnt_exist; //~ ERROR E0583
+
+fn main() {
+}
diff --git a/src/test/ui/E0583.stderr b/src/test/ui/E0583.stderr
new file mode 100644
index 0000000..ef7a48b
--- /dev/null
+++ b/src/test/ui/E0583.stderr
@@ -0,0 +1,11 @@
+error[E0583]: file not found for module `module_that_doesnt_exist`
+  --> $DIR/E0583.rs:1:5
+   |
+LL | mod module_that_doesnt_exist;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: name the file either module_that_doesnt_exist.rs or module_that_doesnt_exist/mod.rs inside the directory "$DIR"
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0583`.
diff --git a/src/test/ui/E0594.ast.nll.stderr b/src/test/ui/E0594.ast.nll.stderr
new file mode 100644
index 0000000..cc1c968
--- /dev/null
+++ b/src/test/ui/E0594.ast.nll.stderr
@@ -0,0 +1,9 @@
+error[E0594]: cannot assign to immutable static item `NUM`
+  --> $DIR/E0594.rs:7:5
+   |
+LL |     NUM = 20;
+   |     ^^^^^^^^ cannot assign
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/E0594.ast.stderr b/src/test/ui/E0594.ast.stderr
new file mode 100644
index 0000000..0c5316d
--- /dev/null
+++ b/src/test/ui/E0594.ast.stderr
@@ -0,0 +1,9 @@
+error[E0594]: cannot assign to immutable static item
+  --> $DIR/E0594.rs:7:5
+   |
+LL |     NUM = 20;
+   |     ^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/E0594.mir.stderr b/src/test/ui/E0594.mir.stderr
new file mode 100644
index 0000000..cc1c968
--- /dev/null
+++ b/src/test/ui/E0594.mir.stderr
@@ -0,0 +1,9 @@
+error[E0594]: cannot assign to immutable static item `NUM`
+  --> $DIR/E0594.rs:7:5
+   |
+LL |     NUM = 20;
+   |     ^^^^^^^^ cannot assign
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/E0594.rs b/src/test/ui/E0594.rs
new file mode 100644
index 0000000..a8ca2fe
--- /dev/null
+++ b/src/test/ui/E0594.rs
@@ -0,0 +1,9 @@
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+static NUM: i32 = 18;
+
+fn main() {
+    NUM = 20; //[ast]~ ERROR E0594
+              //[mir]~^ ERROR cannot assign to immutable static item `NUM`
+}
diff --git a/src/test/ui/E0596.ast.nll.stderr b/src/test/ui/E0596.ast.nll.stderr
new file mode 100644
index 0000000..c89a915
--- /dev/null
+++ b/src/test/ui/E0596.ast.nll.stderr
@@ -0,0 +1,11 @@
+error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
+  --> $DIR/E0596.rs:6:13
+   |
+LL |     let x = 1;
+   |         - help: consider changing this to be mutable: `mut x`
+LL |     let y = &mut x;
+   |             ^^^^^^ cannot borrow as mutable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/E0596.ast.stderr b/src/test/ui/E0596.ast.stderr
new file mode 100644
index 0000000..4b66e49
--- /dev/null
+++ b/src/test/ui/E0596.ast.stderr
@@ -0,0 +1,11 @@
+error[E0596]: cannot borrow immutable local variable `x` as mutable
+  --> $DIR/E0596.rs:6:18
+   |
+LL |     let x = 1;
+   |         - help: make this binding mutable: `mut x`
+LL |     let y = &mut x;
+   |                  ^ cannot borrow mutably
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/E0596.mir.stderr b/src/test/ui/E0596.mir.stderr
new file mode 100644
index 0000000..c89a915
--- /dev/null
+++ b/src/test/ui/E0596.mir.stderr
@@ -0,0 +1,11 @@
+error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
+  --> $DIR/E0596.rs:6:13
+   |
+LL |     let x = 1;
+   |         - help: consider changing this to be mutable: `mut x`
+LL |     let y = &mut x;
+   |             ^^^^^^ cannot borrow as mutable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/E0596.rs b/src/test/ui/E0596.rs
new file mode 100644
index 0000000..3ea2d64
--- /dev/null
+++ b/src/test/ui/E0596.rs
@@ -0,0 +1,8 @@
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+fn main() {
+    let x = 1;
+    let y = &mut x; //[ast]~ ERROR [E0596]
+                    //[mir]~^ ERROR [E0596]
+}
diff --git a/src/test/ui/E0642.rs b/src/test/ui/E0642.rs
new file mode 100644
index 0000000..cfbd362
--- /dev/null
+++ b/src/test/ui/E0642.rs
@@ -0,0 +1,16 @@
+#[derive(Clone, Copy)]
+struct S;
+
+trait T {
+    fn foo((x, y): (i32, i32)); //~ ERROR patterns aren't allowed in methods without bodies
+
+    fn bar((x, y): (i32, i32)) {} //~ ERROR patterns aren't allowed in methods without bodies
+
+    fn method(S { .. }: S) {} //~ ERROR patterns aren't allowed in methods without bodies
+
+    fn f(&ident: &S) {} // ok
+    fn g(&&ident: &&S) {} // ok
+    fn h(mut ident: S) {} // ok
+}
+
+fn main() {}
diff --git a/src/test/ui/E0642.stderr b/src/test/ui/E0642.stderr
new file mode 100644
index 0000000..da25514
--- /dev/null
+++ b/src/test/ui/E0642.stderr
@@ -0,0 +1,33 @@
+error[E0642]: patterns aren't allowed in methods without bodies
+  --> $DIR/E0642.rs:5:12
+   |
+LL |     fn foo((x, y): (i32, i32));
+   |            ^^^^^^
+help: give this argument a name or use an underscore to ignore it
+   |
+LL |     fn foo(_: (i32, i32));
+   |            ^
+
+error[E0642]: patterns aren't allowed in methods without bodies
+  --> $DIR/E0642.rs:7:12
+   |
+LL |     fn bar((x, y): (i32, i32)) {}
+   |            ^^^^^^
+help: give this argument a name or use an underscore to ignore it
+   |
+LL |     fn bar(_: (i32, i32)) {}
+   |            ^
+
+error[E0642]: patterns aren't allowed in methods without bodies
+  --> $DIR/E0642.rs:9:15
+   |
+LL |     fn method(S { .. }: S) {}
+   |               ^^^^^^^^
+help: give this argument a name or use an underscore to ignore it
+   |
+LL |     fn method(_: S) {}
+   |               ^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0642`.
diff --git a/src/test/ui/E0660.rs b/src/test/ui/E0660.rs
new file mode 100644
index 0000000..6280d39
--- /dev/null
+++ b/src/test/ui/E0660.rs
@@ -0,0 +1,9 @@
+#![feature(asm)]
+
+fn main() {
+    let a;
+    asm!("nop" "nop");
+    //~^ ERROR E0660
+    asm!("nop" "nop" : "=r"(a));
+    //~^ ERROR E0660
+}
diff --git a/src/test/ui/E0660.stderr b/src/test/ui/E0660.stderr
new file mode 100644
index 0000000..d355531
--- /dev/null
+++ b/src/test/ui/E0660.stderr
@@ -0,0 +1,15 @@
+error[E0660]: malformed inline assembly
+  --> $DIR/E0660.rs:5:5
+   |
+LL |     asm!("nop" "nop");
+   |     ^^^^^^^^^^^^^^^^^^
+
+error[E0660]: malformed inline assembly
+  --> $DIR/E0660.rs:7:5
+   |
+LL |     asm!("nop" "nop" : "=r"(a));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0660`.
diff --git a/src/test/ui/E0661.rs b/src/test/ui/E0661.rs
new file mode 100644
index 0000000..8d355a8
--- /dev/null
+++ b/src/test/ui/E0661.rs
@@ -0,0 +1,7 @@
+#![feature(asm)]
+
+fn main() {
+    let a;
+    asm!("nop" : "r"(a));
+    //~^ ERROR E0661
+}
diff --git a/src/test/ui/E0661.stderr b/src/test/ui/E0661.stderr
new file mode 100644
index 0000000..1f41f89
--- /dev/null
+++ b/src/test/ui/E0661.stderr
@@ -0,0 +1,9 @@
+error[E0661]: output operand constraint lacks '=' or '+'
+  --> $DIR/E0661.rs:5:18
+   |
+LL |     asm!("nop" : "r"(a));
+   |                  ^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0661`.
diff --git a/src/test/ui/E0662.rs b/src/test/ui/E0662.rs
new file mode 100644
index 0000000..7fe528c
--- /dev/null
+++ b/src/test/ui/E0662.rs
@@ -0,0 +1,8 @@
+#![feature(asm)]
+
+fn main() {
+    asm!("xor %eax, %eax"
+         :
+         : "=test"("a") //~ ERROR E0662
+        );
+}
diff --git a/src/test/ui/E0662.stderr b/src/test/ui/E0662.stderr
new file mode 100644
index 0000000..5dea744
--- /dev/null
+++ b/src/test/ui/E0662.stderr
@@ -0,0 +1,9 @@
+error[E0662]: input operand constraint contains '='
+  --> $DIR/E0662.rs:6:12
+   |
+LL |          : "=test"("a")
+   |            ^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0662`.
diff --git a/src/test/ui/E0663.rs b/src/test/ui/E0663.rs
new file mode 100644
index 0000000..e5b8156
--- /dev/null
+++ b/src/test/ui/E0663.rs
@@ -0,0 +1,8 @@
+#![feature(asm)]
+
+fn main() {
+    asm!("xor %eax, %eax"
+         :
+         : "+test"("a") //~ ERROR E0663
+        );
+}
diff --git a/src/test/ui/E0663.stderr b/src/test/ui/E0663.stderr
new file mode 100644
index 0000000..01bf89e
--- /dev/null
+++ b/src/test/ui/E0663.stderr
@@ -0,0 +1,9 @@
+error[E0663]: input operand constraint contains '+'
+  --> $DIR/E0663.rs:6:12
+   |
+LL |          : "+test"("a")
+   |            ^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0663`.
diff --git a/src/test/ui/E0664.rs b/src/test/ui/E0664.rs
new file mode 100644
index 0000000..29ec7ce
--- /dev/null
+++ b/src/test/ui/E0664.rs
@@ -0,0 +1,9 @@
+#![feature(asm)]
+
+fn main() {
+    asm!("mov $$0x200, %eax"
+         :
+         :
+         : "{eax}" //~ ERROR E0664
+        );
+}
diff --git a/src/test/ui/E0664.stderr b/src/test/ui/E0664.stderr
new file mode 100644
index 0000000..9c9f65e
--- /dev/null
+++ b/src/test/ui/E0664.stderr
@@ -0,0 +1,9 @@
+error[E0664]: clobber should not be surrounded by braces
+  --> $DIR/E0664.rs:7:12
+   |
+LL |          : "{eax}"
+   |            ^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0664`.
diff --git a/src/test/ui/E0665.rs b/src/test/ui/E0665.rs
new file mode 100644
index 0000000..cfd42bd
--- /dev/null
+++ b/src/test/ui/E0665.rs
@@ -0,0 +1,8 @@
+#[derive(Default)] //~ ERROR E0665
+enum Food {
+    Sweet,
+    Salty,
+}
+
+fn main() {
+}
diff --git a/src/test/ui/E0665.stderr b/src/test/ui/E0665.stderr
new file mode 100644
index 0000000..2c2b498
--- /dev/null
+++ b/src/test/ui/E0665.stderr
@@ -0,0 +1,9 @@
+error[E0665]: `Default` cannot be derived for enums, only structs
+  --> $DIR/E0665.rs:1:10
+   |
+LL | #[derive(Default)]
+   |          ^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0665`.
diff --git a/src/test/ui/E0705.rs b/src/test/ui/E0705.rs
new file mode 100644
index 0000000..cc2b8f6
--- /dev/null
+++ b/src/test/ui/E0705.rs
@@ -0,0 +1,10 @@
+// compile-pass
+
+// This is a stub feature that doesn't control anything, so to make tidy happy,
+// gate-test-test_2018_feature
+
+#![feature(test_2018_feature)]
+//~^ WARN the feature `test_2018_feature` is included in the Rust 2018 edition
+#![feature(rust_2018_preview)]
+
+fn main() {}
diff --git a/src/test/ui/E0705.stderr b/src/test/ui/E0705.stderr
new file mode 100644
index 0000000..1cb83f2
--- /dev/null
+++ b/src/test/ui/E0705.stderr
@@ -0,0 +1,6 @@
+warning[E0705]: the feature `test_2018_feature` is included in the Rust 2018 edition
+  --> $DIR/E0705.rs:6:12
+   |
+LL | #![feature(test_2018_feature)]
+   |            ^^^^^^^^^^^^^^^^^
+
diff --git a/src/test/ui/absolute-paths-in-nested-use-groups.rs b/src/test/ui/absolute-paths-in-nested-use-groups.rs
new file mode 100644
index 0000000..96b5131
--- /dev/null
+++ b/src/test/ui/absolute-paths-in-nested-use-groups.rs
@@ -0,0 +1,11 @@
+#![allow(unused_imports)]
+
+mod foo {}
+
+use foo::{
+    ::bar,       //~ ERROR crate root in paths can only be used in start position
+    super::bar,  //~ ERROR `super` in paths can only be used in start position
+    self::bar,   //~ ERROR `self` in paths can only be used in start position
+};
+
+fn main() {}
diff --git a/src/test/ui/absolute-paths-in-nested-use-groups.stderr b/src/test/ui/absolute-paths-in-nested-use-groups.stderr
new file mode 100644
index 0000000..e41590a
--- /dev/null
+++ b/src/test/ui/absolute-paths-in-nested-use-groups.stderr
@@ -0,0 +1,21 @@
+error[E0433]: failed to resolve: crate root in paths can only be used in start position
+  --> $DIR/absolute-paths-in-nested-use-groups.rs:6:5
+   |
+LL |     ::bar,
+   |     ^ crate root in paths can only be used in start position
+
+error[E0433]: failed to resolve: `super` in paths can only be used in start position
+  --> $DIR/absolute-paths-in-nested-use-groups.rs:7:5
+   |
+LL |     super::bar,
+   |     ^^^^^ `super` in paths can only be used in start position
+
+error[E0433]: failed to resolve: `self` in paths can only be used in start position
+  --> $DIR/absolute-paths-in-nested-use-groups.rs:8:5
+   |
+LL |     self::bar,
+   |     ^^^^ `self` in paths can only be used in start position
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/access-mode-in-closures.nll.stderr b/src/test/ui/access-mode-in-closures.nll.stderr
new file mode 100644
index 0000000..713eeba
--- /dev/null
+++ b/src/test/ui/access-mode-in-closures.nll.stderr
@@ -0,0 +1,18 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/access-mode-in-closures.rs:8:15
+   |
+LL |         match *s { S(v) => v }
+   |               ^^     - data moved here
+   |               |
+   |               cannot move out of borrowed content
+   |               help: consider removing the `*`: `s`
+   |
+note: move occurs because `v` has type `std::vec::Vec<isize>`, which does not implement the `Copy` trait
+  --> $DIR/access-mode-in-closures.rs:8:22
+   |
+LL |         match *s { S(v) => v }
+   |                      ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/access-mode-in-closures.rs b/src/test/ui/access-mode-in-closures.rs
new file mode 100644
index 0000000..9bd90e7
--- /dev/null
+++ b/src/test/ui/access-mode-in-closures.rs
@@ -0,0 +1,10 @@
+struct S(Vec<isize>);
+
+fn unpack<F>(_unpack: F) where F: FnOnce(&S) -> Vec<isize> {}
+
+fn main() {
+    let _foo = unpack(|s| {
+        // Test that `s` is moved here.
+        match *s { S(v) => v } //~ ERROR cannot move out
+    });
+}
diff --git a/src/test/ui/access-mode-in-closures.stderr b/src/test/ui/access-mode-in-closures.stderr
new file mode 100644
index 0000000..9976dfe
--- /dev/null
+++ b/src/test/ui/access-mode-in-closures.stderr
@@ -0,0 +1,11 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/access-mode-in-closures.rs:8:15
+   |
+LL |         match *s { S(v) => v }
+   |               ^^     - hint: to prevent move, use `ref v` or `ref mut v`
+   |               |
+   |               cannot move out of borrowed content
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/alloc-error/alloc-error-handler-bad-signature-1.rs b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-1.rs
new file mode 100644
index 0000000..36041e4
--- /dev/null
+++ b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-1.rs
@@ -0,0 +1,18 @@
+// compile-flags:-C panic=abort
+
+#![feature(alloc_error_handler, panic_handler)]
+#![no_std]
+#![no_main]
+
+use core::alloc::Layout;
+
+#[alloc_error_handler]
+fn oom(
+    info: &Layout, //~ ERROR argument should be `Layout`
+) -> () //~ ERROR return type should be `!`
+{
+    loop {}
+}
+
+#[panic_handler]
+fn panic(_: &core::panic::PanicInfo) -> ! { loop {} }
diff --git a/src/test/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr
new file mode 100644
index 0000000..34e09da
--- /dev/null
+++ b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr
@@ -0,0 +1,14 @@
+error: return type should be `!`
+  --> $DIR/alloc-error-handler-bad-signature-1.rs:12:6
+   |
+LL | ) -> ()
+   |      ^^
+
+error: argument should be `Layout`
+  --> $DIR/alloc-error-handler-bad-signature-1.rs:11:11
+   |
+LL |     info: &Layout,
+   |           ^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/alloc-error/alloc-error-handler-bad-signature-2.rs b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-2.rs
new file mode 100644
index 0000000..009f6bc
--- /dev/null
+++ b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-2.rs
@@ -0,0 +1,17 @@
+// compile-flags:-C panic=abort
+
+#![feature(alloc_error_handler, panic_handler)]
+#![no_std]
+#![no_main]
+
+struct Layout;
+
+#[alloc_error_handler]
+fn oom(
+    info: Layout, //~ ERROR argument should be `Layout`
+) { //~ ERROR return type should be `!`
+    loop {}
+}
+
+#[panic_handler]
+fn panic(_: &core::panic::PanicInfo) -> ! { loop {} }
diff --git a/src/test/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr
new file mode 100644
index 0000000..85544b0
--- /dev/null
+++ b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr
@@ -0,0 +1,14 @@
+error: return type should be `!`
+  --> $DIR/alloc-error-handler-bad-signature-2.rs:12:3
+   |
+LL | ) {
+   |   ^
+
+error: argument should be `Layout`
+  --> $DIR/alloc-error-handler-bad-signature-2.rs:11:11
+   |
+LL |     info: Layout,
+   |           ^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/alloc-error/alloc-error-handler-bad-signature-3.rs b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-3.rs
new file mode 100644
index 0000000..f2d884b
--- /dev/null
+++ b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-3.rs
@@ -0,0 +1,15 @@
+// compile-flags:-C panic=abort
+
+#![feature(alloc_error_handler, panic_handler)]
+#![no_std]
+#![no_main]
+
+struct Layout;
+
+#[alloc_error_handler]
+fn oom() -> ! { //~ ERROR function should have one argument
+    loop {}
+}
+
+#[panic_handler]
+fn panic(_: &core::panic::PanicInfo) -> ! { loop {} }
diff --git a/src/test/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr
new file mode 100644
index 0000000..8575e75
--- /dev/null
+++ b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr
@@ -0,0 +1,8 @@
+error: function should have one argument
+  --> $DIR/alloc-error-handler-bad-signature-3.rs:10:1
+   |
+LL | fn oom() -> ! {
+   | ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/allocator-submodule.rs b/src/test/ui/allocator-submodule.rs
new file mode 100644
index 0000000..a1cca50
--- /dev/null
+++ b/src/test/ui/allocator-submodule.rs
@@ -0,0 +1,30 @@
+// Tests that it is possible to create a global allocator in a submodule, rather than in the crate
+// root.
+
+#![feature(alloc, allocator_api, global_allocator)]
+
+extern crate alloc;
+
+use std::{
+    alloc::{GlobalAlloc, Layout},
+    ptr,
+};
+
+struct MyAlloc;
+
+unsafe impl GlobalAlloc for MyAlloc {
+    unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
+        ptr::null_mut()
+    }
+
+    unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {}
+}
+
+mod submod {
+    use super::MyAlloc;
+
+    #[global_allocator]
+    static MY_HEAP: MyAlloc = MyAlloc; //~ ERROR global_allocator
+}
+
+fn main() {}
diff --git a/src/test/ui/allocator-submodule.stderr b/src/test/ui/allocator-submodule.stderr
new file mode 100644
index 0000000..26d7aa8
--- /dev/null
+++ b/src/test/ui/allocator-submodule.stderr
@@ -0,0 +1,8 @@
+error: `global_allocator` cannot be used in submodules
+  --> $DIR/allocator-submodule.rs:27:5
+   |
+LL |     static MY_HEAP: MyAlloc = MyAlloc;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/allocator/auxiliary/system-allocator.rs b/src/test/ui/allocator/auxiliary/system-allocator.rs
new file mode 100644
index 0000000..97b86bb
--- /dev/null
+++ b/src/test/ui/allocator/auxiliary/system-allocator.rs
@@ -0,0 +1,8 @@
+// no-prefer-dynamic
+
+#![crate_type = "rlib"]
+
+use std::alloc::System;
+
+#[global_allocator]
+static A: System = System;
diff --git a/src/test/ui/allocator/auxiliary/system-allocator2.rs b/src/test/ui/allocator/auxiliary/system-allocator2.rs
new file mode 100644
index 0000000..97b86bb
--- /dev/null
+++ b/src/test/ui/allocator/auxiliary/system-allocator2.rs
@@ -0,0 +1,8 @@
+// no-prefer-dynamic
+
+#![crate_type = "rlib"]
+
+use std::alloc::System;
+
+#[global_allocator]
+static A: System = System;
diff --git a/src/test/ui/allocator/function-allocator.rs b/src/test/ui/allocator/function-allocator.rs
new file mode 100644
index 0000000..d53f6e9
--- /dev/null
+++ b/src/test/ui/allocator/function-allocator.rs
@@ -0,0 +1,4 @@
+#[global_allocator]
+fn foo() {} //~ ERROR: allocators must be statics
+
+fn main() {}
diff --git a/src/test/ui/allocator/function-allocator.stderr b/src/test/ui/allocator/function-allocator.stderr
new file mode 100644
index 0000000..5e47b0f
--- /dev/null
+++ b/src/test/ui/allocator/function-allocator.stderr
@@ -0,0 +1,8 @@
+error: allocators must be statics
+  --> $DIR/function-allocator.rs:2:1
+   |
+LL | fn foo() {}
+   | ^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/allocator/not-an-allocator.rs b/src/test/ui/allocator/not-an-allocator.rs
new file mode 100644
index 0000000..417c371
--- /dev/null
+++ b/src/test/ui/allocator/not-an-allocator.rs
@@ -0,0 +1,8 @@
+#[global_allocator]
+static A: usize = 0;
+//~^ the trait bound `usize:
+//~| the trait bound `usize:
+//~| the trait bound `usize:
+//~| the trait bound `usize:
+
+fn main() {}
diff --git a/src/test/ui/allocator/not-an-allocator.stderr b/src/test/ui/allocator/not-an-allocator.stderr
new file mode 100644
index 0000000..dd2cf36
--- /dev/null
+++ b/src/test/ui/allocator/not-an-allocator.stderr
@@ -0,0 +1,35 @@
+error[E0277]: the trait bound `usize: std::alloc::GlobalAlloc` is not satisfied
+  --> $DIR/not-an-allocator.rs:2:1
+   |
+LL | static A: usize = 0;
+   | ^^^^^^^^^^^^^^^^^^^^ the trait `std::alloc::GlobalAlloc` is not implemented for `usize`
+   |
+   = note: required by `std::alloc::GlobalAlloc::alloc`
+
+error[E0277]: the trait bound `usize: std::alloc::GlobalAlloc` is not satisfied
+  --> $DIR/not-an-allocator.rs:2:1
+   |
+LL | static A: usize = 0;
+   | ^^^^^^^^^^^^^^^^^^^^ the trait `std::alloc::GlobalAlloc` is not implemented for `usize`
+   |
+   = note: required by `std::alloc::GlobalAlloc::dealloc`
+
+error[E0277]: the trait bound `usize: std::alloc::GlobalAlloc` is not satisfied
+  --> $DIR/not-an-allocator.rs:2:1
+   |
+LL | static A: usize = 0;
+   | ^^^^^^^^^^^^^^^^^^^^ the trait `std::alloc::GlobalAlloc` is not implemented for `usize`
+   |
+   = note: required by `std::alloc::GlobalAlloc::realloc`
+
+error[E0277]: the trait bound `usize: std::alloc::GlobalAlloc` is not satisfied
+  --> $DIR/not-an-allocator.rs:2:1
+   |
+LL | static A: usize = 0;
+   | ^^^^^^^^^^^^^^^^^^^^ the trait `std::alloc::GlobalAlloc` is not implemented for `usize`
+   |
+   = note: required by `std::alloc::GlobalAlloc::alloc_zeroed`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/allocator/two-allocators.rs b/src/test/ui/allocator/two-allocators.rs
new file mode 100644
index 0000000..c967a45
--- /dev/null
+++ b/src/test/ui/allocator/two-allocators.rs
@@ -0,0 +1,10 @@
+use std::alloc::System;
+
+#[global_allocator]
+static A: System = System;
+#[global_allocator]
+static B: System = System;
+//~^ ERROR: cannot define more than one #[global_allocator]
+
+fn main() {}
+
diff --git a/src/test/ui/allocator/two-allocators.stderr b/src/test/ui/allocator/two-allocators.stderr
new file mode 100644
index 0000000..da247f6
--- /dev/null
+++ b/src/test/ui/allocator/two-allocators.stderr
@@ -0,0 +1,8 @@
+error: cannot define more than one #[global_allocator]
+  --> $DIR/two-allocators.rs:6:1
+   |
+LL | static B: System = System;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/allocator/two-allocators2.rs b/src/test/ui/allocator/two-allocators2.rs
new file mode 100644
index 0000000..b7a07cc
--- /dev/null
+++ b/src/test/ui/allocator/two-allocators2.rs
@@ -0,0 +1,13 @@
+// aux-build:system-allocator.rs
+// no-prefer-dynamic
+// error-pattern: the #[global_allocator] in
+
+extern crate system_allocator;
+
+use std::alloc::System;
+
+#[global_allocator]
+static A: System = System;
+
+fn main() {}
+
diff --git a/src/test/ui/allocator/two-allocators2.stderr b/src/test/ui/allocator/two-allocators2.stderr
new file mode 100644
index 0000000..2b23ce3
--- /dev/null
+++ b/src/test/ui/allocator/two-allocators2.stderr
@@ -0,0 +1,4 @@
+error: the #[global_allocator] in this crate conflicts with global allocator in: system_allocator
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/allocator/two-allocators3.rs b/src/test/ui/allocator/two-allocators3.rs
new file mode 100644
index 0000000..8a06335
--- /dev/null
+++ b/src/test/ui/allocator/two-allocators3.rs
@@ -0,0 +1,10 @@
+// aux-build:system-allocator.rs
+// aux-build:system-allocator2.rs
+// no-prefer-dynamic
+// error-pattern: the #[global_allocator] in
+
+
+extern crate system_allocator;
+extern crate system_allocator2;
+
+fn main() {}
diff --git a/src/test/ui/allocator/two-allocators3.stderr b/src/test/ui/allocator/two-allocators3.stderr
new file mode 100644
index 0000000..86e385a
--- /dev/null
+++ b/src/test/ui/allocator/two-allocators3.stderr
@@ -0,0 +1,4 @@
+error: the #[global_allocator] in system_allocator conflicts with this global allocator in: system_allocator2
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/always-inhabited-union-ref.rs b/src/test/ui/always-inhabited-union-ref.rs
new file mode 100644
index 0000000..11eae2a
--- /dev/null
+++ b/src/test/ui/always-inhabited-union-ref.rs
@@ -0,0 +1,32 @@
+// The precise semantics of inhabitedness with respect to unions and references is currently
+// undecided. This test file currently checks a conservative choice.
+
+#![feature(exhaustive_patterns)]
+#![feature(never_type)]
+
+#![allow(dead_code)]
+#![allow(unreachable_code)]
+
+pub union Foo {
+    foo: !,
+}
+
+fn uninhab_ref() -> &'static ! {
+    unimplemented!()
+}
+
+fn uninhab_union() -> Foo {
+    unimplemented!()
+}
+
+fn match_on_uninhab() {
+    match uninhab_ref() {
+        //~^ ERROR non-exhaustive patterns: type `&'static !` is non-empty
+    }
+
+    match uninhab_union() {
+        //~^ ERROR non-exhaustive patterns: type `Foo` is non-empty
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/always-inhabited-union-ref.stderr b/src/test/ui/always-inhabited-union-ref.stderr
new file mode 100644
index 0000000..792ab6f
--- /dev/null
+++ b/src/test/ui/always-inhabited-union-ref.stderr
@@ -0,0 +1,19 @@
+error[E0004]: non-exhaustive patterns: type `&'static !` is non-empty
+  --> $DIR/always-inhabited-union-ref.rs:23:11
+   |
+LL |     match uninhab_ref() {
+   |           ^^^^^^^^^^^^^
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: type `Foo` is non-empty
+  --> $DIR/always-inhabited-union-ref.rs:27:11
+   |
+LL |     match uninhab_union() {
+   |           ^^^^^^^^^^^^^^^
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/anon-params-denied-2018.rs b/src/test/ui/anon-params-denied-2018.rs
new file mode 100644
index 0000000..5e77aa8
--- /dev/null
+++ b/src/test/ui/anon-params-denied-2018.rs
@@ -0,0 +1,12 @@
+// Tests that anonymous parameters are a hard error in edition 2018.
+
+// edition:2018
+
+trait T {
+    fn foo(i32); //~ expected one of `:` or `@`, found `)`
+
+    fn bar_with_default_impl(String, String) {}
+    //~^ ERROR expected one of `:` or `@`, found `,`
+}
+
+fn main() {}
diff --git a/src/test/ui/anon-params-denied-2018.stderr b/src/test/ui/anon-params-denied-2018.stderr
new file mode 100644
index 0000000..1ec0cf3
--- /dev/null
+++ b/src/test/ui/anon-params-denied-2018.stderr
@@ -0,0 +1,22 @@
+error: expected one of `:` or `@`, found `)`
+  --> $DIR/anon-params-denied-2018.rs:6:15
+   |
+LL |     fn foo(i32);
+   |            ---^ expected one of `:` or `@` here
+   |            |
+   |            help: explicitly ignore parameter: `_: i32`
+   |
+   = note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
+
+error: expected one of `:` or `@`, found `,`
+  --> $DIR/anon-params-denied-2018.rs:8:36
+   |
+LL |     fn bar_with_default_impl(String, String) {}
+   |                              ------^ expected one of `:` or `@` here
+   |                              |
+   |                              help: explicitly ignore parameter: `_: String`
+   |
+   = note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/anon-params-deprecated.fixed b/src/test/ui/anon-params-deprecated.fixed
new file mode 100644
index 0000000..7eee47d
--- /dev/null
+++ b/src/test/ui/anon-params-deprecated.fixed
@@ -0,0 +1,19 @@
+#![warn(anonymous_parameters)]
+// Test for the anonymous_parameters deprecation lint (RFC 1685)
+
+// compile-pass
+// edition:2015
+// run-rustfix
+
+trait T {
+    fn foo(_: i32); //~ WARNING anonymous parameters are deprecated
+                 //~| WARNING hard error
+
+    fn bar_with_default_impl(_: String, _: String) {}
+    //~^ WARNING anonymous parameters are deprecated
+    //~| WARNING hard error
+    //~| WARNING anonymous parameters are deprecated
+    //~| WARNING hard error
+}
+
+fn main() {}
diff --git a/src/test/ui/anon-params-deprecated.rs b/src/test/ui/anon-params-deprecated.rs
new file mode 100644
index 0000000..74de0c0
--- /dev/null
+++ b/src/test/ui/anon-params-deprecated.rs
@@ -0,0 +1,19 @@
+#![warn(anonymous_parameters)]
+// Test for the anonymous_parameters deprecation lint (RFC 1685)
+
+// compile-pass
+// edition:2015
+// run-rustfix
+
+trait T {
+    fn foo(i32); //~ WARNING anonymous parameters are deprecated
+                 //~| WARNING hard error
+
+    fn bar_with_default_impl(String, String) {}
+    //~^ WARNING anonymous parameters are deprecated
+    //~| WARNING hard error
+    //~| WARNING anonymous parameters are deprecated
+    //~| WARNING hard error
+}
+
+fn main() {}
diff --git a/src/test/ui/anon-params-deprecated.stderr b/src/test/ui/anon-params-deprecated.stderr
new file mode 100644
index 0000000..e97dbc1
--- /dev/null
+++ b/src/test/ui/anon-params-deprecated.stderr
@@ -0,0 +1,32 @@
+warning: anonymous parameters are deprecated and will be removed in the next edition.
+  --> $DIR/anon-params-deprecated.rs:9:12
+   |
+LL |     fn foo(i32);
+   |            ^^^ help: Try naming the parameter or explicitly ignoring it: `_: i32`
+   |
+note: lint level defined here
+  --> $DIR/anon-params-deprecated.rs:1:9
+   |
+LL | #![warn(anonymous_parameters)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #41686 <https://github.com/rust-lang/rust/issues/41686>
+
+warning: anonymous parameters are deprecated and will be removed in the next edition.
+  --> $DIR/anon-params-deprecated.rs:12:30
+   |
+LL |     fn bar_with_default_impl(String, String) {}
+   |                              ^^^^^^ help: Try naming the parameter or explicitly ignoring it: `_: String`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #41686 <https://github.com/rust-lang/rust/issues/41686>
+
+warning: anonymous parameters are deprecated and will be removed in the next edition.
+  --> $DIR/anon-params-deprecated.rs:12:38
+   |
+LL |     fn bar_with_default_impl(String, String) {}
+   |                                      ^^^^^^ help: Try naming the parameter or explicitly ignoring it: `_: String`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #41686 <https://github.com/rust-lang/rust/issues/41686>
+
diff --git a/src/test/ui/anonymous-higher-ranked-lifetime.rs b/src/test/ui/anonymous-higher-ranked-lifetime.rs
new file mode 100644
index 0000000..2e2a124
--- /dev/null
+++ b/src/test/ui/anonymous-higher-ranked-lifetime.rs
@@ -0,0 +1,41 @@
+fn main() {
+    f1(|_: (), _: ()| {}); //~ ERROR type mismatch
+    //~^ ERROR type mismatch
+    f2(|_: (), _: ()| {}); //~ ERROR type mismatch
+    //~^ ERROR type mismatch
+    f3(|_: (), _: ()| {}); //~ ERROR type mismatch
+    //~^ ERROR type mismatch
+    f4(|_: (), _: ()| {}); //~ ERROR type mismatch
+    //~^ ERROR type mismatch
+    f5(|_: (), _: ()| {}); //~ ERROR type mismatch
+    //~^ ERROR type mismatch
+    g1(|_: (), _: ()| {}); //~ ERROR type mismatch
+    //~^ ERROR type mismatch
+    g2(|_: (), _: ()| {}); //~ ERROR type mismatch
+    //~^ ERROR type mismatch
+    g3(|_: (), _: ()| {}); //~ ERROR type mismatch
+    //~^ ERROR type mismatch
+    g4(|_: (), _: ()| {}); //~ ERROR type mismatch
+    //~^ ERROR type mismatch
+    h1(|_: (), _: (), _: (), _: ()| {}); //~ ERROR type mismatch
+    //~^ ERROR type mismatch
+    h2(|_: (), _: (), _: (), _: ()| {}); //~ ERROR type mismatch
+    //~^ ERROR type mismatch
+}
+
+// Basic
+fn f1<F>(_: F) where F: Fn(&(), &()) {}
+fn f2<F>(_: F) where F: for<'a> Fn(&'a (), &()) {}
+fn f3<'a, F>(_: F) where F: Fn(&'a (), &()) {}
+fn f4<F>(_: F) where F: for<'r> Fn(&(), &'r ()) {}
+fn f5<F>(_: F) where F: for<'r> Fn(&'r (), &'r ()) {}
+
+// Nested
+fn g1<F>(_: F) where F: Fn(&(), Box<Fn(&())>) {}
+fn g2<F>(_: F) where F: Fn(&(), fn(&())) {}
+fn g3<F>(_: F) where F: for<'s> Fn(&'s (), Box<Fn(&())>) {}
+fn g4<F>(_: F) where F: Fn(&(), for<'r> fn(&'r ())) {}
+
+// Mixed
+fn h1<F>(_: F) where F: Fn(&(), Box<Fn(&())>, &(), fn(&(), &())) {}
+fn h2<F>(_: F) where F: for<'t0> Fn(&(), Box<Fn(&())>, &'t0 (), fn(&(), &())) {}
diff --git a/src/test/ui/anonymous-higher-ranked-lifetime.stderr b/src/test/ui/anonymous-higher-ranked-lifetime.stderr
new file mode 100644
index 0000000..9e84b14
--- /dev/null
+++ b/src/test/ui/anonymous-higher-ranked-lifetime.stderr
@@ -0,0 +1,311 @@
+error[E0631]: type mismatch in closure arguments
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:2:5
+   |
+LL |     f1(|_: (), _: ()| {});
+   |     ^^ -------------- found signature of `fn((), ()) -> _`
+   |     |
+   |     expected signature of `for<'r, 's> fn(&'r (), &'s ()) -> _`
+   |
+note: required by `f1`
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:27:1
+   |
+LL | fn f1<F>(_: F) where F: Fn(&(), &()) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0631]: type mismatch in closure arguments
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:2:5
+   |
+LL |     f1(|_: (), _: ()| {});
+   |     ^^ -------------- found signature of `fn((), ()) -> _`
+   |     |
+   |     expected signature of `fn(&(), &()) -> _`
+   |
+note: required by `f1`
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:27:1
+   |
+LL | fn f1<F>(_: F) where F: Fn(&(), &()) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0631]: type mismatch in closure arguments
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:4:5
+   |
+LL |     f2(|_: (), _: ()| {});
+   |     ^^ -------------- found signature of `fn((), ()) -> _`
+   |     |
+   |     expected signature of `for<'a, 'r> fn(&'a (), &'r ()) -> _`
+   |
+note: required by `f2`
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:28:1
+   |
+LL | fn f2<F>(_: F) where F: for<'a> Fn(&'a (), &()) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0631]: type mismatch in closure arguments
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:4:5
+   |
+LL |     f2(|_: (), _: ()| {});
+   |     ^^ -------------- found signature of `fn((), ()) -> _`
+   |     |
+   |     expected signature of `fn(&'a (), &()) -> _`
+   |
+note: required by `f2`
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:28:1
+   |
+LL | fn f2<F>(_: F) where F: for<'a> Fn(&'a (), &()) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0631]: type mismatch in closure arguments
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:6:5
+   |
+LL |     f3(|_: (), _: ()| {});
+   |     ^^ -------------- found signature of `fn((), ()) -> _`
+   |     |
+   |     expected signature of `for<'r> fn(&(), &'r ()) -> _`
+   |
+note: required by `f3`
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:29:1
+   |
+LL | fn f3<'a, F>(_: F) where F: Fn(&'a (), &()) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0631]: type mismatch in closure arguments
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:6:5
+   |
+LL |     f3(|_: (), _: ()| {});
+   |     ^^ -------------- found signature of `fn((), ()) -> _`
+   |     |
+   |     expected signature of `fn(&(), &()) -> _`
+   |
+note: required by `f3`
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:29:1
+   |
+LL | fn f3<'a, F>(_: F) where F: Fn(&'a (), &()) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0631]: type mismatch in closure arguments
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:8:5
+   |
+LL |     f4(|_: (), _: ()| {});
+   |     ^^ -------------- found signature of `fn((), ()) -> _`
+   |     |
+   |     expected signature of `for<'s, 'r> fn(&'s (), &'r ()) -> _`
+   |
+note: required by `f4`
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:30:1
+   |
+LL | fn f4<F>(_: F) where F: for<'r> Fn(&(), &'r ()) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0631]: type mismatch in closure arguments
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:8:5
+   |
+LL |     f4(|_: (), _: ()| {});
+   |     ^^ -------------- found signature of `fn((), ()) -> _`
+   |     |
+   |     expected signature of `fn(&(), &'r ()) -> _`
+   |
+note: required by `f4`
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:30:1
+   |
+LL | fn f4<F>(_: F) where F: for<'r> Fn(&(), &'r ()) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0631]: type mismatch in closure arguments
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:10:5
+   |
+LL |     f5(|_: (), _: ()| {});
+   |     ^^ -------------- found signature of `fn((), ()) -> _`
+   |     |
+   |     expected signature of `for<'r> fn(&'r (), &'r ()) -> _`
+   |
+note: required by `f5`
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:31:1
+   |
+LL | fn f5<F>(_: F) where F: for<'r> Fn(&'r (), &'r ()) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0631]: type mismatch in closure arguments
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:10:5
+   |
+LL |     f5(|_: (), _: ()| {});
+   |     ^^ -------------- found signature of `fn((), ()) -> _`
+   |     |
+   |     expected signature of `fn(&'r (), &'r ()) -> _`
+   |
+note: required by `f5`
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:31:1
+   |
+LL | fn f5<F>(_: F) where F: for<'r> Fn(&'r (), &'r ()) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0631]: type mismatch in closure arguments
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:12:5
+   |
+LL |     g1(|_: (), _: ()| {});
+   |     ^^ -------------- found signature of `fn((), ()) -> _`
+   |     |
+   |     expected signature of `for<'r> fn(&'r (), std::boxed::Box<(dyn for<'s> std::ops::Fn(&'s ()) + 'static)>) -> _`
+   |
+note: required by `g1`
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:34:1
+   |
+LL | fn g1<F>(_: F) where F: Fn(&(), Box<Fn(&())>) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0631]: type mismatch in closure arguments
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:12:5
+   |
+LL |     g1(|_: (), _: ()| {});
+   |     ^^ -------------- found signature of `fn((), ()) -> _`
+   |     |
+   |     expected signature of `fn(&(), std::boxed::Box<(dyn for<'r> std::ops::Fn(&'r ()) + 'static)>) -> _`
+   |
+note: required by `g1`
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:34:1
+   |
+LL | fn g1<F>(_: F) where F: Fn(&(), Box<Fn(&())>) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0631]: type mismatch in closure arguments
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:14:5
+   |
+LL |     g2(|_: (), _: ()| {});
+   |     ^^ -------------- found signature of `fn((), ()) -> _`
+   |     |
+   |     expected signature of `for<'r> fn(&'r (), for<'s> fn(&'s ())) -> _`
+   |
+note: required by `g2`
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:35:1
+   |
+LL | fn g2<F>(_: F) where F: Fn(&(), fn(&())) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0631]: type mismatch in closure arguments
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:14:5
+   |
+LL |     g2(|_: (), _: ()| {});
+   |     ^^ -------------- found signature of `fn((), ()) -> _`
+   |     |
+   |     expected signature of `fn(&(), for<'r> fn(&'r ())) -> _`
+   |
+note: required by `g2`
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:35:1
+   |
+LL | fn g2<F>(_: F) where F: Fn(&(), fn(&())) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0631]: type mismatch in closure arguments
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:16:5
+   |
+LL |     g3(|_: (), _: ()| {});
+   |     ^^ -------------- found signature of `fn((), ()) -> _`
+   |     |
+   |     expected signature of `for<'s> fn(&'s (), std::boxed::Box<(dyn for<'r> std::ops::Fn(&'r ()) + 'static)>) -> _`
+   |
+note: required by `g3`
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:36:1
+   |
+LL | fn g3<F>(_: F) where F: for<'s> Fn(&'s (), Box<Fn(&())>) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0631]: type mismatch in closure arguments
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:16:5
+   |
+LL |     g3(|_: (), _: ()| {});
+   |     ^^ -------------- found signature of `fn((), ()) -> _`
+   |     |
+   |     expected signature of `fn(&'s (), std::boxed::Box<(dyn for<'r> std::ops::Fn(&'r ()) + 'static)>) -> _`
+   |
+note: required by `g3`
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:36:1
+   |
+LL | fn g3<F>(_: F) where F: for<'s> Fn(&'s (), Box<Fn(&())>) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0631]: type mismatch in closure arguments
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:18:5
+   |
+LL |     g4(|_: (), _: ()| {});
+   |     ^^ -------------- found signature of `fn((), ()) -> _`
+   |     |
+   |     expected signature of `for<'s> fn(&'s (), for<'r> fn(&'r ())) -> _`
+   |
+note: required by `g4`
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:37:1
+   |
+LL | fn g4<F>(_: F) where F: Fn(&(), for<'r> fn(&'r ())) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0631]: type mismatch in closure arguments
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:18:5
+   |
+LL |     g4(|_: (), _: ()| {});
+   |     ^^ -------------- found signature of `fn((), ()) -> _`
+   |     |
+   |     expected signature of `fn(&(), for<'r> fn(&'r ())) -> _`
+   |
+note: required by `g4`
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:37:1
+   |
+LL | fn g4<F>(_: F) where F: Fn(&(), for<'r> fn(&'r ())) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0631]: type mismatch in closure arguments
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:20:5
+   |
+LL |     h1(|_: (), _: (), _: (), _: ()| {});
+   |     ^^ ---------------------------- found signature of `fn((), (), (), ()) -> _`
+   |     |
+   |     expected signature of `for<'r, 's> fn(&'r (), std::boxed::Box<(dyn for<'t0> std::ops::Fn(&'t0 ()) + 'static)>, &'s (), for<'t0, 't1> fn(&'t0 (), &'t1 ())) -> _`
+   |
+note: required by `h1`
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:40:1
+   |
+LL | fn h1<F>(_: F) where F: Fn(&(), Box<Fn(&())>, &(), fn(&(), &())) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0631]: type mismatch in closure arguments
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:20:5
+   |
+LL |     h1(|_: (), _: (), _: (), _: ()| {});
+   |     ^^ ---------------------------- found signature of `fn((), (), (), ()) -> _`
+   |     |
+   |     expected signature of `fn(&(), std::boxed::Box<(dyn for<'r> std::ops::Fn(&'r ()) + 'static)>, &(), for<'r, 's> fn(&'r (), &'s ())) -> _`
+   |
+note: required by `h1`
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:40:1
+   |
+LL | fn h1<F>(_: F) where F: Fn(&(), Box<Fn(&())>, &(), fn(&(), &())) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0631]: type mismatch in closure arguments
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:22:5
+   |
+LL |     h2(|_: (), _: (), _: (), _: ()| {});
+   |     ^^ ---------------------------- found signature of `fn((), (), (), ()) -> _`
+   |     |
+   |     expected signature of `for<'r, 't0> fn(&'r (), std::boxed::Box<(dyn for<'s> std::ops::Fn(&'s ()) + 'static)>, &'t0 (), for<'s, 't1> fn(&'s (), &'t1 ())) -> _`
+   |
+note: required by `h2`
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:41:1
+   |
+LL | fn h2<F>(_: F) where F: for<'t0> Fn(&(), Box<Fn(&())>, &'t0 (), fn(&(), &())) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0631]: type mismatch in closure arguments
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:22:5
+   |
+LL |     h2(|_: (), _: (), _: (), _: ()| {});
+   |     ^^ ---------------------------- found signature of `fn((), (), (), ()) -> _`
+   |     |
+   |     expected signature of `fn(&(), std::boxed::Box<(dyn for<'r> std::ops::Fn(&'r ()) + 'static)>, &'t0 (), for<'r, 's> fn(&'r (), &'s ())) -> _`
+   |
+note: required by `h2`
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:41:1
+   |
+LL | fn h2<F>(_: F) where F: for<'t0> Fn(&(), Box<Fn(&())>, &'t0 (), fn(&(), &())) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 22 previous errors
+
+For more information about this error, try `rustc --explain E0631`.
diff --git a/src/test/ui/arbitrary-self-types-not-object-safe.rs b/src/test/ui/arbitrary-self-types-not-object-safe.rs
new file mode 100644
index 0000000..2c1fd93
--- /dev/null
+++ b/src/test/ui/arbitrary-self-types-not-object-safe.rs
@@ -0,0 +1,41 @@
+#![feature(arbitrary_self_types)]
+
+use std::rc::Rc;
+
+trait Foo {
+    fn foo(self: &Rc<Self>) -> usize;
+}
+
+trait Bar {
+    fn foo(self: &Rc<Self>) -> usize where Self: Sized;
+    fn bar(self: Rc<Self>) -> usize;
+}
+
+impl Foo for usize {
+    fn foo(self: &Rc<Self>) -> usize {
+        **self
+    }
+}
+
+impl Bar for usize {
+    fn foo(self: &Rc<Self>) -> usize {
+        **self
+    }
+
+    fn bar(self: Rc<Self>) -> usize {
+        *self
+    }
+}
+
+fn make_foo() {
+    let x = Rc::new(5usize) as Rc<Foo>;
+    //~^ ERROR E0038
+    //~| ERROR E0038
+}
+
+fn make_bar() {
+    let x = Rc::new(5usize) as Rc<Bar>;
+    x.bar();
+}
+
+fn main() {}
diff --git a/src/test/ui/arbitrary-self-types-not-object-safe.stderr b/src/test/ui/arbitrary-self-types-not-object-safe.stderr
new file mode 100644
index 0000000..dacab12
--- /dev/null
+++ b/src/test/ui/arbitrary-self-types-not-object-safe.stderr
@@ -0,0 +1,20 @@
+error[E0038]: the trait `Foo` cannot be made into an object
+  --> $DIR/arbitrary-self-types-not-object-safe.rs:31:32
+   |
+LL |     let x = Rc::new(5usize) as Rc<Foo>;
+   |                                ^^^^^^^ the trait `Foo` cannot be made into an object
+   |
+   = note: method `foo`'s receiver cannot be dispatched on
+
+error[E0038]: the trait `Foo` cannot be made into an object
+  --> $DIR/arbitrary-self-types-not-object-safe.rs:31:13
+   |
+LL |     let x = Rc::new(5usize) as Rc<Foo>;
+   |             ^^^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object
+   |
+   = note: method `foo`'s receiver cannot be dispatched on
+   = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<std::rc::Rc<dyn Foo>>` for `std::rc::Rc<usize>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/arg-count-mismatch.rs b/src/test/ui/arg-count-mismatch.rs
new file mode 100644
index 0000000..cf74870
--- /dev/null
+++ b/src/test/ui/arg-count-mismatch.rs
@@ -0,0 +1,5 @@
+// error-pattern: parameters were supplied
+
+fn f(x: isize) { }
+
+fn main() { let i: (); i = f(); }
diff --git a/src/test/ui/arg-count-mismatch.stderr b/src/test/ui/arg-count-mismatch.stderr
new file mode 100644
index 0000000..44f1604
--- /dev/null
+++ b/src/test/ui/arg-count-mismatch.stderr
@@ -0,0 +1,12 @@
+error[E0061]: this function takes 1 parameter but 0 parameters were supplied
+  --> $DIR/arg-count-mismatch.rs:5:28
+   |
+LL | fn f(x: isize) { }
+   | -------------- defined here
+LL | 
+LL | fn main() { let i: (); i = f(); }
+   |                            ^^^ expected 1 parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0061`.
diff --git a/src/test/ui/arg-type-mismatch.rs b/src/test/ui/arg-type-mismatch.rs
new file mode 100644
index 0000000..04ce288
--- /dev/null
+++ b/src/test/ui/arg-type-mismatch.rs
@@ -0,0 +1,5 @@
+// error-pattern: mismatched types
+
+fn f(x: isize) { }
+
+fn main() { let i: (); i = f(()); }
diff --git a/src/test/ui/arg-type-mismatch.stderr b/src/test/ui/arg-type-mismatch.stderr
new file mode 100644
index 0000000..d41abd1
--- /dev/null
+++ b/src/test/ui/arg-type-mismatch.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/arg-type-mismatch.rs:5:30
+   |
+LL | fn main() { let i: (); i = f(()); }
+   |                              ^^ expected isize, found ()
+   |
+   = note: expected type `isize`
+              found type `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/array-break-length.rs b/src/test/ui/array-break-length.rs
new file mode 100644
index 0000000..ab15ce6e
--- /dev/null
+++ b/src/test/ui/array-break-length.rs
@@ -0,0 +1,9 @@
+fn main() {
+    loop {
+        |_: [_; break]| {} //~ ERROR: `break` outside of loop
+    }
+
+    loop {
+        |_: [_; continue]| {} //~ ERROR: `continue` outside of loop
+    }
+}
diff --git a/src/test/ui/array-break-length.stderr b/src/test/ui/array-break-length.stderr
new file mode 100644
index 0000000..1cbf77a
--- /dev/null
+++ b/src/test/ui/array-break-length.stderr
@@ -0,0 +1,15 @@
+error[E0268]: `break` outside of loop
+  --> $DIR/array-break-length.rs:3:17
+   |
+LL |         |_: [_; break]| {}
+   |                 ^^^^^ cannot break outside of a loop
+
+error[E0268]: `continue` outside of loop
+  --> $DIR/array-break-length.rs:7:17
+   |
+LL |         |_: [_; continue]| {}
+   |                 ^^^^^^^^ cannot break outside of a loop
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0268`.
diff --git a/src/test/ui/array-not-vector.rs b/src/test/ui/array-not-vector.rs
new file mode 100644
index 0000000..80b40ef
--- /dev/null
+++ b/src/test/ui/array-not-vector.rs
@@ -0,0 +1,14 @@
+fn main() {
+    let _x: i32 = [1, 2, 3];
+    //~^ ERROR mismatched types
+    //~| expected type `i32`
+    //~| found type `[{integer}; 3]`
+    //~| expected i32, found array of 3 elements
+
+    let x: &[i32] = &[1, 2, 3];
+    let _y: &i32 = x;
+    //~^ ERROR mismatched types
+    //~| expected type `&i32`
+    //~| found type `&[i32]`
+    //~| expected i32, found slice
+}
diff --git a/src/test/ui/array-not-vector.stderr b/src/test/ui/array-not-vector.stderr
new file mode 100644
index 0000000..b5a5389
--- /dev/null
+++ b/src/test/ui/array-not-vector.stderr
@@ -0,0 +1,21 @@
+error[E0308]: mismatched types
+  --> $DIR/array-not-vector.rs:2:19
+   |
+LL |     let _x: i32 = [1, 2, 3];
+   |                   ^^^^^^^^^ expected i32, found array of 3 elements
+   |
+   = note: expected type `i32`
+              found type `[{integer}; 3]`
+
+error[E0308]: mismatched types
+  --> $DIR/array-not-vector.rs:9:20
+   |
+LL |     let _y: &i32 = x;
+   |                    ^ expected i32, found slice
+   |
+   = note: expected type `&i32`
+              found type `&[i32]`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/array_const_index-0.rs b/src/test/ui/array_const_index-0.rs
new file mode 100644
index 0000000..3422aea
--- /dev/null
+++ b/src/test/ui/array_const_index-0.rs
@@ -0,0 +1,8 @@
+const A: &'static [i32] = &[];
+const B: i32 = (&A)[1];
+//~^ index out of bounds: the len is 0 but the index is 1
+//~| ERROR any use of this value will cause an error
+
+fn main() {
+    let _ = B;
+}
diff --git a/src/test/ui/array_const_index-0.stderr b/src/test/ui/array_const_index-0.stderr
new file mode 100644
index 0000000..78d456d
--- /dev/null
+++ b/src/test/ui/array_const_index-0.stderr
@@ -0,0 +1,12 @@
+error: any use of this value will cause an error
+  --> $DIR/array_const_index-0.rs:2:16
+   |
+LL | const B: i32 = (&A)[1];
+   | ---------------^^^^^^^-
+   |                |
+   |                index out of bounds: the len is 0 but the index is 1
+   |
+   = note: #[deny(const_err)] on by default
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/array_const_index-1.rs b/src/test/ui/array_const_index-1.rs
new file mode 100644
index 0000000..1f77cb6
--- /dev/null
+++ b/src/test/ui/array_const_index-1.rs
@@ -0,0 +1,8 @@
+const A: [i32; 0] = [];
+const B: i32 = A[1];
+//~^ index out of bounds: the len is 0 but the index is 1
+//~| ERROR any use of this value will cause an error
+
+fn main() {
+    let _ = B;
+}
diff --git a/src/test/ui/array_const_index-1.stderr b/src/test/ui/array_const_index-1.stderr
new file mode 100644
index 0000000..3e7360f
--- /dev/null
+++ b/src/test/ui/array_const_index-1.stderr
@@ -0,0 +1,12 @@
+error: any use of this value will cause an error
+  --> $DIR/array_const_index-1.rs:2:16
+   |
+LL | const B: i32 = A[1];
+   | ---------------^^^^-
+   |                |
+   |                index out of bounds: the len is 0 but the index is 1
+   |
+   = note: #[deny(const_err)] on by default
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/asm/asm-bad-clobber.rs b/src/test/ui/asm/asm-bad-clobber.rs
new file mode 100644
index 0000000..8406a1c
--- /dev/null
+++ b/src/test/ui/asm/asm-bad-clobber.rs
@@ -0,0 +1,25 @@
+// ignore-android
+// ignore-arm
+// ignore-aarch64
+// ignore-s390x
+// ignore-emscripten
+// ignore-powerpc
+// ignore-powerpc64
+// ignore-powerpc64le
+// ignore-sparc
+// ignore-sparc64
+// ignore-mips
+// ignore-mips64
+
+#![feature(asm)]
+
+#[cfg(any(target_arch = "x86",
+          target_arch = "x86_64"))]
+
+pub fn main() {
+    unsafe {
+        // clobber formatted as register input/output
+        asm!("xor %eax, %eax" : : : "{eax}");
+        //~^ ERROR clobber should not be surrounded by braces
+    }
+}
diff --git a/src/test/ui/asm/asm-bad-clobber.stderr b/src/test/ui/asm/asm-bad-clobber.stderr
new file mode 100644
index 0000000..a279421
--- /dev/null
+++ b/src/test/ui/asm/asm-bad-clobber.stderr
@@ -0,0 +1,9 @@
+error[E0664]: clobber should not be surrounded by braces
+  --> $DIR/asm-bad-clobber.rs:22:37
+   |
+LL |         asm!("xor %eax, %eax" : : : "{eax}");
+   |                                     ^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0664`.
diff --git a/src/test/ui/asm/asm-in-bad-modifier.rs b/src/test/ui/asm/asm-in-bad-modifier.rs
new file mode 100644
index 0000000..38cd11e
--- /dev/null
+++ b/src/test/ui/asm/asm-in-bad-modifier.rs
@@ -0,0 +1,34 @@
+// ignore-s390x
+// ignore-emscripten
+// ignore-powerpc
+// ignore-powerpc64
+// ignore-powerpc64le
+// ignore-sparc
+// ignore-sparc64
+// ignore-mips
+// ignore-mips64
+
+#![feature(asm)]
+
+fn foo(x: isize) { println!("{}", x); }
+
+#[cfg(any(target_arch = "x86",
+          target_arch = "x86_64",
+          target_arch = "arm",
+          target_arch = "aarch64"))]
+pub fn main() {
+    let x: isize;
+    let y: isize;
+    unsafe {
+        asm!("mov $1, $0" : "=r"(x) : "=r"(5)); //~ ERROR operand constraint contains '='
+        asm!("mov $1, $0" : "=r"(y) : "+r"(5)); //~ ERROR operand constraint contains '+'
+    }
+    foo(x);
+    foo(y);
+}
+
+#[cfg(not(any(target_arch = "x86",
+              target_arch = "x86_64",
+              target_arch = "arm",
+              target_arch = "aarch64")))]
+pub fn main() {}
diff --git a/src/test/ui/asm/asm-in-bad-modifier.stderr b/src/test/ui/asm/asm-in-bad-modifier.stderr
new file mode 100644
index 0000000..21e80fb
--- /dev/null
+++ b/src/test/ui/asm/asm-in-bad-modifier.stderr
@@ -0,0 +1,16 @@
+error[E0662]: input operand constraint contains '='
+  --> $DIR/asm-in-bad-modifier.rs:23:39
+   |
+LL |         asm!("mov $1, $0" : "=r"(x) : "=r"(5));
+   |                                       ^^^^
+
+error[E0663]: input operand constraint contains '+'
+  --> $DIR/asm-in-bad-modifier.rs:24:39
+   |
+LL |         asm!("mov $1, $0" : "=r"(y) : "+r"(5));
+   |                                       ^^^^
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0662, E0663.
+For more information about an error, try `rustc --explain E0662`.
diff --git a/src/test/ui/asm/asm-misplaced-option.rs b/src/test/ui/asm/asm-misplaced-option.rs
new file mode 100644
index 0000000..5c202a1
--- /dev/null
+++ b/src/test/ui/asm/asm-misplaced-option.rs
@@ -0,0 +1,37 @@
+// ignore-android
+// ignore-arm
+// ignore-aarch64
+// ignore-s390x
+// ignore-emscripten
+// ignore-powerpc
+// ignore-powerpc64
+// ignore-powerpc64le
+// ignore-sparc
+// ignore-sparc64
+// ignore-mips
+// ignore-mips64
+
+// compile-pass
+// skip-codegen
+#![feature(asm)]
+#![allow(dead_code, non_upper_case_globals)]
+
+#[cfg(any(target_arch = "x86",
+          target_arch = "x86_64"))]
+pub fn main() {
+    // assignment not dead
+    let mut x: isize = 0;
+    unsafe {
+        // extra colon
+        asm!("mov $1, $0" : "=r"(x) : "r"(5_usize), "0"(x) : : "cc");
+        //~^ WARNING unrecognized option
+    }
+    assert_eq!(x, 5);
+
+    unsafe {
+        // comma in place of a colon
+        asm!("add $2, $1; mov $1, $0" : "=r"(x) : "r"(x), "r"(8_usize) : "cc", "volatile");
+        //~^ WARNING expected a clobber, found an option
+    }
+    assert_eq!(x, 13);
+}
diff --git a/src/test/ui/asm/asm-misplaced-option.stderr b/src/test/ui/asm/asm-misplaced-option.stderr
new file mode 100644
index 0000000..39d88e3
--- /dev/null
+++ b/src/test/ui/asm/asm-misplaced-option.stderr
@@ -0,0 +1,12 @@
+warning: unrecognized option
+  --> $DIR/asm-misplaced-option.rs:26:64
+   |
+LL |         asm!("mov $1, $0" : "=r"(x) : "r"(5_usize), "0"(x) : : "cc");
+   |                                                                ^^^^
+
+warning: expected a clobber, found an option
+  --> $DIR/asm-misplaced-option.rs:33:80
+   |
+LL |         asm!("add $2, $1; mov $1, $0" : "=r"(x) : "r"(x), "r"(8_usize) : "cc", "volatile");
+   |                                                                                ^^^^^^^^^^
+
diff --git a/src/test/ui/asm/asm-out-assign-imm.nll.stderr b/src/test/ui/asm/asm-out-assign-imm.nll.stderr
new file mode 100644
index 0000000..ac38218
--- /dev/null
+++ b/src/test/ui/asm/asm-out-assign-imm.nll.stderr
@@ -0,0 +1,14 @@
+error[E0384]: cannot assign twice to immutable variable `x`
+  --> $DIR/asm-out-assign-imm.rs:24:34
+   |
+LL |     let x: isize;
+   |         - help: make this binding mutable: `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`.
diff --git a/src/test/ui/asm/asm-out-assign-imm.rs b/src/test/ui/asm/asm-out-assign-imm.rs
new file mode 100644
index 0000000..7a8be2a
--- /dev/null
+++ b/src/test/ui/asm/asm-out-assign-imm.rs
@@ -0,0 +1,34 @@
+// ignore-s390x
+// ignore-emscripten
+// ignore-powerpc
+// ignore-powerpc64
+// ignore-powerpc64le
+// ignore-sparc
+// ignore-sparc64
+// ignore-mips
+// ignore-mips64
+
+#![feature(asm)]
+
+fn foo(x: isize) { println!("{}", x); }
+
+#[cfg(any(target_arch = "x86",
+          target_arch = "x86_64",
+          target_arch = "arm",
+          target_arch = "aarch64"))]
+pub fn main() {
+    let x: isize;
+    x = 1;
+    foo(x);
+    unsafe {
+        asm!("mov $1, $0" : "=r"(x) : "r"(5));
+        //~^ ERROR cannot assign twice to immutable variable `x`
+    }
+    foo(x);
+}
+
+#[cfg(not(any(target_arch = "x86",
+              target_arch = "x86_64",
+              target_arch = "arm",
+              target_arch = "aarch64")))]
+pub fn main() {}
diff --git a/src/test/ui/asm/asm-out-assign-imm.stderr b/src/test/ui/asm/asm-out-assign-imm.stderr
new file mode 100644
index 0000000..98f2f68
--- /dev/null
+++ b/src/test/ui/asm/asm-out-assign-imm.stderr
@@ -0,0 +1,12 @@
+error[E0384]: cannot assign twice to immutable variable `x`
+  --> $DIR/asm-out-assign-imm.rs:24:34
+   |
+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`.
diff --git a/src/test/ui/asm/asm-out-no-modifier.rs b/src/test/ui/asm/asm-out-no-modifier.rs
new file mode 100644
index 0000000..d9142b9
--- /dev/null
+++ b/src/test/ui/asm/asm-out-no-modifier.rs
@@ -0,0 +1,31 @@
+// ignore-s390x
+// ignore-emscripten
+// ignore-powerpc
+// ignore-powerpc64
+// ignore-powerpc64le
+// ignore-sparc
+// ignore-sparc64
+// ignore-mips
+// ignore-mips64
+
+#![feature(asm)]
+
+fn foo(x: isize) { println!("{}", x); }
+
+#[cfg(any(target_arch = "x86",
+          target_arch = "x86_64",
+          target_arch = "arm",
+          target_arch = "aarch64"))]
+pub fn main() {
+    let x: isize;
+    unsafe {
+        asm!("mov $1, $0" : "r"(x) : "r"(5)); //~ ERROR output operand constraint lacks '='
+    }
+    foo(x);
+}
+
+#[cfg(not(any(target_arch = "x86",
+              target_arch = "x86_64",
+              target_arch = "arm",
+              target_arch = "aarch64")))]
+pub fn main() {}
diff --git a/src/test/ui/asm/asm-out-no-modifier.stderr b/src/test/ui/asm/asm-out-no-modifier.stderr
new file mode 100644
index 0000000..99134ce
--- /dev/null
+++ b/src/test/ui/asm/asm-out-no-modifier.stderr
@@ -0,0 +1,9 @@
+error[E0661]: output operand constraint lacks '=' or '+'
+  --> $DIR/asm-out-no-modifier.rs:22:29
+   |
+LL |         asm!("mov $1, $0" : "r"(x) : "r"(5));
+   |                             ^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0661`.
diff --git a/src/test/ui/asm/asm-out-read-uninit.ast.stderr b/src/test/ui/asm/asm-out-read-uninit.ast.stderr
new file mode 100644
index 0000000..cf74298
--- /dev/null
+++ b/src/test/ui/asm/asm-out-read-uninit.ast.stderr
@@ -0,0 +1,9 @@
+error[E0381]: use of possibly uninitialized variable: `x`
+  --> $DIR/asm-out-read-uninit.rs:25:43
+   |
+LL |         asm!("mov $1, $0" : "=r"(x) : "r"(x));
+   |                                           ^ use of possibly uninitialized `x`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/asm/asm-out-read-uninit.mir.stderr b/src/test/ui/asm/asm-out-read-uninit.mir.stderr
new file mode 100644
index 0000000..cf74298
--- /dev/null
+++ b/src/test/ui/asm/asm-out-read-uninit.mir.stderr
@@ -0,0 +1,9 @@
+error[E0381]: use of possibly uninitialized variable: `x`
+  --> $DIR/asm-out-read-uninit.rs:25:43
+   |
+LL |         asm!("mov $1, $0" : "=r"(x) : "r"(x));
+   |                                           ^ use of possibly uninitialized `x`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/asm/asm-out-read-uninit.rs b/src/test/ui/asm/asm-out-read-uninit.rs
new file mode 100644
index 0000000..44dd050
--- /dev/null
+++ b/src/test/ui/asm/asm-out-read-uninit.rs
@@ -0,0 +1,36 @@
+// ignore-s390x
+// ignore-emscripten
+// ignore-powerpc
+// ignore-powerpc64
+// ignore-powerpc64le
+// ignore-sparc
+// ignore-sparc64
+// ignore-mips
+// ignore-mips64
+
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+#![feature(asm)]
+
+fn foo(x: isize) { println!("{}", x); }
+
+#[cfg(any(target_arch = "x86",
+          target_arch = "x86_64",
+          target_arch = "arm",
+          target_arch = "aarch64"))]
+pub fn main() {
+    let x: isize;
+    unsafe {
+        asm!("mov $1, $0" : "=r"(x) : "r"(x));
+        //[ast]~^ ERROR use of possibly uninitialized variable: `x`
+        //[mir]~^^ ERROR use of possibly uninitialized variable: `x`
+    }
+    foo(x);
+}
+
+#[cfg(not(any(target_arch = "x86",
+              target_arch = "x86_64",
+              target_arch = "arm",
+              target_arch = "aarch64")))]
+pub fn main() {}
diff --git a/src/test/ui/asm/asm-parse-errors.rs b/src/test/ui/asm/asm-parse-errors.rs
new file mode 100644
index 0000000..e712ac5
--- /dev/null
+++ b/src/test/ui/asm/asm-parse-errors.rs
@@ -0,0 +1,15 @@
+#![feature(asm)]
+
+fn main() {
+    asm!(); //~ ERROR requires a string literal as an argument
+    asm!("nop" : struct); //~ ERROR expected string literal
+    asm!("mov %eax, $$0x2" : struct); //~ ERROR expected string literal
+    asm!("mov %eax, $$0x2" : "={eax}" struct); //~ ERROR expected `(`
+    asm!("mov %eax, $$0x2" : "={eax}"(struct)); //~ ERROR expected expression
+    asm!("in %dx, %al" : "={al}"(result) : struct); //~ ERROR expected string literal
+    asm!("in %dx, %al" : "={al}"(result) : "{dx}" struct); //~ ERROR expected `(`
+    asm!("in %dx, %al" : "={al}"(result) : "{dx}"(struct)); //~ ERROR expected expression
+    asm!("mov $$0x200, %eax" : : : struct); //~ ERROR expected string literal
+    asm!("mov eax, 2" : "={eax}"(foo) : : : struct); //~ ERROR expected string literal
+    asm!(123); //~ ERROR inline assembly must be a string literal
+}
diff --git a/src/test/ui/asm/asm-parse-errors.stderr b/src/test/ui/asm/asm-parse-errors.stderr
new file mode 100644
index 0000000..9fe59d1
--- /dev/null
+++ b/src/test/ui/asm/asm-parse-errors.stderr
@@ -0,0 +1,68 @@
+error: macro requires a string literal as an argument
+  --> $DIR/asm-parse-errors.rs:4:5
+   |
+LL |     asm!();
+   |     ^^^^^^^ string literal required
+
+error: expected string literal
+  --> $DIR/asm-parse-errors.rs:5:18
+   |
+LL |     asm!("nop" : struct);
+   |                  ^^^^^^ expected string literal
+
+error: expected string literal
+  --> $DIR/asm-parse-errors.rs:6:30
+   |
+LL |     asm!("mov %eax, $$0x2" : struct);
+   |                              ^^^^^^ expected string literal
+
+error: expected `(`, found keyword `struct`
+  --> $DIR/asm-parse-errors.rs:7:39
+   |
+LL |     asm!("mov %eax, $$0x2" : "={eax}" struct);
+   |                                       ^^^^^^ expected `(`
+
+error: expected expression, found keyword `struct`
+  --> $DIR/asm-parse-errors.rs:8:39
+   |
+LL |     asm!("mov %eax, $$0x2" : "={eax}"(struct));
+   |                                       ^^^^^^ expected expression
+
+error: expected string literal
+  --> $DIR/asm-parse-errors.rs:9:44
+   |
+LL |     asm!("in %dx, %al" : "={al}"(result) : struct);
+   |                                            ^^^^^^ expected string literal
+
+error: expected `(`, found keyword `struct`
+  --> $DIR/asm-parse-errors.rs:10:51
+   |
+LL |     asm!("in %dx, %al" : "={al}"(result) : "{dx}" struct);
+   |                                                   ^^^^^^ expected `(`
+
+error: expected expression, found keyword `struct`
+  --> $DIR/asm-parse-errors.rs:11:51
+   |
+LL |     asm!("in %dx, %al" : "={al}"(result) : "{dx}"(struct));
+   |                                                   ^^^^^^ expected expression
+
+error: expected string literal
+  --> $DIR/asm-parse-errors.rs:12:36
+   |
+LL |     asm!("mov $$0x200, %eax" : : : struct);
+   |                                    ^^^^^^ expected string literal
+
+error: expected string literal
+  --> $DIR/asm-parse-errors.rs:13:45
+   |
+LL |     asm!("mov eax, 2" : "={eax}"(foo) : : : struct);
+   |                                             ^^^^^^ expected string literal
+
+error: inline assembly must be a string literal
+  --> $DIR/asm-parse-errors.rs:14:10
+   |
+LL |     asm!(123);
+   |          ^^^
+
+error: aborting due to 11 previous errors
+
diff --git a/src/test/ui/assign-imm-local-twice.ast.nll.stderr b/src/test/ui/assign-imm-local-twice.ast.nll.stderr
new file mode 100644
index 0000000..2995a13
--- /dev/null
+++ b/src/test/ui/assign-imm-local-twice.ast.nll.stderr
@@ -0,0 +1,15 @@
+error[E0384]: cannot assign twice to immutable variable `v`
+  --> $DIR/assign-imm-local-twice.rs:11:5
+   |
+LL |     let v: isize;
+   |         - help: make this binding mutable: `mut v`
+...
+LL |     v = 1;
+   |     ----- first assignment to `v`
+...
+LL |     v = 2;
+   |     ^^^^^ cannot assign twice to immutable variable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0384`.
diff --git a/src/test/ui/assign-imm-local-twice.ast.stderr b/src/test/ui/assign-imm-local-twice.ast.stderr
new file mode 100644
index 0000000..f16b8e2
--- /dev/null
+++ b/src/test/ui/assign-imm-local-twice.ast.stderr
@@ -0,0 +1,12 @@
+error[E0384]: cannot assign twice to immutable variable `v`
+  --> $DIR/assign-imm-local-twice.rs:11:5
+   |
+LL |     v = 1;
+   |     ----- first assignment to `v`
+...
+LL |     v = 2;
+   |     ^^^^^ cannot assign twice to immutable variable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0384`.
diff --git a/src/test/ui/assign-imm-local-twice.mir.stderr b/src/test/ui/assign-imm-local-twice.mir.stderr
new file mode 100644
index 0000000..2995a13
--- /dev/null
+++ b/src/test/ui/assign-imm-local-twice.mir.stderr
@@ -0,0 +1,15 @@
+error[E0384]: cannot assign twice to immutable variable `v`
+  --> $DIR/assign-imm-local-twice.rs:11:5
+   |
+LL |     let v: isize;
+   |         - help: make this binding mutable: `mut v`
+...
+LL |     v = 1;
+   |     ----- first assignment to `v`
+...
+LL |     v = 2;
+   |     ^^^^^ cannot assign twice to immutable variable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0384`.
diff --git a/src/test/ui/assign-imm-local-twice.rs b/src/test/ui/assign-imm-local-twice.rs
new file mode 100644
index 0000000..de966a1
--- /dev/null
+++ b/src/test/ui/assign-imm-local-twice.rs
@@ -0,0 +1,19 @@
+// revisions: ast mir
+//[mir]compile-flags: -Zborrowck=mir
+
+fn test() {
+    let v: isize;
+    //[mir]~^ HELP make this binding mutable
+    //[mir]~| SUGGESTION mut v
+    v = 1; //[ast]~ NOTE first assignment
+           //[mir]~^ NOTE first assignment
+    println!("v={}", v);
+    v = 2; //[ast]~ ERROR cannot assign twice to immutable variable
+           //[mir]~^ ERROR cannot assign twice to immutable variable `v`
+           //[ast]~| NOTE cannot assign twice to immutable
+           //[mir]~| NOTE cannot assign twice to immutable
+    println!("v={}", v);
+}
+
+fn main() {
+}
diff --git a/src/test/ui/assign-to-method.rs b/src/test/ui/assign-to-method.rs
new file mode 100644
index 0000000..95f066c
--- /dev/null
+++ b/src/test/ui/assign-to-method.rs
@@ -0,0 +1,22 @@
+struct Cat {
+  meows : usize,
+
+  how_hungry : isize,
+}
+
+impl Cat {
+    pub fn speak(&self) { self.meows += 1; }
+}
+
+fn cat(in_x : usize, in_y : isize) -> Cat {
+    Cat {
+        meows: in_x,
+        how_hungry: in_y
+    }
+}
+
+fn main() {
+  let nyan : Cat = cat(52, 99);
+  nyan.speak = || println!("meow"); //~ ERROR attempted to take value of method
+  nyan.speak += || println!("meow"); //~ ERROR attempted to take value of method
+}
diff --git a/src/test/ui/assign-to-method.stderr b/src/test/ui/assign-to-method.stderr
new file mode 100644
index 0000000..feceadb
--- /dev/null
+++ b/src/test/ui/assign-to-method.stderr
@@ -0,0 +1,19 @@
+error[E0615]: attempted to take value of method `speak` on type `Cat`
+  --> $DIR/assign-to-method.rs:20:8
+   |
+LL |   nyan.speak = || println!("meow");
+   |        ^^^^^
+   |
+   = help: methods are immutable and cannot be assigned to
+
+error[E0615]: attempted to take value of method `speak` on type `Cat`
+  --> $DIR/assign-to-method.rs:21:8
+   |
+LL |   nyan.speak += || println!("meow");
+   |        ^^^^^
+   |
+   = help: methods are immutable and cannot be assigned to
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0615`.
diff --git a/src/test/ui/assignment-operator-unimplemented.rs b/src/test/ui/assignment-operator-unimplemented.rs
new file mode 100644
index 0000000..21df464
--- /dev/null
+++ b/src/test/ui/assignment-operator-unimplemented.rs
@@ -0,0 +1,7 @@
+struct Foo;
+
+fn main() {
+  let mut a = Foo;
+  let ref b = Foo;
+  a += *b; //~ Error: binary assignment operation `+=` cannot be applied to type `Foo`
+}
diff --git a/src/test/ui/assignment-operator-unimplemented.stderr b/src/test/ui/assignment-operator-unimplemented.stderr
new file mode 100644
index 0000000..5304b09
--- /dev/null
+++ b/src/test/ui/assignment-operator-unimplemented.stderr
@@ -0,0 +1,13 @@
+error[E0368]: binary assignment operation `+=` cannot be applied to type `Foo`
+  --> $DIR/assignment-operator-unimplemented.rs:6:3
+   |
+LL |   a += *b;
+   |   -^^^^^^
+   |   |
+   |   cannot use `+=` on type `Foo`
+   |
+   = note: an implementation of `std::ops::AddAssign` might be missing for `Foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0368`.
diff --git a/src/test/ui/assoc-inherent.rs b/src/test/ui/assoc-inherent.rs
new file mode 100644
index 0000000..05329a2
--- /dev/null
+++ b/src/test/ui/assoc-inherent.rs
@@ -0,0 +1,9 @@
+// Test associated types are, until #8995 is implemented, forbidden in inherent impls.
+
+struct Foo;
+
+impl Foo {
+    type Bar = isize; //~ERROR associated types are not yet supported in inherent impls (see #8995)
+}
+
+fn main() {}
diff --git a/src/test/ui/assoc-inherent.stderr b/src/test/ui/assoc-inherent.stderr
new file mode 100644
index 0000000..f9ea336
--- /dev/null
+++ b/src/test/ui/assoc-inherent.stderr
@@ -0,0 +1,9 @@
+error[E0202]: associated types are not yet supported in inherent impls (see #8995)
+  --> $DIR/assoc-inherent.rs:6:5
+   |
+LL |     type Bar = isize;
+   |     ^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0202`.
diff --git a/src/test/ui/associated-const/associated-const-ambiguity-report.rs b/src/test/ui/associated-const/associated-const-ambiguity-report.rs
new file mode 100644
index 0000000..927d2c6
--- /dev/null
+++ b/src/test/ui/associated-const/associated-const-ambiguity-report.rs
@@ -0,0 +1,21 @@
+trait Foo {
+    const ID: i32;
+}
+
+trait Bar {
+    const ID: i32;
+}
+
+impl Foo for i32 {
+    const ID: i32 = 1;
+}
+
+impl Bar for i32 {
+    const ID: i32 = 3;
+}
+
+const X: i32 = <i32>::ID; //~ ERROR E0034
+
+fn main() {
+    assert_eq!(1, X);
+}
diff --git a/src/test/ui/associated-const/associated-const-ambiguity-report.stderr b/src/test/ui/associated-const/associated-const-ambiguity-report.stderr
new file mode 100644
index 0000000..5f2b9c4
--- /dev/null
+++ b/src/test/ui/associated-const/associated-const-ambiguity-report.stderr
@@ -0,0 +1,20 @@
+error[E0034]: multiple applicable items in scope
+  --> $DIR/associated-const-ambiguity-report.rs:17:16
+   |
+LL | const X: i32 = <i32>::ID;
+   |                ^^^^^^^^^ multiple `ID` found
+   |
+note: candidate #1 is defined in an impl of the trait `Foo` for the type `i32`
+  --> $DIR/associated-const-ambiguity-report.rs:10:5
+   |
+LL |     const ID: i32 = 1;
+   |     ^^^^^^^^^^^^^^^^^^
+note: candidate #2 is defined in an impl of the trait `Bar` for the type `i32`
+  --> $DIR/associated-const-ambiguity-report.rs:14:5
+   |
+LL |     const ID: i32 = 3;
+   |     ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0034`.
diff --git a/src/test/ui/associated-const/associated-const-array-len.rs b/src/test/ui/associated-const/associated-const-array-len.rs
new file mode 100644
index 0000000..17d7824
--- /dev/null
+++ b/src/test/ui/associated-const/associated-const-array-len.rs
@@ -0,0 +1,10 @@
+trait Foo {
+    const ID: usize;
+}
+
+const X: [i32; <i32 as Foo>::ID] = [0, 1, 2];
+//~^ ERROR the trait bound `i32: Foo` is not satisfied
+
+fn main() {
+    assert_eq!(1, X);
+}
diff --git a/src/test/ui/associated-const/associated-const-array-len.stderr b/src/test/ui/associated-const/associated-const-array-len.stderr
new file mode 100644
index 0000000..ff56d11
--- /dev/null
+++ b/src/test/ui/associated-const/associated-const-array-len.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `i32: Foo` is not satisfied
+  --> $DIR/associated-const-array-len.rs:5:16
+   |
+LL | const X: [i32; <i32 as Foo>::ID] = [0, 1, 2];
+   |                ^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `i32`
+   |
+note: required by `Foo::ID`
+  --> $DIR/associated-const-array-len.rs:2:5
+   |
+LL |     const ID: usize;
+   |     ^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/associated-const/associated-const-dead-code.rs b/src/test/ui/associated-const/associated-const-dead-code.rs
new file mode 100644
index 0000000..c47e474
--- /dev/null
+++ b/src/test/ui/associated-const/associated-const-dead-code.rs
@@ -0,0 +1,12 @@
+#![deny(dead_code)]
+
+struct MyFoo;
+
+impl MyFoo {
+    const BAR: u32 = 1;
+    //~^ ERROR associated const is never used: `BAR`
+}
+
+fn main() {
+    let _: MyFoo = MyFoo;
+}
diff --git a/src/test/ui/associated-const/associated-const-dead-code.stderr b/src/test/ui/associated-const/associated-const-dead-code.stderr
new file mode 100644
index 0000000..8c6d76b
--- /dev/null
+++ b/src/test/ui/associated-const/associated-const-dead-code.stderr
@@ -0,0 +1,14 @@
+error: associated const is never used: `BAR`
+  --> $DIR/associated-const-dead-code.rs:6:5
+   |
+LL |     const BAR: u32 = 1;
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/associated-const-dead-code.rs:1:9
+   |
+LL | #![deny(dead_code)]
+   |         ^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/associated-const/associated-const-generic-obligations.rs b/src/test/ui/associated-const/associated-const-generic-obligations.rs
new file mode 100644
index 0000000..498e315
--- /dev/null
+++ b/src/test/ui/associated-const/associated-const-generic-obligations.rs
@@ -0,0 +1,18 @@
+trait Foo {
+    type Out: Sized;
+}
+
+impl Foo for String {
+    type Out = String;
+}
+
+trait Bar: Foo {
+    const FROM: Self::Out;
+}
+
+impl<T: Foo> Bar for T {
+    const FROM: &'static str = "foo";
+    //~^ ERROR implemented const `FROM` has an incompatible type for trait [E0326]
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-const/associated-const-generic-obligations.stderr b/src/test/ui/associated-const/associated-const-generic-obligations.stderr
new file mode 100644
index 0000000..eeee26a
--- /dev/null
+++ b/src/test/ui/associated-const/associated-const-generic-obligations.stderr
@@ -0,0 +1,15 @@
+error[E0326]: implemented const `FROM` has an incompatible type for trait
+  --> $DIR/associated-const-generic-obligations.rs:14:17
+   |
+LL |     const FROM: Self::Out;
+   |                 --------- type in trait
+...
+LL |     const FROM: &'static str = "foo";
+   |                 ^^^^^^^^^^^^ expected associated type, found reference
+   |
+   = note: expected type `<T as Foo>::Out`
+              found type `&'static str`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0326`.
diff --git a/src/test/ui/associated-const/associated-const-impl-wrong-lifetime.rs b/src/test/ui/associated-const/associated-const-impl-wrong-lifetime.rs
new file mode 100644
index 0000000..08260ec
--- /dev/null
+++ b/src/test/ui/associated-const/associated-const-impl-wrong-lifetime.rs
@@ -0,0 +1,11 @@
+trait Foo {
+    const NAME: &'static str;
+}
+
+
+impl<'a> Foo for &'a () {
+    const NAME: &'a str = "unit";
+    //~^ ERROR mismatched types [E0308]
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-const/associated-const-impl-wrong-lifetime.stderr b/src/test/ui/associated-const/associated-const-impl-wrong-lifetime.stderr
new file mode 100644
index 0000000..c213cfe
--- /dev/null
+++ b/src/test/ui/associated-const/associated-const-impl-wrong-lifetime.stderr
@@ -0,0 +1,18 @@
+error[E0308]: mismatched types
+  --> $DIR/associated-const-impl-wrong-lifetime.rs:7:5
+   |
+LL |     const NAME: &'a str = "unit";
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
+   |
+   = note: expected type `&'static str`
+              found type `&'a str`
+note: the lifetime 'a as defined on the impl at 6:6...
+  --> $DIR/associated-const-impl-wrong-lifetime.rs:6:6
+   |
+LL | impl<'a> Foo for &'a () {
+   |      ^^
+   = note: ...does not necessarily outlive the static lifetime
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/associated-const/associated-const-impl-wrong-type.rs b/src/test/ui/associated-const/associated-const-impl-wrong-type.rs
new file mode 100644
index 0000000..1aad749
--- /dev/null
+++ b/src/test/ui/associated-const/associated-const-impl-wrong-type.rs
@@ -0,0 +1,12 @@
+trait Foo {
+    const BAR: u32;
+}
+
+struct SignedBar;
+
+impl Foo for SignedBar {
+    const BAR: i32 = -1;
+    //~^ ERROR implemented const `BAR` has an incompatible type for trait [E0326]
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-const/associated-const-impl-wrong-type.stderr b/src/test/ui/associated-const/associated-const-impl-wrong-type.stderr
new file mode 100644
index 0000000..0693d99
--- /dev/null
+++ b/src/test/ui/associated-const/associated-const-impl-wrong-type.stderr
@@ -0,0 +1,12 @@
+error[E0326]: implemented const `BAR` has an incompatible type for trait
+  --> $DIR/associated-const-impl-wrong-type.rs:8:16
+   |
+LL |     const BAR: u32;
+   |                --- type in trait
+...
+LL |     const BAR: i32 = -1;
+   |                ^^^ expected u32, found i32
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0326`.
diff --git a/src/test/ui/associated-const/associated-const-in-trait.rs b/src/test/ui/associated-const/associated-const-in-trait.rs
new file mode 100644
index 0000000..187708a
--- /dev/null
+++ b/src/test/ui/associated-const/associated-const-in-trait.rs
@@ -0,0 +1,14 @@
+// #29924
+
+#![feature(const_fn, associated_consts)]
+
+trait Trait {
+    const N: usize;
+}
+
+impl Trait {
+    //~^ ERROR the trait `Trait` cannot be made into an object [E0038]
+    const fn n() -> usize { Self::N }
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-const/associated-const-in-trait.stderr b/src/test/ui/associated-const/associated-const-in-trait.stderr
new file mode 100644
index 0000000..44a9263
--- /dev/null
+++ b/src/test/ui/associated-const/associated-const-in-trait.stderr
@@ -0,0 +1,11 @@
+error[E0038]: the trait `Trait` cannot be made into an object
+  --> $DIR/associated-const-in-trait.rs:9:6
+   |
+LL | impl Trait {
+   |      ^^^^^ the trait `Trait` cannot be made into an object
+   |
+   = note: the trait cannot contain associated consts like `N`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/associated-const/associated-const-no-item.rs b/src/test/ui/associated-const/associated-const-no-item.rs
new file mode 100644
index 0000000..35fb662f
--- /dev/null
+++ b/src/test/ui/associated-const/associated-const-no-item.rs
@@ -0,0 +1,10 @@
+trait Foo {
+    const ID: i32;
+}
+
+const X: i32 = <i32>::ID;
+//~^ ERROR no associated item named `ID` found for type `i32`
+
+fn main() {
+    assert_eq!(1, X);
+}
diff --git a/src/test/ui/associated-const/associated-const-no-item.stderr b/src/test/ui/associated-const/associated-const-no-item.stderr
new file mode 100644
index 0000000..d96cf67
--- /dev/null
+++ b/src/test/ui/associated-const/associated-const-no-item.stderr
@@ -0,0 +1,13 @@
+error[E0599]: no associated item named `ID` found for type `i32` in the current scope
+  --> $DIR/associated-const-no-item.rs:5:23
+   |
+LL | const X: i32 = <i32>::ID;
+   |                       ^^ associated item not found in `i32`
+   |
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following trait defines an item `ID`, perhaps you need to implement it:
+           candidate #1: `Foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/associated-const/associated-const-private-impl.rs b/src/test/ui/associated-const/associated-const-private-impl.rs
new file mode 100644
index 0000000..3ee3134
--- /dev/null
+++ b/src/test/ui/associated-const/associated-const-private-impl.rs
@@ -0,0 +1,15 @@
+mod bar1 {
+    pub use self::bar2::Foo;
+    mod bar2 {
+        pub struct Foo;
+
+        impl Foo {
+            const ID: i32 = 1;
+        }
+    }
+}
+
+fn main() {
+    assert_eq!(1, bar1::Foo::ID);
+    //~^ERROR associated constant `ID` is private
+}
diff --git a/src/test/ui/associated-const/associated-const-private-impl.stderr b/src/test/ui/associated-const/associated-const-private-impl.stderr
new file mode 100644
index 0000000..7af5517
--- /dev/null
+++ b/src/test/ui/associated-const/associated-const-private-impl.stderr
@@ -0,0 +1,9 @@
+error[E0624]: associated constant `ID` is private
+  --> $DIR/associated-const-private-impl.rs:13:19
+   |
+LL |     assert_eq!(1, bar1::Foo::ID);
+   |                   ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0624`.
diff --git a/src/test/ui/associated-const/associated-const-trait-bound.rs b/src/test/ui/associated-const/associated-const-trait-bound.rs
new file mode 100644
index 0000000..0ce46d3
--- /dev/null
+++ b/src/test/ui/associated-const/associated-const-trait-bound.rs
@@ -0,0 +1,21 @@
+// compile-pass
+
+trait ConstDefault {
+    const DEFAULT: Self;
+}
+
+trait Foo: Sized {}
+
+trait FooExt: Foo {
+    type T: ConstDefault;
+}
+
+trait Bar<F: FooExt> {
+    const T: F::T;
+}
+
+impl<F: FooExt> Bar<F> for () {
+    const T: F::T = <F::T as ConstDefault>::DEFAULT;
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-const/associated-const-type-parameter-arms.rs b/src/test/ui/associated-const/associated-const-type-parameter-arms.rs
new file mode 100644
index 0000000..3f260d8
--- /dev/null
+++ b/src/test/ui/associated-const/associated-const-type-parameter-arms.rs
@@ -0,0 +1,29 @@
+pub enum EFoo { A, B, C, D }
+
+pub trait Foo {
+    const X: EFoo;
+}
+
+struct Abc;
+
+impl Foo for Abc {
+    const X: EFoo = EFoo::B;
+}
+
+struct Def;
+impl Foo for Def {
+    const X: EFoo = EFoo::D;
+}
+
+pub fn test<A: Foo, B: Foo>(arg: EFoo) {
+    match arg {
+        A::X => println!("A::X"),
+        //~^ error: associated consts cannot be referenced in patterns [E0158]
+        B::X => println!("B::X"),
+        //~^ error: associated consts cannot be referenced in patterns [E0158]
+        _ => (),
+    }
+}
+
+fn main() {
+}
diff --git a/src/test/ui/associated-const/associated-const-type-parameter-arms.stderr b/src/test/ui/associated-const/associated-const-type-parameter-arms.stderr
new file mode 100644
index 0000000..1ccf9fe
--- /dev/null
+++ b/src/test/ui/associated-const/associated-const-type-parameter-arms.stderr
@@ -0,0 +1,15 @@
+error[E0158]: associated consts cannot be referenced in patterns
+  --> $DIR/associated-const-type-parameter-arms.rs:20:9
+   |
+LL |         A::X => println!("A::X"),
+   |         ^^^^
+
+error[E0158]: associated consts cannot be referenced in patterns
+  --> $DIR/associated-const-type-parameter-arms.rs:22:9
+   |
+LL |         B::X => println!("B::X"),
+   |         ^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0158`.
diff --git a/src/test/ui/associated-const/associated-const-type-parameter-arrays-2.rs b/src/test/ui/associated-const/associated-const-type-parameter-arrays-2.rs
new file mode 100644
index 0000000..f1f82ca
--- /dev/null
+++ b/src/test/ui/associated-const/associated-const-type-parameter-arrays-2.rs
@@ -0,0 +1,21 @@
+pub trait Foo {
+    const Y: usize;
+}
+
+struct Abc;
+impl Foo for Abc {
+    const Y: usize = 8;
+}
+
+struct Def;
+impl Foo for Def {
+    const Y: usize = 33;
+}
+
+pub fn test<A: Foo, B: Foo>() {
+    let _array = [4; <A as Foo>::Y];
+    //~^ ERROR the trait bound `A: Foo` is not satisfied [E0277]
+}
+
+fn main() {
+}
diff --git a/src/test/ui/associated-const/associated-const-type-parameter-arrays-2.stderr b/src/test/ui/associated-const/associated-const-type-parameter-arrays-2.stderr
new file mode 100644
index 0000000..573b8ed
--- /dev/null
+++ b/src/test/ui/associated-const/associated-const-type-parameter-arrays-2.stderr
@@ -0,0 +1,16 @@
+error[E0277]: the trait bound `A: Foo` is not satisfied
+  --> $DIR/associated-const-type-parameter-arrays-2.rs:16:22
+   |
+LL |     let _array = [4; <A as Foo>::Y];
+   |                      ^^^^^^^^^^^^^ the trait `Foo` is not implemented for `A`
+   |
+   = help: consider adding a `where A: Foo` bound
+note: required by `Foo::Y`
+  --> $DIR/associated-const-type-parameter-arrays-2.rs:2:5
+   |
+LL |     const Y: usize;
+   |     ^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/associated-const/associated-const-type-parameter-arrays.rs b/src/test/ui/associated-const/associated-const-type-parameter-arrays.rs
new file mode 100644
index 0000000..d518210
--- /dev/null
+++ b/src/test/ui/associated-const/associated-const-type-parameter-arrays.rs
@@ -0,0 +1,21 @@
+pub trait Foo {
+    const Y: usize;
+}
+
+struct Abc;
+impl Foo for Abc {
+    const Y: usize = 8;
+}
+
+struct Def;
+impl Foo for Def {
+    const Y: usize = 33;
+}
+
+pub fn test<A: Foo, B: Foo>() {
+    let _array: [u32; <A as Foo>::Y];
+    //~^ ERROR the trait bound `A: Foo` is not satisfied [E0277]
+}
+
+fn main() {
+}
diff --git a/src/test/ui/associated-const/associated-const-type-parameter-arrays.stderr b/src/test/ui/associated-const/associated-const-type-parameter-arrays.stderr
new file mode 100644
index 0000000..bf1ee38
--- /dev/null
+++ b/src/test/ui/associated-const/associated-const-type-parameter-arrays.stderr
@@ -0,0 +1,16 @@
+error[E0277]: the trait bound `A: Foo` is not satisfied
+  --> $DIR/associated-const-type-parameter-arrays.rs:16:23
+   |
+LL |     let _array: [u32; <A as Foo>::Y];
+   |                       ^^^^^^^^^^^^^ the trait `Foo` is not implemented for `A`
+   |
+   = help: consider adding a `where A: Foo` bound
+note: required by `Foo::Y`
+  --> $DIR/associated-const-type-parameter-arrays.rs:2:5
+   |
+LL |     const Y: usize;
+   |     ^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/associated-item/associated-item-duplicate-names-2.rs b/src/test/ui/associated-item/associated-item-duplicate-names-2.rs
new file mode 100644
index 0000000..550c7ae
--- /dev/null
+++ b/src/test/ui/associated-item/associated-item-duplicate-names-2.rs
@@ -0,0 +1,8 @@
+struct Foo;
+
+impl Foo {
+    const bar: bool = true;
+    fn bar() {} //~ ERROR duplicate definitions
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-item/associated-item-duplicate-names-2.stderr b/src/test/ui/associated-item/associated-item-duplicate-names-2.stderr
new file mode 100644
index 0000000..ea475ff
--- /dev/null
+++ b/src/test/ui/associated-item/associated-item-duplicate-names-2.stderr
@@ -0,0 +1,11 @@
+error[E0201]: duplicate definitions with name `bar`:
+  --> $DIR/associated-item-duplicate-names-2.rs:5:5
+   |
+LL |     const bar: bool = true;
+   |     ----------------------- previous definition of `bar` here
+LL |     fn bar() {}
+   |     ^^^^^^^^^^^ duplicate definition
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0201`.
diff --git a/src/test/ui/associated-item/associated-item-duplicate-names-3.rs b/src/test/ui/associated-item/associated-item-duplicate-names-3.rs
new file mode 100644
index 0000000..6aa1b48
--- /dev/null
+++ b/src/test/ui/associated-item/associated-item-duplicate-names-3.rs
@@ -0,0 +1,19 @@
+//
+// Before the introduction of the "duplicate associated type" error, the
+// program below used to result in the "ambiguous associated type" error E0223,
+// which is unexpected.
+
+trait Foo {
+    type Bar;
+}
+
+struct Baz;
+
+impl Foo for Baz {
+    type Bar = i16;
+    type Bar = u16; //~ ERROR duplicate definitions
+}
+
+fn main() {
+    let x: Baz::Bar = 5;
+}
diff --git a/src/test/ui/associated-item/associated-item-duplicate-names-3.stderr b/src/test/ui/associated-item/associated-item-duplicate-names-3.stderr
new file mode 100644
index 0000000..5749586
--- /dev/null
+++ b/src/test/ui/associated-item/associated-item-duplicate-names-3.stderr
@@ -0,0 +1,11 @@
+error[E0201]: duplicate definitions with name `Bar`:
+  --> $DIR/associated-item-duplicate-names-3.rs:14:5
+   |
+LL |     type Bar = i16;
+   |     --------------- previous definition of `Bar` here
+LL |     type Bar = u16;
+   |     ^^^^^^^^^^^^^^^ duplicate definition
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0201`.
diff --git a/src/test/ui/associated-item/associated-item-duplicate-names.rs b/src/test/ui/associated-item/associated-item-duplicate-names.rs
new file mode 100644
index 0000000..6677fad
--- /dev/null
+++ b/src/test/ui/associated-item/associated-item-duplicate-names.rs
@@ -0,0 +1,19 @@
+// Test for issue #23969
+
+
+trait Foo {
+    type Ty;
+    const BAR: u32;
+}
+
+impl Foo for () {
+    type Ty = ();
+    type Ty = usize; //~ ERROR duplicate definitions
+    const BAR: u32 = 7;
+    const BAR: u32 = 8; //~ ERROR duplicate definitions
+}
+
+fn main() {
+    let _: <() as Foo>::Ty = ();
+    let _: u32 = <() as Foo>::BAR;
+}
diff --git a/src/test/ui/associated-item/associated-item-duplicate-names.stderr b/src/test/ui/associated-item/associated-item-duplicate-names.stderr
new file mode 100644
index 0000000..f4af9e0
--- /dev/null
+++ b/src/test/ui/associated-item/associated-item-duplicate-names.stderr
@@ -0,0 +1,19 @@
+error[E0201]: duplicate definitions with name `Ty`:
+  --> $DIR/associated-item-duplicate-names.rs:11:5
+   |
+LL |     type Ty = ();
+   |     ------------- previous definition of `Ty` here
+LL |     type Ty = usize;
+   |     ^^^^^^^^^^^^^^^^ duplicate definition
+
+error[E0201]: duplicate definitions with name `BAR`:
+  --> $DIR/associated-item-duplicate-names.rs:13:5
+   |
+LL |     const BAR: u32 = 7;
+   |     ------------------- previous definition of `BAR` here
+LL |     const BAR: u32 = 8;
+   |     ^^^^^^^^^^^^^^^^^^^ duplicate definition
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0201`.
diff --git a/src/test/ui/associated-path-shl.rs b/src/test/ui/associated-path-shl.rs
new file mode 100644
index 0000000..d159082
--- /dev/null
+++ b/src/test/ui/associated-path-shl.rs
@@ -0,0 +1,10 @@
+// Check that associated paths starting with `<<` are successfully parsed.
+
+fn main() {
+    let _: <<A>::B>::C; //~ ERROR cannot find type `A` in this scope
+    let _ = <<A>::B>::C; //~ ERROR cannot find type `A` in this scope
+    let <<A>::B>::C; //~ ERROR cannot find type `A` in this scope
+    let 0 ..= <<A>::B>::C; //~ ERROR cannot find type `A` in this scope
+                           //~^ ERROR only char and numeric types are allowed in range patterns
+    <<A>::B>::C; //~ ERROR cannot find type `A` in this scope
+}
diff --git a/src/test/ui/associated-path-shl.stderr b/src/test/ui/associated-path-shl.stderr
new file mode 100644
index 0000000..e1a1e63
--- /dev/null
+++ b/src/test/ui/associated-path-shl.stderr
@@ -0,0 +1,43 @@
+error[E0412]: cannot find type `A` in this scope
+  --> $DIR/associated-path-shl.rs:4:14
+   |
+LL |     let _: <<A>::B>::C;
+   |              ^ not found in this scope
+
+error[E0412]: cannot find type `A` in this scope
+  --> $DIR/associated-path-shl.rs:5:15
+   |
+LL |     let _ = <<A>::B>::C;
+   |               ^ not found in this scope
+
+error[E0412]: cannot find type `A` in this scope
+  --> $DIR/associated-path-shl.rs:6:11
+   |
+LL |     let <<A>::B>::C;
+   |           ^ not found in this scope
+
+error[E0412]: cannot find type `A` in this scope
+  --> $DIR/associated-path-shl.rs:7:17
+   |
+LL |     let 0 ..= <<A>::B>::C;
+   |                 ^ not found in this scope
+
+error[E0412]: cannot find type `A` in this scope
+  --> $DIR/associated-path-shl.rs:9:7
+   |
+LL |     <<A>::B>::C;
+   |       ^ not found in this scope
+
+error[E0029]: only char and numeric types are allowed in range patterns
+  --> $DIR/associated-path-shl.rs:7:15
+   |
+LL |     let 0 ..= <<A>::B>::C;
+   |               ^^^^^^^^^^^ ranges require char or numeric types
+   |
+   = note: start type: {integer}
+   = note: end type: [type error]
+
+error: aborting due to 6 previous errors
+
+Some errors occurred: E0029, E0412.
+For more information about an error, try `rustc --explain E0029`.
diff --git a/src/test/ui/associated-type/associated-type-projection-ambig-between-bound-and-where-clause.rs b/src/test/ui/associated-type/associated-type-projection-ambig-between-bound-and-where-clause.rs
new file mode 100644
index 0000000..c85d41c
--- /dev/null
+++ b/src/test/ui/associated-type/associated-type-projection-ambig-between-bound-and-where-clause.rs
@@ -0,0 +1,42 @@
+// Test equality constraints in a where clause where the type being
+// equated appears in a supertrait.
+
+pub trait Vehicle {
+    type Color;
+
+    fn go(&self) {  }
+}
+
+pub trait Box {
+    type Color;
+
+    fn mail(&self) {  }
+}
+
+fn a<C:Vehicle+Box>(_: C::Color) {
+    //~^ ERROR ambiguous associated type `Color` in bounds of `C`
+}
+
+fn b<C>(_: C::Color) where C : Vehicle+Box {
+    //~^ ERROR ambiguous associated type `Color` in bounds of `C`
+}
+
+fn c<C>(_: C::Color) where C : Vehicle, C : Box {
+    //~^ ERROR ambiguous associated type `Color` in bounds of `C`
+}
+
+struct D<X>;
+impl<X> D<X> where X : Vehicle {
+    fn d(&self, _: X::Color) where X : Box { }
+    //~^ ERROR ambiguous associated type `Color` in bounds of `X`
+}
+
+trait E<X:Vehicle> {
+    fn e(&self, _: X::Color) where X : Box;
+    //~^ ERROR ambiguous associated type `Color` in bounds of `X`
+
+    fn f(&self, _: X::Color) where X : Box { }
+    //~^ ERROR ambiguous associated type `Color` in bounds of `X`
+}
+
+pub fn main() { }
diff --git a/src/test/ui/associated-type/associated-type-projection-ambig-between-bound-and-where-clause.stderr b/src/test/ui/associated-type/associated-type-projection-ambig-between-bound-and-where-clause.stderr
new file mode 100644
index 0000000..9ec6ffb
--- /dev/null
+++ b/src/test/ui/associated-type/associated-type-projection-ambig-between-bound-and-where-clause.stderr
@@ -0,0 +1,75 @@
+error[E0221]: ambiguous associated type `Color` in bounds of `C`
+  --> $DIR/associated-type-projection-ambig-between-bound-and-where-clause.rs:16:24
+   |
+LL |     type Color;
+   |     ----------- ambiguous `Color` from `Vehicle`
+...
+LL |     type Color;
+   |     ----------- ambiguous `Color` from `Box`
+...
+LL | fn a<C:Vehicle+Box>(_: C::Color) {
+   |                        ^^^^^^^^ ambiguous associated type `Color`
+
+error[E0221]: ambiguous associated type `Color` in bounds of `C`
+  --> $DIR/associated-type-projection-ambig-between-bound-and-where-clause.rs:20:12
+   |
+LL |     type Color;
+   |     ----------- ambiguous `Color` from `Vehicle`
+...
+LL |     type Color;
+   |     ----------- ambiguous `Color` from `Box`
+...
+LL | fn b<C>(_: C::Color) where C : Vehicle+Box {
+   |            ^^^^^^^^ ambiguous associated type `Color`
+
+error[E0221]: ambiguous associated type `Color` in bounds of `C`
+  --> $DIR/associated-type-projection-ambig-between-bound-and-where-clause.rs:24:12
+   |
+LL |     type Color;
+   |     ----------- ambiguous `Color` from `Vehicle`
+...
+LL |     type Color;
+   |     ----------- ambiguous `Color` from `Box`
+...
+LL | fn c<C>(_: C::Color) where C : Vehicle, C : Box {
+   |            ^^^^^^^^ ambiguous associated type `Color`
+
+error[E0221]: ambiguous associated type `Color` in bounds of `X`
+  --> $DIR/associated-type-projection-ambig-between-bound-and-where-clause.rs:35:20
+   |
+LL |     type Color;
+   |     ----------- ambiguous `Color` from `Vehicle`
+...
+LL |     type Color;
+   |     ----------- ambiguous `Color` from `Box`
+...
+LL |     fn e(&self, _: X::Color) where X : Box;
+   |                    ^^^^^^^^ ambiguous associated type `Color`
+
+error[E0221]: ambiguous associated type `Color` in bounds of `X`
+  --> $DIR/associated-type-projection-ambig-between-bound-and-where-clause.rs:38:20
+   |
+LL |     type Color;
+   |     ----------- ambiguous `Color` from `Vehicle`
+...
+LL |     type Color;
+   |     ----------- ambiguous `Color` from `Box`
+...
+LL |     fn f(&self, _: X::Color) where X : Box { }
+   |                    ^^^^^^^^ ambiguous associated type `Color`
+
+error[E0221]: ambiguous associated type `Color` in bounds of `X`
+  --> $DIR/associated-type-projection-ambig-between-bound-and-where-clause.rs:30:20
+   |
+LL |     type Color;
+   |     ----------- ambiguous `Color` from `Vehicle`
+...
+LL |     type Color;
+   |     ----------- ambiguous `Color` from `Box`
+...
+LL |     fn d(&self, _: X::Color) where X : Box { }
+   |                    ^^^^^^^^ ambiguous associated type `Color`
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0221`.
diff --git a/src/test/ui/associated-type/associated-type-projection-from-multiple-supertraits.rs b/src/test/ui/associated-type/associated-type-projection-from-multiple-supertraits.rs
new file mode 100644
index 0000000..df9143d
--- /dev/null
+++ b/src/test/ui/associated-type/associated-type-projection-from-multiple-supertraits.rs
@@ -0,0 +1,32 @@
+// Test equality constraints in a where clause where the type being
+// equated appears in a supertrait.
+
+pub trait Vehicle {
+    type Color;
+
+    fn go(&self) {  }
+}
+
+pub trait Box {
+    type Color;
+    //
+    fn mail(&self) {  }
+}
+
+pub trait BoxCar : Box + Vehicle {
+}
+
+fn dent<C:BoxCar>(c: C, color: C::Color) {
+    //~^ ERROR ambiguous associated type `Color` in bounds of `C`
+}
+
+fn dent_object<COLOR>(c: BoxCar<Color=COLOR>) {
+    //~^ ERROR ambiguous associated type
+    //~| ERROR the value of the associated type `Color` (from the trait `Vehicle`) must be specified
+}
+
+fn paint<C:BoxCar>(c: C, d: C::Color) {
+    //~^ ERROR ambiguous associated type `Color` in bounds of `C`
+}
+
+pub fn main() { }
diff --git a/src/test/ui/associated-type/associated-type-projection-from-multiple-supertraits.stderr b/src/test/ui/associated-type/associated-type-projection-from-multiple-supertraits.stderr
new file mode 100644
index 0000000..0994dc8
--- /dev/null
+++ b/src/test/ui/associated-type/associated-type-projection-from-multiple-supertraits.stderr
@@ -0,0 +1,49 @@
+error[E0221]: ambiguous associated type `Color` in bounds of `C`
+  --> $DIR/associated-type-projection-from-multiple-supertraits.rs:19:32
+   |
+LL |     type Color;
+   |     ----------- ambiguous `Color` from `Vehicle`
+...
+LL |     type Color;
+   |     ----------- ambiguous `Color` from `Box`
+...
+LL | fn dent<C:BoxCar>(c: C, color: C::Color) {
+   |                                ^^^^^^^^ ambiguous associated type `Color`
+
+error[E0221]: ambiguous associated type `Color` in bounds of `BoxCar`
+  --> $DIR/associated-type-projection-from-multiple-supertraits.rs:23:33
+   |
+LL |     type Color;
+   |     ----------- ambiguous `Color` from `Vehicle`
+...
+LL |     type Color;
+   |     ----------- ambiguous `Color` from `Box`
+...
+LL | fn dent_object<COLOR>(c: BoxCar<Color=COLOR>) {
+   |                                 ^^^^^^^^^^^ ambiguous associated type `Color`
+
+error[E0191]: the value of the associated type `Color` (from the trait `Vehicle`) must be specified
+  --> $DIR/associated-type-projection-from-multiple-supertraits.rs:23:26
+   |
+LL |     type Color;
+   |     ----------- `Color` defined here
+...
+LL | fn dent_object<COLOR>(c: BoxCar<Color=COLOR>) {
+   |                          ^^^^^^^^^^^^^^^^^^^ associated type `Color` must be specified
+
+error[E0221]: ambiguous associated type `Color` in bounds of `C`
+  --> $DIR/associated-type-projection-from-multiple-supertraits.rs:28:29
+   |
+LL |     type Color;
+   |     ----------- ambiguous `Color` from `Vehicle`
+...
+LL |     type Color;
+   |     ----------- ambiguous `Color` from `Box`
+...
+LL | fn paint<C:BoxCar>(c: C, d: C::Color) {
+   |                             ^^^^^^^^ ambiguous associated type `Color`
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0191, E0221.
+For more information about an error, try `rustc --explain E0191`.
diff --git a/src/test/ui/associated-type/associated-type-projection-from-supertrait.rs b/src/test/ui/associated-type/associated-type-projection-from-supertrait.rs
new file mode 100644
index 0000000..06dfe49
--- /dev/null
+++ b/src/test/ui/associated-type/associated-type-projection-from-supertrait.rs
@@ -0,0 +1,44 @@
+// Test equality constraints in a where clause where the type being
+// equated appears in a supertrait.
+
+pub trait Vehicle {
+    type Color;
+
+    fn go(&self) {  }
+}
+
+pub trait Car : Vehicle {
+    fn honk(&self) { }
+    fn chip_paint(&self, c: Self::Color) { }
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+struct Black;
+struct ModelT;
+impl Vehicle for ModelT { type Color = Black; }
+impl Car for ModelT { }
+
+///////////////////////////////////////////////////////////////////////////
+
+struct Blue;
+struct ModelU;
+impl Vehicle for ModelU { type Color = Blue; }
+impl Car for ModelU { }
+
+///////////////////////////////////////////////////////////////////////////
+
+fn dent<C:Car>(c: C, color: C::Color) { c.chip_paint(color) }
+fn a() { dent(ModelT, Black); }
+fn b() { dent(ModelT, Blue); } //~ ERROR mismatched types
+fn c() { dent(ModelU, Black); } //~ ERROR mismatched types
+fn d() { dent(ModelU, Blue); }
+
+///////////////////////////////////////////////////////////////////////////
+
+fn e() { ModelT.chip_paint(Black); }
+fn f() { ModelT.chip_paint(Blue); } //~ ERROR mismatched types
+fn g() { ModelU.chip_paint(Black); } //~ ERROR mismatched types
+fn h() { ModelU.chip_paint(Blue); }
+
+pub fn main() { }
diff --git a/src/test/ui/associated-type/associated-type-projection-from-supertrait.stderr b/src/test/ui/associated-type/associated-type-projection-from-supertrait.stderr
new file mode 100644
index 0000000..06f1a1c
--- /dev/null
+++ b/src/test/ui/associated-type/associated-type-projection-from-supertrait.stderr
@@ -0,0 +1,39 @@
+error[E0308]: mismatched types
+  --> $DIR/associated-type-projection-from-supertrait.rs:33:23
+   |
+LL | fn b() { dent(ModelT, Blue); }
+   |                       ^^^^ expected struct `Black`, found struct `Blue`
+   |
+   = note: expected type `Black`
+              found type `Blue`
+
+error[E0308]: mismatched types
+  --> $DIR/associated-type-projection-from-supertrait.rs:34:23
+   |
+LL | fn c() { dent(ModelU, Black); }
+   |                       ^^^^^ expected struct `Blue`, found struct `Black`
+   |
+   = note: expected type `Blue`
+              found type `Black`
+
+error[E0308]: mismatched types
+  --> $DIR/associated-type-projection-from-supertrait.rs:40:28
+   |
+LL | fn f() { ModelT.chip_paint(Blue); }
+   |                            ^^^^ expected struct `Black`, found struct `Blue`
+   |
+   = note: expected type `Black`
+              found type `Blue`
+
+error[E0308]: mismatched types
+  --> $DIR/associated-type-projection-from-supertrait.rs:41:28
+   |
+LL | fn g() { ModelU.chip_paint(Black); }
+   |                            ^^^^^ expected struct `Blue`, found struct `Black`
+   |
+   = note: expected type `Blue`
+              found type `Black`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/associated-types/associated-types-ICE-when-projecting-out-of-err.rs b/src/test/ui/associated-types/associated-types-ICE-when-projecting-out-of-err.rs
new file mode 100644
index 0000000..707bcac
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-ICE-when-projecting-out-of-err.rs
@@ -0,0 +1,25 @@
+// Test that we do not ICE when the self type is `ty::err`, but rather
+// just propagate the error.
+
+#![crate_type = "lib"]
+#![feature(lang_items)]
+#![feature(no_core)]
+#![no_core]
+
+#[lang="sized"]
+pub trait Sized {
+    // Empty.
+}
+
+#[lang = "add"]
+trait Add<RHS=Self> {
+    type Output;
+
+    fn add(self, _: RHS) -> Self::Output;
+}
+
+fn ice<A>(a: A) {
+    let r = loop {};
+    r = r + a;
+    //~^ ERROR the trait bound `(): Add<A>` is not satisfied
+}
diff --git a/src/test/ui/associated-types/associated-types-ICE-when-projecting-out-of-err.stderr b/src/test/ui/associated-types/associated-types-ICE-when-projecting-out-of-err.stderr
new file mode 100644
index 0000000..8c3463a
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-ICE-when-projecting-out-of-err.stderr
@@ -0,0 +1,9 @@
+error[E0277]: the trait bound `(): Add<A>` is not satisfied
+  --> $DIR/associated-types-ICE-when-projecting-out-of-err.rs:23:11
+   |
+LL |     r = r + a;
+   |           ^ the trait `Add<A>` is not implemented for `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.rs b/src/test/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.rs
new file mode 100644
index 0000000..6531308
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.rs
@@ -0,0 +1,41 @@
+// Test equality constraints in a where clause where the type being
+// equated appears in a supertrait.
+
+pub trait Vehicle {
+    type Color;
+
+    fn go(&self) {  }
+}
+
+pub trait Car : Vehicle {
+    fn honk(&self) { }
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+struct Black;
+struct ModelT;
+impl Vehicle for ModelT { type Color = Black; }
+impl Car for ModelT { }
+
+///////////////////////////////////////////////////////////////////////////
+
+struct Blue;
+struct ModelU;
+impl Vehicle for ModelU { type Color = Blue; }
+impl Car for ModelU { }
+
+///////////////////////////////////////////////////////////////////////////
+
+fn black_car<C:Car<Color=Black>>(c: C) {
+}
+
+fn blue_car<C:Car<Color=Blue>>(c: C) {
+}
+
+fn a() { black_car(ModelT); }
+fn b() { blue_car(ModelT); } //~ ERROR type mismatch
+fn c() { black_car(ModelU); } //~ ERROR type mismatch
+fn d() { blue_car(ModelU); }
+
+pub fn main() { }
diff --git a/src/test/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.stderr b/src/test/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.stderr
new file mode 100644
index 0000000..4b54860
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.stderr
@@ -0,0 +1,31 @@
+error[E0271]: type mismatch resolving `<ModelT as Vehicle>::Color == Blue`
+  --> $DIR/associated-types-binding-to-type-defined-in-supertrait.rs:37:10
+   |
+LL | fn b() { blue_car(ModelT); }
+   |          ^^^^^^^^ expected struct `Black`, found struct `Blue`
+   |
+   = note: expected type `Black`
+              found type `Blue`
+note: required by `blue_car`
+  --> $DIR/associated-types-binding-to-type-defined-in-supertrait.rs:33:1
+   |
+LL | fn blue_car<C:Car<Color=Blue>>(c: C) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0271]: type mismatch resolving `<ModelU as Vehicle>::Color == Black`
+  --> $DIR/associated-types-binding-to-type-defined-in-supertrait.rs:38:10
+   |
+LL | fn c() { black_car(ModelU); }
+   |          ^^^^^^^^^ expected struct `Blue`, found struct `Black`
+   |
+   = note: expected type `Blue`
+              found type `Black`
+note: required by `black_car`
+  --> $DIR/associated-types-binding-to-type-defined-in-supertrait.rs:30:1
+   |
+LL | fn black_car<C:Car<Color=Black>>(c: C) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/associated-types/associated-types-bound-failure.rs b/src/test/ui/associated-types/associated-types-bound-failure.rs
new file mode 100644
index 0000000..883ac36
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-bound-failure.rs
@@ -0,0 +1,27 @@
+// Test equality constraints on associated types in a where clause.
+
+pub trait ToInt {
+    fn to_int(&self) -> isize;
+}
+
+pub trait GetToInt
+{
+    type R;
+
+    fn get(&self) -> <Self as GetToInt>::R;
+}
+
+fn foo<G>(g: G) -> isize
+    where G : GetToInt
+{
+    ToInt::to_int(&g.get()) //~ ERROR E0277
+}
+
+fn bar<G : GetToInt>(g: G) -> isize
+    where G::R : ToInt
+{
+    ToInt::to_int(&g.get()) // OK
+}
+
+pub fn main() {
+}
diff --git a/src/test/ui/associated-types/associated-types-bound-failure.stderr b/src/test/ui/associated-types/associated-types-bound-failure.stderr
new file mode 100644
index 0000000..502fb4f
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-bound-failure.stderr
@@ -0,0 +1,16 @@
+error[E0277]: the trait bound `<G as GetToInt>::R: ToInt` is not satisfied
+  --> $DIR/associated-types-bound-failure.rs:17:5
+   |
+LL |     ToInt::to_int(&g.get())
+   |     ^^^^^^^^^^^^^ the trait `ToInt` is not implemented for `<G as GetToInt>::R`
+   |
+   = help: consider adding a `where <G as GetToInt>::R: ToInt` bound
+note: required by `ToInt::to_int`
+  --> $DIR/associated-types-bound-failure.rs:4:5
+   |
+LL |     fn to_int(&self) -> isize;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/associated-types/associated-types-coherence-failure.rs b/src/test/ui/associated-types/associated-types-coherence-failure.rs
new file mode 100644
index 0000000..c33f2ac
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-coherence-failure.rs
@@ -0,0 +1,49 @@
+// Test that coherence detects overlap when some of the types in the
+// impls are projections of associated type. Issue #20624.
+
+use std::marker::PhantomData;
+use std::ops::Deref;
+
+pub struct Cow<'a, B: ?Sized>(PhantomData<(&'a (),B)>);
+
+/// Trait for moving into a `Cow`
+pub trait IntoCow<'a, B: ?Sized> {
+    /// Moves `self` into `Cow`
+    fn into_cow(self) -> Cow<'a, B>;
+}
+
+impl<'a, B: ?Sized> IntoCow<'a, B> for <B as ToOwned>::Owned where B: ToOwned {
+    fn into_cow(self) -> Cow<'a, B> {
+        Cow(PhantomData)
+    }
+}
+
+impl<'a, B: ?Sized> IntoCow<'a, B> for Cow<'a, B> where B: ToOwned {
+//~^ ERROR E0119
+    fn into_cow(self) -> Cow<'a, B> {
+        self
+    }
+}
+
+impl<'a, B: ?Sized> IntoCow<'a, B> for &'a B where B: ToOwned {
+//~^ ERROR E0119
+    fn into_cow(self) -> Cow<'a, B> {
+        Cow(PhantomData)
+    }
+}
+
+impl ToOwned for u8 {
+    type Owned = &'static u8;
+    fn to_owned(&self) -> &'static u8 { panic!() }
+}
+
+/// A generalization of Clone to borrowed data.
+pub trait ToOwned {
+    type Owned;
+
+    /// Creates owned data from borrowed data, usually by copying.
+    fn to_owned(&self) -> Self::Owned;
+}
+
+
+fn main() {}
diff --git a/src/test/ui/associated-types/associated-types-coherence-failure.stderr b/src/test/ui/associated-types/associated-types-coherence-failure.stderr
new file mode 100644
index 0000000..2c53b0a
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-coherence-failure.stderr
@@ -0,0 +1,21 @@
+error[E0119]: conflicting implementations of trait `IntoCow<'_, _>` for type `Cow<'_, _>`:
+  --> $DIR/associated-types-coherence-failure.rs:21:1
+   |
+LL | impl<'a, B: ?Sized> IntoCow<'a, B> for <B as ToOwned>::Owned where B: ToOwned {
+   | ----------------------------------------------------------------------------- first implementation here
+...
+LL | impl<'a, B: ?Sized> IntoCow<'a, B> for Cow<'a, B> where B: ToOwned {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Cow<'_, _>`
+
+error[E0119]: conflicting implementations of trait `IntoCow<'_, _>` for type `&_`:
+  --> $DIR/associated-types-coherence-failure.rs:28:1
+   |
+LL | impl<'a, B: ?Sized> IntoCow<'a, B> for <B as ToOwned>::Owned where B: ToOwned {
+   | ----------------------------------------------------------------------------- first implementation here
+...
+LL | impl<'a, B: ?Sized> IntoCow<'a, B> for &'a B where B: ToOwned {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/associated-types/associated-types-eq-1.rs b/src/test/ui/associated-types/associated-types-eq-1.rs
new file mode 100644
index 0000000..c371138
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-eq-1.rs
@@ -0,0 +1,13 @@
+// Test equality constraints on associated types. Check that unsupported syntax
+// does not ICE.
+
+pub trait Foo {
+    type A;
+    fn boo(&self) -> <Self as Foo>::A;
+}
+
+fn foo2<I: Foo>(x: I) {
+    let _: A = x.boo(); //~ ERROR cannot find type `A` in this scope
+}
+
+pub fn main() {}
diff --git a/src/test/ui/associated-types/associated-types-eq-1.stderr b/src/test/ui/associated-types/associated-types-eq-1.stderr
new file mode 100644
index 0000000..aa98731
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-eq-1.stderr
@@ -0,0 +1,9 @@
+error[E0412]: cannot find type `A` in this scope
+  --> $DIR/associated-types-eq-1.rs:10:12
+   |
+LL |     let _: A = x.boo();
+   |            ^ help: a type parameter with a similar name exists: `I`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/src/test/ui/associated-types/associated-types-eq-2.rs b/src/test/ui/associated-types/associated-types-eq-2.rs
new file mode 100644
index 0000000..18e38d4
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-eq-2.rs
@@ -0,0 +1,19 @@
+// Test equality constraints on associated types. Check we get an error when an
+// equality constraint is used in a qualified path.
+
+pub trait Foo {
+    type A;
+    fn boo(&self) -> <Self as Foo>::A;
+}
+
+struct Bar;
+
+impl Foo for isize {
+    type A = usize;
+    fn boo(&self) -> usize { 42 }
+}
+
+fn baz<I: Foo>(x: &<I as Foo<A=Bar>>::A) {}
+//~^ ERROR associated type bindings are not allowed here
+
+pub fn main() {}
diff --git a/src/test/ui/associated-types/associated-types-eq-2.stderr b/src/test/ui/associated-types/associated-types-eq-2.stderr
new file mode 100644
index 0000000..23ee8cd
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-eq-2.stderr
@@ -0,0 +1,9 @@
+error[E0229]: associated type bindings are not allowed here
+  --> $DIR/associated-types-eq-2.rs:16:30
+   |
+LL | fn baz<I: Foo>(x: &<I as Foo<A=Bar>>::A) {}
+   |                              ^^^^^ associated type not allowed here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0229`.
diff --git a/src/test/ui/associated-types/associated-types-eq-3.rs b/src/test/ui/associated-types/associated-types-eq-3.rs
new file mode 100644
index 0000000..1a58dcc
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-eq-3.rs
@@ -0,0 +1,44 @@
+// Test equality constraints on associated types. Check we get type errors
+// where we should.
+
+pub trait Foo {
+    type A;
+    fn boo(&self) -> <Self as Foo>::A;
+}
+
+struct Bar;
+
+impl Foo for isize {
+    type A = usize;
+    fn boo(&self) -> usize {
+        42
+    }
+}
+
+fn foo1<I: Foo<A=Bar>>(x: I) {
+    let _: Bar = x.boo();
+}
+
+fn foo2<I: Foo>(x: I) {
+    let _: Bar = x.boo();
+    //~^ ERROR mismatched types
+    //~| expected type `Bar`
+    //~| found type `<I as Foo>::A`
+    //~| expected struct `Bar`, found associated type
+}
+
+
+pub fn baz(x: &Foo<A=Bar>) {
+    let _: Bar = x.boo();
+}
+
+
+pub fn main() {
+    let a = 42;
+    foo1(a);
+    //~^ ERROR type mismatch resolving
+    //~| expected usize, found struct `Bar`
+    baz(&a);
+    //~^ ERROR type mismatch resolving
+    //~| expected usize, found struct `Bar`
+}
diff --git a/src/test/ui/associated-types/associated-types-eq-3.stderr b/src/test/ui/associated-types/associated-types-eq-3.stderr
new file mode 100644
index 0000000..31d2c5f
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-eq-3.stderr
@@ -0,0 +1,37 @@
+error[E0308]: mismatched types
+  --> $DIR/associated-types-eq-3.rs:23:18
+   |
+LL |     let _: Bar = x.boo();
+   |                  ^^^^^^^ expected struct `Bar`, found associated type
+   |
+   = note: expected type `Bar`
+              found type `<I as Foo>::A`
+
+error[E0271]: type mismatch resolving `<isize as Foo>::A == Bar`
+  --> $DIR/associated-types-eq-3.rs:38:5
+   |
+LL |     foo1(a);
+   |     ^^^^ expected usize, found struct `Bar`
+   |
+   = note: expected type `usize`
+              found type `Bar`
+note: required by `foo1`
+  --> $DIR/associated-types-eq-3.rs:18:1
+   |
+LL | fn foo1<I: Foo<A=Bar>>(x: I) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0271]: type mismatch resolving `<isize as Foo>::A == Bar`
+  --> $DIR/associated-types-eq-3.rs:41:9
+   |
+LL |     baz(&a);
+   |         ^^ expected usize, found struct `Bar`
+   |
+   = note: expected type `usize`
+              found type `Bar`
+   = note: required for the cast to the object type `dyn Foo<A = Bar>`
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0271, E0308.
+For more information about an error, try `rustc --explain E0271`.
diff --git a/src/test/ui/associated-types/associated-types-eq-expr-path.rs b/src/test/ui/associated-types/associated-types-eq-expr-path.rs
new file mode 100644
index 0000000..143992f
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-eq-expr-path.rs
@@ -0,0 +1,16 @@
+// Check that an associated type cannot be bound in an expression path.
+
+trait Foo {
+    type A;
+    fn bar() -> isize;
+}
+
+impl Foo for isize {
+    type A = usize;
+    fn bar() -> isize { 42 }
+}
+
+pub fn main() {
+    let x: isize = Foo::<A=usize>::bar();
+    //~^ ERROR associated type bindings are not allowed here
+}
diff --git a/src/test/ui/associated-types/associated-types-eq-expr-path.stderr b/src/test/ui/associated-types/associated-types-eq-expr-path.stderr
new file mode 100644
index 0000000..bd354cf
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-eq-expr-path.stderr
@@ -0,0 +1,9 @@
+error[E0229]: associated type bindings are not allowed here
+  --> $DIR/associated-types-eq-expr-path.rs:14:26
+   |
+LL |     let x: isize = Foo::<A=usize>::bar();
+   |                          ^^^^^^^ associated type not allowed here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0229`.
diff --git a/src/test/ui/associated-types/associated-types-eq-hr.rs b/src/test/ui/associated-types/associated-types-eq-hr.rs
new file mode 100644
index 0000000..e6afa3f
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-eq-hr.rs
@@ -0,0 +1,111 @@
+// Check testing of equality constraints in a higher-ranked context.
+
+pub trait TheTrait<T> {
+    type A;
+
+    fn get(&self, t: T) -> Self::A;
+}
+
+struct IntStruct {
+    x: isize
+}
+
+impl<'a> TheTrait<&'a isize> for IntStruct {
+    type A = &'a isize;
+
+    fn get(&self, t: &'a isize) -> &'a isize {
+        t
+    }
+}
+
+struct UintStruct {
+    x: isize
+}
+
+impl<'a> TheTrait<&'a isize> for UintStruct {
+    type A = &'a usize;
+
+    fn get(&self, t: &'a isize) -> &'a usize {
+        panic!()
+    }
+}
+
+struct Tuple {
+}
+
+impl<'a> TheTrait<(&'a isize, &'a isize)> for Tuple {
+    type A = &'a isize;
+
+    fn get(&self, t: (&'a isize, &'a isize)) -> &'a isize {
+        t.0
+    }
+}
+
+fn foo<T>()
+    where T : for<'x> TheTrait<&'x isize, A = &'x isize>
+{
+    // ok for IntStruct, but not UintStruct
+}
+
+fn bar<T>()
+    where T : for<'x> TheTrait<&'x isize, A = &'x usize>
+{
+    // ok for UintStruct, but not IntStruct
+}
+
+fn tuple_one<T>()
+    where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'x isize>
+{
+    // not ok for tuple, two lifetimes and we pick first
+}
+
+fn tuple_two<T>()
+    where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'y isize>
+{
+    // not ok for tuple, two lifetimes and we pick second
+}
+
+fn tuple_three<T>()
+    where T : for<'x> TheTrait<(&'x isize, &'x isize), A = &'x isize>
+{
+    // ok for tuple
+}
+
+fn tuple_four<T>()
+    where T : for<'x,'y> TheTrait<(&'x isize, &'y isize)>
+{
+    // not ok for tuple, two lifetimes, and lifetime matching is invariant
+}
+
+pub fn call_foo() {
+    foo::<IntStruct>();
+    foo::<UintStruct>(); //~ ERROR type mismatch
+}
+
+pub fn call_bar() {
+    bar::<IntStruct>(); //~ ERROR type mismatch
+    bar::<UintStruct>();
+}
+
+pub fn call_tuple_one() {
+    tuple_one::<Tuple>();
+    //~^ ERROR not satisfied
+    //~| ERROR type mismatch
+}
+
+pub fn call_tuple_two() {
+    tuple_two::<Tuple>();
+    //~^ ERROR not satisfied
+    //~| ERROR type mismatch
+}
+
+pub fn call_tuple_three() {
+    tuple_three::<Tuple>();
+}
+
+pub fn call_tuple_four() {
+    tuple_four::<Tuple>();
+    //~^ ERROR not satisfied
+}
+
+fn main() { }
diff --git a/src/test/ui/associated-types/associated-types-eq-hr.stderr b/src/test/ui/associated-types/associated-types-eq-hr.stderr
new file mode 100644
index 0000000..82d15b9
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-eq-hr.stderr
@@ -0,0 +1,126 @@
+error[E0271]: type mismatch resolving `for<'x> <UintStruct as TheTrait<&'x isize>>::A == &'x isize`
+  --> $DIR/associated-types-eq-hr.rs:82:5
+   |
+LL |     foo::<UintStruct>();
+   |     ^^^^^^^^^^^^^^^^^ expected usize, found isize
+   |
+   = note: expected type `&usize`
+              found type `&isize`
+note: required by `foo`
+  --> $DIR/associated-types-eq-hr.rs:44:1
+   |
+LL | / fn foo<T>()
+LL | |     where T : for<'x> TheTrait<&'x isize, A = &'x isize>
+LL | | {
+LL | |     // ok for IntStruct, but not UintStruct
+LL | | }
+   | |_^
+
+error[E0271]: type mismatch resolving `for<'x> <IntStruct as TheTrait<&'x isize>>::A == &'x usize`
+  --> $DIR/associated-types-eq-hr.rs:86:5
+   |
+LL |     bar::<IntStruct>();
+   |     ^^^^^^^^^^^^^^^^ expected isize, found usize
+   |
+   = note: expected type `&isize`
+              found type `&usize`
+note: required by `bar`
+  --> $DIR/associated-types-eq-hr.rs:50:1
+   |
+LL | / fn bar<T>()
+LL | |     where T : for<'x> TheTrait<&'x isize, A = &'x usize>
+LL | | {
+LL | |     // ok for UintStruct, but not IntStruct
+LL | | }
+   | |_^
+
+error[E0277]: the trait bound `for<'x, 'y> Tuple: TheTrait<(&'x isize, &'y isize)>` is not satisfied
+  --> $DIR/associated-types-eq-hr.rs:91:5
+   |
+LL |     tuple_one::<Tuple>();
+   |     ^^^^^^^^^^^^^^^^^^ the trait `for<'x, 'y> TheTrait<(&'x isize, &'y isize)>` is not implemented for `Tuple`
+   |
+   = help: the following implementations were found:
+             <Tuple as TheTrait<(&'a isize, &'a isize)>>
+note: required by `tuple_one`
+  --> $DIR/associated-types-eq-hr.rs:56:1
+   |
+LL | / fn tuple_one<T>()
+LL | |     where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'x isize>
+LL | | {
+LL | |     // not ok for tuple, two lifetimes and we pick first
+LL | | }
+   | |_^
+
+error[E0271]: type mismatch resolving `for<'x, 'y> <Tuple as TheTrait<(&'x isize, &'y isize)>>::A == &'x isize`
+  --> $DIR/associated-types-eq-hr.rs:91:5
+   |
+LL |     tuple_one::<Tuple>();
+   |     ^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'x, found concrete lifetime
+   |
+note: required by `tuple_one`
+  --> $DIR/associated-types-eq-hr.rs:56:1
+   |
+LL | / fn tuple_one<T>()
+LL | |     where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'x isize>
+LL | | {
+LL | |     // not ok for tuple, two lifetimes and we pick first
+LL | | }
+   | |_^
+
+error[E0277]: the trait bound `for<'x, 'y> Tuple: TheTrait<(&'x isize, &'y isize)>` is not satisfied
+  --> $DIR/associated-types-eq-hr.rs:97:5
+   |
+LL |     tuple_two::<Tuple>();
+   |     ^^^^^^^^^^^^^^^^^^ the trait `for<'x, 'y> TheTrait<(&'x isize, &'y isize)>` is not implemented for `Tuple`
+   |
+   = help: the following implementations were found:
+             <Tuple as TheTrait<(&'a isize, &'a isize)>>
+note: required by `tuple_two`
+  --> $DIR/associated-types-eq-hr.rs:62:1
+   |
+LL | / fn tuple_two<T>()
+LL | |     where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'y isize>
+LL | | {
+LL | |     // not ok for tuple, two lifetimes and we pick second
+LL | | }
+   | |_^
+
+error[E0271]: type mismatch resolving `for<'x, 'y> <Tuple as TheTrait<(&'x isize, &'y isize)>>::A == &'y isize`
+  --> $DIR/associated-types-eq-hr.rs:97:5
+   |
+LL |     tuple_two::<Tuple>();
+   |     ^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'x, found concrete lifetime
+   |
+note: required by `tuple_two`
+  --> $DIR/associated-types-eq-hr.rs:62:1
+   |
+LL | / fn tuple_two<T>()
+LL | |     where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'y isize>
+LL | | {
+LL | |     // not ok for tuple, two lifetimes and we pick second
+LL | | }
+   | |_^
+
+error[E0277]: the trait bound `for<'x, 'y> Tuple: TheTrait<(&'x isize, &'y isize)>` is not satisfied
+  --> $DIR/associated-types-eq-hr.rs:107:5
+   |
+LL |     tuple_four::<Tuple>();
+   |     ^^^^^^^^^^^^^^^^^^^ the trait `for<'x, 'y> TheTrait<(&'x isize, &'y isize)>` is not implemented for `Tuple`
+   |
+   = help: the following implementations were found:
+             <Tuple as TheTrait<(&'a isize, &'a isize)>>
+note: required by `tuple_four`
+  --> $DIR/associated-types-eq-hr.rs:74:1
+   |
+LL | / fn tuple_four<T>()
+LL | |     where T : for<'x,'y> TheTrait<(&'x isize, &'y isize)>
+LL | | {
+LL | |     // not ok for tuple, two lifetimes, and lifetime matching is invariant
+LL | | }
+   | |_^
+
+error: aborting due to 7 previous errors
+
+Some errors occurred: E0271, E0277.
+For more information about an error, try `rustc --explain E0271`.
diff --git a/src/test/ui/associated-types/associated-types-for-unimpl-trait.rs b/src/test/ui/associated-types/associated-types-for-unimpl-trait.rs
new file mode 100644
index 0000000..5b10d1d
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-for-unimpl-trait.rs
@@ -0,0 +1,12 @@
+trait Get {
+    type Value;
+    fn get(&self) -> <Self as Get>::Value;
+}
+
+trait Other {
+    fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {}
+    //~^ ERROR the trait bound `Self: Get` is not satisfied
+}
+
+fn main() {
+}
diff --git a/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr b/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr
new file mode 100644
index 0000000..9f03368
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr
@@ -0,0 +1,11 @@
+error[E0277]: the trait bound `Self: Get` is not satisfied
+  --> $DIR/associated-types-for-unimpl-trait.rs:7:5
+   |
+LL |     fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
+   |
+   = help: consider adding a `where Self: Get` bound
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/associated-types/associated-types-in-ambiguous-context.rs b/src/test/ui/associated-types/associated-types-in-ambiguous-context.rs
new file mode 100644
index 0000000..1b1ea9d
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-in-ambiguous-context.rs
@@ -0,0 +1,19 @@
+trait Get {
+    type Value;
+    fn get(&self) -> <Self as Get>::Value;
+}
+
+fn get<T:Get,U:Get>(x: T, y: U) -> Get::Value {}
+//~^ ERROR ambiguous associated type
+
+trait Grab {
+    type Value;
+    fn grab(&self) -> Grab::Value;
+    //~^ ERROR ambiguous associated type
+}
+
+type X = std::ops::Deref::Target;
+//~^ ERROR ambiguous associated type
+
+fn main() {
+}
diff --git a/src/test/ui/associated-types/associated-types-in-ambiguous-context.stderr b/src/test/ui/associated-types/associated-types-in-ambiguous-context.stderr
new file mode 100644
index 0000000..83667b5
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-in-ambiguous-context.stderr
@@ -0,0 +1,21 @@
+error[E0223]: ambiguous associated type
+  --> $DIR/associated-types-in-ambiguous-context.rs:6:36
+   |
+LL | fn get<T:Get,U:Get>(x: T, y: U) -> Get::Value {}
+   |                                    ^^^^^^^^^^ help: use fully-qualified syntax: `<Type as Get>::Value`
+
+error[E0223]: ambiguous associated type
+  --> $DIR/associated-types-in-ambiguous-context.rs:15:10
+   |
+LL | type X = std::ops::Deref::Target;
+   |          ^^^^^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<Type as std::ops::Deref>::Target`
+
+error[E0223]: ambiguous associated type
+  --> $DIR/associated-types-in-ambiguous-context.rs:11:23
+   |
+LL |     fn grab(&self) -> Grab::Value;
+   |                       ^^^^^^^^^^^ help: use fully-qualified syntax: `<Type as Grab>::Value`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0223`.
diff --git a/src/test/ui/associated-types/associated-types-incomplete-object.rs b/src/test/ui/associated-types/associated-types-incomplete-object.rs
new file mode 100644
index 0000000..c93f3be
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-incomplete-object.rs
@@ -0,0 +1,31 @@
+// Check that the user gets an error if they omit a binding from an
+// object type.
+
+pub trait Foo {
+    type A;
+    type B;
+    fn boo(&self) -> <Self as Foo>::A;
+}
+
+struct Bar;
+
+impl Foo for isize {
+    type A = usize;
+    type B = char;
+    fn boo(&self) -> usize {
+        42
+    }
+}
+
+pub fn main() {
+    let a = &42isize as &Foo<A=usize, B=char>;
+
+    let b = &42isize as &Foo<A=usize>;
+    //~^ ERROR the value of the associated type `B` (from the trait `Foo`) must be specified
+
+    let c = &42isize as &Foo<B=char>;
+    //~^ ERROR the value of the associated type `A` (from the trait `Foo`) must be specified
+
+    let d = &42isize as &Foo;
+    //~^ ERROR the value of the associated types `A` (from the trait `Foo`), `B` (from the trait
+}
diff --git a/src/test/ui/associated-types/associated-types-incomplete-object.stderr b/src/test/ui/associated-types/associated-types-incomplete-object.stderr
new file mode 100644
index 0000000..d152e02
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-incomplete-object.stderr
@@ -0,0 +1,35 @@
+error[E0191]: the value of the associated type `B` (from the trait `Foo`) must be specified
+  --> $DIR/associated-types-incomplete-object.rs:23:26
+   |
+LL |     type B;
+   |     ------- `B` defined here
+...
+LL |     let b = &42isize as &Foo<A=usize>;
+   |                          ^^^^^^^^^^^^ associated type `B` must be specified
+
+error[E0191]: the value of the associated type `A` (from the trait `Foo`) must be specified
+  --> $DIR/associated-types-incomplete-object.rs:26:26
+   |
+LL |     type A;
+   |     ------- `A` defined here
+...
+LL |     let c = &42isize as &Foo<B=char>;
+   |                          ^^^^^^^^^^^ associated type `A` must be specified
+
+error[E0191]: the value of the associated types `A` (from the trait `Foo`), `B` (from the trait `Foo`) must be specified
+  --> $DIR/associated-types-incomplete-object.rs:29:26
+   |
+LL |     type A;
+   |     ------- `A` defined here
+LL |     type B;
+   |     ------- `B` defined here
+...
+LL |     let d = &42isize as &Foo;
+   |                          ^^^
+   |                          |
+   |                          associated type `A` must be specified
+   |                          associated type `B` must be specified
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0191`.
diff --git a/src/test/ui/associated-types/associated-types-invalid-trait-ref-issue-18865.rs b/src/test/ui/associated-types/associated-types-invalid-trait-ref-issue-18865.rs
new file mode 100644
index 0000000..3bd3f3a
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-invalid-trait-ref-issue-18865.rs
@@ -0,0 +1,14 @@
+// Test that we report an error if the trait ref in a qualified type
+// uses invalid type arguments.
+
+trait Foo<T> {
+    type Bar;
+    fn get_bar(&self) -> Self::Bar;
+}
+
+fn f<T:Foo<isize>>(t: &T) {
+    let u: <T as Foo<usize>>::Bar = t.get_bar();
+    //~^ ERROR the trait bound `T: Foo<usize>` is not satisfied
+}
+
+fn main() { }
diff --git a/src/test/ui/associated-types/associated-types-invalid-trait-ref-issue-18865.stderr b/src/test/ui/associated-types/associated-types-invalid-trait-ref-issue-18865.stderr
new file mode 100644
index 0000000..01f66a1
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-invalid-trait-ref-issue-18865.stderr
@@ -0,0 +1,11 @@
+error[E0277]: the trait bound `T: Foo<usize>` is not satisfied
+  --> $DIR/associated-types-invalid-trait-ref-issue-18865.rs:10:12
+   |
+LL |     let u: <T as Foo<usize>>::Bar = t.get_bar();
+   |            ^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo<usize>` is not implemented for `T`
+   |
+   = help: consider adding a `where T: Foo<usize>` bound
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/associated-types/associated-types-issue-17359.rs b/src/test/ui/associated-types/associated-types-issue-17359.rs
new file mode 100644
index 0000000..88a8a64
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-issue-17359.rs
@@ -0,0 +1,10 @@
+// Test that we do not ICE when an impl is missing an associated type (and that we report
+// a useful error, of course).
+
+trait Trait {
+    type Type;
+}
+
+impl Trait for isize {}  //~ ERROR missing: `Type`
+
+fn main() {}
diff --git a/src/test/ui/associated-types/associated-types-issue-17359.stderr b/src/test/ui/associated-types/associated-types-issue-17359.stderr
new file mode 100644
index 0000000..575a072
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-issue-17359.stderr
@@ -0,0 +1,12 @@
+error[E0046]: not all trait items implemented, missing: `Type`
+  --> $DIR/associated-types-issue-17359.rs:8:1
+   |
+LL |     type Type;
+   |     ---------- `Type` from trait
+...
+LL | impl Trait for isize {}
+   | ^^^^^^^^^^^^^^^^^^^^ missing `Type` in implementation
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0046`.
diff --git a/src/test/ui/associated-types/associated-types-issue-20346.rs b/src/test/ui/associated-types/associated-types-issue-20346.rs
new file mode 100644
index 0000000..0cce847
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-issue-20346.rs
@@ -0,0 +1,35 @@
+// Test that we reliably check the value of the associated type.
+
+#![crate_type = "lib"]
+#![no_implicit_prelude]
+
+use std::option::Option::{self, None, Some};
+use std::vec::Vec;
+
+trait Iterator {
+    type Item;
+
+    fn next(&mut self) -> Option<Self::Item>;
+}
+
+fn is_iterator_of<A, I: Iterator<Item=A>>(_: &I) {}
+
+struct Adapter<I> {
+    iter: I,
+    found_none: bool,
+}
+
+impl<T, I> Iterator for Adapter<I> where I: Iterator<Item=Option<T>> {
+    type Item = T;
+
+    fn next(&mut self) -> Option<T> {
+        loop {}
+    }
+}
+
+fn test_adapter<T, I: Iterator<Item=Option<T>>>(it: I) {
+    is_iterator_of::<Option<T>, _>(&it);  // Sanity check
+    let adapter = Adapter { iter: it, found_none: false };
+    is_iterator_of::<T, _>(&adapter); // OK
+    is_iterator_of::<Option<T>, _>(&adapter); //~ ERROR type mismatch
+}
diff --git a/src/test/ui/associated-types/associated-types-issue-20346.stderr b/src/test/ui/associated-types/associated-types-issue-20346.stderr
new file mode 100644
index 0000000..7d5b16c
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-issue-20346.stderr
@@ -0,0 +1,17 @@
+error[E0271]: type mismatch resolving `<Adapter<I> as Iterator>::Item == std::option::Option<T>`
+  --> $DIR/associated-types-issue-20346.rs:34:5
+   |
+LL |     is_iterator_of::<Option<T>, _>(&adapter);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter, found enum `std::option::Option`
+   |
+   = note: expected type `T`
+              found type `std::option::Option<T>`
+note: required by `is_iterator_of`
+  --> $DIR/associated-types-issue-20346.rs:15:1
+   |
+LL | fn is_iterator_of<A, I: Iterator<Item=A>>(_: &I) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/associated-types/associated-types-multiple-types-one-trait.rs b/src/test/ui/associated-types/associated-types-multiple-types-one-trait.rs
new file mode 100644
index 0000000..daeaf90
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-multiple-types-one-trait.rs
@@ -0,0 +1,46 @@
+trait Foo {
+    type X;
+    type Y;
+}
+
+fn have_x_want_x<T:Foo<X=u32>>(t: &T)
+{
+    want_x(t);
+}
+
+fn have_x_want_y<T:Foo<X=u32>>(t: &T)
+{
+    want_y(t); //~ ERROR type mismatch
+}
+
+fn have_y_want_x<T:Foo<Y=i32>>(t: &T)
+{
+    want_x(t); //~ ERROR type mismatch
+}
+
+fn have_y_want_y<T:Foo<Y=i32>>(t: &T)
+{
+    want_y(t);
+}
+
+fn have_xy_want_x<T:Foo<X=u32,Y=i32>>(t: &T)
+{
+    want_x(t);
+}
+
+fn have_xy_want_y<T:Foo<X=u32,Y=i32>>(t: &T)
+{
+    want_y(t);
+}
+
+fn have_xy_want_xy<T:Foo<X=u32,Y=i32>>(t: &T)
+{
+    want_x(t);
+    want_y(t);
+}
+
+fn want_x<T:Foo<X=u32>>(t: &T) { }
+
+fn want_y<T:Foo<Y=i32>>(t: &T) { }
+
+fn main() { }
diff --git a/src/test/ui/associated-types/associated-types-multiple-types-one-trait.stderr b/src/test/ui/associated-types/associated-types-multiple-types-one-trait.stderr
new file mode 100644
index 0000000..2926bda
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-multiple-types-one-trait.stderr
@@ -0,0 +1,31 @@
+error[E0271]: type mismatch resolving `<T as Foo>::Y == i32`
+  --> $DIR/associated-types-multiple-types-one-trait.rs:13:5
+   |
+LL |     want_y(t);
+   |     ^^^^^^ expected associated type, found i32
+   |
+   = note: expected type `<T as Foo>::Y`
+              found type `i32`
+note: required by `want_y`
+  --> $DIR/associated-types-multiple-types-one-trait.rs:44:1
+   |
+LL | fn want_y<T:Foo<Y=i32>>(t: &T) { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0271]: type mismatch resolving `<T as Foo>::X == u32`
+  --> $DIR/associated-types-multiple-types-one-trait.rs:18:5
+   |
+LL |     want_x(t);
+   |     ^^^^^^ expected associated type, found u32
+   |
+   = note: expected type `<T as Foo>::X`
+              found type `u32`
+note: required by `want_x`
+  --> $DIR/associated-types-multiple-types-one-trait.rs:42:1
+   |
+LL | fn want_x<T:Foo<X=u32>>(t: &T) { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/associated-types/associated-types-no-suitable-bound.rs b/src/test/ui/associated-types/associated-types-no-suitable-bound.rs
new file mode 100644
index 0000000..d42460a
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-no-suitable-bound.rs
@@ -0,0 +1,16 @@
+trait Get {
+    type Value;
+    fn get(&self) -> <Self as Get>::Value;
+}
+
+struct Struct {
+    x: isize,
+}
+
+impl Struct {
+    fn uhoh<T>(foo: <T as Get>::Value) {}
+    //~^ ERROR the trait bound `T: Get` is not satisfied
+}
+
+fn main() {
+}
diff --git a/src/test/ui/associated-types/associated-types-no-suitable-bound.stderr b/src/test/ui/associated-types/associated-types-no-suitable-bound.stderr
new file mode 100644
index 0000000..ada9cac
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-no-suitable-bound.stderr
@@ -0,0 +1,11 @@
+error[E0277]: the trait bound `T: Get` is not satisfied
+  --> $DIR/associated-types-no-suitable-bound.rs:11:5
+   |
+LL |     fn uhoh<T>(foo: <T as Get>::Value) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `T`
+   |
+   = help: consider adding a `where T: Get` bound
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.rs b/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.rs
new file mode 100644
index 0000000..17dfa17
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.rs
@@ -0,0 +1,21 @@
+// Check that we get an error when you use `<Self as Get>::Value` in
+// the trait definition but `Self` does not, in fact, implement `Get`.
+//
+// See also associated-types-no-suitable-supertrait.rs, which checks
+// that we see the same error when making this mistake on an impl
+// rather than the default method impl.
+//
+// See also run-pass/associated-types-projection-to-unrelated-trait.rs,
+// which checks that the trait interface itself is not considered an
+// error as long as all impls satisfy the constraint.
+
+trait Get {
+    type Value;
+}
+
+trait Other {
+    fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {}
+    //~^ ERROR the trait bound `Self: Get` is not satisfied
+}
+
+fn main() { }
diff --git a/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr b/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr
new file mode 100644
index 0000000..56cd6d0
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr
@@ -0,0 +1,11 @@
+error[E0277]: the trait bound `Self: Get` is not satisfied
+  --> $DIR/associated-types-no-suitable-supertrait-2.rs:17:5
+   |
+LL |     fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
+   |
+   = help: consider adding a `where Self: Get` bound
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/associated-types/associated-types-no-suitable-supertrait.rs b/src/test/ui/associated-types/associated-types-no-suitable-supertrait.rs
new file mode 100644
index 0000000..c373c58
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-no-suitable-supertrait.rs
@@ -0,0 +1,26 @@
+// Check that we get an error when you use `<Self as Get>::Value` in
+// the trait definition but `Self` does not, in fact, implement `Get`.
+//
+// See also associated-types-no-suitable-supertrait-2.rs, which checks
+// that we see the same error if we get around to checking the default
+// method body.
+//
+// See also run-pass/associated-types-projection-to-unrelated-trait.rs,
+// which checks that the trait interface itself is not considered an
+// error as long as all impls satisfy the constraint.
+
+trait Get {
+    type Value;
+}
+
+trait Other {
+    fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {}
+    //~^ ERROR the trait bound `Self: Get` is not satisfied
+}
+
+impl<T:Get> Other for T {
+    fn uhoh<U:Get>(&self, foo: U, bar: <(T, U) as Get>::Value) {}
+    //~^ ERROR the trait bound `(T, U): Get` is not satisfied
+}
+
+fn main() { }
diff --git a/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr b/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr
new file mode 100644
index 0000000..71175d3
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr
@@ -0,0 +1,17 @@
+error[E0277]: the trait bound `Self: Get` is not satisfied
+  --> $DIR/associated-types-no-suitable-supertrait.rs:17:5
+   |
+LL |     fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
+   |
+   = help: consider adding a `where Self: Get` bound
+
+error[E0277]: the trait bound `(T, U): Get` is not satisfied
+  --> $DIR/associated-types-no-suitable-supertrait.rs:22:5
+   |
+LL |     fn uhoh<U:Get>(&self, foo: U, bar: <(T, U) as Get>::Value) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `(T, U)`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/associated-types/associated-types-outlives.nll.stderr b/src/test/ui/associated-types/associated-types-outlives.nll.stderr
new file mode 100644
index 0000000..840e33b
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-outlives.nll.stderr
@@ -0,0 +1,13 @@
+error[E0505]: cannot move out of `x` because it is borrowed
+  --> $DIR/associated-types-outlives.rs:22:14
+   |
+LL |         's: loop { y = denormalise(&x); break }
+   |                                    -- borrow of `x` occurs here
+LL |         drop(x);
+   |              ^ move out of `x` occurs here
+LL |         return f(y);
+   |                  - borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0505`.
diff --git a/src/test/ui/associated-types/associated-types-outlives.rs b/src/test/ui/associated-types/associated-types-outlives.rs
new file mode 100644
index 0000000..55c2762
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-outlives.rs
@@ -0,0 +1,28 @@
+// Regression test for issue #24622. The older associated types code
+// was erroneously assuming that all projections outlived the current
+// fn body, causing this (invalid) code to be accepted.
+
+pub trait Foo<'a> {
+    type Bar;
+}
+
+impl<'a, T:'a> Foo<'a> for T {
+    type Bar = &'a T;
+}
+
+fn denormalise<'a, T>(t: &'a T) -> <T as Foo<'a>>::Bar {
+    t
+}
+
+pub fn free_and_use<T: for<'a> Foo<'a>,
+                    F: for<'a> FnOnce(<T as Foo<'a>>::Bar)>(x: T, f: F) {
+    let y;
+    'body: loop { // lifetime annotations added for clarity
+        's: loop { y = denormalise(&x); break }
+        drop(x); //~ ERROR cannot move out of `x` because it is borrowed
+        return f(y);
+    }
+}
+
+pub fn main() {
+}
diff --git a/src/test/ui/associated-types/associated-types-outlives.stderr b/src/test/ui/associated-types/associated-types-outlives.stderr
new file mode 100644
index 0000000..e35862d
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-outlives.stderr
@@ -0,0 +1,11 @@
+error[E0505]: cannot move out of `x` because it is borrowed
+  --> $DIR/associated-types-outlives.rs:22:14
+   |
+LL |         's: loop { y = denormalise(&x); break }
+   |                                     - borrow of `x` occurs here
+LL |         drop(x);
+   |              ^ move out of `x` occurs here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0505`.
diff --git a/src/test/ui/associated-types/associated-types-overridden-binding-2.rs b/src/test/ui/associated-types/associated-types-overridden-binding-2.rs
new file mode 100644
index 0000000..7467f33
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-overridden-binding-2.rs
@@ -0,0 +1,8 @@
+#![feature(trait_alias)]
+
+trait I32Iterator = Iterator<Item = i32>;
+
+fn main() {
+    let _: &I32Iterator<Item = u32> = &vec![42].into_iter();
+    //~^ ERROR type mismatch
+}
diff --git a/src/test/ui/associated-types/associated-types-overridden-binding-2.stderr b/src/test/ui/associated-types/associated-types-overridden-binding-2.stderr
new file mode 100644
index 0000000..ad0b651
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-overridden-binding-2.stderr
@@ -0,0 +1,13 @@
+error[E0271]: type mismatch resolving `<std::vec::IntoIter<u32> as std::iter::Iterator>::Item == i32`
+  --> $DIR/associated-types-overridden-binding-2.rs:6:39
+   |
+LL |     let _: &I32Iterator<Item = u32> = &vec![42].into_iter();
+   |                                       ^^^^^^^^^^^^^^^^^^^^^ expected u32, found i32
+   |
+   = note: expected type `u32`
+              found type `i32`
+   = note: required for the cast to the object type `dyn I32Iterator<Item = u32, Item = i32>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/associated-types/associated-types-overridden-binding.rs b/src/test/ui/associated-types/associated-types-overridden-binding.rs
new file mode 100644
index 0000000..ea3a61b
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-overridden-binding.rs
@@ -0,0 +1,11 @@
+#![feature(trait_alias)]
+
+trait Foo: Iterator<Item = i32> {}
+trait Bar: Foo<Item = u32> {} //~ ERROR type annotations required
+
+trait I32Iterator = Iterator<Item = i32>;
+trait U32Iterator = I32Iterator<Item = u32>;
+
+fn main() {
+    let _: &I32Iterator<Item = u32>;
+}
diff --git a/src/test/ui/associated-types/associated-types-overridden-binding.stderr b/src/test/ui/associated-types/associated-types-overridden-binding.stderr
new file mode 100644
index 0000000..a26ee23
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-overridden-binding.stderr
@@ -0,0 +1,15 @@
+error[E0284]: type annotations required: cannot resolve `<Self as std::iter::Iterator>::Item == i32`
+  --> $DIR/associated-types-overridden-binding.rs:4:1
+   |
+LL | trait Bar: Foo<Item = u32> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: required by `Foo`
+  --> $DIR/associated-types-overridden-binding.rs:3:1
+   |
+LL | trait Foo: Iterator<Item = i32> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0284`.
diff --git a/src/test/ui/associated-types/associated-types-overridden-default.rs b/src/test/ui/associated-types/associated-types-overridden-default.rs
new file mode 100644
index 0000000..629fc7a
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-overridden-default.rs
@@ -0,0 +1,15 @@
+#![feature(associated_type_defaults)]
+
+pub trait Tr {
+    type Assoc = u8;
+    type Assoc2 = Self::Assoc;
+    const C: u8 = 11;
+    fn foo(&self) {}
+}
+
+impl Tr for () {
+    type Assoc = ();
+    //~^ ERROR need to be reimplemented as `Assoc` was overridden: `Assoc2`, `C`, `foo`
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-types/associated-types-overridden-default.stderr b/src/test/ui/associated-types/associated-types-overridden-default.stderr
new file mode 100644
index 0000000..79fb9a6
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-overridden-default.stderr
@@ -0,0 +1,9 @@
+error[E0399]: the following trait items need to be reimplemented as `Assoc` was overridden: `Assoc2`, `C`, `foo`
+  --> $DIR/associated-types-overridden-default.rs:11:5
+   |
+LL |     type Assoc = ();
+   |     ^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0399`.
diff --git a/src/test/ui/associated-types/associated-types-path-1.rs b/src/test/ui/associated-types/associated-types-path-1.rs
new file mode 100644
index 0000000..46a5c9e
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-path-1.rs
@@ -0,0 +1,13 @@
+// Test that we have one and only one associated type per ref.
+
+pub trait Foo {
+    type A;
+}
+pub trait Bar {
+    type A;
+}
+
+pub fn f1<T>(a: T, x: T::A) {} //~ERROR associated type `A` not found
+pub fn f2<T: Foo + Bar>(a: T, x: T::A) {} //~ERROR ambiguous associated type `A`
+
+pub fn main() {}
diff --git a/src/test/ui/associated-types/associated-types-path-1.stderr b/src/test/ui/associated-types/associated-types-path-1.stderr
new file mode 100644
index 0000000..b6d3b53
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-path-1.stderr
@@ -0,0 +1,22 @@
+error[E0220]: associated type `A` not found for `T`
+  --> $DIR/associated-types-path-1.rs:10:23
+   |
+LL | pub fn f1<T>(a: T, x: T::A) {}
+   |                       ^^^^ associated type `A` not found
+
+error[E0221]: ambiguous associated type `A` in bounds of `T`
+  --> $DIR/associated-types-path-1.rs:11:34
+   |
+LL |     type A;
+   |     ------- ambiguous `A` from `Foo`
+...
+LL |     type A;
+   |     ------- ambiguous `A` from `Bar`
+...
+LL | pub fn f2<T: Foo + Bar>(a: T, x: T::A) {}
+   |                                  ^^^^ ambiguous associated type `A`
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0220, E0221.
+For more information about an error, try `rustc --explain E0220`.
diff --git a/src/test/ui/associated-types/associated-types-path-2.rs b/src/test/ui/associated-types/associated-types-path-2.rs
new file mode 100644
index 0000000..b28b60e
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-path-2.rs
@@ -0,0 +1,46 @@
+// Test type checking of uses of associated types via sugary paths.
+
+pub trait Foo {
+    type A;
+
+    fn dummy(&self) { }
+}
+
+impl Foo for i32 {
+    type A = u32;
+}
+
+pub fn f1<T: Foo>(a: T, x: T::A) {}
+pub fn f2<T: Foo>(a: T) -> T::A {
+    panic!();
+}
+
+pub fn f1_int_int() {
+    f1(2i32, 4i32);
+    //~^ ERROR mismatched types
+    //~| expected u32, found i32
+}
+
+pub fn f1_int_uint() {
+    f1(2i32, 4u32);
+}
+
+pub fn f1_uint_uint() {
+    f1(2u32, 4u32);
+    //~^ ERROR `u32: Foo` is not satisfied
+    //~| ERROR `u32: Foo` is not satisfied
+}
+
+pub fn f1_uint_int() {
+    f1(2u32, 4i32);
+    //~^ ERROR `u32: Foo` is not satisfied
+    //~| ERROR `u32: Foo` is not satisfied
+}
+
+pub fn f2_int() {
+    let _: i32 = f2(2i32);
+    //~^ ERROR mismatched types
+    //~| expected i32, found u32
+}
+
+pub fn main() { }
diff --git a/src/test/ui/associated-types/associated-types-path-2.stderr b/src/test/ui/associated-types/associated-types-path-2.stderr
new file mode 100644
index 0000000..be7097a
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-path-2.stderr
@@ -0,0 +1,52 @@
+error[E0308]: mismatched types
+  --> $DIR/associated-types-path-2.rs:19:14
+   |
+LL |     f1(2i32, 4i32);
+   |              ^^^^ expected u32, found i32
+
+error[E0277]: the trait bound `u32: Foo` is not satisfied
+  --> $DIR/associated-types-path-2.rs:29:5
+   |
+LL |     f1(2u32, 4u32);
+   |     ^^ the trait `Foo` is not implemented for `u32`
+   |
+note: required by `f1`
+  --> $DIR/associated-types-path-2.rs:13:1
+   |
+LL | pub fn f1<T: Foo>(a: T, x: T::A) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `u32: Foo` is not satisfied
+  --> $DIR/associated-types-path-2.rs:29:5
+   |
+LL |     f1(2u32, 4u32);
+   |     ^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `u32`
+
+error[E0277]: the trait bound `u32: Foo` is not satisfied
+  --> $DIR/associated-types-path-2.rs:35:5
+   |
+LL |     f1(2u32, 4i32);
+   |     ^^ the trait `Foo` is not implemented for `u32`
+   |
+note: required by `f1`
+  --> $DIR/associated-types-path-2.rs:13:1
+   |
+LL | pub fn f1<T: Foo>(a: T, x: T::A) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `u32: Foo` is not satisfied
+  --> $DIR/associated-types-path-2.rs:35:5
+   |
+LL |     f1(2u32, 4i32);
+   |     ^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `u32`
+
+error[E0308]: mismatched types
+  --> $DIR/associated-types-path-2.rs:41:18
+   |
+LL |     let _: i32 = f2(2i32);
+   |                  ^^^^^^^^ expected i32, found u32
+
+error: aborting due to 6 previous errors
+
+Some errors occurred: E0277, E0308.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/associated-types/associated-types-project-from-hrtb-in-fn-body.rs b/src/test/ui/associated-types/associated-types-project-from-hrtb-in-fn-body.rs
new file mode 100644
index 0000000..9434a88
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-project-from-hrtb-in-fn-body.rs
@@ -0,0 +1,26 @@
+// Check projection of an associated type out of a higher-ranked
+// trait-bound in the context of a function body.
+
+pub trait Foo<T> {
+    type A;
+
+    fn get(&self, t: T) -> Self::A;
+}
+
+fn foo<'a, I : for<'x> Foo<&'x isize>>(
+    x: <I as Foo<&'a isize>>::A)
+{
+    let y: I::A = x;
+}
+
+fn bar<'a, 'b, I : for<'x> Foo<&'x isize>>(
+    x: <I as Foo<&'a isize>>::A,
+    y: <I as Foo<&'b isize>>::A,
+    cond: bool)
+{
+    // x and y here have two distinct lifetimes:
+    let z: I::A = if cond { x } else { y };
+    //~^ ERROR lifetime mismatch
+}
+
+pub fn main() {}
diff --git a/src/test/ui/associated-types/associated-types-project-from-hrtb-in-fn-body.stderr b/src/test/ui/associated-types/associated-types-project-from-hrtb-in-fn-body.stderr
new file mode 100644
index 0000000..d5310c4
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-project-from-hrtb-in-fn-body.stderr
@@ -0,0 +1,14 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/associated-types-project-from-hrtb-in-fn-body.rs:22:40
+   |
+LL |     x: <I as Foo<&'a isize>>::A,
+   |                  --------- these two types are declared with different lifetimes...
+LL |     y: <I as Foo<&'b isize>>::A,
+   |                  ---------
+...
+LL |     let z: I::A = if cond { x } else { y };
+   |                                        ^ ...but data from `x` flows into `y` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/associated-types/associated-types-project-from-hrtb-in-fn.rs b/src/test/ui/associated-types/associated-types-project-from-hrtb-in-fn.rs
new file mode 100644
index 0000000..bf13c41
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-project-from-hrtb-in-fn.rs
@@ -0,0 +1,35 @@
+// Check projection of an associated type out of a higher-ranked trait-bound
+// in the context of a function signature.
+
+pub trait Foo<T> {
+    type A;
+
+    fn get(&self, t: T) -> Self::A;
+}
+
+fn foo2<I : for<'x> Foo<&'x isize>>(
+    x: I::A)
+    //~^ ERROR cannot extract an associated type from a higher-ranked trait bound in this context
+{
+    // This case is illegal because we have to instantiate `'x`, and
+    // we don't know what region to instantiate it with.
+    //
+    // This could perhaps be made equivalent to the examples below,
+    // specifically for fn signatures.
+}
+
+fn foo3<I : for<'x> Foo<&'x isize>>(
+    x: <I as Foo<&isize>>::A)
+{
+    // OK, in this case we spelled out the precise regions involved, though we left one of
+    // them anonymous.
+}
+
+fn foo4<'a, I : for<'x> Foo<&'x isize>>(
+    x: <I as Foo<&'a isize>>::A)
+{
+    // OK, in this case we spelled out the precise regions involved.
+}
+
+
+pub fn main() {}
diff --git a/src/test/ui/associated-types/associated-types-project-from-hrtb-in-fn.stderr b/src/test/ui/associated-types/associated-types-project-from-hrtb-in-fn.stderr
new file mode 100644
index 0000000..e06ad64
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-project-from-hrtb-in-fn.stderr
@@ -0,0 +1,9 @@
+error[E0212]: cannot extract an associated type from a higher-ranked trait bound in this context
+  --> $DIR/associated-types-project-from-hrtb-in-fn.rs:11:8
+   |
+LL |     x: I::A)
+   |        ^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0212`.
diff --git a/src/test/ui/associated-types/associated-types-project-from-hrtb-in-struct.rs b/src/test/ui/associated-types/associated-types-project-from-hrtb-in-struct.rs
new file mode 100644
index 0000000..20f11ec
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-project-from-hrtb-in-struct.rs
@@ -0,0 +1,25 @@
+// Check projection of an associated type out of a higher-ranked trait-bound
+// in the context of a struct definition.
+
+pub trait Foo<T> {
+    type A;
+
+    fn get(&self, t: T) -> Self::A;
+}
+
+struct SomeStruct<I : for<'x> Foo<&'x isize>> {
+    field: I::A
+    //~^ ERROR cannot extract an associated type from a higher-ranked trait bound in this context
+}
+
+// FIXME(eddyb) This one doesn't even compile because of the unsupported syntax.
+
+// struct AnotherStruct<I : for<'x> Foo<&'x isize>> {
+//     field: <I as for<'y> Foo<&'y isize>>::A
+// }
+
+struct YetAnotherStruct<'a, I : for<'x> Foo<&'x isize>> {
+    field: <I as Foo<&'a isize>>::A
+}
+
+pub fn main() {}
diff --git a/src/test/ui/associated-types/associated-types-project-from-hrtb-in-struct.stderr b/src/test/ui/associated-types/associated-types-project-from-hrtb-in-struct.stderr
new file mode 100644
index 0000000..4c9b795
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-project-from-hrtb-in-struct.stderr
@@ -0,0 +1,9 @@
+error[E0212]: cannot extract an associated type from a higher-ranked trait bound in this context
+  --> $DIR/associated-types-project-from-hrtb-in-struct.rs:11:12
+   |
+LL |     field: I::A
+   |            ^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0212`.
diff --git a/src/test/ui/associated-types/associated-types-project-from-hrtb-in-trait-method.rs b/src/test/ui/associated-types/associated-types-project-from-hrtb-in-trait-method.rs
new file mode 100644
index 0000000..cb52c2b
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-project-from-hrtb-in-trait-method.rs
@@ -0,0 +1,23 @@
+// Check projection of an associated type out of a higher-ranked trait-bound
+// in the context of a method definition in a trait.
+
+pub trait Foo<T> {
+    type A;
+
+    fn get(&self, t: T) -> Self::A;
+}
+
+trait SomeTrait<I : for<'x> Foo<&'x isize>> {
+    fn some_method(&self, arg: I::A);
+    //~^ ERROR cannot extract an associated type from a higher-ranked trait bound in this context
+}
+
+trait AnotherTrait<I : for<'x> Foo<&'x isize>> {
+    fn some_method(&self, arg: <I as Foo<&isize>>::A);
+}
+
+trait YetAnotherTrait<I : for<'x> Foo<&'x isize>> {
+    fn some_method<'a>(&self, arg: <I as Foo<&'a isize>>::A);
+}
+
+pub fn main() {}
diff --git a/src/test/ui/associated-types/associated-types-project-from-hrtb-in-trait-method.stderr b/src/test/ui/associated-types/associated-types-project-from-hrtb-in-trait-method.stderr
new file mode 100644
index 0000000..445e1b1
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-project-from-hrtb-in-trait-method.stderr
@@ -0,0 +1,9 @@
+error[E0212]: cannot extract an associated type from a higher-ranked trait bound in this context
+  --> $DIR/associated-types-project-from-hrtb-in-trait-method.rs:11:32
+   |
+LL |     fn some_method(&self, arg: I::A);
+   |                                ^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0212`.
diff --git a/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.rs b/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.rs
new file mode 100644
index 0000000..fc38b26
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.rs
@@ -0,0 +1,29 @@
+// Check that we get an error when you use `<Self as Get>::Value` in
+// the trait definition even if there is no default method.
+
+trait Get {
+    type Value;
+}
+
+trait Other {
+    fn okay<U:Get>(&self, foo: U, bar: <Self as Get>::Value);
+    //~^ ERROR E0277
+}
+
+impl Get for () {
+    type Value = f32;
+}
+
+impl Get for f64 {
+    type Value = u32;
+}
+
+impl Other for () {
+    fn okay<U:Get>(&self, _foo: U, _bar: <Self as Get>::Value) { }
+}
+
+impl Other for f64 {
+    fn okay<U:Get>(&self, _foo: U, _bar: <Self as Get>::Value) { }
+}
+
+fn main() { }
diff --git a/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr b/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr
new file mode 100644
index 0000000..a260e37
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr
@@ -0,0 +1,11 @@
+error[E0277]: the trait bound `Self: Get` is not satisfied
+  --> $DIR/associated-types-projection-to-unrelated-trait-in-method-without-default.rs:9:5
+   |
+LL |     fn okay<U:Get>(&self, foo: U, bar: <Self as Get>::Value);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
+   |
+   = help: consider adding a `where Self: Get` bound
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/associated-types/associated-types-subtyping-1.rs b/src/test/ui/associated-types/associated-types-subtyping-1.rs
new file mode 100644
index 0000000..012cffb
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-subtyping-1.rs
@@ -0,0 +1,47 @@
+#![allow(unused_variables)]
+
+fn make_any<T>() -> T {  loop {} }
+
+trait Trait<'a> {
+    type Type;
+
+    fn method(&'a self) { }
+}
+
+fn method1<'a,'b,T>(x: &'a T, y: &'b T)
+    where T : for<'z> Trait<'z>, 'a : 'b
+{
+    // Note that &'static T <: &'a T.
+    let a: <T as Trait<'a>>::Type = make_any();
+    let b: <T as Trait<'b>>::Type = make_any();
+    let _c: <T as Trait<'a>>::Type = a;
+}
+
+fn method2<'a,'b,T>(x: &'a T, y: &'b T)
+    where T : for<'z> Trait<'z>, 'a : 'b
+{
+    // Note that &'static T <: &'a T.
+    let a: <T as Trait<'a>>::Type = make_any();
+    let b: <T as Trait<'b>>::Type = make_any();
+    let _c: <T as Trait<'b>>::Type = a; //~ ERROR E0623
+}
+
+fn method3<'a,'b,T>(x: &'a T, y: &'b T)
+    where T : for<'z> Trait<'z>, 'a : 'b
+{
+    // Note that &'static T <: &'a T.
+    let a: <T as Trait<'a>>::Type = make_any();
+    let b: <T as Trait<'b>>::Type = make_any();
+    let _c: <T as Trait<'a>>::Type = b; //~ ERROR E0623
+}
+
+fn method4<'a,'b,T>(x: &'a T, y: &'b T)
+    where T : for<'z> Trait<'z>, 'a : 'b
+{
+    // Note that &'static T <: &'a T.
+    let a: <T as Trait<'a>>::Type = make_any();
+    let b: <T as Trait<'b>>::Type = make_any();
+    let _c: <T as Trait<'b>>::Type = b;
+}
+
+fn main() { }
diff --git a/src/test/ui/associated-types/associated-types-subtyping-1.stderr b/src/test/ui/associated-types/associated-types-subtyping-1.stderr
new file mode 100644
index 0000000..58ceec9
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-subtyping-1.stderr
@@ -0,0 +1,21 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/associated-types-subtyping-1.rs:26:38
+   |
+LL | fn method2<'a,'b,T>(x: &'a T, y: &'b T)
+   |                        -----     ----- these two types are declared with different lifetimes...
+...
+LL |     let _c: <T as Trait<'b>>::Type = a;
+   |                                      ^ ...but data from `y` flows into `x` here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/associated-types-subtyping-1.rs:35:38
+   |
+LL | fn method3<'a,'b,T>(x: &'a T, y: &'b T)
+   |                        -----     ----- these two types are declared with different lifetimes...
+...
+LL |     let _c: <T as Trait<'a>>::Type = b;
+   |                                      ^ ...but data from `y` flows into `x` here
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/associated-types/associated-types-unconstrained.rs b/src/test/ui/associated-types/associated-types-unconstrained.rs
new file mode 100644
index 0000000..9942483
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-unconstrained.rs
@@ -0,0 +1,16 @@
+// Check that an associated type cannot be bound in an expression path.
+
+trait Foo {
+    type A;
+    fn bar() -> isize;
+}
+
+impl Foo for isize {
+    type A = usize;
+    fn bar() -> isize { 42 }
+}
+
+pub fn main() {
+    let x: isize = Foo::bar();
+    //~^ ERROR type annotations required
+}
diff --git a/src/test/ui/associated-types/associated-types-unconstrained.stderr b/src/test/ui/associated-types/associated-types-unconstrained.stderr
new file mode 100644
index 0000000..da14a69
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-unconstrained.stderr
@@ -0,0 +1,9 @@
+error[E0284]: type annotations required: cannot resolve `<_ as Foo>::A == _`
+  --> $DIR/associated-types-unconstrained.rs:14:20
+   |
+LL |     let x: isize = Foo::bar();
+   |                    ^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0284`.
diff --git a/src/test/ui/associated-types/associated-types-unsized.rs b/src/test/ui/associated-types/associated-types-unsized.rs
new file mode 100644
index 0000000..a9bc24e
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-unsized.rs
@@ -0,0 +1,11 @@
+trait Get {
+    type Value: ?Sized;
+    fn get(&self) -> <Self as Get>::Value;
+}
+
+fn foo<T:Get>(t: T) {
+    let x = t.get(); //~ ERROR the size for values of type
+}
+
+fn main() {
+}
diff --git a/src/test/ui/associated-types/associated-types-unsized.stderr b/src/test/ui/associated-types/associated-types-unsized.stderr
new file mode 100644
index 0000000..b5db974
--- /dev/null
+++ b/src/test/ui/associated-types/associated-types-unsized.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the size for values of type `<T as Get>::Value` cannot be known at compilation time
+  --> $DIR/associated-types-unsized.rs:7:9
+   |
+LL |     let x = t.get();
+   |         ^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `<T as Get>::Value`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = help: consider adding a `where <T as Get>::Value: std::marker::Sized` bound
+   = note: all local variables must have a statically known size
+   = help: unsized locals are gated as an unstable feature
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/associated-types/bound-lifetime-constrained.clause.stderr b/src/test/ui/associated-types/bound-lifetime-constrained.clause.stderr
new file mode 100644
index 0000000..f089f27
--- /dev/null
+++ b/src/test/ui/associated-types/bound-lifetime-constrained.clause.stderr
@@ -0,0 +1,15 @@
+error[E0582]: binding for associated type `Output` references lifetime `'a`, which does not appear in the trait input types
+  --> $DIR/bound-lifetime-constrained.rs:38:63
+   |
+LL | fn clause1<T>() where T: for<'a> Fn(<() as Foo<'a>>::Item) -> &'a i32 {
+   |                                                               ^^^^^^^
+
+error[E0582]: binding for associated type `Output` references lifetime `'a`, which does not appear in the trait input types
+  --> $DIR/bound-lifetime-constrained.rs:43:42
+   |
+LL | fn clause2<T>() where T: for<'a> Fn() -> <() as Foo<'a>>::Item {
+   |                                          ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0582`.
diff --git a/src/test/ui/associated-types/bound-lifetime-constrained.func.stderr b/src/test/ui/associated-types/bound-lifetime-constrained.func.stderr
new file mode 100644
index 0000000..88d15a1
--- /dev/null
+++ b/src/test/ui/associated-types/bound-lifetime-constrained.func.stderr
@@ -0,0 +1,15 @@
+error[E0581]: return type references lifetime `'a`, which is not constrained by the fn input types
+  --> $DIR/bound-lifetime-constrained.rs:16:50
+   |
+LL | fn func1(_: for<'a> fn(<() as Foo<'a>>::Item) -> &'a i32) {
+   |                                                  ^^^^^^^
+
+error[E0581]: return type references lifetime `'a`, which is not constrained by the fn input types
+  --> $DIR/bound-lifetime-constrained.rs:23:29
+   |
+LL | fn func2(_: for<'a> fn() -> <() as Foo<'a>>::Item) {
+   |                             ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0581`.
diff --git a/src/test/ui/associated-types/bound-lifetime-constrained.object.stderr b/src/test/ui/associated-types/bound-lifetime-constrained.object.stderr
new file mode 100644
index 0000000..9258854
--- /dev/null
+++ b/src/test/ui/associated-types/bound-lifetime-constrained.object.stderr
@@ -0,0 +1,15 @@
+error[E0582]: binding for associated type `Output` references lifetime `'a`, which does not appear in the trait input types
+  --> $DIR/bound-lifetime-constrained.rs:28:56
+   |
+LL | fn object1(_: Box<for<'a> Fn(<() as Foo<'a>>::Item) -> &'a i32>) {
+   |                                                        ^^^^^^^
+
+error[E0582]: binding for associated type `Output` references lifetime `'a`, which does not appear in the trait input types
+  --> $DIR/bound-lifetime-constrained.rs:33:35
+   |
+LL | fn object2(_: Box<for<'a> Fn() -> <() as Foo<'a>>::Item>) {
+   |                                   ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0582`.
diff --git a/src/test/ui/associated-types/bound-lifetime-constrained.rs b/src/test/ui/associated-types/bound-lifetime-constrained.rs
new file mode 100644
index 0000000..b590f88
--- /dev/null
+++ b/src/test/ui/associated-types/bound-lifetime-constrained.rs
@@ -0,0 +1,48 @@
+// revisions: func object clause
+
+#![allow(dead_code)]
+#![feature(rustc_attrs)]
+
+trait Foo<'a> {
+    type Item;
+}
+
+impl<'a> Foo<'a> for() {
+    type Item = ();
+}
+
+// Check that appearing in a projection input in the argument is not enough:
+#[cfg(func)]
+fn func1(_: for<'a> fn(<() as Foo<'a>>::Item) -> &'a i32) {
+    //[func]~^ ERROR E0581
+}
+
+// Check that appearing in a projection input in the return still
+// causes an error:
+#[cfg(func)]
+fn func2(_: for<'a> fn() -> <() as Foo<'a>>::Item) {
+    //[func]~^ ERROR E0581
+}
+
+#[cfg(object)]
+fn object1(_: Box<for<'a> Fn(<() as Foo<'a>>::Item) -> &'a i32>) {
+    //[object]~^ ERROR E0582
+}
+
+#[cfg(object)]
+fn object2(_: Box<for<'a> Fn() -> <() as Foo<'a>>::Item>) {
+    //[object]~^ ERROR E0582
+}
+
+#[cfg(clause)]
+fn clause1<T>() where T: for<'a> Fn(<() as Foo<'a>>::Item) -> &'a i32 {
+    //[clause]~^ ERROR `Output` references lifetime `'a`
+}
+
+#[cfg(clause)]
+fn clause2<T>() where T: for<'a> Fn() -> <() as Foo<'a>>::Item {
+    //[clause]~^ ERROR `Output` references lifetime `'a`
+}
+
+#[rustc_error]
+fn main() { } //[ok]~ ERROR compilation successful
diff --git a/src/test/ui/associated-types/bound-lifetime-in-binding-only.angle.stderr b/src/test/ui/associated-types/bound-lifetime-in-binding-only.angle.stderr
new file mode 100644
index 0000000..fee64c0
--- /dev/null
+++ b/src/test/ui/associated-types/bound-lifetime-in-binding-only.angle.stderr
@@ -0,0 +1,27 @@
+error[E0582]: binding for associated type `Item` references lifetime `'a`, which does not appear in the trait input types
+  --> $DIR/bound-lifetime-in-binding-only.rs:12:25
+   |
+LL | fn angle<T: for<'a> Foo<Item=&'a i32>>() {
+   |                         ^^^^^^^^^^^^
+
+error[E0582]: binding for associated type `Item` references lifetime `'a`, which does not appear in the trait input types
+  --> $DIR/bound-lifetime-in-binding-only.rs:17:37
+   |
+LL | fn angle1<T>() where T: for<'a> Foo<Item=&'a i32> {
+   |                                     ^^^^^^^^^^^^
+
+error[E0582]: binding for associated type `Item` references lifetime `'a`, which does not appear in the trait input types
+  --> $DIR/bound-lifetime-in-binding-only.rs:22:37
+   |
+LL | fn angle2<T>() where for<'a> T: Foo<Item=&'a i32> {
+   |                                     ^^^^^^^^^^^^
+
+error[E0582]: binding for associated type `Item` references lifetime `'a`, which does not appear in the trait input types
+  --> $DIR/bound-lifetime-in-binding-only.rs:27:27
+   |
+LL | fn angle3(_: &for<'a> Foo<Item=&'a i32>) {
+   |                           ^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0582`.
diff --git a/src/test/ui/associated-types/bound-lifetime-in-binding-only.elision.stderr b/src/test/ui/associated-types/bound-lifetime-in-binding-only.elision.stderr
new file mode 100644
index 0000000..2745e44
--- /dev/null
+++ b/src/test/ui/associated-types/bound-lifetime-in-binding-only.elision.stderr
@@ -0,0 +1,11 @@
+error[E0106]: missing lifetime specifier
+  --> $DIR/bound-lifetime-in-binding-only.rs:52:23
+   |
+LL | fn elision<T: Fn() -> &i32>() {
+   |                       ^ help: consider giving it a 'static lifetime: `&'static`
+   |
+   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0106`.
diff --git a/src/test/ui/associated-types/bound-lifetime-in-binding-only.ok.stderr b/src/test/ui/associated-types/bound-lifetime-in-binding-only.ok.stderr
new file mode 100644
index 0000000..fcdb371
--- /dev/null
+++ b/src/test/ui/associated-types/bound-lifetime-in-binding-only.ok.stderr
@@ -0,0 +1,8 @@
+error: compilation successful
+  --> $DIR/bound-lifetime-in-binding-only.rs:71:1
+   |
+LL | fn main() { }
+   | ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/associated-types/bound-lifetime-in-binding-only.paren.stderr b/src/test/ui/associated-types/bound-lifetime-in-binding-only.paren.stderr
new file mode 100644
index 0000000..8c94800
--- /dev/null
+++ b/src/test/ui/associated-types/bound-lifetime-in-binding-only.paren.stderr
@@ -0,0 +1,27 @@
+error[E0582]: binding for associated type `Output` references lifetime `'a`, which does not appear in the trait input types
+  --> $DIR/bound-lifetime-in-binding-only.rs:32:29
+   |
+LL | fn paren<T: for<'a> Fn() -> &'a i32>() {
+   |                             ^^^^^^^
+
+error[E0582]: binding for associated type `Output` references lifetime `'a`, which does not appear in the trait input types
+  --> $DIR/bound-lifetime-in-binding-only.rs:37:41
+   |
+LL | fn paren1<T>() where T: for<'a> Fn() -> &'a i32 {
+   |                                         ^^^^^^^
+
+error[E0582]: binding for associated type `Output` references lifetime `'a`, which does not appear in the trait input types
+  --> $DIR/bound-lifetime-in-binding-only.rs:42:41
+   |
+LL | fn paren2<T>() where for<'a> T: Fn() -> &'a i32 {
+   |                                         ^^^^^^^
+
+error[E0582]: binding for associated type `Output` references lifetime `'a`, which does not appear in the trait input types
+  --> $DIR/bound-lifetime-in-binding-only.rs:47:31
+   |
+LL | fn paren3(_: &for<'a> Fn() -> &'a i32) {
+   |                               ^^^^^^^
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0582`.
diff --git a/src/test/ui/associated-types/bound-lifetime-in-binding-only.rs b/src/test/ui/associated-types/bound-lifetime-in-binding-only.rs
new file mode 100644
index 0000000..e1989d3
--- /dev/null
+++ b/src/test/ui/associated-types/bound-lifetime-in-binding-only.rs
@@ -0,0 +1,71 @@
+// revisions: angle paren ok elision
+
+#![allow(dead_code)]
+#![feature(rustc_attrs)]
+#![feature(unboxed_closures)]
+
+trait Foo {
+    type Item;
+}
+
+#[cfg(angle)]
+fn angle<T: for<'a> Foo<Item=&'a i32>>() {
+    //[angle]~^ ERROR binding for associated type `Item` references lifetime `'a`
+}
+
+#[cfg(angle)]
+fn angle1<T>() where T: for<'a> Foo<Item=&'a i32> {
+    //[angle]~^ ERROR binding for associated type `Item` references lifetime `'a`
+}
+
+#[cfg(angle)]
+fn angle2<T>() where for<'a> T: Foo<Item=&'a i32> {
+    //[angle]~^ ERROR binding for associated type `Item` references lifetime `'a`
+}
+
+#[cfg(angle)]
+fn angle3(_: &for<'a> Foo<Item=&'a i32>) {
+    //[angle]~^ ERROR binding for associated type `Item` references lifetime `'a`
+}
+
+#[cfg(paren)]
+fn paren<T: for<'a> Fn() -> &'a i32>() {
+    //[paren]~^ ERROR binding for associated type `Output` references lifetime `'a`
+}
+
+#[cfg(paren)]
+fn paren1<T>() where T: for<'a> Fn() -> &'a i32 {
+    //[paren]~^ ERROR binding for associated type `Output` references lifetime `'a`
+}
+
+#[cfg(paren)]
+fn paren2<T>() where for<'a> T: Fn() -> &'a i32 {
+    //[paren]~^ ERROR binding for associated type `Output` references lifetime `'a`
+}
+
+#[cfg(paren)]
+fn paren3(_: &for<'a> Fn() -> &'a i32) {
+    //[paren]~^ ERROR binding for associated type `Output` references lifetime `'a`
+}
+
+#[cfg(elision)]
+fn elision<T: Fn() -> &i32>() {
+    //[elision]~^ ERROR E0106
+}
+
+struct Parameterized<'a> { x: &'a str }
+
+#[cfg(ok)]
+fn ok1<T: for<'a> Fn(&Parameterized<'a>) -> &'a i32>() {
+}
+
+#[cfg(ok)]
+fn ok2<T: for<'a,'b> Fn<(&'b Parameterized<'a>,), Output=&'a i32>>() {
+}
+
+#[cfg(ok)]
+fn ok3<T>() where for<'a> Parameterized<'a>: Foo<Item=&'a i32> {
+}
+
+#[rustc_error]
+fn main() { } //[ok]~ ERROR compilation successful
diff --git a/src/test/ui/associated-types/bound-lifetime-in-return-only.elision.stderr b/src/test/ui/associated-types/bound-lifetime-in-return-only.elision.stderr
new file mode 100644
index 0000000..96f0cb8
--- /dev/null
+++ b/src/test/ui/associated-types/bound-lifetime-in-return-only.elision.stderr
@@ -0,0 +1,11 @@
+error[E0106]: missing lifetime specifier
+  --> $DIR/bound-lifetime-in-return-only.rs:34:23
+   |
+LL | fn elision(_: fn() -> &i32) {
+   |                       ^ help: consider giving it a 'static lifetime: `&'static`
+   |
+   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0106`.
diff --git a/src/test/ui/associated-types/bound-lifetime-in-return-only.local.stderr b/src/test/ui/associated-types/bound-lifetime-in-return-only.local.stderr
new file mode 100644
index 0000000..788cf66
--- /dev/null
+++ b/src/test/ui/associated-types/bound-lifetime-in-return-only.local.stderr
@@ -0,0 +1,9 @@
+error[E0581]: return type references lifetime `'a`, which is not constrained by the fn input types
+  --> $DIR/bound-lifetime-in-return-only.rs:23:28
+   |
+LL |     let _: for<'a> fn() -> &'a i32 = loop { };
+   |                            ^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0581`.
diff --git a/src/test/ui/associated-types/bound-lifetime-in-return-only.ok.stderr b/src/test/ui/associated-types/bound-lifetime-in-return-only.ok.stderr
new file mode 100644
index 0000000..504d68e
--- /dev/null
+++ b/src/test/ui/associated-types/bound-lifetime-in-return-only.ok.stderr
@@ -0,0 +1,8 @@
+error: compilation successful
+  --> $DIR/bound-lifetime-in-return-only.rs:49:1
+   |
+LL | fn main() { }
+   | ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/associated-types/bound-lifetime-in-return-only.rs b/src/test/ui/associated-types/bound-lifetime-in-return-only.rs
new file mode 100644
index 0000000..5a7e086
--- /dev/null
+++ b/src/test/ui/associated-types/bound-lifetime-in-return-only.rs
@@ -0,0 +1,49 @@
+// revisions: sig local structure ok elision
+
+#![allow(dead_code)]
+#![feature(rustc_attrs)]
+#![feature(unboxed_closures)]
+
+trait Foo {
+    type Item;
+}
+
+#[cfg(sig)]
+fn sig1(_: for<'a> fn() -> &'a i32) {
+    //[sig]~^ ERROR return type references lifetime `'a`
+}
+
+#[cfg(sig)]
+fn sig2(_: for<'a, 'b> fn(&'b i32) -> &'a i32) {
+    //[sig]~^ ERROR return type references lifetime `'a`
+}
+
+#[cfg(local)]
+fn local1() {
+    let _: for<'a> fn() -> &'a i32 = loop { };
+    //[local]~^ ERROR return type references lifetime `'a`
+}
+
+#[cfg(structure)]
+struct Struct1 {
+    x: for<'a> fn() -> &'a i32
+    //[structure]~^ ERROR return type references lifetime `'a`
+}
+
+#[cfg(elision)]
+fn elision(_: fn() -> &i32) {
+    //[elision]~^ ERROR E0106
+}
+
+struct Parameterized<'a> { x: &'a str }
+
+#[cfg(ok)]
+fn ok1(_: &for<'a> Fn(&Parameterized<'a>) -> &'a i32) {
+}
+
+#[cfg(ok)]
+fn ok2(_: &for<'a,'b> Fn<(&'b Parameterized<'a>,), Output=&'a i32>) {
+}
+
+#[rustc_error]
+fn main() { } //[ok]~ ERROR compilation successful
diff --git a/src/test/ui/associated-types/bound-lifetime-in-return-only.sig.stderr b/src/test/ui/associated-types/bound-lifetime-in-return-only.sig.stderr
new file mode 100644
index 0000000..64dad46
--- /dev/null
+++ b/src/test/ui/associated-types/bound-lifetime-in-return-only.sig.stderr
@@ -0,0 +1,15 @@
+error[E0581]: return type references lifetime `'a`, which is not constrained by the fn input types
+  --> $DIR/bound-lifetime-in-return-only.rs:12:28
+   |
+LL | fn sig1(_: for<'a> fn() -> &'a i32) {
+   |                            ^^^^^^^
+
+error[E0581]: return type references lifetime `'a`, which is not constrained by the fn input types
+  --> $DIR/bound-lifetime-in-return-only.rs:17:39
+   |
+LL | fn sig2(_: for<'a, 'b> fn(&'b i32) -> &'a i32) {
+   |                                       ^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0581`.
diff --git a/src/test/ui/associated-types/bound-lifetime-in-return-only.structure.stderr b/src/test/ui/associated-types/bound-lifetime-in-return-only.structure.stderr
new file mode 100644
index 0000000..f783350
--- /dev/null
+++ b/src/test/ui/associated-types/bound-lifetime-in-return-only.structure.stderr
@@ -0,0 +1,9 @@
+error[E0581]: return type references lifetime `'a`, which is not constrained by the fn input types
+  --> $DIR/bound-lifetime-in-return-only.rs:29:24
+   |
+LL |     x: for<'a> fn() -> &'a i32
+   |                        ^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0581`.
diff --git a/src/test/ui/associated-types/cache/chrono-scan.rs b/src/test/ui/associated-types/cache/chrono-scan.rs
new file mode 100644
index 0000000..00d47c9
--- /dev/null
+++ b/src/test/ui/associated-types/cache/chrono-scan.rs
@@ -0,0 +1,29 @@
+// compile-pass
+// skip-codegen
+#![allow(warnings)]
+pub type ParseResult<T> = Result<T, ()>;
+
+pub enum Item<'a> {     Literal(&'a str),
+ }
+
+pub fn colon_or_space(s: &str) -> ParseResult<&str> {
+    unimplemented!()
+}
+
+pub fn timezone_offset_zulu<F>(s: &str, colon: F) -> ParseResult<(&str, i32)>
+        where F: FnMut(&str) -> ParseResult<&str> {
+    unimplemented!()
+}
+
+pub fn parse<'a, I>(mut s: &str, items: I) -> ParseResult<()>
+        where I: Iterator<Item=Item<'a>> {
+    macro_rules! try_consume {
+        ($e:expr) => ({ let (s_, v) = try!($e); s = s_; v })
+    }
+    let offset = try_consume!(timezone_offset_zulu(s.trim_left(), colon_or_space));
+    let offset = try_consume!(timezone_offset_zulu(s.trim_left(), colon_or_space));
+    Ok(())
+}
+
+
+fn main() { }
diff --git a/src/test/ui/associated-types/cache/elision.rs b/src/test/ui/associated-types/cache/elision.rs
new file mode 100644
index 0000000..2b49cd3
--- /dev/null
+++ b/src/test/ui/associated-types/cache/elision.rs
@@ -0,0 +1,24 @@
+// compile-pass
+// skip-codegen
+#![allow(warnings)]
+// Check that you are allowed to implement using elision but write
+// trait without elision (a bug in this cropped up during
+// bootstrapping, so this is a regression test).
+
+pub struct SplitWhitespace<'a> {
+    x: &'a u8
+}
+
+pub trait UnicodeStr {
+    fn split_whitespace<'a>(&'a self) -> SplitWhitespace<'a>;
+}
+
+impl UnicodeStr for str {
+    #[inline]
+    fn split_whitespace(&self) -> SplitWhitespace {
+        unimplemented!()
+    }
+}
+
+
+fn main() { }
diff --git a/src/test/ui/associated-types/cache/project-fn-ret-contravariant.krisskross.stderr b/src/test/ui/associated-types/cache/project-fn-ret-contravariant.krisskross.stderr
new file mode 100644
index 0000000..fa4c6ad
--- /dev/null
+++ b/src/test/ui/associated-types/cache/project-fn-ret-contravariant.krisskross.stderr
@@ -0,0 +1,25 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/project-fn-ret-contravariant.rs:45:5
+   |
+LL | fn transmute<'a,'b>(x: &'a u32, y: &'b u32) -> (&'a u32, &'b u32) {
+   |                        -------                 ------------------
+   |                        |
+   |                        this parameter and the return type are declared with different lifetimes...
+...
+LL |    (a, b)
+   |     ^ ...but data from `y` is returned here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/project-fn-ret-contravariant.rs:45:8
+   |
+LL | fn transmute<'a,'b>(x: &'a u32, y: &'b u32) -> (&'a u32, &'b u32) {
+   |                                    -------     ------------------
+   |                                    |
+   |                                    this parameter and the return type are declared with different lifetimes...
+...
+LL |    (a, b)
+   |        ^ ...but data from `x` is returned here
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/associated-types/cache/project-fn-ret-contravariant.ok.stderr b/src/test/ui/associated-types/cache/project-fn-ret-contravariant.ok.stderr
new file mode 100644
index 0000000..15bbea6
--- /dev/null
+++ b/src/test/ui/associated-types/cache/project-fn-ret-contravariant.ok.stderr
@@ -0,0 +1,8 @@
+error: compilation successful
+  --> $DIR/project-fn-ret-contravariant.rs:50:1
+   |
+LL | fn main() { }
+   | ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/associated-types/cache/project-fn-ret-contravariant.oneuse.stderr b/src/test/ui/associated-types/cache/project-fn-ret-contravariant.oneuse.stderr
new file mode 100644
index 0000000..15bbea6
--- /dev/null
+++ b/src/test/ui/associated-types/cache/project-fn-ret-contravariant.oneuse.stderr
@@ -0,0 +1,8 @@
+error: compilation successful
+  --> $DIR/project-fn-ret-contravariant.rs:50:1
+   |
+LL | fn main() { }
+   | ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/associated-types/cache/project-fn-ret-contravariant.rs b/src/test/ui/associated-types/cache/project-fn-ret-contravariant.rs
new file mode 100644
index 0000000..d953325
--- /dev/null
+++ b/src/test/ui/associated-types/cache/project-fn-ret-contravariant.rs
@@ -0,0 +1,52 @@
+#![feature(unboxed_closures)]
+#![feature(rustc_attrs)]
+
+// Test for projection cache. We should be able to project distinct
+// lifetimes from `foo` as we reinstantiate it multiple times, but not
+// if we do it just once. In this variant, the region `'a` is used in
+// an contravariant position, which affects the results.
+
+// revisions: ok oneuse transmute krisskross
+
+#![allow(dead_code, unused_variables)]
+
+fn foo<'a>() -> &'a u32 { loop { } }
+
+fn bar<T>(t: T, x: T::Output) -> T::Output
+    where T: FnOnce<()>
+{
+    t()
+}
+
+#[cfg(ok)] // two instantiations: OK
+fn baz<'a,'b>(x: &'a u32, y: &'b u32) -> (&'a u32, &'b u32) {
+    let a = bar(foo, x);
+    let b = bar(foo, y);
+    (a, b)
+}
+
+#[cfg(oneuse)] // one instantiation: OK (surprisingly)
+fn baz<'a,'b>(x: &'a u32, y: &'b u32) -> (&'a u32, &'b u32) {
+    let f /* : fn() -> &'static u32 */ = foo; // <-- inferred type annotated
+    let a = bar(f, x); // this is considered ok because fn args are contravariant...
+    let b = bar(f, y); // ...and hence we infer T to distinct values in each call.
+    (a, b)
+}
+
+#[cfg(transmute)] // one instantiations: BAD
+fn baz<'a,'b>(x: &'a u32) -> &'static u32 {
+   bar(foo, x) //[transmute]~ ERROR E0495
+}
+
+#[cfg(krisskross)] // two instantiations, mixing and matching: BAD
+fn transmute<'a,'b>(x: &'a u32, y: &'b u32) -> (&'a u32, &'b u32) {
+   let a = bar(foo, y);
+   let b = bar(foo, x);
+   (a, b) //[krisskross]~ ERROR lifetime mismatch [E0623]
+   //[krisskross]~^ ERROR lifetime mismatch [E0623]
+}
+
+#[rustc_error]
+fn main() { }
+//[ok]~^ ERROR compilation successful
+//[oneuse]~^^ ERROR compilation successful
diff --git a/src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.stderr b/src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.stderr
new file mode 100644
index 0000000..4309373
--- /dev/null
+++ b/src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.stderr
@@ -0,0 +1,26 @@
+error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
+  --> $DIR/project-fn-ret-contravariant.rs:38:8
+   |
+LL |    bar(foo, x)
+   |        ^^^
+   |
+note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 37:8...
+  --> $DIR/project-fn-ret-contravariant.rs:37:8
+   |
+LL | fn baz<'a,'b>(x: &'a u32) -> &'static u32 {
+   |        ^^
+note: ...so that reference does not outlive borrowed content
+  --> $DIR/project-fn-ret-contravariant.rs:38:13
+   |
+LL |    bar(foo, x)
+   |             ^
+   = note: but, the lifetime must be valid for the static lifetime...
+note: ...so that reference does not outlive borrowed content
+  --> $DIR/project-fn-ret-contravariant.rs:38:4
+   |
+LL |    bar(foo, x)
+   |    ^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0495`.
diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.stderr
new file mode 100644
index 0000000..5009e08
--- /dev/null
+++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.stderr
@@ -0,0 +1,24 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/project-fn-ret-invariant.rs:53:21
+   |
+LL | fn transmute<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
+   |                                     --------     --------------------
+   |                                     |
+   |                                     this parameter and the return type are declared with different lifetimes...
+LL |    let a = bar(foo, y);
+   |                     ^ ...but data from `x` is returned here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/project-fn-ret-invariant.rs:54:21
+   |
+LL | fn transmute<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
+   |                        --------                  --------------------
+   |                        |
+   |                        this parameter and the return type are declared with different lifetimes...
+LL |    let a = bar(foo, y);
+LL |    let b = bar(foo, x);
+   |                     ^ ...but data from `y` is returned here
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.ok.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.ok.stderr
new file mode 100644
index 0000000..8110ed4
--- /dev/null
+++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.ok.stderr
@@ -0,0 +1,8 @@
+error: compilation successful
+  --> $DIR/project-fn-ret-invariant.rs:59:1
+   |
+LL | fn main() { }
+   | ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.stderr
new file mode 100644
index 0000000..65d16440
--- /dev/null
+++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.stderr
@@ -0,0 +1,14 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/project-fn-ret-invariant.rs:39:19
+   |
+LL | fn baz<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
+   |                               --------     --------------------
+   |                               |
+   |                               this parameter and the return type are declared with different lifetimes...
+...
+LL |    let b = bar(f, y);
+   |                   ^ ...but data from `x` is returned here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.rs b/src/test/ui/associated-types/cache/project-fn-ret-invariant.rs
new file mode 100644
index 0000000..54b6e36
--- /dev/null
+++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.rs
@@ -0,0 +1,60 @@
+#![feature(unboxed_closures)]
+#![feature(rustc_attrs)]
+
+// Test for projection cache. We should be able to project distinct
+// lifetimes from `foo` as we reinstantiate it multiple times, but not
+// if we do it just once. In this variant, the region `'a` is used in
+// an invariant position, which affects the results.
+
+// revisions: ok oneuse transmute krisskross
+
+#![allow(dead_code, unused_variables)]
+
+use std::marker::PhantomData;
+
+struct Type<'a> {
+    // Invariant
+    data: PhantomData<fn(&'a u32) -> &'a u32>
+}
+
+fn foo<'a>() -> Type<'a> { loop { } }
+
+fn bar<T>(t: T, x: T::Output) -> T::Output
+    where T: FnOnce<()>
+{
+    t()
+}
+
+#[cfg(ok)] // two instantiations: OK
+fn baz<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
+    let a = bar(foo, x);
+    let b = bar(foo, y);
+    (a, b)
+}
+
+#[cfg(oneuse)] // one instantiation: BAD
+fn baz<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
+   let f = foo; // <-- No consistent type can be inferred for `f` here.
+   let a = bar(f, x);
+   let b = bar(f, y); //[oneuse]~ ERROR lifetime mismatch [E0623]
+   (a, b)
+}
+
+#[cfg(transmute)] // one instantiations: BAD
+fn baz<'a,'b>(x: Type<'a>) -> Type<'static> {
+   // Cannot instantiate `foo` with any lifetime other than `'a`,
+   // since it is provided as input.
+
+   bar(foo, x) //[transmute]~ ERROR E0495
+}
+
+#[cfg(krisskross)] // two instantiations, mixing and matching: BAD
+fn transmute<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
+   let a = bar(foo, y); //[krisskross]~ ERROR E0623
+   let b = bar(foo, x); //[krisskross]~ ERROR E0623
+   (a, b)
+}
+
+#[rustc_error]
+fn main() { }
+//[ok]~^ ERROR compilation successful
diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr
new file mode 100644
index 0000000..b8b1a97
--- /dev/null
+++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr
@@ -0,0 +1,22 @@
+error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
+  --> $DIR/project-fn-ret-invariant.rs:48:8
+   |
+LL |    bar(foo, x)
+   |        ^^^
+   |
+note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 44:8...
+  --> $DIR/project-fn-ret-invariant.rs:44:8
+   |
+LL | fn baz<'a,'b>(x: Type<'a>) -> Type<'static> {
+   |        ^^
+   = note: ...so that the expression is assignable:
+           expected Type<'_>
+              found Type<'a>
+   = note: but, the lifetime must be valid for the static lifetime...
+   = note: ...so that the expression is assignable:
+           expected Type<'static>
+              found Type<'_>
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0495`.
diff --git a/src/test/ui/associated-types/higher-ranked-projection.bad.stderr b/src/test/ui/associated-types/higher-ranked-projection.bad.stderr
new file mode 100644
index 0000000..cc69e84
--- /dev/null
+++ b/src/test/ui/associated-types/higher-ranked-projection.bad.stderr
@@ -0,0 +1,17 @@
+error[E0271]: type mismatch resolving `for<'a> <&'a _ as Mirror>::Image == _`
+  --> $DIR/higher-ranked-projection.rs:25:5
+   |
+LL |     foo(());
+   |     ^^^ expected bound lifetime parameter 'a, found concrete lifetime
+   |
+note: required by `foo`
+  --> $DIR/higher-ranked-projection.rs:14:1
+   |
+LL | / fn foo<U, T>(_t: T)
+LL | |     where for<'a> &'a T: Mirror<Image=U>
+LL | | {}
+   | |__^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/associated-types/higher-ranked-projection.good.stderr b/src/test/ui/associated-types/higher-ranked-projection.good.stderr
new file mode 100644
index 0000000..16fef05
--- /dev/null
+++ b/src/test/ui/associated-types/higher-ranked-projection.good.stderr
@@ -0,0 +1,11 @@
+error: compilation successful
+  --> $DIR/higher-ranked-projection.rs:24:1
+   |
+LL | / fn main() {
+LL | |     foo(());
+LL | |
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/associated-types/higher-ranked-projection.rs b/src/test/ui/associated-types/higher-ranked-projection.rs
new file mode 100644
index 0000000..a2ea6d8
--- /dev/null
+++ b/src/test/ui/associated-types/higher-ranked-projection.rs
@@ -0,0 +1,27 @@
+#![feature(rustc_attrs)]
+
+// revisions: good bad
+
+trait Mirror {
+    type Image;
+}
+
+impl<T> Mirror for T {
+    type Image = T;
+}
+
+#[cfg(bad)]
+fn foo<U, T>(_t: T)
+    where for<'a> &'a T: Mirror<Image=U>
+{}
+
+#[cfg(good)]
+fn foo<U, T>(_t: T)
+    where for<'a> &'a T: Mirror<Image=&'a U>
+{}
+
+#[rustc_error]
+fn main() { //[good]~ ERROR compilation successful
+    foo(());
+    //[bad]~^ ERROR type mismatch
+}
diff --git a/src/test/ui/associated-types/issue-36499.rs b/src/test/ui/associated-types/issue-36499.rs
new file mode 100644
index 0000000..7f8f13e
--- /dev/null
+++ b/src/test/ui/associated-types/issue-36499.rs
@@ -0,0 +1,5 @@
+// error-pattern: aborting due to previous error
+
+fn main() {
+    2 + +2;
+}
diff --git a/src/test/ui/associated-types/issue-36499.stderr b/src/test/ui/associated-types/issue-36499.stderr
new file mode 100644
index 0000000..ff450f6
--- /dev/null
+++ b/src/test/ui/associated-types/issue-36499.stderr
@@ -0,0 +1,8 @@
+error: expected expression, found `+`
+  --> $DIR/issue-36499.rs:4:9
+   |
+LL |     2 + +2;
+   |         ^ expected expression
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/async-fn-multiple-lifetimes.rs b/src/test/ui/async-fn-multiple-lifetimes.rs
new file mode 100644
index 0000000..fccc4fd
--- /dev/null
+++ b/src/test/ui/async-fn-multiple-lifetimes.rs
@@ -0,0 +1,19 @@
+// edition:2018
+
+#![feature(arbitrary_self_types, async_await, await_macro, futures_api, pin)]
+
+use std::ops::Add;
+
+async fn multiple_named_lifetimes<'a, 'b>(_: &'a u8, _: &'b u8) {}
+//~^ ERROR ambiguous lifetime bound in `async fn`
+
+async fn multiple_hrtb_and_single_named_lifetime_ok<'c>(
+    _: impl for<'a> Add<&'a u8>,
+    _: impl for<'b> Add<&'b u8>,
+    _: &'c u8,
+) {}
+
+async fn multiple_elided_lifetimes(_: &u8, _: &u8) {}
+//~^ ambiguous lifetime bound in `async fn`
+
+fn main() {}
diff --git a/src/test/ui/async-fn-multiple-lifetimes.stderr b/src/test/ui/async-fn-multiple-lifetimes.stderr
new file mode 100644
index 0000000..8c3ee2b
--- /dev/null
+++ b/src/test/ui/async-fn-multiple-lifetimes.stderr
@@ -0,0 +1,20 @@
+error: ambiguous lifetime bound in `async fn`
+  --> $DIR/async-fn-multiple-lifetimes.rs:7:65
+   |
+LL | async fn multiple_named_lifetimes<'a, 'b>(_: &'a u8, _: &'b u8) {}
+   |                                                                 ^ neither `'a` nor `'b` outlives the other
+   |
+   = note: multiple unrelated lifetimes are not allowed in `async fn`.
+   = note: if you're using argument-position elided lifetimes, consider switching to a single named lifetime.
+
+error: ambiguous lifetime bound in `async fn`
+  --> $DIR/async-fn-multiple-lifetimes.rs:16:52
+   |
+LL | async fn multiple_elided_lifetimes(_: &u8, _: &u8) {}
+   |                                                    ^ the elided lifetimes here do not outlive one another
+   |
+   = note: multiple unrelated lifetimes are not allowed in `async fn`.
+   = note: if you're using argument-position elided lifetimes, consider switching to a single named lifetime.
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/async-matches-expr.rs b/src/test/ui/async-matches-expr.rs
new file mode 100644
index 0000000..f375d58
--- /dev/null
+++ b/src/test/ui/async-matches-expr.rs
@@ -0,0 +1,13 @@
+// compile-pass
+// edition:2018
+
+#![feature(async_await, await_macro)]
+
+macro_rules! match_expr {
+    ($x:expr) => {}
+}
+
+fn main() {
+    match_expr!(async {});
+    match_expr!(async || {});
+}
diff --git a/src/test/ui/attempted-access-non-fatal.rs b/src/test/ui/attempted-access-non-fatal.rs
new file mode 100644
index 0000000..e50c1f2
--- /dev/null
+++ b/src/test/ui/attempted-access-non-fatal.rs
@@ -0,0 +1,6 @@
+// Check that bogus field access is non-fatal
+fn main() {
+    let x = 0;
+    let _ = x.foo; //~ `{integer}` is a primitive type and therefore doesn't have fields [E0610]
+    let _ = x.bar; //~ `{integer}` is a primitive type and therefore doesn't have fields [E0610]
+}
diff --git a/src/test/ui/attempted-access-non-fatal.stderr b/src/test/ui/attempted-access-non-fatal.stderr
new file mode 100644
index 0000000..5b7db0e
--- /dev/null
+++ b/src/test/ui/attempted-access-non-fatal.stderr
@@ -0,0 +1,15 @@
+error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields
+  --> $DIR/attempted-access-non-fatal.rs:4:15
+   |
+LL |     let _ = x.foo;
+   |               ^^^
+
+error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields
+  --> $DIR/attempted-access-non-fatal.rs:5:15
+   |
+LL |     let _ = x.bar;
+   |               ^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0610`.
diff --git a/src/test/ui/attr-bad-crate-attr.rc b/src/test/ui/attr-bad-crate-attr.rc
new file mode 100644
index 0000000..89ba26d
--- /dev/null
+++ b/src/test/ui/attr-bad-crate-attr.rc
@@ -0,0 +1,4 @@
+// error-pattern: expected item
+
+#![attr = "val"]
+#[attr = "val"] // Unterminated
diff --git a/src/test/ui/attr-eq-token-tree.rs b/src/test/ui/attr-eq-token-tree.rs
new file mode 100644
index 0000000..6aacb9d
--- /dev/null
+++ b/src/test/ui/attr-eq-token-tree.rs
@@ -0,0 +1,4 @@
+#![feature(custom_attribute)]
+
+#[my_attr = !] //~ ERROR unexpected token: `!`
+fn main() {}
diff --git a/src/test/ui/attr-eq-token-tree.stderr b/src/test/ui/attr-eq-token-tree.stderr
new file mode 100644
index 0000000..aae25b2
--- /dev/null
+++ b/src/test/ui/attr-eq-token-tree.stderr
@@ -0,0 +1,8 @@
+error: unexpected token: `!`
+  --> $DIR/attr-eq-token-tree.rs:3:11
+   |
+LL | #[my_attr = !]
+   |           ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/attr-usage-inline.rs b/src/test/ui/attr-usage-inline.rs
new file mode 100644
index 0000000..1996f4a
--- /dev/null
+++ b/src/test/ui/attr-usage-inline.rs
@@ -0,0 +1,9 @@
+#![allow(dead_code)]
+
+#[inline]
+fn f() {}
+
+#[inline] //~ ERROR: attribute should be applied to function or closure
+struct S;
+
+fn main() {}
diff --git a/src/test/ui/attr-usage-inline.stderr b/src/test/ui/attr-usage-inline.stderr
new file mode 100644
index 0000000..d8d7f6a
--- /dev/null
+++ b/src/test/ui/attr-usage-inline.stderr
@@ -0,0 +1,11 @@
+error[E0518]: attribute should be applied to function or closure
+  --> $DIR/attr-usage-inline.rs:6:1
+   |
+LL | #[inline]
+   | ^^^^^^^^^
+LL | struct S;
+   | --------- not a function or closure
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0518`.
diff --git a/src/test/ui/attr-usage-repr.rs b/src/test/ui/attr-usage-repr.rs
new file mode 100644
index 0000000..1df2947
--- /dev/null
+++ b/src/test/ui/attr-usage-repr.rs
@@ -0,0 +1,34 @@
+#![feature(repr_simd)]
+#![feature(repr_align_enum)]
+
+#[repr(C)] //~ ERROR: attribute should be applied to struct, enum or union
+fn f() {}
+
+#[repr(C)]
+struct SExtern(f64, f64);
+
+#[repr(packed)]
+struct SPacked(f64, f64);
+
+#[repr(simd)]
+struct SSimd(f64, f64);
+
+#[repr(i8)] //~ ERROR: attribute should be applied to enum
+struct SInt(f64, f64);
+
+#[repr(C)]
+enum EExtern { A, B }
+
+#[repr(align(8))]
+enum EAlign { A, B }
+
+#[repr(packed)] //~ ERROR: attribute should be applied to struct
+enum EPacked { A, B }
+
+#[repr(simd)] //~ ERROR: attribute should be applied to struct
+enum ESimd { A, B }
+
+#[repr(i8)]
+enum EInt { A, B }
+
+fn main() {}
diff --git a/src/test/ui/attr-usage-repr.stderr b/src/test/ui/attr-usage-repr.stderr
new file mode 100644
index 0000000..f8ad7ee
--- /dev/null
+++ b/src/test/ui/attr-usage-repr.stderr
@@ -0,0 +1,35 @@
+error[E0517]: attribute should be applied to struct, enum or union
+  --> $DIR/attr-usage-repr.rs:4:8
+   |
+LL | #[repr(C)]
+   |        ^
+LL | fn f() {}
+   | --------- not a struct, enum or union
+
+error[E0517]: attribute should be applied to enum
+  --> $DIR/attr-usage-repr.rs:16:8
+   |
+LL | #[repr(i8)]
+   |        ^^
+LL | struct SInt(f64, f64);
+   | ---------------------- not an enum
+
+error[E0517]: attribute should be applied to struct or union
+  --> $DIR/attr-usage-repr.rs:25:8
+   |
+LL | #[repr(packed)]
+   |        ^^^^^^
+LL | enum EPacked { A, B }
+   | --------------------- not a struct or union
+
+error[E0517]: attribute should be applied to struct
+  --> $DIR/attr-usage-repr.rs:28:8
+   |
+LL | #[repr(simd)]
+   |        ^^^^
+LL | enum ESimd { A, B }
+   | ------------------- not a struct
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0517`.
diff --git a/src/test/ui/attribute-with-no-generics-in-parameter-list.rs b/src/test/ui/attribute-with-no-generics-in-parameter-list.rs
new file mode 100644
index 0000000..c2cc91d
--- /dev/null
+++ b/src/test/ui/attribute-with-no-generics-in-parameter-list.rs
@@ -0,0 +1,3 @@
+fn foo<#[attr]>() {} //~ ERROR attribute without generic parameters
+
+fn main() {}
diff --git a/src/test/ui/attribute-with-no-generics-in-parameter-list.stderr b/src/test/ui/attribute-with-no-generics-in-parameter-list.stderr
new file mode 100644
index 0000000..4c59647
--- /dev/null
+++ b/src/test/ui/attribute-with-no-generics-in-parameter-list.stderr
@@ -0,0 +1,8 @@
+error: attribute without generic parameters
+  --> $DIR/attribute-with-no-generics-in-parameter-list.rs:1:8
+   |
+LL | fn foo<#[attr]>() {}
+   |        ^^^^^^^ attributes are only permitted when preceding parameters
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-1.rs b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-1.rs
new file mode 100644
index 0000000..ca5fdd9
--- /dev/null
+++ b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-1.rs
@@ -0,0 +1,15 @@
+// This test checks variations on `<#[attr] 'a, #[oops]>`, where
+// `#[oops]` is left dangling (that is, it is unattached, with no
+// formal binding following it).
+
+#![feature(rustc_attrs)]
+
+struct RefIntPair<'a, 'b>(&'a u32, &'b u32);
+
+impl<#[rustc_1] 'a, 'b, #[oops]> RefIntPair<'a, 'b> {
+    //~^ ERROR trailing attribute after generic parameter
+}
+
+fn main() {
+
+}
diff --git a/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-1.stderr b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-1.stderr
new file mode 100644
index 0000000..55e7a98
--- /dev/null
+++ b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-1.stderr
@@ -0,0 +1,8 @@
+error: trailing attribute after generic parameter
+  --> $DIR/attrs-with-no-formal-in-generics-1.rs:9:25
+   |
+LL | impl<#[rustc_1] 'a, 'b, #[oops]> RefIntPair<'a, 'b> {
+   |                         ^^^^^^^ attributes must go before parameters
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-2.rs b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-2.rs
new file mode 100644
index 0000000..c795612
--- /dev/null
+++ b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-2.rs
@@ -0,0 +1,12 @@
+// This test checks variations on `<#[attr] 'a, #[oops]>`, where
+// `#[oops]` is left dangling (that is, it is unattached, with no
+// formal binding following it).
+
+#![feature(rustc_attrs)]
+
+struct RefAny<'a, T>(&'a T);
+
+impl<#[rustc_1] 'a, #[rustc_2] T, #[oops]> RefAny<'a, T> {}
+//~^ ERROR trailing attribute after generic parameter
+
+fn main() {}
diff --git a/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-2.stderr b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-2.stderr
new file mode 100644
index 0000000..acd0ae3
--- /dev/null
+++ b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-2.stderr
@@ -0,0 +1,8 @@
+error: trailing attribute after generic parameter
+  --> $DIR/attrs-with-no-formal-in-generics-2.rs:9:35
+   |
+LL | impl<#[rustc_1] 'a, #[rustc_2] T, #[oops]> RefAny<'a, T> {}
+   |                                   ^^^^^^^ attributes must go before parameters
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-3.rs b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-3.rs
new file mode 100644
index 0000000..3cfc70b
--- /dev/null
+++ b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-3.rs
@@ -0,0 +1,12 @@
+// This test checks variations on `<#[attr] 'a, #[oops]>`, where
+// `#[oops]` is left dangling (that is, it is unattached, with no
+// formal binding following it).
+
+struct RefIntPair<'a, 'b>(&'a u32, &'b u32);
+
+fn hof_lt<Q>(_: Q)
+    where Q: for <#[allow(unused)] 'a, 'b, #[oops]> Fn(RefIntPair<'a,'b>) -> &'b u32
+    //~^ ERROR trailing attribute after generic parameter
+{}
+
+fn main() {}
diff --git a/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-3.stderr b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-3.stderr
new file mode 100644
index 0000000..b9ca009
--- /dev/null
+++ b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-3.stderr
@@ -0,0 +1,8 @@
+error: trailing attribute after generic parameter
+  --> $DIR/attrs-with-no-formal-in-generics-3.rs:8:44
+   |
+LL |     where Q: for <#[allow(unused)] 'a, 'b, #[oops]> Fn(RefIntPair<'a,'b>) -> &'b u32
+   |                                            ^^^^^^^ attributes must go before parameters
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/augmented-assignments.nll.stderr b/src/test/ui/augmented-assignments.nll.stderr
new file mode 100644
index 0000000..e205e2a
--- /dev/null
+++ b/src/test/ui/augmented-assignments.nll.stderr
@@ -0,0 +1,22 @@
+error[E0505]: cannot move out of `x` because it is borrowed
+  --> $DIR/augmented-assignments.rs:16:5
+   |
+LL |     x
+   |     - borrow of `x` occurs here
+...
+LL |     x;
+   |     ^ move out of `x` occurs here
+
+error[E0596]: cannot borrow `y` as mutable, as it is not declared as mutable
+  --> $DIR/augmented-assignments.rs:21:5
+   |
+LL |     let y = Int(2);
+   |         - help: consider changing this to be mutable: `mut y`
+...
+LL |     y
+   |     ^ cannot borrow as mutable
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0505, E0596.
+For more information about an error, try `rustc --explain E0505`.
diff --git a/src/test/ui/augmented-assignments.rs b/src/test/ui/augmented-assignments.rs
new file mode 100644
index 0000000..eea15ea
--- /dev/null
+++ b/src/test/ui/augmented-assignments.rs
@@ -0,0 +1,25 @@
+use std::ops::AddAssign;
+
+struct Int(i32);
+
+impl AddAssign for Int {
+    fn add_assign(&mut self, _: Int) {
+        unimplemented!()
+    }
+}
+
+fn main() {
+    let mut x = Int(1);
+    x   //~ error: use of moved value: `x`
+    //~^ value used here after move
+    +=
+    x;  //~ value moved here
+
+    let y = Int(2);
+    //~^ HELP make this binding mutable
+    //~| SUGGESTION mut y
+    y   //~ error: cannot borrow immutable local variable `y` as mutable
+        //~| cannot borrow
+    +=
+    Int(1);
+}
diff --git a/src/test/ui/augmented-assignments.stderr b/src/test/ui/augmented-assignments.stderr
new file mode 100644
index 0000000..e429bf2
--- /dev/null
+++ b/src/test/ui/augmented-assignments.stderr
@@ -0,0 +1,24 @@
+error[E0596]: cannot borrow immutable local variable `y` as mutable
+  --> $DIR/augmented-assignments.rs:21:5
+   |
+LL |     let y = Int(2);
+   |         - help: make this binding mutable: `mut y`
+...
+LL |     y
+   |     ^ cannot borrow mutably
+
+error[E0382]: use of moved value: `x`
+  --> $DIR/augmented-assignments.rs:13:5
+   |
+LL |     x
+   |     ^ value used here after move
+...
+LL |     x;
+   |     - value moved here
+   |
+   = note: move occurs because `x` has type `Int`, which does not implement the `Copy` trait
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0382, E0596.
+For more information about an error, try `rustc --explain E0382`.
diff --git a/src/test/ui/auto-ref-slice-plus-ref.rs b/src/test/ui/auto-ref-slice-plus-ref.rs
new file mode 100644
index 0000000..00b279d
--- /dev/null
+++ b/src/test/ui/auto-ref-slice-plus-ref.rs
@@ -0,0 +1,27 @@
+fn main() {
+
+    // Testing that method lookup does not automatically borrow
+    // vectors to slices then automatically create a self reference.
+
+    let mut a = vec![0];
+    a.test_mut(); //~ ERROR no method named `test_mut` found
+    a.test(); //~ ERROR no method named `test` found
+
+    ([1]).test(); //~ ERROR no method named `test` found
+    (&[1]).test(); //~ ERROR no method named `test` found
+}
+
+trait MyIter {
+    fn test_mut(&mut self);
+    fn test(&self);
+}
+
+impl<'a> MyIter for &'a [isize] {
+    fn test_mut(&mut self) { }
+    fn test(&self) { }
+}
+
+impl<'a> MyIter for &'a str {
+    fn test_mut(&mut self) { }
+    fn test(&self) { }
+}
diff --git a/src/test/ui/auto-ref-slice-plus-ref.stderr b/src/test/ui/auto-ref-slice-plus-ref.stderr
new file mode 100644
index 0000000..97b9cd9
--- /dev/null
+++ b/src/test/ui/auto-ref-slice-plus-ref.stderr
@@ -0,0 +1,43 @@
+error[E0599]: no method named `test_mut` found for type `std::vec::Vec<{integer}>` in the current scope
+  --> $DIR/auto-ref-slice-plus-ref.rs:7:7
+   |
+LL |     a.test_mut();
+   |       ^^^^^^^^ help: did you mean: `get_mut`
+   |
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following trait defines an item `test_mut`, perhaps you need to implement it:
+           candidate #1: `MyIter`
+
+error[E0599]: no method named `test` found for type `std::vec::Vec<{integer}>` in the current scope
+  --> $DIR/auto-ref-slice-plus-ref.rs:8:7
+   |
+LL |     a.test();
+   |       ^^^^
+   |
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following trait defines an item `test`, perhaps you need to implement it:
+           candidate #1: `MyIter`
+
+error[E0599]: no method named `test` found for type `[{integer}; 1]` in the current scope
+  --> $DIR/auto-ref-slice-plus-ref.rs:10:11
+   |
+LL |     ([1]).test();
+   |           ^^^^
+   |
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following trait defines an item `test`, perhaps you need to implement it:
+           candidate #1: `MyIter`
+
+error[E0599]: no method named `test` found for type `&[{integer}; 1]` in the current scope
+  --> $DIR/auto-ref-slice-plus-ref.rs:11:12
+   |
+LL |     (&[1]).test();
+   |            ^^^^
+   |
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following trait defines an item `test`, perhaps you need to implement it:
+           candidate #1: `MyIter`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/auto-trait-validation.rs b/src/test/ui/auto-trait-validation.rs
new file mode 100644
index 0000000..34d6c3d
--- /dev/null
+++ b/src/test/ui/auto-trait-validation.rs
@@ -0,0 +1,9 @@
+#![feature(optin_builtin_traits)]
+
+auto trait Generic<T> {}
+//~^ auto traits cannot have generic parameters [E0567]
+auto trait Bound : Copy {}
+//~^ auto traits cannot have super traits [E0568]
+auto trait MyTrait { fn foo() {} }
+//~^ auto traits cannot have methods or associated items [E0380]
+fn main() {}
diff --git a/src/test/ui/auto-trait-validation.stderr b/src/test/ui/auto-trait-validation.stderr
new file mode 100644
index 0000000..e077982
--- /dev/null
+++ b/src/test/ui/auto-trait-validation.stderr
@@ -0,0 +1,22 @@
+error[E0567]: auto traits cannot have generic parameters
+  --> $DIR/auto-trait-validation.rs:3:1
+   |
+LL | auto trait Generic<T> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0568]: auto traits cannot have super traits
+  --> $DIR/auto-trait-validation.rs:5:1
+   |
+LL | auto trait Bound : Copy {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0380]: auto traits cannot have methods or associated items
+  --> $DIR/auto-trait-validation.rs:7:1
+   |
+LL | auto trait MyTrait { fn foo() {} }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0380, E0567, E0568.
+For more information about an error, try `rustc --explain E0380`.
diff --git a/src/test/ui/autoderef-full-lval.rs b/src/test/ui/autoderef-full-lval.rs
new file mode 100644
index 0000000..db09d03
--- /dev/null
+++ b/src/test/ui/autoderef-full-lval.rs
@@ -0,0 +1,25 @@
+#![feature(box_syntax)]
+
+struct Clam {
+    x: Box<isize>,
+    y: Box<isize>,
+}
+
+struct Fish {
+    a: Box<isize>,
+}
+
+fn main() {
+    let a: Clam = Clam{x: box 1, y: box 2};
+    let b: Clam = Clam{x: box 10, y: box 20};
+    let z: isize = a.x + b.y;
+    //~^ ERROR binary operation `+` cannot be applied to type `std::boxed::Box<isize>`
+    println!("{}", z);
+    assert_eq!(z, 21);
+    let forty: Fish = Fish{a: box 40};
+    let two: Fish = Fish{a: box 2};
+    let answer: isize = forty.a + two.a;
+    //~^ ERROR binary operation `+` cannot be applied to type `std::boxed::Box<isize>`
+    println!("{}", answer);
+    assert_eq!(answer, 42);
+}
diff --git a/src/test/ui/autoderef-full-lval.stderr b/src/test/ui/autoderef-full-lval.stderr
new file mode 100644
index 0000000..c9f3e8b
--- /dev/null
+++ b/src/test/ui/autoderef-full-lval.stderr
@@ -0,0 +1,23 @@
+error[E0369]: binary operation `+` cannot be applied to type `std::boxed::Box<isize>`
+  --> $DIR/autoderef-full-lval.rs:15:24
+   |
+LL |     let z: isize = a.x + b.y;
+   |                    --- ^ --- std::boxed::Box<isize>
+   |                    |
+   |                    std::boxed::Box<isize>
+   |
+   = note: an implementation of `std::ops::Add` might be missing for `std::boxed::Box<isize>`
+
+error[E0369]: binary operation `+` cannot be applied to type `std::boxed::Box<isize>`
+  --> $DIR/autoderef-full-lval.rs:21:33
+   |
+LL |     let answer: isize = forty.a + two.a;
+   |                         ------- ^ ----- std::boxed::Box<isize>
+   |                         |
+   |                         std::boxed::Box<isize>
+   |
+   = note: an implementation of `std::ops::Add` might be missing for `std::boxed::Box<isize>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0369`.
diff --git a/src/test/ui/auxiliary/cdylib-dep.rs b/src/test/ui/auxiliary/cdylib-dep.rs
new file mode 100644
index 0000000..8bd2b33
--- /dev/null
+++ b/src/test/ui/auxiliary/cdylib-dep.rs
@@ -0,0 +1 @@
+#![crate_type = "dylib"]
diff --git a/src/test/ui/auxiliary/changing-crates-a1.rs b/src/test/ui/auxiliary/changing-crates-a1.rs
new file mode 100644
index 0000000..bc0559b
--- /dev/null
+++ b/src/test/ui/auxiliary/changing-crates-a1.rs
@@ -0,0 +1,3 @@
+#![crate_name = "a"]
+
+pub fn foo<T>() {}
diff --git a/src/test/ui/auxiliary/changing-crates-a2.rs b/src/test/ui/auxiliary/changing-crates-a2.rs
new file mode 100644
index 0000000..fafc6d5
--- /dev/null
+++ b/src/test/ui/auxiliary/changing-crates-a2.rs
@@ -0,0 +1,3 @@
+#![crate_name = "a"]
+
+pub fn foo<T>() { println!("hello!"); }
diff --git a/src/test/ui/auxiliary/changing-crates-b.rs b/src/test/ui/auxiliary/changing-crates-b.rs
new file mode 100644
index 0000000..f9ce29e
--- /dev/null
+++ b/src/test/ui/auxiliary/changing-crates-b.rs
@@ -0,0 +1,5 @@
+#![crate_name = "b"]
+
+extern crate a;
+
+pub fn foo() { a::foo::<isize>(); }
diff --git a/src/test/ui/auxiliary/default-ty-param-cross-crate-crate.rs b/src/test/ui/auxiliary/default-ty-param-cross-crate-crate.rs
new file mode 100644
index 0000000..612f99d
--- /dev/null
+++ b/src/test/ui/auxiliary/default-ty-param-cross-crate-crate.rs
@@ -0,0 +1,10 @@
+#![crate_type = "lib"]
+#![crate_name = "default_param_test"]
+#![feature(default_type_parameter_fallback)]
+
+use std::marker::PhantomData;
+
+pub struct Foo<A, B>(PhantomData<(A, B)>);
+
+pub fn bleh<A=i32, X=char>() -> Foo<A, X> { Foo(PhantomData) }
+
diff --git a/src/test/ui/auxiliary/define-macro.rs b/src/test/ui/auxiliary/define-macro.rs
new file mode 100644
index 0000000..4956907
--- /dev/null
+++ b/src/test/ui/auxiliary/define-macro.rs
@@ -0,0 +1,6 @@
+#[macro_export]
+macro_rules! define_macro {
+    ($i:ident) => {
+        macro_rules! $i { () => {} }
+    }
+}
diff --git a/src/test/ui/auxiliary/empty-struct.rs b/src/test/ui/auxiliary/empty-struct.rs
new file mode 100644
index 0000000..3fb40f6
--- /dev/null
+++ b/src/test/ui/auxiliary/empty-struct.rs
@@ -0,0 +1,9 @@
+pub struct XEmpty1 {}
+pub struct XEmpty2;
+pub struct XEmpty6();
+
+pub enum XE {
+    XEmpty3 {},
+    XEmpty4,
+    XEmpty5(),
+}
diff --git a/src/test/ui/auxiliary/extern-prelude-vec.rs b/src/test/ui/auxiliary/extern-prelude-vec.rs
new file mode 100644
index 0000000..a643c88
--- /dev/null
+++ b/src/test/ui/auxiliary/extern-prelude-vec.rs
@@ -0,0 +1,3 @@
+#![crate_name = "Vec"]
+
+pub fn new(arg1: f32, arg2: ()) {}
diff --git a/src/test/ui/auxiliary/extern-prelude.rs b/src/test/ui/auxiliary/extern-prelude.rs
new file mode 100644
index 0000000..2fdfd85
--- /dev/null
+++ b/src/test/ui/auxiliary/extern-prelude.rs
@@ -0,0 +1,5 @@
+pub struct S;
+
+impl S {
+    pub fn external(&self) {}
+}
diff --git a/src/test/ui/auxiliary/extern-statics.rs b/src/test/ui/auxiliary/extern-statics.rs
new file mode 100644
index 0000000..725fde5
--- /dev/null
+++ b/src/test/ui/auxiliary/extern-statics.rs
@@ -0,0 +1,4 @@
+extern {
+    pub static XA: u8;
+    pub static mut XB: u8;
+}
diff --git a/src/test/ui/auxiliary/lto-duplicate-symbols1.rs b/src/test/ui/auxiliary/lto-duplicate-symbols1.rs
new file mode 100644
index 0000000..9d510f2
--- /dev/null
+++ b/src/test/ui/auxiliary/lto-duplicate-symbols1.rs
@@ -0,0 +1,6 @@
+// no-prefer-dynamic
+
+#![crate_type = "rlib"]
+
+#[no_mangle]
+pub extern fn foo() {}
diff --git a/src/test/ui/auxiliary/lto-duplicate-symbols2.rs b/src/test/ui/auxiliary/lto-duplicate-symbols2.rs
new file mode 100644
index 0000000..9d510f2
--- /dev/null
+++ b/src/test/ui/auxiliary/lto-duplicate-symbols2.rs
@@ -0,0 +1,6 @@
+// no-prefer-dynamic
+
+#![crate_type = "rlib"]
+
+#[no_mangle]
+pub extern fn foo() {}
diff --git a/src/test/ui/auxiliary/noexporttypelib.rs b/src/test/ui/auxiliary/noexporttypelib.rs
new file mode 100644
index 0000000..67889cc
--- /dev/null
+++ b/src/test/ui/auxiliary/noexporttypelib.rs
@@ -0,0 +1,2 @@
+pub type oint = Option<isize>;
+pub fn foo() -> oint { Some(3) }
diff --git a/src/test/ui/auxiliary/orphan-check-diagnostics.rs b/src/test/ui/auxiliary/orphan-check-diagnostics.rs
new file mode 100644
index 0000000..6b2c42b
--- /dev/null
+++ b/src/test/ui/auxiliary/orphan-check-diagnostics.rs
@@ -0,0 +1 @@
+pub trait RemoteTrait { fn dummy(&self) { } }
diff --git a/src/test/ui/auxiliary/pub-and-stability.rs b/src/test/ui/auxiliary/pub-and-stability.rs
new file mode 100644
index 0000000..ee05a07
--- /dev/null
+++ b/src/test/ui/auxiliary/pub-and-stability.rs
@@ -0,0 +1,133 @@
+// This crate attempts to enumerate the various scenarios for how a
+// type can define fields and methods with various visibilities and
+// stabilities.
+//
+// The basic stability pattern in this file has four cases:
+// 1. no stability attribute at all
+// 2. a stable attribute (feature "unit_test")
+// 3. an unstable attribute that unit test declares (feature "unstable_declared")
+// 4. an unstable attribute that unit test fails to declare (feature "unstable_undeclared")
+//
+// This file also covers four kinds of visibility: private,
+// pub(module), pub(crate), and pub.
+//
+// However, since stability attributes can only be observed in
+// cross-crate linkage scenarios, there is little reason to take the
+// cross-product (4 stability cases * 4 visibility cases), because the
+// first three visibility cases cannot be accessed outside this crate,
+// and therefore stability is only relevant when the visibility is pub
+// to the whole universe.
+//
+// (The only reason to do so would be if one were worried about the
+// compiler having some subtle bug where adding a stability attribute
+// introduces a privacy violation. As a way to provide evidence that
+// this is not occurring, I have put stability attributes on some
+// non-pub fields, marked with SILLY below)
+
+#![feature(staged_api)]
+
+#![stable(feature = "unit_test", since = "1.0.0")]
+
+#[stable(feature = "unit_test", since = "1.0.0")]
+pub use m::{Record, Trait, Tuple};
+
+mod m {
+    #[derive(Default)]
+    #[stable(feature = "unit_test", since = "1.0.0")]
+    pub struct Record {
+        #[stable(feature = "unit_test", since = "1.0.0")]
+        pub a_stable_pub: i32,
+        #[unstable(feature = "unstable_declared", issue = "38412")]
+        pub a_unstable_declared_pub: i32,
+        #[unstable(feature = "unstable_undeclared", issue = "38412")]
+        pub a_unstable_undeclared_pub: i32,
+        #[unstable(feature = "unstable_undeclared", issue = "38412")] // SILLY
+        pub(crate) b_crate: i32,
+        #[unstable(feature = "unstable_declared", issue = "38412")] // SILLY
+        pub(in m) c_mod: i32,
+        #[stable(feature = "unit_test", since = "1.0.0")] // SILLY
+        d_priv: i32
+    }
+
+    #[derive(Default)]
+    #[stable(feature = "unit_test", since = "1.0.0")]
+    pub struct Tuple(
+        #[stable(feature = "unit_test", since = "1.0.0")]
+        pub i32,
+        #[unstable(feature = "unstable_declared", issue = "38412")]
+        pub i32,
+        #[unstable(feature = "unstable_undeclared", issue = "38412")]
+        pub i32,
+
+        pub(crate) i32,
+        pub(in m) i32,
+        i32);
+
+    impl Record {
+        #[stable(feature = "unit_test", since = "1.0.0")]
+        pub fn new() -> Self { Default::default() }
+    }
+
+    impl Tuple {
+        #[stable(feature = "unit_test", since = "1.0.0")]
+        pub fn new() -> Self { Default::default() }
+    }
+
+
+    #[stable(feature = "unit_test", since = "1.0.0")]
+    pub trait Trait {
+        #[stable(feature = "unit_test", since = "1.0.0")]
+        type Type;
+        #[stable(feature = "unit_test", since = "1.0.0")]
+        fn stable_trait_method(&self) -> Self::Type;
+        #[unstable(feature = "unstable_undeclared", issue = "38412")]
+        fn unstable_undeclared_trait_method(&self) -> Self::Type;
+        #[unstable(feature = "unstable_declared", issue = "38412")]
+        fn unstable_declared_trait_method(&self) -> Self::Type;
+    }
+
+    #[stable(feature = "unit_test", since = "1.0.0")]
+    impl Trait for Record {
+        type Type = i32;
+        fn stable_trait_method(&self) -> i32 { self.d_priv }
+        fn unstable_undeclared_trait_method(&self) -> i32 { self.d_priv }
+        fn unstable_declared_trait_method(&self) -> i32 { self.d_priv }
+    }
+
+    #[stable(feature = "unit_test", since = "1.0.0")]
+    impl Trait for Tuple {
+        type Type = i32;
+        fn stable_trait_method(&self) -> i32 { self.3 }
+        fn unstable_undeclared_trait_method(&self) -> i32 { self.3 }
+        fn unstable_declared_trait_method(&self) -> i32 { self.3 }
+    }
+
+    impl Record {
+        #[unstable(feature = "unstable_undeclared", issue = "38412")]
+        pub fn unstable_undeclared(&self) -> i32 { self.d_priv }
+        #[unstable(feature = "unstable_declared", issue = "38412")]
+        pub fn unstable_declared(&self) -> i32 { self.d_priv }
+        #[stable(feature = "unit_test", since = "1.0.0")]
+        pub fn stable(&self) -> i32 { self.d_priv }
+
+        #[unstable(feature = "unstable_undeclared", issue = "38412")] // SILLY
+        pub(crate) fn pub_crate(&self) -> i32 { self.d_priv }
+        #[unstable(feature = "unstable_declared", issue = "38412")] // SILLY
+        pub(in m) fn pub_mod(&self) -> i32 { self.d_priv }
+        #[stable(feature = "unit_test", since = "1.0.0")] // SILLY
+        fn private(&self) -> i32 { self.d_priv }
+    }
+
+    impl Tuple {
+        #[unstable(feature = "unstable_undeclared", issue = "38412")]
+        pub fn unstable_undeclared(&self) -> i32 { self.0 }
+        #[unstable(feature = "unstable_declared", issue = "38412")]
+        pub fn unstable_declared(&self) -> i32 { self.0 }
+        #[stable(feature = "unit_test", since = "1.0.0")]
+        pub fn stable(&self) -> i32 { self.0 }
+
+        pub(crate) fn pub_crate(&self) -> i32 { self.0 }
+        pub(in m) fn pub_mod(&self) -> i32 { self.0 }
+        fn private(&self) -> i32 { self.0 }
+    }
+}
diff --git a/src/test/ui/auxiliary/removing-extern-crate.rs b/src/test/ui/auxiliary/removing-extern-crate.rs
new file mode 100644
index 0000000..65e2cc3
--- /dev/null
+++ b/src/test/ui/auxiliary/removing-extern-crate.rs
@@ -0,0 +1 @@
+// intentionally blank
diff --git a/src/test/ui/auxiliary/rmeta-meta.rs b/src/test/ui/auxiliary/rmeta-meta.rs
new file mode 100644
index 0000000..6d8ed95
--- /dev/null
+++ b/src/test/ui/auxiliary/rmeta-meta.rs
@@ -0,0 +1,8 @@
+// no-prefer-dynamic
+// compile-flags: --emit=metadata
+
+#![crate_type="rlib"]
+
+pub struct Foo {
+    pub field: i32,
+}
diff --git a/src/test/ui/auxiliary/rmeta-rlib.rs b/src/test/ui/auxiliary/rmeta-rlib.rs
new file mode 100644
index 0000000..4a05710
--- /dev/null
+++ b/src/test/ui/auxiliary/rmeta-rlib.rs
@@ -0,0 +1,5 @@
+#![crate_type="rlib"]
+
+pub struct Foo {
+    pub field: i32,
+}
diff --git a/src/test/ui/auxiliary/stability-cfg2.rs b/src/test/ui/auxiliary/stability-cfg2.rs
new file mode 100644
index 0000000..8a28995
--- /dev/null
+++ b/src/test/ui/auxiliary/stability-cfg2.rs
@@ -0,0 +1,5 @@
+// compile-flags:--cfg foo
+
+#![cfg_attr(foo, unstable(feature = "unstable_test_feature", issue = "0"))]
+#![cfg_attr(not(foo), stable(feature = "test_feature", since = "1.0.0"))]
+#![feature(staged_api)]
diff --git a/src/test/ui/auxiliary/weak-lang-items.rs b/src/test/ui/auxiliary/weak-lang-items.rs
new file mode 100644
index 0000000..7a698cf
--- /dev/null
+++ b/src/test/ui/auxiliary/weak-lang-items.rs
@@ -0,0 +1,22 @@
+// no-prefer-dynamic
+
+// This aux-file will require the eh_personality function to be codegen'd, but
+// it hasn't been defined just yet. Make sure we don't explode.
+
+#![no_std]
+#![crate_type = "rlib"]
+
+struct A;
+
+impl core::ops::Drop for A {
+    fn drop(&mut self) {}
+}
+
+pub fn foo() {
+    let _a = A;
+    panic!("wut");
+}
+
+mod std {
+    pub use core::{option, fmt};
+}
diff --git a/src/test/ui/auxiliary/xc-private-method-lib.rs b/src/test/ui/auxiliary/xc-private-method-lib.rs
new file mode 100644
index 0000000..4d5ec6d
--- /dev/null
+++ b/src/test/ui/auxiliary/xc-private-method-lib.rs
@@ -0,0 +1,33 @@
+#![crate_type="lib"]
+
+pub struct Struct {
+    pub x: isize
+}
+
+impl Struct {
+    fn static_meth_struct() -> Struct {
+        Struct { x: 1 }
+    }
+
+    fn meth_struct(&self) -> isize {
+        self.x
+    }
+}
+
+pub enum Enum {
+    Variant1(isize),
+    Variant2(isize)
+}
+
+impl Enum {
+    fn static_meth_enum() -> Enum {
+        Enum::Variant2(10)
+    }
+
+    fn meth_enum(&self) -> isize {
+        match *self {
+            Enum::Variant1(x) |
+            Enum::Variant2(x) => x
+        }
+    }
+}
diff --git a/src/test/ui/await-keyword/2015-edition-no-warnings-with-feature-gate.rs b/src/test/ui/await-keyword/2015-edition-no-warnings-with-feature-gate.rs
new file mode 100644
index 0000000..92c60e7
--- /dev/null
+++ b/src/test/ui/await-keyword/2015-edition-no-warnings-with-feature-gate.rs
@@ -0,0 +1,16 @@
+// compile-pass
+
+#![feature(async_await)]
+#![allow(non_camel_case_types)]
+#![deny(keyword_idents)]
+
+mod outer_mod {
+    pub mod await {
+        pub struct await;
+    }
+}
+use outer_mod::await::await;
+
+fn main() {
+    match await { await => {} }
+}
diff --git a/src/test/ui/await-keyword/2015-edition-warning.fixed b/src/test/ui/await-keyword/2015-edition-warning.fixed
new file mode 100644
index 0000000..c58496c
--- /dev/null
+++ b/src/test/ui/await-keyword/2015-edition-warning.fixed
@@ -0,0 +1,27 @@
+// run-rustfix
+
+#![allow(non_camel_case_types)]
+#![deny(keyword_idents)]
+
+mod outer_mod {
+    pub mod r#await {
+//~^ ERROR `await` is a keyword
+//~| WARN was previously accepted
+        pub struct r#await;
+//~^ ERROR `await` is a keyword
+//~| WARN was previously accepted
+    }
+}
+use outer_mod::r#await::r#await;
+//~^ ERROR `await` is a keyword
+//~| ERROR `await` is a keyword
+//~| WARN was previously accepted
+//~| WARN was previously accepted
+
+fn main() {
+    match r#await { r#await => {} }
+//~^ ERROR `await` is a keyword
+//~| ERROR `await` is a keyword
+//~| WARN was previously accepted
+//~| WARN was previously accepted
+}
diff --git a/src/test/ui/await-keyword/2015-edition-warning.rs b/src/test/ui/await-keyword/2015-edition-warning.rs
new file mode 100644
index 0000000..a7543a1
--- /dev/null
+++ b/src/test/ui/await-keyword/2015-edition-warning.rs
@@ -0,0 +1,27 @@
+// run-rustfix
+
+#![allow(non_camel_case_types)]
+#![deny(keyword_idents)]
+
+mod outer_mod {
+    pub mod await {
+//~^ ERROR `await` is a keyword
+//~| WARN was previously accepted
+        pub struct await;
+//~^ ERROR `await` is a keyword
+//~| WARN was previously accepted
+    }
+}
+use outer_mod::await::await;
+//~^ ERROR `await` is a keyword
+//~| ERROR `await` is a keyword
+//~| WARN was previously accepted
+//~| WARN was previously accepted
+
+fn main() {
+    match await { await => {} }
+//~^ ERROR `await` is a keyword
+//~| ERROR `await` is a keyword
+//~| WARN was previously accepted
+//~| WARN was previously accepted
+}
diff --git a/src/test/ui/await-keyword/2015-edition-warning.stderr b/src/test/ui/await-keyword/2015-edition-warning.stderr
new file mode 100644
index 0000000..d9ae1b9
--- /dev/null
+++ b/src/test/ui/await-keyword/2015-edition-warning.stderr
@@ -0,0 +1,61 @@
+error: `await` is a keyword in the 2018 edition
+  --> $DIR/2015-edition-warning.rs:7:13
+   |
+LL |     pub mod await {
+   |             ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
+   |
+note: lint level defined here
+  --> $DIR/2015-edition-warning.rs:4:9
+   |
+LL | #![deny(keyword_idents)]
+   |         ^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: `await` is a keyword in the 2018 edition
+  --> $DIR/2015-edition-warning.rs:10:20
+   |
+LL |         pub struct await;
+   |                    ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: `await` is a keyword in the 2018 edition
+  --> $DIR/2015-edition-warning.rs:15:16
+   |
+LL | use outer_mod::await::await;
+   |                ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: `await` is a keyword in the 2018 edition
+  --> $DIR/2015-edition-warning.rs:15:23
+   |
+LL | use outer_mod::await::await;
+   |                       ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: `await` is a keyword in the 2018 edition
+  --> $DIR/2015-edition-warning.rs:22:11
+   |
+LL |     match await { await => {} }
+   |           ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: `await` is a keyword in the 2018 edition
+  --> $DIR/2015-edition-warning.rs:22:19
+   |
+LL |     match await { await => {} }
+   |                   ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/await-keyword/2018-edition-error.rs b/src/test/ui/await-keyword/2018-edition-error.rs
new file mode 100644
index 0000000..7ba3382
--- /dev/null
+++ b/src/test/ui/await-keyword/2018-edition-error.rs
@@ -0,0 +1,15 @@
+// edition:2018
+#![allow(non_camel_case_types)]
+
+mod outer_mod {
+    pub mod await { //~ ERROR `await` is a keyword
+        pub struct await; //~ ERROR `await` is a keyword
+    }
+}
+use self::outer_mod::await::await; //~ ERROR `await` is a keyword
+    //~^ ERROR `await` is a keyword
+
+fn main() {
+    match await { await => () } //~ ERROR `await` is a keyword
+    //~^ ERROR `await` is a keyword
+}
diff --git a/src/test/ui/await-keyword/2018-edition-error.stderr b/src/test/ui/await-keyword/2018-edition-error.stderr
new file mode 100644
index 0000000..19bf11a
--- /dev/null
+++ b/src/test/ui/await-keyword/2018-edition-error.stderr
@@ -0,0 +1,39 @@
+error[E0721]: `await` is a keyword in the 2018 edition
+  --> $DIR/2018-edition-error.rs:5:13
+   |
+LL |     pub mod await {
+   |             ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
+
+error[E0721]: `await` is a keyword in the 2018 edition
+  --> $DIR/2018-edition-error.rs:6:20
+   |
+LL |         pub struct await;
+   |                    ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
+
+error[E0721]: `await` is a keyword in the 2018 edition
+  --> $DIR/2018-edition-error.rs:9:22
+   |
+LL | use self::outer_mod::await::await;
+   |                      ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
+
+error[E0721]: `await` is a keyword in the 2018 edition
+  --> $DIR/2018-edition-error.rs:9:29
+   |
+LL | use self::outer_mod::await::await;
+   |                             ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
+
+error[E0721]: `await` is a keyword in the 2018 edition
+  --> $DIR/2018-edition-error.rs:13:11
+   |
+LL |     match await { await => () }
+   |           ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
+
+error[E0721]: `await` is a keyword in the 2018 edition
+  --> $DIR/2018-edition-error.rs:13:19
+   |
+LL |     match await { await => () }
+   |                   ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0721`.
diff --git a/src/test/ui/await-keyword/2018-edition-no-error-with-feature-gate.rs b/src/test/ui/await-keyword/2018-edition-no-error-with-feature-gate.rs
new file mode 100644
index 0000000..52d32c8
--- /dev/null
+++ b/src/test/ui/await-keyword/2018-edition-no-error-with-feature-gate.rs
@@ -0,0 +1,16 @@
+// compile-pass
+// edition:2018
+
+#![allow(non_camel_case_types)]
+#![feature(async_await)]
+
+mod outer_mod {
+    pub mod await {
+        pub struct await;
+    }
+}
+use self::outer_mod::await::await;
+
+fn main() {
+    match await { await => () }
+}
diff --git a/src/test/ui/await-keyword/post_expansion_error.rs b/src/test/ui/await-keyword/post_expansion_error.rs
new file mode 100644
index 0000000..96dd480
--- /dev/null
+++ b/src/test/ui/await-keyword/post_expansion_error.rs
@@ -0,0 +1,10 @@
+// edition:2018
+
+macro_rules! r#await {
+    () => { println!("Hello, world!") }
+}
+
+fn main() {
+    await!()
+    //~^ ERROR `await` is a keyword
+}
diff --git a/src/test/ui/await-keyword/post_expansion_error.stderr b/src/test/ui/await-keyword/post_expansion_error.stderr
new file mode 100644
index 0000000..76ae35b
--- /dev/null
+++ b/src/test/ui/await-keyword/post_expansion_error.stderr
@@ -0,0 +1,9 @@
+error[E0721]: `await` is a keyword in the 2018 edition
+  --> $DIR/post_expansion_error.rs:8:5
+   |
+LL |     await!()
+   |     ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0721`.
diff --git a/src/test/ui/bad/bad-const-type.rs b/src/test/ui/bad/bad-const-type.rs
new file mode 100644
index 0000000..8121929
--- /dev/null
+++ b/src/test/ui/bad/bad-const-type.rs
@@ -0,0 +1,6 @@
+static i: String = 10;
+//~^ ERROR mismatched types
+//~| expected type `std::string::String`
+//~| found type `{integer}`
+//~| expected struct `std::string::String`, found integer
+fn main() { println!("{}", i); }
diff --git a/src/test/ui/bad/bad-const-type.stderr b/src/test/ui/bad/bad-const-type.stderr
new file mode 100644
index 0000000..677dc72
--- /dev/null
+++ b/src/test/ui/bad/bad-const-type.stderr
@@ -0,0 +1,15 @@
+error[E0308]: mismatched types
+  --> $DIR/bad-const-type.rs:1:20
+   |
+LL | static i: String = 10;
+   |                    ^^
+   |                    |
+   |                    expected struct `std::string::String`, found integer
+   |                    help: try using a conversion method: `10.to_string()`
+   |
+   = note: expected type `std::string::String`
+              found type `{integer}`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/bad/bad-crate-name.rs b/src/test/ui/bad/bad-crate-name.rs
new file mode 100644
index 0000000..837d5c3
--- /dev/null
+++ b/src/test/ui/bad/bad-crate-name.rs
@@ -0,0 +1,5 @@
+extern crate krate-name-here;
+//~^ ERROR crate name using dashes are not valid in `extern crate` statements
+//~| ERROR can't find crate for `krate_name_here`
+
+fn main() {}
diff --git a/src/test/ui/bad/bad-crate-name.stderr b/src/test/ui/bad/bad-crate-name.stderr
new file mode 100644
index 0000000..a08535a
--- /dev/null
+++ b/src/test/ui/bad/bad-crate-name.stderr
@@ -0,0 +1,19 @@
+error: crate name using dashes are not valid in `extern crate` statements
+  --> $DIR/bad-crate-name.rs:1:14
+   |
+LL | extern crate krate-name-here;
+   |              ^^^^^^^^^^^^^^^ dash-separated idents are not valid
+help: if the original crate name uses dashes you need to use underscores in the code
+   |
+LL | extern crate krate_name_here;
+   |                   ^    ^
+
+error[E0463]: can't find crate for `krate_name_here`
+  --> $DIR/bad-crate-name.rs:1:1
+   |
+LL | extern crate krate-name-here;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't find crate
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0463`.
diff --git a/src/test/ui/bad/bad-env-capture.rs b/src/test/ui/bad/bad-env-capture.rs
new file mode 100644
index 0000000..83fd254
--- /dev/null
+++ b/src/test/ui/bad/bad-env-capture.rs
@@ -0,0 +1,6 @@
+// error-pattern: can't capture dynamic environment in a fn item
+fn foo() {
+    let x: isize;
+    fn bar() { log(debug, x); }
+}
+fn main() { foo(); }
diff --git a/src/test/ui/bad/bad-env-capture.stderr b/src/test/ui/bad/bad-env-capture.stderr
new file mode 100644
index 0000000..04975b0
--- /dev/null
+++ b/src/test/ui/bad/bad-env-capture.stderr
@@ -0,0 +1,24 @@
+error[E0434]: can't capture dynamic environment in a fn item
+  --> $DIR/bad-env-capture.rs:4:27
+   |
+LL |     fn bar() { log(debug, x); }
+   |                           ^
+   |
+   = help: use the `|| { ... }` closure form instead
+
+error[E0425]: cannot find function `log` in this scope
+  --> $DIR/bad-env-capture.rs:4:16
+   |
+LL |     fn bar() { log(debug, x); }
+   |                ^^^ not found in this scope
+
+error[E0425]: cannot find value `debug` in this scope
+  --> $DIR/bad-env-capture.rs:4:20
+   |
+LL |     fn bar() { log(debug, x); }
+   |                    ^^^^^ not found in this scope
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0425, E0434.
+For more information about an error, try `rustc --explain E0425`.
diff --git a/src/test/ui/bad/bad-env-capture2.rs b/src/test/ui/bad/bad-env-capture2.rs
new file mode 100644
index 0000000..b04569c
--- /dev/null
+++ b/src/test/ui/bad/bad-env-capture2.rs
@@ -0,0 +1,5 @@
+// error-pattern: can't capture dynamic environment in a fn item
+fn foo(x: isize) {
+    fn bar() { log(debug, x); }
+}
+fn main() { foo(2); }
diff --git a/src/test/ui/bad/bad-env-capture2.stderr b/src/test/ui/bad/bad-env-capture2.stderr
new file mode 100644
index 0000000..f7524c6
--- /dev/null
+++ b/src/test/ui/bad/bad-env-capture2.stderr
@@ -0,0 +1,24 @@
+error[E0434]: can't capture dynamic environment in a fn item
+  --> $DIR/bad-env-capture2.rs:3:27
+   |
+LL |     fn bar() { log(debug, x); }
+   |                           ^
+   |
+   = help: use the `|| { ... }` closure form instead
+
+error[E0425]: cannot find function `log` in this scope
+  --> $DIR/bad-env-capture2.rs:3:16
+   |
+LL |     fn bar() { log(debug, x); }
+   |                ^^^ not found in this scope
+
+error[E0425]: cannot find value `debug` in this scope
+  --> $DIR/bad-env-capture2.rs:3:20
+   |
+LL |     fn bar() { log(debug, x); }
+   |                    ^^^^^ not found in this scope
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0425, E0434.
+For more information about an error, try `rustc --explain E0425`.
diff --git a/src/test/ui/bad/bad-env-capture3.rs b/src/test/ui/bad/bad-env-capture3.rs
new file mode 100644
index 0000000..62f12fd
--- /dev/null
+++ b/src/test/ui/bad/bad-env-capture3.rs
@@ -0,0 +1,8 @@
+// error-pattern: can't capture dynamic environment in a fn item
+fn foo(x: isize) {
+    fn mth() {
+        fn bar() { log(debug, x); }
+    }
+}
+
+fn main() { foo(2); }
diff --git a/src/test/ui/bad/bad-env-capture3.stderr b/src/test/ui/bad/bad-env-capture3.stderr
new file mode 100644
index 0000000..137612c
--- /dev/null
+++ b/src/test/ui/bad/bad-env-capture3.stderr
@@ -0,0 +1,24 @@
+error[E0434]: can't capture dynamic environment in a fn item
+  --> $DIR/bad-env-capture3.rs:4:31
+   |
+LL |         fn bar() { log(debug, x); }
+   |                               ^
+   |
+   = help: use the `|| { ... }` closure form instead
+
+error[E0425]: cannot find function `log` in this scope
+  --> $DIR/bad-env-capture3.rs:4:20
+   |
+LL |         fn bar() { log(debug, x); }
+   |                    ^^^ not found in this scope
+
+error[E0425]: cannot find value `debug` in this scope
+  --> $DIR/bad-env-capture3.rs:4:24
+   |
+LL |         fn bar() { log(debug, x); }
+   |                        ^^^^^ not found in this scope
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0425, E0434.
+For more information about an error, try `rustc --explain E0425`.
diff --git a/src/test/ui/bad/bad-expr-lhs.rs b/src/test/ui/bad/bad-expr-lhs.rs
new file mode 100644
index 0000000..2cd8bc9
--- /dev/null
+++ b/src/test/ui/bad/bad-expr-lhs.rs
@@ -0,0 +1,10 @@
+fn main() {
+    1 = 2; //~ ERROR invalid left-hand side expression
+    1 += 2; //~ ERROR invalid left-hand side expression
+    (1, 2) = (3, 4); //~ ERROR invalid left-hand side expression
+
+    let (a, b) = (1, 2);
+    (a, b) = (3, 4); //~ ERROR invalid left-hand side expression
+
+    None = Some(3); //~ ERROR invalid left-hand side expression
+}
diff --git a/src/test/ui/bad/bad-expr-lhs.stderr b/src/test/ui/bad/bad-expr-lhs.stderr
new file mode 100644
index 0000000..3e41b7e
--- /dev/null
+++ b/src/test/ui/bad/bad-expr-lhs.stderr
@@ -0,0 +1,34 @@
+error[E0070]: invalid left-hand side expression
+  --> $DIR/bad-expr-lhs.rs:2:5
+   |
+LL |     1 = 2;
+   |     ^^^^^ left-hand of expression not valid
+
+error[E0067]: invalid left-hand side expression
+  --> $DIR/bad-expr-lhs.rs:3:5
+   |
+LL |     1 += 2;
+   |     ^ invalid expression for left-hand side
+
+error[E0070]: invalid left-hand side expression
+  --> $DIR/bad-expr-lhs.rs:4:5
+   |
+LL |     (1, 2) = (3, 4);
+   |     ^^^^^^^^^^^^^^^ left-hand of expression not valid
+
+error[E0070]: invalid left-hand side expression
+  --> $DIR/bad-expr-lhs.rs:7:5
+   |
+LL |     (a, b) = (3, 4);
+   |     ^^^^^^^^^^^^^^^ left-hand of expression not valid
+
+error[E0070]: invalid left-hand side expression
+  --> $DIR/bad-expr-lhs.rs:9:5
+   |
+LL |     None = Some(3);
+   |     ^^^^^^^^^^^^^^ left-hand of expression not valid
+
+error: aborting due to 5 previous errors
+
+Some errors occurred: E0067, E0070.
+For more information about an error, try `rustc --explain E0067`.
diff --git a/src/test/ui/bad/bad-expr-path.rs b/src/test/ui/bad/bad-expr-path.rs
new file mode 100644
index 0000000..99ba932
--- /dev/null
+++ b/src/test/ui/bad/bad-expr-path.rs
@@ -0,0 +1,8 @@
+mod m1 {}
+
+fn main(arguments: Vec<String>) { //~ ERROR main function has wrong type
+    log(debug, m1::arguments);
+    //~^ ERROR cannot find function `log` in this scope
+    //~| ERROR cannot find value `debug` in this scope
+    //~| ERROR cannot find value `arguments` in module `m1`
+}
diff --git a/src/test/ui/bad/bad-expr-path.stderr b/src/test/ui/bad/bad-expr-path.stderr
new file mode 100644
index 0000000..6dec74e
--- /dev/null
+++ b/src/test/ui/bad/bad-expr-path.stderr
@@ -0,0 +1,31 @@
+error[E0425]: cannot find function `log` in this scope
+  --> $DIR/bad-expr-path.rs:4:5
+   |
+LL |     log(debug, m1::arguments);
+   |     ^^^ not found in this scope
+
+error[E0425]: cannot find value `debug` in this scope
+  --> $DIR/bad-expr-path.rs:4:9
+   |
+LL |     log(debug, m1::arguments);
+   |         ^^^^^ not found in this scope
+
+error[E0425]: cannot find value `arguments` in module `m1`
+  --> $DIR/bad-expr-path.rs:4:20
+   |
+LL |     log(debug, m1::arguments);
+   |                    ^^^^^^^^^ not found in `m1`
+
+error[E0580]: main function has wrong type
+  --> $DIR/bad-expr-path.rs:3:1
+   |
+LL | fn main(arguments: Vec<String>) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect number of function parameters
+   |
+   = note: expected type `fn()`
+              found type `fn(std::vec::Vec<std::string::String>)`
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0425, E0580.
+For more information about an error, try `rustc --explain E0425`.
diff --git a/src/test/ui/bad/bad-expr-path2.rs b/src/test/ui/bad/bad-expr-path2.rs
new file mode 100644
index 0000000..43bd290
--- /dev/null
+++ b/src/test/ui/bad/bad-expr-path2.rs
@@ -0,0 +1,10 @@
+mod m1 {
+    pub mod arguments {}
+}
+
+fn main(arguments: Vec<String>) { //~ ERROR main function has wrong type
+    log(debug, m1::arguments);
+    //~^ ERROR cannot find function `log` in this scope
+    //~| ERROR cannot find value `debug` in this scope
+    //~| ERROR expected value, found module `m1::arguments`
+}
diff --git a/src/test/ui/bad/bad-expr-path2.stderr b/src/test/ui/bad/bad-expr-path2.stderr
new file mode 100644
index 0000000..8212b23
--- /dev/null
+++ b/src/test/ui/bad/bad-expr-path2.stderr
@@ -0,0 +1,31 @@
+error[E0425]: cannot find function `log` in this scope
+  --> $DIR/bad-expr-path2.rs:6:5
+   |
+LL |     log(debug, m1::arguments);
+   |     ^^^ not found in this scope
+
+error[E0425]: cannot find value `debug` in this scope
+  --> $DIR/bad-expr-path2.rs:6:9
+   |
+LL |     log(debug, m1::arguments);
+   |         ^^^^^ not found in this scope
+
+error[E0423]: expected value, found module `m1::arguments`
+  --> $DIR/bad-expr-path2.rs:6:16
+   |
+LL |     log(debug, m1::arguments);
+   |                ^^^^^^^^^^^^^ not a value
+
+error[E0580]: main function has wrong type
+  --> $DIR/bad-expr-path2.rs:5:1
+   |
+LL | fn main(arguments: Vec<String>) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect number of function parameters
+   |
+   = note: expected type `fn()`
+              found type `fn(std::vec::Vec<std::string::String>)`
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0423, E0425, E0580.
+For more information about an error, try `rustc --explain E0423`.
diff --git a/src/test/ui/bad/bad-extern-link-attrs.rs b/src/test/ui/bad/bad-extern-link-attrs.rs
new file mode 100644
index 0000000..f042832
--- /dev/null
+++ b/src/test/ui/bad/bad-extern-link-attrs.rs
@@ -0,0 +1,7 @@
+#[link()] //~ ERROR: specified without `name =
+#[link(name = "")] //~ ERROR: with empty name
+#[link(name = "foo")]
+#[link(name = "foo", kind = "bar")] //~ ERROR: unknown kind
+extern {}
+
+fn main() {}
diff --git a/src/test/ui/bad/bad-extern-link-attrs.stderr b/src/test/ui/bad/bad-extern-link-attrs.stderr
new file mode 100644
index 0000000..a77f5f9
--- /dev/null
+++ b/src/test/ui/bad/bad-extern-link-attrs.stderr
@@ -0,0 +1,24 @@
+error[E0459]: #[link(...)] specified without `name = "foo"`
+  --> $DIR/bad-extern-link-attrs.rs:1:1
+   |
+LL | #[link()]
+   | ^^^^^^^^^ missing `name` argument
+
+error[E0454]: #[link(name = "")] given with empty name
+  --> $DIR/bad-extern-link-attrs.rs:2:1
+   |
+LL | #[link(name = "")]
+   | ^^^^^^^^^^^^^^^^^^ empty name given
+
+error[E0458]: unknown kind: `bar`
+  --> $DIR/bad-extern-link-attrs.rs:4:22
+   |
+LL | #[link(name = "foo", kind = "bar")]
+   | ---------------------^^^^^^^^^^^^--
+   |                      |
+   |                      unknown kind
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0454, E0458, E0459.
+For more information about an error, try `rustc --explain E0454`.
diff --git a/src/test/ui/bad/bad-intrinsic-monomorphization.rs b/src/test/ui/bad/bad-intrinsic-monomorphization.rs
new file mode 100644
index 0000000..a29723f3
--- /dev/null
+++ b/src/test/ui/bad/bad-intrinsic-monomorphization.rs
@@ -0,0 +1,30 @@
+#![feature(repr_simd, platform_intrinsics, core_intrinsics)]
+#![allow(warnings)]
+#![crate_type = "rlib"]
+
+// Bad monomorphizations could previously cause LLVM asserts even though the
+// error was caught in the compiler.
+
+extern "platform-intrinsic" {
+    fn simd_add<T>(x: T, y: T) -> T;
+}
+
+use std::intrinsics;
+
+#[derive(Copy, Clone)]
+pub struct Foo(i64);
+
+pub fn test_cttz(v: Foo) -> Foo {
+    intrinsics::cttz(v)
+    //~^ ERROR `cttz` intrinsic: expected basic integer type, found `Foo`
+}
+
+pub unsafe fn test_fadd_fast(a: Foo, b: Foo) -> Foo {
+    intrinsics::fadd_fast(a, b)
+    //~^ ERROR `fadd_fast` intrinsic: expected basic float type, found `Foo`
+}
+
+pub unsafe fn test_simd_add(a: Foo, b: Foo) -> Foo {
+    simd_add(a, b)
+    //~^ ERROR `simd_add` intrinsic: expected SIMD input type, found non-SIMD `Foo`
+}
diff --git a/src/test/ui/bad/bad-intrinsic-monomorphization.stderr b/src/test/ui/bad/bad-intrinsic-monomorphization.stderr
new file mode 100644
index 0000000..dee33f5
--- /dev/null
+++ b/src/test/ui/bad/bad-intrinsic-monomorphization.stderr
@@ -0,0 +1,21 @@
+error[E0511]: invalid monomorphization of `cttz` intrinsic: expected basic integer type, found `Foo`
+  --> $DIR/bad-intrinsic-monomorphization.rs:18:5
+   |
+LL |     intrinsics::cttz(v)
+   |     ^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `fadd_fast` intrinsic: expected basic float type, found `Foo`
+  --> $DIR/bad-intrinsic-monomorphization.rs:23:5
+   |
+LL |     intrinsics::fadd_fast(a, b)
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_add` intrinsic: expected SIMD input type, found non-SIMD `Foo`
+  --> $DIR/bad-intrinsic-monomorphization.rs:28:5
+   |
+LL |     simd_add(a, b)
+   |     ^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0511`.
diff --git a/src/test/ui/bad/bad-lint-cap.rs b/src/test/ui/bad/bad-lint-cap.rs
new file mode 100644
index 0000000..e65c831
--- /dev/null
+++ b/src/test/ui/bad/bad-lint-cap.rs
@@ -0,0 +1,4 @@
+// compile-flags: --cap-lints test
+// error-pattern: unknown lint level: `test`
+
+fn main() {}
diff --git a/src/test/ui/bad/bad-lint-cap.stderr b/src/test/ui/bad/bad-lint-cap.stderr
new file mode 100644
index 0000000..f284dbf
--- /dev/null
+++ b/src/test/ui/bad/bad-lint-cap.stderr
@@ -0,0 +1,2 @@
+error: unknown lint level: `test`
+
diff --git a/src/test/ui/bad/bad-lint-cap2.rs b/src/test/ui/bad/bad-lint-cap2.rs
new file mode 100644
index 0000000..8bc8aca
--- /dev/null
+++ b/src/test/ui/bad/bad-lint-cap2.rs
@@ -0,0 +1,8 @@
+// compile-flags: --cap-lints deny
+
+#![warn(unused)]
+#![deny(warnings)]
+
+use std::option; //~ ERROR
+
+fn main() {}
diff --git a/src/test/ui/bad/bad-lint-cap2.stderr b/src/test/ui/bad/bad-lint-cap2.stderr
new file mode 100644
index 0000000..f6e67e6
--- /dev/null
+++ b/src/test/ui/bad/bad-lint-cap2.stderr
@@ -0,0 +1,15 @@
+error: unused import: `std::option`
+  --> $DIR/bad-lint-cap2.rs:6:5
+   |
+LL | use std::option;
+   |     ^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/bad-lint-cap2.rs:4:9
+   |
+LL | #![deny(warnings)]
+   |         ^^^^^^^^
+   = note: #[deny(unused_imports)] implied by #[deny(warnings)]
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/bad/bad-lint-cap3.rs b/src/test/ui/bad/bad-lint-cap3.rs
new file mode 100644
index 0000000..8aab38e
--- /dev/null
+++ b/src/test/ui/bad/bad-lint-cap3.rs
@@ -0,0 +1,11 @@
+// compile-flags: --cap-lints warn
+
+#![warn(unused)]
+#![deny(warnings)]
+// compile-pass
+// skip-codegen
+use std::option; //~ WARN
+
+
+fn main() {}
+
diff --git a/src/test/ui/bad/bad-lint-cap3.stderr b/src/test/ui/bad/bad-lint-cap3.stderr
new file mode 100644
index 0000000..a1ea3f7
--- /dev/null
+++ b/src/test/ui/bad/bad-lint-cap3.stderr
@@ -0,0 +1,13 @@
+warning: unused import: `std::option`
+  --> $DIR/bad-lint-cap3.rs:7:5
+   |
+LL | use std::option;
+   |     ^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/bad-lint-cap3.rs:4:9
+   |
+LL | #![deny(warnings)]
+   |         ^^^^^^^^
+   = note: #[warn(unused_imports)] implied by #[warn(warnings)]
+
diff --git a/src/test/ui/bad/bad-main.rs b/src/test/ui/bad/bad-main.rs
new file mode 100644
index 0000000..c9e2f02
--- /dev/null
+++ b/src/test/ui/bad/bad-main.rs
@@ -0,0 +1 @@
+fn main(x: isize) { } //~ ERROR: main function has wrong type [E0580]
diff --git a/src/test/ui/bad/bad-main.stderr b/src/test/ui/bad/bad-main.stderr
new file mode 100644
index 0000000..c7f15e7
--- /dev/null
+++ b/src/test/ui/bad/bad-main.stderr
@@ -0,0 +1,12 @@
+error[E0580]: main function has wrong type
+  --> $DIR/bad-main.rs:1:1
+   |
+LL | fn main(x: isize) { }
+   | ^^^^^^^^^^^^^^^^^ incorrect number of function parameters
+   |
+   = note: expected type `fn()`
+              found type `fn(isize)`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0580`.
diff --git a/src/test/ui/bad/bad-method-typaram-kind.rs b/src/test/ui/bad/bad-method-typaram-kind.rs
new file mode 100644
index 0000000..b088eae
--- /dev/null
+++ b/src/test/ui/bad/bad-method-typaram-kind.rs
@@ -0,0 +1,14 @@
+fn foo<T:'static>() {
+    1.bar::<T>(); //~ ERROR `T` cannot be sent between threads safely
+}
+
+trait Bar {
+    fn bar<T:Send>(&self);
+}
+
+impl Bar for usize {
+    fn bar<T:Send>(&self) {
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/bad/bad-method-typaram-kind.stderr b/src/test/ui/bad/bad-method-typaram-kind.stderr
new file mode 100644
index 0000000..c72b965
--- /dev/null
+++ b/src/test/ui/bad/bad-method-typaram-kind.stderr
@@ -0,0 +1,12 @@
+error[E0277]: `T` cannot be sent between threads safely
+  --> $DIR/bad-method-typaram-kind.rs:2:7
+   |
+LL |     1.bar::<T>();
+   |       ^^^ `T` cannot be sent between threads safely
+   |
+   = help: the trait `std::marker::Send` is not implemented for `T`
+   = help: consider adding a `where T: std::marker::Send` bound
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/bad/bad-mid-path-type-params.rs b/src/test/ui/bad/bad-mid-path-type-params.rs
new file mode 100644
index 0000000..016b1d6
--- /dev/null
+++ b/src/test/ui/bad/bad-mid-path-type-params.rs
@@ -0,0 +1,43 @@
+struct S<T> {
+    contents: T,
+}
+
+impl<T> S<T> {
+    fn new<U>(x: T, _: U) -> S<T> {
+        S {
+            contents: x,
+        }
+    }
+}
+
+trait Trait<T> {
+    fn new<U>(x: T, y: U) -> Self;
+}
+
+struct S2 {
+    contents: isize,
+}
+
+impl Trait<isize> for S2 {
+    fn new<U>(x: isize, _: U) -> S2 {
+        S2 {
+            contents: x,
+        }
+    }
+}
+
+fn foo<'a>() {
+    let _ = S::new::<isize,f64>(1, 1.0);
+    //~^ ERROR wrong number of type arguments
+
+    let _ = S::<'a,isize>::new::<f64>(1, 1.0);
+    //~^ ERROR wrong number of lifetime arguments
+
+    let _: S2 = Trait::new::<isize,f64>(1, 1.0);
+    //~^ ERROR wrong number of type arguments
+
+    let _: S2 = Trait::<'a,isize>::new::<f64>(1, 1.0);
+    //~^ ERROR wrong number of lifetime arguments
+}
+
+fn main() {}
diff --git a/src/test/ui/bad/bad-mid-path-type-params.stderr b/src/test/ui/bad/bad-mid-path-type-params.stderr
new file mode 100644
index 0000000..ef53c9a
--- /dev/null
+++ b/src/test/ui/bad/bad-mid-path-type-params.stderr
@@ -0,0 +1,27 @@
+error[E0107]: wrong number of type arguments: expected 1, found 2
+  --> $DIR/bad-mid-path-type-params.rs:30:28
+   |
+LL |     let _ = S::new::<isize,f64>(1, 1.0);
+   |                            ^^^ unexpected type argument
+
+error[E0107]: wrong number of lifetime arguments: expected 0, found 1
+  --> $DIR/bad-mid-path-type-params.rs:33:17
+   |
+LL |     let _ = S::<'a,isize>::new::<f64>(1, 1.0);
+   |                 ^^ unexpected lifetime argument
+
+error[E0107]: wrong number of type arguments: expected 1, found 2
+  --> $DIR/bad-mid-path-type-params.rs:36:36
+   |
+LL |     let _: S2 = Trait::new::<isize,f64>(1, 1.0);
+   |                                    ^^^ unexpected type argument
+
+error[E0107]: wrong number of lifetime arguments: expected 0, found 1
+  --> $DIR/bad-mid-path-type-params.rs:39:25
+   |
+LL |     let _: S2 = Trait::<'a,isize>::new::<f64>(1, 1.0);
+   |                         ^^ unexpected lifetime argument
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0107`.
diff --git a/src/test/ui/bad/bad-module.rs b/src/test/ui/bad/bad-module.rs
new file mode 100644
index 0000000..a496c81
--- /dev/null
+++ b/src/test/ui/bad/bad-module.rs
@@ -0,0 +1,7 @@
+fn main() {
+    let foo = thing::len(Vec::new());
+    //~^ ERROR failed to resolve: use of undeclared type or module `thing`
+
+    let foo = foo::bar::baz();
+    //~^ ERROR failed to resolve: use of undeclared type or module `foo`
+}
diff --git a/src/test/ui/bad/bad-module.stderr b/src/test/ui/bad/bad-module.stderr
new file mode 100644
index 0000000..45d4c5a
--- /dev/null
+++ b/src/test/ui/bad/bad-module.stderr
@@ -0,0 +1,15 @@
+error[E0433]: failed to resolve: use of undeclared type or module `thing`
+  --> $DIR/bad-module.rs:2:15
+   |
+LL |     let foo = thing::len(Vec::new());
+   |               ^^^^^ use of undeclared type or module `thing`
+
+error[E0433]: failed to resolve: use of undeclared type or module `foo`
+  --> $DIR/bad-module.rs:5:15
+   |
+LL |     let foo = foo::bar::baz();
+   |               ^^^ use of undeclared type or module `foo`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/bad/bad-sized.rs b/src/test/ui/bad/bad-sized.rs
new file mode 100644
index 0000000..0da4e45
--- /dev/null
+++ b/src/test/ui/bad/bad-sized.rs
@@ -0,0 +1,8 @@
+trait Trait {}
+
+pub fn main() {
+    let x: Vec<Trait + Sized> = Vec::new();
+    //~^ ERROR only auto traits can be used as additional traits in a trait object
+    //~| ERROR the size for values of type
+    //~| ERROR the size for values of type
+}
diff --git a/src/test/ui/bad/bad-sized.stderr b/src/test/ui/bad/bad-sized.stderr
new file mode 100644
index 0000000..51b8474
--- /dev/null
+++ b/src/test/ui/bad/bad-sized.stderr
@@ -0,0 +1,30 @@
+error[E0225]: only auto traits can be used as additional traits in a trait object
+  --> $DIR/bad-sized.rs:4:24
+   |
+LL |     let x: Vec<Trait + Sized> = Vec::new();
+   |                        ^^^^^ non-auto additional trait
+
+error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time
+  --> $DIR/bad-sized.rs:4:12
+   |
+LL |     let x: Vec<Trait + Sized> = Vec::new();
+   |            ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `dyn Trait`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: required by `std::vec::Vec`
+
+error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time
+  --> $DIR/bad-sized.rs:4:33
+   |
+LL |     let x: Vec<Trait + Sized> = Vec::new();
+   |                                 ^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `dyn Trait`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: required by `std::vec::Vec::<T>::new`
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0225, E0277.
+For more information about an error, try `rustc --explain E0225`.
diff --git a/src/test/ui/bad/bad-type-env-capture.rs b/src/test/ui/bad/bad-type-env-capture.rs
new file mode 100644
index 0000000..53dfb13
--- /dev/null
+++ b/src/test/ui/bad/bad-type-env-capture.rs
@@ -0,0 +1,4 @@
+fn foo<T>() {
+    fn bar(b: T) { } //~ ERROR can't use generic parameters from outer
+}
+fn main() { }
diff --git a/src/test/ui/bad/bad-type-env-capture.stderr b/src/test/ui/bad/bad-type-env-capture.stderr
new file mode 100644
index 0000000..a459c00
--- /dev/null
+++ b/src/test/ui/bad/bad-type-env-capture.stderr
@@ -0,0 +1,13 @@
+error[E0401]: can't use generic parameters from outer function
+  --> $DIR/bad-type-env-capture.rs:2:15
+   |
+LL | fn foo<T>() {
+   |        - type variable from outer function
+LL |     fn bar(b: T) { }
+   |        ---    ^ use of generic parameter from outer function
+   |        |
+   |        help: try using a local generic parameter instead: `bar<T>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0401`.
diff --git a/src/test/ui/bastion-of-the-turbofish.rs b/src/test/ui/bastion-of-the-turbofish.rs
new file mode 100644
index 0000000..0716fcf
--- /dev/null
+++ b/src/test/ui/bastion-of-the-turbofish.rs
@@ -0,0 +1,36 @@
+// compile-pass
+
+// Bastion of the Turbofish
+// ------------------------
+// Beware travellers, lest you venture into waters callous and unforgiving,
+// where hope must be abandoned, ere it is cruelly torn from you. For here
+// stands the bastion of the Turbofish: an impenetrable fortress holding
+// unshaking against those who would dare suggest the supererogation of the
+// Turbofish.
+//
+// Once I was young and foolish and had the impudence to imagine that I could
+// shake free from the coils by which that creature had us tightly bound. I
+// dared to suggest that there was a better way: a brighter future, in which
+// Rustaceans both new and old could be rid of that vile beast. But alas! In
+// my foolhardiness my ignorance was unveiled and my dreams were dashed
+// unforgivingly against the rock of syntactic ambiguity.
+//
+// This humble program, small and insignificant though it might seem,
+// demonstrates that to which we had previously cast a blind eye: an ambiguity
+// in permitting generic arguments to be provided without the consent of the
+// Great Turbofish. Should you be so naïve as to try to revolt against its
+// mighty clutches, here shall its wrath be indomitably displayed. This
+// program must pass for all eternity, fundamentally at odds with an impetuous
+// rebellion against the Turbofish.
+//
+// My heart aches in sorrow, for I know I am defeated. Let this be a warning
+// to all those who come after. Here stands the bastion of the Turbofish.
+
+// See https://github.com/rust-lang/rust/pull/53562
+// and https://github.com/rust-lang/rfcs/pull/2527
+// for context.
+
+fn main() {
+    let (oh, woe, is, me) = ("the", "Turbofish", "remains", "undefeated");
+    let _: (bool, bool) = (oh<woe, is>(me));
+}
diff --git a/src/test/ui/binary-op-on-double-ref.rs b/src/test/ui/binary-op-on-double-ref.rs
new file mode 100644
index 0000000..6490cc7
--- /dev/null
+++ b/src/test/ui/binary-op-on-double-ref.rs
@@ -0,0 +1,8 @@
+fn main() {
+    let v = vec![1, 2, 3, 4, 5, 6, 7, 8, 9];
+    let vr = v.iter().filter(|x| {
+        x % 2 == 0
+        //~^ ERROR binary operation `%` cannot be applied to type `&&{integer}`
+    });
+    println!("{:?}", vr);
+}
diff --git a/src/test/ui/binary-op-on-double-ref.stderr b/src/test/ui/binary-op-on-double-ref.stderr
new file mode 100644
index 0000000..d036f06
--- /dev/null
+++ b/src/test/ui/binary-op-on-double-ref.stderr
@@ -0,0 +1,13 @@
+error[E0369]: binary operation `%` cannot be applied to type `&&{integer}`
+  --> $DIR/binary-op-on-double-ref.rs:4:11
+   |
+LL |         x % 2 == 0
+   |         - ^ - {integer}
+   |         |
+   |         &&{integer}
+   |
+   = help: `%` can be used on '{integer}', you can dereference `x`: `*x`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0369`.
diff --git a/src/test/ui/bind-by-move/bind-by-move-neither-can-live-while-the-other-survives-2.rs b/src/test/ui/bind-by-move/bind-by-move-neither-can-live-while-the-other-survives-2.rs
new file mode 100644
index 0000000..238f2d9
--- /dev/null
+++ b/src/test/ui/bind-by-move/bind-by-move-neither-can-live-while-the-other-survives-2.rs
@@ -0,0 +1,15 @@
+struct X { x: (), }
+
+impl Drop for X {
+    fn drop(&mut self) {
+        println!("destructor runs");
+    }
+}
+
+fn main() {
+    let x = Some((X { x: () }, X { x: () }));
+    match x {
+        Some((ref _y, _z)) => { }, //~ ERROR cannot bind by-move and by-ref in the same pattern
+        None => panic!()
+    }
+}
diff --git a/src/test/ui/bind-by-move/bind-by-move-neither-can-live-while-the-other-survives-2.stderr b/src/test/ui/bind-by-move/bind-by-move-neither-can-live-while-the-other-survives-2.stderr
new file mode 100644
index 0000000..9157fe0
--- /dev/null
+++ b/src/test/ui/bind-by-move/bind-by-move-neither-can-live-while-the-other-survives-2.stderr
@@ -0,0 +1,11 @@
+error[E0009]: cannot bind by-move and by-ref in the same pattern
+  --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-2.rs:12:23
+   |
+LL |         Some((ref _y, _z)) => { },
+   |               ------  ^^ by-move pattern here
+   |               |
+   |               both by-ref and by-move used
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0009`.
diff --git a/src/test/ui/bind-by-move/bind-by-move-neither-can-live-while-the-other-survives-3.rs b/src/test/ui/bind-by-move/bind-by-move-neither-can-live-while-the-other-survives-3.rs
new file mode 100644
index 0000000..e8357e9
--- /dev/null
+++ b/src/test/ui/bind-by-move/bind-by-move-neither-can-live-while-the-other-survives-3.rs
@@ -0,0 +1,18 @@
+struct X { x: (), }
+
+impl Drop for X {
+    fn drop(&mut self) {
+        println!("destructor runs");
+    }
+}
+
+enum DoubleOption<T,U> { Some2(T,U), None2 }
+
+fn main() {
+    let x = DoubleOption::Some2(X { x: () }, X { x: () });
+    match x {
+        DoubleOption::Some2(ref _y, _z) => { },
+        //~^ ERROR cannot bind by-move and by-ref in the same pattern
+        DoubleOption::None2 => panic!()
+    }
+}
diff --git a/src/test/ui/bind-by-move/bind-by-move-neither-can-live-while-the-other-survives-3.stderr b/src/test/ui/bind-by-move/bind-by-move-neither-can-live-while-the-other-survives-3.stderr
new file mode 100644
index 0000000..d535471
--- /dev/null
+++ b/src/test/ui/bind-by-move/bind-by-move-neither-can-live-while-the-other-survives-3.stderr
@@ -0,0 +1,11 @@
+error[E0009]: cannot bind by-move and by-ref in the same pattern
+  --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-3.rs:14:37
+   |
+LL |         DoubleOption::Some2(ref _y, _z) => { },
+   |                             ------  ^^ by-move pattern here
+   |                             |
+   |                             both by-ref and by-move used
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0009`.
diff --git a/src/test/ui/bind-by-move/bind-by-move-neither-can-live-while-the-other-survives-4.rs b/src/test/ui/bind-by-move/bind-by-move-neither-can-live-while-the-other-survives-4.rs
new file mode 100644
index 0000000..41dafd2
--- /dev/null
+++ b/src/test/ui/bind-by-move/bind-by-move-neither-can-live-while-the-other-survives-4.rs
@@ -0,0 +1,15 @@
+struct X { x: (), }
+
+impl Drop for X {
+    fn drop(&mut self) {
+        println!("destructor runs");
+    }
+}
+
+fn main() {
+    let x = Some((X { x: () }, X { x: () }));
+    match x {
+        Some((_y, ref _z)) => { }, //~ ERROR cannot bind by-move and by-ref in the same pattern
+        None => panic!()
+    }
+}
diff --git a/src/test/ui/bind-by-move/bind-by-move-neither-can-live-while-the-other-survives-4.stderr b/src/test/ui/bind-by-move/bind-by-move-neither-can-live-while-the-other-survives-4.stderr
new file mode 100644
index 0000000..267a9df
--- /dev/null
+++ b/src/test/ui/bind-by-move/bind-by-move-neither-can-live-while-the-other-survives-4.stderr
@@ -0,0 +1,11 @@
+error[E0009]: cannot bind by-move and by-ref in the same pattern
+  --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-4.rs:12:15
+   |
+LL |         Some((_y, ref _z)) => { },
+   |               ^^  ------ both by-ref and by-move used
+   |               |
+   |               by-move pattern here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0009`.
diff --git a/src/test/ui/bind-by-move/bind-by-move-no-guards.nll.stderr b/src/test/ui/bind-by-move/bind-by-move-no-guards.nll.stderr
new file mode 100644
index 0000000..5f8b700
--- /dev/null
+++ b/src/test/ui/bind-by-move/bind-by-move-no-guards.nll.stderr
@@ -0,0 +1,11 @@
+error[E0008]: cannot bind by-move into a pattern guard
+  --> $DIR/bind-by-move-no-guards.rs:8:14
+   |
+LL |         Some(z) if z.recv().unwrap() => { panic!() },
+   |              ^ moves value into pattern guard
+   |
+   = help: add #![feature(bind_by_move_pattern_guards)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0008`.
diff --git a/src/test/ui/bind-by-move/bind-by-move-no-guards.rs b/src/test/ui/bind-by-move/bind-by-move-no-guards.rs
new file mode 100644
index 0000000..bc9b3a8
--- /dev/null
+++ b/src/test/ui/bind-by-move/bind-by-move-no-guards.rs
@@ -0,0 +1,13 @@
+use std::sync::mpsc::channel;
+
+fn main() {
+    let (tx, rx) = channel();
+    let x = Some(rx);
+    tx.send(false);
+    match x {
+        Some(z) if z.recv().unwrap() => { panic!() },
+            //~^ ERROR cannot bind by-move into a pattern guard
+        Some(z) => { assert!(!z.recv().unwrap()); },
+        None => panic!()
+    }
+}
diff --git a/src/test/ui/bind-by-move/bind-by-move-no-guards.stderr b/src/test/ui/bind-by-move/bind-by-move-no-guards.stderr
new file mode 100644
index 0000000..2af2b0d
--- /dev/null
+++ b/src/test/ui/bind-by-move/bind-by-move-no-guards.stderr
@@ -0,0 +1,9 @@
+error[E0008]: cannot bind by-move into a pattern guard
+  --> $DIR/bind-by-move-no-guards.rs:8:14
+   |
+LL |         Some(z) if z.recv().unwrap() => { panic!() },
+   |              ^ moves value into pattern guard
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0008`.
diff --git a/src/test/ui/binop/binop-bitxor-str.rs b/src/test/ui/binop/binop-bitxor-str.rs
new file mode 100644
index 0000000..6021c34
--- /dev/null
+++ b/src/test/ui/binop/binop-bitxor-str.rs
@@ -0,0 +1,3 @@
+// error-pattern:`^` cannot be applied to type `std::string::String`
+
+fn main() { let x = "a".to_string() ^ "b".to_string(); }
diff --git a/src/test/ui/binop/binop-bitxor-str.stderr b/src/test/ui/binop/binop-bitxor-str.stderr
new file mode 100644
index 0000000..9e89922
--- /dev/null
+++ b/src/test/ui/binop/binop-bitxor-str.stderr
@@ -0,0 +1,13 @@
+error[E0369]: binary operation `^` cannot be applied to type `std::string::String`
+  --> $DIR/binop-bitxor-str.rs:3:37
+   |
+LL | fn main() { let x = "a".to_string() ^ "b".to_string(); }
+   |                     --------------- ^ --------------- std::string::String
+   |                     |
+   |                     std::string::String
+   |
+   = note: an implementation of `std::ops::BitXor` might be missing for `std::string::String`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0369`.
diff --git a/src/test/ui/binop/binop-consume-args.nll.stderr b/src/test/ui/binop/binop-consume-args.nll.stderr
new file mode 100644
index 0000000..5751af2
--- /dev/null
+++ b/src/test/ui/binop/binop-consume-args.nll.stderr
@@ -0,0 +1,253 @@
+error[E0382]: use of moved value: `lhs`
+  --> $DIR/binop-consume-args.rs:7:10
+   |
+LL | fn add<A: Add<B, Output=()>, B>(lhs: A, rhs: B) {
+   |        -                        --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
+   |        |
+   |        consider adding a `Copy` constraint to this type argument
+LL |     lhs + rhs;
+   |     --- value moved here
+LL |     drop(lhs);
+   |          ^^^ value used here after move
+
+error[E0382]: use of moved value: `rhs`
+  --> $DIR/binop-consume-args.rs:8:10
+   |
+LL | fn add<A: Add<B, Output=()>, B>(lhs: A, rhs: B) {
+   |                              -          --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait
+   |                              |
+   |                              consider adding a `Copy` constraint to this type argument
+LL |     lhs + rhs;
+   |           --- value moved here
+LL |     drop(lhs);
+LL |     drop(rhs);
+   |          ^^^ value used here after move
+
+error[E0382]: use of moved value: `lhs`
+  --> $DIR/binop-consume-args.rs:13:10
+   |
+LL | fn sub<A: Sub<B, Output=()>, B>(lhs: A, rhs: B) {
+   |        -                        --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
+   |        |
+   |        consider adding a `Copy` constraint to this type argument
+LL |     lhs - rhs;
+   |     --- value moved here
+LL |     drop(lhs);
+   |          ^^^ value used here after move
+
+error[E0382]: use of moved value: `rhs`
+  --> $DIR/binop-consume-args.rs:14:10
+   |
+LL | fn sub<A: Sub<B, Output=()>, B>(lhs: A, rhs: B) {
+   |                              -          --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait
+   |                              |
+   |                              consider adding a `Copy` constraint to this type argument
+LL |     lhs - rhs;
+   |           --- value moved here
+LL |     drop(lhs);
+LL |     drop(rhs);
+   |          ^^^ value used here after move
+
+error[E0382]: use of moved value: `lhs`
+  --> $DIR/binop-consume-args.rs:19:10
+   |
+LL | fn mul<A: Mul<B, Output=()>, B>(lhs: A, rhs: B) {
+   |        -                        --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
+   |        |
+   |        consider adding a `Copy` constraint to this type argument
+LL |     lhs * rhs;
+   |     --- value moved here
+LL |     drop(lhs);
+   |          ^^^ value used here after move
+
+error[E0382]: use of moved value: `rhs`
+  --> $DIR/binop-consume-args.rs:20:10
+   |
+LL | fn mul<A: Mul<B, Output=()>, B>(lhs: A, rhs: B) {
+   |                              -          --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait
+   |                              |
+   |                              consider adding a `Copy` constraint to this type argument
+LL |     lhs * rhs;
+   |           --- value moved here
+LL |     drop(lhs);
+LL |     drop(rhs);
+   |          ^^^ value used here after move
+
+error[E0382]: use of moved value: `lhs`
+  --> $DIR/binop-consume-args.rs:25:10
+   |
+LL | fn div<A: Div<B, Output=()>, B>(lhs: A, rhs: B) {
+   |        -                        --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
+   |        |
+   |        consider adding a `Copy` constraint to this type argument
+LL |     lhs / rhs;
+   |     --- value moved here
+LL |     drop(lhs);
+   |          ^^^ value used here after move
+
+error[E0382]: use of moved value: `rhs`
+  --> $DIR/binop-consume-args.rs:26:10
+   |
+LL | fn div<A: Div<B, Output=()>, B>(lhs: A, rhs: B) {
+   |                              -          --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait
+   |                              |
+   |                              consider adding a `Copy` constraint to this type argument
+LL |     lhs / rhs;
+   |           --- value moved here
+LL |     drop(lhs);
+LL |     drop(rhs);
+   |          ^^^ value used here after move
+
+error[E0382]: use of moved value: `lhs`
+  --> $DIR/binop-consume-args.rs:31:10
+   |
+LL | fn rem<A: Rem<B, Output=()>, B>(lhs: A, rhs: B) {
+   |        -                        --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
+   |        |
+   |        consider adding a `Copy` constraint to this type argument
+LL |     lhs % rhs;
+   |     --- value moved here
+LL |     drop(lhs);
+   |          ^^^ value used here after move
+
+error[E0382]: use of moved value: `rhs`
+  --> $DIR/binop-consume-args.rs:32:10
+   |
+LL | fn rem<A: Rem<B, Output=()>, B>(lhs: A, rhs: B) {
+   |                              -          --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait
+   |                              |
+   |                              consider adding a `Copy` constraint to this type argument
+LL |     lhs % rhs;
+   |           --- value moved here
+LL |     drop(lhs);
+LL |     drop(rhs);
+   |          ^^^ value used here after move
+
+error[E0382]: use of moved value: `lhs`
+  --> $DIR/binop-consume-args.rs:37:10
+   |
+LL | fn bitand<A: BitAnd<B, Output=()>, B>(lhs: A, rhs: B) {
+   |           -                           --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
+   |           |
+   |           consider adding a `Copy` constraint to this type argument
+LL |     lhs & rhs;
+   |     --- value moved here
+LL |     drop(lhs);
+   |          ^^^ value used here after move
+
+error[E0382]: use of moved value: `rhs`
+  --> $DIR/binop-consume-args.rs:38:10
+   |
+LL | fn bitand<A: BitAnd<B, Output=()>, B>(lhs: A, rhs: B) {
+   |                                    -          --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait
+   |                                    |
+   |                                    consider adding a `Copy` constraint to this type argument
+LL |     lhs & rhs;
+   |           --- value moved here
+LL |     drop(lhs);
+LL |     drop(rhs);
+   |          ^^^ value used here after move
+
+error[E0382]: use of moved value: `lhs`
+  --> $DIR/binop-consume-args.rs:43:10
+   |
+LL | fn bitor<A: BitOr<B, Output=()>, B>(lhs: A, rhs: B) {
+   |          -                          --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
+   |          |
+   |          consider adding a `Copy` constraint to this type argument
+LL |     lhs | rhs;
+   |     --- value moved here
+LL |     drop(lhs);
+   |          ^^^ value used here after move
+
+error[E0382]: use of moved value: `rhs`
+  --> $DIR/binop-consume-args.rs:44:10
+   |
+LL | fn bitor<A: BitOr<B, Output=()>, B>(lhs: A, rhs: B) {
+   |                                  -          --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait
+   |                                  |
+   |                                  consider adding a `Copy` constraint to this type argument
+LL |     lhs | rhs;
+   |           --- value moved here
+LL |     drop(lhs);
+LL |     drop(rhs);
+   |          ^^^ value used here after move
+
+error[E0382]: use of moved value: `lhs`
+  --> $DIR/binop-consume-args.rs:49:10
+   |
+LL | fn bitxor<A: BitXor<B, Output=()>, B>(lhs: A, rhs: B) {
+   |           -                           --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
+   |           |
+   |           consider adding a `Copy` constraint to this type argument
+LL |     lhs ^ rhs;
+   |     --- value moved here
+LL |     drop(lhs);
+   |          ^^^ value used here after move
+
+error[E0382]: use of moved value: `rhs`
+  --> $DIR/binop-consume-args.rs:50:10
+   |
+LL | fn bitxor<A: BitXor<B, Output=()>, B>(lhs: A, rhs: B) {
+   |                                    -          --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait
+   |                                    |
+   |                                    consider adding a `Copy` constraint to this type argument
+LL |     lhs ^ rhs;
+   |           --- value moved here
+LL |     drop(lhs);
+LL |     drop(rhs);
+   |          ^^^ value used here after move
+
+error[E0382]: use of moved value: `lhs`
+  --> $DIR/binop-consume-args.rs:55:10
+   |
+LL | fn shl<A: Shl<B, Output=()>, B>(lhs: A, rhs: B) {
+   |        -                        --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
+   |        |
+   |        consider adding a `Copy` constraint to this type argument
+LL |     lhs << rhs;
+   |     --- value moved here
+LL |     drop(lhs);
+   |          ^^^ value used here after move
+
+error[E0382]: use of moved value: `rhs`
+  --> $DIR/binop-consume-args.rs:56:10
+   |
+LL | fn shl<A: Shl<B, Output=()>, B>(lhs: A, rhs: B) {
+   |                              -          --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait
+   |                              |
+   |                              consider adding a `Copy` constraint to this type argument
+LL |     lhs << rhs;
+   |            --- value moved here
+LL |     drop(lhs);
+LL |     drop(rhs);
+   |          ^^^ value used here after move
+
+error[E0382]: use of moved value: `lhs`
+  --> $DIR/binop-consume-args.rs:61:10
+   |
+LL | fn shr<A: Shr<B, Output=()>, B>(lhs: A, rhs: B) {
+   |        -                        --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
+   |        |
+   |        consider adding a `Copy` constraint to this type argument
+LL |     lhs >> rhs;
+   |     --- value moved here
+LL |     drop(lhs);
+   |          ^^^ value used here after move
+
+error[E0382]: use of moved value: `rhs`
+  --> $DIR/binop-consume-args.rs:62:10
+   |
+LL | fn shr<A: Shr<B, Output=()>, B>(lhs: A, rhs: B) {
+   |                              -          --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait
+   |                              |
+   |                              consider adding a `Copy` constraint to this type argument
+LL |     lhs >> rhs;
+   |            --- value moved here
+LL |     drop(lhs);
+LL |     drop(rhs);
+   |          ^^^ value used here after move
+
+error: aborting due to 20 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/binop/binop-consume-args.rs b/src/test/ui/binop/binop-consume-args.rs
new file mode 100644
index 0000000..8d6c725
--- /dev/null
+++ b/src/test/ui/binop/binop-consume-args.rs
@@ -0,0 +1,65 @@
+// Test that binary operators consume their arguments
+
+use std::ops::{Add, Sub, Mul, Div, Rem, BitAnd, BitXor, BitOr, Shl, Shr};
+
+fn add<A: Add<B, Output=()>, B>(lhs: A, rhs: B) {
+    lhs + rhs;
+    drop(lhs);  //~ ERROR use of moved value: `lhs`
+    drop(rhs);  //~ ERROR use of moved value: `rhs`
+}
+
+fn sub<A: Sub<B, Output=()>, B>(lhs: A, rhs: B) {
+    lhs - rhs;
+    drop(lhs);  //~ ERROR use of moved value: `lhs`
+    drop(rhs);  //~ ERROR use of moved value: `rhs`
+}
+
+fn mul<A: Mul<B, Output=()>, B>(lhs: A, rhs: B) {
+    lhs * rhs;
+    drop(lhs);  //~ ERROR use of moved value: `lhs`
+    drop(rhs);  //~ ERROR use of moved value: `rhs`
+}
+
+fn div<A: Div<B, Output=()>, B>(lhs: A, rhs: B) {
+    lhs / rhs;
+    drop(lhs);  //~ ERROR use of moved value: `lhs`
+    drop(rhs);  //~ ERROR use of moved value: `rhs`
+}
+
+fn rem<A: Rem<B, Output=()>, B>(lhs: A, rhs: B) {
+    lhs % rhs;
+    drop(lhs);  //~ ERROR use of moved value: `lhs`
+    drop(rhs);  //~ ERROR use of moved value: `rhs`
+}
+
+fn bitand<A: BitAnd<B, Output=()>, B>(lhs: A, rhs: B) {
+    lhs & rhs;
+    drop(lhs);  //~ ERROR use of moved value: `lhs`
+    drop(rhs);  //~ ERROR use of moved value: `rhs`
+}
+
+fn bitor<A: BitOr<B, Output=()>, B>(lhs: A, rhs: B) {
+    lhs | rhs;
+    drop(lhs);  //~ ERROR use of moved value: `lhs`
+    drop(rhs);  //~ ERROR use of moved value: `rhs`
+}
+
+fn bitxor<A: BitXor<B, Output=()>, B>(lhs: A, rhs: B) {
+    lhs ^ rhs;
+    drop(lhs);  //~ ERROR use of moved value: `lhs`
+    drop(rhs);  //~ ERROR use of moved value: `rhs`
+}
+
+fn shl<A: Shl<B, Output=()>, B>(lhs: A, rhs: B) {
+    lhs << rhs;
+    drop(lhs);  //~ ERROR use of moved value: `lhs`
+    drop(rhs);  //~ ERROR use of moved value: `rhs`
+}
+
+fn shr<A: Shr<B, Output=()>, B>(lhs: A, rhs: B) {
+    lhs >> rhs;
+    drop(lhs);  //~ ERROR use of moved value: `lhs`
+    drop(rhs);  //~ ERROR use of moved value: `rhs`
+}
+
+fn main() {}
diff --git a/src/test/ui/binop/binop-consume-args.stderr b/src/test/ui/binop/binop-consume-args.stderr
new file mode 100644
index 0000000..9246c11
--- /dev/null
+++ b/src/test/ui/binop/binop-consume-args.stderr
@@ -0,0 +1,213 @@
+error[E0382]: use of moved value: `lhs`
+  --> $DIR/binop-consume-args.rs:7:10
+   |
+LL |     lhs + rhs;
+   |     --- value moved here
+LL |     drop(lhs);
+   |          ^^^ value used here after move
+   |
+   = note: move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `rhs`
+  --> $DIR/binop-consume-args.rs:8:10
+   |
+LL |     lhs + rhs;
+   |           --- value moved here
+LL |     drop(lhs);
+LL |     drop(rhs);
+   |          ^^^ value used here after move
+   |
+   = note: move occurs because `rhs` has type `B`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `lhs`
+  --> $DIR/binop-consume-args.rs:13:10
+   |
+LL |     lhs - rhs;
+   |     --- value moved here
+LL |     drop(lhs);
+   |          ^^^ value used here after move
+   |
+   = note: move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `rhs`
+  --> $DIR/binop-consume-args.rs:14:10
+   |
+LL |     lhs - rhs;
+   |           --- value moved here
+LL |     drop(lhs);
+LL |     drop(rhs);
+   |          ^^^ value used here after move
+   |
+   = note: move occurs because `rhs` has type `B`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `lhs`
+  --> $DIR/binop-consume-args.rs:19:10
+   |
+LL |     lhs * rhs;
+   |     --- value moved here
+LL |     drop(lhs);
+   |          ^^^ value used here after move
+   |
+   = note: move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `rhs`
+  --> $DIR/binop-consume-args.rs:20:10
+   |
+LL |     lhs * rhs;
+   |           --- value moved here
+LL |     drop(lhs);
+LL |     drop(rhs);
+   |          ^^^ value used here after move
+   |
+   = note: move occurs because `rhs` has type `B`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `lhs`
+  --> $DIR/binop-consume-args.rs:25:10
+   |
+LL |     lhs / rhs;
+   |     --- value moved here
+LL |     drop(lhs);
+   |          ^^^ value used here after move
+   |
+   = note: move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `rhs`
+  --> $DIR/binop-consume-args.rs:26:10
+   |
+LL |     lhs / rhs;
+   |           --- value moved here
+LL |     drop(lhs);
+LL |     drop(rhs);
+   |          ^^^ value used here after move
+   |
+   = note: move occurs because `rhs` has type `B`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `lhs`
+  --> $DIR/binop-consume-args.rs:31:10
+   |
+LL |     lhs % rhs;
+   |     --- value moved here
+LL |     drop(lhs);
+   |          ^^^ value used here after move
+   |
+   = note: move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `rhs`
+  --> $DIR/binop-consume-args.rs:32:10
+   |
+LL |     lhs % rhs;
+   |           --- value moved here
+LL |     drop(lhs);
+LL |     drop(rhs);
+   |          ^^^ value used here after move
+   |
+   = note: move occurs because `rhs` has type `B`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `lhs`
+  --> $DIR/binop-consume-args.rs:37:10
+   |
+LL |     lhs & rhs;
+   |     --- value moved here
+LL |     drop(lhs);
+   |          ^^^ value used here after move
+   |
+   = note: move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `rhs`
+  --> $DIR/binop-consume-args.rs:38:10
+   |
+LL |     lhs & rhs;
+   |           --- value moved here
+LL |     drop(lhs);
+LL |     drop(rhs);
+   |          ^^^ value used here after move
+   |
+   = note: move occurs because `rhs` has type `B`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `lhs`
+  --> $DIR/binop-consume-args.rs:43:10
+   |
+LL |     lhs | rhs;
+   |     --- value moved here
+LL |     drop(lhs);
+   |          ^^^ value used here after move
+   |
+   = note: move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `rhs`
+  --> $DIR/binop-consume-args.rs:44:10
+   |
+LL |     lhs | rhs;
+   |           --- value moved here
+LL |     drop(lhs);
+LL |     drop(rhs);
+   |          ^^^ value used here after move
+   |
+   = note: move occurs because `rhs` has type `B`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `lhs`
+  --> $DIR/binop-consume-args.rs:49:10
+   |
+LL |     lhs ^ rhs;
+   |     --- value moved here
+LL |     drop(lhs);
+   |          ^^^ value used here after move
+   |
+   = note: move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `rhs`
+  --> $DIR/binop-consume-args.rs:50:10
+   |
+LL |     lhs ^ rhs;
+   |           --- value moved here
+LL |     drop(lhs);
+LL |     drop(rhs);
+   |          ^^^ value used here after move
+   |
+   = note: move occurs because `rhs` has type `B`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `lhs`
+  --> $DIR/binop-consume-args.rs:55:10
+   |
+LL |     lhs << rhs;
+   |     --- value moved here
+LL |     drop(lhs);
+   |          ^^^ value used here after move
+   |
+   = note: move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `rhs`
+  --> $DIR/binop-consume-args.rs:56:10
+   |
+LL |     lhs << rhs;
+   |            --- value moved here
+LL |     drop(lhs);
+LL |     drop(rhs);
+   |          ^^^ value used here after move
+   |
+   = note: move occurs because `rhs` has type `B`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `lhs`
+  --> $DIR/binop-consume-args.rs:61:10
+   |
+LL |     lhs >> rhs;
+   |     --- value moved here
+LL |     drop(lhs);
+   |          ^^^ value used here after move
+   |
+   = note: move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `rhs`
+  --> $DIR/binop-consume-args.rs:62:10
+   |
+LL |     lhs >> rhs;
+   |            --- value moved here
+LL |     drop(lhs);
+LL |     drop(rhs);
+   |          ^^^ value used here after move
+   |
+   = note: move occurs because `rhs` has type `B`, which does not implement the `Copy` trait
+
+error: aborting due to 20 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/binop/binop-logic-float.rs b/src/test/ui/binop/binop-logic-float.rs
new file mode 100644
index 0000000..c95c1d3
--- /dev/null
+++ b/src/test/ui/binop/binop-logic-float.rs
@@ -0,0 +1,4 @@
+fn main() { let x = 1.0_f32 || 2.0_f32; }
+//~^ ERROR mismatched types
+//~| ERROR mismatched types
+
diff --git a/src/test/ui/binop/binop-logic-float.stderr b/src/test/ui/binop/binop-logic-float.stderr
new file mode 100644
index 0000000..5a94307
--- /dev/null
+++ b/src/test/ui/binop/binop-logic-float.stderr
@@ -0,0 +1,15 @@
+error[E0308]: mismatched types
+  --> $DIR/binop-logic-float.rs:1:21
+   |
+LL | fn main() { let x = 1.0_f32 || 2.0_f32; }
+   |                     ^^^^^^^ expected bool, found f32
+
+error[E0308]: mismatched types
+  --> $DIR/binop-logic-float.rs:1:32
+   |
+LL | fn main() { let x = 1.0_f32 || 2.0_f32; }
+   |                                ^^^^^^^ expected bool, found f32
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/binop/binop-logic-int.rs b/src/test/ui/binop/binop-logic-int.rs
new file mode 100644
index 0000000..e71daa2
--- /dev/null
+++ b/src/test/ui/binop/binop-logic-int.rs
@@ -0,0 +1,3 @@
+fn main() { let x = 1 && 2; }
+//~^ ERROR mismatched types
+//~| ERROR mismatched types
diff --git a/src/test/ui/binop/binop-logic-int.stderr b/src/test/ui/binop/binop-logic-int.stderr
new file mode 100644
index 0000000..b699b39
--- /dev/null
+++ b/src/test/ui/binop/binop-logic-int.stderr
@@ -0,0 +1,21 @@
+error[E0308]: mismatched types
+  --> $DIR/binop-logic-int.rs:1:21
+   |
+LL | fn main() { let x = 1 && 2; }
+   |                     ^ expected bool, found integer
+   |
+   = note: expected type `bool`
+              found type `{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/binop-logic-int.rs:1:26
+   |
+LL | fn main() { let x = 1 && 2; }
+   |                          ^ expected bool, found integer
+   |
+   = note: expected type `bool`
+              found type `{integer}`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/binop/binop-move-semantics.nll.stderr b/src/test/ui/binop/binop-move-semantics.nll.stderr
new file mode 100644
index 0000000..7d54de6
--- /dev/null
+++ b/src/test/ui/binop/binop-move-semantics.nll.stderr
@@ -0,0 +1,95 @@
+error[E0382]: use of moved value: `x`
+  --> $DIR/binop-move-semantics.rs:8:5
+   |
+LL | fn double_move<T: Add<Output=()>>(x: T) {
+   |                -                  - move occurs because `x` has type `T`, which does not implement the `Copy` trait
+   |                |
+   |                consider adding a `Copy` constraint to this type argument
+LL |     x
+   |     - value moved here
+LL |     +
+LL |     x;
+   |     ^ value used here after move
+
+error[E0382]: borrow of moved value: `x`
+  --> $DIR/binop-move-semantics.rs:14:5
+   |
+LL | fn move_then_borrow<T: Add<Output=()> + Clone>(x: T) {
+   |                     -                          - move occurs because `x` has type `T`, which does not implement the `Copy` trait
+   |                     |
+   |                     consider adding a `Copy` constraint to this type argument
+LL |     x
+   |     - value moved here
+LL |     +
+LL |     x.clone();
+   |     ^ value borrowed here after move
+
+error[E0505]: cannot move out of `x` because it is borrowed
+  --> $DIR/binop-move-semantics.rs:21:5
+   |
+LL |     let m = &x;
+   |             -- borrow of `x` occurs here
+...
+LL |     x
+   |     ^ move out of `x` occurs here
+...
+LL |     use_mut(n); use_imm(m);
+   |                         - borrow later used here
+
+error[E0505]: cannot move out of `y` because it is borrowed
+  --> $DIR/binop-move-semantics.rs:23:5
+   |
+LL |     let n = &mut y;
+   |             ------ borrow of `y` occurs here
+...
+LL |     y;
+   |     ^ move out of `y` occurs here
+LL |     use_mut(n); use_imm(m);
+   |             - borrow later used here
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/binop-move-semantics.rs:30:5
+   |
+LL |     *m
+   |     ^^ cannot move out of borrowed content
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/binop-move-semantics.rs:32:5
+   |
+LL |     *n;
+   |     ^^ cannot move out of borrowed content
+
+error[E0502]: cannot borrow `f` as immutable because it is also borrowed as mutable
+  --> $DIR/binop-move-semantics.rs:54:5
+   |
+LL |       &mut f
+   |       ------
+   |       |
+   |  _____mutable borrow occurs here
+   | |
+LL | |     +
+LL | |     &f;
+   | |     ^-
+   | |_____||
+   |       |mutable borrow later used here
+   |       immutable borrow occurs here
+
+error[E0502]: cannot borrow `f` as mutable because it is also borrowed as immutable
+  --> $DIR/binop-move-semantics.rs:62:5
+   |
+LL |       &f
+   |       --
+   |       |
+   |  _____immutable borrow occurs here
+   | |
+LL | |     +
+LL | |     &mut f;
+   | |     ^^^^^-
+   | |_____|____|
+   |       |    immutable borrow later used here
+   |       mutable borrow occurs here
+
+error: aborting due to 8 previous errors
+
+Some errors occurred: E0382, E0502, E0505, E0507.
+For more information about an error, try `rustc --explain E0382`.
diff --git a/src/test/ui/binop/binop-move-semantics.rs b/src/test/ui/binop/binop-move-semantics.rs
new file mode 100644
index 0000000..2bcf16f
--- /dev/null
+++ b/src/test/ui/binop/binop-move-semantics.rs
@@ -0,0 +1,68 @@
+// Test that move restrictions are enforced on overloaded binary operations
+
+use std::ops::Add;
+
+fn double_move<T: Add<Output=()>>(x: T) {
+    x
+    +
+    x;  //~ ERROR: use of moved value
+}
+
+fn move_then_borrow<T: Add<Output=()> + Clone>(x: T) {
+    x
+    +
+    x.clone();  //~ ERROR: use of moved value
+}
+
+fn move_borrowed<T: Add<Output=()>>(x: T, mut y: T) {
+    let m = &x;
+    let n = &mut y;
+
+    x  //~ ERROR: cannot move out of `x` because it is borrowed
+    +
+    y;  //~ ERROR: cannot move out of `y` because it is borrowed
+    use_mut(n); use_imm(m);
+}
+fn illegal_dereference<T: Add<Output=()>>(mut x: T, y: T) {
+    let m = &mut x;
+    let n = &y;
+
+    *m  //~ ERROR: cannot move out of borrowed content
+    +
+    *n;  //~ ERROR: cannot move out of borrowed content
+    use_imm(n); use_mut(m);
+}
+struct Foo;
+
+impl<'a, 'b> Add<&'b Foo> for &'a mut Foo {
+    type Output = ();
+
+    fn add(self, _: &Foo) {}
+}
+
+impl<'a, 'b> Add<&'b mut Foo> for &'a Foo {
+    type Output = ();
+
+    fn add(self, _: &mut Foo) {}
+}
+
+fn mut_plus_immut() {
+    let mut f = Foo;
+
+    &mut f
+    +
+    &f;  //~ ERROR: cannot borrow `f` as immutable because it is also borrowed as mutable
+}
+
+fn immut_plus_mut() {
+    let mut f = Foo;
+
+    &f
+    +
+    &mut f;  //~ ERROR: cannot borrow `f` as mutable because it is also borrowed as immutable
+}
+
+fn main() {}
+
+fn use_mut<T>(_: &mut T) { }
+fn use_imm<T>(_: &T) { }
diff --git a/src/test/ui/binop/binop-move-semantics.stderr b/src/test/ui/binop/binop-move-semantics.stderr
new file mode 100644
index 0000000..acc2620
--- /dev/null
+++ b/src/test/ui/binop/binop-move-semantics.stderr
@@ -0,0 +1,80 @@
+error[E0382]: use of moved value: `x`
+  --> $DIR/binop-move-semantics.rs:8:5
+   |
+LL |     x
+   |     - value moved here
+LL |     +
+LL |     x;
+   |     ^ value used here after move
+   |
+   = note: move occurs because `x` has type `T`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `x`
+  --> $DIR/binop-move-semantics.rs:14:5
+   |
+LL |     x
+   |     - value moved here
+LL |     +
+LL |     x.clone();
+   |     ^ value used here after move
+   |
+   = note: move occurs because `x` has type `T`, which does not implement the `Copy` trait
+
+error[E0505]: cannot move out of `x` because it is borrowed
+  --> $DIR/binop-move-semantics.rs:21:5
+   |
+LL |     let m = &x;
+   |              - borrow of `x` occurs here
+...
+LL |     x
+   |     ^ move out of `x` occurs here
+
+error[E0505]: cannot move out of `y` because it is borrowed
+  --> $DIR/binop-move-semantics.rs:23:5
+   |
+LL |     let n = &mut y;
+   |                  - borrow of `y` occurs here
+...
+LL |     y;
+   |     ^ move out of `y` occurs here
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/binop-move-semantics.rs:30:5
+   |
+LL |     *m
+   |     ^^ cannot move out of borrowed content
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/binop-move-semantics.rs:32:5
+   |
+LL |     *n;
+   |     ^^ cannot move out of borrowed content
+
+error[E0502]: cannot borrow `f` as immutable because it is also borrowed as mutable
+  --> $DIR/binop-move-semantics.rs:54:6
+   |
+LL |     &mut f
+   |          - mutable borrow occurs here
+LL |     +
+LL |     &f;
+   |      ^
+   |      |
+   |      immutable borrow occurs here
+   |      mutable borrow ends here
+
+error[E0502]: cannot borrow `f` as mutable because it is also borrowed as immutable
+  --> $DIR/binop-move-semantics.rs:62:10
+   |
+LL |     &f
+   |      - immutable borrow occurs here
+LL |     +
+LL |     &mut f;
+   |          ^
+   |          |
+   |          mutable borrow occurs here
+   |          immutable borrow ends here
+
+error: aborting due to 8 previous errors
+
+Some errors occurred: E0382, E0502, E0505, E0507.
+For more information about an error, try `rustc --explain E0382`.
diff --git a/src/test/ui/binop/binop-mul-bool.rs b/src/test/ui/binop/binop-mul-bool.rs
new file mode 100644
index 0000000..3d5349b
--- /dev/null
+++ b/src/test/ui/binop/binop-mul-bool.rs
@@ -0,0 +1,3 @@
+// error-pattern:`*` cannot be applied to type `bool`
+
+fn main() { let x = true * false; }
diff --git a/src/test/ui/binop/binop-mul-bool.stderr b/src/test/ui/binop/binop-mul-bool.stderr
new file mode 100644
index 0000000..92e14bc
--- /dev/null
+++ b/src/test/ui/binop/binop-mul-bool.stderr
@@ -0,0 +1,13 @@
+error[E0369]: binary operation `*` cannot be applied to type `bool`
+  --> $DIR/binop-mul-bool.rs:3:26
+   |
+LL | fn main() { let x = true * false; }
+   |                     ---- ^ ----- bool
+   |                     |
+   |                     bool
+   |
+   = note: an implementation of `std::ops::Mul` might be missing for `bool`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0369`.
diff --git a/src/test/ui/binop/binop-typeck.rs b/src/test/ui/binop/binop-typeck.rs
new file mode 100644
index 0000000..e1185cf
--- /dev/null
+++ b/src/test/ui/binop/binop-typeck.rs
@@ -0,0 +1,8 @@
+// issue #500
+
+fn main() {
+    let x = true;
+    let y = 1;
+    let z = x + y;
+    //~^ ERROR binary operation `+` cannot be applied to type `bool`
+}
diff --git a/src/test/ui/binop/binop-typeck.stderr b/src/test/ui/binop/binop-typeck.stderr
new file mode 100644
index 0000000..d33cff3
--- /dev/null
+++ b/src/test/ui/binop/binop-typeck.stderr
@@ -0,0 +1,13 @@
+error[E0369]: binary operation `+` cannot be applied to type `bool`
+  --> $DIR/binop-typeck.rs:6:15
+   |
+LL |     let z = x + y;
+   |             - ^ - {integer}
+   |             |
+   |             bool
+   |
+   = note: an implementation of `std::ops::Add` might be missing for `bool`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0369`.
diff --git a/src/test/ui/blind/blind-item-block-item-shadow.rs b/src/test/ui/blind/blind-item-block-item-shadow.rs
new file mode 100644
index 0000000..d90ef77
--- /dev/null
+++ b/src/test/ui/blind/blind-item-block-item-shadow.rs
@@ -0,0 +1,9 @@
+mod foo { pub struct Bar; }
+
+fn main() {
+    {
+        struct Bar;
+        use foo::Bar;
+        //~^ ERROR the name `Bar` is defined multiple times
+    }
+}
diff --git a/src/test/ui/blind/blind-item-block-item-shadow.stderr b/src/test/ui/blind/blind-item-block-item-shadow.stderr
new file mode 100644
index 0000000..d897bf5
--- /dev/null
+++ b/src/test/ui/blind/blind-item-block-item-shadow.stderr
@@ -0,0 +1,17 @@
+error[E0255]: the name `Bar` is defined multiple times
+  --> $DIR/blind-item-block-item-shadow.rs:6:13
+   |
+LL |         struct Bar;
+   |         ----------- previous definition of the type `Bar` here
+LL |         use foo::Bar;
+   |             ^^^^^^^^ `Bar` reimported here
+   |
+   = note: `Bar` must be defined only once in the type namespace of this block
+help: you can use `as` to change the binding name of the import
+   |
+LL |         use foo::Bar as OtherBar;
+   |             ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0255`.
diff --git a/src/test/ui/blind/blind-item-block-middle.rs b/src/test/ui/blind/blind-item-block-middle.rs
new file mode 100644
index 0000000..6cd3f3b
--- /dev/null
+++ b/src/test/ui/blind/blind-item-block-middle.rs
@@ -0,0 +1,9 @@
+#![allow(non_camel_case_types)]
+
+mod foo { pub struct bar; }
+
+fn main() {
+    let bar = 5;
+    //~^ ERROR mismatched types
+    use foo::bar;
+}
diff --git a/src/test/ui/blind/blind-item-block-middle.stderr b/src/test/ui/blind/blind-item-block-middle.stderr
new file mode 100644
index 0000000..389b63c
--- /dev/null
+++ b/src/test/ui/blind/blind-item-block-middle.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/blind-item-block-middle.rs:6:9
+   |
+LL |     let bar = 5;
+   |         ^^^ expected integer, found struct `foo::bar`
+   |
+   = note: expected type `{integer}`
+              found type `foo::bar`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/blind/blind-item-item-shadow.rs b/src/test/ui/blind/blind-item-item-shadow.rs
new file mode 100644
index 0000000..82d07ea
--- /dev/null
+++ b/src/test/ui/blind/blind-item-item-shadow.rs
@@ -0,0 +1,7 @@
+mod foo { pub mod foo {  } }
+
+use foo::foo;
+//~^ ERROR the name `foo` is defined multiple times
+//~| `foo` reimported here
+
+fn main() {}
diff --git a/src/test/ui/blind/blind-item-item-shadow.stderr b/src/test/ui/blind/blind-item-item-shadow.stderr
new file mode 100644
index 0000000..f17d784
--- /dev/null
+++ b/src/test/ui/blind/blind-item-item-shadow.stderr
@@ -0,0 +1,18 @@
+error[E0255]: the name `foo` is defined multiple times
+  --> $DIR/blind-item-item-shadow.rs:3:5
+   |
+LL | mod foo { pub mod foo {  } }
+   | ------- previous definition of the module `foo` here
+LL | 
+LL | use foo::foo;
+   |     ^^^^^^^^ `foo` reimported here
+   |
+   = note: `foo` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | use foo::foo as other_foo;
+   |     ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0255`.
diff --git a/src/test/ui/block-expression-remove-semicolon.rs b/src/test/ui/block-expression-remove-semicolon.rs
new file mode 100644
index 0000000..afa10b3
--- /dev/null
+++ b/src/test/ui/block-expression-remove-semicolon.rs
@@ -0,0 +1,10 @@
+fn foo() -> i32 {
+   0
+}
+
+fn main() {
+    let x: i32 = {
+        //~^ ERROR mismatched types
+        foo(); //~ HELP consider removing this semicolon
+    };
+}
diff --git a/src/test/ui/block-expression-remove-semicolon.stderr b/src/test/ui/block-expression-remove-semicolon.stderr
new file mode 100644
index 0000000..51942f3
--- /dev/null
+++ b/src/test/ui/block-expression-remove-semicolon.stderr
@@ -0,0 +1,17 @@
+error[E0308]: mismatched types
+  --> $DIR/block-expression-remove-semicolon.rs:6:18
+   |
+LL |       let x: i32 = {
+   |  __________________^
+LL | |
+LL | |         foo();
+   | |              - help: consider removing this semicolon
+LL | |     };
+   | |_____^ expected i32, found ()
+   |
+   = note: expected type `i32`
+              found type `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/block-result/block-must-not-have-result-do.rs b/src/test/ui/block-result/block-must-not-have-result-do.rs
new file mode 100644
index 0000000..4fdb697
--- /dev/null
+++ b/src/test/ui/block-result/block-must-not-have-result-do.rs
@@ -0,0 +1,5 @@
+fn main() {
+    loop {
+        true //~  ERROR mismatched types
+    }
+}
diff --git a/src/test/ui/block-result/block-must-not-have-result-do.stderr b/src/test/ui/block-result/block-must-not-have-result-do.stderr
new file mode 100644
index 0000000..5981b8b
--- /dev/null
+++ b/src/test/ui/block-result/block-must-not-have-result-do.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/block-must-not-have-result-do.rs:3:9
+   |
+LL |         true
+   |         ^^^^ expected (), found bool
+   |
+   = note: expected type `()`
+              found type `bool`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/block-result/block-must-not-have-result-res.rs b/src/test/ui/block-result/block-must-not-have-result-res.rs
new file mode 100644
index 0000000..7e86274
--- /dev/null
+++ b/src/test/ui/block-result/block-must-not-have-result-res.rs
@@ -0,0 +1,10 @@
+struct R;
+
+impl Drop for R {
+    fn drop(&mut self) {
+        true //~  ERROR mismatched types
+    }
+}
+
+fn main() {
+}
diff --git a/src/test/ui/block-result/block-must-not-have-result-res.stderr b/src/test/ui/block-result/block-must-not-have-result-res.stderr
new file mode 100644
index 0000000..8a41f8b
--- /dev/null
+++ b/src/test/ui/block-result/block-must-not-have-result-res.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/block-must-not-have-result-res.rs:5:9
+   |
+LL |     fn drop(&mut self) {
+   |                        - expected `()` because of default return type
+LL |         true
+   |         ^^^^ expected (), found bool
+   |
+   = note: expected type `()`
+              found type `bool`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/block-result/block-must-not-have-result-while.rs b/src/test/ui/block-result/block-must-not-have-result-while.rs
new file mode 100644
index 0000000..9659763
--- /dev/null
+++ b/src/test/ui/block-result/block-must-not-have-result-while.rs
@@ -0,0 +1,8 @@
+fn main() {
+    while true {
+        true //~  ERROR mismatched types
+             //~| expected type `()`
+             //~| found type `bool`
+             //~| expected (), found bool
+    }
+}
diff --git a/src/test/ui/block-result/block-must-not-have-result-while.stderr b/src/test/ui/block-result/block-must-not-have-result-while.stderr
new file mode 100644
index 0000000..302d297
--- /dev/null
+++ b/src/test/ui/block-result/block-must-not-have-result-while.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/block-must-not-have-result-while.rs:3:9
+   |
+LL |         true
+   |         ^^^^ expected (), found bool
+   |
+   = note: expected type `()`
+              found type `bool`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/block-result/consider-removing-last-semi.rs b/src/test/ui/block-result/consider-removing-last-semi.rs
new file mode 100644
index 0000000..f8cdccb
--- /dev/null
+++ b/src/test/ui/block-result/consider-removing-last-semi.rs
@@ -0,0 +1,11 @@
+fn f() -> String {  //~ ERROR mismatched types
+    0u8;
+    "bla".to_string();
+}
+
+fn g() -> String {  //~ ERROR mismatched types
+    "this won't work".to_string();
+    "removeme".to_string();
+}
+
+fn main() {}
diff --git a/src/test/ui/block-result/consider-removing-last-semi.stderr b/src/test/ui/block-result/consider-removing-last-semi.stderr
new file mode 100644
index 0000000..618d020
--- /dev/null
+++ b/src/test/ui/block-result/consider-removing-last-semi.stderr
@@ -0,0 +1,31 @@
+error[E0308]: mismatched types
+  --> $DIR/consider-removing-last-semi.rs:1:11
+   |
+LL | fn f() -> String {
+   |    -      ^^^^^^ expected struct `std::string::String`, found ()
+   |    |
+   |    this function's body doesn't return
+LL |     0u8;
+LL |     "bla".to_string();
+   |                      - help: consider removing this semicolon
+   |
+   = note: expected type `std::string::String`
+              found type `()`
+
+error[E0308]: mismatched types
+  --> $DIR/consider-removing-last-semi.rs:6:11
+   |
+LL | fn g() -> String {
+   |    -      ^^^^^^ expected struct `std::string::String`, found ()
+   |    |
+   |    this function's body doesn't return
+LL |     "this won't work".to_string();
+LL |     "removeme".to_string();
+   |                           - help: consider removing this semicolon
+   |
+   = note: expected type `std::string::String`
+              found type `()`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/block-result/issue-11714.rs b/src/test/ui/block-result/issue-11714.rs
new file mode 100644
index 0000000..3dda7e8
--- /dev/null
+++ b/src/test/ui/block-result/issue-11714.rs
@@ -0,0 +1,7 @@
+fn blah() -> i32 { //~ ERROR mismatched types
+    1
+
+    ;
+}
+
+fn main() { }
diff --git a/src/test/ui/block-result/issue-11714.stderr b/src/test/ui/block-result/issue-11714.stderr
new file mode 100644
index 0000000..d73489a
--- /dev/null
+++ b/src/test/ui/block-result/issue-11714.stderr
@@ -0,0 +1,17 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-11714.rs:1:14
+   |
+LL | fn blah() -> i32 {
+   |    ----      ^^^ expected i32, found ()
+   |    |
+   |    this function's body doesn't return
+...
+LL |     ;
+   |     - help: consider removing this semicolon
+   |
+   = note: expected type `i32`
+              found type `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/block-result/issue-13428.rs b/src/test/ui/block-result/issue-13428.rs
new file mode 100644
index 0000000..ac85964
--- /dev/null
+++ b/src/test/ui/block-result/issue-13428.rs
@@ -0,0 +1,16 @@
+// Regression test for #13428
+
+fn foo() -> String {  //~ ERROR mismatched types
+    format!("Hello {}",
+            "world")
+    // Put the trailing semicolon on its own line to test that the
+    // note message gets the offending semicolon exactly
+    ;
+}
+
+fn bar() -> String {  //~ ERROR mismatched types
+    "foobar".to_string()
+    ;
+}
+
+pub fn main() {}
diff --git a/src/test/ui/block-result/issue-13428.stderr b/src/test/ui/block-result/issue-13428.stderr
new file mode 100644
index 0000000..18adb15
--- /dev/null
+++ b/src/test/ui/block-result/issue-13428.stderr
@@ -0,0 +1,31 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-13428.rs:3:13
+   |
+LL | fn foo() -> String {
+   |    ---      ^^^^^^ expected struct `std::string::String`, found ()
+   |    |
+   |    this function's body doesn't return
+...
+LL |     ;
+   |     - help: consider removing this semicolon
+   |
+   = note: expected type `std::string::String`
+              found type `()`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-13428.rs:11:13
+   |
+LL | fn bar() -> String {
+   |    ---      ^^^^^^ expected struct `std::string::String`, found ()
+   |    |
+   |    this function's body doesn't return
+LL |     "foobar".to_string()
+LL |     ;
+   |     - help: consider removing this semicolon
+   |
+   = note: expected type `std::string::String`
+              found type `()`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/block-result/issue-13624.rs b/src/test/ui/block-result/issue-13624.rs
new file mode 100644
index 0000000..7b6a077
--- /dev/null
+++ b/src/test/ui/block-result/issue-13624.rs
@@ -0,0 +1,33 @@
+mod a {
+  pub enum Enum {
+    EnumStructVariant { x: u8, y: u8, z: u8 }
+  }
+
+  pub fn get_enum_struct_variant() -> () {
+    Enum::EnumStructVariant { x: 1, y: 2, z: 3 }
+    //~^ ERROR mismatched types
+    //~| expected type `()`
+    //~| found type `a::Enum`
+    //~| expected (), found enum `a::Enum`
+  }
+}
+
+mod b {
+  mod test {
+    use a;
+
+    fn test_enum_struct_variant() {
+      let enum_struct_variant = ::a::get_enum_struct_variant();
+      match enum_struct_variant {
+        a::Enum::EnumStructVariant { x, y, z } => {
+        //~^ ERROR mismatched types
+        //~| expected type `()`
+        //~| found type `a::Enum`
+        //~| expected (), found enum `a::Enum`
+        }
+      }
+    }
+  }
+}
+
+fn main() {}
diff --git a/src/test/ui/block-result/issue-13624.stderr b/src/test/ui/block-result/issue-13624.stderr
new file mode 100644
index 0000000..417667a
--- /dev/null
+++ b/src/test/ui/block-result/issue-13624.stderr
@@ -0,0 +1,25 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-13624.rs:7:5
+   |
+LL |   pub fn get_enum_struct_variant() -> () {
+   |                                       -- expected `()` because of return type
+LL |     Enum::EnumStructVariant { x: 1, y: 2, z: 3 }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found enum `a::Enum`
+   |
+   = note: expected type `()`
+              found type `a::Enum`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-13624.rs:22:9
+   |
+LL |       match enum_struct_variant {
+   |             ------------------- this match expression has type `()`
+LL |         a::Enum::EnumStructVariant { x, y, z } => {
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found enum `a::Enum`
+   |
+   = note: expected type `()`
+              found type `a::Enum`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/block-result/issue-20862.rs b/src/test/ui/block-result/issue-20862.rs
new file mode 100644
index 0000000..e435fd7
--- /dev/null
+++ b/src/test/ui/block-result/issue-20862.rs
@@ -0,0 +1,9 @@
+fn foo(x: i32) {
+    |y| x + y
+//~^ ERROR: mismatched types
+}
+
+fn main() {
+    let x = foo(5)(2);
+//~^ ERROR: expected function, found `()`
+}
diff --git a/src/test/ui/block-result/issue-20862.stderr b/src/test/ui/block-result/issue-20862.stderr
new file mode 100644
index 0000000..fb4feff
--- /dev/null
+++ b/src/test/ui/block-result/issue-20862.stderr
@@ -0,0 +1,29 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-20862.rs:2:5
+   |
+LL | fn foo(x: i32) {
+   |                - possibly return type missing here?
+LL |     |y| x + y
+   |     ^^^^^^^^^ expected (), found closure
+   |
+   = note: expected type `()`
+              found type `[closure@$DIR/issue-20862.rs:2:5: 2:14 x:_]`
+
+error[E0618]: expected function, found `()`
+  --> $DIR/issue-20862.rs:7:13
+   |
+LL | / fn foo(x: i32) {
+LL | |     |y| x + y
+LL | |
+LL | | }
+   | |_- `foo` defined here returns `()`
+...
+LL |       let x = foo(5)(2);
+   |               ^^^^^^---
+   |               |
+   |               call expression requires function
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0308, E0618.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/block-result/issue-22645.rs b/src/test/ui/block-result/issue-22645.rs
new file mode 100644
index 0000000..5f7fb8d
--- /dev/null
+++ b/src/test/ui/block-result/issue-22645.rs
@@ -0,0 +1,17 @@
+use std::ops::Add;
+
+trait Scalar {}
+impl Scalar for f64 {}
+
+struct Bob;
+
+impl<RHS: Scalar> Add <RHS> for Bob {
+  type Output = Bob;
+  fn add(self, rhs : RHS) -> Bob { Bob }
+}
+
+fn main() {
+  let b = Bob + 3.5;
+  b + 3 //~ ERROR E0277
+  //~^ ERROR: mismatched types
+}
diff --git a/src/test/ui/block-result/issue-22645.stderr b/src/test/ui/block-result/issue-22645.stderr
new file mode 100644
index 0000000..e1e6428
--- /dev/null
+++ b/src/test/ui/block-result/issue-22645.stderr
@@ -0,0 +1,26 @@
+error[E0277]: the trait bound `{integer}: Scalar` is not satisfied
+  --> $DIR/issue-22645.rs:15:5
+   |
+LL |   b + 3
+   |     ^ the trait `Scalar` is not implemented for `{integer}`
+   |
+   = help: the following implementations were found:
+             <f64 as Scalar>
+   = note: required because of the requirements on the impl of `std::ops::Add<{integer}>` for `Bob`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-22645.rs:15:3
+   |
+LL | fn main() {
+   |           - expected `()` because of default return type
+LL |   let b = Bob + 3.5;
+LL |   b + 3
+   |   ^^^^^ expected (), found struct `Bob`
+   |
+   = note: expected type `()`
+              found type `Bob`
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0277, E0308.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/block-result/issue-3563.rs b/src/test/ui/block-result/issue-3563.rs
new file mode 100644
index 0000000..9b313d3
--- /dev/null
+++ b/src/test/ui/block-result/issue-3563.rs
@@ -0,0 +1,7 @@
+trait A {
+    fn a(&self) {
+        || self.b()
+        //~^ ERROR no method named `b` found for type `&Self` in the current scope
+    }
+}
+fn main() {}
diff --git a/src/test/ui/block-result/issue-3563.stderr b/src/test/ui/block-result/issue-3563.stderr
new file mode 100644
index 0000000..a6346a5
--- /dev/null
+++ b/src/test/ui/block-result/issue-3563.stderr
@@ -0,0 +1,9 @@
+error[E0599]: no method named `b` found for type `&Self` in the current scope
+  --> $DIR/issue-3563.rs:3:17
+   |
+LL |         || self.b()
+   |                 ^ help: did you mean: `a`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/block-result/issue-5500.rs b/src/test/ui/block-result/issue-5500.rs
new file mode 100644
index 0000000..5a549bb
--- /dev/null
+++ b/src/test/ui/block-result/issue-5500.rs
@@ -0,0 +1,7 @@
+fn main() {
+    &panic!()
+    //~^ ERROR mismatched types
+    //~| expected type `()`
+    //~| found type `&_`
+    //~| expected (), found reference
+}
diff --git a/src/test/ui/block-result/issue-5500.stderr b/src/test/ui/block-result/issue-5500.stderr
new file mode 100644
index 0000000..6a13b31
--- /dev/null
+++ b/src/test/ui/block-result/issue-5500.stderr
@@ -0,0 +1,17 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-5500.rs:2:5
+   |
+LL | fn main() {
+   |           - expected `()` because of default return type
+LL |     &panic!()
+   |     ^^^^^^^^^
+   |     |
+   |     expected (), found reference
+   |     help: consider removing the borrow: `panic!()`
+   |
+   = note: expected type `()`
+              found type `&_`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/block-result/unexpected-return-on-unit.rs b/src/test/ui/block-result/unexpected-return-on-unit.rs
new file mode 100644
index 0000000..2fcbfe8
--- /dev/null
+++ b/src/test/ui/block-result/unexpected-return-on-unit.rs
@@ -0,0 +1,14 @@
+// Test that we do some basic error correction in the tokeniser (and don't spew
+// too many bogus errors).
+
+fn foo() -> usize {
+    3
+}
+
+fn bar() {
+    foo() //~ ERROR mismatched types
+}
+
+fn main() {
+    bar()
+}
diff --git a/src/test/ui/block-result/unexpected-return-on-unit.stderr b/src/test/ui/block-result/unexpected-return-on-unit.stderr
new file mode 100644
index 0000000..3ceff81
--- /dev/null
+++ b/src/test/ui/block-result/unexpected-return-on-unit.stderr
@@ -0,0 +1,20 @@
+error[E0308]: mismatched types
+  --> $DIR/unexpected-return-on-unit.rs:9:5
+   |
+LL |     foo()
+   |     ^^^^^ expected (), found usize
+   |
+   = note: expected type `()`
+              found type `usize`
+help: try adding a semicolon
+   |
+LL |     foo();
+   |          ^
+help: try adding a return type
+   |
+LL | fn bar() -> usize {
+   |          ^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/bogus-tag.rs b/src/test/ui/bogus-tag.rs
new file mode 100644
index 0000000..c594385
--- /dev/null
+++ b/src/test/ui/bogus-tag.rs
@@ -0,0 +1,10 @@
+enum Color { Rgb(isize, isize, isize), Rgba(isize, isize, isize, isize), }
+
+fn main() {
+    let red: Color = Color::Rgb(255, 0, 0);
+    match red {
+        Color::Rgb(r, g, b) => { println!("rgb"); }
+        Color::Hsl(h, s, l) => { println!("hsl"); }
+        //~^ ERROR no variant
+    }
+}
diff --git a/src/test/ui/bogus-tag.stderr b/src/test/ui/bogus-tag.stderr
new file mode 100644
index 0000000..0bf0d4b
--- /dev/null
+++ b/src/test/ui/bogus-tag.stderr
@@ -0,0 +1,12 @@
+error[E0599]: no variant named `Hsl` found for type `Color` in the current scope
+  --> $DIR/bogus-tag.rs:7:16
+   |
+LL | enum Color { Rgb(isize, isize, isize), Rgba(isize, isize, isize, isize), }
+   | ---------- variant `Hsl` not found here
+...
+LL |         Color::Hsl(h, s, l) => { println!("hsl"); }
+   |                ^^^ variant not found in `Color`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/borrowck/assign_mutable_fields.nll.stderr b/src/test/ui/borrowck/assign_mutable_fields.nll.stderr
new file mode 100644
index 0000000..35101df
--- /dev/null
+++ b/src/test/ui/borrowck/assign_mutable_fields.nll.stderr
@@ -0,0 +1,15 @@
+error[E0381]: assign to part of possibly uninitialized variable: `x`
+  --> $DIR/assign_mutable_fields.rs:9:5
+   |
+LL |     x.0 = 1;
+   |     ^^^^^^^ use of possibly uninitialized `x`
+
+error[E0381]: assign to part of possibly uninitialized variable: `x`
+  --> $DIR/assign_mutable_fields.rs:17:5
+   |
+LL |     x.0 = 1;
+   |     ^^^^^^^ use of possibly uninitialized `x`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/assign_mutable_fields.rs b/src/test/ui/borrowck/assign_mutable_fields.rs
new file mode 100644
index 0000000..85d6f3b
--- /dev/null
+++ b/src/test/ui/borrowck/assign_mutable_fields.rs
@@ -0,0 +1,22 @@
+// Currently, we permit you to assign to individual fields of a mut
+// var, but we do not permit you to use the complete var afterwards.
+// We hope to fix this at some point.
+//
+// FIXME(#54987)
+
+fn assign_both_fields_and_use() {
+    let mut x: (u32, u32);
+    x.0 = 1;
+    x.1 = 22;
+    drop(x.0); //~ ERROR
+    drop(x.1); //~ ERROR
+}
+
+fn assign_both_fields_the_use_var() {
+    let mut x: (u32, u32);
+    x.0 = 1;
+    x.1 = 22;
+    drop(x); //~ ERROR
+}
+
+fn main() { }
diff --git a/src/test/ui/borrowck/assign_mutable_fields.stderr b/src/test/ui/borrowck/assign_mutable_fields.stderr
new file mode 100644
index 0000000..904d2ed
--- /dev/null
+++ b/src/test/ui/borrowck/assign_mutable_fields.stderr
@@ -0,0 +1,21 @@
+error[E0381]: use of possibly uninitialized variable: `x.0`
+  --> $DIR/assign_mutable_fields.rs:11:10
+   |
+LL |     drop(x.0);
+   |          ^^^ use of possibly uninitialized `x.0`
+
+error[E0381]: use of possibly uninitialized variable: `x.1`
+  --> $DIR/assign_mutable_fields.rs:12:10
+   |
+LL |     drop(x.1);
+   |          ^^^ use of possibly uninitialized `x.1`
+
+error[E0381]: use of possibly uninitialized variable: `x`
+  --> $DIR/assign_mutable_fields.rs:19:10
+   |
+LL |     drop(x);
+   |          ^ use of possibly uninitialized `x`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/borrow-immutable-upvar-mutation.nll.stderr b/src/test/ui/borrowck/borrow-immutable-upvar-mutation.nll.stderr
new file mode 100644
index 0000000..af45c8a
--- /dev/null
+++ b/src/test/ui/borrowck/borrow-immutable-upvar-mutation.nll.stderr
@@ -0,0 +1,76 @@
+error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure
+  --> $DIR/borrow-immutable-upvar-mutation.rs:15:27
+   |
+LL |         let _f = to_fn(|| x = 42);
+   |                           ^^^^^^ cannot assign
+   |
+help: consider changing this to accept closures that implement `FnMut`
+  --> $DIR/borrow-immutable-upvar-mutation.rs:15:24
+   |
+LL |         let _f = to_fn(|| x = 42);
+   |                        ^^^^^^^^^
+
+error[E0596]: cannot borrow `y` as mutable, as it is a captured variable in a `Fn` closure
+  --> $DIR/borrow-immutable-upvar-mutation.rs:18:31
+   |
+LL |         let _g = to_fn(|| set(&mut y));
+   |                               ^^^^^^ cannot borrow as mutable
+   |
+help: consider changing this to accept closures that implement `FnMut`
+  --> $DIR/borrow-immutable-upvar-mutation.rs:18:24
+   |
+LL |         let _g = to_fn(|| set(&mut y));
+   |                        ^^^^^^^^^^^^^^
+
+error[E0594]: cannot assign to `z`, as it is a captured variable in a `Fn` closure
+  --> $DIR/borrow-immutable-upvar-mutation.rs:21:55
+   |
+LL |         let _h = to_fn_mut(|| { set(&mut z); to_fn(|| z = 42); });
+   |                                                       ^^^^^^ cannot assign
+   |
+help: consider changing this to accept closures that implement `FnMut`
+  --> $DIR/borrow-immutable-upvar-mutation.rs:21:52
+   |
+LL |         let _h = to_fn_mut(|| { set(&mut z); to_fn(|| z = 42); });
+   |                                                    ^^^^^^^^^
+
+error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure
+  --> $DIR/borrow-immutable-upvar-mutation.rs:27:32
+   |
+LL |         let _f = to_fn(move || x = 42);
+   |                                ^^^^^^ cannot assign
+   |
+help: consider changing this to accept closures that implement `FnMut`
+  --> $DIR/borrow-immutable-upvar-mutation.rs:27:24
+   |
+LL |         let _f = to_fn(move || x = 42);
+   |                        ^^^^^^^^^^^^^^
+
+error[E0596]: cannot borrow `y` as mutable, as it is a captured variable in a `Fn` closure
+  --> $DIR/borrow-immutable-upvar-mutation.rs:30:36
+   |
+LL |         let _g = to_fn(move || set(&mut y));
+   |                                    ^^^^^^ cannot borrow as mutable
+   |
+help: consider changing this to accept closures that implement `FnMut`
+  --> $DIR/borrow-immutable-upvar-mutation.rs:30:24
+   |
+LL |         let _g = to_fn(move || set(&mut y));
+   |                        ^^^^^^^^^^^^^^^^^^^
+
+error[E0594]: cannot assign to `z`, as it is a captured variable in a `Fn` closure
+  --> $DIR/borrow-immutable-upvar-mutation.rs:33:65
+   |
+LL |         let _h = to_fn_mut(move || { set(&mut z); to_fn(move || z = 42); });
+   |                                                                 ^^^^^^ cannot assign
+   |
+help: consider changing this to accept closures that implement `FnMut`
+  --> $DIR/borrow-immutable-upvar-mutation.rs:33:57
+   |
+LL |         let _h = to_fn_mut(move || { set(&mut z); to_fn(move || z = 42); });
+   |                                                         ^^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
+Some errors occurred: E0594, E0596.
+For more information about an error, try `rustc --explain E0594`.
diff --git a/src/test/ui/borrowck/borrow-immutable-upvar-mutation.rs b/src/test/ui/borrowck/borrow-immutable-upvar-mutation.rs
new file mode 100644
index 0000000..fed8bc9
--- /dev/null
+++ b/src/test/ui/borrowck/borrow-immutable-upvar-mutation.rs
@@ -0,0 +1,35 @@
+#![feature(unboxed_closures)]
+
+// Tests that we can't assign to or mutably borrow upvars from `Fn`
+// closures (issue #17780)
+
+fn set(x: &mut usize) { *x = 5; }
+
+fn to_fn<A,F:Fn<A>>(f: F) -> F { f }
+fn to_fn_mut<A,F:FnMut<A>>(f: F) -> F { f }
+
+fn main() {
+    // By-ref captures
+    {
+        let mut x = 0;
+        let _f = to_fn(|| x = 42); //~ ERROR cannot assign
+
+        let mut y = 0;
+        let _g = to_fn(|| set(&mut y)); //~ ERROR cannot borrow
+
+        let mut z = 0;
+        let _h = to_fn_mut(|| { set(&mut z); to_fn(|| z = 42); }); //~ ERROR cannot assign
+    }
+
+    // By-value captures
+    {
+        let mut x = 0;
+        let _f = to_fn(move || x = 42); //~ ERROR cannot assign
+
+        let mut y = 0;
+        let _g = to_fn(move || set(&mut y)); //~ ERROR cannot borrow
+
+        let mut z = 0;
+        let _h = to_fn_mut(move || { set(&mut z); to_fn(move || z = 42); }); //~ ERROR cannot assign
+    }
+}
diff --git a/src/test/ui/borrowck/borrow-immutable-upvar-mutation.stderr b/src/test/ui/borrowck/borrow-immutable-upvar-mutation.stderr
new file mode 100644
index 0000000..09adb35
--- /dev/null
+++ b/src/test/ui/borrowck/borrow-immutable-upvar-mutation.stderr
@@ -0,0 +1,78 @@
+error[E0387]: cannot assign to data in a captured outer variable in an `Fn` closure
+  --> $DIR/borrow-immutable-upvar-mutation.rs:15:27
+   |
+LL |         let _f = to_fn(|| x = 42);
+   |                           ^^^^^^
+   |
+help: consider changing this closure to take self by mutable reference
+  --> $DIR/borrow-immutable-upvar-mutation.rs:15:24
+   |
+LL |         let _f = to_fn(|| x = 42);
+   |                        ^^^^^^^^^
+
+error[E0387]: cannot borrow data mutably in a captured outer variable in an `Fn` closure
+  --> $DIR/borrow-immutable-upvar-mutation.rs:18:36
+   |
+LL |         let _g = to_fn(|| set(&mut y));
+   |                                    ^
+   |
+help: consider changing this closure to take self by mutable reference
+  --> $DIR/borrow-immutable-upvar-mutation.rs:18:24
+   |
+LL |         let _g = to_fn(|| set(&mut y));
+   |                        ^^^^^^^^^^^^^^
+
+error[E0387]: cannot assign to data in a captured outer variable in an `Fn` closure
+  --> $DIR/borrow-immutable-upvar-mutation.rs:21:55
+   |
+LL |         let _h = to_fn_mut(|| { set(&mut z); to_fn(|| z = 42); });
+   |                                                       ^^^^^^
+   |
+help: consider changing this closure to take self by mutable reference
+  --> $DIR/borrow-immutable-upvar-mutation.rs:21:52
+   |
+LL |         let _h = to_fn_mut(|| { set(&mut z); to_fn(|| z = 42); });
+   |                                                    ^^^^^^^^^
+
+error[E0594]: cannot assign to captured outer variable in an `Fn` closure
+  --> $DIR/borrow-immutable-upvar-mutation.rs:27:32
+   |
+LL |         let _f = to_fn(move || x = 42);
+   |                                ^^^^^^
+   |
+   = note: `Fn` closures cannot capture their enclosing environment for modifications
+help: consider changing this closure to take self by mutable reference
+  --> $DIR/borrow-immutable-upvar-mutation.rs:27:24
+   |
+LL |         let _f = to_fn(move || x = 42);
+   |                        ^^^^^^^^^^^^^^
+
+error[E0596]: cannot borrow captured outer variable in an `Fn` closure as mutable
+  --> $DIR/borrow-immutable-upvar-mutation.rs:30:41
+   |
+LL |         let _g = to_fn(move || set(&mut y));
+   |                                         ^
+   |
+help: consider changing this closure to take self by mutable reference
+  --> $DIR/borrow-immutable-upvar-mutation.rs:30:24
+   |
+LL |         let _g = to_fn(move || set(&mut y));
+   |                        ^^^^^^^^^^^^^^^^^^^
+
+error[E0594]: cannot assign to captured outer variable in an `Fn` closure
+  --> $DIR/borrow-immutable-upvar-mutation.rs:33:65
+   |
+LL |         let _h = to_fn_mut(move || { set(&mut z); to_fn(move || z = 42); });
+   |                                                                 ^^^^^^
+   |
+   = note: `Fn` closures cannot capture their enclosing environment for modifications
+help: consider changing this closure to take self by mutable reference
+  --> $DIR/borrow-immutable-upvar-mutation.rs:33:57
+   |
+LL |         let _h = to_fn_mut(move || { set(&mut z); to_fn(move || z = 42); });
+   |                                                         ^^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
+Some errors occurred: E0387, E0594, E0596.
+For more information about an error, try `rustc --explain E0387`.
diff --git a/src/test/ui/borrowck/borrow-tuple-fields.nll.stderr b/src/test/ui/borrowck/borrow-tuple-fields.nll.stderr
new file mode 100644
index 0000000..5c40555
--- /dev/null
+++ b/src/test/ui/borrowck/borrow-tuple-fields.nll.stderr
@@ -0,0 +1,65 @@
+error[E0505]: cannot move out of `x` because it is borrowed
+  --> $DIR/borrow-tuple-fields.rs:12:13
+   |
+LL |     let r = &x.0;
+   |             ---- borrow of `x.0` occurs here
+LL |     let y = x;
+   |             ^ move out of `x` occurs here
+LL | 
+LL |     r.use_ref();
+   |     - borrow later used here
+
+error[E0502]: cannot borrow `x.0` as mutable because it is also borrowed as immutable
+  --> $DIR/borrow-tuple-fields.rs:18:13
+   |
+LL |     let a = &x.0;
+   |             ---- immutable borrow occurs here
+LL |     let b = &mut x.0;
+   |             ^^^^^^^^ mutable borrow occurs here
+LL |     a.use_ref();
+   |     - immutable borrow later used here
+
+error[E0499]: cannot borrow `x.0` as mutable more than once at a time
+  --> $DIR/borrow-tuple-fields.rs:23:13
+   |
+LL |     let a = &mut x.0;
+   |             -------- first mutable borrow occurs here
+LL |     let b = &mut x.0;
+   |             ^^^^^^^^ second mutable borrow occurs here
+LL |     a.use_ref();
+   |     - first borrow later used here
+
+error[E0505]: cannot move out of `x` because it is borrowed
+  --> $DIR/borrow-tuple-fields.rs:28:13
+   |
+LL |     let r = &x.0;
+   |             ---- borrow of `x.0` occurs here
+LL |     let y = x;
+   |             ^ move out of `x` occurs here
+LL |     r.use_ref();
+   |     - borrow later used here
+
+error[E0502]: cannot borrow `x.0` as mutable because it is also borrowed as immutable
+  --> $DIR/borrow-tuple-fields.rs:33:13
+   |
+LL |     let a = &x.0;
+   |             ---- immutable borrow occurs here
+LL |     let b = &mut x.0;
+   |             ^^^^^^^^ mutable borrow occurs here
+LL |     a.use_ref();
+   |     - immutable borrow later used here
+
+error[E0499]: cannot borrow `x.0` as mutable more than once at a time
+  --> $DIR/borrow-tuple-fields.rs:38:13
+   |
+LL |     let a = &mut x.0;
+   |             -------- first mutable borrow occurs here
+LL |     let b = &mut x.0;
+   |             ^^^^^^^^ second mutable borrow occurs here
+LL |     a.use_mut();
+   |     - first borrow later used here
+
+error: aborting due to 6 previous errors
+
+Some errors occurred: E0499, E0502, E0505.
+For more information about an error, try `rustc --explain E0499`.
diff --git a/src/test/ui/borrowck/borrow-tuple-fields.rs b/src/test/ui/borrowck/borrow-tuple-fields.rs
new file mode 100644
index 0000000..3e24a1b
--- /dev/null
+++ b/src/test/ui/borrowck/borrow-tuple-fields.rs
@@ -0,0 +1,43 @@
+#![feature(box_syntax)]
+
+
+
+struct Foo(Box<isize>, isize);
+
+struct Bar(isize, isize);
+
+fn main() {
+    let x: (Box<_>, _) = (box 1, 2);
+    let r = &x.0;
+    let y = x; //~ ERROR cannot move out of `x` because it is borrowed
+
+    r.use_ref();
+
+    let mut x = (1, 2);
+    let a = &x.0;
+    let b = &mut x.0; //~ ERROR cannot borrow `x.0` as mutable because it is also borrowed as
+    a.use_ref();
+
+    let mut x = (1, 2);
+    let a = &mut x.0;
+    let b = &mut x.0; //~ ERROR cannot borrow `x.0` as mutable more than once at a time
+    a.use_ref();
+
+    let x = Foo(box 1, 2);
+    let r = &x.0;
+    let y = x; //~ ERROR cannot move out of `x` because it is borrowed
+    r.use_ref();
+
+    let mut x = Bar(1, 2);
+    let a = &x.0;
+    let b = &mut x.0; //~ ERROR cannot borrow `x.0` as mutable because it is also borrowed as
+    a.use_ref();
+
+    let mut x = Bar(1, 2);
+    let a = &mut x.0;
+    let b = &mut x.0; //~ ERROR cannot borrow `x.0` as mutable more than once at a time
+    a.use_mut();
+}
+
+trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { }  }
+impl<T> Fake for T { }
diff --git a/src/test/ui/borrowck/borrow-tuple-fields.stderr b/src/test/ui/borrowck/borrow-tuple-fields.stderr
new file mode 100644
index 0000000..f7fc06e
--- /dev/null
+++ b/src/test/ui/borrowck/borrow-tuple-fields.stderr
@@ -0,0 +1,64 @@
+error[E0505]: cannot move out of `x` because it is borrowed
+  --> $DIR/borrow-tuple-fields.rs:12:9
+   |
+LL |     let r = &x.0;
+   |              --- borrow of `x.0` occurs here
+LL |     let y = x;
+   |         ^ move out of `x` occurs here
+
+error[E0502]: cannot borrow `x.0` as mutable because it is also borrowed as immutable
+  --> $DIR/borrow-tuple-fields.rs:18:18
+   |
+LL |     let a = &x.0;
+   |              --- immutable borrow occurs here
+LL |     let b = &mut x.0;
+   |                  ^^^ mutable borrow occurs here
+...
+LL | }
+   | - immutable borrow ends here
+
+error[E0499]: cannot borrow `x.0` as mutable more than once at a time
+  --> $DIR/borrow-tuple-fields.rs:23:18
+   |
+LL |     let a = &mut x.0;
+   |                  --- first mutable borrow occurs here
+LL |     let b = &mut x.0;
+   |                  ^^^ second mutable borrow occurs here
+...
+LL | }
+   | - first borrow ends here
+
+error[E0505]: cannot move out of `x` because it is borrowed
+  --> $DIR/borrow-tuple-fields.rs:28:9
+   |
+LL |     let r = &x.0;
+   |              --- borrow of `x.0` occurs here
+LL |     let y = x;
+   |         ^ move out of `x` occurs here
+
+error[E0502]: cannot borrow `x.0` as mutable because it is also borrowed as immutable
+  --> $DIR/borrow-tuple-fields.rs:33:18
+   |
+LL |     let a = &x.0;
+   |              --- immutable borrow occurs here
+LL |     let b = &mut x.0;
+   |                  ^^^ mutable borrow occurs here
+...
+LL | }
+   | - immutable borrow ends here
+
+error[E0499]: cannot borrow `x.0` as mutable more than once at a time
+  --> $DIR/borrow-tuple-fields.rs:38:18
+   |
+LL |     let a = &mut x.0;
+   |                  --- first mutable borrow occurs here
+LL |     let b = &mut x.0;
+   |                  ^^^ second mutable borrow occurs here
+LL |     a.use_mut();
+LL | }
+   | - first borrow ends here
+
+error: aborting due to 6 previous errors
+
+Some errors occurred: E0499, E0502, E0505.
+For more information about an error, try `rustc --explain E0499`.
diff --git a/src/test/ui/borrowck/borrowck-access-permissions.ast.nll.stderr b/src/test/ui/borrowck/borrowck-access-permissions.ast.nll.stderr
new file mode 100644
index 0000000..12f9ad8
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-access-permissions.ast.nll.stderr
@@ -0,0 +1,53 @@
+error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
+  --> $DIR/borrowck-access-permissions.rs:12:19
+   |
+LL |     let x = 1;
+   |         - help: consider changing this to be mutable: `mut x`
+...
+LL |         let _y1 = &mut x;
+   |                   ^^^^^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow immutable static item `static_x` as mutable
+  --> $DIR/borrowck-access-permissions.rs:18:19
+   |
+LL |         let _y1 = &mut static_x;
+   |                   ^^^^^^^^^^^^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow `*box_x` as mutable, as `box_x` is not declared as mutable
+  --> $DIR/borrowck-access-permissions.rs:27:19
+   |
+LL |         let box_x = Box::new(1);
+   |             ----- help: consider changing this to be mutable: `mut box_x`
+...
+LL |         let _y1 = &mut *box_x;
+   |                   ^^^^^^^^^^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow `*ref_x` as mutable, as it is behind a `&` reference
+  --> $DIR/borrowck-access-permissions.rs:36:19
+   |
+LL |         let ref_x = &x;
+   |                     -- help: consider changing this to be a mutable reference: `&mut x`
+...
+LL |         let _y1 = &mut *ref_x;
+   |                   ^^^^^^^^^^^ `ref_x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+
+error[E0596]: cannot borrow `*ptr_x` as mutable, as it is behind a `*const` pointer
+  --> $DIR/borrowck-access-permissions.rs:46:23
+   |
+LL |         let ptr_x : *const _ = &x;
+   |                                -- help: consider changing this to be a mutable pointer: `&mut x`
+...
+LL |             let _y1 = &mut *ptr_x;
+   |                       ^^^^^^^^^^^ `ptr_x` is a `*const` pointer, so the data it refers to cannot be borrowed as mutable
+
+error[E0596]: cannot borrow `*foo_ref.f` as mutable, as it is behind a `&` reference
+  --> $DIR/borrowck-access-permissions.rs:56:18
+   |
+LL |         let foo_ref = &foo;
+   |                       ---- help: consider changing this to be a mutable reference: `&mut foo`
+LL |         let _y = &mut *foo_ref.f;
+   |                  ^^^^^^^^^^^^^^^ `foo_ref` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/borrowck/borrowck-access-permissions.ast.stderr b/src/test/ui/borrowck/borrowck-access-permissions.ast.stderr
new file mode 100644
index 0000000..a1cc063
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-access-permissions.ast.stderr
@@ -0,0 +1,46 @@
+error[E0596]: cannot borrow immutable local variable `x` as mutable
+  --> $DIR/borrowck-access-permissions.rs:12:24
+   |
+LL |     let x = 1;
+   |         - help: make this binding mutable: `mut x`
+...
+LL |         let _y1 = &mut x;
+   |                        ^ cannot borrow mutably
+
+error[E0596]: cannot borrow immutable static item as mutable
+  --> $DIR/borrowck-access-permissions.rs:18:24
+   |
+LL |         let _y1 = &mut static_x;
+   |                        ^^^^^^^^
+
+error[E0596]: cannot borrow immutable `Box` content `*box_x` as mutable
+  --> $DIR/borrowck-access-permissions.rs:27:24
+   |
+LL |         let box_x = Box::new(1);
+   |             ----- help: make this binding mutable: `mut box_x`
+...
+LL |         let _y1 = &mut *box_x;
+   |                        ^^^^^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow immutable borrowed content `*ref_x` as mutable
+  --> $DIR/borrowck-access-permissions.rs:36:24
+   |
+LL |         let _y1 = &mut *ref_x;
+   |                        ^^^^^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow immutable dereference of raw pointer `*ptr_x` as mutable
+  --> $DIR/borrowck-access-permissions.rs:46:28
+   |
+LL |             let _y1 = &mut *ptr_x;
+   |                            ^^^^^^ cannot borrow as mutable
+
+error[E0389]: cannot borrow data mutably in a `&` reference
+  --> $DIR/borrowck-access-permissions.rs:56:23
+   |
+LL |         let _y = &mut *foo_ref.f;
+   |                       ^^^^^^^^^^ assignment into an immutable reference
+
+error: aborting due to 6 previous errors
+
+Some errors occurred: E0389, E0596.
+For more information about an error, try `rustc --explain E0389`.
diff --git a/src/test/ui/borrowck/borrowck-access-permissions.mir.stderr b/src/test/ui/borrowck/borrowck-access-permissions.mir.stderr
new file mode 100644
index 0000000..12f9ad8
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-access-permissions.mir.stderr
@@ -0,0 +1,53 @@
+error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
+  --> $DIR/borrowck-access-permissions.rs:12:19
+   |
+LL |     let x = 1;
+   |         - help: consider changing this to be mutable: `mut x`
+...
+LL |         let _y1 = &mut x;
+   |                   ^^^^^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow immutable static item `static_x` as mutable
+  --> $DIR/borrowck-access-permissions.rs:18:19
+   |
+LL |         let _y1 = &mut static_x;
+   |                   ^^^^^^^^^^^^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow `*box_x` as mutable, as `box_x` is not declared as mutable
+  --> $DIR/borrowck-access-permissions.rs:27:19
+   |
+LL |         let box_x = Box::new(1);
+   |             ----- help: consider changing this to be mutable: `mut box_x`
+...
+LL |         let _y1 = &mut *box_x;
+   |                   ^^^^^^^^^^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow `*ref_x` as mutable, as it is behind a `&` reference
+  --> $DIR/borrowck-access-permissions.rs:36:19
+   |
+LL |         let ref_x = &x;
+   |                     -- help: consider changing this to be a mutable reference: `&mut x`
+...
+LL |         let _y1 = &mut *ref_x;
+   |                   ^^^^^^^^^^^ `ref_x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+
+error[E0596]: cannot borrow `*ptr_x` as mutable, as it is behind a `*const` pointer
+  --> $DIR/borrowck-access-permissions.rs:46:23
+   |
+LL |         let ptr_x : *const _ = &x;
+   |                                -- help: consider changing this to be a mutable pointer: `&mut x`
+...
+LL |             let _y1 = &mut *ptr_x;
+   |                       ^^^^^^^^^^^ `ptr_x` is a `*const` pointer, so the data it refers to cannot be borrowed as mutable
+
+error[E0596]: cannot borrow `*foo_ref.f` as mutable, as it is behind a `&` reference
+  --> $DIR/borrowck-access-permissions.rs:56:18
+   |
+LL |         let foo_ref = &foo;
+   |                       ---- help: consider changing this to be a mutable reference: `&mut foo`
+LL |         let _y = &mut *foo_ref.f;
+   |                  ^^^^^^^^^^^^^^^ `foo_ref` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/borrowck/borrowck-access-permissions.rs b/src/test/ui/borrowck/borrowck-access-permissions.rs
new file mode 100644
index 0000000..993742f
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-access-permissions.rs
@@ -0,0 +1,60 @@
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+static static_x : i32 = 1;
+static mut static_x_mut : i32 = 1;
+
+fn main() {
+    let x = 1;
+    let mut x_mut = 1;
+
+    { // borrow of local
+        let _y1 = &mut x; //[ast]~ ERROR [E0596]
+                          //[mir]~^ ERROR [E0596]
+        let _y2 = &mut x_mut; // No error
+    }
+
+    { // borrow of static
+        let _y1 = &mut static_x; //[ast]~ ERROR [E0596]
+                                 //[mir]~^ ERROR [E0596]
+        unsafe { let _y2 = &mut static_x_mut; } // No error
+    }
+
+    { // borrow of deref to box
+        let box_x = Box::new(1);
+        let mut box_x_mut = Box::new(1);
+
+        let _y1 = &mut *box_x; //[ast]~ ERROR [E0596]
+                               //[mir]~^ ERROR [E0596]
+        let _y2 = &mut *box_x_mut; // No error
+    }
+
+    { // borrow of deref to reference
+        let ref_x = &x;
+        let ref_x_mut = &mut x_mut;
+
+        let _y1 = &mut *ref_x; //[ast]~ ERROR [E0596]
+                               //[mir]~^ ERROR [E0596]
+        let _y2 = &mut *ref_x_mut; // No error
+    }
+
+    { // borrow of deref to pointer
+        let ptr_x : *const _ = &x;
+        let ptr_mut_x : *mut _ = &mut x_mut;
+
+        unsafe {
+            let _y1 = &mut *ptr_x; //[ast]~ ERROR [E0596]
+                                   //[mir]~^ ERROR [E0596]
+            let _y2 = &mut *ptr_mut_x; // No error
+        }
+    }
+
+    { // borrowing mutably through an immutable reference
+        struct Foo<'a> { f: &'a mut i32, g: &'a i32 };
+        let mut foo = Foo { f: &mut x_mut, g: &x };
+        let foo_ref = &foo;
+        let _y = &mut *foo_ref.f; //[ast]~ ERROR [E0389]
+                                  //[mir]~^ ERROR [E0596]
+                                  // FIXME: Wrong error in MIR
+    }
+}
diff --git a/src/test/ui/borrowck/borrowck-and-init.nll.stderr b/src/test/ui/borrowck/borrowck-and-init.nll.stderr
new file mode 100644
index 0000000..2db0751
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-and-init.nll.stderr
@@ -0,0 +1,9 @@
+error[E0381]: borrow of possibly uninitialized variable: `i`
+  --> $DIR/borrowck-and-init.rs:5:20
+   |
+LL |     println!("{}", i);
+   |                    ^ use of possibly uninitialized `i`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/borrowck-and-init.rs b/src/test/ui/borrowck/borrowck-and-init.rs
new file mode 100644
index 0000000..ff076c5
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-and-init.rs
@@ -0,0 +1,6 @@
+fn main() {
+    let i: isize;
+
+    println!("{}", false && { i = 5; true });
+    println!("{}", i); //~ ERROR use of possibly uninitialized variable: `i`
+}
diff --git a/src/test/ui/borrowck/borrowck-and-init.stderr b/src/test/ui/borrowck/borrowck-and-init.stderr
new file mode 100644
index 0000000..13696ac
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-and-init.stderr
@@ -0,0 +1,9 @@
+error[E0381]: use of possibly uninitialized variable: `i`
+  --> $DIR/borrowck-and-init.rs:5:20
+   |
+LL |     println!("{}", i);
+   |                    ^ use of possibly uninitialized `i`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/borrowck-anon-fields-struct.nll.stderr b/src/test/ui/borrowck/borrowck-anon-fields-struct.nll.stderr
new file mode 100644
index 0000000..7a959fb
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-anon-fields-struct.nll.stderr
@@ -0,0 +1,15 @@
+error[E0499]: cannot borrow `y.0` as mutable more than once at a time
+  --> $DIR/borrowck-anon-fields-struct.rs:29:11
+   |
+LL |         Y(ref mut a, _) => a
+   |           --------- first mutable borrow occurs here
+...
+LL |         Y(ref mut b, _) => b
+   |           ^^^^^^^^^ second mutable borrow occurs here
+...
+LL |     *a += 1;
+   |     ------- first borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/borrowck/borrowck-anon-fields-struct.rs b/src/test/ui/borrowck/borrowck-anon-fields-struct.rs
new file mode 100644
index 0000000..a05dfe6
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-anon-fields-struct.rs
@@ -0,0 +1,37 @@
+// Tests that we are able to distinguish when loans borrow different
+// anonymous fields of a tuple vs the same anonymous field.
+
+struct Y(usize, usize);
+
+fn distinct_variant() {
+    let mut y = Y(1, 2);
+
+    let a = match y {
+        Y(ref mut a, _) => a
+    };
+
+    let b = match y {
+        Y(_, ref mut b) => b
+    };
+
+    *a += 1;
+    *b += 1;
+}
+
+fn same_variant() {
+    let mut y = Y(1, 2);
+
+    let a = match y {
+        Y(ref mut a, _) => a
+    };
+
+    let b = match y {
+        Y(ref mut b, _) => b //~ ERROR cannot borrow
+    };
+
+    *a += 1;
+    *b += 1;
+}
+
+fn main() {
+}
diff --git a/src/test/ui/borrowck/borrowck-anon-fields-struct.stderr b/src/test/ui/borrowck/borrowck-anon-fields-struct.stderr
new file mode 100644
index 0000000..efe94de
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-anon-fields-struct.stderr
@@ -0,0 +1,15 @@
+error[E0499]: cannot borrow `y.0` as mutable more than once at a time
+  --> $DIR/borrowck-anon-fields-struct.rs:29:11
+   |
+LL |         Y(ref mut a, _) => a
+   |           --------- first mutable borrow occurs here
+...
+LL |         Y(ref mut b, _) => b
+   |           ^^^^^^^^^ second mutable borrow occurs here
+...
+LL | }
+   | - first borrow ends here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/borrowck/borrowck-anon-fields-tuple.nll.stderr b/src/test/ui/borrowck/borrowck-anon-fields-tuple.nll.stderr
new file mode 100644
index 0000000..88a8867
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-anon-fields-tuple.nll.stderr
@@ -0,0 +1,15 @@
+error[E0499]: cannot borrow `y.0` as mutable more than once at a time
+  --> $DIR/borrowck-anon-fields-tuple.rs:27:10
+   |
+LL |         (ref mut a, _) => a
+   |          --------- first mutable borrow occurs here
+...
+LL |         (ref mut b, _) => b
+   |          ^^^^^^^^^ second mutable borrow occurs here
+...
+LL |     *a += 1;
+   |     ------- first borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/borrowck/borrowck-anon-fields-tuple.rs b/src/test/ui/borrowck/borrowck-anon-fields-tuple.rs
new file mode 100644
index 0000000..de2a8d8
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-anon-fields-tuple.rs
@@ -0,0 +1,35 @@
+// Tests that we are able to distinguish when loans borrow different
+// anonymous fields of a tuple vs the same anonymous field.
+
+fn distinct_variant() {
+    let mut y = (1, 2);
+
+    let a = match y {
+        (ref mut a, _) => a
+    };
+
+    let b = match y {
+        (_, ref mut b) => b
+    };
+
+    *a += 1;
+    *b += 1;
+}
+
+fn same_variant() {
+    let mut y = (1, 2);
+
+    let a = match y {
+        (ref mut a, _) => a
+    };
+
+    let b = match y {
+        (ref mut b, _) => b //~ ERROR cannot borrow
+    };
+
+    *a += 1;
+    *b += 1;
+}
+
+fn main() {
+}
diff --git a/src/test/ui/borrowck/borrowck-anon-fields-tuple.stderr b/src/test/ui/borrowck/borrowck-anon-fields-tuple.stderr
new file mode 100644
index 0000000..40f96cb
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-anon-fields-tuple.stderr
@@ -0,0 +1,15 @@
+error[E0499]: cannot borrow `y.0` as mutable more than once at a time
+  --> $DIR/borrowck-anon-fields-tuple.rs:27:10
+   |
+LL |         (ref mut a, _) => a
+   |          --------- first mutable borrow occurs here
+...
+LL |         (ref mut b, _) => b
+   |          ^^^^^^^^^ second mutable borrow occurs here
+...
+LL | }
+   | - first borrow ends here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/borrowck/borrowck-anon-fields-variant.nll.stderr b/src/test/ui/borrowck/borrowck-anon-fields-variant.nll.stderr
new file mode 100644
index 0000000..6c8a32e
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-anon-fields-variant.nll.stderr
@@ -0,0 +1,43 @@
+warning[E0503]: cannot use `y` because it was mutably borrowed
+  --> $DIR/borrowck-anon-fields-variant.rs:17:7
+   |
+LL |       Foo::Y(ref mut a, _) => a,
+   |              --------- borrow of `y.0` occurs here
+...
+LL |       Foo::Y(_, ref mut b) => b,
+   |       ^^^^^^^^^^^^^^^^^^^^ use of borrowed `y.0`
+...
+LL |     *a += 1;
+   |     ------- borrow later used here
+   |
+   = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
+   = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+
+error[E0503]: cannot use `y` because it was mutably borrowed
+  --> $DIR/borrowck-anon-fields-variant.rs:34:7
+   |
+LL |       Foo::Y(ref mut a, _) => a,
+   |              --------- borrow of `y.0` occurs here
+...
+LL |       Foo::Y(ref mut b, _) => b,
+   |       ^^^^^^^^^^^^^^^^^^^^ use of borrowed `y.0`
+...
+LL |     *a += 1;
+   |     ------- borrow later used here
+
+error[E0499]: cannot borrow `y.0` as mutable more than once at a time
+  --> $DIR/borrowck-anon-fields-variant.rs:34:14
+   |
+LL |       Foo::Y(ref mut a, _) => a,
+   |              --------- first mutable borrow occurs here
+...
+LL |       Foo::Y(ref mut b, _) => b,
+   |              ^^^^^^^^^ second mutable borrow occurs here
+...
+LL |     *a += 1;
+   |     ------- first borrow later used here
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0499, E0503.
+For more information about an error, try `rustc --explain E0499`.
diff --git a/src/test/ui/borrowck/borrowck-anon-fields-variant.rs b/src/test/ui/borrowck/borrowck-anon-fields-variant.rs
new file mode 100644
index 0000000..c274356
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-anon-fields-variant.rs
@@ -0,0 +1,43 @@
+// Tests that we are able to distinguish when loans borrow different
+// anonymous fields of an enum variant vs the same anonymous field.
+
+enum Foo {
+    X, Y(usize, usize)
+}
+
+fn distinct_variant() {
+    let mut y = Foo::Y(1, 2);
+
+    let a = match y {
+      Foo::Y(ref mut a, _) => a,
+      Foo::X => panic!()
+    };
+
+    let b = match y {
+      Foo::Y(_, ref mut b) => b,
+      Foo::X => panic!()
+    };
+
+    *a += 1;
+    *b += 1;
+}
+
+fn same_variant() {
+    let mut y = Foo::Y(1, 2);
+
+    let a = match y {
+      Foo::Y(ref mut a, _) => a,
+      Foo::X => panic!()
+    };
+
+    let b = match y {
+      Foo::Y(ref mut b, _) => b, //~ ERROR cannot borrow
+      Foo::X => panic!()
+    };
+
+    *a += 1;
+    *b += 1;
+}
+
+fn main() {
+}
diff --git a/src/test/ui/borrowck/borrowck-anon-fields-variant.stderr b/src/test/ui/borrowck/borrowck-anon-fields-variant.stderr
new file mode 100644
index 0000000..2835cab
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-anon-fields-variant.stderr
@@ -0,0 +1,15 @@
+error[E0499]: cannot borrow `y.0` as mutable more than once at a time
+  --> $DIR/borrowck-anon-fields-variant.rs:34:14
+   |
+LL |       Foo::Y(ref mut a, _) => a,
+   |              --------- first mutable borrow occurs here
+...
+LL |       Foo::Y(ref mut b, _) => b,
+   |              ^^^^^^^^^ second mutable borrow occurs here
+...
+LL | }
+   | - first borrow ends here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/borrowck/borrowck-argument.nll.stderr b/src/test/ui/borrowck/borrowck-argument.nll.stderr
new file mode 100644
index 0000000..cf15833
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-argument.nll.stderr
@@ -0,0 +1,35 @@
+error[E0596]: cannot borrow `arg` as mutable, as it is not declared as mutable
+  --> $DIR/borrowck-argument.rs:10:5
+   |
+LL | fn func(arg: S) {
+   |         --- help: consider changing this to be mutable: `mut arg`
+LL |     arg.mutate();
+   |     ^^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow `arg` as mutable, as it is not declared as mutable
+  --> $DIR/borrowck-argument.rs:15:9
+   |
+LL |     fn method(&self, arg: S) {
+   |                      --- help: consider changing this to be mutable: `mut arg`
+LL |         arg.mutate();
+   |         ^^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow `arg` as mutable, as it is not declared as mutable
+  --> $DIR/borrowck-argument.rs:21:9
+   |
+LL |     fn default(&self, arg: S) {
+   |                       --- help: consider changing this to be mutable: `mut arg`
+LL |         arg.mutate();
+   |         ^^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow `arg` as mutable, as it is not declared as mutable
+  --> $DIR/borrowck-argument.rs:32:17
+   |
+LL |     (|arg: S| { arg.mutate() })(s);
+   |       ---       ^^^ cannot borrow as mutable
+   |       |
+   |       help: consider changing this to be mutable: `mut arg`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/borrowck/borrowck-argument.rs b/src/test/ui/borrowck/borrowck-argument.rs
new file mode 100644
index 0000000..e1f1ade
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-argument.rs
@@ -0,0 +1,33 @@
+#[derive(Copy, Clone)]
+struct S;
+
+impl S {
+    fn mutate(&mut self) {
+    }
+}
+
+fn func(arg: S) {
+    arg.mutate(); //~ ERROR: cannot borrow immutable argument
+}
+
+impl S {
+    fn method(&self, arg: S) {
+        arg.mutate(); //~ ERROR: cannot borrow immutable argument
+    }
+}
+
+trait T {
+    fn default(&self, arg: S) {
+        arg.mutate(); //~ ERROR: cannot borrow immutable argument
+    }
+}
+
+impl T for S {}
+
+fn main() {
+    let s = S;
+    func(s);
+    s.method(s);
+    s.default(s);
+    (|arg: S| { arg.mutate() })(s); //~ ERROR: cannot borrow immutable argument
+}
diff --git a/src/test/ui/borrowck/borrowck-argument.stderr b/src/test/ui/borrowck/borrowck-argument.stderr
new file mode 100644
index 0000000..6c9c411
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-argument.stderr
@@ -0,0 +1,35 @@
+error[E0596]: cannot borrow immutable argument `arg` as mutable
+  --> $DIR/borrowck-argument.rs:10:5
+   |
+LL | fn func(arg: S) {
+   |         --- help: make this binding mutable: `mut arg`
+LL |     arg.mutate();
+   |     ^^^ cannot borrow mutably
+
+error[E0596]: cannot borrow immutable argument `arg` as mutable
+  --> $DIR/borrowck-argument.rs:15:9
+   |
+LL |     fn method(&self, arg: S) {
+   |                      --- help: make this binding mutable: `mut arg`
+LL |         arg.mutate();
+   |         ^^^ cannot borrow mutably
+
+error[E0596]: cannot borrow immutable argument `arg` as mutable
+  --> $DIR/borrowck-argument.rs:21:9
+   |
+LL |     fn default(&self, arg: S) {
+   |                       --- help: make this binding mutable: `mut arg`
+LL |         arg.mutate();
+   |         ^^^ cannot borrow mutably
+
+error[E0596]: cannot borrow immutable argument `arg` as mutable
+  --> $DIR/borrowck-argument.rs:32:17
+   |
+LL |     (|arg: S| { arg.mutate() })(s);
+   |       ---       ^^^ cannot borrow mutably
+   |       |
+   |       help: make this binding mutable: `mut arg`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/borrowck/borrowck-asm.ast.nll.stderr b/src/test/ui/borrowck/borrowck-asm.ast.nll.stderr
new file mode 100644
index 0000000..dd6e5eb
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-asm.ast.nll.stderr
@@ -0,0 +1,81 @@
+error[E0382]: use of moved value: `x`
+  --> $DIR/borrowck-asm.rs:27:17
+   |
+LL |         let x = &mut 0isize;
+   |             - move occurs because `x` has type `&mut isize`, which does not implement the `Copy` trait
+LL |         unsafe {
+LL |             asm!("nop" : : "r"(x));
+   |                                - value moved here
+LL |         }
+LL |         let z = x;
+   |                 ^ value used here after move
+
+error[E0503]: cannot use `x` because it was mutably borrowed
+  --> $DIR/borrowck-asm.rs:35:32
+   |
+LL |         let y = &mut x;
+   |                 ------ borrow of `x` occurs here
+LL |         unsafe {
+LL |             asm!("nop" : : "r"(x));
+   |                                ^ use of borrowed `x`
+...
+LL |         let z = y;
+   |                 - borrow later used here
+
+error[E0384]: cannot assign twice to immutable variable `x`
+  --> $DIR/borrowck-asm.rs:44:31
+   |
+LL |         let x = 3;
+   |             -
+   |             |
+   |             first assignment to `x`
+   |             help: make this binding mutable: `mut x`
+LL |         unsafe {
+LL |             asm!("nop" : "=r"(x));
+   |                               ^ cannot assign twice to immutable variable
+
+error[E0384]: cannot assign twice to immutable variable `x`
+  --> $DIR/borrowck-asm.rs:60:31
+   |
+LL |         let x = 3;
+   |             -
+   |             |
+   |             first assignment to `x`
+   |             help: make this binding mutable: `mut x`
+LL |         unsafe {
+LL |             asm!("nop" : "+r"(x));
+   |                               ^ cannot assign twice to immutable variable
+
+error[E0381]: use of possibly uninitialized variable: `x`
+  --> $DIR/borrowck-asm.rs:68:32
+   |
+LL |             asm!("nop" : "=*r"(x));
+   |                                ^ use of possibly uninitialized `x`
+
+error[E0506]: cannot assign to `x` because it is borrowed
+  --> $DIR/borrowck-asm.rs:77:31
+   |
+LL |         let y = &*x;
+   |                 --- borrow of `x` occurs here
+LL |         unsafe {
+LL |             asm!("nop" : "+r"(x));
+   |                               ^ assignment to borrowed `x` occurs here
+...
+LL |         let z = y;
+   |                 - borrow later used here
+
+error[E0382]: use of moved value: `x`
+  --> $DIR/borrowck-asm.rs:86:40
+   |
+LL |         let x = &mut 2;
+   |             - move occurs because `x` has type `&mut i32`, which does not implement the `Copy` trait
+LL |         unsafe {
+LL |             asm!("nop" : : "r"(x), "r"(x) );
+   |                                -       ^ value used here after move
+   |                                |
+   |                                value moved here
+
+error: aborting due to 7 previous errors
+
+Some errors occurred: E0381, E0382, E0384, E0503, E0506.
+For more information about an error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/borrowck-asm.ast.stderr b/src/test/ui/borrowck/borrowck-asm.ast.stderr
new file mode 100644
index 0000000..8418bb7
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-asm.ast.stderr
@@ -0,0 +1,76 @@
+error[E0382]: use of moved value: `x`
+  --> $DIR/borrowck-asm.rs:27:13
+   |
+LL |             asm!("nop" : : "r"(x));
+   |                                - value moved here
+LL |         }
+LL |         let z = x;
+   |             ^ value used here after move
+   |
+   = note: move occurs because `x` has type `&mut isize`, which does not implement the `Copy` trait
+
+error[E0503]: cannot use `x` because it was mutably borrowed
+  --> $DIR/borrowck-asm.rs:35:32
+   |
+LL |         let y = &mut x;
+   |                      - borrow of `x` occurs here
+LL |         unsafe {
+LL |             asm!("nop" : : "r"(x));
+   |                                ^ use of borrowed `x`
+
+error[E0384]: cannot assign twice to immutable variable `x`
+  --> $DIR/borrowck-asm.rs:44:31
+   |
+LL |         let x = 3;
+   |             - first assignment to `x`
+LL |         unsafe {
+LL |             asm!("nop" : "=r"(x));
+   |                               ^ cannot assign twice to immutable variable
+
+error[E0506]: cannot assign to `a` because it is borrowed
+  --> $DIR/borrowck-asm.rs:50:31
+   |
+LL |         let b = &*a;
+   |                  -- borrow of `a` occurs here
+LL |         unsafe {
+LL |             asm!("nop" : "=r"(a));
+   |                               ^ assignment to borrowed `a` occurs here
+
+error[E0384]: cannot assign twice to immutable variable `x`
+  --> $DIR/borrowck-asm.rs:60:31
+   |
+LL |         let x = 3;
+   |             - first assignment to `x`
+LL |         unsafe {
+LL |             asm!("nop" : "+r"(x));
+   |                               ^ cannot assign twice to immutable variable
+
+error[E0381]: use of possibly uninitialized variable: `x`
+  --> $DIR/borrowck-asm.rs:68:32
+   |
+LL |             asm!("nop" : "=*r"(x));
+   |                                ^ use of possibly uninitialized `x`
+
+error[E0506]: cannot assign to `x` because it is borrowed
+  --> $DIR/borrowck-asm.rs:77:31
+   |
+LL |         let y = &*x;
+   |                  -- borrow of `x` occurs here
+LL |         unsafe {
+LL |             asm!("nop" : "+r"(x));
+   |                               ^ assignment to borrowed `x` occurs here
+
+error[E0382]: use of moved value: `x`
+  --> $DIR/borrowck-asm.rs:86:40
+   |
+LL |             asm!("nop" : : "r"(x), "r"(x) );
+   |                                -       ^ value used here after move
+   |                                |
+   |                                value moved here
+   |
+   = note: move occurs because `x` has type `&mut i32`, which does not implement the `Copy` trait
+
+error: aborting due to 8 previous errors
+
+Some errors occurred: E0381, E0382, E0384, E0503, E0506.
+For more information about an error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/borrowck-asm.mir.stderr b/src/test/ui/borrowck/borrowck-asm.mir.stderr
new file mode 100644
index 0000000..dd6e5eb
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-asm.mir.stderr
@@ -0,0 +1,81 @@
+error[E0382]: use of moved value: `x`
+  --> $DIR/borrowck-asm.rs:27:17
+   |
+LL |         let x = &mut 0isize;
+   |             - move occurs because `x` has type `&mut isize`, which does not implement the `Copy` trait
+LL |         unsafe {
+LL |             asm!("nop" : : "r"(x));
+   |                                - value moved here
+LL |         }
+LL |         let z = x;
+   |                 ^ value used here after move
+
+error[E0503]: cannot use `x` because it was mutably borrowed
+  --> $DIR/borrowck-asm.rs:35:32
+   |
+LL |         let y = &mut x;
+   |                 ------ borrow of `x` occurs here
+LL |         unsafe {
+LL |             asm!("nop" : : "r"(x));
+   |                                ^ use of borrowed `x`
+...
+LL |         let z = y;
+   |                 - borrow later used here
+
+error[E0384]: cannot assign twice to immutable variable `x`
+  --> $DIR/borrowck-asm.rs:44:31
+   |
+LL |         let x = 3;
+   |             -
+   |             |
+   |             first assignment to `x`
+   |             help: make this binding mutable: `mut x`
+LL |         unsafe {
+LL |             asm!("nop" : "=r"(x));
+   |                               ^ cannot assign twice to immutable variable
+
+error[E0384]: cannot assign twice to immutable variable `x`
+  --> $DIR/borrowck-asm.rs:60:31
+   |
+LL |         let x = 3;
+   |             -
+   |             |
+   |             first assignment to `x`
+   |             help: make this binding mutable: `mut x`
+LL |         unsafe {
+LL |             asm!("nop" : "+r"(x));
+   |                               ^ cannot assign twice to immutable variable
+
+error[E0381]: use of possibly uninitialized variable: `x`
+  --> $DIR/borrowck-asm.rs:68:32
+   |
+LL |             asm!("nop" : "=*r"(x));
+   |                                ^ use of possibly uninitialized `x`
+
+error[E0506]: cannot assign to `x` because it is borrowed
+  --> $DIR/borrowck-asm.rs:77:31
+   |
+LL |         let y = &*x;
+   |                 --- borrow of `x` occurs here
+LL |         unsafe {
+LL |             asm!("nop" : "+r"(x));
+   |                               ^ assignment to borrowed `x` occurs here
+...
+LL |         let z = y;
+   |                 - borrow later used here
+
+error[E0382]: use of moved value: `x`
+  --> $DIR/borrowck-asm.rs:86:40
+   |
+LL |         let x = &mut 2;
+   |             - move occurs because `x` has type `&mut i32`, which does not implement the `Copy` trait
+LL |         unsafe {
+LL |             asm!("nop" : : "r"(x), "r"(x) );
+   |                                -       ^ value used here after move
+   |                                |
+   |                                value moved here
+
+error: aborting due to 7 previous errors
+
+Some errors occurred: E0381, E0382, E0384, E0503, E0506.
+For more information about an error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/borrowck-asm.rs b/src/test/ui/borrowck/borrowck-asm.rs
new file mode 100644
index 0000000..560c87c
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-asm.rs
@@ -0,0 +1,92 @@
+// ignore-s390x
+// ignore-emscripten
+// ignore-powerpc
+// ignore-powerpc64
+// ignore-powerpc64le
+// ignore-sparc
+// ignore-sparc64
+
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+#![feature(asm)]
+
+#[cfg(any(target_arch = "x86",
+            target_arch = "x86_64",
+            target_arch = "arm",
+            target_arch = "aarch64",
+            target_arch = "mips",
+            target_arch = "mips64"))]
+mod test_cases {
+    fn is_move() {
+        let y: &mut isize;
+        let x = &mut 0isize;
+        unsafe {
+            asm!("nop" : : "r"(x));
+        }
+        let z = x;  //[ast]~ ERROR use of moved value: `x`
+                    //[mir]~^ ERROR use of moved value: `x`
+    }
+
+    fn in_is_read() {
+        let mut x = 3;
+        let y = &mut x;
+        unsafe {
+            asm!("nop" : : "r"(x)); //[ast]~ ERROR cannot use
+                                    //[mir]~^ ERROR cannot use
+        }
+        let z = y;
+    }
+
+    fn out_is_assign() {
+        let x = 3;
+        unsafe {
+            asm!("nop" : "=r"(x));  //[ast]~ ERROR cannot assign twice
+                                    //[mir]~^ ERROR cannot assign twice
+        }
+        let mut a = &mut 3;
+        let b = &*a;
+        unsafe {
+            asm!("nop" : "=r"(a));  //[ast]~ ERROR cannot assign to `a` because it is borrowed
+                                    // No MIR error, this is a shallow write.
+        }
+        let c = b;
+        let d = *a;
+    }
+
+    fn rw_is_assign() {
+        let x = 3;
+        unsafe {
+            asm!("nop" : "+r"(x));  //[ast]~ ERROR cannot assign twice
+                                    //[mir]~^ ERROR cannot assign twice
+        }
+    }
+
+    fn indirect_is_not_init() {
+        let x: i32;
+        unsafe {
+            asm!("nop" : "=*r"(x)); //[ast]~ ERROR use of possibly uninitialized variable
+                                    //[mir]~^ ERROR use of possibly uninitialized variable
+        }
+    }
+
+    fn rw_is_read() {
+        let mut x = &mut 3;
+        let y = &*x;
+        unsafe {
+            asm!("nop" : "+r"(x));  //[ast]~ ERROR cannot assign to `x` because it is borrowed
+                                    //[mir]~^ ERROR cannot assign to `x` because it is borrowed
+        }
+        let z = y;
+    }
+
+    fn two_moves() {
+        let x = &mut 2;
+        unsafe {
+            asm!("nop" : : "r"(x), "r"(x) );    //[ast]~ ERROR use of moved value
+                                                //[mir]~^ ERROR use of moved value
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/borrowck-assign-comp-idx.nll.stderr b/src/test/ui/borrowck/borrowck-assign-comp-idx.nll.stderr
new file mode 100644
index 0000000..93f1d8c
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-assign-comp-idx.nll.stderr
@@ -0,0 +1,27 @@
+error[E0502]: cannot borrow `p` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-assign-comp-idx.rs:12:5
+   |
+LL |     let q: &isize = &p[0];
+   |                      - immutable borrow occurs here
+LL | 
+LL |     p[0] = 5;
+   |     ^ mutable borrow occurs here
+LL | 
+LL |     println!("{}", *q);
+   |                    -- immutable borrow later used here
+
+error[E0502]: cannot borrow `p` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-assign-comp-idx.rs:27:9
+   |
+LL |     borrow(
+   |     ------ immutable borrow later used by call
+LL |         &p,
+   |         -- immutable borrow occurs here
+LL |         || p[0] = 5);
+   |         ^^ - second borrow occurs due to use of `p` in closure
+   |         |
+   |         mutable borrow occurs here
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/borrowck/borrowck-assign-comp-idx.rs b/src/test/ui/borrowck/borrowck-assign-comp-idx.rs
new file mode 100644
index 0000000..f4dffeb
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-assign-comp-idx.rs
@@ -0,0 +1,39 @@
+struct Point {
+    x: isize,
+    y: isize,
+}
+
+fn a() {
+    let mut p = vec![1];
+
+    // Create an immutable pointer into p's contents:
+    let q: &isize = &p[0];
+
+    p[0] = 5; //~ ERROR cannot borrow
+
+    println!("{}", *q);
+}
+
+fn borrow<F>(_x: &[isize], _f: F) where F: FnOnce() {}
+
+fn b() {
+    // here we alias the mutable vector into an imm slice and try to
+    // modify the original:
+
+    let mut p = vec![1];
+
+    borrow(
+        &p,
+        || p[0] = 5); //~ ERROR cannot borrow `p` as mutable
+}
+
+fn c() {
+    // Legal because the scope of the borrow does not include the
+    // modification:
+    let mut p = vec![1];
+    borrow(&p, ||{});
+    p[0] = 5;
+}
+
+fn main() {
+}
diff --git a/src/test/ui/borrowck/borrowck-assign-comp-idx.stderr b/src/test/ui/borrowck/borrowck-assign-comp-idx.stderr
new file mode 100644
index 0000000..0d092e6
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-assign-comp-idx.stderr
@@ -0,0 +1,26 @@
+error[E0502]: cannot borrow `p` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-assign-comp-idx.rs:12:5
+   |
+LL |     let q: &isize = &p[0];
+   |                      - immutable borrow occurs here
+LL | 
+LL |     p[0] = 5;
+   |     ^ mutable borrow occurs here
+...
+LL | }
+   | - immutable borrow ends here
+
+error[E0502]: cannot borrow `p` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-assign-comp-idx.rs:27:9
+   |
+LL |         &p,
+   |          - immutable borrow occurs here
+LL |         || p[0] = 5);
+   |         ^^ -       - immutable borrow ends here
+   |         |  |
+   |         |  borrow occurs due to use of `p` in closure
+   |         mutable borrow occurs here
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/borrowck/borrowck-assign-comp.ast.nll.stderr b/src/test/ui/borrowck/borrowck-assign-comp.ast.nll.stderr
new file mode 100644
index 0000000..53af41c
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-assign-comp.ast.nll.stderr
@@ -0,0 +1,37 @@
+error[E0506]: cannot assign to `p.x` because it is borrowed
+  --> $DIR/borrowck-assign-comp.rs:13:5
+   |
+LL |     let q = &p;
+   |             -- borrow of `p.x` occurs here
+...
+LL |     p.x = 5;
+   |     ^^^^^^^ assignment to borrowed `p.x` occurs here
+LL |
+LL |     q.x;
+   |     --- borrow later used here
+
+error[E0506]: cannot assign to `p` because it is borrowed
+  --> $DIR/borrowck-assign-comp.rs:24:5
+   |
+LL |     let q = &p.y;
+   |             ---- borrow of `p` occurs here
+LL |     p = Point {x: 5, y: 7};
+   |     ^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `p` occurs here
+...
+LL |     *q; // stretch loan
+   |     -- borrow later used here
+
+error[E0506]: cannot assign to `p.y` because it is borrowed
+  --> $DIR/borrowck-assign-comp.rs:36:5
+   |
+LL |     let q = &p.y;
+   |             ---- borrow of `p.y` occurs here
+LL |     p.y = 5;
+   |     ^^^^^^^ assignment to borrowed `p.y` occurs here
+LL |
+LL |     *q;
+   |     -- borrow later used here
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/borrowck/borrowck-assign-comp.ast.stderr b/src/test/ui/borrowck/borrowck-assign-comp.ast.stderr
new file mode 100644
index 0000000..4adb19c
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-assign-comp.ast.stderr
@@ -0,0 +1,28 @@
+error[E0506]: cannot assign to `p.x` because it is borrowed
+  --> $DIR/borrowck-assign-comp.rs:13:5
+   |
+LL |     let q = &p;
+   |              - borrow of `p.x` occurs here
+...
+LL |     p.x = 5;
+   |     ^^^^^^^ assignment to borrowed `p.x` occurs here
+
+error[E0506]: cannot assign to `p` because it is borrowed
+  --> $DIR/borrowck-assign-comp.rs:24:5
+   |
+LL |     let q = &p.y;
+   |              --- borrow of `p` occurs here
+LL |     p = Point {x: 5, y: 7};
+   |     ^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `p` occurs here
+
+error[E0506]: cannot assign to `p.y` because it is borrowed
+  --> $DIR/borrowck-assign-comp.rs:36:5
+   |
+LL |     let q = &p.y;
+   |              --- borrow of `p.y` occurs here
+LL |     p.y = 5;
+   |     ^^^^^^^ assignment to borrowed `p.y` occurs here
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/borrowck/borrowck-assign-comp.mir.stderr b/src/test/ui/borrowck/borrowck-assign-comp.mir.stderr
new file mode 100644
index 0000000..53af41c
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-assign-comp.mir.stderr
@@ -0,0 +1,37 @@
+error[E0506]: cannot assign to `p.x` because it is borrowed
+  --> $DIR/borrowck-assign-comp.rs:13:5
+   |
+LL |     let q = &p;
+   |             -- borrow of `p.x` occurs here
+...
+LL |     p.x = 5;
+   |     ^^^^^^^ assignment to borrowed `p.x` occurs here
+LL |
+LL |     q.x;
+   |     --- borrow later used here
+
+error[E0506]: cannot assign to `p` because it is borrowed
+  --> $DIR/borrowck-assign-comp.rs:24:5
+   |
+LL |     let q = &p.y;
+   |             ---- borrow of `p` occurs here
+LL |     p = Point {x: 5, y: 7};
+   |     ^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `p` occurs here
+...
+LL |     *q; // stretch loan
+   |     -- borrow later used here
+
+error[E0506]: cannot assign to `p.y` because it is borrowed
+  --> $DIR/borrowck-assign-comp.rs:36:5
+   |
+LL |     let q = &p.y;
+   |             ---- borrow of `p.y` occurs here
+LL |     p.y = 5;
+   |     ^^^^^^^ assignment to borrowed `p.y` occurs here
+LL |
+LL |     *q;
+   |     -- borrow later used here
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/borrowck/borrowck-assign-comp.rs b/src/test/ui/borrowck/borrowck-assign-comp.rs
new file mode 100644
index 0000000..0cacc38
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-assign-comp.rs
@@ -0,0 +1,42 @@
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+struct Point { x: isize, y: isize }
+
+fn a() {
+    let mut p = Point {x: 3, y: 4};
+    let q = &p;
+
+    // This assignment is illegal because the field x is not
+    // inherently mutable; since `p` was made immutable, `p.x` is now
+    // immutable.  Otherwise the type of &_q.x (&isize) would be wrong.
+    p.x = 5; //[ast]~ ERROR cannot assign to `p.x`
+             //[mir]~^ ERROR cannot assign to `p.x` because it is borrowed
+    q.x;
+}
+
+fn c() {
+    // this is sort of the opposite.  We take a loan to the interior of `p`
+    // and then try to overwrite `p` as a whole.
+
+    let mut p = Point {x: 3, y: 4};
+    let q = &p.y;
+    p = Point {x: 5, y: 7};//[ast]~ ERROR cannot assign to `p`
+                           //[mir]~^ ERROR cannot assign to `p` because it is borrowed
+    p.x; // silence warning
+    *q; // stretch loan
+}
+
+fn d() {
+    // just for completeness's sake, the easy case, where we take the
+    // address of a subcomponent and then modify that subcomponent:
+
+    let mut p = Point {x: 3, y: 4};
+    let q = &p.y;
+    p.y = 5; //[ast]~ ERROR cannot assign to `p.y`
+             //[mir]~^ ERROR cannot assign to `p.y` because it is borrowed
+    *q;
+}
+
+fn main() {
+}
diff --git a/src/test/ui/borrowck/borrowck-assign-to-andmut-in-aliasable-loc.nll.stderr b/src/test/ui/borrowck/borrowck-assign-to-andmut-in-aliasable-loc.nll.stderr
new file mode 100644
index 0000000..d8ccf36
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-assign-to-andmut-in-aliasable-loc.nll.stderr
@@ -0,0 +1,19 @@
+error[E0594]: cannot assign to `*s.pointer` which is behind a `&` reference
+  --> $DIR/borrowck-assign-to-andmut-in-aliasable-loc.rs:9:5
+   |
+LL | fn a(s: &S) {
+   |         -- help: consider changing this to be a mutable reference: `&mut S<'_>`
+LL |     *s.pointer += 1;
+   |     ^^^^^^^^^^^^^^^ `s` is a `&` reference, so the data it refers to cannot be written
+
+error[E0594]: cannot assign to `*s.pointer` which is behind a `&` reference
+  --> $DIR/borrowck-assign-to-andmut-in-aliasable-loc.rs:17:5
+   |
+LL | fn c(s: & &mut S) {
+   |         -------- help: consider changing this to be a mutable reference: `&mut &mut S<'_>`
+LL |     *s.pointer += 1;
+   |     ^^^^^^^^^^^^^^^ `s` is a `&` reference, so the data it refers to cannot be written
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/borrowck/borrowck-assign-to-andmut-in-aliasable-loc.rs b/src/test/ui/borrowck/borrowck-assign-to-andmut-in-aliasable-loc.rs
new file mode 100644
index 0000000..879c037
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-assign-to-andmut-in-aliasable-loc.rs
@@ -0,0 +1,20 @@
+// Test that assignments to an `&mut` pointer which is found in a
+// borrowed (but otherwise non-aliasable) location is illegal.
+
+struct S<'a> {
+    pointer: &'a mut isize
+}
+
+fn a(s: &S) {
+    *s.pointer += 1; //~ ERROR cannot assign
+}
+
+fn b(s: &mut S) {
+    *s.pointer += 1;
+}
+
+fn c(s: & &mut S) {
+    *s.pointer += 1; //~ ERROR cannot assign
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/borrowck-assign-to-andmut-in-aliasable-loc.stderr b/src/test/ui/borrowck/borrowck-assign-to-andmut-in-aliasable-loc.stderr
new file mode 100644
index 0000000..5ec1ff2
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-assign-to-andmut-in-aliasable-loc.stderr
@@ -0,0 +1,19 @@
+error[E0389]: cannot assign to data in a `&` reference
+  --> $DIR/borrowck-assign-to-andmut-in-aliasable-loc.rs:9:5
+   |
+LL | fn a(s: &S) {
+   |         -- use `&mut S` here to make mutable
+LL |     *s.pointer += 1;
+   |     ^^^^^^^^^^^^^^^ assignment into an immutable reference
+
+error[E0389]: cannot assign to data in a `&` reference
+  --> $DIR/borrowck-assign-to-andmut-in-aliasable-loc.rs:17:5
+   |
+LL | fn c(s: & &mut S) {
+   |         -------- use `&mut &mut S` here to make mutable
+LL |     *s.pointer += 1;
+   |     ^^^^^^^^^^^^^^^ assignment into an immutable reference
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0389`.
diff --git a/src/test/ui/borrowck/borrowck-assign-to-andmut-in-borrowed-loc.nll.stderr b/src/test/ui/borrowck/borrowck-assign-to-andmut-in-borrowed-loc.nll.stderr
new file mode 100644
index 0000000..0aacaf9
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-assign-to-andmut-in-borrowed-loc.nll.stderr
@@ -0,0 +1,24 @@
+error[E0503]: cannot use `*y.pointer` because it was mutably borrowed
+  --> $DIR/borrowck-assign-to-andmut-in-borrowed-loc.rs:18:9
+   |
+LL |         let z = copy_borrowed_ptr(&mut y);
+   |                                   ------ borrow of `y` occurs here
+LL |         *y.pointer += 1;
+   |         ^^^^^^^^^^^^^^^ use of borrowed `y`
+LL |         *z.pointer += 1;
+   |         --------------- borrow later used here
+
+error[E0506]: cannot assign to `*y.pointer` because it is borrowed
+  --> $DIR/borrowck-assign-to-andmut-in-borrowed-loc.rs:18:9
+   |
+LL |         let z = copy_borrowed_ptr(&mut y);
+   |                                   ------ borrow of `*y.pointer` occurs here
+LL |         *y.pointer += 1;
+   |         ^^^^^^^^^^^^^^^ assignment to borrowed `*y.pointer` occurs here
+LL |         *z.pointer += 1;
+   |         --------------- borrow later used here
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0503, E0506.
+For more information about an error, try `rustc --explain E0503`.
diff --git a/src/test/ui/borrowck/borrowck-assign-to-andmut-in-borrowed-loc.rs b/src/test/ui/borrowck/borrowck-assign-to-andmut-in-borrowed-loc.rs
new file mode 100644
index 0000000..98080d4
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-assign-to-andmut-in-borrowed-loc.rs
@@ -0,0 +1,21 @@
+// Test that assignments to an `&mut` pointer which is found in a
+// borrowed (but otherwise non-aliasable) location is illegal.
+
+struct S<'a> {
+    pointer: &'a mut isize
+}
+
+fn copy_borrowed_ptr<'a>(p: &'a mut S<'a>) -> S<'a> {
+    S { pointer: &mut *p.pointer }
+}
+
+fn main() {
+    let mut x = 1;
+
+    {
+        let mut y = S { pointer: &mut x };
+        let z = copy_borrowed_ptr(&mut y);
+        *y.pointer += 1; //~ ERROR cannot assign
+        *z.pointer += 1;
+    }
+}
diff --git a/src/test/ui/borrowck/borrowck-assign-to-andmut-in-borrowed-loc.stderr b/src/test/ui/borrowck/borrowck-assign-to-andmut-in-borrowed-loc.stderr
new file mode 100644
index 0000000..10d6ac5
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-assign-to-andmut-in-borrowed-loc.stderr
@@ -0,0 +1,11 @@
+error[E0506]: cannot assign to `*y.pointer` because it is borrowed
+  --> $DIR/borrowck-assign-to-andmut-in-borrowed-loc.rs:18:9
+   |
+LL |         let z = copy_borrowed_ptr(&mut y);
+   |                                        - borrow of `*y.pointer` occurs here
+LL |         *y.pointer += 1;
+   |         ^^^^^^^^^^^^^^^ assignment to borrowed `*y.pointer` occurs here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/borrowck/borrowck-assign-to-constants.ast.nll.stderr b/src/test/ui/borrowck/borrowck-assign-to-constants.ast.nll.stderr
new file mode 100644
index 0000000..626e1ef
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-assign-to-constants.ast.nll.stderr
@@ -0,0 +1,9 @@
+error[E0594]: cannot assign to immutable static item `foo`
+  --> $DIR/borrowck-assign-to-constants.rs:8:5
+   |
+LL |     foo = 6;
+   |     ^^^^^^^ cannot assign
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/borrowck/borrowck-assign-to-constants.ast.stderr b/src/test/ui/borrowck/borrowck-assign-to-constants.ast.stderr
new file mode 100644
index 0000000..e755785
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-assign-to-constants.ast.stderr
@@ -0,0 +1,9 @@
+error[E0594]: cannot assign to immutable static item
+  --> $DIR/borrowck-assign-to-constants.rs:8:5
+   |
+LL |     foo = 6;
+   |     ^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/borrowck/borrowck-assign-to-constants.mir.stderr b/src/test/ui/borrowck/borrowck-assign-to-constants.mir.stderr
new file mode 100644
index 0000000..626e1ef
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-assign-to-constants.mir.stderr
@@ -0,0 +1,9 @@
+error[E0594]: cannot assign to immutable static item `foo`
+  --> $DIR/borrowck-assign-to-constants.rs:8:5
+   |
+LL |     foo = 6;
+   |     ^^^^^^^ cannot assign
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/borrowck/borrowck-assign-to-constants.rs b/src/test/ui/borrowck/borrowck-assign-to-constants.rs
new file mode 100644
index 0000000..768b2a5
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-assign-to-constants.rs
@@ -0,0 +1,10 @@
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+static foo: isize = 5;
+
+fn main() {
+    // assigning to various global constants
+    foo = 6; //[ast]~ ERROR cannot assign to immutable static item
+             //[mir]~^ ERROR cannot assign to immutable static item `foo`
+}
diff --git a/src/test/ui/borrowck/borrowck-auto-mut-ref-to-immut-var.nll.stderr b/src/test/ui/borrowck/borrowck-auto-mut-ref-to-immut-var.nll.stderr
new file mode 100644
index 0000000..3ed76c1
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-auto-mut-ref-to-immut-var.nll.stderr
@@ -0,0 +1,11 @@
+error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
+  --> $DIR/borrowck-auto-mut-ref-to-immut-var.rs:15:5
+   |
+LL |     let x = Foo { x: 3 };
+   |         - help: consider changing this to be mutable: `mut x`
+LL |     x.printme();
+   |     ^ cannot borrow as mutable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/borrowck/borrowck-auto-mut-ref-to-immut-var.rs b/src/test/ui/borrowck/borrowck-auto-mut-ref-to-immut-var.rs
new file mode 100644
index 0000000..247e3da
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-auto-mut-ref-to-immut-var.rs
@@ -0,0 +1,16 @@
+// Tests that auto-ref can't create mutable aliases to immutable memory.
+
+struct Foo {
+    x: isize
+}
+
+impl Foo {
+    pub fn printme(&mut self) {
+        println!("{}", self.x);
+    }
+}
+
+fn main() {
+    let x = Foo { x: 3 };
+    x.printme();    //~ ERROR cannot borrow
+}
diff --git a/src/test/ui/borrowck/borrowck-auto-mut-ref-to-immut-var.stderr b/src/test/ui/borrowck/borrowck-auto-mut-ref-to-immut-var.stderr
new file mode 100644
index 0000000..759b778
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-auto-mut-ref-to-immut-var.stderr
@@ -0,0 +1,11 @@
+error[E0596]: cannot borrow immutable local variable `x` as mutable
+  --> $DIR/borrowck-auto-mut-ref-to-immut-var.rs:15:5
+   |
+LL |     let x = Foo { x: 3 };
+   |         - help: make this binding mutable: `mut x`
+LL |     x.printme();
+   |     ^ cannot borrow mutably
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/borrowck/borrowck-autoref-3261.nll.stderr b/src/test/ui/borrowck/borrowck-autoref-3261.nll.stderr
new file mode 100644
index 0000000..c2dfb68
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-autoref-3261.nll.stderr
@@ -0,0 +1,16 @@
+error[E0499]: cannot borrow `x` as mutable more than once at a time
+  --> $DIR/borrowck-autoref-3261.rs:15:9
+   |
+LL |     (&mut x).with(
+   |     -------- ---- first borrow later used by call
+   |     |
+   |     first mutable borrow occurs here
+LL |         |opt| {
+   |         ^^^^^ second mutable borrow occurs here
+...
+LL |                     x = X(Either::Left((0, 0)));
+   |                     - second borrow occurs due to use of `x` in closure
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/borrowck/borrowck-autoref-3261.rs b/src/test/ui/borrowck/borrowck-autoref-3261.rs
new file mode 100644
index 0000000..2ff3d5b
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-autoref-3261.rs
@@ -0,0 +1,24 @@
+enum Either<T, U> { Left(T), Right(U) }
+
+struct X(Either<(usize,usize), fn()>);
+
+impl X {
+    pub fn with<F>(&self, blk: F) where F: FnOnce(&Either<(usize, usize), fn()>) {
+        let X(ref e) = *self;
+        blk(e)
+    }
+}
+
+fn main() {
+    let mut x = X(Either::Right(main as fn()));
+    (&mut x).with(
+        |opt| { //~ ERROR cannot borrow `x` as mutable more than once at a time
+            match opt {
+                &Either::Right(ref f) => {
+                    x = X(Either::Left((0, 0)));
+                    (*f)()
+                },
+                _ => panic!()
+            }
+        })
+}
diff --git a/src/test/ui/borrowck/borrowck-autoref-3261.stderr b/src/test/ui/borrowck/borrowck-autoref-3261.stderr
new file mode 100644
index 0000000..280704a
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-autoref-3261.stderr
@@ -0,0 +1,17 @@
+error[E0499]: cannot borrow `x` as mutable more than once at a time
+  --> $DIR/borrowck-autoref-3261.rs:15:9
+   |
+LL |     (&mut x).with(
+   |           - first mutable borrow occurs here
+LL |         |opt| {
+   |         ^^^^^ second mutable borrow occurs here
+...
+LL |                     x = X(Either::Left((0, 0)));
+   |                     - borrow occurs due to use of `x` in closure
+...
+LL |         })
+   |          - first borrow ends here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/borrowck/borrowck-bad-nested-calls-free.nll.stderr b/src/test/ui/borrowck/borrowck-bad-nested-calls-free.nll.stderr
new file mode 100644
index 0000000..e273a77
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-bad-nested-calls-free.nll.stderr
@@ -0,0 +1,23 @@
+error[E0502]: cannot borrow `a` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-bad-nested-calls-free.rs:25:17
+   |
+LL |     add(
+   |     --- immutable borrow later used by call
+LL |         &*a,
+   |         --- immutable borrow occurs here
+LL |         rewrite(&mut a));
+   |                 ^^^^^^ mutable borrow occurs here
+
+error[E0502]: cannot borrow `a` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-bad-nested-calls-free.rs:32:17
+   |
+LL |     add(
+   |     --- immutable borrow later used by call
+LL |         &*a,
+   |         --- immutable borrow occurs here
+LL |         rewrite(&mut a));
+   |                 ^^^^^^ mutable borrow occurs here
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/borrowck/borrowck-bad-nested-calls-free.rs b/src/test/ui/borrowck/borrowck-bad-nested-calls-free.rs
new file mode 100644
index 0000000..3abc561
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-bad-nested-calls-free.rs
@@ -0,0 +1,35 @@
+// Test that we detect nested calls that could free pointers evaluated
+// for earlier arguments.
+
+#![feature(box_syntax)]
+
+fn rewrite(v: &mut Box<usize>) -> usize {
+    *v = box 22;
+    **v
+}
+
+fn add(v: &usize, w: usize) -> usize {
+    *v + w
+}
+
+fn implicit() {
+    let mut a: Box<_> = box 1;
+
+    // Note the danger here:
+    //
+    //    the pointer for the first argument has already been
+    //    evaluated, but it gets freed when evaluating the second
+    //    argument!
+    add(
+        &*a,
+        rewrite(&mut a)); //~ ERROR cannot borrow
+}
+
+fn explicit() {
+    let mut a: Box<_> = box 1;
+    add(
+        &*a,
+        rewrite(&mut a)); //~ ERROR cannot borrow
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/borrowck-bad-nested-calls-free.stderr b/src/test/ui/borrowck/borrowck-bad-nested-calls-free.stderr
new file mode 100644
index 0000000..06ec2bd
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-bad-nested-calls-free.stderr
@@ -0,0 +1,23 @@
+error[E0502]: cannot borrow `a` as mutable because `*a` is also borrowed as immutable
+  --> $DIR/borrowck-bad-nested-calls-free.rs:25:22
+   |
+LL |         &*a,
+   |          -- immutable borrow occurs here
+LL |         rewrite(&mut a));
+   |                      ^ - immutable borrow ends here
+   |                      |
+   |                      mutable borrow occurs here
+
+error[E0502]: cannot borrow `a` as mutable because `*a` is also borrowed as immutable
+  --> $DIR/borrowck-bad-nested-calls-free.rs:32:22
+   |
+LL |         &*a,
+   |          -- immutable borrow occurs here
+LL |         rewrite(&mut a));
+   |                      ^ - immutable borrow ends here
+   |                      |
+   |                      mutable borrow occurs here
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/borrowck/borrowck-bad-nested-calls-move.nll.stderr b/src/test/ui/borrowck/borrowck-bad-nested-calls-move.nll.stderr
new file mode 100644
index 0000000..371bcf2
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-bad-nested-calls-move.nll.stderr
@@ -0,0 +1,23 @@
+error[E0505]: cannot move out of `a` because it is borrowed
+  --> $DIR/borrowck-bad-nested-calls-move.rs:25:9
+   |
+LL |     add(
+   |     --- borrow later used by call
+LL |         &*a,
+   |         --- borrow of `*a` occurs here
+LL |         a);
+   |         ^ move out of `a` occurs here
+
+error[E0505]: cannot move out of `a` because it is borrowed
+  --> $DIR/borrowck-bad-nested-calls-move.rs:32:9
+   |
+LL |     add(
+   |     --- borrow later used by call
+LL |         &*a,
+   |         --- borrow of `*a` occurs here
+LL |         a);
+   |         ^ move out of `a` occurs here
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0505`.
diff --git a/src/test/ui/borrowck/borrowck-bad-nested-calls-move.rs b/src/test/ui/borrowck/borrowck-bad-nested-calls-move.rs
new file mode 100644
index 0000000..fd8df78
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-bad-nested-calls-move.rs
@@ -0,0 +1,35 @@
+// Test that we detect nested calls that could free pointers evaluated
+// for earlier arguments.
+
+#![feature(box_syntax)]
+
+fn rewrite(v: &mut Box<usize>) -> usize {
+    *v = box 22;
+    **v
+}
+
+fn add(v: &usize, w: Box<usize>) -> usize {
+    *v + *w
+}
+
+fn implicit() {
+    let mut a: Box<_> = box 1;
+
+    // Note the danger here:
+    //
+    //    the pointer for the first argument has already been
+    //    evaluated, but it gets moved when evaluating the second
+    //    argument!
+    add(
+        &*a,
+        a); //~ ERROR cannot move
+}
+
+fn explicit() {
+    let mut a: Box<_> = box 1;
+    add(
+        &*a,
+        a); //~ ERROR cannot move
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/borrowck-bad-nested-calls-move.stderr b/src/test/ui/borrowck/borrowck-bad-nested-calls-move.stderr
new file mode 100644
index 0000000..3b34a61
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-bad-nested-calls-move.stderr
@@ -0,0 +1,19 @@
+error[E0505]: cannot move out of `a` because it is borrowed
+  --> $DIR/borrowck-bad-nested-calls-move.rs:25:9
+   |
+LL |         &*a,
+   |          -- borrow of `*a` occurs here
+LL |         a);
+   |         ^ move out of `a` occurs here
+
+error[E0505]: cannot move out of `a` because it is borrowed
+  --> $DIR/borrowck-bad-nested-calls-move.rs:32:9
+   |
+LL |         &*a,
+   |          -- borrow of `*a` occurs here
+LL |         a);
+   |         ^ move out of `a` occurs here
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0505`.
diff --git a/src/test/ui/borrowck/borrowck-block-unint.nll.stderr b/src/test/ui/borrowck/borrowck-block-unint.nll.stderr
new file mode 100644
index 0000000..d2a4996
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-block-unint.nll.stderr
@@ -0,0 +1,11 @@
+error[E0381]: borrow of possibly uninitialized variable: `x`
+  --> $DIR/borrowck-block-unint.rs:4:11
+   |
+LL |     force(|| {
+   |           ^^ use of possibly uninitialized `x`
+LL |         println!("{}", x);
+   |                        - borrow occurs due to use in closure
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/borrowck-block-unint.rs b/src/test/ui/borrowck/borrowck-block-unint.rs
new file mode 100644
index 0000000..3c6e9cb
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-block-unint.rs
@@ -0,0 +1,7 @@
+fn force<F>(f: F) where F: FnOnce() { f(); }
+fn main() {
+    let x: isize;
+    force(|| {  //~ ERROR capture of possibly uninitialized variable: `x`
+        println!("{}", x);
+    });
+}
diff --git a/src/test/ui/borrowck/borrowck-block-unint.stderr b/src/test/ui/borrowck/borrowck-block-unint.stderr
new file mode 100644
index 0000000..ab55d79
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-block-unint.stderr
@@ -0,0 +1,9 @@
+error[E0381]: capture of possibly uninitialized variable: `x`
+  --> $DIR/borrowck-block-unint.rs:4:11
+   |
+LL |     force(|| {
+   |           ^^ use of possibly uninitialized `x`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/borrowck-borrow-from-owned-ptr.nll.stderr b/src/test/ui/borrowck/borrowck-borrow-from-owned-ptr.nll.stderr
new file mode 100644
index 0000000..ad6bd7d
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-borrow-from-owned-ptr.nll.stderr
@@ -0,0 +1,116 @@
+error[E0499]: cannot borrow `foo.bar1` as mutable more than once at a time
+  --> $DIR/borrowck-borrow-from-owned-ptr.rs:18:17
+   |
+LL |     let bar1 = &mut foo.bar1;
+   |                ------------- first mutable borrow occurs here
+LL |     let _bar2 = &mut foo.bar1;
+   |                 ^^^^^^^^^^^^^ second mutable borrow occurs here
+LL |     *bar1;
+   |     ----- first borrow later used here
+
+error[E0502]: cannot borrow `foo.bar1` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-borrow-from-owned-ptr.rs:25:17
+   |
+LL |     let bar1 = &mut foo.bar1;
+   |                ------------- mutable borrow occurs here
+LL |     let _bar2 = &foo.bar1;
+   |                 ^^^^^^^^^ immutable borrow occurs here
+LL |     *bar1;
+   |     ----- mutable borrow later used here
+
+error[E0502]: cannot borrow `foo.bar1` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-borrow-from-owned-ptr.rs:32:17
+   |
+LL |     let bar1 = &foo.bar1;
+   |                --------- immutable borrow occurs here
+LL |     let _bar2 = &mut foo.bar1;
+   |                 ^^^^^^^^^^^^^ mutable borrow occurs here
+LL |     *bar1;
+   |     ----- immutable borrow later used here
+
+error[E0499]: cannot borrow `foo.bar1` as mutable more than once at a time
+  --> $DIR/borrowck-borrow-from-owned-ptr.rs:62:21
+   |
+LL |     let bar1 = &mut foo.bar1;
+   |                ------------- first mutable borrow occurs here
+LL |     match *foo {
+LL |         Foo { bar1: ref mut _bar1, bar2: _ } => {}
+   |                     ^^^^^^^^^^^^^ second mutable borrow occurs here
+...
+LL |     *bar1;
+   |     ----- first borrow later used here
+
+error[E0502]: cannot borrow `foo.bar1` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-borrow-from-owned-ptr.rs:71:17
+   |
+LL |     let bar1 = &mut foo.bar1.int1;
+   |                ------------------ mutable borrow occurs here
+LL |     let _foo1 = &foo.bar1;
+   |                 ^^^^^^^^^ immutable borrow occurs here
+LL |     let _foo2 = &*foo;
+LL |     *bar1;
+   |     ----- mutable borrow later used here
+
+error[E0502]: cannot borrow `*foo` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-borrow-from-owned-ptr.rs:72:17
+   |
+LL |     let bar1 = &mut foo.bar1.int1;
+   |                ------------------ mutable borrow occurs here
+LL |     let _foo1 = &foo.bar1;
+LL |     let _foo2 = &*foo;
+   |                 ^^^^^ immutable borrow occurs here
+LL |     *bar1;
+   |     ----- mutable borrow later used here
+
+error[E0499]: cannot borrow `foo.bar1` as mutable more than once at a time
+  --> $DIR/borrowck-borrow-from-owned-ptr.rs:79:17
+   |
+LL |     let bar1 = &mut foo.bar1.int1;
+   |                ------------------ first mutable borrow occurs here
+LL |     let _foo1 = &mut foo.bar1;
+   |                 ^^^^^^^^^^^^^ second mutable borrow occurs here
+LL |     *bar1;
+   |     ----- first borrow later used here
+
+error[E0499]: cannot borrow `*foo` as mutable more than once at a time
+  --> $DIR/borrowck-borrow-from-owned-ptr.rs:86:17
+   |
+LL |     let bar1 = &mut foo.bar1.int1;
+   |                ------------------ first mutable borrow occurs here
+LL |     let _foo2 = &mut *foo;
+   |                 ^^^^^^^^^ second mutable borrow occurs here
+LL |     *bar1;
+   |     ----- first borrow later used here
+
+error[E0502]: cannot borrow `foo.bar1` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-borrow-from-owned-ptr.rs:93:17
+   |
+LL |     let bar1 = &foo.bar1.int1;
+   |                -------------- immutable borrow occurs here
+LL |     let _foo1 = &mut foo.bar1;
+   |                 ^^^^^^^^^^^^^ mutable borrow occurs here
+LL |     *bar1;
+   |     ----- immutable borrow later used here
+
+error[E0502]: cannot borrow `*foo` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-borrow-from-owned-ptr.rs:100:17
+   |
+LL |     let bar1 = &foo.bar1.int1;
+   |                -------------- immutable borrow occurs here
+LL |     let _foo2 = &mut *foo;
+   |                 ^^^^^^^^^ mutable borrow occurs here
+LL |     *bar1;
+   |     ----- immutable borrow later used here
+
+error[E0596]: cannot borrow `foo.bar1` as mutable, as `foo` is not declared as mutable
+  --> $DIR/borrowck-borrow-from-owned-ptr.rs:121:16
+   |
+LL |     let foo = make_foo();
+   |         --- help: consider changing this to be mutable: `mut foo`
+LL |     let bar1 = &mut foo.bar1;
+   |                ^^^^^^^^^^^^^ cannot borrow as mutable
+
+error: aborting due to 11 previous errors
+
+Some errors occurred: E0499, E0502, E0596.
+For more information about an error, try `rustc --explain E0499`.
diff --git a/src/test/ui/borrowck/borrowck-borrow-from-owned-ptr.rs b/src/test/ui/borrowck/borrowck-borrow-from-owned-ptr.rs
new file mode 100644
index 0000000..1435837
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-borrow-from-owned-ptr.rs
@@ -0,0 +1,133 @@
+#[derive(Copy, Clone)]
+struct Foo {
+  bar1: Bar,
+  bar2: Bar
+}
+
+#[derive(Copy, Clone)]
+struct Bar {
+  int1: isize,
+  int2: isize,
+}
+
+fn make_foo() -> Box<Foo> { panic!() }
+
+fn borrow_same_field_twice_mut_mut() {
+    let mut foo = make_foo();
+    let bar1 = &mut foo.bar1;
+    let _bar2 = &mut foo.bar1;  //~ ERROR cannot borrow
+    *bar1;
+}
+
+fn borrow_same_field_twice_mut_imm() {
+    let mut foo = make_foo();
+    let bar1 = &mut foo.bar1;
+    let _bar2 = &foo.bar1;  //~ ERROR cannot borrow
+    *bar1;
+}
+
+fn borrow_same_field_twice_imm_mut() {
+    let mut foo = make_foo();
+    let bar1 = &foo.bar1;
+    let _bar2 = &mut foo.bar1;  //~ ERROR cannot borrow
+    *bar1;
+}
+
+fn borrow_same_field_twice_imm_imm() {
+    let mut foo = make_foo();
+    let bar1 = &foo.bar1;
+    let _bar2 = &foo.bar1;
+    *bar1;
+}
+
+fn borrow_both_fields_mut() {
+    let mut foo = make_foo();
+    let bar1 = &mut foo.bar1;
+    let _bar2 = &mut foo.bar2; //~ ERROR cannot borrow
+    *bar1;
+}
+
+fn borrow_both_mut_pattern() {
+    let mut foo = make_foo();
+    match *foo {
+        Foo { bar1: ref mut _bar1, bar2: ref mut _bar2 } => {}
+        //~^ ERROR cannot borrow
+    }
+}
+
+fn borrow_var_and_pattern() {
+    let mut foo = make_foo();
+    let bar1 = &mut foo.bar1;
+    match *foo {
+        Foo { bar1: ref mut _bar1, bar2: _ } => {}
+        //~^ ERROR cannot borrow
+    }
+    *bar1;
+}
+
+fn borrow_mut_and_base_imm() {
+    let mut foo = make_foo();
+    let bar1 = &mut foo.bar1.int1;
+    let _foo1 = &foo.bar1; //~ ERROR cannot borrow
+    let _foo2 = &*foo; //~ ERROR cannot borrow
+    *bar1;
+}
+
+fn borrow_mut_and_base_mut() {
+    let mut foo = make_foo();
+    let bar1 = &mut foo.bar1.int1;
+    let _foo1 = &mut foo.bar1; //~ ERROR cannot borrow
+    *bar1;
+}
+
+fn borrow_mut_and_base_mut2() {
+    let mut foo = make_foo();
+    let bar1 = &mut foo.bar1.int1;
+    let _foo2 = &mut *foo; //~ ERROR cannot borrow
+    *bar1;
+}
+
+fn borrow_imm_and_base_mut() {
+    let mut foo = make_foo();
+    let bar1 = &foo.bar1.int1;
+    let _foo1 = &mut foo.bar1; //~ ERROR cannot borrow
+    *bar1;
+}
+
+fn borrow_imm_and_base_mut2() {
+    let mut foo = make_foo();
+    let bar1 = &foo.bar1.int1;
+    let _foo2 = &mut *foo; //~ ERROR cannot borrow
+    *bar1;
+}
+
+fn borrow_imm_and_base_imm() {
+    let mut foo = make_foo();
+    let bar1 = &foo.bar1.int1;
+    let _foo1 = &foo.bar1;
+    let _foo2 = &*foo;
+    *bar1;
+}
+
+fn borrow_mut_and_imm() {
+    let mut foo = make_foo();
+    let bar1 = &mut foo.bar1;
+    let _foo1 = &foo.bar2; //~ ERROR cannot borrow
+    *bar1;
+}
+
+fn borrow_mut_from_imm() {
+    let foo = make_foo();
+    let bar1 = &mut foo.bar1; //~ ERROR cannot borrow
+    *bar1;
+}
+
+fn borrow_long_path_both_mut() {
+    let mut foo = make_foo();
+    let bar1 = &mut foo.bar1.int1;
+    let foo1 = &mut foo.bar2.int2; //~ ERROR cannot borrow
+    *bar1;
+    *foo1;
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/borrowck-borrow-from-owned-ptr.stderr b/src/test/ui/borrowck/borrowck-borrow-from-owned-ptr.stderr
new file mode 100644
index 0000000..a4fb28d0
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-borrow-from-owned-ptr.stderr
@@ -0,0 +1,168 @@
+error[E0499]: cannot borrow `foo.bar1` as mutable more than once at a time
+  --> $DIR/borrowck-borrow-from-owned-ptr.rs:18:22
+   |
+LL |     let bar1 = &mut foo.bar1;
+   |                     -------- first mutable borrow occurs here
+LL |     let _bar2 = &mut foo.bar1;
+   |                      ^^^^^^^^ second mutable borrow occurs here
+LL |     *bar1;
+LL | }
+   | - first borrow ends here
+
+error[E0502]: cannot borrow `foo.bar1` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-borrow-from-owned-ptr.rs:25:18
+   |
+LL |     let bar1 = &mut foo.bar1;
+   |                     -------- mutable borrow occurs here
+LL |     let _bar2 = &foo.bar1;
+   |                  ^^^^^^^^ immutable borrow occurs here
+LL |     *bar1;
+LL | }
+   | - mutable borrow ends here
+
+error[E0502]: cannot borrow `foo.bar1` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-borrow-from-owned-ptr.rs:32:22
+   |
+LL |     let bar1 = &foo.bar1;
+   |                 -------- immutable borrow occurs here
+LL |     let _bar2 = &mut foo.bar1;
+   |                      ^^^^^^^^ mutable borrow occurs here
+LL |     *bar1;
+LL | }
+   | - immutable borrow ends here
+
+error[E0499]: cannot borrow `foo` (via `foo.bar2`) as mutable more than once at a time
+  --> $DIR/borrowck-borrow-from-owned-ptr.rs:46:22
+   |
+LL |     let bar1 = &mut foo.bar1;
+   |                     -------- first mutable borrow occurs here (via `foo.bar1`)
+LL |     let _bar2 = &mut foo.bar2;
+   |                      ^^^^^^^^ second mutable borrow occurs here (via `foo.bar2`)
+LL |     *bar1;
+LL | }
+   | - first borrow ends here
+
+error[E0499]: cannot borrow `foo` (via `foo.bar2`) as mutable more than once at a time
+  --> $DIR/borrowck-borrow-from-owned-ptr.rs:53:42
+   |
+LL |         Foo { bar1: ref mut _bar1, bar2: ref mut _bar2 } => {}
+   |                     -------------        ^^^^^^^^^^^^^ second mutable borrow occurs here (via `foo.bar2`)
+   |                     |
+   |                     first mutable borrow occurs here (via `foo.bar1`)
+LL |
+LL |     }
+   |     - first borrow ends here
+
+error[E0499]: cannot borrow `foo.bar1` as mutable more than once at a time
+  --> $DIR/borrowck-borrow-from-owned-ptr.rs:62:21
+   |
+LL |     let bar1 = &mut foo.bar1;
+   |                     -------- first mutable borrow occurs here
+LL |     match *foo {
+LL |         Foo { bar1: ref mut _bar1, bar2: _ } => {}
+   |                     ^^^^^^^^^^^^^ second mutable borrow occurs here
+...
+LL | }
+   | - first borrow ends here
+
+error[E0502]: cannot borrow `foo.bar1` as immutable because `foo.bar1.int1` is also borrowed as mutable
+  --> $DIR/borrowck-borrow-from-owned-ptr.rs:71:18
+   |
+LL |     let bar1 = &mut foo.bar1.int1;
+   |                     ------------- mutable borrow occurs here
+LL |     let _foo1 = &foo.bar1;
+   |                  ^^^^^^^^ immutable borrow occurs here
+...
+LL | }
+   | - mutable borrow ends here
+
+error[E0502]: cannot borrow `*foo` as immutable because `foo.bar1.int1` is also borrowed as mutable
+  --> $DIR/borrowck-borrow-from-owned-ptr.rs:72:18
+   |
+LL |     let bar1 = &mut foo.bar1.int1;
+   |                     ------------- mutable borrow occurs here
+LL |     let _foo1 = &foo.bar1;
+LL |     let _foo2 = &*foo;
+   |                  ^^^^ immutable borrow occurs here
+LL |     *bar1;
+LL | }
+   | - mutable borrow ends here
+
+error[E0499]: cannot borrow `foo.bar1` as mutable more than once at a time
+  --> $DIR/borrowck-borrow-from-owned-ptr.rs:79:22
+   |
+LL |     let bar1 = &mut foo.bar1.int1;
+   |                     ------------- first mutable borrow occurs here
+LL |     let _foo1 = &mut foo.bar1;
+   |                      ^^^^^^^^ second mutable borrow occurs here
+LL |     *bar1;
+LL | }
+   | - first borrow ends here
+
+error[E0499]: cannot borrow `*foo` as mutable more than once at a time
+  --> $DIR/borrowck-borrow-from-owned-ptr.rs:86:22
+   |
+LL |     let bar1 = &mut foo.bar1.int1;
+   |                     ------------- first mutable borrow occurs here
+LL |     let _foo2 = &mut *foo;
+   |                      ^^^^ second mutable borrow occurs here
+LL |     *bar1;
+LL | }
+   | - first borrow ends here
+
+error[E0502]: cannot borrow `foo.bar1` as mutable because `foo.bar1.int1` is also borrowed as immutable
+  --> $DIR/borrowck-borrow-from-owned-ptr.rs:93:22
+   |
+LL |     let bar1 = &foo.bar1.int1;
+   |                 ------------- immutable borrow occurs here
+LL |     let _foo1 = &mut foo.bar1;
+   |                      ^^^^^^^^ mutable borrow occurs here
+LL |     *bar1;
+LL | }
+   | - immutable borrow ends here
+
+error[E0502]: cannot borrow `*foo` as mutable because `foo.bar1.int1` is also borrowed as immutable
+  --> $DIR/borrowck-borrow-from-owned-ptr.rs:100:22
+   |
+LL |     let bar1 = &foo.bar1.int1;
+   |                 ------------- immutable borrow occurs here
+LL |     let _foo2 = &mut *foo;
+   |                      ^^^^ mutable borrow occurs here
+LL |     *bar1;
+LL | }
+   | - immutable borrow ends here
+
+error[E0502]: cannot borrow `foo` (via `foo.bar2`) as immutable because `foo` is also borrowed as mutable (via `foo.bar1`)
+  --> $DIR/borrowck-borrow-from-owned-ptr.rs:115:18
+   |
+LL |     let bar1 = &mut foo.bar1;
+   |                     -------- mutable borrow occurs here (via `foo.bar1`)
+LL |     let _foo1 = &foo.bar2;
+   |                  ^^^^^^^^ immutable borrow of `foo.bar2` -- which overlaps with `foo.bar1` -- occurs here
+LL |     *bar1;
+LL | }
+   | - mutable borrow ends here
+
+error[E0596]: cannot borrow field `foo.bar1` of immutable binding as mutable
+  --> $DIR/borrowck-borrow-from-owned-ptr.rs:121:21
+   |
+LL |     let foo = make_foo();
+   |         --- help: make this binding mutable: `mut foo`
+LL |     let bar1 = &mut foo.bar1;
+   |                     ^^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0499]: cannot borrow `foo` (via `foo.bar2.int2`) as mutable more than once at a time
+  --> $DIR/borrowck-borrow-from-owned-ptr.rs:128:21
+   |
+LL |     let bar1 = &mut foo.bar1.int1;
+   |                     ------------- first mutable borrow occurs here (via `foo.bar1.int1`)
+LL |     let foo1 = &mut foo.bar2.int2;
+   |                     ^^^^^^^^^^^^^ second mutable borrow occurs here (via `foo.bar2.int2`)
+...
+LL | }
+   | - first borrow ends here
+
+error: aborting due to 15 previous errors
+
+Some errors occurred: E0499, E0502, E0596.
+For more information about an error, try `rustc --explain E0499`.
diff --git a/src/test/ui/borrowck/borrowck-borrow-from-stack-variable.nll.stderr b/src/test/ui/borrowck/borrowck-borrow-from-stack-variable.nll.stderr
new file mode 100644
index 0000000..b5c6184
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-borrow-from-stack-variable.nll.stderr
@@ -0,0 +1,116 @@
+error[E0499]: cannot borrow `foo.bar1` as mutable more than once at a time
+  --> $DIR/borrowck-borrow-from-stack-variable.rs:18:17
+   |
+LL |     let bar1 = &mut foo.bar1;
+   |                ------------- first mutable borrow occurs here
+LL |     let _bar2 = &mut foo.bar1;
+   |                 ^^^^^^^^^^^^^ second mutable borrow occurs here
+LL |     *bar1;
+   |     ----- first borrow later used here
+
+error[E0502]: cannot borrow `foo.bar1` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-borrow-from-stack-variable.rs:25:17
+   |
+LL |     let bar1 = &mut foo.bar1;
+   |                ------------- mutable borrow occurs here
+LL |     let _bar2 = &foo.bar1;
+   |                 ^^^^^^^^^ immutable borrow occurs here
+LL |     *bar1;
+   |     ----- mutable borrow later used here
+
+error[E0502]: cannot borrow `foo.bar1` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-borrow-from-stack-variable.rs:32:17
+   |
+LL |     let bar1 = &foo.bar1;
+   |                --------- immutable borrow occurs here
+LL |     let _bar2 = &mut foo.bar1;
+   |                 ^^^^^^^^^^^^^ mutable borrow occurs here
+LL |     *bar1;
+   |     ----- immutable borrow later used here
+
+error[E0499]: cannot borrow `foo.bar1` as mutable more than once at a time
+  --> $DIR/borrowck-borrow-from-stack-variable.rs:61:21
+   |
+LL |     let bar1 = &mut foo.bar1;
+   |                ------------- first mutable borrow occurs here
+LL |     match foo {
+LL |         Foo { bar1: ref mut _bar1, bar2: _ } => {} //
+   |                     ^^^^^^^^^^^^^ second mutable borrow occurs here
+...
+LL |     *bar1;
+   |     ----- first borrow later used here
+
+error[E0502]: cannot borrow `foo.bar1` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-borrow-from-stack-variable.rs:70:17
+   |
+LL |     let bar1 = &mut foo.bar1.int1;
+   |                ------------------ mutable borrow occurs here
+LL |     let _foo1 = &foo.bar1;
+   |                 ^^^^^^^^^ immutable borrow occurs here
+LL |     let _foo2 = &foo;
+LL |     *bar1;
+   |     ----- mutable borrow later used here
+
+error[E0502]: cannot borrow `foo` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-borrow-from-stack-variable.rs:71:17
+   |
+LL |     let bar1 = &mut foo.bar1.int1;
+   |                ------------------ mutable borrow occurs here
+LL |     let _foo1 = &foo.bar1;
+LL |     let _foo2 = &foo;
+   |                 ^^^^ immutable borrow occurs here
+LL |     *bar1;
+   |     ----- mutable borrow later used here
+
+error[E0499]: cannot borrow `foo.bar1` as mutable more than once at a time
+  --> $DIR/borrowck-borrow-from-stack-variable.rs:78:17
+   |
+LL |     let bar1 = &mut foo.bar1.int1;
+   |                ------------------ first mutable borrow occurs here
+LL |     let _foo1 = &mut foo.bar1;
+   |                 ^^^^^^^^^^^^^ second mutable borrow occurs here
+LL |     *bar1;
+   |     ----- first borrow later used here
+
+error[E0499]: cannot borrow `foo` as mutable more than once at a time
+  --> $DIR/borrowck-borrow-from-stack-variable.rs:85:17
+   |
+LL |     let bar1 = &mut foo.bar1.int1;
+   |                ------------------ first mutable borrow occurs here
+LL |     let _foo2 = &mut foo;
+   |                 ^^^^^^^^ second mutable borrow occurs here
+LL |     *bar1;
+   |     ----- first borrow later used here
+
+error[E0502]: cannot borrow `foo.bar1` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-borrow-from-stack-variable.rs:92:17
+   |
+LL |     let bar1 = &foo.bar1.int1;
+   |                -------------- immutable borrow occurs here
+LL |     let _foo1 = &mut foo.bar1;
+   |                 ^^^^^^^^^^^^^ mutable borrow occurs here
+LL |     *bar1;
+   |     ----- immutable borrow later used here
+
+error[E0502]: cannot borrow `foo` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-borrow-from-stack-variable.rs:99:17
+   |
+LL |     let bar1 = &foo.bar1.int1;
+   |                -------------- immutable borrow occurs here
+LL |     let _foo2 = &mut foo;
+   |                 ^^^^^^^^ mutable borrow occurs here
+LL |     *bar1;
+   |     ----- immutable borrow later used here
+
+error[E0596]: cannot borrow `foo.bar1` as mutable, as `foo` is not declared as mutable
+  --> $DIR/borrowck-borrow-from-stack-variable.rs:120:16
+   |
+LL |     let foo = make_foo();
+   |         --- help: consider changing this to be mutable: `mut foo`
+LL |     let bar1 = &mut foo.bar1;
+   |                ^^^^^^^^^^^^^ cannot borrow as mutable
+
+error: aborting due to 11 previous errors
+
+Some errors occurred: E0499, E0502, E0596.
+For more information about an error, try `rustc --explain E0499`.
diff --git a/src/test/ui/borrowck/borrowck-borrow-from-stack-variable.rs b/src/test/ui/borrowck/borrowck-borrow-from-stack-variable.rs
new file mode 100644
index 0000000..231f6be
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-borrow-from-stack-variable.rs
@@ -0,0 +1,131 @@
+#[derive(Copy, Clone)]
+struct Foo {
+  bar1: Bar,
+  bar2: Bar
+}
+
+#[derive(Copy, Clone)]
+struct Bar {
+  int1: isize,
+  int2: isize,
+}
+
+fn make_foo() -> Foo { panic!() }
+
+fn borrow_same_field_twice_mut_mut() {
+    let mut foo = make_foo();
+    let bar1 = &mut foo.bar1;
+    let _bar2 = &mut foo.bar1;  //~ ERROR cannot borrow
+    *bar1;
+}
+
+fn borrow_same_field_twice_mut_imm() {
+    let mut foo = make_foo();
+    let bar1 = &mut foo.bar1;
+    let _bar2 = &foo.bar1;  //~ ERROR cannot borrow
+    *bar1;
+}
+
+fn borrow_same_field_twice_imm_mut() {
+    let mut foo = make_foo();
+    let bar1 = &foo.bar1;
+    let _bar2 = &mut foo.bar1;  //~ ERROR cannot borrow
+    *bar1;
+}
+
+fn borrow_same_field_twice_imm_imm() {
+    let mut foo = make_foo();
+    let bar1 = &foo.bar1;
+    let _bar2 = &foo.bar1;
+    *bar1;
+}
+
+fn borrow_both_mut() {
+    let mut foo = make_foo();
+    let bar1 = &mut foo.bar1;
+    let _bar2 = &mut foo.bar2;
+    *bar1;
+}
+
+fn borrow_both_mut_pattern() {
+    let mut foo = make_foo();
+    match foo {
+        Foo { bar1: ref mut _bar1, bar2: ref mut _bar2 } => {}
+    }
+}
+
+fn borrow_var_and_pattern() {
+    let mut foo = make_foo();
+    let bar1 = &mut foo.bar1;
+    match foo {
+        Foo { bar1: ref mut _bar1, bar2: _ } => {} //
+        //~^ ERROR cannot borrow
+    }
+    *bar1;
+}
+
+fn borrow_mut_and_base_imm() {
+    let mut foo = make_foo();
+    let bar1 = &mut foo.bar1.int1;
+    let _foo1 = &foo.bar1; //~ ERROR cannot borrow
+    let _foo2 = &foo; //~ ERROR cannot borrow
+    *bar1;
+}
+
+fn borrow_mut_and_base_mut() {
+    let mut foo = make_foo();
+    let bar1 = &mut foo.bar1.int1;
+    let _foo1 = &mut foo.bar1; //~ ERROR cannot borrow
+    *bar1;
+}
+
+fn borrow_mut_and_base_mut2() {
+    let mut foo = make_foo();
+    let bar1 = &mut foo.bar1.int1;
+    let _foo2 = &mut foo; //~ ERROR cannot borrow
+    *bar1;
+}
+
+fn borrow_imm_and_base_mut() {
+    let mut foo = make_foo();
+    let bar1 = &foo.bar1.int1;
+    let _foo1 = &mut foo.bar1; //~ ERROR cannot borrow
+    *bar1;
+}
+
+fn borrow_imm_and_base_mut2() {
+    let mut foo = make_foo();
+    let bar1 = &foo.bar1.int1;
+    let _foo2 = &mut foo; //~ ERROR cannot borrow
+    *bar1;
+}
+
+fn borrow_imm_and_base_imm() {
+    let mut foo = make_foo();
+    let bar1 = &foo.bar1.int1;
+    let _foo1 = &foo.bar1;
+    let _foo2 = &foo;
+    *bar1;
+}
+
+fn borrow_mut_and_imm() {
+    let mut foo = make_foo();
+    let bar1 = &mut foo.bar1;
+    let _foo1 = &foo.bar2;
+    *bar1;
+}
+
+fn borrow_mut_from_imm() {
+    let foo = make_foo();
+    let bar1 = &mut foo.bar1; //~ ERROR cannot borrow
+    *bar1;
+}
+
+fn borrow_long_path_both_mut() {
+    let mut foo = make_foo();
+    let bar1 = &mut foo.bar1.int1;
+    let _foo1 = &mut foo.bar2.int2;
+    *bar1;
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/borrowck-borrow-from-stack-variable.stderr b/src/test/ui/borrowck/borrowck-borrow-from-stack-variable.stderr
new file mode 100644
index 0000000..fe60d94
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-borrow-from-stack-variable.stderr
@@ -0,0 +1,124 @@
+error[E0499]: cannot borrow `foo.bar1` as mutable more than once at a time
+  --> $DIR/borrowck-borrow-from-stack-variable.rs:18:22
+   |
+LL |     let bar1 = &mut foo.bar1;
+   |                     -------- first mutable borrow occurs here
+LL |     let _bar2 = &mut foo.bar1;
+   |                      ^^^^^^^^ second mutable borrow occurs here
+LL |     *bar1;
+LL | }
+   | - first borrow ends here
+
+error[E0502]: cannot borrow `foo.bar1` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-borrow-from-stack-variable.rs:25:18
+   |
+LL |     let bar1 = &mut foo.bar1;
+   |                     -------- mutable borrow occurs here
+LL |     let _bar2 = &foo.bar1;
+   |                  ^^^^^^^^ immutable borrow occurs here
+LL |     *bar1;
+LL | }
+   | - mutable borrow ends here
+
+error[E0502]: cannot borrow `foo.bar1` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-borrow-from-stack-variable.rs:32:22
+   |
+LL |     let bar1 = &foo.bar1;
+   |                 -------- immutable borrow occurs here
+LL |     let _bar2 = &mut foo.bar1;
+   |                      ^^^^^^^^ mutable borrow occurs here
+LL |     *bar1;
+LL | }
+   | - immutable borrow ends here
+
+error[E0499]: cannot borrow `foo.bar1` as mutable more than once at a time
+  --> $DIR/borrowck-borrow-from-stack-variable.rs:61:21
+   |
+LL |     let bar1 = &mut foo.bar1;
+   |                     -------- first mutable borrow occurs here
+LL |     match foo {
+LL |         Foo { bar1: ref mut _bar1, bar2: _ } => {} //
+   |                     ^^^^^^^^^^^^^ second mutable borrow occurs here
+...
+LL | }
+   | - first borrow ends here
+
+error[E0502]: cannot borrow `foo.bar1` as immutable because `foo.bar1.int1` is also borrowed as mutable
+  --> $DIR/borrowck-borrow-from-stack-variable.rs:70:18
+   |
+LL |     let bar1 = &mut foo.bar1.int1;
+   |                     ------------- mutable borrow occurs here
+LL |     let _foo1 = &foo.bar1;
+   |                  ^^^^^^^^ immutable borrow occurs here
+...
+LL | }
+   | - mutable borrow ends here
+
+error[E0502]: cannot borrow `foo` as immutable because `foo.bar1.int1` is also borrowed as mutable
+  --> $DIR/borrowck-borrow-from-stack-variable.rs:71:18
+   |
+LL |     let bar1 = &mut foo.bar1.int1;
+   |                     ------------- mutable borrow occurs here
+LL |     let _foo1 = &foo.bar1;
+LL |     let _foo2 = &foo;
+   |                  ^^^ immutable borrow occurs here
+LL |     *bar1;
+LL | }
+   | - mutable borrow ends here
+
+error[E0499]: cannot borrow `foo.bar1` as mutable more than once at a time
+  --> $DIR/borrowck-borrow-from-stack-variable.rs:78:22
+   |
+LL |     let bar1 = &mut foo.bar1.int1;
+   |                     ------------- first mutable borrow occurs here
+LL |     let _foo1 = &mut foo.bar1;
+   |                      ^^^^^^^^ second mutable borrow occurs here
+LL |     *bar1;
+LL | }
+   | - first borrow ends here
+
+error[E0499]: cannot borrow `foo` as mutable more than once at a time
+  --> $DIR/borrowck-borrow-from-stack-variable.rs:85:22
+   |
+LL |     let bar1 = &mut foo.bar1.int1;
+   |                     ------------- first mutable borrow occurs here
+LL |     let _foo2 = &mut foo;
+   |                      ^^^ second mutable borrow occurs here
+LL |     *bar1;
+LL | }
+   | - first borrow ends here
+
+error[E0502]: cannot borrow `foo.bar1` as mutable because `foo.bar1.int1` is also borrowed as immutable
+  --> $DIR/borrowck-borrow-from-stack-variable.rs:92:22
+   |
+LL |     let bar1 = &foo.bar1.int1;
+   |                 ------------- immutable borrow occurs here
+LL |     let _foo1 = &mut foo.bar1;
+   |                      ^^^^^^^^ mutable borrow occurs here
+LL |     *bar1;
+LL | }
+   | - immutable borrow ends here
+
+error[E0502]: cannot borrow `foo` as mutable because `foo.bar1.int1` is also borrowed as immutable
+  --> $DIR/borrowck-borrow-from-stack-variable.rs:99:22
+   |
+LL |     let bar1 = &foo.bar1.int1;
+   |                 ------------- immutable borrow occurs here
+LL |     let _foo2 = &mut foo;
+   |                      ^^^ mutable borrow occurs here
+LL |     *bar1;
+LL | }
+   | - immutable borrow ends here
+
+error[E0596]: cannot borrow field `foo.bar1` of immutable binding as mutable
+  --> $DIR/borrowck-borrow-from-stack-variable.rs:120:21
+   |
+LL |     let foo = make_foo();
+   |         --- help: make this binding mutable: `mut foo`
+LL |     let bar1 = &mut foo.bar1;
+   |                     ^^^^^^^^ cannot mutably borrow field of immutable binding
+
+error: aborting due to 11 previous errors
+
+Some errors occurred: E0499, E0502, E0596.
+For more information about an error, try `rustc --explain E0499`.
diff --git a/src/test/ui/borrowck/borrowck-borrow-from-temporary.nll.stderr b/src/test/ui/borrowck/borrowck-borrow-from-temporary.nll.stderr
new file mode 100644
index 0000000..71bf052
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-borrow-from-temporary.nll.stderr
@@ -0,0 +1,11 @@
+error[E0515]: cannot return value referencing temporary value
+  --> $DIR/borrowck-borrow-from-temporary.rs:10:5
+   |
+LL |     let &Foo(ref x) = &id(Foo(3));
+   |                        ---------- temporary value created here
+LL |     x
+   |     ^ returns a value referencing data owned by the current function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/src/test/ui/borrowck/borrowck-borrow-from-temporary.rs b/src/test/ui/borrowck/borrowck-borrow-from-temporary.rs
new file mode 100644
index 0000000..e7ca1a9
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-borrow-from-temporary.rs
@@ -0,0 +1,14 @@
+// Test lifetimes are linked properly when we take reference
+// to interior.
+
+fn id<T>(x: T) -> T { x }
+
+struct Foo(isize);
+
+fn foo<'a>() -> &'a isize {
+    let &Foo(ref x) = &id(Foo(3)); //~ ERROR borrowed value does not live long enough
+    x
+}
+
+pub fn main() {
+}
diff --git a/src/test/ui/borrowck/borrowck-borrow-from-temporary.stderr b/src/test/ui/borrowck/borrowck-borrow-from-temporary.stderr
new file mode 100644
index 0000000..6f101f6
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-borrow-from-temporary.stderr
@@ -0,0 +1,18 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/borrowck-borrow-from-temporary.rs:9:24
+   |
+LL |     let &Foo(ref x) = &id(Foo(3));
+   |                        ^^^^^^^^^^ temporary value does not live long enough
+LL |     x
+LL | }
+   | - temporary value only lives until here
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 8:8...
+  --> $DIR/borrowck-borrow-from-temporary.rs:8:8
+   |
+LL | fn foo<'a>() -> &'a isize {
+   |        ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/borrowck/borrowck-borrow-immut-deref-of-box-as-mut.nll.stderr b/src/test/ui/borrowck/borrowck-borrow-immut-deref-of-box-as-mut.nll.stderr
new file mode 100644
index 0000000..7d7e305
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-borrow-immut-deref-of-box-as-mut.nll.stderr
@@ -0,0 +1,11 @@
+error[E0596]: cannot borrow `*a` as mutable, as `a` is not declared as mutable
+  --> $DIR/borrowck-borrow-immut-deref-of-box-as-mut.rs:12:5
+   |
+LL |     let a: Box<_> = box A;
+   |         - help: consider changing this to be mutable: `mut a`
+LL |     a.foo();
+   |     ^ cannot borrow as mutable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/borrowck/borrowck-borrow-immut-deref-of-box-as-mut.rs b/src/test/ui/borrowck/borrowck-borrow-immut-deref-of-box-as-mut.rs
new file mode 100644
index 0000000..8d52818
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-borrow-immut-deref-of-box-as-mut.rs
@@ -0,0 +1,14 @@
+#![feature(box_syntax)]
+
+struct A;
+
+impl A {
+    fn foo(&mut self) {
+    }
+}
+
+pub fn main() {
+    let a: Box<_> = box A;
+    a.foo();
+    //~^ ERROR cannot borrow immutable `Box` content `*a` as mutable
+}
diff --git a/src/test/ui/borrowck/borrowck-borrow-immut-deref-of-box-as-mut.stderr b/src/test/ui/borrowck/borrowck-borrow-immut-deref-of-box-as-mut.stderr
new file mode 100644
index 0000000..2c989b2
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-borrow-immut-deref-of-box-as-mut.stderr
@@ -0,0 +1,11 @@
+error[E0596]: cannot borrow immutable `Box` content `*a` as mutable
+  --> $DIR/borrowck-borrow-immut-deref-of-box-as-mut.rs:12:5
+   |
+LL |     let a: Box<_> = box A;
+   |         - help: make this binding mutable: `mut a`
+LL |     a.foo();
+   |     ^ cannot borrow as mutable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.nll.stderr b/src/test/ui/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.nll.stderr
new file mode 100644
index 0000000..7c1c063
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.nll.stderr
@@ -0,0 +1,31 @@
+error[E0594]: cannot assign to `**t1` which is behind a `&` reference
+  --> $DIR/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs:9:5
+   |
+LL |     let t1 = t0;
+   |         -- help: consider changing this to be a mutable reference: `&mut &mut isize`
+LL |     let p: &isize = &**t0;
+LL |     **t1 = 22;
+   |     ^^^^^^^^^ `t1` is a `&` reference, so the data it refers to cannot be written
+
+error[E0502]: cannot borrow `**t0` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs:14:21
+   |
+LL |     let t1 = &mut *t0;
+   |              -------- mutable borrow occurs here
+LL |     let p: &isize = &**t0;
+   |                     ^^^^^ immutable borrow occurs here
+LL |     **t1 = 22;
+   |     --------- mutable borrow later used here
+
+error[E0596]: cannot borrow `**t0` as mutable, as it is behind a `&` reference
+  --> $DIR/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs:19:26
+   |
+LL | fn foo4(t0: & &mut isize) {
+   |             ------------ help: consider changing this to be a mutable reference: `&mut &mut isize`
+LL |     let x:  &mut isize = &mut **t0;
+   |                          ^^^^^^^^^ `t0` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0502, E0594, E0596.
+For more information about an error, try `rustc --explain E0502`.
diff --git a/src/test/ui/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs b/src/test/ui/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs
new file mode 100644
index 0000000..75bf320
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs
@@ -0,0 +1,24 @@
+// Test that attempt to reborrow an `&mut` pointer in an aliasable
+// location yields an error.
+//
+// Example from src/librustc_borrowck/borrowck/README.md
+
+fn foo(t0: & &mut isize) {
+    let t1 = t0;
+    let p: &isize = &**t0;
+    **t1 = 22; //~ ERROR cannot assign
+}
+
+fn foo3(t0: &mut &mut isize) {
+    let t1 = &mut *t0;
+    let p: &isize = &**t0; //~ ERROR cannot borrow
+    **t1 = 22;
+}
+
+fn foo4(t0: & &mut isize) {
+    let x:  &mut isize = &mut **t0; //~ ERROR cannot borrow
+    *x += 1;
+}
+
+fn main() {
+}
diff --git a/src/test/ui/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.stderr b/src/test/ui/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.stderr
new file mode 100644
index 0000000..709a797
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.stderr
@@ -0,0 +1,29 @@
+error[E0389]: cannot assign to data in a `&` reference
+  --> $DIR/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs:9:5
+   |
+LL |     **t1 = 22;
+   |     ^^^^^^^^^ assignment into an immutable reference
+
+error[E0502]: cannot borrow `**t0` as immutable because `*t0` is also borrowed as mutable
+  --> $DIR/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs:14:22
+   |
+LL |     let t1 = &mut *t0;
+   |                   --- mutable borrow occurs here
+LL |     let p: &isize = &**t0;
+   |                      ^^^^ immutable borrow occurs here
+LL |     **t1 = 22;
+LL | }
+   | - mutable borrow ends here
+
+error[E0389]: cannot borrow data mutably in a `&` reference
+  --> $DIR/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs:19:31
+   |
+LL | fn foo4(t0: & &mut isize) {
+   |             ------------ use `&mut &mut isize` here to make mutable
+LL |     let x:  &mut isize = &mut **t0;
+   |                               ^^^^ assignment into an immutable reference
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0389, E0502.
+For more information about an error, try `rustc --explain E0389`.
diff --git a/src/test/ui/borrowck/borrowck-borrow-mut-object-twice.nll.stderr b/src/test/ui/borrowck/borrowck-borrow-mut-object-twice.nll.stderr
new file mode 100644
index 0000000..fa0ae31
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-borrow-mut-object-twice.nll.stderr
@@ -0,0 +1,13 @@
+error[E0499]: cannot borrow `*x` as mutable more than once at a time
+  --> $DIR/borrowck-borrow-mut-object-twice.rs:13:5
+   |
+LL |     let y = x.f1();
+   |             - first mutable borrow occurs here
+LL |     x.f2();
+   |     ^ second mutable borrow occurs here
+LL |     y.use_ref();
+   |     - first borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/borrowck/borrowck-borrow-mut-object-twice.rs b/src/test/ui/borrowck/borrowck-borrow-mut-object-twice.rs
new file mode 100644
index 0000000..5e853af
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-borrow-mut-object-twice.rs
@@ -0,0 +1,20 @@
+// Check that `&mut` objects cannot be borrowed twice, just like
+// other `&mut` pointers.
+
+
+
+trait Foo {
+    fn f1(&mut self) -> &();
+    fn f2(&mut self);
+}
+
+fn test(x: &mut Foo) {
+    let y = x.f1();
+    x.f2(); //~ ERROR cannot borrow `*x` as mutable
+    y.use_ref();
+}
+
+fn main() {}
+
+trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { }  }
+impl<T> Fake for T { }
diff --git a/src/test/ui/borrowck/borrowck-borrow-mut-object-twice.stderr b/src/test/ui/borrowck/borrowck-borrow-mut-object-twice.stderr
new file mode 100644
index 0000000..1b64ad5
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-borrow-mut-object-twice.stderr
@@ -0,0 +1,14 @@
+error[E0499]: cannot borrow `*x` as mutable more than once at a time
+  --> $DIR/borrowck-borrow-mut-object-twice.rs:13:5
+   |
+LL |     let y = x.f1();
+   |             - first mutable borrow occurs here
+LL |     x.f2();
+   |     ^ second mutable borrow occurs here
+LL |     y.use_ref();
+LL | }
+   | - first borrow ends here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/borrowck/borrowck-borrow-overloaded-auto-deref.nll.stderr b/src/test/ui/borrowck/borrowck-borrow-overloaded-auto-deref.nll.stderr
new file mode 100644
index 0000000..4fc320c
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-borrow-overloaded-auto-deref.nll.stderr
@@ -0,0 +1,88 @@
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:47:19
+   |
+LL |     let __isize = &mut x.y;
+   |                   ^^^^^^^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:51:19
+   |
+LL |     let __isize = &mut x.y;
+   |                   ^^^^^^^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:59:5
+   |
+LL |     &mut x.y
+   |     ^^^^^^^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:63:5
+   |
+LL |     &mut x.y
+   |     ^^^^^^^^ cannot borrow as mutable
+
+error[E0594]: cannot assign to data in a `&` reference
+  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:67:5
+   |
+LL |     x.y = 3;
+   |     ^^^^^^^ cannot assign
+
+error[E0594]: cannot assign to data in a `&` reference
+  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:71:5
+   |
+LL |     x.y = 3;
+   |     ^^^^^^^ cannot assign
+
+error[E0594]: cannot assign to data in a `&` reference
+  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:75:5
+   |
+LL |     x.y = 3;
+   |     ^^^^^^^ cannot assign
+
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:83:5
+   |
+LL |     x.set(0, 0);
+   |     ^ cannot borrow as mutable
+
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:87:5
+   |
+LL |     x.set(0, 0);
+   |     ^ cannot borrow as mutable
+
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:95:5
+   |
+LL |     x.y_mut()
+   |     ^ cannot borrow as mutable
+
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:99:5
+   |
+LL |     x.y_mut()
+   |     ^ cannot borrow as mutable
+
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:103:6
+   |
+LL |     *x.y_mut() = 3;
+   |      ^ cannot borrow as mutable
+
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:107:6
+   |
+LL |     *x.y_mut() = 3;
+   |      ^ cannot borrow as mutable
+
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:111:6
+   |
+LL |     *x.y_mut() = 3;
+   |      ^ cannot borrow as mutable
+
+error: aborting due to 14 previous errors
+
+Some errors occurred: E0594, E0596.
+For more information about an error, try `rustc --explain E0594`.
diff --git a/src/test/ui/borrowck/borrowck-borrow-overloaded-auto-deref.rs b/src/test/ui/borrowck/borrowck-borrow-overloaded-auto-deref.rs
new file mode 100644
index 0000000..01dc0af
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-borrow-overloaded-auto-deref.rs
@@ -0,0 +1,114 @@
+// Test how overloaded deref interacts with borrows when only
+// Deref and not DerefMut is implemented.
+
+use std::ops::Deref;
+
+struct Rc<T> {
+    value: *const T
+}
+
+impl<T> Deref for Rc<T> {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        unsafe { &*self.value }
+    }
+}
+
+struct Point {
+    x: isize,
+    y: isize
+}
+
+impl Point {
+    fn get(&self) -> (isize, isize) {
+        (self.x, self.y)
+    }
+
+    fn set(&mut self, x: isize, y: isize) {
+        self.x = x;
+        self.y = y;
+    }
+
+    fn x_ref(&self) -> &isize {
+        &self.x
+    }
+
+    fn y_mut(&mut self) -> &mut isize {
+        &mut self.y
+    }
+}
+
+fn deref_imm_field(x: Rc<Point>) {
+    let __isize = &x.y;
+}
+
+fn deref_mut_field1(x: Rc<Point>) {
+    let __isize = &mut x.y; //~ ERROR cannot borrow
+}
+
+fn deref_mut_field2(mut x: Rc<Point>) {
+    let __isize = &mut x.y; //~ ERROR cannot borrow
+}
+
+fn deref_extend_field(x: &Rc<Point>) -> &isize {
+    &x.y
+}
+
+fn deref_extend_mut_field1(x: &Rc<Point>) -> &mut isize {
+    &mut x.y //~ ERROR cannot borrow
+}
+
+fn deref_extend_mut_field2(x: &mut Rc<Point>) -> &mut isize {
+    &mut x.y //~ ERROR cannot borrow
+}
+
+fn assign_field1<'a>(x: Rc<Point>) {
+    x.y = 3; //~ ERROR cannot assign
+}
+
+fn assign_field2<'a>(x: &'a Rc<Point>) {
+    x.y = 3; //~ ERROR cannot assign
+}
+
+fn assign_field3<'a>(x: &'a mut Rc<Point>) {
+    x.y = 3; //~ ERROR cannot assign
+}
+
+fn deref_imm_method(x: Rc<Point>) {
+    let __isize = x.get();
+}
+
+fn deref_mut_method1(x: Rc<Point>) {
+    x.set(0, 0); //~ ERROR cannot borrow
+}
+
+fn deref_mut_method2(mut x: Rc<Point>) {
+    x.set(0, 0); //~ ERROR cannot borrow
+}
+
+fn deref_extend_method(x: &Rc<Point>) -> &isize {
+    x.x_ref()
+}
+
+fn deref_extend_mut_method1(x: &Rc<Point>) -> &mut isize {
+    x.y_mut() //~ ERROR cannot borrow
+}
+
+fn deref_extend_mut_method2(x: &mut Rc<Point>) -> &mut isize {
+    x.y_mut() //~ ERROR cannot borrow
+}
+
+fn assign_method1<'a>(x: Rc<Point>) {
+    *x.y_mut() = 3; //~ ERROR cannot borrow
+}
+
+fn assign_method2<'a>(x: &'a Rc<Point>) {
+    *x.y_mut() = 3; //~ ERROR cannot borrow
+}
+
+fn assign_method3<'a>(x: &'a mut Rc<Point>) {
+    *x.y_mut() = 3; //~ ERROR cannot borrow
+}
+
+pub fn main() {}
diff --git a/src/test/ui/borrowck/borrowck-borrow-overloaded-auto-deref.stderr b/src/test/ui/borrowck/borrowck-borrow-overloaded-auto-deref.stderr
new file mode 100644
index 0000000..2fe1461
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-borrow-overloaded-auto-deref.stderr
@@ -0,0 +1,88 @@
+error[E0596]: cannot borrow field of immutable binding as mutable
+  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:47:24
+   |
+LL |     let __isize = &mut x.y;
+   |                        ^^^ cannot mutably borrow field of immutable binding
+
+error[E0596]: cannot borrow field of immutable binding as mutable
+  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:51:24
+   |
+LL |     let __isize = &mut x.y;
+   |                        ^^^ cannot mutably borrow field of immutable binding
+
+error[E0596]: cannot borrow field of immutable binding as mutable
+  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:59:10
+   |
+LL |     &mut x.y
+   |          ^^^ cannot mutably borrow field of immutable binding
+
+error[E0596]: cannot borrow field of immutable binding as mutable
+  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:63:10
+   |
+LL |     &mut x.y
+   |          ^^^ cannot mutably borrow field of immutable binding
+
+error[E0594]: cannot assign to field of immutable binding
+  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:67:5
+   |
+LL |     x.y = 3;
+   |     ^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0594]: cannot assign to field of immutable binding
+  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:71:5
+   |
+LL |     x.y = 3;
+   |     ^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0594]: cannot assign to field of immutable binding
+  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:75:5
+   |
+LL |     x.y = 3;
+   |     ^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0596]: cannot borrow immutable borrowed content as mutable
+  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:83:5
+   |
+LL |     x.set(0, 0);
+   |     ^ cannot borrow as mutable
+
+error[E0596]: cannot borrow immutable borrowed content as mutable
+  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:87:5
+   |
+LL |     x.set(0, 0);
+   |     ^ cannot borrow as mutable
+
+error[E0596]: cannot borrow immutable borrowed content as mutable
+  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:95:5
+   |
+LL |     x.y_mut()
+   |     ^ cannot borrow as mutable
+
+error[E0596]: cannot borrow immutable borrowed content as mutable
+  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:99:5
+   |
+LL |     x.y_mut()
+   |     ^ cannot borrow as mutable
+
+error[E0596]: cannot borrow immutable borrowed content as mutable
+  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:103:6
+   |
+LL |     *x.y_mut() = 3;
+   |      ^ cannot borrow as mutable
+
+error[E0596]: cannot borrow immutable borrowed content as mutable
+  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:107:6
+   |
+LL |     *x.y_mut() = 3;
+   |      ^ cannot borrow as mutable
+
+error[E0596]: cannot borrow immutable borrowed content as mutable
+  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:111:6
+   |
+LL |     *x.y_mut() = 3;
+   |      ^ cannot borrow as mutable
+
+error: aborting due to 14 previous errors
+
+Some errors occurred: E0594, E0596.
+For more information about an error, try `rustc --explain E0594`.
diff --git a/src/test/ui/borrowck/borrowck-borrow-overloaded-deref.nll.stderr b/src/test/ui/borrowck/borrowck-borrow-overloaded-deref.nll.stderr
new file mode 100644
index 0000000..cc4d91a
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-borrow-overloaded-deref.nll.stderr
@@ -0,0 +1,46 @@
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/borrowck-borrow-overloaded-deref.rs:23:19
+   |
+LL |     let __isize = &mut *x;
+   |                   ^^^^^^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/borrowck-borrow-overloaded-deref.rs:27:19
+   |
+LL |     let __isize = &mut *x;
+   |                   ^^^^^^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/borrowck-borrow-overloaded-deref.rs:35:5
+   |
+LL |     &mut **x
+   |     ^^^^^^^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/borrowck-borrow-overloaded-deref.rs:39:5
+   |
+LL |     &mut **x
+   |     ^^^^^^^^ cannot borrow as mutable
+
+error[E0594]: cannot assign to data in a `&` reference
+  --> $DIR/borrowck-borrow-overloaded-deref.rs:43:5
+   |
+LL |     *x = 3;
+   |     ^^^^^^ cannot assign
+
+error[E0594]: cannot assign to data in a `&` reference
+  --> $DIR/borrowck-borrow-overloaded-deref.rs:47:5
+   |
+LL |     **x = 3;
+   |     ^^^^^^^ cannot assign
+
+error[E0594]: cannot assign to data in a `&` reference
+  --> $DIR/borrowck-borrow-overloaded-deref.rs:51:5
+   |
+LL |     **x = 3;
+   |     ^^^^^^^ cannot assign
+
+error: aborting due to 7 previous errors
+
+Some errors occurred: E0594, E0596.
+For more information about an error, try `rustc --explain E0594`.
diff --git a/src/test/ui/borrowck/borrowck-borrow-overloaded-deref.rs b/src/test/ui/borrowck/borrowck-borrow-overloaded-deref.rs
new file mode 100644
index 0000000..39fa70c
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-borrow-overloaded-deref.rs
@@ -0,0 +1,54 @@
+// Test how overloaded deref interacts with borrows when only
+// Deref and not DerefMut is implemented.
+
+use std::ops::Deref;
+
+struct Rc<T> {
+    value: *const T
+}
+
+impl<T> Deref for Rc<T> {
+    type Target = T;
+
+    fn deref<'a>(&'a self) -> &'a T {
+        unsafe { &*self.value }
+    }
+}
+
+fn deref_imm(x: Rc<isize>) {
+    let __isize = &*x;
+}
+
+fn deref_mut1(x: Rc<isize>) {
+    let __isize = &mut *x; //~ ERROR cannot borrow
+}
+
+fn deref_mut2(mut x: Rc<isize>) {
+    let __isize = &mut *x; //~ ERROR cannot borrow
+}
+
+fn deref_extend<'a>(x: &'a Rc<isize>) -> &'a isize {
+    &**x
+}
+
+fn deref_extend_mut1<'a>(x: &'a Rc<isize>) -> &'a mut isize {
+    &mut **x //~ ERROR cannot borrow
+}
+
+fn deref_extend_mut2<'a>(x: &'a mut Rc<isize>) -> &'a mut isize {
+    &mut **x //~ ERROR cannot borrow
+}
+
+fn assign1<'a>(x: Rc<isize>) {
+    *x = 3; //~ ERROR cannot assign
+}
+
+fn assign2<'a>(x: &'a Rc<isize>) {
+    **x = 3; //~ ERROR cannot assign
+}
+
+fn assign3<'a>(x: &'a mut Rc<isize>) {
+    **x = 3; //~ ERROR cannot assign
+}
+
+pub fn main() {}
diff --git a/src/test/ui/borrowck/borrowck-borrow-overloaded-deref.stderr b/src/test/ui/borrowck/borrowck-borrow-overloaded-deref.stderr
new file mode 100644
index 0000000..fb79ccb
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-borrow-overloaded-deref.stderr
@@ -0,0 +1,46 @@
+error[E0596]: cannot borrow immutable borrowed content as mutable
+  --> $DIR/borrowck-borrow-overloaded-deref.rs:23:24
+   |
+LL |     let __isize = &mut *x;
+   |                        ^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow immutable borrowed content as mutable
+  --> $DIR/borrowck-borrow-overloaded-deref.rs:27:24
+   |
+LL |     let __isize = &mut *x;
+   |                        ^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow immutable borrowed content as mutable
+  --> $DIR/borrowck-borrow-overloaded-deref.rs:35:10
+   |
+LL |     &mut **x
+   |          ^^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow immutable borrowed content as mutable
+  --> $DIR/borrowck-borrow-overloaded-deref.rs:39:10
+   |
+LL |     &mut **x
+   |          ^^^ cannot borrow as mutable
+
+error[E0594]: cannot assign to immutable borrowed content
+  --> $DIR/borrowck-borrow-overloaded-deref.rs:43:5
+   |
+LL |     *x = 3;
+   |     ^^^^^^ cannot borrow as mutable
+
+error[E0594]: cannot assign to immutable borrowed content
+  --> $DIR/borrowck-borrow-overloaded-deref.rs:47:5
+   |
+LL |     **x = 3;
+   |     ^^^^^^^ cannot borrow as mutable
+
+error[E0594]: cannot assign to immutable borrowed content
+  --> $DIR/borrowck-borrow-overloaded-deref.rs:51:5
+   |
+LL |     **x = 3;
+   |     ^^^^^^^ cannot borrow as mutable
+
+error: aborting due to 7 previous errors
+
+Some errors occurred: E0594, E0596.
+For more information about an error, try `rustc --explain E0594`.
diff --git a/src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue-2.nll.stderr b/src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue-2.nll.stderr
new file mode 100644
index 0000000..1dd18c1
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue-2.nll.stderr
@@ -0,0 +1,16 @@
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/borrowck-borrowed-uniq-rvalue-2.rs:20:20
+   |
+LL |     let x = defer(&vec!["Goodbye", "world!"]);
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^ - temporary value is freed at the end of this statement
+   |                    |
+   |                    creates a temporary which is freed while still in use
+LL |     x.x[0];
+   |     ------ borrow later used here
+   |
+   = note: consider using a `let` binding to create a longer lived value
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue-2.rs b/src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue-2.rs
new file mode 100644
index 0000000..6e943ff
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue-2.rs
@@ -0,0 +1,22 @@
+struct Defer<'a> {
+    x: &'a [&'a str],
+}
+
+impl<'a> Drop for Defer<'a> {
+    fn drop(&mut self) {
+        unsafe {
+            println!("{:?}", self.x);
+        }
+    }
+}
+
+fn defer<'r>(x: &'r [&'r str]) -> Defer<'r> {
+    Defer {
+        x: x
+    }
+}
+
+fn main() {
+    let x = defer(&vec!["Goodbye", "world!"]); //~ ERROR borrowed value does not live long enough
+    x.x[0];
+}
diff --git a/src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue-2.stderr b/src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue-2.stderr
new file mode 100644
index 0000000..d17cf8a
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue-2.stderr
@@ -0,0 +1,17 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/borrowck-borrowed-uniq-rvalue-2.rs:20:20
+   |
+LL |     let x = defer(&vec!["Goodbye", "world!"]);
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^ - temporary value dropped here while still borrowed
+   |                    |
+   |                    temporary value does not live long enough
+LL |     x.x[0];
+LL | }
+   | - temporary value needs to live until here
+   |
+   = note: consider using a `let` binding to increase its lifetime
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue.nll.stderr b/src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue.nll.stderr
new file mode 100644
index 0000000..c91a437
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue.nll.stderr
@@ -0,0 +1,16 @@
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/borrowck-borrowed-uniq-rvalue.rs:10:28
+   |
+LL |     buggy_map.insert(42, &*Box::new(1));
+   |                            ^^^^^^^^^^^ - temporary value is freed at the end of this statement
+   |                            |
+   |                            creates a temporary which is freed while still in use
+...
+LL |     buggy_map.insert(43, &*tmp);
+   |     --------- borrow later used here
+   |
+   = note: consider using a `let` binding to create a longer lived value
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue.rs b/src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue.rs
new file mode 100644
index 0000000..88bd106
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue.rs
@@ -0,0 +1,15 @@
+//buggy.rs
+
+#![feature(box_syntax)]
+
+use std::collections::HashMap;
+
+fn main() {
+    let tmp: Box<_>;
+    let mut buggy_map: HashMap<usize, &usize> = HashMap::new();
+    buggy_map.insert(42, &*Box::new(1)); //~ ERROR borrowed value does not live long enough
+
+    // but it is ok if we use a temporary
+    tmp = box 2;
+    buggy_map.insert(43, &*tmp);
+}
diff --git a/src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue.stderr b/src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue.stderr
new file mode 100644
index 0000000..32a8656
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue.stderr
@@ -0,0 +1,16 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/borrowck-borrowed-uniq-rvalue.rs:10:27
+   |
+LL |     buggy_map.insert(42, &*Box::new(1));
+   |                           ^^^^^^^^^^^^ - borrowed value dropped here while still borrowed
+   |                           |
+   |                           borrowed value does not live long enough
+...
+LL | }
+   | - borrowed value needs to live until here
+   |
+   = note: consider using a `let` binding to increase its lifetime
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/borrowck/borrowck-box-insensitivity.ast.stderr b/src/test/ui/borrowck/borrowck-box-insensitivity.ast.stderr
new file mode 100644
index 0000000..60c8b33
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-box-insensitivity.ast.stderr
@@ -0,0 +1,165 @@
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-box-insensitivity.rs:37:9
+   |
+LL |     let _x = a.x;
+   |         -- value moved here
+LL |
+LL |     let _y = a.y;
+   |         ^^ value used here after move
+   |
+   = note: move occurs because `a.x` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-box-insensitivity.rs:46:9
+   |
+LL |     let _x = a.x;
+   |         -- value moved here
+LL |
+LL |     let _y = a.y;
+   |         ^^ value used here after move
+   |
+   = note: move occurs because `a.x` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-box-insensitivity.rs:55:15
+   |
+LL |     let _x = a.x;
+   |         -- value moved here
+LL |
+LL |     let _y = &a.y;
+   |               ^^^ value used here after move
+   |
+   = note: move occurs because `a.x` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+
+error[E0505]: cannot move out of `a.y` because it is borrowed
+  --> $DIR/borrowck-box-insensitivity.rs:63:9
+   |
+LL |     let _x = &a.x;
+   |               --- borrow of `a.x` occurs here
+LL |     let _y = a.y;
+   |         ^^ move out of `a.y` occurs here
+
+error[E0503]: cannot use `a.y` because it was mutably borrowed
+  --> $DIR/borrowck-box-insensitivity.rs:71:9
+   |
+LL |     let _x = &mut a.x;
+   |                   --- borrow of `a.x` occurs here
+LL |     let _y = a.y;
+   |         ^^ use of borrowed `a.x`
+
+error[E0505]: cannot move out of `a.y` because it is borrowed
+  --> $DIR/borrowck-box-insensitivity.rs:77:9
+   |
+LL |     let _x = &mut a.x;
+   |                   --- borrow of `a.x` occurs here
+LL |     let _y = a.y;
+   |         ^^ move out of `a.y` occurs here
+
+error[E0502]: cannot borrow `a` (via `a.y`) as immutable because `a` is also borrowed as mutable (via `a.x`)
+  --> $DIR/borrowck-box-insensitivity.rs:85:15
+   |
+LL |     let _x = &mut a.x;
+   |                   --- mutable borrow occurs here (via `a.x`)
+LL |     let _y = &a.y;
+   |               ^^^ immutable borrow of `a.y` -- which overlaps with `a.x` -- occurs here
+...
+LL | }
+   | - mutable borrow ends here
+
+error[E0502]: cannot borrow `a` (via `a.y`) as mutable because `a` is also borrowed as immutable (via `a.x`)
+  --> $DIR/borrowck-box-insensitivity.rs:92:19
+   |
+LL |     let _x = &a.x;
+   |               --- immutable borrow occurs here (via `a.x`)
+LL |     let _y = &mut a.y;
+   |                   ^^^ mutable borrow of `a.y` -- which overlaps with `a.x` -- occurs here
+...
+LL | }
+   | - immutable borrow ends here
+
+error[E0382]: use of collaterally moved value: `a.y`
+  --> $DIR/borrowck-box-insensitivity.rs:100:9
+   |
+LL |     let _x = a.x.x;
+   |         -- value moved here
+LL |
+LL |     let _y = a.y;
+   |         ^^ value used here after move
+   |
+   = note: move occurs because `a.x.x` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+
+error[E0382]: use of collaterally moved value: `a.y`
+  --> $DIR/borrowck-box-insensitivity.rs:108:9
+   |
+LL |     let _x = a.x.x;
+   |         -- value moved here
+LL |
+LL |     let _y = a.y;
+   |         ^^ value used here after move
+   |
+   = note: move occurs because `a.x.x` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+
+error[E0382]: use of collaterally moved value: `a.y`
+  --> $DIR/borrowck-box-insensitivity.rs:116:15
+   |
+LL |     let _x = a.x.x;
+   |         -- value moved here
+LL |
+LL |     let _y = &a.y;
+   |               ^^^ value used here after move
+   |
+   = note: move occurs because `a.x.x` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+
+error[E0505]: cannot move out of `a.y` because it is borrowed
+  --> $DIR/borrowck-box-insensitivity.rs:124:9
+   |
+LL |     let _x = &a.x.x;
+   |               ----- borrow of `a.x.x` occurs here
+LL |
+LL |     let _y = a.y;
+   |         ^^ move out of `a.y` occurs here
+
+error[E0503]: cannot use `a.y` because it was mutably borrowed
+  --> $DIR/borrowck-box-insensitivity.rs:132:9
+   |
+LL |     let _x = &mut a.x.x;
+   |                   ----- borrow of `a.x.x` occurs here
+LL |     let _y = a.y;
+   |         ^^ use of borrowed `a.x.x`
+
+error[E0505]: cannot move out of `a.y` because it is borrowed
+  --> $DIR/borrowck-box-insensitivity.rs:138:9
+   |
+LL |     let _x = &mut a.x.x;
+   |                   ----- borrow of `a.x.x` occurs here
+LL |     let _y = a.y;
+   |         ^^ move out of `a.y` occurs here
+
+error[E0502]: cannot borrow `a.y` as immutable because `a.x.x` is also borrowed as mutable
+  --> $DIR/borrowck-box-insensitivity.rs:147:15
+   |
+LL |     let _x = &mut a.x.x;
+   |                   ----- mutable borrow occurs here
+LL |
+LL |     let _y = &a.y;
+   |               ^^^ immutable borrow occurs here
+...
+LL | }
+   | - mutable borrow ends here
+
+error[E0502]: cannot borrow `a.y` as mutable because `a.x.x` is also borrowed as immutable
+  --> $DIR/borrowck-box-insensitivity.rs:155:19
+   |
+LL |     let _x = &a.x.x;
+   |               ----- immutable borrow occurs here
+LL |
+LL |     let _y = &mut a.y;
+   |                   ^^^ mutable borrow occurs here
+...
+LL | }
+   | - immutable borrow ends here
+
+error: aborting due to 16 previous errors
+
+Some errors occurred: E0382, E0502, E0503, E0505.
+For more information about an error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/borrowck-box-insensitivity.mir.stderr b/src/test/ui/borrowck/borrowck-box-insensitivity.mir.stderr
new file mode 100644
index 0000000..0e380e9
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-box-insensitivity.mir.stderr
@@ -0,0 +1,14 @@
+error: compilation successful
+  --> $DIR/borrowck-box-insensitivity.rs:160:1
+   |
+LL | / fn main() {
+LL | |     copy_after_move();
+LL | |     move_after_move();
+LL | |     borrow_after_move();
+...  |
+LL | |     mut_borrow_after_borrow_nested();
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/borrowck/borrowck-box-insensitivity.nll.stderr b/src/test/ui/borrowck/borrowck-box-insensitivity.nll.stderr
new file mode 100644
index 0000000..0e380e9
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-box-insensitivity.nll.stderr
@@ -0,0 +1,14 @@
+error: compilation successful
+  --> $DIR/borrowck-box-insensitivity.rs:160:1
+   |
+LL | / fn main() {
+LL | |     copy_after_move();
+LL | |     move_after_move();
+LL | |     borrow_after_move();
+...  |
+LL | |     mut_borrow_after_borrow_nested();
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/borrowck/borrowck-box-insensitivity.rs b/src/test/ui/borrowck/borrowck-box-insensitivity.rs
new file mode 100644
index 0000000..e72048d
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-box-insensitivity.rs
@@ -0,0 +1,185 @@
+// This test is an artifact of the old policy that `Box<T>` should not
+// be treated specially by the AST-borrowck.
+//
+// NLL goes back to treating `Box<T>` specially (namely, knowing that
+// it uniquely owns the data it holds). See rust-lang/rfcs#130.
+
+// revisions: ast mir
+//[ast] compile-flags: -Z borrowck=ast
+//[mir] compile-flags: -Z borrowck=mir
+// ignore-compare-mode-nll
+#![feature(box_syntax, rustc_attrs)]
+
+struct A {
+    x: Box<isize>,
+    y: isize,
+}
+
+struct B {
+    x: Box<isize>,
+    y: Box<isize>,
+}
+
+struct C {
+    x: Box<A>,
+    y: isize,
+}
+
+struct D {
+    x: Box<A>,
+    y: Box<isize>,
+}
+
+fn copy_after_move() {
+    let a: Box<_> = box A { x: box 0, y: 1 };
+    let _x = a.x;
+    //[ast]~^ value moved here
+    let _y = a.y; //[ast]~ ERROR use of moved
+    //[ast]~^ move occurs because `a.x` has type `std::boxed::Box<isize>`
+    //[ast]~| value used here after move
+}
+
+fn move_after_move() {
+    let a: Box<_> = box B { x: box 0, y: box 1 };
+    let _x = a.x;
+    //[ast]~^ value moved here
+    let _y = a.y; //[ast]~ ERROR use of moved
+    //[ast]~^ move occurs because `a.x` has type `std::boxed::Box<isize>`
+    //[ast]~| value used here after move
+}
+
+fn borrow_after_move() {
+    let a: Box<_> = box A { x: box 0, y: 1 };
+    let _x = a.x;
+    //[ast]~^ value moved here
+    let _y = &a.y; //[ast]~ ERROR use of moved
+    //[ast]~^ move occurs because `a.x` has type `std::boxed::Box<isize>`
+    //[ast]~| value used here after move
+}
+
+fn move_after_borrow() {
+    let a: Box<_> = box B { x: box 0, y: box 1 };
+    let _x = &a.x;
+    let _y = a.y;
+    //[ast]~^ ERROR cannot move
+    //[ast]~| move out of
+    use_imm(_x);
+}
+fn copy_after_mut_borrow() {
+    let mut a: Box<_> = box A { x: box 0, y: 1 };
+    let _x = &mut a.x;
+    let _y = a.y; //[ast]~ ERROR cannot use
+    use_mut(_x);
+}
+fn move_after_mut_borrow() {
+    let mut a: Box<_> = box B { x: box 0, y: box 1 };
+    let _x = &mut a.x;
+    let _y = a.y;
+    //[ast]~^ ERROR cannot move
+    //[ast]~| move out of
+    use_mut(_x);
+}
+fn borrow_after_mut_borrow() {
+    let mut a: Box<_> = box A { x: box 0, y: 1 };
+    let _x = &mut a.x;
+    let _y = &a.y; //[ast]~ ERROR cannot borrow
+    //[ast]~^ immutable borrow of `a.y` -- which overlaps with `a.x` -- occurs here
+    use_mut(_x);
+}
+fn mut_borrow_after_borrow() {
+    let mut a: Box<_> = box A { x: box 0, y: 1 };
+    let _x = &a.x;
+    let _y = &mut a.y; //[ast]~ ERROR cannot borrow
+    //[ast]~^ mutable borrow of `a.y` -- which overlaps with `a.x` -- occurs here
+    use_imm(_x);
+}
+fn copy_after_move_nested() {
+    let a: Box<_> = box C { x: box A { x: box 0, y: 1 }, y: 2 };
+    let _x = a.x.x;
+    //[ast]~^ value moved here
+    let _y = a.y; //[ast]~ ERROR use of collaterally moved
+    //[ast]~| value used here after move
+}
+
+fn move_after_move_nested() {
+    let a: Box<_> = box D { x: box A { x: box 0, y: 1 }, y: box 2 };
+    let _x = a.x.x;
+    //[ast]~^ value moved here
+    let _y = a.y; //[ast]~ ERROR use of collaterally moved
+    //[ast]~| value used here after move
+}
+
+fn borrow_after_move_nested() {
+    let a: Box<_> = box C { x: box A { x: box 0, y: 1 }, y: 2 };
+    let _x = a.x.x;
+    //[ast]~^ value moved here
+    let _y = &a.y; //[ast]~ ERROR use of collaterally moved
+    //[ast]~| value used here after move
+}
+
+fn move_after_borrow_nested() {
+    let a: Box<_> = box D { x: box A { x: box 0, y: 1 }, y: box 2 };
+    let _x = &a.x.x;
+    //[ast]~^ borrow of `a.x.x` occurs here
+    let _y = a.y;
+    //[ast]~^ ERROR cannot move
+    //[ast]~| move out of
+    use_imm(_x);
+}
+fn copy_after_mut_borrow_nested() {
+    let mut a: Box<_> = box C { x: box A { x: box 0, y: 1 }, y: 2 };
+    let _x = &mut a.x.x;
+    let _y = a.y; //[ast]~ ERROR cannot use
+    use_mut(_x);
+}
+fn move_after_mut_borrow_nested() {
+    let mut a: Box<_> = box D { x: box A { x: box 0, y: 1 }, y: box 2 };
+    let _x = &mut a.x.x;
+    let _y = a.y;
+    //[ast]~^ ERROR cannot move
+    //[ast]~| move out of
+    use_mut(_x);
+}
+fn borrow_after_mut_borrow_nested() {
+    let mut a: Box<_> = box C { x: box A { x: box 0, y: 1 }, y: 2 };
+    let _x = &mut a.x.x;
+    //[ast]~^ mutable borrow occurs here
+    let _y = &a.y; //[ast]~ ERROR cannot borrow
+    //[ast]~^ immutable borrow occurs here
+    use_mut(_x);
+}
+fn mut_borrow_after_borrow_nested() {
+    let mut a: Box<_> = box C { x: box A { x: box 0, y: 1 }, y: 2 };
+    let _x = &a.x.x;
+    //[ast]~^ immutable borrow occurs here
+    let _y = &mut a.y; //[ast]~ ERROR cannot borrow
+    //[ast]~^ mutable borrow occurs here
+    use_imm(_x);
+}
+#[rustc_error]
+fn main() { //[mir]~ ERROR compilation successful
+    copy_after_move();
+    move_after_move();
+    borrow_after_move();
+
+    move_after_borrow();
+
+    copy_after_mut_borrow();
+    move_after_mut_borrow();
+    borrow_after_mut_borrow();
+    mut_borrow_after_borrow();
+
+    copy_after_move_nested();
+    move_after_move_nested();
+    borrow_after_move_nested();
+
+    move_after_borrow_nested();
+
+    copy_after_mut_borrow_nested();
+    move_after_mut_borrow_nested();
+    borrow_after_mut_borrow_nested();
+    mut_borrow_after_borrow_nested();
+}
+
+fn use_mut<T>(_: &mut T) { }
+fn use_imm<T>(_: &T) { }
diff --git a/src/test/ui/borrowck/borrowck-break-uninit-2.nll.stderr b/src/test/ui/borrowck/borrowck-break-uninit-2.nll.stderr
new file mode 100644
index 0000000..e40d8d9
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-break-uninit-2.nll.stderr
@@ -0,0 +1,9 @@
+error[E0381]: borrow of possibly uninitialized variable: `x`
+  --> $DIR/borrowck-break-uninit-2.rs:9:20
+   |
+LL |     println!("{}", x);
+   |                    ^ use of possibly uninitialized `x`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/borrowck-break-uninit-2.rs b/src/test/ui/borrowck/borrowck-break-uninit-2.rs
new file mode 100644
index 0000000..95ccb2e
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-break-uninit-2.rs
@@ -0,0 +1,14 @@
+fn foo() -> isize {
+    let x: isize;
+
+    while 1 != 2  {
+        break;
+        x = 0;
+    }
+
+    println!("{}", x); //~ ERROR use of possibly uninitialized variable: `x`
+
+    return 17;
+}
+
+fn main() { println!("{}", foo()); }
diff --git a/src/test/ui/borrowck/borrowck-break-uninit-2.stderr b/src/test/ui/borrowck/borrowck-break-uninit-2.stderr
new file mode 100644
index 0000000..a6c3dfe
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-break-uninit-2.stderr
@@ -0,0 +1,9 @@
+error[E0381]: use of possibly uninitialized variable: `x`
+  --> $DIR/borrowck-break-uninit-2.rs:9:20
+   |
+LL |     println!("{}", x);
+   |                    ^ use of possibly uninitialized `x`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/borrowck-break-uninit.nll.stderr b/src/test/ui/borrowck/borrowck-break-uninit.nll.stderr
new file mode 100644
index 0000000..bbf9b9f
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-break-uninit.nll.stderr
@@ -0,0 +1,9 @@
+error[E0381]: borrow of possibly uninitialized variable: `x`
+  --> $DIR/borrowck-break-uninit.rs:9:20
+   |
+LL |     println!("{}", x);
+   |                    ^ use of possibly uninitialized `x`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/borrowck-break-uninit.rs b/src/test/ui/borrowck/borrowck-break-uninit.rs
new file mode 100644
index 0000000..827637c
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-break-uninit.rs
@@ -0,0 +1,14 @@
+fn foo() -> isize {
+    let x: isize;
+
+    loop {
+        break;
+        x = 0;
+    }
+
+    println!("{}", x); //~ ERROR use of possibly uninitialized variable: `x`
+
+    return 17;
+}
+
+fn main() { println!("{}", foo()); }
diff --git a/src/test/ui/borrowck/borrowck-break-uninit.stderr b/src/test/ui/borrowck/borrowck-break-uninit.stderr
new file mode 100644
index 0000000..dcb024a
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-break-uninit.stderr
@@ -0,0 +1,9 @@
+error[E0381]: use of possibly uninitialized variable: `x`
+  --> $DIR/borrowck-break-uninit.rs:9:20
+   |
+LL |     println!("{}", x);
+   |                    ^ use of possibly uninitialized `x`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/borrowck-closures-mut-and-imm.ast.nll.stderr b/src/test/ui/borrowck/borrowck-closures-mut-and-imm.ast.nll.stderr
new file mode 100644
index 0000000..aac5fdf6
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-closures-mut-and-imm.ast.nll.stderr
@@ -0,0 +1,116 @@
+error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-closures-mut-and-imm.rs:21:14
+   |
+LL |     let c1 = || x = 4;
+   |              -- - first borrow occurs due to use of `x` in closure
+   |              |
+   |              mutable borrow occurs here
+LL |     let c2 = || x * 5;
+   |              ^^ - second borrow occurs due to use of `x` in closure
+   |              |
+   |              immutable borrow occurs here
+LL |
+LL |     drop(c1);
+   |          -- mutable borrow later used here
+
+error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-closures-mut-and-imm.rs:29:14
+   |
+LL |     let c1 = || set(&mut x);
+   |              --          - first borrow occurs due to use of `x` in closure
+   |              |
+   |              mutable borrow occurs here
+LL |     let c2 = || get(&x);
+   |              ^^      - second borrow occurs due to use of `x` in closure
+   |              |
+   |              immutable borrow occurs here
+LL |
+LL |     drop(c1);
+   |          -- mutable borrow later used here
+
+error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-closures-mut-and-imm.rs:37:14
+   |
+LL |     let c1 = || set(&mut x);
+   |              --          - first borrow occurs due to use of `x` in closure
+   |              |
+   |              mutable borrow occurs here
+LL |     let c2 = || x * 5;
+   |              ^^ - second borrow occurs due to use of `x` in closure
+   |              |
+   |              immutable borrow occurs here
+LL |
+LL |     drop(c1);
+   |          -- mutable borrow later used here
+
+error[E0506]: cannot assign to `x` because it is borrowed
+  --> $DIR/borrowck-closures-mut-and-imm.rs:45:5
+   |
+LL |     let c2 = || x * 5;
+   |              -- - borrow occurs due to use in closure
+   |              |
+   |              borrow of `x` occurs here
+LL |     x = 5;
+   |     ^^^^^ assignment to borrowed `x` occurs here
+LL |
+LL |     drop(c2);
+   |          -- borrow later used here
+
+error[E0506]: cannot assign to `x` because it is borrowed
+  --> $DIR/borrowck-closures-mut-and-imm.rs:53:5
+   |
+LL |     let c1 = || get(&x);
+   |              --      - borrow occurs due to use in closure
+   |              |
+   |              borrow of `x` occurs here
+LL |     x = 5;
+   |     ^^^^^ assignment to borrowed `x` occurs here
+LL |
+LL |     drop(c1);
+   |          -- borrow later used here
+
+error[E0506]: cannot assign to `*x` because it is borrowed
+  --> $DIR/borrowck-closures-mut-and-imm.rs:61:5
+   |
+LL |     let c1 = || get(&*x);
+   |              --       - borrow occurs due to use in closure
+   |              |
+   |              borrow of `*x` occurs here
+LL |     *x = 5;
+   |     ^^^^^^ assignment to borrowed `*x` occurs here
+LL |
+LL |     drop(c1);
+   |          -- borrow later used here
+
+error[E0506]: cannot assign to `*x.f` because it is borrowed
+  --> $DIR/borrowck-closures-mut-and-imm.rs:73:5
+   |
+LL |     let c1 = || get(&*x.f);
+   |              --       - borrow occurs due to use in closure
+   |              |
+   |              borrow of `*x.f` occurs here
+LL |     *x.f = 5;
+   |     ^^^^^^^^ assignment to borrowed `*x.f` occurs here
+LL |
+LL |     drop(c1);
+   |          -- borrow later used here
+
+error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-closures-mut-and-imm.rs:85:14
+   |
+LL |     let c1 = || get(&*x.f);
+   |              --       - first borrow occurs due to use of `x` in closure
+   |              |
+   |              immutable borrow occurs here
+LL |     let c2 = || *x.f = 5;
+   |              ^^  - second borrow occurs due to use of `x` in closure
+   |              |
+   |              mutable borrow occurs here
+LL |
+LL |     drop(c1);
+   |          -- immutable borrow later used here
+
+error: aborting due to 8 previous errors
+
+Some errors occurred: E0502, E0506.
+For more information about an error, try `rustc --explain E0502`.
diff --git a/src/test/ui/borrowck/borrowck-closures-mut-and-imm.ast.stderr b/src/test/ui/borrowck/borrowck-closures-mut-and-imm.ast.stderr
new file mode 100644
index 0000000..d672d0c
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-closures-mut-and-imm.ast.stderr
@@ -0,0 +1,96 @@
+error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-closures-mut-and-imm.rs:21:14
+   |
+LL |     let c1 = || x = 4;
+   |              -- - previous borrow occurs due to use of `x` in closure
+   |              |
+   |              mutable borrow occurs here
+LL |     let c2 = || x * 5;
+   |              ^^ - borrow occurs due to use of `x` in closure
+   |              |
+   |              immutable borrow occurs here
+...
+LL | }
+   | - mutable borrow ends here
+
+error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-closures-mut-and-imm.rs:29:14
+   |
+LL |     let c1 = || set(&mut x);
+   |              --          - previous borrow occurs due to use of `x` in closure
+   |              |
+   |              mutable borrow occurs here
+LL |     let c2 = || get(&x);
+   |              ^^      - borrow occurs due to use of `x` in closure
+   |              |
+   |              immutable borrow occurs here
+...
+LL | }
+   | - mutable borrow ends here
+
+error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-closures-mut-and-imm.rs:37:14
+   |
+LL |     let c1 = || set(&mut x);
+   |              --          - previous borrow occurs due to use of `x` in closure
+   |              |
+   |              mutable borrow occurs here
+LL |     let c2 = || x * 5;
+   |              ^^ - borrow occurs due to use of `x` in closure
+   |              |
+   |              immutable borrow occurs here
+...
+LL | }
+   | - mutable borrow ends here
+
+error[E0506]: cannot assign to `x` because it is borrowed
+  --> $DIR/borrowck-closures-mut-and-imm.rs:45:5
+   |
+LL |     let c2 = || x * 5;
+   |              -- borrow of `x` occurs here
+LL |     x = 5;
+   |     ^^^^^ assignment to borrowed `x` occurs here
+
+error[E0506]: cannot assign to `x` because it is borrowed
+  --> $DIR/borrowck-closures-mut-and-imm.rs:53:5
+   |
+LL |     let c1 = || get(&x);
+   |              -- borrow of `x` occurs here
+LL |     x = 5;
+   |     ^^^^^ assignment to borrowed `x` occurs here
+
+error[E0506]: cannot assign to `*x` because it is borrowed
+  --> $DIR/borrowck-closures-mut-and-imm.rs:61:5
+   |
+LL |     let c1 = || get(&*x);
+   |              -- borrow of `*x` occurs here
+LL |     *x = 5;
+   |     ^^^^^^ assignment to borrowed `*x` occurs here
+
+error[E0506]: cannot assign to `*x.f` because it is borrowed
+  --> $DIR/borrowck-closures-mut-and-imm.rs:73:5
+   |
+LL |     let c1 = || get(&*x.f);
+   |              -- borrow of `*x.f` occurs here
+LL |     *x.f = 5;
+   |     ^^^^^^^^ assignment to borrowed `*x.f` occurs here
+
+error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-closures-mut-and-imm.rs:85:14
+   |
+LL |     let c1 = || get(&*x.f);
+   |              --       - previous borrow occurs due to use of `x` in closure
+   |              |
+   |              immutable borrow occurs here
+LL |     let c2 = || *x.f = 5;
+   |              ^^  - borrow occurs due to use of `x` in closure
+   |              |
+   |              mutable borrow occurs here
+...
+LL | }
+   | - immutable borrow ends here
+
+error: aborting due to 8 previous errors
+
+Some errors occurred: E0502, E0506.
+For more information about an error, try `rustc --explain E0502`.
diff --git a/src/test/ui/borrowck/borrowck-closures-mut-and-imm.mir.stderr b/src/test/ui/borrowck/borrowck-closures-mut-and-imm.mir.stderr
new file mode 100644
index 0000000..aac5fdf6
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-closures-mut-and-imm.mir.stderr
@@ -0,0 +1,116 @@
+error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-closures-mut-and-imm.rs:21:14
+   |
+LL |     let c1 = || x = 4;
+   |              -- - first borrow occurs due to use of `x` in closure
+   |              |
+   |              mutable borrow occurs here
+LL |     let c2 = || x * 5;
+   |              ^^ - second borrow occurs due to use of `x` in closure
+   |              |
+   |              immutable borrow occurs here
+LL |
+LL |     drop(c1);
+   |          -- mutable borrow later used here
+
+error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-closures-mut-and-imm.rs:29:14
+   |
+LL |     let c1 = || set(&mut x);
+   |              --          - first borrow occurs due to use of `x` in closure
+   |              |
+   |              mutable borrow occurs here
+LL |     let c2 = || get(&x);
+   |              ^^      - second borrow occurs due to use of `x` in closure
+   |              |
+   |              immutable borrow occurs here
+LL |
+LL |     drop(c1);
+   |          -- mutable borrow later used here
+
+error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-closures-mut-and-imm.rs:37:14
+   |
+LL |     let c1 = || set(&mut x);
+   |              --          - first borrow occurs due to use of `x` in closure
+   |              |
+   |              mutable borrow occurs here
+LL |     let c2 = || x * 5;
+   |              ^^ - second borrow occurs due to use of `x` in closure
+   |              |
+   |              immutable borrow occurs here
+LL |
+LL |     drop(c1);
+   |          -- mutable borrow later used here
+
+error[E0506]: cannot assign to `x` because it is borrowed
+  --> $DIR/borrowck-closures-mut-and-imm.rs:45:5
+   |
+LL |     let c2 = || x * 5;
+   |              -- - borrow occurs due to use in closure
+   |              |
+   |              borrow of `x` occurs here
+LL |     x = 5;
+   |     ^^^^^ assignment to borrowed `x` occurs here
+LL |
+LL |     drop(c2);
+   |          -- borrow later used here
+
+error[E0506]: cannot assign to `x` because it is borrowed
+  --> $DIR/borrowck-closures-mut-and-imm.rs:53:5
+   |
+LL |     let c1 = || get(&x);
+   |              --      - borrow occurs due to use in closure
+   |              |
+   |              borrow of `x` occurs here
+LL |     x = 5;
+   |     ^^^^^ assignment to borrowed `x` occurs here
+LL |
+LL |     drop(c1);
+   |          -- borrow later used here
+
+error[E0506]: cannot assign to `*x` because it is borrowed
+  --> $DIR/borrowck-closures-mut-and-imm.rs:61:5
+   |
+LL |     let c1 = || get(&*x);
+   |              --       - borrow occurs due to use in closure
+   |              |
+   |              borrow of `*x` occurs here
+LL |     *x = 5;
+   |     ^^^^^^ assignment to borrowed `*x` occurs here
+LL |
+LL |     drop(c1);
+   |          -- borrow later used here
+
+error[E0506]: cannot assign to `*x.f` because it is borrowed
+  --> $DIR/borrowck-closures-mut-and-imm.rs:73:5
+   |
+LL |     let c1 = || get(&*x.f);
+   |              --       - borrow occurs due to use in closure
+   |              |
+   |              borrow of `*x.f` occurs here
+LL |     *x.f = 5;
+   |     ^^^^^^^^ assignment to borrowed `*x.f` occurs here
+LL |
+LL |     drop(c1);
+   |          -- borrow later used here
+
+error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-closures-mut-and-imm.rs:85:14
+   |
+LL |     let c1 = || get(&*x.f);
+   |              --       - first borrow occurs due to use of `x` in closure
+   |              |
+   |              immutable borrow occurs here
+LL |     let c2 = || *x.f = 5;
+   |              ^^  - second borrow occurs due to use of `x` in closure
+   |              |
+   |              mutable borrow occurs here
+LL |
+LL |     drop(c1);
+   |          -- immutable borrow later used here
+
+error: aborting due to 8 previous errors
+
+Some errors occurred: E0502, E0506.
+For more information about an error, try `rustc --explain E0502`.
diff --git a/src/test/ui/borrowck/borrowck-closures-mut-and-imm.rs b/src/test/ui/borrowck/borrowck-closures-mut-and-imm.rs
new file mode 100644
index 0000000..3a802bc
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-closures-mut-and-imm.rs
@@ -0,0 +1,91 @@
+// Tests that two closures cannot simultaneously have mutable
+// and immutable access to the variable. Issue #6801.
+
+// ignore-tidy-linelength
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+#![feature(box_syntax)]
+
+fn get(x: &isize) -> isize {
+    *x
+}
+
+fn set(x: &mut isize) {
+    *x = 4;
+}
+
+fn a() {
+    let mut x = 3;
+    let c1 = || x = 4;
+    let c2 = || x * 5; //[ast]~ ERROR cannot borrow `x`
+    //[mir]~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable
+    drop(c1);
+}
+
+fn b() {
+    let mut x = 3;
+    let c1 = || set(&mut x);
+    let c2 = || get(&x); //[ast]~ ERROR cannot borrow `x`
+                         //[mir]~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable
+    drop(c1);
+}
+
+fn c() {
+    let mut x = 3;
+    let c1 = || set(&mut x);
+    let c2 = || x * 5; //[ast]~ ERROR cannot borrow `x`
+                       //[mir]~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable
+    drop(c1);
+}
+
+fn d() {
+    let mut x = 3;
+    let c2 = || x * 5;
+    x = 5; //[ast]~ ERROR cannot assign
+           //[mir]~^ ERROR cannot assign to `x` because it is borrowed
+    drop(c2);
+}
+
+fn e() {
+    let mut x = 3;
+    let c1 = || get(&x);
+    x = 5; //[ast]~ ERROR cannot assign
+           //[mir]~^ ERROR cannot assign to `x` because it is borrowed
+    drop(c1);
+}
+
+fn f() {
+    let mut x: Box<_> = box 3;
+    let c1 = || get(&*x);
+    *x = 5; //[ast]~ ERROR cannot assign to `*x`
+            //[mir]~^ ERROR cannot assign to `*x` because it is borrowed
+    drop(c1);
+}
+
+fn g() {
+    struct Foo {
+        f: Box<isize>
+    }
+
+    let mut x: Box<_> = box Foo { f: box 3 };
+    let c1 = || get(&*x.f);
+    *x.f = 5; //[ast]~ ERROR cannot assign to `*x.f`
+              //[mir]~^ ERROR cannot assign to `*x.f` because it is borrowed
+    drop(c1);
+}
+
+fn h() {
+    struct Foo {
+        f: Box<isize>
+    }
+
+    let mut x: Box<_> = box Foo { f: box 3 };
+    let c1 = || get(&*x.f);
+    let c2 = || *x.f = 5; //[ast]~ ERROR cannot borrow `x` as mutable
+                          //[mir]~^ ERROR cannot borrow `x` as mutable because it is also borrowed as immutable
+    drop(c1);
+}
+
+fn main() {
+}
diff --git a/src/test/ui/borrowck/borrowck-closures-mut-of-imm.nll.stderr b/src/test/ui/borrowck/borrowck-closures-mut-of-imm.nll.stderr
new file mode 100644
index 0000000..0064417
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-closures-mut-of-imm.nll.stderr
@@ -0,0 +1,32 @@
+error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
+  --> $DIR/borrowck-closures-mut-of-imm.rs:13:25
+   |
+LL |     let mut c1 = || set(&mut *x);
+   |                         ^^^^^^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
+  --> $DIR/borrowck-closures-mut-of-imm.rs:15:25
+   |
+LL |     let mut c2 = || set(&mut *x);
+   |                         ^^^^^^^ cannot borrow as mutable
+
+error[E0524]: two closures require unique access to `x` at the same time
+  --> $DIR/borrowck-closures-mut-of-imm.rs:15:18
+   |
+LL |     let mut c1 = || set(&mut *x);
+   |                  --           - first borrow occurs due to use of `x` in closure
+   |                  |
+   |                  first closure is constructed here
+LL |
+LL |     let mut c2 = || set(&mut *x);
+   |                  ^^           - second borrow occurs due to use of `x` in closure
+   |                  |
+   |                  second closure is constructed here
+...
+LL |     c2(); c1();
+   |           -- first borrow later used here
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0524, E0596.
+For more information about an error, try `rustc --explain E0524`.
diff --git a/src/test/ui/borrowck/borrowck-closures-mut-of-imm.rs b/src/test/ui/borrowck/borrowck-closures-mut-of-imm.rs
new file mode 100644
index 0000000..24e06e3
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-closures-mut-of-imm.rs
@@ -0,0 +1,22 @@
+// Tests that two closures cannot simultaneously have mutable
+// and immutable access to the variable. Issue #6801.
+
+fn get(x: &isize) -> isize {
+    *x
+}
+
+fn set(x: &mut isize) {
+    *x = 4;
+}
+
+fn a(x: &isize) {
+    let mut c1 = || set(&mut *x);
+    //~^ ERROR cannot borrow
+    let mut c2 = || set(&mut *x);
+    //~^ ERROR cannot borrow
+    //~| ERROR two closures require unique access to `x` at the same time
+    c2(); c1();
+}
+
+fn main() {
+}
diff --git a/src/test/ui/borrowck/borrowck-closures-mut-of-imm.stderr b/src/test/ui/borrowck/borrowck-closures-mut-of-imm.stderr
new file mode 100644
index 0000000..2f7c6a1
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-closures-mut-of-imm.stderr
@@ -0,0 +1,32 @@
+error[E0524]: two closures require unique access to `x` at the same time
+  --> $DIR/borrowck-closures-mut-of-imm.rs:15:18
+   |
+LL |     let mut c1 = || set(&mut *x);
+   |                  --           - previous borrow occurs due to use of `x` in closure
+   |                  |
+   |                  first closure is constructed here
+LL |
+LL |     let mut c2 = || set(&mut *x);
+   |                  ^^           - borrow occurs due to use of `x` in closure
+   |                  |
+   |                  second closure is constructed here
+...
+LL | }
+   | - borrow from first closure ends here
+
+error[E0596]: cannot borrow immutable borrowed content `***x` as mutable
+  --> $DIR/borrowck-closures-mut-of-imm.rs:13:30
+   |
+LL |     let mut c1 = || set(&mut *x);
+   |                              ^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow immutable borrowed content `***x` as mutable
+  --> $DIR/borrowck-closures-mut-of-imm.rs:15:30
+   |
+LL |     let mut c2 = || set(&mut *x);
+   |                              ^^ cannot borrow as mutable
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0524, E0596.
+For more information about an error, try `rustc --explain E0524`.
diff --git a/src/test/ui/borrowck/borrowck-closures-mut-of-mut.nll.stderr b/src/test/ui/borrowck/borrowck-closures-mut-of-mut.nll.stderr
new file mode 100644
index 0000000..471173e
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-closures-mut-of-mut.nll.stderr
@@ -0,0 +1,18 @@
+error[E0524]: two closures require unique access to `x` at the same time
+  --> $DIR/borrowck-closures-mut-of-mut.rs:14:18
+   |
+LL |     let mut c1 = || set(&mut *x);
+   |                  --           - first borrow occurs due to use of `x` in closure
+   |                  |
+   |                  first closure is constructed here
+LL |     let mut c2 = || set(&mut *x);
+   |                  ^^           - second borrow occurs due to use of `x` in closure
+   |                  |
+   |                  second closure is constructed here
+LL |
+LL |     c2(); c1();
+   |           -- first borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0524`.
diff --git a/src/test/ui/borrowck/borrowck-closures-mut-of-mut.rs b/src/test/ui/borrowck/borrowck-closures-mut-of-mut.rs
new file mode 100644
index 0000000..50c6f2c
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-closures-mut-of-mut.rs
@@ -0,0 +1,20 @@
+// Tests that two closures cannot simultaneously both have mutable
+// access to the variable. Related to issue #6801.
+
+fn get(x: &isize) -> isize {
+    *x
+}
+
+fn set(x: &mut isize) {
+    *x = 4;
+}
+
+fn a(x: &mut isize) {
+    let mut c1 = || set(&mut *x);
+    let mut c2 = || set(&mut *x);
+    //~^ ERROR two closures require unique access to `x` at the same time
+    c2(); c1();
+}
+
+fn main() {
+}
diff --git a/src/test/ui/borrowck/borrowck-closures-mut-of-mut.stderr b/src/test/ui/borrowck/borrowck-closures-mut-of-mut.stderr
new file mode 100644
index 0000000..2c558771
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-closures-mut-of-mut.stderr
@@ -0,0 +1,18 @@
+error[E0524]: two closures require unique access to `x` at the same time
+  --> $DIR/borrowck-closures-mut-of-mut.rs:14:18
+   |
+LL |     let mut c1 = || set(&mut *x);
+   |                  --           - previous borrow occurs due to use of `x` in closure
+   |                  |
+   |                  first closure is constructed here
+LL |     let mut c2 = || set(&mut *x);
+   |                  ^^           - borrow occurs due to use of `x` in closure
+   |                  |
+   |                  second closure is constructed here
+...
+LL | }
+   | - borrow from first closure ends here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0524`.
diff --git a/src/test/ui/borrowck/borrowck-closures-two-mut-fail.nll.stderr b/src/test/ui/borrowck/borrowck-closures-two-mut-fail.nll.stderr
new file mode 100644
index 0000000..07f477d
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-closures-two-mut-fail.nll.stderr
@@ -0,0 +1,75 @@
+error[E0499]: cannot borrow `x` as mutable more than once at a time
+  --> $DIR/borrowck-closures-two-mut-fail.rs:16:24
+   |
+LL |     let c1 = to_fn_mut(|| x = 4);
+   |                        -- - first borrow occurs due to use of `x` in closure
+   |                        |
+   |                        first mutable borrow occurs here
+LL |     let c2 = to_fn_mut(|| x = 5);
+   |                        ^^ - second borrow occurs due to use of `x` in closure
+   |                        |
+   |                        second mutable borrow occurs here
+LL |     c1;
+   |     -- first borrow later used here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time
+  --> $DIR/borrowck-closures-two-mut-fail.rs:27:24
+   |
+LL |     let c1 = to_fn_mut(|| set(&mut x));
+   |                        --          - first borrow occurs due to use of `x` in closure
+   |                        |
+   |                        first mutable borrow occurs here
+LL |     let c2 = to_fn_mut(|| set(&mut x));
+   |                        ^^          - second borrow occurs due to use of `x` in closure
+   |                        |
+   |                        second mutable borrow occurs here
+LL |     c1;
+   |     -- first borrow later used here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time
+  --> $DIR/borrowck-closures-two-mut-fail.rs:34:24
+   |
+LL |     let c1 = to_fn_mut(|| x = 5);
+   |                        -- - first borrow occurs due to use of `x` in closure
+   |                        |
+   |                        first mutable borrow occurs here
+LL |     let c2 = to_fn_mut(|| set(&mut x));
+   |                        ^^          - second borrow occurs due to use of `x` in closure
+   |                        |
+   |                        second mutable borrow occurs here
+LL |     c1;
+   |     -- first borrow later used here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time
+  --> $DIR/borrowck-closures-two-mut-fail.rs:41:24
+   |
+LL |     let c1 = to_fn_mut(|| x = 5);
+   |                        -- - first borrow occurs due to use of `x` in closure
+   |                        |
+   |                        first mutable borrow occurs here
+LL |     let c2 = to_fn_mut(|| { let _y = to_fn_mut(|| set(&mut x)); }); // (nested closure)
+   |                        ^^                                  - second borrow occurs due to use of `x` in closure
+   |                        |
+   |                        second mutable borrow occurs here
+LL |
+LL |     c1;
+   |     -- first borrow later used here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time
+  --> $DIR/borrowck-closures-two-mut-fail.rs:53:24
+   |
+LL |     let c1 = to_fn_mut(|| set(&mut *x.f));
+   |                        --           - first borrow occurs due to use of `x` in closure
+   |                        |
+   |                        first mutable borrow occurs here
+LL |     let c2 = to_fn_mut(|| set(&mut *x.f));
+   |                        ^^           - second borrow occurs due to use of `x` in closure
+   |                        |
+   |                        second mutable borrow occurs here
+LL |
+LL |     c1;
+   |     -- first borrow later used here
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/borrowck/borrowck-closures-two-mut-fail.rs b/src/test/ui/borrowck/borrowck-closures-two-mut-fail.rs
new file mode 100644
index 0000000..2a17572
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-closures-two-mut-fail.rs
@@ -0,0 +1,59 @@
+// Tests that two closures cannot simultaneously have mutable
+// access to the variable, whether that mutable access be used
+// for direct assignment or for taking mutable ref. Issue #6801.
+
+#![feature(box_syntax)]
+
+
+
+
+
+fn to_fn_mut<F: FnMut()>(f: F) -> F { f }
+
+fn a() {
+    let mut x = 3;
+    let c1 = to_fn_mut(|| x = 4);
+    let c2 = to_fn_mut(|| x = 5); //~ ERROR cannot borrow `x` as mutable more than once
+    c1;
+}
+
+fn set(x: &mut isize) {
+    *x = 4;
+}
+
+fn b() {
+    let mut x = 3;
+    let c1 = to_fn_mut(|| set(&mut x));
+    let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as mutable more than once
+    c1;
+}
+
+fn c() {
+    let mut x = 3;
+    let c1 = to_fn_mut(|| x = 5);
+    let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as mutable more than once
+    c1;
+}
+
+fn d() {
+    let mut x = 3;
+    let c1 = to_fn_mut(|| x = 5);
+    let c2 = to_fn_mut(|| { let _y = to_fn_mut(|| set(&mut x)); }); // (nested closure)
+    //~^ ERROR cannot borrow `x` as mutable more than once
+    c1;
+}
+
+fn g() {
+    struct Foo {
+        f: Box<isize>
+    }
+
+    let mut x: Box<_> = box Foo { f: box 3 };
+    let c1 = to_fn_mut(|| set(&mut *x.f));
+    let c2 = to_fn_mut(|| set(&mut *x.f));
+    //~^ ERROR cannot borrow `x` as mutable more than once
+    c1;
+}
+
+fn main() {
+}
diff --git a/src/test/ui/borrowck/borrowck-closures-two-mut-fail.stderr b/src/test/ui/borrowck/borrowck-closures-two-mut-fail.stderr
new file mode 100644
index 0000000..7399f83
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-closures-two-mut-fail.stderr
@@ -0,0 +1,78 @@
+error[E0499]: cannot borrow `x` as mutable more than once at a time
+  --> $DIR/borrowck-closures-two-mut-fail.rs:16:24
+   |
+LL |     let c1 = to_fn_mut(|| x = 4);
+   |                        -- - previous borrow occurs due to use of `x` in closure
+   |                        |
+   |                        first mutable borrow occurs here
+LL |     let c2 = to_fn_mut(|| x = 5);
+   |                        ^^ - borrow occurs due to use of `x` in closure
+   |                        |
+   |                        second mutable borrow occurs here
+LL |     c1;
+LL | }
+   | - first borrow ends here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time
+  --> $DIR/borrowck-closures-two-mut-fail.rs:27:24
+   |
+LL |     let c1 = to_fn_mut(|| set(&mut x));
+   |                        --          - previous borrow occurs due to use of `x` in closure
+   |                        |
+   |                        first mutable borrow occurs here
+LL |     let c2 = to_fn_mut(|| set(&mut x));
+   |                        ^^          - borrow occurs due to use of `x` in closure
+   |                        |
+   |                        second mutable borrow occurs here
+LL |     c1;
+LL | }
+   | - first borrow ends here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time
+  --> $DIR/borrowck-closures-two-mut-fail.rs:34:24
+   |
+LL |     let c1 = to_fn_mut(|| x = 5);
+   |                        -- - previous borrow occurs due to use of `x` in closure
+   |                        |
+   |                        first mutable borrow occurs here
+LL |     let c2 = to_fn_mut(|| set(&mut x));
+   |                        ^^          - borrow occurs due to use of `x` in closure
+   |                        |
+   |                        second mutable borrow occurs here
+LL |     c1;
+LL | }
+   | - first borrow ends here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time
+  --> $DIR/borrowck-closures-two-mut-fail.rs:41:24
+   |
+LL |     let c1 = to_fn_mut(|| x = 5);
+   |                        -- - previous borrow occurs due to use of `x` in closure
+   |                        |
+   |                        first mutable borrow occurs here
+LL |     let c2 = to_fn_mut(|| { let _y = to_fn_mut(|| set(&mut x)); }); // (nested closure)
+   |                        ^^                                  - borrow occurs due to use of `x` in closure
+   |                        |
+   |                        second mutable borrow occurs here
+...
+LL | }
+   | - first borrow ends here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time
+  --> $DIR/borrowck-closures-two-mut-fail.rs:53:24
+   |
+LL |     let c1 = to_fn_mut(|| set(&mut *x.f));
+   |                        --           - previous borrow occurs due to use of `x` in closure
+   |                        |
+   |                        first mutable borrow occurs here
+LL |     let c2 = to_fn_mut(|| set(&mut *x.f));
+   |                        ^^           - borrow occurs due to use of `x` in closure
+   |                        |
+   |                        second mutable borrow occurs here
+...
+LL | }
+   | - first borrow ends here
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/borrowck/borrowck-closures-two-mut.rs b/src/test/ui/borrowck/borrowck-closures-two-mut.rs
new file mode 100644
index 0000000..1fced98
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-closures-two-mut.rs
@@ -0,0 +1,62 @@
+// Tests that two closures cannot simultaneously have mutable
+// access to the variable, whether that mutable access be used
+// for direct assignment or for taking mutable ref. Issue #6801.
+
+// compile-flags: -Z borrowck=compare
+
+#![feature(box_syntax)]
+
+fn to_fn_mut<F: FnMut()>(f: F) -> F { f }
+
+fn a() {
+    let mut x = 3;
+    let c1 = to_fn_mut(|| x = 4);
+    let c2 = to_fn_mut(|| x = 5); //~ ERROR cannot borrow `x` as mutable more than once
+    //~| ERROR cannot borrow `x` as mutable more than once
+    drop((c1, c2));
+}
+
+fn set(x: &mut isize) {
+    *x = 4;
+}
+
+fn b() {
+    let mut x = 3;
+    let c1 = to_fn_mut(|| set(&mut x));
+    let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as mutable more than once
+    //~| ERROR cannot borrow `x` as mutable more than once
+    drop((c1, c2));
+}
+
+fn c() {
+    let mut x = 3;
+    let c1 = to_fn_mut(|| x = 5);
+    let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as mutable more than once
+    //~| ERROR cannot borrow `x` as mutable more than once
+    drop((c1, c2));
+}
+
+fn d() {
+    let mut x = 3;
+    let c1 = to_fn_mut(|| x = 5);
+    let c2 = to_fn_mut(|| { let _y = to_fn_mut(|| set(&mut x)); }); // (nested closure)
+    //~^ ERROR cannot borrow `x` as mutable more than once
+    //~| ERROR cannot borrow `x` as mutable more than once
+    drop((c1, c2));
+}
+
+fn g() {
+    struct Foo {
+        f: Box<isize>
+    }
+
+    let mut x: Box<_> = box Foo { f: box 3 };
+    let c1 = to_fn_mut(|| set(&mut *x.f));
+    let c2 = to_fn_mut(|| set(&mut *x.f));
+    //~^ ERROR cannot borrow `x` as mutable more than once
+    //~| ERROR cannot borrow `x` as mutable more than once
+    drop((c1, c2));
+}
+
+fn main() {
+}
diff --git a/src/test/ui/borrowck/borrowck-closures-two-mut.stderr b/src/test/ui/borrowck/borrowck-closures-two-mut.stderr
new file mode 100644
index 0000000..e881201
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-closures-two-mut.stderr
@@ -0,0 +1,153 @@
+error[E0499]: cannot borrow `x` as mutable more than once at a time (Ast)
+  --> $DIR/borrowck-closures-two-mut.rs:14:24
+   |
+LL |     let c1 = to_fn_mut(|| x = 4);
+   |                        -- - previous borrow occurs due to use of `x` in closure
+   |                        |
+   |                        first mutable borrow occurs here
+LL |     let c2 = to_fn_mut(|| x = 5);
+   |                        ^^ - borrow occurs due to use of `x` in closure
+   |                        |
+   |                        second mutable borrow occurs here
+...
+LL | }
+   | - first borrow ends here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time (Ast)
+  --> $DIR/borrowck-closures-two-mut.rs:26:24
+   |
+LL |     let c1 = to_fn_mut(|| set(&mut x));
+   |                        --          - previous borrow occurs due to use of `x` in closure
+   |                        |
+   |                        first mutable borrow occurs here
+LL |     let c2 = to_fn_mut(|| set(&mut x));
+   |                        ^^          - borrow occurs due to use of `x` in closure
+   |                        |
+   |                        second mutable borrow occurs here
+...
+LL | }
+   | - first borrow ends here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time (Ast)
+  --> $DIR/borrowck-closures-two-mut.rs:34:24
+   |
+LL |     let c1 = to_fn_mut(|| x = 5);
+   |                        -- - previous borrow occurs due to use of `x` in closure
+   |                        |
+   |                        first mutable borrow occurs here
+LL |     let c2 = to_fn_mut(|| set(&mut x));
+   |                        ^^          - borrow occurs due to use of `x` in closure
+   |                        |
+   |                        second mutable borrow occurs here
+...
+LL | }
+   | - first borrow ends here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time (Ast)
+  --> $DIR/borrowck-closures-two-mut.rs:42:24
+   |
+LL |     let c1 = to_fn_mut(|| x = 5);
+   |                        -- - previous borrow occurs due to use of `x` in closure
+   |                        |
+   |                        first mutable borrow occurs here
+LL |     let c2 = to_fn_mut(|| { let _y = to_fn_mut(|| set(&mut x)); }); // (nested closure)
+   |                        ^^                                  - borrow occurs due to use of `x` in closure
+   |                        |
+   |                        second mutable borrow occurs here
+...
+LL | }
+   | - first borrow ends here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time (Ast)
+  --> $DIR/borrowck-closures-two-mut.rs:55:24
+   |
+LL |     let c1 = to_fn_mut(|| set(&mut *x.f));
+   |                        --           - previous borrow occurs due to use of `x` in closure
+   |                        |
+   |                        first mutable borrow occurs here
+LL |     let c2 = to_fn_mut(|| set(&mut *x.f));
+   |                        ^^           - borrow occurs due to use of `x` in closure
+   |                        |
+   |                        second mutable borrow occurs here
+...
+LL | }
+   | - first borrow ends here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time (Mir)
+  --> $DIR/borrowck-closures-two-mut.rs:14:24
+   |
+LL |     let c1 = to_fn_mut(|| x = 4);
+   |                        -- - first borrow occurs due to use of `x` in closure
+   |                        |
+   |                        first mutable borrow occurs here
+LL |     let c2 = to_fn_mut(|| x = 5);
+   |                        ^^ - second borrow occurs due to use of `x` in closure
+   |                        |
+   |                        second mutable borrow occurs here
+LL |
+LL |     drop((c1, c2));
+   |           -- first borrow later used here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time (Mir)
+  --> $DIR/borrowck-closures-two-mut.rs:26:24
+   |
+LL |     let c1 = to_fn_mut(|| set(&mut x));
+   |                        --          - first borrow occurs due to use of `x` in closure
+   |                        |
+   |                        first mutable borrow occurs here
+LL |     let c2 = to_fn_mut(|| set(&mut x));
+   |                        ^^          - second borrow occurs due to use of `x` in closure
+   |                        |
+   |                        second mutable borrow occurs here
+LL |
+LL |     drop((c1, c2));
+   |           -- first borrow later used here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time (Mir)
+  --> $DIR/borrowck-closures-two-mut.rs:34:24
+   |
+LL |     let c1 = to_fn_mut(|| x = 5);
+   |                        -- - first borrow occurs due to use of `x` in closure
+   |                        |
+   |                        first mutable borrow occurs here
+LL |     let c2 = to_fn_mut(|| set(&mut x));
+   |                        ^^          - second borrow occurs due to use of `x` in closure
+   |                        |
+   |                        second mutable borrow occurs here
+LL |
+LL |     drop((c1, c2));
+   |           -- first borrow later used here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time (Mir)
+  --> $DIR/borrowck-closures-two-mut.rs:42:24
+   |
+LL |     let c1 = to_fn_mut(|| x = 5);
+   |                        -- - first borrow occurs due to use of `x` in closure
+   |                        |
+   |                        first mutable borrow occurs here
+LL |     let c2 = to_fn_mut(|| { let _y = to_fn_mut(|| set(&mut x)); }); // (nested closure)
+   |                        ^^                                  - second borrow occurs due to use of `x` in closure
+   |                        |
+   |                        second mutable borrow occurs here
+...
+LL |     drop((c1, c2));
+   |           -- first borrow later used here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time (Mir)
+  --> $DIR/borrowck-closures-two-mut.rs:55:24
+   |
+LL |     let c1 = to_fn_mut(|| set(&mut *x.f));
+   |                        --           - first borrow occurs due to use of `x` in closure
+   |                        |
+   |                        first mutable borrow occurs here
+LL |     let c2 = to_fn_mut(|| set(&mut *x.f));
+   |                        ^^           - second borrow occurs due to use of `x` in closure
+   |                        |
+   |                        second mutable borrow occurs here
+...
+LL |     drop((c1, c2));
+   |           -- first borrow later used here
+
+error: aborting due to 10 previous errors
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/borrowck/borrowck-closures-unique-imm.nll.stderr b/src/test/ui/borrowck/borrowck-closures-unique-imm.nll.stderr
new file mode 100644
index 0000000..b8bbb31
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-closures-unique-imm.nll.stderr
@@ -0,0 +1,13 @@
+error[E0502]: cannot borrow `this.x` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-closures-unique-imm.rs:11:9
+   |
+LL |         let p = &this.x;
+   |                 ------- immutable borrow occurs here
+LL |         &mut this.x;
+   |         ^^^^^^^^^^^ mutable borrow occurs here
+LL |         p.use_ref();
+   |         - immutable borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/borrowck/borrowck-closures-unique-imm.rs b/src/test/ui/borrowck/borrowck-closures-unique-imm.rs
new file mode 100644
index 0000000..0dd0047
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-closures-unique-imm.rs
@@ -0,0 +1,18 @@
+struct Foo {
+    x: isize,
+}
+
+pub fn main() {
+    let mut this = &mut Foo {
+        x: 1,
+    };
+    let mut r = || {
+        let p = &this.x;
+        &mut this.x; //~ ERROR cannot borrow
+        p.use_ref();
+    };
+    r()
+}
+
+trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { }  }
+impl<T> Fake for T { }
diff --git a/src/test/ui/borrowck/borrowck-closures-unique-imm.stderr b/src/test/ui/borrowck/borrowck-closures-unique-imm.stderr
new file mode 100644
index 0000000..3cdc9b9
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-closures-unique-imm.stderr
@@ -0,0 +1,14 @@
+error[E0502]: cannot borrow `this.x` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-closures-unique-imm.rs:11:14
+   |
+LL |         let p = &this.x;
+   |                  ------ immutable borrow occurs here
+LL |         &mut this.x;
+   |              ^^^^^^ mutable borrow occurs here
+LL |         p.use_ref();
+LL |     };
+   |     - immutable borrow ends here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/borrowck/borrowck-closures-unique.nll.stderr b/src/test/ui/borrowck/borrowck-closures-unique.nll.stderr
new file mode 100644
index 0000000..3106f36
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-closures-unique.nll.stderr
@@ -0,0 +1,54 @@
+error[E0500]: closure requires unique access to `x` but it is already borrowed
+  --> $DIR/borrowck-closures-unique.rs:26:14
+   |
+LL |     let c1 = || get(x);
+   |              --     - first borrow occurs due to use of `x` in closure
+   |              |
+   |              borrow occurs here
+LL |     let c2 = || set(x);
+   |              ^^     - second borrow occurs due to use of `x` in closure
+   |              |
+   |              closure construction occurs here
+LL |     c1;
+   |     -- first borrow later used here
+
+error[E0500]: closure requires unique access to `x` but it is already borrowed
+  --> $DIR/borrowck-closures-unique.rs:32:14
+   |
+LL |     let c1 = || get(x);
+   |              --     - first borrow occurs due to use of `x` in closure
+   |              |
+   |              borrow occurs here
+LL |     let c2 = || { get(x); set(x); };
+   |              ^^       - second borrow occurs due to use of `x` in closure
+   |              |
+   |              closure construction occurs here
+LL |     c1;
+   |     -- first borrow later used here
+
+error[E0524]: two closures require unique access to `x` at the same time
+  --> $DIR/borrowck-closures-unique.rs:38:14
+   |
+LL |     let c1 = || set(x);
+   |              --     - first borrow occurs due to use of `x` in closure
+   |              |
+   |              first closure is constructed here
+LL |     let c2 = || set(x);
+   |              ^^     - second borrow occurs due to use of `x` in closure
+   |              |
+   |              second closure is constructed here
+LL |     c1;
+   |     -- first borrow later used here
+
+error[E0594]: cannot assign to `x`, as it is not declared as mutable
+  --> $DIR/borrowck-closures-unique.rs:47:38
+   |
+LL | fn e(x: &'static mut isize) {
+   |      - help: consider changing this to be mutable: `mut x`
+LL |     let c1 = |y: &'static mut isize| x = y;
+   |                                      ^^^^^ cannot assign
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0500, E0524, E0594.
+For more information about an error, try `rustc --explain E0500`.
diff --git a/src/test/ui/borrowck/borrowck-closures-unique.rs b/src/test/ui/borrowck/borrowck-closures-unique.rs
new file mode 100644
index 0000000..a4655eb
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-closures-unique.rs
@@ -0,0 +1,57 @@
+// Tests that a closure which requires mutable access to the referent
+// of an `&mut` requires a "unique" borrow -- that is, the variable to
+// be borrowed (here, `x`) will not be borrowed *mutably*, but
+//  may be *immutable*, but we cannot allow
+// multiple borrows.
+
+
+
+fn get(x: &isize) -> isize {
+    *x
+}
+
+fn set(x: &mut isize) -> isize {
+    *x
+}
+
+fn a(x: &mut isize) {
+    let c1 = || get(x);
+    let c2 = || get(x);
+    c1();
+    c2();
+}
+
+fn b(x: &mut isize) {
+    let c1 = || get(x);
+    let c2 = || set(x); //~ ERROR closure requires unique access to `x`
+    c1;
+}
+
+fn c(x: &mut isize) {
+    let c1 = || get(x);
+    let c2 = || { get(x); set(x); }; //~ ERROR closure requires unique access to `x`
+    c1;
+}
+
+fn d(x: &mut isize) {
+    let c1 = || set(x);
+    let c2 = || set(x); //~ ERROR two closures require unique access to `x` at the same time
+    c1;
+}
+
+// This test was originally encoded in the form shown as `fn f` below.
+// However, since MIR-borrowck and thus NLL takes more control-flow information
+// into account, it was necessary to change the test in order to witness the
+// same (expected) error under both AST-borrowck and NLL.
+fn e(x: &'static mut isize) {
+    let c1 = |y: &'static mut isize| x = y; //~ ERROR closure cannot assign to immutable argument
+    c1;
+}
+
+fn f(x: &'static mut isize) {
+    let c1 = || x = panic!(); //~ ERROR closure cannot assign to immutable argument
+    c1;
+}
+
+fn main() {
+}
diff --git a/src/test/ui/borrowck/borrowck-closures-unique.stderr b/src/test/ui/borrowck/borrowck-closures-unique.stderr
new file mode 100644
index 0000000..238b16f
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-closures-unique.stderr
@@ -0,0 +1,69 @@
+error[E0500]: closure requires unique access to `x` but it is already borrowed
+  --> $DIR/borrowck-closures-unique.rs:26:14
+   |
+LL |     let c1 = || get(x);
+   |              --     - previous borrow occurs due to use of `x` in closure
+   |              |
+   |              borrow occurs here
+LL |     let c2 = || set(x);
+   |              ^^     - borrow occurs due to use of `x` in closure
+   |              |
+   |              closure construction occurs here
+LL |     c1;
+LL | }
+   | - borrow ends here
+
+error[E0500]: closure requires unique access to `x` but it is already borrowed
+  --> $DIR/borrowck-closures-unique.rs:32:14
+   |
+LL |     let c1 = || get(x);
+   |              --     - previous borrow occurs due to use of `x` in closure
+   |              |
+   |              borrow occurs here
+LL |     let c2 = || { get(x); set(x); };
+   |              ^^       - borrow occurs due to use of `x` in closure
+   |              |
+   |              closure construction occurs here
+LL |     c1;
+LL | }
+   | - borrow ends here
+
+error[E0524]: two closures require unique access to `x` at the same time
+  --> $DIR/borrowck-closures-unique.rs:38:14
+   |
+LL |     let c1 = || set(x);
+   |              --     - previous borrow occurs due to use of `x` in closure
+   |              |
+   |              first closure is constructed here
+LL |     let c2 = || set(x);
+   |              ^^     - borrow occurs due to use of `x` in closure
+   |              |
+   |              second closure is constructed here
+LL |     c1;
+LL | }
+   | - borrow from first closure ends here
+
+error[E0595]: closure cannot assign to immutable argument `x`
+  --> $DIR/borrowck-closures-unique.rs:47:14
+   |
+LL |     let c1 = |y: &'static mut isize| x = y;
+   |              ^^^^^^^^^^^^^^^^^^^^^^^ cannot borrow mutably
+help: consider removing the `&mut`, as it is an immutable binding to a mutable reference
+   |
+LL |     x
+   |     ^
+
+error[E0595]: closure cannot assign to immutable argument `x`
+  --> $DIR/borrowck-closures-unique.rs:52:14
+   |
+LL |     let c1 = || x = panic!();
+   |              ^^ cannot borrow mutably
+help: consider removing the `&mut`, as it is an immutable binding to a mutable reference
+   |
+LL |     x
+   |     ^
+
+error: aborting due to 5 previous errors
+
+Some errors occurred: E0500, E0524, E0595.
+For more information about an error, try `rustc --explain E0500`.
diff --git a/src/test/ui/borrowck/borrowck-closures-use-after-free.nll.stderr b/src/test/ui/borrowck/borrowck-closures-use-after-free.nll.stderr
new file mode 100644
index 0000000..a6dbcf3
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-closures-use-after-free.nll.stderr
@@ -0,0 +1,16 @@
+error[E0502]: cannot borrow `*ptr` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-closures-use-after-free.rs:22:8
+   |
+LL |   let mut test = |foo: &Foo| {
+   |                  ----------- mutable borrow occurs here
+LL |     ptr = box Foo { x: ptr.x + 1 };
+   |     --- first borrow occurs due to use of `ptr` in closure
+LL |   };
+LL |   test(&*ptr);
+   |   ---- ^^^^^ immutable borrow occurs here
+   |   |
+   |   mutable borrow later used by call
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/borrowck/borrowck-closures-use-after-free.rs b/src/test/ui/borrowck/borrowck-closures-use-after-free.rs
new file mode 100644
index 0000000..e9f65c4
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-closures-use-after-free.rs
@@ -0,0 +1,23 @@
+// Tests that a closure which mutates a local variable
+// cannot also be supplied a borrowed version of that
+// variable's contents. Issue #11192.
+
+#![feature(box_syntax)]
+
+struct Foo {
+  x: isize
+}
+
+impl Drop for Foo {
+  fn drop(&mut self) {
+    println!("drop {}", self.x);
+  }
+}
+
+fn main() {
+  let mut ptr: Box<_> = box Foo { x: 0 };
+  let mut test = |foo: &Foo| {
+    ptr = box Foo { x: ptr.x + 1 };
+  };
+  test(&*ptr); //~ ERROR cannot borrow `*ptr`
+}
diff --git a/src/test/ui/borrowck/borrowck-closures-use-after-free.stderr b/src/test/ui/borrowck/borrowck-closures-use-after-free.stderr
new file mode 100644
index 0000000..9e77d8c
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-closures-use-after-free.stderr
@@ -0,0 +1,16 @@
+error[E0502]: cannot borrow `*ptr` as immutable because `ptr` is also borrowed as mutable
+  --> $DIR/borrowck-closures-use-after-free.rs:22:9
+   |
+LL |   let mut test = |foo: &Foo| {
+   |                  ----------- mutable borrow occurs here
+LL |     ptr = box Foo { x: ptr.x + 1 };
+   |     --- previous borrow occurs due to use of `ptr` in closure
+LL |   };
+LL |   test(&*ptr);
+   |         ^^^^ immutable borrow occurs here
+LL | }
+   | - mutable borrow ends here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/borrowck/borrowck-consume-unsize-vec.nll.stderr b/src/test/ui/borrowck/borrowck-consume-unsize-vec.nll.stderr
new file mode 100644
index 0000000..c69237f
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-consume-unsize-vec.nll.stderr
@@ -0,0 +1,13 @@
+error[E0382]: use of moved value: `b`
+  --> $DIR/borrowck-consume-unsize-vec.rs:8:13
+   |
+LL | fn foo(b: Box<[i32;5]>) {
+   |        - move occurs because `b` has type `std::boxed::Box<[i32; 5]>`, which does not implement the `Copy` trait
+LL |     consume(b);
+   |             - value moved here
+LL |     consume(b);
+   |             ^ value used here after move
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/borrowck-consume-unsize-vec.rs b/src/test/ui/borrowck/borrowck-consume-unsize-vec.rs
new file mode 100644
index 0000000..347f021
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-consume-unsize-vec.rs
@@ -0,0 +1,12 @@
+// Check that we report an error if an upcast box is moved twice.
+
+fn consume(_: Box<[i32]>) {
+}
+
+fn foo(b: Box<[i32;5]>) {
+    consume(b);
+    consume(b); //~ ERROR use of moved value
+}
+
+fn main() {
+}
diff --git a/src/test/ui/borrowck/borrowck-consume-unsize-vec.stderr b/src/test/ui/borrowck/borrowck-consume-unsize-vec.stderr
new file mode 100644
index 0000000..02644b8
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-consume-unsize-vec.stderr
@@ -0,0 +1,13 @@
+error[E0382]: use of moved value: `b`
+  --> $DIR/borrowck-consume-unsize-vec.rs:8:13
+   |
+LL |     consume(b);
+   |             - value moved here
+LL |     consume(b);
+   |             ^ value used here after move
+   |
+   = note: move occurs because `b` has type `std::boxed::Box<[i32; 5]>`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/borrowck-consume-upcast-box.nll.stderr b/src/test/ui/borrowck/borrowck-consume-upcast-box.nll.stderr
new file mode 100644
index 0000000..e8194ad
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-consume-upcast-box.nll.stderr
@@ -0,0 +1,13 @@
+error[E0382]: use of moved value: `b`
+  --> $DIR/borrowck-consume-upcast-box.rs:10:13
+   |
+LL | fn foo(b: Box<Foo+Send>) {
+   |        - move occurs because `b` has type `std::boxed::Box<dyn Foo + std::marker::Send>`, which does not implement the `Copy` trait
+LL |     consume(b);
+   |             - value moved here
+LL |     consume(b);
+   |             ^ value used here after move
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/borrowck-consume-upcast-box.rs b/src/test/ui/borrowck/borrowck-consume-upcast-box.rs
new file mode 100644
index 0000000..ed669c4
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-consume-upcast-box.rs
@@ -0,0 +1,14 @@
+// Check that we report an error if an upcast box is moved twice.
+
+trait Foo { fn dummy(&self); }
+
+fn consume(_: Box<Foo>) {
+}
+
+fn foo(b: Box<Foo+Send>) {
+    consume(b);
+    consume(b); //~ ERROR use of moved value
+}
+
+fn main() {
+}
diff --git a/src/test/ui/borrowck/borrowck-consume-upcast-box.stderr b/src/test/ui/borrowck/borrowck-consume-upcast-box.stderr
new file mode 100644
index 0000000..7267a99
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-consume-upcast-box.stderr
@@ -0,0 +1,13 @@
+error[E0382]: use of moved value: `b`
+  --> $DIR/borrowck-consume-upcast-box.rs:10:13
+   |
+LL |     consume(b);
+   |             - value moved here
+LL |     consume(b);
+   |             ^ value used here after move
+   |
+   = note: move occurs because `b` has type `std::boxed::Box<(dyn Foo + std::marker::Send + 'static)>`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/borrowck-describe-lvalue.ast.nll.stderr b/src/test/ui/borrowck/borrowck-describe-lvalue.ast.nll.stderr
new file mode 100644
index 0000000..c614469
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-describe-lvalue.ast.nll.stderr
@@ -0,0 +1,383 @@
+error[E0499]: cannot borrow `x` as mutable more than once at a time
+  --> $DIR/borrowck-describe-lvalue.rs:285:13
+   |
+LL |             let y = &mut x;
+   |                     ------ first mutable borrow occurs here
+LL |             &mut x;
+   |             ^^^^^^ second mutable borrow occurs here
+LL |
+LL |             *y = 1;
+   |             ------ first borrow later used here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time
+  --> $DIR/borrowck-describe-lvalue.rs:296:20
+   |
+LL |                    let y = &mut x;
+   |                            ------ first mutable borrow occurs here
+LL |                    &mut x;
+   |                    ^^^^^^ second mutable borrow occurs here
+LL |
+LL |                    *y = 1;
+   |                    ------ first borrow later used here
+
+error: captured variable cannot escape `FnMut` closure body
+  --> $DIR/borrowck-describe-lvalue.rs:294:16
+   |
+LL |              || {
+   |               - inferred to be a `FnMut` closure
+LL | /                || {
+LL | |                    let y = &mut x;
+LL | |                    &mut x;
+LL | |
+LL | |                    *y = 1;
+LL | |                    drop(y);
+LL | |                 }
+   | |_________________^ returns a closure that contains a reference to a captured variable, which then escapes the closure body
+   |
+   = note: `FnMut` closures only have access to their captured variables while they are executing...
+   = note: ...therefore, they cannot allow references to captured variables to escape
+
+error[E0503]: cannot use `f.x` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:43:9
+   |
+LL |         let x = f.x();
+   |                 - borrow of `f` occurs here
+LL |         f.x;
+   |         ^^^ use of borrowed `f`
+LL |
+LL |         drop(x);
+   |              - borrow later used here
+
+error[E0503]: cannot use `g.0` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:51:9
+   |
+LL |         let x = g.x();
+   |                 - borrow of `g` occurs here
+LL |         g.0;
+   |         ^^^ use of borrowed `g`
+LL |
+LL |         drop(x);
+   |              - borrow later used here
+
+error[E0503]: cannot use `h.0` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:59:9
+   |
+LL |         let x = &mut h.0;
+   |                 -------- borrow of `h.0` occurs here
+LL |         h.0;
+   |         ^^^ use of borrowed `h.0`
+LL |
+LL |         drop(x);
+   |              - borrow later used here
+
+error[E0503]: cannot use `e.0` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:68:20
+   |
+LL |         let x = e.x();
+   |                 - borrow of `e` occurs here
+LL |         match e {
+LL |             Baz::X(value) => value
+   |                    ^^^^^ use of borrowed `e`
+...
+LL |         drop(x);
+   |              - borrow later used here
+
+error[E0503]: cannot use `u.a` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:78:9
+   |
+LL |         let x = &mut u.a;
+   |                 -------- borrow of `u.a` occurs here
+LL |         u.a;
+   |         ^^^ use of borrowed `u.a`
+LL |
+LL |         drop(x);
+   |              - borrow later used here
+
+error[E0503]: cannot use `f.x` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:86:9
+   |
+LL |         let x = f.x();
+   |                 - borrow of `*f` occurs here
+LL |         f.x;
+   |         ^^^ use of borrowed `*f`
+LL |
+LL |         drop(x);
+   |              - borrow later used here
+
+error[E0503]: cannot use `g.0` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:94:9
+   |
+LL |         let x = g.x();
+   |                 - borrow of `*g` occurs here
+LL |         g.0;
+   |         ^^^ use of borrowed `*g`
+LL |
+LL |         drop(x);
+   |              - borrow later used here
+
+error[E0503]: cannot use `h.0` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:102:9
+   |
+LL |         let x = &mut h.0;
+   |                 -------- borrow of `h.0` occurs here
+LL |         h.0;
+   |         ^^^ use of borrowed `h.0`
+LL |
+LL |         drop(x);
+   |              - borrow later used here
+
+error[E0503]: cannot use `e.0` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:111:20
+   |
+LL |         let x = e.x();
+   |                 - borrow of `*e` occurs here
+LL |         match *e {
+LL |             Baz::X(value) => value
+   |                    ^^^^^ use of borrowed `*e`
+...
+LL |         drop(x);
+   |              - borrow later used here
+
+error[E0503]: cannot use `u.a` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:121:9
+   |
+LL |         let x = &mut u.a;
+   |                 -------- borrow of `u.a` occurs here
+LL |         u.a;
+   |         ^^^ use of borrowed `u.a`
+LL |
+LL |         drop(x);
+   |              - borrow later used here
+
+error[E0503]: cannot use `v[..]` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:130:15
+   |
+LL |         let x = &mut v;
+   |                 ------ borrow of `v` occurs here
+LL |         match v {
+LL |             &[x, _, .., _, _] => println!("{}", x),
+   |               ^ use of borrowed `v`
+...
+LL |         drop(x);
+   |              - borrow later used here
+
+error[E0503]: cannot use `v[..]` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:136:18
+   |
+LL |         let x = &mut v;
+   |                 ------ borrow of `v` occurs here
+...
+LL |             &[_, x, .., _, _] => println!("{}", x),
+   |                  ^ use of borrowed `v`
+...
+LL |         drop(x);
+   |              - borrow later used here
+
+error[E0503]: cannot use `v[..]` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:142:25
+   |
+LL |         let x = &mut v;
+   |                 ------ borrow of `v` occurs here
+...
+LL |             &[_, _, .., x, _] => println!("{}", x),
+   |                         ^ use of borrowed `v`
+...
+LL |         drop(x);
+   |              - borrow later used here
+
+error[E0503]: cannot use `v[..]` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:148:28
+   |
+LL |         let x = &mut v;
+   |                 ------ borrow of `v` occurs here
+...
+LL |             &[_, _, .., _, x] => println!("{}", x),
+   |                            ^ use of borrowed `v`
+...
+LL |         drop(x);
+   |              - borrow later used here
+
+error[E0503]: cannot use `v[..]` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:160:15
+   |
+LL |         let x = &mut v;
+   |                 ------ borrow of `v` occurs here
+LL |         match v {
+LL |             &[x..] => println!("{:?}", x),
+   |               ^ use of borrowed `v`
+...
+LL |         drop(x);
+   |              - borrow later used here
+
+error[E0503]: cannot use `v[..]` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:166:18
+   |
+LL |         let x = &mut v;
+   |                 ------ borrow of `v` occurs here
+...
+LL |             &[_, x..] => println!("{:?}", x),
+   |                  ^ use of borrowed `v`
+...
+LL |         drop(x);
+   |              - borrow later used here
+
+error[E0503]: cannot use `v[..]` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:172:15
+   |
+LL |         let x = &mut v;
+   |                 ------ borrow of `v` occurs here
+...
+LL |             &[x.., _] => println!("{:?}", x),
+   |               ^ use of borrowed `v`
+...
+LL |         drop(x);
+   |              - borrow later used here
+
+error[E0503]: cannot use `v[..]` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:178:18
+   |
+LL |         let x = &mut v;
+   |                 ------ borrow of `v` occurs here
+...
+LL |             &[_, x.., _] => println!("{:?}", x),
+   |                  ^ use of borrowed `v`
+...
+LL |         drop(x);
+   |              - borrow later used here
+
+error[E0503]: cannot use `e` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:192:13
+   |
+LL |         let x = &mut e;
+   |                 ------ borrow of `e` occurs here
+LL |         match e {
+LL |             E::A(ref ax) =>
+   |             ^^^^^^^^^^^^ use of borrowed `e`
+...
+LL |         drop(x);
+   |              - borrow later used here
+
+error[E0502]: cannot borrow `e.0` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-describe-lvalue.rs:192:18
+   |
+LL |         let x = &mut e;
+   |                 ------ mutable borrow occurs here
+LL |         match e {
+LL |             E::A(ref ax) =>
+   |                  ^^^^^^ immutable borrow occurs here
+...
+LL |         drop(x);
+   |              - mutable borrow later used here
+
+error[E0502]: cannot borrow `e.x` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-describe-lvalue.rs:197:23
+   |
+LL |         let x = &mut e;
+   |                 ------ mutable borrow occurs here
+...
+LL |             E::B { x: ref bx } =>
+   |                       ^^^^^^ immutable borrow occurs here
+...
+LL |         drop(x);
+   |              - mutable borrow later used here
+
+error[E0502]: cannot borrow `s.y.0` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-describe-lvalue.rs:211:22
+   |
+LL |         let x = &mut s;
+   |                 ------ mutable borrow occurs here
+LL |         match s {
+LL |             S  { y: (ref y0, _), .. } =>
+   |                      ^^^^^^ immutable borrow occurs here
+...
+LL |         drop(x);
+   |              - mutable borrow later used here
+
+error[E0502]: cannot borrow `s.x.y` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-describe-lvalue.rs:218:28
+   |
+LL |         let x = &mut s;
+   |                 ------ mutable borrow occurs here
+...
+LL |             S  { x: F { y: ref x0, .. }, .. } =>
+   |                            ^^^^^^ immutable borrow occurs here
+...
+LL |         drop(x);
+   |              - mutable borrow later used here
+
+error[E0503]: cannot use `*v` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:261:9
+   |
+LL |         let x = &mut v;
+   |                 ------ borrow of `v` occurs here
+LL |         v[0].y;
+   |         ^^^^ use of borrowed `v`
+...
+LL |         drop(x);
+   |              - borrow later used here
+
+error[E0503]: cannot use `v[_].y` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:261:9
+   |
+LL |         let x = &mut v;
+   |                 ------ borrow of `v` occurs here
+LL |         v[0].y;
+   |         ^^^^^^ use of borrowed `v`
+...
+LL |         drop(x);
+   |              - borrow later used here
+
+error[E0502]: cannot borrow `v[..].x` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-describe-lvalue.rs:273:24
+   |
+LL |         let x = &mut v;
+   |                 ------ mutable borrow occurs here
+LL |         match v {
+LL |             &[_, F {x: ref xf, ..}] => println!("{}", xf),
+   |                        ^^^^^^ immutable borrow occurs here
+...
+LL |         drop(x);
+   |              - mutable borrow later used here
+
+warning[E0502]: cannot borrow `*block.current` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-describe-lvalue.rs:235:29
+   |
+LL |             let x = &mut block;
+   |                     ---------- mutable borrow occurs here
+LL |             let p: &'a u8 = &*block.current;
+   |                             ^^^^^^^^^^^^^^^ immutable borrow occurs here
+...
+LL |             drop(x);
+   |                  - mutable borrow later used here
+   |
+   = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
+   = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+
+warning[E0502]: cannot borrow `*block.current` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-describe-lvalue.rs:250:33
+   |
+LL |             let x = &mut block;
+   |                     ---------- mutable borrow occurs here
+LL |             let p : *const u8 = &*(*block).current;
+   |                                 ^^^^^^^^^^^^^^^^^^ immutable borrow occurs here
+...
+LL |             drop(x);
+   |                  - mutable borrow later used here
+   |
+   = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
+   = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+
+error[E0382]: use of moved value: `x`
+  --> $DIR/borrowck-describe-lvalue.rs:307:22
+   |
+LL |                 drop(x);
+   |                      - value moved here
+LL |                 drop(x);
+   |                      ^ value used here after move
+   |
+   = note: move occurs because `x` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
+
+error: aborting due to 30 previous errors
+
+Some errors occurred: E0382, E0499, E0502, E0503.
+For more information about an error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/borrowck-describe-lvalue.ast.stderr b/src/test/ui/borrowck/borrowck-describe-lvalue.ast.stderr
new file mode 100644
index 0000000..d892db8
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-describe-lvalue.ast.stderr
@@ -0,0 +1,246 @@
+error[E0503]: cannot use `f.x` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:43:9
+   |
+LL |         let x = f.x();
+   |                 - borrow of `f` occurs here
+LL |         f.x;
+   |         ^^^ use of borrowed `f`
+
+error[E0503]: cannot use `g.0` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:51:9
+   |
+LL |         let x = g.x();
+   |                 - borrow of `g` occurs here
+LL |         g.0;
+   |         ^^^ use of borrowed `g`
+
+error[E0503]: cannot use `h.0` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:59:9
+   |
+LL |         let x = &mut h.0;
+   |                      --- borrow of `h.0` occurs here
+LL |         h.0;
+   |         ^^^ use of borrowed `h.0`
+
+error[E0503]: cannot use `e.0` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:68:20
+   |
+LL |         let x = e.x();
+   |                 - borrow of `e` occurs here
+LL |         match e {
+LL |             Baz::X(value) => value
+   |                    ^^^^^ use of borrowed `e`
+
+error[E0503]: cannot use `u.a` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:78:9
+   |
+LL |         let x = &mut u.a;
+   |                      --- borrow of `u.a` occurs here
+LL |         u.a;
+   |         ^^^ use of borrowed `u.a`
+
+error[E0503]: cannot use `f.x` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:86:9
+   |
+LL |         let x = f.x();
+   |                 - borrow of `*f` occurs here
+LL |         f.x;
+   |         ^^^ use of borrowed `*f`
+
+error[E0503]: cannot use `g.0` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:94:9
+   |
+LL |         let x = g.x();
+   |                 - borrow of `*g` occurs here
+LL |         g.0;
+   |         ^^^ use of borrowed `*g`
+
+error[E0503]: cannot use `h.0` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:102:9
+   |
+LL |         let x = &mut h.0;
+   |                      --- borrow of `h.0` occurs here
+LL |         h.0;
+   |         ^^^ use of borrowed `h.0`
+
+error[E0503]: cannot use `e.0` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:111:20
+   |
+LL |         let x = e.x();
+   |                 - borrow of `*e` occurs here
+LL |         match *e {
+LL |             Baz::X(value) => value
+   |                    ^^^^^ use of borrowed `*e`
+
+error[E0503]: cannot use `u.a` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:121:9
+   |
+LL |         let x = &mut u.a;
+   |                      --- borrow of `u.a` occurs here
+LL |         u.a;
+   |         ^^^ use of borrowed `u.a`
+
+error[E0503]: cannot use `v[..]` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:130:15
+   |
+LL |         let x = &mut v;
+   |                      - borrow of `v` occurs here
+LL |         match v {
+LL |             &[x, _, .., _, _] => println!("{}", x),
+   |               ^ use of borrowed `v`
+
+error[E0503]: cannot use `v[..]` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:136:18
+   |
+LL |         let x = &mut v;
+   |                      - borrow of `v` occurs here
+...
+LL |             &[_, x, .., _, _] => println!("{}", x),
+   |                  ^ use of borrowed `v`
+
+error[E0503]: cannot use `v[..]` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:142:25
+   |
+LL |         let x = &mut v;
+   |                      - borrow of `v` occurs here
+...
+LL |             &[_, _, .., x, _] => println!("{}", x),
+   |                         ^ use of borrowed `v`
+
+error[E0503]: cannot use `v[..]` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:148:28
+   |
+LL |         let x = &mut v;
+   |                      - borrow of `v` occurs here
+...
+LL |             &[_, _, .., _, x] => println!("{}", x),
+   |                            ^ use of borrowed `v`
+
+error[E0503]: cannot use `v[..]` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:160:15
+   |
+LL |         let x = &mut v;
+   |                      - borrow of `v` occurs here
+LL |         match v {
+LL |             &[x..] => println!("{:?}", x),
+   |               ^ use of borrowed `v`
+
+error[E0503]: cannot use `v[..]` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:166:18
+   |
+LL |         let x = &mut v;
+   |                      - borrow of `v` occurs here
+...
+LL |             &[_, x..] => println!("{:?}", x),
+   |                  ^ use of borrowed `v`
+
+error[E0503]: cannot use `v[..]` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:172:15
+   |
+LL |         let x = &mut v;
+   |                      - borrow of `v` occurs here
+...
+LL |             &[x.., _] => println!("{:?}", x),
+   |               ^ use of borrowed `v`
+
+error[E0503]: cannot use `v[..]` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:178:18
+   |
+LL |         let x = &mut v;
+   |                      - borrow of `v` occurs here
+...
+LL |             &[_, x.., _] => println!("{:?}", x),
+   |                  ^ use of borrowed `v`
+
+error[E0502]: cannot borrow `e.0` as immutable because `e` is also borrowed as mutable
+  --> $DIR/borrowck-describe-lvalue.rs:192:18
+   |
+LL |         let x = &mut e;
+   |                      - mutable borrow occurs here
+LL |         match e {
+LL |             E::A(ref ax) =>
+   |                  ^^^^^^ immutable borrow occurs here
+...
+LL |     }
+   |     - mutable borrow ends here
+
+error[E0502]: cannot borrow `e.x` as immutable because `e` is also borrowed as mutable
+  --> $DIR/borrowck-describe-lvalue.rs:197:23
+   |
+LL |         let x = &mut e;
+   |                      - mutable borrow occurs here
+...
+LL |             E::B { x: ref bx } =>
+   |                       ^^^^^^ immutable borrow occurs here
+...
+LL |     }
+   |     - mutable borrow ends here
+
+error[E0502]: cannot borrow `s.y.0` as immutable because `s` is also borrowed as mutable
+  --> $DIR/borrowck-describe-lvalue.rs:211:22
+   |
+LL |         let x = &mut s;
+   |                      - mutable borrow occurs here
+LL |         match s {
+LL |             S  { y: (ref y0, _), .. } =>
+   |                      ^^^^^^ immutable borrow occurs here
+...
+LL |     }
+   |     - mutable borrow ends here
+
+error[E0502]: cannot borrow `s.x.y` as immutable because `s` is also borrowed as mutable
+  --> $DIR/borrowck-describe-lvalue.rs:218:28
+   |
+LL |         let x = &mut s;
+   |                      - mutable borrow occurs here
+...
+LL |             S  { x: F { y: ref x0, .. }, .. } =>
+   |                            ^^^^^^ immutable borrow occurs here
+...
+LL |     }
+   |     - mutable borrow ends here
+
+error[E0503]: cannot use `v[..].y` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:261:9
+   |
+LL |         let x = &mut v;
+   |                      - borrow of `v` occurs here
+LL |         v[0].y;
+   |         ^^^^^^ use of borrowed `v`
+
+error[E0499]: cannot borrow `**x` as mutable more than once at a time
+  --> $DIR/borrowck-describe-lvalue.rs:285:18
+   |
+LL |             let y = &mut x;
+   |                          - first mutable borrow occurs here
+LL |             &mut x;
+   |                  ^ second mutable borrow occurs here
+...
+LL |         };
+   |         - first borrow ends here
+
+error[E0499]: cannot borrow `**x` as mutable more than once at a time
+  --> $DIR/borrowck-describe-lvalue.rs:296:25
+   |
+LL |                    let y = &mut x;
+   |                                 - first mutable borrow occurs here
+LL |                    &mut x;
+   |                         ^ second mutable borrow occurs here
+...
+LL |                 }
+   |                 - first borrow ends here
+
+error[E0382]: use of moved value: `x`
+  --> $DIR/borrowck-describe-lvalue.rs:307:22
+   |
+LL |                 drop(x);
+   |                      - value moved here
+LL |                 drop(x);
+   |                      ^ value used here after move
+   |
+   = note: move occurs because `x` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
+
+error: aborting due to 26 previous errors
+
+Some errors occurred: E0382, E0499, E0502, E0503.
+For more information about an error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/borrowck-describe-lvalue.mir.stderr b/src/test/ui/borrowck/borrowck-describe-lvalue.mir.stderr
new file mode 100644
index 0000000..af78340
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-describe-lvalue.mir.stderr
@@ -0,0 +1,377 @@
+error[E0499]: cannot borrow `x` as mutable more than once at a time
+  --> $DIR/borrowck-describe-lvalue.rs:285:13
+   |
+LL |             let y = &mut x;
+   |                     ------ first mutable borrow occurs here
+LL |             &mut x;
+   |             ^^^^^^ second mutable borrow occurs here
+LL |
+LL |             *y = 1;
+   |             ------ first borrow later used here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time
+  --> $DIR/borrowck-describe-lvalue.rs:296:20
+   |
+LL |                    let y = &mut x;
+   |                            ------ first mutable borrow occurs here
+LL |                    &mut x;
+   |                    ^^^^^^ second mutable borrow occurs here
+LL |
+LL |                    *y = 1;
+   |                    ------ first borrow later used here
+
+error: captured variable cannot escape `FnMut` closure body
+  --> $DIR/borrowck-describe-lvalue.rs:294:16
+   |
+LL |              || {
+   |               - inferred to be a `FnMut` closure
+LL | /                || {
+LL | |                    let y = &mut x;
+LL | |                    &mut x;
+LL | |
+LL | |                    *y = 1;
+LL | |                    drop(y);
+LL | |                 }
+   | |_________________^ returns a closure that contains a reference to a captured variable, which then escapes the closure body
+   |
+   = note: `FnMut` closures only have access to their captured variables while they are executing...
+   = note: ...therefore, they cannot allow references to captured variables to escape
+
+error[E0503]: cannot use `f.x` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:43:9
+   |
+LL |         let x = f.x();
+   |                 - borrow of `f` occurs here
+LL |         f.x;
+   |         ^^^ use of borrowed `f`
+LL |
+LL |         drop(x);
+   |              - borrow later used here
+
+error[E0503]: cannot use `g.0` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:51:9
+   |
+LL |         let x = g.x();
+   |                 - borrow of `g` occurs here
+LL |         g.0;
+   |         ^^^ use of borrowed `g`
+LL |
+LL |         drop(x);
+   |              - borrow later used here
+
+error[E0503]: cannot use `h.0` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:59:9
+   |
+LL |         let x = &mut h.0;
+   |                 -------- borrow of `h.0` occurs here
+LL |         h.0;
+   |         ^^^ use of borrowed `h.0`
+LL |
+LL |         drop(x);
+   |              - borrow later used here
+
+error[E0503]: cannot use `e.0` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:68:20
+   |
+LL |         let x = e.x();
+   |                 - borrow of `e` occurs here
+LL |         match e {
+LL |             Baz::X(value) => value
+   |                    ^^^^^ use of borrowed `e`
+...
+LL |         drop(x);
+   |              - borrow later used here
+
+error[E0503]: cannot use `u.a` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:78:9
+   |
+LL |         let x = &mut u.a;
+   |                 -------- borrow of `u.a` occurs here
+LL |         u.a;
+   |         ^^^ use of borrowed `u.a`
+LL |
+LL |         drop(x);
+   |              - borrow later used here
+
+error[E0503]: cannot use `f.x` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:86:9
+   |
+LL |         let x = f.x();
+   |                 - borrow of `*f` occurs here
+LL |         f.x;
+   |         ^^^ use of borrowed `*f`
+LL |
+LL |         drop(x);
+   |              - borrow later used here
+
+error[E0503]: cannot use `g.0` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:94:9
+   |
+LL |         let x = g.x();
+   |                 - borrow of `*g` occurs here
+LL |         g.0;
+   |         ^^^ use of borrowed `*g`
+LL |
+LL |         drop(x);
+   |              - borrow later used here
+
+error[E0503]: cannot use `h.0` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:102:9
+   |
+LL |         let x = &mut h.0;
+   |                 -------- borrow of `h.0` occurs here
+LL |         h.0;
+   |         ^^^ use of borrowed `h.0`
+LL |
+LL |         drop(x);
+   |              - borrow later used here
+
+error[E0503]: cannot use `e.0` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:111:20
+   |
+LL |         let x = e.x();
+   |                 - borrow of `*e` occurs here
+LL |         match *e {
+LL |             Baz::X(value) => value
+   |                    ^^^^^ use of borrowed `*e`
+...
+LL |         drop(x);
+   |              - borrow later used here
+
+error[E0503]: cannot use `u.a` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:121:9
+   |
+LL |         let x = &mut u.a;
+   |                 -------- borrow of `u.a` occurs here
+LL |         u.a;
+   |         ^^^ use of borrowed `u.a`
+LL |
+LL |         drop(x);
+   |              - borrow later used here
+
+error[E0503]: cannot use `v[..]` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:130:15
+   |
+LL |         let x = &mut v;
+   |                 ------ borrow of `v` occurs here
+LL |         match v {
+LL |             &[x, _, .., _, _] => println!("{}", x),
+   |               ^ use of borrowed `v`
+...
+LL |         drop(x);
+   |              - borrow later used here
+
+error[E0503]: cannot use `v[..]` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:136:18
+   |
+LL |         let x = &mut v;
+   |                 ------ borrow of `v` occurs here
+...
+LL |             &[_, x, .., _, _] => println!("{}", x),
+   |                  ^ use of borrowed `v`
+...
+LL |         drop(x);
+   |              - borrow later used here
+
+error[E0503]: cannot use `v[..]` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:142:25
+   |
+LL |         let x = &mut v;
+   |                 ------ borrow of `v` occurs here
+...
+LL |             &[_, _, .., x, _] => println!("{}", x),
+   |                         ^ use of borrowed `v`
+...
+LL |         drop(x);
+   |              - borrow later used here
+
+error[E0503]: cannot use `v[..]` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:148:28
+   |
+LL |         let x = &mut v;
+   |                 ------ borrow of `v` occurs here
+...
+LL |             &[_, _, .., _, x] => println!("{}", x),
+   |                            ^ use of borrowed `v`
+...
+LL |         drop(x);
+   |              - borrow later used here
+
+error[E0503]: cannot use `v[..]` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:160:15
+   |
+LL |         let x = &mut v;
+   |                 ------ borrow of `v` occurs here
+LL |         match v {
+LL |             &[x..] => println!("{:?}", x),
+   |               ^ use of borrowed `v`
+...
+LL |         drop(x);
+   |              - borrow later used here
+
+error[E0503]: cannot use `v[..]` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:166:18
+   |
+LL |         let x = &mut v;
+   |                 ------ borrow of `v` occurs here
+...
+LL |             &[_, x..] => println!("{:?}", x),
+   |                  ^ use of borrowed `v`
+...
+LL |         drop(x);
+   |              - borrow later used here
+
+error[E0503]: cannot use `v[..]` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:172:15
+   |
+LL |         let x = &mut v;
+   |                 ------ borrow of `v` occurs here
+...
+LL |             &[x.., _] => println!("{:?}", x),
+   |               ^ use of borrowed `v`
+...
+LL |         drop(x);
+   |              - borrow later used here
+
+error[E0503]: cannot use `v[..]` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:178:18
+   |
+LL |         let x = &mut v;
+   |                 ------ borrow of `v` occurs here
+...
+LL |             &[_, x.., _] => println!("{:?}", x),
+   |                  ^ use of borrowed `v`
+...
+LL |         drop(x);
+   |              - borrow later used here
+
+error[E0503]: cannot use `e` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:192:13
+   |
+LL |         let x = &mut e;
+   |                 ------ borrow of `e` occurs here
+LL |         match e {
+LL |             E::A(ref ax) =>
+   |             ^^^^^^^^^^^^ use of borrowed `e`
+...
+LL |         drop(x);
+   |              - borrow later used here
+
+error[E0502]: cannot borrow `e.0` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-describe-lvalue.rs:192:18
+   |
+LL |         let x = &mut e;
+   |                 ------ mutable borrow occurs here
+LL |         match e {
+LL |             E::A(ref ax) =>
+   |                  ^^^^^^ immutable borrow occurs here
+...
+LL |         drop(x);
+   |              - mutable borrow later used here
+
+error[E0502]: cannot borrow `e.x` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-describe-lvalue.rs:197:23
+   |
+LL |         let x = &mut e;
+   |                 ------ mutable borrow occurs here
+...
+LL |             E::B { x: ref bx } =>
+   |                       ^^^^^^ immutable borrow occurs here
+...
+LL |         drop(x);
+   |              - mutable borrow later used here
+
+error[E0502]: cannot borrow `s.y.0` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-describe-lvalue.rs:211:22
+   |
+LL |         let x = &mut s;
+   |                 ------ mutable borrow occurs here
+LL |         match s {
+LL |             S  { y: (ref y0, _), .. } =>
+   |                      ^^^^^^ immutable borrow occurs here
+...
+LL |         drop(x);
+   |              - mutable borrow later used here
+
+error[E0502]: cannot borrow `s.x.y` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-describe-lvalue.rs:218:28
+   |
+LL |         let x = &mut s;
+   |                 ------ mutable borrow occurs here
+...
+LL |             S  { x: F { y: ref x0, .. }, .. } =>
+   |                            ^^^^^^ immutable borrow occurs here
+...
+LL |         drop(x);
+   |              - mutable borrow later used here
+
+error[E0503]: cannot use `*v` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:261:9
+   |
+LL |         let x = &mut v;
+   |                 ------ borrow of `v` occurs here
+LL |         v[0].y;
+   |         ^^^^ use of borrowed `v`
+...
+LL |         drop(x);
+   |              - borrow later used here
+
+error[E0503]: cannot use `v[_].y` because it was mutably borrowed
+  --> $DIR/borrowck-describe-lvalue.rs:261:9
+   |
+LL |         let x = &mut v;
+   |                 ------ borrow of `v` occurs here
+LL |         v[0].y;
+   |         ^^^^^^ use of borrowed `v`
+...
+LL |         drop(x);
+   |              - borrow later used here
+
+error[E0502]: cannot borrow `v[..].x` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-describe-lvalue.rs:273:24
+   |
+LL |         let x = &mut v;
+   |                 ------ mutable borrow occurs here
+LL |         match v {
+LL |             &[_, F {x: ref xf, ..}] => println!("{}", xf),
+   |                        ^^^^^^ immutable borrow occurs here
+...
+LL |         drop(x);
+   |              - mutable borrow later used here
+
+error[E0502]: cannot borrow `*block.current` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-describe-lvalue.rs:235:29
+   |
+LL |             let x = &mut block;
+   |                     ---------- mutable borrow occurs here
+LL |             let p: &'a u8 = &*block.current;
+   |                             ^^^^^^^^^^^^^^^ immutable borrow occurs here
+...
+LL |             drop(x);
+   |                  - mutable borrow later used here
+
+error[E0502]: cannot borrow `*block.current` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-describe-lvalue.rs:250:33
+   |
+LL |             let x = &mut block;
+   |                     ---------- mutable borrow occurs here
+LL |             let p : *const u8 = &*(*block).current;
+   |                                 ^^^^^^^^^^^^^^^^^^ immutable borrow occurs here
+...
+LL |             drop(x);
+   |                  - mutable borrow later used here
+
+error[E0382]: use of moved value: `x`
+  --> $DIR/borrowck-describe-lvalue.rs:307:22
+   |
+LL |                 drop(x);
+   |                      - value moved here
+LL |                 drop(x);
+   |                      ^ value used here after move
+   |
+   = note: move occurs because `x` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
+
+error: aborting due to 32 previous errors
+
+Some errors occurred: E0382, E0499, E0502, E0503.
+For more information about an error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/borrowck-describe-lvalue.rs b/src/test/ui/borrowck/borrowck-describe-lvalue.rs
new file mode 100644
index 0000000..eb622ac
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-describe-lvalue.rs
@@ -0,0 +1,313 @@
+// ignore-tidy-linelength
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+#![feature(slice_patterns)]
+
+pub struct Foo {
+  x: u32
+}
+
+pub struct Bar(u32);
+
+pub enum Baz {
+    X(u32)
+}
+
+union U {
+    a: u8,
+    b: u64,
+}
+
+impl Foo {
+  fn x(&mut self) -> &mut u32 { &mut self.x }
+}
+
+impl Bar {
+    fn x(&mut self) -> &mut u32 { &mut self.0 }
+}
+
+impl Baz {
+    fn x(&mut self) -> &mut u32 {
+        match *self {
+            Baz::X(ref mut value) => value
+        }
+    }
+}
+
+fn main() {
+    // Local and field from struct
+    {
+        let mut f = Foo { x: 22 };
+        let x = f.x();
+        f.x; //[ast]~ ERROR cannot use `f.x` because it was mutably borrowed
+        //[mir]~^ ERROR cannot use `f.x` because it was mutably borrowed
+        drop(x);
+    }
+    // Local and field from tuple-struct
+    {
+        let mut g = Bar(22);
+        let x = g.x();
+        g.0; //[ast]~ ERROR cannot use `g.0` because it was mutably borrowed
+             //[mir]~^ ERROR cannot use `g.0` because it was mutably borrowed
+        drop(x);
+    }
+    // Local and field from tuple
+    {
+        let mut h = (22, 23);
+        let x = &mut h.0;
+        h.0; //[ast]~ ERROR cannot use `h.0` because it was mutably borrowed
+             //[mir]~^ ERROR cannot use `h.0` because it was mutably borrowed
+        drop(x);
+    }
+    // Local and field from enum
+    {
+        let mut e = Baz::X(2);
+        let x = e.x();
+        match e {
+            Baz::X(value) => value
+            //[ast]~^ ERROR cannot use `e.0` because it was mutably borrowed
+            //[mir]~^^ ERROR cannot use `e.0` because it was mutably borrowed
+        };
+        drop(x);
+    }
+    // Local and field from union
+    unsafe {
+        let mut u = U { b: 0 };
+        let x = &mut u.a;
+        u.a; //[ast]~ ERROR cannot use `u.a` because it was mutably borrowed
+             //[mir]~^ ERROR cannot use `u.a` because it was mutably borrowed
+        drop(x);
+    }
+    // Deref and field from struct
+    {
+        let mut f = Box::new(Foo { x: 22 });
+        let x = f.x();
+        f.x; //[ast]~ ERROR cannot use `f.x` because it was mutably borrowed
+             //[mir]~^ ERROR cannot use `f.x` because it was mutably borrowed
+        drop(x);
+    }
+    // Deref and field from tuple-struct
+    {
+        let mut g = Box::new(Bar(22));
+        let x = g.x();
+        g.0; //[ast]~ ERROR cannot use `g.0` because it was mutably borrowed
+             //[mir]~^ ERROR cannot use `g.0` because it was mutably borrowed
+        drop(x);
+    }
+    // Deref and field from tuple
+    {
+        let mut h = Box::new((22, 23));
+        let x = &mut h.0;
+        h.0; //[ast]~ ERROR cannot use `h.0` because it was mutably borrowed
+             //[mir]~^ ERROR cannot use `h.0` because it was mutably borrowed
+        drop(x);
+    }
+    // Deref and field from enum
+    {
+        let mut e = Box::new(Baz::X(3));
+        let x = e.x();
+        match *e {
+            Baz::X(value) => value
+            //[ast]~^ ERROR cannot use `e.0` because it was mutably borrowed
+            //[mir]~^^ ERROR cannot use `e.0` because it was mutably borrowed
+        };
+        drop(x);
+    }
+    // Deref and field from union
+    unsafe {
+        let mut u = Box::new(U { b: 0 });
+        let x = &mut u.a;
+        u.a; //[ast]~ ERROR cannot use `u.a` because it was mutably borrowed
+             //[mir]~^ ERROR cannot use `u.a` because it was mutably borrowed
+        drop(x);
+    }
+    // Constant index
+    {
+        let mut v = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
+        let x = &mut v;
+        match v {
+            &[x, _, .., _, _] => println!("{}", x),
+                //[ast]~^ ERROR cannot use `v[..]` because it was mutably borrowed
+                //[mir]~^^ ERROR cannot use `v[..]` because it was mutably borrowed
+                            _ => panic!("other case"),
+        }
+        match v {
+            &[_, x, .., _, _] => println!("{}", x),
+                //[ast]~^ ERROR cannot use `v[..]` because it was mutably borrowed
+                //[mir]~^^ ERROR cannot use `v[..]` because it was mutably borrowed
+                            _ => panic!("other case"),
+        }
+        match v {
+            &[_, _, .., x, _] => println!("{}", x),
+                //[ast]~^ ERROR cannot use `v[..]` because it was mutably borrowed
+                //[mir]~^^ ERROR cannot use `v[..]` because it was mutably borrowed
+                            _ => panic!("other case"),
+        }
+        match v {
+            &[_, _, .., _, x] => println!("{}", x),
+                //[ast]~^ ERROR cannot use `v[..]` because it was mutably borrowed
+                //[mir]~^^ ERROR cannot use `v[..]` because it was mutably borrowed
+                            _ => panic!("other case"),
+        }
+        drop(x);
+    }
+    // Subslices
+    {
+        let mut v = &[1, 2, 3, 4, 5];
+        let x = &mut v;
+        match v {
+            &[x..] => println!("{:?}", x),
+                //[ast]~^ ERROR cannot use `v[..]` because it was mutably borrowed
+                //[mir]~^^ ERROR cannot use `v[..]` because it was mutably borrowed
+            _ => panic!("other case"),
+        }
+        match v {
+            &[_, x..] => println!("{:?}", x),
+                //[ast]~^ ERROR cannot use `v[..]` because it was mutably borrowed
+                //[mir]~^^ ERROR cannot use `v[..]` because it was mutably borrowed
+            _ => panic!("other case"),
+        }
+        match v {
+            &[x.., _] => println!("{:?}", x),
+                //[ast]~^ ERROR cannot use `v[..]` because it was mutably borrowed
+                //[mir]~^^ ERROR cannot use `v[..]` because it was mutably borrowed
+            _ => panic!("other case"),
+        }
+        match v {
+            &[_, x.., _] => println!("{:?}", x),
+                //[ast]~^ ERROR cannot use `v[..]` because it was mutably borrowed
+                //[mir]~^^ ERROR cannot use `v[..]` because it was mutably borrowed
+            _ => panic!("other case"),
+        }
+        drop(x);
+    }
+    // Downcasted field
+    {
+        enum E<X> { A(X), B { x: X } }
+
+        let mut e = E::A(3);
+        let x = &mut e;
+        match e {
+            E::A(ref ax) =>
+                //[ast]~^ ERROR cannot borrow `e.0` as immutable because `e` is also borrowed as mutable
+                //[mir]~^^ ERROR cannot borrow `e.0` as immutable because it is also borrowed as mutable
+                //[mir]~| ERROR cannot use `e` because it was mutably borrowed
+                println!("e.ax: {:?}", ax),
+            E::B { x: ref bx } =>
+                //[ast]~^ ERROR cannot borrow `e.x` as immutable because `e` is also borrowed as mutable
+                //[mir]~^^ ERROR cannot borrow `e.x` as immutable because it is also borrowed as mutable
+                println!("e.bx: {:?}", bx),
+        }
+        drop(x);
+    }
+    // Field in field
+    {
+        struct F { x: u32, y: u32 };
+        struct S { x: F, y: (u32, u32), };
+        let mut s = S { x: F { x: 1, y: 2}, y: (999, 998) };
+        let x = &mut s;
+        match s {
+            S  { y: (ref y0, _), .. } =>
+                //[ast]~^ ERROR cannot borrow `s.y.0` as immutable because `s` is also borrowed as mutable
+                //[mir]~^^ ERROR cannot borrow `s.y.0` as immutable because it is also borrowed as mutable
+                println!("y0: {:?}", y0),
+            _ => panic!("other case"),
+        }
+        match s {
+            S  { x: F { y: ref x0, .. }, .. } =>
+                //[ast]~^ ERROR cannot borrow `s.x.y` as immutable because `s` is also borrowed as mutable
+                //[mir]~^^ ERROR cannot borrow `s.x.y` as immutable because it is also borrowed as mutable
+                println!("x0: {:?}", x0),
+            _ => panic!("other case"),
+        }
+        drop(x);
+    }
+    // Field of ref
+    {
+        struct Block<'a> {
+            current: &'a u8,
+            unrelated: &'a u8,
+        };
+
+        fn bump<'a>(mut block: &mut Block<'a>) {
+            let x = &mut block;
+            let p: &'a u8 = &*block.current;
+            //[mir]~^ ERROR cannot borrow `*block.current` as immutable because it is also borrowed as mutable
+            // No errors in AST because of issue rust#38899
+            drop(x);
+        }
+    }
+    // Field of ptr
+    {
+        struct Block2 {
+            current: *const u8,
+            unrelated: *const u8,
+        }
+
+        unsafe fn bump2(mut block: *mut Block2) {
+            let x = &mut block;
+            let p : *const u8 = &*(*block).current;
+            //[mir]~^ ERROR cannot borrow `*block.current` as immutable because it is also borrowed as mutable
+            // No errors in AST because of issue rust#38899
+            drop(x);
+        }
+    }
+    // Field of index
+    {
+        struct F {x: u32, y: u32};
+        let mut v = &[F{x: 1, y: 2}, F{x: 3, y: 4}];
+        let x = &mut v;
+        v[0].y;
+        //[ast]~^ ERROR cannot use `v[..].y` because it was mutably borrowed
+        //[mir]~^^ ERROR cannot use `v[_].y` because it was mutably borrowed
+        //[mir]~| ERROR cannot use `*v` because it was mutably borrowed
+        drop(x);
+    }
+    // Field of constant index
+    {
+        struct F {x: u32, y: u32};
+        let mut v = &[F{x: 1, y: 2}, F{x: 3, y: 4}];
+        let x = &mut v;
+        match v {
+            &[_, F {x: ref xf, ..}] => println!("{}", xf),
+            //[mir]~^ ERROR cannot borrow `v[..].x` as immutable because it is also borrowed as mutable
+            // No errors in AST
+            _ => panic!("other case")
+        }
+        drop(x);
+    }
+    // Field from upvar
+    {
+        let mut x = 0;
+        || {
+            let y = &mut x;
+            &mut x; //[ast]~ ERROR cannot borrow `**x` as mutable more than once at a time
+                    //[mir]~^ ERROR cannot borrow `x` as mutable more than once at a time
+            *y = 1;
+        };
+    }
+    // Field from upvar nested
+    {
+        let mut x = 0;
+           || {
+               || { //[mir]~ ERROR captured variable cannot escape `FnMut` closure body
+                   let y = &mut x;
+                   &mut x; //[ast]~ ERROR cannot borrow `**x` as mutable more than once at a time
+                   //[mir]~^ ERROR cannot borrow `x` as mutable more than once at a time
+                   *y = 1;
+                   drop(y);
+                }
+           };
+    }
+    {
+        fn foo(x: Vec<i32>) {
+            let c = || {
+                drop(x);
+                drop(x); //[ast]~ ERROR use of moved value: `x`
+                         //[mir]~^ ERROR use of moved value: `x`
+            };
+            c();
+        }
+    }
+}
diff --git a/src/test/ui/borrowck/borrowck-drop-from-guard.rs b/src/test/ui/borrowck/borrowck-drop-from-guard.rs
new file mode 100644
index 0000000..67a2275
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-drop-from-guard.rs
@@ -0,0 +1,13 @@
+//compile-flags: -Z borrowck=mir
+
+fn foo(_:String) {}
+
+fn main()
+{
+    let my_str = "hello".to_owned();
+    match Some(42) {
+        Some(_) if { drop(my_str); false } => {}
+        Some(_) => {}
+        None => { foo(my_str); } //~ ERROR [E0382]
+    }
+}
diff --git a/src/test/ui/borrowck/borrowck-drop-from-guard.stderr b/src/test/ui/borrowck/borrowck-drop-from-guard.stderr
new file mode 100644
index 0000000..a2b42fa
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-drop-from-guard.stderr
@@ -0,0 +1,15 @@
+error[E0382]: use of moved value: `my_str`
+  --> $DIR/borrowck-drop-from-guard.rs:11:23
+   |
+LL |     let my_str = "hello".to_owned();
+   |         ------ move occurs because `my_str` has type `std::string::String`, which does not implement the `Copy` trait
+LL |     match Some(42) {
+LL |         Some(_) if { drop(my_str); false } => {}
+   |                           ------ value moved here
+LL |         Some(_) => {}
+LL |         None => { foo(my_str); }
+   |                       ^^^^^^ value used here after move
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/borrowck-escaping-closure-error-1.nll.stderr b/src/test/ui/borrowck/borrowck-escaping-closure-error-1.nll.stderr
new file mode 100644
index 0000000..3195120
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-escaping-closure-error-1.nll.stderr
@@ -0,0 +1,21 @@
+error[E0373]: closure may outlive the current function, but it borrows `books`, which is owned by the current function
+  --> $DIR/borrowck-escaping-closure-error-1.rs:13:11
+   |
+LL |     spawn(|| books.push(4));
+   |           ^^ ----- `books` is borrowed here
+   |           |
+   |           may outlive borrowed value `books`
+   |
+note: function requires argument type to outlive `'static`
+  --> $DIR/borrowck-escaping-closure-error-1.rs:13:5
+   |
+LL |     spawn(|| books.push(4));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+help: to force the closure to take ownership of `books` (and any other referenced variables), use the `move` keyword
+   |
+LL |     spawn(move || books.push(4));
+   |           ^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0373`.
diff --git a/src/test/ui/borrowck/borrowck-escaping-closure-error-1.rs b/src/test/ui/borrowck/borrowck-escaping-closure-error-1.rs
new file mode 100644
index 0000000..11c0610
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-escaping-closure-error-1.rs
@@ -0,0 +1,15 @@
+use std::thread::spawn;
+
+// Test that we give a custom error (E0373) for the case where a
+// closure is escaping current frame, and offer a suggested code edit.
+// I refrained from including the precise message here, but the
+// original text as of the time of this writing is:
+//
+//    closure may outlive the current function, but it borrows `books`,
+//    which is owned by the current function
+
+fn main() {
+    let mut books = vec![1,2,3];
+    spawn(|| books.push(4));
+    //~^ ERROR E0373
+}
diff --git a/src/test/ui/borrowck/borrowck-escaping-closure-error-1.stderr b/src/test/ui/borrowck/borrowck-escaping-closure-error-1.stderr
new file mode 100644
index 0000000..16ba61d
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-escaping-closure-error-1.stderr
@@ -0,0 +1,15 @@
+error[E0373]: closure may outlive the current function, but it borrows `books`, which is owned by the current function
+  --> $DIR/borrowck-escaping-closure-error-1.rs:13:11
+   |
+LL |     spawn(|| books.push(4));
+   |           ^^ ----- `books` is borrowed here
+   |           |
+   |           may outlive borrowed value `books`
+help: to force the closure to take ownership of `books` (and any other referenced variables), use the `move` keyword
+   |
+LL |     spawn(move || books.push(4));
+   |           ^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0373`.
diff --git a/src/test/ui/borrowck/borrowck-escaping-closure-error-2.nll.stderr b/src/test/ui/borrowck/borrowck-escaping-closure-error-2.nll.stderr
new file mode 100644
index 0000000..3227aa9b
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-escaping-closure-error-2.nll.stderr
@@ -0,0 +1,21 @@
+error[E0373]: closure may outlive the current function, but it borrows `books`, which is owned by the current function
+  --> $DIR/borrowck-escaping-closure-error-2.rs:11:14
+   |
+LL |     Box::new(|| books.push(4))
+   |              ^^ ----- `books` is borrowed here
+   |              |
+   |              may outlive borrowed value `books`
+   |
+note: closure is returned here
+  --> $DIR/borrowck-escaping-closure-error-2.rs:11:5
+   |
+LL |     Box::new(|| books.push(4))
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: to force the closure to take ownership of `books` (and any other referenced variables), use the `move` keyword
+   |
+LL |     Box::new(move || books.push(4))
+   |              ^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0373`.
diff --git a/src/test/ui/borrowck/borrowck-escaping-closure-error-2.rs b/src/test/ui/borrowck/borrowck-escaping-closure-error-2.rs
new file mode 100644
index 0000000..a44e303
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-escaping-closure-error-2.rs
@@ -0,0 +1,15 @@
+// Test that we give a custom error (E0373) for the case where a
+// closure is escaping current frame, and offer a suggested code edit.
+// I refrained from including the precise message here, but the
+// original text as of the time of this writing is:
+//
+//    closure may outlive the current function, but it borrows `books`,
+//    which is owned by the current function
+
+fn foo<'a>(x: &'a i32) -> Box<FnMut()+'a> {
+    let mut books = vec![1,2,3];
+    Box::new(|| books.push(4))
+    //~^ ERROR E0373
+}
+
+fn main() { }
diff --git a/src/test/ui/borrowck/borrowck-escaping-closure-error-2.stderr b/src/test/ui/borrowck/borrowck-escaping-closure-error-2.stderr
new file mode 100644
index 0000000..960f65d
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-escaping-closure-error-2.stderr
@@ -0,0 +1,15 @@
+error[E0373]: closure may outlive the current function, but it borrows `books`, which is owned by the current function
+  --> $DIR/borrowck-escaping-closure-error-2.rs:11:14
+   |
+LL |     Box::new(|| books.push(4))
+   |              ^^ ----- `books` is borrowed here
+   |              |
+   |              may outlive borrowed value `books`
+help: to force the closure to take ownership of `books` (and any other referenced variables), use the `move` keyword
+   |
+LL |     Box::new(move || books.push(4))
+   |              ^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0373`.
diff --git a/src/test/ui/borrowck/borrowck-feature-nll-overrides-migrate.edition.stderr b/src/test/ui/borrowck/borrowck-feature-nll-overrides-migrate.edition.stderr
new file mode 100644
index 0000000..9059ef4
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-feature-nll-overrides-migrate.edition.stderr
@@ -0,0 +1,9 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/borrowck-feature-nll-overrides-migrate.rs:22:17
+   |
+LL |                 (|| { let bar = foo; bar.take() })();
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/borrowck/borrowck-feature-nll-overrides-migrate.rs b/src/test/ui/borrowck/borrowck-feature-nll-overrides-migrate.rs
new file mode 100644
index 0000000..4eefc58
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-feature-nll-overrides-migrate.rs
@@ -0,0 +1,30 @@
+// This is a test that the `#![feature(nll)]` opt-in overrides the
+// migration mode. The intention here is to emulate the goal behavior
+// that `--edition 2018` effects on borrowck (modeled here by `-Z
+// borrowck=migrate`) are themselves overridden by the
+// `#![feature(nll)]` opt-in.
+//
+// Therefore, for developer convenience, under `#[feature(nll)]` the
+// NLL checks will be emitted as errors *even* in the presence of `-Z
+// borrowck=migrate`.
+
+// revisions: zflag edition
+// [zflag]compile-flags: -Z borrowck=migrate
+// [edition]edition:2018
+
+#![feature(nll)]
+
+fn main() {
+    match Some(&4) {
+        None => {},
+        ref mut foo
+            if {
+                (|| { let bar = foo; bar.take() })();
+                //[zflag]~^ ERROR cannot move out of borrowed content [E0507]
+                //[edition]~^^ ERROR cannot move out of borrowed content [E0507]
+                false
+            } => {},
+        Some(ref _s) => println!("Note this arm is bogus; the `Some` became `None` in the guard."),
+        _ => println!("Here is some supposedly unreachable code."),
+    }
+}
diff --git a/src/test/ui/borrowck/borrowck-feature-nll-overrides-migrate.zflag.stderr b/src/test/ui/borrowck/borrowck-feature-nll-overrides-migrate.zflag.stderr
new file mode 100644
index 0000000..9059ef4
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-feature-nll-overrides-migrate.zflag.stderr
@@ -0,0 +1,9 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/borrowck-feature-nll-overrides-migrate.rs:22:17
+   |
+LL |                 (|| { let bar = foo; bar.take() })();
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/borrowck/borrowck-field-sensitivity.nll.stderr b/src/test/ui/borrowck/borrowck-field-sensitivity.nll.stderr
new file mode 100644
index 0000000..b345165
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-field-sensitivity.nll.stderr
@@ -0,0 +1,132 @@
+error[E0382]: use of moved value: `x.b`
+  --> $DIR/borrowck-field-sensitivity.rs:8:10
+   |
+LL |     drop(x.b);
+   |          --- value moved here
+LL |     drop(*x.b);
+   |          ^^^^ value used here after move
+   |
+   = note: move occurs because `x.b` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `x.b`
+  --> $DIR/borrowck-field-sensitivity.rs:14:10
+   |
+LL |     let y = A { a: 3, .. x };
+   |             ---------------- value moved here
+LL |     drop(*x.b);
+   |          ^^^^ value used here after move
+   |
+   = note: move occurs because `x.b` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+
+error[E0382]: borrow of moved value: `x.b`
+  --> $DIR/borrowck-field-sensitivity.rs:20:13
+   |
+LL |     drop(x.b);
+   |          --- value moved here
+LL |     let p = &x.b;
+   |             ^^^^ value borrowed here after move
+   |
+   = note: move occurs because `x.b` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+
+error[E0382]: borrow of moved value: `x.b`
+  --> $DIR/borrowck-field-sensitivity.rs:27:13
+   |
+LL |     let _y = A { a: 3, .. x };
+   |              ---------------- value moved here
+LL |     let p = &x.b;
+   |             ^^^^ value borrowed here after move
+   |
+   = note: move occurs because `x.b` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+
+error[E0505]: cannot move out of `x.b` because it is borrowed
+  --> $DIR/borrowck-field-sensitivity.rs:34:10
+   |
+LL |     let p = &x.b;
+   |             ---- borrow of `x.b` occurs here
+LL |     drop(x.b);
+   |          ^^^ move out of `x.b` occurs here
+LL |     drop(**p);
+   |          --- borrow later used here
+
+error[E0505]: cannot move out of `x.b` because it is borrowed
+  --> $DIR/borrowck-field-sensitivity.rs:41:14
+   |
+LL |     let p = &x.b;
+   |             ---- borrow of `x.b` occurs here
+LL |     let _y = A { a: 3, .. x };
+   |              ^^^^^^^^^^^^^^^^ move out of `x.b` occurs here
+LL |     drop(**p);
+   |          --- borrow later used here
+
+error[E0499]: cannot borrow `x.a` as mutable more than once at a time
+  --> $DIR/borrowck-field-sensitivity.rs:48:13
+   |
+LL |     let p = &mut x.a;
+   |             -------- first mutable borrow occurs here
+LL |     let q = &mut x.a;
+   |             ^^^^^^^^ second mutable borrow occurs here
+LL |     drop(*p);
+   |          -- first borrow later used here
+
+error[E0382]: use of moved value: `x.b`
+  --> $DIR/borrowck-field-sensitivity.rs:56:10
+   |
+LL |     drop(x.b);
+   |          --- value moved here
+LL |     drop(x.b);
+   |          ^^^ value used here after move
+   |
+   = note: move occurs because `x.b` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `x.b`
+  --> $DIR/borrowck-field-sensitivity.rs:62:10
+   |
+LL |     let _y = A { a: 3, .. x };
+   |              ---------------- value moved here
+LL |     drop(x.b);
+   |          ^^^ value used here after move
+   |
+   = note: move occurs because `x.b` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `x.b`
+  --> $DIR/borrowck-field-sensitivity.rs:68:14
+   |
+LL |     drop(x.b);
+   |          --- value moved here
+LL |     let _z = A { a: 3, .. x };
+   |              ^^^^^^^^^^^^^^^^ value used here after move
+   |
+   = note: move occurs because `x.b` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `x.b`
+  --> $DIR/borrowck-field-sensitivity.rs:74:14
+   |
+LL |     let _y = A { a: 3, .. x };
+   |              ---------------- value moved here
+LL |     let _z = A { a: 4, .. x };
+   |              ^^^^^^^^^^^^^^^^ value used here after move
+   |
+   = note: move occurs because `x.b` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+
+error[E0381]: assign to part of possibly uninitialized variable: `x`
+  --> $DIR/borrowck-field-sensitivity.rs:81:5
+   |
+LL |     x.a = 1;
+   |     ^^^^^^^ use of possibly uninitialized `x`
+
+error[E0381]: assign to part of possibly uninitialized variable: `x`
+  --> $DIR/borrowck-field-sensitivity.rs:87:5
+   |
+LL |     x.a = 1;
+   |     ^^^^^^^ use of possibly uninitialized `x`
+
+error[E0381]: assign to part of possibly uninitialized variable: `x`
+  --> $DIR/borrowck-field-sensitivity.rs:94:5
+   |
+LL |     x.b = box 1;
+   |     ^^^ use of possibly uninitialized `x`
+
+error: aborting due to 14 previous errors
+
+Some errors occurred: E0381, E0382, E0499, E0505.
+For more information about an error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/borrowck-field-sensitivity.rs b/src/test/ui/borrowck/borrowck-field-sensitivity.rs
new file mode 100644
index 0000000..1e9e6d6
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-field-sensitivity.rs
@@ -0,0 +1,116 @@
+#![feature(box_syntax)]
+
+struct A { a: isize, b: Box<isize> }
+
+fn deref_after_move() {
+    let x = A { a: 1, b: box 2 };
+    drop(x.b);
+    drop(*x.b); //~ ERROR use of moved value: `*x.b`
+}
+
+fn deref_after_fu_move() {
+    let x = A { a: 1, b: box 2 };
+    let y = A { a: 3, .. x };
+    drop(*x.b); //~ ERROR use of moved value: `*x.b`
+}
+
+fn borrow_after_move() {
+    let x = A { a: 1, b: box 2 };
+    drop(x.b);
+    let p = &x.b; //~ ERROR use of moved value: `x.b`
+    drop(**p);
+}
+
+fn borrow_after_fu_move() {
+    let x = A { a: 1, b: box 2 };
+    let _y = A { a: 3, .. x };
+    let p = &x.b; //~ ERROR use of moved value: `x.b`
+    drop(**p);
+}
+
+fn move_after_borrow() {
+    let x = A { a: 1, b: box 2 };
+    let p = &x.b;
+    drop(x.b); //~ ERROR cannot move out of `x.b` because it is borrowed
+    drop(**p);
+}
+
+fn fu_move_after_borrow() {
+    let x = A { a: 1, b: box 2 };
+    let p = &x.b;
+    let _y = A { a: 3, .. x }; //~ ERROR cannot move out of `x.b` because it is borrowed
+    drop(**p);
+}
+
+fn mut_borrow_after_mut_borrow() {
+    let mut x = A { a: 1, b: box 2 };
+    let p = &mut x.a;
+    let q = &mut x.a; //~ ERROR cannot borrow `x.a` as mutable more than once at a time
+    drop(*p);
+    drop(*q);
+}
+
+fn move_after_move() {
+    let x = A { a: 1, b: box 2 };
+    drop(x.b);
+    drop(x.b);  //~ ERROR use of moved value: `x.b`
+}
+
+fn move_after_fu_move() {
+    let x = A { a: 1, b: box 2 };
+    let _y = A { a: 3, .. x };
+    drop(x.b);  //~ ERROR use of moved value: `x.b`
+}
+
+fn fu_move_after_move() {
+    let x = A { a: 1, b: box 2 };
+    drop(x.b);
+    let _z = A { a: 3, .. x };  //~ ERROR use of moved value: `x.b`
+}
+
+fn fu_move_after_fu_move() {
+    let x = A { a: 1, b: box 2 };
+    let _y = A { a: 3, .. x };
+    let _z = A { a: 4, .. x };  //~ ERROR use of moved value: `x.b`
+}
+
+// The following functions aren't yet accepted, but they should be.
+
+fn copy_after_field_assign_after_uninit() {
+    let mut x: A;
+    x.a = 1;
+    drop(x.a); //~ ERROR use of possibly uninitialized variable: `x.a`
+}
+
+fn borrow_after_field_assign_after_uninit() {
+    let mut x: A;
+    x.a = 1;
+    let p = &x.a; //~ ERROR use of possibly uninitialized variable: `x.a`
+    drop(*p);
+}
+
+fn move_after_field_assign_after_uninit() {
+    let mut x: A;
+    x.b = box 1;
+    drop(x.b); //~ ERROR use of possibly uninitialized variable: `x.b`
+}
+
+fn main() {
+    deref_after_move();
+    deref_after_fu_move();
+
+    borrow_after_move();
+    borrow_after_fu_move();
+    move_after_borrow();
+    fu_move_after_borrow();
+    mut_borrow_after_mut_borrow();
+
+    move_after_move();
+    move_after_fu_move();
+    fu_move_after_move();
+    fu_move_after_fu_move();
+
+    copy_after_field_assign_after_uninit();
+    borrow_after_field_assign_after_uninit();
+    move_after_field_assign_after_uninit();
+}
diff --git a/src/test/ui/borrowck/borrowck-field-sensitivity.stderr b/src/test/ui/borrowck/borrowck-field-sensitivity.stderr
new file mode 100644
index 0000000..0cf6f3f
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-field-sensitivity.stderr
@@ -0,0 +1,129 @@
+error[E0382]: use of moved value: `*x.b`
+  --> $DIR/borrowck-field-sensitivity.rs:8:10
+   |
+LL |     drop(x.b);
+   |          --- value moved here
+LL |     drop(*x.b);
+   |          ^^^^ value used here after move
+   |
+   = note: move occurs because `x.b` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `*x.b`
+  --> $DIR/borrowck-field-sensitivity.rs:14:10
+   |
+LL |     let y = A { a: 3, .. x };
+   |                          - value moved here
+LL |     drop(*x.b);
+   |          ^^^^ value used here after move
+   |
+   = note: move occurs because `x.b` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `x.b`
+  --> $DIR/borrowck-field-sensitivity.rs:20:14
+   |
+LL |     drop(x.b);
+   |          --- value moved here
+LL |     let p = &x.b;
+   |              ^^^ value used here after move
+   |
+   = note: move occurs because `x.b` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `x.b`
+  --> $DIR/borrowck-field-sensitivity.rs:27:14
+   |
+LL |     let _y = A { a: 3, .. x };
+   |                           - value moved here
+LL |     let p = &x.b;
+   |              ^^^ value used here after move
+   |
+   = note: move occurs because `x.b` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+
+error[E0505]: cannot move out of `x.b` because it is borrowed
+  --> $DIR/borrowck-field-sensitivity.rs:34:10
+   |
+LL |     let p = &x.b;
+   |              --- borrow of `x.b` occurs here
+LL |     drop(x.b);
+   |          ^^^ move out of `x.b` occurs here
+
+error[E0505]: cannot move out of `x.b` because it is borrowed
+  --> $DIR/borrowck-field-sensitivity.rs:41:27
+   |
+LL |     let p = &x.b;
+   |              --- borrow of `x.b` occurs here
+LL |     let _y = A { a: 3, .. x };
+   |                           ^ move out of `x.b` occurs here
+
+error[E0499]: cannot borrow `x.a` as mutable more than once at a time
+  --> $DIR/borrowck-field-sensitivity.rs:48:18
+   |
+LL |     let p = &mut x.a;
+   |                  --- first mutable borrow occurs here
+LL |     let q = &mut x.a;
+   |                  ^^^ second mutable borrow occurs here
+...
+LL | }
+   | - first borrow ends here
+
+error[E0382]: use of moved value: `x.b`
+  --> $DIR/borrowck-field-sensitivity.rs:56:10
+   |
+LL |     drop(x.b);
+   |          --- value moved here
+LL |     drop(x.b);
+   |          ^^^ value used here after move
+   |
+   = note: move occurs because `x.b` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `x.b`
+  --> $DIR/borrowck-field-sensitivity.rs:62:10
+   |
+LL |     let _y = A { a: 3, .. x };
+   |                           - value moved here
+LL |     drop(x.b);
+   |          ^^^ value used here after move
+   |
+   = note: move occurs because `x.b` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `x.b`
+  --> $DIR/borrowck-field-sensitivity.rs:68:27
+   |
+LL |     drop(x.b);
+   |          --- value moved here
+LL |     let _z = A { a: 3, .. x };
+   |                           ^ value used here after move
+   |
+   = note: move occurs because `x.b` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `x.b`
+  --> $DIR/borrowck-field-sensitivity.rs:74:27
+   |
+LL |     let _y = A { a: 3, .. x };
+   |                           - value moved here
+LL |     let _z = A { a: 4, .. x };
+   |                           ^ value used here after move
+   |
+   = note: move occurs because `x.b` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+
+error[E0381]: use of possibly uninitialized variable: `x.a`
+  --> $DIR/borrowck-field-sensitivity.rs:82:10
+   |
+LL |     drop(x.a);
+   |          ^^^ use of possibly uninitialized `x.a`
+
+error[E0381]: use of possibly uninitialized variable: `x.a`
+  --> $DIR/borrowck-field-sensitivity.rs:88:14
+   |
+LL |     let p = &x.a;
+   |              ^^^ use of possibly uninitialized `x.a`
+
+error[E0381]: use of possibly uninitialized variable: `x.b`
+  --> $DIR/borrowck-field-sensitivity.rs:95:10
+   |
+LL |     drop(x.b);
+   |          ^^^ use of possibly uninitialized `x.b`
+
+error: aborting due to 14 previous errors
+
+Some errors occurred: E0381, E0382, E0499, E0505.
+For more information about an error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/borrowck-fn-in-const-a.ast.stderr b/src/test/ui/borrowck/borrowck-fn-in-const-a.ast.stderr
new file mode 100644
index 0000000..16c62fc
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-fn-in-const-a.ast.stderr
@@ -0,0 +1,9 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/borrowck-fn-in-const-a.rs:9:16
+   |
+LL |         return *x
+   |                ^^ cannot move out of borrowed content
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/borrowck/borrowck-fn-in-const-a.mir.stderr b/src/test/ui/borrowck/borrowck-fn-in-const-a.mir.stderr
new file mode 100644
index 0000000..16c62fc
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-fn-in-const-a.mir.stderr
@@ -0,0 +1,9 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/borrowck-fn-in-const-a.rs:9:16
+   |
+LL |         return *x
+   |                ^^ cannot move out of borrowed content
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/borrowck/borrowck-fn-in-const-a.rs b/src/test/ui/borrowck/borrowck-fn-in-const-a.rs
new file mode 100644
index 0000000..17663a3
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-fn-in-const-a.rs
@@ -0,0 +1,16 @@
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+// Check that we check fns appearing in constant declarations.
+// Issue #22382.
+
+const MOVE: fn(&String) -> String = {
+    fn broken(x: &String) -> String {
+        return *x //[ast]~ ERROR cannot move out of borrowed content [E0507]
+                  //[mir]~^ ERROR [E0507]
+    }
+    broken
+};
+
+fn main() {
+}
diff --git a/src/test/ui/borrowck/borrowck-fn-in-const-c.nll.stderr b/src/test/ui/borrowck/borrowck-fn-in-const-c.nll.stderr
new file mode 100644
index 0000000..d48866dc
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-fn-in-const-c.nll.stderr
@@ -0,0 +1,11 @@
+error[E0713]: borrow may still be in use when destructor runs
+  --> $DIR/borrowck-fn-in-const-c.rs:17:16
+   |
+LL |         return &local.inner;
+   |                ^^^^^^^^^^^^ returning this value requires that `local.inner` is borrowed for `'static`
+LL |     }
+   |     - here, drop of `local` needs exclusive access to `local.inner`, because the type `DropString` implements the `Drop` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0713`.
diff --git a/src/test/ui/borrowck/borrowck-fn-in-const-c.rs b/src/test/ui/borrowck/borrowck-fn-in-const-c.rs
new file mode 100644
index 0000000..d0a2e5b
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-fn-in-const-c.rs
@@ -0,0 +1,23 @@
+// Check that we check fns appearing in constant declarations.
+// Issue #22382.
+
+// Returning local references?
+struct DropString {
+    inner: String
+}
+impl Drop for DropString {
+    fn drop(&mut self) {
+        self.inner.clear();
+        self.inner.push_str("dropped");
+    }
+}
+const LOCAL_REF: fn() -> &'static str = {
+    fn broken() -> &'static str {
+        let local = DropString { inner: format!("Some local string") };
+        return &local.inner; //~ ERROR does not live long enough
+    }
+    broken
+};
+
+fn main() {
+}
diff --git a/src/test/ui/borrowck/borrowck-fn-in-const-c.stderr b/src/test/ui/borrowck/borrowck-fn-in-const-c.stderr
new file mode 100644
index 0000000..d2ddf80
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-fn-in-const-c.stderr
@@ -0,0 +1,13 @@
+error[E0597]: `local.inner` does not live long enough
+  --> $DIR/borrowck-fn-in-const-c.rs:17:17
+   |
+LL |         return &local.inner;
+   |                 ^^^^^^^^^^^ borrowed value does not live long enough
+LL |     }
+   |     - borrowed value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/borrowck/borrowck-for-loop-correct-cmt-for-pattern.nll.stderr b/src/test/ui/borrowck/borrowck-for-loop-correct-cmt-for-pattern.nll.stderr
new file mode 100644
index 0000000..08cafa7
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-for-loop-correct-cmt-for-pattern.nll.stderr
@@ -0,0 +1,48 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/borrowck-for-loop-correct-cmt-for-pattern.rs:12:15
+   |
+LL |     for &a in x.iter() {
+   |         --    ^^^^^^^^ cannot move out of borrowed content
+   |         ||
+   |         |data moved here
+   |         help: consider removing the `&`: `a`
+   |
+note: move occurs because `a` has type `&mut i32`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-for-loop-correct-cmt-for-pattern.rs:12:10
+   |
+LL |     for &a in x.iter() {
+   |          ^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/borrowck-for-loop-correct-cmt-for-pattern.rs:18:15
+   |
+LL |     for &a in &f.a {
+   |         --    ^^^^ cannot move out of borrowed content
+   |         ||
+   |         |data moved here
+   |         help: consider removing the `&`: `a`
+   |
+note: move occurs because `a` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-for-loop-correct-cmt-for-pattern.rs:18:10
+   |
+LL |     for &a in &f.a {
+   |          ^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/borrowck-for-loop-correct-cmt-for-pattern.rs:22:15
+   |
+LL |     for &a in x.iter() {
+   |         --    ^^^^^^^^ cannot move out of borrowed content
+   |         ||
+   |         |data moved here
+   |         help: consider removing the `&`: `a`
+   |
+note: move occurs because `a` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-for-loop-correct-cmt-for-pattern.rs:22:10
+   |
+LL |     for &a in x.iter() {
+   |          ^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/borrowck/borrowck-for-loop-correct-cmt-for-pattern.rs b/src/test/ui/borrowck/borrowck-for-loop-correct-cmt-for-pattern.rs
new file mode 100644
index 0000000..de75368
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-for-loop-correct-cmt-for-pattern.rs
@@ -0,0 +1,24 @@
+// Issue #16205.
+
+#![feature(box_syntax)]
+
+struct Foo {
+    a: [Box<isize>; 3],
+}
+
+fn main() {
+    let mut y = 1;
+    let x = Some(&mut y);
+    for &a in x.iter() {    //~ ERROR cannot move out
+    }
+
+    let f = Foo {
+        a: [box 3, box 4, box 5],
+    };
+    for &a in &f.a {  //~ ERROR cannot move out
+    }
+
+    let x: Option<Box<_>> = Some(box 1);
+    for &a in x.iter() {    //~ ERROR cannot move out
+    }
+}
diff --git a/src/test/ui/borrowck/borrowck-for-loop-correct-cmt-for-pattern.stderr b/src/test/ui/borrowck/borrowck-for-loop-correct-cmt-for-pattern.stderr
new file mode 100644
index 0000000..fb53b13
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-for-loop-correct-cmt-for-pattern.stderr
@@ -0,0 +1,30 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/borrowck-for-loop-correct-cmt-for-pattern.rs:12:9
+   |
+LL |     for &a in x.iter() {
+   |         ^-
+   |         ||
+   |         |hint: to prevent move, use `ref a` or `ref mut a`
+   |         cannot move out of borrowed content
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/borrowck-for-loop-correct-cmt-for-pattern.rs:18:9
+   |
+LL |     for &a in &f.a {
+   |         ^-
+   |         ||
+   |         |hint: to prevent move, use `ref a` or `ref mut a`
+   |         cannot move out of borrowed content
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/borrowck-for-loop-correct-cmt-for-pattern.rs:22:9
+   |
+LL |     for &a in x.iter() {
+   |         ^-
+   |         ||
+   |         |hint: to prevent move, use `ref a` or `ref mut a`
+   |         cannot move out of borrowed content
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/borrowck/borrowck-for-loop-head-linkage.nll.stderr b/src/test/ui/borrowck/borrowck-for-loop-head-linkage.nll.stderr
new file mode 100644
index 0000000..f47dce4
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-for-loop-head-linkage.nll.stderr
@@ -0,0 +1,27 @@
+error[E0502]: cannot borrow `vector` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-for-loop-head-linkage.rs:7:9
+   |
+LL |     for &x in &vector {
+   |               -------
+   |               |
+   |               immutable borrow occurs here
+   |               immutable borrow later used here
+LL |         let cap = vector.capacity();
+LL |         vector.extend(repeat(0));
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
+
+error[E0502]: cannot borrow `vector` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-for-loop-head-linkage.rs:8:9
+   |
+LL |     for &x in &vector {
+   |               -------
+   |               |
+   |               immutable borrow occurs here
+   |               immutable borrow later used here
+...
+LL |         vector[1] = 5;
+   |         ^^^^^^ mutable borrow occurs here
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/borrowck/borrowck-for-loop-head-linkage.rs b/src/test/ui/borrowck/borrowck-for-loop-head-linkage.rs
new file mode 100644
index 0000000..a84b695
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-for-loop-head-linkage.rs
@@ -0,0 +1,10 @@
+use std::iter::repeat;
+
+fn main() {
+    let mut vector = vec![1, 2];
+    for &x in &vector {
+        let cap = vector.capacity();
+        vector.extend(repeat(0));      //~ ERROR cannot borrow
+        vector[1] = 5;   //~ ERROR cannot borrow
+    }
+}
diff --git a/src/test/ui/borrowck/borrowck-for-loop-head-linkage.stderr b/src/test/ui/borrowck/borrowck-for-loop-head-linkage.stderr
new file mode 100644
index 0000000..a2d8908
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-for-loop-head-linkage.stderr
@@ -0,0 +1,27 @@
+error[E0502]: cannot borrow `vector` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-for-loop-head-linkage.rs:7:9
+   |
+LL |     for &x in &vector {
+   |                ------
+   |                |    |
+   |                |    immutable borrow ends here
+   |                immutable borrow occurs here
+LL |         let cap = vector.capacity();
+LL |         vector.extend(repeat(0));
+   |         ^^^^^^ mutable borrow occurs here
+
+error[E0502]: cannot borrow `vector` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-for-loop-head-linkage.rs:8:9
+   |
+LL |     for &x in &vector {
+   |                ------
+   |                |    |
+   |                |    immutable borrow ends here
+   |                immutable borrow occurs here
+...
+LL |         vector[1] = 5;
+   |         ^^^^^^ mutable borrow occurs here
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/borrowck/borrowck-if-no-else.rs b/src/test/ui/borrowck/borrowck-if-no-else.rs
new file mode 100644
index 0000000..044db99
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-if-no-else.rs
@@ -0,0 +1,6 @@
+fn foo(x: isize) { println!("{}", x); }
+
+fn main() {
+    let x: isize; if 1 > 2 { x = 10; }
+    foo(x); //~ ERROR use of possibly uninitialized variable: `x`
+}
diff --git a/src/test/ui/borrowck/borrowck-if-no-else.stderr b/src/test/ui/borrowck/borrowck-if-no-else.stderr
new file mode 100644
index 0000000..1223e40
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-if-no-else.stderr
@@ -0,0 +1,9 @@
+error[E0381]: use of possibly uninitialized variable: `x`
+  --> $DIR/borrowck-if-no-else.rs:5:9
+   |
+LL |     foo(x);
+   |         ^ use of possibly uninitialized `x`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/borrowck-if-with-else.rs b/src/test/ui/borrowck/borrowck-if-with-else.rs
new file mode 100644
index 0000000..f632d61
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-if-with-else.rs
@@ -0,0 +1,11 @@
+fn foo(x: isize) { println!("{}", x); }
+
+fn main() {
+    let x: isize;
+    if 1 > 2 {
+        println!("whoops");
+    } else {
+        x = 10;
+    }
+    foo(x); //~ ERROR use of possibly uninitialized variable: `x`
+}
diff --git a/src/test/ui/borrowck/borrowck-if-with-else.stderr b/src/test/ui/borrowck/borrowck-if-with-else.stderr
new file mode 100644
index 0000000..d11f29b
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-if-with-else.stderr
@@ -0,0 +1,9 @@
+error[E0381]: use of possibly uninitialized variable: `x`
+  --> $DIR/borrowck-if-with-else.rs:10:9
+   |
+LL |     foo(x);
+   |         ^ use of possibly uninitialized `x`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.ast.nll.stderr b/src/test/ui/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.ast.nll.stderr
new file mode 100644
index 0000000..88b43c1
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.ast.nll.stderr
@@ -0,0 +1,15 @@
+error[E0506]: cannot assign to `_a` because it is borrowed
+  --> $DIR/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.rs:9:9
+   |
+LL |     let b = &mut _a;
+   |             ------- borrow of `_a` occurs here
+...
+LL |         _a = 4;
+   |         ^^^^^^ assignment to borrowed `_a` occurs here
+...
+LL |     drop(b);
+   |          - borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.ast.stderr b/src/test/ui/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.ast.stderr
new file mode 100644
index 0000000..43c3c33
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.ast.stderr
@@ -0,0 +1,12 @@
+error[E0506]: cannot assign to `_a` because it is borrowed
+  --> $DIR/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.rs:9:9
+   |
+LL |     let b = &mut _a;
+   |                  -- borrow of `_a` occurs here
+...
+LL |         _a = 4;
+   |         ^^^^^^ assignment to borrowed `_a` occurs here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.mir.stderr b/src/test/ui/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.mir.stderr
new file mode 100644
index 0000000..88b43c1
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.mir.stderr
@@ -0,0 +1,15 @@
+error[E0506]: cannot assign to `_a` because it is borrowed
+  --> $DIR/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.rs:9:9
+   |
+LL |     let b = &mut _a;
+   |             ------- borrow of `_a` occurs here
+...
+LL |         _a = 4;
+   |         ^^^^^^ assignment to borrowed `_a` occurs here
+...
+LL |     drop(b);
+   |          - borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.rs b/src/test/ui/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.rs
new file mode 100644
index 0000000..334d2e0
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.rs
@@ -0,0 +1,14 @@
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+fn main() {
+    let mut _a = 3;
+    let b = &mut _a;
+    {
+        let c = &*b;
+        _a = 4; //[ast]~ ERROR cannot assign to `_a`
+        //[mir]~^ ERROR cannot assign to `_a` because it is borrowed
+        drop(c);
+    }
+    drop(b);
+}
diff --git a/src/test/ui/borrowck/borrowck-in-static.nll.stderr b/src/test/ui/borrowck/borrowck-in-static.nll.stderr
new file mode 100644
index 0000000..da639a8
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-in-static.nll.stderr
@@ -0,0 +1,11 @@
+error[E0507]: cannot move out of captured variable in an `Fn` closure
+  --> $DIR/borrowck-in-static.rs:5:17
+   |
+LL |     let x = Box::new(0);
+   |         - captured outer variable
+LL |     Box::new(|| x)
+   |                 ^ cannot move out of captured variable in an `Fn` closure
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/borrowck/borrowck-in-static.rs b/src/test/ui/borrowck/borrowck-in-static.rs
new file mode 100644
index 0000000..c08f413
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-in-static.rs
@@ -0,0 +1,12 @@
+// check that borrowck looks inside consts/statics
+
+static FN : &'static (Fn() -> (Box<Fn()->Box<i32>>) + Sync) = &|| {
+    let x = Box::new(0);
+    Box::new(|| x) //~ ERROR cannot move out of captured outer variable
+};
+
+fn main() {
+    let f = (FN)();
+    f();
+    f();
+}
diff --git a/src/test/ui/borrowck/borrowck-in-static.stderr b/src/test/ui/borrowck/borrowck-in-static.stderr
new file mode 100644
index 0000000..6eeaf42
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-in-static.stderr
@@ -0,0 +1,11 @@
+error[E0507]: cannot move out of captured outer variable in an `Fn` closure
+  --> $DIR/borrowck-in-static.rs:5:17
+   |
+LL |     let x = Box::new(0);
+   |         - captured outer variable
+LL |     Box::new(|| x)
+   |                 ^ cannot move out of captured outer variable in an `Fn` closure
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.rs b/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.rs
new file mode 100644
index 0000000..f745778
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.rs
@@ -0,0 +1,7 @@
+fn main() {
+    let j = || -> isize {
+        let i: isize;
+        i //~ ERROR use of possibly uninitialized variable: `i`
+    };
+    j();
+}
diff --git a/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.stderr b/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.stderr
new file mode 100644
index 0000000..82a602c
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.stderr
@@ -0,0 +1,9 @@
+error[E0381]: use of possibly uninitialized variable: `i`
+  --> $DIR/borrowck-init-in-called-fn-expr.rs:4:9
+   |
+LL |         i
+   |         ^ use of possibly uninitialized `i`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/borrowck-init-in-fn-expr.rs b/src/test/ui/borrowck/borrowck-init-in-fn-expr.rs
new file mode 100644
index 0000000..5055814
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-init-in-fn-expr.rs
@@ -0,0 +1,7 @@
+fn main() {
+    let f  = || -> isize {
+        let i: isize;
+        i //~ ERROR use of possibly uninitialized variable: `i`
+    };
+    println!("{}", f());
+}
diff --git a/src/test/ui/borrowck/borrowck-init-in-fn-expr.stderr b/src/test/ui/borrowck/borrowck-init-in-fn-expr.stderr
new file mode 100644
index 0000000..8997393
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-init-in-fn-expr.stderr
@@ -0,0 +1,9 @@
+error[E0381]: use of possibly uninitialized variable: `i`
+  --> $DIR/borrowck-init-in-fn-expr.rs:4:9
+   |
+LL |         i
+   |         ^ use of possibly uninitialized `i`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/borrowck-init-in-fru.ast.nll.stderr b/src/test/ui/borrowck/borrowck-init-in-fru.ast.nll.stderr
new file mode 100644
index 0000000..35649b1
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-init-in-fru.ast.nll.stderr
@@ -0,0 +1,9 @@
+error[E0381]: use of possibly uninitialized variable: `origin`
+  --> $DIR/borrowck-init-in-fru.rs:12:5
+   |
+LL |     origin = Point { x: 10, ..origin };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ use of possibly uninitialized `origin.y`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/borrowck-init-in-fru.ast.stderr b/src/test/ui/borrowck/borrowck-init-in-fru.ast.stderr
new file mode 100644
index 0000000..3ba0109
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-init-in-fru.ast.stderr
@@ -0,0 +1,9 @@
+error[E0381]: use of possibly uninitialized variable: `origin.y`
+  --> $DIR/borrowck-init-in-fru.rs:12:31
+   |
+LL |     origin = Point { x: 10, ..origin };
+   |                               ^^^^^^ use of possibly uninitialized `origin.y`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/borrowck-init-in-fru.mir.stderr b/src/test/ui/borrowck/borrowck-init-in-fru.mir.stderr
new file mode 100644
index 0000000..35649b1
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-init-in-fru.mir.stderr
@@ -0,0 +1,9 @@
+error[E0381]: use of possibly uninitialized variable: `origin`
+  --> $DIR/borrowck-init-in-fru.rs:12:5
+   |
+LL |     origin = Point { x: 10, ..origin };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ use of possibly uninitialized `origin.y`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/borrowck-init-in-fru.rs b/src/test/ui/borrowck/borrowck-init-in-fru.rs
new file mode 100644
index 0000000..9a06c7a
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-init-in-fru.rs
@@ -0,0 +1,16 @@
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+#[derive(Clone)]
+struct Point {
+    x: isize,
+    y: isize,
+}
+
+fn main() {
+    let mut origin: Point;
+    origin = Point { x: 10, ..origin };
+    //[ast]~^ ERROR use of possibly uninitialized variable: `origin.y` [E0381]
+    //[mir]~^^ ERROR [E0381]
+    origin.clone();
+}
diff --git a/src/test/ui/borrowck/borrowck-init-op-equal.rs b/src/test/ui/borrowck/borrowck-init-op-equal.rs
new file mode 100644
index 0000000..d3fa852
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-init-op-equal.rs
@@ -0,0 +1,8 @@
+fn test() {
+    let v: isize;
+    v += 1; //~ ERROR use of possibly uninitialized variable: `v`
+    v.clone();
+}
+
+fn main() {
+}
diff --git a/src/test/ui/borrowck/borrowck-init-op-equal.stderr b/src/test/ui/borrowck/borrowck-init-op-equal.stderr
new file mode 100644
index 0000000..9863ceb
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-init-op-equal.stderr
@@ -0,0 +1,9 @@
+error[E0381]: use of possibly uninitialized variable: `v`
+  --> $DIR/borrowck-init-op-equal.rs:3:5
+   |
+LL |     v += 1;
+   |     ^^^^^^ use of possibly uninitialized `v`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/borrowck-init-plus-equal.rs b/src/test/ui/borrowck/borrowck-init-plus-equal.rs
new file mode 100644
index 0000000..d895a2e
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-init-plus-equal.rs
@@ -0,0 +1,8 @@
+fn test() {
+    let mut v: isize;
+    v = v + 1; //~ ERROR use of possibly uninitialized variable: `v`
+    v.clone();
+}
+
+fn main() {
+}
diff --git a/src/test/ui/borrowck/borrowck-init-plus-equal.stderr b/src/test/ui/borrowck/borrowck-init-plus-equal.stderr
new file mode 100644
index 0000000..80c4e0c
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-init-plus-equal.stderr
@@ -0,0 +1,9 @@
+error[E0381]: use of possibly uninitialized variable: `v`
+  --> $DIR/borrowck-init-plus-equal.rs:3:9
+   |
+LL |     v = v + 1;
+   |         ^ use of possibly uninitialized `v`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/borrowck-insert-during-each.nll.stderr b/src/test/ui/borrowck/borrowck-insert-during-each.nll.stderr
new file mode 100644
index 0000000..b004447
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-insert-during-each.nll.stderr
@@ -0,0 +1,30 @@
+error[E0501]: cannot borrow `*f` as mutable because previous closure requires unique access
+  --> $DIR/borrowck-insert-during-each.rs:16:3
+   |
+LL |     f.foo(
+   |     ^ --- first borrow later used by call
+   |  ___|
+   | |
+LL | |         |a| {
+   | |         --- closure construction occurs here
+LL | |             f.n.insert(*a);
+   | |             - first borrow occurs due to use of `f` in closure
+LL | |         })
+   | |__________^ second borrow occurs here
+
+error[E0500]: closure requires unique access to `f` but it is already borrowed
+  --> $DIR/borrowck-insert-during-each.rs:17:9
+   |
+LL |   f.foo(
+   |   - --- first borrow later used by call
+   |   |
+   |   borrow occurs here
+LL |         |a| {
+   |         ^^^ closure construction occurs here
+LL |             f.n.insert(*a);
+   |             - second borrow occurs due to use of `f` in closure
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0500, E0501.
+For more information about an error, try `rustc --explain E0500`.
diff --git a/src/test/ui/borrowck/borrowck-insert-during-each.rs b/src/test/ui/borrowck/borrowck-insert-during-each.rs
new file mode 100644
index 0000000..025da4d
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-insert-during-each.rs
@@ -0,0 +1,25 @@
+use std::collections::HashSet;
+
+struct Foo {
+  n: HashSet<isize>,
+}
+
+impl Foo {
+    pub fn foo<F>(&mut self, mut fun: F) where F: FnMut(&isize) {
+        for f in &self.n {
+            fun(f);
+        }
+    }
+}
+
+fn bar(f: &mut Foo) {
+  f.foo(
+        |a| { //~ ERROR closure requires unique access to `f`
+            f.n.insert(*a);
+        })
+}
+
+fn main() {
+  let mut f = Foo { n: HashSet::new() };
+  bar(&mut f);
+}
diff --git a/src/test/ui/borrowck/borrowck-insert-during-each.stderr b/src/test/ui/borrowck/borrowck-insert-during-each.stderr
new file mode 100644
index 0000000..3b63397
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-insert-during-each.stderr
@@ -0,0 +1,15 @@
+error[E0500]: closure requires unique access to `f` but `*f` is already borrowed
+  --> $DIR/borrowck-insert-during-each.rs:17:9
+   |
+LL |   f.foo(
+   |   - borrow occurs here
+LL |         |a| {
+   |         ^^^ closure construction occurs here
+LL |             f.n.insert(*a);
+   |             - borrow occurs due to use of `f` in closure
+LL |         })
+   |          - borrow ends here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0500`.
diff --git a/src/test/ui/borrowck/borrowck-issue-14498.ast.nll.stderr b/src/test/ui/borrowck/borrowck-issue-14498.ast.nll.stderr
new file mode 100644
index 0000000..b53cfdd
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-issue-14498.ast.nll.stderr
@@ -0,0 +1,108 @@
+error[E0594]: cannot assign to `***p` which is behind a `&` reference
+  --> $DIR/borrowck-issue-14498.rs:19:5
+   |
+LL |     let p = &y;
+   |             -- help: consider changing this to be a mutable reference: `&mut y`
+LL |     ***p = 2;
+   |     ^^^^^^^^ `p` is a `&` reference, so the data it refers to cannot be written
+
+error[E0506]: cannot assign to `**y` because it is borrowed
+  --> $DIR/borrowck-issue-14498.rs:29:5
+   |
+LL |     let p = &y;
+   |             -- borrow of `**y` occurs here
+LL |     let q = &***p;
+LL |     **y = 2;
+   |     ^^^^^^^ assignment to borrowed `**y` occurs here
+LL |
+LL |     drop(p);
+   |          - borrow later used here
+
+error[E0506]: cannot assign to `**y` because it is borrowed
+  --> $DIR/borrowck-issue-14498.rs:40:5
+   |
+LL |     let p = &y;
+   |             -- borrow of `**y` occurs here
+LL |     let q = &***p;
+LL |     **y = 2;
+   |     ^^^^^^^ assignment to borrowed `**y` occurs here
+LL |
+LL |     drop(p);
+   |          - borrow later used here
+
+error[E0506]: cannot assign to `**y` because it is borrowed
+  --> $DIR/borrowck-issue-14498.rs:51:5
+   |
+LL |     let p = &y;
+   |             -- borrow of `**y` occurs here
+LL |     let q = &***p;
+LL |     **y = 2;
+   |     ^^^^^^^ assignment to borrowed `**y` occurs here
+LL |
+LL |     drop(p);
+   |          - borrow later used here
+
+error[E0506]: cannot assign to `**y` because it is borrowed
+  --> $DIR/borrowck-issue-14498.rs:62:5
+   |
+LL |     let p = &y;
+   |             -- borrow of `**y` occurs here
+LL |     let q = &***p;
+LL |     **y = 2;
+   |     ^^^^^^^ assignment to borrowed `**y` occurs here
+LL |
+LL |     drop(p);
+   |          - borrow later used here
+
+error[E0506]: cannot assign to `**y.a` because it is borrowed
+  --> $DIR/borrowck-issue-14498.rs:73:5
+   |
+LL |     let p = &y.a;
+   |             ---- borrow of `**y.a` occurs here
+LL |     let q = &***p;
+LL |     **y.a = 2;
+   |     ^^^^^^^^^ assignment to borrowed `**y.a` occurs here
+LL |
+LL |     drop(p);
+   |          - borrow later used here
+
+error[E0506]: cannot assign to `**y.a` because it is borrowed
+  --> $DIR/borrowck-issue-14498.rs:84:5
+   |
+LL |     let p = &y.a;
+   |             ---- borrow of `**y.a` occurs here
+LL |     let q = &***p;
+LL |     **y.a = 2;
+   |     ^^^^^^^^^ assignment to borrowed `**y.a` occurs here
+LL |
+LL |     drop(p);
+   |          - borrow later used here
+
+error[E0506]: cannot assign to `**y.a` because it is borrowed
+  --> $DIR/borrowck-issue-14498.rs:95:5
+   |
+LL |     let p = &y.a;
+   |             ---- borrow of `**y.a` occurs here
+LL |     let q = &***p;
+LL |     **y.a = 2;
+   |     ^^^^^^^^^ assignment to borrowed `**y.a` occurs here
+LL |
+LL |     drop(p);
+   |          - borrow later used here
+
+error[E0506]: cannot assign to `**y.a` because it is borrowed
+  --> $DIR/borrowck-issue-14498.rs:106:5
+   |
+LL |     let p = &y.a;
+   |             ---- borrow of `**y.a` occurs here
+LL |     let q = &***p;
+LL |     **y.a = 2;
+   |     ^^^^^^^^^ assignment to borrowed `**y.a` occurs here
+LL |
+LL |     drop(p);
+   |          - borrow later used here
+
+error: aborting due to 9 previous errors
+
+Some errors occurred: E0506, E0594.
+For more information about an error, try `rustc --explain E0506`.
diff --git a/src/test/ui/borrowck/borrowck-issue-14498.ast.stderr b/src/test/ui/borrowck/borrowck-issue-14498.ast.stderr
new file mode 100644
index 0000000..b002ee7
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-issue-14498.ast.stderr
@@ -0,0 +1,82 @@
+error[E0389]: cannot assign to data in a `&` reference
+  --> $DIR/borrowck-issue-14498.rs:19:5
+   |
+LL |     ***p = 2;
+   |     ^^^^^^^^ assignment into an immutable reference
+
+error[E0506]: cannot assign to `**y` because it is borrowed
+  --> $DIR/borrowck-issue-14498.rs:29:5
+   |
+LL |     let p = &y;
+   |              - borrow of `**y` occurs here
+LL |     let q = &***p;
+LL |     **y = 2;
+   |     ^^^^^^^ assignment to borrowed `**y` occurs here
+
+error[E0506]: cannot assign to `**y` because it is borrowed
+  --> $DIR/borrowck-issue-14498.rs:40:5
+   |
+LL |     let p = &y;
+   |              - borrow of `**y` occurs here
+LL |     let q = &***p;
+LL |     **y = 2;
+   |     ^^^^^^^ assignment to borrowed `**y` occurs here
+
+error[E0506]: cannot assign to `**y` because it is borrowed
+  --> $DIR/borrowck-issue-14498.rs:51:5
+   |
+LL |     let p = &y;
+   |              - borrow of `**y` occurs here
+LL |     let q = &***p;
+LL |     **y = 2;
+   |     ^^^^^^^ assignment to borrowed `**y` occurs here
+
+error[E0506]: cannot assign to `**y` because it is borrowed
+  --> $DIR/borrowck-issue-14498.rs:62:5
+   |
+LL |     let p = &y;
+   |              - borrow of `**y` occurs here
+LL |     let q = &***p;
+LL |     **y = 2;
+   |     ^^^^^^^ assignment to borrowed `**y` occurs here
+
+error[E0506]: cannot assign to `**y.a` because it is borrowed
+  --> $DIR/borrowck-issue-14498.rs:73:5
+   |
+LL |     let p = &y.a;
+   |              --- borrow of `**y.a` occurs here
+LL |     let q = &***p;
+LL |     **y.a = 2;
+   |     ^^^^^^^^^ assignment to borrowed `**y.a` occurs here
+
+error[E0506]: cannot assign to `**y.a` because it is borrowed
+  --> $DIR/borrowck-issue-14498.rs:84:5
+   |
+LL |     let p = &y.a;
+   |              --- borrow of `**y.a` occurs here
+LL |     let q = &***p;
+LL |     **y.a = 2;
+   |     ^^^^^^^^^ assignment to borrowed `**y.a` occurs here
+
+error[E0506]: cannot assign to `**y.a` because it is borrowed
+  --> $DIR/borrowck-issue-14498.rs:95:5
+   |
+LL |     let p = &y.a;
+   |              --- borrow of `**y.a` occurs here
+LL |     let q = &***p;
+LL |     **y.a = 2;
+   |     ^^^^^^^^^ assignment to borrowed `**y.a` occurs here
+
+error[E0506]: cannot assign to `**y.a` because it is borrowed
+  --> $DIR/borrowck-issue-14498.rs:106:5
+   |
+LL |     let p = &y.a;
+   |              --- borrow of `**y.a` occurs here
+LL |     let q = &***p;
+LL |     **y.a = 2;
+   |     ^^^^^^^^^ assignment to borrowed `**y.a` occurs here
+
+error: aborting due to 9 previous errors
+
+Some errors occurred: E0389, E0506.
+For more information about an error, try `rustc --explain E0389`.
diff --git a/src/test/ui/borrowck/borrowck-issue-14498.mir.stderr b/src/test/ui/borrowck/borrowck-issue-14498.mir.stderr
new file mode 100644
index 0000000..b53cfdd
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-issue-14498.mir.stderr
@@ -0,0 +1,108 @@
+error[E0594]: cannot assign to `***p` which is behind a `&` reference
+  --> $DIR/borrowck-issue-14498.rs:19:5
+   |
+LL |     let p = &y;
+   |             -- help: consider changing this to be a mutable reference: `&mut y`
+LL |     ***p = 2;
+   |     ^^^^^^^^ `p` is a `&` reference, so the data it refers to cannot be written
+
+error[E0506]: cannot assign to `**y` because it is borrowed
+  --> $DIR/borrowck-issue-14498.rs:29:5
+   |
+LL |     let p = &y;
+   |             -- borrow of `**y` occurs here
+LL |     let q = &***p;
+LL |     **y = 2;
+   |     ^^^^^^^ assignment to borrowed `**y` occurs here
+LL |
+LL |     drop(p);
+   |          - borrow later used here
+
+error[E0506]: cannot assign to `**y` because it is borrowed
+  --> $DIR/borrowck-issue-14498.rs:40:5
+   |
+LL |     let p = &y;
+   |             -- borrow of `**y` occurs here
+LL |     let q = &***p;
+LL |     **y = 2;
+   |     ^^^^^^^ assignment to borrowed `**y` occurs here
+LL |
+LL |     drop(p);
+   |          - borrow later used here
+
+error[E0506]: cannot assign to `**y` because it is borrowed
+  --> $DIR/borrowck-issue-14498.rs:51:5
+   |
+LL |     let p = &y;
+   |             -- borrow of `**y` occurs here
+LL |     let q = &***p;
+LL |     **y = 2;
+   |     ^^^^^^^ assignment to borrowed `**y` occurs here
+LL |
+LL |     drop(p);
+   |          - borrow later used here
+
+error[E0506]: cannot assign to `**y` because it is borrowed
+  --> $DIR/borrowck-issue-14498.rs:62:5
+   |
+LL |     let p = &y;
+   |             -- borrow of `**y` occurs here
+LL |     let q = &***p;
+LL |     **y = 2;
+   |     ^^^^^^^ assignment to borrowed `**y` occurs here
+LL |
+LL |     drop(p);
+   |          - borrow later used here
+
+error[E0506]: cannot assign to `**y.a` because it is borrowed
+  --> $DIR/borrowck-issue-14498.rs:73:5
+   |
+LL |     let p = &y.a;
+   |             ---- borrow of `**y.a` occurs here
+LL |     let q = &***p;
+LL |     **y.a = 2;
+   |     ^^^^^^^^^ assignment to borrowed `**y.a` occurs here
+LL |
+LL |     drop(p);
+   |          - borrow later used here
+
+error[E0506]: cannot assign to `**y.a` because it is borrowed
+  --> $DIR/borrowck-issue-14498.rs:84:5
+   |
+LL |     let p = &y.a;
+   |             ---- borrow of `**y.a` occurs here
+LL |     let q = &***p;
+LL |     **y.a = 2;
+   |     ^^^^^^^^^ assignment to borrowed `**y.a` occurs here
+LL |
+LL |     drop(p);
+   |          - borrow later used here
+
+error[E0506]: cannot assign to `**y.a` because it is borrowed
+  --> $DIR/borrowck-issue-14498.rs:95:5
+   |
+LL |     let p = &y.a;
+   |             ---- borrow of `**y.a` occurs here
+LL |     let q = &***p;
+LL |     **y.a = 2;
+   |     ^^^^^^^^^ assignment to borrowed `**y.a` occurs here
+LL |
+LL |     drop(p);
+   |          - borrow later used here
+
+error[E0506]: cannot assign to `**y.a` because it is borrowed
+  --> $DIR/borrowck-issue-14498.rs:106:5
+   |
+LL |     let p = &y.a;
+   |             ---- borrow of `**y.a` occurs here
+LL |     let q = &***p;
+LL |     **y.a = 2;
+   |     ^^^^^^^^^ assignment to borrowed `**y.a` occurs here
+LL |
+LL |     drop(p);
+   |          - borrow later used here
+
+error: aborting due to 9 previous errors
+
+Some errors occurred: E0506, E0594.
+For more information about an error, try `rustc --explain E0506`.
diff --git a/src/test/ui/borrowck/borrowck-issue-14498.rs b/src/test/ui/borrowck/borrowck-issue-14498.rs
new file mode 100644
index 0000000..da62c5a
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-issue-14498.rs
@@ -0,0 +1,122 @@
+// This tests that we can't modify Box<&mut T> contents while they
+// are borrowed (#14498).
+//
+// Also includes tests of the errors reported when the Box in question
+// is immutable (#14270).
+
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+#![feature(box_syntax)]
+
+struct A { a: isize }
+struct B<'a> { a: Box<&'a mut isize> }
+
+fn indirect_write_to_imm_box() {
+    let mut x: isize = 1;
+    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 `***p`
+    drop(p);
+}
+
+fn borrow_in_var_from_var() {
+    let mut x: isize = 1;
+    let mut y: Box<_> = box &mut x;
+    let p = &y;
+    let q = &***p;
+    **y = 2; //[ast]~ ERROR cannot assign to `**y` because it is borrowed
+             //[mir]~^ ERROR cannot assign to `**y` because it is borrowed
+    drop(p);
+    drop(q);
+}
+
+fn borrow_in_var_from_var_via_imm_box() {
+    let mut x: isize = 1;
+    let y: Box<_> = box &mut x;
+    let p = &y;
+    let q = &***p;
+    **y = 2; //[ast]~ ERROR cannot assign to `**y` because it is borrowed
+             //[mir]~^ ERROR cannot assign to `**y` because it is borrowed
+    drop(p);
+    drop(q);
+}
+
+fn borrow_in_var_from_field() {
+    let mut x = A { a: 1 };
+    let mut y: Box<_> = box &mut x.a;
+    let p = &y;
+    let q = &***p;
+    **y = 2; //[ast]~ ERROR cannot assign to `**y` because it is borrowed
+             //[mir]~^ ERROR cannot assign to `**y` because it is borrowed
+    drop(p);
+    drop(q);
+}
+
+fn borrow_in_var_from_field_via_imm_box() {
+    let mut x = A { a: 1 };
+    let y: Box<_> = box &mut x.a;
+    let p = &y;
+    let q = &***p;
+    **y = 2; //[ast]~ ERROR cannot assign to `**y` because it is borrowed
+             //[mir]~^ ERROR cannot assign to `**y` because it is borrowed
+    drop(p);
+    drop(q);
+}
+
+fn borrow_in_field_from_var() {
+    let mut x: isize = 1;
+    let mut y = B { a: box &mut x };
+    let p = &y.a;
+    let q = &***p;
+    **y.a = 2; //[ast]~ ERROR cannot assign to `**y.a` because it is borrowed
+               //[mir]~^ ERROR cannot assign to `**y.a` because it is borrowed
+    drop(p);
+    drop(q);
+}
+
+fn borrow_in_field_from_var_via_imm_box() {
+    let mut x: isize = 1;
+    let y = B { a: box &mut x };
+    let p = &y.a;
+    let q = &***p;
+    **y.a = 2; //[ast]~ ERROR cannot assign to `**y.a` because it is borrowed
+               //[mir]~^ ERROR cannot assign to `**y.a` because it is borrowed
+    drop(p);
+    drop(q);
+}
+
+fn borrow_in_field_from_field() {
+    let mut x = A { a: 1 };
+    let mut y = B { a: box &mut x.a };
+    let p = &y.a;
+    let q = &***p;
+    **y.a = 2; //[ast]~ ERROR cannot assign to `**y.a` because it is borrowed
+               //[mir]~^ ERROR cannot assign to `**y.a` because it is borrowed
+    drop(p);
+    drop(q);
+}
+
+fn borrow_in_field_from_field_via_imm_box() {
+    let mut x = A { a: 1 };
+    let y = B { a: box &mut x.a };
+    let p = &y.a;
+    let q = &***p;
+    **y.a = 2; //[ast]~ ERROR cannot assign to `**y.a` because it is borrowed
+               //[mir]~^ ERROR cannot assign to `**y.a` because it is borrowed
+    drop(p);
+    drop(q);
+}
+
+fn main() {
+    indirect_write_to_imm_box();
+    borrow_in_var_from_var();
+    borrow_in_var_from_var_via_imm_box();
+    borrow_in_var_from_field();
+    borrow_in_var_from_field_via_imm_box();
+    borrow_in_field_from_var();
+    borrow_in_field_from_var_via_imm_box();
+    borrow_in_field_from_field();
+    borrow_in_field_from_field_via_imm_box();
+}
diff --git a/src/test/ui/borrowck/borrowck-issue-2657-1.nll.stderr b/src/test/ui/borrowck/borrowck-issue-2657-1.nll.stderr
new file mode 100644
index 0000000..4ea4eb8
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-issue-2657-1.nll.stderr
@@ -0,0 +1,13 @@
+error[E0505]: cannot move out of `x` because it is borrowed
+  --> $DIR/borrowck-issue-2657-1.rs:9:18
+   |
+LL |       Some(ref _y) => {
+   |            ------ borrow of `x.0` occurs here
+LL |         let _a = x;
+   |                  ^ move out of `x` occurs here
+LL |         _y.use_ref();
+   |         -- borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0505`.
diff --git a/src/test/ui/borrowck/borrowck-issue-2657-1.rs b/src/test/ui/borrowck/borrowck-issue-2657-1.rs
new file mode 100644
index 0000000..c382937
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-issue-2657-1.rs
@@ -0,0 +1,17 @@
+#![feature(box_syntax)]
+
+
+
+fn main() {
+    let x: Option<Box<_>> = Some(box 1);
+    match x {
+      Some(ref _y) => {
+        let _a = x; //~ ERROR cannot move
+        _y.use_ref();
+      }
+      _ => {}
+    }
+}
+
+trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { }  }
+impl<T> Fake for T { }
diff --git a/src/test/ui/borrowck/borrowck-issue-2657-1.stderr b/src/test/ui/borrowck/borrowck-issue-2657-1.stderr
new file mode 100644
index 0000000..d9ad86b
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-issue-2657-1.stderr
@@ -0,0 +1,11 @@
+error[E0505]: cannot move out of `x` because it is borrowed
+  --> $DIR/borrowck-issue-2657-1.rs:9:13
+   |
+LL |       Some(ref _y) => {
+   |            ------ borrow of `x.0` occurs here
+LL |         let _a = x;
+   |             ^^ move out of `x` occurs here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0505`.
diff --git a/src/test/ui/borrowck/borrowck-issue-2657-2.nll.stderr b/src/test/ui/borrowck/borrowck-issue-2657-2.nll.stderr
new file mode 100644
index 0000000..4ef36df
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-issue-2657-2.nll.stderr
@@ -0,0 +1,12 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/borrowck-issue-2657-2.rs:7:18
+   |
+LL |         let _b = *y;
+   |                  ^^
+   |                  |
+   |                  cannot move out of borrowed content
+   |                  help: consider removing the `*`: `y`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/borrowck/borrowck-issue-2657-2.rs b/src/test/ui/borrowck/borrowck-issue-2657-2.rs
new file mode 100644
index 0000000..cea5611
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-issue-2657-2.rs
@@ -0,0 +1,11 @@
+#![feature(box_syntax)]
+
+fn main() {
+    let x: Option<Box<_>> = Some(box 1);
+    match x {
+      Some(ref y) => {
+        let _b = *y; //~ ERROR cannot move out
+      }
+      _ => {}
+    }
+}
diff --git a/src/test/ui/borrowck/borrowck-issue-2657-2.stderr b/src/test/ui/borrowck/borrowck-issue-2657-2.stderr
new file mode 100644
index 0000000..1314b1a
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-issue-2657-2.stderr
@@ -0,0 +1,12 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/borrowck-issue-2657-2.rs:7:18
+   |
+LL |         let _b = *y;
+   |                  ^^
+   |                  |
+   |                  cannot move out of borrowed content
+   |                  help: consider using a reference instead: `&*y`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/borrowck/borrowck-issue-48962.rs b/src/test/ui/borrowck/borrowck-issue-48962.rs
new file mode 100644
index 0000000..e7df319
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-issue-48962.rs
@@ -0,0 +1,28 @@
+#![feature(nll)]
+
+struct Node {
+    elem: i32,
+    next: Option<Box<Node>>,
+}
+
+fn a() {
+    let mut node = Node {
+        elem: 5,
+        next: None,
+    };
+
+    let mut src = &mut node;
+    {src};
+    src.next = None; //~ ERROR use of moved value: `src` [E0382]
+}
+
+fn b() {
+    let mut src = &mut (22, 44);
+    {src};
+    src.0 = 66; //~ ERROR use of moved value: `src` [E0382]
+}
+
+fn main() {
+    a();
+    b();
+}
diff --git a/src/test/ui/borrowck/borrowck-issue-48962.stderr b/src/test/ui/borrowck/borrowck-issue-48962.stderr
new file mode 100644
index 0000000..a5462b4
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-issue-48962.stderr
@@ -0,0 +1,23 @@
+error[E0382]: use of moved value: `src`
+  --> $DIR/borrowck-issue-48962.rs:16:5
+   |
+LL |     let mut src = &mut node;
+   |         ------- move occurs because `src` has type `&mut Node`, which does not implement the `Copy` trait
+LL |     {src};
+   |      --- value moved here
+LL |     src.next = None;
+   |     ^^^^^^^^ value used here after move
+
+error[E0382]: use of moved value: `src`
+  --> $DIR/borrowck-issue-48962.rs:22:5
+   |
+LL |     let mut src = &mut (22, 44);
+   |         ------- move occurs because `src` has type `&mut (i32, i32)`, which does not implement the `Copy` trait
+LL |     {src};
+   |      --- value moved here
+LL |     src.0 = 66;
+   |     ^^^^^^^^^^ value used here after move
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/borrowck-lend-flow-if.nll.stderr b/src/test/ui/borrowck/borrowck-lend-flow-if.nll.stderr
new file mode 100644
index 0000000..68a82bd
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-lend-flow-if.nll.stderr
@@ -0,0 +1,14 @@
+error[E0502]: cannot borrow `*v` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-lend-flow-if.rs:29:16
+   |
+LL |         _w = &v;
+   |              -- immutable borrow occurs here
+LL |     }
+LL |     borrow_mut(&mut *v);
+   |                ^^^^^^^ mutable borrow occurs here
+LL |     _w.use_ref();
+   |     -- immutable borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/borrowck/borrowck-lend-flow-if.rs b/src/test/ui/borrowck/borrowck-lend-flow-if.rs
new file mode 100644
index 0000000..1150346
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-lend-flow-if.rs
@@ -0,0 +1,51 @@
+// Note: the borrowck analysis is currently flow-insensitive.
+// Therefore, some of these errors are marked as spurious and could be
+// corrected by a simple change to the analysis.  The others are
+// either genuine or would require more advanced changes.  The latter
+// cases are noted.
+
+#![feature(box_syntax)]
+
+fn borrow(_v: &isize) {}
+fn borrow_mut(_v: &mut isize) {}
+fn cond() -> bool { panic!() }
+fn for_func<F>(_f: F) where F: FnOnce() -> bool { panic!() }
+fn produce<T>() -> T { panic!(); }
+
+fn inc(v: &mut Box<isize>) {
+    *v = box (**v + 1);
+}
+
+fn pre_freeze_cond() {
+    // In this instance, the freeze is conditional and starts before
+    // the mut borrow.
+
+    let u = box 0;
+    let mut v: Box<_> = box 3;
+    let mut _w = &u;
+    if cond() {
+        _w = &v;
+    }
+    borrow_mut(&mut *v); //~ ERROR cannot borrow
+    _w.use_ref();
+}
+
+fn pre_freeze_else() {
+    // In this instance, the freeze and mut borrow are on separate sides
+    // of the if.
+
+    let u = box 0;
+    let mut v: Box<_> = box 3;
+    let mut _w = &u;
+    if cond() {
+        _w = &v;
+    } else {
+        borrow_mut(&mut *v);
+    }
+    _w.use_ref();
+}
+
+fn main() {}
+
+trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { }  }
+impl<T> Fake for T { }
diff --git a/src/test/ui/borrowck/borrowck-lend-flow-if.stderr b/src/test/ui/borrowck/borrowck-lend-flow-if.stderr
new file mode 100644
index 0000000..1acd47c
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-lend-flow-if.stderr
@@ -0,0 +1,15 @@
+error[E0502]: cannot borrow `*v` as mutable because `v` is also borrowed as immutable
+  --> $DIR/borrowck-lend-flow-if.rs:29:21
+   |
+LL |         _w = &v;
+   |               - immutable borrow occurs here
+LL |     }
+LL |     borrow_mut(&mut *v);
+   |                     ^^ mutable borrow occurs here
+LL |     _w.use_ref();
+LL | }
+   | - immutable borrow ends here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/borrowck/borrowck-lend-flow-loop.ast.stderr b/src/test/ui/borrowck/borrowck-lend-flow-loop.ast.stderr
new file mode 100644
index 0000000..ab10caa
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-lend-flow-loop.ast.stderr
@@ -0,0 +1,93 @@
+error[E0502]: cannot borrow `*v` as immutable because `v` is also borrowed as mutable
+  --> $DIR/borrowck-lend-flow-loop.rs:35:17
+   |
+LL |     let mut x = &mut v;
+   |                      - mutable borrow occurs here
+...
+LL |         borrow(&*v);
+   |                 ^^ immutable borrow occurs here
+LL |     }
+LL | }
+   | - mutable borrow ends here
+
+error[E0502]: cannot borrow `*v` as immutable because `v` is also borrowed as mutable
+  --> $DIR/borrowck-lend-flow-loop.rs:45:17
+   |
+LL |     let mut x = &mut v;
+   |                      - mutable borrow occurs here
+LL |     for _ in 0..3 {
+LL |         borrow(&*v);
+   |                 ^^ immutable borrow occurs here
+...
+LL | }
+   | - mutable borrow ends here
+
+error[E0502]: cannot borrow `*v` as mutable because `v` is also borrowed as immutable
+  --> $DIR/borrowck-lend-flow-loop.rs:57:25
+   |
+LL |         borrow_mut(&mut *v);
+   |                         ^^ mutable borrow occurs here
+LL |         _x = &v;
+   |               - immutable borrow occurs here
+LL |     }
+LL | }
+   | - immutable borrow ends here
+
+error[E0502]: cannot borrow `*v` as mutable because `v` is also borrowed as immutable
+  --> $DIR/borrowck-lend-flow-loop.rs:69:25
+   |
+LL |         borrow_mut(&mut *v);
+   |                         ^^ mutable borrow occurs here
+LL |         _x = &v;
+   |               - immutable borrow occurs here
+LL |     }
+LL | }
+   | - immutable borrow ends here
+
+error[E0502]: cannot borrow `*v` as mutable because `v` is also borrowed as immutable
+  --> $DIR/borrowck-lend-flow-loop.rs:86:21
+   |
+LL |         _x = &v;
+   |               - immutable borrow occurs here
+...
+LL |     borrow_mut(&mut *v);
+   |                     ^^ mutable borrow occurs here
+LL | }
+   | - immutable borrow ends here
+
+error[E0502]: cannot borrow `*v` as mutable because `v` is also borrowed as immutable
+  --> $DIR/borrowck-lend-flow-loop.rs:100:21
+   |
+LL |         _x = &v;
+   |               - immutable borrow occurs here
+...
+LL |     borrow_mut(&mut *v);
+   |                     ^^ mutable borrow occurs here
+LL | }
+   | - immutable borrow ends here
+
+error[E0502]: cannot borrow `*v` as immutable because `v` is also borrowed as mutable
+  --> $DIR/borrowck-lend-flow-loop.rs:109:17
+   |
+LL |         borrow(&*v);
+   |                 ^^ immutable borrow occurs here
+...
+LL |             x = &mut v;
+   |                      - mutable borrow occurs here
+...
+LL | }
+   | - mutable borrow ends here
+
+error[E0499]: cannot borrow `v` as mutable more than once at a time
+  --> $DIR/borrowck-lend-flow-loop.rs:112:22
+   |
+LL |             x = &mut v;
+   |                      ^ mutable borrow starts here in previous iteration of loop
+...
+LL | }
+   | - mutable borrow ends here
+
+error: aborting due to 8 previous errors
+
+Some errors occurred: E0499, E0502.
+For more information about an error, try `rustc --explain E0499`.
diff --git a/src/test/ui/borrowck/borrowck-lend-flow-loop.nll.stderr b/src/test/ui/borrowck/borrowck-lend-flow-loop.nll.stderr
new file mode 100644
index 0000000..6dd6c1f
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-lend-flow-loop.nll.stderr
@@ -0,0 +1,26 @@
+error[E0502]: cannot borrow `*v` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-lend-flow-loop.rs:45:16
+   |
+LL |     let mut x = &mut v;
+   |                 ------ mutable borrow occurs here
+LL |     for _ in 0..3 {
+LL |         borrow(&*v);
+   |                ^^^ immutable borrow occurs here
+...
+LL |     *x = box 5;
+   |     -- mutable borrow later used here
+
+error[E0502]: cannot borrow `*v` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-lend-flow-loop.rs:109:16
+   |
+LL |         **x += 1;
+   |         -------- mutable borrow later used here
+LL |         borrow(&*v);
+   |                ^^^ immutable borrow occurs here
+...
+LL |             x = &mut v;
+   |                 ------ mutable borrow occurs here
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/borrowck/borrowck-lend-flow-loop.rs b/src/test/ui/borrowck/borrowck-lend-flow-loop.rs
new file mode 100644
index 0000000..7008e5c
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-lend-flow-loop.rs
@@ -0,0 +1,150 @@
+// revisions: ast nll
+
+// Since we are testing nll migration explicitly as a separate
+// revision, don't worry about the --compare-mode=nll on this test.
+
+// ignore-compare-mode-nll
+
+//[ast]compile-flags: -Z borrowck=ast
+//[nll]compile-flags: -Z borrowck=migrate -Z two-phase-borrows
+
+// Note: the borrowck analysis was originally a flow-insensitive pass
+// over the AST. Therefore, some of these (AST) errors are marked as
+// spurious and are corrected by the flow-sensitive (NLL) analysis.
+// The others are either genuine or would require more advanced
+// changes. The latter cases are noted.
+
+#![feature(box_syntax)]
+
+fn borrow(_v: &isize) {}
+fn borrow_mut(_v: &mut isize) {}
+fn cond() -> bool { panic!() }
+fn produce<T>() -> T { panic!(); }
+
+fn inc(v: &mut Box<isize>) {
+    *v = box (**v + 1);
+}
+
+fn loop_overarching_alias_mut() {
+    // In this instance, the borrow encompasses the entire loop.
+
+    let mut v: Box<_> = box 3;
+    let mut x = &mut v;
+    **x += 1;
+    loop {
+        borrow(&*v); //[ast]~ ERROR cannot borrow
+    }
+}
+
+fn block_overarching_alias_mut() {
+    // In this instance, the borrow encompasses the entire closure call.
+
+    let mut v: Box<_> = box 3;
+    let mut x = &mut v;
+    for _ in 0..3 {
+        borrow(&*v); //[ast]~ ERROR cannot borrow
+        //[nll]~^ ERROR cannot borrow
+    }
+    *x = box 5;
+}
+fn loop_aliased_mut() {
+    // In this instance, the borrow is carried through the loop.
+
+    let mut v: Box<_> = box 3;
+    let mut w: Box<_> = box 4;
+    let mut _x = &w;
+    loop {
+        borrow_mut(&mut *v); //[ast]~ ERROR cannot borrow
+        _x = &v;
+    }
+}
+
+fn while_aliased_mut() {
+    // In this instance, the borrow is carried through the loop.
+
+    let mut v: Box<_> = box 3;
+    let mut w: Box<_> = box 4;
+    let mut _x = &w;
+    while cond() {
+        borrow_mut(&mut *v); //[ast]~ ERROR cannot borrow
+        _x = &v;
+    }
+}
+
+
+fn loop_aliased_mut_break() {
+    // In this instance, the borrow is carried through the loop.
+
+    let mut v: Box<_> = box 3;
+    let mut w: Box<_> = box 4;
+    let mut _x = &w;
+    loop {
+        borrow_mut(&mut *v);
+        _x = &v;
+        break;
+    }
+    borrow_mut(&mut *v); //[ast]~ ERROR cannot borrow
+}
+
+fn while_aliased_mut_break() {
+    // In this instance, the borrow is carried through the loop.
+
+    let mut v: Box<_> = box 3;
+    let mut w: Box<_> = box 4;
+    let mut _x = &w;
+    while cond() {
+        borrow_mut(&mut *v);
+        _x = &v;
+        break;
+    }
+    borrow_mut(&mut *v); //[ast]~ ERROR cannot borrow
+}
+
+fn while_aliased_mut_cond(cond: bool, cond2: bool) {
+    let mut v: Box<_> = box 3;
+    let mut w: Box<_> = box 4;
+    let mut x = &mut w;
+    while cond {
+        **x += 1;
+        borrow(&*v); //[ast]~ ERROR cannot borrow
+        //[nll]~^ ERROR cannot borrow
+        if cond2 {
+            x = &mut v; //[ast]~ ERROR cannot borrow
+        }
+    }
+}
+fn loop_break_pops_scopes<'r, F>(_v: &'r mut [usize], mut f: F) where
+    F: FnMut(&'r mut usize) -> bool,
+{
+    // Here we check that when you break out of an inner loop, the
+    // borrows that go out of scope as you exit the inner loop are
+    // removed from the bitset.
+
+    while cond() {
+        while cond() {
+            // this borrow is limited to the scope of `r`...
+            let r: &'r mut usize = produce();
+            if !f(&mut *r) {
+                break; // ...so it is not live as exit the `while` loop here
+            }
+        }
+    }
+}
+
+fn loop_loop_pops_scopes<'r, F>(_v: &'r mut [usize], mut f: F)
+    where F: FnMut(&'r mut usize) -> bool
+{
+    // Similar to `loop_break_pops_scopes` but for the `loop` keyword
+
+    while cond() {
+        while cond() {
+            // this borrow is limited to the scope of `r`...
+            let r: &'r mut usize = produce();
+            if !f(&mut *r) {
+                continue; // ...so it is not live as exit (and re-enter) the `while` loop here
+            }
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/borrowck-lend-flow-match.ast.nll.stderr b/src/test/ui/borrowck/borrowck-lend-flow-match.ast.nll.stderr
new file mode 100644
index 0000000..734f965
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-lend-flow-match.ast.nll.stderr
@@ -0,0 +1,14 @@
+error[E0506]: cannot assign to `x` because it is borrowed
+  --> $DIR/borrowck-lend-flow-match.rs:18:13
+   |
+LL |         Some(ref r) => {
+   |              ----- borrow of `x` occurs here
+LL |             x = Some(1);
+   |             ^^^^^^^^^^^ assignment to borrowed `x` occurs here
+LL |
+LL |             drop(r);
+   |                  - borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/borrowck/borrowck-lend-flow-match.ast.stderr b/src/test/ui/borrowck/borrowck-lend-flow-match.ast.stderr
new file mode 100644
index 0000000..236bc11
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-lend-flow-match.ast.stderr
@@ -0,0 +1,11 @@
+error[E0506]: cannot assign to `x` because it is borrowed
+  --> $DIR/borrowck-lend-flow-match.rs:18:13
+   |
+LL |         Some(ref r) => {
+   |              ----- borrow of `x` occurs here
+LL |             x = Some(1);
+   |             ^^^^^^^^^^^ assignment to borrowed `x` occurs here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/borrowck/borrowck-lend-flow-match.mir.stderr b/src/test/ui/borrowck/borrowck-lend-flow-match.mir.stderr
new file mode 100644
index 0000000..734f965
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-lend-flow-match.mir.stderr
@@ -0,0 +1,14 @@
+error[E0506]: cannot assign to `x` because it is borrowed
+  --> $DIR/borrowck-lend-flow-match.rs:18:13
+   |
+LL |         Some(ref r) => {
+   |              ----- borrow of `x` occurs here
+LL |             x = Some(1);
+   |             ^^^^^^^^^^^ assignment to borrowed `x` occurs here
+LL |
+LL |             drop(r);
+   |                  - borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/borrowck/borrowck-lend-flow-match.rs b/src/test/ui/borrowck/borrowck-lend-flow-match.rs
new file mode 100644
index 0000000..4cd2a23
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-lend-flow-match.rs
@@ -0,0 +1,26 @@
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+#![allow(unused_variables)]
+#![allow(unused_assignments)]
+
+fn separate_arms() {
+    // Here both arms perform assignments, but only is illegal.
+
+    let mut x = None;
+    match x {
+        None => {
+            // It is ok to reassign x here, because there is in
+            // fact no outstanding loan of x!
+            x = Some(0);
+        }
+        Some(ref r) => {
+            x = Some(1); //[ast]~ ERROR cannot assign
+            //[mir]~^ ERROR cannot assign to `x` because it is borrowed
+            drop(r);
+        }
+    }
+    x.clone(); // just to prevent liveness warnings
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/borrowck-lend-flow.nll.stderr b/src/test/ui/borrowck/borrowck-lend-flow.nll.stderr
new file mode 100644
index 0000000..07b11b3
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-lend-flow.nll.stderr
@@ -0,0 +1,13 @@
+error[E0502]: cannot borrow `*v` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-lend-flow.rs:24:16
+   |
+LL |     let _w = &v;
+   |              -- immutable borrow occurs here
+LL |     borrow_mut(&mut *v);
+   |                ^^^^^^^ mutable borrow occurs here
+LL |     _w.use_ref();
+   |     -- immutable borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/borrowck/borrowck-lend-flow.rs b/src/test/ui/borrowck/borrowck-lend-flow.rs
new file mode 100644
index 0000000..0eb62ed
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-lend-flow.rs
@@ -0,0 +1,39 @@
+// Note: the borrowck analysis is currently flow-insensitive.
+// Therefore, some of these errors are marked as spurious and could be
+// corrected by a simple change to the analysis.  The others are
+// either genuine or would require more advanced changes.  The latter
+// cases are noted.
+
+#![feature(box_syntax)]
+
+fn borrow(_v: &isize) {}
+fn borrow_mut(_v: &mut isize) {}
+fn cond() -> bool { panic!() }
+fn for_func<F>(_f: F) where F: FnOnce() -> bool { panic!() }
+fn produce<T>() -> T { panic!(); }
+
+fn inc(v: &mut Box<isize>) {
+    *v = box (**v + 1);
+}
+
+fn pre_freeze() {
+    // In this instance, the freeze starts before the mut borrow.
+
+    let mut v: Box<_> = box 3;
+    let _w = &v;
+    borrow_mut(&mut *v); //~ ERROR cannot borrow
+    _w.use_ref();
+}
+
+fn post_freeze() {
+    // In this instance, the const alias starts after the borrow.
+
+    let mut v: Box<_> = box 3;
+    borrow_mut(&mut *v);
+    let _w = &v;
+}
+
+fn main() {}
+
+trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { }  }
+impl<T> Fake for T { }
diff --git a/src/test/ui/borrowck/borrowck-lend-flow.stderr b/src/test/ui/borrowck/borrowck-lend-flow.stderr
new file mode 100644
index 0000000..e39fb6c
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-lend-flow.stderr
@@ -0,0 +1,14 @@
+error[E0502]: cannot borrow `*v` as mutable because `v` is also borrowed as immutable
+  --> $DIR/borrowck-lend-flow.rs:24:21
+   |
+LL |     let _w = &v;
+   |               - immutable borrow occurs here
+LL |     borrow_mut(&mut *v);
+   |                     ^^ mutable borrow occurs here
+LL |     _w.use_ref();
+LL | }
+   | - immutable borrow ends here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/borrowck/borrowck-loan-blocks-move-cc.nll.stderr b/src/test/ui/borrowck/borrowck-loan-blocks-move-cc.nll.stderr
new file mode 100644
index 0000000..4497cfb
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-loan-blocks-move-cc.nll.stderr
@@ -0,0 +1,29 @@
+error[E0505]: cannot move out of `v` because it is borrowed
+  --> $DIR/borrowck-loan-blocks-move-cc.rs:14:19
+   |
+LL |     let w = &v;
+   |             -- borrow of `v` occurs here
+LL |     thread::spawn(move|| {
+   |                   ^^^^^^ move out of `v` occurs here
+LL |         println!("v={}", *v);
+   |                           - move occurs due to use in closure
+...
+LL |     w.use_ref();
+   |     - borrow later used here
+
+error[E0505]: cannot move out of `v` because it is borrowed
+  --> $DIR/borrowck-loan-blocks-move-cc.rs:24:19
+   |
+LL |     let w = &v;
+   |             -- borrow of `v` occurs here
+LL |     thread::spawn(move|| {
+   |                   ^^^^^^ move out of `v` occurs here
+LL |         println!("v={}", *v);
+   |                           - move occurs due to use in closure
+...
+LL |     w.use_ref();
+   |     - borrow later used here
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0505`.
diff --git a/src/test/ui/borrowck/borrowck-loan-blocks-move-cc.rs b/src/test/ui/borrowck/borrowck-loan-blocks-move-cc.rs
new file mode 100644
index 0000000..29a2047
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-loan-blocks-move-cc.rs
@@ -0,0 +1,35 @@
+#![feature(box_syntax)]
+
+use std::thread;
+
+
+
+fn borrow<F>(v: &isize, f: F) where F: FnOnce(&isize) {
+    f(v);
+}
+
+fn box_imm() {
+    let v: Box<_> = box 3;
+    let w = &v;
+    thread::spawn(move|| {
+        println!("v={}", *v);
+        //~^ ERROR cannot move `v` into closure
+    });
+    w.use_ref();
+}
+
+fn box_imm_explicit() {
+    let v: Box<_> = box 3;
+    let w = &v;
+    thread::spawn(move|| {
+        println!("v={}", *v);
+        //~^ ERROR cannot move
+    });
+    w.use_ref();
+}
+
+fn main() {
+}
+
+trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { }  }
+impl<T> Fake for T { }
diff --git a/src/test/ui/borrowck/borrowck-loan-blocks-move-cc.stderr b/src/test/ui/borrowck/borrowck-loan-blocks-move-cc.stderr
new file mode 100644
index 0000000..b170635
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-loan-blocks-move-cc.stderr
@@ -0,0 +1,21 @@
+error[E0504]: cannot move `v` into closure because it is borrowed
+  --> $DIR/borrowck-loan-blocks-move-cc.rs:15:27
+   |
+LL |     let w = &v;
+   |              - borrow of `v` occurs here
+LL |     thread::spawn(move|| {
+LL |         println!("v={}", *v);
+   |                           ^ move into closure occurs here
+
+error[E0504]: cannot move `v` into closure because it is borrowed
+  --> $DIR/borrowck-loan-blocks-move-cc.rs:25:27
+   |
+LL |     let w = &v;
+   |              - borrow of `v` occurs here
+LL |     thread::spawn(move|| {
+LL |         println!("v={}", *v);
+   |                           ^ move into closure occurs here
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0504`.
diff --git a/src/test/ui/borrowck/borrowck-loan-blocks-move.nll.stderr b/src/test/ui/borrowck/borrowck-loan-blocks-move.nll.stderr
new file mode 100644
index 0000000..615660f
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-loan-blocks-move.nll.stderr
@@ -0,0 +1,13 @@
+error[E0505]: cannot move out of `v` because it is borrowed
+  --> $DIR/borrowck-loan-blocks-move.rs:11:10
+   |
+LL |     let w = &v;
+   |             -- borrow of `v` occurs here
+LL |     take(v);
+   |          ^ move out of `v` occurs here
+LL |     w.use_ref();
+   |     - borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0505`.
diff --git a/src/test/ui/borrowck/borrowck-loan-blocks-move.rs b/src/test/ui/borrowck/borrowck-loan-blocks-move.rs
new file mode 100644
index 0000000..bde7321
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-loan-blocks-move.rs
@@ -0,0 +1,19 @@
+#![feature(box_syntax)]
+
+
+
+fn take(_v: Box<isize>) {
+}
+
+fn box_imm() {
+    let v = box 3;
+    let w = &v;
+    take(v); //~ ERROR cannot move out of `v` because it is borrowed
+    w.use_ref();
+}
+
+fn main() {
+}
+
+trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { }  }
+impl<T> Fake for T { }
diff --git a/src/test/ui/borrowck/borrowck-loan-blocks-move.stderr b/src/test/ui/borrowck/borrowck-loan-blocks-move.stderr
new file mode 100644
index 0000000..e6f0a69
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-loan-blocks-move.stderr
@@ -0,0 +1,11 @@
+error[E0505]: cannot move out of `v` because it is borrowed
+  --> $DIR/borrowck-loan-blocks-move.rs:11:10
+   |
+LL |     let w = &v;
+   |              - borrow of `v` occurs here
+LL |     take(v);
+   |          ^ move out of `v` occurs here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0505`.
diff --git a/src/test/ui/borrowck/borrowck-loan-blocks-mut-uniq.nll.stderr b/src/test/ui/borrowck/borrowck-loan-blocks-mut-uniq.nll.stderr
new file mode 100644
index 0000000..1d1522a
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-loan-blocks-mut-uniq.nll.stderr
@@ -0,0 +1,15 @@
+error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-loan-blocks-mut-uniq.rs:10:12
+   |
+LL |     borrow(&*v,
+   |     ------ --- immutable borrow occurs here
+   |     |
+   |     immutable borrow later used by call
+LL |            |w| {
+   |            ^^^ mutable borrow occurs here
+LL |             v = box 4;
+   |             - second borrow occurs due to use of `v` in closure
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/borrowck/borrowck-loan-blocks-mut-uniq.rs b/src/test/ui/borrowck/borrowck-loan-blocks-mut-uniq.rs
new file mode 100644
index 0000000..da30bfa
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-loan-blocks-mut-uniq.rs
@@ -0,0 +1,18 @@
+#![feature(box_syntax)]
+
+fn borrow<F>(v: &isize, f: F) where F: FnOnce(&isize) {
+    f(v);
+}
+
+fn box_imm() {
+    let mut v: Box<_> = box 3;
+    borrow(&*v,
+           |w| { //~ ERROR cannot borrow `v` as mutable
+            v = box 4;
+            assert_eq!(*v, 3);
+            assert_eq!(*w, 4);
+        })
+}
+
+fn main() {
+}
diff --git a/src/test/ui/borrowck/borrowck-loan-blocks-mut-uniq.stderr b/src/test/ui/borrowck/borrowck-loan-blocks-mut-uniq.stderr
new file mode 100644
index 0000000..c916b7e
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-loan-blocks-mut-uniq.stderr
@@ -0,0 +1,16 @@
+error[E0502]: cannot borrow `v` as mutable because `*v` is also borrowed as immutable
+  --> $DIR/borrowck-loan-blocks-mut-uniq.rs:10:12
+   |
+LL |     borrow(&*v,
+   |             -- immutable borrow occurs here
+LL |            |w| {
+   |            ^^^ mutable borrow occurs here
+LL |             v = box 4;
+   |             - borrow occurs due to use of `v` in closure
+...
+LL |         })
+   |          - immutable borrow ends here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/borrowck/borrowck-loan-in-overloaded-op.nll.stderr b/src/test/ui/borrowck/borrowck-loan-in-overloaded-op.nll.stderr
new file mode 100644
index 0000000..095ae7f
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-loan-in-overloaded-op.nll.stderr
@@ -0,0 +1,13 @@
+error[E0382]: borrow of moved value: `x`
+  --> $DIR/borrowck-loan-in-overloaded-op.rs:21:20
+   |
+LL |     let x = Foo(box 3);
+   |         - move occurs because `x` has type `Foo`, which does not implement the `Copy` trait
+LL |     let _y = {x} + x.clone(); // the `{x}` forces a move to occur
+   |               -    ^ value borrowed here after move
+   |               |
+   |               value moved here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/borrowck-loan-in-overloaded-op.rs b/src/test/ui/borrowck/borrowck-loan-in-overloaded-op.rs
new file mode 100644
index 0000000..464f01c
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-loan-in-overloaded-op.rs
@@ -0,0 +1,23 @@
+#![feature(box_patterns)]
+#![feature(box_syntax)]
+
+use std::ops::Add;
+
+#[derive(Clone)]
+struct Foo(Box<usize>);
+
+impl Add for Foo {
+    type Output = Foo;
+
+    fn add(self, f: Foo) -> Foo {
+        let Foo(box i) = self;
+        let Foo(box j) = f;
+        Foo(box (i + j))
+    }
+}
+
+fn main() {
+    let x = Foo(box 3);
+    let _y = {x} + x.clone(); // the `{x}` forces a move to occur
+    //~^ ERROR use of moved value: `x`
+}
diff --git a/src/test/ui/borrowck/borrowck-loan-in-overloaded-op.stderr b/src/test/ui/borrowck/borrowck-loan-in-overloaded-op.stderr
new file mode 100644
index 0000000..b6147aa
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-loan-in-overloaded-op.stderr
@@ -0,0 +1,13 @@
+error[E0382]: use of moved value: `x`
+  --> $DIR/borrowck-loan-in-overloaded-op.rs:21:20
+   |
+LL |     let _y = {x} + x.clone(); // the `{x}` forces a move to occur
+   |               -    ^ value used here after move
+   |               |
+   |               value moved here
+   |
+   = note: move occurs because `x` has type `Foo`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/borrowck-loan-of-static-data-issue-27616.nll.stderr b/src/test/ui/borrowck/borrowck-loan-of-static-data-issue-27616.nll.stderr
new file mode 100644
index 0000000..6994c83
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-loan-of-static-data-issue-27616.nll.stderr
@@ -0,0 +1,14 @@
+error[E0506]: cannot assign to `*s` because it is borrowed
+  --> $DIR/borrowck-loan-of-static-data-issue-27616.rs:16:5
+   |
+LL |     let alias: &'static mut String = s;
+   |                -------------------   - borrow of `*s` occurs here
+   |                |
+   |                type annotation requires that `*s` is borrowed for `'static`
+...
+LL |     *s = String::new();
+   |     ^^ assignment to borrowed `*s` occurs here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/borrowck/borrowck-loan-of-static-data-issue-27616.rs b/src/test/ui/borrowck/borrowck-loan-of-static-data-issue-27616.rs
new file mode 100644
index 0000000..cb801ef
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-loan-of-static-data-issue-27616.rs
@@ -0,0 +1,24 @@
+use std::mem;
+
+fn leak<T>(mut b: Box<T>) -> &'static mut T {
+    // isn't this supposed to be safe?
+    let inner = &mut *b as *mut _;
+    mem::forget(b);
+    unsafe { &mut *inner }
+}
+
+fn evil(mut s: &'static mut String)
+{
+    // create alias
+    let alias: &'static mut String = s;
+    let inner: &str = &alias;
+    // free value
+    *s = String::new(); //~ ERROR cannot assign
+    let _spray = "0wned".to_owned();
+    // ... and then use it
+    println!("{}", inner);
+}
+
+fn main() {
+    evil(leak(Box::new("hello".to_owned())));
+}
diff --git a/src/test/ui/borrowck/borrowck-loan-of-static-data-issue-27616.stderr b/src/test/ui/borrowck/borrowck-loan-of-static-data-issue-27616.stderr
new file mode 100644
index 0000000..c9d36a7
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-loan-of-static-data-issue-27616.stderr
@@ -0,0 +1,12 @@
+error[E0506]: cannot assign to `*s` because it is borrowed
+  --> $DIR/borrowck-loan-of-static-data-issue-27616.rs:16:5
+   |
+LL |     let alias: &'static mut String = s;
+   |                                      - borrow of `*s` occurs here
+...
+LL |     *s = String::new();
+   |     ^^^^^^^^^^^^^^^^^^ assignment to borrowed `*s` occurs here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/borrowck/borrowck-loan-rcvr-overloaded-op.nll.stderr b/src/test/ui/borrowck/borrowck-loan-rcvr-overloaded-op.nll.stderr
new file mode 100644
index 0000000..ad74a89
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-loan-rcvr-overloaded-op.nll.stderr
@@ -0,0 +1,28 @@
+error[E0503]: cannot use `p` because it was mutably borrowed
+  --> $DIR/borrowck-loan-rcvr-overloaded-op.rs:38:5
+   |
+LL |     let q = &mut p;
+   |             ------ borrow of `p` occurs here
+LL | 
+LL |     p + 3;
+   |     ^ use of borrowed `p`
+...
+LL |     *q + 3; // OK to use the new alias `q`
+   |     -- borrow later used here
+
+error[E0502]: cannot borrow `p` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-loan-rcvr-overloaded-op.rs:39:5
+   |
+LL |     let q = &mut p;
+   |             ------ mutable borrow occurs here
+...
+LL |     p.times(3);
+   |     ^ immutable borrow occurs here
+LL | 
+LL |     *q + 3; // OK to use the new alias `q`
+   |     -- mutable borrow later used here
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0502, E0503.
+For more information about an error, try `rustc --explain E0502`.
diff --git a/src/test/ui/borrowck/borrowck-loan-rcvr-overloaded-op.rs b/src/test/ui/borrowck/borrowck-loan-rcvr-overloaded-op.rs
new file mode 100644
index 0000000..4da10fd
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-loan-rcvr-overloaded-op.rs
@@ -0,0 +1,46 @@
+use std::ops::Add;
+
+#[derive(Copy, Clone)]
+struct Point {
+    x: isize,
+    y: isize,
+}
+
+impl Add<isize> for Point {
+    type Output = isize;
+
+    fn add(self, z: isize) -> isize {
+        self.x + self.y + z
+    }
+}
+
+impl Point {
+    pub fn times(&self, z: isize) -> isize {
+        self.x * self.y * z
+    }
+}
+
+fn a() {
+    let mut p = Point {x: 3, y: 4};
+
+    // ok (we can loan out rcvr)
+    p + 3;
+    p.times(3);
+}
+
+fn b() {
+    let mut p = Point {x: 3, y: 4};
+
+    // Here I create an outstanding loan and check that we get conflicts:
+
+    let q = &mut p;
+
+    p + 3;  //~ ERROR cannot use `p`
+    p.times(3); //~ ERROR cannot borrow `p`
+
+    *q + 3; // OK to use the new alias `q`
+    q.x += 1; // and OK to mutate it
+}
+
+fn main() {
+}
diff --git a/src/test/ui/borrowck/borrowck-loan-rcvr-overloaded-op.stderr b/src/test/ui/borrowck/borrowck-loan-rcvr-overloaded-op.stderr
new file mode 100644
index 0000000..d180e3e
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-loan-rcvr-overloaded-op.stderr
@@ -0,0 +1,25 @@
+error[E0503]: cannot use `p` because it was mutably borrowed
+  --> $DIR/borrowck-loan-rcvr-overloaded-op.rs:38:5
+   |
+LL |     let q = &mut p;
+   |                  - borrow of `p` occurs here
+LL | 
+LL |     p + 3;
+   |     ^ use of borrowed `p`
+
+error[E0502]: cannot borrow `p` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-loan-rcvr-overloaded-op.rs:39:5
+   |
+LL |     let q = &mut p;
+   |                  - mutable borrow occurs here
+...
+LL |     p.times(3);
+   |     ^ immutable borrow occurs here
+...
+LL | }
+   | - mutable borrow ends here
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0502, E0503.
+For more information about an error, try `rustc --explain E0502`.
diff --git a/src/test/ui/borrowck/borrowck-loan-rcvr.nll.stderr b/src/test/ui/borrowck/borrowck-loan-rcvr.nll.stderr
new file mode 100644
index 0000000..ec3edc8
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-loan-rcvr.nll.stderr
@@ -0,0 +1,25 @@
+error[E0502]: cannot borrow `p` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-loan-rcvr.rs:23:14
+   |
+LL |     p.blockm(|| {
+   |     - ------ ^^ mutable borrow occurs here
+   |     | |
+   |     | immutable borrow later used by call
+   |     immutable borrow occurs here
+LL |         p.x = 10;
+   |         - second borrow occurs due to use of `p` in closure
+
+error[E0502]: cannot borrow `p` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-loan-rcvr.rs:34:5
+   |
+LL |     let l = &mut p;
+   |             ------ mutable borrow occurs here
+LL |     p.impurem();
+   |     ^ immutable borrow occurs here
+LL | 
+LL |     l.x += 1;
+   |     -------- mutable borrow later used here
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/borrowck/borrowck-loan-rcvr.rs b/src/test/ui/borrowck/borrowck-loan-rcvr.rs
new file mode 100644
index 0000000..d2234e1
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-loan-rcvr.rs
@@ -0,0 +1,40 @@
+struct Point { x: isize, y: isize }
+
+trait Methods {
+    fn impurem(&self);
+    fn blockm<F>(&self, f: F) where F: FnOnce();
+}
+
+impl Methods for Point {
+    fn impurem(&self) {
+    }
+
+    fn blockm<F>(&self, f: F) where F: FnOnce() { f() }
+}
+
+fn a() {
+    let mut p = Point {x: 3, y: 4};
+
+    // Here: it's ok to call even though receiver is mutable, because we
+    // can loan it out.
+    p.impurem();
+
+    // But in this case we do not honor the loan:
+    p.blockm(|| { //~ ERROR cannot borrow `p` as mutable
+        p.x = 10;
+    })
+}
+
+fn b() {
+    let mut p = Point {x: 3, y: 4};
+
+    // Here I create an outstanding loan and check that we get conflicts:
+
+    let l = &mut p;
+    p.impurem(); //~ ERROR cannot borrow
+
+    l.x += 1;
+}
+
+fn main() {
+}
diff --git a/src/test/ui/borrowck/borrowck-loan-rcvr.stderr b/src/test/ui/borrowck/borrowck-loan-rcvr.stderr
new file mode 100644
index 0000000..56d33ef
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-loan-rcvr.stderr
@@ -0,0 +1,26 @@
+error[E0502]: cannot borrow `p` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-loan-rcvr.rs:23:14
+   |
+LL |     p.blockm(|| {
+   |     -        ^^ mutable borrow occurs here
+   |     |
+   |     immutable borrow occurs here
+LL |         p.x = 10;
+   |         - borrow occurs due to use of `p` in closure
+LL |     })
+   |      - immutable borrow ends here
+
+error[E0502]: cannot borrow `p` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-loan-rcvr.rs:34:5
+   |
+LL |     let l = &mut p;
+   |                  - mutable borrow occurs here
+LL |     p.impurem();
+   |     ^ immutable borrow occurs here
+...
+LL | }
+   | - mutable borrow ends here
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/borrowck/borrowck-loan-vec-content.nll.stderr b/src/test/ui/borrowck/borrowck-loan-vec-content.nll.stderr
new file mode 100644
index 0000000..6691a23
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-loan-vec-content.nll.stderr
@@ -0,0 +1,15 @@
+error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-loan-vec-content.rs:18:9
+   |
+LL |     takes_imm_elt(
+   |     ------------- immutable borrow later used by call
+LL |         &v[0],
+   |          - immutable borrow occurs here
+LL |         || {
+   |         ^^ mutable borrow occurs here
+LL |             v[1] = 4;
+   |             - second borrow occurs due to use of `v` in closure
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/borrowck/borrowck-loan-vec-content.rs b/src/test/ui/borrowck/borrowck-loan-vec-content.rs
new file mode 100644
index 0000000..300ec88
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-loan-vec-content.rs
@@ -0,0 +1,24 @@
+// Here we check that it is allowed to lend out an element of a
+// (locally rooted) mutable, unique vector, and that we then prevent
+// modifications to the contents.
+
+fn takes_imm_elt<F>(_v: &isize, f: F) where F: FnOnce() {
+    f();
+}
+
+fn has_mut_vec_and_does_not_try_to_change_it() {
+    let mut v: Vec<isize> = vec![1, 2, 3];
+    takes_imm_elt(&v[0], || {})
+}
+
+fn has_mut_vec_but_tries_to_change_it() {
+    let mut v: Vec<isize> = vec![1, 2, 3];
+    takes_imm_elt(
+        &v[0],
+        || { //~ ERROR cannot borrow `v` as mutable
+            v[1] = 4;
+        })
+}
+
+fn main() {
+}
diff --git a/src/test/ui/borrowck/borrowck-loan-vec-content.stderr b/src/test/ui/borrowck/borrowck-loan-vec-content.stderr
new file mode 100644
index 0000000..eea6a09
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-loan-vec-content.stderr
@@ -0,0 +1,15 @@
+error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-loan-vec-content.rs:18:9
+   |
+LL |         &v[0],
+   |          - immutable borrow occurs here
+LL |         || {
+   |         ^^ mutable borrow occurs here
+LL |             v[1] = 4;
+   |             - borrow occurs due to use of `v` in closure
+LL |         })
+   |          - immutable borrow ends here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/borrowck/borrowck-local-borrow-outlives-fn.ast.nll.stderr b/src/test/ui/borrowck/borrowck-local-borrow-outlives-fn.ast.nll.stderr
new file mode 100644
index 0000000..df89e85
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-local-borrow-outlives-fn.ast.nll.stderr
@@ -0,0 +1,9 @@
+error[E0515]: cannot return reference to function parameter `x`
+  --> $DIR/borrowck-local-borrow-outlives-fn.rs:5:5
+   |
+LL |     &x
+   |     ^^ returns a reference to data owned by the current function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/src/test/ui/borrowck/borrowck-local-borrow-outlives-fn.ast.stderr b/src/test/ui/borrowck/borrowck-local-borrow-outlives-fn.ast.stderr
new file mode 100644
index 0000000..6eda8a4
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-local-borrow-outlives-fn.ast.stderr
@@ -0,0 +1,14 @@
+error[E0597]: `x` does not live long enough
+  --> $DIR/borrowck-local-borrow-outlives-fn.rs:5:6
+   |
+LL |     &x
+   |      ^ borrowed value does not live long enough
+...
+LL | }
+   | - borrowed value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/borrowck/borrowck-local-borrow-outlives-fn.mir.stderr b/src/test/ui/borrowck/borrowck-local-borrow-outlives-fn.mir.stderr
new file mode 100644
index 0000000..df89e85
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-local-borrow-outlives-fn.mir.stderr
@@ -0,0 +1,9 @@
+error[E0515]: cannot return reference to function parameter `x`
+  --> $DIR/borrowck-local-borrow-outlives-fn.rs:5:5
+   |
+LL |     &x
+   |     ^^ returns a reference to data owned by the current function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/src/test/ui/borrowck/borrowck-local-borrow-outlives-fn.rs b/src/test/ui/borrowck/borrowck-local-borrow-outlives-fn.rs
new file mode 100644
index 0000000..6137ac9
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-local-borrow-outlives-fn.rs
@@ -0,0 +1,10 @@
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+fn cplusplus_mode(x: isize) -> &'static isize {
+    &x
+    //[ast]~^ ERROR `x` does not live long enough [E0597]
+    //[mir]~^^ ERROR cannot return reference to function parameter `x` [E0515]
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/borrowck-local-borrow-with-panic-outlives-fn.ast.nll.stderr b/src/test/ui/borrowck/borrowck-local-borrow-with-panic-outlives-fn.ast.nll.stderr
new file mode 100644
index 0000000..ac9e73f
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-local-borrow-with-panic-outlives-fn.ast.nll.stderr
@@ -0,0 +1,15 @@
+error[E0597]: `z.1` does not live long enough
+  --> $DIR/borrowck-local-borrow-with-panic-outlives-fn.rs:6:15
+   |
+LL |     *x = Some(&mut z.1);
+   |     ----------^^^^^^^^-
+   |     |         |
+   |     |         borrowed value does not live long enough
+   |     assignment requires that `z.1` is borrowed for `'static`
+...
+LL | }
+   | - `z.1` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/borrowck/borrowck-local-borrow-with-panic-outlives-fn.ast.stderr b/src/test/ui/borrowck/borrowck-local-borrow-with-panic-outlives-fn.ast.stderr
new file mode 100644
index 0000000..89a0e6c
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-local-borrow-with-panic-outlives-fn.ast.stderr
@@ -0,0 +1,14 @@
+error[E0597]: `z.1` does not live long enough
+  --> $DIR/borrowck-local-borrow-with-panic-outlives-fn.rs:6:20
+   |
+LL |     *x = Some(&mut z.1);
+   |                    ^^^ borrowed value does not live long enough
+...
+LL | }
+   | - borrowed value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/borrowck/borrowck-local-borrow-with-panic-outlives-fn.mir.stderr b/src/test/ui/borrowck/borrowck-local-borrow-with-panic-outlives-fn.mir.stderr
new file mode 100644
index 0000000..ac9e73f
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-local-borrow-with-panic-outlives-fn.mir.stderr
@@ -0,0 +1,15 @@
+error[E0597]: `z.1` does not live long enough
+  --> $DIR/borrowck-local-borrow-with-panic-outlives-fn.rs:6:15
+   |
+LL |     *x = Some(&mut z.1);
+   |     ----------^^^^^^^^-
+   |     |         |
+   |     |         borrowed value does not live long enough
+   |     assignment requires that `z.1` is borrowed for `'static`
+...
+LL | }
+   | - `z.1` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/borrowck/borrowck-local-borrow-with-panic-outlives-fn.rs b/src/test/ui/borrowck/borrowck-local-borrow-with-panic-outlives-fn.rs
new file mode 100644
index 0000000..9ead465
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-local-borrow-with-panic-outlives-fn.rs
@@ -0,0 +1,14 @@
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+fn cplusplus_mode_exceptionally_unsafe(x: &mut Option<&'static mut isize>) {
+    let mut z = (0, 0);
+    *x = Some(&mut z.1);
+    //[ast]~^ ERROR `z.1` does not live long enough [E0597]
+    //[mir]~^^ ERROR `z.1` does not live long enough [E0597]
+    panic!("catch me for a dangling pointer!")
+}
+
+fn main() {
+    cplusplus_mode_exceptionally_unsafe(&mut None);
+}
diff --git a/src/test/ui/borrowck/borrowck-match-already-borrowed.ast.nll.stderr b/src/test/ui/borrowck/borrowck-match-already-borrowed.ast.nll.stderr
new file mode 100644
index 0000000..ecbfeec
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-match-already-borrowed.ast.nll.stderr
@@ -0,0 +1,51 @@
+error[E0503]: cannot use `foo` because it was mutably borrowed
+  --> $DIR/borrowck-match-already-borrowed.rs:13:9
+   |
+LL |     let p = &mut foo;
+   |             -------- borrow of `foo` occurs here
+LL |     let _ = match foo {
+LL |         Foo::B => 1,
+   |         ^^^^^^ use of borrowed `foo`
+...
+LL |     drop(p);
+   |          - borrow later used here
+
+error[E0503]: cannot use `foo.0` because it was mutably borrowed
+  --> $DIR/borrowck-match-already-borrowed.rs:15:16
+   |
+LL |     let p = &mut foo;
+   |             -------- borrow of `foo` occurs here
+...
+LL |         Foo::A(x) => x
+   |                ^ use of borrowed `foo`
+...
+LL |     drop(p);
+   |          - borrow later used here
+
+error[E0503]: cannot use `x` because it was mutably borrowed
+  --> $DIR/borrowck-match-already-borrowed.rs:26:9
+   |
+LL |     let r = &mut x;
+   |             ------ borrow of `x` occurs here
+LL |     let _ = match x {
+LL |         x => x + 1,
+   |         ^ use of borrowed `x`
+...
+LL |     drop(r);
+   |          - borrow later used here
+
+error[E0503]: cannot use `x` because it was mutably borrowed
+  --> $DIR/borrowck-match-already-borrowed.rs:28:9
+   |
+LL |     let r = &mut x;
+   |             ------ borrow of `x` occurs here
+...
+LL |         y => y + 2,
+   |         ^ use of borrowed `x`
+...
+LL |     drop(r);
+   |          - borrow later used here
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0503`.
diff --git a/src/test/ui/borrowck/borrowck-match-already-borrowed.ast.stderr b/src/test/ui/borrowck/borrowck-match-already-borrowed.ast.stderr
new file mode 100644
index 0000000..a5da1fc
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-match-already-borrowed.ast.stderr
@@ -0,0 +1,30 @@
+error[E0503]: cannot use `(foo as Foo::A).0` because it was mutably borrowed
+  --> $DIR/borrowck-match-already-borrowed.rs:15:16
+   |
+LL |     let p = &mut foo;
+   |                  --- borrow of `foo` occurs here
+...
+LL |         Foo::A(x) => x
+   |                ^ use of borrowed `foo`
+
+error[E0503]: cannot use `x` because it was mutably borrowed
+  --> $DIR/borrowck-match-already-borrowed.rs:26:9
+   |
+LL |     let r = &mut x;
+   |                  - borrow of `x` occurs here
+LL |     let _ = match x {
+LL |         x => x + 1,
+   |         ^ use of borrowed `x`
+
+error[E0503]: cannot use `x` because it was mutably borrowed
+  --> $DIR/borrowck-match-already-borrowed.rs:28:9
+   |
+LL |     let r = &mut x;
+   |                  - borrow of `x` occurs here
+...
+LL |         y => y + 2,
+   |         ^ use of borrowed `x`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0503`.
diff --git a/src/test/ui/borrowck/borrowck-match-already-borrowed.mir.stderr b/src/test/ui/borrowck/borrowck-match-already-borrowed.mir.stderr
new file mode 100644
index 0000000..ecbfeec
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-match-already-borrowed.mir.stderr
@@ -0,0 +1,51 @@
+error[E0503]: cannot use `foo` because it was mutably borrowed
+  --> $DIR/borrowck-match-already-borrowed.rs:13:9
+   |
+LL |     let p = &mut foo;
+   |             -------- borrow of `foo` occurs here
+LL |     let _ = match foo {
+LL |         Foo::B => 1,
+   |         ^^^^^^ use of borrowed `foo`
+...
+LL |     drop(p);
+   |          - borrow later used here
+
+error[E0503]: cannot use `foo.0` because it was mutably borrowed
+  --> $DIR/borrowck-match-already-borrowed.rs:15:16
+   |
+LL |     let p = &mut foo;
+   |             -------- borrow of `foo` occurs here
+...
+LL |         Foo::A(x) => x
+   |                ^ use of borrowed `foo`
+...
+LL |     drop(p);
+   |          - borrow later used here
+
+error[E0503]: cannot use `x` because it was mutably borrowed
+  --> $DIR/borrowck-match-already-borrowed.rs:26:9
+   |
+LL |     let r = &mut x;
+   |             ------ borrow of `x` occurs here
+LL |     let _ = match x {
+LL |         x => x + 1,
+   |         ^ use of borrowed `x`
+...
+LL |     drop(r);
+   |          - borrow later used here
+
+error[E0503]: cannot use `x` because it was mutably borrowed
+  --> $DIR/borrowck-match-already-borrowed.rs:28:9
+   |
+LL |     let r = &mut x;
+   |             ------ borrow of `x` occurs here
+...
+LL |         y => y + 2,
+   |         ^ use of borrowed `x`
+...
+LL |     drop(r);
+   |          - borrow later used here
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0503`.
diff --git a/src/test/ui/borrowck/borrowck-match-already-borrowed.rs b/src/test/ui/borrowck/borrowck-match-already-borrowed.rs
new file mode 100644
index 0000000..7f4cdbd
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-match-already-borrowed.rs
@@ -0,0 +1,32 @@
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+enum Foo {
+    A(i32),
+    B
+}
+
+fn match_enum() {
+    let mut foo = Foo::B;
+    let p = &mut foo;
+    let _ = match foo {
+        Foo::B => 1, //[mir]~ ERROR [E0503]
+        _ => 2,
+        Foo::A(x) => x //[ast]~ ERROR [E0503]
+                       //[mir]~^ ERROR [E0503]
+    };
+    drop(p);
+}
+
+
+fn main() {
+    let mut x = 1;
+    let r = &mut x;
+    let _ = match x {
+        x => x + 1, //[ast]~ ERROR [E0503]
+                    //[mir]~^ ERROR [E0503]
+        y => y + 2, //[ast]~ ERROR [E0503]
+                    //[mir]~^ ERROR [E0503]
+    };
+    drop(r);
+}
diff --git a/src/test/ui/borrowck/borrowck-match-binding-is-assignment.ast.nll.stderr b/src/test/ui/borrowck/borrowck-match-binding-is-assignment.ast.nll.stderr
new file mode 100644
index 0000000..2ac0539
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-match-binding-is-assignment.ast.nll.stderr
@@ -0,0 +1,58 @@
+error[E0384]: cannot assign twice to immutable variable `x`
+  --> $DIR/borrowck-match-binding-is-assignment.rs:17:13
+   |
+LL |         x => {
+   |         -
+   |         |
+   |         first assignment to `x`
+   |         help: make this binding mutable: `mut x`
+LL |             x += 1;
+   |             ^^^^^^ cannot assign twice to immutable variable
+
+error[E0384]: cannot assign twice to immutable variable `x`
+  --> $DIR/borrowck-match-binding-is-assignment.rs:24:13
+   |
+LL |         E::Foo(x) => {
+   |                -
+   |                |
+   |                first assignment to `x`
+   |                help: make this binding mutable: `mut x`
+LL |             x += 1;
+   |             ^^^^^^ cannot assign twice to immutable variable
+
+error[E0384]: cannot assign twice to immutable variable `x`
+  --> $DIR/borrowck-match-binding-is-assignment.rs:31:13
+   |
+LL |         S { bar: x } => {
+   |                  -
+   |                  |
+   |                  first assignment to `x`
+   |                  help: make this binding mutable: `mut x`
+LL |             x += 1;
+   |             ^^^^^^ cannot assign twice to immutable variable
+
+error[E0384]: cannot assign twice to immutable variable `x`
+  --> $DIR/borrowck-match-binding-is-assignment.rs:38:13
+   |
+LL |         (x,) => {
+   |          -
+   |          |
+   |          first assignment to `x`
+   |          help: make this binding mutable: `mut x`
+LL |             x += 1;
+   |             ^^^^^^ cannot assign twice to immutable variable
+
+error[E0384]: cannot assign twice to immutable variable `x`
+  --> $DIR/borrowck-match-binding-is-assignment.rs:45:13
+   |
+LL |         [x,_,_] => {
+   |          -
+   |          |
+   |          first assignment to `x`
+   |          help: make this binding mutable: `mut x`
+LL |             x += 1;
+   |             ^^^^^^ cannot assign twice to immutable variable
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0384`.
diff --git a/src/test/ui/borrowck/borrowck-match-binding-is-assignment.ast.stderr b/src/test/ui/borrowck/borrowck-match-binding-is-assignment.ast.stderr
new file mode 100644
index 0000000..5f43302
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-match-binding-is-assignment.ast.stderr
@@ -0,0 +1,43 @@
+error[E0384]: cannot assign twice to immutable variable `x`
+  --> $DIR/borrowck-match-binding-is-assignment.rs:17:13
+   |
+LL |         x => {
+   |         - first assignment to `x`
+LL |             x += 1;
+   |             ^^^^^^ cannot assign twice to immutable variable
+
+error[E0384]: cannot assign twice to immutable variable `x`
+  --> $DIR/borrowck-match-binding-is-assignment.rs:24:13
+   |
+LL |         E::Foo(x) => {
+   |                - first assignment to `x`
+LL |             x += 1;
+   |             ^^^^^^ cannot assign twice to immutable variable
+
+error[E0384]: cannot assign twice to immutable variable `x`
+  --> $DIR/borrowck-match-binding-is-assignment.rs:31:13
+   |
+LL |         S { bar: x } => {
+   |                  - first assignment to `x`
+LL |             x += 1;
+   |             ^^^^^^ cannot assign twice to immutable variable
+
+error[E0384]: cannot assign twice to immutable variable `x`
+  --> $DIR/borrowck-match-binding-is-assignment.rs:38:13
+   |
+LL |         (x,) => {
+   |          - first assignment to `x`
+LL |             x += 1;
+   |             ^^^^^^ cannot assign twice to immutable variable
+
+error[E0384]: cannot assign twice to immutable variable `x`
+  --> $DIR/borrowck-match-binding-is-assignment.rs:45:13
+   |
+LL |         [x,_,_] => {
+   |          - first assignment to `x`
+LL |             x += 1;
+   |             ^^^^^^ cannot assign twice to immutable variable
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0384`.
diff --git a/src/test/ui/borrowck/borrowck-match-binding-is-assignment.mir.stderr b/src/test/ui/borrowck/borrowck-match-binding-is-assignment.mir.stderr
new file mode 100644
index 0000000..2ac0539
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-match-binding-is-assignment.mir.stderr
@@ -0,0 +1,58 @@
+error[E0384]: cannot assign twice to immutable variable `x`
+  --> $DIR/borrowck-match-binding-is-assignment.rs:17:13
+   |
+LL |         x => {
+   |         -
+   |         |
+   |         first assignment to `x`
+   |         help: make this binding mutable: `mut x`
+LL |             x += 1;
+   |             ^^^^^^ cannot assign twice to immutable variable
+
+error[E0384]: cannot assign twice to immutable variable `x`
+  --> $DIR/borrowck-match-binding-is-assignment.rs:24:13
+   |
+LL |         E::Foo(x) => {
+   |                -
+   |                |
+   |                first assignment to `x`
+   |                help: make this binding mutable: `mut x`
+LL |             x += 1;
+   |             ^^^^^^ cannot assign twice to immutable variable
+
+error[E0384]: cannot assign twice to immutable variable `x`
+  --> $DIR/borrowck-match-binding-is-assignment.rs:31:13
+   |
+LL |         S { bar: x } => {
+   |                  -
+   |                  |
+   |                  first assignment to `x`
+   |                  help: make this binding mutable: `mut x`
+LL |             x += 1;
+   |             ^^^^^^ cannot assign twice to immutable variable
+
+error[E0384]: cannot assign twice to immutable variable `x`
+  --> $DIR/borrowck-match-binding-is-assignment.rs:38:13
+   |
+LL |         (x,) => {
+   |          -
+   |          |
+   |          first assignment to `x`
+   |          help: make this binding mutable: `mut x`
+LL |             x += 1;
+   |             ^^^^^^ cannot assign twice to immutable variable
+
+error[E0384]: cannot assign twice to immutable variable `x`
+  --> $DIR/borrowck-match-binding-is-assignment.rs:45:13
+   |
+LL |         [x,_,_] => {
+   |          -
+   |          |
+   |          first assignment to `x`
+   |          help: make this binding mutable: `mut x`
+LL |             x += 1;
+   |             ^^^^^^ cannot assign twice to immutable variable
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0384`.
diff --git a/src/test/ui/borrowck/borrowck-match-binding-is-assignment.rs b/src/test/ui/borrowck/borrowck-match-binding-is-assignment.rs
new file mode 100644
index 0000000..2c9c41c
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-match-binding-is-assignment.rs
@@ -0,0 +1,49 @@
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+// Test that immutable pattern bindings cannot be reassigned.
+
+enum E {
+    Foo(isize)
+}
+
+struct S {
+    bar: isize,
+}
+
+pub fn main() {
+    match 1 {
+        x => {
+            x += 1; //[ast]~ ERROR cannot assign twice to immutable variable `x`
+                    //[mir]~^ ERROR [E0384]
+        }
+    }
+
+    match E::Foo(1) {
+        E::Foo(x) => {
+            x += 1; //[ast]~ ERROR cannot assign twice to immutable variable `x`
+                    //[mir]~^ ERROR [E0384]
+        }
+    }
+
+    match (S { bar: 1 }) {
+        S { bar: x } => {
+            x += 1; //[ast]~ ERROR cannot assign twice to immutable variable `x`
+                    //[mir]~^ ERROR [E0384]
+        }
+    }
+
+    match (1,) {
+        (x,) => {
+            x += 1; //[ast]~ ERROR cannot assign twice to immutable variable `x`
+                    //[mir]~^ ERROR [E0384]
+        }
+    }
+
+    match [1,2,3] {
+        [x,_,_] => {
+            x += 1; //[ast]~ ERROR cannot assign twice to immutable variable `x`
+                    //[mir]~^ ERROR [E0384]
+        }
+    }
+}
diff --git a/src/test/ui/borrowck/borrowck-migrate-to-nll.edition.stderr b/src/test/ui/borrowck/borrowck-migrate-to-nll.edition.stderr
new file mode 100644
index 0000000..8dba34b
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-migrate-to-nll.edition.stderr
@@ -0,0 +1,9 @@
+warning[E0507]: cannot move out of borrowed content
+  --> $DIR/borrowck-migrate-to-nll.rs:25:17
+   |
+LL |                 (|| { let bar = foo; bar.take() })();
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+   |
+   = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
+   = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+
diff --git a/src/test/ui/borrowck/borrowck-migrate-to-nll.rs b/src/test/ui/borrowck/borrowck-migrate-to-nll.rs
new file mode 100644
index 0000000..5b7018d
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-migrate-to-nll.rs
@@ -0,0 +1,31 @@
+// This is a test of the borrowck migrate mode. It leverages #27282, a
+// bug that is fixed by NLL: this code is (unsoundly) accepted by
+// AST-borrowck, but is correctly rejected by the NLL borrowck.
+//
+// Therefore, for backwards-compatiblity, under borrowck=migrate the
+// NLL checks will be emitted as *warnings*.
+
+// NLL mode makes this compile-fail; we cannot currently encode a
+// test that is run-pass or compile-fail based on compare-mode. So
+// just ignore it instead:
+
+// ignore-compare-mode-nll
+
+// revisions: zflag edition
+//[zflag]compile-flags: -Z borrowck=migrate
+//[edition]edition:2018
+//[zflag] run-pass
+//[edition] run-pass
+
+fn main() {
+    match Some(&4) {
+        None => {},
+        ref mut foo
+            if {
+                (|| { let bar = foo; bar.take() })();
+                false
+            } => {},
+        Some(ref _s) => println!("Note this arm is bogus; the `Some` became `None` in the guard."),
+        _ => println!("Here is some supposedly unreachable code."),
+    }
+}
diff --git a/src/test/ui/borrowck/borrowck-migrate-to-nll.zflag.stderr b/src/test/ui/borrowck/borrowck-migrate-to-nll.zflag.stderr
new file mode 100644
index 0000000..8dba34b
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-migrate-to-nll.zflag.stderr
@@ -0,0 +1,9 @@
+warning[E0507]: cannot move out of borrowed content
+  --> $DIR/borrowck-migrate-to-nll.rs:25:17
+   |
+LL |                 (|| { let bar = foo; bar.take() })();
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+   |
+   = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
+   = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+
diff --git a/src/test/ui/borrowck/borrowck-move-by-capture.nll.stderr b/src/test/ui/borrowck/borrowck-move-by-capture.nll.stderr
new file mode 100644
index 0000000..38f6ca7
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-by-capture.nll.stderr
@@ -0,0 +1,12 @@
+error[E0507]: cannot move out of captured variable in an `FnMut` closure
+  --> $DIR/borrowck-move-by-capture.rs:9:29
+   |
+LL |     let bar: Box<_> = box 3;
+   |         --- captured outer variable
+LL |     let _g = to_fn_mut(|| {
+LL |         let _h = to_fn_once(move || -> isize { *bar });
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of captured variable in an `FnMut` closure
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/borrowck/borrowck-move-by-capture.rs b/src/test/ui/borrowck/borrowck-move-by-capture.rs
new file mode 100644
index 0000000..a825ed5
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-by-capture.rs
@@ -0,0 +1,11 @@
+#![feature(box_syntax,unboxed_closures)]
+
+fn to_fn_mut<A,F:FnMut<A>>(f: F) -> F { f }
+fn to_fn_once<A,F:FnOnce<A>>(f: F) -> F { f }
+
+pub fn main() {
+    let bar: Box<_> = box 3;
+    let _g = to_fn_mut(|| {
+        let _h = to_fn_once(move || -> isize { *bar }); //~ ERROR cannot move out of
+    });
+}
diff --git a/src/test/ui/borrowck/borrowck-move-by-capture.stderr b/src/test/ui/borrowck/borrowck-move-by-capture.stderr
new file mode 100644
index 0000000..d845a57
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-by-capture.stderr
@@ -0,0 +1,12 @@
+error[E0507]: cannot move out of captured outer variable in an `FnMut` closure
+  --> $DIR/borrowck-move-by-capture.rs:9:29
+   |
+LL |     let bar: Box<_> = box 3;
+   |         --- captured outer variable
+LL |     let _g = to_fn_mut(|| {
+LL |         let _h = to_fn_once(move || -> isize { *bar });
+   |                             ^^^^^^^^^^^^^^^^ cannot move out of captured outer variable in an `FnMut` closure
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/borrowck/borrowck-move-error-with-note.nll.stderr b/src/test/ui/borrowck/borrowck-move-error-with-note.nll.stderr
new file mode 100644
index 0000000..25eb8d0
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-error-with-note.nll.stderr
@@ -0,0 +1,67 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/borrowck-move-error-with-note.rs:11:11
+   |
+LL |     match *f {
+   |           ^^
+   |           |
+   |           cannot move out of borrowed content
+   |           help: consider removing the `*`: `f`
+LL |
+LL |         Foo::Foo1(num1,
+   |                   ---- data moved here
+LL |                   num2) => (),
+   |                   ---- ...and here
+LL |         Foo::Foo2(num) => (),
+   |                   --- ...and here
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/borrowck-move-error-with-note.rs:13:19
+   |
+LL |         Foo::Foo1(num1,
+   |                   ^^^^
+LL |                   num2) => (),
+   |                   ^^^^
+LL |         Foo::Foo2(num) => (),
+   |                   ^^^
+
+error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
+  --> $DIR/borrowck-move-error-with-note.rs:29:11
+   |
+LL |     match (S {f: "foo".to_string(), g: "bar".to_string()}) {
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of here
+...
+LL |             f: _s,
+   |                -- data moved here
+LL |             g: _t
+   |                -- ...and here
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/borrowck-move-error-with-note.rs:32:16
+   |
+LL |             f: _s,
+   |                ^^
+LL |             g: _t
+   |                ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/borrowck-move-error-with-note.rs:47:11
+   |
+LL |     match a.a {
+   |           ^^^
+   |           |
+   |           cannot move out of borrowed content
+   |           help: consider borrowing here: `&a.a`
+LL |
+LL |         n => {
+   |         - data moved here
+   |
+note: move occurs because `n` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-move-error-with-note.rs:49:9
+   |
+LL |         n => {
+   |         ^
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0507, E0509.
+For more information about an error, try `rustc --explain E0507`.
diff --git a/src/test/ui/borrowck/borrowck-move-error-with-note.rs b/src/test/ui/borrowck/borrowck-move-error-with-note.rs
new file mode 100644
index 0000000..d2dab2e
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-error-with-note.rs
@@ -0,0 +1,56 @@
+#![feature(box_syntax)]
+
+enum Foo {
+    Foo1(Box<u32>, Box<u32>),
+    Foo2(Box<u32>),
+    Foo3,
+}
+
+fn blah() {
+    let f = &Foo::Foo1(box 1, box 2);
+    match *f {             //~ ERROR cannot move out of
+                           //~| cannot move out
+        Foo::Foo1(num1,
+                  num2) => (),
+        Foo::Foo2(num) => (),
+        Foo::Foo3 => ()
+    }
+}
+
+struct S {
+    f: String,
+    g: String
+}
+impl Drop for S {
+    fn drop(&mut self) { println!("{}", self.f); }
+}
+
+fn move_in_match() {
+    match (S {f: "foo".to_string(), g: "bar".to_string()}) {
+        S {         //~ ERROR cannot move out of type `S`, which implements the `Drop` trait
+        //~| cannot move out of here
+            f: _s,
+            g: _t
+        } => {}
+    }
+}
+
+// from issue-8064
+struct A {
+    a: Box<isize>,
+}
+
+fn free<T>(_: T) {}
+
+fn blah2() {
+    let a = &A { a: box 1 };
+    match a.a {           //~ ERROR cannot move out of
+                          //~| cannot move out
+        n => {
+            free(n)
+        }
+    }
+    free(a)
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/borrowck-move-error-with-note.stderr b/src/test/ui/borrowck/borrowck-move-error-with-note.stderr
new file mode 100644
index 0000000..8b07229
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-error-with-note.stderr
@@ -0,0 +1,38 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/borrowck-move-error-with-note.rs:11:11
+   |
+LL |     match *f {
+   |           ^^ cannot move out of borrowed content
+LL |
+LL |         Foo::Foo1(num1,
+   |                   ---- hint: to prevent move, use `ref num1` or `ref mut num1`
+LL |                   num2) => (),
+   |                   ---- ...and here (use `ref num2` or `ref mut num2`)
+LL |         Foo::Foo2(num) => (),
+   |                   --- ...and here (use `ref num` or `ref mut num`)
+
+error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
+  --> $DIR/borrowck-move-error-with-note.rs:30:9
+   |
+LL | /         S {
+LL | |
+LL | |             f: _s,
+   | |                -- hint: to prevent move, use `ref _s` or `ref mut _s`
+LL | |             g: _t
+   | |                -- ...and here (use `ref _t` or `ref mut _t`)
+LL | |         } => {}
+   | |_________^ cannot move out of here
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/borrowck-move-error-with-note.rs:47:11
+   |
+LL |     match a.a {
+   |           ^ cannot move out of borrowed content
+LL |
+LL |         n => {
+   |         - hint: to prevent move, use `ref n` or `ref mut n`
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0507, E0509.
+For more information about an error, try `rustc --explain E0507`.
diff --git a/src/test/ui/borrowck/borrowck-move-from-subpath-of-borrowed-path.nll.stderr b/src/test/ui/borrowck/borrowck-move-from-subpath-of-borrowed-path.nll.stderr
new file mode 100644
index 0000000..e4840fb
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-from-subpath-of-borrowed-path.nll.stderr
@@ -0,0 +1,14 @@
+error[E0505]: cannot move out of `*a` because it is borrowed
+  --> $DIR/borrowck-move-from-subpath-of-borrowed-path.rs:12:13
+   |
+LL |     let b = &a;
+   |             -- borrow of `a` occurs here
+LL | 
+LL |     let z = *a;
+   |             ^^ move out of `*a` occurs here
+LL |     b.use_ref();
+   |     - borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0505`.
diff --git a/src/test/ui/borrowck/borrowck-move-from-subpath-of-borrowed-path.rs b/src/test/ui/borrowck/borrowck-move-from-subpath-of-borrowed-path.rs
new file mode 100644
index 0000000..e058c80
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-from-subpath-of-borrowed-path.rs
@@ -0,0 +1,17 @@
+// verify that an error is raised when trying to move out of a
+// borrowed path.
+
+
+
+#![feature(box_syntax)]
+
+fn main() {
+    let a: Box<Box<_>> = box box 2;
+    let b = &a;
+
+    let z = *a; //~ ERROR: cannot move out of `*a` because it is borrowed
+    b.use_ref();
+}
+
+trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { }  }
+impl<T> Fake for T { }
diff --git a/src/test/ui/borrowck/borrowck-move-from-subpath-of-borrowed-path.stderr b/src/test/ui/borrowck/borrowck-move-from-subpath-of-borrowed-path.stderr
new file mode 100644
index 0000000..5e2428e
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-from-subpath-of-borrowed-path.stderr
@@ -0,0 +1,12 @@
+error[E0505]: cannot move out of `*a` because it is borrowed
+  --> $DIR/borrowck-move-from-subpath-of-borrowed-path.rs:12:9
+   |
+LL |     let b = &a;
+   |              - borrow of `a` occurs here
+LL | 
+LL |     let z = *a;
+   |         ^ move out of `*a` occurs here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0505`.
diff --git a/src/test/ui/borrowck/borrowck-move-from-unsafe-ptr.nll.stderr b/src/test/ui/borrowck/borrowck-move-from-unsafe-ptr.nll.stderr
new file mode 100644
index 0000000..615e3fd
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-from-unsafe-ptr.nll.stderr
@@ -0,0 +1,12 @@
+error[E0507]: cannot move out of dereference of raw pointer
+  --> $DIR/borrowck-move-from-unsafe-ptr.rs:2:13
+   |
+LL |     let y = *x;
+   |             ^^
+   |             |
+   |             cannot move out of dereference of raw pointer
+   |             help: consider removing the `*`: `x`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/borrowck/borrowck-move-from-unsafe-ptr.rs b/src/test/ui/borrowck/borrowck-move-from-unsafe-ptr.rs
new file mode 100644
index 0000000..bf8ff9c
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-from-unsafe-ptr.rs
@@ -0,0 +1,7 @@
+unsafe fn foo(x: *const Box<isize>) -> Box<isize> {
+    let y = *x; //~ ERROR cannot move out of dereference of raw pointer
+    return y;
+}
+
+fn main() {
+}
diff --git a/src/test/ui/borrowck/borrowck-move-from-unsafe-ptr.stderr b/src/test/ui/borrowck/borrowck-move-from-unsafe-ptr.stderr
new file mode 100644
index 0000000..c23c5bb
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-from-unsafe-ptr.stderr
@@ -0,0 +1,12 @@
+error[E0507]: cannot move out of dereference of raw pointer
+  --> $DIR/borrowck-move-from-unsafe-ptr.rs:2:13
+   |
+LL |     let y = *x;
+   |             ^^
+   |             |
+   |             cannot move out of dereference of raw pointer
+   |             help: consider using a reference instead: `&*x`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/borrowck/borrowck-move-in-irrefut-pat.ast.nll.stderr b/src/test/ui/borrowck/borrowck-move-in-irrefut-pat.ast.nll.stderr
new file mode 100644
index 0000000..c18fce9
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-in-irrefut-pat.ast.nll.stderr
@@ -0,0 +1,50 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/borrowck-move-in-irrefut-pat.rs:6:13
+   |
+LL | fn arg_item(&_x: &String) {}
+   |             ^--
+   |             ||
+   |             |data moved here
+   |             cannot move out of borrowed content
+   |             help: consider removing the `&`: `_x`
+   |
+note: move occurs because `_x` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-move-in-irrefut-pat.rs:6:14
+   |
+LL | fn arg_item(&_x: &String) {}
+   |              ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/borrowck-move-in-irrefut-pat.rs:11:11
+   |
+LL |     with(|&_x| ())
+   |           ^--
+   |           ||
+   |           |data moved here
+   |           cannot move out of borrowed content
+   |           help: consider removing the `&`: `_x`
+   |
+note: move occurs because `_x` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-move-in-irrefut-pat.rs:11:12
+   |
+LL |     with(|&_x| ())
+   |            ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/borrowck-move-in-irrefut-pat.rs:17:15
+   |
+LL |     let &_x = &"hi".to_string();
+   |         ---   ^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+   |         ||
+   |         |data moved here
+   |         help: consider removing the `&`: `_x`
+   |
+note: move occurs because `_x` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-move-in-irrefut-pat.rs:17:10
+   |
+LL |     let &_x = &"hi".to_string();
+   |          ^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/borrowck/borrowck-move-in-irrefut-pat.ast.stderr b/src/test/ui/borrowck/borrowck-move-in-irrefut-pat.ast.stderr
new file mode 100644
index 0000000..019ed96
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-in-irrefut-pat.ast.stderr
@@ -0,0 +1,30 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/borrowck-move-in-irrefut-pat.rs:6:13
+   |
+LL | fn arg_item(&_x: &String) {}
+   |             ^--
+   |             ||
+   |             |hint: to prevent move, use `ref _x` or `ref mut _x`
+   |             cannot move out of borrowed content
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/borrowck-move-in-irrefut-pat.rs:11:11
+   |
+LL |     with(|&_x| ())
+   |           ^--
+   |           ||
+   |           |hint: to prevent move, use `ref _x` or `ref mut _x`
+   |           cannot move out of borrowed content
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/borrowck-move-in-irrefut-pat.rs:17:9
+   |
+LL |     let &_x = &"hi".to_string();
+   |         ^--
+   |         ||
+   |         |hint: to prevent move, use `ref _x` or `ref mut _x`
+   |         cannot move out of borrowed content
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/borrowck/borrowck-move-in-irrefut-pat.mir.stderr b/src/test/ui/borrowck/borrowck-move-in-irrefut-pat.mir.stderr
new file mode 100644
index 0000000..c18fce9
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-in-irrefut-pat.mir.stderr
@@ -0,0 +1,50 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/borrowck-move-in-irrefut-pat.rs:6:13
+   |
+LL | fn arg_item(&_x: &String) {}
+   |             ^--
+   |             ||
+   |             |data moved here
+   |             cannot move out of borrowed content
+   |             help: consider removing the `&`: `_x`
+   |
+note: move occurs because `_x` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-move-in-irrefut-pat.rs:6:14
+   |
+LL | fn arg_item(&_x: &String) {}
+   |              ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/borrowck-move-in-irrefut-pat.rs:11:11
+   |
+LL |     with(|&_x| ())
+   |           ^--
+   |           ||
+   |           |data moved here
+   |           cannot move out of borrowed content
+   |           help: consider removing the `&`: `_x`
+   |
+note: move occurs because `_x` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-move-in-irrefut-pat.rs:11:12
+   |
+LL |     with(|&_x| ())
+   |            ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/borrowck-move-in-irrefut-pat.rs:17:15
+   |
+LL |     let &_x = &"hi".to_string();
+   |         ---   ^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+   |         ||
+   |         |data moved here
+   |         help: consider removing the `&`: `_x`
+   |
+note: move occurs because `_x` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-move-in-irrefut-pat.rs:17:10
+   |
+LL |     let &_x = &"hi".to_string();
+   |          ^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/borrowck/borrowck-move-in-irrefut-pat.rs b/src/test/ui/borrowck/borrowck-move-in-irrefut-pat.rs
new file mode 100644
index 0000000..c63f4f6
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-in-irrefut-pat.rs
@@ -0,0 +1,22 @@
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+fn with<F>(f: F) where F: FnOnce(&String) {}
+
+fn arg_item(&_x: &String) {}
+    //[ast]~^ ERROR cannot move out of borrowed content [E0507]
+    //[mir]~^^ ERROR [E0507]
+
+fn arg_closure() {
+    with(|&_x| ())
+    //[ast]~^ ERROR cannot move out of borrowed content [E0507]
+    //[mir]~^^ ERROR [E0507]
+}
+
+fn let_pat() {
+    let &_x = &"hi".to_string();
+    //[ast]~^ ERROR cannot move out of borrowed content [E0507]
+    //[mir]~^^ ERROR [E0507]
+}
+
+pub fn main() {}
diff --git a/src/test/ui/borrowck/borrowck-move-moved-value-into-closure.ast.nll.stderr b/src/test/ui/borrowck/borrowck-move-moved-value-into-closure.ast.nll.stderr
new file mode 100644
index 0000000..874c38c
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-moved-value-into-closure.ast.nll.stderr
@@ -0,0 +1,18 @@
+error[E0382]: use of moved value: `t`
+  --> $DIR/borrowck-move-moved-value-into-closure.rs:14:12
+   |
+LL |     let t: Box<_> = box 3;
+   |         - move occurs because `t` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+LL | 
+LL |     call_f(move|| { *t + 1 });
+   |            ------    - variable moved due to use in closure
+   |            |
+   |            value moved into closure here
+LL |     call_f(move|| { *t + 1 });
+   |            ^^^^^^    - use occurs due to use in closure
+   |            |
+   |            value used here after move
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/borrowck-move-moved-value-into-closure.ast.stderr b/src/test/ui/borrowck/borrowck-move-moved-value-into-closure.ast.stderr
new file mode 100644
index 0000000..48651ee
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-moved-value-into-closure.ast.stderr
@@ -0,0 +1,13 @@
+error[E0382]: capture of moved value: `t`
+  --> $DIR/borrowck-move-moved-value-into-closure.rs:14:22
+   |
+LL |     call_f(move|| { *t + 1 });
+   |            ------ value moved (into closure) here
+LL |     call_f(move|| { *t + 1 });
+   |                      ^ value captured here after move
+   |
+   = note: move occurs because `t` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/borrowck-move-moved-value-into-closure.mir.stderr b/src/test/ui/borrowck/borrowck-move-moved-value-into-closure.mir.stderr
new file mode 100644
index 0000000..874c38c
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-moved-value-into-closure.mir.stderr
@@ -0,0 +1,18 @@
+error[E0382]: use of moved value: `t`
+  --> $DIR/borrowck-move-moved-value-into-closure.rs:14:12
+   |
+LL |     let t: Box<_> = box 3;
+   |         - move occurs because `t` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+LL | 
+LL |     call_f(move|| { *t + 1 });
+   |            ------    - variable moved due to use in closure
+   |            |
+   |            value moved into closure here
+LL |     call_f(move|| { *t + 1 });
+   |            ^^^^^^    - use occurs due to use in closure
+   |            |
+   |            value used here after move
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/borrowck-move-moved-value-into-closure.rs b/src/test/ui/borrowck/borrowck-move-moved-value-into-closure.rs
new file mode 100644
index 0000000..2715533
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-moved-value-into-closure.rs
@@ -0,0 +1,16 @@
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+#![feature(box_syntax)]
+
+fn call_f<F:FnOnce() -> isize>(f: F) -> isize {
+    f()
+}
+
+fn main() {
+    let t: Box<_> = box 3;
+
+    call_f(move|| { *t + 1 });
+    call_f(move|| { *t + 1 }); //[ast]~ ERROR capture of moved value
+    //[mir]~^ ERROR use of moved value
+}
diff --git a/src/test/ui/borrowck/borrowck-move-mut-base-ptr.nll.stderr b/src/test/ui/borrowck/borrowck-move-mut-base-ptr.nll.stderr
new file mode 100644
index 0000000..77f5b72
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-mut-base-ptr.nll.stderr
@@ -0,0 +1,14 @@
+error[E0505]: cannot move out of `t0` because it is borrowed
+  --> $DIR/borrowck-move-mut-base-ptr.rs:10:14
+   |
+LL |     let p: &isize = &*t0; // Freezes `*t0`
+   |                     ---- borrow of `*t0` occurs here
+LL |     let t1 = t0;
+   |              ^^ move out of `t0` occurs here
+LL |     *t1 = 22;
+LL |     p.use_ref();
+   |     - borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0505`.
diff --git a/src/test/ui/borrowck/borrowck-move-mut-base-ptr.rs b/src/test/ui/borrowck/borrowck-move-mut-base-ptr.rs
new file mode 100644
index 0000000..10fc143
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-mut-base-ptr.rs
@@ -0,0 +1,19 @@
+// Test that attempt to move `&mut` pointer while pointee is borrowed
+// yields an error.
+//
+// Example from src/librustc_borrowck/borrowck/README.md
+
+
+
+fn foo(t0: &mut isize) {
+    let p: &isize = &*t0; // Freezes `*t0`
+    let t1 = t0;        //~ ERROR cannot move out of `t0`
+    *t1 = 22;
+    p.use_ref();
+}
+
+fn main() {
+}
+
+trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { }  }
+impl<T> Fake for T { }
diff --git a/src/test/ui/borrowck/borrowck-move-mut-base-ptr.stderr b/src/test/ui/borrowck/borrowck-move-mut-base-ptr.stderr
new file mode 100644
index 0000000..d385383
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-mut-base-ptr.stderr
@@ -0,0 +1,11 @@
+error[E0505]: cannot move out of `t0` because it is borrowed
+  --> $DIR/borrowck-move-mut-base-ptr.rs:10:9
+   |
+LL |     let p: &isize = &*t0; // Freezes `*t0`
+   |                      --- borrow of `*t0` occurs here
+LL |     let t1 = t0;
+   |         ^^ move out of `t0` occurs here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0505`.
diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array.ast.stderr b/src/test/ui/borrowck/borrowck-move-out-from-array.ast.stderr
new file mode 100644
index 0000000..88a1ab2
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-out-from-array.ast.stderr
@@ -0,0 +1,23 @@
+error[E0382]: use of moved value: `a[..]`
+  --> $DIR/borrowck-move-out-from-array.rs:10:14
+   |
+LL |     let [_, _x] = a;
+   |             -- value moved here
+LL |     let [.., _y] = a;
+   |              ^^ value used here after move
+   |
+   = note: move occurs because `a[..]` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a[..]`
+  --> $DIR/borrowck-move-out-from-array.rs:17:10
+   |
+LL |     let [_x, _] = a;
+   |          -- value moved here
+LL |     let [_y..] = a;
+   |          ^^ value used here after move
+   |
+   = note: move occurs because `a[..]` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array.mir.stderr b/src/test/ui/borrowck/borrowck-move-out-from-array.mir.stderr
new file mode 100644
index 0000000..88a1ab2
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-out-from-array.mir.stderr
@@ -0,0 +1,23 @@
+error[E0382]: use of moved value: `a[..]`
+  --> $DIR/borrowck-move-out-from-array.rs:10:14
+   |
+LL |     let [_, _x] = a;
+   |             -- value moved here
+LL |     let [.., _y] = a;
+   |              ^^ value used here after move
+   |
+   = note: move occurs because `a[..]` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a[..]`
+  --> $DIR/borrowck-move-out-from-array.rs:17:10
+   |
+LL |     let [_x, _] = a;
+   |          -- value moved here
+LL |     let [_y..] = a;
+   |          ^^ value used here after move
+   |
+   = note: move occurs because `a[..]` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array.rs b/src/test/ui/borrowck/borrowck-move-out-from-array.rs
new file mode 100644
index 0000000..503e7b9
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-out-from-array.rs
@@ -0,0 +1,21 @@
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+#![feature(box_syntax)]
+#![feature(slice_patterns)]
+
+fn move_out_from_begin_and_end() {
+    let a = [box 1, box 2];
+    let [_, _x] = a;
+    let [.., _y] = a; //[ast]~ ERROR [E0382]
+                      //[mir]~^ ERROR [E0382]
+}
+
+fn move_out_by_const_index_and_subslice() {
+    let a = [box 1, box 2];
+    let [_x, _] = a;
+    let [_y..] = a; //[ast]~ ERROR [E0382]
+                    //[mir]~^ ERROR [E0382]
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.ast.nll.stderr b/src/test/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.ast.nll.stderr
new file mode 100644
index 0000000..81afb10
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.ast.nll.stderr
@@ -0,0 +1,9 @@
+error[E0507]: cannot move out of an `Rc`
+  --> $DIR/borrowck-move-out-of-overloaded-auto-deref.rs:7:14
+   |
+LL |     let _x = Rc::new(vec![1, 2]).into_iter();
+   |              ^^^^^^^^^^^^^^^^^^^ cannot move out of an `Rc`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.ast.stderr b/src/test/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.ast.stderr
new file mode 100644
index 0000000..e55898a
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.ast.stderr
@@ -0,0 +1,9 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/borrowck-move-out-of-overloaded-auto-deref.rs:7:14
+   |
+LL |     let _x = Rc::new(vec![1, 2]).into_iter();
+   |              ^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.mir.stderr b/src/test/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.mir.stderr
new file mode 100644
index 0000000..81afb10
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.mir.stderr
@@ -0,0 +1,9 @@
+error[E0507]: cannot move out of an `Rc`
+  --> $DIR/borrowck-move-out-of-overloaded-auto-deref.rs:7:14
+   |
+LL |     let _x = Rc::new(vec![1, 2]).into_iter();
+   |              ^^^^^^^^^^^^^^^^^^^ cannot move out of an `Rc`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.rs b/src/test/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.rs
new file mode 100644
index 0000000..5ced894
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.rs
@@ -0,0 +1,10 @@
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+use std::rc::Rc;
+
+pub fn main() {
+    let _x = Rc::new(vec![1, 2]).into_iter();
+    //[ast]~^ ERROR cannot move out of borrowed content [E0507]
+    //[mir]~^^ ERROR [E0507]
+}
diff --git a/src/test/ui/borrowck/borrowck-move-out-of-overloaded-deref.nll.stderr b/src/test/ui/borrowck/borrowck-move-out-of-overloaded-deref.nll.stderr
new file mode 100644
index 0000000..e6af992
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-out-of-overloaded-deref.nll.stderr
@@ -0,0 +1,12 @@
+error[E0507]: cannot move out of an `Rc`
+  --> $DIR/borrowck-move-out-of-overloaded-deref.rs:4:14
+   |
+LL |     let _x = *Rc::new("hi".to_string());
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |              |
+   |              cannot move out of an `Rc`
+   |              help: consider removing the `*`: `Rc::new("hi".to_string())`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/borrowck/borrowck-move-out-of-overloaded-deref.rs b/src/test/ui/borrowck/borrowck-move-out-of-overloaded-deref.rs
new file mode 100644
index 0000000..d5b6013
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-out-of-overloaded-deref.rs
@@ -0,0 +1,6 @@
+use std::rc::Rc;
+
+pub fn main() {
+    let _x = *Rc::new("hi".to_string());
+    //~^ ERROR cannot move out of borrowed content
+}
diff --git a/src/test/ui/borrowck/borrowck-move-out-of-overloaded-deref.stderr b/src/test/ui/borrowck/borrowck-move-out-of-overloaded-deref.stderr
new file mode 100644
index 0000000..cd8d146
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-out-of-overloaded-deref.stderr
@@ -0,0 +1,12 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/borrowck-move-out-of-overloaded-deref.rs:4:14
+   |
+LL |     let _x = *Rc::new("hi".to_string());
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |              |
+   |              cannot move out of borrowed content
+   |              help: consider using a reference instead: `&*Rc::new("hi".to_string())`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/borrowck/borrowck-move-out-of-static-item.ast.stderr b/src/test/ui/borrowck/borrowck-move-out-of-static-item.ast.stderr
new file mode 100644
index 0000000..26d06c0
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-out-of-static-item.ast.stderr
@@ -0,0 +1,9 @@
+error[E0507]: cannot move out of static item
+  --> $DIR/borrowck-move-out-of-static-item.rs:18:10
+   |
+LL |     test(BAR);
+   |          ^^^ cannot move out of static item
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/borrowck/borrowck-move-out-of-static-item.mir.stderr b/src/test/ui/borrowck/borrowck-move-out-of-static-item.mir.stderr
new file mode 100644
index 0000000..26d06c0
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-out-of-static-item.mir.stderr
@@ -0,0 +1,9 @@
+error[E0507]: cannot move out of static item
+  --> $DIR/borrowck-move-out-of-static-item.rs:18:10
+   |
+LL |     test(BAR);
+   |          ^^^ cannot move out of static item
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/borrowck/borrowck-move-out-of-static-item.rs b/src/test/ui/borrowck/borrowck-move-out-of-static-item.rs
new file mode 100644
index 0000000..d68d5de
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-out-of-static-item.rs
@@ -0,0 +1,20 @@
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+// Ensure that moves out of static items is forbidden
+
+struct Foo {
+    foo: isize,
+}
+
+static BAR: Foo = Foo { foo: 5 };
+
+
+fn test(f: Foo) {
+    let _f = Foo{foo: 4, ..f};
+}
+
+fn main() {
+    test(BAR); //[ast]~ ERROR cannot move out of static item [E0507]
+               //[mir]~^ ERROR [E0507]
+}
diff --git a/src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.ast.nll.stderr b/src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.ast.nll.stderr
new file mode 100644
index 0000000..c1c04ca
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.ast.nll.stderr
@@ -0,0 +1,47 @@
+error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
+  --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:10:11
+   |
+LL |     match (S {f:"foo".to_string()}) {
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of here
+LL |
+LL |         S {f:_s} => {}
+   |              -- data moved here
+   |
+note: move occurs because `_s` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:12:14
+   |
+LL |         S {f:_s} => {}
+   |              ^^
+
+error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
+  --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:18:20
+   |
+LL |     let S {f:_s} = S {f:"foo".to_string()};
+   |              --    ^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of here
+   |              |
+   |              data moved here
+   |
+note: move occurs because `_s` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:18:14
+   |
+LL |     let S {f:_s} = S {f:"foo".to_string()};
+   |              ^^
+
+error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
+  --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:23:19
+   |
+LL | fn move_in_fn_arg(S {f:_s}: S) {
+   |                   ^^^^^--^
+   |                   |    |
+   |                   |    data moved here
+   |                   cannot move out of here
+   |
+note: move occurs because `_s` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:23:24
+   |
+LL | fn move_in_fn_arg(S {f:_s}: S) {
+   |                        ^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0509`.
diff --git a/src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.ast.stderr b/src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.ast.stderr
new file mode 100644
index 0000000..0b025fa
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.ast.stderr
@@ -0,0 +1,30 @@
+error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
+  --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:12:9
+   |
+LL |         S {f:_s} => {}
+   |         ^^^^^--^
+   |         |    |
+   |         |    hint: to prevent move, use `ref _s` or `ref mut _s`
+   |         cannot move out of here
+
+error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
+  --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:18:9
+   |
+LL |     let S {f:_s} = S {f:"foo".to_string()};
+   |         ^^^^^--^
+   |         |    |
+   |         |    hint: to prevent move, use `ref _s` or `ref mut _s`
+   |         cannot move out of here
+
+error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
+  --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:23:19
+   |
+LL | fn move_in_fn_arg(S {f:_s}: S) {
+   |                   ^^^^^--^
+   |                   |    |
+   |                   |    hint: to prevent move, use `ref _s` or `ref mut _s`
+   |                   cannot move out of here
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0509`.
diff --git a/src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.mir.stderr b/src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.mir.stderr
new file mode 100644
index 0000000..c1c04ca
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.mir.stderr
@@ -0,0 +1,47 @@
+error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
+  --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:10:11
+   |
+LL |     match (S {f:"foo".to_string()}) {
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of here
+LL |
+LL |         S {f:_s} => {}
+   |              -- data moved here
+   |
+note: move occurs because `_s` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:12:14
+   |
+LL |         S {f:_s} => {}
+   |              ^^
+
+error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
+  --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:18:20
+   |
+LL |     let S {f:_s} = S {f:"foo".to_string()};
+   |              --    ^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of here
+   |              |
+   |              data moved here
+   |
+note: move occurs because `_s` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:18:14
+   |
+LL |     let S {f:_s} = S {f:"foo".to_string()};
+   |              ^^
+
+error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
+  --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:23:19
+   |
+LL | fn move_in_fn_arg(S {f:_s}: S) {
+   |                   ^^^^^--^
+   |                   |    |
+   |                   |    data moved here
+   |                   cannot move out of here
+   |
+note: move occurs because `_s` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:23:24
+   |
+LL | fn move_in_fn_arg(S {f:_s}: S) {
+   |                        ^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0509`.
diff --git a/src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.rs b/src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.rs
new file mode 100644
index 0000000..cdd71d8
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.rs
@@ -0,0 +1,28 @@
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+struct S {f:String}
+impl Drop for S {
+    fn drop(&mut self) { println!("{}", self.f); }
+}
+
+fn move_in_match() {
+    match (S {f:"foo".to_string()}) {
+        //[mir]~^ ERROR [E0509]
+        S {f:_s} => {}
+        //[ast]~^ ERROR cannot move out of type `S`, which implements the `Drop` trait [E0509]
+    }
+}
+
+fn move_in_let() {
+    let S {f:_s} = S {f:"foo".to_string()};
+    //[ast]~^ ERROR cannot move out of type `S`, which implements the `Drop` trait [E0509]
+    //[mir]~^^ ERROR [E0509]
+}
+
+fn move_in_fn_arg(S {f:_s}: S) {
+    //[ast]~^ ERROR cannot move out of type `S`, which implements the `Drop` trait [E0509]
+    //[mir]~^^ ERROR [E0509]
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.nll.stderr b/src/test/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.nll.stderr
new file mode 100644
index 0000000..cecba15
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.nll.stderr
@@ -0,0 +1,46 @@
+error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
+  --> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:7:11
+   |
+LL |     match S("foo".to_string()) {
+   |           ^^^^^^^^^^^^^^^^^^^^ cannot move out of here
+LL |         S(_s) => {}
+   |           -- data moved here
+   |
+note: move occurs because `_s` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:8:11
+   |
+LL |         S(_s) => {}
+   |           ^^
+
+error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
+  --> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:14:17
+   |
+LL |     let S(_s) = S("foo".to_string());
+   |           --    ^^^^^^^^^^^^^^^^^^^^ cannot move out of here
+   |           |
+   |           data moved here
+   |
+note: move occurs because `_s` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:14:11
+   |
+LL |     let S(_s) = S("foo".to_string());
+   |           ^^
+
+error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
+  --> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:18:19
+   |
+LL | fn move_in_fn_arg(S(_s): S) {
+   |                   ^^--^
+   |                   | |
+   |                   | data moved here
+   |                   cannot move out of here
+   |
+note: move occurs because `_s` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:18:21
+   |
+LL | fn move_in_fn_arg(S(_s): S) {
+   |                     ^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0509`.
diff --git a/src/test/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.rs b/src/test/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.rs
new file mode 100644
index 0000000..bb29411
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.rs
@@ -0,0 +1,22 @@
+struct S(String);
+impl Drop for S {
+    fn drop(&mut self) { }
+}
+
+fn move_in_match() {
+    match S("foo".to_string()) {
+        S(_s) => {}
+        //~^ ERROR cannot move out of type `S`, which implements the `Drop` trait
+    }
+}
+
+fn move_in_let() {
+    let S(_s) = S("foo".to_string());
+    //~^ ERROR cannot move out of type `S`, which implements the `Drop` trait
+}
+
+fn move_in_fn_arg(S(_s): S) {
+    //~^ ERROR cannot move out of type `S`, which implements the `Drop` trait
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.stderr b/src/test/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.stderr
new file mode 100644
index 0000000..134b5e3
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.stderr
@@ -0,0 +1,30 @@
+error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
+  --> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:8:9
+   |
+LL |         S(_s) => {}
+   |         ^^--^
+   |         | |
+   |         | hint: to prevent move, use `ref _s` or `ref mut _s`
+   |         cannot move out of here
+
+error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
+  --> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:14:9
+   |
+LL |     let S(_s) = S("foo".to_string());
+   |         ^^--^
+   |         | |
+   |         | hint: to prevent move, use `ref _s` or `ref mut _s`
+   |         cannot move out of here
+
+error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
+  --> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:18:19
+   |
+LL | fn move_in_fn_arg(S(_s): S) {
+   |                   ^^--^
+   |                   | |
+   |                   | hint: to prevent move, use `ref _s` or `ref mut _s`
+   |                   cannot move out of here
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0509`.
diff --git a/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.nll.stderr b/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.nll.stderr
new file mode 100644
index 0000000..51caf60
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.nll.stderr
@@ -0,0 +1,31 @@
+error[E0508]: cannot move out of type `[Foo]`, a non-copy slice
+  --> $DIR/borrowck-move-out-of-vec-tail.rs:19:19
+   |
+LL |             match tail {
+   |                   ^^^^ cannot move out of here
+LL |                 &[Foo { string: a },
+   |                                 - data moved here
+...
+LL |                   Foo { string: b }] => {
+   |                                 - ...and here
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/borrowck-move-out-of-vec-tail.rs:20:33
+   |
+LL |                 &[Foo { string: a },
+   |                                 ^
+...
+LL |                   Foo { string: b }] => {
+   |                                 ^
+help: consider removing the `&`
+   |
+LL |                 [Foo { string: a },
+LL |
+LL |
+LL |
+LL |                   Foo { string: b }] => {
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0508`.
diff --git a/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.rs b/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.rs
new file mode 100644
index 0000000..5f6e01f
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.rs
@@ -0,0 +1,37 @@
+// Test that we do not permit moves from &[] matched by a vec pattern.
+
+#![feature(slice_patterns)]
+
+#[derive(Clone, Debug)]
+struct Foo {
+    string: String
+}
+
+pub fn main() {
+    let x = vec![
+        Foo { string: "foo".to_string() },
+        Foo { string: "bar".to_string() },
+        Foo { string: "baz".to_string() }
+    ];
+    let x: &[Foo] = &x;
+    match *x {
+        [_, ref tail..] => {
+            match tail {
+                &[Foo { string: a },
+                //~^ ERROR cannot move out of type `[Foo]`
+                //~| cannot move out
+                //~| to prevent move
+                  Foo { string: b }] => {
+                }
+                _ => {
+                    unreachable!();
+                }
+            }
+            let z = tail[0].clone();
+            println!("{:?}", z);
+        }
+        _ => {
+            unreachable!();
+        }
+    }
+}
diff --git a/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.stderr b/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.stderr
new file mode 100644
index 0000000..5ec0dab
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.stderr
@@ -0,0 +1,18 @@
+error[E0508]: cannot move out of type `[Foo]`, a non-copy slice
+  --> $DIR/borrowck-move-out-of-vec-tail.rs:20:18
+   |
+LL |                   &[Foo { string: a },
+   |                    ^              - hint: to prevent move, use `ref a` or `ref mut a`
+   |  __________________|
+   | |
+LL | |
+LL | |
+LL | |
+LL | |                   Foo { string: b }] => {
+   | |_________________________________-__^ cannot move out of here
+   |                                   |
+   |                                   ...and here (use `ref b` or `ref mut b`)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0508`.
diff --git a/src/test/ui/borrowck/borrowck-move-subcomponent.nll.stderr b/src/test/ui/borrowck/borrowck-move-subcomponent.nll.stderr
new file mode 100644
index 0000000..8c9083f
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-subcomponent.nll.stderr
@@ -0,0 +1,13 @@
+error[E0505]: cannot move out of `a.x` because it is borrowed
+  --> $DIR/borrowck-move-subcomponent.rs:15:14
+   |
+LL |   let pb = &a;
+   |            -- borrow of `a` occurs here
+LL |   let S { x: ax } = a;
+   |              ^^ move out of `a.x` occurs here
+LL |   f(pb);
+   |     -- borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0505`.
diff --git a/src/test/ui/borrowck/borrowck-move-subcomponent.rs b/src/test/ui/borrowck/borrowck-move-subcomponent.rs
new file mode 100644
index 0000000..4185632
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-subcomponent.rs
@@ -0,0 +1,17 @@
+// Tests that the borrow checker checks all components of a path when moving
+// out.
+
+#![feature(box_syntax)]
+
+struct S {
+  x : Box<isize>
+}
+
+fn f<T>(_: T) {}
+
+fn main() {
+  let a : S = S { x : box 1 };
+  let pb = &a;
+  let S { x: ax } = a;  //~ ERROR cannot move out
+  f(pb);
+}
diff --git a/src/test/ui/borrowck/borrowck-move-subcomponent.stderr b/src/test/ui/borrowck/borrowck-move-subcomponent.stderr
new file mode 100644
index 0000000..fd3deef
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-subcomponent.stderr
@@ -0,0 +1,11 @@
+error[E0505]: cannot move out of `a.x` because it is borrowed
+  --> $DIR/borrowck-move-subcomponent.rs:15:14
+   |
+LL |   let pb = &a;
+   |             - borrow of `a` occurs here
+LL |   let S { x: ax } = a;
+   |              ^^ move out of `a.x` occurs here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0505`.
diff --git a/src/test/ui/borrowck/borrowck-multiple-captures.nll.stderr b/src/test/ui/borrowck/borrowck-multiple-captures.nll.stderr
new file mode 100644
index 0000000..32c7067
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-multiple-captures.nll.stderr
@@ -0,0 +1,103 @@
+error[E0505]: cannot move out of `x1` because it is borrowed
+  --> $DIR/borrowck-multiple-captures.rs:12:19
+   |
+LL |     let p1 = &x1;
+   |              --- borrow of `x1` occurs here
+...
+LL |     thread::spawn(move|| {
+   |                   ^^^^^^ move out of `x1` occurs here
+LL |         drop(x1);
+   |              -- move occurs due to use in closure
+...
+LL |     borrow(&*p1);
+   |            ---- borrow later used here
+
+error[E0505]: cannot move out of `x2` because it is borrowed
+  --> $DIR/borrowck-multiple-captures.rs:12:19
+   |
+LL |     let p2 = &x2;
+   |              --- borrow of `x2` occurs here
+LL |     thread::spawn(move|| {
+   |                   ^^^^^^ move out of `x2` occurs here
+LL |         drop(x1);
+LL |         drop(x2);
+   |              -- move occurs due to use in closure
+...
+LL |     borrow(&*p2);
+   |            ---- borrow later used here
+
+error[E0382]: use of moved value: `x1`
+  --> $DIR/borrowck-multiple-captures.rs:25:19
+   |
+LL |     let x1: Box<_> = box 1;
+   |         -- move occurs because `x1` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
+LL |     drop(x1);
+   |          -- value moved here
+...
+LL |     thread::spawn(move|| {
+   |                   ^^^^^^ value used here after move
+LL |         drop(x1);
+   |              -- use occurs due to use in closure
+
+error[E0382]: use of moved value: `x2`
+  --> $DIR/borrowck-multiple-captures.rs:25:19
+   |
+LL |     let x2: Box<_> = box 2;
+   |         -- move occurs because `x2` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
+LL |     drop(x2);
+   |          -- value moved here
+LL |     thread::spawn(move|| {
+   |                   ^^^^^^ value used here after move
+LL |         drop(x1);
+LL |         drop(x2);
+   |              -- use occurs due to use in closure
+
+error[E0382]: use of moved value: `x`
+  --> $DIR/borrowck-multiple-captures.rs:36:14
+   |
+LL |         drop(x);
+   |              - value moved here
+LL |         drop(x);
+   |              ^ value used here after move
+   |
+   = note: move occurs because `x` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
+
+error[E0505]: cannot move out of `x` because it is borrowed
+  --> $DIR/borrowck-multiple-captures.rs:34:19
+   |
+LL |     let p = &x;
+   |             -- borrow of `x` occurs here
+LL |     thread::spawn(move|| {
+   |                   ^^^^^^ move out of `x` occurs here
+LL |         drop(x);
+   |              - move occurs due to use in closure
+...
+LL |     borrow(&*p);
+   |            --- borrow later used here
+
+error[E0382]: use of moved value: `x`
+  --> $DIR/borrowck-multiple-captures.rs:46:14
+   |
+LL |         drop(x);
+   |              - value moved here
+LL |         drop(x);
+   |              ^ value used here after move
+   |
+   = note: move occurs because `x` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `x`
+  --> $DIR/borrowck-multiple-captures.rs:44:19
+   |
+LL |     let x: Box<_> = box 1;
+   |         - move occurs because `x` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
+LL |     drop(x);
+   |          - value moved here
+LL |     thread::spawn(move|| {
+   |                   ^^^^^^ value used here after move
+LL |         drop(x);
+   |              - use occurs due to use in closure
+
+error: aborting due to 8 previous errors
+
+Some errors occurred: E0382, E0505.
+For more information about an error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/borrowck-multiple-captures.rs b/src/test/ui/borrowck/borrowck-multiple-captures.rs
new file mode 100644
index 0000000..ad75378
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-multiple-captures.rs
@@ -0,0 +1,55 @@
+#![feature(box_syntax)]
+
+use std::thread;
+
+fn borrow<T>(_: &T) { }
+
+fn different_vars_after_borrows() {
+    let x1: Box<_> = box 1;
+    let p1 = &x1;
+    let x2: Box<_> = box 2;
+    let p2 = &x2;
+    thread::spawn(move|| {
+        drop(x1); //~ ERROR cannot move `x1` into closure because it is borrowed
+        drop(x2); //~ ERROR cannot move `x2` into closure because it is borrowed
+    });
+    borrow(&*p1);
+    borrow(&*p2);
+}
+
+fn different_vars_after_moves() {
+    let x1: Box<_> = box 1;
+    drop(x1);
+    let x2: Box<_> = box 2;
+    drop(x2);
+    thread::spawn(move|| {
+        drop(x1); //~ ERROR capture of moved value: `x1`
+        drop(x2); //~ ERROR capture of moved value: `x2`
+    });
+}
+
+fn same_var_after_borrow() {
+    let x: Box<_> = box 1;
+    let p = &x;
+    thread::spawn(move|| {
+        drop(x); //~ ERROR cannot move `x` into closure because it is borrowed
+        drop(x); //~ ERROR use of moved value: `x`
+    });
+    borrow(&*p);
+}
+
+fn same_var_after_move() {
+    let x: Box<_> = box 1;
+    drop(x);
+    thread::spawn(move|| {
+        drop(x); //~ ERROR capture of moved value: `x`
+        drop(x); //~ ERROR use of moved value: `x`
+    });
+}
+
+fn main() {
+    different_vars_after_borrows();
+    different_vars_after_moves();
+    same_var_after_borrow();
+    same_var_after_move();
+}
diff --git a/src/test/ui/borrowck/borrowck-multiple-captures.stderr b/src/test/ui/borrowck/borrowck-multiple-captures.stderr
new file mode 100644
index 0000000..f25b19e
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-multiple-captures.stderr
@@ -0,0 +1,84 @@
+error[E0504]: cannot move `x1` into closure because it is borrowed
+  --> $DIR/borrowck-multiple-captures.rs:13:14
+   |
+LL |     let p1 = &x1;
+   |               -- borrow of `x1` occurs here
+...
+LL |         drop(x1);
+   |              ^^ move into closure occurs here
+
+error[E0504]: cannot move `x2` into closure because it is borrowed
+  --> $DIR/borrowck-multiple-captures.rs:14:14
+   |
+LL |     let p2 = &x2;
+   |               -- borrow of `x2` occurs here
+...
+LL |         drop(x2);
+   |              ^^ move into closure occurs here
+
+error[E0382]: capture of moved value: `x1`
+  --> $DIR/borrowck-multiple-captures.rs:26:14
+   |
+LL |     drop(x1);
+   |          -- value moved here
+...
+LL |         drop(x1);
+   |              ^^ value captured here after move
+   |
+   = note: move occurs because `x1` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
+
+error[E0382]: capture of moved value: `x2`
+  --> $DIR/borrowck-multiple-captures.rs:27:14
+   |
+LL |     drop(x2);
+   |          -- value moved here
+...
+LL |         drop(x2);
+   |              ^^ value captured here after move
+   |
+   = note: move occurs because `x2` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
+
+error[E0504]: cannot move `x` into closure because it is borrowed
+  --> $DIR/borrowck-multiple-captures.rs:35:14
+   |
+LL |     let p = &x;
+   |              - borrow of `x` occurs here
+LL |     thread::spawn(move|| {
+LL |         drop(x);
+   |              ^ move into closure occurs here
+
+error[E0382]: use of moved value: `x`
+  --> $DIR/borrowck-multiple-captures.rs:36:14
+   |
+LL |         drop(x);
+   |              - value moved here
+LL |         drop(x);
+   |              ^ value used here after move
+   |
+   = note: move occurs because `x` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
+
+error[E0382]: capture of moved value: `x`
+  --> $DIR/borrowck-multiple-captures.rs:45:14
+   |
+LL |     drop(x);
+   |          - value moved here
+LL |     thread::spawn(move|| {
+LL |         drop(x);
+   |              ^ value captured here after move
+   |
+   = note: move occurs because `x` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `x`
+  --> $DIR/borrowck-multiple-captures.rs:46:14
+   |
+LL |         drop(x);
+   |              - value moved here
+LL |         drop(x);
+   |              ^ value used here after move
+   |
+   = note: move occurs because `x` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
+
+error: aborting due to 8 previous errors
+
+Some errors occurred: E0382, E0504.
+For more information about an error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/borrowck-mut-addr-of-imm-var.nll.stderr b/src/test/ui/borrowck/borrowck-mut-addr-of-imm-var.nll.stderr
new file mode 100644
index 0000000..d58548f
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-mut-addr-of-imm-var.nll.stderr
@@ -0,0 +1,11 @@
+error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
+  --> $DIR/borrowck-mut-addr-of-imm-var.rs:3:25
+   |
+LL |     let x: isize = 3;
+   |         - help: consider changing this to be mutable: `mut x`
+LL |     let y: &mut isize = &mut x;
+   |                         ^^^^^^ cannot borrow as mutable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/borrowck/borrowck-mut-addr-of-imm-var.rs b/src/test/ui/borrowck/borrowck-mut-addr-of-imm-var.rs
new file mode 100644
index 0000000..a79a239
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-mut-addr-of-imm-var.rs
@@ -0,0 +1,6 @@
+fn main() {
+    let x: isize = 3;
+    let y: &mut isize = &mut x; //~ ERROR cannot borrow
+    *y = 5;
+    println!("{}", *y);
+}
diff --git a/src/test/ui/borrowck/borrowck-mut-addr-of-imm-var.stderr b/src/test/ui/borrowck/borrowck-mut-addr-of-imm-var.stderr
new file mode 100644
index 0000000..aa3b39c
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-mut-addr-of-imm-var.stderr
@@ -0,0 +1,11 @@
+error[E0596]: cannot borrow immutable local variable `x` as mutable
+  --> $DIR/borrowck-mut-addr-of-imm-var.rs:3:30
+   |
+LL |     let x: isize = 3;
+   |         - help: make this binding mutable: `mut x`
+LL |     let y: &mut isize = &mut x;
+   |                              ^ cannot borrow mutably
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.ast.nll.stderr b/src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.ast.nll.stderr
new file mode 100644
index 0000000..a6e7d74
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.ast.nll.stderr
@@ -0,0 +1,32 @@
+error[E0499]: cannot borrow `x` as mutable more than once at a time
+  --> $DIR/borrowck-mut-borrow-linear-errors.rs:13:30
+   |
+LL |             1 => { addr.push(&mut x); }
+   |                    ----      ^^^^^^ second mutable borrow occurs here
+   |                    |
+   |                    first borrow later used here
+...
+LL |             _ => { addr.push(&mut x); }
+   |                              ------ first mutable borrow occurs here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time
+  --> $DIR/borrowck-mut-borrow-linear-errors.rs:15:30
+   |
+LL |             1 => { addr.push(&mut x); }
+   |                    ---- first borrow later used here
+LL |
+LL |             2 => { addr.push(&mut x); }
+   |                              ^^^^^^ second mutable borrow occurs here
+LL |
+LL |             _ => { addr.push(&mut x); }
+   |                              ------ first mutable borrow occurs here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time
+  --> $DIR/borrowck-mut-borrow-linear-errors.rs:17:30
+   |
+LL |             _ => { addr.push(&mut x); }
+   |                              ^^^^^^ mutable borrow starts here in previous iteration of loop
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.ast.stderr b/src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.ast.stderr
new file mode 100644
index 0000000..cee61db
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.ast.stderr
@@ -0,0 +1,36 @@
+error[E0499]: cannot borrow `x` as mutable more than once at a time
+  --> $DIR/borrowck-mut-borrow-linear-errors.rs:13:35
+   |
+LL |             1 => { addr.push(&mut x); }
+   |                                   ^ mutable borrow starts here in previous iteration of loop
+...
+LL | }
+   | - mutable borrow ends here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time
+  --> $DIR/borrowck-mut-borrow-linear-errors.rs:15:35
+   |
+LL |             1 => { addr.push(&mut x); }
+   |                                   - first mutable borrow occurs here
+LL |
+LL |             2 => { addr.push(&mut x); }
+   |                                   ^ second mutable borrow occurs here
+...
+LL | }
+   | - first borrow ends here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time
+  --> $DIR/borrowck-mut-borrow-linear-errors.rs:17:35
+   |
+LL |             1 => { addr.push(&mut x); }
+   |                                   - first mutable borrow occurs here
+...
+LL |             _ => { addr.push(&mut x); }
+   |                                   ^ second mutable borrow occurs here
+...
+LL | }
+   | - first borrow ends here
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.mir.stderr b/src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.mir.stderr
new file mode 100644
index 0000000..a6e7d74
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.mir.stderr
@@ -0,0 +1,32 @@
+error[E0499]: cannot borrow `x` as mutable more than once at a time
+  --> $DIR/borrowck-mut-borrow-linear-errors.rs:13:30
+   |
+LL |             1 => { addr.push(&mut x); }
+   |                    ----      ^^^^^^ second mutable borrow occurs here
+   |                    |
+   |                    first borrow later used here
+...
+LL |             _ => { addr.push(&mut x); }
+   |                              ------ first mutable borrow occurs here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time
+  --> $DIR/borrowck-mut-borrow-linear-errors.rs:15:30
+   |
+LL |             1 => { addr.push(&mut x); }
+   |                    ---- first borrow later used here
+LL |
+LL |             2 => { addr.push(&mut x); }
+   |                              ^^^^^^ second mutable borrow occurs here
+LL |
+LL |             _ => { addr.push(&mut x); }
+   |                              ------ first mutable borrow occurs here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time
+  --> $DIR/borrowck-mut-borrow-linear-errors.rs:17:30
+   |
+LL |             _ => { addr.push(&mut x); }
+   |                              ^^^^^^ mutable borrow starts here in previous iteration of loop
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.rs b/src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.rs
new file mode 100644
index 0000000..bb0b26e
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.rs
@@ -0,0 +1,21 @@
+// Test to ensure we only report an error for the first issued loan that
+// conflicts with a new loan, as opposed to every issued loan.  This keeps us
+// down to O(n) errors (for n problem lines), instead of O(n^2) errors.
+
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+fn main() {
+    let mut x = 1;
+    let mut addr = vec![];
+    loop {
+        match 1 {
+            1 => { addr.push(&mut x); } //[ast]~ ERROR [E0499]
+            //[mir]~^ ERROR [E0499]
+            2 => { addr.push(&mut x); } //[ast]~ ERROR [E0499]
+            //[mir]~^ ERROR [E0499]
+            _ => { addr.push(&mut x); } //[ast]~ ERROR [E0499]
+            //[mir]~^ ERROR [E0499]
+        }
+    }
+}
diff --git a/src/test/ui/borrowck/borrowck-mut-borrow-of-mut-base-ptr.nll.stderr b/src/test/ui/borrowck/borrowck-mut-borrow-of-mut-base-ptr.nll.stderr
new file mode 100644
index 0000000..925930a
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-mut-borrow-of-mut-base-ptr.nll.stderr
@@ -0,0 +1,26 @@
+error[E0502]: cannot borrow `t0` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-mut-borrow-of-mut-base-ptr.rs:11:18
+   |
+LL |     let p: &isize = &*t0;     // Freezes `*t0`
+   |                     ---- immutable borrow occurs here
+LL |     let mut t2 = &mut t0;
+   |                  ^^^^^^^ mutable borrow occurs here
+LL |     **t2 += 1;              // Mutates `*t0`
+LL |     p.use_ref();
+   |     - immutable borrow later used here
+
+error[E0499]: cannot borrow `t0` as mutable more than once at a time
+  --> $DIR/borrowck-mut-borrow-of-mut-base-ptr.rs:19:18
+   |
+LL |     let p: &mut isize = &mut *t0; // Claims `*t0`
+   |                         -------- first mutable borrow occurs here
+LL |     let mut t2 = &mut t0;
+   |                  ^^^^^^^ second mutable borrow occurs here
+LL |     **t2 += 1;                  // Mutates `*t0` but not through `*p`
+LL |     p.use_mut();
+   |     - first borrow later used here
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0499, E0502.
+For more information about an error, try `rustc --explain E0499`.
diff --git a/src/test/ui/borrowck/borrowck-mut-borrow-of-mut-base-ptr.rs b/src/test/ui/borrowck/borrowck-mut-borrow-of-mut-base-ptr.rs
new file mode 100644
index 0000000..32caa46
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-mut-borrow-of-mut-base-ptr.rs
@@ -0,0 +1,28 @@
+// Test that attempt to mutably borrow `&mut` pointer while pointee is
+// borrowed yields an error.
+//
+// Example from src/librustc_borrowck/borrowck/README.md
+
+
+
+fn foo<'a>(mut t0: &'a mut isize,
+           mut t1: &'a mut isize) {
+    let p: &isize = &*t0;     // Freezes `*t0`
+    let mut t2 = &mut t0;   //~ ERROR cannot borrow `t0`
+    **t2 += 1;              // Mutates `*t0`
+    p.use_ref();
+}
+
+fn bar<'a>(mut t0: &'a mut isize,
+           mut t1: &'a mut isize) {
+    let p: &mut isize = &mut *t0; // Claims `*t0`
+    let mut t2 = &mut t0;       //~ ERROR cannot borrow `t0`
+    **t2 += 1;                  // Mutates `*t0` but not through `*p`
+    p.use_mut();
+}
+
+fn main() {
+}
+
+trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { }  }
+impl<T> Fake for T { }
diff --git a/src/test/ui/borrowck/borrowck-mut-borrow-of-mut-base-ptr.stderr b/src/test/ui/borrowck/borrowck-mut-borrow-of-mut-base-ptr.stderr
new file mode 100644
index 0000000..fb73dbd
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-mut-borrow-of-mut-base-ptr.stderr
@@ -0,0 +1,26 @@
+error[E0502]: cannot borrow `t0` as mutable because `*t0` is also borrowed as immutable
+  --> $DIR/borrowck-mut-borrow-of-mut-base-ptr.rs:11:23
+   |
+LL |     let p: &isize = &*t0;     // Freezes `*t0`
+   |                      --- immutable borrow occurs here
+LL |     let mut t2 = &mut t0;
+   |                       ^^ mutable borrow occurs here
+...
+LL | }
+   | - immutable borrow ends here
+
+error[E0499]: cannot borrow `t0` as mutable more than once at a time
+  --> $DIR/borrowck-mut-borrow-of-mut-base-ptr.rs:19:23
+   |
+LL |     let p: &mut isize = &mut *t0; // Claims `*t0`
+   |                              --- first mutable borrow occurs here
+LL |     let mut t2 = &mut t0;
+   |                       ^^ second mutable borrow occurs here
+...
+LL | }
+   | - first borrow ends here
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0499, E0502.
+For more information about an error, try `rustc --explain E0499`.
diff --git a/src/test/ui/borrowck/borrowck-mut-slice-of-imm-vec.nll.stderr b/src/test/ui/borrowck/borrowck-mut-slice-of-imm-vec.nll.stderr
new file mode 100644
index 0000000..8e7ffdc
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-mut-slice-of-imm-vec.nll.stderr
@@ -0,0 +1,11 @@
+error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable
+  --> $DIR/borrowck-mut-slice-of-imm-vec.rs:7:11
+   |
+LL |     let v = vec![1, 2, 3];
+   |         - help: consider changing this to be mutable: `mut v`
+LL |     write(&mut v);
+   |           ^^^^^^ cannot borrow as mutable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/borrowck/borrowck-mut-slice-of-imm-vec.rs b/src/test/ui/borrowck/borrowck-mut-slice-of-imm-vec.rs
new file mode 100644
index 0000000..8e23571
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-mut-slice-of-imm-vec.rs
@@ -0,0 +1,8 @@
+fn write(v: &mut [isize]) {
+    v[0] += 1;
+}
+
+fn main() {
+    let v = vec![1, 2, 3];
+    write(&mut v); //~ ERROR cannot borrow
+}
diff --git a/src/test/ui/borrowck/borrowck-mut-slice-of-imm-vec.stderr b/src/test/ui/borrowck/borrowck-mut-slice-of-imm-vec.stderr
new file mode 100644
index 0000000..4160919
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-mut-slice-of-imm-vec.stderr
@@ -0,0 +1,11 @@
+error[E0596]: cannot borrow immutable local variable `v` as mutable
+  --> $DIR/borrowck-mut-slice-of-imm-vec.rs:7:16
+   |
+LL |     let v = vec![1, 2, 3];
+   |         - help: make this binding mutable: `mut v`
+LL |     write(&mut v);
+   |                ^ cannot borrow mutably
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/borrowck/borrowck-mutate-in-guard.nll.stderr b/src/test/ui/borrowck/borrowck-mutate-in-guard.nll.stderr
new file mode 100644
index 0000000..c1b794f
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-mutate-in-guard.nll.stderr
@@ -0,0 +1,24 @@
+error[E0302]: cannot assign in a pattern guard
+  --> $DIR/borrowck-mutate-in-guard.rs:10:25
+   |
+LL |         Enum::A(_) if { x = Enum::B(false); false } => 1,
+   |                         ^^^^^^^^^^^^^^^^^^ assignment in pattern guard
+
+error[E0301]: cannot mutably borrow in a pattern guard
+  --> $DIR/borrowck-mutate-in-guard.rs:12:38
+   |
+LL |         Enum::A(_) if { let y = &mut x; *y = Enum::B(false); false } => 1,
+   |                                      ^ borrowed mutably in pattern guard
+   |
+   = help: add #![feature(bind_by_move_pattern_guards)] to the crate attributes to enable
+
+error[E0302]: cannot assign in a pattern guard
+  --> $DIR/borrowck-mutate-in-guard.rs:12:41
+   |
+LL |         Enum::A(_) if { let y = &mut x; *y = Enum::B(false); false } => 1,
+   |                                         ^^^^^^^^^^^^^^^^^^^ assignment in pattern guard
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0301, E0302.
+For more information about an error, try `rustc --explain E0301`.
diff --git a/src/test/ui/borrowck/borrowck-mutate-in-guard.rs b/src/test/ui/borrowck/borrowck-mutate-in-guard.rs
new file mode 100644
index 0000000..2bda3de
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-mutate-in-guard.rs
@@ -0,0 +1,22 @@
+enum Enum<'a> {
+    A(&'a isize),
+    B(bool),
+}
+
+fn foo() -> isize {
+    let mut n = 42;
+    let mut x = Enum::A(&mut n);
+    match x {
+        Enum::A(_) if { x = Enum::B(false); false } => 1,
+        //~^ ERROR cannot assign in a pattern guard
+        Enum::A(_) if { let y = &mut x; *y = Enum::B(false); false } => 1,
+        //~^ ERROR cannot mutably borrow in a pattern guard
+        //~^^ ERROR cannot assign in a pattern guard
+        Enum::A(p) => *p,
+        Enum::B(_) => 2,
+    }
+}
+
+fn main() {
+    foo();
+}
diff --git a/src/test/ui/borrowck/borrowck-mutate-in-guard.stderr b/src/test/ui/borrowck/borrowck-mutate-in-guard.stderr
new file mode 100644
index 0000000..9e40856
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-mutate-in-guard.stderr
@@ -0,0 +1,22 @@
+error[E0302]: cannot assign in a pattern guard
+  --> $DIR/borrowck-mutate-in-guard.rs:10:25
+   |
+LL |         Enum::A(_) if { x = Enum::B(false); false } => 1,
+   |                         ^^^^^^^^^^^^^^^^^^ assignment in pattern guard
+
+error[E0301]: cannot mutably borrow in a pattern guard
+  --> $DIR/borrowck-mutate-in-guard.rs:12:38
+   |
+LL |         Enum::A(_) if { let y = &mut x; *y = Enum::B(false); false } => 1,
+   |                                      ^ borrowed mutably in pattern guard
+
+error[E0302]: cannot assign in a pattern guard
+  --> $DIR/borrowck-mutate-in-guard.rs:12:41
+   |
+LL |         Enum::A(_) if { let y = &mut x; *y = Enum::B(false); false } => 1,
+   |                                         ^^^^^^^^^^^^^^^^^^^ assignment in pattern guard
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0301, E0302.
+For more information about an error, try `rustc --explain E0301`.
diff --git a/src/test/ui/borrowck/borrowck-no-cycle-in-exchange-heap.nll.stderr b/src/test/ui/borrowck/borrowck-no-cycle-in-exchange-heap.nll.stderr
new file mode 100644
index 0000000..3462b76
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-no-cycle-in-exchange-heap.nll.stderr
@@ -0,0 +1,13 @@
+error[E0505]: cannot move out of `x` because it is borrowed
+  --> $DIR/borrowck-no-cycle-in-exchange-heap.rs:16:15
+   |
+LL |       Cycle::Node(ref mut y) => {
+   |                   --------- borrow of `x.0` occurs here
+LL |         y.a = x;
+   |         ---   ^ move out of `x` occurs here
+   |         |
+   |         borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0505`.
diff --git a/src/test/ui/borrowck/borrowck-no-cycle-in-exchange-heap.rs b/src/test/ui/borrowck/borrowck-no-cycle-in-exchange-heap.rs
new file mode 100644
index 0000000..4c1ff98
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-no-cycle-in-exchange-heap.rs
@@ -0,0 +1,20 @@
+#![feature(box_syntax)]
+
+struct Node_ {
+    a: Box<Cycle>
+}
+
+enum Cycle {
+    Node(Node_),
+    Empty,
+}
+fn main() {
+    let mut x: Box<_> = box Cycle::Node(Node_ {a: box Cycle::Empty});
+    // Create a cycle!
+    match *x {
+      Cycle::Node(ref mut y) => {
+        y.a = x; //~ ERROR cannot move out of
+      }
+      Cycle::Empty => {}
+    };
+}
diff --git a/src/test/ui/borrowck/borrowck-no-cycle-in-exchange-heap.stderr b/src/test/ui/borrowck/borrowck-no-cycle-in-exchange-heap.stderr
new file mode 100644
index 0000000..5fc1694
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-no-cycle-in-exchange-heap.stderr
@@ -0,0 +1,11 @@
+error[E0505]: cannot move out of `x` because it is borrowed
+  --> $DIR/borrowck-no-cycle-in-exchange-heap.rs:16:15
+   |
+LL |       Cycle::Node(ref mut y) => {
+   |                   --------- borrow of `x.0` occurs here
+LL |         y.a = x;
+   |               ^ move out of `x` occurs here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0505`.
diff --git a/src/test/ui/borrowck/borrowck-object-lifetime.nll.stderr b/src/test/ui/borrowck/borrowck-object-lifetime.nll.stderr
new file mode 100644
index 0000000..cf94c74
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-object-lifetime.nll.stderr
@@ -0,0 +1,23 @@
+error[E0502]: cannot borrow `*x` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-object-lifetime.rs:20:13
+   |
+LL |     let y = x.borrowed();
+   |             - immutable borrow occurs here
+LL |     let z = x.mut_borrowed();
+   |             ^^^^^^^^^^^^^^^^ mutable borrow occurs here
+LL |     y.use_ref();
+   |     - immutable borrow later used here
+
+error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-object-lifetime.rs:26:13
+   |
+LL |     let y = x.borrowed();
+   |             - immutable borrow occurs here
+LL |     let z = &mut x;
+   |             ^^^^^^ mutable borrow occurs here
+LL |     y.use_ref();
+   |     - immutable borrow later used here
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/borrowck/borrowck-object-lifetime.rs b/src/test/ui/borrowck/borrowck-object-lifetime.rs
new file mode 100644
index 0000000..495516c
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-object-lifetime.rs
@@ -0,0 +1,40 @@
+// Test that borrows that occur due to calls to object methods
+// properly "claim" the object path.
+
+
+
+trait Foo {
+    fn borrowed(&self) -> &();
+    fn mut_borrowed(&mut self) -> &();
+}
+
+fn borrowed_receiver(x: &Foo) {
+    let y = x.borrowed();
+    let z = x.borrowed();
+    z.use_ref();
+    y.use_ref();
+}
+
+fn mut_borrowed_receiver(x: &mut Foo) {
+    let y = x.borrowed();
+    let z = x.mut_borrowed(); //~ ERROR cannot borrow
+    y.use_ref();
+}
+
+fn mut_owned_receiver(mut x: Box<Foo>) {
+    let y = x.borrowed();
+    let z = &mut x; //~ ERROR cannot borrow
+    y.use_ref();
+}
+
+fn imm_owned_receiver(mut x: Box<Foo>) {
+    let y = x.borrowed();
+    let z = &x;
+    z.use_ref();
+    y.use_ref();
+}
+
+fn main() {}
+
+trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { }  }
+impl<T> Fake for T { }
diff --git a/src/test/ui/borrowck/borrowck-object-lifetime.stderr b/src/test/ui/borrowck/borrowck-object-lifetime.stderr
new file mode 100644
index 0000000..8f6c8e0
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-object-lifetime.stderr
@@ -0,0 +1,25 @@
+error[E0502]: cannot borrow `*x` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-object-lifetime.rs:20:13
+   |
+LL |     let y = x.borrowed();
+   |             - immutable borrow occurs here
+LL |     let z = x.mut_borrowed();
+   |             ^ mutable borrow occurs here
+LL |     y.use_ref();
+LL | }
+   | - immutable borrow ends here
+
+error[E0502]: cannot borrow `x` as mutable because `*x` is also borrowed as immutable
+  --> $DIR/borrowck-object-lifetime.rs:26:18
+   |
+LL |     let y = x.borrowed();
+   |             - immutable borrow occurs here
+LL |     let z = &mut x;
+   |                  ^ mutable borrow occurs here
+LL |     y.use_ref();
+LL | }
+   | - immutable borrow ends here
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/borrowck/borrowck-or-init.nll.stderr b/src/test/ui/borrowck/borrowck-or-init.nll.stderr
new file mode 100644
index 0000000..122f519
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-or-init.nll.stderr
@@ -0,0 +1,9 @@
+error[E0381]: borrow of possibly uninitialized variable: `i`
+  --> $DIR/borrowck-or-init.rs:5:20
+   |
+LL |     println!("{}", i);
+   |                    ^ use of possibly uninitialized `i`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/borrowck-or-init.rs b/src/test/ui/borrowck/borrowck-or-init.rs
new file mode 100644
index 0000000..5b14878
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-or-init.rs
@@ -0,0 +1,6 @@
+fn main() {
+    let i: isize;
+
+    println!("{}", false || { i = 5; true });
+    println!("{}", i); //~ ERROR use of possibly uninitialized variable: `i`
+}
diff --git a/src/test/ui/borrowck/borrowck-or-init.stderr b/src/test/ui/borrowck/borrowck-or-init.stderr
new file mode 100644
index 0000000..a2b69b1
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-or-init.stderr
@@ -0,0 +1,9 @@
+error[E0381]: use of possibly uninitialized variable: `i`
+  --> $DIR/borrowck-or-init.rs:5:20
+   |
+LL |     println!("{}", i);
+   |                    ^ use of possibly uninitialized `i`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/borrowck-overloaded-call.nll.stderr b/src/test/ui/borrowck/borrowck-overloaded-call.nll.stderr
new file mode 100644
index 0000000..b7fcaa6
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-overloaded-call.nll.stderr
@@ -0,0 +1,34 @@
+error[E0502]: cannot borrow `s` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-overloaded-call.rs:59:5
+   |
+LL |     let sp = &mut s;
+   |              ------ mutable borrow occurs here
+LL |     s(3);
+   |     ^ immutable borrow occurs here
+LL |     use_mut(sp);
+   |             -- mutable borrow later used here
+
+error[E0596]: cannot borrow `s` as mutable, as it is not declared as mutable
+  --> $DIR/borrowck-overloaded-call.rs:67:5
+   |
+LL |     let s = SFnMut {
+   |         - help: consider changing this to be mutable: `mut s`
+...
+LL |     s(3);
+   |     ^ cannot borrow as mutable
+
+error[E0382]: use of moved value: `s`
+  --> $DIR/borrowck-overloaded-call.rs:75:5
+   |
+LL |     let s = SFnOnce {
+   |         - move occurs because `s` has type `SFnOnce`, which does not implement the `Copy` trait
+...
+LL |     s(" world".to_string());
+   |     - value moved here
+LL |     s(" world".to_string());
+   |     ^ value used here after move
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0382, E0502, E0596.
+For more information about an error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/borrowck-overloaded-call.rs b/src/test/ui/borrowck/borrowck-overloaded-call.rs
new file mode 100644
index 0000000..8601449
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-overloaded-call.rs
@@ -0,0 +1,80 @@
+#![feature(fn_traits, unboxed_closures)]
+
+use std::ops::{Fn, FnMut, FnOnce};
+
+struct SFn {
+    x: isize,
+    y: isize,
+}
+
+impl Fn<(isize,)> for SFn {
+    extern "rust-call" fn call(&self, (z,): (isize,)) -> isize {
+        self.x * self.y * z
+    }
+}
+
+impl FnMut<(isize,)> for SFn {
+    extern "rust-call" fn call_mut(&mut self, args: (isize,)) -> isize { self.call(args) }
+}
+
+impl FnOnce<(isize,)> for SFn {
+    type Output = isize;
+    extern "rust-call" fn call_once(self, args: (isize,)) -> isize { self.call(args) }
+}
+
+struct SFnMut {
+    x: isize,
+    y: isize,
+}
+
+impl FnMut<(isize,)> for SFnMut {
+    extern "rust-call" fn call_mut(&mut self, (z,): (isize,)) -> isize {
+        self.x * self.y * z
+    }
+}
+
+impl FnOnce<(isize,)> for SFnMut {
+    type Output = isize;
+    extern "rust-call" fn call_once(mut self, args: (isize,)) -> isize { self.call_mut(args) }
+}
+
+struct SFnOnce {
+    x: String,
+}
+
+impl FnOnce<(String,)> for SFnOnce {
+    type Output = usize;
+
+    extern "rust-call" fn call_once(self, (z,): (String,)) -> usize {
+        self.x.len() + z.len()
+    }
+}
+
+fn f() {
+    let mut s = SFn {
+        x: 1,
+        y: 2,
+    };
+    let sp = &mut s;
+    s(3);   //~ ERROR cannot borrow `s` as immutable because it is also borrowed as mutable
+    use_mut(sp);
+}
+fn g() {
+    let s = SFnMut {
+        x: 1,
+        y: 2,
+    };
+    s(3);   //~ ERROR cannot borrow immutable local variable `s` as mutable
+}
+
+fn h() {
+    let s = SFnOnce {
+        x: "hello".to_string(),
+    };
+    s(" world".to_string());
+    s(" world".to_string());    //~ ERROR use of moved value: `s`
+}
+
+fn main() {}
+
+fn use_mut<T>(_: &mut T) { }
diff --git a/src/test/ui/borrowck/borrowck-overloaded-call.stderr b/src/test/ui/borrowck/borrowck-overloaded-call.stderr
new file mode 100644
index 0000000..97223a2
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-overloaded-call.stderr
@@ -0,0 +1,34 @@
+error[E0502]: cannot borrow `s` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-overloaded-call.rs:59:5
+   |
+LL |     let sp = &mut s;
+   |                   - mutable borrow occurs here
+LL |     s(3);
+   |     ^ immutable borrow occurs here
+LL |     use_mut(sp);
+LL | }
+   | - mutable borrow ends here
+
+error[E0596]: cannot borrow immutable local variable `s` as mutable
+  --> $DIR/borrowck-overloaded-call.rs:67:5
+   |
+LL |     let s = SFnMut {
+   |         - help: make this binding mutable: `mut s`
+...
+LL |     s(3);
+   |     ^ cannot borrow mutably
+
+error[E0382]: use of moved value: `s`
+  --> $DIR/borrowck-overloaded-call.rs:75:5
+   |
+LL |     s(" world".to_string());
+   |     - value moved here
+LL |     s(" world".to_string());
+   |     ^ value used here after move
+   |
+   = note: move occurs because `s` has type `SFnOnce`, which does not implement the `Copy` trait
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0382, E0502, E0596.
+For more information about an error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/borrowck-overloaded-index-and-overloaded-deref.ast.nll.stderr b/src/test/ui/borrowck/borrowck-overloaded-index-and-overloaded-deref.ast.nll.stderr
new file mode 100644
index 0000000..f33fb55
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-overloaded-index-and-overloaded-deref.ast.nll.stderr
@@ -0,0 +1,14 @@
+error[E0506]: cannot assign to `v` because it is borrowed
+  --> $DIR/borrowck-overloaded-index-and-overloaded-deref.rs:34:5
+   |
+LL |     let i = &v[0].f;
+   |              - borrow of `v` occurs here
+LL |     v = MyVec { x: MyPtr { x: Foo { f: 23 } } };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `v` occurs here
+...
+LL |     read(*i);
+   |          -- borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/borrowck/borrowck-overloaded-index-and-overloaded-deref.ast.stderr b/src/test/ui/borrowck/borrowck-overloaded-index-and-overloaded-deref.ast.stderr
new file mode 100644
index 0000000..59841ee
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-overloaded-index-and-overloaded-deref.ast.stderr
@@ -0,0 +1,11 @@
+error[E0506]: cannot assign to `v` because it is borrowed
+  --> $DIR/borrowck-overloaded-index-and-overloaded-deref.rs:34:5
+   |
+LL |     let i = &v[0].f;
+   |              - borrow of `v` occurs here
+LL |     v = MyVec { x: MyPtr { x: Foo { f: 23 } } };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `v` occurs here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/borrowck/borrowck-overloaded-index-and-overloaded-deref.mir.stderr b/src/test/ui/borrowck/borrowck-overloaded-index-and-overloaded-deref.mir.stderr
new file mode 100644
index 0000000..f33fb55
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-overloaded-index-and-overloaded-deref.mir.stderr
@@ -0,0 +1,14 @@
+error[E0506]: cannot assign to `v` because it is borrowed
+  --> $DIR/borrowck-overloaded-index-and-overloaded-deref.rs:34:5
+   |
+LL |     let i = &v[0].f;
+   |              - borrow of `v` occurs here
+LL |     v = MyVec { x: MyPtr { x: Foo { f: 23 } } };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `v` occurs here
+...
+LL |     read(*i);
+   |          -- borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/borrowck/borrowck-overloaded-index-and-overloaded-deref.rs b/src/test/ui/borrowck/borrowck-overloaded-index-and-overloaded-deref.rs
new file mode 100644
index 0000000..348d99f
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-overloaded-index-and-overloaded-deref.rs
@@ -0,0 +1,40 @@
+// Check that we properly record borrows when we are doing an
+// overloaded, autoderef of a value obtained via an overloaded index
+// operator. The accounting of the all the implicit things going on
+// here is rather subtle. Issue #20232.
+
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+use std::ops::{Deref, Index};
+
+struct MyVec<T> { x: T }
+
+impl<T> Index<usize> for MyVec<T> {
+    type Output = T;
+    fn index(&self, _: usize) -> &T {
+        &self.x
+    }
+}
+
+struct MyPtr<T> { x: T }
+
+impl<T> Deref for MyPtr<T> {
+    type Target = T;
+    fn deref(&self) -> &T {
+        &self.x
+    }
+}
+
+struct Foo { f: usize }
+
+fn main() {
+    let mut v = MyVec { x: MyPtr { x: Foo { f: 22 } } };
+    let i = &v[0].f;
+    v = MyVec { x: MyPtr { x: Foo { f: 23 } } };
+    //[ast]~^ ERROR cannot assign to `v`
+    //[mir]~^^ ERROR cannot assign to `v` because it is borrowed
+    read(*i);
+}
+
+fn read(_: usize) { }
diff --git a/src/test/ui/borrowck/borrowck-overloaded-index-autoderef.nll.stderr b/src/test/ui/borrowck/borrowck-overloaded-index-autoderef.nll.stderr
new file mode 100644
index 0000000..5f34749
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-overloaded-index-autoderef.nll.stderr
@@ -0,0 +1,84 @@
+error[E0502]: cannot borrow `*f` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-overloaded-index-autoderef.rs:37:14
+   |
+LL |     let p = &mut f[&s];
+   |                  - mutable borrow occurs here
+LL |     let q = &f[&s];
+   |              ^ immutable borrow occurs here
+LL |     p.use_mut();
+   |     - mutable borrow later used here
+
+error[E0499]: cannot borrow `*f` as mutable more than once at a time
+  --> $DIR/borrowck-overloaded-index-autoderef.rs:43:18
+   |
+LL |     let p = &mut f[&s];
+   |                  - first mutable borrow occurs here
+LL |     let q = &mut f[&s];
+   |                  ^ second mutable borrow occurs here
+LL |     p.use_mut();
+   |     - first borrow later used here
+
+error[E0499]: cannot borrow `f.foo` as mutable more than once at a time
+  --> $DIR/borrowck-overloaded-index-autoderef.rs:53:18
+   |
+LL |     let p = &mut f.foo[&s];
+   |                  ----- first mutable borrow occurs here
+LL |     let q = &mut f.foo[&s];
+   |                  ^^^^^ second mutable borrow occurs here
+LL |     p.use_mut();
+   |     - first borrow later used here
+
+error[E0502]: cannot borrow `f.foo` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-overloaded-index-autoderef.rs:65:18
+   |
+LL |     let p = &f.foo[&s];
+   |              ----- immutable borrow occurs here
+LL |     let q = &mut f.foo[&s];
+   |                  ^^^^^ mutable borrow occurs here
+LL |     p.use_ref();
+   |     - immutable borrow later used here
+
+error[E0506]: cannot assign to `f.foo` because it is borrowed
+  --> $DIR/borrowck-overloaded-index-autoderef.rs:71:5
+   |
+LL |     let p = &f.foo[&s];
+   |              ----- borrow of `f.foo` occurs here
+LL |     f.foo = g;
+   |     ^^^^^^^^^ assignment to borrowed `f.foo` occurs here
+LL |     p.use_ref();
+   |     - borrow later used here
+
+error[E0506]: cannot assign to `*f` because it is borrowed
+  --> $DIR/borrowck-overloaded-index-autoderef.rs:77:5
+   |
+LL |     let p = &f.foo[&s];
+   |              ----- borrow of `*f` occurs here
+LL |     *f = g;
+   |     ^^^^^^ assignment to borrowed `*f` occurs here
+LL |     p.use_ref();
+   |     - borrow later used here
+
+error[E0506]: cannot assign to `f.foo` because it is borrowed
+  --> $DIR/borrowck-overloaded-index-autoderef.rs:83:5
+   |
+LL |     let p = &mut f.foo[&s];
+   |                  ----- borrow of `f.foo` occurs here
+LL |     f.foo = g;
+   |     ^^^^^^^^^ assignment to borrowed `f.foo` occurs here
+LL |     p.use_mut();
+   |     - borrow later used here
+
+error[E0506]: cannot assign to `*f` because it is borrowed
+  --> $DIR/borrowck-overloaded-index-autoderef.rs:89:5
+   |
+LL |     let p = &mut f.foo[&s];
+   |                  ----- borrow of `*f` occurs here
+LL |     *f = g;
+   |     ^^^^^^ assignment to borrowed `*f` occurs here
+LL |     p.use_mut();
+   |     - borrow later used here
+
+error: aborting due to 8 previous errors
+
+Some errors occurred: E0499, E0502, E0506.
+For more information about an error, try `rustc --explain E0499`.
diff --git a/src/test/ui/borrowck/borrowck-overloaded-index-autoderef.rs b/src/test/ui/borrowck/borrowck-overloaded-index-autoderef.rs
new file mode 100644
index 0000000..3d3a3af
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-overloaded-index-autoderef.rs
@@ -0,0 +1,97 @@
+// Test that we still see borrowck errors of various kinds when using
+// indexing and autoderef in combination.
+
+use std::ops::{Index, IndexMut};
+
+
+
+struct Foo {
+    x: isize,
+    y: isize,
+}
+
+impl<'a> Index<&'a String> for Foo {
+    type Output = isize;
+
+    fn index(&self, z: &String) -> &isize {
+        if *z == "x" {
+            &self.x
+        } else {
+            &self.y
+        }
+    }
+}
+
+impl<'a> IndexMut<&'a String> for Foo {
+    fn index_mut(&mut self, z: &String) -> &mut isize {
+        if *z == "x" {
+            &mut self.x
+        } else {
+            &mut self.y
+        }
+    }
+}
+
+fn test1(mut f: Box<Foo>, s: String) {
+    let p = &mut f[&s];
+    let q = &f[&s]; //~ ERROR cannot borrow
+    p.use_mut();
+}
+
+fn test2(mut f: Box<Foo>, s: String) {
+    let p = &mut f[&s];
+    let q = &mut f[&s]; //~ ERROR cannot borrow
+    p.use_mut();
+}
+
+struct Bar {
+    foo: Foo
+}
+
+fn test3(mut f: Box<Bar>, s: String) {
+    let p = &mut f.foo[&s];
+    let q = &mut f.foo[&s]; //~ ERROR cannot borrow
+    p.use_mut();
+}
+
+fn test4(mut f: Box<Bar>, s: String) {
+    let p = &f.foo[&s];
+    let q = &f.foo[&s];
+    p.use_ref();
+}
+
+fn test5(mut f: Box<Bar>, s: String) {
+    let p = &f.foo[&s];
+    let q = &mut f.foo[&s]; //~ ERROR cannot borrow
+    p.use_ref();
+}
+
+fn test6(mut f: Box<Bar>, g: Foo, s: String) {
+    let p = &f.foo[&s];
+    f.foo = g; //~ ERROR cannot assign
+    p.use_ref();
+}
+
+fn test7(mut f: Box<Bar>, g: Bar, s: String) {
+    let p = &f.foo[&s];
+    *f = g; //~ ERROR cannot assign
+    p.use_ref();
+}
+
+fn test8(mut f: Box<Bar>, g: Foo, s: String) {
+    let p = &mut f.foo[&s];
+    f.foo = g; //~ ERROR cannot assign
+    p.use_mut();
+}
+
+fn test9(mut f: Box<Bar>, g: Bar, s: String) {
+    let p = &mut f.foo[&s];
+    *f = g; //~ ERROR cannot assign
+    p.use_mut();
+}
+
+fn main() {
+}
+
+trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { }  }
+impl<T> Fake for T { }
diff --git a/src/test/ui/borrowck/borrowck-overloaded-index-autoderef.stderr b/src/test/ui/borrowck/borrowck-overloaded-index-autoderef.stderr
new file mode 100644
index 0000000..73cab88
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-overloaded-index-autoderef.stderr
@@ -0,0 +1,80 @@
+error[E0502]: cannot borrow `*f` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-overloaded-index-autoderef.rs:37:14
+   |
+LL |     let p = &mut f[&s];
+   |                  - mutable borrow occurs here
+LL |     let q = &f[&s];
+   |              ^ immutable borrow occurs here
+LL |     p.use_mut();
+LL | }
+   | - mutable borrow ends here
+
+error[E0499]: cannot borrow `*f` as mutable more than once at a time
+  --> $DIR/borrowck-overloaded-index-autoderef.rs:43:18
+   |
+LL |     let p = &mut f[&s];
+   |                  - first mutable borrow occurs here
+LL |     let q = &mut f[&s];
+   |                  ^ second mutable borrow occurs here
+LL |     p.use_mut();
+LL | }
+   | - first borrow ends here
+
+error[E0499]: cannot borrow `f.foo` as mutable more than once at a time
+  --> $DIR/borrowck-overloaded-index-autoderef.rs:53:18
+   |
+LL |     let p = &mut f.foo[&s];
+   |                  ----- first mutable borrow occurs here
+LL |     let q = &mut f.foo[&s];
+   |                  ^^^^^ second mutable borrow occurs here
+LL |     p.use_mut();
+LL | }
+   | - first borrow ends here
+
+error[E0502]: cannot borrow `f.foo` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-overloaded-index-autoderef.rs:65:18
+   |
+LL |     let p = &f.foo[&s];
+   |              ----- immutable borrow occurs here
+LL |     let q = &mut f.foo[&s];
+   |                  ^^^^^ mutable borrow occurs here
+LL |     p.use_ref();
+LL | }
+   | - immutable borrow ends here
+
+error[E0506]: cannot assign to `f.foo` because it is borrowed
+  --> $DIR/borrowck-overloaded-index-autoderef.rs:71:5
+   |
+LL |     let p = &f.foo[&s];
+   |              ----- borrow of `f.foo` occurs here
+LL |     f.foo = g;
+   |     ^^^^^^^^^ assignment to borrowed `f.foo` occurs here
+
+error[E0506]: cannot assign to `*f` because it is borrowed
+  --> $DIR/borrowck-overloaded-index-autoderef.rs:77:5
+   |
+LL |     let p = &f.foo[&s];
+   |              ----- borrow of `*f` occurs here
+LL |     *f = g;
+   |     ^^^^^^ assignment to borrowed `*f` occurs here
+
+error[E0506]: cannot assign to `f.foo` because it is borrowed
+  --> $DIR/borrowck-overloaded-index-autoderef.rs:83:5
+   |
+LL |     let p = &mut f.foo[&s];
+   |                  ----- borrow of `f.foo` occurs here
+LL |     f.foo = g;
+   |     ^^^^^^^^^ assignment to borrowed `f.foo` occurs here
+
+error[E0506]: cannot assign to `*f` because it is borrowed
+  --> $DIR/borrowck-overloaded-index-autoderef.rs:89:5
+   |
+LL |     let p = &mut f.foo[&s];
+   |                  ----- borrow of `*f` occurs here
+LL |     *f = g;
+   |     ^^^^^^ assignment to borrowed `*f` occurs here
+
+error: aborting due to 8 previous errors
+
+Some errors occurred: E0499, E0502, E0506.
+For more information about an error, try `rustc --explain E0499`.
diff --git a/src/test/ui/borrowck/borrowck-overloaded-index-move-from-vec.nll.stderr b/src/test/ui/borrowck/borrowck-overloaded-index-move-from-vec.nll.stderr
new file mode 100644
index 0000000..dbd805f
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-overloaded-index-move-from-vec.nll.stderr
@@ -0,0 +1,12 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/borrowck-overloaded-index-move-from-vec.rs:20:15
+   |
+LL |     let bad = v[0];
+   |               ^^^^
+   |               |
+   |               cannot move out of borrowed content
+   |               help: consider borrowing here: `&v[0]`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/borrowck/borrowck-overloaded-index-move-from-vec.rs b/src/test/ui/borrowck/borrowck-overloaded-index-move-from-vec.rs
new file mode 100644
index 0000000..76dd97e
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-overloaded-index-move-from-vec.rs
@@ -0,0 +1,22 @@
+#![feature(box_syntax)]
+
+use std::ops::Index;
+
+struct MyVec<T> {
+    data: Vec<T>,
+}
+
+impl<T> Index<usize> for MyVec<T> {
+    type Output = T;
+
+    fn index(&self, i: usize) -> &T {
+        &self.data[i]
+    }
+}
+
+fn main() {
+    let v = MyVec::<Box<_>> { data: vec![box 1, box 2, box 3] };
+    let good = &v[0]; // Shouldn't fail here
+    let bad = v[0];
+    //~^ ERROR cannot move out of indexed content
+}
diff --git a/src/test/ui/borrowck/borrowck-overloaded-index-move-from-vec.stderr b/src/test/ui/borrowck/borrowck-overloaded-index-move-from-vec.stderr
new file mode 100644
index 0000000..fe655dc
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-overloaded-index-move-from-vec.stderr
@@ -0,0 +1,12 @@
+error[E0507]: cannot move out of indexed content
+  --> $DIR/borrowck-overloaded-index-move-from-vec.rs:20:15
+   |
+LL |     let bad = v[0];
+   |               ^^^^
+   |               |
+   |               cannot move out of indexed content
+   |               help: consider using a reference instead: `&v[0]`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/borrowck/borrowck-overloaded-index-move-index.nll.stderr b/src/test/ui/borrowck/borrowck-overloaded-index-move-index.nll.stderr
new file mode 100644
index 0000000..de60067
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-overloaded-index-move-index.nll.stderr
@@ -0,0 +1,40 @@
+error[E0505]: cannot move out of `s` because it is borrowed
+  --> $DIR/borrowck-overloaded-index-move-index.rs:50:22
+   |
+LL |     let rs = &mut s;
+   |              ------ borrow of `s` occurs here
+LL | 
+LL |     println!("{}", f[s]);
+   |                      ^ move out of `s` occurs here
+...
+LL |     use_mut(rs);
+   |             -- borrow later used here
+
+error[E0505]: cannot move out of `s` because it is borrowed
+  --> $DIR/borrowck-overloaded-index-move-index.rs:53:7
+   |
+LL |     let rs = &mut s;
+   |              ------ borrow of `s` occurs here
+...
+LL |     f[s] = 10;
+   |       ^ move out of `s` occurs here
+...
+LL |     use_mut(rs);
+   |             -- borrow later used here
+
+error[E0382]: use of moved value: `s`
+  --> $DIR/borrowck-overloaded-index-move-index.rs:53:7
+   |
+LL |     let mut s = "hello".to_string();
+   |         ----- move occurs because `s` has type `std::string::String`, which does not implement the `Copy` trait
+...
+LL |     println!("{}", f[s]);
+   |                      - value moved here
+...
+LL |     f[s] = 10;
+   |       ^ value used here after move
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0382, E0505.
+For more information about an error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/borrowck-overloaded-index-move-index.rs b/src/test/ui/borrowck/borrowck-overloaded-index-move-index.rs
new file mode 100644
index 0000000..00f4483
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-overloaded-index-move-index.rs
@@ -0,0 +1,68 @@
+use std::ops::{Index, IndexMut};
+
+struct Foo {
+    x: isize,
+    y: isize,
+}
+
+impl Index<String> for Foo {
+    type Output = isize;
+
+    fn index(&self, z: String) -> &isize {
+        if z == "x" {
+            &self.x
+        } else {
+            &self.y
+        }
+    }
+}
+
+impl IndexMut<String> for Foo {
+    fn index_mut(&mut self, z: String) -> &mut isize {
+        if z == "x" {
+            &mut self.x
+        } else {
+            &mut self.y
+        }
+    }
+}
+
+struct Bar {
+    x: isize,
+}
+
+impl Index<isize> for Bar {
+    type Output = isize;
+
+    fn index<'a>(&'a self, z: isize) -> &'a isize {
+        &self.x
+    }
+}
+
+fn main() {
+    let mut f = Foo {
+        x: 1,
+        y: 2,
+    };
+    let mut s = "hello".to_string();
+    let rs = &mut s;
+
+    println!("{}", f[s]);
+    //~^ ERROR cannot move out of `s` because it is borrowed
+
+    f[s] = 10;
+    //~^ ERROR cannot move out of `s` because it is borrowed
+    //~| ERROR use of moved value: `s`
+
+    let s = Bar {
+        x: 1,
+    };
+    let i = 2;
+    let _j = &i;
+    println!("{}", s[i]); // no error, i is copy
+    println!("{}", s[i]);
+
+    use_mut(rs);
+}
+
+fn use_mut<T>(_: &mut T) { }
diff --git a/src/test/ui/borrowck/borrowck-overloaded-index-move-index.stderr b/src/test/ui/borrowck/borrowck-overloaded-index-move-index.stderr
new file mode 100644
index 0000000..7ea311f
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-overloaded-index-move-index.stderr
@@ -0,0 +1,33 @@
+error[E0505]: cannot move out of `s` because it is borrowed
+  --> $DIR/borrowck-overloaded-index-move-index.rs:50:22
+   |
+LL |     let rs = &mut s;
+   |                   - borrow of `s` occurs here
+LL | 
+LL |     println!("{}", f[s]);
+   |                      ^ move out of `s` occurs here
+
+error[E0505]: cannot move out of `s` because it is borrowed
+  --> $DIR/borrowck-overloaded-index-move-index.rs:53:7
+   |
+LL |     let rs = &mut s;
+   |                   - borrow of `s` occurs here
+...
+LL |     f[s] = 10;
+   |       ^ move out of `s` occurs here
+
+error[E0382]: use of moved value: `s`
+  --> $DIR/borrowck-overloaded-index-move-index.rs:53:7
+   |
+LL |     println!("{}", f[s]);
+   |                      - value moved here
+...
+LL |     f[s] = 10;
+   |       ^ value used here after move
+   |
+   = note: move occurs because `s` has type `std::string::String`, which does not implement the `Copy` trait
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0382, E0505.
+For more information about an error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/borrowck-overloaded-index-ref-index.ast.nll.stderr b/src/test/ui/borrowck/borrowck-overloaded-index-ref-index.ast.nll.stderr
new file mode 100644
index 0000000..2010e8f
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-overloaded-index-ref-index.ast.nll.stderr
@@ -0,0 +1,33 @@
+error[E0502]: cannot borrow `s` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-overloaded-index-ref-index.rs:52:22
+   |
+LL |     let rs = &mut s;
+   |              ------ mutable borrow occurs here
+LL |     println!("{}", f[&s]);
+   |                      ^^ immutable borrow occurs here
+...
+LL |     drop(rs);
+   |          -- mutable borrow later used here
+
+error[E0502]: cannot borrow `s` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-overloaded-index-ref-index.rs:55:7
+   |
+LL |     let rs = &mut s;
+   |              ------ mutable borrow occurs here
+...
+LL |     f[&s] = 10;
+   |       ^^ immutable borrow occurs here
+...
+LL |     drop(rs);
+   |          -- mutable borrow later used here
+
+error[E0594]: cannot assign to data in a `&` reference
+  --> $DIR/borrowck-overloaded-index-ref-index.rs:61:5
+   |
+LL |     s[2] = 20;
+   |     ^^^^^^^^^ cannot assign
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0502, E0594.
+For more information about an error, try `rustc --explain E0502`.
diff --git a/src/test/ui/borrowck/borrowck-overloaded-index-ref-index.ast.stderr b/src/test/ui/borrowck/borrowck-overloaded-index-ref-index.ast.stderr
new file mode 100644
index 0000000..f97f046
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-overloaded-index-ref-index.ast.stderr
@@ -0,0 +1,35 @@
+error[E0594]: cannot assign to immutable indexed content
+  --> $DIR/borrowck-overloaded-index-ref-index.rs:61:5
+   |
+LL |     s[2] = 20;
+   |     ^^^^^^^^^ cannot borrow as mutable
+   |
+   = help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `Bar`
+
+error[E0502]: cannot borrow `s` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-overloaded-index-ref-index.rs:52:23
+   |
+LL |     let rs = &mut s;
+   |                   - mutable borrow occurs here
+LL |     println!("{}", f[&s]);
+   |                       ^ immutable borrow occurs here
+...
+LL | }
+   | - mutable borrow ends here
+
+error[E0502]: cannot borrow `s` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-overloaded-index-ref-index.rs:55:8
+   |
+LL |     let rs = &mut s;
+   |                   - mutable borrow occurs here
+...
+LL |     f[&s] = 10;
+   |        ^ immutable borrow occurs here
+...
+LL | }
+   | - mutable borrow ends here
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0502, E0594.
+For more information about an error, try `rustc --explain E0502`.
diff --git a/src/test/ui/borrowck/borrowck-overloaded-index-ref-index.mir.stderr b/src/test/ui/borrowck/borrowck-overloaded-index-ref-index.mir.stderr
new file mode 100644
index 0000000..2010e8f
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-overloaded-index-ref-index.mir.stderr
@@ -0,0 +1,33 @@
+error[E0502]: cannot borrow `s` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-overloaded-index-ref-index.rs:52:22
+   |
+LL |     let rs = &mut s;
+   |              ------ mutable borrow occurs here
+LL |     println!("{}", f[&s]);
+   |                      ^^ immutable borrow occurs here
+...
+LL |     drop(rs);
+   |          -- mutable borrow later used here
+
+error[E0502]: cannot borrow `s` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-overloaded-index-ref-index.rs:55:7
+   |
+LL |     let rs = &mut s;
+   |              ------ mutable borrow occurs here
+...
+LL |     f[&s] = 10;
+   |       ^^ immutable borrow occurs here
+...
+LL |     drop(rs);
+   |          -- mutable borrow later used here
+
+error[E0594]: cannot assign to data in a `&` reference
+  --> $DIR/borrowck-overloaded-index-ref-index.rs:61:5
+   |
+LL |     s[2] = 20;
+   |     ^^^^^^^^^ cannot assign
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0502, E0594.
+For more information about an error, try `rustc --explain E0502`.
diff --git a/src/test/ui/borrowck/borrowck-overloaded-index-ref-index.rs b/src/test/ui/borrowck/borrowck-overloaded-index-ref-index.rs
new file mode 100644
index 0000000..53cab52
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-overloaded-index-ref-index.rs
@@ -0,0 +1,65 @@
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+use std::ops::{Index, IndexMut};
+
+struct Foo {
+    x: isize,
+    y: isize,
+}
+
+impl<'a> Index<&'a String> for Foo {
+    type Output = isize;
+
+    fn index(&self, z: &String) -> &isize {
+        if *z == "x" {
+            &self.x
+        } else {
+            &self.y
+        }
+    }
+}
+
+impl<'a> IndexMut<&'a String> for Foo {
+    fn index_mut(&mut self, z: &String) -> &mut isize {
+        if *z == "x" {
+            &mut self.x
+        } else {
+            &mut self.y
+        }
+    }
+}
+
+struct Bar {
+    x: isize,
+}
+
+impl Index<isize> for Bar {
+    type Output = isize;
+
+    fn index<'a>(&'a self, z: isize) -> &'a isize {
+        &self.x
+    }
+}
+
+fn main() {
+    let mut f = Foo {
+        x: 1,
+        y: 2,
+    };
+    let mut s = "hello".to_string();
+    let rs = &mut s;
+    println!("{}", f[&s]);
+    //[ast]~^ ERROR cannot borrow `s` as immutable because it is also borrowed as mutable
+    //[mir]~^^ ERROR cannot borrow `s` as immutable because it is also borrowed as mutable
+    f[&s] = 10;
+    //[ast]~^ ERROR cannot borrow `s` as immutable because it is also borrowed as mutable
+    //[mir]~^^ ERROR cannot borrow `s` as immutable because it is also borrowed as mutable
+    let s = Bar {
+        x: 1,
+    };
+    s[2] = 20;
+    //[ast]~^ ERROR cannot assign to immutable indexed content
+    //[mir]~^^ ERROR cannot assign to data in a `&` reference
+    drop(rs);
+}
diff --git a/src/test/ui/borrowck/borrowck-partial-reinit-1.nll.stderr b/src/test/ui/borrowck/borrowck-partial-reinit-1.nll.stderr
new file mode 100644
index 0000000..65f2bd6
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-partial-reinit-1.nll.stderr
@@ -0,0 +1,25 @@
+error[E0382]: assign of moved value: `t`
+  --> $DIR/borrowck-partial-reinit-1.rs:27:5
+   |
+LL |     let mut t = Test2 { b: None };
+   |         ----- move occurs because `t` has type `Test2`, which does not implement the `Copy` trait
+LL |     let u = Test;
+LL |     drop(t);
+   |          - value moved here
+LL |     t.b = Some(u);
+   |     ^^^ value assigned here after move
+
+error[E0382]: assign of moved value: `t`
+  --> $DIR/borrowck-partial-reinit-1.rs:33:5
+   |
+LL |     let mut t = Test3(None);
+   |         ----- move occurs because `t` has type `Test3`, which does not implement the `Copy` trait
+LL |     let u = Test;
+LL |     drop(t);
+   |          - value moved here
+LL |     t.0 = Some(u);
+   |     ^^^ value assigned here after move
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/borrowck-partial-reinit-1.rs b/src/test/ui/borrowck/borrowck-partial-reinit-1.rs
new file mode 100644
index 0000000..f763759
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-partial-reinit-1.rs
@@ -0,0 +1,39 @@
+struct Test;
+
+struct Test2 {
+    b: Option<Test>,
+}
+
+struct Test3(Option<Test>);
+
+impl Drop for Test {
+    fn drop(&mut self) {
+        println!("dropping!");
+    }
+}
+
+impl Drop for Test2 {
+    fn drop(&mut self) {}
+}
+
+impl Drop for Test3 {
+    fn drop(&mut self) {}
+}
+
+fn stuff() {
+    let mut t = Test2 { b: None };
+    let u = Test;
+    drop(t);
+    t.b = Some(u);
+    //~^ ERROR partial reinitialization of uninitialized structure `t`
+
+    let mut t = Test3(None);
+    let u = Test;
+    drop(t);
+    t.0 = Some(u);
+    //~^ ERROR partial reinitialization of uninitialized structure `t`
+}
+
+fn main() {
+    stuff()
+}
diff --git a/src/test/ui/borrowck/borrowck-partial-reinit-1.stderr b/src/test/ui/borrowck/borrowck-partial-reinit-1.stderr
new file mode 100644
index 0000000..23f5035
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-partial-reinit-1.stderr
@@ -0,0 +1,15 @@
+error[E0383]: partial reinitialization of uninitialized structure `t`
+  --> $DIR/borrowck-partial-reinit-1.rs:27:5
+   |
+LL |     t.b = Some(u);
+   |     ^^^^^^^^^^^^^
+
+error[E0383]: partial reinitialization of uninitialized structure `t`
+  --> $DIR/borrowck-partial-reinit-1.rs:33:5
+   |
+LL |     t.0 = Some(u);
+   |     ^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0383`.
diff --git a/src/test/ui/borrowck/borrowck-partial-reinit-2.nll.stderr b/src/test/ui/borrowck/borrowck-partial-reinit-2.nll.stderr
new file mode 100644
index 0000000..36a871f
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-partial-reinit-2.nll.stderr
@@ -0,0 +1,13 @@
+error[E0382]: assign of moved value: `t`
+  --> $DIR/borrowck-partial-reinit-2.rs:15:5
+   |
+LL |     let mut t = Test { a: 1, b: None};
+   |         ----- move occurs because `t` has type `Test`, which does not implement the `Copy` trait
+LL |     let mut u = Test { a: 2, b: Some(Box::new(t))};
+   |                                               - value moved here
+LL |     t.b = Some(Box::new(u));
+   |     ^^^ value assigned here after move
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/borrowck-partial-reinit-2.rs b/src/test/ui/borrowck/borrowck-partial-reinit-2.rs
new file mode 100644
index 0000000..986c20e
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-partial-reinit-2.rs
@@ -0,0 +1,23 @@
+struct Test {
+    a: isize,
+    b: Option<Box<Test>>,
+}
+
+impl Drop for Test {
+    fn drop(&mut self) {
+        println!("Dropping {}", self.a);
+    }
+}
+
+fn stuff() {
+    let mut t = Test { a: 1, b: None};
+    let mut u = Test { a: 2, b: Some(Box::new(t))};
+    t.b = Some(Box::new(u));
+    //~^ ERROR partial reinitialization of uninitialized structure `t`
+    println!("done");
+}
+
+fn main() {
+    stuff();
+    println!("Hello, world!")
+}
diff --git a/src/test/ui/borrowck/borrowck-partial-reinit-2.stderr b/src/test/ui/borrowck/borrowck-partial-reinit-2.stderr
new file mode 100644
index 0000000..891f608
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-partial-reinit-2.stderr
@@ -0,0 +1,9 @@
+error[E0383]: partial reinitialization of uninitialized structure `t`
+  --> $DIR/borrowck-partial-reinit-2.rs:15:5
+   |
+LL |     t.b = Some(Box::new(u));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0383`.
diff --git a/src/test/ui/borrowck/borrowck-partial-reinit-3.nll.stderr b/src/test/ui/borrowck/borrowck-partial-reinit-3.nll.stderr
new file mode 100644
index 0000000..05f5411
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-partial-reinit-3.nll.stderr
@@ -0,0 +1,13 @@
+error[E0382]: assign of moved value: `x.0`
+  --> $DIR/borrowck-partial-reinit-3.rs:11:5
+   |
+LL |     mem::drop(x.0);
+   |               --- value moved here
+LL |     x.0.f = 3;
+   |     ^^^^^^^^^ value assigned here after move
+   |
+   = note: move occurs because `x.0` has type `Test`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/borrowck-partial-reinit-3.rs b/src/test/ui/borrowck/borrowck-partial-reinit-3.rs
new file mode 100644
index 0000000..c7fbd7f
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-partial-reinit-3.rs
@@ -0,0 +1,13 @@
+use std::mem;
+
+struct Test { f: usize }
+impl Drop for Test {
+    fn drop(&mut self) {}
+}
+
+fn main() {
+    let mut x = (Test { f: 2 }, Test { f: 4 });
+    mem::drop(x.0);
+    x.0.f = 3;
+    //~^ ERROR partial reinitialization of uninitialized structure `x.0`
+}
diff --git a/src/test/ui/borrowck/borrowck-partial-reinit-3.stderr b/src/test/ui/borrowck/borrowck-partial-reinit-3.stderr
new file mode 100644
index 0000000..2623174
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-partial-reinit-3.stderr
@@ -0,0 +1,9 @@
+error[E0383]: partial reinitialization of uninitialized structure `x.0`
+  --> $DIR/borrowck-partial-reinit-3.rs:11:5
+   |
+LL |     x.0.f = 3;
+   |     ^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0383`.
diff --git a/src/test/ui/borrowck/borrowck-partial-reinit-4.nll.stderr b/src/test/ui/borrowck/borrowck-partial-reinit-4.nll.stderr
new file mode 100644
index 0000000..f0a9a7d
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-partial-reinit-4.nll.stderr
@@ -0,0 +1,9 @@
+error[E0381]: assign of possibly uninitialized variable: `x.0`
+  --> $DIR/borrowck-partial-reinit-4.rs:17:5
+   |
+LL |     (x.0).0 = Some(Test);
+   |     ^^^^^^^ use of possibly uninitialized `x.0`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/borrowck-partial-reinit-4.rs b/src/test/ui/borrowck/borrowck-partial-reinit-4.rs
new file mode 100644
index 0000000..ffa6b11
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-partial-reinit-4.rs
@@ -0,0 +1,23 @@
+struct Test;
+
+struct Test2(Option<Test>);
+
+impl Drop for Test {
+    fn drop(&mut self) {
+        println!("dropping!");
+    }
+}
+
+impl Drop for Test2 {
+    fn drop(&mut self) {}
+}
+
+fn stuff() {
+    let mut x : (Test2, Test2);
+    (x.0).0 = Some(Test);
+    //~^ ERROR partial reinitialization of uninitialized structure `x.0`
+}
+
+fn main() {
+    stuff()
+}
diff --git a/src/test/ui/borrowck/borrowck-partial-reinit-4.stderr b/src/test/ui/borrowck/borrowck-partial-reinit-4.stderr
new file mode 100644
index 0000000..8ca8e7e
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-partial-reinit-4.stderr
@@ -0,0 +1,9 @@
+error[E0383]: partial reinitialization of uninitialized structure `x.0`
+  --> $DIR/borrowck-partial-reinit-4.rs:17:5
+   |
+LL |     (x.0).0 = Some(Test);
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0383`.
diff --git a/src/test/ui/borrowck/borrowck-pat-reassign-binding.ast.nll.stderr b/src/test/ui/borrowck/borrowck-pat-reassign-binding.ast.nll.stderr
new file mode 100644
index 0000000..f0e1683
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-pat-reassign-binding.ast.nll.stderr
@@ -0,0 +1,15 @@
+error[E0506]: cannot assign to `x` because it is borrowed
+  --> $DIR/borrowck-pat-reassign-binding.rs:13:11
+   |
+LL |       Some(ref i) => {
+   |            ----- borrow of `x` occurs here
+LL |           // But on this branch, `i` is an outstanding borrow
+LL |           x = Some(*i+1);
+   |           ^^^^^^^^^^^^^^ assignment to borrowed `x` occurs here
+LL |
+LL |           drop(i);
+   |                - borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/borrowck/borrowck-pat-reassign-binding.ast.stderr b/src/test/ui/borrowck/borrowck-pat-reassign-binding.ast.stderr
new file mode 100644
index 0000000..d7bce40
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-pat-reassign-binding.ast.stderr
@@ -0,0 +1,12 @@
+error[E0506]: cannot assign to `x` because it is borrowed
+  --> $DIR/borrowck-pat-reassign-binding.rs:13:11
+   |
+LL |       Some(ref i) => {
+   |            ----- borrow of `x` occurs here
+LL |           // But on this branch, `i` is an outstanding borrow
+LL |           x = Some(*i+1);
+   |           ^^^^^^^^^^^^^^ assignment to borrowed `x` occurs here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/borrowck/borrowck-pat-reassign-binding.mir.stderr b/src/test/ui/borrowck/borrowck-pat-reassign-binding.mir.stderr
new file mode 100644
index 0000000..f0e1683
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-pat-reassign-binding.mir.stderr
@@ -0,0 +1,15 @@
+error[E0506]: cannot assign to `x` because it is borrowed
+  --> $DIR/borrowck-pat-reassign-binding.rs:13:11
+   |
+LL |       Some(ref i) => {
+   |            ----- borrow of `x` occurs here
+LL |           // But on this branch, `i` is an outstanding borrow
+LL |           x = Some(*i+1);
+   |           ^^^^^^^^^^^^^^ assignment to borrowed `x` occurs here
+LL |
+LL |           drop(i);
+   |                - borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/borrowck/borrowck-pat-reassign-binding.rs b/src/test/ui/borrowck/borrowck-pat-reassign-binding.rs
new file mode 100644
index 0000000..9befa91
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-pat-reassign-binding.rs
@@ -0,0 +1,19 @@
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+fn main() {
+    let mut x: Option<isize> = None;
+    match x {
+      None => {
+          // Note: on this branch, no borrow has occurred.
+          x = Some(0);
+      }
+      Some(ref i) => {
+          // But on this branch, `i` is an outstanding borrow
+          x = Some(*i+1); //[ast]~ ERROR cannot assign to `x`
+          //[mir]~^ ERROR cannot assign to `x` because it is borrowed
+          drop(i);
+      }
+    }
+    x.clone(); // just to prevent liveness warnings
+}
diff --git a/src/test/ui/borrowck/borrowck-reborrow-from-mut.nll.stderr b/src/test/ui/borrowck/borrowck-reborrow-from-mut.nll.stderr
new file mode 100644
index 0000000..21bc8bb
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-reborrow-from-mut.nll.stderr
@@ -0,0 +1,116 @@
+error[E0499]: cannot borrow `foo.bar1` as mutable more than once at a time
+  --> $DIR/borrowck-reborrow-from-mut.rs:13:17
+   |
+LL |     let _bar1 = &mut foo.bar1;
+   |                 ------------- first mutable borrow occurs here
+LL |     let _bar2 = &mut foo.bar1;
+   |                 ^^^^^^^^^^^^^ second mutable borrow occurs here
+LL |     use_mut(_bar1);
+   |             ----- first borrow later used here
+
+error[E0502]: cannot borrow `foo.bar1` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-reborrow-from-mut.rs:18:17
+   |
+LL |     let _bar1 = &mut foo.bar1;
+   |                 ------------- mutable borrow occurs here
+LL |     let _bar2 = &foo.bar1;
+   |                 ^^^^^^^^^ immutable borrow occurs here
+LL |     use_mut(_bar1);
+   |             ----- mutable borrow later used here
+
+error[E0502]: cannot borrow `foo.bar1` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-reborrow-from-mut.rs:23:17
+   |
+LL |     let _bar1 = &foo.bar1;
+   |                 --------- immutable borrow occurs here
+LL |     let _bar2 = &mut foo.bar1;
+   |                 ^^^^^^^^^^^^^ mutable borrow occurs here
+LL |     use_imm(_bar1);
+   |             ----- immutable borrow later used here
+
+error[E0499]: cannot borrow `foo.bar1` as mutable more than once at a time
+  --> $DIR/borrowck-reborrow-from-mut.rs:45:21
+   |
+LL |     let _bar1 = &mut foo.bar1;
+   |                 ------------- first mutable borrow occurs here
+LL |     match *foo {
+LL |         Foo { bar1: ref mut _bar1, bar2: _ } => {}
+   |                     ^^^^^^^^^^^^^ second mutable borrow occurs here
+...
+LL |     use_mut(_bar1);
+   |             ----- first borrow later used here
+
+error[E0502]: cannot borrow `foo.bar1` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-reborrow-from-mut.rs:52:17
+   |
+LL |     let _bar1 = &mut foo.bar1.int1;
+   |                 ------------------ mutable borrow occurs here
+LL |     let _foo1 = &foo.bar1;
+   |                 ^^^^^^^^^ immutable borrow occurs here
+LL |     let _foo2 = &*foo;
+LL |     use_mut(_bar1);
+   |             ----- mutable borrow later used here
+
+error[E0502]: cannot borrow `*foo` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-reborrow-from-mut.rs:53:17
+   |
+LL |     let _bar1 = &mut foo.bar1.int1;
+   |                 ------------------ mutable borrow occurs here
+LL |     let _foo1 = &foo.bar1;
+LL |     let _foo2 = &*foo;
+   |                 ^^^^^ immutable borrow occurs here
+LL |     use_mut(_bar1);
+   |             ----- mutable borrow later used here
+
+error[E0499]: cannot borrow `foo.bar1` as mutable more than once at a time
+  --> $DIR/borrowck-reborrow-from-mut.rs:58:17
+   |
+LL |     let _bar1 = &mut foo.bar1.int1;
+   |                 ------------------ first mutable borrow occurs here
+LL |     let _foo1 = &mut foo.bar1;
+   |                 ^^^^^^^^^^^^^ second mutable borrow occurs here
+LL |     use_mut(_bar1);
+   |             ----- first borrow later used here
+
+error[E0499]: cannot borrow `*foo` as mutable more than once at a time
+  --> $DIR/borrowck-reborrow-from-mut.rs:63:17
+   |
+LL |     let _bar1 = &mut foo.bar1.int1;
+   |                 ------------------ first mutable borrow occurs here
+LL |     let _foo2 = &mut *foo;
+   |                 ^^^^^^^^^ second mutable borrow occurs here
+LL |     use_mut(_bar1);
+   |             ----- first borrow later used here
+
+error[E0502]: cannot borrow `foo.bar1` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-reborrow-from-mut.rs:68:17
+   |
+LL |     let _bar1 = &foo.bar1.int1;
+   |                 -------------- immutable borrow occurs here
+LL |     let _foo1 = &mut foo.bar1;
+   |                 ^^^^^^^^^^^^^ mutable borrow occurs here
+LL |     use_imm(_bar1);
+   |             ----- immutable borrow later used here
+
+error[E0502]: cannot borrow `*foo` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-reborrow-from-mut.rs:73:17
+   |
+LL |     let _bar1 = &foo.bar1.int1;
+   |                 -------------- immutable borrow occurs here
+LL |     let _foo2 = &mut *foo;
+   |                 ^^^^^^^^^ mutable borrow occurs here
+LL |     use_imm(_bar1);
+   |             ----- immutable borrow later used here
+
+error[E0596]: cannot borrow `foo.bar1` as mutable, as it is behind a `&` reference
+  --> $DIR/borrowck-reborrow-from-mut.rs:88:17
+   |
+LL | fn borrow_mut_from_imm(foo: &Foo) {
+   |                             ---- help: consider changing this to be a mutable reference: `&mut Foo`
+LL |     let _bar1 = &mut foo.bar1;
+   |                 ^^^^^^^^^^^^^ `foo` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+
+error: aborting due to 11 previous errors
+
+Some errors occurred: E0499, E0502, E0596.
+For more information about an error, try `rustc --explain E0499`.
diff --git a/src/test/ui/borrowck/borrowck-reborrow-from-mut.rs b/src/test/ui/borrowck/borrowck-reborrow-from-mut.rs
new file mode 100644
index 0000000..eef83c5
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-reborrow-from-mut.rs
@@ -0,0 +1,99 @@
+struct Foo {
+  bar1: Bar,
+  bar2: Bar
+}
+
+struct Bar {
+  int1: isize,
+  int2: isize,
+}
+
+fn borrow_same_field_twice_mut_mut(foo: &mut Foo) {
+    let _bar1 = &mut foo.bar1;
+    let _bar2 = &mut foo.bar1;  //~ ERROR cannot borrow
+    use_mut(_bar1);
+}
+fn borrow_same_field_twice_mut_imm(foo: &mut Foo) {
+    let _bar1 = &mut foo.bar1;
+    let _bar2 = &foo.bar1;  //~ ERROR cannot borrow
+    use_mut(_bar1);
+}
+fn borrow_same_field_twice_imm_mut(foo: &mut Foo) {
+    let _bar1 = &foo.bar1;
+    let _bar2 = &mut foo.bar1;  //~ ERROR cannot borrow
+    use_imm(_bar1);
+}
+fn borrow_same_field_twice_imm_imm(foo: &mut Foo) {
+    let _bar1 = &foo.bar1;
+    let _bar2 = &foo.bar1;
+    use_imm(_bar1);
+}
+fn borrow_both_mut(foo: &mut Foo) {
+    let _bar1 = &mut foo.bar1;
+    let _bar2 = &mut foo.bar2;
+    use_mut(_bar1);
+}
+fn borrow_both_mut_pattern(foo: &mut Foo) {
+    match *foo {
+        Foo { bar1: ref mut _bar1, bar2: ref mut _bar2 } =>
+        { use_mut(_bar1); use_mut(_bar2); }
+    }
+}
+fn borrow_var_and_pattern(foo: &mut Foo) {
+    let _bar1 = &mut foo.bar1;
+    match *foo {
+        Foo { bar1: ref mut _bar1, bar2: _ } => {}
+        //~^ ERROR cannot borrow
+    }
+    use_mut(_bar1);
+}
+fn borrow_mut_and_base_imm(foo: &mut Foo) {
+    let _bar1 = &mut foo.bar1.int1;
+    let _foo1 = &foo.bar1; //~ ERROR cannot borrow
+    let _foo2 = &*foo; //~ ERROR cannot borrow
+    use_mut(_bar1);
+}
+fn borrow_mut_and_base_mut(foo: &mut Foo) {
+    let _bar1 = &mut foo.bar1.int1;
+    let _foo1 = &mut foo.bar1; //~ ERROR cannot borrow
+    use_mut(_bar1);
+}
+fn borrow_mut_and_base_mut2(foo: &mut Foo) {
+    let _bar1 = &mut foo.bar1.int1;
+    let _foo2 = &mut *foo; //~ ERROR cannot borrow
+    use_mut(_bar1);
+}
+fn borrow_imm_and_base_mut(foo: &mut Foo) {
+    let _bar1 = &foo.bar1.int1;
+    let _foo1 = &mut foo.bar1; //~ ERROR cannot borrow
+    use_imm(_bar1);
+}
+fn borrow_imm_and_base_mut2(foo: &mut Foo) {
+    let _bar1 = &foo.bar1.int1;
+    let _foo2 = &mut *foo; //~ ERROR cannot borrow
+    use_imm(_bar1);
+}
+fn borrow_imm_and_base_imm(foo: &mut Foo) {
+    let _bar1 = &foo.bar1.int1;
+    let _foo1 = &foo.bar1;
+    let _foo2 = &*foo;
+    use_imm(_bar1);
+}
+fn borrow_mut_and_imm(foo: &mut Foo) {
+    let _bar1 = &mut foo.bar1;
+    let _foo1 = &foo.bar2;
+    use_mut(_bar1);
+}
+fn borrow_mut_from_imm(foo: &Foo) {
+    let _bar1 = &mut foo.bar1; //~ ERROR cannot borrow
+}
+
+fn borrow_long_path_both_mut(foo: &mut Foo) {
+    let _bar1 = &mut foo.bar1.int1;
+    let _foo1 = &mut foo.bar2.int2;
+    use_mut(_bar1);
+}
+fn main() {}
+
+fn use_mut<T>(_: &mut T) { }
+fn use_imm<T>(_: &T) { }
diff --git a/src/test/ui/borrowck/borrowck-reborrow-from-mut.stderr b/src/test/ui/borrowck/borrowck-reborrow-from-mut.stderr
new file mode 100644
index 0000000..ea62401
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-reborrow-from-mut.stderr
@@ -0,0 +1,124 @@
+error[E0499]: cannot borrow `foo.bar1` as mutable more than once at a time
+  --> $DIR/borrowck-reborrow-from-mut.rs:13:22
+   |
+LL |     let _bar1 = &mut foo.bar1;
+   |                      -------- first mutable borrow occurs here
+LL |     let _bar2 = &mut foo.bar1;
+   |                      ^^^^^^^^ second mutable borrow occurs here
+LL |     use_mut(_bar1);
+LL | }
+   | - first borrow ends here
+
+error[E0502]: cannot borrow `foo.bar1` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-reborrow-from-mut.rs:18:18
+   |
+LL |     let _bar1 = &mut foo.bar1;
+   |                      -------- mutable borrow occurs here
+LL |     let _bar2 = &foo.bar1;
+   |                  ^^^^^^^^ immutable borrow occurs here
+LL |     use_mut(_bar1);
+LL | }
+   | - mutable borrow ends here
+
+error[E0502]: cannot borrow `foo.bar1` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-reborrow-from-mut.rs:23:22
+   |
+LL |     let _bar1 = &foo.bar1;
+   |                  -------- immutable borrow occurs here
+LL |     let _bar2 = &mut foo.bar1;
+   |                      ^^^^^^^^ mutable borrow occurs here
+LL |     use_imm(_bar1);
+LL | }
+   | - immutable borrow ends here
+
+error[E0499]: cannot borrow `foo.bar1` as mutable more than once at a time
+  --> $DIR/borrowck-reborrow-from-mut.rs:45:21
+   |
+LL |     let _bar1 = &mut foo.bar1;
+   |                      -------- first mutable borrow occurs here
+LL |     match *foo {
+LL |         Foo { bar1: ref mut _bar1, bar2: _ } => {}
+   |                     ^^^^^^^^^^^^^ second mutable borrow occurs here
+...
+LL | }
+   | - first borrow ends here
+
+error[E0502]: cannot borrow `foo.bar1` as immutable because `foo.bar1.int1` is also borrowed as mutable
+  --> $DIR/borrowck-reborrow-from-mut.rs:52:18
+   |
+LL |     let _bar1 = &mut foo.bar1.int1;
+   |                      ------------- mutable borrow occurs here
+LL |     let _foo1 = &foo.bar1;
+   |                  ^^^^^^^^ immutable borrow occurs here
+...
+LL | }
+   | - mutable borrow ends here
+
+error[E0502]: cannot borrow `*foo` as immutable because `foo.bar1.int1` is also borrowed as mutable
+  --> $DIR/borrowck-reborrow-from-mut.rs:53:18
+   |
+LL |     let _bar1 = &mut foo.bar1.int1;
+   |                      ------------- mutable borrow occurs here
+LL |     let _foo1 = &foo.bar1;
+LL |     let _foo2 = &*foo;
+   |                  ^^^^ immutable borrow occurs here
+LL |     use_mut(_bar1);
+LL | }
+   | - mutable borrow ends here
+
+error[E0499]: cannot borrow `foo.bar1` as mutable more than once at a time
+  --> $DIR/borrowck-reborrow-from-mut.rs:58:22
+   |
+LL |     let _bar1 = &mut foo.bar1.int1;
+   |                      ------------- first mutable borrow occurs here
+LL |     let _foo1 = &mut foo.bar1;
+   |                      ^^^^^^^^ second mutable borrow occurs here
+LL |     use_mut(_bar1);
+LL | }
+   | - first borrow ends here
+
+error[E0499]: cannot borrow `*foo` as mutable more than once at a time
+  --> $DIR/borrowck-reborrow-from-mut.rs:63:22
+   |
+LL |     let _bar1 = &mut foo.bar1.int1;
+   |                      ------------- first mutable borrow occurs here
+LL |     let _foo2 = &mut *foo;
+   |                      ^^^^ second mutable borrow occurs here
+LL |     use_mut(_bar1);
+LL | }
+   | - first borrow ends here
+
+error[E0502]: cannot borrow `foo.bar1` as mutable because `foo.bar1.int1` is also borrowed as immutable
+  --> $DIR/borrowck-reborrow-from-mut.rs:68:22
+   |
+LL |     let _bar1 = &foo.bar1.int1;
+   |                  ------------- immutable borrow occurs here
+LL |     let _foo1 = &mut foo.bar1;
+   |                      ^^^^^^^^ mutable borrow occurs here
+LL |     use_imm(_bar1);
+LL | }
+   | - immutable borrow ends here
+
+error[E0502]: cannot borrow `*foo` as mutable because `foo.bar1.int1` is also borrowed as immutable
+  --> $DIR/borrowck-reborrow-from-mut.rs:73:22
+   |
+LL |     let _bar1 = &foo.bar1.int1;
+   |                  ------------- immutable borrow occurs here
+LL |     let _foo2 = &mut *foo;
+   |                      ^^^^ mutable borrow occurs here
+LL |     use_imm(_bar1);
+LL | }
+   | - immutable borrow ends here
+
+error[E0596]: cannot borrow field `foo.bar1` of immutable binding as mutable
+  --> $DIR/borrowck-reborrow-from-mut.rs:88:22
+   |
+LL | fn borrow_mut_from_imm(foo: &Foo) {
+   |                             ---- use `&mut Foo` here to make mutable
+LL |     let _bar1 = &mut foo.bar1;
+   |                      ^^^^^^^^ cannot mutably borrow field of immutable binding
+
+error: aborting due to 11 previous errors
+
+Some errors occurred: E0499, E0502, E0596.
+For more information about an error, try `rustc --explain E0499`.
diff --git a/src/test/ui/borrowck/borrowck-reborrow-from-shorter-lived-andmut.rs b/src/test/ui/borrowck/borrowck-reborrow-from-shorter-lived-andmut.rs
new file mode 100644
index 0000000..a7c9200
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-reborrow-from-shorter-lived-andmut.rs
@@ -0,0 +1,22 @@
+// Test that assignments to an `&mut` pointer which is found in a
+// borrowed (but otherwise non-aliasable) location is illegal.
+
+struct S<'a> {
+    pointer: &'a mut isize
+}
+
+fn copy_borrowed_ptr<'a,'b>(p: &'a mut S<'b>) -> S<'b> {
+    S { pointer: &mut *p.pointer }
+    //~^ ERROR lifetime mismatch
+}
+
+fn main() {
+    let mut x = 1;
+
+    {
+        let mut y = S { pointer: &mut x };
+        let z = copy_borrowed_ptr(&mut y);
+        *y.pointer += 1;
+        *z.pointer += 1;
+    }
+}
diff --git a/src/test/ui/borrowck/borrowck-reborrow-from-shorter-lived-andmut.stderr b/src/test/ui/borrowck/borrowck-reborrow-from-shorter-lived-andmut.stderr
new file mode 100644
index 0000000..67b6f64
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-reborrow-from-shorter-lived-andmut.stderr
@@ -0,0 +1,13 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/borrowck-reborrow-from-shorter-lived-andmut.rs:9:5
+   |
+LL | fn copy_borrowed_ptr<'a,'b>(p: &'a mut S<'b>) -> S<'b> {
+   |                                -------------     -----
+   |                                |
+   |                                this parameter and the return type are declared with different lifetimes...
+LL |     S { pointer: &mut *p.pointer }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...but data from `p` is returned here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/borrowck/borrowck-ref-mut-of-imm.nll.stderr b/src/test/ui/borrowck/borrowck-ref-mut-of-imm.nll.stderr
new file mode 100644
index 0000000..e744fc6
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-ref-mut-of-imm.nll.stderr
@@ -0,0 +1,12 @@
+error[E0596]: cannot borrow `x.0` as mutable, as `x` is not declared as mutable
+  --> $DIR/borrowck-ref-mut-of-imm.rs:4:12
+   |
+LL | fn destructure(x: Option<isize>) -> isize {
+   |                - help: consider changing this to be mutable: `mut x`
+...
+LL |       Some(ref mut v) => *v
+   |            ^^^^^^^^^ cannot borrow as mutable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/borrowck/borrowck-ref-mut-of-imm.rs b/src/test/ui/borrowck/borrowck-ref-mut-of-imm.rs
new file mode 100644
index 0000000..ae5bb85
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-ref-mut-of-imm.rs
@@ -0,0 +1,10 @@
+fn destructure(x: Option<isize>) -> isize {
+    match x {
+      None => 0,
+      Some(ref mut v) => *v //~ ERROR cannot borrow
+    }
+}
+
+fn main() {
+    assert_eq!(destructure(Some(22)), 22);
+}
diff --git a/src/test/ui/borrowck/borrowck-ref-mut-of-imm.stderr b/src/test/ui/borrowck/borrowck-ref-mut-of-imm.stderr
new file mode 100644
index 0000000..6e0d2f6
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-ref-mut-of-imm.stderr
@@ -0,0 +1,12 @@
+error[E0596]: cannot borrow field `(x as std::prelude::v1::Some).0` of immutable binding as mutable
+  --> $DIR/borrowck-ref-mut-of-imm.rs:4:12
+   |
+LL | fn destructure(x: Option<isize>) -> isize {
+   |                - help: make this binding mutable: `mut x`
+...
+LL |       Some(ref mut v) => *v
+   |            ^^^^^^^^^ cannot mutably borrow field of immutable binding
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/borrowck/borrowck-reinit.rs b/src/test/ui/borrowck/borrowck-reinit.rs
new file mode 100644
index 0000000..e8e38a9
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-reinit.rs
@@ -0,0 +1,10 @@
+// compile-flags: -Z borrowck=compare
+
+fn main() {
+    let mut x = Box::new(0);
+    let _u = x; // error shouldn't note this move
+    x = Box::new(1);
+    drop(x);
+    let _ = (1,x); //~ ERROR use of moved value: `x` (Ast)
+    //~^ ERROR use of moved value: `x` (Mir)
+}
diff --git a/src/test/ui/borrowck/borrowck-reinit.stderr b/src/test/ui/borrowck/borrowck-reinit.stderr
new file mode 100644
index 0000000..3618a7c
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-reinit.stderr
@@ -0,0 +1,24 @@
+error[E0382]: use of moved value: `x` (Ast)
+  --> $DIR/borrowck-reinit.rs:8:16
+   |
+LL |     drop(x);
+   |          - value moved here
+LL |     let _ = (1,x);
+   |                ^ value used here after move
+   |
+   = note: move occurs because `x` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `x` (Mir)
+  --> $DIR/borrowck-reinit.rs:8:16
+   |
+LL |     let mut x = Box::new(0);
+   |         ----- move occurs because `x` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
+...
+LL |     drop(x);
+   |          - value moved here
+LL |     let _ = (1,x);
+   |                ^ value used here after move
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/borrowck-report-with-custom-diagnostic.nll.stderr b/src/test/ui/borrowck/borrowck-report-with-custom-diagnostic.nll.stderr
new file mode 100644
index 0000000..ee8f90e
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-report-with-custom-diagnostic.nll.stderr
@@ -0,0 +1,40 @@
+error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-report-with-custom-diagnostic.rs:8:13
+   |
+LL |     let y = &mut x;
+   |             ------ mutable borrow occurs here
+LL |
+LL |     let z = &x;
+   |             ^^ immutable borrow occurs here
+...
+LL |     y.use_mut();
+   |     - mutable borrow later used here
+
+error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-report-with-custom-diagnostic.rs:21:21
+   |
+LL |             let y = &x;
+   |                     -- immutable borrow occurs here
+LL |
+LL |             let z = &mut x;
+   |                     ^^^^^^ mutable borrow occurs here
+...
+LL |             y.use_ref();
+   |             - immutable borrow later used here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time
+  --> $DIR/borrowck-report-with-custom-diagnostic.rs:36:17
+   |
+LL |         let y = &mut x;
+   |                 ------ first mutable borrow occurs here
+LL |
+LL |         let z = &mut x;
+   |                 ^^^^^^ second mutable borrow occurs here
+...
+LL |         y.use_mut();
+   |         - first borrow later used here
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0499, E0502.
+For more information about an error, try `rustc --explain E0499`.
diff --git a/src/test/ui/borrowck/borrowck-report-with-custom-diagnostic.rs b/src/test/ui/borrowck/borrowck-report-with-custom-diagnostic.rs
new file mode 100644
index 0000000..6f323d9
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-report-with-custom-diagnostic.rs
@@ -0,0 +1,44 @@
+#![feature(rustc_attrs)]
+#![allow(dead_code)]
+fn main() { #![rustc_error] // rust-lang/rust#49855
+    // Original borrow ends at end of function
+    let mut x = 1;
+    let y = &mut x;
+    //~^ mutable borrow occurs here
+    let z = &x; //~ ERROR cannot borrow
+    //~^ immutable borrow occurs here
+    z.use_ref();
+    y.use_mut();
+}
+
+fn foo() {
+    match true {
+        true => {
+            // Original borrow ends at end of match arm
+            let mut x = 1;
+            let y = &x;
+            //~^ immutable borrow occurs here
+            let z = &mut x; //~ ERROR cannot borrow
+            //~^ mutable borrow occurs here
+            z.use_mut();
+            y.use_ref();
+        }
+        false => ()
+    }
+}
+
+fn bar() {
+    // Original borrow ends at end of closure
+    || {
+        let mut x = 1;
+        let y = &mut x;
+        //~^ first mutable borrow occurs here
+        let z = &mut x; //~ ERROR cannot borrow
+        //~^ second mutable borrow occurs here
+        z.use_mut();
+        y.use_mut();
+    };
+}
+
+trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { }  }
+impl<T> Fake for T { }
diff --git a/src/test/ui/borrowck/borrowck-report-with-custom-diagnostic.stderr b/src/test/ui/borrowck/borrowck-report-with-custom-diagnostic.stderr
new file mode 100644
index 0000000..79aec6c
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-report-with-custom-diagnostic.stderr
@@ -0,0 +1,40 @@
+error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-report-with-custom-diagnostic.rs:8:14
+   |
+LL |     let y = &mut x;
+   |                  - mutable borrow occurs here
+LL |
+LL |     let z = &x;
+   |              ^ immutable borrow occurs here
+...
+LL | }
+   | - mutable borrow ends here
+
+error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-report-with-custom-diagnostic.rs:21:26
+   |
+LL |             let y = &x;
+   |                      - immutable borrow occurs here
+LL |
+LL |             let z = &mut x;
+   |                          ^ mutable borrow occurs here
+...
+LL |         }
+   |         - immutable borrow ends here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time
+  --> $DIR/borrowck-report-with-custom-diagnostic.rs:36:22
+   |
+LL |         let y = &mut x;
+   |                      - first mutable borrow occurs here
+LL |
+LL |         let z = &mut x;
+   |                      ^ second mutable borrow occurs here
+...
+LL |     };
+   |     - first borrow ends here
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0499, E0502.
+For more information about an error, try `rustc --explain E0499`.
diff --git a/src/test/ui/borrowck/borrowck-return-variable-on-stack-via-clone.nll.stderr b/src/test/ui/borrowck/borrowck-return-variable-on-stack-via-clone.nll.stderr
new file mode 100644
index 0000000..d54449a
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-return-variable-on-stack-via-clone.nll.stderr
@@ -0,0 +1,12 @@
+error[E0515]: cannot return value referencing function parameter `x`
+  --> $DIR/borrowck-return-variable-on-stack-via-clone.rs:7:5
+   |
+LL |     (&x).clone()
+   |     ----^^^^^^^^
+   |     |
+   |     returns a value referencing data owned by the current function
+   |     `x` is borrowed here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/src/test/ui/borrowck/borrowck-return-variable-on-stack-via-clone.rs b/src/test/ui/borrowck/borrowck-return-variable-on-stack-via-clone.rs
new file mode 100644
index 0000000..f8cdc3e
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-return-variable-on-stack-via-clone.rs
@@ -0,0 +1,10 @@
+// Check that when we clone a `&T` pointer we properly relate the
+// lifetime of the pointer which results to the pointer being cloned.
+// Bugs in method resolution have sometimes broken this connection.
+// Issue #19261.
+
+fn leak<'a, T>(x: T) -> &'a T {
+    (&x).clone() //~ ERROR `x` does not live long enough
+}
+
+fn main() { }
diff --git a/src/test/ui/borrowck/borrowck-return-variable-on-stack-via-clone.stderr b/src/test/ui/borrowck/borrowck-return-variable-on-stack-via-clone.stderr
new file mode 100644
index 0000000..4d4244b
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-return-variable-on-stack-via-clone.stderr
@@ -0,0 +1,17 @@
+error[E0597]: `x` does not live long enough
+  --> $DIR/borrowck-return-variable-on-stack-via-clone.rs:7:7
+   |
+LL |     (&x).clone()
+   |       ^ borrowed value does not live long enough
+LL | }
+   | - borrowed value only lives until here
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 6:9...
+  --> $DIR/borrowck-return-variable-on-stack-via-clone.rs:6:9
+   |
+LL | fn leak<'a, T>(x: T) -> &'a T {
+   |         ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/borrowck/borrowck-return.rs b/src/test/ui/borrowck/borrowck-return.rs
new file mode 100644
index 0000000..e5bee2c
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-return.rs
@@ -0,0 +1,6 @@
+fn f() -> isize {
+    let x: isize;
+    return x; //~ ERROR use of possibly uninitialized variable: `x`
+}
+
+fn main() { f(); }
diff --git a/src/test/ui/borrowck/borrowck-return.stderr b/src/test/ui/borrowck/borrowck-return.stderr
new file mode 100644
index 0000000..a2b65af
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-return.stderr
@@ -0,0 +1,9 @@
+error[E0381]: use of possibly uninitialized variable: `x`
+  --> $DIR/borrowck-return.rs:3:12
+   |
+LL |     return x;
+   |            ^ use of possibly uninitialized `x`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan.rs b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan.rs
new file mode 100644
index 0000000..5de8dd3
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan.rs
@@ -0,0 +1,127 @@
+//compile-flags: -Z borrowck=mir
+
+#![feature(slice_patterns)]
+
+fn nop(_s: &[& i32]) {}
+fn nop_subslice(_s: &[i32]) {}
+
+fn const_index_ok(s: &mut [i32]) {
+    if let [ref first, ref second, _, ref fourth, ..] = *s {
+        if let [_, _, ref mut third, ..] = *s {
+            nop(&[first, second, third, fourth]);
+        }
+    }
+}
+
+fn const_index_err(s: &mut [i32]) {
+    if let [ref first, ref second, ..] = *s {
+        if let [_, ref mut  second2, ref mut third, ..] = *s { //~ERROR
+            nop(&[first, second, second2, third]);
+        }
+    }
+}
+
+fn const_index_from_end_ok(s: &mut [i32]) {
+    if let [.., ref fourth, ref third, _, ref first] = *s {
+        if let [.., ref mut second, _] = *s {
+            nop(&[first, second, third, fourth]);
+        }
+    }
+}
+
+fn const_index_from_end_err(s: &mut [i32]) {
+    if let [.., ref fourth, ref third, _, ref first] = *s {
+        if let [.., ref mut third2, _, _] = *s { //~ERROR
+            nop(&[first, third, third2, fourth]);
+        }
+    }
+}
+
+fn const_index_mixed(s: &mut [i32]) {
+    if let [.., _, ref from_end4, ref from_end3, _, ref from_end1] = *s {
+        if let [ref mut from_begin0, ..] = *s {
+            nop(&[from_begin0, from_end1, from_end3, from_end4]);
+        }
+        if let [_, ref mut from_begin1, ..] = *s { //~ERROR
+            nop(&[from_begin1, from_end1, from_end3, from_end4]);
+        }
+        if let [_, _, ref mut from_begin2, ..] = *s { //~ERROR
+            nop(&[from_begin2, from_end1, from_end3, from_end4]);
+        }
+        if let [_, _, _, ref mut from_begin3, ..] = *s { //~ERROR
+            nop(&[from_begin3, from_end1, from_end3, from_end4]);
+        }
+    }
+    if let [ref from_begin0, ref from_begin1, _, ref from_begin3, _, ..] = *s {
+        if let [.., ref mut from_end1] = *s {
+            nop(&[from_begin0, from_begin1, from_begin3, from_end1]);
+        }
+        if let [.., ref mut from_end2, _] = *s { //~ERROR
+            nop(&[from_begin0, from_begin1, from_begin3, from_end2]);
+        }
+        if let [.., ref mut from_end3, _,  _] = *s { //~ERROR
+            nop(&[from_begin0, from_begin1, from_begin3, from_end3]);
+        }
+        if let [.., ref mut from_end4, _, _, _] = *s { //~ERROR
+            nop(&[from_begin0, from_begin1, from_begin3, from_end4]);
+        }
+    }
+}
+
+fn const_index_and_subslice_ok(s: &mut [i32]) {
+    if let [ref first, ref second, ..] = *s {
+        if let [_, _, ref mut tail..] = *s {
+            nop(&[first, second]);
+            nop_subslice(tail);
+        }
+    }
+}
+
+fn const_index_and_subslice_err(s: &mut [i32]) {
+    if let [ref first, ref second, ..] = *s {
+        if let [_, ref mut tail..] = *s { //~ERROR
+            nop(&[first, second]);
+            nop_subslice(tail);
+        }
+    }
+}
+
+fn const_index_and_subslice_from_end_ok(s: &mut [i32]) {
+    if let [.., ref second, ref first] = *s {
+        if let [ref mut tail.., _, _] = *s {
+            nop(&[first, second]);
+            nop_subslice(tail);
+        }
+    }
+}
+
+fn const_index_and_subslice_from_end_err(s: &mut [i32]) {
+    if let [.., ref second, ref first] = *s {
+        if let [ref mut tail.., _] = *s { //~ERROR
+            nop(&[first, second]);
+            nop_subslice(tail);
+        }
+    }
+}
+
+fn subslices(s: &mut [i32]) {
+    if let [_, _, _, ref s1..] = *s {
+        if let [ref mut s2.., _, _, _] = *s { //~ERROR
+            nop_subslice(s1);
+            nop_subslice(s2);
+        }
+    }
+}
+
+fn main() {
+    let mut v = [1,2,3,4];
+    const_index_ok(&mut v);
+    const_index_err(&mut v);
+    const_index_from_end_ok(&mut v);
+    const_index_from_end_err(&mut v);
+    const_index_and_subslice_ok(&mut v);
+    const_index_and_subslice_err(&mut v);
+    const_index_and_subslice_from_end_ok(&mut v);
+    const_index_and_subslice_from_end_err(&mut v);
+    subslices(&mut v);
+}
diff --git a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan.stderr b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan.stderr
new file mode 100644
index 0000000..f716ee6
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan.stderr
@@ -0,0 +1,119 @@
+error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-slice-pattern-element-loan.rs:18:20
+   |
+LL |     if let [ref first, ref second, ..] = *s {
+   |                        ---------- immutable borrow occurs here
+LL |         if let [_, ref mut  second2, ref mut third, ..] = *s {
+   |                    ^^^^^^^^^^^^^^^^ mutable borrow occurs here
+LL |             nop(&[first, second, second2, third]);
+   |                          ------ immutable borrow later used here
+
+error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-slice-pattern-element-loan.rs:34:21
+   |
+LL |     if let [.., ref fourth, ref third, _, ref first] = *s {
+   |                             --------- immutable borrow occurs here
+LL |         if let [.., ref mut third2, _, _] = *s {
+   |                     ^^^^^^^^^^^^^^ mutable borrow occurs here
+LL |             nop(&[first, third, third2, fourth]);
+   |                          ----- immutable borrow later used here
+
+error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-slice-pattern-element-loan.rs:45:20
+   |
+LL |     if let [.., _, ref from_end4, ref from_end3, _, ref from_end1] = *s {
+   |                    ------------- immutable borrow occurs here
+...
+LL |         if let [_, ref mut from_begin1, ..] = *s {
+   |                    ^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
+LL |             nop(&[from_begin1, from_end1, from_end3, from_end4]);
+   |                                                      --------- immutable borrow later used here
+
+error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-slice-pattern-element-loan.rs:48:23
+   |
+LL |     if let [.., _, ref from_end4, ref from_end3, _, ref from_end1] = *s {
+   |                                   ------------- immutable borrow occurs here
+...
+LL |         if let [_, _, ref mut from_begin2, ..] = *s {
+   |                       ^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
+LL |             nop(&[from_begin2, from_end1, from_end3, from_end4]);
+   |                                           --------- immutable borrow later used here
+
+error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-slice-pattern-element-loan.rs:51:26
+   |
+LL |     if let [.., _, ref from_end4, ref from_end3, _, ref from_end1] = *s {
+   |                                   ------------- immutable borrow occurs here
+...
+LL |         if let [_, _, _, ref mut from_begin3, ..] = *s {
+   |                          ^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
+LL |             nop(&[from_begin3, from_end1, from_end3, from_end4]);
+   |                                           --------- immutable borrow later used here
+
+error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-slice-pattern-element-loan.rs:59:21
+   |
+LL |     if let [ref from_begin0, ref from_begin1, _, ref from_begin3, _, ..] = *s {
+   |                                                  --------------- immutable borrow occurs here
+...
+LL |         if let [.., ref mut from_end2, _] = *s {
+   |                     ^^^^^^^^^^^^^^^^^ mutable borrow occurs here
+LL |             nop(&[from_begin0, from_begin1, from_begin3, from_end2]);
+   |                                             ----------- immutable borrow later used here
+
+error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-slice-pattern-element-loan.rs:62:21
+   |
+LL |     if let [ref from_begin0, ref from_begin1, _, ref from_begin3, _, ..] = *s {
+   |                                                  --------------- immutable borrow occurs here
+...
+LL |         if let [.., ref mut from_end3, _,  _] = *s {
+   |                     ^^^^^^^^^^^^^^^^^ mutable borrow occurs here
+LL |             nop(&[from_begin0, from_begin1, from_begin3, from_end3]);
+   |                                             ----------- immutable borrow later used here
+
+error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-slice-pattern-element-loan.rs:65:21
+   |
+LL |     if let [ref from_begin0, ref from_begin1, _, ref from_begin3, _, ..] = *s {
+   |                              --------------- immutable borrow occurs here
+...
+LL |         if let [.., ref mut from_end4, _, _, _] = *s {
+   |                     ^^^^^^^^^^^^^^^^^ mutable borrow occurs here
+LL |             nop(&[from_begin0, from_begin1, from_begin3, from_end4]);
+   |                                ----------- immutable borrow later used here
+
+error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-slice-pattern-element-loan.rs:82:20
+   |
+LL |     if let [ref first, ref second, ..] = *s {
+   |                        ---------- immutable borrow occurs here
+LL |         if let [_, ref mut tail..] = *s {
+   |                    ^^^^^^^^^^^^ mutable borrow occurs here
+LL |             nop(&[first, second]);
+   |                          ------ immutable borrow later used here
+
+error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-slice-pattern-element-loan.rs:100:17
+   |
+LL |     if let [.., ref second, ref first] = *s {
+   |                 ---------- immutable borrow occurs here
+LL |         if let [ref mut tail.., _] = *s {
+   |                 ^^^^^^^^^^^^ mutable borrow occurs here
+LL |             nop(&[first, second]);
+   |                          ------ immutable borrow later used here
+
+error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-slice-pattern-element-loan.rs:109:17
+   |
+LL |     if let [_, _, _, ref s1..] = *s {
+   |                      ------ immutable borrow occurs here
+LL |         if let [ref mut s2.., _, _, _] = *s {
+   |                 ^^^^^^^^^^ mutable borrow occurs here
+LL |             nop_subslice(s1);
+   |                          -- immutable borrow later used here
+
+error: aborting due to 11 previous errors
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/borrowck/borrowck-storage-dead.rs b/src/test/ui/borrowck/borrowck-storage-dead.rs
new file mode 100644
index 0000000..72c3bc1
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-storage-dead.rs
@@ -0,0 +1,27 @@
+// compile-flags: -Z borrowck=compare
+
+fn ok() {
+    loop {
+        let _x = 1;
+    }
+}
+
+fn also_ok() {
+    loop {
+        let _x = String::new();
+    }
+}
+
+fn fail() {
+    loop {
+        let x: i32;
+        let _ = x + 1; //~ERROR (Ast) [E0381]
+                       //~^ ERROR (Mir) [E0381]
+    }
+}
+
+fn main() {
+    ok();
+    also_ok();
+    fail();
+}
diff --git a/src/test/ui/borrowck/borrowck-storage-dead.stderr b/src/test/ui/borrowck/borrowck-storage-dead.stderr
new file mode 100644
index 0000000..c291ed2
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-storage-dead.stderr
@@ -0,0 +1,15 @@
+error[E0381]: use of possibly uninitialized variable: `x` (Ast)
+  --> $DIR/borrowck-storage-dead.rs:18:17
+   |
+LL |         let _ = x + 1;
+   |                 ^ use of possibly uninitialized `x`
+
+error[E0381]: use of possibly uninitialized variable: `x` (Mir)
+  --> $DIR/borrowck-storage-dead.rs:18:17
+   |
+LL |         let _ = x + 1;
+   |                 ^ use of possibly uninitialized `x`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/borrowck-struct-update-with-dtor.ast.nll.stderr b/src/test/ui/borrowck/borrowck-struct-update-with-dtor.ast.nll.stderr
new file mode 100644
index 0000000..dbc9ece
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-struct-update-with-dtor.ast.nll.stderr
@@ -0,0 +1,15 @@
+error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
+  --> $DIR/borrowck-struct-update-with-dtor.rs:15:15
+   |
+LL |     let _s2 = S{a: 2, ..s0};
+   |               ^^^^^^^^^^^^^ cannot move out of here
+
+error[E0509]: cannot move out of type `T`, which implements the `Drop` trait
+  --> $DIR/borrowck-struct-update-with-dtor.rs:21:15
+   |
+LL |     let _s2 = T{a: 2, ..s0};
+   |               ^^^^^^^^^^^^^ cannot move out of here
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0509`.
diff --git a/src/test/ui/borrowck/borrowck-struct-update-with-dtor.ast.stderr b/src/test/ui/borrowck/borrowck-struct-update-with-dtor.ast.stderr
new file mode 100644
index 0000000..bc0a954b
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-struct-update-with-dtor.ast.stderr
@@ -0,0 +1,15 @@
+error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
+  --> $DIR/borrowck-struct-update-with-dtor.rs:15:25
+   |
+LL |     let _s2 = S{a: 2, ..s0};
+   |                         ^^ cannot move out of here
+
+error[E0509]: cannot move out of type `T`, which implements the `Drop` trait
+  --> $DIR/borrowck-struct-update-with-dtor.rs:21:25
+   |
+LL |     let _s2 = T{a: 2, ..s0};
+   |                         ^^ cannot move out of here
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0509`.
diff --git a/src/test/ui/borrowck/borrowck-struct-update-with-dtor.mir.stderr b/src/test/ui/borrowck/borrowck-struct-update-with-dtor.mir.stderr
new file mode 100644
index 0000000..dbc9ece
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-struct-update-with-dtor.mir.stderr
@@ -0,0 +1,15 @@
+error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
+  --> $DIR/borrowck-struct-update-with-dtor.rs:15:15
+   |
+LL |     let _s2 = S{a: 2, ..s0};
+   |               ^^^^^^^^^^^^^ cannot move out of here
+
+error[E0509]: cannot move out of type `T`, which implements the `Drop` trait
+  --> $DIR/borrowck-struct-update-with-dtor.rs:21:15
+   |
+LL |     let _s2 = T{a: 2, ..s0};
+   |               ^^^^^^^^^^^^^ cannot move out of here
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0509`.
diff --git a/src/test/ui/borrowck/borrowck-struct-update-with-dtor.rs b/src/test/ui/borrowck/borrowck-struct-update-with-dtor.rs
new file mode 100644
index 0000000..da5bb63
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-struct-update-with-dtor.rs
@@ -0,0 +1,26 @@
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+// Issue 4691: Ensure that functional-struct-update can only copy, not
+// move, when the struct implements Drop.
+
+struct B;
+struct S { a: isize, b: B }
+impl Drop for S { fn drop(&mut self) { } }
+
+struct T { a: isize, mv: Box<isize> }
+impl Drop for T { fn drop(&mut self) { } }
+
+fn f(s0:S) {
+    let _s2 = S{a: 2, ..s0};
+    //[ast]~^ error: cannot move out of type `S`, which implements the `Drop` trait
+    //[mir]~^^ ERROR [E0509]
+}
+
+fn g(s0:T) {
+    let _s2 = T{a: 2, ..s0};
+    //[ast]~^ error: cannot move out of type `T`, which implements the `Drop` trait
+    //[mir]~^^ ERROR [E0509]
+}
+
+fn main() { }
diff --git a/src/test/ui/borrowck/borrowck-swap-mut-base-ptr.nll.stderr b/src/test/ui/borrowck/borrowck-swap-mut-base-ptr.nll.stderr
new file mode 100644
index 0000000..1c55953
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-swap-mut-base-ptr.nll.stderr
@@ -0,0 +1,14 @@
+error[E0502]: cannot borrow `t0` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-swap-mut-base-ptr.rs:13:10
+   |
+LL |     let p: &isize = &*t0;     // Freezes `*t0`
+   |                     ---- immutable borrow occurs here
+LL |     swap(&mut t0, &mut t1);
+   |          ^^^^^^^ mutable borrow occurs here
+LL |     *t1 = 22;
+LL |     p.use_ref();
+   |     - immutable borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/borrowck/borrowck-swap-mut-base-ptr.rs b/src/test/ui/borrowck/borrowck-swap-mut-base-ptr.rs
new file mode 100644
index 0000000..3d40d31
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-swap-mut-base-ptr.rs
@@ -0,0 +1,22 @@
+// Test that attempt to swap `&mut` pointer while pointee is borrowed
+// yields an error.
+//
+// Example from src/librustc_borrowck/borrowck/README.md
+
+use std::mem::swap;
+
+
+
+fn foo<'a>(mut t0: &'a mut isize,
+           mut t1: &'a mut isize) {
+    let p: &isize = &*t0;     // Freezes `*t0`
+    swap(&mut t0, &mut t1); //~ ERROR cannot borrow `t0`
+    *t1 = 22;
+    p.use_ref();
+}
+
+fn main() {
+}
+
+trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { }  }
+impl<T> Fake for T { }
diff --git a/src/test/ui/borrowck/borrowck-swap-mut-base-ptr.stderr b/src/test/ui/borrowck/borrowck-swap-mut-base-ptr.stderr
new file mode 100644
index 0000000..9efd249
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-swap-mut-base-ptr.stderr
@@ -0,0 +1,14 @@
+error[E0502]: cannot borrow `t0` as mutable because `*t0` is also borrowed as immutable
+  --> $DIR/borrowck-swap-mut-base-ptr.rs:13:15
+   |
+LL |     let p: &isize = &*t0;     // Freezes `*t0`
+   |                      --- immutable borrow occurs here
+LL |     swap(&mut t0, &mut t1);
+   |               ^^ mutable borrow occurs here
+...
+LL | }
+   | - immutable borrow ends here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/borrowck/borrowck-thread-local-static-borrow-outlives-fn.ast.nll.stderr b/src/test/ui/borrowck/borrowck-thread-local-static-borrow-outlives-fn.ast.nll.stderr
new file mode 100644
index 0000000..d2b6e06
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-thread-local-static-borrow-outlives-fn.ast.nll.stderr
@@ -0,0 +1,12 @@
+error[E0712]: thread-local variable borrowed past end of function
+  --> $DIR/borrowck-thread-local-static-borrow-outlives-fn.rs:11:20
+   |
+LL |      assert_static(&FOO);
+   |                    ^^^^ thread-local variables cannot be borrowed beyond the end of the function
+LL |
+LL | }
+   | - end of enclosing function is here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0712`.
diff --git a/src/test/ui/borrowck/borrowck-thread-local-static-borrow-outlives-fn.ast.stderr b/src/test/ui/borrowck/borrowck-thread-local-static-borrow-outlives-fn.ast.stderr
new file mode 100644
index 0000000..ce7b5e6
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-thread-local-static-borrow-outlives-fn.ast.stderr
@@ -0,0 +1,13 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/borrowck-thread-local-static-borrow-outlives-fn.rs:11:21
+   |
+LL |      assert_static(&FOO);
+   |                     ^^^ - borrowed value only lives until here
+   |                     |
+   |                     borrowed value does not live long enough
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/borrowck/borrowck-thread-local-static-borrow-outlives-fn.mir.stderr b/src/test/ui/borrowck/borrowck-thread-local-static-borrow-outlives-fn.mir.stderr
new file mode 100644
index 0000000..d2b6e06
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-thread-local-static-borrow-outlives-fn.mir.stderr
@@ -0,0 +1,12 @@
+error[E0712]: thread-local variable borrowed past end of function
+  --> $DIR/borrowck-thread-local-static-borrow-outlives-fn.rs:11:20
+   |
+LL |      assert_static(&FOO);
+   |                    ^^^^ thread-local variables cannot be borrowed beyond the end of the function
+LL |
+LL | }
+   | - end of enclosing function is here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0712`.
diff --git a/src/test/ui/borrowck/borrowck-thread-local-static-borrow-outlives-fn.rs b/src/test/ui/borrowck/borrowck-thread-local-static-borrow-outlives-fn.rs
new file mode 100644
index 0000000..6fd6acc
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-thread-local-static-borrow-outlives-fn.rs
@@ -0,0 +1,13 @@
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+#![feature(thread_local)]
+
+#[thread_local]
+static FOO: u8 = 3;
+
+fn assert_static(_t: &'static u8) {}
+fn main() {
+     assert_static(&FOO); //[ast]~ ERROR [E0597]
+                          //[mir]~^ ERROR [E0712]
+}
diff --git a/src/test/ui/borrowck/borrowck-unary-move.ast.nll.stderr b/src/test/ui/borrowck/borrowck-unary-move.ast.nll.stderr
new file mode 100644
index 0000000..c29ff53
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-unary-move.ast.nll.stderr
@@ -0,0 +1,14 @@
+error[E0505]: cannot move out of `x` because it is borrowed
+  --> $DIR/borrowck-unary-move.rs:7:10
+   |
+LL |     let y = &*x;
+   |             --- borrow of `*x` occurs here
+LL |     free(x);
+   |          ^ move out of `x` occurs here
+LL |
+LL |     *y
+   |     -- borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0505`.
diff --git a/src/test/ui/borrowck/borrowck-unary-move.ast.stderr b/src/test/ui/borrowck/borrowck-unary-move.ast.stderr
new file mode 100644
index 0000000..e05b110
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-unary-move.ast.stderr
@@ -0,0 +1,11 @@
+error[E0505]: cannot move out of `x` because it is borrowed
+  --> $DIR/borrowck-unary-move.rs:7:10
+   |
+LL |     let y = &*x;
+   |              -- borrow of `*x` occurs here
+LL |     free(x);
+   |          ^ move out of `x` occurs here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0505`.
diff --git a/src/test/ui/borrowck/borrowck-unary-move.mir.stderr b/src/test/ui/borrowck/borrowck-unary-move.mir.stderr
new file mode 100644
index 0000000..c29ff53
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-unary-move.mir.stderr
@@ -0,0 +1,14 @@
+error[E0505]: cannot move out of `x` because it is borrowed
+  --> $DIR/borrowck-unary-move.rs:7:10
+   |
+LL |     let y = &*x;
+   |             --- borrow of `*x` occurs here
+LL |     free(x);
+   |          ^ move out of `x` occurs here
+LL |
+LL |     *y
+   |     -- borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0505`.
diff --git a/src/test/ui/borrowck/borrowck-unary-move.rs b/src/test/ui/borrowck/borrowck-unary-move.rs
new file mode 100644
index 0000000..4e023ac
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-unary-move.rs
@@ -0,0 +1,16 @@
+// ignore-tidy-linelength
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+fn foo(x: Box<isize>) -> isize {
+    let y = &*x;
+    free(x); //[ast]~ ERROR cannot move out of `x` because it is borrowed
+    //[mir]~^ ERROR cannot move out of `x` because it is borrowed
+    *y
+}
+
+fn free(_x: Box<isize>) {
+}
+
+fn main() {
+}
diff --git a/src/test/ui/borrowck/borrowck-unboxed-closures.nll.stderr b/src/test/ui/borrowck/borrowck-unboxed-closures.nll.stderr
new file mode 100644
index 0000000..ec1cf4a
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-unboxed-closures.nll.stderr
@@ -0,0 +1,34 @@
+error[E0502]: cannot borrow `f` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-unboxed-closures.rs:3:5
+   |
+LL |     let g = &mut f;
+   |             ------ mutable borrow occurs here
+LL |     f(1, 2);
+   |     ^ immutable borrow occurs here
+LL |     use_mut(g);
+   |             - mutable borrow later used here
+
+error[E0596]: cannot borrow `f` as mutable, as it is not declared as mutable
+  --> $DIR/borrowck-unboxed-closures.rs:7:5
+   |
+LL | fn b<F:FnMut(isize, isize) -> isize>(f: F) {
+   |                                      - help: consider changing this to be mutable: `mut f`
+LL |     f(1, 2);
+   |     ^ cannot borrow as mutable
+
+error[E0382]: use of moved value: `f`
+  --> $DIR/borrowck-unboxed-closures.rs:12:5
+   |
+LL | fn c<F:FnOnce(isize, isize) -> isize>(f: F) {
+   |      -                                - move occurs because `f` has type `F`, which does not implement the `Copy` trait
+   |      |
+   |      consider adding a `Copy` constraint to this type argument
+LL |     f(1, 2);
+   |     - value moved here
+LL |     f(1, 2);
+   |     ^ value used here after move
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0382, E0502, E0596.
+For more information about an error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/borrowck-unboxed-closures.rs b/src/test/ui/borrowck/borrowck-unboxed-closures.rs
new file mode 100644
index 0000000..bfd0fbb
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-unboxed-closures.rs
@@ -0,0 +1,17 @@
+fn a<F:Fn(isize, isize) -> isize>(mut f: F) {
+    let g = &mut f;
+    f(1, 2);    //~ ERROR cannot borrow `f` as immutable
+    use_mut(g);
+}
+fn b<F:FnMut(isize, isize) -> isize>(f: F) {
+    f(1, 2);    //~ ERROR cannot borrow immutable argument
+}
+
+fn c<F:FnOnce(isize, isize) -> isize>(f: F) {
+    f(1, 2);
+    f(1, 2);    //~ ERROR use of moved value
+}
+
+fn main() {}
+
+fn use_mut<T>(_: &mut T) { }
diff --git a/src/test/ui/borrowck/borrowck-unboxed-closures.stderr b/src/test/ui/borrowck/borrowck-unboxed-closures.stderr
new file mode 100644
index 0000000..2e0773a
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-unboxed-closures.stderr
@@ -0,0 +1,33 @@
+error[E0502]: cannot borrow `f` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-unboxed-closures.rs:3:5
+   |
+LL |     let g = &mut f;
+   |                  - mutable borrow occurs here
+LL |     f(1, 2);
+   |     ^ immutable borrow occurs here
+LL |     use_mut(g);
+LL | }
+   | - mutable borrow ends here
+
+error[E0596]: cannot borrow immutable argument `f` as mutable
+  --> $DIR/borrowck-unboxed-closures.rs:7:5
+   |
+LL | fn b<F:FnMut(isize, isize) -> isize>(f: F) {
+   |                                      - help: make this binding mutable: `mut f`
+LL |     f(1, 2);
+   |     ^ cannot borrow mutably
+
+error[E0382]: use of moved value: `f`
+  --> $DIR/borrowck-unboxed-closures.rs:12:5
+   |
+LL |     f(1, 2);
+   |     - value moved here
+LL |     f(1, 2);
+   |     ^ value used here after move
+   |
+   = note: move occurs because `f` has type `F`, which does not implement the `Copy` trait
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0382, E0502, E0596.
+For more information about an error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/borrowck-uninit-after-item.rs b/src/test/ui/borrowck/borrowck-uninit-after-item.rs
new file mode 100644
index 0000000..83f3752
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-uninit-after-item.rs
@@ -0,0 +1,5 @@
+fn main() {
+    let bar;
+    fn baz(_x: isize) { }
+    baz(bar); //~ ERROR use of possibly uninitialized variable: `bar`
+}
diff --git a/src/test/ui/borrowck/borrowck-uninit-after-item.stderr b/src/test/ui/borrowck/borrowck-uninit-after-item.stderr
new file mode 100644
index 0000000..2d0b21d
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-uninit-after-item.stderr
@@ -0,0 +1,9 @@
+error[E0381]: use of possibly uninitialized variable: `bar`
+  --> $DIR/borrowck-uninit-after-item.rs:4:9
+   |
+LL |     baz(bar);
+   |         ^^^ use of possibly uninitialized `bar`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/borrowck-uninit-field-access.ast.nll.stderr b/src/test/ui/borrowck/borrowck-uninit-field-access.ast.nll.stderr
new file mode 100644
index 0000000..a6e5f0b
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-uninit-field-access.ast.nll.stderr
@@ -0,0 +1,30 @@
+error[E0381]: use of possibly uninitialized variable: `a`
+  --> $DIR/borrowck-uninit-field-access.rs:24:13
+   |
+LL |     let _ = a.x + 1;
+   |             ^^^ use of possibly uninitialized `a.x`
+
+error[E0382]: use of moved value: `line1.origin`
+  --> $DIR/borrowck-uninit-field-access.rs:29:13
+   |
+LL |     let _moved = line1.origin;
+   |                  ------------ value moved here
+LL |     let _ = line1.origin.x + 1;
+   |             ^^^^^^^^^^^^^^ value used here after move
+   |
+   = note: move occurs because `line1.origin` has type `Point`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `line2`
+  --> $DIR/borrowck-uninit-field-access.rs:34:5
+   |
+LL |     let _moved = (line2.origin, line2.middle);
+   |                                 ------------ value moved here
+LL |     line2.consume();
+   |     ^^^^^ value used here after partial move
+   |
+   = note: move occurs because `line2.middle` has type `Point`, which does not implement the `Copy` trait
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0381, E0382.
+For more information about an error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/borrowck-uninit-field-access.ast.stderr b/src/test/ui/borrowck/borrowck-uninit-field-access.ast.stderr
new file mode 100644
index 0000000..58fc1d4
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-uninit-field-access.ast.stderr
@@ -0,0 +1,30 @@
+error[E0381]: use of possibly uninitialized variable: `a.x`
+  --> $DIR/borrowck-uninit-field-access.rs:24:13
+   |
+LL |     let _ = a.x + 1;
+   |             ^^^ use of possibly uninitialized `a.x`
+
+error[E0382]: use of moved value: `line1.origin.x`
+  --> $DIR/borrowck-uninit-field-access.rs:29:13
+   |
+LL |     let _moved = line1.origin;
+   |         ------ value moved here
+LL |     let _ = line1.origin.x + 1;
+   |             ^^^^^^^^^^^^^^ value used here after move
+   |
+   = note: move occurs because `line1.origin` has type `Point`, which does not implement the `Copy` trait
+
+error[E0382]: use of partially moved value: `line2`
+  --> $DIR/borrowck-uninit-field-access.rs:34:5
+   |
+LL |     let _moved = (line2.origin, line2.middle);
+   |                   ------------ value moved here
+LL |     line2.consume();
+   |     ^^^^^ value used here after move
+   |
+   = note: move occurs because `line2.origin` has type `Point`, which does not implement the `Copy` trait
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0381, E0382.
+For more information about an error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/borrowck-uninit-field-access.mir.stderr b/src/test/ui/borrowck/borrowck-uninit-field-access.mir.stderr
new file mode 100644
index 0000000..a6e5f0b
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-uninit-field-access.mir.stderr
@@ -0,0 +1,30 @@
+error[E0381]: use of possibly uninitialized variable: `a`
+  --> $DIR/borrowck-uninit-field-access.rs:24:13
+   |
+LL |     let _ = a.x + 1;
+   |             ^^^ use of possibly uninitialized `a.x`
+
+error[E0382]: use of moved value: `line1.origin`
+  --> $DIR/borrowck-uninit-field-access.rs:29:13
+   |
+LL |     let _moved = line1.origin;
+   |                  ------------ value moved here
+LL |     let _ = line1.origin.x + 1;
+   |             ^^^^^^^^^^^^^^ value used here after move
+   |
+   = note: move occurs because `line1.origin` has type `Point`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `line2`
+  --> $DIR/borrowck-uninit-field-access.rs:34:5
+   |
+LL |     let _moved = (line2.origin, line2.middle);
+   |                                 ------------ value moved here
+LL |     line2.consume();
+   |     ^^^^^ value used here after partial move
+   |
+   = note: move occurs because `line2.middle` has type `Point`, which does not implement the `Copy` trait
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0381, E0382.
+For more information about an error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/borrowck-uninit-field-access.rs b/src/test/ui/borrowck/borrowck-uninit-field-access.rs
new file mode 100644
index 0000000..ab19b2d
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-uninit-field-access.rs
@@ -0,0 +1,36 @@
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+// Check that do not allow access to fields of uninitialized or moved
+// structs.
+
+#[derive(Default)]
+struct Point {
+    x: isize,
+    y: isize,
+}
+
+#[derive(Default)]
+struct Line {
+    origin: Point,
+    middle: Point,
+    target: Point,
+}
+
+impl Line { fn consume(self) { } }
+
+fn main() {
+    let mut a: Point;
+    let _ = a.x + 1; //[ast]~ ERROR use of possibly uninitialized variable: `a.x`
+                     //[mir]~^ ERROR [E0381]
+
+    let mut line1 = Line::default();
+    let _moved = line1.origin;
+    let _ = line1.origin.x + 1; //[ast]~ ERROR use of moved value: `line1.origin.x`
+                                //[mir]~^ [E0382]
+
+    let mut line2 = Line::default();
+    let _moved = (line2.origin, line2.middle);
+    line2.consume(); //[ast]~ ERROR use of partially moved value: `line2` [E0382]
+                     //[mir]~^ [E0382]
+}
diff --git a/src/test/ui/borrowck/borrowck-uninit-in-assignop.rs b/src/test/ui/borrowck/borrowck-uninit-in-assignop.rs
new file mode 100644
index 0000000..bfb0dd4
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-uninit-in-assignop.rs
@@ -0,0 +1,34 @@
+// Tests that the use of uninitialized variable in assignment operator
+// expression is detected.
+
+pub fn main() {
+    let x: isize;
+    x += 1; //~ ERROR use of possibly uninitialized variable: `x`
+
+    let x: isize;
+    x -= 1; //~ ERROR use of possibly uninitialized variable: `x`
+
+    let x: isize;
+    x *= 1; //~ ERROR use of possibly uninitialized variable: `x`
+
+    let x: isize;
+    x /= 1; //~ ERROR use of possibly uninitialized variable: `x`
+
+    let x: isize;
+    x %= 1; //~ ERROR use of possibly uninitialized variable: `x`
+
+    let x: isize;
+    x ^= 1; //~ ERROR use of possibly uninitialized variable: `x`
+
+    let x: isize;
+    x &= 1; //~ ERROR use of possibly uninitialized variable: `x`
+
+    let x: isize;
+    x |= 1; //~ ERROR use of possibly uninitialized variable: `x`
+
+    let x: isize;
+    x <<= 1;    //~ ERROR use of possibly uninitialized variable: `x`
+
+    let x: isize;
+    x >>= 1;    //~ ERROR use of possibly uninitialized variable: `x`
+}
diff --git a/src/test/ui/borrowck/borrowck-uninit-in-assignop.stderr b/src/test/ui/borrowck/borrowck-uninit-in-assignop.stderr
new file mode 100644
index 0000000..163395e
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-uninit-in-assignop.stderr
@@ -0,0 +1,63 @@
+error[E0381]: use of possibly uninitialized variable: `x`
+  --> $DIR/borrowck-uninit-in-assignop.rs:6:5
+   |
+LL |     x += 1;
+   |     ^^^^^^ use of possibly uninitialized `x`
+
+error[E0381]: use of possibly uninitialized variable: `x`
+  --> $DIR/borrowck-uninit-in-assignop.rs:9:5
+   |
+LL |     x -= 1;
+   |     ^^^^^^ use of possibly uninitialized `x`
+
+error[E0381]: use of possibly uninitialized variable: `x`
+  --> $DIR/borrowck-uninit-in-assignop.rs:12:5
+   |
+LL |     x *= 1;
+   |     ^^^^^^ use of possibly uninitialized `x`
+
+error[E0381]: use of possibly uninitialized variable: `x`
+  --> $DIR/borrowck-uninit-in-assignop.rs:15:5
+   |
+LL |     x /= 1;
+   |     ^^^^^^ use of possibly uninitialized `x`
+
+error[E0381]: use of possibly uninitialized variable: `x`
+  --> $DIR/borrowck-uninit-in-assignop.rs:18:5
+   |
+LL |     x %= 1;
+   |     ^^^^^^ use of possibly uninitialized `x`
+
+error[E0381]: use of possibly uninitialized variable: `x`
+  --> $DIR/borrowck-uninit-in-assignop.rs:21:5
+   |
+LL |     x ^= 1;
+   |     ^^^^^^ use of possibly uninitialized `x`
+
+error[E0381]: use of possibly uninitialized variable: `x`
+  --> $DIR/borrowck-uninit-in-assignop.rs:24:5
+   |
+LL |     x &= 1;
+   |     ^^^^^^ use of possibly uninitialized `x`
+
+error[E0381]: use of possibly uninitialized variable: `x`
+  --> $DIR/borrowck-uninit-in-assignop.rs:27:5
+   |
+LL |     x |= 1;
+   |     ^^^^^^ use of possibly uninitialized `x`
+
+error[E0381]: use of possibly uninitialized variable: `x`
+  --> $DIR/borrowck-uninit-in-assignop.rs:30:5
+   |
+LL |     x <<= 1;
+   |     ^^^^^^^ use of possibly uninitialized `x`
+
+error[E0381]: use of possibly uninitialized variable: `x`
+  --> $DIR/borrowck-uninit-in-assignop.rs:33:5
+   |
+LL |     x >>= 1;
+   |     ^^^^^^^ use of possibly uninitialized `x`
+
+error: aborting due to 10 previous errors
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/borrowck-uninit-ref-chain.ast.nll.stderr b/src/test/ui/borrowck/borrowck-uninit-ref-chain.ast.nll.stderr
new file mode 100644
index 0000000..a5cf59c
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-uninit-ref-chain.ast.nll.stderr
@@ -0,0 +1,45 @@
+error[E0381]: borrow of possibly uninitialized variable: `x`
+  --> $DIR/borrowck-uninit-ref-chain.rs:11:14
+   |
+LL |     let _y = &**x;
+   |              ^^^^ use of possibly uninitialized `**x`
+
+error[E0381]: borrow of possibly uninitialized variable: `x`
+  --> $DIR/borrowck-uninit-ref-chain.rs:15:14
+   |
+LL |     let _y = &**x;
+   |              ^^^^ use of possibly uninitialized `**x`
+
+error[E0381]: borrow of possibly uninitialized variable: `x`
+  --> $DIR/borrowck-uninit-ref-chain.rs:19:14
+   |
+LL |     let _y = &**x;
+   |              ^^^^ use of possibly uninitialized `**x`
+
+error[E0381]: assign to part of possibly uninitialized variable: `a`
+  --> $DIR/borrowck-uninit-ref-chain.rs:24:5
+   |
+LL |     a.x = 0;
+   |     ^^^^^^^ use of possibly uninitialized `a`
+
+error[E0381]: assign to part of possibly uninitialized variable: `a`
+  --> $DIR/borrowck-uninit-ref-chain.rs:29:5
+   |
+LL |     a.x = &&0;
+   |     ^^^^^^^^^ use of possibly uninitialized `a`
+
+error[E0381]: assign to part of possibly uninitialized variable: `a`
+  --> $DIR/borrowck-uninit-ref-chain.rs:35:5
+   |
+LL |     a.x = 0;
+   |     ^^^^^^^ use of possibly uninitialized `a`
+
+error[E0381]: assign to part of possibly uninitialized variable: `a`
+  --> $DIR/borrowck-uninit-ref-chain.rs:40:5
+   |
+LL |     a.x = &&0;
+   |     ^^^^^^^^^ use of possibly uninitialized `a`
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/borrowck-uninit-ref-chain.ast.stderr b/src/test/ui/borrowck/borrowck-uninit-ref-chain.ast.stderr
new file mode 100644
index 0000000..8cb3f3b
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-uninit-ref-chain.ast.stderr
@@ -0,0 +1,45 @@
+error[E0381]: use of possibly uninitialized variable: `**x`
+  --> $DIR/borrowck-uninit-ref-chain.rs:11:15
+   |
+LL |     let _y = &**x;
+   |               ^^^ use of possibly uninitialized `**x`
+
+error[E0381]: use of possibly uninitialized variable: `**x`
+  --> $DIR/borrowck-uninit-ref-chain.rs:15:15
+   |
+LL |     let _y = &**x;
+   |               ^^^ use of possibly uninitialized `**x`
+
+error[E0381]: use of possibly uninitialized variable: `**x`
+  --> $DIR/borrowck-uninit-ref-chain.rs:19:15
+   |
+LL |     let _y = &**x;
+   |               ^^^ use of possibly uninitialized `**x`
+
+error[E0381]: use of possibly uninitialized variable: `a.x`
+  --> $DIR/borrowck-uninit-ref-chain.rs:25:15
+   |
+LL |     let _b = &a.x;
+   |               ^^^ use of possibly uninitialized `a.x`
+
+error[E0381]: use of possibly uninitialized variable: `**a.x`
+  --> $DIR/borrowck-uninit-ref-chain.rs:30:15
+   |
+LL |     let _b = &**a.x;
+   |               ^^^^^ use of possibly uninitialized `**a.x`
+
+error[E0381]: use of possibly uninitialized variable: `a.y`
+  --> $DIR/borrowck-uninit-ref-chain.rs:36:15
+   |
+LL |     let _b = &a.y;
+   |               ^^^ use of possibly uninitialized `a.y`
+
+error[E0381]: use of possibly uninitialized variable: `**a.y`
+  --> $DIR/borrowck-uninit-ref-chain.rs:41:15
+   |
+LL |     let _b = &**a.y;
+   |               ^^^^^ use of possibly uninitialized `**a.y`
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/borrowck-uninit-ref-chain.mir.stderr b/src/test/ui/borrowck/borrowck-uninit-ref-chain.mir.stderr
new file mode 100644
index 0000000..a5cf59c
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-uninit-ref-chain.mir.stderr
@@ -0,0 +1,45 @@
+error[E0381]: borrow of possibly uninitialized variable: `x`
+  --> $DIR/borrowck-uninit-ref-chain.rs:11:14
+   |
+LL |     let _y = &**x;
+   |              ^^^^ use of possibly uninitialized `**x`
+
+error[E0381]: borrow of possibly uninitialized variable: `x`
+  --> $DIR/borrowck-uninit-ref-chain.rs:15:14
+   |
+LL |     let _y = &**x;
+   |              ^^^^ use of possibly uninitialized `**x`
+
+error[E0381]: borrow of possibly uninitialized variable: `x`
+  --> $DIR/borrowck-uninit-ref-chain.rs:19:14
+   |
+LL |     let _y = &**x;
+   |              ^^^^ use of possibly uninitialized `**x`
+
+error[E0381]: assign to part of possibly uninitialized variable: `a`
+  --> $DIR/borrowck-uninit-ref-chain.rs:24:5
+   |
+LL |     a.x = 0;
+   |     ^^^^^^^ use of possibly uninitialized `a`
+
+error[E0381]: assign to part of possibly uninitialized variable: `a`
+  --> $DIR/borrowck-uninit-ref-chain.rs:29:5
+   |
+LL |     a.x = &&0;
+   |     ^^^^^^^^^ use of possibly uninitialized `a`
+
+error[E0381]: assign to part of possibly uninitialized variable: `a`
+  --> $DIR/borrowck-uninit-ref-chain.rs:35:5
+   |
+LL |     a.x = 0;
+   |     ^^^^^^^ use of possibly uninitialized `a`
+
+error[E0381]: assign to part of possibly uninitialized variable: `a`
+  --> $DIR/borrowck-uninit-ref-chain.rs:40:5
+   |
+LL |     a.x = &&0;
+   |     ^^^^^^^^^ use of possibly uninitialized `a`
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/borrowck-uninit-ref-chain.rs b/src/test/ui/borrowck/borrowck-uninit-ref-chain.rs
new file mode 100644
index 0000000..562012a
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-uninit-ref-chain.rs
@@ -0,0 +1,43 @@
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+struct S<X, Y> {
+    x: X,
+    y: Y,
+}
+
+fn main() {
+    let x: &&Box<i32>;
+    let _y = &**x; //[ast]~ ERROR use of possibly uninitialized variable: `**x` [E0381]
+                   //[mir]~^ [E0381]
+
+    let x: &&S<i32, i32>;
+    let _y = &**x; //[ast]~ ERROR use of possibly uninitialized variable: `**x` [E0381]
+                   //[mir]~^ [E0381]
+
+    let x: &&i32;
+    let _y = &**x; //[ast]~ ERROR use of possibly uninitialized variable: `**x` [E0381]
+                   //[mir]~^ [E0381]
+
+
+    let mut a: S<i32, i32>;
+    a.x = 0;       //[mir]~ ERROR assign to part of possibly uninitialized variable: `a` [E0381]
+    let _b = &a.x; //[ast]~ ERROR use of possibly uninitialized variable: `a.x` [E0381]
+
+
+    let mut a: S<&&i32, &&i32>;
+    a.x = &&0;       //[mir]~ ERROR assign to part of possibly uninitialized variable: `a` [E0381]
+    let _b = &**a.x; //[ast]~ ERROR use of possibly uninitialized variable: `**a.x` [E0381]
+
+
+
+    let mut a: S<i32, i32>;
+    a.x = 0;       //[mir]~ ERROR assign to part of possibly uninitialized variable: `a` [E0381]
+    let _b = &a.y; //[ast]~ ERROR use of possibly uninitialized variable: `a.y` [E0381]
+
+
+    let mut a: S<&&i32, &&i32>;
+    a.x = &&0;       //[mir]~ assign to part of possibly uninitialized variable: `a` [E0381]
+    let _b = &**a.y; //[ast]~ ERROR use of possibly uninitialized variable: `**a.y` [E0381]
+
+}
diff --git a/src/test/ui/borrowck/borrowck-uninit.rs b/src/test/ui/borrowck/borrowck-uninit.rs
new file mode 100644
index 0000000..71c1f59
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-uninit.rs
@@ -0,0 +1,6 @@
+fn foo(x: isize) { println!("{}", x); }
+
+fn main() {
+    let x: isize;
+    foo(x); //~ ERROR use of possibly uninitialized variable: `x`
+}
diff --git a/src/test/ui/borrowck/borrowck-uninit.stderr b/src/test/ui/borrowck/borrowck-uninit.stderr
new file mode 100644
index 0000000..5db9c1b
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-uninit.stderr
@@ -0,0 +1,9 @@
+error[E0381]: use of possibly uninitialized variable: `x`
+  --> $DIR/borrowck-uninit.rs:5:9
+   |
+LL |     foo(x);
+   |         ^ use of possibly uninitialized `x`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/borrowck-union-borrow-nested.nll.stderr b/src/test/ui/borrowck/borrowck-union-borrow-nested.nll.stderr
new file mode 100644
index 0000000..61569b9
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-union-borrow-nested.nll.stderr
@@ -0,0 +1,13 @@
+error[E0503]: cannot use `u.c` because it was mutably borrowed
+  --> $DIR/borrowck-union-borrow-nested.rs:24:21
+   |
+LL |             let ra = &mut u.s.a;
+   |                      ---------- borrow of `u.s.a` occurs here
+LL |             let b = u.c;
+   |                     ^^^ use of borrowed `u.s.a`
+LL |             ra.use_mut();
+   |             -- borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0503`.
diff --git a/src/test/ui/borrowck/borrowck-union-borrow-nested.rs b/src/test/ui/borrowck/borrowck-union-borrow-nested.rs
new file mode 100644
index 0000000..b3a6670
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-union-borrow-nested.rs
@@ -0,0 +1,31 @@
+#[derive(Clone, Copy)]
+struct S {
+    a: u8,
+    b: u16,
+}
+
+#[derive(Clone, Copy)]
+union U {
+    s: S,
+    c: u32,
+}
+
+fn main() {
+    unsafe {
+        {
+            let mut u = U { s: S { a: 0, b: 1 } };
+            let ra = &mut u.s.a;
+            let b = u.s.b; // OK
+            ra.use_mut();
+        }
+        {
+            let mut u = U { s: S { a: 0, b: 1 } };
+            let ra = &mut u.s.a;
+            let b = u.c; //~ ERROR cannot use `u.c` because it was mutably borrowed
+            ra.use_mut();
+        }
+    }
+}
+
+trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { }  }
+impl<T> Fake for T { }
diff --git a/src/test/ui/borrowck/borrowck-union-borrow-nested.stderr b/src/test/ui/borrowck/borrowck-union-borrow-nested.stderr
new file mode 100644
index 0000000..71fae6f
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-union-borrow-nested.stderr
@@ -0,0 +1,11 @@
+error[E0503]: cannot use `u.c` because it was mutably borrowed
+  --> $DIR/borrowck-union-borrow-nested.rs:24:17
+   |
+LL |             let ra = &mut u.s.a;
+   |                           ----- borrow of `u.s.a` occurs here
+LL |             let b = u.c;
+   |                 ^ use of borrowed `u.s.a`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0503`.
diff --git a/src/test/ui/borrowck/borrowck-union-borrow.nll.stderr b/src/test/ui/borrowck/borrowck-union-borrow.nll.stderr
new file mode 100644
index 0000000..518f062
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-union-borrow.nll.stderr
@@ -0,0 +1,131 @@
+error[E0502]: cannot borrow `u.a` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-union-borrow.rs:25:23
+   |
+LL |             let ra = &u.a;
+   |                      ---- immutable borrow occurs here
+LL |             let rma = &mut u.a;
+   |                       ^^^^^^^^ mutable borrow occurs here
+LL |             drop(ra);
+   |                  -- immutable borrow later used here
+
+error[E0506]: cannot assign to `u.a` because it is borrowed
+  --> $DIR/borrowck-union-borrow.rs:30:13
+   |
+LL |             let ra = &u.a;
+   |                      ---- borrow of `u.a` occurs here
+LL |             u.a = 1;
+   |             ^^^^^^^ assignment to borrowed `u.a` occurs here
+LL |             drop(ra);
+   |                  -- borrow later used here
+
+error[E0502]: cannot borrow `u` (via `u.b`) as mutable because it is also borrowed as immutable (via `u.a`)
+  --> $DIR/borrowck-union-borrow.rs:46:23
+   |
+LL |             let ra = &u.a;
+   |                      ---- immutable borrow occurs here (via `u.a`)
+LL |             let rmb = &mut u.b;
+   |                       ^^^^^^^^ mutable borrow of `u.b` -- which overlaps with `u.a` -- occurs here
+LL |             drop(ra);
+   |                  -- immutable borrow later used here
+   |
+   = note: `u.b` is a field of the union `U`, so it overlaps the field `u.a`
+
+error[E0506]: cannot assign to `u.b` because it is borrowed
+  --> $DIR/borrowck-union-borrow.rs:51:13
+   |
+LL |             let ra = &u.a;
+   |                      ---- borrow of `u.b` occurs here
+LL |             u.b = 1;
+   |             ^^^^^^^ assignment to borrowed `u.b` occurs here
+LL |             drop(ra);
+   |                  -- borrow later used here
+
+error[E0502]: cannot borrow `u.a` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-union-borrow.rs:57:22
+   |
+LL |             let rma = &mut u.a;
+   |                       -------- mutable borrow occurs here
+LL |             let ra = &u.a;
+   |                      ^^^^ immutable borrow occurs here
+LL |             drop(rma);
+   |                  --- mutable borrow later used here
+
+error[E0503]: cannot use `u.a` because it was mutably borrowed
+  --> $DIR/borrowck-union-borrow.rs:62:21
+   |
+LL |             let ra = &mut u.a;
+   |                      -------- borrow of `u.a` occurs here
+LL |             let a = u.a;
+   |                     ^^^ use of borrowed `u.a`
+LL |             drop(ra);
+   |                  -- borrow later used here
+
+error[E0499]: cannot borrow `u.a` as mutable more than once at a time
+  --> $DIR/borrowck-union-borrow.rs:67:24
+   |
+LL |             let rma = &mut u.a;
+   |                       -------- first mutable borrow occurs here
+LL |             let rma2 = &mut u.a;
+   |                        ^^^^^^^^ second mutable borrow occurs here
+LL |             drop(rma);
+   |                  --- first borrow later used here
+
+error[E0506]: cannot assign to `u.a` because it is borrowed
+  --> $DIR/borrowck-union-borrow.rs:72:13
+   |
+LL |             let rma = &mut u.a;
+   |                       -------- borrow of `u.a` occurs here
+LL |             u.a = 1;
+   |             ^^^^^^^ assignment to borrowed `u.a` occurs here
+LL |             drop(rma);
+   |                  --- borrow later used here
+
+error[E0502]: cannot borrow `u` (via `u.b`) as immutable because it is also borrowed as mutable (via `u.a`)
+  --> $DIR/borrowck-union-borrow.rs:78:22
+   |
+LL |             let rma = &mut u.a;
+   |                       -------- mutable borrow occurs here (via `u.a`)
+LL |             let rb = &u.b;
+   |                      ^^^^ immutable borrow of `u.b` -- which overlaps with `u.a` -- occurs here
+LL |             drop(rma);
+   |                  --- mutable borrow later used here
+   |
+   = note: `u.b` is a field of the union `U`, so it overlaps the field `u.a`
+
+error[E0503]: cannot use `u.b` because it was mutably borrowed
+  --> $DIR/borrowck-union-borrow.rs:83:21
+   |
+LL |             let ra = &mut u.a;
+   |                      -------- borrow of `u.a` occurs here
+LL |             let b = u.b;
+   |                     ^^^ use of borrowed `u.a`
+LL | 
+LL |             drop(ra);
+   |                  -- borrow later used here
+
+error[E0499]: cannot borrow `u` (via `u.b`) as mutable more than once at a time
+  --> $DIR/borrowck-union-borrow.rs:89:24
+   |
+LL |             let rma = &mut u.a;
+   |                       -------- first mutable borrow occurs here (via `u.a`)
+LL |             let rmb2 = &mut u.b;
+   |                        ^^^^^^^^ second mutable borrow occurs here (via `u.b`)
+LL |             drop(rma);
+   |                  --- first borrow later used here
+   |
+   = note: `u.b` is a field of the union `U`, so it overlaps the field `u.a`
+
+error[E0506]: cannot assign to `u.b` because it is borrowed
+  --> $DIR/borrowck-union-borrow.rs:94:13
+   |
+LL |             let rma = &mut u.a;
+   |                       -------- borrow of `u.b` occurs here
+LL |             u.b = 1;
+   |             ^^^^^^^ assignment to borrowed `u.b` occurs here
+LL |             drop(rma);
+   |                  --- borrow later used here
+
+error: aborting due to 12 previous errors
+
+Some errors occurred: E0499, E0502, E0503, E0506.
+For more information about an error, try `rustc --explain E0499`.
diff --git a/src/test/ui/borrowck/borrowck-union-borrow.rs b/src/test/ui/borrowck/borrowck-union-borrow.rs
new file mode 100644
index 0000000..8afc0be
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-union-borrow.rs
@@ -0,0 +1,98 @@
+// ignore-tidy-linelength
+
+#[derive(Clone, Copy)]
+union U {
+    a: u8,
+    b: u64,
+}
+
+fn main() {
+    unsafe {
+        let mut u = U { b: 0 };
+        // Imm borrow, same field
+        {
+            let ra = &u.a;
+            let ra2 = &u.a; // OK
+            drop(ra);
+        }
+        {
+            let ra = &u.a;
+            let a = u.a; // OK
+            drop(ra);
+        }
+        {
+            let ra = &u.a;
+            let rma = &mut u.a; //~ ERROR cannot borrow `u.a` as mutable because it is also borrowed as immutable
+            drop(ra);
+        }
+        {
+            let ra = &u.a;
+            u.a = 1; //~ ERROR cannot assign to `u.a` because it is borrowed
+            drop(ra);
+        }
+        // Imm borrow, other field
+        {
+            let ra = &u.a;
+            let rb = &u.b; // OK
+            drop(ra);
+        }
+        {
+            let ra = &u.a;
+            let b = u.b; // OK
+            drop(ra);
+        }
+        {
+            let ra = &u.a;
+            let rmb = &mut u.b; //~ ERROR cannot borrow `u` (via `u.b`) as mutable because `u` is also borrowed as immutable (via `u.a`)
+            drop(ra);
+        }
+        {
+            let ra = &u.a;
+            u.b = 1; //~ ERROR cannot assign to `u.b` because it is borrowed
+            drop(ra);
+        }
+        // Mut borrow, same field
+        {
+            let rma = &mut u.a;
+            let ra = &u.a; //~ ERROR cannot borrow `u.a` as immutable because it is also borrowed as mutable
+            drop(rma);
+        }
+        {
+            let ra = &mut u.a;
+            let a = u.a; //~ ERROR cannot use `u.a` because it was mutably borrowed
+            drop(ra);
+        }
+        {
+            let rma = &mut u.a;
+            let rma2 = &mut u.a; //~ ERROR cannot borrow `u.a` as mutable more than once at a time
+            drop(rma);
+        }
+        {
+            let rma = &mut u.a;
+            u.a = 1; //~ ERROR cannot assign to `u.a` because it is borrowed
+            drop(rma);
+        }
+        // Mut borrow, other field
+        {
+            let rma = &mut u.a;
+            let rb = &u.b; //~ ERROR cannot borrow `u` (via `u.b`) as immutable because `u` is also borrowed as mutable (via `u.a`)
+            drop(rma);
+        }
+        {
+            let ra = &mut u.a;
+            let b = u.b; //~ ERROR cannot use `u.b` because it was mutably borrowed
+
+            drop(ra);
+        }
+        {
+            let rma = &mut u.a;
+            let rmb2 = &mut u.b; //~ ERROR cannot borrow `u` (via `u.b`) as mutable more than once at a time
+            drop(rma);
+        }
+        {
+            let rma = &mut u.a;
+            u.b = 1; //~ ERROR cannot assign to `u.b` because it is borrowed
+            drop(rma);
+        }
+    }
+}
diff --git a/src/test/ui/borrowck/borrowck-union-borrow.stderr b/src/test/ui/borrowck/borrowck-union-borrow.stderr
new file mode 100644
index 0000000..1cda7e4
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-union-borrow.stderr
@@ -0,0 +1,118 @@
+error[E0502]: cannot borrow `u.a` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-union-borrow.rs:25:28
+   |
+LL |             let ra = &u.a;
+   |                       --- immutable borrow occurs here
+LL |             let rma = &mut u.a;
+   |                            ^^^ mutable borrow occurs here
+LL |             drop(ra);
+LL |         }
+   |         - immutable borrow ends here
+
+error[E0506]: cannot assign to `u.a` because it is borrowed
+  --> $DIR/borrowck-union-borrow.rs:30:13
+   |
+LL |             let ra = &u.a;
+   |                       --- borrow of `u.a` occurs here
+LL |             u.a = 1;
+   |             ^^^^^^^ assignment to borrowed `u.a` occurs here
+
+error[E0502]: cannot borrow `u` (via `u.b`) as mutable because `u` is also borrowed as immutable (via `u.a`)
+  --> $DIR/borrowck-union-borrow.rs:46:28
+   |
+LL |             let ra = &u.a;
+   |                       --- immutable borrow occurs here (via `u.a`)
+LL |             let rmb = &mut u.b;
+   |                            ^^^ mutable borrow of `u.b` -- which overlaps with `u.a` -- occurs here
+LL |             drop(ra);
+LL |         }
+   |         - immutable borrow ends here
+
+error[E0506]: cannot assign to `u.b` because it is borrowed
+  --> $DIR/borrowck-union-borrow.rs:51:13
+   |
+LL |             let ra = &u.a;
+   |                       --- borrow of `u.b` occurs here
+LL |             u.b = 1;
+   |             ^^^^^^^ assignment to borrowed `u.b` occurs here
+
+error[E0502]: cannot borrow `u.a` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-union-borrow.rs:57:23
+   |
+LL |             let rma = &mut u.a;
+   |                            --- mutable borrow occurs here
+LL |             let ra = &u.a;
+   |                       ^^^ immutable borrow occurs here
+LL |             drop(rma);
+LL |         }
+   |         - mutable borrow ends here
+
+error[E0503]: cannot use `u.a` because it was mutably borrowed
+  --> $DIR/borrowck-union-borrow.rs:62:17
+   |
+LL |             let ra = &mut u.a;
+   |                           --- borrow of `u.a` occurs here
+LL |             let a = u.a;
+   |                 ^ use of borrowed `u.a`
+
+error[E0499]: cannot borrow `u.a` as mutable more than once at a time
+  --> $DIR/borrowck-union-borrow.rs:67:29
+   |
+LL |             let rma = &mut u.a;
+   |                            --- first mutable borrow occurs here
+LL |             let rma2 = &mut u.a;
+   |                             ^^^ second mutable borrow occurs here
+LL |             drop(rma);
+LL |         }
+   |         - first borrow ends here
+
+error[E0506]: cannot assign to `u.a` because it is borrowed
+  --> $DIR/borrowck-union-borrow.rs:72:13
+   |
+LL |             let rma = &mut u.a;
+   |                            --- borrow of `u.a` occurs here
+LL |             u.a = 1;
+   |             ^^^^^^^ assignment to borrowed `u.a` occurs here
+
+error[E0502]: cannot borrow `u` (via `u.b`) as immutable because `u` is also borrowed as mutable (via `u.a`)
+  --> $DIR/borrowck-union-borrow.rs:78:23
+   |
+LL |             let rma = &mut u.a;
+   |                            --- mutable borrow occurs here (via `u.a`)
+LL |             let rb = &u.b;
+   |                       ^^^ immutable borrow of `u.b` -- which overlaps with `u.a` -- occurs here
+LL |             drop(rma);
+LL |         }
+   |         - mutable borrow ends here
+
+error[E0503]: cannot use `u.b` because it was mutably borrowed
+  --> $DIR/borrowck-union-borrow.rs:83:17
+   |
+LL |             let ra = &mut u.a;
+   |                           --- borrow of `u.a` occurs here
+LL |             let b = u.b;
+   |                 ^ use of borrowed `u.a`
+
+error[E0499]: cannot borrow `u` (via `u.b`) as mutable more than once at a time
+  --> $DIR/borrowck-union-borrow.rs:89:29
+   |
+LL |             let rma = &mut u.a;
+   |                            --- first mutable borrow occurs here (via `u.a`)
+LL |             let rmb2 = &mut u.b;
+   |                             ^^^ second mutable borrow occurs here (via `u.b`)
+LL |             drop(rma);
+LL |         }
+   |         - first borrow ends here
+
+error[E0506]: cannot assign to `u.b` because it is borrowed
+  --> $DIR/borrowck-union-borrow.rs:94:13
+   |
+LL |             let rma = &mut u.a;
+   |                            --- borrow of `u.b` occurs here
+LL |             u.b = 1;
+   |             ^^^^^^^ assignment to borrowed `u.b` occurs here
+
+error: aborting due to 12 previous errors
+
+Some errors occurred: E0499, E0502, E0503, E0506.
+For more information about an error, try `rustc --explain E0499`.
diff --git a/src/test/ui/borrowck/borrowck-union-move-assign.nll.stderr b/src/test/ui/borrowck/borrowck-union-move-assign.nll.stderr
new file mode 100644
index 0000000..0b1714f
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-union-move-assign.nll.stderr
@@ -0,0 +1,13 @@
+error[E0382]: use of moved value: `u`
+  --> $DIR/borrowck-union-move-assign.rs:17:21
+   |
+LL |             let mut u = U { a: A };
+   |                 ----- move occurs because `u` has type `U`, which does not implement the `Copy` trait
+LL |             let a = u.a;
+   |                     --- value moved here
+LL |             let a = u.a;
+   |                     ^^^ value used here after move
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/borrowck-union-move-assign.rs b/src/test/ui/borrowck/borrowck-union-move-assign.rs
new file mode 100644
index 0000000..1bb4325
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-union-move-assign.rs
@@ -0,0 +1,32 @@
+#![feature(untagged_unions)]
+
+// Non-copy
+struct A;
+struct B;
+
+union U {
+    a: A,
+    b: B,
+}
+
+fn main() {
+    unsafe {
+        {
+            let mut u = U { a: A };
+            let a = u.a;
+            let a = u.a; //~ ERROR use of moved value: `u.a`
+        }
+        {
+            let mut u = U { a: A };
+            let a = u.a;
+            u.a = A;
+            let a = u.a; // OK
+        }
+        {
+            let mut u = U { a: A };
+            let a = u.a;
+            u.b = B;
+            let a = u.a; // OK
+        }
+    }
+}
diff --git a/src/test/ui/borrowck/borrowck-union-move-assign.stderr b/src/test/ui/borrowck/borrowck-union-move-assign.stderr
new file mode 100644
index 0000000..04e67fc
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-union-move-assign.stderr
@@ -0,0 +1,13 @@
+error[E0382]: use of moved value: `u.a`
+  --> $DIR/borrowck-union-move-assign.rs:17:17
+   |
+LL |             let a = u.a;
+   |                 - value moved here
+LL |             let a = u.a;
+   |                 ^ value used here after move
+   |
+   = note: move occurs because `u.a` has type `A`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/borrowck-union-move.nll.stderr b/src/test/ui/borrowck/borrowck-union-move.nll.stderr
new file mode 100644
index 0000000..abbb014
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-union-move.nll.stderr
@@ -0,0 +1,63 @@
+error[E0382]: use of moved value: `u`
+  --> $DIR/borrowck-union-move.rs:26:21
+   |
+LL |             let mut u = Unn { n1: NonCopy };
+   |                 ----- move occurs because `u` has type `Unn`, which does not implement the `Copy` trait
+LL |             let a = u.n1;
+   |                     ---- value moved here
+LL |             let a = u.n1;
+   |                     ^^^^ value used here after move
+
+error[E0382]: use of moved value: `u`
+  --> $DIR/borrowck-union-move.rs:31:21
+   |
+LL |             let mut u = Unn { n1: NonCopy };
+   |                 ----- move occurs because `u` has type `Unn`, which does not implement the `Copy` trait
+LL |             let a = u.n1;
+   |                     ---- value moved here
+LL |             let a = u;
+   |                     ^ value used here after move
+
+error[E0382]: use of moved value: `u`
+  --> $DIR/borrowck-union-move.rs:36:21
+   |
+LL |             let mut u = Unn { n1: NonCopy };
+   |                 ----- move occurs because `u` has type `Unn`, which does not implement the `Copy` trait
+LL |             let a = u.n1;
+   |                     ---- value moved here
+LL |             let a = u.n2;
+   |                     ^^^^ value used here after move
+
+error[E0382]: use of moved value: `u`
+  --> $DIR/borrowck-union-move.rs:63:21
+   |
+LL |             let mut u = Ucn { c: Copy };
+   |                 ----- move occurs because `u` has type `Ucn`, which does not implement the `Copy` trait
+LL |             let a = u.n;
+   |                     --- value moved here
+LL |             let a = u.n;
+   |                     ^^^ value used here after move
+
+error[E0382]: use of moved value: `u`
+  --> $DIR/borrowck-union-move.rs:68:21
+   |
+LL |             let mut u = Ucn { c: Copy };
+   |                 ----- move occurs because `u` has type `Ucn`, which does not implement the `Copy` trait
+LL |             let a = u.n;
+   |                     --- value moved here
+LL |             let a = u.c;
+   |                     ^^^ value used here after move
+
+error[E0382]: use of moved value: `u`
+  --> $DIR/borrowck-union-move.rs:83:21
+   |
+LL |             let mut u = Ucn { c: Copy };
+   |                 ----- move occurs because `u` has type `Ucn`, which does not implement the `Copy` trait
+LL |             let a = u.n;
+   |                     --- value moved here
+LL |             let a = u;
+   |                     ^ value used here after move
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/borrowck-union-move.rs b/src/test/ui/borrowck/borrowck-union-move.rs
new file mode 100644
index 0000000..e248060
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-union-move.rs
@@ -0,0 +1,86 @@
+#![feature(untagged_unions)]
+
+#[derive(Clone, Copy)]
+struct Copy;
+struct NonCopy;
+
+union Unn {
+    n1: NonCopy,
+    n2: NonCopy,
+}
+union Ucc {
+    c1: Copy,
+    c2: Copy,
+}
+union Ucn {
+    c: Copy,
+    n: NonCopy,
+}
+
+fn main() {
+    unsafe {
+        // 2 NonCopy
+        {
+            let mut u = Unn { n1: NonCopy };
+            let a = u.n1;
+            let a = u.n1; //~ ERROR use of moved value: `u.n1`
+        }
+        {
+            let mut u = Unn { n1: NonCopy };
+            let a = u.n1;
+            let a = u; //~ ERROR use of partially moved value: `u`
+        }
+        {
+            let mut u = Unn { n1: NonCopy };
+            let a = u.n1;
+            let a = u.n2; //~ ERROR use of moved value: `u.n2`
+        }
+        // 2 Copy
+        {
+            let mut u = Ucc { c1: Copy };
+            let a = u.c1;
+            let a = u.c1; // OK
+        }
+        {
+            let mut u = Ucc { c1: Copy };
+            let a = u.c1;
+            let a = u; // OK
+        }
+        {
+            let mut u = Ucc { c1: Copy };
+            let a = u.c1;
+            let a = u.c2; // OK
+        }
+        // 1 Copy, 1 NonCopy
+        {
+            let mut u = Ucn { c: Copy };
+            let a = u.c;
+            let a = u.c; // OK
+        }
+        {
+            let mut u = Ucn { c: Copy };
+            let a = u.n;
+            let a = u.n; //~ ERROR use of moved value: `u.n`
+        }
+        {
+            let mut u = Ucn { c: Copy };
+            let a = u.n;
+            let a = u.c; //~ ERROR use of moved value: `u.c`
+        }
+        {
+            let mut u = Ucn { c: Copy };
+            let a = u.c;
+            let a = u.n; // OK
+        }
+        {
+            let mut u = Ucn { c: Copy };
+            let a = u.c;
+            let a = u; // OK
+        }
+        {
+            let mut u = Ucn { c: Copy };
+            let a = u.n;
+            let a = u; //~ ERROR use of partially moved value: `u`
+        }
+    }
+}
diff --git a/src/test/ui/borrowck/borrowck-union-move.stderr b/src/test/ui/borrowck/borrowck-union-move.stderr
new file mode 100644
index 0000000..4ce372a
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-union-move.stderr
@@ -0,0 +1,63 @@
+error[E0382]: use of moved value: `u.n1`
+  --> $DIR/borrowck-union-move.rs:26:17
+   |
+LL |             let a = u.n1;
+   |                 - value moved here
+LL |             let a = u.n1;
+   |                 ^ value used here after move
+   |
+   = note: move occurs because `u.n1` has type `NonCopy`, which does not implement the `Copy` trait
+
+error[E0382]: use of partially moved value: `u`
+  --> $DIR/borrowck-union-move.rs:31:17
+   |
+LL |             let a = u.n1;
+   |                 - value moved here
+LL |             let a = u;
+   |                 ^ value used here after move
+   |
+   = note: move occurs because `u.n2` has type `[type error]`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `u.n2`
+  --> $DIR/borrowck-union-move.rs:36:17
+   |
+LL |             let a = u.n1;
+   |                 - value moved here
+LL |             let a = u.n2;
+   |                 ^ value used here after move
+   |
+   = note: move occurs because `u.n2` has type `[type error]`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `u.n`
+  --> $DIR/borrowck-union-move.rs:63:17
+   |
+LL |             let a = u.n;
+   |                 - value moved here
+LL |             let a = u.n;
+   |                 ^ value used here after move
+   |
+   = note: move occurs because `u.n` has type `NonCopy`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `u.c`
+  --> $DIR/borrowck-union-move.rs:68:17
+   |
+LL |             let a = u.n;
+   |                 - value moved here
+LL |             let a = u.c;
+   |                 ^ value used here after move
+   |
+   = note: move occurs because `u.c` has type `[type error]`, which does not implement the `Copy` trait
+
+error[E0382]: use of partially moved value: `u`
+  --> $DIR/borrowck-union-move.rs:83:17
+   |
+LL |             let a = u.n;
+   |                 - value moved here
+LL |             let a = u;
+   |                 ^ value used here after move
+   |
+   = note: move occurs because `u.c` has type `[type error]`, which does not implement the `Copy` trait
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/borrowck-union-uninitialized.nll.stderr b/src/test/ui/borrowck/borrowck-union-uninitialized.nll.stderr
new file mode 100644
index 0000000..06c884e
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-union-uninitialized.nll.stderr
@@ -0,0 +1,15 @@
+error[E0381]: assign to part of possibly uninitialized variable: `s`
+  --> $DIR/borrowck-union-uninitialized.rs:13:9
+   |
+LL |         s.a = 0;
+   |         ^^^^^^^ use of possibly uninitialized `s`
+
+error[E0381]: assign to part of possibly uninitialized variable: `u`
+  --> $DIR/borrowck-union-uninitialized.rs:14:9
+   |
+LL |         u.a = 0;
+   |         ^^^^^^^ use of possibly uninitialized `u`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/borrowck-union-uninitialized.rs b/src/test/ui/borrowck/borrowck-union-uninitialized.rs
new file mode 100644
index 0000000..e7d456e
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-union-uninitialized.rs
@@ -0,0 +1,18 @@
+struct S {
+    a: u8,
+}
+
+union U {
+    a: u8,
+}
+
+fn main() {
+    unsafe {
+        let mut s: S;
+        let mut u: U;
+        s.a = 0;
+        u.a = 0;
+        let sa = s.a; //~ ERROR use of possibly uninitialized variable: `s.a`
+        let ua = u.a; //~ ERROR use of possibly uninitialized variable: `u.a`
+    }
+}
diff --git a/src/test/ui/borrowck/borrowck-union-uninitialized.stderr b/src/test/ui/borrowck/borrowck-union-uninitialized.stderr
new file mode 100644
index 0000000..6a1401f
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-union-uninitialized.stderr
@@ -0,0 +1,15 @@
+error[E0381]: use of possibly uninitialized variable: `s.a`
+  --> $DIR/borrowck-union-uninitialized.rs:15:13
+   |
+LL |         let sa = s.a;
+   |             ^^ use of possibly uninitialized `s.a`
+
+error[E0381]: use of possibly uninitialized variable: `u.a`
+  --> $DIR/borrowck-union-uninitialized.rs:16:13
+   |
+LL |         let ua = u.a;
+   |             ^^ use of possibly uninitialized `u.a`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/borrowck-uniq-via-lend.nll.stderr b/src/test/ui/borrowck/borrowck-uniq-via-lend.nll.stderr
new file mode 100644
index 0000000..923edc8
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-uniq-via-lend.nll.stderr
@@ -0,0 +1,23 @@
+error[E0502]: cannot borrow `*v` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-uniq-via-lend.rs:36:12
+   |
+LL |     let w = &mut v;
+   |             ------ mutable borrow occurs here
+LL |     borrow(&*v);
+   |            ^^^ immutable borrow occurs here
+LL |     w.use_mut();
+   |     - mutable borrow later used here
+
+error[E0502]: cannot borrow `*v` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-uniq-via-lend.rs:53:12
+   |
+LL |     x = &mut v;
+   |         ------ mutable borrow occurs here
+LL |     borrow(&*v);
+   |            ^^^ immutable borrow occurs here
+LL |     x.use_mut();
+   |     - mutable borrow later used here
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/borrowck/borrowck-uniq-via-lend.rs b/src/test/ui/borrowck/borrowck-uniq-via-lend.rs
new file mode 100644
index 0000000..f628807
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-uniq-via-lend.rs
@@ -0,0 +1,61 @@
+#![feature(box_syntax)]
+
+
+
+fn borrow(_v: &isize) {}
+
+fn local() {
+    let mut v: Box<_> = box 3;
+    borrow(&*v);
+}
+
+fn local_rec() {
+    struct F { f: Box<isize> }
+    let mut v = F {f: box 3};
+    borrow(&*v.f);
+}
+
+fn local_recs() {
+    struct F { f: G }
+    struct G { g: H }
+    struct H { h: Box<isize> }
+    let mut v = F {f: G {g: H {h: box 3}}};
+    borrow(&*v.f.g.h);
+}
+
+fn aliased_imm() {
+    let mut v: Box<_> = box 3;
+    let w = &v;
+    borrow(&*v);
+    w.use_ref();
+}
+
+fn aliased_mut() {
+    let mut v: Box<_> = box 3;
+    let w = &mut v;
+    borrow(&*v); //~ ERROR cannot borrow `*v`
+    w.use_mut();
+}
+
+fn aliased_other() {
+    let mut v: Box<_> = box 3;
+    let mut w: Box<_> = box 4;
+    let x = &mut w;
+    borrow(&*v);
+    x.use_mut();
+}
+
+fn aliased_other_reassign() {
+    let mut v: Box<_> = box 3;
+    let mut w: Box<_> = box 4;
+    let mut x = &mut w;
+    x = &mut v;
+    borrow(&*v); //~ ERROR cannot borrow `*v`
+    x.use_mut();
+}
+
+fn main() {
+}
+
+trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { }  }
+impl<T> Fake for T { }
diff --git a/src/test/ui/borrowck/borrowck-uniq-via-lend.stderr b/src/test/ui/borrowck/borrowck-uniq-via-lend.stderr
new file mode 100644
index 0000000..00fd77e
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-uniq-via-lend.stderr
@@ -0,0 +1,25 @@
+error[E0502]: cannot borrow `*v` as immutable because `v` is also borrowed as mutable
+  --> $DIR/borrowck-uniq-via-lend.rs:36:13
+   |
+LL |     let w = &mut v;
+   |                  - mutable borrow occurs here
+LL |     borrow(&*v);
+   |             ^^ immutable borrow occurs here
+LL |     w.use_mut();
+LL | }
+   | - mutable borrow ends here
+
+error[E0502]: cannot borrow `*v` as immutable because `v` is also borrowed as mutable
+  --> $DIR/borrowck-uniq-via-lend.rs:53:13
+   |
+LL |     x = &mut v;
+   |              - mutable borrow occurs here
+LL |     borrow(&*v);
+   |             ^^ immutable borrow occurs here
+LL |     x.use_mut();
+LL | }
+   | - mutable borrow ends here
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/borrowck/borrowck-use-in-index-lvalue.ast.nll.stderr b/src/test/ui/borrowck/borrowck-use-in-index-lvalue.ast.nll.stderr
new file mode 100644
index 0000000..c5e4f89
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-use-in-index-lvalue.ast.nll.stderr
@@ -0,0 +1,15 @@
+error[E0381]: use of possibly uninitialized variable: `w`
+  --> $DIR/borrowck-use-in-index-lvalue.rs:6:5
+   |
+LL |     w[5] = 0;
+   |     ^^^^ use of possibly uninitialized `*w`
+
+error[E0381]: use of possibly uninitialized variable: `w`
+  --> $DIR/borrowck-use-in-index-lvalue.rs:10:5
+   |
+LL |     w[5] = 0;
+   |     ^^^^ use of possibly uninitialized `*w`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/borrowck-use-in-index-lvalue.ast.stderr b/src/test/ui/borrowck/borrowck-use-in-index-lvalue.ast.stderr
new file mode 100644
index 0000000..e235bdf
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-use-in-index-lvalue.ast.stderr
@@ -0,0 +1,15 @@
+error[E0381]: use of possibly uninitialized variable: `*w`
+  --> $DIR/borrowck-use-in-index-lvalue.rs:6:5
+   |
+LL |     w[5] = 0;
+   |     ^^^^^^^^ use of possibly uninitialized `*w`
+
+error[E0381]: use of possibly uninitialized variable: `*w`
+  --> $DIR/borrowck-use-in-index-lvalue.rs:10:5
+   |
+LL |     w[5] = 0;
+   |     ^^^^^^^^ use of possibly uninitialized `*w`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/borrowck-use-in-index-lvalue.mir.stderr b/src/test/ui/borrowck/borrowck-use-in-index-lvalue.mir.stderr
new file mode 100644
index 0000000..c5e4f89
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-use-in-index-lvalue.mir.stderr
@@ -0,0 +1,15 @@
+error[E0381]: use of possibly uninitialized variable: `w`
+  --> $DIR/borrowck-use-in-index-lvalue.rs:6:5
+   |
+LL |     w[5] = 0;
+   |     ^^^^ use of possibly uninitialized `*w`
+
+error[E0381]: use of possibly uninitialized variable: `w`
+  --> $DIR/borrowck-use-in-index-lvalue.rs:10:5
+   |
+LL |     w[5] = 0;
+   |     ^^^^ use of possibly uninitialized `*w`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/borrowck-use-in-index-lvalue.rs b/src/test/ui/borrowck/borrowck-use-in-index-lvalue.rs
new file mode 100644
index 0000000..f953dec
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-use-in-index-lvalue.rs
@@ -0,0 +1,14 @@
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+fn test() {
+    let w: &mut [isize];
+    w[5] = 0; //[ast]~ ERROR use of possibly uninitialized variable: `*w` [E0381]
+              //[mir]~^ ERROR [E0381]
+
+    let mut w: &mut [isize];
+    w[5] = 0; //[ast]~ ERROR use of possibly uninitialized variable: `*w` [E0381]
+              //[mir]~^ ERROR [E0381]
+}
+
+fn main() { test(); }
diff --git a/src/test/ui/borrowck/borrowck-use-mut-borrow.nll.stderr b/src/test/ui/borrowck/borrowck-use-mut-borrow.nll.stderr
new file mode 100644
index 0000000..91d69c5
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-use-mut-borrow.nll.stderr
@@ -0,0 +1,95 @@
+error[E0503]: cannot use `x` because it was mutably borrowed
+  --> $DIR/borrowck-use-mut-borrow.rs:11:10
+   |
+LL |     let p = &mut x;
+   |             ------ borrow of `x` occurs here
+LL |     drop(x);
+   |          ^ use of borrowed `x`
+LL |     *p = 2;
+   |     ------ borrow later used here
+
+error[E0503]: cannot use `x` because it was mutably borrowed
+  --> $DIR/borrowck-use-mut-borrow.rs:18:10
+   |
+LL |     let p = &mut x.a;
+   |             -------- borrow of `x.a` occurs here
+LL |     drop(x);
+   |          ^ use of borrowed `x.a`
+LL |     *p = 3;
+   |     ------ borrow later used here
+
+error[E0503]: cannot use `x.a` because it was mutably borrowed
+  --> $DIR/borrowck-use-mut-borrow.rs:25:10
+   |
+LL |     let p = &mut x;
+   |             ------ borrow of `x` occurs here
+LL |     drop(x.a);
+   |          ^^^ use of borrowed `x`
+LL |     p.a = 3;
+   |     ------- borrow later used here
+
+error[E0503]: cannot use `x.a` because it was mutably borrowed
+  --> $DIR/borrowck-use-mut-borrow.rs:32:10
+   |
+LL |     let p = &mut x.a;
+   |             -------- borrow of `x.a` occurs here
+LL |     drop(x.a);
+   |          ^^^ use of borrowed `x.a`
+LL |     *p = 3;
+   |     ------ borrow later used here
+
+error[E0503]: cannot use `x.a` because it was mutably borrowed
+  --> $DIR/borrowck-use-mut-borrow.rs:39:13
+   |
+LL |     let p = &mut x;
+   |             ------ borrow of `x` occurs here
+LL |     let y = A { b: 3, .. x };
+   |             ^^^^^^^^^^^^^^^^ use of borrowed `x`
+LL |     drop(y);
+LL |     p.a = 4;
+   |     ------- borrow later used here
+
+error[E0503]: cannot use `x.a` because it was mutably borrowed
+  --> $DIR/borrowck-use-mut-borrow.rs:47:13
+   |
+LL |     let p = &mut x.a;
+   |             -------- borrow of `x.a` occurs here
+LL |     let y = A { b: 3, .. x };
+   |             ^^^^^^^^^^^^^^^^ use of borrowed `x.a`
+LL |     drop(y);
+LL |     *p = 4;
+   |     ------ borrow later used here
+
+error[E0503]: cannot use `*x` because it was mutably borrowed
+  --> $DIR/borrowck-use-mut-borrow.rs:55:10
+   |
+LL |     let p = &mut x;
+   |             ------ borrow of `x` occurs here
+LL |     drop(*x);
+   |          ^^ use of borrowed `x`
+LL |     **p = 2;
+   |     ------- borrow later used here
+
+error[E0503]: cannot use `*x.b` because it was mutably borrowed
+  --> $DIR/borrowck-use-mut-borrow.rs:62:10
+   |
+LL |     let p = &mut x;
+   |             ------ borrow of `x` occurs here
+LL |     drop(*x.b);
+   |          ^^^^ use of borrowed `x`
+LL |     p.a = 3;
+   |     ------- borrow later used here
+
+error[E0503]: cannot use `*x.b` because it was mutably borrowed
+  --> $DIR/borrowck-use-mut-borrow.rs:69:10
+   |
+LL |     let p = &mut x.b;
+   |             -------- borrow of `x.b` occurs here
+LL |     drop(*x.b);
+   |          ^^^^ use of borrowed `x.b`
+LL |     **p = 3;
+   |     ------- borrow later used here
+
+error: aborting due to 9 previous errors
+
+For more information about this error, try `rustc --explain E0503`.
diff --git a/src/test/ui/borrowck/borrowck-use-mut-borrow.rs b/src/test/ui/borrowck/borrowck-use-mut-borrow.rs
new file mode 100644
index 0000000..95b165d
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-use-mut-borrow.rs
@@ -0,0 +1,86 @@
+#![feature(box_syntax)]
+
+#[derive(Copy, Clone)]
+struct A { a: isize, b: isize }
+
+struct B { a: isize, b: Box<isize> }
+
+fn var_copy_after_var_borrow() {
+    let mut x: isize = 1;
+    let p = &mut x;
+    drop(x); //~ ERROR cannot use `x` because it was mutably borrowed
+    *p = 2;
+}
+
+fn var_copy_after_field_borrow() {
+    let mut x = A { a: 1, b: 2 };
+    let p = &mut x.a;
+    drop(x); //~ ERROR cannot use `x` because it was mutably borrowed
+    *p = 3;
+}
+
+fn field_copy_after_var_borrow() {
+    let mut x = A { a: 1, b: 2 };
+    let p = &mut x;
+    drop(x.a); //~ ERROR cannot use `x.a` because it was mutably borrowed
+    p.a = 3;
+}
+
+fn field_copy_after_field_borrow() {
+    let mut x = A { a: 1, b: 2 };
+    let p = &mut x.a;
+    drop(x.a); //~ ERROR cannot use `x.a` because it was mutably borrowed
+    *p = 3;
+}
+
+fn fu_field_copy_after_var_borrow() {
+    let mut x = A { a: 1, b: 2 };
+    let p = &mut x;
+    let y = A { b: 3, .. x }; //~ ERROR cannot use `x.a` because it was mutably borrowed
+    drop(y);
+    p.a = 4;
+}
+
+fn fu_field_copy_after_field_borrow() {
+    let mut x = A { a: 1, b: 2 };
+    let p = &mut x.a;
+    let y = A { b: 3, .. x }; //~ ERROR cannot use `x.a` because it was mutably borrowed
+    drop(y);
+    *p = 4;
+}
+
+fn var_deref_after_var_borrow() {
+    let mut x: Box<isize> = box 1;
+    let p = &mut x;
+    drop(*x); //~ ERROR cannot use `*x` because it was mutably borrowed
+    **p = 2;
+}
+
+fn field_deref_after_var_borrow() {
+    let mut x = B { a: 1, b: box 2 };
+    let p = &mut x;
+    drop(*x.b); //~ ERROR cannot use `*x.b` because it was mutably borrowed
+    p.a = 3;
+}
+
+fn field_deref_after_field_borrow() {
+    let mut x = B { a: 1, b: box 2 };
+    let p = &mut x.b;
+    drop(*x.b); //~ ERROR cannot use `*x.b` because it was mutably borrowed
+    **p = 3;
+}
+
+fn main() {
+    var_copy_after_var_borrow();
+    var_copy_after_field_borrow();
+
+    field_copy_after_var_borrow();
+    field_copy_after_field_borrow();
+
+    fu_field_copy_after_var_borrow();
+    fu_field_copy_after_field_borrow();
+
+    var_deref_after_var_borrow();
+    field_deref_after_var_borrow();
+    field_deref_after_field_borrow();
+}
diff --git a/src/test/ui/borrowck/borrowck-use-mut-borrow.stderr b/src/test/ui/borrowck/borrowck-use-mut-borrow.stderr
new file mode 100644
index 0000000..5c1d726
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-use-mut-borrow.stderr
@@ -0,0 +1,75 @@
+error[E0503]: cannot use `x` because it was mutably borrowed
+  --> $DIR/borrowck-use-mut-borrow.rs:11:10
+   |
+LL |     let p = &mut x;
+   |                  - borrow of `x` occurs here
+LL |     drop(x);
+   |          ^ use of borrowed `x`
+
+error[E0503]: cannot use `x` because it was mutably borrowed
+  --> $DIR/borrowck-use-mut-borrow.rs:18:10
+   |
+LL |     let p = &mut x.a;
+   |                  --- borrow of `x.a` occurs here
+LL |     drop(x);
+   |          ^ use of borrowed `x.a`
+
+error[E0503]: cannot use `x.a` because it was mutably borrowed
+  --> $DIR/borrowck-use-mut-borrow.rs:25:10
+   |
+LL |     let p = &mut x;
+   |                  - borrow of `x` occurs here
+LL |     drop(x.a);
+   |          ^^^ use of borrowed `x`
+
+error[E0503]: cannot use `x.a` because it was mutably borrowed
+  --> $DIR/borrowck-use-mut-borrow.rs:32:10
+   |
+LL |     let p = &mut x.a;
+   |                  --- borrow of `x.a` occurs here
+LL |     drop(x.a);
+   |          ^^^ use of borrowed `x.a`
+
+error[E0503]: cannot use `x.a` because it was mutably borrowed
+  --> $DIR/borrowck-use-mut-borrow.rs:39:26
+   |
+LL |     let p = &mut x;
+   |                  - borrow of `x` occurs here
+LL |     let y = A { b: 3, .. x };
+   |                          ^ use of borrowed `x`
+
+error[E0503]: cannot use `x.a` because it was mutably borrowed
+  --> $DIR/borrowck-use-mut-borrow.rs:47:26
+   |
+LL |     let p = &mut x.a;
+   |                  --- borrow of `x.a` occurs here
+LL |     let y = A { b: 3, .. x };
+   |                          ^ use of borrowed `x.a`
+
+error[E0503]: cannot use `*x` because it was mutably borrowed
+  --> $DIR/borrowck-use-mut-borrow.rs:55:10
+   |
+LL |     let p = &mut x;
+   |                  - borrow of `x` occurs here
+LL |     drop(*x);
+   |          ^^ use of borrowed `x`
+
+error[E0503]: cannot use `*x.b` because it was mutably borrowed
+  --> $DIR/borrowck-use-mut-borrow.rs:62:10
+   |
+LL |     let p = &mut x;
+   |                  - borrow of `x` occurs here
+LL |     drop(*x.b);
+   |          ^^^^ use of borrowed `x`
+
+error[E0503]: cannot use `*x.b` because it was mutably borrowed
+  --> $DIR/borrowck-use-mut-borrow.rs:69:10
+   |
+LL |     let p = &mut x.b;
+   |                  --- borrow of `x.b` occurs here
+LL |     drop(*x.b);
+   |          ^^^^ use of borrowed `x.b`
+
+error: aborting due to 9 previous errors
+
+For more information about this error, try `rustc --explain E0503`.
diff --git a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.ast.nll.stderr b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.ast.nll.stderr
new file mode 100644
index 0000000..a208dc4
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.ast.nll.stderr
@@ -0,0 +1,9 @@
+error[E0381]: borrow of possibly uninitialized variable: `x`
+  --> $DIR/borrowck-use-uninitialized-in-cast-trait.rs:12:13
+   |
+LL |     let y = x as *const Foo;
+   |             ^ use of possibly uninitialized `*x`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.ast.stderr b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.ast.stderr
new file mode 100644
index 0000000..49a4300
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.ast.stderr
@@ -0,0 +1,9 @@
+error[E0381]: use of possibly uninitialized variable: `*x`
+  --> $DIR/borrowck-use-uninitialized-in-cast-trait.rs:12:13
+   |
+LL |     let y = x as *const Foo;
+   |             ^ use of possibly uninitialized `*x`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.mir.stderr b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.mir.stderr
new file mode 100644
index 0000000..a208dc4
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.mir.stderr
@@ -0,0 +1,9 @@
+error[E0381]: borrow of possibly uninitialized variable: `x`
+  --> $DIR/borrowck-use-uninitialized-in-cast-trait.rs:12:13
+   |
+LL |     let y = x as *const Foo;
+   |             ^ use of possibly uninitialized `*x`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.rs b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.rs
new file mode 100644
index 0000000..518228a
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.rs
@@ -0,0 +1,14 @@
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+// Variation on `borrowck-use-uninitialized-in-cast` in which we do a
+// trait cast from an uninitialized source. Issue #20791.
+
+trait Foo { fn dummy(&self) { } }
+impl Foo for i32 { }
+
+fn main() {
+    let x: &i32;
+    let y = x as *const Foo; //[ast]~ ERROR use of possibly uninitialized variable: `*x`
+                             //[mir]~^ ERROR [E0381]
+}
diff --git a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.ast.nll.stderr b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.ast.nll.stderr
new file mode 100644
index 0000000..0f62c3a
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.ast.nll.stderr
@@ -0,0 +1,9 @@
+error[E0381]: borrow of possibly uninitialized variable: `x`
+  --> $DIR/borrowck-use-uninitialized-in-cast.rs:10:13
+   |
+LL |     let y = x as *const i32;
+   |             ^ use of possibly uninitialized `*x`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.ast.stderr b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.ast.stderr
new file mode 100644
index 0000000..d813738
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.ast.stderr
@@ -0,0 +1,9 @@
+error[E0381]: use of possibly uninitialized variable: `*x`
+  --> $DIR/borrowck-use-uninitialized-in-cast.rs:10:13
+   |
+LL |     let y = x as *const i32;
+   |             ^ use of possibly uninitialized `*x`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.mir.stderr b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.mir.stderr
new file mode 100644
index 0000000..0f62c3a
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.mir.stderr
@@ -0,0 +1,9 @@
+error[E0381]: borrow of possibly uninitialized variable: `x`
+  --> $DIR/borrowck-use-uninitialized-in-cast.rs:10:13
+   |
+LL |     let y = x as *const i32;
+   |             ^ use of possibly uninitialized `*x`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.rs b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.rs
new file mode 100644
index 0000000..e15479b
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.rs
@@ -0,0 +1,12 @@
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+// Check that we detect unused values that are cast to other things.
+// The problem was specified to casting to `*`, as creating unsafe
+// pointers was not being fully checked. Issue #20791.
+
+fn main() {
+    let x: &i32;
+    let y = x as *const i32; //[ast]~ ERROR use of possibly uninitialized variable: `*x` [E0381]
+                             //[mir]~^ ERROR [E0381]
+}
diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-element-loan.nll.stderr b/src/test/ui/borrowck/borrowck-vec-pattern-element-loan.nll.stderr
new file mode 100644
index 0000000..da6d929
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-vec-pattern-element-loan.nll.stderr
@@ -0,0 +1,30 @@
+error[E0515]: cannot return value referencing local variable `vec`
+  --> $DIR/borrowck-vec-pattern-element-loan.rs:10:5
+   |
+LL |     let vec: &[isize] = &vec;
+   |                         ---- `vec` is borrowed here
+...
+LL |     tail
+   |     ^^^^ returns a value referencing data owned by the current function
+
+error[E0515]: cannot return value referencing local variable `vec`
+  --> $DIR/borrowck-vec-pattern-element-loan.rs:20:5
+   |
+LL |     let vec: &[isize] = &vec;
+   |                         ---- `vec` is borrowed here
+...
+LL |     init
+   |     ^^^^ returns a value referencing data owned by the current function
+
+error[E0515]: cannot return value referencing local variable `vec`
+  --> $DIR/borrowck-vec-pattern-element-loan.rs:30:5
+   |
+LL |     let vec: &[isize] = &vec;
+   |                         ---- `vec` is borrowed here
+...
+LL |     slice
+   |     ^^^^^ returns a value referencing data owned by the current function
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-element-loan.rs b/src/test/ui/borrowck/borrowck-vec-pattern-element-loan.rs
new file mode 100644
index 0000000..0de5132
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-vec-pattern-element-loan.rs
@@ -0,0 +1,33 @@
+#![feature(slice_patterns)]
+
+fn a<'a>() -> &'a [isize] {
+    let vec = vec![1, 2, 3, 4];
+    let vec: &[isize] = &vec; //~ ERROR does not live long enough
+    let tail = match vec {
+        &[_, ref tail..] => tail,
+        _ => panic!("a")
+    };
+    tail
+}
+
+fn b<'a>() -> &'a [isize] {
+    let vec = vec![1, 2, 3, 4];
+    let vec: &[isize] = &vec; //~ ERROR does not live long enough
+    let init = match vec {
+        &[ref init.., _] => init,
+        _ => panic!("b")
+    };
+    init
+}
+
+fn c<'a>() -> &'a [isize] {
+    let vec = vec![1, 2, 3, 4];
+    let vec: &[isize] = &vec; //~ ERROR does not live long enough
+    let slice = match vec {
+        &[_, ref slice.., _] => slice,
+        _ => panic!("c")
+    };
+    slice
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-element-loan.stderr b/src/test/ui/borrowck/borrowck-vec-pattern-element-loan.stderr
new file mode 100644
index 0000000..b0eaee7
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-vec-pattern-element-loan.stderr
@@ -0,0 +1,48 @@
+error[E0597]: `vec` does not live long enough
+  --> $DIR/borrowck-vec-pattern-element-loan.rs:5:26
+   |
+LL |     let vec: &[isize] = &vec;
+   |                          ^^^ borrowed value does not live long enough
+...
+LL | }
+   | - borrowed value only lives until here
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 3:6...
+  --> $DIR/borrowck-vec-pattern-element-loan.rs:3:6
+   |
+LL | fn a<'a>() -> &'a [isize] {
+   |      ^^
+
+error[E0597]: `vec` does not live long enough
+  --> $DIR/borrowck-vec-pattern-element-loan.rs:15:26
+   |
+LL |     let vec: &[isize] = &vec;
+   |                          ^^^ borrowed value does not live long enough
+...
+LL | }
+   | - borrowed value only lives until here
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 13:6...
+  --> $DIR/borrowck-vec-pattern-element-loan.rs:13:6
+   |
+LL | fn b<'a>() -> &'a [isize] {
+   |      ^^
+
+error[E0597]: `vec` does not live long enough
+  --> $DIR/borrowck-vec-pattern-element-loan.rs:25:26
+   |
+LL |     let vec: &[isize] = &vec;
+   |                          ^^^ borrowed value does not live long enough
+...
+LL | }
+   | - borrowed value only lives until here
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 23:6...
+  --> $DIR/borrowck-vec-pattern-element-loan.rs:23:6
+   |
+LL | fn c<'a>() -> &'a [isize] {
+   |      ^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-loan-from-mut.nll.stderr b/src/test/ui/borrowck/borrowck-vec-pattern-loan-from-mut.nll.stderr
new file mode 100644
index 0000000..251f445
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-vec-pattern-loan-from-mut.nll.stderr
@@ -0,0 +1,14 @@
+error[E0499]: cannot borrow `v` as mutable more than once at a time
+  --> $DIR/borrowck-vec-pattern-loan-from-mut.rs:8:13
+   |
+LL |     let vb: &mut [isize] = &mut v;
+   |                            ------ first mutable borrow occurs here
+...
+LL |             v.push(tail[0] + tail[1]);
+   |             ^      ------- first borrow later used here
+   |             |
+   |             second mutable borrow occurs here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-loan-from-mut.rs b/src/test/ui/borrowck/borrowck-vec-pattern-loan-from-mut.rs
new file mode 100644
index 0000000..4d99a92
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-vec-pattern-loan-from-mut.rs
@@ -0,0 +1,14 @@
+#![feature(slice_patterns)]
+
+fn a() {
+    let mut v = vec![1, 2, 3];
+    let vb: &mut [isize] = &mut v;
+    match vb {
+        &mut [_a, ref tail..] => {
+            v.push(tail[0] + tail[1]); //~ ERROR cannot borrow
+        }
+        _ => {}
+    };
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-loan-from-mut.stderr b/src/test/ui/borrowck/borrowck-vec-pattern-loan-from-mut.stderr
new file mode 100644
index 0000000..1ce6a3b
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-vec-pattern-loan-from-mut.stderr
@@ -0,0 +1,15 @@
+error[E0499]: cannot borrow `v` as mutable more than once at a time
+  --> $DIR/borrowck-vec-pattern-loan-from-mut.rs:8:13
+   |
+LL |     let vb: &mut [isize] = &mut v;
+   |                                 - first mutable borrow occurs here
+...
+LL |             v.push(tail[0] + tail[1]);
+   |             ^ second mutable borrow occurs here
+...
+LL | }
+   | - first borrow ends here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.ast.nll.stderr b/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.ast.nll.stderr
new file mode 100644
index 0000000..7d0d888
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.ast.nll.stderr
@@ -0,0 +1,15 @@
+error[E0506]: cannot assign to `a[_]` because it is borrowed
+  --> $DIR/borrowck-vec-pattern-move-tail.rs:16:5
+   |
+LL |         [1, 2, ref tail..] => tail,
+   |                -------- borrow of `a[_]` occurs here
+...
+LL |     a[2] = 0;
+   |     ^^^^^^^^ assignment to borrowed `a[_]` occurs here
+...
+LL |     println!("t[0]: {}", t[0]);
+   |                          ---- borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.ast.stderr b/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.ast.stderr
new file mode 100644
index 0000000..1207d4a
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.ast.stderr
@@ -0,0 +1,12 @@
+error[E0506]: cannot assign to `a[..]` because it is borrowed
+  --> $DIR/borrowck-vec-pattern-move-tail.rs:16:5
+   |
+LL |         [1, 2, ref tail..] => tail,
+   |                -------- borrow of `a[..]` occurs here
+...
+LL |     a[2] = 0;
+   |     ^^^^^^^^ assignment to borrowed `a[..]` occurs here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.cmp.stderr b/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.cmp.stderr
new file mode 100644
index 0000000..f764d5f
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.cmp.stderr
@@ -0,0 +1,24 @@
+error[E0506]: cannot assign to `a[..]` because it is borrowed (Ast)
+  --> $DIR/borrowck-vec-pattern-move-tail.rs:16:5
+   |
+LL |         [1, 2, ref tail..] => tail,
+   |                -------- borrow of `a[..]` occurs here
+...
+LL |     a[2] = 0;
+   |     ^^^^^^^^ assignment to borrowed `a[..]` occurs here
+
+error[E0506]: cannot assign to `a[_]` because it is borrowed (Mir)
+  --> $DIR/borrowck-vec-pattern-move-tail.rs:16:5
+   |
+LL |         [1, 2, ref tail..] => tail,
+   |                -------- borrow of `a[_]` occurs here
+...
+LL |     a[2] = 0;
+   |     ^^^^^^^^ assignment to borrowed `a[_]` occurs here
+...
+LL |     println!("t[0]: {}", t[0]);
+   |                          ---- borrow later used here
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.rs b/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.rs
new file mode 100644
index 0000000..e14ecd9
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.rs
@@ -0,0 +1,21 @@
+// http://rust-lang.org/COPYRIGHT.
+//
+
+// revisions: ast cmp
+//[cmp]compile-flags: -Z borrowck=compare
+
+#![feature(slice_patterns)]
+
+fn main() {
+    let mut a = [1, 2, 3, 4];
+    let t = match a {
+        [1, 2, ref tail..] => tail,
+        _ => unreachable!()
+    };
+    println!("t[0]: {}", t[0]);
+    a[2] = 0; //[ast]~ ERROR cannot assign to `a[..]` because it is borrowed
+              //[cmp]~^ ERROR cannot assign to `a[..]` because it is borrowed (Ast)
+              //[cmp]~| ERROR cannot assign to `a[_]` because it is borrowed (Mir)
+    println!("t[0]: {}", t[0]);
+    t[0];
+}
diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-nesting.nll.stderr b/src/test/ui/borrowck/borrowck-vec-pattern-nesting.nll.stderr
new file mode 100644
index 0000000..aafcb31
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-vec-pattern-nesting.nll.stderr
@@ -0,0 +1,117 @@
+error[E0506]: cannot assign to `vec[_]` because it is borrowed
+  --> $DIR/borrowck-vec-pattern-nesting.rs:10:13
+   |
+LL |         [box ref _a, _, _] => {
+   |              ------ borrow of `vec[_]` occurs here
+LL |
+LL |             vec[0] = box 4;
+   |             ^^^^^^ assignment to borrowed `vec[_]` occurs here
+LL |
+LL |             _a.use_ref();
+   |             -- borrow later used here
+
+error[E0506]: cannot assign to `vec[_]` because it is borrowed
+  --> $DIR/borrowck-vec-pattern-nesting.rs:23:13
+   |
+LL |         &mut [ref _b..] => {
+   |               ------ borrow of `vec[_]` occurs here
+LL |
+LL |             vec[0] = box 4;
+   |             ^^^^^^ assignment to borrowed `vec[_]` occurs here
+LL |
+LL |             _b.use_ref();
+   |             -- borrow later used here
+
+error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
+  --> $DIR/borrowck-vec-pattern-nesting.rs:33:11
+   |
+LL |     match vec {
+   |           ^^^ cannot move out of here
+LL |         &mut [_a,
+   |               -- data moved here
+   |
+note: move occurs because `_a` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-vec-pattern-nesting.rs:34:15
+   |
+LL |         &mut [_a,
+   |               ^^
+help: consider removing the `&mut`
+   |
+LL |         [_a,
+LL |
+LL |
+LL |             ..
+LL |         ] => {
+   |
+
+error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
+  --> $DIR/borrowck-vec-pattern-nesting.rs:47:13
+   |
+LL |     let a = vec[0];
+   |             ^^^^^^
+   |             |
+   |             cannot move out of here
+   |             help: consider borrowing here: `&vec[0]`
+
+error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
+  --> $DIR/borrowck-vec-pattern-nesting.rs:54:11
+   |
+LL |     match vec {
+   |           ^^^ cannot move out of here
+...
+LL |          _b] => {}
+   |          -- data moved here
+   |
+note: move occurs because `_b` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-vec-pattern-nesting.rs:57:10
+   |
+LL |          _b] => {}
+   |          ^^
+help: consider removing the `&mut`
+   |
+LL |         [
+LL |
+LL |          _b] => {}
+   |
+
+error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
+  --> $DIR/borrowck-vec-pattern-nesting.rs:60:13
+   |
+LL |     let a = vec[0];
+   |             ^^^^^^
+   |             |
+   |             cannot move out of here
+   |             help: consider borrowing here: `&vec[0]`
+
+error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
+  --> $DIR/borrowck-vec-pattern-nesting.rs:67:11
+   |
+LL |     match vec {
+   |           ^^^ cannot move out of here
+LL |         &mut [_a, _b, _c] => {}
+   |         -----------------
+   |         |     |   |   |
+   |         |     |   |   ...and here
+   |         |     |   ...and here
+   |         |     data moved here
+   |         help: consider removing the `&mut`: `[_a, _b, _c]`
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/borrowck-vec-pattern-nesting.rs:68:15
+   |
+LL |         &mut [_a, _b, _c] => {}
+   |               ^^  ^^  ^^
+
+error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
+  --> $DIR/borrowck-vec-pattern-nesting.rs:72:13
+   |
+LL |     let a = vec[0];
+   |             ^^^^^^
+   |             |
+   |             cannot move out of here
+   |             help: consider borrowing here: `&vec[0]`
+
+error: aborting due to 8 previous errors
+
+Some errors occurred: E0506, E0508.
+For more information about an error, try `rustc --explain E0506`.
diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-nesting.rs b/src/test/ui/borrowck/borrowck-vec-pattern-nesting.rs
new file mode 100644
index 0000000..46203b7
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-vec-pattern-nesting.rs
@@ -0,0 +1,79 @@
+#![feature(box_patterns)]
+#![feature(box_syntax)]
+#![feature(slice_patterns)]
+
+fn a() {
+    let mut vec = [box 1, box 2, box 3];
+    match vec {
+        [box ref _a, _, _] => {
+        //~^ borrow of `vec[..]` occurs here
+            vec[0] = box 4; //~ ERROR cannot assign
+            //~^ assignment to borrowed `vec[..]` occurs here
+            _a.use_ref();
+        }
+    }
+}
+
+fn b() {
+    let mut vec = vec![box 1, box 2, box 3];
+    let vec: &mut [Box<isize>] = &mut vec;
+    match vec {
+        &mut [ref _b..] => {
+        //~^ borrow of `vec[..]` occurs here
+            vec[0] = box 4; //~ ERROR cannot assign
+            //~^ assignment to borrowed `vec[..]` occurs here
+            _b.use_ref();
+        }
+    }
+}
+
+fn c() {
+    let mut vec = vec![box 1, box 2, box 3];
+    let vec: &mut [Box<isize>] = &mut vec;
+    match vec {
+        &mut [_a, //~ ERROR cannot move out
+            //~| cannot move out
+            //~| to prevent move
+            ..
+        ] => {
+            // Note: `_a` is *moved* here, but `b` is borrowing,
+            // hence illegal.
+            //
+            // See comment in middle/borrowck/gather_loans/mod.rs
+            // in the case covering these sorts of vectors.
+        }
+        _ => {}
+    }
+    let a = vec[0]; //~ ERROR cannot move out
+    //~| cannot move out of here
+}
+
+fn d() {
+    let mut vec = vec![box 1, box 2, box 3];
+    let vec: &mut [Box<isize>] = &mut vec;
+    match vec {
+        &mut [ //~ ERROR cannot move out
+        //~^ cannot move out
+         _b] => {}
+        _ => {}
+    }
+    let a = vec[0]; //~ ERROR cannot move out
+    //~| cannot move out of here
+}
+
+fn e() {
+    let mut vec = vec![box 1, box 2, box 3];
+    let vec: &mut [Box<isize>] = &mut vec;
+    match vec {
+        &mut [_a, _b, _c] => {}  //~ ERROR cannot move out
+        //~| cannot move out
+        _ => {}
+    }
+    let a = vec[0]; //~ ERROR cannot move out
+    //~| cannot move out of here
+}
+
+fn main() {}
+
+trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { }  }
+impl<T> Fake for T { }
diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-nesting.stderr b/src/test/ui/borrowck/borrowck-vec-pattern-nesting.stderr
new file mode 100644
index 0000000..0e3f514
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-vec-pattern-nesting.stderr
@@ -0,0 +1,84 @@
+error[E0506]: cannot assign to `vec[..]` because it is borrowed
+  --> $DIR/borrowck-vec-pattern-nesting.rs:10:13
+   |
+LL |         [box ref _a, _, _] => {
+   |              ------ borrow of `vec[..]` occurs here
+LL |
+LL |             vec[0] = box 4;
+   |             ^^^^^^^^^^^^^^ assignment to borrowed `vec[..]` occurs here
+
+error[E0506]: cannot assign to `vec[..]` because it is borrowed
+  --> $DIR/borrowck-vec-pattern-nesting.rs:23:13
+   |
+LL |         &mut [ref _b..] => {
+   |               ------ borrow of `vec[..]` occurs here
+LL |
+LL |             vec[0] = box 4;
+   |             ^^^^^^^^^^^^^^ assignment to borrowed `vec[..]` occurs here
+
+error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
+  --> $DIR/borrowck-vec-pattern-nesting.rs:34:14
+   |
+LL |           &mut [_a,
+   |                ^-- hint: to prevent move, use `ref _a` or `ref mut _a`
+   |  ______________|
+   | |
+LL | |
+LL | |
+LL | |             ..
+LL | |         ] => {
+   | |_________^ cannot move out of here
+
+error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
+  --> $DIR/borrowck-vec-pattern-nesting.rs:47:13
+   |
+LL |     let a = vec[0];
+   |             ^^^^^^
+   |             |
+   |             cannot move out of here
+   |             help: consider using a reference instead: `&vec[0]`
+
+error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
+  --> $DIR/borrowck-vec-pattern-nesting.rs:55:14
+   |
+LL |           &mut [
+   |  ______________^
+LL | |
+LL | |          _b] => {}
+   | |__________--^ cannot move out of here
+   |            |
+   |            hint: to prevent move, use `ref _b` or `ref mut _b`
+
+error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
+  --> $DIR/borrowck-vec-pattern-nesting.rs:60:13
+   |
+LL |     let a = vec[0];
+   |             ^^^^^^
+   |             |
+   |             cannot move out of here
+   |             help: consider using a reference instead: `&vec[0]`
+
+error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
+  --> $DIR/borrowck-vec-pattern-nesting.rs:68:14
+   |
+LL |         &mut [_a, _b, _c] => {}
+   |              ^--^^--^^--^
+   |              ||   |   |
+   |              ||   |   ...and here (use `ref _c` or `ref mut _c`)
+   |              ||   ...and here (use `ref _b` or `ref mut _b`)
+   |              |hint: to prevent move, use `ref _a` or `ref mut _a`
+   |              cannot move out of here
+
+error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
+  --> $DIR/borrowck-vec-pattern-nesting.rs:72:13
+   |
+LL |     let a = vec[0];
+   |             ^^^^^^
+   |             |
+   |             cannot move out of here
+   |             help: consider using a reference instead: `&vec[0]`
+
+error: aborting due to 8 previous errors
+
+Some errors occurred: E0506, E0508.
+For more information about an error, try `rustc --explain E0506`.
diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-tail-element-loan.nll.stderr b/src/test/ui/borrowck/borrowck-vec-pattern-tail-element-loan.nll.stderr
new file mode 100644
index 0000000..c1290a6
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-vec-pattern-tail-element-loan.nll.stderr
@@ -0,0 +1,12 @@
+error[E0515]: cannot return value referencing local variable `vec`
+  --> $DIR/borrowck-vec-pattern-tail-element-loan.rs:10:5
+   |
+LL |     let vec: &[isize] = &vec;
+   |                         ---- `vec` is borrowed here
+...
+LL |     tail
+   |     ^^^^ returns a value referencing data owned by the current function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-tail-element-loan.rs b/src/test/ui/borrowck/borrowck-vec-pattern-tail-element-loan.rs
new file mode 100644
index 0000000..b18052a
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-vec-pattern-tail-element-loan.rs
@@ -0,0 +1,16 @@
+#![feature(slice_patterns)]
+
+fn a<'a>() -> &'a isize {
+    let vec = vec![1, 2, 3, 4];
+    let vec: &[isize] = &vec; //~ ERROR `vec` does not live long enough
+    let tail = match vec {
+        &[_a, ref tail..] => &tail[0],
+        _ => panic!("foo")
+    };
+    tail
+}
+
+fn main() {
+    let fifth = a();
+    println!("{}", *fifth);
+}
diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-tail-element-loan.stderr b/src/test/ui/borrowck/borrowck-vec-pattern-tail-element-loan.stderr
new file mode 100644
index 0000000..0a5f773
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-vec-pattern-tail-element-loan.stderr
@@ -0,0 +1,18 @@
+error[E0597]: `vec` does not live long enough
+  --> $DIR/borrowck-vec-pattern-tail-element-loan.rs:5:26
+   |
+LL |     let vec: &[isize] = &vec;
+   |                          ^^^ borrowed value does not live long enough
+...
+LL | }
+   | - borrowed value only lives until here
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 3:6...
+  --> $DIR/borrowck-vec-pattern-tail-element-loan.rs:3:6
+   |
+LL | fn a<'a>() -> &'a isize {
+   |      ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/borrowck/borrowck-while-break.nll.stderr b/src/test/ui/borrowck/borrowck-while-break.nll.stderr
new file mode 100644
index 0000000..0fe3cdc
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-while-break.nll.stderr
@@ -0,0 +1,9 @@
+error[E0381]: borrow of possibly uninitialized variable: `v`
+  --> $DIR/borrowck-while-break.rs:7:20
+   |
+LL |     println!("{}", v);
+   |                    ^ use of possibly uninitialized `v`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/borrowck-while-break.rs b/src/test/ui/borrowck/borrowck-while-break.rs
new file mode 100644
index 0000000..293760e
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-while-break.rs
@@ -0,0 +1,12 @@
+fn test(cond: bool) {
+    let v;
+    while cond {
+        v = 3;
+        break;
+    }
+    println!("{}", v); //~ ERROR use of possibly uninitialized variable: `v`
+}
+
+fn main() {
+    test(true);
+}
diff --git a/src/test/ui/borrowck/borrowck-while-break.stderr b/src/test/ui/borrowck/borrowck-while-break.stderr
new file mode 100644
index 0000000..55969b8
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-while-break.stderr
@@ -0,0 +1,9 @@
+error[E0381]: use of possibly uninitialized variable: `v`
+  --> $DIR/borrowck-while-break.rs:7:20
+   |
+LL |     println!("{}", v);
+   |                    ^ use of possibly uninitialized `v`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/borrowck-while-cond.rs b/src/test/ui/borrowck/borrowck-while-cond.rs
new file mode 100644
index 0000000..28a5fb1
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-while-cond.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let x: bool;
+    while x { } //~ ERROR use of possibly uninitialized variable: `x`
+}
diff --git a/src/test/ui/borrowck/borrowck-while-cond.stderr b/src/test/ui/borrowck/borrowck-while-cond.stderr
new file mode 100644
index 0000000..06deae3
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-while-cond.stderr
@@ -0,0 +1,9 @@
+error[E0381]: use of possibly uninitialized variable: `x`
+  --> $DIR/borrowck-while-cond.rs:3:11
+   |
+LL |     while x { }
+   |           ^ use of possibly uninitialized `x`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/borrowck-while.rs b/src/test/ui/borrowck/borrowck-while.rs
new file mode 100644
index 0000000..4274fa9
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-while.rs
@@ -0,0 +1,7 @@
+fn f() -> isize {
+    let mut x: isize;
+    while 1 == 1 { x = 10; }
+    return x; //~ ERROR use of possibly uninitialized variable: `x`
+}
+
+fn main() { f(); }
diff --git a/src/test/ui/borrowck/borrowck-while.stderr b/src/test/ui/borrowck/borrowck-while.stderr
new file mode 100644
index 0000000..60622d6
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-while.stderr
@@ -0,0 +1,9 @@
+error[E0381]: use of possibly uninitialized variable: `x`
+  --> $DIR/borrowck-while.rs:4:12
+   |
+LL |     return x;
+   |            ^ use of possibly uninitialized `x`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/immutable-arg.rs b/src/test/ui/borrowck/immutable-arg.rs
new file mode 100644
index 0000000..5a5e619
--- /dev/null
+++ b/src/test/ui/borrowck/immutable-arg.rs
@@ -0,0 +1,10 @@
+//compile-flags: -Z borrowck=compare
+
+fn foo(_x: u32) {
+    _x = 4;
+    //~^ ERROR cannot assign to immutable argument `_x` (Mir)
+    //~^^ ERROR cannot assign twice to immutable variable `_x` (Ast)
+}
+
+fn main() {}
+
diff --git a/src/test/ui/borrowck/immutable-arg.stderr b/src/test/ui/borrowck/immutable-arg.stderr
new file mode 100644
index 0000000..8b21e92
--- /dev/null
+++ b/src/test/ui/borrowck/immutable-arg.stderr
@@ -0,0 +1,19 @@
+error[E0384]: cannot assign twice to immutable variable `_x` (Ast)
+  --> $DIR/immutable-arg.rs:4:5
+   |
+LL | fn foo(_x: u32) {
+   |        -- first assignment to `_x`
+LL |     _x = 4;
+   |     ^^^^^^ cannot assign twice to immutable variable
+
+error[E0384]: cannot assign to immutable argument `_x` (Mir)
+  --> $DIR/immutable-arg.rs:4:5
+   |
+LL | fn foo(_x: u32) {
+   |        -- help: make this binding mutable: `mut _x`
+LL |     _x = 4;
+   |     ^^^^^^ cannot assign to immutable argument
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0384`.
diff --git a/src/test/ui/borrowck/index-mut-help-with-impl.nll.stderr b/src/test/ui/borrowck/index-mut-help-with-impl.nll.stderr
new file mode 100644
index 0000000..4b29beb
--- /dev/null
+++ b/src/test/ui/borrowck/index-mut-help-with-impl.nll.stderr
@@ -0,0 +1,11 @@
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/index-mut-help-with-impl.rs:9:5
+   |
+LL |     Index::index(&v, 1..2).make_ascii_uppercase();
+   |     ^^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable
+   |
+   = help: trait `IndexMut` is required to modify indexed content
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/borrowck/index-mut-help-with-impl.rs b/src/test/ui/borrowck/index-mut-help-with-impl.rs
new file mode 100644
index 0000000..44b57c4
--- /dev/null
+++ b/src/test/ui/borrowck/index-mut-help-with-impl.rs
@@ -0,0 +1,10 @@
+// When mutably indexing a type that implements `Index` and `IndexMut` but
+// `Index::index` is being used specifically, the normal special help message
+// should not mention a missing `IndexMut` impl.
+
+fn main() {
+    use std::ops::Index;
+
+    let v = String::from("dinosaur");
+    Index::index(&v, 1..2).make_ascii_uppercase(); //~ ERROR
+}
diff --git a/src/test/ui/borrowck/index-mut-help-with-impl.stderr b/src/test/ui/borrowck/index-mut-help-with-impl.stderr
new file mode 100644
index 0000000..6e6efc6
--- /dev/null
+++ b/src/test/ui/borrowck/index-mut-help-with-impl.stderr
@@ -0,0 +1,9 @@
+error[E0596]: cannot borrow immutable borrowed content as mutable
+  --> $DIR/index-mut-help-with-impl.rs:9:5
+   |
+LL |     Index::index(&v, 1..2).make_ascii_uppercase();
+   |     ^^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/borrowck/index-mut-help.nll.stderr b/src/test/ui/borrowck/index-mut-help.nll.stderr
new file mode 100644
index 0000000..92b9420
--- /dev/null
+++ b/src/test/ui/borrowck/index-mut-help.nll.stderr
@@ -0,0 +1,26 @@
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/index-mut-help.rs:11:5
+   |
+LL |     map["peter"].clear();
+   |     ^^^^^^^^^^^^ cannot borrow as mutable
+   |
+   = help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `std::collections::HashMap<&str, std::string::String>`
+
+error[E0594]: cannot assign to data in a `&` reference
+  --> $DIR/index-mut-help.rs:12:5
+   |
+LL |     map["peter"] = "0".to_string();
+   |     ^^^^^^^^^^^^ cannot assign
+
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/index-mut-help.rs:13:13
+   |
+LL |     let _ = &mut map["peter"];
+   |             ^^^^^^^^^^^^^^^^^ cannot borrow as mutable
+   |
+   = help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `std::collections::HashMap<&str, std::string::String>`
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0594, E0596.
+For more information about an error, try `rustc --explain E0594`.
diff --git a/src/test/ui/borrowck/index-mut-help.rs b/src/test/ui/borrowck/index-mut-help.rs
new file mode 100644
index 0000000..d57ef97
--- /dev/null
+++ b/src/test/ui/borrowck/index-mut-help.rs
@@ -0,0 +1,14 @@
+// When mutably indexing a type that implements `Index` but not `IndexMut`, a
+// special 'help' message is added to the output.
+
+
+fn main() {
+    use std::collections::HashMap;
+
+    let mut map = HashMap::new();
+    map.insert("peter", "23".to_string());
+
+    map["peter"].clear();           //~ ERROR
+    map["peter"] = "0".to_string(); //~ ERROR
+    let _ = &mut map["peter"];      //~ ERROR
+}
diff --git a/src/test/ui/borrowck/index-mut-help.stderr b/src/test/ui/borrowck/index-mut-help.stderr
new file mode 100644
index 0000000..434dd11
--- /dev/null
+++ b/src/test/ui/borrowck/index-mut-help.stderr
@@ -0,0 +1,28 @@
+error[E0596]: cannot borrow immutable indexed content as mutable
+  --> $DIR/index-mut-help.rs:11:5
+   |
+LL |     map["peter"].clear();
+   |     ^^^^^^^^^^^^ cannot borrow as mutable
+   |
+   = help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `std::collections::HashMap<&str, std::string::String>`
+
+error[E0594]: cannot assign to immutable indexed content
+  --> $DIR/index-mut-help.rs:12:5
+   |
+LL |     map["peter"] = "0".to_string();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable
+   |
+   = help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `std::collections::HashMap<&str, std::string::String>`
+
+error[E0596]: cannot borrow immutable indexed content as mutable
+  --> $DIR/index-mut-help.rs:13:18
+   |
+LL |     let _ = &mut map["peter"];
+   |                  ^^^^^^^^^^^^ cannot borrow as mutable
+   |
+   = help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `std::collections::HashMap<&str, std::string::String>`
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0594, E0596.
+For more information about an error, try `rustc --explain E0594`.
diff --git a/src/test/ui/borrowck/issue-10876.rs b/src/test/ui/borrowck/issue-10876.rs
new file mode 100644
index 0000000..d8fff5f
--- /dev/null
+++ b/src/test/ui/borrowck/issue-10876.rs
@@ -0,0 +1,19 @@
+// run-pass
+
+#![feature(nll)]
+
+enum Nat {
+    S(Box<Nat>),
+    Z
+}
+fn test(x: &mut Nat) {
+    let mut p = &mut *x;
+    loop {
+        match p {
+            &mut Nat::Z => break,
+            &mut Nat::S(ref mut n) => p = &mut *n
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/issue-41962.rs b/src/test/ui/borrowck/issue-41962.rs
new file mode 100644
index 0000000..2bcc074
--- /dev/null
+++ b/src/test/ui/borrowck/issue-41962.rs
@@ -0,0 +1,13 @@
+// compile-flags: -Z borrowck=compare
+
+pub fn main(){
+    let maybe = Some(vec![true, true]);
+
+    loop {
+        if let Some(thing) = maybe {
+        }
+        //~^^ ERROR use of partially moved value: `maybe` (Ast) [E0382]
+        //~| ERROR use of moved value: `(maybe as std::prelude::v1::Some).0` (Ast) [E0382]
+        //~| ERROR use of moved value (Mir) [E0382]
+    }
+}
diff --git a/src/test/ui/borrowck/issue-41962.stderr b/src/test/ui/borrowck/issue-41962.stderr
new file mode 100644
index 0000000..fd4d318
--- /dev/null
+++ b/src/test/ui/borrowck/issue-41962.stderr
@@ -0,0 +1,29 @@
+error[E0382]: use of partially moved value: `maybe` (Ast)
+  --> $DIR/issue-41962.rs:7:30
+   |
+LL |         if let Some(thing) = maybe {
+   |                     -----    ^^^^^ value used here after move
+   |                     |
+   |                     value moved here
+   |
+   = note: move occurs because the value has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `(maybe as std::prelude::v1::Some).0` (Ast)
+  --> $DIR/issue-41962.rs:7:21
+   |
+LL |         if let Some(thing) = maybe {
+   |                     ^^^^^ value moved here in previous iteration of loop
+   |
+   = note: move occurs because the value has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value (Mir)
+  --> $DIR/issue-41962.rs:7:21
+   |
+LL |         if let Some(thing) = maybe {
+   |                     ^^^^^ value moved here, in previous iteration of loop
+   |
+   = note: move occurs because value has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/issue-45983.ast.stderr b/src/test/ui/borrowck/issue-45983.ast.stderr
new file mode 100644
index 0000000..9cb83c9
--- /dev/null
+++ b/src/test/ui/borrowck/issue-45983.ast.stderr
@@ -0,0 +1,12 @@
+error: borrowed data cannot be stored outside of its closure
+  --> $DIR/issue-45983.rs:26:27
+   |
+LL |     let x = None;
+   |         - borrowed data cannot be stored into here...
+LL |     give_any(|y| x = Some(y));
+   |              ---          ^ cannot be stored outside of its closure
+   |              |
+   |              ...because it cannot outlive this closure
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/borrowck/issue-45983.migrate.stderr b/src/test/ui/borrowck/issue-45983.migrate.stderr
new file mode 100644
index 0000000..9cb83c9
--- /dev/null
+++ b/src/test/ui/borrowck/issue-45983.migrate.stderr
@@ -0,0 +1,12 @@
+error: borrowed data cannot be stored outside of its closure
+  --> $DIR/issue-45983.rs:26:27
+   |
+LL |     let x = None;
+   |         - borrowed data cannot be stored into here...
+LL |     give_any(|y| x = Some(y));
+   |              ---          ^ cannot be stored outside of its closure
+   |              |
+   |              ...because it cannot outlive this closure
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/borrowck/issue-45983.nll.stderr b/src/test/ui/borrowck/issue-45983.nll.stderr
new file mode 100644
index 0000000..0a03858
--- /dev/null
+++ b/src/test/ui/borrowck/issue-45983.nll.stderr
@@ -0,0 +1,22 @@
+error[E0521]: borrowed data escapes outside of closure
+  --> $DIR/issue-45983.rs:26:18
+   |
+LL |     let x = None;
+   |         - `x` is declared here, outside of the closure body
+LL |     give_any(|y| x = Some(y));
+   |               -  ^^^^^^^^^^^ `y` escapes the closure body here
+   |               |
+   |               `y` is a reference that is only valid in the closure body
+
+error[E0594]: cannot assign to `x`, as it is not declared as mutable
+  --> $DIR/issue-45983.rs:26:18
+   |
+LL |     let x = None;
+   |         - help: consider changing this to be mutable: `mut x`
+LL |     give_any(|y| x = Some(y));
+   |                  ^^^^^^^^^^^ cannot assign
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0521, E0594.
+For more information about an error, try `rustc --explain E0521`.
diff --git a/src/test/ui/borrowck/issue-45983.rs b/src/test/ui/borrowck/issue-45983.rs
new file mode 100644
index 0000000..4dac67d
--- /dev/null
+++ b/src/test/ui/borrowck/issue-45983.rs
@@ -0,0 +1,31 @@
+// As documented in Issue #45983, this test is evaluating the quality
+// of our diagnostics on erroneous code using higher-ranked closures.
+//
+// However, as documented on Issue #53026, this test also became a
+// prime example of our need to test the NLL migration mode
+// *separately* from the existing test suites that focus solely on
+// AST-borrwock and NLL.
+
+// revisions: ast migrate nll
+
+// Since we are testing nll (and migration) explicitly as a separate
+// revisions, don't worry about the --compare-mode=nll on this test.
+
+// ignore-compare-mode-nll
+
+//[ast]compile-flags: -Z borrowck=ast
+//[migrate]compile-flags: -Z borrowck=migrate -Z two-phase-borrows
+//[nll]compile-flags: -Z borrowck=mir -Z two-phase-borrows
+
+fn give_any<F: for<'r> FnOnce(&'r ())>(f: F) {
+    f(&());
+}
+
+fn main() {
+    let x = None;
+    give_any(|y| x = Some(y));
+    //[ast]~^ ERROR borrowed data cannot be stored outside of its closure
+    //[migrate]~^^ ERROR borrowed data cannot be stored outside of its closure
+    //[nll]~^^^ ERROR borrowed data escapes outside of closure
+    //[nll]~| ERROR cannot assign to `x`, as it is not declared as mutable
+}
diff --git a/src/test/ui/borrowck/issue-47215-ice-from-drop-elab.nll.stderr b/src/test/ui/borrowck/issue-47215-ice-from-drop-elab.nll.stderr
new file mode 100644
index 0000000..eb71ab0
--- /dev/null
+++ b/src/test/ui/borrowck/issue-47215-ice-from-drop-elab.nll.stderr
@@ -0,0 +1,12 @@
+error[E0507]: cannot move out of static item
+  --> $DIR/issue-47215-ice-from-drop-elab.rs:17:21
+   |
+LL |         let mut x = X;
+   |                     ^
+   |                     |
+   |                     cannot move out of static item
+   |                     help: consider borrowing here: `&X`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/borrowck/issue-47215-ice-from-drop-elab.rs b/src/test/ui/borrowck/issue-47215-ice-from-drop-elab.rs
new file mode 100644
index 0000000..7477947
--- /dev/null
+++ b/src/test/ui/borrowck/issue-47215-ice-from-drop-elab.rs
@@ -0,0 +1,20 @@
+// rust-lang/rust#47215: at one time, the compiler categorized
+// thread-local statics as a temporary rvalue, as a way to enforce
+// that they are only valid for a given lifetime.
+//
+// The problem with this is that you cannot move out of static items,
+// but you *can* move temporary rvalues. I.e., the categorization
+// above only solves half of the problem presented by thread-local
+// statics.
+
+#![feature(thread_local)]
+
+#[thread_local]
+static mut X: ::std::sync::atomic::AtomicUsize = ::std::sync::atomic::AtomicUsize::new(0);
+
+fn main() {
+    unsafe {
+        let mut x = X; //~ ERROR cannot move out of thread-local static item [E0507]
+        let _y = x.get_mut();
+    }
+}
diff --git a/src/test/ui/borrowck/issue-47215-ice-from-drop-elab.stderr b/src/test/ui/borrowck/issue-47215-ice-from-drop-elab.stderr
new file mode 100644
index 0000000..b09028e
--- /dev/null
+++ b/src/test/ui/borrowck/issue-47215-ice-from-drop-elab.stderr
@@ -0,0 +1,12 @@
+error[E0507]: cannot move out of thread-local static item
+  --> $DIR/issue-47215-ice-from-drop-elab.rs:17:21
+   |
+LL |         let mut x = X;
+   |                     ^
+   |                     |
+   |                     cannot move out of thread-local static item
+   |                     help: consider using a reference instead: `&X`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/borrowck/issue-51117.nll.stderr b/src/test/ui/borrowck/issue-51117.nll.stderr
new file mode 100644
index 0000000..f8a9608
--- /dev/null
+++ b/src/test/ui/borrowck/issue-51117.nll.stderr
@@ -0,0 +1,13 @@
+error[E0499]: cannot borrow `*bar` as mutable more than once at a time
+  --> $DIR/issue-51117.rs:10:13
+   |
+LL |         Some(baz) => {
+   |              --- first mutable borrow occurs here
+LL |             bar.take();
+   |             ^^^ second mutable borrow occurs here
+LL |             drop(baz);
+   |                  --- first borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/borrowck/issue-51117.rs b/src/test/ui/borrowck/issue-51117.rs
new file mode 100644
index 0000000..e4664e4
--- /dev/null
+++ b/src/test/ui/borrowck/issue-51117.rs
@@ -0,0 +1,15 @@
+// Regression test for #51117 in borrowck interaction with match
+// default bindings. The borrow of `*bar` created by `baz` was failing
+// to register as a conflict with `bar.take()`.
+
+fn main() {
+    let mut foo = Some("foo".to_string());
+    let bar = &mut foo;
+    match bar {
+        Some(baz) => {
+            bar.take(); //~ ERROR cannot borrow
+            drop(baz);
+        },
+        None => unreachable!(),
+    }
+}
diff --git a/src/test/ui/borrowck/issue-51117.stderr b/src/test/ui/borrowck/issue-51117.stderr
new file mode 100644
index 0000000..8f2a786
--- /dev/null
+++ b/src/test/ui/borrowck/issue-51117.stderr
@@ -0,0 +1,14 @@
+error[E0499]: cannot borrow `*bar` as mutable more than once at a time
+  --> $DIR/issue-51117.rs:10:13
+   |
+LL |         Some(baz) => {
+   |              --- first mutable borrow occurs here
+LL |             bar.take();
+   |             ^^^ second mutable borrow occurs here
+...
+LL |     }
+   |     - first borrow ends here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/borrowck/issue-51348-multi-ref-mut-in-guard.rs b/src/test/ui/borrowck/issue-51348-multi-ref-mut-in-guard.rs
new file mode 100644
index 0000000..a8bfdba
--- /dev/null
+++ b/src/test/ui/borrowck/issue-51348-multi-ref-mut-in-guard.rs
@@ -0,0 +1,23 @@
+// We used to ICE if you had a single match arm with multiple
+// candidate patterns with `ref mut` identifiers used in the arm's
+// guard.
+//
+// Also, this test expands on the original bug's example by actually
+// trying to double check that we are matching against the right part
+// of the input data based on which candidate pattern actually fired.
+
+// run-pass
+
+#![feature(nll)]
+
+fn foo(x: &mut Result<(u32, u32), (u32, u32)>) -> u32 {
+    match *x {
+        Ok((ref mut v, _)) | Err((_, ref mut v)) if *v > 0 => { *v }
+        _ => { 0 }
+    }
+}
+
+fn main() {
+    assert_eq!(foo(&mut Ok((3, 4))), 3);
+    assert_eq!(foo(&mut Err((3, 4))), 4);
+}
diff --git a/src/test/ui/borrowck/issue-51415.nll.stderr b/src/test/ui/borrowck/issue-51415.nll.stderr
new file mode 100644
index 0000000..b025374
--- /dev/null
+++ b/src/test/ui/borrowck/issue-51415.nll.stderr
@@ -0,0 +1,18 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/issue-51415.rs:6:42
+   |
+LL |     let opt = a.iter().enumerate().find(|(_, &s)| {
+   |                                          ^^^^^-^
+   |                                          |    |
+   |                                          |    data moved here
+   |                                          cannot move out of borrowed content
+   |
+note: move occurs because `s` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/issue-51415.rs:6:47
+   |
+LL |     let opt = a.iter().enumerate().find(|(_, &s)| {
+   |                                               ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/borrowck/issue-51415.rs b/src/test/ui/borrowck/issue-51415.rs
new file mode 100644
index 0000000..f031308
--- /dev/null
+++ b/src/test/ui/borrowck/issue-51415.rs
@@ -0,0 +1,11 @@
+// Regression test for #51415: match default bindings were failing to
+// see the "move out" implied by `&s` below.
+
+fn main() {
+    let a = vec![String::from("a")];
+    let opt = a.iter().enumerate().find(|(_, &s)| {
+        //~^ ERROR cannot move out
+        *s == String::from("d")
+    }).map(|(i, _)| i);
+    println!("{:?}", opt);
+}
diff --git a/src/test/ui/borrowck/issue-51415.stderr b/src/test/ui/borrowck/issue-51415.stderr
new file mode 100644
index 0000000..895c35e
--- /dev/null
+++ b/src/test/ui/borrowck/issue-51415.stderr
@@ -0,0 +1,12 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/issue-51415.rs:6:46
+   |
+LL |     let opt = a.iter().enumerate().find(|(_, &s)| {
+   |                                              ^-
+   |                                              ||
+   |                                              |hint: to prevent move, use `ref s` or `ref mut s`
+   |                                              cannot move out of borrowed content
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/borrowck/issue-52713-bug.rs b/src/test/ui/borrowck/issue-52713-bug.rs
new file mode 100644
index 0000000..460e6b4
--- /dev/null
+++ b/src/test/ui/borrowck/issue-52713-bug.rs
@@ -0,0 +1,19 @@
+// Regression test for a bug in #52713: this was an optimization for
+// computing liveness that wound up accidentally causing the program
+// below to be accepted.
+
+#![feature(nll)]
+
+fn foo<'a>(x: &'a mut u32) -> u32 {
+    let mut x = 22;
+    let y = &x;
+    if false {
+        return x;
+    }
+
+    x += 1; //~ ERROR
+    println!("{}", y);
+    return 0;
+}
+
+fn main() { }
diff --git a/src/test/ui/borrowck/issue-52713-bug.stderr b/src/test/ui/borrowck/issue-52713-bug.stderr
new file mode 100644
index 0000000..e3216f5
--- /dev/null
+++ b/src/test/ui/borrowck/issue-52713-bug.stderr
@@ -0,0 +1,14 @@
+error[E0506]: cannot assign to `x` because it is borrowed
+  --> $DIR/issue-52713-bug.rs:14:5
+   |
+LL |     let y = &x;
+   |             -- borrow of `x` occurs here
+...
+LL |     x += 1;
+   |     ^^^^^^ assignment to borrowed `x` occurs here
+LL |     println!("{}", y);
+   |                    - borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/borrowck/issue-52967-edition-2018-needs-two-phase-borrows.rs b/src/test/ui/borrowck/issue-52967-edition-2018-needs-two-phase-borrows.rs
new file mode 100644
index 0000000..dcf047c
--- /dev/null
+++ b/src/test/ui/borrowck/issue-52967-edition-2018-needs-two-phase-borrows.rs
@@ -0,0 +1,22 @@
+// This is a regression test for #52967, where we discovered that in
+// the initial deployment of NLL for the 2018 edition, I forgot to
+// turn on two-phase-borrows in addition to `-Z borrowck=migrate`.
+
+// revisions: ast zflags edition
+//[zflags]compile-flags: -Z borrowck=migrate -Z two-phase-borrows
+//[edition]edition:2018
+
+// run-pass
+
+fn the_bug() {
+    let mut stuff = ("left", "right");
+    match stuff {
+        (ref mut left, _) if *left == "left" => { *left = "new left"; }
+        _ => {}
+    }
+    assert_eq!(stuff, ("new left", "right"));
+}
+
+fn main() {
+    the_bug();
+}
diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.ast.stderr b/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.ast.stderr
new file mode 100644
index 0000000..d72cc20
--- /dev/null
+++ b/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.ast.stderr
@@ -0,0 +1,39 @@
+error[E0381]: use of possibly uninitialized variable: `t.0`
+  --> $DIR/issue-54499-field-mutation-marks-mut-as-used.rs:25:31
+   |
+LL |         println!("{:?} {:?}", t.0, t.1);
+   |                               ^^^ use of possibly uninitialized `t.0`
+
+error[E0381]: use of possibly uninitialized variable: `t.1`
+  --> $DIR/issue-54499-field-mutation-marks-mut-as-used.rs:25:36
+   |
+LL |         println!("{:?} {:?}", t.0, t.1);
+   |                                    ^^^ use of possibly uninitialized `t.1`
+
+error[E0381]: use of possibly uninitialized variable: `u.0`
+  --> $DIR/issue-54499-field-mutation-marks-mut-as-used.rs:35:31
+   |
+LL |         println!("{:?} {:?}", u.0, u.1);
+   |                               ^^^ use of possibly uninitialized `u.0`
+
+error[E0381]: use of possibly uninitialized variable: `u.1`
+  --> $DIR/issue-54499-field-mutation-marks-mut-as-used.rs:35:36
+   |
+LL |         println!("{:?} {:?}", u.0, u.1);
+   |                                    ^^^ use of possibly uninitialized `u.1`
+
+error[E0381]: use of possibly uninitialized variable: `v.x`
+  --> $DIR/issue-54499-field-mutation-marks-mut-as-used.rs:45:31
+   |
+LL |         println!("{:?} {:?}", v.x, v.y);
+   |                               ^^^ use of possibly uninitialized `v.x`
+
+error[E0381]: use of possibly uninitialized variable: `v.y`
+  --> $DIR/issue-54499-field-mutation-marks-mut-as-used.rs:45:36
+   |
+LL |         println!("{:?} {:?}", v.x, v.y);
+   |                                    ^^^ use of possibly uninitialized `v.y`
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.nll.stderr b/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.nll.stderr
new file mode 100644
index 0000000..ebc6c7f
--- /dev/null
+++ b/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.nll.stderr
@@ -0,0 +1,21 @@
+error[E0381]: assign to part of possibly uninitialized variable: `t`
+  --> $DIR/issue-54499-field-mutation-marks-mut-as-used.rs:22:9
+   |
+LL |         t.0 = S(1);
+   |         ^^^^^^^^^^ use of possibly uninitialized `t`
+
+error[E0381]: assign to part of possibly uninitialized variable: `u`
+  --> $DIR/issue-54499-field-mutation-marks-mut-as-used.rs:32:9
+   |
+LL |         u.0 = S(1);
+   |         ^^^^^^^^^^ use of possibly uninitialized `u`
+
+error[E0381]: assign to part of possibly uninitialized variable: `v`
+  --> $DIR/issue-54499-field-mutation-marks-mut-as-used.rs:42:9
+   |
+LL |         v.x = S(1);
+   |         ^^^^^^^^^^ use of possibly uninitialized `v`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.rs b/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.rs
new file mode 100644
index 0000000..4358e8e
--- /dev/null
+++ b/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.rs
@@ -0,0 +1,49 @@
+// revisions: ast nll
+
+// Since we are testing nll migration explicitly as a separate
+// revision, don't worry about the --compare-mode=nll on this test.
+
+// ignore-compare-mode-nll
+
+//[ast]compile-flags: -Z borrowck=ast
+//[nll]compile-flags: -Z borrowck=migrate -Z two-phase-borrows
+
+#![warn(unused)]
+#[derive(Debug)]
+struct S(i32);
+
+type Tuple = (S, i32);
+struct Tpair(S, i32);
+struct Spair { x: S, y: i32 }
+
+fn main() {
+    {
+        let mut t: Tuple;
+        t.0 = S(1);
+        //[nll]~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381]
+        t.1 = 2;
+        println!("{:?} {:?}", t.0, t.1);
+        //[ast]~^ ERROR use of possibly uninitialized variable: `t.0` [E0381]
+        //[ast]~| ERROR use of possibly uninitialized variable: `t.1` [E0381]
+    }
+
+    {
+        let mut u: Tpair;
+        u.0 = S(1);
+        //[nll]~^ ERROR assign to part of possibly uninitialized variable: `u` [E0381]
+        u.1 = 2;
+        println!("{:?} {:?}", u.0, u.1);
+        //[ast]~^ ERROR use of possibly uninitialized variable: `u.0` [E0381]
+        //[ast]~| ERROR use of possibly uninitialized variable: `u.1` [E0381]
+    }
+
+    {
+        let mut v: Spair;
+        v.x = S(1);
+        //[nll]~^ ERROR assign to part of possibly uninitialized variable: `v` [E0381]
+        v.y = 2;
+        println!("{:?} {:?}", v.x, v.y);
+        //[ast]~^ ERROR use of possibly uninitialized variable: `v.x` [E0381]
+        //[ast]~| ERROR use of possibly uninitialized variable: `v.y` [E0381]
+    }
+}
diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out-with-mut.ast.stderr b/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out-with-mut.ast.stderr
new file mode 100644
index 0000000..4f845d8
--- /dev/null
+++ b/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out-with-mut.ast.stderr
@@ -0,0 +1,69 @@
+error[E0382]: use of moved value: `t.0`
+  --> $DIR/issue-54499-field-mutation-of-moved-out-with-mut.rs:26:31
+   |
+LL |         drop(t);
+   |              - value moved here
+...
+LL |         println!("{:?} {:?}", t.0, t.1);
+   |                               ^^^ value used here after move
+   |
+   = note: move occurs because `t` has type `(S, i32)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `t.1`
+  --> $DIR/issue-54499-field-mutation-of-moved-out-with-mut.rs:26:36
+   |
+LL |         drop(t);
+   |              - value moved here
+...
+LL |         println!("{:?} {:?}", t.0, t.1);
+   |                                    ^^^ value used here after move
+   |
+   = note: move occurs because `t` has type `(S, i32)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `u.0`
+  --> $DIR/issue-54499-field-mutation-of-moved-out-with-mut.rs:37:31
+   |
+LL |         drop(u);
+   |              - value moved here
+...
+LL |         println!("{:?} {:?}", u.0, u.1);
+   |                               ^^^ value used here after move
+   |
+   = note: move occurs because `u` has type `Tpair`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `u.1`
+  --> $DIR/issue-54499-field-mutation-of-moved-out-with-mut.rs:37:36
+   |
+LL |         drop(u);
+   |              - value moved here
+...
+LL |         println!("{:?} {:?}", u.0, u.1);
+   |                                    ^^^ value used here after move
+   |
+   = note: move occurs because `u` has type `Tpair`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `v.x`
+  --> $DIR/issue-54499-field-mutation-of-moved-out-with-mut.rs:48:31
+   |
+LL |         drop(v);
+   |              - value moved here
+...
+LL |         println!("{:?} {:?}", v.x, v.y);
+   |                               ^^^ value used here after move
+   |
+   = note: move occurs because `v` has type `Spair`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `v.y`
+  --> $DIR/issue-54499-field-mutation-of-moved-out-with-mut.rs:48:36
+   |
+LL |         drop(v);
+   |              - value moved here
+...
+LL |         println!("{:?} {:?}", v.x, v.y);
+   |                                    ^^^ value used here after move
+   |
+   = note: move occurs because `v` has type `Spair`, which does not implement the `Copy` trait
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out-with-mut.nll.stderr b/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out-with-mut.nll.stderr
new file mode 100644
index 0000000..42aa038
--- /dev/null
+++ b/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out-with-mut.nll.stderr
@@ -0,0 +1,33 @@
+error[E0382]: assign to part of moved value: `t`
+  --> $DIR/issue-54499-field-mutation-of-moved-out-with-mut.rs:23:9
+   |
+LL |         let mut t: Tuple = (S(0), 0);
+   |             ----- move occurs because `t` has type `(S, i32)`, which does not implement the `Copy` trait
+LL |         drop(t);
+   |              - value moved here
+LL |         t.0 = S(1);
+   |         ^^^^^^^^^^ value partially assigned here after move
+
+error[E0382]: assign to part of moved value: `u`
+  --> $DIR/issue-54499-field-mutation-of-moved-out-with-mut.rs:34:9
+   |
+LL |         let mut u: Tpair = Tpair(S(0), 0);
+   |             ----- move occurs because `u` has type `Tpair`, which does not implement the `Copy` trait
+LL |         drop(u);
+   |              - value moved here
+LL |         u.0 = S(1);
+   |         ^^^^^^^^^^ value partially assigned here after move
+
+error[E0382]: assign to part of moved value: `v`
+  --> $DIR/issue-54499-field-mutation-of-moved-out-with-mut.rs:45:9
+   |
+LL |         let mut v: Spair = Spair { x: S(0), y: 0 };
+   |             ----- move occurs because `v` has type `Spair`, which does not implement the `Copy` trait
+LL |         drop(v);
+   |              - value moved here
+LL |         v.x = S(1);
+   |         ^^^^^^^^^^ value partially assigned here after move
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out-with-mut.rs b/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out-with-mut.rs
new file mode 100644
index 0000000..358a5dd
--- /dev/null
+++ b/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out-with-mut.rs
@@ -0,0 +1,52 @@
+// revisions: ast nll
+
+// Since we are testing nll migration explicitly as a separate
+// revision, don't worry about the --compare-mode=nll on this test.
+
+// ignore-compare-mode-nll
+
+//[ast]compile-flags: -Z borrowck=ast
+//[nll]compile-flags: -Z borrowck=migrate -Z two-phase-borrows
+
+#![warn(unused)]
+#[derive(Debug)]
+struct S(i32);
+
+type Tuple = (S, i32);
+struct Tpair(S, i32);
+struct Spair { x: S, y: i32 }
+
+fn main() {
+    {
+        let mut t: Tuple = (S(0), 0);
+        drop(t);
+        t.0 = S(1);
+        //[nll]~^ ERROR assign to part of moved value
+        t.1 = 2;
+        println!("{:?} {:?}", t.0, t.1);
+        //[ast]~^ ERROR use of moved value
+        //[ast]~^^ ERROR use of moved value
+    }
+
+    {
+        let mut u: Tpair = Tpair(S(0), 0);
+        drop(u);
+        u.0 = S(1);
+        //[nll]~^ ERROR assign to part of moved value
+        u.1 = 2;
+        println!("{:?} {:?}", u.0, u.1);
+        //[ast]~^ ERROR use of moved value
+        //[ast]~^^ ERROR use of moved value
+    }
+
+    {
+        let mut v: Spair = Spair { x: S(0), y: 0 };
+        drop(v);
+        v.x = S(1);
+        //[nll]~^ ERROR assign to part of moved value
+        v.y = 2;
+        println!("{:?} {:?}", v.x, v.y);
+        //[ast]~^ ERROR use of moved value
+        //[ast]~^^ ERROR use of moved value
+    }
+}
diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out.ast.stderr b/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out.ast.stderr
new file mode 100644
index 0000000..565272a
--- /dev/null
+++ b/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out.ast.stderr
@@ -0,0 +1,124 @@
+error[E0594]: cannot assign to field `t.0` of immutable binding
+  --> $DIR/issue-54499-field-mutation-of-moved-out.rs:23:9
+   |
+LL |         let t: Tuple = (S(0), 0);
+   |             - help: make this binding mutable: `mut t`
+LL |         drop(t);
+LL |         t.0 = S(1);
+   |         ^^^^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0594]: cannot assign to field `t.1` of immutable binding
+  --> $DIR/issue-54499-field-mutation-of-moved-out.rs:27:9
+   |
+LL |         let t: Tuple = (S(0), 0);
+   |             - help: make this binding mutable: `mut t`
+...
+LL |         t.1 = 2;
+   |         ^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0594]: cannot assign to field `u.0` of immutable binding
+  --> $DIR/issue-54499-field-mutation-of-moved-out.rs:38:9
+   |
+LL |         let u: Tpair = Tpair(S(0), 0);
+   |             - help: make this binding mutable: `mut u`
+LL |         drop(u);
+LL |         u.0 = S(1);
+   |         ^^^^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0594]: cannot assign to field `u.1` of immutable binding
+  --> $DIR/issue-54499-field-mutation-of-moved-out.rs:42:9
+   |
+LL |         let u: Tpair = Tpair(S(0), 0);
+   |             - help: make this binding mutable: `mut u`
+...
+LL |         u.1 = 2;
+   |         ^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0594]: cannot assign to field `v.x` of immutable binding
+  --> $DIR/issue-54499-field-mutation-of-moved-out.rs:53:9
+   |
+LL |         let v: Spair = Spair { x: S(0), y: 0 };
+   |             - help: make this binding mutable: `mut v`
+LL |         drop(v);
+LL |         v.x = S(1);
+   |         ^^^^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0594]: cannot assign to field `v.y` of immutable binding
+  --> $DIR/issue-54499-field-mutation-of-moved-out.rs:57:9
+   |
+LL |         let v: Spair = Spair { x: S(0), y: 0 };
+   |             - help: make this binding mutable: `mut v`
+...
+LL |         v.y = 2;
+   |         ^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0382]: use of moved value: `t.0`
+  --> $DIR/issue-54499-field-mutation-of-moved-out.rs:30:31
+   |
+LL |         drop(t);
+   |              - value moved here
+...
+LL |         println!("{:?} {:?}", t.0, t.1);
+   |                               ^^^ value used here after move
+   |
+   = note: move occurs because `t` has type `(S, i32)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `t.1`
+  --> $DIR/issue-54499-field-mutation-of-moved-out.rs:30:36
+   |
+LL |         drop(t);
+   |              - value moved here
+...
+LL |         println!("{:?} {:?}", t.0, t.1);
+   |                                    ^^^ value used here after move
+   |
+   = note: move occurs because `t` has type `(S, i32)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `u.0`
+  --> $DIR/issue-54499-field-mutation-of-moved-out.rs:45:31
+   |
+LL |         drop(u);
+   |              - value moved here
+...
+LL |         println!("{:?} {:?}", u.0, u.1);
+   |                               ^^^ value used here after move
+   |
+   = note: move occurs because `u` has type `Tpair`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `u.1`
+  --> $DIR/issue-54499-field-mutation-of-moved-out.rs:45:36
+   |
+LL |         drop(u);
+   |              - value moved here
+...
+LL |         println!("{:?} {:?}", u.0, u.1);
+   |                                    ^^^ value used here after move
+   |
+   = note: move occurs because `u` has type `Tpair`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `v.x`
+  --> $DIR/issue-54499-field-mutation-of-moved-out.rs:60:31
+   |
+LL |         drop(v);
+   |              - value moved here
+...
+LL |         println!("{:?} {:?}", v.x, v.y);
+   |                               ^^^ value used here after move
+   |
+   = note: move occurs because `v` has type `Spair`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `v.y`
+  --> $DIR/issue-54499-field-mutation-of-moved-out.rs:60:36
+   |
+LL |         drop(v);
+   |              - value moved here
+...
+LL |         println!("{:?} {:?}", v.x, v.y);
+   |                                    ^^^ value used here after move
+   |
+   = note: move occurs because `v` has type `Spair`, which does not implement the `Copy` trait
+
+error: aborting due to 12 previous errors
+
+Some errors occurred: E0382, E0594.
+For more information about an error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out.nll.stderr b/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out.nll.stderr
new file mode 100644
index 0000000..1184907
--- /dev/null
+++ b/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out.nll.stderr
@@ -0,0 +1,88 @@
+error[E0594]: cannot assign to `t.0`, as `t` is not declared as mutable
+  --> $DIR/issue-54499-field-mutation-of-moved-out.rs:23:9
+   |
+LL |         let t: Tuple = (S(0), 0);
+   |             - help: consider changing this to be mutable: `mut t`
+LL |         drop(t);
+LL |         t.0 = S(1);
+   |         ^^^^^^^^^^ cannot assign
+
+error[E0382]: assign to part of moved value: `t`
+  --> $DIR/issue-54499-field-mutation-of-moved-out.rs:23:9
+   |
+LL |         let t: Tuple = (S(0), 0);
+   |             - move occurs because `t` has type `(S, i32)`, which does not implement the `Copy` trait
+LL |         drop(t);
+   |              - value moved here
+LL |         t.0 = S(1);
+   |         ^^^^^^^^^^ value partially assigned here after move
+
+error[E0594]: cannot assign to `t.1`, as `t` is not declared as mutable
+  --> $DIR/issue-54499-field-mutation-of-moved-out.rs:27:9
+   |
+LL |         let t: Tuple = (S(0), 0);
+   |             - help: consider changing this to be mutable: `mut t`
+...
+LL |         t.1 = 2;
+   |         ^^^^^^^ cannot assign
+
+error[E0594]: cannot assign to `u.0`, as `u` is not declared as mutable
+  --> $DIR/issue-54499-field-mutation-of-moved-out.rs:38:9
+   |
+LL |         let u: Tpair = Tpair(S(0), 0);
+   |             - help: consider changing this to be mutable: `mut u`
+LL |         drop(u);
+LL |         u.0 = S(1);
+   |         ^^^^^^^^^^ cannot assign
+
+error[E0382]: assign to part of moved value: `u`
+  --> $DIR/issue-54499-field-mutation-of-moved-out.rs:38:9
+   |
+LL |         let u: Tpair = Tpair(S(0), 0);
+   |             - move occurs because `u` has type `Tpair`, which does not implement the `Copy` trait
+LL |         drop(u);
+   |              - value moved here
+LL |         u.0 = S(1);
+   |         ^^^^^^^^^^ value partially assigned here after move
+
+error[E0594]: cannot assign to `u.1`, as `u` is not declared as mutable
+  --> $DIR/issue-54499-field-mutation-of-moved-out.rs:42:9
+   |
+LL |         let u: Tpair = Tpair(S(0), 0);
+   |             - help: consider changing this to be mutable: `mut u`
+...
+LL |         u.1 = 2;
+   |         ^^^^^^^ cannot assign
+
+error[E0594]: cannot assign to `v.x`, as `v` is not declared as mutable
+  --> $DIR/issue-54499-field-mutation-of-moved-out.rs:53:9
+   |
+LL |         let v: Spair = Spair { x: S(0), y: 0 };
+   |             - help: consider changing this to be mutable: `mut v`
+LL |         drop(v);
+LL |         v.x = S(1);
+   |         ^^^^^^^^^^ cannot assign
+
+error[E0382]: assign to part of moved value: `v`
+  --> $DIR/issue-54499-field-mutation-of-moved-out.rs:53:9
+   |
+LL |         let v: Spair = Spair { x: S(0), y: 0 };
+   |             - move occurs because `v` has type `Spair`, which does not implement the `Copy` trait
+LL |         drop(v);
+   |              - value moved here
+LL |         v.x = S(1);
+   |         ^^^^^^^^^^ value partially assigned here after move
+
+error[E0594]: cannot assign to `v.y`, as `v` is not declared as mutable
+  --> $DIR/issue-54499-field-mutation-of-moved-out.rs:57:9
+   |
+LL |         let v: Spair = Spair { x: S(0), y: 0 };
+   |             - help: consider changing this to be mutable: `mut v`
+...
+LL |         v.y = 2;
+   |         ^^^^^^^ cannot assign
+
+error: aborting due to 9 previous errors
+
+Some errors occurred: E0382, E0594.
+For more information about an error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out.rs b/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out.rs
new file mode 100644
index 0000000..b19dcd6
--- /dev/null
+++ b/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out.rs
@@ -0,0 +1,64 @@
+// revisions: ast nll
+
+// Since we are testing nll migration explicitly as a separate
+// revision, don't worry about the --compare-mode=nll on this test.
+
+// ignore-compare-mode-nll
+
+//[ast]compile-flags: -Z borrowck=ast
+//[nll]compile-flags: -Z borrowck=migrate -Z two-phase-borrows
+
+#![warn(unused)]
+#[derive(Debug)]
+struct S(i32);
+
+type Tuple = (S, i32);
+struct Tpair(S, i32);
+struct Spair { x: S, y: i32 }
+
+fn main() {
+    {
+        let t: Tuple = (S(0), 0);
+        drop(t);
+        t.0 = S(1);
+        //[ast]~^ ERROR cannot assign to field `t.0` of immutable binding [E0594]
+        //[nll]~^^ ERROR assign to part of moved value: `t` [E0382]
+        //[nll]~| ERROR cannot assign to `t.0`, as `t` is not declared as mutable [E0594]
+        t.1 = 2;
+        //[ast]~^ ERROR cannot assign to field `t.1` of immutable binding [E0594]
+        //[nll]~^^ ERROR cannot assign to `t.1`, as `t` is not declared as mutable [E0594]
+        println!("{:?} {:?}", t.0, t.1);
+        //[ast]~^ ERROR use of moved value: `t.0` [E0382]
+        //[ast]~| ERROR use of moved value: `t.1` [E0382]
+    }
+
+    {
+        let u: Tpair = Tpair(S(0), 0);
+        drop(u);
+        u.0 = S(1);
+        //[ast]~^ ERROR cannot assign to field `u.0` of immutable binding [E0594]
+        //[nll]~^^ ERROR assign to part of moved value: `u` [E0382]
+        //[nll]~| ERROR cannot assign to `u.0`, as `u` is not declared as mutable [E0594]
+        u.1 = 2;
+        //[ast]~^ ERROR cannot assign to field `u.1` of immutable binding [E0594]
+        //[nll]~^^ ERROR cannot assign to `u.1`, as `u` is not declared as mutable [E0594]
+        println!("{:?} {:?}", u.0, u.1);
+        //[ast]~^ ERROR use of moved value: `u.0` [E0382]
+        //[ast]~| ERROR use of moved value: `u.1` [E0382]
+    }
+
+    {
+        let v: Spair = Spair { x: S(0), y: 0 };
+        drop(v);
+        v.x = S(1);
+        //[ast]~^ ERROR cannot assign to field `v.x` of immutable binding [E0594]
+        //[nll]~^^ ERROR assign to part of moved value: `v` [E0382]
+        //[nll]~| ERROR cannot assign to `v.x`, as `v` is not declared as mutable [E0594]
+        v.y = 2;
+        //[ast]~^ ERROR cannot assign to field `v.y` of immutable binding [E0594]
+        //[nll]~^^ ERROR cannot assign to `v.y`, as `v` is not declared as mutable [E0594]
+        println!("{:?} {:?}", v.x, v.y);
+        //[ast]~^ ERROR use of moved value: `v.x` [E0382]
+        //[ast]~| ERROR use of moved value: `v.y` [E0382]
+    }
+}
diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.ast.stderr b/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.ast.stderr
new file mode 100644
index 0000000..ea6b63b
--- /dev/null
+++ b/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.ast.stderr
@@ -0,0 +1,91 @@
+error[E0594]: cannot assign to field `t.0` of immutable binding
+  --> $DIR/issue-54499-field-mutation-of-never-init.rs:22:9
+   |
+LL |         let t: Tuple;
+   |             - help: make this binding mutable: `mut t`
+LL |         t.0 = S(1);
+   |         ^^^^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0594]: cannot assign to field `t.1` of immutable binding
+  --> $DIR/issue-54499-field-mutation-of-never-init.rs:25:9
+   |
+LL |         let t: Tuple;
+   |             - help: make this binding mutable: `mut t`
+...
+LL |         t.1 = 2;
+   |         ^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0594]: cannot assign to field `u.0` of immutable binding
+  --> $DIR/issue-54499-field-mutation-of-never-init.rs:34:9
+   |
+LL |         let u: Tpair;
+   |             - help: make this binding mutable: `mut u`
+LL |         u.0 = S(1);
+   |         ^^^^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0594]: cannot assign to field `u.1` of immutable binding
+  --> $DIR/issue-54499-field-mutation-of-never-init.rs:37:9
+   |
+LL |         let u: Tpair;
+   |             - help: make this binding mutable: `mut u`
+...
+LL |         u.1 = 2;
+   |         ^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0594]: cannot assign to field `v.x` of immutable binding
+  --> $DIR/issue-54499-field-mutation-of-never-init.rs:46:9
+   |
+LL |         let v: Spair;
+   |             - help: make this binding mutable: `mut v`
+LL |         v.x = S(1);
+   |         ^^^^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0594]: cannot assign to field `v.y` of immutable binding
+  --> $DIR/issue-54499-field-mutation-of-never-init.rs:49:9
+   |
+LL |         let v: Spair;
+   |             - help: make this binding mutable: `mut v`
+...
+LL |         v.y = 2;
+   |         ^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0381]: use of possibly uninitialized variable: `t.0`
+  --> $DIR/issue-54499-field-mutation-of-never-init.rs:27:31
+   |
+LL |         println!("{:?} {:?}", t.0, t.1);
+   |                               ^^^ use of possibly uninitialized `t.0`
+
+error[E0381]: use of possibly uninitialized variable: `t.1`
+  --> $DIR/issue-54499-field-mutation-of-never-init.rs:27:36
+   |
+LL |         println!("{:?} {:?}", t.0, t.1);
+   |                                    ^^^ use of possibly uninitialized `t.1`
+
+error[E0381]: use of possibly uninitialized variable: `u.0`
+  --> $DIR/issue-54499-field-mutation-of-never-init.rs:39:31
+   |
+LL |         println!("{:?} {:?}", u.0, u.1);
+   |                               ^^^ use of possibly uninitialized `u.0`
+
+error[E0381]: use of possibly uninitialized variable: `u.1`
+  --> $DIR/issue-54499-field-mutation-of-never-init.rs:39:36
+   |
+LL |         println!("{:?} {:?}", u.0, u.1);
+   |                                    ^^^ use of possibly uninitialized `u.1`
+
+error[E0381]: use of possibly uninitialized variable: `v.x`
+  --> $DIR/issue-54499-field-mutation-of-never-init.rs:51:31
+   |
+LL |         println!("{:?} {:?}", v.x, v.y);
+   |                               ^^^ use of possibly uninitialized `v.x`
+
+error[E0381]: use of possibly uninitialized variable: `v.y`
+  --> $DIR/issue-54499-field-mutation-of-never-init.rs:51:36
+   |
+LL |         println!("{:?} {:?}", v.x, v.y);
+   |                                    ^^^ use of possibly uninitialized `v.y`
+
+error: aborting due to 12 previous errors
+
+Some errors occurred: E0381, E0594.
+For more information about an error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.nll.stderr b/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.nll.stderr
new file mode 100644
index 0000000..3dc2b5b
--- /dev/null
+++ b/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.nll.stderr
@@ -0,0 +1,21 @@
+error[E0381]: assign to part of possibly uninitialized variable: `t`
+  --> $DIR/issue-54499-field-mutation-of-never-init.rs:22:9
+   |
+LL |         t.0 = S(1);
+   |         ^^^^^^^^^^ use of possibly uninitialized `t`
+
+error[E0381]: assign to part of possibly uninitialized variable: `u`
+  --> $DIR/issue-54499-field-mutation-of-never-init.rs:34:9
+   |
+LL |         u.0 = S(1);
+   |         ^^^^^^^^^^ use of possibly uninitialized `u`
+
+error[E0381]: assign to part of possibly uninitialized variable: `v`
+  --> $DIR/issue-54499-field-mutation-of-never-init.rs:46:9
+   |
+LL |         v.x = S(1);
+   |         ^^^^^^^^^^ use of possibly uninitialized `v`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.rs b/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.rs
new file mode 100644
index 0000000..03eb962
--- /dev/null
+++ b/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.rs
@@ -0,0 +1,55 @@
+// revisions: ast nll
+
+// Since we are testing nll migration explicitly as a separate
+// revision, don't worry about the --compare-mode=nll on this test.
+
+// ignore-compare-mode-nll
+
+//[ast]compile-flags: -Z borrowck=ast
+//[nll]compile-flags: -Z borrowck=migrate -Z two-phase-borrows
+
+#![warn(unused)]
+#[derive(Debug)]
+struct S(i32);
+
+type Tuple = (S, i32);
+struct Tpair(S, i32);
+struct Spair { x: S, y: i32 }
+
+fn main() {
+    {
+        let t: Tuple;
+        t.0 = S(1);
+        //[ast]~^ ERROR cannot assign to field `t.0` of immutable binding [E0594]
+        //[nll]~^^ ERROR assign to part of possibly uninitialized variable: `t` [E0381]
+        t.1 = 2;
+        //[ast]~^ ERROR cannot assign to field `t.1` of immutable binding [E0594]
+        println!("{:?} {:?}", t.0, t.1);
+        //[ast]~^ ERROR use of possibly uninitialized variable: `t.0` [E0381]
+        //[ast]~| ERROR use of possibly uninitialized variable: `t.1` [E0381]
+    }
+
+    {
+        let u: Tpair;
+        u.0 = S(1);
+        //[ast]~^ ERROR cannot assign to field `u.0` of immutable binding [E0594]
+        //[nll]~^^ ERROR assign to part of possibly uninitialized variable: `u` [E0381]
+        u.1 = 2;
+        //[ast]~^ ERROR cannot assign to field `u.1` of immutable binding [E0594]
+        println!("{:?} {:?}", u.0, u.1);
+        //[ast]~^ ERROR use of possibly uninitialized variable: `u.0` [E0381]
+        //[ast]~| ERROR use of possibly uninitialized variable: `u.1` [E0381]
+    }
+
+    {
+        let v: Spair;
+        v.x = S(1);
+        //[ast]~^ ERROR cannot assign to field `v.x` of immutable binding [E0594]
+        //[nll]~^^ ERROR assign to part of possibly uninitialized variable: `v` [E0381]
+        v.y = 2;
+        //[ast]~^ ERROR cannot assign to field `v.y` of immutable binding [E0594]
+        println!("{:?} {:?}", v.x, v.y);
+        //[ast]~^ ERROR use of possibly uninitialized variable: `v.x` [E0381]
+        //[ast]~| ERROR use of possibly uninitialized variable: `v.y` [E0381]
+    }
+}
diff --git a/src/test/ui/borrowck/issue-54597-reject-move-out-of-borrow-via-pat.rs b/src/test/ui/borrowck/issue-54597-reject-move-out-of-borrow-via-pat.rs
new file mode 100644
index 0000000..ad4accb
--- /dev/null
+++ b/src/test/ui/borrowck/issue-54597-reject-move-out-of-borrow-via-pat.rs
@@ -0,0 +1,22 @@
+#![feature(nll)]
+
+#![allow(dead_code)]
+
+#[derive(Debug)]
+struct Value;
+impl Value {
+    fn as_array(&self) -> Option<&Vec<Value>> {
+        None
+    }
+}
+
+fn foo(val: Value) {
+    let _reviewers_original: Vec<Value> = match val.as_array() {
+        Some(array) => {
+            *array //~ ERROR cannot move out of borrowed content
+        }
+        None => vec![]
+    };
+}
+
+fn main() { }
diff --git a/src/test/ui/borrowck/issue-54597-reject-move-out-of-borrow-via-pat.stderr b/src/test/ui/borrowck/issue-54597-reject-move-out-of-borrow-via-pat.stderr
new file mode 100644
index 0000000..6a12016
--- /dev/null
+++ b/src/test/ui/borrowck/issue-54597-reject-move-out-of-borrow-via-pat.stderr
@@ -0,0 +1,12 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/issue-54597-reject-move-out-of-borrow-via-pat.rs:16:13
+   |
+LL |             *array
+   |             ^^^^^^
+   |             |
+   |             cannot move out of borrowed content
+   |             help: consider removing the `*`: `array`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.ast.stderr b/src/test/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.ast.stderr
new file mode 100644
index 0000000..f3e9ce3
--- /dev/null
+++ b/src/test/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.ast.stderr
@@ -0,0 +1,55 @@
+error[E0595]: closure cannot assign to immutable argument `x`
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:21:22
+   |
+LL |         let mut c1 = |y: &'static mut isize| x = y;
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^ cannot borrow mutably
+help: consider removing the `&mut`, as it is an immutable binding to a mutable reference
+   |
+LL |         x
+   |
+
+error[E0595]: closure cannot assign to immutable argument `x`
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:32:22
+   |
+LL |         let mut c1 = |z: &'static mut isize| {
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^ cannot borrow mutably
+help: consider removing the `&mut`, as it is an immutable binding to a mutable reference
+   |
+LL |         x
+   |
+
+error[E0595]: closure cannot assign to immutable argument `x`
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:46:9
+   |
+LL |     pub fn capture_assign_whole(x: (i32,)) {
+   |                                 - help: make this binding mutable: `mut x`
+LL |         || { x = (1,); };
+   |         ^^ cannot borrow mutably
+
+error[E0595]: closure cannot assign to immutable argument `x`
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:52:9
+   |
+LL |     pub fn capture_assign_part(x: (i32,)) {
+   |                                - help: make this binding mutable: `mut x`
+LL |         || { x.0 = 1; };
+   |         ^^ cannot borrow mutably
+
+error[E0595]: closure cannot assign to immutable argument `x`
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:58:9
+   |
+LL |     pub fn capture_reborrow_whole(x: (i32,)) {
+   |                                   - help: make this binding mutable: `mut x`
+LL |         || { &mut x; };
+   |         ^^ cannot borrow mutably
+
+error[E0595]: closure cannot assign to immutable argument `x`
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:64:9
+   |
+LL |     pub fn capture_reborrow_part(x: (i32,)) {
+   |                                  - help: make this binding mutable: `mut x`
+LL |         || { &mut x.0; };
+   |         ^^ cannot borrow mutably
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0595`.
diff --git a/src/test/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.migrate.stderr b/src/test/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.migrate.stderr
new file mode 100644
index 0000000..434f318
--- /dev/null
+++ b/src/test/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.migrate.stderr
@@ -0,0 +1,54 @@
+error[E0594]: cannot assign to `x`, as it is not declared as mutable
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:21:46
+   |
+LL |     pub fn e(x: &'static mut isize) {
+   |              - help: consider changing this to be mutable: `mut x`
+LL |         static mut Y: isize = 3;
+LL |         let mut c1 = |y: &'static mut isize| x = y;
+   |                                              ^^^^^ cannot assign
+
+error[E0594]: cannot assign to `x`, as it is not declared as mutable
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:34:50
+   |
+LL |     pub fn ee(x: &'static mut isize) {
+   |               - help: consider changing this to be mutable: `mut x`
+...
+LL |             let mut c2 = |y: &'static mut isize| x = y;
+   |                                                  ^^^^^ cannot assign
+
+error[E0594]: cannot assign to `x`, as it is not declared as mutable
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:46:14
+   |
+LL |     pub fn capture_assign_whole(x: (i32,)) {
+   |                                 - help: consider changing this to be mutable: `mut x`
+LL |         || { x = (1,); };
+   |              ^^^^^^^^ cannot assign
+
+error[E0594]: cannot assign to `x.0`, as `x` is not declared as mutable
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:52:14
+   |
+LL |     pub fn capture_assign_part(x: (i32,)) {
+   |                                - help: consider changing this to be mutable: `mut x`
+LL |         || { x.0 = 1; };
+   |              ^^^^^^^ cannot assign
+
+error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:58:14
+   |
+LL |     pub fn capture_reborrow_whole(x: (i32,)) {
+   |                                   - help: consider changing this to be mutable: `mut x`
+LL |         || { &mut x; };
+   |              ^^^^^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow `x.0` as mutable, as `x` is not declared as mutable
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:64:14
+   |
+LL |     pub fn capture_reborrow_part(x: (i32,)) {
+   |                                  - help: consider changing this to be mutable: `mut x`
+LL |         || { &mut x.0; };
+   |              ^^^^^^^^ cannot borrow as mutable
+
+error: aborting due to 6 previous errors
+
+Some errors occurred: E0594, E0596.
+For more information about an error, try `rustc --explain E0594`.
diff --git a/src/test/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.nll.stderr b/src/test/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.nll.stderr
new file mode 100644
index 0000000..434f318
--- /dev/null
+++ b/src/test/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.nll.stderr
@@ -0,0 +1,54 @@
+error[E0594]: cannot assign to `x`, as it is not declared as mutable
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:21:46
+   |
+LL |     pub fn e(x: &'static mut isize) {
+   |              - help: consider changing this to be mutable: `mut x`
+LL |         static mut Y: isize = 3;
+LL |         let mut c1 = |y: &'static mut isize| x = y;
+   |                                              ^^^^^ cannot assign
+
+error[E0594]: cannot assign to `x`, as it is not declared as mutable
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:34:50
+   |
+LL |     pub fn ee(x: &'static mut isize) {
+   |               - help: consider changing this to be mutable: `mut x`
+...
+LL |             let mut c2 = |y: &'static mut isize| x = y;
+   |                                                  ^^^^^ cannot assign
+
+error[E0594]: cannot assign to `x`, as it is not declared as mutable
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:46:14
+   |
+LL |     pub fn capture_assign_whole(x: (i32,)) {
+   |                                 - help: consider changing this to be mutable: `mut x`
+LL |         || { x = (1,); };
+   |              ^^^^^^^^ cannot assign
+
+error[E0594]: cannot assign to `x.0`, as `x` is not declared as mutable
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:52:14
+   |
+LL |     pub fn capture_assign_part(x: (i32,)) {
+   |                                - help: consider changing this to be mutable: `mut x`
+LL |         || { x.0 = 1; };
+   |              ^^^^^^^ cannot assign
+
+error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:58:14
+   |
+LL |     pub fn capture_reborrow_whole(x: (i32,)) {
+   |                                   - help: consider changing this to be mutable: `mut x`
+LL |         || { &mut x; };
+   |              ^^^^^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow `x.0` as mutable, as `x` is not declared as mutable
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:64:14
+   |
+LL |     pub fn capture_reborrow_part(x: (i32,)) {
+   |                                  - help: consider changing this to be mutable: `mut x`
+LL |         || { &mut x.0; };
+   |              ^^^^^^^^ cannot borrow as mutable
+
+error: aborting due to 6 previous errors
+
+Some errors occurred: E0594, E0596.
+For more information about an error, try `rustc --explain E0594`.
diff --git a/src/test/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.rs b/src/test/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.rs
new file mode 100644
index 0000000..2bd71ec
--- /dev/null
+++ b/src/test/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.rs
@@ -0,0 +1,79 @@
+// rust-lang/rust#55492: errors detected during MIR-borrowck's
+// analysis of a closure body may only be caught when AST-borrowck
+// looks at some parent.
+
+// revisions: ast migrate nll
+
+// Since we are testing nll (and migration) explicitly as a separate
+// revisions, don't worry about the --compare-mode=nll on this test.
+
+// ignore-compare-mode-nll
+
+//[ast]compile-flags: -Z borrowck=ast
+//[migrate]compile-flags: -Z borrowck=migrate -Z two-phase-borrows
+//[nll]compile-flags: -Z borrowck=mir -Z two-phase-borrows
+
+
+// transcribed from borrowck-closures-unique.rs
+mod borrowck_closures_unique {
+    pub fn e(x: &'static mut isize) {
+        static mut Y: isize = 3;
+        let mut c1 = |y: &'static mut isize| x = y;
+        //[migrate]~^ ERROR is not declared as mutable
+        //[nll]~^^ ERROR is not declared as mutable
+        //[ast]~^^^ closure cannot assign to immutable
+        unsafe { c1(&mut Y); }
+    }
+}
+
+mod borrowck_closures_unique_grandparent {
+    pub fn ee(x: &'static mut isize) {
+        static mut Z: isize = 3;
+        let mut c1 = |z: &'static mut isize| {
+        //[ast]~^ closure cannot assign to immutable
+            let mut c2 = |y: &'static mut isize| x = y;
+        //[migrate]~^ ERROR is not declared as mutable
+        //[nll]~^^ ERROR is not declared as mutable
+            c2(z);
+        };
+        unsafe { c1(&mut Z); }
+    }
+}
+
+// adapted from mutability_errors.rs
+mod mutability_errors {
+    pub fn capture_assign_whole(x: (i32,)) {
+        || { x = (1,); };
+        //[ast]~^ ERROR immutable argument
+        //[migrate]~^^ ERROR is not declared as mutable
+        //[nll]~^^^ ERROR is not declared as mutable
+    }
+    pub fn capture_assign_part(x: (i32,)) {
+        || { x.0 = 1; };
+        //[ast]~^ ERROR immutable argument
+        //[migrate]~^^ ERROR is not declared as mutable
+        //[nll]~^^^ ERROR is not declared as mutable
+    }
+    pub fn capture_reborrow_whole(x: (i32,)) {
+        || { &mut x; };
+        //[ast]~^ ERROR immutable argument
+        //[migrate]~^^ ERROR is not declared as mutable
+        //[nll]~^^^ ERROR is not declared as mutable
+    }
+    pub fn capture_reborrow_part(x: (i32,)) {
+        || { &mut x.0; };
+        //[ast]~^ ERROR immutable argument
+        //[migrate]~^^ ERROR is not declared as mutable
+        //[nll]~^^^ ERROR is not declared as mutable
+    }
+}
+
+fn main() {
+    static mut X: isize = 2;
+    unsafe { borrowck_closures_unique::e(&mut X); }
+
+    mutability_errors::capture_assign_whole((1000,));
+    mutability_errors::capture_assign_part((2000,));
+    mutability_errors::capture_reborrow_whole((3000,));
+    mutability_errors::capture_reborrow_part((4000,));
+}
diff --git a/src/test/ui/borrowck/issue-55552-ascribe-wildcard-to-structured-pattern.rs b/src/test/ui/borrowck/issue-55552-ascribe-wildcard-to-structured-pattern.rs
new file mode 100644
index 0000000..6d91fd3
--- /dev/null
+++ b/src/test/ui/borrowck/issue-55552-ascribe-wildcard-to-structured-pattern.rs
@@ -0,0 +1,31 @@
+// compile-pass
+
+// rust-lang/rust#55552: The strategy pnkfelix landed in PR #55274
+// (for ensuring that NLL respects user-provided lifetime annotations)
+// did not handle the case where the ascribed type has some expliit
+// wildcards (`_`) mixed in, and it caused an internal compiler error
+// (ICE).
+//
+// This test is just checking that we do not ICE when such things
+// occur.
+
+struct X;
+struct Y;
+struct Z;
+
+struct Pair { x: X, y: Y }
+
+pub fn join<A, B, RA, RB>(oper_a: A, oper_b: B) -> (RA, RB)
+where A: FnOnce() -> RA + Send,
+      B: FnOnce() -> RB + Send,
+      RA: Send,
+      RB: Send
+{
+    (oper_a(), oper_b())
+}
+
+fn main() {
+    let ((_x, _y), _z): (_, Z) = join(|| (X, Y), || Z);
+
+    let (Pair { x: _x, y: _y }, Z): (_, Z) = join(|| Pair { x: X, y: Y }, || Z);
+}
diff --git a/src/test/ui/borrowck/issue-58776-borrowck-scans-children.ast.stderr b/src/test/ui/borrowck/issue-58776-borrowck-scans-children.ast.stderr
new file mode 100644
index 0000000..9e0b0aa
--- /dev/null
+++ b/src/test/ui/borrowck/issue-58776-borrowck-scans-children.ast.stderr
@@ -0,0 +1,15 @@
+error[E0597]: `**greeting` does not live long enough
+  --> $DIR/issue-58776-borrowck-scans-children.rs:10:24
+   |
+LL |     let res = (|| (|| &greeting)())();
+   |                    --  ^^^^^^^^     - borrowed value only lives until here
+   |                    |   |
+   |                    |   borrowed value does not live long enough
+   |                    capture occurs here
+...
+LL | }
+   | - borrowed value needs to live until here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/borrowck/issue-58776-borrowck-scans-children.migrate.stderr b/src/test/ui/borrowck/issue-58776-borrowck-scans-children.migrate.stderr
new file mode 100644
index 0000000..bd8f228
--- /dev/null
+++ b/src/test/ui/borrowck/issue-58776-borrowck-scans-children.migrate.stderr
@@ -0,0 +1,32 @@
+error[E0506]: cannot assign to `greeting` because it is borrowed
+  --> $DIR/issue-58776-borrowck-scans-children.rs:13:5
+   |
+LL |     let res = (|| (|| &greeting)())();
+   |                --      -------- borrow occurs due to use in closure
+   |                |
+   |                borrow of `greeting` occurs here
+...
+LL |     greeting = "DEALLOCATED".to_string();
+   |     ^^^^^^^^ assignment to borrowed `greeting` occurs here
+...
+LL |     println!("thread result: {:?}", res);
+   |                                     --- borrow later used here
+
+error[E0505]: cannot move out of `greeting` because it is borrowed
+  --> $DIR/issue-58776-borrowck-scans-children.rs:16:10
+   |
+LL |     let res = (|| (|| &greeting)())();
+   |                --      -------- borrow occurs due to use in closure
+   |                |
+   |                borrow of `greeting` occurs here
+...
+LL |     drop(greeting);
+   |          ^^^^^^^^ move out of `greeting` occurs here
+...
+LL |     println!("thread result: {:?}", res);
+   |                                     --- borrow later used here
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0505, E0506.
+For more information about an error, try `rustc --explain E0505`.
diff --git a/src/test/ui/borrowck/issue-58776-borrowck-scans-children.nll.stderr b/src/test/ui/borrowck/issue-58776-borrowck-scans-children.nll.stderr
new file mode 100644
index 0000000..bd8f228
--- /dev/null
+++ b/src/test/ui/borrowck/issue-58776-borrowck-scans-children.nll.stderr
@@ -0,0 +1,32 @@
+error[E0506]: cannot assign to `greeting` because it is borrowed
+  --> $DIR/issue-58776-borrowck-scans-children.rs:13:5
+   |
+LL |     let res = (|| (|| &greeting)())();
+   |                --      -------- borrow occurs due to use in closure
+   |                |
+   |                borrow of `greeting` occurs here
+...
+LL |     greeting = "DEALLOCATED".to_string();
+   |     ^^^^^^^^ assignment to borrowed `greeting` occurs here
+...
+LL |     println!("thread result: {:?}", res);
+   |                                     --- borrow later used here
+
+error[E0505]: cannot move out of `greeting` because it is borrowed
+  --> $DIR/issue-58776-borrowck-scans-children.rs:16:10
+   |
+LL |     let res = (|| (|| &greeting)())();
+   |                --      -------- borrow occurs due to use in closure
+   |                |
+   |                borrow of `greeting` occurs here
+...
+LL |     drop(greeting);
+   |          ^^^^^^^^ move out of `greeting` occurs here
+...
+LL |     println!("thread result: {:?}", res);
+   |                                     --- borrow later used here
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0505, E0506.
+For more information about an error, try `rustc --explain E0505`.
diff --git a/src/test/ui/borrowck/issue-58776-borrowck-scans-children.rs b/src/test/ui/borrowck/issue-58776-borrowck-scans-children.rs
new file mode 100644
index 0000000..378969f
--- /dev/null
+++ b/src/test/ui/borrowck/issue-58776-borrowck-scans-children.rs
@@ -0,0 +1,21 @@
+// ignore-compare-mode-nll
+
+// revisions: ast migrate nll
+
+//[migrate]compile-flags: -Z borrowck=migrate
+#![cfg_attr(nll, feature(nll))]
+
+fn main() {
+    let mut greeting = "Hello world!".to_string();
+    let res = (|| (|| &greeting)())();
+    //[ast]~^ ERROR does not live long enough
+
+    greeting = "DEALLOCATED".to_string();
+    //[migrate]~^ ERROR cannot assign
+    //[nll]~^^ ERROR cannot assign
+    drop(greeting);
+    //[migrate]~^ ERROR cannot move
+    //[nll]~^^ ERROR cannot move
+
+    println!("thread result: {:?}", res);
+}
diff --git a/src/test/ui/borrowck/issue-7573.rs b/src/test/ui/borrowck/issue-7573.rs
new file mode 100644
index 0000000..20a6a5c
--- /dev/null
+++ b/src/test/ui/borrowck/issue-7573.rs
@@ -0,0 +1,43 @@
+pub struct CrateId {
+    local_path: String,
+    junk: String
+}
+
+impl CrateId {
+    fn new(s: &str) -> CrateId {
+        CrateId {
+            local_path: s.to_string(),
+            junk: "wutevs".to_string()
+        }
+    }
+}
+
+pub fn remove_package_from_database() {
+    let mut lines_to_use: Vec<&CrateId> = Vec::new();
+        //~^ NOTE cannot infer an appropriate lifetime
+    let push_id = |installed_id: &CrateId| {
+        //~^ NOTE borrowed data cannot outlive this closure
+        //~| NOTE ...so that variable is valid at time of its declaration
+        lines_to_use.push(installed_id);
+        //~^ ERROR borrowed data cannot be stored outside of its closure
+        //~| NOTE cannot be stored outside of its closure
+    };
+    list_database(push_id);
+
+    for l in &lines_to_use {
+        println!("{}", l.local_path);
+    }
+
+}
+
+pub fn list_database<F>(mut f: F) where F: FnMut(&CrateId) {
+    let stuff = ["foo", "bar"];
+
+    for l in &stuff {
+        f(&CrateId::new(*l));
+    }
+}
+
+pub fn main() {
+    remove_package_from_database();
+}
diff --git a/src/test/ui/borrowck/issue-7573.stderr b/src/test/ui/borrowck/issue-7573.stderr
new file mode 100644
index 0000000..32b3ef7
--- /dev/null
+++ b/src/test/ui/borrowck/issue-7573.stderr
@@ -0,0 +1,16 @@
+error: borrowed data cannot be stored outside of its closure
+  --> $DIR/issue-7573.rs:21:27
+   |
+LL |     let mut lines_to_use: Vec<&CrateId> = Vec::new();
+   |                               - cannot infer an appropriate lifetime...
+LL |
+LL |     let push_id = |installed_id: &CrateId| {
+   |         -------   ------------------------ borrowed data cannot outlive this closure
+   |         |
+   |         ...so that variable is valid at time of its declaration
+...
+LL |         lines_to_use.push(installed_id);
+   |                           ^^^^^^^^^^^^ cannot be stored outside of its closure
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/borrowck/move-in-static-initializer-issue-38520.ast.stderr b/src/test/ui/borrowck/move-in-static-initializer-issue-38520.ast.stderr
new file mode 100644
index 0000000..14078b7
--- /dev/null
+++ b/src/test/ui/borrowck/move-in-static-initializer-issue-38520.ast.stderr
@@ -0,0 +1,15 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/move-in-static-initializer-issue-38520.rs:15:23
+   |
+LL | static Y: usize = get(*&X);
+   |                       ^^^ cannot move out of borrowed content
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/move-in-static-initializer-issue-38520.rs:17:22
+   |
+LL | const Z: usize = get(*&X);
+   |                      ^^^ cannot move out of borrowed content
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/borrowck/move-in-static-initializer-issue-38520.mir.stderr b/src/test/ui/borrowck/move-in-static-initializer-issue-38520.mir.stderr
new file mode 100644
index 0000000..14078b7
--- /dev/null
+++ b/src/test/ui/borrowck/move-in-static-initializer-issue-38520.mir.stderr
@@ -0,0 +1,15 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/move-in-static-initializer-issue-38520.rs:15:23
+   |
+LL | static Y: usize = get(*&X);
+   |                       ^^^ cannot move out of borrowed content
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/move-in-static-initializer-issue-38520.rs:17:22
+   |
+LL | const Z: usize = get(*&X);
+   |                      ^^^ cannot move out of borrowed content
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/borrowck/move-in-static-initializer-issue-38520.rs b/src/test/ui/borrowck/move-in-static-initializer-issue-38520.rs
new file mode 100644
index 0000000..a7b17f7
--- /dev/null
+++ b/src/test/ui/borrowck/move-in-static-initializer-issue-38520.rs
@@ -0,0 +1,21 @@
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+// Regression test for #38520. Check that moves of `Foo` are not
+// permitted as `Foo` is not copy (even in a static/const
+// initializer).
+
+struct Foo(usize);
+
+const fn get(x: Foo) -> usize {
+    x.0
+}
+
+const X: Foo = Foo(22);
+static Y: usize = get(*&X); //[ast]~ ERROR E0507
+                            //[mir]~^ ERROR [E0507]
+const Z: usize = get(*&X); //[ast]~ ERROR E0507
+                           //[mir]~^ ERROR [E0507]
+
+fn main() {
+}
diff --git a/src/test/ui/borrowck/mut-borrow-in-loop.nll.stderr b/src/test/ui/borrowck/mut-borrow-in-loop.nll.stderr
new file mode 100644
index 0000000..eda2f51
--- /dev/null
+++ b/src/test/ui/borrowck/mut-borrow-in-loop.nll.stderr
@@ -0,0 +1,39 @@
+error[E0499]: cannot borrow `*arg` as mutable more than once at a time
+  --> $DIR/mut-borrow-in-loop.rs:10:25
+   |
+LL | impl<'a, T : 'a> FuncWrapper<'a, T> {
+   |      -- lifetime `'a` defined here
+...
+LL |             (self.func)(arg)
+   |             ------------^^^-
+   |             |           |
+   |             |           mutable borrow starts here in previous iteration of loop
+   |             argument requires that `*arg` is borrowed for `'a`
+
+error[E0499]: cannot borrow `*arg` as mutable more than once at a time
+  --> $DIR/mut-borrow-in-loop.rs:16:25
+   |
+LL | impl<'a, T : 'a> FuncWrapper<'a, T> {
+   |      -- lifetime `'a` defined here
+...
+LL |             (self.func)(arg)
+   |             ------------^^^-
+   |             |           |
+   |             |           mutable borrow starts here in previous iteration of loop
+   |             argument requires that `*arg` is borrowed for `'a`
+
+error[E0499]: cannot borrow `*arg` as mutable more than once at a time
+  --> $DIR/mut-borrow-in-loop.rs:23:25
+   |
+LL | impl<'a, T : 'a> FuncWrapper<'a, T> {
+   |      -- lifetime `'a` defined here
+...
+LL |             (self.func)(arg)
+   |             ------------^^^-
+   |             |           |
+   |             |           mutable borrow starts here in previous iteration of loop
+   |             argument requires that `*arg` is borrowed for `'a`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/borrowck/mut-borrow-in-loop.rs b/src/test/ui/borrowck/mut-borrow-in-loop.rs
new file mode 100644
index 0000000..6b65b90
--- /dev/null
+++ b/src/test/ui/borrowck/mut-borrow-in-loop.rs
@@ -0,0 +1,30 @@
+// produce special borrowck message inside all kinds of loops
+
+struct FuncWrapper<'a, T : 'a> {
+    func : fn(&'a mut T) -> ()
+}
+
+impl<'a, T : 'a> FuncWrapper<'a, T> {
+    fn in_loop(self, arg : &'a mut T) {
+        loop {
+            (self.func)(arg) //~ ERROR cannot borrow
+        }
+    }
+
+    fn in_while(self, arg : &'a mut T) {
+        while true {
+            (self.func)(arg) //~ ERROR cannot borrow
+        }
+    }
+
+    fn in_for(self, arg : &'a mut T) {
+        let v : Vec<()> = vec![];
+        for _ in v.iter() {
+            (self.func)(arg) //~ ERROR cannot borrow
+        }
+    }
+}
+
+fn main() {
+}
+
diff --git a/src/test/ui/borrowck/mut-borrow-in-loop.stderr b/src/test/ui/borrowck/mut-borrow-in-loop.stderr
new file mode 100644
index 0000000..478d586
--- /dev/null
+++ b/src/test/ui/borrowck/mut-borrow-in-loop.stderr
@@ -0,0 +1,30 @@
+error[E0499]: cannot borrow `*arg` as mutable more than once at a time
+  --> $DIR/mut-borrow-in-loop.rs:10:25
+   |
+LL |             (self.func)(arg)
+   |                         ^^^ mutable borrow starts here in previous iteration of loop
+LL |         }
+LL |     }
+   |     - mutable borrow ends here
+
+error[E0499]: cannot borrow `*arg` as mutable more than once at a time
+  --> $DIR/mut-borrow-in-loop.rs:16:25
+   |
+LL |             (self.func)(arg)
+   |                         ^^^ mutable borrow starts here in previous iteration of loop
+LL |         }
+LL |     }
+   |     - mutable borrow ends here
+
+error[E0499]: cannot borrow `*arg` as mutable more than once at a time
+  --> $DIR/mut-borrow-in-loop.rs:23:25
+   |
+LL |             (self.func)(arg)
+   |                         ^^^ mutable borrow starts here in previous iteration of loop
+LL |         }
+LL |     }
+   |     - mutable borrow ends here
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/borrowck/mut-borrow-of-mut-ref.nll.stderr b/src/test/ui/borrowck/mut-borrow-of-mut-ref.nll.stderr
new file mode 100644
index 0000000..09dabbc
--- /dev/null
+++ b/src/test/ui/borrowck/mut-borrow-of-mut-ref.nll.stderr
@@ -0,0 +1,11 @@
+error[E0596]: cannot borrow `b` as mutable, as it is not declared as mutable
+  --> $DIR/mut-borrow-of-mut-ref.rs:8:7
+   |
+LL | fn f(b: &mut i32) {
+   |      - help: consider changing this to be mutable: `mut b`
+LL |     g(&mut b)
+   |       ^^^^^^ cannot borrow as mutable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/borrowck/mut-borrow-of-mut-ref.rs b/src/test/ui/borrowck/mut-borrow-of-mut-ref.rs
new file mode 100644
index 0000000..212f706
--- /dev/null
+++ b/src/test/ui/borrowck/mut-borrow-of-mut-ref.rs
@@ -0,0 +1,11 @@
+// Suggest not mutably borrowing a mutable reference
+
+fn main() {
+    f(&mut 0)
+}
+
+fn f(b: &mut i32) {
+    g(&mut b) //~ ERROR cannot borrow
+}
+
+fn g(_: &mut i32) {}
diff --git a/src/test/ui/borrowck/mut-borrow-of-mut-ref.stderr b/src/test/ui/borrowck/mut-borrow-of-mut-ref.stderr
new file mode 100644
index 0000000..4653c35
--- /dev/null
+++ b/src/test/ui/borrowck/mut-borrow-of-mut-ref.stderr
@@ -0,0 +1,13 @@
+error[E0596]: cannot borrow immutable argument `b` as mutable
+  --> $DIR/mut-borrow-of-mut-ref.rs:8:12
+   |
+LL |     g(&mut b)
+   |            ^ cannot borrow mutably
+help: consider removing the `&mut`, as it is an immutable binding to a mutable reference
+   |
+LL |     g(b)
+   |       ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/borrowck/mut-borrow-outside-loop.nll.stderr b/src/test/ui/borrowck/mut-borrow-outside-loop.nll.stderr
new file mode 100644
index 0000000..4fcb693
--- /dev/null
+++ b/src/test/ui/borrowck/mut-borrow-outside-loop.nll.stderr
@@ -0,0 +1,24 @@
+error[E0499]: cannot borrow `void` as mutable more than once at a time
+  --> $DIR/mut-borrow-outside-loop.rs:7:18
+   |
+LL |     let first = &mut void;
+   |                 --------- first mutable borrow occurs here
+LL |     let second = &mut void;
+   |                  ^^^^^^^^^ second mutable borrow occurs here
+LL |     first.use_mut();
+   |     ----- first borrow later used here
+
+error[E0499]: cannot borrow `inner_void` as mutable more than once at a time
+  --> $DIR/mut-borrow-outside-loop.rs:15:28
+   |
+LL |         let inner_first = &mut inner_void;
+   |                           --------------- first mutable borrow occurs here
+LL |         let inner_second = &mut inner_void;
+   |                            ^^^^^^^^^^^^^^^ second mutable borrow occurs here
+LL |         inner_second.use_mut();
+LL |         inner_first.use_mut();
+   |         ----------- first borrow later used here
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/borrowck/mut-borrow-outside-loop.rs b/src/test/ui/borrowck/mut-borrow-outside-loop.rs
new file mode 100644
index 0000000..c02bfbf
--- /dev/null
+++ b/src/test/ui/borrowck/mut-borrow-outside-loop.rs
@@ -0,0 +1,22 @@
+// ensure borrowck messages are correct outside special case
+#![feature(rustc_attrs)]
+fn main() { #![rustc_error] // rust-lang/rust#49855
+    let mut void = ();
+
+    let first = &mut void;
+    let second = &mut void; //~ ERROR cannot borrow
+    first.use_mut();
+    second.use_mut();
+
+    loop {
+        let mut inner_void = ();
+
+        let inner_first = &mut inner_void;
+        let inner_second = &mut inner_void; //~ ERROR cannot borrow
+        inner_second.use_mut();
+        inner_first.use_mut();
+    }
+}
+
+trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { }  }
+impl<T> Fake for T { }
diff --git a/src/test/ui/borrowck/mut-borrow-outside-loop.stderr b/src/test/ui/borrowck/mut-borrow-outside-loop.stderr
new file mode 100644
index 0000000..45db962
--- /dev/null
+++ b/src/test/ui/borrowck/mut-borrow-outside-loop.stderr
@@ -0,0 +1,25 @@
+error[E0499]: cannot borrow `void` as mutable more than once at a time
+  --> $DIR/mut-borrow-outside-loop.rs:7:23
+   |
+LL |     let first = &mut void;
+   |                      ---- first mutable borrow occurs here
+LL |     let second = &mut void;
+   |                       ^^^^ second mutable borrow occurs here
+...
+LL | }
+   | - first borrow ends here
+
+error[E0499]: cannot borrow `inner_void` as mutable more than once at a time
+  --> $DIR/mut-borrow-outside-loop.rs:15:33
+   |
+LL |         let inner_first = &mut inner_void;
+   |                                ---------- first mutable borrow occurs here
+LL |         let inner_second = &mut inner_void;
+   |                                 ^^^^^^^^^^ second mutable borrow occurs here
+...
+LL |     }
+   |     - first borrow ends here
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/borrowck/mutability-errors.nll.stderr b/src/test/ui/borrowck/mutability-errors.nll.stderr
new file mode 100644
index 0000000..11bc788
--- /dev/null
+++ b/src/test/ui/borrowck/mutability-errors.nll.stderr
@@ -0,0 +1,379 @@
+error[E0594]: cannot assign to `*x` which is behind a `&` reference
+  --> $DIR/mutability-errors.rs:9:5
+   |
+LL | fn named_ref(x: &(i32,)) {
+   |                 ------- help: consider changing this to be a mutable reference: `&mut (i32,)`
+LL |     *x = (1,);
+   |     ^^^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written
+
+error[E0594]: cannot assign to `x.0` which is behind a `&` reference
+  --> $DIR/mutability-errors.rs:10:5
+   |
+LL | fn named_ref(x: &(i32,)) {
+   |                 ------- help: consider changing this to be a mutable reference: `&mut (i32,)`
+LL |     *x = (1,);
+LL |     x.0 = 1;
+   |     ^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written
+
+error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
+  --> $DIR/mutability-errors.rs:11:5
+   |
+LL | fn named_ref(x: &(i32,)) {
+   |                 ------- help: consider changing this to be a mutable reference: `&mut (i32,)`
+...
+LL |     &mut *x;
+   |     ^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+
+error[E0596]: cannot borrow `x.0` as mutable, as it is behind a `&` reference
+  --> $DIR/mutability-errors.rs:12:5
+   |
+LL | fn named_ref(x: &(i32,)) {
+   |                 ------- help: consider changing this to be a mutable reference: `&mut (i32,)`
+...
+LL |     &mut x.0;
+   |     ^^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+
+error[E0594]: cannot assign to data in a `&` reference
+  --> $DIR/mutability-errors.rs:16:5
+   |
+LL |     *f() = (1,);
+   |     ^^^^^^^^^^^ cannot assign
+
+error[E0594]: cannot assign to data in a `&` reference
+  --> $DIR/mutability-errors.rs:17:5
+   |
+LL |     f().0 = 1;
+   |     ^^^^^^^^^ cannot assign
+
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/mutability-errors.rs:18:5
+   |
+LL |     &mut *f();
+   |     ^^^^^^^^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/mutability-errors.rs:19:5
+   |
+LL |     &mut f().0;
+   |     ^^^^^^^^^^ cannot borrow as mutable
+
+error[E0594]: cannot assign to `*x` which is behind a `*const` pointer
+  --> $DIR/mutability-errors.rs:23:5
+   |
+LL | unsafe fn named_ptr(x: *const (i32,)) {
+   |                        ------------- help: consider changing this to be a mutable pointer: `*mut (i32,)`
+LL |     *x = (1,);
+   |     ^^^^^^^^^ `x` is a `*const` pointer, so the data it refers to cannot be written
+
+error[E0594]: cannot assign to `x.0` which is behind a `*const` pointer
+  --> $DIR/mutability-errors.rs:24:5
+   |
+LL | unsafe fn named_ptr(x: *const (i32,)) {
+   |                        ------------- help: consider changing this to be a mutable pointer: `*mut (i32,)`
+LL |     *x = (1,);
+LL |     (*x).0 = 1;
+   |     ^^^^^^^^^^ `x` is a `*const` pointer, so the data it refers to cannot be written
+
+error[E0596]: cannot borrow `*x` as mutable, as it is behind a `*const` pointer
+  --> $DIR/mutability-errors.rs:25:5
+   |
+LL | unsafe fn named_ptr(x: *const (i32,)) {
+   |                        ------------- help: consider changing this to be a mutable pointer: `*mut (i32,)`
+...
+LL |     &mut *x;
+   |     ^^^^^^^ `x` is a `*const` pointer, so the data it refers to cannot be borrowed as mutable
+
+error[E0596]: cannot borrow `x.0` as mutable, as it is behind a `*const` pointer
+  --> $DIR/mutability-errors.rs:26:5
+   |
+LL | unsafe fn named_ptr(x: *const (i32,)) {
+   |                        ------------- help: consider changing this to be a mutable pointer: `*mut (i32,)`
+...
+LL |     &mut (*x).0;
+   |     ^^^^^^^^^^^ `x` is a `*const` pointer, so the data it refers to cannot be borrowed as mutable
+
+error[E0594]: cannot assign to data in a `*const` pointer
+  --> $DIR/mutability-errors.rs:30:5
+   |
+LL |     *f() = (1,);
+   |     ^^^^^^^^^^^ cannot assign
+
+error[E0594]: cannot assign to data in a `*const` pointer
+  --> $DIR/mutability-errors.rs:31:5
+   |
+LL |     (*f()).0 = 1;
+   |     ^^^^^^^^^^^^ cannot assign
+
+error[E0596]: cannot borrow data in a `*const` pointer as mutable
+  --> $DIR/mutability-errors.rs:32:5
+   |
+LL |     &mut *f();
+   |     ^^^^^^^^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow data in a `*const` pointer as mutable
+  --> $DIR/mutability-errors.rs:33:5
+   |
+LL |     &mut (*f()).0;
+   |     ^^^^^^^^^^^^^ cannot borrow as mutable
+
+error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure
+  --> $DIR/mutability-errors.rs:40:9
+   |
+LL |         x = (1,);
+   |         ^^^^^^^^ cannot assign
+   |
+help: consider changing this to accept closures that implement `FnMut`
+  --> $DIR/mutability-errors.rs:39:12
+   |
+LL |       fn_ref(|| {
+   |  ____________^
+LL | |         x = (1,);
+LL | |         x.0 = 1;
+LL | |         &mut x;
+LL | |         &mut x.0;
+LL | |     });
+   | |_____^
+
+error[E0594]: cannot assign to `x.0`, as `Fn` closures cannot mutate their captured variables
+  --> $DIR/mutability-errors.rs:41:9
+   |
+LL |         x.0 = 1;
+   |         ^^^^^^^ cannot assign
+   |
+help: consider changing this to accept closures that implement `FnMut`
+  --> $DIR/mutability-errors.rs:39:12
+   |
+LL |       fn_ref(|| {
+   |  ____________^
+LL | |         x = (1,);
+LL | |         x.0 = 1;
+LL | |         &mut x;
+LL | |         &mut x.0;
+LL | |     });
+   | |_____^
+
+error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
+  --> $DIR/mutability-errors.rs:42:9
+   |
+LL |         &mut x;
+   |         ^^^^^^ cannot borrow as mutable
+   |
+help: consider changing this to accept closures that implement `FnMut`
+  --> $DIR/mutability-errors.rs:39:12
+   |
+LL |       fn_ref(|| {
+   |  ____________^
+LL | |         x = (1,);
+LL | |         x.0 = 1;
+LL | |         &mut x;
+LL | |         &mut x.0;
+LL | |     });
+   | |_____^
+
+error[E0596]: cannot borrow `x.0` as mutable, as `Fn` closures cannot mutate their captured variables
+  --> $DIR/mutability-errors.rs:43:9
+   |
+LL |         &mut x.0;
+   |         ^^^^^^^^ cannot borrow as mutable
+   |
+help: consider changing this to accept closures that implement `FnMut`
+  --> $DIR/mutability-errors.rs:39:12
+   |
+LL |       fn_ref(|| {
+   |  ____________^
+LL | |         x = (1,);
+LL | |         x.0 = 1;
+LL | |         &mut x;
+LL | |         &mut x.0;
+LL | |     });
+   | |_____^
+
+error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure
+  --> $DIR/mutability-errors.rs:46:9
+   |
+LL |         x = (1,);
+   |         ^^^^^^^^ cannot assign
+   |
+help: consider changing this to accept closures that implement `FnMut`
+  --> $DIR/mutability-errors.rs:45:12
+   |
+LL |       fn_ref(move || {
+   |  ____________^
+LL | |         x = (1,);
+LL | |         x.0 = 1;
+LL | |         &mut x;
+LL | |         &mut x.0;
+LL | |     });
+   | |_____^
+
+error[E0594]: cannot assign to `x.0`, as `Fn` closures cannot mutate their captured variables
+  --> $DIR/mutability-errors.rs:47:9
+   |
+LL |         x.0 = 1;
+   |         ^^^^^^^ cannot assign
+   |
+help: consider changing this to accept closures that implement `FnMut`
+  --> $DIR/mutability-errors.rs:45:12
+   |
+LL |       fn_ref(move || {
+   |  ____________^
+LL | |         x = (1,);
+LL | |         x.0 = 1;
+LL | |         &mut x;
+LL | |         &mut x.0;
+LL | |     });
+   | |_____^
+
+error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
+  --> $DIR/mutability-errors.rs:48:9
+   |
+LL |         &mut x;
+   |         ^^^^^^ cannot borrow as mutable
+   |
+help: consider changing this to accept closures that implement `FnMut`
+  --> $DIR/mutability-errors.rs:45:12
+   |
+LL |       fn_ref(move || {
+   |  ____________^
+LL | |         x = (1,);
+LL | |         x.0 = 1;
+LL | |         &mut x;
+LL | |         &mut x.0;
+LL | |     });
+   | |_____^
+
+error[E0596]: cannot borrow `x.0` as mutable, as `Fn` closures cannot mutate their captured variables
+  --> $DIR/mutability-errors.rs:49:9
+   |
+LL |         &mut x.0;
+   |         ^^^^^^^^ cannot borrow as mutable
+   |
+help: consider changing this to accept closures that implement `FnMut`
+  --> $DIR/mutability-errors.rs:45:12
+   |
+LL |       fn_ref(move || {
+   |  ____________^
+LL | |         x = (1,);
+LL | |         x.0 = 1;
+LL | |         &mut x;
+LL | |         &mut x.0;
+LL | |     });
+   | |_____^
+
+error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
+  --> $DIR/mutability-errors.rs:54:5
+   |
+LL | fn imm_local(x: (i32,)) {
+   |              - help: consider changing this to be mutable: `mut x`
+LL |     &mut x;
+   |     ^^^^^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow `x.0` as mutable, as `x` is not declared as mutable
+  --> $DIR/mutability-errors.rs:55:5
+   |
+LL | fn imm_local(x: (i32,)) {
+   |              - help: consider changing this to be mutable: `mut x`
+LL |     &mut x;
+LL |     &mut x.0;
+   |     ^^^^^^^^ cannot borrow as mutable
+
+error[E0594]: cannot assign to `x`, as it is not declared as mutable
+  --> $DIR/mutability-errors.rs:60:9
+   |
+LL | fn imm_capture(x: (i32,)) {
+   |                - help: consider changing this to be mutable: `mut x`
+LL |     || {
+LL |         x = (1,);
+   |         ^^^^^^^^ cannot assign
+
+error[E0594]: cannot assign to `x.0`, as `x` is not declared as mutable
+  --> $DIR/mutability-errors.rs:61:9
+   |
+LL | fn imm_capture(x: (i32,)) {
+   |                - help: consider changing this to be mutable: `mut x`
+...
+LL |         x.0 = 1;
+   |         ^^^^^^^ cannot assign
+
+error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
+  --> $DIR/mutability-errors.rs:62:9
+   |
+LL | fn imm_capture(x: (i32,)) {
+   |                - help: consider changing this to be mutable: `mut x`
+...
+LL |         &mut x;
+   |         ^^^^^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow `x.0` as mutable, as `x` is not declared as mutable
+  --> $DIR/mutability-errors.rs:63:9
+   |
+LL | fn imm_capture(x: (i32,)) {
+   |                - help: consider changing this to be mutable: `mut x`
+...
+LL |         &mut x.0;
+   |         ^^^^^^^^ cannot borrow as mutable
+
+error[E0594]: cannot assign to `x`, as it is not declared as mutable
+  --> $DIR/mutability-errors.rs:66:9
+   |
+LL | fn imm_capture(x: (i32,)) {
+   |                - help: consider changing this to be mutable: `mut x`
+...
+LL |         x = (1,);
+   |         ^^^^^^^^ cannot assign
+
+error[E0594]: cannot assign to `x.0`, as `x` is not declared as mutable
+  --> $DIR/mutability-errors.rs:67:9
+   |
+LL | fn imm_capture(x: (i32,)) {
+   |                - help: consider changing this to be mutable: `mut x`
+...
+LL |         x.0 = 1;
+   |         ^^^^^^^ cannot assign
+
+error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
+  --> $DIR/mutability-errors.rs:68:9
+   |
+LL | fn imm_capture(x: (i32,)) {
+   |                - help: consider changing this to be mutable: `mut x`
+...
+LL |         &mut x;
+   |         ^^^^^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow `x.0` as mutable, as `x` is not declared as mutable
+  --> $DIR/mutability-errors.rs:69:9
+   |
+LL | fn imm_capture(x: (i32,)) {
+   |                - help: consider changing this to be mutable: `mut x`
+...
+LL |         &mut x.0;
+   |         ^^^^^^^^ cannot borrow as mutable
+
+error[E0594]: cannot assign to immutable static item `X`
+  --> $DIR/mutability-errors.rs:76:5
+   |
+LL |     X = (1,);
+   |     ^^^^^^^^ cannot assign
+
+error[E0594]: cannot assign to `X.0`, as `X` is an immutable static item
+  --> $DIR/mutability-errors.rs:77:5
+   |
+LL |     X.0 = 1;
+   |     ^^^^^^^ cannot assign
+
+error[E0596]: cannot borrow immutable static item `X` as mutable
+  --> $DIR/mutability-errors.rs:78:5
+   |
+LL |     &mut X;
+   |     ^^^^^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow `X.0` as mutable, as `X` is an immutable static item
+  --> $DIR/mutability-errors.rs:79:5
+   |
+LL |     &mut X.0;
+   |     ^^^^^^^^ cannot borrow as mutable
+
+error: aborting due to 38 previous errors
+
+Some errors occurred: E0594, E0596.
+For more information about an error, try `rustc --explain E0594`.
diff --git a/src/test/ui/borrowck/mutability-errors.rs b/src/test/ui/borrowck/mutability-errors.rs
new file mode 100644
index 0000000..26f7f60
--- /dev/null
+++ b/src/test/ui/borrowck/mutability-errors.rs
@@ -0,0 +1,82 @@
+// All the possible mutability error cases.
+
+#![allow(unused)]
+
+type MakeRef = fn() -> &'static (i32,);
+type MakePtr = fn() -> *const (i32,);
+
+fn named_ref(x: &(i32,)) {
+    *x = (1,); //~ ERROR
+    x.0 = 1; //~ ERROR
+    &mut *x; //~ ERROR
+    &mut x.0; //~ ERROR
+}
+
+fn unnamed_ref(f: MakeRef) {
+    *f() = (1,); //~ ERROR
+    f().0 = 1; //~ ERROR
+    &mut *f(); //~ ERROR
+    &mut f().0; //~ ERROR
+}
+
+unsafe fn named_ptr(x: *const (i32,)) {
+    *x = (1,); //~ ERROR
+    (*x).0 = 1; //~ ERROR
+    &mut *x; //~ ERROR
+    &mut (*x).0; //~ ERROR
+}
+
+unsafe fn unnamed_ptr(f: MakePtr) {
+    *f() = (1,); //~ ERROR
+    (*f()).0 = 1; //~ ERROR
+    &mut *f(); //~ ERROR
+    &mut (*f()).0; //~ ERROR
+}
+
+fn fn_ref<F: Fn()>(f: F) -> F { f }
+
+fn ref_closure(mut x: (i32,)) {
+    fn_ref(|| {
+        x = (1,); //~ ERROR
+        x.0 = 1; //~ ERROR
+        &mut x; //~ ERROR
+        &mut x.0; //~ ERROR
+    });
+    fn_ref(move || {
+        x = (1,); //~ ERROR
+        x.0 = 1; //~ ERROR
+        &mut x; //~ ERROR
+        &mut x.0; //~ ERROR
+    });
+}
+
+fn imm_local(x: (i32,)) {
+    &mut x; //~ ERROR
+    &mut x.0; //~ ERROR
+}
+
+fn imm_capture(x: (i32,)) {
+    || { //~ ERROR
+        x = (1,);
+        x.0 = 1;
+        &mut x;
+        &mut x.0;
+    };
+    move || {
+        x = (1,); //~ ERROR
+        x.0 = 1; //~ ERROR
+        &mut x; //~ ERROR
+        &mut x.0; //~ ERROR
+    };
+}
+
+static X: (i32,) = (0,);
+
+fn imm_static() {
+    X = (1,); //~ ERROR
+    X.0 = 1; //~ ERROR
+    &mut X; //~ ERROR
+    &mut X.0; //~ ERROR
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/mutability-errors.stderr b/src/test/ui/borrowck/mutability-errors.stderr
new file mode 100644
index 0000000..cf4f37e
--- /dev/null
+++ b/src/test/ui/borrowck/mutability-errors.stderr
@@ -0,0 +1,308 @@
+error[E0594]: cannot assign to immutable borrowed content `*x`
+  --> $DIR/mutability-errors.rs:9:5
+   |
+LL | fn named_ref(x: &(i32,)) {
+   |                 ------- use `&mut (i32,)` here to make mutable
+LL |     *x = (1,);
+   |     ^^^^^^^^^ cannot borrow as mutable
+
+error[E0594]: cannot assign to field `x.0` of immutable binding
+  --> $DIR/mutability-errors.rs:10:5
+   |
+LL | fn named_ref(x: &(i32,)) {
+   |                 ------- use `&mut (i32,)` here to make mutable
+LL |     *x = (1,);
+LL |     x.0 = 1;
+   |     ^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0596]: cannot borrow immutable borrowed content `*x` as mutable
+  --> $DIR/mutability-errors.rs:11:10
+   |
+LL | fn named_ref(x: &(i32,)) {
+   |                 ------- use `&mut (i32,)` here to make mutable
+...
+LL |     &mut *x;
+   |          ^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow field `x.0` of immutable binding as mutable
+  --> $DIR/mutability-errors.rs:12:10
+   |
+LL | fn named_ref(x: &(i32,)) {
+   |                 ------- use `&mut (i32,)` here to make mutable
+...
+LL |     &mut x.0;
+   |          ^^^ cannot mutably borrow field of immutable binding
+
+error[E0594]: cannot assign to immutable borrowed content
+  --> $DIR/mutability-errors.rs:16:5
+   |
+LL |     *f() = (1,);
+   |     ^^^^^^^^^^^ cannot borrow as mutable
+
+error[E0594]: cannot assign to field of immutable binding
+  --> $DIR/mutability-errors.rs:17:5
+   |
+LL |     f().0 = 1;
+   |     ^^^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0596]: cannot borrow immutable borrowed content as mutable
+  --> $DIR/mutability-errors.rs:18:10
+   |
+LL |     &mut *f();
+   |          ^^^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow field of immutable binding as mutable
+  --> $DIR/mutability-errors.rs:19:10
+   |
+LL |     &mut f().0;
+   |          ^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0594]: cannot assign to immutable dereference of raw pointer `*x`
+  --> $DIR/mutability-errors.rs:23:5
+   |
+LL |     *x = (1,);
+   |     ^^^^^^^^^ cannot borrow as mutable
+
+error[E0594]: cannot assign to field `x.0` of immutable binding
+  --> $DIR/mutability-errors.rs:24:5
+   |
+LL |     (*x).0 = 1;
+   |     ^^^^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0596]: cannot borrow immutable dereference of raw pointer `*x` as mutable
+  --> $DIR/mutability-errors.rs:25:10
+   |
+LL |     &mut *x;
+   |          ^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow field `x.0` of immutable binding as mutable
+  --> $DIR/mutability-errors.rs:26:10
+   |
+LL |     &mut (*x).0;
+   |          ^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0594]: cannot assign to immutable dereference of raw pointer
+  --> $DIR/mutability-errors.rs:30:5
+   |
+LL |     *f() = (1,);
+   |     ^^^^^^^^^^^ cannot borrow as mutable
+
+error[E0594]: cannot assign to field of immutable binding
+  --> $DIR/mutability-errors.rs:31:5
+   |
+LL |     (*f()).0 = 1;
+   |     ^^^^^^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0596]: cannot borrow immutable dereference of raw pointer as mutable
+  --> $DIR/mutability-errors.rs:32:10
+   |
+LL |     &mut *f();
+   |          ^^^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow field of immutable binding as mutable
+  --> $DIR/mutability-errors.rs:33:10
+   |
+LL |     &mut (*f()).0;
+   |          ^^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0387]: cannot assign to data in a captured outer variable in an `Fn` closure
+  --> $DIR/mutability-errors.rs:40:9
+   |
+LL |         x = (1,);
+   |         ^^^^^^^^
+   |
+help: consider changing this closure to take self by mutable reference
+  --> $DIR/mutability-errors.rs:39:12
+   |
+LL |       fn_ref(|| {
+   |  ____________^
+LL | |         x = (1,);
+LL | |         x.0 = 1;
+LL | |         &mut x;
+LL | |         &mut x.0;
+LL | |     });
+   | |_____^
+
+error[E0387]: cannot assign to data in a captured outer variable in an `Fn` closure
+  --> $DIR/mutability-errors.rs:41:9
+   |
+LL |         x.0 = 1;
+   |         ^^^^^^^
+   |
+help: consider changing this closure to take self by mutable reference
+  --> $DIR/mutability-errors.rs:39:12
+   |
+LL |       fn_ref(|| {
+   |  ____________^
+LL | |         x = (1,);
+LL | |         x.0 = 1;
+LL | |         &mut x;
+LL | |         &mut x.0;
+LL | |     });
+   | |_____^
+
+error[E0387]: cannot borrow data mutably in a captured outer variable in an `Fn` closure
+  --> $DIR/mutability-errors.rs:42:14
+   |
+LL |         &mut x;
+   |              ^
+   |
+help: consider changing this closure to take self by mutable reference
+  --> $DIR/mutability-errors.rs:39:12
+   |
+LL |       fn_ref(|| {
+   |  ____________^
+LL | |         x = (1,);
+LL | |         x.0 = 1;
+LL | |         &mut x;
+LL | |         &mut x.0;
+LL | |     });
+   | |_____^
+
+error[E0387]: cannot borrow data mutably in a captured outer variable in an `Fn` closure
+  --> $DIR/mutability-errors.rs:43:14
+   |
+LL |         &mut x.0;
+   |              ^^^
+   |
+help: consider changing this closure to take self by mutable reference
+  --> $DIR/mutability-errors.rs:39:12
+   |
+LL |       fn_ref(|| {
+   |  ____________^
+LL | |         x = (1,);
+LL | |         x.0 = 1;
+LL | |         &mut x;
+LL | |         &mut x.0;
+LL | |     });
+   | |_____^
+
+error[E0594]: cannot assign to captured outer variable in an `Fn` closure
+  --> $DIR/mutability-errors.rs:46:9
+   |
+LL |         x = (1,);
+   |         ^^^^^^^^
+   |
+   = note: `Fn` closures cannot capture their enclosing environment for modifications
+help: consider changing this closure to take self by mutable reference
+  --> $DIR/mutability-errors.rs:45:12
+   |
+LL |       fn_ref(move || {
+   |  ____________^
+LL | |         x = (1,);
+LL | |         x.0 = 1;
+LL | |         &mut x;
+LL | |         &mut x.0;
+LL | |     });
+   | |_____^
+
+error[E0594]: cannot assign to field `x.0` of immutable binding
+  --> $DIR/mutability-errors.rs:47:9
+   |
+LL |         x.0 = 1;
+   |         ^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0596]: cannot borrow captured outer variable in an `Fn` closure as mutable
+  --> $DIR/mutability-errors.rs:48:14
+   |
+LL |         &mut x;
+   |              ^
+   |
+help: consider changing this closure to take self by mutable reference
+  --> $DIR/mutability-errors.rs:45:12
+   |
+LL |       fn_ref(move || {
+   |  ____________^
+LL | |         x = (1,);
+LL | |         x.0 = 1;
+LL | |         &mut x;
+LL | |         &mut x.0;
+LL | |     });
+   | |_____^
+
+error[E0596]: cannot borrow field `x.0` of immutable binding as mutable
+  --> $DIR/mutability-errors.rs:49:14
+   |
+LL |         &mut x.0;
+   |              ^^^ cannot mutably borrow field of immutable binding
+
+error[E0596]: cannot borrow immutable argument `x` as mutable
+  --> $DIR/mutability-errors.rs:54:10
+   |
+LL | fn imm_local(x: (i32,)) {
+   |              - help: make this binding mutable: `mut x`
+LL |     &mut x;
+   |          ^ cannot borrow mutably
+
+error[E0596]: cannot borrow field `x.0` of immutable binding as mutable
+  --> $DIR/mutability-errors.rs:55:10
+   |
+LL | fn imm_local(x: (i32,)) {
+   |              - help: make this binding mutable: `mut x`
+LL |     &mut x;
+LL |     &mut x.0;
+   |          ^^^ cannot mutably borrow field of immutable binding
+
+error[E0595]: closure cannot assign to immutable argument `x`
+  --> $DIR/mutability-errors.rs:59:5
+   |
+LL | fn imm_capture(x: (i32,)) {
+   |                - help: make this binding mutable: `mut x`
+LL |     || {
+   |     ^^ cannot borrow mutably
+
+error[E0594]: cannot assign to captured outer variable in an `FnMut` closure
+  --> $DIR/mutability-errors.rs:66:9
+   |
+LL | fn imm_capture(x: (i32,)) {
+   |                - help: consider making `x` mutable: `mut x`
+...
+LL |         x = (1,);
+   |         ^^^^^^^^
+
+error[E0594]: cannot assign to field `x.0` of immutable binding
+  --> $DIR/mutability-errors.rs:67:9
+   |
+LL |         x.0 = 1;
+   |         ^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0596]: cannot borrow captured outer variable in an `FnMut` closure as mutable
+  --> $DIR/mutability-errors.rs:68:14
+   |
+LL |         &mut x;
+   |              ^
+
+error[E0596]: cannot borrow field `x.0` of immutable binding as mutable
+  --> $DIR/mutability-errors.rs:69:14
+   |
+LL |         &mut x.0;
+   |              ^^^ cannot mutably borrow field of immutable binding
+
+error[E0594]: cannot assign to immutable static item
+  --> $DIR/mutability-errors.rs:76:5
+   |
+LL |     X = (1,);
+   |     ^^^^^^^^
+
+error[E0594]: cannot assign to field of immutable binding
+  --> $DIR/mutability-errors.rs:77:5
+   |
+LL |     X.0 = 1;
+   |     ^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0596]: cannot borrow immutable static item as mutable
+  --> $DIR/mutability-errors.rs:78:10
+   |
+LL |     &mut X;
+   |          ^
+
+error[E0596]: cannot borrow field of immutable binding as mutable
+  --> $DIR/mutability-errors.rs:79:10
+   |
+LL |     &mut X.0;
+   |          ^^^ cannot mutably borrow field of immutable binding
+
+error: aborting due to 35 previous errors
+
+Some errors occurred: E0387, E0594, E0595, E0596.
+For more information about an error, try `rustc --explain E0387`.
diff --git a/src/test/ui/borrowck/promote-ref-mut-in-let-issue-46557.nll.stderr b/src/test/ui/borrowck/promote-ref-mut-in-let-issue-46557.nll.stderr
new file mode 100644
index 0000000..60af412
--- /dev/null
+++ b/src/test/ui/borrowck/promote-ref-mut-in-let-issue-46557.nll.stderr
@@ -0,0 +1,50 @@
+error[E0515]: cannot return value referencing temporary value
+  --> $DIR/promote-ref-mut-in-let-issue-46557.rs:6:5
+   |
+LL |     let ref mut x = 1234543;
+   |                     ------- temporary value created here
+LL |     x
+   |     ^ returns a value referencing data owned by the current function
+
+error[E0515]: cannot return value referencing temporary value
+  --> $DIR/promote-ref-mut-in-let-issue-46557.rs:11:5
+   |
+LL |     let (ref mut x, ) = (1234543, );
+   |                         ----------- temporary value created here
+LL |     x
+   |     ^ returns a value referencing data owned by the current function
+
+error[E0515]: cannot return value referencing temporary value
+  --> $DIR/promote-ref-mut-in-let-issue-46557.rs:15:5
+   |
+LL |       match 1234543 {
+   |       ^     ------- temporary value created here
+   |  _____|
+   | |
+LL | |         ref mut x => x
+LL | |     }
+   | |_____^ returns a value referencing data owned by the current function
+
+error[E0515]: cannot return value referencing temporary value
+  --> $DIR/promote-ref-mut-in-let-issue-46557.rs:21:5
+   |
+LL |       match (123443,) {
+   |       ^     --------- temporary value created here
+   |  _____|
+   | |
+LL | |         (ref mut x,) => x,
+LL | |     }
+   | |_____^ returns a value referencing data owned by the current function
+
+error[E0515]: cannot return reference to temporary value
+  --> $DIR/promote-ref-mut-in-let-issue-46557.rs:27:5
+   |
+LL |     &mut 1234543
+   |     ^^^^^-------
+   |     |    |
+   |     |    temporary value created here
+   |     returns a reference to data owned by the current function
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/src/test/ui/borrowck/promote-ref-mut-in-let-issue-46557.rs b/src/test/ui/borrowck/promote-ref-mut-in-let-issue-46557.rs
new file mode 100644
index 0000000..ae305b6
--- /dev/null
+++ b/src/test/ui/borrowck/promote-ref-mut-in-let-issue-46557.rs
@@ -0,0 +1,31 @@
+// Test that we fail to promote the constant here which has a `ref
+// mut` borrow.
+
+fn gimme_static_mut_let() -> &'static mut u32 {
+    let ref mut x = 1234543; //~ ERROR
+    x
+}
+
+fn gimme_static_mut_let_nested() -> &'static mut u32 {
+    let (ref mut x, ) = (1234543, ); //~ ERROR
+    x
+}
+
+fn gimme_static_mut_match() -> &'static mut u32 {
+    match 1234543 {
+        ref mut x => x //~ ERROR
+    }
+}
+
+fn gimme_static_mut_match_nested() -> &'static mut u32 {
+    match (123443,) {
+        (ref mut x,) => x, //~ ERROR
+    }
+}
+
+fn gimme_static_mut_ampersand() -> &'static mut u32 {
+    &mut 1234543 //~ ERROR
+}
+
+fn main() {
+}
diff --git a/src/test/ui/borrowck/promote-ref-mut-in-let-issue-46557.stderr b/src/test/ui/borrowck/promote-ref-mut-in-let-issue-46557.stderr
new file mode 100644
index 0000000..ae68df7
--- /dev/null
+++ b/src/test/ui/borrowck/promote-ref-mut-in-let-issue-46557.stderr
@@ -0,0 +1,57 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/promote-ref-mut-in-let-issue-46557.rs:5:9
+   |
+LL |     let ref mut x = 1234543;
+   |         ^^^^^^^^^ temporary value does not live long enough
+LL |     x
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/promote-ref-mut-in-let-issue-46557.rs:10:10
+   |
+LL |     let (ref mut x, ) = (1234543, );
+   |          ^^^^^^^^^ borrowed value does not live long enough
+LL |     x
+LL | }
+   | - borrowed value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/promote-ref-mut-in-let-issue-46557.rs:16:9
+   |
+LL |         ref mut x => x
+   |         ^^^^^^^^^ temporary value does not live long enough
+LL |     }
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/promote-ref-mut-in-let-issue-46557.rs:22:10
+   |
+LL |         (ref mut x,) => x,
+   |          ^^^^^^^^^ borrowed value does not live long enough
+LL |     }
+LL | }
+   | - borrowed value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/promote-ref-mut-in-let-issue-46557.rs:27:10
+   |
+LL |     &mut 1234543
+   |          ^^^^^^^ temporary value does not live long enough
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/borrowck/reassignment_immutable_fields.nll.stderr b/src/test/ui/borrowck/reassignment_immutable_fields.nll.stderr
new file mode 100644
index 0000000..d455a8f
--- /dev/null
+++ b/src/test/ui/borrowck/reassignment_immutable_fields.nll.stderr
@@ -0,0 +1,15 @@
+error[E0381]: assign to part of possibly uninitialized variable: `x`
+  --> $DIR/reassignment_immutable_fields.rs:7:5
+   |
+LL |     x.0 = 1;
+   |     ^^^^^^^ use of possibly uninitialized `x`
+
+error[E0381]: assign to part of possibly uninitialized variable: `x`
+  --> $DIR/reassignment_immutable_fields.rs:15:5
+   |
+LL |     x.0 = 1;
+   |     ^^^^^^^ use of possibly uninitialized `x`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/reassignment_immutable_fields.rs b/src/test/ui/borrowck/reassignment_immutable_fields.rs
new file mode 100644
index 0000000..4529e32
--- /dev/null
+++ b/src/test/ui/borrowck/reassignment_immutable_fields.rs
@@ -0,0 +1,20 @@
+// This test is currently disallowed, but we hope someday to support it.
+//
+// FIXME(#21232)
+
+fn assign_both_fields_and_use() {
+    let x: (u32, u32);
+    x.0 = 1; //~ ERROR
+    x.1 = 22; //~ ERROR
+    drop(x.0); //~ ERROR
+    drop(x.1); //~ ERROR
+}
+
+fn assign_both_fields_the_use_var() {
+    let x: (u32, u32);
+    x.0 = 1; //~ ERROR
+    x.1 = 22; //~ ERROR
+    drop(x); //~ ERROR
+}
+
+fn main() { }
diff --git a/src/test/ui/borrowck/reassignment_immutable_fields.stderr b/src/test/ui/borrowck/reassignment_immutable_fields.stderr
new file mode 100644
index 0000000..74f0217
--- /dev/null
+++ b/src/test/ui/borrowck/reassignment_immutable_fields.stderr
@@ -0,0 +1,56 @@
+error[E0594]: cannot assign to field `x.0` of immutable binding
+  --> $DIR/reassignment_immutable_fields.rs:7:5
+   |
+LL |     let x: (u32, u32);
+   |         - help: make this binding mutable: `mut x`
+LL |     x.0 = 1;
+   |     ^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0594]: cannot assign to field `x.1` of immutable binding
+  --> $DIR/reassignment_immutable_fields.rs:8:5
+   |
+LL |     let x: (u32, u32);
+   |         - help: make this binding mutable: `mut x`
+LL |     x.0 = 1;
+LL |     x.1 = 22;
+   |     ^^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0381]: use of possibly uninitialized variable: `x.0`
+  --> $DIR/reassignment_immutable_fields.rs:9:10
+   |
+LL |     drop(x.0);
+   |          ^^^ use of possibly uninitialized `x.0`
+
+error[E0381]: use of possibly uninitialized variable: `x.1`
+  --> $DIR/reassignment_immutable_fields.rs:10:10
+   |
+LL |     drop(x.1);
+   |          ^^^ use of possibly uninitialized `x.1`
+
+error[E0594]: cannot assign to field `x.0` of immutable binding
+  --> $DIR/reassignment_immutable_fields.rs:15:5
+   |
+LL |     let x: (u32, u32);
+   |         - help: make this binding mutable: `mut x`
+LL |     x.0 = 1;
+   |     ^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0594]: cannot assign to field `x.1` of immutable binding
+  --> $DIR/reassignment_immutable_fields.rs:16:5
+   |
+LL |     let x: (u32, u32);
+   |         - help: make this binding mutable: `mut x`
+LL |     x.0 = 1;
+LL |     x.1 = 22;
+   |     ^^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0381]: use of possibly uninitialized variable: `x`
+  --> $DIR/reassignment_immutable_fields.rs:17:10
+   |
+LL |     drop(x);
+   |          ^ use of possibly uninitialized `x`
+
+error: aborting due to 7 previous errors
+
+Some errors occurred: E0381, E0594.
+For more information about an error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/reassignment_immutable_fields_overlapping.nll.stderr b/src/test/ui/borrowck/reassignment_immutable_fields_overlapping.nll.stderr
new file mode 100644
index 0000000..5f1313f
--- /dev/null
+++ b/src/test/ui/borrowck/reassignment_immutable_fields_overlapping.nll.stderr
@@ -0,0 +1,19 @@
+error[E0381]: assign to part of possibly uninitialized variable: `x`
+  --> $DIR/reassignment_immutable_fields_overlapping.rs:12:5
+   |
+LL |     x.a = 1;
+   |     ^^^^^^^ use of possibly uninitialized `x`
+
+error[E0594]: cannot assign to `x.b`, as `x` is not declared as mutable
+  --> $DIR/reassignment_immutable_fields_overlapping.rs:13:5
+   |
+LL |     let x: Foo;
+   |         - help: consider changing this to be mutable: `mut x`
+LL |     x.a = 1;
+LL |     x.b = 22;
+   |     ^^^^^^^^ cannot assign
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0381, E0594.
+For more information about an error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/reassignment_immutable_fields_overlapping.rs b/src/test/ui/borrowck/reassignment_immutable_fields_overlapping.rs
new file mode 100644
index 0000000..d7aad6c
--- /dev/null
+++ b/src/test/ui/borrowck/reassignment_immutable_fields_overlapping.rs
@@ -0,0 +1,16 @@
+// This should never be allowed -- `foo.a` and `foo.b` are
+// overlapping, so since `x` is not `mut` we should not permit
+// reassignment.
+
+union Foo {
+    a: u32,
+    b: u32,
+}
+
+unsafe fn overlapping_fields() {
+    let x: Foo;
+    x.a = 1;  //~ ERROR
+    x.b = 22; //~ ERROR
+}
+
+fn main() { }
diff --git a/src/test/ui/borrowck/reassignment_immutable_fields_overlapping.stderr b/src/test/ui/borrowck/reassignment_immutable_fields_overlapping.stderr
new file mode 100644
index 0000000..673c157
--- /dev/null
+++ b/src/test/ui/borrowck/reassignment_immutable_fields_overlapping.stderr
@@ -0,0 +1,20 @@
+error[E0594]: cannot assign to field `x.a` of immutable binding
+  --> $DIR/reassignment_immutable_fields_overlapping.rs:12:5
+   |
+LL |     let x: Foo;
+   |         - help: make this binding mutable: `mut x`
+LL |     x.a = 1;
+   |     ^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0594]: cannot assign to field `x.b` of immutable binding
+  --> $DIR/reassignment_immutable_fields_overlapping.rs:13:5
+   |
+LL |     let x: Foo;
+   |         - help: make this binding mutable: `mut x`
+LL |     x.a = 1;
+LL |     x.b = 22;
+   |     ^^^^^^^^ cannot mutably borrow field of immutable binding
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/borrowck/reassignment_immutable_fields_twice.nll.stderr b/src/test/ui/borrowck/reassignment_immutable_fields_twice.nll.stderr
new file mode 100644
index 0000000..553ee24
--- /dev/null
+++ b/src/test/ui/borrowck/reassignment_immutable_fields_twice.nll.stderr
@@ -0,0 +1,19 @@
+error[E0594]: cannot assign to `x.0`, as `x` is not declared as mutable
+  --> $DIR/reassignment_immutable_fields_twice.rs:7:5
+   |
+LL |     let x: (u32, u32);
+   |         - help: consider changing this to be mutable: `mut x`
+LL |     x = (22, 44);
+LL |     x.0 = 1;
+   |     ^^^^^^^ cannot assign
+
+error[E0381]: assign to part of possibly uninitialized variable: `x`
+  --> $DIR/reassignment_immutable_fields_twice.rs:12:5
+   |
+LL |     x.0 = 1;
+   |     ^^^^^^^ use of possibly uninitialized `x`
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0381, E0594.
+For more information about an error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/reassignment_immutable_fields_twice.rs b/src/test/ui/borrowck/reassignment_immutable_fields_twice.rs
new file mode 100644
index 0000000..a10baf6
--- /dev/null
+++ b/src/test/ui/borrowck/reassignment_immutable_fields_twice.rs
@@ -0,0 +1,17 @@
+// This should never be allowed -- since `x` is not `mut`, so `x.0`
+// cannot be assigned twice.
+
+fn var_then_field() {
+    let x: (u32, u32);
+    x = (22, 44);
+    x.0 = 1; //~ ERROR
+}
+
+fn same_field_twice() {
+    let x: (u32, u32);
+    x.0 = 1; //~ ERROR
+    x.0 = 22; //~ ERROR
+    x.1 = 44; //~ ERROR
+}
+
+fn main() { }
diff --git a/src/test/ui/borrowck/reassignment_immutable_fields_twice.stderr b/src/test/ui/borrowck/reassignment_immutable_fields_twice.stderr
new file mode 100644
index 0000000..db1c74d
--- /dev/null
+++ b/src/test/ui/borrowck/reassignment_immutable_fields_twice.stderr
@@ -0,0 +1,38 @@
+error[E0594]: cannot assign to field `x.0` of immutable binding
+  --> $DIR/reassignment_immutable_fields_twice.rs:7:5
+   |
+LL |     let x: (u32, u32);
+   |         - help: make this binding mutable: `mut x`
+LL |     x = (22, 44);
+LL |     x.0 = 1;
+   |     ^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0594]: cannot assign to field `x.0` of immutable binding
+  --> $DIR/reassignment_immutable_fields_twice.rs:12:5
+   |
+LL |     let x: (u32, u32);
+   |         - help: make this binding mutable: `mut x`
+LL |     x.0 = 1;
+   |     ^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0594]: cannot assign to field `x.0` of immutable binding
+  --> $DIR/reassignment_immutable_fields_twice.rs:13:5
+   |
+LL |     let x: (u32, u32);
+   |         - help: make this binding mutable: `mut x`
+LL |     x.0 = 1;
+LL |     x.0 = 22;
+   |     ^^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0594]: cannot assign to field `x.1` of immutable binding
+  --> $DIR/reassignment_immutable_fields_twice.rs:14:5
+   |
+LL |     let x: (u32, u32);
+   |         - help: make this binding mutable: `mut x`
+...
+LL |     x.1 = 44;
+   |     ^^^^^^^^ cannot mutably borrow field of immutable binding
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.rs b/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.rs
new file mode 100644
index 0000000..da918ba
--- /dev/null
+++ b/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.rs
@@ -0,0 +1,53 @@
+// Check that explicit region bounds are allowed on the various
+// nominal types (but not on other types) and that they are type
+// checked.
+
+struct Inv<'a> { // invariant w/r/t 'a
+    x: &'a mut &'a isize
+}
+
+pub trait Foo<'a, 't> {
+    fn no_bound<'b>(self, b: Inv<'b>);
+    fn has_bound<'b:'a>(self, b: Inv<'b>);
+    fn wrong_bound1<'b,'c,'d:'a+'b>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>);
+    fn wrong_bound2<'b,'c,'d:'a+'b>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>);
+    fn okay_bound<'b,'c,'d:'a+'b+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>);
+    fn another_bound<'x: 'a>(self, x: Inv<'x>, y: Inv<'t>);
+}
+
+impl<'a, 't> Foo<'a, 't> for &'a isize {
+    fn no_bound<'b:'a>(self, b: Inv<'b>) {
+        //~^ ERROR lifetime parameters or bounds on method `no_bound` do not match
+    }
+
+    fn has_bound<'b>(self, b: Inv<'b>) {
+        //~^ ERROR lifetime parameters or bounds on method `has_bound` do not match
+    }
+
+    fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) {
+        //~^ ERROR method not compatible with trait
+        //
+        // Note: This is a terrible error message. It is caused
+        // because, in the trait, 'b is early bound, and in the impl,
+        // 'c is early bound, so -- after substitution -- the
+        // lifetimes themselves look isomorphic.  We fail because the
+        // lifetimes that appear in the types are in the wrong
+        // order. This should really be fixed by keeping more
+        // information about the lifetime declarations in the trait so
+        // that we can compare better to the impl, even in cross-crate
+        // cases.
+    }
+
+    fn wrong_bound2(self, b: Inv, c: Inv, d: Inv) {
+        //~^ ERROR lifetime parameters or bounds on method `wrong_bound2` do not match the trait
+    }
+
+    fn okay_bound<'b,'c,'e:'b+'c>(self, b: Inv<'b>, c: Inv<'c>, e: Inv<'e>) {
+    }
+
+    fn another_bound<'x: 't>(self, x: Inv<'x>, y: Inv<'t>) {
+        //~^ ERROR E0276
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr b/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr
new file mode 100644
index 0000000..8d6ac62
--- /dev/null
+++ b/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr
@@ -0,0 +1,59 @@
+error[E0195]: lifetime parameters or bounds on method `no_bound` do not match the trait declaration
+  --> $DIR/regions-bound-missing-bound-in-impl.rs:19:16
+   |
+LL |     fn no_bound<'b>(self, b: Inv<'b>);
+   |                ---- lifetimes in impl do not match this method in trait
+...
+LL |     fn no_bound<'b:'a>(self, b: Inv<'b>) {
+   |                ^^^^^^^ lifetimes do not match method in trait
+
+error[E0195]: lifetime parameters or bounds on method `has_bound` do not match the trait declaration
+  --> $DIR/regions-bound-missing-bound-in-impl.rs:23:17
+   |
+LL |     fn has_bound<'b:'a>(self, b: Inv<'b>);
+   |                 ------- lifetimes in impl do not match this method in trait
+...
+LL |     fn has_bound<'b>(self, b: Inv<'b>) {
+   |                 ^^^^ lifetimes do not match method in trait
+
+error[E0308]: method not compatible with trait
+  --> $DIR/regions-bound-missing-bound-in-impl.rs:27:5
+   |
+LL |     fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
+   |
+   = note: expected type `fn(&'a isize, Inv<'c>, Inv<'c>, Inv<'d>)`
+              found type `fn(&'a isize, Inv<'_>, Inv<'c>, Inv<'d>)`
+note: the lifetime 'c as defined on the method body at 27:24...
+  --> $DIR/regions-bound-missing-bound-in-impl.rs:27:24
+   |
+LL |     fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) {
+   |                        ^^
+note: ...does not necessarily outlive the lifetime 'c as defined on the method body at 27:24
+  --> $DIR/regions-bound-missing-bound-in-impl.rs:27:24
+   |
+LL |     fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) {
+   |                        ^^
+
+error[E0195]: lifetime parameters or bounds on method `wrong_bound2` do not match the trait declaration
+  --> $DIR/regions-bound-missing-bound-in-impl.rs:41:5
+   |
+LL |     fn wrong_bound2<'b,'c,'d:'a+'b>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>);
+   |                    ---------------- lifetimes in impl do not match this method in trait
+...
+LL |     fn wrong_bound2(self, b: Inv, c: Inv, d: Inv) {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetimes do not match method in trait
+
+error[E0276]: impl has stricter requirements than trait
+  --> $DIR/regions-bound-missing-bound-in-impl.rs:48:5
+   |
+LL |     fn another_bound<'x: 'a>(self, x: Inv<'x>, y: Inv<'t>);
+   |     ------------------------------------------------------- definition of `another_bound` from trait
+...
+LL |     fn another_bound<'x: 't>(self, x: Inv<'x>, y: Inv<'t>) {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `'x: 't`
+
+error: aborting due to 5 previous errors
+
+Some errors occurred: E0195, E0276, E0308.
+For more information about an error, try `rustc --explain E0195`.
diff --git a/src/test/ui/borrowck/regions-escape-bound-fn-2.rs b/src/test/ui/borrowck/regions-escape-bound-fn-2.rs
new file mode 100644
index 0000000..cb42303
--- /dev/null
+++ b/src/test/ui/borrowck/regions-escape-bound-fn-2.rs
@@ -0,0 +1,10 @@
+fn with_int<F>(f: F) where F: FnOnce(&isize) {
+    let x = 3;
+    f(&x);
+}
+
+fn main() {
+    let mut x = None;
+    with_int(|y| x = Some(y));
+    //~^ ERROR borrowed data cannot be stored outside of its closure
+}
diff --git a/src/test/ui/borrowck/regions-escape-bound-fn-2.stderr b/src/test/ui/borrowck/regions-escape-bound-fn-2.stderr
new file mode 100644
index 0000000..4b37eda
--- /dev/null
+++ b/src/test/ui/borrowck/regions-escape-bound-fn-2.stderr
@@ -0,0 +1,12 @@
+error: borrowed data cannot be stored outside of its closure
+  --> $DIR/regions-escape-bound-fn-2.rs:8:27
+   |
+LL |     let mut x = None;
+   |         ----- borrowed data cannot be stored into here...
+LL |     with_int(|y| x = Some(y));
+   |              ---          ^ cannot be stored outside of its closure
+   |              |
+   |              ...because it cannot outlive this closure
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/borrowck/regions-escape-bound-fn.rs b/src/test/ui/borrowck/regions-escape-bound-fn.rs
new file mode 100644
index 0000000..772df3e
--- /dev/null
+++ b/src/test/ui/borrowck/regions-escape-bound-fn.rs
@@ -0,0 +1,10 @@
+fn with_int<F>(f: F) where F: FnOnce(&isize) {
+    let x = 3;
+    f(&x);
+}
+
+fn main() {
+    let mut x: Option<&isize> = None;
+    with_int(|y| x = Some(y));
+    //~^ ERROR borrowed data cannot be stored outside of its closure
+}
diff --git a/src/test/ui/borrowck/regions-escape-bound-fn.stderr b/src/test/ui/borrowck/regions-escape-bound-fn.stderr
new file mode 100644
index 0000000..4973d53
--- /dev/null
+++ b/src/test/ui/borrowck/regions-escape-bound-fn.stderr
@@ -0,0 +1,12 @@
+error: borrowed data cannot be stored outside of its closure
+  --> $DIR/regions-escape-bound-fn.rs:8:27
+   |
+LL |     let mut x: Option<&isize> = None;
+   |         ----- borrowed data cannot be stored into here...
+LL |     with_int(|y| x = Some(y));
+   |              ---          ^ cannot be stored outside of its closure
+   |              |
+   |              ...because it cannot outlive this closure
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/borrowck/regions-escape-unboxed-closure.rs b/src/test/ui/borrowck/regions-escape-unboxed-closure.rs
new file mode 100644
index 0000000..62ddf4d
--- /dev/null
+++ b/src/test/ui/borrowck/regions-escape-unboxed-closure.rs
@@ -0,0 +1,8 @@
+fn with_int(f: &mut FnMut(&isize)) {
+}
+
+fn main() {
+    let mut x: Option<&isize> = None;
+    with_int(&mut |y| x = Some(y));
+    //~^ ERROR borrowed data cannot be stored outside of its closure
+}
diff --git a/src/test/ui/borrowck/regions-escape-unboxed-closure.stderr b/src/test/ui/borrowck/regions-escape-unboxed-closure.stderr
new file mode 100644
index 0000000..047e290
--- /dev/null
+++ b/src/test/ui/borrowck/regions-escape-unboxed-closure.stderr
@@ -0,0 +1,12 @@
+error: borrowed data cannot be stored outside of its closure
+  --> $DIR/regions-escape-unboxed-closure.rs:6:32
+   |
+LL |     let mut x: Option<&isize> = None;
+   |         ----- borrowed data cannot be stored into here...
+LL |     with_int(&mut |y| x = Some(y));
+   |                   ---          ^ cannot be stored outside of its closure
+   |                   |
+   |                   ...because it cannot outlive this closure
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/borrowck/two-phase-across-loop.rs b/src/test/ui/borrowck/two-phase-across-loop.rs
new file mode 100644
index 0000000..b1a4c54
--- /dev/null
+++ b/src/test/ui/borrowck/two-phase-across-loop.rs
@@ -0,0 +1,24 @@
+// Test that a borrow which starts as a 2-phase borrow and gets
+// carried around a loop winds up conflicting with itself.
+
+#![feature(nll)]
+
+struct Foo { x: String }
+
+impl Foo {
+    fn get_string(&mut self) -> &str {
+        &self.x
+    }
+}
+
+fn main() {
+    let mut foo = Foo { x: format!("Hello, world") };
+    let mut strings = vec![];
+
+    loop {
+        strings.push(foo.get_string()); //~ ERROR cannot borrow `foo` as mutable
+        if strings.len() > 2 { break; }
+    }
+
+    println!("{:?}", strings);
+}
diff --git a/src/test/ui/borrowck/two-phase-across-loop.stderr b/src/test/ui/borrowck/two-phase-across-loop.stderr
new file mode 100644
index 0000000..933d3eb
--- /dev/null
+++ b/src/test/ui/borrowck/two-phase-across-loop.stderr
@@ -0,0 +1,9 @@
+error[E0499]: cannot borrow `foo` as mutable more than once at a time
+  --> $DIR/two-phase-across-loop.rs:19:22
+   |
+LL |         strings.push(foo.get_string());
+   |                      ^^^ mutable borrow starts here in previous iteration of loop
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/borrowck/two-phase-activation-sharing-interference.nll_target.stderr b/src/test/ui/borrowck/two-phase-activation-sharing-interference.nll_target.stderr
new file mode 100644
index 0000000..8370aad
--- /dev/null
+++ b/src/test/ui/borrowck/two-phase-activation-sharing-interference.nll_target.stderr
@@ -0,0 +1,47 @@
+error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
+  --> $DIR/two-phase-activation-sharing-interference.rs:32:15
+   |
+LL |     let y = &mut x;
+   |             ------ mutable borrow occurs here
+LL |     { let z = &x; read(z); }
+   |               ^^ immutable borrow occurs here
+LL |
+LL |     *y += 1;
+   |     ------- mutable borrow later used here
+
+error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
+  --> $DIR/two-phase-activation-sharing-interference.rs:40:13
+   |
+LL |     let y = &mut x;
+   |             ------ mutable borrow occurs here
+LL |     let z = &x;
+   |             ^^ immutable borrow occurs here
+LL |
+LL |     *y += 1;
+   |     ------- mutable borrow later used here
+
+error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
+  --> $DIR/two-phase-activation-sharing-interference.rs:51:13
+   |
+LL |     let y = &mut x;
+   |             ------ mutable borrow occurs here
+LL |     let z = &x;
+   |             ^^ immutable borrow occurs here
+...
+LL |     *y += 1;
+   |     ------- mutable borrow later used here
+
+error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
+  --> $DIR/two-phase-activation-sharing-interference.rs:62:14
+   |
+LL |     let y = &mut x;
+   |             ------ mutable borrow occurs here
+LL |     let _z = &x;
+   |              ^^ immutable borrow occurs here
+LL |
+LL |     *y += 1;
+   |     ------- mutable borrow later used here
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/borrowck/two-phase-activation-sharing-interference.rs b/src/test/ui/borrowck/two-phase-activation-sharing-interference.rs
new file mode 100644
index 0000000..5754220
--- /dev/null
+++ b/src/test/ui/borrowck/two-phase-activation-sharing-interference.rs
@@ -0,0 +1,69 @@
+// ignore-tidy-linelength
+
+// revisions: nll_target
+
+// The following revisions are disabled due to missing support from two-phase beyond autorefs
+//[nll_beyond] compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z two-phase-beyond-autoref
+
+//[nll_target] compile-flags: -Z borrowck=mir -Z two-phase-borrows
+
+// This is an important corner case pointed out by Niko: one is
+// allowed to initiate a shared borrow during a reservation, but it
+// *must end* before the activation occurs.
+//
+// FIXME: for clarity, diagnostics for these cases might be better off
+// if they specifically said "cannot activate mutable borrow of `x`"
+//
+// The convention for the listed revisions: "lxl" means lexical
+// lifetimes (which can be easier to reason about). "nll" means
+// non-lexical lifetimes. "nll_target" means the initial conservative
+// two-phase borrows that only applies to autoref-introduced borrows.
+// "nll_beyond" means the generalization of two-phase borrows to all
+// `&mut`-borrows (doing so makes it easier to write code for specific
+// corner cases).
+
+#![allow(dead_code)]
+
+fn read(_: &i32) { }
+
+fn ok() {
+    let mut x = 3;
+    let y = &mut x;
+    { let z = &x; read(z); }
+    //[nll_target]~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable
+    *y += 1;
+}
+
+fn not_ok() {
+    let mut x = 3;
+    let y = &mut x;
+    let z = &x;
+    //[nll_target]~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable
+    *y += 1;
+    //[lxl_beyond]~^   ERROR cannot borrow `x` as mutable because it is also borrowed as immutable
+    //[nll_beyond]~^^  ERROR cannot borrow `x` as mutable because it is also borrowed as immutable
+    read(z);
+}
+
+fn should_be_ok_with_nll() {
+    let mut x = 3;
+    let y = &mut x;
+    let z = &x;
+    //[nll_target]~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable
+    read(z);
+    *y += 1;
+    //[lxl_beyond]~^ ERROR cannot borrow `x` as mutable because it is also borrowed as immutable
+    // (okay with (generalized) nll today)
+}
+
+fn should_also_eventually_be_ok_with_nll() {
+    let mut x = 3;
+    let y = &mut x;
+    let _z = &x;
+    //[nll_target]~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable
+    *y += 1;
+    //[lxl_beyond]~^ ERROR cannot borrow `x` as mutable because it is also borrowed as immutable
+    // (okay with (generalized) nll today)
+}
+
+fn main() { }
diff --git a/src/test/ui/borrowck/two-phase-allow-access-during-reservation.nll_target.stderr b/src/test/ui/borrowck/two-phase-allow-access-during-reservation.nll_target.stderr
new file mode 100644
index 0000000..9f31c3f
--- /dev/null
+++ b/src/test/ui/borrowck/two-phase-allow-access-during-reservation.nll_target.stderr
@@ -0,0 +1,27 @@
+error[E0503]: cannot use `i` because it was mutably borrowed
+  --> $DIR/two-phase-allow-access-during-reservation.rs:30:19
+   |
+LL |     /*1*/ let p = &mut i; // (reservation of `i` starts here)
+   |                   ------ borrow of `i` occurs here
+LL | 
+LL |     /*2*/ let j = i;      // OK: `i` is only reserved here
+   |                   ^ use of borrowed `i`
+...
+LL |     /*3*/ *p += 1;        // (mutable borrow of `i` starts here, since `p` is used)
+   |           ------- borrow later used here
+
+error[E0503]: cannot use `i` because it was mutably borrowed
+  --> $DIR/two-phase-allow-access-during-reservation.rs:35:19
+   |
+LL |     /*1*/ let p = &mut i; // (reservation of `i` starts here)
+   |                   ------ borrow of `i` occurs here
+...
+LL |     /*4*/ let k = i;
+   |                   ^ use of borrowed `i`
+...
+LL |     /*5*/ *p += 1;
+   |           ------- borrow later used here
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0503`.
diff --git a/src/test/ui/borrowck/two-phase-allow-access-during-reservation.rs b/src/test/ui/borrowck/two-phase-allow-access-during-reservation.rs
new file mode 100644
index 0000000..e428964
--- /dev/null
+++ b/src/test/ui/borrowck/two-phase-allow-access-during-reservation.rs
@@ -0,0 +1,41 @@
+// ignore-tidy-linelength
+
+// revisions: nll_target
+
+// The following revisions are disabled due to missing support for two_phase_beyond_autoref
+//[nll_beyond] compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z two_phase_beyond_autoref
+
+//[nll_target] compile-flags: -Z borrowck=mir -Z two-phase-borrows
+
+// This is the second counter-example from Niko's blog post
+// smallcultfollowing.com/babysteps/blog/2017/03/01/nested-method-calls-via-two-phase-borrowing/
+//
+// It is "artificial". It is meant to illustrate directly that we
+// should allow an aliasing access during reservation, but *not* while
+// the mutable borrow is active.
+//
+// The convention for the listed revisions: "lxl" means lexical
+// lifetimes (which can be easier to reason about). "nll" means
+// non-lexical lifetimes. "nll_target" means the initial conservative
+// two-phase borrows that only applies to autoref-introduced borrows.
+// "nll_beyond" means the generalization of two-phase borrows to all
+// `&mut`-borrows (doing so makes it easier to write code for specific
+// corner cases).
+
+fn main() {
+    /*0*/ let mut i = 0;
+
+    /*1*/ let p = &mut i; // (reservation of `i` starts here)
+
+    /*2*/ let j = i;      // OK: `i` is only reserved here
+                          //[nll_target]~^  ERROR cannot use `i` because it was mutably borrowed [E0503]
+
+    /*3*/ *p += 1;        // (mutable borrow of `i` starts here, since `p` is used)
+
+    /*4*/ let k = i;      //[nll_beyond]~  ERROR cannot use `i` because it was mutably borrowed [E0503]
+                          //[nll_target]~^ ERROR cannot use `i` because it was mutably borrowed [E0503]
+
+    /*5*/ *p += 1;
+
+    let _ = (j, k, p);
+}
diff --git a/src/test/ui/borrowck/two-phase-cannot-nest-mut-self-calls.rs b/src/test/ui/borrowck/two-phase-cannot-nest-mut-self-calls.rs
new file mode 100644
index 0000000..fd1b884
--- /dev/null
+++ b/src/test/ui/borrowck/two-phase-cannot-nest-mut-self-calls.rs
@@ -0,0 +1,21 @@
+// compile-flags: -Z borrowck=mir -Z two-phase-borrows
+
+// This is the third counter-example from Niko's blog post
+// smallcultfollowing.com/babysteps/blog/2017/03/01/nested-method-calls-via-two-phase-borrowing/
+//
+// It shows that not all nested method calls on `self` are magically
+// allowed by this change. In particular, a nested `&mut` borrow is
+// still disallowed.
+
+fn main() {
+
+
+    let mut vec = vec![0, 1];
+    vec.get({
+
+        vec.push(2);
+        //~^ ERROR cannot borrow `vec` as mutable because it is also borrowed as immutable
+
+        0
+    });
+}
diff --git a/src/test/ui/borrowck/two-phase-cannot-nest-mut-self-calls.stderr b/src/test/ui/borrowck/two-phase-cannot-nest-mut-self-calls.stderr
new file mode 100644
index 0000000..9bfd8b99
--- /dev/null
+++ b/src/test/ui/borrowck/two-phase-cannot-nest-mut-self-calls.stderr
@@ -0,0 +1,14 @@
+error[E0502]: cannot borrow `vec` as mutable because it is also borrowed as immutable
+  --> $DIR/two-phase-cannot-nest-mut-self-calls.rs:16:9
+   |
+LL |     vec.get({
+   |     --- --- immutable borrow later used by call
+   |     |
+   |     immutable borrow occurs here
+LL | 
+LL |         vec.push(2);
+   |         ^^^ mutable borrow occurs here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/borrowck/two-phase-method-receivers.rs b/src/test/ui/borrowck/two-phase-method-receivers.rs
new file mode 100644
index 0000000..f1df1a6
--- /dev/null
+++ b/src/test/ui/borrowck/two-phase-method-receivers.rs
@@ -0,0 +1,17 @@
+// compile-flags: -Z borrowck=mir -Z two-phase-borrows
+
+// run-pass
+
+struct Foo<'a> {
+    x: &'a i32
+}
+
+impl<'a> Foo<'a> {
+    fn method(&mut self, _: &i32) {
+    }
+}
+
+fn main() {
+    let a = &mut Foo { x: &22 };
+    Foo::method(a, a.x);
+}
diff --git a/src/test/ui/borrowck/two-phase-multi-mut.rs b/src/test/ui/borrowck/two-phase-multi-mut.rs
new file mode 100644
index 0000000..ed3d257
--- /dev/null
+++ b/src/test/ui/borrowck/two-phase-multi-mut.rs
@@ -0,0 +1,16 @@
+#![feature(nll)]
+
+struct Foo {
+}
+
+impl Foo {
+    fn method(&mut self, foo: &mut Foo) {
+    }
+}
+
+fn main() {
+    let mut foo = Foo { };
+    foo.method(&mut foo);
+    //~^     cannot borrow `foo` as mutable more than once at a time
+    //~^^    cannot borrow `foo` as mutable more than once at a time
+}
diff --git a/src/test/ui/borrowck/two-phase-multi-mut.stderr b/src/test/ui/borrowck/two-phase-multi-mut.stderr
new file mode 100644
index 0000000..c416850
--- /dev/null
+++ b/src/test/ui/borrowck/two-phase-multi-mut.stderr
@@ -0,0 +1,22 @@
+error[E0499]: cannot borrow `foo` as mutable more than once at a time
+  --> $DIR/two-phase-multi-mut.rs:13:5
+   |
+LL |     foo.method(&mut foo);
+   |     ^^^^------^--------^
+   |     |   |      |
+   |     |   |      first mutable borrow occurs here
+   |     |   first borrow later used by call
+   |     second mutable borrow occurs here
+
+error[E0499]: cannot borrow `foo` as mutable more than once at a time
+  --> $DIR/two-phase-multi-mut.rs:13:16
+   |
+LL |     foo.method(&mut foo);
+   |     --- ------ ^^^^^^^^ second mutable borrow occurs here
+   |     |   |
+   |     |   first borrow later used by call
+   |     first mutable borrow occurs here
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/borrowck/two-phase-multiple-activations.rs b/src/test/ui/borrowck/two-phase-multiple-activations.rs
new file mode 100644
index 0000000..38ba094
--- /dev/null
+++ b/src/test/ui/borrowck/two-phase-multiple-activations.rs
@@ -0,0 +1,23 @@
+// compile-flags: -Z borrowck=mir -Z two-phase-borrows
+
+// run-pass
+
+use std::io::Result;
+
+struct Foo {}
+
+pub trait FakeRead {
+    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize>;
+}
+
+impl FakeRead for Foo {
+    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize> {
+        Ok(4)
+    }
+}
+
+fn main() {
+    let mut a = Foo {};
+    let mut v = Vec::new();
+    a.read_to_end(&mut v);
+}
diff --git a/src/test/ui/borrowck/two-phase-nonrecv-autoref.ast.nll.stderr b/src/test/ui/borrowck/two-phase-nonrecv-autoref.ast.nll.stderr
new file mode 100644
index 0000000..223de36
--- /dev/null
+++ b/src/test/ui/borrowck/two-phase-nonrecv-autoref.ast.nll.stderr
@@ -0,0 +1,71 @@
+error[E0499]: cannot borrow `*f` as mutable more than once at a time
+  --> $DIR/two-phase-nonrecv-autoref.rs:60:11
+   |
+LL |         f(f(10));
+   |         - ^ second mutable borrow occurs here
+   |         |
+   |         first mutable borrow occurs here
+   |         first borrow later used by call
+
+error[E0382]: use of moved value: `f`
+  --> $DIR/two-phase-nonrecv-autoref.rs:69:11
+   |
+LL |     fn twice_ten_so<F: FnOnce(i32) -> i32>(f: Box<F>) {
+   |                                            - move occurs because `f` has type `std::boxed::Box<F>`, which does not implement the `Copy` trait
+LL |         f(f(10));
+   |         - ^ value used here after move
+   |         |
+   |         value moved here
+
+error[E0499]: cannot borrow `*f` as mutable more than once at a time
+  --> $DIR/two-phase-nonrecv-autoref.rs:76:11
+   |
+LL |         f(f(10));
+   |         - ^ second mutable borrow occurs here
+   |         |
+   |         first mutable borrow occurs here
+   |         first borrow later used by call
+
+error[E0382]: use of moved value: `f`
+  --> $DIR/two-phase-nonrecv-autoref.rs:85:11
+   |
+LL |     fn twice_ten_oo(f: Box<FnOnce(i32) -> i32>) {
+   |                     - move occurs because `f` has type `std::boxed::Box<dyn std::ops::FnOnce(i32) -> i32>`, which does not implement the `Copy` trait
+LL |         f(f(10));
+   |         - ^ value used here after move
+   |         |
+   |         value moved here
+
+error[E0502]: cannot borrow `a` as immutable because it is also borrowed as mutable
+  --> $DIR/two-phase-nonrecv-autoref.rs:125:27
+   |
+LL |     double_access(&mut a, &a);
+   |     ------------- ------  ^^ immutable borrow occurs here
+   |     |             |
+   |     |             mutable borrow occurs here
+   |     mutable borrow later used by call
+
+error[E0502]: cannot borrow `i` as immutable because it is also borrowed as mutable
+  --> $DIR/two-phase-nonrecv-autoref.rs:153:7
+   |
+LL |     i[i[3]] = 4;
+   |     --^----
+   |     | |
+   |     | immutable borrow occurs here
+   |     mutable borrow occurs here
+   |     mutable borrow later used here
+
+error[E0502]: cannot borrow `i` as immutable because it is also borrowed as mutable
+  --> $DIR/two-phase-nonrecv-autoref.rs:159:7
+   |
+LL |     i[i[3]] = i[4];
+   |     --^----
+   |     | |
+   |     | immutable borrow occurs here
+   |     mutable borrow occurs here
+   |     mutable borrow later used here
+
+error: aborting due to 7 previous errors
+
+Some errors occurred: E0382, E0499, E0502.
+For more information about an error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/two-phase-nonrecv-autoref.ast.stderr b/src/test/ui/borrowck/two-phase-nonrecv-autoref.ast.stderr
new file mode 100644
index 0000000..d98b272
--- /dev/null
+++ b/src/test/ui/borrowck/two-phase-nonrecv-autoref.ast.stderr
@@ -0,0 +1,113 @@
+error[E0503]: cannot use `*x` because it was mutably borrowed
+  --> $DIR/two-phase-nonrecv-autoref.rs:31:12
+   |
+LL |     foo(x, *x);
+   |         -  ^^ use of borrowed `*x`
+   |         |
+   |         borrow of `*x` occurs here
+
+error[E0499]: cannot borrow `*f` as mutable more than once at a time
+  --> $DIR/two-phase-nonrecv-autoref.rs:60:11
+   |
+LL |         f(f(10));
+   |         - ^    - first borrow ends here
+   |         | |
+   |         | second mutable borrow occurs here
+   |         first mutable borrow occurs here
+
+error[E0382]: use of moved value: `f`
+  --> $DIR/two-phase-nonrecv-autoref.rs:69:11
+   |
+LL |         f(f(10));
+   |         - ^ value used here after move
+   |         |
+   |         value moved here
+   |
+   = note: move occurs because `f` has type `std::boxed::Box<F>`, which does not implement the `Copy` trait
+
+error[E0499]: cannot borrow `*f` as mutable more than once at a time
+  --> $DIR/two-phase-nonrecv-autoref.rs:76:11
+   |
+LL |         f(f(10));
+   |         - ^    - first borrow ends here
+   |         | |
+   |         | second mutable borrow occurs here
+   |         first mutable borrow occurs here
+
+error[E0382]: use of moved value: `f`
+  --> $DIR/two-phase-nonrecv-autoref.rs:85:11
+   |
+LL |         f(f(10));
+   |         - ^ value used here after move
+   |         |
+   |         value moved here
+   |
+   = note: move occurs because `f` has type `std::boxed::Box<(dyn std::ops::FnOnce(i32) -> i32 + 'static)>`, which does not implement the `Copy` trait
+
+error[E0502]: cannot borrow `a` as immutable because it is also borrowed as mutable
+  --> $DIR/two-phase-nonrecv-autoref.rs:125:28
+   |
+LL |     double_access(&mut a, &a);
+   |                        -   ^- mutable borrow ends here
+   |                        |   |
+   |                        |   immutable borrow occurs here
+   |                        mutable borrow occurs here
+
+error[E0502]: cannot borrow `a` as immutable because it is also borrowed as mutable
+  --> $DIR/two-phase-nonrecv-autoref.rs:131:9
+   |
+LL |     a.m(a.i(10));
+   |     -   ^      - mutable borrow ends here
+   |     |   |
+   |     |   immutable borrow occurs here
+   |     mutable borrow occurs here
+
+error[E0502]: cannot borrow `i` as immutable because it is also borrowed as mutable
+  --> $DIR/two-phase-nonrecv-autoref.rs:153:7
+   |
+LL |     i[i[3]] = 4;
+   |     - ^   - mutable borrow ends here
+   |     | |
+   |     | immutable borrow occurs here
+   |     mutable borrow occurs here
+
+error[E0502]: cannot borrow `i` as immutable because it is also borrowed as mutable
+  --> $DIR/two-phase-nonrecv-autoref.rs:159:7
+   |
+LL |     i[i[3]] = i[4];
+   |     - ^   - mutable borrow ends here
+   |     | |
+   |     | immutable borrow occurs here
+   |     mutable borrow occurs here
+
+error[E0502]: cannot borrow `v` as immutable because it is also borrowed as mutable
+  --> $DIR/two-phase-nonrecv-autoref.rs:168:12
+   |
+LL |     v.push(v.len());
+   |     -      ^      - mutable borrow ends here
+   |     |      |
+   |     |      immutable borrow occurs here
+   |     mutable borrow occurs here
+
+error[E0502]: cannot borrow `s` as immutable because it is also borrowed as mutable
+  --> $DIR/two-phase-nonrecv-autoref.rs:179:9
+   |
+LL |     s.m(s.i(10));
+   |     -   ^      - mutable borrow ends here
+   |     |   |
+   |     |   immutable borrow occurs here
+   |     mutable borrow occurs here
+
+error[E0502]: cannot borrow `t` as immutable because it is also borrowed as mutable
+  --> $DIR/two-phase-nonrecv-autoref.rs:184:9
+   |
+LL |     t.m(t.i(10));
+   |     -   ^      - mutable borrow ends here
+   |     |   |
+   |     |   immutable borrow occurs here
+   |     mutable borrow occurs here
+
+error: aborting due to 12 previous errors
+
+Some errors occurred: E0382, E0499, E0502, E0503.
+For more information about an error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/two-phase-nonrecv-autoref.nll.stderr b/src/test/ui/borrowck/two-phase-nonrecv-autoref.nll.stderr
new file mode 100644
index 0000000..223de36
--- /dev/null
+++ b/src/test/ui/borrowck/two-phase-nonrecv-autoref.nll.stderr
@@ -0,0 +1,71 @@
+error[E0499]: cannot borrow `*f` as mutable more than once at a time
+  --> $DIR/two-phase-nonrecv-autoref.rs:60:11
+   |
+LL |         f(f(10));
+   |         - ^ second mutable borrow occurs here
+   |         |
+   |         first mutable borrow occurs here
+   |         first borrow later used by call
+
+error[E0382]: use of moved value: `f`
+  --> $DIR/two-phase-nonrecv-autoref.rs:69:11
+   |
+LL |     fn twice_ten_so<F: FnOnce(i32) -> i32>(f: Box<F>) {
+   |                                            - move occurs because `f` has type `std::boxed::Box<F>`, which does not implement the `Copy` trait
+LL |         f(f(10));
+   |         - ^ value used here after move
+   |         |
+   |         value moved here
+
+error[E0499]: cannot borrow `*f` as mutable more than once at a time
+  --> $DIR/two-phase-nonrecv-autoref.rs:76:11
+   |
+LL |         f(f(10));
+   |         - ^ second mutable borrow occurs here
+   |         |
+   |         first mutable borrow occurs here
+   |         first borrow later used by call
+
+error[E0382]: use of moved value: `f`
+  --> $DIR/two-phase-nonrecv-autoref.rs:85:11
+   |
+LL |     fn twice_ten_oo(f: Box<FnOnce(i32) -> i32>) {
+   |                     - move occurs because `f` has type `std::boxed::Box<dyn std::ops::FnOnce(i32) -> i32>`, which does not implement the `Copy` trait
+LL |         f(f(10));
+   |         - ^ value used here after move
+   |         |
+   |         value moved here
+
+error[E0502]: cannot borrow `a` as immutable because it is also borrowed as mutable
+  --> $DIR/two-phase-nonrecv-autoref.rs:125:27
+   |
+LL |     double_access(&mut a, &a);
+   |     ------------- ------  ^^ immutable borrow occurs here
+   |     |             |
+   |     |             mutable borrow occurs here
+   |     mutable borrow later used by call
+
+error[E0502]: cannot borrow `i` as immutable because it is also borrowed as mutable
+  --> $DIR/two-phase-nonrecv-autoref.rs:153:7
+   |
+LL |     i[i[3]] = 4;
+   |     --^----
+   |     | |
+   |     | immutable borrow occurs here
+   |     mutable borrow occurs here
+   |     mutable borrow later used here
+
+error[E0502]: cannot borrow `i` as immutable because it is also borrowed as mutable
+  --> $DIR/two-phase-nonrecv-autoref.rs:159:7
+   |
+LL |     i[i[3]] = i[4];
+   |     --^----
+   |     | |
+   |     | immutable borrow occurs here
+   |     mutable borrow occurs here
+   |     mutable borrow later used here
+
+error: aborting due to 7 previous errors
+
+Some errors occurred: E0382, E0499, E0502.
+For more information about an error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/two-phase-nonrecv-autoref.rs b/src/test/ui/borrowck/two-phase-nonrecv-autoref.rs
new file mode 100644
index 0000000..1005da0
--- /dev/null
+++ b/src/test/ui/borrowck/two-phase-nonrecv-autoref.rs
@@ -0,0 +1,190 @@
+// revisions: ast nll
+//[ast]compile-flags:
+//[nll]compile-flags: -Z borrowck=mir -Z two-phase-borrows
+
+//[g2p]compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z two-phase-beyond-autoref
+// the above revision is disabled until two-phase-beyond-autoref support is better
+
+// This is a test checking that when we limit two-phase borrows to
+// method receivers, we do not let other kinds of auto-ref to leak
+// through.
+//
+// The g2p revision illustrates the "undesirable" behavior you would
+// otherwise observe without limiting the phasing to autoref on method
+// receivers (namely, in many cases demonstrated below, the error
+// would not arise).
+
+// (If we revise the compiler or this test so that the g2p revision
+// passes, turn the `rustc_attrs` feature back on and tag the `fn
+// main` with `#[rustc_error]` so that this remains a valid
+// compile-fail test.)
+//
+// #![feature(rustc_attrs)]
+
+use std::ops::{Index, IndexMut};
+
+fn foo(x: &mut u32, y: u32) {
+    *x += y;
+}
+
+fn deref_coercion(x: &mut u32) {
+    foo(x, *x);
+    //[ast]~^ ERROR cannot use `*x` because it was mutably borrowed [E0503]
+    // Above error is a known limitation of AST borrowck
+}
+
+// While adding a flag to adjustments (indicating whether they
+// should support two-phase borrows, here are the cases I
+// encountered:
+//
+// - [x] Resolving overloaded_call_traits (call, call_mut, call_once)
+// - [x] deref_coercion (shown above)
+// - [x] coerce_unsized e.g., `&[T; n]`, `&mut [T; n] -> &[T]`,
+//                      `&mut [T; n] -> &mut [T]`, `&Concrete -> &Trait`
+// - [x] Method Call Receivers (the case we want to support!)
+// - [x] ExprKind::Index and ExprKind::Unary Deref; only need to handle coerce_index_op
+// - [x] overloaded_binops
+
+fn overloaded_call_traits() {
+    // Regarding overloaded call traits, note that there is no
+    // scenario where adding two-phase borrows should "fix" these
+    // cases, because either we will resolve both invocations to
+    // `call_mut` (in which case the inner call requires a mutable
+    // borrow which will conflict with the outer reservation), or we
+    // will resolve both to `call` (which will just work, regardless
+    // of two-phase borrow support), or we will resolve both to
+    // `call_once` (in which case the inner call requires moving the
+    // receiver, invalidating the outer call).
+
+    fn twice_ten_sm<F: FnMut(i32) -> i32>(f: &mut F) {
+        f(f(10));
+        //[nll]~^   ERROR cannot borrow `*f` as mutable more than once at a time
+        //[g2p]~^^ ERROR cannot borrow `*f` as mutable more than once at a time
+        //[ast]~^^^ ERROR cannot borrow `*f` as mutable more than once at a time
+    }
+    fn twice_ten_si<F: Fn(i32) -> i32>(f: &mut F) {
+        f(f(10));
+    }
+    fn twice_ten_so<F: FnOnce(i32) -> i32>(f: Box<F>) {
+        f(f(10));
+        //[nll]~^   ERROR use of moved value: `f`
+        //[g2p]~^^  ERROR use of moved value: `f`
+        //[ast]~^^^ ERROR use of moved value: `f`
+    }
+
+    fn twice_ten_om(f: &mut FnMut(i32) -> i32) {
+        f(f(10));
+        //[nll]~^   ERROR cannot borrow `*f` as mutable more than once at a time
+        //[g2p]~^^  ERROR cannot borrow `*f` as mutable more than once at a time
+        //[ast]~^^^ ERROR cannot borrow `*f` as mutable more than once at a time
+    }
+    fn twice_ten_oi(f: &mut Fn(i32) -> i32) {
+        f(f(10));
+    }
+    fn twice_ten_oo(f: Box<FnOnce(i32) -> i32>) {
+        f(f(10));
+        //[nll]~^   ERROR use of moved value: `f`
+        //[g2p]~^^  ERROR use of moved value: `f`
+        //[ast]~^^^ ERROR use of moved value: `f`
+    }
+
+    twice_ten_sm(&mut |x| x + 1);
+    twice_ten_si(&mut |x| x + 1);
+    twice_ten_so(Box::new(|x| x + 1));
+    twice_ten_om(&mut |x| x + 1);
+    twice_ten_oi(&mut |x| x + 1);
+    twice_ten_oo(Box::new(|x| x + 1));
+}
+
+trait TwoMethods {
+    fn m(&mut self, x: i32) -> i32 { x + 1 }
+    fn i(&self, x: i32) -> i32 { x + 1 }
+}
+
+struct T;
+
+impl TwoMethods for T { }
+
+struct S;
+
+impl S {
+    fn m(&mut self, x: i32) -> i32 { x + 1 }
+    fn i(&self, x: i32) -> i32 { x + 1 }
+}
+
+impl TwoMethods for [i32; 3] { }
+
+fn double_access<X: Copy>(m: &mut [X], s: &[X]) {
+    m[0] = s[1];
+}
+
+fn coerce_unsized() {
+    let mut a = [1, 2, 3];
+
+    // This is not okay.
+    double_access(&mut a, &a);
+    //[nll]~^   ERROR cannot borrow `a` as immutable because it is also borrowed as mutable [E0502]
+    //[g2p]~^^  ERROR cannot borrow `a` as immutable because it is also borrowed as mutable [E0502]
+    //[ast]~^^^ ERROR cannot borrow `a` as immutable because it is also borrowed as mutable [E0502]
+
+    // But this is okay.
+    a.m(a.i(10));
+    //[ast]~^ ERROR cannot borrow `a` as immutable because it is also borrowed as mutable [E0502]
+    // Above error is an expected limitation of AST borrowck
+}
+
+struct I(i32);
+
+impl Index<i32> for I {
+    type Output = i32;
+    fn index(&self, _: i32) -> &i32 {
+        &self.0
+    }
+}
+
+impl IndexMut<i32> for I {
+    fn index_mut(&mut self, _: i32) -> &mut i32 {
+        &mut self.0
+    }
+}
+
+fn coerce_index_op() {
+    let mut i = I(10);
+    i[i[3]] = 4;
+    //[nll]~^  ERROR cannot borrow `i` as immutable because it is also borrowed as mutable [E0502]
+    //[ast]~^^ ERROR cannot borrow `i` as immutable because it is also borrowed as mutable [E0502]
+
+    i[3] = i[4];
+
+    i[i[3]] = i[4];
+    //[nll]~^  ERROR cannot borrow `i` as immutable because it is also borrowed as mutable [E0502]
+    //[ast]~^^ ERROR cannot borrow `i` as immutable because it is also borrowed as mutable [E0502]
+}
+
+fn main() {
+
+    // As a reminder, this is the basic case we want to ensure we handle.
+    let mut v = vec![1, 2, 3];
+    v.push(v.len());
+    //[ast]~^ ERROR cannot borrow `v` as immutable because it is also borrowed as mutable [E0502]
+    // Error above is an expected limitation of AST borrowck
+
+    // (as a rule, pnkfelix does not like to write tests with dead code.)
+
+    deref_coercion(&mut 5);
+    overloaded_call_traits();
+
+
+    let mut s = S;
+    s.m(s.i(10));
+    //[ast]~^ ERROR cannot borrow `s` as immutable because it is also borrowed as mutable [E0502]
+    // Error above is an expected limitation of AST borrowck
+
+    let mut t = T;
+    t.m(t.i(10));
+    //[ast]~^ ERROR cannot borrow `t` as immutable because it is also borrowed as mutable [E0502]
+    // Error above is an expected limitation of AST borrowck
+
+    coerce_unsized();
+    coerce_index_op();
+}
diff --git a/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.ast.stderr b/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.ast.stderr
new file mode 100644
index 0000000..28c997e
--- /dev/null
+++ b/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.ast.stderr
@@ -0,0 +1,36 @@
+error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
+  --> $DIR/two-phase-reservation-sharing-interference-2.rs:19:5
+   |
+LL |     let shared = &v;
+   |                   - immutable borrow occurs here
+LL | 
+LL |     v.extend(shared);
+   |     ^ mutable borrow occurs here
+...
+LL | }
+   | - immutable borrow ends here
+
+error[E0502]: cannot borrow `v` as immutable because it is also borrowed as mutable
+  --> $DIR/two-phase-reservation-sharing-interference-2.rs:30:15
+   |
+LL |     v.extend(&v);
+   |     -         ^- mutable borrow ends here
+   |     |         |
+   |     |         immutable borrow occurs here
+   |     mutable borrow occurs here
+
+error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
+  --> $DIR/two-phase-reservation-sharing-interference-2.rs:42:5
+   |
+LL |     let shared = &v;
+   |                   - immutable borrow occurs here
+LL | 
+LL |     v.push(shared.len());
+   |     ^ mutable borrow occurs here
+...
+LL | }
+   | - immutable borrow ends here
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.migrate2015.stderr b/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.migrate2015.stderr
new file mode 100644
index 0000000..bb11b2e
--- /dev/null
+++ b/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.migrate2015.stderr
@@ -0,0 +1,40 @@
+error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
+  --> $DIR/two-phase-reservation-sharing-interference-2.rs:19:5
+   |
+LL |     let shared = &v;
+   |                  -- immutable borrow occurs here
+LL | 
+LL |     v.extend(shared);
+   |     ^^------^^^^^^^^
+   |     | |
+   |     | immutable borrow later used by call
+   |     mutable borrow occurs here
+
+error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
+  --> $DIR/two-phase-reservation-sharing-interference-2.rs:30:5
+   |
+LL |     v.extend(&v);
+   |     ^^------^--^
+   |     | |      |
+   |     | |      immutable borrow occurs here
+   |     | immutable borrow later used by call
+   |     mutable borrow occurs here
+
+warning: cannot borrow `v` as mutable because it is also borrowed as immutable
+  --> $DIR/two-phase-reservation-sharing-interference-2.rs:42:5
+   |
+LL |     let shared = &v;
+   |                  -- immutable borrow occurs here
+LL | 
+LL |     v.push(shared.len());
+   |     ^      ------ immutable borrow later used here
+   |     |
+   |     mutable borrow occurs here
+   |
+   = note: #[warn(mutable_borrow_reservation_conflict)] on by default
+   = warning: this borrowing pattern was not meant to be accepted, and may become a hard error in the future
+   = note: for more information, see issue #59159 <https://github.com/rust-lang/rust/issues/59159>
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.migrate2018.stderr b/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.migrate2018.stderr
new file mode 100644
index 0000000..bb11b2e
--- /dev/null
+++ b/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.migrate2018.stderr
@@ -0,0 +1,40 @@
+error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
+  --> $DIR/two-phase-reservation-sharing-interference-2.rs:19:5
+   |
+LL |     let shared = &v;
+   |                  -- immutable borrow occurs here
+LL | 
+LL |     v.extend(shared);
+   |     ^^------^^^^^^^^
+   |     | |
+   |     | immutable borrow later used by call
+   |     mutable borrow occurs here
+
+error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
+  --> $DIR/two-phase-reservation-sharing-interference-2.rs:30:5
+   |
+LL |     v.extend(&v);
+   |     ^^------^--^
+   |     | |      |
+   |     | |      immutable borrow occurs here
+   |     | immutable borrow later used by call
+   |     mutable borrow occurs here
+
+warning: cannot borrow `v` as mutable because it is also borrowed as immutable
+  --> $DIR/two-phase-reservation-sharing-interference-2.rs:42:5
+   |
+LL |     let shared = &v;
+   |                  -- immutable borrow occurs here
+LL | 
+LL |     v.push(shared.len());
+   |     ^      ------ immutable borrow later used here
+   |     |
+   |     mutable borrow occurs here
+   |
+   = note: #[warn(mutable_borrow_reservation_conflict)] on by default
+   = warning: this borrowing pattern was not meant to be accepted, and may become a hard error in the future
+   = note: for more information, see issue #59159 <https://github.com/rust-lang/rust/issues/59159>
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.nll2015.stderr b/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.nll2015.stderr
new file mode 100644
index 0000000..fb3a1fd
--- /dev/null
+++ b/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.nll2015.stderr
@@ -0,0 +1,35 @@
+error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
+  --> $DIR/two-phase-reservation-sharing-interference-2.rs:19:5
+   |
+LL |     let shared = &v;
+   |                  -- immutable borrow occurs here
+LL | 
+LL |     v.extend(shared);
+   |     ^        ------ immutable borrow later used here
+   |     |
+   |     mutable borrow occurs here
+
+error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
+  --> $DIR/two-phase-reservation-sharing-interference-2.rs:30:5
+   |
+LL |     v.extend(&v);
+   |     ^^------^--^
+   |     | |      |
+   |     | |      immutable borrow occurs here
+   |     | immutable borrow later used by call
+   |     mutable borrow occurs here
+
+error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
+  --> $DIR/two-phase-reservation-sharing-interference-2.rs:42:5
+   |
+LL |     let shared = &v;
+   |                  -- immutable borrow occurs here
+LL | 
+LL |     v.push(shared.len());
+   |     ^      ------ immutable borrow later used here
+   |     |
+   |     mutable borrow occurs here
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.nll2018.stderr b/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.nll2018.stderr
new file mode 100644
index 0000000..fb3a1fd
--- /dev/null
+++ b/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.nll2018.stderr
@@ -0,0 +1,35 @@
+error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
+  --> $DIR/two-phase-reservation-sharing-interference-2.rs:19:5
+   |
+LL |     let shared = &v;
+   |                  -- immutable borrow occurs here
+LL | 
+LL |     v.extend(shared);
+   |     ^        ------ immutable borrow later used here
+   |     |
+   |     mutable borrow occurs here
+
+error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
+  --> $DIR/two-phase-reservation-sharing-interference-2.rs:30:5
+   |
+LL |     v.extend(&v);
+   |     ^^------^--^
+   |     | |      |
+   |     | |      immutable borrow occurs here
+   |     | immutable borrow later used by call
+   |     mutable borrow occurs here
+
+error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
+  --> $DIR/two-phase-reservation-sharing-interference-2.rs:42:5
+   |
+LL |     let shared = &v;
+   |                  -- immutable borrow occurs here
+LL | 
+LL |     v.push(shared.len());
+   |     ^      ------ immutable borrow later used here
+   |     |
+   |     mutable borrow occurs here
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.rs b/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.rs
new file mode 100644
index 0000000..54fad9f
--- /dev/null
+++ b/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.rs
@@ -0,0 +1,54 @@
+// Test for #56254, we previously allowed the last example on the 2018
+// editiion. Make sure that we now emit a warning in that case and an error for
+// everyone else.
+
+//ignore-compare-mode-nll
+
+//revisions: ast migrate2015 migrate2018 nll2015 nll2018
+
+//[migrate2015] compile-flags: -Zborrowck=migrate -Ztwo-phase-borrows
+//[migrate2018] edition:2018
+//[nll2018] edition:2018
+
+#![cfg_attr(any(nll2015, nll2018), feature(nll))]
+
+fn double_conflicts() {
+    let mut v = vec![0, 1, 2];
+    let shared = &v;
+
+    v.extend(shared);
+    //[migrate2015]~^ ERROR cannot borrow `v` as mutable
+    //[nll2015]~^^ ERROR cannot borrow `v` as mutable
+    //[migrate2018]~^^^ ERROR cannot borrow `v` as mutable
+    //[nll2018]~^^^^ ERROR cannot borrow `v` as mutable
+    //[ast]~^^^^^ ERROR cannot borrow `v` as mutable
+}
+
+fn activation_conflict() {
+    let mut v = vec![0, 1, 2];
+
+    v.extend(&v);
+    //[migrate2015]~^ ERROR cannot borrow `v` as mutable
+    //[nll2015]~^^ ERROR cannot borrow `v` as mutable
+    //[migrate2018]~^^^ ERROR cannot borrow `v` as mutable
+    //[nll2018]~^^^^ ERROR cannot borrow `v` as mutable
+    //[ast]~^^^^^ ERROR cannot borrow `v` as immutable
+}
+
+fn reservation_conflict() {
+    let mut v = vec![0, 1, 2];
+    let shared = &v;
+
+    v.push(shared.len());
+    //[nll2015]~^ ERROR cannot borrow `v` as mutable
+    //[nll2018]~^^ ERROR cannot borrow `v` as mutable
+    //[migrate2015]~^^^ WARNING cannot borrow `v` as mutable
+    //[migrate2015]~| WARNING may become a hard error in the future
+
+    //[migrate2018]~^^^^^^ WARNING cannot borrow `v` as mutable
+    //[migrate2018]~| WARNING may become a hard error in the future
+
+    //[ast]~^^^^^^^^^ ERROR cannot borrow `v` as mutable
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/two-phase-reservation-sharing-interference-future-compat-lint.rs b/src/test/ui/borrowck/two-phase-reservation-sharing-interference-future-compat-lint.rs
new file mode 100644
index 0000000..0e1d77a
--- /dev/null
+++ b/src/test/ui/borrowck/two-phase-reservation-sharing-interference-future-compat-lint.rs
@@ -0,0 +1,43 @@
+// Check that the future-compat-lint for the reservation conflict is
+// handled like any other lint.
+
+// edition:2018
+
+mod future_compat_allow {
+    #![allow(mutable_borrow_reservation_conflict)]
+
+    fn reservation_conflict() {
+        let mut v = vec![0, 1, 2];
+        let shared = &v;
+
+        v.push(shared.len());
+    }
+}
+
+mod future_compat_warn {
+    #![warn(mutable_borrow_reservation_conflict)]
+
+    fn reservation_conflict() {
+        let mut v = vec![0, 1, 2];
+        let shared = &v;
+
+        v.push(shared.len());
+        //~^ WARNING cannot borrow `v` as mutable
+        //~| WARNING may become a hard error in the future
+    }
+}
+
+mod future_compat_deny {
+    #![deny(mutable_borrow_reservation_conflict)]
+
+    fn reservation_conflict() {
+        let mut v = vec![0, 1, 2];
+        let shared = &v;
+
+        v.push(shared.len());
+        //~^ ERROR cannot borrow `v` as mutable
+        //~| WARNING may become a hard error in the future
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/two-phase-reservation-sharing-interference-future-compat-lint.stderr b/src/test/ui/borrowck/two-phase-reservation-sharing-interference-future-compat-lint.stderr
new file mode 100644
index 0000000..77fbfb37
--- /dev/null
+++ b/src/test/ui/borrowck/two-phase-reservation-sharing-interference-future-compat-lint.stderr
@@ -0,0 +1,40 @@
+warning: cannot borrow `v` as mutable because it is also borrowed as immutable
+  --> $DIR/two-phase-reservation-sharing-interference-future-compat-lint.rs:24:9
+   |
+LL |         let shared = &v;
+   |                      -- immutable borrow occurs here
+LL | 
+LL |         v.push(shared.len());
+   |         ^      ------ immutable borrow later used here
+   |         |
+   |         mutable borrow occurs here
+   |
+note: lint level defined here
+  --> $DIR/two-phase-reservation-sharing-interference-future-compat-lint.rs:18:13
+   |
+LL |     #![warn(mutable_borrow_reservation_conflict)]
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = warning: this borrowing pattern was not meant to be accepted, and may become a hard error in the future
+   = note: for more information, see issue #59159 <https://github.com/rust-lang/rust/issues/59159>
+
+error: cannot borrow `v` as mutable because it is also borrowed as immutable
+  --> $DIR/two-phase-reservation-sharing-interference-future-compat-lint.rs:37:9
+   |
+LL |         let shared = &v;
+   |                      -- immutable borrow occurs here
+LL | 
+LL |         v.push(shared.len());
+   |         ^      ------ immutable borrow later used here
+   |         |
+   |         mutable borrow occurs here
+   |
+note: lint level defined here
+  --> $DIR/two-phase-reservation-sharing-interference-future-compat-lint.rs:31:13
+   |
+LL |     #![deny(mutable_borrow_reservation_conflict)]
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = warning: this borrowing pattern was not meant to be accepted, and may become a hard error in the future
+   = note: for more information, see issue #59159 <https://github.com/rust-lang/rust/issues/59159>
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/borrowck/two-phase-reservation-sharing-interference.nll_target.stderr b/src/test/ui/borrowck/two-phase-reservation-sharing-interference.nll_target.stderr
new file mode 100644
index 0000000..7b64d9d
--- /dev/null
+++ b/src/test/ui/borrowck/two-phase-reservation-sharing-interference.nll_target.stderr
@@ -0,0 +1,15 @@
+error[E0502]: cannot borrow `vec` as mutable because it is also borrowed as immutable
+  --> $DIR/two-phase-reservation-sharing-interference.rs:36:17
+   |
+LL |         let shared = &vec;
+   |                      ---- immutable borrow occurs here
+...
+LL |         delay = &mut vec;
+   |                 ^^^^^^^^ mutable borrow occurs here
+...
+LL |         shared[0];
+   |         ------ immutable borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/borrowck/two-phase-reservation-sharing-interference.rs b/src/test/ui/borrowck/two-phase-reservation-sharing-interference.rs
new file mode 100644
index 0000000..f5fa821
--- /dev/null
+++ b/src/test/ui/borrowck/two-phase-reservation-sharing-interference.rs
@@ -0,0 +1,50 @@
+// ignore-tidy-linelength
+
+// revisions: nll_target
+
+// The following revisions are disabled due to missing support from two-phase beyond autorefs
+//[nll_beyond]compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z two-phase-beyond-autoref
+//[nll_beyond] should-fail
+
+//[nll_target]compile-flags: -Z borrowck=mir -Z two-phase-borrows
+
+// This is a corner case that the current implementation is (probably)
+// treating more conservatively than is necessary. But it also does
+// not seem like a terribly important use case to cover.
+//
+// So this test is just making a note of the current behavior, with
+// the caveat that in the future, the rules may be loosened, at which
+// point this test might be thrown out.
+//
+// The convention for the listed revisions: "lxl" means lexical
+// lifetimes (which can be easier to reason about). "nll" means
+// non-lexical lifetimes. "nll_target" means the initial conservative
+// two-phase borrows that only applies to autoref-introduced borrows.
+// "nll_beyond" means the generalization of two-phase borrows to all
+// `&mut`-borrows (doing so makes it easier to write code for specific
+// corner cases).
+
+fn main() {
+    let mut vec = vec![0, 1];
+    let delay: &mut Vec<_>;
+    {
+        let shared = &vec;
+
+        // we reserve here, which could (on its own) be compatible
+        // with the shared borrow. But in the current implementation,
+        // its an error.
+        delay = &mut vec;
+        //[nll_beyond]~^  ERROR cannot borrow `vec` as mutable because it is also borrowed as immutable
+        //[nll_target]~^^ ERROR cannot borrow `vec` as mutable because it is also borrowed as immutable
+
+        shared[0];
+    }
+
+    // the &mut-borrow only becomes active way down here.
+    //
+    // (At least in theory; part of the reason this test fails is that
+    // the constructed MIR throws in extra &mut reborrows which
+    // flummoxes our attmpt to delay the activation point here.)
+    delay.push(2);
+}
+
diff --git a/src/test/ui/borrowck/two-phase-sneaky.nll.stderr b/src/test/ui/borrowck/two-phase-sneaky.nll.stderr
new file mode 100644
index 0000000..c66f3cb
--- /dev/null
+++ b/src/test/ui/borrowck/two-phase-sneaky.nll.stderr
@@ -0,0 +1,14 @@
+error[E0499]: cannot borrow `v` as mutable more than once at a time
+  --> $DIR/two-phase-sneaky.rs:12:9
+   |
+LL |     v[0].push_str({
+   |     -    -------- first borrow later used by call
+   |     |
+   |     first mutable borrow occurs here
+LL | 
+LL |         v.push(format!("foo"));
+   |         ^ second mutable borrow occurs here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/borrowck/two-phase-sneaky.rs b/src/test/ui/borrowck/two-phase-sneaky.rs
new file mode 100644
index 0000000..abfa13d
--- /dev/null
+++ b/src/test/ui/borrowck/two-phase-sneaky.rs
@@ -0,0 +1,17 @@
+// cmpile-flags: -Z borrowck=mir -Z two-phase-borrows
+
+// This is the first counter-example from Niko's blog post
+// smallcultfollowing.com/babysteps/blog/2017/03/01/nested-method-calls-via-two-phase-borrowing/
+// of a danger for code to crash if we just turned off the check for whether
+// a mutable-borrow aliases another borrow.
+
+fn main() {
+    let mut v: Vec<String> = vec![format!("Hello, ")];
+    v[0].push_str({
+
+        v.push(format!("foo"));
+        //~^   ERROR cannot borrow `v` as mutable more than once at a time [E0499]
+
+        "World!"
+    });
+}
diff --git a/src/test/ui/borrowck/two-phase-sneaky.stderr b/src/test/ui/borrowck/two-phase-sneaky.stderr
new file mode 100644
index 0000000..38f24cc
--- /dev/null
+++ b/src/test/ui/borrowck/two-phase-sneaky.stderr
@@ -0,0 +1,15 @@
+error[E0499]: cannot borrow `v` as mutable more than once at a time
+  --> $DIR/two-phase-sneaky.rs:12:9
+   |
+LL |     v[0].push_str({
+   |     - first mutable borrow occurs here
+LL | 
+LL |         v.push(format!("foo"));
+   |         ^ second mutable borrow occurs here
+...
+LL |     });
+   |      - first borrow ends here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/borrowck/two-phase-surprise-no-conflict.ast.stderr b/src/test/ui/borrowck/two-phase-surprise-no-conflict.ast.stderr
new file mode 100644
index 0000000..a2e5c7e
--- /dev/null
+++ b/src/test/ui/borrowck/two-phase-surprise-no-conflict.ast.stderr
@@ -0,0 +1,133 @@
+error[E0503]: cannot use `self.cx` because it was mutably borrowed
+  --> $DIR/two-phase-surprise-no-conflict.rs:30:13
+   |
+LL |         let _mut_borrow = &mut *self;
+   |                                ----- borrow of `*self` occurs here
+LL |         let _access = self.cx;
+   |             ^^^^^^^ use of borrowed `*self`
+
+error[E0502]: cannot borrow `*self.cx_mut` as immutable because `*self` is also borrowed as mutable
+  --> $DIR/two-phase-surprise-no-conflict.rs:69:33
+   |
+LL |                 self.hash_expr(&self.cx_mut.body(eid).value);
+   |                 ----            ^^^^^^^^^^^                - mutable borrow ends here
+   |                 |               |
+   |                 |               immutable borrow occurs here
+   |                 mutable borrow occurs here
+
+error[E0502]: cannot borrow `reg.sess_mut` as immutable because `*reg` is also borrowed as mutable
+  --> $DIR/two-phase-surprise-no-conflict.rs:121:52
+   |
+LL |     reg.register_static(Box::new(TrivialPass::new(&reg.sess_mut)));
+   |     ---                                            ^^^^^^^^^^^^  - mutable borrow ends here
+   |     |                                              |
+   |     mutable borrow occurs here                     immutable borrow occurs here
+
+error[E0502]: cannot borrow `reg.sess_mut` as immutable because `*reg` is also borrowed as mutable
+  --> $DIR/two-phase-surprise-no-conflict.rs:125:51
+   |
+LL |     reg.register_bound(Box::new(TrivialPass::new(&reg.sess_mut)));
+   |     ---                                           ^^^^^^^^^^^^  - mutable borrow ends here
+   |     |                                             |
+   |     mutable borrow occurs here                    immutable borrow occurs here
+
+error[E0502]: cannot borrow `reg.sess_mut` as immutable because `*reg` is also borrowed as mutable
+  --> $DIR/two-phase-surprise-no-conflict.rs:129:50
+   |
+LL |     reg.register_univ(Box::new(TrivialPass::new(&reg.sess_mut)));
+   |     ---                                          ^^^^^^^^^^^^  - mutable borrow ends here
+   |     |                                            |
+   |     mutable borrow occurs here                   immutable borrow occurs here
+
+error[E0502]: cannot borrow `reg.sess_mut` as immutable because `*reg` is also borrowed as mutable
+  --> $DIR/two-phase-surprise-no-conflict.rs:133:41
+   |
+LL |     reg.register_ref(&TrivialPass::new(&reg.sess_mut));
+   |     ---                                 ^^^^^^^^^^^^ - mutable borrow ends here
+   |     |                                   |
+   |     mutable borrow occurs here          immutable borrow occurs here
+
+error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time
+  --> $DIR/two-phase-surprise-no-conflict.rs:141:56
+   |
+LL |     reg.register_static(Box::new(TrivialPass::new(&mut reg.sess_mut)));
+   |     ---                                                ^^^^^^^^^^^^  - first borrow ends here
+   |     |                                                  |
+   |     first mutable borrow occurs here                   second mutable borrow occurs here
+
+error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time
+  --> $DIR/two-phase-surprise-no-conflict.rs:146:59
+   |
+LL |     reg.register_bound(Box::new(TrivialPass::new_mut(&mut reg.sess_mut)));
+   |     ---                                                   ^^^^^^^^^^^^  - first borrow ends here
+   |     |                                                     |
+   |     first mutable borrow occurs here                      second mutable borrow occurs here
+
+error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time
+  --> $DIR/two-phase-surprise-no-conflict.rs:151:58
+   |
+LL |     reg.register_univ(Box::new(TrivialPass::new_mut(&mut reg.sess_mut)));
+   |     ---                                                  ^^^^^^^^^^^^  - first borrow ends here
+   |     |                                                    |
+   |     first mutable borrow occurs here                     second mutable borrow occurs here
+
+error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time
+  --> $DIR/two-phase-surprise-no-conflict.rs:156:49
+   |
+LL |     reg.register_ref(&TrivialPass::new_mut(&mut reg.sess_mut));
+   |     ---                                         ^^^^^^^^^^^^ - first borrow ends here
+   |     |                                           |
+   |     first mutable borrow occurs here            second mutable borrow occurs here
+
+error[E0502]: cannot borrow `reg.sess_mut` as immutable because `*reg` is also borrowed as mutable
+  --> $DIR/two-phase-surprise-no-conflict.rs:168:51
+   |
+LL |     reg.register_bound(Box::new(CapturePass::new(&reg.sess_mut)));
+   |     ---                                           ^^^^^^^^^^^^  - mutable borrow ends here
+   |     |                                             |
+   |     mutable borrow occurs here                    immutable borrow occurs here
+
+error[E0502]: cannot borrow `reg.sess_mut` as immutable because `*reg` is also borrowed as mutable
+  --> $DIR/two-phase-surprise-no-conflict.rs:173:50
+   |
+LL |     reg.register_univ(Box::new(CapturePass::new(&reg.sess_mut)));
+   |     ---                                          ^^^^^^^^^^^^  - mutable borrow ends here
+   |     |                                            |
+   |     mutable borrow occurs here                   immutable borrow occurs here
+
+error[E0502]: cannot borrow `reg.sess_mut` as immutable because `*reg` is also borrowed as mutable
+  --> $DIR/two-phase-surprise-no-conflict.rs:178:41
+   |
+LL |     reg.register_ref(&CapturePass::new(&reg.sess_mut));
+   |     ---                                 ^^^^^^^^^^^^ - mutable borrow ends here
+   |     |                                   |
+   |     mutable borrow occurs here          immutable borrow occurs here
+
+error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time
+  --> $DIR/two-phase-surprise-no-conflict.rs:190:59
+   |
+LL |     reg.register_bound(Box::new(CapturePass::new_mut(&mut reg.sess_mut)));
+   |     ---                                                   ^^^^^^^^^^^^  - first borrow ends here
+   |     |                                                     |
+   |     first mutable borrow occurs here                      second mutable borrow occurs here
+
+error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time
+  --> $DIR/two-phase-surprise-no-conflict.rs:196:58
+   |
+LL |     reg.register_univ(Box::new(CapturePass::new_mut(&mut reg.sess_mut)));
+   |     ---                                                  ^^^^^^^^^^^^  - first borrow ends here
+   |     |                                                    |
+   |     first mutable borrow occurs here                     second mutable borrow occurs here
+
+error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time
+  --> $DIR/two-phase-surprise-no-conflict.rs:202:49
+   |
+LL |     reg.register_ref(&CapturePass::new_mut(&mut reg.sess_mut));
+   |     ---                                         ^^^^^^^^^^^^ - first borrow ends here
+   |     |                                           |
+   |     first mutable borrow occurs here            second mutable borrow occurs here
+
+error: aborting due to 16 previous errors
+
+Some errors occurred: E0499, E0502, E0503.
+For more information about an error, try `rustc --explain E0499`.
diff --git a/src/test/ui/borrowck/two-phase-surprise-no-conflict.nll.stderr b/src/test/ui/borrowck/two-phase-surprise-no-conflict.nll.stderr
new file mode 100644
index 0000000..1ac3a69
--- /dev/null
+++ b/src/test/ui/borrowck/two-phase-surprise-no-conflict.nll.stderr
@@ -0,0 +1,154 @@
+error[E0503]: cannot use `self.cx` because it was mutably borrowed
+  --> $DIR/two-phase-surprise-no-conflict.rs:30:23
+   |
+LL |         let _mut_borrow = &mut *self;
+   |                           ---------- borrow of `*self` occurs here
+LL |         let _access = self.cx;
+   |                       ^^^^^^^ use of borrowed `*self`
+...
+LL |         _mut_borrow;
+   |         ----------- borrow later used here
+
+error[E0502]: cannot borrow `*self` as mutable because it is also borrowed as immutable
+  --> $DIR/two-phase-surprise-no-conflict.rs:69:17
+   |
+LL |                 self.hash_expr(&self.cx_mut.body(eid).value);
+   |                 ^^^^^---------^^-----------^^^^^^^^^^^^^^^^^
+   |                 |    |          |
+   |                 |    |          immutable borrow occurs here
+   |                 |    immutable borrow later used by call
+   |                 mutable borrow occurs here
+
+error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time
+  --> $DIR/two-phase-surprise-no-conflict.rs:141:51
+   |
+LL |     reg.register_static(Box::new(TrivialPass::new(&mut reg.sess_mut)));
+   |     --- ---------------                           ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
+   |     |   |
+   |     |   first borrow later used by call
+   |     first mutable borrow occurs here
+
+error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time
+  --> $DIR/two-phase-surprise-no-conflict.rs:146:54
+   |
+LL |     reg.register_bound(Box::new(TrivialPass::new_mut(&mut reg.sess_mut)));
+   |     --- --------------                               ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
+   |     |   |
+   |     |   first borrow later used by call
+   |     first mutable borrow occurs here
+
+error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time
+  --> $DIR/two-phase-surprise-no-conflict.rs:151:53
+   |
+LL |     reg.register_univ(Box::new(TrivialPass::new_mut(&mut reg.sess_mut)));
+   |     --- -------------                               ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
+   |     |   |
+   |     |   first borrow later used by call
+   |     first mutable borrow occurs here
+
+error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time
+  --> $DIR/two-phase-surprise-no-conflict.rs:156:44
+   |
+LL |     reg.register_ref(&TrivialPass::new_mut(&mut reg.sess_mut));
+   |     --- ------------                       ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
+   |     |   |
+   |     |   first borrow later used by call
+   |     first mutable borrow occurs here
+
+error[E0502]: cannot borrow `*reg` as mutable because it is also borrowed as immutable
+  --> $DIR/two-phase-surprise-no-conflict.rs:168:5
+   |
+LL |     reg.register_bound(Box::new(CapturePass::new(&reg.sess_mut)));
+   |     ^^^^--------------^^^^^^^^^^^^^^^^^^^^^^^^^^^-------------^^^
+   |     |   |                                        |
+   |     |   |                                        immutable borrow occurs here
+   |     |   immutable borrow later used by call
+   |     mutable borrow occurs here
+
+error[E0502]: cannot borrow `*reg` as mutable because it is also borrowed as immutable
+  --> $DIR/two-phase-surprise-no-conflict.rs:173:5
+   |
+LL | fn register_plugins<'a>(mk_reg: impl Fn() -> &'a mut Registry<'a>) {
+   |                     -- lifetime `'a` defined here
+...
+LL |     reg.register_univ(Box::new(CapturePass::new(&reg.sess_mut)));
+   |     ^^^^^^^^^^^^^^^^^^-----------------------------------------^
+   |     |                 |                         |
+   |     |                 |                         immutable borrow occurs here
+   |     |                 cast requires that `reg.sess_mut` is borrowed for `'a`
+   |     mutable borrow occurs here
+
+error[E0502]: cannot borrow `*reg` as mutable because it is also borrowed as immutable
+  --> $DIR/two-phase-surprise-no-conflict.rs:178:5
+   |
+LL |     reg.register_ref(&CapturePass::new(&reg.sess_mut));
+   |     ^^^^------------^^^^^^^^^^^^^^^^^^^-------------^^
+   |     |   |                              |
+   |     |   |                              immutable borrow occurs here
+   |     |   immutable borrow later used by call
+   |     mutable borrow occurs here
+
+error[E0499]: cannot borrow `*reg` as mutable more than once at a time
+  --> $DIR/two-phase-surprise-no-conflict.rs:190:5
+   |
+LL |     reg.register_bound(Box::new(CapturePass::new_mut(&mut reg.sess_mut)));
+   |     ^^^^--------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------------^^^
+   |     |   |                                            |
+   |     |   |                                            first mutable borrow occurs here
+   |     |   first borrow later used by call
+   |     second mutable borrow occurs here
+
+error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time
+  --> $DIR/two-phase-surprise-no-conflict.rs:190:54
+   |
+LL |     reg.register_bound(Box::new(CapturePass::new_mut(&mut reg.sess_mut)));
+   |     --- --------------                               ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
+   |     |   |
+   |     |   first borrow later used by call
+   |     first mutable borrow occurs here
+
+error[E0499]: cannot borrow `*reg` as mutable more than once at a time
+  --> $DIR/two-phase-surprise-no-conflict.rs:196:5
+   |
+LL | fn register_plugins<'a>(mk_reg: impl Fn() -> &'a mut Registry<'a>) {
+   |                     -- lifetime `'a` defined here
+...
+LL |     reg.register_univ(Box::new(CapturePass::new_mut(&mut reg.sess_mut)));
+   |     ^^^^^^^^^^^^^^^^^^-------------------------------------------------^
+   |     |                 |                             |
+   |     |                 |                             first mutable borrow occurs here
+   |     |                 cast requires that `reg.sess_mut` is borrowed for `'a`
+   |     second mutable borrow occurs here
+
+error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time
+  --> $DIR/two-phase-surprise-no-conflict.rs:196:53
+   |
+LL |     reg.register_univ(Box::new(CapturePass::new_mut(&mut reg.sess_mut)));
+   |     --- -------------                               ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
+   |     |   |
+   |     |   first borrow later used by call
+   |     first mutable borrow occurs here
+
+error[E0499]: cannot borrow `*reg` as mutable more than once at a time
+  --> $DIR/two-phase-surprise-no-conflict.rs:202:5
+   |
+LL |     reg.register_ref(&CapturePass::new_mut(&mut reg.sess_mut));
+   |     ^^^^------------^^^^^^^^^^^^^^^^^^^^^^^-----------------^^
+   |     |   |                                  |
+   |     |   |                                  first mutable borrow occurs here
+   |     |   first borrow later used by call
+   |     second mutable borrow occurs here
+
+error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time
+  --> $DIR/two-phase-surprise-no-conflict.rs:202:44
+   |
+LL |     reg.register_ref(&CapturePass::new_mut(&mut reg.sess_mut));
+   |     --- ------------                       ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
+   |     |   |
+   |     |   first borrow later used by call
+   |     first mutable borrow occurs here
+
+error: aborting due to 15 previous errors
+
+Some errors occurred: E0499, E0502, E0503.
+For more information about an error, try `rustc --explain E0499`.
diff --git a/src/test/ui/borrowck/two-phase-surprise-no-conflict.no2pb.stderr b/src/test/ui/borrowck/two-phase-surprise-no-conflict.no2pb.stderr
new file mode 100644
index 0000000..9b46567
--- /dev/null
+++ b/src/test/ui/borrowck/two-phase-surprise-no-conflict.no2pb.stderr
@@ -0,0 +1,159 @@
+error[E0503]: cannot use `self.cx` because it was mutably borrowed
+  --> $DIR/two-phase-surprise-no-conflict.rs:30:23
+   |
+LL |         let _mut_borrow = &mut *self;
+   |                           ---------- borrow of `*self` occurs here
+LL |         let _access = self.cx;
+   |                       ^^^^^^^ use of borrowed `*self`
+...
+LL |         _mut_borrow;
+   |         ----------- borrow later used here
+
+error[E0502]: cannot borrow `*self.cx` as immutable because it is also borrowed as mutable
+  --> $DIR/two-phase-surprise-no-conflict.rs:54:33
+   |
+LL |                 self.hash_expr(&self.cx.body(eid).value);
+   |                 ---- ---------  ^^^^^^^ immutable borrow occurs here
+   |                 |    |
+   |                 |    mutable borrow later used by call
+   |                 mutable borrow occurs here
+
+error[E0502]: cannot borrow `*self.cx_mut` as immutable because it is also borrowed as mutable
+  --> $DIR/two-phase-surprise-no-conflict.rs:69:33
+   |
+LL |                 self.hash_expr(&self.cx_mut.body(eid).value);
+   |                 ---- ---------  ^^^^^^^^^^^ immutable borrow occurs here
+   |                 |    |
+   |                 |    mutable borrow later used by call
+   |                 mutable borrow occurs here
+
+error[E0502]: cannot borrow `reg.sess_mut` as immutable because it is also borrowed as mutable
+  --> $DIR/two-phase-surprise-no-conflict.rs:121:51
+   |
+LL |     reg.register_static(Box::new(TrivialPass::new(&reg.sess_mut)));
+   |     --- ---------------                           ^^^^^^^^^^^^^ immutable borrow occurs here
+   |     |   |
+   |     |   mutable borrow later used by call
+   |     mutable borrow occurs here
+
+error[E0502]: cannot borrow `reg.sess_mut` as immutable because it is also borrowed as mutable
+  --> $DIR/two-phase-surprise-no-conflict.rs:125:50
+   |
+LL |     reg.register_bound(Box::new(TrivialPass::new(&reg.sess_mut)));
+   |     --- --------------                           ^^^^^^^^^^^^^ immutable borrow occurs here
+   |     |   |
+   |     |   mutable borrow later used by call
+   |     mutable borrow occurs here
+
+error[E0502]: cannot borrow `reg.sess_mut` as immutable because it is also borrowed as mutable
+  --> $DIR/two-phase-surprise-no-conflict.rs:129:49
+   |
+LL |     reg.register_univ(Box::new(TrivialPass::new(&reg.sess_mut)));
+   |     --- -------------                           ^^^^^^^^^^^^^ immutable borrow occurs here
+   |     |   |
+   |     |   mutable borrow later used by call
+   |     mutable borrow occurs here
+
+error[E0502]: cannot borrow `reg.sess_mut` as immutable because it is also borrowed as mutable
+  --> $DIR/two-phase-surprise-no-conflict.rs:133:40
+   |
+LL |     reg.register_ref(&TrivialPass::new(&reg.sess_mut));
+   |     --- ------------                   ^^^^^^^^^^^^^ immutable borrow occurs here
+   |     |   |
+   |     |   mutable borrow later used by call
+   |     mutable borrow occurs here
+
+error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time
+  --> $DIR/two-phase-surprise-no-conflict.rs:141:51
+   |
+LL |     reg.register_static(Box::new(TrivialPass::new(&mut reg.sess_mut)));
+   |     --- ---------------                           ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
+   |     |   |
+   |     |   first borrow later used by call
+   |     first mutable borrow occurs here
+
+error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time
+  --> $DIR/two-phase-surprise-no-conflict.rs:146:54
+   |
+LL |     reg.register_bound(Box::new(TrivialPass::new_mut(&mut reg.sess_mut)));
+   |     --- --------------                               ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
+   |     |   |
+   |     |   first borrow later used by call
+   |     first mutable borrow occurs here
+
+error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time
+  --> $DIR/two-phase-surprise-no-conflict.rs:151:53
+   |
+LL |     reg.register_univ(Box::new(TrivialPass::new_mut(&mut reg.sess_mut)));
+   |     --- -------------                               ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
+   |     |   |
+   |     |   first borrow later used by call
+   |     first mutable borrow occurs here
+
+error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time
+  --> $DIR/two-phase-surprise-no-conflict.rs:156:44
+   |
+LL |     reg.register_ref(&TrivialPass::new_mut(&mut reg.sess_mut));
+   |     --- ------------                       ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
+   |     |   |
+   |     |   first borrow later used by call
+   |     first mutable borrow occurs here
+
+error[E0502]: cannot borrow `reg.sess_mut` as immutable because it is also borrowed as mutable
+  --> $DIR/two-phase-surprise-no-conflict.rs:168:50
+   |
+LL |     reg.register_bound(Box::new(CapturePass::new(&reg.sess_mut)));
+   |     --- --------------                           ^^^^^^^^^^^^^ immutable borrow occurs here
+   |     |   |
+   |     |   mutable borrow later used by call
+   |     mutable borrow occurs here
+
+error[E0502]: cannot borrow `reg.sess_mut` as immutable because it is also borrowed as mutable
+  --> $DIR/two-phase-surprise-no-conflict.rs:173:49
+   |
+LL |     reg.register_univ(Box::new(CapturePass::new(&reg.sess_mut)));
+   |     --- -------------                           ^^^^^^^^^^^^^ immutable borrow occurs here
+   |     |   |
+   |     |   mutable borrow later used by call
+   |     mutable borrow occurs here
+
+error[E0502]: cannot borrow `reg.sess_mut` as immutable because it is also borrowed as mutable
+  --> $DIR/two-phase-surprise-no-conflict.rs:178:40
+   |
+LL |     reg.register_ref(&CapturePass::new(&reg.sess_mut));
+   |     --- ------------                   ^^^^^^^^^^^^^ immutable borrow occurs here
+   |     |   |
+   |     |   mutable borrow later used by call
+   |     mutable borrow occurs here
+
+error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time
+  --> $DIR/two-phase-surprise-no-conflict.rs:190:54
+   |
+LL |     reg.register_bound(Box::new(CapturePass::new_mut(&mut reg.sess_mut)));
+   |     --- --------------                               ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
+   |     |   |
+   |     |   first borrow later used by call
+   |     first mutable borrow occurs here
+
+error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time
+  --> $DIR/two-phase-surprise-no-conflict.rs:196:53
+   |
+LL |     reg.register_univ(Box::new(CapturePass::new_mut(&mut reg.sess_mut)));
+   |     --- -------------                               ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
+   |     |   |
+   |     |   first borrow later used by call
+   |     first mutable borrow occurs here
+
+error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time
+  --> $DIR/two-phase-surprise-no-conflict.rs:202:44
+   |
+LL |     reg.register_ref(&CapturePass::new_mut(&mut reg.sess_mut));
+   |     --- ------------                       ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
+   |     |   |
+   |     |   first borrow later used by call
+   |     first mutable borrow occurs here
+
+error: aborting due to 17 previous errors
+
+Some errors occurred: E0499, E0502, E0503.
+For more information about an error, try `rustc --explain E0499`.
diff --git a/src/test/ui/borrowck/two-phase-surprise-no-conflict.rs b/src/test/ui/borrowck/two-phase-surprise-no-conflict.rs
new file mode 100644
index 0000000..f097def
--- /dev/null
+++ b/src/test/ui/borrowck/two-phase-surprise-no-conflict.rs
@@ -0,0 +1,209 @@
+// This is a test adapted from a minimization of the code from
+// rust-lang/rust#52934, where an accidental disabling of
+// two-phase-borrows (in the initial 2018 edition integration) broke
+// Clippy, but the scenarios where it was breaking were subtle enough
+// that we decided it warranted its own unit test, and pnkfelix
+// decided to use that test as an opportunity to illustrate the cases.
+
+// revisions: ast no2pb nll
+//[ast]compile-flags: -Z borrowck=ast
+//[no2pb]compile-flags: -Z borrowck=mir
+//[nll]compile-flags: -Z borrowck=mir -Z two-phase-borrows
+
+// (Since we are manually toggling NLL variations on and off, don't
+// bother with compare-mode=nll)
+// ignore-compare-mode-nll
+
+#[derive(Copy, Clone)]
+struct BodyId;
+enum Expr { Closure(BodyId), Others }
+struct Body { value: Expr }
+
+struct Map { body: Body, }
+impl Map { fn body(&self, _: BodyId) -> &Body { unimplemented!() } }
+
+struct SpanlessHash<'a> { cx: &'a Map, cx_mut: &'a mut Map }
+
+impl <'a> SpanlessHash<'a> {
+    fn demo(&mut self) {
+        let _mut_borrow = &mut *self;
+        let _access = self.cx;
+        //[ast]~^ ERROR cannot use `self.cx` because it was mutably borrowed [E0503]
+        //[no2pb]~^^ ERROR cannot use `self.cx` because it was mutably borrowed [E0503]
+        //[nll]~^^^ ERROR cannot use `self.cx` because it was mutably borrowed [E0503]
+        _mut_borrow;
+    }
+
+    fn hash_expr(&mut self, e: &Expr) {
+        match *e {
+            Expr::Closure(eid) => {
+                // Accepted by AST-borrowck for erroneous reasons
+                // (rust-lang/rust#38899).
+                //
+                // Not okay without two-phase borrows: the implicit
+                // `&mut self` of the receiver is evaluated first, and
+                // that conflicts with the `self.cx`` access during
+                // argument evaluation, as demonstrated in `fn demo`
+                // above.
+                //
+                // Okay if we have two-phase borrows. Note that even
+                // if `self.cx.body(..)` holds onto a reference into
+                // `self.cx`, `self.cx` is an immutable-borrow, so
+                // nothing in the activation for `self.hash_expr(..)`
+                // can interfere with that immutable borrow.
+                self.hash_expr(&self.cx.body(eid).value);
+                //[no2pb]~^ ERROR cannot borrow `*self.cx`
+            },
+            _ => {}
+        }
+    }
+
+    fn hash_expr_mut(&mut self, e: &Expr) {
+        match *e {
+            Expr::Closure(eid) => {
+                // Not okay: the call to `self.cx_mut.body(eid)` might
+                // hold on to some mutably borrowed state in
+                // `self.cx_mut`, which would then interfere with the
+                // eventual activation of the `self` mutable borrow
+                // for `self.hash_expr(..)`
+                self.hash_expr(&self.cx_mut.body(eid).value);
+                //[ast]~^ ERROR cannot borrow `*self.cx_mut`
+                //[no2pb]~^^ ERROR cannot borrow `*self.cx_mut`
+                //[nll]~^^^ ERROR cannot borrow `*self`
+            },
+            _ => {}
+        }
+    }
+}
+
+struct Session;
+struct Config;
+trait LateLintPass<'a> { }
+
+struct TrivialPass;
+impl TrivialPass {
+    fn new(_: &Session) -> Self { TrivialPass }
+    fn new_mut(_: &mut Session) -> Self { TrivialPass }
+}
+
+struct CapturePass<'a> { s: &'a Session }
+impl<'a> CapturePass<'a> {
+    fn new(s: &'a Session) -> Self { CapturePass { s } }
+    fn new_mut(s: &'a mut Session) -> Self { CapturePass { s } }
+}
+
+impl<'a> LateLintPass<'a> for TrivialPass { }
+impl<'a, 'b> LateLintPass<'a> for CapturePass<'b> { }
+
+struct Registry<'a> { sess_mut: &'a mut Session }
+impl<'a> Registry<'a> {
+    fn register_static(&mut self, _: Box<dyn LateLintPass + 'static>) { }
+
+    // Note: there isn't an interesting distinction between these
+    // different methods explored by any of the cases in the test
+    // below. pnkfelix just happened to write these cases out while
+    // exploring variations on `dyn for <'a> Trait<'a> + 'static`, and
+    // then decided to keep these particular ones in.
+    fn register_bound(&mut self, _: Box<dyn LateLintPass + 'a>) { }
+    fn register_univ(&mut self, _: Box<dyn for <'b> LateLintPass<'b> + 'a>) { }
+    fn register_ref(&mut self, _: &dyn LateLintPass) { }
+}
+
+fn register_plugins<'a>(mk_reg: impl Fn() -> &'a mut Registry<'a>) {
+    // Not okay without two-phase borrows: The implicit `&mut reg` of
+    // the receiver is evaluaated first, and that conflicts with the
+    // `reg.sess_mut` access during argument evaluation.
+    //
+    // Okay if we have two-phase borrows: inner borrows do not survive
+    // to the actual method invocation, because `TrivialPass::new`
+    // cannot (according to its type) keep them alive.
+    let reg = mk_reg();
+    reg.register_static(Box::new(TrivialPass::new(&reg.sess_mut)));
+    //[ast]~^ ERROR cannot borrow `reg.sess_mut`
+    //[no2pb]~^^ ERROR cannot borrow `reg.sess_mut`
+    let reg = mk_reg();
+    reg.register_bound(Box::new(TrivialPass::new(&reg.sess_mut)));
+    //[ast]~^ ERROR cannot borrow `reg.sess_mut`
+    //[no2pb]~^^ ERROR cannot borrow `reg.sess_mut`
+    let reg = mk_reg();
+    reg.register_univ(Box::new(TrivialPass::new(&reg.sess_mut)));
+    //[ast]~^ ERROR cannot borrow `reg.sess_mut`
+    //[no2pb]~^^ ERROR cannot borrow `reg.sess_mut`
+    let reg = mk_reg();
+    reg.register_ref(&TrivialPass::new(&reg.sess_mut));
+    //[ast]~^ ERROR cannot borrow `reg.sess_mut`
+    //[no2pb]~^^ ERROR cannot borrow `reg.sess_mut`
+
+    // These are not okay: the inner mutable borrows immediately
+    // conflict with the outer borrow/reservation, even with support
+    // for two-phase borrows.
+    let reg = mk_reg();
+    reg.register_static(Box::new(TrivialPass::new(&mut reg.sess_mut)));
+    //[ast]~^ ERROR cannot borrow `reg.sess_mut`
+    //[no2pb]~^^ ERROR cannot borrow `reg.sess_mut`
+    //[nll]~^^^ ERROR cannot borrow `reg.sess_mut`
+    let reg = mk_reg();
+    reg.register_bound(Box::new(TrivialPass::new_mut(&mut reg.sess_mut)));
+    //[ast]~^ ERROR cannot borrow `reg.sess_mut`
+    //[no2pb]~^^ ERROR cannot borrow `reg.sess_mut`
+    //[nll]~^^^ ERROR cannot borrow `reg.sess_mut`
+    let reg = mk_reg();
+    reg.register_univ(Box::new(TrivialPass::new_mut(&mut reg.sess_mut)));
+    //[ast]~^ ERROR cannot borrow `reg.sess_mut`
+    //[no2pb]~^^ ERROR cannot borrow `reg.sess_mut`
+    //[nll]~^^^ ERROR cannot borrow `reg.sess_mut`
+    let reg = mk_reg();
+    reg.register_ref(&TrivialPass::new_mut(&mut reg.sess_mut));
+    //[ast]~^ ERROR cannot borrow `reg.sess_mut`
+    //[no2pb]~^^ ERROR cannot borrow `reg.sess_mut`
+    //[nll]~^^^ ERROR cannot borrow `reg.sess_mut`
+
+    // These are not okay: the inner borrows may reach the actual
+    // method invocation, because `CapturePass::new` might (according
+    // to its type) keep them alive.
+    //
+    // (Also, we don't test `register_static` on CapturePass because
+    // that will fail to get past lifetime inference.)
+    let reg = mk_reg();
+    reg.register_bound(Box::new(CapturePass::new(&reg.sess_mut)));
+    //[ast]~^ ERROR cannot borrow `reg.sess_mut`
+    //[no2pb]~^^ ERROR cannot borrow `reg.sess_mut`
+    //[nll]~^^^ ERROR cannot borrow `*reg` as mutable
+    let reg = mk_reg();
+    reg.register_univ(Box::new(CapturePass::new(&reg.sess_mut)));
+    //[ast]~^ ERROR cannot borrow `reg.sess_mut`
+    //[no2pb]~^^ ERROR cannot borrow `reg.sess_mut`
+    //[nll]~^^^ ERROR cannot borrow `*reg` as mutable
+    let reg = mk_reg();
+    reg.register_ref(&CapturePass::new(&reg.sess_mut));
+    //[ast]~^ ERROR cannot borrow `reg.sess_mut`
+    //[no2pb]~^^ ERROR cannot borrow `reg.sess_mut`
+    //[nll]~^^^ ERROR cannot borrow `*reg` as mutable
+
+    // These are not okay: the inner mutable borrows immediately
+    // conflict with the outer borrow/reservation, even with support
+    // for two-phase borrows.
+    //
+    // (Again, we don't test `register_static` on CapturePass because
+    // that will fail to get past lifetime inference.)
+    let reg = mk_reg();
+    reg.register_bound(Box::new(CapturePass::new_mut(&mut reg.sess_mut)));
+    //[ast]~^ ERROR cannot borrow `reg.sess_mut`
+    //[no2pb]~^^ ERROR cannot borrow `reg.sess_mut`
+    //[nll]~^^^ ERROR cannot borrow `reg.sess_mut` as mutable more than once at a time
+    //[nll]~^^^^ ERROR cannot borrow `*reg` as mutable more than once at a time
+    let reg = mk_reg();
+    reg.register_univ(Box::new(CapturePass::new_mut(&mut reg.sess_mut)));
+    //[ast]~^ ERROR cannot borrow `reg.sess_mut`
+    //[no2pb]~^^ ERROR cannot borrow `reg.sess_mut`
+    //[nll]~^^^ ERROR cannot borrow `reg.sess_mut` as mutable more than once at a time
+    //[nll]~^^^^ ERROR cannot borrow `*reg` as mutable more than once at a time
+    let reg = mk_reg();
+    reg.register_ref(&CapturePass::new_mut(&mut reg.sess_mut));
+    //[ast]~^ ERROR cannot borrow `reg.sess_mut`
+    //[no2pb]~^^ ERROR cannot borrow `reg.sess_mut`
+    //[nll]~^^^ ERROR cannot borrow `reg.sess_mut` as mutable more than once at a time
+    //[nll]~^^^^ ERROR cannot borrow `*reg` as mutable more than once at a time
+}
+
+fn main() { }
diff --git a/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.nll.stderr b/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.nll.stderr
new file mode 100644
index 0000000..d6125cf
--- /dev/null
+++ b/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.nll.stderr
@@ -0,0 +1,12 @@
+error[E0507]: cannot move out of captured variable in an `Fn` closure
+  --> $DIR/unboxed-closures-move-upvar-from-non-once-ref-closure.rs:11:9
+   |
+LL |     let y = vec![format!("World")];
+   |         - captured outer variable
+LL |     call(|| {
+LL |         y.into_iter();
+   |         ^ cannot move out of captured variable in an `Fn` closure
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.rs b/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.rs
new file mode 100644
index 0000000..4c6a053
--- /dev/null
+++ b/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.rs
@@ -0,0 +1,14 @@
+// Test that a by-ref `FnMut` closure gets an error when it tries to
+// consume a value.
+
+fn call<F>(f: F) where F : Fn() {
+    f();
+}
+
+fn main() {
+    let y = vec![format!("World")];
+    call(|| {
+        y.into_iter();
+        //~^ ERROR cannot move out of captured outer variable in an `Fn` closure
+    });
+}
diff --git a/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr b/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr
new file mode 100644
index 0000000..bdfd6fb7e
--- /dev/null
+++ b/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr
@@ -0,0 +1,12 @@
+error[E0507]: cannot move out of captured outer variable in an `Fn` closure
+  --> $DIR/unboxed-closures-move-upvar-from-non-once-ref-closure.rs:11:9
+   |
+LL |     let y = vec![format!("World")];
+   |         - captured outer variable
+LL |     call(|| {
+LL |         y.into_iter();
+   |         ^ cannot move out of captured outer variable in an `Fn` closure
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/bounds-lifetime.rs b/src/test/ui/bounds-lifetime.rs
new file mode 100644
index 0000000..8abfe3e
--- /dev/null
+++ b/src/test/ui/bounds-lifetime.rs
@@ -0,0 +1,7 @@
+type A = for<'b, 'a: 'b> fn(); //~ ERROR lifetime bounds cannot be used in this context
+type B = for<'b, 'a: 'b,> fn(); //~ ERROR lifetime bounds cannot be used in this context
+type C = for<'b, 'a: 'b +> fn(); //~ ERROR lifetime bounds cannot be used in this context
+type D = for<'a, T> fn(); //~ ERROR only lifetime parameters can be used in this context
+type E = for<T> Fn(); //~ ERROR only lifetime parameters can be used in this context
+
+fn main() {}
diff --git a/src/test/ui/bounds-lifetime.stderr b/src/test/ui/bounds-lifetime.stderr
new file mode 100644
index 0000000..21a7814
--- /dev/null
+++ b/src/test/ui/bounds-lifetime.stderr
@@ -0,0 +1,32 @@
+error: lifetime bounds cannot be used in this context
+  --> $DIR/bounds-lifetime.rs:1:22
+   |
+LL | type A = for<'b, 'a: 'b> fn();
+   |                      ^^
+
+error: lifetime bounds cannot be used in this context
+  --> $DIR/bounds-lifetime.rs:2:22
+   |
+LL | type B = for<'b, 'a: 'b,> fn();
+   |                      ^^
+
+error: lifetime bounds cannot be used in this context
+  --> $DIR/bounds-lifetime.rs:3:22
+   |
+LL | type C = for<'b, 'a: 'b +> fn();
+   |                      ^^
+
+error: only lifetime parameters can be used in this context
+  --> $DIR/bounds-lifetime.rs:4:18
+   |
+LL | type D = for<'a, T> fn();
+   |                  ^
+
+error: only lifetime parameters can be used in this context
+  --> $DIR/bounds-lifetime.rs:5:14
+   |
+LL | type E = for<T> Fn();
+   |              ^
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/ui/break-outside-loop.rs b/src/test/ui/break-outside-loop.rs
new file mode 100644
index 0000000..fef298f
--- /dev/null
+++ b/src/test/ui/break-outside-loop.rs
@@ -0,0 +1,25 @@
+struct Foo {
+    t: String
+}
+
+fn cond() -> bool { true }
+
+fn foo<F>(_: F) where F: FnOnce() {}
+
+fn main() {
+    let pth = break; //~ ERROR: `break` outside of loop
+    if cond() { continue } //~ ERROR: `continue` outside of loop
+
+    while cond() {
+        if cond() { break }
+        if cond() { continue }
+        foo(|| {
+            if cond() { break } //~ ERROR: `break` inside of a closure
+            if cond() { continue } //~ ERROR: `continue` inside of a closure
+        })
+    }
+
+    let rs: Foo = Foo{t: pth};
+
+    let unconstrained = break; //~ ERROR: `break` outside of loop
+}
diff --git a/src/test/ui/break-outside-loop.stderr b/src/test/ui/break-outside-loop.stderr
new file mode 100644
index 0000000..c1aa580
--- /dev/null
+++ b/src/test/ui/break-outside-loop.stderr
@@ -0,0 +1,34 @@
+error[E0268]: `break` outside of loop
+  --> $DIR/break-outside-loop.rs:10:15
+   |
+LL |     let pth = break;
+   |               ^^^^^ cannot break outside of a loop
+
+error[E0268]: `continue` outside of loop
+  --> $DIR/break-outside-loop.rs:11:17
+   |
+LL |     if cond() { continue }
+   |                 ^^^^^^^^ cannot break outside of a loop
+
+error[E0267]: `break` inside of a closure
+  --> $DIR/break-outside-loop.rs:17:25
+   |
+LL |             if cond() { break }
+   |                         ^^^^^ cannot break inside of a closure
+
+error[E0267]: `continue` inside of a closure
+  --> $DIR/break-outside-loop.rs:18:25
+   |
+LL |             if cond() { continue }
+   |                         ^^^^^^^^ cannot break inside of a closure
+
+error[E0268]: `break` outside of loop
+  --> $DIR/break-outside-loop.rs:24:25
+   |
+LL |     let unconstrained = break;
+   |                         ^^^^^ cannot break outside of a loop
+
+error: aborting due to 5 previous errors
+
+Some errors occurred: E0267, E0268.
+For more information about an error, try `rustc --explain E0267`.
diff --git a/src/test/ui/break-while-condition.rs b/src/test/ui/break-while-condition.rs
new file mode 100644
index 0000000..6064e6a
--- /dev/null
+++ b/src/test/ui/break-while-condition.rs
@@ -0,0 +1,29 @@
+#![feature(never_type)]
+
+fn main() {
+    // The `if false` expressions are simply to
+    // make sure we don't avoid checking everything
+    // simply because a few expressions are unreachable.
+
+    if false {
+        let _: ! = { //~ ERROR mismatched types
+            'a: while break 'a {};
+        };
+    }
+
+    if false {
+        let _: ! = {
+            while false { //~ ERROR mismatched types
+                break
+            }
+        };
+    }
+
+    if false {
+        let _: ! = {
+            while false { //~ ERROR mismatched types
+                return
+            }
+        };
+    }
+}
diff --git a/src/test/ui/break-while-condition.stderr b/src/test/ui/break-while-condition.stderr
new file mode 100644
index 0000000..a08edee
--- /dev/null
+++ b/src/test/ui/break-while-condition.stderr
@@ -0,0 +1,37 @@
+error[E0308]: mismatched types
+  --> $DIR/break-while-condition.rs:9:20
+   |
+LL |           let _: ! = {
+   |  ____________________^
+LL | |             'a: while break 'a {};
+LL | |         };
+   | |_________^ expected !, found ()
+   |
+   = note: expected type `!`
+              found type `()`
+
+error[E0308]: mismatched types
+  --> $DIR/break-while-condition.rs:16:13
+   |
+LL | /             while false {
+LL | |                 break
+LL | |             }
+   | |_____________^ expected !, found ()
+   |
+   = note: expected type `!`
+              found type `()`
+
+error[E0308]: mismatched types
+  --> $DIR/break-while-condition.rs:24:13
+   |
+LL | /             while false {
+LL | |                 return
+LL | |             }
+   | |_____________^ expected !, found ()
+   |
+   = note: expected type `!`
+              found type `()`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/builtin-superkinds/auxiliary/trait_superkinds_in_metadata.rs b/src/test/ui/builtin-superkinds/auxiliary/trait_superkinds_in_metadata.rs
new file mode 100644
index 0000000..acfd1e1
--- /dev/null
+++ b/src/test/ui/builtin-superkinds/auxiliary/trait_superkinds_in_metadata.rs
@@ -0,0 +1,8 @@
+// Test library crate for cross-crate usages of traits inheriting
+// from the builtin kinds. Mostly tests metadata correctness.
+
+#![crate_type="lib"]
+
+pub trait RequiresShare : Sync { }
+pub trait RequiresRequiresShareAndSend : RequiresShare + Send { }
+pub trait RequiresCopy : Copy { }
diff --git a/src/test/ui/builtin-superkinds/builtin-superkinds-double-superkind.rs b/src/test/ui/builtin-superkinds/builtin-superkinds-double-superkind.rs
new file mode 100644
index 0000000..e716489
--- /dev/null
+++ b/src/test/ui/builtin-superkinds/builtin-superkinds-double-superkind.rs
@@ -0,0 +1,14 @@
+// Test for traits that inherit from multiple builtin kinds at once,
+// testing that all such kinds must be present on implementing types.
+
+trait Foo : Send+Sync { }
+
+impl <T: Sync+'static> Foo for (T,) { }
+//~^ ERROR `T` cannot be sent between threads safely [E0277]
+
+impl <T: Send> Foo for (T,T) { }
+//~^ ERROR `T` cannot be shared between threads safely [E0277]
+
+impl <T: Send+Sync> Foo for (T,T,T) { } // (ok)
+
+fn main() { }
diff --git a/src/test/ui/builtin-superkinds/builtin-superkinds-double-superkind.stderr b/src/test/ui/builtin-superkinds/builtin-superkinds-double-superkind.stderr
new file mode 100644
index 0000000..9771436
--- /dev/null
+++ b/src/test/ui/builtin-superkinds/builtin-superkinds-double-superkind.stderr
@@ -0,0 +1,23 @@
+error[E0277]: `T` cannot be sent between threads safely
+  --> $DIR/builtin-superkinds-double-superkind.rs:6:24
+   |
+LL | impl <T: Sync+'static> Foo for (T,) { }
+   |                        ^^^ `T` cannot be sent between threads safely
+   |
+   = help: within `(T,)`, the trait `std::marker::Send` is not implemented for `T`
+   = help: consider adding a `where T: std::marker::Send` bound
+   = note: required because it appears within the type `(T,)`
+
+error[E0277]: `T` cannot be shared between threads safely
+  --> $DIR/builtin-superkinds-double-superkind.rs:9:16
+   |
+LL | impl <T: Send> Foo for (T,T) { }
+   |                ^^^ `T` cannot be shared between threads safely
+   |
+   = help: within `(T, T)`, the trait `std::marker::Sync` is not implemented for `T`
+   = help: consider adding a `where T: std::marker::Sync` bound
+   = note: required because it appears within the type `(T, T)`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/builtin-superkinds/builtin-superkinds-in-metadata.rs b/src/test/ui/builtin-superkinds/builtin-superkinds-in-metadata.rs
new file mode 100644
index 0000000..b4555a1
--- /dev/null
+++ b/src/test/ui/builtin-superkinds/builtin-superkinds-in-metadata.rs
@@ -0,0 +1,16 @@
+// aux-build:trait_superkinds_in_metadata.rs
+
+// Test for traits inheriting from the builtin kinds cross-crate.
+// Mostly tests correctness of metadata.
+
+extern crate trait_superkinds_in_metadata;
+use trait_superkinds_in_metadata::{RequiresRequiresShareAndSend, RequiresShare};
+
+struct X<T>(T);
+
+impl <T:Sync> RequiresShare for X<T> { }
+
+impl <T:Sync+'static> RequiresRequiresShareAndSend for X<T> { }
+//~^ ERROR `T` cannot be sent between threads safely [E0277]
+
+fn main() { }
diff --git a/src/test/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr b/src/test/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr
new file mode 100644
index 0000000..61c18a2
--- /dev/null
+++ b/src/test/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr
@@ -0,0 +1,13 @@
+error[E0277]: `T` cannot be sent between threads safely
+  --> $DIR/builtin-superkinds-in-metadata.rs:13:23
+   |
+LL | impl <T:Sync+'static> RequiresRequiresShareAndSend for X<T> { }
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `T` cannot be sent between threads safely
+   |
+   = help: within `X<T>`, the trait `std::marker::Send` is not implemented for `T`
+   = help: consider adding a `where T: std::marker::Send` bound
+   = note: required because it appears within the type `X<T>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/builtin-superkinds/builtin-superkinds-self-type.rs b/src/test/ui/builtin-superkinds/builtin-superkinds-self-type.rs
new file mode 100644
index 0000000..6fba87b
--- /dev/null
+++ b/src/test/ui/builtin-superkinds/builtin-superkinds-self-type.rs
@@ -0,0 +1,17 @@
+// Tests (negatively) the ability for the Self type in default methods
+// to use capabilities granted by builtin kinds as supertraits.
+
+use std::sync::mpsc::{channel, Sender};
+
+trait Foo : Sized+Sync+'static {
+    fn foo(self, mut chan: Sender<Self>) { }
+}
+
+impl <T: Sync> Foo for T { }
+//~^ ERROR the parameter type `T` may not live long enough
+
+fn main() {
+    let (tx, rx) = channel();
+    1193182.foo(tx);
+    assert_eq!(rx.recv(), 1193182);
+}
diff --git a/src/test/ui/builtin-superkinds/builtin-superkinds-self-type.stderr b/src/test/ui/builtin-superkinds/builtin-superkinds-self-type.stderr
new file mode 100644
index 0000000..2fdb383
--- /dev/null
+++ b/src/test/ui/builtin-superkinds/builtin-superkinds-self-type.stderr
@@ -0,0 +1,17 @@
+error[E0310]: the parameter type `T` may not live long enough
+  --> $DIR/builtin-superkinds-self-type.rs:10:16
+   |
+LL | impl <T: Sync> Foo for T { }
+   |       --       ^^^
+   |       |
+   |       help: consider adding an explicit lifetime bound `T: 'static`...
+   |
+note: ...so that the type `T` will meet its required lifetime bounds
+  --> $DIR/builtin-superkinds-self-type.rs:10:16
+   |
+LL | impl <T: Sync> Foo for T { }
+   |                ^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0310`.
diff --git a/src/test/ui/builtin-superkinds/builtin-superkinds-simple.rs b/src/test/ui/builtin-superkinds/builtin-superkinds-simple.rs
new file mode 100644
index 0000000..afafc09
--- /dev/null
+++ b/src/test/ui/builtin-superkinds/builtin-superkinds-simple.rs
@@ -0,0 +1,9 @@
+// Basic test for traits inheriting from the builtin kinds, checking
+// the type contents of the implementing type (that's not a typaram).
+
+trait Foo : Send { }
+
+impl Foo for std::rc::Rc<i8> { }
+//~^ ERROR `std::rc::Rc<i8>` cannot be sent between threads safely
+
+fn main() { }
diff --git a/src/test/ui/builtin-superkinds/builtin-superkinds-simple.stderr b/src/test/ui/builtin-superkinds/builtin-superkinds-simple.stderr
new file mode 100644
index 0000000..a0ff640
--- /dev/null
+++ b/src/test/ui/builtin-superkinds/builtin-superkinds-simple.stderr
@@ -0,0 +1,11 @@
+error[E0277]: `std::rc::Rc<i8>` cannot be sent between threads safely
+  --> $DIR/builtin-superkinds-simple.rs:6:6
+   |
+LL | impl Foo for std::rc::Rc<i8> { }
+   |      ^^^ `std::rc::Rc<i8>` cannot be sent between threads safely
+   |
+   = help: the trait `std::marker::Send` is not implemented for `std::rc::Rc<i8>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/builtin-superkinds/builtin-superkinds-typaram-not-send.rs b/src/test/ui/builtin-superkinds/builtin-superkinds-typaram-not-send.rs
new file mode 100644
index 0000000..74ae627
--- /dev/null
+++ b/src/test/ui/builtin-superkinds/builtin-superkinds-typaram-not-send.rs
@@ -0,0 +1,8 @@
+// Basic test for traits inheriting from the builtin kinds.
+
+trait Foo : Send { }
+
+impl <T: Sync+'static> Foo for T { }
+//~^ ERROR `T` cannot be sent between threads safely
+
+fn main() { }
diff --git a/src/test/ui/builtin-superkinds/builtin-superkinds-typaram-not-send.stderr b/src/test/ui/builtin-superkinds/builtin-superkinds-typaram-not-send.stderr
new file mode 100644
index 0000000..dc5479e
--- /dev/null
+++ b/src/test/ui/builtin-superkinds/builtin-superkinds-typaram-not-send.stderr
@@ -0,0 +1,12 @@
+error[E0277]: `T` cannot be sent between threads safely
+  --> $DIR/builtin-superkinds-typaram-not-send.rs:5:24
+   |
+LL | impl <T: Sync+'static> Foo for T { }
+   |                        ^^^ `T` cannot be sent between threads safely
+   |
+   = help: the trait `std::marker::Send` is not implemented for `T`
+   = help: consider adding a `where T: std::marker::Send` bound
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/by-move-pattern-binding.nll.stderr b/src/test/ui/by-move-pattern-binding.nll.stderr
new file mode 100644
index 0000000..8b53147
--- /dev/null
+++ b/src/test/ui/by-move-pattern-binding.nll.stderr
@@ -0,0 +1,21 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/by-move-pattern-binding.rs:14:11
+   |
+LL |     match &s.x {
+   |           ^^^^ cannot move out of borrowed content
+LL |         &E::Foo => {}
+LL |         &E::Bar(identifier) => f(identifier.clone())
+   |         -------------------
+   |         |       |
+   |         |       data moved here
+   |         help: consider removing the `&`: `E::Bar(identifier)`
+   |
+note: move occurs because `identifier` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/by-move-pattern-binding.rs:16:17
+   |
+LL |         &E::Bar(identifier) => f(identifier.clone())
+   |                 ^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/by-move-pattern-binding.rs b/src/test/ui/by-move-pattern-binding.rs
new file mode 100644
index 0000000..455b206
--- /dev/null
+++ b/src/test/ui/by-move-pattern-binding.rs
@@ -0,0 +1,22 @@
+enum E {
+    Foo,
+    Bar(String)
+}
+
+struct S {
+    x: E
+}
+
+fn f(x: String) {}
+
+fn main() {
+    let s = S { x: E::Bar("hello".to_string()) };
+    match &s.x {
+        &E::Foo => {}
+        &E::Bar(identifier) => f(identifier.clone())  //~ ERROR cannot move
+    };
+    match &s.x {
+        &E::Foo => {}
+        &E::Bar(ref identifier) => println!("{}", *identifier)
+    };
+}
diff --git a/src/test/ui/by-move-pattern-binding.stderr b/src/test/ui/by-move-pattern-binding.stderr
new file mode 100644
index 0000000..5135e0d
--- /dev/null
+++ b/src/test/ui/by-move-pattern-binding.stderr
@@ -0,0 +1,12 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/by-move-pattern-binding.rs:16:9
+   |
+LL |         &E::Bar(identifier) => f(identifier.clone())
+   |         ^^^^^^^^----------^
+   |         |       |
+   |         |       hint: to prevent move, use `ref identifier` or `ref mut identifier`
+   |         cannot move out of borrowed content
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/c-variadic/variadic-ffi-1.rs b/src/test/ui/c-variadic/variadic-ffi-1.rs
new file mode 100644
index 0000000..61b2ad4
--- /dev/null
+++ b/src/test/ui/c-variadic/variadic-ffi-1.rs
@@ -0,0 +1,31 @@
+// ignore-arm stdcall isn't supported
+// ignore-aarch64 stdcall isn't supported
+
+extern "stdcall" {
+    fn printf(_: *const u8, ...); //~ ERROR: variadic function must have C or cdecl calling
+}
+
+extern {
+    fn foo(f: isize, x: u8, ...);
+}
+
+extern "C" fn bar(f: isize, x: u8) {}
+
+fn main() {
+    // errors below are no longer checked because error above aborts
+    // compilation; see variadic-ffi-3.rs for corresponding test.
+    unsafe {
+        foo();
+        foo(1);
+
+        let x: unsafe extern "C" fn(f: isize, x: u8) = foo;
+        let y: extern "C" fn(f: isize, x: u8, ...) = bar;
+
+        foo(1, 2, 3f32);
+        foo(1, 2, true);
+        foo(1, 2, 1i8);
+        foo(1, 2, 1u8);
+        foo(1, 2, 1i16);
+        foo(1, 2, 1u16);
+    }
+}
diff --git a/src/test/ui/c-variadic/variadic-ffi-1.stderr b/src/test/ui/c-variadic/variadic-ffi-1.stderr
new file mode 100644
index 0000000..1a2bb44
--- /dev/null
+++ b/src/test/ui/c-variadic/variadic-ffi-1.stderr
@@ -0,0 +1,9 @@
+error[E0045]: C-variadic function must have C or cdecl calling convention
+  --> $DIR/variadic-ffi-1.rs:5:5
+   |
+LL |     fn printf(_: *const u8, ...);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadics require C or cdecl calling convention
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0045`.
diff --git a/src/test/ui/c-variadic/variadic-ffi-2.rs b/src/test/ui/c-variadic/variadic-ffi-2.rs
new file mode 100644
index 0000000..224ac16
--- /dev/null
+++ b/src/test/ui/c-variadic/variadic-ffi-2.rs
@@ -0,0 +1,8 @@
+// ignore-arm stdcall isn't supported
+
+fn baz(f: extern "stdcall" fn(usize, ...)) {
+    //~^ ERROR: variadic function must have C or cdecl calling convention
+    f(22, 44);
+}
+
+fn main() {}
diff --git a/src/test/ui/c-variadic/variadic-ffi-2.stderr b/src/test/ui/c-variadic/variadic-ffi-2.stderr
new file mode 100644
index 0000000..4c8b8d2b
--- /dev/null
+++ b/src/test/ui/c-variadic/variadic-ffi-2.stderr
@@ -0,0 +1,9 @@
+error[E0045]: C-variadic function must have C or cdecl calling convention
+  --> $DIR/variadic-ffi-2.rs:3:11
+   |
+LL | fn baz(f: extern "stdcall" fn(usize, ...)) {
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadics require C or cdecl calling convention
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0045`.
diff --git a/src/test/ui/c-variadic/variadic-ffi-3.rs b/src/test/ui/c-variadic/variadic-ffi-3.rs
new file mode 100644
index 0000000..c02d1f5
--- /dev/null
+++ b/src/test/ui/c-variadic/variadic-ffi-3.rs
@@ -0,0 +1,29 @@
+extern {
+    fn foo(f: isize, x: u8, ...);
+    //~^ defined here
+    //~| defined here
+}
+
+extern "C" fn bar(f: isize, x: u8) {}
+
+fn main() {
+    unsafe {
+        foo(); //~ ERROR: this function takes at least 2 parameters but 0 parameters were supplied
+        foo(1); //~ ERROR: this function takes at least 2 parameters but 1 parameter was supplied
+
+        let x: unsafe extern "C" fn(f: isize, x: u8) = foo;
+        //~^ ERROR: mismatched types
+        //~| expected type `unsafe extern "C" fn(isize, u8)`
+
+        let y: extern "C" fn(f: isize, x: u8, ...) = bar;
+        //~^ ERROR: mismatched types
+        //~| expected type `for<'r> extern "C" fn(isize, u8, std::ffi::VaList<'r>, ...)`
+
+        foo(1, 2, 3f32); //~ ERROR can't pass `f32` to variadic function
+        foo(1, 2, true); //~ ERROR can't pass `bool` to variadic function
+        foo(1, 2, 1i8); //~ ERROR can't pass `i8` to variadic function
+        foo(1, 2, 1u8); //~ ERROR can't pass `u8` to variadic function
+        foo(1, 2, 1i16); //~ ERROR can't pass `i16` to variadic function
+        foo(1, 2, 1u16); //~ ERROR can't pass `u16` to variadic function
+    }
+}
diff --git a/src/test/ui/c-variadic/variadic-ffi-3.stderr b/src/test/ui/c-variadic/variadic-ffi-3.stderr
new file mode 100644
index 0000000..6e19fc1
--- /dev/null
+++ b/src/test/ui/c-variadic/variadic-ffi-3.stderr
@@ -0,0 +1,76 @@
+error[E0060]: this function takes at least 2 parameters but 0 parameters were supplied
+  --> $DIR/variadic-ffi-3.rs:11:9
+   |
+LL |     fn foo(f: isize, x: u8, ...);
+   |     ----------------------------- defined here
+...
+LL |         foo();
+   |         ^^^^^ expected at least 2 parameters
+
+error[E0060]: this function takes at least 2 parameters but 1 parameter was supplied
+  --> $DIR/variadic-ffi-3.rs:12:9
+   |
+LL |     fn foo(f: isize, x: u8, ...);
+   |     ----------------------------- defined here
+...
+LL |         foo(1);
+   |         ^^^^^^ expected at least 2 parameters
+
+error[E0308]: mismatched types
+  --> $DIR/variadic-ffi-3.rs:14:56
+   |
+LL |         let x: unsafe extern "C" fn(f: isize, x: u8) = foo;
+   |                                                        ^^^ expected non-variadic fn, found variadic function
+   |
+   = note: expected type `unsafe extern "C" fn(isize, u8)`
+              found type `for<'r> unsafe extern "C" fn(isize, u8, std::ffi::VaList<'r>, ...) {foo}`
+
+error[E0308]: mismatched types
+  --> $DIR/variadic-ffi-3.rs:18:54
+   |
+LL |         let y: extern "C" fn(f: isize, x: u8, ...) = bar;
+   |                                                      ^^^ expected variadic fn, found non-variadic function
+   |
+   = note: expected type `for<'r> extern "C" fn(isize, u8, std::ffi::VaList<'r>, ...)`
+              found type `extern "C" fn(isize, u8) {bar}`
+
+error[E0617]: can't pass `f32` to variadic function
+  --> $DIR/variadic-ffi-3.rs:22:19
+   |
+LL |         foo(1, 2, 3f32);
+   |                   ^^^^ help: cast the value to `c_double`: `3f32 as c_double`
+
+error[E0617]: can't pass `bool` to variadic function
+  --> $DIR/variadic-ffi-3.rs:23:19
+   |
+LL |         foo(1, 2, true);
+   |                   ^^^^ help: cast the value to `c_int`: `true as c_int`
+
+error[E0617]: can't pass `i8` to variadic function
+  --> $DIR/variadic-ffi-3.rs:24:19
+   |
+LL |         foo(1, 2, 1i8);
+   |                   ^^^ help: cast the value to `c_int`: `1i8 as c_int`
+
+error[E0617]: can't pass `u8` to variadic function
+  --> $DIR/variadic-ffi-3.rs:25:19
+   |
+LL |         foo(1, 2, 1u8);
+   |                   ^^^ help: cast the value to `c_uint`: `1u8 as c_uint`
+
+error[E0617]: can't pass `i16` to variadic function
+  --> $DIR/variadic-ffi-3.rs:26:19
+   |
+LL |         foo(1, 2, 1i16);
+   |                   ^^^^ help: cast the value to `c_int`: `1i16 as c_int`
+
+error[E0617]: can't pass `u16` to variadic function
+  --> $DIR/variadic-ffi-3.rs:27:19
+   |
+LL |         foo(1, 2, 1u16);
+   |                   ^^^^ help: cast the value to `c_uint`: `1u16 as c_uint`
+
+error: aborting due to 10 previous errors
+
+Some errors occurred: E0060, E0308, E0617.
+For more information about an error, try `rustc --explain E0060`.
diff --git a/src/test/ui/c-variadic/variadic-ffi-4.rs b/src/test/ui/c-variadic/variadic-ffi-4.rs
new file mode 100644
index 0000000..1c77479
--- /dev/null
+++ b/src/test/ui/c-variadic/variadic-ffi-4.rs
@@ -0,0 +1,29 @@
+#![crate_type="lib"]
+#![no_std]
+#![feature(c_variadic)]
+
+use core::ffi::VaList;
+
+pub unsafe extern "C" fn no_escape0<'a>(_: usize, ap: ...) -> VaList<'a> {
+    ap //~ ERROR: explicit lifetime required
+}
+
+pub unsafe extern "C" fn no_escape1(_: usize, ap: ...) -> VaList<'static> {
+    ap //~ ERROR: explicit lifetime required
+}
+
+pub unsafe extern "C" fn no_escape2(_: usize, ap: ...) {
+    let _ = ap.with_copy(|ap| { ap }); //~ ERROR: cannot infer an appropriate lifetime
+}
+
+pub unsafe extern "C" fn no_escape3(_: usize, mut ap0: &mut VaList, mut ap1: ...) {
+    *ap0 = ap1; //~ ERROR: mismatched types
+}
+
+pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaList, mut ap1: ...) {
+    ap0 = &mut ap1;
+    //~^ ERROR: a value of type `core::ffi::VaList<'_>` is borrowed for too long
+    //~^^ ERROR: mismatched types
+    //~^^^ ERROR: mismatched types
+    //~^^^^ ERROR: cannot infer an appropriate lifetime
+}
diff --git a/src/test/ui/c-variadic/variadic-ffi-4.stderr b/src/test/ui/c-variadic/variadic-ffi-4.stderr
new file mode 100644
index 0000000..311e217
--- /dev/null
+++ b/src/test/ui/c-variadic/variadic-ffi-4.stderr
@@ -0,0 +1,198 @@
+error[E0621]: explicit lifetime required in the type of `ap`
+  --> $DIR/variadic-ffi-4.rs:8:5
+   |
+LL | pub unsafe extern "C" fn no_escape0<'a>(_: usize, ap: ...) -> VaList<'a> {
+   |                                                       --- help: add explicit lifetime `'a` to the type of `ap`: `core::ffi::VaList<'a>`
+LL |     ap
+   |     ^^ lifetime `'a` required
+
+error[E0621]: explicit lifetime required in the type of `ap`
+  --> $DIR/variadic-ffi-4.rs:12:5
+   |
+LL | pub unsafe extern "C" fn no_escape1(_: usize, ap: ...) -> VaList<'static> {
+   |                                                   --- help: add explicit lifetime `'static` to the type of `ap`: `core::ffi::VaList<'static>`
+LL |     ap
+   |     ^^ lifetime `'static` required
+
+error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
+  --> $DIR/variadic-ffi-4.rs:16:33
+   |
+LL |     let _ = ap.with_copy(|ap| { ap });
+   |                                 ^^
+   |
+note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the body at 16:26...
+  --> $DIR/variadic-ffi-4.rs:16:26
+   |
+LL |     let _ = ap.with_copy(|ap| { ap });
+   |                          ^^^^^^^^^^^
+   = note: ...so that the expression is assignable:
+           expected core::ffi::VaList<'_>
+              found core::ffi::VaList<'_>
+note: but, the lifetime must be valid for the method call at 16:13...
+  --> $DIR/variadic-ffi-4.rs:16:13
+   |
+LL |     let _ = ap.with_copy(|ap| { ap });
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...so type `core::ffi::VaList<'_>` of expression is valid during the expression
+  --> $DIR/variadic-ffi-4.rs:16:13
+   |
+LL |     let _ = ap.with_copy(|ap| { ap });
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/variadic-ffi-4.rs:20:12
+   |
+LL |     *ap0 = ap1;
+   |            ^^^ lifetime mismatch
+   |
+   = note: expected type `core::ffi::VaList<'_>`
+              found type `core::ffi::VaList<'_>`
+note: the anonymous lifetime #3 defined on the function body at 19:1...
+  --> $DIR/variadic-ffi-4.rs:19:1
+   |
+LL | / pub unsafe extern "C" fn no_escape3(_: usize, mut ap0: &mut VaList, mut ap1: ...) {
+LL | |     *ap0 = ap1;
+LL | | }
+   | |_^
+note: ...does not necessarily outlive the anonymous lifetime #2 defined on the function body at 19:1
+  --> $DIR/variadic-ffi-4.rs:19:1
+   |
+LL | / pub unsafe extern "C" fn no_escape3(_: usize, mut ap0: &mut VaList, mut ap1: ...) {
+LL | |     *ap0 = ap1;
+LL | | }
+   | |_^
+
+error[E0490]: a value of type `core::ffi::VaList<'_>` is borrowed for too long
+  --> $DIR/variadic-ffi-4.rs:24:11
+   |
+LL |     ap0 = &mut ap1;
+   |           ^^^^^^^^
+   |
+note: the type is valid for the anonymous lifetime #1 defined on the function body at 23:1
+  --> $DIR/variadic-ffi-4.rs:23:1
+   |
+LL | / pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaList, mut ap1: ...) {
+LL | |     ap0 = &mut ap1;
+LL | |
+LL | |
+LL | |
+LL | |
+LL | | }
+   | |_^
+note: but the borrow lasts for the anonymous lifetime #3 defined on the function body at 23:1
+  --> $DIR/variadic-ffi-4.rs:23:1
+   |
+LL | / pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaList, mut ap1: ...) {
+LL | |     ap0 = &mut ap1;
+LL | |
+LL | |
+LL | |
+LL | |
+LL | | }
+   | |_^
+
+error[E0308]: mismatched types
+  --> $DIR/variadic-ffi-4.rs:24:11
+   |
+LL |     ap0 = &mut ap1;
+   |           ^^^^^^^^ lifetime mismatch
+   |
+   = note: expected type `&mut core::ffi::VaList<'_>`
+              found type `&mut core::ffi::VaList<'_>`
+note: the anonymous lifetime #3 defined on the function body at 23:1...
+  --> $DIR/variadic-ffi-4.rs:23:1
+   |
+LL | / pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaList, mut ap1: ...) {
+LL | |     ap0 = &mut ap1;
+LL | |
+LL | |
+LL | |
+LL | |
+LL | | }
+   | |_^
+note: ...does not necessarily outlive the anonymous lifetime #2 defined on the function body at 23:1
+  --> $DIR/variadic-ffi-4.rs:23:1
+   |
+LL | / pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaList, mut ap1: ...) {
+LL | |     ap0 = &mut ap1;
+LL | |
+LL | |
+LL | |
+LL | |
+LL | | }
+   | |_^
+
+error[E0308]: mismatched types
+  --> $DIR/variadic-ffi-4.rs:24:11
+   |
+LL |     ap0 = &mut ap1;
+   |           ^^^^^^^^ lifetime mismatch
+   |
+   = note: expected type `&mut core::ffi::VaList<'_>`
+              found type `&mut core::ffi::VaList<'_>`
+note: the anonymous lifetime #2 defined on the function body at 23:1...
+  --> $DIR/variadic-ffi-4.rs:23:1
+   |
+LL | / pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaList, mut ap1: ...) {
+LL | |     ap0 = &mut ap1;
+LL | |
+LL | |
+LL | |
+LL | |
+LL | | }
+   | |_^
+note: ...does not necessarily outlive the anonymous lifetime #3 defined on the function body at 23:1
+  --> $DIR/variadic-ffi-4.rs:23:1
+   |
+LL | / pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaList, mut ap1: ...) {
+LL | |     ap0 = &mut ap1;
+LL | |
+LL | |
+LL | |
+LL | |
+LL | | }
+   | |_^
+
+error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
+  --> $DIR/variadic-ffi-4.rs:24:11
+   |
+LL |     ap0 = &mut ap1;
+   |           ^^^^^^^^
+   |
+note: first, the lifetime cannot outlive the anonymous lifetime #3 defined on the function body at 23:1...
+  --> $DIR/variadic-ffi-4.rs:23:1
+   |
+LL | / pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaList, mut ap1: ...) {
+LL | |     ap0 = &mut ap1;
+LL | |
+LL | |
+LL | |
+LL | |
+LL | | }
+   | |_^
+note: ...so that the type `core::ffi::VaList<'_>` is not borrowed for too long
+  --> $DIR/variadic-ffi-4.rs:24:11
+   |
+LL |     ap0 = &mut ap1;
+   |           ^^^^^^^^
+note: but, the lifetime must be valid for the anonymous lifetime #1 defined on the function body at 23:1...
+  --> $DIR/variadic-ffi-4.rs:23:1
+   |
+LL | / pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaList, mut ap1: ...) {
+LL | |     ap0 = &mut ap1;
+LL | |
+LL | |
+LL | |
+LL | |
+LL | | }
+   | |_^
+note: ...so that reference does not outlive borrowed content
+  --> $DIR/variadic-ffi-4.rs:24:11
+   |
+LL |     ap0 = &mut ap1;
+   |           ^^^^^^^^
+
+error: aborting due to 8 previous errors
+
+Some errors occurred: E0308, E0490, E0495, E0621.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/c-variadic/variadic-ffi-5.rs b/src/test/ui/c-variadic/variadic-ffi-5.rs
new file mode 100644
index 0000000..fcc80d9
--- /dev/null
+++ b/src/test/ui/c-variadic/variadic-ffi-5.rs
@@ -0,0 +1,31 @@
+#![crate_type="lib"]
+#![no_std]
+#![feature(c_variadic)]
+// The tests in this file are similar to that of variadic-ffi-4, but this
+// one enables nll.
+#![feature(nll)]
+
+use core::ffi::VaList;
+
+pub unsafe extern "C" fn no_escape0<'a>(_: usize, ap: ...) -> VaList<'a> {
+    ap //~ ERROR: explicit lifetime required
+}
+
+pub unsafe extern "C" fn no_escape1(_: usize, ap: ...) -> VaList<'static> {
+    ap //~ ERROR: explicit lifetime required
+}
+
+pub unsafe extern "C" fn no_escape2(_: usize, ap: ...) {
+    let _ = ap.with_copy(|ap| { ap }); //~ ERROR: lifetime may not live long enough
+}
+
+pub unsafe extern "C" fn no_escape3(_: usize, ap0: &mut VaList, mut ap1: ...) {
+    *ap0 = ap1; //~ ERROR: lifetime may not live long enough
+}
+
+pub unsafe extern "C" fn no_escape4(_: usize, mut ap0: &mut VaList, mut ap1: ...) {
+    ap0 = &mut ap1;
+    //~^ ERROR: lifetime may not live long enough
+    //~^^ ERROR: lifetime may not live long enough
+    //~^^^ ERROR: `ap1` does not live long enough
+}
diff --git a/src/test/ui/c-variadic/variadic-ffi-5.stderr b/src/test/ui/c-variadic/variadic-ffi-5.stderr
new file mode 100644
index 0000000..8f1dfe8
--- /dev/null
+++ b/src/test/ui/c-variadic/variadic-ffi-5.stderr
@@ -0,0 +1,73 @@
+error[E0621]: explicit lifetime required in the type of `ap`
+  --> $DIR/variadic-ffi-5.rs:11:5
+   |
+LL | pub unsafe extern "C" fn no_escape0<'a>(_: usize, ap: ...) -> VaList<'a> {
+   |                                                       --- help: add explicit lifetime `'a` to the type of `ap`: `core::ffi::VaList<'a>`
+LL |     ap
+   |     ^^ lifetime `'a` required
+
+error[E0621]: explicit lifetime required in the type of `ap`
+  --> $DIR/variadic-ffi-5.rs:15:5
+   |
+LL | pub unsafe extern "C" fn no_escape1(_: usize, ap: ...) -> VaList<'static> {
+   |                                                   --- help: add explicit lifetime `'static` to the type of `ap`: `core::ffi::VaList<'static>`
+LL |     ap
+   |     ^^ lifetime `'static` required
+
+error: lifetime may not live long enough
+  --> $DIR/variadic-ffi-5.rs:19:33
+   |
+LL |     let _ = ap.with_copy(|ap| { ap });
+   |                           ---   ^^ returning this value requires that `'1` must outlive `'2`
+   |                           | |
+   |                           | return type of closure is core::ffi::VaList<'2>
+   |                           has type `core::ffi::VaList<'1>`
+
+error: lifetime may not live long enough
+  --> $DIR/variadic-ffi-5.rs:23:5
+   |
+LL | pub unsafe extern "C" fn no_escape3(_: usize, ap0: &mut VaList, mut ap1: ...) {
+   |                                               ---               ------- has type `core::ffi::VaList<'1>`
+   |                                               |
+   |                                               has type `&mut core::ffi::VaList<'2>`
+LL |     *ap0 = ap1;
+   |     ^^^^^^^^^^ assignment requires that `'1` must outlive `'2`
+
+error: lifetime may not live long enough
+  --> $DIR/variadic-ffi-5.rs:27:5
+   |
+LL | pub unsafe extern "C" fn no_escape4(_: usize, mut ap0: &mut VaList, mut ap1: ...) {
+   |                                               -------               ------- has type `core::ffi::VaList<'2>`
+   |                                               |
+   |                                               has type `&mut core::ffi::VaList<'1>`
+LL |     ap0 = &mut ap1;
+   |     ^^^^^^^^^^^^^^ assignment requires that `'1` must outlive `'2`
+
+error: lifetime may not live long enough
+  --> $DIR/variadic-ffi-5.rs:27:5
+   |
+LL | pub unsafe extern "C" fn no_escape4(_: usize, mut ap0: &mut VaList, mut ap1: ...) {
+   |                                               -------               ------- has type `core::ffi::VaList<'1>`
+   |                                               |
+   |                                               has type `&mut core::ffi::VaList<'2>`
+LL |     ap0 = &mut ap1;
+   |     ^^^^^^^^^^^^^^ assignment requires that `'1` must outlive `'2`
+
+error[E0597]: `ap1` does not live long enough
+  --> $DIR/variadic-ffi-5.rs:27:11
+   |
+LL | pub unsafe extern "C" fn no_escape4(_: usize, mut ap0: &mut VaList, mut ap1: ...) {
+   |                                                        - let's call the lifetime of this reference `'1`
+LL |     ap0 = &mut ap1;
+   |     ------^^^^^^^^
+   |     |     |
+   |     |     borrowed value does not live long enough
+   |     assignment requires that `ap1` is borrowed for `'1`
+...
+LL | }
+   |  - `ap1` dropped here while still borrowed
+
+error: aborting due to 7 previous errors
+
+Some errors occurred: E0597, E0621.
+For more information about an error, try `rustc --explain E0597`.
diff --git a/src/test/ui/c-variadic/variadic-ffi-6.rs b/src/test/ui/c-variadic/variadic-ffi-6.rs
new file mode 100644
index 0000000..4dd8a2d
--- /dev/null
+++ b/src/test/ui/c-variadic/variadic-ffi-6.rs
@@ -0,0 +1,13 @@
+#![crate_type="lib"]
+#![feature(c_variadic)]
+
+pub unsafe extern "C" fn use_vararg_lifetime(
+    x: usize,
+    y: ...
+) -> &usize { //~ ERROR missing lifetime specifier
+    &0
+}
+
+pub unsafe extern "C" fn use_normal_arg_lifetime(x: &usize, y: ...) -> &usize { // OK
+    x
+}
diff --git a/src/test/ui/c-variadic/variadic-ffi-6.stderr b/src/test/ui/c-variadic/variadic-ffi-6.stderr
new file mode 100644
index 0000000..882e7f8
--- /dev/null
+++ b/src/test/ui/c-variadic/variadic-ffi-6.stderr
@@ -0,0 +1,11 @@
+error[E0106]: missing lifetime specifier
+  --> $DIR/variadic-ffi-6.rs:7:6
+   |
+LL | ) -> &usize {
+   |      ^ help: consider giving it an explicit bounded or 'static lifetime: `&'static`
+   |
+   = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0106`.
diff --git a/src/test/ui/call-fn-never-arg-wrong-type.rs b/src/test/ui/call-fn-never-arg-wrong-type.rs
new file mode 100644
index 0000000..7ed1162
--- /dev/null
+++ b/src/test/ui/call-fn-never-arg-wrong-type.rs
@@ -0,0 +1,12 @@
+// Test that we can't pass other types for !
+
+#![feature(never_type)]
+
+fn foo(x: !) -> ! {
+    x
+}
+
+fn main() {
+    foo("wow"); //~ ERROR mismatched types
+}
+
diff --git a/src/test/ui/call-fn-never-arg-wrong-type.stderr b/src/test/ui/call-fn-never-arg-wrong-type.stderr
new file mode 100644
index 0000000..7a50fd3
--- /dev/null
+++ b/src/test/ui/call-fn-never-arg-wrong-type.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/call-fn-never-arg-wrong-type.rs:10:9
+   |
+LL |     foo("wow");
+   |         ^^^^^ expected !, found reference
+   |
+   = note: expected type `!`
+              found type `&'static str`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/can-begin-expr-check.rs b/src/test/ui/can-begin-expr-check.rs
new file mode 100644
index 0000000..35aed06
--- /dev/null
+++ b/src/test/ui/can-begin-expr-check.rs
@@ -0,0 +1,20 @@
+pub fn main() {
+
+    return;
+    return ();
+    return as ();
+    return return as ();
+    return return return;
+
+    return if true {
+        ()
+    } else {
+        ()
+    };
+
+    loop {
+        return break as ();
+    }
+
+    return enum; //~ ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `enum`
+}
diff --git a/src/test/ui/can-begin-expr-check.stderr b/src/test/ui/can-begin-expr-check.stderr
new file mode 100644
index 0000000..676c2cb
--- /dev/null
+++ b/src/test/ui/can-begin-expr-check.stderr
@@ -0,0 +1,8 @@
+error: expected one of `.`, `;`, `?`, `}`, or an operator, found `enum`
+  --> $DIR/can-begin-expr-check.rs:19:12
+   |
+LL |     return enum;
+   |            ^^^^ expected one of `.`, `;`, `?`, `}`, or an operator here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/cannot-mutate-captured-non-mut-var.ast.nll.stderr b/src/test/ui/cannot-mutate-captured-non-mut-var.ast.nll.stderr
new file mode 100644
index 0000000..581dcde
--- /dev/null
+++ b/src/test/ui/cannot-mutate-captured-non-mut-var.ast.nll.stderr
@@ -0,0 +1,20 @@
+error[E0594]: cannot assign to `x`, as it is not declared as mutable
+  --> $DIR/cannot-mutate-captured-non-mut-var.rs:13:25
+   |
+LL |     let x = 1;
+   |         - help: consider changing this to be mutable: `mut x`
+LL |     to_fn_once(move|| { x = 2; });
+   |                         ^^^^^ cannot assign
+
+error[E0596]: cannot borrow `s` as mutable, as it is not declared as mutable
+  --> $DIR/cannot-mutate-captured-non-mut-var.rs:18:25
+   |
+LL |     let s = std::io::stdin();
+   |         - help: consider changing this to be mutable: `mut s`
+LL |     to_fn_once(move|| { s.read_to_end(&mut Vec::new()); });
+   |                         ^ cannot borrow as mutable
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0594, E0596.
+For more information about an error, try `rustc --explain E0594`.
diff --git a/src/test/ui/cannot-mutate-captured-non-mut-var.ast.stderr b/src/test/ui/cannot-mutate-captured-non-mut-var.ast.stderr
new file mode 100644
index 0000000..1098c16
--- /dev/null
+++ b/src/test/ui/cannot-mutate-captured-non-mut-var.ast.stderr
@@ -0,0 +1,16 @@
+error[E0594]: cannot assign to immutable captured outer variable in an `FnOnce` closure `x`
+  --> $DIR/cannot-mutate-captured-non-mut-var.rs:13:25
+   |
+LL |     to_fn_once(move|| { x = 2; });
+   |                         ^^^^^
+
+error[E0596]: cannot borrow immutable captured outer variable in an `FnOnce` closure `s` as mutable
+  --> $DIR/cannot-mutate-captured-non-mut-var.rs:18:25
+   |
+LL |     to_fn_once(move|| { s.read_to_end(&mut Vec::new()); });
+   |                         ^
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0594, E0596.
+For more information about an error, try `rustc --explain E0594`.
diff --git a/src/test/ui/cannot-mutate-captured-non-mut-var.mir.stderr b/src/test/ui/cannot-mutate-captured-non-mut-var.mir.stderr
new file mode 100644
index 0000000..581dcde
--- /dev/null
+++ b/src/test/ui/cannot-mutate-captured-non-mut-var.mir.stderr
@@ -0,0 +1,20 @@
+error[E0594]: cannot assign to `x`, as it is not declared as mutable
+  --> $DIR/cannot-mutate-captured-non-mut-var.rs:13:25
+   |
+LL |     let x = 1;
+   |         - help: consider changing this to be mutable: `mut x`
+LL |     to_fn_once(move|| { x = 2; });
+   |                         ^^^^^ cannot assign
+
+error[E0596]: cannot borrow `s` as mutable, as it is not declared as mutable
+  --> $DIR/cannot-mutate-captured-non-mut-var.rs:18:25
+   |
+LL |     let s = std::io::stdin();
+   |         - help: consider changing this to be mutable: `mut s`
+LL |     to_fn_once(move|| { s.read_to_end(&mut Vec::new()); });
+   |                         ^ cannot borrow as mutable
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0594, E0596.
+For more information about an error, try `rustc --explain E0594`.
diff --git a/src/test/ui/cannot-mutate-captured-non-mut-var.rs b/src/test/ui/cannot-mutate-captured-non-mut-var.rs
new file mode 100644
index 0000000..18257d0
--- /dev/null
+++ b/src/test/ui/cannot-mutate-captured-non-mut-var.rs
@@ -0,0 +1,21 @@
+// ignore-tidy-linelength
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+#![feature(unboxed_closures)]
+
+use std::io::Read;
+
+fn to_fn_once<A,F:FnOnce<A>>(f: F) -> F { f }
+
+fn main() {
+    let x = 1;
+    to_fn_once(move|| { x = 2; });
+    //[ast]~^ ERROR: cannot assign to immutable captured outer variable
+    //[mir]~^^ ERROR: cannot assign to `x`, as it is not declared as mutable
+
+    let s = std::io::stdin();
+    to_fn_once(move|| { s.read_to_end(&mut Vec::new()); });
+    //[ast]~^ ERROR: cannot borrow immutable captured outer variable
+    //[mir]~^^ ERROR: cannot borrow `s` as mutable, as it is not declared as mutable
+}
diff --git a/src/test/ui/capture1.rs b/src/test/ui/capture1.rs
new file mode 100644
index 0000000..2938c08
--- /dev/null
+++ b/src/test/ui/capture1.rs
@@ -0,0 +1,6 @@
+// error-pattern: can't capture dynamic environment in a fn item
+
+fn main() {
+    let bar: isize = 5;
+    fn foo() -> isize { return bar; }
+}
diff --git a/src/test/ui/capture1.stderr b/src/test/ui/capture1.stderr
new file mode 100644
index 0000000..ad84347
--- /dev/null
+++ b/src/test/ui/capture1.stderr
@@ -0,0 +1,11 @@
+error[E0434]: can't capture dynamic environment in a fn item
+  --> $DIR/capture1.rs:5:32
+   |
+LL |     fn foo() -> isize { return bar; }
+   |                                ^^^
+   |
+   = help: use the `|| { ... }` closure form instead
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0434`.
diff --git a/src/test/ui/cast/cast-as-bool.rs b/src/test/ui/cast/cast-as-bool.rs
new file mode 100644
index 0000000..8130f4d
--- /dev/null
+++ b/src/test/ui/cast/cast-as-bool.rs
@@ -0,0 +1,9 @@
+fn main() {
+    let u = 5 as bool; //~ ERROR cannot cast as `bool`
+                       //~| HELP compare with zero instead
+                       //~| SUGGESTION 5 != 0
+    let t = (1 + 2) as bool; //~ ERROR cannot cast as `bool`
+                             //~| HELP compare with zero instead
+                             //~| SUGGESTION (1 + 2) != 0
+    let v = "hello" as bool; //~ ERROR cannot cast as `bool`
+}
diff --git a/src/test/ui/cast/cast-as-bool.stderr b/src/test/ui/cast/cast-as-bool.stderr
new file mode 100644
index 0000000..30f8459
--- /dev/null
+++ b/src/test/ui/cast/cast-as-bool.stderr
@@ -0,0 +1,21 @@
+error[E0054]: cannot cast as `bool`
+  --> $DIR/cast-as-bool.rs:2:13
+   |
+LL |     let u = 5 as bool;
+   |             ^^^^^^^^^ help: compare with zero instead: `5 != 0`
+
+error[E0054]: cannot cast as `bool`
+  --> $DIR/cast-as-bool.rs:5:13
+   |
+LL |     let t = (1 + 2) as bool;
+   |             ^^^^^^^^^^^^^^^ help: compare with zero instead: `(1 + 2) != 0`
+
+error[E0054]: cannot cast as `bool`
+  --> $DIR/cast-as-bool.rs:8:13
+   |
+LL |     let v = "hello" as bool;
+   |             ^^^^^^^^^^^^^^^ unsupported cast
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0054`.
diff --git a/src/test/ui/cast/cast-errors-issue-43825.rs b/src/test/ui/cast/cast-errors-issue-43825.rs
new file mode 100644
index 0000000..00e0da4
--- /dev/null
+++ b/src/test/ui/cast/cast-errors-issue-43825.rs
@@ -0,0 +1,7 @@
+fn main() {
+    let error = error; //~ ERROR cannot find value `error`
+
+    // These used to cause errors.
+    0 as f32;
+    0.0 as u32;
+}
diff --git a/src/test/ui/cast/cast-errors-issue-43825.stderr b/src/test/ui/cast/cast-errors-issue-43825.stderr
new file mode 100644
index 0000000..1e77f5d
--- /dev/null
+++ b/src/test/ui/cast/cast-errors-issue-43825.stderr
@@ -0,0 +1,9 @@
+error[E0425]: cannot find value `error` in this scope
+  --> $DIR/cast-errors-issue-43825.rs:2:17
+   |
+LL |     let error = error;
+   |                 ^^^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/cast/cast-from-nil.rs b/src/test/ui/cast/cast-from-nil.rs
new file mode 100644
index 0000000..b5ceef7
--- /dev/null
+++ b/src/test/ui/cast/cast-from-nil.rs
@@ -0,0 +1,2 @@
+// error-pattern: non-primitive cast: `()` as `u32`
+fn main() { let u = (assert!(true) as u32); }
diff --git a/src/test/ui/cast/cast-from-nil.stderr b/src/test/ui/cast/cast-from-nil.stderr
new file mode 100644
index 0000000..c8e3628
--- /dev/null
+++ b/src/test/ui/cast/cast-from-nil.stderr
@@ -0,0 +1,11 @@
+error[E0605]: non-primitive cast: `()` as `u32`
+  --> $DIR/cast-from-nil.rs:2:21
+   |
+LL | fn main() { let u = (assert!(true) as u32); }
+   |                     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0605`.
diff --git a/src/test/ui/cast/cast-ptr-to-int-const.rs b/src/test/ui/cast/cast-ptr-to-int-const.rs
new file mode 100644
index 0000000..ac153cb
--- /dev/null
+++ b/src/test/ui/cast/cast-ptr-to-int-const.rs
@@ -0,0 +1,11 @@
+// gate-test-const_raw_ptr_to_usize_cast
+
+fn main() {
+    const X: u32 = unsafe {
+        main as u32 //~ ERROR casting pointers to integers in constants is unstable
+    };
+    const Y: u32 = 0;
+    const Z: u32 = unsafe {
+        &Y as *const u32 as u32 //~ ERROR is unstable
+    };
+}
diff --git a/src/test/ui/cast/cast-ptr-to-int-const.stderr b/src/test/ui/cast/cast-ptr-to-int-const.stderr
new file mode 100644
index 0000000..0d4397c
--- /dev/null
+++ b/src/test/ui/cast/cast-ptr-to-int-const.stderr
@@ -0,0 +1,19 @@
+error[E0658]: casting pointers to integers in constants is unstable (see issue #51910)
+  --> $DIR/cast-ptr-to-int-const.rs:5:9
+   |
+LL |         main as u32
+   |         ^^^^^^^^^^^
+   |
+   = help: add #![feature(const_raw_ptr_to_usize_cast)] to the crate attributes to enable
+
+error[E0658]: casting pointers to integers in constants is unstable (see issue #51910)
+  --> $DIR/cast-ptr-to-int-const.rs:9:9
+   |
+LL |         &Y as *const u32 as u32
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_raw_ptr_to_usize_cast)] to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/cast/cast-rfc0401-2.rs b/src/test/ui/cast/cast-rfc0401-2.rs
new file mode 100644
index 0000000..7709aa3
--- /dev/null
+++ b/src/test/ui/cast/cast-rfc0401-2.rs
@@ -0,0 +1,8 @@
+// RFC 401 test extracted into distinct file. This is because some the
+// change to suppress "derived" errors wound up suppressing this error
+// message, since the fallback for `3` doesn't occur.
+
+fn main() {
+    let _ = 3 as bool;
+    //~^ ERROR cannot cast as `bool`
+}
diff --git a/src/test/ui/cast/cast-rfc0401-2.stderr b/src/test/ui/cast/cast-rfc0401-2.stderr
new file mode 100644
index 0000000..52f6af7
--- /dev/null
+++ b/src/test/ui/cast/cast-rfc0401-2.stderr
@@ -0,0 +1,9 @@
+error[E0054]: cannot cast as `bool`
+  --> $DIR/cast-rfc0401-2.rs:6:13
+   |
+LL |     let _ = 3 as bool;
+   |             ^^^^^^^^^ help: compare with zero instead: `3 != 0`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0054`.
diff --git a/src/test/ui/cast/cast-to-bare-fn.rs b/src/test/ui/cast/cast-to-bare-fn.rs
new file mode 100644
index 0000000..1992f26
--- /dev/null
+++ b/src/test/ui/cast/cast-to-bare-fn.rs
@@ -0,0 +1,10 @@
+fn foo(_x: isize) { }
+
+fn main() {
+    let v: u64 = 5;
+    let x = foo as extern "C" fn() -> isize;
+    //~^ ERROR non-primitive cast
+    let y = v as extern "Rust" fn(isize) -> (isize, isize);
+    //~^ ERROR non-primitive cast
+    y(x());
+}
diff --git a/src/test/ui/cast/cast-to-bare-fn.stderr b/src/test/ui/cast/cast-to-bare-fn.stderr
new file mode 100644
index 0000000..84933dc
--- /dev/null
+++ b/src/test/ui/cast/cast-to-bare-fn.stderr
@@ -0,0 +1,19 @@
+error[E0605]: non-primitive cast: `fn(isize) {foo}` as `extern "C" fn() -> isize`
+  --> $DIR/cast-to-bare-fn.rs:5:13
+   |
+LL |     let x = foo as extern "C" fn() -> isize;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+
+error[E0605]: non-primitive cast: `u64` as `fn(isize) -> (isize, isize)`
+  --> $DIR/cast-to-bare-fn.rs:7:13
+   |
+LL |     let y = v as extern "Rust" fn(isize) -> (isize, isize);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0605`.
diff --git a/src/test/ui/cast/cast-to-nil.rs b/src/test/ui/cast/cast-to-nil.rs
new file mode 100644
index 0000000..085bb09
--- /dev/null
+++ b/src/test/ui/cast/cast-to-nil.rs
@@ -0,0 +1,2 @@
+// error-pattern: non-primitive cast: `u32` as `()`
+fn main() { let u = 0u32 as (); }
diff --git a/src/test/ui/cast/cast-to-nil.stderr b/src/test/ui/cast/cast-to-nil.stderr
new file mode 100644
index 0000000..478f6b6
--- /dev/null
+++ b/src/test/ui/cast/cast-to-nil.stderr
@@ -0,0 +1,11 @@
+error[E0605]: non-primitive cast: `u32` as `()`
+  --> $DIR/cast-to-nil.rs:2:21
+   |
+LL | fn main() { let u = 0u32 as (); }
+   |                     ^^^^^^^^^^
+   |
+   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0605`.
diff --git a/src/test/ui/cast/cast-to-unsized-trait-object-suggestion.rs b/src/test/ui/cast/cast-to-unsized-trait-object-suggestion.rs
new file mode 100644
index 0000000..ac859c5
--- /dev/null
+++ b/src/test/ui/cast/cast-to-unsized-trait-object-suggestion.rs
@@ -0,0 +1,4 @@
+fn main() {
+    &1 as Send; //~ ERROR cast to unsized
+    Box::new(1) as Send; //~ ERROR cast to unsized
+}
diff --git a/src/test/ui/cast/cast-to-unsized-trait-object-suggestion.stderr b/src/test/ui/cast/cast-to-unsized-trait-object-suggestion.stderr
new file mode 100644
index 0000000..bd7a0e1
--- /dev/null
+++ b/src/test/ui/cast/cast-to-unsized-trait-object-suggestion.stderr
@@ -0,0 +1,19 @@
+error[E0620]: cast to unsized type: `&{integer}` as `dyn std::marker::Send`
+  --> $DIR/cast-to-unsized-trait-object-suggestion.rs:2:5
+   |
+LL |     &1 as Send;
+   |     ^^^^^^----
+   |           |
+   |           help: try casting to a reference instead: `&Send`
+
+error[E0620]: cast to unsized type: `std::boxed::Box<{integer}>` as `dyn std::marker::Send`
+  --> $DIR/cast-to-unsized-trait-object-suggestion.rs:3:5
+   |
+LL |     Box::new(1) as Send;
+   |     ^^^^^^^^^^^^^^^----
+   |                    |
+   |                    help: try casting to a `Box` instead: `Box<Send>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0620`.
diff --git a/src/test/ui/cast_char.rs b/src/test/ui/cast_char.rs
new file mode 100644
index 0000000..8c319af
--- /dev/null
+++ b/src/test/ui/cast_char.rs
@@ -0,0 +1,10 @@
+#![deny(overflowing_literals)]
+
+fn main() {
+    const XYZ: char = 0x1F888 as char;
+    //~^ ERROR only u8 can be cast into char
+    const XY: char = 129160 as char;
+    //~^ ERROR only u8 can be cast into char
+    const ZYX: char = '\u{01F888}';
+    println!("{}", XYZ);
+}
diff --git a/src/test/ui/cast_char.stderr b/src/test/ui/cast_char.stderr
new file mode 100644
index 0000000..f0c9b89
--- /dev/null
+++ b/src/test/ui/cast_char.stderr
@@ -0,0 +1,20 @@
+error: only u8 can be cast into char
+  --> $DIR/cast_char.rs:4:23
+   |
+LL |     const XYZ: char = 0x1F888 as char;
+   |                       ^^^^^^^^^^^^^^^ help: use a char literal instead: `'\u{1F888}'`
+   |
+note: lint level defined here
+  --> $DIR/cast_char.rs:1:9
+   |
+LL | #![deny(overflowing_literals)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: only u8 can be cast into char
+  --> $DIR/cast_char.rs:6:22
+   |
+LL |     const XY: char = 129160 as char;
+   |                      ^^^^^^^^^^^^^^ help: use a char literal instead: `'\u{1F888}'`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/casts-differing-anon.rs b/src/test/ui/casts-differing-anon.rs
new file mode 100644
index 0000000..cba1781
--- /dev/null
+++ b/src/test/ui/casts-differing-anon.rs
@@ -0,0 +1,22 @@
+use std::fmt;
+
+fn foo() -> Box<impl fmt::Debug+?Sized> {
+    let x : Box<[u8]> = Box::new([0]);
+    x
+}
+fn bar() -> Box<impl fmt::Debug+?Sized> {
+    let y: Box<fmt::Debug> = Box::new([0]);
+    y
+}
+
+fn main() {
+    let f = foo();
+    let b = bar();
+
+    // this is an `*mut [u8]` in practice
+    let f_raw : *mut _ = Box::into_raw(f);
+    // this is an `*mut fmt::Debug` in practice
+    let mut b_raw = Box::into_raw(b);
+    // ... and they should not be mixable
+    b_raw = f_raw as *mut _; //~ ERROR is invalid
+}
diff --git a/src/test/ui/casts-differing-anon.stderr b/src/test/ui/casts-differing-anon.stderr
new file mode 100644
index 0000000..fbbb8e3
--- /dev/null
+++ b/src/test/ui/casts-differing-anon.stderr
@@ -0,0 +1,11 @@
+error[E0606]: casting `*mut impl std::fmt::Debug+?Sized` as `*mut impl std::fmt::Debug+?Sized` is invalid
+  --> $DIR/casts-differing-anon.rs:21:13
+   |
+LL |     b_raw = f_raw as *mut _;
+   |             ^^^^^^^^^^^^^^^
+   |
+   = note: vtable kinds may not match
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0606`.
diff --git a/src/test/ui/casts-issue-46365.rs b/src/test/ui/casts-issue-46365.rs
new file mode 100644
index 0000000..2e7c26b
--- /dev/null
+++ b/src/test/ui/casts-issue-46365.rs
@@ -0,0 +1,7 @@
+struct Lorem {
+    ipsum: Ipsum //~ ERROR cannot find type `Ipsum`
+}
+
+fn main() {
+    let _foo: *mut Lorem = 0 as *mut _; // no error here
+}
diff --git a/src/test/ui/casts-issue-46365.stderr b/src/test/ui/casts-issue-46365.stderr
new file mode 100644
index 0000000..8417547
--- /dev/null
+++ b/src/test/ui/casts-issue-46365.stderr
@@ -0,0 +1,9 @@
+error[E0412]: cannot find type `Ipsum` in this scope
+  --> $DIR/casts-issue-46365.rs:2:12
+   |
+LL |     ipsum: Ipsum
+   |            ^^^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/src/test/ui/cdylib-deps-must-be-static.rs b/src/test/ui/cdylib-deps-must-be-static.rs
new file mode 100644
index 0000000..241cc96
--- /dev/null
+++ b/src/test/ui/cdylib-deps-must-be-static.rs
@@ -0,0 +1,9 @@
+// error-pattern: crate `cdylib_dep` required to be available in rlib format, but was not found
+// aux-build:cdylib-dep.rs
+// ignore-musl
+// ignore-cloudabi
+// ignore-emscripten
+
+#![crate_type = "cdylib"]
+
+extern crate cdylib_dep;
diff --git a/src/test/ui/cdylib-deps-must-be-static.stderr b/src/test/ui/cdylib-deps-must-be-static.stderr
new file mode 100644
index 0000000..a1dc8e9
--- /dev/null
+++ b/src/test/ui/cdylib-deps-must-be-static.stderr
@@ -0,0 +1,4 @@
+error: crate `cdylib_dep` required to be available in rlib format, but was not found in this form
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/chalkify/lower_env1.rs b/src/test/ui/chalkify/lower_env1.rs
new file mode 100644
index 0000000..afb6bdd
--- /dev/null
+++ b/src/test/ui/chalkify/lower_env1.rs
@@ -0,0 +1,14 @@
+#![feature(rustc_attrs)]
+#![allow(dead_code)]
+
+trait Foo { }
+
+#[rustc_dump_program_clauses] //~ ERROR program clause dump
+trait Bar where Self: Foo { }
+
+#[rustc_dump_env_program_clauses] //~ ERROR program clause dump
+fn bar<T: Bar + ?Sized>() {
+}
+
+fn main() {
+}
diff --git a/src/test/ui/chalkify/lower_env1.stderr b/src/test/ui/chalkify/lower_env1.stderr
new file mode 100644
index 0000000..bc426e0
--- /dev/null
+++ b/src/test/ui/chalkify/lower_env1.stderr
@@ -0,0 +1,22 @@
+error: program clause dump
+  --> $DIR/lower_env1.rs:6:1
+   |
+LL | #[rustc_dump_program_clauses]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: forall<Self> { FromEnv(Self: Foo) :- FromEnv(Self: Bar). }
+   = note: forall<Self> { Implemented(Self: Bar) :- FromEnv(Self: Bar). }
+   = note: forall<Self> { WellFormed(Self: Bar) :- Implemented(Self: Bar), WellFormed(Self: Foo). }
+
+error: program clause dump
+  --> $DIR/lower_env1.rs:9:1
+   |
+LL | #[rustc_dump_env_program_clauses]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: forall<Self> { FromEnv(Self: Foo) :- FromEnv(Self: Bar). }
+   = note: forall<Self> { Implemented(Self: Bar) :- FromEnv(Self: Bar). }
+   = note: forall<Self> { Implemented(Self: Foo) :- FromEnv(Self: Foo). }
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/chalkify/lower_env2.rs b/src/test/ui/chalkify/lower_env2.rs
new file mode 100644
index 0000000..a067575
--- /dev/null
+++ b/src/test/ui/chalkify/lower_env2.rs
@@ -0,0 +1,16 @@
+#![feature(rustc_attrs)]
+#![allow(dead_code)]
+
+trait Foo { }
+
+#[rustc_dump_program_clauses] //~ ERROR program clause dump
+struct S<'a, T: ?Sized> where T: Foo {
+    data: &'a T,
+}
+
+#[rustc_dump_env_program_clauses] //~ ERROR program clause dump
+fn bar<T: Foo>(_x: S<'_, T>) { // note that we have an implicit `T: Sized` bound
+}
+
+fn main() {
+}
diff --git a/src/test/ui/chalkify/lower_env2.stderr b/src/test/ui/chalkify/lower_env2.stderr
new file mode 100644
index 0000000..613a568
--- /dev/null
+++ b/src/test/ui/chalkify/lower_env2.stderr
@@ -0,0 +1,23 @@
+error: program clause dump
+  --> $DIR/lower_env2.rs:6:1
+   |
+LL | #[rustc_dump_program_clauses]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: forall<'a, T> { FromEnv(T: Foo) :- FromEnv(S<'a, T>). }
+   = note: forall<'a, T> { TypeOutlives(T: 'a) :- FromEnv(S<'a, T>). }
+   = note: forall<'a, T> { WellFormed(S<'a, T>) :- WellFormed(T: Foo), TypeOutlives(T: 'a). }
+
+error: program clause dump
+  --> $DIR/lower_env2.rs:11:1
+   |
+LL | #[rustc_dump_env_program_clauses]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: forall<'a, T> { FromEnv(T: Foo) :- FromEnv(S<'a, T>). }
+   = note: forall<'a, T> { TypeOutlives(T: 'a) :- FromEnv(S<'a, T>). }
+   = note: forall<Self> { Implemented(Self: Foo) :- FromEnv(Self: Foo). }
+   = note: forall<Self> { Implemented(Self: std::marker::Sized) :- FromEnv(Self: std::marker::Sized). }
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/chalkify/lower_env3.rs b/src/test/ui/chalkify/lower_env3.rs
new file mode 100644
index 0000000..61ed3cb
--- /dev/null
+++ b/src/test/ui/chalkify/lower_env3.rs
@@ -0,0 +1,16 @@
+#![feature(rustc_attrs)]
+#![allow(dead_code)]
+
+trait Foo {
+    #[rustc_dump_env_program_clauses] //~ ERROR program clause dump
+    fn foo(&self);
+}
+
+impl<T> Foo for T where T: Clone {
+    #[rustc_dump_env_program_clauses] //~ ERROR program clause dump
+    fn foo(&self) {
+    }
+}
+
+fn main() {
+}
diff --git a/src/test/ui/chalkify/lower_env3.stderr b/src/test/ui/chalkify/lower_env3.stderr
new file mode 100644
index 0000000..a1fc83b
--- /dev/null
+++ b/src/test/ui/chalkify/lower_env3.stderr
@@ -0,0 +1,20 @@
+error: program clause dump
+  --> $DIR/lower_env3.rs:5:5
+   |
+LL |     #[rustc_dump_env_program_clauses]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: forall<Self> { Implemented(Self: Foo) :- FromEnv(Self: Foo). }
+
+error: program clause dump
+  --> $DIR/lower_env3.rs:10:5
+   |
+LL |     #[rustc_dump_env_program_clauses]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: forall<Self> { FromEnv(Self: std::marker::Sized) :- FromEnv(Self: std::clone::Clone). }
+   = note: forall<Self> { Implemented(Self: std::clone::Clone) :- FromEnv(Self: std::clone::Clone). }
+   = note: forall<Self> { Implemented(Self: std::marker::Sized) :- FromEnv(Self: std::marker::Sized). }
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/chalkify/lower_impl.rs b/src/test/ui/chalkify/lower_impl.rs
new file mode 100644
index 0000000..1bd44a9
--- /dev/null
+++ b/src/test/ui/chalkify/lower_impl.rs
@@ -0,0 +1,19 @@
+#![feature(rustc_attrs)]
+
+trait Foo { }
+
+#[rustc_dump_program_clauses] //~ ERROR program clause dump
+impl<T: 'static> Foo for T where T: Iterator<Item = i32> { }
+
+trait Bar {
+    type Assoc;
+}
+
+impl<T> Bar for T where T: Iterator<Item = i32> {
+    #[rustc_dump_program_clauses] //~ ERROR program clause dump
+    type Assoc = Vec<T>;
+}
+
+fn main() {
+    println!("hello");
+}
diff --git a/src/test/ui/chalkify/lower_impl.stderr b/src/test/ui/chalkify/lower_impl.stderr
new file mode 100644
index 0000000..d6827fb
--- /dev/null
+++ b/src/test/ui/chalkify/lower_impl.stderr
@@ -0,0 +1,18 @@
+error: program clause dump
+  --> $DIR/lower_impl.rs:5:1
+   |
+LL | #[rustc_dump_program_clauses]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: forall<T> { Implemented(T: Foo) :- ProjectionEq(<T as std::iter::Iterator>::Item == i32), TypeOutlives(T: 'static), Implemented(T: std::iter::Iterator), Implemented(T: std::marker::Sized). }
+
+error: program clause dump
+  --> $DIR/lower_impl.rs:13:5
+   |
+LL |     #[rustc_dump_program_clauses]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: forall<T> { Normalize(<T as Bar>::Assoc -> std::vec::Vec<T>) :- Implemented(T: Bar). }
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/chalkify/lower_struct.rs b/src/test/ui/chalkify/lower_struct.rs
new file mode 100644
index 0000000..aecccea
--- /dev/null
+++ b/src/test/ui/chalkify/lower_struct.rs
@@ -0,0 +1,8 @@
+#![feature(rustc_attrs)]
+
+#[rustc_dump_program_clauses] //~ ERROR program clause dump
+struct Foo<'a, T> where Box<T>: Clone {
+    _x: std::marker::PhantomData<&'a T>,
+}
+
+fn main() { }
diff --git a/src/test/ui/chalkify/lower_struct.stderr b/src/test/ui/chalkify/lower_struct.stderr
new file mode 100644
index 0000000..0331c2f
--- /dev/null
+++ b/src/test/ui/chalkify/lower_struct.stderr
@@ -0,0 +1,13 @@
+error: program clause dump
+  --> $DIR/lower_struct.rs:3:1
+   |
+LL | #[rustc_dump_program_clauses]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: forall<'a, T> { FromEnv(T: std::marker::Sized) :- FromEnv(Foo<'a, T>). }
+   = note: forall<'a, T> { FromEnv(std::boxed::Box<T>: std::clone::Clone) :- FromEnv(Foo<'a, T>). }
+   = note: forall<'a, T> { TypeOutlives(T: 'a) :- FromEnv(Foo<'a, T>). }
+   = note: forall<'a, T> { WellFormed(Foo<'a, T>) :- WellFormed(T: std::marker::Sized), WellFormed(std::boxed::Box<T>: std::clone::Clone), TypeOutlives(T: 'a). }
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/chalkify/lower_trait.rs b/src/test/ui/chalkify/lower_trait.rs
new file mode 100644
index 0000000..0e19560
--- /dev/null
+++ b/src/test/ui/chalkify/lower_trait.rs
@@ -0,0 +1,13 @@
+#![feature(rustc_attrs)]
+
+trait Bar { }
+
+#[rustc_dump_program_clauses] //~ ERROR program clause dump
+trait Foo<S, T: ?Sized> {
+    #[rustc_dump_program_clauses] //~ ERROR program clause dump
+    type Assoc: Bar + ?Sized;
+}
+
+fn main() {
+    println!("hello");
+}
diff --git a/src/test/ui/chalkify/lower_trait.stderr b/src/test/ui/chalkify/lower_trait.stderr
new file mode 100644
index 0000000..ed3bded3
--- /dev/null
+++ b/src/test/ui/chalkify/lower_trait.stderr
@@ -0,0 +1,24 @@
+error: program clause dump
+  --> $DIR/lower_trait.rs:5:1
+   |
+LL | #[rustc_dump_program_clauses]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: forall<Self, S, T> { FromEnv(<Self as Foo<S, T>>::Assoc: Bar) :- FromEnv(Self: Foo<S, T>). }
+   = note: forall<Self, S, T> { FromEnv(S: std::marker::Sized) :- FromEnv(Self: Foo<S, T>). }
+   = note: forall<Self, S, T> { Implemented(Self: Foo<S, T>) :- FromEnv(Self: Foo<S, T>). }
+   = note: forall<Self, S, T> { WellFormed(Self: Foo<S, T>) :- Implemented(Self: Foo<S, T>), WellFormed(S: std::marker::Sized), WellFormed(<Self as Foo<S, T>>::Assoc: Bar). }
+
+error: program clause dump
+  --> $DIR/lower_trait.rs:7:5
+   |
+LL |     #[rustc_dump_program_clauses]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: forall<Self, S, T, ^3> { ProjectionEq(<Self as Foo<S, T>>::Assoc == ^3) :- Normalize(<Self as Foo<S, T>>::Assoc -> ^3). }
+   = note: forall<Self, S, T> { FromEnv(Self: Foo<S, T>) :- FromEnv(Unnormalized(<Self as Foo<S, T>>::Assoc)). }
+   = note: forall<Self, S, T> { ProjectionEq(<Self as Foo<S, T>>::Assoc == Unnormalized(<Self as Foo<S, T>>::Assoc)). }
+   = note: forall<Self, S, T> { WellFormed(Unnormalized(<Self as Foo<S, T>>::Assoc)) :- WellFormed(Self: Foo<S, T>). }
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/chalkify/lower_trait_higher_rank.rs b/src/test/ui/chalkify/lower_trait_higher_rank.rs
new file mode 100644
index 0000000..715f096
--- /dev/null
+++ b/src/test/ui/chalkify/lower_trait_higher_rank.rs
@@ -0,0 +1,10 @@
+#![feature(rustc_attrs)]
+
+#[rustc_dump_program_clauses] //~ ERROR program clause dump
+trait Foo<F: ?Sized> where for<'a> F: Fn(&'a (u8, u16)) -> &'a u8
+{
+}
+
+fn main() {
+    println!("hello");
+}
diff --git a/src/test/ui/chalkify/lower_trait_higher_rank.stderr b/src/test/ui/chalkify/lower_trait_higher_rank.stderr
new file mode 100644
index 0000000..79bbc9f
--- /dev/null
+++ b/src/test/ui/chalkify/lower_trait_higher_rank.stderr
@@ -0,0 +1,13 @@
+error: program clause dump
+  --> $DIR/lower_trait_higher_rank.rs:3:1
+   |
+LL | #[rustc_dump_program_clauses]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: forall<'a, Self, F> { FromEnv(F: std::ops::Fn<(&'a (u8, u16),)>) :- FromEnv(Self: Foo<F>). }
+   = note: forall<'a, Self, F> { ProjectionEq(<F as std::ops::FnOnce<(&'a (u8, u16),)>>::Output == &'a u8) :- FromEnv(Self: Foo<F>). }
+   = note: forall<Self, F> { Implemented(Self: Foo<F>) :- FromEnv(Self: Foo<F>). }
+   = note: forall<Self, F> { WellFormed(Self: Foo<F>) :- Implemented(Self: Foo<F>), forall<'a> { WellFormed(F: std::ops::Fn<(&'a (u8, u16),)>) }, forall<'a> { ProjectionEq(<F as std::ops::FnOnce<(&'a (u8, u16),)>>::Output == &'a u8) }. }
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/chalkify/lower_trait_where_clause.rs b/src/test/ui/chalkify/lower_trait_where_clause.rs
new file mode 100644
index 0000000..78fa39f
--- /dev/null
+++ b/src/test/ui/chalkify/lower_trait_where_clause.rs
@@ -0,0 +1,17 @@
+#![feature(rustc_attrs)]
+
+use std::borrow::Borrow;
+
+#[rustc_dump_program_clauses] //~ ERROR program clause dump
+trait Foo<'a, 'b, T, U>
+where
+    T: Borrow<U> + ?Sized,
+    U: ?Sized + 'b,
+    'a: 'b,
+    Box<T>:, // NOTE(#53696) this checks an empty list of bounds.
+{
+}
+
+fn main() {
+    println!("hello");
+}
diff --git a/src/test/ui/chalkify/lower_trait_where_clause.stderr b/src/test/ui/chalkify/lower_trait_where_clause.stderr
new file mode 100644
index 0000000..408f371
--- /dev/null
+++ b/src/test/ui/chalkify/lower_trait_where_clause.stderr
@@ -0,0 +1,15 @@
+error: program clause dump
+  --> $DIR/lower_trait_where_clause.rs:5:1
+   |
+LL | #[rustc_dump_program_clauses]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: forall<'a, 'b, Self, T, U> { FromEnv(T: std::borrow::Borrow<U>) :- FromEnv(Self: Foo<'a, 'b, T, U>). }
+   = note: forall<'a, 'b, Self, T, U> { Implemented(Self: Foo<'a, 'b, T, U>) :- FromEnv(Self: Foo<'a, 'b, T, U>). }
+   = note: forall<'a, 'b, Self, T, U> { RegionOutlives('a: 'b) :- FromEnv(Self: Foo<'a, 'b, T, U>). }
+   = note: forall<'a, 'b, Self, T, U> { TypeOutlives(U: 'b) :- FromEnv(Self: Foo<'a, 'b, T, U>). }
+   = note: forall<'a, 'b, Self, T, U> { TypeOutlives(std::boxed::Box<T>: '<empty>) :- FromEnv(Self: Foo<'a, 'b, T, U>). }
+   = note: forall<'a, 'b, Self, T, U> { WellFormed(Self: Foo<'a, 'b, T, U>) :- Implemented(Self: Foo<'a, 'b, T, U>), WellFormed(T: std::borrow::Borrow<U>), TypeOutlives(U: 'b), RegionOutlives('a: 'b), TypeOutlives(std::boxed::Box<T>: '<empty>). }
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/chalkify/type_inference.rs b/src/test/ui/chalkify/type_inference.rs
new file mode 100644
index 0000000..62a53ec
--- /dev/null
+++ b/src/test/ui/chalkify/type_inference.rs
@@ -0,0 +1,26 @@
+// compile-flags: -Z chalk
+
+trait Foo { }
+impl Foo for i32 { }
+
+trait Bar { }
+impl Bar for i32 { }
+impl Bar for u32 { }
+
+fn only_foo<T: Foo>(_x: T) { }
+
+fn only_bar<T: Bar>(_x: T) { }
+
+fn main() {
+    let x = 5.0;
+
+    // The only type which implements `Foo` is `i32`, so the chalk trait solver
+    // is expecting a variable of type `i32`. This behavior differs from the
+    // old-style trait solver. I guess this will change, that's why I'm
+    // adding that test.
+    only_foo(x); //~ ERROR mismatched types
+
+    // Here we have two solutions so we get back the behavior of the old-style
+    // trait solver.
+    only_bar(x); //~ ERROR the trait bound `{float}: Bar` is not satisfied
+}
diff --git a/src/test/ui/chalkify/type_inference.stderr b/src/test/ui/chalkify/type_inference.stderr
new file mode 100644
index 0000000..d1d56d3
--- /dev/null
+++ b/src/test/ui/chalkify/type_inference.stderr
@@ -0,0 +1,28 @@
+error[E0308]: mismatched types
+  --> $DIR/type_inference.rs:21:14
+   |
+LL |     only_foo(x);
+   |              ^ expected i32, found floating-point number
+   |
+   = note: expected type `i32`
+              found type `{float}`
+
+error[E0277]: the trait bound `{float}: Bar` is not satisfied
+  --> $DIR/type_inference.rs:25:5
+   |
+LL |     only_bar(x);
+   |     ^^^^^^^^ the trait `Bar` is not implemented for `{float}`
+   |
+   = help: the following implementations were found:
+             <i32 as Bar>
+             <u32 as Bar>
+note: required by `only_bar`
+  --> $DIR/type_inference.rs:12:1
+   |
+LL | fn only_bar<T: Bar>(_x: T) { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0277, E0308.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/changing-crates.rs b/src/test/ui/changing-crates.rs
new file mode 100644
index 0000000..60c043b
--- /dev/null
+++ b/src/test/ui/changing-crates.rs
@@ -0,0 +1,12 @@
+// ignore-msvc FIXME #31306
+
+// note that these aux-build directives must be in this order
+// aux-build:changing-crates-a1.rs
+// aux-build:changing-crates-b.rs
+// aux-build:changing-crates-a2.rs
+// normalize-stderr-test: "(crate `(\w+)`:) .*" -> "$1 $$PATH_$2"
+
+extern crate a;
+extern crate b; //~ ERROR: found possibly newer version of crate `a` which `b` depends on
+
+fn main() {}
diff --git a/src/test/ui/changing-crates.stderr b/src/test/ui/changing-crates.stderr
new file mode 100644
index 0000000..6339309
--- /dev/null
+++ b/src/test/ui/changing-crates.stderr
@@ -0,0 +1,14 @@
+error[E0460]: found possibly newer version of crate `a` which `b` depends on
+  --> $DIR/changing-crates.rs:10:1
+   |
+LL | extern crate b;
+   | ^^^^^^^^^^^^^^^
+   |
+   = note: perhaps that crate needs to be recompiled?
+   = note: the following crate versions were found:
+           crate `a`: $PATH_a
+           crate `b`: $PATH_b
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0460`.
diff --git a/src/test/ui/check-static-immutable-mut-slices.rs b/src/test/ui/check-static-immutable-mut-slices.rs
new file mode 100644
index 0000000..d5e9fb2
--- /dev/null
+++ b/src/test/ui/check-static-immutable-mut-slices.rs
@@ -0,0 +1,6 @@
+// Checks that immutable static items can't have mutable slices
+
+static TEST: &'static mut [isize] = &mut [];
+//~^ ERROR references in statics may only refer to immutable values
+
+pub fn main() { }
diff --git a/src/test/ui/check-static-immutable-mut-slices.stderr b/src/test/ui/check-static-immutable-mut-slices.stderr
new file mode 100644
index 0000000..4f4bf16
--- /dev/null
+++ b/src/test/ui/check-static-immutable-mut-slices.stderr
@@ -0,0 +1,9 @@
+error[E0017]: references in statics may only refer to immutable values
+  --> $DIR/check-static-immutable-mut-slices.rs:3:37
+   |
+LL | static TEST: &'static mut [isize] = &mut [];
+   |                                     ^^^^^^^ statics require immutable values
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0017`.
diff --git a/src/test/ui/check-static-values-constraints.nll.stderr b/src/test/ui/check-static-values-constraints.nll.stderr
new file mode 100644
index 0000000..fe014fa
--- /dev/null
+++ b/src/test/ui/check-static-values-constraints.nll.stderr
@@ -0,0 +1,112 @@
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/check-static-values-constraints.rs:65:43
+   |
+LL |                                           ..SafeStruct{field1: SafeEnum::Variant3(WithDtor),
+   |  ___________________________________________^
+LL | |
+LL | |                                                      field2: SafeEnum::Variant1}};
+   | |________________________________________________________________________________^ statics cannot evaluate destructors
+
+error[E0010]: allocations are not allowed in statics
+  --> $DIR/check-static-values-constraints.rs:79:33
+   |
+LL | static STATIC11: Box<MyOwned> = box MyOwned;
+   |                                 ^^^^^^^^^^^ allocation not allowed in statics
+
+error[E0019]: static contains unimplemented expression type
+  --> $DIR/check-static-values-constraints.rs:79:37
+   |
+LL | static STATIC11: Box<MyOwned> = box MyOwned;
+   |                                     ^^^^^^^
+
+error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
+  --> $DIR/check-static-values-constraints.rs:90:32
+   |
+LL |     field2: SafeEnum::Variant4("str".to_string())
+   |                                ^^^^^^^^^^^^^^^^^
+
+error[E0010]: allocations are not allowed in statics
+  --> $DIR/check-static-values-constraints.rs:95:5
+   |
+LL |     box MyOwned,
+   |     ^^^^^^^^^^^ allocation not allowed in statics
+
+error[E0019]: static contains unimplemented expression type
+  --> $DIR/check-static-values-constraints.rs:95:9
+   |
+LL |     box MyOwned,
+   |         ^^^^^^^
+
+error[E0010]: allocations are not allowed in statics
+  --> $DIR/check-static-values-constraints.rs:97:5
+   |
+LL |     box MyOwned,
+   |     ^^^^^^^^^^^ allocation not allowed in statics
+
+error[E0019]: static contains unimplemented expression type
+  --> $DIR/check-static-values-constraints.rs:97:9
+   |
+LL |     box MyOwned,
+   |         ^^^^^^^
+
+error[E0010]: allocations are not allowed in statics
+  --> $DIR/check-static-values-constraints.rs:102:6
+   |
+LL |     &box MyOwned,
+   |      ^^^^^^^^^^^ allocation not allowed in statics
+
+error[E0019]: static contains unimplemented expression type
+  --> $DIR/check-static-values-constraints.rs:102:10
+   |
+LL |     &box MyOwned,
+   |          ^^^^^^^
+
+error[E0010]: allocations are not allowed in statics
+  --> $DIR/check-static-values-constraints.rs:104:6
+   |
+LL |     &box MyOwned,
+   |      ^^^^^^^^^^^ allocation not allowed in statics
+
+error[E0019]: static contains unimplemented expression type
+  --> $DIR/check-static-values-constraints.rs:104:10
+   |
+LL |     &box MyOwned,
+   |          ^^^^^^^
+
+error[E0010]: allocations are not allowed in statics
+  --> $DIR/check-static-values-constraints.rs:111:5
+   |
+LL |     box 3;
+   |     ^^^^^ allocation not allowed in statics
+
+error[E0019]: static contains unimplemented expression type
+  --> $DIR/check-static-values-constraints.rs:111:9
+   |
+LL |     box 3;
+   |         ^
+
+error[E0507]: cannot move out of static item
+  --> $DIR/check-static-values-constraints.rs:116:45
+   |
+LL |     let y = { static x: Box<isize> = box 3; x };
+   |                                             ^
+   |                                             |
+   |                                             cannot move out of static item
+   |                                             help: consider borrowing here: `&x`
+
+error[E0010]: allocations are not allowed in statics
+  --> $DIR/check-static-values-constraints.rs:116:38
+   |
+LL |     let y = { static x: Box<isize> = box 3; x };
+   |                                      ^^^^^ allocation not allowed in statics
+
+error[E0019]: static contains unimplemented expression type
+  --> $DIR/check-static-values-constraints.rs:116:42
+   |
+LL |     let y = { static x: Box<isize> = box 3; x };
+   |                                          ^
+
+error: aborting due to 17 previous errors
+
+Some errors occurred: E0010, E0015, E0019, E0493, E0507.
+For more information about an error, try `rustc --explain E0010`.
diff --git a/src/test/ui/check-static-values-constraints.rs b/src/test/ui/check-static-values-constraints.rs
new file mode 100644
index 0000000..acfb3b5
--- /dev/null
+++ b/src/test/ui/check-static-values-constraints.rs
@@ -0,0 +1,120 @@
+// Verifies all possible restrictions for statics values.
+
+#![allow(warnings)]
+#![feature(box_syntax)]
+
+use std::marker;
+
+struct WithDtor;
+
+impl Drop for WithDtor {
+    fn drop(&mut self) {}
+}
+
+// This enum will be used to test the following rules:
+// 1. Variants are safe for static
+// 2. Expr calls are allowed as long as they arguments are safe
+// 3. Expr calls with unsafe arguments for statics are rejected
+enum SafeEnum {
+    Variant1,
+    Variant2(isize),
+    Variant3(WithDtor),
+    Variant4(String)
+}
+
+// These should be ok
+static STATIC1: SafeEnum = SafeEnum::Variant1;
+static STATIC2: SafeEnum = SafeEnum::Variant2(0);
+static STATIC3: SafeEnum = SafeEnum::Variant3(WithDtor);
+
+enum UnsafeEnum {
+    Variant5,
+    Variant6(isize)
+}
+
+impl Drop for UnsafeEnum {
+    fn drop(&mut self) {}
+}
+
+
+static STATIC4: UnsafeEnum = UnsafeEnum::Variant5;
+static STATIC5: UnsafeEnum = UnsafeEnum::Variant6(0);
+
+
+struct SafeStruct {
+    field1: SafeEnum,
+    field2: SafeEnum,
+}
+
+
+// Struct fields are safe, hence this static should be safe
+static STATIC6: SafeStruct = SafeStruct{field1: SafeEnum::Variant1, field2: SafeEnum::Variant2(0)};
+
+static STATIC7: SafeStruct = SafeStruct{field1: SafeEnum::Variant1,
+                                        field2: SafeEnum::Variant3(WithDtor)};
+
+// Test variadic constructor for structs. The base struct should be examined
+// as well as every field present in the constructor.
+// This example shouldn't fail because all the fields are safe.
+static STATIC8: SafeStruct = SafeStruct{field1: SafeEnum::Variant1,
+                                        ..SafeStruct{field1: SafeEnum::Variant1,
+                                                     field2: SafeEnum::Variant1}};
+
+// This example should fail because field1 in the base struct is not safe
+static STATIC9: SafeStruct = SafeStruct{field1: SafeEnum::Variant1,
+                                        ..SafeStruct{field1: SafeEnum::Variant3(WithDtor),
+//~^ ERROR destructors cannot be evaluated at compile-time
+                                                     field2: SafeEnum::Variant1}};
+
+struct UnsafeStruct;
+
+impl Drop for UnsafeStruct {
+    fn drop(&mut self) {}
+}
+
+static STATIC10: UnsafeStruct = UnsafeStruct;
+
+struct MyOwned;
+
+static STATIC11: Box<MyOwned> = box MyOwned;
+//~^ ERROR allocations are not allowed in statics
+//~| ERROR static contains unimplemented expression type
+
+static mut STATIC12: UnsafeStruct = UnsafeStruct;
+
+static mut STATIC13: SafeStruct = SafeStruct{field1: SafeEnum::Variant1,
+                                             field2: SafeEnum::Variant3(WithDtor)};
+
+static mut STATIC14: SafeStruct = SafeStruct {
+    field1: SafeEnum::Variant1,
+    field2: SafeEnum::Variant4("str".to_string())
+//~^ ERROR calls in statics are limited to constant functions
+};
+
+static STATIC15: &'static [Box<MyOwned>] = &[
+    box MyOwned, //~ ERROR allocations are not allowed in statics
+    //~| ERROR contains unimplemented expression
+    box MyOwned, //~ ERROR allocations are not allowed in statics
+    //~| ERROR contains unimplemented expression
+];
+
+static STATIC16: (&'static Box<MyOwned>, &'static Box<MyOwned>) = (
+    &box MyOwned, //~ ERROR allocations are not allowed in statics
+    //~| ERROR contains unimplemented expression
+    &box MyOwned, //~ ERROR allocations are not allowed in statics
+    //~| ERROR contains unimplemented expression
+);
+
+static mut STATIC17: SafeEnum = SafeEnum::Variant1;
+
+static STATIC19: Box<isize> =
+    box 3;
+//~^ ERROR allocations are not allowed in statics
+    //~| ERROR contains unimplemented expression
+
+pub fn main() {
+    let y = { static x: Box<isize> = box 3; x };
+    //~^ ERROR allocations are not allowed in statics
+    //~| ERROR cannot move out of static item
+    //~| ERROR contains unimplemented expression
+}
diff --git a/src/test/ui/check-static-values-constraints.stderr b/src/test/ui/check-static-values-constraints.stderr
new file mode 100644
index 0000000..91fe0fe
--- /dev/null
+++ b/src/test/ui/check-static-values-constraints.stderr
@@ -0,0 +1,109 @@
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/check-static-values-constraints.rs:65:43
+   |
+LL |                                           ..SafeStruct{field1: SafeEnum::Variant3(WithDtor),
+   |  ___________________________________________^
+LL | |
+LL | |                                                      field2: SafeEnum::Variant1}};
+   | |________________________________________________________________________________^ statics cannot evaluate destructors
+
+error[E0010]: allocations are not allowed in statics
+  --> $DIR/check-static-values-constraints.rs:79:33
+   |
+LL | static STATIC11: Box<MyOwned> = box MyOwned;
+   |                                 ^^^^^^^^^^^ allocation not allowed in statics
+
+error[E0019]: static contains unimplemented expression type
+  --> $DIR/check-static-values-constraints.rs:79:37
+   |
+LL | static STATIC11: Box<MyOwned> = box MyOwned;
+   |                                     ^^^^^^^
+
+error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
+  --> $DIR/check-static-values-constraints.rs:90:32
+   |
+LL |     field2: SafeEnum::Variant4("str".to_string())
+   |                                ^^^^^^^^^^^^^^^^^
+
+error[E0010]: allocations are not allowed in statics
+  --> $DIR/check-static-values-constraints.rs:95:5
+   |
+LL |     box MyOwned,
+   |     ^^^^^^^^^^^ allocation not allowed in statics
+
+error[E0019]: static contains unimplemented expression type
+  --> $DIR/check-static-values-constraints.rs:95:9
+   |
+LL |     box MyOwned,
+   |         ^^^^^^^
+
+error[E0010]: allocations are not allowed in statics
+  --> $DIR/check-static-values-constraints.rs:97:5
+   |
+LL |     box MyOwned,
+   |     ^^^^^^^^^^^ allocation not allowed in statics
+
+error[E0019]: static contains unimplemented expression type
+  --> $DIR/check-static-values-constraints.rs:97:9
+   |
+LL |     box MyOwned,
+   |         ^^^^^^^
+
+error[E0010]: allocations are not allowed in statics
+  --> $DIR/check-static-values-constraints.rs:102:6
+   |
+LL |     &box MyOwned,
+   |      ^^^^^^^^^^^ allocation not allowed in statics
+
+error[E0019]: static contains unimplemented expression type
+  --> $DIR/check-static-values-constraints.rs:102:10
+   |
+LL |     &box MyOwned,
+   |          ^^^^^^^
+
+error[E0010]: allocations are not allowed in statics
+  --> $DIR/check-static-values-constraints.rs:104:6
+   |
+LL |     &box MyOwned,
+   |      ^^^^^^^^^^^ allocation not allowed in statics
+
+error[E0019]: static contains unimplemented expression type
+  --> $DIR/check-static-values-constraints.rs:104:10
+   |
+LL |     &box MyOwned,
+   |          ^^^^^^^
+
+error[E0010]: allocations are not allowed in statics
+  --> $DIR/check-static-values-constraints.rs:111:5
+   |
+LL |     box 3;
+   |     ^^^^^ allocation not allowed in statics
+
+error[E0019]: static contains unimplemented expression type
+  --> $DIR/check-static-values-constraints.rs:111:9
+   |
+LL |     box 3;
+   |         ^
+
+error[E0507]: cannot move out of static item
+  --> $DIR/check-static-values-constraints.rs:116:45
+   |
+LL |     let y = { static x: Box<isize> = box 3; x };
+   |                                             ^ cannot move out of static item
+
+error[E0010]: allocations are not allowed in statics
+  --> $DIR/check-static-values-constraints.rs:116:38
+   |
+LL |     let y = { static x: Box<isize> = box 3; x };
+   |                                      ^^^^^ allocation not allowed in statics
+
+error[E0019]: static contains unimplemented expression type
+  --> $DIR/check-static-values-constraints.rs:116:42
+   |
+LL |     let y = { static x: Box<isize> = box 3; x };
+   |                                          ^
+
+error: aborting due to 17 previous errors
+
+Some errors occurred: E0010, E0015, E0019, E0493, E0507.
+For more information about an error, try `rustc --explain E0010`.
diff --git a/src/test/ui/check_match/issue-35609.rs b/src/test/ui/check_match/issue-35609.rs
new file mode 100644
index 0000000..8ef75e3
--- /dev/null
+++ b/src/test/ui/check_match/issue-35609.rs
@@ -0,0 +1,43 @@
+enum Enum {
+    A, B, C, D, E, F
+}
+use Enum::*;
+
+struct S(Enum, ());
+struct Sd { x: Enum, y: () }
+
+fn main() {
+    match (A, ()) { //~ ERROR non-exhaustive
+        (A, _) => {}
+    }
+
+    match (A, A) { //~ ERROR non-exhaustive
+        (_, A) => {}
+    }
+
+    match ((A, ()), ()) { //~ ERROR non-exhaustive
+        ((A, ()), _) => {}
+    }
+
+    match ((A, ()), A) { //~ ERROR non-exhaustive
+        ((A, ()), _) => {}
+    }
+
+    match ((A, ()), ()) { //~ ERROR non-exhaustive
+        ((A, _), _) => {}
+    }
+
+
+    match S(A, ()) { //~ ERROR non-exhaustive
+        S(A, _) => {}
+    }
+
+    match (Sd { x: A, y: () }) { //~ ERROR non-exhaustive
+        Sd { x: A, y: _ } => {}
+    }
+
+    match Some(A) { //~ ERROR non-exhaustive
+        Some(A) => (),
+        None => ()
+    }
+}
diff --git a/src/test/ui/check_match/issue-35609.stderr b/src/test/ui/check_match/issue-35609.stderr
new file mode 100644
index 0000000..af22535
--- /dev/null
+++ b/src/test/ui/check_match/issue-35609.stderr
@@ -0,0 +1,73 @@
+error[E0004]: non-exhaustive patterns: `(B, _)`, `(C, _)`, `(D, _)` and 2 more not covered
+  --> $DIR/issue-35609.rs:10:11
+   |
+LL |     match (A, ()) {
+   |           ^^^^^^^ patterns `(B, _)`, `(C, _)`, `(D, _)` and 2 more not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `(_, B)`, `(_, C)`, `(_, D)` and 2 more not covered
+  --> $DIR/issue-35609.rs:14:11
+   |
+LL |     match (A, A) {
+   |           ^^^^^^ patterns `(_, B)`, `(_, C)`, `(_, D)` and 2 more not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `((B, _), _)`, `((C, _), _)`, `((D, _), _)` and 2 more not covered
+  --> $DIR/issue-35609.rs:18:11
+   |
+LL |     match ((A, ()), ()) {
+   |           ^^^^^^^^^^^^^ patterns `((B, _), _)`, `((C, _), _)`, `((D, _), _)` and 2 more not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `((B, _), _)`, `((C, _), _)`, `((D, _), _)` and 2 more not covered
+  --> $DIR/issue-35609.rs:22:11
+   |
+LL |     match ((A, ()), A) {
+   |           ^^^^^^^^^^^^ patterns `((B, _), _)`, `((C, _), _)`, `((D, _), _)` and 2 more not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `((B, _), _)`, `((C, _), _)`, `((D, _), _)` and 2 more not covered
+  --> $DIR/issue-35609.rs:26:11
+   |
+LL |     match ((A, ()), ()) {
+   |           ^^^^^^^^^^^^^ patterns `((B, _), _)`, `((C, _), _)`, `((D, _), _)` and 2 more not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `S(B, _)`, `S(C, _)`, `S(D, _)` and 2 more not covered
+  --> $DIR/issue-35609.rs:31:11
+   |
+LL | struct S(Enum, ());
+   | ------------------- `S` defined here
+...
+LL |     match S(A, ()) {
+   |           ^^^^^^^^ patterns `S(B, _)`, `S(C, _)`, `S(D, _)` and 2 more not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `Sd { x: B, .. }`, `Sd { x: C, .. }`, `Sd { x: D, .. }` and 2 more not covered
+  --> $DIR/issue-35609.rs:35:11
+   |
+LL | struct Sd { x: Enum, y: () }
+   | ---------------------------- `Sd` defined here
+...
+LL |     match (Sd { x: A, y: () }) {
+   |           ^^^^^^^^^^^^^^^^^^^^ patterns `Sd { x: B, .. }`, `Sd { x: C, .. }`, `Sd { x: D, .. }` and 2 more not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `Some(B)`, `Some(C)`, `Some(D)` and 2 more not covered
+  --> $DIR/issue-35609.rs:39:11
+   |
+LL |     match Some(A) {
+   |           ^^^^^^^ patterns `Some(B)`, `Some(C)`, `Some(D)` and 2 more not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/check_match/issue-43253.rs b/src/test/ui/check_match/issue-43253.rs
new file mode 100644
index 0000000..5d08424
--- /dev/null
+++ b/src/test/ui/check_match/issue-43253.rs
@@ -0,0 +1,44 @@
+// compile-pass
+
+#![feature(exclusive_range_pattern)]
+#![warn(unreachable_patterns)]
+
+fn main() {
+    // These cases should generate no warning.
+    match 10 {
+        1..10 => {},
+        10 => {},
+        _ => {},
+    }
+
+    match 10 {
+        1..10 => {},
+        9..=10 => {},
+        _ => {},
+    }
+
+    match 10 {
+        1..10 => {},
+        10..=10 => {},
+        _ => {},
+    }
+
+    // These cases should generate an "unreachable pattern" warning.
+    match 10 {
+        1..10 => {},
+        9 => {},
+        _ => {},
+    }
+
+    match 10 {
+        1..10 => {},
+        8..=9 => {},
+        _ => {},
+    }
+
+    match 10 {
+        1..10 => {},
+        9..=9 => {},
+        _ => {},
+    }
+}
diff --git a/src/test/ui/check_match/issue-43253.stderr b/src/test/ui/check_match/issue-43253.stderr
new file mode 100644
index 0000000..d961f62
--- /dev/null
+++ b/src/test/ui/check_match/issue-43253.stderr
@@ -0,0 +1,24 @@
+warning: unreachable pattern
+  --> $DIR/issue-43253.rs:29:9
+   |
+LL |         9 => {},
+   |         ^
+   |
+note: lint level defined here
+  --> $DIR/issue-43253.rs:4:9
+   |
+LL | #![warn(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+warning: unreachable pattern
+  --> $DIR/issue-43253.rs:35:9
+   |
+LL |         8..=9 => {},
+   |         ^^^^^
+
+warning: unreachable pattern
+  --> $DIR/issue-43253.rs:41:9
+   |
+LL |         9..=9 => {},
+   |         ^^^^^
+
diff --git a/src/test/ui/class-cast-to-trait.rs b/src/test/ui/class-cast-to-trait.rs
new file mode 100644
index 0000000..3ae4987
--- /dev/null
+++ b/src/test/ui/class-cast-to-trait.rs
@@ -0,0 +1,54 @@
+#![feature(box_syntax)]
+
+trait Noisy {
+  fn speak(&self);
+}
+
+struct Cat {
+  meows : usize,
+
+  how_hungry : isize,
+  name : String,
+}
+
+impl Cat {
+  pub fn eat(&self) -> bool {
+    if self.how_hungry > 0 {
+        println!("OM NOM NOM");
+        self.how_hungry -= 2;
+        return true;
+    }
+    else {
+        println!("Not hungry!");
+        return false;
+    }
+  }
+}
+
+impl Noisy for Cat {
+  fn speak(&self) { self.meow(); }
+
+}
+
+impl Cat {
+    fn meow(&self) {
+      println!("Meow");
+      self.meows += 1;
+      if self.meows % 5 == 0 {
+          self.how_hungry += 1;
+      }
+    }
+}
+
+fn cat(in_x : usize, in_y : isize, in_name: String) -> Cat {
+    Cat {
+        meows: in_x,
+        how_hungry: in_y,
+        name: in_name
+    }
+}
+
+fn main() {
+  let nyan: Box<Noisy> = box cat(0, 2, "nyan".to_string()) as Box<Noisy>;
+  nyan.eat(); //~ ERROR no method named `eat` found
+}
diff --git a/src/test/ui/class-cast-to-trait.stderr b/src/test/ui/class-cast-to-trait.stderr
new file mode 100644
index 0000000..39f308c
--- /dev/null
+++ b/src/test/ui/class-cast-to-trait.stderr
@@ -0,0 +1,9 @@
+error[E0599]: no method named `eat` found for type `std::boxed::Box<dyn Noisy>` in the current scope
+  --> $DIR/class-cast-to-trait.rs:53:8
+   |
+LL |   nyan.eat();
+   |        ^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/class-method-missing.rs b/src/test/ui/class-method-missing.rs
new file mode 100644
index 0000000..5dc1832
--- /dev/null
+++ b/src/test/ui/class-method-missing.rs
@@ -0,0 +1,21 @@
+trait Animal {
+  fn eat(&self);
+}
+
+struct Cat {
+  meows: usize,
+}
+
+impl Animal for Cat {
+    //~^ ERROR not all trait items implemented, missing: `eat`
+}
+
+fn cat(in_x : usize) -> Cat {
+    Cat {
+        meows: in_x
+    }
+}
+
+fn main() {
+  let nyan = cat(0);
+}
diff --git a/src/test/ui/class-method-missing.stderr b/src/test/ui/class-method-missing.stderr
new file mode 100644
index 0000000..3b4ac3a
--- /dev/null
+++ b/src/test/ui/class-method-missing.stderr
@@ -0,0 +1,12 @@
+error[E0046]: not all trait items implemented, missing: `eat`
+  --> $DIR/class-method-missing.rs:9:1
+   |
+LL |   fn eat(&self);
+   |   -------------- `eat` from trait
+...
+LL | impl Animal for Cat {
+   | ^^^^^^^^^^^^^^^^^^^ missing `eat` in implementation
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0046`.
diff --git a/src/test/ui/class-missing-self.rs b/src/test/ui/class-missing-self.rs
new file mode 100644
index 0000000..515754e
--- /dev/null
+++ b/src/test/ui/class-missing-self.rs
@@ -0,0 +1,16 @@
+struct Cat {
+  meows : usize,
+}
+
+impl Cat {
+    fn sleep(&self) { loop{} }
+    fn meow(&self) {
+      println!("Meow");
+      meows += 1; //~ ERROR cannot find value `meows` in this scope
+      sleep();     //~ ERROR cannot find function `sleep` in this scope
+    }
+
+}
+
+
+ fn main() { }
diff --git a/src/test/ui/class-missing-self.stderr b/src/test/ui/class-missing-self.stderr
new file mode 100644
index 0000000..ec11f12
--- /dev/null
+++ b/src/test/ui/class-missing-self.stderr
@@ -0,0 +1,19 @@
+error[E0425]: cannot find value `meows` in this scope
+  --> $DIR/class-missing-self.rs:9:7
+   |
+LL |       meows += 1;
+   |       ^^^^^ help: try: `self.meows`
+
+error[E0425]: cannot find function `sleep` in this scope
+  --> $DIR/class-missing-self.rs:10:7
+   |
+LL |       sleep();
+   |       ^^^^^ not found in this scope
+help: possible candidate is found in another module, you can import it into scope
+   |
+LL | use std::thread::sleep;
+   |
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/cleanup-rvalue-scopes-cf.rs b/src/test/ui/cleanup-rvalue-scopes-cf.rs
new file mode 100644
index 0000000..106dbd3
--- /dev/null
+++ b/src/test/ui/cleanup-rvalue-scopes-cf.rs
@@ -0,0 +1,35 @@
+// ignore-compare-mode-nll
+
+// Test that the borrow checker prevents pointers to temporaries
+// with statement lifetimes from escaping.
+
+use std::ops::Drop;
+
+static mut FLAGS: u64 = 0;
+
+struct Box<T> { f: T }
+struct AddFlags { bits: u64 }
+
+fn AddFlags(bits: u64) -> AddFlags {
+    AddFlags { bits: bits }
+}
+
+fn arg(x: &AddFlags) -> &AddFlags {
+    x
+}
+
+impl AddFlags {
+    fn get(&self) -> &AddFlags {
+        self
+    }
+}
+
+pub fn main() {
+    let _x = arg(&AddFlags(1)); //~ ERROR value does not live long enough
+    let _x = AddFlags(1).get(); //~ ERROR value does not live long enough
+    let _x = &*arg(&AddFlags(1)); //~ ERROR value does not live long enough
+    let ref _x = *arg(&AddFlags(1)); //~ ERROR value does not live long enough
+    let &ref _x = arg(&AddFlags(1)); //~ ERROR value does not live long enough
+    let _x = AddFlags(1).get(); //~ ERROR value does not live long enough
+    let Box { f: _x } = Box { f: AddFlags(1).get() }; //~ ERROR value does not live long enough
+}
diff --git a/src/test/ui/cleanup-rvalue-scopes-cf.stderr b/src/test/ui/cleanup-rvalue-scopes-cf.stderr
new file mode 100644
index 0000000..e35e71c
--- /dev/null
+++ b/src/test/ui/cleanup-rvalue-scopes-cf.stderr
@@ -0,0 +1,93 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/cleanup-rvalue-scopes-cf.rs:28:19
+   |
+LL |     let _x = arg(&AddFlags(1));
+   |                   ^^^^^^^^^^^ - temporary value dropped here while still borrowed
+   |                   |
+   |                   temporary value does not live long enough
+...
+LL | }
+   | - temporary value needs to live until here
+   |
+   = note: consider using a `let` binding to increase its lifetime
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/cleanup-rvalue-scopes-cf.rs:29:14
+   |
+LL |     let _x = AddFlags(1).get();
+   |              ^^^^^^^^^^^      - temporary value dropped here while still borrowed
+   |              |
+   |              temporary value does not live long enough
+...
+LL | }
+   | - temporary value needs to live until here
+   |
+   = note: consider using a `let` binding to increase its lifetime
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/cleanup-rvalue-scopes-cf.rs:30:21
+   |
+LL |     let _x = &*arg(&AddFlags(1));
+   |                     ^^^^^^^^^^^ - temporary value dropped here while still borrowed
+   |                     |
+   |                     temporary value does not live long enough
+...
+LL | }
+   | - temporary value needs to live until here
+   |
+   = note: consider using a `let` binding to increase its lifetime
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/cleanup-rvalue-scopes-cf.rs:31:24
+   |
+LL |     let ref _x = *arg(&AddFlags(1));
+   |                        ^^^^^^^^^^^ - temporary value dropped here while still borrowed
+   |                        |
+   |                        temporary value does not live long enough
+...
+LL | }
+   | - temporary value needs to live until here
+   |
+   = note: consider using a `let` binding to increase its lifetime
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/cleanup-rvalue-scopes-cf.rs:32:24
+   |
+LL |     let &ref _x = arg(&AddFlags(1));
+   |                        ^^^^^^^^^^^ - temporary value dropped here while still borrowed
+   |                        |
+   |                        temporary value does not live long enough
+...
+LL | }
+   | - temporary value needs to live until here
+   |
+   = note: consider using a `let` binding to increase its lifetime
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/cleanup-rvalue-scopes-cf.rs:33:14
+   |
+LL |     let _x = AddFlags(1).get();
+   |              ^^^^^^^^^^^      - temporary value dropped here while still borrowed
+   |              |
+   |              temporary value does not live long enough
+LL |     let Box { f: _x } = Box { f: AddFlags(1).get() };
+LL | }
+   | - temporary value needs to live until here
+   |
+   = note: consider using a `let` binding to increase its lifetime
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/cleanup-rvalue-scopes-cf.rs:34:34
+   |
+LL |     let Box { f: _x } = Box { f: AddFlags(1).get() };
+   |                                  ^^^^^^^^^^^        - temporary value dropped here while still borrowed
+   |                                  |
+   |                                  temporary value does not live long enough
+LL | }
+   | - temporary value needs to live until here
+   |
+   = note: consider using a `let` binding to increase its lifetime
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/closure-expected-type/expect-fn-supply-fn-multiple.rs b/src/test/ui/closure-expected-type/expect-fn-supply-fn-multiple.rs
new file mode 100644
index 0000000..1bfaecd
--- /dev/null
+++ b/src/test/ui/closure-expected-type/expect-fn-supply-fn-multiple.rs
@@ -0,0 +1,38 @@
+// compile-pass
+
+#![allow(warnings)]
+
+type Different<'a, 'b> = &'a mut (&'a (), &'b ());
+type Same<'a> = Different<'a, 'a>;
+
+fn with_closure_expecting_different<F>(_: F)
+    where F: for<'a, 'b> FnOnce(Different<'a, 'b>)
+{
+}
+
+fn with_closure_expecting_different_anon<F>(_: F)
+    where F: FnOnce(Different<'_, '_>)
+{
+}
+
+fn supplying_nothing_expecting_anon() {
+    with_closure_expecting_different_anon(|x: Different| {
+    })
+}
+
+fn supplying_nothing_expecting_named() {
+    with_closure_expecting_different(|x: Different| {
+    })
+}
+
+fn supplying_underscore_expecting_anon() {
+    with_closure_expecting_different_anon(|x: Different<'_, '_>| {
+    })
+}
+
+fn supplying_underscore_expecting_named() {
+    with_closure_expecting_different(|x: Different<'_, '_>| {
+    })
+}
+
+fn main() { }
diff --git a/src/test/ui/closure-expected-type/expect-fn-supply-fn.rs b/src/test/ui/closure-expected-type/expect-fn-supply-fn.rs
new file mode 100644
index 0000000..a4e43da
--- /dev/null
+++ b/src/test/ui/closure-expected-type/expect-fn-supply-fn.rs
@@ -0,0 +1,59 @@
+fn with_closure_expecting_fn_with_free_region<F>(_: F)
+    where F: for<'a> FnOnce(fn(&'a u32), &i32)
+{
+}
+
+fn with_closure_expecting_fn_with_bound_region<F>(_: F)
+    where F: FnOnce(fn(&u32), &i32)
+{
+}
+
+fn expect_free_supply_free_from_fn<'x>(x: &'x u32) {
+    // Here, the type given for `'x` "obscures" a region from the
+    // expected signature that is bound at closure level.
+    with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {});
+    //~^ ERROR mismatched types
+    //~| ERROR mismatched types
+}
+
+fn expect_free_supply_free_from_closure() {
+    // A variant on the previous test. Here, the region `'a` will be
+    // bound at the closure level, just as is expected, so no error
+    // results.
+    type Foo<'a> = fn(&'a u32);
+    with_closure_expecting_fn_with_free_region(|_x: Foo<'_>, y| {});
+}
+
+fn expect_free_supply_bound() {
+    // Here, we are given a function whose region is bound at closure level,
+    // but we expect one bound in the argument. Error results.
+    with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {});
+    //~^ ERROR type mismatch
+}
+
+fn expect_bound_supply_free_from_fn<'x>(x: &'x u32) {
+    // Here, we are given a `fn(&u32)` but we expect a `fn(&'x
+    // u32)`. In principle, this could be ok, but we demand equality.
+    with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {});
+    //~^ ERROR type mismatch
+}
+
+fn expect_bound_supply_free_from_closure() {
+    // A variant on the previous test. Here, the region `'a` will be
+    // bound at the closure level, but we expect something bound at
+    // the argument level.
+    type Foo<'a> = fn(&'a u32);
+    with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| {
+    //~^ ERROR type mismatch
+    });
+}
+
+fn expect_bound_supply_bound<'x>(x: &'x u32) {
+    // No error in this case. The supplied type supplies the bound
+    // regions, and hence we are able to figure out the type of `y`
+    // from the expected type
+    with_closure_expecting_fn_with_bound_region(|x: for<'z> fn(&'z u32), y| {
+    });
+}
+
+fn main() { }
diff --git a/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr b/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr
new file mode 100644
index 0000000..ab35aef
--- /dev/null
+++ b/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr
@@ -0,0 +1,93 @@
+error[E0308]: mismatched types
+  --> $DIR/expect-fn-supply-fn.rs:14:52
+   |
+LL |     with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {});
+   |                                                    ^^^^^^^^^^^ lifetime mismatch
+   |
+   = note: expected type `fn(&u32)`
+              found type `fn(&'x u32)`
+note: the anonymous lifetime #2 defined on the body at 14:48...
+  --> $DIR/expect-fn-supply-fn.rs:14:48
+   |
+LL |     with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {});
+   |                                                ^^^^^^^^^^^^^^^^^^^^^^
+note: ...does not necessarily outlive the lifetime 'x as defined on the function body at 11:36
+  --> $DIR/expect-fn-supply-fn.rs:11:36
+   |
+LL | fn expect_free_supply_free_from_fn<'x>(x: &'x u32) {
+   |                                    ^^
+
+error[E0308]: mismatched types
+  --> $DIR/expect-fn-supply-fn.rs:14:52
+   |
+LL |     with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {});
+   |                                                    ^^^^^^^^^^^ lifetime mismatch
+   |
+   = note: expected type `fn(&u32)`
+              found type `fn(&'x u32)`
+note: the lifetime 'x as defined on the function body at 11:36...
+  --> $DIR/expect-fn-supply-fn.rs:11:36
+   |
+LL | fn expect_free_supply_free_from_fn<'x>(x: &'x u32) {
+   |                                    ^^
+note: ...does not necessarily outlive the anonymous lifetime #2 defined on the body at 14:48
+  --> $DIR/expect-fn-supply-fn.rs:14:48
+   |
+LL |     with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {});
+   |                                                ^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0631]: type mismatch in closure arguments
+  --> $DIR/expect-fn-supply-fn.rs:30:5
+   |
+LL |     with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {});
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ---------------- found signature of `fn(for<'r> fn(&'r u32), _) -> _`
+   |     |
+   |     expected signature of `fn(fn(&'a u32), &i32) -> _`
+   |
+note: required by `with_closure_expecting_fn_with_free_region`
+  --> $DIR/expect-fn-supply-fn.rs:1:1
+   |
+LL | / fn with_closure_expecting_fn_with_free_region<F>(_: F)
+LL | |     where F: for<'a> FnOnce(fn(&'a u32), &i32)
+LL | | {
+LL | | }
+   | |_^
+
+error[E0631]: type mismatch in closure arguments
+  --> $DIR/expect-fn-supply-fn.rs:37:5
+   |
+LL |     with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {});
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------------------- found signature of `fn(fn(&'x u32), _) -> _`
+   |     |
+   |     expected signature of `fn(for<'r> fn(&'r u32), &i32) -> _`
+   |
+note: required by `with_closure_expecting_fn_with_bound_region`
+  --> $DIR/expect-fn-supply-fn.rs:6:1
+   |
+LL | / fn with_closure_expecting_fn_with_bound_region<F>(_: F)
+LL | |     where F: FnOnce(fn(&u32), &i32)
+LL | | {
+LL | | }
+   | |_^
+
+error[E0631]: type mismatch in closure arguments
+  --> $DIR/expect-fn-supply-fn.rs:46:5
+   |
+LL |     with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ --------------- found signature of `for<'r> fn(fn(&'r u32), _) -> _`
+   |     |
+   |     expected signature of `fn(for<'r> fn(&'r u32), &i32) -> _`
+   |
+note: required by `with_closure_expecting_fn_with_bound_region`
+  --> $DIR/expect-fn-supply-fn.rs:6:1
+   |
+LL | / fn with_closure_expecting_fn_with_bound_region<F>(_: F)
+LL | |     where F: FnOnce(fn(&u32), &i32)
+LL | | {
+LL | | }
+   | |_^
+
+error: aborting due to 5 previous errors
+
+Some errors occurred: E0308, E0631.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/closure-expected-type/expect-infer-var-appearing-twice.rs b/src/test/ui/closure-expected-type/expect-infer-var-appearing-twice.rs
new file mode 100644
index 0000000..e5ec6b2
--- /dev/null
+++ b/src/test/ui/closure-expected-type/expect-infer-var-appearing-twice.rs
@@ -0,0 +1,25 @@
+fn with_closure<F, A>(_: F)
+    where F: FnOnce(A, A)
+{
+}
+
+fn a() {
+    with_closure(|x: u32, y| {
+        // We deduce type of `y` from `x`.
+    });
+}
+
+fn b() {
+    // Here we take the supplied types, resulting in an error later on.
+    with_closure(|x: u32, y: i32| {
+        //~^ ERROR type mismatch in closure arguments
+    });
+}
+
+fn c() {
+    with_closure(|x, y: i32| {
+        // We deduce type of `x` from `y`.
+    });
+}
+
+fn main() { }
diff --git a/src/test/ui/closure-expected-type/expect-infer-var-appearing-twice.stderr b/src/test/ui/closure-expected-type/expect-infer-var-appearing-twice.stderr
new file mode 100644
index 0000000..7a0938e
--- /dev/null
+++ b/src/test/ui/closure-expected-type/expect-infer-var-appearing-twice.stderr
@@ -0,0 +1,20 @@
+error[E0631]: type mismatch in closure arguments
+  --> $DIR/expect-infer-var-appearing-twice.rs:14:5
+   |
+LL |     with_closure(|x: u32, y: i32| {
+   |     ^^^^^^^^^^^^ ---------------- found signature of `fn(u32, i32) -> _`
+   |     |
+   |     expected signature of `fn(_, _) -> _`
+   |
+note: required by `with_closure`
+  --> $DIR/expect-infer-var-appearing-twice.rs:1:1
+   |
+LL | / fn with_closure<F, A>(_: F)
+LL | |     where F: FnOnce(A, A)
+LL | | {
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0631`.
diff --git a/src/test/ui/closure-expected-type/expect-infer-var-supply-ty-with-bound-region.rs b/src/test/ui/closure-expected-type/expect-infer-var-supply-ty-with-bound-region.rs
new file mode 100644
index 0000000..3e42284
--- /dev/null
+++ b/src/test/ui/closure-expected-type/expect-infer-var-supply-ty-with-bound-region.rs
@@ -0,0 +1,19 @@
+// compile-pass
+
+fn with_closure<F, A>(_: F)
+    where F: FnOnce(A, &u32)
+{
+}
+
+fn foo() {
+    // This version works; we infer `A` to be `u32`, and take the type
+    // of `y` to be `&u32`.
+    with_closure(|x: u32, y| {});
+}
+
+fn bar() {
+    // This version also works.
+    with_closure(|x: &u32, y| {});
+}
+
+fn main() { }
diff --git a/src/test/ui/closure-expected-type/expect-infer-var-supply-ty-with-free-region.rs b/src/test/ui/closure-expected-type/expect-infer-var-supply-ty-with-free-region.rs
new file mode 100644
index 0000000..cf417d7
--- /dev/null
+++ b/src/test/ui/closure-expected-type/expect-infer-var-supply-ty-with-free-region.rs
@@ -0,0 +1,19 @@
+// compile-pass
+
+fn with_closure<F, A>(_: F)
+    where F: FnOnce(A, &u32)
+{
+}
+
+fn foo() {
+    // This version works; we infer `A` to be `u32`, and take the type
+    // of `y` to be `&u32`.
+    with_closure(|x: u32, y| {});
+}
+
+fn bar<'x>(x: &'x u32) {
+    // Same.
+    with_closure(|x: &'x u32, y| {});
+}
+
+fn main() { }
diff --git a/src/test/ui/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.rs b/src/test/ui/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.rs
new file mode 100644
index 0000000..97d7a51
--- /dev/null
+++ b/src/test/ui/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.rs
@@ -0,0 +1,19 @@
+fn with_closure<F, A, B>(_: F)
+    where F: FnOnce(A, B)
+{
+}
+
+fn a() {
+    // Type of `y` is unconstrained.
+    with_closure(|x: u32, y| {}); //~ ERROR E0282
+}
+
+fn b() {
+    with_closure(|x: u32, y: u32| {}); // OK
+}
+
+fn c() {
+    with_closure(|x: u32, y: u32| {}); // OK
+}
+
+fn main() { }
diff --git a/src/test/ui/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.stderr b/src/test/ui/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.stderr
new file mode 100644
index 0000000..2005bd4
--- /dev/null
+++ b/src/test/ui/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.stderr
@@ -0,0 +1,9 @@
+error[E0282]: type annotations needed
+  --> $DIR/expect-two-infer-vars-supply-ty-with-bound-region.rs:8:27
+   |
+LL |     with_closure(|x: u32, y| {});
+   |                           ^ consider giving this closure parameter a type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/closure-expected-type/issue-24421.rs b/src/test/ui/closure-expected-type/issue-24421.rs
new file mode 100644
index 0000000..477eb40
--- /dev/null
+++ b/src/test/ui/closure-expected-type/issue-24421.rs
@@ -0,0 +1,10 @@
+// compile-pass
+
+fn test<F: Fn(&u64, &u64)>(f: F) {}
+
+fn main() {
+    test(|x,      y     | {});
+    test(|x:&u64, y:&u64| {});
+    test(|x:&u64, y     | {});
+    test(|x,      y:&u64| {});
+}
diff --git a/src/test/ui/closure-expected.rs b/src/test/ui/closure-expected.rs
new file mode 100644
index 0000000..9b15a63
--- /dev/null
+++ b/src/test/ui/closure-expected.rs
@@ -0,0 +1,5 @@
+fn main() {
+    let x = Some(1);
+    let y = x.or_else(4);
+    //~^ ERROR expected a `std::ops::FnOnce<()>` closure, found `{integer}`
+}
diff --git a/src/test/ui/closure-expected.stderr b/src/test/ui/closure-expected.stderr
new file mode 100644
index 0000000..ff77423
--- /dev/null
+++ b/src/test/ui/closure-expected.stderr
@@ -0,0 +1,12 @@
+error[E0277]: expected a `std::ops::FnOnce<()>` closure, found `{integer}`
+  --> $DIR/closure-expected.rs:3:15
+   |
+LL |     let y = x.or_else(4);
+   |               ^^^^^^^ expected an `FnOnce<()>` closure, found `{integer}`
+   |
+   = help: the trait `std::ops::FnOnce<()>` is not implemented for `{integer}`
+   = note: wrap the `{integer}` in a closure with no arguments: `|| { /* code */ }
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/closure_context/issue-26046-fn-mut.rs b/src/test/ui/closure_context/issue-26046-fn-mut.rs
new file mode 100644
index 0000000..e584018
--- /dev/null
+++ b/src/test/ui/closure_context/issue-26046-fn-mut.rs
@@ -0,0 +1,11 @@
+fn foo() -> Box<Fn()> {
+    let num = 5;
+
+    let closure = || { //~ ERROR expected a closure that
+        num += 1;
+    };
+
+    Box::new(closure)
+}
+
+fn main() {}
diff --git a/src/test/ui/closure_context/issue-26046-fn-mut.stderr b/src/test/ui/closure_context/issue-26046-fn-mut.stderr
new file mode 100644
index 0000000..74d3c49
--- /dev/null
+++ b/src/test/ui/closure_context/issue-26046-fn-mut.stderr
@@ -0,0 +1,14 @@
+error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnMut`
+  --> $DIR/issue-26046-fn-mut.rs:4:19
+   |
+LL |     let closure = || {
+   |                   ^^ this closure implements `FnMut`, not `Fn`
+LL |         num += 1;
+   |         --- closure is `FnMut` because it mutates the variable `num` here
+...
+LL |     Box::new(closure)
+   |     ----------------- the requirement to implement `Fn` derives from here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0525`.
diff --git a/src/test/ui/closure_context/issue-26046-fn-once.rs b/src/test/ui/closure_context/issue-26046-fn-once.rs
new file mode 100644
index 0000000..d33420c
--- /dev/null
+++ b/src/test/ui/closure_context/issue-26046-fn-once.rs
@@ -0,0 +1,11 @@
+fn get_closure() -> Box<Fn() -> Vec<u8>> {
+    let vec = vec![1u8, 2u8];
+
+    let closure = move || { //~ ERROR expected a closure
+        vec
+    };
+
+    Box::new(closure)
+}
+
+fn main() {}
diff --git a/src/test/ui/closure_context/issue-26046-fn-once.stderr b/src/test/ui/closure_context/issue-26046-fn-once.stderr
new file mode 100644
index 0000000..473e8e8
--- /dev/null
+++ b/src/test/ui/closure_context/issue-26046-fn-once.stderr
@@ -0,0 +1,14 @@
+error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce`
+  --> $DIR/issue-26046-fn-once.rs:4:19
+   |
+LL |     let closure = move || {
+   |                   ^^^^^^^ this closure implements `FnOnce`, not `Fn`
+LL |         vec
+   |         --- closure is `FnOnce` because it moves the variable `vec` out of its environment
+...
+LL |     Box::new(closure)
+   |     ----------------- the requirement to implement `Fn` derives from here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0525`.
diff --git a/src/test/ui/closure_context/issue-42065.rs b/src/test/ui/closure_context/issue-42065.rs
new file mode 100644
index 0000000..c506600
--- /dev/null
+++ b/src/test/ui/closure_context/issue-42065.rs
@@ -0,0 +1,13 @@
+use std::collections::HashMap;
+
+fn main() {
+    let dict: HashMap<i32, i32> = HashMap::new();
+    let debug_dump_dict = || {
+        for (key, value) in dict {
+            println!("{:?} - {:?}", key, value);
+        }
+    };
+    debug_dump_dict();
+    debug_dump_dict();
+    //~^ ERROR use of moved value: `debug_dump_dict`
+}
diff --git a/src/test/ui/closure_context/issue-42065.stderr b/src/test/ui/closure_context/issue-42065.stderr
new file mode 100644
index 0000000..69d9865
--- /dev/null
+++ b/src/test/ui/closure_context/issue-42065.stderr
@@ -0,0 +1,17 @@
+error[E0382]: use of moved value: `debug_dump_dict`
+  --> $DIR/issue-42065.rs:11:5
+   |
+LL |     debug_dump_dict();
+   |     --------------- value moved here
+LL |     debug_dump_dict();
+   |     ^^^^^^^^^^^^^^^ value used here after move
+   |
+note: closure cannot be invoked more than once because it moves the variable `dict` out of its environment
+  --> $DIR/issue-42065.rs:6:29
+   |
+LL |         for (key, value) in dict {
+   |                             ^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/closure_promotion.rs b/src/test/ui/closure_promotion.rs
new file mode 100644
index 0000000..a80745e
--- /dev/null
+++ b/src/test/ui/closure_promotion.rs
@@ -0,0 +1,8 @@
+// ignore-compare-mode-nll
+
+#![allow(const_err)]
+
+// nll successfully compiles this.
+fn main() {
+    let x: &'static _ = &|| { let z = 3; z }; //~ ERROR does not live long enough
+}
diff --git a/src/test/ui/closure_promotion.stderr b/src/test/ui/closure_promotion.stderr
new file mode 100644
index 0000000..475e283
--- /dev/null
+++ b/src/test/ui/closure_promotion.stderr
@@ -0,0 +1,13 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/closure_promotion.rs:7:26
+   |
+LL |     let x: &'static _ = &|| { let z = 3; z };
+   |                          ^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/closures/closure-array-break-length.rs b/src/test/ui/closures/closure-array-break-length.rs
new file mode 100644
index 0000000..ac17bfd
--- /dev/null
+++ b/src/test/ui/closures/closure-array-break-length.rs
@@ -0,0 +1,7 @@
+fn main() {
+    |_: [_; continue]| {}; //~ ERROR: `continue` outside of loop
+
+    while |_: [_; continue]| {} {} //~ ERROR: `continue` outside of loop
+
+    while |_: [_; break]| {} {} //~ ERROR: `break` outside of loop
+}
diff --git a/src/test/ui/closures/closure-array-break-length.stderr b/src/test/ui/closures/closure-array-break-length.stderr
new file mode 100644
index 0000000..9b78aa1
--- /dev/null
+++ b/src/test/ui/closures/closure-array-break-length.stderr
@@ -0,0 +1,21 @@
+error[E0268]: `continue` outside of loop
+  --> $DIR/closure-array-break-length.rs:2:13
+   |
+LL |     |_: [_; continue]| {};
+   |             ^^^^^^^^ cannot break outside of a loop
+
+error[E0268]: `continue` outside of loop
+  --> $DIR/closure-array-break-length.rs:4:19
+   |
+LL |     while |_: [_; continue]| {} {}
+   |                   ^^^^^^^^ cannot break outside of a loop
+
+error[E0268]: `break` outside of loop
+  --> $DIR/closure-array-break-length.rs:6:19
+   |
+LL |     while |_: [_; break]| {} {}
+   |                   ^^^^^ cannot break outside of a loop
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0268`.
diff --git a/src/test/ui/closures/closure-bounds-cant-promote-superkind-in-struct.rs b/src/test/ui/closures/closure-bounds-cant-promote-superkind-in-struct.rs
new file mode 100644
index 0000000..039cf3e
--- /dev/null
+++ b/src/test/ui/closures/closure-bounds-cant-promote-superkind-in-struct.rs
@@ -0,0 +1,11 @@
+struct X<F> where F: FnOnce() + 'static + Send {
+    field: F,
+}
+
+fn foo<F>(blk: F) -> X<F> where F: FnOnce() + 'static {
+    //~^ ERROR `F` cannot be sent between threads safely
+    return X { field: blk };
+}
+
+fn main() {
+}
diff --git a/src/test/ui/closures/closure-bounds-cant-promote-superkind-in-struct.stderr b/src/test/ui/closures/closure-bounds-cant-promote-superkind-in-struct.stderr
new file mode 100644
index 0000000..81c4f4e
--- /dev/null
+++ b/src/test/ui/closures/closure-bounds-cant-promote-superkind-in-struct.stderr
@@ -0,0 +1,20 @@
+error[E0277]: `F` cannot be sent between threads safely
+  --> $DIR/closure-bounds-cant-promote-superkind-in-struct.rs:5:1
+   |
+LL | / fn foo<F>(blk: F) -> X<F> where F: FnOnce() + 'static {
+LL | |
+LL | |     return X { field: blk };
+LL | | }
+   | |_^ `F` cannot be sent between threads safely
+   |
+   = help: the trait `std::marker::Send` is not implemented for `F`
+   = help: consider adding a `where F: std::marker::Send` bound
+note: required by `X`
+  --> $DIR/closure-bounds-cant-promote-superkind-in-struct.rs:1:1
+   |
+LL | struct X<F> where F: FnOnce() + 'static + Send {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/closures/closure-bounds-static-cant-capture-borrowed.rs b/src/test/ui/closures/closure-bounds-static-cant-capture-borrowed.rs
new file mode 100644
index 0000000..4fa5d54
--- /dev/null
+++ b/src/test/ui/closures/closure-bounds-static-cant-capture-borrowed.rs
@@ -0,0 +1,12 @@
+fn bar<F>(blk: F) where F: FnOnce() + 'static {
+}
+
+fn foo(x: &()) {
+    bar(|| {
+        //~^ ERROR explicit lifetime required in the type of `x` [E0621]
+        let _ = x;
+    })
+}
+
+fn main() {
+}
diff --git a/src/test/ui/closures/closure-bounds-static-cant-capture-borrowed.stderr b/src/test/ui/closures/closure-bounds-static-cant-capture-borrowed.stderr
new file mode 100644
index 0000000..f50c3e3
--- /dev/null
+++ b/src/test/ui/closures/closure-bounds-static-cant-capture-borrowed.stderr
@@ -0,0 +1,11 @@
+error[E0621]: explicit lifetime required in the type of `x`
+  --> $DIR/closure-bounds-static-cant-capture-borrowed.rs:5:5
+   |
+LL | fn foo(x: &()) {
+   |           --- help: add explicit lifetime `'static` to the type of `x`: `&'static ()`
+LL |     bar(|| {
+   |     ^^^ lifetime `'static` required
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/closures/closure-bounds-subtype.rs b/src/test/ui/closures/closure-bounds-subtype.rs
new file mode 100644
index 0000000..4888cbf
--- /dev/null
+++ b/src/test/ui/closures/closure-bounds-subtype.rs
@@ -0,0 +1,16 @@
+fn take_any<F>(_: F) where F: FnOnce() {
+}
+
+fn take_const_owned<F>(_: F) where F: FnOnce() + Sync + Send {
+}
+
+fn give_any<F>(f: F) where F: FnOnce() {
+    take_any(f);
+}
+
+fn give_owned<F>(f: F) where F: FnOnce() + Send {
+    take_any(f);
+    take_const_owned(f); //~ ERROR `F` cannot be shared between threads safely [E0277]
+}
+
+fn main() {}
diff --git a/src/test/ui/closures/closure-bounds-subtype.stderr b/src/test/ui/closures/closure-bounds-subtype.stderr
new file mode 100644
index 0000000..3b9fd10
--- /dev/null
+++ b/src/test/ui/closures/closure-bounds-subtype.stderr
@@ -0,0 +1,17 @@
+error[E0277]: `F` cannot be shared between threads safely
+  --> $DIR/closure-bounds-subtype.rs:13:5
+   |
+LL |     take_const_owned(f);
+   |     ^^^^^^^^^^^^^^^^ `F` cannot be shared between threads safely
+   |
+   = help: the trait `std::marker::Sync` is not implemented for `F`
+   = help: consider adding a `where F: std::marker::Sync` bound
+note: required by `take_const_owned`
+  --> $DIR/closure-bounds-subtype.rs:4:1
+   |
+LL | fn take_const_owned<F>(_: F) where F: FnOnce() + Sync + Send {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/closures/closure-expected-type/expect-region-supply-region.rs b/src/test/ui/closures/closure-expected-type/expect-region-supply-region.rs
new file mode 100644
index 0000000..28a6ab7
--- /dev/null
+++ b/src/test/ui/closures/closure-expected-type/expect-region-supply-region.rs
@@ -0,0 +1,70 @@
+#![allow(warnings)]
+
+fn closure_expecting_bound<F>(_: F)
+    where F: FnOnce(&u32)
+{
+}
+
+fn closure_expecting_free<'a, F>(_: F)
+    where F: FnOnce(&'a u32)
+{
+}
+
+fn expect_bound_supply_nothing() {
+    // Because `x` is inferred to have a bound region, we cannot allow
+    // it to escape into `f`:
+    let mut f: Option<&u32> = None;
+    closure_expecting_bound(|x| {
+        f = Some(x); //~ ERROR borrowed data cannot be stored outside of its closure
+    });
+}
+
+fn expect_bound_supply_bound() {
+    // Because `x` is inferred to have a bound region, we cannot allow
+    // it to escape into `f`, even with an explicit type annotation on
+    // closure:
+    let mut f: Option<&u32> = None;
+    closure_expecting_bound(|x: &u32| {
+        f = Some(x); //~ ERROR borrowed data cannot be stored outside of its closure
+    });
+}
+
+fn expect_bound_supply_named<'x>() {
+    let mut f: Option<&u32> = None;
+
+    // Here we give a type annotation that `x` should be free. We get
+    // an error because of that.
+    closure_expecting_bound(|x: &'x u32| {
+        //~^ ERROR mismatched types
+        //~| ERROR mismatched types
+
+        // And we still cannot let `x` escape into `f`.
+        f = Some(x);
+        //~^ ERROR borrowed data cannot be stored outside of its closure
+    });
+}
+
+fn expect_free_supply_nothing() {
+    let mut f: Option<&u32> = None;
+    closure_expecting_free(|x| f = Some(x)); // OK
+}
+
+fn expect_free_supply_bound() {
+    let mut f: Option<&u32> = None;
+
+    // Here, even though the annotation `&u32` could be seen as being
+    // bound in the closure, we permit it to be defined as a free
+    // region (which is inferred to something in the fn body).
+    closure_expecting_free(|x: &u32| f = Some(x)); // OK
+}
+
+fn expect_free_supply_named<'x>() {
+    let mut f: Option<&u32> = None;
+
+    // Here, even though the annotation `&u32` could be seen as being
+    // bound in the closure, we permit it to be defined as a free
+    // region (which is inferred to something in the fn body).
+    closure_expecting_free(|x: &'x u32| f = Some(x)); // OK
+}
+
+fn main() { }
diff --git a/src/test/ui/closures/closure-expected-type/expect-region-supply-region.stderr b/src/test/ui/closures/closure-expected-type/expect-region-supply-region.stderr
new file mode 100644
index 0000000..e3b623d
--- /dev/null
+++ b/src/test/ui/closures/closure-expected-type/expect-region-supply-region.stderr
@@ -0,0 +1,87 @@
+error: borrowed data cannot be stored outside of its closure
+  --> $DIR/expect-region-supply-region.rs:18:18
+   |
+LL |     let mut f: Option<&u32> = None;
+   |         ----- borrowed data cannot be stored into here...
+LL |     closure_expecting_bound(|x| {
+   |                             --- ...because it cannot outlive this closure
+LL |         f = Some(x);
+   |                  ^ cannot be stored outside of its closure
+
+error: borrowed data cannot be stored outside of its closure
+  --> $DIR/expect-region-supply-region.rs:28:18
+   |
+LL |     let mut f: Option<&u32> = None;
+   |         ----- borrowed data cannot be stored into here...
+LL |     closure_expecting_bound(|x: &u32| {
+   |                             --------- ...because it cannot outlive this closure
+LL |         f = Some(x);
+   |                  ^ cannot be stored outside of its closure
+
+error[E0308]: mismatched types
+  --> $DIR/expect-region-supply-region.rs:37:33
+   |
+LL |     closure_expecting_bound(|x: &'x u32| {
+   |                                 ^^^^^^^ lifetime mismatch
+   |
+   = note: expected type `&u32`
+              found type `&'x u32`
+note: the anonymous lifetime #2 defined on the body at 37:29...
+  --> $DIR/expect-region-supply-region.rs:37:29
+   |
+LL |       closure_expecting_bound(|x: &'x u32| {
+   |  _____________________________^
+LL | |
+LL | |
+LL | |
+...  |
+LL | |
+LL | |     });
+   | |_____^
+note: ...does not necessarily outlive the lifetime 'x as defined on the function body at 32:30
+  --> $DIR/expect-region-supply-region.rs:32:30
+   |
+LL | fn expect_bound_supply_named<'x>() {
+   |                              ^^
+
+error[E0308]: mismatched types
+  --> $DIR/expect-region-supply-region.rs:37:33
+   |
+LL |     closure_expecting_bound(|x: &'x u32| {
+   |                                 ^^^^^^^ lifetime mismatch
+   |
+   = note: expected type `&u32`
+              found type `&'x u32`
+note: the lifetime 'x as defined on the function body at 32:30...
+  --> $DIR/expect-region-supply-region.rs:32:30
+   |
+LL | fn expect_bound_supply_named<'x>() {
+   |                              ^^
+note: ...does not necessarily outlive the anonymous lifetime #2 defined on the body at 37:29
+  --> $DIR/expect-region-supply-region.rs:37:29
+   |
+LL |       closure_expecting_bound(|x: &'x u32| {
+   |  _____________________________^
+LL | |
+LL | |
+LL | |
+...  |
+LL | |
+LL | |     });
+   | |_____^
+
+error: borrowed data cannot be stored outside of its closure
+  --> $DIR/expect-region-supply-region.rs:42:18
+   |
+LL |     let mut f: Option<&u32> = None;
+   |         ----- borrowed data cannot be stored into here...
+...
+LL |     closure_expecting_bound(|x: &'x u32| {
+   |                             ------------ ...because it cannot outlive this closure
+...
+LL |         f = Some(x);
+   |                  ^ cannot be stored outside of its closure
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/closures/closure-immutable-outer-variable.fixed b/src/test/ui/closures/closure-immutable-outer-variable.fixed
new file mode 100644
index 0000000..22164a2
--- /dev/null
+++ b/src/test/ui/closures/closure-immutable-outer-variable.fixed
@@ -0,0 +1,12 @@
+// run-rustfix
+
+// Point at the captured immutable outer variable
+
+fn foo(mut f: Box<FnMut()>) {
+    f();
+}
+
+fn main() {
+    let mut y = true;
+    foo(Box::new(move || y = false) as Box<_>); //~ ERROR cannot assign to captured outer variable
+}
diff --git a/src/test/ui/closures/closure-immutable-outer-variable.nll.stderr b/src/test/ui/closures/closure-immutable-outer-variable.nll.stderr
new file mode 100644
index 0000000..7e60f3c
--- /dev/null
+++ b/src/test/ui/closures/closure-immutable-outer-variable.nll.stderr
@@ -0,0 +1,11 @@
+error[E0594]: cannot assign to `y`, as it is not declared as mutable
+  --> $DIR/closure-immutable-outer-variable.rs:11:26
+   |
+LL |     let y = true;
+   |         - help: consider changing this to be mutable: `mut y`
+LL |     foo(Box::new(move || y = false) as Box<_>);
+   |                          ^^^^^^^^^ cannot assign
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/closures/closure-immutable-outer-variable.rs b/src/test/ui/closures/closure-immutable-outer-variable.rs
new file mode 100644
index 0000000..fc4e385
--- /dev/null
+++ b/src/test/ui/closures/closure-immutable-outer-variable.rs
@@ -0,0 +1,12 @@
+// run-rustfix
+
+// Point at the captured immutable outer variable
+
+fn foo(mut f: Box<FnMut()>) {
+    f();
+}
+
+fn main() {
+    let y = true;
+    foo(Box::new(move || y = false) as Box<_>); //~ ERROR cannot assign to captured outer variable
+}
diff --git a/src/test/ui/closures/closure-immutable-outer-variable.rs.fixed b/src/test/ui/closures/closure-immutable-outer-variable.rs.fixed
new file mode 100644
index 0000000..5c6358b
--- /dev/null
+++ b/src/test/ui/closures/closure-immutable-outer-variable.rs.fixed
@@ -0,0 +1,10 @@
+// Point at the captured immutable outer variable
+
+fn foo(mut f: Box<FnMut()>) {
+    f();
+}
+
+fn main() {
+    let mut y = true;
+    foo(Box::new(move || y = false) as Box<_>); //~ ERROR cannot assign to captured outer variable
+}
diff --git a/src/test/ui/closures/closure-immutable-outer-variable.stderr b/src/test/ui/closures/closure-immutable-outer-variable.stderr
new file mode 100644
index 0000000..3323207
--- /dev/null
+++ b/src/test/ui/closures/closure-immutable-outer-variable.stderr
@@ -0,0 +1,11 @@
+error[E0594]: cannot assign to captured outer variable in an `FnMut` closure
+  --> $DIR/closure-immutable-outer-variable.rs:11:26
+   |
+LL |     let y = true;
+   |         - help: consider making `y` mutable: `mut y`
+LL |     foo(Box::new(move || y = false) as Box<_>);
+   |                          ^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/closures/closure-move-sync.rs b/src/test/ui/closures/closure-move-sync.rs
new file mode 100644
index 0000000..580cd1a
--- /dev/null
+++ b/src/test/ui/closures/closure-move-sync.rs
@@ -0,0 +1,22 @@
+use std::thread;
+use std::sync::mpsc::channel;
+
+fn bar() {
+    let (send, recv) = channel();
+    let t = thread::spawn(|| {
+        recv.recv().unwrap();
+        //~^^ ERROR `std::sync::mpsc::Receiver<()>` cannot be shared between threads safely
+    });
+
+    send.send(());
+
+    t.join().unwrap();
+}
+
+fn foo() {
+    let (tx, _rx) = channel();
+    thread::spawn(|| tx.send(()).unwrap());
+    //~^ ERROR `std::sync::mpsc::Sender<()>` cannot be shared between threads safely
+}
+
+fn main() {}
diff --git a/src/test/ui/closures/closure-move-sync.stderr b/src/test/ui/closures/closure-move-sync.stderr
new file mode 100644
index 0000000..8afebc7
--- /dev/null
+++ b/src/test/ui/closures/closure-move-sync.stderr
@@ -0,0 +1,25 @@
+error[E0277]: `std::sync::mpsc::Receiver<()>` cannot be shared between threads safely
+  --> $DIR/closure-move-sync.rs:6:13
+   |
+LL |     let t = thread::spawn(|| {
+   |             ^^^^^^^^^^^^^ `std::sync::mpsc::Receiver<()>` cannot be shared between threads safely
+   |
+   = help: the trait `std::marker::Sync` is not implemented for `std::sync::mpsc::Receiver<()>`
+   = note: required because of the requirements on the impl of `std::marker::Send` for `&std::sync::mpsc::Receiver<()>`
+   = note: required because it appears within the type `[closure@$DIR/closure-move-sync.rs:6:27: 9:6 recv:&std::sync::mpsc::Receiver<()>]`
+   = note: required by `std::thread::spawn`
+
+error[E0277]: `std::sync::mpsc::Sender<()>` cannot be shared between threads safely
+  --> $DIR/closure-move-sync.rs:18:5
+   |
+LL |     thread::spawn(|| tx.send(()).unwrap());
+   |     ^^^^^^^^^^^^^ `std::sync::mpsc::Sender<()>` cannot be shared between threads safely
+   |
+   = help: the trait `std::marker::Sync` is not implemented for `std::sync::mpsc::Sender<()>`
+   = note: required because of the requirements on the impl of `std::marker::Send` for `&std::sync::mpsc::Sender<()>`
+   = note: required because it appears within the type `[closure@$DIR/closure-move-sync.rs:18:19: 18:42 tx:&std::sync::mpsc::Sender<()>]`
+   = note: required by `std::thread::spawn`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/closures/closure-no-fn-1.rs b/src/test/ui/closures/closure-no-fn-1.rs
new file mode 100644
index 0000000..48c3e47
--- /dev/null
+++ b/src/test/ui/closures/closure-no-fn-1.rs
@@ -0,0 +1,8 @@
+// Ensure that capturing closures are never coerced to fns
+// Especially interesting as non-capturing closures can be.
+
+fn main() {
+    let mut a = 0u8;
+    let foo: fn(u8) -> u8 = |v: u8| { a += v; a };
+    //~^ ERROR mismatched types
+}
diff --git a/src/test/ui/closures/closure-no-fn-1.stderr b/src/test/ui/closures/closure-no-fn-1.stderr
new file mode 100644
index 0000000..6d07c6b
--- /dev/null
+++ b/src/test/ui/closures/closure-no-fn-1.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/closure-no-fn-1.rs:6:29
+   |
+LL |     let foo: fn(u8) -> u8 = |v: u8| { a += v; a };
+   |                             ^^^^^^^^^^^^^^^^^^^^^ expected fn pointer, found closure
+   |
+   = note: expected type `fn(u8) -> u8`
+              found type `[closure@$DIR/closure-no-fn-1.rs:6:29: 6:50 a:_]`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/closures/closure-no-fn-2.rs b/src/test/ui/closures/closure-no-fn-2.rs
new file mode 100644
index 0000000..f3066f7
--- /dev/null
+++ b/src/test/ui/closures/closure-no-fn-2.rs
@@ -0,0 +1,8 @@
+// Ensure that capturing closures are never coerced to fns
+// Especially interesting as non-capturing closures can be.
+
+fn main() {
+    let b = 0u8;
+    let bar: fn() -> u8 = || { b };
+    //~^ ERROR mismatched types
+}
diff --git a/src/test/ui/closures/closure-no-fn-2.stderr b/src/test/ui/closures/closure-no-fn-2.stderr
new file mode 100644
index 0000000..5adcdf6
--- /dev/null
+++ b/src/test/ui/closures/closure-no-fn-2.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/closure-no-fn-2.rs:6:27
+   |
+LL |     let bar: fn() -> u8 = || { b };
+   |                           ^^^^^^^^ expected fn pointer, found closure
+   |
+   = note: expected type `fn() -> u8`
+              found type `[closure@$DIR/closure-no-fn-2.rs:6:27: 6:35 b:_]`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/closures/closure-no-fn-3.rs b/src/test/ui/closures/closure-no-fn-3.rs
new file mode 100644
index 0000000..53217c2
--- /dev/null
+++ b/src/test/ui/closures/closure-no-fn-3.rs
@@ -0,0 +1,8 @@
+// Ensure that capturing closures are never coerced to fns
+// Especially interesting as non-capturing closures can be.
+
+fn main() {
+    let b = 0u8;
+    let baz: fn() -> u8 = (|| { b }) as fn() -> u8;
+    //~^ ERROR non-primitive cast
+}
diff --git a/src/test/ui/closures/closure-no-fn-3.stderr b/src/test/ui/closures/closure-no-fn-3.stderr
new file mode 100644
index 0000000..ab6056b
--- /dev/null
+++ b/src/test/ui/closures/closure-no-fn-3.stderr
@@ -0,0 +1,11 @@
+error[E0605]: non-primitive cast: `[closure@$DIR/closure-no-fn-3.rs:6:27: 6:37 b:_]` as `fn() -> u8`
+  --> $DIR/closure-no-fn-3.rs:6:27
+   |
+LL |     let baz: fn() -> u8 = (|| { b }) as fn() -> u8;
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0605`.
diff --git a/src/test/ui/closures/closure-referencing-itself-issue-25954.rs b/src/test/ui/closures/closure-referencing-itself-issue-25954.rs
new file mode 100644
index 0000000..7dd0e51
--- /dev/null
+++ b/src/test/ui/closures/closure-referencing-itself-issue-25954.rs
@@ -0,0 +1,18 @@
+// Regression test for #25954: detect and reject a closure type that
+// references itself.
+
+use std::cell::{Cell, RefCell};
+
+struct A<T: Fn()> {
+    x: RefCell<Option<T>>,
+    b: Cell<i32>,
+}
+
+fn main() {
+    let mut p = A{x: RefCell::new(None), b: Cell::new(4i32)};
+
+    // This is an error about types of infinite size:
+    let q = || p.b.set(5i32); //~ ERROR mismatched types
+
+    *(p.x.borrow_mut()) = Some(q);
+}
diff --git a/src/test/ui/closures/closure-referencing-itself-issue-25954.stderr b/src/test/ui/closures/closure-referencing-itself-issue-25954.stderr
new file mode 100644
index 0000000..8ca43cd
--- /dev/null
+++ b/src/test/ui/closures/closure-referencing-itself-issue-25954.stderr
@@ -0,0 +1,9 @@
+error[E0308]: mismatched types
+  --> $DIR/closure-referencing-itself-issue-25954.rs:15:13
+   |
+LL |     let q = || p.b.set(5i32);
+   |             ^^^^^^^^^^^^^^^^ cyclic type of infinite size
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/closures/closure-reform-bad.rs b/src/test/ui/closures/closure-reform-bad.rs
new file mode 100644
index 0000000..0ba48ab
--- /dev/null
+++ b/src/test/ui/closures/closure-reform-bad.rs
@@ -0,0 +1,12 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+fn call_bare(f: fn(&str)) {
+    f("Hello ");
+}
+
+fn main() {
+    let string = "world!";
+    let f = |s: &str| println!("{}{}", s, string);
+    call_bare(f)    //~ ERROR mismatched types
+}
diff --git a/src/test/ui/closures/closure-reform-bad.stderr b/src/test/ui/closures/closure-reform-bad.stderr
new file mode 100644
index 0000000..5c54809
--- /dev/null
+++ b/src/test/ui/closures/closure-reform-bad.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/closure-reform-bad.rs:11:15
+   |
+LL |     call_bare(f)
+   |               ^ expected fn pointer, found closure
+   |
+   = note: expected type `for<'r> fn(&'r str)`
+              found type `[closure@$DIR/closure-reform-bad.rs:10:13: 10:50 string:_]`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/closures/closure-wrong-kind.rs b/src/test/ui/closures/closure-wrong-kind.rs
new file mode 100644
index 0000000..9bf38bf
--- /dev/null
+++ b/src/test/ui/closures/closure-wrong-kind.rs
@@ -0,0 +1,12 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+struct X;
+fn foo<T>(_: T) {}
+fn bar<T: Fn(u32)>(_: T) {}
+
+fn main() {
+    let x = X;
+    let closure = |_| foo(x);  //~ ERROR E0525
+    bar(closure);
+}
diff --git a/src/test/ui/closures/closure-wrong-kind.stderr b/src/test/ui/closures/closure-wrong-kind.stderr
new file mode 100644
index 0000000..6502612
--- /dev/null
+++ b/src/test/ui/closures/closure-wrong-kind.stderr
@@ -0,0 +1,14 @@
+error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce`
+  --> $DIR/closure-wrong-kind.rs:10:19
+   |
+LL |     let closure = |_| foo(x);
+   |                   ^^^^^^^^-^
+   |                   |       |
+   |                   |       closure is `FnOnce` because it moves the variable `x` out of its environment
+   |                   this closure implements `FnOnce`, not `Fn`
+LL |     bar(closure);
+   |     --- the requirement to implement `Fn` derives from here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0525`.
diff --git a/src/test/ui/codemap_tests/bad-format-args.rs b/src/test/ui/codemap_tests/bad-format-args.rs
new file mode 100644
index 0000000..9f90185
--- /dev/null
+++ b/src/test/ui/codemap_tests/bad-format-args.rs
@@ -0,0 +1,5 @@
+fn main() {
+    format!(); //~ ERROR requires at least a format string argument
+    format!("" 1); //~ ERROR expected token: `,`
+    format!("", 1 1); //~ ERROR expected token: `,`
+}
diff --git a/src/test/ui/codemap_tests/bad-format-args.stderr b/src/test/ui/codemap_tests/bad-format-args.stderr
new file mode 100644
index 0000000..c424eb0
--- /dev/null
+++ b/src/test/ui/codemap_tests/bad-format-args.stderr
@@ -0,0 +1,22 @@
+error: requires at least a format string argument
+  --> $DIR/bad-format-args.rs:2:5
+   |
+LL |     format!();
+   |     ^^^^^^^^^^
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: expected token: `,`
+  --> $DIR/bad-format-args.rs:3:16
+   |
+LL |     format!("" 1);
+   |                ^
+
+error: expected token: `,`
+  --> $DIR/bad-format-args.rs:4:19
+   |
+LL |     format!("", 1 1);
+   |                   ^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/codemap_tests/coherence-overlapping-inherent-impl-trait.rs b/src/test/ui/codemap_tests/coherence-overlapping-inherent-impl-trait.rs
new file mode 100644
index 0000000..f35fbad
--- /dev/null
+++ b/src/test/ui/codemap_tests/coherence-overlapping-inherent-impl-trait.rs
@@ -0,0 +1,6 @@
+#![allow(dead_code)]
+
+trait C {}
+impl C { fn f() {} } //~ ERROR duplicate
+impl C { fn f() {} }
+fn main() { }
diff --git a/src/test/ui/codemap_tests/coherence-overlapping-inherent-impl-trait.stderr b/src/test/ui/codemap_tests/coherence-overlapping-inherent-impl-trait.stderr
new file mode 100644
index 0000000..087084a
--- /dev/null
+++ b/src/test/ui/codemap_tests/coherence-overlapping-inherent-impl-trait.stderr
@@ -0,0 +1,11 @@
+error[E0592]: duplicate definitions with name `f`
+  --> $DIR/coherence-overlapping-inherent-impl-trait.rs:4:10
+   |
+LL | impl C { fn f() {} }
+   |          ^^^^^^^^^ duplicate definitions for `f`
+LL | impl C { fn f() {} }
+   |          --------- other definition for `f`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0592`.
diff --git a/src/test/ui/codemap_tests/empty_span.rs b/src/test/ui/codemap_tests/empty_span.rs
new file mode 100644
index 0000000..4d52b39
--- /dev/null
+++ b/src/test/ui/codemap_tests/empty_span.rs
@@ -0,0 +1,8 @@
+#![feature(optin_builtin_traits)]
+fn main() {
+    struct Foo;
+
+    impl !Sync for Foo {}
+
+    unsafe impl Send for &'static Foo { } //~ ERROR cross-crate traits with a default impl
+}
diff --git a/src/test/ui/codemap_tests/empty_span.stderr b/src/test/ui/codemap_tests/empty_span.stderr
new file mode 100644
index 0000000..1dd99cf
--- /dev/null
+++ b/src/test/ui/codemap_tests/empty_span.stderr
@@ -0,0 +1,9 @@
+error[E0321]: cross-crate traits with a default impl, like `std::marker::Send`, can only be implemented for a struct/enum type, not `&'static main::Foo`
+  --> $DIR/empty_span.rs:7:5
+   |
+LL |     unsafe impl Send for &'static Foo { }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0321`.
diff --git a/src/test/ui/codemap_tests/huge_multispan_highlight.nll.stderr b/src/test/ui/codemap_tests/huge_multispan_highlight.nll.stderr
new file mode 100644
index 0000000..a60f1c7
--- /dev/null
+++ b/src/test/ui/codemap_tests/huge_multispan_highlight.nll.stderr
@@ -0,0 +1,12 @@
+error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
+  --> $DIR/huge_multispan_highlight.rs:90:13
+   |
+LL |     let x = "foo";
+   |         - help: consider changing this to be mutable: `mut x`
+...
+LL |     let y = &mut x;
+   |             ^^^^^^ cannot borrow as mutable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/codemap_tests/huge_multispan_highlight.rs b/src/test/ui/codemap_tests/huge_multispan_highlight.rs
new file mode 100644
index 0000000..623c590
--- /dev/null
+++ b/src/test/ui/codemap_tests/huge_multispan_highlight.rs
@@ -0,0 +1,91 @@
+fn main() {
+    let x = "foo";
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+    let y = &mut x; //~ ERROR cannot borrow
+}
diff --git a/src/test/ui/codemap_tests/huge_multispan_highlight.stderr b/src/test/ui/codemap_tests/huge_multispan_highlight.stderr
new file mode 100644
index 0000000..13bd666
--- /dev/null
+++ b/src/test/ui/codemap_tests/huge_multispan_highlight.stderr
@@ -0,0 +1,12 @@
+error[E0596]: cannot borrow immutable local variable `x` as mutable
+  --> $DIR/huge_multispan_highlight.rs:90:18
+   |
+LL |     let x = "foo";
+   |         - help: make this binding mutable: `mut x`
+...
+LL |     let y = &mut x;
+   |                  ^ cannot borrow mutably
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/codemap_tests/issue-11715.nll.stderr b/src/test/ui/codemap_tests/issue-11715.nll.stderr
new file mode 100644
index 0000000..d0c29c7
--- /dev/null
+++ b/src/test/ui/codemap_tests/issue-11715.nll.stderr
@@ -0,0 +1,14 @@
+error[E0499]: cannot borrow `x` as mutable more than once at a time
+  --> $DIR/issue-11715.rs:5:13
+   |
+LL |     let y = &mut x;
+   |             ------ first mutable borrow occurs here
+LL |     let z = &mut x;
+   |             ^^^^^^ second mutable borrow occurs here
+LL |     z.use_mut();
+LL |     y.use_mut();
+   |     - first borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/codemap_tests/issue-11715.rs b/src/test/ui/codemap_tests/issue-11715.rs
new file mode 100644
index 0000000..617d57f
--- /dev/null
+++ b/src/test/ui/codemap_tests/issue-11715.rs
@@ -0,0 +1,11 @@
+#![feature(rustc_attrs)]
+fn main() { #![rustc_error] // rust-lang/rust#49855
+    let mut x = "foo";
+    let y = &mut x;
+    let z = &mut x; //~ ERROR cannot borrow
+    z.use_mut();
+    y.use_mut();
+}
+
+trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { }  }
+impl<T> Fake for T { }
diff --git a/src/test/ui/codemap_tests/issue-11715.stderr b/src/test/ui/codemap_tests/issue-11715.stderr
new file mode 100644
index 0000000..c37e6b3
--- /dev/null
+++ b/src/test/ui/codemap_tests/issue-11715.stderr
@@ -0,0 +1,14 @@
+error[E0499]: cannot borrow `x` as mutable more than once at a time
+  --> $DIR/issue-11715.rs:5:18
+   |
+LL |     let y = &mut x;
+   |                  - first mutable borrow occurs here
+LL |     let z = &mut x;
+   |                  ^ second mutable borrow occurs here
+...
+LL | }
+   | - first borrow ends here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/codemap_tests/issue-28308.rs b/src/test/ui/codemap_tests/issue-28308.rs
new file mode 100644
index 0000000..81493f8
--- /dev/null
+++ b/src/test/ui/codemap_tests/issue-28308.rs
@@ -0,0 +1,4 @@
+fn main() {
+    assert!("foo");
+    //~^ ERROR cannot apply unary operator `!`
+}
diff --git a/src/test/ui/codemap_tests/issue-28308.stderr b/src/test/ui/codemap_tests/issue-28308.stderr
new file mode 100644
index 0000000..d44c157
--- /dev/null
+++ b/src/test/ui/codemap_tests/issue-28308.stderr
@@ -0,0 +1,9 @@
+error[E0600]: cannot apply unary operator `!` to type `&'static str`
+  --> $DIR/issue-28308.rs:2:5
+   |
+LL |     assert!("foo");
+   |     ^^^^^^^^^^^^^^^ cannot apply unary operator `!`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0600`.
diff --git a/src/test/ui/codemap_tests/one_line.nll.stderr b/src/test/ui/codemap_tests/one_line.nll.stderr
new file mode 100644
index 0000000..eddbd29
--- /dev/null
+++ b/src/test/ui/codemap_tests/one_line.nll.stderr
@@ -0,0 +1,12 @@
+error[E0499]: cannot borrow `v` as mutable more than once at a time
+  --> $DIR/one_line.rs:3:12
+   |
+LL |     v.push(v.pop().unwrap());
+   |     - ---- ^ second mutable borrow occurs here
+   |     | |
+   |     | first borrow later used by call
+   |     first mutable borrow occurs here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/codemap_tests/one_line.rs b/src/test/ui/codemap_tests/one_line.rs
new file mode 100644
index 0000000..bb36813
--- /dev/null
+++ b/src/test/ui/codemap_tests/one_line.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let mut v = vec![Some("foo"), Some("bar")];
+    v.push(v.pop().unwrap()); //~ ERROR cannot borrow
+}
diff --git a/src/test/ui/codemap_tests/one_line.stderr b/src/test/ui/codemap_tests/one_line.stderr
new file mode 100644
index 0000000..9dcaba8
--- /dev/null
+++ b/src/test/ui/codemap_tests/one_line.stderr
@@ -0,0 +1,12 @@
+error[E0499]: cannot borrow `v` as mutable more than once at a time
+  --> $DIR/one_line.rs:3:12
+   |
+LL |     v.push(v.pop().unwrap());
+   |     -      ^               - first borrow ends here
+   |     |      |
+   |     |      second mutable borrow occurs here
+   |     first mutable borrow occurs here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/codemap_tests/overlapping_inherent_impls.rs b/src/test/ui/codemap_tests/overlapping_inherent_impls.rs
new file mode 100644
index 0000000..66af212
--- /dev/null
+++ b/src/test/ui/codemap_tests/overlapping_inherent_impls.rs
@@ -0,0 +1,36 @@
+// Test that you cannot define items with the same name in overlapping inherent
+// impl blocks.
+
+#![allow(unused)]
+
+struct Foo;
+
+impl Foo {
+    fn id() {} //~ ERROR duplicate definitions
+}
+
+impl Foo {
+    fn id() {}
+}
+
+struct Bar<T>(T);
+
+impl<T> Bar<T> {
+    fn bar(&self) {} //~ ERROR duplicate definitions
+}
+
+impl Bar<u32> {
+    fn bar(&self) {}
+}
+
+struct Baz<T>(T);
+
+impl<T: Copy> Baz<T> {
+    fn baz(&self) {} //~ ERROR duplicate definitions
+}
+
+impl<T> Baz<Vec<T>> {
+    fn baz(&self) {}
+}
+
+fn main() {}
diff --git a/src/test/ui/codemap_tests/overlapping_inherent_impls.stderr b/src/test/ui/codemap_tests/overlapping_inherent_impls.stderr
new file mode 100644
index 0000000..70c1093
--- /dev/null
+++ b/src/test/ui/codemap_tests/overlapping_inherent_impls.stderr
@@ -0,0 +1,32 @@
+error[E0592]: duplicate definitions with name `id`
+  --> $DIR/overlapping_inherent_impls.rs:9:5
+   |
+LL |     fn id() {}
+   |     ^^^^^^^^^^ duplicate definitions for `id`
+...
+LL |     fn id() {}
+   |     ---------- other definition for `id`
+
+error[E0592]: duplicate definitions with name `bar`
+  --> $DIR/overlapping_inherent_impls.rs:19:5
+   |
+LL |     fn bar(&self) {}
+   |     ^^^^^^^^^^^^^^^^ duplicate definitions for `bar`
+...
+LL |     fn bar(&self) {}
+   |     ---------------- other definition for `bar`
+
+error[E0592]: duplicate definitions with name `baz`
+  --> $DIR/overlapping_inherent_impls.rs:29:5
+   |
+LL |     fn baz(&self) {}
+   |     ^^^^^^^^^^^^^^^^ duplicate definitions for `baz`
+...
+LL |     fn baz(&self) {}
+   |     ---------------- other definition for `baz`
+   |
+   = note: upstream crates may add new impl of trait `std::marker::Copy` for type `std::vec::Vec<_>` in future versions
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0592`.
diff --git a/src/test/ui/codemap_tests/tab.rs b/src/test/ui/codemap_tests/tab.rs
new file mode 100644
index 0000000..64569f2
--- /dev/null
+++ b/src/test/ui/codemap_tests/tab.rs
@@ -0,0 +1,9 @@
+// ignore-tidy-tab
+
+fn main() {
+	bar; //~ ERROR cannot find value `bar`
+}
+
+fn foo() {
+	"bar			boo" //~ ERROR mismatched types
+}
diff --git a/src/test/ui/codemap_tests/tab.stderr b/src/test/ui/codemap_tests/tab.stderr
new file mode 100644
index 0000000..bcc21e9
--- /dev/null
+++ b/src/test/ui/codemap_tests/tab.stderr
@@ -0,0 +1,21 @@
+error[E0425]: cannot find value `bar` in this scope
+  --> $DIR/tab.rs:4:2
+   |
+LL |     bar;
+   |     ^^^ not found in this scope
+
+error[E0308]: mismatched types
+  --> $DIR/tab.rs:8:2
+   |
+LL | fn foo() {
+   |          - help: try adding a return type: `-> &'static str`
+LL |     "bar            boo"
+   |     ^^^^^^^^^^^^^^^^^^^^ expected (), found reference
+   |
+   = note: expected type `()`
+              found type `&'static str`
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0308, E0425.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/codemap_tests/tab_2.rs b/src/test/ui/codemap_tests/tab_2.rs
new file mode 100644
index 0000000..644697c
--- /dev/null
+++ b/src/test/ui/codemap_tests/tab_2.rs
@@ -0,0 +1,5 @@
+// ignore-tidy-tab
+
+fn main() {
+				"""; //~ ERROR unterminated double quote
+}
diff --git a/src/test/ui/codemap_tests/tab_2.stderr b/src/test/ui/codemap_tests/tab_2.stderr
new file mode 100644
index 0000000..70414bb
--- /dev/null
+++ b/src/test/ui/codemap_tests/tab_2.stderr
@@ -0,0 +1,10 @@
+error: unterminated double quote string
+  --> $DIR/tab_2.rs:4:7
+   |
+LL |                   """;
+   |  ___________________^
+LL | | }
+   | |__^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/codemap_tests/tab_3.nll.stderr b/src/test/ui/codemap_tests/tab_3.nll.stderr
new file mode 100644
index 0000000..97816a7
--- /dev/null
+++ b/src/test/ui/codemap_tests/tab_3.nll.stderr
@@ -0,0 +1,14 @@
+error[E0382]: borrow of moved value: `some_vec`
+  --> $DIR/tab_3.rs:7:20
+   |
+LL |     let some_vec = vec!["hi"];
+   |         -------- move occurs because `some_vec` has type `std::vec::Vec<&str>`, which does not implement the `Copy` trait
+LL |     some_vec.into_iter();
+   |     -------- value moved here
+LL |     {
+LL |         println!("{:?}", some_vec);
+   |                          ^^^^^^^^ value borrowed here after move
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/codemap_tests/tab_3.rs b/src/test/ui/codemap_tests/tab_3.rs
new file mode 100644
index 0000000..4fd5b70
--- /dev/null
+++ b/src/test/ui/codemap_tests/tab_3.rs
@@ -0,0 +1,9 @@
+// ignore-tidy-tab
+
+fn main() {
+	let some_vec = vec!["hi"];
+	some_vec.into_iter();
+	{
+		println!("{:?}", some_vec); //~ ERROR use of moved
+	}
+}
diff --git a/src/test/ui/codemap_tests/tab_3.stderr b/src/test/ui/codemap_tests/tab_3.stderr
new file mode 100644
index 0000000..4b550db
--- /dev/null
+++ b/src/test/ui/codemap_tests/tab_3.stderr
@@ -0,0 +1,14 @@
+error[E0382]: use of moved value: `some_vec`
+  --> $DIR/tab_3.rs:7:20
+   |
+LL |     some_vec.into_iter();
+   |     -------- value moved here
+LL |     {
+LL |         println!("{:?}", some_vec);
+   |                          ^^^^^^^^ value used here after move
+   |
+   = note: move occurs because `some_vec` has type `std::vec::Vec<&str>`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/codemap_tests/two_files.rs b/src/test/ui/codemap_tests/two_files.rs
new file mode 100644
index 0000000..71d97d3
--- /dev/null
+++ b/src/test/ui/codemap_tests/two_files.rs
@@ -0,0 +1,7 @@
+include!("two_files_data.rs");
+
+struct Baz { }
+
+impl Bar for Baz { } //~ ERROR expected trait, found type alias
+
+fn main() { }
diff --git a/src/test/ui/codemap_tests/two_files.stderr b/src/test/ui/codemap_tests/two_files.stderr
new file mode 100644
index 0000000..5027b78
--- /dev/null
+++ b/src/test/ui/codemap_tests/two_files.stderr
@@ -0,0 +1,11 @@
+error[E0404]: expected trait, found type alias `Bar`
+  --> $DIR/two_files.rs:5:6
+   |
+LL | impl Bar for Baz { }
+   |      ^^^ type aliases cannot be used as traits
+   |
+   = note: did you mean to use a trait alias?
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0404`.
diff --git a/src/test/ui/codemap_tests/two_files_data.rs b/src/test/ui/codemap_tests/two_files_data.rs
new file mode 100644
index 0000000..db8ab14
--- /dev/null
+++ b/src/test/ui/codemap_tests/two_files_data.rs
@@ -0,0 +1,5 @@
+// ignore-test
+
+trait Foo { }
+
+type Bar = Foo;
diff --git a/src/test/ui/codemap_tests/unicode.rs b/src/test/ui/codemap_tests/unicode.rs
new file mode 100644
index 0000000..7180e90
--- /dev/null
+++ b/src/test/ui/codemap_tests/unicode.rs
@@ -0,0 +1,3 @@
+extern "路濫狼á́́" fn foo() {} //~ ERROR invalid ABI
+
+fn main() { }
diff --git a/src/test/ui/codemap_tests/unicode.stderr b/src/test/ui/codemap_tests/unicode.stderr
new file mode 100644
index 0000000..7aadeb7
--- /dev/null
+++ b/src/test/ui/codemap_tests/unicode.stderr
@@ -0,0 +1,11 @@
+error[E0703]: invalid ABI: found `路濫狼á́́`
+  --> $DIR/unicode.rs:1:8
+   |
+LL | extern "路濫狼á́́" fn foo() {}
+   |        ^^^^^^^^^ invalid ABI
+   |
+   = help: valid ABIs: cdecl, stdcall, fastcall, vectorcall, thiscall, aapcs, win64, sysv64, ptx-kernel, msp430-interrupt, x86-interrupt, amdgpu-kernel, Rust, C, system, rust-intrinsic, rust-call, platform-intrinsic, unadjusted
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0703`.
diff --git a/src/test/ui/codemap_tests/unicode_2.rs b/src/test/ui/codemap_tests/unicode_2.rs
new file mode 100644
index 0000000..fa69115
--- /dev/null
+++ b/src/test/ui/codemap_tests/unicode_2.rs
@@ -0,0 +1,7 @@
+#![feature(non_ascii_idents)]
+
+fn main() {
+    let _ = ("a̐éö̲", 0u7); //~ ERROR invalid width
+    let _ = ("아あ", 1i42); //~ ERROR invalid width
+    let _ = a̐é; //~ ERROR cannot find
+}
diff --git a/src/test/ui/codemap_tests/unicode_2.stderr b/src/test/ui/codemap_tests/unicode_2.stderr
new file mode 100644
index 0000000..92634d8
--- /dev/null
+++ b/src/test/ui/codemap_tests/unicode_2.stderr
@@ -0,0 +1,25 @@
+error: invalid width `7` for integer literal
+  --> $DIR/unicode_2.rs:4:25
+   |
+LL |     let _ = ("a̐éö̲", 0u7);
+   |                     ^^^
+   |
+   = help: valid widths are 8, 16, 32, 64 and 128
+
+error: invalid width `42` for integer literal
+  --> $DIR/unicode_2.rs:5:20
+   |
+LL |     let _ = ("아あ", 1i42);
+   |                      ^^^^
+   |
+   = help: valid widths are 8, 16, 32, 64 and 128
+
+error[E0425]: cannot find value `a̐é` in this scope
+  --> $DIR/unicode_2.rs:6:13
+   |
+LL |     let _ = a̐é;
+   |             ^^ not found in this scope
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/codemap_tests/unicode_3.rs b/src/test/ui/codemap_tests/unicode_3.rs
new file mode 100644
index 0000000..ff6d544
--- /dev/null
+++ b/src/test/ui/codemap_tests/unicode_3.rs
@@ -0,0 +1,6 @@
+// compile-pass
+
+fn main() {
+    let s = "ZͨA͑ͦ͒͋ͤ͑̚L̄͑͋Ĝͨͥ̿͒̽̈́Oͥ͛ͭ!̏"; while true { break; }
+    println!("{}", s);
+}
diff --git a/src/test/ui/codemap_tests/unicode_3.stderr b/src/test/ui/codemap_tests/unicode_3.stderr
new file mode 100644
index 0000000..56f4f73
--- /dev/null
+++ b/src/test/ui/codemap_tests/unicode_3.stderr
@@ -0,0 +1,8 @@
+warning: denote infinite loops with `loop { ... }`
+  --> $DIR/unicode_3.rs:4:45
+   |
+LL |     let s = "ZͨA͑ͦ͒͋ͤ͑̚L̄͑͋Ĝͨͥ̿͒̽̈́Oͥ͛ͭ!̏"; while true { break; }
+   |                       ^^^^^^^^^^ help: use `loop`
+   |
+   = note: #[warn(while_true)] on by default
+
diff --git a/src/test/ui/coercion/coerce-expect-unsized-ascribed.rs b/src/test/ui/coercion/coerce-expect-unsized-ascribed.rs
new file mode 100644
index 0000000..9a4e134
--- /dev/null
+++ b/src/test/ui/coercion/coerce-expect-unsized-ascribed.rs
@@ -0,0 +1,32 @@
+// A version of coerce-expect-unsized that uses type ascription.
+// Doesn't work so far, but supposed to work eventually
+
+#![feature(box_syntax, type_ascription)]
+
+use std::fmt::Debug;
+
+pub fn main() {
+    let _ = box { [1, 2, 3] }: Box<[i32]>; //~ ERROR mismatched types
+    let _ = box if true { [1, 2, 3] } else { [1, 3, 4] }: Box<[i32]>; //~ ERROR mismatched types
+    let _ = box match true { true => [1, 2, 3], false => [1, 3, 4] }: Box<[i32]>;
+    //~^ ERROR mismatched types
+    let _ = box { |x| (x as u8) }: Box<Fn(i32) -> _>; //~ ERROR mismatched types
+    let _ = box if true { false } else { true }: Box<Debug>; //~ ERROR mismatched types
+    let _ = box match true { true => 'a', false => 'b' }: Box<Debug>; //~ ERROR mismatched types
+
+    let _ = &{ [1, 2, 3] }: &[i32]; //~ ERROR mismatched types
+    let _ = &if true { [1, 2, 3] } else { [1, 3, 4] }: &[i32]; //~ ERROR mismatched types
+    let _ = &match true { true => [1, 2, 3], false => [1, 3, 4] }: &[i32];
+    //~^ ERROR mismatched types
+    let _ = &{ |x| (x as u8) }: &Fn(i32) -> _; //~ ERROR mismatched types
+    let _ = &if true { false } else { true }: &Debug; //~ ERROR mismatched types
+    let _ = &match true { true => 'a', false => 'b' }: &Debug; //~ ERROR mismatched types
+
+    let _ = Box::new([1, 2, 3]): Box<[i32]>; //~ ERROR mismatched types
+    let _ = Box::new(|x| (x as u8)): Box<Fn(i32) -> _>; //~ ERROR mismatched types
+
+    let _ = vec![
+        Box::new(|x| (x as u8)),
+        box |x| (x as i16 as u8),
+    ]: Vec<Box<Fn(i32) -> _>>;
+}
diff --git a/src/test/ui/coercion/coerce-expect-unsized-ascribed.stderr b/src/test/ui/coercion/coerce-expect-unsized-ascribed.stderr
new file mode 100644
index 0000000..be362c9
--- /dev/null
+++ b/src/test/ui/coercion/coerce-expect-unsized-ascribed.stderr
@@ -0,0 +1,129 @@
+error[E0308]: mismatched types
+  --> $DIR/coerce-expect-unsized-ascribed.rs:9:13
+   |
+LL |     let _ = box { [1, 2, 3] }: Box<[i32]>;
+   |             ^^^^^^^^^^^^^^^^^ expected slice, found array of 3 elements
+   |
+   = note: expected type `std::boxed::Box<[i32]>`
+              found type `std::boxed::Box<[i32; 3]>`
+
+error[E0308]: mismatched types
+  --> $DIR/coerce-expect-unsized-ascribed.rs:10:13
+   |
+LL |     let _ = box if true { [1, 2, 3] } else { [1, 3, 4] }: Box<[i32]>;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected slice, found array of 3 elements
+   |
+   = note: expected type `std::boxed::Box<[i32]>`
+              found type `std::boxed::Box<[i32; 3]>`
+
+error[E0308]: mismatched types
+  --> $DIR/coerce-expect-unsized-ascribed.rs:11:13
+   |
+LL |     let _ = box match true { true => [1, 2, 3], false => [1, 3, 4] }: Box<[i32]>;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected slice, found array of 3 elements
+   |
+   = note: expected type `std::boxed::Box<[i32]>`
+              found type `std::boxed::Box<[i32; 3]>`
+
+error[E0308]: mismatched types
+  --> $DIR/coerce-expect-unsized-ascribed.rs:13:13
+   |
+LL |     let _ = box { |x| (x as u8) }: Box<Fn(i32) -> _>;
+   |             ^^^^^^^^^^^^^^^^^^^^^ expected trait std::ops::Fn, found closure
+   |
+   = note: expected type `std::boxed::Box<dyn std::ops::Fn(i32) -> u8>`
+              found type `std::boxed::Box<[closure@$DIR/coerce-expect-unsized-ascribed.rs:13:19: 13:32]>`
+
+error[E0308]: mismatched types
+  --> $DIR/coerce-expect-unsized-ascribed.rs:14:13
+   |
+LL |     let _ = box if true { false } else { true }: Box<Debug>;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait std::fmt::Debug, found bool
+   |
+   = note: expected type `std::boxed::Box<dyn std::fmt::Debug>`
+              found type `std::boxed::Box<bool>`
+
+error[E0308]: mismatched types
+  --> $DIR/coerce-expect-unsized-ascribed.rs:15:13
+   |
+LL |     let _ = box match true { true => 'a', false => 'b' }: Box<Debug>;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait std::fmt::Debug, found char
+   |
+   = note: expected type `std::boxed::Box<dyn std::fmt::Debug>`
+              found type `std::boxed::Box<char>`
+
+error[E0308]: mismatched types
+  --> $DIR/coerce-expect-unsized-ascribed.rs:17:13
+   |
+LL |     let _ = &{ [1, 2, 3] }: &[i32];
+   |             ^^^^^^^^^^^^^^ expected slice, found array of 3 elements
+   |
+   = note: expected type `&[i32]`
+              found type `&[i32; 3]`
+
+error[E0308]: mismatched types
+  --> $DIR/coerce-expect-unsized-ascribed.rs:18:13
+   |
+LL |     let _ = &if true { [1, 2, 3] } else { [1, 3, 4] }: &[i32];
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected slice, found array of 3 elements
+   |
+   = note: expected type `&[i32]`
+              found type `&[i32; 3]`
+
+error[E0308]: mismatched types
+  --> $DIR/coerce-expect-unsized-ascribed.rs:19:13
+   |
+LL |     let _ = &match true { true => [1, 2, 3], false => [1, 3, 4] }: &[i32];
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected slice, found array of 3 elements
+   |
+   = note: expected type `&[i32]`
+              found type `&[i32; 3]`
+
+error[E0308]: mismatched types
+  --> $DIR/coerce-expect-unsized-ascribed.rs:21:13
+   |
+LL |     let _ = &{ |x| (x as u8) }: &Fn(i32) -> _;
+   |             ^^^^^^^^^^^^^^^^^^ expected trait std::ops::Fn, found closure
+   |
+   = note: expected type `&dyn std::ops::Fn(i32) -> u8`
+              found type `&[closure@$DIR/coerce-expect-unsized-ascribed.rs:21:16: 21:29]`
+
+error[E0308]: mismatched types
+  --> $DIR/coerce-expect-unsized-ascribed.rs:22:13
+   |
+LL |     let _ = &if true { false } else { true }: &Debug;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait std::fmt::Debug, found bool
+   |
+   = note: expected type `&dyn std::fmt::Debug`
+              found type `&bool`
+
+error[E0308]: mismatched types
+  --> $DIR/coerce-expect-unsized-ascribed.rs:23:13
+   |
+LL |     let _ = &match true { true => 'a', false => 'b' }: &Debug;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait std::fmt::Debug, found char
+   |
+   = note: expected type `&dyn std::fmt::Debug`
+              found type `&char`
+
+error[E0308]: mismatched types
+  --> $DIR/coerce-expect-unsized-ascribed.rs:25:13
+   |
+LL |     let _ = Box::new([1, 2, 3]): Box<[i32]>;
+   |             ^^^^^^^^^^^^^^^^^^^ expected slice, found array of 3 elements
+   |
+   = note: expected type `std::boxed::Box<[i32]>`
+              found type `std::boxed::Box<[i32; 3]>`
+
+error[E0308]: mismatched types
+  --> $DIR/coerce-expect-unsized-ascribed.rs:26:13
+   |
+LL |     let _ = Box::new(|x| (x as u8)): Box<Fn(i32) -> _>;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^ expected trait std::ops::Fn, found closure
+   |
+   = note: expected type `std::boxed::Box<dyn std::ops::Fn(i32) -> _>`
+              found type `std::boxed::Box<[closure@$DIR/coerce-expect-unsized-ascribed.rs:26:22: 26:35]>`
+
+error: aborting due to 14 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/coercion/coerce-issue-49593-box-never.rs b/src/test/ui/coercion/coerce-issue-49593-box-never.rs
new file mode 100644
index 0000000..81723bb
--- /dev/null
+++ b/src/test/ui/coercion/coerce-issue-49593-box-never.rs
@@ -0,0 +1,52 @@
+// compile-pass
+
+#![feature(never_type)]
+#![allow(unreachable_code)]
+
+use std::error::Error;
+use std::mem;
+
+fn raw_ptr_box<T>(t: T) -> *mut T {
+    panic!()
+}
+
+fn foo(x: !) -> Box<dyn Error> {
+    /* *mut $0 is coerced to Box<dyn Error> here */ Box::<_ /* ! */>::new(x)
+}
+
+fn foo_raw_ptr(x: !) -> *mut dyn Error {
+    /* *mut $0 is coerced to *mut Error here */ raw_ptr_box::<_ /* ! */>(x)
+}
+
+fn no_coercion(d: *mut dyn Error) -> *mut dyn Error {
+    /* an unsize coercion won't compile here, and it is indeed not used
+       because there is nothing requiring the _ to be Sized */
+    d as *mut _
+}
+
+trait Xyz {}
+struct S;
+struct T;
+impl Xyz for S {}
+impl Xyz for T {}
+
+fn foo_no_never() {
+    let mut x /* : Option<S> */ = None;
+    let mut first_iter = false;
+    loop {
+        if !first_iter {
+            let y: Box<dyn Xyz>
+                = /* Box<$0> is coerced to Box<Xyz> here */ Box::new(x.unwrap());
+        }
+
+        x = Some(S);
+        first_iter = true;
+    }
+
+    let mut y : Option<S> = None;
+    // assert types are equal
+    mem::swap(&mut x, &mut y);
+}
+
+fn main() {
+}
diff --git a/src/test/ui/coercion/coerce-mut.rs b/src/test/ui/coercion/coerce-mut.rs
new file mode 100644
index 0000000..409fb8e
--- /dev/null
+++ b/src/test/ui/coercion/coerce-mut.rs
@@ -0,0 +1,10 @@
+fn f(x: &mut i32) {}
+
+fn main() {
+    let x = 0;
+    f(&x);
+    //~^ ERROR mismatched types
+    //~| expected type `&mut i32`
+    //~| found type `&{integer}`
+    //~| types differ in mutability
+}
diff --git a/src/test/ui/coercion/coerce-mut.stderr b/src/test/ui/coercion/coerce-mut.stderr
new file mode 100644
index 0000000..f8e3d6e
--- /dev/null
+++ b/src/test/ui/coercion/coerce-mut.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/coerce-mut.rs:5:7
+   |
+LL |     f(&x);
+   |       ^^ types differ in mutability
+   |
+   = note: expected type `&mut i32`
+              found type `&{integer}`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/coercion/coerce-overloaded-autoderef.ast.nll.stderr b/src/test/ui/coercion/coerce-overloaded-autoderef.ast.nll.stderr
new file mode 100644
index 0000000..5b9249c
--- /dev/null
+++ b/src/test/ui/coercion/coerce-overloaded-autoderef.ast.nll.stderr
@@ -0,0 +1,46 @@
+error[E0499]: cannot borrow `*x` as mutable more than once at a time
+  --> $DIR/coerce-overloaded-autoderef.rs:12:24
+   |
+LL |     let y = borrow_mut(x);
+   |                        - first mutable borrow occurs here
+LL |     let z = borrow_mut(x);
+   |                        ^ second mutable borrow occurs here
+...
+LL |     drop((y, z));
+   |           - first borrow later used here
+
+error[E0506]: cannot assign to `**x` because it is borrowed
+  --> $DIR/coerce-overloaded-autoderef.rs:21:5
+   |
+LL |     let y = borrow(x);
+   |                    - borrow of `**x` occurs here
+LL |     let z = borrow(x);
+LL |     **x += 1;
+   |     ^^^^^^^^ assignment to borrowed `**x` occurs here
+...
+LL |     drop((y, z));
+   |           - borrow later used here
+
+error[E0499]: cannot borrow `*x` as mutable more than once at a time
+  --> $DIR/coerce-overloaded-autoderef.rs:28:20
+   |
+LL |     borrow_mut2(x, x);
+   |     ----------- -  ^ second mutable borrow occurs here
+   |     |           |
+   |     |           first mutable borrow occurs here
+   |     first borrow later used by call
+
+error[E0502]: cannot borrow `*x` as mutable because it is also borrowed as immutable
+  --> $DIR/coerce-overloaded-autoderef.rs:34:5
+   |
+LL |     borrow2(x, x);
+   |     -------^^^^-^
+   |     |          |
+   |     |          immutable borrow occurs here
+   |     mutable borrow occurs here
+   |     immutable borrow later used by call
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0499, E0502, E0506.
+For more information about an error, try `rustc --explain E0499`.
diff --git a/src/test/ui/coercion/coerce-overloaded-autoderef.ast.stderr b/src/test/ui/coercion/coerce-overloaded-autoderef.ast.stderr
new file mode 100644
index 0000000..54215f5
--- /dev/null
+++ b/src/test/ui/coercion/coerce-overloaded-autoderef.ast.stderr
@@ -0,0 +1,42 @@
+error[E0499]: cannot borrow `*x` as mutable more than once at a time
+  --> $DIR/coerce-overloaded-autoderef.rs:12:24
+   |
+LL |     let y = borrow_mut(x);
+   |                        - first mutable borrow occurs here
+LL |     let z = borrow_mut(x);
+   |                        ^ second mutable borrow occurs here
+...
+LL | }
+   | - first borrow ends here
+
+error[E0506]: cannot assign to `**x` because it is borrowed
+  --> $DIR/coerce-overloaded-autoderef.rs:21:5
+   |
+LL |     let y = borrow(x);
+   |                    - borrow of `**x` occurs here
+LL |     let z = borrow(x);
+LL |     **x += 1;
+   |     ^^^^^^^^ assignment to borrowed `**x` occurs here
+
+error[E0499]: cannot borrow `*x` as mutable more than once at a time
+  --> $DIR/coerce-overloaded-autoderef.rs:28:20
+   |
+LL |     borrow_mut2(x, x);
+   |                 -  ^- first borrow ends here
+   |                 |  |
+   |                 |  second mutable borrow occurs here
+   |                 first mutable borrow occurs here
+
+error[E0502]: cannot borrow `*x` as immutable because it is also borrowed as mutable
+  --> $DIR/coerce-overloaded-autoderef.rs:34:16
+   |
+LL |     borrow2(x, x);
+   |             -  ^- mutable borrow ends here
+   |             |  |
+   |             |  immutable borrow occurs here
+   |             mutable borrow occurs here
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0499, E0502, E0506.
+For more information about an error, try `rustc --explain E0499`.
diff --git a/src/test/ui/coercion/coerce-overloaded-autoderef.mir.nll.stderr b/src/test/ui/coercion/coerce-overloaded-autoderef.mir.nll.stderr
new file mode 100644
index 0000000..5b9249c
--- /dev/null
+++ b/src/test/ui/coercion/coerce-overloaded-autoderef.mir.nll.stderr
@@ -0,0 +1,46 @@
+error[E0499]: cannot borrow `*x` as mutable more than once at a time
+  --> $DIR/coerce-overloaded-autoderef.rs:12:24
+   |
+LL |     let y = borrow_mut(x);
+   |                        - first mutable borrow occurs here
+LL |     let z = borrow_mut(x);
+   |                        ^ second mutable borrow occurs here
+...
+LL |     drop((y, z));
+   |           - first borrow later used here
+
+error[E0506]: cannot assign to `**x` because it is borrowed
+  --> $DIR/coerce-overloaded-autoderef.rs:21:5
+   |
+LL |     let y = borrow(x);
+   |                    - borrow of `**x` occurs here
+LL |     let z = borrow(x);
+LL |     **x += 1;
+   |     ^^^^^^^^ assignment to borrowed `**x` occurs here
+...
+LL |     drop((y, z));
+   |           - borrow later used here
+
+error[E0499]: cannot borrow `*x` as mutable more than once at a time
+  --> $DIR/coerce-overloaded-autoderef.rs:28:20
+   |
+LL |     borrow_mut2(x, x);
+   |     ----------- -  ^ second mutable borrow occurs here
+   |     |           |
+   |     |           first mutable borrow occurs here
+   |     first borrow later used by call
+
+error[E0502]: cannot borrow `*x` as mutable because it is also borrowed as immutable
+  --> $DIR/coerce-overloaded-autoderef.rs:34:5
+   |
+LL |     borrow2(x, x);
+   |     -------^^^^-^
+   |     |          |
+   |     |          immutable borrow occurs here
+   |     mutable borrow occurs here
+   |     immutable borrow later used by call
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0499, E0502, E0506.
+For more information about an error, try `rustc --explain E0499`.
diff --git a/src/test/ui/coercion/coerce-overloaded-autoderef.mir.stderr b/src/test/ui/coercion/coerce-overloaded-autoderef.mir.stderr
new file mode 100644
index 0000000..8dc6fe5
--- /dev/null
+++ b/src/test/ui/coercion/coerce-overloaded-autoderef.mir.stderr
@@ -0,0 +1,45 @@
+error[E0499]: cannot borrow `*x` as mutable more than once at a time
+  --> $DIR/coerce-overloaded-autoderef.rs:12:24
+   |
+LL |     let y = borrow_mut(x);
+   |                        - first mutable borrow occurs here
+LL |     let z = borrow_mut(x);
+   |                        ^ second mutable borrow occurs here
+...
+LL |     drop((y, z));
+   |           - first borrow later used here
+
+error[E0506]: cannot assign to `**x` because it is borrowed
+  --> $DIR/coerce-overloaded-autoderef.rs:21:5
+   |
+LL |     let y = borrow(x);
+   |                    - borrow of `**x` occurs here
+LL |     let z = borrow(x);
+LL |     **x += 1;
+   |     ^^^^^^^^ assignment to borrowed `**x` occurs here
+...
+LL |     drop((y, z));
+   |           - borrow later used here
+
+error[E0499]: cannot borrow `*x` as mutable more than once at a time
+  --> $DIR/coerce-overloaded-autoderef.rs:28:20
+   |
+LL |     borrow_mut2(x, x);
+   |     ----------- -  ^ second mutable borrow occurs here
+   |     |           |
+   |     |           first mutable borrow occurs here
+   |     first borrow later used by call
+
+error[E0502]: cannot borrow `*x` as immutable because it is also borrowed as mutable
+  --> $DIR/coerce-overloaded-autoderef.rs:34:16
+   |
+LL |     borrow2(x, x);
+   |     ------- -  ^ immutable borrow occurs here
+   |     |       |
+   |     |       mutable borrow occurs here
+   |     mutable borrow later used by call
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0499, E0502, E0506.
+For more information about an error, try `rustc --explain E0499`.
diff --git a/src/test/ui/coercion/coerce-overloaded-autoderef.rs b/src/test/ui/coercion/coerce-overloaded-autoderef.rs
new file mode 100644
index 0000000..ec72745
--- /dev/null
+++ b/src/test/ui/coercion/coerce-overloaded-autoderef.rs
@@ -0,0 +1,39 @@
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+fn borrow_mut<T>(x: &mut T) -> &mut T { x }
+fn borrow<T>(x: &T) -> &T { x }
+
+fn borrow_mut2<T>(_: &mut T, _: &mut T) {}
+fn borrow2<T>(_: &mut T, _: &T) {}
+
+fn double_mut_borrow<T>(x: &mut Box<T>) {
+    let y = borrow_mut(x);
+    let z = borrow_mut(x);
+    //[ast]~^ ERROR cannot borrow `*x` as mutable more than once at a time
+    //[mir]~^^ ERROR cannot borrow `*x` as mutable more than once at a time
+    drop((y, z));
+}
+
+fn double_imm_borrow(x: &mut Box<i32>) {
+    let y = borrow(x);
+    let z = borrow(x);
+    **x += 1;
+    //[ast]~^ ERROR cannot assign to `**x` because it is borrowed
+    //[mir]~^^ ERROR cannot assign to `**x` because it is borrowed
+    drop((y, z));
+}
+
+fn double_mut_borrow2<T>(x: &mut Box<T>) {
+    borrow_mut2(x, x);
+    //[ast]~^ ERROR cannot borrow `*x` as mutable more than once at a time
+    //[mir]~^^ ERROR cannot borrow `*x` as mutable more than once at a time
+}
+
+fn double_borrow2<T>(x: &mut Box<T>) {
+    borrow2(x, x);
+    //[ast]~^ ERROR cannot borrow `*x` as immutable because it is also borrowed as mutable
+    //[mir]~^^ ERROR cannot borrow `*x` as immutable because it is also borrowed as mutable
+}
+
+pub fn main() {}
diff --git a/src/test/ui/coercion/coerce-to-bang-cast.rs b/src/test/ui/coercion/coerce-to-bang-cast.rs
new file mode 100644
index 0000000..8ef1948
--- /dev/null
+++ b/src/test/ui/coercion/coerce-to-bang-cast.rs
@@ -0,0 +1,14 @@
+#![feature(never_type)]
+
+fn foo(x: usize, y: !, z: usize) { }
+
+fn cast_a() {
+    let y = {return; 22} as !;
+    //~^ ERROR non-primitive cast
+}
+
+fn cast_b() {
+    let y = 22 as !; //~ ERROR non-primitive cast
+}
+
+fn main() { }
diff --git a/src/test/ui/coercion/coerce-to-bang-cast.stderr b/src/test/ui/coercion/coerce-to-bang-cast.stderr
new file mode 100644
index 0000000..ff30ebc
--- /dev/null
+++ b/src/test/ui/coercion/coerce-to-bang-cast.stderr
@@ -0,0 +1,19 @@
+error[E0605]: non-primitive cast: `i32` as `!`
+  --> $DIR/coerce-to-bang-cast.rs:6:13
+   |
+LL |     let y = {return; 22} as !;
+   |             ^^^^^^^^^^^^^^^^^
+   |
+   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+
+error[E0605]: non-primitive cast: `i32` as `!`
+  --> $DIR/coerce-to-bang-cast.rs:11:13
+   |
+LL |     let y = 22 as !;
+   |             ^^^^^^^
+   |
+   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0605`.
diff --git a/src/test/ui/coercion/coerce-to-bang.rs b/src/test/ui/coercion/coerce-to-bang.rs
new file mode 100644
index 0000000..1e06934
--- /dev/null
+++ b/src/test/ui/coercion/coerce-to-bang.rs
@@ -0,0 +1,79 @@
+#![feature(never_type)]
+
+fn foo(x: usize, y: !, z: usize) { }
+
+fn call_foo_a() {
+    foo(return, 22, 44);
+    //~^ ERROR mismatched types
+}
+
+fn call_foo_b() {
+    // Divergence happens in the argument itself, definitely ok.
+    foo(22, return, 44);
+}
+
+fn call_foo_c() {
+    // This test fails because the divergence happens **after** the
+    // coercion to `!`:
+    foo(22, 44, return); //~ ERROR mismatched types
+}
+
+fn call_foo_d() {
+    // This test passes because `a` has type `!`:
+    let a: ! = return;
+    let b = 22;
+    let c = 44;
+    foo(a, b, c); // ... and hence a reference to `a` is expected to diverge.
+    //~^ ERROR mismatched types
+}
+
+fn call_foo_e() {
+    // This test probably could pass but we don't *know* that `a`
+    // has type `!` so we don't let it work.
+    let a = return;
+    let b = 22;
+    let c = 44;
+    foo(a, b, c); //~ ERROR mismatched types
+}
+
+fn call_foo_f() {
+    // This fn fails because `a` has type `usize`, and hence a
+    // reference to is it **not** considered to diverge.
+    let a: usize = return;
+    let b = 22;
+    let c = 44;
+    foo(a, b, c); //~ ERROR mismatched types
+}
+
+fn array_a() {
+    // Return is coerced to `!` just fine, but `22` cannot be.
+    let x: [!; 2] = [return, 22]; //~ ERROR mismatched types
+}
+
+fn array_b() {
+    // Error: divergence has not yet occurred.
+    let x: [!; 2] = [22, return]; //~ ERROR mismatched types
+}
+
+fn tuple_a() {
+    // No divergence at all.
+    let x: (usize, !, usize) = (22, 44, 66); //~ ERROR mismatched types
+}
+
+fn tuple_b() {
+    // Divergence happens before coercion: OK
+    let x: (usize, !, usize) = (return, 44, 66);
+    //~^ ERROR mismatched types
+}
+
+fn tuple_c() {
+    // Divergence happens before coercion: OK
+    let x: (usize, !, usize) = (22, return, 66);
+}
+
+fn tuple_d() {
+    // Error: divergence happens too late
+    let x: (usize, !, usize) = (22, 44, return); //~ ERROR mismatched types
+}
+
+fn main() { }
diff --git a/src/test/ui/coercion/coerce-to-bang.stderr b/src/test/ui/coercion/coerce-to-bang.stderr
new file mode 100644
index 0000000..a46e97d
--- /dev/null
+++ b/src/test/ui/coercion/coerce-to-bang.stderr
@@ -0,0 +1,93 @@
+error[E0308]: mismatched types
+  --> $DIR/coerce-to-bang.rs:6:17
+   |
+LL |     foo(return, 22, 44);
+   |                 ^^ expected !, found integer
+   |
+   = note: expected type `!`
+              found type `{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/coerce-to-bang.rs:18:13
+   |
+LL |     foo(22, 44, return);
+   |             ^^ expected !, found integer
+   |
+   = note: expected type `!`
+              found type `{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/coerce-to-bang.rs:26:12
+   |
+LL |     foo(a, b, c); // ... and hence a reference to `a` is expected to diverge.
+   |            ^ expected !, found integer
+   |
+   = note: expected type `!`
+              found type `{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/coerce-to-bang.rs:36:12
+   |
+LL |     foo(a, b, c);
+   |            ^ expected !, found integer
+   |
+   = note: expected type `!`
+              found type `{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/coerce-to-bang.rs:45:12
+   |
+LL |     foo(a, b, c);
+   |            ^ expected !, found integer
+   |
+   = note: expected type `!`
+              found type `{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/coerce-to-bang.rs:50:21
+   |
+LL |     let x: [!; 2] = [return, 22];
+   |                     ^^^^^^^^^^^^ expected !, found integer
+   |
+   = note: expected type `[!; 2]`
+              found type `[{integer}; 2]`
+
+error[E0308]: mismatched types
+  --> $DIR/coerce-to-bang.rs:55:22
+   |
+LL |     let x: [!; 2] = [22, return];
+   |                      ^^ expected !, found integer
+   |
+   = note: expected type `!`
+              found type `{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/coerce-to-bang.rs:60:37
+   |
+LL |     let x: (usize, !, usize) = (22, 44, 66);
+   |                                     ^^ expected !, found integer
+   |
+   = note: expected type `!`
+              found type `{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/coerce-to-bang.rs:65:41
+   |
+LL |     let x: (usize, !, usize) = (return, 44, 66);
+   |                                         ^^ expected !, found integer
+   |
+   = note: expected type `!`
+              found type `{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/coerce-to-bang.rs:76:37
+   |
+LL |     let x: (usize, !, usize) = (22, 44, return);
+   |                                     ^^ expected !, found integer
+   |
+   = note: expected type `!`
+              found type `{integer}`
+
+error: aborting due to 10 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/coercion/coercion-missing-tail-expected-type.rs b/src/test/ui/coercion/coercion-missing-tail-expected-type.rs
new file mode 100644
index 0000000..20a4407
--- /dev/null
+++ b/src/test/ui/coercion/coercion-missing-tail-expected-type.rs
@@ -0,0 +1,14 @@
+// #41425 -- error message "mismatched types" has wrong types
+
+fn plus_one(x: i32) -> i32 { //~ ERROR mismatched types
+    x + 1;
+}
+
+fn foo() -> Result<u8, u64> { //~ ERROR mismatched types
+    Ok(1);
+}
+
+fn main() {
+    let x = plus_one(5);
+    println!("X = {}", x);
+}
diff --git a/src/test/ui/coercion/coercion-missing-tail-expected-type.stderr b/src/test/ui/coercion/coercion-missing-tail-expected-type.stderr
new file mode 100644
index 0000000..057de5b
--- /dev/null
+++ b/src/test/ui/coercion/coercion-missing-tail-expected-type.stderr
@@ -0,0 +1,29 @@
+error[E0308]: mismatched types
+  --> $DIR/coercion-missing-tail-expected-type.rs:3:24
+   |
+LL | fn plus_one(x: i32) -> i32 {
+   |    --------            ^^^ expected i32, found ()
+   |    |
+   |    this function's body doesn't return
+LL |     x + 1;
+   |          - help: consider removing this semicolon
+   |
+   = note: expected type `i32`
+              found type `()`
+
+error[E0308]: mismatched types
+  --> $DIR/coercion-missing-tail-expected-type.rs:7:13
+   |
+LL | fn foo() -> Result<u8, u64> {
+   |    ---      ^^^^^^^^^^^^^^^ expected enum `std::result::Result`, found ()
+   |    |
+   |    this function's body doesn't return
+LL |     Ok(1);
+   |          - help: consider removing this semicolon
+   |
+   = note: expected type `std::result::Result<u8, u64>`
+              found type `()`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/coercion/coercion-slice.rs b/src/test/ui/coercion/coercion-slice.rs
new file mode 100644
index 0000000..312b634
--- /dev/null
+++ b/src/test/ui/coercion/coercion-slice.rs
@@ -0,0 +1,8 @@
+// Tests that we forbid coercion from `[T; n]` to `&[T]`
+
+fn main() {
+    let _: &[i32] = [0];
+    //~^ ERROR mismatched types
+    //~| expected type `&[i32]`
+    //~| expected &[i32], found array of 1 elements
+}
diff --git a/src/test/ui/coercion/coercion-slice.stderr b/src/test/ui/coercion/coercion-slice.stderr
new file mode 100644
index 0000000..6fa7123
--- /dev/null
+++ b/src/test/ui/coercion/coercion-slice.stderr
@@ -0,0 +1,15 @@
+error[E0308]: mismatched types
+  --> $DIR/coercion-slice.rs:4:21
+   |
+LL |     let _: &[i32] = [0];
+   |                     ^^^
+   |                     |
+   |                     expected &[i32], found array of 1 elements
+   |                     help: consider borrowing here: `&[0]`
+   |
+   = note: expected type `&[i32]`
+              found type `[{integer}; 1]`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/coherence/auxiliary/coherence_copy_like_lib.rs b/src/test/ui/coherence/auxiliary/coherence_copy_like_lib.rs
new file mode 100644
index 0000000..b5b4802
--- /dev/null
+++ b/src/test/ui/coherence/auxiliary/coherence_copy_like_lib.rs
@@ -0,0 +1,10 @@
+#![crate_type = "rlib"]
+#![feature(fundamental)]
+
+pub trait MyCopy { }
+impl MyCopy for i32 { }
+
+pub struct MyStruct<T>(T);
+
+#[fundamental]
+pub struct MyFundamentalStruct<T>(T);
diff --git a/src/test/ui/coherence/auxiliary/coherence_fundamental_trait_lib.rs b/src/test/ui/coherence/auxiliary/coherence_fundamental_trait_lib.rs
new file mode 100644
index 0000000..21aaea4
--- /dev/null
+++ b/src/test/ui/coherence/auxiliary/coherence_fundamental_trait_lib.rs
@@ -0,0 +1,7 @@
+#![crate_type = "rlib"]
+#![feature(fundamental)]
+
+pub trait Misc {}
+
+#[fundamental]
+pub trait Fundamental<T> {}
diff --git a/src/test/ui/coherence/auxiliary/coherence_inherent_cc_lib.rs b/src/test/ui/coherence/auxiliary/coherence_inherent_cc_lib.rs
new file mode 100644
index 0000000..08d22fb
--- /dev/null
+++ b/src/test/ui/coherence/auxiliary/coherence_inherent_cc_lib.rs
@@ -0,0 +1,11 @@
+// See coherence_inherent_cc.rs
+
+pub trait TheTrait {
+    fn the_fn(&self);
+}
+
+pub struct TheStruct;
+
+impl TheTrait for TheStruct {
+    fn the_fn(&self) {}
+}
diff --git a/src/test/ui/coherence/auxiliary/coherence_lib.rs b/src/test/ui/coherence/auxiliary/coherence_lib.rs
new file mode 100644
index 0000000..9a5ec82
--- /dev/null
+++ b/src/test/ui/coherence/auxiliary/coherence_lib.rs
@@ -0,0 +1,15 @@
+#![crate_type="lib"]
+
+pub trait Remote {
+    fn foo(&self) { }
+}
+
+pub trait Remote1<T> {
+    fn foo(&self, t: T) { }
+}
+
+pub trait Remote2<T, U> {
+    fn foo(&self, t: T, u: U) { }
+}
+
+pub struct Pair<T,U>(T,U);
diff --git a/src/test/ui/coherence/auxiliary/coherence_orphan_lib.rs b/src/test/ui/coherence/auxiliary/coherence_orphan_lib.rs
new file mode 100644
index 0000000..2664ef5
--- /dev/null
+++ b/src/test/ui/coherence/auxiliary/coherence_orphan_lib.rs
@@ -0,0 +1,3 @@
+pub trait TheTrait<T> {
+    fn the_fn(&self);
+}
diff --git a/src/test/ui/coherence/auxiliary/go_trait.rs b/src/test/ui/coherence/auxiliary/go_trait.rs
new file mode 100644
index 0000000..aa0ec22
--- /dev/null
+++ b/src/test/ui/coherence/auxiliary/go_trait.rs
@@ -0,0 +1,43 @@
+#![feature(specialization)]
+
+// Common code used for tests that model the Fn/FnMut/FnOnce hierarchy.
+
+pub trait Go {
+    fn go(&self, arg: isize);
+}
+
+pub fn go<G:Go>(this: &G, arg: isize) {
+    this.go(arg)
+}
+
+pub trait GoMut {
+    fn go_mut(&mut self, arg: isize);
+}
+
+pub fn go_mut<G:GoMut>(this: &mut G, arg: isize) {
+    this.go_mut(arg)
+}
+
+pub trait GoOnce {
+    fn go_once(self, arg: isize);
+}
+
+pub fn go_once<G:GoOnce>(this: G, arg: isize) {
+    this.go_once(arg)
+}
+
+impl<G> GoMut for G
+    where G : Go
+{
+    default fn go_mut(&mut self, arg: isize) {
+        go(&*self, arg)
+    }
+}
+
+impl<G> GoOnce for G
+    where G : GoMut
+{
+    default fn go_once(mut self, arg: isize) {
+        go_mut(&mut self, arg)
+    }
+}
diff --git a/src/test/ui/coherence/auxiliary/re_rebalance_coherence_lib.rs b/src/test/ui/coherence/auxiliary/re_rebalance_coherence_lib.rs
new file mode 100644
index 0000000..c8d027b
--- /dev/null
+++ b/src/test/ui/coherence/auxiliary/re_rebalance_coherence_lib.rs
@@ -0,0 +1,23 @@
+
+pub trait Backend{}
+pub trait SupportsDefaultKeyword {}
+
+impl SupportsDefaultKeyword for Postgres {}
+
+pub struct Postgres;
+
+impl Backend for Postgres {}
+
+pub struct AstPass<DB>(::std::marker::PhantomData<DB>);
+
+pub trait QueryFragment<DB: Backend> {}
+
+
+#[derive(Debug, Clone, Copy)]
+pub struct BatchInsert<'a, T: 'a, Tab> {
+    _marker: ::std::marker::PhantomData<(&'a T, Tab)>,
+}
+
+impl<'a, T:'a, Tab, DB> QueryFragment<DB> for BatchInsert<'a, T, Tab>
+where DB: SupportsDefaultKeyword + Backend,
+{}
diff --git a/src/test/ui/coherence/auxiliary/trait_impl_conflict.rs b/src/test/ui/coherence/auxiliary/trait_impl_conflict.rs
new file mode 100644
index 0000000..5e5f017
--- /dev/null
+++ b/src/test/ui/coherence/auxiliary/trait_impl_conflict.rs
@@ -0,0 +1,6 @@
+pub trait Foo {
+    fn foo() {}
+}
+
+impl Foo for isize {
+}
diff --git a/src/test/ui/coherence/coherence-all-remote.old.stderr b/src/test/ui/coherence/coherence-all-remote.old.stderr
new file mode 100644
index 0000000..0389a62
--- /dev/null
+++ b/src/test/ui/coherence/coherence-all-remote.old.stderr
@@ -0,0 +1,11 @@
+error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
+  --> $DIR/coherence-all-remote.rs:9:1
+   |
+LL | impl<T> Remote1<T> for isize { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type
+   |
+   = note: only traits defined in the current crate can be implemented for a type parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0210`.
diff --git a/src/test/ui/coherence/coherence-all-remote.re.stderr b/src/test/ui/coherence/coherence-all-remote.re.stderr
new file mode 100644
index 0000000..0389a62
--- /dev/null
+++ b/src/test/ui/coherence/coherence-all-remote.re.stderr
@@ -0,0 +1,11 @@
+error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
+  --> $DIR/coherence-all-remote.rs:9:1
+   |
+LL | impl<T> Remote1<T> for isize { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type
+   |
+   = note: only traits defined in the current crate can be implemented for a type parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0210`.
diff --git a/src/test/ui/coherence/coherence-all-remote.rs b/src/test/ui/coherence/coherence-all-remote.rs
new file mode 100644
index 0000000..68c924e
--- /dev/null
+++ b/src/test/ui/coherence/coherence-all-remote.rs
@@ -0,0 +1,13 @@
+// aux-build:coherence_lib.rs
+// revisions: old re
+
+#![cfg_attr(re, feature(re_rebalance_coherence))]
+
+extern crate coherence_lib as lib;
+use lib::Remote1;
+
+impl<T> Remote1<T> for isize { }
+//[old]~^ ERROR E0210
+//[re]~^^ ERROR E0210
+
+fn main() { }
diff --git a/src/test/ui/coherence/coherence-bigint-param.old.stderr b/src/test/ui/coherence/coherence-bigint-param.old.stderr
new file mode 100644
index 0000000..54fec07
--- /dev/null
+++ b/src/test/ui/coherence/coherence-bigint-param.old.stderr
@@ -0,0 +1,11 @@
+error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
+  --> $DIR/coherence-bigint-param.rs:11:1
+   |
+LL | impl<T> Remote1<BigInt> for T { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type
+   |
+   = note: only traits defined in the current crate can be implemented for a type parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0210`.
diff --git a/src/test/ui/coherence/coherence-bigint-param.re.stderr b/src/test/ui/coherence/coherence-bigint-param.re.stderr
new file mode 100644
index 0000000..54fec07
--- /dev/null
+++ b/src/test/ui/coherence/coherence-bigint-param.re.stderr
@@ -0,0 +1,11 @@
+error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
+  --> $DIR/coherence-bigint-param.rs:11:1
+   |
+LL | impl<T> Remote1<BigInt> for T { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type
+   |
+   = note: only traits defined in the current crate can be implemented for a type parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0210`.
diff --git a/src/test/ui/coherence/coherence-bigint-param.rs b/src/test/ui/coherence/coherence-bigint-param.rs
new file mode 100644
index 0000000..24106b4
--- /dev/null
+++ b/src/test/ui/coherence/coherence-bigint-param.rs
@@ -0,0 +1,15 @@
+// aux-build:coherence_lib.rs
+// revisions: old re
+
+#![cfg_attr(re, feature(re_rebalance_coherence))]
+
+extern crate coherence_lib as lib;
+use lib::Remote1;
+
+pub struct BigInt;
+
+impl<T> Remote1<BigInt> for T { }
+//[old]~^ ERROR type parameter `T` must be used as the type parameter for some local type
+//[re]~^^ ERROR E0210
+
+fn main() { }
diff --git a/src/test/ui/coherence/coherence-blanket-conflicts-with-blanket-implemented.old.stderr b/src/test/ui/coherence/coherence-blanket-conflicts-with-blanket-implemented.old.stderr
new file mode 100644
index 0000000..a6d2904
--- /dev/null
+++ b/src/test/ui/coherence/coherence-blanket-conflicts-with-blanket-implemented.old.stderr
@@ -0,0 +1,12 @@
+error[E0119]: conflicting implementations of trait `MyTrait`:
+  --> $DIR/coherence-blanket-conflicts-with-blanket-implemented.rs:28:1
+   |
+LL | impl<T:Even> MyTrait for T {
+   | -------------------------- first implementation here
+...
+LL | impl<T:Odd> MyTrait for T {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/coherence/coherence-blanket-conflicts-with-blanket-implemented.re.stderr b/src/test/ui/coherence/coherence-blanket-conflicts-with-blanket-implemented.re.stderr
new file mode 100644
index 0000000..a6d2904
--- /dev/null
+++ b/src/test/ui/coherence/coherence-blanket-conflicts-with-blanket-implemented.re.stderr
@@ -0,0 +1,12 @@
+error[E0119]: conflicting implementations of trait `MyTrait`:
+  --> $DIR/coherence-blanket-conflicts-with-blanket-implemented.rs:28:1
+   |
+LL | impl<T:Even> MyTrait for T {
+   | -------------------------- first implementation here
+...
+LL | impl<T:Odd> MyTrait for T {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/coherence/coherence-blanket-conflicts-with-blanket-implemented.rs b/src/test/ui/coherence/coherence-blanket-conflicts-with-blanket-implemented.rs
new file mode 100644
index 0000000..098a13e
--- /dev/null
+++ b/src/test/ui/coherence/coherence-blanket-conflicts-with-blanket-implemented.rs
@@ -0,0 +1,35 @@
+// revisions: old re
+
+#![cfg_attr(re, feature(re_rebalance_coherence))]
+
+use std::fmt::Debug;
+use std::default::Default;
+
+// Test that two blanket impls conflict (at least without negative
+// bounds).  After all, some other crate could implement Even or Odd
+// for the same type (though this crate doesn't).
+
+trait MyTrait {
+    fn get(&self) -> usize;
+}
+
+trait Even { }
+
+trait Odd { }
+
+impl Even for isize { }
+
+impl Odd for usize { }
+
+impl<T:Even> MyTrait for T {
+    fn get(&self) -> usize { 0 }
+}
+
+impl<T:Odd> MyTrait for T {
+//[old]~^ ERROR E0119
+//[re]~^^ ERROR E0119
+
+    fn get(&self) -> usize { 0 }
+}
+
+fn main() { }
diff --git a/src/test/ui/coherence/coherence-blanket-conflicts-with-blanket-unimplemented.old.stderr b/src/test/ui/coherence/coherence-blanket-conflicts-with-blanket-unimplemented.old.stderr
new file mode 100644
index 0000000..1f3ddd1
--- /dev/null
+++ b/src/test/ui/coherence/coherence-blanket-conflicts-with-blanket-unimplemented.old.stderr
@@ -0,0 +1,12 @@
+error[E0119]: conflicting implementations of trait `MyTrait`:
+  --> $DIR/coherence-blanket-conflicts-with-blanket-unimplemented.rs:24:1
+   |
+LL | impl<T:Even> MyTrait for T {
+   | -------------------------- first implementation here
+...
+LL | impl<T:Odd> MyTrait for T {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/coherence/coherence-blanket-conflicts-with-blanket-unimplemented.re.stderr b/src/test/ui/coherence/coherence-blanket-conflicts-with-blanket-unimplemented.re.stderr
new file mode 100644
index 0000000..1f3ddd1
--- /dev/null
+++ b/src/test/ui/coherence/coherence-blanket-conflicts-with-blanket-unimplemented.re.stderr
@@ -0,0 +1,12 @@
+error[E0119]: conflicting implementations of trait `MyTrait`:
+  --> $DIR/coherence-blanket-conflicts-with-blanket-unimplemented.rs:24:1
+   |
+LL | impl<T:Even> MyTrait for T {
+   | -------------------------- first implementation here
+...
+LL | impl<T:Odd> MyTrait for T {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/coherence/coherence-blanket-conflicts-with-blanket-unimplemented.rs b/src/test/ui/coherence/coherence-blanket-conflicts-with-blanket-unimplemented.rs
new file mode 100644
index 0000000..5b76fc0
--- /dev/null
+++ b/src/test/ui/coherence/coherence-blanket-conflicts-with-blanket-unimplemented.rs
@@ -0,0 +1,30 @@
+// revisions: old re
+
+#![cfg_attr(re, feature(re_rebalance_coherence))]
+
+use std::fmt::Debug;
+use std::default::Default;
+
+// Test that two blanket impls conflict (at least without negative
+// bounds).  After all, some other crate could implement Even or Odd
+// for the same type (though this crate doesn't implement them at all).
+
+trait MyTrait {
+    fn get(&self) -> usize;
+}
+
+trait Even {}
+
+trait Odd {}
+
+impl<T:Even> MyTrait for T {
+    fn get(&self) -> usize { 0 }
+}
+
+impl<T:Odd> MyTrait for T {
+//[old]~^ ERROR E0119
+//[re]~^^ ERROR E0119
+    fn get(&self) -> usize { 0 }
+}
+
+fn main() { }
diff --git a/src/test/ui/coherence/coherence-blanket-conflicts-with-specific-cross-crate.old.stderr b/src/test/ui/coherence/coherence-blanket-conflicts-with-specific-cross-crate.old.stderr
new file mode 100644
index 0000000..298ac6d
--- /dev/null
+++ b/src/test/ui/coherence/coherence-blanket-conflicts-with-specific-cross-crate.old.stderr
@@ -0,0 +1,13 @@
+error[E0119]: conflicting implementations of trait `go_trait::GoMut` for type `MyThingy`:
+  --> $DIR/coherence-blanket-conflicts-with-specific-cross-crate.rs:18:1
+   |
+LL | impl GoMut for MyThingy {
+   | ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: conflicting implementation in crate `go_trait`:
+           - impl<G> go_trait::GoMut for G
+             where G: go_trait::Go;
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/coherence/coherence-blanket-conflicts-with-specific-cross-crate.re.stderr b/src/test/ui/coherence/coherence-blanket-conflicts-with-specific-cross-crate.re.stderr
new file mode 100644
index 0000000..298ac6d
--- /dev/null
+++ b/src/test/ui/coherence/coherence-blanket-conflicts-with-specific-cross-crate.re.stderr
@@ -0,0 +1,13 @@
+error[E0119]: conflicting implementations of trait `go_trait::GoMut` for type `MyThingy`:
+  --> $DIR/coherence-blanket-conflicts-with-specific-cross-crate.rs:18:1
+   |
+LL | impl GoMut for MyThingy {
+   | ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: conflicting implementation in crate `go_trait`:
+           - impl<G> go_trait::GoMut for G
+             where G: go_trait::Go;
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/coherence/coherence-blanket-conflicts-with-specific-cross-crate.rs b/src/test/ui/coherence/coherence-blanket-conflicts-with-specific-cross-crate.rs
new file mode 100644
index 0000000..b0aaf57
--- /dev/null
+++ b/src/test/ui/coherence/coherence-blanket-conflicts-with-specific-cross-crate.rs
@@ -0,0 +1,24 @@
+// aux-build:go_trait.rs
+// revisions: old re
+
+#![cfg_attr(re, feature(re_rebalance_coherence))]
+
+extern crate go_trait;
+
+use go_trait::{Go,GoMut};
+use std::fmt::Debug;
+use std::default::Default;
+
+struct MyThingy;
+
+impl Go for MyThingy {
+    fn go(&self, arg: isize) { }
+}
+
+impl GoMut for MyThingy {
+//[old]~^ ERROR conflicting implementations
+//[re]~^^ ERROR E0119
+    fn go_mut(&mut self, arg: isize) { }
+}
+
+fn main() { }
diff --git a/src/test/ui/coherence/coherence-blanket-conflicts-with-specific-multidispatch.old.stderr b/src/test/ui/coherence/coherence-blanket-conflicts-with-specific-multidispatch.old.stderr
new file mode 100644
index 0000000..94bbbdb
--- /dev/null
+++ b/src/test/ui/coherence/coherence-blanket-conflicts-with-specific-multidispatch.old.stderr
@@ -0,0 +1,12 @@
+error[E0119]: conflicting implementations of trait `MyTrait<MyType>` for type `MyType`:
+  --> $DIR/coherence-blanket-conflicts-with-specific-multidispatch.rs:26:1
+   |
+LL | impl<T> MyTrait<T> for T {
+   | ------------------------ first implementation here
+...
+LL | impl MyTrait<MyType> for MyType {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `MyType`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/coherence/coherence-blanket-conflicts-with-specific-multidispatch.re.stderr b/src/test/ui/coherence/coherence-blanket-conflicts-with-specific-multidispatch.re.stderr
new file mode 100644
index 0000000..94bbbdb
--- /dev/null
+++ b/src/test/ui/coherence/coherence-blanket-conflicts-with-specific-multidispatch.re.stderr
@@ -0,0 +1,12 @@
+error[E0119]: conflicting implementations of trait `MyTrait<MyType>` for type `MyType`:
+  --> $DIR/coherence-blanket-conflicts-with-specific-multidispatch.rs:26:1
+   |
+LL | impl<T> MyTrait<T> for T {
+   | ------------------------ first implementation here
+...
+LL | impl MyTrait<MyType> for MyType {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `MyType`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/coherence/coherence-blanket-conflicts-with-specific-multidispatch.rs b/src/test/ui/coherence/coherence-blanket-conflicts-with-specific-multidispatch.rs
new file mode 100644
index 0000000..9192d123
--- /dev/null
+++ b/src/test/ui/coherence/coherence-blanket-conflicts-with-specific-multidispatch.rs
@@ -0,0 +1,32 @@
+// revisions: old re
+
+#![cfg_attr(re, feature(re_rebalance_coherence))]
+
+use std::fmt::Debug;
+use std::default::Default;
+
+// Test that a blank impl for all T conflicts with an impl for some
+// specific T, even when there are multiple type parameters involved.
+
+trait MyTrait<T> {
+    fn get(&self) -> T;
+}
+
+impl<T> MyTrait<T> for T {
+    fn get(&self) -> T {
+        panic!()
+    }
+}
+
+#[derive(Clone)]
+struct MyType {
+    dummy: usize
+}
+
+impl MyTrait<MyType> for MyType {
+//[old]~^ ERROR E0119
+//[re]~^^ ERROR E0119
+    fn get(&self) -> usize { (*self).clone() }
+}
+
+fn main() { }
diff --git a/src/test/ui/coherence/coherence-blanket-conflicts-with-specific-trait.old.stderr b/src/test/ui/coherence/coherence-blanket-conflicts-with-specific-trait.old.stderr
new file mode 100644
index 0000000..cf799c2
--- /dev/null
+++ b/src/test/ui/coherence/coherence-blanket-conflicts-with-specific-trait.old.stderr
@@ -0,0 +1,12 @@
+error[E0119]: conflicting implementations of trait `MyTrait` for type `MyType`:
+  --> $DIR/coherence-blanket-conflicts-with-specific-trait.rs:24:1
+   |
+LL | impl<T:OtherTrait> MyTrait for T {
+   | -------------------------------- first implementation here
+...
+LL | impl MyTrait for MyType {
+   | ^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `MyType`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/coherence/coherence-blanket-conflicts-with-specific-trait.re.stderr b/src/test/ui/coherence/coherence-blanket-conflicts-with-specific-trait.re.stderr
new file mode 100644
index 0000000..cf799c2
--- /dev/null
+++ b/src/test/ui/coherence/coherence-blanket-conflicts-with-specific-trait.re.stderr
@@ -0,0 +1,12 @@
+error[E0119]: conflicting implementations of trait `MyTrait` for type `MyType`:
+  --> $DIR/coherence-blanket-conflicts-with-specific-trait.rs:24:1
+   |
+LL | impl<T:OtherTrait> MyTrait for T {
+   | -------------------------------- first implementation here
+...
+LL | impl MyTrait for MyType {
+   | ^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `MyType`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/coherence/coherence-blanket-conflicts-with-specific-trait.rs b/src/test/ui/coherence/coherence-blanket-conflicts-with-specific-trait.rs
new file mode 100644
index 0000000..51cb10e
--- /dev/null
+++ b/src/test/ui/coherence/coherence-blanket-conflicts-with-specific-trait.rs
@@ -0,0 +1,34 @@
+// Test that a blank impl for all T:PartialEq conflicts with an impl for some
+// specific T when T:PartialEq.
+
+// revisions: old re
+
+#![cfg_attr(re, feature(re_rebalance_coherence))]
+
+trait OtherTrait {
+    fn noop(&self);
+}
+
+trait MyTrait {
+    fn get(&self) -> usize;
+}
+
+impl<T:OtherTrait> MyTrait for T {
+    fn get(&self) -> usize { 0 }
+}
+
+struct MyType {
+    dummy: usize
+}
+
+impl MyTrait for MyType {
+//[old]~^ ERROR E0119
+//[re]~^^ ERROR E0119
+    fn get(&self) -> usize { self.dummy }
+}
+
+impl OtherTrait for MyType {
+    fn noop(&self) { }
+}
+
+fn main() { }
diff --git a/src/test/ui/coherence/coherence-blanket-conflicts-with-specific.old.stderr b/src/test/ui/coherence/coherence-blanket-conflicts-with-specific.old.stderr
new file mode 100644
index 0000000..0807b11
--- /dev/null
+++ b/src/test/ui/coherence/coherence-blanket-conflicts-with-specific.old.stderr
@@ -0,0 +1,12 @@
+error[E0119]: conflicting implementations of trait `MyTrait` for type `MyType`:
+  --> $DIR/coherence-blanket-conflicts-with-specific.rs:23:1
+   |
+LL | impl<T> MyTrait for T {
+   | --------------------- first implementation here
+...
+LL | impl MyTrait for MyType {
+   | ^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `MyType`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/coherence/coherence-blanket-conflicts-with-specific.re.stderr b/src/test/ui/coherence/coherence-blanket-conflicts-with-specific.re.stderr
new file mode 100644
index 0000000..0807b11
--- /dev/null
+++ b/src/test/ui/coherence/coherence-blanket-conflicts-with-specific.re.stderr
@@ -0,0 +1,12 @@
+error[E0119]: conflicting implementations of trait `MyTrait` for type `MyType`:
+  --> $DIR/coherence-blanket-conflicts-with-specific.rs:23:1
+   |
+LL | impl<T> MyTrait for T {
+   | --------------------- first implementation here
+...
+LL | impl MyTrait for MyType {
+   | ^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `MyType`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/coherence/coherence-blanket-conflicts-with-specific.rs b/src/test/ui/coherence/coherence-blanket-conflicts-with-specific.rs
new file mode 100644
index 0000000..3ecb613
--- /dev/null
+++ b/src/test/ui/coherence/coherence-blanket-conflicts-with-specific.rs
@@ -0,0 +1,29 @@
+// revisions: old re
+
+#![cfg_attr(re, feature(re_rebalance_coherence))]
+
+use std::fmt::Debug;
+use std::default::Default;
+
+// Test that a blank impl for all T conflicts with an impl for some
+// specific T.
+
+trait MyTrait {
+    fn get(&self) -> usize;
+}
+
+impl<T> MyTrait for T {
+    fn get(&self) -> usize { 0 }
+}
+
+struct MyType {
+    dummy: usize
+}
+
+impl MyTrait for MyType {
+//[old]~^ ERROR E0119
+//[re]~^^ ERROR E0119
+    fn get(&self) -> usize { self.dummy }
+}
+
+fn main() { }
diff --git a/src/test/ui/coherence/coherence-conflicting-negative-trait-impl.old.stderr b/src/test/ui/coherence/coherence-conflicting-negative-trait-impl.old.stderr
new file mode 100644
index 0000000..bb3641f
--- /dev/null
+++ b/src/test/ui/coherence/coherence-conflicting-negative-trait-impl.old.stderr
@@ -0,0 +1,21 @@
+error[E0119]: conflicting implementations of trait `std::marker::Send` for type `TestType<_>`:
+  --> $DIR/coherence-conflicting-negative-trait-impl.rs:13:1
+   |
+LL | unsafe impl<T: MyTrait+'static> Send for TestType<T> {}
+   | ---------------------------------------------------- first implementation here
+LL | 
+LL | impl<T: MyTrait> !Send for TestType<T> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `TestType<_>`
+
+error[E0119]: conflicting implementations of trait `std::marker::Send` for type `TestType<i32>`:
+  --> $DIR/coherence-conflicting-negative-trait-impl.rs:19:1
+   |
+LL | unsafe impl<T:'static> Send for TestType<T> {}
+   | ------------------------------------------- first implementation here
+LL | 
+LL | impl !Send for TestType<i32> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `TestType<i32>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/coherence/coherence-conflicting-negative-trait-impl.re.stderr b/src/test/ui/coherence/coherence-conflicting-negative-trait-impl.re.stderr
new file mode 100644
index 0000000..bb3641f
--- /dev/null
+++ b/src/test/ui/coherence/coherence-conflicting-negative-trait-impl.re.stderr
@@ -0,0 +1,21 @@
+error[E0119]: conflicting implementations of trait `std::marker::Send` for type `TestType<_>`:
+  --> $DIR/coherence-conflicting-negative-trait-impl.rs:13:1
+   |
+LL | unsafe impl<T: MyTrait+'static> Send for TestType<T> {}
+   | ---------------------------------------------------- first implementation here
+LL | 
+LL | impl<T: MyTrait> !Send for TestType<T> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `TestType<_>`
+
+error[E0119]: conflicting implementations of trait `std::marker::Send` for type `TestType<i32>`:
+  --> $DIR/coherence-conflicting-negative-trait-impl.rs:19:1
+   |
+LL | unsafe impl<T:'static> Send for TestType<T> {}
+   | ------------------------------------------- first implementation here
+LL | 
+LL | impl !Send for TestType<i32> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `TestType<i32>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/coherence/coherence-conflicting-negative-trait-impl.rs b/src/test/ui/coherence/coherence-conflicting-negative-trait-impl.rs
new file mode 100644
index 0000000..e05fecb
--- /dev/null
+++ b/src/test/ui/coherence/coherence-conflicting-negative-trait-impl.rs
@@ -0,0 +1,23 @@
+// revisions: old re
+
+#![cfg_attr(re, feature(re_rebalance_coherence))]
+#![feature(optin_builtin_traits)]
+#![feature(overlapping_marker_traits)]
+
+trait MyTrait {}
+
+struct TestType<T>(::std::marker::PhantomData<T>);
+
+unsafe impl<T: MyTrait+'static> Send for TestType<T> {}
+
+impl<T: MyTrait> !Send for TestType<T> {}
+//[old]~^ ERROR conflicting implementations of trait `std::marker::Send`
+//[re]~^^ ERROR E0119
+
+unsafe impl<T:'static> Send for TestType<T> {}
+
+impl !Send for TestType<i32> {}
+//[old]~^ ERROR conflicting implementations of trait `std::marker::Send`
+//[re]~^^ ERROR E0119
+
+fn main() {}
diff --git a/src/test/ui/coherence/coherence-cow.a.stderr b/src/test/ui/coherence/coherence-cow.a.stderr
new file mode 100644
index 0000000..dd9cfab
--- /dev/null
+++ b/src/test/ui/coherence/coherence-cow.a.stderr
@@ -0,0 +1,11 @@
+error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
+  --> $DIR/coherence-cow.rs:18:1
+   |
+LL | impl<T> Remote for Pair<T,Cover<T>> { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type
+   |
+   = note: only traits defined in the current crate can be implemented for a type parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0210`.
diff --git a/src/test/ui/coherence/coherence-cow.b.stderr b/src/test/ui/coherence/coherence-cow.b.stderr
new file mode 100644
index 0000000..fb3ca3f
--- /dev/null
+++ b/src/test/ui/coherence/coherence-cow.b.stderr
@@ -0,0 +1,11 @@
+error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
+  --> $DIR/coherence-cow.rs:23:1
+   |
+LL | impl<T> Remote for Pair<Cover<T>,T> { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type
+   |
+   = note: only traits defined in the current crate can be implemented for a type parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0210`.
diff --git a/src/test/ui/coherence/coherence-cow.c.stderr b/src/test/ui/coherence/coherence-cow.c.stderr
new file mode 100644
index 0000000..f17823b
--- /dev/null
+++ b/src/test/ui/coherence/coherence-cow.c.stderr
@@ -0,0 +1,11 @@
+error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
+  --> $DIR/coherence-cow.rs:28:1
+   |
+LL | impl<T,U> Remote for Pair<Cover<T>,U> { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type
+   |
+   = note: only traits defined in the current crate can be implemented for a type parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0210`.
diff --git a/src/test/ui/coherence/coherence-cow.re_a.stderr b/src/test/ui/coherence/coherence-cow.re_a.stderr
new file mode 100644
index 0000000..b0ec55a
--- /dev/null
+++ b/src/test/ui/coherence/coherence-cow.re_a.stderr
@@ -0,0 +1,12 @@
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/coherence-cow.rs:18:1
+   |
+LL | impl<T> Remote for Pair<T,Cover<T>> { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0117`.
diff --git a/src/test/ui/coherence/coherence-cow.re_b.stderr b/src/test/ui/coherence/coherence-cow.re_b.stderr
new file mode 100644
index 0000000..ce26112
--- /dev/null
+++ b/src/test/ui/coherence/coherence-cow.re_b.stderr
@@ -0,0 +1,12 @@
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/coherence-cow.rs:23:1
+   |
+LL | impl<T> Remote for Pair<Cover<T>,T> { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0117`.
diff --git a/src/test/ui/coherence/coherence-cow.re_c.stderr b/src/test/ui/coherence/coherence-cow.re_c.stderr
new file mode 100644
index 0000000..1c2030d
--- /dev/null
+++ b/src/test/ui/coherence/coherence-cow.re_c.stderr
@@ -0,0 +1,12 @@
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/coherence-cow.rs:28:1
+   |
+LL | impl<T,U> Remote for Pair<Cover<T>,U> { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0117`.
diff --git a/src/test/ui/coherence/coherence-cow.rs b/src/test/ui/coherence/coherence-cow.rs
new file mode 100644
index 0000000..956b073
--- /dev/null
+++ b/src/test/ui/coherence/coherence-cow.rs
@@ -0,0 +1,32 @@
+// revisions: a b c re_a re_b re_c
+
+#![cfg_attr(any(re_a, re_b, re_c), feature(re_rebalance_coherence))]
+
+// aux-build:coherence_lib.rs
+
+// Test that the `Pair` type reports an error if it contains type
+// parameters, even when they are covered by local types. This test
+// was originally intended to test the opposite, but the rules changed
+// with RFC 1023 and this became illegal.
+
+extern crate coherence_lib as lib;
+use lib::{Remote,Pair};
+
+pub struct Cover<T>(T);
+
+#[cfg(any(a, re_a))]
+impl<T> Remote for Pair<T,Cover<T>> { }
+//[a]~^ ERROR E0210
+//[re_a]~^^ ERROR E0117
+
+#[cfg(any(b, re_b))]
+impl<T> Remote for Pair<Cover<T>,T> { }
+//[b]~^ ERROR E0210
+//[re_b]~^^ ERROR E0117
+
+#[cfg(any(c, re_c))]
+impl<T,U> Remote for Pair<Cover<T>,U> { }
+//[c]~^ ERROR type parameter `T` must be used as the type parameter for some local type
+//[re_c]~^^ ERROR E0117
+
+fn main() { }
diff --git a/src/test/ui/coherence/coherence-cross-crate-conflict.old.stderr b/src/test/ui/coherence/coherence-cross-crate-conflict.old.stderr
new file mode 100644
index 0000000..3ba32a5
--- /dev/null
+++ b/src/test/ui/coherence/coherence-cross-crate-conflict.old.stderr
@@ -0,0 +1,21 @@
+error[E0119]: conflicting implementations of trait `trait_impl_conflict::Foo` for type `isize`:
+  --> $DIR/coherence-cross-crate-conflict.rs:12:1
+   |
+LL | impl<A> Foo for A {
+   | ^^^^^^^^^^^^^^^^^
+   |
+   = note: conflicting implementation in crate `trait_impl_conflict`:
+           - impl trait_impl_conflict::Foo for isize;
+
+error[E0210]: type parameter `A` must be used as the type parameter for some local type (e.g., `MyStruct<A>`)
+  --> $DIR/coherence-cross-crate-conflict.rs:12:1
+   |
+LL | impl<A> Foo for A {
+   | ^^^^^^^^^^^^^^^^^ type parameter `A` must be used as the type parameter for some local type
+   |
+   = note: only traits defined in the current crate can be implemented for a type parameter
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0119, E0210.
+For more information about an error, try `rustc --explain E0119`.
diff --git a/src/test/ui/coherence/coherence-cross-crate-conflict.re.stderr b/src/test/ui/coherence/coherence-cross-crate-conflict.re.stderr
new file mode 100644
index 0000000..3ba32a5
--- /dev/null
+++ b/src/test/ui/coherence/coherence-cross-crate-conflict.re.stderr
@@ -0,0 +1,21 @@
+error[E0119]: conflicting implementations of trait `trait_impl_conflict::Foo` for type `isize`:
+  --> $DIR/coherence-cross-crate-conflict.rs:12:1
+   |
+LL | impl<A> Foo for A {
+   | ^^^^^^^^^^^^^^^^^
+   |
+   = note: conflicting implementation in crate `trait_impl_conflict`:
+           - impl trait_impl_conflict::Foo for isize;
+
+error[E0210]: type parameter `A` must be used as the type parameter for some local type (e.g., `MyStruct<A>`)
+  --> $DIR/coherence-cross-crate-conflict.rs:12:1
+   |
+LL | impl<A> Foo for A {
+   | ^^^^^^^^^^^^^^^^^ type parameter `A` must be used as the type parameter for some local type
+   |
+   = note: only traits defined in the current crate can be implemented for a type parameter
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0119, E0210.
+For more information about an error, try `rustc --explain E0119`.
diff --git a/src/test/ui/coherence/coherence-cross-crate-conflict.rs b/src/test/ui/coherence/coherence-cross-crate-conflict.rs
new file mode 100644
index 0000000..9643ab6
--- /dev/null
+++ b/src/test/ui/coherence/coherence-cross-crate-conflict.rs
@@ -0,0 +1,20 @@
+// The error here is strictly due to orphan rules; the impl here
+// generalizes the one upstream
+
+// aux-build:trait_impl_conflict.rs
+// revisions: old re
+
+#![cfg_attr(re, feature(re_rebalance_coherence))]
+
+extern crate trait_impl_conflict;
+use trait_impl_conflict::Foo;
+
+impl<A> Foo for A {
+    //[old]~^ ERROR type parameter `A` must be used as the type parameter for some local type
+    //[old]~| ERROR conflicting implementations of trait `trait_impl_conflict::Foo` for type `isize`
+    //[re]~^^^ ERROR E0119
+    //[re]~| ERROR E0210
+}
+
+fn main() {
+}
diff --git a/src/test/ui/coherence/coherence-default-trait-impl.old.stderr b/src/test/ui/coherence/coherence-default-trait-impl.old.stderr
new file mode 100644
index 0000000..534f4b0
--- /dev/null
+++ b/src/test/ui/coherence/coherence-default-trait-impl.old.stderr
@@ -0,0 +1,16 @@
+error[E0199]: implementing the trait `MySafeTrait` is not unsafe
+  --> $DIR/coherence-default-trait-impl.rs:10:1
+   |
+LL | unsafe impl MySafeTrait for Foo {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0200]: the trait `MyUnsafeTrait` requires an `unsafe impl` declaration
+  --> $DIR/coherence-default-trait-impl.rs:16:1
+   |
+LL | impl MyUnsafeTrait for Foo {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0199, E0200.
+For more information about an error, try `rustc --explain E0199`.
diff --git a/src/test/ui/coherence/coherence-default-trait-impl.re.stderr b/src/test/ui/coherence/coherence-default-trait-impl.re.stderr
new file mode 100644
index 0000000..534f4b0
--- /dev/null
+++ b/src/test/ui/coherence/coherence-default-trait-impl.re.stderr
@@ -0,0 +1,16 @@
+error[E0199]: implementing the trait `MySafeTrait` is not unsafe
+  --> $DIR/coherence-default-trait-impl.rs:10:1
+   |
+LL | unsafe impl MySafeTrait for Foo {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0200]: the trait `MyUnsafeTrait` requires an `unsafe impl` declaration
+  --> $DIR/coherence-default-trait-impl.rs:16:1
+   |
+LL | impl MyUnsafeTrait for Foo {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0199, E0200.
+For more information about an error, try `rustc --explain E0199`.
diff --git a/src/test/ui/coherence/coherence-default-trait-impl.rs b/src/test/ui/coherence/coherence-default-trait-impl.rs
new file mode 100644
index 0000000..606b494
--- /dev/null
+++ b/src/test/ui/coherence/coherence-default-trait-impl.rs
@@ -0,0 +1,20 @@
+// revisions: old re
+
+#![cfg_attr(re, feature(re_rebalance_coherence))]
+#![feature(optin_builtin_traits)]
+
+auto trait MySafeTrait {}
+
+struct Foo;
+
+unsafe impl MySafeTrait for Foo {}
+//[old]~^ ERROR implementing the trait `MySafeTrait` is not unsafe
+//[re]~^^ ERROR E0199
+
+unsafe auto trait MyUnsafeTrait {}
+
+impl MyUnsafeTrait for Foo {}
+//[old]~^ ERROR the trait `MyUnsafeTrait` requires an `unsafe impl` declaration
+//[re]~^^ ERROR E0200
+
+fn main() {}
diff --git a/src/test/ui/coherence/coherence-error-suppression.old.stderr b/src/test/ui/coherence/coherence-error-suppression.old.stderr
new file mode 100644
index 0000000..b81f755
--- /dev/null
+++ b/src/test/ui/coherence/coherence-error-suppression.old.stderr
@@ -0,0 +1,9 @@
+error[E0412]: cannot find type `DoesNotExist` in this scope
+  --> $DIR/coherence-error-suppression.rs:13:14
+   |
+LL | impl Foo for DoesNotExist {}
+   |              ^^^^^^^^^^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/src/test/ui/coherence/coherence-error-suppression.re.stderr b/src/test/ui/coherence/coherence-error-suppression.re.stderr
new file mode 100644
index 0000000..b81f755
--- /dev/null
+++ b/src/test/ui/coherence/coherence-error-suppression.re.stderr
@@ -0,0 +1,9 @@
+error[E0412]: cannot find type `DoesNotExist` in this scope
+  --> $DIR/coherence-error-suppression.rs:13:14
+   |
+LL | impl Foo for DoesNotExist {}
+   |              ^^^^^^^^^^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/src/test/ui/coherence/coherence-error-suppression.rs b/src/test/ui/coherence/coherence-error-suppression.rs
new file mode 100644
index 0000000..60b88fb
--- /dev/null
+++ b/src/test/ui/coherence/coherence-error-suppression.rs
@@ -0,0 +1,21 @@
+// check that error types in coherence do not cause error cascades.
+
+// revisions: old re
+
+#![cfg_attr(re, feature(re_rebalance_coherence))]
+
+trait Foo {}
+
+impl Foo for i8 {}
+impl Foo for i16 {}
+impl Foo for i32 {}
+impl Foo for i64 {}
+impl Foo for DoesNotExist {}
+//[old]~^ ERROR cannot find type `DoesNotExist` in this scope
+//[re]~^^ ERROR E0412
+impl Foo for u8 {}
+impl Foo for u16 {}
+impl Foo for u32 {}
+impl Foo for u64 {}
+
+fn main() {}
diff --git a/src/test/ui/coherence/coherence-fundamental-trait-objects.old.stderr b/src/test/ui/coherence/coherence-fundamental-trait-objects.old.stderr
new file mode 100644
index 0000000..2d1247e
--- /dev/null
+++ b/src/test/ui/coherence/coherence-fundamental-trait-objects.old.stderr
@@ -0,0 +1,12 @@
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/coherence-fundamental-trait-objects.rs:15:1
+   |
+LL | impl Misc for dyn Fundamental<Local> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0117`.
diff --git a/src/test/ui/coherence/coherence-fundamental-trait-objects.re.stderr b/src/test/ui/coherence/coherence-fundamental-trait-objects.re.stderr
new file mode 100644
index 0000000..2d1247e
--- /dev/null
+++ b/src/test/ui/coherence/coherence-fundamental-trait-objects.re.stderr
@@ -0,0 +1,12 @@
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/coherence-fundamental-trait-objects.rs:15:1
+   |
+LL | impl Misc for dyn Fundamental<Local> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0117`.
diff --git a/src/test/ui/coherence/coherence-fundamental-trait-objects.rs b/src/test/ui/coherence/coherence-fundamental-trait-objects.rs
new file mode 100644
index 0000000..0c7d544
--- /dev/null
+++ b/src/test/ui/coherence/coherence-fundamental-trait-objects.rs
@@ -0,0 +1,19 @@
+// Check that trait objects from #[fundamental] traits are not
+// treated as #[fundamental] types - the 2 meanings of #[fundamental]
+// are distinct.
+
+// aux-build:coherence_fundamental_trait_lib.rs
+// revisions: old re
+
+#![cfg_attr(re, feature(re_rebalance_coherence))]
+
+extern crate coherence_fundamental_trait_lib;
+
+use coherence_fundamental_trait_lib::{Fundamental, Misc};
+
+pub struct Local;
+impl Misc for dyn Fundamental<Local> {}
+//[old]~^ ERROR E0117
+//[re]~^^ ERROR E0117
+
+fn main() {}
diff --git a/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-negative.rs b/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-negative.rs
new file mode 100644
index 0000000..5ea6919
--- /dev/null
+++ b/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-negative.rs
@@ -0,0 +1,29 @@
+#![feature(optin_builtin_traits)]
+
+// Test for issue #56934 - that it is impossible to redundantly
+// implement an auto-trait for a trait object type that contains it.
+
+// Negative impl variant.
+
+auto trait Marker1 {}
+auto trait Marker2 {}
+
+trait Object: Marker1 {}
+
+// A supertrait marker is illegal...
+impl !Marker1 for dyn Object + Marker2 { }   //~ ERROR E0371
+// ...and also a direct component.
+impl !Marker2 for dyn Object + Marker2 { }   //~ ERROR E0371
+
+// But implementing a marker if it is not present is OK.
+impl !Marker2 for dyn Object {} // OK
+
+// A non-principal trait-object type is orphan even in its crate.
+impl !Send for dyn Marker2 {} //~ ERROR E0117
+
+// And impl'ing a remote marker for a local trait object is forbidden
+// by one of these special orphan-like rules.
+impl !Send for dyn Object {} //~ ERROR E0321
+impl !Send for dyn Object + Marker2 {} //~ ERROR E0321
+
+fn main() { }
diff --git a/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr b/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr
new file mode 100644
index 0000000..86a63eb
--- /dev/null
+++ b/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr
@@ -0,0 +1,37 @@
+error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker1`
+  --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:14:1
+   |
+LL | impl !Marker1 for dyn Object + Marker2 { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker1`
+
+error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker2`
+  --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:16:1
+   |
+LL | impl !Marker2 for dyn Object + Marker2 { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker2`
+
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:22:1
+   |
+LL | impl !Send for dyn Marker2 {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error[E0321]: cross-crate traits with a default impl, like `std::marker::Send`, can only be implemented for a struct/enum type, not `(dyn Object + 'static)`
+  --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:26:1
+   |
+LL | impl !Send for dyn Object {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type
+
+error[E0321]: cross-crate traits with a default impl, like `std::marker::Send`, can only be implemented for a struct/enum type, not `(dyn Object + Marker2 + 'static)`
+  --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:27:1
+   |
+LL | impl !Send for dyn Object + Marker2 {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type
+
+error: aborting due to 5 previous errors
+
+Some errors occurred: E0117, E0321, E0371.
+For more information about an error, try `rustc --explain E0117`.
diff --git a/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-positive.rs b/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-positive.rs
new file mode 100644
index 0000000..6b5689e
--- /dev/null
+++ b/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-positive.rs
@@ -0,0 +1,29 @@
+#![feature(optin_builtin_traits)]
+
+// Test for issue #56934 - that it is impossible to redundantly
+// implement an auto-trait for a trait object type that contains it.
+
+// Positive impl variant.
+
+auto trait Marker1 {}
+auto trait Marker2 {}
+
+trait Object: Marker1 {}
+
+// A supertrait marker is illegal...
+impl Marker1 for dyn Object + Marker2 { }   //~ ERROR E0371
+// ...and also a direct component.
+impl Marker2 for dyn Object + Marker2 { }   //~ ERROR E0371
+
+// But implementing a marker if it is not present is OK.
+impl Marker2 for dyn Object {} // OK
+
+// A non-principal trait-object type is orphan even in its crate.
+unsafe impl Send for dyn Marker2 {} //~ ERROR E0117
+
+// And impl'ing a remote marker for a local trait object is forbidden
+// by one of these special orphan-like rules.
+unsafe impl Send for dyn Object {} //~ ERROR E0321
+unsafe impl Send for dyn Object + Marker2 {} //~ ERROR E0321
+
+fn main() { }
diff --git a/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr b/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr
new file mode 100644
index 0000000..536b462
--- /dev/null
+++ b/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr
@@ -0,0 +1,37 @@
+error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker1`
+  --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:14:1
+   |
+LL | impl Marker1 for dyn Object + Marker2 { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker1`
+
+error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker2`
+  --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:16:1
+   |
+LL | impl Marker2 for dyn Object + Marker2 { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker2`
+
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:22:1
+   |
+LL | unsafe impl Send for dyn Marker2 {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error[E0321]: cross-crate traits with a default impl, like `std::marker::Send`, can only be implemented for a struct/enum type, not `(dyn Object + 'static)`
+  --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:26:1
+   |
+LL | unsafe impl Send for dyn Object {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type
+
+error[E0321]: cross-crate traits with a default impl, like `std::marker::Send`, can only be implemented for a struct/enum type, not `(dyn Object + Marker2 + 'static)`
+  --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:27:1
+   |
+LL | unsafe impl Send for dyn Object + Marker2 {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type
+
+error: aborting due to 5 previous errors
+
+Some errors occurred: E0117, E0321, E0371.
+For more information about an error, try `rustc --explain E0117`.
diff --git a/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.old.stderr b/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.old.stderr
new file mode 100644
index 0000000..b48f6bb
--- /dev/null
+++ b/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.old.stderr
@@ -0,0 +1,11 @@
+error[E0038]: the trait `NotObjectSafe` cannot be made into an object
+  --> $DIR/coherence-impl-trait-for-trait-object-safe.rs:11:6
+   |
+LL | impl NotObjectSafe for NotObjectSafe { }
+   |      ^^^^^^^^^^^^^ the trait `NotObjectSafe` cannot be made into an object
+   |
+   = note: method `eq` references the `Self` type in its arguments or return type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.re.stderr b/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.re.stderr
new file mode 100644
index 0000000..b48f6bb
--- /dev/null
+++ b/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.re.stderr
@@ -0,0 +1,11 @@
+error[E0038]: the trait `NotObjectSafe` cannot be made into an object
+  --> $DIR/coherence-impl-trait-for-trait-object-safe.rs:11:6
+   |
+LL | impl NotObjectSafe for NotObjectSafe { }
+   |      ^^^^^^^^^^^^^ the trait `NotObjectSafe` cannot be made into an object
+   |
+   = note: method `eq` references the `Self` type in its arguments or return type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.rs b/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.rs
new file mode 100644
index 0000000..803e8fc
--- /dev/null
+++ b/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.rs
@@ -0,0 +1,15 @@
+// Test that we give suitable error messages when the user attempts to
+// impl a trait `Trait` for its own object type.
+
+// revisions: old re
+
+#![cfg_attr(re, feature(re_rebalance_coherence))]
+
+// If the trait is not object-safe, we give a more tailored message
+// because we're such schnuckels:
+trait NotObjectSafe { fn eq(&self, other: Self); }
+impl NotObjectSafe for NotObjectSafe { }
+//[old]~^ ERROR E0038
+//[re]~^^ ERROR E0038
+
+fn main() { }
diff --git a/src/test/ui/coherence/coherence-impl-trait-for-trait.old.stderr b/src/test/ui/coherence/coherence-impl-trait-for-trait.old.stderr
new file mode 100644
index 0000000..3247476
--- /dev/null
+++ b/src/test/ui/coherence/coherence-impl-trait-for-trait.old.stderr
@@ -0,0 +1,21 @@
+error[E0371]: the object type `(dyn Baz + 'static)` automatically implements the trait `Foo`
+  --> $DIR/coherence-impl-trait-for-trait.rs:13:1
+   |
+LL | impl Foo for Baz { }
+   | ^^^^^^^^^^^^^^^^ `(dyn Baz + 'static)` automatically implements trait `Foo`
+
+error[E0371]: the object type `(dyn Baz + 'static)` automatically implements the trait `Bar`
+  --> $DIR/coherence-impl-trait-for-trait.rs:16:1
+   |
+LL | impl Bar for Baz { }
+   | ^^^^^^^^^^^^^^^^ `(dyn Baz + 'static)` automatically implements trait `Bar`
+
+error[E0371]: the object type `(dyn Baz + 'static)` automatically implements the trait `Baz`
+  --> $DIR/coherence-impl-trait-for-trait.rs:19:1
+   |
+LL | impl Baz for Baz { }
+   | ^^^^^^^^^^^^^^^^ `(dyn Baz + 'static)` automatically implements trait `Baz`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0371`.
diff --git a/src/test/ui/coherence/coherence-impl-trait-for-trait.re.stderr b/src/test/ui/coherence/coherence-impl-trait-for-trait.re.stderr
new file mode 100644
index 0000000..3247476
--- /dev/null
+++ b/src/test/ui/coherence/coherence-impl-trait-for-trait.re.stderr
@@ -0,0 +1,21 @@
+error[E0371]: the object type `(dyn Baz + 'static)` automatically implements the trait `Foo`
+  --> $DIR/coherence-impl-trait-for-trait.rs:13:1
+   |
+LL | impl Foo for Baz { }
+   | ^^^^^^^^^^^^^^^^ `(dyn Baz + 'static)` automatically implements trait `Foo`
+
+error[E0371]: the object type `(dyn Baz + 'static)` automatically implements the trait `Bar`
+  --> $DIR/coherence-impl-trait-for-trait.rs:16:1
+   |
+LL | impl Bar for Baz { }
+   | ^^^^^^^^^^^^^^^^ `(dyn Baz + 'static)` automatically implements trait `Bar`
+
+error[E0371]: the object type `(dyn Baz + 'static)` automatically implements the trait `Baz`
+  --> $DIR/coherence-impl-trait-for-trait.rs:19:1
+   |
+LL | impl Baz for Baz { }
+   | ^^^^^^^^^^^^^^^^ `(dyn Baz + 'static)` automatically implements trait `Baz`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0371`.
diff --git a/src/test/ui/coherence/coherence-impl-trait-for-trait.rs b/src/test/ui/coherence/coherence-impl-trait-for-trait.rs
new file mode 100644
index 0000000..dcaf564
--- /dev/null
+++ b/src/test/ui/coherence/coherence-impl-trait-for-trait.rs
@@ -0,0 +1,27 @@
+// Test that we give suitable error messages when the user attempts to
+// impl a trait `Trait` for its own object type.
+
+// revisions: old re
+
+#![cfg_attr(re, feature(re_rebalance_coherence))]
+
+trait Foo { fn dummy(&self) { } }
+trait Bar: Foo { }
+trait Baz: Bar { }
+
+// Supertraits of Baz are not legal:
+impl Foo for Baz { }
+//[old]~^ ERROR E0371
+//[re]~^^ ERROR E0371
+impl Bar for Baz { }
+//[old]~^ ERROR E0371
+//[re]~^^ ERROR E0371
+impl Baz for Baz { }
+//[old]~^ ERROR E0371
+//[re]~^^ ERROR E0371
+
+// But other random traits are:
+trait Other { }
+impl Other for Baz { } // OK, Other not a supertrait of Baz
+
+fn main() { }
diff --git a/src/test/ui/coherence/coherence-impls-copy.old.stderr b/src/test/ui/coherence/coherence-impls-copy.old.stderr
new file mode 100644
index 0000000..e870c26
--- /dev/null
+++ b/src/test/ui/coherence/coherence-impls-copy.old.stderr
@@ -0,0 +1,87 @@
+error[E0119]: conflicting implementations of trait `std::marker::Copy` for type `i32`:
+  --> $DIR/coherence-impls-copy.rs:8:1
+   |
+LL | impl Copy for i32 {}
+   | ^^^^^^^^^^^^^^^^^
+   |
+   = note: conflicting implementation in crate `core`:
+           - impl std::marker::Copy for i32;
+
+error[E0119]: conflicting implementations of trait `std::marker::Copy` for type `&NotSync`:
+  --> $DIR/coherence-impls-copy.rs:37:1
+   |
+LL | impl Copy for &'static NotSync {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: conflicting implementation in crate `core`:
+           - impl<T> std::marker::Copy for &T
+             where T: ?Sized;
+
+error[E0119]: conflicting implementations of trait `std::marker::Copy` for type `&[NotSync]`:
+  --> $DIR/coherence-impls-copy.rs:45:1
+   |
+LL | impl Copy for &'static [NotSync] {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: conflicting implementation in crate `core`:
+           - impl<T> std::marker::Copy for &T
+             where T: ?Sized;
+
+error[E0206]: the trait `Copy` may not be implemented for this type
+  --> $DIR/coherence-impls-copy.rs:27:15
+   |
+LL | impl Copy for &'static mut MyType {}
+   |               ^^^^^^^^^^^^^^^^^^^ type is not a structure or enumeration
+
+error[E0206]: the trait `Copy` may not be implemented for this type
+  --> $DIR/coherence-impls-copy.rs:32:15
+   |
+LL | impl Copy for (MyType, MyType) {}
+   |               ^^^^^^^^^^^^^^^^ type is not a structure or enumeration
+
+error[E0206]: the trait `Copy` may not be implemented for this type
+  --> $DIR/coherence-impls-copy.rs:40:15
+   |
+LL | impl Copy for [MyType] {}
+   |               ^^^^^^^^ type is not a structure or enumeration
+
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/coherence-impls-copy.rs:8:1
+   |
+LL | impl Copy for i32 {}
+   | ^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/coherence-impls-copy.rs:32:1
+   |
+LL | impl Copy for (MyType, MyType) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/coherence-impls-copy.rs:40:1
+   |
+LL | impl Copy for [MyType] {}
+   | ^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/coherence-impls-copy.rs:45:1
+   |
+LL | impl Copy for &'static [NotSync] {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error: aborting due to 10 previous errors
+
+Some errors occurred: E0117, E0119, E0206.
+For more information about an error, try `rustc --explain E0117`.
diff --git a/src/test/ui/coherence/coherence-impls-copy.re.stderr b/src/test/ui/coherence/coherence-impls-copy.re.stderr
new file mode 100644
index 0000000..e870c26
--- /dev/null
+++ b/src/test/ui/coherence/coherence-impls-copy.re.stderr
@@ -0,0 +1,87 @@
+error[E0119]: conflicting implementations of trait `std::marker::Copy` for type `i32`:
+  --> $DIR/coherence-impls-copy.rs:8:1
+   |
+LL | impl Copy for i32 {}
+   | ^^^^^^^^^^^^^^^^^
+   |
+   = note: conflicting implementation in crate `core`:
+           - impl std::marker::Copy for i32;
+
+error[E0119]: conflicting implementations of trait `std::marker::Copy` for type `&NotSync`:
+  --> $DIR/coherence-impls-copy.rs:37:1
+   |
+LL | impl Copy for &'static NotSync {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: conflicting implementation in crate `core`:
+           - impl<T> std::marker::Copy for &T
+             where T: ?Sized;
+
+error[E0119]: conflicting implementations of trait `std::marker::Copy` for type `&[NotSync]`:
+  --> $DIR/coherence-impls-copy.rs:45:1
+   |
+LL | impl Copy for &'static [NotSync] {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: conflicting implementation in crate `core`:
+           - impl<T> std::marker::Copy for &T
+             where T: ?Sized;
+
+error[E0206]: the trait `Copy` may not be implemented for this type
+  --> $DIR/coherence-impls-copy.rs:27:15
+   |
+LL | impl Copy for &'static mut MyType {}
+   |               ^^^^^^^^^^^^^^^^^^^ type is not a structure or enumeration
+
+error[E0206]: the trait `Copy` may not be implemented for this type
+  --> $DIR/coherence-impls-copy.rs:32:15
+   |
+LL | impl Copy for (MyType, MyType) {}
+   |               ^^^^^^^^^^^^^^^^ type is not a structure or enumeration
+
+error[E0206]: the trait `Copy` may not be implemented for this type
+  --> $DIR/coherence-impls-copy.rs:40:15
+   |
+LL | impl Copy for [MyType] {}
+   |               ^^^^^^^^ type is not a structure or enumeration
+
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/coherence-impls-copy.rs:8:1
+   |
+LL | impl Copy for i32 {}
+   | ^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/coherence-impls-copy.rs:32:1
+   |
+LL | impl Copy for (MyType, MyType) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/coherence-impls-copy.rs:40:1
+   |
+LL | impl Copy for [MyType] {}
+   | ^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/coherence-impls-copy.rs:45:1
+   |
+LL | impl Copy for &'static [NotSync] {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error: aborting due to 10 previous errors
+
+Some errors occurred: E0117, E0119, E0206.
+For more information about an error, try `rustc --explain E0117`.
diff --git a/src/test/ui/coherence/coherence-impls-copy.rs b/src/test/ui/coherence/coherence-impls-copy.rs
new file mode 100644
index 0000000..97133bc
--- /dev/null
+++ b/src/test/ui/coherence/coherence-impls-copy.rs
@@ -0,0 +1,51 @@
+// revisions: old re
+
+#![cfg_attr(re, feature(re_rebalance_coherence))]
+#![feature(optin_builtin_traits)]
+
+use std::marker::Copy;
+
+impl Copy for i32 {}
+//[old]~^ ERROR conflicting implementations of trait `std::marker::Copy` for type `i32`:
+//[old]~| ERROR only traits defined in the current crate can be implemented for arbitrary types
+//[re]~^^^ ERROR E0119
+//[re]~| ERROR E0117
+enum TestE {
+  A
+}
+
+struct MyType;
+
+struct NotSync;
+impl !Sync for NotSync {}
+
+impl Copy for TestE {}
+impl Clone for TestE { fn clone(&self) -> Self { *self } }
+
+impl Copy for MyType {}
+
+impl Copy for &'static mut MyType {}
+//[old]~^ ERROR the trait `Copy` may not be implemented for this type
+//[re]~^^ ERROR E0206
+impl Clone for MyType { fn clone(&self) -> Self { *self } }
+
+impl Copy for (MyType, MyType) {}
+//[old]~^ ERROR the trait `Copy` may not be implemented for this type
+//[old]~| ERROR only traits defined in the current crate can be implemented for arbitrary types
+//[re]~^^^ ERROR E0206
+//[re]~| ERROR E0117
+impl Copy for &'static NotSync {}
+//[old]~^ ERROR conflicting implementations of trait `std::marker::Copy` for type `&NotSync`:
+//[re]~^^  ERROR E0119
+impl Copy for [MyType] {}
+//[old]~^ ERROR the trait `Copy` may not be implemented for this type
+//[old]~| ERROR only traits defined in the current crate can be implemented for arbitrary types
+//[re]~^^^ ERROR E0206
+//[re]~| ERROR E0117
+impl Copy for &'static [NotSync] {}
+//[old]~^ ERROR conflicting implementations of trait `std::marker::Copy` for type `&[NotSync]`:
+//[old]~| ERROR only traits defined in the current crate can be implemented for arbitrary types
+//[re]~^^^ ERROR E0119
+//[re]~| ERROR E0117
+fn main() {
+}
diff --git a/src/test/ui/coherence/coherence-impls-send.old.stderr b/src/test/ui/coherence/coherence-impls-send.old.stderr
new file mode 100644
index 0000000..3ede836
--- /dev/null
+++ b/src/test/ui/coherence/coherence-impls-send.old.stderr
@@ -0,0 +1,37 @@
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/coherence-impls-send.rs:20:1
+   |
+LL | unsafe impl Send for (MyType, MyType) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error[E0321]: cross-crate traits with a default impl, like `std::marker::Send`, can only be implemented for a struct/enum type, not `&'static NotSync`
+  --> $DIR/coherence-impls-send.rs:24:1
+   |
+LL | unsafe impl Send for &'static NotSync {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type
+
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/coherence-impls-send.rs:28:1
+   |
+LL | unsafe impl Send for [MyType] {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/coherence-impls-send.rs:32:1
+   |
+LL | unsafe impl Send for &'static [NotSync] {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0117, E0321.
+For more information about an error, try `rustc --explain E0117`.
diff --git a/src/test/ui/coherence/coherence-impls-send.re.stderr b/src/test/ui/coherence/coherence-impls-send.re.stderr
new file mode 100644
index 0000000..3ede836
--- /dev/null
+++ b/src/test/ui/coherence/coherence-impls-send.re.stderr
@@ -0,0 +1,37 @@
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/coherence-impls-send.rs:20:1
+   |
+LL | unsafe impl Send for (MyType, MyType) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error[E0321]: cross-crate traits with a default impl, like `std::marker::Send`, can only be implemented for a struct/enum type, not `&'static NotSync`
+  --> $DIR/coherence-impls-send.rs:24:1
+   |
+LL | unsafe impl Send for &'static NotSync {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type
+
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/coherence-impls-send.rs:28:1
+   |
+LL | unsafe impl Send for [MyType] {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/coherence-impls-send.rs:32:1
+   |
+LL | unsafe impl Send for &'static [NotSync] {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0117, E0321.
+For more information about an error, try `rustc --explain E0117`.
diff --git a/src/test/ui/coherence/coherence-impls-send.rs b/src/test/ui/coherence/coherence-impls-send.rs
new file mode 100644
index 0000000..ef13e9c
--- /dev/null
+++ b/src/test/ui/coherence/coherence-impls-send.rs
@@ -0,0 +1,37 @@
+// revisions: old re
+
+#![cfg_attr(re, feature(re_rebalance_coherence))]
+#![feature(optin_builtin_traits)]
+#![feature(overlapping_marker_traits)]
+
+use std::marker::Copy;
+
+enum TestE {
+  A
+}
+
+struct MyType;
+
+struct NotSync;
+impl !Sync for NotSync {}
+
+unsafe impl Send for TestE {}
+unsafe impl Send for MyType {}
+unsafe impl Send for (MyType, MyType) {}
+//[old]~^ ERROR E0117
+//[re]~^^ ERROR E0117
+
+unsafe impl Send for &'static NotSync {}
+//[old]~^ ERROR E0321
+//[re]~^^ ERROR E0321
+
+unsafe impl Send for [MyType] {}
+//[old]~^ ERROR E0117
+//[re]~^^ ERROR E0117
+
+unsafe impl Send for &'static [NotSync] {}
+//[old]~^ ERROR E0117
+//[re]~^^ ERROR E0117
+
+fn main() {
+}
diff --git a/src/test/ui/coherence/coherence-impls-sized.old.stderr b/src/test/ui/coherence/coherence-impls-sized.old.stderr
new file mode 100644
index 0000000..86a0996
--- /dev/null
+++ b/src/test/ui/coherence/coherence-impls-sized.old.stderr
@@ -0,0 +1,67 @@
+error[E0322]: explicit impls for the `Sized` trait are not permitted
+  --> $DIR/coherence-impls-sized.rs:17:1
+   |
+LL | impl Sized for TestE {}
+   | ^^^^^^^^^^^^^^^^^^^^ impl of 'Sized' not allowed
+
+error[E0322]: explicit impls for the `Sized` trait are not permitted
+  --> $DIR/coherence-impls-sized.rs:22:1
+   |
+LL | impl Sized for MyType {}
+   | ^^^^^^^^^^^^^^^^^^^^^ impl of 'Sized' not allowed
+
+error[E0322]: explicit impls for the `Sized` trait are not permitted
+  --> $DIR/coherence-impls-sized.rs:27:1
+   |
+LL | impl Sized for (MyType, MyType) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of 'Sized' not allowed
+
+error[E0322]: explicit impls for the `Sized` trait are not permitted
+  --> $DIR/coherence-impls-sized.rs:34:1
+   |
+LL | impl Sized for &'static NotSync {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of 'Sized' not allowed
+
+error[E0322]: explicit impls for the `Sized` trait are not permitted
+  --> $DIR/coherence-impls-sized.rs:39:1
+   |
+LL | impl Sized for [MyType] {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^ impl of 'Sized' not allowed
+
+error[E0322]: explicit impls for the `Sized` trait are not permitted
+  --> $DIR/coherence-impls-sized.rs:46:1
+   |
+LL | impl Sized for &'static [NotSync] {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of 'Sized' not allowed
+
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/coherence-impls-sized.rs:27:1
+   |
+LL | impl Sized for (MyType, MyType) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/coherence-impls-sized.rs:39:1
+   |
+LL | impl Sized for [MyType] {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/coherence-impls-sized.rs:46:1
+   |
+LL | impl Sized for &'static [NotSync] {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error: aborting due to 9 previous errors
+
+Some errors occurred: E0117, E0322.
+For more information about an error, try `rustc --explain E0117`.
diff --git a/src/test/ui/coherence/coherence-impls-sized.re.stderr b/src/test/ui/coherence/coherence-impls-sized.re.stderr
new file mode 100644
index 0000000..86a0996
--- /dev/null
+++ b/src/test/ui/coherence/coherence-impls-sized.re.stderr
@@ -0,0 +1,67 @@
+error[E0322]: explicit impls for the `Sized` trait are not permitted
+  --> $DIR/coherence-impls-sized.rs:17:1
+   |
+LL | impl Sized for TestE {}
+   | ^^^^^^^^^^^^^^^^^^^^ impl of 'Sized' not allowed
+
+error[E0322]: explicit impls for the `Sized` trait are not permitted
+  --> $DIR/coherence-impls-sized.rs:22:1
+   |
+LL | impl Sized for MyType {}
+   | ^^^^^^^^^^^^^^^^^^^^^ impl of 'Sized' not allowed
+
+error[E0322]: explicit impls for the `Sized` trait are not permitted
+  --> $DIR/coherence-impls-sized.rs:27:1
+   |
+LL | impl Sized for (MyType, MyType) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of 'Sized' not allowed
+
+error[E0322]: explicit impls for the `Sized` trait are not permitted
+  --> $DIR/coherence-impls-sized.rs:34:1
+   |
+LL | impl Sized for &'static NotSync {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of 'Sized' not allowed
+
+error[E0322]: explicit impls for the `Sized` trait are not permitted
+  --> $DIR/coherence-impls-sized.rs:39:1
+   |
+LL | impl Sized for [MyType] {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^ impl of 'Sized' not allowed
+
+error[E0322]: explicit impls for the `Sized` trait are not permitted
+  --> $DIR/coherence-impls-sized.rs:46:1
+   |
+LL | impl Sized for &'static [NotSync] {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of 'Sized' not allowed
+
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/coherence-impls-sized.rs:27:1
+   |
+LL | impl Sized for (MyType, MyType) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/coherence-impls-sized.rs:39:1
+   |
+LL | impl Sized for [MyType] {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/coherence-impls-sized.rs:46:1
+   |
+LL | impl Sized for &'static [NotSync] {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error: aborting due to 9 previous errors
+
+Some errors occurred: E0117, E0322.
+For more information about an error, try `rustc --explain E0117`.
diff --git a/src/test/ui/coherence/coherence-impls-sized.rs b/src/test/ui/coherence/coherence-impls-sized.rs
new file mode 100644
index 0000000..84ae2dd
--- /dev/null
+++ b/src/test/ui/coherence/coherence-impls-sized.rs
@@ -0,0 +1,54 @@
+// revisions: old re
+
+#![cfg_attr(re, feature(re_rebalance_coherence))]
+#![feature(optin_builtin_traits)]
+
+use std::marker::Copy;
+
+enum TestE {
+  A
+}
+
+struct MyType;
+
+struct NotSync;
+impl !Sync for NotSync {}
+
+impl Sized for TestE {}
+//[old]~^ ERROR E0322
+//[old]~| impl of 'Sized' not allowed
+//[re]~^^^ ERROR E0322
+
+impl Sized for MyType {}
+//[old]~^ ERROR E0322
+//[old]~| impl of 'Sized' not allowed
+//[re]~^^^ ERROR E0322
+
+impl Sized for (MyType, MyType) {}
+//[old]~^ ERROR E0322
+//[old]~| impl of 'Sized' not allowed
+//[old]~| ERROR E0117
+//[re]~^^^^ ERROR E0322
+//[re]~| ERROR E0117
+
+impl Sized for &'static NotSync {}
+//[old]~^ ERROR E0322
+//[old]~| impl of 'Sized' not allowed
+//[re]~^^^ ERROR E0322
+
+impl Sized for [MyType] {}
+//[old]~^ ERROR E0322
+//[old]~| impl of 'Sized' not allowed
+//[old]~| ERROR E0117
+//[re]~^^^^ ERROR E0322
+//[re]~| ERROR E0117
+
+impl Sized for &'static [NotSync] {}
+//[old]~^ ERROR E0322
+//[old]~| impl of 'Sized' not allowed
+//[old]~| ERROR E0117
+//[re]~^^^^ ERROR E0322
+//[re]~| ERROR E0117
+
+fn main() {
+}
diff --git a/src/test/ui/coherence/coherence-inherited-assoc-ty-cycle-err.old.stderr b/src/test/ui/coherence/coherence-inherited-assoc-ty-cycle-err.old.stderr
new file mode 100644
index 0000000..a2fa49a
--- /dev/null
+++ b/src/test/ui/coherence/coherence-inherited-assoc-ty-cycle-err.old.stderr
@@ -0,0 +1,16 @@
+error[E0391]: cycle detected when processing `Trait`
+  --> $DIR/coherence-inherited-assoc-ty-cycle-err.rs:12:1
+   |
+LL | trait Trait<T> { type Assoc; }
+   | ^^^^^^^^^^^^^^
+   |
+   = note: ...which again requires processing `Trait`, completing the cycle
+note: cycle used when coherence checking all impls of trait `Trait`
+  --> $DIR/coherence-inherited-assoc-ty-cycle-err.rs:12:1
+   |
+LL | trait Trait<T> { type Assoc; }
+   | ^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/coherence/coherence-inherited-assoc-ty-cycle-err.re.stderr b/src/test/ui/coherence/coherence-inherited-assoc-ty-cycle-err.re.stderr
new file mode 100644
index 0000000..a2fa49a
--- /dev/null
+++ b/src/test/ui/coherence/coherence-inherited-assoc-ty-cycle-err.re.stderr
@@ -0,0 +1,16 @@
+error[E0391]: cycle detected when processing `Trait`
+  --> $DIR/coherence-inherited-assoc-ty-cycle-err.rs:12:1
+   |
+LL | trait Trait<T> { type Assoc; }
+   | ^^^^^^^^^^^^^^
+   |
+   = note: ...which again requires processing `Trait`, completing the cycle
+note: cycle used when coherence checking all impls of trait `Trait`
+  --> $DIR/coherence-inherited-assoc-ty-cycle-err.rs:12:1
+   |
+LL | trait Trait<T> { type Assoc; }
+   | ^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/coherence/coherence-inherited-assoc-ty-cycle-err.rs b/src/test/ui/coherence/coherence-inherited-assoc-ty-cycle-err.rs
new file mode 100644
index 0000000..5a6b8fb
--- /dev/null
+++ b/src/test/ui/coherence/coherence-inherited-assoc-ty-cycle-err.rs
@@ -0,0 +1,28 @@
+// Formerly this ICEd with the following message:
+// Tried to project an inherited associated type during coherence checking,
+// which is currently not supported.
+//
+// No we expect to run into a more user-friendly cycle error instead.
+
+// revisions: old re
+
+#![cfg_attr(re, feature(re_rebalance_coherence))]
+#![feature(specialization)]
+
+trait Trait<T> { type Assoc; }
+//[old]~^ cycle detected
+//[re]~^^ ERROR E0391
+
+impl<T> Trait<T> for Vec<T> {
+    type Assoc = ();
+}
+
+impl Trait<u8> for Vec<u8> {}
+
+impl<T> Trait<T> for String {
+    type Assoc = ();
+}
+
+impl Trait<<Vec<u8> as Trait<u8>>::Assoc> for String {}
+
+fn main() {}
diff --git a/src/test/ui/coherence/coherence-lone-type-parameter.old.stderr b/src/test/ui/coherence/coherence-lone-type-parameter.old.stderr
new file mode 100644
index 0000000..ac77241
--- /dev/null
+++ b/src/test/ui/coherence/coherence-lone-type-parameter.old.stderr
@@ -0,0 +1,11 @@
+error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
+  --> $DIR/coherence-lone-type-parameter.rs:9:1
+   |
+LL | impl<T> Remote for T { }
+   | ^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type
+   |
+   = note: only traits defined in the current crate can be implemented for a type parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0210`.
diff --git a/src/test/ui/coherence/coherence-lone-type-parameter.re.stderr b/src/test/ui/coherence/coherence-lone-type-parameter.re.stderr
new file mode 100644
index 0000000..ac77241
--- /dev/null
+++ b/src/test/ui/coherence/coherence-lone-type-parameter.re.stderr
@@ -0,0 +1,11 @@
+error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
+  --> $DIR/coherence-lone-type-parameter.rs:9:1
+   |
+LL | impl<T> Remote for T { }
+   | ^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type
+   |
+   = note: only traits defined in the current crate can be implemented for a type parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0210`.
diff --git a/src/test/ui/coherence/coherence-lone-type-parameter.rs b/src/test/ui/coherence/coherence-lone-type-parameter.rs
new file mode 100644
index 0000000..63b38bf
--- /dev/null
+++ b/src/test/ui/coherence/coherence-lone-type-parameter.rs
@@ -0,0 +1,14 @@
+// aux-build:coherence_lib.rs
+// revisions: old re
+
+#![cfg_attr(re, feature(re_rebalance_coherence))]
+
+extern crate coherence_lib as lib;
+use lib::Remote;
+
+impl<T> Remote for T { }
+//[old]~^ ERROR type parameter `T` must be used as the type parameter for some local type
+//[re]~^^ ERROR E0210
+
+
+fn main() { }
diff --git a/src/test/ui/coherence/coherence-negative-impls-safe.old.stderr b/src/test/ui/coherence/coherence-negative-impls-safe.old.stderr
new file mode 100644
index 0000000..7ed47dc
--- /dev/null
+++ b/src/test/ui/coherence/coherence-negative-impls-safe.old.stderr
@@ -0,0 +1,9 @@
+error[E0198]: negative impls cannot be unsafe
+  --> $DIR/coherence-negative-impls-safe.rs:10:1
+   |
+LL | unsafe impl !Send for TestType {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0198`.
diff --git a/src/test/ui/coherence/coherence-negative-impls-safe.re.stderr b/src/test/ui/coherence/coherence-negative-impls-safe.re.stderr
new file mode 100644
index 0000000..7ed47dc
--- /dev/null
+++ b/src/test/ui/coherence/coherence-negative-impls-safe.re.stderr
@@ -0,0 +1,9 @@
+error[E0198]: negative impls cannot be unsafe
+  --> $DIR/coherence-negative-impls-safe.rs:10:1
+   |
+LL | unsafe impl !Send for TestType {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0198`.
diff --git a/src/test/ui/coherence/coherence-negative-impls-safe.rs b/src/test/ui/coherence/coherence-negative-impls-safe.rs
new file mode 100644
index 0000000..b6658d5
--- /dev/null
+++ b/src/test/ui/coherence/coherence-negative-impls-safe.rs
@@ -0,0 +1,14 @@
+// revisions: old re
+
+#![cfg_attr(re, feature(re_rebalance_coherence))]
+#![feature(optin_builtin_traits)]
+
+use std::marker::Send;
+
+struct TestType;
+
+unsafe impl !Send for TestType {}
+//[old]~^ ERROR negative impls cannot be unsafe
+//[re]~^^ ERROR E0198
+
+fn main() {}
diff --git a/src/test/ui/coherence/coherence-no-direct-lifetime-dispatch.old.stderr b/src/test/ui/coherence/coherence-no-direct-lifetime-dispatch.old.stderr
new file mode 100644
index 0000000..81465e7
--- /dev/null
+++ b/src/test/ui/coherence/coherence-no-direct-lifetime-dispatch.old.stderr
@@ -0,0 +1,11 @@
+error[E0119]: conflicting implementations of trait `MyTrait`:
+  --> $DIR/coherence-no-direct-lifetime-dispatch.rs:10:1
+   |
+LL | impl<T> MyTrait for T {}
+   | --------------------- first implementation here
+LL | impl<T: 'static> MyTrait for T {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/coherence/coherence-no-direct-lifetime-dispatch.re.stderr b/src/test/ui/coherence/coherence-no-direct-lifetime-dispatch.re.stderr
new file mode 100644
index 0000000..81465e7
--- /dev/null
+++ b/src/test/ui/coherence/coherence-no-direct-lifetime-dispatch.re.stderr
@@ -0,0 +1,11 @@
+error[E0119]: conflicting implementations of trait `MyTrait`:
+  --> $DIR/coherence-no-direct-lifetime-dispatch.rs:10:1
+   |
+LL | impl<T> MyTrait for T {}
+   | --------------------- first implementation here
+LL | impl<T: 'static> MyTrait for T {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/coherence/coherence-no-direct-lifetime-dispatch.rs b/src/test/ui/coherence/coherence-no-direct-lifetime-dispatch.rs
new file mode 100644
index 0000000..9717f1e
--- /dev/null
+++ b/src/test/ui/coherence/coherence-no-direct-lifetime-dispatch.rs
@@ -0,0 +1,14 @@
+// Test that you cannot *directly* dispatch on lifetime requirements
+
+// revisions: old re
+
+#![cfg_attr(re, feature(re_rebalance_coherence))]
+
+trait MyTrait { fn foo() {} }
+
+impl<T> MyTrait for T {}
+impl<T: 'static> MyTrait for T {}
+//[old]~^ ERROR E0119
+//[re]~^^ ERROR E0119
+
+fn main() {}
diff --git a/src/test/ui/coherence/coherence-orphan.old.stderr b/src/test/ui/coherence/coherence-orphan.old.stderr
new file mode 100644
index 0000000..e6dc17d
--- /dev/null
+++ b/src/test/ui/coherence/coherence-orphan.old.stderr
@@ -0,0 +1,21 @@
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/coherence-orphan.rs:13:1
+   |
+LL | impl TheTrait<usize> for isize { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/coherence-orphan.rs:21:1
+   |
+LL | impl !Send for Vec<isize> { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0117`.
diff --git a/src/test/ui/coherence/coherence-orphan.re.stderr b/src/test/ui/coherence/coherence-orphan.re.stderr
new file mode 100644
index 0000000..e6dc17d
--- /dev/null
+++ b/src/test/ui/coherence/coherence-orphan.re.stderr
@@ -0,0 +1,21 @@
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/coherence-orphan.rs:13:1
+   |
+LL | impl TheTrait<usize> for isize { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/coherence-orphan.rs:21:1
+   |
+LL | impl !Send for Vec<isize> { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0117`.
diff --git a/src/test/ui/coherence/coherence-orphan.rs b/src/test/ui/coherence/coherence-orphan.rs
new file mode 100644
index 0000000..18f50e4
--- /dev/null
+++ b/src/test/ui/coherence/coherence-orphan.rs
@@ -0,0 +1,25 @@
+// aux-build:coherence_orphan_lib.rs
+// revisions: old re
+
+#![cfg_attr(re, feature(re_rebalance_coherence))]
+#![feature(optin_builtin_traits)]
+
+extern crate coherence_orphan_lib as lib;
+
+use lib::TheTrait;
+
+struct TheType;
+
+impl TheTrait<usize> for isize { }
+//[old]~^ ERROR E0117
+//[re]~^^ ERROR E0117
+
+impl TheTrait<TheType> for isize { }
+
+impl TheTrait<isize> for TheType { }
+
+impl !Send for Vec<isize> { }
+//[old]~^ ERROR E0117
+//[re]~^^ ERROR E0117
+
+fn main() { }
diff --git a/src/test/ui/coherence/coherence-overlap-all-t-and-tuple.old.stderr b/src/test/ui/coherence/coherence-overlap-all-t-and-tuple.old.stderr
new file mode 100644
index 0000000..c7f85b0
--- /dev/null
+++ b/src/test/ui/coherence/coherence-overlap-all-t-and-tuple.old.stderr
@@ -0,0 +1,12 @@
+error[E0119]: conflicting implementations of trait `From<(_,)>` for type `(_,)`:
+  --> $DIR/coherence-overlap-all-t-and-tuple.rs:20:1
+   |
+LL | impl <T> From<T> for T {
+   | ---------------------- first implementation here
+...
+LL | impl <T11, U11> From<(U11,)> for (T11,) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(_,)`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/coherence/coherence-overlap-all-t-and-tuple.re.stderr b/src/test/ui/coherence/coherence-overlap-all-t-and-tuple.re.stderr
new file mode 100644
index 0000000..c7f85b0
--- /dev/null
+++ b/src/test/ui/coherence/coherence-overlap-all-t-and-tuple.re.stderr
@@ -0,0 +1,12 @@
+error[E0119]: conflicting implementations of trait `From<(_,)>` for type `(_,)`:
+  --> $DIR/coherence-overlap-all-t-and-tuple.rs:20:1
+   |
+LL | impl <T> From<T> for T {
+   | ---------------------- first implementation here
+...
+LL | impl <T11, U11> From<(U11,)> for (T11,) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(_,)`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/coherence/coherence-overlap-all-t-and-tuple.rs b/src/test/ui/coherence/coherence-overlap-all-t-and-tuple.rs
new file mode 100644
index 0000000..bf3ce89
--- /dev/null
+++ b/src/test/ui/coherence/coherence-overlap-all-t-and-tuple.rs
@@ -0,0 +1,25 @@
+// Check that we detect an overlap here in the case where:
+//
+//    for some type X:
+//      T = (X,)
+//      T11 = X, U11 = X
+//
+// Seems pretty basic, but then there was issue #24241. :)
+
+// revisions: old re
+
+#![cfg_attr(re, feature(re_rebalance_coherence))]
+
+trait From<U> {
+    fn foo() {}
+}
+
+impl <T> From<T> for T {
+}
+
+impl <T11, U11> From<(U11,)> for (T11,) {
+//[old]~^ ERROR E0119
+//[re]~^^ ERROR E0119
+}
+
+fn main() { }
diff --git a/src/test/ui/coherence/coherence-overlap-downstream-inherent.old.stderr b/src/test/ui/coherence/coherence-overlap-downstream-inherent.old.stderr
new file mode 100644
index 0000000..dcfc017
--- /dev/null
+++ b/src/test/ui/coherence/coherence-overlap-downstream-inherent.old.stderr
@@ -0,0 +1,23 @@
+error[E0592]: duplicate definitions with name `dummy`
+  --> $DIR/coherence-overlap-downstream-inherent.rs:11:26
+   |
+LL | impl<T:Sugar> Sweet<T> { fn dummy(&self) { } }
+   |                          ^^^^^^^^^^^^^^^^^^^ duplicate definitions for `dummy`
+...
+LL | impl<T:Fruit> Sweet<T> { fn dummy(&self) { } }
+   |                          ------------------- other definition for `dummy`
+
+error[E0592]: duplicate definitions with name `f`
+  --> $DIR/coherence-overlap-downstream-inherent.rs:18:38
+   |
+LL | impl<X, T> A<T, X> where T: Bar<X> { fn f(&self) {} }
+   |                                      ^^^^^^^^^^^^^^ duplicate definitions for `f`
+...
+LL | impl<X> A<i32, X> { fn f(&self) {} }
+   |                     -------------- other definition for `f`
+   |
+   = note: downstream crates may implement trait `Bar<_>` for type `i32`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0592`.
diff --git a/src/test/ui/coherence/coherence-overlap-downstream-inherent.re.stderr b/src/test/ui/coherence/coherence-overlap-downstream-inherent.re.stderr
new file mode 100644
index 0000000..dcfc017
--- /dev/null
+++ b/src/test/ui/coherence/coherence-overlap-downstream-inherent.re.stderr
@@ -0,0 +1,23 @@
+error[E0592]: duplicate definitions with name `dummy`
+  --> $DIR/coherence-overlap-downstream-inherent.rs:11:26
+   |
+LL | impl<T:Sugar> Sweet<T> { fn dummy(&self) { } }
+   |                          ^^^^^^^^^^^^^^^^^^^ duplicate definitions for `dummy`
+...
+LL | impl<T:Fruit> Sweet<T> { fn dummy(&self) { } }
+   |                          ------------------- other definition for `dummy`
+
+error[E0592]: duplicate definitions with name `f`
+  --> $DIR/coherence-overlap-downstream-inherent.rs:18:38
+   |
+LL | impl<X, T> A<T, X> where T: Bar<X> { fn f(&self) {} }
+   |                                      ^^^^^^^^^^^^^^ duplicate definitions for `f`
+...
+LL | impl<X> A<i32, X> { fn f(&self) {} }
+   |                     -------------- other definition for `f`
+   |
+   = note: downstream crates may implement trait `Bar<_>` for type `i32`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0592`.
diff --git a/src/test/ui/coherence/coherence-overlap-downstream-inherent.rs b/src/test/ui/coherence/coherence-overlap-downstream-inherent.rs
new file mode 100644
index 0000000..ad54d24
--- /dev/null
+++ b/src/test/ui/coherence/coherence-overlap-downstream-inherent.rs
@@ -0,0 +1,23 @@
+// Tests that we consider `T: Sugar + Fruit` to be ambiguous, even
+// though no impls are found.
+
+// revisions: old re
+
+#![cfg_attr(re, feature(re_rebalance_coherence))]
+
+struct Sweet<X>(X);
+pub trait Sugar {}
+pub trait Fruit {}
+impl<T:Sugar> Sweet<T> { fn dummy(&self) { } }
+//[old]~^ ERROR E0592
+//[re]~^^ ERROR E0592
+impl<T:Fruit> Sweet<T> { fn dummy(&self) { } }
+
+trait Bar<X> {}
+struct A<T, X>(T, X);
+impl<X, T> A<T, X> where T: Bar<X> { fn f(&self) {} }
+//[old]~^ ERROR E0592
+//[re]~^^ ERROR E0592
+impl<X> A<i32, X> { fn f(&self) {} }
+
+fn main() {}
diff --git a/src/test/ui/coherence/coherence-overlap-downstream.old.stderr b/src/test/ui/coherence/coherence-overlap-downstream.old.stderr
new file mode 100644
index 0000000..b4847c0
--- /dev/null
+++ b/src/test/ui/coherence/coherence-overlap-downstream.old.stderr
@@ -0,0 +1,21 @@
+error[E0119]: conflicting implementations of trait `Sweet`:
+  --> $DIR/coherence-overlap-downstream.rs:12:1
+   |
+LL | impl<T:Sugar> Sweet for T { }
+   | ------------------------- first implementation here
+LL | impl<T:Fruit> Sweet for T { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
+
+error[E0119]: conflicting implementations of trait `Foo<_>` for type `i32`:
+  --> $DIR/coherence-overlap-downstream.rs:19:1
+   |
+LL | impl<X, T> Foo<X> for T where T: Bar<X> {}
+   | --------------------------------------- first implementation here
+LL | impl<X> Foo<X> for i32 {}
+   | ^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `i32`
+   |
+   = note: downstream crates may implement trait `Bar<_>` for type `i32`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/coherence/coherence-overlap-downstream.re.stderr b/src/test/ui/coherence/coherence-overlap-downstream.re.stderr
new file mode 100644
index 0000000..b4847c0
--- /dev/null
+++ b/src/test/ui/coherence/coherence-overlap-downstream.re.stderr
@@ -0,0 +1,21 @@
+error[E0119]: conflicting implementations of trait `Sweet`:
+  --> $DIR/coherence-overlap-downstream.rs:12:1
+   |
+LL | impl<T:Sugar> Sweet for T { }
+   | ------------------------- first implementation here
+LL | impl<T:Fruit> Sweet for T { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
+
+error[E0119]: conflicting implementations of trait `Foo<_>` for type `i32`:
+  --> $DIR/coherence-overlap-downstream.rs:19:1
+   |
+LL | impl<X, T> Foo<X> for T where T: Bar<X> {}
+   | --------------------------------------- first implementation here
+LL | impl<X> Foo<X> for i32 {}
+   | ^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `i32`
+   |
+   = note: downstream crates may implement trait `Bar<_>` for type `i32`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/coherence/coherence-overlap-downstream.rs b/src/test/ui/coherence/coherence-overlap-downstream.rs
new file mode 100644
index 0000000..c6ced7b
--- /dev/null
+++ b/src/test/ui/coherence/coherence-overlap-downstream.rs
@@ -0,0 +1,23 @@
+// Tests that we consider `T: Sugar + Fruit` to be ambiguous, even
+// though no impls are found.
+
+// revisions: old re
+
+#![cfg_attr(re, feature(re_rebalance_coherence))]
+
+pub trait Sugar {}
+pub trait Fruit {}
+pub trait Sweet {}
+impl<T:Sugar> Sweet for T { }
+impl<T:Fruit> Sweet for T { }
+//[old]~^ ERROR E0119
+//[re]~^^ ERROR E0119
+
+pub trait Foo<X> {}
+pub trait Bar<X> {}
+impl<X, T> Foo<X> for T where T: Bar<X> {}
+impl<X> Foo<X> for i32 {}
+//[old]~^ ERROR E0119
+//[re]~^^ ERROR E0119
+
+fn main() { }
diff --git a/src/test/ui/coherence/coherence-overlap-issue-23516-inherent.old.stderr b/src/test/ui/coherence/coherence-overlap-issue-23516-inherent.old.stderr
new file mode 100644
index 0000000..6fd9307
--- /dev/null
+++ b/src/test/ui/coherence/coherence-overlap-issue-23516-inherent.old.stderr
@@ -0,0 +1,14 @@
+error[E0592]: duplicate definitions with name `dummy`
+  --> $DIR/coherence-overlap-issue-23516-inherent.rs:13:25
+   |
+LL | impl<T:Sugar> Cake<T> { fn dummy(&self) { } }
+   |                         ^^^^^^^^^^^^^^^^^^^ duplicate definitions for `dummy`
+...
+LL | impl<U:Sugar> Cake<Box<U>> { fn dummy(&self) { } }
+   |                              ------------------- other definition for `dummy`
+   |
+   = note: downstream crates may implement trait `Sugar` for type `std::boxed::Box<_>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0592`.
diff --git a/src/test/ui/coherence/coherence-overlap-issue-23516-inherent.re.stderr b/src/test/ui/coherence/coherence-overlap-issue-23516-inherent.re.stderr
new file mode 100644
index 0000000..6fd9307
--- /dev/null
+++ b/src/test/ui/coherence/coherence-overlap-issue-23516-inherent.re.stderr
@@ -0,0 +1,14 @@
+error[E0592]: duplicate definitions with name `dummy`
+  --> $DIR/coherence-overlap-issue-23516-inherent.rs:13:25
+   |
+LL | impl<T:Sugar> Cake<T> { fn dummy(&self) { } }
+   |                         ^^^^^^^^^^^^^^^^^^^ duplicate definitions for `dummy`
+...
+LL | impl<U:Sugar> Cake<Box<U>> { fn dummy(&self) { } }
+   |                              ------------------- other definition for `dummy`
+   |
+   = note: downstream crates may implement trait `Sugar` for type `std::boxed::Box<_>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0592`.
diff --git a/src/test/ui/coherence/coherence-overlap-issue-23516-inherent.rs b/src/test/ui/coherence/coherence-overlap-issue-23516-inherent.rs
new file mode 100644
index 0000000..969366e
--- /dev/null
+++ b/src/test/ui/coherence/coherence-overlap-issue-23516-inherent.rs
@@ -0,0 +1,18 @@
+// Tests that we consider `Box<U>: !Sugar` to be ambiguous, even
+// though we see no impl of `Sugar` for `Box`. Therefore, an overlap
+// error is reported for the following pair of impls (#23516).
+
+// revisions: old re
+
+#![cfg_attr(re, feature(re_rebalance_coherence))]
+
+pub trait Sugar {}
+
+struct Cake<X>(X);
+
+impl<T:Sugar> Cake<T> { fn dummy(&self) { } }
+//[old]~^ ERROR E0592
+//[re]~^^ ERROR E0592
+impl<U:Sugar> Cake<Box<U>> { fn dummy(&self) { } }
+
+fn main() { }
diff --git a/src/test/ui/coherence/coherence-overlap-issue-23516.old.stderr b/src/test/ui/coherence/coherence-overlap-issue-23516.old.stderr
new file mode 100644
index 0000000..d17d67a
--- /dev/null
+++ b/src/test/ui/coherence/coherence-overlap-issue-23516.old.stderr
@@ -0,0 +1,13 @@
+error[E0119]: conflicting implementations of trait `Sweet` for type `std::boxed::Box<_>`:
+  --> $DIR/coherence-overlap-issue-23516.rs:12:1
+   |
+LL | impl<T:Sugar> Sweet for T { }
+   | ------------------------- first implementation here
+LL | impl<U:Sugar> Sweet for Box<U> { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `std::boxed::Box<_>`
+   |
+   = note: downstream crates may implement trait `Sugar` for type `std::boxed::Box<_>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/coherence/coherence-overlap-issue-23516.re.stderr b/src/test/ui/coherence/coherence-overlap-issue-23516.re.stderr
new file mode 100644
index 0000000..d17d67a
--- /dev/null
+++ b/src/test/ui/coherence/coherence-overlap-issue-23516.re.stderr
@@ -0,0 +1,13 @@
+error[E0119]: conflicting implementations of trait `Sweet` for type `std::boxed::Box<_>`:
+  --> $DIR/coherence-overlap-issue-23516.rs:12:1
+   |
+LL | impl<T:Sugar> Sweet for T { }
+   | ------------------------- first implementation here
+LL | impl<U:Sugar> Sweet for Box<U> { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `std::boxed::Box<_>`
+   |
+   = note: downstream crates may implement trait `Sugar` for type `std::boxed::Box<_>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/coherence/coherence-overlap-issue-23516.rs b/src/test/ui/coherence/coherence-overlap-issue-23516.rs
new file mode 100644
index 0000000..e3c15e1
--- /dev/null
+++ b/src/test/ui/coherence/coherence-overlap-issue-23516.rs
@@ -0,0 +1,16 @@
+// Tests that we consider `Box<U>: !Sugar` to be ambiguous, even
+// though we see no impl of `Sugar` for `Box`. Therefore, an overlap
+// error is reported for the following pair of impls (#23516).
+
+// revisions: old re
+
+#![cfg_attr(re, feature(re_rebalance_coherence))]
+
+pub trait Sugar { fn dummy(&self) { } }
+pub trait Sweet { fn dummy(&self) { } }
+impl<T:Sugar> Sweet for T { }
+impl<U:Sugar> Sweet for Box<U> { }
+//[old]~^ ERROR E0119
+//[re]~^^ ERROR E0119
+
+fn main() { }
diff --git a/src/test/ui/coherence/coherence-overlap-messages.old.stderr b/src/test/ui/coherence/coherence-overlap-messages.old.stderr
new file mode 100644
index 0000000..429e675
--- /dev/null
+++ b/src/test/ui/coherence/coherence-overlap-messages.old.stderr
@@ -0,0 +1,44 @@
+error[E0119]: conflicting implementations of trait `Foo`:
+  --> $DIR/coherence-overlap-messages.rs:8:1
+   |
+LL | impl<T> Foo for T {}
+   | ----------------- first implementation here
+LL | impl<U> Foo for U {}
+   | ^^^^^^^^^^^^^^^^^ conflicting implementation
+
+error[E0119]: conflicting implementations of trait `Bar` for type `(u8, u8)`:
+  --> $DIR/coherence-overlap-messages.rs:16:1
+   |
+LL | impl<T> Bar for (T, u8) {}
+   | ----------------------- first implementation here
+LL | impl<T> Bar for (u8, T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(u8, u8)`
+
+error[E0119]: conflicting implementations of trait `Baz<u8>` for type `u8`:
+  --> $DIR/coherence-overlap-messages.rs:23:1
+   |
+LL | impl<T> Baz<u8> for T {}
+   | --------------------- first implementation here
+LL | impl<T> Baz<T> for u8 {}
+   | ^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u8`
+
+error[E0119]: conflicting implementations of trait `Quux<_, _>`:
+  --> $DIR/coherence-overlap-messages.rs:30:1
+   |
+LL | impl<T, U, V> Quux<U, V> for T {}
+   | ------------------------------ first implementation here
+LL | impl<T, U> Quux<U, U> for T {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
+
+error[E0119]: conflicting implementations of trait `Quux<_, _>`:
+  --> $DIR/coherence-overlap-messages.rs:33:1
+   |
+LL | impl<T, U, V> Quux<U, V> for T {}
+   | ------------------------------ first implementation here
+...
+LL | impl<T, V> Quux<T, V> for T {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/coherence/coherence-overlap-messages.re.stderr b/src/test/ui/coherence/coherence-overlap-messages.re.stderr
new file mode 100644
index 0000000..429e675
--- /dev/null
+++ b/src/test/ui/coherence/coherence-overlap-messages.re.stderr
@@ -0,0 +1,44 @@
+error[E0119]: conflicting implementations of trait `Foo`:
+  --> $DIR/coherence-overlap-messages.rs:8:1
+   |
+LL | impl<T> Foo for T {}
+   | ----------------- first implementation here
+LL | impl<U> Foo for U {}
+   | ^^^^^^^^^^^^^^^^^ conflicting implementation
+
+error[E0119]: conflicting implementations of trait `Bar` for type `(u8, u8)`:
+  --> $DIR/coherence-overlap-messages.rs:16:1
+   |
+LL | impl<T> Bar for (T, u8) {}
+   | ----------------------- first implementation here
+LL | impl<T> Bar for (u8, T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(u8, u8)`
+
+error[E0119]: conflicting implementations of trait `Baz<u8>` for type `u8`:
+  --> $DIR/coherence-overlap-messages.rs:23:1
+   |
+LL | impl<T> Baz<u8> for T {}
+   | --------------------- first implementation here
+LL | impl<T> Baz<T> for u8 {}
+   | ^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u8`
+
+error[E0119]: conflicting implementations of trait `Quux<_, _>`:
+  --> $DIR/coherence-overlap-messages.rs:30:1
+   |
+LL | impl<T, U, V> Quux<U, V> for T {}
+   | ------------------------------ first implementation here
+LL | impl<T, U> Quux<U, U> for T {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
+
+error[E0119]: conflicting implementations of trait `Quux<_, _>`:
+  --> $DIR/coherence-overlap-messages.rs:33:1
+   |
+LL | impl<T, U, V> Quux<U, V> for T {}
+   | ------------------------------ first implementation here
+...
+LL | impl<T, V> Quux<T, V> for T {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/coherence/coherence-overlap-messages.rs b/src/test/ui/coherence/coherence-overlap-messages.rs
new file mode 100644
index 0000000..e0e2e67
--- /dev/null
+++ b/src/test/ui/coherence/coherence-overlap-messages.rs
@@ -0,0 +1,37 @@
+// revisions: old re
+
+#![cfg_attr(re, feature(re_rebalance_coherence))]
+
+trait Foo { fn foo() {} }
+
+impl<T> Foo for T {}
+impl<U> Foo for U {}
+//[old]~^ ERROR conflicting implementations of trait `Foo`:
+//[re]~^^ ERROR E0119
+
+
+trait Bar { fn bar() {} }
+
+impl<T> Bar for (T, u8) {}
+impl<T> Bar for (u8, T) {}
+//[old]~^ ERROR conflicting implementations of trait `Bar` for type `(u8, u8)`:
+//[re]~^^ ERROR E0119
+
+trait Baz<T> { fn baz() {} }
+
+impl<T> Baz<u8> for T {}
+impl<T> Baz<T> for u8 {}
+//[old]~^ ERROR conflicting implementations of trait `Baz<u8>` for type `u8`:
+//[re]~^^ ERROR E0119
+
+trait Quux<U, V> { fn quux() {} }
+
+impl<T, U, V> Quux<U, V> for T {}
+impl<T, U> Quux<U, U> for T {}
+//[old]~^ ERROR conflicting implementations of trait `Quux<_, _>`:
+//[re]~^^ ERROR E0119
+impl<T, V> Quux<T, V> for T {}
+//[old]~^ ERROR conflicting implementations of trait `Quux<_, _>`:
+//[re]~^^ ERROR E0119
+
+fn main() {}
diff --git a/src/test/ui/coherence/coherence-overlap-upstream-inherent.old.stderr b/src/test/ui/coherence/coherence-overlap-upstream-inherent.old.stderr
new file mode 100644
index 0000000..928b65e
--- /dev/null
+++ b/src/test/ui/coherence/coherence-overlap-upstream-inherent.old.stderr
@@ -0,0 +1,14 @@
+error[E0592]: duplicate definitions with name `dummy`
+  --> $DIR/coherence-overlap-upstream-inherent.rs:15:32
+   |
+LL | impl<T> A<T> where T: Remote { fn dummy(&self) { } }
+   |                                ^^^^^^^^^^^^^^^^^^^ duplicate definitions for `dummy`
+...
+LL | impl A<i16> { fn dummy(&self) { } }
+   |               ------------------- other definition for `dummy`
+   |
+   = note: upstream crates may add new impl of trait `coherence_lib::Remote` for type `i16` in future versions
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0592`.
diff --git a/src/test/ui/coherence/coherence-overlap-upstream-inherent.re.stderr b/src/test/ui/coherence/coherence-overlap-upstream-inherent.re.stderr
new file mode 100644
index 0000000..928b65e
--- /dev/null
+++ b/src/test/ui/coherence/coherence-overlap-upstream-inherent.re.stderr
@@ -0,0 +1,14 @@
+error[E0592]: duplicate definitions with name `dummy`
+  --> $DIR/coherence-overlap-upstream-inherent.rs:15:32
+   |
+LL | impl<T> A<T> where T: Remote { fn dummy(&self) { } }
+   |                                ^^^^^^^^^^^^^^^^^^^ duplicate definitions for `dummy`
+...
+LL | impl A<i16> { fn dummy(&self) { } }
+   |               ------------------- other definition for `dummy`
+   |
+   = note: upstream crates may add new impl of trait `coherence_lib::Remote` for type `i16` in future versions
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0592`.
diff --git a/src/test/ui/coherence/coherence-overlap-upstream-inherent.rs b/src/test/ui/coherence/coherence-overlap-upstream-inherent.rs
new file mode 100644
index 0000000..92b619a
--- /dev/null
+++ b/src/test/ui/coherence/coherence-overlap-upstream-inherent.rs
@@ -0,0 +1,20 @@
+// Tests that we consider `i16: Remote` to be ambiguous, even
+// though the upstream crate doesn't implement it for now.
+
+// aux-build:coherence_lib.rs
+// revisions: old re
+
+#![cfg_attr(re, feature(re_rebalance_coherence))]
+
+
+extern crate coherence_lib;
+
+use coherence_lib::Remote;
+
+struct A<X>(X);
+impl<T> A<T> where T: Remote { fn dummy(&self) { } }
+//[old]~^ ERROR E0592
+//[re]~^^ ERROR E0592
+impl A<i16> { fn dummy(&self) { } }
+
+fn main() {}
diff --git a/src/test/ui/coherence/coherence-overlap-upstream.old.stderr b/src/test/ui/coherence/coherence-overlap-upstream.old.stderr
new file mode 100644
index 0000000..6c3484c
--- /dev/null
+++ b/src/test/ui/coherence/coherence-overlap-upstream.old.stderr
@@ -0,0 +1,13 @@
+error[E0119]: conflicting implementations of trait `Foo` for type `i16`:
+  --> $DIR/coherence-overlap-upstream.rs:16:1
+   |
+LL | impl<T> Foo for T where T: Remote {}
+   | --------------------------------- first implementation here
+LL | impl Foo for i16 {}
+   | ^^^^^^^^^^^^^^^^ conflicting implementation for `i16`
+   |
+   = note: upstream crates may add new impl of trait `coherence_lib::Remote` for type `i16` in future versions
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/coherence/coherence-overlap-upstream.re.stderr b/src/test/ui/coherence/coherence-overlap-upstream.re.stderr
new file mode 100644
index 0000000..6c3484c
--- /dev/null
+++ b/src/test/ui/coherence/coherence-overlap-upstream.re.stderr
@@ -0,0 +1,13 @@
+error[E0119]: conflicting implementations of trait `Foo` for type `i16`:
+  --> $DIR/coherence-overlap-upstream.rs:16:1
+   |
+LL | impl<T> Foo for T where T: Remote {}
+   | --------------------------------- first implementation here
+LL | impl Foo for i16 {}
+   | ^^^^^^^^^^^^^^^^ conflicting implementation for `i16`
+   |
+   = note: upstream crates may add new impl of trait `coherence_lib::Remote` for type `i16` in future versions
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/coherence/coherence-overlap-upstream.rs b/src/test/ui/coherence/coherence-overlap-upstream.rs
new file mode 100644
index 0000000..62f6750
--- /dev/null
+++ b/src/test/ui/coherence/coherence-overlap-upstream.rs
@@ -0,0 +1,20 @@
+// Tests that we consider `i16: Remote` to be ambiguous, even
+// though the upstream crate doesn't implement it for now.
+
+// aux-build:coherence_lib.rs
+// revisions: old re
+
+#![cfg_attr(re, feature(re_rebalance_coherence))]
+
+
+extern crate coherence_lib;
+
+use coherence_lib::Remote;
+
+trait Foo {}
+impl<T> Foo for T where T: Remote {}
+impl Foo for i16 {}
+//[old]~^ ERROR E0119
+//[re]~^^ ERROR E0119
+
+fn main() {}
diff --git a/src/test/ui/coherence/coherence-overlapping-pairs.old.stderr b/src/test/ui/coherence/coherence-overlapping-pairs.old.stderr
new file mode 100644
index 0000000..b275af9
--- /dev/null
+++ b/src/test/ui/coherence/coherence-overlapping-pairs.old.stderr
@@ -0,0 +1,11 @@
+error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
+  --> $DIR/coherence-overlapping-pairs.rs:11:1
+   |
+LL | impl<T> Remote for lib::Pair<T,Foo> { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type
+   |
+   = note: only traits defined in the current crate can be implemented for a type parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0210`.
diff --git a/src/test/ui/coherence/coherence-overlapping-pairs.re.stderr b/src/test/ui/coherence/coherence-overlapping-pairs.re.stderr
new file mode 100644
index 0000000..a6fa609
--- /dev/null
+++ b/src/test/ui/coherence/coherence-overlapping-pairs.re.stderr
@@ -0,0 +1,12 @@
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/coherence-overlapping-pairs.rs:11:1
+   |
+LL | impl<T> Remote for lib::Pair<T,Foo> { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0117`.
diff --git a/src/test/ui/coherence/coherence-overlapping-pairs.rs b/src/test/ui/coherence/coherence-overlapping-pairs.rs
new file mode 100644
index 0000000..de31a08
--- /dev/null
+++ b/src/test/ui/coherence/coherence-overlapping-pairs.rs
@@ -0,0 +1,15 @@
+// aux-build:coherence_lib.rs
+// revisions: old re
+
+#![cfg_attr(re, feature(re_rebalance_coherence))]
+
+extern crate coherence_lib as lib;
+use lib::Remote;
+
+struct Foo;
+
+impl<T> Remote for lib::Pair<T,Foo> { }
+//[old]~^ ERROR type parameter `T` must be used as the type parameter for some local type
+//[re]~^^ ERROR E0117
+
+fn main() { }
diff --git a/src/test/ui/coherence/coherence-pair-covered-uncovered-1.old.stderr b/src/test/ui/coherence/coherence-pair-covered-uncovered-1.old.stderr
new file mode 100644
index 0000000..8b25bee
--- /dev/null
+++ b/src/test/ui/coherence/coherence-pair-covered-uncovered-1.old.stderr
@@ -0,0 +1,11 @@
+error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
+  --> $DIR/coherence-pair-covered-uncovered-1.rs:15:1
+   |
+LL | impl<T, U> Remote1<Pair<T, Local<U>>> for i32 { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type
+   |
+   = note: only traits defined in the current crate can be implemented for a type parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0210`.
diff --git a/src/test/ui/coherence/coherence-pair-covered-uncovered-1.re.stderr b/src/test/ui/coherence/coherence-pair-covered-uncovered-1.re.stderr
new file mode 100644
index 0000000..e45cd78
--- /dev/null
+++ b/src/test/ui/coherence/coherence-pair-covered-uncovered-1.re.stderr
@@ -0,0 +1,12 @@
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/coherence-pair-covered-uncovered-1.rs:15:1
+   |
+LL | impl<T, U> Remote1<Pair<T, Local<U>>> for i32 { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0117`.
diff --git a/src/test/ui/coherence/coherence-pair-covered-uncovered-1.rs b/src/test/ui/coherence/coherence-pair-covered-uncovered-1.rs
new file mode 100644
index 0000000..91794b7
--- /dev/null
+++ b/src/test/ui/coherence/coherence-pair-covered-uncovered-1.rs
@@ -0,0 +1,19 @@
+// Test that the same coverage rules apply even if the local type appears in the
+// list of type parameters, not the self type.
+
+// aux-build:coherence_lib.rs
+// revisions: old re
+
+#![cfg_attr(re, feature(re_rebalance_coherence))]
+
+
+extern crate coherence_lib as lib;
+use lib::{Remote1, Pair};
+
+pub struct Local<T>(T);
+
+impl<T, U> Remote1<Pair<T, Local<U>>> for i32 { }
+//[old]~^ ERROR type parameter `T` must be used as the type parameter for some local type
+//[re]~^^ ERROR E0117
+
+fn main() { }
diff --git a/src/test/ui/coherence/coherence-pair-covered-uncovered.old.stderr b/src/test/ui/coherence/coherence-pair-covered-uncovered.old.stderr
new file mode 100644
index 0000000..39558d8
--- /dev/null
+++ b/src/test/ui/coherence/coherence-pair-covered-uncovered.old.stderr
@@ -0,0 +1,11 @@
+error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
+  --> $DIR/coherence-pair-covered-uncovered.rs:11:1
+   |
+LL | impl<T,U> Remote for Pair<T,Local<U>> { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type
+   |
+   = note: only traits defined in the current crate can be implemented for a type parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0210`.
diff --git a/src/test/ui/coherence/coherence-pair-covered-uncovered.re.stderr b/src/test/ui/coherence/coherence-pair-covered-uncovered.re.stderr
new file mode 100644
index 0000000..54d5f3058
--- /dev/null
+++ b/src/test/ui/coherence/coherence-pair-covered-uncovered.re.stderr
@@ -0,0 +1,12 @@
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/coherence-pair-covered-uncovered.rs:11:1
+   |
+LL | impl<T,U> Remote for Pair<T,Local<U>> { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0117`.
diff --git a/src/test/ui/coherence/coherence-pair-covered-uncovered.rs b/src/test/ui/coherence/coherence-pair-covered-uncovered.rs
new file mode 100644
index 0000000..49a9141
--- /dev/null
+++ b/src/test/ui/coherence/coherence-pair-covered-uncovered.rs
@@ -0,0 +1,15 @@
+// aux-build:coherence_lib.rs
+// revisions: old re
+
+#![cfg_attr(re, feature(re_rebalance_coherence))]
+
+extern crate coherence_lib as lib;
+use lib::{Remote, Pair};
+
+struct Local<T>(T);
+
+impl<T,U> Remote for Pair<T,Local<U>> { }
+//[old]~^ ERROR type parameter `T` must be used as the type parameter for some local type
+//[re]~^^ ERROR E0117
+
+fn main() { }
diff --git a/src/test/ui/coherence/coherence-projection-conflict-orphan.old.stderr b/src/test/ui/coherence/coherence-projection-conflict-orphan.old.stderr
new file mode 100644
index 0000000..cde9360
--- /dev/null
+++ b/src/test/ui/coherence/coherence-projection-conflict-orphan.old.stderr
@@ -0,0 +1,14 @@
+error[E0119]: conflicting implementations of trait `Foo<i32>` for type `i32`:
+  --> $DIR/coherence-projection-conflict-orphan.rs:19:1
+   |
+LL | impl Foo<i32> for i32 { }
+   | --------------------- first implementation here
+LL | 
+LL | impl<A:Iterator> Foo<A::Item> for A { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `i32`
+   |
+   = note: upstream crates may add new impl of trait `std::iter::Iterator` for type `i32` in future versions
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/coherence/coherence-projection-conflict-orphan.re.stderr b/src/test/ui/coherence/coherence-projection-conflict-orphan.re.stderr
new file mode 100644
index 0000000..cde9360
--- /dev/null
+++ b/src/test/ui/coherence/coherence-projection-conflict-orphan.re.stderr
@@ -0,0 +1,14 @@
+error[E0119]: conflicting implementations of trait `Foo<i32>` for type `i32`:
+  --> $DIR/coherence-projection-conflict-orphan.rs:19:1
+   |
+LL | impl Foo<i32> for i32 { }
+   | --------------------- first implementation here
+LL | 
+LL | impl<A:Iterator> Foo<A::Item> for A { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `i32`
+   |
+   = note: upstream crates may add new impl of trait `std::iter::Iterator` for type `i32` in future versions
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/coherence/coherence-projection-conflict-orphan.rs b/src/test/ui/coherence/coherence-projection-conflict-orphan.rs
new file mode 100644
index 0000000..4f7fc71
--- /dev/null
+++ b/src/test/ui/coherence/coherence-projection-conflict-orphan.rs
@@ -0,0 +1,23 @@
+// revisions: old re
+
+#![cfg_attr(re, feature(re_rebalance_coherence))]
+#![feature(rustc_attrs)]
+
+// Here we expect a coherence conflict because, even though `i32` does
+// not implement `Iterator`, we cannot rely on that negative reasoning
+// due to the orphan rules. Therefore, `A::Item` may yet turn out to
+// be `i32`.
+
+pub trait Foo<P> { fn foo() {} }
+
+pub trait Bar {
+    type Output: 'static;
+}
+
+impl Foo<i32> for i32 { }
+
+impl<A:Iterator> Foo<A::Item> for A { }
+//[old]~^ ERROR E0119
+//[re]~^^ ERROR E0119
+
+fn main() {}
diff --git a/src/test/ui/coherence/coherence-projection-conflict-ty-param.old.stderr b/src/test/ui/coherence/coherence-projection-conflict-ty-param.old.stderr
new file mode 100644
index 0000000..b53a4c9
--- /dev/null
+++ b/src/test/ui/coherence/coherence-projection-conflict-ty-param.old.stderr
@@ -0,0 +1,12 @@
+error[E0119]: conflicting implementations of trait `Foo<_>` for type `std::option::Option<_>`:
+  --> $DIR/coherence-projection-conflict-ty-param.rs:14:1
+   |
+LL | impl <P, T: Foo<P>> Foo<P> for Option<T> {}
+   | ---------------------------------------- first implementation here
+LL | 
+LL | impl<T, U> Foo<T> for Option<U> { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `std::option::Option<_>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/coherence/coherence-projection-conflict-ty-param.re.stderr b/src/test/ui/coherence/coherence-projection-conflict-ty-param.re.stderr
new file mode 100644
index 0000000..b53a4c9
--- /dev/null
+++ b/src/test/ui/coherence/coherence-projection-conflict-ty-param.re.stderr
@@ -0,0 +1,12 @@
+error[E0119]: conflicting implementations of trait `Foo<_>` for type `std::option::Option<_>`:
+  --> $DIR/coherence-projection-conflict-ty-param.rs:14:1
+   |
+LL | impl <P, T: Foo<P>> Foo<P> for Option<T> {}
+   | ---------------------------------------- first implementation here
+LL | 
+LL | impl<T, U> Foo<T> for Option<U> { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `std::option::Option<_>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/coherence/coherence-projection-conflict-ty-param.rs b/src/test/ui/coherence/coherence-projection-conflict-ty-param.rs
new file mode 100644
index 0000000..819947f
--- /dev/null
+++ b/src/test/ui/coherence/coherence-projection-conflict-ty-param.rs
@@ -0,0 +1,18 @@
+// Coherence error results because we do not know whether `T: Foo<P>` or not
+// for the second impl.
+
+// revisions: old re
+
+#![cfg_attr(re, feature(re_rebalance_coherence))]
+
+use std::marker::PhantomData;
+
+pub trait Foo<P> { fn foo() {} }
+
+impl <P, T: Foo<P>> Foo<P> for Option<T> {}
+
+impl<T, U> Foo<T> for Option<U> { }
+//[old]~^ ERROR E0119
+//[re]~^^ ERROR E0119
+
+fn main() {}
diff --git a/src/test/ui/coherence/coherence-projection-conflict.old.stderr b/src/test/ui/coherence/coherence-projection-conflict.old.stderr
new file mode 100644
index 0000000..c2e5fc8
--- /dev/null
+++ b/src/test/ui/coherence/coherence-projection-conflict.old.stderr
@@ -0,0 +1,12 @@
+error[E0119]: conflicting implementations of trait `Foo<i32>` for type `i32`:
+  --> $DIR/coherence-projection-conflict.rs:15:1
+   |
+LL | impl Foo<i32> for i32 { }
+   | --------------------- first implementation here
+LL | 
+LL | impl<A:Bar> Foo<A::Output> for A { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `i32`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/coherence/coherence-projection-conflict.re.stderr b/src/test/ui/coherence/coherence-projection-conflict.re.stderr
new file mode 100644
index 0000000..c2e5fc8
--- /dev/null
+++ b/src/test/ui/coherence/coherence-projection-conflict.re.stderr
@@ -0,0 +1,12 @@
+error[E0119]: conflicting implementations of trait `Foo<i32>` for type `i32`:
+  --> $DIR/coherence-projection-conflict.rs:15:1
+   |
+LL | impl Foo<i32> for i32 { }
+   | --------------------- first implementation here
+LL | 
+LL | impl<A:Bar> Foo<A::Output> for A { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `i32`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/coherence/coherence-projection-conflict.rs b/src/test/ui/coherence/coherence-projection-conflict.rs
new file mode 100644
index 0000000..4086aee
--- /dev/null
+++ b/src/test/ui/coherence/coherence-projection-conflict.rs
@@ -0,0 +1,23 @@
+// revisions: old re
+
+#![cfg_attr(re, feature(re_rebalance_coherence))]
+
+use std::marker::PhantomData;
+
+pub trait Foo<P> { fn foo() {} }
+
+pub trait Bar {
+    type Output: 'static;
+}
+
+impl Foo<i32> for i32 { }
+
+impl<A:Bar> Foo<A::Output> for A { }
+//[old]~^ ERROR E0119
+//[re]~^^ ERROR E0119
+
+impl Bar for i32 {
+    type Output = i32;
+}
+
+fn main() {}
diff --git a/src/test/ui/coherence/coherence-projection-ok-orphan.rs b/src/test/ui/coherence/coherence-projection-ok-orphan.rs
new file mode 100644
index 0000000..652b438
--- /dev/null
+++ b/src/test/ui/coherence/coherence-projection-ok-orphan.rs
@@ -0,0 +1,22 @@
+// compile-pass
+// skip-codegen
+// revisions: old re
+
+#![cfg_attr(re, feature(re_rebalance_coherence))]
+#![allow(dead_code)]
+// Here we do not get a coherence conflict because `Baz: Iterator`
+// does not hold and (due to the orphan rules), we can rely on that.
+
+pub trait Foo<P> {}
+
+pub trait Bar {
+    type Output: 'static;
+}
+
+struct Baz;
+impl Foo<i32> for Baz { }
+
+impl<A:Iterator> Foo<A::Item> for A { }
+
+
+fn main() {}
diff --git a/src/test/ui/coherence/coherence-projection-ok.rs b/src/test/ui/coherence/coherence-projection-ok.rs
new file mode 100644
index 0000000..f759a9e
--- /dev/null
+++ b/src/test/ui/coherence/coherence-projection-ok.rs
@@ -0,0 +1,21 @@
+// compile-pass
+// skip-codegen
+// revisions: old re
+
+#![cfg_attr(re, feature(re_rebalance_coherence))]
+pub trait Foo<P> {}
+
+pub trait Bar {
+    type Output: 'static;
+}
+
+impl Foo<i32> for i32 { }
+
+impl<A:Bar> Foo<A::Output> for A { }
+
+impl Bar for i32 {
+    type Output = u32;
+}
+
+
+fn main() {}
diff --git a/src/test/ui/coherence/coherence-subtyping.rs b/src/test/ui/coherence/coherence-subtyping.rs
new file mode 100644
index 0000000..e740675
--- /dev/null
+++ b/src/test/ui/coherence/coherence-subtyping.rs
@@ -0,0 +1,22 @@
+// Test that two distinct impls which match subtypes of one another
+// yield coherence errors (or not) depending on the variance.
+//
+// Note: This scenario is currently accepted, but as part of the
+// universe transition (#56105) may eventually become an error.
+
+// revisions: old re
+// compile-pass
+
+#![cfg_attr(re, feature(re_rebalance_coherence))]
+
+trait TheTrait {
+    fn foo(&self) { }
+}
+
+impl TheTrait for for<'a,'b> fn(&'a u8, &'b u8) -> &'a u8 {
+}
+
+impl TheTrait for for<'a> fn(&'a u8, &'a u8) -> &'a u8 {
+}
+
+fn main() { }
diff --git a/src/test/ui/coherence/coherence-tuple-conflict.old.stderr b/src/test/ui/coherence/coherence-tuple-conflict.old.stderr
new file mode 100644
index 0000000..e832bde
--- /dev/null
+++ b/src/test/ui/coherence/coherence-tuple-conflict.old.stderr
@@ -0,0 +1,12 @@
+error[E0119]: conflicting implementations of trait `MyTrait` for type `(_, _)`:
+  --> $DIR/coherence-tuple-conflict.rs:19:1
+   |
+LL | impl<T> MyTrait for (T,T) {
+   | ------------------------- first implementation here
+...
+LL | impl<A,B> MyTrait for (A,B) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(_, _)`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/coherence/coherence-tuple-conflict.re.stderr b/src/test/ui/coherence/coherence-tuple-conflict.re.stderr
new file mode 100644
index 0000000..e832bde
--- /dev/null
+++ b/src/test/ui/coherence/coherence-tuple-conflict.re.stderr
@@ -0,0 +1,12 @@
+error[E0119]: conflicting implementations of trait `MyTrait` for type `(_, _)`:
+  --> $DIR/coherence-tuple-conflict.rs:19:1
+   |
+LL | impl<T> MyTrait for (T,T) {
+   | ------------------------- first implementation here
+...
+LL | impl<A,B> MyTrait for (A,B) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(_, _)`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/coherence/coherence-tuple-conflict.rs b/src/test/ui/coherence/coherence-tuple-conflict.rs
new file mode 100644
index 0000000..130867b
--- /dev/null
+++ b/src/test/ui/coherence/coherence-tuple-conflict.rs
@@ -0,0 +1,25 @@
+// revisions: old re
+
+#![cfg_attr(re, feature(re_rebalance_coherence))]
+
+use std::fmt::Debug;
+use std::default::Default;
+
+// Test that a blank impl for all T conflicts with an impl for some
+// specific T.
+
+trait MyTrait {
+    fn get(&self) -> usize;
+}
+
+impl<T> MyTrait for (T,T) {
+    fn get(&self) -> usize { 0 }
+}
+
+impl<A,B> MyTrait for (A,B) {
+//[old]~^ ERROR E0119
+//[re]~^^ ERROR E0119
+    fn get(&self) -> usize { self.dummy }
+}
+
+fn main() { }
diff --git a/src/test/ui/coherence/coherence-vec-local-2.old.stderr b/src/test/ui/coherence/coherence-vec-local-2.old.stderr
new file mode 100644
index 0000000..1c1118a
--- /dev/null
+++ b/src/test/ui/coherence/coherence-vec-local-2.old.stderr
@@ -0,0 +1,11 @@
+error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
+  --> $DIR/coherence-vec-local-2.rs:14:1
+   |
+LL | impl<T> Remote for Vec<Local<T>> { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type
+   |
+   = note: only traits defined in the current crate can be implemented for a type parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0210`.
diff --git a/src/test/ui/coherence/coherence-vec-local-2.re.stderr b/src/test/ui/coherence/coherence-vec-local-2.re.stderr
new file mode 100644
index 0000000..6992aa7
--- /dev/null
+++ b/src/test/ui/coherence/coherence-vec-local-2.re.stderr
@@ -0,0 +1,12 @@
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/coherence-vec-local-2.rs:14:1
+   |
+LL | impl<T> Remote for Vec<Local<T>> { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0117`.
diff --git a/src/test/ui/coherence/coherence-vec-local-2.rs b/src/test/ui/coherence/coherence-vec-local-2.rs
new file mode 100644
index 0000000..4235439
--- /dev/null
+++ b/src/test/ui/coherence/coherence-vec-local-2.rs
@@ -0,0 +1,18 @@
+// Test that a local, generic type appearing within a
+// *non-fundamental* remote type like `Vec` is not considered local.
+
+// aux-build:coherence_lib.rs
+// revisions: old re
+
+#![cfg_attr(re, feature(re_rebalance_coherence))]
+
+extern crate coherence_lib as lib;
+use lib::Remote;
+
+struct Local<T>(T);
+
+impl<T> Remote for Vec<Local<T>> { }
+//[old]~^ ERROR E0210
+//[re]~^^ ERROR E0117
+
+fn main() { }
diff --git a/src/test/ui/coherence/coherence-vec-local.old.stderr b/src/test/ui/coherence/coherence-vec-local.old.stderr
new file mode 100644
index 0000000..b35e7a8
--- /dev/null
+++ b/src/test/ui/coherence/coherence-vec-local.old.stderr
@@ -0,0 +1,12 @@
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/coherence-vec-local.rs:14:1
+   |
+LL | impl Remote for Vec<Local> { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0117`.
diff --git a/src/test/ui/coherence/coherence-vec-local.re.stderr b/src/test/ui/coherence/coherence-vec-local.re.stderr
new file mode 100644
index 0000000..b35e7a8
--- /dev/null
+++ b/src/test/ui/coherence/coherence-vec-local.re.stderr
@@ -0,0 +1,12 @@
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/coherence-vec-local.rs:14:1
+   |
+LL | impl Remote for Vec<Local> { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0117`.
diff --git a/src/test/ui/coherence/coherence-vec-local.rs b/src/test/ui/coherence/coherence-vec-local.rs
new file mode 100644
index 0000000..351ddd2
--- /dev/null
+++ b/src/test/ui/coherence/coherence-vec-local.rs
@@ -0,0 +1,18 @@
+// Test that a local type (with no type parameters) appearing within a
+// *non-fundamental* remote type like `Vec` is not considered local.
+
+// aux-build:coherence_lib.rs
+// revisions: old re
+
+#![cfg_attr(re, feature(re_rebalance_coherence))]
+
+extern crate coherence_lib as lib;
+use lib::Remote;
+
+struct Local;
+
+impl Remote for Vec<Local> { }
+//[old]~^ ERROR E0117
+//[re]~^^ ERROR E0117
+
+fn main() { }
diff --git a/src/test/ui/coherence/coherence_copy_like_err_fundamental_struct.rs b/src/test/ui/coherence/coherence_copy_like_err_fundamental_struct.rs
new file mode 100644
index 0000000..a030314
--- /dev/null
+++ b/src/test/ui/coherence/coherence_copy_like_err_fundamental_struct.rs
@@ -0,0 +1,27 @@
+// Test that we are able to introduce a negative constraint that
+// `MyType: !MyTrait` along with other "fundamental" wrappers.
+
+// aux-build:coherence_copy_like_lib.rs
+// compile-pass
+// skip-codgen
+// revisions: old re
+
+#![cfg_attr(re, feature(re_rebalance_coherence))]
+#![allow(dead_code)]
+
+extern crate coherence_copy_like_lib as lib;
+
+struct MyType { x: i32 }
+
+trait MyTrait { fn foo() {} }
+impl<T: lib::MyCopy> MyTrait for T { }
+
+// `MyFundamentalStruct` is declared fundamental, so we can test that
+//
+//    MyFundamentalStruct<MyTrait>: !MyTrait
+//
+// Huzzah.
+impl MyTrait for lib::MyFundamentalStruct<MyType> { }
+
+
+fn main() { }
diff --git a/src/test/ui/coherence/coherence_copy_like_err_fundamental_struct_ref.rs b/src/test/ui/coherence/coherence_copy_like_err_fundamental_struct_ref.rs
new file mode 100644
index 0000000..bd8317e
--- /dev/null
+++ b/src/test/ui/coherence/coherence_copy_like_err_fundamental_struct_ref.rs
@@ -0,0 +1,27 @@
+// Test that we are able to introduce a negative constraint that
+// `MyType: !MyTrait` along with other "fundamental" wrappers.
+
+// aux-build:coherence_copy_like_lib.rs
+// compile-pass
+// skip-codegen
+// revisions: old re
+
+#![cfg_attr(re, feature(re_rebalance_coherence))]
+#![allow(dead_code)]
+
+extern crate coherence_copy_like_lib as lib;
+
+struct MyType { x: i32 }
+
+trait MyTrait { fn foo() {} }
+impl<T: lib::MyCopy> MyTrait for T { }
+
+// `MyFundamentalStruct` is declared fundamental, so we can test that
+//
+//    MyFundamentalStruct<&MyTrait>: !MyTrait
+//
+// Huzzah.
+impl<'a> MyTrait for lib::MyFundamentalStruct<&'a MyType> { }
+
+
+fn main() { }
diff --git a/src/test/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.old.stderr b/src/test/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.old.stderr
new file mode 100644
index 0000000..12c7a1f
--- /dev/null
+++ b/src/test/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.old.stderr
@@ -0,0 +1,14 @@
+error[E0119]: conflicting implementations of trait `MyTrait` for type `lib::MyFundamentalStruct<(MyType,)>`:
+  --> $DIR/coherence_copy_like_err_fundamental_struct_tuple.rs:19:1
+   |
+LL | impl<T: lib::MyCopy> MyTrait for T { }
+   | ---------------------------------- first implementation here
+...
+LL | impl MyTrait for lib::MyFundamentalStruct<(MyType,)> { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `lib::MyFundamentalStruct<(MyType,)>`
+   |
+   = note: upstream crates may add new impl of trait `lib::MyCopy` for type `lib::MyFundamentalStruct<(MyType,)>` in future versions
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.re.stderr b/src/test/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.re.stderr
new file mode 100644
index 0000000..12c7a1f
--- /dev/null
+++ b/src/test/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.re.stderr
@@ -0,0 +1,14 @@
+error[E0119]: conflicting implementations of trait `MyTrait` for type `lib::MyFundamentalStruct<(MyType,)>`:
+  --> $DIR/coherence_copy_like_err_fundamental_struct_tuple.rs:19:1
+   |
+LL | impl<T: lib::MyCopy> MyTrait for T { }
+   | ---------------------------------- first implementation here
+...
+LL | impl MyTrait for lib::MyFundamentalStruct<(MyType,)> { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `lib::MyFundamentalStruct<(MyType,)>`
+   |
+   = note: upstream crates may add new impl of trait `lib::MyCopy` for type `lib::MyFundamentalStruct<(MyType,)>` in future versions
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.rs b/src/test/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.rs
new file mode 100644
index 0000000..2a61042
--- /dev/null
+++ b/src/test/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.rs
@@ -0,0 +1,24 @@
+// Test that we are able to introduce a negative constraint that
+// `MyType: !MyTrait` along with other "fundamental" wrappers.
+
+// aux-build:coherence_copy_like_lib.rs
+// revisions: old re
+
+#![cfg_attr(re, feature(re_rebalance_coherence))]
+
+
+extern crate coherence_copy_like_lib as lib;
+
+struct MyType { x: i32 }
+
+trait MyTrait { fn foo() {} }
+
+impl<T: lib::MyCopy> MyTrait for T { }
+
+// Tuples are not fundamental.
+impl MyTrait for lib::MyFundamentalStruct<(MyType,)> { }
+//[old]~^ ERROR E0119
+//[re]~^^ ERROR E0119
+
+
+fn main() { }
diff --git a/src/test/ui/coherence/coherence_copy_like_err_struct.old.stderr b/src/test/ui/coherence/coherence_copy_like_err_struct.old.stderr
new file mode 100644
index 0000000..1b6c62e
--- /dev/null
+++ b/src/test/ui/coherence/coherence_copy_like_err_struct.old.stderr
@@ -0,0 +1,14 @@
+error[E0119]: conflicting implementations of trait `MyTrait` for type `lib::MyStruct<MyType>`:
+  --> $DIR/coherence_copy_like_err_struct.rs:22:1
+   |
+LL | impl<T: lib::MyCopy> MyTrait for T { }
+   | ---------------------------------- first implementation here
+...
+LL | impl MyTrait for lib::MyStruct<MyType> { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `lib::MyStruct<MyType>`
+   |
+   = note: upstream crates may add new impl of trait `lib::MyCopy` for type `lib::MyStruct<MyType>` in future versions
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/coherence/coherence_copy_like_err_struct.re.stderr b/src/test/ui/coherence/coherence_copy_like_err_struct.re.stderr
new file mode 100644
index 0000000..1b6c62e
--- /dev/null
+++ b/src/test/ui/coherence/coherence_copy_like_err_struct.re.stderr
@@ -0,0 +1,14 @@
+error[E0119]: conflicting implementations of trait `MyTrait` for type `lib::MyStruct<MyType>`:
+  --> $DIR/coherence_copy_like_err_struct.rs:22:1
+   |
+LL | impl<T: lib::MyCopy> MyTrait for T { }
+   | ---------------------------------- first implementation here
+...
+LL | impl MyTrait for lib::MyStruct<MyType> { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `lib::MyStruct<MyType>`
+   |
+   = note: upstream crates may add new impl of trait `lib::MyCopy` for type `lib::MyStruct<MyType>` in future versions
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/coherence/coherence_copy_like_err_struct.rs b/src/test/ui/coherence/coherence_copy_like_err_struct.rs
new file mode 100644
index 0000000..38fc2e6
--- /dev/null
+++ b/src/test/ui/coherence/coherence_copy_like_err_struct.rs
@@ -0,0 +1,26 @@
+// aux-build:coherence_copy_like_lib.rs
+// revisions: old re
+
+#![cfg_attr(re, feature(re_rebalance_coherence))]
+
+// Test that we are able to introduce a negative constraint that
+// `MyType: !MyTrait` along with other "fundamental" wrappers.
+
+extern crate coherence_copy_like_lib as lib;
+
+struct MyType { x: i32 }
+
+trait MyTrait { fn foo() {} }
+impl<T: lib::MyCopy> MyTrait for T { }
+
+// `MyStruct` is not declared fundamental, therefore this would
+// require that
+//
+//     MyStruct<MyType>: !MyTrait
+//
+// which we cannot approve.
+impl MyTrait for lib::MyStruct<MyType> { }
+//[old]~^ ERROR E0119
+//[re]~^^ ERROR E0119
+
+fn main() { }
diff --git a/src/test/ui/coherence/coherence_copy_like_err_tuple.old.stderr b/src/test/ui/coherence/coherence_copy_like_err_tuple.old.stderr
new file mode 100644
index 0000000..11bd788
--- /dev/null
+++ b/src/test/ui/coherence/coherence_copy_like_err_tuple.old.stderr
@@ -0,0 +1,14 @@
+error[E0119]: conflicting implementations of trait `MyTrait` for type `(MyType,)`:
+  --> $DIR/coherence_copy_like_err_tuple.rs:21:1
+   |
+LL | impl<T: lib::MyCopy> MyTrait for T { }
+   | ---------------------------------- first implementation here
+...
+LL | impl MyTrait for (MyType,) { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(MyType,)`
+   |
+   = note: upstream crates may add new impl of trait `lib::MyCopy` for type `(MyType,)` in future versions
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/coherence/coherence_copy_like_err_tuple.re.stderr b/src/test/ui/coherence/coherence_copy_like_err_tuple.re.stderr
new file mode 100644
index 0000000..11bd788
--- /dev/null
+++ b/src/test/ui/coherence/coherence_copy_like_err_tuple.re.stderr
@@ -0,0 +1,14 @@
+error[E0119]: conflicting implementations of trait `MyTrait` for type `(MyType,)`:
+  --> $DIR/coherence_copy_like_err_tuple.rs:21:1
+   |
+LL | impl<T: lib::MyCopy> MyTrait for T { }
+   | ---------------------------------- first implementation here
+...
+LL | impl MyTrait for (MyType,) { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(MyType,)`
+   |
+   = note: upstream crates may add new impl of trait `lib::MyCopy` for type `(MyType,)` in future versions
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/coherence/coherence_copy_like_err_tuple.rs b/src/test/ui/coherence/coherence_copy_like_err_tuple.rs
new file mode 100644
index 0000000..7234bed
--- /dev/null
+++ b/src/test/ui/coherence/coherence_copy_like_err_tuple.rs
@@ -0,0 +1,25 @@
+// Test that we are able to introduce a negative constraint that
+// `MyType: !MyTrait` along with other "fundamental" wrappers.
+
+// aux-build:coherence_copy_like_lib.rs
+// revisions: old re
+
+#![cfg_attr(re, feature(re_rebalance_coherence))]
+
+extern crate coherence_copy_like_lib as lib;
+
+struct MyType { x: i32 }
+
+trait MyTrait { fn foo() {} }
+impl<T: lib::MyCopy> MyTrait for T { }
+
+// Tuples are not fundamental, therefore this would require that
+//
+//     (MyType,): !MyTrait
+//
+// which we cannot approve.
+impl MyTrait for (MyType,) { }
+//[old]~^ ERROR E0119
+//[re]~^^ ERROR E0119
+
+fn main() { }
diff --git a/src/test/ui/coherence/coherence_inherent.old.stderr b/src/test/ui/coherence/coherence_inherent.old.stderr
new file mode 100644
index 0000000..fa56445
--- /dev/null
+++ b/src/test/ui/coherence/coherence_inherent.old.stderr
@@ -0,0 +1,13 @@
+error[E0599]: no method named `the_fn` found for type `&Lib::TheStruct` in the current scope
+  --> $DIR/coherence_inherent.rs:35:11
+   |
+LL |         s.the_fn();
+   |           ^^^^^^
+   |
+   = help: items from traits can only be used if the trait is in scope
+   = note: the following trait is implemented but not in scope, perhaps add a `use` for it:
+           `use Lib::TheTrait;`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/coherence/coherence_inherent.re.stderr b/src/test/ui/coherence/coherence_inherent.re.stderr
new file mode 100644
index 0000000..fa56445
--- /dev/null
+++ b/src/test/ui/coherence/coherence_inherent.re.stderr
@@ -0,0 +1,13 @@
+error[E0599]: no method named `the_fn` found for type `&Lib::TheStruct` in the current scope
+  --> $DIR/coherence_inherent.rs:35:11
+   |
+LL |         s.the_fn();
+   |           ^^^^^^
+   |
+   = help: items from traits can only be used if the trait is in scope
+   = note: the following trait is implemented but not in scope, perhaps add a `use` for it:
+           `use Lib::TheTrait;`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/coherence/coherence_inherent.rs b/src/test/ui/coherence/coherence_inherent.rs
new file mode 100644
index 0000000..f0d3682
--- /dev/null
+++ b/src/test/ui/coherence/coherence_inherent.rs
@@ -0,0 +1,41 @@
+// Tests that methods that implement a trait cannot be invoked
+// unless the trait is imported.
+
+// revisions: old re
+
+#![cfg_attr(re, feature(re_rebalance_coherence))]
+
+mod Lib {
+    pub trait TheTrait {
+        fn the_fn(&self);
+    }
+
+    pub struct TheStruct;
+
+    impl TheTrait for TheStruct {
+        fn the_fn(&self) {}
+    }
+}
+
+mod Import {
+    // Trait is in scope here:
+    use Lib::TheStruct;
+    use Lib::TheTrait;
+
+    fn call_the_fn(s: &TheStruct) {
+        s.the_fn();
+    }
+}
+
+mod NoImport {
+    // Trait is not in scope here:
+    use Lib::TheStruct;
+
+    fn call_the_fn(s: &TheStruct) {
+        s.the_fn();
+        //[old]~^ ERROR no method named `the_fn` found
+        //[re]~^^ ERROR E0599
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/coherence/coherence_inherent_cc.old.stderr b/src/test/ui/coherence/coherence_inherent_cc.old.stderr
new file mode 100644
index 0000000..4d93e69
--- /dev/null
+++ b/src/test/ui/coherence/coherence_inherent_cc.old.stderr
@@ -0,0 +1,13 @@
+error[E0599]: no method named `the_fn` found for type `&coherence_inherent_cc_lib::TheStruct` in the current scope
+  --> $DIR/coherence_inherent_cc.rs:26:11
+   |
+LL |         s.the_fn();
+   |           ^^^^^^
+   |
+   = help: items from traits can only be used if the trait is in scope
+   = note: the following trait is implemented but not in scope, perhaps add a `use` for it:
+           `use coherence_inherent_cc_lib::TheTrait;`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/coherence/coherence_inherent_cc.re.stderr b/src/test/ui/coherence/coherence_inherent_cc.re.stderr
new file mode 100644
index 0000000..4d93e69
--- /dev/null
+++ b/src/test/ui/coherence/coherence_inherent_cc.re.stderr
@@ -0,0 +1,13 @@
+error[E0599]: no method named `the_fn` found for type `&coherence_inherent_cc_lib::TheStruct` in the current scope
+  --> $DIR/coherence_inherent_cc.rs:26:11
+   |
+LL |         s.the_fn();
+   |           ^^^^^^
+   |
+   = help: items from traits can only be used if the trait is in scope
+   = note: the following trait is implemented but not in scope, perhaps add a `use` for it:
+           `use coherence_inherent_cc_lib::TheTrait;`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/coherence/coherence_inherent_cc.rs b/src/test/ui/coherence/coherence_inherent_cc.rs
new file mode 100644
index 0000000..2c980d8
--- /dev/null
+++ b/src/test/ui/coherence/coherence_inherent_cc.rs
@@ -0,0 +1,32 @@
+// aux-build:coherence_inherent_cc_lib.rs
+// revisions: old re
+
+#![cfg_attr(re, feature(re_rebalance_coherence))]
+
+// Tests that methods that implement a trait cannot be invoked
+// unless the trait is imported.
+
+extern crate coherence_inherent_cc_lib;
+
+mod Import {
+    // Trait is in scope here:
+    use coherence_inherent_cc_lib::TheStruct;
+    use coherence_inherent_cc_lib::TheTrait;
+
+    fn call_the_fn(s: &TheStruct) {
+        s.the_fn();
+    }
+}
+
+mod NoImport {
+    // Trait is not in scope here:
+    use coherence_inherent_cc_lib::TheStruct;
+
+    fn call_the_fn(s: &TheStruct) {
+        s.the_fn();
+        //[old]~^ ERROR no method named `the_fn` found
+        //[re]~^^ ERROR E0599
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/coherence/coherence_local.rs b/src/test/ui/coherence/coherence_local.rs
new file mode 100644
index 0000000..cac45b0
--- /dev/null
+++ b/src/test/ui/coherence/coherence_local.rs
@@ -0,0 +1,26 @@
+// Test that we are able to introduce a negative constraint that
+// `MyType: !MyTrait` along with other "fundamental" wrappers.
+
+// aux-build:coherence_copy_like_lib.rs
+// compile-pass
+// skip-codegen
+// revisions: old re
+
+#![cfg_attr(re, feature(re_rebalance_coherence))]
+#![allow(dead_code)]
+
+extern crate coherence_copy_like_lib as lib;
+
+struct MyType { x: i32 }
+
+// These are all legal because they are all fundamental types:
+
+impl lib::MyCopy for MyType { }
+impl<'a> lib::MyCopy for &'a MyType { }
+impl<'a> lib::MyCopy for &'a Box<MyType> { }
+impl lib::MyCopy for Box<MyType> { }
+impl lib::MyCopy for lib::MyFundamentalStruct<MyType> { }
+impl lib::MyCopy for lib::MyFundamentalStruct<Box<MyType>> { }
+
+
+fn main() { }
diff --git a/src/test/ui/coherence/coherence_local_err_struct.old.stderr b/src/test/ui/coherence/coherence_local_err_struct.old.stderr
new file mode 100644
index 0000000..e1f6514
--- /dev/null
+++ b/src/test/ui/coherence/coherence_local_err_struct.old.stderr
@@ -0,0 +1,12 @@
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/coherence_local_err_struct.rs:17:1
+   |
+LL | impl lib::MyCopy for lib::MyStruct<MyType> { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0117`.
diff --git a/src/test/ui/coherence/coherence_local_err_struct.re.stderr b/src/test/ui/coherence/coherence_local_err_struct.re.stderr
new file mode 100644
index 0000000..e1f6514
--- /dev/null
+++ b/src/test/ui/coherence/coherence_local_err_struct.re.stderr
@@ -0,0 +1,12 @@
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/coherence_local_err_struct.rs:17:1
+   |
+LL | impl lib::MyCopy for lib::MyStruct<MyType> { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0117`.
diff --git a/src/test/ui/coherence/coherence_local_err_struct.rs b/src/test/ui/coherence/coherence_local_err_struct.rs
new file mode 100644
index 0000000..d6faaf2
--- /dev/null
+++ b/src/test/ui/coherence/coherence_local_err_struct.rs
@@ -0,0 +1,22 @@
+// Test that we are able to introduce a negative constraint that
+// `MyType: !MyTrait` along with other "fundamental" wrappers.
+
+// aux-build:coherence_copy_like_lib.rs
+// revisions: old re
+
+#![cfg_attr(re, feature(re_rebalance_coherence))]
+#![allow(dead_code)]
+
+extern crate coherence_copy_like_lib as lib;
+
+struct MyType { x: i32 }
+
+// These are all legal because they are all fundamental types:
+
+// MyStruct is not fundamental.
+impl lib::MyCopy for lib::MyStruct<MyType> { }
+//[old]~^ ERROR E0117
+//[re]~^^ ERROR E0117
+
+
+fn main() { }
diff --git a/src/test/ui/coherence/coherence_local_err_tuple.old.stderr b/src/test/ui/coherence/coherence_local_err_tuple.old.stderr
new file mode 100644
index 0000000..171daa5
--- /dev/null
+++ b/src/test/ui/coherence/coherence_local_err_tuple.old.stderr
@@ -0,0 +1,12 @@
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/coherence_local_err_tuple.rs:17:1
+   |
+LL | impl lib::MyCopy for (MyType,) { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0117`.
diff --git a/src/test/ui/coherence/coherence_local_err_tuple.re.stderr b/src/test/ui/coherence/coherence_local_err_tuple.re.stderr
new file mode 100644
index 0000000..171daa5
--- /dev/null
+++ b/src/test/ui/coherence/coherence_local_err_tuple.re.stderr
@@ -0,0 +1,12 @@
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/coherence_local_err_tuple.rs:17:1
+   |
+LL | impl lib::MyCopy for (MyType,) { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0117`.
diff --git a/src/test/ui/coherence/coherence_local_err_tuple.rs b/src/test/ui/coherence/coherence_local_err_tuple.rs
new file mode 100644
index 0000000..2685b2d
--- /dev/null
+++ b/src/test/ui/coherence/coherence_local_err_tuple.rs
@@ -0,0 +1,22 @@
+// Test that we are able to introduce a negative constraint that
+// `MyType: !MyTrait` along with other "fundamental" wrappers.
+
+// aux-build:coherence_copy_like_lib.rs
+// revisions: old re
+
+#![cfg_attr(re, feature(re_rebalance_coherence))]
+#![allow(dead_code)]
+
+extern crate coherence_copy_like_lib as lib;
+
+struct MyType { x: i32 }
+
+// These are all legal because they are all fundamental types:
+
+// Tuples are not fundamental, so this is not a local impl.
+impl lib::MyCopy for (MyType,) { }
+//[old]~^ ERROR E0117
+//[re]~^^ ERROR E0117
+
+
+fn main() { }
diff --git a/src/test/ui/coherence/coherence_local_ref.rs b/src/test/ui/coherence/coherence_local_ref.rs
new file mode 100644
index 0000000..a52510b
--- /dev/null
+++ b/src/test/ui/coherence/coherence_local_ref.rs
@@ -0,0 +1,20 @@
+// Test that we are able to introduce a negative constraint that
+// `MyType: !MyTrait` along with other "fundamental" wrappers.
+
+// aux-build:coherence_copy_like_lib.rs
+// compile-pass
+// skip-codegen
+// revisions: old re
+
+#![cfg_attr(re, feature(re_rebalance_coherence))]
+#![allow(dead_code)]
+
+extern crate coherence_copy_like_lib as lib;
+
+struct MyType { x: i32 }
+
+// naturally, legal
+impl lib::MyCopy for MyType { }
+
+
+fn main() { }
diff --git a/src/test/ui/coherence/re-rebalance-coherence.rs b/src/test/ui/coherence/re-rebalance-coherence.rs
new file mode 100644
index 0000000..33ad4e9
--- /dev/null
+++ b/src/test/ui/coherence/re-rebalance-coherence.rs
@@ -0,0 +1,13 @@
+#![feature(re_rebalance_coherence)]
+
+// run-pass
+// aux-build:re_rebalance_coherence_lib.rs
+
+extern crate re_rebalance_coherence_lib as lib;
+use lib::*;
+
+struct Oracle;
+impl Backend for Oracle {}
+impl<'a, T:'a, Tab> QueryFragment<Oracle> for BatchInsert<'a, T, Tab> {}
+
+fn main() {}
diff --git a/src/test/ui/command-line-diagnostics.nll.stderr b/src/test/ui/command-line-diagnostics.nll.stderr
new file mode 100644
index 0000000..b3f8d8a
--- /dev/null
+++ b/src/test/ui/command-line-diagnostics.nll.stderr
@@ -0,0 +1,14 @@
+error[E0384]: cannot assign twice to immutable variable `x`
+  --> $DIR/command-line-diagnostics.rs:6:5
+   |
+LL |     let x = 42;
+   |         -
+   |         |
+   |         first assignment to `x`
+   |         help: make this binding mutable: `mut x`
+LL |     x = 43;
+   |     ^^^^^^ cannot assign twice to immutable variable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0384`.
diff --git a/src/test/ui/command-line-diagnostics.rs b/src/test/ui/command-line-diagnostics.rs
new file mode 100644
index 0000000..248fb83
--- /dev/null
+++ b/src/test/ui/command-line-diagnostics.rs
@@ -0,0 +1,7 @@
+// This test checks the output format without the intermediate json representation
+// compile-flags: --error-format=human
+
+pub fn main() {
+    let x = 42;
+    x = 43;
+}
diff --git a/src/test/ui/command-line-diagnostics.stderr b/src/test/ui/command-line-diagnostics.stderr
new file mode 100644
index 0000000..6f1156e
--- /dev/null
+++ b/src/test/ui/command-line-diagnostics.stderr
@@ -0,0 +1,11 @@
+error[E0384]: cannot assign twice to immutable variable `x`
+  --> $DIR/command-line-diagnostics.rs:6:5
+   |
+LL |     let x = 42;
+   |         - first assignment to `x`
+LL |     x = 43;
+   |     ^^^^^^ cannot assign twice to immutable variable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0384`.
diff --git a/src/test/ui/compare-method/proj-outlives-region.rs b/src/test/ui/compare-method/proj-outlives-region.rs
new file mode 100644
index 0000000..969bc56
--- /dev/null
+++ b/src/test/ui/compare-method/proj-outlives-region.rs
@@ -0,0 +1,14 @@
+// Test that we elaborate `Type: 'region` constraints and infer various important things.
+
+trait Master<'a, T: ?Sized, U> {
+    fn foo() where T: 'a;
+}
+
+// `U::Item: 'a` does not imply that `U: 'a`
+impl<'a, U: Iterator> Master<'a, U::Item, U> for () {
+    fn foo() where U: 'a { } //~ ERROR E0276
+}
+
+fn main() {
+    println!("Hello, world!");
+}
diff --git a/src/test/ui/compare-method/proj-outlives-region.stderr b/src/test/ui/compare-method/proj-outlives-region.stderr
new file mode 100644
index 0000000..e5f5c5e
--- /dev/null
+++ b/src/test/ui/compare-method/proj-outlives-region.stderr
@@ -0,0 +1,12 @@
+error[E0276]: impl has stricter requirements than trait
+  --> $DIR/proj-outlives-region.rs:9:5
+   |
+LL |     fn foo() where T: 'a;
+   |     --------------------- definition of `foo` from trait
+...
+LL |     fn foo() where U: 'a { }
+   |     ^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `U: 'a`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0276`.
diff --git a/src/test/ui/compare-method/region-extra-2.rs b/src/test/ui/compare-method/region-extra-2.rs
new file mode 100644
index 0000000..3d57b54
--- /dev/null
+++ b/src/test/ui/compare-method/region-extra-2.rs
@@ -0,0 +1,15 @@
+// Regression test for issue #22779. An extra where clause was
+// permitted on the impl that is not present on the trait.
+
+trait Tr<'a, T> {
+    fn renew<'b: 'a>(self) -> &'b mut [T];
+}
+
+impl<'a, T> Tr<'a, T> for &'a mut [T] {
+    fn renew<'b: 'a>(self) -> &'b mut [T] where 'a: 'b {
+        //~^ ERROR E0276
+        &mut self[..]
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/compare-method/region-extra-2.stderr b/src/test/ui/compare-method/region-extra-2.stderr
new file mode 100644
index 0000000..420d99c
--- /dev/null
+++ b/src/test/ui/compare-method/region-extra-2.stderr
@@ -0,0 +1,12 @@
+error[E0276]: impl has stricter requirements than trait
+  --> $DIR/region-extra-2.rs:9:5
+   |
+LL |     fn renew<'b: 'a>(self) -> &'b mut [T];
+   |     -------------------------------------- definition of `renew` from trait
+...
+LL |     fn renew<'b: 'a>(self) -> &'b mut [T] where 'a: 'b {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `'a: 'b`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0276`.
diff --git a/src/test/ui/compare-method/region-extra.rs b/src/test/ui/compare-method/region-extra.rs
new file mode 100644
index 0000000..1070cb8
--- /dev/null
+++ b/src/test/ui/compare-method/region-extra.rs
@@ -0,0 +1,14 @@
+// Test that you cannot add an extra where clause in the impl relating
+// two regions.
+
+trait Master<'a, 'b> {
+    fn foo();
+}
+
+impl<'a, 'b> Master<'a, 'b> for () {
+    fn foo() where 'a: 'b { } //~ ERROR impl has stricter
+}
+
+fn main() {
+    println!("Hello, world!");
+}
diff --git a/src/test/ui/compare-method/region-extra.stderr b/src/test/ui/compare-method/region-extra.stderr
new file mode 100644
index 0000000..5a584c7
--- /dev/null
+++ b/src/test/ui/compare-method/region-extra.stderr
@@ -0,0 +1,12 @@
+error[E0276]: impl has stricter requirements than trait
+  --> $DIR/region-extra.rs:9:5
+   |
+LL |     fn foo();
+   |     --------- definition of `foo` from trait
+...
+LL |     fn foo() where 'a: 'b { }
+   |     ^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `'a: 'b`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0276`.
diff --git a/src/test/ui/compare-method/region-unrelated.rs b/src/test/ui/compare-method/region-unrelated.rs
new file mode 100644
index 0000000..9730c9d
--- /dev/null
+++ b/src/test/ui/compare-method/region-unrelated.rs
@@ -0,0 +1,15 @@
+// Test that we elaborate `Type: 'region` constraints and infer various important things.
+
+trait Master<'a, T: ?Sized, U> {
+    fn foo() where T: 'a;
+}
+
+// `U: 'a` does not imply `V: 'a`
+impl<'a, U, V> Master<'a, U, V> for () {
+    fn foo() where V: 'a { }
+    //~^ ERROR impl has stricter requirements than trait
+}
+
+fn main() {
+    println!("Hello, world!");
+}
diff --git a/src/test/ui/compare-method/region-unrelated.stderr b/src/test/ui/compare-method/region-unrelated.stderr
new file mode 100644
index 0000000..fd3576d
--- /dev/null
+++ b/src/test/ui/compare-method/region-unrelated.stderr
@@ -0,0 +1,12 @@
+error[E0276]: impl has stricter requirements than trait
+  --> $DIR/region-unrelated.rs:9:5
+   |
+LL |     fn foo() where T: 'a;
+   |     --------------------- definition of `foo` from trait
+...
+LL |     fn foo() where V: 'a { }
+   |     ^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `V: 'a`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0276`.
diff --git a/src/test/ui/compare-method/reordered-type-param.rs b/src/test/ui/compare-method/reordered-type-param.rs
new file mode 100644
index 0000000..a858b66
--- /dev/null
+++ b/src/test/ui/compare-method/reordered-type-param.rs
@@ -0,0 +1,19 @@
+// Tests that ty params get matched correctly when comparing
+// an impl against a trait
+//
+// cc #26111
+
+trait A {
+  fn b<C:Clone,D>(&self, x: C) -> C;
+}
+
+struct E {
+ f: isize
+}
+
+impl A for E {
+  // n.b. The error message is awful -- see #3404
+  fn b<F:Clone,G>(&self, _x: G) -> G { panic!() } //~ ERROR method `b` has an incompatible type
+}
+
+fn main() {}
diff --git a/src/test/ui/compare-method/reordered-type-param.stderr b/src/test/ui/compare-method/reordered-type-param.stderr
new file mode 100644
index 0000000..a33908c
--- /dev/null
+++ b/src/test/ui/compare-method/reordered-type-param.stderr
@@ -0,0 +1,15 @@
+error[E0053]: method `b` has an incompatible type for trait
+  --> $DIR/reordered-type-param.rs:16:30
+   |
+LL |   fn b<C:Clone,D>(&self, x: C) -> C;
+   |                             - type in trait
+...
+LL |   fn b<F:Clone,G>(&self, _x: G) -> G { panic!() }
+   |                              ^ expected type parameter, found a different type parameter
+   |
+   = note: expected type `fn(&E, F) -> F`
+              found type `fn(&E, G) -> G`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0053`.
diff --git a/src/test/ui/compare-method/trait-bound-on-type-parameter.rs b/src/test/ui/compare-method/trait-bound-on-type-parameter.rs
new file mode 100644
index 0000000..5359001
--- /dev/null
+++ b/src/test/ui/compare-method/trait-bound-on-type-parameter.rs
@@ -0,0 +1,18 @@
+// Tests that impl can't add extra `F: Sync` bound aren't *more* restrictive
+// than the trait method it's implementing.
+//
+// Regr test for #26111.
+
+trait A {
+  fn b<C,D>(&self, x: C) -> C;
+}
+
+struct E {
+ f: isize
+}
+
+impl A for E {
+    fn b<F: Sync, G>(&self, _x: F) -> F { panic!() } //~ ERROR E0276
+}
+
+fn main() {}
diff --git a/src/test/ui/compare-method/trait-bound-on-type-parameter.stderr b/src/test/ui/compare-method/trait-bound-on-type-parameter.stderr
new file mode 100644
index 0000000..5d09038
--- /dev/null
+++ b/src/test/ui/compare-method/trait-bound-on-type-parameter.stderr
@@ -0,0 +1,12 @@
+error[E0276]: impl has stricter requirements than trait
+  --> $DIR/trait-bound-on-type-parameter.rs:15:5
+   |
+LL |   fn b<C,D>(&self, x: C) -> C;
+   |   ---------------------------- definition of `b` from trait
+...
+LL |     fn b<F: Sync, G>(&self, _x: F) -> F { panic!() }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `F: std::marker::Sync`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0276`.
diff --git a/src/test/ui/compare-method/traits-misc-mismatch-1.rs b/src/test/ui/compare-method/traits-misc-mismatch-1.rs
new file mode 100644
index 0000000..0da4aba
--- /dev/null
+++ b/src/test/ui/compare-method/traits-misc-mismatch-1.rs
@@ -0,0 +1,71 @@
+//
+// Make sure rustc checks the type parameter bounds in implementations of traits,
+// see #2687
+
+use std::marker;
+
+trait A { }
+
+trait B: A {}
+
+trait C: A {}
+
+trait Foo {
+    fn test_error1_fn<T: Eq>(&self);
+    fn test_error2_fn<T: Eq + Ord>(&self);
+    fn test_error3_fn<T: Eq + Ord>(&self);
+    fn test3_fn<T: Eq + Ord>(&self);
+    fn test4_fn<T: Eq + Ord>(&self);
+    fn test_error5_fn<T: A>(&self);
+    fn test6_fn<T: A + Eq>(&self);
+    fn test_error7_fn<T: A>(&self);
+    fn test_error8_fn<T: B>(&self);
+}
+
+impl Foo for isize {
+    // invalid bound for T, was defined as Eq in trait
+    fn test_error1_fn<T: Ord>(&self) {}
+    //~^ ERROR E0276
+
+    // invalid bound for T, was defined as Eq + Ord in trait
+    fn test_error2_fn<T: Eq + B>(&self) {}
+    //~^ ERROR E0276
+
+    // invalid bound for T, was defined as Eq + Ord in trait
+    fn test_error3_fn<T: B + Eq>(&self) {}
+    //~^ ERROR E0276
+
+    // multiple bounds, same order as in trait
+    fn test3_fn<T: Ord + Eq>(&self) {}
+
+    // multiple bounds, different order as in trait
+    fn test4_fn<T: Eq + Ord>(&self) {}
+
+    // parameters in impls must be equal or more general than in the defining trait
+    fn test_error5_fn<T: B>(&self) {}
+    //~^ ERROR E0276
+
+    // bound `std::cmp::Eq` not enforced by this implementation, but this is OK
+    fn test6_fn<T: A>(&self) {}
+
+    fn test_error7_fn<T: A + Eq>(&self) {}
+    //~^ ERROR E0276
+
+    fn test_error8_fn<T: C>(&self) {}
+    //~^ ERROR E0276
+}
+
+trait Getter<T> {
+    fn get(&self) -> T { loop { } }
+}
+
+trait Trait {
+    fn method<G:Getter<isize>>(&self);
+}
+
+impl Trait for usize {
+    fn method<G: Getter<usize>>(&self) {}
+    //~^ ERROR E0276
+}
+
+fn main() {}
diff --git a/src/test/ui/compare-method/traits-misc-mismatch-1.stderr b/src/test/ui/compare-method/traits-misc-mismatch-1.stderr
new file mode 100644
index 0000000..717c0d2
--- /dev/null
+++ b/src/test/ui/compare-method/traits-misc-mismatch-1.stderr
@@ -0,0 +1,66 @@
+error[E0276]: impl has stricter requirements than trait
+  --> $DIR/traits-misc-mismatch-1.rs:27:5
+   |
+LL |     fn test_error1_fn<T: Eq>(&self);
+   |     -------------------------------- definition of `test_error1_fn` from trait
+...
+LL |     fn test_error1_fn<T: Ord>(&self) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `T: std::cmp::Ord`
+
+error[E0276]: impl has stricter requirements than trait
+  --> $DIR/traits-misc-mismatch-1.rs:31:5
+   |
+LL |     fn test_error2_fn<T: Eq + Ord>(&self);
+   |     -------------------------------------- definition of `test_error2_fn` from trait
+...
+LL |     fn test_error2_fn<T: Eq + B>(&self) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `T: B`
+
+error[E0276]: impl has stricter requirements than trait
+  --> $DIR/traits-misc-mismatch-1.rs:35:5
+   |
+LL |     fn test_error3_fn<T: Eq + Ord>(&self);
+   |     -------------------------------------- definition of `test_error3_fn` from trait
+...
+LL |     fn test_error3_fn<T: B + Eq>(&self) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `T: B`
+
+error[E0276]: impl has stricter requirements than trait
+  --> $DIR/traits-misc-mismatch-1.rs:45:5
+   |
+LL |     fn test_error5_fn<T: A>(&self);
+   |     ------------------------------- definition of `test_error5_fn` from trait
+...
+LL |     fn test_error5_fn<T: B>(&self) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `T: B`
+
+error[E0276]: impl has stricter requirements than trait
+  --> $DIR/traits-misc-mismatch-1.rs:51:5
+   |
+LL |     fn test_error7_fn<T: A>(&self);
+   |     ------------------------------- definition of `test_error7_fn` from trait
+...
+LL |     fn test_error7_fn<T: A + Eq>(&self) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `T: std::cmp::Eq`
+
+error[E0276]: impl has stricter requirements than trait
+  --> $DIR/traits-misc-mismatch-1.rs:54:5
+   |
+LL |     fn test_error8_fn<T: B>(&self);
+   |     ------------------------------- definition of `test_error8_fn` from trait
+...
+LL |     fn test_error8_fn<T: C>(&self) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `T: C`
+
+error[E0276]: impl has stricter requirements than trait
+  --> $DIR/traits-misc-mismatch-1.rs:67:5
+   |
+LL |     fn method<G:Getter<isize>>(&self);
+   |     ---------------------------------- definition of `method` from trait
+...
+LL |     fn method<G: Getter<usize>>(&self) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `G: Getter<usize>`
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0276`.
diff --git a/src/test/ui/compare-method/traits-misc-mismatch-2.rs b/src/test/ui/compare-method/traits-misc-mismatch-2.rs
new file mode 100644
index 0000000..d7f31c1
--- /dev/null
+++ b/src/test/ui/compare-method/traits-misc-mismatch-2.rs
@@ -0,0 +1,23 @@
+// Issue #5886: a complex instance of issue #2687.
+
+trait Iterator<A> {
+    fn next(&mut self) -> Option<A>;
+}
+
+trait IteratorUtil<A>: Sized
+{
+    fn zip<B, U: Iterator<U>>(self, other: U) -> ZipIterator<Self, U>;
+}
+
+impl<A, T: Iterator<A>> IteratorUtil<A> for T {
+    fn zip<B, U: Iterator<B>>(self, other: U) -> ZipIterator<T, U> {
+    //~^ ERROR E0276
+        ZipIterator{a: self, b: other}
+    }
+}
+
+struct ZipIterator<T, U> {
+    a: T, b: U
+}
+
+fn main() {}
diff --git a/src/test/ui/compare-method/traits-misc-mismatch-2.stderr b/src/test/ui/compare-method/traits-misc-mismatch-2.stderr
new file mode 100644
index 0000000..acf94ad
--- /dev/null
+++ b/src/test/ui/compare-method/traits-misc-mismatch-2.stderr
@@ -0,0 +1,12 @@
+error[E0276]: impl has stricter requirements than trait
+  --> $DIR/traits-misc-mismatch-2.rs:13:5
+   |
+LL |     fn zip<B, U: Iterator<U>>(self, other: U) -> ZipIterator<Self, U>;
+   |     ------------------------------------------------------------------ definition of `zip` from trait
+...
+LL |     fn zip<B, U: Iterator<B>>(self, other: U) -> ZipIterator<T, U> {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `U: Iterator<B>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0276`.
diff --git a/src/test/ui/compile_error_macro.rs b/src/test/ui/compile_error_macro.rs
new file mode 100644
index 0000000..3f7b57c
--- /dev/null
+++ b/src/test/ui/compile_error_macro.rs
@@ -0,0 +1,3 @@
+fn main() {
+    compile_error!("a very descriptive error message"); //~ ERROR: a very descriptive error message
+}
diff --git a/src/test/ui/compile_error_macro.stderr b/src/test/ui/compile_error_macro.stderr
new file mode 100644
index 0000000..8aa1878
--- /dev/null
+++ b/src/test/ui/compile_error_macro.stderr
@@ -0,0 +1,8 @@
+error: a very descriptive error message
+  --> $DIR/compile_error_macro.rs:2:5
+   |
+LL |     compile_error!("a very descriptive error message");
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/concat.rs b/src/test/ui/concat.rs
new file mode 100644
index 0000000..d7ab7d6
--- /dev/null
+++ b/src/test/ui/concat.rs
@@ -0,0 +1,6 @@
+fn main() {
+    concat!(b'f');  //~ ERROR: cannot concatenate a byte string literal
+    concat!(b"foo");  //~ ERROR: cannot concatenate a byte string literal
+    concat!(foo);   //~ ERROR: expected a literal
+    concat!(foo()); //~ ERROR: expected a literal
+}
diff --git a/src/test/ui/concat.stderr b/src/test/ui/concat.stderr
new file mode 100644
index 0000000..61fb9de
--- /dev/null
+++ b/src/test/ui/concat.stderr
@@ -0,0 +1,30 @@
+error: cannot concatenate a byte string literal
+  --> $DIR/concat.rs:2:13
+   |
+LL |     concat!(b'f');
+   |             ^^^^
+
+error: cannot concatenate a byte string literal
+  --> $DIR/concat.rs:3:13
+   |
+LL |     concat!(b"foo");
+   |             ^^^^^^
+
+error: expected a literal
+  --> $DIR/concat.rs:4:13
+   |
+LL |     concat!(foo);
+   |             ^^^
+   |
+   = note: only literals (like `"foo"`, `42` and `3.14`) can be passed to `concat!()`
+
+error: expected a literal
+  --> $DIR/concat.rs:5:13
+   |
+LL |     concat!(foo());
+   |             ^^^^^
+   |
+   = note: only literals (like `"foo"`, `42` and `3.14`) can be passed to `concat!()`
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/conditional-compilation/auxiliary/namespaced_enums.rs b/src/test/ui/conditional-compilation/auxiliary/namespaced_enums.rs
new file mode 100644
index 0000000..d3548c7
--- /dev/null
+++ b/src/test/ui/conditional-compilation/auxiliary/namespaced_enums.rs
@@ -0,0 +1,10 @@
+pub enum Foo {
+    A,
+    B(isize),
+    C { a: isize },
+}
+
+impl Foo {
+    pub fn foo() {}
+    pub fn bar(&self) {}
+}
diff --git a/src/test/ui/conditional-compilation/cfg-arg-invalid-1.rs b/src/test/ui/conditional-compilation/cfg-arg-invalid-1.rs
new file mode 100644
index 0000000..36dd78d
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg-arg-invalid-1.rs
@@ -0,0 +1,3 @@
+// compile-flags: --cfg a(b=c)
+// error-pattern: invalid `--cfg` argument: `a(b=c)` (expected `key` or `key="value"`)
+fn main() {}
diff --git a/src/test/ui/conditional-compilation/cfg-arg-invalid-2.rs b/src/test/ui/conditional-compilation/cfg-arg-invalid-2.rs
new file mode 100644
index 0000000..48d656a
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg-arg-invalid-2.rs
@@ -0,0 +1,3 @@
+// compile-flags: --cfg a{b}
+// error-pattern: invalid `--cfg` argument: `a{b}` (expected `key` or `key="value"`)
+fn main() {}
diff --git a/src/test/ui/conditional-compilation/cfg-arg-invalid-3.rs b/src/test/ui/conditional-compilation/cfg-arg-invalid-3.rs
new file mode 100644
index 0000000..96ac782
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg-arg-invalid-3.rs
@@ -0,0 +1,3 @@
+// compile-flags: --cfg a::b
+// error-pattern: invalid `--cfg` argument: `a::b` (argument key must be an identifier)
+fn main() {}
diff --git a/src/test/ui/conditional-compilation/cfg-arg-invalid-4.rs b/src/test/ui/conditional-compilation/cfg-arg-invalid-4.rs
new file mode 100644
index 0000000..e7dfa17
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg-arg-invalid-4.rs
@@ -0,0 +1,3 @@
+// compile-flags: --cfg a(b)
+// error-pattern: invalid `--cfg` argument: `a(b)` (expected `key` or `key="value"`)
+fn main() {}
diff --git a/src/test/ui/conditional-compilation/cfg-arg-invalid-5.rs b/src/test/ui/conditional-compilation/cfg-arg-invalid-5.rs
new file mode 100644
index 0000000..a939f45
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg-arg-invalid-5.rs
@@ -0,0 +1,3 @@
+// compile-flags: --cfg a=10
+// error-pattern: invalid `--cfg` argument: `a=10` (argument value must be a string)
+fn main() {}
diff --git a/src/test/ui/conditional-compilation/cfg-attr-cfg-2.rs b/src/test/ui/conditional-compilation/cfg-attr-cfg-2.rs
new file mode 100644
index 0000000..898c5ba
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg-attr-cfg-2.rs
@@ -0,0 +1,9 @@
+//
+// error-pattern: `main` function not found
+// compile-flags: --cfg foo
+
+// main is conditionally compiled, but the conditional compilation
+// is conditional too!
+
+#[cfg_attr(foo, cfg(bar))]
+fn main() { }
diff --git a/src/test/ui/conditional-compilation/cfg-attr-cfg-2.stderr b/src/test/ui/conditional-compilation/cfg-attr-cfg-2.stderr
new file mode 100644
index 0000000..db3c7ac
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg-attr-cfg-2.stderr
@@ -0,0 +1,7 @@
+error[E0601]: `main` function not found in crate `cfg_attr_cfg_2`
+   |
+   = note: consider adding a `main` function to `$DIR/cfg-attr-cfg-2.rs`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0601`.
diff --git a/src/test/ui/conditional-compilation/cfg-attr-crate-2.rs b/src/test/ui/conditional-compilation/cfg-attr-crate-2.rs
new file mode 100644
index 0000000..0dceba2
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg-attr-crate-2.rs
@@ -0,0 +1,8 @@
+// https://github.com/rust-lang/rust/issues/21833#issuecomment-72353044
+
+// compile-flags: --cfg broken
+
+#![crate_type = "lib"]
+#![cfg_attr(broken, no_core)] //~ ERROR no_core is experimental
+
+pub struct S {}
diff --git a/src/test/ui/conditional-compilation/cfg-attr-crate-2.stderr b/src/test/ui/conditional-compilation/cfg-attr-crate-2.stderr
new file mode 100644
index 0000000..8d308f0
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg-attr-crate-2.stderr
@@ -0,0 +1,11 @@
+error[E0658]: no_core is experimental (see issue #29639)
+  --> $DIR/cfg-attr-crate-2.rs:6:21
+   |
+LL | #![cfg_attr(broken, no_core)]
+   |                     ^^^^^^^
+   |
+   = help: add #![feature(no_core)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/conditional-compilation/cfg-attr-invalid-predicate.rs b/src/test/ui/conditional-compilation/cfg-attr-invalid-predicate.rs
new file mode 100644
index 0000000..496d196
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg-attr-invalid-predicate.rs
@@ -0,0 +1,4 @@
+#[cfg(foo(bar))] //~ ERROR invalid predicate `foo`
+fn check() {}
+
+fn main() {}
diff --git a/src/test/ui/conditional-compilation/cfg-attr-invalid-predicate.stderr b/src/test/ui/conditional-compilation/cfg-attr-invalid-predicate.stderr
new file mode 100644
index 0000000..96c571e
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg-attr-invalid-predicate.stderr
@@ -0,0 +1,9 @@
+error[E0537]: invalid predicate `foo`
+  --> $DIR/cfg-attr-invalid-predicate.rs:1:7
+   |
+LL | #[cfg(foo(bar))]
+   |       ^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0537`.
diff --git a/src/test/ui/conditional-compilation/cfg-attr-multi-false.rs b/src/test/ui/conditional-compilation/cfg-attr-multi-false.rs
new file mode 100644
index 0000000..f1ab2f0
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg-attr-multi-false.rs
@@ -0,0 +1,19 @@
+// Test that cfg_attr doesn't emit any attributes when the
+// configuration variable is false. This mirrors `cfg-attr-multi-true.rs`
+
+// compile-pass
+
+#![warn(unused_must_use)]
+
+#[cfg_attr(any(), deprecated, must_use)]
+struct Struct {}
+
+impl Struct {
+    fn new() -> Struct {
+        Struct {}
+    }
+}
+
+fn main() {
+    Struct::new();
+}
diff --git a/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-1.rs b/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-1.rs
new file mode 100644
index 0000000..be762c5
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-1.rs
@@ -0,0 +1,6 @@
+// compile-flags: --cfg broken
+
+#![crate_type = "lib"]
+#![cfg_attr(broken, no_core, no_std)] //~ ERROR no_core is experimental
+
+pub struct S {}
diff --git a/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-1.stderr b/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-1.stderr
new file mode 100644
index 0000000..8485459
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-1.stderr
@@ -0,0 +1,11 @@
+error[E0658]: no_core is experimental (see issue #29639)
+  --> $DIR/cfg-attr-multi-invalid-1.rs:4:21
+   |
+LL | #![cfg_attr(broken, no_core, no_std)]
+   |                     ^^^^^^^
+   |
+   = help: add #![feature(no_core)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-2.rs b/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-2.rs
new file mode 100644
index 0000000..8a9e99d
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-2.rs
@@ -0,0 +1,6 @@
+// compile-flags: --cfg broken
+
+#![crate_type = "lib"]
+#![cfg_attr(broken, no_std, no_core)] //~ ERROR no_core is experimental
+
+pub struct S {}
diff --git a/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-2.stderr b/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-2.stderr
new file mode 100644
index 0000000..2a673ea
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-2.stderr
@@ -0,0 +1,11 @@
+error[E0658]: no_core is experimental (see issue #29639)
+  --> $DIR/cfg-attr-multi-invalid-2.rs:4:29
+   |
+LL | #![cfg_attr(broken, no_std, no_core)]
+   |                             ^^^^^^^
+   |
+   = help: add #![feature(no_core)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/conditional-compilation/cfg-attr-multi-true.rs b/src/test/ui/conditional-compilation/cfg-attr-multi-true.rs
new file mode 100644
index 0000000..86524e8
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg-attr-multi-true.rs
@@ -0,0 +1,21 @@
+// Test that cfg_attr with multiple attributes actually emits both attributes.
+// This is done by emitting two attributes that cause new warnings, and then
+// triggering those warnings.
+
+// compile-pass
+
+#![warn(unused_must_use)]
+
+#[cfg_attr(all(), deprecated, must_use)]
+struct MustUseDeprecated {}
+
+impl MustUseDeprecated { //~ warning: use of deprecated item
+    fn new() -> MustUseDeprecated { //~ warning: use of deprecated item
+        MustUseDeprecated {} //~ warning: use of deprecated item
+    }
+}
+
+fn main() {
+    MustUseDeprecated::new(); //~ warning: use of deprecated item
+    //| warning: unused `MustUseDeprecated` that must be used
+}
diff --git a/src/test/ui/conditional-compilation/cfg-attr-multi-true.stderr b/src/test/ui/conditional-compilation/cfg-attr-multi-true.stderr
new file mode 100644
index 0000000..64e9570
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg-attr-multi-true.stderr
@@ -0,0 +1,38 @@
+warning: use of deprecated item 'MustUseDeprecated'
+  --> $DIR/cfg-attr-multi-true.rs:12:6
+   |
+LL | impl MustUseDeprecated {
+   |      ^^^^^^^^^^^^^^^^^
+   |
+   = note: #[warn(deprecated)] on by default
+
+warning: use of deprecated item 'MustUseDeprecated'
+  --> $DIR/cfg-attr-multi-true.rs:19:5
+   |
+LL |     MustUseDeprecated::new();
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'MustUseDeprecated'
+  --> $DIR/cfg-attr-multi-true.rs:13:17
+   |
+LL |     fn new() -> MustUseDeprecated {
+   |                 ^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'MustUseDeprecated'
+  --> $DIR/cfg-attr-multi-true.rs:14:9
+   |
+LL |         MustUseDeprecated {}
+   |         ^^^^^^^^^^^^^^^^^
+
+warning: unused `MustUseDeprecated` that must be used
+  --> $DIR/cfg-attr-multi-true.rs:19:5
+   |
+LL |     MustUseDeprecated::new();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/cfg-attr-multi-true.rs:7:9
+   |
+LL | #![warn(unused_must_use)]
+   |         ^^^^^^^^^^^^^^^
+
diff --git a/src/test/ui/conditional-compilation/cfg-attr-parse.rs b/src/test/ui/conditional-compilation/cfg-attr-parse.rs
new file mode 100644
index 0000000..93aef72
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg-attr-parse.rs
@@ -0,0 +1,43 @@
+// Parse `cfg_attr` with varying numbers of attributes and trailing commas
+
+// Completely empty `cfg_attr` input
+#[cfg_attr()] //~ error: expected identifier, found `)`
+struct NoConfigurationPredicate;
+
+// Zero attributes, zero trailing comma (comma manatory here)
+#[cfg_attr(all())] //~ error: expected `,`, found `)`
+struct A0C0;
+
+// Zero attributes, one trailing comma
+#[cfg_attr(all(),)] // Ok
+struct A0C1;
+
+// Zero attributes, two trailing commas
+#[cfg_attr(all(),,)] //~ ERROR expected identifier
+struct A0C2;
+
+// One attribute, no trailing comma
+#[cfg_attr(all(), must_use)] // Ok
+struct A1C0;
+
+// One attribute, one trailing comma
+#[cfg_attr(all(), must_use,)] // Ok
+struct A1C1;
+
+// One attribute, two trailing commas
+#[cfg_attr(all(), must_use,,)] //~ ERROR expected identifier
+struct A1C2;
+
+// Two attributes, no trailing comma
+#[cfg_attr(all(), must_use, deprecated)] // Ok
+struct A2C0;
+
+// Two attributes, one trailing comma
+#[cfg_attr(all(), must_use, deprecated,)] // Ok
+struct A2C1;
+
+// Two attributes, two trailing commas
+#[cfg_attr(all(), must_use, deprecated,,)] //~ ERROR expected identifier
+struct A2C2;
+
+fn main() {}
diff --git a/src/test/ui/conditional-compilation/cfg-attr-parse.stderr b/src/test/ui/conditional-compilation/cfg-attr-parse.stderr
new file mode 100644
index 0000000..3dfbd6d
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg-attr-parse.stderr
@@ -0,0 +1,32 @@
+error: expected identifier, found `)`
+  --> $DIR/cfg-attr-parse.rs:4:12
+   |
+LL | #[cfg_attr()]
+   |            ^ expected identifier
+
+error: expected `,`, found `)`
+  --> $DIR/cfg-attr-parse.rs:8:17
+   |
+LL | #[cfg_attr(all())]
+   |                 ^ expected `,`
+
+error: expected identifier, found `,`
+  --> $DIR/cfg-attr-parse.rs:16:18
+   |
+LL | #[cfg_attr(all(),,)]
+   |                  ^ expected identifier
+
+error: expected identifier, found `,`
+  --> $DIR/cfg-attr-parse.rs:28:28
+   |
+LL | #[cfg_attr(all(), must_use,,)]
+   |                            ^ expected identifier
+
+error: expected identifier, found `,`
+  --> $DIR/cfg-attr-parse.rs:40:40
+   |
+LL | #[cfg_attr(all(), must_use, deprecated,,)]
+   |                                        ^ expected identifier
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/ui/conditional-compilation/cfg-attr-syntax-validation.rs b/src/test/ui/conditional-compilation/cfg-attr-syntax-validation.rs
new file mode 100644
index 0000000..7f0648b
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg-attr-syntax-validation.rs
@@ -0,0 +1,38 @@
+#[cfg] //~ ERROR `cfg` is not followed by parentheses
+struct S1;
+
+#[cfg = 10] //~ ERROR `cfg` is not followed by parentheses
+struct S2;
+
+#[cfg()] //~ ERROR `cfg` predicate is not specified
+struct S3;
+
+#[cfg(a, b)] //~ ERROR multiple `cfg` predicates are specified
+struct S4;
+
+#[cfg("str")] //~ ERROR `cfg` predicate key cannot be a literal
+struct S5;
+
+#[cfg(a::b)] //~ ERROR `cfg` predicate key must be an identifier
+struct S6;
+
+#[cfg(a())] //~ ERROR invalid predicate `a`
+struct S7;
+
+#[cfg(a = 10)] //~ ERROR literal in `cfg` predicate value must be a string
+struct S8;
+
+#[cfg(a = b"hi")]  //~ ERROR literal in `cfg` predicate value must be a string
+struct S9;
+
+macro_rules! generate_s10 {
+    ($expr: expr) => {
+        #[cfg(feature = $expr)]
+        //~^ ERROR expected unsuffixed literal or identifier, found `concat!("nonexistent")`
+        struct S10;
+    }
+}
+
+generate_s10!(concat!("nonexistent"));
+
+fn main() {}
diff --git a/src/test/ui/conditional-compilation/cfg-attr-syntax-validation.stderr b/src/test/ui/conditional-compilation/cfg-attr-syntax-validation.stderr
new file mode 100644
index 0000000..ae37461
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg-attr-syntax-validation.stderr
@@ -0,0 +1,67 @@
+error: `cfg` is not followed by parentheses
+  --> $DIR/cfg-attr-syntax-validation.rs:1:1
+   |
+LL | #[cfg]
+   | ^^^^^^ help: expected syntax is: `cfg(/* predicate */)`
+
+error: `cfg` is not followed by parentheses
+  --> $DIR/cfg-attr-syntax-validation.rs:4:1
+   |
+LL | #[cfg = 10]
+   | ^^^^^^^^^^^ help: expected syntax is: `cfg(/* predicate */)`
+
+error: `cfg` predicate is not specified
+  --> $DIR/cfg-attr-syntax-validation.rs:7:1
+   |
+LL | #[cfg()]
+   | ^^^^^^^^
+
+error: multiple `cfg` predicates are specified
+  --> $DIR/cfg-attr-syntax-validation.rs:10:10
+   |
+LL | #[cfg(a, b)]
+   |          ^
+
+error: `cfg` predicate key cannot be a literal
+  --> $DIR/cfg-attr-syntax-validation.rs:13:7
+   |
+LL | #[cfg("str")]
+   |       ^^^^^
+
+error: `cfg` predicate key must be an identifier
+  --> $DIR/cfg-attr-syntax-validation.rs:16:7
+   |
+LL | #[cfg(a::b)]
+   |       ^^^^
+
+error[E0537]: invalid predicate `a`
+  --> $DIR/cfg-attr-syntax-validation.rs:19:7
+   |
+LL | #[cfg(a())]
+   |       ^^^
+
+error[E0565]: literal in `cfg` predicate value must be a string
+  --> $DIR/cfg-attr-syntax-validation.rs:22:11
+   |
+LL | #[cfg(a = 10)]
+   |           ^^
+
+error[E0565]: literal in `cfg` predicate value must be a string
+  --> $DIR/cfg-attr-syntax-validation.rs:25:11
+   |
+LL | #[cfg(a = b"hi")]
+   |           ^^^^^ help: consider removing the prefix: `"hi"`
+
+error: expected unsuffixed literal or identifier, found `concat!("nonexistent")`
+  --> $DIR/cfg-attr-syntax-validation.rs:30:25
+   |
+LL |         #[cfg(feature = $expr)]
+   |                         ^^^^^
+...
+LL | generate_s10!(concat!("nonexistent"));
+   | -------------------------------------- in this macro invocation
+
+error: aborting due to 10 previous errors
+
+Some errors occurred: E0537, E0565.
+For more information about an error, try `rustc --explain E0537`.
diff --git a/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.rs b/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.rs
new file mode 100644
index 0000000..1ed2ddc
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.rs
@@ -0,0 +1,10 @@
+macro_rules! foo {
+    () => {
+        #[cfg_attr(all(), unknown)] //~ ERROR `unknown` is currently unknown
+        fn foo() {}
+    }
+}
+
+foo!();
+
+fn main() {}
diff --git a/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.stderr b/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.stderr
new file mode 100644
index 0000000..d0b59c3
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.stderr
@@ -0,0 +1,14 @@
+error[E0658]: The attribute `unknown` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/cfg-attr-unknown-attribute-macro-expansion.rs:3:27
+   |
+LL |         #[cfg_attr(all(), unknown)]
+   |                           ^^^^^^^
+...
+LL | foo!();
+   | ------- in this macro invocation
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/conditional-compilation/cfg-empty-codemap.rs b/src/test/ui/conditional-compilation/cfg-empty-codemap.rs
new file mode 100644
index 0000000..9e34cac
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg-empty-codemap.rs
@@ -0,0 +1,8 @@
+// Tests that empty source_maps don't ICE (#23301)
+
+// compile-flags: --cfg ""
+
+// error-pattern: invalid `--cfg` argument: `""` (expected `key` or `key="value"`)
+
+pub fn main() {
+}
diff --git a/src/test/ui/conditional-compilation/cfg-in-crate-1.rs b/src/test/ui/conditional-compilation/cfg-in-crate-1.rs
new file mode 100644
index 0000000..8561cd8
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg-in-crate-1.rs
@@ -0,0 +1,3 @@
+// error-pattern: `main` function not found
+
+#![cfg(bar)]
diff --git a/src/test/ui/conditional-compilation/cfg-in-crate-1.stderr b/src/test/ui/conditional-compilation/cfg-in-crate-1.stderr
new file mode 100644
index 0000000..c6d42c7
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg-in-crate-1.stderr
@@ -0,0 +1,7 @@
+error[E0601]: `main` function not found in crate `cfg_in_crate_1`
+   |
+   = note: consider adding a `main` function to `$DIR/cfg-in-crate-1.rs`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0601`.
diff --git a/src/test/ui/conditional-compilation/cfg-non-opt-expr.rs b/src/test/ui/conditional-compilation/cfg-non-opt-expr.rs
new file mode 100644
index 0000000..0ddbd8a
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg-non-opt-expr.rs
@@ -0,0 +1,11 @@
+#![feature(stmt_expr_attributes)]
+#![feature(custom_test_frameworks)]
+
+fn main() {
+    let _ = #[cfg(unset)] ();
+    //~^ ERROR removing an expression is not supported in this position
+    let _ = 1 + 2 + #[cfg(unset)] 3;
+    //~^ ERROR removing an expression is not supported in this position
+    let _ = [1, 2, 3][#[cfg(unset)] 1];
+    //~^ ERROR removing an expression is not supported in this position
+}
diff --git a/src/test/ui/conditional-compilation/cfg-non-opt-expr.stderr b/src/test/ui/conditional-compilation/cfg-non-opt-expr.stderr
new file mode 100644
index 0000000..933b7dc
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg-non-opt-expr.stderr
@@ -0,0 +1,20 @@
+error: removing an expression is not supported in this position
+  --> $DIR/cfg-non-opt-expr.rs:5:13
+   |
+LL |     let _ = #[cfg(unset)] ();
+   |             ^^^^^^^^^^^^^
+
+error: removing an expression is not supported in this position
+  --> $DIR/cfg-non-opt-expr.rs:7:21
+   |
+LL |     let _ = 1 + 2 + #[cfg(unset)] 3;
+   |                     ^^^^^^^^^^^^^
+
+error: removing an expression is not supported in this position
+  --> $DIR/cfg-non-opt-expr.rs:9:23
+   |
+LL |     let _ = [1, 2, 3][#[cfg(unset)] 1];
+   |                       ^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/conditional-compilation/cfg_attr_path.rs b/src/test/ui/conditional-compilation/cfg_attr_path.rs
new file mode 100644
index 0000000..9e9ff66
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg_attr_path.rs
@@ -0,0 +1,14 @@
+// compile-pass
+// skip-codegen
+#![allow(dead_code)]
+#![deny(unused_attributes)] // c.f #35584
+mod auxiliary {
+    #[cfg_attr(any(), path = "nonexistent_file.rs")] pub mod namespaced_enums;
+    #[cfg_attr(all(), path = "namespaced_enums.rs")] pub mod nonexistent_file;
+}
+
+
+fn main() {
+    let _ = auxiliary::namespaced_enums::Foo::A;
+    let _ = auxiliary::nonexistent_file::Foo::A;
+}
diff --git a/src/test/ui/conflicting-repr-hints.rs b/src/test/ui/conflicting-repr-hints.rs
new file mode 100644
index 0000000..cc986b2
--- /dev/null
+++ b/src/test/ui/conflicting-repr-hints.rs
@@ -0,0 +1,56 @@
+#![allow(dead_code)]
+
+#[repr(C)]
+enum A { A }
+
+#[repr(u64)]
+enum B { B }
+
+#[repr(C, u64)] //~ WARNING conflicting representation hints
+enum C { C }
+
+#[repr(u32, u64)] //~ WARNING conflicting representation hints
+enum D { D }
+
+#[repr(C, packed)]
+struct E(i32);
+
+#[repr(packed, align(8))]
+struct F(i32); //~ ERROR type has conflicting packed and align representation hints
+
+#[repr(packed)]
+#[repr(align(8))]
+struct G(i32); //~ ERROR type has conflicting packed and align representation hints
+
+#[repr(align(8))]
+#[repr(packed)]
+struct H(i32); //~ ERROR type has conflicting packed and align representation hints
+
+#[repr(packed, packed(2))]
+struct I(i32); //~ ERROR type has conflicting packed representation hints
+
+#[repr(packed(2))]
+#[repr(packed)]
+struct J(i32); //~ ERROR type has conflicting packed representation hints
+
+#[repr(packed, packed(1))]
+struct K(i32);
+
+#[repr(packed, align(8))]
+union X { //~ ERROR type has conflicting packed and align representation hints
+    i: i32
+}
+
+#[repr(packed)]
+#[repr(align(8))]
+union Y { //~ ERROR type has conflicting packed and align representation hints
+    i: i32
+}
+
+#[repr(align(8))]
+#[repr(packed)]
+union Z { //~ ERROR type has conflicting packed and align representation hints
+    i: i32
+}
+
+fn main() {}
diff --git a/src/test/ui/conflicting-repr-hints.stderr b/src/test/ui/conflicting-repr-hints.stderr
new file mode 100644
index 0000000..c39055f
--- /dev/null
+++ b/src/test/ui/conflicting-repr-hints.stderr
@@ -0,0 +1,70 @@
+warning[E0566]: conflicting representation hints
+  --> $DIR/conflicting-repr-hints.rs:9:8
+   |
+LL | #[repr(C, u64)]
+   |        ^  ^^^
+
+warning[E0566]: conflicting representation hints
+  --> $DIR/conflicting-repr-hints.rs:12:8
+   |
+LL | #[repr(u32, u64)]
+   |        ^^^  ^^^
+
+error[E0587]: type has conflicting packed and align representation hints
+  --> $DIR/conflicting-repr-hints.rs:19:1
+   |
+LL | struct F(i32);
+   | ^^^^^^^^^^^^^^
+
+error[E0587]: type has conflicting packed and align representation hints
+  --> $DIR/conflicting-repr-hints.rs:23:1
+   |
+LL | struct G(i32);
+   | ^^^^^^^^^^^^^^
+
+error[E0587]: type has conflicting packed and align representation hints
+  --> $DIR/conflicting-repr-hints.rs:27:1
+   |
+LL | struct H(i32);
+   | ^^^^^^^^^^^^^^
+
+error[E0634]: type has conflicting packed representation hints
+  --> $DIR/conflicting-repr-hints.rs:30:1
+   |
+LL | struct I(i32);
+   | ^^^^^^^^^^^^^^
+
+error[E0634]: type has conflicting packed representation hints
+  --> $DIR/conflicting-repr-hints.rs:34:1
+   |
+LL | struct J(i32);
+   | ^^^^^^^^^^^^^^
+
+error[E0587]: type has conflicting packed and align representation hints
+  --> $DIR/conflicting-repr-hints.rs:40:1
+   |
+LL | / union X {
+LL | |     i: i32
+LL | | }
+   | |_^
+
+error[E0587]: type has conflicting packed and align representation hints
+  --> $DIR/conflicting-repr-hints.rs:46:1
+   |
+LL | / union Y {
+LL | |     i: i32
+LL | | }
+   | |_^
+
+error[E0587]: type has conflicting packed and align representation hints
+  --> $DIR/conflicting-repr-hints.rs:52:1
+   |
+LL | / union Z {
+LL | |     i: i32
+LL | | }
+   | |_^
+
+error: aborting due to 8 previous errors
+
+Some errors occurred: E0566, E0587, E0634.
+For more information about an error, try `rustc --explain E0566`.
diff --git a/src/test/ui/confuse-field-and-method/issue-18343.rs b/src/test/ui/confuse-field-and-method/issue-18343.rs
new file mode 100644
index 0000000..bc2d73f
--- /dev/null
+++ b/src/test/ui/confuse-field-and-method/issue-18343.rs
@@ -0,0 +1,9 @@
+struct Obj<F> where F: FnMut() -> u32 {
+    closure: F,
+}
+
+fn main() {
+    let o = Obj { closure: || 42 };
+    o.closure();
+    //~^ ERROR no method named `closure` found
+}
diff --git a/src/test/ui/confuse-field-and-method/issue-18343.stderr b/src/test/ui/confuse-field-and-method/issue-18343.stderr
new file mode 100644
index 0000000..03f9d99
--- /dev/null
+++ b/src/test/ui/confuse-field-and-method/issue-18343.stderr
@@ -0,0 +1,16 @@
+error[E0599]: no method named `closure` found for type `Obj<[closure@$DIR/issue-18343.rs:6:28: 6:33]>` in the current scope
+  --> $DIR/issue-18343.rs:7:7
+   |
+LL | struct Obj<F> where F: FnMut() -> u32 {
+   | ------------------------------------- method `closure` not found for this
+...
+LL |     o.closure();
+   |       ^^^^^^^ field, not a method
+help: to call the function stored in `closure`, surround the field access with parentheses
+   |
+LL |     (o.closure)();
+   |     ^         ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/confuse-field-and-method/issue-2392.rs b/src/test/ui/confuse-field-and-method/issue-2392.rs
new file mode 100644
index 0000000..41287c2
--- /dev/null
+++ b/src/test/ui/confuse-field-and-method/issue-2392.rs
@@ -0,0 +1,73 @@
+#![feature(core, fnbox)]
+
+use std::boxed::FnBox;
+
+struct FuncContainer {
+    f1: fn(data: u8),
+    f2: extern "C" fn(data: u8),
+    f3: unsafe fn(data: u8),
+}
+
+struct FuncContainerOuter {
+    container: Box<FuncContainer>
+}
+
+struct Obj<F> where F: FnOnce() -> u32 {
+    closure: F,
+    not_closure: usize,
+}
+
+struct BoxedObj {
+    boxed_closure: Box<FnBox() -> u32>,
+}
+
+struct Wrapper<F> where F: FnMut() -> u32 {
+    wrap: Obj<F>,
+}
+
+fn func() -> u32 {
+    0
+}
+
+fn check_expression() -> Obj<Box<FnBox() -> u32>> {
+    Obj { closure: Box::new(|| 42_u32) as Box<FnBox() -> u32>, not_closure: 42 }
+}
+
+fn main() {
+    // test variations of function
+
+    let o_closure = Obj { closure: || 42, not_closure: 42 };
+    o_closure.closure(); //~ ERROR no method named `closure` found
+
+    o_closure.not_closure();
+    //~^ ERROR no method named `not_closure` found
+
+    let o_func = Obj { closure: func, not_closure: 5 };
+    o_func.closure(); //~ ERROR no method named `closure` found
+
+    let boxed_fn = BoxedObj { boxed_closure: Box::new(func) };
+    boxed_fn.boxed_closure();//~ ERROR no method named `boxed_closure` found
+
+    let boxed_closure = BoxedObj { boxed_closure: Box::new(|| 42_u32) as Box<FnBox() -> u32> };
+    boxed_closure.boxed_closure();//~ ERROR no method named `boxed_closure` found
+
+    // test expression writing in the notes
+
+    let w = Wrapper { wrap: o_func };
+    w.wrap.closure();//~ ERROR no method named `closure` found
+
+    w.wrap.not_closure();
+    //~^ ERROR no method named `not_closure` found
+
+    check_expression().closure();//~ ERROR no method named `closure` found
+}
+
+impl FuncContainerOuter {
+    fn run(&self) {
+        unsafe {
+            (*self.container).f1(1); //~ ERROR no method named `f1` found
+            (*self.container).f2(1); //~ ERROR no method named `f2` found
+            (*self.container).f3(1); //~ ERROR no method named `f3` found
+        }
+    }
+}
diff --git a/src/test/ui/confuse-field-and-method/issue-2392.stderr b/src/test/ui/confuse-field-and-method/issue-2392.stderr
new file mode 100644
index 0000000..2107318
--- /dev/null
+++ b/src/test/ui/confuse-field-and-method/issue-2392.stderr
@@ -0,0 +1,142 @@
+error[E0599]: no method named `closure` found for type `Obj<[closure@$DIR/issue-2392.rs:39:36: 39:41]>` in the current scope
+  --> $DIR/issue-2392.rs:40:15
+   |
+LL | struct Obj<F> where F: FnOnce() -> u32 {
+   | -------------------------------------- method `closure` not found for this
+...
+LL |     o_closure.closure();
+   |               ^^^^^^^ field, not a method
+help: to call the function stored in `closure`, surround the field access with parentheses
+   |
+LL |     (o_closure.closure)();
+   |     ^                 ^
+
+error[E0599]: no method named `not_closure` found for type `Obj<[closure@$DIR/issue-2392.rs:39:36: 39:41]>` in the current scope
+  --> $DIR/issue-2392.rs:42:15
+   |
+LL | struct Obj<F> where F: FnOnce() -> u32 {
+   | -------------------------------------- method `not_closure` not found for this
+...
+LL |     o_closure.not_closure();
+   |               ^^^^^^^^^^^-- help: remove the arguments
+   |               |
+   |               field, not a method
+
+error[E0599]: no method named `closure` found for type `Obj<fn() -> u32 {func}>` in the current scope
+  --> $DIR/issue-2392.rs:46:12
+   |
+LL | struct Obj<F> where F: FnOnce() -> u32 {
+   | -------------------------------------- method `closure` not found for this
+...
+LL |     o_func.closure();
+   |            ^^^^^^^ field, not a method
+help: to call the function stored in `closure`, surround the field access with parentheses
+   |
+LL |     (o_func.closure)();
+   |     ^              ^
+
+error[E0599]: no method named `boxed_closure` found for type `BoxedObj` in the current scope
+  --> $DIR/issue-2392.rs:49:14
+   |
+LL | struct BoxedObj {
+   | --------------- method `boxed_closure` not found for this
+...
+LL |     boxed_fn.boxed_closure();
+   |              ^^^^^^^^^^^^^ field, not a method
+help: to call the function stored in `boxed_closure`, surround the field access with parentheses
+   |
+LL |     (boxed_fn.boxed_closure)();
+   |     ^                      ^
+
+error[E0599]: no method named `boxed_closure` found for type `BoxedObj` in the current scope
+  --> $DIR/issue-2392.rs:52:19
+   |
+LL | struct BoxedObj {
+   | --------------- method `boxed_closure` not found for this
+...
+LL |     boxed_closure.boxed_closure();
+   |                   ^^^^^^^^^^^^^ field, not a method
+help: to call the function stored in `boxed_closure`, surround the field access with parentheses
+   |
+LL |     (boxed_closure.boxed_closure)();
+   |     ^                           ^
+
+error[E0599]: no method named `closure` found for type `Obj<fn() -> u32 {func}>` in the current scope
+  --> $DIR/issue-2392.rs:57:12
+   |
+LL | struct Obj<F> where F: FnOnce() -> u32 {
+   | -------------------------------------- method `closure` not found for this
+...
+LL |     w.wrap.closure();
+   |            ^^^^^^^ field, not a method
+help: to call the function stored in `closure`, surround the field access with parentheses
+   |
+LL |     (w.wrap.closure)();
+   |     ^              ^
+
+error[E0599]: no method named `not_closure` found for type `Obj<fn() -> u32 {func}>` in the current scope
+  --> $DIR/issue-2392.rs:59:12
+   |
+LL | struct Obj<F> where F: FnOnce() -> u32 {
+   | -------------------------------------- method `not_closure` not found for this
+...
+LL |     w.wrap.not_closure();
+   |            ^^^^^^^^^^^-- help: remove the arguments
+   |            |
+   |            field, not a method
+
+error[E0599]: no method named `closure` found for type `Obj<std::boxed::Box<(dyn std::boxed::FnBox<(), Output = u32> + 'static)>>` in the current scope
+  --> $DIR/issue-2392.rs:62:24
+   |
+LL | struct Obj<F> where F: FnOnce() -> u32 {
+   | -------------------------------------- method `closure` not found for this
+...
+LL |     check_expression().closure();
+   |                        ^^^^^^^ field, not a method
+help: to call the function stored in `closure`, surround the field access with parentheses
+   |
+LL |     (check_expression().closure)();
+   |     ^                          ^
+
+error[E0599]: no method named `f1` found for type `FuncContainer` in the current scope
+  --> $DIR/issue-2392.rs:68:31
+   |
+LL | struct FuncContainer {
+   | -------------------- method `f1` not found for this
+...
+LL |             (*self.container).f1(1);
+   |                               ^^ field, not a method
+help: to call the function stored in `f1`, surround the field access with parentheses
+   |
+LL |             ((*self.container).f1)(1);
+   |             ^                    ^
+
+error[E0599]: no method named `f2` found for type `FuncContainer` in the current scope
+  --> $DIR/issue-2392.rs:69:31
+   |
+LL | struct FuncContainer {
+   | -------------------- method `f2` not found for this
+...
+LL |             (*self.container).f2(1);
+   |                               ^^ field, not a method
+help: to call the function stored in `f2`, surround the field access with parentheses
+   |
+LL |             ((*self.container).f2)(1);
+   |             ^                    ^
+
+error[E0599]: no method named `f3` found for type `FuncContainer` in the current scope
+  --> $DIR/issue-2392.rs:70:31
+   |
+LL | struct FuncContainer {
+   | -------------------- method `f3` not found for this
+...
+LL |             (*self.container).f3(1);
+   |                               ^^ field, not a method
+help: to call the function stored in `f3`, surround the field access with parentheses
+   |
+LL |             ((*self.container).f3)(1);
+   |             ^                    ^
+
+error: aborting due to 11 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/confuse-field-and-method/issue-32128.rs b/src/test/ui/confuse-field-and-method/issue-32128.rs
new file mode 100644
index 0000000..02c6838
--- /dev/null
+++ b/src/test/ui/confuse-field-and-method/issue-32128.rs
@@ -0,0 +1,15 @@
+struct Example {
+    example: Box<Fn(i32) -> i32>
+}
+
+fn main() {
+    let demo = Example {
+        example: Box::new(|x| {
+            x + 1
+        })
+    };
+
+    demo.example(1);
+    //~^ ERROR no method named `example`
+    // (demo.example)(1);
+}
diff --git a/src/test/ui/confuse-field-and-method/issue-32128.stderr b/src/test/ui/confuse-field-and-method/issue-32128.stderr
new file mode 100644
index 0000000..fbabb3a
--- /dev/null
+++ b/src/test/ui/confuse-field-and-method/issue-32128.stderr
@@ -0,0 +1,16 @@
+error[E0599]: no method named `example` found for type `Example` in the current scope
+  --> $DIR/issue-32128.rs:12:10
+   |
+LL | struct Example {
+   | -------------- method `example` not found for this
+...
+LL |     demo.example(1);
+   |          ^^^^^^^ field, not a method
+help: to call the function stored in `example`, surround the field access with parentheses
+   |
+LL |     (demo.example)(1);
+   |     ^            ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/confuse-field-and-method/issue-33784.rs b/src/test/ui/confuse-field-and-method/issue-33784.rs
new file mode 100644
index 0000000..e9bb1f9
--- /dev/null
+++ b/src/test/ui/confuse-field-and-method/issue-33784.rs
@@ -0,0 +1,33 @@
+use std::ops::Deref;
+
+struct Obj<F> where F: FnMut() -> u32 {
+    fn_ptr: fn() -> (),
+    closure: F,
+}
+
+struct C {
+    c_fn_ptr: fn() -> (),
+}
+
+struct D(C);
+
+impl Deref for D {
+    type Target = C;
+    fn deref(&self) -> &C {
+        &self.0
+    }
+}
+
+
+fn empty() {}
+
+fn main() {
+    let o = Obj { fn_ptr: empty, closure: || 42 };
+    let p = &o;
+    p.closure(); //~ ERROR no method named `closure` found
+    let q = &p;
+    q.fn_ptr(); //~ ERROR no method named `fn_ptr` found
+    let r = D(C { c_fn_ptr: empty });
+    let s = &r;
+    s.c_fn_ptr(); //~ ERROR no method named `c_fn_ptr` found
+}
diff --git a/src/test/ui/confuse-field-and-method/issue-33784.stderr b/src/test/ui/confuse-field-and-method/issue-33784.stderr
new file mode 100644
index 0000000..60f1a93
--- /dev/null
+++ b/src/test/ui/confuse-field-and-method/issue-33784.stderr
@@ -0,0 +1,33 @@
+error[E0599]: no method named `closure` found for type `&Obj<[closure@$DIR/issue-33784.rs:25:43: 25:48]>` in the current scope
+  --> $DIR/issue-33784.rs:27:7
+   |
+LL |     p.closure();
+   |       ^^^^^^^ field, not a method
+help: to call the function stored in `closure`, surround the field access with parentheses
+   |
+LL |     (p.closure)();
+   |     ^         ^
+
+error[E0599]: no method named `fn_ptr` found for type `&&Obj<[closure@$DIR/issue-33784.rs:25:43: 25:48]>` in the current scope
+  --> $DIR/issue-33784.rs:29:7
+   |
+LL |     q.fn_ptr();
+   |       ^^^^^^ field, not a method
+help: to call the function stored in `fn_ptr`, surround the field access with parentheses
+   |
+LL |     (q.fn_ptr)();
+   |     ^        ^
+
+error[E0599]: no method named `c_fn_ptr` found for type `&D` in the current scope
+  --> $DIR/issue-33784.rs:32:7
+   |
+LL |     s.c_fn_ptr();
+   |       ^^^^^^^^ field, not a method
+help: to call the function stored in `c_fn_ptr`, surround the field access with parentheses
+   |
+LL |     (s.c_fn_ptr)();
+   |     ^          ^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/confuse-field-and-method/private-field.rs b/src/test/ui/confuse-field-and-method/private-field.rs
new file mode 100644
index 0000000..28b8935
--- /dev/null
+++ b/src/test/ui/confuse-field-and-method/private-field.rs
@@ -0,0 +1,19 @@
+pub mod animal {
+    pub struct Dog {
+        pub age: usize,
+        dog_age: usize,
+    }
+
+    impl Dog {
+        pub fn new(age: usize) -> Dog {
+            Dog { age: age, dog_age: age * 7 }
+        }
+    }
+}
+
+fn main() {
+    let dog = animal::Dog::new(3);
+    let dog_age = dog.dog_age(); //~ ERROR no method
+    //let dog_age = dog.dog_age;
+    println!("{}", dog_age);
+}
diff --git a/src/test/ui/confuse-field-and-method/private-field.stderr b/src/test/ui/confuse-field-and-method/private-field.stderr
new file mode 100644
index 0000000..97c949e
--- /dev/null
+++ b/src/test/ui/confuse-field-and-method/private-field.stderr
@@ -0,0 +1,12 @@
+error[E0599]: no method named `dog_age` found for type `animal::Dog` in the current scope
+  --> $DIR/private-field.rs:16:23
+   |
+LL |     pub struct Dog {
+   |     -------------- method `dog_age` not found for this
+...
+LL |     let dog_age = dog.dog_age();
+   |                       ^^^^^^^ private field, not a method
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/conservative_impl_trait.rs b/src/test/ui/conservative_impl_trait.rs
new file mode 100644
index 0000000..b7f795e
--- /dev/null
+++ b/src/test/ui/conservative_impl_trait.rs
@@ -0,0 +1,7 @@
+// #39872, #39553
+
+fn will_ice(something: &u32) -> impl Iterator<Item = &u32> {
+    //~^ ERROR `()` is not an iterator
+}
+
+fn main() {}
diff --git a/src/test/ui/conservative_impl_trait.stderr b/src/test/ui/conservative_impl_trait.stderr
new file mode 100644
index 0000000..58223d9
--- /dev/null
+++ b/src/test/ui/conservative_impl_trait.stderr
@@ -0,0 +1,12 @@
+error[E0277]: `()` is not an iterator
+  --> $DIR/conservative_impl_trait.rs:3:33
+   |
+LL | fn will_ice(something: &u32) -> impl Iterator<Item = &u32> {
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator
+   |
+   = help: the trait `std::iter::Iterator` is not implemented for `()`
+   = note: the return type of a function must have a statically known size
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/const-generics/cannot-infer-type-for-const-param.rs b/src/test/ui/const-generics/cannot-infer-type-for-const-param.rs
new file mode 100644
index 0000000..7d54682
--- /dev/null
+++ b/src/test/ui/const-generics/cannot-infer-type-for-const-param.rs
@@ -0,0 +1,17 @@
+// The test is failing on 1.35.0 stable but that's not important since the ICE happens only with
+// the feature gate enabled, thus it doesn't affect stable.
+// https://github.com/rust-lang/rust/pull/60710#issuecomment-493662676
+//
+// ignore-test
+
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+// We should probably be able to infer the types here. However, this test is checking that we don't
+// get an ICE in this case. It may be modified later to not be an error.
+
+struct Foo<const NUM_BYTES: usize>(pub [u8; NUM_BYTES]);
+
+fn main() {
+    let _ = Foo::<3>([1, 2, 3]); //~ ERROR type annotations needed
+}
diff --git a/src/test/ui/const-generics/cannot-infer-type-for-const-param.stderr b/src/test/ui/const-generics/cannot-infer-type-for-const-param.stderr
new file mode 100644
index 0000000..a0641bd
--- /dev/null
+++ b/src/test/ui/const-generics/cannot-infer-type-for-const-param.stderr
@@ -0,0 +1,15 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/cannot-infer-type-for-const-param.rs:1:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+
+error[E0282]: type annotations needed
+  --> $DIR/cannot-infer-type-for-const-param.rs:10:19
+   |
+LL |     let _ = Foo::<3>([1, 2, 3]);
+   |                   ^ cannot infer type for `{integer}`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/const-generics/const-expression-parameter.rs b/src/test/ui/const-generics/const-expression-parameter.rs
new file mode 100644
index 0000000..662c7b7
--- /dev/null
+++ b/src/test/ui/const-generics/const-expression-parameter.rs
@@ -0,0 +1,22 @@
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+fn i32_identity<const X: i32>() -> i32 {
+    5
+}
+
+fn foo_a() {
+    i32_identity::<-1>(); //~ ERROR expected identifier, found `<-`
+}
+
+fn foo_b() {
+    i32_identity::<1 + 2>(); //~ ERROR expected one of `,` or `>`, found `+`
+}
+
+fn foo_c() {
+    i32_identity::< -1 >(); // ok
+}
+
+fn main() {
+    i32_identity::<5>(); // ok
+}
diff --git a/src/test/ui/const-generics/const-expression-parameter.stderr b/src/test/ui/const-generics/const-expression-parameter.stderr
new file mode 100644
index 0000000..2f7a80f
--- /dev/null
+++ b/src/test/ui/const-generics/const-expression-parameter.stderr
@@ -0,0 +1,20 @@
+error: expected identifier, found `<-`
+  --> $DIR/const-expression-parameter.rs:9:19
+   |
+LL |     i32_identity::<-1>();
+   |                   ^^ expected identifier
+
+error: expected one of `,` or `>`, found `+`
+  --> $DIR/const-expression-parameter.rs:13:22
+   |
+LL |     i32_identity::<1 + 2>();
+   |                      ^ expected one of `,` or `>` here
+
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/const-expression-parameter.rs:1:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/const-generics/const-fn-with-const-param.rs b/src/test/ui/const-generics/const-fn-with-const-param.rs
new file mode 100644
index 0000000..f36bf38
--- /dev/null
+++ b/src/test/ui/const-generics/const-fn-with-const-param.rs
@@ -0,0 +1,11 @@
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+const fn const_u32_identity<const X: u32>() -> u32 {
+    //~^ ERROR const parameters are not permitted in `const fn`
+    X
+}
+
+fn main() {
+    println!("{:?}", const_u32_identity::<18>());
+}
diff --git a/src/test/ui/const-generics/const-fn-with-const-param.stderr b/src/test/ui/const-generics/const-fn-with-const-param.stderr
new file mode 100644
index 0000000..c0cd7ba
--- /dev/null
+++ b/src/test/ui/const-generics/const-fn-with-const-param.stderr
@@ -0,0 +1,17 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/const-fn-with-const-param.rs:1:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+
+error: const parameters are not permitted in `const fn`
+  --> $DIR/const-fn-with-const-param.rs:4:1
+   |
+LL | / const fn const_u32_identity<const X: u32>() -> u32 {
+LL | |
+LL | |     X
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/const-generics/const-param-before-other-params.rs b/src/test/ui/const-generics/const-param-before-other-params.rs
new file mode 100644
index 0000000..188b5dc
--- /dev/null
+++ b/src/test/ui/const-generics/const-param-before-other-params.rs
@@ -0,0 +1,12 @@
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+fn foo<const X: (), T>(_: &T) {
+    //~^ ERROR type parameters must be declared prior to const parameters
+}
+
+fn bar<const X: (), 'a>(_: &'a ()) {
+    //~^ ERROR lifetime parameters must be declared prior to const parameters
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/const-param-before-other-params.stderr b/src/test/ui/const-generics/const-param-before-other-params.stderr
new file mode 100644
index 0000000..78f129e
--- /dev/null
+++ b/src/test/ui/const-generics/const-param-before-other-params.stderr
@@ -0,0 +1,20 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/const-param-before-other-params.rs:1:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+
+error: type parameters must be declared prior to const parameters
+  --> $DIR/const-param-before-other-params.rs:4:21
+   |
+LL | fn foo<const X: (), T>(_: &T) {
+   |       --------------^- help: reorder the parameters: lifetimes, then types, then consts: `<T, const X: ()>`
+
+error: lifetime parameters must be declared prior to const parameters
+  --> $DIR/const-param-before-other-params.rs:8:21
+   |
+LL | fn bar<const X: (), 'a>(_: &'a ()) {
+   |       --------------^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, const X: ()>`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/const-generics/const-param-from-outer-fn.rs b/src/test/ui/const-generics/const-param-from-outer-fn.rs
new file mode 100644
index 0000000..6534bcf
--- /dev/null
+++ b/src/test/ui/const-generics/const-param-from-outer-fn.rs
@@ -0,0 +1,10 @@
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+fn foo<const X: u32>() {
+    fn bar() -> u32 {
+        X //~ ERROR can't use generic parameters from outer function
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/const-param-from-outer-fn.stderr b/src/test/ui/const-generics/const-param-from-outer-fn.stderr
new file mode 100644
index 0000000..e37b34f
--- /dev/null
+++ b/src/test/ui/const-generics/const-param-from-outer-fn.stderr
@@ -0,0 +1,19 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/const-param-from-outer-fn.rs:1:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+
+error[E0401]: can't use generic parameters from outer function
+  --> $DIR/const-param-from-outer-fn.rs:6:9
+   |
+LL | fn foo<const X: u32>() {
+   |              - const variable from outer function
+LL |     fn bar() -> u32 {
+   |        --- try adding a local generic parameter in this method instead
+LL |         X
+   |         ^ use of generic parameter from outer function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0401`.
diff --git a/src/test/ui/const-generics/const-parameter-uppercase-lint.rs b/src/test/ui/const-generics/const-parameter-uppercase-lint.rs
new file mode 100644
index 0000000..164205d
--- /dev/null
+++ b/src/test/ui/const-generics/const-parameter-uppercase-lint.rs
@@ -0,0 +1,10 @@
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+#![deny(non_upper_case_globals)]
+
+fn noop<const x: u32>() {
+    //~^ ERROR const parameter `x` should have an upper case name
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/const-parameter-uppercase-lint.stderr b/src/test/ui/const-generics/const-parameter-uppercase-lint.stderr
new file mode 100644
index 0000000..190798d
--- /dev/null
+++ b/src/test/ui/const-generics/const-parameter-uppercase-lint.stderr
@@ -0,0 +1,20 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/const-parameter-uppercase-lint.rs:1:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+
+error: const parameter `x` should have an upper case name
+  --> $DIR/const-parameter-uppercase-lint.rs:6:15
+   |
+LL | fn noop<const x: u32>() {
+   |               ^ help: convert the identifier to upper case: `X`
+   |
+note: lint level defined here
+  --> $DIR/const-parameter-uppercase-lint.rs:4:9
+   |
+LL | #![deny(non_upper_case_globals)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/const-generics/invalid-const-arg-for-type-param.rs b/src/test/ui/const-generics/invalid-const-arg-for-type-param.rs
new file mode 100644
index 0000000..b069cd8
--- /dev/null
+++ b/src/test/ui/const-generics/invalid-const-arg-for-type-param.rs
@@ -0,0 +1,9 @@
+use std::convert::TryInto;
+
+struct S;
+
+fn main() {
+    let _: u32 = 5i32.try_into::<32>().unwrap(); //~ ERROR wrong number of const arguments
+    S.f::<0>(); //~ ERROR no method named `f`
+    S::<0>; //~ ERROR  wrong number of const arguments
+}
diff --git a/src/test/ui/const-generics/invalid-const-arg-for-type-param.stderr b/src/test/ui/const-generics/invalid-const-arg-for-type-param.stderr
new file mode 100644
index 0000000..1bd9865
--- /dev/null
+++ b/src/test/ui/const-generics/invalid-const-arg-for-type-param.stderr
@@ -0,0 +1,25 @@
+error[E0107]: wrong number of const arguments: expected 0, found 1
+  --> $DIR/invalid-const-arg-for-type-param.rs:6:34
+   |
+LL |     let _: u32 = 5i32.try_into::<32>().unwrap();
+   |                                  ^^ unexpected const argument
+
+error[E0599]: no method named `f` found for type `S` in the current scope
+  --> $DIR/invalid-const-arg-for-type-param.rs:7:7
+   |
+LL | struct S;
+   | --------- method `f` not found for this
+...
+LL |     S.f::<0>();
+   |       ^
+
+error[E0107]: wrong number of const arguments: expected 0, found 1
+  --> $DIR/invalid-const-arg-for-type-param.rs:8:9
+   |
+LL |     S::<0>;
+   |         ^ unexpected const argument
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0107, E0599.
+For more information about an error, try `rustc --explain E0107`.
diff --git a/src/test/ui/const-generics/invalid-constant-in-args.rs b/src/test/ui/const-generics/invalid-constant-in-args.rs
new file mode 100644
index 0000000..40df237
--- /dev/null
+++ b/src/test/ui/const-generics/invalid-constant-in-args.rs
@@ -0,0 +1,3 @@
+fn main() {
+    let _: Vec<&str, "a"> = Vec::new(); //~ ERROR wrong number of const arguments
+}
diff --git a/src/test/ui/const-generics/invalid-constant-in-args.stderr b/src/test/ui/const-generics/invalid-constant-in-args.stderr
new file mode 100644
index 0000000..b9f874f
--- /dev/null
+++ b/src/test/ui/const-generics/invalid-constant-in-args.stderr
@@ -0,0 +1,9 @@
+error[E0107]: wrong number of const arguments: expected 0, found 1
+  --> $DIR/invalid-constant-in-args.rs:2:22
+   |
+LL |     let _: Vec<&str, "a"> = Vec::new();
+   |                      ^^^ unexpected const argument
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0107`.
diff --git a/src/test/ui/const-generics/struct-with-invalid-const-param.rs b/src/test/ui/const-generics/struct-with-invalid-const-param.rs
new file mode 100644
index 0000000..207b07b
--- /dev/null
+++ b/src/test/ui/const-generics/struct-with-invalid-const-param.rs
@@ -0,0 +1,6 @@
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+struct S<const C: u8>(C); //~ ERROR expected type, found const parameter
+
+fn main() {}
diff --git a/src/test/ui/const-generics/struct-with-invalid-const-param.stderr b/src/test/ui/const-generics/struct-with-invalid-const-param.stderr
new file mode 100644
index 0000000..561464b
--- /dev/null
+++ b/src/test/ui/const-generics/struct-with-invalid-const-param.stderr
@@ -0,0 +1,15 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/struct-with-invalid-const-param.rs:1:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+
+error[E0573]: expected type, found const parameter `C`
+  --> $DIR/struct-with-invalid-const-param.rs:4:23
+   |
+LL | struct S<const C: u8>(C);
+   |                       ^ help: a struct with a similar name exists: `S`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0573`.
diff --git a/src/test/ui/constructor-lifetime-args.rs b/src/test/ui/constructor-lifetime-args.rs
new file mode 100644
index 0000000..6af5f6d
--- /dev/null
+++ b/src/test/ui/constructor-lifetime-args.rs
@@ -0,0 +1,26 @@
+// All lifetime parameters in struct constructors are currently considered early bound,
+// i.e., `S::<ARGS>` is interpreted kinda like an associated item `S::<ARGS>::ctor`.
+// This behavior is a bit weird, because if equivalent constructor were written manually
+// it would get late bound lifetime parameters.
+// Variant constructors behave in the same way, lifetime parameters are considered
+// belonging to the enum and being early bound.
+// https://github.com/rust-lang/rust/issues/30904
+
+struct S<'a, 'b>(&'a u8, &'b u8);
+enum E<'a, 'b> {
+    V(&'a u8),
+    U(&'b u8),
+}
+
+fn main() {
+    S(&0, &0); // OK
+    S::<'static>(&0, &0);
+    //~^ ERROR wrong number of lifetime arguments: expected 2, found 1
+    S::<'static, 'static, 'static>(&0, &0);
+    //~^ ERROR wrong number of lifetime arguments: expected 2, found 3
+    E::V(&0); // OK
+    E::V::<'static>(&0);
+    //~^ ERROR wrong number of lifetime arguments: expected 2, found 1
+    E::V::<'static, 'static, 'static>(&0);
+    //~^ ERROR wrong number of lifetime arguments: expected 2, found 3
+}
diff --git a/src/test/ui/constructor-lifetime-args.stderr b/src/test/ui/constructor-lifetime-args.stderr
new file mode 100644
index 0000000..ec8ed92
--- /dev/null
+++ b/src/test/ui/constructor-lifetime-args.stderr
@@ -0,0 +1,27 @@
+error[E0107]: wrong number of lifetime arguments: expected 2, found 1
+  --> $DIR/constructor-lifetime-args.rs:17:5
+   |
+LL |     S::<'static>(&0, &0);
+   |     ^^^^^^^^^^^^ expected 2 lifetime arguments
+
+error[E0107]: wrong number of lifetime arguments: expected 2, found 3
+  --> $DIR/constructor-lifetime-args.rs:19:27
+   |
+LL |     S::<'static, 'static, 'static>(&0, &0);
+   |                           ^^^^^^^ unexpected lifetime argument
+
+error[E0107]: wrong number of lifetime arguments: expected 2, found 1
+  --> $DIR/constructor-lifetime-args.rs:22:5
+   |
+LL |     E::V::<'static>(&0);
+   |     ^^^^^^^^^^^^^^^ expected 2 lifetime arguments
+
+error[E0107]: wrong number of lifetime arguments: expected 2, found 3
+  --> $DIR/constructor-lifetime-args.rs:24:30
+   |
+LL |     E::V::<'static, 'static, 'static>(&0);
+   |                              ^^^^^^^ unexpected lifetime argument
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0107`.
diff --git a/src/test/ui/consts/auxiliary/const_fn_lib.rs b/src/test/ui/consts/auxiliary/const_fn_lib.rs
new file mode 100644
index 0000000..85714ef
--- /dev/null
+++ b/src/test/ui/consts/auxiliary/const_fn_lib.rs
@@ -0,0 +1,23 @@
+// Crate that exports a const fn. Used for testing cross-crate.
+
+#![feature(const_fn)]
+#![crate_type="rlib"]
+
+pub const fn foo() -> usize { 22 }
+
+pub const fn bar() -> fn() {
+    fn x() {}
+    x
+}
+
+#[inline]
+pub const fn bar_inlined() -> fn() {
+    fn x() {}
+    x
+}
+
+#[inline(always)]
+pub const fn bar_inlined_always() -> fn() {
+    fn x() {}
+    x
+}
diff --git a/src/test/ui/consts/auxiliary/promotable_const_fn_lib.rs b/src/test/ui/consts/auxiliary/promotable_const_fn_lib.rs
new file mode 100644
index 0000000..e54cbb0
--- /dev/null
+++ b/src/test/ui/consts/auxiliary/promotable_const_fn_lib.rs
@@ -0,0 +1,21 @@
+// Crate that exports a const fn. Used for testing cross-crate.
+
+#![feature(staged_api, rustc_attrs)]
+#![stable(since="1.0.0", feature = "mep")]
+
+#![crate_type="rlib"]
+
+#[rustc_promotable]
+#[stable(since="1.0.0", feature = "mep")]
+#[inline]
+pub const fn foo() -> usize { 22 }
+
+#[stable(since="1.0.0", feature = "mep")]
+pub struct Foo(usize);
+
+impl Foo {
+    #[stable(since="1.0.0", feature = "mep")]
+    #[inline]
+    #[rustc_promotable]
+    pub const fn foo() -> usize { 22 }
+}
diff --git a/src/test/ui/consts/const-array-oob-arith.rs b/src/test/ui/consts/const-array-oob-arith.rs
new file mode 100644
index 0000000..2f9b30b
--- /dev/null
+++ b/src/test/ui/consts/const-array-oob-arith.rs
@@ -0,0 +1,12 @@
+#![feature(const_indexing)]
+
+const ARR: [i32; 6] = [42, 43, 44, 45, 46, 47];
+const IDX: usize = 3;
+const VAL: i32 = ARR[IDX];
+const BONG: [i32; (ARR[0] - 41) as usize] = [5];
+const BLUB: [i32; (ARR[0] - 40) as usize] = [5]; //~ ERROR: mismatched types
+const BOO: [i32; (ARR[0] - 41) as usize] = [5, 99]; //~ ERROR: mismatched types
+
+fn main() {
+    let _ = VAL;
+}
diff --git a/src/test/ui/consts/const-array-oob-arith.stderr b/src/test/ui/consts/const-array-oob-arith.stderr
new file mode 100644
index 0000000..00286b0
--- /dev/null
+++ b/src/test/ui/consts/const-array-oob-arith.stderr
@@ -0,0 +1,21 @@
+error[E0308]: mismatched types
+  --> $DIR/const-array-oob-arith.rs:7:45
+   |
+LL | const BLUB: [i32; (ARR[0] - 40) as usize] = [5];
+   |                                             ^^^ expected an array with a fixed size of 2 elements, found one with 1 elements
+   |
+   = note: expected type `[i32; 2]`
+              found type `[i32; 1]`
+
+error[E0308]: mismatched types
+  --> $DIR/const-array-oob-arith.rs:8:44
+   |
+LL | const BOO: [i32; (ARR[0] - 41) as usize] = [5, 99];
+   |                                            ^^^^^^^ expected an array with a fixed size of 1 elements, found one with 2 elements
+   |
+   = note: expected type `[i32; 1]`
+              found type `[i32; 2]`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/consts/const-array-oob.rs b/src/test/ui/consts/const-array-oob.rs
new file mode 100644
index 0000000..39ef451
--- /dev/null
+++ b/src/test/ui/consts/const-array-oob.rs
@@ -0,0 +1,14 @@
+// ignore-tidy-linelength
+
+#![feature(const_indexing)]
+
+const FOO: [usize; 3] = [1, 2, 3];
+const BAR: usize = FOO[5]; // no error, because the error below occurs before regular const eval
+
+const BLUB: [u32; FOO[4]] = [5, 6];
+//~^ ERROR evaluation of constant value failed [E0080]
+//~| index out of bounds: the len is 3 but the index is 4
+
+fn main() {
+    let _ = BAR;
+}
diff --git a/src/test/ui/consts/const-array-oob.stderr b/src/test/ui/consts/const-array-oob.stderr
new file mode 100644
index 0000000..2d9a4fd
--- /dev/null
+++ b/src/test/ui/consts/const-array-oob.stderr
@@ -0,0 +1,9 @@
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-array-oob.rs:8:19
+   |
+LL | const BLUB: [u32; FOO[4]] = [5, 6];
+   |                   ^^^^^^ index out of bounds: the len is 3 but the index is 4
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-block-non-item-statement.rs b/src/test/ui/consts/const-block-non-item-statement.rs
new file mode 100644
index 0000000..5ecf9a0
--- /dev/null
+++ b/src/test/ui/consts/const-block-non-item-statement.rs
@@ -0,0 +1,23 @@
+// compile-pass
+
+enum Foo {
+    Bar = { let x = 1; 3 }
+}
+
+
+const A: usize = { 1; 2 };
+
+const B: usize = { { } 2 };
+
+macro_rules! foo {
+    () => (())
+}
+
+const C: usize = { foo!(); 2 };
+
+const D: usize = { let x = 4; 2 };
+
+type Array = [u32; {  let x = 2; 5 }];
+type Array2 = [u32; { let mut x = 2; x = 3; x}];
+
+pub fn main() {}
diff --git a/src/test/ui/consts/const-call.rs b/src/test/ui/consts/const-call.rs
new file mode 100644
index 0000000..3d5b64e
--- /dev/null
+++ b/src/test/ui/consts/const-call.rs
@@ -0,0 +1,9 @@
+fn f(x: usize) -> usize {
+    x
+}
+
+fn main() {
+    let _ = [0; f(2)];
+    //~^ ERROR calls in constants are limited to constant functions
+    //~| ERROR evaluation of constant value failed
+}
diff --git a/src/test/ui/consts/const-call.stderr b/src/test/ui/consts/const-call.stderr
new file mode 100644
index 0000000..12a6983
--- /dev/null
+++ b/src/test/ui/consts/const-call.stderr
@@ -0,0 +1,16 @@
+error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
+  --> $DIR/const-call.rs:6:17
+   |
+LL |     let _ = [0; f(2)];
+   |                 ^^^^
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-call.rs:6:17
+   |
+LL |     let _ = [0; f(2)];
+   |                 ^^^^ calling non-const function `f`
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0015, E0080.
+For more information about an error, try `rustc --explain E0015`.
diff --git a/src/test/ui/consts/const-cast-different-types.rs b/src/test/ui/consts/const-cast-different-types.rs
new file mode 100644
index 0000000..3bd5ed8
--- /dev/null
+++ b/src/test/ui/consts/const-cast-different-types.rs
@@ -0,0 +1,6 @@
+static a: &'static str = "foo";
+static b: *const u8 = a as *const u8; //~ ERROR casting
+static c: *const u8 = &a as *const u8; //~ ERROR casting
+
+fn main() {
+}
diff --git a/src/test/ui/consts/const-cast-different-types.stderr b/src/test/ui/consts/const-cast-different-types.stderr
new file mode 100644
index 0000000..9960ccb
--- /dev/null
+++ b/src/test/ui/consts/const-cast-different-types.stderr
@@ -0,0 +1,15 @@
+error[E0606]: casting `&'static str` as `*const u8` is invalid
+  --> $DIR/const-cast-different-types.rs:2:23
+   |
+LL | static b: *const u8 = a as *const u8;
+   |                       ^^^^^^^^^^^^^^
+
+error[E0606]: casting `&&'static str` as `*const u8` is invalid
+  --> $DIR/const-cast-different-types.rs:3:23
+   |
+LL | static c: *const u8 = &a as *const u8;
+   |                       ^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0606`.
diff --git a/src/test/ui/consts/const-cast-wrong-type.rs b/src/test/ui/consts/const-cast-wrong-type.rs
new file mode 100644
index 0000000..c250cc5
--- /dev/null
+++ b/src/test/ui/consts/const-cast-wrong-type.rs
@@ -0,0 +1,5 @@
+static a: [u8; 3] = ['h' as u8, 'i' as u8, 0 as u8];
+static b: *const i8 = &a as *const i8; //~ ERROR mismatched types
+
+fn main() {
+}
diff --git a/src/test/ui/consts/const-cast-wrong-type.stderr b/src/test/ui/consts/const-cast-wrong-type.stderr
new file mode 100644
index 0000000..ad816d9
--- /dev/null
+++ b/src/test/ui/consts/const-cast-wrong-type.stderr
@@ -0,0 +1,9 @@
+error[E0308]: mismatched types
+  --> $DIR/const-cast-wrong-type.rs:2:23
+   |
+LL | static b: *const i8 = &a as *const i8;
+   |                       ^^^^^^^^^^^^^^^ expected u8, found i8
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/consts/const-deref-ptr.rs b/src/test/ui/consts/const-deref-ptr.rs
new file mode 100644
index 0000000..b5f603b
--- /dev/null
+++ b/src/test/ui/consts/const-deref-ptr.rs
@@ -0,0 +1,7 @@
+// Check that you can't dereference raw pointers in constants.
+
+fn main() {
+    static C: u64 = unsafe {*(0xdeadbeef as *const u64)};
+    //~^ ERROR dereferencing raw pointers in statics is unstable
+    println!("{}", C);
+}
diff --git a/src/test/ui/consts/const-deref-ptr.stderr b/src/test/ui/consts/const-deref-ptr.stderr
new file mode 100644
index 0000000..8de0f6c
--- /dev/null
+++ b/src/test/ui/consts/const-deref-ptr.stderr
@@ -0,0 +1,11 @@
+error[E0658]: dereferencing raw pointers in statics is unstable (see issue #51911)
+  --> $DIR/const-deref-ptr.rs:4:29
+   |
+LL |     static C: u64 = unsafe {*(0xdeadbeef as *const u64)};
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/consts/const-err-early.rs b/src/test/ui/consts/const-err-early.rs
new file mode 100644
index 0000000..bae2cd2
--- /dev/null
+++ b/src/test/ui/consts/const-err-early.rs
@@ -0,0 +1,16 @@
+#![deny(const_err)]
+
+pub const A: i8 = -std::i8::MIN; //~ ERROR const_err
+pub const B: u8 = 200u8 + 200u8; //~ ERROR const_err
+pub const C: u8 = 200u8 * 4; //~ ERROR const_err
+pub const D: u8 = 42u8 - (42u8 + 1); //~ ERROR const_err
+pub const E: u8 = [5u8][1]; //~ ERROR const_err
+
+fn main() {
+    let _a = A;
+    let _b = B;
+    let _c = C;
+    let _d = D;
+    let _e = E;
+    let _e = [6u8][1];
+}
diff --git a/src/test/ui/consts/const-err-early.stderr b/src/test/ui/consts/const-err-early.stderr
new file mode 100644
index 0000000..9b0ef94
--- /dev/null
+++ b/src/test/ui/consts/const-err-early.stderr
@@ -0,0 +1,48 @@
+error: any use of this value will cause an error
+  --> $DIR/const-err-early.rs:3:19
+   |
+LL | pub const A: i8 = -std::i8::MIN;
+   | ------------------^^^^^^^^^^^^^-
+   |                   |
+   |                   attempt to negate with overflow
+   |
+note: lint level defined here
+  --> $DIR/const-err-early.rs:1:9
+   |
+LL | #![deny(const_err)]
+   |         ^^^^^^^^^
+
+error: any use of this value will cause an error
+  --> $DIR/const-err-early.rs:4:19
+   |
+LL | pub const B: u8 = 200u8 + 200u8;
+   | ------------------^^^^^^^^^^^^^-
+   |                   |
+   |                   attempt to add with overflow
+
+error: any use of this value will cause an error
+  --> $DIR/const-err-early.rs:5:19
+   |
+LL | pub const C: u8 = 200u8 * 4;
+   | ------------------^^^^^^^^^-
+   |                   |
+   |                   attempt to multiply with overflow
+
+error: any use of this value will cause an error
+  --> $DIR/const-err-early.rs:6:19
+   |
+LL | pub const D: u8 = 42u8 - (42u8 + 1);
+   | ------------------^^^^^^^^^^^^^^^^^-
+   |                   |
+   |                   attempt to subtract with overflow
+
+error: any use of this value will cause an error
+  --> $DIR/const-err-early.rs:7:19
+   |
+LL | pub const E: u8 = [5u8][1];
+   | ------------------^^^^^^^^-
+   |                   |
+   |                   index out of bounds: the len is 1 but the index is 1
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/ui/consts/const-err-multi.rs b/src/test/ui/consts/const-err-multi.rs
new file mode 100644
index 0000000..fa3ad83
--- /dev/null
+++ b/src/test/ui/consts/const-err-multi.rs
@@ -0,0 +1,14 @@
+#![deny(const_err)]
+
+pub const A: i8 = -std::i8::MIN;
+//~^ ERROR const_err
+pub const B: i8 = A;
+//~^ ERROR const_err
+pub const C: u8 = A as u8;
+//~^ ERROR const_err
+pub const D: i8 = 50 - A;
+//~^ ERROR const_err
+
+fn main() {
+    let _ = (A, B, C, D);
+}
diff --git a/src/test/ui/consts/const-err-multi.stderr b/src/test/ui/consts/const-err-multi.stderr
new file mode 100644
index 0000000..c647f13
--- /dev/null
+++ b/src/test/ui/consts/const-err-multi.stderr
@@ -0,0 +1,40 @@
+error: any use of this value will cause an error
+  --> $DIR/const-err-multi.rs:3:19
+   |
+LL | pub const A: i8 = -std::i8::MIN;
+   | ------------------^^^^^^^^^^^^^-
+   |                   |
+   |                   attempt to negate with overflow
+   |
+note: lint level defined here
+  --> $DIR/const-err-multi.rs:1:9
+   |
+LL | #![deny(const_err)]
+   |         ^^^^^^^^^
+
+error: any use of this value will cause an error
+  --> $DIR/const-err-multi.rs:5:19
+   |
+LL | pub const B: i8 = A;
+   | ------------------^-
+   |                   |
+   |                   referenced constant has errors
+
+error: any use of this value will cause an error
+  --> $DIR/const-err-multi.rs:7:19
+   |
+LL | pub const C: u8 = A as u8;
+   | ------------------^^^^^^^-
+   |                   |
+   |                   referenced constant has errors
+
+error: any use of this value will cause an error
+  --> $DIR/const-err-multi.rs:9:19
+   |
+LL | pub const D: i8 = 50 - A;
+   | ------------------^^^^^^-
+   |                   |
+   |                   referenced constant has errors
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/consts/const-err.rs b/src/test/ui/consts/const-err.rs
new file mode 100644
index 0000000..8cc3dc7
--- /dev/null
+++ b/src/test/ui/consts/const-err.rs
@@ -0,0 +1,16 @@
+// compile-flags: -Zforce-overflow-checks=on
+
+#![allow(exceeding_bitshifts)]
+#![warn(const_err)]
+
+fn black_box<T>(_: T) {
+    unimplemented!()
+}
+
+const FOO: u8 = [5u8][1];
+//~^ WARN any use of this value will cause an error
+
+fn main() {
+    black_box((FOO, FOO));
+    //~^ ERROR erroneous constant used
+}
diff --git a/src/test/ui/consts/const-err.stderr b/src/test/ui/consts/const-err.stderr
new file mode 100644
index 0000000..0ee9ecd
--- /dev/null
+++ b/src/test/ui/consts/const-err.stderr
@@ -0,0 +1,23 @@
+warning: any use of this value will cause an error
+  --> $DIR/const-err.rs:10:17
+   |
+LL | const FOO: u8 = [5u8][1];
+   | ----------------^^^^^^^^-
+   |                 |
+   |                 index out of bounds: the len is 1 but the index is 1
+   |
+note: lint level defined here
+  --> $DIR/const-err.rs:4:9
+   |
+LL | #![warn(const_err)]
+   |         ^^^^^^^^^
+
+error[E0080]: erroneous constant used
+  --> $DIR/const-err.rs:14:15
+   |
+LL |     black_box((FOO, FOO));
+   |               ^^^^^^^^^^ referenced constant has errors
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-err2.rs b/src/test/ui/consts/const-err2.rs
new file mode 100644
index 0000000..a5f685a
--- /dev/null
+++ b/src/test/ui/consts/const-err2.rs
@@ -0,0 +1,29 @@
+// needed because negating int::MIN will behave differently between
+// optimized compilation and unoptimized compilation and thus would
+// lead to different lints being emitted
+// compile-flags: -O
+
+#![feature(rustc_attrs)]
+#![allow(exceeding_bitshifts)]
+#![deny(const_err)]
+
+fn black_box<T>(_: T) {
+    unimplemented!()
+}
+
+fn main() {
+    let a = -std::i8::MIN;
+    //~^ ERROR const_err
+    let b = 200u8 + 200u8 + 200u8;
+    //~^ ERROR const_err
+    let c = 200u8 * 4;
+    //~^ ERROR const_err
+    let d = 42u8 - (42u8 + 1);
+    //~^ ERROR const_err
+    let _e = [5u8][1];
+    //~^ ERROR const_err
+    black_box(a);
+    black_box(b);
+    black_box(c);
+    black_box(d);
+}
diff --git a/src/test/ui/consts/const-err2.stderr b/src/test/ui/consts/const-err2.stderr
new file mode 100644
index 0000000..659c3af
--- /dev/null
+++ b/src/test/ui/consts/const-err2.stderr
@@ -0,0 +1,38 @@
+error: this expression will panic at runtime
+  --> $DIR/const-err2.rs:15:13
+   |
+LL |     let a = -std::i8::MIN;
+   |             ^^^^^^^^^^^^^ attempt to negate with overflow
+   |
+note: lint level defined here
+  --> $DIR/const-err2.rs:8:9
+   |
+LL | #![deny(const_err)]
+   |         ^^^^^^^^^
+
+error: this expression will panic at runtime
+  --> $DIR/const-err2.rs:17:13
+   |
+LL |     let b = 200u8 + 200u8 + 200u8;
+   |             ^^^^^^^^^^^^^ attempt to add with overflow
+
+error: this expression will panic at runtime
+  --> $DIR/const-err2.rs:19:13
+   |
+LL |     let c = 200u8 * 4;
+   |             ^^^^^^^^^ attempt to multiply with overflow
+
+error: this expression will panic at runtime
+  --> $DIR/const-err2.rs:21:13
+   |
+LL |     let d = 42u8 - (42u8 + 1);
+   |             ^^^^^^^^^^^^^^^^^ attempt to subtract with overflow
+
+error: index out of bounds: the len is 1 but the index is 1
+  --> $DIR/const-err2.rs:23:14
+   |
+LL |     let _e = [5u8][1];
+   |              ^^^^^^^^
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/ui/consts/const-err4.rs b/src/test/ui/consts/const-err4.rs
new file mode 100644
index 0000000..70d9bc1
--- /dev/null
+++ b/src/test/ui/consts/const-err4.rs
@@ -0,0 +1,14 @@
+#[derive(Copy, Clone)]
+union Foo {
+    a: isize,
+    b: (),
+}
+
+enum Bar {
+    Boo = [unsafe { Foo { b: () }.a }; 4][3],
+    //~^ ERROR it is undefined behavior to use this value
+}
+
+fn main() {
+    assert_ne!(Bar::Boo as isize, 0);
+}
diff --git a/src/test/ui/consts/const-err4.stderr b/src/test/ui/consts/const-err4.stderr
new file mode 100644
index 0000000..1feec3c
--- /dev/null
+++ b/src/test/ui/consts/const-err4.stderr
@@ -0,0 +1,11 @@
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/const-err4.rs:8:11
+   |
+LL |     Boo = [unsafe { Foo { b: () }.a }; 4][3],
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected initialized plain (non-pointer) bytes
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.rs b/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.rs
new file mode 100644
index 0000000..4d3c714
--- /dev/null
+++ b/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.rs
@@ -0,0 +1,19 @@
+// New test for #53818: modifying static memory at compile-time is not allowed.
+// The test should never compile successfully
+
+#![feature(const_raw_ptr_deref)]
+
+use std::cell::UnsafeCell;
+
+struct Foo(UnsafeCell<u32>);
+
+unsafe impl Send for Foo {}
+unsafe impl Sync for Foo {}
+
+static FOO: Foo = Foo(UnsafeCell::new(42));
+
+static BAR: () = unsafe {
+    *FOO.0.get() = 5; //~ ERROR contains unimplemented expression type
+};
+
+fn main() {}
diff --git a/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.stderr b/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.stderr
new file mode 100644
index 0000000..148b121
--- /dev/null
+++ b/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.stderr
@@ -0,0 +1,9 @@
+error[E0019]: static contains unimplemented expression type
+  --> $DIR/assign-to-static-within-other-static-2.rs:16:5
+   |
+LL |     *FOO.0.get() = 5;
+   |     ^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0019`.
diff --git a/src/test/ui/consts/const-eval/assign-to-static-within-other-static.rs b/src/test/ui/consts/const-eval/assign-to-static-within-other-static.rs
new file mode 100644
index 0000000..b4c416b
--- /dev/null
+++ b/src/test/ui/consts/const-eval/assign-to-static-within-other-static.rs
@@ -0,0 +1,13 @@
+// New test for #53818: modifying static memory at compile-time is not allowed.
+// The test should never compile successfully
+
+#![feature(const_raw_ptr_deref)]
+
+use std::cell::UnsafeCell;
+
+static mut FOO: u32 = 42;
+static BOO: () = unsafe {
+    FOO = 5; //~ ERROR cannot mutate statics in the initializer of another static
+};
+
+fn main() {}
diff --git a/src/test/ui/consts/const-eval/assign-to-static-within-other-static.stderr b/src/test/ui/consts/const-eval/assign-to-static-within-other-static.stderr
new file mode 100644
index 0000000..02b7276
--- /dev/null
+++ b/src/test/ui/consts/const-eval/assign-to-static-within-other-static.stderr
@@ -0,0 +1,8 @@
+error: cannot mutate statics in the initializer of another static
+  --> $DIR/assign-to-static-within-other-static.rs:10:5
+   |
+LL |     FOO = 5;
+   |     ^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/consts/const-eval/auxiliary/stability.rs b/src/test/ui/consts/const-eval/auxiliary/stability.rs
new file mode 100644
index 0000000..5551d35
--- /dev/null
+++ b/src/test/ui/consts/const-eval/auxiliary/stability.rs
@@ -0,0 +1,11 @@
+// Crate that exports a const fn. Used for testing cross-crate.
+
+#![crate_type="rlib"]
+#![stable(feature = "rust1", since = "1.0.0")]
+
+#![feature(rustc_const_unstable, const_fn)]
+#![feature(staged_api)]
+
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_const_unstable(feature="foo")]
+pub const fn foo() -> u32 { 42 }
diff --git a/src/test/ui/consts/const-eval/conditional_array_execution.rs b/src/test/ui/consts/const-eval/conditional_array_execution.rs
new file mode 100644
index 0000000..12e51c2
--- /dev/null
+++ b/src/test/ui/consts/const-eval/conditional_array_execution.rs
@@ -0,0 +1,11 @@
+#![warn(const_err)]
+
+const X: u32 = 5;
+const Y: u32 = 6;
+const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
+//~^ WARN any use of this value will cause an error
+
+fn main() {
+    println!("{}", FOO);
+    //~^ ERROR
+}
diff --git a/src/test/ui/consts/const-eval/conditional_array_execution.stderr b/src/test/ui/consts/const-eval/conditional_array_execution.stderr
new file mode 100644
index 0000000..7f94d84
--- /dev/null
+++ b/src/test/ui/consts/const-eval/conditional_array_execution.stderr
@@ -0,0 +1,23 @@
+warning: any use of this value will cause an error
+  --> $DIR/conditional_array_execution.rs:5:19
+   |
+LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
+   | ------------------^^^^^---------------------------
+   |                   |
+   |                   attempt to subtract with overflow
+   |
+note: lint level defined here
+  --> $DIR/conditional_array_execution.rs:1:9
+   |
+LL | #![warn(const_err)]
+   |         ^^^^^^^^^
+
+error[E0080]: evaluation of constant expression failed
+  --> $DIR/conditional_array_execution.rs:9:20
+   |
+LL |     println!("{}", FOO);
+   |                    ^^^ referenced constant has errors
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/const-eval-overflow-2.rs b/src/test/ui/consts/const-eval/const-eval-overflow-2.rs
new file mode 100644
index 0000000..9369702
--- /dev/null
+++ b/src/test/ui/consts/const-eval/const-eval-overflow-2.rs
@@ -0,0 +1,19 @@
+// Evaluation of constants in refutable patterns goes through
+// different compiler control-flow paths.
+
+#![allow(unused_imports, warnings, const_err)]
+
+use std::fmt;
+use std::{i8, i16, i32, i64, isize};
+use std::{u8, u16, u32, u64, usize};
+
+const NEG_128: i8 = -128;
+const NEG_NEG_128: i8 = -NEG_128;
+
+fn main() {
+    match -128i8 {
+        NEG_NEG_128 => println!("A"),
+        //~^ ERROR could not evaluate constant pattern
+        _ => println!("B"),
+    }
+}
diff --git a/src/test/ui/consts/const-eval/const-eval-overflow-2.stderr b/src/test/ui/consts/const-eval/const-eval-overflow-2.stderr
new file mode 100644
index 0000000..13f00c4
--- /dev/null
+++ b/src/test/ui/consts/const-eval/const-eval-overflow-2.stderr
@@ -0,0 +1,8 @@
+error: could not evaluate constant pattern
+  --> $DIR/const-eval-overflow-2.rs:15:9
+   |
+LL |         NEG_NEG_128 => println!("A"),
+   |         ^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/consts/const-eval/const-eval-overflow-3.rs b/src/test/ui/consts/const-eval/const-eval-overflow-3.rs
new file mode 100644
index 0000000..6fd8e9c
--- /dev/null
+++ b/src/test/ui/consts/const-eval/const-eval-overflow-3.rs
@@ -0,0 +1,29 @@
+// Evaluation of constants in array-elem count goes through different
+// compiler control-flow paths.
+//
+// This test is checking the count in an array expression.
+
+
+
+
+
+
+
+#![allow(unused_imports)]
+
+use std::fmt;
+use std::{i8, i16, i32, i64, isize};
+use std::{u8, u16, u32, u64, usize};
+
+const A_I8_I
+    : [u32; (i8::MAX as usize) + 1]
+    = [0; (i8::MAX + 1) as usize];
+//~^ ERROR evaluation of constant value failed
+
+fn main() {
+    foo(&A_I8_I[..]);
+}
+
+fn foo<T:fmt::Debug>(x: T) {
+    println!("{:?}", x);
+}
diff --git a/src/test/ui/consts/const-eval/const-eval-overflow-3.stderr b/src/test/ui/consts/const-eval/const-eval-overflow-3.stderr
new file mode 100644
index 0000000..2c5b460
--- /dev/null
+++ b/src/test/ui/consts/const-eval/const-eval-overflow-3.stderr
@@ -0,0 +1,9 @@
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-eval-overflow-3.rs:20:11
+   |
+LL |     = [0; (i8::MAX + 1) as usize];
+   |           ^^^^^^^^^^^^^ attempt to add with overflow
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/const-eval-overflow-3b.rs b/src/test/ui/consts/const-eval/const-eval-overflow-3b.rs
new file mode 100644
index 0000000..d9b0637
--- /dev/null
+++ b/src/test/ui/consts/const-eval/const-eval-overflow-3b.rs
@@ -0,0 +1,35 @@
+// Evaluation of constants in array-elem count goes through different
+// compiler control-flow paths.
+//
+// This test is checking the count in an array expression.
+//
+// This is a variation of another such test, but in this case the
+// types for the left- and right-hand sides of the addition do not
+// match (as well as overflow).
+
+
+
+
+
+
+
+#![allow(unused_imports)]
+
+use std::fmt;
+use std::{i8, i16, i32, i64, isize};
+use std::{u8, u16, u32, u64, usize};
+
+const A_I8_I
+    : [u32; (i8::MAX as usize) + 1]
+    = [0; (i8::MAX + 1u8) as usize];
+//~^ ERROR mismatched types
+//~| ERROR cannot add `u8` to `i8`
+
+fn main() {
+    foo(&A_I8_I[..]);
+}
+
+fn foo<T:fmt::Debug>(x: T) {
+    println!("{:?}", x);
+}
+
diff --git a/src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr b/src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr
new file mode 100644
index 0000000..59a9d25
--- /dev/null
+++ b/src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr
@@ -0,0 +1,18 @@
+error[E0308]: mismatched types
+  --> $DIR/const-eval-overflow-3b.rs:24:22
+   |
+LL |     = [0; (i8::MAX + 1u8) as usize];
+   |                      ^^^ expected i8, found u8
+
+error[E0277]: cannot add `u8` to `i8`
+  --> $DIR/const-eval-overflow-3b.rs:24:20
+   |
+LL |     = [0; (i8::MAX + 1u8) as usize];
+   |                    ^ no implementation for `i8 + u8`
+   |
+   = help: the trait `std::ops::Add<u8>` is not implemented for `i8`
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0277, E0308.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/consts/const-eval/const-eval-overflow-4.rs b/src/test/ui/consts/const-eval/const-eval-overflow-4.rs
new file mode 100644
index 0000000..0b12a43
--- /dev/null
+++ b/src/test/ui/consts/const-eval/const-eval-overflow-4.rs
@@ -0,0 +1,23 @@
+// Evaluation of constants in array-elem count goes through different
+// compiler control-flow paths.
+//
+// This test is checking the count in an array type.
+
+#![allow(unused_imports)]
+
+use std::fmt;
+use std::{i8, i16, i32, i64, isize};
+use std::{u8, u16, u32, u64, usize};
+
+const A_I8_T
+    : [u32; (i8::MAX as i8 + 1i8) as usize]
+    //~^ ERROR evaluation of constant value failed
+    = [0; (i8::MAX as usize) + 1];
+
+fn main() {
+    foo(&A_I8_T[..]);
+}
+
+fn foo<T:fmt::Debug>(x: T) {
+    println!("{:?}", x);
+}
diff --git a/src/test/ui/consts/const-eval/const-eval-overflow-4.stderr b/src/test/ui/consts/const-eval/const-eval-overflow-4.stderr
new file mode 100644
index 0000000..fe7db23
--- /dev/null
+++ b/src/test/ui/consts/const-eval/const-eval-overflow-4.stderr
@@ -0,0 +1,9 @@
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-eval-overflow-4.rs:13:13
+   |
+LL |     : [u32; (i8::MAX as i8 + 1i8) as usize]
+   |             ^^^^^^^^^^^^^^^^^^^^^ attempt to add with overflow
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/const-eval-overflow-4b.rs b/src/test/ui/consts/const-eval/const-eval-overflow-4b.rs
new file mode 100644
index 0000000..75c396f
--- /dev/null
+++ b/src/test/ui/consts/const-eval/const-eval-overflow-4b.rs
@@ -0,0 +1,29 @@
+// Evaluation of constants in array-elem count goes through different
+// compiler control-flow paths.
+//
+// This test is checking the count in an array type.
+
+#![allow(unused_imports)]
+
+use std::{i8, i16, i32, i64, isize};
+use std::{u8, u16, u32, u64, usize};
+
+const A_I8_T
+    : [u32; (i8::MAX as i8 + 1u8) as usize]
+    //~^ ERROR mismatched types
+    //~| expected i8, found u8
+    //~| ERROR cannot add `u8` to `i8`
+    = [0; (i8::MAX as usize) + 1];
+
+
+const A_CHAR_USIZE
+    : [u32; 5u8 as char as usize]
+    = [0; 5];
+
+
+const A_BAD_CHAR_USIZE
+    : [u32; 5i8 as char as usize]
+    //~^ ERROR only `u8` can be cast as `char`, not `i8`
+    = [0; 5];
+
+fn main() {}
diff --git a/src/test/ui/consts/const-eval/const-eval-overflow-4b.stderr b/src/test/ui/consts/const-eval/const-eval-overflow-4b.stderr
new file mode 100644
index 0000000..0c2f76a5
--- /dev/null
+++ b/src/test/ui/consts/const-eval/const-eval-overflow-4b.stderr
@@ -0,0 +1,24 @@
+error[E0308]: mismatched types
+  --> $DIR/const-eval-overflow-4b.rs:12:30
+   |
+LL |     : [u32; (i8::MAX as i8 + 1u8) as usize]
+   |                              ^^^ expected i8, found u8
+
+error[E0277]: cannot add `u8` to `i8`
+  --> $DIR/const-eval-overflow-4b.rs:12:28
+   |
+LL |     : [u32; (i8::MAX as i8 + 1u8) as usize]
+   |                            ^ no implementation for `i8 + u8`
+   |
+   = help: the trait `std::ops::Add<u8>` is not implemented for `i8`
+
+error[E0604]: only `u8` can be cast as `char`, not `i8`
+  --> $DIR/const-eval-overflow-4b.rs:25:13
+   |
+LL |     : [u32; 5i8 as char as usize]
+   |             ^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0277, E0308, E0604.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/consts/const-eval/const-eval-overflow2.rs b/src/test/ui/consts/const-eval/const-eval-overflow2.rs
new file mode 100644
index 0000000..a0dbcc8
--- /dev/null
+++ b/src/test/ui/consts/const-eval/const-eval-overflow2.rs
@@ -0,0 +1,73 @@
+#![allow(unused_imports)]
+
+// Note: the relevant lint pass here runs before some of the constant
+// evaluation below (e.g., that performed by codegen and llvm), so if you
+// change this warn to a deny, then the compiler will exit before
+// those errors are detected.
+
+#![deny(const_err)]
+
+use std::fmt;
+use std::{i8, i16, i32, i64, isize};
+use std::{u8, u16, u32, u64, usize};
+
+const VALS_I8: (i8,) =
+    (
+     i8::MIN - 1,
+     );
+ //~^^ ERROR any use of this value will cause an error
+
+const VALS_I16: (i16,) =
+    (
+     i16::MIN - 1,
+     );
+ //~^^ ERROR any use of this value will cause an error
+
+const VALS_I32: (i32,) =
+    (
+     i32::MIN - 1,
+     );
+ //~^^ ERROR any use of this value will cause an error
+
+const VALS_I64: (i64,) =
+    (
+     i64::MIN - 1,
+     );
+ //~^^ ERROR any use of this value will cause an error
+
+const VALS_U8: (u8,) =
+    (
+     u8::MIN - 1,
+     );
+ //~^^ ERROR any use of this value will cause an error
+
+const VALS_U16: (u16,) = (
+     u16::MIN - 1,
+     );
+ //~^^ ERROR any use of this value will cause an error
+
+const VALS_U32: (u32,) = (
+     u32::MIN - 1,
+     );
+ //~^^ ERROR any use of this value will cause an error
+
+const VALS_U64: (u64,) =
+    (
+     u64::MIN - 1,
+     );
+ //~^^ ERROR any use of this value will cause an error
+
+fn main() {
+    foo(VALS_I8);
+    foo(VALS_I16);
+    foo(VALS_I32);
+    foo(VALS_I64);
+
+    foo(VALS_U8);
+    foo(VALS_U16);
+    foo(VALS_U32);
+    foo(VALS_U64);
+}
+
+fn foo<T>(_: T) {
+}
diff --git a/src/test/ui/consts/const-eval/const-eval-overflow2.stderr b/src/test/ui/consts/const-eval/const-eval-overflow2.stderr
new file mode 100644
index 0000000..419b3d5
--- /dev/null
+++ b/src/test/ui/consts/const-eval/const-eval-overflow2.stderr
@@ -0,0 +1,86 @@
+error: any use of this value will cause an error
+  --> $DIR/const-eval-overflow2.rs:16:6
+   |
+LL | / const VALS_I8: (i8,) =
+LL | |     (
+LL | |      i8::MIN - 1,
+   | |      ^^^^^^^^^^^ attempt to subtract with overflow
+LL | |      );
+   | |_______-
+   |
+note: lint level defined here
+  --> $DIR/const-eval-overflow2.rs:8:9
+   |
+LL | #![deny(const_err)]
+   |         ^^^^^^^^^
+
+error: any use of this value will cause an error
+  --> $DIR/const-eval-overflow2.rs:22:6
+   |
+LL | / const VALS_I16: (i16,) =
+LL | |     (
+LL | |      i16::MIN - 1,
+   | |      ^^^^^^^^^^^^ attempt to subtract with overflow
+LL | |      );
+   | |_______-
+
+error: any use of this value will cause an error
+  --> $DIR/const-eval-overflow2.rs:28:6
+   |
+LL | / const VALS_I32: (i32,) =
+LL | |     (
+LL | |      i32::MIN - 1,
+   | |      ^^^^^^^^^^^^ attempt to subtract with overflow
+LL | |      );
+   | |_______-
+
+error: any use of this value will cause an error
+  --> $DIR/const-eval-overflow2.rs:34:6
+   |
+LL | / const VALS_I64: (i64,) =
+LL | |     (
+LL | |      i64::MIN - 1,
+   | |      ^^^^^^^^^^^^ attempt to subtract with overflow
+LL | |      );
+   | |_______-
+
+error: any use of this value will cause an error
+  --> $DIR/const-eval-overflow2.rs:40:6
+   |
+LL | / const VALS_U8: (u8,) =
+LL | |     (
+LL | |      u8::MIN - 1,
+   | |      ^^^^^^^^^^^ attempt to subtract with overflow
+LL | |      );
+   | |_______-
+
+error: any use of this value will cause an error
+  --> $DIR/const-eval-overflow2.rs:45:6
+   |
+LL | / const VALS_U16: (u16,) = (
+LL | |      u16::MIN - 1,
+   | |      ^^^^^^^^^^^^ attempt to subtract with overflow
+LL | |      );
+   | |_______-
+
+error: any use of this value will cause an error
+  --> $DIR/const-eval-overflow2.rs:50:6
+   |
+LL | / const VALS_U32: (u32,) = (
+LL | |      u32::MIN - 1,
+   | |      ^^^^^^^^^^^^ attempt to subtract with overflow
+LL | |      );
+   | |_______-
+
+error: any use of this value will cause an error
+  --> $DIR/const-eval-overflow2.rs:56:6
+   |
+LL | / const VALS_U64: (u64,) =
+LL | |     (
+LL | |      u64::MIN - 1,
+   | |      ^^^^^^^^^^^^ attempt to subtract with overflow
+LL | |      );
+   | |_______-
+
+error: aborting due to 8 previous errors
+
diff --git a/src/test/ui/consts/const-eval/const-eval-overflow2b.rs b/src/test/ui/consts/const-eval/const-eval-overflow2b.rs
new file mode 100644
index 0000000..da88367
--- /dev/null
+++ b/src/test/ui/consts/const-eval/const-eval-overflow2b.rs
@@ -0,0 +1,73 @@
+#![allow(unused_imports)]
+
+// Note: the relevant lint pass here runs before some of the constant
+// evaluation below (e.g., that performed by codegen and llvm), so if you
+// change this warn to a deny, then the compiler will exit before
+// those errors are detected.
+
+#![deny(const_err)]
+
+use std::fmt;
+use std::{i8, i16, i32, i64, isize};
+use std::{u8, u16, u32, u64, usize};
+
+const VALS_I8: (i8,) =
+    (
+     i8::MAX + 1,
+     );
+ //~^^ ERROR any use of this value will cause an error
+
+const VALS_I16: (i16,) =
+    (
+     i16::MAX + 1,
+     );
+ //~^^ ERROR any use of this value will cause an error
+
+const VALS_I32: (i32,) =
+    (
+     i32::MAX + 1,
+     );
+ //~^^ ERROR any use of this value will cause an error
+
+const VALS_I64: (i64,) =
+    (
+     i64::MAX + 1,
+     );
+ //~^^ ERROR any use of this value will cause an error
+
+const VALS_U8: (u8,) =
+    (
+     u8::MAX + 1,
+     );
+ //~^^ ERROR any use of this value will cause an error
+
+const VALS_U16: (u16,) = (
+     u16::MAX + 1,
+     );
+ //~^^ ERROR any use of this value will cause an error
+
+const VALS_U32: (u32,) = (
+     u32::MAX + 1,
+     );
+ //~^^ ERROR any use of this value will cause an error
+
+const VALS_U64: (u64,) =
+    (
+     u64::MAX + 1,
+     );
+ //~^^ ERROR any use of this value will cause an error
+
+fn main() {
+    foo(VALS_I8);
+    foo(VALS_I16);
+    foo(VALS_I32);
+    foo(VALS_I64);
+
+    foo(VALS_U8);
+    foo(VALS_U16);
+    foo(VALS_U32);
+    foo(VALS_U64);
+}
+
+fn foo<T>(_: T) {
+}
diff --git a/src/test/ui/consts/const-eval/const-eval-overflow2b.stderr b/src/test/ui/consts/const-eval/const-eval-overflow2b.stderr
new file mode 100644
index 0000000..2cfd34c
--- /dev/null
+++ b/src/test/ui/consts/const-eval/const-eval-overflow2b.stderr
@@ -0,0 +1,86 @@
+error: any use of this value will cause an error
+  --> $DIR/const-eval-overflow2b.rs:16:6
+   |
+LL | / const VALS_I8: (i8,) =
+LL | |     (
+LL | |      i8::MAX + 1,
+   | |      ^^^^^^^^^^^ attempt to add with overflow
+LL | |      );
+   | |_______-
+   |
+note: lint level defined here
+  --> $DIR/const-eval-overflow2b.rs:8:9
+   |
+LL | #![deny(const_err)]
+   |         ^^^^^^^^^
+
+error: any use of this value will cause an error
+  --> $DIR/const-eval-overflow2b.rs:22:6
+   |
+LL | / const VALS_I16: (i16,) =
+LL | |     (
+LL | |      i16::MAX + 1,
+   | |      ^^^^^^^^^^^^ attempt to add with overflow
+LL | |      );
+   | |_______-
+
+error: any use of this value will cause an error
+  --> $DIR/const-eval-overflow2b.rs:28:6
+   |
+LL | / const VALS_I32: (i32,) =
+LL | |     (
+LL | |      i32::MAX + 1,
+   | |      ^^^^^^^^^^^^ attempt to add with overflow
+LL | |      );
+   | |_______-
+
+error: any use of this value will cause an error
+  --> $DIR/const-eval-overflow2b.rs:34:6
+   |
+LL | / const VALS_I64: (i64,) =
+LL | |     (
+LL | |      i64::MAX + 1,
+   | |      ^^^^^^^^^^^^ attempt to add with overflow
+LL | |      );
+   | |_______-
+
+error: any use of this value will cause an error
+  --> $DIR/const-eval-overflow2b.rs:40:6
+   |
+LL | / const VALS_U8: (u8,) =
+LL | |     (
+LL | |      u8::MAX + 1,
+   | |      ^^^^^^^^^^^ attempt to add with overflow
+LL | |      );
+   | |_______-
+
+error: any use of this value will cause an error
+  --> $DIR/const-eval-overflow2b.rs:45:6
+   |
+LL | / const VALS_U16: (u16,) = (
+LL | |      u16::MAX + 1,
+   | |      ^^^^^^^^^^^^ attempt to add with overflow
+LL | |      );
+   | |_______-
+
+error: any use of this value will cause an error
+  --> $DIR/const-eval-overflow2b.rs:50:6
+   |
+LL | / const VALS_U32: (u32,) = (
+LL | |      u32::MAX + 1,
+   | |      ^^^^^^^^^^^^ attempt to add with overflow
+LL | |      );
+   | |_______-
+
+error: any use of this value will cause an error
+  --> $DIR/const-eval-overflow2b.rs:56:6
+   |
+LL | / const VALS_U64: (u64,) =
+LL | |     (
+LL | |      u64::MAX + 1,
+   | |      ^^^^^^^^^^^^ attempt to add with overflow
+LL | |      );
+   | |_______-
+
+error: aborting due to 8 previous errors
+
diff --git a/src/test/ui/consts/const-eval/const-eval-overflow2c.rs b/src/test/ui/consts/const-eval/const-eval-overflow2c.rs
new file mode 100644
index 0000000..e873444
--- /dev/null
+++ b/src/test/ui/consts/const-eval/const-eval-overflow2c.rs
@@ -0,0 +1,73 @@
+#![allow(unused_imports)]
+
+// Note: the relevant lint pass here runs before some of the constant
+// evaluation below (e.g., that performed by codegen and llvm), so if you
+// change this warn to a deny, then the compiler will exit before
+// those errors are detected.
+
+#![deny(const_err)]
+
+use std::fmt;
+use std::{i8, i16, i32, i64, isize};
+use std::{u8, u16, u32, u64, usize};
+
+const VALS_I8: (i8,) =
+    (
+     i8::MIN * 2,
+     );
+ //~^^ ERROR any use of this value will cause an error
+
+const VALS_I16: (i16,) =
+    (
+     i16::MIN * 2,
+     );
+ //~^^ ERROR any use of this value will cause an error
+
+const VALS_I32: (i32,) =
+    (
+     i32::MIN * 2,
+     );
+ //~^^ ERROR any use of this value will cause an error
+
+const VALS_I64: (i64,) =
+    (
+     i64::MIN * 2,
+     );
+ //~^^ ERROR any use of this value will cause an error
+
+const VALS_U8: (u8,) =
+    (
+     u8::MAX * 2,
+     );
+ //~^^ ERROR any use of this value will cause an error
+
+const VALS_U16: (u16,) = (
+     u16::MAX * 2,
+     );
+ //~^^ ERROR any use of this value will cause an error
+
+const VALS_U32: (u32,) = (
+     u32::MAX * 2,
+     );
+ //~^^ ERROR any use of this value will cause an error
+
+const VALS_U64: (u64,) =
+    (
+     u64::MAX * 2,
+     );
+ //~^^ ERROR any use of this value will cause an error
+
+fn main() {
+    foo(VALS_I8);
+    foo(VALS_I16);
+    foo(VALS_I32);
+    foo(VALS_I64);
+
+    foo(VALS_U8);
+    foo(VALS_U16);
+    foo(VALS_U32);
+    foo(VALS_U64);
+}
+
+fn foo<T>(_: T) {
+}
diff --git a/src/test/ui/consts/const-eval/const-eval-overflow2c.stderr b/src/test/ui/consts/const-eval/const-eval-overflow2c.stderr
new file mode 100644
index 0000000..5e63286
--- /dev/null
+++ b/src/test/ui/consts/const-eval/const-eval-overflow2c.stderr
@@ -0,0 +1,86 @@
+error: any use of this value will cause an error
+  --> $DIR/const-eval-overflow2c.rs:16:6
+   |
+LL | / const VALS_I8: (i8,) =
+LL | |     (
+LL | |      i8::MIN * 2,
+   | |      ^^^^^^^^^^^ attempt to multiply with overflow
+LL | |      );
+   | |_______-
+   |
+note: lint level defined here
+  --> $DIR/const-eval-overflow2c.rs:8:9
+   |
+LL | #![deny(const_err)]
+   |         ^^^^^^^^^
+
+error: any use of this value will cause an error
+  --> $DIR/const-eval-overflow2c.rs:22:6
+   |
+LL | / const VALS_I16: (i16,) =
+LL | |     (
+LL | |      i16::MIN * 2,
+   | |      ^^^^^^^^^^^^ attempt to multiply with overflow
+LL | |      );
+   | |_______-
+
+error: any use of this value will cause an error
+  --> $DIR/const-eval-overflow2c.rs:28:6
+   |
+LL | / const VALS_I32: (i32,) =
+LL | |     (
+LL | |      i32::MIN * 2,
+   | |      ^^^^^^^^^^^^ attempt to multiply with overflow
+LL | |      );
+   | |_______-
+
+error: any use of this value will cause an error
+  --> $DIR/const-eval-overflow2c.rs:34:6
+   |
+LL | / const VALS_I64: (i64,) =
+LL | |     (
+LL | |      i64::MIN * 2,
+   | |      ^^^^^^^^^^^^ attempt to multiply with overflow
+LL | |      );
+   | |_______-
+
+error: any use of this value will cause an error
+  --> $DIR/const-eval-overflow2c.rs:40:6
+   |
+LL | / const VALS_U8: (u8,) =
+LL | |     (
+LL | |      u8::MAX * 2,
+   | |      ^^^^^^^^^^^ attempt to multiply with overflow
+LL | |      );
+   | |_______-
+
+error: any use of this value will cause an error
+  --> $DIR/const-eval-overflow2c.rs:45:6
+   |
+LL | / const VALS_U16: (u16,) = (
+LL | |      u16::MAX * 2,
+   | |      ^^^^^^^^^^^^ attempt to multiply with overflow
+LL | |      );
+   | |_______-
+
+error: any use of this value will cause an error
+  --> $DIR/const-eval-overflow2c.rs:50:6
+   |
+LL | / const VALS_U32: (u32,) = (
+LL | |      u32::MAX * 2,
+   | |      ^^^^^^^^^^^^ attempt to multiply with overflow
+LL | |      );
+   | |_______-
+
+error: any use of this value will cause an error
+  --> $DIR/const-eval-overflow2c.rs:56:6
+   |
+LL | / const VALS_U64: (u64,) =
+LL | |     (
+LL | |      u64::MAX * 2,
+   | |      ^^^^^^^^^^^^ attempt to multiply with overflow
+LL | |      );
+   | |_______-
+
+error: aborting due to 8 previous errors
+
diff --git a/src/test/ui/consts/const-eval/const-eval-span.rs b/src/test/ui/consts/const-eval/const-eval-span.rs
new file mode 100644
index 0000000..59f4b13
--- /dev/null
+++ b/src/test/ui/consts/const-eval/const-eval-span.rs
@@ -0,0 +1,15 @@
+// Check that error in constant evaluation of enum discriminant
+// provides the context for what caused the evaluation.
+
+struct S(i32);
+
+const CONSTANT: S = S(0);
+
+enum E {
+    V = CONSTANT,
+    //~^ ERROR mismatched types
+    //~| expected isize, found struct `S`
+    //~|         found type `S`
+}
+
+fn main() {}
diff --git a/src/test/ui/consts/const-eval/const-eval-span.stderr b/src/test/ui/consts/const-eval/const-eval-span.stderr
new file mode 100644
index 0000000..8ff9bfe
--- /dev/null
+++ b/src/test/ui/consts/const-eval/const-eval-span.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/const-eval-span.rs:9:9
+   |
+LL |     V = CONSTANT,
+   |         ^^^^^^^^ expected isize, found struct `S`
+   |
+   = note: expected type `isize`
+              found type `S`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.rs b/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.rs
new file mode 100644
index 0000000..cc5ddb4
--- /dev/null
+++ b/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.rs
@@ -0,0 +1,110 @@
+// only-x86_64
+
+union Nonsense {
+    u: usize,
+    int_32_ref: &'static i32,
+    uint_8: u8,
+    uint_16: u16,
+    uint_32: u32,
+    uint_64: u64,
+    uint_128: u128,
+    int_8: i8,
+    int_16: i16,
+    int_32: i32,
+    int_64: i64,
+    int_128: i128,
+    float_32: f32,
+    float_64: f64,
+    truthy_falsey: bool,
+    character: char,
+    stringy: &'static str,
+}
+
+fn main() {
+    const I32_REF_USIZE_UNION: usize = unsafe { Nonsense { int_32_ref: &3 }.u };
+    //~^ ERROR it is undefined behavior to use this value
+
+    const I32_REF_U8_UNION: u8 = unsafe { Nonsense { int_32_ref: &3 }.uint_8 };
+    //~^ ERROR any use of this value will cause an error
+
+    const I32_REF_U16_UNION: u16 = unsafe { Nonsense { int_32_ref: &3 }.uint_16 };
+    //~^ ERROR any use of this value will cause an error
+
+    const I32_REF_U32_UNION: u32 = unsafe { Nonsense { int_32_ref: &3 }.uint_32 };
+    //~^ ERROR any use of this value will cause an error
+
+    const I32_REF_U64_UNION: u64 = unsafe { Nonsense { int_32_ref: &3 }.uint_64 };
+    //~^ ERROR it is undefined behavior to use this value
+
+    const I32_REF_U128_UNION: u128 = unsafe { Nonsense { int_32_ref: &3 }.uint_128 };
+    //~^ ERROR it is undefined behavior to use this value
+
+    const I32_REF_I8_UNION: i8 = unsafe { Nonsense { int_32_ref: &3 }.int_8 };
+    //~^ ERROR any use of this value will cause an error
+
+    const I32_REF_I16_UNION: i16 = unsafe { Nonsense { int_32_ref: &3 }.int_16 };
+    //~^ ERROR any use of this value will cause an error
+
+    const I32_REF_I32_UNION: i32 = unsafe { Nonsense { int_32_ref: &3 }.int_32 };
+    //~^ ERROR any use of this value will cause an error
+
+    const I32_REF_I64_UNION: i64 = unsafe { Nonsense { int_32_ref: &3 }.int_64 };
+    //~^ ERROR it is undefined behavior to use this value
+
+    const I32_REF_I128_UNION: i128 = unsafe { Nonsense { int_32_ref: &3 }.int_128 };
+    //~^ ERROR it is undefined behavior to use this value
+
+    const I32_REF_F32_UNION: f32 = unsafe { Nonsense { int_32_ref: &3 }.float_32 };
+    //~^ ERROR any use of this value will cause an error
+
+    const I32_REF_F64_UNION: f64 = unsafe { Nonsense { int_32_ref: &3 }.float_64 };
+    //~^ ERROR it is undefined behavior to use this value
+
+    const I32_REF_BOOL_UNION: bool = unsafe { Nonsense { int_32_ref: &3 }.truthy_falsey };
+    //~^ ERROR any use of this value will cause an error
+
+    const I32_REF_CHAR_UNION: char = unsafe { Nonsense { int_32_ref: &3 }.character };
+    //~^ ERROR any use of this value will cause an error
+
+    const STR_U8_UNION: u8 = unsafe { Nonsense { stringy: "3" }.uint_8 };
+    //~^ ERROR any use of this value will cause an error
+
+    const STR_U16_UNION: u16 = unsafe { Nonsense { stringy: "3" }.uint_16 };
+    //~^ ERROR any use of this value will cause an error
+
+    const STR_U32_UNION: u32 = unsafe { Nonsense { stringy: "3" }.uint_32 };
+    //~^ ERROR any use of this value will cause an error
+
+    const STR_U64_UNION: u64 = unsafe { Nonsense { stringy: "3" }.uint_64 };
+    //~^ ERROR it is undefined behavior to use this value
+
+    const STR_U128_UNION: u128 = unsafe { Nonsense { stringy: "3" }.uint_128 };
+    //~^ ERROR any use of this value will cause an error
+
+    const STR_I8_UNION: i8 = unsafe { Nonsense { stringy: "3" }.int_8 };
+    //~^ ERROR any use of this value will cause an error
+
+    const STR_I16_UNION: i16 = unsafe { Nonsense { stringy: "3" }.int_16 };
+    //~^ ERROR any use of this value will cause an error
+
+    const STR_I32_UNION: i32 = unsafe { Nonsense { stringy: "3" }.int_32 };
+    //~^ ERROR any use of this value will cause an error
+
+    const STR_I64_UNION: i64 = unsafe { Nonsense { stringy: "3" }.int_64 };
+    //~^ ERROR it is undefined behavior to use this value
+
+    const STR_I128_UNION: i128 = unsafe { Nonsense { stringy: "3" }.int_128 };
+    //~^ ERROR any use of this value will cause an error
+
+    const STR_F32_UNION: f32 = unsafe { Nonsense { stringy: "3" }.float_32 };
+    //~^ ERROR any use of this value will cause an error
+
+    const STR_F64_UNION: f64 = unsafe { Nonsense { stringy: "3" }.float_64 };
+    //~^ ERROR it is undefined behavior to use this value
+
+    const STR_BOOL_UNION: bool = unsafe { Nonsense { stringy: "3" }.truthy_falsey };
+    //~^ ERROR any use of this value will cause an error
+
+    const STR_CHAR_UNION: char = unsafe { Nonsense { stringy: "3" }.character };
+    //~^ ERROR any use of this value will cause an error
+}
diff --git a/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.stderr b/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.stderr
new file mode 100644
index 0000000..284b069
--- /dev/null
+++ b/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.stderr
@@ -0,0 +1,237 @@
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/const-pointer-values-in-various-types.rs:24:5
+   |
+LL |     const I32_REF_USIZE_UNION: usize = unsafe { Nonsense { int_32_ref: &3 }.u };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error: any use of this value will cause an error
+  --> $DIR/const-pointer-values-in-various-types.rs:27:43
+   |
+LL |     const I32_REF_U8_UNION: u8 = unsafe { Nonsense { int_32_ref: &3 }.uint_8 };
+   |     --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                           |
+   |                                           a raw memory access tried to access part of a pointer value as raw bytes
+   |
+   = note: #[deny(const_err)] on by default
+
+error: any use of this value will cause an error
+  --> $DIR/const-pointer-values-in-various-types.rs:30:45
+   |
+LL |     const I32_REF_U16_UNION: u16 = unsafe { Nonsense { int_32_ref: &3 }.uint_16 };
+   |     ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                             |
+   |                                             a raw memory access tried to access part of a pointer value as raw bytes
+
+error: any use of this value will cause an error
+  --> $DIR/const-pointer-values-in-various-types.rs:33:45
+   |
+LL |     const I32_REF_U32_UNION: u32 = unsafe { Nonsense { int_32_ref: &3 }.uint_32 };
+   |     ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                             |
+   |                                             a raw memory access tried to access part of a pointer value as raw bytes
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/const-pointer-values-in-various-types.rs:36:5
+   |
+LL |     const I32_REF_U64_UNION: u64 = unsafe { Nonsense { int_32_ref: &3 }.uint_64 };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/const-pointer-values-in-various-types.rs:39:5
+   |
+LL |     const I32_REF_U128_UNION: u128 = unsafe { Nonsense { int_32_ref: &3 }.uint_128 };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected initialized plain (non-pointer) bytes
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error: any use of this value will cause an error
+  --> $DIR/const-pointer-values-in-various-types.rs:42:43
+   |
+LL |     const I32_REF_I8_UNION: i8 = unsafe { Nonsense { int_32_ref: &3 }.int_8 };
+   |     --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                           |
+   |                                           a raw memory access tried to access part of a pointer value as raw bytes
+
+error: any use of this value will cause an error
+  --> $DIR/const-pointer-values-in-various-types.rs:45:45
+   |
+LL |     const I32_REF_I16_UNION: i16 = unsafe { Nonsense { int_32_ref: &3 }.int_16 };
+   |     ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                             |
+   |                                             a raw memory access tried to access part of a pointer value as raw bytes
+
+error: any use of this value will cause an error
+  --> $DIR/const-pointer-values-in-various-types.rs:48:45
+   |
+LL |     const I32_REF_I32_UNION: i32 = unsafe { Nonsense { int_32_ref: &3 }.int_32 };
+   |     ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                             |
+   |                                             a raw memory access tried to access part of a pointer value as raw bytes
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/const-pointer-values-in-various-types.rs:51:5
+   |
+LL |     const I32_REF_I64_UNION: i64 = unsafe { Nonsense { int_32_ref: &3 }.int_64 };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/const-pointer-values-in-various-types.rs:54:5
+   |
+LL |     const I32_REF_I128_UNION: i128 = unsafe { Nonsense { int_32_ref: &3 }.int_128 };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected initialized plain (non-pointer) bytes
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error: any use of this value will cause an error
+  --> $DIR/const-pointer-values-in-various-types.rs:57:45
+   |
+LL |     const I32_REF_F32_UNION: f32 = unsafe { Nonsense { int_32_ref: &3 }.float_32 };
+   |     ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                             |
+   |                                             a raw memory access tried to access part of a pointer value as raw bytes
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/const-pointer-values-in-various-types.rs:60:5
+   |
+LL |     const I32_REF_F64_UNION: f64 = unsafe { Nonsense { int_32_ref: &3 }.float_64 };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error: any use of this value will cause an error
+  --> $DIR/const-pointer-values-in-various-types.rs:63:47
+   |
+LL |     const I32_REF_BOOL_UNION: bool = unsafe { Nonsense { int_32_ref: &3 }.truthy_falsey };
+   |     ------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                               |
+   |                                               a raw memory access tried to access part of a pointer value as raw bytes
+
+error: any use of this value will cause an error
+  --> $DIR/const-pointer-values-in-various-types.rs:66:47
+   |
+LL |     const I32_REF_CHAR_UNION: char = unsafe { Nonsense { int_32_ref: &3 }.character };
+   |     ------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                               |
+   |                                               a raw memory access tried to access part of a pointer value as raw bytes
+
+error: any use of this value will cause an error
+  --> $DIR/const-pointer-values-in-various-types.rs:69:39
+   |
+LL |     const STR_U8_UNION: u8 = unsafe { Nonsense { stringy: "3" }.uint_8 };
+   |     ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                       |
+   |                                       a raw memory access tried to access part of a pointer value as raw bytes
+
+error: any use of this value will cause an error
+  --> $DIR/const-pointer-values-in-various-types.rs:72:41
+   |
+LL |     const STR_U16_UNION: u16 = unsafe { Nonsense { stringy: "3" }.uint_16 };
+   |     ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                         |
+   |                                         a raw memory access tried to access part of a pointer value as raw bytes
+
+error: any use of this value will cause an error
+  --> $DIR/const-pointer-values-in-various-types.rs:75:41
+   |
+LL |     const STR_U32_UNION: u32 = unsafe { Nonsense { stringy: "3" }.uint_32 };
+   |     ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                         |
+   |                                         a raw memory access tried to access part of a pointer value as raw bytes
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/const-pointer-values-in-various-types.rs:78:5
+   |
+LL |     const STR_U64_UNION: u64 = unsafe { Nonsense { stringy: "3" }.uint_64 };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error: any use of this value will cause an error
+  --> $DIR/const-pointer-values-in-various-types.rs:81:43
+   |
+LL |     const STR_U128_UNION: u128 = unsafe { Nonsense { stringy: "3" }.uint_128 };
+   |     --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                           |
+   |                                           a raw memory access tried to access part of a pointer value as raw bytes
+
+error: any use of this value will cause an error
+  --> $DIR/const-pointer-values-in-various-types.rs:84:39
+   |
+LL |     const STR_I8_UNION: i8 = unsafe { Nonsense { stringy: "3" }.int_8 };
+   |     ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                       |
+   |                                       a raw memory access tried to access part of a pointer value as raw bytes
+
+error: any use of this value will cause an error
+  --> $DIR/const-pointer-values-in-various-types.rs:87:41
+   |
+LL |     const STR_I16_UNION: i16 = unsafe { Nonsense { stringy: "3" }.int_16 };
+   |     ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                         |
+   |                                         a raw memory access tried to access part of a pointer value as raw bytes
+
+error: any use of this value will cause an error
+  --> $DIR/const-pointer-values-in-various-types.rs:90:41
+   |
+LL |     const STR_I32_UNION: i32 = unsafe { Nonsense { stringy: "3" }.int_32 };
+   |     ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                         |
+   |                                         a raw memory access tried to access part of a pointer value as raw bytes
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/const-pointer-values-in-various-types.rs:93:5
+   |
+LL |     const STR_I64_UNION: i64 = unsafe { Nonsense { stringy: "3" }.int_64 };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error: any use of this value will cause an error
+  --> $DIR/const-pointer-values-in-various-types.rs:96:43
+   |
+LL |     const STR_I128_UNION: i128 = unsafe { Nonsense { stringy: "3" }.int_128 };
+   |     --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                           |
+   |                                           a raw memory access tried to access part of a pointer value as raw bytes
+
+error: any use of this value will cause an error
+  --> $DIR/const-pointer-values-in-various-types.rs:99:41
+   |
+LL |     const STR_F32_UNION: f32 = unsafe { Nonsense { stringy: "3" }.float_32 };
+   |     ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                         |
+   |                                         a raw memory access tried to access part of a pointer value as raw bytes
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/const-pointer-values-in-various-types.rs:102:5
+   |
+LL |     const STR_F64_UNION: f64 = unsafe { Nonsense { stringy: "3" }.float_64 };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error: any use of this value will cause an error
+  --> $DIR/const-pointer-values-in-various-types.rs:105:43
+   |
+LL |     const STR_BOOL_UNION: bool = unsafe { Nonsense { stringy: "3" }.truthy_falsey };
+   |     --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                           |
+   |                                           a raw memory access tried to access part of a pointer value as raw bytes
+
+error: any use of this value will cause an error
+  --> $DIR/const-pointer-values-in-various-types.rs:108:43
+   |
+LL |     const STR_CHAR_UNION: char = unsafe { Nonsense { stringy: "3" }.character };
+   |     --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                           |
+   |                                           a raw memory access tried to access part of a pointer value as raw bytes
+
+error: aborting due to 29 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/const_let.rs b/src/test/ui/consts/const-eval/const_let.rs
new file mode 100644
index 0000000..63321b9
--- /dev/null
+++ b/src/test/ui/consts/const-eval/const_let.rs
@@ -0,0 +1,18 @@
+fn main() {}
+
+struct FakeNeedsDrop;
+
+impl Drop for FakeNeedsDrop {
+    fn drop(&mut self) {}
+}
+
+// ok
+const X: FakeNeedsDrop = { let x = FakeNeedsDrop; x };
+
+// error
+const Y: FakeNeedsDrop = { let mut x = FakeNeedsDrop; x = FakeNeedsDrop; x };
+//~^ ERROR constant contains unimplemented expression type
+
+// error
+const Z: () = { let mut x = None; x = Some(FakeNeedsDrop); };
+//~^ ERROR constant contains unimplemented expression type
diff --git a/src/test/ui/consts/const-eval/const_let.stderr b/src/test/ui/consts/const-eval/const_let.stderr
new file mode 100644
index 0000000..00de97e
--- /dev/null
+++ b/src/test/ui/consts/const-eval/const_let.stderr
@@ -0,0 +1,15 @@
+error[E0019]: constant contains unimplemented expression type
+  --> $DIR/const_let.rs:13:55
+   |
+LL | const Y: FakeNeedsDrop = { let mut x = FakeNeedsDrop; x = FakeNeedsDrop; x };
+   |                                                       ^
+
+error[E0019]: constant contains unimplemented expression type
+  --> $DIR/const_let.rs:17:35
+   |
+LL | const Z: () = { let mut x = None; x = Some(FakeNeedsDrop); };
+   |                                   ^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0019`.
diff --git a/src/test/ui/consts/const-eval/const_panic.rs b/src/test/ui/consts/const-eval/const_panic.rs
new file mode 100644
index 0000000..3e5112b
--- /dev/null
+++ b/src/test/ui/consts/const-eval/const_panic.rs
@@ -0,0 +1,11 @@
+#![feature(const_panic)]
+#![crate_type = "lib"]
+
+pub const Z: () = panic!("cheese");
+//~^ ERROR any use of this value will cause an error
+
+pub const Y: () = unreachable!();
+//~^ ERROR any use of this value will cause an error
+
+pub const X: () = unimplemented!();
+//~^ ERROR any use of this value will cause an error
diff --git a/src/test/ui/consts/const-eval/const_panic.stderr b/src/test/ui/consts/const-eval/const_panic.stderr
new file mode 100644
index 0000000..12c7e3d
--- /dev/null
+++ b/src/test/ui/consts/const-eval/const_panic.stderr
@@ -0,0 +1,33 @@
+error: any use of this value will cause an error
+  --> $DIR/const_panic.rs:4:19
+   |
+LL | pub const Z: () = panic!("cheese");
+   | ------------------^^^^^^^^^^^^^^^^-
+   |                   |
+   |                   the evaluated program panicked at 'cheese', $DIR/const_panic.rs:4:19
+   |
+   = note: #[deny(const_err)] on by default
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: any use of this value will cause an error
+  --> $DIR/const_panic.rs:7:19
+   |
+LL | pub const Y: () = unreachable!();
+   | ------------------^^^^^^^^^^^^^^-
+   |                   |
+   |                   the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic.rs:7:19
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: any use of this value will cause an error
+  --> $DIR/const_panic.rs:10:19
+   |
+LL | pub const X: () = unimplemented!();
+   | ------------------^^^^^^^^^^^^^^^^-
+   |                   |
+   |                   the evaluated program panicked at 'not yet implemented', $DIR/const_panic.rs:10:19
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/consts/const-eval/const_panic_libcore.rs b/src/test/ui/consts/const-eval/const_panic_libcore.rs
new file mode 100644
index 0000000..e42685e
--- /dev/null
+++ b/src/test/ui/consts/const-eval/const_panic_libcore.rs
@@ -0,0 +1,12 @@
+#![no_std]
+#![crate_type = "lib"]
+#![feature(const_panic)]
+
+const Z: () = panic!("cheese");
+//~^ ERROR any use of this value will cause an error
+
+const Y: () = unreachable!();
+//~^ ERROR any use of this value will cause an error
+
+const X: () = unimplemented!();
+//~^ ERROR any use of this value will cause an error
diff --git a/src/test/ui/consts/const-eval/const_panic_libcore.stderr b/src/test/ui/consts/const-eval/const_panic_libcore.stderr
new file mode 100644
index 0000000..9dddac4
--- /dev/null
+++ b/src/test/ui/consts/const-eval/const_panic_libcore.stderr
@@ -0,0 +1,33 @@
+error: any use of this value will cause an error
+  --> $DIR/const_panic_libcore.rs:5:15
+   |
+LL | const Z: () = panic!("cheese");
+   | --------------^^^^^^^^^^^^^^^^-
+   |               |
+   |               the evaluated program panicked at 'cheese', $DIR/const_panic_libcore.rs:5:15
+   |
+   = note: #[deny(const_err)] on by default
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: any use of this value will cause an error
+  --> $DIR/const_panic_libcore.rs:8:15
+   |
+LL | const Y: () = unreachable!();
+   | --------------^^^^^^^^^^^^^^-
+   |               |
+   |               the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic_libcore.rs:8:15
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: any use of this value will cause an error
+  --> $DIR/const_panic_libcore.rs:11:15
+   |
+LL | const X: () = unimplemented!();
+   | --------------^^^^^^^^^^^^^^^^-
+   |               |
+   |               the evaluated program panicked at 'not yet implemented', $DIR/const_panic_libcore.rs:11:15
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/consts/const-eval/const_panic_libcore_main.rs b/src/test/ui/consts/const-eval/const_panic_libcore_main.rs
new file mode 100644
index 0000000..9afcdf7
--- /dev/null
+++ b/src/test/ui/consts/const-eval/const_panic_libcore_main.rs
@@ -0,0 +1,26 @@
+#![crate_type = "bin"]
+#![feature(lang_items)]
+#![feature(const_panic)]
+#![no_main]
+#![no_std]
+
+use core::panic::PanicInfo;
+
+const Z: () = panic!("cheese");
+//~^ ERROR any use of this value will cause an error
+
+const Y: () = unreachable!();
+//~^ ERROR any use of this value will cause an error
+
+const X: () = unimplemented!();
+//~^ ERROR any use of this value will cause an error
+
+#[lang = "eh_personality"]
+fn eh() {}
+#[lang = "eh_unwind_resume"]
+fn eh_unwind_resume() {}
+
+#[panic_handler]
+fn panic(_info: &PanicInfo) -> ! {
+    loop {}
+}
diff --git a/src/test/ui/consts/const-eval/const_panic_libcore_main.stderr b/src/test/ui/consts/const-eval/const_panic_libcore_main.stderr
new file mode 100644
index 0000000..df04a03
--- /dev/null
+++ b/src/test/ui/consts/const-eval/const_panic_libcore_main.stderr
@@ -0,0 +1,33 @@
+error: any use of this value will cause an error
+  --> $DIR/const_panic_libcore_main.rs:9:15
+   |
+LL | const Z: () = panic!("cheese");
+   | --------------^^^^^^^^^^^^^^^^-
+   |               |
+   |               the evaluated program panicked at 'cheese', $DIR/const_panic_libcore_main.rs:9:15
+   |
+   = note: #[deny(const_err)] on by default
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: any use of this value will cause an error
+  --> $DIR/const_panic_libcore_main.rs:12:15
+   |
+LL | const Y: () = unreachable!();
+   | --------------^^^^^^^^^^^^^^-
+   |               |
+   |               the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic_libcore_main.rs:12:15
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: any use of this value will cause an error
+  --> $DIR/const_panic_libcore_main.rs:15:15
+   |
+LL | const X: () = unimplemented!();
+   | --------------^^^^^^^^^^^^^^^^-
+   |               |
+   |               the evaluated program panicked at 'not yet implemented', $DIR/const_panic_libcore_main.rs:15:15
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/consts/const-eval/const_prop_errors.rs b/src/test/ui/consts/const-eval/const_prop_errors.rs
new file mode 100644
index 0000000..51b50b2
--- /dev/null
+++ b/src/test/ui/consts/const-eval/const_prop_errors.rs
@@ -0,0 +1,14 @@
+// compile-pass
+
+pub trait Foo {
+    fn foo(self) -> u32;
+}
+
+impl<T> Foo for T {
+    fn foo(self) -> u32 {
+        fn bar<T>() { loop {} }
+        bar::<T> as u32
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/consts/const-eval/const_raw_ptr_ops.rs b/src/test/ui/consts/const-eval/const_raw_ptr_ops.rs
new file mode 100644
index 0000000..4426668
--- /dev/null
+++ b/src/test/ui/consts/const-eval/const_raw_ptr_ops.rs
@@ -0,0 +1,17 @@
+#![feature(const_raw_ptr_to_usize_cast, const_compare_raw_pointers, const_raw_ptr_deref)]
+
+fn main() {}
+
+// unconst and bad, will thus error in miri
+const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 }; //~ ERROR any use of this
+// unconst and fine
+const X2: bool = unsafe { 42 as *const i32 == 43 as *const i32 };
+// unconst and fine
+const Y: usize = unsafe { 42usize as *const i32 as usize + 1 };
+// unconst and bad, will thus error in miri
+const Y2: usize = unsafe { &1 as *const i32 as usize + 1 }; //~ ERROR any use of this
+// unconst and fine
+const Z: i32 = unsafe { *(&1 as *const i32) };
+// unconst and bad, will thus error in miri
+const Z2: i32 = unsafe { *(42 as *const i32) }; //~ ERROR any use of this value will cause
+const Z3: i32 = unsafe { *(44 as *const i32) }; //~ ERROR any use of this value will cause
diff --git a/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr b/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr
new file mode 100644
index 0000000..0d4c0b9
--- /dev/null
+++ b/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr
@@ -0,0 +1,36 @@
+error: any use of this value will cause an error
+  --> $DIR/const_raw_ptr_ops.rs:6:26
+   |
+LL | const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 };
+   | -------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                          |
+   |                          "pointer arithmetic or comparison" needs an rfc before being allowed inside constants
+   |
+   = note: #[deny(const_err)] on by default
+
+error: any use of this value will cause an error
+  --> $DIR/const_raw_ptr_ops.rs:12:28
+   |
+LL | const Y2: usize = unsafe { &1 as *const i32 as usize + 1 };
+   | ---------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                            |
+   |                            "pointer arithmetic or comparison" needs an rfc before being allowed inside constants
+
+error: any use of this value will cause an error
+  --> $DIR/const_raw_ptr_ops.rs:16:26
+   |
+LL | const Z2: i32 = unsafe { *(42 as *const i32) };
+   | -------------------------^^^^^^^^^^^^^^^^^^^---
+   |                          |
+   |                          a memory access tried to interpret some bytes as a pointer
+
+error: any use of this value will cause an error
+  --> $DIR/const_raw_ptr_ops.rs:17:26
+   |
+LL | const Z3: i32 = unsafe { *(44 as *const i32) };
+   | -------------------------^^^^^^^^^^^^^^^^^^^---
+   |                          |
+   |                          a memory access tried to interpret some bytes as a pointer
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/consts/const-eval/const_signed_pat.rs b/src/test/ui/consts/const-eval/const_signed_pat.rs
new file mode 100644
index 0000000..cb4fb46
--- /dev/null
+++ b/src/test/ui/consts/const-eval/const_signed_pat.rs
@@ -0,0 +1,9 @@
+// compile-pass
+
+fn main() {
+    const MIN: i8 = -5;
+    match 5i8 {
+        MIN..=-1 => {},
+        _ => {},
+    }
+}
diff --git a/src/test/ui/consts/const-eval/const_transmute.rs b/src/test/ui/consts/const-eval/const_transmute.rs
new file mode 100644
index 0000000..e4f7fb1
--- /dev/null
+++ b/src/test/ui/consts/const-eval/const_transmute.rs
@@ -0,0 +1,54 @@
+// compile-pass
+// run-pass
+
+#![feature(const_fn_union)]
+
+union Transmute<T: Copy, U: Copy> {
+    t: T,
+    u: U,
+}
+
+trait Bar {
+    fn bar(&self) -> u32;
+}
+
+struct Foo {
+    foo: u32,
+    bar: bool,
+}
+
+impl Bar for Foo {
+    fn bar(&self) -> u32 {
+        self.foo
+    }
+}
+
+impl Drop for Foo {
+    fn drop(&mut self) {
+        assert!(!self.bar);
+        self.bar = true;
+        println!("dropping Foo");
+    }
+}
+
+#[derive(Copy, Clone)]
+struct Fat<'a>(&'a Foo, &'static VTable);
+
+struct VTable {
+    drop: Option<for<'a> fn(&'a mut Foo)>,
+    size: usize,
+    align: usize,
+    bar: for<'a> fn(&'a Foo) -> u32,
+}
+
+const FOO: &Bar = &Foo { foo: 128, bar: false };
+const G: Fat = unsafe { Transmute { t: FOO }.u };
+const F: Option<for<'a> fn(&'a mut Foo)> = G.1.drop;
+const H: for<'a> fn(&'a Foo) -> u32 = G.1.bar;
+
+fn main() {
+    let mut foo = Foo { foo: 99, bar: false };
+    (F.unwrap())(&mut foo);
+    std::mem::forget(foo); // already ran the drop impl
+    assert_eq!(H(&Foo { foo: 42, bar: false }), 42);
+}
diff --git a/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn.nll.stderr b/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn.nll.stderr
new file mode 100644
index 0000000..ca80a9a
--- /dev/null
+++ b/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn.nll.stderr
@@ -0,0 +1,43 @@
+error: `foo` is not yet stable as a const fn
+  --> $DIR/dont_promote_unstable_const_fn.rs:15:25
+   |
+LL | const fn bar() -> u32 { foo() }
+   |                         ^^^^^
+   |
+   = help: add `#![feature(foo)]` to the crate attributes to enable
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/dont_promote_unstable_const_fn.rs:18:28
+   |
+LL |     let _: &'static u32 = &foo();
+   |            ------------    ^^^^^ creates a temporary which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/dont_promote_unstable_const_fn.rs:22:28
+   |
+LL |     let _: &'static u32 = &meh();
+   |            ------------    ^^^^^ creates a temporary which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+...
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/dont_promote_unstable_const_fn.rs:23:26
+   |
+LL |     let x: &'static _ = &std::time::Duration::from_millis(42).subsec_millis();
+   |            ----------    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+LL |
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn.rs b/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn.rs
new file mode 100644
index 0000000..7170be1
--- /dev/null
+++ b/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn.rs
@@ -0,0 +1,25 @@
+#![unstable(feature = "humans",
+            reason = "who ever let humans program computers,
+            we're apparently really bad at it",
+            issue = "0")]
+
+#![feature(rustc_const_unstable, const_fn)]
+#![feature(staged_api)]
+
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_const_unstable(feature="foo")]
+const fn foo() -> u32 { 42 }
+
+fn meh() -> u32 { 42 }
+
+const fn bar() -> u32 { foo() } //~ ERROR `foo` is not yet stable as a const fn
+
+fn a() {
+    let _: &'static u32 = &foo(); //~ ERROR does not live long enough
+}
+
+fn main() {
+    let _: &'static u32 = &meh(); //~ ERROR does not live long enough
+    let x: &'static _ = &std::time::Duration::from_millis(42).subsec_millis();
+    //~^ ERROR does not live long enough
+}
diff --git a/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn.stderr b/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn.stderr
new file mode 100644
index 0000000..d796666
--- /dev/null
+++ b/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn.stderr
@@ -0,0 +1,43 @@
+error: `foo` is not yet stable as a const fn
+  --> $DIR/dont_promote_unstable_const_fn.rs:15:25
+   |
+LL | const fn bar() -> u32 { foo() }
+   |                         ^^^^^
+   |
+   = help: add `#![feature(foo)]` to the crate attributes to enable
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/dont_promote_unstable_const_fn.rs:18:28
+   |
+LL |     let _: &'static u32 = &foo();
+   |                            ^^^^^ temporary value does not live long enough
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/dont_promote_unstable_const_fn.rs:22:28
+   |
+LL |     let _: &'static u32 = &meh();
+   |                            ^^^^^ temporary value does not live long enough
+...
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/dont_promote_unstable_const_fn.rs:23:26
+   |
+LL |     let x: &'static _ = &std::time::Duration::from_millis(42).subsec_millis();
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+LL |
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn_cross_crate.nll.stderr b/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn_cross_crate.nll.stderr
new file mode 100644
index 0000000..129f061
--- /dev/null
+++ b/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn_cross_crate.nll.stderr
@@ -0,0 +1,24 @@
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/dont_promote_unstable_const_fn_cross_crate.rs:8:28
+   |
+LL |     let _: &'static u32 = &foo();
+   |            ------------    ^^^^^ creates a temporary which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+LL |     let _x: &'static u32 = &foo();
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/dont_promote_unstable_const_fn_cross_crate.rs:9:29
+   |
+LL |     let _x: &'static u32 = &foo();
+   |             ------------    ^^^^^ creates a temporary which is freed while still in use
+   |             |
+   |             type annotation requires that borrow lasts for `'static`
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn_cross_crate.rs b/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn_cross_crate.rs
new file mode 100644
index 0000000..6dcfcfe
--- /dev/null
+++ b/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn_cross_crate.rs
@@ -0,0 +1,10 @@
+// aux-build:stability.rs
+
+extern crate stability;
+
+use stability::foo;
+
+fn main() {
+    let _: &'static u32 = &foo(); //~ ERROR does not live long enough
+    let _x: &'static u32 = &foo(); //~ ERROR does not live long enough
+}
diff --git a/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn_cross_crate.stderr b/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn_cross_crate.stderr
new file mode 100644
index 0000000..516c008
--- /dev/null
+++ b/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn_cross_crate.stderr
@@ -0,0 +1,24 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/dont_promote_unstable_const_fn_cross_crate.rs:8:28
+   |
+LL |     let _: &'static u32 = &foo();
+   |                            ^^^^^ temporary value does not live long enough
+LL |     let _x: &'static u32 = &foo();
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/dont_promote_unstable_const_fn_cross_crate.rs:9:29
+   |
+LL |     let _x: &'static u32 = &foo();
+   |                             ^^^^^ temporary value does not live long enough
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/consts/const-eval/double_check.rs b/src/test/ui/consts/const-eval/double_check.rs
new file mode 100644
index 0000000..9ac5117
--- /dev/null
+++ b/src/test/ui/consts/const-eval/double_check.rs
@@ -0,0 +1,22 @@
+// compile-pass
+
+enum Foo {
+    A = 5,
+    B = 42,
+}
+enum Bar {
+    C = 42,
+    D = 99,
+}
+union Union {
+    foo: &'static Foo,
+    bar: &'static Bar,
+    u8: &'static u8,
+}
+static BAR: u8 = 42;
+static FOO: (&Foo, &Bar) = unsafe {(
+    Union { u8: &BAR }.foo,
+    Union { u8: &BAR }.bar,
+)};
+
+fn main() {}
diff --git a/src/test/ui/consts/const-eval/double_check2.rs b/src/test/ui/consts/const-eval/double_check2.rs
new file mode 100644
index 0000000..dc2b58f
--- /dev/null
+++ b/src/test/ui/consts/const-eval/double_check2.rs
@@ -0,0 +1,20 @@
+enum Foo {
+    A = 5,
+    B = 42,
+}
+enum Bar {
+    C = 42,
+    D = 99,
+}
+union Union {
+    foo: &'static Foo,
+    bar: &'static Bar,
+    u8: &'static u8,
+}
+static BAR: u8 = 5;
+static FOO: (&Foo, &Bar) = unsafe {( //~ undefined behavior
+    Union { u8: &BAR }.foo,
+    Union { u8: &BAR }.bar,
+)};
+
+fn main() {}
diff --git a/src/test/ui/consts/const-eval/double_check2.stderr b/src/test/ui/consts/const-eval/double_check2.stderr
new file mode 100644
index 0000000..2b61d33
--- /dev/null
+++ b/src/test/ui/consts/const-eval/double_check2.stderr
@@ -0,0 +1,14 @@
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/double_check2.rs:15:1
+   |
+LL | / static FOO: (&Foo, &Bar) = unsafe {(
+LL | |     Union { u8: &BAR }.foo,
+LL | |     Union { u8: &BAR }.bar,
+LL | | )};
+   | |___^ type validation failed: encountered 5 at .1.<deref>, but expected a valid enum discriminant
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/double_promotion.rs b/src/test/ui/consts/const-eval/double_promotion.rs
new file mode 100644
index 0000000..0e75ea8
--- /dev/null
+++ b/src/test/ui/consts/const-eval/double_promotion.rs
@@ -0,0 +1,17 @@
+// compile-pass
+
+#![feature(const_fn, rustc_attrs)]
+
+#[rustc_args_required_const(0)]
+pub const fn a(value: u8) -> u8 {
+    value
+}
+
+#[rustc_args_required_const(0)]
+pub fn b(_: u8) {
+    unimplemented!()
+}
+
+fn main() {
+    let _ = b(a(0));
+}
diff --git a/src/test/ui/consts/const-eval/duration_conversion.rs b/src/test/ui/consts/const-eval/duration_conversion.rs
new file mode 100644
index 0000000..854f97d
--- /dev/null
+++ b/src/test/ui/consts/const-eval/duration_conversion.rs
@@ -0,0 +1,16 @@
+// compile-pass
+
+use std::time::Duration;
+
+fn main() {
+    const _ONE_SECOND: Duration = Duration::from_nanos(1_000_000_000);
+    const _ONE_MILLISECOND: Duration = Duration::from_nanos(1_000_000);
+    const _ONE_MICROSECOND: Duration = Duration::from_nanos(1_000);
+    const _ONE_NANOSECOND: Duration = Duration::from_nanos(1);
+    const _ONE: usize = _ONE_SECOND.as_secs() as usize;
+    const _TWO: usize = _ONE_MILLISECOND.subsec_millis() as usize;
+    const _THREE: usize = _ONE_MICROSECOND.subsec_micros() as usize;
+    const _FOUR: usize = _ONE_NANOSECOND.subsec_nanos() as usize;
+    const _0: [[u8; _ONE]; _TWO] = [[1; _ONE]; _TWO];
+    const _1: [[u8; _THREE]; _FOUR] = [[3; _THREE]; _FOUR];
+}
diff --git a/src/test/ui/consts/const-eval/enum_discr.rs b/src/test/ui/consts/const-eval/enum_discr.rs
new file mode 100644
index 0000000..4851e75
--- /dev/null
+++ b/src/test/ui/consts/const-eval/enum_discr.rs
@@ -0,0 +1,26 @@
+// compile-pass
+// run-pass
+
+enum Foo {
+    X = 42,
+    Y = Foo::X as isize - 3,
+}
+
+enum Bar {
+    X,
+    Y = Bar::X as isize + 2,
+}
+
+enum Boo {
+    X = Boo::Y as isize * 2,
+    Y = 9,
+}
+
+fn main() {
+    assert_eq!(Foo::X as isize, 42);
+    assert_eq!(Foo::Y as isize, 39);
+    assert_eq!(Bar::X as isize, 0);
+    assert_eq!(Bar::Y as isize, 2);
+    assert_eq!(Boo::X as isize, 18);
+    assert_eq!(Boo::Y as isize, 9);
+}
diff --git a/src/test/ui/consts/const-eval/extern_fat_pointer.rs b/src/test/ui/consts/const-eval/extern_fat_pointer.rs
new file mode 100644
index 0000000..f8e6fd0
--- /dev/null
+++ b/src/test/ui/consts/const-eval/extern_fat_pointer.rs
@@ -0,0 +1,13 @@
+// compile-pass
+
+#![feature(extern_types)]
+
+extern {
+    type Opaque;
+}
+
+const FOO: *const u8 = &42 as *const _ as *const Opaque as *const u8;
+
+fn main() {
+    let _foo = FOO;
+}
diff --git a/src/test/ui/consts/const-eval/feature-gate-const_fn_union.rs b/src/test/ui/consts/const-eval/feature-gate-const_fn_union.rs
new file mode 100644
index 0000000..b0ae746
--- /dev/null
+++ b/src/test/ui/consts/const-eval/feature-gate-const_fn_union.rs
@@ -0,0 +1,12 @@
+#![feature(const_fn)]
+
+fn main() {}
+
+union Foo {
+    u: u32,
+    i: i32,
+}
+
+const unsafe fn foo(u: u32) -> i32 {
+    Foo { u }.i //~ ERROR unions in const fn are unstable
+}
diff --git a/src/test/ui/consts/const-eval/feature-gate-const_fn_union.stderr b/src/test/ui/consts/const-eval/feature-gate-const_fn_union.stderr
new file mode 100644
index 0000000..5a72c82
--- /dev/null
+++ b/src/test/ui/consts/const-eval/feature-gate-const_fn_union.stderr
@@ -0,0 +1,11 @@
+error[E0658]: unions in const fn are unstable (see issue #51909)
+  --> $DIR/feature-gate-const_fn_union.rs:11:5
+   |
+LL |     Foo { u }.i
+   |     ^^^^^^^^^^^
+   |
+   = help: add #![feature(const_fn_union)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/consts/const-eval/feature-gate-const_panic.rs b/src/test/ui/consts/const-eval/feature-gate-const_panic.rs
new file mode 100644
index 0000000..ba5b072
--- /dev/null
+++ b/src/test/ui/consts/const-eval/feature-gate-const_panic.rs
@@ -0,0 +1,10 @@
+fn main() {}
+
+const Z: () = panic!("cheese");
+//~^ ERROR panicking in constants is unstable
+
+const Y: () = unreachable!();
+//~^ ERROR panicking in constants is unstable
+
+const X: () = unimplemented!();
+//~^ ERROR panicking in constants is unstable
diff --git a/src/test/ui/consts/const-eval/feature-gate-const_panic.stderr b/src/test/ui/consts/const-eval/feature-gate-const_panic.stderr
new file mode 100644
index 0000000..0810341
--- /dev/null
+++ b/src/test/ui/consts/const-eval/feature-gate-const_panic.stderr
@@ -0,0 +1,30 @@
+error[E0658]: panicking in constants is unstable (see issue #51999)
+  --> $DIR/feature-gate-const_panic.rs:3:15
+   |
+LL | const Z: () = panic!("cheese");
+   |               ^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_panic)] to the crate attributes to enable
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error[E0658]: panicking in constants is unstable (see issue #51999)
+  --> $DIR/feature-gate-const_panic.rs:9:15
+   |
+LL | const X: () = unimplemented!();
+   |               ^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_panic)] to the crate attributes to enable
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error[E0658]: panicking in constants is unstable (see issue #51999)
+  --> $DIR/feature-gate-const_panic.rs:6:15
+   |
+LL | const Y: () = unreachable!();
+   |               ^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_panic)] to the crate attributes to enable
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/consts/const-eval/ice-generic-assoc-const.rs b/src/test/ui/consts/const-eval/ice-generic-assoc-const.rs
new file mode 100644
index 0000000..e92de84
--- /dev/null
+++ b/src/test/ui/consts/const-eval/ice-generic-assoc-const.rs
@@ -0,0 +1,18 @@
+// compile-pass
+
+pub trait Nullable {
+    const NULL: Self;
+
+    fn is_null(&self) -> bool;
+}
+
+impl<T> Nullable for *const T {
+    const NULL: Self = 0 as *const T;
+
+    fn is_null(&self) -> bool {
+        *self == Self::NULL
+    }
+}
+
+fn main() {
+}
diff --git a/src/test/ui/consts/const-eval/ice-packed.rs b/src/test/ui/consts/const-eval/ice-packed.rs
new file mode 100644
index 0000000..b9fe4ea
--- /dev/null
+++ b/src/test/ui/consts/const-eval/ice-packed.rs
@@ -0,0 +1,18 @@
+// compile-pass
+#[derive(Copy, Clone, PartialEq, Eq)]
+#[repr(packed)]
+pub struct Num(u64);
+
+impl Num {
+    pub const ZERO: Self = Num(0);
+}
+
+pub fn decrement(a: Num) -> Num {
+    match a {
+        Num::ZERO => Num::ZERO,
+        a => Num(a.0 - 1)
+    }
+}
+
+fn main() {
+}
diff --git a/src/test/ui/consts/const-eval/index_out_of_bounds.rs b/src/test/ui/consts/const-eval/index_out_of_bounds.rs
new file mode 100644
index 0000000..80e0d28
--- /dev/null
+++ b/src/test/ui/consts/const-eval/index_out_of_bounds.rs
@@ -0,0 +1,4 @@
+static FOO: i32 = [][0];
+//~^ ERROR E0080
+
+fn main() {}
diff --git a/src/test/ui/consts/const-eval/index_out_of_bounds.stderr b/src/test/ui/consts/const-eval/index_out_of_bounds.stderr
new file mode 100644
index 0000000..1b2974e
--- /dev/null
+++ b/src/test/ui/consts/const-eval/index_out_of_bounds.stderr
@@ -0,0 +1,9 @@
+error[E0080]: could not evaluate static initializer
+  --> $DIR/index_out_of_bounds.rs:1:19
+   |
+LL | static FOO: i32 = [][0];
+   |                   ^^^^^ index out of bounds: the len is 0 but the index is 0
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/index_out_of_bounds_propagated.rs b/src/test/ui/consts/const-eval/index_out_of_bounds_propagated.rs
new file mode 100644
index 0000000..4b487c0
--- /dev/null
+++ b/src/test/ui/consts/const-eval/index_out_of_bounds_propagated.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let array = [std::env::args().len()];
+    array[1]; //~ ERROR index out of bounds
+}
diff --git a/src/test/ui/consts/const-eval/index_out_of_bounds_propagated.stderr b/src/test/ui/consts/const-eval/index_out_of_bounds_propagated.stderr
new file mode 100644
index 0000000..ac045f2
--- /dev/null
+++ b/src/test/ui/consts/const-eval/index_out_of_bounds_propagated.stderr
@@ -0,0 +1,10 @@
+error: index out of bounds: the len is 1 but the index is 1
+  --> $DIR/index_out_of_bounds_propagated.rs:3:5
+   |
+LL |     array[1];
+   |     ^^^^^^^^
+   |
+   = note: #[deny(const_err)] on by default
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/consts/const-eval/infinite_loop.rs b/src/test/ui/consts/const-eval/infinite_loop.rs
new file mode 100644
index 0000000..a2a45af
--- /dev/null
+++ b/src/test/ui/consts/const-eval/infinite_loop.rs
@@ -0,0 +1,13 @@
+fn main() {
+    // Tests the Collatz conjecture with an incorrect base case (0 instead of 1).
+    // The value of `n` will loop indefinitely (4 - 2 - 1 - 4).
+    let _ = [(); {
+        //~^ WARNING Constant evaluating a complex constant, this might take some time
+        let mut n = 113383; // #20 in https://oeis.org/A006884
+        while n != 0 { //~ ERROR constant contains unimplemented expression type
+            n = if n % 2 == 0 { n/2 } else { 3*n + 1 };
+            //~^ ERROR evaluation of constant value failed
+        }
+        n
+    }];
+}
diff --git a/src/test/ui/consts/const-eval/infinite_loop.stderr b/src/test/ui/consts/const-eval/infinite_loop.stderr
new file mode 100644
index 0000000..ee696c5
--- /dev/null
+++ b/src/test/ui/consts/const-eval/infinite_loop.stderr
@@ -0,0 +1,32 @@
+error[E0019]: constant contains unimplemented expression type
+  --> $DIR/infinite_loop.rs:7:9
+   |
+LL | /         while n != 0 {
+LL | |             n = if n % 2 == 0 { n/2 } else { 3*n + 1 };
+LL | |
+LL | |         }
+   | |_________^
+
+warning: Constant evaluating a complex constant, this might take some time
+  --> $DIR/infinite_loop.rs:4:18
+   |
+LL |       let _ = [(); {
+   |  __________________^
+LL | |
+LL | |         let mut n = 113383; // #20 in https://oeis.org/A006884
+LL | |         while n != 0 {
+...  |
+LL | |         n
+LL | |     }];
+   | |_____^
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/infinite_loop.rs:8:20
+   |
+LL |             n = if n % 2 == 0 { n/2 } else { 3*n + 1 };
+   |                    ^^^^^^^^^^ duplicate interpreter state observed here, const evaluation will never terminate
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0019, E0080.
+For more information about an error, try `rustc --explain E0019`.
diff --git a/src/test/ui/consts/const-eval/issue-43197.rs b/src/test/ui/consts/const-eval/issue-43197.rs
new file mode 100644
index 0000000..4408620
--- /dev/null
+++ b/src/test/ui/consts/const-eval/issue-43197.rs
@@ -0,0 +1,15 @@
+#![warn(const_err)]
+
+const fn foo(x: u32) -> u32 {
+    x
+}
+
+fn main() {
+    const X: u32 = 0-1;
+    //~^ WARN any use of this value will cause
+    const Y: u32 = foo(0-1);
+    //~^ WARN any use of this value will cause
+    println!("{} {}", X, Y);
+    //~^ ERROR evaluation of constant expression failed
+    //~| ERROR evaluation of constant expression failed
+}
diff --git a/src/test/ui/consts/const-eval/issue-43197.stderr b/src/test/ui/consts/const-eval/issue-43197.stderr
new file mode 100644
index 0000000..478e453
--- /dev/null
+++ b/src/test/ui/consts/const-eval/issue-43197.stderr
@@ -0,0 +1,37 @@
+warning: any use of this value will cause an error
+  --> $DIR/issue-43197.rs:8:20
+   |
+LL |     const X: u32 = 0-1;
+   |     ---------------^^^-
+   |                    |
+   |                    attempt to subtract with overflow
+   |
+note: lint level defined here
+  --> $DIR/issue-43197.rs:1:9
+   |
+LL | #![warn(const_err)]
+   |         ^^^^^^^^^
+
+warning: any use of this value will cause an error
+  --> $DIR/issue-43197.rs:10:24
+   |
+LL |     const Y: u32 = foo(0-1);
+   |     -------------------^^^--
+   |                        |
+   |                        attempt to subtract with overflow
+
+error[E0080]: evaluation of constant expression failed
+  --> $DIR/issue-43197.rs:12:26
+   |
+LL |     println!("{} {}", X, Y);
+   |                          ^ referenced constant has errors
+
+error[E0080]: evaluation of constant expression failed
+  --> $DIR/issue-43197.rs:12:23
+   |
+LL |     println!("{} {}", X, Y);
+   |                       ^ referenced constant has errors
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/issue-44578.rs b/src/test/ui/consts/const-eval/issue-44578.rs
new file mode 100644
index 0000000..4d93130
--- /dev/null
+++ b/src/test/ui/consts/const-eval/issue-44578.rs
@@ -0,0 +1,27 @@
+#![allow(const_err)]
+
+trait Foo {
+    const AMT: usize;
+}
+
+enum Bar<A, B> {
+    First(A),
+    Second(B),
+}
+
+impl<A: Foo, B: Foo> Foo for Bar<A, B> {
+    const AMT: usize = [A::AMT][(A::AMT > B::AMT) as usize];
+}
+
+impl Foo for u8 {
+    const AMT: usize = 1;
+}
+
+impl Foo for u16 {
+    const AMT: usize = 2;
+}
+
+fn main() {
+    println!("{}", <Bar<u16, u8> as Foo>::AMT);
+    //~^ ERROR E0080
+}
diff --git a/src/test/ui/consts/const-eval/issue-44578.stderr b/src/test/ui/consts/const-eval/issue-44578.stderr
new file mode 100644
index 0000000..3fadeac
--- /dev/null
+++ b/src/test/ui/consts/const-eval/issue-44578.stderr
@@ -0,0 +1,9 @@
+error[E0080]: evaluation of constant expression failed
+  --> $DIR/issue-44578.rs:25:20
+   |
+LL |     println!("{}", <Bar<u16, u8> as Foo>::AMT);
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/issue-47971.rs b/src/test/ui/consts/const-eval/issue-47971.rs
new file mode 100644
index 0000000..9d7b05c
--- /dev/null
+++ b/src/test/ui/consts/const-eval/issue-47971.rs
@@ -0,0 +1,9 @@
+// compile-pass
+
+struct S(pub &'static u32, pub u32);
+
+const fn g(ss: &S) -> &u32 { &ss.1 }
+
+static T: S = S(g(&T), 0);
+
+fn main () { }
diff --git a/src/test/ui/consts/const-eval/issue-49296.rs b/src/test/ui/consts/const-eval/issue-49296.rs
new file mode 100644
index 0000000..a7c3c53
--- /dev/null
+++ b/src/test/ui/consts/const-eval/issue-49296.rs
@@ -0,0 +1,23 @@
+// issue-49296: Unsafe shenigans in constants can result in missing errors
+
+#![feature(const_fn)]
+#![feature(const_fn_union)]
+
+const unsafe fn transmute<T: Copy, U: Copy>(t: T) -> U {
+    union Transmute<T: Copy, U: Copy> {
+        from: T,
+        to: U,
+    }
+
+    Transmute { from: t }.to
+}
+
+const fn wat(x: u64) -> &'static u64 {
+    unsafe { transmute(&x) }
+}
+const X: u64 = *wat(42);
+//~^ ERROR any use of this value will cause an error
+
+fn main() {
+    println!("{}", X);
+}
diff --git a/src/test/ui/consts/const-eval/issue-49296.stderr b/src/test/ui/consts/const-eval/issue-49296.stderr
new file mode 100644
index 0000000..5a59a8b
--- /dev/null
+++ b/src/test/ui/consts/const-eval/issue-49296.stderr
@@ -0,0 +1,12 @@
+error: any use of this value will cause an error
+  --> $DIR/issue-49296.rs:18:16
+   |
+LL | const X: u64 = *wat(42);
+   | ---------------^^^^^^^^-
+   |                |
+   |                dangling pointer was dereferenced
+   |
+   = note: #[deny(const_err)] on by default
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/consts/const-eval/issue-50706.rs b/src/test/ui/consts/const-eval/issue-50706.rs
new file mode 100644
index 0000000..cb45b86
--- /dev/null
+++ b/src/test/ui/consts/const-eval/issue-50706.rs
@@ -0,0 +1,37 @@
+// compile-pass
+
+pub struct Stats;
+
+#[derive(PartialEq, Eq)]
+pub struct StatVariant {
+    pub id: u8,
+    _priv: (),
+}
+
+#[derive(PartialEq, Eq)]
+pub struct Stat {
+    pub variant: StatVariant,
+    pub index: usize,
+    _priv: (),
+}
+
+impl Stats {
+    pub const TEST: StatVariant = StatVariant{id: 0, _priv: (),};
+    #[allow(non_upper_case_globals)]
+    pub const A: Stat = Stat{
+         variant: Self::TEST,
+         index: 0,
+         _priv: (),};
+}
+
+impl Stat {
+    pub fn from_index(variant: StatVariant, index: usize) -> Option<Stat> {
+        let stat = Stat{variant, index, _priv: (),};
+        match stat {
+            Stats::A => Some(Stats::A),
+            _ => None,
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/consts/const-eval/issue-50814-2.rs b/src/test/ui/consts/const-eval/issue-50814-2.rs
new file mode 100644
index 0000000..b13c19c
--- /dev/null
+++ b/src/test/ui/consts/const-eval/issue-50814-2.rs
@@ -0,0 +1,32 @@
+trait C {
+    const BOO: usize;
+}
+
+trait Foo<T> {
+    const BAR: usize;
+}
+
+struct A<T>(T);
+
+impl<T: C> Foo<T> for A<T> {
+    const BAR: usize = [5, 6, 7][T::BOO]; //~ ERROR any use of this value will cause an error
+}
+
+fn foo<T: C>() -> &'static usize {
+    &<A<T> as Foo<T>>::BAR //~ ERROR E0080
+}
+
+impl C for () {
+    const BOO: usize = 42;
+}
+
+impl C for u32 {
+    const BOO: usize = 1;
+}
+
+fn main() {
+    println!("{:x}", foo::<()>() as *const usize as usize);
+    println!("{:x}", foo::<u32>() as *const usize as usize);
+    println!("{:x}", foo::<()>());
+    println!("{:x}", foo::<u32>());
+}
diff --git a/src/test/ui/consts/const-eval/issue-50814-2.stderr b/src/test/ui/consts/const-eval/issue-50814-2.stderr
new file mode 100644
index 0000000..da56004
--- /dev/null
+++ b/src/test/ui/consts/const-eval/issue-50814-2.stderr
@@ -0,0 +1,21 @@
+error: any use of this value will cause an error
+  --> $DIR/issue-50814-2.rs:12:24
+   |
+LL |     const BAR: usize = [5, 6, 7][T::BOO];
+   |     -------------------^^^^^^^^^^^^^^^^^-
+   |                        |
+   |                        index out of bounds: the len is 3 but the index is 42
+   |
+   = note: #[deny(const_err)] on by default
+
+error[E0080]: evaluation of constant expression failed
+  --> $DIR/issue-50814-2.rs:16:5
+   |
+LL |     &<A<T> as Foo<T>>::BAR
+   |     ^---------------------
+   |      |
+   |      referenced constant has errors
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/issue-50814.rs b/src/test/ui/consts/const-eval/issue-50814.rs
new file mode 100644
index 0000000..b85cecd
--- /dev/null
+++ b/src/test/ui/consts/const-eval/issue-50814.rs
@@ -0,0 +1,22 @@
+trait Unsigned {
+    const MAX: u8;
+}
+
+struct U8(u8);
+impl Unsigned for U8 {
+    const MAX: u8 = 0xff;
+}
+
+struct Sum<A,B>(A,B);
+
+impl<A: Unsigned, B: Unsigned> Unsigned for Sum<A,B> {
+    const MAX: u8 = A::MAX + B::MAX; //~ ERROR any use of this value will cause an error
+}
+
+fn foo<T>(_: T) -> &'static u8 {
+    &Sum::<U8,U8>::MAX //~ ERROR E0080
+}
+
+fn main() {
+    foo(0);
+}
diff --git a/src/test/ui/consts/const-eval/issue-50814.stderr b/src/test/ui/consts/const-eval/issue-50814.stderr
new file mode 100644
index 0000000..bc9443b
--- /dev/null
+++ b/src/test/ui/consts/const-eval/issue-50814.stderr
@@ -0,0 +1,21 @@
+error: any use of this value will cause an error
+  --> $DIR/issue-50814.rs:13:21
+   |
+LL |     const MAX: u8 = A::MAX + B::MAX;
+   |     ----------------^^^^^^^^^^^^^^^-
+   |                     |
+   |                     attempt to add with overflow
+   |
+   = note: #[deny(const_err)] on by default
+
+error[E0080]: evaluation of constant expression failed
+  --> $DIR/issue-50814.rs:17:5
+   |
+LL |     &Sum::<U8,U8>::MAX
+   |     ^-----------------
+   |      |
+   |      referenced constant has errors
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/issue-51300.rs b/src/test/ui/consts/const-eval/issue-51300.rs
new file mode 100644
index 0000000..72a6072e
--- /dev/null
+++ b/src/test/ui/consts/const-eval/issue-51300.rs
@@ -0,0 +1,31 @@
+// compile-pass
+// https://github.com/rust-lang/rust/issues/51300
+
+#[derive(PartialEq, Eq, Clone, Copy)]
+pub struct Stat {
+    pub id: u8,
+    pub index: usize,
+}
+
+impl Stat {
+    pub const STUDENT_HAPPINESS: Stat = Stat{
+        id: 0,
+        index: 0,
+    };
+    pub const STUDENT_HUNGER: Stat = Stat{
+        id: 0,
+        index: Self::STUDENT_HAPPINESS.index + 1,
+    };
+
+}
+
+pub fn from_index(id: u8, index: usize) -> Option<Stat> {
+    let stat = Stat{id, index};
+    match stat {
+        Stat::STUDENT_HAPPINESS => Some(Stat::STUDENT_HAPPINESS),
+        Stat::STUDENT_HUNGER => Some(Stat::STUDENT_HUNGER),
+        _ => None,
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/consts/const-eval/issue-52442.rs b/src/test/ui/consts/const-eval/issue-52442.rs
new file mode 100644
index 0000000..fadcde5
--- /dev/null
+++ b/src/test/ui/consts/const-eval/issue-52442.rs
@@ -0,0 +1,4 @@
+fn main() {
+    [();  { &loop { break } as *const _ as usize } ]; //~ ERROR unimplemented expression type
+    //~^ ERROR it is undefined behavior to use this value
+}
diff --git a/src/test/ui/consts/const-eval/issue-52442.stderr b/src/test/ui/consts/const-eval/issue-52442.stderr
new file mode 100644
index 0000000..2352ecb
--- /dev/null
+++ b/src/test/ui/consts/const-eval/issue-52442.stderr
@@ -0,0 +1,18 @@
+error[E0019]: constant contains unimplemented expression type
+  --> $DIR/issue-52442.rs:2:14
+   |
+LL |     [();  { &loop { break } as *const _ as usize } ];
+   |              ^^^^^^^^^^^^^^
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/issue-52442.rs:2:11
+   |
+LL |     [();  { &loop { break } as *const _ as usize } ];
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0019, E0080.
+For more information about an error, try `rustc --explain E0019`.
diff --git a/src/test/ui/consts/const-eval/issue-52475.rs b/src/test/ui/consts/const-eval/issue-52475.rs
new file mode 100644
index 0000000..aafdd5f
--- /dev/null
+++ b/src/test/ui/consts/const-eval/issue-52475.rs
@@ -0,0 +1,12 @@
+fn main() {
+    let _ = [(); {
+        //~^ WARNING Constant evaluating a complex constant, this might take some time
+        let mut x = &0;
+        let mut n = 0;
+        while n < 5 { //~ ERROR constant contains unimplemented expression type
+            n = (n + 1) % 5; //~ ERROR evaluation of constant value failed
+            x = &0; // Materialize a new AllocId
+        }
+        0
+    }];
+}
diff --git a/src/test/ui/consts/const-eval/issue-52475.stderr b/src/test/ui/consts/const-eval/issue-52475.stderr
new file mode 100644
index 0000000..605c71d
--- /dev/null
+++ b/src/test/ui/consts/const-eval/issue-52475.stderr
@@ -0,0 +1,32 @@
+error[E0019]: constant contains unimplemented expression type
+  --> $DIR/issue-52475.rs:6:9
+   |
+LL | /         while n < 5 {
+LL | |             n = (n + 1) % 5;
+LL | |             x = &0; // Materialize a new AllocId
+LL | |         }
+   | |_________^
+
+warning: Constant evaluating a complex constant, this might take some time
+  --> $DIR/issue-52475.rs:2:18
+   |
+LL |       let _ = [(); {
+   |  __________________^
+LL | |
+LL | |         let mut x = &0;
+LL | |         let mut n = 0;
+...  |
+LL | |         0
+LL | |     }];
+   | |_____^
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/issue-52475.rs:7:17
+   |
+LL |             n = (n + 1) % 5;
+   |                 ^^^^^^^^^^^ duplicate interpreter state observed here, const evaluation will never terminate
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0019, E0080.
+For more information about an error, try `rustc --explain E0019`.
diff --git a/src/test/ui/consts/const-eval/issue-53157.rs b/src/test/ui/consts/const-eval/issue-53157.rs
new file mode 100644
index 0000000..b995860
--- /dev/null
+++ b/src/test/ui/consts/const-eval/issue-53157.rs
@@ -0,0 +1,13 @@
+// compile-pass
+
+macro_rules! m {
+    () => {{
+        fn f(_: impl Sized) {}
+        f
+    }}
+}
+
+fn main() {
+    fn f() -> impl Sized {};
+    m!()(f());
+}
diff --git a/src/test/ui/consts/const-eval/issue-53401.rs b/src/test/ui/consts/const-eval/issue-53401.rs
new file mode 100644
index 0000000..89834aa
--- /dev/null
+++ b/src/test/ui/consts/const-eval/issue-53401.rs
@@ -0,0 +1,11 @@
+// compile-pass
+
+pub const STATIC_TRAIT: &Test = &();
+
+fn main() {}
+
+pub trait Test {
+    fn test() where Self: Sized {}
+}
+
+impl Test for () {}
diff --git a/src/test/ui/consts/const-eval/issue-55541.rs b/src/test/ui/consts/const-eval/issue-55541.rs
new file mode 100644
index 0000000..611fb89
--- /dev/null
+++ b/src/test/ui/consts/const-eval/issue-55541.rs
@@ -0,0 +1,27 @@
+// compile-pass
+
+// Test that we can handle newtypes wrapping extern types
+
+#![feature(extern_types, const_transmute)]
+
+use std::marker::PhantomData;
+
+extern "C" {
+  pub type ExternType;
+}
+unsafe impl Sync for ExternType {}
+static MAGIC_FFI_STATIC: u8 = 42;
+
+#[repr(transparent)]
+pub struct Wrapper(ExternType);
+pub static MAGIC_FFI_REF: &'static Wrapper = unsafe {
+  std::mem::transmute(&MAGIC_FFI_STATIC)
+};
+
+#[repr(transparent)]
+pub struct Wrapper2(PhantomData<Vec<i32>>, ExternType);
+pub static MAGIC_FFI_REF2: &'static Wrapper2 = unsafe {
+  std::mem::transmute(&MAGIC_FFI_STATIC)
+};
+
+fn main() {}
diff --git a/src/test/ui/consts/const-eval/match-test-ptr-null.rs b/src/test/ui/consts/const-eval/match-test-ptr-null.rs
new file mode 100644
index 0000000..b27b816
--- /dev/null
+++ b/src/test/ui/consts/const-eval/match-test-ptr-null.rs
@@ -0,0 +1,13 @@
+fn main() {
+    // Make sure match uses the usual pointer comparison code path -- i.e., it should complain
+    // that pointer comparison is disallowed, not that parts of a pointer are accessed as raw
+    // bytes.
+    let _: [u8; 0] = [4; {
+        match &1 as *const i32 as usize { //~ ERROR casting pointers to integers in constants
+            0 => 42, //~ ERROR constant contains unimplemented expression type
+            //~^ NOTE "pointer arithmetic or comparison" needs an rfc before being allowed
+            //~| ERROR evaluation of constant value failed
+            n => n,
+        }
+    }];
+}
diff --git a/src/test/ui/consts/const-eval/match-test-ptr-null.stderr b/src/test/ui/consts/const-eval/match-test-ptr-null.stderr
new file mode 100644
index 0000000..fd5647c
--- /dev/null
+++ b/src/test/ui/consts/const-eval/match-test-ptr-null.stderr
@@ -0,0 +1,24 @@
+error[E0658]: casting pointers to integers in constants is unstable (see issue #51910)
+  --> $DIR/match-test-ptr-null.rs:6:15
+   |
+LL |         match &1 as *const i32 as usize {
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_raw_ptr_to_usize_cast)] to the crate attributes to enable
+
+error[E0019]: constant contains unimplemented expression type
+  --> $DIR/match-test-ptr-null.rs:7:13
+   |
+LL |             0 => 42,
+   |             ^
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/match-test-ptr-null.rs:7:13
+   |
+LL |             0 => 42,
+   |             ^ "pointer arithmetic or comparison" needs an rfc before being allowed inside constants
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0019, E0080, E0658.
+For more information about an error, try `rustc --explain E0019`.
diff --git a/src/test/ui/consts/const-eval/mod-static-with-const-fn.rs b/src/test/ui/consts/const-eval/mod-static-with-const-fn.rs
new file mode 100644
index 0000000..32f0062
--- /dev/null
+++ b/src/test/ui/consts/const-eval/mod-static-with-const-fn.rs
@@ -0,0 +1,27 @@
+// New test for #53818: modifying static memory at compile-time is not allowed.
+// The test should never compile successfully
+
+#![feature(const_raw_ptr_deref)]
+
+use std::cell::UnsafeCell;
+
+struct Foo(UnsafeCell<u32>);
+
+unsafe impl Send for Foo {}
+unsafe impl Sync for Foo {}
+
+static FOO: Foo = Foo(UnsafeCell::new(42));
+
+fn foo() {}
+
+static BAR: () = unsafe {
+    *FOO.0.get() = 5;
+    //~^ contains unimplemented expression
+
+    foo();
+    //~^ ERROR calls in statics are limited to constant functions, tuple structs and tuple variants
+};
+
+fn main() {
+    println!("{}", unsafe { *FOO.0.get() });
+}
diff --git a/src/test/ui/consts/const-eval/mod-static-with-const-fn.stderr b/src/test/ui/consts/const-eval/mod-static-with-const-fn.stderr
new file mode 100644
index 0000000..9fad686
--- /dev/null
+++ b/src/test/ui/consts/const-eval/mod-static-with-const-fn.stderr
@@ -0,0 +1,16 @@
+error[E0019]: static contains unimplemented expression type
+  --> $DIR/mod-static-with-const-fn.rs:18:5
+   |
+LL |     *FOO.0.get() = 5;
+   |     ^^^^^^^^^^^^^^^^
+
+error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
+  --> $DIR/mod-static-with-const-fn.rs:21:5
+   |
+LL |     foo();
+   |     ^^^^^
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0015, E0019.
+For more information about an error, try `rustc --explain E0015`.
diff --git a/src/test/ui/consts/const-eval/no_lint_for_statically_known_error.rs b/src/test/ui/consts/const-eval/no_lint_for_statically_known_error.rs
new file mode 100644
index 0000000..0d14cf0
--- /dev/null
+++ b/src/test/ui/consts/const-eval/no_lint_for_statically_known_error.rs
@@ -0,0 +1,18 @@
+// compile-pass
+
+// if `X` were used instead of `x`, `X - 10` would result in a lint.
+// This file should never produce a lint, no matter how the const
+// propagator is improved.
+
+#![deny(warnings)]
+
+const X: u32 = 5;
+
+fn main() {
+    let x = X;
+    if x > 10 {
+        println!("{}", x - 10);
+    } else {
+        println!("{}", 10 - x);
+    }
+}
diff --git a/src/test/ui/consts/const-eval/promote_mutable_zst_mir_borrowck.rs b/src/test/ui/consts/const-eval/promote_mutable_zst_mir_borrowck.rs
new file mode 100644
index 0000000..06b1727
--- /dev/null
+++ b/src/test/ui/consts/const-eval/promote_mutable_zst_mir_borrowck.rs
@@ -0,0 +1,7 @@
+// compile-pass
+
+#![feature(nll)]
+
+pub fn main() {
+    let y: &'static mut [u8; 0] = &mut [];
+}
diff --git a/src/test/ui/consts/const-eval/promoted_const_fn_fail.nll.stderr b/src/test/ui/consts/const-eval/promoted_const_fn_fail.nll.stderr
new file mode 100644
index 0000000..519ba7d
--- /dev/null
+++ b/src/test/ui/consts/const-eval/promoted_const_fn_fail.nll.stderr
@@ -0,0 +1,14 @@
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promoted_const_fn_fail.rs:20:27
+   |
+LL |     let x: &'static u8 = &(bar() + 1);
+   |            -----------    ^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+...
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/src/test/ui/consts/const-eval/promoted_const_fn_fail.rs b/src/test/ui/consts/const-eval/promoted_const_fn_fail.rs
new file mode 100644
index 0000000..80562b0
--- /dev/null
+++ b/src/test/ui/consts/const-eval/promoted_const_fn_fail.rs
@@ -0,0 +1,23 @@
+#![feature(const_fn, const_fn_union)]
+
+#![allow(const_err)]
+
+union Bar {
+    a: &'static u8,
+    b: usize,
+}
+
+const fn bar() -> u8 {
+    unsafe {
+        // this will error as long as this test
+        // is run on a system whose pointers need more
+        // than 8 bits
+        Bar { a: &42 }.b as u8
+    }
+}
+
+fn main() {
+    let x: &'static u8 = &(bar() + 1); //~ ERROR does not live long enough
+    let y = *x;
+    unreachable!();
+}
diff --git a/src/test/ui/consts/const-eval/promoted_const_fn_fail.stderr b/src/test/ui/consts/const-eval/promoted_const_fn_fail.stderr
new file mode 100644
index 0000000..c9a357d
--- /dev/null
+++ b/src/test/ui/consts/const-eval/promoted_const_fn_fail.stderr
@@ -0,0 +1,14 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/promoted_const_fn_fail.rs:20:27
+   |
+LL |     let x: &'static u8 = &(bar() + 1);
+   |                           ^^^^^^^^^^^ temporary value does not live long enough
+...
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.nll.stderr b/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.nll.stderr
new file mode 100644
index 0000000..987d230
--- /dev/null
+++ b/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.nll.stderr
@@ -0,0 +1,14 @@
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promoted_const_fn_fail_deny_const_err.rs:21:27
+   |
+LL |     let x: &'static u8 = &(bar() + 1);
+   |            -----------    ^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+...
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.rs b/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.rs
new file mode 100644
index 0000000..f331e44
--- /dev/null
+++ b/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.rs
@@ -0,0 +1,25 @@
+#![feature(const_fn, const_fn_union)]
+
+#![deny(const_err)]
+
+union Bar {
+    a: &'static u8,
+    b: usize,
+}
+
+const fn bar() -> u8 {
+    unsafe {
+        // This will error as long as this test is run on a system whose
+        // pointers need more than 8 bits.
+        Bar { a: &42 }.b as u8
+    }
+}
+
+fn main() {
+    // This will compile, but then hard-abort at runtime.
+    // FIXME(oli-obk): this should instead panic (not hard-abort) at runtime.
+    let x: &'static u8 = &(bar() + 1);
+    //~^ ERROR does not live long enough
+    let y = *x;
+    unreachable!();
+}
diff --git a/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.stderr b/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.stderr
new file mode 100644
index 0000000..9c786b0
--- /dev/null
+++ b/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.stderr
@@ -0,0 +1,14 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/promoted_const_fn_fail_deny_const_err.rs:21:27
+   |
+LL |     let x: &'static u8 = &(bar() + 1);
+   |                           ^^^^^^^^^^^ temporary value does not live long enough
+...
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/consts/const-eval/promoted_errors.rs b/src/test/ui/consts/const-eval/promoted_errors.rs
new file mode 100644
index 0000000..ebf80e7
--- /dev/null
+++ b/src/test/ui/consts/const-eval/promoted_errors.rs
@@ -0,0 +1,19 @@
+#![warn(const_err)]
+
+// compile-pass
+// compile-flags: -O
+fn main() {
+    println!("{}", 0u32 - 1);
+    let _x = 0u32 - 1;
+    //~^ WARN const_err
+    println!("{}", 1/(1-1));
+    //~^ WARN const_err
+    let _x = 1/(1-1);
+    //~^ WARN const_err
+    //~| WARN const_err
+    println!("{}", 1/(false as u32));
+    //~^ WARN const_err
+    let _x = 1/(false as u32);
+    //~^ WARN const_err
+    //~| WARN const_err
+}
diff --git a/src/test/ui/consts/const-eval/promoted_errors.stderr b/src/test/ui/consts/const-eval/promoted_errors.stderr
new file mode 100644
index 0000000..c9d5ede
--- /dev/null
+++ b/src/test/ui/consts/const-eval/promoted_errors.stderr
@@ -0,0 +1,60 @@
+warning: this expression will panic at runtime
+  --> $DIR/promoted_errors.rs:7:14
+   |
+LL |     let _x = 0u32 - 1;
+   |              ^^^^^^^^ attempt to subtract with overflow
+   |
+note: lint level defined here
+  --> $DIR/promoted_errors.rs:1:9
+   |
+LL | #![warn(const_err)]
+   |         ^^^^^^^^^
+
+warning: attempt to divide by zero
+  --> $DIR/promoted_errors.rs:9:20
+   |
+LL |     println!("{}", 1/(1-1));
+   |                    ^^^^^^^
+
+warning: attempt to divide by zero
+  --> $DIR/promoted_errors.rs:11:14
+   |
+LL |     let _x = 1/(1-1);
+   |              ^^^^^^^
+
+warning: this expression will panic at runtime
+  --> $DIR/promoted_errors.rs:11:14
+   |
+LL |     let _x = 1/(1-1);
+   |              ^^^^^^^ attempt to divide by zero
+
+warning: attempt to divide by zero
+  --> $DIR/promoted_errors.rs:14:20
+   |
+LL |     println!("{}", 1/(false as u32));
+   |                    ^^^^^^^^^^^^^^^^
+
+warning: attempt to divide by zero
+  --> $DIR/promoted_errors.rs:16:14
+   |
+LL |     let _x = 1/(false as u32);
+   |              ^^^^^^^^^^^^^^^^
+
+warning: this expression will panic at runtime
+  --> $DIR/promoted_errors.rs:16:14
+   |
+LL |     let _x = 1/(false as u32);
+   |              ^^^^^^^^^^^^^^^^ attempt to divide by zero
+
+warning: reaching this expression at runtime will panic or abort
+  --> $DIR/promoted_errors.rs:14:20
+   |
+LL |     println!("{}", 1/(false as u32));
+   |                    ^^^^^^^^^^^^^^^^ attempt to divide by zero
+
+warning: reaching this expression at runtime will panic or abort
+  --> $DIR/promoted_errors.rs:9:20
+   |
+LL |     println!("{}", 1/(1-1));
+   |                    ^^^^^^^ attempt to divide by zero
+
diff --git a/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.nll.stderr b/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.nll.stderr
new file mode 100644
index 0000000..a8bb697
--- /dev/null
+++ b/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.nll.stderr
@@ -0,0 +1,46 @@
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promoted_raw_ptr_ops.rs:4:29
+   |
+LL |     let x: &'static bool = &(42 as *const i32 == 43 as *const i32);
+   |            -------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+...
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promoted_raw_ptr_ops.rs:6:30
+   |
+LL |     let y: &'static usize = &(&1 as *const i32 as usize + 1);
+   |            --------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+...
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promoted_raw_ptr_ops.rs:7:28
+   |
+LL |     let z: &'static i32 = &(unsafe { *(42 as *const i32) });
+   |            ------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+LL |     let a: &'static bool = &(main as fn() == main as fn());
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promoted_raw_ptr_ops.rs:8:29
+   |
+LL |     let a: &'static bool = &(main as fn() == main as fn());
+   |            -------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.rs b/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.rs
new file mode 100644
index 0000000..ef7e550
--- /dev/null
+++ b/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.rs
@@ -0,0 +1,9 @@
+#![feature(const_raw_ptr_to_usize_cast, const_compare_raw_pointers, const_raw_ptr_deref)]
+
+fn main() {
+    let x: &'static bool = &(42 as *const i32 == 43 as *const i32);
+    //~^ ERROR does not live long enough
+    let y: &'static usize = &(&1 as *const i32 as usize + 1); //~ ERROR does not live long enough
+    let z: &'static i32 = &(unsafe { *(42 as *const i32) }); //~ ERROR does not live long enough
+    let a: &'static bool = &(main as fn() == main as fn()); //~ ERROR does not live long enough
+}
diff --git a/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.stderr b/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.stderr
new file mode 100644
index 0000000..5a0654c
--- /dev/null
+++ b/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.stderr
@@ -0,0 +1,46 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/promoted_raw_ptr_ops.rs:4:29
+   |
+LL |     let x: &'static bool = &(42 as *const i32 == 43 as *const i32);
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+...
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/promoted_raw_ptr_ops.rs:6:30
+   |
+LL |     let y: &'static usize = &(&1 as *const i32 as usize + 1);
+   |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+...
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/promoted_raw_ptr_ops.rs:7:28
+   |
+LL |     let z: &'static i32 = &(unsafe { *(42 as *const i32) });
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+LL |     let a: &'static bool = &(main as fn() == main as fn());
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/promoted_raw_ptr_ops.rs:8:29
+   |
+LL |     let a: &'static bool = &(main as fn() == main as fn());
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/consts/const-eval/pub_const_err.rs b/src/test/ui/consts/const-eval/pub_const_err.rs
new file mode 100644
index 0000000..d882dad
--- /dev/null
+++ b/src/test/ui/consts/const-eval/pub_const_err.rs
@@ -0,0 +1,9 @@
+// compile-pass
+#![warn(const_err)]
+
+#![crate_type = "lib"]
+
+pub const Z: u32 = 0 - 1;
+//~^ WARN any use of this value will cause an error
+
+pub type Foo = [i32; 0 - 1];
diff --git a/src/test/ui/consts/const-eval/pub_const_err.stderr b/src/test/ui/consts/const-eval/pub_const_err.stderr
new file mode 100644
index 0000000..bd262b6
--- /dev/null
+++ b/src/test/ui/consts/const-eval/pub_const_err.stderr
@@ -0,0 +1,14 @@
+warning: any use of this value will cause an error
+  --> $DIR/pub_const_err.rs:6:20
+   |
+LL | pub const Z: u32 = 0 - 1;
+   | -------------------^^^^^-
+   |                    |
+   |                    attempt to subtract with overflow
+   |
+note: lint level defined here
+  --> $DIR/pub_const_err.rs:2:9
+   |
+LL | #![warn(const_err)]
+   |         ^^^^^^^^^
+
diff --git a/src/test/ui/consts/const-eval/pub_const_err_bin.rs b/src/test/ui/consts/const-eval/pub_const_err_bin.rs
new file mode 100644
index 0000000..dee09b7
--- /dev/null
+++ b/src/test/ui/consts/const-eval/pub_const_err_bin.rs
@@ -0,0 +1,9 @@
+// compile-pass
+#![warn(const_err)]
+
+pub const Z: u32 = 0 - 1;
+//~^ WARN any use of this value will cause an error
+
+pub type Foo = [i32; 0 - 1];
+
+fn main() {}
diff --git a/src/test/ui/consts/const-eval/pub_const_err_bin.stderr b/src/test/ui/consts/const-eval/pub_const_err_bin.stderr
new file mode 100644
index 0000000..866d175
--- /dev/null
+++ b/src/test/ui/consts/const-eval/pub_const_err_bin.stderr
@@ -0,0 +1,14 @@
+warning: any use of this value will cause an error
+  --> $DIR/pub_const_err_bin.rs:4:20
+   |
+LL | pub const Z: u32 = 0 - 1;
+   | -------------------^^^^^-
+   |                    |
+   |                    attempt to subtract with overflow
+   |
+note: lint level defined here
+  --> $DIR/pub_const_err_bin.rs:2:9
+   |
+LL | #![warn(const_err)]
+   |         ^^^^^^^^^
+
diff --git a/src/test/ui/consts/const-eval/ref_to_int_match.rs b/src/test/ui/consts/const-eval/ref_to_int_match.rs
new file mode 100644
index 0000000..b6a2ed1
--- /dev/null
+++ b/src/test/ui/consts/const-eval/ref_to_int_match.rs
@@ -0,0 +1,23 @@
+#![feature(const_fn_union)]
+
+fn main() {
+    let n: Int = 40;
+    match n {
+        0..=10 => {},
+        10..=BAR => {}, //~ ERROR could not evaluate constant pattern
+        _ => {},
+    }
+}
+
+union Foo {
+    f: Int,
+    r: &'static u32,
+}
+
+#[cfg(target_pointer_width="64")]
+type Int = u64;
+
+#[cfg(target_pointer_width="32")]
+type Int = u32;
+
+const BAR: Int = unsafe { Foo { r: &42 }.f }; //~ ERROR it is undefined behavior to use this value
diff --git a/src/test/ui/consts/const-eval/ref_to_int_match.stderr b/src/test/ui/consts/const-eval/ref_to_int_match.stderr
new file mode 100644
index 0000000..f8eafed
--- /dev/null
+++ b/src/test/ui/consts/const-eval/ref_to_int_match.stderr
@@ -0,0 +1,17 @@
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ref_to_int_match.rs:23:1
+   |
+LL | const BAR: Int = unsafe { Foo { r: &42 }.f };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error: could not evaluate constant pattern
+  --> $DIR/ref_to_int_match.rs:7:14
+   |
+LL |         10..=BAR => {},
+   |              ^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/shift_overflow.rs b/src/test/ui/consts/const-eval/shift_overflow.rs
new file mode 100644
index 0000000..f7d0f6b
--- /dev/null
+++ b/src/test/ui/consts/const-eval/shift_overflow.rs
@@ -0,0 +1,9 @@
+enum Foo {
+    // test that we detect overflows for non-u32 discriminants
+    X = 1 << ((u32::max_value() as u64) + 1), //~ ERROR E0080
+    Y = 42,
+}
+
+
+fn main() {
+}
diff --git a/src/test/ui/consts/const-eval/shift_overflow.stderr b/src/test/ui/consts/const-eval/shift_overflow.stderr
new file mode 100644
index 0000000..5db231c
--- /dev/null
+++ b/src/test/ui/consts/const-eval/shift_overflow.stderr
@@ -0,0 +1,9 @@
+error[E0080]: evaluation of constant value failed
+  --> $DIR/shift_overflow.rs:3:9
+   |
+LL |     X = 1 << ((u32::max_value() as u64) + 1),
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to shift left with overflow
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/simple_with_undef.rs b/src/test/ui/consts/const-eval/simple_with_undef.rs
new file mode 100644
index 0000000..61398f3
--- /dev/null
+++ b/src/test/ui/consts/const-eval/simple_with_undef.rs
@@ -0,0 +1,6 @@
+// compile-pass
+
+const PARSE_BOOL: Option<&'static str> = None;
+static FOO: (Option<&str>, u32) = (PARSE_BOOL, 42);
+
+fn main() {}
diff --git a/src/test/ui/consts/const-eval/strlen.rs b/src/test/ui/consts/const-eval/strlen.rs
new file mode 100644
index 0000000..6a5cad8
--- /dev/null
+++ b/src/test/ui/consts/const-eval/strlen.rs
@@ -0,0 +1,23 @@
+// run-pass
+
+#![feature(const_str_len, const_str_as_bytes)]
+
+const S: &str = "foo";
+pub const B: &[u8] = S.as_bytes();
+
+pub fn foo() -> [u8; S.len()] {
+    let mut buf = [0; S.len()];
+    for (i, &c) in S.as_bytes().iter().enumerate() {
+        buf[i] = c;
+    }
+    buf
+}
+
+fn main() {
+    assert_eq!(&foo()[..], b"foo");
+    assert_eq!(foo().len(), S.len());
+    const LEN: usize = S.len();
+    assert_eq!(LEN, S.len());
+    assert_eq!(B, foo());
+    assert_eq!(B, b"foo");
+}
diff --git a/src/test/ui/consts/const-eval/transmute-const-promotion.nll.stderr b/src/test/ui/consts/const-eval/transmute-const-promotion.nll.stderr
new file mode 100644
index 0000000..5aae8c1
--- /dev/null
+++ b/src/test/ui/consts/const-eval/transmute-const-promotion.nll.stderr
@@ -0,0 +1,14 @@
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/transmute-const-promotion.rs:6:37
+   |
+LL |     let x: &'static u32 = unsafe { &mem::transmute(3.0f32) };
+   |            ------------             ^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+LL |
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/src/test/ui/consts/const-eval/transmute-const-promotion.rs b/src/test/ui/consts/const-eval/transmute-const-promotion.rs
new file mode 100644
index 0000000..a1da350
--- /dev/null
+++ b/src/test/ui/consts/const-eval/transmute-const-promotion.rs
@@ -0,0 +1,8 @@
+#![feature(const_transmute)]
+
+use std::mem;
+
+fn main() {
+    let x: &'static u32 = unsafe { &mem::transmute(3.0f32) };
+    //~^ ERROR value does not live long enough
+}
diff --git a/src/test/ui/consts/const-eval/transmute-const-promotion.stderr b/src/test/ui/consts/const-eval/transmute-const-promotion.stderr
new file mode 100644
index 0000000..5829a17
--- /dev/null
+++ b/src/test/ui/consts/const-eval/transmute-const-promotion.stderr
@@ -0,0 +1,14 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/transmute-const-promotion.rs:6:37
+   |
+LL |     let x: &'static u32 = unsafe { &mem::transmute(3.0f32) };
+   |                                     ^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+LL |
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/consts/const-eval/transmute-const.rs b/src/test/ui/consts/const-eval/transmute-const.rs
new file mode 100644
index 0000000..48f2b39
--- /dev/null
+++ b/src/test/ui/consts/const-eval/transmute-const.rs
@@ -0,0 +1,8 @@
+#![feature(const_transmute)]
+
+use std::mem;
+
+static FOO: bool = unsafe { mem::transmute(3u8) };
+//~^ ERROR it is undefined behavior to use this value
+
+fn main() {}
diff --git a/src/test/ui/consts/const-eval/transmute-const.stderr b/src/test/ui/consts/const-eval/transmute-const.stderr
new file mode 100644
index 0000000..cacf863
--- /dev/null
+++ b/src/test/ui/consts/const-eval/transmute-const.stderr
@@ -0,0 +1,11 @@
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/transmute-const.rs:5:1
+   |
+LL | static FOO: bool = unsafe { mem::transmute(3u8) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3, but expected something less or equal to 1
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/ub-enum.rs b/src/test/ui/consts/const-eval/ub-enum.rs
new file mode 100644
index 0000000..fe8675d
--- /dev/null
+++ b/src/test/ui/consts/const-eval/ub-enum.rs
@@ -0,0 +1,60 @@
+#![allow(const_err)] // make sure we cannot allow away the errors tested here
+
+#[repr(usize)]
+#[derive(Copy, Clone)]
+enum Enum {
+    A = 0,
+}
+union TransmuteEnum {
+    in1: &'static u8,
+    out1: Enum,
+}
+
+// A pointer is guaranteed non-null
+const BAD_ENUM: Enum = unsafe { TransmuteEnum { in1: &1 }.out1 };
+//~^ ERROR is undefined behavior
+
+// (Potentially) invalid enum discriminant
+#[repr(usize)]
+#[derive(Copy, Clone)]
+enum Enum2 {
+    A = 2,
+}
+#[repr(transparent)]
+#[derive(Copy, Clone)]
+struct Wrap<T>(T);
+union TransmuteEnum2 {
+    in1: usize,
+    in2: &'static u8,
+    in3: (),
+    out1: Enum2,
+    out2: Wrap<Enum2>, // something wrapping the enum so that we test layout first, not enum
+    out3: Option<Enum2>,
+}
+const BAD_ENUM2: Enum2 = unsafe { TransmuteEnum2 { in1: 0 }.out1 };
+//~^ ERROR is undefined behavior
+const BAD_ENUM3: Enum2 = unsafe { TransmuteEnum2 { in2: &0 }.out1 };
+//~^ ERROR is undefined behavior
+const BAD_ENUM4: Wrap<Enum2> = unsafe { TransmuteEnum2 { in2: &0 }.out2 };
+//~^ ERROR is undefined behavior
+
+// Undef enum discriminant.
+const BAD_ENUM_UNDEF : Enum2 = unsafe { TransmuteEnum2 { in3: () }.out1 };
+//~^ ERROR is undefined behavior
+
+// Pointer value in an enum with a niche that is not just 0.
+const BAD_ENUM_PTR: Option<Enum2> = unsafe { TransmuteEnum2 { in2: &0 }.out3 };
+//~^ ERROR is undefined behavior
+
+// Invalid enum field content (mostly to test printing of paths for enum tuple
+// variants and tuples).
+union TransmuteChar {
+    a: u32,
+    b: char,
+}
+// Need to create something which does not clash with enum layout optimizations.
+const BAD_ENUM_CHAR: Option<(char, char)> = Some(('x', unsafe { TransmuteChar { a: !0 }.b }));
+//~^ ERROR is undefined behavior
+
+fn main() {
+}
diff --git a/src/test/ui/consts/const-eval/ub-enum.stderr b/src/test/ui/consts/const-eval/ub-enum.stderr
new file mode 100644
index 0000000..2bf4cf9
--- /dev/null
+++ b/src/test/ui/consts/const-eval/ub-enum.stderr
@@ -0,0 +1,59 @@
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-enum.rs:14:1
+   |
+LL | const BAD_ENUM: Enum = unsafe { TransmuteEnum { in1: &1 }.out1 };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected a valid enum discriminant
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-enum.rs:34:1
+   |
+LL | const BAD_ENUM2: Enum2 = unsafe { TransmuteEnum2 { in1: 0 }.out1 };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected a valid enum discriminant
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-enum.rs:36:1
+   |
+LL | const BAD_ENUM3: Enum2 = unsafe { TransmuteEnum2 { in2: &0 }.out1 };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected a valid enum discriminant
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-enum.rs:38:1
+   |
+LL | const BAD_ENUM4: Wrap<Enum2> = unsafe { TransmuteEnum2 { in2: &0 }.out2 };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected something that cannot possibly fail to be in the range 2..=2
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-enum.rs:42:1
+   |
+LL | const BAD_ENUM_UNDEF : Enum2 = unsafe { TransmuteEnum2 { in3: () }.out1 };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected a valid enum discriminant
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-enum.rs:46:1
+   |
+LL | const BAD_ENUM_PTR: Option<Enum2> = unsafe { TransmuteEnum2 { in2: &0 }.out3 };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected a valid enum discriminant
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-enum.rs:56:1
+   |
+LL | const BAD_ENUM_CHAR: Option<(char, char)> = Some(('x', unsafe { TransmuteChar { a: !0 }.b }));
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 4294967295 at .<downcast-variant(Some)>.0.1, but expected something less or equal to 1114111
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/ub-nonnull.rs b/src/test/ui/consts/const-eval/ub-nonnull.rs
new file mode 100644
index 0000000..3e0b094
--- /dev/null
+++ b/src/test/ui/consts/const-eval/ub-nonnull.rs
@@ -0,0 +1,37 @@
+#![feature(rustc_attrs, const_transmute)]
+#![allow(const_err)] // make sure we cannot allow away the errors tested here
+
+use std::mem;
+use std::ptr::NonNull;
+use std::num::{NonZeroU8, NonZeroUsize};
+
+const NULL_PTR: NonNull<u8> = unsafe { mem::transmute(0usize) };
+//~^ ERROR it is undefined behavior to use this value
+
+const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) };
+//~^ ERROR it is undefined behavior to use this value
+const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) };
+//~^ ERROR it is undefined behavior to use this value
+
+union Transmute {
+    uninit: (),
+    out: NonZeroU8,
+}
+const UNINIT: NonZeroU8 = unsafe { Transmute { uninit: () }.out };
+//~^ ERROR it is undefined behavior to use this value
+
+// Also test other uses of rustc_layout_scalar_valid_range_start
+
+#[rustc_layout_scalar_valid_range_start(10)]
+#[rustc_layout_scalar_valid_range_end(30)]
+struct RestrictedRange1(u32);
+const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) };
+//~^ ERROR it is undefined behavior to use this value
+
+#[rustc_layout_scalar_valid_range_start(30)]
+#[rustc_layout_scalar_valid_range_end(10)]
+struct RestrictedRange2(u32);
+const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) };
+//~^ ERROR it is undefined behavior to use this value
+
+fn main() {}
diff --git a/src/test/ui/consts/const-eval/ub-nonnull.stderr b/src/test/ui/consts/const-eval/ub-nonnull.stderr
new file mode 100644
index 0000000..6230712
--- /dev/null
+++ b/src/test/ui/consts/const-eval/ub-nonnull.stderr
@@ -0,0 +1,51 @@
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-nonnull.rs:8:1
+   |
+LL | const NULL_PTR: NonNull<u8> = unsafe { mem::transmute(0usize) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-nonnull.rs:11:1
+   |
+LL | const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-nonnull.rs:13:1
+   |
+LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-nonnull.rs:20:1
+   |
+LL | const UNINIT: NonZeroU8 = unsafe { Transmute { uninit: () }.out };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected something greater or equal to 1
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-nonnull.rs:28:1
+   |
+LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 42, but expected something in the range 10..=30
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-nonnull.rs:34:1
+   |
+LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 20, but expected something less or equal to 10, or greater or equal to 30
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/ub-ref.rs b/src/test/ui/consts/const-eval/ub-ref.rs
new file mode 100644
index 0000000..0d8f301
--- /dev/null
+++ b/src/test/ui/consts/const-eval/ub-ref.rs
@@ -0,0 +1,23 @@
+// ignore-tidy-linelength
+#![feature(const_transmute)]
+#![allow(const_err)] // make sure we cannot allow away the errors tested here
+
+use std::mem;
+
+const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) };
+//~^ ERROR it is undefined behavior to use this value
+//~^^ type validation failed: encountered unaligned reference (required 2 byte alignment but found 1)
+
+const NULL: &u16 = unsafe { mem::transmute(0usize) };
+//~^ ERROR it is undefined behavior to use this value
+
+const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) };
+//~^ ERROR it is undefined behavior to use this value
+
+const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
+//~^ ERROR it is undefined behavior to use this value
+
+const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) };
+//~^ ERROR it is undefined behavior to use this value
+
+fn main() {}
diff --git a/src/test/ui/consts/const-eval/ub-ref.stderr b/src/test/ui/consts/const-eval/ub-ref.stderr
new file mode 100644
index 0000000..33535c2
--- /dev/null
+++ b/src/test/ui/consts/const-eval/ub-ref.stderr
@@ -0,0 +1,43 @@
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-ref.rs:7:1
+   |
+LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered unaligned reference (required 2 byte alignment but found 1)
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-ref.rs:11:1
+   |
+LL | const NULL: &u16 = unsafe { mem::transmute(0usize) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-ref.rs:14:1
+   |
+LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-ref.rs:17:1
+   |
+LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .<deref>, but expected plain (non-pointer) bytes
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-ref.rs:20:1
+   |
+LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered integer pointer in non-ZST reference
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/ub-uninhabit.rs b/src/test/ui/consts/const-eval/ub-uninhabit.rs
new file mode 100644
index 0000000..42cba02
--- /dev/null
+++ b/src/test/ui/consts/const-eval/ub-uninhabit.rs
@@ -0,0 +1,23 @@
+#![feature(const_transmute)]
+#![allow(const_err)] // make sure we cannot allow away the errors tested here
+
+use std::mem;
+
+#[derive(Copy, Clone)]
+enum Bar {}
+
+union TransmuteUnion<A: Clone + Copy, B: Clone + Copy> {
+    a: A,
+    b: B,
+}
+
+const BAD_BAD_BAD: Bar = unsafe { (TransmuteUnion::<(), Bar> { a: () }).b };
+//~^ ERROR it is undefined behavior to use this value
+
+const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) };
+//~^ ERROR it is undefined behavior to use this value
+
+const BAD_BAD_ARRAY: [Bar; 1] = unsafe { (TransmuteUnion::<(), [Bar; 1]> { a: () }).b };
+//~^ ERROR it is undefined behavior to use this value
+
+fn main() {}
diff --git a/src/test/ui/consts/const-eval/ub-uninhabit.stderr b/src/test/ui/consts/const-eval/ub-uninhabit.stderr
new file mode 100644
index 0000000..c8842ec
--- /dev/null
+++ b/src/test/ui/consts/const-eval/ub-uninhabit.stderr
@@ -0,0 +1,27 @@
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-uninhabit.rs:14:1
+   |
+LL | const BAD_BAD_BAD: Bar = unsafe { (TransmuteUnion::<(), Bar> { a: () }).b };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-uninhabit.rs:17:1
+   |
+LL | const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type at .<deref>
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-uninhabit.rs:20:1
+   |
+LL | const BAD_BAD_ARRAY: [Bar; 1] = unsafe { (TransmuteUnion::<(), [Bar; 1]> { a: () }).b };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/ub-upvars.rs b/src/test/ui/consts/const-eval/ub-upvars.rs
new file mode 100644
index 0000000..9b7bca6
--- /dev/null
+++ b/src/test/ui/consts/const-eval/ub-upvars.rs
@@ -0,0 +1,12 @@
+#![feature(const_transmute)]
+#![allow(const_err)] // make sure we cannot allow away the errors tested here
+
+use std::mem;
+
+const BAD_UPVAR: &FnOnce() = &{ //~ ERROR it is undefined behavior to use this value
+    let bad_ref: &'static u16 = unsafe { mem::transmute(0usize) };
+    let another_var = 13;
+    move || { let _ = bad_ref; let _ = another_var; }
+};
+
+fn main() {}
diff --git a/src/test/ui/consts/const-eval/ub-upvars.stderr b/src/test/ui/consts/const-eval/ub-upvars.stderr
new file mode 100644
index 0000000..21d2847
--- /dev/null
+++ b/src/test/ui/consts/const-eval/ub-upvars.stderr
@@ -0,0 +1,15 @@
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-upvars.rs:6:1
+   |
+LL | / const BAD_UPVAR: &FnOnce() = &{
+LL | |     let bad_ref: &'static u16 = unsafe { mem::transmute(0usize) };
+LL | |     let another_var = 13;
+LL | |     move || { let _ = bad_ref; let _ = another_var; }
+LL | | };
+   | |__^ type validation failed: encountered 0 at .<deref>.<dyn-downcast>.<closure-var(bad_ref)>, but expected something greater or equal to 1
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/union-const-eval-field.rs b/src/test/ui/consts/const-eval/union-const-eval-field.rs
new file mode 100644
index 0000000..56f3ef3
--- /dev/null
+++ b/src/test/ui/consts/const-eval/union-const-eval-field.rs
@@ -0,0 +1,36 @@
+#![feature(const_fn)]
+
+type Field1 = i32;
+type Field2 = f32;
+type Field3 = i64;
+
+union DummyUnion {
+    field1: Field1,
+    field2: Field2,
+    field3: Field3,
+}
+
+const FLOAT1_AS_I32: i32 = 1065353216;
+const UNION: DummyUnion = DummyUnion { field1: FLOAT1_AS_I32 };
+
+const fn read_field1() -> Field1 {
+    const FIELD1: Field1 = unsafe { UNION.field1 };
+    FIELD1
+}
+
+const fn read_field2() -> Field2 {
+    const FIELD2: Field2 = unsafe { UNION.field2 };
+    FIELD2
+}
+
+const fn read_field3() -> Field3 {
+    const FIELD3: Field3 = unsafe { UNION.field3 };
+    //~^ ERROR it is undefined behavior to use this value
+    FIELD3
+}
+
+fn main() {
+    assert_eq!(read_field1(), FLOAT1_AS_I32);
+    assert_eq!(read_field2(), 1.0);
+    assert_eq!(read_field3(), unsafe { UNION.field3 });
+}
diff --git a/src/test/ui/consts/const-eval/union-const-eval-field.stderr b/src/test/ui/consts/const-eval/union-const-eval-field.stderr
new file mode 100644
index 0000000..4a53337
--- /dev/null
+++ b/src/test/ui/consts/const-eval/union-const-eval-field.stderr
@@ -0,0 +1,11 @@
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/union-const-eval-field.rs:27:5
+   |
+LL |     const FIELD3: Field3 = unsafe { UNION.field3 };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected initialized plain (non-pointer) bytes
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/union-ice.rs b/src/test/ui/consts/const-eval/union-ice.rs
new file mode 100644
index 0000000..33736b3
--- /dev/null
+++ b/src/test/ui/consts/const-eval/union-ice.rs
@@ -0,0 +1,41 @@
+#![feature(const_fn)]
+
+type Field1 = i32;
+type Field3 = i64;
+
+union DummyUnion {
+    field1: Field1,
+    field3: Field3,
+}
+
+const UNION: DummyUnion = DummyUnion { field1: 1065353216 };
+
+const FIELD3: Field3 = unsafe { UNION.field3 }; //~ ERROR it is undefined behavior to use this value
+
+const FIELD_PATH: Struct = Struct { //~ ERROR it is undefined behavior to use this value
+    a: 42,
+    b: unsafe { UNION.field3 },
+};
+
+struct Struct {
+    a: u8,
+    b: Field3,
+}
+
+const FIELD_PATH2: Struct2 = Struct2 { //~ ERROR it is undefined behavior to use this value
+    b: [
+        21,
+        unsafe { UNION.field3 },
+        23,
+        24,
+    ],
+    a: 42,
+};
+
+struct Struct2 {
+    b: [Field3; 4],
+    a: u8,
+}
+
+fn main() {
+}
diff --git a/src/test/ui/consts/const-eval/union-ice.stderr b/src/test/ui/consts/const-eval/union-ice.stderr
new file mode 100644
index 0000000..b25cb8c
--- /dev/null
+++ b/src/test/ui/consts/const-eval/union-ice.stderr
@@ -0,0 +1,36 @@
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/union-ice.rs:13:1
+   |
+LL | const FIELD3: Field3 = unsafe { UNION.field3 };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected initialized plain (non-pointer) bytes
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/union-ice.rs:15:1
+   |
+LL | / const FIELD_PATH: Struct = Struct {
+LL | |     a: 42,
+LL | |     b: unsafe { UNION.field3 },
+LL | | };
+   | |__^ type validation failed: encountered uninitialized bytes at .b, but expected initialized plain (non-pointer) bytes
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/union-ice.rs:25:1
+   |
+LL | / const FIELD_PATH2: Struct2 = Struct2 {
+LL | |     b: [
+LL | |         21,
+LL | |         unsafe { UNION.field3 },
+...  |
+LL | |     a: 42,
+LL | | };
+   | |__^ type validation failed: encountered undefined bytes at .b[1]
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/union-ub-fat-ptr.rs b/src/test/ui/consts/const-eval/union-ub-fat-ptr.rs
new file mode 100644
index 0000000..13489c5
--- /dev/null
+++ b/src/test/ui/consts/const-eval/union-ub-fat-ptr.rs
@@ -0,0 +1,131 @@
+#![allow(unused)]
+#![allow(const_err)] // make sure we cannot allow away the errors tested here
+
+// normalize-stderr-test "alignment \d+" -> "alignment N"
+// normalize-stderr-test "offset \d+" -> "offset N"
+// normalize-stderr-test "allocation \d+" -> "allocation N"
+// normalize-stderr-test "size \d+" -> "size N"
+
+union BoolTransmute {
+  val: u8,
+  bl: bool,
+}
+
+#[repr(C)]
+#[derive(Copy, Clone)]
+struct SliceRepr {
+    ptr: *const u8,
+    len: usize,
+}
+
+#[repr(C)]
+#[derive(Copy, Clone)]
+struct BadSliceRepr {
+    ptr: *const u8,
+    len: &'static u8,
+}
+
+union SliceTransmute {
+    repr: SliceRepr,
+    bad: BadSliceRepr,
+    slice: &'static [u8],
+    str: &'static str,
+    my_str: &'static MyStr,
+    my_slice: &'static MySliceBool,
+}
+
+#[repr(C)]
+#[derive(Copy, Clone)]
+struct DynRepr {
+    ptr: *const u8,
+    vtable: *const u8,
+}
+
+#[repr(C)]
+#[derive(Copy, Clone)]
+struct DynRepr2 {
+    ptr: *const u8,
+    vtable: *const u64,
+}
+
+#[repr(C)]
+#[derive(Copy, Clone)]
+struct BadDynRepr {
+    ptr: *const u8,
+    vtable: usize,
+}
+
+union DynTransmute {
+    repr: DynRepr,
+    repr2: DynRepr2,
+    bad: BadDynRepr,
+    rust: &'static Trait,
+}
+
+trait Trait {}
+impl Trait for bool {}
+
+// custom unsized type
+struct MyStr(str);
+
+// custom unsized type with sized fields
+struct MySlice<T: ?Sized>(bool, T);
+type MySliceBool = MySlice<[bool]>;
+
+// OK
+const A: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 1 } }.str};
+// bad str
+const B: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.str};
+//~^ ERROR it is undefined behavior to use this value
+// bad str
+const C: &str = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.str};
+//~^ ERROR it is undefined behavior to use this value
+// bad str in user-defined unsized type
+const C2: &MyStr = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.my_str};
+//~^ ERROR it is undefined behavior to use this value
+
+// OK
+const A2: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 1 } }.slice};
+// bad slice
+const B2: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.slice};
+//~^ ERROR it is undefined behavior to use this value
+// bad slice
+const C3: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.slice};
+//~^ ERROR it is undefined behavior to use this value
+
+// bad trait object
+const D: &Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust};
+//~^ ERROR it is undefined behavior to use this value
+// bad trait object
+const E: &Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust};
+//~^ ERROR it is undefined behavior to use this value
+// bad trait object
+const F: &Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust};
+//~^ ERROR it is undefined behavior to use this value
+
+// bad data *inside* the trait object
+const G: &Trait = &unsafe { BoolTransmute { val: 3 }.bl };
+//~^ ERROR it is undefined behavior to use this value
+
+// bad data *inside* the slice
+const H: &[bool] = &[unsafe { BoolTransmute { val: 3 }.bl }];
+//~^ ERROR it is undefined behavior to use this value
+
+// good MySliceBool
+const I1: &MySliceBool = &MySlice(true, [false]);
+// bad: sized field is not okay
+const I2: &MySliceBool = &MySlice(unsafe { BoolTransmute { val: 3 }.bl }, [false]);
+//~^ ERROR it is undefined behavior to use this value
+// bad: unsized part is not okay
+const I3: &MySliceBool = &MySlice(true, [unsafe { BoolTransmute { val: 3 }.bl }]);
+//~^ ERROR it is undefined behavior to use this value
+
+// invalid UTF-8
+const J1: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str };
+//~^ ERROR it is undefined behavior to use this value
+// invalid UTF-8 in user-defined str-like
+const J2: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my_str };
+//~^ ERROR it is undefined behavior to use this value
+
+fn main() {
+}
diff --git a/src/test/ui/consts/const-eval/union-ub-fat-ptr.stderr b/src/test/ui/consts/const-eval/union-ub-fat-ptr.stderr
new file mode 100644
index 0000000..761a5fc4
--- /dev/null
+++ b/src/test/ui/consts/const-eval/union-ub-fat-ptr.stderr
@@ -0,0 +1,115 @@
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/union-ub-fat-ptr.rs:78:1
+   |
+LL | const B: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.str};
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling (not entirely in bounds) reference
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/union-ub-fat-ptr.rs:81:1
+   |
+LL | const C: &str = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.str};
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in fat pointer
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/union-ub-fat-ptr.rs:84:1
+   |
+LL | const C2: &MyStr = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.my_str};
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in fat pointer
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/union-ub-fat-ptr.rs:90:1
+   |
+LL | const B2: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.slice};
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling (not entirely in bounds) reference
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/union-ub-fat-ptr.rs:93:1
+   |
+LL | const C3: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.slice};
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in fat pointer
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/union-ub-fat-ptr.rs:97:1
+   |
+LL | const D: &Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust};
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid drop fn in vtable
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/union-ub-fat-ptr.rs:100:1
+   |
+LL | const E: &Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust};
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid drop fn in vtable
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/union-ub-fat-ptr.rs:103:1
+   |
+LL | const F: &Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust};
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-pointer vtable in fat pointer
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/union-ub-fat-ptr.rs:107:1
+   |
+LL | const G: &Trait = &unsafe { BoolTransmute { val: 3 }.bl };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>.<dyn-downcast>, but expected something less or equal to 1
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/union-ub-fat-ptr.rs:111:1
+   |
+LL | const H: &[bool] = &[unsafe { BoolTransmute { val: 3 }.bl }];
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>[0], but expected something less or equal to 1
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/union-ub-fat-ptr.rs:117:1
+   |
+LL | const I2: &MySliceBool = &MySlice(unsafe { BoolTransmute { val: 3 }.bl }, [false]);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>.0, but expected something less or equal to 1
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/union-ub-fat-ptr.rs:120:1
+   |
+LL | const I3: &MySliceBool = &MySlice(true, [unsafe { BoolTransmute { val: 3 }.bl }]);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>.1[0], but expected something less or equal to 1
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/union-ub-fat-ptr.rs:124:1
+   |
+LL | const J1: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at .<deref>
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/union-ub-fat-ptr.rs:127:1
+   |
+LL | const J2: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my_str };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at .<deref>.0
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error: aborting due to 14 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/union-ub.rs b/src/test/ui/consts/const-eval/union-ub.rs
new file mode 100644
index 0000000..cf43614
--- /dev/null
+++ b/src/test/ui/consts/const-eval/union-ub.rs
@@ -0,0 +1,36 @@
+#![allow(const_err)] // make sure we cannot allow away the errors tested here
+
+union DummyUnion {
+    u8: u8,
+    bool: bool,
+}
+
+#[repr(C)]
+#[derive(Copy, Clone)]
+enum Enum {
+    A,
+    B,
+    C,
+}
+
+#[derive(Copy, Clone)]
+union Foo {
+    a: bool,
+    b: Enum,
+}
+
+union Bar {
+    foo: Foo,
+    u8: u8,
+}
+
+// the value is not valid for bools
+const BAD_BOOL: bool = unsafe { DummyUnion { u8: 42 }.bool};
+//~^ ERROR it is undefined behavior to use this value
+
+// The value is not valid for any union variant, but that's fine
+// unions are just a convenient way to transmute bits around
+const BAD_UNION: Foo = unsafe { Bar { u8: 42 }.foo };
+
+
+fn main() {}
diff --git a/src/test/ui/consts/const-eval/union-ub.stderr b/src/test/ui/consts/const-eval/union-ub.stderr
new file mode 100644
index 0000000..7baa55b
--- /dev/null
+++ b/src/test/ui/consts/const-eval/union-ub.stderr
@@ -0,0 +1,11 @@
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/union-ub.rs:28:1
+   |
+LL | const BAD_BOOL: bool = unsafe { DummyUnion { u8: 42 }.bool};
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 42, but expected something less or equal to 1
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/union_promotion.nll.stderr b/src/test/ui/consts/const-eval/union_promotion.nll.stderr
new file mode 100644
index 0000000..b530c02
--- /dev/null
+++ b/src/test/ui/consts/const-eval/union_promotion.nll.stderr
@@ -0,0 +1,16 @@
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/union_promotion.rs:9:29
+   |
+LL |       let x: &'static bool = &unsafe {
+   |  ____________-------------____^
+   | |            |
+   | |            type annotation requires that borrow lasts for `'static`
+LL | |         Foo { a: &1 }.b == Foo { a: &2 }.b
+LL | |     };
+   | |_____^ creates a temporary which is freed while still in use
+LL |   }
+   |   - temporary value is freed at the end of this statement
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/src/test/ui/consts/const-eval/union_promotion.rs b/src/test/ui/consts/const-eval/union_promotion.rs
new file mode 100644
index 0000000..c308c81
--- /dev/null
+++ b/src/test/ui/consts/const-eval/union_promotion.rs
@@ -0,0 +1,12 @@
+#![allow(const_err)]
+
+union Foo {
+    a: &'static u32,
+    b: usize,
+}
+
+fn main() {
+    let x: &'static bool = &unsafe { //~ borrowed value does not live long enough
+        Foo { a: &1 }.b == Foo { a: &2 }.b
+    };
+}
diff --git a/src/test/ui/consts/const-eval/union_promotion.stderr b/src/test/ui/consts/const-eval/union_promotion.stderr
new file mode 100644
index 0000000..c60f671
--- /dev/null
+++ b/src/test/ui/consts/const-eval/union_promotion.stderr
@@ -0,0 +1,16 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/union_promotion.rs:9:29
+   |
+LL |       let x: &'static bool = &unsafe {
+   |  _____________________________^
+LL | |         Foo { a: &1 }.b == Foo { a: &2 }.b
+LL | |     };
+   | |_____^ temporary value does not live long enough
+LL |   }
+   |   - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/consts/const-eval/unused-broken-const.rs b/src/test/ui/consts/const-eval/unused-broken-const.rs
new file mode 100644
index 0000000..56b16e2
--- /dev/null
+++ b/src/test/ui/consts/const-eval/unused-broken-const.rs
@@ -0,0 +1,8 @@
+// make sure that an *unused* broken const triggers an error even in a check build
+
+// compile-flags: --emit=dep-info,metadata
+
+const FOO: i32 = [][0];
+//~^ ERROR any use of this value will cause an error
+
+fn main() {}
diff --git a/src/test/ui/consts/const-eval/unused-broken-const.stderr b/src/test/ui/consts/const-eval/unused-broken-const.stderr
new file mode 100644
index 0000000..603efe4
--- /dev/null
+++ b/src/test/ui/consts/const-eval/unused-broken-const.stderr
@@ -0,0 +1,14 @@
+warning: due to multiple output types requested, the explicitly specified output file name will be adapted for each output type
+
+error: any use of this value will cause an error
+  --> $DIR/unused-broken-const.rs:5:18
+   |
+LL | const FOO: i32 = [][0];
+   | -----------------^^^^^-
+   |                  |
+   |                  index out of bounds: the len is 0 but the index is 0
+   |
+   = note: #[deny(const_err)] on by default
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/consts/const-eval/valid-const.rs b/src/test/ui/consts/const-eval/valid-const.rs
new file mode 100644
index 0000000..a195e12
--- /dev/null
+++ b/src/test/ui/consts/const-eval/valid-const.rs
@@ -0,0 +1,18 @@
+// compile-pass
+
+// Some constants that *are* valid
+#![feature(const_transmute)]
+
+use std::mem;
+use std::ptr::NonNull;
+use std::num::{NonZeroU8, NonZeroUsize};
+
+const NON_NULL_PTR1: NonNull<u8> = unsafe { mem::transmute(1usize) };
+const NON_NULL_PTR2: NonNull<u8> = unsafe { mem::transmute(&0) };
+
+const NON_NULL_U8: NonZeroU8 = unsafe { mem::transmute(1u8) };
+const NON_NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(1usize) };
+
+const UNIT: () = ();
+
+fn main() {}
diff --git a/src/test/ui/consts/const-eval/zst_operand_eval.rs b/src/test/ui/consts/const-eval/zst_operand_eval.rs
new file mode 100644
index 0000000..d837da1
--- /dev/null
+++ b/src/test/ui/consts/const-eval/zst_operand_eval.rs
@@ -0,0 +1,5 @@
+// compile-pass
+
+static ASSERT: () = [()][!(std::mem::size_of::<u32>() == 4) as usize];
+
+fn main() {}
diff --git a/src/test/ui/consts/const-expr-addr-operator.rs b/src/test/ui/consts/const-expr-addr-operator.rs
new file mode 100644
index 0000000..dc9f292
--- /dev/null
+++ b/src/test/ui/consts/const-expr-addr-operator.rs
@@ -0,0 +1,11 @@
+// Encountered while testing #44614.
+// compile-pass
+
+pub fn main() {
+    // Constant of generic type (int)
+    const X: &'static u32 = &22;
+    assert_eq!(0, match &22 {
+        X => 0,
+        _ => 1,
+    });
+}
diff --git a/src/test/ui/consts/const-fn-destructuring-arg.rs b/src/test/ui/consts/const-fn-destructuring-arg.rs
new file mode 100644
index 0000000..dcf89f9
--- /dev/null
+++ b/src/test/ui/consts/const-fn-destructuring-arg.rs
@@ -0,0 +1,7 @@
+// compile-pass
+
+const fn i((a, b): (u32, u32)) -> u32 {
+    a + b
+}
+
+fn main() {}
diff --git a/src/test/ui/consts/const-fn-mismatch.rs b/src/test/ui/consts/const-fn-mismatch.rs
new file mode 100644
index 0000000..5bd274f
--- /dev/null
+++ b/src/test/ui/consts/const-fn-mismatch.rs
@@ -0,0 +1,17 @@
+// Test that we can't declare a const fn in an impl -- right now it's
+// just not allowed at all, though eventually it'd make sense to allow
+// it if the trait fn is const (but right now no trait fns can be
+// const).
+
+#![feature(const_fn)]
+
+trait Foo {
+    fn f() -> u32;
+}
+
+impl Foo for u32 {
+    const fn f() -> u32 { 22 }
+    //~^ ERROR trait fns cannot be declared const
+}
+
+fn main() { }
diff --git a/src/test/ui/consts/const-fn-mismatch.stderr b/src/test/ui/consts/const-fn-mismatch.stderr
new file mode 100644
index 0000000..03bb7c6
--- /dev/null
+++ b/src/test/ui/consts/const-fn-mismatch.stderr
@@ -0,0 +1,9 @@
+error[E0379]: trait fns cannot be declared const
+  --> $DIR/const-fn-mismatch.rs:13:5
+   |
+LL |     const fn f() -> u32 { 22 }
+   |     ^^^^^ trait fns cannot be const
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0379`.
diff --git a/src/test/ui/consts/const-fn-not-in-trait.rs b/src/test/ui/consts/const-fn-not-in-trait.rs
new file mode 100644
index 0000000..3975c22
--- /dev/null
+++ b/src/test/ui/consts/const-fn-not-in-trait.rs
@@ -0,0 +1,13 @@
+// Test that const fn is illegal in a trait declaration, whether or
+// not a default is provided.
+
+#![feature(const_fn)]
+
+trait Foo {
+    const fn f() -> u32;
+    //~^ ERROR trait fns cannot be declared const
+    const fn g() -> u32 { 0 }
+    //~^ ERROR trait fns cannot be declared const
+}
+
+fn main() { }
diff --git a/src/test/ui/consts/const-fn-not-in-trait.stderr b/src/test/ui/consts/const-fn-not-in-trait.stderr
new file mode 100644
index 0000000..6821a6c
--- /dev/null
+++ b/src/test/ui/consts/const-fn-not-in-trait.stderr
@@ -0,0 +1,15 @@
+error[E0379]: trait fns cannot be declared const
+  --> $DIR/const-fn-not-in-trait.rs:7:5
+   |
+LL |     const fn f() -> u32;
+   |     ^^^^^ trait fns cannot be const
+
+error[E0379]: trait fns cannot be declared const
+  --> $DIR/const-fn-not-in-trait.rs:9:5
+   |
+LL |     const fn g() -> u32 { 0 }
+   |     ^^^^^ trait fns cannot be const
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0379`.
diff --git a/src/test/ui/consts/const-fn-not-safe-for-const.rs b/src/test/ui/consts/const-fn-not-safe-for-const.rs
new file mode 100644
index 0000000..085ff5c
--- /dev/null
+++ b/src/test/ui/consts/const-fn-not-safe-for-const.rs
@@ -0,0 +1,35 @@
+// Test that we can't call random fns in a const fn or do other bad things.
+
+#![feature(const_fn, const_transmute)]
+
+use std::mem::transmute;
+
+fn random() -> u32 { 0 }
+
+const fn sub(x: &u32) -> usize {
+    unsafe { transmute(x) }
+}
+
+const fn sub1() -> u32 {
+    random() //~ ERROR E0015
+}
+
+static Y: u32 = 0;
+
+const fn get_Y() -> u32 {
+    Y
+        //~^ ERROR E0013
+}
+
+const fn get_Y_addr() -> &'static u32 {
+    &Y
+        //~^ ERROR E0013
+}
+
+const fn get() -> u32 {
+    let x = 22;
+    let y = 44;
+    x + y
+}
+
+fn main() {}
diff --git a/src/test/ui/consts/const-fn-not-safe-for-const.stderr b/src/test/ui/consts/const-fn-not-safe-for-const.stderr
new file mode 100644
index 0000000..a5e4807
--- /dev/null
+++ b/src/test/ui/consts/const-fn-not-safe-for-const.stderr
@@ -0,0 +1,22 @@
+error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
+  --> $DIR/const-fn-not-safe-for-const.rs:14:5
+   |
+LL |     random()
+   |     ^^^^^^^^
+
+error[E0013]: constant functions cannot refer to statics, use a constant instead
+  --> $DIR/const-fn-not-safe-for-const.rs:20:5
+   |
+LL |     Y
+   |     ^
+
+error[E0013]: constant functions cannot refer to statics, use a constant instead
+  --> $DIR/const-fn-not-safe-for-const.rs:25:5
+   |
+LL |     &Y
+   |     ^^
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0013, E0015.
+For more information about an error, try `rustc --explain E0013`.
diff --git a/src/test/ui/consts/const-fn-stability-calls-3.rs b/src/test/ui/consts/const-fn-stability-calls-3.rs
new file mode 100644
index 0000000..44bcca8
--- /dev/null
+++ b/src/test/ui/consts/const-fn-stability-calls-3.rs
@@ -0,0 +1,15 @@
+// Test use of const fn from another crate without a feature gate.
+
+// compile-pass
+// skip-codegen
+#![allow(unused_variables)]
+// aux-build:const_fn_lib.rs
+
+extern crate const_fn_lib;
+
+use const_fn_lib::foo;
+
+
+fn main() {
+    let x = foo(); // use outside a constant is ok
+}
diff --git a/src/test/ui/consts/const-int-conversion.nll.stderr b/src/test/ui/consts/const-int-conversion.nll.stderr
new file mode 100644
index 0000000..65330e2
--- /dev/null
+++ b/src/test/ui/consts/const-int-conversion.nll.stderr
@@ -0,0 +1,80 @@
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/const-int-conversion.rs:4:28
+   |
+LL |     let x: &'static i32 = &(5_i32.reverse_bits());
+   |            ------------    ^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+...
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/const-int-conversion.rs:6:28
+   |
+LL |     let y: &'static i32 = &(i32::from_be_bytes([0x12, 0x34, 0x56, 0x78]));
+   |            ------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+...
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/const-int-conversion.rs:8:28
+   |
+LL |     let z: &'static i32 = &(i32::from_le_bytes([0x12, 0x34, 0x56, 0x78]));
+   |            ------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+...
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/const-int-conversion.rs:10:28
+   |
+LL |     let a: &'static i32 = &(i32::from_be(i32::from_ne_bytes([0x80, 0, 0, 0])));
+   |            ------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+...
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/const-int-conversion.rs:12:29
+   |
+LL |     let b: &'static [u8] = &(0x12_34_56_78_i32.to_be_bytes());
+   |            -------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+...
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/const-int-conversion.rs:14:29
+   |
+LL |     let c: &'static [u8] = &(0x12_34_56_78_i32.to_le_bytes());
+   |            -------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+...
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/const-int-conversion.rs:16:29
+   |
+LL |     let d: &'static [u8] = &(i32::min_value().to_be().to_ne_bytes());
+   |            -------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+LL |
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/src/test/ui/consts/const-int-conversion.rs b/src/test/ui/consts/const-int-conversion.rs
new file mode 100644
index 0000000..8f0aa14
--- /dev/null
+++ b/src/test/ui/consts/const-int-conversion.rs
@@ -0,0 +1,18 @@
+#![feature(reverse_bits)]
+
+fn main() {
+    let x: &'static i32 = &(5_i32.reverse_bits());
+        //~^ ERROR does not live long enough
+    let y: &'static i32 = &(i32::from_be_bytes([0x12, 0x34, 0x56, 0x78]));
+        //~^ ERROR does not live long enough
+    let z: &'static i32 = &(i32::from_le_bytes([0x12, 0x34, 0x56, 0x78]));
+        //~^ ERROR does not live long enough
+    let a: &'static i32 = &(i32::from_be(i32::from_ne_bytes([0x80, 0, 0, 0])));
+        //~^ ERROR does not live long enough
+    let b: &'static [u8] = &(0x12_34_56_78_i32.to_be_bytes());
+        //~^ ERROR does not live long enough
+    let c: &'static [u8] = &(0x12_34_56_78_i32.to_le_bytes());
+        //~^ ERROR does not live long enough
+    let d: &'static [u8] = &(i32::min_value().to_be().to_ne_bytes());
+        //~^ ERROR does not live long enough
+}
diff --git a/src/test/ui/consts/const-int-conversion.stderr b/src/test/ui/consts/const-int-conversion.stderr
new file mode 100644
index 0000000..ddb1a75
--- /dev/null
+++ b/src/test/ui/consts/const-int-conversion.stderr
@@ -0,0 +1,80 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/const-int-conversion.rs:4:28
+   |
+LL |     let x: &'static i32 = &(5_i32.reverse_bits());
+   |                            ^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+...
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/const-int-conversion.rs:6:28
+   |
+LL |     let y: &'static i32 = &(i32::from_be_bytes([0x12, 0x34, 0x56, 0x78]));
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+...
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/const-int-conversion.rs:8:28
+   |
+LL |     let z: &'static i32 = &(i32::from_le_bytes([0x12, 0x34, 0x56, 0x78]));
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+...
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/const-int-conversion.rs:10:28
+   |
+LL |     let a: &'static i32 = &(i32::from_be(i32::from_ne_bytes([0x80, 0, 0, 0])));
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+...
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/const-int-conversion.rs:12:29
+   |
+LL |     let b: &'static [u8] = &(0x12_34_56_78_i32.to_be_bytes());
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+...
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/const-int-conversion.rs:14:29
+   |
+LL |     let c: &'static [u8] = &(0x12_34_56_78_i32.to_le_bytes());
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+...
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/const-int-conversion.rs:16:29
+   |
+LL |     let d: &'static [u8] = &(i32::min_value().to_be().to_ne_bytes());
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+LL |
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/consts/const-int-overflowing.nll.stderr b/src/test/ui/consts/const-int-overflowing.nll.stderr
new file mode 100644
index 0000000..bd061ab
--- /dev/null
+++ b/src/test/ui/consts/const-int-overflowing.nll.stderr
@@ -0,0 +1,35 @@
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/const-int-overflowing.rs:2:36
+   |
+LL |     let x: &'static (i32, bool) = &(5_i32.overflowing_add(3));
+   |            --------------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+...
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/const-int-overflowing.rs:3:36
+   |
+LL |     let y: &'static (i32, bool) = &(5_i32.overflowing_sub(3));
+   |            --------------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+LL |     let z: &'static (i32, bool) = &(5_i32.overflowing_mul(3));
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/const-int-overflowing.rs:4:36
+   |
+LL |     let z: &'static (i32, bool) = &(5_i32.overflowing_mul(3));
+   |            --------------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/src/test/ui/consts/const-int-overflowing.rs b/src/test/ui/consts/const-int-overflowing.rs
new file mode 100644
index 0000000..4e69e85
--- /dev/null
+++ b/src/test/ui/consts/const-int-overflowing.rs
@@ -0,0 +1,5 @@
+fn main() {
+    let x: &'static (i32, bool) = &(5_i32.overflowing_add(3)); //~ ERROR does not live long enough
+    let y: &'static (i32, bool) = &(5_i32.overflowing_sub(3)); //~ ERROR does not live long enough
+    let z: &'static (i32, bool) = &(5_i32.overflowing_mul(3)); //~ ERROR does not live long enough
+}
diff --git a/src/test/ui/consts/const-int-overflowing.stderr b/src/test/ui/consts/const-int-overflowing.stderr
new file mode 100644
index 0000000..7228b5d
--- /dev/null
+++ b/src/test/ui/consts/const-int-overflowing.stderr
@@ -0,0 +1,35 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/const-int-overflowing.rs:2:36
+   |
+LL |     let x: &'static (i32, bool) = &(5_i32.overflowing_add(3));
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+...
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/const-int-overflowing.rs:3:36
+   |
+LL |     let y: &'static (i32, bool) = &(5_i32.overflowing_sub(3));
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+LL |     let z: &'static (i32, bool) = &(5_i32.overflowing_mul(3));
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/const-int-overflowing.rs:4:36
+   |
+LL |     let z: &'static (i32, bool) = &(5_i32.overflowing_mul(3));
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/consts/const-int-rotate.nll.stderr b/src/test/ui/consts/const-int-rotate.nll.stderr
new file mode 100644
index 0000000..2b7cdf5
--- /dev/null
+++ b/src/test/ui/consts/const-int-rotate.nll.stderr
@@ -0,0 +1,24 @@
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/const-int-rotate.rs:2:28
+   |
+LL |     let x: &'static i32 = &(5_i32.rotate_left(3));
+   |            ------------    ^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+LL |     let y: &'static i32 = &(5_i32.rotate_right(3));
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/const-int-rotate.rs:3:28
+   |
+LL |     let y: &'static i32 = &(5_i32.rotate_right(3));
+   |            ------------    ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/src/test/ui/consts/const-int-rotate.rs b/src/test/ui/consts/const-int-rotate.rs
new file mode 100644
index 0000000..d07c00e
--- /dev/null
+++ b/src/test/ui/consts/const-int-rotate.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let x: &'static i32 = &(5_i32.rotate_left(3)); //~ ERROR does not live long enough
+    let y: &'static i32 = &(5_i32.rotate_right(3)); //~ ERROR does not live long enough
+}
diff --git a/src/test/ui/consts/const-int-rotate.stderr b/src/test/ui/consts/const-int-rotate.stderr
new file mode 100644
index 0000000..ec08e0a
--- /dev/null
+++ b/src/test/ui/consts/const-int-rotate.stderr
@@ -0,0 +1,24 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/const-int-rotate.rs:2:28
+   |
+LL |     let x: &'static i32 = &(5_i32.rotate_left(3));
+   |                            ^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+LL |     let y: &'static i32 = &(5_i32.rotate_right(3));
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/const-int-rotate.rs:3:28
+   |
+LL |     let y: &'static i32 = &(5_i32.rotate_right(3));
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/consts/const-int-sign.nll.stderr b/src/test/ui/consts/const-int-sign.nll.stderr
new file mode 100644
index 0000000..0ad7a39
--- /dev/null
+++ b/src/test/ui/consts/const-int-sign.nll.stderr
@@ -0,0 +1,24 @@
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/const-int-sign.rs:2:29
+   |
+LL |     let x: &'static bool = &(5_i32.is_negative());
+   |            -------------    ^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+LL |     let y: &'static bool = &(5_i32.is_positive());
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/const-int-sign.rs:3:29
+   |
+LL |     let y: &'static bool = &(5_i32.is_positive());
+   |            -------------    ^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/src/test/ui/consts/const-int-sign.rs b/src/test/ui/consts/const-int-sign.rs
new file mode 100644
index 0000000..a21797c
--- /dev/null
+++ b/src/test/ui/consts/const-int-sign.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let x: &'static bool = &(5_i32.is_negative()); //~ ERROR does not live long enough
+    let y: &'static bool = &(5_i32.is_positive()); //~ ERROR does not live long enough
+}
diff --git a/src/test/ui/consts/const-int-sign.stderr b/src/test/ui/consts/const-int-sign.stderr
new file mode 100644
index 0000000..ffe09a0
--- /dev/null
+++ b/src/test/ui/consts/const-int-sign.stderr
@@ -0,0 +1,24 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/const-int-sign.rs:2:29
+   |
+LL |     let x: &'static bool = &(5_i32.is_negative());
+   |                             ^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+LL |     let y: &'static bool = &(5_i32.is_positive());
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/const-int-sign.rs:3:29
+   |
+LL |     let y: &'static bool = &(5_i32.is_positive());
+   |                             ^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/consts/const-int-unchecked.rs b/src/test/ui/consts/const-int-unchecked.rs
new file mode 100644
index 0000000..8ee029b
--- /dev/null
+++ b/src/test/ui/consts/const-int-unchecked.rs
@@ -0,0 +1,120 @@
+#![feature(core_intrinsics)]
+
+use std::intrinsics;
+
+// The documentation of `unchecked_shl` states that it:
+//
+// Performs an unchecked left shift, resulting in undefined behavior when
+// y < 0 or y >= N, where N is the width of T in bits.
+//
+// So we check this for a few `y`.
+
+// unsigned types:
+
+const SHL_U8: u8 = unsafe { intrinsics::unchecked_shl(5_u8, 8) };
+//~^ ERROR any use of this value will cause an error
+const SHL_U16: u16 = unsafe { intrinsics::unchecked_shl(5_u16, 16) };
+//~^ ERROR any use of this value will cause an error
+const SHL_U32: u32 = unsafe { intrinsics::unchecked_shl(5_u32, 32) };
+//~^ ERROR any use of this value will cause an error
+const SHL_U64: u64 = unsafe { intrinsics::unchecked_shl(5_u64, 64) };
+//~^ ERROR any use of this value will cause an error
+const SHL_U128: u128 = unsafe { intrinsics::unchecked_shl(5_u128, 128) };
+//~^ ERROR any use of this value will cause an error
+
+// signed types:
+
+const SHL_I8: i8 = unsafe { intrinsics::unchecked_shl(5_i8, 8) };
+//~^ ERROR any use of this value will cause an error
+const SHL_I16: i16 = unsafe { intrinsics::unchecked_shl(5_16, 16) };
+//~^ ERROR any use of this value will cause an error
+const SHL_I32: i32 = unsafe { intrinsics::unchecked_shl(5_i32, 32) };
+//~^ ERROR any use of this value will cause an error
+const SHL_I64: i64 = unsafe { intrinsics::unchecked_shl(5_i64, 64) };
+//~^ ERROR any use of this value will cause an error
+const SHL_I128: i128 = unsafe { intrinsics::unchecked_shl(5_i128, 128) };
+//~^ ERROR any use of this value will cause an error
+
+// and make sure we capture y < 0:
+
+const SHL_I8_NEG: i8 = unsafe { intrinsics::unchecked_shl(5_i8, -1) };
+//~^ ERROR any use of this value will cause an error
+const SHL_I16_NEG: i16 = unsafe { intrinsics::unchecked_shl(5_16, -1) };
+//~^ ERROR any use of this value will cause an error
+const SHL_I32_NEG: i32 = unsafe { intrinsics::unchecked_shl(5_i32, -1) };
+//~^ ERROR any use of this value will cause an error
+const SHL_I64_NEG: i64 = unsafe { intrinsics::unchecked_shl(5_i64, -1) };
+//~^ ERROR any use of this value will cause an error
+const SHL_I128_NEG: i128 = unsafe { intrinsics::unchecked_shl(5_i128, -1) };
+//~^ ERROR any use of this value will cause an error
+
+// and that there's no special relation to the value -1 by picking some
+// negative values at random:
+
+const SHL_I8_NEG_RANDOM: i8 = unsafe { intrinsics::unchecked_shl(5_i8, -6) };
+//~^ ERROR any use of this value will cause an error
+const SHL_I16_NEG_RANDOM: i16 = unsafe { intrinsics::unchecked_shl(5_16, -13) };
+//~^ ERROR any use of this value will cause an error
+const SHL_I32_NEG_RANDOM: i32 = unsafe { intrinsics::unchecked_shl(5_i32, -25) };
+//~^ ERROR any use of this value will cause an error
+const SHL_I64_NEG_RANDOM: i64 = unsafe { intrinsics::unchecked_shl(5_i64, -30) };
+//~^ ERROR any use of this value will cause an error
+const SHL_I128_NEG_RANDOM: i128 = unsafe { intrinsics::unchecked_shl(5_i128, -93) };
+//~^ ERROR any use of this value will cause an error
+
+// Repeat it all over for `unchecked_shr`
+
+// unsigned types:
+
+const SHR_U8: u8 = unsafe { intrinsics::unchecked_shr(5_u8, 8) };
+//~^ ERROR any use of this value will cause an error
+const SHR_U16: u16 = unsafe { intrinsics::unchecked_shr(5_u16, 16) };
+//~^ ERROR any use of this value will cause an error
+const SHR_U32: u32 = unsafe { intrinsics::unchecked_shr(5_u32, 32) };
+//~^ ERROR any use of this value will cause an error
+const SHR_U64: u64 = unsafe { intrinsics::unchecked_shr(5_u64, 64) };
+//~^ ERROR any use of this value will cause an error
+const SHR_U128: u128 = unsafe { intrinsics::unchecked_shr(5_u128, 128) };
+//~^ ERROR any use of this value will cause an error
+
+// signed types:
+
+const SHR_I8: i8 = unsafe { intrinsics::unchecked_shr(5_i8, 8) };
+//~^ ERROR any use of this value will cause an error
+const SHR_I16: i16 = unsafe { intrinsics::unchecked_shr(5_16, 16) };
+//~^ ERROR any use of this value will cause an error
+const SHR_I32: i32 = unsafe { intrinsics::unchecked_shr(5_i32, 32) };
+//~^ ERROR any use of this value will cause an error
+const SHR_I64: i64 = unsafe { intrinsics::unchecked_shr(5_i64, 64) };
+//~^ ERROR any use of this value will cause an error
+const SHR_I128: i128 = unsafe { intrinsics::unchecked_shr(5_i128, 128) };
+//~^ ERROR any use of this value will cause an error
+
+// and make sure we capture y < 0:
+
+const SHR_I8_NEG: i8 = unsafe { intrinsics::unchecked_shr(5_i8, -1) };
+//~^ ERROR any use of this value will cause an error
+const SHR_I16_NEG: i16 = unsafe { intrinsics::unchecked_shr(5_16, -1) };
+//~^ ERROR any use of this value will cause an error
+const SHR_I32_NEG: i32 = unsafe { intrinsics::unchecked_shr(5_i32, -1) };
+//~^ ERROR any use of this value will cause an error
+const SHR_I64_NEG: i64 = unsafe { intrinsics::unchecked_shr(5_i64, -1) };
+//~^ ERROR any use of this value will cause an error
+const SHR_I128_NEG: i128 = unsafe { intrinsics::unchecked_shr(5_i128, -1) };
+//~^ ERROR any use of this value will cause an error
+
+// and that there's no special relation to the value -1 by picking some
+// negative values at random:
+
+const SHR_I8_NEG_RANDOM: i8 = unsafe { intrinsics::unchecked_shr(5_i8, -6) };
+//~^ ERROR any use of this value will cause an error
+const SHR_I16_NEG_RANDOM: i16 = unsafe { intrinsics::unchecked_shr(5_16, -13) };
+//~^ ERROR any use of this value will cause an error
+const SHR_I32_NEG_RANDOM: i32 = unsafe { intrinsics::unchecked_shr(5_i32, -25) };
+//~^ ERROR any use of this value will cause an error
+const SHR_I64_NEG_RANDOM: i64 = unsafe { intrinsics::unchecked_shr(5_i64, -30) };
+//~^ ERROR any use of this value will cause an error
+const SHR_I128_NEG_RANDOM: i128 = unsafe { intrinsics::unchecked_shr(5_i128, -93) };
+//~^ ERROR any use of this value will cause an error
+
+fn main() {}
diff --git a/src/test/ui/consts/const-int-unchecked.stderr b/src/test/ui/consts/const-int-unchecked.stderr
new file mode 100644
index 0000000..0fa8200
--- /dev/null
+++ b/src/test/ui/consts/const-int-unchecked.stderr
@@ -0,0 +1,324 @@
+error: any use of this value will cause an error
+  --> $DIR/const-int-unchecked.rs:14:29
+   |
+LL | const SHL_U8: u8 = unsafe { intrinsics::unchecked_shl(5_u8, 8) };
+   | ----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                             |
+   |                             Overflowing shift by 8 in unchecked_shl
+   |
+   = note: #[deny(const_err)] on by default
+
+error: any use of this value will cause an error
+  --> $DIR/const-int-unchecked.rs:16:31
+   |
+LL | const SHL_U16: u16 = unsafe { intrinsics::unchecked_shl(5_u16, 16) };
+   | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                               |
+   |                               Overflowing shift by 16 in unchecked_shl
+
+error: any use of this value will cause an error
+  --> $DIR/const-int-unchecked.rs:18:31
+   |
+LL | const SHL_U32: u32 = unsafe { intrinsics::unchecked_shl(5_u32, 32) };
+   | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                               |
+   |                               Overflowing shift by 32 in unchecked_shl
+
+error: any use of this value will cause an error
+  --> $DIR/const-int-unchecked.rs:20:31
+   |
+LL | const SHL_U64: u64 = unsafe { intrinsics::unchecked_shl(5_u64, 64) };
+   | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                               |
+   |                               Overflowing shift by 64 in unchecked_shl
+
+error: any use of this value will cause an error
+  --> $DIR/const-int-unchecked.rs:22:33
+   |
+LL | const SHL_U128: u128 = unsafe { intrinsics::unchecked_shl(5_u128, 128) };
+   | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                 |
+   |                                 Overflowing shift by 128 in unchecked_shl
+
+error: any use of this value will cause an error
+  --> $DIR/const-int-unchecked.rs:27:29
+   |
+LL | const SHL_I8: i8 = unsafe { intrinsics::unchecked_shl(5_i8, 8) };
+   | ----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                             |
+   |                             Overflowing shift by 8 in unchecked_shl
+
+error: any use of this value will cause an error
+  --> $DIR/const-int-unchecked.rs:29:31
+   |
+LL | const SHL_I16: i16 = unsafe { intrinsics::unchecked_shl(5_16, 16) };
+   | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                               |
+   |                               Overflowing shift by 16 in unchecked_shl
+
+error: any use of this value will cause an error
+  --> $DIR/const-int-unchecked.rs:31:31
+   |
+LL | const SHL_I32: i32 = unsafe { intrinsics::unchecked_shl(5_i32, 32) };
+   | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                               |
+   |                               Overflowing shift by 32 in unchecked_shl
+
+error: any use of this value will cause an error
+  --> $DIR/const-int-unchecked.rs:33:31
+   |
+LL | const SHL_I64: i64 = unsafe { intrinsics::unchecked_shl(5_i64, 64) };
+   | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                               |
+   |                               Overflowing shift by 64 in unchecked_shl
+
+error: any use of this value will cause an error
+  --> $DIR/const-int-unchecked.rs:35:33
+   |
+LL | const SHL_I128: i128 = unsafe { intrinsics::unchecked_shl(5_i128, 128) };
+   | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                 |
+   |                                 Overflowing shift by 128 in unchecked_shl
+
+error: any use of this value will cause an error
+  --> $DIR/const-int-unchecked.rs:40:33
+   |
+LL | const SHL_I8_NEG: i8 = unsafe { intrinsics::unchecked_shl(5_i8, -1) };
+   | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                 |
+   |                                 Overflowing shift by 255 in unchecked_shl
+
+error: any use of this value will cause an error
+  --> $DIR/const-int-unchecked.rs:42:35
+   |
+LL | const SHL_I16_NEG: i16 = unsafe { intrinsics::unchecked_shl(5_16, -1) };
+   | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                   |
+   |                                   Overflowing shift by 65535 in unchecked_shl
+
+error: any use of this value will cause an error
+  --> $DIR/const-int-unchecked.rs:44:35
+   |
+LL | const SHL_I32_NEG: i32 = unsafe { intrinsics::unchecked_shl(5_i32, -1) };
+   | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                   |
+   |                                   Overflowing shift by 4294967295 in unchecked_shl
+
+error: any use of this value will cause an error
+  --> $DIR/const-int-unchecked.rs:46:35
+   |
+LL | const SHL_I64_NEG: i64 = unsafe { intrinsics::unchecked_shl(5_i64, -1) };
+   | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                   |
+   |                                   Overflowing shift by 18446744073709551615 in unchecked_shl
+
+error: any use of this value will cause an error
+  --> $DIR/const-int-unchecked.rs:48:37
+   |
+LL | const SHL_I128_NEG: i128 = unsafe { intrinsics::unchecked_shl(5_i128, -1) };
+   | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                     |
+   |                                     Overflowing shift by 340282366920938463463374607431768211455 in unchecked_shl
+
+error: any use of this value will cause an error
+  --> $DIR/const-int-unchecked.rs:54:40
+   |
+LL | const SHL_I8_NEG_RANDOM: i8 = unsafe { intrinsics::unchecked_shl(5_i8, -6) };
+   | ---------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                        |
+   |                                        Overflowing shift by 250 in unchecked_shl
+
+error: any use of this value will cause an error
+  --> $DIR/const-int-unchecked.rs:56:42
+   |
+LL | const SHL_I16_NEG_RANDOM: i16 = unsafe { intrinsics::unchecked_shl(5_16, -13) };
+   | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                          |
+   |                                          Overflowing shift by 65523 in unchecked_shl
+
+error: any use of this value will cause an error
+  --> $DIR/const-int-unchecked.rs:58:42
+   |
+LL | const SHL_I32_NEG_RANDOM: i32 = unsafe { intrinsics::unchecked_shl(5_i32, -25) };
+   | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                          |
+   |                                          Overflowing shift by 4294967271 in unchecked_shl
+
+error: any use of this value will cause an error
+  --> $DIR/const-int-unchecked.rs:60:42
+   |
+LL | const SHL_I64_NEG_RANDOM: i64 = unsafe { intrinsics::unchecked_shl(5_i64, -30) };
+   | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                          |
+   |                                          Overflowing shift by 18446744073709551586 in unchecked_shl
+
+error: any use of this value will cause an error
+  --> $DIR/const-int-unchecked.rs:62:44
+   |
+LL | const SHL_I128_NEG_RANDOM: i128 = unsafe { intrinsics::unchecked_shl(5_i128, -93) };
+   | -------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                            |
+   |                                            Overflowing shift by 340282366920938463463374607431768211363 in unchecked_shl
+
+error: any use of this value will cause an error
+  --> $DIR/const-int-unchecked.rs:69:29
+   |
+LL | const SHR_U8: u8 = unsafe { intrinsics::unchecked_shr(5_u8, 8) };
+   | ----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                             |
+   |                             Overflowing shift by 8 in unchecked_shr
+
+error: any use of this value will cause an error
+  --> $DIR/const-int-unchecked.rs:71:31
+   |
+LL | const SHR_U16: u16 = unsafe { intrinsics::unchecked_shr(5_u16, 16) };
+   | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                               |
+   |                               Overflowing shift by 16 in unchecked_shr
+
+error: any use of this value will cause an error
+  --> $DIR/const-int-unchecked.rs:73:31
+   |
+LL | const SHR_U32: u32 = unsafe { intrinsics::unchecked_shr(5_u32, 32) };
+   | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                               |
+   |                               Overflowing shift by 32 in unchecked_shr
+
+error: any use of this value will cause an error
+  --> $DIR/const-int-unchecked.rs:75:31
+   |
+LL | const SHR_U64: u64 = unsafe { intrinsics::unchecked_shr(5_u64, 64) };
+   | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                               |
+   |                               Overflowing shift by 64 in unchecked_shr
+
+error: any use of this value will cause an error
+  --> $DIR/const-int-unchecked.rs:77:33
+   |
+LL | const SHR_U128: u128 = unsafe { intrinsics::unchecked_shr(5_u128, 128) };
+   | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                 |
+   |                                 Overflowing shift by 128 in unchecked_shr
+
+error: any use of this value will cause an error
+  --> $DIR/const-int-unchecked.rs:82:29
+   |
+LL | const SHR_I8: i8 = unsafe { intrinsics::unchecked_shr(5_i8, 8) };
+   | ----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                             |
+   |                             Overflowing shift by 8 in unchecked_shr
+
+error: any use of this value will cause an error
+  --> $DIR/const-int-unchecked.rs:84:31
+   |
+LL | const SHR_I16: i16 = unsafe { intrinsics::unchecked_shr(5_16, 16) };
+   | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                               |
+   |                               Overflowing shift by 16 in unchecked_shr
+
+error: any use of this value will cause an error
+  --> $DIR/const-int-unchecked.rs:86:31
+   |
+LL | const SHR_I32: i32 = unsafe { intrinsics::unchecked_shr(5_i32, 32) };
+   | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                               |
+   |                               Overflowing shift by 32 in unchecked_shr
+
+error: any use of this value will cause an error
+  --> $DIR/const-int-unchecked.rs:88:31
+   |
+LL | const SHR_I64: i64 = unsafe { intrinsics::unchecked_shr(5_i64, 64) };
+   | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                               |
+   |                               Overflowing shift by 64 in unchecked_shr
+
+error: any use of this value will cause an error
+  --> $DIR/const-int-unchecked.rs:90:33
+   |
+LL | const SHR_I128: i128 = unsafe { intrinsics::unchecked_shr(5_i128, 128) };
+   | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                 |
+   |                                 Overflowing shift by 128 in unchecked_shr
+
+error: any use of this value will cause an error
+  --> $DIR/const-int-unchecked.rs:95:33
+   |
+LL | const SHR_I8_NEG: i8 = unsafe { intrinsics::unchecked_shr(5_i8, -1) };
+   | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                 |
+   |                                 Overflowing shift by 255 in unchecked_shr
+
+error: any use of this value will cause an error
+  --> $DIR/const-int-unchecked.rs:97:35
+   |
+LL | const SHR_I16_NEG: i16 = unsafe { intrinsics::unchecked_shr(5_16, -1) };
+   | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                   |
+   |                                   Overflowing shift by 65535 in unchecked_shr
+
+error: any use of this value will cause an error
+  --> $DIR/const-int-unchecked.rs:99:35
+   |
+LL | const SHR_I32_NEG: i32 = unsafe { intrinsics::unchecked_shr(5_i32, -1) };
+   | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                   |
+   |                                   Overflowing shift by 4294967295 in unchecked_shr
+
+error: any use of this value will cause an error
+  --> $DIR/const-int-unchecked.rs:101:35
+   |
+LL | const SHR_I64_NEG: i64 = unsafe { intrinsics::unchecked_shr(5_i64, -1) };
+   | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                   |
+   |                                   Overflowing shift by 18446744073709551615 in unchecked_shr
+
+error: any use of this value will cause an error
+  --> $DIR/const-int-unchecked.rs:103:37
+   |
+LL | const SHR_I128_NEG: i128 = unsafe { intrinsics::unchecked_shr(5_i128, -1) };
+   | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                     |
+   |                                     Overflowing shift by 340282366920938463463374607431768211455 in unchecked_shr
+
+error: any use of this value will cause an error
+  --> $DIR/const-int-unchecked.rs:109:40
+   |
+LL | const SHR_I8_NEG_RANDOM: i8 = unsafe { intrinsics::unchecked_shr(5_i8, -6) };
+   | ---------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                        |
+   |                                        Overflowing shift by 250 in unchecked_shr
+
+error: any use of this value will cause an error
+  --> $DIR/const-int-unchecked.rs:111:42
+   |
+LL | const SHR_I16_NEG_RANDOM: i16 = unsafe { intrinsics::unchecked_shr(5_16, -13) };
+   | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                          |
+   |                                          Overflowing shift by 65523 in unchecked_shr
+
+error: any use of this value will cause an error
+  --> $DIR/const-int-unchecked.rs:113:42
+   |
+LL | const SHR_I32_NEG_RANDOM: i32 = unsafe { intrinsics::unchecked_shr(5_i32, -25) };
+   | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                          |
+   |                                          Overflowing shift by 4294967271 in unchecked_shr
+
+error: any use of this value will cause an error
+  --> $DIR/const-int-unchecked.rs:115:42
+   |
+LL | const SHR_I64_NEG_RANDOM: i64 = unsafe { intrinsics::unchecked_shr(5_i64, -30) };
+   | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                          |
+   |                                          Overflowing shift by 18446744073709551586 in unchecked_shr
+
+error: any use of this value will cause an error
+  --> $DIR/const-int-unchecked.rs:117:44
+   |
+LL | const SHR_I128_NEG_RANDOM: i128 = unsafe { intrinsics::unchecked_shr(5_i128, -93) };
+   | -------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                            |
+   |                                            Overflowing shift by 340282366920938463463374607431768211363 in unchecked_shr
+
+error: aborting due to 40 previous errors
+
diff --git a/src/test/ui/consts/const-int-wrapping.nll.stderr b/src/test/ui/consts/const-int-wrapping.nll.stderr
new file mode 100644
index 0000000..a186854
--- /dev/null
+++ b/src/test/ui/consts/const-int-wrapping.nll.stderr
@@ -0,0 +1,57 @@
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/const-int-wrapping.rs:2:28
+   |
+LL |     let x: &'static i32 = &(5_i32.wrapping_add(3));
+   |            ------------    ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+...
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/const-int-wrapping.rs:3:28
+   |
+LL |     let y: &'static i32 = &(5_i32.wrapping_sub(3));
+   |            ------------    ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+...
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/const-int-wrapping.rs:4:28
+   |
+LL |     let z: &'static i32 = &(5_i32.wrapping_mul(3));
+   |            ------------    ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+...
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/const-int-wrapping.rs:5:28
+   |
+LL |     let a: &'static i32 = &(5_i32.wrapping_shl(3));
+   |            ------------    ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+LL |     let b: &'static i32 = &(5_i32.wrapping_shr(3));
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/const-int-wrapping.rs:6:28
+   |
+LL |     let b: &'static i32 = &(5_i32.wrapping_shr(3));
+   |            ------------    ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/src/test/ui/consts/const-int-wrapping.rs b/src/test/ui/consts/const-int-wrapping.rs
new file mode 100644
index 0000000..720e40b
--- /dev/null
+++ b/src/test/ui/consts/const-int-wrapping.rs
@@ -0,0 +1,7 @@
+fn main() {
+    let x: &'static i32 = &(5_i32.wrapping_add(3)); //~ ERROR does not live long enough
+    let y: &'static i32 = &(5_i32.wrapping_sub(3)); //~ ERROR does not live long enough
+    let z: &'static i32 = &(5_i32.wrapping_mul(3)); //~ ERROR does not live long enough
+    let a: &'static i32 = &(5_i32.wrapping_shl(3)); //~ ERROR does not live long enough
+    let b: &'static i32 = &(5_i32.wrapping_shr(3)); //~ ERROR does not live long enough
+}
diff --git a/src/test/ui/consts/const-int-wrapping.stderr b/src/test/ui/consts/const-int-wrapping.stderr
new file mode 100644
index 0000000..478a6d8
--- /dev/null
+++ b/src/test/ui/consts/const-int-wrapping.stderr
@@ -0,0 +1,57 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/const-int-wrapping.rs:2:28
+   |
+LL |     let x: &'static i32 = &(5_i32.wrapping_add(3));
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+...
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/const-int-wrapping.rs:3:28
+   |
+LL |     let y: &'static i32 = &(5_i32.wrapping_sub(3));
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+...
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/const-int-wrapping.rs:4:28
+   |
+LL |     let z: &'static i32 = &(5_i32.wrapping_mul(3));
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+...
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/const-int-wrapping.rs:5:28
+   |
+LL |     let a: &'static i32 = &(5_i32.wrapping_shl(3));
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+LL |     let b: &'static i32 = &(5_i32.wrapping_shr(3));
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/const-int-wrapping.rs:6:28
+   |
+LL |     let b: &'static i32 = &(5_i32.wrapping_shr(3));
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/consts/const-integer-bool-ops.rs b/src/test/ui/consts/const-integer-bool-ops.rs
new file mode 100644
index 0000000..f0d5a55
--- /dev/null
+++ b/src/test/ui/consts/const-integer-bool-ops.rs
@@ -0,0 +1,85 @@
+const X: usize = 42 && 39;
+//~^ ERROR mismatched types
+//~| expected bool, found integer
+//~| ERROR mismatched types
+//~| expected bool, found integer
+//~| ERROR mismatched types
+//~| expected usize, found bool
+const ARR: [i32; X] = [99; 34];
+//~^ ERROR evaluation of constant value failed
+
+const X1: usize = 42 || 39;
+//~^ ERROR mismatched types
+//~| expected bool, found integer
+//~| ERROR mismatched types
+//~| expected bool, found integer
+//~| ERROR mismatched types
+//~| expected usize, found bool
+const ARR1: [i32; X1] = [99; 47];
+//~^ ERROR evaluation of constant value failed
+
+const X2: usize = -42 || -39;
+//~^ ERROR mismatched types
+//~| expected bool, found integer
+//~| ERROR mismatched types
+//~| expected bool, found integer
+//~| ERROR mismatched types
+//~| expected usize, found bool
+const ARR2: [i32; X2] = [99; 18446744073709551607];
+//~^ ERROR evaluation of constant value failed
+
+const X3: usize = -42 && -39;
+//~^ ERROR mismatched types
+//~| expected bool, found integer
+//~| ERROR mismatched types
+//~| expected bool, found integer
+//~| ERROR mismatched types
+//~| expected usize, found bool
+const ARR3: [i32; X3] = [99; 6];
+//~^ ERROR evaluation of constant value failed
+
+const Y: usize = 42.0 == 42.0;
+//~^ ERROR mismatched types
+//~| expected usize, found bool
+const ARRR: [i32; Y] = [99; 1];
+//~^ ERROR evaluation of constant value failed
+
+const Y1: usize = 42.0 >= 42.0;
+//~^ ERROR mismatched types
+//~| expected usize, found bool
+const ARRR1: [i32; Y1] = [99; 1];
+//~^ ERROR evaluation of constant value failed
+
+const Y2: usize = 42.0 <= 42.0;
+//~^ ERROR mismatched types
+//~| expected usize, found bool
+const ARRR2: [i32; Y2] = [99; 1];
+//~^ ERROR evaluation of constant value failed
+
+const Y3: usize = 42.0 > 42.0;
+//~^ ERROR mismatched types
+//~| expected usize, found bool
+const ARRR3: [i32; Y3] = [99; 0];
+//~^ ERROR evaluation of constant value failed
+
+const Y4: usize = 42.0 < 42.0;
+//~^ ERROR mismatched types
+//~| expected usize, found bool
+const ARRR4: [i32; Y4] = [99; 0];
+//~^ ERROR evaluation of constant value failed
+
+const Y5: usize = 42.0 != 42.0;
+//~^ ERROR mismatched types
+//~| expected usize, found bool
+const ARRR5: [i32; Y5] = [99; 0];
+//~^ ERROR evaluation of constant value failed
+
+fn main() {
+    let _ = ARR;
+    let _ = ARRR;
+    let _ = ARRR1;
+    let _ = ARRR2;
+    let _ = ARRR3;
+    let _ = ARRR4;
+    let _ = ARRR5;
+}
diff --git a/src/test/ui/consts/const-integer-bool-ops.stderr b/src/test/ui/consts/const-integer-bool-ops.stderr
new file mode 100644
index 0000000..7885eb4
--- /dev/null
+++ b/src/test/ui/consts/const-integer-bool-ops.stderr
@@ -0,0 +1,196 @@
+error[E0308]: mismatched types
+  --> $DIR/const-integer-bool-ops.rs:1:18
+   |
+LL | const X: usize = 42 && 39;
+   |                  ^^ expected bool, found integer
+   |
+   = note: expected type `bool`
+              found type `{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/const-integer-bool-ops.rs:1:24
+   |
+LL | const X: usize = 42 && 39;
+   |                        ^^ expected bool, found integer
+   |
+   = note: expected type `bool`
+              found type `{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/const-integer-bool-ops.rs:1:18
+   |
+LL | const X: usize = 42 && 39;
+   |                  ^^^^^^^^ expected usize, found bool
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-integer-bool-ops.rs:8:18
+   |
+LL | const ARR: [i32; X] = [99; 34];
+   |                  ^ referenced constant has errors
+
+error[E0308]: mismatched types
+  --> $DIR/const-integer-bool-ops.rs:11:19
+   |
+LL | const X1: usize = 42 || 39;
+   |                   ^^ expected bool, found integer
+   |
+   = note: expected type `bool`
+              found type `{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/const-integer-bool-ops.rs:11:25
+   |
+LL | const X1: usize = 42 || 39;
+   |                         ^^ expected bool, found integer
+   |
+   = note: expected type `bool`
+              found type `{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/const-integer-bool-ops.rs:11:19
+   |
+LL | const X1: usize = 42 || 39;
+   |                   ^^^^^^^^ expected usize, found bool
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-integer-bool-ops.rs:18:19
+   |
+LL | const ARR1: [i32; X1] = [99; 47];
+   |                   ^^ referenced constant has errors
+
+error[E0308]: mismatched types
+  --> $DIR/const-integer-bool-ops.rs:21:19
+   |
+LL | const X2: usize = -42 || -39;
+   |                   ^^^ expected bool, found integer
+   |
+   = note: expected type `bool`
+              found type `{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/const-integer-bool-ops.rs:21:26
+   |
+LL | const X2: usize = -42 || -39;
+   |                          ^^^ expected bool, found integer
+   |
+   = note: expected type `bool`
+              found type `{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/const-integer-bool-ops.rs:21:19
+   |
+LL | const X2: usize = -42 || -39;
+   |                   ^^^^^^^^^^ expected usize, found bool
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-integer-bool-ops.rs:28:19
+   |
+LL | const ARR2: [i32; X2] = [99; 18446744073709551607];
+   |                   ^^ referenced constant has errors
+
+error[E0308]: mismatched types
+  --> $DIR/const-integer-bool-ops.rs:31:19
+   |
+LL | const X3: usize = -42 && -39;
+   |                   ^^^ expected bool, found integer
+   |
+   = note: expected type `bool`
+              found type `{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/const-integer-bool-ops.rs:31:26
+   |
+LL | const X3: usize = -42 && -39;
+   |                          ^^^ expected bool, found integer
+   |
+   = note: expected type `bool`
+              found type `{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/const-integer-bool-ops.rs:31:19
+   |
+LL | const X3: usize = -42 && -39;
+   |                   ^^^^^^^^^^ expected usize, found bool
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-integer-bool-ops.rs:38:19
+   |
+LL | const ARR3: [i32; X3] = [99; 6];
+   |                   ^^ referenced constant has errors
+
+error[E0308]: mismatched types
+  --> $DIR/const-integer-bool-ops.rs:41:18
+   |
+LL | const Y: usize = 42.0 == 42.0;
+   |                  ^^^^^^^^^^^^ expected usize, found bool
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-integer-bool-ops.rs:44:19
+   |
+LL | const ARRR: [i32; Y] = [99; 1];
+   |                   ^ referenced constant has errors
+
+error[E0308]: mismatched types
+  --> $DIR/const-integer-bool-ops.rs:47:19
+   |
+LL | const Y1: usize = 42.0 >= 42.0;
+   |                   ^^^^^^^^^^^^ expected usize, found bool
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-integer-bool-ops.rs:50:20
+   |
+LL | const ARRR1: [i32; Y1] = [99; 1];
+   |                    ^^ referenced constant has errors
+
+error[E0308]: mismatched types
+  --> $DIR/const-integer-bool-ops.rs:53:19
+   |
+LL | const Y2: usize = 42.0 <= 42.0;
+   |                   ^^^^^^^^^^^^ expected usize, found bool
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-integer-bool-ops.rs:56:20
+   |
+LL | const ARRR2: [i32; Y2] = [99; 1];
+   |                    ^^ referenced constant has errors
+
+error[E0308]: mismatched types
+  --> $DIR/const-integer-bool-ops.rs:59:19
+   |
+LL | const Y3: usize = 42.0 > 42.0;
+   |                   ^^^^^^^^^^^ expected usize, found bool
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-integer-bool-ops.rs:62:20
+   |
+LL | const ARRR3: [i32; Y3] = [99; 0];
+   |                    ^^ referenced constant has errors
+
+error[E0308]: mismatched types
+  --> $DIR/const-integer-bool-ops.rs:65:19
+   |
+LL | const Y4: usize = 42.0 < 42.0;
+   |                   ^^^^^^^^^^^ expected usize, found bool
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-integer-bool-ops.rs:68:20
+   |
+LL | const ARRR4: [i32; Y4] = [99; 0];
+   |                    ^^ referenced constant has errors
+
+error[E0308]: mismatched types
+  --> $DIR/const-integer-bool-ops.rs:71:19
+   |
+LL | const Y5: usize = 42.0 != 42.0;
+   |                   ^^^^^^^^^^^^ expected usize, found bool
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-integer-bool-ops.rs:74:20
+   |
+LL | const ARRR5: [i32; Y5] = [99; 0];
+   |                    ^^ referenced constant has errors
+
+error: aborting due to 28 previous errors
+
+Some errors occurred: E0080, E0308.
+For more information about an error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-len-underflow-separate-spans.rs b/src/test/ui/consts/const-len-underflow-separate-spans.rs
new file mode 100644
index 0000000..01d2951
--- /dev/null
+++ b/src/test/ui/consts/const-len-underflow-separate-spans.rs
@@ -0,0 +1,13 @@
+// Check that a constant-evaluation underflow highlights the correct
+// spot (where the underflow occurred), while also providing the
+// overall context for what caused the evaluation.
+
+const ONE: usize = 1;
+const TWO: usize = 2;
+const LEN: usize = ONE - TWO;
+//~^ ERROR any use of this value will cause an error
+
+fn main() {
+    let a: [i8; LEN] = unimplemented!();
+//~^ ERROR E0080
+}
diff --git a/src/test/ui/consts/const-len-underflow-separate-spans.stderr b/src/test/ui/consts/const-len-underflow-separate-spans.stderr
new file mode 100644
index 0000000..ef4fa12
--- /dev/null
+++ b/src/test/ui/consts/const-len-underflow-separate-spans.stderr
@@ -0,0 +1,19 @@
+error: any use of this value will cause an error
+  --> $DIR/const-len-underflow-separate-spans.rs:7:20
+   |
+LL | const LEN: usize = ONE - TWO;
+   | -------------------^^^^^^^^^-
+   |                    |
+   |                    attempt to subtract with overflow
+   |
+   = note: #[deny(const_err)] on by default
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-len-underflow-separate-spans.rs:11:17
+   |
+LL |     let a: [i8; LEN] = unimplemented!();
+   |                 ^^^ referenced constant has errors
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-len-underflow-subspans.rs b/src/test/ui/consts/const-len-underflow-subspans.rs
new file mode 100644
index 0000000..37f6ef1
--- /dev/null
+++ b/src/test/ui/consts/const-len-underflow-subspans.rs
@@ -0,0 +1,11 @@
+// Check that a constant-evaluation underflow highlights the correct
+// spot (where the underflow occurred).
+
+const ONE: usize = 1;
+const TWO: usize = 2;
+
+fn main() {
+    let a: [i8; ONE - TWO] = unimplemented!();
+    //~^ ERROR evaluation of constant value failed
+    //~| attempt to subtract with overflow
+}
diff --git a/src/test/ui/consts/const-len-underflow-subspans.stderr b/src/test/ui/consts/const-len-underflow-subspans.stderr
new file mode 100644
index 0000000..63bce1e
--- /dev/null
+++ b/src/test/ui/consts/const-len-underflow-subspans.stderr
@@ -0,0 +1,9 @@
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-len-underflow-subspans.rs:8:17
+   |
+LL |     let a: [i8; ONE - TWO] = unimplemented!();
+   |                 ^^^^^^^^^ attempt to subtract with overflow
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-match-check.eval1.stderr b/src/test/ui/consts/const-match-check.eval1.stderr
new file mode 100644
index 0000000..4c6499c
--- /dev/null
+++ b/src/test/ui/consts/const-match-check.eval1.stderr
@@ -0,0 +1,9 @@
+error[E0005]: refutable pattern in local binding: `-2147483648i32..=-1i32` not covered
+  --> $DIR/const-match-check.rs:25:15
+   |
+LL |     A = { let 0 = 0; 0 },
+   |               ^ pattern `-2147483648i32..=-1i32` not covered
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0005`.
diff --git a/src/test/ui/consts/const-match-check.eval2.stderr b/src/test/ui/consts/const-match-check.eval2.stderr
new file mode 100644
index 0000000..854f8f3
--- /dev/null
+++ b/src/test/ui/consts/const-match-check.eval2.stderr
@@ -0,0 +1,9 @@
+error[E0005]: refutable pattern in local binding: `-2147483648i32..=-1i32` not covered
+  --> $DIR/const-match-check.rs:31:24
+   |
+LL |     let x: [i32; { let 0 = 0; 0 }] = [];
+   |                        ^ pattern `-2147483648i32..=-1i32` not covered
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0005`.
diff --git a/src/test/ui/consts/const-match-check.matchck.stderr b/src/test/ui/consts/const-match-check.matchck.stderr
new file mode 100644
index 0000000..c9028b1
--- /dev/null
+++ b/src/test/ui/consts/const-match-check.matchck.stderr
@@ -0,0 +1,27 @@
+error[E0005]: refutable pattern in local binding: `-2147483648i32..=-1i32` not covered
+  --> $DIR/const-match-check.rs:4:22
+   |
+LL | const X: i32 = { let 0 = 0; 0 };
+   |                      ^ pattern `-2147483648i32..=-1i32` not covered
+
+error[E0005]: refutable pattern in local binding: `-2147483648i32..=-1i32` not covered
+  --> $DIR/const-match-check.rs:8:23
+   |
+LL | static Y: i32 = { let 0 = 0; 0 };
+   |                       ^ pattern `-2147483648i32..=-1i32` not covered
+
+error[E0005]: refutable pattern in local binding: `-2147483648i32..=-1i32` not covered
+  --> $DIR/const-match-check.rs:13:26
+   |
+LL |     const X: i32 = { let 0 = 0; 0 };
+   |                          ^ pattern `-2147483648i32..=-1i32` not covered
+
+error[E0005]: refutable pattern in local binding: `-2147483648i32..=-1i32` not covered
+  --> $DIR/const-match-check.rs:19:26
+   |
+LL |     const X: i32 = { let 0 = 0; 0 };
+   |                          ^ pattern `-2147483648i32..=-1i32` not covered
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0005`.
diff --git a/src/test/ui/consts/const-match-check.rs b/src/test/ui/consts/const-match-check.rs
new file mode 100644
index 0000000..60f60fa
--- /dev/null
+++ b/src/test/ui/consts/const-match-check.rs
@@ -0,0 +1,33 @@
+// revisions: matchck eval1 eval2
+
+#[cfg(matchck)]
+const X: i32 = { let 0 = 0; 0 };
+//[matchck]~^ ERROR refutable pattern in local binding
+
+#[cfg(matchck)]
+static Y: i32 = { let 0 = 0; 0 };
+//[matchck]~^ ERROR refutable pattern in local binding
+
+#[cfg(matchck)]
+trait Bar {
+    const X: i32 = { let 0 = 0; 0 };
+    //[matchck]~^ ERROR refutable pattern in local binding
+}
+
+#[cfg(matchck)]
+impl Bar for () {
+    const X: i32 = { let 0 = 0; 0 };
+    //[matchck]~^ ERROR refutable pattern in local binding
+}
+
+#[cfg(eval1)]
+enum Foo {
+    A = { let 0 = 0; 0 },
+    //[eval1]~^ ERROR refutable pattern in local binding
+}
+
+fn main() {
+    #[cfg(eval2)]
+    let x: [i32; { let 0 = 0; 0 }] = [];
+    //[eval2]~^ ERROR refutable pattern in local binding
+}
diff --git a/src/test/ui/consts/const-match-pattern-arm.rs b/src/test/ui/consts/const-match-pattern-arm.rs
new file mode 100644
index 0000000..3b98526
--- /dev/null
+++ b/src/test/ui/consts/const-match-pattern-arm.rs
@@ -0,0 +1,17 @@
+#![allow(warnings)]
+
+const x: bool = match Some(true) {
+    Some(value) => true,
+    //~^ ERROR: constant contains unimplemented expression type [E0019]
+    _ => false
+};
+
+const y: bool = {
+    match Some(true) {
+        Some(value) => true,
+        //~^ ERROR: constant contains unimplemented expression type [E0019]
+        _ => false
+    }
+};
+
+fn main() {}
diff --git a/src/test/ui/consts/const-match-pattern-arm.stderr b/src/test/ui/consts/const-match-pattern-arm.stderr
new file mode 100644
index 0000000..c793cc0
--- /dev/null
+++ b/src/test/ui/consts/const-match-pattern-arm.stderr
@@ -0,0 +1,15 @@
+error[E0019]: constant contains unimplemented expression type
+  --> $DIR/const-match-pattern-arm.rs:4:5
+   |
+LL |     Some(value) => true,
+   |     ^^^^^^^^^^^
+
+error[E0019]: constant contains unimplemented expression type
+  --> $DIR/const-match-pattern-arm.rs:11:9
+   |
+LL |         Some(value) => true,
+   |         ^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0019`.
diff --git a/src/test/ui/consts/const-nonzero.rs b/src/test/ui/consts/const-nonzero.rs
new file mode 100644
index 0000000..c06ab22
--- /dev/null
+++ b/src/test/ui/consts/const-nonzero.rs
@@ -0,0 +1,9 @@
+// compile-pass
+
+use std::num::NonZeroU8;
+
+const X: NonZeroU8 = unsafe { NonZeroU8::new_unchecked(5) };
+const Y: u8 = X.get();
+
+fn main() {
+}
diff --git a/src/test/ui/consts/const-pattern-irrefutable.rs b/src/test/ui/consts/const-pattern-irrefutable.rs
new file mode 100644
index 0000000..d3f7be1
--- /dev/null
+++ b/src/test/ui/consts/const-pattern-irrefutable.rs
@@ -0,0 +1,16 @@
+mod foo {
+    pub const b: u8 = 2;
+    pub const d: u8 = 2;
+}
+
+use foo::b as c;
+use foo::d;
+
+const a: u8 = 2;
+
+fn main() {
+    let a = 4; //~ ERROR refutable pattern in local binding: `0u8..=1u8` not covered
+    let c = 4; //~ ERROR refutable pattern in local binding: `0u8..=1u8` not covered
+    let d = 4; //~ ERROR refutable pattern in local binding: `0u8..=1u8` not covered
+    fn f() {} // Check that the `NOTE`s still work with an item here (cf. issue #35115).
+}
diff --git a/src/test/ui/consts/const-pattern-irrefutable.stderr b/src/test/ui/consts/const-pattern-irrefutable.stderr
new file mode 100644
index 0000000..48fe24d
--- /dev/null
+++ b/src/test/ui/consts/const-pattern-irrefutable.stderr
@@ -0,0 +1,21 @@
+error[E0005]: refutable pattern in local binding: `0u8..=1u8` not covered
+  --> $DIR/const-pattern-irrefutable.rs:12:9
+   |
+LL |     let a = 4;
+   |         ^ interpreted as a constant pattern, not new variable
+
+error[E0005]: refutable pattern in local binding: `0u8..=1u8` not covered
+  --> $DIR/const-pattern-irrefutable.rs:13:9
+   |
+LL |     let c = 4;
+   |         ^ interpreted as a constant pattern, not new variable
+
+error[E0005]: refutable pattern in local binding: `0u8..=1u8` not covered
+  --> $DIR/const-pattern-irrefutable.rs:14:9
+   |
+LL |     let d = 4;
+   |         ^ interpreted as a constant pattern, not new variable
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0005`.
diff --git a/src/test/ui/consts/const-pattern-not-const-evaluable.rs b/src/test/ui/consts/const-pattern-not-const-evaluable.rs
new file mode 100644
index 0000000..8dd78ca
--- /dev/null
+++ b/src/test/ui/consts/const-pattern-not-const-evaluable.rs
@@ -0,0 +1,30 @@
+// compile-pass
+
+#[derive(PartialEq, Eq)]
+enum Cake {
+    BlackForest,
+    Marmor,
+}
+use Cake::*;
+
+struct Pair<A, B>(A, B);
+
+const BOO: Pair<Cake, Cake> = Pair(Marmor, BlackForest);
+const FOO: Cake = BOO.1;
+
+const fn foo() -> Cake {
+    Marmor
+}
+
+const WORKS: Cake = Marmor;
+
+const GOO: Cake = foo();
+
+fn main() {
+    match BlackForest {
+        FOO => println!("hi"),
+        GOO => println!("meh"),
+        WORKS => println!("möp"),
+        _ => println!("bye"),
+    }
+}
diff --git a/src/test/ui/consts/const-prop-ice.rs b/src/test/ui/consts/const-prop-ice.rs
new file mode 100644
index 0000000..13309f9
--- /dev/null
+++ b/src/test/ui/consts/const-prop-ice.rs
@@ -0,0 +1,3 @@
+fn main() {
+    [0; 3][3u64 as usize]; //~ ERROR the len is 3 but the index is 3
+}
diff --git a/src/test/ui/consts/const-prop-ice.stderr b/src/test/ui/consts/const-prop-ice.stderr
new file mode 100644
index 0000000..8ec54b4
--- /dev/null
+++ b/src/test/ui/consts/const-prop-ice.stderr
@@ -0,0 +1,10 @@
+error: index out of bounds: the len is 3 but the index is 3
+  --> $DIR/const-prop-ice.rs:2:5
+   |
+LL |     [0; 3][3u64 as usize];
+   |     ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: #[deny(const_err)] on by default
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/consts/const-prop-ice2.rs b/src/test/ui/consts/const-prop-ice2.rs
new file mode 100644
index 0000000..e5fd79f
--- /dev/null
+++ b/src/test/ui/consts/const-prop-ice2.rs
@@ -0,0 +1,5 @@
+fn main() {
+    enum Enum { One=1 }
+    let xs=[0;1 as usize];
+    println!("{}", xs[Enum::One as usize]); //~ ERROR the len is 1 but the index is 1
+}
diff --git a/src/test/ui/consts/const-prop-ice2.stderr b/src/test/ui/consts/const-prop-ice2.stderr
new file mode 100644
index 0000000..68a7164
--- /dev/null
+++ b/src/test/ui/consts/const-prop-ice2.stderr
@@ -0,0 +1,10 @@
+error: index out of bounds: the len is 1 but the index is 1
+  --> $DIR/const-prop-ice2.rs:4:20
+   |
+LL |     println!("{}", xs[Enum::One as usize]);
+   |                    ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: #[deny(const_err)] on by default
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/consts/const-ptr-nonnull.nll.stderr b/src/test/ui/consts/const-ptr-nonnull.nll.stderr
new file mode 100644
index 0000000..26946fb
--- /dev/null
+++ b/src/test/ui/consts/const-ptr-nonnull.nll.stderr
@@ -0,0 +1,25 @@
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/const-ptr-nonnull.rs:4:37
+   |
+LL |     let x: &'static NonNull<u32> = &(NonNull::dangling());
+   |            ---------------------    ^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+...
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/const-ptr-nonnull.rs:9:37
+   |
+LL |     let x: &'static NonNull<u32> = &(non_null.cast());
+   |            ---------------------    ^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+LL |
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/src/test/ui/consts/const-ptr-nonnull.rs b/src/test/ui/consts/const-ptr-nonnull.rs
new file mode 100644
index 0000000..54e743a
--- /dev/null
+++ b/src/test/ui/consts/const-ptr-nonnull.rs
@@ -0,0 +1,11 @@
+use std::ptr::NonNull;
+
+fn main() {
+    let x: &'static NonNull<u32> = &(NonNull::dangling());
+    //~^ ERROR borrowed value does not live long enough
+
+    let mut i: i32 = 10;
+    let non_null = NonNull::new(&mut i).unwrap();
+    let x: &'static NonNull<u32> = &(non_null.cast());
+    //~^ ERROR borrowed value does not live long enough
+}
diff --git a/src/test/ui/consts/const-ptr-nonnull.stderr b/src/test/ui/consts/const-ptr-nonnull.stderr
new file mode 100644
index 0000000..a606bed
--- /dev/null
+++ b/src/test/ui/consts/const-ptr-nonnull.stderr
@@ -0,0 +1,25 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/const-ptr-nonnull.rs:4:37
+   |
+LL |     let x: &'static NonNull<u32> = &(NonNull::dangling());
+   |                                     ^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+...
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/const-ptr-nonnull.rs:9:37
+   |
+LL |     let x: &'static NonNull<u32> = &(non_null.cast());
+   |                                     ^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+LL |
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/consts/const-ptr-unique.nll.stderr b/src/test/ui/consts/const-ptr-unique.nll.stderr
new file mode 100644
index 0000000..3644cf4
--- /dev/null
+++ b/src/test/ui/consts/const-ptr-unique.nll.stderr
@@ -0,0 +1,14 @@
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/const-ptr-unique.rs:8:33
+   |
+LL |     let x: &'static *mut u32 = &(unique.as_ptr());
+   |            -----------------    ^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+LL |
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/src/test/ui/consts/const-ptr-unique.rs b/src/test/ui/consts/const-ptr-unique.rs
new file mode 100644
index 0000000..be44a24
--- /dev/null
+++ b/src/test/ui/consts/const-ptr-unique.rs
@@ -0,0 +1,10 @@
+#![feature(ptr_internals)]
+
+use std::ptr::Unique;
+
+fn main() {
+    let mut i: u32 = 10;
+    let unique = Unique::new(&mut i).unwrap();
+    let x: &'static *mut u32 = &(unique.as_ptr());
+    //~^ ERROR borrowed value does not live long enough
+}
diff --git a/src/test/ui/consts/const-ptr-unique.stderr b/src/test/ui/consts/const-ptr-unique.stderr
new file mode 100644
index 0000000..482b78b
--- /dev/null
+++ b/src/test/ui/consts/const-ptr-unique.stderr
@@ -0,0 +1,14 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/const-ptr-unique.rs:8:33
+   |
+LL |     let x: &'static *mut u32 = &(unique.as_ptr());
+   |                                 ^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+LL |
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/consts/const-size_of-cycle.rs b/src/test/ui/consts/const-size_of-cycle.rs
new file mode 100644
index 0000000..1bbe881
--- /dev/null
+++ b/src/test/ui/consts/const-size_of-cycle.rs
@@ -0,0 +1,9 @@
+// ignore-musl
+// ignore-x86
+// error-pattern: cycle detected
+
+struct Foo {
+    bytes: [u8; std::mem::size_of::<Foo>()]
+}
+
+fn main() {}
diff --git a/src/test/ui/consts/const-size_of-cycle.stderr b/src/test/ui/consts/const-size_of-cycle.stderr
new file mode 100644
index 0000000..3762f5e
--- /dev/null
+++ b/src/test/ui/consts/const-size_of-cycle.stderr
@@ -0,0 +1,28 @@
+error[E0391]: cycle detected when const-evaluating + checking `Foo::bytes::{{constant}}#0`
+  --> $DIR/const-size_of-cycle.rs:6:17
+   |
+LL |     bytes: [u8; std::mem::size_of::<Foo>()]
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: ...which requires const-evaluating `Foo::bytes::{{constant}}#0`...
+  --> $SRC_DIR/libcore/mem.rs:LL:COL
+   |
+LL |     intrinsics::size_of::<T>()
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: ...which requires computing layout of `Foo`...
+   = note: ...which requires normalizing `ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: All, def_id: None }, value: [u8; _] }`...
+note: ...which requires const-evaluating + checking `Foo::bytes::{{constant}}#0`...
+  --> $DIR/const-size_of-cycle.rs:6:17
+   |
+LL |     bytes: [u8; std::mem::size_of::<Foo>()]
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: ...which again requires const-evaluating + checking `Foo::bytes::{{constant}}#0`, completing the cycle
+note: cycle used when processing `Foo`
+  --> $DIR/const-size_of-cycle.rs:5:1
+   |
+LL | struct Foo {
+   | ^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/consts/const-slice-oob.rs b/src/test/ui/consts/const-slice-oob.rs
new file mode 100644
index 0000000..1775f35
--- /dev/null
+++ b/src/test/ui/consts/const-slice-oob.rs
@@ -0,0 +1,10 @@
+#[deny(const_err)]
+
+const FOO: &'static[u32] = &[1, 2, 3];
+const BAR: u32 = FOO[5];
+//~^ index out of bounds: the len is 3 but the index is 5
+//~| ERROR any use of this value will cause an error
+
+fn main() {
+    let _ = BAR;
+}
diff --git a/src/test/ui/consts/const-slice-oob.stderr b/src/test/ui/consts/const-slice-oob.stderr
new file mode 100644
index 0000000..c90cdbc
--- /dev/null
+++ b/src/test/ui/consts/const-slice-oob.stderr
@@ -0,0 +1,12 @@
+error: any use of this value will cause an error
+  --> $DIR/const-slice-oob.rs:4:18
+   |
+LL | const BAR: u32 = FOO[5];
+   | -----------------^^^^^^-
+   |                  |
+   |                  index out of bounds: the len is 3 but the index is 5
+   |
+   = note: #[deny(const_err)] on by default
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/consts/const-tup-index-span.rs b/src/test/ui/consts/const-tup-index-span.rs
new file mode 100644
index 0000000..047ed02
--- /dev/null
+++ b/src/test/ui/consts/const-tup-index-span.rs
@@ -0,0 +1,10 @@
+// Test spans of errors
+
+const TUP: (usize,) = 5usize << 64;
+//~^ ERROR mismatched types
+//~| expected tuple, found usize
+const ARR: [i32; TUP.0] = [];
+//~^ ERROR evaluation of constant value failed
+
+fn main() {
+}
diff --git a/src/test/ui/consts/const-tup-index-span.stderr b/src/test/ui/consts/const-tup-index-span.stderr
new file mode 100644
index 0000000..ed631b8
--- /dev/null
+++ b/src/test/ui/consts/const-tup-index-span.stderr
@@ -0,0 +1,19 @@
+error[E0308]: mismatched types
+  --> $DIR/const-tup-index-span.rs:3:23
+   |
+LL | const TUP: (usize,) = 5usize << 64;
+   |                       ^^^^^^^^^^^^ expected tuple, found usize
+   |
+   = note: expected type `(usize,)`
+              found type `usize`
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-tup-index-span.rs:6:18
+   |
+LL | const ARR: [i32; TUP.0] = [];
+   |                  ^^^ referenced constant has errors
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0080, E0308.
+For more information about an error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-type-mismatch.rs b/src/test/ui/consts/const-type-mismatch.rs
new file mode 100644
index 0000000..6e56c04
--- /dev/null
+++ b/src/test/ui/consts/const-type-mismatch.rs
@@ -0,0 +1,11 @@
+// `const`s shouldn't suggest `.into()`
+
+const TEN: u8 = 10;
+const TWELVE: u16 = TEN + 2;
+//~^ ERROR mismatched types [E0308]
+
+fn main() {
+    const TEN: u8 = 10;
+    const ALSO_TEN: u16 = TEN;
+    //~^ ERROR mismatched types [E0308]
+}
diff --git a/src/test/ui/consts/const-type-mismatch.stderr b/src/test/ui/consts/const-type-mismatch.stderr
new file mode 100644
index 0000000..dbc533c
--- /dev/null
+++ b/src/test/ui/consts/const-type-mismatch.stderr
@@ -0,0 +1,15 @@
+error[E0308]: mismatched types
+  --> $DIR/const-type-mismatch.rs:4:21
+   |
+LL | const TWELVE: u16 = TEN + 2;
+   |                     ^^^^^^^ expected u16, found u8
+
+error[E0308]: mismatched types
+  --> $DIR/const-type-mismatch.rs:9:27
+   |
+LL |     const ALSO_TEN: u16 = TEN;
+   |                           ^^^ expected u16, found u8
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/consts/const-typeid-of.rs b/src/test/ui/consts/const-typeid-of.rs
new file mode 100644
index 0000000..3829c48
--- /dev/null
+++ b/src/test/ui/consts/const-typeid-of.rs
@@ -0,0 +1,8 @@
+use std::any::TypeId;
+
+struct A;
+
+fn main() {
+    const A_ID: TypeId = TypeId::of::<A>();
+    //~^ ERROR `std::any::TypeId::of` is not yet stable as a const fn
+}
diff --git a/src/test/ui/consts/const-typeid-of.stderr b/src/test/ui/consts/const-typeid-of.stderr
new file mode 100644
index 0000000..05347fb
--- /dev/null
+++ b/src/test/ui/consts/const-typeid-of.stderr
@@ -0,0 +1,10 @@
+error: `std::any::TypeId::of` is not yet stable as a const fn
+  --> $DIR/const-typeid-of.rs:6:26
+   |
+LL |     const A_ID: TypeId = TypeId::of::<A>();
+   |                          ^^^^^^^^^^^^^^^^^
+   |
+   = help: add `#![feature(const_type_id)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/consts/const-unsized.rs b/src/test/ui/consts/const-unsized.rs
new file mode 100644
index 0000000..e20ded6
--- /dev/null
+++ b/src/test/ui/consts/const-unsized.rs
@@ -0,0 +1,17 @@
+use std::fmt::Debug;
+
+const CONST_0: Debug+Sync = *(&0 as &(Debug+Sync));
+//~^ ERROR the size for values of type
+
+const CONST_FOO: str = *"foo";
+//~^ ERROR the size for values of type
+
+static STATIC_1: Debug+Sync = *(&1 as &(Debug+Sync));
+//~^ ERROR the size for values of type
+
+static STATIC_BAR: str = *"bar";
+//~^ ERROR the size for values of type
+
+fn main() {
+    println!("{:?} {:?} {:?} {:?}", &CONST_0, &CONST_FOO, &STATIC_1, &STATIC_BAR);
+}
diff --git a/src/test/ui/consts/const-unsized.stderr b/src/test/ui/consts/const-unsized.stderr
new file mode 100644
index 0000000..0f996fc
--- /dev/null
+++ b/src/test/ui/consts/const-unsized.stderr
@@ -0,0 +1,39 @@
+error[E0277]: the size for values of type `(dyn std::fmt::Debug + std::marker::Sync + 'static)` cannot be known at compilation time
+  --> $DIR/const-unsized.rs:3:16
+   |
+LL | const CONST_0: Debug+Sync = *(&0 as &(Debug+Sync));
+   |                ^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `(dyn std::fmt::Debug + std::marker::Sync + 'static)`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+  --> $DIR/const-unsized.rs:6:18
+   |
+LL | const CONST_FOO: str = *"foo";
+   |                  ^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `str`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+
+error[E0277]: the size for values of type `(dyn std::fmt::Debug + std::marker::Sync + 'static)` cannot be known at compilation time
+  --> $DIR/const-unsized.rs:9:18
+   |
+LL | static STATIC_1: Debug+Sync = *(&1 as &(Debug+Sync));
+   |                  ^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `(dyn std::fmt::Debug + std::marker::Sync + 'static)`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+  --> $DIR/const-unsized.rs:12:20
+   |
+LL | static STATIC_BAR: str = *"bar";
+   |                    ^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `str`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/consts/const-validation-fail-55455.rs b/src/test/ui/consts/const-validation-fail-55455.rs
new file mode 100644
index 0000000..def4062
--- /dev/null
+++ b/src/test/ui/consts/const-validation-fail-55455.rs
@@ -0,0 +1,9 @@
+// https://github.com/rust-lang/rust/issues/55454
+// compile-pass
+
+struct This<T>(T);
+
+const C: This<Option<&i32>> = This(Some(&1));
+
+fn main() {
+}
diff --git a/src/test/ui/consts/const_arg_local.rs b/src/test/ui/consts/const_arg_local.rs
new file mode 100644
index 0000000..0da4b44
--- /dev/null
+++ b/src/test/ui/consts/const_arg_local.rs
@@ -0,0 +1,13 @@
+// only-x86_64
+
+#[cfg(target_arch = "x86")]
+use std::arch::x86::*;
+#[cfg(target_arch = "x86_64")]
+use std::arch::x86_64::*;
+
+unsafe fn pclmul(a: __m128i, b: __m128i) -> __m128i {
+    let imm8 = 3;
+    _mm_clmulepi64_si128(a, b, imm8) //~ ERROR argument 3 is required to be a constant
+}
+
+fn main() {}
diff --git a/src/test/ui/consts/const_arg_local.stderr b/src/test/ui/consts/const_arg_local.stderr
new file mode 100644
index 0000000..197b2f0
--- /dev/null
+++ b/src/test/ui/consts/const_arg_local.stderr
@@ -0,0 +1,8 @@
+error: argument 3 is required to be a constant
+  --> $DIR/const_arg_local.rs:10:5
+   |
+LL |     _mm_clmulepi64_si128(a, b, imm8)
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/consts/const_arg_promotable.rs b/src/test/ui/consts/const_arg_promotable.rs
new file mode 100644
index 0000000..25f4510
--- /dev/null
+++ b/src/test/ui/consts/const_arg_promotable.rs
@@ -0,0 +1,12 @@
+// only-x86_64
+
+#[cfg(target_arch = "x86")]
+use std::arch::x86::*;
+#[cfg(target_arch = "x86_64")]
+use std::arch::x86_64::*;
+
+unsafe fn pclmul(a: __m128i, b: __m128i) -> __m128i {
+    _mm_clmulepi64_si128(a, b, *&mut 42) //~ ERROR argument 3 is required to be a constant
+}
+
+fn main() {}
diff --git a/src/test/ui/consts/const_arg_promotable.stderr b/src/test/ui/consts/const_arg_promotable.stderr
new file mode 100644
index 0000000..5de3ee6
--- /dev/null
+++ b/src/test/ui/consts/const_arg_promotable.stderr
@@ -0,0 +1,8 @@
+error: argument 3 is required to be a constant
+  --> $DIR/const_arg_promotable.rs:9:5
+   |
+LL |     _mm_clmulepi64_si128(a, b, *&mut 42)
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/consts/const_arg_wrapper.rs b/src/test/ui/consts/const_arg_wrapper.rs
new file mode 100644
index 0000000..92ff264
--- /dev/null
+++ b/src/test/ui/consts/const_arg_wrapper.rs
@@ -0,0 +1,12 @@
+// only-x86_64
+
+#[cfg(target_arch = "x86")]
+use std::arch::x86::*;
+#[cfg(target_arch = "x86_64")]
+use std::arch::x86_64::*;
+
+unsafe fn pclmul(a: __m128i, b: __m128i, imm8: i32) -> __m128i {
+    _mm_clmulepi64_si128(a, b, imm8) //~ ERROR argument 3 is required to be a constant
+}
+
+fn main() {}
diff --git a/src/test/ui/consts/const_arg_wrapper.stderr b/src/test/ui/consts/const_arg_wrapper.stderr
new file mode 100644
index 0000000..4acf2f0
--- /dev/null
+++ b/src/test/ui/consts/const_arg_wrapper.stderr
@@ -0,0 +1,8 @@
+error: argument 3 is required to be a constant
+  --> $DIR/const_arg_wrapper.rs:9:5
+   |
+LL |     _mm_clmulepi64_si128(a, b, imm8)
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/consts/const_fn_return_nested_fn_ptr.rs b/src/test/ui/consts/const_fn_return_nested_fn_ptr.rs
new file mode 100644
index 0000000..c7617c9
--- /dev/null
+++ b/src/test/ui/consts/const_fn_return_nested_fn_ptr.rs
@@ -0,0 +1,10 @@
+// compile-pass
+// aux-build:const_fn_lib.rs
+
+extern crate const_fn_lib;
+
+fn main() {
+    const_fn_lib::bar()();
+    const_fn_lib::bar_inlined()();
+    const_fn_lib::bar_inlined_always()();
+}
diff --git a/src/test/ui/consts/const_let_assign.rs b/src/test/ui/consts/const_let_assign.rs
new file mode 100644
index 0000000..0b09b84
--- /dev/null
+++ b/src/test/ui/consts/const_let_assign.rs
@@ -0,0 +1,10 @@
+// compile-pass
+
+struct S(i32);
+
+const A: () = {
+    let mut s = S(0);
+    s.0 = 1;
+};
+
+fn main() {}
diff --git a/src/test/ui/consts/const_let_assign2.rs b/src/test/ui/consts/const_let_assign2.rs
new file mode 100644
index 0000000..1c44237
--- /dev/null
+++ b/src/test/ui/consts/const_let_assign2.rs
@@ -0,0 +1,22 @@
+// compile-pass
+
+pub struct AA {
+    pub data: [u8; 10],
+}
+
+impl AA {
+    pub const fn new() -> Self {
+        let mut res: AA = AA { data: [0; 10] };
+        res.data[0] = 5;
+        res
+    }
+}
+
+static mut BB: AA = AA::new();
+
+fn main() {
+    let ptr = unsafe { &mut BB };
+    for a in ptr.data.iter() {
+        println!("{}", a);
+    }
+}
diff --git a/src/test/ui/consts/const_let_assign3.rs b/src/test/ui/consts/const_let_assign3.rs
new file mode 100644
index 0000000..cbe7392
--- /dev/null
+++ b/src/test/ui/consts/const_let_assign3.rs
@@ -0,0 +1,31 @@
+#![feature(const_fn)]
+
+struct S {
+    state: u32,
+}
+
+impl S {
+    const fn foo(&mut self, x: u32) {
+        self.state = x;
+        //~^ contains unimplemented expression
+    }
+}
+
+const FOO: S = {
+    let mut s = S { state: 42 };
+    s.foo(3); //~ ERROR references in constants may only refer to immutable values
+    s
+};
+
+type Array = [u32; {
+    let mut x = 2;
+    let y = &mut x;
+//~^ ERROR references in constants may only refer to immutable values
+    *y = 42;
+//~^ ERROR constant contains unimplemented expression type
+    *y
+}];
+
+fn main() {
+    assert_eq!(FOO.state, 3);
+}
diff --git a/src/test/ui/consts/const_let_assign3.stderr b/src/test/ui/consts/const_let_assign3.stderr
new file mode 100644
index 0000000..c0e978a
--- /dev/null
+++ b/src/test/ui/consts/const_let_assign3.stderr
@@ -0,0 +1,28 @@
+error[E0019]: constant function contains unimplemented expression type
+  --> $DIR/const_let_assign3.rs:9:9
+   |
+LL |         self.state = x;
+   |         ^^^^^^^^^^^^^^
+
+error[E0017]: references in constants may only refer to immutable values
+  --> $DIR/const_let_assign3.rs:16:5
+   |
+LL |     s.foo(3);
+   |     ^ constants require immutable values
+
+error[E0017]: references in constants may only refer to immutable values
+  --> $DIR/const_let_assign3.rs:22:13
+   |
+LL |     let y = &mut x;
+   |             ^^^^^^ constants require immutable values
+
+error[E0019]: constant contains unimplemented expression type
+  --> $DIR/const_let_assign3.rs:24:5
+   |
+LL |     *y = 42;
+   |     ^^^^^^^
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0017, E0019.
+For more information about an error, try `rustc --explain E0017`.
diff --git a/src/test/ui/consts/const_let_eq.rs b/src/test/ui/consts/const_let_eq.rs
new file mode 100644
index 0000000..a2364c3
--- /dev/null
+++ b/src/test/ui/consts/const_let_eq.rs
@@ -0,0 +1,468 @@
+// run-pass
+
+struct Foo<T>(T);
+struct Bar<T> { x: T }
+struct W(u32);
+struct A { a: u32 }
+
+const fn basics((a,): (u32,)) -> u32 {
+    // Deferred assignment:
+    let b: u32;
+    b = a + 1;
+
+    // Immediate assignment:
+    let c: u32 = b + 1;
+
+    // Mutables:
+    let mut d: u32 = c + 1;
+    d = d + 1;
+    // +4 so far.
+
+    // No effect statements work:
+    ; ;
+    1;
+
+    // Array projection
+    let mut arr: [u32; 1] = [0];
+    arr[0] = 1;
+    d = d + arr[0];
+    // +5
+
+    // Field projection:
+    let mut foo: Foo<u32> = Foo(0);
+    let mut bar: Bar<u32> = Bar { x: 0 };
+    foo.0 = 1;
+    bar.x = 1;
+    d = d + foo.0 + bar.x;
+    // +7
+
+    // Array + Field projection:
+    let mut arr: [Foo<u32>; 1] = [Foo(0)];
+    arr[0].0 = 1;
+    d = d + arr[0].0;
+    let mut arr: [Bar<u32>; 1] = [Bar { x: 0 }];
+    arr[0].x = 1;
+    d = d + arr[0].x;
+    // +9
+
+    // Field + Array projection:
+    let mut arr: Foo<[u32; 1]> = Foo([0]);
+    (arr.0)[0] = 1;
+    d = d + (arr.0)[0];
+    let mut arr: Bar<[u32; 1]> = Bar { x: [0] };
+    arr.x[0] = 1;
+    d = d + arr.x[0];
+    // +11
+
+    d
+}
+
+const fn add_assign(W(a): W) -> u32 {
+    // Mutables:
+    let mut d: u32 = a + 1;
+    d += 1;
+    // +2 so far.
+
+    // Array projection
+    let mut arr: [u32; 1] = [0];
+    arr[0] += 1;
+    d += arr[0];
+    // +3
+
+    // Field projection:
+    let mut foo: Foo<u32> = Foo(0);
+    let mut bar: Bar<u32> = Bar { x: 0 };
+    foo.0 += 1;
+    bar.x += 1;
+    d += foo.0 + bar.x;
+    // +5
+
+    // Array + Field projection:
+    let mut arr: [Foo<u32>; 1] = [Foo(0)];
+    arr[0].0 += 1;
+    d += arr[0].0;
+    let mut arr: [Bar<u32>; 1] = [Bar { x: 0 }];
+    arr[0].x += 1;
+    d += arr[0].x;
+    // +7
+
+    // Field + Array projection:
+    let mut arr: Foo<[u32; 1]> = Foo([0]);
+    (arr.0)[0] += 1;
+    d += (arr.0)[0];
+    let mut arr: Bar<[u32; 1]> = Bar { x: [0] };
+    arr.x[0] += 1;
+    d += arr.x[0];
+    // +9
+
+    d
+}
+
+const fn mul_assign(A { a }: A) -> u32 {
+    // Mutables:
+    let mut d: u32 = a + 1;
+    d *= 2;
+    // 2^1 * (a + 1)
+
+    // Array projection
+    let mut arr: [u32; 1] = [1];
+    arr[0] *= 2;
+    d *= arr[0];
+    // 2^2 * (a + 1)
+
+    // Field projection:
+    let mut foo: Foo<u32> = Foo(1);
+    let mut bar: Bar<u32> = Bar { x: 1 };
+    foo.0 *= 2;
+    bar.x *= 2;
+    d *= foo.0 + bar.x;
+    // 2^4 * (a + 1)
+
+    // Array + Field projection:
+    let mut arr: [Foo<u32>; 1] = [Foo(1)];
+    arr[0].0 *= 2;
+    d *= arr[0].0;
+    let mut arr: [Bar<u32>; 1] = [Bar { x: 1 }];
+    arr[0].x *= 2;
+    d *= arr[0].x;
+    // 2^6 * (a + 1)
+
+    // Field + Array projection:
+    let mut arr: Foo<[u32; 1]> = Foo([1]);
+    (arr.0)[0] *= 2;
+    d *= (arr.0)[0];
+    let mut arr: Bar<[u32; 1]> = Bar { x: [1] };
+    arr.x[0] *= 2;
+    d *= arr.x[0];
+    // 2^8 * (a + 1)
+
+    d
+}
+
+const fn div_assign(a: [u32; 1]) -> u32 {
+    let a = a[0];
+    // Mutables:
+    let mut d: u32 = 1024 * a;
+    d /= 2;
+    // 512
+
+    // Array projection
+    let mut arr: [u32; 1] = [4];
+    arr[0] /= 2;
+    d /= arr[0];
+    // 256
+
+    // Field projection:
+    let mut foo: Foo<u32> = Foo(4);
+    let mut bar: Bar<u32> = Bar { x: 4 };
+    foo.0 /= 2;
+    bar.x /= 2;
+    d /= foo.0;
+    d /= bar.x;
+    // 64
+
+    // Array + Field projection:
+    let mut arr: [Foo<u32>; 1] = [Foo(4)];
+    arr[0].0 /= 2;
+    d /= arr[0].0;
+    let mut arr: [Bar<u32>; 1] = [Bar { x: 4 }];
+    arr[0].x /= 2;
+    d /= arr[0].x;
+    // 16
+
+    // Field + Array projection:
+    let mut arr: Foo<[u32; 1]> = Foo([4]);
+    (arr.0)[0] /= 2;
+    d /= (arr.0)[0];
+    let mut arr: Bar<[u32; 1]> = Bar { x: [4] };
+    arr.x[0] /= 2;
+    d /= arr.x[0];
+    // 4
+
+    d
+}
+
+const fn rem_assign(W(a): W) -> u32 {
+    // Mutables:
+    let mut d: u32 = a;
+    d %= 10;
+    d += 10;
+
+    // Array projection
+    let mut arr: [u32; 1] = [3];
+    arr[0] %= 2;
+    d %= 9 + arr[0];
+    d += 10;
+
+    // Field projection:
+    let mut foo: Foo<u32> = Foo(5);
+    let mut bar: Bar<u32> = Bar { x: 7 };
+    foo.0 %= 2;
+    bar.x %= 2;
+    d %= 8 + foo.0 + bar.x;
+    d += 10;
+
+    // Array + Field projection:
+    let mut arr: [Foo<u32>; 1] = [Foo(4)];
+    arr[0].0 %= 3;
+    d %= 9 + arr[0].0;
+    d += 10;
+    let mut arr: [Bar<u32>; 1] = [Bar { x: 7 }];
+    arr[0].x %= 3;
+    d %= 9 + arr[0].x;
+    d += 10;
+
+    // Field + Array projection:
+    let mut arr: Foo<[u32; 1]> = Foo([6]);
+    (arr.0)[0] %= 5;
+    d %= 9 + (arr.0)[0];
+    let mut arr: Bar<[u32; 1]> = Bar { x: [11] };
+    arr.x[0] %= 5;
+    d %= 9 + arr.x[0];
+
+    d
+}
+
+const fn sub_assign(W(a): W) -> u32 {
+    // Mutables:
+    let mut d: u32 = a;
+    d -= 1;
+
+    // Array projection
+    let mut arr: [u32; 1] = [2];
+    arr[0] -= 1;
+    d -= arr[0];
+
+    // Field projection:
+    let mut foo: Foo<u32> = Foo(2);
+    let mut bar: Bar<u32> = Bar { x: 2 };
+    foo.0 -= 1;
+    bar.x -= 1;
+    d -= foo.0 + bar.x;
+
+    // Array + Field projection:
+    let mut arr: [Foo<u32>; 1] = [Foo(2)];
+    arr[0].0 -= 1;
+    d -= arr[0].0;
+    let mut arr: [Bar<u32>; 1] = [Bar { x: 2 }];
+    arr[0].x -= 1;
+    d -= arr[0].x;
+
+    // Field + Array projection:
+    let mut arr: Foo<[u32; 1]> = Foo([2]);
+    (arr.0)[0] -= 1;
+    d -= (arr.0)[0];
+    let mut arr: Bar<[u32; 1]> = Bar { x: [2] };
+    arr.x[0] -= 1;
+    d -= arr.x[0];
+
+    d
+}
+
+const fn shl_assign(W(a): W) -> u32 {
+    // Mutables:
+    let mut d: u32 = a;
+    d <<= 1; // 10
+
+    // Array projection
+    let mut arr: [u32; 1] = [1];
+    arr[0] <<= 1;
+    d <<= arr[0]; // 10 << 2
+
+    // Field projection:
+    let mut foo: Foo<u32> = Foo(1);
+    let mut bar: Bar<u32> = Bar { x: 1 };
+    foo.0 <<= 1;
+    bar.x <<= 1;
+    d <<= foo.0 + bar.x; // 1000 << 4
+
+    // Array + Field projection:
+    let mut arr: [Foo<u32>; 1] = [Foo(1)];
+    arr[0].0 <<= 1;
+    d <<= arr[0].0; // 1000_0000 << 2
+    let mut arr: [Bar<u32>; 1] = [Bar { x: 1 }];
+    arr[0].x <<= 1;
+    d <<= arr[0].x; // 1000_0000_00 << 2
+
+    // Field + Array projection:
+    let mut arr: Foo<[u32; 1]> = Foo([1]);
+    (arr.0)[0] <<= 1;
+    d <<= (arr.0)[0]; // 1000_0000_0000 << 2
+    let mut arr: Bar<[u32; 1]> = Bar { x: [1] };
+    arr.x[0] <<= 1;
+    d <<= arr.x[0]; // 1000_0000_0000_00 << 2
+
+    d
+}
+
+const fn shr_assign(W(a): W) -> u32 {
+    // Mutables:
+    let mut d: u32 = a;
+    d >>= 1; // /= 2
+
+    // Array projection
+    let mut arr: [u32; 1] = [2];
+    arr[0] >>= 1;
+    d >>= arr[0]; // /= 4
+
+    // Field projection:
+    let mut foo: Foo<u32> = Foo(2);
+    let mut bar: Bar<u32> = Bar { x: 2 };
+    foo.0 >>= 1;
+    bar.x >>= 1;
+    d >>= foo.0 + bar.x; // /= 16
+
+    // Array + Field projection:
+    let mut arr: [Foo<u32>; 1] = [Foo(2)];
+    arr[0].0 >>= 1;
+    d >>= arr[0].0; // /= 32
+    let mut arr: [Bar<u32>; 1] = [Bar { x: 2 }];
+    arr[0].x >>= 1;
+    d >>= arr[0].x; // /= 64
+
+    // Field + Array projection:
+    let mut arr: Foo<[u32; 1]> = Foo([2]);
+    (arr.0)[0] >>= 1;
+    d >>= (arr.0)[0]; // /= 128
+    let mut arr: Bar<[u32; 1]> = Bar { x: [2] };
+    arr.x[0] >>= 1;
+    d >>= arr.x[0]; // /= 256
+
+    d
+}
+
+const fn bit_and_assign(W(a): W) -> u32 {
+    let f = 0b1111_1111_1111_1111;
+
+    // Mutables:
+    let mut d: u32 = a;
+    d &= 0b1111_1111_1111_1110;
+
+    // Array projection
+    let mut arr: [u32; 1] = [f];
+    arr[0] &= 0b1111_1111_1111_1101;
+    d &= arr[0];
+
+    // Field projection:
+    let mut foo: Foo<u32> = Foo(f);
+    let mut bar: Bar<u32> = Bar { x: f };
+    foo.0 &= 0b1111_1111_1111_0111;
+    bar.x &= 0b1111_1111_1101_1111;
+    d &= foo.0 & bar.x;
+
+    // Array + Field projection:
+    let mut arr: [Foo<u32>; 1] = [Foo(f)];
+    arr[0].0 &= 0b1111_1110_1111_1111;
+    d &= arr[0].0;
+    let mut arr: [Bar<u32>; 1] = [Bar { x: f }];
+    arr[0].x &= 0b1111_1101_1111_1111;
+    d &= arr[0].x;
+
+    // Field + Array projection:
+    let mut arr: Foo<[u32; 1]> = Foo([f]);
+    (arr.0)[0] &= 0b1011_1111_1111_1111;
+    d &= (arr.0)[0];
+    let mut arr: Bar<[u32; 1]> = Bar { x: [f] };
+    arr.x[0] &= 0b0111_1111_1111_1111;
+    d &= arr.x[0];
+
+    d
+}
+
+const fn bit_or_assign(W(a): W) -> u32 {
+    let f = 0b0000_0000_0000_0000;
+
+    // Mutables:
+    let mut d: u32 = a;
+    d |= 0b0000_0000_0000_0001;
+
+    // Array projection
+    let mut arr: [u32; 1] = [f];
+    arr[0] |= 0b0000_0000_0000_1001;
+    d |= arr[0];
+
+    // Field projection:
+    let mut foo: Foo<u32> = Foo(f);
+    let mut bar: Bar<u32> = Bar { x: f };
+    foo.0 |= 0b0000_0000_0001_0000;
+    bar.x |= 0b0000_0000_0100_0000;
+    d |= foo.0 | bar.x;
+
+    // Array + Field projection:
+    let mut arr: [Foo<u32>; 1] = [Foo(f)];
+    arr[0].0 |= 0b0000_0001_0000_0000;
+    d |= arr[0].0;
+    let mut arr: [Bar<u32>; 1] = [Bar { x: f }];
+    arr[0].x |= 0b0000_0010_0000_0000;
+    d |= arr[0].x;
+
+    // Field + Array projection:
+    let mut arr: Foo<[u32; 1]> = Foo([f]);
+    (arr.0)[0] |= 0b1000_0000_0000_0000;
+    d |= (arr.0)[0]; // /= 128
+    let mut arr: Bar<[u32; 1]> = Bar { x: [f] };
+    arr.x[0] |= 0b1100_0000_0000_0000;
+    d |= arr.x[0]; // /= 256
+
+    d
+}
+
+const fn bit_xor_assign(W(a): W) -> u32 {
+    let f = 0b0000_0000_0000_0000;
+
+    // Mutables:
+    let mut d: u32 = a;
+    d ^= 0b0000_0000_0000_0001;
+
+    // Array projection
+    let mut arr: [u32; 1] = [f];
+    arr[0] ^= 0b0000_0000_0000_0010;
+    d ^= arr[0];
+
+    // Field projection:
+    let mut foo: Foo<u32> = Foo(f);
+    let mut bar: Bar<u32> = Bar { x: f };
+    foo.0 ^= 0b0000_0000_0001_0000;
+    bar.x ^= 0b0000_0000_1000_0000;
+    d ^= foo.0 ^ bar.x;
+
+    // Array + Field projection:
+    let mut arr: [Foo<u32>; 1] = [Foo(f)];
+    arr[0].0 ^= 0b0000_0001_0000_0000;
+    d ^= arr[0].0;
+    let mut arr: [Bar<u32>; 1] = [Bar { x: f }];
+    arr[0].x ^= 0b0000_0010_0000_0000;
+    d ^= arr[0].x;
+
+    // Field + Array projection:
+    let mut arr: Foo<[u32; 1]> = Foo([f]);
+    (arr.0)[0] ^= 0b0100_0000_0000_0000;
+    d ^= (arr.0)[0];
+    let mut arr: Bar<[u32; 1]> = Bar { x: [f] };
+    arr.x[0] ^= 0b1000_0000_0000_0000;
+    d ^= arr.x[0];
+
+    d
+}
+
+macro_rules! test {
+    ($c:ident, $e:expr, $r:expr) => {
+        const $c: u32 = $e;
+        assert_eq!($c, $r);
+        assert_eq!($e, $r);
+    }
+}
+
+fn main() {
+    test!(BASICS, basics((2,)), 13);
+    test!(ADD, add_assign(W(1)), 10);
+    test!(MUL, mul_assign(A { a: 0 }), 256);
+    test!(DIV, div_assign([1]), 4);
+    test!(REM, rem_assign(W(5)), 5);
+    test!(SUB, sub_assign(W(8)), 0);
+    test!(SHL, shl_assign(W(1)), 0b1000_0000_0000_0000);
+    test!(SHR, shr_assign(W(256)), 1);
+    test!(AND, bit_and_assign(W(0b1011_1111_1111_1111_1111)), 0b0011_1100_1101_0100);
+    test!(OR, bit_or_assign(W(0b1011_0000_0000_0000)), 0b1111_0011_0101_1001);
+    test!(XOR, bit_xor_assign(W(0b0000_0000_0000_0000)), 0b1100_0011_1001_0011);
+}
diff --git a/src/test/ui/consts/const_let_eq_float.rs b/src/test/ui/consts/const_let_eq_float.rs
new file mode 100644
index 0000000..c48f54e
--- /dev/null
+++ b/src/test/ui/consts/const_let_eq_float.rs
@@ -0,0 +1,279 @@
+// compile-pass
+
+#![feature(const_fn)]
+
+struct Foo<T>(T);
+struct Bar<T> { x: T }
+struct W(f32);
+struct A { a: f32 }
+
+const fn basics((a,): (f32,)) -> f32 {
+    // Deferred assignment:
+    let b: f32;
+    b = a + 1.0;
+
+    // Immediate assignment:
+    let c: f32 = b + 1.0;
+
+    // Mutables:
+    let mut d: f32 = c + 1.0;
+    d = d + 1.0;
+    // +4 so far.
+
+    // No effect statements work:
+    ; ;
+    1;
+
+    // Array projection
+    let mut arr: [f32; 1] = [0.0];
+    arr[0] = 1.0;
+    d = d + arr[0];
+    // +5
+
+    // Field projection:
+    let mut foo: Foo<f32> = Foo(0.0);
+    let mut bar: Bar<f32> = Bar { x: 0.0 };
+    foo.0 = 1.0;
+    bar.x = 1.0;
+    d = d + foo.0 + bar.x;
+    // +7
+
+    // Array + Field projection:
+    let mut arr: [Foo<f32>; 1] = [Foo(0.0)];
+    arr[0].0 = 1.0;
+    d = d + arr[0].0;
+    let mut arr: [Bar<f32>; 1] = [Bar { x: 0.0 }];
+    arr[0].x = 1.0;
+    d = d + arr[0].x;
+    // +9
+
+    // Field + Array projection:
+    let mut arr: Foo<[f32; 1]> = Foo([0.0]);
+    (arr.0)[0] = 1.0;
+    d = d + (arr.0)[0];
+    let mut arr: Bar<[f32; 1]> = Bar { x: [0.0] };
+    arr.x[0] = 1.0;
+    d = d + arr.x[0];
+    // +11
+
+    d
+}
+
+const fn add_assign(W(a): W) -> f32 {
+    // Mutables:
+    let mut d: f32 = a + 1.0;
+    d += 1.0;
+    // +2 so far.
+
+    // Array projection
+    let mut arr: [f32; 1] = [0.0];
+    arr[0] += 1.0;
+    d += arr[0];
+    // +3
+
+    // Field projection:
+    let mut foo: Foo<f32> = Foo(0.0);
+    let mut bar: Bar<f32> = Bar { x: 0.0 };
+    foo.0 += 1.0;
+    bar.x += 1.0;
+    d += foo.0 + bar.x;
+    // +5
+
+    // Array + Field projection:
+    let mut arr: [Foo<f32>; 1] = [Foo(0.0)];
+    arr[0].0 += 1.0;
+    d += arr[0].0;
+    let mut arr: [Bar<f32>; 1] = [Bar { x: 0.0 }];
+    arr[0].x += 1.0;
+    d += arr[0].x;
+    // +7
+
+    // Field + Array projection:
+    let mut arr: Foo<[f32; 1]> = Foo([0.0]);
+    (arr.0)[0] += 1.0;
+    d += (arr.0)[0];
+    let mut arr: Bar<[f32; 1]> = Bar { x: [0.0] };
+    arr.x[0] += 1.0;
+    d += arr.x[0];
+    // +9
+
+    d
+}
+
+const fn mul_assign(A { a }: A) -> f32 {
+    // Mutables:
+    let mut d: f32 = a + 1.0;
+    d *= 2.0;
+    // 2^1 * (a + 1)
+
+    // Array projection
+    let mut arr: [f32; 1] = [1.0];
+    arr[0] *= 2.0;
+    d *= arr[0];
+    // 2^2 * (a + 1)
+
+    // Field projection:
+    let mut foo: Foo<f32> = Foo(1.0);
+    let mut bar: Bar<f32> = Bar { x: 1.0 };
+    foo.0 *= 2.0;
+    bar.x *= 2.0;
+    d *= foo.0 + bar.x;
+    // 2^4 * (a + 1)
+
+    // Array + Field projection:
+    let mut arr: [Foo<f32>; 1] = [Foo(1.0)];
+    arr[0].0 *= 2.0;
+    d *= arr[0].0;
+    let mut arr: [Bar<f32>; 1] = [Bar { x: 1.0 }];
+    arr[0].x *= 2.0;
+    d *= arr[0].x;
+    // 2^6 * (a + 1)
+
+    // Field + Array projection:
+    let mut arr: Foo<[f32; 1]> = Foo([1.0]);
+    (arr.0)[0] *= 2.0;
+    d *= (arr.0)[0];
+    let mut arr: Bar<[f32; 1]> = Bar { x: [1.0] };
+    arr.x[0] *= 2.0;
+    d *= arr.x[0];
+    // 2^8 * (a + 1)
+
+    d
+}
+
+const fn div_assign(a: [f32; 1]) -> f32 {
+    let a = a[0];
+    // Mutables:
+    let mut d: f32 = 1024.0 * a;
+    d /= 2.0;
+    // 512
+
+    // Array projection
+    let mut arr: [f32; 1] = [4.0];
+    arr[0] /= 2.0;
+    d /= arr[0];
+    // 256
+
+    // Field projection:
+    let mut foo: Foo<f32> = Foo(4.0);
+    let mut bar: Bar<f32> = Bar { x: 4.0 };
+    foo.0 /= 2.0;
+    bar.x /= 2.0;
+    d /= foo.0;
+    d /= bar.x;
+    // 64
+
+    // Array + Field projection:
+    let mut arr: [Foo<f32>; 1] = [Foo(4.0)];
+    arr[0].0 /= 2.0;
+    d /= arr[0].0;
+    let mut arr: [Bar<f32>; 1] = [Bar { x: 4.0 }];
+    arr[0].x /= 2.0;
+    d /= arr[0].x;
+    // 16
+
+    // Field + Array projection:
+    let mut arr: Foo<[f32; 1]> = Foo([4.0]);
+    (arr.0)[0] /= 2.0;
+    d /= (arr.0)[0];
+    let mut arr: Bar<[f32; 1]> = Bar { x: [4.0] };
+    arr.x[0] /= 2.0;
+    d /= arr.x[0];
+    // 4
+
+    d
+}
+
+const fn rem_assign(W(a): W) -> f32 {
+    // Mutables:
+    let mut d: f32 = a;
+    d %= 10.0;
+    d += 10.0;
+
+    // Array projection
+    let mut arr: [f32; 1] = [3.0];
+    arr[0] %= 2.0;
+    d %= 9.0 + arr[0];
+    d += 10.0;
+
+    // Field projection:
+    let mut foo: Foo<f32> = Foo(5.0);
+    let mut bar: Bar<f32> = Bar { x: 7.0 };
+    foo.0 %= 2.0;
+    bar.x %= 2.0;
+    d %= 8.0 + foo.0 + bar.x;
+    d += 10.0;
+
+    // Array + Field projection:
+    let mut arr: [Foo<f32>; 1] = [Foo(4.0)];
+    arr[0].0 %= 3.0;
+    d %= 9.0 + arr[0].0;
+    d += 10.0;
+    let mut arr: [Bar<f32>; 1] = [Bar { x: 7.0 }];
+    arr[0].x %= 3.0;
+    d %= 9.0 + arr[0].x;
+    d += 10.0;
+
+    // Field + Array projection:
+    let mut arr: Foo<[f32; 1]> = Foo([6.0]);
+    (arr.0)[0] %= 5.0;
+    d %= 9.0 + (arr.0)[0];
+    let mut arr: Bar<[f32; 1]> = Bar { x: [11.0] };
+    arr.x[0] %= 5.0;
+    d %= 9.0 + arr.x[0];
+
+    d
+}
+
+const fn sub_assign(W(a): W) -> f32 {
+    // Mutables:
+    let mut d: f32 = a;
+    d -= 1.0;
+
+    // Array projection
+    let mut arr: [f32; 1] = [2.0];
+    arr[0] -= 1.0;
+    d -= arr[0];
+
+    // Field projection:
+    let mut foo: Foo<f32> = Foo(2.0);
+    let mut bar: Bar<f32> = Bar { x: 2.0 };
+    foo.0 -= 1.0;
+    bar.x -= 1.0;
+    d -= foo.0 + bar.x;
+
+    // Array + Field projection:
+    let mut arr: [Foo<f32>; 1] = [Foo(2.0)];
+    arr[0].0 -= 1.0;
+    d -= arr[0].0;
+    let mut arr: [Bar<f32>; 1] = [Bar { x: 2.0 }];
+    arr[0].x -= 1.0;
+    d -= arr[0].x;
+
+    // Field + Array projection:
+    let mut arr: Foo<[f32; 1]> = Foo([2.0]);
+    (arr.0)[0] -= 1.0;
+    d -= (arr.0)[0];
+    let mut arr: Bar<[f32; 1]> = Bar { x: [2.0] };
+    arr.x[0] -= 1.0;
+    d -= arr.x[0];
+
+    d
+}
+
+macro_rules! test {
+    ($c:ident, $e:expr, $r:expr) => {
+        const $c: f32 = $e;
+        assert_eq!($c, $r);
+        assert_eq!($e, $r);
+    }
+}
+
+fn main() {
+    test!(BASICS, basics((2.0,)), 13.0);
+    test!(ADD, add_assign(W(1.0)), 10.0);
+    test!(MUL, mul_assign(A { a: 0.0 }), 256.0);
+    test!(DIV, div_assign([1.0]), 4.0);
+    test!(REM, rem_assign(W(5.0)), 5.0);
+    test!(SUB, sub_assign(W(8.0)), 0.0);
+}
diff --git a/src/test/ui/consts/const_let_irrefutable.rs b/src/test/ui/consts/const_let_irrefutable.rs
new file mode 100644
index 0000000..424a16f
--- /dev/null
+++ b/src/test/ui/consts/const_let_irrefutable.rs
@@ -0,0 +1,11 @@
+// compile-pass
+
+fn main() {}
+
+const fn tup((a, b): (i32, i32)) -> i32 {
+    a + b
+}
+
+const fn array([a, b]: [i32; 2]) -> i32 {
+    a + b
+}
diff --git a/src/test/ui/consts/const_let_refutable.rs b/src/test/ui/consts/const_let_refutable.rs
new file mode 100644
index 0000000..345f682
--- /dev/null
+++ b/src/test/ui/consts/const_let_refutable.rs
@@ -0,0 +1,5 @@
+fn main() {}
+
+const fn slice([a, b]: &[i32]) -> i32 { //~ ERROR refutable pattern in function argument
+    a + b
+}
diff --git a/src/test/ui/consts/const_let_refutable.stderr b/src/test/ui/consts/const_let_refutable.stderr
new file mode 100644
index 0000000..155c858
--- /dev/null
+++ b/src/test/ui/consts/const_let_refutable.stderr
@@ -0,0 +1,9 @@
+error[E0005]: refutable pattern in function argument: `&[]` not covered
+  --> $DIR/const_let_refutable.rs:3:16
+   |
+LL | const fn slice([a, b]: &[i32]) -> i32 {
+   |                ^^^^^^ pattern `&[]` not covered
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0005`.
diff --git a/src/test/ui/consts/const_short_circuit.rs b/src/test/ui/consts/const_short_circuit.rs
new file mode 100644
index 0000000..1e7b7ed
--- /dev/null
+++ b/src/test/ui/consts/const_short_circuit.rs
@@ -0,0 +1,16 @@
+#![feature(underscore_const_names)]
+
+const _: bool = false && false;
+const _: bool = true && false;
+const _: bool = {
+    let mut x = true && false;
+    //~^ ERROR new features like let bindings are not permitted
+    x
+};
+const _: bool = {
+    let x = true && false;
+    //~^ ERROR new features like let bindings are not permitted
+    x
+};
+
+fn main() {}
diff --git a/src/test/ui/consts/const_short_circuit.stderr b/src/test/ui/consts/const_short_circuit.stderr
new file mode 100644
index 0000000..a67bb0b
--- /dev/null
+++ b/src/test/ui/consts/const_short_circuit.stderr
@@ -0,0 +1,26 @@
+error: new features like let bindings are not permitted in constants which also use short circuiting operators
+  --> $DIR/const_short_circuit.rs:6:9
+   |
+LL |     let mut x = true && false;
+   |         ^^^^^
+   |
+note: use of `&&` operator here does not actually short circuit due to the const evaluator presently not being able to do control flow. See https://github.com/rust-lang/rust/issues/49146 for more information.
+  --> $DIR/const_short_circuit.rs:6:22
+   |
+LL |     let mut x = true && false;
+   |                      ^^
+
+error: new features like let bindings are not permitted in constants which also use short circuiting operators
+  --> $DIR/const_short_circuit.rs:11:9
+   |
+LL |     let x = true && false;
+   |         ^
+   |
+note: use of `&&` operator here does not actually short circuit due to the const evaluator presently not being able to do control flow. See https://github.com/rust-lang/rust/issues/49146 for more information.
+  --> $DIR/const_short_circuit.rs:11:18
+   |
+LL |     let x = true && false;
+   |                  ^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/consts/dangling-alloc-id-ice.rs b/src/test/ui/consts/dangling-alloc-id-ice.rs
new file mode 100644
index 0000000..dbc50f1
--- /dev/null
+++ b/src/test/ui/consts/dangling-alloc-id-ice.rs
@@ -0,0 +1,13 @@
+// https://github.com/rust-lang/rust/issues/55223
+
+union Foo<'a> {
+    y: &'a (),
+    long_live_the_unit: &'static (),
+}
+
+const FOO: &() = { //~ ERROR any use of this value will cause an error
+    let y = ();
+    unsafe { Foo { y: &y }.long_live_the_unit }
+};
+
+fn main() {}
diff --git a/src/test/ui/consts/dangling-alloc-id-ice.stderr b/src/test/ui/consts/dangling-alloc-id-ice.stderr
new file mode 100644
index 0000000..87f8448
--- /dev/null
+++ b/src/test/ui/consts/dangling-alloc-id-ice.stderr
@@ -0,0 +1,13 @@
+error: any use of this value will cause an error
+  --> $DIR/dangling-alloc-id-ice.rs:8:1
+   |
+LL | / const FOO: &() = {
+LL | |     let y = ();
+LL | |     unsafe { Foo { y: &y }.long_live_the_unit }
+LL | | };
+   | |__^ type validation failed: encountered dangling pointer in final constant
+   |
+   = note: #[deny(const_err)] on by default
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/consts/dangling_raw_ptr.rs b/src/test/ui/consts/dangling_raw_ptr.rs
new file mode 100644
index 0000000..c2d8e6d
--- /dev/null
+++ b/src/test/ui/consts/dangling_raw_ptr.rs
@@ -0,0 +1,8 @@
+const FOO: *const u32 = { //~ ERROR any use of this value will cause an error
+    let x = 42;
+    &x
+};
+
+fn main() {
+    let x = FOO;
+}
diff --git a/src/test/ui/consts/dangling_raw_ptr.stderr b/src/test/ui/consts/dangling_raw_ptr.stderr
new file mode 100644
index 0000000..0168c08
--- /dev/null
+++ b/src/test/ui/consts/dangling_raw_ptr.stderr
@@ -0,0 +1,13 @@
+error: any use of this value will cause an error
+  --> $DIR/dangling_raw_ptr.rs:1:1
+   |
+LL | / const FOO: *const u32 = {
+LL | |     let x = 42;
+LL | |     &x
+LL | | };
+   | |__^ type validation failed: encountered dangling pointer in final constant
+   |
+   = note: #[deny(const_err)] on by default
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/consts/drop_none.rs b/src/test/ui/consts/drop_none.rs
new file mode 100644
index 0000000..86a197f
--- /dev/null
+++ b/src/test/ui/consts/drop_none.rs
@@ -0,0 +1,13 @@
+// compile-pass
+#![allow(dead_code)]
+struct A;
+impl Drop for A {
+    fn drop(&mut self) {}
+}
+
+const FOO: Option<A> = None;
+
+const BAR: () = (FOO, ()).1;
+
+
+fn main() {}
diff --git a/src/test/ui/consts/int_ptr_for_zst_slices.rs b/src/test/ui/consts/int_ptr_for_zst_slices.rs
new file mode 100644
index 0000000..afa2c6a
--- /dev/null
+++ b/src/test/ui/consts/int_ptr_for_zst_slices.rs
@@ -0,0 +1,7 @@
+// compile-pass
+
+#![feature(const_raw_ptr_deref)]
+
+const FOO: &str = unsafe { &*(1_usize as *const [u8; 0] as *const [u8] as *const str) };
+
+fn main() {}
diff --git a/src/test/ui/consts/invalid_promotion.rs b/src/test/ui/consts/invalid_promotion.rs
new file mode 100644
index 0000000..f98406e
--- /dev/null
+++ b/src/test/ui/consts/invalid_promotion.rs
@@ -0,0 +1,18 @@
+// compile-pass
+// note this was only reproducible with lib crates
+// compile-flags: --crate-type=lib
+
+pub struct Hz;
+
+impl Hz {
+    pub const fn num(&self) -> u32 {
+        42
+    }
+    pub const fn normalized(&self) -> Hz {
+        Hz
+    }
+
+    pub const fn as_u32(&self) -> u32 {
+        self.normalized().num() // this used to promote the `self.normalized()`
+    }
+}
diff --git a/src/test/ui/consts/issue-54224.rs b/src/test/ui/consts/issue-54224.rs
new file mode 100644
index 0000000..b5a8fe8
--- /dev/null
+++ b/src/test/ui/consts/issue-54224.rs
@@ -0,0 +1,14 @@
+#![feature(nll)]
+
+const FOO: Option<&[[u8; 3]]> = Some(&[*b"foo"]); //~ ERROR temporary value dropped while borrowed
+
+use std::borrow::Cow;
+
+pub const X: [u8; 3] = *b"ABC";
+pub const Y: Cow<'static, [ [u8; 3] ]> = Cow::Borrowed(&[X]);
+
+
+pub const Z: Cow<'static, [ [u8; 3] ]> = Cow::Borrowed(&[*b"ABC"]);
+//~^ ERROR temporary value dropped while borrowed
+
+fn main() {}
diff --git a/src/test/ui/consts/issue-54224.stderr b/src/test/ui/consts/issue-54224.stderr
new file mode 100644
index 0000000..9b6638b2
--- /dev/null
+++ b/src/test/ui/consts/issue-54224.stderr
@@ -0,0 +1,23 @@
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/issue-54224.rs:3:39
+   |
+LL | const FOO: Option<&[[u8; 3]]> = Some(&[*b"foo"]);
+   |                                 ------^^^^^^^^^-
+   |                                 |     |        |
+   |                                 |     |        temporary value is freed at the end of this statement
+   |                                 |     creates a temporary which is freed while still in use
+   |                                 using this value as a constant requires that borrow lasts for `'static`
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/issue-54224.rs:11:57
+   |
+LL | pub const Z: Cow<'static, [ [u8; 3] ]> = Cow::Borrowed(&[*b"ABC"]);
+   |                                          ---------------^^^^^^^^^-
+   |                                          |              |        |
+   |                                          |              |        temporary value is freed at the end of this statement
+   |                                          |              creates a temporary which is freed while still in use
+   |                                          using this value as a constant requires that borrow lasts for `'static`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/src/test/ui/consts/issue-56164.rs b/src/test/ui/consts/issue-56164.rs
new file mode 100644
index 0000000..9d1a8b5
--- /dev/null
+++ b/src/test/ui/consts/issue-56164.rs
@@ -0,0 +1,13 @@
+#![feature(const_fn)]
+
+const fn foo() { (||{})() }
+//~^ ERROR calls in constant functions are limited to constant functions, tuple structs and tuple
+// variants
+
+const fn bad(input: fn()) {
+    input()
+    //~^ ERROR function pointers are not allowed in const fn
+}
+
+fn main() {
+}
diff --git a/src/test/ui/consts/issue-56164.stderr b/src/test/ui/consts/issue-56164.stderr
new file mode 100644
index 0000000..d3e9ce3
--- /dev/null
+++ b/src/test/ui/consts/issue-56164.stderr
@@ -0,0 +1,15 @@
+error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
+  --> $DIR/issue-56164.rs:3:18
+   |
+LL | const fn foo() { (||{})() }
+   |                  ^^^^^^^^
+
+error: function pointers are not allowed in const fn
+  --> $DIR/issue-56164.rs:8:5
+   |
+LL |     input()
+   |     ^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0015`.
diff --git a/src/test/ui/consts/match_ice.rs b/src/test/ui/consts/match_ice.rs
new file mode 100644
index 0000000..53c5782
--- /dev/null
+++ b/src/test/ui/consts/match_ice.rs
@@ -0,0 +1,10 @@
+// https://github.com/rust-lang/rust/issues/53708
+
+struct S;
+
+fn main() {
+    const C: &S = &S;
+    match C { //~ ERROR non-exhaustive
+        C => {} // this is a common bug around constants and references in patterns
+    }
+}
diff --git a/src/test/ui/consts/match_ice.stderr b/src/test/ui/consts/match_ice.stderr
new file mode 100644
index 0000000..e238fad
--- /dev/null
+++ b/src/test/ui/consts/match_ice.stderr
@@ -0,0 +1,11 @@
+error[E0004]: non-exhaustive patterns: `&S` not covered
+  --> $DIR/match_ice.rs:7:11
+   |
+LL |     match C {
+   |           ^ pattern `&S` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/consts/min_const_fn/bad_const_fn_body_ice.rs b/src/test/ui/consts/min_const_fn/bad_const_fn_body_ice.rs
new file mode 100644
index 0000000..3e42cb8
--- /dev/null
+++ b/src/test/ui/consts/min_const_fn/bad_const_fn_body_ice.rs
@@ -0,0 +1,5 @@
+const fn foo(a: i32) -> Vec<i32> {
+    vec![1, 2, 3] //~ ERROR heap allocations are not allowed in const fn
+}
+
+fn main() {}
diff --git a/src/test/ui/consts/min_const_fn/bad_const_fn_body_ice.stderr b/src/test/ui/consts/min_const_fn/bad_const_fn_body_ice.stderr
new file mode 100644
index 0000000..b0cd57b
--- /dev/null
+++ b/src/test/ui/consts/min_const_fn/bad_const_fn_body_ice.stderr
@@ -0,0 +1,12 @@
+error[E0723]: heap allocations are not allowed in const fn (see issue #57563)
+  --> $DIR/bad_const_fn_body_ice.rs:2:5
+   |
+LL |     vec![1, 2, 3]
+   |     ^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0723`.
diff --git a/src/test/ui/consts/min_const_fn/cast_errors.rs b/src/test/ui/consts/min_const_fn/cast_errors.rs
new file mode 100644
index 0000000..8648cd3
--- /dev/null
+++ b/src/test/ui/consts/min_const_fn/cast_errors.rs
@@ -0,0 +1,14 @@
+fn main() {}
+
+const fn unsize(x: &[u8; 3]) -> &[u8] { x }
+//~^ ERROR unsizing casts are not allowed in const fn
+const fn closure() -> fn() { || {} }
+//~^ ERROR function pointers in const fn are unstable
+const fn closure2() {
+    (|| {}) as fn();
+//~^ ERROR function pointers in const fn are unstable
+}
+const fn reify(f: fn()) -> unsafe fn() { f }
+//~^ ERROR function pointers in const fn are unstable
+const fn reify2() { main as unsafe fn(); }
+//~^ ERROR function pointers in const fn are unstable
diff --git a/src/test/ui/consts/min_const_fn/cast_errors.stderr b/src/test/ui/consts/min_const_fn/cast_errors.stderr
new file mode 100644
index 0000000..b5af3e7
--- /dev/null
+++ b/src/test/ui/consts/min_const_fn/cast_errors.stderr
@@ -0,0 +1,43 @@
+error[E0723]: unsizing casts are not allowed in const fn (see issue #57563)
+  --> $DIR/cast_errors.rs:3:41
+   |
+LL | const fn unsize(x: &[u8; 3]) -> &[u8] { x }
+   |                                         ^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: function pointers in const fn are unstable (see issue #57563)
+  --> $DIR/cast_errors.rs:5:23
+   |
+LL | const fn closure() -> fn() { || {} }
+   |                       ^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: function pointers in const fn are unstable (see issue #57563)
+  --> $DIR/cast_errors.rs:8:5
+   |
+LL |     (|| {}) as fn();
+   |     ^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: function pointers in const fn are unstable (see issue #57563)
+  --> $DIR/cast_errors.rs:11:28
+   |
+LL | const fn reify(f: fn()) -> unsafe fn() { f }
+   |                            ^^^^^^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: function pointers in const fn are unstable (see issue #57563)
+  --> $DIR/cast_errors.rs:13:21
+   |
+LL | const fn reify2() { main as unsafe fn(); }
+   |                     ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0723`.
diff --git a/src/test/ui/consts/min_const_fn/cmp_fn_pointers.rs b/src/test/ui/consts/min_const_fn/cmp_fn_pointers.rs
new file mode 100644
index 0000000..c2600f8
--- /dev/null
+++ b/src/test/ui/consts/min_const_fn/cmp_fn_pointers.rs
@@ -0,0 +1,5 @@
+const fn cmp(x: fn(), y: fn()) -> bool { //~ ERROR function pointers in const fn are unstable
+    unsafe { x == y }
+}
+
+fn main() {}
diff --git a/src/test/ui/consts/min_const_fn/cmp_fn_pointers.stderr b/src/test/ui/consts/min_const_fn/cmp_fn_pointers.stderr
new file mode 100644
index 0000000..0de41c6
--- /dev/null
+++ b/src/test/ui/consts/min_const_fn/cmp_fn_pointers.stderr
@@ -0,0 +1,11 @@
+error[E0723]: function pointers in const fn are unstable (see issue #57563)
+  --> $DIR/cmp_fn_pointers.rs:1:14
+   |
+LL | const fn cmp(x: fn(), y: fn()) -> bool {
+   |              ^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0723`.
diff --git a/src/test/ui/consts/min_const_fn/loop_ice.rs b/src/test/ui/consts/min_const_fn/loop_ice.rs
new file mode 100644
index 0000000..4278a8e
--- /dev/null
+++ b/src/test/ui/consts/min_const_fn/loop_ice.rs
@@ -0,0 +1,5 @@
+const fn foo() {
+    loop {} //~ ERROR loops are not allowed in const fn
+}
+
+fn main() {}
diff --git a/src/test/ui/consts/min_const_fn/loop_ice.stderr b/src/test/ui/consts/min_const_fn/loop_ice.stderr
new file mode 100644
index 0000000..0d35e36
--- /dev/null
+++ b/src/test/ui/consts/min_const_fn/loop_ice.stderr
@@ -0,0 +1,11 @@
+error[E0723]: loops are not allowed in const fn (see issue #57563)
+  --> $DIR/loop_ice.rs:2:5
+   |
+LL |     loop {}
+   |     ^^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0723`.
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr b/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr
new file mode 100644
index 0000000..95b8097
--- /dev/null
+++ b/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr
@@ -0,0 +1,298 @@
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/min_const_fn.rs:37:25
+   |
+LL |     const fn into_inner(self) -> T { self.0 }
+   |                         ^^^^ constant functions cannot evaluate destructors
+
+error[E0723]: mutable references in const fn are unstable (see issue #57563)
+  --> $DIR/min_const_fn.rs:39:36
+   |
+LL |     const fn get_mut(&mut self) -> &mut T { &mut self.0 }
+   |                                    ^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/min_const_fn.rs:44:28
+   |
+LL |     const fn into_inner_lt(self) -> T { self.0 }
+   |                            ^^^^ constant functions cannot evaluate destructors
+
+error[E0723]: mutable references in const fn are unstable (see issue #57563)
+  --> $DIR/min_const_fn.rs:46:42
+   |
+LL |     const fn get_mut_lt(&'a mut self) -> &mut T { &mut self.0 }
+   |                                          ^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/min_const_fn.rs:51:27
+   |
+LL |     const fn into_inner_s(self) -> T { self.0 }
+   |                           ^^^^ constant functions cannot evaluate destructors
+
+error[E0723]: mutable references in const fn are unstable (see issue #57563)
+  --> $DIR/min_const_fn.rs:53:38
+   |
+LL |     const fn get_mut_s(&mut self) -> &mut T { &mut self.0 }
+   |                                      ^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: mutable references in const fn are unstable (see issue #57563)
+  --> $DIR/min_const_fn.rs:58:39
+   |
+LL |     const fn get_mut_sq(&mut self) -> &mut T { &mut self.0 }
+   |                                       ^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable (see issue #57563)
+  --> $DIR/min_const_fn.rs:76:16
+   |
+LL | const fn foo11<T: std::fmt::Display>(t: T) -> T { t }
+   |                ^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable (see issue #57563)
+  --> $DIR/min_const_fn.rs:78:18
+   |
+LL | const fn foo11_2<T: Send>(t: T) -> T { t }
+   |                  ^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: only int, `bool` and `char` operations are stable in const fn (see issue #57563)
+  --> $DIR/min_const_fn.rs:80:33
+   |
+LL | const fn foo19(f: f32) -> f32 { f * 2.0 }
+   |                                 ^^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: only int, `bool` and `char` operations are stable in const fn (see issue #57563)
+  --> $DIR/min_const_fn.rs:82:35
+   |
+LL | const fn foo19_2(f: f32) -> f32 { 2.0 - f }
+   |                                   ^^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: only int and `bool` operations are stable in const fn (see issue #57563)
+  --> $DIR/min_const_fn.rs:84:35
+   |
+LL | const fn foo19_3(f: f32) -> f32 { -f }
+   |                                   ^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: only int, `bool` and `char` operations are stable in const fn (see issue #57563)
+  --> $DIR/min_const_fn.rs:86:43
+   |
+LL | const fn foo19_4(f: f32, g: f32) -> f32 { f / g }
+   |                                           ^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: cannot access `static` items in const fn (see issue #57563)
+  --> $DIR/min_const_fn.rs:90:27
+   |
+LL | const fn foo25() -> u32 { BAR }
+   |                           ^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: cannot access `static` items in const fn (see issue #57563)
+  --> $DIR/min_const_fn.rs:91:36
+   |
+LL | const fn foo26() -> &'static u32 { &BAR }
+   |                                    ^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: casting pointers to ints is unstable in const fn (see issue #57563)
+  --> $DIR/min_const_fn.rs:92:42
+   |
+LL | const fn foo30(x: *const u32) -> usize { x as usize }
+   |                                          ^^^^^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: casting pointers to ints is unstable in const fn (see issue #57563)
+  --> $DIR/min_const_fn.rs:94:63
+   |
+LL | const fn foo30_with_unsafe(x: *const u32) -> usize { unsafe { x as usize } }
+   |                                                               ^^^^^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: casting pointers to ints is unstable in const fn (see issue #57563)
+  --> $DIR/min_const_fn.rs:96:42
+   |
+LL | const fn foo30_2(x: *mut u32) -> usize { x as usize }
+   |                                          ^^^^^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: casting pointers to ints is unstable in const fn (see issue #57563)
+  --> $DIR/min_const_fn.rs:98:63
+   |
+LL | const fn foo30_2_with_unsafe(x: *mut u32) -> usize { unsafe { x as usize } }
+   |                                                               ^^^^^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: `if`, `match`, `&&` and `||` are not stable in const fn (see issue #57563)
+  --> $DIR/min_const_fn.rs:100:38
+   |
+LL | const fn foo30_4(b: bool) -> usize { if b { 1 } else { 42 } }
+   |                                      ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: `if`, `match`, `&&` and `||` are not stable in const fn (see issue #57563)
+  --> $DIR/min_const_fn.rs:102:29
+   |
+LL | const fn foo30_5(b: bool) { while b { } }
+   |                             ^^^^^^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: `if`, `match`, `&&` and `||` are not stable in const fn (see issue #57563)
+  --> $DIR/min_const_fn.rs:104:44
+   |
+LL | const fn foo36(a: bool, b: bool) -> bool { a && b }
+   |                                            ^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: `if`, `match`, `&&` and `||` are not stable in const fn (see issue #57563)
+  --> $DIR/min_const_fn.rs:106:44
+   |
+LL | const fn foo37(a: bool, b: bool) -> bool { a || b }
+   |                                            ^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: mutable references in const fn are unstable (see issue #57563)
+  --> $DIR/min_const_fn.rs:108:14
+   |
+LL | const fn inc(x: &mut i32) { *x += 1 }
+   |              ^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable (see issue #57563)
+  --> $DIR/min_const_fn.rs:113:6
+   |
+LL | impl<T: std::fmt::Debug> Foo<T> {
+   |      ^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable (see issue #57563)
+  --> $DIR/min_const_fn.rs:118:6
+   |
+LL | impl<T: std::fmt::Debug + Sized> Foo<T> {
+   |      ^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable (see issue #57563)
+  --> $DIR/min_const_fn.rs:123:6
+   |
+LL | impl<T: Sync + Sized> Foo<T> {
+   |      ^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: `impl Trait` in const fn is unstable (see issue #57563)
+  --> $DIR/min_const_fn.rs:129:24
+   |
+LL | const fn no_rpit2() -> AlanTuring<impl std::fmt::Debug> { AlanTuring(0) }
+   |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable (see issue #57563)
+  --> $DIR/min_const_fn.rs:131:34
+   |
+LL | const fn no_apit2(_x: AlanTuring<impl std::fmt::Debug>) {}
+   |                                  ^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable (see issue #57563)
+  --> $DIR/min_const_fn.rs:133:22
+   |
+LL | const fn no_apit(_x: impl std::fmt::Debug) {}
+   |                      ^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: `impl Trait` in const fn is unstable (see issue #57563)
+  --> $DIR/min_const_fn.rs:134:23
+   |
+LL | const fn no_rpit() -> impl std::fmt::Debug {}
+   |                       ^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable (see issue #57563)
+  --> $DIR/min_const_fn.rs:135:23
+   |
+LL | const fn no_dyn_trait(_x: &dyn std::fmt::Debug) {}
+   |                       ^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable (see issue #57563)
+  --> $DIR/min_const_fn.rs:136:32
+   |
+LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() }
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+warning[E0515]: cannot return reference to temporary value
+  --> $DIR/min_const_fn.rs:136:63
+   |
+LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() }
+   |                                                               ^--
+   |                                                               ||
+   |                                                               |temporary value created here
+   |                                                               returns a reference to data owned by the current function
+   |
+   = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
+   = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+
+error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable (see issue #57563)
+  --> $DIR/min_const_fn.rs:141:41
+   |
+LL | const fn really_no_traits_i_mean_it() { (&() as &std::fmt::Debug, ()).1 }
+   |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: function pointers in const fn are unstable (see issue #57563)
+  --> $DIR/min_const_fn.rs:144:21
+   |
+LL | const fn no_fn_ptrs(_x: fn()) {}
+   |                     ^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: function pointers in const fn are unstable (see issue #57563)
+  --> $DIR/min_const_fn.rs:146:27
+   |
+LL | const fn no_fn_ptrs2() -> fn() { fn foo() {} foo }
+   |                           ^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error: aborting due to 36 previous errors
+
+Some errors occurred: E0493, E0515, E0723.
+For more information about an error, try `rustc --explain E0493`.
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.rs b/src/test/ui/consts/min_const_fn/min_const_fn.rs
new file mode 100644
index 0000000..ee3ffcd
--- /dev/null
+++ b/src/test/ui/consts/min_const_fn/min_const_fn.rs
@@ -0,0 +1,148 @@
+// ok
+const fn foo1() {}
+const fn foo2(x: i32) -> i32 { x }
+const fn foo3<T>(x: T) -> T { x }
+const fn foo7() {
+    (
+        foo1(),
+        foo2(420),
+        foo3(69),
+    ).0
+}
+const fn foo12<T: Sized>(t: T) -> T { t }
+const fn foo13<T: ?Sized>(t: &T) -> &T { t }
+const fn foo14<'a, T: 'a>(t: &'a T) -> &'a T { t }
+const fn foo15<T>(t: T) -> T where T: Sized { t }
+const fn foo15_2<T>(t: &T) -> &T where T: ?Sized { t }
+const fn foo16(f: f32) -> f32 { f }
+const fn foo17(f: f32) -> u32 { f as u32 }
+const fn foo18(i: i32) -> i32 { i * 3 }
+const fn foo20(b: bool) -> bool { !b }
+const fn foo21<T, U>(t: T, u: U) -> (T, U) { (t, u) }
+const fn foo22(s: &[u8], i: usize) -> u8 { s[i] }
+const FOO: u32 = 42;
+const fn foo23() -> u32 { FOO }
+const fn foo24() -> &'static u32 { &FOO }
+const fn foo27(x: &u32) -> u32 { *x }
+const fn foo28(x: u32) -> u32 { *&x }
+const fn foo29(x: u32) -> i32 { x as i32 }
+const fn foo31(a: bool, b: bool) -> bool { a & b }
+const fn foo32(a: bool, b: bool) -> bool { a | b }
+const fn foo33(a: bool, b: bool) -> bool { a & b }
+const fn foo34(a: bool, b: bool) -> bool { a | b }
+const fn foo35(a: bool, b: bool) -> bool { a ^ b }
+struct Foo<T: ?Sized>(T);
+impl<T> Foo<T> {
+    const fn new(t: T) -> Self { Foo(t) }
+    const fn into_inner(self) -> T { self.0 } //~ destructors cannot be evaluated
+    const fn get(&self) -> &T { &self.0 }
+    const fn get_mut(&mut self) -> &mut T { &mut self.0 }
+    //~^ mutable references in const fn are unstable
+}
+impl<'a, T> Foo<T> {
+    const fn new_lt(t: T) -> Self { Foo(t) }
+    const fn into_inner_lt(self) -> T { self.0 } //~ destructors cannot be evaluated
+    const fn get_lt(&'a self) -> &T { &self.0 }
+    const fn get_mut_lt(&'a mut self) -> &mut T { &mut self.0 }
+    //~^ mutable references in const fn are unstable
+}
+impl<T: Sized> Foo<T> {
+    const fn new_s(t: T) -> Self { Foo(t) }
+    const fn into_inner_s(self) -> T { self.0 } //~ ERROR destructors
+    const fn get_s(&self) -> &T { &self.0 }
+    const fn get_mut_s(&mut self) -> &mut T { &mut self.0 }
+    //~^ mutable references in const fn are unstable
+}
+impl<T: ?Sized> Foo<T> {
+    const fn get_sq(&self) -> &T { &self.0 }
+    const fn get_mut_sq(&mut self) -> &mut T { &mut self.0 }
+    //~^ mutable references in const fn are unstable
+}
+
+
+const fn char_ops(c: char, d: char) -> bool { c == d }
+const fn char_ops2(c: char, d: char) -> bool { c < d }
+const fn char_ops3(c: char, d: char) -> bool { c != d }
+const fn i32_ops(c: i32, d: i32) -> bool { c == d }
+const fn i32_ops2(c: i32, d: i32) -> bool { c < d }
+const fn i32_ops3(c: i32, d: i32) -> bool { c != d }
+const fn i32_ops4(c: i32, d: i32) -> i32 { c + d }
+const fn char_cast(u: u8) -> char { u as char }
+const unsafe fn ret_i32_no_unsafe() -> i32 { 42 }
+const unsafe fn ret_null_ptr_no_unsafe<T>() -> *const T { 0 as *const T }
+const unsafe fn ret_null_mut_ptr_no_unsafe<T>() -> *mut T { 0 as *mut T }
+
+// not ok
+const fn foo11<T: std::fmt::Display>(t: T) -> T { t }
+//~^ ERROR trait bounds other than `Sized` on const fn parameters are unstable
+const fn foo11_2<T: Send>(t: T) -> T { t }
+//~^ ERROR trait bounds other than `Sized` on const fn parameters are unstable
+const fn foo19(f: f32) -> f32 { f * 2.0 }
+//~^ ERROR only int, `bool` and `char` operations are stable in const fn
+const fn foo19_2(f: f32) -> f32 { 2.0 - f }
+//~^ ERROR only int, `bool` and `char` operations are stable in const fn
+const fn foo19_3(f: f32) -> f32 { -f }
+//~^ ERROR only int and `bool` operations are stable in const fn
+const fn foo19_4(f: f32, g: f32) -> f32 { f / g }
+//~^ ERROR only int, `bool` and `char` operations are stable in const fn
+
+static BAR: u32 = 42;
+const fn foo25() -> u32 { BAR } //~ ERROR cannot access `static` items in const fn
+const fn foo26() -> &'static u32 { &BAR } //~ ERROR cannot access `static` items
+const fn foo30(x: *const u32) -> usize { x as usize }
+//~^ ERROR casting pointers to ints is unstable
+const fn foo30_with_unsafe(x: *const u32) -> usize { unsafe { x as usize } }
+//~^ ERROR casting pointers to ints is unstable
+const fn foo30_2(x: *mut u32) -> usize { x as usize }
+//~^ ERROR casting pointers to ints is unstable
+const fn foo30_2_with_unsafe(x: *mut u32) -> usize { unsafe { x as usize } }
+//~^ ERROR casting pointers to ints is unstable
+const fn foo30_4(b: bool) -> usize { if b { 1 } else { 42 } }
+//~^ ERROR `if`, `match`, `&&` and `||` are not stable in const fn
+const fn foo30_5(b: bool) { while b { } } //~ ERROR not stable in const fn
+const fn foo30_6() -> bool { let x = true; x }
+const fn foo36(a: bool, b: bool) -> bool { a && b }
+//~^ ERROR `if`, `match`, `&&` and `||` are not stable in const fn
+const fn foo37(a: bool, b: bool) -> bool { a || b }
+//~^ ERROR `if`, `match`, `&&` and `||` are not stable in const fn
+const fn inc(x: &mut i32) { *x += 1 }
+//~^ ERROR mutable references in const fn are unstable
+
+fn main() {}
+
+impl<T: std::fmt::Debug> Foo<T> {
+//~^ ERROR trait bounds other than `Sized` on const fn parameters are unstable
+    const fn foo(&self) {}
+}
+
+impl<T: std::fmt::Debug + Sized> Foo<T> {
+//~^ ERROR trait bounds other than `Sized` on const fn parameters are unstable
+    const fn foo2(&self) {}
+}
+
+impl<T: Sync + Sized> Foo<T> {
+//~^ ERROR trait bounds other than `Sized` on const fn parameters are unstable
+    const fn foo3(&self) {}
+}
+
+struct AlanTuring<T>(T);
+const fn no_rpit2() -> AlanTuring<impl std::fmt::Debug> { AlanTuring(0) }
+//~^ ERROR `impl Trait` in const fn is unstable
+const fn no_apit2(_x: AlanTuring<impl std::fmt::Debug>) {}
+//~^ ERROR trait bounds other than `Sized`
+const fn no_apit(_x: impl std::fmt::Debug) {} //~ ERROR trait bounds other than `Sized`
+const fn no_rpit() -> impl std::fmt::Debug {} //~ ERROR `impl Trait` in const fn is unstable
+const fn no_dyn_trait(_x: &dyn std::fmt::Debug) {} //~ ERROR trait bounds other than `Sized`
+const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() }
+//~^ ERROR trait bounds other than `Sized`
+
+const fn no_unsafe() { unsafe {} }
+
+const fn really_no_traits_i_mean_it() { (&() as &std::fmt::Debug, ()).1 }
+//~^ ERROR trait bounds other than `Sized`
+
+const fn no_fn_ptrs(_x: fn()) {}
+//~^ ERROR function pointers in const fn are unstable
+const fn no_fn_ptrs2() -> fn() { fn foo() {} foo }
+//~^ ERROR function pointers in const fn are unstable
+
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.stderr b/src/test/ui/consts/min_const_fn/min_const_fn.stderr
new file mode 100644
index 0000000..cdf6b10
--- /dev/null
+++ b/src/test/ui/consts/min_const_fn/min_const_fn.stderr
@@ -0,0 +1,286 @@
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/min_const_fn.rs:37:25
+   |
+LL |     const fn into_inner(self) -> T { self.0 }
+   |                         ^^^^ constant functions cannot evaluate destructors
+
+error[E0723]: mutable references in const fn are unstable (see issue #57563)
+  --> $DIR/min_const_fn.rs:39:36
+   |
+LL |     const fn get_mut(&mut self) -> &mut T { &mut self.0 }
+   |                                    ^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/min_const_fn.rs:44:28
+   |
+LL |     const fn into_inner_lt(self) -> T { self.0 }
+   |                            ^^^^ constant functions cannot evaluate destructors
+
+error[E0723]: mutable references in const fn are unstable (see issue #57563)
+  --> $DIR/min_const_fn.rs:46:42
+   |
+LL |     const fn get_mut_lt(&'a mut self) -> &mut T { &mut self.0 }
+   |                                          ^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/min_const_fn.rs:51:27
+   |
+LL |     const fn into_inner_s(self) -> T { self.0 }
+   |                           ^^^^ constant functions cannot evaluate destructors
+
+error[E0723]: mutable references in const fn are unstable (see issue #57563)
+  --> $DIR/min_const_fn.rs:53:38
+   |
+LL |     const fn get_mut_s(&mut self) -> &mut T { &mut self.0 }
+   |                                      ^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: mutable references in const fn are unstable (see issue #57563)
+  --> $DIR/min_const_fn.rs:58:39
+   |
+LL |     const fn get_mut_sq(&mut self) -> &mut T { &mut self.0 }
+   |                                       ^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable (see issue #57563)
+  --> $DIR/min_const_fn.rs:76:16
+   |
+LL | const fn foo11<T: std::fmt::Display>(t: T) -> T { t }
+   |                ^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable (see issue #57563)
+  --> $DIR/min_const_fn.rs:78:18
+   |
+LL | const fn foo11_2<T: Send>(t: T) -> T { t }
+   |                  ^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: only int, `bool` and `char` operations are stable in const fn (see issue #57563)
+  --> $DIR/min_const_fn.rs:80:33
+   |
+LL | const fn foo19(f: f32) -> f32 { f * 2.0 }
+   |                                 ^^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: only int, `bool` and `char` operations are stable in const fn (see issue #57563)
+  --> $DIR/min_const_fn.rs:82:35
+   |
+LL | const fn foo19_2(f: f32) -> f32 { 2.0 - f }
+   |                                   ^^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: only int and `bool` operations are stable in const fn (see issue #57563)
+  --> $DIR/min_const_fn.rs:84:35
+   |
+LL | const fn foo19_3(f: f32) -> f32 { -f }
+   |                                   ^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: only int, `bool` and `char` operations are stable in const fn (see issue #57563)
+  --> $DIR/min_const_fn.rs:86:43
+   |
+LL | const fn foo19_4(f: f32, g: f32) -> f32 { f / g }
+   |                                           ^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: cannot access `static` items in const fn (see issue #57563)
+  --> $DIR/min_const_fn.rs:90:27
+   |
+LL | const fn foo25() -> u32 { BAR }
+   |                           ^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: cannot access `static` items in const fn (see issue #57563)
+  --> $DIR/min_const_fn.rs:91:36
+   |
+LL | const fn foo26() -> &'static u32 { &BAR }
+   |                                    ^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: casting pointers to ints is unstable in const fn (see issue #57563)
+  --> $DIR/min_const_fn.rs:92:42
+   |
+LL | const fn foo30(x: *const u32) -> usize { x as usize }
+   |                                          ^^^^^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: casting pointers to ints is unstable in const fn (see issue #57563)
+  --> $DIR/min_const_fn.rs:94:63
+   |
+LL | const fn foo30_with_unsafe(x: *const u32) -> usize { unsafe { x as usize } }
+   |                                                               ^^^^^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: casting pointers to ints is unstable in const fn (see issue #57563)
+  --> $DIR/min_const_fn.rs:96:42
+   |
+LL | const fn foo30_2(x: *mut u32) -> usize { x as usize }
+   |                                          ^^^^^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: casting pointers to ints is unstable in const fn (see issue #57563)
+  --> $DIR/min_const_fn.rs:98:63
+   |
+LL | const fn foo30_2_with_unsafe(x: *mut u32) -> usize { unsafe { x as usize } }
+   |                                                               ^^^^^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: `if`, `match`, `&&` and `||` are not stable in const fn (see issue #57563)
+  --> $DIR/min_const_fn.rs:100:38
+   |
+LL | const fn foo30_4(b: bool) -> usize { if b { 1 } else { 42 } }
+   |                                      ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: `if`, `match`, `&&` and `||` are not stable in const fn (see issue #57563)
+  --> $DIR/min_const_fn.rs:102:29
+   |
+LL | const fn foo30_5(b: bool) { while b { } }
+   |                             ^^^^^^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: `if`, `match`, `&&` and `||` are not stable in const fn (see issue #57563)
+  --> $DIR/min_const_fn.rs:104:44
+   |
+LL | const fn foo36(a: bool, b: bool) -> bool { a && b }
+   |                                            ^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: `if`, `match`, `&&` and `||` are not stable in const fn (see issue #57563)
+  --> $DIR/min_const_fn.rs:106:44
+   |
+LL | const fn foo37(a: bool, b: bool) -> bool { a || b }
+   |                                            ^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: mutable references in const fn are unstable (see issue #57563)
+  --> $DIR/min_const_fn.rs:108:14
+   |
+LL | const fn inc(x: &mut i32) { *x += 1 }
+   |              ^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable (see issue #57563)
+  --> $DIR/min_const_fn.rs:113:6
+   |
+LL | impl<T: std::fmt::Debug> Foo<T> {
+   |      ^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable (see issue #57563)
+  --> $DIR/min_const_fn.rs:118:6
+   |
+LL | impl<T: std::fmt::Debug + Sized> Foo<T> {
+   |      ^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable (see issue #57563)
+  --> $DIR/min_const_fn.rs:123:6
+   |
+LL | impl<T: Sync + Sized> Foo<T> {
+   |      ^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: `impl Trait` in const fn is unstable (see issue #57563)
+  --> $DIR/min_const_fn.rs:129:24
+   |
+LL | const fn no_rpit2() -> AlanTuring<impl std::fmt::Debug> { AlanTuring(0) }
+   |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable (see issue #57563)
+  --> $DIR/min_const_fn.rs:131:34
+   |
+LL | const fn no_apit2(_x: AlanTuring<impl std::fmt::Debug>) {}
+   |                                  ^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable (see issue #57563)
+  --> $DIR/min_const_fn.rs:133:22
+   |
+LL | const fn no_apit(_x: impl std::fmt::Debug) {}
+   |                      ^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: `impl Trait` in const fn is unstable (see issue #57563)
+  --> $DIR/min_const_fn.rs:134:23
+   |
+LL | const fn no_rpit() -> impl std::fmt::Debug {}
+   |                       ^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable (see issue #57563)
+  --> $DIR/min_const_fn.rs:135:23
+   |
+LL | const fn no_dyn_trait(_x: &dyn std::fmt::Debug) {}
+   |                       ^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable (see issue #57563)
+  --> $DIR/min_const_fn.rs:136:32
+   |
+LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() }
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable (see issue #57563)
+  --> $DIR/min_const_fn.rs:141:41
+   |
+LL | const fn really_no_traits_i_mean_it() { (&() as &std::fmt::Debug, ()).1 }
+   |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: function pointers in const fn are unstable (see issue #57563)
+  --> $DIR/min_const_fn.rs:144:21
+   |
+LL | const fn no_fn_ptrs(_x: fn()) {}
+   |                     ^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: function pointers in const fn are unstable (see issue #57563)
+  --> $DIR/min_const_fn.rs:146:27
+   |
+LL | const fn no_fn_ptrs2() -> fn() { fn foo() {} foo }
+   |                           ^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error: aborting due to 36 previous errors
+
+Some errors occurred: E0493, E0723.
+For more information about an error, try `rustc --explain E0493`.
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_dyn.nll.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_dyn.nll.stderr
new file mode 100644
index 0000000..2800d62
--- /dev/null
+++ b/src/test/ui/consts/min_const_fn/min_const_fn_dyn.nll.stderr
@@ -0,0 +1,32 @@
+error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable (see issue #57563)
+  --> $DIR/min_const_fn_dyn.rs:9:5
+   |
+LL |     x.0.field;
+   |     ^^^^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable (see issue #57563)
+  --> $DIR/min_const_fn_dyn.rs:12:66
+   |
+LL | const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasDyn { field: &0 }) }
+   |                                                                  ^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+warning[E0716]: temporary value dropped while borrowed
+  --> $DIR/min_const_fn_dyn.rs:12:67
+   |
+LL | const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasDyn { field: &0 }) }
+   |                                                                  -^    - temporary value is freed at the end of this statement
+   |                                                                  ||
+   |                                                                  |creates a temporary which is freed while still in use
+   |                                                                  cast requires that borrow lasts for `'static`
+   |
+   = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
+   = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0716, E0723.
+For more information about an error, try `rustc --explain E0716`.
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_dyn.rs b/src/test/ui/consts/min_const_fn/min_const_fn_dyn.rs
new file mode 100644
index 0000000..6ca1e59
--- /dev/null
+++ b/src/test/ui/consts/min_const_fn/min_const_fn_dyn.rs
@@ -0,0 +1,15 @@
+struct HasDyn {
+    field: &'static dyn std::fmt::Debug,
+}
+
+struct Hide(HasDyn);
+
+const fn no_inner_dyn_trait(_x: Hide) {}
+const fn no_inner_dyn_trait2(x: Hide) {
+    x.0.field;
+//~^ ERROR trait bounds other than `Sized`
+}
+const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasDyn { field: &0 }) }
+//~^ ERROR trait bounds other than `Sized`
+
+fn main() {}
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr
new file mode 100644
index 0000000..8ff9637
--- /dev/null
+++ b/src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr
@@ -0,0 +1,19 @@
+error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable (see issue #57563)
+  --> $DIR/min_const_fn_dyn.rs:9:5
+   |
+LL |     x.0.field;
+   |     ^^^^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable (see issue #57563)
+  --> $DIR/min_const_fn_dyn.rs:12:66
+   |
+LL | const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasDyn { field: &0 }) }
+   |                                                                  ^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0723`.
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.rs b/src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.rs
new file mode 100644
index 0000000..584ea46
--- /dev/null
+++ b/src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.rs
@@ -0,0 +1,17 @@
+struct HasPtr {
+    field: fn(),
+}
+
+struct Hide(HasPtr);
+
+fn field() {}
+
+const fn no_inner_dyn_trait(_x: Hide) {}
+const fn no_inner_dyn_trait2(x: Hide) {
+    x.0.field;
+//~^ ERROR function pointers in const fn
+}
+const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasPtr { field }) }
+//~^ ERROR function pointers in const fn
+
+fn main() {}
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.stderr
new file mode 100644
index 0000000..8838aba
--- /dev/null
+++ b/src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.stderr
@@ -0,0 +1,19 @@
+error[E0723]: function pointers in const fn are unstable (see issue #57563)
+  --> $DIR/min_const_fn_fn_ptr.rs:11:5
+   |
+LL |     x.0.field;
+   |     ^^^^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: function pointers in const fn are unstable (see issue #57563)
+  --> $DIR/min_const_fn_fn_ptr.rs:14:59
+   |
+LL | const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasPtr { field }) }
+   |                                                           ^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0723`.
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_libstd.rs b/src/test/ui/consts/min_const_fn/min_const_fn_libstd.rs
new file mode 100644
index 0000000..781d289
--- /dev/null
+++ b/src/test/ui/consts/min_const_fn/min_const_fn_libstd.rs
@@ -0,0 +1,28 @@
+#![feature(integer_atomics)]
+
+// compile-pass
+
+use std::cell::UnsafeCell;
+use std::sync::atomic::AtomicU32;
+pub struct Condvar {
+    condvar: UnsafeCell<AtomicU32>,
+}
+
+unsafe impl Send for Condvar {}
+unsafe impl Sync for Condvar {}
+
+#[repr(C)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+struct NoWait(u32);
+
+const CONDVAR_HAS_NO_WAITERS: NoWait = NoWait(42);
+
+impl Condvar {
+    pub const fn new() -> Condvar {
+        Condvar {
+            condvar: UnsafeCell::new(AtomicU32::new(CONDVAR_HAS_NO_WAITERS.0)),
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs b/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs
new file mode 100644
index 0000000..db416e7
--- /dev/null
+++ b/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs
@@ -0,0 +1,36 @@
+#![unstable(feature = "humans",
+            reason = "who ever let humans program computers,
+            we're apparently really bad at it",
+            issue = "0")]
+
+#![feature(rustc_const_unstable, const_fn, foo, foo2)]
+#![feature(staged_api)]
+
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_const_unstable(feature="foo")]
+const fn foo() -> u32 { 42 }
+
+#[stable(feature = "rust1", since = "1.0.0")]
+// can't call non-min_const_fn
+const fn bar() -> u32 { foo() } //~ ERROR can only call other `min_const_fn`
+
+#[unstable(feature = "rust1", issue="0")]
+const fn foo2() -> u32 { 42 }
+
+#[stable(feature = "rust1", since = "1.0.0")]
+// can't call non-min_const_fn
+const fn bar2() -> u32 { foo2() } //~ ERROR can only call other `min_const_fn`
+
+#[stable(feature = "rust1", since = "1.0.0")]
+// conformity is required, even with `const_fn` feature gate
+const fn bar3() -> u32 { (5f32 + 6f32) as u32 } //~ ERROR only int, `bool` and `char` operations
+
+// check whether this function cannot be called even with the feature gate active
+#[unstable(feature = "foo2", issue="0")]
+const fn foo2_gated() -> u32 { 42 }
+
+#[stable(feature = "rust1", since = "1.0.0")]
+// can't call non-min_const_fn
+const fn bar2_gated() -> u32 { foo2_gated() } //~ ERROR can only call other `min_const_fn`
+
+fn main() {}
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr
new file mode 100644
index 0000000..a8d0dc3
--- /dev/null
+++ b/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr
@@ -0,0 +1,35 @@
+error[E0723]: can only call other `min_const_fn` within a `min_const_fn` (see issue #57563)
+  --> $DIR/min_const_fn_libstd_stability.rs:15:25
+   |
+LL | const fn bar() -> u32 { foo() }
+   |                         ^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: can only call other `min_const_fn` within a `min_const_fn` (see issue #57563)
+  --> $DIR/min_const_fn_libstd_stability.rs:22:26
+   |
+LL | const fn bar2() -> u32 { foo2() }
+   |                          ^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: only int, `bool` and `char` operations are stable in const fn (see issue #57563)
+  --> $DIR/min_const_fn_libstd_stability.rs:26:26
+   |
+LL | const fn bar3() -> u32 { (5f32 + 6f32) as u32 }
+   |                          ^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: can only call other `min_const_fn` within a `min_const_fn` (see issue #57563)
+  --> $DIR/min_const_fn_libstd_stability.rs:34:32
+   |
+LL | const fn bar2_gated() -> u32 { foo2_gated() }
+   |                                ^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0723`.
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.rs b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.rs
new file mode 100644
index 0000000..e25dafa
--- /dev/null
+++ b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.rs
@@ -0,0 +1,65 @@
+//------------------------------------------------------------------------------
+// OK
+//------------------------------------------------------------------------------
+
+const unsafe fn ret_i32_no_unsafe() -> i32 { 42 }
+const unsafe fn ret_null_ptr_no_unsafe<T>() -> *const T { 0 as *const T }
+const unsafe fn ret_null_mut_ptr_no_unsafe<T>() -> *mut T { 0 as *mut T }
+const fn no_unsafe() { unsafe {} }
+
+const fn call_unsafe_const_fn() -> i32 {
+    unsafe { ret_i32_no_unsafe() }
+}
+const fn call_unsafe_generic_const_fn() -> *const String {
+    unsafe { ret_null_ptr_no_unsafe::<String>() }
+}
+const fn call_unsafe_generic_cell_const_fn()
+    -> *const Vec<std::cell::Cell<u32>>
+{
+    unsafe { ret_null_mut_ptr_no_unsafe::<Vec<std::cell::Cell<u32>>>() }
+}
+
+const unsafe fn call_unsafe_const_unsafe_fn() -> i32 {
+    unsafe { ret_i32_no_unsafe() }
+}
+const unsafe fn call_unsafe_generic_const_unsafe_fn() -> *const String {
+    unsafe { ret_null_ptr_no_unsafe::<String>() }
+}
+const unsafe fn call_unsafe_generic_cell_const_unsafe_fn()
+    -> *const Vec<std::cell::Cell<u32>>
+{
+    unsafe { ret_null_mut_ptr_no_unsafe::<Vec<std::cell::Cell<u32>>>() }
+}
+
+const unsafe fn call_unsafe_const_unsafe_fn_immediate() -> i32 {
+    ret_i32_no_unsafe()
+}
+const unsafe fn call_unsafe_generic_const_unsafe_fn_immediate() -> *const String {
+    ret_null_ptr_no_unsafe::<String>()
+}
+const unsafe fn call_unsafe_generic_cell_const_unsafe_fn_immediate()
+    -> *const Vec<std::cell::Cell<u32>>
+{
+    ret_null_mut_ptr_no_unsafe::<Vec<std::cell::Cell<u32>>>()
+}
+
+//------------------------------------------------------------------------------
+// NOT OK
+//------------------------------------------------------------------------------
+
+const fn bad_const_fn_deref_raw(x: *mut usize) -> &'static usize { unsafe { &*x } } //~ is unsafe
+//~^ dereferencing raw pointers in constant functions
+
+const unsafe fn bad_const_unsafe_deref_raw(x: *mut usize) -> usize { *x }
+//~^ dereferencing raw pointers in constant functions
+
+const unsafe fn bad_const_unsafe_deref_raw_ref(x: *mut usize) -> &'static usize { &*x }
+//~^ dereferencing raw pointers in constant functions
+
+fn main() {}
+
+const unsafe fn no_union() {
+    union Foo { x: (), y: () }
+    Foo { x: () }.y
+    //~^ unions in const fn
+}
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr
new file mode 100644
index 0000000..48c2606
--- /dev/null
+++ b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr
@@ -0,0 +1,44 @@
+error[E0658]: dereferencing raw pointers in constant functions is unstable (see issue #51911)
+  --> $DIR/min_const_fn_unsafe.rs:50:77
+   |
+LL | const fn bad_const_fn_deref_raw(x: *mut usize) -> &'static usize { unsafe { &*x } }
+   |                                                                             ^^^
+   |
+   = help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable
+
+error[E0658]: dereferencing raw pointers in constant functions is unstable (see issue #51911)
+  --> $DIR/min_const_fn_unsafe.rs:53:70
+   |
+LL | const unsafe fn bad_const_unsafe_deref_raw(x: *mut usize) -> usize { *x }
+   |                                                                      ^^
+   |
+   = help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable
+
+error[E0658]: dereferencing raw pointers in constant functions is unstable (see issue #51911)
+  --> $DIR/min_const_fn_unsafe.rs:56:83
+   |
+LL | const unsafe fn bad_const_unsafe_deref_raw_ref(x: *mut usize) -> &'static usize { &*x }
+   |                                                                                   ^^^
+   |
+   = help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable
+
+error[E0658]: unions in const fn are unstable (see issue #51909)
+  --> $DIR/min_const_fn_unsafe.rs:63:5
+   |
+LL |     Foo { x: () }.y
+   |     ^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_fn_union)] to the crate attributes to enable
+
+error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
+  --> $DIR/min_const_fn_unsafe.rs:50:77
+   |
+LL | const fn bad_const_fn_deref_raw(x: *mut usize) -> &'static usize { unsafe { &*x } }
+   |                                                                             ^^^ dereference of raw pointer
+   |
+   = note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+
+error: aborting due to 5 previous errors
+
+Some errors occurred: E0133, E0658.
+For more information about an error, try `rustc --explain E0133`.
diff --git a/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.rs b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.rs
new file mode 100644
index 0000000..7faba48
--- /dev/null
+++ b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.rs
@@ -0,0 +1,36 @@
+#![unstable(feature = "humans",
+            reason = "who ever let humans program computers,
+            we're apparently really bad at it",
+            issue = "0")]
+
+#![feature(rustc_const_unstable, const_fn, foo, foo2)]
+#![feature(staged_api)]
+
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_const_unstable(feature="foo")]
+const unsafe fn foo() -> u32 { 42 }
+
+#[stable(feature = "rust1", since = "1.0.0")]
+// can't call non-min_const_fn
+const unsafe fn bar() -> u32 { unsafe { foo() } } //~ ERROR can only call other `min_const_fn`
+
+#[unstable(feature = "rust1", issue="0")]
+const unsafe fn foo2() -> u32 { 42 }
+
+#[stable(feature = "rust1", since = "1.0.0")]
+// can't call non-min_const_fn
+const unsafe fn bar2() -> u32 { unsafe { foo2() } } //~ ERROR can only call other `min_const_fn`
+
+#[stable(feature = "rust1", since = "1.0.0")]
+// conformity is required, even with `const_fn` feature gate
+const unsafe fn bar3() -> u32 { (5f32 + 6f32) as u32 } //~ ERROR only int, `bool` and `char` op
+
+// check whether this function cannot be called even with the feature gate active
+#[unstable(feature = "foo2", issue="0")]
+const unsafe fn foo2_gated() -> u32 { 42 }
+
+#[stable(feature = "rust1", since = "1.0.0")]
+// can't call non-min_const_fn
+const unsafe fn bar2_gated() -> u32 { unsafe { foo2_gated() } } //~ ERROR can only call other
+
+fn main() {}
diff --git a/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr
new file mode 100644
index 0000000..5b2bee1
--- /dev/null
+++ b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr
@@ -0,0 +1,35 @@
+error[E0723]: can only call other `min_const_fn` within a `min_const_fn` (see issue #57563)
+  --> $DIR/min_const_unsafe_fn_libstd_stability.rs:15:41
+   |
+LL | const unsafe fn bar() -> u32 { unsafe { foo() } }
+   |                                         ^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: can only call other `min_const_fn` within a `min_const_fn` (see issue #57563)
+  --> $DIR/min_const_unsafe_fn_libstd_stability.rs:22:42
+   |
+LL | const unsafe fn bar2() -> u32 { unsafe { foo2() } }
+   |                                          ^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: only int, `bool` and `char` operations are stable in const fn (see issue #57563)
+  --> $DIR/min_const_unsafe_fn_libstd_stability.rs:26:33
+   |
+LL | const unsafe fn bar3() -> u32 { (5f32 + 6f32) as u32 }
+   |                                 ^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: can only call other `min_const_fn` within a `min_const_fn` (see issue #57563)
+  --> $DIR/min_const_unsafe_fn_libstd_stability.rs:34:48
+   |
+LL | const unsafe fn bar2_gated() -> u32 { unsafe { foo2_gated() } }
+   |                                                ^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0723`.
diff --git a/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.rs b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.rs
new file mode 100644
index 0000000..bc1d509
--- /dev/null
+++ b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.rs
@@ -0,0 +1,32 @@
+#![unstable(feature = "humans",
+            reason = "who ever let humans program computers,
+            we're apparently really bad at it",
+            issue = "0")]
+
+#![feature(rustc_const_unstable, const_fn, foo, foo2)]
+#![feature(staged_api)]
+
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_const_unstable(feature="foo")]
+const fn foo() -> u32 { 42 }
+
+#[stable(feature = "rust1", since = "1.0.0")]
+// can't call non-min_const_fn
+const unsafe fn bar() -> u32 { foo() } //~ ERROR can only call other `min_const_fn`
+
+#[unstable(feature = "rust1", issue="0")]
+const fn foo2() -> u32 { 42 }
+
+#[stable(feature = "rust1", since = "1.0.0")]
+// can't call non-min_const_fn
+const unsafe fn bar2() -> u32 { foo2() } //~ ERROR can only call other `min_const_fn`
+
+// check whether this function cannot be called even with the feature gate active
+#[unstable(feature = "foo2", issue="0")]
+const fn foo2_gated() -> u32 { 42 }
+
+#[stable(feature = "rust1", since = "1.0.0")]
+// can't call non-min_const_fn
+const unsafe fn bar2_gated() -> u32 { foo2_gated() } //~ ERROR can only call other `min_const_fn`
+
+fn main() {}
diff --git a/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.stderr b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.stderr
new file mode 100644
index 0000000..f7f630c
--- /dev/null
+++ b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.stderr
@@ -0,0 +1,27 @@
+error[E0723]: can only call other `min_const_fn` within a `min_const_fn` (see issue #57563)
+  --> $DIR/min_const_unsafe_fn_libstd_stability2.rs:15:32
+   |
+LL | const unsafe fn bar() -> u32 { foo() }
+   |                                ^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: can only call other `min_const_fn` within a `min_const_fn` (see issue #57563)
+  --> $DIR/min_const_unsafe_fn_libstd_stability2.rs:22:33
+   |
+LL | const unsafe fn bar2() -> u32 { foo2() }
+   |                                 ^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: can only call other `min_const_fn` within a `min_const_fn` (see issue #57563)
+  --> $DIR/min_const_unsafe_fn_libstd_stability2.rs:30:39
+   |
+LL | const unsafe fn bar2_gated() -> u32 { foo2_gated() }
+   |                                       ^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0723`.
diff --git a/src/test/ui/consts/min_const_fn/mutable_borrow.rs b/src/test/ui/consts/min_const_fn/mutable_borrow.rs
new file mode 100644
index 0000000..89acfea
--- /dev/null
+++ b/src/test/ui/consts/min_const_fn/mutable_borrow.rs
@@ -0,0 +1,17 @@
+const fn mutable_ref_in_const() -> u8 {
+    let mut a = 0;
+    let b = &mut a; //~ ERROR mutable references in const fn
+    *b
+}
+
+struct X;
+
+impl X {
+    const fn inherent_mutable_ref_in_const() -> u8 {
+        let mut a = 0;
+        let b = &mut a; //~ ERROR mutable references in const fn
+        *b
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/consts/min_const_fn/mutable_borrow.stderr b/src/test/ui/consts/min_const_fn/mutable_borrow.stderr
new file mode 100644
index 0000000..a2d67a0
--- /dev/null
+++ b/src/test/ui/consts/min_const_fn/mutable_borrow.stderr
@@ -0,0 +1,19 @@
+error[E0723]: mutable references in const fn are unstable (see issue #57563)
+  --> $DIR/mutable_borrow.rs:3:9
+   |
+LL |     let b = &mut a;
+   |         ^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: mutable references in const fn are unstable (see issue #57563)
+  --> $DIR/mutable_borrow.rs:12:13
+   |
+LL |         let b = &mut a;
+   |             ^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0723`.
diff --git a/src/test/ui/consts/min_const_fn/promotion.nll.stderr b/src/test/ui/consts/min_const_fn/promotion.nll.stderr
new file mode 100644
index 0000000..550423c
--- /dev/null
+++ b/src/test/ui/consts/min_const_fn/promotion.nll.stderr
@@ -0,0 +1,68 @@
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promotion.rs:11:27
+   |
+LL |     let x: &'static () = &foo1();
+   |            -----------    ^^^^^^ creates a temporary which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+...
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promotion.rs:12:28
+   |
+LL |     let y: &'static i32 = &foo2(42);
+   |            ------------    ^^^^^^^^ creates a temporary which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+...
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promotion.rs:13:28
+   |
+LL |     let z: &'static i32 = &foo3();
+   |            ------------    ^^^^^^ creates a temporary which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+...
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promotion.rs:14:34
+   |
+LL |     let a: &'static Cell<i32> = &foo4();
+   |            ------------------    ^^^^^^ creates a temporary which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+...
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promotion.rs:15:42
+   |
+LL |     let a: &'static Option<Cell<i32>> = &foo5();
+   |            --------------------------    ^^^^^^ creates a temporary which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+LL |     let a: &'static Option<Cell<i32>> = &foo6();
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promotion.rs:16:42
+   |
+LL |     let a: &'static Option<Cell<i32>> = &foo6();
+   |            --------------------------    ^^^^^^ creates a temporary which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/src/test/ui/consts/min_const_fn/promotion.rs b/src/test/ui/consts/min_const_fn/promotion.rs
new file mode 100644
index 0000000..969bf40
--- /dev/null
+++ b/src/test/ui/consts/min_const_fn/promotion.rs
@@ -0,0 +1,17 @@
+use std::cell::Cell;
+
+const fn foo1() {}
+const fn foo2(x: i32) -> i32 { x }
+const fn foo3() -> i32 { 42 }
+const fn foo4() -> Cell<i32> { Cell::new(42) }
+const fn foo5() -> Option<Cell<i32>> { Some(Cell::new(42)) }
+const fn foo6() -> Option<Cell<i32>> { None }
+
+fn main() {
+    let x: &'static () = &foo1(); //~ ERROR does not live long enough
+    let y: &'static i32 = &foo2(42); //~ ERROR does not live long enough
+    let z: &'static i32 = &foo3(); //~ ERROR does not live long enough
+    let a: &'static Cell<i32> = &foo4();  //~ ERROR does not live long enough
+    let a: &'static Option<Cell<i32>> = &foo5(); //~ ERROR does not live long enough
+    let a: &'static Option<Cell<i32>> = &foo6(); //~ ERROR does not live long enough
+}
diff --git a/src/test/ui/consts/min_const_fn/promotion.stderr b/src/test/ui/consts/min_const_fn/promotion.stderr
new file mode 100644
index 0000000..92d60f0
--- /dev/null
+++ b/src/test/ui/consts/min_const_fn/promotion.stderr
@@ -0,0 +1,68 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/promotion.rs:11:27
+   |
+LL |     let x: &'static () = &foo1();
+   |                           ^^^^^^ temporary value does not live long enough
+...
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/promotion.rs:12:28
+   |
+LL |     let y: &'static i32 = &foo2(42);
+   |                            ^^^^^^^^ temporary value does not live long enough
+...
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/promotion.rs:13:28
+   |
+LL |     let z: &'static i32 = &foo3();
+   |                            ^^^^^^ temporary value does not live long enough
+...
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/promotion.rs:14:34
+   |
+LL |     let a: &'static Cell<i32> = &foo4();
+   |                                  ^^^^^^ temporary value does not live long enough
+...
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/promotion.rs:15:42
+   |
+LL |     let a: &'static Option<Cell<i32>> = &foo5();
+   |                                          ^^^^^^ temporary value does not live long enough
+LL |     let a: &'static Option<Cell<i32>> = &foo6();
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/promotion.rs:16:42
+   |
+LL |     let a: &'static Option<Cell<i32>> = &foo6();
+   |                                          ^^^^^^ temporary value does not live long enough
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/consts/miri_unleashed/assoc_const.rs b/src/test/ui/consts/miri_unleashed/assoc_const.rs
new file mode 100644
index 0000000..b895966
--- /dev/null
+++ b/src/test/ui/consts/miri_unleashed/assoc_const.rs
@@ -0,0 +1,30 @@
+// compile-flags: -Zunleash-the-miri-inside-of-you
+#![allow(const_err)]
+
+// a test demonstrating why we do need to run static const qualification on associated constants
+// instead of just checking the final constant
+
+trait Foo<T> {
+    const X: T;
+}
+
+trait Bar<T, U: Foo<T>> {
+    const F: u32 = (U::X, 42).1; //~ WARN skipping const checks
+}
+
+impl Foo<u32> for () {
+    const X: u32 = 42;
+}
+impl Foo<Vec<u32>> for String {
+    const X: Vec<u32> = Vec::new();
+}
+
+impl Bar<u32, ()> for () {}
+impl Bar<Vec<u32>, String> for String {}
+
+fn main() {
+    // this is fine, but would have been forbidden by the static checks on `F`
+    let x = <() as Bar<u32, ()>>::F;
+    // this test only causes errors due to the line below, so post-monomorphization
+    let y = <String as Bar<Vec<u32>, String>>::F; //~ ERROR erroneous constant
+}
diff --git a/src/test/ui/consts/miri_unleashed/assoc_const.stderr b/src/test/ui/consts/miri_unleashed/assoc_const.stderr
new file mode 100644
index 0000000..e814303
--- /dev/null
+++ b/src/test/ui/consts/miri_unleashed/assoc_const.stderr
@@ -0,0 +1,15 @@
+warning: skipping const checks
+  --> $DIR/assoc_const.rs:12:31
+   |
+LL |     const F: u32 = (U::X, 42).1;
+   |                               ^
+
+error[E0080]: erroneous constant used
+  --> $DIR/assoc_const.rs:29:13
+   |
+LL |     let y = <String as Bar<Vec<u32>, String>>::F;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/miri_unleashed/assoc_const_2.rs b/src/test/ui/consts/miri_unleashed/assoc_const_2.rs
new file mode 100644
index 0000000..c87b638
--- /dev/null
+++ b/src/test/ui/consts/miri_unleashed/assoc_const_2.rs
@@ -0,0 +1,28 @@
+#![allow(const_err)]
+
+// a test demonstrating that const qualification cannot prevent monomorphization time errors
+
+trait Foo {
+    const X: u32;
+}
+
+trait Bar<U: Foo> {
+    const F: u32 = 100 / U::X;
+}
+
+impl Foo for () {
+    const X: u32 = 42;
+}
+
+impl Foo for String {
+    const X: u32 = 0;
+}
+
+impl Bar<()> for () {}
+impl Bar<String> for String {}
+
+fn main() {
+    let x = <() as Bar<()>>::F;
+    // this test only causes errors due to the line below, so post-monomorphization
+    let y = <String as Bar<String>>::F; //~ ERROR erroneous constant
+}
diff --git a/src/test/ui/consts/miri_unleashed/assoc_const_2.stderr b/src/test/ui/consts/miri_unleashed/assoc_const_2.stderr
new file mode 100644
index 0000000..dbfe1d9
--- /dev/null
+++ b/src/test/ui/consts/miri_unleashed/assoc_const_2.stderr
@@ -0,0 +1,9 @@
+error[E0080]: erroneous constant used
+  --> $DIR/assoc_const_2.rs:27:13
+   |
+LL |     let y = <String as Bar<String>>::F;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.rs b/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.rs
new file mode 100644
index 0000000..5fb9253
--- /dev/null
+++ b/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.rs
@@ -0,0 +1,27 @@
+#![allow(const_err)]
+
+// a test demonstrating why we do need to run static const qualification on associated constants
+// instead of just checking the final constant
+
+trait Foo<T> {
+    const X: T;
+}
+
+trait Bar<T, U: Foo<T>> {
+    const F: u32 = (U::X, 42).1; //~ ERROR destructors cannot be evaluated at compile-time
+}
+
+impl Foo<u32> for () {
+    const X: u32 = 42;
+}
+impl Foo<Vec<u32>> for String {
+    const X: Vec<u32> = Vec::new(); //~ ERROR not yet stable as a const fn
+}
+
+impl Bar<u32, ()> for () {}
+impl Bar<Vec<u32>, String> for String {}
+
+fn main() {
+    let x = <() as Bar<u32, ()>>::F;
+    let y = <String as Bar<Vec<u32>, String>>::F;
+}
diff --git a/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.stderr b/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.stderr
new file mode 100644
index 0000000..7ede44c
--- /dev/null
+++ b/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.stderr
@@ -0,0 +1,17 @@
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/feature-gate-unleash_the_miri_inside_of_you.rs:11:20
+   |
+LL |     const F: u32 = (U::X, 42).1;
+   |                    ^^^^^^^^^^ constants cannot evaluate destructors
+
+error: `std::vec::Vec::<T>::new` is not yet stable as a const fn
+  --> $DIR/feature-gate-unleash_the_miri_inside_of_you.rs:18:25
+   |
+LL |     const X: Vec<u32> = Vec::new();
+   |                         ^^^^^^^^^^
+   |
+   = help: add `#![feature(const_vec_new)]` to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0493`.
diff --git a/src/test/ui/consts/partial_qualif.rs b/src/test/ui/consts/partial_qualif.rs
new file mode 100644
index 0000000..32c68e6
--- /dev/null
+++ b/src/test/ui/consts/partial_qualif.rs
@@ -0,0 +1,9 @@
+use std::cell::Cell;
+
+const FOO: &(Cell<usize>, bool) = {
+    let mut a = (Cell::new(0), false);
+    a.1 = true; // sets `qualif(a)` to `qualif(a) | qualif(true)`
+    &{a} //~ ERROR cannot borrow a constant which may contain interior mutability
+};
+
+fn main() {}
diff --git a/src/test/ui/consts/partial_qualif.stderr b/src/test/ui/consts/partial_qualif.stderr
new file mode 100644
index 0000000..221e449
--- /dev/null
+++ b/src/test/ui/consts/partial_qualif.stderr
@@ -0,0 +1,9 @@
+error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
+  --> $DIR/partial_qualif.rs:6:5
+   |
+LL |     &{a}
+   |     ^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0492`.
diff --git a/src/test/ui/consts/projection_qualif.rs b/src/test/ui/consts/projection_qualif.rs
new file mode 100644
index 0000000..dedb7db
--- /dev/null
+++ b/src/test/ui/consts/projection_qualif.rs
@@ -0,0 +1,13 @@
+use std::cell::Cell;
+
+const FOO: &u32 = {
+    let mut a = 42;
+    {
+        let b: *mut u32 = &mut a; //~ ERROR may only refer to immutable values
+        unsafe { *b = 5; } //~ ERROR dereferencing raw pointers in constants
+        //~^ contains unimplemented expression
+    }
+    &{a}
+};
+
+fn main() {}
diff --git a/src/test/ui/consts/projection_qualif.stderr b/src/test/ui/consts/projection_qualif.stderr
new file mode 100644
index 0000000..45679e3
--- /dev/null
+++ b/src/test/ui/consts/projection_qualif.stderr
@@ -0,0 +1,24 @@
+error[E0017]: references in constants may only refer to immutable values
+  --> $DIR/projection_qualif.rs:6:27
+   |
+LL |         let b: *mut u32 = &mut a;
+   |                           ^^^^^^ constants require immutable values
+
+error[E0019]: constant contains unimplemented expression type
+  --> $DIR/projection_qualif.rs:7:18
+   |
+LL |         unsafe { *b = 5; }
+   |                  ^^^^^^
+
+error[E0658]: dereferencing raw pointers in constants is unstable (see issue #51911)
+  --> $DIR/projection_qualif.rs:7:18
+   |
+LL |         unsafe { *b = 5; }
+   |                  ^^^^^^
+   |
+   = help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0017, E0019, E0658.
+For more information about an error, try `rustc --explain E0017`.
diff --git a/src/test/ui/consts/promote_const_let.nll.stderr b/src/test/ui/consts/promote_const_let.nll.stderr
new file mode 100644
index 0000000..a0af949
--- /dev/null
+++ b/src/test/ui/consts/promote_const_let.nll.stderr
@@ -0,0 +1,29 @@
+error[E0597]: `y` does not live long enough
+  --> $DIR/promote_const_let.rs:4:9
+   |
+LL |     let x: &'static u32 = {
+   |            ------------ type annotation requires that `y` is borrowed for `'static`
+LL |         let y = 42;
+LL |         &y
+   |         ^^ borrowed value does not live long enough
+LL |     };
+   |     - `y` dropped here while still borrowed
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promote_const_let.rs:6:28
+   |
+LL |       let x: &'static u32 = &{
+   |  ____________------------____^
+   | |            |
+   | |            type annotation requires that borrow lasts for `'static`
+LL | |         let y = 42;
+LL | |         y
+LL | |     };
+   | |_____^ creates a temporary which is freed while still in use
+LL |   }
+   |   - temporary value is freed at the end of this statement
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0597, E0716.
+For more information about an error, try `rustc --explain E0597`.
diff --git a/src/test/ui/consts/promote_const_let.rs b/src/test/ui/consts/promote_const_let.rs
new file mode 100644
index 0000000..a8a6d4d
--- /dev/null
+++ b/src/test/ui/consts/promote_const_let.rs
@@ -0,0 +1,10 @@
+fn main() {
+    let x: &'static u32 = {
+        let y = 42;
+        &y //~ ERROR does not live long enough
+    };
+    let x: &'static u32 = &{ //~ ERROR does not live long enough
+        let y = 42;
+        y
+    };
+}
diff --git a/src/test/ui/consts/promote_const_let.stderr b/src/test/ui/consts/promote_const_let.stderr
new file mode 100644
index 0000000..c429577
--- /dev/null
+++ b/src/test/ui/consts/promote_const_let.stderr
@@ -0,0 +1,27 @@
+error[E0597]: `y` does not live long enough
+  --> $DIR/promote_const_let.rs:4:10
+   |
+LL |         &y
+   |          ^ borrowed value does not live long enough
+LL |     };
+   |     - borrowed value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/promote_const_let.rs:6:28
+   |
+LL |       let x: &'static u32 = &{
+   |  ____________________________^
+LL | |         let y = 42;
+LL | |         y
+LL | |     };
+   | |_____^ temporary value does not live long enough
+LL |   }
+   |   - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/consts/promote_evaluation_unused_result.rs b/src/test/ui/consts/promote_evaluation_unused_result.rs
new file mode 100644
index 0000000..d199e34
--- /dev/null
+++ b/src/test/ui/consts/promote_evaluation_unused_result.rs
@@ -0,0 +1,8 @@
+//compile-pass
+
+#![feature(nll)]
+
+fn main() {
+
+    let _: &'static usize = &(loop {}, 1).1;
+}
diff --git a/src/test/ui/consts/promote_fn_calls.rs b/src/test/ui/consts/promote_fn_calls.rs
new file mode 100644
index 0000000..045322d
--- /dev/null
+++ b/src/test/ui/consts/promote_fn_calls.rs
@@ -0,0 +1,13 @@
+// compile-pass
+// aux-build:promotable_const_fn_lib.rs
+
+#![feature(nll)]
+
+extern crate promotable_const_fn_lib;
+
+use promotable_const_fn_lib::{foo, Foo};
+
+fn main() {
+    let x: &'static usize = &foo();
+    let x: &'static usize = &Foo::foo();
+}
diff --git a/src/test/ui/consts/promote_fn_calls_std.rs b/src/test/ui/consts/promote_fn_calls_std.rs
new file mode 100644
index 0000000..0350708
--- /dev/null
+++ b/src/test/ui/consts/promote_fn_calls_std.rs
@@ -0,0 +1,30 @@
+// compile-pass
+
+#![feature(nll)]
+
+fn main() {
+    let x: &'static u8 = &u8::max_value();
+    let x: &'static u16 = &u16::max_value();
+    let x: &'static u32 = &u32::max_value();
+    let x: &'static u64 = &u64::max_value();
+    let x: &'static u128 = &u128::max_value();
+    let x: &'static usize = &usize::max_value();
+    let x: &'static u8 = &u8::min_value();
+    let x: &'static u16 = &u16::min_value();
+    let x: &'static u32 = &u32::min_value();
+    let x: &'static u64 = &u64::min_value();
+    let x: &'static u128 = &u128::min_value();
+    let x: &'static usize = &usize::min_value();
+    let x: &'static i8 = &i8::max_value();
+    let x: &'static i16 = &i16::max_value();
+    let x: &'static i32 = &i32::max_value();
+    let x: &'static i64 = &i64::max_value();
+    let x: &'static i128 = &i128::max_value();
+    let x: &'static isize = &isize::max_value();
+    let x: &'static i8 = &i8::min_value();
+    let x: &'static i16 = &i16::min_value();
+    let x: &'static i32 = &i32::min_value();
+    let x: &'static i64 = &i64::min_value();
+    let x: &'static i128 = &i128::min_value();
+    let x: &'static isize = &isize::min_value();
+}
diff --git a/src/test/ui/consts/promoted-validation-55454.rs b/src/test/ui/consts/promoted-validation-55454.rs
new file mode 100644
index 0000000..5e193b1
--- /dev/null
+++ b/src/test/ui/consts/promoted-validation-55454.rs
@@ -0,0 +1,9 @@
+// https://github.com/rust-lang/rust/issues/55454
+// compile-pass
+
+#[derive(PartialEq)]
+struct This<T>(T);
+
+fn main() {
+    This(Some(&1)) == This(Some(&1));
+}
diff --git a/src/test/ui/consts/promoted_regression.rs b/src/test/ui/consts/promoted_regression.rs
new file mode 100644
index 0000000..68b9a20
--- /dev/null
+++ b/src/test/ui/consts/promoted_regression.rs
@@ -0,0 +1,9 @@
+// compile-pass
+
+fn main() {
+    let _ = &[("", ""); 3];
+}
+
+const FOO: &[(&str, &str)] = &[("", ""); 3];
+const BAR: &[(&str, &str); 5] = &[("", ""); 5];
+const BAA: &[[&str; 12]; 11] = &[[""; 12]; 11];
diff --git a/src/test/ui/consts/qualif_overwrite.rs b/src/test/ui/consts/qualif_overwrite.rs
new file mode 100644
index 0000000..430eea3
--- /dev/null
+++ b/src/test/ui/consts/qualif_overwrite.rs
@@ -0,0 +1,13 @@
+use std::cell::Cell;
+
+// this is overly conservative. The reset to `None` should clear `a` of all qualifications
+// while we could fix this, it would be inconsistent with `qualif_overwrite_2.rs`.
+// We can fix this properly in the future by allowing constants that do not depend on generics
+// to be checked by an analysis on the final value instead of looking at the body.
+const FOO: &Option<Cell<usize>> = {
+    let mut a = Some(Cell::new(0));
+    a = None; // sets `qualif(a)` to `qualif(a) | qualif(None)`
+    &{a} //~ ERROR cannot borrow a constant which may contain interior mutability
+};
+
+fn main() {}
diff --git a/src/test/ui/consts/qualif_overwrite.stderr b/src/test/ui/consts/qualif_overwrite.stderr
new file mode 100644
index 0000000..fbaae71
--- /dev/null
+++ b/src/test/ui/consts/qualif_overwrite.stderr
@@ -0,0 +1,9 @@
+error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
+  --> $DIR/qualif_overwrite.rs:10:5
+   |
+LL |     &{a}
+   |     ^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0492`.
diff --git a/src/test/ui/consts/qualif_overwrite_2.rs b/src/test/ui/consts/qualif_overwrite_2.rs
new file mode 100644
index 0000000..fa79b5c
--- /dev/null
+++ b/src/test/ui/consts/qualif_overwrite_2.rs
@@ -0,0 +1,11 @@
+use std::cell::Cell;
+
+// const qualification is not smart enough to know about fields and always assumes that there might
+// be other fields that caused the qualification
+const FOO: &Option<Cell<usize>> = {
+    let mut a = (Some(Cell::new(0)),);
+    a.0 = None; // sets `qualif(a)` to `qualif(a) | qualif(None)`
+    &{a.0} //~ ERROR cannot borrow a constant which may contain interior mutability
+};
+
+fn main() {}
diff --git a/src/test/ui/consts/qualif_overwrite_2.stderr b/src/test/ui/consts/qualif_overwrite_2.stderr
new file mode 100644
index 0000000..a393c4e
--- /dev/null
+++ b/src/test/ui/consts/qualif_overwrite_2.stderr
@@ -0,0 +1,9 @@
+error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
+  --> $DIR/qualif_overwrite_2.rs:8:5
+   |
+LL |     &{a.0}
+   |     ^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0492`.
diff --git a/src/test/ui/consts/single_variant_match_ice.rs b/src/test/ui/consts/single_variant_match_ice.rs
new file mode 100644
index 0000000..79dde3c
--- /dev/null
+++ b/src/test/ui/consts/single_variant_match_ice.rs
@@ -0,0 +1,23 @@
+enum Foo {
+    Prob,
+}
+
+const FOO: u32 = match Foo::Prob {
+    Foo::Prob => 42, //~ ERROR unimplemented expression type
+};
+
+const BAR: u32 = match Foo::Prob {
+    x => 42, //~ ERROR unimplemented expression type
+};
+
+impl Foo {
+    pub const fn as_val(&self) -> u8 {
+        use self::Foo::*;
+
+        match *self {
+            Prob => 0x1, //~ ERROR `if`, `match`, `&&` and `||` are not stable in const fn
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/consts/single_variant_match_ice.stderr b/src/test/ui/consts/single_variant_match_ice.stderr
new file mode 100644
index 0000000..bc80de4
--- /dev/null
+++ b/src/test/ui/consts/single_variant_match_ice.stderr
@@ -0,0 +1,24 @@
+error[E0019]: constant contains unimplemented expression type
+  --> $DIR/single_variant_match_ice.rs:6:5
+   |
+LL |     Foo::Prob => 42,
+   |     ^^^^^^^^^
+
+error[E0019]: constant contains unimplemented expression type
+  --> $DIR/single_variant_match_ice.rs:10:5
+   |
+LL |     x => 42,
+   |     ^
+
+error[E0723]: `if`, `match`, `&&` and `||` are not stable in const fn (see issue #57563)
+  --> $DIR/single_variant_match_ice.rs:18:13
+   |
+LL |             Prob => 0x1,
+   |             ^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0019, E0723.
+For more information about an error, try `rustc --explain E0019`.
diff --git a/src/test/ui/consts/static_mut_containing_mut_ref.rs b/src/test/ui/consts/static_mut_containing_mut_ref.rs
new file mode 100644
index 0000000..27e1a11
--- /dev/null
+++ b/src/test/ui/consts/static_mut_containing_mut_ref.rs
@@ -0,0 +1,7 @@
+// compile-pass
+
+static mut STDERR_BUFFER_SPACE: [u8; 42] = [0u8; 42];
+
+pub static mut STDERR_BUFFER: *mut [u8] = unsafe { &mut STDERR_BUFFER_SPACE };
+
+fn main() {}
diff --git a/src/test/ui/consts/static_mut_containing_mut_ref2.rs b/src/test/ui/consts/static_mut_containing_mut_ref2.rs
new file mode 100644
index 0000000..ef378fa
--- /dev/null
+++ b/src/test/ui/consts/static_mut_containing_mut_ref2.rs
@@ -0,0 +1,7 @@
+static mut STDERR_BUFFER_SPACE: u8 = 0;
+
+pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; };
+//~^ ERROR references in statics may only refer to immutable values
+//~| ERROR static contains unimplemented expression type
+
+fn main() {}
diff --git a/src/test/ui/consts/static_mut_containing_mut_ref2.stderr b/src/test/ui/consts/static_mut_containing_mut_ref2.stderr
new file mode 100644
index 0000000..7218657
--- /dev/null
+++ b/src/test/ui/consts/static_mut_containing_mut_ref2.stderr
@@ -0,0 +1,16 @@
+error[E0017]: references in statics may only refer to immutable values
+  --> $DIR/static_mut_containing_mut_ref2.rs:3:46
+   |
+LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; };
+   |                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^ statics require immutable values
+
+error[E0019]: static contains unimplemented expression type
+  --> $DIR/static_mut_containing_mut_ref2.rs:3:45
+   |
+LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; };
+   |                                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0017, E0019.
+For more information about an error, try `rustc --explain E0017`.
diff --git a/src/test/ui/consts/static_mut_containing_mut_ref3.rs b/src/test/ui/consts/static_mut_containing_mut_ref3.rs
new file mode 100644
index 0000000..c24c7e2
--- /dev/null
+++ b/src/test/ui/consts/static_mut_containing_mut_ref3.rs
@@ -0,0 +1,6 @@
+static mut FOO: (u8, u8) = (42, 43);
+
+static mut BAR: () = unsafe { FOO.0 = 99; };
+//~^ ERROR could not evaluate static initializer
+
+fn main() {}
diff --git a/src/test/ui/consts/static_mut_containing_mut_ref3.stderr b/src/test/ui/consts/static_mut_containing_mut_ref3.stderr
new file mode 100644
index 0000000..e88e49b
--- /dev/null
+++ b/src/test/ui/consts/static_mut_containing_mut_ref3.stderr
@@ -0,0 +1,9 @@
+error[E0080]: could not evaluate static initializer
+  --> $DIR/static_mut_containing_mut_ref3.rs:3:31
+   |
+LL | static mut BAR: () = unsafe { FOO.0 = 99; };
+   |                               ^^^^^^^^^^ tried to modify a static's initial value from another static's initializer
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/std/cell.rs b/src/test/ui/consts/std/cell.rs
new file mode 100644
index 0000000..cf6c0f2
--- /dev/null
+++ b/src/test/ui/consts/std/cell.rs
@@ -0,0 +1,30 @@
+use std::cell::*;
+
+// not ok, because this would create a silent constant with interior mutability.
+// the rules could be relaxed in the future
+static FOO: Wrap<*mut u32> = Wrap(Cell::new(42).as_ptr());
+//~^ ERROR cannot borrow a constant which may contain interior mutability
+
+static FOO3: Wrap<Cell<u32>> = Wrap(Cell::new(42));
+// ok
+static FOO4: Wrap<*mut u32> = Wrap(FOO3.0.as_ptr());
+
+// not ok, because the `as_ptr` call takes a reference to a type with interior mutability
+// which is not allowed in constants
+const FOO2: *mut u32 = Cell::new(42).as_ptr();
+//~^ ERROR cannot borrow a constant which may contain interior mutability
+
+struct IMSafeTrustMe(UnsafeCell<u32>);
+unsafe impl Send for IMSafeTrustMe {}
+unsafe impl Sync for IMSafeTrustMe {}
+
+static BAR: IMSafeTrustMe = IMSafeTrustMe(UnsafeCell::new(5));
+
+
+struct Wrap<T>(T);
+unsafe impl<T> Send for Wrap<T> {}
+unsafe impl<T> Sync for Wrap<T> {}
+
+static BAR_PTR: Wrap<*mut u32> = Wrap(BAR.0.get());
+
+fn main() {}
diff --git a/src/test/ui/consts/std/cell.stderr b/src/test/ui/consts/std/cell.stderr
new file mode 100644
index 0000000..f75aadf
--- /dev/null
+++ b/src/test/ui/consts/std/cell.stderr
@@ -0,0 +1,15 @@
+error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
+  --> $DIR/cell.rs:5:35
+   |
+LL | static FOO: Wrap<*mut u32> = Wrap(Cell::new(42).as_ptr());
+   |                                   ^^^^^^^^^^^^^
+
+error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
+  --> $DIR/cell.rs:14:24
+   |
+LL | const FOO2: *mut u32 = Cell::new(42).as_ptr();
+   |                        ^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0492`.
diff --git a/src/test/ui/consts/std/char.rs b/src/test/ui/consts/std/char.rs
new file mode 100644
index 0000000..fe79059
--- /dev/null
+++ b/src/test/ui/consts/std/char.rs
@@ -0,0 +1,9 @@
+// run-pass
+
+static X: bool = 'a'.is_ascii();
+static Y: bool = 'ä'.is_ascii();
+
+fn main() {
+    assert!(X);
+    assert!(!Y);
+}
diff --git a/src/test/ui/consts/std/iter.rs b/src/test/ui/consts/std/iter.rs
new file mode 100644
index 0000000..e9af781
--- /dev/null
+++ b/src/test/ui/consts/std/iter.rs
@@ -0,0 +1,9 @@
+// run-pass
+
+const I: std::iter::Empty<u32> = std::iter::empty();
+
+fn main() {
+    for i in I {
+        panic!("magical value creation: {}", i);
+    }
+}
diff --git a/src/test/ui/consts/std/slice.rs b/src/test/ui/consts/std/slice.rs
new file mode 100644
index 0000000..ad38105
--- /dev/null
+++ b/src/test/ui/consts/std/slice.rs
@@ -0,0 +1,10 @@
+// compile-pass
+
+struct Wrap<T>(T);
+unsafe impl<T> Send for Wrap<T> {}
+unsafe impl<T> Sync for Wrap<T> {}
+
+static FOO: Wrap<*const u32> = Wrap([42, 44, 46].as_ptr());
+static BAR: Wrap<*const u8> = Wrap("hello".as_ptr());
+
+fn main() {}
diff --git a/src/test/ui/consts/union_constant.rs b/src/test/ui/consts/union_constant.rs
new file mode 100644
index 0000000..0740149
--- /dev/null
+++ b/src/test/ui/consts/union_constant.rs
@@ -0,0 +1,11 @@
+// compile-pass
+
+union Uninit {
+    _never_use: *const u8,
+    uninit: (),
+}
+
+const UNINIT: Uninit = Uninit { uninit: () };
+
+fn main() {}
+
diff --git a/src/test/ui/consts/validate_never_arrays.rs b/src/test/ui/consts/validate_never_arrays.rs
new file mode 100644
index 0000000..9610b7b
--- /dev/null
+++ b/src/test/ui/consts/validate_never_arrays.rs
@@ -0,0 +1,5 @@
+#![feature(const_raw_ptr_deref, never_type)]
+
+const FOO: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) }; //~ ERROR undefined behavior
+
+fn main() {}
diff --git a/src/test/ui/consts/validate_never_arrays.stderr b/src/test/ui/consts/validate_never_arrays.stderr
new file mode 100644
index 0000000..7a7d816
--- /dev/null
+++ b/src/test/ui/consts/validate_never_arrays.stderr
@@ -0,0 +1,11 @@
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/validate_never_arrays.rs:3:1
+   |
+LL | const FOO: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type at .<deref>
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/conversion-methods.rs b/src/test/ui/conversion-methods.rs
new file mode 100644
index 0000000..46c2e51
--- /dev/null
+++ b/src/test/ui/conversion-methods.rs
@@ -0,0 +1,13 @@
+use std::path::{Path, PathBuf};
+
+
+fn main() {
+    let _tis_an_instants_play: String = "'Tis a fond Ambush—"; //~ ERROR mismatched types
+    let _just_to_make_bliss: PathBuf = Path::new("/ern/her/own/surprise");
+    //~^ ERROR mismatched types
+
+    let _but_should_the_play: String = 2; // Perhaps surprisingly, we suggest .to_string() here
+    //~^ ERROR mismatched types
+
+    let _prove_piercing_earnest: Vec<usize> = &[1, 2, 3]; //~ ERROR mismatched types
+}
diff --git a/src/test/ui/conversion-methods.stderr b/src/test/ui/conversion-methods.stderr
new file mode 100644
index 0000000..b9662e7
--- /dev/null
+++ b/src/test/ui/conversion-methods.stderr
@@ -0,0 +1,51 @@
+error[E0308]: mismatched types
+  --> $DIR/conversion-methods.rs:5:41
+   |
+LL |     let _tis_an_instants_play: String = "'Tis a fond Ambush—";
+   |                                         ^^^^^^^^^^^^^^^^^^^^^
+   |                                         |
+   |                                         expected struct `std::string::String`, found reference
+   |                                         help: try using a conversion method: `"'Tis a fond Ambush—".to_string()`
+   |
+   = note: expected type `std::string::String`
+              found type `&'static str`
+
+error[E0308]: mismatched types
+  --> $DIR/conversion-methods.rs:6:40
+   |
+LL |     let _just_to_make_bliss: PathBuf = Path::new("/ern/her/own/surprise");
+   |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                        |
+   |                                        expected struct `std::path::PathBuf`, found reference
+   |                                        help: try using a conversion method: `Path::new("/ern/her/own/surprise").to_path_buf()`
+   |
+   = note: expected type `std::path::PathBuf`
+              found type `&std::path::Path`
+
+error[E0308]: mismatched types
+  --> $DIR/conversion-methods.rs:9:40
+   |
+LL |     let _but_should_the_play: String = 2; // Perhaps surprisingly, we suggest .to_string() here
+   |                                        ^
+   |                                        |
+   |                                        expected struct `std::string::String`, found integer
+   |                                        help: try using a conversion method: `2.to_string()`
+   |
+   = note: expected type `std::string::String`
+              found type `{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/conversion-methods.rs:12:47
+   |
+LL |     let _prove_piercing_earnest: Vec<usize> = &[1, 2, 3];
+   |                                               ^^^^^^^^^^
+   |                                               |
+   |                                               expected struct `std::vec::Vec`, found reference
+   |                                               help: try using a conversion method: `&[1, 2, 3].to_vec()`
+   |
+   = note: expected type `std::vec::Vec<usize>`
+              found type `&[{integer}; 3]`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/copy-a-resource.rs b/src/test/ui/copy-a-resource.rs
new file mode 100644
index 0000000..55f2dd4
--- /dev/null
+++ b/src/test/ui/copy-a-resource.rs
@@ -0,0 +1,21 @@
+#[derive(Debug)]
+struct Foo {
+  i: isize,
+}
+
+impl Drop for Foo {
+    fn drop(&mut self) {}
+}
+
+fn foo(i:isize) -> Foo {
+    Foo {
+        i: i
+    }
+}
+
+fn main() {
+    let x = foo(10);
+    let _y = x.clone();
+    //~^ ERROR no method named `clone` found
+    println!("{:?}", x);
+}
diff --git a/src/test/ui/copy-a-resource.stderr b/src/test/ui/copy-a-resource.stderr
new file mode 100644
index 0000000..cceb9e3
--- /dev/null
+++ b/src/test/ui/copy-a-resource.stderr
@@ -0,0 +1,16 @@
+error[E0599]: no method named `clone` found for type `Foo` in the current scope
+  --> $DIR/copy-a-resource.rs:18:16
+   |
+LL | struct Foo {
+   | ---------- method `clone` not found for this
+...
+LL |     let _y = x.clone();
+   |                ^^^^^
+   |
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following trait defines an item `clone`, perhaps you need to implement it:
+           candidate #1: `std::clone::Clone`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/crate-in-paths.rs b/src/test/ui/crate-in-paths.rs
new file mode 100644
index 0000000..50ed50c
--- /dev/null
+++ b/src/test/ui/crate-in-paths.rs
@@ -0,0 +1,12 @@
+// edition:2018
+
+#![feature(crate_visibility_modifier)]
+
+mod bar {
+    crate struct Foo;
+}
+
+fn main() {
+    Foo;
+    //~^ ERROR cannot find value `Foo` in this scope [E0425]
+}
diff --git a/src/test/ui/crate-in-paths.stderr b/src/test/ui/crate-in-paths.stderr
new file mode 100644
index 0000000..c67fd4a
--- /dev/null
+++ b/src/test/ui/crate-in-paths.stderr
@@ -0,0 +1,13 @@
+error[E0425]: cannot find value `Foo` in this scope
+  --> $DIR/crate-in-paths.rs:10:5
+   |
+LL |     Foo;
+   |     ^^^ not found in this scope
+help: possible candidate is found in another module, you can import it into scope
+   |
+LL | use crate::bar::Foo;
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/crate-name-mismatch.rs b/src/test/ui/crate-name-mismatch.rs
new file mode 100644
index 0000000..49a257f
--- /dev/null
+++ b/src/test/ui/crate-name-mismatch.rs
@@ -0,0 +1,6 @@
+// compile-flags: --crate-name foo
+
+#![crate_name = "bar"]
+//~^ ERROR: --crate-name and #[crate_name] are required to match, but `foo` != `bar`
+
+fn main() {}
diff --git a/src/test/ui/crate-name-mismatch.stderr b/src/test/ui/crate-name-mismatch.stderr
new file mode 100644
index 0000000..4784db8
--- /dev/null
+++ b/src/test/ui/crate-name-mismatch.stderr
@@ -0,0 +1,8 @@
+error: --crate-name and #[crate_name] are required to match, but `foo` != `bar`
+  --> $DIR/crate-name-mismatch.rs:3:1
+   |
+LL | #![crate_name = "bar"]
+   | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/cross/cross-borrow-trait.rs b/src/test/ui/cross/cross-borrow-trait.rs
new file mode 100644
index 0000000..d8d7537
--- /dev/null
+++ b/src/test/ui/cross/cross-borrow-trait.rs
@@ -0,0 +1,13 @@
+// Test that cross-borrowing (implicitly converting from `Box<T>` to `&T`) is
+// forbidden when `T` is a trait.
+
+struct Foo;
+trait Trait { fn foo(&self) {} }
+impl Trait for Foo {}
+
+pub fn main() {
+    let x: Box<Trait> = Box::new(Foo);
+    let _y: &Trait = x; //~ ERROR E0308
+                        //~| expected type `&dyn Trait`
+                        //~| found type `std::boxed::Box<dyn Trait>`
+}
diff --git a/src/test/ui/cross/cross-borrow-trait.stderr b/src/test/ui/cross/cross-borrow-trait.stderr
new file mode 100644
index 0000000..b35f596
--- /dev/null
+++ b/src/test/ui/cross/cross-borrow-trait.stderr
@@ -0,0 +1,15 @@
+error[E0308]: mismatched types
+  --> $DIR/cross-borrow-trait.rs:10:22
+   |
+LL |     let _y: &Trait = x;
+   |                      ^
+   |                      |
+   |                      expected &dyn Trait, found struct `std::boxed::Box`
+   |                      help: consider borrowing here: `&x`
+   |
+   = note: expected type `&dyn Trait`
+              found type `std::boxed::Box<dyn Trait>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/cross/cross-crate-macro-backtrace/auxiliary/extern_macro_crate.rs b/src/test/ui/cross/cross-crate-macro-backtrace/auxiliary/extern_macro_crate.rs
new file mode 100644
index 0000000..fbda3db
--- /dev/null
+++ b/src/test/ui/cross/cross-crate-macro-backtrace/auxiliary/extern_macro_crate.rs
@@ -0,0 +1,13 @@
+#![crate_type = "dylib"]
+
+pub fn print(_args: std::fmt::Arguments) {}
+
+#[macro_export]
+macro_rules! myprint {
+    ($($arg:tt)*) => ($crate::print(format_args!($($arg)*)));
+}
+
+#[macro_export]
+macro_rules! myprintln {
+    ($fmt:expr) => (myprint!(concat!($fmt, "\n")));
+}
diff --git a/src/test/ui/cross/cross-crate-macro-backtrace/main.rs b/src/test/ui/cross/cross-crate-macro-backtrace/main.rs
new file mode 100644
index 0000000..f7d4330
--- /dev/null
+++ b/src/test/ui/cross/cross-crate-macro-backtrace/main.rs
@@ -0,0 +1,8 @@
+// aux-build:extern_macro_crate.rs
+#[macro_use(myprintln, myprint)]
+extern crate extern_macro_crate;
+
+fn main() {
+    myprintln!("{}");
+    //~^ ERROR in format string
+}
diff --git a/src/test/ui/cross/cross-crate-macro-backtrace/main.stderr b/src/test/ui/cross/cross-crate-macro-backtrace/main.stderr
new file mode 100644
index 0000000..b6ebe0f
--- /dev/null
+++ b/src/test/ui/cross/cross-crate-macro-backtrace/main.stderr
@@ -0,0 +1,10 @@
+error: 1 positional argument in format string, but no arguments were given
+  --> $DIR/main.rs:6:5
+   |
+LL |     myprintln!("{}");
+   |     ^^^^^^^^^^^^^^^^^
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/cross/cross-file-errors/main.rs b/src/test/ui/cross/cross-file-errors/main.rs
new file mode 100644
index 0000000..74e9461
--- /dev/null
+++ b/src/test/ui/cross/cross-file-errors/main.rs
@@ -0,0 +1,7 @@
+#[macro_use]
+mod underscore;
+
+fn main() {
+    underscore!();
+    //~^ ERROR expected expression, found reserved identifier `_`
+}
diff --git a/src/test/ui/cross/cross-file-errors/main.stderr b/src/test/ui/cross/cross-file-errors/main.stderr
new file mode 100644
index 0000000..7fd91eb
--- /dev/null
+++ b/src/test/ui/cross/cross-file-errors/main.stderr
@@ -0,0 +1,13 @@
+error: expected expression, found reserved identifier `_`
+  --> $DIR/underscore.rs:8:9
+   |
+LL |         _
+   |         ^ expected expression
+   | 
+  ::: $DIR/main.rs:5:5
+   |
+LL |     underscore!();
+   |     -------------- in this macro invocation
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/cross/cross-file-errors/underscore.rs b/src/test/ui/cross/cross-file-errors/underscore.rs
new file mode 100644
index 0000000..76e72a9
--- /dev/null
+++ b/src/test/ui/cross/cross-file-errors/underscore.rs
@@ -0,0 +1,10 @@
+// We want this file only so we can test cross-file error
+// messages, but we don't want it in an external crate.
+// ignore-test
+#![crate_type = "lib"]
+
+macro_rules! underscore {
+    () => (
+        _
+    )
+}
diff --git a/src/test/ui/cross/cross-fn-cache-hole.rs b/src/test/ui/cross/cross-fn-cache-hole.rs
new file mode 100644
index 0000000..249c647
--- /dev/null
+++ b/src/test/ui/cross/cross-fn-cache-hole.rs
@@ -0,0 +1,31 @@
+// Check that when there are vacuous predicates in the environment
+// (which make a fn uncallable) we don't erroneously cache those and
+// then consider them satisfied elsewhere. The current technique for
+// doing this is to not use global caches when there is a chance that
+// the environment contains such a predicate.
+// We still error for `i32: Bar<u32>` pending #48214
+
+trait Foo<X,Y>: Bar<X> {
+}
+
+trait Bar<X> { }
+
+// We don't always check where clauses for sanity, but in this case
+// wfcheck does report an error here:
+fn vacuous<A>() //~ ERROR the trait bound `i32: Bar<u32>` is not satisfied
+    where i32: Foo<u32, A>
+{
+    // ... the original intention was to check that we don't use that
+    // vacuous where clause (which could never be satisfied) to accept
+    // the following line and then mess up calls elsewhere.
+    require::<i32, u32>();
+}
+
+fn require<A,B>()
+    where A: Bar<B>
+{
+}
+
+fn main() {
+    require::<i32, u32>();
+}
diff --git a/src/test/ui/cross/cross-fn-cache-hole.stderr b/src/test/ui/cross/cross-fn-cache-hole.stderr
new file mode 100644
index 0000000..3bedd0d
--- /dev/null
+++ b/src/test/ui/cross/cross-fn-cache-hole.stderr
@@ -0,0 +1,18 @@
+error[E0277]: the trait bound `i32: Bar<u32>` is not satisfied
+  --> $DIR/cross-fn-cache-hole.rs:15:1
+   |
+LL | / fn vacuous<A>()
+LL | |     where i32: Foo<u32, A>
+LL | | {
+LL | |     // ... the original intention was to check that we don't use that
+...  |
+LL | |     require::<i32, u32>();
+LL | | }
+   | |_^ the trait `Bar<u32>` is not implemented for `i32`
+   |
+   = help: see issue #48214
+   = help: add #![feature(trivial_bounds)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/custom-attribute-multisegment.rs b/src/test/ui/custom-attribute-multisegment.rs
new file mode 100644
index 0000000..95cefe5
--- /dev/null
+++ b/src/test/ui/custom-attribute-multisegment.rs
@@ -0,0 +1,8 @@
+// Unresolved multi-segment attributes are not treated as custom.
+
+#![feature(custom_attribute)]
+
+mod existent {}
+
+#[existent::nonexistent] //~ ERROR failed to resolve: could not find `nonexistent` in `existent`
+fn main() {}
diff --git a/src/test/ui/custom-attribute-multisegment.stderr b/src/test/ui/custom-attribute-multisegment.stderr
new file mode 100644
index 0000000..9ba9c00
--- /dev/null
+++ b/src/test/ui/custom-attribute-multisegment.stderr
@@ -0,0 +1,9 @@
+error[E0433]: failed to resolve: could not find `nonexistent` in `existent`
+  --> $DIR/custom-attribute-multisegment.rs:7:13
+   |
+LL | #[existent::nonexistent]
+   |             ^^^^^^^^^^^ could not find `nonexistent` in `existent`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/custom-derive/auxiliary/plugin.rs b/src/test/ui/custom-derive/auxiliary/plugin.rs
new file mode 100644
index 0000000..5e500de
--- /dev/null
+++ b/src/test/ui/custom-derive/auxiliary/plugin.rs
@@ -0,0 +1,28 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(Foo)]
+pub fn derive_foo(input: TokenStream) -> TokenStream {
+    input
+}
+
+#[proc_macro_derive(Bar)]
+pub fn derive_bar(input: TokenStream) -> TokenStream {
+    panic!("lolnope");
+}
+
+#[proc_macro_derive(WithHelper, attributes(helper))]
+pub fn with_helper(input: TokenStream) -> TokenStream {
+    TokenStream::new()
+}
+
+#[proc_macro_attribute]
+pub fn helper(_: TokenStream, input: TokenStream) -> TokenStream {
+    input
+}
diff --git a/src/test/ui/custom-derive/derive-in-mod.rs b/src/test/ui/custom-derive/derive-in-mod.rs
new file mode 100644
index 0000000..8478ff1
--- /dev/null
+++ b/src/test/ui/custom-derive/derive-in-mod.rs
@@ -0,0 +1,13 @@
+// compile-pass
+// aux-build:plugin.rs
+
+extern crate plugin;
+
+mod inner {
+    use plugin::WithHelper;
+
+    #[derive(WithHelper)]
+    struct S;
+}
+
+fn main() {}
diff --git a/src/test/ui/custom-derive/helper-attr-blocked-by-import-ambig.rs b/src/test/ui/custom-derive/helper-attr-blocked-by-import-ambig.rs
new file mode 100644
index 0000000..ba072ba
--- /dev/null
+++ b/src/test/ui/custom-derive/helper-attr-blocked-by-import-ambig.rs
@@ -0,0 +1,12 @@
+// aux-build:plugin.rs
+
+#[macro_use(WithHelper)]
+extern crate plugin;
+
+use plugin::helper;
+
+#[derive(WithHelper)]
+#[helper] //~ ERROR `helper` is ambiguous
+struct S;
+
+fn main() {}
diff --git a/src/test/ui/custom-derive/helper-attr-blocked-by-import-ambig.stderr b/src/test/ui/custom-derive/helper-attr-blocked-by-import-ambig.stderr
new file mode 100644
index 0000000..e83c291
--- /dev/null
+++ b/src/test/ui/custom-derive/helper-attr-blocked-by-import-ambig.stderr
@@ -0,0 +1,21 @@
+error[E0659]: `helper` is ambiguous (derive helper attribute vs any other name)
+  --> $DIR/helper-attr-blocked-by-import-ambig.rs:9:3
+   |
+LL | #[helper]
+   |   ^^^^^^ ambiguous name
+   |
+note: `helper` could refer to the derive helper attribute defined here
+  --> $DIR/helper-attr-blocked-by-import-ambig.rs:8:10
+   |
+LL | #[derive(WithHelper)]
+   |          ^^^^^^^^^^
+note: `helper` could also refer to the attribute macro imported here
+  --> $DIR/helper-attr-blocked-by-import-ambig.rs:6:5
+   |
+LL | use plugin::helper;
+   |     ^^^^^^^^^^^^^^
+   = help: use `crate::helper` to refer to this attribute macro unambiguously
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0659`.
diff --git a/src/test/ui/custom-derive/helper-attr-blocked-by-import.rs b/src/test/ui/custom-derive/helper-attr-blocked-by-import.rs
new file mode 100644
index 0000000..abbf014
--- /dev/null
+++ b/src/test/ui/custom-derive/helper-attr-blocked-by-import.rs
@@ -0,0 +1,28 @@
+// compile-pass
+// aux-build:plugin.rs
+
+#[macro_use(WithHelper)]
+extern crate plugin;
+
+use self::one::*;
+use self::two::*;
+
+mod helper {}
+
+mod one {
+    use helper;
+
+    #[derive(WithHelper)]
+    #[helper]
+    struct One;
+}
+
+mod two {
+    use helper;
+
+    #[derive(WithHelper)]
+    #[helper]
+    struct Two;
+}
+
+fn main() {}
diff --git a/src/test/ui/custom-derive/issue-36935.rs b/src/test/ui/custom-derive/issue-36935.rs
new file mode 100644
index 0000000..7a5d19f
--- /dev/null
+++ b/src/test/ui/custom-derive/issue-36935.rs
@@ -0,0 +1,12 @@
+// aux-build:plugin.rs
+
+
+#[macro_use] extern crate plugin;
+
+#[derive(Foo, Bar)] //~ ERROR proc-macro derive panicked
+struct Baz {
+    a: i32,
+    b: i32,
+}
+
+fn main() {}
diff --git a/src/test/ui/custom-derive/issue-36935.stderr b/src/test/ui/custom-derive/issue-36935.stderr
new file mode 100644
index 0000000..2875bc5
--- /dev/null
+++ b/src/test/ui/custom-derive/issue-36935.stderr
@@ -0,0 +1,10 @@
+error: proc-macro derive panicked
+  --> $DIR/issue-36935.rs:6:15
+   |
+LL | #[derive(Foo, Bar)]
+   |               ^^^
+   |
+   = help: message: lolnope
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/custom-test-frameworks-simple.rs b/src/test/ui/custom-test-frameworks-simple.rs
new file mode 100644
index 0000000..a8aac6e
--- /dev/null
+++ b/src/test/ui/custom-test-frameworks-simple.rs
@@ -0,0 +1,22 @@
+// compile-flags: --test
+// run-pass
+
+#![feature(custom_test_frameworks)]
+#![test_runner(crate::foo_runner)]
+
+#[cfg(test)]
+fn foo_runner(ts: &[&Fn(usize)->()]) {
+    for (i, t) in ts.iter().enumerate() {
+        t(i);
+    }
+}
+
+#[test_case]
+fn test1(i: usize) {
+    println!("Hi #{}", i);
+}
+
+#[test_case]
+fn test2(i: usize) {
+    println!("Hey #{}", i);
+}
diff --git a/src/test/ui/custom_attribute.rs b/src/test/ui/custom_attribute.rs
new file mode 100644
index 0000000..9cb43ab
--- /dev/null
+++ b/src/test/ui/custom_attribute.rs
@@ -0,0 +1,9 @@
+#![feature(stmt_expr_attributes)]
+
+#[foo] //~ ERROR The attribute `foo`
+fn main() {
+    #[foo] //~ ERROR The attribute `foo`
+    let x = ();
+    #[foo] //~ ERROR The attribute `foo`
+    x
+}
diff --git a/src/test/ui/custom_attribute.stderr b/src/test/ui/custom_attribute.stderr
new file mode 100644
index 0000000..6608fb5
--- /dev/null
+++ b/src/test/ui/custom_attribute.stderr
@@ -0,0 +1,27 @@
+error[E0658]: The attribute `foo` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/custom_attribute.rs:3:3
+   |
+LL | #[foo]
+   |   ^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error[E0658]: The attribute `foo` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/custom_attribute.rs:5:7
+   |
+LL |     #[foo]
+   |       ^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error[E0658]: The attribute `foo` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/custom_attribute.rs:7:7
+   |
+LL |     #[foo]
+   |       ^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/custom_test_frameworks/auxiliary/dynamic_runner.rs b/src/test/ui/custom_test_frameworks/auxiliary/dynamic_runner.rs
new file mode 100644
index 0000000..a56e0b1
--- /dev/null
+++ b/src/test/ui/custom_test_frameworks/auxiliary/dynamic_runner.rs
@@ -0,0 +1,35 @@
+use std::process::exit;
+
+pub trait Testable {
+    // Name of the test
+    fn name(&self) -> String;
+
+    // Tests pass by default
+    fn run(&self) -> bool {
+        true
+    }
+
+    // A test can generate subtests
+    fn subtests(&self) -> Vec<Box<dyn Testable>> {
+        vec![]
+    }
+}
+
+fn run_test(t: &dyn Testable) -> bool {
+    let success = t.subtests().into_iter().all(|sub_t| run_test(&*sub_t)) && t.run();
+    println!("{}...{}", t.name(), if success { "SUCCESS" } else { "FAIL" });
+    success
+}
+
+pub fn runner(tests: &[&dyn Testable]) {
+    let mut failed = false;
+    for t in tests {
+        if !run_test(*t) {
+            failed = true;
+        }
+    }
+
+    if failed {
+        exit(1);
+    }
+}
diff --git a/src/test/ui/custom_test_frameworks/auxiliary/example_runner.rs b/src/test/ui/custom_test_frameworks/auxiliary/example_runner.rs
new file mode 100644
index 0000000..dd68c06
--- /dev/null
+++ b/src/test/ui/custom_test_frameworks/auxiliary/example_runner.rs
@@ -0,0 +1,10 @@
+pub trait Testable {
+    fn name(&self) -> String;
+    fn run(&self) -> Option<String>; // None will be success, Some is the error message
+}
+
+pub fn runner(tests: &[&dyn Testable]) {
+    for t in tests {
+        print!("{}........{}", t.name(), t.run().unwrap_or_else(|| "SUCCESS".to_string()));
+    }
+}
diff --git a/src/test/ui/custom_test_frameworks/dynamic.rs b/src/test/ui/custom_test_frameworks/dynamic.rs
new file mode 100644
index 0000000..6766ec5
--- /dev/null
+++ b/src/test/ui/custom_test_frameworks/dynamic.rs
@@ -0,0 +1,35 @@
+// run-pass
+// aux-build:dynamic_runner.rs
+// compile-flags:--test
+#![feature(custom_test_frameworks)]
+#![test_runner(dynamic_runner::runner)]
+
+extern crate dynamic_runner;
+
+pub struct AllFoo(&'static str);
+struct IsFoo(String);
+
+impl dynamic_runner::Testable for AllFoo {
+    fn name(&self) -> String {
+        String::from(self.0)
+    }
+
+    fn subtests(&self) -> Vec<Box<dyn dynamic_runner::Testable>> {
+        self.0.split(" ").map(|word|
+            Box::new(IsFoo(word.into())) as Box<dyn dynamic_runner::Testable>
+        ).collect()
+    }
+}
+
+impl dynamic_runner::Testable for IsFoo {
+    fn name(&self) -> String {
+        self.0.clone()
+    }
+
+    fn run(&self) -> bool {
+        self.0 == "foo"
+    }
+}
+
+#[test_case]
+const TEST_2: AllFoo = AllFoo("foo foo");
diff --git a/src/test/ui/custom_test_frameworks/full.rs b/src/test/ui/custom_test_frameworks/full.rs
new file mode 100644
index 0000000..8c81882
--- /dev/null
+++ b/src/test/ui/custom_test_frameworks/full.rs
@@ -0,0 +1,28 @@
+// run-pass
+// aux-build:example_runner.rs
+// compile-flags:--test
+
+#![feature(custom_test_frameworks)]
+#![test_runner(example_runner::runner)]
+extern crate example_runner;
+
+pub struct IsFoo(&'static str);
+
+impl example_runner::Testable for IsFoo {
+    fn name(&self) -> String {
+        self.0.to_string()
+    }
+
+    fn run(&self) -> Option<String> {
+        if self.0 != "foo" {
+            return Some(format!("{} != foo", self.0));
+        }
+        None
+    }
+}
+
+#[test_case]
+const TEST_1: IsFoo = IsFoo("hello");
+
+#[test_case]
+const TEST_2: IsFoo = IsFoo("foo");
diff --git a/src/test/ui/custom_test_frameworks/mismatch.rs b/src/test/ui/custom_test_frameworks/mismatch.rs
new file mode 100644
index 0000000..e6848e2
--- /dev/null
+++ b/src/test/ui/custom_test_frameworks/mismatch.rs
@@ -0,0 +1,10 @@
+// aux-build:example_runner.rs
+// compile-flags:--test
+#![feature(custom_test_frameworks)]
+#![test_runner(example_runner::runner)]
+
+extern crate example_runner;
+
+#[test]
+fn wrong_kind(){}
+//~^ ERROR trait bound `test::TestDescAndFn: example_runner::Testable` is not satisfied
diff --git a/src/test/ui/custom_test_frameworks/mismatch.stderr b/src/test/ui/custom_test_frameworks/mismatch.stderr
new file mode 100644
index 0000000..9e2688c6
--- /dev/null
+++ b/src/test/ui/custom_test_frameworks/mismatch.stderr
@@ -0,0 +1,11 @@
+error[E0277]: the trait bound `test::TestDescAndFn: example_runner::Testable` is not satisfied
+  --> $DIR/mismatch.rs:9:1
+   |
+LL | fn wrong_kind(){}
+   | ^^^^^^^^^^^^^^^^^ the trait `example_runner::Testable` is not implemented for `test::TestDescAndFn`
+   |
+   = note: required for the cast to the object type `dyn example_runner::Testable`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/cycle-projection-based-on-where-clause.rs b/src/test/ui/cycle-projection-based-on-where-clause.rs
new file mode 100644
index 0000000..336b678
--- /dev/null
+++ b/src/test/ui/cycle-projection-based-on-where-clause.rs
@@ -0,0 +1,25 @@
+// Example cycle where a bound on `T` uses a shorthand for `T`. This
+// creates a cycle because we have to know the bounds on `T` to figure
+// out what trait defines `Item`, but we can't know the bounds on `T`
+// without knowing how to handle `T::Item`.
+//
+// Note that in the future cases like this could perhaps become legal,
+// if we got more fine-grained about our cycle detection or changed
+// how we handle `T::Item` resolution.
+
+use std::ops::Add;
+
+// Preamble.
+trait Trait { type Item; }
+
+struct A<T>
+    where T : Trait,
+          T : Add<T::Item>
+    //~^ ERROR cycle detected
+    //~| ERROR associated type `Item` not found for `T`
+{
+    data: T
+}
+
+fn main() {
+}
diff --git a/src/test/ui/cycle-projection-based-on-where-clause.stderr b/src/test/ui/cycle-projection-based-on-where-clause.stderr
new file mode 100644
index 0000000..b11a8bd
--- /dev/null
+++ b/src/test/ui/cycle-projection-based-on-where-clause.stderr
@@ -0,0 +1,23 @@
+error[E0391]: cycle detected when computing the bounds for type parameter `T`
+  --> $DIR/cycle-projection-based-on-where-clause.rs:17:19
+   |
+LL |           T : Add<T::Item>
+   |                   ^^^^^^^
+   |
+   = note: ...which again requires computing the bounds for type parameter `T`, completing the cycle
+note: cycle used when processing `A`
+  --> $DIR/cycle-projection-based-on-where-clause.rs:17:19
+   |
+LL |           T : Add<T::Item>
+   |                   ^^^^^^^
+
+error[E0220]: associated type `Item` not found for `T`
+  --> $DIR/cycle-projection-based-on-where-clause.rs:17:19
+   |
+LL |           T : Add<T::Item>
+   |                   ^^^^^^^ associated type `Item` not found
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0220, E0391.
+For more information about an error, try `rustc --explain E0220`.
diff --git a/src/test/ui/cycle-trait/cycle-trait-default-type-trait.rs b/src/test/ui/cycle-trait/cycle-trait-default-type-trait.rs
new file mode 100644
index 0000000..d658753
--- /dev/null
+++ b/src/test/ui/cycle-trait/cycle-trait-default-type-trait.rs
@@ -0,0 +1,8 @@
+// Test a cycle where a type parameter on a trait has a default that
+// again references the trait.
+
+trait Foo<X = Box<Foo>> {
+    //~^ ERROR cycle detected
+}
+
+fn main() { }
diff --git a/src/test/ui/cycle-trait/cycle-trait-default-type-trait.stderr b/src/test/ui/cycle-trait/cycle-trait-default-type-trait.stderr
new file mode 100644
index 0000000..aa45462
--- /dev/null
+++ b/src/test/ui/cycle-trait/cycle-trait-default-type-trait.stderr
@@ -0,0 +1,16 @@
+error[E0391]: cycle detected when processing `Foo::X`
+  --> $DIR/cycle-trait-default-type-trait.rs:4:19
+   |
+LL | trait Foo<X = Box<Foo>> {
+   |                   ^^^
+   |
+   = note: ...which again requires processing `Foo::X`, completing the cycle
+note: cycle used when collecting item types in top-level module
+  --> $DIR/cycle-trait-default-type-trait.rs:4:1
+   |
+LL | trait Foo<X = Box<Foo>> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/cycle-trait/cycle-trait-supertrait-direct.rs b/src/test/ui/cycle-trait/cycle-trait-supertrait-direct.rs
new file mode 100644
index 0000000..e6ab2c7
--- /dev/null
+++ b/src/test/ui/cycle-trait/cycle-trait-supertrait-direct.rs
@@ -0,0 +1,7 @@
+// Test a supertrait cycle where a trait extends itself.
+
+trait Chromosome: Chromosome {
+    //~^ ERROR cycle detected
+}
+
+fn main() { }
diff --git a/src/test/ui/cycle-trait/cycle-trait-supertrait-direct.stderr b/src/test/ui/cycle-trait/cycle-trait-supertrait-direct.stderr
new file mode 100644
index 0000000..8aa3ac8a
--- /dev/null
+++ b/src/test/ui/cycle-trait/cycle-trait-supertrait-direct.stderr
@@ -0,0 +1,16 @@
+error[E0391]: cycle detected when computing the supertraits of `Chromosome`
+  --> $DIR/cycle-trait-supertrait-direct.rs:3:19
+   |
+LL | trait Chromosome: Chromosome {
+   |                   ^^^^^^^^^^
+   |
+   = note: ...which again requires computing the supertraits of `Chromosome`, completing the cycle
+note: cycle used when collecting item types in top-level module
+  --> $DIR/cycle-trait-supertrait-direct.rs:3:1
+   |
+LL | trait Chromosome: Chromosome {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/cycle-trait/cycle-trait-supertrait-indirect.rs b/src/test/ui/cycle-trait/cycle-trait-supertrait-indirect.rs
new file mode 100644
index 0000000..9a72b65
--- /dev/null
+++ b/src/test/ui/cycle-trait/cycle-trait-supertrait-indirect.rs
@@ -0,0 +1,13 @@
+// Test a supertrait cycle where the first trait we find (`A`) is not
+// a direct participant in the cycle.
+
+trait A: B {
+}
+
+trait B: C {
+    //~^ ERROR cycle detected
+}
+
+trait C: B { }
+
+fn main() { }
diff --git a/src/test/ui/cycle-trait/cycle-trait-supertrait-indirect.stderr b/src/test/ui/cycle-trait/cycle-trait-supertrait-indirect.stderr
new file mode 100644
index 0000000..9740f43
--- /dev/null
+++ b/src/test/ui/cycle-trait/cycle-trait-supertrait-indirect.stderr
@@ -0,0 +1,21 @@
+error[E0391]: cycle detected when computing the supertraits of `B`
+  --> $DIR/cycle-trait-supertrait-indirect.rs:7:10
+   |
+LL | trait B: C {
+   |          ^
+   |
+note: ...which requires computing the supertraits of `C`...
+  --> $DIR/cycle-trait-supertrait-indirect.rs:11:10
+   |
+LL | trait C: B { }
+   |          ^
+   = note: ...which again requires computing the supertraits of `B`, completing the cycle
+note: cycle used when computing the supertraits of `A`
+  --> $DIR/cycle-trait-supertrait-indirect.rs:4:10
+   |
+LL | trait A: B {
+   |          ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/dead-code-closure-bang.rs b/src/test/ui/dead-code-closure-bang.rs
new file mode 100644
index 0000000..8e8636b
--- /dev/null
+++ b/src/test/ui/dead-code-closure-bang.rs
@@ -0,0 +1,9 @@
+// ignore-test FIXME(#20574)
+
+#![deny(unreachable_code)]
+
+fn main() {
+    let x = || panic!();
+    x();
+    println!("Foo bar"); //~ ERROR: unreachable statement
+}
diff --git a/src/test/ui/dead-code-impl.rs b/src/test/ui/dead-code-impl.rs
new file mode 100644
index 0000000..84829c9
--- /dev/null
+++ b/src/test/ui/dead-code-impl.rs
@@ -0,0 +1,17 @@
+// run-pass
+
+#![deny(dead_code)]
+
+pub struct GenericFoo<T>(T);
+
+type Foo = GenericFoo<u32>;
+
+impl Foo {
+    fn bar(self) -> u8 {
+        0
+    }
+}
+
+fn main() {
+    println!("{}", GenericFoo(0).bar());
+}
diff --git a/src/test/ui/dead-code-ret.rs b/src/test/ui/dead-code-ret.rs
new file mode 100644
index 0000000..fad3579
--- /dev/null
+++ b/src/test/ui/dead-code-ret.rs
@@ -0,0 +1,8 @@
+// error-pattern: unreachable statement
+
+#![deny(unreachable_code)]
+
+fn main() {
+    return;
+    println!("Paul is dead");
+}
diff --git a/src/test/ui/dead-code-ret.stderr b/src/test/ui/dead-code-ret.stderr
new file mode 100644
index 0000000..092a176
--- /dev/null
+++ b/src/test/ui/dead-code-ret.stderr
@@ -0,0 +1,15 @@
+error: unreachable statement
+  --> $DIR/dead-code-ret.rs:7:5
+   |
+LL |     println!("Paul is dead");
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/dead-code-ret.rs:3:9
+   |
+LL | #![deny(unreachable_code)]
+   |         ^^^^^^^^^^^^^^^^
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/dead-code-tuple-struct-field.rs b/src/test/ui/dead-code-tuple-struct-field.rs
new file mode 100644
index 0000000..496ce4f
--- /dev/null
+++ b/src/test/ui/dead-code-tuple-struct-field.rs
@@ -0,0 +1,12 @@
+// compile-pass
+
+#![deny(dead_code)]
+
+const LEN: usize = 4;
+
+#[derive(Debug)]
+struct Wrapper([u8; LEN]);
+
+fn main() {
+    println!("{:?}", Wrapper([0, 1, 2, 3]));
+}
diff --git a/src/test/ui/defaulted-never-note.rs b/src/test/ui/defaulted-never-note.rs
new file mode 100644
index 0000000..acda4b4
--- /dev/null
+++ b/src/test/ui/defaulted-never-note.rs
@@ -0,0 +1,35 @@
+// We need to opt into the `!` feature in order to trigger the
+// requirement that this is testing.
+#![feature(never_type)]
+
+#![allow(unused)]
+
+trait Deserialize: Sized {
+    fn deserialize() -> Result<Self, String>;
+}
+
+impl Deserialize for () {
+    fn deserialize() -> Result<(), String> {
+        Ok(())
+    }
+}
+
+trait ImplementedForUnitButNotNever {}
+
+impl ImplementedForUnitButNotNever for () {}
+
+fn foo<T: ImplementedForUnitButNotNever>(_t: T) {}
+//~^ NOTE required by `foo`
+
+fn smeg() {
+    let _x = return;
+    foo(_x);
+    //~^ ERROR the trait bound
+    //~| NOTE the trait `ImplementedForUnitButNotNever` is not implemented
+    //~| NOTE the trait is implemented for `()`
+}
+
+fn main() {
+    smeg();
+}
+
diff --git a/src/test/ui/defaulted-never-note.stderr b/src/test/ui/defaulted-never-note.stderr
new file mode 100644
index 0000000..45174c3
--- /dev/null
+++ b/src/test/ui/defaulted-never-note.stderr
@@ -0,0 +1,16 @@
+error[E0277]: the trait bound `!: ImplementedForUnitButNotNever` is not satisfied
+  --> $DIR/defaulted-never-note.rs:26:5
+   |
+LL |     foo(_x);
+   |     ^^^ the trait `ImplementedForUnitButNotNever` is not implemented for `!`
+   |
+   = note: the trait is implemented for `()`. Possibly this error has been caused by changes to Rust's type-inference algorithm (see: https://github.com/rust-lang/rust/issues/48950 for more info). Consider whether you meant to use the type `()` here instead.
+note: required by `foo`
+  --> $DIR/defaulted-never-note.rs:21:1
+   |
+LL | fn foo<T: ImplementedForUnitButNotNever>(_t: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/dep-graph/dep-graph-assoc-type-codegen.rs b/src/test/ui/dep-graph/dep-graph-assoc-type-codegen.rs
new file mode 100644
index 0000000..bcf7e3e
--- /dev/null
+++ b/src/test/ui/dep-graph/dep-graph-assoc-type-codegen.rs
@@ -0,0 +1,37 @@
+// Test that when a trait impl changes, fns whose body uses that trait
+// must also be recompiled.
+
+// compile-flags: -Z query-dep-graph
+
+#![feature(rustc_attrs)]
+#![allow(warnings)]
+
+fn main() { }
+
+pub trait Foo: Sized {
+    type T;
+    fn method(self) { }
+}
+
+mod x {
+    use Foo;
+
+    #[rustc_if_this_changed]
+    impl Foo for char { type T = char; }
+
+    impl Foo for u32 { type T = u32; }
+}
+
+mod y {
+    use Foo;
+
+    #[rustc_then_this_would_need(typeck_tables_of)] //~ ERROR OK
+    pub fn use_char_assoc() {
+        // Careful here: in the representation, <char as Foo>::T gets
+        // normalized away, so at a certain point we had no edge to
+        // codegen.  (But now codegen just depends on typeck.)
+        let x: <char as Foo>::T = 'a';
+    }
+
+    pub fn take_foo<T:Foo>(t: T) { }
+}
diff --git a/src/test/ui/dep-graph/dep-graph-assoc-type-codegen.stderr b/src/test/ui/dep-graph/dep-graph-assoc-type-codegen.stderr
new file mode 100644
index 0000000..a603d71
--- /dev/null
+++ b/src/test/ui/dep-graph/dep-graph-assoc-type-codegen.stderr
@@ -0,0 +1,8 @@
+error: OK
+  --> $DIR/dep-graph-assoc-type-codegen.rs:28:5
+   |
+LL |     #[rustc_then_this_would_need(typeck_tables_of)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/dep-graph/dep-graph-caller-callee.rs b/src/test/ui/dep-graph/dep-graph-caller-callee.rs
new file mode 100644
index 0000000..18b4252
--- /dev/null
+++ b/src/test/ui/dep-graph/dep-graph-caller-callee.rs
@@ -0,0 +1,35 @@
+// Test that immediate callers have to change when callee changes, but
+// not callers' callers.
+
+// compile-flags: -Z query-dep-graph
+
+#![feature(rustc_attrs)]
+#![allow(dead_code)]
+
+fn main() { }
+
+mod x {
+    #[rustc_if_this_changed]
+    pub fn x() { }
+}
+
+mod y {
+    use x;
+
+    // These dependencies SHOULD exist:
+    #[rustc_then_this_would_need(typeck_tables_of)] //~ ERROR OK
+    pub fn y() {
+        x::x();
+    }
+}
+
+mod z {
+    use y;
+
+    // These are expected to yield errors, because changes to `x`
+    // affect the BODY of `y`, but not its signature.
+    #[rustc_then_this_would_need(typeck_tables_of)] //~ ERROR no path
+    pub fn z() {
+        y::y();
+    }
+}
diff --git a/src/test/ui/dep-graph/dep-graph-caller-callee.stderr b/src/test/ui/dep-graph/dep-graph-caller-callee.stderr
new file mode 100644
index 0000000..de041e6
--- /dev/null
+++ b/src/test/ui/dep-graph/dep-graph-caller-callee.stderr
@@ -0,0 +1,14 @@
+error: OK
+  --> $DIR/dep-graph-caller-callee.rs:20:5
+   |
+LL |     #[rustc_then_this_would_need(typeck_tables_of)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: no path from `x::x` to `typeck_tables_of`
+  --> $DIR/dep-graph-caller-callee.rs:31:5
+   |
+LL |     #[rustc_then_this_would_need(typeck_tables_of)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/dep-graph/dep-graph-struct-signature.rs b/src/test/ui/dep-graph/dep-graph-struct-signature.rs
new file mode 100644
index 0000000..8b78d39
--- /dev/null
+++ b/src/test/ui/dep-graph/dep-graph-struct-signature.rs
@@ -0,0 +1,86 @@
+// Test cases where a changing struct appears in the signature of fns
+// and methods.
+
+// compile-flags: -Z query-dep-graph
+
+#![feature(rustc_attrs)]
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+fn main() { }
+
+#[rustc_if_this_changed]
+struct WillChange {
+    x: u32,
+    y: u32
+}
+
+struct WontChange {
+    x: u32,
+    y: u32
+}
+
+// these are valid dependencies
+mod signatures {
+    use WillChange;
+
+    #[rustc_then_this_would_need(type_of)] //~ ERROR no path
+    #[rustc_then_this_would_need(associated_item)] //~ ERROR no path
+    #[rustc_then_this_would_need(trait_def)] //~ ERROR no path
+    trait Bar {
+        #[rustc_then_this_would_need(fn_sig)] //~ ERROR OK
+        fn do_something(x: WillChange);
+    }
+
+    #[rustc_then_this_would_need(fn_sig)] //~ ERROR OK
+    #[rustc_then_this_would_need(typeck_tables_of)] //~ ERROR OK
+    fn some_fn(x: WillChange) { }
+
+    #[rustc_then_this_would_need(fn_sig)] //~ ERROR OK
+    #[rustc_then_this_would_need(typeck_tables_of)] //~ ERROR OK
+    fn new_foo(x: u32, y: u32) -> WillChange {
+        WillChange { x: x, y: y }
+    }
+
+    #[rustc_then_this_would_need(type_of)] //~ ERROR OK
+    impl WillChange {
+        #[rustc_then_this_would_need(fn_sig)] //~ ERROR OK
+        #[rustc_then_this_would_need(typeck_tables_of)] //~ ERROR OK
+        fn new(x: u32, y: u32) -> WillChange { loop { } }
+    }
+
+    #[rustc_then_this_would_need(type_of)] //~ ERROR OK
+    impl WillChange {
+        #[rustc_then_this_would_need(fn_sig)] //~ ERROR OK
+        #[rustc_then_this_would_need(typeck_tables_of)] //~ ERROR OK
+        fn method(&self, x: u32) { }
+    }
+
+    struct WillChanges {
+        #[rustc_then_this_would_need(type_of)] //~ ERROR OK
+        x: WillChange,
+        #[rustc_then_this_would_need(type_of)] //~ ERROR OK
+        y: WillChange
+    }
+
+    // The fields change, not the type itself.
+    #[rustc_then_this_would_need(type_of)] //~ ERROR no path
+    fn indirect(x: WillChanges) { }
+}
+
+mod invalid_signatures {
+    use WontChange;
+
+    #[rustc_then_this_would_need(type_of)] //~ ERROR no path
+    trait A {
+        #[rustc_then_this_would_need(fn_sig)] //~ ERROR no path
+        fn do_something_else_twice(x: WontChange);
+    }
+
+    #[rustc_then_this_would_need(fn_sig)] //~ ERROR no path
+    fn b(x: WontChange) { }
+
+    #[rustc_then_this_would_need(fn_sig)] //~ ERROR no path from `WillChange`
+    #[rustc_then_this_would_need(typeck_tables_of)] //~ ERROR no path from `WillChange`
+    fn c(x: u32) { }
+}
diff --git a/src/test/ui/dep-graph/dep-graph-struct-signature.stderr b/src/test/ui/dep-graph/dep-graph-struct-signature.stderr
new file mode 100644
index 0000000..2e00e5a
--- /dev/null
+++ b/src/test/ui/dep-graph/dep-graph-struct-signature.stderr
@@ -0,0 +1,134 @@
+error: no path from `WillChange` to `type_of`
+  --> $DIR/dep-graph-struct-signature.rs:27:5
+   |
+LL |     #[rustc_then_this_would_need(type_of)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: no path from `WillChange` to `associated_item`
+  --> $DIR/dep-graph-struct-signature.rs:28:5
+   |
+LL |     #[rustc_then_this_would_need(associated_item)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: no path from `WillChange` to `trait_def`
+  --> $DIR/dep-graph-struct-signature.rs:29:5
+   |
+LL |     #[rustc_then_this_would_need(trait_def)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: OK
+  --> $DIR/dep-graph-struct-signature.rs:35:5
+   |
+LL |     #[rustc_then_this_would_need(fn_sig)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: OK
+  --> $DIR/dep-graph-struct-signature.rs:36:5
+   |
+LL |     #[rustc_then_this_would_need(typeck_tables_of)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: OK
+  --> $DIR/dep-graph-struct-signature.rs:39:5
+   |
+LL |     #[rustc_then_this_would_need(fn_sig)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: OK
+  --> $DIR/dep-graph-struct-signature.rs:40:5
+   |
+LL |     #[rustc_then_this_would_need(typeck_tables_of)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: OK
+  --> $DIR/dep-graph-struct-signature.rs:45:5
+   |
+LL |     #[rustc_then_this_would_need(type_of)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: OK
+  --> $DIR/dep-graph-struct-signature.rs:52:5
+   |
+LL |     #[rustc_then_this_would_need(type_of)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: OK
+  --> $DIR/dep-graph-struct-signature.rs:60:9
+   |
+LL |         #[rustc_then_this_would_need(type_of)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: OK
+  --> $DIR/dep-graph-struct-signature.rs:62:9
+   |
+LL |         #[rustc_then_this_would_need(type_of)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: no path from `WillChange` to `type_of`
+  --> $DIR/dep-graph-struct-signature.rs:67:5
+   |
+LL |     #[rustc_then_this_would_need(type_of)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: no path from `WillChange` to `type_of`
+  --> $DIR/dep-graph-struct-signature.rs:74:5
+   |
+LL |     #[rustc_then_this_would_need(type_of)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: no path from `WillChange` to `fn_sig`
+  --> $DIR/dep-graph-struct-signature.rs:80:5
+   |
+LL |     #[rustc_then_this_would_need(fn_sig)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: no path from `WillChange` to `fn_sig`
+  --> $DIR/dep-graph-struct-signature.rs:83:5
+   |
+LL |     #[rustc_then_this_would_need(fn_sig)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: no path from `WillChange` to `typeck_tables_of`
+  --> $DIR/dep-graph-struct-signature.rs:84:5
+   |
+LL |     #[rustc_then_this_would_need(typeck_tables_of)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: OK
+  --> $DIR/dep-graph-struct-signature.rs:31:9
+   |
+LL |         #[rustc_then_this_would_need(fn_sig)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: no path from `WillChange` to `fn_sig`
+  --> $DIR/dep-graph-struct-signature.rs:76:9
+   |
+LL |         #[rustc_then_this_would_need(fn_sig)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: OK
+  --> $DIR/dep-graph-struct-signature.rs:47:9
+   |
+LL |         #[rustc_then_this_would_need(fn_sig)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: OK
+  --> $DIR/dep-graph-struct-signature.rs:48:9
+   |
+LL |         #[rustc_then_this_would_need(typeck_tables_of)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: OK
+  --> $DIR/dep-graph-struct-signature.rs:54:9
+   |
+LL |         #[rustc_then_this_would_need(fn_sig)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: OK
+  --> $DIR/dep-graph-struct-signature.rs:55:9
+   |
+LL |         #[rustc_then_this_would_need(typeck_tables_of)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 22 previous errors
+
diff --git a/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits-same-method.rs b/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits-same-method.rs
new file mode 100644
index 0000000..38622a7
--- /dev/null
+++ b/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits-same-method.rs
@@ -0,0 +1,45 @@
+// Test that adding an impl to a trait `Foo` DOES affect functions
+// that only use `Bar` if they have methods in common.
+
+// compile-flags: -Z query-dep-graph
+
+#![feature(rustc_attrs)]
+#![allow(dead_code)]
+#![allow(unused_imports)]
+
+fn main() { }
+
+pub trait Foo: Sized {
+    fn method(self) { }
+}
+
+pub trait Bar: Sized {
+    fn method(self) { }
+}
+
+mod x {
+    use {Foo, Bar};
+
+    #[rustc_if_this_changed]
+    impl Foo for u32 { }
+
+    impl Bar for char { }
+}
+
+mod y {
+    use {Foo, Bar};
+
+    #[rustc_then_this_would_need(typeck_tables_of)] //~ ERROR OK
+    pub fn with_char() {
+        char::method('a');
+    }
+}
+
+mod z {
+    use y;
+
+    #[rustc_then_this_would_need(typeck_tables_of)] //~ ERROR no path
+    pub fn z() {
+        y::with_char();
+    }
+}
diff --git a/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits-same-method.stderr b/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits-same-method.stderr
new file mode 100644
index 0000000..3384fd7
--- /dev/null
+++ b/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits-same-method.stderr
@@ -0,0 +1,14 @@
+error: OK
+  --> $DIR/dep-graph-trait-impl-two-traits-same-method.rs:32:5
+   |
+LL |     #[rustc_then_this_would_need(typeck_tables_of)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: no path from `x::<impl Foo for u32>` to `typeck_tables_of`
+  --> $DIR/dep-graph-trait-impl-two-traits-same-method.rs:41:5
+   |
+LL |     #[rustc_then_this_would_need(typeck_tables_of)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits.rs b/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits.rs
new file mode 100644
index 0000000..82306b6
--- /dev/null
+++ b/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits.rs
@@ -0,0 +1,44 @@
+// Test that adding an impl to a trait `Foo` does not affect functions
+// that only use `Bar`, so long as they do not have methods in common.
+
+// compile-flags: -Z query-dep-graph
+
+#![feature(rustc_attrs)]
+#![allow(warnings)]
+
+fn main() { }
+
+pub trait Foo: Sized {
+    fn foo(self) { }
+}
+
+pub trait Bar: Sized {
+    fn bar(self) { }
+}
+
+mod x {
+    use {Foo, Bar};
+
+    #[rustc_if_this_changed]
+    impl Foo for char { }
+
+    impl Bar for char { }
+}
+
+mod y {
+    use {Foo, Bar};
+
+    #[rustc_then_this_would_need(typeck_tables_of)] //~ ERROR no path
+    pub fn call_bar() {
+        char::bar('a');
+    }
+}
+
+mod z {
+    use y;
+
+    #[rustc_then_this_would_need(typeck_tables_of)] //~ ERROR no path
+    pub fn z() {
+        y::call_bar();
+    }
+}
diff --git a/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits.stderr b/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits.stderr
new file mode 100644
index 0000000..d8a1f05
--- /dev/null
+++ b/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits.stderr
@@ -0,0 +1,14 @@
+error: no path from `x::<impl Foo for char>` to `typeck_tables_of`
+  --> $DIR/dep-graph-trait-impl-two-traits.rs:31:5
+   |
+LL |     #[rustc_then_this_would_need(typeck_tables_of)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: no path from `x::<impl Foo for char>` to `typeck_tables_of`
+  --> $DIR/dep-graph-trait-impl-two-traits.rs:40:5
+   |
+LL |     #[rustc_then_this_would_need(typeck_tables_of)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/dep-graph/dep-graph-trait-impl.rs b/src/test/ui/dep-graph/dep-graph-trait-impl.rs
new file mode 100644
index 0000000..e4483b9
--- /dev/null
+++ b/src/test/ui/dep-graph/dep-graph-trait-impl.rs
@@ -0,0 +1,60 @@
+// Test that when a trait impl changes, fns whose body uses that trait
+// must also be recompiled.
+
+// compile-flags: -Z query-dep-graph
+
+#![feature(rustc_attrs)]
+#![allow(warnings)]
+
+fn main() { }
+
+pub trait Foo: Sized {
+    fn method(self) { }
+}
+
+mod x {
+    use Foo;
+
+    #[rustc_if_this_changed]
+    impl Foo for char { }
+
+    impl Foo for u32 { }
+}
+
+mod y {
+    use Foo;
+
+    #[rustc_then_this_would_need(typeck_tables_of)] //~ ERROR OK
+    pub fn with_char() {
+        char::method('a');
+    }
+
+    #[rustc_then_this_would_need(typeck_tables_of)] //~ ERROR OK
+    pub fn take_foo_with_char() {
+        take_foo::<char>('a');
+    }
+
+    #[rustc_then_this_would_need(typeck_tables_of)] //~ ERROR OK
+    pub fn with_u32() {
+        u32::method(22);
+    }
+
+    #[rustc_then_this_would_need(typeck_tables_of)] //~ ERROR OK
+    pub fn take_foo_with_u32() {
+        take_foo::<u32>(22);
+    }
+
+    pub fn take_foo<T:Foo>(t: T) { }
+}
+
+mod z {
+    use y;
+
+    // These are expected to yield errors, because changes to `x`
+    // affect the BODY of `y`, but not its signature.
+    #[rustc_then_this_would_need(typeck_tables_of)] //~ ERROR no path
+    pub fn z() {
+        y::with_char();
+        y::with_u32();
+    }
+}
diff --git a/src/test/ui/dep-graph/dep-graph-trait-impl.stderr b/src/test/ui/dep-graph/dep-graph-trait-impl.stderr
new file mode 100644
index 0000000..ca9676a
--- /dev/null
+++ b/src/test/ui/dep-graph/dep-graph-trait-impl.stderr
@@ -0,0 +1,32 @@
+error: OK
+  --> $DIR/dep-graph-trait-impl.rs:27:5
+   |
+LL |     #[rustc_then_this_would_need(typeck_tables_of)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: OK
+  --> $DIR/dep-graph-trait-impl.rs:32:5
+   |
+LL |     #[rustc_then_this_would_need(typeck_tables_of)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: OK
+  --> $DIR/dep-graph-trait-impl.rs:37:5
+   |
+LL |     #[rustc_then_this_would_need(typeck_tables_of)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: OK
+  --> $DIR/dep-graph-trait-impl.rs:42:5
+   |
+LL |     #[rustc_then_this_would_need(typeck_tables_of)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: no path from `x::<impl Foo for char>` to `typeck_tables_of`
+  --> $DIR/dep-graph-trait-impl.rs:55:5
+   |
+LL |     #[rustc_then_this_would_need(typeck_tables_of)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/ui/dep-graph/dep-graph-type-alias.rs b/src/test/ui/dep-graph/dep-graph-type-alias.rs
new file mode 100644
index 0000000..2d4a18f
--- /dev/null
+++ b/src/test/ui/dep-graph/dep-graph-type-alias.rs
@@ -0,0 +1,55 @@
+// Test that changing what a `type` points to does not go unnoticed.
+
+// compile-flags: -Z query-dep-graph
+
+#![feature(rustc_attrs)]
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+fn main() { }
+
+
+#[rustc_if_this_changed]
+type TypeAlias = u32;
+
+// The type alias directly affects the type of the field,
+// not the enclosing struct:
+#[rustc_then_this_would_need(type_of)] //~ ERROR no path
+struct Struct {
+    #[rustc_then_this_would_need(type_of)] //~ ERROR OK
+    x: TypeAlias,
+    y: u32
+}
+
+#[rustc_then_this_would_need(type_of)] //~ ERROR no path
+enum Enum {
+    Variant1 {
+        #[rustc_then_this_would_need(type_of)] //~ ERROR OK
+        t: TypeAlias
+    },
+    Variant2(i32)
+}
+
+#[rustc_then_this_would_need(type_of)] //~ ERROR no path
+trait Trait {
+    #[rustc_then_this_would_need(fn_sig)] //~ ERROR OK
+    fn method(&self, _: TypeAlias);
+}
+
+struct SomeType;
+
+#[rustc_then_this_would_need(type_of)] //~ ERROR no path
+impl SomeType {
+    #[rustc_then_this_would_need(fn_sig)] //~ ERROR OK
+    #[rustc_then_this_would_need(typeck_tables_of)] //~ ERROR OK
+    fn method(&self, _: TypeAlias) {}
+}
+
+#[rustc_then_this_would_need(type_of)] //~ ERROR OK
+type TypeAlias2 = TypeAlias;
+
+#[rustc_then_this_would_need(fn_sig)] //~ ERROR OK
+#[rustc_then_this_would_need(typeck_tables_of)] //~ ERROR OK
+fn function(_: TypeAlias) {
+
+}
diff --git a/src/test/ui/dep-graph/dep-graph-type-alias.stderr b/src/test/ui/dep-graph/dep-graph-type-alias.stderr
new file mode 100644
index 0000000..393e4ba
--- /dev/null
+++ b/src/test/ui/dep-graph/dep-graph-type-alias.stderr
@@ -0,0 +1,74 @@
+error: no path from `TypeAlias` to `type_of`
+  --> $DIR/dep-graph-type-alias.rs:17:1
+   |
+LL | #[rustc_then_this_would_need(type_of)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: OK
+  --> $DIR/dep-graph-type-alias.rs:19:5
+   |
+LL |     #[rustc_then_this_would_need(type_of)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: no path from `TypeAlias` to `type_of`
+  --> $DIR/dep-graph-type-alias.rs:24:1
+   |
+LL | #[rustc_then_this_would_need(type_of)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: OK
+  --> $DIR/dep-graph-type-alias.rs:27:9
+   |
+LL |         #[rustc_then_this_would_need(type_of)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: no path from `TypeAlias` to `type_of`
+  --> $DIR/dep-graph-type-alias.rs:33:1
+   |
+LL | #[rustc_then_this_would_need(type_of)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: no path from `TypeAlias` to `type_of`
+  --> $DIR/dep-graph-type-alias.rs:41:1
+   |
+LL | #[rustc_then_this_would_need(type_of)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: OK
+  --> $DIR/dep-graph-type-alias.rs:48:1
+   |
+LL | #[rustc_then_this_would_need(type_of)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: OK
+  --> $DIR/dep-graph-type-alias.rs:51:1
+   |
+LL | #[rustc_then_this_would_need(fn_sig)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: OK
+  --> $DIR/dep-graph-type-alias.rs:52:1
+   |
+LL | #[rustc_then_this_would_need(typeck_tables_of)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: OK
+  --> $DIR/dep-graph-type-alias.rs:35:5
+   |
+LL |     #[rustc_then_this_would_need(fn_sig)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: OK
+  --> $DIR/dep-graph-type-alias.rs:43:5
+   |
+LL |     #[rustc_then_this_would_need(fn_sig)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: OK
+  --> $DIR/dep-graph-type-alias.rs:44:5
+   |
+LL |     #[rustc_then_this_would_need(typeck_tables_of)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 12 previous errors
+
diff --git a/src/test/ui/dep-graph/dep-graph-variance-alias.rs b/src/test/ui/dep-graph/dep-graph-variance-alias.rs
new file mode 100644
index 0000000..9564568
--- /dev/null
+++ b/src/test/ui/dep-graph/dep-graph-variance-alias.rs
@@ -0,0 +1,22 @@
+// Test that changing what a `type` points to does not go unnoticed
+// by the variance analysis.
+
+// compile-flags: -Z query-dep-graph
+
+#![feature(rustc_attrs)]
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+fn main() { }
+
+struct Foo<T> {
+    f: T
+}
+
+#[rustc_if_this_changed(Krate)]
+type TypeAlias<T> = Foo<T>;
+
+#[rustc_then_this_would_need(variances_of)] //~ ERROR OK
+struct Use<T> {
+    x: TypeAlias<T>
+}
diff --git a/src/test/ui/dep-graph/dep-graph-variance-alias.stderr b/src/test/ui/dep-graph/dep-graph-variance-alias.stderr
new file mode 100644
index 0000000..554ff45
--- /dev/null
+++ b/src/test/ui/dep-graph/dep-graph-variance-alias.stderr
@@ -0,0 +1,8 @@
+error: OK
+  --> $DIR/dep-graph-variance-alias.rs:19:1
+   |
+LL | #[rustc_then_this_would_need(variances_of)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/deprecation/atomic_initializers.fixed b/src/test/ui/deprecation/atomic_initializers.fixed
new file mode 100644
index 0000000..dee1d97
--- /dev/null
+++ b/src/test/ui/deprecation/atomic_initializers.fixed
@@ -0,0 +1,11 @@
+// run-rustfix
+// compile-pass
+
+#[allow(deprecated, unused_imports)]
+use std::sync::atomic::{AtomicIsize, ATOMIC_ISIZE_INIT};
+
+#[allow(dead_code)]
+static FOO: AtomicIsize = AtomicIsize::new(0);
+//~^ WARN use of deprecated item
+
+fn main() {}
diff --git a/src/test/ui/deprecation/atomic_initializers.rs b/src/test/ui/deprecation/atomic_initializers.rs
new file mode 100644
index 0000000..b9e25e8
--- /dev/null
+++ b/src/test/ui/deprecation/atomic_initializers.rs
@@ -0,0 +1,11 @@
+// run-rustfix
+// compile-pass
+
+#[allow(deprecated, unused_imports)]
+use std::sync::atomic::{AtomicIsize, ATOMIC_ISIZE_INIT};
+
+#[allow(dead_code)]
+static FOO: AtomicIsize = ATOMIC_ISIZE_INIT;
+//~^ WARN use of deprecated item
+
+fn main() {}
diff --git a/src/test/ui/deprecation/atomic_initializers.stderr b/src/test/ui/deprecation/atomic_initializers.stderr
new file mode 100644
index 0000000..b009ff9
--- /dev/null
+++ b/src/test/ui/deprecation/atomic_initializers.stderr
@@ -0,0 +1,8 @@
+warning: use of deprecated item 'std::sync::atomic::ATOMIC_ISIZE_INIT': the `new` function is now preferred
+  --> $DIR/atomic_initializers.rs:8:27
+   |
+LL | static FOO: AtomicIsize = ATOMIC_ISIZE_INIT;
+   |                           ^^^^^^^^^^^^^^^^^ help: replace the use of the deprecated item: `AtomicIsize::new(0)`
+   |
+   = note: #[warn(deprecated)] on by default
+
diff --git a/src/test/ui/deprecation/auxiliary/deprecation-lint.rs b/src/test/ui/deprecation/auxiliary/deprecation-lint.rs
new file mode 100644
index 0000000..948bf1c
--- /dev/null
+++ b/src/test/ui/deprecation/auxiliary/deprecation-lint.rs
@@ -0,0 +1,98 @@
+#![feature(deprecated)]
+
+#[deprecated(since = "1.0.0", note = "text")]
+pub fn deprecated() {}
+#[deprecated(since = "1.0.0", note = "text")]
+pub fn deprecated_text() {}
+
+pub struct MethodTester;
+
+impl MethodTester {
+    #[deprecated(since = "1.0.0", note = "text")]
+    pub fn method_deprecated(&self) {}
+    #[deprecated(since = "1.0.0", note = "text")]
+    pub fn method_deprecated_text(&self) {}
+}
+
+pub trait Trait {
+    #[deprecated(since = "1.0.0", note = "text")]
+    fn trait_deprecated(&self) {}
+    #[deprecated(since = "1.0.0", note = "text")]
+    fn trait_deprecated_text(&self) {}
+}
+
+#[deprecated(since = "1.0.0", note = "text")]
+pub trait DeprecatedTrait { fn dummy(&self) { } }
+
+impl Trait for MethodTester {}
+
+#[deprecated(since = "1.0.0", note = "text")]
+pub struct DeprecatedStruct {
+    pub i: isize
+}
+
+#[deprecated(since = "1.0.0", note = "text")]
+pub struct DeprecatedUnitStruct;
+
+pub enum Enum {
+    #[deprecated(since = "1.0.0", note = "text")]
+    DeprecatedVariant,
+}
+
+#[deprecated(since = "1.0.0", note = "text")]
+pub struct DeprecatedTupleStruct(pub isize);
+
+pub mod nested {
+    #[deprecated(since = "1.0.0", note = "text")]
+    pub struct DeprecatedStruct {
+        pub i: isize
+    }
+
+    #[deprecated(since = "1.0.0", note = "text")]
+    pub struct DeprecatedUnitStruct;
+
+    pub enum Enum {
+        #[deprecated(since = "1.0.0", note = "text")]
+        DeprecatedVariant,
+    }
+
+    #[deprecated(since = "1.0.0", note = "text")]
+    pub struct DeprecatedTupleStruct(pub isize);
+}
+
+pub struct Stable {
+    #[deprecated(since = "1.0.0", note = "text")]
+    pub override2: u8,
+}
+
+pub struct Stable2(pub u8, pub u8, #[deprecated(since = "1.0.0", note = "text")] pub u8);
+
+#[deprecated(since = "1.0.0", note = "text")]
+pub struct Deprecated {
+    pub inherit: u8,
+}
+
+#[deprecated(since = "1.0.0", note = "text")]
+pub struct Deprecated2(pub u8,
+                       pub u8,
+                       pub u8);
+
+#[deprecated(since = "1.0.0", note = "text")]
+pub mod deprecated_mod {
+    pub fn deprecated() {}
+}
+
+#[macro_export]
+macro_rules! macro_test {
+    () => (deprecated());
+}
+
+#[macro_export]
+macro_rules! macro_test_arg {
+    ($func:expr) => ($func);
+}
+
+#[macro_export]
+macro_rules! macro_test_arg_nested {
+    ($func:ident) => (macro_test_arg!($func()));
+}
diff --git a/src/test/ui/deprecation/deprecated-macro_escape-inner.rs b/src/test/ui/deprecation/deprecated-macro_escape-inner.rs
new file mode 100644
index 0000000..957e839
--- /dev/null
+++ b/src/test/ui/deprecation/deprecated-macro_escape-inner.rs
@@ -0,0 +1,8 @@
+// run-pass
+
+mod foo {
+    #![macro_escape] //~ WARNING macro_escape is a deprecated synonym for macro_use
+}
+
+fn main() {
+}
diff --git a/src/test/ui/deprecation/deprecated-macro_escape-inner.stderr b/src/test/ui/deprecation/deprecated-macro_escape-inner.stderr
new file mode 100644
index 0000000..a2cd196
--- /dev/null
+++ b/src/test/ui/deprecation/deprecated-macro_escape-inner.stderr
@@ -0,0 +1,8 @@
+warning: macro_escape is a deprecated synonym for macro_use
+  --> $DIR/deprecated-macro_escape-inner.rs:4:5
+   |
+LL |     #![macro_escape]
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: consider an outer attribute, #[macro_use] mod ...
+
diff --git a/src/test/ui/deprecation/deprecated-macro_escape.rs b/src/test/ui/deprecation/deprecated-macro_escape.rs
new file mode 100644
index 0000000..1b82a99
--- /dev/null
+++ b/src/test/ui/deprecation/deprecated-macro_escape.rs
@@ -0,0 +1,8 @@
+// run-pass
+
+#[macro_escape] //~ WARNING macro_escape is a deprecated synonym for macro_use
+mod foo {
+}
+
+fn main() {
+}
diff --git a/src/test/ui/deprecation/deprecated-macro_escape.stderr b/src/test/ui/deprecation/deprecated-macro_escape.stderr
new file mode 100644
index 0000000..b76d6d7
--- /dev/null
+++ b/src/test/ui/deprecation/deprecated-macro_escape.stderr
@@ -0,0 +1,6 @@
+warning: macro_escape is a deprecated synonym for macro_use
+  --> $DIR/deprecated-macro_escape.rs:3:1
+   |
+LL | #[macro_escape]
+   | ^^^^^^^^^^^^^^^
+
diff --git a/src/test/ui/deprecation/deprecated_no_stack_check.rs b/src/test/ui/deprecation/deprecated_no_stack_check.rs
new file mode 100644
index 0000000..8e1f5bb
--- /dev/null
+++ b/src/test/ui/deprecation/deprecated_no_stack_check.rs
@@ -0,0 +1,6 @@
+#![deny(warnings)]
+#![feature(no_stack_check)]
+//~^ ERROR: feature has been removed [E0557]
+fn main() {
+
+}
diff --git a/src/test/ui/deprecation/deprecated_no_stack_check.stderr b/src/test/ui/deprecation/deprecated_no_stack_check.stderr
new file mode 100644
index 0000000..c936a55
--- /dev/null
+++ b/src/test/ui/deprecation/deprecated_no_stack_check.stderr
@@ -0,0 +1,9 @@
+error[E0557]: feature has been removed
+  --> $DIR/deprecated_no_stack_check.rs:2:12
+   |
+LL | #![feature(no_stack_check)]
+   |            ^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0557`.
diff --git a/src/test/ui/deprecation/deprecation-in-future.rs b/src/test/ui/deprecation/deprecation-in-future.rs
new file mode 100644
index 0000000..138d902
--- /dev/null
+++ b/src/test/ui/deprecation/deprecation-in-future.rs
@@ -0,0 +1,14 @@
+// ignore-tidy-linelength
+
+// run-pass
+
+#![deny(deprecated_in_future)]
+
+#[deprecated(since = "99.99.99", note = "text")]
+pub fn deprecated_future() {}
+
+fn test() {
+    deprecated_future(); // ok; deprecated_in_future only applies to rustc_deprecated
+}
+
+fn main() {}
diff --git a/src/test/ui/deprecation/deprecation-in-future.stderr b/src/test/ui/deprecation/deprecation-in-future.stderr
new file mode 100644
index 0000000..81d2461
--- /dev/null
+++ b/src/test/ui/deprecation/deprecation-in-future.stderr
@@ -0,0 +1,8 @@
+warning: use of deprecated item 'deprecated_future': text
+  --> $DIR/deprecation-in-future.rs:11:5
+   |
+LL |     deprecated_future(); // ok; deprecated_in_future only applies to rustc_deprecated
+   |     ^^^^^^^^^^^^^^^^^
+   |
+   = note: #[warn(deprecated)] on by default
+
diff --git a/src/test/ui/deprecation/deprecation-in-staged-api.rs b/src/test/ui/deprecation/deprecation-in-staged-api.rs
new file mode 100644
index 0000000..bcc17c7
--- /dev/null
+++ b/src/test/ui/deprecation/deprecation-in-staged-api.rs
@@ -0,0 +1,8 @@
+// #[deprecated] can't be used in staged api
+
+#![feature(staged_api)]
+
+#![stable(feature = "stable_test_feature", since = "1.0.0")]
+
+#[deprecated]
+fn main() { } //~ERROR `#[deprecated]` cannot be used in staged api
diff --git a/src/test/ui/deprecation/deprecation-in-staged-api.stderr b/src/test/ui/deprecation/deprecation-in-staged-api.stderr
new file mode 100644
index 0000000..6a8056e
--- /dev/null
+++ b/src/test/ui/deprecation/deprecation-in-staged-api.stderr
@@ -0,0 +1,8 @@
+error: `#[deprecated]` cannot be used in staged api, use `#[rustc_deprecated]` instead
+  --> $DIR/deprecation-in-staged-api.rs:8:1
+   |
+LL | fn main() { }
+   | ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/deprecation/deprecation-lint-2.rs b/src/test/ui/deprecation/deprecation-lint-2.rs
new file mode 100644
index 0000000..2aa0d0c
--- /dev/null
+++ b/src/test/ui/deprecation/deprecation-lint-2.rs
@@ -0,0 +1,13 @@
+// aux-build:deprecation-lint.rs
+// error-pattern: use of deprecated item
+
+#![deny(deprecated)]
+
+#[macro_use]
+extern crate deprecation_lint;
+
+use deprecation_lint::*;
+
+fn main() {
+    macro_test!();
+}
diff --git a/src/test/ui/deprecation/deprecation-lint-2.stderr b/src/test/ui/deprecation/deprecation-lint-2.stderr
new file mode 100644
index 0000000..f90ca79
--- /dev/null
+++ b/src/test/ui/deprecation/deprecation-lint-2.stderr
@@ -0,0 +1,15 @@
+error: use of deprecated item 'deprecation_lint::deprecated': text
+  --> $DIR/deprecation-lint-2.rs:12:5
+   |
+LL |     macro_test!();
+   |     ^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/deprecation-lint-2.rs:4:9
+   |
+LL | #![deny(deprecated)]
+   |         ^^^^^^^^^^
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/deprecation/deprecation-lint-3.rs b/src/test/ui/deprecation/deprecation-lint-3.rs
new file mode 100644
index 0000000..ae2dd7a
--- /dev/null
+++ b/src/test/ui/deprecation/deprecation-lint-3.rs
@@ -0,0 +1,14 @@
+// aux-build:deprecation-lint.rs
+// error-pattern: use of deprecated item
+
+#![deny(deprecated)]
+#![allow(warnings)]
+
+#[macro_use]
+extern crate deprecation_lint;
+
+use deprecation_lint::*;
+
+fn main() {
+    macro_test_arg_nested!(deprecated_text);
+}
diff --git a/src/test/ui/deprecation/deprecation-lint-3.stderr b/src/test/ui/deprecation/deprecation-lint-3.stderr
new file mode 100644
index 0000000..fb90a63
--- /dev/null
+++ b/src/test/ui/deprecation/deprecation-lint-3.stderr
@@ -0,0 +1,15 @@
+error: use of deprecated item 'deprecation_lint::deprecated_text': text
+  --> $DIR/deprecation-lint-3.rs:13:5
+   |
+LL |     macro_test_arg_nested!(deprecated_text);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/deprecation-lint-3.rs:4:9
+   |
+LL | #![deny(deprecated)]
+   |         ^^^^^^^^^^
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/deprecation/deprecation-lint-nested.rs b/src/test/ui/deprecation/deprecation-lint-nested.rs
new file mode 100644
index 0000000..ee6f0a2
--- /dev/null
+++ b/src/test/ui/deprecation/deprecation-lint-nested.rs
@@ -0,0 +1,71 @@
+#![deny(deprecated)]
+#![allow(warnings)]
+
+#[deprecated]
+fn issue_35128() {
+    format_args!("foo");
+}
+
+#[deprecated]
+fn issue_35128_minimal() {
+    static FOO: &'static str = "foo";
+    let _ = FOO;
+}
+
+#[deprecated]
+mod silent {
+    type DeprecatedType = u8;
+    struct DeprecatedStruct;
+    fn deprecated_fn() {}
+    trait DeprecatedTrait {}
+    static DEPRECATED_STATIC: u8 = 0;
+    const DEPRECATED_CONST: u8 = 1;
+
+    struct Foo(DeprecatedType);
+
+    impl DeprecatedTrait for Foo {}
+
+    impl Foo {
+        fn bar<T: DeprecatedTrait>() {
+            deprecated_fn();
+        }
+    }
+
+    fn foo() -> u8 {
+        DEPRECATED_STATIC +
+        DEPRECATED_CONST
+    }
+}
+
+#[deprecated]
+mod loud {
+    #[deprecated]
+    type DeprecatedType = u8;
+    #[deprecated]
+    struct DeprecatedStruct;
+    #[deprecated]
+    fn deprecated_fn() {}
+    #[deprecated]
+    trait DeprecatedTrait {}
+    #[deprecated]
+    static DEPRECATED_STATIC: u8 = 0;
+    #[deprecated]
+    const DEPRECATED_CONST: u8 = 1;
+
+    struct Foo(DeprecatedType); //~ ERROR use of deprecated item
+
+    impl DeprecatedTrait for Foo {} //~ ERROR use of deprecated item
+
+    impl Foo {
+        fn bar<T: DeprecatedTrait>() { //~ ERROR use of deprecated item
+            deprecated_fn(); //~ ERROR use of deprecated item
+        }
+    }
+
+    fn foo() -> u8 {
+        DEPRECATED_STATIC + //~ ERROR use of deprecated item
+        DEPRECATED_CONST //~ ERROR use of deprecated item
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/deprecation/deprecation-lint-nested.stderr b/src/test/ui/deprecation/deprecation-lint-nested.stderr
new file mode 100644
index 0000000..206e12c
--- /dev/null
+++ b/src/test/ui/deprecation/deprecation-lint-nested.stderr
@@ -0,0 +1,44 @@
+error: use of deprecated item 'loud::DeprecatedType'
+  --> $DIR/deprecation-lint-nested.rs:55:16
+   |
+LL |     struct Foo(DeprecatedType);
+   |                ^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/deprecation-lint-nested.rs:1:9
+   |
+LL | #![deny(deprecated)]
+   |         ^^^^^^^^^^
+
+error: use of deprecated item 'loud::DeprecatedTrait'
+  --> $DIR/deprecation-lint-nested.rs:57:10
+   |
+LL |     impl DeprecatedTrait for Foo {}
+   |          ^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'loud::DEPRECATED_STATIC'
+  --> $DIR/deprecation-lint-nested.rs:66:9
+   |
+LL |         DEPRECATED_STATIC +
+   |         ^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'loud::DEPRECATED_CONST'
+  --> $DIR/deprecation-lint-nested.rs:67:9
+   |
+LL |         DEPRECATED_CONST
+   |         ^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'loud::DeprecatedTrait'
+  --> $DIR/deprecation-lint-nested.rs:60:19
+   |
+LL |         fn bar<T: DeprecatedTrait>() {
+   |                   ^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'loud::deprecated_fn'
+  --> $DIR/deprecation-lint-nested.rs:61:13
+   |
+LL |             deprecated_fn();
+   |             ^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/deprecation/deprecation-lint.rs b/src/test/ui/deprecation/deprecation-lint.rs
new file mode 100644
index 0000000..2627139
--- /dev/null
+++ b/src/test/ui/deprecation/deprecation-lint.rs
@@ -0,0 +1,436 @@
+// aux-build:deprecation-lint.rs
+// ignore-tidy-linelength
+
+#![deny(deprecated)]
+#![allow(warnings)]
+
+#[macro_use]
+extern crate deprecation_lint;
+
+mod cross_crate {
+    use deprecation_lint::*;
+
+    fn test() {
+        type Foo = MethodTester;
+        let foo = MethodTester;
+
+        deprecated(); //~ ERROR use of deprecated item 'deprecation_lint::deprecated'
+        foo.method_deprecated(); //~ ERROR use of deprecated item 'deprecation_lint::MethodTester::method_deprecated'
+        Foo::method_deprecated(&foo); //~ ERROR use of deprecated item 'deprecation_lint::MethodTester::method_deprecated'
+        <Foo>::method_deprecated(&foo); //~ ERROR use of deprecated item 'deprecation_lint::MethodTester::method_deprecated'
+        foo.trait_deprecated(); //~ ERROR use of deprecated item 'deprecation_lint::Trait::trait_deprecated'
+        Trait::trait_deprecated(&foo); //~ ERROR use of deprecated item 'deprecation_lint::Trait::trait_deprecated'
+        <Foo>::trait_deprecated(&foo); //~ ERROR use of deprecated item 'deprecation_lint::Trait::trait_deprecated'
+        <Foo as Trait>::trait_deprecated(&foo); //~ ERROR use of deprecated item 'deprecation_lint::Trait::trait_deprecated'
+
+        deprecated_text(); //~ ERROR use of deprecated item 'deprecation_lint::deprecated_text': text
+        foo.method_deprecated_text(); //~ ERROR use of deprecated item 'deprecation_lint::MethodTester::method_deprecated_text': text
+        Foo::method_deprecated_text(&foo); //~ ERROR use of deprecated item 'deprecation_lint::MethodTester::method_deprecated_text': text
+        <Foo>::method_deprecated_text(&foo); //~ ERROR use of deprecated item 'deprecation_lint::MethodTester::method_deprecated_text': text
+        foo.trait_deprecated_text(); //~ ERROR use of deprecated item 'deprecation_lint::Trait::trait_deprecated_text': text
+        Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated item 'deprecation_lint::Trait::trait_deprecated_text': text
+        <Foo>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item 'deprecation_lint::Trait::trait_deprecated_text': text
+        <Foo as Trait>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item 'deprecation_lint::Trait::trait_deprecated_text': text
+
+        let _ = DeprecatedStruct { //~ ERROR use of deprecated item 'deprecation_lint::DeprecatedStruct': text
+            i: 0 //~ ERROR use of deprecated item 'deprecation_lint::DeprecatedStruct::i': text
+        };
+
+        let _ = DeprecatedUnitStruct; //~ ERROR use of deprecated item 'deprecation_lint::DeprecatedUnitStruct': text
+
+        let _ = Enum::DeprecatedVariant; //~ ERROR use of deprecated item 'deprecation_lint::Enum::DeprecatedVariant': text
+
+        let _ = DeprecatedTupleStruct (1); //~ ERROR use of deprecated item 'deprecation_lint::DeprecatedTupleStruct': text
+
+        let _ = nested::DeprecatedStruct { //~ ERROR use of deprecated item 'deprecation_lint::nested::DeprecatedStruct': text
+            i: 0 //~ ERROR use of deprecated item 'deprecation_lint::nested::DeprecatedStruct::i': text
+        };
+
+        let _ = nested::DeprecatedUnitStruct; //~ ERROR use of deprecated item 'deprecation_lint::nested::DeprecatedUnitStruct': text
+
+        let _ = nested::Enum::DeprecatedVariant; //~ ERROR use of deprecated item 'deprecation_lint::nested::Enum::DeprecatedVariant': text
+
+        let _ = nested::DeprecatedTupleStruct (1); //~ ERROR use of deprecated item 'deprecation_lint::nested::DeprecatedTupleStruct': text
+
+        // At the moment, the lint checker only checks stability in
+        // in the arguments of macros.
+        // Eventually, we will want to lint the contents of the
+        // macro in the module *defining* it. Also, stability levels
+        // on macros themselves are not yet linted.
+        macro_test_arg!(deprecated_text()); //~ ERROR use of deprecated item 'deprecation_lint::deprecated_text': text
+        macro_test_arg!(macro_test_arg!(deprecated_text())); //~ ERROR use of deprecated item 'deprecation_lint::deprecated_text': text
+    }
+
+    fn test_method_param<Foo: Trait>(foo: Foo) {
+        foo.trait_deprecated(); //~ ERROR use of deprecated item 'deprecation_lint::Trait::trait_deprecated'
+        Trait::trait_deprecated(&foo); //~ ERROR use of deprecated item 'deprecation_lint::Trait::trait_deprecated'
+        <Foo>::trait_deprecated(&foo); //~ ERROR use of deprecated item 'deprecation_lint::Trait::trait_deprecated'
+        <Foo as Trait>::trait_deprecated(&foo); //~ ERROR use of deprecated item 'deprecation_lint::Trait::trait_deprecated'
+        foo.trait_deprecated_text(); //~ ERROR use of deprecated item 'deprecation_lint::Trait::trait_deprecated_text': text
+        Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated item 'deprecation_lint::Trait::trait_deprecated_text': text
+        <Foo>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item 'deprecation_lint::Trait::trait_deprecated_text': text
+        <Foo as Trait>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item 'deprecation_lint::Trait::trait_deprecated_text': text
+    }
+
+    fn test_method_object(foo: &Trait) {
+        foo.trait_deprecated(); //~ ERROR use of deprecated item 'deprecation_lint::Trait::trait_deprecated'
+        foo.trait_deprecated_text(); //~ ERROR use of deprecated item 'deprecation_lint::Trait::trait_deprecated_text': text
+    }
+
+    struct S;
+
+    impl DeprecatedTrait for S {} //~ ERROR use of deprecated item 'deprecation_lint::DeprecatedTrait': text
+    trait LocalTrait : DeprecatedTrait { } //~ ERROR use of deprecated item 'deprecation_lint::DeprecatedTrait': text
+
+    pub fn foo() {
+        let x = Stable {
+            override2: 3,
+            //~^ ERROR use of deprecated item 'deprecation_lint::Stable::override2': text
+        };
+
+        let _ = x.override2;
+        //~^ ERROR use of deprecated item 'deprecation_lint::Stable::override2': text
+
+        let Stable {
+            override2: _
+            //~^ ERROR use of deprecated item 'deprecation_lint::Stable::override2': text
+        } = x;
+        // all fine
+        let Stable { .. } = x;
+
+        let x = Stable2(1, 2, 3);
+
+        let _ = x.2;
+        //~^ ERROR use of deprecated item 'deprecation_lint::Stable2::2': text
+
+        let Stable2(_,
+                   _,
+                   _)
+            //~^ ERROR use of deprecated item 'deprecation_lint::Stable2::2': text
+            = x;
+        // all fine
+        let Stable2(..) = x;
+
+        let x = Deprecated {
+            //~^ ERROR use of deprecated item 'deprecation_lint::Deprecated': text
+            inherit: 1,
+            //~^ ERROR use of deprecated item 'deprecation_lint::Deprecated::inherit': text
+        };
+
+        let _ = x.inherit;
+        //~^ ERROR use of deprecated item 'deprecation_lint::Deprecated::inherit': text
+
+        let Deprecated {
+            //~^ ERROR use of deprecated item 'deprecation_lint::Deprecated': text
+            inherit: _,
+            //~^ ERROR use of deprecated item 'deprecation_lint::Deprecated::inherit': text
+        } = x;
+
+        let Deprecated
+            //~^ ERROR use of deprecated item 'deprecation_lint::Deprecated': text
+            { .. } = x;
+
+        let x = Deprecated2(1, 2, 3);
+        //~^ ERROR use of deprecated item 'deprecation_lint::Deprecated2': text
+
+        let _ = x.0;
+        //~^ ERROR use of deprecated item 'deprecation_lint::Deprecated2::0': text
+        let _ = x.1;
+        //~^ ERROR use of deprecated item 'deprecation_lint::Deprecated2::1': text
+        let _ = x.2;
+        //~^ ERROR use of deprecated item 'deprecation_lint::Deprecated2::2': text
+
+        let Deprecated2
+        //~^ ERROR use of deprecated item 'deprecation_lint::Deprecated2': text
+            (_,
+             //~^ ERROR use of deprecated item 'deprecation_lint::Deprecated2::0': text
+             _,
+             //~^ ERROR use of deprecated item 'deprecation_lint::Deprecated2::1': text
+             _)
+             //~^ ERROR use of deprecated item 'deprecation_lint::Deprecated2::2': text
+            = x;
+        let Deprecated2
+        //~^ ERROR use of deprecated item 'deprecation_lint::Deprecated2': text
+            // the patterns are all fine:
+            (..) = x;
+    }
+}
+
+mod inheritance {
+    use deprecation_lint::*;
+
+    fn test_inheritance() {
+        deprecated_mod::deprecated(); //~ ERROR use of deprecated item 'deprecation_lint::deprecated_mod::deprecated': text
+    }
+}
+
+mod this_crate {
+    #[deprecated(since = "1.0.0", note = "text")]
+    pub fn deprecated() {}
+    #[deprecated(since = "1.0.0", note = "text")]
+    pub fn deprecated_text() {}
+
+    #[deprecated(since = "99.99.99", note = "text")]
+    pub fn deprecated_future() {}
+    #[deprecated(since = "99.99.99", note = "text")]
+    pub fn deprecated_future_text() {}
+
+    pub struct MethodTester;
+
+    impl MethodTester {
+        #[deprecated(since = "1.0.0", note = "text")]
+        pub fn method_deprecated(&self) {}
+        #[deprecated(since = "1.0.0", note = "text")]
+        pub fn method_deprecated_text(&self) {}
+    }
+
+    pub trait Trait {
+        #[deprecated(since = "1.0.0", note = "text")]
+        fn trait_deprecated(&self) {}
+        #[deprecated(since = "1.0.0", note = "text")]
+        fn trait_deprecated_text(&self) {}
+    }
+
+    impl Trait for MethodTester {}
+
+    #[deprecated(since = "1.0.0", note = "text")]
+    pub struct DeprecatedStruct {
+        i: isize
+    }
+    pub struct UnstableStruct {
+        i: isize
+    }
+    pub struct StableStruct {
+        i: isize
+    }
+
+    #[deprecated(since = "1.0.0", note = "text")]
+    pub struct DeprecatedUnitStruct;
+
+    pub enum Enum {
+        #[deprecated(since = "1.0.0", note = "text")]
+        DeprecatedVariant,
+    }
+
+    #[deprecated(since = "1.0.0", note = "text")]
+    pub struct DeprecatedTupleStruct(isize);
+
+    mod nested {
+        #[deprecated(since = "1.0.0", note = "text")]
+        pub struct DeprecatedStruct {
+            i: isize
+        }
+
+        #[deprecated(since = "1.0.0", note = "text")]
+        pub struct DeprecatedUnitStruct;
+
+        pub enum Enum {
+            #[deprecated(since = "1.0.0", note = "text")]
+            DeprecatedVariant,
+        }
+
+        #[deprecated(since = "1.0.0", note = "text")]
+        pub struct DeprecatedTupleStruct(pub isize);
+    }
+
+    fn test() {
+        use self::nested;
+
+        // Only the deprecated cases of the following should generate
+        // errors, because other stability attributes now have meaning
+        // only *across* crates, not within a single crate.
+
+        type Foo = MethodTester;
+        let foo = MethodTester;
+
+        deprecated(); //~ ERROR use of deprecated item 'this_crate::deprecated'
+        foo.method_deprecated(); //~ ERROR use of deprecated item 'this_crate::MethodTester::method_deprecated'
+        Foo::method_deprecated(&foo); //~ ERROR use of deprecated item 'this_crate::MethodTester::method_deprecated'
+        <Foo>::method_deprecated(&foo); //~ ERROR use of deprecated item 'this_crate::MethodTester::method_deprecated'
+        foo.trait_deprecated(); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated'
+        Trait::trait_deprecated(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated'
+        <Foo>::trait_deprecated(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated'
+        <Foo as Trait>::trait_deprecated(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated'
+
+        deprecated_text(); //~ ERROR use of deprecated item 'this_crate::deprecated_text': text
+        foo.method_deprecated_text(); //~ ERROR use of deprecated item 'this_crate::MethodTester::method_deprecated_text': text
+        Foo::method_deprecated_text(&foo); //~ ERROR use of deprecated item 'this_crate::MethodTester::method_deprecated_text': text
+        <Foo>::method_deprecated_text(&foo); //~ ERROR use of deprecated item 'this_crate::MethodTester::method_deprecated_text': text
+        foo.trait_deprecated_text(); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+        Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+        <Foo>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+        <Foo as Trait>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+
+        // Future deprecations are only permitted for rustc_deprecated.
+        deprecated_future(); //~ ERROR use of deprecated item
+        deprecated_future_text(); //~ ERROR use of deprecated item
+
+        let _ = DeprecatedStruct {
+            //~^ ERROR use of deprecated item 'this_crate::DeprecatedStruct': text
+            i: 0 //~ ERROR use of deprecated item 'this_crate::DeprecatedStruct::i': text
+        };
+
+        let _ = DeprecatedUnitStruct; //~ ERROR use of deprecated item 'this_crate::DeprecatedUnitStruct': text
+
+        let _ = Enum::DeprecatedVariant; //~ ERROR use of deprecated item 'this_crate::Enum::DeprecatedVariant': text
+
+        let _ = DeprecatedTupleStruct (1); //~ ERROR use of deprecated item 'this_crate::DeprecatedTupleStruct': text
+
+        let _ = nested::DeprecatedStruct {
+            //~^ ERROR use of deprecated item 'this_crate::nested::DeprecatedStruct': text
+            i: 0 //~ ERROR use of deprecated item 'this_crate::nested::DeprecatedStruct::i': text
+        };
+
+        let _ = nested::DeprecatedUnitStruct; //~ ERROR use of deprecated item 'this_crate::nested::DeprecatedUnitStruct': text
+
+        let _ = nested::Enum::DeprecatedVariant; //~ ERROR use of deprecated item 'this_crate::nested::Enum::DeprecatedVariant': text
+
+        let _ = nested::DeprecatedTupleStruct (1); //~ ERROR use of deprecated item 'this_crate::nested::DeprecatedTupleStruct': text
+    }
+
+    fn test_method_param<Foo: Trait>(foo: Foo) {
+        foo.trait_deprecated(); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated'
+        Trait::trait_deprecated(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated'
+        <Foo>::trait_deprecated(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated'
+        <Foo as Trait>::trait_deprecated(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated'
+        foo.trait_deprecated_text(); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+        Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+        <Foo>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+        <Foo as Trait>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+    }
+
+    fn test_method_object(foo: &Trait) {
+        foo.trait_deprecated(); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated'
+        foo.trait_deprecated_text(); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+    }
+
+    #[deprecated(since = "1.0.0", note = "text")]
+    fn test_fn_body() {
+        fn fn_in_body() {}
+        fn_in_body();
+    }
+
+    fn test_fn_closure_body() {
+        let _ = || {
+            #[deprecated]
+            fn bar() { }
+            bar(); //~ ERROR use of deprecated item 'this_crate::test_fn_closure_body::{{closure}}#0::bar'
+        };
+    }
+
+    impl MethodTester {
+        #[deprecated(since = "1.0.0", note = "text")]
+        fn test_method_body(&self) {
+            fn fn_in_body() {}
+            fn_in_body();
+        }
+    }
+
+    #[deprecated(since = "1.0.0", note = "text")]
+    pub trait DeprecatedTrait {
+        fn dummy(&self) { }
+    }
+
+    struct S;
+
+    impl DeprecatedTrait for S { } //~ ERROR use of deprecated item 'this_crate::DeprecatedTrait': text
+
+    trait LocalTrait : DeprecatedTrait { } //~ ERROR use of deprecated item 'this_crate::DeprecatedTrait': text
+}
+
+mod this_crate2 {
+    struct Stable {
+        #[deprecated(since = "1.0.0", note = "text")]
+        override2: u8,
+    }
+
+    struct Stable2(u8,
+                   u8,
+                   #[deprecated(since = "1.0.0", note = "text")] u8);
+
+    #[deprecated(since = "1.0.0", note = "text")]
+    struct Deprecated {
+        inherit: u8,
+    }
+
+    #[deprecated(since = "1.0.0", note = "text")]
+    struct Deprecated2(u8,
+                       u8,
+                       u8);
+
+    pub fn foo() {
+        let x = Stable {
+            override2: 3,
+            //~^ ERROR use of deprecated item 'this_crate2::Stable::override2': text
+        };
+
+        let _ = x.override2;
+        //~^ ERROR use of deprecated item 'this_crate2::Stable::override2': text
+
+        let Stable {
+            override2: _
+            //~^ ERROR use of deprecated item 'this_crate2::Stable::override2': text
+        } = x;
+        // all fine
+        let Stable { .. } = x;
+
+        let x = Stable2(1, 2, 3);
+
+        let _ = x.2;
+        //~^ ERROR use of deprecated item 'this_crate2::Stable2::2': text
+
+        let Stable2(_,
+                   _,
+                   _)
+            //~^ ERROR use of deprecated item 'this_crate2::Stable2::2': text
+            = x;
+        // all fine
+        let Stable2(..) = x;
+
+        let x = Deprecated {
+            //~^ ERROR use of deprecated item 'this_crate2::Deprecated': text
+            inherit: 1,
+            //~^ ERROR use of deprecated item 'this_crate2::Deprecated::inherit': text
+        };
+
+        let _ = x.inherit;
+        //~^ ERROR use of deprecated item 'this_crate2::Deprecated::inherit': text
+
+        let Deprecated {
+            //~^ ERROR use of deprecated item 'this_crate2::Deprecated': text
+            inherit: _,
+            //~^ ERROR use of deprecated item 'this_crate2::Deprecated::inherit': text
+        } = x;
+
+        let Deprecated
+            //~^ ERROR use of deprecated item 'this_crate2::Deprecated': text
+            // the patterns are all fine:
+            { .. } = x;
+
+        let x = Deprecated2(1, 2, 3);
+        //~^ ERROR use of deprecated item 'this_crate2::Deprecated2': text
+
+        let _ = x.0;
+        //~^ ERROR use of deprecated item 'this_crate2::Deprecated2::0': text
+        let _ = x.1;
+        //~^ ERROR use of deprecated item 'this_crate2::Deprecated2::1': text
+        let _ = x.2;
+        //~^ ERROR use of deprecated item 'this_crate2::Deprecated2::2': text
+
+        let Deprecated2
+        //~^ ERROR use of deprecated item 'this_crate2::Deprecated2': text
+            (_,
+             //~^ ERROR use of deprecated item 'this_crate2::Deprecated2::0': text
+             _,
+             //~^ ERROR use of deprecated item 'this_crate2::Deprecated2::1': text
+             _)
+            //~^ ERROR use of deprecated item 'this_crate2::Deprecated2::2': text
+            = x;
+        let Deprecated2
+        //~^ ERROR use of deprecated item 'this_crate2::Deprecated2': text
+            // the patterns are all fine:
+            (..) = x;
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/deprecation/deprecation-lint.stderr b/src/test/ui/deprecation/deprecation-lint.stderr
new file mode 100644
index 0000000..ffbcb25
--- /dev/null
+++ b/src/test/ui/deprecation/deprecation-lint.stderr
@@ -0,0 +1,740 @@
+error: use of deprecated item 'deprecation_lint::deprecated': text
+  --> $DIR/deprecation-lint.rs:17:9
+   |
+LL |         deprecated();
+   |         ^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/deprecation-lint.rs:4:9
+   |
+LL | #![deny(deprecated)]
+   |         ^^^^^^^^^^
+
+error: use of deprecated item 'deprecation_lint::Trait::trait_deprecated': text
+  --> $DIR/deprecation-lint.rs:22:9
+   |
+LL |         Trait::trait_deprecated(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'deprecation_lint::Trait::trait_deprecated': text
+  --> $DIR/deprecation-lint.rs:24:9
+   |
+LL |         <Foo as Trait>::trait_deprecated(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'deprecation_lint::deprecated_text': text
+  --> $DIR/deprecation-lint.rs:26:9
+   |
+LL |         deprecated_text();
+   |         ^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'deprecation_lint::Trait::trait_deprecated_text': text
+  --> $DIR/deprecation-lint.rs:31:9
+   |
+LL |         Trait::trait_deprecated_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'deprecation_lint::Trait::trait_deprecated_text': text
+  --> $DIR/deprecation-lint.rs:33:9
+   |
+LL |         <Foo as Trait>::trait_deprecated_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'deprecation_lint::DeprecatedStruct': text
+  --> $DIR/deprecation-lint.rs:35:17
+   |
+LL |         let _ = DeprecatedStruct {
+   |                 ^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'deprecation_lint::DeprecatedUnitStruct': text
+  --> $DIR/deprecation-lint.rs:39:17
+   |
+LL |         let _ = DeprecatedUnitStruct;
+   |                 ^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'deprecation_lint::Enum::DeprecatedVariant': text
+  --> $DIR/deprecation-lint.rs:41:17
+   |
+LL |         let _ = Enum::DeprecatedVariant;
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'deprecation_lint::DeprecatedTupleStruct': text
+  --> $DIR/deprecation-lint.rs:43:17
+   |
+LL |         let _ = DeprecatedTupleStruct (1);
+   |                 ^^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'deprecation_lint::nested::DeprecatedStruct': text
+  --> $DIR/deprecation-lint.rs:45:17
+   |
+LL |         let _ = nested::DeprecatedStruct {
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'deprecation_lint::nested::DeprecatedUnitStruct': text
+  --> $DIR/deprecation-lint.rs:49:17
+   |
+LL |         let _ = nested::DeprecatedUnitStruct;
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'deprecation_lint::nested::Enum::DeprecatedVariant': text
+  --> $DIR/deprecation-lint.rs:51:17
+   |
+LL |         let _ = nested::Enum::DeprecatedVariant;
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'deprecation_lint::nested::DeprecatedTupleStruct': text
+  --> $DIR/deprecation-lint.rs:53:17
+   |
+LL |         let _ = nested::DeprecatedTupleStruct (1);
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'deprecation_lint::deprecated_text': text
+  --> $DIR/deprecation-lint.rs:60:25
+   |
+LL |         macro_test_arg!(deprecated_text());
+   |                         ^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'deprecation_lint::deprecated_text': text
+  --> $DIR/deprecation-lint.rs:61:41
+   |
+LL |         macro_test_arg!(macro_test_arg!(deprecated_text()));
+   |                                         ^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'deprecation_lint::Trait::trait_deprecated': text
+  --> $DIR/deprecation-lint.rs:66:9
+   |
+LL |         Trait::trait_deprecated(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'deprecation_lint::Trait::trait_deprecated': text
+  --> $DIR/deprecation-lint.rs:68:9
+   |
+LL |         <Foo as Trait>::trait_deprecated(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'deprecation_lint::Trait::trait_deprecated_text': text
+  --> $DIR/deprecation-lint.rs:70:9
+   |
+LL |         Trait::trait_deprecated_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'deprecation_lint::Trait::trait_deprecated_text': text
+  --> $DIR/deprecation-lint.rs:72:9
+   |
+LL |         <Foo as Trait>::trait_deprecated_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'deprecation_lint::DeprecatedTrait': text
+  --> $DIR/deprecation-lint.rs:82:10
+   |
+LL |     impl DeprecatedTrait for S {}
+   |          ^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'deprecation_lint::DeprecatedTrait': text
+  --> $DIR/deprecation-lint.rs:83:24
+   |
+LL |     trait LocalTrait : DeprecatedTrait { }
+   |                        ^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'deprecation_lint::Deprecated': text
+  --> $DIR/deprecation-lint.rs:114:17
+   |
+LL |         let x = Deprecated {
+   |                 ^^^^^^^^^^
+
+error: use of deprecated item 'deprecation_lint::Deprecated': text
+  --> $DIR/deprecation-lint.rs:123:13
+   |
+LL |         let Deprecated {
+   |             ^^^^^^^^^^
+
+error: use of deprecated item 'deprecation_lint::Deprecated': text
+  --> $DIR/deprecation-lint.rs:129:13
+   |
+LL |         let Deprecated
+   |             ^^^^^^^^^^
+
+error: use of deprecated item 'deprecation_lint::Deprecated2': text
+  --> $DIR/deprecation-lint.rs:133:17
+   |
+LL |         let x = Deprecated2(1, 2, 3);
+   |                 ^^^^^^^^^^^
+
+error: use of deprecated item 'deprecation_lint::Deprecated2': text
+  --> $DIR/deprecation-lint.rs:143:13
+   |
+LL |         let Deprecated2
+   |             ^^^^^^^^^^^
+
+error: use of deprecated item 'deprecation_lint::Deprecated2': text
+  --> $DIR/deprecation-lint.rs:152:13
+   |
+LL |         let Deprecated2
+   |             ^^^^^^^^^^^
+
+error: use of deprecated item 'deprecation_lint::deprecated_mod::deprecated': text
+  --> $DIR/deprecation-lint.rs:163:9
+   |
+LL |         deprecated_mod::deprecated();
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::deprecated': text
+  --> $DIR/deprecation-lint.rs:246:9
+   |
+LL |         deprecated();
+   |         ^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::Trait::trait_deprecated': text
+  --> $DIR/deprecation-lint.rs:251:9
+   |
+LL |         Trait::trait_deprecated(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::Trait::trait_deprecated': text
+  --> $DIR/deprecation-lint.rs:253:9
+   |
+LL |         <Foo as Trait>::trait_deprecated(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::deprecated_text': text
+  --> $DIR/deprecation-lint.rs:255:9
+   |
+LL |         deprecated_text();
+   |         ^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+  --> $DIR/deprecation-lint.rs:260:9
+   |
+LL |         Trait::trait_deprecated_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+  --> $DIR/deprecation-lint.rs:262:9
+   |
+LL |         <Foo as Trait>::trait_deprecated_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::deprecated_future': text
+  --> $DIR/deprecation-lint.rs:265:9
+   |
+LL |         deprecated_future();
+   |         ^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::deprecated_future_text': text
+  --> $DIR/deprecation-lint.rs:266:9
+   |
+LL |         deprecated_future_text();
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::DeprecatedStruct': text
+  --> $DIR/deprecation-lint.rs:268:17
+   |
+LL |         let _ = DeprecatedStruct {
+   |                 ^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::DeprecatedUnitStruct': text
+  --> $DIR/deprecation-lint.rs:273:17
+   |
+LL |         let _ = DeprecatedUnitStruct;
+   |                 ^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::Enum::DeprecatedVariant': text
+  --> $DIR/deprecation-lint.rs:275:17
+   |
+LL |         let _ = Enum::DeprecatedVariant;
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::DeprecatedTupleStruct': text
+  --> $DIR/deprecation-lint.rs:277:17
+   |
+LL |         let _ = DeprecatedTupleStruct (1);
+   |                 ^^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::nested::DeprecatedStruct': text
+  --> $DIR/deprecation-lint.rs:279:17
+   |
+LL |         let _ = nested::DeprecatedStruct {
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::nested::DeprecatedUnitStruct': text
+  --> $DIR/deprecation-lint.rs:284:17
+   |
+LL |         let _ = nested::DeprecatedUnitStruct;
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::nested::Enum::DeprecatedVariant': text
+  --> $DIR/deprecation-lint.rs:286:17
+   |
+LL |         let _ = nested::Enum::DeprecatedVariant;
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::nested::DeprecatedTupleStruct': text
+  --> $DIR/deprecation-lint.rs:288:17
+   |
+LL |         let _ = nested::DeprecatedTupleStruct (1);
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::Trait::trait_deprecated': text
+  --> $DIR/deprecation-lint.rs:293:9
+   |
+LL |         Trait::trait_deprecated(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::Trait::trait_deprecated': text
+  --> $DIR/deprecation-lint.rs:295:9
+   |
+LL |         <Foo as Trait>::trait_deprecated(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+  --> $DIR/deprecation-lint.rs:297:9
+   |
+LL |         Trait::trait_deprecated_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+  --> $DIR/deprecation-lint.rs:299:9
+   |
+LL |         <Foo as Trait>::trait_deprecated_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::test_fn_closure_body::{{closure}}#0::bar'
+  --> $DIR/deprecation-lint.rs:317:13
+   |
+LL |             bar();
+   |             ^^^
+
+error: use of deprecated item 'this_crate::DeprecatedTrait': text
+  --> $DIR/deprecation-lint.rs:336:10
+   |
+LL |     impl DeprecatedTrait for S { }
+   |          ^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::DeprecatedTrait': text
+  --> $DIR/deprecation-lint.rs:338:24
+   |
+LL |     trait LocalTrait : DeprecatedTrait { }
+   |                        ^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate2::Deprecated': text
+  --> $DIR/deprecation-lint.rs:390:17
+   |
+LL |         let x = Deprecated {
+   |                 ^^^^^^^^^^
+
+error: use of deprecated item 'this_crate2::Deprecated': text
+  --> $DIR/deprecation-lint.rs:399:13
+   |
+LL |         let Deprecated {
+   |             ^^^^^^^^^^
+
+error: use of deprecated item 'this_crate2::Deprecated': text
+  --> $DIR/deprecation-lint.rs:405:13
+   |
+LL |         let Deprecated
+   |             ^^^^^^^^^^
+
+error: use of deprecated item 'this_crate2::Deprecated2': text
+  --> $DIR/deprecation-lint.rs:410:17
+   |
+LL |         let x = Deprecated2(1, 2, 3);
+   |                 ^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate2::Deprecated2': text
+  --> $DIR/deprecation-lint.rs:420:13
+   |
+LL |         let Deprecated2
+   |             ^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate2::Deprecated2': text
+  --> $DIR/deprecation-lint.rs:429:13
+   |
+LL |         let Deprecated2
+   |             ^^^^^^^^^^^
+
+error: use of deprecated item 'deprecation_lint::MethodTester::method_deprecated': text
+  --> $DIR/deprecation-lint.rs:18:13
+   |
+LL |         foo.method_deprecated();
+   |             ^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'deprecation_lint::MethodTester::method_deprecated': text
+  --> $DIR/deprecation-lint.rs:19:9
+   |
+LL |         Foo::method_deprecated(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'deprecation_lint::MethodTester::method_deprecated': text
+  --> $DIR/deprecation-lint.rs:20:9
+   |
+LL |         <Foo>::method_deprecated(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'deprecation_lint::Trait::trait_deprecated': text
+  --> $DIR/deprecation-lint.rs:21:13
+   |
+LL |         foo.trait_deprecated();
+   |             ^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'deprecation_lint::Trait::trait_deprecated': text
+  --> $DIR/deprecation-lint.rs:23:9
+   |
+LL |         <Foo>::trait_deprecated(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'deprecation_lint::MethodTester::method_deprecated_text': text
+  --> $DIR/deprecation-lint.rs:27:13
+   |
+LL |         foo.method_deprecated_text();
+   |             ^^^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'deprecation_lint::MethodTester::method_deprecated_text': text
+  --> $DIR/deprecation-lint.rs:28:9
+   |
+LL |         Foo::method_deprecated_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'deprecation_lint::MethodTester::method_deprecated_text': text
+  --> $DIR/deprecation-lint.rs:29:9
+   |
+LL |         <Foo>::method_deprecated_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'deprecation_lint::Trait::trait_deprecated_text': text
+  --> $DIR/deprecation-lint.rs:30:13
+   |
+LL |         foo.trait_deprecated_text();
+   |             ^^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'deprecation_lint::Trait::trait_deprecated_text': text
+  --> $DIR/deprecation-lint.rs:32:9
+   |
+LL |         <Foo>::trait_deprecated_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'deprecation_lint::DeprecatedStruct::i': text
+  --> $DIR/deprecation-lint.rs:36:13
+   |
+LL |             i: 0
+   |             ^^^^
+
+error: use of deprecated item 'deprecation_lint::nested::DeprecatedStruct::i': text
+  --> $DIR/deprecation-lint.rs:46:13
+   |
+LL |             i: 0
+   |             ^^^^
+
+error: use of deprecated item 'deprecation_lint::Trait::trait_deprecated': text
+  --> $DIR/deprecation-lint.rs:65:13
+   |
+LL |         foo.trait_deprecated();
+   |             ^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'deprecation_lint::Trait::trait_deprecated': text
+  --> $DIR/deprecation-lint.rs:67:9
+   |
+LL |         <Foo>::trait_deprecated(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'deprecation_lint::Trait::trait_deprecated_text': text
+  --> $DIR/deprecation-lint.rs:69:13
+   |
+LL |         foo.trait_deprecated_text();
+   |             ^^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'deprecation_lint::Trait::trait_deprecated_text': text
+  --> $DIR/deprecation-lint.rs:71:9
+   |
+LL |         <Foo>::trait_deprecated_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'deprecation_lint::Trait::trait_deprecated': text
+  --> $DIR/deprecation-lint.rs:76:13
+   |
+LL |         foo.trait_deprecated();
+   |             ^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'deprecation_lint::Trait::trait_deprecated_text': text
+  --> $DIR/deprecation-lint.rs:77:13
+   |
+LL |         foo.trait_deprecated_text();
+   |             ^^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'deprecation_lint::Stable::override2': text
+  --> $DIR/deprecation-lint.rs:87:13
+   |
+LL |             override2: 3,
+   |             ^^^^^^^^^^^^
+
+error: use of deprecated item 'deprecation_lint::Stable::override2': text
+  --> $DIR/deprecation-lint.rs:91:17
+   |
+LL |         let _ = x.override2;
+   |                 ^^^^^^^^^^^
+
+error: use of deprecated item 'deprecation_lint::Stable::override2': text
+  --> $DIR/deprecation-lint.rs:95:13
+   |
+LL |             override2: _
+   |             ^^^^^^^^^^^^
+
+error: use of deprecated item 'deprecation_lint::Stable2::2': text
+  --> $DIR/deprecation-lint.rs:103:17
+   |
+LL |         let _ = x.2;
+   |                 ^^^
+
+error: use of deprecated item 'deprecation_lint::Stable2::2': text
+  --> $DIR/deprecation-lint.rs:108:20
+   |
+LL |                    _)
+   |                    ^
+
+error: use of deprecated item 'deprecation_lint::Deprecated::inherit': text
+  --> $DIR/deprecation-lint.rs:116:13
+   |
+LL |             inherit: 1,
+   |             ^^^^^^^^^^
+
+error: use of deprecated item 'deprecation_lint::Deprecated::inherit': text
+  --> $DIR/deprecation-lint.rs:120:17
+   |
+LL |         let _ = x.inherit;
+   |                 ^^^^^^^^^
+
+error: use of deprecated item 'deprecation_lint::Deprecated::inherit': text
+  --> $DIR/deprecation-lint.rs:125:13
+   |
+LL |             inherit: _,
+   |             ^^^^^^^^^^
+
+error: use of deprecated item 'deprecation_lint::Deprecated2::0': text
+  --> $DIR/deprecation-lint.rs:136:17
+   |
+LL |         let _ = x.0;
+   |                 ^^^
+
+error: use of deprecated item 'deprecation_lint::Deprecated2::1': text
+  --> $DIR/deprecation-lint.rs:138:17
+   |
+LL |         let _ = x.1;
+   |                 ^^^
+
+error: use of deprecated item 'deprecation_lint::Deprecated2::2': text
+  --> $DIR/deprecation-lint.rs:140:17
+   |
+LL |         let _ = x.2;
+   |                 ^^^
+
+error: use of deprecated item 'deprecation_lint::Deprecated2::0': text
+  --> $DIR/deprecation-lint.rs:145:14
+   |
+LL |             (_,
+   |              ^
+
+error: use of deprecated item 'deprecation_lint::Deprecated2::1': text
+  --> $DIR/deprecation-lint.rs:147:14
+   |
+LL |              _,
+   |              ^
+
+error: use of deprecated item 'deprecation_lint::Deprecated2::2': text
+  --> $DIR/deprecation-lint.rs:149:14
+   |
+LL |              _)
+   |              ^
+
+error: use of deprecated item 'this_crate::MethodTester::method_deprecated': text
+  --> $DIR/deprecation-lint.rs:247:13
+   |
+LL |         foo.method_deprecated();
+   |             ^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::MethodTester::method_deprecated': text
+  --> $DIR/deprecation-lint.rs:248:9
+   |
+LL |         Foo::method_deprecated(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::MethodTester::method_deprecated': text
+  --> $DIR/deprecation-lint.rs:249:9
+   |
+LL |         <Foo>::method_deprecated(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::Trait::trait_deprecated': text
+  --> $DIR/deprecation-lint.rs:250:13
+   |
+LL |         foo.trait_deprecated();
+   |             ^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::Trait::trait_deprecated': text
+  --> $DIR/deprecation-lint.rs:252:9
+   |
+LL |         <Foo>::trait_deprecated(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::MethodTester::method_deprecated_text': text
+  --> $DIR/deprecation-lint.rs:256:13
+   |
+LL |         foo.method_deprecated_text();
+   |             ^^^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::MethodTester::method_deprecated_text': text
+  --> $DIR/deprecation-lint.rs:257:9
+   |
+LL |         Foo::method_deprecated_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::MethodTester::method_deprecated_text': text
+  --> $DIR/deprecation-lint.rs:258:9
+   |
+LL |         <Foo>::method_deprecated_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+  --> $DIR/deprecation-lint.rs:259:13
+   |
+LL |         foo.trait_deprecated_text();
+   |             ^^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+  --> $DIR/deprecation-lint.rs:261:9
+   |
+LL |         <Foo>::trait_deprecated_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::DeprecatedStruct::i': text
+  --> $DIR/deprecation-lint.rs:270:13
+   |
+LL |             i: 0
+   |             ^^^^
+
+error: use of deprecated item 'this_crate::nested::DeprecatedStruct::i': text
+  --> $DIR/deprecation-lint.rs:281:13
+   |
+LL |             i: 0
+   |             ^^^^
+
+error: use of deprecated item 'this_crate::Trait::trait_deprecated': text
+  --> $DIR/deprecation-lint.rs:292:13
+   |
+LL |         foo.trait_deprecated();
+   |             ^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::Trait::trait_deprecated': text
+  --> $DIR/deprecation-lint.rs:294:9
+   |
+LL |         <Foo>::trait_deprecated(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+  --> $DIR/deprecation-lint.rs:296:13
+   |
+LL |         foo.trait_deprecated_text();
+   |             ^^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+  --> $DIR/deprecation-lint.rs:298:9
+   |
+LL |         <Foo>::trait_deprecated_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::Trait::trait_deprecated': text
+  --> $DIR/deprecation-lint.rs:303:13
+   |
+LL |         foo.trait_deprecated();
+   |             ^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+  --> $DIR/deprecation-lint.rs:304:13
+   |
+LL |         foo.trait_deprecated_text();
+   |             ^^^^^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate2::Stable::override2': text
+  --> $DIR/deprecation-lint.rs:363:13
+   |
+LL |             override2: 3,
+   |             ^^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate2::Stable::override2': text
+  --> $DIR/deprecation-lint.rs:367:17
+   |
+LL |         let _ = x.override2;
+   |                 ^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate2::Stable::override2': text
+  --> $DIR/deprecation-lint.rs:371:13
+   |
+LL |             override2: _
+   |             ^^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate2::Stable2::2': text
+  --> $DIR/deprecation-lint.rs:379:17
+   |
+LL |         let _ = x.2;
+   |                 ^^^
+
+error: use of deprecated item 'this_crate2::Stable2::2': text
+  --> $DIR/deprecation-lint.rs:384:20
+   |
+LL |                    _)
+   |                    ^
+
+error: use of deprecated item 'this_crate2::Deprecated::inherit': text
+  --> $DIR/deprecation-lint.rs:392:13
+   |
+LL |             inherit: 1,
+   |             ^^^^^^^^^^
+
+error: use of deprecated item 'this_crate2::Deprecated::inherit': text
+  --> $DIR/deprecation-lint.rs:396:17
+   |
+LL |         let _ = x.inherit;
+   |                 ^^^^^^^^^
+
+error: use of deprecated item 'this_crate2::Deprecated::inherit': text
+  --> $DIR/deprecation-lint.rs:401:13
+   |
+LL |             inherit: _,
+   |             ^^^^^^^^^^
+
+error: use of deprecated item 'this_crate2::Deprecated2::0': text
+  --> $DIR/deprecation-lint.rs:413:17
+   |
+LL |         let _ = x.0;
+   |                 ^^^
+
+error: use of deprecated item 'this_crate2::Deprecated2::1': text
+  --> $DIR/deprecation-lint.rs:415:17
+   |
+LL |         let _ = x.1;
+   |                 ^^^
+
+error: use of deprecated item 'this_crate2::Deprecated2::2': text
+  --> $DIR/deprecation-lint.rs:417:17
+   |
+LL |         let _ = x.2;
+   |                 ^^^
+
+error: use of deprecated item 'this_crate2::Deprecated2::0': text
+  --> $DIR/deprecation-lint.rs:422:14
+   |
+LL |             (_,
+   |              ^
+
+error: use of deprecated item 'this_crate2::Deprecated2::1': text
+  --> $DIR/deprecation-lint.rs:424:14
+   |
+LL |              _,
+   |              ^
+
+error: use of deprecated item 'this_crate2::Deprecated2::2': text
+  --> $DIR/deprecation-lint.rs:426:14
+   |
+LL |              _)
+   |              ^
+
+error: aborting due to 122 previous errors
+
diff --git a/src/test/ui/deprecation/deprecation-sanity.rs b/src/test/ui/deprecation/deprecation-sanity.rs
new file mode 100644
index 0000000..a559908
--- /dev/null
+++ b/src/test/ui/deprecation/deprecation-sanity.rs
@@ -0,0 +1,33 @@
+// Various checks that deprecation attributes are used correctly
+
+mod bogus_attribute_types_1 {
+    #[deprecated(since = "a", note = "a", reason)] //~ ERROR unknown meta item 'reason'
+    fn f1() { }
+
+    #[deprecated(since = "a", note)] //~ ERROR incorrect meta item
+    fn f2() { }
+
+    #[deprecated(since, note = "a")] //~ ERROR incorrect meta item
+    fn f3() { }
+
+    #[deprecated(since = "a", note(b))] //~ ERROR incorrect meta item
+    fn f5() { }
+
+    #[deprecated(since(b), note = "a")] //~ ERROR incorrect meta item
+    fn f6() { }
+
+    #[deprecated(note = b"test")] //~ ERROR literal in `deprecated` value must be a string
+    fn f7() { }
+
+    #[deprecated("test")] //~ ERROR item in `deprecated` must be a key/value pair
+    fn f8() { }
+}
+
+#[deprecated(since = "a", note = "b")]
+#[deprecated(since = "a", note = "b")]
+fn multiple1() { } //~ ERROR multiple deprecated attributes
+
+#[deprecated(since = "a", since = "b", note = "c")] //~ ERROR multiple 'since' items
+fn f1() { }
+
+fn main() { }
diff --git a/src/test/ui/deprecation/deprecation-sanity.stderr b/src/test/ui/deprecation/deprecation-sanity.stderr
new file mode 100644
index 0000000..6d5e3d5
--- /dev/null
+++ b/src/test/ui/deprecation/deprecation-sanity.stderr
@@ -0,0 +1,58 @@
+error[E0541]: unknown meta item 'reason'
+  --> $DIR/deprecation-sanity.rs:4:43
+   |
+LL |     #[deprecated(since = "a", note = "a", reason)]
+   |                                           ^^^^^^ expected one of `since`, `note`
+
+error[E0551]: incorrect meta item
+  --> $DIR/deprecation-sanity.rs:7:31
+   |
+LL |     #[deprecated(since = "a", note)]
+   |                               ^^^^
+
+error[E0551]: incorrect meta item
+  --> $DIR/deprecation-sanity.rs:10:18
+   |
+LL |     #[deprecated(since, note = "a")]
+   |                  ^^^^^
+
+error[E0551]: incorrect meta item
+  --> $DIR/deprecation-sanity.rs:13:31
+   |
+LL |     #[deprecated(since = "a", note(b))]
+   |                               ^^^^^^^
+
+error[E0551]: incorrect meta item
+  --> $DIR/deprecation-sanity.rs:16:18
+   |
+LL |     #[deprecated(since(b), note = "a")]
+   |                  ^^^^^^^^
+
+error[E0565]: literal in `deprecated` value must be a string
+  --> $DIR/deprecation-sanity.rs:19:25
+   |
+LL |     #[deprecated(note = b"test")]
+   |                         ^^^^^^^ help: consider removing the prefix: `"test"`
+
+error[E0565]: item in `deprecated` must be a key/value pair
+  --> $DIR/deprecation-sanity.rs:22:18
+   |
+LL |     #[deprecated("test")]
+   |                  ^^^^^^
+
+error[E0550]: multiple deprecated attributes
+  --> $DIR/deprecation-sanity.rs:28:1
+   |
+LL | fn multiple1() { }
+   | ^^^^^^^^^^^^^^^^^^
+
+error[E0538]: multiple 'since' items
+  --> $DIR/deprecation-sanity.rs:30:27
+   |
+LL | #[deprecated(since = "a", since = "b", note = "c")]
+   |                           ^^^^^^^^^^^
+
+error: aborting due to 9 previous errors
+
+Some errors occurred: E0538, E0541, E0550, E0551, E0565.
+For more information about an error, try `rustc --explain E0538`.
diff --git a/src/test/ui/deprecation/derive_on_deprecated.rs b/src/test/ui/deprecation/derive_on_deprecated.rs
new file mode 100644
index 0000000..4980a7f
--- /dev/null
+++ b/src/test/ui/deprecation/derive_on_deprecated.rs
@@ -0,0 +1,9 @@
+// compile-pass
+
+#![deny(deprecated)]
+
+#[deprecated = "oh no"]
+#[derive(Default)]
+struct X;
+
+fn main() {}
diff --git a/src/test/ui/deprecation/derive_on_deprecated_forbidden.rs b/src/test/ui/deprecation/derive_on_deprecated_forbidden.rs
new file mode 100644
index 0000000..235146b
--- /dev/null
+++ b/src/test/ui/deprecation/derive_on_deprecated_forbidden.rs
@@ -0,0 +1,9 @@
+// compile-pass
+
+#![forbid(deprecated)]
+
+#[deprecated = "oh no"]
+#[derive(Default)]
+struct X;
+
+fn main() {}
diff --git a/src/test/ui/deprecation/invalid-literal.rs b/src/test/ui/deprecation/invalid-literal.rs
new file mode 100644
index 0000000..7e0d8cd
--- /dev/null
+++ b/src/test/ui/deprecation/invalid-literal.rs
@@ -0,0 +1,4 @@
+#[deprecated = b"test"] //~ ERROR attribute must be of the form
+fn foo() {}
+
+fn main() {}
diff --git a/src/test/ui/deprecation/invalid-literal.stderr b/src/test/ui/deprecation/invalid-literal.stderr
new file mode 100644
index 0000000..28bc2e2
--- /dev/null
+++ b/src/test/ui/deprecation/invalid-literal.stderr
@@ -0,0 +1,8 @@
+error: attribute must be of the form `#[deprecated]` or `#[deprecated(/*opt*/ since = "version", /*opt*/ note = "reason)]` or `#[deprecated = "reason"]`
+  --> $DIR/invalid-literal.rs:1:1
+   |
+LL | #[deprecated = b"test"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/deprecation/rustc_deprecation-in-future.rs b/src/test/ui/deprecation/rustc_deprecation-in-future.rs
new file mode 100644
index 0000000..a19363c
--- /dev/null
+++ b/src/test/ui/deprecation/rustc_deprecation-in-future.rs
@@ -0,0 +1,15 @@
+// ignore-tidy-linelength
+
+#![deny(deprecated_in_future)]
+
+#![feature(staged_api)]
+
+#![stable(feature = "rustc_deprecation-in-future-test", since = "1.0.0")]
+
+#[rustc_deprecated(since = "99.99.99", reason = "effectively never")]
+#[stable(feature = "rustc_deprecation-in-future-test", since = "1.0.0")]
+pub struct S;
+
+fn main() {
+    let _ = S; //~ ERROR use of item 'S' that will be deprecated in future version 99.99.99: effectively never
+}
diff --git a/src/test/ui/deprecation/rustc_deprecation-in-future.stderr b/src/test/ui/deprecation/rustc_deprecation-in-future.stderr
new file mode 100644
index 0000000..4bbe79b
--- /dev/null
+++ b/src/test/ui/deprecation/rustc_deprecation-in-future.stderr
@@ -0,0 +1,14 @@
+error: use of item 'S' that will be deprecated in future version 99.99.99: effectively never
+  --> $DIR/rustc_deprecation-in-future.rs:14:13
+   |
+LL |     let _ = S;
+   |             ^
+   |
+note: lint level defined here
+  --> $DIR/rustc_deprecation-in-future.rs:3:9
+   |
+LL | #![deny(deprecated_in_future)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/deprecation/suggestion.fixed b/src/test/ui/deprecation/suggestion.fixed
new file mode 100644
index 0000000..eba72f8
--- /dev/null
+++ b/src/test/ui/deprecation/suggestion.fixed
@@ -0,0 +1,28 @@
+// run-rustfix
+
+#![feature(staged_api)]
+
+#![stable(since = "1.0.0", feature = "test")]
+
+#![deny(deprecated)]
+#![allow(dead_code)]
+
+struct Foo;
+
+impl Foo {
+    #[rustc_deprecated(
+        since = "1.0.0",
+        reason = "replaced by `replacement`",
+        suggestion = "replacement",
+    )]
+    #[stable(since = "1.0.0", feature = "test")]
+    fn deprecated(&self) {}
+
+    fn replacement(&self) {}
+}
+
+fn main() {
+    let foo = Foo;
+
+    foo.replacement(); //~ ERROR use of deprecated
+}
diff --git a/src/test/ui/deprecation/suggestion.rs b/src/test/ui/deprecation/suggestion.rs
new file mode 100644
index 0000000..8f9791c
--- /dev/null
+++ b/src/test/ui/deprecation/suggestion.rs
@@ -0,0 +1,28 @@
+// run-rustfix
+
+#![feature(staged_api)]
+
+#![stable(since = "1.0.0", feature = "test")]
+
+#![deny(deprecated)]
+#![allow(dead_code)]
+
+struct Foo;
+
+impl Foo {
+    #[rustc_deprecated(
+        since = "1.0.0",
+        reason = "replaced by `replacement`",
+        suggestion = "replacement",
+    )]
+    #[stable(since = "1.0.0", feature = "test")]
+    fn deprecated(&self) {}
+
+    fn replacement(&self) {}
+}
+
+fn main() {
+    let foo = Foo;
+
+    foo.deprecated(); //~ ERROR use of deprecated
+}
diff --git a/src/test/ui/deprecation/suggestion.stderr b/src/test/ui/deprecation/suggestion.stderr
new file mode 100644
index 0000000..6aaabfe
--- /dev/null
+++ b/src/test/ui/deprecation/suggestion.stderr
@@ -0,0 +1,14 @@
+error: use of deprecated item 'Foo::deprecated': replaced by `replacement`
+  --> $DIR/suggestion.rs:27:9
+   |
+LL |     foo.deprecated();
+   |         ^^^^^^^^^^ help: replace the use of the deprecated item: `replacement`
+   |
+note: lint level defined here
+  --> $DIR/suggestion.rs:7:9
+   |
+LL | #![deny(deprecated)]
+   |         ^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/deref-non-pointer.rs b/src/test/ui/deref-non-pointer.rs
new file mode 100644
index 0000000..82ab355
--- /dev/null
+++ b/src/test/ui/deref-non-pointer.rs
@@ -0,0 +1,5 @@
+fn main() {
+  match *1 { //~ ERROR: cannot be dereferenced
+      _ => { panic!(); }
+  }
+}
diff --git a/src/test/ui/deref-non-pointer.stderr b/src/test/ui/deref-non-pointer.stderr
new file mode 100644
index 0000000..1297e49
--- /dev/null
+++ b/src/test/ui/deref-non-pointer.stderr
@@ -0,0 +1,9 @@
+error[E0614]: type `{integer}` cannot be dereferenced
+  --> $DIR/deref-non-pointer.rs:2:9
+   |
+LL |   match *1 {
+   |         ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0614`.
diff --git a/src/test/ui/deref-suggestion.rs b/src/test/ui/deref-suggestion.rs
new file mode 100644
index 0000000..580410a
--- /dev/null
+++ b/src/test/ui/deref-suggestion.rs
@@ -0,0 +1,48 @@
+macro_rules! borrow {
+    ($x:expr) => { &$x } //~ ERROR mismatched types
+}
+
+fn foo(_: String) {}
+
+fn foo2(s: &String) {
+    foo(s);
+    //~^ ERROR mismatched types
+}
+
+fn foo3(_: u32) {}
+fn foo4(u: &u32) {
+    foo3(u);
+    //~^ ERROR mismatched types
+}
+
+struct S<'a> {
+    u: &'a u32,
+}
+
+struct R {
+    i: u32,
+}
+
+fn main() {
+    let s = String::new();
+    let r_s = &s;
+    foo2(r_s);
+    foo(&"aaa".to_owned());
+    //~^ ERROR mismatched types
+    foo(&mut "aaa".to_owned());
+    //~^ ERROR mismatched types
+    foo3(borrow!(0));
+    foo4(&0);
+    assert_eq!(3i32, &3i32);
+    //~^ ERROR mismatched types
+    let u = 3;
+    let s = S { u };
+    //~^ ERROR mismatched types
+    let s = S { u: u };
+    //~^ ERROR mismatched types
+    let i = &4;
+    let r = R { i };
+    //~^ ERROR mismatched types
+    let r = R { i: i };
+    //~^ ERROR mismatched types
+}
diff --git a/src/test/ui/deref-suggestion.stderr b/src/test/ui/deref-suggestion.stderr
new file mode 100644
index 0000000..9c49f54
--- /dev/null
+++ b/src/test/ui/deref-suggestion.stderr
@@ -0,0 +1,121 @@
+error[E0308]: mismatched types
+  --> $DIR/deref-suggestion.rs:8:9
+   |
+LL |     foo(s);
+   |         ^
+   |         |
+   |         expected struct `std::string::String`, found reference
+   |         help: try using a conversion method: `s.to_string()`
+   |
+   = note: expected type `std::string::String`
+              found type `&std::string::String`
+
+error[E0308]: mismatched types
+  --> $DIR/deref-suggestion.rs:14:10
+   |
+LL |     foo3(u);
+   |          ^
+   |          |
+   |          expected u32, found &u32
+   |          help: consider dereferencing the borrow: `*u`
+   |
+   = note: expected type `u32`
+              found type `&u32`
+
+error[E0308]: mismatched types
+  --> $DIR/deref-suggestion.rs:30:9
+   |
+LL |     foo(&"aaa".to_owned());
+   |         ^^^^^^^^^^^^^^^^^
+   |         |
+   |         expected struct `std::string::String`, found reference
+   |         help: consider removing the borrow: `"aaa".to_owned()`
+   |
+   = note: expected type `std::string::String`
+              found type `&std::string::String`
+
+error[E0308]: mismatched types
+  --> $DIR/deref-suggestion.rs:32:9
+   |
+LL |     foo(&mut "aaa".to_owned());
+   |         ^^^^^^^^^^^^^^^^^^^^^
+   |         |
+   |         expected struct `std::string::String`, found mutable reference
+   |         help: consider removing the borrow: `"aaa".to_owned()`
+   |
+   = note: expected type `std::string::String`
+              found type `&mut std::string::String`
+
+error[E0308]: mismatched types
+  --> $DIR/deref-suggestion.rs:2:20
+   |
+LL |     ($x:expr) => { &$x }
+   |                    ^^^ expected u32, found &{integer}
+...
+LL |     foo3(borrow!(0));
+   |          ---------- in this macro invocation
+   |
+   = note: expected type `u32`
+              found type `&{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/deref-suggestion.rs:36:5
+   |
+LL |     assert_eq!(3i32, &3i32);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ expected i32, found &i32
+   |
+   = note: expected type `i32`
+              found type `&i32`
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error[E0308]: mismatched types
+  --> $DIR/deref-suggestion.rs:39:17
+   |
+LL |     let s = S { u };
+   |                 ^
+   |                 |
+   |                 expected &u32, found integer
+   |                 help: consider borrowing here: `u: &u`
+   |
+   = note: expected type `&u32`
+              found type `{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/deref-suggestion.rs:41:20
+   |
+LL |     let s = S { u: u };
+   |                    ^
+   |                    |
+   |                    expected &u32, found integer
+   |                    help: consider borrowing here: `&u`
+   |
+   = note: expected type `&u32`
+              found type `{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/deref-suggestion.rs:44:17
+   |
+LL |     let r = R { i };
+   |                 ^
+   |                 |
+   |                 expected u32, found &{integer}
+   |                 help: consider dereferencing the borrow: `i: *i`
+   |
+   = note: expected type `u32`
+              found type `&{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/deref-suggestion.rs:46:20
+   |
+LL |     let r = R { i: i };
+   |                    ^
+   |                    |
+   |                    expected u32, found &{integer}
+   |                    help: consider dereferencing the borrow: `*i`
+   |
+   = note: expected type `u32`
+              found type `&{integer}`
+
+error: aborting due to 10 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/derive-uninhabited-enum-38885.rs b/src/test/ui/derive-uninhabited-enum-38885.rs
new file mode 100644
index 0000000..c0279d6
--- /dev/null
+++ b/src/test/ui/derive-uninhabited-enum-38885.rs
@@ -0,0 +1,17 @@
+// compile-pass
+// compile-flags: -Wunused
+
+// ensure there are no special warnings about uninhabited types
+// when deriving Debug on an empty enum
+
+#[derive(Debug)]
+enum Void {} //~ WARN never used
+
+#[derive(Debug)]
+enum Foo { //~ WARN never used
+    Bar(u8),
+    Void(Void),
+}
+
+fn main() {}
+
diff --git a/src/test/ui/derive-uninhabited-enum-38885.stderr b/src/test/ui/derive-uninhabited-enum-38885.stderr
new file mode 100644
index 0000000..941c98b
--- /dev/null
+++ b/src/test/ui/derive-uninhabited-enum-38885.stderr
@@ -0,0 +1,14 @@
+warning: enum is never used: `Void`
+  --> $DIR/derive-uninhabited-enum-38885.rs:8:1
+   |
+LL | enum Void {}
+   | ^^^^^^^^^
+   |
+   = note: `-W dead-code` implied by `-W unused`
+
+warning: enum is never used: `Foo`
+  --> $DIR/derive-uninhabited-enum-38885.rs:11:1
+   |
+LL | enum Foo {
+   | ^^^^^^^^
+
diff --git a/src/test/ui/derived-errors/issue-30580.rs b/src/test/ui/derived-errors/issue-30580.rs
new file mode 100644
index 0000000..6940fcf
--- /dev/null
+++ b/src/test/ui/derived-errors/issue-30580.rs
@@ -0,0 +1,17 @@
+// Test that we do not see uninformative region-related errors
+// when we get some basic type-checking failure. See #30580.
+
+pub struct Foo { a: u32 }
+pub struct Pass<'a, 'tcx: 'a>(&'a mut &'a (), &'a &'tcx ());
+
+impl<'a, 'tcx> Pass<'a, 'tcx>
+{
+    pub fn tcx(&self) -> &'a &'tcx () { self.1 }
+    fn lol(&mut self, b: &Foo)
+    {
+        b.c; //~ ERROR no field `c` on type `&Foo`
+        self.tcx();
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/derived-errors/issue-30580.stderr b/src/test/ui/derived-errors/issue-30580.stderr
new file mode 100644
index 0000000..14c575f
--- /dev/null
+++ b/src/test/ui/derived-errors/issue-30580.stderr
@@ -0,0 +1,9 @@
+error[E0609]: no field `c` on type `&Foo`
+  --> $DIR/issue-30580.rs:12:11
+   |
+LL |         b.c;
+   |           ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0609`.
diff --git a/src/test/ui/derived-errors/issue-31997-1.rs b/src/test/ui/derived-errors/issue-31997-1.rs
new file mode 100644
index 0000000..90c1b49
--- /dev/null
+++ b/src/test/ui/derived-errors/issue-31997-1.rs
@@ -0,0 +1,56 @@
+// Regression test for this example from #31997 -- main goal is to
+// emit as minimal and precise an error set as possible. Ideally, we'd
+// only emit the E0433 error below, but right now we emit two.
+
+use std::io::prelude::*;
+// use std::collections::HashMap;
+use std::io;
+
+#[derive(Debug)]
+struct Instance {
+    name: String,
+    start: Option<String>,
+    end: Option<String>,
+}
+
+fn main() {
+    let input = io::stdin();
+    let mut input = input.lock();
+
+    let mut map = HashMap::new();
+    //~^ ERROR E0433
+
+    for line in input.lines() {
+        let line = line.unwrap();
+        println!("process: {}", line);
+        let mut parts = line.splitn(2, ":");
+        let _logfile = parts.next().unwrap();
+        let rest = parts.next().unwrap();
+        let mut parts = line.split(" [-] ");
+
+        let stamp = parts.next().unwrap();
+
+        let rest = parts.next().unwrap();
+        let words = rest.split_whitespace().collect::<Vec<_>>();
+
+        let instance = words.iter().find(|a| a.starts_with("i-")).unwrap();
+        let name = words[1].to_owned();
+        let mut entry = map.entry(instance.to_owned()).or_insert(Instance {
+            name: name,
+            start: None,
+            end: None,
+        });
+
+        if rest.contains("terminating") {
+            assert!(entry.end.is_none());
+            entry.end = Some(stamp.to_string());
+        }
+        if rest.contains("waiting for") {
+            assert!(entry.start.is_none());
+            entry.start = Some(stamp.to_string());
+        }
+
+    }
+
+    println!("{:?}", map);
+}
diff --git a/src/test/ui/derived-errors/issue-31997-1.stderr b/src/test/ui/derived-errors/issue-31997-1.stderr
new file mode 100644
index 0000000..6df7481
--- /dev/null
+++ b/src/test/ui/derived-errors/issue-31997-1.stderr
@@ -0,0 +1,9 @@
+error[E0433]: failed to resolve: use of undeclared type or module `HashMap`
+  --> $DIR/issue-31997-1.rs:20:19
+   |
+LL |     let mut map = HashMap::new();
+   |                   ^^^^^^^ use of undeclared type or module `HashMap`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/derived-errors/issue-31997.rs b/src/test/ui/derived-errors/issue-31997.rs
new file mode 100644
index 0000000..025e910
--- /dev/null
+++ b/src/test/ui/derived-errors/issue-31997.rs
@@ -0,0 +1,17 @@
+// Test that the resolve failure does not lead to downstream type errors.
+// See issue #31997.
+
+trait TheTrait { }
+
+fn closure<F, T>(x: F) -> Result<T, ()>
+    where F: FnMut() -> T, T: TheTrait,
+{
+    unimplemented!()
+}
+
+fn foo() -> Result<(), ()> {
+    try!(closure(|| bar(0 as *mut _))); //~ ERROR cannot find function `bar` in this scope
+    Ok(())
+}
+
+fn main() { }
diff --git a/src/test/ui/derived-errors/issue-31997.stderr b/src/test/ui/derived-errors/issue-31997.stderr
new file mode 100644
index 0000000..dbceba0
--- /dev/null
+++ b/src/test/ui/derived-errors/issue-31997.stderr
@@ -0,0 +1,9 @@
+error[E0425]: cannot find function `bar` in this scope
+  --> $DIR/issue-31997.rs:13:21
+   |
+LL |     try!(closure(|| bar(0 as *mut _)));
+   |                     ^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/derives/derive-assoc-type-not-impl.rs b/src/test/ui/derives/derive-assoc-type-not-impl.rs
new file mode 100644
index 0000000..0f642d6
--- /dev/null
+++ b/src/test/ui/derives/derive-assoc-type-not-impl.rs
@@ -0,0 +1,19 @@
+trait Foo {
+    type X;
+    fn method(&self) {}
+}
+
+#[derive(Clone)]
+struct Bar<T: Foo> {
+    x: T::X,
+}
+
+struct NotClone;
+
+impl Foo for NotClone {
+    type X = i8;
+}
+
+fn main() {
+    Bar::<NotClone> { x: 1 }.clone(); //~ ERROR
+}
diff --git a/src/test/ui/derives/derive-assoc-type-not-impl.stderr b/src/test/ui/derives/derive-assoc-type-not-impl.stderr
new file mode 100644
index 0000000..b9e175e
--- /dev/null
+++ b/src/test/ui/derives/derive-assoc-type-not-impl.stderr
@@ -0,0 +1,18 @@
+error[E0599]: no method named `clone` found for type `Bar<NotClone>` in the current scope
+  --> $DIR/derive-assoc-type-not-impl.rs:18:30
+   |
+LL | struct Bar<T: Foo> {
+   | ------------------ method `clone` not found for this
+...
+LL |     Bar::<NotClone> { x: 1 }.clone();
+   |                              ^^^^^
+   |
+   = note: the method `clone` exists but the following trait bounds were not satisfied:
+           `Bar<NotClone> : std::clone::Clone`
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following trait defines an item `clone`, perhaps you need to implement it:
+           candidate #1: `std::clone::Clone`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/derives/derive-on-trait-item-or-impl-item.rs b/src/test/ui/derives/derive-on-trait-item-or-impl-item.rs
new file mode 100644
index 0000000..b847000
--- /dev/null
+++ b/src/test/ui/derives/derive-on-trait-item-or-impl-item.rs
@@ -0,0 +1,15 @@
+trait Foo {
+    #[derive(Clone)]
+    //~^ ERROR `derive` may only be applied to structs, enums and unions
+    type Bar;
+}
+
+struct Bar;
+
+impl Bar {
+    #[derive(Clone)]
+    //~^ ERROR `derive` may only be applied to structs, enums and unions
+    fn bar(&self) {}
+}
+
+fn main() {}
diff --git a/src/test/ui/derives/derive-on-trait-item-or-impl-item.stderr b/src/test/ui/derives/derive-on-trait-item-or-impl-item.stderr
new file mode 100644
index 0000000..b3aa886
--- /dev/null
+++ b/src/test/ui/derives/derive-on-trait-item-or-impl-item.stderr
@@ -0,0 +1,14 @@
+error: `derive` may only be applied to structs, enums and unions
+  --> $DIR/derive-on-trait-item-or-impl-item.rs:2:5
+   |
+LL |     #[derive(Clone)]
+   |     ^^^^^^^^^^^^^^^^
+
+error: `derive` may only be applied to structs, enums and unions
+  --> $DIR/derive-on-trait-item-or-impl-item.rs:10:5
+   |
+LL |     #[derive(Clone)]
+   |     ^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/derives/derives-span-Clone-enum-struct-variant.rs b/src/test/ui/derives/derives-span-Clone-enum-struct-variant.rs
new file mode 100644
index 0000000..b556d44
--- /dev/null
+++ b/src/test/ui/derives/derives-span-Clone-enum-struct-variant.rs
@@ -0,0 +1,13 @@
+// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
+
+
+struct Error;
+
+#[derive(Clone)]
+enum Enum {
+   A {
+     x: Error //~ ERROR
+   }
+}
+
+fn main() {}
diff --git a/src/test/ui/derives/derives-span-Clone-enum-struct-variant.stderr b/src/test/ui/derives/derives-span-Clone-enum-struct-variant.stderr
new file mode 100644
index 0000000..7db5fbe
--- /dev/null
+++ b/src/test/ui/derives/derives-span-Clone-enum-struct-variant.stderr
@@ -0,0 +1,11 @@
+error[E0277]: the trait bound `Error: std::clone::Clone` is not satisfied
+  --> $DIR/derives-span-Clone-enum-struct-variant.rs:9:6
+   |
+LL |      x: Error
+   |      ^^^^^^^^ the trait `std::clone::Clone` is not implemented for `Error`
+   |
+   = note: required by `std::clone::Clone::clone`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/derives/derives-span-Clone-enum.rs b/src/test/ui/derives/derives-span-Clone-enum.rs
new file mode 100644
index 0000000..9bb4f48
--- /dev/null
+++ b/src/test/ui/derives/derives-span-Clone-enum.rs
@@ -0,0 +1,13 @@
+// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
+
+
+struct Error;
+
+#[derive(Clone)]
+enum Enum {
+   A(
+     Error //~ ERROR
+     )
+}
+
+fn main() {}
diff --git a/src/test/ui/derives/derives-span-Clone-enum.stderr b/src/test/ui/derives/derives-span-Clone-enum.stderr
new file mode 100644
index 0000000..4371dc9
--- /dev/null
+++ b/src/test/ui/derives/derives-span-Clone-enum.stderr
@@ -0,0 +1,11 @@
+error[E0277]: the trait bound `Error: std::clone::Clone` is not satisfied
+  --> $DIR/derives-span-Clone-enum.rs:9:6
+   |
+LL |      Error
+   |      ^^^^^ the trait `std::clone::Clone` is not implemented for `Error`
+   |
+   = note: required by `std::clone::Clone::clone`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/derives/derives-span-Clone-struct.rs b/src/test/ui/derives/derives-span-Clone-struct.rs
new file mode 100644
index 0000000..f151636
--- /dev/null
+++ b/src/test/ui/derives/derives-span-Clone-struct.rs
@@ -0,0 +1,11 @@
+// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
+
+
+struct Error;
+
+#[derive(Clone)]
+struct Struct {
+    x: Error //~ ERROR
+}
+
+fn main() {}
diff --git a/src/test/ui/derives/derives-span-Clone-struct.stderr b/src/test/ui/derives/derives-span-Clone-struct.stderr
new file mode 100644
index 0000000..cc3b602
--- /dev/null
+++ b/src/test/ui/derives/derives-span-Clone-struct.stderr
@@ -0,0 +1,11 @@
+error[E0277]: the trait bound `Error: std::clone::Clone` is not satisfied
+  --> $DIR/derives-span-Clone-struct.rs:8:5
+   |
+LL |     x: Error
+   |     ^^^^^^^^ the trait `std::clone::Clone` is not implemented for `Error`
+   |
+   = note: required by `std::clone::Clone::clone`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/derives/derives-span-Clone-tuple-struct.rs b/src/test/ui/derives/derives-span-Clone-tuple-struct.rs
new file mode 100644
index 0000000..7a62885
--- /dev/null
+++ b/src/test/ui/derives/derives-span-Clone-tuple-struct.rs
@@ -0,0 +1,11 @@
+// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
+
+
+struct Error;
+
+#[derive(Clone)]
+struct Struct(
+    Error //~ ERROR
+);
+
+fn main() {}
diff --git a/src/test/ui/derives/derives-span-Clone-tuple-struct.stderr b/src/test/ui/derives/derives-span-Clone-tuple-struct.stderr
new file mode 100644
index 0000000..b2bf352
--- /dev/null
+++ b/src/test/ui/derives/derives-span-Clone-tuple-struct.stderr
@@ -0,0 +1,11 @@
+error[E0277]: the trait bound `Error: std::clone::Clone` is not satisfied
+  --> $DIR/derives-span-Clone-tuple-struct.rs:8:5
+   |
+LL |     Error
+   |     ^^^^^ the trait `std::clone::Clone` is not implemented for `Error`
+   |
+   = note: required by `std::clone::Clone::clone`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/derives/derives-span-Debug-enum-struct-variant.rs b/src/test/ui/derives/derives-span-Debug-enum-struct-variant.rs
new file mode 100644
index 0000000..949597b
--- /dev/null
+++ b/src/test/ui/derives/derives-span-Debug-enum-struct-variant.rs
@@ -0,0 +1,13 @@
+// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
+
+
+struct Error;
+
+#[derive(Debug)]
+enum Enum {
+   A {
+     x: Error //~ ERROR
+   }
+}
+
+fn main() {}
diff --git a/src/test/ui/derives/derives-span-Debug-enum-struct-variant.stderr b/src/test/ui/derives/derives-span-Debug-enum-struct-variant.stderr
new file mode 100644
index 0000000..ca5bcfe
--- /dev/null
+++ b/src/test/ui/derives/derives-span-Debug-enum-struct-variant.stderr
@@ -0,0 +1,14 @@
+error[E0277]: `Error` doesn't implement `std::fmt::Debug`
+  --> $DIR/derives-span-Debug-enum-struct-variant.rs:9:6
+   |
+LL |      x: Error
+   |      ^^^^^^^^ `Error` cannot be formatted using `{:?}`
+   |
+   = help: the trait `std::fmt::Debug` is not implemented for `Error`
+   = note: add `#[derive(Debug)]` or manually implement `std::fmt::Debug`
+   = note: required because of the requirements on the impl of `std::fmt::Debug` for `&Error`
+   = note: required for the cast to the object type `dyn std::fmt::Debug`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/derives/derives-span-Debug-enum.rs b/src/test/ui/derives/derives-span-Debug-enum.rs
new file mode 100644
index 0000000..b2a3970
--- /dev/null
+++ b/src/test/ui/derives/derives-span-Debug-enum.rs
@@ -0,0 +1,13 @@
+// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
+
+
+struct Error;
+
+#[derive(Debug)]
+enum Enum {
+   A(
+     Error //~ ERROR
+     )
+}
+
+fn main() {}
diff --git a/src/test/ui/derives/derives-span-Debug-enum.stderr b/src/test/ui/derives/derives-span-Debug-enum.stderr
new file mode 100644
index 0000000..cd367a3
--- /dev/null
+++ b/src/test/ui/derives/derives-span-Debug-enum.stderr
@@ -0,0 +1,14 @@
+error[E0277]: `Error` doesn't implement `std::fmt::Debug`
+  --> $DIR/derives-span-Debug-enum.rs:9:6
+   |
+LL |      Error
+   |      ^^^^^ `Error` cannot be formatted using `{:?}`
+   |
+   = help: the trait `std::fmt::Debug` is not implemented for `Error`
+   = note: add `#[derive(Debug)]` or manually implement `std::fmt::Debug`
+   = note: required because of the requirements on the impl of `std::fmt::Debug` for `&Error`
+   = note: required for the cast to the object type `dyn std::fmt::Debug`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/derives/derives-span-Debug-struct.rs b/src/test/ui/derives/derives-span-Debug-struct.rs
new file mode 100644
index 0000000..cf91c94
--- /dev/null
+++ b/src/test/ui/derives/derives-span-Debug-struct.rs
@@ -0,0 +1,11 @@
+// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
+
+
+struct Error;
+
+#[derive(Debug)]
+struct Struct {
+    x: Error //~ ERROR
+}
+
+fn main() {}
diff --git a/src/test/ui/derives/derives-span-Debug-struct.stderr b/src/test/ui/derives/derives-span-Debug-struct.stderr
new file mode 100644
index 0000000..e00695e
--- /dev/null
+++ b/src/test/ui/derives/derives-span-Debug-struct.stderr
@@ -0,0 +1,14 @@
+error[E0277]: `Error` doesn't implement `std::fmt::Debug`
+  --> $DIR/derives-span-Debug-struct.rs:8:5
+   |
+LL |     x: Error
+   |     ^^^^^^^^ `Error` cannot be formatted using `{:?}`
+   |
+   = help: the trait `std::fmt::Debug` is not implemented for `Error`
+   = note: add `#[derive(Debug)]` or manually implement `std::fmt::Debug`
+   = note: required because of the requirements on the impl of `std::fmt::Debug` for `&Error`
+   = note: required for the cast to the object type `dyn std::fmt::Debug`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/derives/derives-span-Debug-tuple-struct.rs b/src/test/ui/derives/derives-span-Debug-tuple-struct.rs
new file mode 100644
index 0000000..cea973c
--- /dev/null
+++ b/src/test/ui/derives/derives-span-Debug-tuple-struct.rs
@@ -0,0 +1,11 @@
+// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
+
+
+struct Error;
+
+#[derive(Debug)]
+struct Struct(
+    Error //~ ERROR
+);
+
+fn main() {}
diff --git a/src/test/ui/derives/derives-span-Debug-tuple-struct.stderr b/src/test/ui/derives/derives-span-Debug-tuple-struct.stderr
new file mode 100644
index 0000000..37440b5
--- /dev/null
+++ b/src/test/ui/derives/derives-span-Debug-tuple-struct.stderr
@@ -0,0 +1,14 @@
+error[E0277]: `Error` doesn't implement `std::fmt::Debug`
+  --> $DIR/derives-span-Debug-tuple-struct.rs:8:5
+   |
+LL |     Error
+   |     ^^^^^ `Error` cannot be formatted using `{:?}`
+   |
+   = help: the trait `std::fmt::Debug` is not implemented for `Error`
+   = note: add `#[derive(Debug)]` or manually implement `std::fmt::Debug`
+   = note: required because of the requirements on the impl of `std::fmt::Debug` for `&Error`
+   = note: required for the cast to the object type `dyn std::fmt::Debug`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/derives/derives-span-Default-struct.rs b/src/test/ui/derives/derives-span-Default-struct.rs
new file mode 100644
index 0000000..71fd582
--- /dev/null
+++ b/src/test/ui/derives/derives-span-Default-struct.rs
@@ -0,0 +1,11 @@
+// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
+
+
+struct Error;
+
+#[derive(Default)]
+struct Struct {
+    x: Error //~ ERROR
+}
+
+fn main() {}
diff --git a/src/test/ui/derives/derives-span-Default-struct.stderr b/src/test/ui/derives/derives-span-Default-struct.stderr
new file mode 100644
index 0000000..413d4ec
--- /dev/null
+++ b/src/test/ui/derives/derives-span-Default-struct.stderr
@@ -0,0 +1,11 @@
+error[E0277]: the trait bound `Error: std::default::Default` is not satisfied
+  --> $DIR/derives-span-Default-struct.rs:8:5
+   |
+LL |     x: Error
+   |     ^^^^^^^^ the trait `std::default::Default` is not implemented for `Error`
+   |
+   = note: required by `std::default::Default::default`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/derives/derives-span-Default-tuple-struct.rs b/src/test/ui/derives/derives-span-Default-tuple-struct.rs
new file mode 100644
index 0000000..463f7d2
--- /dev/null
+++ b/src/test/ui/derives/derives-span-Default-tuple-struct.rs
@@ -0,0 +1,11 @@
+// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
+
+
+struct Error;
+
+#[derive(Default)]
+struct Struct(
+    Error //~ ERROR
+);
+
+fn main() {}
diff --git a/src/test/ui/derives/derives-span-Default-tuple-struct.stderr b/src/test/ui/derives/derives-span-Default-tuple-struct.stderr
new file mode 100644
index 0000000..8f4d43d
--- /dev/null
+++ b/src/test/ui/derives/derives-span-Default-tuple-struct.stderr
@@ -0,0 +1,11 @@
+error[E0277]: the trait bound `Error: std::default::Default` is not satisfied
+  --> $DIR/derives-span-Default-tuple-struct.rs:8:5
+   |
+LL |     Error
+   |     ^^^^^ the trait `std::default::Default` is not implemented for `Error`
+   |
+   = note: required by `std::default::Default::default`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/derives/derives-span-Eq-enum-struct-variant.rs b/src/test/ui/derives/derives-span-Eq-enum-struct-variant.rs
new file mode 100644
index 0000000..d2dab86
--- /dev/null
+++ b/src/test/ui/derives/derives-span-Eq-enum-struct-variant.rs
@@ -0,0 +1,13 @@
+// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
+
+#[derive(PartialEq)]
+struct Error;
+
+#[derive(Eq,PartialEq)]
+enum Enum {
+   A {
+     x: Error //~ ERROR
+   }
+}
+
+fn main() {}
diff --git a/src/test/ui/derives/derives-span-Eq-enum-struct-variant.stderr b/src/test/ui/derives/derives-span-Eq-enum-struct-variant.stderr
new file mode 100644
index 0000000..52ecce4
--- /dev/null
+++ b/src/test/ui/derives/derives-span-Eq-enum-struct-variant.stderr
@@ -0,0 +1,11 @@
+error[E0277]: the trait bound `Error: std::cmp::Eq` is not satisfied
+  --> $DIR/derives-span-Eq-enum-struct-variant.rs:9:6
+   |
+LL |      x: Error
+   |      ^^^^^^^^ the trait `std::cmp::Eq` is not implemented for `Error`
+   |
+   = note: required by `std::cmp::AssertParamIsEq`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/derives/derives-span-Eq-enum.rs b/src/test/ui/derives/derives-span-Eq-enum.rs
new file mode 100644
index 0000000..c6c0d43
--- /dev/null
+++ b/src/test/ui/derives/derives-span-Eq-enum.rs
@@ -0,0 +1,13 @@
+// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
+
+#[derive(PartialEq)]
+struct Error;
+
+#[derive(Eq,PartialEq)]
+enum Enum {
+   A(
+     Error //~ ERROR
+     )
+}
+
+fn main() {}
diff --git a/src/test/ui/derives/derives-span-Eq-enum.stderr b/src/test/ui/derives/derives-span-Eq-enum.stderr
new file mode 100644
index 0000000..bf91a0e
--- /dev/null
+++ b/src/test/ui/derives/derives-span-Eq-enum.stderr
@@ -0,0 +1,11 @@
+error[E0277]: the trait bound `Error: std::cmp::Eq` is not satisfied
+  --> $DIR/derives-span-Eq-enum.rs:9:6
+   |
+LL |      Error
+   |      ^^^^^ the trait `std::cmp::Eq` is not implemented for `Error`
+   |
+   = note: required by `std::cmp::AssertParamIsEq`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/derives/derives-span-Eq-struct.rs b/src/test/ui/derives/derives-span-Eq-struct.rs
new file mode 100644
index 0000000..df31003
--- /dev/null
+++ b/src/test/ui/derives/derives-span-Eq-struct.rs
@@ -0,0 +1,11 @@
+// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
+
+#[derive(PartialEq)]
+struct Error;
+
+#[derive(Eq,PartialEq)]
+struct Struct {
+    x: Error //~ ERROR
+}
+
+fn main() {}
diff --git a/src/test/ui/derives/derives-span-Eq-struct.stderr b/src/test/ui/derives/derives-span-Eq-struct.stderr
new file mode 100644
index 0000000..531e888
--- /dev/null
+++ b/src/test/ui/derives/derives-span-Eq-struct.stderr
@@ -0,0 +1,11 @@
+error[E0277]: the trait bound `Error: std::cmp::Eq` is not satisfied
+  --> $DIR/derives-span-Eq-struct.rs:8:5
+   |
+LL |     x: Error
+   |     ^^^^^^^^ the trait `std::cmp::Eq` is not implemented for `Error`
+   |
+   = note: required by `std::cmp::AssertParamIsEq`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/derives/derives-span-Eq-tuple-struct.rs b/src/test/ui/derives/derives-span-Eq-tuple-struct.rs
new file mode 100644
index 0000000..abf6526
--- /dev/null
+++ b/src/test/ui/derives/derives-span-Eq-tuple-struct.rs
@@ -0,0 +1,11 @@
+// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
+
+#[derive(PartialEq)]
+struct Error;
+
+#[derive(Eq,PartialEq)]
+struct Struct(
+    Error //~ ERROR
+);
+
+fn main() {}
diff --git a/src/test/ui/derives/derives-span-Eq-tuple-struct.stderr b/src/test/ui/derives/derives-span-Eq-tuple-struct.stderr
new file mode 100644
index 0000000..9e21c6c
--- /dev/null
+++ b/src/test/ui/derives/derives-span-Eq-tuple-struct.stderr
@@ -0,0 +1,11 @@
+error[E0277]: the trait bound `Error: std::cmp::Eq` is not satisfied
+  --> $DIR/derives-span-Eq-tuple-struct.rs:8:5
+   |
+LL |     Error
+   |     ^^^^^ the trait `std::cmp::Eq` is not implemented for `Error`
+   |
+   = note: required by `std::cmp::AssertParamIsEq`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/derives/derives-span-Hash-enum-struct-variant.rs b/src/test/ui/derives/derives-span-Hash-enum-struct-variant.rs
new file mode 100644
index 0000000..3018a7b
--- /dev/null
+++ b/src/test/ui/derives/derives-span-Hash-enum-struct-variant.rs
@@ -0,0 +1,13 @@
+// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
+
+
+struct Error;
+
+#[derive(Hash)]
+enum Enum {
+   A {
+     x: Error //~ ERROR
+   }
+}
+
+fn main() {}
diff --git a/src/test/ui/derives/derives-span-Hash-enum-struct-variant.stderr b/src/test/ui/derives/derives-span-Hash-enum-struct-variant.stderr
new file mode 100644
index 0000000..417c720
--- /dev/null
+++ b/src/test/ui/derives/derives-span-Hash-enum-struct-variant.stderr
@@ -0,0 +1,11 @@
+error[E0277]: the trait bound `Error: std::hash::Hash` is not satisfied
+  --> $DIR/derives-span-Hash-enum-struct-variant.rs:9:6
+   |
+LL |      x: Error
+   |      ^^^^^^^^ the trait `std::hash::Hash` is not implemented for `Error`
+   |
+   = note: required by `std::hash::Hash::hash`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/derives/derives-span-Hash-enum.rs b/src/test/ui/derives/derives-span-Hash-enum.rs
new file mode 100644
index 0000000..bb656e5
--- /dev/null
+++ b/src/test/ui/derives/derives-span-Hash-enum.rs
@@ -0,0 +1,13 @@
+// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
+
+
+struct Error;
+
+#[derive(Hash)]
+enum Enum {
+   A(
+     Error //~ ERROR
+     )
+}
+
+fn main() {}
diff --git a/src/test/ui/derives/derives-span-Hash-enum.stderr b/src/test/ui/derives/derives-span-Hash-enum.stderr
new file mode 100644
index 0000000..25be879
--- /dev/null
+++ b/src/test/ui/derives/derives-span-Hash-enum.stderr
@@ -0,0 +1,11 @@
+error[E0277]: the trait bound `Error: std::hash::Hash` is not satisfied
+  --> $DIR/derives-span-Hash-enum.rs:9:6
+   |
+LL |      Error
+   |      ^^^^^ the trait `std::hash::Hash` is not implemented for `Error`
+   |
+   = note: required by `std::hash::Hash::hash`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/derives/derives-span-Hash-struct.rs b/src/test/ui/derives/derives-span-Hash-struct.rs
new file mode 100644
index 0000000..fa5e2af
--- /dev/null
+++ b/src/test/ui/derives/derives-span-Hash-struct.rs
@@ -0,0 +1,11 @@
+// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
+
+
+struct Error;
+
+#[derive(Hash)]
+struct Struct {
+    x: Error //~ ERROR
+}
+
+fn main() {}
diff --git a/src/test/ui/derives/derives-span-Hash-struct.stderr b/src/test/ui/derives/derives-span-Hash-struct.stderr
new file mode 100644
index 0000000..c057445
--- /dev/null
+++ b/src/test/ui/derives/derives-span-Hash-struct.stderr
@@ -0,0 +1,11 @@
+error[E0277]: the trait bound `Error: std::hash::Hash` is not satisfied
+  --> $DIR/derives-span-Hash-struct.rs:8:5
+   |
+LL |     x: Error
+   |     ^^^^^^^^ the trait `std::hash::Hash` is not implemented for `Error`
+   |
+   = note: required by `std::hash::Hash::hash`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/derives/derives-span-Hash-tuple-struct.rs b/src/test/ui/derives/derives-span-Hash-tuple-struct.rs
new file mode 100644
index 0000000..3822bce
--- /dev/null
+++ b/src/test/ui/derives/derives-span-Hash-tuple-struct.rs
@@ -0,0 +1,11 @@
+// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
+
+
+struct Error;
+
+#[derive(Hash)]
+struct Struct(
+    Error //~ ERROR
+);
+
+fn main() {}
diff --git a/src/test/ui/derives/derives-span-Hash-tuple-struct.stderr b/src/test/ui/derives/derives-span-Hash-tuple-struct.stderr
new file mode 100644
index 0000000..6339c38
--- /dev/null
+++ b/src/test/ui/derives/derives-span-Hash-tuple-struct.stderr
@@ -0,0 +1,11 @@
+error[E0277]: the trait bound `Error: std::hash::Hash` is not satisfied
+  --> $DIR/derives-span-Hash-tuple-struct.rs:8:5
+   |
+LL |     Error
+   |     ^^^^^ the trait `std::hash::Hash` is not implemented for `Error`
+   |
+   = note: required by `std::hash::Hash::hash`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/derives/derives-span-Ord-enum-struct-variant.rs b/src/test/ui/derives/derives-span-Ord-enum-struct-variant.rs
new file mode 100644
index 0000000..62355cc
--- /dev/null
+++ b/src/test/ui/derives/derives-span-Ord-enum-struct-variant.rs
@@ -0,0 +1,13 @@
+// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
+
+#[derive(Eq,PartialOrd,PartialEq)]
+struct Error;
+
+#[derive(Ord,Eq,PartialOrd,PartialEq)]
+enum Enum {
+   A {
+     x: Error //~ ERROR
+   }
+}
+
+fn main() {}
diff --git a/src/test/ui/derives/derives-span-Ord-enum-struct-variant.stderr b/src/test/ui/derives/derives-span-Ord-enum-struct-variant.stderr
new file mode 100644
index 0000000..5c0d4e4
--- /dev/null
+++ b/src/test/ui/derives/derives-span-Ord-enum-struct-variant.stderr
@@ -0,0 +1,11 @@
+error[E0277]: the trait bound `Error: std::cmp::Ord` is not satisfied
+  --> $DIR/derives-span-Ord-enum-struct-variant.rs:9:6
+   |
+LL |      x: Error
+   |      ^^^^^^^^ the trait `std::cmp::Ord` is not implemented for `Error`
+   |
+   = note: required by `std::cmp::Ord::cmp`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/derives/derives-span-Ord-enum.rs b/src/test/ui/derives/derives-span-Ord-enum.rs
new file mode 100644
index 0000000..7273893
--- /dev/null
+++ b/src/test/ui/derives/derives-span-Ord-enum.rs
@@ -0,0 +1,13 @@
+// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
+
+#[derive(Eq,PartialOrd,PartialEq)]
+struct Error;
+
+#[derive(Ord,Eq,PartialOrd,PartialEq)]
+enum Enum {
+   A(
+     Error //~ ERROR
+     )
+}
+
+fn main() {}
diff --git a/src/test/ui/derives/derives-span-Ord-enum.stderr b/src/test/ui/derives/derives-span-Ord-enum.stderr
new file mode 100644
index 0000000..56268a2
--- /dev/null
+++ b/src/test/ui/derives/derives-span-Ord-enum.stderr
@@ -0,0 +1,11 @@
+error[E0277]: the trait bound `Error: std::cmp::Ord` is not satisfied
+  --> $DIR/derives-span-Ord-enum.rs:9:6
+   |
+LL |      Error
+   |      ^^^^^ the trait `std::cmp::Ord` is not implemented for `Error`
+   |
+   = note: required by `std::cmp::Ord::cmp`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/derives/derives-span-Ord-struct.rs b/src/test/ui/derives/derives-span-Ord-struct.rs
new file mode 100644
index 0000000..53d4c2c
--- /dev/null
+++ b/src/test/ui/derives/derives-span-Ord-struct.rs
@@ -0,0 +1,11 @@
+// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
+
+#[derive(Eq,PartialOrd,PartialEq)]
+struct Error;
+
+#[derive(Ord,Eq,PartialOrd,PartialEq)]
+struct Struct {
+    x: Error //~ ERROR
+}
+
+fn main() {}
diff --git a/src/test/ui/derives/derives-span-Ord-struct.stderr b/src/test/ui/derives/derives-span-Ord-struct.stderr
new file mode 100644
index 0000000..40dc3d0
--- /dev/null
+++ b/src/test/ui/derives/derives-span-Ord-struct.stderr
@@ -0,0 +1,11 @@
+error[E0277]: the trait bound `Error: std::cmp::Ord` is not satisfied
+  --> $DIR/derives-span-Ord-struct.rs:8:5
+   |
+LL |     x: Error
+   |     ^^^^^^^^ the trait `std::cmp::Ord` is not implemented for `Error`
+   |
+   = note: required by `std::cmp::Ord::cmp`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/derives/derives-span-Ord-tuple-struct.rs b/src/test/ui/derives/derives-span-Ord-tuple-struct.rs
new file mode 100644
index 0000000..4e09c27
--- /dev/null
+++ b/src/test/ui/derives/derives-span-Ord-tuple-struct.rs
@@ -0,0 +1,11 @@
+// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
+
+#[derive(Eq,PartialOrd,PartialEq)]
+struct Error;
+
+#[derive(Ord,Eq,PartialOrd,PartialEq)]
+struct Struct(
+    Error //~ ERROR
+);
+
+fn main() {}
diff --git a/src/test/ui/derives/derives-span-Ord-tuple-struct.stderr b/src/test/ui/derives/derives-span-Ord-tuple-struct.stderr
new file mode 100644
index 0000000..4a9dea8
--- /dev/null
+++ b/src/test/ui/derives/derives-span-Ord-tuple-struct.stderr
@@ -0,0 +1,11 @@
+error[E0277]: the trait bound `Error: std::cmp::Ord` is not satisfied
+  --> $DIR/derives-span-Ord-tuple-struct.rs:8:5
+   |
+LL |     Error
+   |     ^^^^^ the trait `std::cmp::Ord` is not implemented for `Error`
+   |
+   = note: required by `std::cmp::Ord::cmp`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/derives/derives-span-PartialEq-enum-struct-variant.rs b/src/test/ui/derives/derives-span-PartialEq-enum-struct-variant.rs
new file mode 100644
index 0000000..d66faa0
--- /dev/null
+++ b/src/test/ui/derives/derives-span-PartialEq-enum-struct-variant.rs
@@ -0,0 +1,14 @@
+// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
+
+
+struct Error;
+
+#[derive(PartialEq)]
+enum Enum {
+   A {
+     x: Error //~ ERROR
+//~^ ERROR
+   }
+}
+
+fn main() {}
diff --git a/src/test/ui/derives/derives-span-PartialEq-enum-struct-variant.stderr b/src/test/ui/derives/derives-span-PartialEq-enum-struct-variant.stderr
new file mode 100644
index 0000000..ed5468c
--- /dev/null
+++ b/src/test/ui/derives/derives-span-PartialEq-enum-struct-variant.stderr
@@ -0,0 +1,19 @@
+error[E0369]: binary operation `==` cannot be applied to type `Error`
+  --> $DIR/derives-span-PartialEq-enum-struct-variant.rs:9:6
+   |
+LL |      x: Error
+   |      ^^^^^^^^
+   |
+   = note: an implementation of `std::cmp::PartialEq` might be missing for `Error`
+
+error[E0369]: binary operation `!=` cannot be applied to type `Error`
+  --> $DIR/derives-span-PartialEq-enum-struct-variant.rs:9:6
+   |
+LL |      x: Error
+   |      ^^^^^^^^
+   |
+   = note: an implementation of `std::cmp::PartialEq` might be missing for `Error`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0369`.
diff --git a/src/test/ui/derives/derives-span-PartialEq-enum.rs b/src/test/ui/derives/derives-span-PartialEq-enum.rs
new file mode 100644
index 0000000..66edf460
--- /dev/null
+++ b/src/test/ui/derives/derives-span-PartialEq-enum.rs
@@ -0,0 +1,14 @@
+// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
+
+
+struct Error;
+
+#[derive(PartialEq)]
+enum Enum {
+   A(
+     Error //~ ERROR
+//~^ ERROR
+     )
+}
+
+fn main() {}
diff --git a/src/test/ui/derives/derives-span-PartialEq-enum.stderr b/src/test/ui/derives/derives-span-PartialEq-enum.stderr
new file mode 100644
index 0000000..06a88c0
--- /dev/null
+++ b/src/test/ui/derives/derives-span-PartialEq-enum.stderr
@@ -0,0 +1,19 @@
+error[E0369]: binary operation `==` cannot be applied to type `Error`
+  --> $DIR/derives-span-PartialEq-enum.rs:9:6
+   |
+LL |      Error
+   |      ^^^^^
+   |
+   = note: an implementation of `std::cmp::PartialEq` might be missing for `Error`
+
+error[E0369]: binary operation `!=` cannot be applied to type `Error`
+  --> $DIR/derives-span-PartialEq-enum.rs:9:6
+   |
+LL |      Error
+   |      ^^^^^
+   |
+   = note: an implementation of `std::cmp::PartialEq` might be missing for `Error`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0369`.
diff --git a/src/test/ui/derives/derives-span-PartialEq-struct.rs b/src/test/ui/derives/derives-span-PartialEq-struct.rs
new file mode 100644
index 0000000..ce5c67a
--- /dev/null
+++ b/src/test/ui/derives/derives-span-PartialEq-struct.rs
@@ -0,0 +1,12 @@
+// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
+
+
+struct Error;
+
+#[derive(PartialEq)]
+struct Struct {
+    x: Error //~ ERROR
+//~^ ERROR
+}
+
+fn main() {}
diff --git a/src/test/ui/derives/derives-span-PartialEq-struct.stderr b/src/test/ui/derives/derives-span-PartialEq-struct.stderr
new file mode 100644
index 0000000..b848104
--- /dev/null
+++ b/src/test/ui/derives/derives-span-PartialEq-struct.stderr
@@ -0,0 +1,19 @@
+error[E0369]: binary operation `==` cannot be applied to type `Error`
+  --> $DIR/derives-span-PartialEq-struct.rs:8:5
+   |
+LL |     x: Error
+   |     ^^^^^^^^
+   |
+   = note: an implementation of `std::cmp::PartialEq` might be missing for `Error`
+
+error[E0369]: binary operation `!=` cannot be applied to type `Error`
+  --> $DIR/derives-span-PartialEq-struct.rs:8:5
+   |
+LL |     x: Error
+   |     ^^^^^^^^
+   |
+   = note: an implementation of `std::cmp::PartialEq` might be missing for `Error`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0369`.
diff --git a/src/test/ui/derives/derives-span-PartialEq-tuple-struct.rs b/src/test/ui/derives/derives-span-PartialEq-tuple-struct.rs
new file mode 100644
index 0000000..eaa6283
--- /dev/null
+++ b/src/test/ui/derives/derives-span-PartialEq-tuple-struct.rs
@@ -0,0 +1,12 @@
+// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
+
+
+struct Error;
+
+#[derive(PartialEq)]
+struct Struct(
+    Error //~ ERROR
+//~^ ERROR
+);
+
+fn main() {}
diff --git a/src/test/ui/derives/derives-span-PartialEq-tuple-struct.stderr b/src/test/ui/derives/derives-span-PartialEq-tuple-struct.stderr
new file mode 100644
index 0000000..4398d25
--- /dev/null
+++ b/src/test/ui/derives/derives-span-PartialEq-tuple-struct.stderr
@@ -0,0 +1,19 @@
+error[E0369]: binary operation `==` cannot be applied to type `Error`
+  --> $DIR/derives-span-PartialEq-tuple-struct.rs:8:5
+   |
+LL |     Error
+   |     ^^^^^
+   |
+   = note: an implementation of `std::cmp::PartialEq` might be missing for `Error`
+
+error[E0369]: binary operation `!=` cannot be applied to type `Error`
+  --> $DIR/derives-span-PartialEq-tuple-struct.rs:8:5
+   |
+LL |     Error
+   |     ^^^^^
+   |
+   = note: an implementation of `std::cmp::PartialEq` might be missing for `Error`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0369`.
diff --git a/src/test/ui/derives/derives-span-PartialOrd-enum-struct-variant.rs b/src/test/ui/derives/derives-span-PartialOrd-enum-struct-variant.rs
new file mode 100644
index 0000000..0bc6f98
--- /dev/null
+++ b/src/test/ui/derives/derives-span-PartialOrd-enum-struct-variant.rs
@@ -0,0 +1,13 @@
+// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
+
+#[derive(PartialEq)]
+struct Error;
+
+#[derive(PartialOrd,PartialEq)]
+enum Enum {
+   A {
+     x: Error //~ ERROR
+   }
+}
+
+fn main() {}
diff --git a/src/test/ui/derives/derives-span-PartialOrd-enum-struct-variant.stderr b/src/test/ui/derives/derives-span-PartialOrd-enum-struct-variant.stderr
new file mode 100644
index 0000000..ac9f450
--- /dev/null
+++ b/src/test/ui/derives/derives-span-PartialOrd-enum-struct-variant.stderr
@@ -0,0 +1,12 @@
+error[E0277]: can't compare `Error` with `Error`
+  --> $DIR/derives-span-PartialOrd-enum-struct-variant.rs:9:6
+   |
+LL |      x: Error
+   |      ^^^^^^^^ no implementation for `Error < Error` and `Error > Error`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `Error`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/derives/derives-span-PartialOrd-enum.rs b/src/test/ui/derives/derives-span-PartialOrd-enum.rs
new file mode 100644
index 0000000..ee4423f
--- /dev/null
+++ b/src/test/ui/derives/derives-span-PartialOrd-enum.rs
@@ -0,0 +1,13 @@
+// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
+
+#[derive(PartialEq)]
+struct Error;
+
+#[derive(PartialOrd,PartialEq)]
+enum Enum {
+   A(
+     Error //~ ERROR
+     )
+}
+
+fn main() {}
diff --git a/src/test/ui/derives/derives-span-PartialOrd-enum.stderr b/src/test/ui/derives/derives-span-PartialOrd-enum.stderr
new file mode 100644
index 0000000..3e684ae
--- /dev/null
+++ b/src/test/ui/derives/derives-span-PartialOrd-enum.stderr
@@ -0,0 +1,12 @@
+error[E0277]: can't compare `Error` with `Error`
+  --> $DIR/derives-span-PartialOrd-enum.rs:9:6
+   |
+LL |      Error
+   |      ^^^^^ no implementation for `Error < Error` and `Error > Error`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `Error`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/derives/derives-span-PartialOrd-struct.rs b/src/test/ui/derives/derives-span-PartialOrd-struct.rs
new file mode 100644
index 0000000..48435e0
--- /dev/null
+++ b/src/test/ui/derives/derives-span-PartialOrd-struct.rs
@@ -0,0 +1,11 @@
+// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
+
+#[derive(PartialEq)]
+struct Error;
+
+#[derive(PartialOrd,PartialEq)]
+struct Struct {
+    x: Error //~ ERROR
+}
+
+fn main() {}
diff --git a/src/test/ui/derives/derives-span-PartialOrd-struct.stderr b/src/test/ui/derives/derives-span-PartialOrd-struct.stderr
new file mode 100644
index 0000000..10659aa
--- /dev/null
+++ b/src/test/ui/derives/derives-span-PartialOrd-struct.stderr
@@ -0,0 +1,12 @@
+error[E0277]: can't compare `Error` with `Error`
+  --> $DIR/derives-span-PartialOrd-struct.rs:8:5
+   |
+LL |     x: Error
+   |     ^^^^^^^^ no implementation for `Error < Error` and `Error > Error`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `Error`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/derives/derives-span-PartialOrd-tuple-struct.rs b/src/test/ui/derives/derives-span-PartialOrd-tuple-struct.rs
new file mode 100644
index 0000000..2aa412e
--- /dev/null
+++ b/src/test/ui/derives/derives-span-PartialOrd-tuple-struct.rs
@@ -0,0 +1,11 @@
+// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
+
+#[derive(PartialEq)]
+struct Error;
+
+#[derive(PartialOrd,PartialEq)]
+struct Struct(
+    Error //~ ERROR
+);
+
+fn main() {}
diff --git a/src/test/ui/derives/derives-span-PartialOrd-tuple-struct.stderr b/src/test/ui/derives/derives-span-PartialOrd-tuple-struct.stderr
new file mode 100644
index 0000000..cbe05e3
--- /dev/null
+++ b/src/test/ui/derives/derives-span-PartialOrd-tuple-struct.stderr
@@ -0,0 +1,12 @@
+error[E0277]: can't compare `Error` with `Error`
+  --> $DIR/derives-span-PartialOrd-tuple-struct.rs:8:5
+   |
+LL |     Error
+   |     ^^^^^ no implementation for `Error < Error` and `Error > Error`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `Error`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/derives/deriving-bounds.rs b/src/test/ui/derives/deriving-bounds.rs
new file mode 100644
index 0000000..607cfa1
--- /dev/null
+++ b/src/test/ui/derives/deriving-bounds.rs
@@ -0,0 +1,9 @@
+#[derive(Send)]
+//~^ ERROR this unsafe trait should be implemented explicitly
+struct Test;
+
+#[derive(Sync)]
+//~^ ERROR this unsafe trait should be implemented explicitly
+struct Test1;
+
+pub fn main() {}
diff --git a/src/test/ui/derives/deriving-bounds.stderr b/src/test/ui/derives/deriving-bounds.stderr
new file mode 100644
index 0000000..deb84fd
--- /dev/null
+++ b/src/test/ui/derives/deriving-bounds.stderr
@@ -0,0 +1,14 @@
+error: this unsafe trait should be implemented explicitly
+  --> $DIR/deriving-bounds.rs:1:10
+   |
+LL | #[derive(Send)]
+   |          ^^^^
+
+error: this unsafe trait should be implemented explicitly
+  --> $DIR/deriving-bounds.rs:5:10
+   |
+LL | #[derive(Sync)]
+   |          ^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/derives/deriving-copyclone.rs b/src/test/ui/derives/deriving-copyclone.rs
new file mode 100644
index 0000000..afe6196
--- /dev/null
+++ b/src/test/ui/derives/deriving-copyclone.rs
@@ -0,0 +1,38 @@
+// this will get a no-op Clone impl
+#[derive(Copy, Clone)]
+struct A {
+    a: i32,
+    b: i64
+}
+
+// this will get a deep Clone impl
+#[derive(Copy, Clone)]
+struct B<T> {
+    a: i32,
+    b: T
+}
+
+struct C; // not Copy or Clone
+#[derive(Clone)] struct D; // Clone but not Copy
+
+fn is_copy<T: Copy>(_: T) {}
+fn is_clone<T: Clone>(_: T) {}
+
+fn main() {
+    // A can be copied and cloned
+    is_copy(A { a: 1, b: 2 });
+    is_clone(A { a: 1, b: 2 });
+
+    // B<i32> can be copied and cloned
+    is_copy(B { a: 1, b: 2 });
+    is_clone(B { a: 1, b: 2 });
+
+    // B<C> cannot be copied or cloned
+    is_copy(B { a: 1, b: C }); //~ERROR Copy
+    is_clone(B { a: 1, b: C }); //~ERROR Clone
+
+    // B<D> can be cloned but not copied
+    is_copy(B { a: 1, b: D }); //~ERROR Copy
+    is_clone(B { a: 1, b: D });
+}
+
diff --git a/src/test/ui/derives/deriving-copyclone.stderr b/src/test/ui/derives/deriving-copyclone.stderr
new file mode 100644
index 0000000..e6060c2
--- /dev/null
+++ b/src/test/ui/derives/deriving-copyclone.stderr
@@ -0,0 +1,42 @@
+error[E0277]: the trait bound `C: std::marker::Copy` is not satisfied
+  --> $DIR/deriving-copyclone.rs:31:5
+   |
+LL |     is_copy(B { a: 1, b: C });
+   |     ^^^^^^^ the trait `std::marker::Copy` is not implemented for `C`
+   |
+   = note: required because of the requirements on the impl of `std::marker::Copy` for `B<C>`
+note: required by `is_copy`
+  --> $DIR/deriving-copyclone.rs:18:1
+   |
+LL | fn is_copy<T: Copy>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `C: std::clone::Clone` is not satisfied
+  --> $DIR/deriving-copyclone.rs:32:5
+   |
+LL |     is_clone(B { a: 1, b: C });
+   |     ^^^^^^^^ the trait `std::clone::Clone` is not implemented for `C`
+   |
+   = note: required because of the requirements on the impl of `std::clone::Clone` for `B<C>`
+note: required by `is_clone`
+  --> $DIR/deriving-copyclone.rs:19:1
+   |
+LL | fn is_clone<T: Clone>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `D: std::marker::Copy` is not satisfied
+  --> $DIR/deriving-copyclone.rs:35:5
+   |
+LL |     is_copy(B { a: 1, b: D });
+   |     ^^^^^^^ the trait `std::marker::Copy` is not implemented for `D`
+   |
+   = note: required because of the requirements on the impl of `std::marker::Copy` for `B<D>`
+note: required by `is_copy`
+  --> $DIR/deriving-copyclone.rs:18:1
+   |
+LL | fn is_copy<T: Copy>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/derives/deriving-meta-empty-trait-list.rs b/src/test/ui/derives/deriving-meta-empty-trait-list.rs
new file mode 100644
index 0000000..8824841
--- /dev/null
+++ b/src/test/ui/derives/deriving-meta-empty-trait-list.rs
@@ -0,0 +1,6 @@
+// compile-pass
+
+#[derive()] //~ WARNING empty trait list in `derive`
+struct Bar;
+
+pub fn main() {}
diff --git a/src/test/ui/derives/deriving-meta-empty-trait-list.stderr b/src/test/ui/derives/deriving-meta-empty-trait-list.stderr
new file mode 100644
index 0000000..f8414b6
--- /dev/null
+++ b/src/test/ui/derives/deriving-meta-empty-trait-list.stderr
@@ -0,0 +1,6 @@
+warning: empty trait list in `derive`
+  --> $DIR/deriving-meta-empty-trait-list.rs:3:1
+   |
+LL | #[derive()]
+   | ^^^^^^^^^^^
+
diff --git a/src/test/ui/derives/deriving-meta-unknown-trait.rs b/src/test/ui/derives/deriving-meta-unknown-trait.rs
new file mode 100644
index 0000000..2b29f10
--- /dev/null
+++ b/src/test/ui/derives/deriving-meta-unknown-trait.rs
@@ -0,0 +1,7 @@
+// ignore-tidy-linelength
+
+#[derive(Eqr)]
+//~^ ERROR cannot find derive macro `Eqr` in this scope
+struct Foo;
+
+pub fn main() {}
diff --git a/src/test/ui/derives/deriving-meta-unknown-trait.stderr b/src/test/ui/derives/deriving-meta-unknown-trait.stderr
new file mode 100644
index 0000000..2b121ac
--- /dev/null
+++ b/src/test/ui/derives/deriving-meta-unknown-trait.stderr
@@ -0,0 +1,8 @@
+error: cannot find derive macro `Eqr` in this scope
+  --> $DIR/deriving-meta-unknown-trait.rs:3:10
+   |
+LL | #[derive(Eqr)]
+   |          ^^^ help: try: `Eq`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/derives/deriving-no-inner-impl-error-message.rs b/src/test/ui/derives/deriving-no-inner-impl-error-message.rs
new file mode 100644
index 0000000..d3ac5d2
--- /dev/null
+++ b/src/test/ui/derives/deriving-no-inner-impl-error-message.rs
@@ -0,0 +1,15 @@
+struct NoCloneOrEq;
+
+#[derive(PartialEq)]
+struct E {
+    x: NoCloneOrEq //~ ERROR binary operation `==` cannot be applied to type `NoCloneOrEq`
+         //~^ ERROR binary operation `!=` cannot be applied to type `NoCloneOrEq`
+}
+#[derive(Clone)]
+struct C {
+    x: NoCloneOrEq
+    //~^ ERROR `NoCloneOrEq: std::clone::Clone` is not satisfied
+}
+
+
+fn main() {}
diff --git a/src/test/ui/derives/deriving-no-inner-impl-error-message.stderr b/src/test/ui/derives/deriving-no-inner-impl-error-message.stderr
new file mode 100644
index 0000000..3206eec
--- /dev/null
+++ b/src/test/ui/derives/deriving-no-inner-impl-error-message.stderr
@@ -0,0 +1,28 @@
+error[E0369]: binary operation `==` cannot be applied to type `NoCloneOrEq`
+  --> $DIR/deriving-no-inner-impl-error-message.rs:5:5
+   |
+LL |     x: NoCloneOrEq
+   |     ^^^^^^^^^^^^^^
+   |
+   = note: an implementation of `std::cmp::PartialEq` might be missing for `NoCloneOrEq`
+
+error[E0369]: binary operation `!=` cannot be applied to type `NoCloneOrEq`
+  --> $DIR/deriving-no-inner-impl-error-message.rs:5:5
+   |
+LL |     x: NoCloneOrEq
+   |     ^^^^^^^^^^^^^^
+   |
+   = note: an implementation of `std::cmp::PartialEq` might be missing for `NoCloneOrEq`
+
+error[E0277]: the trait bound `NoCloneOrEq: std::clone::Clone` is not satisfied
+  --> $DIR/deriving-no-inner-impl-error-message.rs:10:5
+   |
+LL |     x: NoCloneOrEq
+   |     ^^^^^^^^^^^^^^ the trait `std::clone::Clone` is not implemented for `NoCloneOrEq`
+   |
+   = note: required by `std::clone::Clone::clone`
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0277, E0369.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/derives/deriving-non-type.rs b/src/test/ui/derives/deriving-non-type.rs
new file mode 100644
index 0000000..7e14c12
--- /dev/null
+++ b/src/test/ui/derives/deriving-non-type.rs
@@ -0,0 +1,30 @@
+#![allow(dead_code)]
+
+struct S;
+
+#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to structs, enums and unions
+trait T { }
+
+#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to structs, enums and unions
+impl S { }
+
+#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to structs, enums and unions
+impl T for S { }
+
+#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to structs, enums and unions
+static s: usize = 0;
+
+#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to structs, enums and unions
+const c: usize = 0;
+
+#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to structs, enums and unions
+mod m { }
+
+#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to structs, enums and unions
+extern "C" { }
+
+#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to structs, enums and unions
+type A = usize;
+
+#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to structs, enums and unions
+fn main() { }
diff --git a/src/test/ui/derives/deriving-non-type.stderr b/src/test/ui/derives/deriving-non-type.stderr
new file mode 100644
index 0000000..563e76d
--- /dev/null
+++ b/src/test/ui/derives/deriving-non-type.stderr
@@ -0,0 +1,56 @@
+error: `derive` may only be applied to structs, enums and unions
+  --> $DIR/deriving-non-type.rs:5:1
+   |
+LL | #[derive(PartialEq)]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: `derive` may only be applied to structs, enums and unions
+  --> $DIR/deriving-non-type.rs:8:1
+   |
+LL | #[derive(PartialEq)]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: `derive` may only be applied to structs, enums and unions
+  --> $DIR/deriving-non-type.rs:11:1
+   |
+LL | #[derive(PartialEq)]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: `derive` may only be applied to structs, enums and unions
+  --> $DIR/deriving-non-type.rs:14:1
+   |
+LL | #[derive(PartialEq)]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: `derive` may only be applied to structs, enums and unions
+  --> $DIR/deriving-non-type.rs:17:1
+   |
+LL | #[derive(PartialEq)]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: `derive` may only be applied to structs, enums and unions
+  --> $DIR/deriving-non-type.rs:20:1
+   |
+LL | #[derive(PartialEq)]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: `derive` may only be applied to structs, enums and unions
+  --> $DIR/deriving-non-type.rs:23:1
+   |
+LL | #[derive(PartialEq)]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: `derive` may only be applied to structs, enums and unions
+  --> $DIR/deriving-non-type.rs:26:1
+   |
+LL | #[derive(PartialEq)]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: `derive` may only be applied to structs, enums and unions
+  --> $DIR/deriving-non-type.rs:29:1
+   |
+LL | #[derive(PartialEq)]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 9 previous errors
+
diff --git a/src/test/ui/derives/deriving-primitive.rs b/src/test/ui/derives/deriving-primitive.rs
new file mode 100644
index 0000000..53acf61
--- /dev/null
+++ b/src/test/ui/derives/deriving-primitive.rs
@@ -0,0 +1,5 @@
+#[derive(FromPrimitive)] //~ ERROR cannot find derive macro `FromPrimitive` in this scope
+enum Foo {}
+
+fn main() {}
+
diff --git a/src/test/ui/derives/deriving-primitive.stderr b/src/test/ui/derives/deriving-primitive.stderr
new file mode 100644
index 0000000..d1b4449
--- /dev/null
+++ b/src/test/ui/derives/deriving-primitive.stderr
@@ -0,0 +1,8 @@
+error: cannot find derive macro `FromPrimitive` in this scope
+  --> $DIR/deriving-primitive.rs:1:10
+   |
+LL | #[derive(FromPrimitive)]
+   |          ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/derives/deriving-with-repr-packed.rs b/src/test/ui/derives/deriving-with-repr-packed.rs
new file mode 100644
index 0000000..66b0f85
--- /dev/null
+++ b/src/test/ui/derives/deriving-with-repr-packed.rs
@@ -0,0 +1,31 @@
+#![deny(safe_packed_borrows)]
+
+// check that derive on a packed struct with non-Copy fields
+// correctly. This can't be made to work perfectly because
+// we can't just use the field from the struct as it might
+// not be aligned.
+
+#[derive(Copy, Clone, PartialEq, Eq)]
+//~^ ERROR #[derive] can't be used
+//~| hard error
+//~^^^ ERROR #[derive] can't be used
+//~| hard error
+#[repr(packed)]
+pub struct Foo<T>(T, T, T);
+
+#[derive(PartialEq, Eq)]
+//~^ ERROR #[derive] can't be used
+//~| hard error
+#[repr(packed)]
+pub struct Bar(u32, u32, u32);
+
+#[derive(PartialEq)]
+struct Y(usize);
+
+#[derive(PartialEq)]
+//~^ ERROR #[derive] can't be used
+//~| hard error
+#[repr(packed)]
+struct X(Y);
+
+fn main() {}
diff --git a/src/test/ui/derives/deriving-with-repr-packed.stderr b/src/test/ui/derives/deriving-with-repr-packed.stderr
new file mode 100644
index 0000000..9d96908
--- /dev/null
+++ b/src/test/ui/derives/deriving-with-repr-packed.stderr
@@ -0,0 +1,43 @@
+error: #[derive] can't be used on a #[repr(packed)] struct with type or const parameters (error E0133)
+  --> $DIR/deriving-with-repr-packed.rs:8:16
+   |
+LL | #[derive(Copy, Clone, PartialEq, Eq)]
+   |                ^^^^^
+   |
+note: lint level defined here
+  --> $DIR/deriving-with-repr-packed.rs:1:9
+   |
+LL | #![deny(safe_packed_borrows)]
+   |         ^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #46043 <https://github.com/rust-lang/rust/issues/46043>
+
+error: #[derive] can't be used on a #[repr(packed)] struct with type or const parameters (error E0133)
+  --> $DIR/deriving-with-repr-packed.rs:8:23
+   |
+LL | #[derive(Copy, Clone, PartialEq, Eq)]
+   |                       ^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #46043 <https://github.com/rust-lang/rust/issues/46043>
+
+error: #[derive] can't be used on a #[repr(packed)] struct that does not derive Copy (error E0133)
+  --> $DIR/deriving-with-repr-packed.rs:16:10
+   |
+LL | #[derive(PartialEq, Eq)]
+   |          ^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #46043 <https://github.com/rust-lang/rust/issues/46043>
+
+error: #[derive] can't be used on a #[repr(packed)] struct that does not derive Copy (error E0133)
+  --> $DIR/deriving-with-repr-packed.rs:25:10
+   |
+LL | #[derive(PartialEq)]
+   |          ^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #46043 <https://github.com/rust-lang/rust/issues/46043>
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/destructure-trait-ref.rs b/src/test/ui/destructure-trait-ref.rs
new file mode 100644
index 0000000..66be493
--- /dev/null
+++ b/src/test/ui/destructure-trait-ref.rs
@@ -0,0 +1,45 @@
+// The regression test for #15031 to make sure destructuring trait
+// reference work properly.
+
+#![feature(box_patterns)]
+#![feature(box_syntax)]
+
+trait T { fn foo(&self) {} }
+impl T for isize {}
+
+fn main() {
+    // For an expression of the form:
+    //
+    //      let &...&x = &..&SomeTrait;
+    //
+    // Say we have n `&` at the left hand and m `&` right hand, then:
+    // if n < m, we are golden;
+    // if n == m, it's a derefing non-derefable type error;
+    // if n > m, it's a type mismatch error.
+
+    // n < m
+    let &x = &(&1isize as &T);
+    let &x = &&(&1isize as &T);
+    let &&x = &&(&1isize as &T);
+
+    // n == m
+    let &x = &1isize as &T;      //~ ERROR type `&dyn T` cannot be dereferenced
+    let &&x = &(&1isize as &T);  //~ ERROR type `&dyn T` cannot be dereferenced
+    let box x = box 1isize as Box<T>; //~ ERROR type `std::boxed::Box<dyn T>` cannot be dereferenced
+
+    // n > m
+    let &&x = &1isize as &T;
+    //~^ ERROR mismatched types
+    //~| expected type `dyn T`
+    //~| found type `&_`
+    //~| expected trait T, found reference
+    let &&&x = &(&1isize as &T);
+    //~^ ERROR mismatched types
+    //~| expected type `dyn T`
+    //~| found type `&_`
+    //~| expected trait T, found reference
+    let box box x = box 1isize as Box<T>;
+    //~^ ERROR mismatched types
+    //~| expected type `dyn T`
+    //~| found type `std::boxed::Box<_>`
+}
diff --git a/src/test/ui/destructure-trait-ref.stderr b/src/test/ui/destructure-trait-ref.stderr
new file mode 100644
index 0000000..8fc2b76
--- /dev/null
+++ b/src/test/ui/destructure-trait-ref.stderr
@@ -0,0 +1,51 @@
+error[E0033]: type `&dyn T` cannot be dereferenced
+  --> $DIR/destructure-trait-ref.rs:26:9
+   |
+LL |     let &x = &1isize as &T;
+   |         ^^ type `&dyn T` cannot be dereferenced
+
+error[E0033]: type `&dyn T` cannot be dereferenced
+  --> $DIR/destructure-trait-ref.rs:27:10
+   |
+LL |     let &&x = &(&1isize as &T);
+   |          ^^ type `&dyn T` cannot be dereferenced
+
+error[E0033]: type `std::boxed::Box<dyn T>` cannot be dereferenced
+  --> $DIR/destructure-trait-ref.rs:28:9
+   |
+LL |     let box x = box 1isize as Box<T>;
+   |         ^^^^^ type `std::boxed::Box<dyn T>` cannot be dereferenced
+
+error[E0308]: mismatched types
+  --> $DIR/destructure-trait-ref.rs:31:10
+   |
+LL |     let &&x = &1isize as &T;
+   |          ^^ expected trait T, found reference
+   |
+   = note: expected type `dyn T`
+              found type `&_`
+   = help: did you mean `x: &dyn T`?
+
+error[E0308]: mismatched types
+  --> $DIR/destructure-trait-ref.rs:36:11
+   |
+LL |     let &&&x = &(&1isize as &T);
+   |           ^^ expected trait T, found reference
+   |
+   = note: expected type `dyn T`
+              found type `&_`
+   = help: did you mean `x: &dyn T`?
+
+error[E0308]: mismatched types
+  --> $DIR/destructure-trait-ref.rs:41:13
+   |
+LL |     let box box x = box 1isize as Box<T>;
+   |             ^^^^^ expected trait T, found struct `std::boxed::Box`
+   |
+   = note: expected type `dyn T`
+              found type `std::boxed::Box<_>`
+
+error: aborting due to 6 previous errors
+
+Some errors occurred: E0033, E0308.
+For more information about an error, try `rustc --explain E0033`.
diff --git a/src/test/ui/did_you_mean/E0178.rs b/src/test/ui/did_you_mean/E0178.rs
new file mode 100644
index 0000000..aad95dc
--- /dev/null
+++ b/src/test/ui/did_you_mean/E0178.rs
@@ -0,0 +1,11 @@
+trait Foo {}
+
+struct Bar<'a> {
+    w: &'a Foo + Copy, //~ ERROR expected a path
+    x: &'a Foo + 'a, //~ ERROR expected a path
+    y: &'a mut Foo + 'a, //~ ERROR expected a path
+    z: fn() -> Foo + 'a, //~ ERROR expected a path
+}
+
+fn main() {
+}
diff --git a/src/test/ui/did_you_mean/E0178.stderr b/src/test/ui/did_you_mean/E0178.stderr
new file mode 100644
index 0000000..44e6ddd
--- /dev/null
+++ b/src/test/ui/did_you_mean/E0178.stderr
@@ -0,0 +1,27 @@
+error[E0178]: expected a path on the left-hand side of `+`, not `&'a Foo`
+  --> $DIR/E0178.rs:4:8
+   |
+LL |     w: &'a Foo + Copy,
+   |        ^^^^^^^^^^^^^^ help: try adding parentheses: `&'a (Foo + Copy)`
+
+error[E0178]: expected a path on the left-hand side of `+`, not `&'a Foo`
+  --> $DIR/E0178.rs:5:8
+   |
+LL |     x: &'a Foo + 'a,
+   |        ^^^^^^^^^^^^ help: try adding parentheses: `&'a (Foo + 'a)`
+
+error[E0178]: expected a path on the left-hand side of `+`, not `&'a mut Foo`
+  --> $DIR/E0178.rs:6:8
+   |
+LL |     y: &'a mut Foo + 'a,
+   |        ^^^^^^^^^^^^^^^^ help: try adding parentheses: `&'a mut (Foo + 'a)`
+
+error[E0178]: expected a path on the left-hand side of `+`, not `fn() -> Foo`
+  --> $DIR/E0178.rs:7:8
+   |
+LL |     z: fn() -> Foo + 'a,
+   |        ^^^^^^^^^^^^^^^^ perhaps you forgot parentheses?
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0178`.
diff --git a/src/test/ui/did_you_mean/bad-assoc-expr.rs b/src/test/ui/did_you_mean/bad-assoc-expr.rs
new file mode 100644
index 0000000..1d58475
--- /dev/null
+++ b/src/test/ui/did_you_mean/bad-assoc-expr.rs
@@ -0,0 +1,36 @@
+fn main() {
+    let a = [1, 2, 3, 4];
+    [i32; 4]::clone(&a);
+    //~^ ERROR missing angle brackets in associated item path
+
+    [i32]::as_ref(&a);
+    //~^ ERROR missing angle brackets in associated item path
+
+    (u8)::clone(&0);
+    //~^ ERROR missing angle brackets in associated item path
+
+    (u8, u8)::clone(&(0, 0));
+    //~^ ERROR missing angle brackets in associated item path
+
+    &(u8)::clone(&0);
+    //~^ ERROR missing angle brackets in associated item path
+
+    10 + (u8)::clone(&0);
+    //~^ ERROR missing angle brackets in associated item path
+}
+
+macro_rules! expr {
+    ($ty: ty) => ($ty::clone(&0))
+    //~^ ERROR missing angle brackets in associated item path
+}
+macro_rules! ty {
+    () => (u8)
+}
+
+fn check_macros() {
+    expr!(u8);
+    let _ = ty!()::clone(&0);
+    //~^ ERROR missing angle brackets in associated item path
+    ty!()::clone(&0);
+    //~^ ERROR missing angle brackets in associated item path
+}
diff --git a/src/test/ui/did_you_mean/bad-assoc-expr.stderr b/src/test/ui/did_you_mean/bad-assoc-expr.stderr
new file mode 100644
index 0000000..2024564
--- /dev/null
+++ b/src/test/ui/did_you_mean/bad-assoc-expr.stderr
@@ -0,0 +1,59 @@
+error: missing angle brackets in associated item path
+  --> $DIR/bad-assoc-expr.rs:3:5
+   |
+LL |     [i32; 4]::clone(&a);
+   |     ^^^^^^^^^^^^^^^ help: try: `<[i32; 4]>::clone`
+
+error: missing angle brackets in associated item path
+  --> $DIR/bad-assoc-expr.rs:6:5
+   |
+LL |     [i32]::as_ref(&a);
+   |     ^^^^^^^^^^^^^ help: try: `<[i32]>::as_ref`
+
+error: missing angle brackets in associated item path
+  --> $DIR/bad-assoc-expr.rs:9:5
+   |
+LL |     (u8)::clone(&0);
+   |     ^^^^^^^^^^^ help: try: `<(u8)>::clone`
+
+error: missing angle brackets in associated item path
+  --> $DIR/bad-assoc-expr.rs:12:5
+   |
+LL |     (u8, u8)::clone(&(0, 0));
+   |     ^^^^^^^^^^^^^^^ help: try: `<(u8, u8)>::clone`
+
+error: missing angle brackets in associated item path
+  --> $DIR/bad-assoc-expr.rs:15:6
+   |
+LL |     &(u8)::clone(&0);
+   |      ^^^^^^^^^^^ help: try: `<(u8)>::clone`
+
+error: missing angle brackets in associated item path
+  --> $DIR/bad-assoc-expr.rs:18:10
+   |
+LL |     10 + (u8)::clone(&0);
+   |          ^^^^^^^^^^^ help: try: `<(u8)>::clone`
+
+error: missing angle brackets in associated item path
+  --> $DIR/bad-assoc-expr.rs:32:13
+   |
+LL |     let _ = ty!()::clone(&0);
+   |             ^^^^^^^^^^^^ help: try: `<ty!()>::clone`
+
+error: missing angle brackets in associated item path
+  --> $DIR/bad-assoc-expr.rs:34:5
+   |
+LL |     ty!()::clone(&0);
+   |     ^^^^^^^^^^^^ help: try: `<ty!()>::clone`
+
+error: missing angle brackets in associated item path
+  --> $DIR/bad-assoc-expr.rs:23:19
+   |
+LL |     ($ty: ty) => ($ty::clone(&0))
+   |                   ^^^^^^^^^^ help: try: `<$ty>::clone`
+...
+LL |     expr!(u8);
+   |     ---------- in this macro invocation
+
+error: aborting due to 9 previous errors
+
diff --git a/src/test/ui/did_you_mean/bad-assoc-pat.rs b/src/test/ui/did_you_mean/bad-assoc-pat.rs
new file mode 100644
index 0000000..7e7ba59
--- /dev/null
+++ b/src/test/ui/did_you_mean/bad-assoc-pat.rs
@@ -0,0 +1,36 @@
+fn main() {
+    match 0u8 {
+        [u8]::AssocItem => {}
+        //~^ ERROR missing angle brackets in associated item path
+        //~| ERROR no associated item named `AssocItem` found for type `[u8]` in the current scope
+        (u8, u8)::AssocItem => {}
+        //~^ ERROR missing angle brackets in associated item path
+        //~| ERROR no associated item named `AssocItem` found for type `(u8, u8)` in the current sco
+        _::AssocItem => {}
+        //~^ ERROR missing angle brackets in associated item path
+        //~| ERROR no associated item named `AssocItem` found for type `_` in the current scope
+    }
+    match &0u8 {
+        &(u8,)::AssocItem => {}
+        //~^ ERROR missing angle brackets in associated item path
+        //~| ERROR no associated item named `AssocItem` found for type `(u8,)` in the current scope
+    }
+}
+
+macro_rules! pat {
+    ($ty: ty) => ($ty::AssocItem)
+    //~^ ERROR missing angle brackets in associated item path
+    //~| ERROR no associated item named `AssocItem` found for type `u8` in the current scope
+}
+macro_rules! ty {
+    () => (u8)
+}
+
+fn check_macros() {
+    match 0u8 {
+        pat!(u8) => {}
+        ty!()::AssocItem => {}
+        //~^ ERROR missing angle brackets in associated item path
+        //~| ERROR no associated item named `AssocItem` found for type `u8` in the current scope
+    }
+}
diff --git a/src/test/ui/did_you_mean/bad-assoc-pat.stderr b/src/test/ui/did_you_mean/bad-assoc-pat.stderr
new file mode 100644
index 0000000..59b8654
--- /dev/null
+++ b/src/test/ui/did_you_mean/bad-assoc-pat.stderr
@@ -0,0 +1,81 @@
+error: missing angle brackets in associated item path
+  --> $DIR/bad-assoc-pat.rs:3:9
+   |
+LL |         [u8]::AssocItem => {}
+   |         ^^^^^^^^^^^^^^^ help: try: `<[u8]>::AssocItem`
+
+error: missing angle brackets in associated item path
+  --> $DIR/bad-assoc-pat.rs:6:9
+   |
+LL |         (u8, u8)::AssocItem => {}
+   |         ^^^^^^^^^^^^^^^^^^^ help: try: `<(u8, u8)>::AssocItem`
+
+error: missing angle brackets in associated item path
+  --> $DIR/bad-assoc-pat.rs:9:9
+   |
+LL |         _::AssocItem => {}
+   |         ^^^^^^^^^^^^ help: try: `<_>::AssocItem`
+
+error: missing angle brackets in associated item path
+  --> $DIR/bad-assoc-pat.rs:14:10
+   |
+LL |         &(u8,)::AssocItem => {}
+   |          ^^^^^^^^^^^^^^^^ help: try: `<(u8,)>::AssocItem`
+
+error: missing angle brackets in associated item path
+  --> $DIR/bad-assoc-pat.rs:32:9
+   |
+LL |         ty!()::AssocItem => {}
+   |         ^^^^^^^^^^^^^^^^ help: try: `<ty!()>::AssocItem`
+
+error: missing angle brackets in associated item path
+  --> $DIR/bad-assoc-pat.rs:21:19
+   |
+LL |     ($ty: ty) => ($ty::AssocItem)
+   |                   ^^^^^^^^^^^^^^ help: try: `<$ty>::AssocItem`
+...
+LL |         pat!(u8) => {}
+   |         -------- in this macro invocation
+
+error[E0599]: no associated item named `AssocItem` found for type `[u8]` in the current scope
+  --> $DIR/bad-assoc-pat.rs:3:15
+   |
+LL |         [u8]::AssocItem => {}
+   |               ^^^^^^^^^ associated item not found in `[u8]`
+
+error[E0599]: no associated item named `AssocItem` found for type `(u8, u8)` in the current scope
+  --> $DIR/bad-assoc-pat.rs:6:19
+   |
+LL |         (u8, u8)::AssocItem => {}
+   |                   ^^^^^^^^^ associated item not found in `(u8, u8)`
+
+error[E0599]: no associated item named `AssocItem` found for type `_` in the current scope
+  --> $DIR/bad-assoc-pat.rs:9:12
+   |
+LL |         _::AssocItem => {}
+   |            ^^^^^^^^^ associated item not found in `_`
+
+error[E0599]: no associated item named `AssocItem` found for type `(u8,)` in the current scope
+  --> $DIR/bad-assoc-pat.rs:14:17
+   |
+LL |         &(u8,)::AssocItem => {}
+   |                 ^^^^^^^^^ associated item not found in `(u8,)`
+
+error[E0599]: no associated item named `AssocItem` found for type `u8` in the current scope
+  --> $DIR/bad-assoc-pat.rs:21:24
+   |
+LL |     ($ty: ty) => ($ty::AssocItem)
+   |                        ^^^^^^^^^ associated item not found in `u8`
+...
+LL |         pat!(u8) => {}
+   |         -------- in this macro invocation
+
+error[E0599]: no associated item named `AssocItem` found for type `u8` in the current scope
+  --> $DIR/bad-assoc-pat.rs:32:16
+   |
+LL |         ty!()::AssocItem => {}
+   |                ^^^^^^^^^ associated item not found in `u8`
+
+error: aborting due to 12 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/did_you_mean/bad-assoc-ty.rs b/src/test/ui/did_you_mean/bad-assoc-ty.rs
new file mode 100644
index 0000000..85e36f8
--- /dev/null
+++ b/src/test/ui/did_you_mean/bad-assoc-ty.rs
@@ -0,0 +1,48 @@
+type A = [u8; 4]::AssocTy;
+//~^ ERROR missing angle brackets in associated item path
+//~| ERROR ambiguous associated type
+
+type B = [u8]::AssocTy;
+//~^ ERROR missing angle brackets in associated item path
+//~| ERROR ambiguous associated type
+
+type C = (u8)::AssocTy;
+//~^ ERROR missing angle brackets in associated item path
+//~| ERROR ambiguous associated type
+
+type D = (u8, u8)::AssocTy;
+//~^ ERROR missing angle brackets in associated item path
+//~| ERROR ambiguous associated type
+
+type E = _::AssocTy;
+//~^ ERROR missing angle brackets in associated item path
+//~| ERROR the type placeholder `_` is not allowed within types on item signatures
+
+type F = &'static (u8)::AssocTy;
+//~^ ERROR missing angle brackets in associated item path
+//~| ERROR ambiguous associated type
+
+// Qualified paths cannot appear in bounds, so the recovery
+// should apply to the whole sum and not `(Send)`.
+type G = 'static + (Send)::AssocTy;
+//~^ ERROR missing angle brackets in associated item path
+//~| ERROR ambiguous associated type
+
+// This is actually a legal path with fn-like generic arguments in the middle!
+// Recovery should not apply in this context.
+type H = Fn(u8) -> (u8)::Output;
+//~^ ERROR ambiguous associated type
+
+macro_rules! ty {
+    ($ty: ty) => ($ty::AssocTy);
+    //~^ ERROR missing angle brackets in associated item path
+    //~| ERROR ambiguous associated type
+    () => (u8);
+}
+
+type J = ty!(u8);
+type I = ty!()::AssocTy;
+//~^ ERROR missing angle brackets in associated item path
+//~| ERROR ambiguous associated type
+
+fn main() {}
diff --git a/src/test/ui/did_you_mean/bad-assoc-ty.stderr b/src/test/ui/did_you_mean/bad-assoc-ty.stderr
new file mode 100644
index 0000000..7e7f18f
--- /dev/null
+++ b/src/test/ui/did_you_mean/bad-assoc-ty.stderr
@@ -0,0 +1,124 @@
+error: missing angle brackets in associated item path
+  --> $DIR/bad-assoc-ty.rs:1:10
+   |
+LL | type A = [u8; 4]::AssocTy;
+   |          ^^^^^^^^^^^^^^^^ help: try: `<[u8; 4]>::AssocTy`
+
+error: missing angle brackets in associated item path
+  --> $DIR/bad-assoc-ty.rs:5:10
+   |
+LL | type B = [u8]::AssocTy;
+   |          ^^^^^^^^^^^^^ help: try: `<[u8]>::AssocTy`
+
+error: missing angle brackets in associated item path
+  --> $DIR/bad-assoc-ty.rs:9:10
+   |
+LL | type C = (u8)::AssocTy;
+   |          ^^^^^^^^^^^^^ help: try: `<(u8)>::AssocTy`
+
+error: missing angle brackets in associated item path
+  --> $DIR/bad-assoc-ty.rs:13:10
+   |
+LL | type D = (u8, u8)::AssocTy;
+   |          ^^^^^^^^^^^^^^^^^ help: try: `<(u8, u8)>::AssocTy`
+
+error: missing angle brackets in associated item path
+  --> $DIR/bad-assoc-ty.rs:17:10
+   |
+LL | type E = _::AssocTy;
+   |          ^^^^^^^^^^ help: try: `<_>::AssocTy`
+
+error: missing angle brackets in associated item path
+  --> $DIR/bad-assoc-ty.rs:21:19
+   |
+LL | type F = &'static (u8)::AssocTy;
+   |                   ^^^^^^^^^^^^^ help: try: `<(u8)>::AssocTy`
+
+error: missing angle brackets in associated item path
+  --> $DIR/bad-assoc-ty.rs:27:10
+   |
+LL | type G = 'static + (Send)::AssocTy;
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `<'static + (Send)>::AssocTy`
+
+error: missing angle brackets in associated item path
+  --> $DIR/bad-assoc-ty.rs:44:10
+   |
+LL | type I = ty!()::AssocTy;
+   |          ^^^^^^^^^^^^^^ help: try: `<ty!()>::AssocTy`
+
+error: missing angle brackets in associated item path
+  --> $DIR/bad-assoc-ty.rs:37:19
+   |
+LL |     ($ty: ty) => ($ty::AssocTy);
+   |                   ^^^^^^^^^^^^ help: try: `<$ty>::AssocTy`
+...
+LL | type J = ty!(u8);
+   |          ------- in this macro invocation
+
+error[E0223]: ambiguous associated type
+  --> $DIR/bad-assoc-ty.rs:1:10
+   |
+LL | type A = [u8; 4]::AssocTy;
+   |          ^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<[u8; _] as Trait>::AssocTy`
+
+error[E0223]: ambiguous associated type
+  --> $DIR/bad-assoc-ty.rs:5:10
+   |
+LL | type B = [u8]::AssocTy;
+   |          ^^^^^^^^^^^^^ help: use fully-qualified syntax: `<[u8] as Trait>::AssocTy`
+
+error[E0223]: ambiguous associated type
+  --> $DIR/bad-assoc-ty.rs:9:10
+   |
+LL | type C = (u8)::AssocTy;
+   |          ^^^^^^^^^^^^^ help: use fully-qualified syntax: `<u8 as Trait>::AssocTy`
+
+error[E0223]: ambiguous associated type
+  --> $DIR/bad-assoc-ty.rs:13:10
+   |
+LL | type D = (u8, u8)::AssocTy;
+   |          ^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<(u8, u8) as Trait>::AssocTy`
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/bad-assoc-ty.rs:17:10
+   |
+LL | type E = _::AssocTy;
+   |          ^ not allowed in type signatures
+
+error[E0223]: ambiguous associated type
+  --> $DIR/bad-assoc-ty.rs:21:19
+   |
+LL | type F = &'static (u8)::AssocTy;
+   |                   ^^^^^^^^^^^^^ help: use fully-qualified syntax: `<u8 as Trait>::AssocTy`
+
+error[E0223]: ambiguous associated type
+  --> $DIR/bad-assoc-ty.rs:27:10
+   |
+LL | type G = 'static + (Send)::AssocTy;
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<(dyn std::marker::Send + 'static) as Trait>::AssocTy`
+
+error[E0223]: ambiguous associated type
+  --> $DIR/bad-assoc-ty.rs:33:10
+   |
+LL | type H = Fn(u8) -> (u8)::Output;
+   |          ^^^^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<(dyn std::ops::Fn(u8) -> u8 + 'static) as Trait>::Output`
+
+error[E0223]: ambiguous associated type
+  --> $DIR/bad-assoc-ty.rs:37:19
+   |
+LL |     ($ty: ty) => ($ty::AssocTy);
+   |                   ^^^^^^^^^^^^ help: use fully-qualified syntax: `<u8 as Trait>::AssocTy`
+...
+LL | type J = ty!(u8);
+   |          ------- in this macro invocation
+
+error[E0223]: ambiguous associated type
+  --> $DIR/bad-assoc-ty.rs:44:10
+   |
+LL | type I = ty!()::AssocTy;
+   |          ^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<u8 as Trait>::AssocTy`
+
+error: aborting due to 19 previous errors
+
+Some errors occurred: E0121, E0223.
+For more information about an error, try `rustc --explain E0121`.
diff --git a/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.rs b/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.rs
new file mode 100644
index 0000000..1749137
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.rs
@@ -0,0 +1,26 @@
+trait Foo<A> {
+    fn foo(&self, a: A) -> A {
+        a
+    }
+}
+
+trait NotRelevant<A> {
+    fn nr(&self, a: A) -> A {
+        a
+    }
+}
+
+struct Bar;
+
+impl Foo<i32> for Bar {}
+
+impl Foo<u8> for Bar {}
+
+impl NotRelevant<usize> for Bar {}
+
+fn main() {
+    let f1 = Bar;
+
+    f1.foo(1usize);
+    //~^ error: the trait bound `Bar: Foo<usize>` is not satisfied
+}
diff --git a/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.stderr b/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.stderr
new file mode 100644
index 0000000..8aedb42
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.stderr
@@ -0,0 +1,13 @@
+error[E0277]: the trait bound `Bar: Foo<usize>` is not satisfied
+  --> $DIR/issue-21659-show-relevant-trait-impls-1.rs:24:8
+   |
+LL |     f1.foo(1usize);
+   |        ^^^ the trait `Foo<usize>` is not implemented for `Bar`
+   |
+   = help: the following implementations were found:
+             <Bar as Foo<i32>>
+             <Bar as Foo<u8>>
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.rs b/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.rs
new file mode 100644
index 0000000..e898b22
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.rs
@@ -0,0 +1,30 @@
+trait Foo<A> {
+    fn foo(&self, a: A) -> A {
+        a
+    }
+}
+
+trait NotRelevant<A> {
+    fn nr(&self, a: A) -> A {
+        a
+    }
+}
+
+struct Bar;
+
+impl Foo<i8> for Bar {}
+impl Foo<i16> for Bar {}
+impl Foo<i32> for Bar {}
+
+impl Foo<u8> for Bar {}
+impl Foo<u16> for Bar {}
+impl Foo<u32> for Bar {}
+
+impl NotRelevant<usize> for Bar {}
+
+fn main() {
+    let f1 = Bar;
+
+    f1.foo(1usize);
+    //~^ error: the trait bound `Bar: Foo<usize>` is not satisfied
+}
diff --git a/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr b/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr
new file mode 100644
index 0000000..d6d5ce4
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr
@@ -0,0 +1,16 @@
+error[E0277]: the trait bound `Bar: Foo<usize>` is not satisfied
+  --> $DIR/issue-21659-show-relevant-trait-impls-2.rs:28:8
+   |
+LL |     f1.foo(1usize);
+   |        ^^^ the trait `Foo<usize>` is not implemented for `Bar`
+   |
+   = help: the following implementations were found:
+             <Bar as Foo<i16>>
+             <Bar as Foo<i32>>
+             <Bar as Foo<i8>>
+             <Bar as Foo<u16>>
+           and 2 others
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/did_you_mean/issue-31424.nll.stderr b/src/test/ui/did_you_mean/issue-31424.nll.stderr
new file mode 100644
index 0000000..147225f
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-31424.nll.stderr
@@ -0,0 +1,33 @@
+error[E0596]: cannot borrow `self` as mutable, as it is not declared as mutable
+  --> $DIR/issue-31424.rs:7:9
+   |
+LL |         (&mut self).bar();
+   |         ^^^^^^^^^^^
+   |         |
+   |         cannot borrow as mutable
+   |         try removing `&mut` here
+
+warning: function cannot return without recursing
+  --> $DIR/issue-31424.rs:12:5
+   |
+LL |     fn bar(self: &mut Self) {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
+LL |
+LL |         (&mut self).bar();
+   |         ----------------- recursive call site
+   |
+   = note: #[warn(unconditional_recursion)] on by default
+   = help: a `loop` may express intention better if this is on purpose
+
+error[E0596]: cannot borrow `self` as mutable, as it is not declared as mutable
+  --> $DIR/issue-31424.rs:14:9
+   |
+LL |         (&mut self).bar();
+   |         ^^^^^^^^^^^
+   |         |
+   |         cannot borrow as mutable
+   |         try removing `&mut` here
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/did_you_mean/issue-31424.rs b/src/test/ui/did_you_mean/issue-31424.rs
new file mode 100644
index 0000000..d321d64
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-31424.rs
@@ -0,0 +1,18 @@
+// forbid-output: &mut mut self
+
+struct Struct;
+
+impl Struct {
+    fn foo(&mut self) {
+        (&mut self).bar(); //~ ERROR cannot borrow
+    }
+
+    // In this case we could keep the suggestion, but to distinguish the
+    // two cases is pretty hard. It's an obscure case anyway.
+    fn bar(self: &mut Self) {
+        //~^ WARN function cannot return without recursing
+        (&mut self).bar(); //~ ERROR cannot borrow
+    }
+}
+
+fn main () {}
diff --git a/src/test/ui/did_you_mean/issue-31424.stderr b/src/test/ui/did_you_mean/issue-31424.stderr
new file mode 100644
index 0000000..7c351ea
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-31424.stderr
@@ -0,0 +1,34 @@
+error[E0596]: cannot borrow immutable argument `self` as mutable
+  --> $DIR/issue-31424.rs:7:15
+   |
+LL |         (&mut self).bar();
+   |               ^^^^
+   |               |
+   |               cannot reborrow mutably
+   |               try removing `&mut` here
+
+warning: function cannot return without recursing
+  --> $DIR/issue-31424.rs:12:5
+   |
+LL |     fn bar(self: &mut Self) {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
+LL |
+LL |         (&mut self).bar();
+   |         ----------------- recursive call site
+   |
+   = note: #[warn(unconditional_recursion)] on by default
+   = help: a `loop` may express intention better if this is on purpose
+
+error[E0596]: cannot borrow immutable argument `self` as mutable
+  --> $DIR/issue-31424.rs:14:15
+   |
+LL |         (&mut self).bar();
+   |               ^^^^ cannot borrow mutably
+help: consider removing the `&mut`, as it is an immutable binding to a mutable reference
+   |
+LL |         self.bar();
+   |         ^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/did_you_mean/issue-34126.nll.stderr b/src/test/ui/did_you_mean/issue-34126.nll.stderr
new file mode 100644
index 0000000..e738df1
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-34126.nll.stderr
@@ -0,0 +1,22 @@
+error[E0596]: cannot borrow `self` as mutable, as it is not declared as mutable
+  --> $DIR/issue-34126.rs:6:18
+   |
+LL |         self.run(&mut self);
+   |                  ^^^^^^^^^
+   |                  |
+   |                  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:6:18
+   |
+LL |         self.run(&mut self);
+   |         ---- --- ^^^^^^^^^ mutable borrow occurs here
+   |         |    |
+   |         |    immutable borrow later used by call
+   |         immutable borrow occurs here
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0502, E0596.
+For more information about an error, try `rustc --explain E0502`.
diff --git a/src/test/ui/did_you_mean/issue-34126.rs b/src/test/ui/did_you_mean/issue-34126.rs
new file mode 100644
index 0000000..15bef1e
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-34126.rs
@@ -0,0 +1,13 @@
+struct Z { }
+
+impl Z {
+    fn run(&self, z: &mut Z) { }
+    fn start(&mut self) {
+        self.run(&mut self); //~ ERROR cannot borrow
+    }
+}
+
+fn main() {
+    let mut z = Z {};
+    z.start();
+}
diff --git a/src/test/ui/did_you_mean/issue-34126.stderr b/src/test/ui/did_you_mean/issue-34126.stderr
new file mode 100644
index 0000000..536e2951
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-34126.stderr
@@ -0,0 +1,12 @@
+error[E0596]: cannot borrow immutable argument `self` as mutable
+  --> $DIR/issue-34126.rs:6:23
+   |
+LL |         self.run(&mut self);
+   |                       ^^^^
+   |                       |
+   |                       cannot reborrow mutably
+   |                       try removing `&mut` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/did_you_mean/issue-34337.nll.stderr b/src/test/ui/did_you_mean/issue-34337.nll.stderr
new file mode 100644
index 0000000..81f7b6d
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-34337.nll.stderr
@@ -0,0 +1,12 @@
+error[E0596]: cannot borrow `key` as mutable, as it is not declared as mutable
+  --> $DIR/issue-34337.rs:6:9
+   |
+LL |     get(&mut key);
+   |         ^^^^^^^^
+   |         |
+   |         cannot borrow as mutable
+   |         try removing `&mut` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/did_you_mean/issue-34337.rs b/src/test/ui/did_you_mean/issue-34337.rs
new file mode 100644
index 0000000..bb69960
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-34337.rs
@@ -0,0 +1,7 @@
+fn get(key: &mut String) { }
+
+fn main() {
+    let mut v: Vec<String> = Vec::new();
+    let ref mut key = v[0];
+    get(&mut key); //~ ERROR cannot borrow
+}
diff --git a/src/test/ui/did_you_mean/issue-34337.stderr b/src/test/ui/did_you_mean/issue-34337.stderr
new file mode 100644
index 0000000..353f409
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-34337.stderr
@@ -0,0 +1,12 @@
+error[E0596]: cannot borrow immutable local variable `key` as mutable
+  --> $DIR/issue-34337.rs:6:14
+   |
+LL |     get(&mut key);
+   |              ^^^
+   |              |
+   |              cannot reborrow mutably
+   |              try removing `&mut` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/did_you_mean/issue-35937.nll.stderr b/src/test/ui/did_you_mean/issue-35937.nll.stderr
new file mode 100644
index 0000000..216cb14
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-35937.nll.stderr
@@ -0,0 +1,28 @@
+error[E0596]: cannot borrow `f.v` as mutable, as `f` is not declared as mutable
+  --> $DIR/issue-35937.rs:7:5
+   |
+LL |     let f = Foo { v: Vec::new() };
+   |         - help: consider changing this to be mutable: `mut f`
+LL |     f.v.push("cat".to_string());
+   |     ^^^ cannot borrow as mutable
+
+error[E0594]: cannot assign to `s.x`, as `s` is not declared as mutable
+  --> $DIR/issue-35937.rs:16:5
+   |
+LL |     let s = S { x: 42 };
+   |         - help: consider changing this to be mutable: `mut s`
+LL |     s.x += 1;
+   |     ^^^^^^^^ cannot assign
+
+error[E0594]: cannot assign to `s.x`, as `s` is not declared as mutable
+  --> $DIR/issue-35937.rs:20:5
+   |
+LL | fn bar(s: S) {
+   |        - help: consider changing this to be mutable: `mut s`
+LL |     s.x += 1;
+   |     ^^^^^^^^ cannot assign
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0594, E0596.
+For more information about an error, try `rustc --explain E0594`.
diff --git a/src/test/ui/did_you_mean/issue-35937.rs b/src/test/ui/did_you_mean/issue-35937.rs
new file mode 100644
index 0000000..ebeba74
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-35937.rs
@@ -0,0 +1,21 @@
+struct Foo {
+    pub v: Vec<String>
+}
+
+fn main() {
+    let f = Foo { v: Vec::new() };
+    f.v.push("cat".to_string()); //~ ERROR cannot borrow
+}
+
+
+struct S {
+    x: i32,
+}
+fn foo() {
+    let s = S { x: 42 };
+    s.x += 1; //~ ERROR cannot assign
+}
+
+fn bar(s: S) {
+    s.x += 1; //~ ERROR cannot assign
+}
diff --git a/src/test/ui/did_you_mean/issue-35937.stderr b/src/test/ui/did_you_mean/issue-35937.stderr
new file mode 100644
index 0000000..1e70f98
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-35937.stderr
@@ -0,0 +1,28 @@
+error[E0596]: cannot borrow field `f.v` of immutable binding as mutable
+  --> $DIR/issue-35937.rs:7:5
+   |
+LL |     let f = Foo { v: Vec::new() };
+   |         - help: make this binding mutable: `mut f`
+LL |     f.v.push("cat".to_string());
+   |     ^^^ cannot mutably borrow field of immutable binding
+
+error[E0594]: cannot assign to field `s.x` of immutable binding
+  --> $DIR/issue-35937.rs:16:5
+   |
+LL |     let s = S { x: 42 };
+   |         - help: make this binding mutable: `mut s`
+LL |     s.x += 1;
+   |     ^^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0594]: cannot assign to field `s.x` of immutable binding
+  --> $DIR/issue-35937.rs:20:5
+   |
+LL | fn bar(s: S) {
+   |        - help: make this binding mutable: `mut s`
+LL |     s.x += 1;
+   |     ^^^^^^^^ cannot mutably borrow field of immutable binding
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0594, E0596.
+For more information about an error, try `rustc --explain E0594`.
diff --git a/src/test/ui/did_you_mean/issue-36798.rs b/src/test/ui/did_you_mean/issue-36798.rs
new file mode 100644
index 0000000..89d71d8
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-36798.rs
@@ -0,0 +1,8 @@
+struct Foo {
+    bar: u8
+}
+
+fn main() {
+    let f = Foo { bar: 22 };
+    f.baz; //~ ERROR no field
+}
diff --git a/src/test/ui/did_you_mean/issue-36798.stderr b/src/test/ui/did_you_mean/issue-36798.stderr
new file mode 100644
index 0000000..98876e3
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-36798.stderr
@@ -0,0 +1,9 @@
+error[E0609]: no field `baz` on type `Foo`
+  --> $DIR/issue-36798.rs:7:7
+   |
+LL |     f.baz;
+   |       ^^^ help: a field with a similar name exists: `bar`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0609`.
diff --git a/src/test/ui/did_you_mean/issue-36798_unknown_field.rs b/src/test/ui/did_you_mean/issue-36798_unknown_field.rs
new file mode 100644
index 0000000..ef9744b
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-36798_unknown_field.rs
@@ -0,0 +1,8 @@
+struct Foo {
+    bar: u8
+}
+
+fn main() {
+    let f = Foo { bar: 22 };
+    f.zz; //~ ERROR no field
+}
diff --git a/src/test/ui/did_you_mean/issue-36798_unknown_field.stderr b/src/test/ui/did_you_mean/issue-36798_unknown_field.stderr
new file mode 100644
index 0000000..2ed0a09
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-36798_unknown_field.stderr
@@ -0,0 +1,11 @@
+error[E0609]: no field `zz` on type `Foo`
+  --> $DIR/issue-36798_unknown_field.rs:7:7
+   |
+LL |     f.zz;
+   |       ^^ unknown field
+   |
+   = note: available fields are: `bar`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0609`.
diff --git a/src/test/ui/did_you_mean/issue-37139.nll.stderr b/src/test/ui/did_you_mean/issue-37139.nll.stderr
new file mode 100644
index 0000000..163817d
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-37139.nll.stderr
@@ -0,0 +1,12 @@
+error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
+  --> $DIR/issue-37139.rs:12:18
+   |
+LL |             test(&mut x);
+   |                  ^^^^^^
+   |                  |
+   |                  cannot borrow as mutable
+   |                  try removing `&mut` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/did_you_mean/issue-37139.rs b/src/test/ui/did_you_mean/issue-37139.rs
new file mode 100644
index 0000000..b7f419a
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-37139.rs
@@ -0,0 +1,15 @@
+enum TestEnum {
+    Item(i32),
+}
+
+fn test(_: &mut i32) {
+}
+
+fn main() {
+    let mut x = TestEnum::Item(10);
+    match x {
+        TestEnum::Item(ref mut x) => {
+            test(&mut x); //~ ERROR cannot borrow immutable
+        }
+    }
+}
diff --git a/src/test/ui/did_you_mean/issue-37139.stderr b/src/test/ui/did_you_mean/issue-37139.stderr
new file mode 100644
index 0000000..cd42ee8
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-37139.stderr
@@ -0,0 +1,12 @@
+error[E0596]: cannot borrow immutable local variable `x` as mutable
+  --> $DIR/issue-37139.rs:12:23
+   |
+LL |             test(&mut x);
+   |                       ^
+   |                       |
+   |                       cannot reborrow mutably
+   |                       try removing `&mut` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.rs b/src/test/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.rs
new file mode 100644
index 0000000..a1ef68e
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.rs
@@ -0,0 +1,5 @@
+use Foo; //~ ERROR unresolved
+
+use Foo1; //~ ERROR unresolved
+
+fn main() {}
diff --git a/src/test/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.stderr b/src/test/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.stderr
new file mode 100644
index 0000000..852abae
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.stderr
@@ -0,0 +1,15 @@
+error[E0432]: unresolved import `Foo`
+  --> $DIR/issue-38054-do-not-show-unresolved-names.rs:1:5
+   |
+LL | use Foo;
+   |     ^^^ no `Foo` in the root
+
+error[E0432]: unresolved import `Foo1`
+  --> $DIR/issue-38054-do-not-show-unresolved-names.rs:3:5
+   |
+LL | use Foo1;
+   |     ^^^^ no `Foo1` in the root
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/did_you_mean/issue-38147-1.nll.stderr b/src/test/ui/did_you_mean/issue-38147-1.nll.stderr
new file mode 100644
index 0000000..6efac37
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-38147-1.nll.stderr
@@ -0,0 +1,11 @@
+error[E0596]: cannot borrow `*self.s` as mutable, as it is behind a `&` reference
+  --> $DIR/issue-38147-1.rs:17:9
+   |
+LL |     fn f(&self) {
+   |          ----- help: consider changing this to be a mutable reference: `&mut self`
+LL |         self.s.push('x');
+   |         ^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/did_you_mean/issue-38147-1.rs b/src/test/ui/did_you_mean/issue-38147-1.rs
new file mode 100644
index 0000000..b672396
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-38147-1.rs
@@ -0,0 +1,21 @@
+struct Pass<'a> {
+    s: &'a mut String
+}
+
+impl<'a> Pass<'a> {
+    fn f(&mut self) {
+        self.s.push('x');
+    }
+}
+
+struct Foo<'a> {
+    s: &'a mut String
+}
+
+impl<'a> Foo<'a> {
+    fn f(&self) {
+        self.s.push('x'); //~ ERROR cannot borrow data mutably
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/did_you_mean/issue-38147-1.stderr b/src/test/ui/did_you_mean/issue-38147-1.stderr
new file mode 100644
index 0000000..4311836b
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-38147-1.stderr
@@ -0,0 +1,11 @@
+error[E0389]: cannot borrow data mutably in a `&` reference
+  --> $DIR/issue-38147-1.rs:17:9
+   |
+LL |     fn f(&self) {
+   |          ----- use `&mut self` here to make mutable
+LL |         self.s.push('x');
+   |         ^^^^^^ assignment into an immutable reference
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0389`.
diff --git a/src/test/ui/did_you_mean/issue-38147-2.nll.stderr b/src/test/ui/did_you_mean/issue-38147-2.nll.stderr
new file mode 100644
index 0000000..cb49810
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-38147-2.nll.stderr
@@ -0,0 +1,12 @@
+error[E0596]: cannot borrow `*self.s` as mutable, as it is behind a `&` reference
+  --> $DIR/issue-38147-2.rs:7:9
+   |
+LL |     s: &'a String
+   |        ---------- help: consider changing this to be mutable: `&'a mut String`
+...
+LL |         self.s.push('x');
+   |         ^^^^^^ cannot borrow as mutable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/did_you_mean/issue-38147-2.rs b/src/test/ui/did_you_mean/issue-38147-2.rs
new file mode 100644
index 0000000..e43ebf9
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-38147-2.rs
@@ -0,0 +1,12 @@
+struct Bar<'a> {
+    s: &'a String
+}
+
+impl<'a> Bar<'a> {
+    fn f(&mut self) {
+        self.s.push('x');
+        //~^ ERROR cannot borrow borrowed content `*self.s` of immutable binding as mutable
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/did_you_mean/issue-38147-2.stderr b/src/test/ui/did_you_mean/issue-38147-2.stderr
new file mode 100644
index 0000000..fa4fccb
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-38147-2.stderr
@@ -0,0 +1,12 @@
+error[E0596]: cannot borrow borrowed content `*self.s` of immutable binding as mutable
+  --> $DIR/issue-38147-2.rs:7:9
+   |
+LL |     s: &'a String
+   |        ---------- use `&'a mut String` here to make mutable
+...
+LL |         self.s.push('x');
+   |         ^^^^^^ cannot borrow as mutable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/did_you_mean/issue-38147-3.nll.stderr b/src/test/ui/did_you_mean/issue-38147-3.nll.stderr
new file mode 100644
index 0000000..6778257
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-38147-3.nll.stderr
@@ -0,0 +1,12 @@
+error[E0596]: cannot borrow `*self.s` as mutable, as it is behind a `&` reference
+  --> $DIR/issue-38147-3.rs:7:9
+   |
+LL |     s: &'a String
+   |        ---------- help: consider changing this to be mutable: `&'a mut String`
+...
+LL |         self.s.push('x');
+   |         ^^^^^^ cannot borrow as mutable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/did_you_mean/issue-38147-3.rs b/src/test/ui/did_you_mean/issue-38147-3.rs
new file mode 100644
index 0000000..4cd703f
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-38147-3.rs
@@ -0,0 +1,12 @@
+struct Qux<'a> {
+    s: &'a String
+}
+
+impl<'a> Qux<'a> {
+    fn f(&self) {
+        self.s.push('x');
+        //~^ ERROR cannot borrow borrowed content `*self.s` of immutable binding as mutable
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/did_you_mean/issue-38147-3.stderr b/src/test/ui/did_you_mean/issue-38147-3.stderr
new file mode 100644
index 0000000..2cb9835
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-38147-3.stderr
@@ -0,0 +1,12 @@
+error[E0596]: cannot borrow borrowed content `*self.s` of immutable binding as mutable
+  --> $DIR/issue-38147-3.rs:7:9
+   |
+LL |     s: &'a String
+   |        ---------- use `&'a mut String` here to make mutable
+...
+LL |         self.s.push('x');
+   |         ^^^^^^ cannot borrow as mutable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/did_you_mean/issue-38147-4.nll.stderr b/src/test/ui/did_you_mean/issue-38147-4.nll.stderr
new file mode 100644
index 0000000..db3e6b8
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-38147-4.nll.stderr
@@ -0,0 +1,11 @@
+error[E0596]: cannot borrow `*f.s` as mutable, as it is behind a `&` reference
+  --> $DIR/issue-38147-4.rs:6:5
+   |
+LL | fn f(x: usize, f: &Foo) {
+   |                   ---- help: consider changing this to be a mutable reference: `&mut Foo<'_>`
+LL |     f.s.push('x');
+   |     ^^^ `f` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/did_you_mean/issue-38147-4.rs b/src/test/ui/did_you_mean/issue-38147-4.rs
new file mode 100644
index 0000000..26573d4
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-38147-4.rs
@@ -0,0 +1,9 @@
+struct Foo<'a> {
+    s: &'a mut String
+}
+
+fn f(x: usize, f: &Foo) {
+    f.s.push('x'); //~ ERROR cannot borrow data mutably
+}
+
+fn main() {}
diff --git a/src/test/ui/did_you_mean/issue-38147-4.stderr b/src/test/ui/did_you_mean/issue-38147-4.stderr
new file mode 100644
index 0000000..71d44f9
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-38147-4.stderr
@@ -0,0 +1,11 @@
+error[E0389]: cannot borrow data mutably in a `&` reference
+  --> $DIR/issue-38147-4.rs:6:5
+   |
+LL | fn f(x: usize, f: &Foo) {
+   |                   ---- use `&mut Foo` here to make mutable
+LL |     f.s.push('x');
+   |     ^^^ assignment into an immutable reference
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0389`.
diff --git a/src/test/ui/did_you_mean/issue-39544.nll.stderr b/src/test/ui/did_you_mean/issue-39544.nll.stderr
new file mode 100644
index 0000000..899a42b5
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-39544.nll.stderr
@@ -0,0 +1,102 @@
+error[E0596]: cannot borrow `z.x` as mutable, as `z` is not declared as mutable
+  --> $DIR/issue-39544.rs:11:13
+   |
+LL |     let z = Z { x: X::Y };
+   |         - help: consider changing this to be mutable: `mut z`
+LL |     let _ = &mut z.x;
+   |             ^^^^^^^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow `self.x` as mutable, as it is behind a `&` reference
+  --> $DIR/issue-39544.rs:16:17
+   |
+LL |     fn foo<'z>(&'z self) {
+   |                -------- help: consider changing this to be a mutable reference: `&'z mut self`
+LL |         let _ = &mut self.x;
+   |                 ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+
+error[E0596]: cannot borrow `self.x` as mutable, as it is behind a `&` reference
+  --> $DIR/issue-39544.rs:20:17
+   |
+LL |     fn foo1(&self, other: &Z) {
+   |             ----- help: consider changing this to be a mutable reference: `&mut self`
+LL |         let _ = &mut self.x;
+   |                 ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+
+error[E0596]: cannot borrow `other.x` as mutable, as it is behind a `&` reference
+  --> $DIR/issue-39544.rs:21:17
+   |
+LL |     fn foo1(&self, other: &Z) {
+   |                           -- help: consider changing this to be a mutable reference: `&mut Z`
+LL |         let _ = &mut self.x;
+LL |         let _ = &mut other.x;
+   |                 ^^^^^^^^^^^^ `other` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+
+error[E0596]: cannot borrow `self.x` as mutable, as it is behind a `&` reference
+  --> $DIR/issue-39544.rs:25:17
+   |
+LL |     fn foo2<'a>(&'a self, other: &Z) {
+   |                 -------- help: consider changing this to be a mutable reference: `&'a mut self`
+LL |         let _ = &mut self.x;
+   |                 ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+
+error[E0596]: cannot borrow `other.x` as mutable, as it is behind a `&` reference
+  --> $DIR/issue-39544.rs:26: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;
+LL |         let _ = &mut other.x;
+   |                 ^^^^^^^^^^^^ `other` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+
+error[E0596]: cannot borrow `self.x` as mutable, as it is behind a `&` reference
+  --> $DIR/issue-39544.rs:30:17
+   |
+LL |     fn foo3<'a>(self: &'a Self, other: &Z) {
+   |                       -------- help: consider changing this to be a mutable reference: `&'a mut Self`
+LL |         let _ = &mut self.x;
+   |                 ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+
+error[E0596]: cannot borrow `other.x` as mutable, as it is behind a `&` reference
+  --> $DIR/issue-39544.rs:31: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;
+LL |         let _ = &mut other.x;
+   |                 ^^^^^^^^^^^^ `other` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+
+error[E0596]: cannot borrow `other.x` as mutable, as it is behind a `&` reference
+  --> $DIR/issue-39544.rs:35:17
+   |
+LL |     fn foo4(other: &Z) {
+   |                    -- help: consider changing this to be a mutable reference: `&mut Z`
+LL |         let _ = &mut other.x;
+   |                 ^^^^^^^^^^^^ `other` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+
+error[E0596]: cannot borrow `z.x` as mutable, as `z` is not declared as mutable
+  --> $DIR/issue-39544.rs:41:13
+   |
+LL | pub fn with_arg(z: Z, w: &Z) {
+   |                 - help: consider changing this to be mutable: `mut z`
+LL |     let _ = &mut z.x;
+   |             ^^^^^^^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow `w.x` as mutable, as it is behind a `&` reference
+  --> $DIR/issue-39544.rs:42: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;
+LL |     let _ = &mut w.x;
+   |             ^^^^^^^^ `w` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+
+error[E0594]: cannot assign to `*x.0` which is behind a `&` reference
+  --> $DIR/issue-39544.rs:48:5
+   |
+LL |     *x.0 = 1;
+   |     ^^^^^^^^ cannot assign
+
+error: aborting due to 12 previous errors
+
+Some errors occurred: E0594, E0596.
+For more information about an error, try `rustc --explain E0594`.
diff --git a/src/test/ui/did_you_mean/issue-39544.rs b/src/test/ui/did_you_mean/issue-39544.rs
new file mode 100644
index 0000000..89696a0
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-39544.rs
@@ -0,0 +1,50 @@
+pub enum X {
+    Y
+}
+
+pub struct Z {
+    x: X
+}
+
+fn main() {
+    let z = Z { x: X::Y };
+    let _ = &mut z.x; //~ ERROR cannot borrow
+}
+
+impl Z {
+    fn foo<'z>(&'z self) {
+        let _ = &mut self.x; //~ ERROR cannot borrow
+    }
+
+    fn foo1(&self, other: &Z) {
+        let _ = &mut self.x; //~ ERROR cannot borrow
+        let _ = &mut other.x; //~ ERROR cannot borrow
+    }
+
+    fn foo2<'a>(&'a self, other: &Z) {
+        let _ = &mut self.x; //~ ERROR cannot borrow
+        let _ = &mut other.x; //~ ERROR cannot borrow
+    }
+
+    fn foo3<'a>(self: &'a Self, other: &Z) {
+        let _ = &mut self.x; //~ ERROR cannot borrow
+        let _ = &mut other.x; //~ ERROR cannot borrow
+    }
+
+    fn foo4(other: &Z) {
+        let _ = &mut other.x; //~ ERROR cannot borrow
+    }
+
+}
+
+pub fn with_arg(z: Z, w: &Z) {
+    let _ = &mut z.x; //~ ERROR cannot borrow
+    let _ = &mut w.x; //~ ERROR cannot borrow
+}
+
+pub fn with_tuple() {
+    let mut y = 0;
+    let x = (&y,);
+    *x.0 = 1;
+    //~^ ERROR cannot assign to borrowed content `*x.0` of immutable binding
+}
diff --git a/src/test/ui/did_you_mean/issue-39544.stderr b/src/test/ui/did_you_mean/issue-39544.stderr
new file mode 100644
index 0000000..d86ea89
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-39544.stderr
@@ -0,0 +1,102 @@
+error[E0596]: cannot borrow field `z.x` of immutable binding as mutable
+  --> $DIR/issue-39544.rs:11:18
+   |
+LL |     let z = Z { x: X::Y };
+   |         - help: make this binding mutable: `mut z`
+LL |     let _ = &mut z.x;
+   |                  ^^^ cannot mutably borrow field of immutable binding
+
+error[E0596]: cannot borrow field `self.x` of immutable binding as mutable
+  --> $DIR/issue-39544.rs:16:22
+   |
+LL |     fn foo<'z>(&'z self) {
+   |                -------- use `&'z mut self` here to make mutable
+LL |         let _ = &mut self.x;
+   |                      ^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0596]: cannot borrow field `self.x` of immutable binding as mutable
+  --> $DIR/issue-39544.rs:20:22
+   |
+LL |     fn foo1(&self, other: &Z) {
+   |             ----- use `&mut self` here to make mutable
+LL |         let _ = &mut self.x;
+   |                      ^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0596]: cannot borrow field `other.x` of immutable binding as mutable
+  --> $DIR/issue-39544.rs:21:22
+   |
+LL |     fn foo1(&self, other: &Z) {
+   |                           -- use `&mut Z` here to make mutable
+LL |         let _ = &mut self.x;
+LL |         let _ = &mut other.x;
+   |                      ^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0596]: cannot borrow field `self.x` of immutable binding as mutable
+  --> $DIR/issue-39544.rs:25:22
+   |
+LL |     fn foo2<'a>(&'a self, other: &Z) {
+   |                 -------- use `&'a mut self` here to make mutable
+LL |         let _ = &mut self.x;
+   |                      ^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0596]: cannot borrow field `other.x` of immutable binding as mutable
+  --> $DIR/issue-39544.rs:26:22
+   |
+LL |     fn foo2<'a>(&'a self, other: &Z) {
+   |                                  -- use `&mut Z` here to make mutable
+LL |         let _ = &mut self.x;
+LL |         let _ = &mut other.x;
+   |                      ^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0596]: cannot borrow field `self.x` of immutable binding as mutable
+  --> $DIR/issue-39544.rs:30:22
+   |
+LL |     fn foo3<'a>(self: &'a Self, other: &Z) {
+   |                       -------- use `&'a mut Self` here to make mutable
+LL |         let _ = &mut self.x;
+   |                      ^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0596]: cannot borrow field `other.x` of immutable binding as mutable
+  --> $DIR/issue-39544.rs:31:22
+   |
+LL |     fn foo3<'a>(self: &'a Self, other: &Z) {
+   |                                        -- use `&mut Z` here to make mutable
+LL |         let _ = &mut self.x;
+LL |         let _ = &mut other.x;
+   |                      ^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0596]: cannot borrow field `other.x` of immutable binding as mutable
+  --> $DIR/issue-39544.rs:35:22
+   |
+LL |     fn foo4(other: &Z) {
+   |                    -- use `&mut Z` here to make mutable
+LL |         let _ = &mut other.x;
+   |                      ^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0596]: cannot borrow field `z.x` of immutable binding as mutable
+  --> $DIR/issue-39544.rs:41:18
+   |
+LL | pub fn with_arg(z: Z, w: &Z) {
+   |                 - help: make this binding mutable: `mut z`
+LL |     let _ = &mut z.x;
+   |                  ^^^ cannot mutably borrow field of immutable binding
+
+error[E0596]: cannot borrow field `w.x` of immutable binding as mutable
+  --> $DIR/issue-39544.rs:42:18
+   |
+LL | pub fn with_arg(z: Z, w: &Z) {
+   |                          -- use `&mut Z` here to make mutable
+LL |     let _ = &mut z.x;
+LL |     let _ = &mut w.x;
+   |                  ^^^ cannot mutably borrow field of immutable binding
+
+error[E0594]: cannot assign to borrowed content `*x.0` of immutable binding
+  --> $DIR/issue-39544.rs:48:5
+   |
+LL |     *x.0 = 1;
+   |     ^^^^^^^^ cannot borrow as mutable
+
+error: aborting due to 12 previous errors
+
+Some errors occurred: E0594, E0596.
+For more information about an error, try `rustc --explain E0594`.
diff --git a/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.rs b/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.rs
new file mode 100644
index 0000000..63a8c54
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.rs
@@ -0,0 +1,27 @@
+trait Foo<B> {
+    fn bar(&self){}
+}
+
+impl Foo<u8> for i8 {}
+impl Foo<u16> for i8 {}
+impl Foo<u32> for i8 {}
+impl Foo<u64> for i8 {}
+impl Foo<bool> for i8 {}
+
+impl Foo<u16> for u8 {}
+impl Foo<u32> for u8 {}
+impl Foo<u64> for u8 {}
+impl Foo<bool> for u8 {}
+
+impl Foo<u8> for bool {}
+impl Foo<u16> for bool {}
+impl Foo<u32> for bool {}
+impl Foo<u64> for bool {}
+impl Foo<bool> for bool {}
+impl Foo<i8> for bool {}
+
+fn main() {
+    Foo::<i32>::bar(&1i8); //~ ERROR is not satisfied
+    Foo::<i32>::bar(&1u8); //~ ERROR is not satisfied
+    Foo::<i32>::bar(&true); //~ ERROR is not satisfied
+}
diff --git a/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr b/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr
new file mode 100644
index 0000000..cfb1da0
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr
@@ -0,0 +1,56 @@
+error[E0277]: the trait bound `i8: Foo<i32>` is not satisfied
+  --> $DIR/issue-39802-show-5-trait-impls.rs:24:5
+   |
+LL |     Foo::<i32>::bar(&1i8);
+   |     ^^^^^^^^^^^^^^^ the trait `Foo<i32>` is not implemented for `i8`
+   |
+   = help: the following implementations were found:
+             <i8 as Foo<bool>>
+             <i8 as Foo<u16>>
+             <i8 as Foo<u32>>
+             <i8 as Foo<u64>>
+             <i8 as Foo<u8>>
+note: required by `Foo::bar`
+  --> $DIR/issue-39802-show-5-trait-impls.rs:2:5
+   |
+LL |     fn bar(&self){}
+   |     ^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `u8: Foo<i32>` is not satisfied
+  --> $DIR/issue-39802-show-5-trait-impls.rs:25:5
+   |
+LL |     Foo::<i32>::bar(&1u8);
+   |     ^^^^^^^^^^^^^^^ the trait `Foo<i32>` is not implemented for `u8`
+   |
+   = help: the following implementations were found:
+             <u8 as Foo<bool>>
+             <u8 as Foo<u16>>
+             <u8 as Foo<u32>>
+             <u8 as Foo<u64>>
+note: required by `Foo::bar`
+  --> $DIR/issue-39802-show-5-trait-impls.rs:2:5
+   |
+LL |     fn bar(&self){}
+   |     ^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `bool: Foo<i32>` is not satisfied
+  --> $DIR/issue-39802-show-5-trait-impls.rs:26:5
+   |
+LL |     Foo::<i32>::bar(&true);
+   |     ^^^^^^^^^^^^^^^ the trait `Foo<i32>` is not implemented for `bool`
+   |
+   = help: the following implementations were found:
+             <bool as Foo<bool>>
+             <bool as Foo<i8>>
+             <bool as Foo<u16>>
+             <bool as Foo<u32>>
+           and 2 others
+note: required by `Foo::bar`
+  --> $DIR/issue-39802-show-5-trait-impls.rs:2:5
+   |
+LL |     fn bar(&self){}
+   |     ^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/did_you_mean/issue-40006.rs b/src/test/ui/did_you_mean/issue-40006.rs
new file mode 100644
index 0000000..75ea02b
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-40006.rs
@@ -0,0 +1,25 @@
+impl X { //~ ERROR cannot be made into an object
+//~^ ERROR missing
+    Y
+}
+
+struct S;
+
+trait X { //~ ERROR missing
+    X() {}
+    fn xxx() { ### } //~ ERROR missing
+    //~^ ERROR expected
+    L = M; //~ ERROR missing
+    Z = { 2 + 3 }; //~ ERROR expected one of
+    ::Y (); //~ ERROR expected one of
+}
+
+impl S {
+    pub hello_method(&self) { //~ ERROR missing
+        println!("Hello");
+    }
+}
+
+fn main() {
+    S.hello_method();
+}
diff --git a/src/test/ui/did_you_mean/issue-40006.stderr b/src/test/ui/did_you_mean/issue-40006.stderr
new file mode 100644
index 0000000..f6f7fe5
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-40006.stderr
@@ -0,0 +1,69 @@
+error: missing `fn`, `type`, or `const` for impl-item declaration
+  --> $DIR/issue-40006.rs:1:9
+   |
+LL |   impl X {
+   |  _________^
+LL | |
+LL | |     Y
+   | |____^ missing `fn`, `type`, or `const`
+
+error: missing `fn`, `type`, or `const` for trait-item declaration
+  --> $DIR/issue-40006.rs:8:10
+   |
+LL |   trait X {
+   |  __________^
+LL | |     X() {}
+   | |____^ missing `fn`, `type`, or `const`
+
+error: expected `[`, found `#`
+  --> $DIR/issue-40006.rs:10:17
+   |
+LL |     fn xxx() { ### }
+   |                 ^ expected `[`
+
+error: missing `fn`, `type`, or `const` for trait-item declaration
+  --> $DIR/issue-40006.rs:10:21
+   |
+LL |       fn xxx() { ### }
+   |  _____________________^
+LL | |
+LL | |     L = M;
+   | |____^ missing `fn`, `type`, or `const`
+
+error: missing `fn`, `type`, or `const` for trait-item declaration
+  --> $DIR/issue-40006.rs:12:11
+   |
+LL |       L = M;
+   |  ___________^
+LL | |     Z = { 2 + 3 };
+   | |____^ missing `fn`, `type`, or `const`
+
+error: expected one of `async`, `const`, `extern`, `fn`, `type`, `unsafe`, or `}`, found `;`
+  --> $DIR/issue-40006.rs:13:18
+   |
+LL |     Z = { 2 + 3 };
+   |                  ^ expected one of 7 possible tokens here
+
+error: expected one of `!` or `::`, found `(`
+  --> $DIR/issue-40006.rs:14:9
+   |
+LL |     ::Y ();
+   |         ^ expected one of `!` or `::` here
+
+error: missing `fn`, `type`, or `const` for impl-item declaration
+  --> $DIR/issue-40006.rs:18:8
+   |
+LL |     pub hello_method(&self) {
+   |        ^ missing `fn`, `type`, or `const`
+
+error[E0038]: the trait `X` cannot be made into an object
+  --> $DIR/issue-40006.rs:1:6
+   |
+LL | impl X {
+   |      ^ the trait `X` cannot be made into an object
+   |
+   = note: method `xxx` has no receiver
+
+error: aborting due to 9 previous errors
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/did_you_mean/issue-40396.rs b/src/test/ui/did_you_mean/issue-40396.rs
new file mode 100644
index 0000000..63eec50
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-40396.rs
@@ -0,0 +1,27 @@
+fn foo() {
+    (0..13).collect<Vec<i32>>();
+    //~^ ERROR chained comparison
+    //~| ERROR expected value, found struct `Vec`
+    //~| ERROR expected value, found builtin type `i32`
+    //~| ERROR attempted to take value of method `collect`
+}
+
+fn bar() {
+    Vec<i32>::new();
+    //~^ ERROR chained comparison
+    //~| ERROR expected value, found struct `Vec`
+    //~| ERROR expected value, found builtin type `i32`
+    //~| ERROR cannot find function `new` in the crate root
+}
+
+fn qux() {
+    (0..13).collect<Vec<i32>();
+    //~^ ERROR chained comparison
+    //~| ERROR chained comparison
+    //~| ERROR expected value, found struct `Vec`
+    //~| ERROR expected value, found builtin type `i32`
+    //~| ERROR attempted to take value of method `collect`
+    //~| ERROR mismatched types
+}
+
+fn main() {}
diff --git a/src/test/ui/did_you_mean/issue-40396.stderr b/src/test/ui/did_you_mean/issue-40396.stderr
new file mode 100644
index 0000000..86bbf2b
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-40396.stderr
@@ -0,0 +1,103 @@
+error: chained comparison operators require parentheses
+  --> $DIR/issue-40396.rs:2:20
+   |
+LL |     (0..13).collect<Vec<i32>>();
+   |                    ^^^^^^^^
+   |
+   = help: use `::<...>` instead of `<...>` if you meant to specify type arguments
+   = help: or use `(...)` if you meant to specify fn arguments
+
+error: chained comparison operators require parentheses
+  --> $DIR/issue-40396.rs:10:8
+   |
+LL |     Vec<i32>::new();
+   |        ^^^^^^^
+   |
+   = help: use `::<...>` instead of `<...>` if you meant to specify type arguments
+   = help: or use `(...)` if you meant to specify fn arguments
+
+error: chained comparison operators require parentheses
+  --> $DIR/issue-40396.rs:18:20
+   |
+LL |     (0..13).collect<Vec<i32>();
+   |                    ^^^^^^^^
+   |
+   = help: use `::<...>` instead of `<...>` if you meant to specify type arguments
+   = help: or use `(...)` if you meant to specify fn arguments
+
+error: chained comparison operators require parentheses
+  --> $DIR/issue-40396.rs:18:24
+   |
+LL |     (0..13).collect<Vec<i32>();
+   |                        ^^^^^^
+   |
+   = help: use `::<...>` instead of `<...>` if you meant to specify type arguments
+   = help: or use `(...)` if you meant to specify fn arguments
+
+error[E0423]: expected value, found struct `Vec`
+  --> $DIR/issue-40396.rs:2:21
+   |
+LL |     (0..13).collect<Vec<i32>>();
+   |                     ^^^ did you mean `Vec { /* fields */ }`?
+
+error[E0423]: expected value, found builtin type `i32`
+  --> $DIR/issue-40396.rs:2:25
+   |
+LL |     (0..13).collect<Vec<i32>>();
+   |                         ^^^ not a value
+
+error[E0423]: expected value, found struct `Vec`
+  --> $DIR/issue-40396.rs:10:5
+   |
+LL |     Vec<i32>::new();
+   |     ^^^ did you mean `Vec { /* fields */ }`?
+
+error[E0423]: expected value, found builtin type `i32`
+  --> $DIR/issue-40396.rs:10:9
+   |
+LL |     Vec<i32>::new();
+   |         ^^^ not a value
+
+error[E0425]: cannot find function `new` in the crate root
+  --> $DIR/issue-40396.rs:10:15
+   |
+LL |     Vec<i32>::new();
+   |               ^^^ not found in the crate root
+
+error[E0423]: expected value, found struct `Vec`
+  --> $DIR/issue-40396.rs:18:21
+   |
+LL |     (0..13).collect<Vec<i32>();
+   |                     ^^^ did you mean `Vec { /* fields */ }`?
+
+error[E0423]: expected value, found builtin type `i32`
+  --> $DIR/issue-40396.rs:18:25
+   |
+LL |     (0..13).collect<Vec<i32>();
+   |                         ^^^ not a value
+
+error[E0615]: attempted to take value of method `collect` on type `std::ops::Range<{integer}>`
+  --> $DIR/issue-40396.rs:2:13
+   |
+LL |     (0..13).collect<Vec<i32>>();
+   |             ^^^^^^^ help: use parentheses to call the method: `collect()`
+
+error[E0615]: attempted to take value of method `collect` on type `std::ops::Range<{integer}>`
+  --> $DIR/issue-40396.rs:18:13
+   |
+LL |     (0..13).collect<Vec<i32>();
+   |             ^^^^^^^ help: use parentheses to call the method: `collect()`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-40396.rs:18:29
+   |
+LL |     (0..13).collect<Vec<i32>();
+   |                             ^^ expected bool, found ()
+   |
+   = note: expected type `bool`
+              found type `()`
+
+error: aborting due to 14 previous errors
+
+Some errors occurred: E0308, E0423, E0425, E0615.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/did_you_mean/issue-40823.nll.stderr b/src/test/ui/did_you_mean/issue-40823.nll.stderr
new file mode 100644
index 0000000..7347340
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-40823.nll.stderr
@@ -0,0 +1,11 @@
+error[E0596]: cannot borrow `*buf` as mutable, as it is behind a `&` reference
+  --> $DIR/issue-40823.rs:3: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();
+   |     ^^^ `buf` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/did_you_mean/issue-40823.rs b/src/test/ui/did_you_mean/issue-40823.rs
new file mode 100644
index 0000000..7e456a3
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-40823.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let mut buf = &[1, 2, 3, 4];
+    buf.iter_mut(); //~ ERROR cannot borrow immutable borrowed content
+}
diff --git a/src/test/ui/did_you_mean/issue-40823.stderr b/src/test/ui/did_you_mean/issue-40823.stderr
new file mode 100644
index 0000000..fa2150a
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-40823.stderr
@@ -0,0 +1,9 @@
+error[E0596]: cannot borrow immutable borrowed content `*buf` as mutable
+  --> $DIR/issue-40823.rs:3:5
+   |
+LL |     buf.iter_mut();
+   |     ^^^ cannot borrow as mutable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/did_you_mean/issue-41679-tilde-bitwise-negation-attempt.rs b/src/test/ui/did_you_mean/issue-41679-tilde-bitwise-negation-attempt.rs
new file mode 100644
index 0000000..b59fe42
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-41679-tilde-bitwise-negation-attempt.rs
@@ -0,0 +1,3 @@
+fn main() {
+    let x = ~1; //~ ERROR cannot be used as a unary operator
+}
diff --git a/src/test/ui/did_you_mean/issue-41679-tilde-bitwise-negation-attempt.stderr b/src/test/ui/did_you_mean/issue-41679-tilde-bitwise-negation-attempt.stderr
new file mode 100644
index 0000000..84235ca
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-41679-tilde-bitwise-negation-attempt.stderr
@@ -0,0 +1,8 @@
+error: `~` cannot be used as a unary operator
+  --> $DIR/issue-41679-tilde-bitwise-negation-attempt.rs:2:13
+   |
+LL |     let x = ~1;
+   |             ^ help: use `!` to perform bitwise negation
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/did_you_mean/issue-42599_available_fields_note.rs b/src/test/ui/did_you_mean/issue-42599_available_fields_note.rs
new file mode 100644
index 0000000..c377dfc
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-42599_available_fields_note.rs
@@ -0,0 +1,37 @@
+mod submodule {
+
+    #[derive(Default)]
+    pub struct Demo {
+        pub favorite_integer: isize,
+        secret_integer: isize,
+        pub innocently_misspellable: (),
+        another_field: bool,
+        yet_another_field: bool,
+        always_more_fields: bool,
+        and_ever: bool,
+    }
+
+    impl Demo {
+        fn new_with_secret_two() -> Self {
+            Self { secret_integer: 2, inocently_mispellable: () }
+            //~^ ERROR no field
+        }
+
+        fn new_with_secret_three() -> Self {
+            Self { secret_integer: 3, egregiously_nonexistent_field: () }
+            //~^ ERROR no field
+        }
+    }
+
+}
+
+fn main() {
+    use submodule::Demo;
+
+    let demo = Demo::default();
+    let innocent_field_misaccess = demo.inocently_mispellable;
+    //~^ ERROR no field
+    // note shouldn't suggest private fields
+    let egregious_field_misaccess = demo.egregiously_nonexistent_field;
+    //~^ ERROR no field
+}
diff --git a/src/test/ui/did_you_mean/issue-42599_available_fields_note.stderr b/src/test/ui/did_you_mean/issue-42599_available_fields_note.stderr
new file mode 100644
index 0000000..e5dd61c
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-42599_available_fields_note.stderr
@@ -0,0 +1,32 @@
+error[E0560]: struct `submodule::Demo` has no field named `inocently_mispellable`
+  --> $DIR/issue-42599_available_fields_note.rs:16:39
+   |
+LL |             Self { secret_integer: 2, inocently_mispellable: () }
+   |                                       ^^^^^^^^^^^^^^^^^^^^^ help: a field with a similar name exists: `innocently_misspellable`
+
+error[E0560]: struct `submodule::Demo` has no field named `egregiously_nonexistent_field`
+  --> $DIR/issue-42599_available_fields_note.rs:21:39
+   |
+LL |             Self { secret_integer: 3, egregiously_nonexistent_field: () }
+   |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `submodule::Demo` does not have this field
+   |
+   = note: available fields are: `favorite_integer`, `secret_integer`, `innocently_misspellable`, `another_field`, `yet_another_field` ... and 2 others
+
+error[E0609]: no field `inocently_mispellable` on type `submodule::Demo`
+  --> $DIR/issue-42599_available_fields_note.rs:32:41
+   |
+LL |     let innocent_field_misaccess = demo.inocently_mispellable;
+   |                                         ^^^^^^^^^^^^^^^^^^^^^ help: a field with a similar name exists: `innocently_misspellable`
+
+error[E0609]: no field `egregiously_nonexistent_field` on type `submodule::Demo`
+  --> $DIR/issue-42599_available_fields_note.rs:35:42
+   |
+LL |     let egregious_field_misaccess = demo.egregiously_nonexistent_field;
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unknown field
+   |
+   = note: available fields are: `favorite_integer`, `innocently_misspellable`
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0560, E0609.
+For more information about an error, try `rustc --explain E0560`.
diff --git a/src/test/ui/did_you_mean/issue-42764.rs b/src/test/ui/did_you_mean/issue-42764.rs
new file mode 100644
index 0000000..5dd70aa
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-42764.rs
@@ -0,0 +1,29 @@
+enum DoubleOption<T> {
+    FirstSome(T),
+    AlternativeSome(T),
+    Nothing,
+}
+
+fn this_function_expects_a_double_option<T>(d: DoubleOption<T>) {}
+
+fn main() {
+    let n: usize = 42;
+    this_function_expects_a_double_option(n);
+    //~^ ERROR mismatched types
+    //~| HELP try using a variant of the expected type
+}
+
+
+// But don't issue the "try using a variant" help if the one-"variant" ADT is
+// actually a one-field struct.
+
+struct Payload;
+
+struct Wrapper { payload: Payload }
+
+struct Context { wrapper: Wrapper }
+
+fn overton() {
+    let _c = Context { wrapper: Payload{} };
+    //~^ ERROR mismatched types
+}
diff --git a/src/test/ui/did_you_mean/issue-42764.stderr b/src/test/ui/did_you_mean/issue-42764.stderr
new file mode 100644
index 0000000..64868c4
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-42764.stderr
@@ -0,0 +1,27 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-42764.rs:11:43
+   |
+LL |     this_function_expects_a_double_option(n);
+   |                                           ^ expected enum `DoubleOption`, found usize
+   |
+   = note: expected type `DoubleOption<_>`
+              found type `usize`
+help: try using a variant of the expected type
+   |
+LL |     this_function_expects_a_double_option(DoubleOption::FirstSome(n));
+   |                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     this_function_expects_a_double_option(DoubleOption::AlternativeSome(n));
+   |                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/issue-42764.rs:27:33
+   |
+LL |     let _c = Context { wrapper: Payload{} };
+   |                                 ^^^^^^^^^ expected struct `Wrapper`, found struct `Payload`
+   |
+   = note: expected type `Wrapper`
+              found type `Payload`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/did_you_mean/issue-43871-enum-instead-of-variant.rs b/src/test/ui/did_you_mean/issue-43871-enum-instead-of-variant.rs
new file mode 100644
index 0000000..7d3aba36
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-43871-enum-instead-of-variant.rs
@@ -0,0 +1,36 @@
+enum Example { Ex(String), NotEx }
+
+enum Void {}
+
+enum ManyVariants {
+    One,
+    Two,
+    Three,
+    Four,
+    Five,
+    Six,
+    Seven,
+    Eight,
+    Nine,
+    Ten,
+}
+
+fn result_test() {
+    let x = Option(1); //~ ERROR expected function, found enum
+
+    if let Option(_) = x { //~ ERROR expected tuple struct/variant, found enum
+        println!("It is OK.");
+    }
+
+    let y = Example::Ex(String::from("test"));
+
+    if let Example(_) = y { //~ ERROR expected tuple struct/variant, found enum
+        println!("It is OK.");
+    }
+
+    let y = Void(); //~ ERROR expected function, found enum
+
+    let z = ManyVariants(); //~ ERROR expected function, found enum
+}
+
+fn main() {}
diff --git a/src/test/ui/did_you_mean/issue-43871-enum-instead-of-variant.stderr b/src/test/ui/did_you_mean/issue-43871-enum-instead-of-variant.stderr
new file mode 100644
index 0000000..4210b4e
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-43871-enum-instead-of-variant.stderr
@@ -0,0 +1,63 @@
+error[E0423]: expected function, found enum `Option`
+  --> $DIR/issue-43871-enum-instead-of-variant.rs:19:13
+   |
+LL |     let x = Option(1);
+   |             ^^^^^^
+help: try using one of the enum's variants
+   |
+LL |     let x = std::prelude::v1::Option::None(1);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     let x = std::prelude::v1::Option::Some(1);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0532]: expected tuple struct/variant, found enum `Option`
+  --> $DIR/issue-43871-enum-instead-of-variant.rs:21:12
+   |
+LL |     if let Option(_) = x {
+   |            ^^^^^^
+help: try using one of the enum's variants
+   |
+LL |     if let std::prelude::v1::Option::None(_) = x {
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     if let std::prelude::v1::Option::Some(_) = x {
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0532]: expected tuple struct/variant, found enum `Example`
+  --> $DIR/issue-43871-enum-instead-of-variant.rs:27:12
+   |
+LL |     if let Example(_) = y {
+   |            ^^^^^^^
+help: try using one of the enum's variants
+   |
+LL |     if let Example::Ex(_) = y {
+   |            ^^^^^^^^^^^
+LL |     if let Example::NotEx(_) = y {
+   |            ^^^^^^^^^^^^^^
+
+error[E0423]: expected function, found enum `Void`
+  --> $DIR/issue-43871-enum-instead-of-variant.rs:31:13
+   |
+LL |     let y = Void();
+   |             ^^^^
+
+error[E0423]: expected function, found enum `ManyVariants`
+  --> $DIR/issue-43871-enum-instead-of-variant.rs:33:13
+   |
+LL |     let z = ManyVariants();
+   |             ^^^^^^^^^^^^
+help: try using one of the enum's variants
+   |
+LL |     let z = ManyVariants::Eight();
+   |             ^^^^^^^^^^^^^^^^^^^
+LL |     let z = ManyVariants::Five();
+   |             ^^^^^^^^^^^^^^^^^^
+LL |     let z = ManyVariants::Four();
+   |             ^^^^^^^^^^^^^^^^^^
+LL |     let z = ManyVariants::Nine();
+   |             ^^^^^^^^^^^^^^^^^^
+and 6 other candidates
+
+error: aborting due to 5 previous errors
+
+Some errors occurred: E0423, E0532.
+For more information about an error, try `rustc --explain E0423`.
diff --git a/src/test/ui/did_you_mean/issue-46718-struct-pattern-dotdotdot.rs b/src/test/ui/did_you_mean/issue-46718-struct-pattern-dotdotdot.rs
new file mode 100644
index 0000000..63e8b2b
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-46718-struct-pattern-dotdotdot.rs
@@ -0,0 +1,17 @@
+#![allow(unused)]
+
+struct PersonalityInventory {
+    expressivity: f32,
+    instrumentality: f32
+}
+
+impl PersonalityInventory {
+    fn expressivity(&self) -> f32 {
+        match *self {
+            PersonalityInventory { expressivity: exp, ... } => exp
+            //~^ ERROR expected field pattern, found `...`
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/did_you_mean/issue-46718-struct-pattern-dotdotdot.stderr b/src/test/ui/did_you_mean/issue-46718-struct-pattern-dotdotdot.stderr
new file mode 100644
index 0000000..bfe1ed3
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-46718-struct-pattern-dotdotdot.stderr
@@ -0,0 +1,8 @@
+error: expected field pattern, found `...`
+  --> $DIR/issue-46718-struct-pattern-dotdotdot.rs:11:55
+   |
+LL |             PersonalityInventory { expressivity: exp, ... } => exp
+   |                                                       ^^^ help: to omit remaining fields, use one fewer `.`: `..`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.rs b/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.rs
new file mode 100644
index 0000000..df697cc
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.rs
@@ -0,0 +1,34 @@
+fn gratitude() {
+    let for_you = false;
+    if not for_you {
+        //~^ ERROR unexpected `for_you` after identifier
+        println!("I couldn't");
+    }
+}
+
+fn qualification() {
+    let the_worst = true;
+    while not the_worst {
+        //~^ ERROR unexpected `the_worst` after identifier
+        println!("still pretty bad");
+    }
+}
+
+fn should_we() {
+    let not = true;
+    if not  // lack of braces is [sic]
+        println!("Then when?");
+    //~^ ERROR expected `{`, found `;
+    //~| ERROR unexpected `println` after identifier
+}
+
+fn sleepy() {
+    let resource = not 2;
+    //~^ ERROR unexpected `2` after identifier
+}
+
+fn main() {
+    let be_smothered_out_before = true;
+    let young_souls = not be_smothered_out_before;
+    //~^ ERROR unexpected `be_smothered_out_before` after identifier
+}
diff --git a/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr b/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr
new file mode 100644
index 0000000..f1c93d5
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr
@@ -0,0 +1,50 @@
+error: unexpected `for_you` after identifier
+  --> $DIR/issue-46836-identifier-not-instead-of-negation.rs:3:12
+   |
+LL |     if not for_you {
+   |        ----^^^^^^^
+   |        |
+   |        help: use `!` to perform logical negation
+
+error: unexpected `the_worst` after identifier
+  --> $DIR/issue-46836-identifier-not-instead-of-negation.rs:11:15
+   |
+LL |     while not the_worst {
+   |           ----^^^^^^^^^
+   |           |
+   |           help: use `!` to perform logical negation
+
+error: unexpected `println` after identifier
+  --> $DIR/issue-46836-identifier-not-instead-of-negation.rs:20:9
+   |
+LL |     if not  // lack of braces is [sic]
+   |        ----- help: use `!` to perform logical negation
+LL |         println!("Then when?");
+   |         ^^^^^^^
+
+error: expected `{`, found `;`
+  --> $DIR/issue-46836-identifier-not-instead-of-negation.rs:20:31
+   |
+LL |     if not  // lack of braces is [sic]
+   |     -- this `if` statement has a condition, but no block
+LL |         println!("Then when?");
+   |                               ^ expected `{`
+
+error: unexpected `2` after identifier
+  --> $DIR/issue-46836-identifier-not-instead-of-negation.rs:26:24
+   |
+LL |     let resource = not 2;
+   |                    ----^
+   |                    |
+   |                    help: use `!` to perform logical negation
+
+error: unexpected `be_smothered_out_before` after identifier
+  --> $DIR/issue-46836-identifier-not-instead-of-negation.rs:32:27
+   |
+LL |     let young_souls = not be_smothered_out_before;
+   |                       ----^^^^^^^^^^^^^^^^^^^^^^^
+   |                       |
+   |                       help: use `!` to perform logical negation
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/did_you_mean/issue-48492-tuple-destructure-missing-parens.rs b/src/test/ui/did_you_mean/issue-48492-tuple-destructure-missing-parens.rs
new file mode 100644
index 0000000..43b5f6d
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-48492-tuple-destructure-missing-parens.rs
@@ -0,0 +1,87 @@
+#![allow(unused)]
+
+#[derive(Copy, Clone)]
+enum Nucleotide {
+    Adenine,
+    Thymine,
+    Cytosine,
+    Guanine
+}
+
+#[derive(Clone)]
+struct Autosome;
+
+#[derive(Clone)]
+enum Allosome {
+    X(Vec<Nucleotide>),
+    Y(Vec<Nucleotide>)
+}
+
+impl Allosome {
+    fn is_x(&self) -> bool {
+        match *self {
+            Allosome::X(_) => true,
+            Allosome::Y(_) => false,
+        }
+    }
+}
+
+#[derive(Clone)]
+struct Genome {
+    autosomes: [Autosome; 22],
+    allosomes: (Allosome, Allosome)
+}
+
+fn find_start_codon(strand: &[Nucleotide]) -> Option<usize> {
+    let mut reading_frame = strand.windows(3);
+    // (missing parentheses in `while let` tuple pattern)
+    while let b1, b2, b3 = reading_frame.next().expect("there should be a start codon") {
+        //~^ ERROR unexpected `,` in pattern
+        // ...
+    }
+    None
+}
+
+fn find_thr(strand: &[Nucleotide]) -> Option<usize> {
+    let mut reading_frame = strand.windows(3);
+    let mut i = 0;
+    // (missing parentheses in `if let` tuple pattern)
+    if let b1, b2, b3 = reading_frame.next().unwrap() {
+        //~^ ERROR unexpected `,` in pattern
+        // ...
+    }
+    None
+}
+
+fn is_thr(codon: (Nucleotide, Nucleotide, Nucleotide)) -> bool {
+    match codon {
+        // (missing parentheses in match arm tuple pattern)
+        Nucleotide::Adenine, Nucleotide::Cytosine, _ => true
+        //~^ ERROR unexpected `,` in pattern
+        _ => false
+    }
+}
+
+fn analyze_female_sex_chromosomes(women: &[Genome]) {
+    // (missing parentheses in `for` tuple pattern)
+    for x, _barr_body in women.iter().map(|woman| woman.allosomes.clone()) {
+        //~^ ERROR unexpected `,` in pattern
+        // ...
+    }
+}
+
+fn analyze_male_sex_chromosomes(men: &[Genome]) {
+    // (missing parentheses in pattern with `@` binding)
+    for x, y @ Allosome::Y(_) in men.iter().map(|man| man.allosomes.clone()) {
+        //~^ ERROR unexpected `,` in pattern
+        // ...
+    }
+}
+
+fn main() {
+    let genomes = Vec::new();
+    // (missing parentheses in `let` pattern)
+    let women, men: (Vec<Genome>, Vec<Genome>) = genomes.iter().cloned()
+    //~^ ERROR unexpected `,` in pattern
+        .partition(|g: &Genome| g.allosomes.0.is_x() && g.allosomes.1.is_x());
+}
diff --git a/src/test/ui/did_you_mean/issue-48492-tuple-destructure-missing-parens.stderr b/src/test/ui/did_you_mean/issue-48492-tuple-destructure-missing-parens.stderr
new file mode 100644
index 0000000..8099c3c
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-48492-tuple-destructure-missing-parens.stderr
@@ -0,0 +1,86 @@
+error: unexpected `,` in pattern
+  --> $DIR/issue-48492-tuple-destructure-missing-parens.rs:38:17
+   |
+LL |     while let b1, b2, b3 = reading_frame.next().expect("there should be a start codon") {
+   |                 ^
+help: try adding parentheses to match on a tuple..
+   |
+LL |     while let (b1, b2, b3) = reading_frame.next().expect("there should be a start codon") {
+   |               ^^^^^^^^^^^^
+help: ..or a vertical bar to match on multiple alternatives
+   |
+LL |     while let b1 | b2 | b3 = reading_frame.next().expect("there should be a start codon") {
+   |               ^^^^^^^^^^^^
+
+error: unexpected `,` in pattern
+  --> $DIR/issue-48492-tuple-destructure-missing-parens.rs:49:14
+   |
+LL |     if let b1, b2, b3 = reading_frame.next().unwrap() {
+   |              ^
+help: try adding parentheses to match on a tuple..
+   |
+LL |     if let (b1, b2, b3) = reading_frame.next().unwrap() {
+   |            ^^^^^^^^^^^^
+help: ..or a vertical bar to match on multiple alternatives
+   |
+LL |     if let b1 | b2 | b3 = reading_frame.next().unwrap() {
+   |            ^^^^^^^^^^^^
+
+error: unexpected `,` in pattern
+  --> $DIR/issue-48492-tuple-destructure-missing-parens.rs:59:28
+   |
+LL |         Nucleotide::Adenine, Nucleotide::Cytosine, _ => true
+   |                            ^
+help: try adding parentheses to match on a tuple..
+   |
+LL |         (Nucleotide::Adenine, Nucleotide::Cytosine, _) => true
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: ..or a vertical bar to match on multiple alternatives
+   |
+LL |         Nucleotide::Adenine | Nucleotide::Cytosine | _ => true
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: unexpected `,` in pattern
+  --> $DIR/issue-48492-tuple-destructure-missing-parens.rs:67:10
+   |
+LL |     for x, _barr_body in women.iter().map(|woman| woman.allosomes.clone()) {
+   |          ^
+help: try adding parentheses to match on a tuple..
+   |
+LL |     for (x, _barr_body) in women.iter().map(|woman| woman.allosomes.clone()) {
+   |         ^^^^^^^^^^^^^^^
+help: ..or a vertical bar to match on multiple alternatives
+   |
+LL |     for x | _barr_body in women.iter().map(|woman| woman.allosomes.clone()) {
+   |         ^^^^^^^^^^^^^^
+
+error: unexpected `,` in pattern
+  --> $DIR/issue-48492-tuple-destructure-missing-parens.rs:75:10
+   |
+LL |     for x, y @ Allosome::Y(_) in men.iter().map(|man| man.allosomes.clone()) {
+   |          ^
+help: try adding parentheses to match on a tuple..
+   |
+LL |     for (x, y @ Allosome::Y(_)) in men.iter().map(|man| man.allosomes.clone()) {
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+help: ..or a vertical bar to match on multiple alternatives
+   |
+LL |     for x | y @ Allosome::Y(_) in men.iter().map(|man| man.allosomes.clone()) {
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+
+error: unexpected `,` in pattern
+  --> $DIR/issue-48492-tuple-destructure-missing-parens.rs:84:14
+   |
+LL |     let women, men: (Vec<Genome>, Vec<Genome>) = genomes.iter().cloned()
+   |              ^
+help: try adding parentheses to match on a tuple..
+   |
+LL |     let (women, men): (Vec<Genome>, Vec<Genome>) = genomes.iter().cloned()
+   |         ^^^^^^^^^^^^
+help: ..or a vertical bar to match on multiple alternatives
+   |
+LL |     let women | men: (Vec<Genome>, Vec<Genome>) = genomes.iter().cloned()
+   |         ^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.rs b/src/test/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.rs
new file mode 100644
index 0000000..b4795e7
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.rs
@@ -0,0 +1,4 @@
+const UNIVERSAL_GRAVITATIONAL_CONSTANT: f64 = 6.674e−11; // m³⋅kg⁻¹⋅s⁻²
+//~^ ERROR expected at least one digit in exponent
+
+fn main() {}
diff --git a/src/test/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.stderr b/src/test/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.stderr
new file mode 100644
index 0000000..253deb2
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.stderr
@@ -0,0 +1,12 @@
+error: expected at least one digit in exponent
+  --> $DIR/issue-49746-unicode-confusable-in-float-literal-expt.rs:1:53
+   |
+LL | const UNIVERSAL_GRAVITATIONAL_CONSTANT: f64 = 6.674e−11; // m³⋅kg⁻¹⋅s⁻²
+   |                                                     ^
+help: Unicode character '−' (Minus Sign) looks like '-' (Minus/Hyphen), but it is not
+   |
+LL | const UNIVERSAL_GRAVITATIONAL_CONSTANT: f64 = 6.674e-11; // m³⋅kg⁻¹⋅s⁻²
+   |                                                     ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/did_you_mean/issue-53280-expected-float-found-integer-literal.rs b/src/test/ui/did_you_mean/issue-53280-expected-float-found-integer-literal.rs
new file mode 100644
index 0000000..73f1856
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-53280-expected-float-found-integer-literal.rs
@@ -0,0 +1,19 @@
+fn main() {
+    let sixteen: f32 = 16;
+    //~^ ERROR mismatched types
+    //~| HELP use a float literal
+    let a_million_and_seventy: f64 = 1_000_070;
+    //~^ ERROR mismatched types
+    //~| HELP use a float literal
+    let negative_nine: f32 = -9;
+    //~^ ERROR mismatched types
+    //~| HELP use a float literal
+
+
+    // only base-10 literals get the suggestion
+
+    let sixteen_again: f64 = 0x10;
+    //~^ ERROR mismatched types
+    let and_once_more: f32 = 0o20;
+    //~^ ERROR mismatched types
+}
diff --git a/src/test/ui/did_you_mean/issue-53280-expected-float-found-integer-literal.stderr b/src/test/ui/did_you_mean/issue-53280-expected-float-found-integer-literal.stderr
new file mode 100644
index 0000000..301704e
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-53280-expected-float-found-integer-literal.stderr
@@ -0,0 +1,57 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-53280-expected-float-found-integer-literal.rs:2:24
+   |
+LL |     let sixteen: f32 = 16;
+   |                        ^^
+   |                        |
+   |                        expected f32, found integer
+   |                        help: use a float literal: `16.0`
+   |
+   = note: expected type `f32`
+              found type `{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-53280-expected-float-found-integer-literal.rs:5:38
+   |
+LL |     let a_million_and_seventy: f64 = 1_000_070;
+   |                                      ^^^^^^^^^
+   |                                      |
+   |                                      expected f64, found integer
+   |                                      help: use a float literal: `1_000_070.0`
+   |
+   = note: expected type `f64`
+              found type `{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-53280-expected-float-found-integer-literal.rs:8:30
+   |
+LL |     let negative_nine: f32 = -9;
+   |                              ^^
+   |                              |
+   |                              expected f32, found integer
+   |                              help: use a float literal: `-9.0`
+   |
+   = note: expected type `f32`
+              found type `{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-53280-expected-float-found-integer-literal.rs:15:30
+   |
+LL |     let sixteen_again: f64 = 0x10;
+   |                              ^^^^ expected f64, found integer
+   |
+   = note: expected type `f64`
+              found type `{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-53280-expected-float-found-integer-literal.rs:17:30
+   |
+LL |     let and_once_more: f32 = 0o20;
+   |                              ^^^^ expected f32, found integer
+   |
+   = note: expected type `f32`
+              found type `{integer}`
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/did_you_mean/issue-54109-and_instead_of_ampersands.rs b/src/test/ui/did_you_mean/issue-54109-and_instead_of_ampersands.rs
new file mode 100644
index 0000000..687479b
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-54109-and_instead_of_ampersands.rs
@@ -0,0 +1,56 @@
+fn test_and() {
+    let a = true;
+    let b = false;
+    if a and b {
+        //~^ ERROR expected `{`, found `and`
+        println!("both");
+    }
+}
+
+fn test_or() {
+    let a = true;
+    let b = false;
+    if a or b {
+        //~^ ERROR expected `{`, found `or`
+        println!("both");
+    }
+}
+
+fn test_and_par() {
+    let a = true;
+    let b = false;
+    if (a and b) {
+        //~^ ERROR expected one of `!`, `)`, `,`, `.`, `::`, `?`, `{`, or an operator, found `and`
+        println!("both");
+    }
+}
+
+fn test_or_par() {
+    let a = true;
+    let b = false;
+    if (a or b) {
+        //~^ ERROR expected one of `!`, `)`, `,`, `.`, `::`, `?`, `{`, or an operator, found `or`
+        println!("both");
+    }
+}
+
+fn test_while_and() {
+    let a = true;
+    let b = false;
+    while a and b {
+        //~^ ERROR expected one of `!`, `.`, `::`, `?`, `{`, or an operator, found `and`
+        println!("both");
+    }
+}
+
+fn test_while_or() {
+    let a = true;
+    let b = false;
+    while a or b {
+        //~^ ERROR expected one of `!`, `.`, `::`, `?`, `{`, or an operator, found `or`
+        println!("both");
+    }
+}
+
+fn main() {
+}
diff --git a/src/test/ui/did_you_mean/issue-54109-and_instead_of_ampersands.stderr b/src/test/ui/did_you_mean/issue-54109-and_instead_of_ampersands.stderr
new file mode 100644
index 0000000..35123b1
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-54109-and_instead_of_ampersands.stderr
@@ -0,0 +1,58 @@
+error: expected `{`, found `and`
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:4:10
+   |
+LL |     if a and b {
+   |     --   ^^^
+   |     |    |
+   |     |    expected `{`
+   |     |    help: use `&&` instead of `and` for the boolean operator
+   |     this `if` statement has a condition, but no block
+
+error: expected `{`, found `or`
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:13:10
+   |
+LL |     if a or b {
+   |     --   ^^
+   |     |    |
+   |     |    expected `{`
+   |     |    help: use `||` instead of `or` for the boolean operator
+   |     this `if` statement has a condition, but no block
+
+error: expected one of `!`, `)`, `,`, `.`, `::`, `?`, `{`, or an operator, found `and`
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:22:11
+   |
+LL |     if (a and b) {
+   |           ^^^
+   |           |
+   |           expected one of 8 possible tokens here
+   |           help: use `&&` instead of `and` for the boolean operator
+
+error: expected one of `!`, `)`, `,`, `.`, `::`, `?`, `{`, or an operator, found `or`
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:31:11
+   |
+LL |     if (a or b) {
+   |           ^^
+   |           |
+   |           expected one of 8 possible tokens here
+   |           help: use `||` instead of `or` for the boolean operator
+
+error: expected one of `!`, `.`, `::`, `?`, `{`, or an operator, found `and`
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:40:13
+   |
+LL |     while a and b {
+   |             ^^^
+   |             |
+   |             expected one of `!`, `.`, `::`, `?`, `{`, or an operator here
+   |             help: use `&&` instead of `and` for the boolean operator
+
+error: expected one of `!`, `.`, `::`, `?`, `{`, or an operator, found `or`
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:49:13
+   |
+LL |     while a or b {
+   |             ^^
+   |             |
+   |             expected one of `!`, `.`, `::`, `?`, `{`, or an operator here
+   |             help: use `||` instead of `or` for the boolean operator
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/did_you_mean/issue-56028-there-is-an-enum-variant.rs b/src/test/ui/did_you_mean/issue-56028-there-is-an-enum-variant.rs
new file mode 100644
index 0000000..264cfa4
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-56028-there-is-an-enum-variant.rs
@@ -0,0 +1,15 @@
+enum PutDown { Set }
+enum AffixHeart { Set }
+enum CauseToBe { Set }
+enum Determine { Set }
+enum TableDishesAction { Set }
+enum Solidify { Set }
+enum UnorderedCollection { Set }
+
+fn setup() -> Set { Set }
+//~^ ERROR cannot find type `Set` in this scope
+//~| ERROR cannot find value `Set` in this scope
+
+fn main() {
+    setup();
+}
diff --git a/src/test/ui/did_you_mean/issue-56028-there-is-an-enum-variant.stderr b/src/test/ui/did_you_mean/issue-56028-there-is-an-enum-variant.stderr
new file mode 100644
index 0000000..6107ca3
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-56028-there-is-an-enum-variant.stderr
@@ -0,0 +1,38 @@
+error[E0412]: cannot find type `Set` in this scope
+  --> $DIR/issue-56028-there-is-an-enum-variant.rs:9:15
+   |
+LL | fn setup() -> Set { Set }
+   |               ^^^ not found in this scope
+help: there is an enum variant `AffixHeart::Set` and 7 others; try using the variant's enum
+   |
+LL | fn setup() -> AffixHeart { Set }
+   |               ^^^^^^^^^^
+LL | fn setup() -> CauseToBe { Set }
+   |               ^^^^^^^^^
+LL | fn setup() -> Determine { Set }
+   |               ^^^^^^^^^
+LL | fn setup() -> PutDown { Set }
+   |               ^^^^^^^
+and 3 other candidates
+
+error[E0425]: cannot find value `Set` in this scope
+  --> $DIR/issue-56028-there-is-an-enum-variant.rs:9:21
+   |
+LL | fn setup() -> Set { Set }
+   |                     ^^^ not found in this scope
+help: possible candidates are found in other modules, you can import them into scope
+   |
+LL | use AffixHeart::Set;
+   |
+LL | use CauseToBe::Set;
+   |
+LL | use Determine::Set;
+   |
+LL | use PutDown::Set;
+   |
+and 3 other candidates
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0412, E0425.
+For more information about an error, try `rustc --explain E0412`.
diff --git a/src/test/ui/did_you_mean/multiple-pattern-typo.rs b/src/test/ui/did_you_mean/multiple-pattern-typo.rs
new file mode 100644
index 0000000..14ad33d
--- /dev/null
+++ b/src/test/ui/did_you_mean/multiple-pattern-typo.rs
@@ -0,0 +1,7 @@
+fn main() {
+    let x = 3;
+    match x {
+        1 | 2 || 3 => (), //~ ERROR unexpected token `||` after pattern
+        _ => (),
+    }
+}
diff --git a/src/test/ui/did_you_mean/multiple-pattern-typo.stderr b/src/test/ui/did_you_mean/multiple-pattern-typo.stderr
new file mode 100644
index 0000000..a29fa58
--- /dev/null
+++ b/src/test/ui/did_you_mean/multiple-pattern-typo.stderr
@@ -0,0 +1,8 @@
+error: unexpected token `||` after pattern
+  --> $DIR/multiple-pattern-typo.rs:4:15
+   |
+LL |         1 | 2 || 3 => (),
+   |               ^^ help: use a single `|` to specify multiple patterns: `|`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/did_you_mean/pub-macro-rules.rs b/src/test/ui/did_you_mean/pub-macro-rules.rs
new file mode 100644
index 0000000..c539370
--- /dev/null
+++ b/src/test/ui/did_you_mean/pub-macro-rules.rs
@@ -0,0 +1,16 @@
+#[macro_use] mod bleh {
+    pub macro_rules! foo { //~ ERROR can't qualify macro_rules invocation
+        ($n:ident) => (
+            fn $n () -> i32 {
+                1
+            }
+        )
+    }
+
+}
+
+foo!(meh);
+
+fn main() {
+    println!("{}", meh());
+}
diff --git a/src/test/ui/did_you_mean/pub-macro-rules.stderr b/src/test/ui/did_you_mean/pub-macro-rules.stderr
new file mode 100644
index 0000000..0bde578
--- /dev/null
+++ b/src/test/ui/did_you_mean/pub-macro-rules.stderr
@@ -0,0 +1,8 @@
+error: can't qualify macro_rules invocation with `pub`
+  --> $DIR/pub-macro-rules.rs:2:5
+   |
+LL |     pub macro_rules! foo {
+   |     ^^^ help: try exporting the macro: `#[macro_export]`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/did_you_mean/recursion_limit.rs b/src/test/ui/did_you_mean/recursion_limit.rs
new file mode 100644
index 0000000..38db129
--- /dev/null
+++ b/src/test/ui/did_you_mean/recursion_limit.rs
@@ -0,0 +1,35 @@
+// Test that the recursion limit can be changed and that the compiler
+// suggests a fix. In this case, we have deeply nested types that will
+// fail the `Send` check by overflow when the recursion limit is set
+// very low.
+
+#![allow(dead_code)]
+#![recursion_limit="10"]
+
+macro_rules! link {
+    ($id:ident, $t:ty) => {
+        enum $id { $id($t) }
+    }
+}
+
+link! { A, B }
+link! { B, C }
+link! { C, D }
+link! { D, E }
+link! { E, F }
+link! { F, G }
+link! { G, H }
+link! { H, I }
+link! { I, J }
+link! { J, K }
+link! { K, L }
+link! { L, M }
+link! { M, N }
+
+enum N { N(usize) }
+
+fn is_send<T:Send>() { }
+
+fn main() {
+    is_send::<A>(); //~ ERROR overflow evaluating the requirement
+}
diff --git a/src/test/ui/did_you_mean/recursion_limit.stderr b/src/test/ui/did_you_mean/recursion_limit.stderr
new file mode 100644
index 0000000..a646d98
--- /dev/null
+++ b/src/test/ui/did_you_mean/recursion_limit.stderr
@@ -0,0 +1,25 @@
+error[E0275]: overflow evaluating the requirement `J: std::marker::Send`
+  --> $DIR/recursion_limit.rs:34:5
+   |
+LL |     is_send::<A>();
+   |     ^^^^^^^^^^^^
+   |
+   = help: consider adding a `#![recursion_limit="20"]` attribute to your crate
+   = note: required because it appears within the type `I`
+   = note: required because it appears within the type `H`
+   = note: required because it appears within the type `G`
+   = note: required because it appears within the type `F`
+   = note: required because it appears within the type `E`
+   = note: required because it appears within the type `D`
+   = note: required because it appears within the type `C`
+   = note: required because it appears within the type `B`
+   = note: required because it appears within the type `A`
+note: required by `is_send`
+  --> $DIR/recursion_limit.rs:31:1
+   |
+LL | fn is_send<T:Send>() { }
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/src/test/ui/did_you_mean/recursion_limit_deref.rs b/src/test/ui/did_you_mean/recursion_limit_deref.rs
new file mode 100644
index 0000000..76e555e
--- /dev/null
+++ b/src/test/ui/did_you_mean/recursion_limit_deref.rs
@@ -0,0 +1,53 @@
+// Test that the recursion limit can be changed and that the compiler
+// suggests a fix. In this case, we have a long chain of Deref impls
+// which will cause an overflow during the autoderef loop.
+
+#![allow(dead_code)]
+#![recursion_limit="10"]
+
+macro_rules! link {
+    ($outer:ident, $inner:ident) => {
+        struct $outer($inner);
+
+        impl $outer {
+            fn new() -> $outer {
+                $outer($inner::new())
+            }
+        }
+
+        impl std::ops::Deref for $outer {
+            type Target = $inner;
+
+            fn deref(&self) -> &$inner {
+                &self.0
+            }
+        }
+    }
+}
+
+struct Bottom;
+impl Bottom {
+    fn new() -> Bottom {
+        Bottom
+    }
+}
+
+link!(Top, A);
+link!(A, B);
+link!(B, C);
+link!(C, D);
+link!(D, E);
+link!(E, F);
+link!(F, G);
+link!(G, H);
+link!(H, I);
+link!(I, J);
+link!(J, K);
+link!(K, Bottom);
+
+fn main() {
+    let t = Top::new();
+    let x: &Bottom = &t; //~ ERROR mismatched types
+    //~^ error recursion limit
+}
+
diff --git a/src/test/ui/did_you_mean/recursion_limit_deref.stderr b/src/test/ui/did_you_mean/recursion_limit_deref.stderr
new file mode 100644
index 0000000..08e32ad
--- /dev/null
+++ b/src/test/ui/did_you_mean/recursion_limit_deref.stderr
@@ -0,0 +1,21 @@
+error[E0055]: reached the recursion limit while auto-dereferencing `I`
+  --> $DIR/recursion_limit_deref.rs:50:22
+   |
+LL |     let x: &Bottom = &t;
+   |                      ^^ deref recursion limit reached
+   |
+   = help: consider adding a `#![recursion_limit="20"]` attribute to your crate
+
+error[E0308]: mismatched types
+  --> $DIR/recursion_limit_deref.rs:50:22
+   |
+LL |     let x: &Bottom = &t;
+   |                      ^^ expected struct `Bottom`, found struct `Top`
+   |
+   = note: expected type `&Bottom`
+              found type `&Top`
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0055, E0308.
+For more information about an error, try `rustc --explain E0055`.
diff --git a/src/test/ui/did_you_mean/recursion_limit_macro.rs b/src/test/ui/did_you_mean/recursion_limit_macro.rs
new file mode 100644
index 0000000..c941536
--- /dev/null
+++ b/src/test/ui/did_you_mean/recursion_limit_macro.rs
@@ -0,0 +1,16 @@
+// Test that the recursion limit can be changed and that the compiler
+// suggests a fix. In this case, we have a recursing macro that will
+// overflow if the number of arguments surpasses the recursion limit.
+
+#![allow(dead_code)]
+#![recursion_limit="10"]
+
+macro_rules! recurse {
+    () => { };
+    ($t:tt $($tail:tt)*) => { recurse!($($tail)*) }; //~ ERROR recursion limit
+}
+
+fn main() {
+    recurse!(0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9);
+}
+
diff --git a/src/test/ui/did_you_mean/recursion_limit_macro.stderr b/src/test/ui/did_you_mean/recursion_limit_macro.stderr
new file mode 100644
index 0000000..6640ced
--- /dev/null
+++ b/src/test/ui/did_you_mean/recursion_limit_macro.stderr
@@ -0,0 +1,13 @@
+error: recursion limit reached while expanding the macro `recurse`
+  --> $DIR/recursion_limit_macro.rs:10:31
+   |
+LL |     ($t:tt $($tail:tt)*) => { recurse!($($tail)*) };
+   |                               ^^^^^^^^^^^^^^^^^^^
+...
+LL |     recurse!(0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9);
+   |     -------------------------------------------------- in this macro invocation
+   |
+   = help: consider adding a `#![recursion_limit="20"]` attribute to your crate
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/did_you_mean/trait-object-reference-without-parens-suggestion.rs b/src/test/ui/did_you_mean/trait-object-reference-without-parens-suggestion.rs
new file mode 100644
index 0000000..a052274
--- /dev/null
+++ b/src/test/ui/did_you_mean/trait-object-reference-without-parens-suggestion.rs
@@ -0,0 +1,5 @@
+fn main() {
+    let _: &Copy + 'static; //~ ERROR expected a path
+    //~^ ERROR cannot be made into an object
+    let _: &'static Copy + 'static; //~ ERROR expected a path
+}
diff --git a/src/test/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr b/src/test/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr
new file mode 100644
index 0000000..a94260d
--- /dev/null
+++ b/src/test/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr
@@ -0,0 +1,24 @@
+error[E0178]: expected a path on the left-hand side of `+`, not `&Copy`
+  --> $DIR/trait-object-reference-without-parens-suggestion.rs:2:12
+   |
+LL |     let _: &Copy + 'static;
+   |            ^^^^^^^^^^^^^^^ help: try adding parentheses: `&(Copy + 'static)`
+
+error[E0178]: expected a path on the left-hand side of `+`, not `&'static Copy`
+  --> $DIR/trait-object-reference-without-parens-suggestion.rs:4:12
+   |
+LL |     let _: &'static Copy + 'static;
+   |            ^^^^^^^^^^^^^^^^^^^^^^^ help: try adding parentheses: `&'static (Copy + 'static)`
+
+error[E0038]: the trait `std::marker::Copy` cannot be made into an object
+  --> $DIR/trait-object-reference-without-parens-suggestion.rs:2:12
+   |
+LL |     let _: &Copy + 'static;
+   |            ^^^^^ the trait `std::marker::Copy` cannot be made into an object
+   |
+   = note: the trait cannot require that `Self : Sized`
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0038, E0178.
+For more information about an error, try `rustc --explain E0038`.
diff --git a/src/test/ui/directory_ownership/foo/compiletest-ignore-dir b/src/test/ui/directory_ownership/foo/compiletest-ignore-dir
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/test/ui/directory_ownership/foo/compiletest-ignore-dir
diff --git a/src/test/ui/directory_ownership/foo/mod_file_not_owning/aux2.rs b/src/test/ui/directory_ownership/foo/mod_file_not_owning/aux2.rs
new file mode 100644
index 0000000..d11c69f
--- /dev/null
+++ b/src/test/ui/directory_ownership/foo/mod_file_not_owning/aux2.rs
@@ -0,0 +1 @@
+// intentionally empty
diff --git a/src/test/ui/directory_ownership/foo/mod_file_not_owning_aux2.rs b/src/test/ui/directory_ownership/foo/mod_file_not_owning_aux2.rs
new file mode 100644
index 0000000..d11c69f
--- /dev/null
+++ b/src/test/ui/directory_ownership/foo/mod_file_not_owning_aux2.rs
@@ -0,0 +1 @@
+// intentionally empty
diff --git a/src/test/ui/directory_ownership/macro-expanded-mod.rs b/src/test/ui/directory_ownership/macro-expanded-mod.rs
new file mode 100644
index 0000000..9752a64
--- /dev/null
+++ b/src/test/ui/directory_ownership/macro-expanded-mod.rs
@@ -0,0 +1,14 @@
+// Test that macro-expanded non-inline modules behave correctly
+
+macro_rules! mod_decl {
+    ($i:ident) => { mod $i; }
+}
+
+mod macro_expanded_mod_helper {
+    mod_decl!(foo); // This should search in the folder `macro_expanded_mod_helper`
+}
+
+fn main() {
+    mod_decl!(foo);
+    //~^ ERROR Cannot declare a non-inline module inside a block
+}
diff --git a/src/test/ui/directory_ownership/macro-expanded-mod.stderr b/src/test/ui/directory_ownership/macro-expanded-mod.stderr
new file mode 100644
index 0000000..620a00f
--- /dev/null
+++ b/src/test/ui/directory_ownership/macro-expanded-mod.stderr
@@ -0,0 +1,8 @@
+error: Cannot declare a non-inline module inside a block unless it has a path attribute
+  --> $DIR/macro-expanded-mod.rs:12:15
+   |
+LL |     mod_decl!(foo);
+   |               ^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/directory_ownership/macro_expanded_mod_helper/foo/bar.rs b/src/test/ui/directory_ownership/macro_expanded_mod_helper/foo/bar.rs
new file mode 100644
index 0000000..01c087d
--- /dev/null
+++ b/src/test/ui/directory_ownership/macro_expanded_mod_helper/foo/bar.rs
@@ -0,0 +1 @@
+// ignore-test not a test, auxiliary
diff --git a/src/test/ui/directory_ownership/macro_expanded_mod_helper/foo/mod.rs b/src/test/ui/directory_ownership/macro_expanded_mod_helper/foo/mod.rs
new file mode 100644
index 0000000..2ec1c8b
--- /dev/null
+++ b/src/test/ui/directory_ownership/macro_expanded_mod_helper/foo/mod.rs
@@ -0,0 +1,3 @@
+// ignore-test not a test, auxiliary
+
+mod_decl!(bar);
diff --git a/src/test/ui/directory_ownership/mod_file_not_owning_aux1.rs b/src/test/ui/directory_ownership/mod_file_not_owning_aux1.rs
new file mode 100644
index 0000000..eb5e8e3
--- /dev/null
+++ b/src/test/ui/directory_ownership/mod_file_not_owning_aux1.rs
@@ -0,0 +1,6 @@
+// ignore-test this is not a test
+
+macro_rules! m {
+    () => { mod mod_file_not_owning_aux2; }
+}
+m!();
diff --git a/src/test/ui/directory_ownership/mod_file_not_owning_aux1/compiletest-ignore-dir b/src/test/ui/directory_ownership/mod_file_not_owning_aux1/compiletest-ignore-dir
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/test/ui/directory_ownership/mod_file_not_owning_aux1/compiletest-ignore-dir
diff --git a/src/test/ui/directory_ownership/mod_file_not_owning_aux1/mod_file_not_owning_aux2.rs b/src/test/ui/directory_ownership/mod_file_not_owning_aux1/mod_file_not_owning_aux2.rs
new file mode 100644
index 0000000..d11c69f
--- /dev/null
+++ b/src/test/ui/directory_ownership/mod_file_not_owning_aux1/mod_file_not_owning_aux2.rs
@@ -0,0 +1 @@
+// intentionally empty
diff --git a/src/test/ui/directory_ownership/mod_file_not_owning_aux2.rs b/src/test/ui/directory_ownership/mod_file_not_owning_aux2.rs
new file mode 100644
index 0000000..920938c
--- /dev/null
+++ b/src/test/ui/directory_ownership/mod_file_not_owning_aux2.rs
@@ -0,0 +1 @@
+// ignore-test this is not a test
diff --git a/src/test/ui/directory_ownership/mod_file_not_owning_aux3.rs b/src/test/ui/directory_ownership/mod_file_not_owning_aux3.rs
new file mode 100644
index 0000000..6e4a392
--- /dev/null
+++ b/src/test/ui/directory_ownership/mod_file_not_owning_aux3.rs
@@ -0,0 +1,3 @@
+// ignore-test this is not a test
+
+mod mod_file_not_owning_aux2;
diff --git a/src/test/ui/directory_ownership/non-inline-mod-restriction.rs b/src/test/ui/directory_ownership/non-inline-mod-restriction.rs
new file mode 100644
index 0000000..af31b8a
--- /dev/null
+++ b/src/test/ui/directory_ownership/non-inline-mod-restriction.rs
@@ -0,0 +1,5 @@
+// Test that non-inline modules are not allowed inside blocks.
+
+fn main() {
+    mod foo; //~ ERROR Cannot declare a non-inline module inside a block
+}
diff --git a/src/test/ui/directory_ownership/non-inline-mod-restriction.stderr b/src/test/ui/directory_ownership/non-inline-mod-restriction.stderr
new file mode 100644
index 0000000..46acc7e
--- /dev/null
+++ b/src/test/ui/directory_ownership/non-inline-mod-restriction.stderr
@@ -0,0 +1,8 @@
+error: Cannot declare a non-inline module inside a block unless it has a path attribute
+  --> $DIR/non-inline-mod-restriction.rs:4:9
+   |
+LL |     mod foo;
+   |         ^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.nll.stderr b/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.nll.stderr
new file mode 100644
index 0000000..fff3a64
--- /dev/null
+++ b/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.nll.stderr
@@ -0,0 +1,17 @@
+error[E0509]: cannot move out of type `X`, which implements the `Drop` trait
+  --> $DIR/disallowed-deconstructing-destructing-struct-let.rs:12:22
+   |
+LL |     let X { x: y } = x;
+   |                -     ^ cannot move out of here
+   |                |
+   |                data moved here
+   |
+note: move occurs because `y` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/disallowed-deconstructing-destructing-struct-let.rs:12:16
+   |
+LL |     let X { x: y } = x;
+   |                ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0509`.
diff --git a/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.rs b/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.rs
new file mode 100644
index 0000000..8e39449
--- /dev/null
+++ b/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.rs
@@ -0,0 +1,20 @@
+struct X {
+    x: String,
+}
+
+impl Drop for X {
+    fn drop(&mut self) {
+        println!("value: {}", self.x);
+    }
+}
+
+fn unwrap(x: X) -> String {
+    let X { x: y } = x; //~ ERROR cannot move out of type
+    y
+}
+
+fn main() {
+    let x = X { x: "hello".to_string() };
+    let y = unwrap(x);
+    println!("contents: {}", y);
+}
diff --git a/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.stderr b/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.stderr
new file mode 100644
index 0000000..9984cac
--- /dev/null
+++ b/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.stderr
@@ -0,0 +1,12 @@
+error[E0509]: cannot move out of type `X`, which implements the `Drop` trait
+  --> $DIR/disallowed-deconstructing-destructing-struct-let.rs:12:9
+   |
+LL |     let X { x: y } = x;
+   |         ^^^^^^^-^^
+   |         |      |
+   |         |      hint: to prevent move, use `ref y` or `ref mut y`
+   |         cannot move out of here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0509`.
diff --git a/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.nll.stderr b/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.nll.stderr
new file mode 100644
index 0000000..2143c2f9
--- /dev/null
+++ b/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.nll.stderr
@@ -0,0 +1,17 @@
+error[E0509]: cannot move out of type `X`, which implements the `Drop` trait
+  --> $DIR/disallowed-deconstructing-destructing-struct-match.rs:14:11
+   |
+LL |     match x {
+   |           ^ cannot move out of here
+LL |         X { x: y } => println!("contents: {}", y)
+   |                - data moved here
+   |
+note: move occurs because `y` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/disallowed-deconstructing-destructing-struct-match.rs:15:16
+   |
+LL |         X { x: y } => println!("contents: {}", y)
+   |                ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0509`.
diff --git a/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.rs b/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.rs
new file mode 100644
index 0000000..3a5ed6e
--- /dev/null
+++ b/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.rs
@@ -0,0 +1,18 @@
+struct X {
+    x: String,
+}
+
+impl Drop for X {
+    fn drop(&mut self) {
+        println!("value: {}", self.x);
+    }
+}
+
+fn main() {
+    let x = X { x: "hello".to_string() };
+
+    match x {
+        X { x: y } => println!("contents: {}", y)
+        //~^ ERROR cannot move out of type `X`, which implements the `Drop` trait
+    }
+}
diff --git a/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.stderr b/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.stderr
new file mode 100644
index 0000000..8be1b38
--- /dev/null
+++ b/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.stderr
@@ -0,0 +1,12 @@
+error[E0509]: cannot move out of type `X`, which implements the `Drop` trait
+  --> $DIR/disallowed-deconstructing-destructing-struct-match.rs:15:9
+   |
+LL |         X { x: y } => println!("contents: {}", y)
+   |         ^^^^^^^-^^
+   |         |      |
+   |         |      hint: to prevent move, use `ref y` or `ref mut y`
+   |         cannot move out of here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0509`.
diff --git a/src/test/ui/discrim/discrim-ill-typed.rs b/src/test/ui/discrim/discrim-ill-typed.rs
new file mode 100644
index 0000000..3844d21
--- /dev/null
+++ b/src/test/ui/discrim/discrim-ill-typed.rs
@@ -0,0 +1,116 @@
+// When explicit discriminant value has
+// a type that does not match the representation
+// type, rustc should fail gracefully.
+
+// See also run-pass/discrim-explicit-23030.rs where the input types
+// are correct.
+
+#![allow(dead_code, unused_variables, unused_imports)]
+
+use std::{i8,u8,i16,u16,i32,u32,i64, u64};
+
+fn f_i8() {
+    #[repr(i8)]
+    enum A {
+        Ok = i8::MAX - 1,
+        Ok2,
+        OhNo = 0_u8,
+        //~^ ERROR mismatched types
+        //~| expected i8, found u8
+    }
+
+    let x = A::Ok;
+}
+
+fn f_u8() {
+    #[repr(u8)]
+    enum A {
+        Ok = u8::MAX - 1,
+        Ok2,
+        OhNo = 0_i8,
+        //~^ ERROR mismatched types
+        //~| expected u8, found i8
+    }
+
+    let x = A::Ok;
+}
+
+fn f_i16() {
+    #[repr(i16)]
+    enum A {
+        Ok = i16::MAX - 1,
+        Ok2,
+        OhNo = 0_u16,
+        //~^ ERROR mismatched types
+        //~| expected i16, found u16
+    }
+
+    let x = A::Ok;
+}
+
+fn f_u16() {
+    #[repr(u16)]
+    enum A {
+        Ok = u16::MAX - 1,
+        Ok2,
+        OhNo = 0_i16,
+        //~^ ERROR mismatched types
+        //~| expected u16, found i16
+    }
+
+    let x = A::Ok;
+}
+
+fn f_i32() {
+    #[repr(i32)]
+    enum A {
+        Ok = i32::MAX - 1,
+        Ok2,
+        OhNo = 0_u32,
+        //~^ ERROR mismatched types
+        //~| expected i32, found u32
+    }
+
+    let x = A::Ok;
+}
+
+fn f_u32() {
+    #[repr(u32)]
+    enum A {
+        Ok = u32::MAX - 1,
+        Ok2,
+        OhNo = 0_i32,
+        //~^ ERROR mismatched types
+        //~| expected u32, found i32
+    }
+
+    let x = A::Ok;
+}
+
+fn f_i64() {
+    #[repr(i64)]
+    enum A {
+        Ok = i64::MAX - 1,
+        Ok2,
+        OhNo = 0_u64,
+        //~^ ERROR mismatched types
+        //~| expected i64, found u64
+    }
+
+    let x = A::Ok;
+}
+
+fn f_u64() {
+    #[repr(u64)]
+    enum A {
+        Ok = u64::MAX - 1,
+        Ok2,
+        OhNo = 0_i64,
+        //~^ ERROR mismatched types
+        //~| expected u64, found i64
+    }
+
+    let x = A::Ok;
+}
+
+fn main() { }
diff --git a/src/test/ui/discrim/discrim-ill-typed.stderr b/src/test/ui/discrim/discrim-ill-typed.stderr
new file mode 100644
index 0000000..14cdb9e
--- /dev/null
+++ b/src/test/ui/discrim/discrim-ill-typed.stderr
@@ -0,0 +1,51 @@
+error[E0308]: mismatched types
+  --> $DIR/discrim-ill-typed.rs:17:16
+   |
+LL |         OhNo = 0_u8,
+   |                ^^^^ expected i8, found u8
+
+error[E0308]: mismatched types
+  --> $DIR/discrim-ill-typed.rs:30:16
+   |
+LL |         OhNo = 0_i8,
+   |                ^^^^ expected u8, found i8
+
+error[E0308]: mismatched types
+  --> $DIR/discrim-ill-typed.rs:43:16
+   |
+LL |         OhNo = 0_u16,
+   |                ^^^^^ expected i16, found u16
+
+error[E0308]: mismatched types
+  --> $DIR/discrim-ill-typed.rs:56:16
+   |
+LL |         OhNo = 0_i16,
+   |                ^^^^^ expected u16, found i16
+
+error[E0308]: mismatched types
+  --> $DIR/discrim-ill-typed.rs:69:16
+   |
+LL |         OhNo = 0_u32,
+   |                ^^^^^ expected i32, found u32
+
+error[E0308]: mismatched types
+  --> $DIR/discrim-ill-typed.rs:82:16
+   |
+LL |         OhNo = 0_i32,
+   |                ^^^^^ expected u32, found i32
+
+error[E0308]: mismatched types
+  --> $DIR/discrim-ill-typed.rs:95:16
+   |
+LL |         OhNo = 0_u64,
+   |                ^^^^^ expected i64, found u64
+
+error[E0308]: mismatched types
+  --> $DIR/discrim-ill-typed.rs:108:16
+   |
+LL |         OhNo = 0_i64,
+   |                ^^^^^ expected u64, found i64
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/discrim/discrim-overflow-2.rs b/src/test/ui/discrim/discrim-overflow-2.rs
new file mode 100644
index 0000000..9ff39cd
--- /dev/null
+++ b/src/test/ui/discrim/discrim-overflow-2.rs
@@ -0,0 +1,84 @@
+// ignore-tidy-linelength
+
+// Issue 23030: Detect overflowing discriminant
+//
+// Check that we detect the overflow even if enum is not used.
+
+// See also run-pass/discrim-explicit-23030.rs where the suggested
+// workaround is tested.
+
+use std::{i8,u8,i16,u16,i32,u32,i64, u64};
+
+fn f_i8() {
+    #[repr(i8)]
+    enum A {
+        Ok = i8::MAX - 1,
+        Ok2,
+        OhNo, //~ ERROR enum discriminant overflowed [E0370]
+    }
+}
+
+fn f_u8() {
+    #[repr(u8)]
+    enum A {
+        Ok = u8::MAX - 1,
+        Ok2,
+        OhNo, //~ ERROR enum discriminant overflowed [E0370]
+    }
+}
+
+fn f_i16() {
+    #[repr(i16)]
+    enum A {
+        Ok = i16::MAX - 1,
+        Ok2,
+        OhNo, //~ ERROR enum discriminant overflowed [E0370]
+    }
+}
+
+fn f_u16() {
+    #[repr(u16)]
+    enum A {
+        Ok = u16::MAX - 1,
+        Ok2,
+        OhNo, //~ ERROR enum discriminant overflowed [E0370]
+    }
+}
+
+fn f_i32() {
+    #[repr(i32)]
+    enum A {
+        Ok = i32::MAX - 1,
+        Ok2,
+        OhNo, //~ ERROR enum discriminant overflowed [E0370]
+    }
+}
+
+fn f_u32() {
+    #[repr(u32)]
+    enum A {
+        Ok = u32::MAX - 1,
+        Ok2,
+        OhNo, //~ ERROR enum discriminant overflowed [E0370]
+    }
+}
+
+fn f_i64() {
+    #[repr(i64)]
+    enum A {
+        Ok = i64::MAX - 1,
+        Ok2,
+        OhNo, //~ ERROR enum discriminant overflowed [E0370]
+    }
+}
+
+fn f_u64() {
+    #[repr(u64)]
+    enum A {
+        Ok = u64::MAX - 1,
+        Ok2,
+        OhNo, //~ ERROR enum discriminant overflowed [E0370]
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/discrim/discrim-overflow-2.stderr b/src/test/ui/discrim/discrim-overflow-2.stderr
new file mode 100644
index 0000000..744324d
--- /dev/null
+++ b/src/test/ui/discrim/discrim-overflow-2.stderr
@@ -0,0 +1,67 @@
+error[E0370]: enum discriminant overflowed
+  --> $DIR/discrim-overflow-2.rs:17:9
+   |
+LL |         OhNo,
+   |         ^^^^ overflowed on value after 127
+   |
+   = note: explicitly set `OhNo = -128` if that is desired outcome
+
+error[E0370]: enum discriminant overflowed
+  --> $DIR/discrim-overflow-2.rs:26:9
+   |
+LL |         OhNo,
+   |         ^^^^ overflowed on value after 255
+   |
+   = note: explicitly set `OhNo = 0` if that is desired outcome
+
+error[E0370]: enum discriminant overflowed
+  --> $DIR/discrim-overflow-2.rs:35:9
+   |
+LL |         OhNo,
+   |         ^^^^ overflowed on value after 32767
+   |
+   = note: explicitly set `OhNo = -32768` if that is desired outcome
+
+error[E0370]: enum discriminant overflowed
+  --> $DIR/discrim-overflow-2.rs:44:9
+   |
+LL |         OhNo,
+   |         ^^^^ overflowed on value after 65535
+   |
+   = note: explicitly set `OhNo = 0` if that is desired outcome
+
+error[E0370]: enum discriminant overflowed
+  --> $DIR/discrim-overflow-2.rs:53:9
+   |
+LL |         OhNo,
+   |         ^^^^ overflowed on value after 2147483647
+   |
+   = note: explicitly set `OhNo = -2147483648` if that is desired outcome
+
+error[E0370]: enum discriminant overflowed
+  --> $DIR/discrim-overflow-2.rs:62:9
+   |
+LL |         OhNo,
+   |         ^^^^ overflowed on value after 4294967295
+   |
+   = note: explicitly set `OhNo = 0` if that is desired outcome
+
+error[E0370]: enum discriminant overflowed
+  --> $DIR/discrim-overflow-2.rs:71:9
+   |
+LL |         OhNo,
+   |         ^^^^ overflowed on value after 9223372036854775807
+   |
+   = note: explicitly set `OhNo = -9223372036854775808` if that is desired outcome
+
+error[E0370]: enum discriminant overflowed
+  --> $DIR/discrim-overflow-2.rs:80:9
+   |
+LL |         OhNo,
+   |         ^^^^ overflowed on value after 18446744073709551615
+   |
+   = note: explicitly set `OhNo = 0` if that is desired outcome
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0370`.
diff --git a/src/test/ui/discrim/discrim-overflow.rs b/src/test/ui/discrim/discrim-overflow.rs
new file mode 100644
index 0000000..c612661
--- /dev/null
+++ b/src/test/ui/discrim/discrim-overflow.rs
@@ -0,0 +1,103 @@
+// ignore-tidy-linelength
+
+// Issue 23030: Detect overflowing discriminant
+
+// See also run-pass/discrim-explicit-23030.rs where the suggested
+// workaround is tested.
+
+use std::{i8,u8,i16,u16,i32,u32,i64, u64};
+
+fn f_i8() {
+    #[repr(i8)]
+    enum A {
+        Ok = i8::MAX - 1,
+        Ok2,
+        OhNo, //~ ERROR enum discriminant overflowed [E0370]
+    }
+
+    let x = A::Ok;
+}
+
+fn f_u8() {
+    #[repr(u8)]
+    enum A {
+        Ok = u8::MAX - 1,
+        Ok2,
+        OhNo, //~ ERROR enum discriminant overflowed [E0370]
+    }
+
+    let x = A::Ok;
+}
+
+fn f_i16() {
+    #[repr(i16)]
+    enum A {
+        Ok = i16::MAX - 1,
+        Ok2,
+        OhNo, //~ ERROR enum discriminant overflowed [E0370]
+    }
+
+    let x = A::Ok;
+}
+
+fn f_u16() {
+    #[repr(u16)]
+    enum A {
+        Ok = u16::MAX - 1,
+        Ok2,
+        OhNo, //~ ERROR enum discriminant overflowed [E0370]
+              //~| overflowed on value after 65535
+    }
+
+    let x = A::Ok;
+}
+
+fn f_i32() {
+    #[repr(i32)]
+    enum A {
+        Ok = i32::MAX - 1,
+        Ok2,
+        OhNo, //~ ERROR enum discriminant overflowed [E0370]
+              //~| overflowed on value after 2147483647
+    }
+
+    let x = A::Ok;
+}
+
+fn f_u32() {
+    #[repr(u32)]
+    enum A {
+        Ok = u32::MAX - 1,
+        Ok2,
+        OhNo, //~ ERROR enum discriminant overflowed [E0370]
+              //~| overflowed on value after 4294967295
+    }
+
+    let x = A::Ok;
+}
+
+fn f_i64() {
+    #[repr(i64)]
+    enum A {
+        Ok = i64::MAX - 1,
+        Ok2,
+        OhNo, //~ ERROR enum discriminant overflowed [E0370]
+              //~| overflowed on value after 9223372036854775807
+    }
+
+    let x = A::Ok;
+}
+
+fn f_u64() {
+    #[repr(u64)]
+    enum A {
+        Ok = u64::MAX - 1,
+        Ok2,
+        OhNo, //~ ERROR enum discriminant overflowed [E0370]
+              //~| overflowed on value after 18446744073709551615
+    }
+
+    let x = A::Ok;
+}
+
+fn main() { }
diff --git a/src/test/ui/discrim/discrim-overflow.stderr b/src/test/ui/discrim/discrim-overflow.stderr
new file mode 100644
index 0000000..c831fdf
--- /dev/null
+++ b/src/test/ui/discrim/discrim-overflow.stderr
@@ -0,0 +1,67 @@
+error[E0370]: enum discriminant overflowed
+  --> $DIR/discrim-overflow.rs:15:9
+   |
+LL |         OhNo,
+   |         ^^^^ overflowed on value after 127
+   |
+   = note: explicitly set `OhNo = -128` if that is desired outcome
+
+error[E0370]: enum discriminant overflowed
+  --> $DIR/discrim-overflow.rs:26:9
+   |
+LL |         OhNo,
+   |         ^^^^ overflowed on value after 255
+   |
+   = note: explicitly set `OhNo = 0` if that is desired outcome
+
+error[E0370]: enum discriminant overflowed
+  --> $DIR/discrim-overflow.rs:37:9
+   |
+LL |         OhNo,
+   |         ^^^^ overflowed on value after 32767
+   |
+   = note: explicitly set `OhNo = -32768` if that is desired outcome
+
+error[E0370]: enum discriminant overflowed
+  --> $DIR/discrim-overflow.rs:48:9
+   |
+LL |         OhNo,
+   |         ^^^^ overflowed on value after 65535
+   |
+   = note: explicitly set `OhNo = 0` if that is desired outcome
+
+error[E0370]: enum discriminant overflowed
+  --> $DIR/discrim-overflow.rs:60:9
+   |
+LL |         OhNo,
+   |         ^^^^ overflowed on value after 2147483647
+   |
+   = note: explicitly set `OhNo = -2147483648` if that is desired outcome
+
+error[E0370]: enum discriminant overflowed
+  --> $DIR/discrim-overflow.rs:72:9
+   |
+LL |         OhNo,
+   |         ^^^^ overflowed on value after 4294967295
+   |
+   = note: explicitly set `OhNo = 0` if that is desired outcome
+
+error[E0370]: enum discriminant overflowed
+  --> $DIR/discrim-overflow.rs:84:9
+   |
+LL |         OhNo,
+   |         ^^^^ overflowed on value after 9223372036854775807
+   |
+   = note: explicitly set `OhNo = -9223372036854775808` if that is desired outcome
+
+error[E0370]: enum discriminant overflowed
+  --> $DIR/discrim-overflow.rs:96:9
+   |
+LL |         OhNo,
+   |         ^^^^ overflowed on value after 18446744073709551615
+   |
+   = note: explicitly set `OhNo = 0` if that is desired outcome
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0370`.
diff --git a/src/test/ui/diverging-fn-tail-35849.rs b/src/test/ui/diverging-fn-tail-35849.rs
new file mode 100644
index 0000000..f21ce29
--- /dev/null
+++ b/src/test/ui/diverging-fn-tail-35849.rs
@@ -0,0 +1,8 @@
+fn assert_sizeof() -> ! {
+    unsafe {
+        ::std::mem::transmute::<f64, [u8; 8]>(panic!())
+            //~^ ERROR mismatched types
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/diverging-fn-tail-35849.stderr b/src/test/ui/diverging-fn-tail-35849.stderr
new file mode 100644
index 0000000..383a700
--- /dev/null
+++ b/src/test/ui/diverging-fn-tail-35849.stderr
@@ -0,0 +1,15 @@
+error[E0308]: mismatched types
+  --> $DIR/diverging-fn-tail-35849.rs:3:9
+   |
+LL | fn assert_sizeof() -> ! {
+   |                       - expected `!` because of return type
+LL |     unsafe {
+LL |         ::std::mem::transmute::<f64, [u8; 8]>(panic!())
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected !, found array of 8 elements
+   |
+   = note: expected type `!`
+              found type `[u8; 8]`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/diverging-tuple-parts-39485.rs b/src/test/ui/diverging-tuple-parts-39485.rs
new file mode 100644
index 0000000..0cde611
--- /dev/null
+++ b/src/test/ui/diverging-tuple-parts-39485.rs
@@ -0,0 +1,15 @@
+// After #39485, this test used to pass, but that change was reverted
+// due to numerous inference failures like #39808, so it now fails
+// again. #39485 made it so that diverging types never propagate
+// upward; but we now do propagate such types upward in many more
+// cases.
+
+fn g() {
+    &panic!() //~ ERROR mismatched types
+}
+
+fn f() -> isize {
+    (return 1, return 2) //~ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/src/test/ui/diverging-tuple-parts-39485.stderr b/src/test/ui/diverging-tuple-parts-39485.stderr
new file mode 100644
index 0000000..70eefeb
--- /dev/null
+++ b/src/test/ui/diverging-tuple-parts-39485.stderr
@@ -0,0 +1,31 @@
+error[E0308]: mismatched types
+  --> $DIR/diverging-tuple-parts-39485.rs:8:5
+   |
+LL |     &panic!()
+   |     ^^^^^^^^^ expected (), found reference
+   |
+   = note: expected type `()`
+              found type `&_`
+help: try adding a return type
+   |
+LL | fn g() -> &_ {
+   |        ^^^^^
+help: consider removing the borrow
+   |
+LL |     panic!()
+   |     ^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/diverging-tuple-parts-39485.rs:12:5
+   |
+LL | fn f() -> isize {
+   |           ----- expected `isize` because of return type
+LL |     (return 1, return 2)
+   |     ^^^^^^^^^^^^^^^^^^^^ expected isize, found tuple
+   |
+   = note: expected type `isize`
+              found type `(!, !)`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/does-nothing.rs b/src/test/ui/does-nothing.rs
new file mode 100644
index 0000000..e4992e2
--- /dev/null
+++ b/src/test/ui/does-nothing.rs
@@ -0,0 +1,2 @@
+fn main() { println!("doing"); this_does_nothing_what_the; println!("boing"); }
+//~^ ERROR cannot find value `this_does_nothing_what_the` in this scope
diff --git a/src/test/ui/does-nothing.stderr b/src/test/ui/does-nothing.stderr
new file mode 100644
index 0000000..dca7923
--- /dev/null
+++ b/src/test/ui/does-nothing.stderr
@@ -0,0 +1,9 @@
+error[E0425]: cannot find value `this_does_nothing_what_the` in this scope
+  --> $DIR/does-nothing.rs:1:32
+   |
+LL | fn main() { println!("doing"); this_does_nothing_what_the; println!("boing"); }
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/dollar-crate/dollar-crate-is-keyword-2.rs b/src/test/ui/dollar-crate/dollar-crate-is-keyword-2.rs
new file mode 100644
index 0000000..bbab6f8
--- /dev/null
+++ b/src/test/ui/dollar-crate/dollar-crate-is-keyword-2.rs
@@ -0,0 +1,13 @@
+mod a {}
+
+macro_rules! m {
+    () => {
+        use a::$crate; //~ ERROR unresolved import `a::$crate`
+        use a::$crate::b; //~ ERROR `$crate` in paths can only be used in start position
+        type A = a::$crate; //~ ERROR `$crate` in paths can only be used in start position
+    }
+}
+
+m!();
+
+fn main() {}
diff --git a/src/test/ui/dollar-crate/dollar-crate-is-keyword-2.stderr b/src/test/ui/dollar-crate/dollar-crate-is-keyword-2.stderr
new file mode 100644
index 0000000..f9de5e1
--- /dev/null
+++ b/src/test/ui/dollar-crate/dollar-crate-is-keyword-2.stderr
@@ -0,0 +1,31 @@
+error[E0433]: failed to resolve: `$crate` in paths can only be used in start position
+  --> $DIR/dollar-crate-is-keyword-2.rs:6:16
+   |
+LL |         use a::$crate::b;
+   |                ^^^^^^ `$crate` in paths can only be used in start position
+...
+LL | m!();
+   | ----- in this macro invocation
+
+error[E0432]: unresolved import `a::$crate`
+  --> $DIR/dollar-crate-is-keyword-2.rs:5:13
+   |
+LL |         use a::$crate;
+   |             ^^^^^^^^^ no `$crate` in `a`
+...
+LL | m!();
+   | ----- in this macro invocation
+
+error[E0433]: failed to resolve: `$crate` in paths can only be used in start position
+  --> $DIR/dollar-crate-is-keyword-2.rs:7:21
+   |
+LL |         type A = a::$crate;
+   |                     ^^^^^^ `$crate` in paths can only be used in start position
+...
+LL | m!();
+   | ----- in this macro invocation
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0432, E0433.
+For more information about an error, try `rustc --explain E0432`.
diff --git a/src/test/ui/dollar-crate/dollar-crate-is-keyword.rs b/src/test/ui/dollar-crate/dollar-crate-is-keyword.rs
new file mode 100644
index 0000000..6deaeb8
--- /dev/null
+++ b/src/test/ui/dollar-crate/dollar-crate-is-keyword.rs
@@ -0,0 +1,18 @@
+macro_rules! m {
+    () => {
+        // Avoid having more than one `$crate`-named item in the same module,
+        // as even though they error, they still parse as `$crate` and conflict.
+        mod foo {
+            struct $crate {} //~ ERROR expected identifier, found reserved identifier `$crate`
+        }
+
+        use $crate; // OK
+                    //~^ WARN `$crate` may not be imported
+        use $crate as $crate; //~ ERROR expected identifier, found reserved identifier `$crate`
+                              //~^ WARN `$crate` may not be imported
+    }
+}
+
+m!();
+
+fn main() {}
diff --git a/src/test/ui/dollar-crate/dollar-crate-is-keyword.stderr b/src/test/ui/dollar-crate/dollar-crate-is-keyword.stderr
new file mode 100644
index 0000000..5d4f390
--- /dev/null
+++ b/src/test/ui/dollar-crate/dollar-crate-is-keyword.stderr
@@ -0,0 +1,42 @@
+error: expected identifier, found reserved identifier `$crate`
+  --> $DIR/dollar-crate-is-keyword.rs:6:20
+   |
+LL |             struct $crate {}
+   |                    ^^^^^^ expected identifier, found reserved identifier
+...
+LL | m!();
+   | ----- in this macro invocation
+
+error: expected identifier, found reserved identifier `$crate`
+  --> $DIR/dollar-crate-is-keyword.rs:11:23
+   |
+LL |         use $crate as $crate;
+   |                       ^^^^^^ expected identifier, found reserved identifier
+...
+LL | m!();
+   | ----- in this macro invocation
+
+warning: `$crate` may not be imported
+  --> $DIR/dollar-crate-is-keyword.rs:9:9
+   |
+LL |         use $crate; // OK
+   |         ^^^^^^^^^^^
+...
+LL | m!();
+   | ----- in this macro invocation
+   |
+   = note: `use $crate;` was erroneously allowed and will become a hard error in a future release
+
+warning: `$crate` may not be imported
+  --> $DIR/dollar-crate-is-keyword.rs:11:9
+   |
+LL |         use $crate as $crate;
+   |         ^^^^^^^^^^^^^^^^^^^^^
+...
+LL | m!();
+   | ----- in this macro invocation
+   |
+   = note: `use $crate;` was erroneously allowed and will become a hard error in a future release
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/dont-suggest-private-trait-method.rs b/src/test/ui/dont-suggest-private-trait-method.rs
new file mode 100644
index 0000000..ef0904c
--- /dev/null
+++ b/src/test/ui/dont-suggest-private-trait-method.rs
@@ -0,0 +1,6 @@
+struct T;
+
+fn main() {
+    T::new();
+    //~^ ERROR no function or associated item named `new` found for type `T` in the current scope
+}
diff --git a/src/test/ui/dont-suggest-private-trait-method.stderr b/src/test/ui/dont-suggest-private-trait-method.stderr
new file mode 100644
index 0000000..5189ffa
--- /dev/null
+++ b/src/test/ui/dont-suggest-private-trait-method.stderr
@@ -0,0 +1,12 @@
+error[E0599]: no function or associated item named `new` found for type `T` in the current scope
+  --> $DIR/dont-suggest-private-trait-method.rs:4:8
+   |
+LL | struct T;
+   | --------- function or associated item `new` not found for this
+...
+LL |     T::new();
+   |        ^^^ function or associated item not found in `T`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/dotdotdot-expr.rs b/src/test/ui/dotdotdot-expr.rs
new file mode 100644
index 0000000..d842fb6
--- /dev/null
+++ b/src/test/ui/dotdotdot-expr.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let _redemptive = 1...21;
+    //~^ ERROR unexpected token
+}
diff --git a/src/test/ui/dotdotdot-expr.stderr b/src/test/ui/dotdotdot-expr.stderr
new file mode 100644
index 0000000..a5ef7b6
--- /dev/null
+++ b/src/test/ui/dotdotdot-expr.stderr
@@ -0,0 +1,16 @@
+error: unexpected token: `...`
+  --> $DIR/dotdotdot-expr.rs:2:24
+   |
+LL |     let _redemptive = 1...21;
+   |                        ^^^
+help: use `..` for an exclusive range
+   |
+LL |     let _redemptive = 1..21;
+   |                        ^^
+help: or `..=` for an inclusive range
+   |
+LL |     let _redemptive = 1..=21;
+   |                        ^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/double-import.rs b/src/test/ui/double-import.rs
new file mode 100644
index 0000000..e732536
--- /dev/null
+++ b/src/test/ui/double-import.rs
@@ -0,0 +1,15 @@
+// This tests that conflicting imports shows both `use` lines
+// when reporting the error.
+
+mod sub1 {
+    pub fn foo() {} // implementation 1
+}
+
+mod sub2 {
+    pub fn foo() {} // implementation 2
+}
+
+use sub1::foo;
+use sub2::foo; //~ ERROR the name `foo` is defined multiple times
+
+fn main() {}
diff --git a/src/test/ui/double-import.stderr b/src/test/ui/double-import.stderr
new file mode 100644
index 0000000..7a4e8e5
--- /dev/null
+++ b/src/test/ui/double-import.stderr
@@ -0,0 +1,17 @@
+error[E0252]: the name `foo` is defined multiple times
+  --> $DIR/double-import.rs:13:5
+   |
+LL | use sub1::foo;
+   |     --------- previous import of the value `foo` here
+LL | use sub2::foo;
+   |     ^^^^^^^^^ `foo` reimported here
+   |
+   = note: `foo` must be defined only once in the value namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | use sub2::foo as other_foo;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0252`.
diff --git a/src/test/ui/double-type-import.rs b/src/test/ui/double-type-import.rs
new file mode 100644
index 0000000..6b1eb65
--- /dev/null
+++ b/src/test/ui/double-type-import.rs
@@ -0,0 +1,13 @@
+mod foo {
+    pub use self::bar::X;
+    use self::bar::X;
+    //~^ ERROR the name `X` is defined multiple times
+
+    mod bar {
+        pub struct X;
+    }
+}
+
+fn main() {
+    let _ = foo::X;
+}
diff --git a/src/test/ui/double-type-import.stderr b/src/test/ui/double-type-import.stderr
new file mode 100644
index 0000000..a2f30d8
--- /dev/null
+++ b/src/test/ui/double-type-import.stderr
@@ -0,0 +1,13 @@
+error[E0252]: the name `X` is defined multiple times
+  --> $DIR/double-type-import.rs:3:9
+   |
+LL |     pub use self::bar::X;
+   |             ------------ previous import of the type `X` here
+LL |     use self::bar::X;
+   |         ^^^^^^^^^^^^ `X` reimported here
+   |
+   = note: `X` must be defined only once in the type namespace of this module
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0252`.
diff --git a/src/test/ui/dropck/auxiliary/dropck_eyepatch_extern_crate.rs b/src/test/ui/dropck/auxiliary/dropck_eyepatch_extern_crate.rs
new file mode 100644
index 0000000..e070829
--- /dev/null
+++ b/src/test/ui/dropck/auxiliary/dropck_eyepatch_extern_crate.rs
@@ -0,0 +1,37 @@
+#![feature(dropck_eyepatch)]
+
+// This is a support file for ../dropck-eyepatch-extern-crate.rs
+//
+// The point of this test is to illustrate that the `#[may_dangle]`
+// attribute specifically allows, in the context of a type
+// implementing `Drop`, a generic parameter to be instantiated with a
+// lifetime that does not strictly outlive the owning type itself,
+// and that this attribute's effects are preserved when importing
+// the type from another crate.
+//
+// See also ../dropck-eyepatch.rs for more information about the general
+// structure of the test.
+
+use std::fmt;
+
+pub struct Dt<A: fmt::Debug>(pub &'static str, pub A);
+pub struct Dr<'a, B:'a+fmt::Debug>(pub &'static str, pub &'a B);
+pub struct Pt<A,B: fmt::Debug>(pub &'static str, pub A, pub B);
+pub struct Pr<'a, 'b, B:'a+'b+fmt::Debug>(pub &'static str, pub &'a B, pub &'b B);
+pub struct St<A: fmt::Debug>(pub &'static str, pub A);
+pub struct Sr<'a, B:'a+fmt::Debug>(pub &'static str, pub &'a B);
+
+impl<A: fmt::Debug> Drop for Dt<A> {
+    fn drop(&mut self) { println!("drop {} {:?}", self.0, self.1); }
+}
+impl<'a, B: fmt::Debug> Drop for Dr<'a, B> {
+    fn drop(&mut self) { println!("drop {} {:?}", self.0, self.1); }
+}
+unsafe impl<#[may_dangle] A, B: fmt::Debug> Drop for Pt<A, B> {
+    // (unsafe to access self.1  due to #[may_dangle] on A)
+    fn drop(&mut self) { println!("drop {} {:?}", self.0, self.2); }
+}
+unsafe impl<#[may_dangle] 'a, 'b, B: fmt::Debug> Drop for Pr<'a, 'b, B> {
+    // (unsafe to access self.1 due to #[may_dangle] on 'a)
+    fn drop(&mut self) { println!("drop {} {:?}", self.0, self.2); }
+}
diff --git a/src/test/ui/dropck/drop-on-non-struct.rs b/src/test/ui/dropck/drop-on-non-struct.rs
new file mode 100644
index 0000000..259cdf4
--- /dev/null
+++ b/src/test/ui/dropck/drop-on-non-struct.rs
@@ -0,0 +1,10 @@
+impl<'a> Drop for &'a mut isize {
+    //~^ ERROR the Drop trait may only be implemented on structures
+    //~^^ ERROR E0117
+    fn drop(&mut self) {
+        println!("kaboom");
+    }
+}
+
+fn main() {
+}
diff --git a/src/test/ui/dropck/drop-on-non-struct.stderr b/src/test/ui/dropck/drop-on-non-struct.stderr
new file mode 100644
index 0000000..6b670d5
--- /dev/null
+++ b/src/test/ui/dropck/drop-on-non-struct.stderr
@@ -0,0 +1,19 @@
+error[E0120]: the Drop trait may only be implemented on structures
+  --> $DIR/drop-on-non-struct.rs:1:19
+   |
+LL | impl<'a> Drop for &'a mut isize {
+   |                   ^^^^^^^^^^^^^ implementing Drop requires a struct
+
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/drop-on-non-struct.rs:1:1
+   |
+LL | impl<'a> Drop for &'a mut isize {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0117, E0120.
+For more information about an error, try `rustc --explain E0117`.
diff --git a/src/test/ui/dropck/drop-with-active-borrows-1.nll.stderr b/src/test/ui/dropck/drop-with-active-borrows-1.nll.stderr
new file mode 100644
index 0000000..7fed27a
--- /dev/null
+++ b/src/test/ui/dropck/drop-with-active-borrows-1.nll.stderr
@@ -0,0 +1,13 @@
+error[E0505]: cannot move out of `a` because it is borrowed
+  --> $DIR/drop-with-active-borrows-1.rs:4:10
+   |
+LL |     let b: Vec<&str> = a.lines().collect();
+   |                        - borrow of `a` occurs here
+LL |     drop(a);
+   |          ^ move out of `a` occurs here
+LL |     for s in &b {
+   |              -- borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0505`.
diff --git a/src/test/ui/dropck/drop-with-active-borrows-1.rs b/src/test/ui/dropck/drop-with-active-borrows-1.rs
new file mode 100644
index 0000000..1e924af
--- /dev/null
+++ b/src/test/ui/dropck/drop-with-active-borrows-1.rs
@@ -0,0 +1,8 @@
+fn main() {
+    let a = "".to_string();
+    let b: Vec<&str> = a.lines().collect();
+    drop(a);    //~ ERROR cannot move out of `a` because it is borrowed
+    for s in &b {
+        println!("{}", *s);
+    }
+}
diff --git a/src/test/ui/dropck/drop-with-active-borrows-1.stderr b/src/test/ui/dropck/drop-with-active-borrows-1.stderr
new file mode 100644
index 0000000..71960fc
--- /dev/null
+++ b/src/test/ui/dropck/drop-with-active-borrows-1.stderr
@@ -0,0 +1,11 @@
+error[E0505]: cannot move out of `a` because it is borrowed
+  --> $DIR/drop-with-active-borrows-1.rs:4:10
+   |
+LL |     let b: Vec<&str> = a.lines().collect();
+   |                        - borrow of `a` occurs here
+LL |     drop(a);
+   |          ^ move out of `a` occurs here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0505`.
diff --git a/src/test/ui/dropck/drop-with-active-borrows-2.nll.stderr b/src/test/ui/dropck/drop-with-active-borrows-2.nll.stderr
new file mode 100644
index 0000000..ffec930
--- /dev/null
+++ b/src/test/ui/dropck/drop-with-active-borrows-2.nll.stderr
@@ -0,0 +1,12 @@
+error[E0515]: cannot return value referencing local variable `raw_lines`
+  --> $DIR/drop-with-active-borrows-2.rs:3:5
+   |
+LL |     raw_lines.iter().map(|l| l.trim()).collect()
+   |     ---------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     |
+   |     returns a value referencing data owned by the current function
+   |     `raw_lines` is borrowed here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/src/test/ui/dropck/drop-with-active-borrows-2.rs b/src/test/ui/dropck/drop-with-active-borrows-2.rs
new file mode 100644
index 0000000..4e45633
--- /dev/null
+++ b/src/test/ui/dropck/drop-with-active-borrows-2.rs
@@ -0,0 +1,9 @@
+fn read_lines_borrowed<'a>() -> Vec<&'a str> {
+    let raw_lines: Vec<String> = vec!["foo  ".to_string(), "  bar".to_string()];
+    raw_lines.iter().map(|l| l.trim()).collect()
+    //~^ ERROR `raw_lines` does not live long enough
+}
+
+fn main() {
+    println!("{:?}", read_lines_borrowed());
+}
diff --git a/src/test/ui/dropck/drop-with-active-borrows-2.stderr b/src/test/ui/dropck/drop-with-active-borrows-2.stderr
new file mode 100644
index 0000000..ef46c92
--- /dev/null
+++ b/src/test/ui/dropck/drop-with-active-borrows-2.stderr
@@ -0,0 +1,18 @@
+error[E0597]: `raw_lines` does not live long enough
+  --> $DIR/drop-with-active-borrows-2.rs:3:5
+   |
+LL |     raw_lines.iter().map(|l| l.trim()).collect()
+   |     ^^^^^^^^^ borrowed value does not live long enough
+LL |
+LL | }
+   | - borrowed value only lives until here
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 1:24...
+  --> $DIR/drop-with-active-borrows-2.rs:1:24
+   |
+LL | fn read_lines_borrowed<'a>() -> Vec<&'a str> {
+   |                        ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/dropck/dropck-eyepatch-extern-crate.ast.stderr b/src/test/ui/dropck/dropck-eyepatch-extern-crate.ast.stderr
new file mode 100644
index 0000000..31adb2f
--- /dev/null
+++ b/src/test/ui/dropck/dropck-eyepatch-extern-crate.ast.stderr
@@ -0,0 +1,69 @@
+error[E0597]: `c` does not live long enough
+  --> $DIR/dropck-eyepatch-extern-crate.rs:41:20
+   |
+LL |     dt = Dt("dt", &c);
+   |                    ^ borrowed value does not live long enough
+...
+LL | }
+   | - `c` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error[E0597]: `c` does not live long enough
+  --> $DIR/dropck-eyepatch-extern-crate.rs:43:20
+   |
+LL |     dr = Dr("dr", &c);
+   |                    ^ borrowed value does not live long enough
+...
+LL | }
+   | - `c` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error[E0597]: `c_shortest` does not live long enough
+  --> $DIR/dropck-eyepatch-extern-crate.rs:47:20
+   |
+LL |     dt = Dt("dt", &c_shortest);
+   |                    ^^^^^^^^^^ borrowed value does not live long enough
+...
+LL | }
+   | - `c_shortest` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error[E0597]: `c_shortest` does not live long enough
+  --> $DIR/dropck-eyepatch-extern-crate.rs:50:20
+   |
+LL |     dr = Dr("dr", &c_shortest);
+   |                    ^^^^^^^^^^ borrowed value does not live long enough
+...
+LL | }
+   | - `c_shortest` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error[E0597]: `c_shortest` does not live long enough
+  --> $DIR/dropck-eyepatch-extern-crate.rs:57:29
+   |
+LL |     pt = Pt("pt", &c_long, &c_shortest);
+   |                             ^^^^^^^^^^ borrowed value does not live long enough
+...
+LL | }
+   | - `c_shortest` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error[E0597]: `c_shortest` does not live long enough
+  --> $DIR/dropck-eyepatch-extern-crate.rs:59:29
+   |
+LL |     pr = Pr("pr", &c_long, &c_shortest);
+   |                             ^^^^^^^^^^ borrowed value does not live long enough
+...
+LL | }
+   | - `c_shortest` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/dropck/dropck-eyepatch-extern-crate.nll.stderr b/src/test/ui/dropck/dropck-eyepatch-extern-crate.nll.stderr
new file mode 100644
index 0000000..e0b7fc4
--- /dev/null
+++ b/src/test/ui/dropck/dropck-eyepatch-extern-crate.nll.stderr
@@ -0,0 +1,17 @@
+error[E0597]: `c_shortest` does not live long enough
+  --> $DIR/dropck-eyepatch-extern-crate.rs:47:19
+   |
+LL |     dt = Dt("dt", &c_shortest);
+   |                   ^^^^^^^^^^^ borrowed value does not live long enough
+...
+LL | }
+   | -
+   | |
+   | `c_shortest` dropped here while still borrowed
+   | borrow might be used here, when `dt` is dropped and runs the `Drop` code for type `other::Dt`
+   |
+   = note: values in a scope are dropped in the opposite order they are defined
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/dropck/dropck-eyepatch-extern-crate.rs b/src/test/ui/dropck/dropck-eyepatch-extern-crate.rs
new file mode 100644
index 0000000..6806563
--- /dev/null
+++ b/src/test/ui/dropck/dropck-eyepatch-extern-crate.rs
@@ -0,0 +1,70 @@
+// The behavior of AST-borrowck and NLL explcitly differ here due to
+// NLL's increased precision; so we use revisions and do not worry
+// about the --compare-mode=nll on this test.
+
+// revisions: ast nll
+//[ast]compile-flags: -Z borrowck=ast
+//[nll]compile-flags: -Z borrowck=migrate -Z two-phase-borrows
+
+// ignore-compare-mode-nll
+
+// aux-build:dropck_eyepatch_extern_crate.rs
+
+// The point of this test is to illustrate that the `#[may_dangle]`
+// attribute specifically allows, in the context of a type
+// implementing `Drop`, a generic parameter to be instantiated with a
+// lifetime that does not strictly outlive the owning type itself,
+// and that this attribute's effects are preserved when importing
+// the type from another crate.
+//
+// See also dropck-eyepatch.rs for more information about the general
+// structure of the test.
+#![feature(rustc_attrs)]
+extern crate dropck_eyepatch_extern_crate as other;
+
+use other::{Dt,Dr,Pt,Pr,St,Sr};
+
+fn main() { #![rustc_error] // rust-lang/rust#49855
+    use std::cell::Cell;
+    let c_long;
+    let (c, mut dt, mut dr, mut pt, mut pr, st, sr, c_shortest)
+        : (Cell<_>, Dt<_>, Dr<_>, Pt<_, _>, Pr<_>, St<_>, Sr<_>, Cell<_>);
+    c_long = Cell::new(1);
+    c = Cell::new(1);
+    c_shortest = Cell::new(1);
+
+    // No error: sufficiently long-lived state can be referenced in dtors
+    dt = Dt("dt", &c_long);
+    dr = Dr("dr", &c_long);
+
+    // Error: destructor order imprecisely modelled
+    dt = Dt("dt", &c);
+    //[ast]~^ ERROR `c` does not live long enough
+    dr = Dr("dr", &c);
+    //[ast]~^ ERROR `c` does not live long enough
+
+    // Error: `c_shortest` dies too soon for the references in dtors to be valid.
+    dt = Dt("dt", &c_shortest);
+    //[ast]~^ ERROR `c_shortest` does not live long enough
+    //[nll]~^^ ERROR `c_shortest` does not live long enough
+    dr = Dr("dr", &c_shortest);
+    //[ast]~^ ERROR `c_shortest` does not live long enough
+    // No error: Drop impl asserts .1 (A and &'a _) are not accessed
+    pt = Pt("pt", &c_shortest, &c_long);
+    pr = Pr("pr", &c_shortest, &c_long);
+
+    // Error: Drop impl's assertion does not apply to `B` nor `&'b _`
+    pt = Pt("pt", &c_long, &c_shortest);
+    //[ast]~^ ERROR `c_shortest` does not live long enough
+    pr = Pr("pr", &c_long, &c_shortest);
+    //[ast]~^ ERROR `c_shortest` does not live long enough
+
+    // No error: St and Sr have no destructor.
+    st = St("st", &c_shortest);
+    sr = Sr("sr", &c_shortest);
+
+    println!("{:?}", (dt.0, dr.0, pt.0, pr.0, st.0, sr.0));
+    use_imm(sr.1); use_imm(st.1); use_imm(pr.1); use_imm(pt.1); use_imm(dr.1); use_imm(dt.1);
+}
+
+fn use_imm<T>(_: &T) { }
diff --git a/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.rs b/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.rs
new file mode 100644
index 0000000..6869ab1
--- /dev/null
+++ b/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.rs
@@ -0,0 +1,35 @@
+#![feature(dropck_eyepatch)]
+
+// This test ensures that a use of `#[may_dangle]` is rejected if
+// it is not attached to an `unsafe impl`.
+
+use std::fmt;
+
+struct Dt<A: fmt::Debug>(&'static str, A);
+struct Dr<'a, B:'a+fmt::Debug>(&'static str, &'a B);
+struct Pt<A,B: fmt::Debug>(&'static str, A, B);
+struct Pr<'a, 'b, B:'a+'b+fmt::Debug>(&'static str, &'a B, &'b B);
+struct St<A: fmt::Debug>(&'static str, A);
+struct Sr<'a, B:'a+fmt::Debug>(&'static str, &'a B);
+
+impl<A: fmt::Debug> Drop for Dt<A> {
+    fn drop(&mut self) { println!("drop {} {:?}", self.0, self.1); }
+}
+impl<'a, B: fmt::Debug> Drop for Dr<'a, B> {
+    fn drop(&mut self) { println!("drop {} {:?}", self.0, self.1); }
+}
+impl<#[may_dangle] A, B: fmt::Debug> Drop for Pt<A, B> {
+    //~^ ERROR requires an `unsafe impl` declaration due to `#[may_dangle]` attribute
+
+    // (unsafe to access self.1  due to #[may_dangle] on A)
+    fn drop(&mut self) { println!("drop {} {:?}", self.0, self.2); }
+}
+impl<#[may_dangle] 'a, 'b, B: fmt::Debug> Drop for Pr<'a, 'b, B> {
+    //~^ ERROR requires an `unsafe impl` declaration due to `#[may_dangle]` attribute
+
+    // (unsafe to access self.1 due to #[may_dangle] on 'a)
+    fn drop(&mut self) { println!("drop {} {:?}", self.0, self.2); }
+}
+
+fn main() {
+}
diff --git a/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr b/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr
new file mode 100644
index 0000000..49e55be
--- /dev/null
+++ b/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr
@@ -0,0 +1,25 @@
+error[E0569]: requires an `unsafe impl` declaration due to `#[may_dangle]` attribute
+  --> $DIR/dropck-eyepatch-implies-unsafe-impl.rs:21:1
+   |
+LL | / impl<#[may_dangle] A, B: fmt::Debug> Drop for Pt<A, B> {
+LL | |
+LL | |
+LL | |     // (unsafe to access self.1  due to #[may_dangle] on A)
+LL | |     fn drop(&mut self) { println!("drop {} {:?}", self.0, self.2); }
+LL | | }
+   | |_^
+
+error[E0569]: requires an `unsafe impl` declaration due to `#[may_dangle]` attribute
+  --> $DIR/dropck-eyepatch-implies-unsafe-impl.rs:27:1
+   |
+LL | / impl<#[may_dangle] 'a, 'b, B: fmt::Debug> Drop for Pr<'a, 'b, B> {
+LL | |
+LL | |
+LL | |     // (unsafe to access self.1 due to #[may_dangle] on 'a)
+LL | |     fn drop(&mut self) { println!("drop {} {:?}", self.0, self.2); }
+LL | | }
+   | |_^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0569`.
diff --git a/src/test/ui/dropck/dropck-eyepatch-reorder.ast.stderr b/src/test/ui/dropck/dropck-eyepatch-reorder.ast.stderr
new file mode 100644
index 0000000..ddd47e9
--- /dev/null
+++ b/src/test/ui/dropck/dropck-eyepatch-reorder.ast.stderr
@@ -0,0 +1,69 @@
+error[E0597]: `c` does not live long enough
+  --> $DIR/dropck-eyepatch-reorder.rs:58:20
+   |
+LL |     dt = Dt("dt", &c);
+   |                    ^ borrowed value does not live long enough
+...
+LL | }
+   | - `c` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error[E0597]: `c` does not live long enough
+  --> $DIR/dropck-eyepatch-reorder.rs:60:20
+   |
+LL |     dr = Dr("dr", &c);
+   |                    ^ borrowed value does not live long enough
+...
+LL | }
+   | - `c` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error[E0597]: `c_shortest` does not live long enough
+  --> $DIR/dropck-eyepatch-reorder.rs:64:20
+   |
+LL |     dt = Dt("dt", &c_shortest);
+   |                    ^^^^^^^^^^ borrowed value does not live long enough
+...
+LL | }
+   | - `c_shortest` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error[E0597]: `c_shortest` does not live long enough
+  --> $DIR/dropck-eyepatch-reorder.rs:67:20
+   |
+LL |     dr = Dr("dr", &c_shortest);
+   |                    ^^^^^^^^^^ borrowed value does not live long enough
+...
+LL | }
+   | - `c_shortest` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error[E0597]: `c_shortest` does not live long enough
+  --> $DIR/dropck-eyepatch-reorder.rs:74:29
+   |
+LL |     pt = Pt("pt", &c_long, &c_shortest);
+   |                             ^^^^^^^^^^ borrowed value does not live long enough
+...
+LL | }
+   | - `c_shortest` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error[E0597]: `c_shortest` does not live long enough
+  --> $DIR/dropck-eyepatch-reorder.rs:76:29
+   |
+LL |     pr = Pr("pr", &c_long, &c_shortest);
+   |                             ^^^^^^^^^^ borrowed value does not live long enough
+...
+LL | }
+   | - `c_shortest` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/dropck/dropck-eyepatch-reorder.nll.stderr b/src/test/ui/dropck/dropck-eyepatch-reorder.nll.stderr
new file mode 100644
index 0000000..97c1caa
--- /dev/null
+++ b/src/test/ui/dropck/dropck-eyepatch-reorder.nll.stderr
@@ -0,0 +1,17 @@
+error[E0597]: `c_shortest` does not live long enough
+  --> $DIR/dropck-eyepatch-reorder.rs:64:19
+   |
+LL |     dt = Dt("dt", &c_shortest);
+   |                   ^^^^^^^^^^^ borrowed value does not live long enough
+...
+LL | }
+   | -
+   | |
+   | `c_shortest` dropped here while still borrowed
+   | borrow might be used here, when `dt` is dropped and runs the `Drop` code for type `Dt`
+   |
+   = note: values in a scope are dropped in the opposite order they are defined
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/dropck/dropck-eyepatch-reorder.rs b/src/test/ui/dropck/dropck-eyepatch-reorder.rs
new file mode 100644
index 0000000..16aaa26
--- /dev/null
+++ b/src/test/ui/dropck/dropck-eyepatch-reorder.rs
@@ -0,0 +1,87 @@
+// The behavior of AST-borrowck and NLL explcitly differ here due to
+// NLL's increased precision; so we use revisions and do not worry
+// about the --compare-mode=nll on this test.
+
+// revisions: ast nll
+//[ast]compile-flags: -Z borrowck=ast
+//[nll]compile-flags: -Z borrowck=migrate -Z two-phase-borrows
+
+// ignore-compare-mode-nll
+
+#![feature(dropck_eyepatch, rustc_attrs)]
+
+// The point of this test is to test uses of `#[may_dangle]` attribute
+// where the formal declaration order (in the impl generics) does not
+// match the actual usage order (in the type instantiation).
+//
+// See also dropck-eyepatch.rs for more information about the general
+// structure of the test.
+
+use std::fmt;
+
+struct Dt<A: fmt::Debug>(&'static str, A);
+struct Dr<'a, B:'a+fmt::Debug>(&'static str, &'a B);
+struct Pt<A: fmt::Debug, B: fmt::Debug>(&'static str, A, B);
+struct Pr<'a, 'b, B:'a+'b+fmt::Debug>(&'static str, &'a B, &'b B);
+struct St<A: fmt::Debug>(&'static str, A);
+struct Sr<'a, B:'a+fmt::Debug>(&'static str, &'a B);
+
+impl<A: fmt::Debug> Drop for Dt<A> {
+    fn drop(&mut self) { println!("drop {} {:?}", self.0, self.1); }
+}
+impl<'a, B: fmt::Debug> Drop for Dr<'a, B> {
+    fn drop(&mut self) { println!("drop {} {:?}", self.0, self.1); }
+}
+unsafe impl<B: fmt::Debug, #[may_dangle] A: fmt::Debug> Drop for Pt<A, B> {
+    // (unsafe to access self.1  due to #[may_dangle] on A)
+    fn drop(&mut self) { println!("drop {} {:?}", self.0, self.2); }
+}
+unsafe impl<'b, #[may_dangle] 'a, B: fmt::Debug> Drop for Pr<'a, 'b, B> {
+    // (unsafe to access self.1 due to #[may_dangle] on 'a)
+    fn drop(&mut self) { println!("drop {} {:?}", self.0, self.2); }
+}
+
+fn main() { #![rustc_error] // rust-lang/rust#49855
+    use std::cell::Cell;
+    let c_long;
+    let (c, mut dt, mut dr, mut pt, mut pr, st, sr, c_shortest)
+        : (Cell<_>, Dt<_>, Dr<_>, Pt<_, _>, Pr<_>, St<_>, Sr<_>, Cell<_>);
+    c_long = Cell::new(1);
+    c = Cell::new(1);
+    c_shortest = Cell::new(1);
+
+    // No error: sufficiently long-lived state can be referenced in dtors
+    dt = Dt("dt", &c_long);
+    dr = Dr("dr", &c_long);
+
+    // Error: destructor order imprecisely modelled
+    dt = Dt("dt", &c);
+    //[ast]~^ ERROR `c` does not live long enough
+    dr = Dr("dr", &c);
+    //[ast]~^ ERROR `c` does not live long enough
+
+    // Error: `c_shortest` dies too soon for the references in dtors to be valid.
+    dt = Dt("dt", &c_shortest);
+    //[ast]~^ ERROR `c_shortest` does not live long enough
+    //[nll]~^^ ERROR `c_shortest` does not live long enough
+    dr = Dr("dr", &c_shortest);
+    //[ast]~^ ERROR `c_shortest` does not live long enough
+    // No error: Drop impl asserts .1 (A and &'a _) are not accessed
+    pt = Pt("pt", &c_shortest, &c_long);
+    pr = Pr("pr", &c_shortest, &c_long);
+
+    // Error: Drop impl's assertion does not apply to `B` nor `&'b _`
+    pt = Pt("pt", &c_long, &c_shortest);
+    //[ast]~^ ERROR `c_shortest` does not live long enough
+    pr = Pr("pr", &c_long, &c_shortest);
+    //[ast]~^ ERROR `c_shortest` does not live long enough
+
+    // No error: St and Sr have no destructor.
+    st = St("st", &c_shortest);
+    sr = Sr("sr", &c_shortest);
+
+    println!("{:?}", (dt.0, dr.0, pt.0, pr.0, st.0, sr.0));
+    use_imm(sr.1); use_imm(st.1); use_imm(pr.1); use_imm(pt.1); use_imm(dr.1); use_imm(dt.1);
+}
+
+fn use_imm<T>(_: &T) { }
diff --git a/src/test/ui/dropck/dropck-eyepatch.ast.stderr b/src/test/ui/dropck/dropck-eyepatch.ast.stderr
new file mode 100644
index 0000000..0952ed0
--- /dev/null
+++ b/src/test/ui/dropck/dropck-eyepatch.ast.stderr
@@ -0,0 +1,69 @@
+error[E0597]: `c` does not live long enough
+  --> $DIR/dropck-eyepatch.rs:81:20
+   |
+LL |     dt = Dt("dt", &c);
+   |                    ^ borrowed value does not live long enough
+...
+LL | }
+   | - `c` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error[E0597]: `c` does not live long enough
+  --> $DIR/dropck-eyepatch.rs:83:20
+   |
+LL |     dr = Dr("dr", &c);
+   |                    ^ borrowed value does not live long enough
+...
+LL | }
+   | - `c` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error[E0597]: `c_shortest` does not live long enough
+  --> $DIR/dropck-eyepatch.rs:87:20
+   |
+LL |     dt = Dt("dt", &c_shortest);
+   |                    ^^^^^^^^^^ borrowed value does not live long enough
+...
+LL | }
+   | - `c_shortest` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error[E0597]: `c_shortest` does not live long enough
+  --> $DIR/dropck-eyepatch.rs:90:20
+   |
+LL |     dr = Dr("dr", &c_shortest);
+   |                    ^^^^^^^^^^ borrowed value does not live long enough
+...
+LL | }
+   | - `c_shortest` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error[E0597]: `c_shortest` does not live long enough
+  --> $DIR/dropck-eyepatch.rs:98:29
+   |
+LL |     pt = Pt("pt", &c_long, &c_shortest);
+   |                             ^^^^^^^^^^ borrowed value does not live long enough
+...
+LL | }
+   | - `c_shortest` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error[E0597]: `c_shortest` does not live long enough
+  --> $DIR/dropck-eyepatch.rs:100:29
+   |
+LL |     pr = Pr("pr", &c_long, &c_shortest);
+   |                             ^^^^^^^^^^ borrowed value does not live long enough
+...
+LL | }
+   | - `c_shortest` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/dropck/dropck-eyepatch.nll.stderr b/src/test/ui/dropck/dropck-eyepatch.nll.stderr
new file mode 100644
index 0000000..4a6e42e
--- /dev/null
+++ b/src/test/ui/dropck/dropck-eyepatch.nll.stderr
@@ -0,0 +1,17 @@
+error[E0597]: `c_shortest` does not live long enough
+  --> $DIR/dropck-eyepatch.rs:87:19
+   |
+LL |     dt = Dt("dt", &c_shortest);
+   |                   ^^^^^^^^^^^ borrowed value does not live long enough
+...
+LL | }
+   | -
+   | |
+   | `c_shortest` dropped here while still borrowed
+   | borrow might be used here, when `dt` is dropped and runs the `Drop` code for type `Dt`
+   |
+   = note: values in a scope are dropped in the opposite order they are defined
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/dropck/dropck-eyepatch.rs b/src/test/ui/dropck/dropck-eyepatch.rs
new file mode 100644
index 0000000..fb1c03b
--- /dev/null
+++ b/src/test/ui/dropck/dropck-eyepatch.rs
@@ -0,0 +1,111 @@
+// The behavior of AST-borrowck and NLL explcitly differ here due to
+// NLL's increased precision; so we use revisions and do not worry
+// about the --compare-mode=nll on this test.
+
+// revisions: ast nll
+//[ast]compile-flags: -Z borrowck=ast
+//[nll]compile-flags: -Z borrowck=migrate -Z two-phase-borrows
+
+// ignore-compare-mode-nll
+
+#![feature(dropck_eyepatch, rustc_attrs)]
+
+// The point of this test is to illustrate that the `#[may_dangle]`
+// attribute specifically allows, in the context of a type
+// implementing `Drop`, a generic parameter to be instantiated with a
+// lifetime that does not strictly outlive the owning type itself.
+//
+// Here we test that only the expected errors are issued.
+//
+// The illustration is made concrete by comparison with two variations
+// on the type with `#[may_dangle]`:
+//
+//   1. an analogous type that does not implement `Drop` (and thus
+//      should exhibit maximal flexibility with respect to dropck), and
+//
+//   2. an analogous type that does not use `#[may_dangle]` (and thus
+//      should exhibit the standard limitations imposed by dropck.
+//
+// The types in this file follow a pattern, {D,P,S}{t,r}, where:
+//
+// - D means "I implement Drop"
+//
+// - P means "I implement Drop but guarantee my (first) parameter is
+//     pure, i.e., not accessed from the destructor"; no other parameters
+//     are pure.
+//
+// - S means "I do not implement Drop"
+//
+// - t suffix is used when the first generic is a type
+//
+// - r suffix is used when the first generic is a lifetime.
+
+use std::fmt;
+
+struct Dt<A: fmt::Debug>(&'static str, A);
+struct Dr<'a, B:'a+fmt::Debug>(&'static str, &'a B);
+struct Pt<A,B: fmt::Debug>(&'static str, A, B);
+struct Pr<'a, 'b, B:'a+'b+fmt::Debug>(&'static str, &'a B, &'b B);
+struct St<A: fmt::Debug>(&'static str, A);
+struct Sr<'a, B:'a+fmt::Debug>(&'static str, &'a B);
+
+impl<A: fmt::Debug> Drop for Dt<A> {
+    fn drop(&mut self) { println!("drop {} {:?}", self.0, self.1); }
+}
+impl<'a, B: fmt::Debug> Drop for Dr<'a, B> {
+    fn drop(&mut self) { println!("drop {} {:?}", self.0, self.1); }
+}
+unsafe impl<#[may_dangle] A, B: fmt::Debug> Drop for Pt<A, B> {
+    // (unsafe to access self.1  due to #[may_dangle] on A)
+    fn drop(&mut self) { println!("drop {} {:?}", self.0, self.2); }
+}
+unsafe impl<#[may_dangle] 'a, 'b, B: fmt::Debug> Drop for Pr<'a, 'b, B> {
+    // (unsafe to access self.1 due to #[may_dangle] on 'a)
+    fn drop(&mut self) { println!("drop {} {:?}", self.0, self.2); }
+}
+
+fn main() { #![rustc_error] // rust-lang/rust#49855
+    use std::cell::Cell;
+    let c_long;
+    let (c, mut dt, mut dr, mut pt, mut pr, st, sr, c_shortest)
+        : (Cell<_>, Dt<_>, Dr<_>, Pt<_, _>, Pr<_>, St<_>, Sr<_>, Cell<_>);
+    c_long = Cell::new(1);
+    c = Cell::new(1);
+    c_shortest = Cell::new(1);
+
+    // No error: sufficiently long-lived state can be referenced in dtors
+    dt = Dt("dt", &c_long);
+    dr = Dr("dr", &c_long);
+
+    // Error: destructor order imprecisely modelled
+    dt = Dt("dt", &c);
+    //[ast]~^ ERROR `c` does not live long enough
+    dr = Dr("dr", &c);
+    //[ast]~^ ERROR `c` does not live long enough
+
+    // Error: `c_shortest` dies too soon for the references in dtors to be valid.
+    dt = Dt("dt", &c_shortest);
+    //[ast]~^ ERROR `c_shortest` does not live long enough
+    //[nll]~^^ ERROR `c_shortest` does not live long enough
+    dr = Dr("dr", &c_shortest);
+    //[ast]~^ ERROR `c_shortest` does not live long enough
+
+    // No error: Drop impl asserts .1 (A and &'a _) are not accessed
+    pt = Pt("pt", &c_shortest, &c_long);
+    pr = Pr("pr", &c_shortest, &c_long);
+
+    // Error: Drop impl's assertion does not apply to `B` nor `&'b _`
+    pt = Pt("pt", &c_long, &c_shortest);
+    //[ast]~^ ERROR `c_shortest` does not live long enough
+    pr = Pr("pr", &c_long, &c_shortest);
+    //[ast]~^ ERROR `c_shortest` does not live long enough
+
+    // No error: St and Sr have no destructor.
+    st = St("st", &c_shortest);
+    sr = Sr("sr", &c_shortest);
+
+    println!("{:?}", (dt.0, dr.0, pt.0, pr.0, st.0, sr.0));
+    use_imm(sr.1); use_imm(st.1); use_imm(pr.1); use_imm(pt.1); use_imm(dr.1); use_imm(dt.1);
+}
+
+fn use_imm<T>(_: &T) { }
diff --git a/src/test/ui/dropck/dropck-union.nll.stderr b/src/test/ui/dropck/dropck-union.nll.stderr
new file mode 100644
index 0000000..2287443
--- /dev/null
+++ b/src/test/ui/dropck/dropck-union.nll.stderr
@@ -0,0 +1,14 @@
+error[E0597]: `v` does not live long enough
+  --> $DIR/dropck-union.rs:39:18
+   |
+LL |     v.0.set(Some(&v));
+   |                  ^^ borrowed value does not live long enough
+LL | }
+   | -
+   | |
+   | `v` dropped here while still borrowed
+   | borrow might be used here, when `v` is dropped and runs the `Drop` code for type `Wrap`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/dropck/dropck-union.rs b/src/test/ui/dropck/dropck-union.rs
new file mode 100644
index 0000000..ef4d1b3
--- /dev/null
+++ b/src/test/ui/dropck/dropck-union.rs
@@ -0,0 +1,40 @@
+#![feature(untagged_unions)]
+
+use std::cell::Cell;
+use std::ops::Deref;
+use std::mem::ManuallyDrop;
+
+union Wrap<T> { x: ManuallyDrop<T> }
+
+impl<T> Drop for Wrap<T>  {
+    fn drop(&mut self) {
+        unsafe { std::ptr::drop_in_place(&mut *self.x as *mut T); }
+    }
+}
+
+impl<T> Wrap<T> {
+    fn new(x: T) -> Self {
+        Wrap { x: ManuallyDrop::new(x) }
+    }
+}
+
+impl<T> Deref for Wrap<T> {
+    type Target = T;
+    #[inline]
+    fn deref(&self) -> &Self::Target {
+        unsafe {
+            &self.x
+        }
+    }
+}
+
+struct C<'a>(Cell<Option<&'a C<'a>>>);
+
+impl<'a> Drop for C<'a> {
+    fn drop(&mut self) {}
+}
+
+fn main() {
+    let v : Wrap<C> = Wrap::new(C(Cell::new(None)));
+    v.0.set(Some(&v)); //~ ERROR: `v` does not live long enough
+}
diff --git a/src/test/ui/dropck/dropck-union.stderr b/src/test/ui/dropck/dropck-union.stderr
new file mode 100644
index 0000000..4f6cd87
--- /dev/null
+++ b/src/test/ui/dropck/dropck-union.stderr
@@ -0,0 +1,13 @@
+error[E0597]: `v` does not live long enough
+  --> $DIR/dropck-union.rs:39:19
+   |
+LL |     v.0.set(Some(&v));
+   |                   ^ borrowed value does not live long enough
+LL | }
+   | - `v` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/dropck/dropck_no_diverge_on_nonregular_1.rs b/src/test/ui/dropck/dropck_no_diverge_on_nonregular_1.rs
new file mode 100644
index 0000000..6ca5f5e
--- /dev/null
+++ b/src/test/ui/dropck/dropck_no_diverge_on_nonregular_1.rs
@@ -0,0 +1,27 @@
+// Issue 22443: Reject code using non-regular types that would
+// otherwise cause dropck to loop infinitely.
+
+use std::marker::PhantomData;
+
+struct Digit<T> {
+    elem: T
+}
+
+struct Node<T:'static> { m: PhantomData<&'static T> }
+
+
+enum FingerTree<T:'static> {
+    Single(T),
+    // Bug report said Digit after Box would stack overflow (versus
+    // Digit before Box; see dropck_no_diverge_on_nonregular_2).
+    Deep(
+        Box<FingerTree<Node<T>>>,
+        Digit<T>,
+        )
+}
+
+fn main() {
+    let ft = //~ ERROR overflow while adding drop-check rules for FingerTree
+        FingerTree::Single(1);
+    //~^ ERROR overflow while adding drop-check rules for FingerTree
+}
diff --git a/src/test/ui/dropck/dropck_no_diverge_on_nonregular_1.stderr b/src/test/ui/dropck/dropck_no_diverge_on_nonregular_1.stderr
new file mode 100644
index 0000000..9bf3244
--- /dev/null
+++ b/src/test/ui/dropck/dropck_no_diverge_on_nonregular_1.stderr
@@ -0,0 +1,19 @@
+error[E0320]: overflow while adding drop-check rules for FingerTree<i32>
+  --> $DIR/dropck_no_diverge_on_nonregular_1.rs:24:9
+   |
+LL |     let ft =
+   |         ^^
+   |
+   = note: overflowed on FingerTree<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<i32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+
+error[E0320]: overflow while adding drop-check rules for FingerTree<i32>
+  --> $DIR/dropck_no_diverge_on_nonregular_1.rs:25:9
+   |
+LL |         FingerTree::Single(1);
+   |         ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: overflowed on FingerTree<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<i32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0320`.
diff --git a/src/test/ui/dropck/dropck_no_diverge_on_nonregular_2.rs b/src/test/ui/dropck/dropck_no_diverge_on_nonregular_2.rs
new file mode 100644
index 0000000..d34f7e3
--- /dev/null
+++ b/src/test/ui/dropck/dropck_no_diverge_on_nonregular_2.rs
@@ -0,0 +1,26 @@
+// Issue 22443: Reject code using non-regular types that would
+// otherwise cause dropck to loop infinitely.
+
+use std::marker::PhantomData;
+
+struct Digit<T> {
+    elem: T
+}
+
+struct Node<T:'static> { m: PhantomData<&'static T> }
+
+enum FingerTree<T:'static> {
+    Single(T),
+    // Bug report said Digit before Box would infinite loop (versus
+    // Digit after Box; see dropck_no_diverge_on_nonregular_1).
+    Deep(
+        Digit<T>,
+        Box<FingerTree<Node<T>>>,
+        )
+}
+
+fn main() {
+    let ft = //~ ERROR overflow while adding drop-check rules for FingerTree
+        FingerTree::Single(1);
+    //~^ ERROR overflow while adding drop-check rules for FingerTree
+}
diff --git a/src/test/ui/dropck/dropck_no_diverge_on_nonregular_2.stderr b/src/test/ui/dropck/dropck_no_diverge_on_nonregular_2.stderr
new file mode 100644
index 0000000..0a74377
--- /dev/null
+++ b/src/test/ui/dropck/dropck_no_diverge_on_nonregular_2.stderr
@@ -0,0 +1,19 @@
+error[E0320]: overflow while adding drop-check rules for FingerTree<i32>
+  --> $DIR/dropck_no_diverge_on_nonregular_2.rs:23:9
+   |
+LL |     let ft =
+   |         ^^
+   |
+   = note: overflowed on FingerTree<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<i32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+
+error[E0320]: overflow while adding drop-check rules for FingerTree<i32>
+  --> $DIR/dropck_no_diverge_on_nonregular_2.rs:24:9
+   |
+LL |         FingerTree::Single(1);
+   |         ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: overflowed on FingerTree<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<i32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0320`.
diff --git a/src/test/ui/dropck/dropck_no_diverge_on_nonregular_3.rs b/src/test/ui/dropck/dropck_no_diverge_on_nonregular_3.rs
new file mode 100644
index 0000000..e2e600b
--- /dev/null
+++ b/src/test/ui/dropck/dropck_no_diverge_on_nonregular_3.rs
@@ -0,0 +1,36 @@
+// Issue 22443: Reject code using non-regular types that would
+// otherwise cause dropck to loop infinitely.
+//
+// This version is just checking that we still sanely handle a trivial
+// wrapper around the non-regular type. (It also demonstrates how the
+// error messages will report different types depending on which type
+// dropck is analyzing.)
+
+use std::marker::PhantomData;
+
+struct Digit<T> {
+    elem: T
+}
+
+struct Node<T:'static> { m: PhantomData<&'static T> }
+
+enum FingerTree<T:'static> {
+    Single(T),
+    // According to the bug report, Digit before Box would infinite loop.
+    Deep(
+        Digit<T>,
+        Box<FingerTree<Node<T>>>,
+        )
+}
+
+enum Wrapper<T:'static> {
+    Simple,
+    Other(FingerTree<T>),
+}
+
+fn main() {
+    let w = //~ ERROR overflow while adding drop-check rules for std::option
+        Some(Wrapper::Simple::<u32>);
+    //~^ ERROR overflow while adding drop-check rules for std::option::Option
+    //~| ERROR overflow while adding drop-check rules for Wrapper
+}
diff --git a/src/test/ui/dropck/dropck_no_diverge_on_nonregular_3.stderr b/src/test/ui/dropck/dropck_no_diverge_on_nonregular_3.stderr
new file mode 100644
index 0000000..d484e157
--- /dev/null
+++ b/src/test/ui/dropck/dropck_no_diverge_on_nonregular_3.stderr
@@ -0,0 +1,27 @@
+error[E0320]: overflow while adding drop-check rules for std::option::Option<Wrapper<u32>>
+  --> $DIR/dropck_no_diverge_on_nonregular_3.rs:32:9
+   |
+LL |     let w =
+   |         ^
+   |
+   = note: overflowed on FingerTree<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<u32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+
+error[E0320]: overflow while adding drop-check rules for std::option::Option<Wrapper<u32>>
+  --> $DIR/dropck_no_diverge_on_nonregular_3.rs:33:9
+   |
+LL |         Some(Wrapper::Simple::<u32>);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: overflowed on FingerTree<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<u32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+
+error[E0320]: overflow while adding drop-check rules for Wrapper<u32>
+  --> $DIR/dropck_no_diverge_on_nonregular_3.rs:33:14
+   |
+LL |         Some(Wrapper::Simple::<u32>);
+   |              ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: overflowed on FingerTree<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<u32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0320`.
diff --git a/src/test/ui/dropck/dropck_trait_cycle_checked.nll.stderr b/src/test/ui/dropck/dropck_trait_cycle_checked.nll.stderr
new file mode 100644
index 0000000..8c669b5
--- /dev/null
+++ b/src/test/ui/dropck/dropck_trait_cycle_checked.nll.stderr
@@ -0,0 +1,73 @@
+error[E0597]: `o2` does not live long enough
+  --> $DIR/dropck_trait_cycle_checked.rs:111:13
+   |
+LL |     let (o1, o2, o3): (Box<Obj>, Box<Obj>, Box<Obj>) = (O::new(), O::new(), O::new());
+   |                                                                   -------- cast requires that `o2` is borrowed for `'static`
+LL |     o1.set0(&o2);
+   |             ^^^ borrowed value does not live long enough
+...
+LL | }
+   | - `o2` dropped here while still borrowed
+
+error[E0597]: `o3` does not live long enough
+  --> $DIR/dropck_trait_cycle_checked.rs:112:13
+   |
+LL |     let (o1, o2, o3): (Box<Obj>, Box<Obj>, Box<Obj>) = (O::new(), O::new(), O::new());
+   |                                                                             -------- cast requires that `o3` is borrowed for `'static`
+LL |     o1.set0(&o2);
+LL |     o1.set1(&o3);
+   |             ^^^ borrowed value does not live long enough
+...
+LL | }
+   | - `o3` dropped here while still borrowed
+
+error[E0597]: `o2` does not live long enough
+  --> $DIR/dropck_trait_cycle_checked.rs:113:13
+   |
+LL |     let (o1, o2, o3): (Box<Obj>, Box<Obj>, Box<Obj>) = (O::new(), O::new(), O::new());
+   |                                                                   -------- cast requires that `o2` is borrowed for `'static`
+...
+LL |     o2.set0(&o2);
+   |             ^^^ borrowed value does not live long enough
+...
+LL | }
+   | - `o2` dropped here while still borrowed
+
+error[E0597]: `o3` does not live long enough
+  --> $DIR/dropck_trait_cycle_checked.rs:114:13
+   |
+LL |     let (o1, o2, o3): (Box<Obj>, Box<Obj>, Box<Obj>) = (O::new(), O::new(), O::new());
+   |                                                                             -------- cast requires that `o3` is borrowed for `'static`
+...
+LL |     o2.set1(&o3);
+   |             ^^^ borrowed value does not live long enough
+...
+LL | }
+   | - `o3` dropped here while still borrowed
+
+error[E0597]: `o1` does not live long enough
+  --> $DIR/dropck_trait_cycle_checked.rs:115:13
+   |
+LL |     let (o1, o2, o3): (Box<Obj>, Box<Obj>, Box<Obj>) = (O::new(), O::new(), O::new());
+   |                                                         -------- cast requires that `o1` is borrowed for `'static`
+...
+LL |     o3.set0(&o1);
+   |             ^^^ borrowed value does not live long enough
+LL |     o3.set1(&o2);
+LL | }
+   | - `o1` dropped here while still borrowed
+
+error[E0597]: `o2` does not live long enough
+  --> $DIR/dropck_trait_cycle_checked.rs:116:13
+   |
+LL |     let (o1, o2, o3): (Box<Obj>, Box<Obj>, Box<Obj>) = (O::new(), O::new(), O::new());
+   |                                                                   -------- cast requires that `o2` is borrowed for `'static`
+...
+LL |     o3.set1(&o2);
+   |             ^^^ borrowed value does not live long enough
+LL | }
+   | - `o2` dropped here while still borrowed
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/dropck/dropck_trait_cycle_checked.rs b/src/test/ui/dropck/dropck_trait_cycle_checked.rs
new file mode 100644
index 0000000..128bbb0
--- /dev/null
+++ b/src/test/ui/dropck/dropck_trait_cycle_checked.rs
@@ -0,0 +1,121 @@
+// Reject mixing cyclic structure and Drop when using trait
+// objects to hide the cross-references.
+//
+// (Compare against compile-fail/dropck_vec_cycle_checked.rs)
+
+use std::cell::Cell;
+use id::Id;
+
+mod s {
+    use std::sync::atomic::{AtomicUsize, Ordering};
+
+    static S_COUNT: AtomicUsize = AtomicUsize::new(0);
+
+    pub fn next_count() -> usize {
+        S_COUNT.fetch_add(1, Ordering::SeqCst) + 1
+    }
+}
+
+mod id {
+    use s;
+    #[derive(Debug)]
+    pub struct Id {
+        orig_count: usize,
+        count: usize,
+    }
+
+    impl Id {
+        pub fn new() -> Id {
+            let c = s::next_count();
+            println!("building Id {}", c);
+            Id { orig_count: c, count: c }
+        }
+        pub fn count(&self) -> usize {
+            println!("Id::count on {} returns {}", self.orig_count, self.count);
+            self.count
+        }
+    }
+
+    impl Drop for Id {
+        fn drop(&mut self) {
+            println!("dropping Id {}", self.count);
+            self.count = 0;
+        }
+    }
+}
+
+trait HasId {
+    fn count(&self) -> usize;
+}
+
+#[derive(Debug)]
+struct CheckId<T:HasId> {
+    v: T
+}
+
+#[allow(non_snake_case)]
+fn CheckId<T:HasId>(t: T) -> CheckId<T> { CheckId{ v: t } }
+
+impl<T:HasId> Drop for CheckId<T> {
+    fn drop(&mut self) {
+        assert!(self.v.count() > 0);
+    }
+}
+
+trait Obj<'a> : HasId {
+    fn set0(&self, b: &'a Box<Obj<'a>>);
+    fn set1(&self, b: &'a Box<Obj<'a>>);
+}
+
+struct O<'a> {
+    id: Id,
+    obj0: CheckId<Cell<Option<&'a Box<Obj<'a>>>>>,
+    obj1: CheckId<Cell<Option<&'a Box<Obj<'a>>>>>,
+}
+
+impl<'a> HasId for O<'a> {
+    fn count(&self) -> usize { self.id.count() }
+}
+
+impl<'a> O<'a> {
+    fn new() -> Box<O<'a>> {
+        Box::new(O {
+            id: Id::new(),
+            obj0: CheckId(Cell::new(None)),
+            obj1: CheckId(Cell::new(None)),
+        })
+    }
+}
+
+impl<'a> HasId for Cell<Option<&'a Box<Obj<'a>>>> {
+    fn count(&self) -> usize {
+        match self.get() {
+            None => 1,
+            Some(c) => c.count(),
+        }
+    }
+}
+
+impl<'a> Obj<'a> for O<'a> {
+    fn set0(&self, b: &'a Box<Obj<'a>>) {
+        self.obj0.v.set(Some(b))
+    }
+    fn set1(&self, b: &'a Box<Obj<'a>>) {
+        self.obj1.v.set(Some(b))
+    }
+}
+
+
+fn f() {
+    let (o1, o2, o3): (Box<Obj>, Box<Obj>, Box<Obj>) = (O::new(), O::new(), O::new());
+    o1.set0(&o2); //~ ERROR `o2` does not live long enough
+    o1.set1(&o3); //~ ERROR `o3` does not live long enough
+    o2.set0(&o2); //~ ERROR `o2` does not live long enough
+    o2.set1(&o3); //~ ERROR `o3` does not live long enough
+    o3.set0(&o1); //~ ERROR `o1` does not live long enough
+    o3.set1(&o2); //~ ERROR `o2` does not live long enough
+}
+
+fn main() {
+    f();
+}
diff --git a/src/test/ui/dropck/dropck_trait_cycle_checked.stderr b/src/test/ui/dropck/dropck_trait_cycle_checked.stderr
new file mode 100644
index 0000000..792ef46
--- /dev/null
+++ b/src/test/ui/dropck/dropck_trait_cycle_checked.stderr
@@ -0,0 +1,68 @@
+error[E0597]: `o2` does not live long enough
+  --> $DIR/dropck_trait_cycle_checked.rs:111:14
+   |
+LL |     o1.set0(&o2);
+   |              ^^ borrowed value does not live long enough
+...
+LL | }
+   | - borrowed value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: `o3` does not live long enough
+  --> $DIR/dropck_trait_cycle_checked.rs:112:14
+   |
+LL |     o1.set1(&o3);
+   |              ^^ borrowed value does not live long enough
+...
+LL | }
+   | - borrowed value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: `o2` does not live long enough
+  --> $DIR/dropck_trait_cycle_checked.rs:113:14
+   |
+LL |     o2.set0(&o2);
+   |              ^^ borrowed value does not live long enough
+...
+LL | }
+   | - borrowed value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: `o3` does not live long enough
+  --> $DIR/dropck_trait_cycle_checked.rs:114:14
+   |
+LL |     o2.set1(&o3);
+   |              ^^ borrowed value does not live long enough
+...
+LL | }
+   | - borrowed value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: `o1` does not live long enough
+  --> $DIR/dropck_trait_cycle_checked.rs:115:14
+   |
+LL |     o3.set0(&o1);
+   |              ^^ borrowed value does not live long enough
+LL |     o3.set1(&o2);
+LL | }
+   | - borrowed value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: `o2` does not live long enough
+  --> $DIR/dropck_trait_cycle_checked.rs:116:14
+   |
+LL |     o3.set1(&o2);
+   |              ^^ borrowed value does not live long enough
+LL | }
+   | - borrowed value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/dst/dst-bad-assign-2.rs b/src/test/ui/dst/dst-bad-assign-2.rs
new file mode 100644
index 0000000..b4f72d0
--- /dev/null
+++ b/src/test/ui/dst/dst-bad-assign-2.rs
@@ -0,0 +1,38 @@
+// Forbid assignment into a dynamically sized type.
+
+struct Fat<T: ?Sized> {
+    f1: isize,
+    f2: &'static str,
+    ptr: T
+}
+
+#[derive(PartialEq,Eq)]
+struct Bar;
+
+#[derive(PartialEq,Eq)]
+struct Bar1 {
+    f: isize
+}
+
+trait ToBar {
+    fn to_bar(&self) -> Bar;
+    fn to_val(&self) -> isize;
+}
+
+impl ToBar for Bar1 {
+    fn to_bar(&self) -> Bar {
+        Bar
+    }
+    fn to_val(&self) -> isize {
+        self.f
+    }
+}
+
+pub fn main() {
+    // Assignment.
+    let f5: &mut Fat<ToBar> = &mut Fat { f1: 5, f2: "some str", ptr: Bar1 {f :42} };
+    let z: Box<ToBar> = Box::new(Bar1 {f: 36});
+    f5.ptr = *z;
+    //~^ ERROR the size for values of type
+
+}
diff --git a/src/test/ui/dst/dst-bad-assign-2.stderr b/src/test/ui/dst/dst-bad-assign-2.stderr
new file mode 100644
index 0000000..4e1e67c
--- /dev/null
+++ b/src/test/ui/dst/dst-bad-assign-2.stderr
@@ -0,0 +1,13 @@
+error[E0277]: the size for values of type `dyn ToBar` cannot be known at compilation time
+  --> $DIR/dst-bad-assign-2.rs:35:5
+   |
+LL |     f5.ptr = *z;
+   |     ^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `dyn ToBar`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: the left-hand-side of an assignment must have a statically known size
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/dst/dst-bad-assign-3.rs b/src/test/ui/dst/dst-bad-assign-3.rs
new file mode 100644
index 0000000..5124abc
--- /dev/null
+++ b/src/test/ui/dst/dst-bad-assign-3.rs
@@ -0,0 +1,39 @@
+// Forbid assignment into a dynamically sized type.
+
+#![feature(unsized_tuple_coercion)]
+
+type Fat<T> = (isize, &'static str, T);
+
+#[derive(PartialEq,Eq)]
+struct Bar;
+
+#[derive(PartialEq,Eq)]
+struct Bar1 {
+    f: isize
+}
+
+trait ToBar {
+    fn to_bar(&self) -> Bar;
+    fn to_val(&self) -> isize;
+}
+
+impl ToBar for Bar1 {
+    fn to_bar(&self) -> Bar {
+        Bar
+    }
+    fn to_val(&self) -> isize {
+        self.f
+    }
+}
+
+pub fn main() {
+    // Assignment.
+    let f5: &mut Fat<ToBar> = &mut (5, "some str", Bar1 {f :42});
+    let z: Box<ToBar> = Box::new(Bar1 {f: 36});
+    f5.2 = Bar1 {f: 36};
+    //~^ ERROR mismatched types
+    //~| expected type `dyn ToBar`
+    //~| found type `Bar1`
+    //~| expected trait ToBar, found struct `Bar1`
+    //~| ERROR the size for values of type
+}
diff --git a/src/test/ui/dst/dst-bad-assign-3.stderr b/src/test/ui/dst/dst-bad-assign-3.stderr
new file mode 100644
index 0000000..0c4f866
--- /dev/null
+++ b/src/test/ui/dst/dst-bad-assign-3.stderr
@@ -0,0 +1,23 @@
+error[E0308]: mismatched types
+  --> $DIR/dst-bad-assign-3.rs:33:12
+   |
+LL |     f5.2 = Bar1 {f: 36};
+   |            ^^^^^^^^^^^^ expected trait ToBar, found struct `Bar1`
+   |
+   = note: expected type `dyn ToBar`
+              found type `Bar1`
+
+error[E0277]: the size for values of type `dyn ToBar` cannot be known at compilation time
+  --> $DIR/dst-bad-assign-3.rs:33:5
+   |
+LL |     f5.2 = Bar1 {f: 36};
+   |     ^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `dyn ToBar`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: the left-hand-side of an assignment must have a statically known size
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0277, E0308.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/dst/dst-bad-assign.rs b/src/test/ui/dst/dst-bad-assign.rs
new file mode 100644
index 0000000..003c80b
--- /dev/null
+++ b/src/test/ui/dst/dst-bad-assign.rs
@@ -0,0 +1,41 @@
+// Forbid assignment into a dynamically sized type.
+
+struct Fat<T: ?Sized> {
+    f1: isize,
+    f2: &'static str,
+    ptr: T
+}
+
+#[derive(PartialEq,Eq)]
+struct Bar;
+
+#[derive(PartialEq,Eq)]
+struct Bar1 {
+    f: isize
+}
+
+trait ToBar {
+    fn to_bar(&self) -> Bar;
+    fn to_val(&self) -> isize;
+}
+
+impl ToBar for Bar1 {
+    fn to_bar(&self) -> Bar {
+        Bar
+    }
+    fn to_val(&self) -> isize {
+        self.f
+    }
+}
+
+pub fn main() {
+    // Assignment.
+    let f5: &mut Fat<ToBar> = &mut Fat { f1: 5, f2: "some str", ptr: Bar1 {f :42} };
+    let z: Box<ToBar> = Box::new(Bar1 {f: 36});
+    f5.ptr = Bar1 {f: 36};
+    //~^ ERROR mismatched types
+    //~| expected type `dyn ToBar`
+    //~| found type `Bar1`
+    //~| expected trait ToBar, found struct `Bar1`
+    //~| ERROR the size for values of type
+}
diff --git a/src/test/ui/dst/dst-bad-assign.stderr b/src/test/ui/dst/dst-bad-assign.stderr
new file mode 100644
index 0000000..a60d9d6
--- /dev/null
+++ b/src/test/ui/dst/dst-bad-assign.stderr
@@ -0,0 +1,23 @@
+error[E0308]: mismatched types
+  --> $DIR/dst-bad-assign.rs:35:14
+   |
+LL |     f5.ptr = Bar1 {f: 36};
+   |              ^^^^^^^^^^^^ expected trait ToBar, found struct `Bar1`
+   |
+   = note: expected type `dyn ToBar`
+              found type `Bar1`
+
+error[E0277]: the size for values of type `dyn ToBar` cannot be known at compilation time
+  --> $DIR/dst-bad-assign.rs:35:5
+   |
+LL |     f5.ptr = Bar1 {f: 36};
+   |     ^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `dyn ToBar`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: the left-hand-side of an assignment must have a statically known size
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0277, E0308.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/dst/dst-bad-coerce1.rs b/src/test/ui/dst/dst-bad-coerce1.rs
new file mode 100644
index 0000000..8ca3423
--- /dev/null
+++ b/src/test/ui/dst/dst-bad-coerce1.rs
@@ -0,0 +1,36 @@
+// Attempt to change the type as well as unsizing.
+
+#![feature(unsized_tuple_coercion)]
+
+struct Fat<T: ?Sized> {
+    ptr: T
+}
+
+struct Foo;
+trait Bar { fn bar(&self) {} }
+
+pub fn main() {
+    // With a vec of isize.
+    let f1 = Fat { ptr: [1, 2, 3] };
+    let f2: &Fat<[isize; 3]> = &f1;
+    let f3: &Fat<[usize]> = f2;
+    //~^ ERROR mismatched types
+
+    // With a trait.
+    let f1 = Fat { ptr: Foo };
+    let f2: &Fat<Foo> = &f1;
+    let f3: &Fat<Bar> = f2;
+    //~^ ERROR `Foo: Bar` is not satisfied
+
+    // Tuple with a vec of isize.
+    let f1 = ([1, 2, 3],);
+    let f2: &([isize; 3],) = &f1;
+    let f3: &([usize],) = f2;
+    //~^ ERROR mismatched types
+
+    // Tuple with a trait.
+    let f1 = (Foo,);
+    let f2: &(Foo,) = &f1;
+    let f3: &(Bar,) = f2;
+    //~^ ERROR `Foo: Bar` is not satisfied
+}
diff --git a/src/test/ui/dst/dst-bad-coerce1.stderr b/src/test/ui/dst/dst-bad-coerce1.stderr
new file mode 100644
index 0000000..34b2d6d
--- /dev/null
+++ b/src/test/ui/dst/dst-bad-coerce1.stderr
@@ -0,0 +1,38 @@
+error[E0308]: mismatched types
+  --> $DIR/dst-bad-coerce1.rs:16:29
+   |
+LL |     let f3: &Fat<[usize]> = f2;
+   |                             ^^ expected slice, found array of 3 elements
+   |
+   = note: expected type `&Fat<[usize]>`
+              found type `&Fat<[isize; 3]>`
+
+error[E0277]: the trait bound `Foo: Bar` is not satisfied
+  --> $DIR/dst-bad-coerce1.rs:22:25
+   |
+LL |     let f3: &Fat<Bar> = f2;
+   |                         ^^ the trait `Bar` is not implemented for `Foo`
+   |
+   = note: required for the cast to the object type `dyn Bar`
+
+error[E0308]: mismatched types
+  --> $DIR/dst-bad-coerce1.rs:28:27
+   |
+LL |     let f3: &([usize],) = f2;
+   |                           ^^ expected slice, found array of 3 elements
+   |
+   = note: expected type `&([usize],)`
+              found type `&([isize; 3],)`
+
+error[E0277]: the trait bound `Foo: Bar` is not satisfied
+  --> $DIR/dst-bad-coerce1.rs:34:23
+   |
+LL |     let f3: &(Bar,) = f2;
+   |                       ^^ the trait `Bar` is not implemented for `Foo`
+   |
+   = note: required for the cast to the object type `dyn Bar`
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0277, E0308.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/dst/dst-bad-coerce2.rs b/src/test/ui/dst/dst-bad-coerce2.rs
new file mode 100644
index 0000000..2bc7ecc
--- /dev/null
+++ b/src/test/ui/dst/dst-bad-coerce2.rs
@@ -0,0 +1,31 @@
+// Attempt to change the mutability as well as unsizing.
+
+struct Fat<T: ?Sized> {
+    ptr: T
+}
+
+struct Foo;
+trait Bar {}
+impl Bar for Foo {}
+
+pub fn main() {
+    // With a vec of ints.
+    let f1 = Fat { ptr: [1, 2, 3] };
+    let f2: &Fat<[isize; 3]> = &f1;
+    let f3: &mut Fat<[isize]> = f2; //~ ERROR mismatched types
+
+    // With a trait.
+    let f1 = Fat { ptr: Foo };
+    let f2: &Fat<Foo> = &f1;
+    let f3: &mut Fat<Bar> = f2; //~ ERROR mismatched types
+
+    // Tuple with a vec of ints.
+    let f1 = ([1, 2, 3],);
+    let f2: &([isize; 3],) = &f1;
+    let f3: &mut ([isize],) = f2; //~ ERROR mismatched types
+
+    // Tuple with a trait.
+    let f1 = (Foo,);
+    let f2: &(Foo,) = &f1;
+    let f3: &mut (Bar,) = f2; //~ ERROR mismatched types
+}
diff --git a/src/test/ui/dst/dst-bad-coerce2.stderr b/src/test/ui/dst/dst-bad-coerce2.stderr
new file mode 100644
index 0000000..cae4ec5
--- /dev/null
+++ b/src/test/ui/dst/dst-bad-coerce2.stderr
@@ -0,0 +1,39 @@
+error[E0308]: mismatched types
+  --> $DIR/dst-bad-coerce2.rs:15:33
+   |
+LL |     let f3: &mut Fat<[isize]> = f2;
+   |                                 ^^ types differ in mutability
+   |
+   = note: expected type `&mut Fat<[isize]>`
+              found type `&Fat<[isize; 3]>`
+
+error[E0308]: mismatched types
+  --> $DIR/dst-bad-coerce2.rs:20:29
+   |
+LL |     let f3: &mut Fat<Bar> = f2;
+   |                             ^^ types differ in mutability
+   |
+   = note: expected type `&mut Fat<dyn Bar>`
+              found type `&Fat<Foo>`
+
+error[E0308]: mismatched types
+  --> $DIR/dst-bad-coerce2.rs:25:31
+   |
+LL |     let f3: &mut ([isize],) = f2;
+   |                               ^^ types differ in mutability
+   |
+   = note: expected type `&mut ([isize],)`
+              found type `&([isize; 3],)`
+
+error[E0308]: mismatched types
+  --> $DIR/dst-bad-coerce2.rs:30:27
+   |
+LL |     let f3: &mut (Bar,) = f2;
+   |                           ^^ types differ in mutability
+   |
+   = note: expected type `&mut (dyn Bar,)`
+              found type `&(Foo,)`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/dst/dst-bad-coerce3.nll.stderr b/src/test/ui/dst/dst-bad-coerce3.nll.stderr
new file mode 100644
index 0000000..289d451
--- /dev/null
+++ b/src/test/ui/dst/dst-bad-coerce3.nll.stderr
@@ -0,0 +1,58 @@
+error[E0597]: `f1` does not live long enough
+  --> $DIR/dst-bad-coerce3.rs:16:32
+   |
+LL | fn baz<'a>() {
+   |        -- lifetime `'a` defined here
+...
+LL |     let f2: &Fat<[isize; 3]> = &f1;
+   |                                ^^^ borrowed value does not live long enough
+LL |     let f3: &'a Fat<[isize]> = f2;
+   |             ---------------- type annotation requires that `f1` is borrowed for `'a`
+...
+LL | }
+   | - `f1` dropped here while still borrowed
+
+error[E0597]: `f1` does not live long enough
+  --> $DIR/dst-bad-coerce3.rs:21:25
+   |
+LL | fn baz<'a>() {
+   |        -- lifetime `'a` defined here
+...
+LL |     let f2: &Fat<Foo> = &f1;
+   |                         ^^^ borrowed value does not live long enough
+LL |     let f3: &'a Fat<Bar> = f2;
+   |             ------------ type annotation requires that `f1` is borrowed for `'a`
+...
+LL | }
+   | - `f1` dropped here while still borrowed
+
+error[E0597]: `f1` does not live long enough
+  --> $DIR/dst-bad-coerce3.rs:26:30
+   |
+LL | fn baz<'a>() {
+   |        -- lifetime `'a` defined here
+...
+LL |     let f2: &([isize; 3],) = &f1;
+   |                              ^^^ borrowed value does not live long enough
+LL |     let f3: &'a ([isize],) = f2;
+   |             -------------- type annotation requires that `f1` is borrowed for `'a`
+...
+LL | }
+   | - `f1` dropped here while still borrowed
+
+error[E0597]: `f1` does not live long enough
+  --> $DIR/dst-bad-coerce3.rs:31:23
+   |
+LL | fn baz<'a>() {
+   |        -- lifetime `'a` defined here
+...
+LL |     let f2: &(Foo,) = &f1;
+   |                       ^^^ borrowed value does not live long enough
+LL |     let f3: &'a (Bar,) = f2;
+   |             ---------- type annotation requires that `f1` is borrowed for `'a`
+LL | }
+   | - `f1` dropped here while still borrowed
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/dst/dst-bad-coerce3.rs b/src/test/ui/dst/dst-bad-coerce3.rs
new file mode 100644
index 0000000..58c9885
--- /dev/null
+++ b/src/test/ui/dst/dst-bad-coerce3.rs
@@ -0,0 +1,37 @@
+// Attempt to extend the lifetime as well as unsizing.
+
+#![feature(unsized_tuple_coercion)]
+
+struct Fat<T: ?Sized> {
+    ptr: T
+}
+
+struct Foo;
+trait Bar { fn bar(&self) {} }
+impl Bar for Foo {}
+
+fn baz<'a>() {
+    // With a vec of ints.
+    let f1 = Fat { ptr: [1, 2, 3] };
+    let f2: &Fat<[isize; 3]> = &f1; //~ ERROR `f1` does not live long enough
+    let f3: &'a Fat<[isize]> = f2;
+
+    // With a trait.
+    let f1 = Fat { ptr: Foo };
+    let f2: &Fat<Foo> = &f1; //~ ERROR `f1` does not live long enough
+    let f3: &'a Fat<Bar> = f2;
+
+    // Tuple with a vec of ints.
+    let f1 = ([1, 2, 3],);
+    let f2: &([isize; 3],) = &f1; //~ ERROR `f1` does not live long enough
+    let f3: &'a ([isize],) = f2;
+
+    // Tuple with a trait.
+    let f1 = (Foo,);
+    let f2: &(Foo,) = &f1; //~ ERROR `f1` does not live long enough
+    let f3: &'a (Bar,) = f2;
+}
+
+pub fn main() {
+    baz();
+}
diff --git a/src/test/ui/dst/dst-bad-coerce3.stderr b/src/test/ui/dst/dst-bad-coerce3.stderr
new file mode 100644
index 0000000..6147326
--- /dev/null
+++ b/src/test/ui/dst/dst-bad-coerce3.stderr
@@ -0,0 +1,63 @@
+error[E0597]: `f1` does not live long enough
+  --> $DIR/dst-bad-coerce3.rs:16:33
+   |
+LL |     let f2: &Fat<[isize; 3]> = &f1;
+   |                                 ^^ borrowed value does not live long enough
+...
+LL | }
+   | - borrowed value only lives until here
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 13:8...
+  --> $DIR/dst-bad-coerce3.rs:13:8
+   |
+LL | fn baz<'a>() {
+   |        ^^
+
+error[E0597]: `f1` does not live long enough
+  --> $DIR/dst-bad-coerce3.rs:21:26
+   |
+LL |     let f2: &Fat<Foo> = &f1;
+   |                          ^^ borrowed value does not live long enough
+...
+LL | }
+   | - borrowed value only lives until here
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 13:8...
+  --> $DIR/dst-bad-coerce3.rs:13:8
+   |
+LL | fn baz<'a>() {
+   |        ^^
+
+error[E0597]: `f1` does not live long enough
+  --> $DIR/dst-bad-coerce3.rs:26:31
+   |
+LL |     let f2: &([isize; 3],) = &f1;
+   |                               ^^ borrowed value does not live long enough
+...
+LL | }
+   | - borrowed value only lives until here
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 13:8...
+  --> $DIR/dst-bad-coerce3.rs:13:8
+   |
+LL | fn baz<'a>() {
+   |        ^^
+
+error[E0597]: `f1` does not live long enough
+  --> $DIR/dst-bad-coerce3.rs:31:24
+   |
+LL |     let f2: &(Foo,) = &f1;
+   |                        ^^ borrowed value does not live long enough
+LL |     let f3: &'a (Bar,) = f2;
+LL | }
+   | - borrowed value only lives until here
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 13:8...
+  --> $DIR/dst-bad-coerce3.rs:13:8
+   |
+LL | fn baz<'a>() {
+   |        ^^
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/dst/dst-bad-coerce4.rs b/src/test/ui/dst/dst-bad-coerce4.rs
new file mode 100644
index 0000000..9635e1e
--- /dev/null
+++ b/src/test/ui/dst/dst-bad-coerce4.rs
@@ -0,0 +1,25 @@
+// Attempt to coerce from unsized to sized.
+
+#![feature(unsized_tuple_coercion)]
+
+struct Fat<T: ?Sized> {
+    ptr: T
+}
+
+pub fn main() {
+    // With a vec of isizes.
+    let f1: &Fat<[isize]> = &Fat { ptr: [1, 2, 3] };
+    let f2: &Fat<[isize; 3]> = f1;
+    //~^ ERROR mismatched types
+    //~| expected type `&Fat<[isize; 3]>`
+    //~| found type `&Fat<[isize]>`
+    //~| expected array of 3 elements, found slice
+
+    // Tuple with a vec of isizes.
+    let f1: &([isize],) = &([1, 2, 3],);
+    let f2: &([isize; 3],) = f1;
+    //~^ ERROR mismatched types
+    //~| expected type `&([isize; 3],)`
+    //~| found type `&([isize],)`
+    //~| expected array of 3 elements, found slice
+}
diff --git a/src/test/ui/dst/dst-bad-coerce4.stderr b/src/test/ui/dst/dst-bad-coerce4.stderr
new file mode 100644
index 0000000..fbf59ae
--- /dev/null
+++ b/src/test/ui/dst/dst-bad-coerce4.stderr
@@ -0,0 +1,21 @@
+error[E0308]: mismatched types
+  --> $DIR/dst-bad-coerce4.rs:12:32
+   |
+LL |     let f2: &Fat<[isize; 3]> = f1;
+   |                                ^^ expected array of 3 elements, found slice
+   |
+   = note: expected type `&Fat<[isize; 3]>`
+              found type `&Fat<[isize]>`
+
+error[E0308]: mismatched types
+  --> $DIR/dst-bad-coerce4.rs:20:30
+   |
+LL |     let f2: &([isize; 3],) = f1;
+   |                              ^^ expected array of 3 elements, found slice
+   |
+   = note: expected type `&([isize; 3],)`
+              found type `&([isize],)`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/dst/dst-bad-coercions.rs b/src/test/ui/dst/dst-bad-coercions.rs
new file mode 100644
index 0000000..9aa6972
--- /dev/null
+++ b/src/test/ui/dst/dst-bad-coercions.rs
@@ -0,0 +1,26 @@
+// Test implicit coercions involving DSTs and raw pointers.
+
+struct S;
+trait T {}
+impl T for S {}
+
+struct Foo<T: ?Sized> {
+    f: T
+}
+
+pub fn main() {
+    // Test that we cannot convert from *-ptr to &S and &T
+    let x: *const S = &S;
+    let y: &S = x; //~ ERROR mismatched types
+    let y: &T = x; //~ ERROR mismatched types
+
+    // Test that we cannot convert from *-ptr to &S and &T (mut version)
+    let x: *mut S = &mut S;
+    let y: &S = x; //~ ERROR mismatched types
+    let y: &T = x; //~ ERROR mismatched types
+
+    // Test that we cannot convert an immutable ptr to a mutable one using *-ptrs
+    let x: &mut T = &S; //~ ERROR mismatched types
+    let x: *mut T = &S; //~ ERROR mismatched types
+    let x: *mut S = &S; //~ ERROR mismatched types
+}
diff --git a/src/test/ui/dst/dst-bad-coercions.stderr b/src/test/ui/dst/dst-bad-coercions.stderr
new file mode 100644
index 0000000..2701682
--- /dev/null
+++ b/src/test/ui/dst/dst-bad-coercions.stderr
@@ -0,0 +1,72 @@
+error[E0308]: mismatched types
+  --> $DIR/dst-bad-coercions.rs:14:17
+   |
+LL |     let y: &S = x;
+   |                 ^ expected &S, found *-ptr
+   |
+   = note: expected type `&S`
+              found type `*const S`
+
+error[E0308]: mismatched types
+  --> $DIR/dst-bad-coercions.rs:15:17
+   |
+LL |     let y: &T = x;
+   |                 ^
+   |                 |
+   |                 expected &dyn T, found *-ptr
+   |                 help: consider borrowing here: `&x`
+   |
+   = note: expected type `&dyn T`
+              found type `*const S`
+
+error[E0308]: mismatched types
+  --> $DIR/dst-bad-coercions.rs:19:17
+   |
+LL |     let y: &S = x;
+   |                 ^ expected &S, found *-ptr
+   |
+   = note: expected type `&S`
+              found type `*mut S`
+
+error[E0308]: mismatched types
+  --> $DIR/dst-bad-coercions.rs:20:17
+   |
+LL |     let y: &T = x;
+   |                 ^
+   |                 |
+   |                 expected &dyn T, found *-ptr
+   |                 help: consider borrowing here: `&x`
+   |
+   = note: expected type `&dyn T`
+              found type `*mut S`
+
+error[E0308]: mismatched types
+  --> $DIR/dst-bad-coercions.rs:23:21
+   |
+LL |     let x: &mut T = &S;
+   |                     ^^ types differ in mutability
+   |
+   = note: expected type `&mut dyn T`
+              found type `&S`
+
+error[E0308]: mismatched types
+  --> $DIR/dst-bad-coercions.rs:24:21
+   |
+LL |     let x: *mut T = &S;
+   |                     ^^ types differ in mutability
+   |
+   = note: expected type `*mut dyn T`
+              found type `&S`
+
+error[E0308]: mismatched types
+  --> $DIR/dst-bad-coercions.rs:25:21
+   |
+LL |     let x: *mut S = &S;
+   |                     ^^ types differ in mutability
+   |
+   = note: expected type `*mut S`
+              found type `&S`
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/dst/dst-bad-deep-2.rs b/src/test/ui/dst/dst-bad-deep-2.rs
new file mode 100644
index 0000000..e587399
--- /dev/null
+++ b/src/test/ui/dst/dst-bad-deep-2.rs
@@ -0,0 +1,13 @@
+// Try to initialise a DST struct where the lost information is deeply nested.
+// This is an error because it requires an unsized rvalue. This is a problem
+// because it would require stack allocation of an unsized temporary (*g in the
+// test).
+
+#![feature(unsized_tuple_coercion)]
+
+pub fn main() {
+    let f: ([isize; 3],) = ([5, 6, 7],);
+    let g: &([isize],) = &f;
+    let h: &(([isize],),) = &(*g,);
+    //~^ ERROR the size for values of type
+}
diff --git a/src/test/ui/dst/dst-bad-deep-2.stderr b/src/test/ui/dst/dst-bad-deep-2.stderr
new file mode 100644
index 0000000..cb27351
--- /dev/null
+++ b/src/test/ui/dst/dst-bad-deep-2.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the size for values of type `[isize]` cannot be known at compilation time
+  --> $DIR/dst-bad-deep-2.rs:11:30
+   |
+LL |     let h: &(([isize],),) = &(*g,);
+   |                              ^^^^^ doesn't have a size known at compile-time
+   |
+   = help: within `(([isize],),)`, the trait `std::marker::Sized` is not implemented for `[isize]`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: required because it appears within the type `([isize],)`
+   = note: required because it appears within the type `(([isize],),)`
+   = note: tuples must have a statically known size to be initialized
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/dst/dst-bad-deep.rs b/src/test/ui/dst/dst-bad-deep.rs
new file mode 100644
index 0000000..a426729
--- /dev/null
+++ b/src/test/ui/dst/dst-bad-deep.rs
@@ -0,0 +1,15 @@
+// Try to initialise a DST struct where the lost information is deeply nested.
+// This is an error because it requires an unsized rvalue. This is a problem
+// because it would require stack allocation of an unsized temporary (*g in the
+// test).
+
+struct Fat<T: ?Sized> {
+    ptr: T
+}
+
+pub fn main() {
+    let f: Fat<[isize; 3]> = Fat { ptr: [5, 6, 7] };
+    let g: &Fat<[isize]> = &f;
+    let h: &Fat<Fat<[isize]>> = &Fat { ptr: *g };
+    //~^ ERROR the size for values of type
+}
diff --git a/src/test/ui/dst/dst-bad-deep.stderr b/src/test/ui/dst/dst-bad-deep.stderr
new file mode 100644
index 0000000..521adf6
--- /dev/null
+++ b/src/test/ui/dst/dst-bad-deep.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the size for values of type `[isize]` cannot be known at compilation time
+  --> $DIR/dst-bad-deep.rs:13:34
+   |
+LL |     let h: &Fat<Fat<[isize]>> = &Fat { ptr: *g };
+   |                                  ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: within `Fat<Fat<[isize]>>`, the trait `std::marker::Sized` is not implemented for `[isize]`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: required because it appears within the type `Fat<[isize]>`
+   = note: required because it appears within the type `Fat<Fat<[isize]>>`
+   = note: structs must have a statically known size to be initialized
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/dst/dst-index.nll.stderr b/src/test/ui/dst/dst-index.nll.stderr
new file mode 100644
index 0000000..92e3d2b
--- /dev/null
+++ b/src/test/ui/dst/dst-index.nll.stderr
@@ -0,0 +1,28 @@
+error[E0161]: cannot move a value of type str: the size of str cannot be statically determined
+  --> $DIR/dst-index.rs:31:5
+   |
+LL |     S[0];
+   |     ^^^^
+
+error[E0161]: cannot move a value of type dyn std::fmt::Debug: the size of dyn std::fmt::Debug cannot be statically determined
+  --> $DIR/dst-index.rs:34:5
+   |
+LL |     T[0];
+   |     ^^^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/dst-index.rs:31:5
+   |
+LL |     S[0];
+   |     ^^^^ cannot move out of borrowed content
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/dst-index.rs:34:5
+   |
+LL |     T[0];
+   |     ^^^^ cannot move out of borrowed content
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0161, E0507.
+For more information about an error, try `rustc --explain E0161`.
diff --git a/src/test/ui/dst/dst-index.rs b/src/test/ui/dst/dst-index.rs
new file mode 100644
index 0000000..663c704
--- /dev/null
+++ b/src/test/ui/dst/dst-index.rs
@@ -0,0 +1,37 @@
+// Test that overloaded index expressions with DST result types
+// can't be used as rvalues
+
+use std::ops::Index;
+use std::fmt::Debug;
+
+#[derive(Copy, Clone)]
+struct S;
+
+impl Index<usize> for S {
+    type Output = str;
+
+    fn index(&self, _: usize) -> &str {
+        "hello"
+    }
+}
+
+#[derive(Copy, Clone)]
+struct T;
+
+impl Index<usize> for T {
+    type Output = Debug + 'static;
+
+    fn index<'a>(&'a self, idx: usize) -> &'a (Debug + 'static) {
+        static x: usize = 42;
+        &x
+    }
+}
+
+fn main() {
+    S[0];
+    //~^ ERROR cannot move out of indexed content
+    //~^^ ERROR E0161
+    T[0];
+    //~^ ERROR cannot move out of indexed content
+    //~^^ ERROR E0161
+}
diff --git a/src/test/ui/dst/dst-index.stderr b/src/test/ui/dst/dst-index.stderr
new file mode 100644
index 0000000..05993f5
--- /dev/null
+++ b/src/test/ui/dst/dst-index.stderr
@@ -0,0 +1,28 @@
+error[E0161]: cannot move a value of type str: the size of str cannot be statically determined
+  --> $DIR/dst-index.rs:31:5
+   |
+LL |     S[0];
+   |     ^^^^
+
+error[E0161]: cannot move a value of type (dyn std::fmt::Debug + 'static): the size of (dyn std::fmt::Debug + 'static) cannot be statically determined
+  --> $DIR/dst-index.rs:34:5
+   |
+LL |     T[0];
+   |     ^^^^
+
+error[E0507]: cannot move out of indexed content
+  --> $DIR/dst-index.rs:31:5
+   |
+LL |     S[0];
+   |     ^^^^ cannot move out of indexed content
+
+error[E0507]: cannot move out of indexed content
+  --> $DIR/dst-index.rs:34:5
+   |
+LL |     T[0];
+   |     ^^^^ cannot move out of indexed content
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0161, E0507.
+For more information about an error, try `rustc --explain E0161`.
diff --git a/src/test/ui/dst/dst-object-from-unsized-type.rs b/src/test/ui/dst/dst-object-from-unsized-type.rs
new file mode 100644
index 0000000..f4ee178
--- /dev/null
+++ b/src/test/ui/dst/dst-object-from-unsized-type.rs
@@ -0,0 +1,27 @@
+// Test that we cannot create objects from unsized types.
+
+trait Foo { fn foo(&self) {} }
+impl Foo for str {}
+impl Foo for [u8] {}
+
+fn test1<T: ?Sized + Foo>(t: &T) {
+    let u: &Foo = t;
+    //~^ ERROR the size for values of type
+}
+
+fn test2<T: ?Sized + Foo>(t: &T) {
+    let v: &Foo = t as &Foo;
+    //~^ ERROR the size for values of type
+}
+
+fn test3() {
+    let _: &[&Foo] = &["hi"];
+    //~^ ERROR the size for values of type
+}
+
+fn test4(x: &[u8]) {
+    let _: &Foo = x as &Foo;
+    //~^ ERROR the size for values of type
+}
+
+fn main() { }
diff --git a/src/test/ui/dst/dst-object-from-unsized-type.stderr b/src/test/ui/dst/dst-object-from-unsized-type.stderr
new file mode 100644
index 0000000..4851ca1
--- /dev/null
+++ b/src/test/ui/dst/dst-object-from-unsized-type.stderr
@@ -0,0 +1,45 @@
+error[E0277]: the size for values of type `T` cannot be known at compilation time
+  --> $DIR/dst-object-from-unsized-type.rs:8:19
+   |
+LL |     let u: &Foo = t;
+   |                   ^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `T`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = help: consider adding a `where T: std::marker::Sized` bound
+   = note: required for the cast to the object type `dyn Foo`
+
+error[E0277]: the size for values of type `T` cannot be known at compilation time
+  --> $DIR/dst-object-from-unsized-type.rs:13:19
+   |
+LL |     let v: &Foo = t as &Foo;
+   |                   ^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `T`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = help: consider adding a `where T: std::marker::Sized` bound
+   = note: required for the cast to the object type `dyn Foo`
+
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+  --> $DIR/dst-object-from-unsized-type.rs:18:24
+   |
+LL |     let _: &[&Foo] = &["hi"];
+   |                        ^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `str`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: required for the cast to the object type `dyn Foo`
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/dst-object-from-unsized-type.rs:23:19
+   |
+LL |     let _: &Foo = x as &Foo;
+   |                   ^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `[u8]`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: required for the cast to the object type `dyn Foo`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/dst/dst-rvalue.nll.stderr b/src/test/ui/dst/dst-rvalue.nll.stderr
new file mode 100644
index 0000000..d0d8f79
--- /dev/null
+++ b/src/test/ui/dst/dst-rvalue.nll.stderr
@@ -0,0 +1,28 @@
+error[E0161]: cannot move a value of type str: the size of str cannot be statically determined
+  --> $DIR/dst-rvalue.rs:6:28
+   |
+LL |     let _x: Box<str> = box *"hello world";
+   |                            ^^^^^^^^^^^^^^
+
+error[E0161]: cannot move a value of type [isize]: the size of [isize] cannot be statically determined
+  --> $DIR/dst-rvalue.rs:11:32
+   |
+LL |     let _x: Box<[isize]> = box *array;
+   |                                ^^^^^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/dst-rvalue.rs:6:28
+   |
+LL |     let _x: Box<str> = box *"hello world";
+   |                            ^^^^^^^^^^^^^^ cannot move out of borrowed content
+
+error[E0508]: cannot move out of type `[isize]`, a non-copy slice
+  --> $DIR/dst-rvalue.rs:11:32
+   |
+LL |     let _x: Box<[isize]> = box *array;
+   |                                ^^^^^^ cannot move out of here
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0161, E0507, E0508.
+For more information about an error, try `rustc --explain E0161`.
diff --git a/src/test/ui/dst/dst-rvalue.rs b/src/test/ui/dst/dst-rvalue.rs
new file mode 100644
index 0000000..86747da
--- /dev/null
+++ b/src/test/ui/dst/dst-rvalue.rs
@@ -0,0 +1,14 @@
+// Check that dynamically sized rvalues are forbidden
+
+#![feature(box_syntax)]
+
+pub fn main() {
+    let _x: Box<str> = box *"hello world";
+    //~^ ERROR E0161
+    //~^^ ERROR cannot move out of borrowed content
+
+    let array: &[isize] = &[1, 2, 3];
+    let _x: Box<[isize]> = box *array;
+    //~^ ERROR E0161
+    //~^^ ERROR cannot move out of borrowed content
+}
diff --git a/src/test/ui/dst/dst-rvalue.stderr b/src/test/ui/dst/dst-rvalue.stderr
new file mode 100644
index 0000000..2c92f5d
--- /dev/null
+++ b/src/test/ui/dst/dst-rvalue.stderr
@@ -0,0 +1,28 @@
+error[E0161]: cannot move a value of type str: the size of str cannot be statically determined
+  --> $DIR/dst-rvalue.rs:6:28
+   |
+LL |     let _x: Box<str> = box *"hello world";
+   |                            ^^^^^^^^^^^^^^
+
+error[E0161]: cannot move a value of type [isize]: the size of [isize] cannot be statically determined
+  --> $DIR/dst-rvalue.rs:11:32
+   |
+LL |     let _x: Box<[isize]> = box *array;
+   |                                ^^^^^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/dst-rvalue.rs:6:28
+   |
+LL |     let _x: Box<str> = box *"hello world";
+   |                            ^^^^^^^^^^^^^^ cannot move out of borrowed content
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/dst-rvalue.rs:11:32
+   |
+LL |     let _x: Box<[isize]> = box *array;
+   |                                ^^^^^^ cannot move out of borrowed content
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0161, E0507.
+For more information about an error, try `rustc --explain E0161`.
diff --git a/src/test/ui/dst/dst-sized-trait-param.rs b/src/test/ui/dst/dst-sized-trait-param.rs
new file mode 100644
index 0000000..cfd5919
--- /dev/null
+++ b/src/test/ui/dst/dst-sized-trait-param.rs
@@ -0,0 +1,13 @@
+// Check that when you implement a trait that has a sized type
+// parameter, the corresponding value must be sized. Also that the
+// self type must be sized if appropriate.
+
+trait Foo<T> : Sized { fn take(self, x: &T) { } } // Note: T is sized
+
+impl Foo<[isize]> for usize { }
+//~^ ERROR the size for values of type
+
+impl Foo<isize> for [usize] { }
+//~^ ERROR the size for values of type
+
+pub fn main() { }
diff --git a/src/test/ui/dst/dst-sized-trait-param.stderr b/src/test/ui/dst/dst-sized-trait-param.stderr
new file mode 100644
index 0000000..40dc997
--- /dev/null
+++ b/src/test/ui/dst/dst-sized-trait-param.stderr
@@ -0,0 +1,21 @@
+error[E0277]: the size for values of type `[isize]` cannot be known at compilation time
+  --> $DIR/dst-sized-trait-param.rs:7:6
+   |
+LL | impl Foo<[isize]> for usize { }
+   |      ^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `[isize]`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+
+error[E0277]: the size for values of type `[usize]` cannot be known at compilation time
+  --> $DIR/dst-sized-trait-param.rs:10:6
+   |
+LL | impl Foo<isize> for [usize] { }
+   |      ^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `[usize]`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/duplicate/dupe-symbols-1.rs b/src/test/ui/duplicate/dupe-symbols-1.rs
new file mode 100644
index 0000000..f943c7b
--- /dev/null
+++ b/src/test/ui/duplicate/dupe-symbols-1.rs
@@ -0,0 +1,12 @@
+//
+#![crate_type="rlib"]
+#![allow(warnings)]
+
+#[export_name="fail"]
+pub fn a() {
+}
+
+#[export_name="fail"]
+pub fn b() {
+//~^ symbol `fail` is already defined
+}
diff --git a/src/test/ui/duplicate/dupe-symbols-1.stderr b/src/test/ui/duplicate/dupe-symbols-1.stderr
new file mode 100644
index 0000000..c46ac0c
--- /dev/null
+++ b/src/test/ui/duplicate/dupe-symbols-1.stderr
@@ -0,0 +1,10 @@
+error: symbol `fail` is already defined
+  --> $DIR/dupe-symbols-1.rs:10:1
+   |
+LL | / pub fn b() {
+LL | |
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/duplicate/dupe-symbols-2.rs b/src/test/ui/duplicate/dupe-symbols-2.rs
new file mode 100644
index 0000000..9257f97
--- /dev/null
+++ b/src/test/ui/duplicate/dupe-symbols-2.rs
@@ -0,0 +1,16 @@
+//
+#![crate_type="rlib"]
+#![allow(warnings)]
+
+pub mod a {
+    #[no_mangle]
+    pub extern fn fail() {
+    }
+}
+
+pub mod b {
+    #[no_mangle]
+    pub extern fn fail() {
+    //~^ symbol `fail` is already defined
+    }
+}
diff --git a/src/test/ui/duplicate/dupe-symbols-2.stderr b/src/test/ui/duplicate/dupe-symbols-2.stderr
new file mode 100644
index 0000000..821bdd0
--- /dev/null
+++ b/src/test/ui/duplicate/dupe-symbols-2.stderr
@@ -0,0 +1,10 @@
+error: symbol `fail` is already defined
+  --> $DIR/dupe-symbols-2.rs:13:5
+   |
+LL | /     pub extern fn fail() {
+LL | |
+LL | |     }
+   | |_____^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/duplicate/dupe-symbols-3.rs b/src/test/ui/duplicate/dupe-symbols-3.rs
new file mode 100644
index 0000000..03b3a0a
--- /dev/null
+++ b/src/test/ui/duplicate/dupe-symbols-3.rs
@@ -0,0 +1,12 @@
+//
+#![crate_type="rlib"]
+#![allow(warnings)]
+
+#[export_name="fail"]
+pub fn a() {
+}
+
+#[no_mangle]
+pub fn fail() {
+//~^ symbol `fail` is already defined
+}
diff --git a/src/test/ui/duplicate/dupe-symbols-3.stderr b/src/test/ui/duplicate/dupe-symbols-3.stderr
new file mode 100644
index 0000000..f30c88e
--- /dev/null
+++ b/src/test/ui/duplicate/dupe-symbols-3.stderr
@@ -0,0 +1,10 @@
+error: symbol `fail` is already defined
+  --> $DIR/dupe-symbols-3.rs:10:1
+   |
+LL | / pub fn fail() {
+LL | |
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/duplicate/dupe-symbols-4.rs b/src/test/ui/duplicate/dupe-symbols-4.rs
new file mode 100644
index 0000000..8fbf115
--- /dev/null
+++ b/src/test/ui/duplicate/dupe-symbols-4.rs
@@ -0,0 +1,22 @@
+//
+// error-pattern: symbol `fail` is already defined
+#![crate_type="rlib"]
+#![allow(warnings)]
+
+
+pub trait A {
+    fn fail(self);
+}
+
+struct B;
+struct C;
+
+impl A for B {
+    #[no_mangle]
+    fn fail(self) {}
+}
+
+impl A for C {
+    #[no_mangle]
+    fn fail(self) {}
+}
diff --git a/src/test/ui/duplicate/dupe-symbols-4.stderr b/src/test/ui/duplicate/dupe-symbols-4.stderr
new file mode 100644
index 0000000..84d5776
--- /dev/null
+++ b/src/test/ui/duplicate/dupe-symbols-4.stderr
@@ -0,0 +1,8 @@
+error: symbol `fail` is already defined
+  --> $DIR/dupe-symbols-4.rs:21:5
+   |
+LL |     fn fail(self) {}
+   |     ^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/duplicate/dupe-symbols-5.rs b/src/test/ui/duplicate/dupe-symbols-5.rs
new file mode 100644
index 0000000..4a96a68
--- /dev/null
+++ b/src/test/ui/duplicate/dupe-symbols-5.rs
@@ -0,0 +1,11 @@
+//
+#![crate_type="rlib"]
+#![allow(warnings)]
+
+#[export_name="fail"]
+static HELLO: u8 = 0;
+
+#[export_name="fail"]
+pub fn b() {
+//~^ symbol `fail` is already defined
+}
diff --git a/src/test/ui/duplicate/dupe-symbols-5.stderr b/src/test/ui/duplicate/dupe-symbols-5.stderr
new file mode 100644
index 0000000..cee7266
--- /dev/null
+++ b/src/test/ui/duplicate/dupe-symbols-5.stderr
@@ -0,0 +1,10 @@
+error: symbol `fail` is already defined
+  --> $DIR/dupe-symbols-5.rs:9:1
+   |
+LL | / pub fn b() {
+LL | |
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/duplicate/dupe-symbols-6.rs b/src/test/ui/duplicate/dupe-symbols-6.rs
new file mode 100644
index 0000000..5a1b917
--- /dev/null
+++ b/src/test/ui/duplicate/dupe-symbols-6.rs
@@ -0,0 +1,9 @@
+#![crate_type="rlib"]
+#![allow(warnings)]
+
+#[export_name="fail"]
+static HELLO: u8 = 0;
+
+#[export_name="fail"]
+static HELLO_TWICE: u16 = 0;
+//~^ symbol `fail` is already defined
diff --git a/src/test/ui/duplicate/dupe-symbols-6.stderr b/src/test/ui/duplicate/dupe-symbols-6.stderr
new file mode 100644
index 0000000..69781ee
--- /dev/null
+++ b/src/test/ui/duplicate/dupe-symbols-6.stderr
@@ -0,0 +1,8 @@
+error: symbol `fail` is already defined
+  --> $DIR/dupe-symbols-6.rs:8:1
+   |
+LL | static HELLO_TWICE: u16 = 0;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/duplicate/dupe-symbols-7.rs b/src/test/ui/duplicate/dupe-symbols-7.rs
new file mode 100644
index 0000000..b28f1a4
--- /dev/null
+++ b/src/test/ui/duplicate/dupe-symbols-7.rs
@@ -0,0 +1,6 @@
+//
+// error-pattern: entry symbol `main` defined multiple times
+#![allow(warnings)]
+
+#[no_mangle]
+fn main(){}
diff --git a/src/test/ui/duplicate/dupe-symbols-7.stderr b/src/test/ui/duplicate/dupe-symbols-7.stderr
new file mode 100644
index 0000000..a1dbbb0
--- /dev/null
+++ b/src/test/ui/duplicate/dupe-symbols-7.stderr
@@ -0,0 +1,10 @@
+error: entry symbol `main` defined multiple times
+  --> $DIR/dupe-symbols-7.rs:6:1
+   |
+LL | fn main(){}
+   | ^^^^^^^^^^^
+   |
+   = help: did you use #[no_mangle] on `fn main`? Use #[start] instead
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/duplicate/duplicate-check-macro-exports.rs b/src/test/ui/duplicate/duplicate-check-macro-exports.rs
new file mode 100644
index 0000000..9ba28ac
--- /dev/null
+++ b/src/test/ui/duplicate/duplicate-check-macro-exports.rs
@@ -0,0 +1,6 @@
+pub use std::panic;
+
+#[macro_export]
+macro_rules! panic { () => {} } //~ ERROR the name `panic` is defined multiple times
+
+fn main() {}
diff --git a/src/test/ui/duplicate/duplicate-check-macro-exports.stderr b/src/test/ui/duplicate/duplicate-check-macro-exports.stderr
new file mode 100644
index 0000000..02f0206
--- /dev/null
+++ b/src/test/ui/duplicate/duplicate-check-macro-exports.stderr
@@ -0,0 +1,18 @@
+error[E0255]: the name `panic` is defined multiple times
+  --> $DIR/duplicate-check-macro-exports.rs:4:1
+   |
+LL | pub use std::panic;
+   |         ---------- previous import of the macro `panic` here
+...
+LL | macro_rules! panic { () => {} }
+   | ^^^^^^^^^^^^^^^^^^ `panic` redefined here
+   |
+   = note: `panic` must be defined only once in the macro namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | pub use std::panic as other_panic;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0255`.
diff --git a/src/test/ui/duplicate/duplicate-parameter.rs b/src/test/ui/duplicate/duplicate-parameter.rs
new file mode 100644
index 0000000..e5b21bb
--- /dev/null
+++ b/src/test/ui/duplicate/duplicate-parameter.rs
@@ -0,0 +1,5 @@
+fn f(a: isize, a: isize) {}
+//~^ ERROR identifier `a` is bound more than once in this parameter list
+
+fn main() {
+}
diff --git a/src/test/ui/duplicate/duplicate-parameter.stderr b/src/test/ui/duplicate/duplicate-parameter.stderr
new file mode 100644
index 0000000..f3ef0bc
--- /dev/null
+++ b/src/test/ui/duplicate/duplicate-parameter.stderr
@@ -0,0 +1,9 @@
+error[E0415]: identifier `a` is bound more than once in this parameter list
+  --> $DIR/duplicate-parameter.rs:1:16
+   |
+LL | fn f(a: isize, a: isize) {}
+   |                ^ used as parameter more than once
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0415`.
diff --git a/src/test/ui/duplicate/duplicate-type-parameter.rs b/src/test/ui/duplicate/duplicate-type-parameter.rs
new file mode 100644
index 0000000..2751b3c
--- /dev/null
+++ b/src/test/ui/duplicate/duplicate-type-parameter.rs
@@ -0,0 +1,29 @@
+type Foo<T,T> = Option<T>;
+//~^ ERROR the name `T` is already used
+
+struct Bar<T,T>(T);
+//~^ ERROR the name `T` is already used
+
+struct Baz<T,T> {
+//~^ ERROR the name `T` is already used
+    x: T,
+}
+
+enum Boo<T,T> {
+//~^ ERROR the name `T` is already used
+    A(T),
+    B,
+}
+
+fn quux<T,T>(x: T) {}
+//~^ ERROR the name `T` is already used
+
+trait Qux<T,T> {}
+//~^ ERROR the name `T` is already used
+
+impl<T,T> Qux<T,T> for Option<T> {}
+//~^ ERROR the name `T` is already used
+//~^^ ERROR the type parameter `T` is not constrained
+
+fn main() {
+}
diff --git a/src/test/ui/duplicate/duplicate-type-parameter.stderr b/src/test/ui/duplicate/duplicate-type-parameter.stderr
new file mode 100644
index 0000000..17d48ed
--- /dev/null
+++ b/src/test/ui/duplicate/duplicate-type-parameter.stderr
@@ -0,0 +1,66 @@
+error[E0403]: the name `T` is already used for a generic parameter in this list of generic parameters
+  --> $DIR/duplicate-type-parameter.rs:1:12
+   |
+LL | type Foo<T,T> = Option<T>;
+   |          - ^ already used
+   |          |
+   |          first use of `T`
+
+error[E0403]: the name `T` is already used for a generic parameter in this list of generic parameters
+  --> $DIR/duplicate-type-parameter.rs:4:14
+   |
+LL | struct Bar<T,T>(T);
+   |            - ^ already used
+   |            |
+   |            first use of `T`
+
+error[E0403]: the name `T` is already used for a generic parameter in this list of generic parameters
+  --> $DIR/duplicate-type-parameter.rs:7:14
+   |
+LL | struct Baz<T,T> {
+   |            - ^ already used
+   |            |
+   |            first use of `T`
+
+error[E0403]: the name `T` is already used for a generic parameter in this list of generic parameters
+  --> $DIR/duplicate-type-parameter.rs:12:12
+   |
+LL | enum Boo<T,T> {
+   |          - ^ already used
+   |          |
+   |          first use of `T`
+
+error[E0403]: the name `T` is already used for a generic parameter in this list of generic parameters
+  --> $DIR/duplicate-type-parameter.rs:18:11
+   |
+LL | fn quux<T,T>(x: T) {}
+   |         - ^ already used
+   |         |
+   |         first use of `T`
+
+error[E0403]: the name `T` is already used for a generic parameter in this list of generic parameters
+  --> $DIR/duplicate-type-parameter.rs:21:13
+   |
+LL | trait Qux<T,T> {}
+   |           - ^ already used
+   |           |
+   |           first use of `T`
+
+error[E0403]: the name `T` is already used for a generic parameter in this list of generic parameters
+  --> $DIR/duplicate-type-parameter.rs:24:8
+   |
+LL | impl<T,T> Qux<T,T> for Option<T> {}
+   |      - ^ already used
+   |      |
+   |      first use of `T`
+
+error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates
+  --> $DIR/duplicate-type-parameter.rs:24:6
+   |
+LL | impl<T,T> Qux<T,T> for Option<T> {}
+   |      ^ unconstrained type parameter
+
+error: aborting due to 8 previous errors
+
+Some errors occurred: E0207, E0403.
+For more information about an error, try `rustc --explain E0207`.
diff --git a/src/test/ui/duplicate_entry_error.rs b/src/test/ui/duplicate_entry_error.rs
new file mode 100644
index 0000000..62df42b
--- /dev/null
+++ b/src/test/ui/duplicate_entry_error.rs
@@ -0,0 +1,15 @@
+// note-pattern: first defined in crate `std`.
+
+// Test for issue #31788 and E0152
+
+#![feature(lang_items)]
+
+use std::panic::PanicInfo;
+
+#[lang = "panic_impl"]
+fn panic_impl(info: &PanicInfo) -> ! {
+//~^ ERROR: duplicate lang item found: `panic_impl`.
+    loop {}
+}
+
+fn main() {}
diff --git a/src/test/ui/duplicate_entry_error.stderr b/src/test/ui/duplicate_entry_error.stderr
new file mode 100644
index 0000000..1892ad3
--- /dev/null
+++ b/src/test/ui/duplicate_entry_error.stderr
@@ -0,0 +1,14 @@
+error[E0152]: duplicate lang item found: `panic_impl`.
+  --> $DIR/duplicate_entry_error.rs:10:1
+   |
+LL | / fn panic_impl(info: &PanicInfo) -> ! {
+LL | |
+LL | |     loop {}
+LL | | }
+   | |_^
+   |
+   = note: first defined in crate `std`.
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0152`.
diff --git a/src/test/ui/dyn-keyword/dyn-2015-edition-keyword-ident-lint.fixed b/src/test/ui/dyn-keyword/dyn-2015-edition-keyword-ident-lint.fixed
new file mode 100644
index 0000000..0037362
--- /dev/null
+++ b/src/test/ui/dyn-keyword/dyn-2015-edition-keyword-ident-lint.fixed
@@ -0,0 +1,81 @@
+// Under the 2015 edition with the keyword_idents lint, `dyn` is not
+// entirely acceptable as an identifier. We currently do not attempt
+// to detect or fix uses of `dyn` under a macro. Since we are testing
+// this file via `rustfix`, we want the rustfix output to be
+// compilable; so the macros here carefully use `dyn` "correctly."
+
+// run-rustfix
+
+#![allow(non_camel_case_types)]
+#![deny(keyword_idents)]
+
+mod outer_mod {
+    pub mod r#dyn {
+//~^ ERROR `dyn` is a keyword
+//~| WARN was previously accepted
+        pub struct r#dyn;
+//~^ ERROR `dyn` is a keyword
+//~| WARN was previously accepted
+    }
+}
+use outer_mod::r#dyn::r#dyn;
+//~^ ERROR `dyn` is a keyword
+//~| WARN was previously accepted
+//~| ERROR `dyn` is a keyword
+//~| WARN was previously accepted
+
+fn main() {
+    match r#dyn { r#dyn => {} }
+//~^ ERROR `dyn` is a keyword
+//~| WARN was previously accepted
+//~| ERROR `dyn` is a keyword
+//~| WARN was previously accepted
+    macro_defn::r#dyn();
+//~^ ERROR `dyn` is a keyword
+//~| WARN was previously accepted
+
+    macro_defn::boxed();
+}
+
+mod macro_defn {
+    use super::Trait;
+
+    macro_rules! r#dyn {
+//~^ ERROR `dyn` is a keyword
+//~| WARN was previously accepted
+
+        // Note that we do not lint nor fix occurrences under macros
+        ($dyn:tt) => { (Box<dyn Trait>, Box<$dyn Trait>) }
+    }
+
+    pub fn r#dyn() -> ::outer_mod::r#dyn::r#dyn {
+//~^ ERROR `dyn` is a keyword
+//~| WARN was previously accepted
+//~| ERROR `dyn` is a keyword
+//~| WARN was previously accepted
+//~| ERROR `dyn` is a keyword
+//~| WARN was previously accepted
+        ::outer_mod::r#dyn::r#dyn
+//~^ ERROR `dyn` is a keyword
+//~| WARN was previously accepted
+//~| ERROR `dyn` is a keyword
+//~| WARN was previously accepted
+    }
+
+
+
+    pub fn boxed() -> r#dyn!(
+        //~^ ERROR `dyn` is a keyword
+        //~| WARN was previously accepted
+
+            // Note that we do not lint nor fix occurrences under macros
+            dyn
+    )
+    {
+        (Box::new(1), Box::new(2))
+    }
+}
+
+pub trait Trait { }
+
+impl Trait for u32 { }
diff --git a/src/test/ui/dyn-keyword/dyn-2015-edition-keyword-ident-lint.rs b/src/test/ui/dyn-keyword/dyn-2015-edition-keyword-ident-lint.rs
new file mode 100644
index 0000000..0e5c39f
--- /dev/null
+++ b/src/test/ui/dyn-keyword/dyn-2015-edition-keyword-ident-lint.rs
@@ -0,0 +1,81 @@
+// Under the 2015 edition with the keyword_idents lint, `dyn` is not
+// entirely acceptable as an identifier. We currently do not attempt
+// to detect or fix uses of `dyn` under a macro. Since we are testing
+// this file via `rustfix`, we want the rustfix output to be
+// compilable; so the macros here carefully use `dyn` "correctly."
+
+// run-rustfix
+
+#![allow(non_camel_case_types)]
+#![deny(keyword_idents)]
+
+mod outer_mod {
+    pub mod dyn {
+//~^ ERROR `dyn` is a keyword
+//~| WARN was previously accepted
+        pub struct dyn;
+//~^ ERROR `dyn` is a keyword
+//~| WARN was previously accepted
+    }
+}
+use outer_mod::dyn::dyn;
+//~^ ERROR `dyn` is a keyword
+//~| WARN was previously accepted
+//~| ERROR `dyn` is a keyword
+//~| WARN was previously accepted
+
+fn main() {
+    match dyn { dyn => {} }
+//~^ ERROR `dyn` is a keyword
+//~| WARN was previously accepted
+//~| ERROR `dyn` is a keyword
+//~| WARN was previously accepted
+    macro_defn::dyn();
+//~^ ERROR `dyn` is a keyword
+//~| WARN was previously accepted
+
+    macro_defn::boxed();
+}
+
+mod macro_defn {
+    use super::Trait;
+
+    macro_rules! dyn {
+//~^ ERROR `dyn` is a keyword
+//~| WARN was previously accepted
+
+        // Note that we do not lint nor fix occurrences under macros
+        ($dyn:tt) => { (Box<dyn Trait>, Box<$dyn Trait>) }
+    }
+
+    pub fn dyn() -> ::outer_mod::dyn::dyn {
+//~^ ERROR `dyn` is a keyword
+//~| WARN was previously accepted
+//~| ERROR `dyn` is a keyword
+//~| WARN was previously accepted
+//~| ERROR `dyn` is a keyword
+//~| WARN was previously accepted
+        ::outer_mod::dyn::dyn
+//~^ ERROR `dyn` is a keyword
+//~| WARN was previously accepted
+//~| ERROR `dyn` is a keyword
+//~| WARN was previously accepted
+    }
+
+
+
+    pub fn boxed() -> dyn!(
+        //~^ ERROR `dyn` is a keyword
+        //~| WARN was previously accepted
+
+            // Note that we do not lint nor fix occurrences under macros
+            dyn
+    )
+    {
+        (Box::new(1), Box::new(2))
+    }
+}
+
+pub trait Trait { }
+
+impl Trait for u32 { }
diff --git a/src/test/ui/dyn-keyword/dyn-2015-edition-keyword-ident-lint.stderr b/src/test/ui/dyn-keyword/dyn-2015-edition-keyword-ident-lint.stderr
new file mode 100644
index 0000000..3617277
--- /dev/null
+++ b/src/test/ui/dyn-keyword/dyn-2015-edition-keyword-ident-lint.stderr
@@ -0,0 +1,133 @@
+error: `dyn` is a keyword in the 2018 edition
+  --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:13:13
+   |
+LL |     pub mod dyn {
+   |             ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
+   |
+note: lint level defined here
+  --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:10:9
+   |
+LL | #![deny(keyword_idents)]
+   |         ^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: `dyn` is a keyword in the 2018 edition
+  --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:16:20
+   |
+LL |         pub struct dyn;
+   |                    ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: `dyn` is a keyword in the 2018 edition
+  --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:21:16
+   |
+LL | use outer_mod::dyn::dyn;
+   |                ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: `dyn` is a keyword in the 2018 edition
+  --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:21:21
+   |
+LL | use outer_mod::dyn::dyn;
+   |                     ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: `dyn` is a keyword in the 2018 edition
+  --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:28:11
+   |
+LL |     match dyn { dyn => {} }
+   |           ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: `dyn` is a keyword in the 2018 edition
+  --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:28:17
+   |
+LL |     match dyn { dyn => {} }
+   |                 ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: `dyn` is a keyword in the 2018 edition
+  --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:33:17
+   |
+LL |     macro_defn::dyn();
+   |                 ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: `dyn` is a keyword in the 2018 edition
+  --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:43:18
+   |
+LL |     macro_rules! dyn {
+   |                  ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: `dyn` is a keyword in the 2018 edition
+  --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:51:12
+   |
+LL |     pub fn dyn() -> ::outer_mod::dyn::dyn {
+   |            ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: `dyn` is a keyword in the 2018 edition
+  --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:51:34
+   |
+LL |     pub fn dyn() -> ::outer_mod::dyn::dyn {
+   |                                  ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: `dyn` is a keyword in the 2018 edition
+  --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:51:39
+   |
+LL |     pub fn dyn() -> ::outer_mod::dyn::dyn {
+   |                                       ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: `dyn` is a keyword in the 2018 edition
+  --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:58:22
+   |
+LL |         ::outer_mod::dyn::dyn
+   |                      ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: `dyn` is a keyword in the 2018 edition
+  --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:58:27
+   |
+LL |         ::outer_mod::dyn::dyn
+   |                           ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: `dyn` is a keyword in the 2018 edition
+  --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:67:23
+   |
+LL |     pub fn boxed() -> dyn!(
+   |                       ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: aborting due to 14 previous errors
+
diff --git a/src/test/ui/dyn-keyword/dyn-2015-idents-in-decl-macros-unlinted.rs b/src/test/ui/dyn-keyword/dyn-2015-idents-in-decl-macros-unlinted.rs
new file mode 100644
index 0000000..f535791
--- /dev/null
+++ b/src/test/ui/dyn-keyword/dyn-2015-idents-in-decl-macros-unlinted.rs
@@ -0,0 +1,51 @@
+// compile-pass
+
+// Under the 2015 edition with the keyword_idents lint, `dyn` is
+// not entirely acceptable as an identifier.
+//
+// We currently do not attempt to detect or fix uses of `dyn` as an
+// identifier under a macro, including under the declarative `macro`
+// forms from macros 1.2 and macros 2.0.
+
+#![feature(decl_macro)]
+#![allow(non_camel_case_types)]
+#![deny(keyword_idents)]
+
+mod outer_mod {
+    pub mod r#dyn {
+        pub struct r#dyn;
+    }
+}
+
+// Here we are illustrating that the current lint does not flag the
+// occurrences of `dyn` in this macro definition; however, it
+// certainly *could* (and it would be nice if it did), since these
+// occurrences are not compatible with the 2018 edition's
+// interpretation of `dyn` as a keyword.
+macro defn_has_dyn_idents() { ::outer_mod::dyn::dyn }
+
+struct X;
+trait Trait { fn hello(&self) { }}
+impl Trait for X { }
+
+macro tt_trait($arg:tt) { & $arg Trait }
+macro id_trait($id:ident) { & $id Trait }
+
+fn main() {
+    defn_has_dyn_idents!();
+
+    // Here we are illustrating that the current lint does not flag
+    // the occurrences of `dyn` in these macro invocations. It
+    // definitely should *not* flag the one in `tt_trait`, since that
+    // is expanding in a valid fashion to `&dyn Trait`.
+    //
+    // It is arguable whether it would be valid to flag the occurrence
+    // in `id_trait`, since that macro specifies that it takes an
+    // `ident` as its input.
+    fn f_tt(x: &X) -> tt_trait!(dyn) { x }
+    fn f_id(x: &X) -> id_trait!(dyn) { x }
+
+    let x = X;
+    f_tt(&x).hello();
+    f_id(&x).hello();
+}
diff --git a/src/test/ui/dyn-keyword/dyn-2015-idents-in-macros-unlinted.rs b/src/test/ui/dyn-keyword/dyn-2015-idents-in-macros-unlinted.rs
new file mode 100644
index 0000000..27e4905
--- /dev/null
+++ b/src/test/ui/dyn-keyword/dyn-2015-idents-in-macros-unlinted.rs
@@ -0,0 +1,56 @@
+// compile-pass
+
+// Under the 2015 edition with the keyword_idents lint, `dyn` is
+// not entirely acceptable as an identifier.
+//
+// We currently do not attempt to detect or fix uses of `dyn` as an
+// identifier under a macro.
+
+#![allow(non_camel_case_types)]
+#![deny(keyword_idents)]
+
+mod outer_mod {
+    pub mod r#dyn {
+        pub struct r#dyn;
+    }
+}
+
+// Here we are illustrating that the current lint does not flag the
+// occurrences of `dyn` in this macro definition; however, it
+// certainly *could* (and it would be nice if it did), since these
+// occurrences are not compatible with the 2018 edition's
+// interpretation of `dyn` as a keyword.
+macro_rules! defn_has_dyn_idents {
+    () => { ::outer_mod::dyn::dyn }
+}
+
+struct X;
+trait Trait { fn hello(&self) { }}
+impl Trait for X { }
+
+macro_rules! tt_trait {
+    ($arg:tt) => { & $arg Trait }
+}
+
+macro_rules! id_trait {
+    ($id:ident) => { & $id Trait }
+}
+
+fn main() {
+    defn_has_dyn_idents!();
+
+    // Here we are illustrating that the current lint does not flag
+    // the occurrences of `dyn` in these macro invocations. It
+    // definitely should *not* flag the one in `tt_trait`, since that
+    // is expanding in a valid fashion to `&dyn Trait`.
+    //
+    // It is arguable whether it would be valid to flag the occurrence
+    // in `id_trait`, since that macro specifies that it takes an
+    // `ident` as its input.
+    fn f_tt(x: &X) -> tt_trait!(dyn) { x }
+    fn f_id(x: &X) -> id_trait!(dyn) { x }
+
+    let x = X;
+    f_tt(&x).hello();
+    f_id(&x).hello();
+}
diff --git a/src/test/ui/dyn-keyword/dyn-2015-no-warnings-without-lints.rs b/src/test/ui/dyn-keyword/dyn-2015-no-warnings-without-lints.rs
new file mode 100644
index 0000000..8cef5c2
--- /dev/null
+++ b/src/test/ui/dyn-keyword/dyn-2015-no-warnings-without-lints.rs
@@ -0,0 +1,27 @@
+// Under the 2015 edition without the keyword_idents lint, `dyn` is
+// entirely acceptable as an identifier.
+
+// compile-pass
+
+#![allow(non_camel_case_types)]
+
+mod outer_mod {
+    pub mod dyn {
+        pub struct dyn;
+    }
+}
+use outer_mod::dyn::dyn;
+
+fn main() {
+    match dyn { dyn => {} }
+    macro_defn::dyn();
+}
+mod macro_defn {
+    macro_rules! dyn {
+        () => { ::outer_mod::dyn::dyn }
+    }
+
+    pub fn dyn() -> ::outer_mod::dyn::dyn {
+        dyn!()
+    }
+}
diff --git a/src/test/ui/dyn-keyword/issue-56327-dyn-trait-in-macro-is-okay.rs b/src/test/ui/dyn-keyword/issue-56327-dyn-trait-in-macro-is-okay.rs
new file mode 100644
index 0000000..ff3830d
--- /dev/null
+++ b/src/test/ui/dyn-keyword/issue-56327-dyn-trait-in-macro-is-okay.rs
@@ -0,0 +1,25 @@
+// compile-pass
+
+// rust-lang/rust#56327: Some occurrences of `dyn` within a macro are
+// not instances of identifiers, and thus should *not* be caught by the
+// keyword_ident lint.
+//
+// Otherwise, rustfix replaces the type `Box<dyn Drop>` with
+// `Box<r#dyn Drop>`, which is injecting a bug rather than fixing
+// anything.
+
+#![deny(rust_2018_compatibility)]
+
+macro_rules! foo {
+    () => {
+        fn generated_foo() {
+            let _x: Box<dyn Drop>;
+        }
+    }
+}
+
+foo!();
+
+fn main() {
+    generated_foo();
+}
diff --git a/src/test/ui/dyn-trait-compatibility.rs b/src/test/ui/dyn-trait-compatibility.rs
new file mode 100644
index 0000000..2a1cea6
--- /dev/null
+++ b/src/test/ui/dyn-trait-compatibility.rs
@@ -0,0 +1,14 @@
+type A0 = dyn;
+//~^ ERROR cannot find type `dyn` in this scope
+type A1 = dyn::dyn;
+//~^ ERROR use of undeclared type or module `dyn`
+type A2 = dyn<dyn, dyn>;
+//~^ ERROR cannot find type `dyn` in this scope
+//~| ERROR cannot find type `dyn` in this scope
+//~| ERROR cannot find type `dyn` in this scope
+type A3 = dyn<<dyn as dyn>::dyn>;
+//~^ ERROR cannot find type `dyn` in this scope
+//~| ERROR cannot find type `dyn` in this scope
+//~| ERROR use of undeclared type or module `dyn`
+
+fn main() {}
diff --git a/src/test/ui/dyn-trait-compatibility.stderr b/src/test/ui/dyn-trait-compatibility.stderr
new file mode 100644
index 0000000..aef785a
--- /dev/null
+++ b/src/test/ui/dyn-trait-compatibility.stderr
@@ -0,0 +1,52 @@
+error[E0433]: failed to resolve: use of undeclared type or module `dyn`
+  --> $DIR/dyn-trait-compatibility.rs:3:11
+   |
+LL | type A1 = dyn::dyn;
+   |           ^^^ use of undeclared type or module `dyn`
+
+error[E0433]: failed to resolve: use of undeclared type or module `dyn`
+  --> $DIR/dyn-trait-compatibility.rs:9:23
+   |
+LL | type A3 = dyn<<dyn as dyn>::dyn>;
+   |                       ^^^ use of undeclared type or module `dyn`
+
+error[E0412]: cannot find type `dyn` in this scope
+  --> $DIR/dyn-trait-compatibility.rs:1:11
+   |
+LL | type A0 = dyn;
+   |           ^^^ not found in this scope
+
+error[E0412]: cannot find type `dyn` in this scope
+  --> $DIR/dyn-trait-compatibility.rs:5:11
+   |
+LL | type A2 = dyn<dyn, dyn>;
+   |           ^^^ not found in this scope
+
+error[E0412]: cannot find type `dyn` in this scope
+  --> $DIR/dyn-trait-compatibility.rs:5:15
+   |
+LL | type A2 = dyn<dyn, dyn>;
+   |               ^^^ not found in this scope
+
+error[E0412]: cannot find type `dyn` in this scope
+  --> $DIR/dyn-trait-compatibility.rs:5:20
+   |
+LL | type A2 = dyn<dyn, dyn>;
+   |                    ^^^ not found in this scope
+
+error[E0412]: cannot find type `dyn` in this scope
+  --> $DIR/dyn-trait-compatibility.rs:9:11
+   |
+LL | type A3 = dyn<<dyn as dyn>::dyn>;
+   |           ^^^ not found in this scope
+
+error[E0412]: cannot find type `dyn` in this scope
+  --> $DIR/dyn-trait-compatibility.rs:9:16
+   |
+LL | type A3 = dyn<<dyn as dyn>::dyn>;
+   |                ^^^ not found in this scope
+
+error: aborting due to 8 previous errors
+
+Some errors occurred: E0412, E0433.
+For more information about an error, try `rustc --explain E0412`.
diff --git a/src/test/ui/e0119/auxiliary/complex_impl_support.rs b/src/test/ui/e0119/auxiliary/complex_impl_support.rs
new file mode 100644
index 0000000..ad5bb10
--- /dev/null
+++ b/src/test/ui/e0119/auxiliary/complex_impl_support.rs
@@ -0,0 +1,22 @@
+use std::marker::PhantomData;
+
+pub trait External {}
+
+pub struct M<'a, 'b, 'c, T, U, V> {
+    a: PhantomData<&'a ()>,
+    b: PhantomData<&'b ()>,
+    c: PhantomData<&'c ()>,
+    d: PhantomData<T>,
+    e: PhantomData<U>,
+    f: PhantomData<V>,
+}
+
+impl<'a, 'b, 'c, T, U, V, W> External for (T, M<'a, 'b, 'c, Box<U>, V, W>)
+where
+    'b: 'a,
+    T: 'a,
+    U: (FnOnce(T) -> V) + 'static,
+    V: Iterator<Item=T> + Clone,
+    W: std::ops::Add,
+    W::Output: Copy,
+{}
diff --git a/src/test/ui/e0119/auxiliary/issue-23563-a.rs b/src/test/ui/e0119/auxiliary/issue-23563-a.rs
new file mode 100644
index 0000000..4e85bcc
--- /dev/null
+++ b/src/test/ui/e0119/auxiliary/issue-23563-a.rs
@@ -0,0 +1,25 @@
+// Ref: https://github.com/rust-lang/rust/issues/23563#issuecomment-260751672
+
+pub trait LolTo<T> {
+    fn convert_to(&self) -> T;
+}
+
+pub trait LolInto<T>: Sized {
+    fn convert_into(self) -> T;
+}
+
+pub trait LolFrom<T> {
+    fn from(T) -> Self;
+}
+
+impl<'a, T: ?Sized, U> LolInto<U> for &'a T where T: LolTo<U> {
+    fn convert_into(self) -> U {
+        self.convert_to()
+    }
+}
+
+impl<T, U> LolFrom<T> for U where T: LolInto<U> {
+    fn from(t: T) -> U {
+        t.convert_into()
+    }
+}
diff --git a/src/test/ui/e0119/complex-impl.rs b/src/test/ui/e0119/complex-impl.rs
new file mode 100644
index 0000000..3cba39e
--- /dev/null
+++ b/src/test/ui/e0119/complex-impl.rs
@@ -0,0 +1,12 @@
+// aux-build:complex_impl_support.rs
+
+extern crate complex_impl_support;
+
+use complex_impl_support::{External, M};
+
+struct Q;
+
+impl<R> External for (Q, R) {} //~ ERROR must be used
+//~^ ERROR conflicting implementations of trait
+
+fn main() {}
diff --git a/src/test/ui/e0119/complex-impl.stderr b/src/test/ui/e0119/complex-impl.stderr
new file mode 100644
index 0000000..f211530
--- /dev/null
+++ b/src/test/ui/e0119/complex-impl.stderr
@@ -0,0 +1,22 @@
+error[E0119]: conflicting implementations of trait `complex_impl_support::External` for type `(Q, complex_impl_support::M<'_, '_, '_, std::boxed::Box<_>, _, _>)`:
+  --> $DIR/complex-impl.rs:9:1
+   |
+LL | impl<R> External for (Q, R) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: conflicting implementation in crate `complex_impl_support`:
+           - impl<'a, 'b, 'c, T, U, V, W> complex_impl_support::External for (T, complex_impl_support::M<'a, 'b, 'c, std::boxed::Box<U>, V, W>)
+             where <U as std::ops::FnOnce<(T,)>>::Output == V, <V as std::iter::Iterator>::Item == T, 'b : 'a, T : 'a, U: std::ops::FnOnce<(T,)>, U : 'static, V: std::iter::Iterator, V: std::clone::Clone, W: std::ops::Add, <W as std::ops::Add>::Output: std::marker::Copy;
+
+error[E0210]: type parameter `R` must be used as the type parameter for some local type (e.g., `MyStruct<R>`)
+  --> $DIR/complex-impl.rs:9:1
+   |
+LL | impl<R> External for (Q, R) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `R` must be used as the type parameter for some local type
+   |
+   = note: only traits defined in the current crate can be implemented for a type parameter
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0119, E0210.
+For more information about an error, try `rustc --explain E0119`.
diff --git a/src/test/ui/e0119/conflict-with-std.rs b/src/test/ui/e0119/conflict-with-std.rs
new file mode 100644
index 0000000..6dc81f3
--- /dev/null
+++ b/src/test/ui/e0119/conflict-with-std.rs
@@ -0,0 +1,27 @@
+
+use std::marker::PhantomData;
+use std::convert::{TryFrom, AsRef};
+
+struct Q;
+impl AsRef<Q> for Box<Q> { //~ ERROR conflicting implementations
+    fn as_ref(&self) -> &Q {
+        &**self
+    }
+}
+
+struct S;
+impl From<S> for S { //~ ERROR conflicting implementations
+    fn from(s: S) -> S {
+        s
+    }
+}
+
+struct X;
+impl TryFrom<X> for X { //~ ERROR conflicting implementations
+    type Error = ();
+    fn try_from(u: X) -> Result<X, ()> {
+        Ok(u)
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/e0119/conflict-with-std.stderr b/src/test/ui/e0119/conflict-with-std.stderr
new file mode 100644
index 0000000..8c12b3d
--- /dev/null
+++ b/src/test/ui/e0119/conflict-with-std.stderr
@@ -0,0 +1,32 @@
+error[E0119]: conflicting implementations of trait `std::convert::AsRef<Q>` for type `std::boxed::Box<Q>`:
+  --> $DIR/conflict-with-std.rs:6:1
+   |
+LL | impl AsRef<Q> for Box<Q> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: conflicting implementation in crate `alloc`:
+           - impl<T> std::convert::AsRef<T> for std::boxed::Box<T>
+             where T: ?Sized;
+
+error[E0119]: conflicting implementations of trait `std::convert::From<S>` for type `S`:
+  --> $DIR/conflict-with-std.rs:13:1
+   |
+LL | impl From<S> for S {
+   | ^^^^^^^^^^^^^^^^^^
+   |
+   = note: conflicting implementation in crate `core`:
+           - impl<T> std::convert::From<T> for T;
+
+error[E0119]: conflicting implementations of trait `std::convert::TryFrom<X>` for type `X`:
+  --> $DIR/conflict-with-std.rs:20:1
+   |
+LL | impl TryFrom<X> for X {
+   | ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: conflicting implementation in crate `core`:
+           - impl<T, U> std::convert::TryFrom<U> for T
+             where U: std::convert::Into<T>;
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/e0119/issue-23563.rs b/src/test/ui/e0119/issue-23563.rs
new file mode 100644
index 0000000..f578560
--- /dev/null
+++ b/src/test/ui/e0119/issue-23563.rs
@@ -0,0 +1,29 @@
+// aux-build:issue-23563-a.rs
+
+// Ref: https://github.com/rust-lang/rust/issues/23563#issuecomment-260751672
+
+extern crate issue_23563_a as a;
+
+use a::LolFrom;
+use a::LolInto;
+use a::LolTo;
+
+struct LocalType<T>(Option<T>);
+
+impl<'a, T> LolFrom<&'a [T]> for LocalType<T> { //~ ERROR conflicting implementations of trait
+    fn from(_: &'a [T]) -> LocalType<T> { LocalType(None) }
+}
+
+impl<T> LolInto<LocalType<T>> for LocalType<T> {
+    fn convert_into(self) -> LocalType<T> {
+        self
+    }
+}
+
+impl LolTo<LocalType<u8>> for [u8] {
+    fn convert_to(&self) -> LocalType<u8> {
+        LocalType(None)
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/e0119/issue-23563.stderr b/src/test/ui/e0119/issue-23563.stderr
new file mode 100644
index 0000000..8011689
--- /dev/null
+++ b/src/test/ui/e0119/issue-23563.stderr
@@ -0,0 +1,13 @@
+error[E0119]: conflicting implementations of trait `a::LolFrom<&[_]>` for type `LocalType<_>`:
+  --> $DIR/issue-23563.rs:13:1
+   |
+LL | impl<'a, T> LolFrom<&'a [T]> for LocalType<T> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: conflicting implementation in crate `issue_23563_a`:
+           - impl<T, U> a::LolFrom<T> for U
+             where T: a::LolInto<U>;
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/e0119/issue-27403.rs b/src/test/ui/e0119/issue-27403.rs
new file mode 100644
index 0000000..b03a564
--- /dev/null
+++ b/src/test/ui/e0119/issue-27403.rs
@@ -0,0 +1,11 @@
+pub struct GenX<S> {
+    inner: S,
+}
+
+impl<S> Into<S> for GenX<S> { //~ ERROR conflicting implementations
+    fn into(self) -> S {
+        self.inner
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/e0119/issue-27403.stderr b/src/test/ui/e0119/issue-27403.stderr
new file mode 100644
index 0000000..cba1043
--- /dev/null
+++ b/src/test/ui/e0119/issue-27403.stderr
@@ -0,0 +1,13 @@
+error[E0119]: conflicting implementations of trait `std::convert::Into<_>` for type `GenX<_>`:
+  --> $DIR/issue-27403.rs:5:1
+   |
+LL | impl<S> Into<S> for GenX<S> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: conflicting implementation in crate `core`:
+           - impl<T, U> std::convert::Into<U> for T
+             where U: std::convert::From<T>;
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/e0119/issue-28981.rs b/src/test/ui/e0119/issue-28981.rs
new file mode 100644
index 0000000..c31b212
--- /dev/null
+++ b/src/test/ui/e0119/issue-28981.rs
@@ -0,0 +1,8 @@
+use std::ops::Deref;
+
+struct Foo;
+
+impl<Foo> Deref for Foo { } //~ ERROR must be used
+//~^ ERROR conflicting implementations
+
+fn main() {}
diff --git a/src/test/ui/e0119/issue-28981.stderr b/src/test/ui/e0119/issue-28981.stderr
new file mode 100644
index 0000000..e1e0719
--- /dev/null
+++ b/src/test/ui/e0119/issue-28981.stderr
@@ -0,0 +1,22 @@
+error[E0119]: conflicting implementations of trait `std::ops::Deref` for type `&_`:
+  --> $DIR/issue-28981.rs:5:1
+   |
+LL | impl<Foo> Deref for Foo { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: conflicting implementation in crate `core`:
+           - impl<T> std::ops::Deref for &T
+             where T: ?Sized;
+
+error[E0210]: type parameter `Foo` must be used as the type parameter for some local type (e.g., `MyStruct<Foo>`)
+  --> $DIR/issue-28981.rs:5:1
+   |
+LL | impl<Foo> Deref for Foo { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^ type parameter `Foo` must be used as the type parameter for some local type
+   |
+   = note: only traits defined in the current crate can be implemented for a type parameter
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0119, E0210.
+For more information about an error, try `rustc --explain E0119`.
diff --git a/src/test/ui/e0119/so-37347311.rs b/src/test/ui/e0119/so-37347311.rs
new file mode 100644
index 0000000..d5f624b
--- /dev/null
+++ b/src/test/ui/e0119/so-37347311.rs
@@ -0,0 +1,17 @@
+// Ref: https://stackoverflow.com/q/37347311
+
+trait Storage {
+    type Error;
+}
+
+enum MyError<S: Storage> {
+    StorageProblem(S::Error),
+}
+
+impl<S: Storage> From<S::Error> for MyError<S> { //~ ERROR conflicting implementations
+    fn from(error: S::Error) -> MyError<S> {
+        MyError::StorageProblem(error)
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/e0119/so-37347311.stderr b/src/test/ui/e0119/so-37347311.stderr
new file mode 100644
index 0000000..f2166de
--- /dev/null
+++ b/src/test/ui/e0119/so-37347311.stderr
@@ -0,0 +1,12 @@
+error[E0119]: conflicting implementations of trait `std::convert::From<MyError<_>>` for type `MyError<_>`:
+  --> $DIR/so-37347311.rs:11:1
+   |
+LL | impl<S: Storage> From<S::Error> for MyError<S> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: conflicting implementation in crate `core`:
+           - impl<T> std::convert::From<T> for T;
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/editions/auxiliary/absolute.rs b/src/test/ui/editions/auxiliary/absolute.rs
new file mode 100644
index 0000000..d596f97
--- /dev/null
+++ b/src/test/ui/editions/auxiliary/absolute.rs
@@ -0,0 +1 @@
+pub struct Path;
diff --git a/src/test/ui/editions/auxiliary/edition-extern-crate-allowed.rs b/src/test/ui/editions/auxiliary/edition-extern-crate-allowed.rs
new file mode 100644
index 0000000..d11c69f
--- /dev/null
+++ b/src/test/ui/editions/auxiliary/edition-extern-crate-allowed.rs
@@ -0,0 +1 @@
+// intentionally empty
diff --git a/src/test/ui/editions/auxiliary/edition-imports-2015.rs b/src/test/ui/editions/auxiliary/edition-imports-2015.rs
new file mode 100644
index 0000000..c72331c
--- /dev/null
+++ b/src/test/ui/editions/auxiliary/edition-imports-2015.rs
@@ -0,0 +1,31 @@
+// edition:2015
+
+#[macro_export]
+macro_rules! gen_imports { () => {
+    use import::Path;
+    use std::collections::LinkedList;
+
+    fn check_absolute() {
+        ::absolute::Path;
+        ::std::collections::LinkedList::<u8>::new();
+    }
+}}
+
+#[macro_export]
+macro_rules! gen_glob { () => {
+    use *;
+}}
+
+#[macro_export]
+macro_rules! gen_gated { () => {
+    fn check_gated() {
+        enum E { A }
+        use E::*;
+    }
+}}
+
+#[macro_export]
+macro_rules! gen_ambiguous { () => {
+    use Ambiguous;
+    type A = ::edition_imports_2015::Path;
+}}
diff --git a/src/test/ui/editions/auxiliary/edition-imports-2018.rs b/src/test/ui/editions/auxiliary/edition-imports-2018.rs
new file mode 100644
index 0000000..b08dc49
--- /dev/null
+++ b/src/test/ui/editions/auxiliary/edition-imports-2018.rs
@@ -0,0 +1,17 @@
+// edition:2018
+
+#[macro_export]
+macro_rules! gen_imports { () => {
+    use import::Path;
+    use std::collections::LinkedList;
+
+    fn check_absolute() {
+        ::absolute::Path;
+        ::std::collections::LinkedList::<u8>::new();
+    }
+}}
+
+#[macro_export]
+macro_rules! gen_glob { () => {
+    use *;
+}}
diff --git a/src/test/ui/editions/auxiliary/edition-kw-macro-2015.rs b/src/test/ui/editions/auxiliary/edition-kw-macro-2015.rs
new file mode 100644
index 0000000..7cfd128
--- /dev/null
+++ b/src/test/ui/editions/auxiliary/edition-kw-macro-2015.rs
@@ -0,0 +1,28 @@
+// edition:2015
+
+#![allow(keyword_idents)]
+
+#[macro_export]
+macro_rules! produces_async {
+    () => (pub fn async() {})
+}
+
+#[macro_export]
+macro_rules! produces_async_raw {
+    () => (pub fn r#async() {})
+}
+
+#[macro_export]
+macro_rules! consumes_async {
+    (async) => (1)
+}
+
+#[macro_export]
+macro_rules! consumes_async_raw {
+    (r#async) => (1)
+}
+
+#[macro_export]
+macro_rules! passes_ident {
+    ($i: ident) => ($i)
+}
diff --git a/src/test/ui/editions/auxiliary/edition-kw-macro-2018.rs b/src/test/ui/editions/auxiliary/edition-kw-macro-2018.rs
new file mode 100644
index 0000000..d07c021
--- /dev/null
+++ b/src/test/ui/editions/auxiliary/edition-kw-macro-2018.rs
@@ -0,0 +1,28 @@
+// edition:2018
+
+#![allow(keyword_idents)]
+
+#[macro_export]
+macro_rules! produces_async {
+    () => (pub fn async() {})
+}
+
+#[macro_export]
+macro_rules! produces_async_raw {
+    () => (pub fn r#async() {})
+}
+
+#[macro_export]
+macro_rules! consumes_async {
+    (async) => (1)
+}
+
+#[macro_export]
+macro_rules! consumes_async_raw {
+    (r#async) => (1)
+}
+
+#[macro_export]
+macro_rules! passes_ident {
+    ($i: ident) => ($i)
+}
diff --git a/src/test/ui/editions/edition-deny-async-fns-2015.rs b/src/test/ui/editions/edition-deny-async-fns-2015.rs
new file mode 100644
index 0000000..2105aa5
--- /dev/null
+++ b/src/test/ui/editions/edition-deny-async-fns-2015.rs
@@ -0,0 +1,34 @@
+// edition:2015
+
+#![feature(futures_api, async_await)]
+
+async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition
+
+fn baz() { async fn foo() {} } //~ ERROR `async fn` is not permitted in the 2015 edition
+
+async fn async_baz() { //~ ERROR `async fn` is not permitted in the 2015 edition
+    async fn bar() {} //~ ERROR `async fn` is not permitted in the 2015 edition
+}
+
+struct Foo {}
+
+impl Foo {
+    async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition
+}
+
+trait Bar {
+    async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition
+                      //~^ ERROR trait fns cannot be declared `async`
+}
+
+fn main() {
+    macro_rules! accept_item { ($x:item) => {} }
+
+    accept_item! {
+        async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition
+    }
+
+    let inside_closure = || {
+        async fn bar() {} //~ ERROR `async fn` is not permitted in the 2015 edition
+    };
+}
diff --git a/src/test/ui/editions/edition-deny-async-fns-2015.stderr b/src/test/ui/editions/edition-deny-async-fns-2015.stderr
new file mode 100644
index 0000000..83c8dbc
--- /dev/null
+++ b/src/test/ui/editions/edition-deny-async-fns-2015.stderr
@@ -0,0 +1,58 @@
+error[E0670]: `async fn` is not permitted in the 2015 edition
+  --> $DIR/edition-deny-async-fns-2015.rs:5:1
+   |
+LL | async fn foo() {}
+   | ^^^^^
+
+error[E0670]: `async fn` is not permitted in the 2015 edition
+  --> $DIR/edition-deny-async-fns-2015.rs:7:12
+   |
+LL | fn baz() { async fn foo() {} }
+   |            ^^^^^
+
+error[E0670]: `async fn` is not permitted in the 2015 edition
+  --> $DIR/edition-deny-async-fns-2015.rs:10:5
+   |
+LL |     async fn bar() {}
+   |     ^^^^^
+
+error[E0670]: `async fn` is not permitted in the 2015 edition
+  --> $DIR/edition-deny-async-fns-2015.rs:9:1
+   |
+LL | async fn async_baz() {
+   | ^^^^^
+
+error[E0670]: `async fn` is not permitted in the 2015 edition
+  --> $DIR/edition-deny-async-fns-2015.rs:32:9
+   |
+LL |         async fn bar() {}
+   |         ^^^^^
+
+error[E0670]: `async fn` is not permitted in the 2015 edition
+  --> $DIR/edition-deny-async-fns-2015.rs:28:9
+   |
+LL |         async fn foo() {}
+   |         ^^^^^
+
+error[E0670]: `async fn` is not permitted in the 2015 edition
+  --> $DIR/edition-deny-async-fns-2015.rs:16:5
+   |
+LL |     async fn foo() {}
+   |     ^^^^^
+
+error[E0706]: trait fns cannot be declared `async`
+  --> $DIR/edition-deny-async-fns-2015.rs:20:5
+   |
+LL |     async fn foo() {}
+   |     ^^^^^^^^^^^^^^^^^
+
+error[E0670]: `async fn` is not permitted in the 2015 edition
+  --> $DIR/edition-deny-async-fns-2015.rs:20:5
+   |
+LL |     async fn foo() {}
+   |     ^^^^^
+
+error: aborting due to 9 previous errors
+
+Some errors occurred: E0670, E0706.
+For more information about an error, try `rustc --explain E0670`.
diff --git a/src/test/ui/editions/edition-extern-crate-allowed.rs b/src/test/ui/editions/edition-extern-crate-allowed.rs
new file mode 100644
index 0000000..6361fff
--- /dev/null
+++ b/src/test/ui/editions/edition-extern-crate-allowed.rs
@@ -0,0 +1,10 @@
+// aux-build:edition-extern-crate-allowed.rs
+// edition:2015
+// compile-pass
+
+#![warn(rust_2018_idioms)]
+
+extern crate edition_extern_crate_allowed;
+//~^ WARNING unused extern crate
+
+fn main() {}
diff --git a/src/test/ui/editions/edition-extern-crate-allowed.stderr b/src/test/ui/editions/edition-extern-crate-allowed.stderr
new file mode 100644
index 0000000..b675c13
--- /dev/null
+++ b/src/test/ui/editions/edition-extern-crate-allowed.stderr
@@ -0,0 +1,13 @@
+warning: unused extern crate
+  --> $DIR/edition-extern-crate-allowed.rs:7:1
+   |
+LL | extern crate edition_extern_crate_allowed;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
+   |
+note: lint level defined here
+  --> $DIR/edition-extern-crate-allowed.rs:5:9
+   |
+LL | #![warn(rust_2018_idioms)]
+   |         ^^^^^^^^^^^^^^^^
+   = note: #[warn(unused_extern_crates)] implied by #[warn(rust_2018_idioms)]
+
diff --git a/src/test/ui/editions/edition-feature-ok.rs b/src/test/ui/editions/edition-feature-ok.rs
new file mode 100644
index 0000000..c2468df
--- /dev/null
+++ b/src/test/ui/editions/edition-feature-ok.rs
@@ -0,0 +1,5 @@
+// compile-pass
+
+#![feature(rust_2018_preview)]
+
+fn main() {}
diff --git a/src/test/ui/editions/edition-feature-redundant.rs b/src/test/ui/editions/edition-feature-redundant.rs
new file mode 100644
index 0000000..87a2a22
--- /dev/null
+++ b/src/test/ui/editions/edition-feature-redundant.rs
@@ -0,0 +1,7 @@
+// edition:2018
+// compile-pass
+
+#![feature(rust_2018_preview)]
+//~^ WARN the feature `rust_2018_preview` is included in the Rust 2018 edition
+
+fn main() {}
diff --git a/src/test/ui/editions/edition-feature-redundant.stderr b/src/test/ui/editions/edition-feature-redundant.stderr
new file mode 100644
index 0000000..36e90f3
--- /dev/null
+++ b/src/test/ui/editions/edition-feature-redundant.stderr
@@ -0,0 +1,6 @@
+warning[E0705]: the feature `rust_2018_preview` is included in the Rust 2018 edition
+  --> $DIR/edition-feature-redundant.rs:4:12
+   |
+LL | #![feature(rust_2018_preview)]
+   |            ^^^^^^^^^^^^^^^^^
+
diff --git a/src/test/ui/editions/edition-imports-2015.rs b/src/test/ui/editions/edition-imports-2015.rs
new file mode 100644
index 0000000..5ba45b1
--- /dev/null
+++ b/src/test/ui/editions/edition-imports-2015.rs
@@ -0,0 +1,26 @@
+// edition:2015
+// compile-flags:--extern absolute
+// aux-build:edition-imports-2018.rs
+// aux-build:absolute.rs
+
+#[macro_use]
+extern crate edition_imports_2018;
+
+mod check {
+    mod import {
+        pub struct Path;
+    }
+
+    gen_imports!(); // OK
+
+    fn check() {
+        Path;
+        LinkedList::<u8>::new();
+    }
+}
+
+mod check_glob {
+    gen_glob!(); //~ ERROR cannot glob-import all possible crates
+}
+
+fn main() {}
diff --git a/src/test/ui/editions/edition-imports-2015.stderr b/src/test/ui/editions/edition-imports-2015.stderr
new file mode 100644
index 0000000..4aba532
--- /dev/null
+++ b/src/test/ui/editions/edition-imports-2015.stderr
@@ -0,0 +1,10 @@
+error: cannot glob-import all possible crates
+  --> $DIR/edition-imports-2015.rs:23:5
+   |
+LL |     gen_glob!();
+   |     ^^^^^^^^^^^^
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/editions/edition-imports-2018.rs b/src/test/ui/editions/edition-imports-2018.rs
new file mode 100644
index 0000000..dcdbf0d
--- /dev/null
+++ b/src/test/ui/editions/edition-imports-2018.rs
@@ -0,0 +1,27 @@
+// edition:2018
+// aux-build:edition-imports-2015.rs
+
+#[macro_use]
+extern crate edition_imports_2015;
+
+mod import {
+    pub struct Path;
+}
+mod absolute {
+    pub struct Path;
+}
+
+mod check {
+    gen_imports!(); // OK
+
+    fn check() {
+        Path;
+        LinkedList::<u8>::new();
+    }
+}
+
+mod check_glob {
+    gen_glob!(); //~ ERROR cannot glob-import all possible crates
+}
+
+fn main() {}
diff --git a/src/test/ui/editions/edition-imports-2018.stderr b/src/test/ui/editions/edition-imports-2018.stderr
new file mode 100644
index 0000000..6ef49b6
--- /dev/null
+++ b/src/test/ui/editions/edition-imports-2018.stderr
@@ -0,0 +1,10 @@
+error: cannot glob-import all possible crates
+  --> $DIR/edition-imports-2018.rs:24:5
+   |
+LL |     gen_glob!();
+   |     ^^^^^^^^^^^^
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.rs b/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.rs
new file mode 100644
index 0000000..940b0c3
--- /dev/null
+++ b/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.rs
@@ -0,0 +1,20 @@
+// compile-pass
+// edition:2018
+// compile-flags:--extern edition_imports_2015
+// aux-build:edition-imports-2015.rs
+
+mod edition_imports_2015 {
+    pub struct Path;
+}
+
+pub struct Ambiguous {}
+
+mod check {
+    pub struct Ambiguous {}
+
+    fn check() {
+        edition_imports_2015::gen_ambiguous!(); // OK
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/editions/edition-imports-virtual-2015-gated.rs b/src/test/ui/editions/edition-imports-virtual-2015-gated.rs
new file mode 100644
index 0000000..634d3e9
--- /dev/null
+++ b/src/test/ui/editions/edition-imports-virtual-2015-gated.rs
@@ -0,0 +1,11 @@
+// edition:2018
+// aux-build:edition-imports-2015.rs
+
+#[macro_use]
+extern crate edition_imports_2015;
+
+mod check {
+    gen_gated!(); //~ ERROR unresolved import `E`
+}
+
+fn main() {}
diff --git a/src/test/ui/editions/edition-imports-virtual-2015-gated.stderr b/src/test/ui/editions/edition-imports-virtual-2015-gated.stderr
new file mode 100644
index 0000000..e6d0f18
--- /dev/null
+++ b/src/test/ui/editions/edition-imports-virtual-2015-gated.stderr
@@ -0,0 +1,11 @@
+error[E0432]: unresolved import `E`
+  --> $DIR/edition-imports-virtual-2015-gated.rs:8:5
+   |
+LL |     gen_gated!();
+   |     ^^^^^^^^^^^^^ could not find `E` in `{{root}}`
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/editions/edition-keywords-2015-2015-expansion.rs b/src/test/ui/editions/edition-keywords-2015-2015-expansion.rs
new file mode 100644
index 0000000..c3757ab
--- /dev/null
+++ b/src/test/ui/editions/edition-keywords-2015-2015-expansion.rs
@@ -0,0 +1,17 @@
+// edition:2015
+// aux-build:edition-kw-macro-2015.rs
+// compile-pass
+
+#![allow(keyword_idents)]
+
+#[macro_use]
+extern crate edition_kw_macro_2015;
+
+mod one_async {
+    produces_async! {} // OK
+}
+mod two_async {
+    produces_async_raw! {} // OK
+}
+
+fn main() {}
diff --git a/src/test/ui/editions/edition-keywords-2015-2015-parsing.rs b/src/test/ui/editions/edition-keywords-2015-2015-parsing.rs
new file mode 100644
index 0000000..d1752a7
--- /dev/null
+++ b/src/test/ui/editions/edition-keywords-2015-2015-parsing.rs
@@ -0,0 +1,26 @@
+// edition:2015
+// aux-build:edition-kw-macro-2015.rs
+
+#[macro_use]
+extern crate edition_kw_macro_2015;
+
+mod module {
+    pub fn async() {}
+}
+
+pub fn check_async() {
+    let mut async = 1; // OK
+    let mut r#async = 1; // OK
+
+    r#async = consumes_async!(async); // OK
+    r#async = consumes_async!(r#async); //~ ERROR no rules expected the token `r#async`
+    r#async = consumes_async_raw!(async); //~ ERROR no rules expected the token `async`
+    r#async = consumes_async_raw!(r#async); // OK
+
+    if passes_ident!(async) == 1 {} // OK
+    if passes_ident!(r#async) == 1 {} // OK
+    module::async(); // OK
+    module::r#async(); // OK
+}
+
+fn main() {}
diff --git a/src/test/ui/editions/edition-keywords-2015-2015-parsing.stderr b/src/test/ui/editions/edition-keywords-2015-2015-parsing.stderr
new file mode 100644
index 0000000..3435fdf
--- /dev/null
+++ b/src/test/ui/editions/edition-keywords-2015-2015-parsing.stderr
@@ -0,0 +1,14 @@
+error: no rules expected the token `r#async`
+  --> $DIR/edition-keywords-2015-2015-parsing.rs:16:31
+   |
+LL |     r#async = consumes_async!(r#async);
+   |                               ^^^^^^^ no rules expected this token in macro call
+
+error: no rules expected the token `async`
+  --> $DIR/edition-keywords-2015-2015-parsing.rs:17:35
+   |
+LL |     r#async = consumes_async_raw!(async);
+   |                                   ^^^^^ no rules expected this token in macro call
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/editions/edition-keywords-2015-2018-expansion.rs b/src/test/ui/editions/edition-keywords-2015-2018-expansion.rs
new file mode 100644
index 0000000..2684c8e
--- /dev/null
+++ b/src/test/ui/editions/edition-keywords-2015-2018-expansion.rs
@@ -0,0 +1,14 @@
+// edition:2015
+// aux-build:edition-kw-macro-2018.rs
+
+#[macro_use]
+extern crate edition_kw_macro_2018;
+
+mod one_async {
+    produces_async! {} //~ ERROR expected identifier, found reserved keyword
+}
+mod two_async {
+    produces_async_raw! {} // OK
+}
+
+fn main() {}
diff --git a/src/test/ui/editions/edition-keywords-2015-2018-expansion.stderr b/src/test/ui/editions/edition-keywords-2015-2018-expansion.stderr
new file mode 100644
index 0000000..9724f78
--- /dev/null
+++ b/src/test/ui/editions/edition-keywords-2015-2018-expansion.stderr
@@ -0,0 +1,14 @@
+error: expected identifier, found reserved keyword `async`
+  --> $DIR/edition-keywords-2015-2018-expansion.rs:8:5
+   |
+LL |     produces_async! {}
+   |     ^^^^^^^^^^^^^^^^^^ expected identifier, found reserved keyword
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+help: you can escape reserved keywords to use them as identifiers
+   |
+LL | (  ) => ( pub fn r#async (  ) {  } )
+   |                  ^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/editions/edition-keywords-2015-2018-parsing.rs b/src/test/ui/editions/edition-keywords-2015-2018-parsing.rs
new file mode 100644
index 0000000..44455f4
--- /dev/null
+++ b/src/test/ui/editions/edition-keywords-2015-2018-parsing.rs
@@ -0,0 +1,26 @@
+// edition:2015
+// aux-build:edition-kw-macro-2018.rs
+
+#[macro_use]
+extern crate edition_kw_macro_2018;
+
+mod module {
+    pub fn async() {}
+}
+
+pub fn check_async() {
+    let mut async = 1; // OK
+    let mut r#async = 1; // OK
+
+    r#async = consumes_async!(async); // OK
+    r#async = consumes_async!(r#async); //~ ERROR no rules expected the token `r#async`
+    r#async = consumes_async_raw!(async); //~ ERROR no rules expected the token `async`
+    r#async = consumes_async_raw!(r#async); // OK
+
+    if passes_ident!(async) == 1 {} // OK
+    if passes_ident!(r#async) == 1 {} // OK
+    module::async(); // OK
+    module::r#async(); // OK
+}
+
+fn main() {}
diff --git a/src/test/ui/editions/edition-keywords-2015-2018-parsing.stderr b/src/test/ui/editions/edition-keywords-2015-2018-parsing.stderr
new file mode 100644
index 0000000..6e86d74
--- /dev/null
+++ b/src/test/ui/editions/edition-keywords-2015-2018-parsing.stderr
@@ -0,0 +1,14 @@
+error: no rules expected the token `r#async`
+  --> $DIR/edition-keywords-2015-2018-parsing.rs:16:31
+   |
+LL |     r#async = consumes_async!(r#async);
+   |                               ^^^^^^^ no rules expected this token in macro call
+
+error: no rules expected the token `async`
+  --> $DIR/edition-keywords-2015-2018-parsing.rs:17:35
+   |
+LL |     r#async = consumes_async_raw!(async);
+   |                                   ^^^^^ no rules expected this token in macro call
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/editions/edition-keywords-2018-2015-expansion.rs b/src/test/ui/editions/edition-keywords-2018-2015-expansion.rs
new file mode 100644
index 0000000..6a30c49
--- /dev/null
+++ b/src/test/ui/editions/edition-keywords-2018-2015-expansion.rs
@@ -0,0 +1,17 @@
+// edition:2018
+// aux-build:edition-kw-macro-2015.rs
+// compile-pass
+
+#![allow(keyword_idents)]
+
+#[macro_use]
+extern crate edition_kw_macro_2015;
+
+mod one_async {
+    produces_async! {} // OK
+}
+mod two_async {
+    produces_async_raw! {} // OK
+}
+
+fn main() {}
diff --git a/src/test/ui/editions/edition-keywords-2018-2015-parsing.rs b/src/test/ui/editions/edition-keywords-2018-2015-parsing.rs
new file mode 100644
index 0000000..fb8e0cd
--- /dev/null
+++ b/src/test/ui/editions/edition-keywords-2018-2015-parsing.rs
@@ -0,0 +1,20 @@
+// edition:2018
+// aux-build:edition-kw-macro-2015.rs
+
+#[macro_use]
+extern crate edition_kw_macro_2015;
+
+pub fn check_async() {
+    let mut async = 1; //~ ERROR expected identifier, found reserved keyword `async`
+    let mut r#async = 1; // OK
+
+    r#async = consumes_async!(async); // OK
+    r#async = consumes_async!(r#async); //~ ERROR no rules expected the token `r#async`
+    r#async = consumes_async_raw!(async); //~ ERROR no rules expected the token `async`
+    r#async = consumes_async_raw!(r#async); // OK
+
+    if passes_ident!(async) == 1 {}
+    if passes_ident!(r#async) == 1 {} // OK
+    module::async(); //~ ERROR expected identifier, found reserved keyword `async`
+    module::r#async(); // OK
+}
diff --git a/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr b/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr
new file mode 100644
index 0000000..0d8850c
--- /dev/null
+++ b/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr
@@ -0,0 +1,45 @@
+error: expected identifier, found reserved keyword `async`
+  --> $DIR/edition-keywords-2018-2015-parsing.rs:8:13
+   |
+LL |     let mut async = 1;
+   |             ^^^^^ expected identifier, found reserved keyword
+help: you can escape reserved keywords to use them as identifiers
+   |
+LL |     let mut r#async = 1;
+   |             ^^^^^^^
+
+error: expected identifier, found reserved keyword `async`
+  --> $DIR/edition-keywords-2018-2015-parsing.rs:18:13
+   |
+LL |     module::async();
+   |             ^^^^^ expected identifier, found reserved keyword
+help: you can escape reserved keywords to use them as identifiers
+   |
+LL |     module::r#async();
+   |             ^^^^^^^
+
+error: no rules expected the token `r#async`
+  --> $DIR/edition-keywords-2018-2015-parsing.rs:12:31
+   |
+LL |     r#async = consumes_async!(r#async);
+   |                               ^^^^^^^ no rules expected this token in macro call
+
+error: no rules expected the token `async`
+  --> $DIR/edition-keywords-2018-2015-parsing.rs:13:35
+   |
+LL |     r#async = consumes_async_raw!(async);
+   |                                   ^^^^^ no rules expected this token in macro call
+
+error: macro expansion ends with an incomplete expression: expected one of `move`, `|`, or `||`
+  --> <::edition_kw_macro_2015::passes_ident macros>:1:25
+   |
+LL | ( $ i : ident ) => ( $ i )
+   |                         ^ expected one of `move`, `|`, or `||` here
+   | 
+  ::: $DIR/edition-keywords-2018-2015-parsing.rs:16:8
+   |
+LL |     if passes_ident!(async) == 1 {}
+   |        -------------------- in this macro invocation
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/ui/editions/edition-keywords-2018-2018-expansion.rs b/src/test/ui/editions/edition-keywords-2018-2018-expansion.rs
new file mode 100644
index 0000000..6f76655
--- /dev/null
+++ b/src/test/ui/editions/edition-keywords-2018-2018-expansion.rs
@@ -0,0 +1,14 @@
+// edition:2018
+// aux-build:edition-kw-macro-2018.rs
+
+#[macro_use]
+extern crate edition_kw_macro_2018;
+
+mod one_async {
+    produces_async! {} //~ ERROR expected identifier, found reserved keyword `async`
+}
+mod two_async {
+    produces_async_raw! {} // OK
+}
+
+fn main() {}
diff --git a/src/test/ui/editions/edition-keywords-2018-2018-expansion.stderr b/src/test/ui/editions/edition-keywords-2018-2018-expansion.stderr
new file mode 100644
index 0000000..ab601c8
--- /dev/null
+++ b/src/test/ui/editions/edition-keywords-2018-2018-expansion.stderr
@@ -0,0 +1,14 @@
+error: expected identifier, found reserved keyword `async`
+  --> $DIR/edition-keywords-2018-2018-expansion.rs:8:5
+   |
+LL |     produces_async! {}
+   |     ^^^^^^^^^^^^^^^^^^ expected identifier, found reserved keyword
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+help: you can escape reserved keywords to use them as identifiers
+   |
+LL | (  ) => ( pub fn r#async (  ) {  } )
+   |                  ^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/editions/edition-keywords-2018-2018-parsing.rs b/src/test/ui/editions/edition-keywords-2018-2018-parsing.rs
new file mode 100644
index 0000000..88cebf4
--- /dev/null
+++ b/src/test/ui/editions/edition-keywords-2018-2018-parsing.rs
@@ -0,0 +1,20 @@
+// edition:2018
+// aux-build:edition-kw-macro-2018.rs
+
+#[macro_use]
+extern crate edition_kw_macro_2018;
+
+pub fn check_async() {
+    let mut async = 1; //~ ERROR expected identifier, found reserved keyword `async`
+    let mut r#async = 1; // OK
+
+    r#async = consumes_async!(async); // OK
+    r#async = consumes_async!(r#async); //~ ERROR no rules expected the token `r#async`
+    r#async = consumes_async_raw!(async); //~ ERROR no rules expected the token `async`
+    r#async = consumes_async_raw!(r#async); // OK
+
+    if passes_ident!(async) == 1 {}
+    if passes_ident!(r#async) == 1 {} // OK
+    module::async(); //~ ERROR expected identifier, found reserved keyword `async`
+    module::r#async(); // OK
+}
diff --git a/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr b/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr
new file mode 100644
index 0000000..0604b60
--- /dev/null
+++ b/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr
@@ -0,0 +1,45 @@
+error: expected identifier, found reserved keyword `async`
+  --> $DIR/edition-keywords-2018-2018-parsing.rs:8:13
+   |
+LL |     let mut async = 1;
+   |             ^^^^^ expected identifier, found reserved keyword
+help: you can escape reserved keywords to use them as identifiers
+   |
+LL |     let mut r#async = 1;
+   |             ^^^^^^^
+
+error: expected identifier, found reserved keyword `async`
+  --> $DIR/edition-keywords-2018-2018-parsing.rs:18:13
+   |
+LL |     module::async();
+   |             ^^^^^ expected identifier, found reserved keyword
+help: you can escape reserved keywords to use them as identifiers
+   |
+LL |     module::r#async();
+   |             ^^^^^^^
+
+error: no rules expected the token `r#async`
+  --> $DIR/edition-keywords-2018-2018-parsing.rs:12:31
+   |
+LL |     r#async = consumes_async!(r#async);
+   |                               ^^^^^^^ no rules expected this token in macro call
+
+error: no rules expected the token `async`
+  --> $DIR/edition-keywords-2018-2018-parsing.rs:13:35
+   |
+LL |     r#async = consumes_async_raw!(async);
+   |                                   ^^^^^ no rules expected this token in macro call
+
+error: macro expansion ends with an incomplete expression: expected one of `move`, `|`, or `||`
+  --> <::edition_kw_macro_2018::passes_ident macros>:1:25
+   |
+LL | ( $ i : ident ) => ( $ i )
+   |                         ^ expected one of `move`, `|`, or `||` here
+   | 
+  ::: $DIR/edition-keywords-2018-2018-parsing.rs:16:8
+   |
+LL |     if passes_ident!(async) == 1 {}
+   |        -------------------- in this macro invocation
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/ui/editions/edition-raw-pointer-method-2015.rs b/src/test/ui/editions/edition-raw-pointer-method-2015.rs
new file mode 100644
index 0000000..a538bca
--- /dev/null
+++ b/src/test/ui/editions/edition-raw-pointer-method-2015.rs
@@ -0,0 +1,13 @@
+// ignore-tidy-linelength
+// edition:2015
+
+// tests that editions work with the tyvar warning-turned-error
+
+#[deny(warnings)]
+fn main() {
+    let x = 0;
+    let y = &x as *const _;
+    let _ = y.is_null();
+    //~^ error: type annotations needed [tyvar_behind_raw_pointer]
+    //~^^ warning: this was previously accepted
+}
diff --git a/src/test/ui/editions/edition-raw-pointer-method-2015.stderr b/src/test/ui/editions/edition-raw-pointer-method-2015.stderr
new file mode 100644
index 0000000..deea6a7
--- /dev/null
+++ b/src/test/ui/editions/edition-raw-pointer-method-2015.stderr
@@ -0,0 +1,17 @@
+error: type annotations needed
+  --> $DIR/edition-raw-pointer-method-2015.rs:10:15
+   |
+LL |     let _ = y.is_null();
+   |               ^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/edition-raw-pointer-method-2015.rs:6:8
+   |
+LL | #[deny(warnings)]
+   |        ^^^^^^^^
+   = note: #[deny(tyvar_behind_raw_pointer)] implied by #[deny(warnings)]
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #46906 <https://github.com/rust-lang/rust/issues/46906>
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/editions/edition-raw-pointer-method-2018.rs b/src/test/ui/editions/edition-raw-pointer-method-2018.rs
new file mode 100644
index 0000000..eabab5e
--- /dev/null
+++ b/src/test/ui/editions/edition-raw-pointer-method-2018.rs
@@ -0,0 +1,12 @@
+// ignore-tidy-linelength
+// edition:2018
+
+// tests that editions work with the tyvar warning-turned-error
+
+#[deny(warnings)]
+fn main() {
+    let x = 0;
+    let y = &x as *const _;
+    let _ = y.is_null();
+    //~^ error: the type of this value must be known to call a method on a raw pointer on it [E0699]
+}
diff --git a/src/test/ui/editions/edition-raw-pointer-method-2018.stderr b/src/test/ui/editions/edition-raw-pointer-method-2018.stderr
new file mode 100644
index 0000000..03e7f3a
--- /dev/null
+++ b/src/test/ui/editions/edition-raw-pointer-method-2018.stderr
@@ -0,0 +1,9 @@
+error[E0699]: the type of this value must be known to call a method on a raw pointer on it
+  --> $DIR/edition-raw-pointer-method-2018.rs:10:15
+   |
+LL |     let _ = y.is_null();
+   |               ^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0699`.
diff --git a/src/test/ui/elide-errors-on-mismatched-tuple.rs b/src/test/ui/elide-errors-on-mismatched-tuple.rs
new file mode 100644
index 0000000..e68358f
--- /dev/null
+++ b/src/test/ui/elide-errors-on-mismatched-tuple.rs
@@ -0,0 +1,18 @@
+// Hide irrelevant E0277 errors (#50333)
+
+trait T {}
+
+struct A;
+impl T for A {}
+impl A {
+    fn new() -> Self {
+        Self {}
+    }
+}
+
+fn main() {
+    let (a, b, c) = (A::new(), A::new()); // This tuple is 2 elements, should be three
+    //~^ ERROR mismatched types
+    let ts: Vec<&T> = vec![&a, &b, &c];
+    // There is no E0277 error above, as `a`, `b` and `c` are `TyErr`
+}
diff --git a/src/test/ui/elide-errors-on-mismatched-tuple.stderr b/src/test/ui/elide-errors-on-mismatched-tuple.stderr
new file mode 100644
index 0000000..1ef9d7a
--- /dev/null
+++ b/src/test/ui/elide-errors-on-mismatched-tuple.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/elide-errors-on-mismatched-tuple.rs:14:9
+   |
+LL |     let (a, b, c) = (A::new(), A::new()); // This tuple is 2 elements, should be three
+   |         ^^^^^^^^^ expected a tuple with 2 elements, found one with 3 elements
+   |
+   = note: expected type `(A, A)`
+              found type `(_, _, _)`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/elided-test.rs b/src/test/ui/elided-test.rs
new file mode 100644
index 0000000..b3f4446
--- /dev/null
+++ b/src/test/ui/elided-test.rs
@@ -0,0 +1,7 @@
+// error-pattern: `main` function not found
+
+// Since we're not compiling a test runner this function should be elided
+// and the build will fail because main doesn't exist
+#[test]
+fn main() {
+}
diff --git a/src/test/ui/elided-test.stderr b/src/test/ui/elided-test.stderr
new file mode 100644
index 0000000..d22eee4
--- /dev/null
+++ b/src/test/ui/elided-test.stderr
@@ -0,0 +1,7 @@
+error[E0601]: `main` function not found in crate `elided_test`
+   |
+   = note: consider adding a `main` function to `$DIR/elided-test.rs`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0601`.
diff --git a/src/test/ui/empty/auxiliary/empty-struct.rs b/src/test/ui/empty/auxiliary/empty-struct.rs
new file mode 100644
index 0000000..3fb40f6
--- /dev/null
+++ b/src/test/ui/empty/auxiliary/empty-struct.rs
@@ -0,0 +1,9 @@
+pub struct XEmpty1 {}
+pub struct XEmpty2;
+pub struct XEmpty6();
+
+pub enum XE {
+    XEmpty3 {},
+    XEmpty4,
+    XEmpty5(),
+}
diff --git a/src/test/ui/empty/auxiliary/two_macros.rs b/src/test/ui/empty/auxiliary/two_macros.rs
new file mode 100644
index 0000000..2330c75
--- /dev/null
+++ b/src/test/ui/empty/auxiliary/two_macros.rs
@@ -0,0 +1,5 @@
+#[macro_export]
+macro_rules! macro_one { () => ("one") }
+
+#[macro_export]
+macro_rules! macro_two { () => ("two") }
diff --git a/src/test/ui/empty/empty-comment.rs b/src/test/ui/empty/empty-comment.rs
new file mode 100644
index 0000000..174274d
--- /dev/null
+++ b/src/test/ui/empty/empty-comment.rs
@@ -0,0 +1,11 @@
+// `/**/` was previously regarded as a doc comment because it starts with `/**` and ends with `*/`.
+// This could break some internal logic that assumes the length of a doc comment is at least 5,
+// leading to an ICE.
+
+macro_rules! one_arg_macro {
+    ($fmt:expr) => (print!(concat!($fmt, "\n")));
+}
+
+fn main() {
+    one_arg_macro!(/**/); //~ ERROR unexpected end
+}
diff --git a/src/test/ui/empty/empty-comment.stderr b/src/test/ui/empty/empty-comment.stderr
new file mode 100644
index 0000000..116cc83
--- /dev/null
+++ b/src/test/ui/empty/empty-comment.stderr
@@ -0,0 +1,11 @@
+error: unexpected end of macro invocation
+  --> $DIR/empty-comment.rs:10:5
+   |
+LL | macro_rules! one_arg_macro {
+   | -------------------------- when calling this macro
+...
+LL |     one_arg_macro!(/**/);
+   |     ^^^^^^^^^^^^^^^^^^^^^ missing tokens in macro arguments
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/empty/empty-linkname.rs b/src/test/ui/empty/empty-linkname.rs
new file mode 100644
index 0000000..79895ab
--- /dev/null
+++ b/src/test/ui/empty/empty-linkname.rs
@@ -0,0 +1,5 @@
+#[link(name = "")] //~ ERROR: given with empty name
+extern {
+}
+
+fn main() {}
diff --git a/src/test/ui/empty/empty-linkname.stderr b/src/test/ui/empty/empty-linkname.stderr
new file mode 100644
index 0000000..df41cb8
--- /dev/null
+++ b/src/test/ui/empty/empty-linkname.stderr
@@ -0,0 +1,9 @@
+error[E0454]: #[link(name = "")] given with empty name
+  --> $DIR/empty-linkname.rs:1:1
+   |
+LL | #[link(name = "")]
+   | ^^^^^^^^^^^^^^^^^^ empty name given
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0454`.
diff --git a/src/test/ui/empty/empty-macro-use.rs b/src/test/ui/empty/empty-macro-use.rs
new file mode 100644
index 0000000..846004e
--- /dev/null
+++ b/src/test/ui/empty/empty-macro-use.rs
@@ -0,0 +1,9 @@
+// aux-build:two_macros.rs
+
+#[macro_use()]
+extern crate two_macros;
+
+pub fn main() {
+    macro_two!();
+    //~^ ERROR cannot find macro
+}
diff --git a/src/test/ui/empty/empty-macro-use.stderr b/src/test/ui/empty/empty-macro-use.stderr
new file mode 100644
index 0000000..1630041
--- /dev/null
+++ b/src/test/ui/empty/empty-macro-use.stderr
@@ -0,0 +1,8 @@
+error: cannot find macro `macro_two!` in this scope
+  --> $DIR/empty-macro-use.rs:7:5
+   |
+LL |     macro_two!();
+   |     ^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/empty/empty-never-array.rs b/src/test/ui/empty/empty-never-array.rs
new file mode 100644
index 0000000..01b9913
--- /dev/null
+++ b/src/test/ui/empty/empty-never-array.rs
@@ -0,0 +1,17 @@
+#![feature(never_type)]
+
+enum Helper<T, U> {
+    T(T, [!; 0]),
+    #[allow(dead_code)]
+    U(U),
+}
+
+fn transmute<T, U>(t: T) -> U {
+    let Helper::U(u) = Helper::T(t, []);
+    //~^ ERROR refutable pattern in local binding: `T(_, _)` not covered
+    u
+}
+
+fn main() {
+    println!("{:?}", transmute::<&str, (*const u8, u64)>("type safety"));
+}
diff --git a/src/test/ui/empty/empty-never-array.stderr b/src/test/ui/empty/empty-never-array.stderr
new file mode 100644
index 0000000..f1be4a6
--- /dev/null
+++ b/src/test/ui/empty/empty-never-array.stderr
@@ -0,0 +1,16 @@
+error[E0005]: refutable pattern in local binding: `T(_, _)` not covered
+  --> $DIR/empty-never-array.rs:10:9
+   |
+LL | / enum Helper<T, U> {
+LL | |     T(T, [!; 0]),
+LL | |     #[allow(dead_code)]
+LL | |     U(U),
+LL | | }
+   | |_- `Helper<T, U>` defined here
+...
+LL |       let Helper::U(u) = Helper::T(t, []);
+   |           ^^^^^^^^^^^^ pattern `T(_, _)` not covered
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0005`.
diff --git a/src/test/ui/empty/empty-struct-braces-expr.rs b/src/test/ui/empty/empty-struct-braces-expr.rs
new file mode 100644
index 0000000..2f2f41a
--- /dev/null
+++ b/src/test/ui/empty/empty-struct-braces-expr.rs
@@ -0,0 +1,24 @@
+// Can't use empty braced struct as constant or constructor function
+
+// aux-build:empty-struct.rs
+
+extern crate empty_struct;
+use empty_struct::*;
+
+struct Empty1 {}
+
+enum E {
+    Empty3 {}
+}
+
+fn main() {
+    let e1 = Empty1; //~ ERROR expected value, found struct `Empty1`
+    let e1 = Empty1(); //~ ERROR expected function, found struct `Empty1`
+    let e3 = E::Empty3; //~ ERROR expected value, found struct variant `E::Empty3`
+    let e3 = E::Empty3(); //~ ERROR expected function, found struct variant `E::Empty3`
+
+    let xe1 = XEmpty1; //~ ERROR expected value, found struct `XEmpty1`
+    let xe1 = XEmpty1(); //~ ERROR expected function, found struct `XEmpty1`
+    let xe3 = XE::Empty3; //~ ERROR no variant named `Empty3` found for type
+    let xe3 = XE::Empty3(); //~ ERROR no variant named `Empty3` found for type
+}
diff --git a/src/test/ui/empty/empty-struct-braces-expr.stderr b/src/test/ui/empty/empty-struct-braces-expr.stderr
new file mode 100644
index 0000000..57c8c1c
--- /dev/null
+++ b/src/test/ui/empty/empty-struct-braces-expr.stderr
@@ -0,0 +1,70 @@
+error[E0423]: expected value, found struct `Empty1`
+  --> $DIR/empty-struct-braces-expr.rs:15:14
+   |
+LL |     let e1 = Empty1;
+   |              ^^^^^^
+   |              |
+   |              did you mean `Empty1 { /* fields */ }`?
+   |              help: a unit struct with a similar name exists: `XEmpty2`
+
+error[E0423]: expected function, found struct `Empty1`
+  --> $DIR/empty-struct-braces-expr.rs:16:14
+   |
+LL |     let e1 = Empty1();
+   |              ^^^^^^
+   |              |
+   |              did you mean `Empty1 { /* fields */ }`?
+   |              help: a unit struct with a similar name exists: `XEmpty2`
+
+error[E0423]: expected value, found struct variant `E::Empty3`
+  --> $DIR/empty-struct-braces-expr.rs:17:14
+   |
+LL |     let e3 = E::Empty3;
+   |              ^^^^^^^^^ did you mean `E::Empty3 { /* fields */ }`?
+
+error[E0423]: expected function, found struct variant `E::Empty3`
+  --> $DIR/empty-struct-braces-expr.rs:18:14
+   |
+LL |     let e3 = E::Empty3();
+   |              ^^^^^^^^^ did you mean `E::Empty3 { /* fields */ }`?
+
+error[E0423]: expected value, found struct `XEmpty1`
+  --> $DIR/empty-struct-braces-expr.rs:20:15
+   |
+LL |     let xe1 = XEmpty1;
+   |               ^^^^^^^
+   |               |
+   |               did you mean `XEmpty1 { /* fields */ }`?
+   |               help: a unit struct with a similar name exists: `XEmpty2`
+
+error[E0423]: expected function, found struct `XEmpty1`
+  --> $DIR/empty-struct-braces-expr.rs:21:15
+   |
+LL |     let xe1 = XEmpty1();
+   |               ^^^^^^^
+   |               |
+   |               did you mean `XEmpty1 { /* fields */ }`?
+   |               help: a unit struct with a similar name exists: `XEmpty2`
+
+error[E0599]: no variant named `Empty3` found for type `empty_struct::XE` in the current scope
+  --> $DIR/empty-struct-braces-expr.rs:22:19
+   |
+LL |     let xe3 = XE::Empty3;
+   |                   ^^^^^^
+   |                   |
+   |                   variant not found in `empty_struct::XE`
+   |                   help: did you mean: `XEmpty3`
+
+error[E0599]: no variant named `Empty3` found for type `empty_struct::XE` in the current scope
+  --> $DIR/empty-struct-braces-expr.rs:23:19
+   |
+LL |     let xe3 = XE::Empty3();
+   |                   ^^^^^^
+   |                   |
+   |                   variant not found in `empty_struct::XE`
+   |                   help: did you mean: `XEmpty3`
+
+error: aborting due to 8 previous errors
+
+Some errors occurred: E0423, E0599.
+For more information about an error, try `rustc --explain E0423`.
diff --git a/src/test/ui/empty/empty-struct-braces-pat-1.rs b/src/test/ui/empty/empty-struct-braces-pat-1.rs
new file mode 100644
index 0000000..8106232
--- /dev/null
+++ b/src/test/ui/empty/empty-struct-braces-pat-1.rs
@@ -0,0 +1,34 @@
+// Can't use empty braced struct as constant pattern
+
+// aux-build:empty-struct.rs
+
+extern crate empty_struct;
+use empty_struct::*;
+
+struct Empty1 {}
+
+enum E {
+    Empty3 {}
+}
+
+fn main() {
+    let e1 = Empty1 {};
+    let e3 = E::Empty3 {};
+    let xe1 = XEmpty1 {};
+    let xe3 = XE::XEmpty3 {};
+
+    match e1 {
+        Empty1 => () // Not an error, `Empty1` is interpreted as a new binding
+    }
+    match e3 {
+        E::Empty3 => ()
+        //~^ ERROR expected unit struct/variant or constant, found struct variant `E::Empty3`
+    }
+    match xe1 {
+        XEmpty1 => () // Not an error, `XEmpty1` is interpreted as a new binding
+    }
+    match xe3 {
+        XE::XEmpty3 => ()
+        //~^ ERROR expected unit struct/variant or constant, found struct variant `XE::XEmpty3`
+    }
+}
diff --git a/src/test/ui/empty/empty-struct-braces-pat-1.stderr b/src/test/ui/empty/empty-struct-braces-pat-1.stderr
new file mode 100644
index 0000000..6c361c7
--- /dev/null
+++ b/src/test/ui/empty/empty-struct-braces-pat-1.stderr
@@ -0,0 +1,18 @@
+error[E0532]: expected unit struct/variant or constant, found struct variant `E::Empty3`
+  --> $DIR/empty-struct-braces-pat-1.rs:24:9
+   |
+LL |         E::Empty3 => ()
+   |         ^^^^^^^^^ did you mean `E::Empty3 { /* fields */ }`?
+
+error[E0532]: expected unit struct/variant or constant, found struct variant `XE::XEmpty3`
+  --> $DIR/empty-struct-braces-pat-1.rs:31:9
+   |
+LL |         XE::XEmpty3 => ()
+   |         ^^^^-------
+   |         |   |
+   |         |   help: a unit variant with a similar name exists: `XEmpty4`
+   |         did you mean `XE::XEmpty3 { /* fields */ }`?
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0532`.
diff --git a/src/test/ui/empty/empty-struct-braces-pat-2.rs b/src/test/ui/empty/empty-struct-braces-pat-2.rs
new file mode 100644
index 0000000..187d953
--- /dev/null
+++ b/src/test/ui/empty/empty-struct-braces-pat-2.rs
@@ -0,0 +1,26 @@
+// Can't use empty braced struct as enum pattern
+
+// aux-build:empty-struct.rs
+
+extern crate empty_struct;
+use empty_struct::*;
+
+struct Empty1 {}
+
+fn main() {
+    let e1 = Empty1 {};
+    let xe1 = XEmpty1 {};
+
+    match e1 {
+        Empty1() => () //~ ERROR expected tuple struct/variant, found struct `Empty1`
+    }
+    match xe1 {
+        XEmpty1() => () //~ ERROR expected tuple struct/variant, found struct `XEmpty1`
+    }
+    match e1 {
+        Empty1(..) => () //~ ERROR expected tuple struct/variant, found struct `Empty1`
+    }
+    match xe1 {
+        XEmpty1(..) => () //~ ERROR expected tuple struct/variant, found struct `XEmpty1`
+    }
+}
diff --git a/src/test/ui/empty/empty-struct-braces-pat-2.stderr b/src/test/ui/empty/empty-struct-braces-pat-2.stderr
new file mode 100644
index 0000000..12047b5
--- /dev/null
+++ b/src/test/ui/empty/empty-struct-braces-pat-2.stderr
@@ -0,0 +1,39 @@
+error[E0532]: expected tuple struct/variant, found struct `Empty1`
+  --> $DIR/empty-struct-braces-pat-2.rs:15:9
+   |
+LL |         Empty1() => ()
+   |         ^^^^^^
+   |         |
+   |         did you mean `Empty1 { /* fields */ }`?
+   |         help: a tuple struct with a similar name exists: `XEmpty6`
+
+error[E0532]: expected tuple struct/variant, found struct `XEmpty1`
+  --> $DIR/empty-struct-braces-pat-2.rs:18:9
+   |
+LL |         XEmpty1() => ()
+   |         ^^^^^^^
+   |         |
+   |         did you mean `XEmpty1 { /* fields */ }`?
+   |         help: a tuple struct with a similar name exists: `XEmpty6`
+
+error[E0532]: expected tuple struct/variant, found struct `Empty1`
+  --> $DIR/empty-struct-braces-pat-2.rs:21:9
+   |
+LL |         Empty1(..) => ()
+   |         ^^^^^^
+   |         |
+   |         did you mean `Empty1 { /* fields */ }`?
+   |         help: a tuple struct with a similar name exists: `XEmpty6`
+
+error[E0532]: expected tuple struct/variant, found struct `XEmpty1`
+  --> $DIR/empty-struct-braces-pat-2.rs:24:9
+   |
+LL |         XEmpty1(..) => ()
+   |         ^^^^^^^
+   |         |
+   |         did you mean `XEmpty1 { /* fields */ }`?
+   |         help: a tuple struct with a similar name exists: `XEmpty6`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0532`.
diff --git a/src/test/ui/empty/empty-struct-braces-pat-3.rs b/src/test/ui/empty/empty-struct-braces-pat-3.rs
new file mode 100644
index 0000000..fad28d7
--- /dev/null
+++ b/src/test/ui/empty/empty-struct-braces-pat-3.rs
@@ -0,0 +1,32 @@
+// Can't use empty braced struct as enum pattern
+
+// aux-build:empty-struct.rs
+
+extern crate empty_struct;
+use empty_struct::*;
+
+enum E {
+    Empty3 {}
+}
+
+fn main() {
+    let e3 = E::Empty3 {};
+    let xe3 = XE::XEmpty3 {};
+
+    match e3 {
+        E::Empty3() => ()
+        //~^ ERROR expected tuple struct/variant, found struct variant `E::Empty3`
+    }
+    match xe3 {
+        XE::XEmpty3() => ()
+        //~^ ERROR expected tuple struct/variant, found struct variant `XE::XEmpty3`
+    }
+    match e3 {
+        E::Empty3(..) => ()
+        //~^ ERROR expected tuple struct/variant, found struct variant `E::Empty3`
+    }
+    match xe3 {
+        XE::XEmpty3(..) => ()
+        //~^ ERROR expected tuple struct/variant, found struct variant `XE::XEmpty3
+    }
+}
diff --git a/src/test/ui/empty/empty-struct-braces-pat-3.stderr b/src/test/ui/empty/empty-struct-braces-pat-3.stderr
new file mode 100644
index 0000000..af8731b
--- /dev/null
+++ b/src/test/ui/empty/empty-struct-braces-pat-3.stderr
@@ -0,0 +1,33 @@
+error[E0532]: expected tuple struct/variant, found struct variant `E::Empty3`
+  --> $DIR/empty-struct-braces-pat-3.rs:17:9
+   |
+LL |         E::Empty3() => ()
+   |         ^^^^^^^^^ did you mean `E::Empty3 { /* fields */ }`?
+
+error[E0532]: expected tuple struct/variant, found struct variant `XE::XEmpty3`
+  --> $DIR/empty-struct-braces-pat-3.rs:21:9
+   |
+LL |         XE::XEmpty3() => ()
+   |         ^^^^-------
+   |         |   |
+   |         |   help: a tuple variant with a similar name exists: `XEmpty5`
+   |         did you mean `XE::XEmpty3 { /* fields */ }`?
+
+error[E0532]: expected tuple struct/variant, found struct variant `E::Empty3`
+  --> $DIR/empty-struct-braces-pat-3.rs:25:9
+   |
+LL |         E::Empty3(..) => ()
+   |         ^^^^^^^^^ did you mean `E::Empty3 { /* fields */ }`?
+
+error[E0532]: expected tuple struct/variant, found struct variant `XE::XEmpty3`
+  --> $DIR/empty-struct-braces-pat-3.rs:29:9
+   |
+LL |         XE::XEmpty3(..) => ()
+   |         ^^^^-------
+   |         |   |
+   |         |   help: a tuple variant with a similar name exists: `XEmpty5`
+   |         did you mean `XE::XEmpty3 { /* fields */ }`?
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0532`.
diff --git a/src/test/ui/empty/empty-struct-tuple-pat.rs b/src/test/ui/empty/empty-struct-tuple-pat.rs
new file mode 100644
index 0000000..00a4859
--- /dev/null
+++ b/src/test/ui/empty/empty-struct-tuple-pat.rs
@@ -0,0 +1,37 @@
+// Can't use unit struct as enum pattern
+
+// aux-build:empty-struct.rs
+
+extern crate empty_struct;
+use empty_struct::*;
+
+struct Empty2();
+
+enum E {
+    Empty4()
+}
+
+// remove attribute after warning cycle and promoting warnings to errors
+fn main() {
+    let e2 = Empty2();
+    let e4 = E::Empty4();
+    let xe6 = XEmpty6();
+    let xe5 = XE::XEmpty5();
+
+    match e2 {
+        Empty2 => () //~ ERROR match bindings cannot shadow tuple structs
+    }
+    match xe6 {
+        XEmpty6 => () //~ ERROR match bindings cannot shadow tuple structs
+    }
+
+    match e4 {
+        E::Empty4 => ()
+        //~^ ERROR expected unit struct/variant or constant, found tuple variant `E::Empty4`
+    }
+    match xe5 {
+        XE::XEmpty5 => (),
+        //~^ ERROR expected unit struct/variant or constant, found tuple variant `XE::XEmpty5`
+        _ => {},
+    }
+}
diff --git a/src/test/ui/empty/empty-struct-tuple-pat.stderr b/src/test/ui/empty/empty-struct-tuple-pat.stderr
new file mode 100644
index 0000000..71a8141
--- /dev/null
+++ b/src/test/ui/empty/empty-struct-tuple-pat.stderr
@@ -0,0 +1,36 @@
+error[E0530]: match bindings cannot shadow tuple structs
+  --> $DIR/empty-struct-tuple-pat.rs:22:9
+   |
+LL | struct Empty2();
+   | ---------------- the tuple struct `Empty2` is defined here
+...
+LL |         Empty2 => ()
+   |         ^^^^^^ cannot be named the same as a tuple struct
+
+error[E0530]: match bindings cannot shadow tuple structs
+  --> $DIR/empty-struct-tuple-pat.rs:25:9
+   |
+LL | use empty_struct::*;
+   |     --------------- the tuple struct `XEmpty6` is imported here
+...
+LL |         XEmpty6 => ()
+   |         ^^^^^^^ cannot be named the same as a tuple struct
+
+error[E0532]: expected unit struct/variant or constant, found tuple variant `E::Empty4`
+  --> $DIR/empty-struct-tuple-pat.rs:29:9
+   |
+LL |         E::Empty4 => ()
+   |         ^^^^^^^^^ not a unit struct/variant or constant
+
+error[E0532]: expected unit struct/variant or constant, found tuple variant `XE::XEmpty5`
+  --> $DIR/empty-struct-tuple-pat.rs:33:9
+   |
+LL |         XE::XEmpty5 => (),
+   |         ^^^^-------
+   |             |
+   |             help: a unit variant with a similar name exists: `XEmpty4`
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0530, E0532.
+For more information about an error, try `rustc --explain E0530`.
diff --git a/src/test/ui/empty/empty-struct-unit-expr.rs b/src/test/ui/empty/empty-struct-unit-expr.rs
new file mode 100644
index 0000000..b192e3a
--- /dev/null
+++ b/src/test/ui/empty/empty-struct-unit-expr.rs
@@ -0,0 +1,21 @@
+// Can't use unit struct as constructor function
+
+// aux-build:empty-struct.rs
+
+extern crate empty_struct;
+use empty_struct::*;
+
+struct Empty2;
+
+enum E {
+    Empty4
+}
+
+fn main() {
+    let e2 = Empty2(); //~ ERROR expected function, found `Empty2`
+    let e4 = E::Empty4();
+    //~^ ERROR expected function, found enum variant `E::Empty4` [E0618]
+    let xe2 = XEmpty2(); //~ ERROR expected function, found `empty_struct::XEmpty2`
+    let xe4 = XE::XEmpty4();
+    //~^ ERROR expected function, found enum variant `XE::XEmpty4` [E0618]
+}
diff --git a/src/test/ui/empty/empty-struct-unit-expr.stderr b/src/test/ui/empty/empty-struct-unit-expr.stderr
new file mode 100644
index 0000000..696eabe
--- /dev/null
+++ b/src/test/ui/empty/empty-struct-unit-expr.stderr
@@ -0,0 +1,49 @@
+error[E0618]: expected function, found `Empty2`
+  --> $DIR/empty-struct-unit-expr.rs:15:14
+   |
+LL | struct Empty2;
+   | -------------- `Empty2` defined here
+...
+LL |     let e2 = Empty2();
+   |              ^^^^^^--
+   |              |
+   |              call expression requires function
+
+error[E0618]: expected function, found enum variant `E::Empty4`
+  --> $DIR/empty-struct-unit-expr.rs:16:14
+   |
+LL |     Empty4
+   |     ------ `E::Empty4` defined here
+...
+LL |     let e4 = E::Empty4();
+   |              ^^^^^^^^^--
+   |              |
+   |              call expression requires function
+help: `E::Empty4` is a unit variant, you need to write it without the parenthesis
+   |
+LL |     let e4 = E::Empty4;
+   |              ^^^^^^^^^
+
+error[E0618]: expected function, found `empty_struct::XEmpty2`
+  --> $DIR/empty-struct-unit-expr.rs:18:15
+   |
+LL |     let xe2 = XEmpty2();
+   |               ^^^^^^^--
+   |               |
+   |               call expression requires function
+
+error[E0618]: expected function, found enum variant `XE::XEmpty4`
+  --> $DIR/empty-struct-unit-expr.rs:19:15
+   |
+LL |     let xe4 = XE::XEmpty4();
+   |               ^^^^^^^^^^^--
+   |               |
+   |               call expression requires function
+help: `XE::XEmpty4` is a unit variant, you need to write it without the parenthesis
+   |
+LL |     let xe4 = XE::XEmpty4;
+   |               ^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0618`.
diff --git a/src/test/ui/empty/empty-struct-unit-pat.rs b/src/test/ui/empty/empty-struct-unit-pat.rs
new file mode 100644
index 0000000..8a0e2f5
--- /dev/null
+++ b/src/test/ui/empty/empty-struct-unit-pat.rs
@@ -0,0 +1,49 @@
+// Can't use unit struct as tuple struct pattern
+
+// aux-build:empty-struct.rs
+
+extern crate empty_struct;
+use empty_struct::*;
+
+struct Empty2;
+
+enum E {
+    Empty4
+}
+
+fn main() {
+    let e2 = Empty2;
+    let e4 = E::Empty4;
+    let xe2 = XEmpty2;
+    let xe4 = XE::XEmpty4;
+
+    match e2 {
+        Empty2() => () //~ ERROR expected tuple struct/variant, found unit struct `Empty2`
+    }
+    match xe2 {
+        XEmpty2() => () //~ ERROR expected tuple struct/variant, found unit struct `XEmpty2`
+    }
+    match e2 {
+        Empty2(..) => () //~ ERROR expected tuple struct/variant, found unit struct `Empty2`
+    }
+    match xe2 {
+        XEmpty2(..) => () //~ ERROR expected tuple struct/variant, found unit struct `XEmpty2`
+    }
+
+    match e4 {
+        E::Empty4() => () //~ ERROR expected tuple struct/variant, found unit variant `E::Empty4`
+    }
+    match xe4 {
+        XE::XEmpty4() => (),
+        //~^ ERROR expected tuple struct/variant, found unit variant `XE::XEmpty4`
+        _ => {},
+    }
+    match e4 {
+        E::Empty4(..) => () //~ ERROR expected tuple struct/variant, found unit variant `E::Empty4`
+    }
+    match xe4 {
+        XE::XEmpty4(..) => (),
+        //~^ ERROR expected tuple struct/variant, found unit variant `XE::XEmpty4`
+        _ => {},
+    }
+}
diff --git a/src/test/ui/empty/empty-struct-unit-pat.stderr b/src/test/ui/empty/empty-struct-unit-pat.stderr
new file mode 100644
index 0000000..268fc7a
--- /dev/null
+++ b/src/test/ui/empty/empty-struct-unit-pat.stderr
@@ -0,0 +1,55 @@
+error[E0532]: expected tuple struct/variant, found unit struct `Empty2`
+  --> $DIR/empty-struct-unit-pat.rs:21:9
+   |
+LL |         Empty2() => ()
+   |         ^^^^^^ help: a tuple struct with a similar name exists: `XEmpty6`
+
+error[E0532]: expected tuple struct/variant, found unit struct `XEmpty2`
+  --> $DIR/empty-struct-unit-pat.rs:24:9
+   |
+LL |         XEmpty2() => ()
+   |         ^^^^^^^ help: a tuple struct with a similar name exists: `XEmpty6`
+
+error[E0532]: expected tuple struct/variant, found unit struct `Empty2`
+  --> $DIR/empty-struct-unit-pat.rs:27:9
+   |
+LL |         Empty2(..) => ()
+   |         ^^^^^^ help: a tuple struct with a similar name exists: `XEmpty6`
+
+error[E0532]: expected tuple struct/variant, found unit struct `XEmpty2`
+  --> $DIR/empty-struct-unit-pat.rs:30:9
+   |
+LL |         XEmpty2(..) => ()
+   |         ^^^^^^^ help: a tuple struct with a similar name exists: `XEmpty6`
+
+error[E0532]: expected tuple struct/variant, found unit variant `E::Empty4`
+  --> $DIR/empty-struct-unit-pat.rs:34:9
+   |
+LL |         E::Empty4() => ()
+   |         ^^^^^^^^^ not a tuple struct/variant
+
+error[E0532]: expected tuple struct/variant, found unit variant `XE::XEmpty4`
+  --> $DIR/empty-struct-unit-pat.rs:37:9
+   |
+LL |         XE::XEmpty4() => (),
+   |         ^^^^-------
+   |             |
+   |             help: a tuple variant with a similar name exists: `XEmpty5`
+
+error[E0532]: expected tuple struct/variant, found unit variant `E::Empty4`
+  --> $DIR/empty-struct-unit-pat.rs:42:9
+   |
+LL |         E::Empty4(..) => ()
+   |         ^^^^^^^^^ not a tuple struct/variant
+
+error[E0532]: expected tuple struct/variant, found unit variant `XE::XEmpty4`
+  --> $DIR/empty-struct-unit-pat.rs:45:9
+   |
+LL |         XE::XEmpty4(..) => (),
+   |         ^^^^-------
+   |             |
+   |             help: a tuple variant with a similar name exists: `XEmpty5`
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0532`.
diff --git a/src/test/ui/enable-unstable-lib-feature.rs b/src/test/ui/enable-unstable-lib-feature.rs
new file mode 100644
index 0000000..383c686
--- /dev/null
+++ b/src/test/ui/enable-unstable-lib-feature.rs
@@ -0,0 +1,14 @@
+// Test that enabling an unstable feature disables warnings
+
+// aux-build:stability-cfg2.rs
+
+#![feature(unstable_test_feature)]
+#![deny(non_snake_case)] // To trigger a hard error
+
+// Shouldn't generate a warning about unstable features
+#[allow(unused_extern_crates)]
+extern crate stability_cfg2;
+
+pub fn BOGUS() { } //~ ERROR
+
+pub fn main() { }
diff --git a/src/test/ui/enable-unstable-lib-feature.stderr b/src/test/ui/enable-unstable-lib-feature.stderr
new file mode 100644
index 0000000..5b6ebc4
--- /dev/null
+++ b/src/test/ui/enable-unstable-lib-feature.stderr
@@ -0,0 +1,14 @@
+error: function `BOGUS` should have a snake case name
+  --> $DIR/enable-unstable-lib-feature.rs:12:8
+   |
+LL | pub fn BOGUS() { }
+   |        ^^^^^ help: convert the identifier to snake case: `bogus`
+   |
+note: lint level defined here
+  --> $DIR/enable-unstable-lib-feature.rs:6:9
+   |
+LL | #![deny(non_snake_case)] // To trigger a hard error
+   |         ^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/enum-variant-generic-args.rs b/src/test/ui/enum-variant-generic-args.rs
new file mode 100644
index 0000000..dd1f5f3
--- /dev/null
+++ b/src/test/ui/enum-variant-generic-args.rs
@@ -0,0 +1,73 @@
+#![feature(type_alias_enum_variants)]
+
+enum Enum<T> { TSVariant(T), SVariant { v: T } }
+type Alias<T> = Enum<T>;
+type AliasFixed = Enum<()>;
+
+impl<T> Enum<T> {
+    fn ts_variant() {
+        Self::TSVariant(());
+        //~^ ERROR mismatched types [E0308]
+        Self::TSVariant::<()>(());
+        //~^ ERROR type arguments are not allowed for this type [E0109]
+        Self::<()>::TSVariant(());
+        //~^ ERROR type arguments are not allowed for this type [E0109]
+        //~^^ ERROR mismatched types [E0308]
+        Self::<()>::TSVariant::<()>(());
+        //~^ ERROR type arguments are not allowed for this type [E0109]
+        //~^^ ERROR type arguments are not allowed for this type [E0109]
+    }
+
+    fn s_variant() {
+        Self::SVariant { v: () };
+        //~^ ERROR mismatched types [E0308]
+        Self::SVariant::<()> { v: () };
+        //~^ ERROR type arguments are not allowed for this type [E0109]
+        //~^^ ERROR mismatched types [E0308]
+        Self::<()>::SVariant { v: () };
+        //~^ ERROR type arguments are not allowed for this type [E0109]
+        //~^^ ERROR mismatched types [E0308]
+        Self::<()>::SVariant::<()> { v: () };
+        //~^ ERROR type arguments are not allowed for this type [E0109]
+        //~^^ ERROR type arguments are not allowed for this type [E0109]
+        //~^^^ ERROR mismatched types [E0308]
+    }
+}
+
+fn main() {
+    // Tuple struct variant
+
+    Enum::<()>::TSVariant::<()>(());
+    //~^ ERROR type arguments are not allowed for this type [E0109]
+
+    Alias::TSVariant::<()>(());
+    //~^ ERROR type arguments are not allowed for this type [E0109]
+    Alias::<()>::TSVariant::<()>(());
+    //~^ ERROR type arguments are not allowed for this type [E0109]
+
+    AliasFixed::TSVariant::<()>(());
+    //~^ ERROR type arguments are not allowed for this type [E0109]
+    AliasFixed::<()>::TSVariant(());
+    //~^ ERROR wrong number of type arguments: expected 0, found 1 [E0107]
+    AliasFixed::<()>::TSVariant::<()>(());
+    //~^ ERROR type arguments are not allowed for this type [E0109]
+    //~^^ ERROR wrong number of type arguments: expected 0, found 1 [E0107]
+
+    // Struct variant
+
+    Enum::<()>::SVariant::<()> { v: () };
+    //~^ ERROR type arguments are not allowed for this type [E0109]
+
+    Alias::SVariant::<()> { v: () };
+    //~^ ERROR type arguments are not allowed for this type [E0109]
+    Alias::<()>::SVariant::<()> { v: () };
+    //~^ ERROR type arguments are not allowed for this type [E0109]
+
+    AliasFixed::SVariant::<()> { v: () };
+    //~^ ERROR type arguments are not allowed for this type [E0109]
+    AliasFixed::<()>::SVariant { v: () };
+    //~^ ERROR wrong number of type arguments: expected 0, found 1 [E0107]
+    AliasFixed::<()>::SVariant::<()> { v: () };
+    //~^ ERROR type arguments are not allowed for this type [E0109]
+    //~^^ ERROR wrong number of type arguments: expected 0, found 1 [E0107]
+}
diff --git a/src/test/ui/enum-variant-generic-args.stderr b/src/test/ui/enum-variant-generic-args.stderr
new file mode 100644
index 0000000..09b9a4ee
--- /dev/null
+++ b/src/test/ui/enum-variant-generic-args.stderr
@@ -0,0 +1,190 @@
+error[E0308]: mismatched types
+  --> $DIR/enum-variant-generic-args.rs:9:25
+   |
+LL |         Self::TSVariant(());
+   |                         ^^ expected type parameter, found ()
+   |
+   = note: expected type `T`
+              found type `()`
+
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/enum-variant-generic-args.rs:11:27
+   |
+LL |         Self::TSVariant::<()>(());
+   |                           ^^ type argument not allowed
+
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/enum-variant-generic-args.rs:13:16
+   |
+LL |         Self::<()>::TSVariant(());
+   |                ^^ type argument not allowed
+
+error[E0308]: mismatched types
+  --> $DIR/enum-variant-generic-args.rs:13:31
+   |
+LL |         Self::<()>::TSVariant(());
+   |                               ^^ expected type parameter, found ()
+   |
+   = note: expected type `T`
+              found type `()`
+
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/enum-variant-generic-args.rs:16:16
+   |
+LL |         Self::<()>::TSVariant::<()>(());
+   |                ^^ type argument not allowed
+
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/enum-variant-generic-args.rs:16:33
+   |
+LL |         Self::<()>::TSVariant::<()>(());
+   |                                 ^^ type argument not allowed
+
+error[E0308]: mismatched types
+  --> $DIR/enum-variant-generic-args.rs:22:29
+   |
+LL |         Self::SVariant { v: () };
+   |                             ^^ expected type parameter, found ()
+   |
+   = note: expected type `T`
+              found type `()`
+
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/enum-variant-generic-args.rs:24:26
+   |
+LL |         Self::SVariant::<()> { v: () };
+   |                          ^^ type argument not allowed
+
+error[E0308]: mismatched types
+  --> $DIR/enum-variant-generic-args.rs:24:35
+   |
+LL |         Self::SVariant::<()> { v: () };
+   |                                   ^^ expected type parameter, found ()
+   |
+   = note: expected type `T`
+              found type `()`
+
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/enum-variant-generic-args.rs:27:16
+   |
+LL |         Self::<()>::SVariant { v: () };
+   |                ^^ type argument not allowed
+
+error[E0308]: mismatched types
+  --> $DIR/enum-variant-generic-args.rs:27:35
+   |
+LL |         Self::<()>::SVariant { v: () };
+   |                                   ^^ expected type parameter, found ()
+   |
+   = note: expected type `T`
+              found type `()`
+
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/enum-variant-generic-args.rs:30:16
+   |
+LL |         Self::<()>::SVariant::<()> { v: () };
+   |                ^^ type argument not allowed
+
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/enum-variant-generic-args.rs:30:32
+   |
+LL |         Self::<()>::SVariant::<()> { v: () };
+   |                                ^^ type argument not allowed
+
+error[E0308]: mismatched types
+  --> $DIR/enum-variant-generic-args.rs:30:41
+   |
+LL |         Self::<()>::SVariant::<()> { v: () };
+   |                                         ^^ expected type parameter, found ()
+   |
+   = note: expected type `T`
+              found type `()`
+
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/enum-variant-generic-args.rs:40:29
+   |
+LL |     Enum::<()>::TSVariant::<()>(());
+   |                             ^^ type argument not allowed
+
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/enum-variant-generic-args.rs:43:24
+   |
+LL |     Alias::TSVariant::<()>(());
+   |                        ^^ type argument not allowed
+
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/enum-variant-generic-args.rs:45:30
+   |
+LL |     Alias::<()>::TSVariant::<()>(());
+   |                              ^^ type argument not allowed
+
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/enum-variant-generic-args.rs:48:29
+   |
+LL |     AliasFixed::TSVariant::<()>(());
+   |                             ^^ type argument not allowed
+
+error[E0107]: wrong number of type arguments: expected 0, found 1
+  --> $DIR/enum-variant-generic-args.rs:50:18
+   |
+LL |     AliasFixed::<()>::TSVariant(());
+   |                  ^^ unexpected type argument
+
+error[E0107]: wrong number of type arguments: expected 0, found 1
+  --> $DIR/enum-variant-generic-args.rs:52:18
+   |
+LL |     AliasFixed::<()>::TSVariant::<()>(());
+   |                  ^^ unexpected type argument
+
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/enum-variant-generic-args.rs:52:35
+   |
+LL |     AliasFixed::<()>::TSVariant::<()>(());
+   |                                   ^^ type argument not allowed
+
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/enum-variant-generic-args.rs:58:28
+   |
+LL |     Enum::<()>::SVariant::<()> { v: () };
+   |                            ^^ type argument not allowed
+
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/enum-variant-generic-args.rs:61:23
+   |
+LL |     Alias::SVariant::<()> { v: () };
+   |                       ^^ type argument not allowed
+
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/enum-variant-generic-args.rs:63:29
+   |
+LL |     Alias::<()>::SVariant::<()> { v: () };
+   |                             ^^ type argument not allowed
+
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/enum-variant-generic-args.rs:66:28
+   |
+LL |     AliasFixed::SVariant::<()> { v: () };
+   |                            ^^ type argument not allowed
+
+error[E0107]: wrong number of type arguments: expected 0, found 1
+  --> $DIR/enum-variant-generic-args.rs:68:18
+   |
+LL |     AliasFixed::<()>::SVariant { v: () };
+   |                  ^^ unexpected type argument
+
+error[E0107]: wrong number of type arguments: expected 0, found 1
+  --> $DIR/enum-variant-generic-args.rs:70:18
+   |
+LL |     AliasFixed::<()>::SVariant::<()> { v: () };
+   |                  ^^ unexpected type argument
+
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/enum-variant-generic-args.rs:70:34
+   |
+LL |     AliasFixed::<()>::SVariant::<()> { v: () };
+   |                                  ^^ type argument not allowed
+
+error: aborting due to 28 previous errors
+
+Some errors occurred: E0107, E0109, E0308.
+For more information about an error, try `rustc --explain E0107`.
diff --git a/src/test/ui/enum/enum-and-module-in-same-scope.rs b/src/test/ui/enum/enum-and-module-in-same-scope.rs
new file mode 100644
index 0000000..cc6e199
--- /dev/null
+++ b/src/test/ui/enum/enum-and-module-in-same-scope.rs
@@ -0,0 +1,10 @@
+enum Foo {
+    X
+}
+
+mod Foo { //~ ERROR the name `Foo` is defined multiple times
+    pub static X: isize = 42;
+    fn f() { f() } // Check that this does not result in a resolution error
+}
+
+fn main() {}
diff --git a/src/test/ui/enum/enum-and-module-in-same-scope.stderr b/src/test/ui/enum/enum-and-module-in-same-scope.stderr
new file mode 100644
index 0000000..538898c
--- /dev/null
+++ b/src/test/ui/enum/enum-and-module-in-same-scope.stderr
@@ -0,0 +1,14 @@
+error[E0428]: the name `Foo` is defined multiple times
+  --> $DIR/enum-and-module-in-same-scope.rs:5:1
+   |
+LL | enum Foo {
+   | -------- previous definition of the type `Foo` here
+...
+LL | mod Foo {
+   | ^^^^^^^ `Foo` redefined here
+   |
+   = note: `Foo` must be defined only once in the type namespace of this module
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0428`.
diff --git a/src/test/ui/enum/enum-discrim-autosizing.rs b/src/test/ui/enum/enum-discrim-autosizing.rs
new file mode 100644
index 0000000..e9bb927
--- /dev/null
+++ b/src/test/ui/enum/enum-discrim-autosizing.rs
@@ -0,0 +1,11 @@
+// With no repr attribute the discriminant will default to isize.
+// On 32-bit architectures this is equivalent to i32 so the variants
+// collide. On other architectures we need compilation to fail anyway,
+// so force the repr.
+#[cfg_attr(not(target_pointer_width = "32"), repr(i32))]
+enum Eu64 {
+    Au64 = 0,
+    Bu64 = 0x8000_0000_0000_0000 //~ERROR already exists
+}
+
+fn main() {}
diff --git a/src/test/ui/enum/enum-discrim-autosizing.stderr b/src/test/ui/enum/enum-discrim-autosizing.stderr
new file mode 100644
index 0000000..8848f98
--- /dev/null
+++ b/src/test/ui/enum/enum-discrim-autosizing.stderr
@@ -0,0 +1,11 @@
+error[E0081]: discriminant value `0` already exists
+  --> $DIR/enum-discrim-autosizing.rs:8:12
+   |
+LL |     Au64 = 0,
+   |            - first use of `0`
+LL |     Bu64 = 0x8000_0000_0000_0000
+   |            ^^^^^^^^^^^^^^^^^^^^^ enum already has `0`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0081`.
diff --git a/src/test/ui/enum/enum-discrim-too-small.rs b/src/test/ui/enum/enum-discrim-too-small.rs
new file mode 100644
index 0000000..e498414
--- /dev/null
+++ b/src/test/ui/enum/enum-discrim-too-small.rs
@@ -0,0 +1,38 @@
+#[repr(u8)]
+enum Eu8 {
+    Au8 = 23,
+    Bu8 = 223,
+    Cu8 = -23,
+    //~^ ERROR cannot apply unary operator `-` to type `u8`
+}
+
+#[repr(u16)]
+enum Eu16 {
+    Au16 = 23,
+    Bu16 = 55555,
+    Cu16 = -22333,
+    //~^ ERROR cannot apply unary operator `-` to type `u16`
+}
+
+#[repr(u32)]
+enum Eu32 {
+    Au32 = 23,
+    Bu32 = 3_000_000_000,
+    Cu32 = -2_000_000_000,
+    //~^ ERROR cannot apply unary operator `-` to type `u32`
+}
+
+#[repr(u64)]
+enum Eu64 {
+    Au32 = 23,
+    Bu32 = 3_000_000_000,
+    Cu32 = -2_000_000_000,
+    //~^ ERROR cannot apply unary operator `-` to type `u64`
+}
+
+// u64 currently allows negative numbers, and i64 allows numbers greater than `1<<63`.  This is a
+// little counterintuitive, but since the discriminant can store all the bits, and extracting it
+// with a cast requires specifying the signedness, there is no loss of information in those cases.
+// This also applies to isize and usize on 64-bit targets.
+
+pub fn main() { }
diff --git a/src/test/ui/enum/enum-discrim-too-small.stderr b/src/test/ui/enum/enum-discrim-too-small.stderr
new file mode 100644
index 0000000..40205d9
--- /dev/null
+++ b/src/test/ui/enum/enum-discrim-too-small.stderr
@@ -0,0 +1,35 @@
+error[E0600]: cannot apply unary operator `-` to type `u8`
+  --> $DIR/enum-discrim-too-small.rs:5:11
+   |
+LL |     Cu8 = -23,
+   |           ^^^ cannot apply unary operator `-`
+   |
+   = note: unsigned values cannot be negated
+
+error[E0600]: cannot apply unary operator `-` to type `u16`
+  --> $DIR/enum-discrim-too-small.rs:13:12
+   |
+LL |     Cu16 = -22333,
+   |            ^^^^^^ cannot apply unary operator `-`
+   |
+   = note: unsigned values cannot be negated
+
+error[E0600]: cannot apply unary operator `-` to type `u32`
+  --> $DIR/enum-discrim-too-small.rs:21:12
+   |
+LL |     Cu32 = -2_000_000_000,
+   |            ^^^^^^^^^^^^^^ cannot apply unary operator `-`
+   |
+   = note: unsigned values cannot be negated
+
+error[E0600]: cannot apply unary operator `-` to type `u64`
+  --> $DIR/enum-discrim-too-small.rs:29:12
+   |
+LL |     Cu32 = -2_000_000_000,
+   |            ^^^^^^^^^^^^^^ cannot apply unary operator `-`
+   |
+   = note: unsigned values cannot be negated
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0600`.
diff --git a/src/test/ui/enum/enum-discrim-too-small2.rs b/src/test/ui/enum/enum-discrim-too-small2.rs
new file mode 100644
index 0000000..af60564
--- /dev/null
+++ b/src/test/ui/enum/enum-discrim-too-small2.rs
@@ -0,0 +1,37 @@
+#![deny(overflowing_literals)]
+#![allow(dead_code)]
+
+#[repr(i8)]
+enum Ei8 {
+    Ai8 = 23,
+    Bi8 = -23,
+    Ci8 = 223, //~ ERROR literal out of range for i8
+}
+
+#[repr(i16)]
+enum Ei16 {
+    Ai16 = 23,
+    Bi16 = -22333,
+    Ci16 = 55555, //~ ERROR literal out of range for i16
+}
+
+#[repr(i32)]
+enum Ei32 {
+    Ai32 = 23,
+    Bi32 = -2_000_000_000,
+    Ci32 = 3_000_000_000, //~ ERROR literal out of range for i32
+}
+
+#[repr(i64)]
+enum Ei64 {
+    Ai64 = 23,
+    Bi64 = -9223372036854775808,
+    Ci64 = 9223372036854775809, //~ ERROR literal out of range for i64
+}
+
+// u64 currently allows negative numbers, and i64 allows numbers greater than `1<<63`.  This is a
+// little counterintuitive, but since the discriminant can store all the bits, and extracting it
+// with a cast requires specifying the signedness, there is no loss of information in those cases.
+// This also applies to isize and usize on 64-bit targets.
+
+pub fn main() { }
diff --git a/src/test/ui/enum/enum-discrim-too-small2.stderr b/src/test/ui/enum/enum-discrim-too-small2.stderr
new file mode 100644
index 0000000..6340f5a
--- /dev/null
+++ b/src/test/ui/enum/enum-discrim-too-small2.stderr
@@ -0,0 +1,32 @@
+error: literal out of range for i8
+  --> $DIR/enum-discrim-too-small2.rs:8:11
+   |
+LL |     Ci8 = 223,
+   |           ^^^
+   |
+note: lint level defined here
+  --> $DIR/enum-discrim-too-small2.rs:1:9
+   |
+LL | #![deny(overflowing_literals)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: literal out of range for i16
+  --> $DIR/enum-discrim-too-small2.rs:15:12
+   |
+LL |     Ci16 = 55555,
+   |            ^^^^^
+
+error: literal out of range for i32
+  --> $DIR/enum-discrim-too-small2.rs:22:12
+   |
+LL |     Ci32 = 3_000_000_000,
+   |            ^^^^^^^^^^^^^
+
+error: literal out of range for i64
+  --> $DIR/enum-discrim-too-small2.rs:29:12
+   |
+LL |     Ci64 = 9223372036854775809,
+   |            ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/enum/enum-in-scope.rs b/src/test/ui/enum/enum-in-scope.rs
new file mode 100644
index 0000000..df14bc6
--- /dev/null
+++ b/src/test/ui/enum/enum-in-scope.rs
@@ -0,0 +1,7 @@
+#![allow(non_camel_case_types)]
+
+struct hello(isize);
+
+fn main() {
+    let hello = 0; //~ERROR let bindings cannot shadow tuple structs
+}
diff --git a/src/test/ui/enum/enum-in-scope.stderr b/src/test/ui/enum/enum-in-scope.stderr
new file mode 100644
index 0000000..49a01abcb
--- /dev/null
+++ b/src/test/ui/enum/enum-in-scope.stderr
@@ -0,0 +1,12 @@
+error[E0530]: let bindings cannot shadow tuple structs
+  --> $DIR/enum-in-scope.rs:6:9
+   |
+LL | struct hello(isize);
+   | -------------------- the tuple struct `hello` is defined here
+...
+LL |     let hello = 0;
+   |         ^^^^^ cannot be named the same as a tuple struct
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0530`.
diff --git a/src/test/ui/enum/enum-size-variance.rs b/src/test/ui/enum/enum-size-variance.rs
new file mode 100644
index 0000000..082bd0d
--- /dev/null
+++ b/src/test/ui/enum/enum-size-variance.rs
@@ -0,0 +1,35 @@
+// run-pass
+
+#![warn(variant_size_differences)]
+#![allow(dead_code)]
+
+// Note that the following test works because all fields of the enum variants are of the same size.
+// If this test is modified and the reordering logic in librustc/ty/layout.rs kicks in, it fails.
+
+enum Enum1 { }
+
+enum Enum2 { A, B, C }
+
+enum Enum3 { D(i64), E, F }
+
+enum Enum4 { H(i64), I(i64), J }
+
+enum Enum5 {
+    L(i64, i64, i64, i64), //~ WARNING three times larger
+    M(i64),
+    N
+}
+
+enum Enum6<T, U> {
+    O(T),
+    P(U),
+    Q(i64)
+}
+
+#[allow(variant_size_differences)]
+enum Enum7 {
+    R(i64, i64, i64, i64),
+    S(i64),
+    T
+}
+pub fn main() { }
diff --git a/src/test/ui/enum/enum-size-variance.stderr b/src/test/ui/enum/enum-size-variance.stderr
new file mode 100644
index 0000000..1ebd9b6
--- /dev/null
+++ b/src/test/ui/enum/enum-size-variance.stderr
@@ -0,0 +1,12 @@
+warning: enum variant is more than three times larger (32 bytes) than the next largest
+  --> $DIR/enum-size-variance.rs:18:5
+   |
+LL |     L(i64, i64, i64, i64),
+   |     ^^^^^^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/enum-size-variance.rs:3:9
+   |
+LL | #![warn(variant_size_differences)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^
+
diff --git a/src/test/ui/enum/enum-to-float-cast-2.rs b/src/test/ui/enum/enum-to-float-cast-2.rs
new file mode 100644
index 0000000..c861b5e
--- /dev/null
+++ b/src/test/ui/enum/enum-to-float-cast-2.rs
@@ -0,0 +1,18 @@
+// Tests that enum-to-float casts are disallowed.
+
+enum E {
+    L0 = -1,
+    H0 = 1
+}
+
+enum F {
+    L1 = 1,
+    H1 = 0xFFFFFFFFFFFFFFFF
+}
+
+pub fn main() {
+    let a = E::L0 as f32;  //~ ERROR casting
+    let c = F::H1 as f32;  //~ ERROR casting
+    assert_eq!(a, -1.0f32);
+    assert_eq!(c, -1.0f32);
+}
diff --git a/src/test/ui/enum/enum-to-float-cast-2.stderr b/src/test/ui/enum/enum-to-float-cast-2.stderr
new file mode 100644
index 0000000..2bc4140
--- /dev/null
+++ b/src/test/ui/enum/enum-to-float-cast-2.stderr
@@ -0,0 +1,19 @@
+error[E0606]: casting `E` as `f32` is invalid
+  --> $DIR/enum-to-float-cast-2.rs:14:13
+   |
+LL |     let a = E::L0 as f32;
+   |             ^^^^^^^^^^^^
+   |
+   = help: cast through an integer first
+
+error[E0606]: casting `F` as `f32` is invalid
+  --> $DIR/enum-to-float-cast-2.rs:15:13
+   |
+LL |     let c = F::H1 as f32;
+   |             ^^^^^^^^^^^^
+   |
+   = help: cast through an integer first
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0606`.
diff --git a/src/test/ui/enum/enum-to-float-cast.rs b/src/test/ui/enum/enum-to-float-cast.rs
new file mode 100644
index 0000000..05acdfd
--- /dev/null
+++ b/src/test/ui/enum/enum-to-float-cast.rs
@@ -0,0 +1,21 @@
+// Tests that enum-to-float casts are disallowed.
+
+enum E {
+    L0 = -1,
+    H0 = 1
+}
+
+enum F {
+    L1 = 1,
+    H1 = 0xFFFFFFFFFFFFFFFF
+}
+
+static C0: f32 = E::L0 as f32; //~ ERROR casting
+static C1: f32 = F::H1 as f32; //~ ERROR casting
+
+pub fn main() {
+    let b = C0;
+    let d = C1;
+    assert_eq!(b, -1.0f32);
+    assert_eq!(d, -1.0f32);
+}
diff --git a/src/test/ui/enum/enum-to-float-cast.stderr b/src/test/ui/enum/enum-to-float-cast.stderr
new file mode 100644
index 0000000..191606d
--- /dev/null
+++ b/src/test/ui/enum/enum-to-float-cast.stderr
@@ -0,0 +1,19 @@
+error[E0606]: casting `E` as `f32` is invalid
+  --> $DIR/enum-to-float-cast.rs:13:18
+   |
+LL | static C0: f32 = E::L0 as f32;
+   |                  ^^^^^^^^^^^^
+   |
+   = help: cast through an integer first
+
+error[E0606]: casting `F` as `f32` is invalid
+  --> $DIR/enum-to-float-cast.rs:14:18
+   |
+LL | static C1: f32 = F::H1 as f32;
+   |                  ^^^^^^^^^^^^
+   |
+   = help: cast through an integer first
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0606`.
diff --git a/src/test/ui/enum/enum-variant-type-2.rs b/src/test/ui/enum/enum-variant-type-2.rs
new file mode 100644
index 0000000..27286a0
--- /dev/null
+++ b/src/test/ui/enum/enum-variant-type-2.rs
@@ -0,0 +1,9 @@
+// Test that enum variants are not actually types.
+
+enum Foo {
+    Bar
+}
+
+fn foo(x: Foo::Bar) {} //~ ERROR expected type, found variant `Foo::Bar`
+
+fn main() {}
diff --git a/src/test/ui/enum/enum-variant-type-2.stderr b/src/test/ui/enum/enum-variant-type-2.stderr
new file mode 100644
index 0000000..7e8453c
--- /dev/null
+++ b/src/test/ui/enum/enum-variant-type-2.stderr
@@ -0,0 +1,12 @@
+error[E0573]: expected type, found variant `Foo::Bar`
+  --> $DIR/enum-variant-type-2.rs:7:11
+   |
+LL | fn foo(x: Foo::Bar) {}
+   |           ^^^^^^^^
+   |           |
+   |           not a type
+   |           help: try using the variant's enum: `Foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0573`.
diff --git a/src/test/ui/enums-pats-not-idents.rs b/src/test/ui/enums-pats-not-idents.rs
new file mode 100644
index 0000000..1593f1e
--- /dev/null
+++ b/src/test/ui/enums-pats-not-idents.rs
@@ -0,0 +1,3 @@
+fn main() {
+    let a(1) = 13; //~ ERROR cannot find tuple struct/variant `a` in this scope
+}
diff --git a/src/test/ui/enums-pats-not-idents.stderr b/src/test/ui/enums-pats-not-idents.stderr
new file mode 100644
index 0000000..6b1e604
--- /dev/null
+++ b/src/test/ui/enums-pats-not-idents.stderr
@@ -0,0 +1,9 @@
+error[E0531]: cannot find tuple struct/variant `a` in this scope
+  --> $DIR/enums-pats-not-idents.rs:2:9
+   |
+LL |     let a(1) = 13;
+   |         ^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0531`.
diff --git a/src/test/ui/error-codes/E0001.rs b/src/test/ui/error-codes/E0001.rs
new file mode 100644
index 0000000..2c95f02
--- /dev/null
+++ b/src/test/ui/error-codes/E0001.rs
@@ -0,0 +1,10 @@
+#![deny(unreachable_patterns)]
+
+fn main() {
+    let foo = Some(1);
+    match foo {
+        Some(_) => {/* ... */}
+        None => {/* ... */}
+        _ => {/* ... */} //~ ERROR unreachable pattern
+    }
+}
diff --git a/src/test/ui/error-codes/E0001.stderr b/src/test/ui/error-codes/E0001.stderr
new file mode 100644
index 0000000..9923451
--- /dev/null
+++ b/src/test/ui/error-codes/E0001.stderr
@@ -0,0 +1,14 @@
+error: unreachable pattern
+  --> $DIR/E0001.rs:8:9
+   |
+LL |         _ => {/* ... */}
+   |         ^
+   |
+note: lint level defined here
+  --> $DIR/E0001.rs:1:9
+   |
+LL | #![deny(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/error-codes/E0004-2.rs b/src/test/ui/error-codes/E0004-2.rs
new file mode 100644
index 0000000..c7612fd
--- /dev/null
+++ b/src/test/ui/error-codes/E0004-2.rs
@@ -0,0 +1,5 @@
+fn main() {
+    let x = Some(1);
+
+    match x { } //~ ERROR E0004
+}
diff --git a/src/test/ui/error-codes/E0004-2.stderr b/src/test/ui/error-codes/E0004-2.stderr
new file mode 100644
index 0000000..db0a2b5
--- /dev/null
+++ b/src/test/ui/error-codes/E0004-2.stderr
@@ -0,0 +1,11 @@
+error[E0004]: non-exhaustive patterns: multiple patterns of type `std::option::Option<i32>` are not handled
+  --> $DIR/E0004-2.rs:4:11
+   |
+LL |     match x { }
+   |           ^
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/error-codes/E0004.rs b/src/test/ui/error-codes/E0004.rs
new file mode 100644
index 0000000..1ee9d2b
--- /dev/null
+++ b/src/test/ui/error-codes/E0004.rs
@@ -0,0 +1,12 @@
+enum Terminator {
+    HastaLaVistaBaby,
+    TalkToMyHand,
+}
+
+fn main() {
+    let x = Terminator::HastaLaVistaBaby;
+
+    match x { //~ ERROR E0004
+        Terminator::TalkToMyHand => {}
+    }
+}
diff --git a/src/test/ui/error-codes/E0004.stderr b/src/test/ui/error-codes/E0004.stderr
new file mode 100644
index 0000000..2940ad4
--- /dev/null
+++ b/src/test/ui/error-codes/E0004.stderr
@@ -0,0 +1,18 @@
+error[E0004]: non-exhaustive patterns: `HastaLaVistaBaby` not covered
+  --> $DIR/E0004.rs:9:11
+   |
+LL | / enum Terminator {
+LL | |     HastaLaVistaBaby,
+   | |     ---------------- not covered
+LL | |     TalkToMyHand,
+LL | | }
+   | |_- `Terminator` defined here
+...
+LL |       match x {
+   |             ^ pattern `HastaLaVistaBaby` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/error-codes/E0005.rs b/src/test/ui/error-codes/E0005.rs
new file mode 100644
index 0000000..f473069
--- /dev/null
+++ b/src/test/ui/error-codes/E0005.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let x = Some(1);
+    let Some(y) = x; //~ ERROR E0005
+}
diff --git a/src/test/ui/error-codes/E0005.stderr b/src/test/ui/error-codes/E0005.stderr
new file mode 100644
index 0000000..56a4bcf
--- /dev/null
+++ b/src/test/ui/error-codes/E0005.stderr
@@ -0,0 +1,9 @@
+error[E0005]: refutable pattern in local binding: `None` not covered
+  --> $DIR/E0005.rs:3:9
+   |
+LL |     let Some(y) = x;
+   |         ^^^^^^^ pattern `None` not covered
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0005`.
diff --git a/src/test/ui/error-codes/E0007.rs b/src/test/ui/error-codes/E0007.rs
new file mode 100644
index 0000000..8fc6342
--- /dev/null
+++ b/src/test/ui/error-codes/E0007.rs
@@ -0,0 +1,9 @@
+fn main() {
+    let x = Some("s".to_string());
+    match x {
+        op_string @ Some(s) => {},
+        //~^ ERROR E0007
+        //~| ERROR E0303
+        None => {},
+    }
+}
diff --git a/src/test/ui/error-codes/E0007.stderr b/src/test/ui/error-codes/E0007.stderr
new file mode 100644
index 0000000..a5d6949
--- /dev/null
+++ b/src/test/ui/error-codes/E0007.stderr
@@ -0,0 +1,16 @@
+error[E0007]: cannot bind by-move with sub-bindings
+  --> $DIR/E0007.rs:4:9
+   |
+LL |         op_string @ Some(s) => {},
+   |         ^^^^^^^^^^^^^^^^^^^ binds an already bound by-move value by moving it
+
+error[E0303]: pattern bindings are not allowed after an `@`
+  --> $DIR/E0007.rs:4:26
+   |
+LL |         op_string @ Some(s) => {},
+   |                          ^ not allowed after `@`
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0007, E0303.
+For more information about an error, try `rustc --explain E0007`.
diff --git a/src/test/ui/error-codes/E0008.nll.stderr b/src/test/ui/error-codes/E0008.nll.stderr
new file mode 100644
index 0000000..2505c03
--- /dev/null
+++ b/src/test/ui/error-codes/E0008.nll.stderr
@@ -0,0 +1,11 @@
+error[E0008]: cannot bind by-move into a pattern guard
+  --> $DIR/E0008.rs:3:14
+   |
+LL |         Some(s) if s.len() == 0 => {},
+   |              ^ moves value into pattern guard
+   |
+   = help: add #![feature(bind_by_move_pattern_guards)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0008`.
diff --git a/src/test/ui/error-codes/E0008.rs b/src/test/ui/error-codes/E0008.rs
new file mode 100644
index 0000000..c87ef4c
--- /dev/null
+++ b/src/test/ui/error-codes/E0008.rs
@@ -0,0 +1,7 @@
+fn main() {
+    match Some("hi".to_string()) {
+        Some(s) if s.len() == 0 => {},
+        //~^ ERROR E0008
+        _ => {},
+    }
+}
diff --git a/src/test/ui/error-codes/E0008.stderr b/src/test/ui/error-codes/E0008.stderr
new file mode 100644
index 0000000..d5c44ef
--- /dev/null
+++ b/src/test/ui/error-codes/E0008.stderr
@@ -0,0 +1,9 @@
+error[E0008]: cannot bind by-move into a pattern guard
+  --> $DIR/E0008.rs:3:14
+   |
+LL |         Some(s) if s.len() == 0 => {},
+   |              ^ moves value into pattern guard
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0008`.
diff --git a/src/test/ui/error-codes/E0009.rs b/src/test/ui/error-codes/E0009.rs
new file mode 100644
index 0000000..0610d03
--- /dev/null
+++ b/src/test/ui/error-codes/E0009.rs
@@ -0,0 +1,9 @@
+fn main() {
+    struct X { x: (), }
+    let x = Some((X { x: () }, X { x: () }));
+    match x {
+        Some((y, ref z)) => {},
+        //~^ ERROR E0009
+        None => panic!()
+    }
+}
diff --git a/src/test/ui/error-codes/E0009.stderr b/src/test/ui/error-codes/E0009.stderr
new file mode 100644
index 0000000..f8acb9a
--- /dev/null
+++ b/src/test/ui/error-codes/E0009.stderr
@@ -0,0 +1,11 @@
+error[E0009]: cannot bind by-move and by-ref in the same pattern
+  --> $DIR/E0009.rs:5:15
+   |
+LL |         Some((y, ref z)) => {},
+   |               ^  ----- both by-ref and by-move used
+   |               |
+   |               by-move pattern here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0009`.
diff --git a/src/test/ui/error-codes/E0010-teach.rs b/src/test/ui/error-codes/E0010-teach.rs
new file mode 100644
index 0000000..da51035
--- /dev/null
+++ b/src/test/ui/error-codes/E0010-teach.rs
@@ -0,0 +1,9 @@
+// compile-flags: -Z teach
+
+#![feature(box_syntax)]
+#![allow(warnings)]
+
+const CON : Box<i32> = box 0; //~ ERROR E0010
+//~^ ERROR constant contains unimplemented expression type
+
+fn main() {}
diff --git a/src/test/ui/error-codes/E0010-teach.stderr b/src/test/ui/error-codes/E0010-teach.stderr
new file mode 100644
index 0000000..3e8467f
--- /dev/null
+++ b/src/test/ui/error-codes/E0010-teach.stderr
@@ -0,0 +1,21 @@
+error[E0010]: allocations are not allowed in constants
+  --> $DIR/E0010-teach.rs:6:24
+   |
+LL | const CON : Box<i32> = box 0;
+   |                        ^^^^^ allocation not allowed in constants
+   |
+   = note: The value of statics and constants must be known at compile time, and they live for the entire lifetime of a program. Creating a boxed value allocates memory on the heap at runtime, and therefore cannot be done at compile time.
+
+error[E0019]: constant contains unimplemented expression type
+  --> $DIR/E0010-teach.rs:6:28
+   |
+LL | const CON : Box<i32> = box 0;
+   |                            ^
+   |
+   = note: A function call isn't allowed in the const's initialization expression because the expression's value must be known at compile-time.
+   = note: Remember: you can't use a function call inside a const's initialization expression! However, you can use it anywhere else.
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0010, E0019.
+For more information about an error, try `rustc --explain E0010`.
diff --git a/src/test/ui/error-codes/E0010.rs b/src/test/ui/error-codes/E0010.rs
new file mode 100644
index 0000000..3398e2c
--- /dev/null
+++ b/src/test/ui/error-codes/E0010.rs
@@ -0,0 +1,7 @@
+#![feature(box_syntax)]
+#![allow(warnings)]
+
+const CON : Box<i32> = box 0; //~ ERROR E0010
+//~^ ERROR constant contains unimplemented expression type
+
+fn main() {}
diff --git a/src/test/ui/error-codes/E0010.stderr b/src/test/ui/error-codes/E0010.stderr
new file mode 100644
index 0000000..285570f
--- /dev/null
+++ b/src/test/ui/error-codes/E0010.stderr
@@ -0,0 +1,16 @@
+error[E0010]: allocations are not allowed in constants
+  --> $DIR/E0010.rs:4:24
+   |
+LL | const CON : Box<i32> = box 0;
+   |                        ^^^^^ allocation not allowed in constants
+
+error[E0019]: constant contains unimplemented expression type
+  --> $DIR/E0010.rs:4:28
+   |
+LL | const CON : Box<i32> = box 0;
+   |                            ^
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0010, E0019.
+For more information about an error, try `rustc --explain E0010`.
diff --git a/src/test/ui/error-codes/E0017.nll.stderr b/src/test/ui/error-codes/E0017.nll.stderr
new file mode 100644
index 0000000..3c2a072
--- /dev/null
+++ b/src/test/ui/error-codes/E0017.nll.stderr
@@ -0,0 +1,34 @@
+error[E0017]: references in constants may only refer to immutable values
+  --> $DIR/E0017.rs:4:30
+   |
+LL | const CR: &'static mut i32 = &mut C;
+   |                              ^^^^^^ constants require immutable values
+
+error[E0017]: references in statics may only refer to immutable values
+  --> $DIR/E0017.rs:5:39
+   |
+LL | static STATIC_REF: &'static mut i32 = &mut X;
+   |                                       ^^^^^^ statics require immutable values
+
+error: cannot mutate statics in the initializer of another static
+  --> $DIR/E0017.rs:5:39
+   |
+LL | static STATIC_REF: &'static mut i32 = &mut X;
+   |                                       ^^^^^^
+
+error[E0596]: cannot borrow immutable static item `X` as mutable
+  --> $DIR/E0017.rs:5:39
+   |
+LL | static STATIC_REF: &'static mut i32 = &mut X;
+   |                                       ^^^^^^ cannot borrow as mutable
+
+error[E0017]: references in statics may only refer to immutable values
+  --> $DIR/E0017.rs:8:38
+   |
+LL | static CONST_REF: &'static mut i32 = &mut C;
+   |                                      ^^^^^^ statics require immutable values
+
+error: aborting due to 5 previous errors
+
+Some errors occurred: E0017, E0596.
+For more information about an error, try `rustc --explain E0017`.
diff --git a/src/test/ui/error-codes/E0017.rs b/src/test/ui/error-codes/E0017.rs
new file mode 100644
index 0000000..71250eb
--- /dev/null
+++ b/src/test/ui/error-codes/E0017.rs
@@ -0,0 +1,9 @@
+static X: i32 = 1;
+const C: i32 = 2;
+
+const CR: &'static mut i32 = &mut C; //~ ERROR E0017
+static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0017
+                                              //~| ERROR cannot borrow
+                                              //~| ERROR cannot mutate statics
+static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0017
+fn main() {}
diff --git a/src/test/ui/error-codes/E0017.stderr b/src/test/ui/error-codes/E0017.stderr
new file mode 100644
index 0000000..d0bd93e
--- /dev/null
+++ b/src/test/ui/error-codes/E0017.stderr
@@ -0,0 +1,34 @@
+error[E0017]: references in constants may only refer to immutable values
+  --> $DIR/E0017.rs:4:30
+   |
+LL | const CR: &'static mut i32 = &mut C;
+   |                              ^^^^^^ constants require immutable values
+
+error[E0017]: references in statics may only refer to immutable values
+  --> $DIR/E0017.rs:5:39
+   |
+LL | static STATIC_REF: &'static mut i32 = &mut X;
+   |                                       ^^^^^^ statics require immutable values
+
+error: cannot mutate statics in the initializer of another static
+  --> $DIR/E0017.rs:5:39
+   |
+LL | static STATIC_REF: &'static mut i32 = &mut X;
+   |                                       ^^^^^^
+
+error[E0596]: cannot borrow immutable static item as mutable
+  --> $DIR/E0017.rs:5:44
+   |
+LL | static STATIC_REF: &'static mut i32 = &mut X;
+   |                                            ^
+
+error[E0017]: references in statics may only refer to immutable values
+  --> $DIR/E0017.rs:8:38
+   |
+LL | static CONST_REF: &'static mut i32 = &mut C;
+   |                                      ^^^^^^ statics require immutable values
+
+error: aborting due to 5 previous errors
+
+Some errors occurred: E0017, E0596.
+For more information about an error, try `rustc --explain E0017`.
diff --git a/src/test/ui/error-codes/E0023.rs b/src/test/ui/error-codes/E0023.rs
new file mode 100644
index 0000000..2a97e90
--- /dev/null
+++ b/src/test/ui/error-codes/E0023.rs
@@ -0,0 +1,14 @@
+enum Fruit {
+    Apple(String, String),
+    Pear(u32),
+}
+
+
+fn main() {
+    let x = Fruit::Apple(String::new(), String::new());
+    match x {
+        Fruit::Apple(a) => {}, //~ ERROR E0023
+        Fruit::Apple(a, b, c) => {}, //~ ERROR E0023
+        Fruit::Pear(1, 2) => {}, //~ ERROR E0023
+    }
+}
diff --git a/src/test/ui/error-codes/E0023.stderr b/src/test/ui/error-codes/E0023.stderr
new file mode 100644
index 0000000..1bc90a9
--- /dev/null
+++ b/src/test/ui/error-codes/E0023.stderr
@@ -0,0 +1,21 @@
+error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 2 fields
+  --> $DIR/E0023.rs:10:9
+   |
+LL |         Fruit::Apple(a) => {},
+   |         ^^^^^^^^^^^^^^^ expected 2 fields, found 1
+
+error[E0023]: this pattern has 3 fields, but the corresponding tuple variant has 2 fields
+  --> $DIR/E0023.rs:11:9
+   |
+LL |         Fruit::Apple(a, b, c) => {},
+   |         ^^^^^^^^^^^^^^^^^^^^^ expected 2 fields, found 3
+
+error[E0023]: this pattern has 2 fields, but the corresponding tuple variant has 1 field
+  --> $DIR/E0023.rs:12:9
+   |
+LL |         Fruit::Pear(1, 2) => {},
+   |         ^^^^^^^^^^^^^^^^^ expected 1 field, found 2
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0023`.
diff --git a/src/test/ui/error-codes/E0025.rs b/src/test/ui/error-codes/E0025.rs
new file mode 100644
index 0000000..549269a
--- /dev/null
+++ b/src/test/ui/error-codes/E0025.rs
@@ -0,0 +1,10 @@
+struct Foo {
+    a: u8,
+    b: u8,
+}
+
+fn main() {
+    let x = Foo { a:1, b:2 };
+    let Foo { a: x, a: y, b: 0 } = x;
+    //~^ ERROR field `a` bound multiple times in the pattern
+}
diff --git a/src/test/ui/error-codes/E0025.stderr b/src/test/ui/error-codes/E0025.stderr
new file mode 100644
index 0000000..dfec6d0
--- /dev/null
+++ b/src/test/ui/error-codes/E0025.stderr
@@ -0,0 +1,11 @@
+error[E0025]: field `a` bound multiple times in the pattern
+  --> $DIR/E0025.rs:8:21
+   |
+LL |     let Foo { a: x, a: y, b: 0 } = x;
+   |               ----  ^^^^ multiple uses of `a` in pattern
+   |               |
+   |               first use of `a`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0025`.
diff --git a/src/test/ui/error-codes/E0026-teach.rs b/src/test/ui/error-codes/E0026-teach.rs
new file mode 100644
index 0000000..7c51004
--- /dev/null
+++ b/src/test/ui/error-codes/E0026-teach.rs
@@ -0,0 +1,14 @@
+// compile-flags: -Z teach
+
+struct Thing {
+    x: u32,
+    y: u32
+}
+
+fn main() {
+    let thing = Thing { x: 0, y: 0 };
+    match thing {
+        Thing { x, y, z } => {}
+        //~^ ERROR struct `Thing` does not have a field named `z` [E0026]
+    }
+}
diff --git a/src/test/ui/error-codes/E0026-teach.stderr b/src/test/ui/error-codes/E0026-teach.stderr
new file mode 100644
index 0000000..1a80edc
--- /dev/null
+++ b/src/test/ui/error-codes/E0026-teach.stderr
@@ -0,0 +1,13 @@
+error[E0026]: struct `Thing` does not have a field named `z`
+  --> $DIR/E0026-teach.rs:11:23
+   |
+LL |         Thing { x, y, z } => {}
+   |                       ^ struct `Thing` does not have this field
+   |
+   = note: This error indicates that a struct pattern attempted to extract a non-existent field from a struct. Struct fields are identified by the name used before the colon : so struct patterns should resemble the declaration of the struct type being matched.
+           
+           If you are using shorthand field patterns but want to refer to the struct field by a different name, you should rename it explicitly.
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0026`.
diff --git a/src/test/ui/error-codes/E0026.rs b/src/test/ui/error-codes/E0026.rs
new file mode 100644
index 0000000..0b1ea1c
--- /dev/null
+++ b/src/test/ui/error-codes/E0026.rs
@@ -0,0 +1,12 @@
+struct Thing {
+    x: u32,
+    y: u32
+}
+
+fn main() {
+    let thing = Thing { x: 0, y: 0 };
+    match thing {
+        Thing { x, y, z } => {}
+        //~^ ERROR struct `Thing` does not have a field named `z` [E0026]
+    }
+}
diff --git a/src/test/ui/error-codes/E0026.stderr b/src/test/ui/error-codes/E0026.stderr
new file mode 100644
index 0000000..0314818
--- /dev/null
+++ b/src/test/ui/error-codes/E0026.stderr
@@ -0,0 +1,9 @@
+error[E0026]: struct `Thing` does not have a field named `z`
+  --> $DIR/E0026.rs:9:23
+   |
+LL |         Thing { x, y, z } => {}
+   |                       ^ struct `Thing` does not have this field
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0026`.
diff --git a/src/test/ui/error-codes/E0027-teach.rs b/src/test/ui/error-codes/E0027-teach.rs
new file mode 100644
index 0000000..11402f0
--- /dev/null
+++ b/src/test/ui/error-codes/E0027-teach.rs
@@ -0,0 +1,15 @@
+// compile-flags: -Z teach
+
+struct Dog {
+    name: String,
+    age: u32,
+}
+
+fn main() {
+    let d = Dog { name: "Rusty".to_string(), age: 8 };
+
+    match d {
+        Dog { age: x } => {}
+        //~^ ERROR pattern does not mention field `name`
+    }
+}
diff --git a/src/test/ui/error-codes/E0027-teach.stderr b/src/test/ui/error-codes/E0027-teach.stderr
new file mode 100644
index 0000000..aa4cb9d
--- /dev/null
+++ b/src/test/ui/error-codes/E0027-teach.stderr
@@ -0,0 +1,11 @@
+error[E0027]: pattern does not mention field `name`
+  --> $DIR/E0027-teach.rs:12:9
+   |
+LL |         Dog { age: x } => {}
+   |         ^^^^^^^^^^^^^^ missing field `name`
+   |
+   = note: This error indicates that a pattern for a struct fails to specify a sub-pattern for every one of the struct's fields. Ensure that each field from the struct's definition is mentioned in the pattern, or use `..` to ignore unwanted fields.
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0027`.
diff --git a/src/test/ui/error-codes/E0027.rs b/src/test/ui/error-codes/E0027.rs
new file mode 100644
index 0000000..b8c6a2b
--- /dev/null
+++ b/src/test/ui/error-codes/E0027.rs
@@ -0,0 +1,13 @@
+struct Dog {
+    name: String,
+    age: u32,
+}
+
+fn main() {
+    let d = Dog { name: "Rusty".to_string(), age: 8 };
+
+    match d {
+        Dog { age: x } => {}
+        //~^ ERROR pattern does not mention field `name`
+    }
+}
diff --git a/src/test/ui/error-codes/E0027.stderr b/src/test/ui/error-codes/E0027.stderr
new file mode 100644
index 0000000..4f17bba
--- /dev/null
+++ b/src/test/ui/error-codes/E0027.stderr
@@ -0,0 +1,9 @@
+error[E0027]: pattern does not mention field `name`
+  --> $DIR/E0027.rs:10:9
+   |
+LL |         Dog { age: x } => {}
+   |         ^^^^^^^^^^^^^^ missing field `name`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0027`.
diff --git a/src/test/ui/error-codes/E0029-teach.rs b/src/test/ui/error-codes/E0029-teach.rs
new file mode 100644
index 0000000..83058d3
--- /dev/null
+++ b/src/test/ui/error-codes/E0029-teach.rs
@@ -0,0 +1,11 @@
+// compile-flags: -Z teach
+
+fn main() {
+    let s = "hoho";
+
+    match s {
+        "hello" ..= "world" => {}
+        //~^ ERROR only char and numeric types are allowed in range patterns
+        _ => {}
+    }
+}
diff --git a/src/test/ui/error-codes/E0029-teach.stderr b/src/test/ui/error-codes/E0029-teach.stderr
new file mode 100644
index 0000000..998ef4b
--- /dev/null
+++ b/src/test/ui/error-codes/E0029-teach.stderr
@@ -0,0 +1,13 @@
+error[E0029]: only char and numeric types are allowed in range patterns
+  --> $DIR/E0029-teach.rs:7:9
+   |
+LL |         "hello" ..= "world" => {}
+   |         ^^^^^^^^^^^^^^^^^^^ ranges require char or numeric types
+   |
+   = note: start type: &'static str
+   = note: end type: &'static str
+   = note: In a match expression, only numbers and characters can be matched against a range. This is because the compiler checks that the range is non-empty at compile-time, and is unable to evaluate arbitrary comparison functions. If you want to capture values of an orderable type between two end-points, you can use a guard.
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0029`.
diff --git a/src/test/ui/error-codes/E0029.rs b/src/test/ui/error-codes/E0029.rs
new file mode 100644
index 0000000..fe0d851
--- /dev/null
+++ b/src/test/ui/error-codes/E0029.rs
@@ -0,0 +1,9 @@
+fn main() {
+    let s = "hoho";
+
+    match s {
+        "hello" ..= "world" => {}
+        //~^ ERROR only char and numeric types are allowed in range patterns
+        _ => {}
+    }
+}
diff --git a/src/test/ui/error-codes/E0029.stderr b/src/test/ui/error-codes/E0029.stderr
new file mode 100644
index 0000000..209d219
--- /dev/null
+++ b/src/test/ui/error-codes/E0029.stderr
@@ -0,0 +1,12 @@
+error[E0029]: only char and numeric types are allowed in range patterns
+  --> $DIR/E0029.rs:5:9
+   |
+LL |         "hello" ..= "world" => {}
+   |         ^^^^^^^^^^^^^^^^^^^ ranges require char or numeric types
+   |
+   = note: start type: &'static str
+   = note: end type: &'static str
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0029`.
diff --git a/src/test/ui/error-codes/E0030-teach.rs b/src/test/ui/error-codes/E0030-teach.rs
new file mode 100644
index 0000000..388064f
--- /dev/null
+++ b/src/test/ui/error-codes/E0030-teach.rs
@@ -0,0 +1,8 @@
+// compile-flags: -Z teach
+
+fn main() {
+    match 5u32 {
+        1000 ..= 5 => {}
+        //~^ ERROR lower range bound must be less than or equal to upper
+    }
+}
diff --git a/src/test/ui/error-codes/E0030-teach.stderr b/src/test/ui/error-codes/E0030-teach.stderr
new file mode 100644
index 0000000..3f1ad4a
--- /dev/null
+++ b/src/test/ui/error-codes/E0030-teach.stderr
@@ -0,0 +1,11 @@
+error[E0030]: lower range bound must be less than or equal to upper
+  --> $DIR/E0030-teach.rs:5:9
+   |
+LL |         1000 ..= 5 => {}
+   |         ^^^^ lower bound larger than upper bound
+   |
+   = note: When matching against a range, the compiler verifies that the range is non-empty. Range patterns include both end-points, so this is equivalent to requiring the start of the range to be less than or equal to the end of the range.
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0030`.
diff --git a/src/test/ui/error-codes/E0030.rs b/src/test/ui/error-codes/E0030.rs
new file mode 100644
index 0000000..58d856b
--- /dev/null
+++ b/src/test/ui/error-codes/E0030.rs
@@ -0,0 +1,6 @@
+fn main() {
+    match 5u32 {
+        1000 ..= 5 => {}
+        //~^ ERROR lower range bound must be less than or equal to upper
+    }
+}
diff --git a/src/test/ui/error-codes/E0030.stderr b/src/test/ui/error-codes/E0030.stderr
new file mode 100644
index 0000000..db8161d
--- /dev/null
+++ b/src/test/ui/error-codes/E0030.stderr
@@ -0,0 +1,9 @@
+error[E0030]: lower range bound must be less than or equal to upper
+  --> $DIR/E0030.rs:3:9
+   |
+LL |         1000 ..= 5 => {}
+   |         ^^^^ lower bound larger than upper bound
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0030`.
diff --git a/src/test/ui/error-codes/E0033-teach.rs b/src/test/ui/error-codes/E0033-teach.rs
new file mode 100644
index 0000000..0f0b8d8
--- /dev/null
+++ b/src/test/ui/error-codes/E0033-teach.rs
@@ -0,0 +1,15 @@
+// compile-flags: -Z teach
+
+trait SomeTrait {
+    fn foo();
+}
+
+fn main() {
+    let trait_obj: &SomeTrait = SomeTrait;
+    //~^ ERROR expected value, found trait `SomeTrait`
+    //~| ERROR E0038
+    //~| method `foo` has no receiver
+
+    let &invalid = trait_obj;
+    //~^ ERROR E0033
+}
diff --git a/src/test/ui/error-codes/E0033-teach.stderr b/src/test/ui/error-codes/E0033-teach.stderr
new file mode 100644
index 0000000..81a8f16
--- /dev/null
+++ b/src/test/ui/error-codes/E0033-teach.stderr
@@ -0,0 +1,28 @@
+error[E0423]: expected value, found trait `SomeTrait`
+  --> $DIR/E0033-teach.rs:8:33
+   |
+LL |     let trait_obj: &SomeTrait = SomeTrait;
+   |                                 ^^^^^^^^^ not a value
+
+error[E0038]: the trait `SomeTrait` cannot be made into an object
+  --> $DIR/E0033-teach.rs:8:20
+   |
+LL |     let trait_obj: &SomeTrait = SomeTrait;
+   |                    ^^^^^^^^^^ the trait `SomeTrait` cannot be made into an object
+   |
+   = note: method `foo` has no receiver
+
+error[E0033]: type `&dyn SomeTrait` cannot be dereferenced
+  --> $DIR/E0033-teach.rs:13:9
+   |
+LL |     let &invalid = trait_obj;
+   |         ^^^^^^^^ type `&dyn SomeTrait` cannot be dereferenced
+   |
+   = note: This error indicates that a pointer to a trait type cannot be implicitly dereferenced by a pattern. Every trait defines a type, but because the size of trait implementors isn't fixed, this type has no compile-time size. Therefore, all accesses to trait types must be through pointers. If you encounter this error you should try to avoid dereferencing the pointer.
+           
+           You can read more about trait objects in the Trait Objects section of the Reference: https://doc.rust-lang.org/reference/types.html#trait-objects
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0033, E0038, E0423.
+For more information about an error, try `rustc --explain E0033`.
diff --git a/src/test/ui/error-codes/E0033.rs b/src/test/ui/error-codes/E0033.rs
new file mode 100644
index 0000000..5a4f3cb
--- /dev/null
+++ b/src/test/ui/error-codes/E0033.rs
@@ -0,0 +1,13 @@
+trait SomeTrait {
+    fn foo();
+}
+
+fn main() {
+    let trait_obj: &SomeTrait = SomeTrait;
+    //~^ ERROR expected value, found trait `SomeTrait`
+    //~| ERROR E0038
+    //~| method `foo` has no receiver
+
+    let &invalid = trait_obj;
+    //~^ ERROR E0033
+}
diff --git a/src/test/ui/error-codes/E0033.stderr b/src/test/ui/error-codes/E0033.stderr
new file mode 100644
index 0000000..e250df8
--- /dev/null
+++ b/src/test/ui/error-codes/E0033.stderr
@@ -0,0 +1,24 @@
+error[E0423]: expected value, found trait `SomeTrait`
+  --> $DIR/E0033.rs:6:33
+   |
+LL |     let trait_obj: &SomeTrait = SomeTrait;
+   |                                 ^^^^^^^^^ not a value
+
+error[E0038]: the trait `SomeTrait` cannot be made into an object
+  --> $DIR/E0033.rs:6:20
+   |
+LL |     let trait_obj: &SomeTrait = SomeTrait;
+   |                    ^^^^^^^^^^ the trait `SomeTrait` cannot be made into an object
+   |
+   = note: method `foo` has no receiver
+
+error[E0033]: type `&dyn SomeTrait` cannot be dereferenced
+  --> $DIR/E0033.rs:11:9
+   |
+LL |     let &invalid = trait_obj;
+   |         ^^^^^^^^ type `&dyn SomeTrait` cannot be dereferenced
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0033, E0038, E0423.
+For more information about an error, try `rustc --explain E0033`.
diff --git a/src/test/ui/error-codes/E0034.rs b/src/test/ui/error-codes/E0034.rs
new file mode 100644
index 0000000..f962da1
--- /dev/null
+++ b/src/test/ui/error-codes/E0034.rs
@@ -0,0 +1,21 @@
+struct Test;
+
+trait Trait1 {
+    fn foo();
+}
+
+trait Trait2 {
+    fn foo();
+}
+
+impl Trait1 for Test {
+    fn foo() {}
+}
+
+impl Trait2 for Test {
+    fn foo() {}
+}
+
+fn main() {
+    Test::foo() //~ ERROR multiple applicable items in scope
+}
diff --git a/src/test/ui/error-codes/E0034.stderr b/src/test/ui/error-codes/E0034.stderr
new file mode 100644
index 0000000..816a48f
--- /dev/null
+++ b/src/test/ui/error-codes/E0034.stderr
@@ -0,0 +1,20 @@
+error[E0034]: multiple applicable items in scope
+  --> $DIR/E0034.rs:20:5
+   |
+LL |     Test::foo()
+   |     ^^^^^^^^^ multiple `foo` found
+   |
+note: candidate #1 is defined in an impl of the trait `Trait1` for the type `Test`
+  --> $DIR/E0034.rs:12:5
+   |
+LL |     fn foo() {}
+   |     ^^^^^^^^
+note: candidate #2 is defined in an impl of the trait `Trait2` for the type `Test`
+  --> $DIR/E0034.rs:16:5
+   |
+LL |     fn foo() {}
+   |     ^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0034`.
diff --git a/src/test/ui/error-codes/E0038.rs b/src/test/ui/error-codes/E0038.rs
new file mode 100644
index 0000000..b222680
--- /dev/null
+++ b/src/test/ui/error-codes/E0038.rs
@@ -0,0 +1,11 @@
+trait Trait {
+    fn foo(&self) -> Self;
+}
+
+fn call_foo(x: Box<Trait>) {
+    //~^ ERROR E0038
+    let y = x.foo();
+}
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0038.stderr b/src/test/ui/error-codes/E0038.stderr
new file mode 100644
index 0000000..74b7733
--- /dev/null
+++ b/src/test/ui/error-codes/E0038.stderr
@@ -0,0 +1,11 @@
+error[E0038]: the trait `Trait` cannot be made into an object
+  --> $DIR/E0038.rs:5:1
+   |
+LL | fn call_foo(x: Box<Trait>) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` cannot be made into an object
+   |
+   = note: method `foo` references the `Self` type in its arguments or return type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/error-codes/E0040.rs b/src/test/ui/error-codes/E0040.rs
new file mode 100644
index 0000000..113efae
--- /dev/null
+++ b/src/test/ui/error-codes/E0040.rs
@@ -0,0 +1,15 @@
+struct Foo {
+    x: i32,
+}
+
+impl Drop for Foo {
+    fn drop(&mut self) {
+        println!("kaboom");
+    }
+}
+
+fn main() {
+    let mut x = Foo { x: -7 };
+    x.drop();
+    //~^ ERROR E0040
+}
diff --git a/src/test/ui/error-codes/E0040.stderr b/src/test/ui/error-codes/E0040.stderr
new file mode 100644
index 0000000..9664559
--- /dev/null
+++ b/src/test/ui/error-codes/E0040.stderr
@@ -0,0 +1,9 @@
+error[E0040]: explicit use of destructor method
+  --> $DIR/E0040.rs:13:7
+   |
+LL |     x.drop();
+   |       ^^^^ explicit destructor calls not allowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0040`.
diff --git a/src/test/ui/error-codes/E0044.rs b/src/test/ui/error-codes/E0044.rs
new file mode 100644
index 0000000..a5265e7
--- /dev/null
+++ b/src/test/ui/error-codes/E0044.rs
@@ -0,0 +1,9 @@
+extern {
+    fn sqrt<T>(f: T) -> T;
+    //~^ ERROR foreign items may not have type parameters [E0044]
+    //~| HELP use specialization instead of type parameters by replacing them with concrete types
+    //~| NOTE can't have type parameters
+}
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0044.stderr b/src/test/ui/error-codes/E0044.stderr
new file mode 100644
index 0000000..57c2111
--- /dev/null
+++ b/src/test/ui/error-codes/E0044.stderr
@@ -0,0 +1,11 @@
+error[E0044]: foreign items may not have type parameters
+  --> $DIR/E0044.rs:2:5
+   |
+LL |     fn sqrt<T>(f: T) -> T;
+   |     ^^^^^^^^^^^^^^^^^^^^^^ can't have type parameters
+   |
+   = help: use specialization instead of type parameters by replacing them with concrete types like `u32`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0044`.
diff --git a/src/test/ui/error-codes/E0045.rs b/src/test/ui/error-codes/E0045.rs
new file mode 100644
index 0000000..fb3df56
--- /dev/null
+++ b/src/test/ui/error-codes/E0045.rs
@@ -0,0 +1,4 @@
+extern "Rust" { fn foo(x: u8, ...); }   //~ ERROR E0045
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0045.stderr b/src/test/ui/error-codes/E0045.stderr
new file mode 100644
index 0000000..d163128
--- /dev/null
+++ b/src/test/ui/error-codes/E0045.stderr
@@ -0,0 +1,9 @@
+error[E0045]: C-variadic function must have C or cdecl calling convention
+  --> $DIR/E0045.rs:1:17
+   |
+LL | extern "Rust" { fn foo(x: u8, ...); }
+   |                 ^^^^^^^^^^^^^^^^^^^ C-variadics require C or cdecl calling convention
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0045`.
diff --git a/src/test/ui/error-codes/E0049.rs b/src/test/ui/error-codes/E0049.rs
new file mode 100644
index 0000000..c141f8a
--- /dev/null
+++ b/src/test/ui/error-codes/E0049.rs
@@ -0,0 +1,12 @@
+trait Foo {
+    fn foo<T: Default>(x: T) -> Self;
+}
+
+struct Bar;
+
+impl Foo for Bar {
+    fn foo(x: bool) -> Self { Bar } //~ ERROR E0049
+}
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0049.stderr b/src/test/ui/error-codes/E0049.stderr
new file mode 100644
index 0000000..7e9b9e8
--- /dev/null
+++ b/src/test/ui/error-codes/E0049.stderr
@@ -0,0 +1,12 @@
+error[E0049]: method `foo` has 0 type parameters but its trait declaration has 1 type parameter
+  --> $DIR/E0049.rs:8:5
+   |
+LL |     fn foo<T: Default>(x: T) -> Self;
+   |     --------------------------------- expected 1 type parameter
+...
+LL |     fn foo(x: bool) -> Self { Bar }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ found 0 type parameters
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0049`.
diff --git a/src/test/ui/error-codes/E0050.rs b/src/test/ui/error-codes/E0050.rs
new file mode 100644
index 0000000..98fb627
--- /dev/null
+++ b/src/test/ui/error-codes/E0050.rs
@@ -0,0 +1,16 @@
+trait Foo {
+    fn foo(&self, x: u8) -> bool;
+    fn bar(&self, x: u8, y: u8, z: u8);
+    fn less(&self);
+}
+
+struct Bar;
+
+impl Foo for Bar {
+    fn foo(&self) -> bool { true } //~ ERROR E0050
+    fn bar(&self) { } //~ ERROR E0050
+    fn less(&self, x: u8, y: u8, z: u8) { } //~ ERROR E0050
+}
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0050.stderr b/src/test/ui/error-codes/E0050.stderr
new file mode 100644
index 0000000..fe9ac5e
--- /dev/null
+++ b/src/test/ui/error-codes/E0050.stderr
@@ -0,0 +1,30 @@
+error[E0050]: method `foo` has 1 parameter but the declaration in trait `Foo::foo` has 2
+  --> $DIR/E0050.rs:10:12
+   |
+LL |     fn foo(&self, x: u8) -> bool;
+   |            ------------ trait requires 2 parameters
+...
+LL |     fn foo(&self) -> bool { true }
+   |            ^^^^^ expected 2 parameters, found 1
+
+error[E0050]: method `bar` has 1 parameter but the declaration in trait `Foo::bar` has 4
+  --> $DIR/E0050.rs:11:12
+   |
+LL |     fn bar(&self, x: u8, y: u8, z: u8);
+   |            -------------------------- trait requires 4 parameters
+...
+LL |     fn bar(&self) { }
+   |            ^^^^^ expected 4 parameters, found 1
+
+error[E0050]: method `less` has 4 parameters but the declaration in trait `Foo::less` has 1
+  --> $DIR/E0050.rs:12:13
+   |
+LL |     fn less(&self);
+   |             ----- trait requires 1 parameter
+...
+LL |     fn less(&self, x: u8, y: u8, z: u8) { }
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 1 parameter, found 4
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0050`.
diff --git a/src/test/ui/error-codes/E0054.rs b/src/test/ui/error-codes/E0054.rs
new file mode 100644
index 0000000..55bda4e
--- /dev/null
+++ b/src/test/ui/error-codes/E0054.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let x = 5;
+    let x_is_nonzero = x as bool; //~ ERROR E0054
+}
diff --git a/src/test/ui/error-codes/E0054.stderr b/src/test/ui/error-codes/E0054.stderr
new file mode 100644
index 0000000..6b10927
--- /dev/null
+++ b/src/test/ui/error-codes/E0054.stderr
@@ -0,0 +1,9 @@
+error[E0054]: cannot cast as `bool`
+  --> $DIR/E0054.rs:3:24
+   |
+LL |     let x_is_nonzero = x as bool;
+   |                        ^^^^^^^^^ help: compare with zero instead: `x != 0`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0054`.
diff --git a/src/test/ui/error-codes/E0055.rs b/src/test/ui/error-codes/E0055.rs
new file mode 100644
index 0000000..b525575
--- /dev/null
+++ b/src/test/ui/error-codes/E0055.rs
@@ -0,0 +1,13 @@
+#![recursion_limit="5"]
+struct Foo;
+
+impl Foo {
+    fn foo(&self) {}
+}
+
+fn main() {
+    let foo = Foo;
+    let ref_foo = &&&&&Foo;
+    ref_foo.foo();
+    //~^ ERROR E0055
+}
diff --git a/src/test/ui/error-codes/E0055.stderr b/src/test/ui/error-codes/E0055.stderr
new file mode 100644
index 0000000..d06566f
--- /dev/null
+++ b/src/test/ui/error-codes/E0055.stderr
@@ -0,0 +1,11 @@
+error[E0055]: reached the recursion limit while auto-dereferencing `Foo`
+  --> $DIR/E0055.rs:11:13
+   |
+LL |     ref_foo.foo();
+   |             ^^^ deref recursion limit reached
+   |
+   = help: consider adding a `#![recursion_limit="10"]` attribute to your crate
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0055`.
diff --git a/src/test/ui/error-codes/E0057.rs b/src/test/ui/error-codes/E0057.rs
new file mode 100644
index 0000000..83f941f
--- /dev/null
+++ b/src/test/ui/error-codes/E0057.rs
@@ -0,0 +1,6 @@
+fn main() {
+    let f = |x| x * 3;
+    let a = f(); //~ ERROR E0057
+    let b = f(4);
+    let c = f(2, 3); //~ ERROR E0057
+}
diff --git a/src/test/ui/error-codes/E0057.stderr b/src/test/ui/error-codes/E0057.stderr
new file mode 100644
index 0000000..6b5890c
--- /dev/null
+++ b/src/test/ui/error-codes/E0057.stderr
@@ -0,0 +1,15 @@
+error[E0057]: this function takes 1 parameter but 0 parameters were supplied
+  --> $DIR/E0057.rs:3:13
+   |
+LL |     let a = f();
+   |             ^^^ expected 1 parameter
+
+error[E0057]: this function takes 1 parameter but 2 parameters were supplied
+  --> $DIR/E0057.rs:5:13
+   |
+LL |     let c = f(2, 3);
+   |             ^^^^^^^ expected 1 parameter
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0057`.
diff --git a/src/test/ui/error-codes/E0059.rs b/src/test/ui/error-codes/E0059.rs
new file mode 100644
index 0000000..f775089
--- /dev/null
+++ b/src/test/ui/error-codes/E0059.rs
@@ -0,0 +1,6 @@
+#![feature(unboxed_closures)]
+
+fn foo<F: Fn<i32>>(f: F) -> F::Output { f(3) } //~ ERROR E0059
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0059.stderr b/src/test/ui/error-codes/E0059.stderr
new file mode 100644
index 0000000..a1b8aea
--- /dev/null
+++ b/src/test/ui/error-codes/E0059.stderr
@@ -0,0 +1,9 @@
+error[E0059]: cannot use call notation; the first type parameter for the function trait is neither a tuple nor unit
+  --> $DIR/E0059.rs:3:41
+   |
+LL | fn foo<F: Fn<i32>>(f: F) -> F::Output { f(3) }
+   |                                         ^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0059`.
diff --git a/src/test/ui/error-codes/E0060.rs b/src/test/ui/error-codes/E0060.rs
new file mode 100644
index 0000000..2bb490f
--- /dev/null
+++ b/src/test/ui/error-codes/E0060.rs
@@ -0,0 +1,9 @@
+extern "C" {
+    fn printf(_: *const u8, ...) -> u32;
+}
+
+fn main() {
+    unsafe { printf(); }
+    //~^ ERROR E0060
+    //~| expected at least 1 parameter
+}
diff --git a/src/test/ui/error-codes/E0060.stderr b/src/test/ui/error-codes/E0060.stderr
new file mode 100644
index 0000000..8a2e7d1
--- /dev/null
+++ b/src/test/ui/error-codes/E0060.stderr
@@ -0,0 +1,12 @@
+error[E0060]: this function takes at least 1 parameter but 0 parameters were supplied
+  --> $DIR/E0060.rs:6:14
+   |
+LL |     fn printf(_: *const u8, ...) -> u32;
+   |     ------------------------------------ defined here
+...
+LL |     unsafe { printf(); }
+   |              ^^^^^^^^ expected at least 1 parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0060`.
diff --git a/src/test/ui/error-codes/E0061.rs b/src/test/ui/error-codes/E0061.rs
new file mode 100644
index 0000000..e64ea36
--- /dev/null
+++ b/src/test/ui/error-codes/E0061.rs
@@ -0,0 +1,13 @@
+fn f(a: u16, b: &str) {}
+
+fn f2(a: u16) {}
+
+fn main() {
+    f(0);
+    //~^ ERROR E0061
+    //~| expected 2 parameters
+
+    f2();
+    //~^ ERROR E0061
+    //~| expected 1 parameter
+}
diff --git a/src/test/ui/error-codes/E0061.stderr b/src/test/ui/error-codes/E0061.stderr
new file mode 100644
index 0000000..7310324
--- /dev/null
+++ b/src/test/ui/error-codes/E0061.stderr
@@ -0,0 +1,21 @@
+error[E0061]: this function takes 2 parameters but 1 parameter was supplied
+  --> $DIR/E0061.rs:6:5
+   |
+LL | fn f(a: u16, b: &str) {}
+   | --------------------- defined here
+...
+LL |     f(0);
+   |     ^^^^ expected 2 parameters
+
+error[E0061]: this function takes 1 parameter but 0 parameters were supplied
+  --> $DIR/E0061.rs:10:5
+   |
+LL | fn f2(a: u16) {}
+   | ------------- defined here
+...
+LL |     f2();
+   |     ^^^^ expected 1 parameter
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0061`.
diff --git a/src/test/ui/error-codes/E0062.rs b/src/test/ui/error-codes/E0062.rs
new file mode 100644
index 0000000..3b7f887
--- /dev/null
+++ b/src/test/ui/error-codes/E0062.rs
@@ -0,0 +1,11 @@
+struct Foo {
+    x: i32
+}
+
+fn main() {
+    let x = Foo {
+        x: 0,
+        x: 0,
+        //~^ ERROR E0062
+    };
+}
diff --git a/src/test/ui/error-codes/E0062.stderr b/src/test/ui/error-codes/E0062.stderr
new file mode 100644
index 0000000..a3e1409
--- /dev/null
+++ b/src/test/ui/error-codes/E0062.stderr
@@ -0,0 +1,11 @@
+error[E0062]: field `x` specified more than once
+  --> $DIR/E0062.rs:8:9
+   |
+LL |         x: 0,
+   |         ---- first use of `x`
+LL |         x: 0,
+   |         ^ used more than once
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0062`.
diff --git a/src/test/ui/error-codes/E0063.rs b/src/test/ui/error-codes/E0063.rs
new file mode 100644
index 0000000..37fc0a2
--- /dev/null
+++ b/src/test/ui/error-codes/E0063.rs
@@ -0,0 +1,40 @@
+// ignore-tidy-linelength
+
+struct SingleFoo {
+    x: i32
+}
+
+struct PluralFoo {
+    x: i32,
+    y: i32,
+    z: i32
+}
+
+struct TruncatedFoo {
+    a: i32,
+    b: i32,
+    x: i32,
+    y: i32,
+    z: i32
+}
+
+struct TruncatedPluralFoo {
+    a: i32,
+    b: i32,
+    c: i32,
+    x: i32,
+    y: i32,
+    z: i32
+}
+
+
+fn main() {
+    let w = SingleFoo { };
+    //~^ ERROR missing field `x` in initializer of `SingleFoo`
+    let x = PluralFoo {x: 1};
+    //~^ ERROR missing fields `y`, `z` in initializer of `PluralFoo`
+    let y = TruncatedFoo{x:1};
+    //~^ missing fields `a`, `b`, `y` and 1 other field in initializer of `TruncatedFoo`
+    let z = TruncatedPluralFoo{x:1};
+    //~^ ERROR missing fields `a`, `b`, `c` and 2 other fields in initializer of `TruncatedPluralFoo`
+}
diff --git a/src/test/ui/error-codes/E0063.stderr b/src/test/ui/error-codes/E0063.stderr
new file mode 100644
index 0000000..5d366e0
--- /dev/null
+++ b/src/test/ui/error-codes/E0063.stderr
@@ -0,0 +1,27 @@
+error[E0063]: missing field `x` in initializer of `SingleFoo`
+  --> $DIR/E0063.rs:32:13
+   |
+LL |     let w = SingleFoo { };
+   |             ^^^^^^^^^ missing `x`
+
+error[E0063]: missing fields `y`, `z` in initializer of `PluralFoo`
+  --> $DIR/E0063.rs:34:13
+   |
+LL |     let x = PluralFoo {x: 1};
+   |             ^^^^^^^^^ missing `y`, `z`
+
+error[E0063]: missing fields `a`, `b`, `y` and 1 other field in initializer of `TruncatedFoo`
+  --> $DIR/E0063.rs:36:13
+   |
+LL |     let y = TruncatedFoo{x:1};
+   |             ^^^^^^^^^^^^ missing `a`, `b`, `y` and 1 other field
+
+error[E0063]: missing fields `a`, `b`, `c` and 2 other fields in initializer of `TruncatedPluralFoo`
+  --> $DIR/E0063.rs:38:13
+   |
+LL |     let z = TruncatedPluralFoo{x:1};
+   |             ^^^^^^^^^^^^^^^^^^ missing `a`, `b`, `c` and 2 other fields
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0063`.
diff --git a/src/test/ui/error-codes/E0067.rs b/src/test/ui/error-codes/E0067.rs
new file mode 100644
index 0000000..5925443
--- /dev/null
+++ b/src/test/ui/error-codes/E0067.rs
@@ -0,0 +1,6 @@
+use std::collections::LinkedList;
+
+fn main() {
+    LinkedList::new() += 1; //~ ERROR E0368
+                            //~^ ERROR E0067
+}
diff --git a/src/test/ui/error-codes/E0067.stderr b/src/test/ui/error-codes/E0067.stderr
new file mode 100644
index 0000000..024c868
--- /dev/null
+++ b/src/test/ui/error-codes/E0067.stderr
@@ -0,0 +1,20 @@
+error[E0368]: binary assignment operation `+=` cannot be applied to type `std::collections::LinkedList<_>`
+  --> $DIR/E0067.rs:4:5
+   |
+LL |     LinkedList::new() += 1;
+   |     -----------------^^^^^
+   |     |
+   |     cannot use `+=` on type `std::collections::LinkedList<_>`
+   |
+   = note: an implementation of `std::ops::AddAssign` might be missing for `std::collections::LinkedList<_>`
+
+error[E0067]: invalid left-hand side expression
+  --> $DIR/E0067.rs:4:5
+   |
+LL |     LinkedList::new() += 1;
+   |     ^^^^^^^^^^^^^^^^^ invalid expression for left-hand side
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0067, E0368.
+For more information about an error, try `rustc --explain E0067`.
diff --git a/src/test/ui/error-codes/E0069.rs b/src/test/ui/error-codes/E0069.rs
new file mode 100644
index 0000000..a4ba9fd
--- /dev/null
+++ b/src/test/ui/error-codes/E0069.rs
@@ -0,0 +1,7 @@
+fn foo() -> u8 {
+    return;
+    //~^ ERROR `return;` in a function whose return type is not `()`
+}
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0069.stderr b/src/test/ui/error-codes/E0069.stderr
new file mode 100644
index 0000000..ff9bbe0
--- /dev/null
+++ b/src/test/ui/error-codes/E0069.stderr
@@ -0,0 +1,11 @@
+error[E0069]: `return;` in a function whose return type is not `()`
+  --> $DIR/E0069.rs:2:5
+   |
+LL | fn foo() -> u8 {
+   |             -- expected `u8` because of this return type
+LL |     return;
+   |     ^^^^^^ return type is not `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0069`.
diff --git a/src/test/ui/error-codes/E0070.rs b/src/test/ui/error-codes/E0070.rs
new file mode 100644
index 0000000..ab956d8
--- /dev/null
+++ b/src/test/ui/error-codes/E0070.rs
@@ -0,0 +1,13 @@
+const SOME_CONST : i32 = 12;
+
+fn some_other_func() {}
+
+fn some_function() {
+    SOME_CONST = 14; //~ ERROR E0070
+    1 = 3; //~ ERROR E0070
+    some_other_func() = 4; //~ ERROR E0070
+                           //~^ ERROR E0308
+}
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0070.stderr b/src/test/ui/error-codes/E0070.stderr
new file mode 100644
index 0000000..6592ad3
--- /dev/null
+++ b/src/test/ui/error-codes/E0070.stderr
@@ -0,0 +1,31 @@
+error[E0070]: invalid left-hand side expression
+  --> $DIR/E0070.rs:6:5
+   |
+LL |     SOME_CONST = 14;
+   |     ^^^^^^^^^^^^^^^ left-hand of expression not valid
+
+error[E0070]: invalid left-hand side expression
+  --> $DIR/E0070.rs:7:5
+   |
+LL |     1 = 3;
+   |     ^^^^^ left-hand of expression not valid
+
+error[E0308]: mismatched types
+  --> $DIR/E0070.rs:8:25
+   |
+LL |     some_other_func() = 4;
+   |                         ^ expected (), found integer
+   |
+   = note: expected type `()`
+              found type `{integer}`
+
+error[E0070]: invalid left-hand side expression
+  --> $DIR/E0070.rs:8:5
+   |
+LL |     some_other_func() = 4;
+   |     ^^^^^^^^^^^^^^^^^^^^^ left-hand of expression not valid
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0070, E0308.
+For more information about an error, try `rustc --explain E0070`.
diff --git a/src/test/ui/error-codes/E0071.rs b/src/test/ui/error-codes/E0071.rs
new file mode 100644
index 0000000..bd8469d
--- /dev/null
+++ b/src/test/ui/error-codes/E0071.rs
@@ -0,0 +1,7 @@
+enum Foo {}
+type FooAlias = Foo;
+
+fn main() {
+    let u = FooAlias { value: 0 };
+    //~^ ERROR expected struct, variant or union type, found enum `Foo` [E0071]
+}
diff --git a/src/test/ui/error-codes/E0071.stderr b/src/test/ui/error-codes/E0071.stderr
new file mode 100644
index 0000000..ae312fc
--- /dev/null
+++ b/src/test/ui/error-codes/E0071.stderr
@@ -0,0 +1,9 @@
+error[E0071]: expected struct, variant or union type, found enum `Foo`
+  --> $DIR/E0071.rs:5:13
+   |
+LL |     let u = FooAlias { value: 0 };
+   |             ^^^^^^^^ not a struct
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0071`.
diff --git a/src/test/ui/error-codes/E0075.rs b/src/test/ui/error-codes/E0075.rs
new file mode 100644
index 0000000..7feab0a
--- /dev/null
+++ b/src/test/ui/error-codes/E0075.rs
@@ -0,0 +1,7 @@
+#![feature(repr_simd)]
+
+#[repr(simd)]
+struct Bad; //~ ERROR E0075
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0075.stderr b/src/test/ui/error-codes/E0075.stderr
new file mode 100644
index 0000000..d8b90d0
--- /dev/null
+++ b/src/test/ui/error-codes/E0075.stderr
@@ -0,0 +1,9 @@
+error[E0075]: SIMD vector cannot be empty
+  --> $DIR/E0075.rs:4:1
+   |
+LL | struct Bad;
+   | ^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0075`.
diff --git a/src/test/ui/error-codes/E0076.rs b/src/test/ui/error-codes/E0076.rs
new file mode 100644
index 0000000..a27072e
--- /dev/null
+++ b/src/test/ui/error-codes/E0076.rs
@@ -0,0 +1,8 @@
+#![feature(repr_simd)]
+
+#[repr(simd)]
+struct Bad(u16, u32, u32);
+//~^ ERROR E0076
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0076.stderr b/src/test/ui/error-codes/E0076.stderr
new file mode 100644
index 0000000..2c2842d
--- /dev/null
+++ b/src/test/ui/error-codes/E0076.stderr
@@ -0,0 +1,9 @@
+error[E0076]: SIMD vector should be homogeneous
+  --> $DIR/E0076.rs:4:1
+   |
+LL | struct Bad(u16, u32, u32);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^ SIMD elements must have the same type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0076`.
diff --git a/src/test/ui/error-codes/E0077.rs b/src/test/ui/error-codes/E0077.rs
new file mode 100644
index 0000000..fa2d5e2
--- /dev/null
+++ b/src/test/ui/error-codes/E0077.rs
@@ -0,0 +1,7 @@
+#![feature(repr_simd)]
+
+#[repr(simd)]
+struct Bad(String); //~ ERROR E0077
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0077.stderr b/src/test/ui/error-codes/E0077.stderr
new file mode 100644
index 0000000..4f85d17
--- /dev/null
+++ b/src/test/ui/error-codes/E0077.stderr
@@ -0,0 +1,9 @@
+error[E0077]: SIMD vector element type should be machine type
+  --> $DIR/E0077.rs:4:1
+   |
+LL | struct Bad(String);
+   | ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0077`.
diff --git a/src/test/ui/error-codes/E0080.rs b/src/test/ui/error-codes/E0080.rs
new file mode 100644
index 0000000..ac0e773
--- /dev/null
+++ b/src/test/ui/error-codes/E0080.rs
@@ -0,0 +1,8 @@
+enum Enum {
+    X = (1 << 500), //~ ERROR E0080
+    //~| shift left with overflow
+    Y = (1 / 0) //~ ERROR E0080
+}
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0080.stderr b/src/test/ui/error-codes/E0080.stderr
new file mode 100644
index 0000000..3113fd2
--- /dev/null
+++ b/src/test/ui/error-codes/E0080.stderr
@@ -0,0 +1,15 @@
+error[E0080]: evaluation of constant value failed
+  --> $DIR/E0080.rs:2:9
+   |
+LL |     X = (1 << 500),
+   |         ^^^^^^^^^^ attempt to shift left with overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/E0080.rs:4:9
+   |
+LL |     Y = (1 / 0)
+   |         ^^^^^^^ attempt to divide by zero
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/error-codes/E0081.rs b/src/test/ui/error-codes/E0081.rs
new file mode 100644
index 0000000..33c8c14
--- /dev/null
+++ b/src/test/ui/error-codes/E0081.rs
@@ -0,0 +1,9 @@
+enum Enum {
+    P = 3,
+    X = 3,
+    //~^ ERROR discriminant value `3` already exists
+    Y = 5
+}
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0081.stderr b/src/test/ui/error-codes/E0081.stderr
new file mode 100644
index 0000000..0b3d351
--- /dev/null
+++ b/src/test/ui/error-codes/E0081.stderr
@@ -0,0 +1,11 @@
+error[E0081]: discriminant value `3` already exists
+  --> $DIR/E0081.rs:3:9
+   |
+LL |     P = 3,
+   |         - first use of `3`
+LL |     X = 3,
+   |         ^ enum already has `3`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0081`.
diff --git a/src/test/ui/error-codes/E0084.rs b/src/test/ui/error-codes/E0084.rs
new file mode 100644
index 0000000..a550e04
--- /dev/null
+++ b/src/test/ui/error-codes/E0084.rs
@@ -0,0 +1,5 @@
+#[repr(i32)] //~ ERROR: E0084
+enum Foo {}
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0084.stderr b/src/test/ui/error-codes/E0084.stderr
new file mode 100644
index 0000000..1f818da
--- /dev/null
+++ b/src/test/ui/error-codes/E0084.stderr
@@ -0,0 +1,11 @@
+error[E0084]: unsupported representation for zero-variant enum
+  --> $DIR/E0084.rs:1:1
+   |
+LL | #[repr(i32)]
+   | ^^^^^^^^^^^^
+LL | enum Foo {}
+   | ----------- zero-variant enum
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0084`.
diff --git a/src/test/ui/error-codes/E0091.rs b/src/test/ui/error-codes/E0091.rs
new file mode 100644
index 0000000..2427f5c
--- /dev/null
+++ b/src/test/ui/error-codes/E0091.rs
@@ -0,0 +1,5 @@
+type Foo<T> = u32; //~ ERROR E0091
+type Foo2<A, B> = Box<A>; //~ ERROR E0091
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0091.stderr b/src/test/ui/error-codes/E0091.stderr
new file mode 100644
index 0000000..a596b75
--- /dev/null
+++ b/src/test/ui/error-codes/E0091.stderr
@@ -0,0 +1,15 @@
+error[E0091]: type parameter `T` is unused
+  --> $DIR/E0091.rs:1:10
+   |
+LL | type Foo<T> = u32;
+   |          ^ unused type parameter
+
+error[E0091]: type parameter `B` is unused
+  --> $DIR/E0091.rs:2:14
+   |
+LL | type Foo2<A, B> = Box<A>;
+   |              ^ unused type parameter
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0091`.
diff --git a/src/test/ui/error-codes/E0092.rs b/src/test/ui/error-codes/E0092.rs
new file mode 100644
index 0000000..ddaace9
--- /dev/null
+++ b/src/test/ui/error-codes/E0092.rs
@@ -0,0 +1,7 @@
+#![feature(intrinsics)]
+extern "rust-intrinsic" {
+    fn atomic_foo(); //~ ERROR E0092
+}
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0092.stderr b/src/test/ui/error-codes/E0092.stderr
new file mode 100644
index 0000000..2d590a8
--- /dev/null
+++ b/src/test/ui/error-codes/E0092.stderr
@@ -0,0 +1,9 @@
+error[E0092]: unrecognized atomic operation function: `foo`
+  --> $DIR/E0092.rs:3:5
+   |
+LL |     fn atomic_foo();
+   |     ^^^^^^^^^^^^^^^^ unrecognized atomic operation
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0092`.
diff --git a/src/test/ui/error-codes/E0093.rs b/src/test/ui/error-codes/E0093.rs
new file mode 100644
index 0000000..a2f0b1a
--- /dev/null
+++ b/src/test/ui/error-codes/E0093.rs
@@ -0,0 +1,8 @@
+#![feature(intrinsics)]
+extern "rust-intrinsic" {
+    fn foo();
+    //~^ ERROR E0093
+}
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0093.stderr b/src/test/ui/error-codes/E0093.stderr
new file mode 100644
index 0000000..cb03055
--- /dev/null
+++ b/src/test/ui/error-codes/E0093.stderr
@@ -0,0 +1,9 @@
+error[E0093]: unrecognized intrinsic function: `foo`
+  --> $DIR/E0093.rs:3:5
+   |
+LL |     fn foo();
+   |     ^^^^^^^^^ unrecognized intrinsic
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0093`.
diff --git a/src/test/ui/error-codes/E0094.rs b/src/test/ui/error-codes/E0094.rs
new file mode 100644
index 0000000..0d58e5a
--- /dev/null
+++ b/src/test/ui/error-codes/E0094.rs
@@ -0,0 +1,7 @@
+#![feature(intrinsics)]
+extern "rust-intrinsic" {
+    fn size_of<T, U>() -> usize; //~ ERROR E0094
+}
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0094.stderr b/src/test/ui/error-codes/E0094.stderr
new file mode 100644
index 0000000..da97f3a
--- /dev/null
+++ b/src/test/ui/error-codes/E0094.stderr
@@ -0,0 +1,9 @@
+error[E0094]: intrinsic has wrong number of type parameters: found 2, expected 1
+  --> $DIR/E0094.rs:3:15
+   |
+LL |     fn size_of<T, U>() -> usize;
+   |               ^^^^^^ expected 1 type parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0094`.
diff --git a/src/test/ui/error-codes/E0106.rs b/src/test/ui/error-codes/E0106.rs
new file mode 100644
index 0000000..d6537d1
--- /dev/null
+++ b/src/test/ui/error-codes/E0106.rs
@@ -0,0 +1,26 @@
+struct Foo {
+    x: &bool,
+    //~^ ERROR E0106
+}
+enum Bar {
+    A(u8),
+    B(&bool),
+   //~^ ERROR E0106
+}
+type MyStr = &str;
+        //~^ ERROR E0106
+
+struct Baz<'a>(&'a str);
+struct Buzz<'a, 'b>(&'a str, &'b str);
+
+struct Quux {
+    baz: Baz,
+    //~^ ERROR E0106
+    //~| expected lifetime parameter
+    buzz: Buzz,
+    //~^ ERROR E0106
+    //~| expected 2 lifetime parameters
+}
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0106.stderr b/src/test/ui/error-codes/E0106.stderr
new file mode 100644
index 0000000..cea9581
--- /dev/null
+++ b/src/test/ui/error-codes/E0106.stderr
@@ -0,0 +1,33 @@
+error[E0106]: missing lifetime specifier
+  --> $DIR/E0106.rs:2:8
+   |
+LL |     x: &bool,
+   |        ^ expected lifetime parameter
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/E0106.rs:7:7
+   |
+LL |     B(&bool),
+   |       ^ expected lifetime parameter
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/E0106.rs:10:14
+   |
+LL | type MyStr = &str;
+   |              ^ expected lifetime parameter
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/E0106.rs:17:10
+   |
+LL |     baz: Baz,
+   |          ^^^ expected lifetime parameter
+
+error[E0106]: missing lifetime specifiers
+  --> $DIR/E0106.rs:20:11
+   |
+LL |     buzz: Buzz,
+   |           ^^^^ expected 2 lifetime parameters
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0106`.
diff --git a/src/test/ui/error-codes/E0107.rs b/src/test/ui/error-codes/E0107.rs
new file mode 100644
index 0000000..35173dc
--- /dev/null
+++ b/src/test/ui/error-codes/E0107.rs
@@ -0,0 +1,23 @@
+struct Foo<'a>(&'a str);
+struct Buzz<'a, 'b>(&'a str, &'b str);
+
+enum Bar {
+    A,
+    B,
+    C,
+}
+
+struct Baz<'a, 'b, 'c> {
+    buzz: Buzz<'a>,
+    //~^ ERROR E0107
+    //~| expected 2 lifetime arguments
+    bar: Bar<'a>,
+    //~^ ERROR E0107
+    //~| unexpected lifetime argument
+    foo2: Foo<'a, 'b, 'c>,
+    //~^ ERROR E0107
+    //~| unexpected lifetime argument
+    //~| unexpected lifetime argument
+}
+
+fn main() {}
diff --git a/src/test/ui/error-codes/E0107.stderr b/src/test/ui/error-codes/E0107.stderr
new file mode 100644
index 0000000..486810a
--- /dev/null
+++ b/src/test/ui/error-codes/E0107.stderr
@@ -0,0 +1,23 @@
+error[E0107]: wrong number of lifetime arguments: expected 2, found 1
+  --> $DIR/E0107.rs:11:11
+   |
+LL |     buzz: Buzz<'a>,
+   |           ^^^^^^^^ expected 2 lifetime arguments
+
+error[E0107]: wrong number of lifetime arguments: expected 0, found 1
+  --> $DIR/E0107.rs:14:14
+   |
+LL |     bar: Bar<'a>,
+   |              ^^ unexpected lifetime argument
+
+error[E0107]: wrong number of lifetime arguments: expected 1, found 3
+  --> $DIR/E0107.rs:17:19
+   |
+LL |     foo2: Foo<'a, 'b, 'c>,
+   |                   ^^  ^^ unexpected lifetime argument
+   |                   |
+   |                   unexpected lifetime argument
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0107`.
diff --git a/src/test/ui/error-codes/E0109.rs b/src/test/ui/error-codes/E0109.rs
new file mode 100644
index 0000000..2e38256
--- /dev/null
+++ b/src/test/ui/error-codes/E0109.rs
@@ -0,0 +1,4 @@
+type X = u32<i32>; //~ ERROR E0109
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0109.stderr b/src/test/ui/error-codes/E0109.stderr
new file mode 100644
index 0000000..577e286
--- /dev/null
+++ b/src/test/ui/error-codes/E0109.stderr
@@ -0,0 +1,9 @@
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/E0109.rs:1:14
+   |
+LL | type X = u32<i32>;
+   |              ^^^ type argument not allowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0109`.
diff --git a/src/test/ui/error-codes/E0110.rs b/src/test/ui/error-codes/E0110.rs
new file mode 100644
index 0000000..314c7f5
--- /dev/null
+++ b/src/test/ui/error-codes/E0110.rs
@@ -0,0 +1,3 @@
+type X = u32<'static>; //~ ERROR E0109
+
+fn main() {}
diff --git a/src/test/ui/error-codes/E0110.stderr b/src/test/ui/error-codes/E0110.stderr
new file mode 100644
index 0000000..b022131
--- /dev/null
+++ b/src/test/ui/error-codes/E0110.stderr
@@ -0,0 +1,9 @@
+error[E0109]: lifetime arguments are not allowed for this type
+  --> $DIR/E0110.rs:1:14
+   |
+LL | type X = u32<'static>;
+   |              ^^^^^^^ lifetime argument not allowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0109`.
diff --git a/src/test/ui/error-codes/E0116.rs b/src/test/ui/error-codes/E0116.rs
new file mode 100644
index 0000000..898beb1
--- /dev/null
+++ b/src/test/ui/error-codes/E0116.rs
@@ -0,0 +1,5 @@
+impl Vec<u8> {}
+//~^ ERROR E0116
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0116.stderr b/src/test/ui/error-codes/E0116.stderr
new file mode 100644
index 0000000..a5ceeb4
--- /dev/null
+++ b/src/test/ui/error-codes/E0116.stderr
@@ -0,0 +1,11 @@
+error[E0116]: cannot define inherent `impl` for a type outside of the crate where the type is defined
+  --> $DIR/E0116.rs:1:1
+   |
+LL | impl Vec<u8> {}
+   | ^^^^^^^^^^^^^^^ impl for type defined outside of crate.
+   |
+   = note: define and implement a trait or new type instead
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0116`.
diff --git a/src/test/ui/error-codes/E0117.rs b/src/test/ui/error-codes/E0117.rs
new file mode 100644
index 0000000..18dd809
--- /dev/null
+++ b/src/test/ui/error-codes/E0117.rs
@@ -0,0 +1,6 @@
+impl Drop for u32 {} //~ ERROR E0117
+//~| ERROR the Drop trait may only be implemented on structures
+//~| implementing Drop requires a struct
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0117.stderr b/src/test/ui/error-codes/E0117.stderr
new file mode 100644
index 0000000..80b3a4e
--- /dev/null
+++ b/src/test/ui/error-codes/E0117.stderr
@@ -0,0 +1,19 @@
+error[E0120]: the Drop trait may only be implemented on structures
+  --> $DIR/E0117.rs:1:15
+   |
+LL | impl Drop for u32 {}
+   |               ^^^ implementing Drop requires a struct
+
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/E0117.rs:1:1
+   |
+LL | impl Drop for u32 {}
+   | ^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0117, E0120.
+For more information about an error, try `rustc --explain E0117`.
diff --git a/src/test/ui/error-codes/E0118.rs b/src/test/ui/error-codes/E0118.rs
new file mode 100644
index 0000000..7bf3621
--- /dev/null
+++ b/src/test/ui/error-codes/E0118.rs
@@ -0,0 +1,8 @@
+impl (u8, u8) { //~ ERROR E0118
+    fn get_state(&self) -> String {
+        String::new()
+    }
+}
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0118.stderr b/src/test/ui/error-codes/E0118.stderr
new file mode 100644
index 0000000..b0afaeb
--- /dev/null
+++ b/src/test/ui/error-codes/E0118.stderr
@@ -0,0 +1,11 @@
+error[E0118]: no base type found for inherent implementation
+  --> $DIR/E0118.rs:1:6
+   |
+LL | impl (u8, u8) {
+   |      ^^^^^^^^ impl requires a base type
+   |
+   = note: either implement a trait on it or create a newtype to wrap it instead
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0118`.
diff --git a/src/test/ui/error-codes/E0119.rs b/src/test/ui/error-codes/E0119.rs
new file mode 100644
index 0000000..7f89e5a
--- /dev/null
+++ b/src/test/ui/error-codes/E0119.rs
@@ -0,0 +1,18 @@
+trait MyTrait {
+    fn get(&self) -> usize;
+}
+
+impl<T> MyTrait for T {
+    fn get(&self) -> usize { 0 }
+}
+
+struct Foo {
+    value: usize
+}
+
+impl MyTrait for Foo { //~ ERROR E0119
+    fn get(&self) -> usize { self.value }
+}
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0119.stderr b/src/test/ui/error-codes/E0119.stderr
new file mode 100644
index 0000000..e7690aa
--- /dev/null
+++ b/src/test/ui/error-codes/E0119.stderr
@@ -0,0 +1,12 @@
+error[E0119]: conflicting implementations of trait `MyTrait` for type `Foo`:
+  --> $DIR/E0119.rs:13:1
+   |
+LL | impl<T> MyTrait for T {
+   | --------------------- first implementation here
+...
+LL | impl MyTrait for Foo {
+   | ^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/error-codes/E0120.rs b/src/test/ui/error-codes/E0120.rs
new file mode 100644
index 0000000..0497074
--- /dev/null
+++ b/src/test/ui/error-codes/E0120.rs
@@ -0,0 +1,9 @@
+trait MyTrait { fn foo() {} }
+
+impl Drop for MyTrait {
+              //~^ ERROR E0120
+    fn drop(&mut self) {}
+}
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0120.stderr b/src/test/ui/error-codes/E0120.stderr
new file mode 100644
index 0000000..9b6603d
--- /dev/null
+++ b/src/test/ui/error-codes/E0120.stderr
@@ -0,0 +1,9 @@
+error[E0120]: the Drop trait may only be implemented on structures
+  --> $DIR/E0120.rs:3:15
+   |
+LL | impl Drop for MyTrait {
+   |               ^^^^^^^ implementing Drop requires a struct
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0120`.
diff --git a/src/test/ui/error-codes/E0121.rs b/src/test/ui/error-codes/E0121.rs
new file mode 100644
index 0000000..f8b4d61
--- /dev/null
+++ b/src/test/ui/error-codes/E0121.rs
@@ -0,0 +1,6 @@
+fn foo() -> _ { 5 } //~ ERROR E0121
+
+static BAR: _ = "test"; //~ ERROR E0121
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0121.stderr b/src/test/ui/error-codes/E0121.stderr
new file mode 100644
index 0000000..b7f4ce4
--- /dev/null
+++ b/src/test/ui/error-codes/E0121.stderr
@@ -0,0 +1,15 @@
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/E0121.rs:1:13
+   |
+LL | fn foo() -> _ { 5 }
+   |             ^ not allowed in type signatures
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/E0121.rs:3:13
+   |
+LL | static BAR: _ = "test";
+   |             ^ not allowed in type signatures
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0121`.
diff --git a/src/test/ui/error-codes/E0124.rs b/src/test/ui/error-codes/E0124.rs
new file mode 100644
index 0000000..9d6a716
--- /dev/null
+++ b/src/test/ui/error-codes/E0124.rs
@@ -0,0 +1,8 @@
+struct Foo {
+    field1: i32,
+    field1: i32,
+    //~^ ERROR field `field1` is already declared [E0124]
+}
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0124.stderr b/src/test/ui/error-codes/E0124.stderr
new file mode 100644
index 0000000..73819a8
--- /dev/null
+++ b/src/test/ui/error-codes/E0124.stderr
@@ -0,0 +1,11 @@
+error[E0124]: field `field1` is already declared
+  --> $DIR/E0124.rs:3:5
+   |
+LL |     field1: i32,
+   |     ----------- `field1` first declared here
+LL |     field1: i32,
+   |     ^^^^^^^^^^^ field already declared
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0124`.
diff --git a/src/test/ui/error-codes/E0128.rs b/src/test/ui/error-codes/E0128.rs
new file mode 100644
index 0000000..f42c32b
--- /dev/null
+++ b/src/test/ui/error-codes/E0128.rs
@@ -0,0 +1,7 @@
+struct Foo<T=U, U=()> { //~ ERROR E0128
+    field1: T,
+    field2: U,
+}
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0128.stderr b/src/test/ui/error-codes/E0128.stderr
new file mode 100644
index 0000000..253aa16
--- /dev/null
+++ b/src/test/ui/error-codes/E0128.stderr
@@ -0,0 +1,9 @@
+error[E0128]: type parameters with a default cannot use forward declared identifiers
+  --> $DIR/E0128.rs:1:14
+   |
+LL | struct Foo<T=U, U=()> {
+   |              ^ defaulted type parameters cannot be forward declared
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0128`.
diff --git a/src/test/ui/error-codes/E0130.rs b/src/test/ui/error-codes/E0130.rs
new file mode 100644
index 0000000..1ac546b
--- /dev/null
+++ b/src/test/ui/error-codes/E0130.rs
@@ -0,0 +1,7 @@
+extern {
+    fn foo((a, b): (u32, u32));
+    //~^ ERROR E0130
+}
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0130.stderr b/src/test/ui/error-codes/E0130.stderr
new file mode 100644
index 0000000..a45571f
--- /dev/null
+++ b/src/test/ui/error-codes/E0130.stderr
@@ -0,0 +1,9 @@
+error[E0130]: patterns aren't allowed in foreign function declarations
+  --> $DIR/E0130.rs:2:12
+   |
+LL |     fn foo((a, b): (u32, u32));
+   |            ^^^^^^ pattern not allowed in foreign function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0130`.
diff --git a/src/test/ui/error-codes/E0131.rs b/src/test/ui/error-codes/E0131.rs
new file mode 100644
index 0000000..3ed7399
--- /dev/null
+++ b/src/test/ui/error-codes/E0131.rs
@@ -0,0 +1,3 @@
+fn main<T>() {
+    //~^ ERROR E0131
+}
diff --git a/src/test/ui/error-codes/E0131.stderr b/src/test/ui/error-codes/E0131.stderr
new file mode 100644
index 0000000..4467e19
--- /dev/null
+++ b/src/test/ui/error-codes/E0131.stderr
@@ -0,0 +1,9 @@
+error[E0131]: `main` function is not allowed to have generic parameters
+  --> $DIR/E0131.rs:1:8
+   |
+LL | fn main<T>() {
+   |        ^^^ `main` cannot have generic parameters
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0131`.
diff --git a/src/test/ui/error-codes/E0132.rs b/src/test/ui/error-codes/E0132.rs
new file mode 100644
index 0000000..fb5e5d7
--- /dev/null
+++ b/src/test/ui/error-codes/E0132.rs
@@ -0,0 +1,7 @@
+#![feature(start)]
+
+#[start]
+fn f< T >() {} //~ ERROR E0132
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0132.stderr b/src/test/ui/error-codes/E0132.stderr
new file mode 100644
index 0000000..c213637
--- /dev/null
+++ b/src/test/ui/error-codes/E0132.stderr
@@ -0,0 +1,9 @@
+error[E0132]: start function is not allowed to have type parameters
+  --> $DIR/E0132.rs:4:5
+   |
+LL | fn f< T >() {}
+   |     ^^^^^ start function cannot have type parameters
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0132`.
diff --git a/src/test/ui/error-codes/E0133.rs b/src/test/ui/error-codes/E0133.rs
new file mode 100644
index 0000000..52494ce
--- /dev/null
+++ b/src/test/ui/error-codes/E0133.rs
@@ -0,0 +1,6 @@
+unsafe fn f() { return; }
+
+fn main() {
+    f();
+    //~^ ERROR E0133
+}
diff --git a/src/test/ui/error-codes/E0133.stderr b/src/test/ui/error-codes/E0133.stderr
new file mode 100644
index 0000000..1eb6965
--- /dev/null
+++ b/src/test/ui/error-codes/E0133.stderr
@@ -0,0 +1,11 @@
+error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
+  --> $DIR/E0133.rs:4:5
+   |
+LL |     f();
+   |     ^^^ call to unsafe function
+   |
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/error-codes/E0137.rs b/src/test/ui/error-codes/E0137.rs
new file mode 100644
index 0000000..b8299c7
--- /dev/null
+++ b/src/test/ui/error-codes/E0137.rs
@@ -0,0 +1,8 @@
+#![feature(main)]
+
+#[main]
+fn foo() {}
+
+#[main]
+fn f() {}
+//~^ ERROR E0137
diff --git a/src/test/ui/error-codes/E0137.stderr b/src/test/ui/error-codes/E0137.stderr
new file mode 100644
index 0000000..a5f05d3
--- /dev/null
+++ b/src/test/ui/error-codes/E0137.stderr
@@ -0,0 +1,12 @@
+error[E0137]: multiple functions with a #[main] attribute
+  --> $DIR/E0137.rs:7:1
+   |
+LL | fn foo() {}
+   | ----------- first #[main] function
+...
+LL | fn f() {}
+   | ^^^^^^^^^ additional #[main] function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0137`.
diff --git a/src/test/ui/error-codes/E0138.rs b/src/test/ui/error-codes/E0138.rs
new file mode 100644
index 0000000..6f3c362
--- /dev/null
+++ b/src/test/ui/error-codes/E0138.rs
@@ -0,0 +1,8 @@
+#![feature(start)]
+
+#[start]
+fn foo(argc: isize, argv: *const *const u8) -> isize { 0 }
+
+#[start]
+fn f(argc: isize, argv: *const *const u8) -> isize { 0 }
+//~^ ERROR E0138
diff --git a/src/test/ui/error-codes/E0138.stderr b/src/test/ui/error-codes/E0138.stderr
new file mode 100644
index 0000000..745dccf
--- /dev/null
+++ b/src/test/ui/error-codes/E0138.stderr
@@ -0,0 +1,12 @@
+error[E0138]: multiple 'start' functions
+  --> $DIR/E0138.rs:7:1
+   |
+LL | fn foo(argc: isize, argv: *const *const u8) -> isize { 0 }
+   | ---------------------------------------------------------- previous `start` function here
+...
+LL | fn f(argc: isize, argv: *const *const u8) -> isize { 0 }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ multiple `start` functions
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0138`.
diff --git a/src/test/ui/error-codes/E0152.rs b/src/test/ui/error-codes/E0152.rs
new file mode 100644
index 0000000..dcaf920
--- /dev/null
+++ b/src/test/ui/error-codes/E0152.rs
@@ -0,0 +1,7 @@
+#![feature(lang_items)]
+
+#[lang = "arc"]
+struct Foo; //~ ERROR E0152
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0152.stderr b/src/test/ui/error-codes/E0152.stderr
new file mode 100644
index 0000000..26e6e2e
--- /dev/null
+++ b/src/test/ui/error-codes/E0152.stderr
@@ -0,0 +1,11 @@
+error[E0152]: duplicate lang item found: `arc`.
+  --> $DIR/E0152.rs:4:1
+   |
+LL | struct Foo;
+   | ^^^^^^^^^^^
+   |
+   = note: first defined in crate `alloc`.
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0152`.
diff --git a/src/test/ui/error-codes/E0161.ast.stderr b/src/test/ui/error-codes/E0161.ast.stderr
new file mode 100644
index 0000000..536a81a
--- /dev/null
+++ b/src/test/ui/error-codes/E0161.ast.stderr
@@ -0,0 +1,9 @@
+error[E0161]: cannot move a value of type [i32]: the size of [i32] cannot be statically determined
+  --> $DIR/E0161.rs:22:9
+   |
+LL |     box *x;
+   |         ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0161`.
diff --git a/src/test/ui/error-codes/E0161.astul.stderr b/src/test/ui/error-codes/E0161.astul.stderr
new file mode 100644
index 0000000..2baba99
--- /dev/null
+++ b/src/test/ui/error-codes/E0161.astul.stderr
@@ -0,0 +1,9 @@
+error[E0161]: cannot move a value of type [i32]: the size of [i32] cannot be statically determined
+  --> $DIR/E0161.rs:22:5
+   |
+LL |     box *x;
+   |     ^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0161`.
diff --git a/src/test/ui/error-codes/E0161.edition.stderr b/src/test/ui/error-codes/E0161.edition.stderr
new file mode 100644
index 0000000..536a81a
--- /dev/null
+++ b/src/test/ui/error-codes/E0161.edition.stderr
@@ -0,0 +1,9 @@
+error[E0161]: cannot move a value of type [i32]: the size of [i32] cannot be statically determined
+  --> $DIR/E0161.rs:22:9
+   |
+LL |     box *x;
+   |         ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0161`.
diff --git a/src/test/ui/error-codes/E0161.editionul.stderr b/src/test/ui/error-codes/E0161.editionul.stderr
new file mode 100644
index 0000000..2baba99
--- /dev/null
+++ b/src/test/ui/error-codes/E0161.editionul.stderr
@@ -0,0 +1,9 @@
+error[E0161]: cannot move a value of type [i32]: the size of [i32] cannot be statically determined
+  --> $DIR/E0161.rs:22:5
+   |
+LL |     box *x;
+   |     ^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0161`.
diff --git a/src/test/ui/error-codes/E0161.nll.stderr b/src/test/ui/error-codes/E0161.nll.stderr
new file mode 100644
index 0000000..536a81a
--- /dev/null
+++ b/src/test/ui/error-codes/E0161.nll.stderr
@@ -0,0 +1,9 @@
+error[E0161]: cannot move a value of type [i32]: the size of [i32] cannot be statically determined
+  --> $DIR/E0161.rs:22:9
+   |
+LL |     box *x;
+   |         ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0161`.
diff --git a/src/test/ui/error-codes/E0161.nllul.stderr b/src/test/ui/error-codes/E0161.nllul.stderr
new file mode 100644
index 0000000..2baba99
--- /dev/null
+++ b/src/test/ui/error-codes/E0161.nllul.stderr
@@ -0,0 +1,9 @@
+error[E0161]: cannot move a value of type [i32]: the size of [i32] cannot be statically determined
+  --> $DIR/E0161.rs:22:5
+   |
+LL |     box *x;
+   |     ^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0161`.
diff --git a/src/test/ui/error-codes/E0161.rs b/src/test/ui/error-codes/E0161.rs
new file mode 100644
index 0000000..a6d2b24
--- /dev/null
+++ b/src/test/ui/error-codes/E0161.rs
@@ -0,0 +1,33 @@
+// ignore-compare-mode-nll
+
+// Check that E0161 is a hard error in all possible configurations that might
+// affect it.
+
+// revisions: ast nll zflags edition astul nllul zflagsul editionul
+//[zflags]compile-flags: -Z borrowck=migrate -Z two-phase-borrows
+//[edition]edition:2018
+//[zflagsul]compile-flags: -Z borrowck=migrate -Z two-phase-borrows
+//[editionul]edition:2018
+
+#![cfg_attr(nll, feature(nll))]
+#![cfg_attr(nllul, feature(nll))]
+#![cfg_attr(astul, feature(unsized_locals))]
+#![cfg_attr(zflagsul, feature(unsized_locals))]
+#![cfg_attr(nllul, feature(unsized_locals))]
+#![cfg_attr(editionul, feature(unsized_locals))]
+
+#![feature(box_syntax)]
+
+fn foo(x: Box<[i32]>) {
+    box *x;
+    //[ast]~^ ERROR E0161
+    //[nll]~^^ ERROR E0161
+    //[zflags]~^^^ ERROR E0161
+    //[edition]~^^^^ ERROR E0161
+    //[astul]~^^^^^ ERROR E0161
+    //[nllul]~^^^^^^ ERROR E0161
+    //[zflagsul]~^^^^^^^ ERROR E0161
+    //[editionul]~^^^^^^^^ ERROR E0161
+}
+
+fn main() {}
diff --git a/src/test/ui/error-codes/E0161.zflags.stderr b/src/test/ui/error-codes/E0161.zflags.stderr
new file mode 100644
index 0000000..536a81a
--- /dev/null
+++ b/src/test/ui/error-codes/E0161.zflags.stderr
@@ -0,0 +1,9 @@
+error[E0161]: cannot move a value of type [i32]: the size of [i32] cannot be statically determined
+  --> $DIR/E0161.rs:22:9
+   |
+LL |     box *x;
+   |         ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0161`.
diff --git a/src/test/ui/error-codes/E0161.zflagsul.stderr b/src/test/ui/error-codes/E0161.zflagsul.stderr
new file mode 100644
index 0000000..2baba99
--- /dev/null
+++ b/src/test/ui/error-codes/E0161.zflagsul.stderr
@@ -0,0 +1,9 @@
+error[E0161]: cannot move a value of type [i32]: the size of [i32] cannot be statically determined
+  --> $DIR/E0161.rs:22:5
+   |
+LL |     box *x;
+   |     ^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0161`.
diff --git a/src/test/ui/error-codes/E0164.rs b/src/test/ui/error-codes/E0164.rs
new file mode 100644
index 0000000..2d412f7
--- /dev/null
+++ b/src/test/ui/error-codes/E0164.rs
@@ -0,0 +1,14 @@
+enum Foo {}
+
+impl Foo {
+    const B: u8 = 0;
+}
+
+fn bar(foo: Foo) -> u32 {
+    match foo {
+        Foo::B(i) => i, //~ ERROR E0164
+    }
+}
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0164.stderr b/src/test/ui/error-codes/E0164.stderr
new file mode 100644
index 0000000..0a153d8
--- /dev/null
+++ b/src/test/ui/error-codes/E0164.stderr
@@ -0,0 +1,9 @@
+error[E0164]: expected tuple struct/variant, found associated constant `<Foo>::B`
+  --> $DIR/E0164.rs:9:9
+   |
+LL |         Foo::B(i) => i,
+   |         ^^^^^^^^^ not a tuple variant or struct
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0164`.
diff --git a/src/test/ui/error-codes/E0184.rs b/src/test/ui/error-codes/E0184.rs
new file mode 100644
index 0000000..0c448e4
--- /dev/null
+++ b/src/test/ui/error-codes/E0184.rs
@@ -0,0 +1,10 @@
+#[derive(Copy)] //~ ERROR E0184
+struct Foo;
+
+impl Drop for Foo {
+    fn drop(&mut self) {
+    }
+}
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0184.stderr b/src/test/ui/error-codes/E0184.stderr
new file mode 100644
index 0000000..b4128b9
--- /dev/null
+++ b/src/test/ui/error-codes/E0184.stderr
@@ -0,0 +1,9 @@
+error[E0184]: the trait `Copy` may not be implemented for this type; the type has a destructor
+  --> $DIR/E0184.rs:1:10
+   |
+LL | #[derive(Copy)]
+   |          ^^^^ Copy not allowed on types with destructors
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0184`.
diff --git a/src/test/ui/error-codes/E0185.rs b/src/test/ui/error-codes/E0185.rs
new file mode 100644
index 0000000..45eb8b0
--- /dev/null
+++ b/src/test/ui/error-codes/E0185.rs
@@ -0,0 +1,15 @@
+trait Foo {
+    fn foo();
+    //~^ NOTE trait method declared without `&self`
+}
+
+struct Bar;
+
+impl Foo for Bar {
+    fn foo(&self) {}
+    //~^ ERROR E0185
+    //~| NOTE `&self` used in impl
+}
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0185.stderr b/src/test/ui/error-codes/E0185.stderr
new file mode 100644
index 0000000..8a99c06
--- /dev/null
+++ b/src/test/ui/error-codes/E0185.stderr
@@ -0,0 +1,12 @@
+error[E0185]: method `foo` has a `&self` declaration in the impl, but not in the trait
+  --> $DIR/E0185.rs:9:5
+   |
+LL |     fn foo();
+   |     --------- trait method declared without `&self`
+...
+LL |     fn foo(&self) {}
+   |     ^^^^^^^^^^^^^ `&self` used in impl
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0185`.
diff --git a/src/test/ui/error-codes/E0186.rs b/src/test/ui/error-codes/E0186.rs
new file mode 100644
index 0000000..83ef78e
--- /dev/null
+++ b/src/test/ui/error-codes/E0186.rs
@@ -0,0 +1,13 @@
+trait Foo {
+    fn foo(&self); //~ `&self` used in trait
+}
+
+struct Bar;
+
+impl Foo for Bar {
+    fn foo() {} //~ ERROR E0186
+    //~^ expected `&self` in impl
+}
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0186.stderr b/src/test/ui/error-codes/E0186.stderr
new file mode 100644
index 0000000..8971d61
--- /dev/null
+++ b/src/test/ui/error-codes/E0186.stderr
@@ -0,0 +1,12 @@
+error[E0186]: method `foo` has a `&self` declaration in the trait, but not in the impl
+  --> $DIR/E0186.rs:8:5
+   |
+LL |     fn foo(&self);
+   |     -------------- `&self` used in trait
+...
+LL |     fn foo() {}
+   |     ^^^^^^^^ expected `&self` in impl
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0186`.
diff --git a/src/test/ui/error-codes/E0191.rs b/src/test/ui/error-codes/E0191.rs
new file mode 100644
index 0000000..3561106
--- /dev/null
+++ b/src/test/ui/error-codes/E0191.rs
@@ -0,0 +1,7 @@
+trait Trait {
+    type Bar;
+}
+
+type Foo = Trait; //~ ERROR E0191
+
+fn main() {}
diff --git a/src/test/ui/error-codes/E0191.stderr b/src/test/ui/error-codes/E0191.stderr
new file mode 100644
index 0000000..2d9fdfe
--- /dev/null
+++ b/src/test/ui/error-codes/E0191.stderr
@@ -0,0 +1,12 @@
+error[E0191]: the value of the associated type `Bar` (from the trait `Trait`) must be specified
+  --> $DIR/E0191.rs:5:12
+   |
+LL |     type Bar;
+   |     --------- `Bar` defined here
+...
+LL | type Foo = Trait;
+   |            ^^^^^ associated type `Bar` must be specified
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0191`.
diff --git a/src/test/ui/error-codes/E0192.rs b/src/test/ui/error-codes/E0192.rs
new file mode 100644
index 0000000..c52977e
--- /dev/null
+++ b/src/test/ui/error-codes/E0192.rs
@@ -0,0 +1,12 @@
+#![feature(optin_builtin_traits)]
+
+trait Trait {
+    type Bar;
+}
+
+struct Foo;
+
+impl !Trait for Foo { } //~ ERROR E0192
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0192.stderr b/src/test/ui/error-codes/E0192.stderr
new file mode 100644
index 0000000..8faa550
--- /dev/null
+++ b/src/test/ui/error-codes/E0192.stderr
@@ -0,0 +1,9 @@
+error[E0192]: negative impls are only allowed for auto traits (e.g., `Send` and `Sync`)
+  --> $DIR/E0192.rs:9:1
+   |
+LL | impl !Trait for Foo { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0192`.
diff --git a/src/test/ui/error-codes/E0194.rs b/src/test/ui/error-codes/E0194.rs
new file mode 100644
index 0000000..71eff0e
--- /dev/null
+++ b/src/test/ui/error-codes/E0194.rs
@@ -0,0 +1,8 @@
+trait Foo<T> {
+    fn do_something(&self) -> T;
+    fn do_something_else<T: Clone>(&self, bar: T);
+    //~^ ERROR E0194
+}
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0194.stderr b/src/test/ui/error-codes/E0194.stderr
new file mode 100644
index 0000000..ab4918a
--- /dev/null
+++ b/src/test/ui/error-codes/E0194.stderr
@@ -0,0 +1,12 @@
+error[E0194]: type parameter `T` shadows another type parameter of the same name
+  --> $DIR/E0194.rs:3:26
+   |
+LL | trait Foo<T> {
+   |           - first `T` declared here
+LL |     fn do_something(&self) -> T;
+LL |     fn do_something_else<T: Clone>(&self, bar: T);
+   |                          ^ shadows another type parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0194`.
diff --git a/src/test/ui/error-codes/E0195.rs b/src/test/ui/error-codes/E0195.rs
new file mode 100644
index 0000000..f712ee4
--- /dev/null
+++ b/src/test/ui/error-codes/E0195.rs
@@ -0,0 +1,15 @@
+trait Trait {
+    fn bar<'a,'b:'a>(x: &'a str, y: &'b str);
+    //~^ NOTE lifetimes in impl do not match this method in trait
+}
+
+struct Foo;
+
+impl Trait for Foo {
+    fn bar<'a,'b>(x: &'a str, y: &'b str) { //~ ERROR E0195
+    //~^ NOTE lifetimes do not match method in trait
+    }
+}
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0195.stderr b/src/test/ui/error-codes/E0195.stderr
new file mode 100644
index 0000000..6eaa1750
--- /dev/null
+++ b/src/test/ui/error-codes/E0195.stderr
@@ -0,0 +1,12 @@
+error[E0195]: lifetime parameters or bounds on method `bar` do not match the trait declaration
+  --> $DIR/E0195.rs:9:11
+   |
+LL |     fn bar<'a,'b:'a>(x: &'a str, y: &'b str);
+   |           ---------- lifetimes in impl do not match this method in trait
+...
+LL |     fn bar<'a,'b>(x: &'a str, y: &'b str) {
+   |           ^^^^^^^ lifetimes do not match method in trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0195`.
diff --git a/src/test/ui/error-codes/E0197.rs b/src/test/ui/error-codes/E0197.rs
new file mode 100644
index 0000000..4025a1f
--- /dev/null
+++ b/src/test/ui/error-codes/E0197.rs
@@ -0,0 +1,6 @@
+struct Foo;
+
+unsafe impl Foo { } //~ ERROR E0197
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0197.stderr b/src/test/ui/error-codes/E0197.stderr
new file mode 100644
index 0000000..bb7b647
--- /dev/null
+++ b/src/test/ui/error-codes/E0197.stderr
@@ -0,0 +1,9 @@
+error[E0197]: inherent impls cannot be unsafe
+  --> $DIR/E0197.rs:3:1
+   |
+LL | unsafe impl Foo { }
+   | ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0197`.
diff --git a/src/test/ui/error-codes/E0198.rs b/src/test/ui/error-codes/E0198.rs
new file mode 100644
index 0000000..00ab0c3
--- /dev/null
+++ b/src/test/ui/error-codes/E0198.rs
@@ -0,0 +1,8 @@
+#![feature(optin_builtin_traits)]
+
+struct Foo;
+
+unsafe impl !Send for Foo { } //~ ERROR E0198
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0198.stderr b/src/test/ui/error-codes/E0198.stderr
new file mode 100644
index 0000000..0d37063
--- /dev/null
+++ b/src/test/ui/error-codes/E0198.stderr
@@ -0,0 +1,9 @@
+error[E0198]: negative impls cannot be unsafe
+  --> $DIR/E0198.rs:5:1
+   |
+LL | unsafe impl !Send for Foo { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0198`.
diff --git a/src/test/ui/error-codes/E0199.rs b/src/test/ui/error-codes/E0199.rs
new file mode 100644
index 0000000..c95afa3
--- /dev/null
+++ b/src/test/ui/error-codes/E0199.rs
@@ -0,0 +1,9 @@
+#![feature(optin_builtin_traits)]
+
+struct Foo;
+
+trait Bar { }
+unsafe impl Bar for Foo { } //~ ERROR implementing the trait `Bar` is not unsafe [E0199]
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0199.stderr b/src/test/ui/error-codes/E0199.stderr
new file mode 100644
index 0000000..3632d26
--- /dev/null
+++ b/src/test/ui/error-codes/E0199.stderr
@@ -0,0 +1,9 @@
+error[E0199]: implementing the trait `Bar` is not unsafe
+  --> $DIR/E0199.rs:6:1
+   |
+LL | unsafe impl Bar for Foo { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0199`.
diff --git a/src/test/ui/error-codes/E0200.rs b/src/test/ui/error-codes/E0200.rs
new file mode 100644
index 0000000..24806a6
--- /dev/null
+++ b/src/test/ui/error-codes/E0200.rs
@@ -0,0 +1,8 @@
+struct Foo;
+
+unsafe trait Bar { }
+
+impl Bar for Foo { } //~ ERROR E0200
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0200.stderr b/src/test/ui/error-codes/E0200.stderr
new file mode 100644
index 0000000..677271a
--- /dev/null
+++ b/src/test/ui/error-codes/E0200.stderr
@@ -0,0 +1,9 @@
+error[E0200]: the trait `Bar` requires an `unsafe impl` declaration
+  --> $DIR/E0200.rs:5:1
+   |
+LL | impl Bar for Foo { }
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0200`.
diff --git a/src/test/ui/error-codes/E0201.rs b/src/test/ui/error-codes/E0201.rs
new file mode 100644
index 0000000..adefd4b
--- /dev/null
+++ b/src/test/ui/error-codes/E0201.rs
@@ -0,0 +1,22 @@
+struct Foo(u8);
+
+impl Foo {
+    fn bar(&self) -> bool { self.0 > 5 }
+    fn bar() {} //~ ERROR E0201
+}
+
+trait Baz {
+    type Quux;
+    fn baz(&self) -> bool;
+}
+
+impl Baz for Foo {
+    type Quux = u32;
+
+    fn baz(&self) -> bool { true }
+    fn baz(&self) -> bool { self.0 > 5 } //~ ERROR E0201
+    type Quux = u32; //~ ERROR E0201
+}
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0201.stderr b/src/test/ui/error-codes/E0201.stderr
new file mode 100644
index 0000000..89cfd40
--- /dev/null
+++ b/src/test/ui/error-codes/E0201.stderr
@@ -0,0 +1,28 @@
+error[E0201]: duplicate definitions with name `bar`:
+  --> $DIR/E0201.rs:5:5
+   |
+LL |     fn bar(&self) -> bool { self.0 > 5 }
+   |     ------------------------------------ previous definition of `bar` here
+LL |     fn bar() {}
+   |     ^^^^^^^^^^^ duplicate definition
+
+error[E0201]: duplicate definitions with name `baz`:
+  --> $DIR/E0201.rs:17:5
+   |
+LL |     fn baz(&self) -> bool { true }
+   |     ------------------------------ previous definition of `baz` here
+LL |     fn baz(&self) -> bool { self.0 > 5 }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ duplicate definition
+
+error[E0201]: duplicate definitions with name `Quux`:
+  --> $DIR/E0201.rs:18:5
+   |
+LL |     type Quux = u32;
+   |     ---------------- previous definition of `Quux` here
+...
+LL |     type Quux = u32;
+   |     ^^^^^^^^^^^^^^^^ duplicate definition
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0201`.
diff --git a/src/test/ui/error-codes/E0206.rs b/src/test/ui/error-codes/E0206.rs
new file mode 100644
index 0000000..bace046
--- /dev/null
+++ b/src/test/ui/error-codes/E0206.rs
@@ -0,0 +1,14 @@
+type Foo = [u8; 256];
+
+impl Copy for Foo { }
+//~^ ERROR the trait `Copy` may not be implemented for this type
+//~| ERROR only traits defined in the current crate can be implemented for arbitrary types
+
+#[derive(Copy, Clone)]
+struct Bar;
+
+impl Copy for &'static mut Bar { }
+//~^ ERROR the trait `Copy` may not be implemented for this type
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0206.stderr b/src/test/ui/error-codes/E0206.stderr
new file mode 100644
index 0000000..a0c4b01
--- /dev/null
+++ b/src/test/ui/error-codes/E0206.stderr
@@ -0,0 +1,25 @@
+error[E0206]: the trait `Copy` may not be implemented for this type
+  --> $DIR/E0206.rs:3:15
+   |
+LL | impl Copy for Foo { }
+   |               ^^^ type is not a structure or enumeration
+
+error[E0206]: the trait `Copy` may not be implemented for this type
+  --> $DIR/E0206.rs:10:15
+   |
+LL | impl Copy for &'static mut Bar { }
+   |               ^^^^^^^^^^^^^^^^ type is not a structure or enumeration
+
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/E0206.rs:3:1
+   |
+LL | impl Copy for Foo { }
+   | ^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0117, E0206.
+For more information about an error, try `rustc --explain E0117`.
diff --git a/src/test/ui/error-codes/E0207.rs b/src/test/ui/error-codes/E0207.rs
new file mode 100644
index 0000000..7f5d4ab
--- /dev/null
+++ b/src/test/ui/error-codes/E0207.rs
@@ -0,0 +1,10 @@
+struct Foo;
+
+impl<T: Default> Foo { //~ ERROR E0207
+    fn get(&self) -> T {
+        <T as Default>::default()
+    }
+}
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0207.stderr b/src/test/ui/error-codes/E0207.stderr
new file mode 100644
index 0000000..5ef51ed
--- /dev/null
+++ b/src/test/ui/error-codes/E0207.stderr
@@ -0,0 +1,9 @@
+error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates
+  --> $DIR/E0207.rs:3:6
+   |
+LL | impl<T: Default> Foo {
+   |      ^ unconstrained type parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0207`.
diff --git a/src/test/ui/error-codes/E0214.rs b/src/test/ui/error-codes/E0214.rs
new file mode 100644
index 0000000..fd73189
--- /dev/null
+++ b/src/test/ui/error-codes/E0214.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let v: Vec(&str) = vec!["foo"];
+    //~^ ERROR E0214
+}
diff --git a/src/test/ui/error-codes/E0214.stderr b/src/test/ui/error-codes/E0214.stderr
new file mode 100644
index 0000000..a10f2c0
--- /dev/null
+++ b/src/test/ui/error-codes/E0214.stderr
@@ -0,0 +1,12 @@
+error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
+  --> $DIR/E0214.rs:2:15
+   |
+LL |     let v: Vec(&str) = vec!["foo"];
+   |               ^^^^^^
+   |               |
+   |               only `Fn` traits may use parentheses
+   |               help: use angle brackets instead: `<&str>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0214`.
diff --git a/src/test/ui/error-codes/E0220.rs b/src/test/ui/error-codes/E0220.rs
new file mode 100644
index 0000000..f479804
--- /dev/null
+++ b/src/test/ui/error-codes/E0220.rs
@@ -0,0 +1,8 @@
+trait Trait {
+    type Bar;
+}
+
+type Foo = Trait<F=i32>; //~ ERROR E0220
+                         //~| ERROR E0191
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0220.stderr b/src/test/ui/error-codes/E0220.stderr
new file mode 100644
index 0000000..4394983
--- /dev/null
+++ b/src/test/ui/error-codes/E0220.stderr
@@ -0,0 +1,19 @@
+error[E0220]: associated type `F` not found for `Trait`
+  --> $DIR/E0220.rs:5:18
+   |
+LL | type Foo = Trait<F=i32>;
+   |                  ^^^^^ associated type `F` not found
+
+error[E0191]: the value of the associated type `Bar` (from the trait `Trait`) must be specified
+  --> $DIR/E0220.rs:5:12
+   |
+LL |     type Bar;
+   |     --------- `Bar` defined here
+...
+LL | type Foo = Trait<F=i32>;
+   |            ^^^^^^^^^^^^ associated type `Bar` must be specified
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0191, E0220.
+For more information about an error, try `rustc --explain E0191`.
diff --git a/src/test/ui/error-codes/E0221.rs b/src/test/ui/error-codes/E0221.rs
new file mode 100644
index 0000000..7c7e139
--- /dev/null
+++ b/src/test/ui/error-codes/E0221.rs
@@ -0,0 +1,27 @@
+trait T1 {}
+trait T2 {}
+
+trait Foo {
+    type A: T1;
+}
+
+trait Bar : Foo {
+    type A: T2;
+    fn do_something() {
+        let _: Self::A;
+        //~^ ERROR E0221
+    }
+}
+
+trait T3 {}
+
+trait My : std::str::FromStr {
+    type Err: T3;
+    fn test() {
+        let _: Self::Err;
+        //~^ ERROR E0221
+    }
+}
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0221.stderr b/src/test/ui/error-codes/E0221.stderr
new file mode 100644
index 0000000..043f0c6
--- /dev/null
+++ b/src/test/ui/error-codes/E0221.stderr
@@ -0,0 +1,30 @@
+error[E0221]: ambiguous associated type `A` in bounds of `Self`
+  --> $DIR/E0221.rs:11:16
+   |
+LL |     type A: T1;
+   |     ----------- ambiguous `A` from `Foo`
+...
+LL |     type A: T2;
+   |     ----------- ambiguous `A` from `Bar`
+LL |     fn do_something() {
+LL |         let _: Self::A;
+   |                ^^^^^^^ ambiguous associated type `A`
+
+error[E0221]: ambiguous associated type `Err` in bounds of `Self`
+  --> $DIR/E0221.rs:21:16
+   |
+LL |     type Err: T3;
+   |     ------------- ambiguous `Err` from `My`
+LL |     fn test() {
+LL |         let _: Self::Err;
+   |                ^^^^^^^^^ ambiguous associated type `Err`
+   |
+note: associated type `Self` could derive from `std::str::FromStr`
+  --> $DIR/E0221.rs:21:16
+   |
+LL |         let _: Self::Err;
+   |                ^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0221`.
diff --git a/src/test/ui/error-codes/E0223.rs b/src/test/ui/error-codes/E0223.rs
new file mode 100644
index 0000000..6031b68
--- /dev/null
+++ b/src/test/ui/error-codes/E0223.rs
@@ -0,0 +1,6 @@
+trait MyTrait { type X; }
+
+fn main() {
+    let foo: MyTrait::X;
+    //~^ ERROR ambiguous associated type
+}
diff --git a/src/test/ui/error-codes/E0223.stderr b/src/test/ui/error-codes/E0223.stderr
new file mode 100644
index 0000000..726f39e
--- /dev/null
+++ b/src/test/ui/error-codes/E0223.stderr
@@ -0,0 +1,9 @@
+error[E0223]: ambiguous associated type
+  --> $DIR/E0223.rs:4:14
+   |
+LL |     let foo: MyTrait::X;
+   |              ^^^^^^^^^^ help: use fully-qualified syntax: `<Type as MyTrait>::X`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0223`.
diff --git a/src/test/ui/error-codes/E0225.rs b/src/test/ui/error-codes/E0225.rs
new file mode 100644
index 0000000..1789be1
--- /dev/null
+++ b/src/test/ui/error-codes/E0225.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let _: Box<std::io::Read + std::io::Write>;
+    //~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+}
diff --git a/src/test/ui/error-codes/E0225.stderr b/src/test/ui/error-codes/E0225.stderr
new file mode 100644
index 0000000..85a0470
--- /dev/null
+++ b/src/test/ui/error-codes/E0225.stderr
@@ -0,0 +1,9 @@
+error[E0225]: only auto traits can be used as additional traits in a trait object
+  --> $DIR/E0225.rs:2:32
+   |
+LL |     let _: Box<std::io::Read + std::io::Write>;
+   |                                ^^^^^^^^^^^^^^ non-auto additional trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0225`.
diff --git a/src/test/ui/error-codes/E0229.rs b/src/test/ui/error-codes/E0229.rs
new file mode 100644
index 0000000..4c19341
--- /dev/null
+++ b/src/test/ui/error-codes/E0229.rs
@@ -0,0 +1,17 @@
+pub trait Foo {
+    type A;
+    fn boo(&self) -> <Self as Foo>::A;
+}
+
+struct Bar;
+
+impl Foo for isize {
+    type A = usize;
+    fn boo(&self) -> usize { 42 }
+}
+
+fn baz<I>(x: &<I as Foo<A=Bar>>::A) {}
+//~^ ERROR associated type bindings are not allowed here [E0229]
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0229.stderr b/src/test/ui/error-codes/E0229.stderr
new file mode 100644
index 0000000..4679331
--- /dev/null
+++ b/src/test/ui/error-codes/E0229.stderr
@@ -0,0 +1,9 @@
+error[E0229]: associated type bindings are not allowed here
+  --> $DIR/E0229.rs:13:25
+   |
+LL | fn baz<I>(x: &<I as Foo<A=Bar>>::A) {}
+   |                         ^^^^^ associated type not allowed here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0229`.
diff --git a/src/test/ui/error-codes/E0252.rs b/src/test/ui/error-codes/E0252.rs
new file mode 100644
index 0000000..6b51634
--- /dev/null
+++ b/src/test/ui/error-codes/E0252.rs
@@ -0,0 +1,15 @@
+#![allow(non_camel_case_types)]
+
+use foo::baz;
+use bar::baz; //~ ERROR E0252
+
+mod foo {
+    pub struct baz;
+}
+
+mod bar {
+    pub mod baz {}
+}
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0252.stderr b/src/test/ui/error-codes/E0252.stderr
new file mode 100644
index 0000000..8486806
--- /dev/null
+++ b/src/test/ui/error-codes/E0252.stderr
@@ -0,0 +1,17 @@
+error[E0252]: the name `baz` is defined multiple times
+  --> $DIR/E0252.rs:4:5
+   |
+LL | use foo::baz;
+   |     -------- previous import of the type `baz` here
+LL | use bar::baz;
+   |     ^^^^^^^^ `baz` reimported here
+   |
+   = note: `baz` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | use bar::baz as other_baz;
+   |     ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0252`.
diff --git a/src/test/ui/error-codes/E0253.rs b/src/test/ui/error-codes/E0253.rs
new file mode 100644
index 0000000..284b16d
--- /dev/null
+++ b/src/test/ui/error-codes/E0253.rs
@@ -0,0 +1,10 @@
+mod foo {
+    pub trait MyTrait {
+        fn do_something();
+    }
+}
+
+use foo::MyTrait::do_something;
+    //~^ ERROR E0253
+
+fn main() {}
diff --git a/src/test/ui/error-codes/E0253.stderr b/src/test/ui/error-codes/E0253.stderr
new file mode 100644
index 0000000..8f21a0a
--- /dev/null
+++ b/src/test/ui/error-codes/E0253.stderr
@@ -0,0 +1,9 @@
+error[E0253]: `do_something` is not directly importable
+  --> $DIR/E0253.rs:7:5
+   |
+LL | use foo::MyTrait::do_something;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot be imported directly
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0253`.
diff --git a/src/test/ui/error-codes/E0254.rs b/src/test/ui/error-codes/E0254.rs
new file mode 100644
index 0000000..706cd34
--- /dev/null
+++ b/src/test/ui/error-codes/E0254.rs
@@ -0,0 +1,15 @@
+#![feature(alloc)]
+#![allow(unused_extern_crates, non_camel_case_types)]
+
+extern crate alloc;
+
+mod foo {
+    pub trait alloc {
+        fn do_something();
+    }
+}
+
+use foo::alloc;
+//~^ ERROR E0254
+
+fn main() {}
diff --git a/src/test/ui/error-codes/E0254.stderr b/src/test/ui/error-codes/E0254.stderr
new file mode 100644
index 0000000..c2d013d
--- /dev/null
+++ b/src/test/ui/error-codes/E0254.stderr
@@ -0,0 +1,18 @@
+error[E0254]: the name `alloc` is defined multiple times
+  --> $DIR/E0254.rs:12:5
+   |
+LL | extern crate alloc;
+   | ------------------- previous import of the extern crate `alloc` here
+...
+LL | use foo::alloc;
+   |     ^^^^^^^^^^ `alloc` reimported here
+   |
+   = note: `alloc` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | use foo::alloc as other_alloc;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0254`.
diff --git a/src/test/ui/error-codes/E0255.rs b/src/test/ui/error-codes/E0255.rs
new file mode 100644
index 0000000..d1c21eb
--- /dev/null
+++ b/src/test/ui/error-codes/E0255.rs
@@ -0,0 +1,9 @@
+use bar::foo;
+
+fn foo() {} //~ ERROR E0255
+
+mod bar {
+     pub fn foo() {}
+}
+
+fn main() {}
diff --git a/src/test/ui/error-codes/E0255.stderr b/src/test/ui/error-codes/E0255.stderr
new file mode 100644
index 0000000..36e4eee
--- /dev/null
+++ b/src/test/ui/error-codes/E0255.stderr
@@ -0,0 +1,18 @@
+error[E0255]: the name `foo` is defined multiple times
+  --> $DIR/E0255.rs:3:1
+   |
+LL | use bar::foo;
+   |     -------- previous import of the value `foo` here
+LL | 
+LL | fn foo() {}
+   | ^^^^^^^^ `foo` redefined here
+   |
+   = note: `foo` must be defined only once in the value namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | use bar::foo as other_foo;
+   |     ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0255`.
diff --git a/src/test/ui/error-codes/E0259.rs b/src/test/ui/error-codes/E0259.rs
new file mode 100644
index 0000000..cda3db3
--- /dev/null
+++ b/src/test/ui/error-codes/E0259.rs
@@ -0,0 +1,9 @@
+#![feature(alloc, rustc_private)]
+#![allow(unused_extern_crates)]
+
+extern crate alloc;
+
+extern crate libc as alloc;
+//~^ ERROR E0259
+
+fn main() {}
diff --git a/src/test/ui/error-codes/E0259.stderr b/src/test/ui/error-codes/E0259.stderr
new file mode 100644
index 0000000..fd6a408
--- /dev/null
+++ b/src/test/ui/error-codes/E0259.stderr
@@ -0,0 +1,18 @@
+error[E0259]: the name `alloc` is defined multiple times
+  --> $DIR/E0259.rs:6:1
+   |
+LL | extern crate alloc;
+   | ------------------- previous import of the extern crate `alloc` here
+LL | 
+LL | extern crate libc as alloc;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `alloc` reimported here
+   |
+   = note: `alloc` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | extern crate libc as other_alloc;
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0259`.
diff --git a/src/test/ui/error-codes/E0260.rs b/src/test/ui/error-codes/E0260.rs
new file mode 100644
index 0000000..80382c0
--- /dev/null
+++ b/src/test/ui/error-codes/E0260.rs
@@ -0,0 +1,13 @@
+#![feature(alloc)]
+#![allow(unused_extern_crates)]
+
+extern crate alloc;
+
+mod alloc {
+//~^ ERROR the name `alloc` is defined multiple times [E0260]
+    pub trait MyTrait {
+        fn do_something();
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/error-codes/E0260.stderr b/src/test/ui/error-codes/E0260.stderr
new file mode 100644
index 0000000..bfe2ed0
--- /dev/null
+++ b/src/test/ui/error-codes/E0260.stderr
@@ -0,0 +1,18 @@
+error[E0260]: the name `alloc` is defined multiple times
+  --> $DIR/E0260.rs:6:1
+   |
+LL | extern crate alloc;
+   | ------------------- previous import of the extern crate `alloc` here
+LL | 
+LL | mod alloc {
+   | ^^^^^^^^^ `alloc` redefined here
+   |
+   = note: `alloc` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | extern crate alloc as other_alloc;
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0260`.
diff --git a/src/test/ui/error-codes/E0261.rs b/src/test/ui/error-codes/E0261.rs
new file mode 100644
index 0000000..f05e09a
--- /dev/null
+++ b/src/test/ui/error-codes/E0261.rs
@@ -0,0 +1,9 @@
+fn foo(x: &'a str) { } //~ ERROR E0261
+                       //~| undeclared lifetime
+
+struct Foo {
+    x: &'a str, //~ ERROR E0261
+                //~| undeclared lifetime
+}
+
+fn main() {}
diff --git a/src/test/ui/error-codes/E0261.stderr b/src/test/ui/error-codes/E0261.stderr
new file mode 100644
index 0000000..3bf5e9d
--- /dev/null
+++ b/src/test/ui/error-codes/E0261.stderr
@@ -0,0 +1,15 @@
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/E0261.rs:1:12
+   |
+LL | fn foo(x: &'a str) { }
+   |            ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/E0261.rs:5:9
+   |
+LL |     x: &'a str,
+   |         ^^ undeclared lifetime
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0261`.
diff --git a/src/test/ui/error-codes/E0262.rs b/src/test/ui/error-codes/E0262.rs
new file mode 100644
index 0000000..55264f1
--- /dev/null
+++ b/src/test/ui/error-codes/E0262.rs
@@ -0,0 +1,4 @@
+fn foo<'static>(x: &'static str) { } //~ ERROR E0262
+                                     //~| 'static is a reserved lifetime name
+
+fn main() {}
diff --git a/src/test/ui/error-codes/E0262.stderr b/src/test/ui/error-codes/E0262.stderr
new file mode 100644
index 0000000..ad90b71
--- /dev/null
+++ b/src/test/ui/error-codes/E0262.stderr
@@ -0,0 +1,9 @@
+error[E0262]: invalid lifetime parameter name: `'static`
+  --> $DIR/E0262.rs:1:8
+   |
+LL | fn foo<'static>(x: &'static str) { }
+   |        ^^^^^^^ 'static is a reserved lifetime name
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0262`.
diff --git a/src/test/ui/error-codes/E0263.rs b/src/test/ui/error-codes/E0263.rs
new file mode 100644
index 0000000..4376437
--- /dev/null
+++ b/src/test/ui/error-codes/E0263.rs
@@ -0,0 +1,5 @@
+fn foo<'a, 'b, 'a>(x: &'a str, y: &'b str) {
+    //~^ ERROR E0263
+}
+
+fn main() {}
diff --git a/src/test/ui/error-codes/E0263.stderr b/src/test/ui/error-codes/E0263.stderr
new file mode 100644
index 0000000..4dae02b
--- /dev/null
+++ b/src/test/ui/error-codes/E0263.stderr
@@ -0,0 +1,11 @@
+error[E0263]: lifetime name `'a` declared twice in the same scope
+  --> $DIR/E0263.rs:1:16
+   |
+LL | fn foo<'a, 'b, 'a>(x: &'a str, y: &'b str) {
+   |        --      ^^ declared twice
+   |        |
+   |        previous declaration here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0263`.
diff --git a/src/test/ui/error-codes/E0264.rs b/src/test/ui/error-codes/E0264.rs
new file mode 100644
index 0000000..6adaf01
--- /dev/null
+++ b/src/test/ui/error-codes/E0264.rs
@@ -0,0 +1,8 @@
+#![feature(lang_items)]
+
+extern "C" {
+    #[lang = "cake"]
+    fn cake(); //~ ERROR E0264
+}
+
+fn main() {}
diff --git a/src/test/ui/error-codes/E0264.stderr b/src/test/ui/error-codes/E0264.stderr
new file mode 100644
index 0000000..403c0aa
--- /dev/null
+++ b/src/test/ui/error-codes/E0264.stderr
@@ -0,0 +1,9 @@
+error[E0264]: unknown external lang item: `cake`
+  --> $DIR/E0264.rs:5:5
+   |
+LL |     fn cake();
+   |     ^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0264`.
diff --git a/src/test/ui/error-codes/E0267.rs b/src/test/ui/error-codes/E0267.rs
new file mode 100644
index 0000000..45e875a
--- /dev/null
+++ b/src/test/ui/error-codes/E0267.rs
@@ -0,0 +1,3 @@
+fn main() {
+    let w = || { break; }; //~ ERROR E0267
+}
diff --git a/src/test/ui/error-codes/E0267.stderr b/src/test/ui/error-codes/E0267.stderr
new file mode 100644
index 0000000..b14cfd1
--- /dev/null
+++ b/src/test/ui/error-codes/E0267.stderr
@@ -0,0 +1,9 @@
+error[E0267]: `break` inside of a closure
+  --> $DIR/E0267.rs:2:18
+   |
+LL |     let w = || { break; };
+   |                  ^^^^^ cannot break inside of a closure
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0267`.
diff --git a/src/test/ui/error-codes/E0268.rs b/src/test/ui/error-codes/E0268.rs
new file mode 100644
index 0000000..742ba54
--- /dev/null
+++ b/src/test/ui/error-codes/E0268.rs
@@ -0,0 +1,3 @@
+fn main() {
+    break; //~ ERROR E0268
+}
diff --git a/src/test/ui/error-codes/E0268.stderr b/src/test/ui/error-codes/E0268.stderr
new file mode 100644
index 0000000..3c77e7f
--- /dev/null
+++ b/src/test/ui/error-codes/E0268.stderr
@@ -0,0 +1,9 @@
+error[E0268]: `break` outside of loop
+  --> $DIR/E0268.rs:2:5
+   |
+LL |     break;
+   |     ^^^^^ cannot break outside of a loop
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0268`.
diff --git a/src/test/ui/error-codes/E0271.rs b/src/test/ui/error-codes/E0271.rs
new file mode 100644
index 0000000..f271907
--- /dev/null
+++ b/src/test/ui/error-codes/E0271.rs
@@ -0,0 +1,11 @@
+trait Trait { type AssociatedType; }
+
+fn foo<T>(t: T) where T: Trait<AssociatedType=u32> {
+    println!("in foo");
+}
+
+impl Trait for i8 { type AssociatedType = &'static str; }
+
+fn main() {
+    foo(3_i8); //~ ERROR E0271
+}
diff --git a/src/test/ui/error-codes/E0271.stderr b/src/test/ui/error-codes/E0271.stderr
new file mode 100644
index 0000000..16c3ab9
--- /dev/null
+++ b/src/test/ui/error-codes/E0271.stderr
@@ -0,0 +1,17 @@
+error[E0271]: type mismatch resolving `<i8 as Trait>::AssociatedType == u32`
+  --> $DIR/E0271.rs:10:5
+   |
+LL |     foo(3_i8);
+   |     ^^^ expected reference, found u32
+   |
+   = note: expected type `&'static str`
+              found type `u32`
+note: required by `foo`
+  --> $DIR/E0271.rs:3:1
+   |
+LL | fn foo<T>(t: T) where T: Trait<AssociatedType=u32> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/error-codes/E0275.rs b/src/test/ui/error-codes/E0275.rs
new file mode 100644
index 0000000..28a9676f
--- /dev/null
+++ b/src/test/ui/error-codes/E0275.rs
@@ -0,0 +1,8 @@
+trait Foo {}
+
+struct Bar<T>(T);
+
+impl<T> Foo for T where Bar<T>: Foo {} //~ ERROR E0275
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0275.stderr b/src/test/ui/error-codes/E0275.stderr
new file mode 100644
index 0000000..01a923a
--- /dev/null
+++ b/src/test/ui/error-codes/E0275.stderr
@@ -0,0 +1,79 @@
+error[E0275]: overflow evaluating the requirement `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Foo`
+  --> $DIR/E0275.rs:5:1
+   |
+LL | impl<T> Foo for T where Bar<T>: Foo {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding a `#![recursion_limit="128"]` attribute to your crate
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<T>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<T>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<T>>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<T>>`
+   = note: required because of the requirements on the impl of `Foo` for `Bar<T>`
+note: required by `Foo`
+  --> $DIR/E0275.rs:1:1
+   |
+LL | trait Foo {}
+   | ^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/src/test/ui/error-codes/E0276.rs b/src/test/ui/error-codes/E0276.rs
new file mode 100644
index 0000000..5e3d9f6
--- /dev/null
+++ b/src/test/ui/error-codes/E0276.rs
@@ -0,0 +1,10 @@
+trait Foo {
+    fn foo<T>(x: T);
+}
+
+impl Foo for bool {
+    fn foo<T>(x: T) where T: Copy {} //~ ERROR E0276
+}
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0276.stderr b/src/test/ui/error-codes/E0276.stderr
new file mode 100644
index 0000000..a8b016e
--- /dev/null
+++ b/src/test/ui/error-codes/E0276.stderr
@@ -0,0 +1,12 @@
+error[E0276]: impl has stricter requirements than trait
+  --> $DIR/E0276.rs:6:5
+   |
+LL |     fn foo<T>(x: T);
+   |     ---------------- definition of `foo` from trait
+...
+LL |     fn foo<T>(x: T) where T: Copy {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `T: std::marker::Copy`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0276`.
diff --git a/src/test/ui/error-codes/E0277-2.rs b/src/test/ui/error-codes/E0277-2.rs
new file mode 100644
index 0000000..4285187
--- /dev/null
+++ b/src/test/ui/error-codes/E0277-2.rs
@@ -0,0 +1,18 @@
+struct Foo {
+    bar: Bar
+}
+
+struct Bar {
+    baz: Baz
+}
+
+struct Baz {
+    x: *const u8
+}
+
+fn is_send<T: Send>() { }
+
+fn main() {
+    is_send::<Foo>();
+    //~^ ERROR `*const u8` cannot be sent between threads safely
+}
diff --git a/src/test/ui/error-codes/E0277-2.stderr b/src/test/ui/error-codes/E0277-2.stderr
new file mode 100644
index 0000000..a4db1c8
--- /dev/null
+++ b/src/test/ui/error-codes/E0277-2.stderr
@@ -0,0 +1,19 @@
+error[E0277]: `*const u8` cannot be sent between threads safely
+  --> $DIR/E0277-2.rs:16:5
+   |
+LL |     is_send::<Foo>();
+   |     ^^^^^^^^^^^^^^ `*const u8` cannot be sent between threads safely
+   |
+   = help: within `Foo`, the trait `std::marker::Send` is not implemented for `*const u8`
+   = note: required because it appears within the type `Baz`
+   = note: required because it appears within the type `Bar`
+   = note: required because it appears within the type `Foo`
+note: required by `is_send`
+  --> $DIR/E0277-2.rs:13:1
+   |
+LL | fn is_send<T: Send>() { }
+   | ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/error-codes/E0277.rs b/src/test/ui/error-codes/E0277.rs
new file mode 100644
index 0000000..e60d830
--- /dev/null
+++ b/src/test/ui/error-codes/E0277.rs
@@ -0,0 +1,19 @@
+// ignore-cloudabi no std::path
+
+use std::path::Path;
+
+trait Foo {
+    fn bar(&self);
+}
+
+fn some_func<T: Foo>(foo: T) {
+    foo.bar();
+}
+
+fn f(p: Path) { }
+//~^ ERROR the size for values of type
+
+fn main() {
+    some_func(5i32);
+    //~^ ERROR the trait bound `i32: Foo` is not satisfied
+}
diff --git a/src/test/ui/error-codes/E0277.stderr b/src/test/ui/error-codes/E0277.stderr
new file mode 100644
index 0000000..e5e416d
--- /dev/null
+++ b/src/test/ui/error-codes/E0277.stderr
@@ -0,0 +1,27 @@
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/E0277.rs:13:6
+   |
+LL | fn f(p: Path) { }
+   |      ^ borrow the `Path` instead
+   |
+   = help: within `std::path::Path`, the trait `std::marker::Sized` is not implemented for `[u8]`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: required because it appears within the type `std::path::Path`
+   = note: all local variables must have a statically known size
+   = help: unsized locals are gated as an unstable feature
+
+error[E0277]: the trait bound `i32: Foo` is not satisfied
+  --> $DIR/E0277.rs:17:5
+   |
+LL |     some_func(5i32);
+   |     ^^^^^^^^^ the trait `Foo` is not implemented for `i32`
+   |
+note: required by `some_func`
+  --> $DIR/E0277.rs:9:1
+   |
+LL | fn some_func<T: Foo>(foo: T) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/error-codes/E0282.rs b/src/test/ui/error-codes/E0282.rs
new file mode 100644
index 0000000..9bd16ab
--- /dev/null
+++ b/src/test/ui/error-codes/E0282.rs
@@ -0,0 +1,3 @@
+fn main() {
+    let x = "hello".chars().rev().collect(); //~ ERROR E0282
+}
diff --git a/src/test/ui/error-codes/E0282.stderr b/src/test/ui/error-codes/E0282.stderr
new file mode 100644
index 0000000..3a5040e
--- /dev/null
+++ b/src/test/ui/error-codes/E0282.stderr
@@ -0,0 +1,12 @@
+error[E0282]: type annotations needed
+  --> $DIR/E0282.rs:2:9
+   |
+LL |     let x = "hello".chars().rev().collect();
+   |         ^
+   |         |
+   |         cannot infer type
+   |         consider giving `x` a type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/error-codes/E0283.rs b/src/test/ui/error-codes/E0283.rs
new file mode 100644
index 0000000..9bdcc9a
--- /dev/null
+++ b/src/test/ui/error-codes/E0283.rs
@@ -0,0 +1,19 @@
+trait Generator {
+    fn create() -> u32;
+}
+
+struct Impl;
+
+impl Generator for Impl {
+    fn create() -> u32 { 1 }
+}
+
+struct AnotherImpl;
+
+impl Generator for AnotherImpl {
+    fn create() -> u32 { 2 }
+}
+
+fn main() {
+    let cont: u32 = Generator::create(); //~ ERROR E0283
+}
diff --git a/src/test/ui/error-codes/E0283.stderr b/src/test/ui/error-codes/E0283.stderr
new file mode 100644
index 0000000..e1f53e5
--- /dev/null
+++ b/src/test/ui/error-codes/E0283.stderr
@@ -0,0 +1,15 @@
+error[E0283]: type annotations required: cannot resolve `_: Generator`
+  --> $DIR/E0283.rs:18:21
+   |
+LL |     let cont: u32 = Generator::create();
+   |                     ^^^^^^^^^^^^^^^^^
+   |
+note: required by `Generator::create`
+  --> $DIR/E0283.rs:2:5
+   |
+LL |     fn create() -> u32;
+   |     ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0283`.
diff --git a/src/test/ui/error-codes/E0297.rs b/src/test/ui/error-codes/E0297.rs
new file mode 100644
index 0000000..27c7960
--- /dev/null
+++ b/src/test/ui/error-codes/E0297.rs
@@ -0,0 +1,6 @@
+fn main() {
+    let xs : Vec<Option<i32>> = vec![Some(1), None];
+
+    for Some(x) in xs {}
+    //~^ ERROR E0005
+}
diff --git a/src/test/ui/error-codes/E0297.stderr b/src/test/ui/error-codes/E0297.stderr
new file mode 100644
index 0000000..f356a5b
--- /dev/null
+++ b/src/test/ui/error-codes/E0297.stderr
@@ -0,0 +1,9 @@
+error[E0005]: refutable pattern in `for` loop binding: `None` not covered
+  --> $DIR/E0297.rs:4:9
+   |
+LL |     for Some(x) in xs {}
+   |         ^^^^^^^ pattern `None` not covered
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0005`.
diff --git a/src/test/ui/error-codes/E0301.nll.stderr b/src/test/ui/error-codes/E0301.nll.stderr
new file mode 100644
index 0000000..24234c9
--- /dev/null
+++ b/src/test/ui/error-codes/E0301.nll.stderr
@@ -0,0 +1,11 @@
+error[E0301]: cannot mutably borrow in a pattern guard
+  --> $DIR/E0301.rs:4:19
+   |
+LL |         option if option.take().is_none() => {},
+   |                   ^^^^^^ borrowed mutably in pattern guard
+   |
+   = help: add #![feature(bind_by_move_pattern_guards)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0301`.
diff --git a/src/test/ui/error-codes/E0301.rs b/src/test/ui/error-codes/E0301.rs
new file mode 100644
index 0000000..54372f8
--- /dev/null
+++ b/src/test/ui/error-codes/E0301.rs
@@ -0,0 +1,7 @@
+fn main() {
+    match Some(()) {
+        None => { },
+        option if option.take().is_none() => {}, //~ ERROR E0301
+        Some(_) => { }
+    }
+}
diff --git a/src/test/ui/error-codes/E0301.stderr b/src/test/ui/error-codes/E0301.stderr
new file mode 100644
index 0000000..80ee681
--- /dev/null
+++ b/src/test/ui/error-codes/E0301.stderr
@@ -0,0 +1,9 @@
+error[E0301]: cannot mutably borrow in a pattern guard
+  --> $DIR/E0301.rs:4:19
+   |
+LL |         option if option.take().is_none() => {},
+   |                   ^^^^^^ borrowed mutably in pattern guard
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0301`.
diff --git a/src/test/ui/error-codes/E0302.rs b/src/test/ui/error-codes/E0302.rs
new file mode 100644
index 0000000..7c76eb3
--- /dev/null
+++ b/src/test/ui/error-codes/E0302.rs
@@ -0,0 +1,7 @@
+fn main() {
+    match Some(()) {
+        None => { },
+        option if { option = None; false } => { }, //~ ERROR E0302
+        Some(_) => { }
+    }
+}
diff --git a/src/test/ui/error-codes/E0302.stderr b/src/test/ui/error-codes/E0302.stderr
new file mode 100644
index 0000000..69ebb6b
--- /dev/null
+++ b/src/test/ui/error-codes/E0302.stderr
@@ -0,0 +1,9 @@
+error[E0302]: cannot assign in a pattern guard
+  --> $DIR/E0302.rs:4:21
+   |
+LL |         option if { option = None; false } => { },
+   |                     ^^^^^^^^^^^^^ assignment in pattern guard
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0302`.
diff --git a/src/test/ui/error-codes/E0303.rs b/src/test/ui/error-codes/E0303.rs
new file mode 100644
index 0000000..0530d43
--- /dev/null
+++ b/src/test/ui/error-codes/E0303.rs
@@ -0,0 +1,8 @@
+fn main() {
+    match Some("hi".to_string()) {
+        ref op_string_ref @ Some(s) => {},
+        //~^ ERROR pattern bindings are not allowed after an `@` [E0303]
+        //~| ERROR E0009
+        None => {},
+    }
+}
diff --git a/src/test/ui/error-codes/E0303.stderr b/src/test/ui/error-codes/E0303.stderr
new file mode 100644
index 0000000..d701b07
--- /dev/null
+++ b/src/test/ui/error-codes/E0303.stderr
@@ -0,0 +1,19 @@
+error[E0009]: cannot bind by-move and by-ref in the same pattern
+  --> $DIR/E0303.rs:3:34
+   |
+LL |         ref op_string_ref @ Some(s) => {},
+   |         -------------------------^-
+   |         |                        |
+   |         |                        by-move pattern here
+   |         both by-ref and by-move used
+
+error[E0303]: pattern bindings are not allowed after an `@`
+  --> $DIR/E0303.rs:3:34
+   |
+LL |         ref op_string_ref @ Some(s) => {},
+   |                                  ^ not allowed after `@`
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0009, E0303.
+For more information about an error, try `rustc --explain E0009`.
diff --git a/src/test/ui/error-codes/E0308-4.rs b/src/test/ui/error-codes/E0308-4.rs
new file mode 100644
index 0000000..aaf7ef5
--- /dev/null
+++ b/src/test/ui/error-codes/E0308-4.rs
@@ -0,0 +1,7 @@
+fn main() {
+    let x = 1u8;
+    match x {
+        0u8..=3i8 => (), //~ ERROR E0308
+        _ => ()
+    }
+}
diff --git a/src/test/ui/error-codes/E0308-4.stderr b/src/test/ui/error-codes/E0308-4.stderr
new file mode 100644
index 0000000..3c51106
--- /dev/null
+++ b/src/test/ui/error-codes/E0308-4.stderr
@@ -0,0 +1,11 @@
+error[E0308]: mismatched types
+  --> $DIR/E0308-4.rs:4:9
+   |
+LL |     match x {
+   |           - this match expression has type `u8`
+LL |         0u8..=3i8 => (),
+   |         ^^^^^^^^^ expected u8, found i8
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/error-codes/E0308.rs b/src/test/ui/error-codes/E0308.rs
new file mode 100644
index 0000000..fa79bee
--- /dev/null
+++ b/src/test/ui/error-codes/E0308.rs
@@ -0,0 +1,8 @@
+#![feature(intrinsics)]
+
+extern "rust-intrinsic" {
+    fn size_of<T>(); //~ ERROR E0308
+}
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0308.stderr b/src/test/ui/error-codes/E0308.stderr
new file mode 100644
index 0000000..bd9834c
--- /dev/null
+++ b/src/test/ui/error-codes/E0308.stderr
@@ -0,0 +1,12 @@
+error[E0308]: intrinsic has wrong type
+  --> $DIR/E0308.rs:4:5
+   |
+LL |     fn size_of<T>();
+   |     ^^^^^^^^^^^^^^^^ expected (), found usize
+   |
+   = note: expected type `extern "rust-intrinsic" fn()`
+              found type `extern "rust-intrinsic" fn() -> usize`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/error-codes/E0328.rs b/src/test/ui/error-codes/E0328.rs
new file mode 100644
index 0000000..ef55f44
--- /dev/null
+++ b/src/test/ui/error-codes/E0328.rs
@@ -0,0 +1,10 @@
+#![feature(unsize)]
+
+use std::marker::Unsize;
+
+pub struct MyType;
+
+impl<T> Unsize<T> for MyType {}
+//~^ ERROR explicit impls for the `Unsize` trait are not permitted [E0328]
+
+fn main() {}
diff --git a/src/test/ui/error-codes/E0328.stderr b/src/test/ui/error-codes/E0328.stderr
new file mode 100644
index 0000000..70e6baf
--- /dev/null
+++ b/src/test/ui/error-codes/E0328.stderr
@@ -0,0 +1,9 @@
+error[E0328]: explicit impls for the `Unsize` trait are not permitted
+  --> $DIR/E0328.rs:7:1
+   |
+LL | impl<T> Unsize<T> for MyType {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of `Unsize` not allowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0328`.
diff --git a/src/test/ui/error-codes/E0365.rs b/src/test/ui/error-codes/E0365.rs
new file mode 100644
index 0000000..f12ff96
--- /dev/null
+++ b/src/test/ui/error-codes/E0365.rs
@@ -0,0 +1,8 @@
+mod foo {
+    pub const X: u32 = 1;
+}
+
+pub use foo as foo2;
+//~^ ERROR `foo` is private, and cannot be re-exported [E0365]
+
+fn main() {}
diff --git a/src/test/ui/error-codes/E0365.stderr b/src/test/ui/error-codes/E0365.stderr
new file mode 100644
index 0000000..c8fc59f
--- /dev/null
+++ b/src/test/ui/error-codes/E0365.stderr
@@ -0,0 +1,11 @@
+error[E0365]: `foo` is private, and cannot be re-exported
+  --> $DIR/E0365.rs:5:9
+   |
+LL | pub use foo as foo2;
+   |         ^^^^^^^^^^^ re-export of private `foo`
+   |
+   = note: consider declaring type or module `foo` with `pub`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0365`.
diff --git a/src/test/ui/error-codes/E0370.rs b/src/test/ui/error-codes/E0370.rs
new file mode 100644
index 0000000..32a66b6
--- /dev/null
+++ b/src/test/ui/error-codes/E0370.rs
@@ -0,0 +1,10 @@
+#![allow(dead_code)]
+
+#[deny(overflowing_literals)]
+#[repr(i64)]
+enum Foo {
+    X = 0x7fffffffffffffff,
+    Y, //~ ERROR E0370
+}
+
+fn main() {}
diff --git a/src/test/ui/error-codes/E0370.stderr b/src/test/ui/error-codes/E0370.stderr
new file mode 100644
index 0000000..7fb622e
--- /dev/null
+++ b/src/test/ui/error-codes/E0370.stderr
@@ -0,0 +1,11 @@
+error[E0370]: enum discriminant overflowed
+  --> $DIR/E0370.rs:7:5
+   |
+LL |     Y,
+   |     ^ overflowed on value after 9223372036854775807
+   |
+   = note: explicitly set `Y = -9223372036854775808` if that is desired outcome
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0370`.
diff --git a/src/test/ui/error-codes/E0374.rs b/src/test/ui/error-codes/E0374.rs
new file mode 100644
index 0000000..41fcedc
--- /dev/null
+++ b/src/test/ui/error-codes/E0374.rs
@@ -0,0 +1,11 @@
+#![feature(coerce_unsized)]
+use std::ops::CoerceUnsized;
+
+struct Foo<T: ?Sized> {
+    a: i32,
+}
+
+impl<T, U> CoerceUnsized<Foo<U>> for Foo<T> //~ ERROR E0374
+    where T: CoerceUnsized<U> {}
+
+fn main() {}
diff --git a/src/test/ui/error-codes/E0374.stderr b/src/test/ui/error-codes/E0374.stderr
new file mode 100644
index 0000000..7ab0f82
--- /dev/null
+++ b/src/test/ui/error-codes/E0374.stderr
@@ -0,0 +1,10 @@
+error[E0374]: the trait `CoerceUnsized` may only be implemented for a coercion between structures with one field being coerced, none found
+  --> $DIR/E0374.rs:8:1
+   |
+LL | / impl<T, U> CoerceUnsized<Foo<U>> for Foo<T>
+LL | |     where T: CoerceUnsized<U> {}
+   | |________________________________^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0374`.
diff --git a/src/test/ui/error-codes/E0375.rs b/src/test/ui/error-codes/E0375.rs
new file mode 100644
index 0000000..362854a
--- /dev/null
+++ b/src/test/ui/error-codes/E0375.rs
@@ -0,0 +1,15 @@
+// ignore-tidy-linelength
+
+#![feature(coerce_unsized)]
+use std::ops::CoerceUnsized;
+
+struct Foo<T: ?Sized, U: ?Sized> {
+    a: i32,
+    b: T,
+    c: U,
+}
+
+impl<T, U> CoerceUnsized<Foo<U, T>> for Foo<T, U> {}
+//~^ ERROR E0375
+
+fn main() {}
diff --git a/src/test/ui/error-codes/E0375.stderr b/src/test/ui/error-codes/E0375.stderr
new file mode 100644
index 0000000..18416e9
--- /dev/null
+++ b/src/test/ui/error-codes/E0375.stderr
@@ -0,0 +1,12 @@
+error[E0375]: implementing the trait `CoerceUnsized` requires multiple coercions
+  --> $DIR/E0375.rs:12:12
+   |
+LL | impl<T, U> CoerceUnsized<Foo<U, T>> for Foo<T, U> {}
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^ requires multiple coercions
+   |
+   = note: `CoerceUnsized` may only be implemented for a coercion between structures with one field being coerced
+   = note: currently, 2 fields need coercions: `b` (`T` to `U`), `c` (`U` to `T`)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0375`.
diff --git a/src/test/ui/error-codes/E0376.rs b/src/test/ui/error-codes/E0376.rs
new file mode 100644
index 0000000..f092eb0
--- /dev/null
+++ b/src/test/ui/error-codes/E0376.rs
@@ -0,0 +1,10 @@
+#![feature(coerce_unsized)]
+use std::ops::CoerceUnsized;
+
+struct Foo<T: ?Sized> {
+    a: T,
+}
+
+impl<T, U> CoerceUnsized<U> for Foo<T> {} //~ ERROR E0376
+
+fn main() {}
diff --git a/src/test/ui/error-codes/E0376.stderr b/src/test/ui/error-codes/E0376.stderr
new file mode 100644
index 0000000..015448c
--- /dev/null
+++ b/src/test/ui/error-codes/E0376.stderr
@@ -0,0 +1,9 @@
+error[E0376]: the trait `CoerceUnsized` may only be implemented for a coercion between structures
+  --> $DIR/E0376.rs:8:1
+   |
+LL | impl<T, U> CoerceUnsized<U> for Foo<T> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0376`.
diff --git a/src/test/ui/error-codes/E0388.nll.stderr b/src/test/ui/error-codes/E0388.nll.stderr
new file mode 100644
index 0000000..0fc8a76
--- /dev/null
+++ b/src/test/ui/error-codes/E0388.nll.stderr
@@ -0,0 +1,34 @@
+error[E0017]: references in constants may only refer to immutable values
+  --> $DIR/E0388.rs:4:30
+   |
+LL | const CR: &'static mut i32 = &mut C;
+   |                              ^^^^^^ constants require immutable values
+
+error[E0017]: references in statics may only refer to immutable values
+  --> $DIR/E0388.rs:5:39
+   |
+LL | static STATIC_REF: &'static mut i32 = &mut X;
+   |                                       ^^^^^^ statics require immutable values
+
+error: cannot mutate statics in the initializer of another static
+  --> $DIR/E0388.rs:5:39
+   |
+LL | static STATIC_REF: &'static mut i32 = &mut X;
+   |                                       ^^^^^^
+
+error[E0596]: cannot borrow immutable static item `X` as mutable
+  --> $DIR/E0388.rs:5:39
+   |
+LL | static STATIC_REF: &'static mut i32 = &mut X;
+   |                                       ^^^^^^ cannot borrow as mutable
+
+error[E0017]: references in statics may only refer to immutable values
+  --> $DIR/E0388.rs:8:38
+   |
+LL | static CONST_REF: &'static mut i32 = &mut C;
+   |                                      ^^^^^^ statics require immutable values
+
+error: aborting due to 5 previous errors
+
+Some errors occurred: E0017, E0596.
+For more information about an error, try `rustc --explain E0017`.
diff --git a/src/test/ui/error-codes/E0388.rs b/src/test/ui/error-codes/E0388.rs
new file mode 100644
index 0000000..817f255
--- /dev/null
+++ b/src/test/ui/error-codes/E0388.rs
@@ -0,0 +1,10 @@
+static X: i32 = 1;
+const C: i32 = 2;
+
+const CR: &'static mut i32 = &mut C; //~ ERROR E0017
+static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0017
+                                              //~| ERROR cannot borrow
+                                              //~| ERROR cannot mutate statics
+static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0017
+
+fn main() {}
diff --git a/src/test/ui/error-codes/E0388.stderr b/src/test/ui/error-codes/E0388.stderr
new file mode 100644
index 0000000..3f66245
--- /dev/null
+++ b/src/test/ui/error-codes/E0388.stderr
@@ -0,0 +1,34 @@
+error[E0017]: references in constants may only refer to immutable values
+  --> $DIR/E0388.rs:4:30
+   |
+LL | const CR: &'static mut i32 = &mut C;
+   |                              ^^^^^^ constants require immutable values
+
+error[E0017]: references in statics may only refer to immutable values
+  --> $DIR/E0388.rs:5:39
+   |
+LL | static STATIC_REF: &'static mut i32 = &mut X;
+   |                                       ^^^^^^ statics require immutable values
+
+error: cannot mutate statics in the initializer of another static
+  --> $DIR/E0388.rs:5:39
+   |
+LL | static STATIC_REF: &'static mut i32 = &mut X;
+   |                                       ^^^^^^
+
+error[E0596]: cannot borrow immutable static item as mutable
+  --> $DIR/E0388.rs:5:44
+   |
+LL | static STATIC_REF: &'static mut i32 = &mut X;
+   |                                            ^
+
+error[E0017]: references in statics may only refer to immutable values
+  --> $DIR/E0388.rs:8:38
+   |
+LL | static CONST_REF: &'static mut i32 = &mut C;
+   |                                      ^^^^^^ statics require immutable values
+
+error: aborting due to 5 previous errors
+
+Some errors occurred: E0017, E0596.
+For more information about an error, try `rustc --explain E0017`.
diff --git a/src/test/ui/error-codes/E0389.nll.stderr b/src/test/ui/error-codes/E0389.nll.stderr
new file mode 100644
index 0000000..c47750b
--- /dev/null
+++ b/src/test/ui/error-codes/E0389.nll.stderr
@@ -0,0 +1,11 @@
+error[E0594]: cannot assign to `fancy_ref.num` which is behind a `&` reference
+  --> $DIR/E0389.rs:8:5
+   |
+LL |     let fancy_ref = &(&mut fancy);
+   |                     ------------- help: consider changing this to be a mutable reference: `&mut (&mut fancy)`
+LL |     fancy_ref.num = 6;
+   |     ^^^^^^^^^^^^^^^^^ `fancy_ref` is a `&` reference, so the data it refers to cannot be written
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/error-codes/E0389.rs b/src/test/ui/error-codes/E0389.rs
new file mode 100644
index 0000000..8b82133
--- /dev/null
+++ b/src/test/ui/error-codes/E0389.rs
@@ -0,0 +1,10 @@
+struct FancyNum {
+    num: u8,
+}
+
+fn main() {
+    let mut fancy = FancyNum{ num: 5 };
+    let fancy_ref = &(&mut fancy);
+    fancy_ref.num = 6; //~ ERROR E0389
+    println!("{}", fancy_ref.num);
+}
diff --git a/src/test/ui/error-codes/E0389.stderr b/src/test/ui/error-codes/E0389.stderr
new file mode 100644
index 0000000..927eace
--- /dev/null
+++ b/src/test/ui/error-codes/E0389.stderr
@@ -0,0 +1,9 @@
+error[E0389]: cannot assign to data in a `&` reference
+  --> $DIR/E0389.rs:8:5
+   |
+LL |     fancy_ref.num = 6;
+   |     ^^^^^^^^^^^^^^^^^ assignment into an immutable reference
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0389`.
diff --git a/src/test/ui/error-codes/E0390.rs b/src/test/ui/error-codes/E0390.rs
new file mode 100644
index 0000000..4eb59a0
--- /dev/null
+++ b/src/test/ui/error-codes/E0390.rs
@@ -0,0 +1,8 @@
+struct Foo {
+    x: i32
+}
+
+impl *mut Foo {} //~ ERROR E0390
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0390.stderr b/src/test/ui/error-codes/E0390.stderr
new file mode 100644
index 0000000..3ca3a77
--- /dev/null
+++ b/src/test/ui/error-codes/E0390.stderr
@@ -0,0 +1,15 @@
+error[E0390]: only a single inherent implementation marked with `#[lang = "mut_ptr"]` is allowed for the `*mut T` primitive
+  --> $DIR/E0390.rs:5:1
+   |
+LL | impl *mut Foo {}
+   | ^^^^^^^^^^^^^^^^
+   |
+help: consider using a trait to implement these methods
+  --> $DIR/E0390.rs:5:1
+   |
+LL | impl *mut Foo {}
+   | ^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0390`.
diff --git a/src/test/ui/error-codes/E0392.rs b/src/test/ui/error-codes/E0392.rs
new file mode 100644
index 0000000..c98d900
--- /dev/null
+++ b/src/test/ui/error-codes/E0392.rs
@@ -0,0 +1,4 @@
+enum Foo<T> { Bar } //~ ERROR E0392
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0392.stderr b/src/test/ui/error-codes/E0392.stderr
new file mode 100644
index 0000000..1841957
--- /dev/null
+++ b/src/test/ui/error-codes/E0392.stderr
@@ -0,0 +1,11 @@
+error[E0392]: parameter `T` is never used
+  --> $DIR/E0392.rs:1:10
+   |
+LL | enum Foo<T> { Bar }
+   |          ^ unused type parameter
+   |
+   = help: consider removing `T` or using a marker such as `std::marker::PhantomData`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0392`.
diff --git a/src/test/ui/error-codes/E0393.rs b/src/test/ui/error-codes/E0393.rs
new file mode 100644
index 0000000..bdd4dea
--- /dev/null
+++ b/src/test/ui/error-codes/E0393.rs
@@ -0,0 +1,7 @@
+trait A<T=Self> {}
+
+fn together_we_will_rule_the_galaxy(son: &A) {}
+//~^ ERROR E0393
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0393.stderr b/src/test/ui/error-codes/E0393.stderr
new file mode 100644
index 0000000..bf564ef
--- /dev/null
+++ b/src/test/ui/error-codes/E0393.stderr
@@ -0,0 +1,11 @@
+error[E0393]: the type parameter `T` must be explicitly specified
+  --> $DIR/E0393.rs:3:43
+   |
+LL | fn together_we_will_rule_the_galaxy(son: &A) {}
+   |                                           ^ missing reference to `T`
+   |
+   = note: because of the default `Self` reference, type parameters must be specified on object types
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0393`.
diff --git a/src/test/ui/error-codes/E0395.rs b/src/test/ui/error-codes/E0395.rs
new file mode 100644
index 0000000..9657bbd
--- /dev/null
+++ b/src/test/ui/error-codes/E0395.rs
@@ -0,0 +1,8 @@
+// gate-test-const_compare_raw_pointers
+
+static FOO: i32 = 42;
+static BAR: i32 = 42;
+
+static BAZ: bool = unsafe { (&FOO as *const i32) == (&BAR as *const i32) }; //~ ERROR issue #53020
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0395.stderr b/src/test/ui/error-codes/E0395.stderr
new file mode 100644
index 0000000..9d80acb
--- /dev/null
+++ b/src/test/ui/error-codes/E0395.stderr
@@ -0,0 +1,11 @@
+error[E0658]: comparing raw pointers inside static (see issue #53020)
+  --> $DIR/E0395.rs:6:29
+   |
+LL | static BAZ: bool = unsafe { (&FOO as *const i32) == (&BAR as *const i32) };
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_compare_raw_pointers)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/error-codes/E0396-fixed.rs b/src/test/ui/error-codes/E0396-fixed.rs
new file mode 100644
index 0000000..1029c75
--- /dev/null
+++ b/src/test/ui/error-codes/E0396-fixed.rs
@@ -0,0 +1,9 @@
+#![feature(const_raw_ptr_deref)]
+
+const REG_ADDR: *const u8 = 0x5f3759df as *const u8;
+
+const VALUE: u8 = unsafe { *REG_ADDR };
+//~^ ERROR any use of this value will cause an error
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0396-fixed.stderr b/src/test/ui/error-codes/E0396-fixed.stderr
new file mode 100644
index 0000000..4b7f1fa
--- /dev/null
+++ b/src/test/ui/error-codes/E0396-fixed.stderr
@@ -0,0 +1,12 @@
+error: any use of this value will cause an error
+  --> $DIR/E0396-fixed.rs:5:28
+   |
+LL | const VALUE: u8 = unsafe { *REG_ADDR };
+   | ---------------------------^^^^^^^^^---
+   |                            |
+   |                            a memory access tried to interpret some bytes as a pointer
+   |
+   = note: #[deny(const_err)] on by default
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/error-codes/E0396.rs b/src/test/ui/error-codes/E0396.rs
new file mode 100644
index 0000000..b32853e
--- /dev/null
+++ b/src/test/ui/error-codes/E0396.rs
@@ -0,0 +1,9 @@
+// gate-test-const_raw_ptr_deref
+
+const REG_ADDR: *const u8 = 0x5f3759df as *const u8;
+
+const VALUE: u8 = unsafe { *REG_ADDR };
+//~^ ERROR dereferencing raw pointers in constants is unstable
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0396.stderr b/src/test/ui/error-codes/E0396.stderr
new file mode 100644
index 0000000..1006ff6
--- /dev/null
+++ b/src/test/ui/error-codes/E0396.stderr
@@ -0,0 +1,11 @@
+error[E0658]: dereferencing raw pointers in constants is unstable (see issue #51911)
+  --> $DIR/E0396.rs:5:28
+   |
+LL | const VALUE: u8 = unsafe { *REG_ADDR };
+   |                            ^^^^^^^^^
+   |
+   = help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/error-codes/E0401.rs b/src/test/ui/error-codes/E0401.rs
new file mode 100644
index 0000000..a120198
--- /dev/null
+++ b/src/test/ui/error-codes/E0401.rs
@@ -0,0 +1,30 @@
+trait Baz<T> {}
+
+fn foo<T>(x: T) {
+    fn bfnr<U, V: Baz<U>, W: Fn()>(y: T) { //~ ERROR E0401
+    }
+    fn baz<U,
+           V: Baz<U>,
+           W: Fn()>
+           (y: T) { //~ ERROR E0401
+    }
+    bfnr(x);
+}
+
+
+struct A<T> {
+    inner: T,
+}
+
+impl<T> Iterator for A<T> {
+    type Item = u8;
+    fn next(&mut self) -> Option<u8> {
+        fn helper(sel: &Self) -> u8 { //~ ERROR E0401
+            unimplemented!();
+        }
+        Some(helper(self))
+    }
+}
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0401.stderr b/src/test/ui/error-codes/E0401.stderr
new file mode 100644
index 0000000..7c54e5b
--- /dev/null
+++ b/src/test/ui/error-codes/E0401.stderr
@@ -0,0 +1,37 @@
+error[E0401]: can't use generic parameters from outer function
+  --> $DIR/E0401.rs:4:39
+   |
+LL | fn foo<T>(x: T) {
+   |        - type variable from outer function
+LL |     fn bfnr<U, V: Baz<U>, W: Fn()>(y: T) {
+   |        ---------------------------    ^ use of generic parameter from outer function
+   |        |
+   |        help: try using a local generic parameter instead: `bfnr<U, V: Baz<U>, W: Fn(), T>`
+
+error[E0401]: can't use generic parameters from outer function
+  --> $DIR/E0401.rs:9:16
+   |
+LL | fn foo<T>(x: T) {
+   |        - type variable from outer function
+...
+LL |     fn baz<U,
+   |        --- try adding a local generic parameter in this method instead
+...
+LL |            (y: T) {
+   |                ^ use of generic parameter from outer function
+
+error[E0401]: can't use generic parameters from outer function
+  --> $DIR/E0401.rs:22:25
+   |
+LL | impl<T> Iterator for A<T> {
+   | ---- `Self` type implicitly declared here, by this `impl`
+...
+LL |         fn helper(sel: &Self) -> u8 {
+   |                         ^^^^
+   |                         |
+   |                         use of generic parameter from outer function
+   |                         use a type here instead
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0401`.
diff --git a/src/test/ui/error-codes/E0403.rs b/src/test/ui/error-codes/E0403.rs
new file mode 100644
index 0000000..8bccb63
--- /dev/null
+++ b/src/test/ui/error-codes/E0403.rs
@@ -0,0 +1,4 @@
+fn foo<T, T>(s: T, u: T) {} //~ ERROR E0403
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0403.stderr b/src/test/ui/error-codes/E0403.stderr
new file mode 100644
index 0000000..2bd7de6
--- /dev/null
+++ b/src/test/ui/error-codes/E0403.stderr
@@ -0,0 +1,11 @@
+error[E0403]: the name `T` is already used for a generic parameter in this list of generic parameters
+  --> $DIR/E0403.rs:1:11
+   |
+LL | fn foo<T, T>(s: T, u: T) {}
+   |        -  ^ already used
+   |        |
+   |        first use of `T`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0403`.
diff --git a/src/test/ui/error-codes/E0404.rs b/src/test/ui/error-codes/E0404.rs
new file mode 100644
index 0000000..b173337
--- /dev/null
+++ b/src/test/ui/error-codes/E0404.rs
@@ -0,0 +1,8 @@
+struct Foo;
+struct Bar;
+
+impl Foo for Bar {} //~ ERROR E0404
+
+fn main() {}
+
+fn baz<T: Foo>(_: T) {} //~ ERROR E0404
diff --git a/src/test/ui/error-codes/E0404.stderr b/src/test/ui/error-codes/E0404.stderr
new file mode 100644
index 0000000..4ccb6c5
--- /dev/null
+++ b/src/test/ui/error-codes/E0404.stderr
@@ -0,0 +1,15 @@
+error[E0404]: expected trait, found struct `Foo`
+  --> $DIR/E0404.rs:4:6
+   |
+LL | impl Foo for Bar {}
+   |      ^^^ not a trait
+
+error[E0404]: expected trait, found struct `Foo`
+  --> $DIR/E0404.rs:8:11
+   |
+LL | fn baz<T: Foo>(_: T) {}
+   |           ^^^ not a trait
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0404`.
diff --git a/src/test/ui/error-codes/E0405.rs b/src/test/ui/error-codes/E0405.rs
new file mode 100644
index 0000000..f03c4e1
--- /dev/null
+++ b/src/test/ui/error-codes/E0405.rs
@@ -0,0 +1,6 @@
+struct Foo;
+
+impl SomeTrait for Foo {} //~ ERROR E0405
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0405.stderr b/src/test/ui/error-codes/E0405.stderr
new file mode 100644
index 0000000..a22afe6
--- /dev/null
+++ b/src/test/ui/error-codes/E0405.stderr
@@ -0,0 +1,9 @@
+error[E0405]: cannot find trait `SomeTrait` in this scope
+  --> $DIR/E0405.rs:3:6
+   |
+LL | impl SomeTrait for Foo {}
+   |      ^^^^^^^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0405`.
diff --git a/src/test/ui/error-codes/E0407.rs b/src/test/ui/error-codes/E0407.rs
new file mode 100644
index 0000000..962bd57
--- /dev/null
+++ b/src/test/ui/error-codes/E0407.rs
@@ -0,0 +1,14 @@
+trait Foo {
+    fn a();
+}
+
+struct Bar;
+
+impl Foo for Bar {
+    fn a() {}
+    fn b() {}
+    //~^ ERROR E0407
+}
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0407.stderr b/src/test/ui/error-codes/E0407.stderr
new file mode 100644
index 0000000..567fc87
--- /dev/null
+++ b/src/test/ui/error-codes/E0407.stderr
@@ -0,0 +1,9 @@
+error[E0407]: method `b` is not a member of trait `Foo`
+  --> $DIR/E0407.rs:9:5
+   |
+LL |     fn b() {}
+   |     ^^^^^^^^^ not a member of trait `Foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0407`.
diff --git a/src/test/ui/error-codes/E0408.rs b/src/test/ui/error-codes/E0408.rs
new file mode 100644
index 0000000..e91a98f
--- /dev/null
+++ b/src/test/ui/error-codes/E0408.rs
@@ -0,0 +1,8 @@
+fn main() {
+    let x = Some(0);
+
+    match x {
+        Some(y) | None => {} //~  ERROR variable `y` is not bound in all patterns
+        _ => ()
+    }
+}
diff --git a/src/test/ui/error-codes/E0408.stderr b/src/test/ui/error-codes/E0408.stderr
new file mode 100644
index 0000000..132a943
--- /dev/null
+++ b/src/test/ui/error-codes/E0408.stderr
@@ -0,0 +1,11 @@
+error[E0408]: variable `y` is not bound in all patterns
+  --> $DIR/E0408.rs:5:19
+   |
+LL |         Some(y) | None => {}
+   |              -    ^^^^ pattern doesn't bind `y`
+   |              |
+   |              variable not in all patterns
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0408`.
diff --git a/src/test/ui/error-codes/E0411.rs b/src/test/ui/error-codes/E0411.rs
new file mode 100644
index 0000000..872370f
--- /dev/null
+++ b/src/test/ui/error-codes/E0411.rs
@@ -0,0 +1,3 @@
+fn main() {
+    <Self>::foo; //~ ERROR E0411
+}
diff --git a/src/test/ui/error-codes/E0411.stderr b/src/test/ui/error-codes/E0411.stderr
new file mode 100644
index 0000000..c1c25e8
--- /dev/null
+++ b/src/test/ui/error-codes/E0411.stderr
@@ -0,0 +1,9 @@
+error[E0411]: cannot find type `Self` in this scope
+  --> $DIR/E0411.rs:2:6
+   |
+LL |     <Self>::foo;
+   |      ^^^^ `Self` is only available in impls, traits, and type definitions
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0411`.
diff --git a/src/test/ui/error-codes/E0412.rs b/src/test/ui/error-codes/E0412.rs
new file mode 100644
index 0000000..5f922a5
--- /dev/null
+++ b/src/test/ui/error-codes/E0412.rs
@@ -0,0 +1,4 @@
+impl Something {} //~ ERROR E0412
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0412.stderr b/src/test/ui/error-codes/E0412.stderr
new file mode 100644
index 0000000..7bdaa18
--- /dev/null
+++ b/src/test/ui/error-codes/E0412.stderr
@@ -0,0 +1,9 @@
+error[E0412]: cannot find type `Something` in this scope
+  --> $DIR/E0412.rs:1:6
+   |
+LL | impl Something {}
+   |      ^^^^^^^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/src/test/ui/error-codes/E0415.rs b/src/test/ui/error-codes/E0415.rs
new file mode 100644
index 0000000..6177ac3
--- /dev/null
+++ b/src/test/ui/error-codes/E0415.rs
@@ -0,0 +1,4 @@
+fn foo(f: i32, f: i32) {} //~ ERROR E0415
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0415.stderr b/src/test/ui/error-codes/E0415.stderr
new file mode 100644
index 0000000..c2b8fdc
--- /dev/null
+++ b/src/test/ui/error-codes/E0415.stderr
@@ -0,0 +1,9 @@
+error[E0415]: identifier `f` is bound more than once in this parameter list
+  --> $DIR/E0415.rs:1:16
+   |
+LL | fn foo(f: i32, f: i32) {}
+   |                ^ used as parameter more than once
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0415`.
diff --git a/src/test/ui/error-codes/E0416.rs b/src/test/ui/error-codes/E0416.rs
new file mode 100644
index 0000000..88eece0
--- /dev/null
+++ b/src/test/ui/error-codes/E0416.rs
@@ -0,0 +1,5 @@
+fn main() {
+    match (1, 2) {
+        (x, x) => {} //~ ERROR E0416
+    }
+}
diff --git a/src/test/ui/error-codes/E0416.stderr b/src/test/ui/error-codes/E0416.stderr
new file mode 100644
index 0000000..78acac5
--- /dev/null
+++ b/src/test/ui/error-codes/E0416.stderr
@@ -0,0 +1,9 @@
+error[E0416]: identifier `x` is bound more than once in the same pattern
+  --> $DIR/E0416.rs:3:13
+   |
+LL |         (x, x) => {}
+   |             ^ used in a pattern more than once
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0416`.
diff --git a/src/test/ui/error-codes/E0423.rs b/src/test/ui/error-codes/E0423.rs
new file mode 100644
index 0000000..2b26808
--- /dev/null
+++ b/src/test/ui/error-codes/E0423.rs
@@ -0,0 +1,24 @@
+fn main () {
+    struct Foo { a: bool };
+
+    let f = Foo(); //~ ERROR E0423
+}
+
+fn bar() {
+    struct S { x: i32, y: i32 }
+    #[derive(PartialEq)]
+    struct T {}
+
+    if let S { x: _x, y: 2 } = S { x: 1, y: 2 } { println!("Ok"); }
+    //~^ ERROR E0423
+    //~|  expected type, found `1`
+    if T {} == T {} { println!("Ok"); }
+    //~^ ERROR E0423
+    //~| ERROR expected expression, found `==`
+}
+
+fn foo() {
+    for _ in std::ops::Range { start: 0, end: 10 } {}
+    //~^ ERROR E0423
+    //~| ERROR expected type, found `0`
+}
diff --git a/src/test/ui/error-codes/E0423.stderr b/src/test/ui/error-codes/E0423.stderr
new file mode 100644
index 0000000..b0ef4e1
--- /dev/null
+++ b/src/test/ui/error-codes/E0423.stderr
@@ -0,0 +1,70 @@
+error: expected type, found `1`
+  --> $DIR/E0423.rs:12:39
+   |
+LL |     if let S { x: _x, y: 2 } = S { x: 1, y: 2 } { println!("Ok"); }
+   |                                       ^ expecting a type here because of type ascription
+   |
+   = note: type ascription is a nightly-only feature that lets you annotate an expression with a type: `<expr>: <type>`
+note: this expression expects an ascribed type after the colon
+  --> $DIR/E0423.rs:12:36
+   |
+LL |     if let S { x: _x, y: 2 } = S { x: 1, y: 2 } { println!("Ok"); }
+   |                                    ^
+   = help: this might be indicative of a syntax error elsewhere
+
+error: expected expression, found `==`
+  --> $DIR/E0423.rs:15:13
+   |
+LL |     if T {} == T {} { println!("Ok"); }
+   |             ^^ expected expression
+
+error: expected type, found `0`
+  --> $DIR/E0423.rs:21:39
+   |
+LL |     for _ in std::ops::Range { start: 0, end: 10 } {}
+   |                                       ^ expecting a type here because of type ascription
+   |
+   = note: type ascription is a nightly-only feature that lets you annotate an expression with a type: `<expr>: <type>`
+note: this expression expects an ascribed type after the colon
+  --> $DIR/E0423.rs:21:32
+   |
+LL |     for _ in std::ops::Range { start: 0, end: 10 } {}
+   |                                ^^^^^
+   = help: this might be indicative of a syntax error elsewhere
+
+error[E0423]: expected function, found struct `Foo`
+  --> $DIR/E0423.rs:4:13
+   |
+LL |     let f = Foo();
+   |             ^^^
+   |             |
+   |             did you mean `Foo { /* fields */ }`?
+   |             help: a function with a similar name exists: `foo`
+
+error[E0423]: expected value, found struct `S`
+  --> $DIR/E0423.rs:12:32
+   |
+LL |     if let S { x: _x, y: 2 } = S { x: 1, y: 2 } { println!("Ok"); }
+   |                                ^---------------
+   |                                |
+   |                                help: surround the struct literal with parenthesis: `(S { x: 1, y: 2 })`
+
+error[E0423]: expected value, found struct `T`
+  --> $DIR/E0423.rs:15:8
+   |
+LL |     if T {} == T {} { println!("Ok"); }
+   |        ^---
+   |        |
+   |        help: surround the struct literal with parenthesis: `(T {})`
+
+error[E0423]: expected value, found struct `std::ops::Range`
+  --> $DIR/E0423.rs:21:14
+   |
+LL |     for _ in std::ops::Range { start: 0, end: 10 } {}
+   |              ^^^^^^^^^^^^^^^----------------------
+   |              |
+   |              help: surround the struct literal with parenthesis: `(std::ops::Range { start: 0, end: 10 })`
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0423`.
diff --git a/src/test/ui/error-codes/E0424.rs b/src/test/ui/error-codes/E0424.rs
new file mode 100644
index 0000000..3c6a1d4
--- /dev/null
+++ b/src/test/ui/error-codes/E0424.rs
@@ -0,0 +1,13 @@
+struct Foo;
+
+impl Foo {
+    fn bar(self) {}
+
+    fn foo() {
+        self.bar(); //~ ERROR E0424
+    }
+}
+
+fn main () {
+    let self = "self"; //~ ERROR E0424
+}
diff --git a/src/test/ui/error-codes/E0424.stderr b/src/test/ui/error-codes/E0424.stderr
new file mode 100644
index 0000000..d67a266
--- /dev/null
+++ b/src/test/ui/error-codes/E0424.stderr
@@ -0,0 +1,15 @@
+error[E0424]: expected value, found module `self`
+  --> $DIR/E0424.rs:7:9
+   |
+LL |         self.bar();
+   |         ^^^^ `self` value is a keyword only available in methods with `self` parameter
+
+error[E0424]: expected unit struct/variant or constant, found module `self`
+  --> $DIR/E0424.rs:12:9
+   |
+LL |     let self = "self";
+   |         ^^^^ `self` value is a keyword and may not be bound to variables or shadowed
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0424`.
diff --git a/src/test/ui/error-codes/E0425.rs b/src/test/ui/error-codes/E0425.rs
new file mode 100644
index 0000000..ec234ae
--- /dev/null
+++ b/src/test/ui/error-codes/E0425.rs
@@ -0,0 +1,8 @@
+trait Foo {
+    fn bar() {
+        elf; //~ ERROR E0425
+    }
+}
+
+fn main () {
+}
diff --git a/src/test/ui/error-codes/E0425.stderr b/src/test/ui/error-codes/E0425.stderr
new file mode 100644
index 0000000..9ef4608
--- /dev/null
+++ b/src/test/ui/error-codes/E0425.stderr
@@ -0,0 +1,9 @@
+error[E0425]: cannot find value `elf` in this scope
+  --> $DIR/E0425.rs:3:9
+   |
+LL |         elf;
+   |         ^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/error-codes/E0426.rs b/src/test/ui/error-codes/E0426.rs
new file mode 100644
index 0000000..7a1dcde
--- /dev/null
+++ b/src/test/ui/error-codes/E0426.rs
@@ -0,0 +1,6 @@
+fn main () {
+    loop {
+        break 'a;
+        //~^ ERROR E0426
+    }
+}
diff --git a/src/test/ui/error-codes/E0426.stderr b/src/test/ui/error-codes/E0426.stderr
new file mode 100644
index 0000000..035f2eb
--- /dev/null
+++ b/src/test/ui/error-codes/E0426.stderr
@@ -0,0 +1,9 @@
+error[E0426]: use of undeclared label `'a`
+  --> $DIR/E0426.rs:3:15
+   |
+LL |         break 'a;
+   |               ^^ undeclared label `'a`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0426`.
diff --git a/src/test/ui/error-codes/E0428.rs b/src/test/ui/error-codes/E0428.rs
new file mode 100644
index 0000000..eb9594f
--- /dev/null
+++ b/src/test/ui/error-codes/E0428.rs
@@ -0,0 +1,5 @@
+struct Bar; //~ previous definition of the type `Bar` here
+struct Bar; //~ ERROR E0428
+
+fn main () {
+}
diff --git a/src/test/ui/error-codes/E0428.stderr b/src/test/ui/error-codes/E0428.stderr
new file mode 100644
index 0000000..205bcf3
--- /dev/null
+++ b/src/test/ui/error-codes/E0428.stderr
@@ -0,0 +1,13 @@
+error[E0428]: the name `Bar` is defined multiple times
+  --> $DIR/E0428.rs:2:1
+   |
+LL | struct Bar;
+   | ----------- previous definition of the type `Bar` here
+LL | struct Bar;
+   | ^^^^^^^^^^^ `Bar` redefined here
+   |
+   = note: `Bar` must be defined only once in the type namespace of this module
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0428`.
diff --git a/src/test/ui/error-codes/E0429.rs b/src/test/ui/error-codes/E0429.rs
new file mode 100644
index 0000000..e74b27a
--- /dev/null
+++ b/src/test/ui/error-codes/E0429.rs
@@ -0,0 +1,4 @@
+use std::fmt::self; //~ ERROR E0429
+
+fn main () {
+}
diff --git a/src/test/ui/error-codes/E0429.stderr b/src/test/ui/error-codes/E0429.stderr
new file mode 100644
index 0000000..b5f76a1
--- /dev/null
+++ b/src/test/ui/error-codes/E0429.stderr
@@ -0,0 +1,9 @@
+error[E0429]: `self` imports are only allowed within a { } list
+  --> $DIR/E0429.rs:1:5
+   |
+LL | use std::fmt::self;
+   |     ^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0429`.
diff --git a/src/test/ui/error-codes/E0430.rs b/src/test/ui/error-codes/E0430.rs
new file mode 100644
index 0000000..ba2f671
--- /dev/null
+++ b/src/test/ui/error-codes/E0430.rs
@@ -0,0 +1,5 @@
+use std::fmt::{self, self}; //~ ERROR E0430
+                            //~^ ERROR E0252
+
+fn main () {
+}
diff --git a/src/test/ui/error-codes/E0430.stderr b/src/test/ui/error-codes/E0430.stderr
new file mode 100644
index 0000000..d8e4a80
--- /dev/null
+++ b/src/test/ui/error-codes/E0430.stderr
@@ -0,0 +1,22 @@
+error[E0430]: `self` import can only appear once in an import list
+  --> $DIR/E0430.rs:1:16
+   |
+LL | use std::fmt::{self, self};
+   |                ^^^^  ---- another `self` import appears here
+   |                |
+   |                can only appear once in an import list
+
+error[E0252]: the name `fmt` is defined multiple times
+  --> $DIR/E0430.rs:1:22
+   |
+LL | use std::fmt::{self, self};
+   |                ----  ^^^^ `fmt` reimported here
+   |                |
+   |                previous import of the module `fmt` here
+   |
+   = note: `fmt` must be defined only once in the type namespace of this module
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0252, E0430.
+For more information about an error, try `rustc --explain E0252`.
diff --git a/src/test/ui/error-codes/E0431.rs b/src/test/ui/error-codes/E0431.rs
new file mode 100644
index 0000000..2e2ccba
--- /dev/null
+++ b/src/test/ui/error-codes/E0431.rs
@@ -0,0 +1,4 @@
+use {self}; //~ ERROR E0431
+
+fn main () {
+}
diff --git a/src/test/ui/error-codes/E0431.stderr b/src/test/ui/error-codes/E0431.stderr
new file mode 100644
index 0000000..adfd2d9
--- /dev/null
+++ b/src/test/ui/error-codes/E0431.stderr
@@ -0,0 +1,9 @@
+error[E0431]: `self` import can only appear in an import list with a non-empty prefix
+  --> $DIR/E0431.rs:1:6
+   |
+LL | use {self};
+   |      ^^^^ can only appear in an import list with a non-empty prefix
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0431`.
diff --git a/src/test/ui/error-codes/E0432.rs b/src/test/ui/error-codes/E0432.rs
new file mode 100644
index 0000000..1fc95f9
--- /dev/null
+++ b/src/test/ui/error-codes/E0432.rs
@@ -0,0 +1,4 @@
+use something::Foo; //~ ERROR E0432
+
+fn main () {
+}
diff --git a/src/test/ui/error-codes/E0432.stderr b/src/test/ui/error-codes/E0432.stderr
new file mode 100644
index 0000000..137a1af
--- /dev/null
+++ b/src/test/ui/error-codes/E0432.stderr
@@ -0,0 +1,9 @@
+error[E0432]: unresolved import `something`
+  --> $DIR/E0432.rs:1:5
+   |
+LL | use something::Foo;
+   |     ^^^^^^^^^ maybe a missing `extern crate something;`?
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/error-codes/E0433.rs b/src/test/ui/error-codes/E0433.rs
new file mode 100644
index 0000000..9b54ec8
--- /dev/null
+++ b/src/test/ui/error-codes/E0433.rs
@@ -0,0 +1,3 @@
+fn main () {
+    let map = HashMap::new(); //~ ERROR E0433
+}
diff --git a/src/test/ui/error-codes/E0433.stderr b/src/test/ui/error-codes/E0433.stderr
new file mode 100644
index 0000000..d852e18
--- /dev/null
+++ b/src/test/ui/error-codes/E0433.stderr
@@ -0,0 +1,9 @@
+error[E0433]: failed to resolve: use of undeclared type or module `HashMap`
+  --> $DIR/E0433.rs:2:15
+   |
+LL |     let map = HashMap::new();
+   |               ^^^^^^^ use of undeclared type or module `HashMap`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/error-codes/E0434.rs b/src/test/ui/error-codes/E0434.rs
new file mode 100644
index 0000000..db7037e
--- /dev/null
+++ b/src/test/ui/error-codes/E0434.rs
@@ -0,0 +1,9 @@
+fn foo() {
+    let y = 5;
+    fn bar() -> u32 {
+        y //~ ERROR E0434
+    }
+}
+
+fn main () {
+}
diff --git a/src/test/ui/error-codes/E0434.stderr b/src/test/ui/error-codes/E0434.stderr
new file mode 100644
index 0000000..14508cc
--- /dev/null
+++ b/src/test/ui/error-codes/E0434.stderr
@@ -0,0 +1,11 @@
+error[E0434]: can't capture dynamic environment in a fn item
+  --> $DIR/E0434.rs:4:9
+   |
+LL |         y
+   |         ^
+   |
+   = help: use the `|| { ... }` closure form instead
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0434`.
diff --git a/src/test/ui/error-codes/E0435.rs b/src/test/ui/error-codes/E0435.rs
new file mode 100644
index 0000000..620dd30
--- /dev/null
+++ b/src/test/ui/error-codes/E0435.rs
@@ -0,0 +1,4 @@
+fn main () {
+    let foo = 42u32;
+    let _: [u8; foo]; //~ ERROR E0435
+}
diff --git a/src/test/ui/error-codes/E0435.stderr b/src/test/ui/error-codes/E0435.stderr
new file mode 100644
index 0000000..349aa0d
--- /dev/null
+++ b/src/test/ui/error-codes/E0435.stderr
@@ -0,0 +1,9 @@
+error[E0435]: attempt to use a non-constant value in a constant
+  --> $DIR/E0435.rs:3:17
+   |
+LL |     let _: [u8; foo];
+   |                 ^^^ non-constant value
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0435`.
diff --git a/src/test/ui/error-codes/E0437.rs b/src/test/ui/error-codes/E0437.rs
new file mode 100644
index 0000000..f8c1500
--- /dev/null
+++ b/src/test/ui/error-codes/E0437.rs
@@ -0,0 +1,8 @@
+trait Foo {}
+
+impl Foo for i32 {
+    type Bar = bool; //~ ERROR E0437
+}
+
+fn main () {
+}
diff --git a/src/test/ui/error-codes/E0437.stderr b/src/test/ui/error-codes/E0437.stderr
new file mode 100644
index 0000000..217b164
--- /dev/null
+++ b/src/test/ui/error-codes/E0437.stderr
@@ -0,0 +1,9 @@
+error[E0437]: type `Bar` is not a member of trait `Foo`
+  --> $DIR/E0437.rs:4:5
+   |
+LL |     type Bar = bool;
+   |     ^^^^^^^^^^^^^^^^ not a member of trait `Foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0437`.
diff --git a/src/test/ui/error-codes/E0438.rs b/src/test/ui/error-codes/E0438.rs
new file mode 100644
index 0000000..02898b8
--- /dev/null
+++ b/src/test/ui/error-codes/E0438.rs
@@ -0,0 +1,8 @@
+trait Bar {}
+
+impl Bar for i32 {
+    const BAR: bool = true; //~ ERROR E0438
+}
+
+fn main () {
+}
diff --git a/src/test/ui/error-codes/E0438.stderr b/src/test/ui/error-codes/E0438.stderr
new file mode 100644
index 0000000..853f0c3
--- /dev/null
+++ b/src/test/ui/error-codes/E0438.stderr
@@ -0,0 +1,9 @@
+error[E0438]: const `BAR` is not a member of trait `Bar`
+  --> $DIR/E0438.rs:4:5
+   |
+LL |     const BAR: bool = true;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ not a member of trait `Bar`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0438`.
diff --git a/src/test/ui/error-codes/E0439.rs b/src/test/ui/error-codes/E0439.rs
new file mode 100644
index 0000000..86e9cb5
--- /dev/null
+++ b/src/test/ui/error-codes/E0439.rs
@@ -0,0 +1,8 @@
+#![feature(platform_intrinsics)]
+
+extern "platform-intrinsic" {
+    fn simd_shuffle<A,B>(a: A, b: A, c: [u32; 8]) -> B; //~ ERROR E0439
+}
+
+fn main () {
+}
diff --git a/src/test/ui/error-codes/E0439.stderr b/src/test/ui/error-codes/E0439.stderr
new file mode 100644
index 0000000..8021f7d
--- /dev/null
+++ b/src/test/ui/error-codes/E0439.stderr
@@ -0,0 +1,9 @@
+error[E0439]: invalid `simd_shuffle`, needs length: `simd_shuffle`
+  --> $DIR/E0439.rs:4:5
+   |
+LL |     fn simd_shuffle<A,B>(a: A, b: A, c: [u32; 8]) -> B;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0439`.
diff --git a/src/test/ui/error-codes/E0445.rs b/src/test/ui/error-codes/E0445.rs
new file mode 100644
index 0000000..a9a3aee
--- /dev/null
+++ b/src/test/ui/error-codes/E0445.rs
@@ -0,0 +1,12 @@
+trait Foo {
+    fn dummy(&self) { }
+}
+
+pub trait Bar : Foo {}
+//~^ ERROR private trait `Foo` in public interface [E0445]
+pub struct Bar2<T: Foo>(pub T);
+//~^ ERROR private trait `Foo` in public interface [E0445]
+pub fn foo<T: Foo> (t: T) {}
+//~^ ERROR private trait `Foo` in public interface [E0445]
+
+fn main() {}
diff --git a/src/test/ui/error-codes/E0445.stderr b/src/test/ui/error-codes/E0445.stderr
new file mode 100644
index 0000000..d0d6ebe
--- /dev/null
+++ b/src/test/ui/error-codes/E0445.stderr
@@ -0,0 +1,21 @@
+error[E0445]: private trait `Foo` in public interface
+  --> $DIR/E0445.rs:5:1
+   |
+LL | pub trait Bar : Foo {}
+   | ^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait
+
+error[E0445]: private trait `Foo` in public interface
+  --> $DIR/E0445.rs:7:1
+   |
+LL | pub struct Bar2<T: Foo>(pub T);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait
+
+error[E0445]: private trait `Foo` in public interface
+  --> $DIR/E0445.rs:9:1
+   |
+LL | pub fn foo<T: Foo> (t: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0445`.
diff --git a/src/test/ui/error-codes/E0446.rs b/src/test/ui/error-codes/E0446.rs
new file mode 100644
index 0000000..f61c7e5
--- /dev/null
+++ b/src/test/ui/error-codes/E0446.rs
@@ -0,0 +1,9 @@
+mod foo {
+    struct Bar(u32);
+
+    pub fn bar() -> Bar { //~ ERROR E0446
+        Bar(0)
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/error-codes/E0446.stderr b/src/test/ui/error-codes/E0446.stderr
new file mode 100644
index 0000000..a0f5f70
--- /dev/null
+++ b/src/test/ui/error-codes/E0446.stderr
@@ -0,0 +1,14 @@
+error[E0446]: private type `foo::Bar` in public interface
+  --> $DIR/E0446.rs:4:5
+   |
+LL |       struct Bar(u32);
+   |       - `foo::Bar` declared as private
+LL | 
+LL | /     pub fn bar() -> Bar {
+LL | |         Bar(0)
+LL | |     }
+   | |_____^ can't leak private type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0446`.
diff --git a/src/test/ui/error-codes/E0449.rs b/src/test/ui/error-codes/E0449.rs
new file mode 100644
index 0000000..eba0d47
--- /dev/null
+++ b/src/test/ui/error-codes/E0449.rs
@@ -0,0 +1,14 @@
+struct Bar;
+
+trait Foo {
+    fn foo();
+}
+
+pub impl Bar {} //~ ERROR E0449
+
+pub impl Foo for Bar { //~ ERROR E0449
+    pub fn foo() {} //~ ERROR E0449
+}
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0449.stderr b/src/test/ui/error-codes/E0449.stderr
new file mode 100644
index 0000000..8221a5e
--- /dev/null
+++ b/src/test/ui/error-codes/E0449.stderr
@@ -0,0 +1,23 @@
+error[E0449]: unnecessary visibility qualifier
+  --> $DIR/E0449.rs:7:1
+   |
+LL | pub impl Bar {}
+   | ^^^ `pub` not permitted here because it's implied
+   |
+   = note: place qualifiers on individual impl items instead
+
+error[E0449]: unnecessary visibility qualifier
+  --> $DIR/E0449.rs:9:1
+   |
+LL | pub impl Foo for Bar {
+   | ^^^ `pub` not permitted here because it's implied
+
+error[E0449]: unnecessary visibility qualifier
+  --> $DIR/E0449.rs:10:5
+   |
+LL |     pub fn foo() {}
+   |     ^^^ `pub` not permitted here because it's implied
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0449`.
diff --git a/src/test/ui/error-codes/E0451.rs b/src/test/ui/error-codes/E0451.rs
new file mode 100644
index 0000000..aa8f051
--- /dev/null
+++ b/src/test/ui/error-codes/E0451.rs
@@ -0,0 +1,19 @@
+mod bar {
+    pub struct Foo {
+        pub a: isize,
+        b: isize,
+    }
+
+    pub struct FooTuple (
+        pub isize,
+        isize,
+    );
+}
+
+fn pat_match(foo: bar::Foo) {
+    let bar::Foo{a, b} = foo; //~ ERROR E0451
+}
+
+fn main() {
+    let f = bar::Foo{ a: 0, b: 0 }; //~ ERROR E0451
+}
diff --git a/src/test/ui/error-codes/E0451.stderr b/src/test/ui/error-codes/E0451.stderr
new file mode 100644
index 0000000..655f3a9
--- /dev/null
+++ b/src/test/ui/error-codes/E0451.stderr
@@ -0,0 +1,15 @@
+error[E0451]: field `b` of struct `bar::Foo` is private
+  --> $DIR/E0451.rs:14:21
+   |
+LL |     let bar::Foo{a, b} = foo;
+   |                     ^ field `b` is private
+
+error[E0451]: field `b` of struct `bar::Foo` is private
+  --> $DIR/E0451.rs:18:29
+   |
+LL |     let f = bar::Foo{ a: 0, b: 0 };
+   |                             ^^^^ field `b` is private
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0451`.
diff --git a/src/test/ui/error-codes/E0452.rs b/src/test/ui/error-codes/E0452.rs
new file mode 100644
index 0000000..940b9f6
--- /dev/null
+++ b/src/test/ui/error-codes/E0452.rs
@@ -0,0 +1,4 @@
+#![allow(foo = "")] //~ ERROR E0452
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0452.stderr b/src/test/ui/error-codes/E0452.stderr
new file mode 100644
index 0000000..7c30933
--- /dev/null
+++ b/src/test/ui/error-codes/E0452.stderr
@@ -0,0 +1,9 @@
+error[E0452]: malformed lint attribute
+  --> $DIR/E0452.rs:1:10
+   |
+LL | #![allow(foo = "")]
+   |          ^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0452`.
diff --git a/src/test/ui/error-codes/E0453.rs b/src/test/ui/error-codes/E0453.rs
new file mode 100644
index 0000000..46fa048
--- /dev/null
+++ b/src/test/ui/error-codes/E0453.rs
@@ -0,0 +1,6 @@
+#![forbid(non_snake_case)]
+
+#[allow(non_snake_case)]
+//~^ ERROR allow(non_snake_case) overruled by outer forbid(non_snake_case)
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0453.stderr b/src/test/ui/error-codes/E0453.stderr
new file mode 100644
index 0000000..03cc756
--- /dev/null
+++ b/src/test/ui/error-codes/E0453.stderr
@@ -0,0 +1,12 @@
+error[E0453]: allow(non_snake_case) overruled by outer forbid(non_snake_case)
+  --> $DIR/E0453.rs:3:9
+   |
+LL | #![forbid(non_snake_case)]
+   |           -------------- `forbid` level set here
+LL | 
+LL | #[allow(non_snake_case)]
+   |         ^^^^^^^^^^^^^^ overruled by previous forbid
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0453`.
diff --git a/src/test/ui/error-codes/E0454.rs b/src/test/ui/error-codes/E0454.rs
new file mode 100644
index 0000000..d62210c
--- /dev/null
+++ b/src/test/ui/error-codes/E0454.rs
@@ -0,0 +1,5 @@
+#[link(name = "")] extern {}
+//~^ ERROR E0454
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0454.stderr b/src/test/ui/error-codes/E0454.stderr
new file mode 100644
index 0000000..352c3ba
--- /dev/null
+++ b/src/test/ui/error-codes/E0454.stderr
@@ -0,0 +1,9 @@
+error[E0454]: #[link(name = "")] given with empty name
+  --> $DIR/E0454.rs:1:1
+   |
+LL | #[link(name = "")] extern {}
+   | ^^^^^^^^^^^^^^^^^^ empty name given
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0454`.
diff --git a/src/test/ui/error-codes/E0458.rs b/src/test/ui/error-codes/E0458.rs
new file mode 100644
index 0000000..3d23035
--- /dev/null
+++ b/src/test/ui/error-codes/E0458.rs
@@ -0,0 +1,5 @@
+#[link(kind = "wonderful_unicorn")] extern {} //~ ERROR E0458
+                                              //~| ERROR E0459
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0458.stderr b/src/test/ui/error-codes/E0458.stderr
new file mode 100644
index 0000000..154e0b1
--- /dev/null
+++ b/src/test/ui/error-codes/E0458.stderr
@@ -0,0 +1,18 @@
+error[E0458]: unknown kind: `wonderful_unicorn`
+  --> $DIR/E0458.rs:1:8
+   |
+LL | #[link(kind = "wonderful_unicorn")] extern {}
+   | -------^^^^^^^^^^^^^^^^^^^^^^^^^^--
+   |        |
+   |        unknown kind
+
+error[E0459]: #[link(...)] specified without `name = "foo"`
+  --> $DIR/E0458.rs:1:1
+   |
+LL | #[link(kind = "wonderful_unicorn")] extern {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `name` argument
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0458, E0459.
+For more information about an error, try `rustc --explain E0458`.
diff --git a/src/test/ui/error-codes/E0459.rs b/src/test/ui/error-codes/E0459.rs
new file mode 100644
index 0000000..80a2fd3
--- /dev/null
+++ b/src/test/ui/error-codes/E0459.rs
@@ -0,0 +1,4 @@
+#[link(kind = "dylib")] extern {} //~ ERROR E0459
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0459.stderr b/src/test/ui/error-codes/E0459.stderr
new file mode 100644
index 0000000..da7069f
--- /dev/null
+++ b/src/test/ui/error-codes/E0459.stderr
@@ -0,0 +1,9 @@
+error[E0459]: #[link(...)] specified without `name = "foo"`
+  --> $DIR/E0459.rs:1:1
+   |
+LL | #[link(kind = "dylib")] extern {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^ missing `name` argument
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0459`.
diff --git a/src/test/ui/error-codes/E0463.rs b/src/test/ui/error-codes/E0463.rs
new file mode 100644
index 0000000..6835652
--- /dev/null
+++ b/src/test/ui/error-codes/E0463.rs
@@ -0,0 +1,7 @@
+#![feature(plugin)]
+#![plugin(cookie_monster)]
+//~^ ERROR E0463
+extern crate cake_is_a_lie;
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0463.stderr b/src/test/ui/error-codes/E0463.stderr
new file mode 100644
index 0000000..1aa66e1
--- /dev/null
+++ b/src/test/ui/error-codes/E0463.stderr
@@ -0,0 +1,9 @@
+error[E0463]: can't find crate for `cookie_monster`
+  --> $DIR/E0463.rs:2:11
+   |
+LL | #![plugin(cookie_monster)]
+   |           ^^^^^^^^^^^^^^ can't find crate
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0463`.
diff --git a/src/test/ui/error-codes/E0478.rs b/src/test/ui/error-codes/E0478.rs
new file mode 100644
index 0000000..1b5ca09
--- /dev/null
+++ b/src/test/ui/error-codes/E0478.rs
@@ -0,0 +1,8 @@
+trait Wedding<'t>: 't { }
+
+struct Prince<'kiss, 'SnowWhite> {
+    child: Box<Wedding<'kiss> + 'SnowWhite>, //~ ERROR E0478
+}
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0478.stderr b/src/test/ui/error-codes/E0478.stderr
new file mode 100644
index 0000000..71e49036
--- /dev/null
+++ b/src/test/ui/error-codes/E0478.stderr
@@ -0,0 +1,20 @@
+error[E0478]: lifetime bound not satisfied
+  --> $DIR/E0478.rs:4:5
+   |
+LL |     child: Box<Wedding<'kiss> + 'SnowWhite>,
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: lifetime parameter instantiated with the lifetime 'SnowWhite as defined on the struct at 3:22
+  --> $DIR/E0478.rs:3:22
+   |
+LL | struct Prince<'kiss, 'SnowWhite> {
+   |                      ^^^^^^^^^^
+note: but lifetime parameter must outlive the lifetime 'kiss as defined on the struct at 3:15
+  --> $DIR/E0478.rs:3:15
+   |
+LL | struct Prince<'kiss, 'SnowWhite> {
+   |               ^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0478`.
diff --git a/src/test/ui/error-codes/E0492.rs b/src/test/ui/error-codes/E0492.rs
new file mode 100644
index 0000000..2de4c12
--- /dev/null
+++ b/src/test/ui/error-codes/E0492.rs
@@ -0,0 +1,7 @@
+use std::sync::atomic::AtomicUsize;
+
+const A: AtomicUsize = AtomicUsize::new(0);
+static B: &'static AtomicUsize = &A; //~ ERROR E0492
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0492.stderr b/src/test/ui/error-codes/E0492.stderr
new file mode 100644
index 0000000..5f337dd
--- /dev/null
+++ b/src/test/ui/error-codes/E0492.stderr
@@ -0,0 +1,9 @@
+error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
+  --> $DIR/E0492.rs:4:34
+   |
+LL | static B: &'static AtomicUsize = &A;
+   |                                  ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0492`.
diff --git a/src/test/ui/error-codes/E0496.rs b/src/test/ui/error-codes/E0496.rs
new file mode 100644
index 0000000..b57c9c7
--- /dev/null
+++ b/src/test/ui/error-codes/E0496.rs
@@ -0,0 +1,11 @@
+struct Foo<'a> {
+    a: &'a i32,
+}
+
+impl<'a> Foo<'a> {
+    fn f<'a>(x: &'a i32) { //~ ERROR E0496
+    }
+}
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0496.stderr b/src/test/ui/error-codes/E0496.stderr
new file mode 100644
index 0000000..b0294ee
--- /dev/null
+++ b/src/test/ui/error-codes/E0496.stderr
@@ -0,0 +1,11 @@
+error[E0496]: lifetime name `'a` shadows a lifetime name that is already in scope
+  --> $DIR/E0496.rs:6:10
+   |
+LL | impl<'a> Foo<'a> {
+   |      -- first declared here
+LL |     fn f<'a>(x: &'a i32) {
+   |          ^^ lifetime 'a already in scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0496`.
diff --git a/src/test/ui/error-codes/E0499.nll.stderr b/src/test/ui/error-codes/E0499.nll.stderr
new file mode 100644
index 0000000..d56baf7
--- /dev/null
+++ b/src/test/ui/error-codes/E0499.nll.stderr
@@ -0,0 +1,14 @@
+error[E0499]: cannot borrow `i` as mutable more than once at a time
+  --> $DIR/E0499.rs:4:17
+   |
+LL |     let mut x = &mut i;
+   |                 ------ first mutable borrow occurs here
+LL |     let mut a = &mut i;
+   |                 ^^^^^^ second mutable borrow occurs here
+LL |     a.use_mut();
+LL |     x.use_mut();
+   |     - first borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/error-codes/E0499.rs b/src/test/ui/error-codes/E0499.rs
new file mode 100644
index 0000000..919f97c
--- /dev/null
+++ b/src/test/ui/error-codes/E0499.rs
@@ -0,0 +1,10 @@
+fn main() {
+    let mut i = 0;
+    let mut x = &mut i;
+    let mut a = &mut i; //~ ERROR E0499
+    a.use_mut();
+    x.use_mut();
+}
+
+trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { }  }
+impl<T> Fake for T { }
diff --git a/src/test/ui/error-codes/E0499.stderr b/src/test/ui/error-codes/E0499.stderr
new file mode 100644
index 0000000..8227016
--- /dev/null
+++ b/src/test/ui/error-codes/E0499.stderr
@@ -0,0 +1,14 @@
+error[E0499]: cannot borrow `i` as mutable more than once at a time
+  --> $DIR/E0499.rs:4:22
+   |
+LL |     let mut x = &mut i;
+   |                      - first mutable borrow occurs here
+LL |     let mut a = &mut i;
+   |                      ^ second mutable borrow occurs here
+...
+LL | }
+   | - first borrow ends here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/error-codes/E0502.nll.stderr b/src/test/ui/error-codes/E0502.nll.stderr
new file mode 100644
index 0000000..cade6d7
--- /dev/null
+++ b/src/test/ui/error-codes/E0502.nll.stderr
@@ -0,0 +1,13 @@
+error[E0502]: cannot borrow `*a` as mutable because it is also borrowed as immutable
+  --> $DIR/E0502.rs:4:5
+   |
+LL |     let ref y = a;
+   |         ----- immutable borrow occurs here
+LL |     bar(a);
+   |     ^^^^^^ mutable borrow occurs here
+LL |     y.use_ref();
+   |     - immutable borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/error-codes/E0502.rs b/src/test/ui/error-codes/E0502.rs
new file mode 100644
index 0000000..958380e
--- /dev/null
+++ b/src/test/ui/error-codes/E0502.rs
@@ -0,0 +1,12 @@
+fn bar(x: &mut i32) {}
+fn foo(a: &mut i32) {
+    let ref y = a;
+    bar(a); //~ ERROR E0502
+    y.use_ref();
+}
+
+fn main() {
+}
+
+trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { }  }
+impl<T> Fake for T { }
diff --git a/src/test/ui/error-codes/E0502.stderr b/src/test/ui/error-codes/E0502.stderr
new file mode 100644
index 0000000..26a2c3b
--- /dev/null
+++ b/src/test/ui/error-codes/E0502.stderr
@@ -0,0 +1,14 @@
+error[E0502]: cannot borrow `*a` as mutable because `a` is also borrowed as immutable
+  --> $DIR/E0502.rs:4:9
+   |
+LL |     let ref y = a;
+   |         ----- immutable borrow occurs here
+LL |     bar(a);
+   |         ^ mutable borrow occurs here
+LL |     y.use_ref();
+LL | }
+   | - immutable borrow ends here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/error-codes/E0503.nll.stderr b/src/test/ui/error-codes/E0503.nll.stderr
new file mode 100644
index 0000000..106dda2
--- /dev/null
+++ b/src/test/ui/error-codes/E0503.nll.stderr
@@ -0,0 +1,13 @@
+error[E0503]: cannot use `value` because it was mutably borrowed
+  --> $DIR/E0503.rs:4:16
+   |
+LL |     let _borrow = &mut value;
+   |                   ---------- borrow of `value` occurs here
+LL |     let _sum = value + 1;
+   |                ^^^^^ use of borrowed `value`
+LL |     _borrow.use_mut();
+   |     ------- borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0503`.
diff --git a/src/test/ui/error-codes/E0503.rs b/src/test/ui/error-codes/E0503.rs
new file mode 100644
index 0000000..88f5fc1
--- /dev/null
+++ b/src/test/ui/error-codes/E0503.rs
@@ -0,0 +1,9 @@
+fn main() {
+    let mut value = 3;
+    let _borrow = &mut value;
+    let _sum = value + 1; //~ ERROR E0503
+    _borrow.use_mut();
+}
+
+trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { }  }
+impl<T> Fake for T { }
diff --git a/src/test/ui/error-codes/E0503.stderr b/src/test/ui/error-codes/E0503.stderr
new file mode 100644
index 0000000..62cb3af
--- /dev/null
+++ b/src/test/ui/error-codes/E0503.stderr
@@ -0,0 +1,11 @@
+error[E0503]: cannot use `value` because it was mutably borrowed
+  --> $DIR/E0503.rs:4:16
+   |
+LL |     let _borrow = &mut value;
+   |                        ----- borrow of `value` occurs here
+LL |     let _sum = value + 1;
+   |                ^^^^^ use of borrowed `value`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0503`.
diff --git a/src/test/ui/error-codes/E0504.nll.stderr b/src/test/ui/error-codes/E0504.nll.stderr
new file mode 100644
index 0000000..1f2a040
--- /dev/null
+++ b/src/test/ui/error-codes/E0504.nll.stderr
@@ -0,0 +1,17 @@
+error[E0505]: cannot move out of `fancy_num` because it is borrowed
+  --> $DIR/E0504.rs:9:13
+   |
+LL |     let fancy_ref = &fancy_num;
+   |                     ---------- borrow of `fancy_num` occurs here
+LL | 
+LL |     let x = move || {
+   |             ^^^^^^^ move out of `fancy_num` occurs here
+LL |         println!("child function: {}", fancy_num.num);
+   |                                        --------- move occurs due to use in closure
+...
+LL |     println!("main function: {}", fancy_ref.num);
+   |                                   ------------- borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0505`.
diff --git a/src/test/ui/error-codes/E0504.rs b/src/test/ui/error-codes/E0504.rs
new file mode 100644
index 0000000..06ae084
--- /dev/null
+++ b/src/test/ui/error-codes/E0504.rs
@@ -0,0 +1,15 @@
+struct FancyNum {
+    num: u8,
+}
+
+fn main() {
+    let fancy_num = FancyNum { num: 5 };
+    let fancy_ref = &fancy_num;
+
+    let x = move || {
+        println!("child function: {}", fancy_num.num); //~ ERROR E0504
+    };
+
+    x();
+    println!("main function: {}", fancy_ref.num);
+}
diff --git a/src/test/ui/error-codes/E0504.stderr b/src/test/ui/error-codes/E0504.stderr
new file mode 100644
index 0000000..a987713
--- /dev/null
+++ b/src/test/ui/error-codes/E0504.stderr
@@ -0,0 +1,12 @@
+error[E0504]: cannot move `fancy_num` into closure because it is borrowed
+  --> $DIR/E0504.rs:10:40
+   |
+LL |     let fancy_ref = &fancy_num;
+   |                      --------- borrow of `fancy_num` occurs here
+...
+LL |         println!("child function: {}", fancy_num.num);
+   |                                        ^^^^^^^^^ move into closure occurs here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0504`.
diff --git a/src/test/ui/error-codes/E0505.nll.stderr b/src/test/ui/error-codes/E0505.nll.stderr
new file mode 100644
index 0000000..4d9d1ef
--- /dev/null
+++ b/src/test/ui/error-codes/E0505.nll.stderr
@@ -0,0 +1,13 @@
+error[E0505]: cannot move out of `x` because it is borrowed
+  --> $DIR/E0505.rs:9:13
+   |
+LL |         let _ref_to_val: &Value = &x;
+   |                                   -- borrow of `x` occurs here
+LL |         eat(x);
+   |             ^ move out of `x` occurs here
+LL |         _ref_to_val.use_ref();
+   |         ----------- borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0505`.
diff --git a/src/test/ui/error-codes/E0505.rs b/src/test/ui/error-codes/E0505.rs
new file mode 100644
index 0000000..941f5f2
--- /dev/null
+++ b/src/test/ui/error-codes/E0505.rs
@@ -0,0 +1,15 @@
+struct Value {}
+
+fn eat(val: Value) {}
+
+fn main() {
+    let x = Value{};
+    {
+        let _ref_to_val: &Value = &x;
+        eat(x); //~ ERROR E0505
+        _ref_to_val.use_ref();
+    }
+}
+
+trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { }  }
+impl<T> Fake for T { }
diff --git a/src/test/ui/error-codes/E0505.stderr b/src/test/ui/error-codes/E0505.stderr
new file mode 100644
index 0000000..28dfb25
--- /dev/null
+++ b/src/test/ui/error-codes/E0505.stderr
@@ -0,0 +1,11 @@
+error[E0505]: cannot move out of `x` because it is borrowed
+  --> $DIR/E0505.rs:9:13
+   |
+LL |         let _ref_to_val: &Value = &x;
+   |                                    - borrow of `x` occurs here
+LL |         eat(x);
+   |             ^ move out of `x` occurs here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0505`.
diff --git a/src/test/ui/error-codes/E0507.rs b/src/test/ui/error-codes/E0507.rs
new file mode 100644
index 0000000..bae90a4
--- /dev/null
+++ b/src/test/ui/error-codes/E0507.rs
@@ -0,0 +1,13 @@
+use std::cell::RefCell;
+
+struct TheDarkKnight;
+
+impl TheDarkKnight {
+    fn nothing_is_true(self) {}
+}
+
+fn main() {
+    let x = RefCell::new(TheDarkKnight);
+
+    x.borrow().nothing_is_true(); //~ ERROR E0507
+}
diff --git a/src/test/ui/error-codes/E0507.stderr b/src/test/ui/error-codes/E0507.stderr
new file mode 100644
index 0000000..1a596af
--- /dev/null
+++ b/src/test/ui/error-codes/E0507.stderr
@@ -0,0 +1,9 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/E0507.rs:12:5
+   |
+LL |     x.borrow().nothing_is_true();
+   |     ^^^^^^^^^^ cannot move out of borrowed content
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/error-codes/E0509.nll.stderr b/src/test/ui/error-codes/E0509.nll.stderr
new file mode 100644
index 0000000..e5c0cf6
--- /dev/null
+++ b/src/test/ui/error-codes/E0509.nll.stderr
@@ -0,0 +1,12 @@
+error[E0509]: cannot move out of type `DropStruct`, which implements the `Drop` trait
+  --> $DIR/E0509.rs:16:23
+   |
+LL |     let fancy_field = drop_struct.fancy;
+   |                       ^^^^^^^^^^^^^^^^^
+   |                       |
+   |                       cannot move out of here
+   |                       help: consider borrowing here: `&drop_struct.fancy`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0509`.
diff --git a/src/test/ui/error-codes/E0509.rs b/src/test/ui/error-codes/E0509.rs
new file mode 100644
index 0000000..b2665c4
--- /dev/null
+++ b/src/test/ui/error-codes/E0509.rs
@@ -0,0 +1,18 @@
+struct FancyNum {
+    num: usize
+}
+
+struct DropStruct {
+    fancy: FancyNum
+}
+
+impl Drop for DropStruct {
+    fn drop(&mut self) {
+    }
+}
+
+fn main() {
+    let drop_struct = DropStruct{fancy: FancyNum{num: 5}};
+    let fancy_field = drop_struct.fancy; //~ ERROR E0509
+    println!("Fancy: {}", fancy_field.num);
+}
diff --git a/src/test/ui/error-codes/E0509.stderr b/src/test/ui/error-codes/E0509.stderr
new file mode 100644
index 0000000..25b6d8a
--- /dev/null
+++ b/src/test/ui/error-codes/E0509.stderr
@@ -0,0 +1,12 @@
+error[E0509]: cannot move out of type `DropStruct`, which implements the `Drop` trait
+  --> $DIR/E0509.rs:16:23
+   |
+LL |     let fancy_field = drop_struct.fancy;
+   |                       ^^^^^^^^^^^^^^^^^
+   |                       |
+   |                       cannot move out of here
+   |                       help: consider using a reference instead: `&drop_struct.fancy`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0509`.
diff --git a/src/test/ui/error-codes/E0511.rs b/src/test/ui/error-codes/E0511.rs
new file mode 100644
index 0000000..3590f12
--- /dev/null
+++ b/src/test/ui/error-codes/E0511.rs
@@ -0,0 +1,9 @@
+#![feature(platform_intrinsics)]
+
+extern "platform-intrinsic" {
+    fn simd_add<T>(a: T, b: T) -> T;
+}
+
+fn main() {
+    unsafe { simd_add(0, 1); } //~ ERROR E0511
+}
diff --git a/src/test/ui/error-codes/E0511.stderr b/src/test/ui/error-codes/E0511.stderr
new file mode 100644
index 0000000..1362a3d
--- /dev/null
+++ b/src/test/ui/error-codes/E0511.stderr
@@ -0,0 +1,9 @@
+error[E0511]: invalid monomorphization of `simd_add` intrinsic: expected SIMD input type, found non-SIMD `i32`
+  --> $DIR/E0511.rs:8:14
+   |
+LL |     unsafe { simd_add(0, 1); }
+   |              ^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0511`.
diff --git a/src/test/ui/error-codes/E0512.rs b/src/test/ui/error-codes/E0512.rs
new file mode 100644
index 0000000..e70992a
--- /dev/null
+++ b/src/test/ui/error-codes/E0512.rs
@@ -0,0 +1,5 @@
+fn takes_u8(_: u8) {}
+
+fn main() {
+    unsafe { takes_u8(::std::mem::transmute(0u16)); } //~ ERROR E0512
+}
diff --git a/src/test/ui/error-codes/E0512.stderr b/src/test/ui/error-codes/E0512.stderr
new file mode 100644
index 0000000..3fecce5
--- /dev/null
+++ b/src/test/ui/error-codes/E0512.stderr
@@ -0,0 +1,12 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/E0512.rs:4:23
+   |
+LL |     unsafe { takes_u8(::std::mem::transmute(0u16)); }
+   |                       ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: source type: `u16` (16 bits)
+   = note: target type: `u8` (8 bits)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0512`.
diff --git a/src/test/ui/error-codes/E0516.rs b/src/test/ui/error-codes/E0516.rs
new file mode 100644
index 0000000..834bb63
--- /dev/null
+++ b/src/test/ui/error-codes/E0516.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let x: typeof(92) = 92; //~ ERROR E0516
+                            //~| reserved keyword
+}
diff --git a/src/test/ui/error-codes/E0516.stderr b/src/test/ui/error-codes/E0516.stderr
new file mode 100644
index 0000000..2e6de50
--- /dev/null
+++ b/src/test/ui/error-codes/E0516.stderr
@@ -0,0 +1,9 @@
+error[E0516]: `typeof` is a reserved keyword but unimplemented
+  --> $DIR/E0516.rs:2:12
+   |
+LL |     let x: typeof(92) = 92;
+   |            ^^^^^^^^^^ reserved keyword
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0516`.
diff --git a/src/test/ui/error-codes/E0517.rs b/src/test/ui/error-codes/E0517.rs
new file mode 100644
index 0000000..1dcaa2d
--- /dev/null
+++ b/src/test/ui/error-codes/E0517.rs
@@ -0,0 +1,15 @@
+#[repr(C)] //~ ERROR: E0517
+type Foo = u8;
+
+#[repr(packed)] //~ ERROR: E0517
+enum Foo2 {Bar, Baz}
+
+#[repr(u8)] //~ ERROR: E0517
+struct Foo3 {bar: bool, baz: bool}
+
+#[repr(C)] //~ ERROR: E0517
+impl Foo3 {
+}
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0517.stderr b/src/test/ui/error-codes/E0517.stderr
new file mode 100644
index 0000000..e256c07
--- /dev/null
+++ b/src/test/ui/error-codes/E0517.stderr
@@ -0,0 +1,36 @@
+error[E0517]: attribute should be applied to struct, enum or union
+  --> $DIR/E0517.rs:1:8
+   |
+LL | #[repr(C)]
+   |        ^
+LL | type Foo = u8;
+   | -------------- not a struct, enum or union
+
+error[E0517]: attribute should be applied to struct or union
+  --> $DIR/E0517.rs:4:8
+   |
+LL | #[repr(packed)]
+   |        ^^^^^^
+LL | enum Foo2 {Bar, Baz}
+   | -------------------- not a struct or union
+
+error[E0517]: attribute should be applied to enum
+  --> $DIR/E0517.rs:7:8
+   |
+LL | #[repr(u8)]
+   |        ^^
+LL | struct Foo3 {bar: bool, baz: bool}
+   | ---------------------------------- not an enum
+
+error[E0517]: attribute should be applied to struct, enum or union
+  --> $DIR/E0517.rs:10:8
+   |
+LL |   #[repr(C)]
+   |          ^
+LL | / impl Foo3 {
+LL | | }
+   | |_- not a struct, enum or union
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0517`.
diff --git a/src/test/ui/error-codes/E0518.rs b/src/test/ui/error-codes/E0518.rs
new file mode 100644
index 0000000..9c99702
--- /dev/null
+++ b/src/test/ui/error-codes/E0518.rs
@@ -0,0 +1,9 @@
+#[inline(always)] //~ ERROR: E0518
+struct Foo;
+
+#[inline(never)] //~ ERROR: E0518
+impl Foo {
+}
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0518.stderr b/src/test/ui/error-codes/E0518.stderr
new file mode 100644
index 0000000..561446f
--- /dev/null
+++ b/src/test/ui/error-codes/E0518.stderr
@@ -0,0 +1,20 @@
+error[E0518]: attribute should be applied to function or closure
+  --> $DIR/E0518.rs:1:1
+   |
+LL | #[inline(always)]
+   | ^^^^^^^^^^^^^^^^^
+LL | struct Foo;
+   | ----------- not a function or closure
+
+error[E0518]: attribute should be applied to function or closure
+  --> $DIR/E0518.rs:4:1
+   |
+LL |   #[inline(never)]
+   |   ^^^^^^^^^^^^^^^^
+LL | / impl Foo {
+LL | | }
+   | |_- not a function or closure
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0518`.
diff --git a/src/test/ui/error-codes/E0520.rs b/src/test/ui/error-codes/E0520.rs
new file mode 100644
index 0000000..b746ca6
--- /dev/null
+++ b/src/test/ui/error-codes/E0520.rs
@@ -0,0 +1,21 @@
+#![feature(specialization)]
+
+trait SpaceLlama {
+    fn fly(&self);
+}
+
+impl<T> SpaceLlama for T {
+    default fn fly(&self) {}
+}
+
+impl<T: Clone> SpaceLlama for T {
+    fn fly(&self) {}
+}
+
+impl SpaceLlama for i32 {
+    default fn fly(&self) {}
+    //~^ ERROR E0520
+}
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0520.stderr b/src/test/ui/error-codes/E0520.stderr
new file mode 100644
index 0000000..72fc85a
--- /dev/null
+++ b/src/test/ui/error-codes/E0520.stderr
@@ -0,0 +1,16 @@
+error[E0520]: `fly` specializes an item from a parent `impl`, but that item is not marked `default`
+  --> $DIR/E0520.rs:16:5
+   |
+LL | / impl<T: Clone> SpaceLlama for T {
+LL | |     fn fly(&self) {}
+LL | | }
+   | |_- parent `impl` is here
+...
+LL |       default fn fly(&self) {}
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `fly`
+   |
+   = note: to specialize, `fly` in the parent `impl` must be marked `default`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0520`.
diff --git a/src/test/ui/error-codes/E0522.rs b/src/test/ui/error-codes/E0522.rs
new file mode 100644
index 0000000..1414e82
--- /dev/null
+++ b/src/test/ui/error-codes/E0522.rs
@@ -0,0 +1,9 @@
+#![feature(lang_items)]
+
+#[lang = "cookie"]
+fn cookie() -> ! {
+//~^^ ERROR definition of an unknown language item: `cookie` [E0522]
+    loop {}
+}
+
+fn main() {}
diff --git a/src/test/ui/error-codes/E0522.stderr b/src/test/ui/error-codes/E0522.stderr
new file mode 100644
index 0000000..0a8a415
--- /dev/null
+++ b/src/test/ui/error-codes/E0522.stderr
@@ -0,0 +1,9 @@
+error[E0522]: definition of an unknown language item: `cookie`
+  --> $DIR/E0522.rs:3:1
+   |
+LL | #[lang = "cookie"]
+   | ^^^^^^^^^^^^^^^^^^ definition of unknown language item `cookie`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0522`.
diff --git a/src/test/ui/error-codes/E0527.rs b/src/test/ui/error-codes/E0527.rs
new file mode 100644
index 0000000..af055ff
--- /dev/null
+++ b/src/test/ui/error-codes/E0527.rs
@@ -0,0 +1,9 @@
+fn main() {
+    let r = &[1, 2, 3, 4];
+    match r {
+        &[a, b] => {
+            //~^ ERROR E0527
+            println!("a={}, b={}", a, b);
+        }
+    }
+}
diff --git a/src/test/ui/error-codes/E0527.stderr b/src/test/ui/error-codes/E0527.stderr
new file mode 100644
index 0000000..a2e6288
--- /dev/null
+++ b/src/test/ui/error-codes/E0527.stderr
@@ -0,0 +1,9 @@
+error[E0527]: pattern requires 2 elements but array has 4
+  --> $DIR/E0527.rs:4:10
+   |
+LL |         &[a, b] => {
+   |          ^^^^^^ expected 4 elements
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0527`.
diff --git a/src/test/ui/error-codes/E0528.rs b/src/test/ui/error-codes/E0528.rs
new file mode 100644
index 0000000..f2681fa
--- /dev/null
+++ b/src/test/ui/error-codes/E0528.rs
@@ -0,0 +1,10 @@
+#![feature(slice_patterns)]
+
+fn main() {
+    let r = &[1, 2];
+    match r {
+        &[a, b, c, rest..] => {
+        //~^ ERROR E0528
+        }
+    }
+}
diff --git a/src/test/ui/error-codes/E0528.stderr b/src/test/ui/error-codes/E0528.stderr
new file mode 100644
index 0000000..a7205af
--- /dev/null
+++ b/src/test/ui/error-codes/E0528.stderr
@@ -0,0 +1,9 @@
+error[E0528]: pattern requires at least 3 elements but array has 2
+  --> $DIR/E0528.rs:6:10
+   |
+LL |         &[a, b, c, rest..] => {
+   |          ^^^^^^^^^^^^^^^^^ pattern cannot match array of 2 elements
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0528`.
diff --git a/src/test/ui/error-codes/E0529.rs b/src/test/ui/error-codes/E0529.rs
new file mode 100644
index 0000000..a82bc9e
--- /dev/null
+++ b/src/test/ui/error-codes/E0529.rs
@@ -0,0 +1,8 @@
+fn main() {
+    let r: f32 = 1.0;
+    match r {
+        [a, b] => {
+        //~^ ERROR E0529
+        }
+    }
+}
diff --git a/src/test/ui/error-codes/E0529.stderr b/src/test/ui/error-codes/E0529.stderr
new file mode 100644
index 0000000..96b22bb
--- /dev/null
+++ b/src/test/ui/error-codes/E0529.stderr
@@ -0,0 +1,9 @@
+error[E0529]: expected an array or slice, found `f32`
+  --> $DIR/E0529.rs:4:9
+   |
+LL |         [a, b] => {
+   |         ^^^^^^ pattern cannot match with input type `f32`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0529`.
diff --git a/src/test/ui/error-codes/E0530.rs b/src/test/ui/error-codes/E0530.rs
new file mode 100644
index 0000000..5bc4096
--- /dev/null
+++ b/src/test/ui/error-codes/E0530.rs
@@ -0,0 +1,8 @@
+fn main() {
+    static TEST: i32 = 0;
+
+    let r: (i32, i32) = (0, 0);
+    match r {
+        TEST => {} //~ ERROR E0530
+    }
+}
diff --git a/src/test/ui/error-codes/E0530.stderr b/src/test/ui/error-codes/E0530.stderr
new file mode 100644
index 0000000..c312144
--- /dev/null
+++ b/src/test/ui/error-codes/E0530.stderr
@@ -0,0 +1,12 @@
+error[E0530]: match bindings cannot shadow statics
+  --> $DIR/E0530.rs:6:9
+   |
+LL |     static TEST: i32 = 0;
+   |     --------------------- the static `TEST` is defined here
+...
+LL |         TEST => {}
+   |         ^^^^ cannot be named the same as a static
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0530`.
diff --git a/src/test/ui/error-codes/E0532.rs b/src/test/ui/error-codes/E0532.rs
new file mode 100644
index 0000000..931ca46
--- /dev/null
+++ b/src/test/ui/error-codes/E0532.rs
@@ -0,0 +1,14 @@
+fn main() {
+    let value = 1;
+
+    match SomeStruct(value) {
+        StructConst1(_) => { },
+        //~^ ERROR expected tuple struct/variant, found constant `StructConst1`
+        _ => { },
+    }
+
+    struct SomeStruct(u8);
+
+    const StructConst1 : SomeStruct = SomeStruct(1);
+    const StructConst2 : SomeStruct = SomeStruct(2);
+}
diff --git a/src/test/ui/error-codes/E0532.stderr b/src/test/ui/error-codes/E0532.stderr
new file mode 100644
index 0000000..887ede0
--- /dev/null
+++ b/src/test/ui/error-codes/E0532.stderr
@@ -0,0 +1,9 @@
+error[E0532]: expected tuple struct/variant, found constant `StructConst1`
+  --> $DIR/E0532.rs:5:9
+   |
+LL |         StructConst1(_) => { },
+   |         ^^^^^^^^^^^^ not a tuple struct/variant
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0532`.
diff --git a/src/test/ui/error-codes/E0534.rs b/src/test/ui/error-codes/E0534.rs
new file mode 100644
index 0000000..a424249
--- /dev/null
+++ b/src/test/ui/error-codes/E0534.rs
@@ -0,0 +1,6 @@
+#[inline()] //~ ERROR E0534
+pub fn something() {}
+
+fn main() {
+    something();
+}
diff --git a/src/test/ui/error-codes/E0534.stderr b/src/test/ui/error-codes/E0534.stderr
new file mode 100644
index 0000000..23f9cd7
--- /dev/null
+++ b/src/test/ui/error-codes/E0534.stderr
@@ -0,0 +1,9 @@
+error[E0534]: expected one argument
+  --> $DIR/E0534.rs:1:1
+   |
+LL | #[inline()]
+   | ^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0534`.
diff --git a/src/test/ui/error-codes/E0559.rs b/src/test/ui/error-codes/E0559.rs
new file mode 100644
index 0000000..c6d04ff
--- /dev/null
+++ b/src/test/ui/error-codes/E0559.rs
@@ -0,0 +1,8 @@
+enum Field {
+    Fool { x: u32 },
+}
+
+fn main() {
+    let s = Field::Fool { joke: 0 };
+    //~^ ERROR E0559
+}
diff --git a/src/test/ui/error-codes/E0559.stderr b/src/test/ui/error-codes/E0559.stderr
new file mode 100644
index 0000000..63ee1cd7
--- /dev/null
+++ b/src/test/ui/error-codes/E0559.stderr
@@ -0,0 +1,11 @@
+error[E0559]: variant `Field::Fool` has no field named `joke`
+  --> $DIR/E0559.rs:6:27
+   |
+LL |     let s = Field::Fool { joke: 0 };
+   |                           ^^^^ `Field::Fool` does not have this field
+   |
+   = note: available fields are: `x`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0559`.
diff --git a/src/test/ui/error-codes/E0560.rs b/src/test/ui/error-codes/E0560.rs
new file mode 100644
index 0000000..1d60f89
--- /dev/null
+++ b/src/test/ui/error-codes/E0560.rs
@@ -0,0 +1,8 @@
+struct Simba {
+    mother: u32,
+}
+
+fn main() {
+    let s = Simba { mother: 1, father: 0 };
+    //~^ ERROR E0560
+}
diff --git a/src/test/ui/error-codes/E0560.stderr b/src/test/ui/error-codes/E0560.stderr
new file mode 100644
index 0000000..6b634f1
--- /dev/null
+++ b/src/test/ui/error-codes/E0560.stderr
@@ -0,0 +1,11 @@
+error[E0560]: struct `Simba` has no field named `father`
+  --> $DIR/E0560.rs:6:32
+   |
+LL |     let s = Simba { mother: 1, father: 0 };
+   |                                ^^^^^^ `Simba` does not have this field
+   |
+   = note: available fields are: `mother`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0560`.
diff --git a/src/test/ui/error-codes/E0565-1.rs b/src/test/ui/error-codes/E0565-1.rs
new file mode 100644
index 0000000..30fba01
--- /dev/null
+++ b/src/test/ui/error-codes/E0565-1.rs
@@ -0,0 +1,5 @@
+// deprecated doesn't currently support literals
+#[deprecated("since")] //~ ERROR E0565
+fn f() {  }
+
+fn main() {  }
diff --git a/src/test/ui/error-codes/E0565-1.stderr b/src/test/ui/error-codes/E0565-1.stderr
new file mode 100644
index 0000000..1283a9c
--- /dev/null
+++ b/src/test/ui/error-codes/E0565-1.stderr
@@ -0,0 +1,9 @@
+error[E0565]: item in `deprecated` must be a key/value pair
+  --> $DIR/E0565-1.rs:2:14
+   |
+LL | #[deprecated("since")]
+   |              ^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0565`.
diff --git a/src/test/ui/error-codes/E0565-2.rs b/src/test/ui/error-codes/E0565-2.rs
new file mode 100644
index 0000000..0319ecb
--- /dev/null
+++ b/src/test/ui/error-codes/E0565-2.rs
@@ -0,0 +1,5 @@
+// repr currently doesn't support literals
+#[deprecated(since = b"1.29", note = "hi")] //~ ERROR E0565
+struct A {  }
+
+fn main() {  }
diff --git a/src/test/ui/error-codes/E0565-2.stderr b/src/test/ui/error-codes/E0565-2.stderr
new file mode 100644
index 0000000..bb30bd7
--- /dev/null
+++ b/src/test/ui/error-codes/E0565-2.stderr
@@ -0,0 +1,9 @@
+error[E0565]: literal in `deprecated` value must be a string
+  --> $DIR/E0565-2.rs:2:22
+   |
+LL | #[deprecated(since = b"1.29", note = "hi")]
+   |                      ^^^^^^^ help: consider removing the prefix: `"1.29"`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0565`.
diff --git a/src/test/ui/error-codes/E0565.rs b/src/test/ui/error-codes/E0565.rs
new file mode 100644
index 0000000..b09f5df
--- /dev/null
+++ b/src/test/ui/error-codes/E0565.rs
@@ -0,0 +1,5 @@
+// repr currently doesn't support literals
+#[repr("C")] //~ ERROR E0565
+struct A {  }
+
+fn main() {  }
diff --git a/src/test/ui/error-codes/E0565.stderr b/src/test/ui/error-codes/E0565.stderr
new file mode 100644
index 0000000..6ed90c0
--- /dev/null
+++ b/src/test/ui/error-codes/E0565.stderr
@@ -0,0 +1,9 @@
+error[E0565]: meta item in `repr` must be an identifier
+  --> $DIR/E0565.rs:2:8
+   |
+LL | #[repr("C")]
+   |        ^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0565`.
diff --git a/src/test/ui/error-codes/E0572.rs b/src/test/ui/error-codes/E0572.rs
new file mode 100644
index 0000000..cb842c9
--- /dev/null
+++ b/src/test/ui/error-codes/E0572.rs
@@ -0,0 +1,3 @@
+const FOO: u32 = return 0; //~ ERROR E0572
+
+fn main() {}
diff --git a/src/test/ui/error-codes/E0572.stderr b/src/test/ui/error-codes/E0572.stderr
new file mode 100644
index 0000000..36619f8
--- /dev/null
+++ b/src/test/ui/error-codes/E0572.stderr
@@ -0,0 +1,9 @@
+error[E0572]: return statement outside of function body
+  --> $DIR/E0572.rs:1:18
+   |
+LL | const FOO: u32 = return 0;
+   |                  ^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0572`.
diff --git a/src/test/ui/error-codes/E0582.rs b/src/test/ui/error-codes/E0582.rs
new file mode 100644
index 0000000..ff25012
--- /dev/null
+++ b/src/test/ui/error-codes/E0582.rs
@@ -0,0 +1,42 @@
+// This test was derived from the wasm and parsell crates.  They
+// stopped compiling when #32330 is fixed.
+
+#![allow(dead_code, unused_variables)]
+
+use std::str::Chars;
+
+pub trait HasOutput<Ch, Str> {
+    type Output;
+}
+
+#[derive(Clone, PartialEq, Eq, Hash, Ord, PartialOrd, Debug)]
+pub enum Token<'a> {
+    Begin(&'a str)
+}
+
+fn mk_unexpected_char_err<'a>() -> Option<&'a i32> {
+    unimplemented!()
+}
+
+fn foo<'a>(data: &mut Chars<'a>) {
+    bar(mk_unexpected_char_err)
+}
+
+fn bar<F>(t: F)
+    // No type can satisfy this requirement, since `'a` does not
+    // appear in any of the input types:
+    where F: for<'a> Fn() -> Option<&'a i32>
+    //~^ ERROR E0582
+{
+}
+
+fn baz<F>(t: F)
+    // No type can satisfy this requirement, since `'a` does not
+    // appear in any of the input types:
+    where F: for<'a> Iterator<Item=&'a i32>
+    //~^ ERROR E0582
+{
+}
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0582.stderr b/src/test/ui/error-codes/E0582.stderr
new file mode 100644
index 0000000..81a2f00
--- /dev/null
+++ b/src/test/ui/error-codes/E0582.stderr
@@ -0,0 +1,15 @@
+error[E0582]: binding for associated type `Output` references lifetime `'a`, which does not appear in the trait input types
+  --> $DIR/E0582.rs:28:30
+   |
+LL |     where F: for<'a> Fn() -> Option<&'a i32>
+   |                              ^^^^^^^^^^^^^^^
+
+error[E0582]: binding for associated type `Item` references lifetime `'a`, which does not appear in the trait input types
+  --> $DIR/E0582.rs:36:31
+   |
+LL |     where F: for<'a> Iterator<Item=&'a i32>
+   |                               ^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0582`.
diff --git a/src/test/ui/error-codes/E0585.rs b/src/test/ui/error-codes/E0585.rs
new file mode 100644
index 0000000..890b77b
--- /dev/null
+++ b/src/test/ui/error-codes/E0585.rs
@@ -0,0 +1,4 @@
+fn main() {
+    /// Hello! I'm useless...
+    //~^ ERROR E0585
+}
diff --git a/src/test/ui/error-codes/E0585.stderr b/src/test/ui/error-codes/E0585.stderr
new file mode 100644
index 0000000..7a31c48
--- /dev/null
+++ b/src/test/ui/error-codes/E0585.stderr
@@ -0,0 +1,11 @@
+error[E0585]: found a documentation comment that doesn't document anything
+  --> $DIR/E0585.rs:2:5
+   |
+LL |     /// Hello! I'm useless...
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: doc comments must come before what they document, maybe a comment was intended with `//`?
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0585`.
diff --git a/src/test/ui/error-codes/E0586.rs b/src/test/ui/error-codes/E0586.rs
new file mode 100644
index 0000000..2ab8a29
--- /dev/null
+++ b/src/test/ui/error-codes/E0586.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let tmp = vec![0, 1, 2, 3, 4, 4, 3, 3, 2, 1];
+    let x = &tmp[1..=]; //~ ERROR E0586
+}
diff --git a/src/test/ui/error-codes/E0586.stderr b/src/test/ui/error-codes/E0586.stderr
new file mode 100644
index 0000000..d1e7e3f
--- /dev/null
+++ b/src/test/ui/error-codes/E0586.stderr
@@ -0,0 +1,11 @@
+error[E0586]: inclusive range with no end
+  --> $DIR/E0586.rs:3:22
+   |
+LL |     let x = &tmp[1..=];
+   |                      ^
+   |
+   = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0586`.
diff --git a/src/test/ui/error-codes/E0597.nll.stderr b/src/test/ui/error-codes/E0597.nll.stderr
new file mode 100644
index 0000000..b4a1180
--- /dev/null
+++ b/src/test/ui/error-codes/E0597.nll.stderr
@@ -0,0 +1,17 @@
+error[E0597]: `y` does not live long enough
+  --> $DIR/E0597.rs:8:16
+   |
+LL |     x.x = Some(&y);
+   |                ^^ borrowed value does not live long enough
+LL |
+LL | }
+   | -
+   | |
+   | `y` dropped here while still borrowed
+   | borrow might be used here, when `x` is dropped and runs the `Drop` code for type `Foo`
+   |
+   = note: values in a scope are dropped in the opposite order they are defined
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/error-codes/E0597.rs b/src/test/ui/error-codes/E0597.rs
new file mode 100644
index 0000000..7217e35
--- /dev/null
+++ b/src/test/ui/error-codes/E0597.rs
@@ -0,0 +1,12 @@
+struct Foo<'a> {
+    x: Option<&'a u32>,
+}
+
+fn main() {
+    let mut x = Foo { x: None };
+    let y = 0;
+    x.x = Some(&y);
+    //~^ `y` does not live long enough [E0597]
+}
+
+impl<'a> Drop for Foo<'a> { fn drop(&mut self) { } }
diff --git a/src/test/ui/error-codes/E0597.stderr b/src/test/ui/error-codes/E0597.stderr
new file mode 100644
index 0000000..cab9785
--- /dev/null
+++ b/src/test/ui/error-codes/E0597.stderr
@@ -0,0 +1,14 @@
+error[E0597]: `y` does not live long enough
+  --> $DIR/E0597.rs:8:17
+   |
+LL |     x.x = Some(&y);
+   |                 ^ borrowed value does not live long enough
+LL |
+LL | }
+   | - `y` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/error-codes/E0599.rs b/src/test/ui/error-codes/E0599.rs
new file mode 100644
index 0000000..a2d7bb2
--- /dev/null
+++ b/src/test/ui/error-codes/E0599.rs
@@ -0,0 +1,5 @@
+struct Foo;
+
+fn main() {
+    || if let Foo::NotEvenReal() = Foo {}; //~ ERROR E0599
+}
diff --git a/src/test/ui/error-codes/E0599.stderr b/src/test/ui/error-codes/E0599.stderr
new file mode 100644
index 0000000..89bfccf
--- /dev/null
+++ b/src/test/ui/error-codes/E0599.stderr
@@ -0,0 +1,12 @@
+error[E0599]: no associated item named `NotEvenReal` found for type `Foo` in the current scope
+  --> $DIR/E0599.rs:4:20
+   |
+LL | struct Foo;
+   | ----------- associated item `NotEvenReal` not found for this
+...
+LL |     || if let Foo::NotEvenReal() = Foo {};
+   |                    ^^^^^^^^^^^ associated item not found in `Foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/error-codes/E0600.rs b/src/test/ui/error-codes/E0600.rs
new file mode 100644
index 0000000..7731d86
--- /dev/null
+++ b/src/test/ui/error-codes/E0600.rs
@@ -0,0 +1,3 @@
+fn main() {
+    !"a"; //~ ERROR E0600
+}
diff --git a/src/test/ui/error-codes/E0600.stderr b/src/test/ui/error-codes/E0600.stderr
new file mode 100644
index 0000000..95ac451
--- /dev/null
+++ b/src/test/ui/error-codes/E0600.stderr
@@ -0,0 +1,9 @@
+error[E0600]: cannot apply unary operator `!` to type `&'static str`
+  --> $DIR/E0600.rs:2:5
+   |
+LL |     !"a";
+   |     ^^^^ cannot apply unary operator `!`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0600`.
diff --git a/src/test/ui/error-codes/E0601.rs b/src/test/ui/error-codes/E0601.rs
new file mode 100644
index 0000000..47feb7f
--- /dev/null
+++ b/src/test/ui/error-codes/E0601.rs
@@ -0,0 +1 @@
+// Test for main function not found.
diff --git a/src/test/ui/error-codes/E0601.stderr b/src/test/ui/error-codes/E0601.stderr
new file mode 100644
index 0000000..cbc20db
--- /dev/null
+++ b/src/test/ui/error-codes/E0601.stderr
@@ -0,0 +1,7 @@
+error[E0601]: `main` function not found in crate `E0601`
+   |
+   = note: consider adding a `main` function to `$DIR/E0601.rs`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0601`.
diff --git a/src/test/ui/error-codes/E0602.rs b/src/test/ui/error-codes/E0602.rs
new file mode 100644
index 0000000..8fadce5
--- /dev/null
+++ b/src/test/ui/error-codes/E0602.rs
@@ -0,0 +1,6 @@
+// compile-flags:-D bogus
+
+// error-pattern:E0602
+// error-pattern:requested on the command line with `-D bogus`
+
+fn main() {}
diff --git a/src/test/ui/error-codes/E0602.stderr b/src/test/ui/error-codes/E0602.stderr
new file mode 100644
index 0000000..8636004
--- /dev/null
+++ b/src/test/ui/error-codes/E0602.stderr
@@ -0,0 +1,7 @@
+error[E0602]: unknown lint: `bogus`
+   |
+   = note: requested on the command line with `-D bogus`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0602`.
diff --git a/src/test/ui/error-codes/E0603.rs b/src/test/ui/error-codes/E0603.rs
new file mode 100644
index 0000000..24a9ba8
--- /dev/null
+++ b/src/test/ui/error-codes/E0603.rs
@@ -0,0 +1,7 @@
+mod SomeModule {
+    const PRIVATE: u32 = 0x_a_bad_1dea_u32;
+}
+
+fn main() {
+    SomeModule::PRIVATE; //~ ERROR E0603
+}
diff --git a/src/test/ui/error-codes/E0603.stderr b/src/test/ui/error-codes/E0603.stderr
new file mode 100644
index 0000000..444005e
--- /dev/null
+++ b/src/test/ui/error-codes/E0603.stderr
@@ -0,0 +1,9 @@
+error[E0603]: constant `PRIVATE` is private
+  --> $DIR/E0603.rs:6:17
+   |
+LL |     SomeModule::PRIVATE;
+   |                 ^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0603`.
diff --git a/src/test/ui/error-codes/E0604.rs b/src/test/ui/error-codes/E0604.rs
new file mode 100644
index 0000000..b9c0d1f
--- /dev/null
+++ b/src/test/ui/error-codes/E0604.rs
@@ -0,0 +1,3 @@
+fn main() {
+    1u32 as char; //~ ERROR E0604
+}
diff --git a/src/test/ui/error-codes/E0604.stderr b/src/test/ui/error-codes/E0604.stderr
new file mode 100644
index 0000000..5861bdc
--- /dev/null
+++ b/src/test/ui/error-codes/E0604.stderr
@@ -0,0 +1,9 @@
+error[E0604]: only `u8` can be cast as `char`, not `u32`
+  --> $DIR/E0604.rs:2:5
+   |
+LL |     1u32 as char;
+   |     ^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0604`.
diff --git a/src/test/ui/error-codes/E0605.rs b/src/test/ui/error-codes/E0605.rs
new file mode 100644
index 0000000..0e86e36
--- /dev/null
+++ b/src/test/ui/error-codes/E0605.rs
@@ -0,0 +1,7 @@
+fn main() {
+    let x = 0u8;
+    x as Vec<u8>; //~ ERROR E0605
+
+    let v = 0 as *const u8;
+    v as &u8; //~ ERROR E0605
+}
diff --git a/src/test/ui/error-codes/E0605.stderr b/src/test/ui/error-codes/E0605.stderr
new file mode 100644
index 0000000..95e899d
--- /dev/null
+++ b/src/test/ui/error-codes/E0605.stderr
@@ -0,0 +1,19 @@
+error[E0605]: non-primitive cast: `u8` as `std::vec::Vec<u8>`
+  --> $DIR/E0605.rs:3:5
+   |
+LL |     x as Vec<u8>;
+   |     ^^^^^^^^^^^^
+   |
+   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+
+error[E0605]: non-primitive cast: `*const u8` as `&u8`
+  --> $DIR/E0605.rs:6:5
+   |
+LL |     v as &u8;
+   |     ^^^^^^^^
+   |
+   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0605`.
diff --git a/src/test/ui/error-codes/E0606.rs b/src/test/ui/error-codes/E0606.rs
new file mode 100644
index 0000000..cb0d8cf
--- /dev/null
+++ b/src/test/ui/error-codes/E0606.rs
@@ -0,0 +1,3 @@
+fn main() {
+    &0u8 as u8; //~ ERROR E0606
+}
diff --git a/src/test/ui/error-codes/E0606.stderr b/src/test/ui/error-codes/E0606.stderr
new file mode 100644
index 0000000..fce2488
--- /dev/null
+++ b/src/test/ui/error-codes/E0606.stderr
@@ -0,0 +1,12 @@
+error[E0606]: casting `&u8` as `u8` is invalid
+  --> $DIR/E0606.rs:2:5
+   |
+LL |     &0u8 as u8;
+   |     ----^^^^^^
+   |     |
+   |     cannot cast `&u8` as `u8`
+   |     help: dereference the expression: `*&0u8`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0606`.
diff --git a/src/test/ui/error-codes/E0607.rs b/src/test/ui/error-codes/E0607.rs
new file mode 100644
index 0000000..ad9f870
--- /dev/null
+++ b/src/test/ui/error-codes/E0607.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let v = 0 as *const u8;
+    v as *const [u8]; //~ ERROR E0607
+}
diff --git a/src/test/ui/error-codes/E0607.stderr b/src/test/ui/error-codes/E0607.stderr
new file mode 100644
index 0000000..a0fe02c
--- /dev/null
+++ b/src/test/ui/error-codes/E0607.stderr
@@ -0,0 +1,9 @@
+error[E0607]: cannot cast thin pointer `*const u8` to fat pointer `*const [u8]`
+  --> $DIR/E0607.rs:3:5
+   |
+LL |     v as *const [u8];
+   |     ^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0607`.
diff --git a/src/test/ui/error-codes/E0608.rs b/src/test/ui/error-codes/E0608.rs
new file mode 100644
index 0000000..1e342d6
--- /dev/null
+++ b/src/test/ui/error-codes/E0608.rs
@@ -0,0 +1,3 @@
+fn main() {
+    0u8[2]; //~ ERROR E0608
+}
diff --git a/src/test/ui/error-codes/E0608.stderr b/src/test/ui/error-codes/E0608.stderr
new file mode 100644
index 0000000..3aec509
--- /dev/null
+++ b/src/test/ui/error-codes/E0608.stderr
@@ -0,0 +1,9 @@
+error[E0608]: cannot index into a value of type `u8`
+  --> $DIR/E0608.rs:2:5
+   |
+LL |     0u8[2];
+   |     ^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0608`.
diff --git a/src/test/ui/error-codes/E0609.rs b/src/test/ui/error-codes/E0609.rs
new file mode 100644
index 0000000..e3a97f2
--- /dev/null
+++ b/src/test/ui/error-codes/E0609.rs
@@ -0,0 +1,12 @@
+struct Foo {
+    x: u32,
+}
+struct Bar;
+
+fn main() {
+    let x = Foo { x: 0 };
+    let _ = x.foo; //~ ERROR E0609
+
+    let y = Bar;
+    y.1; //~ ERROR E0609
+}
diff --git a/src/test/ui/error-codes/E0609.stderr b/src/test/ui/error-codes/E0609.stderr
new file mode 100644
index 0000000..797e95d
--- /dev/null
+++ b/src/test/ui/error-codes/E0609.stderr
@@ -0,0 +1,17 @@
+error[E0609]: no field `foo` on type `Foo`
+  --> $DIR/E0609.rs:8:15
+   |
+LL |     let _ = x.foo;
+   |               ^^^ unknown field
+   |
+   = note: available fields are: `x`
+
+error[E0609]: no field `1` on type `Bar`
+  --> $DIR/E0609.rs:11:7
+   |
+LL |     y.1;
+   |       ^ unknown field
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0609`.
diff --git a/src/test/ui/error-codes/E0610.rs b/src/test/ui/error-codes/E0610.rs
new file mode 100644
index 0000000..de246f3
--- /dev/null
+++ b/src/test/ui/error-codes/E0610.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let x = 0;
+    let _ = x.foo; //~ ERROR E0610
+}
diff --git a/src/test/ui/error-codes/E0610.stderr b/src/test/ui/error-codes/E0610.stderr
new file mode 100644
index 0000000..a2966ee
--- /dev/null
+++ b/src/test/ui/error-codes/E0610.stderr
@@ -0,0 +1,9 @@
+error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields
+  --> $DIR/E0610.rs:3:15
+   |
+LL |     let _ = x.foo;
+   |               ^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0610`.
diff --git a/src/test/ui/error-codes/E0614.rs b/src/test/ui/error-codes/E0614.rs
new file mode 100644
index 0000000..6b4817b
--- /dev/null
+++ b/src/test/ui/error-codes/E0614.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let y = 0u32;
+    *y; //~ ERROR E0614
+}
diff --git a/src/test/ui/error-codes/E0614.stderr b/src/test/ui/error-codes/E0614.stderr
new file mode 100644
index 0000000..598117c
--- /dev/null
+++ b/src/test/ui/error-codes/E0614.stderr
@@ -0,0 +1,9 @@
+error[E0614]: type `u32` cannot be dereferenced
+  --> $DIR/E0614.rs:3:5
+   |
+LL |     *y;
+   |     ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0614`.
diff --git a/src/test/ui/error-codes/E0615.rs b/src/test/ui/error-codes/E0615.rs
new file mode 100644
index 0000000..d04e4d5
--- /dev/null
+++ b/src/test/ui/error-codes/E0615.rs
@@ -0,0 +1,12 @@
+struct Foo {
+    x: u32,
+}
+
+impl Foo {
+    fn method(&self) {}
+}
+
+fn main() {
+    let f = Foo { x: 0 };
+    f.method; //~ ERROR E0615
+}
diff --git a/src/test/ui/error-codes/E0615.stderr b/src/test/ui/error-codes/E0615.stderr
new file mode 100644
index 0000000..7720587
--- /dev/null
+++ b/src/test/ui/error-codes/E0615.stderr
@@ -0,0 +1,9 @@
+error[E0615]: attempted to take value of method `method` on type `Foo`
+  --> $DIR/E0615.rs:11:7
+   |
+LL |     f.method;
+   |       ^^^^^^ help: use parentheses to call the method: `method()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0615`.
diff --git a/src/test/ui/error-codes/E0616.rs b/src/test/ui/error-codes/E0616.rs
new file mode 100644
index 0000000..98f87a8
--- /dev/null
+++ b/src/test/ui/error-codes/E0616.rs
@@ -0,0 +1,14 @@
+mod a {
+    pub struct Foo {
+        x: u32,
+    }
+
+    impl Foo {
+        pub fn new() -> Foo { Foo { x: 0 } }
+    }
+}
+
+fn main() {
+    let f = a::Foo::new();
+    f.x; //~ ERROR E0616
+}
diff --git a/src/test/ui/error-codes/E0616.stderr b/src/test/ui/error-codes/E0616.stderr
new file mode 100644
index 0000000..556e5db
--- /dev/null
+++ b/src/test/ui/error-codes/E0616.stderr
@@ -0,0 +1,9 @@
+error[E0616]: field `x` of struct `a::Foo` is private
+  --> $DIR/E0616.rs:13:5
+   |
+LL |     f.x;
+   |     ^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0616`.
diff --git a/src/test/ui/error-codes/E0617.rs b/src/test/ui/error-codes/E0617.rs
new file mode 100644
index 0000000..51f13c7
--- /dev/null
+++ b/src/test/ui/error-codes/E0617.rs
@@ -0,0 +1,28 @@
+// ignore-tidy-linelength
+
+extern {
+    fn printf(c: *const i8, ...);
+}
+
+fn main() {
+    unsafe {
+        printf(::std::ptr::null(), 0f32);
+        //~^ ERROR can't pass `f32` to variadic function
+        //~| HELP cast the value to `c_double`
+        printf(::std::ptr::null(), 0i8);
+        //~^ ERROR can't pass `i8` to variadic function
+        //~| HELP cast the value to `c_int`
+        printf(::std::ptr::null(), 0i16);
+        //~^ ERROR can't pass `i16` to variadic function
+        //~| HELP cast the value to `c_int`
+        printf(::std::ptr::null(), 0u8);
+        //~^ ERROR can't pass `u8` to variadic function
+        //~| HELP cast the value to `c_uint`
+        printf(::std::ptr::null(), 0u16);
+        //~^ ERROR can't pass `u16` to variadic function
+        //~| HELP cast the value to `c_uint`
+        printf(::std::ptr::null(), printf);
+        //~^ ERROR can't pass `for<'r> unsafe extern "C" fn(*const i8, std::ffi::VaList<'r>, ...) {printf}` to variadic function
+        //~| HELP cast the value to `for<'r> unsafe extern "C" fn(*const i8, std::ffi::VaList<'r>, ...)`
+    }
+}
diff --git a/src/test/ui/error-codes/E0617.stderr b/src/test/ui/error-codes/E0617.stderr
new file mode 100644
index 0000000..8387d5c
--- /dev/null
+++ b/src/test/ui/error-codes/E0617.stderr
@@ -0,0 +1,43 @@
+error[E0617]: can't pass `f32` to variadic function
+  --> $DIR/E0617.rs:9:36
+   |
+LL |         printf(::std::ptr::null(), 0f32);
+   |                                    ^^^^ help: cast the value to `c_double`: `0f32 as c_double`
+
+error[E0617]: can't pass `i8` to variadic function
+  --> $DIR/E0617.rs:12:36
+   |
+LL |         printf(::std::ptr::null(), 0i8);
+   |                                    ^^^ help: cast the value to `c_int`: `0i8 as c_int`
+
+error[E0617]: can't pass `i16` to variadic function
+  --> $DIR/E0617.rs:15:36
+   |
+LL |         printf(::std::ptr::null(), 0i16);
+   |                                    ^^^^ help: cast the value to `c_int`: `0i16 as c_int`
+
+error[E0617]: can't pass `u8` to variadic function
+  --> $DIR/E0617.rs:18:36
+   |
+LL |         printf(::std::ptr::null(), 0u8);
+   |                                    ^^^ help: cast the value to `c_uint`: `0u8 as c_uint`
+
+error[E0617]: can't pass `u16` to variadic function
+  --> $DIR/E0617.rs:21:36
+   |
+LL |         printf(::std::ptr::null(), 0u16);
+   |                                    ^^^^ help: cast the value to `c_uint`: `0u16 as c_uint`
+
+error[E0617]: can't pass `for<'r> unsafe extern "C" fn(*const i8, std::ffi::VaList<'r>, ...) {printf}` to variadic function
+  --> $DIR/E0617.rs:24:36
+   |
+LL |         printf(::std::ptr::null(), printf);
+   |                                    ^^^^^^
+help: cast the value to `for<'r> unsafe extern "C" fn(*const i8, std::ffi::VaList<'r>, ...)`
+   |
+LL |         printf(::std::ptr::null(), printf as for<'r> unsafe extern "C" fn(*const i8, std::ffi::VaList<'r>, ...));
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0617`.
diff --git a/src/test/ui/error-codes/E0618.rs b/src/test/ui/error-codes/E0618.rs
new file mode 100644
index 0000000..2616e71
--- /dev/null
+++ b/src/test/ui/error-codes/E0618.rs
@@ -0,0 +1,11 @@
+enum X {
+    Entry,
+}
+
+fn main() {
+    X::Entry();
+    //~^ ERROR expected function, found enum variant `X::Entry` [E0618]
+    let x = 0i32;
+    x();
+    //~^ ERROR expected function, found `i32` [E0618]
+}
diff --git a/src/test/ui/error-codes/E0618.stderr b/src/test/ui/error-codes/E0618.stderr
new file mode 100644
index 0000000..b691f09
--- /dev/null
+++ b/src/test/ui/error-codes/E0618.stderr
@@ -0,0 +1,28 @@
+error[E0618]: expected function, found enum variant `X::Entry`
+  --> $DIR/E0618.rs:6:5
+   |
+LL |     Entry,
+   |     ----- `X::Entry` defined here
+...
+LL |     X::Entry();
+   |     ^^^^^^^^--
+   |     |
+   |     call expression requires function
+help: `X::Entry` is a unit variant, you need to write it without the parenthesis
+   |
+LL |     X::Entry;
+   |     ^^^^^^^^
+
+error[E0618]: expected function, found `i32`
+  --> $DIR/E0618.rs:9:5
+   |
+LL |     let x = 0i32;
+   |         - `i32` defined here
+LL |     x();
+   |     ^--
+   |     |
+   |     call expression requires function
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0618`.
diff --git a/src/test/ui/error-codes/E0620.rs b/src/test/ui/error-codes/E0620.rs
new file mode 100644
index 0000000..2831413
--- /dev/null
+++ b/src/test/ui/error-codes/E0620.rs
@@ -0,0 +1,3 @@
+fn main() {
+    let _foo = &[1_usize, 2] as [usize]; //~ ERROR E0620
+}
diff --git a/src/test/ui/error-codes/E0620.stderr b/src/test/ui/error-codes/E0620.stderr
new file mode 100644
index 0000000..65152b2
--- /dev/null
+++ b/src/test/ui/error-codes/E0620.stderr
@@ -0,0 +1,15 @@
+error[E0620]: cast to unsized type: `&[usize; 2]` as `[usize]`
+  --> $DIR/E0620.rs:2:16
+   |
+LL |     let _foo = &[1_usize, 2] as [usize];
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: consider using an implicit coercion to `&[usize]` instead
+  --> $DIR/E0620.rs:2:16
+   |
+LL |     let _foo = &[1_usize, 2] as [usize];
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0620`.
diff --git a/src/test/ui/error-codes/E0621-does-not-trigger-for-closures.rs b/src/test/ui/error-codes/E0621-does-not-trigger-for-closures.rs
new file mode 100644
index 0000000..c58744d
--- /dev/null
+++ b/src/test/ui/error-codes/E0621-does-not-trigger-for-closures.rs
@@ -0,0 +1,18 @@
+// Test that we give the generic E0495 when one of the free regions is
+// bound in a closure (rather than suggesting a change to the signature
+// of the closure, which is not specified in `foo` but rather in `invoke`).
+
+// FIXME - This might be better as a UI test, but the finer details
+// of the error seem to vary on different machines.
+fn invoke<'a, F>(x: &'a i32, f: F) -> &'a i32
+where F: FnOnce(&'a i32, &i32) -> &'a i32
+{
+    let y = 22;
+    f(x, &y)
+}
+
+fn foo<'a>(x: &'a i32) {
+    invoke(&x, |a, b| if a > b { a } else { b }); //~ ERROR E0495
+}
+
+fn main() {}
diff --git a/src/test/ui/error-codes/E0621-does-not-trigger-for-closures.stderr b/src/test/ui/error-codes/E0621-does-not-trigger-for-closures.stderr
new file mode 100644
index 0000000..feca7f1
--- /dev/null
+++ b/src/test/ui/error-codes/E0621-does-not-trigger-for-closures.stderr
@@ -0,0 +1,30 @@
+error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
+  --> $DIR/E0621-does-not-trigger-for-closures.rs:15:5
+   |
+LL |     invoke(&x, |a, b| if a > b { a } else { b });
+   |     ^^^^^^
+   |
+note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the body at 15:16...
+  --> $DIR/E0621-does-not-trigger-for-closures.rs:15:16
+   |
+LL |     invoke(&x, |a, b| if a > b { a } else { b });
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...so that reference does not outlive borrowed content
+  --> $DIR/E0621-does-not-trigger-for-closures.rs:15:45
+   |
+LL |     invoke(&x, |a, b| if a > b { a } else { b });
+   |                                             ^
+note: but, the lifetime must be valid for the call at 15:5...
+  --> $DIR/E0621-does-not-trigger-for-closures.rs:15:5
+   |
+LL |     invoke(&x, |a, b| if a > b { a } else { b });
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...so type `&i32` of expression is valid during the expression
+  --> $DIR/E0621-does-not-trigger-for-closures.rs:15:5
+   |
+LL |     invoke(&x, |a, b| if a > b { a } else { b });
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0495`.
diff --git a/src/test/ui/error-codes/E0622.rs b/src/test/ui/error-codes/E0622.rs
new file mode 100644
index 0000000..ae7378a
--- /dev/null
+++ b/src/test/ui/error-codes/E0622.rs
@@ -0,0 +1,6 @@
+#![feature(intrinsics)]
+extern "rust-intrinsic" {
+    pub static breakpoint : unsafe extern "rust-intrinsic" fn();
+    //~^ ERROR intrinsic must be a function [E0622]
+}
+fn main() { unsafe { breakpoint(); } }
diff --git a/src/test/ui/error-codes/E0622.stderr b/src/test/ui/error-codes/E0622.stderr
new file mode 100644
index 0000000..8466dfe
--- /dev/null
+++ b/src/test/ui/error-codes/E0622.stderr
@@ -0,0 +1,9 @@
+error[E0622]: intrinsic must be a function
+  --> $DIR/E0622.rs:3:5
+   |
+LL |     pub static breakpoint : unsafe extern "rust-intrinsic" fn();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected a function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0622`.
diff --git a/src/test/ui/error-codes/E0624.rs b/src/test/ui/error-codes/E0624.rs
new file mode 100644
index 0000000..45f72a5
--- /dev/null
+++ b/src/test/ui/error-codes/E0624.rs
@@ -0,0 +1,12 @@
+mod inner {
+    pub struct Foo;
+
+    impl Foo {
+        fn method(&self) {}
+    }
+}
+
+fn main() {
+    let foo = inner::Foo;
+    foo.method(); //~ ERROR method `method` is private [E0624]
+}
diff --git a/src/test/ui/error-codes/E0624.stderr b/src/test/ui/error-codes/E0624.stderr
new file mode 100644
index 0000000..01ac24c
--- /dev/null
+++ b/src/test/ui/error-codes/E0624.stderr
@@ -0,0 +1,9 @@
+error[E0624]: method `method` is private
+  --> $DIR/E0624.rs:11:9
+   |
+LL |     foo.method();
+   |         ^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0624`.
diff --git a/src/test/ui/error-codes/E0637.rs b/src/test/ui/error-codes/E0637.rs
new file mode 100644
index 0000000..b4888d4
--- /dev/null
+++ b/src/test/ui/error-codes/E0637.rs
@@ -0,0 +1,9 @@
+struct Foo<'a: '_>(&'a u8); //~ ERROR cannot be used here
+fn foo<'a: '_>(_: &'a u8) {} //~ ERROR cannot be used here
+
+struct Bar<'a>(&'a u8);
+impl<'a: '_> Bar<'a> { //~ ERROR cannot be used here
+  fn bar() {}
+}
+
+fn main() {}
diff --git a/src/test/ui/error-codes/E0637.stderr b/src/test/ui/error-codes/E0637.stderr
new file mode 100644
index 0000000..d19ebfd
--- /dev/null
+++ b/src/test/ui/error-codes/E0637.stderr
@@ -0,0 +1,21 @@
+error[E0637]: `'_` cannot be used here
+  --> $DIR/E0637.rs:1:16
+   |
+LL | struct Foo<'a: '_>(&'a u8);
+   |                ^^ `'_` is a reserved lifetime name
+
+error[E0637]: `'_` cannot be used here
+  --> $DIR/E0637.rs:2:12
+   |
+LL | fn foo<'a: '_>(_: &'a u8) {}
+   |            ^^ `'_` is a reserved lifetime name
+
+error[E0637]: `'_` cannot be used here
+  --> $DIR/E0637.rs:5:10
+   |
+LL | impl<'a: '_> Bar<'a> {
+   |          ^^ `'_` is a reserved lifetime name
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0637`.
diff --git a/src/test/ui/error-codes/E0646.rs b/src/test/ui/error-codes/E0646.rs
new file mode 100644
index 0000000..bb62428
--- /dev/null
+++ b/src/test/ui/error-codes/E0646.rs
@@ -0,0 +1 @@
+fn main() where (): Copy {} //~ ERROR [E0646]
diff --git a/src/test/ui/error-codes/E0646.stderr b/src/test/ui/error-codes/E0646.stderr
new file mode 100644
index 0000000..976cdd4
--- /dev/null
+++ b/src/test/ui/error-codes/E0646.stderr
@@ -0,0 +1,9 @@
+error[E0646]: `main` function is not allowed to have a `where` clause
+  --> $DIR/E0646.rs:1:17
+   |
+LL | fn main() where (): Copy {}
+   |                 ^^^^^^^^ `main` cannot have a `where` clause
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0646`.
diff --git a/src/test/ui/error-codes/E0647.rs b/src/test/ui/error-codes/E0647.rs
new file mode 100644
index 0000000..fc08551
--- /dev/null
+++ b/src/test/ui/error-codes/E0647.rs
@@ -0,0 +1,9 @@
+#![no_std]
+#![feature(start)]
+
+extern crate std;
+
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize where (): Copy { //~ ERROR [E0647]
+    0
+}
diff --git a/src/test/ui/error-codes/E0647.stderr b/src/test/ui/error-codes/E0647.stderr
new file mode 100644
index 0000000..465cc77
--- /dev/null
+++ b/src/test/ui/error-codes/E0647.stderr
@@ -0,0 +1,9 @@
+error[E0647]: start function is not allowed to have a `where` clause
+  --> $DIR/E0647.rs:7:56
+   |
+LL | fn start(_: isize, _: *const *const u8) -> isize where (): Copy {
+   |                                                        ^^^^^^^^ start function cannot have a `where` clause
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0647`.
diff --git a/src/test/ui/error-codes/E0648.rs b/src/test/ui/error-codes/E0648.rs
new file mode 100644
index 0000000..8408a78
--- /dev/null
+++ b/src/test/ui/error-codes/E0648.rs
@@ -0,0 +1,4 @@
+#[export_name="\0foo"] //~ ERROR E0648
+pub fn bar() {}
+
+fn main() {}
diff --git a/src/test/ui/error-codes/E0648.stderr b/src/test/ui/error-codes/E0648.stderr
new file mode 100644
index 0000000..1a65825
--- /dev/null
+++ b/src/test/ui/error-codes/E0648.stderr
@@ -0,0 +1,9 @@
+error[E0648]: `export_name` may not contain null characters
+  --> $DIR/E0648.rs:1:1
+   |
+LL | #[export_name="\0foo"]
+   | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0648`.
diff --git a/src/test/ui/error-codes/E0657.rs b/src/test/ui/error-codes/E0657.rs
new file mode 100644
index 0000000..cb11de1
--- /dev/null
+++ b/src/test/ui/error-codes/E0657.rs
@@ -0,0 +1,26 @@
+#![allow(warnings)]
+
+trait Id<T> {}
+trait Lt<'a> {}
+
+impl<'a> Lt<'a> for () {}
+impl<T> Id<T> for T {}
+
+fn free_fn_capture_hrtb_in_impl_trait()
+    -> Box<for<'a> Id<impl Lt<'a>>>
+        //~^ ERROR `impl Trait` can only capture lifetimes bound at the fn or impl level [E0657]
+{
+    Box::new(())
+}
+
+struct Foo;
+impl Foo {
+    fn impl_fn_capture_hrtb_in_impl_trait()
+        -> Box<for<'a> Id<impl Lt<'a>>>
+            //~^ ERROR `impl Trait` can only capture lifetimes bound at the fn or impl level
+    {
+        Box::new(())
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/error-codes/E0657.stderr b/src/test/ui/error-codes/E0657.stderr
new file mode 100644
index 0000000..df76b45
--- /dev/null
+++ b/src/test/ui/error-codes/E0657.stderr
@@ -0,0 +1,15 @@
+error[E0657]: `impl Trait` can only capture lifetimes bound at the fn or impl level
+  --> $DIR/E0657.rs:10:31
+   |
+LL |     -> Box<for<'a> Id<impl Lt<'a>>>
+   |                               ^^
+
+error[E0657]: `impl Trait` can only capture lifetimes bound at the fn or impl level
+  --> $DIR/E0657.rs:19:35
+   |
+LL |         -> Box<for<'a> Id<impl Lt<'a>>>
+   |                                   ^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0657`.
diff --git a/src/test/ui/error-codes/E0658.rs b/src/test/ui/error-codes/E0658.rs
new file mode 100644
index 0000000..9c9b95d
--- /dev/null
+++ b/src/test/ui/error-codes/E0658.rs
@@ -0,0 +1,6 @@
+#[repr(u128)]
+enum Foo { //~ ERROR E0658
+    Bar(u64),
+}
+
+fn main() {}
diff --git a/src/test/ui/error-codes/E0658.stderr b/src/test/ui/error-codes/E0658.stderr
new file mode 100644
index 0000000..292c49f
--- /dev/null
+++ b/src/test/ui/error-codes/E0658.stderr
@@ -0,0 +1,13 @@
+error[E0658]: repr with 128-bit type is unstable (see issue #35118)
+  --> $DIR/E0658.rs:2:1
+   |
+LL | / enum Foo {
+LL | |     Bar(u64),
+LL | | }
+   | |_^
+   |
+   = help: add #![feature(repr128)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/error-codes/E0659.rs b/src/test/ui/error-codes/E0659.rs
new file mode 100644
index 0000000..c00026b
--- /dev/null
+++ b/src/test/ui/error-codes/E0659.rs
@@ -0,0 +1,16 @@
+mod moon {
+    pub fn foo() {}
+}
+
+mod earth {
+    pub fn foo() {}
+}
+
+mod collider {
+    pub use moon::*;
+    pub use earth::*;
+}
+
+fn main() {
+    collider::foo(); //~ ERROR E0659
+}
diff --git a/src/test/ui/error-codes/E0659.stderr b/src/test/ui/error-codes/E0659.stderr
new file mode 100644
index 0000000..2f01f54
--- /dev/null
+++ b/src/test/ui/error-codes/E0659.stderr
@@ -0,0 +1,22 @@
+error[E0659]: `foo` is ambiguous (glob import vs glob import in the same module)
+  --> $DIR/E0659.rs:15:15
+   |
+LL |     collider::foo();
+   |               ^^^ ambiguous name
+   |
+note: `foo` could refer to the function imported here
+  --> $DIR/E0659.rs:10:13
+   |
+LL |     pub use moon::*;
+   |             ^^^^^^^
+   = help: consider adding an explicit import of `foo` to disambiguate
+note: `foo` could also refer to the function imported here
+  --> $DIR/E0659.rs:11:13
+   |
+LL |     pub use earth::*;
+   |             ^^^^^^^^
+   = help: consider adding an explicit import of `foo` to disambiguate
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0659`.
diff --git a/src/test/ui/error-codes/E0718.rs b/src/test/ui/error-codes/E0718.rs
new file mode 100644
index 0000000..82ab2d4
--- /dev/null
+++ b/src/test/ui/error-codes/E0718.rs
@@ -0,0 +1,7 @@
+#![feature(lang_items)]
+
+// Arc is expected to be a struct, so this will error.
+#[lang = "arc"] //~ ERROR language item must be applied to a struct
+static X: u32 = 42;
+
+fn main() {}
diff --git a/src/test/ui/error-codes/E0718.stderr b/src/test/ui/error-codes/E0718.stderr
new file mode 100644
index 0000000..412c856
--- /dev/null
+++ b/src/test/ui/error-codes/E0718.stderr
@@ -0,0 +1,9 @@
+error[E0718]: `arc` language item must be applied to a struct
+  --> $DIR/E0718.rs:4:1
+   |
+LL | #[lang = "arc"]
+   | ^^^^^^^^^^^^^^^ attribute should be applied to a struct, not a static item
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0718`.
diff --git a/src/test/ui/error-codes/E0719.rs b/src/test/ui/error-codes/E0719.rs
new file mode 100644
index 0000000..6b572f4
--- /dev/null
+++ b/src/test/ui/error-codes/E0719.rs
@@ -0,0 +1,14 @@
+trait Foo: Iterator<Item = i32, Item = i32> {}
+//~^ ERROR is already specified
+
+type Unit = ();
+
+fn test() -> Box<Iterator<Item = (), Item = Unit>> {
+//~^ ERROR is already specified
+    Box::new(None.into_iter())
+}
+
+fn main() {
+    let _: &Iterator<Item = i32, Item = i32>;
+    test();
+}
diff --git a/src/test/ui/error-codes/E0719.stderr b/src/test/ui/error-codes/E0719.stderr
new file mode 100644
index 0000000..209bfba
--- /dev/null
+++ b/src/test/ui/error-codes/E0719.stderr
@@ -0,0 +1,19 @@
+error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
+  --> $DIR/E0719.rs:1:33
+   |
+LL | trait Foo: Iterator<Item = i32, Item = i32> {}
+   |                     ----------  ^^^^^^^^^^ re-bound here
+   |                     |
+   |                     `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
+  --> $DIR/E0719.rs:6:38
+   |
+LL | fn test() -> Box<Iterator<Item = (), Item = Unit>> {
+   |                           ---------  ^^^^^^^^^^^ re-bound here
+   |                           |
+   |                           `Item` bound here first
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0719`.
diff --git a/src/test/ui/error-codes/ex-E0611.rs b/src/test/ui/error-codes/ex-E0611.rs
new file mode 100644
index 0000000..8460341
--- /dev/null
+++ b/src/test/ui/error-codes/ex-E0611.rs
@@ -0,0 +1,12 @@
+mod a {
+    pub struct Foo(u32);
+
+    impl Foo {
+        pub fn new() -> Foo { Foo(0) }
+    }
+}
+
+fn main() {
+   let y = a::Foo::new();
+   y.0; //~ ERROR field `0` of struct `a::Foo` is private
+}
diff --git a/src/test/ui/error-codes/ex-E0611.stderr b/src/test/ui/error-codes/ex-E0611.stderr
new file mode 100644
index 0000000..8bd00a3
--- /dev/null
+++ b/src/test/ui/error-codes/ex-E0611.stderr
@@ -0,0 +1,9 @@
+error[E0616]: field `0` of struct `a::Foo` is private
+  --> $DIR/ex-E0611.rs:11:4
+   |
+LL |    y.0;
+   |    ^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0616`.
diff --git a/src/test/ui/error-codes/ex-E0612.rs b/src/test/ui/error-codes/ex-E0612.rs
new file mode 100644
index 0000000..c8ea53a
--- /dev/null
+++ b/src/test/ui/error-codes/ex-E0612.rs
@@ -0,0 +1,6 @@
+struct Foo(u32);
+
+fn main() {
+   let y = Foo(0);
+   y.1; //~ ERROR no field `1` on type `Foo`
+}
diff --git a/src/test/ui/error-codes/ex-E0612.stderr b/src/test/ui/error-codes/ex-E0612.stderr
new file mode 100644
index 0000000..b21b6fd
--- /dev/null
+++ b/src/test/ui/error-codes/ex-E0612.stderr
@@ -0,0 +1,9 @@
+error[E0609]: no field `1` on type `Foo`
+  --> $DIR/ex-E0612.rs:5:6
+   |
+LL |    y.1;
+   |      ^ help: a field with a similar name exists: `0`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0609`.
diff --git a/src/test/ui/error-festival.rs b/src/test/ui/error-festival.rs
new file mode 100644
index 0000000..e462824
--- /dev/null
+++ b/src/test/ui/error-festival.rs
@@ -0,0 +1,43 @@
+enum Question {
+    Yes,
+    No,
+}
+
+mod foo {
+    const FOO: u32 = 0;
+}
+
+fn main() {
+    let x = "a";
+    x += 2;
+    //~^ ERROR E0368
+    y = 2;
+    //~^ ERROR E0425
+    x.z();
+    //~^ ERROR E0599
+
+    !Question::Yes;
+    //~^ ERROR E0600
+
+    foo::FOO;
+    //~^ ERROR E0603
+
+    0u32 as char;
+    //~^ ERROR E0604
+
+    let x = 0u8;
+    x as Vec<u8>;
+    //~^ ERROR E0605
+
+    let x = 5;
+    let x_is_nonzero = x as bool;
+    //~^ ERROR E0054
+
+    let x = &0u8;
+    let y: u32 = x as u32;
+    //~^ ERROR E0606
+
+    let v = 0 as *const u8;
+    v as *const [u8];
+    //~^ ERROR E0607
+}
diff --git a/src/test/ui/error-festival.stderr b/src/test/ui/error-festival.stderr
new file mode 100644
index 0000000..ff6504e
--- /dev/null
+++ b/src/test/ui/error-festival.stderr
@@ -0,0 +1,75 @@
+error[E0425]: cannot find value `y` in this scope
+  --> $DIR/error-festival.rs:14:5
+   |
+LL |     y = 2;
+   |     ^ help: a local variable with a similar name exists: `x`
+
+error[E0603]: constant `FOO` is private
+  --> $DIR/error-festival.rs:22:10
+   |
+LL |     foo::FOO;
+   |          ^^^
+
+error[E0368]: binary assignment operation `+=` cannot be applied to type `&str`
+  --> $DIR/error-festival.rs:12:5
+   |
+LL |     x += 2;
+   |     -^^^^^
+   |     |
+   |     cannot use `+=` on type `&str`
+   |
+   = note: an implementation of `std::ops::AddAssign` might be missing for `&str`
+
+error[E0599]: no method named `z` found for type `&str` in the current scope
+  --> $DIR/error-festival.rs:16:7
+   |
+LL |     x.z();
+   |       ^
+
+error[E0600]: cannot apply unary operator `!` to type `Question`
+  --> $DIR/error-festival.rs:19:5
+   |
+LL |     !Question::Yes;
+   |     ^^^^^^^^^^^^^^ cannot apply unary operator `!`
+   |
+   = note: an implementation of `std::ops::Not` might be missing for `Question`
+
+error[E0604]: only `u8` can be cast as `char`, not `u32`
+  --> $DIR/error-festival.rs:25:5
+   |
+LL |     0u32 as char;
+   |     ^^^^^^^^^^^^
+
+error[E0605]: non-primitive cast: `u8` as `std::vec::Vec<u8>`
+  --> $DIR/error-festival.rs:29:5
+   |
+LL |     x as Vec<u8>;
+   |     ^^^^^^^^^^^^
+   |
+   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+
+error[E0054]: cannot cast as `bool`
+  --> $DIR/error-festival.rs:33:24
+   |
+LL |     let x_is_nonzero = x as bool;
+   |                        ^^^^^^^^^ help: compare with zero instead: `x != 0`
+
+error[E0606]: casting `&u8` as `u32` is invalid
+  --> $DIR/error-festival.rs:37:18
+   |
+LL |     let y: u32 = x as u32;
+   |                  -^^^^^^^
+   |                  |
+   |                  cannot cast `&u8` as `u32`
+   |                  help: dereference the expression: `*x`
+
+error[E0607]: cannot cast thin pointer `*const u8` to fat pointer `*const [u8]`
+  --> $DIR/error-festival.rs:41:5
+   |
+LL |     v as *const [u8];
+   |     ^^^^^^^^^^^^^^^^
+
+error: aborting due to 10 previous errors
+
+Some errors occurred: E0054, E0368, E0425, E0599, E0600, E0603, E0604, E0605, E0606...
+For more information about an error, try `rustc --explain E0054`.
diff --git a/src/test/ui/error-should-say-copy-not-pod.rs b/src/test/ui/error-should-say-copy-not-pod.rs
new file mode 100644
index 0000000..be4e451
--- /dev/null
+++ b/src/test/ui/error-should-say-copy-not-pod.rs
@@ -0,0 +1,7 @@
+// Tests that the error message uses the word Copy, not Pod.
+
+fn check_bound<T:Copy>(_: T) {}
+
+fn main() {
+    check_bound("nocopy".to_string()); //~ ERROR : std::marker::Copy` is not satisfied
+}
diff --git a/src/test/ui/error-should-say-copy-not-pod.stderr b/src/test/ui/error-should-say-copy-not-pod.stderr
new file mode 100644
index 0000000..7143f8c
--- /dev/null
+++ b/src/test/ui/error-should-say-copy-not-pod.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied
+  --> $DIR/error-should-say-copy-not-pod.rs:6:5
+   |
+LL |     check_bound("nocopy".to_string());
+   |     ^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String`
+   |
+note: required by `check_bound`
+  --> $DIR/error-should-say-copy-not-pod.rs:3:1
+   |
+LL | fn check_bound<T:Copy>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/estr-subtyping.rs b/src/test/ui/estr-subtyping.rs
new file mode 100644
index 0000000..9c5825f
--- /dev/null
+++ b/src/test/ui/estr-subtyping.rs
@@ -0,0 +1,15 @@
+fn wants_uniq(x: String) { }
+fn wants_slice(x: &str) { }
+
+fn has_uniq(x: String) {
+   wants_uniq(x);
+   wants_slice(&*x);
+}
+
+fn has_slice(x: &str) {
+   wants_uniq(x); //~ ERROR mismatched types
+   wants_slice(x);
+}
+
+fn main() {
+}
diff --git a/src/test/ui/estr-subtyping.stderr b/src/test/ui/estr-subtyping.stderr
new file mode 100644
index 0000000..29f2108
--- /dev/null
+++ b/src/test/ui/estr-subtyping.stderr
@@ -0,0 +1,15 @@
+error[E0308]: mismatched types
+  --> $DIR/estr-subtyping.rs:10:15
+   |
+LL |    wants_uniq(x);
+   |               ^
+   |               |
+   |               expected struct `std::string::String`, found &str
+   |               help: try using a conversion method: `x.to_string()`
+   |
+   = note: expected type `std::string::String`
+              found type `&str`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/eval-enum.rs b/src/test/ui/eval-enum.rs
new file mode 100644
index 0000000..cf49b96
--- /dev/null
+++ b/src/test/ui/eval-enum.rs
@@ -0,0 +1,10 @@
+enum Test {
+    DivZero = 1/0,
+    //~^ attempt to divide by zero
+    //~| ERROR evaluation of constant value failed
+    RemZero = 1%0,
+    //~^ attempt to calculate the remainder with a divisor of zero
+    //~| ERROR evaluation of constant value failed
+}
+
+fn main() {}
diff --git a/src/test/ui/eval-enum.stderr b/src/test/ui/eval-enum.stderr
new file mode 100644
index 0000000..195eadd
--- /dev/null
+++ b/src/test/ui/eval-enum.stderr
@@ -0,0 +1,15 @@
+error[E0080]: evaluation of constant value failed
+  --> $DIR/eval-enum.rs:2:15
+   |
+LL |     DivZero = 1/0,
+   |               ^^^ attempt to divide by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/eval-enum.rs:5:15
+   |
+LL |     RemZero = 1%0,
+   |               ^^^ attempt to calculate the remainder with a divisor of zero
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/exclusive-drop-and-copy.rs b/src/test/ui/exclusive-drop-and-copy.rs
new file mode 100644
index 0000000..7a25167
--- /dev/null
+++ b/src/test/ui/exclusive-drop-and-copy.rs
@@ -0,0 +1,17 @@
+// issue #20126
+
+#[derive(Copy, Clone)] //~ ERROR the trait `Copy` may not be implemented
+struct Foo;
+
+impl Drop for Foo {
+    fn drop(&mut self) {}
+}
+
+#[derive(Copy, Clone)] //~ ERROR the trait `Copy` may not be implemented
+struct Bar<T>(::std::marker::PhantomData<T>);
+
+impl<T> Drop for Bar<T> {
+    fn drop(&mut self) {}
+}
+
+fn main() {}
diff --git a/src/test/ui/exclusive-drop-and-copy.stderr b/src/test/ui/exclusive-drop-and-copy.stderr
new file mode 100644
index 0000000..9983aac
--- /dev/null
+++ b/src/test/ui/exclusive-drop-and-copy.stderr
@@ -0,0 +1,15 @@
+error[E0184]: the trait `Copy` may not be implemented for this type; the type has a destructor
+  --> $DIR/exclusive-drop-and-copy.rs:3:10
+   |
+LL | #[derive(Copy, Clone)]
+   |          ^^^^ Copy not allowed on types with destructors
+
+error[E0184]: the trait `Copy` may not be implemented for this type; the type has a destructor
+  --> $DIR/exclusive-drop-and-copy.rs:10:10
+   |
+LL | #[derive(Copy, Clone)]
+   |          ^^^^ Copy not allowed on types with destructors
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0184`.
diff --git a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision.rs b/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision.rs
new file mode 100644
index 0000000..d95c4b0
--- /dev/null
+++ b/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision.rs
@@ -0,0 +1,8 @@
+#![feature(exclusive_range_pattern)]
+
+fn main() {
+    match [5..4, 99..105, 43..44] {
+        [_, 99.., _] => {}, //~ ERROR unexpected token: `,`
+        _ => {},
+    }
+}
diff --git a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision.stderr b/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision.stderr
new file mode 100644
index 0000000..03867a8
--- /dev/null
+++ b/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision.stderr
@@ -0,0 +1,8 @@
+error: unexpected token: `,`
+  --> $DIR/exclusive_range_pattern_syntax_collision.rs:5:15
+   |
+LL |         [_, 99.., _] => {},
+   |               ^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision2.rs b/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision2.rs
new file mode 100644
index 0000000..95677e3
--- /dev/null
+++ b/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision2.rs
@@ -0,0 +1,8 @@
+#![feature(exclusive_range_pattern)]
+
+fn main() {
+    match [5..4, 99..105, 43..44] {
+        [_, 99..] => {}, //~ ERROR unexpected token: `]`
+        _ => {},
+    }
+}
diff --git a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision2.stderr b/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision2.stderr
new file mode 100644
index 0000000..5ac435b
--- /dev/null
+++ b/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision2.stderr
@@ -0,0 +1,8 @@
+error: unexpected token: `]`
+  --> $DIR/exclusive_range_pattern_syntax_collision2.rs:5:15
+   |
+LL |         [_, 99..] => {},
+   |               ^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision3.rs b/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision3.rs
new file mode 100644
index 0000000..3bf5da7
--- /dev/null
+++ b/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision3.rs
@@ -0,0 +1,8 @@
+#![feature(exclusive_range_pattern)]
+
+fn main() {
+    match [5..4, 99..105, 43..44] {
+        [..9, 99..100, _] => {}, //~ ERROR expected one of `,` or `]`, found `9`
+        _ => {},
+    }
+}
diff --git a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision3.stderr b/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision3.stderr
new file mode 100644
index 0000000..a09ba35
--- /dev/null
+++ b/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision3.stderr
@@ -0,0 +1,8 @@
+error: expected one of `,` or `]`, found `9`
+  --> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:12
+   |
+LL |         [..9, 99..100, _] => {},
+   |            ^ expected one of `,` or `]` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/exhaustive_integer_patterns.rs b/src/test/ui/exhaustive_integer_patterns.rs
new file mode 100644
index 0000000..2570bc8
--- /dev/null
+++ b/src/test/ui/exhaustive_integer_patterns.rs
@@ -0,0 +1,156 @@
+#![feature(precise_pointer_size_matching)]
+#![feature(exclusive_range_pattern)]
+
+#![deny(unreachable_patterns)]
+
+use std::{char, u8, u16, u32, u64, u128, i8, i16, i32, i64, i128};
+
+fn main() {
+    let x: u8 = 0;
+
+    // A single range covering the entire domain.
+    match x {
+        0 ..= 255 => {} // ok
+    }
+
+    // A combination of ranges and values.
+    // These are currently allowed to be overlapping.
+    match x {
+        0 ..= 32 => {}
+        33 => {}
+        34 .. 128 => {}
+        100 ..= 200 => {}
+        200 => {} //~ ERROR unreachable pattern
+        201 ..= 255 => {}
+    }
+
+    // An incomplete set of values.
+    match x { //~ ERROR non-exhaustive patterns
+        0 .. 128 => {}
+    }
+
+    // A more incomplete set of values.
+    match x { //~ ERROR non-exhaustive patterns
+        0 ..= 10 => {}
+        20 ..= 30 => {}
+        35 => {}
+        70 .. 255 => {}
+    }
+
+    let x: i8 = 0;
+    match x { //~ ERROR non-exhaustive patterns
+        -7 => {}
+        -5..=120 => {}
+        -2..=20 => {} //~ ERROR unreachable pattern
+        125 => {}
+    }
+
+    // Let's test other types too!
+    let c: char = '\u{0}';
+    match c {
+        '\u{0}' ..= char::MAX => {} // ok
+    }
+
+    // We can actually get away with just covering the
+    // following two ranges, which correspond to all
+    // valid Unicode Scalar Values.
+    match c {
+        '\u{0000}' ..= '\u{D7FF}' => {}
+        '\u{E000}' ..= '\u{10_FFFF}' => {}
+    }
+
+    match 0u16 {
+        0 ..= u16::MAX => {} // ok
+    }
+
+    match 0u32 {
+        0 ..= u32::MAX => {} // ok
+    }
+
+    match 0u64 {
+        0 ..= u64::MAX => {} // ok
+    }
+
+    match 0u128 {
+        0 ..= u128::MAX => {} // ok
+    }
+
+    match 0i8 {
+        -128 ..= 127 => {} // ok
+    }
+
+    match 0i8 { //~ ERROR non-exhaustive patterns
+        -127 ..= 127 => {}
+    }
+
+    match 0i16 {
+        i16::MIN ..= i16::MAX => {} // ok
+    }
+
+    match 0i16 { //~ ERROR non-exhaustive patterns
+        i16::MIN ..= -1 => {}
+        1 ..= i16::MAX => {}
+    }
+
+    match 0i32 {
+        i32::MIN ..= i32::MAX => {} // ok
+    }
+
+    match 0i64 {
+        i64::MIN ..= i64::MAX => {} // ok
+    }
+
+    match 0i128 {
+        i128::MIN ..= i128::MAX => {} // ok
+    }
+
+    // Make sure that guards don't factor into the exhaustiveness checks.
+    match 0u8 { //~ ERROR non-exhaustive patterns
+        0 .. 128 => {}
+        128 ..= 255 if true => {}
+    }
+
+    match 0u8 {
+        0 .. 128 => {}
+        128 ..= 255 if false => {}
+        128 ..= 255 => {} // ok, because previous arm was guarded
+    }
+
+    // Now things start getting a bit more interesting. Testing products!
+    match (0u8, Some(())) { //~ ERROR non-exhaustive patterns
+        (1, _) => {}
+        (_, None) => {}
+    }
+
+    match (0u8, true) { //~ ERROR non-exhaustive patterns
+        (0 ..= 125, false) => {}
+        (128 ..= 255, false) => {}
+        (0 ..= 255, true) => {}
+    }
+
+    match (0u8, true) { // ok
+        (0 ..= 125, false) => {}
+        (128 ..= 255, false) => {}
+        (0 ..= 255, true) => {}
+        (125 .. 128, false) => {}
+    }
+
+    match 0u8 { // ok
+        0 .. 2 => {}
+        1 ..= 2 => {}
+        _ => {}
+    }
+
+    const LIM: u128 = u128::MAX - 1;
+    match 0u128 { //~ ERROR non-exhaustive patterns
+        0 ..= LIM => {}
+    }
+
+    match 0u128 { //~ ERROR non-exhaustive patterns
+        0 ..= 4 => {}
+    }
+
+    match 0u128 { //~ ERROR non-exhaustive patterns
+        4 ..= u128::MAX => {}
+    }
+}
diff --git a/src/test/ui/exhaustive_integer_patterns.stderr b/src/test/ui/exhaustive_integer_patterns.stderr
new file mode 100644
index 0000000..82b0b48
--- /dev/null
+++ b/src/test/ui/exhaustive_integer_patterns.stderr
@@ -0,0 +1,109 @@
+error: unreachable pattern
+  --> $DIR/exhaustive_integer_patterns.rs:23:9
+   |
+LL |         200 => {}
+   |         ^^^
+   |
+note: lint level defined here
+  --> $DIR/exhaustive_integer_patterns.rs:4:9
+   |
+LL | #![deny(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error[E0004]: non-exhaustive patterns: `128u8..=255u8` not covered
+  --> $DIR/exhaustive_integer_patterns.rs:28:11
+   |
+LL |     match x {
+   |           ^ pattern `128u8..=255u8` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `11u8..=19u8`, `31u8..=34u8`, `36u8..=69u8` and 1 more not covered
+  --> $DIR/exhaustive_integer_patterns.rs:33:11
+   |
+LL |     match x {
+   |           ^ patterns `11u8..=19u8`, `31u8..=34u8`, `36u8..=69u8` and 1 more not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: unreachable pattern
+  --> $DIR/exhaustive_integer_patterns.rs:44:9
+   |
+LL |         -2..=20 => {}
+   |         ^^^^^^^
+
+error[E0004]: non-exhaustive patterns: `-128i8..=-8i8`, `-6i8`, `121i8..=124i8` and 1 more not covered
+  --> $DIR/exhaustive_integer_patterns.rs:41:11
+   |
+LL |     match x {
+   |           ^ patterns `-128i8..=-8i8`, `-6i8`, `121i8..=124i8` and 1 more not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `-128i8` not covered
+  --> $DIR/exhaustive_integer_patterns.rs:82:11
+   |
+LL |     match 0i8 {
+   |           ^^^ pattern `-128i8` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `0i16` not covered
+  --> $DIR/exhaustive_integer_patterns.rs:90:11
+   |
+LL |     match 0i16 {
+   |           ^^^^ pattern `0i16` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `128u8..=255u8` not covered
+  --> $DIR/exhaustive_integer_patterns.rs:108:11
+   |
+LL |     match 0u8 {
+   |           ^^^ pattern `128u8..=255u8` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `(0u8, Some(_))` and `(2u8..=255u8, Some(_))` not covered
+  --> $DIR/exhaustive_integer_patterns.rs:120:11
+   |
+LL |     match (0u8, Some(())) {
+   |           ^^^^^^^^^^^^^^^ patterns `(0u8, Some(_))` and `(2u8..=255u8, Some(_))` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `(126u8..=127u8, false)` not covered
+  --> $DIR/exhaustive_integer_patterns.rs:125:11
+   |
+LL |     match (0u8, true) {
+   |           ^^^^^^^^^^^ pattern `(126u8..=127u8, false)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `340282366920938463463374607431768211455u128` not covered
+  --> $DIR/exhaustive_integer_patterns.rs:145:11
+   |
+LL |     match 0u128 {
+   |           ^^^^^ pattern `340282366920938463463374607431768211455u128` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `5u128..=340282366920938463463374607431768211455u128` not covered
+  --> $DIR/exhaustive_integer_patterns.rs:149:11
+   |
+LL |     match 0u128 {
+   |           ^^^^^ pattern `5u128..=340282366920938463463374607431768211455u128` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `0u128..=3u128` not covered
+  --> $DIR/exhaustive_integer_patterns.rs:153:11
+   |
+LL |     match 0u128 {
+   |           ^^^^^ pattern `0u128..=3u128` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to 13 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/existential_types/auxiliary/cross_crate_ice.rs b/src/test/ui/existential_types/auxiliary/cross_crate_ice.rs
new file mode 100644
index 0000000..af2d209
--- /dev/null
+++ b/src/test/ui/existential_types/auxiliary/cross_crate_ice.rs
@@ -0,0 +1,12 @@
+// Crate that exports an existential type. Used for testing cross-crate.
+
+#![crate_type="rlib"]
+
+#![feature(existential_type)]
+
+pub existential type Foo: std::fmt::Debug;
+
+pub fn foo() -> Foo {
+    5
+}
+
diff --git a/src/test/ui/existential_types/auxiliary/cross_crate_ice2.rs b/src/test/ui/existential_types/auxiliary/cross_crate_ice2.rs
new file mode 100644
index 0000000..39ec539
--- /dev/null
+++ b/src/test/ui/existential_types/auxiliary/cross_crate_ice2.rs
@@ -0,0 +1,21 @@
+// Crate that exports an existential type. Used for testing cross-crate.
+
+#![crate_type="rlib"]
+
+#![feature(existential_type)]
+
+pub trait View {
+    type Tmp: Iterator<Item = u32>;
+
+    fn test(&self) -> Self::Tmp;
+}
+
+pub struct X;
+
+impl View for X {
+    existential type Tmp: Iterator<Item = u32>;
+
+    fn test(&self) -> Self::Tmp {
+        vec![1,2,3].into_iter()
+    }
+}
diff --git a/src/test/ui/existential_types/bound_reduction.rs b/src/test/ui/existential_types/bound_reduction.rs
new file mode 100644
index 0000000..c1c0c60
--- /dev/null
+++ b/src/test/ui/existential_types/bound_reduction.rs
@@ -0,0 +1,20 @@
+// compile-pass
+
+#![allow(warnings)]
+
+#![feature(existential_type)]
+
+fn main() {
+}
+
+existential type Foo<V>: std::fmt::Debug;
+
+trait Trait<U> {}
+
+fn foo_desugared<T: Trait<[u32; {
+    #[no_mangle]
+    static FOO: usize = 42;
+    3
+}]>>(_: T) -> Foo<T> {
+    (42, std::marker::PhantomData::<T>)
+}
diff --git a/src/test/ui/existential_types/bound_reduction2.rs b/src/test/ui/existential_types/bound_reduction2.rs
new file mode 100644
index 0000000..542e076
--- /dev/null
+++ b/src/test/ui/existential_types/bound_reduction2.rs
@@ -0,0 +1,19 @@
+#![feature(existential_type)]
+
+fn main() {
+}
+
+trait TraitWithAssoc {
+    type Assoc;
+}
+
+existential type Foo<V>: Trait<V>;
+//~^ ERROR could not find defining uses
+
+trait Trait<U> {}
+
+impl<W> Trait<W> for () {}
+
+fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> { //~ ERROR does not fully define
+    ()
+}
diff --git a/src/test/ui/existential_types/bound_reduction2.stderr b/src/test/ui/existential_types/bound_reduction2.stderr
new file mode 100644
index 0000000..b8bad7d
--- /dev/null
+++ b/src/test/ui/existential_types/bound_reduction2.stderr
@@ -0,0 +1,16 @@
+error: defining existential type use does not fully define existential type
+  --> $DIR/bound_reduction2.rs:17:1
+   |
+LL | / fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> {
+LL | |     ()
+LL | | }
+   | |_^
+
+error: could not find defining uses
+  --> $DIR/bound_reduction2.rs:10:1
+   |
+LL | existential type Foo<V>: Trait<V>;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/existential_types/cross_crate_ice.rs b/src/test/ui/existential_types/cross_crate_ice.rs
new file mode 100644
index 0000000..c5d5ca9
--- /dev/null
+++ b/src/test/ui/existential_types/cross_crate_ice.rs
@@ -0,0 +1,16 @@
+// aux-build:cross_crate_ice.rs
+// compile-pass
+
+extern crate cross_crate_ice;
+
+struct Bar(cross_crate_ice::Foo);
+
+impl Bar {
+    fn zero(&self) -> &cross_crate_ice::Foo {
+        &self.0
+    }
+}
+
+fn main() {
+    let _ = cross_crate_ice::foo();
+}
diff --git a/src/test/ui/existential_types/cross_crate_ice2.rs b/src/test/ui/existential_types/cross_crate_ice2.rs
new file mode 100644
index 0000000..a0f3933
--- /dev/null
+++ b/src/test/ui/existential_types/cross_crate_ice2.rs
@@ -0,0 +1,11 @@
+// aux-build:cross_crate_ice2.rs
+// compile-pass
+
+extern crate cross_crate_ice2;
+
+use cross_crate_ice2::View;
+
+fn main() {
+    let v = cross_crate_ice2::X;
+    v.test();
+}
diff --git a/src/test/ui/existential_types/declared_but_never_defined.rs b/src/test/ui/existential_types/declared_but_never_defined.rs
new file mode 100644
index 0000000..ff25339
--- /dev/null
+++ b/src/test/ui/existential_types/declared_but_never_defined.rs
@@ -0,0 +1,6 @@
+#![feature(existential_type)]
+
+fn main() {}
+
+// declared but never defined
+existential type Bar: std::fmt::Debug; //~ ERROR could not find defining uses
diff --git a/src/test/ui/existential_types/declared_but_never_defined.stderr b/src/test/ui/existential_types/declared_but_never_defined.stderr
new file mode 100644
index 0000000..7294a07
--- /dev/null
+++ b/src/test/ui/existential_types/declared_but_never_defined.stderr
@@ -0,0 +1,8 @@
+error: could not find defining uses
+  --> $DIR/declared_but_never_defined.rs:6:1
+   |
+LL | existential type Bar: std::fmt::Debug;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/existential_types/declared_but_not_defined_in_scope.rs b/src/test/ui/existential_types/declared_but_not_defined_in_scope.rs
new file mode 100644
index 0000000..a6311ee
--- /dev/null
+++ b/src/test/ui/existential_types/declared_but_not_defined_in_scope.rs
@@ -0,0 +1,12 @@
+#![feature(existential_type)]
+
+fn main() {}
+
+mod boo {
+    // declared in module but not defined inside of it
+    pub existential type Boo: ::std::fmt::Debug; //~ ERROR could not find defining uses
+}
+
+fn bomp() -> boo::Boo {
+    ""
+}
diff --git a/src/test/ui/existential_types/declared_but_not_defined_in_scope.stderr b/src/test/ui/existential_types/declared_but_not_defined_in_scope.stderr
new file mode 100644
index 0000000..a72709f
--- /dev/null
+++ b/src/test/ui/existential_types/declared_but_not_defined_in_scope.stderr
@@ -0,0 +1,8 @@
+error: could not find defining uses
+  --> $DIR/declared_but_not_defined_in_scope.rs:7:5
+   |
+LL |     pub existential type Boo: ::std::fmt::Debug;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/existential_types/different_defining_uses.rs b/src/test/ui/existential_types/different_defining_uses.rs
new file mode 100644
index 0000000..a8670cc
--- /dev/null
+++ b/src/test/ui/existential_types/different_defining_uses.rs
@@ -0,0 +1,14 @@
+#![feature(existential_type)]
+
+fn main() {}
+
+// two definitions with different types
+existential type Foo: std::fmt::Debug;
+
+fn foo() -> Foo {
+    ""
+}
+
+fn bar() -> Foo { //~ ERROR concrete type differs from previous
+    42i32
+}
diff --git a/src/test/ui/existential_types/different_defining_uses.stderr b/src/test/ui/existential_types/different_defining_uses.stderr
new file mode 100644
index 0000000..fddba58
--- /dev/null
+++ b/src/test/ui/existential_types/different_defining_uses.stderr
@@ -0,0 +1,18 @@
+error: concrete type differs from previous defining existential type use
+  --> $DIR/different_defining_uses.rs:12:1
+   |
+LL | / fn bar() -> Foo {
+LL | |     42i32
+LL | | }
+   | |_^ expected `&'static str`, got `i32`
+   |
+note: previous use here
+  --> $DIR/different_defining_uses.rs:8:1
+   |
+LL | / fn foo() -> Foo {
+LL | |     ""
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/existential_types/different_defining_uses_never_type.rs b/src/test/ui/existential_types/different_defining_uses_never_type.rs
new file mode 100644
index 0000000..13ada63
--- /dev/null
+++ b/src/test/ui/existential_types/different_defining_uses_never_type.rs
@@ -0,0 +1,18 @@
+#![feature(existential_type)]
+
+fn main() {}
+
+// two definitions with different types
+existential type Foo: std::fmt::Debug;
+
+fn foo() -> Foo {
+    ""
+}
+
+fn bar() -> Foo { //~ ERROR concrete type differs from previous
+    panic!()
+}
+
+fn boo() -> Foo { //~ ERROR concrete type differs from previous
+    loop {}
+}
diff --git a/src/test/ui/existential_types/different_defining_uses_never_type.stderr b/src/test/ui/existential_types/different_defining_uses_never_type.stderr
new file mode 100644
index 0000000..14b7a81
--- /dev/null
+++ b/src/test/ui/existential_types/different_defining_uses_never_type.stderr
@@ -0,0 +1,34 @@
+error: concrete type differs from previous defining existential type use
+  --> $DIR/different_defining_uses_never_type.rs:12:1
+   |
+LL | / fn bar() -> Foo {
+LL | |     panic!()
+LL | | }
+   | |_^ expected `&'static str`, got `()`
+   |
+note: previous use here
+  --> $DIR/different_defining_uses_never_type.rs:8:1
+   |
+LL | / fn foo() -> Foo {
+LL | |     ""
+LL | | }
+   | |_^
+
+error: concrete type differs from previous defining existential type use
+  --> $DIR/different_defining_uses_never_type.rs:16:1
+   |
+LL | / fn boo() -> Foo {
+LL | |     loop {}
+LL | | }
+   | |_^ expected `&'static str`, got `()`
+   |
+note: previous use here
+  --> $DIR/different_defining_uses_never_type.rs:8:1
+   |
+LL | / fn foo() -> Foo {
+LL | |     ""
+LL | | }
+   | |_^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/existential_types/different_defining_uses_never_type2.rs b/src/test/ui/existential_types/different_defining_uses_never_type2.rs
new file mode 100644
index 0000000..2953f17
--- /dev/null
+++ b/src/test/ui/existential_types/different_defining_uses_never_type2.rs
@@ -0,0 +1,44 @@
+// compile-pass
+
+#![feature(existential_type)]
+
+fn main() {}
+
+// two definitions with different types
+existential type Foo: std::fmt::Debug;
+
+fn foo() -> Foo {
+    ""
+}
+
+fn bar(arg: bool) -> Foo {
+    if arg {
+        panic!()
+    } else {
+        "bar"
+    }
+}
+
+fn boo(arg: bool) -> Foo {
+    if arg {
+        loop {}
+    } else {
+        "boo"
+    }
+}
+
+fn bar2(arg: bool) -> Foo {
+    if arg {
+        "bar2"
+    } else {
+        panic!()
+    }
+}
+
+fn boo2(arg: bool) -> Foo {
+    if arg {
+        "boo2"
+    } else {
+        loop {}
+    }
+}
diff --git a/src/test/ui/existential_types/existential-associated-type.rs b/src/test/ui/existential_types/existential-associated-type.rs
new file mode 100644
index 0000000..299ae91
--- /dev/null
+++ b/src/test/ui/existential_types/existential-associated-type.rs
@@ -0,0 +1,26 @@
+#![feature(existential_type)]
+// compile-pass
+
+trait Bar {}
+struct Dummy;
+impl Bar for Dummy {}
+
+trait Foo {
+    type Assoc: Bar;
+    fn foo() -> Self::Assoc;
+    fn bar() -> Self::Assoc;
+}
+
+existential type Helper: Bar;
+
+impl Foo for i32 {
+    type Assoc = Helper;
+    fn foo() -> Helper {
+        Dummy
+    }
+    fn bar() -> Helper {
+        Dummy
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/existential_types/existential-types-with-cycle-error.rs b/src/test/ui/existential_types/existential-types-with-cycle-error.rs
new file mode 100644
index 0000000..3f01908
--- /dev/null
+++ b/src/test/ui/existential_types/existential-types-with-cycle-error.rs
@@ -0,0 +1,12 @@
+#![feature(existential_type)]
+
+existential type Foo: Fn() -> Foo;
+//~^ ERROR: cycle detected when processing `Foo`
+
+fn crash(x: Foo) -> Foo {
+    x
+}
+
+fn main() {
+
+}
diff --git a/src/test/ui/existential_types/existential-types-with-cycle-error.stderr b/src/test/ui/existential_types/existential-types-with-cycle-error.stderr
new file mode 100644
index 0000000..56057a9
--- /dev/null
+++ b/src/test/ui/existential_types/existential-types-with-cycle-error.stderr
@@ -0,0 +1,30 @@
+error[E0391]: cycle detected when processing `Foo`
+  --> $DIR/existential-types-with-cycle-error.rs:3:1
+   |
+LL | existential type Foo: Fn() -> Foo;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: ...which requires processing `crash`...
+  --> $DIR/existential-types-with-cycle-error.rs:6:25
+   |
+LL |   fn crash(x: Foo) -> Foo {
+   |  _________________________^
+LL | |     x
+LL | | }
+   | |_^
+   = note: ...which again requires processing `Foo`, completing the cycle
+note: cycle used when collecting item types in top-level module
+  --> $DIR/existential-types-with-cycle-error.rs:1:1
+   |
+LL | / #![feature(existential_type)]
+LL | |
+LL | | existential type Foo: Fn() -> Foo;
+LL | |
+...  |
+LL | |
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/existential_types/existential-types-with-cycle-error2.rs b/src/test/ui/existential_types/existential-types-with-cycle-error2.rs
new file mode 100644
index 0000000..2941030
--- /dev/null
+++ b/src/test/ui/existential_types/existential-types-with-cycle-error2.rs
@@ -0,0 +1,16 @@
+#![feature(existential_type)]
+
+pub trait Bar<T> {
+    type Item;
+}
+
+existential type Foo: Bar<Foo, Item = Foo>;
+//~^ ERROR: cycle detected when processing `Foo`
+
+fn crash(x: Foo) -> Foo {
+    x
+}
+
+fn main() {
+
+}
diff --git a/src/test/ui/existential_types/existential-types-with-cycle-error2.stderr b/src/test/ui/existential_types/existential-types-with-cycle-error2.stderr
new file mode 100644
index 0000000..8c7bf52
--- /dev/null
+++ b/src/test/ui/existential_types/existential-types-with-cycle-error2.stderr
@@ -0,0 +1,30 @@
+error[E0391]: cycle detected when processing `Foo`
+  --> $DIR/existential-types-with-cycle-error2.rs:7:1
+   |
+LL | existential type Foo: Bar<Foo, Item = Foo>;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: ...which requires processing `crash`...
+  --> $DIR/existential-types-with-cycle-error2.rs:10:25
+   |
+LL |   fn crash(x: Foo) -> Foo {
+   |  _________________________^
+LL | |     x
+LL | | }
+   | |_^
+   = note: ...which again requires processing `Foo`, completing the cycle
+note: cycle used when collecting item types in top-level module
+  --> $DIR/existential-types-with-cycle-error2.rs:1:1
+   |
+LL | / #![feature(existential_type)]
+LL | |
+LL | | pub trait Bar<T> {
+LL | |     type Item;
+...  |
+LL | |
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/existential_types/generic_different_defining_uses.rs b/src/test/ui/existential_types/generic_different_defining_uses.rs
new file mode 100644
index 0000000..ce3ab88
--- /dev/null
+++ b/src/test/ui/existential_types/generic_different_defining_uses.rs
@@ -0,0 +1,13 @@
+#![feature(existential_type)]
+
+fn main() {}
+
+existential type MyIter<T>: Iterator<Item = T>;
+
+fn my_iter<T>(t: T) -> MyIter<T> {
+    std::iter::once(t)
+}
+
+fn my_iter2<T>(t: T) -> MyIter<T> { //~ ERROR concrete type differs from previous
+    Some(t).into_iter()
+}
diff --git a/src/test/ui/existential_types/generic_different_defining_uses.stderr b/src/test/ui/existential_types/generic_different_defining_uses.stderr
new file mode 100644
index 0000000..e5b1539
--- /dev/null
+++ b/src/test/ui/existential_types/generic_different_defining_uses.stderr
@@ -0,0 +1,18 @@
+error: concrete type differs from previous defining existential type use
+  --> $DIR/generic_different_defining_uses.rs:11:1
+   |
+LL | / fn my_iter2<T>(t: T) -> MyIter<T> {
+LL | |     Some(t).into_iter()
+LL | | }
+   | |_^ expected `std::iter::Once<T>`, got `std::option::IntoIter<T>`
+   |
+note: previous use here
+  --> $DIR/generic_different_defining_uses.rs:7:1
+   |
+LL | / fn my_iter<T>(t: T) -> MyIter<T> {
+LL | |     std::iter::once(t)
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/existential_types/generic_duplicate_lifetime_param.rs b/src/test/ui/existential_types/generic_duplicate_lifetime_param.rs
new file mode 100644
index 0000000..e9943be
--- /dev/null
+++ b/src/test/ui/existential_types/generic_duplicate_lifetime_param.rs
@@ -0,0 +1,9 @@
+#![feature(existential_type)]
+
+fn main() {}
+
+existential type Two<'a, 'b>: std::fmt::Debug;
+
+fn one<'a>(t: &'a ()) -> Two<'a, 'a> { //~ ERROR non-defining existential type use
+    t
+}
diff --git a/src/test/ui/existential_types/generic_duplicate_lifetime_param.stderr b/src/test/ui/existential_types/generic_duplicate_lifetime_param.stderr
new file mode 100644
index 0000000..29bd252
--- /dev/null
+++ b/src/test/ui/existential_types/generic_duplicate_lifetime_param.stderr
@@ -0,0 +1,16 @@
+error: non-defining existential type use in defining scope
+  --> $DIR/generic_duplicate_lifetime_param.rs:7:1
+   |
+LL | / fn one<'a>(t: &'a ()) -> Two<'a, 'a> {
+LL | |     t
+LL | | }
+   | |_^
+   |
+note: lifetime used multiple times
+  --> $DIR/generic_duplicate_lifetime_param.rs:5:22
+   |
+LL | existential type Two<'a, 'b>: std::fmt::Debug;
+   |                      ^^  ^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/existential_types/generic_duplicate_param_use.rs b/src/test/ui/existential_types/generic_duplicate_param_use.rs
new file mode 100644
index 0000000..3f87533
--- /dev/null
+++ b/src/test/ui/existential_types/generic_duplicate_param_use.rs
@@ -0,0 +1,14 @@
+#![feature(existential_type)]
+
+use std::fmt::Debug;
+
+fn main() {}
+
+// test that unused generic parameters are ok
+existential type Two<T, U>: Debug;
+//~^ could not find defining uses
+
+fn one<T: Debug>(t: T) -> Two<T, T> {
+//~^ ERROR defining existential type use restricts existential type
+    t
+}
diff --git a/src/test/ui/existential_types/generic_duplicate_param_use.stderr b/src/test/ui/existential_types/generic_duplicate_param_use.stderr
new file mode 100644
index 0000000..a382794
--- /dev/null
+++ b/src/test/ui/existential_types/generic_duplicate_param_use.stderr
@@ -0,0 +1,17 @@
+error: defining existential type use restricts existential type by using the generic parameter `T` twice
+  --> $DIR/generic_duplicate_param_use.rs:11:1
+   |
+LL | / fn one<T: Debug>(t: T) -> Two<T, T> {
+LL | |
+LL | |     t
+LL | | }
+   | |_^
+
+error: could not find defining uses
+  --> $DIR/generic_duplicate_param_use.rs:8:1
+   |
+LL | existential type Two<T, U>: Debug;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/existential_types/generic_duplicate_param_use10.rs b/src/test/ui/existential_types/generic_duplicate_param_use10.rs
new file mode 100644
index 0000000..10f2c63
--- /dev/null
+++ b/src/test/ui/existential_types/generic_duplicate_param_use10.rs
@@ -0,0 +1,12 @@
+// compile-pass
+#![feature(existential_type)]
+
+use std::fmt::Debug;
+
+fn main() {}
+
+existential type Two<T, U>: Debug;
+
+fn two<T: Debug, U: Debug>(t: T, _: U) -> Two<T, U> {
+    (t, 4u32)
+}
diff --git a/src/test/ui/existential_types/generic_duplicate_param_use2.rs b/src/test/ui/existential_types/generic_duplicate_param_use2.rs
new file mode 100644
index 0000000..3842292
--- /dev/null
+++ b/src/test/ui/existential_types/generic_duplicate_param_use2.rs
@@ -0,0 +1,17 @@
+#![feature(existential_type)]
+
+use std::fmt::Debug;
+
+fn main() {}
+
+// test that unused generic parameters are ok
+existential type Two<T, U>: Debug;
+
+fn one<T: Debug>(t: T) -> Two<T, T> {
+//~^ defining existential type use restricts existential type
+    t
+}
+
+fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> {
+    t
+}
diff --git a/src/test/ui/existential_types/generic_duplicate_param_use2.stderr b/src/test/ui/existential_types/generic_duplicate_param_use2.stderr
new file mode 100644
index 0000000..74f2802
--- /dev/null
+++ b/src/test/ui/existential_types/generic_duplicate_param_use2.stderr
@@ -0,0 +1,11 @@
+error: defining existential type use restricts existential type by using the generic parameter `T` twice
+  --> $DIR/generic_duplicate_param_use2.rs:10:1
+   |
+LL | / fn one<T: Debug>(t: T) -> Two<T, T> {
+LL | |
+LL | |     t
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/existential_types/generic_duplicate_param_use3.rs b/src/test/ui/existential_types/generic_duplicate_param_use3.rs
new file mode 100644
index 0000000..05c77c8
--- /dev/null
+++ b/src/test/ui/existential_types/generic_duplicate_param_use3.rs
@@ -0,0 +1,22 @@
+#![feature(existential_type)]
+
+use std::fmt::Debug;
+
+fn main() {}
+
+// test that unused generic parameters are ok
+existential type Two<T, U>: Debug;
+
+fn one<T: Debug>(t: T) -> Two<T, T> {
+//~^ defining existential type use restricts existential type
+    t
+}
+
+fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> {
+    t
+}
+
+fn three<T, U: Debug>(_: T, u: U) -> Two<T, U> {
+//~^ concrete type's generic parameters differ from previous defining use
+    u
+}
diff --git a/src/test/ui/existential_types/generic_duplicate_param_use3.stderr b/src/test/ui/existential_types/generic_duplicate_param_use3.stderr
new file mode 100644
index 0000000..22d5467
--- /dev/null
+++ b/src/test/ui/existential_types/generic_duplicate_param_use3.stderr
@@ -0,0 +1,28 @@
+error: defining existential type use restricts existential type by using the generic parameter `T` twice
+  --> $DIR/generic_duplicate_param_use3.rs:10:1
+   |
+LL | / fn one<T: Debug>(t: T) -> Two<T, T> {
+LL | |
+LL | |     t
+LL | | }
+   | |_^
+
+error: concrete type's generic parameters differ from previous defining use
+  --> $DIR/generic_duplicate_param_use3.rs:19:1
+   |
+LL | / fn three<T, U: Debug>(_: T, u: U) -> Two<T, U> {
+LL | |
+LL | |     u
+LL | | }
+   | |_^ expected [`T`], got [`U`]
+   |
+note: previous use here
+  --> $DIR/generic_duplicate_param_use3.rs:15:1
+   |
+LL | / fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> {
+LL | |     t
+LL | | }
+   | |_^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/existential_types/generic_duplicate_param_use4.rs b/src/test/ui/existential_types/generic_duplicate_param_use4.rs
new file mode 100644
index 0000000..609dbe0
--- /dev/null
+++ b/src/test/ui/existential_types/generic_duplicate_param_use4.rs
@@ -0,0 +1,17 @@
+#![feature(existential_type)]
+
+use std::fmt::Debug;
+
+fn main() {}
+
+// test that unused generic parameters are ok
+existential type Two<T, U>: Debug;
+
+fn one<T: Debug>(t: T) -> Two<T, T> {
+//~^ ERROR defining existential type use restricts existential type
+    t
+}
+
+fn three<T, U: Debug>(_: T, u: U) -> Two<T, U> {
+    u
+}
diff --git a/src/test/ui/existential_types/generic_duplicate_param_use4.stderr b/src/test/ui/existential_types/generic_duplicate_param_use4.stderr
new file mode 100644
index 0000000..d7e6955
--- /dev/null
+++ b/src/test/ui/existential_types/generic_duplicate_param_use4.stderr
@@ -0,0 +1,11 @@
+error: defining existential type use restricts existential type by using the generic parameter `T` twice
+  --> $DIR/generic_duplicate_param_use4.rs:10:1
+   |
+LL | / fn one<T: Debug>(t: T) -> Two<T, T> {
+LL | |
+LL | |     t
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/existential_types/generic_duplicate_param_use5.rs b/src/test/ui/existential_types/generic_duplicate_param_use5.rs
new file mode 100644
index 0000000..3f4a23b
--- /dev/null
+++ b/src/test/ui/existential_types/generic_duplicate_param_use5.rs
@@ -0,0 +1,17 @@
+#![feature(existential_type)]
+
+use std::fmt::Debug;
+
+fn main() {}
+
+// test that unused generic parameters are ok
+existential type Two<T, U>: Debug;
+
+fn two<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
+    (t, u)
+}
+
+fn three<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
+//~^ concrete type differs from previous
+    (u, t)
+}
diff --git a/src/test/ui/existential_types/generic_duplicate_param_use5.stderr b/src/test/ui/existential_types/generic_duplicate_param_use5.stderr
new file mode 100644
index 0000000..cf4535d
--- /dev/null
+++ b/src/test/ui/existential_types/generic_duplicate_param_use5.stderr
@@ -0,0 +1,19 @@
+error: concrete type differs from previous defining existential type use
+  --> $DIR/generic_duplicate_param_use5.rs:14:1
+   |
+LL | / fn three<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
+LL | |
+LL | |     (u, t)
+LL | | }
+   | |_^ expected `(T, U)`, got `(U, T)`
+   |
+note: previous use here
+  --> $DIR/generic_duplicate_param_use5.rs:10:1
+   |
+LL | / fn two<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
+LL | |     (t, u)
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/existential_types/generic_duplicate_param_use6.rs b/src/test/ui/existential_types/generic_duplicate_param_use6.rs
new file mode 100644
index 0000000..3b8c563
--- /dev/null
+++ b/src/test/ui/existential_types/generic_duplicate_param_use6.rs
@@ -0,0 +1,17 @@
+#![feature(existential_type)]
+
+use std::fmt::Debug;
+
+fn main() {}
+
+// test that unused generic parameters are ok
+existential type Two<T, U>: Debug;
+
+fn two<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
+    (t, t)
+}
+
+fn three<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
+//~^ concrete type differs from previous
+    (u, t)
+}
diff --git a/src/test/ui/existential_types/generic_duplicate_param_use6.stderr b/src/test/ui/existential_types/generic_duplicate_param_use6.stderr
new file mode 100644
index 0000000..1f767da
--- /dev/null
+++ b/src/test/ui/existential_types/generic_duplicate_param_use6.stderr
@@ -0,0 +1,19 @@
+error: concrete type differs from previous defining existential type use
+  --> $DIR/generic_duplicate_param_use6.rs:14:1
+   |
+LL | / fn three<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
+LL | |
+LL | |     (u, t)
+LL | | }
+   | |_^ expected `(T, T)`, got `(U, T)`
+   |
+note: previous use here
+  --> $DIR/generic_duplicate_param_use6.rs:10:1
+   |
+LL | / fn two<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
+LL | |     (t, t)
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/existential_types/generic_duplicate_param_use7.rs b/src/test/ui/existential_types/generic_duplicate_param_use7.rs
new file mode 100644
index 0000000..2bcac31
--- /dev/null
+++ b/src/test/ui/existential_types/generic_duplicate_param_use7.rs
@@ -0,0 +1,25 @@
+// compile-pass
+#![feature(existential_type)]
+
+use std::fmt::Debug;
+
+fn main() {}
+
+existential type Two<A, B>: Debug;
+
+fn two<T: Debug + Copy, U>(t: T, u: U) -> Two<T, U> {
+    (t, t)
+}
+
+fn three<T: Debug, U>(t: T, t2: T, u: U) -> Two<T, U> {
+    (t, t2)
+}
+
+fn four<T: Debug, U, V>(t: T, t2: T, u: U, v: V) -> Two<T, U> {
+    (t, t2)
+}
+
+fn five<X, Y: Debug>(x: X, y: Y, y2: Y) -> Two<Y, X> {
+    (y, y2)
+}
+
diff --git a/src/test/ui/existential_types/generic_duplicate_param_use8.rs b/src/test/ui/existential_types/generic_duplicate_param_use8.rs
new file mode 100644
index 0000000..83501ad
--- /dev/null
+++ b/src/test/ui/existential_types/generic_duplicate_param_use8.rs
@@ -0,0 +1,16 @@
+#![feature(existential_type)]
+
+use std::fmt::Debug;
+
+fn main() {}
+
+existential type Two<T, U>: Debug;
+
+fn two<T: Debug, U: Debug>(t: T, _: U) -> Two<T, U> {
+    (t, 4u32)
+}
+
+fn three<T: Debug, U: Debug>(_: T, u: U) -> Two<T, U> {
+//~^ concrete type differs from previous
+    (u, 4u32)
+}
diff --git a/src/test/ui/existential_types/generic_duplicate_param_use8.stderr b/src/test/ui/existential_types/generic_duplicate_param_use8.stderr
new file mode 100644
index 0000000..58f4f97b
--- /dev/null
+++ b/src/test/ui/existential_types/generic_duplicate_param_use8.stderr
@@ -0,0 +1,19 @@
+error: concrete type differs from previous defining existential type use
+  --> $DIR/generic_duplicate_param_use8.rs:13:1
+   |
+LL | / fn three<T: Debug, U: Debug>(_: T, u: U) -> Two<T, U> {
+LL | |
+LL | |     (u, 4u32)
+LL | | }
+   | |_^ expected `(T, u32)`, got `(U, u32)`
+   |
+note: previous use here
+  --> $DIR/generic_duplicate_param_use8.rs:9:1
+   |
+LL | / fn two<T: Debug, U: Debug>(t: T, _: U) -> Two<T, U> {
+LL | |     (t, 4u32)
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/existential_types/generic_duplicate_param_use9.rs b/src/test/ui/existential_types/generic_duplicate_param_use9.rs
new file mode 100644
index 0000000..4c68972
--- /dev/null
+++ b/src/test/ui/existential_types/generic_duplicate_param_use9.rs
@@ -0,0 +1,20 @@
+#![feature(existential_type)]
+
+use std::fmt::Debug;
+
+fn main() {}
+
+existential type Two<A, B>: Debug;
+
+trait Foo {
+    type Bar: Debug;
+    const BAR: Self::Bar;
+}
+
+fn two<T: Debug + Foo, U: Debug>(t: T, u: U) -> Two<T, U> {
+    (t, u, T::BAR)
+}
+
+fn three<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
+    (t, u, 42) //~^ ERROR concrete type differs from previous
+}
diff --git a/src/test/ui/existential_types/generic_duplicate_param_use9.stderr b/src/test/ui/existential_types/generic_duplicate_param_use9.stderr
new file mode 100644
index 0000000..fe4ae6c
--- /dev/null
+++ b/src/test/ui/existential_types/generic_duplicate_param_use9.stderr
@@ -0,0 +1,18 @@
+error: concrete type differs from previous defining existential type use
+  --> $DIR/generic_duplicate_param_use9.rs:18:1
+   |
+LL | / fn three<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
+LL | |     (t, u, 42)
+LL | | }
+   | |_^ expected `(A, B, <A as Foo>::Bar)`, got `(A, B, i32)`
+   |
+note: previous use here
+  --> $DIR/generic_duplicate_param_use9.rs:14:1
+   |
+LL | / fn two<T: Debug + Foo, U: Debug>(t: T, u: U) -> Two<T, U> {
+LL | |     (t, u, T::BAR)
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/existential_types/generic_lifetime_param.rs b/src/test/ui/existential_types/generic_lifetime_param.rs
new file mode 100644
index 0000000..a8bb022
--- /dev/null
+++ b/src/test/ui/existential_types/generic_lifetime_param.rs
@@ -0,0 +1,11 @@
+// compile-pass
+
+#![feature(existential_type)]
+
+fn main() {}
+
+existential type Region<'a>: std::fmt::Debug;
+
+fn region<'b>(a: &'b ()) -> Region<'b> {
+    a
+}
diff --git a/src/test/ui/existential_types/generic_nondefining_use.rs b/src/test/ui/existential_types/generic_nondefining_use.rs
new file mode 100644
index 0000000..75af5d9
--- /dev/null
+++ b/src/test/ui/existential_types/generic_nondefining_use.rs
@@ -0,0 +1,11 @@
+#![feature(existential_type)]
+
+fn main() {}
+
+existential type Cmp<T>: 'static;
+//~^ ERROR could not find defining uses
+
+// not a defining use, because it doesn't define *all* possible generics
+fn cmp() -> Cmp<u32> { //~ ERROR defining existential type use does not fully define
+    5u32
+}
diff --git a/src/test/ui/existential_types/generic_nondefining_use.stderr b/src/test/ui/existential_types/generic_nondefining_use.stderr
new file mode 100644
index 0000000..ef57926
--- /dev/null
+++ b/src/test/ui/existential_types/generic_nondefining_use.stderr
@@ -0,0 +1,16 @@
+error: defining existential type use does not fully define existential type
+  --> $DIR/generic_nondefining_use.rs:9:1
+   |
+LL | / fn cmp() -> Cmp<u32> {
+LL | |     5u32
+LL | | }
+   | |_^
+
+error: could not find defining uses
+  --> $DIR/generic_nondefining_use.rs:5:1
+   |
+LL | existential type Cmp<T>: 'static;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/existential_types/generic_not_used.rs b/src/test/ui/existential_types/generic_not_used.rs
new file mode 100644
index 0000000..bfe7b8c
--- /dev/null
+++ b/src/test/ui/existential_types/generic_not_used.rs
@@ -0,0 +1,10 @@
+#![feature(existential_type)]
+
+fn main() {}
+
+existential type WrongGeneric<T: 'static>: 'static;
+
+fn wrong_generic<U: 'static, V: 'static>(_: U, v: V) -> WrongGeneric<U> {
+//~^ ERROR type parameter `V` is part of concrete type but not used in parameter list
+    v
+}
diff --git a/src/test/ui/existential_types/generic_not_used.stderr b/src/test/ui/existential_types/generic_not_used.stderr
new file mode 100644
index 0000000..1ae4ab6
--- /dev/null
+++ b/src/test/ui/existential_types/generic_not_used.stderr
@@ -0,0 +1,12 @@
+error: type parameter `V` is part of concrete type but not used in parameter list for existential type
+  --> $DIR/generic_not_used.rs:7:73
+   |
+LL |   fn wrong_generic<U: 'static, V: 'static>(_: U, v: V) -> WrongGeneric<U> {
+   |  _________________________________________________________________________^
+LL | |
+LL | |     v
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/existential_types/generic_type_does_not_live_long_enough.rs b/src/test/ui/existential_types/generic_type_does_not_live_long_enough.rs
new file mode 100644
index 0000000..02bb151
--- /dev/null
+++ b/src/test/ui/existential_types/generic_type_does_not_live_long_enough.rs
@@ -0,0 +1,14 @@
+#![feature(existential_type)]
+
+fn main() {
+    let y = 42;
+    let x = wrong_generic(&y);
+    let z: i32 = x; //~ ERROR mismatched types
+}
+
+existential type WrongGeneric<T>: 'static;
+//~^ ERROR the parameter type `T` may not live long enough
+
+fn wrong_generic<T>(t: T) -> WrongGeneric<T> {
+    t
+}
diff --git a/src/test/ui/existential_types/generic_type_does_not_live_long_enough.stderr b/src/test/ui/existential_types/generic_type_does_not_live_long_enough.stderr
new file mode 100644
index 0000000..e3e5481
--- /dev/null
+++ b/src/test/ui/existential_types/generic_type_does_not_live_long_enough.stderr
@@ -0,0 +1,28 @@
+error[E0308]: mismatched types
+  --> $DIR/generic_type_does_not_live_long_enough.rs:6:18
+   |
+LL |     let z: i32 = x;
+   |                  ^ expected i32, found opaque type
+   |
+   = note: expected type `i32`
+              found type `WrongGeneric::<&{integer}>`
+
+error[E0310]: the parameter type `T` may not live long enough
+  --> $DIR/generic_type_does_not_live_long_enough.rs:9:1
+   |
+LL | existential type WrongGeneric<T>: 'static;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn wrong_generic<T>(t: T) -> WrongGeneric<T> {
+   |                  - help: consider adding an explicit lifetime bound `T: 'static`...
+   |
+note: ...so that the type `T` will meet its required lifetime bounds
+  --> $DIR/generic_type_does_not_live_long_enough.rs:9:1
+   |
+LL | existential type WrongGeneric<T>: 'static;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0308, E0310.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/existential_types/generic_underconstrained.rs b/src/test/ui/existential_types/generic_underconstrained.rs
new file mode 100644
index 0000000..967faca
--- /dev/null
+++ b/src/test/ui/existential_types/generic_underconstrained.rs
@@ -0,0 +1,11 @@
+#![feature(existential_type)]
+
+fn main() {}
+
+trait Trait {}
+existential type Underconstrained<T: Trait>: 'static; //~ ERROR the trait bound `T: Trait`
+
+// no `Trait` bound
+fn underconstrain<T>(_: T) -> Underconstrained<T> {
+    unimplemented!()
+}
diff --git a/src/test/ui/existential_types/generic_underconstrained.stderr b/src/test/ui/existential_types/generic_underconstrained.stderr
new file mode 100644
index 0000000..8551a93
--- /dev/null
+++ b/src/test/ui/existential_types/generic_underconstrained.stderr
@@ -0,0 +1,12 @@
+error[E0277]: the trait bound `T: Trait` is not satisfied
+  --> $DIR/generic_underconstrained.rs:6:1
+   |
+LL | existential type Underconstrained<T: Trait>: 'static;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `T`
+   |
+   = help: consider adding a `where T: Trait` bound
+   = note: the return type of a function must have a statically known size
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/existential_types/generic_underconstrained2.rs b/src/test/ui/existential_types/generic_underconstrained2.rs
new file mode 100644
index 0000000..98d9da8
--- /dev/null
+++ b/src/test/ui/existential_types/generic_underconstrained2.rs
@@ -0,0 +1,19 @@
+#![feature(existential_type)]
+
+fn main() {}
+
+existential type Underconstrained<T: std::fmt::Debug>: 'static;
+//~^ ERROR `U` doesn't implement `std::fmt::Debug`
+
+// not a defining use, because it doesn't define *all* possible generics
+fn underconstrained<U>(_: U) -> Underconstrained<U> {
+    5u32
+}
+
+existential type Underconstrained2<T: std::fmt::Debug>: 'static;
+//~^ ERROR `V` doesn't implement `std::fmt::Debug`
+
+// not a defining use, because it doesn't define *all* possible generics
+fn underconstrained2<U, V>(_: U, _: V) -> Underconstrained2<V> {
+    5u32
+}
diff --git a/src/test/ui/existential_types/generic_underconstrained2.stderr b/src/test/ui/existential_types/generic_underconstrained2.stderr
new file mode 100644
index 0000000..c7b6d6a
--- /dev/null
+++ b/src/test/ui/existential_types/generic_underconstrained2.stderr
@@ -0,0 +1,23 @@
+error[E0277]: `U` doesn't implement `std::fmt::Debug`
+  --> $DIR/generic_underconstrained2.rs:5:1
+   |
+LL | existential type Underconstrained<T: std::fmt::Debug>: 'static;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug`
+   |
+   = help: the trait `std::fmt::Debug` is not implemented for `U`
+   = help: consider adding a `where U: std::fmt::Debug` bound
+   = note: the return type of a function must have a statically known size
+
+error[E0277]: `V` doesn't implement `std::fmt::Debug`
+  --> $DIR/generic_underconstrained2.rs:13:1
+   |
+LL | existential type Underconstrained2<T: std::fmt::Debug>: 'static;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `V` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug`
+   |
+   = help: the trait `std::fmt::Debug` is not implemented for `V`
+   = help: consider adding a `where V: std::fmt::Debug` bound
+   = note: the return type of a function must have a statically known size
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/existential_types/nested_existential_types.rs b/src/test/ui/existential_types/nested_existential_types.rs
new file mode 100644
index 0000000..62a4779
--- /dev/null
+++ b/src/test/ui/existential_types/nested_existential_types.rs
@@ -0,0 +1,21 @@
+#![feature(existential_type)]
+// compile-pass
+mod my_mod {
+  use std::fmt::Debug;
+
+  pub existential type Foo: Debug;
+  pub existential type Foot: Debug;
+
+  pub fn get_foo() -> Foo {
+      5i32
+  }
+
+  pub fn get_foot() -> Foot {
+      get_foo()
+  }
+}
+
+fn main() {
+    let _: my_mod::Foot = my_mod::get_foot();
+}
+
diff --git a/src/test/ui/existential_types/never_reveal_concrete_type.rs b/src/test/ui/existential_types/never_reveal_concrete_type.rs
new file mode 100644
index 0000000..04da394
--- /dev/null
+++ b/src/test/ui/existential_types/never_reveal_concrete_type.rs
@@ -0,0 +1,15 @@
+#![feature(existential_type)]
+
+fn main() {}
+
+// don't reveal the concrete type
+existential type NoReveal: std::fmt::Debug;
+
+fn define_no_reveal() -> NoReveal {
+    ""
+}
+
+fn no_reveal(x: NoReveal) {
+    let _: &'static str = x; //~ mismatched types
+    let _ = x as &'static str; //~ non-primitive cast
+}
diff --git a/src/test/ui/existential_types/never_reveal_concrete_type.stderr b/src/test/ui/existential_types/never_reveal_concrete_type.stderr
new file mode 100644
index 0000000..81b6584
--- /dev/null
+++ b/src/test/ui/existential_types/never_reveal_concrete_type.stderr
@@ -0,0 +1,21 @@
+error[E0308]: mismatched types
+  --> $DIR/never_reveal_concrete_type.rs:13:27
+   |
+LL |     let _: &'static str = x;
+   |                           ^ expected reference, found opaque type
+   |
+   = note: expected type `&'static str`
+              found type `NoReveal`
+
+error[E0605]: non-primitive cast: `NoReveal` as `&'static str`
+  --> $DIR/never_reveal_concrete_type.rs:14:13
+   |
+LL |     let _ = x as &'static str;
+   |             ^^^^^^^^^^^^^^^^^
+   |
+   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0308, E0605.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/existential_types/no_inferrable_concrete_type.rs b/src/test/ui/existential_types/no_inferrable_concrete_type.rs
new file mode 100644
index 0000000..6bbe8bd
--- /dev/null
+++ b/src/test/ui/existential_types/no_inferrable_concrete_type.rs
@@ -0,0 +1,13 @@
+// Issue 52985: Cause cycle error if user code provides no use case that allows an existential type
+// to be inferred to a concrete type. This results in an infinite cycle during type normalization.
+
+#![feature(existential_type)]
+
+existential type Foo: Copy; //~ cycle detected
+
+// make compiler happy about using 'Foo'
+fn bar(x: Foo) -> Foo { x }
+
+fn main() {
+    let _: Foo = std::mem::transmute(0u8);
+}
diff --git a/src/test/ui/existential_types/no_inferrable_concrete_type.stderr b/src/test/ui/existential_types/no_inferrable_concrete_type.stderr
new file mode 100644
index 0000000..4605332
--- /dev/null
+++ b/src/test/ui/existential_types/no_inferrable_concrete_type.stderr
@@ -0,0 +1,27 @@
+error[E0391]: cycle detected when processing `Foo`
+  --> $DIR/no_inferrable_concrete_type.rs:6:1
+   |
+LL | existential type Foo: Copy;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: ...which requires processing `bar`...
+  --> $DIR/no_inferrable_concrete_type.rs:9:23
+   |
+LL | fn bar(x: Foo) -> Foo { x }
+   |                       ^^^^^
+   = note: ...which again requires processing `Foo`, completing the cycle
+note: cycle used when collecting item types in top-level module
+  --> $DIR/no_inferrable_concrete_type.rs:4:1
+   |
+LL | / #![feature(existential_type)]
+LL | |
+LL | | existential type Foo: Copy;
+LL | |
+...  |
+LL | |     let _: Foo = std::mem::transmute(0u8);
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/existential_types/no_revealing_outside_defining_module.rs b/src/test/ui/existential_types/no_revealing_outside_defining_module.rs
new file mode 100644
index 0000000..142f2f6
--- /dev/null
+++ b/src/test/ui/existential_types/no_revealing_outside_defining_module.rs
@@ -0,0 +1,24 @@
+#![feature(existential_type)]
+
+fn main() {}
+
+mod boo {
+    pub existential type Boo: ::std::fmt::Debug;
+    fn bomp() -> Boo {
+        ""
+    }
+}
+
+// don't actually know the type here
+
+fn bomp2() {
+    let _: &str = bomp(); //~ ERROR mismatched types
+}
+
+fn bomp() -> boo::Boo {
+    "" //~ ERROR mismatched types
+}
+
+fn bomp_loop() -> boo::Boo {
+    loop {}
+}
diff --git a/src/test/ui/existential_types/no_revealing_outside_defining_module.stderr b/src/test/ui/existential_types/no_revealing_outside_defining_module.stderr
new file mode 100644
index 0000000..5e58269
--- /dev/null
+++ b/src/test/ui/existential_types/no_revealing_outside_defining_module.stderr
@@ -0,0 +1,23 @@
+error[E0308]: mismatched types
+  --> $DIR/no_revealing_outside_defining_module.rs:15:19
+   |
+LL |     let _: &str = bomp();
+   |                   ^^^^^^ expected &str, found opaque type
+   |
+   = note: expected type `&str`
+              found type `Boo`
+
+error[E0308]: mismatched types
+  --> $DIR/no_revealing_outside_defining_module.rs:19:5
+   |
+LL | fn bomp() -> boo::Boo {
+   |              -------- expected `Boo` because of return type
+LL |     ""
+   |     ^^ expected opaque type, found reference
+   |
+   = note: expected type `Boo`
+              found type `&'static str`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/existential_types/not_a_defining_use.rs b/src/test/ui/existential_types/not_a_defining_use.rs
new file mode 100644
index 0000000..3f81f51
--- /dev/null
+++ b/src/test/ui/existential_types/not_a_defining_use.rs
@@ -0,0 +1,40 @@
+#![feature(existential_type)]
+
+use std::fmt::Debug;
+
+fn main() {}
+
+existential type Two<T, U>: Debug;
+
+fn two<T: Debug>(t: T) -> Two<T, u32> {
+    //~^ ERROR defining existential type use does not fully define existential type
+    (t, 4i8)
+}
+
+fn three<T: Debug, U>(t: T) -> Two<T, U> {
+    (t, 5i8)
+}
+
+trait Bar {
+    type Blub: Debug;
+    const FOO: Self::Blub;
+}
+
+impl Bar for u32 {
+    type Blub = i32;
+    const FOO: i32 = 42;
+}
+
+// this should work! But it requires `two` and `three` not to be defining uses,
+// just restricting uses
+fn four<T: Debug, U: Bar>(t: T) -> Two<T, U> { //~ concrete type differs from previous
+    (t, <U as Bar>::FOO)
+}
+
+fn is_sync<T: Sync>() {}
+
+fn asdfl() {
+    //FIXME(oli-obk): these currently cause cycle errors
+    //is_sync::<Two<i32, u32>>();
+    //is_sync::<Two<i32, *const i32>>();
+}
diff --git a/src/test/ui/existential_types/not_a_defining_use.stderr b/src/test/ui/existential_types/not_a_defining_use.stderr
new file mode 100644
index 0000000..f315811
--- /dev/null
+++ b/src/test/ui/existential_types/not_a_defining_use.stderr
@@ -0,0 +1,27 @@
+error: defining existential type use does not fully define existential type
+  --> $DIR/not_a_defining_use.rs:9:1
+   |
+LL | / fn two<T: Debug>(t: T) -> Two<T, u32> {
+LL | |
+LL | |     (t, 4i8)
+LL | | }
+   | |_^
+
+error: concrete type differs from previous defining existential type use
+  --> $DIR/not_a_defining_use.rs:30:1
+   |
+LL | / fn four<T: Debug, U: Bar>(t: T) -> Two<T, U> {
+LL | |     (t, <U as Bar>::FOO)
+LL | | }
+   | |_^ expected `(T, i8)`, got `(T, <U as Bar>::Blub)`
+   |
+note: previous use here
+  --> $DIR/not_a_defining_use.rs:14:1
+   |
+LL | / fn three<T: Debug, U>(t: T) -> Two<T, U> {
+LL | |     (t, 5i8)
+LL | | }
+   | |_^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/existential_types/not_well_formed.rs b/src/test/ui/existential_types/not_well_formed.rs
new file mode 100644
index 0000000..073fa90
--- /dev/null
+++ b/src/test/ui/existential_types/not_well_formed.rs
@@ -0,0 +1,18 @@
+#![feature(existential_type)]
+
+fn main() {
+}
+
+trait TraitWithAssoc {
+    type Assoc;
+}
+
+existential type Foo<V>: Trait<V::Assoc>; //~ associated type `Assoc` not found for `V`
+
+trait Trait<U> {}
+
+impl<W> Trait<W> for () {}
+
+fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T> {
+    ()
+}
diff --git a/src/test/ui/existential_types/not_well_formed.stderr b/src/test/ui/existential_types/not_well_formed.stderr
new file mode 100644
index 0000000..05f84d5
--- /dev/null
+++ b/src/test/ui/existential_types/not_well_formed.stderr
@@ -0,0 +1,9 @@
+error[E0220]: associated type `Assoc` not found for `V`
+  --> $DIR/not_well_formed.rs:10:32
+   |
+LL | existential type Foo<V>: Trait<V::Assoc>;
+   |                                ^^^^^^^^ associated type `Assoc` not found
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0220`.
diff --git a/src/test/ui/existential_types/private_unused.rs b/src/test/ui/existential_types/private_unused.rs
new file mode 100644
index 0000000..736d812
--- /dev/null
+++ b/src/test/ui/existential_types/private_unused.rs
@@ -0,0 +1,13 @@
+// compile-pass
+
+#[deny(warnings)]
+
+enum Empty { }
+trait Bar<T> {}
+impl Bar<Empty> for () {}
+
+fn boo() -> impl Bar<Empty> {}
+
+fn main() {
+    boo();
+}
diff --git a/src/test/ui/existential_types/unused_generic_param.rs b/src/test/ui/existential_types/unused_generic_param.rs
new file mode 100644
index 0000000..7af6508
--- /dev/null
+++ b/src/test/ui/existential_types/unused_generic_param.rs
@@ -0,0 +1,23 @@
+// compile-pass
+#![feature(existential_type)]
+
+fn main() {
+}
+
+// test that unused generic parameters are ok
+existential type PartiallyDefined<T>: 'static;
+
+fn partially_defined<T: std::fmt::Debug>(_: T) -> PartiallyDefined<T> {
+    4u32
+}
+
+// test that unused generic parameters are ok
+existential type PartiallyDefined2<T>: 'static;
+
+fn partially_defined2<T: std::fmt::Debug>(_: T) -> PartiallyDefined2<T> {
+    4u32
+}
+
+fn partially_defined22<T>(_: T) -> PartiallyDefined2<T> {
+    4u32
+}
diff --git a/src/test/ui/expanded-cfg.rs b/src/test/ui/expanded-cfg.rs
new file mode 100644
index 0000000..fbae093
--- /dev/null
+++ b/src/test/ui/expanded-cfg.rs
@@ -0,0 +1,23 @@
+// skip-codegen
+// compile-pass
+#![feature(custom_attribute)]
+macro_rules! mac {
+    {} => {
+        #[cfg(attr)]
+        mod m {
+            #[lang_item]
+            fn f() {}
+
+            #[cfg_attr(target_thread_local, custom)]
+            fn g() {}
+        }
+
+        #[cfg(attr)]
+        unconfigured_invocation!();
+    }
+}
+
+mac! {}
+
+
+fn main() {}
diff --git a/src/test/ui/explain.rs b/src/test/ui/explain.rs
new file mode 100644
index 0000000..3622ba7
--- /dev/null
+++ b/src/test/ui/explain.rs
@@ -0,0 +1,2 @@
+// compile-flags: --explain E0591
+// compile-pass
diff --git a/src/test/ui/explain.stdout b/src/test/ui/explain.stdout
new file mode 100644
index 0000000..411cdfb
--- /dev/null
+++ b/src/test/ui/explain.stdout
@@ -0,0 +1,63 @@
+Per [RFC 401][rfc401], if you have a function declaration `foo`:
+
+```
+// For the purposes of this explanation, all of these
+// different kinds of `fn` declarations are equivalent:
+struct S;
+fn foo(x: S) { /* ... */ }
+extern "C" { fn foo(x: S); }
+impl S { fn foo(self) { /* ... */ } }
+```
+
+the type of `foo` is **not** `fn(S)`, as one might expect.
+Rather, it is a unique, zero-sized marker type written here as `typeof(foo)`.
+However, `typeof(foo)` can be _coerced_ to a function pointer `fn(S)`,
+so you rarely notice this:
+
+```
+let x: fn(S) = foo; // OK, coerces
+```
+
+The reason that this matter is that the type `fn(S)` is not specific to
+any particular function: it's a function _pointer_. So calling `x()` results
+in a virtual call, whereas `foo()` is statically dispatched, because the type
+of `foo` tells us precisely what function is being called.
+
+As noted above, coercions mean that most code doesn't have to be
+concerned with this distinction. However, you can tell the difference
+when using **transmute** to convert a fn item into a fn pointer.
+
+This is sometimes done as part of an FFI:
+
+```
+extern "C" fn foo(userdata: Box<i32>) {
+    /* ... */
+}
+
+let f: extern "C" fn(*mut i32) = transmute(foo);
+callback(f);
+```
+
+Here, transmute is being used to convert the types of the fn arguments.
+This pattern is incorrect because, because the type of `foo` is a function
+**item** (`typeof(foo)`), which is zero-sized, and the target type (`fn()`)
+is a function pointer, which is not zero-sized.
+This pattern should be rewritten. There are a few possible ways to do this:
+
+- change the original fn declaration to match the expected signature,
+  and do the cast in the fn body (the preferred option)
+- cast the fn item fo a fn pointer before calling transmute, as shown here:
+
+    ```
+    let f: extern "C" fn(*mut i32) = transmute(foo as extern "C" fn(_));
+    let f: extern "C" fn(*mut i32) = transmute(foo as usize); // works too
+    ```
+
+The same applies to transmutes to `*mut fn()`, which were observedin practice.
+Note though that use of this type is generally incorrect.
+The intention is typically to describe a function pointer, but just `fn()`
+alone suffices for that. `*mut fn()` is a pointer to a fn pointer.
+(Since these values are typically just passed to C code, however, this rarely
+makes a difference in practice.)
+
+[rfc401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md
diff --git a/src/test/ui/explicit/explicit-call-to-dtor.rs b/src/test/ui/explicit/explicit-call-to-dtor.rs
new file mode 100644
index 0000000..a6f9acc
--- /dev/null
+++ b/src/test/ui/explicit/explicit-call-to-dtor.rs
@@ -0,0 +1,14 @@
+struct Foo {
+    x: isize
+}
+
+impl Drop for Foo {
+    fn drop(&mut self) {
+        println!("kaboom");
+    }
+}
+
+fn main() {
+    let x = Foo { x: 3 };
+    x.drop();   //~ ERROR explicit use of destructor method
+}
diff --git a/src/test/ui/explicit/explicit-call-to-dtor.stderr b/src/test/ui/explicit/explicit-call-to-dtor.stderr
new file mode 100644
index 0000000..cbbe967
--- /dev/null
+++ b/src/test/ui/explicit/explicit-call-to-dtor.stderr
@@ -0,0 +1,9 @@
+error[E0040]: explicit use of destructor method
+  --> $DIR/explicit-call-to-dtor.rs:13:7
+   |
+LL |     x.drop();
+   |       ^^^^ explicit destructor calls not allowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0040`.
diff --git a/src/test/ui/explicit/explicit-call-to-supertrait-dtor.rs b/src/test/ui/explicit/explicit-call-to-supertrait-dtor.rs
new file mode 100644
index 0000000..ff56b9a
--- /dev/null
+++ b/src/test/ui/explicit/explicit-call-to-supertrait-dtor.rs
@@ -0,0 +1,23 @@
+struct Foo {
+    x: isize
+}
+
+trait Bar : Drop {
+    fn blah(&self);
+}
+
+impl Drop for Foo {
+    fn drop(&mut self) {
+        println!("kaboom");
+    }
+}
+
+impl Bar for Foo {
+    fn blah(&self) {
+        self.drop();    //~ ERROR explicit use of destructor method
+    }
+}
+
+fn main() {
+    let x = Foo { x: 3 };
+}
diff --git a/src/test/ui/explicit/explicit-call-to-supertrait-dtor.stderr b/src/test/ui/explicit/explicit-call-to-supertrait-dtor.stderr
new file mode 100644
index 0000000..0b302e3
--- /dev/null
+++ b/src/test/ui/explicit/explicit-call-to-supertrait-dtor.stderr
@@ -0,0 +1,9 @@
+error[E0040]: explicit use of destructor method
+  --> $DIR/explicit-call-to-supertrait-dtor.rs:17:14
+   |
+LL |         self.drop();
+   |              ^^^^ explicit destructor calls not allowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0040`.
diff --git a/src/test/ui/explicit/explicit-self-lifetime-mismatch.rs b/src/test/ui/explicit/explicit-self-lifetime-mismatch.rs
new file mode 100644
index 0000000..82c64bc
--- /dev/null
+++ b/src/test/ui/explicit/explicit-self-lifetime-mismatch.rs
@@ -0,0 +1,20 @@
+struct Foo<'a,'b> {
+    x: &'a isize,
+    y: &'b isize,
+}
+
+impl<'a,'b> Foo<'a,'b> {
+    fn bar(self:
+           Foo<'b,'a>
+    //~^ ERROR mismatched method receiver
+    //~| expected type `Foo<'a, 'b>`
+    //~| found type `Foo<'b, 'a>`
+    //~| lifetime mismatch
+    //~| ERROR mismatched method receiver
+    //~| expected type `Foo<'a, 'b>`
+    //~| found type `Foo<'b, 'a>`
+    //~| lifetime mismatch
+           ) {}
+}
+
+fn main() {}
diff --git a/src/test/ui/explicit/explicit-self-lifetime-mismatch.stderr b/src/test/ui/explicit/explicit-self-lifetime-mismatch.stderr
new file mode 100644
index 0000000..e6f9ede
--- /dev/null
+++ b/src/test/ui/explicit/explicit-self-lifetime-mismatch.stderr
@@ -0,0 +1,41 @@
+error[E0308]: mismatched method receiver
+  --> $DIR/explicit-self-lifetime-mismatch.rs:8:12
+   |
+LL |            Foo<'b,'a>
+   |            ^^^^^^^^^^ lifetime mismatch
+   |
+   = note: expected type `Foo<'a, 'b>`
+              found type `Foo<'b, 'a>`
+note: the lifetime 'b as defined on the impl at 6:9...
+  --> $DIR/explicit-self-lifetime-mismatch.rs:6:9
+   |
+LL | impl<'a,'b> Foo<'a,'b> {
+   |         ^^
+note: ...does not necessarily outlive the lifetime 'a as defined on the impl at 6:6
+  --> $DIR/explicit-self-lifetime-mismatch.rs:6:6
+   |
+LL | impl<'a,'b> Foo<'a,'b> {
+   |      ^^
+
+error[E0308]: mismatched method receiver
+  --> $DIR/explicit-self-lifetime-mismatch.rs:8:12
+   |
+LL |            Foo<'b,'a>
+   |            ^^^^^^^^^^ lifetime mismatch
+   |
+   = note: expected type `Foo<'a, 'b>`
+              found type `Foo<'b, 'a>`
+note: the lifetime 'a as defined on the impl at 6:6...
+  --> $DIR/explicit-self-lifetime-mismatch.rs:6:6
+   |
+LL | impl<'a,'b> Foo<'a,'b> {
+   |      ^^
+note: ...does not necessarily outlive the lifetime 'b as defined on the impl at 6:9
+  --> $DIR/explicit-self-lifetime-mismatch.rs:6:9
+   |
+LL | impl<'a,'b> Foo<'a,'b> {
+   |         ^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/explore-issue-38412.rs b/src/test/ui/explore-issue-38412.rs
new file mode 100644
index 0000000..e7bcd7c
--- /dev/null
+++ b/src/test/ui/explore-issue-38412.rs
@@ -0,0 +1,66 @@
+// aux-build:pub-and-stability.rs
+
+#![feature(unused_feature)]
+
+// A big point of this test is that we *declare* `unstable_declared`,
+// but do *not* declare `unstable_undeclared`. This way we can check
+// that the compiler is letting in uses of declared feature-gated
+// stuff but still rejecting uses of undeclared feature-gated stuff.
+#![feature(unstable_declared)]
+
+extern crate pub_and_stability;
+use pub_and_stability::{Record, Trait, Tuple};
+
+fn main() {
+    // Okay
+    let Record { .. } = Record::new();
+
+    // Okay
+    let Record { a_stable_pub: _, a_unstable_declared_pub: _, .. } = Record::new();
+
+    let Record { a_stable_pub: _, a_unstable_declared_pub: _, a_unstable_undeclared_pub: _, .. } =
+        Record::new();
+    //~^^ ERROR use of unstable library feature 'unstable_undeclared'
+
+    let r = Record::new();
+    let t = Tuple::new();
+
+    r.a_stable_pub;
+    r.a_unstable_declared_pub;
+    r.a_unstable_undeclared_pub; //~ ERROR use of unstable library feature
+    r.b_crate;                   //~ ERROR is private
+    r.c_mod;                     //~ ERROR is private
+    r.d_priv;                    //~ ERROR is private
+
+    t.0;
+    t.1;
+    t.2;                         //~ ERROR use of unstable library feature
+    t.3;                         //~ ERROR is private
+    t.4;                         //~ ERROR is private
+    t.5;                         //~ ERROR is private
+
+    r.stable_trait_method();
+    r.unstable_declared_trait_method();
+    r.unstable_undeclared_trait_method(); //~ ERROR use of unstable library feature
+
+    r.stable();
+    r.unstable_declared();
+    r.unstable_undeclared();              //~ ERROR use of unstable library feature
+
+    r.pub_crate();                        //~ ERROR `pub_crate` is private
+    r.pub_mod();                          //~ ERROR `pub_mod` is private
+    r.private();                          //~ ERROR `private` is private
+
+    let t = Tuple::new();
+    t.stable_trait_method();
+    t.unstable_declared_trait_method();
+    t.unstable_undeclared_trait_method(); //~ ERROR use of unstable library feature
+
+    t.stable();
+    t.unstable_declared();
+    t.unstable_undeclared();              //~ ERROR use of unstable library feature
+
+    t.pub_crate();                        //~ ERROR `pub_crate` is private
+    t.pub_mod();                          //~ ERROR `pub_mod` is private
+    t.private();                          //~ ERROR `private` is private
+}
diff --git a/src/test/ui/explore-issue-38412.stderr b/src/test/ui/explore-issue-38412.stderr
new file mode 100644
index 0000000..5e5d952
--- /dev/null
+++ b/src/test/ui/explore-issue-38412.stderr
@@ -0,0 +1,132 @@
+error[E0658]: use of unstable library feature 'unstable_undeclared' (see issue #38412)
+  --> $DIR/explore-issue-38412.rs:21:63
+   |
+LL |     let Record { a_stable_pub: _, a_unstable_declared_pub: _, a_unstable_undeclared_pub: _, .. } =
+   |                                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_undeclared)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_undeclared' (see issue #38412)
+  --> $DIR/explore-issue-38412.rs:30:5
+   |
+LL |     r.a_unstable_undeclared_pub;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_undeclared)] to the crate attributes to enable
+
+error[E0616]: field `b_crate` of struct `pub_and_stability::Record` is private
+  --> $DIR/explore-issue-38412.rs:31:5
+   |
+LL |     r.b_crate;
+   |     ^^^^^^^^^
+
+error[E0616]: field `c_mod` of struct `pub_and_stability::Record` is private
+  --> $DIR/explore-issue-38412.rs:32:5
+   |
+LL |     r.c_mod;
+   |     ^^^^^^^
+
+error[E0616]: field `d_priv` of struct `pub_and_stability::Record` is private
+  --> $DIR/explore-issue-38412.rs:33:5
+   |
+LL |     r.d_priv;
+   |     ^^^^^^^^
+
+error[E0658]: use of unstable library feature 'unstable_undeclared' (see issue #38412)
+  --> $DIR/explore-issue-38412.rs:37:5
+   |
+LL |     t.2;
+   |     ^^^
+   |
+   = help: add #![feature(unstable_undeclared)] to the crate attributes to enable
+
+error[E0616]: field `3` of struct `pub_and_stability::Tuple` is private
+  --> $DIR/explore-issue-38412.rs:38:5
+   |
+LL |     t.3;
+   |     ^^^
+
+error[E0616]: field `4` of struct `pub_and_stability::Tuple` is private
+  --> $DIR/explore-issue-38412.rs:39:5
+   |
+LL |     t.4;
+   |     ^^^
+
+error[E0616]: field `5` of struct `pub_and_stability::Tuple` is private
+  --> $DIR/explore-issue-38412.rs:40:5
+   |
+LL |     t.5;
+   |     ^^^
+
+error[E0658]: use of unstable library feature 'unstable_undeclared' (see issue #38412)
+  --> $DIR/explore-issue-38412.rs:44:7
+   |
+LL |     r.unstable_undeclared_trait_method();
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_undeclared)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_undeclared' (see issue #38412)
+  --> $DIR/explore-issue-38412.rs:48:7
+   |
+LL |     r.unstable_undeclared();
+   |       ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_undeclared)] to the crate attributes to enable
+
+error[E0624]: method `pub_crate` is private
+  --> $DIR/explore-issue-38412.rs:50:7
+   |
+LL |     r.pub_crate();
+   |       ^^^^^^^^^
+
+error[E0624]: method `pub_mod` is private
+  --> $DIR/explore-issue-38412.rs:51:7
+   |
+LL |     r.pub_mod();
+   |       ^^^^^^^
+
+error[E0624]: method `private` is private
+  --> $DIR/explore-issue-38412.rs:52:7
+   |
+LL |     r.private();
+   |       ^^^^^^^
+
+error[E0658]: use of unstable library feature 'unstable_undeclared' (see issue #38412)
+  --> $DIR/explore-issue-38412.rs:57:7
+   |
+LL |     t.unstable_undeclared_trait_method();
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_undeclared)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_undeclared' (see issue #38412)
+  --> $DIR/explore-issue-38412.rs:61:7
+   |
+LL |     t.unstable_undeclared();
+   |       ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_undeclared)] to the crate attributes to enable
+
+error[E0624]: method `pub_crate` is private
+  --> $DIR/explore-issue-38412.rs:63:7
+   |
+LL |     t.pub_crate();
+   |       ^^^^^^^^^
+
+error[E0624]: method `pub_mod` is private
+  --> $DIR/explore-issue-38412.rs:64:7
+   |
+LL |     t.pub_mod();
+   |       ^^^^^^^
+
+error[E0624]: method `private` is private
+  --> $DIR/explore-issue-38412.rs:65:7
+   |
+LL |     t.private();
+   |       ^^^^^^^
+
+error: aborting due to 19 previous errors
+
+Some errors occurred: E0616, E0624, E0658.
+For more information about an error, try `rustc --explain E0616`.
diff --git a/src/test/ui/export-fully-qualified.rs b/src/test/ui/export-fully-qualified.rs
new file mode 100644
index 0000000..99cb558
--- /dev/null
+++ b/src/test/ui/export-fully-qualified.rs
@@ -0,0 +1,11 @@
+// In this test baz isn't resolved when called as foo.baz even though
+// it's called from inside foo. This is somewhat surprising and may
+// want to change eventually.
+
+mod foo {
+    pub fn bar() { foo::baz(); } //~ ERROR failed to resolve: use of undeclared type or module `foo`
+
+    fn baz() { }
+}
+
+fn main() { }
diff --git a/src/test/ui/export-fully-qualified.stderr b/src/test/ui/export-fully-qualified.stderr
new file mode 100644
index 0000000..c2ec160
--- /dev/null
+++ b/src/test/ui/export-fully-qualified.stderr
@@ -0,0 +1,9 @@
+error[E0433]: failed to resolve: use of undeclared type or module `foo`
+  --> $DIR/export-fully-qualified.rs:6:20
+   |
+LL |     pub fn bar() { foo::baz(); }
+   |                    ^^^ use of undeclared type or module `foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/export-import.rs b/src/test/ui/export-import.rs
new file mode 100644
index 0000000..3f54363
--- /dev/null
+++ b/src/test/ui/export-import.rs
@@ -0,0 +1,11 @@
+use m::unexported;
+//~^ ERROR: is private
+
+mod m {
+    pub fn exported() { }
+
+    fn unexported() { }
+}
+
+
+fn main() { unexported(); }
diff --git a/src/test/ui/export-import.stderr b/src/test/ui/export-import.stderr
new file mode 100644
index 0000000..e02952e
--- /dev/null
+++ b/src/test/ui/export-import.stderr
@@ -0,0 +1,9 @@
+error[E0603]: function `unexported` is private
+  --> $DIR/export-import.rs:1:8
+   |
+LL | use m::unexported;
+   |        ^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0603`.
diff --git a/src/test/ui/export-tag-variant.rs b/src/test/ui/export-tag-variant.rs
new file mode 100644
index 0000000..46c1006
--- /dev/null
+++ b/src/test/ui/export-tag-variant.rs
@@ -0,0 +1,7 @@
+mod foo {
+    pub fn x() { }
+
+    enum Y { Y1 }
+}
+
+fn main() { let z = foo::Y::Y1; } //~ ERROR: enum `Y` is private
diff --git a/src/test/ui/export-tag-variant.stderr b/src/test/ui/export-tag-variant.stderr
new file mode 100644
index 0000000..b5a2c12
--- /dev/null
+++ b/src/test/ui/export-tag-variant.stderr
@@ -0,0 +1,9 @@
+error[E0603]: enum `Y` is private
+  --> $DIR/export-tag-variant.rs:7:26
+   |
+LL | fn main() { let z = foo::Y::Y1; }
+   |                          ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0603`.
diff --git a/src/test/ui/export.rs b/src/test/ui/export.rs
new file mode 100644
index 0000000..73ceec6
--- /dev/null
+++ b/src/test/ui/export.rs
@@ -0,0 +1,10 @@
+mod foo {
+    pub fn x(y: isize) { log(debug, y); }
+    //~^ ERROR cannot find function `log` in this scope
+    //~| ERROR cannot find value `debug` in this scope
+    fn z(y: isize) { log(debug, y); }
+    //~^ ERROR cannot find function `log` in this scope
+    //~| ERROR cannot find value `debug` in this scope
+}
+
+fn main() { foo::z(10); } //~ ERROR function `z` is private
diff --git a/src/test/ui/export.stderr b/src/test/ui/export.stderr
new file mode 100644
index 0000000..76ec91e
--- /dev/null
+++ b/src/test/ui/export.stderr
@@ -0,0 +1,34 @@
+error[E0425]: cannot find function `log` in this scope
+  --> $DIR/export.rs:2:26
+   |
+LL |     pub fn x(y: isize) { log(debug, y); }
+   |                          ^^^ not found in this scope
+
+error[E0425]: cannot find value `debug` in this scope
+  --> $DIR/export.rs:2:30
+   |
+LL |     pub fn x(y: isize) { log(debug, y); }
+   |                              ^^^^^ not found in this scope
+
+error[E0425]: cannot find function `log` in this scope
+  --> $DIR/export.rs:5:22
+   |
+LL |     fn z(y: isize) { log(debug, y); }
+   |                      ^^^ not found in this scope
+
+error[E0425]: cannot find value `debug` in this scope
+  --> $DIR/export.rs:5:26
+   |
+LL |     fn z(y: isize) { log(debug, y); }
+   |                          ^^^^^ not found in this scope
+
+error[E0603]: function `z` is private
+  --> $DIR/export.rs:10:18
+   |
+LL | fn main() { foo::z(10); }
+   |                  ^
+
+error: aborting due to 5 previous errors
+
+Some errors occurred: E0425, E0603.
+For more information about an error, try `rustc --explain E0425`.
diff --git a/src/test/ui/export2.rs b/src/test/ui/export2.rs
new file mode 100644
index 0000000..811d96f
--- /dev/null
+++ b/src/test/ui/export2.rs
@@ -0,0 +1,11 @@
+mod foo {
+    pub fn x() { bar::x(); } //~ ERROR failed to resolve: use of undeclared type or module `bar`
+}
+
+mod bar {
+    fn x() { println!("x"); }
+
+    pub fn y() { }
+}
+
+fn main() { foo::x(); }
diff --git a/src/test/ui/export2.stderr b/src/test/ui/export2.stderr
new file mode 100644
index 0000000..e0cd440
--- /dev/null
+++ b/src/test/ui/export2.stderr
@@ -0,0 +1,9 @@
+error[E0433]: failed to resolve: use of undeclared type or module `bar`
+  --> $DIR/export2.rs:2:18
+   |
+LL |     pub fn x() { bar::x(); }
+   |                  ^^^ use of undeclared type or module `bar`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/expr_attr_paren_order.rs b/src/test/ui/expr_attr_paren_order.rs
new file mode 100644
index 0000000..65f2b67
--- /dev/null
+++ b/src/test/ui/expr_attr_paren_order.rs
@@ -0,0 +1,24 @@
+#![feature(stmt_expr_attributes)]
+
+fn main() {
+
+    // Test that attributes on parens get concatenated
+    // in the expected order in the hir folder.
+
+    #[deny(non_snake_case)] (
+        #![allow(non_snake_case)]
+        {
+            let X = 0;
+            let _ = X;
+        }
+    );
+
+    #[allow(non_snake_case)] (
+        #![deny(non_snake_case)]
+        {
+            let X = 0; //~ ERROR snake case name
+            let _ = X;
+        }
+    );
+
+}
diff --git a/src/test/ui/expr_attr_paren_order.stderr b/src/test/ui/expr_attr_paren_order.stderr
new file mode 100644
index 0000000..89f615f
--- /dev/null
+++ b/src/test/ui/expr_attr_paren_order.stderr
@@ -0,0 +1,14 @@
+error: variable `X` should have a snake case name
+  --> $DIR/expr_attr_paren_order.rs:19:17
+   |
+LL |             let X = 0;
+   |                 ^ help: convert the identifier to snake case: `x`
+   |
+note: lint level defined here
+  --> $DIR/expr_attr_paren_order.rs:17:17
+   |
+LL |         #![deny(non_snake_case)]
+   |                 ^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/ext-nonexistent.rs b/src/test/ui/ext-nonexistent.rs
new file mode 100644
index 0000000..e65b165
--- /dev/null
+++ b/src/test/ui/ext-nonexistent.rs
@@ -0,0 +1,2 @@
+// error-pattern:cannot find macro
+fn main() { iamnotanextensionthatexists!(""); }
diff --git a/src/test/ui/ext-nonexistent.stderr b/src/test/ui/ext-nonexistent.stderr
new file mode 100644
index 0000000..3fbbb49
--- /dev/null
+++ b/src/test/ui/ext-nonexistent.stderr
@@ -0,0 +1,8 @@
+error: cannot find macro `iamnotanextensionthatexists!` in this scope
+  --> $DIR/ext-nonexistent.rs:2:13
+   |
+LL | fn main() { iamnotanextensionthatexists!(""); }
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/extenv/extenv-arg-2-not-string-literal.rs b/src/test/ui/extenv/extenv-arg-2-not-string-literal.rs
new file mode 100644
index 0000000..66dced4
--- /dev/null
+++ b/src/test/ui/extenv/extenv-arg-2-not-string-literal.rs
@@ -0,0 +1 @@
+fn main() { env!("one", 10); } //~ ERROR: expected string literal
diff --git a/src/test/ui/extenv/extenv-arg-2-not-string-literal.stderr b/src/test/ui/extenv/extenv-arg-2-not-string-literal.stderr
new file mode 100644
index 0000000..258e2b3
--- /dev/null
+++ b/src/test/ui/extenv/extenv-arg-2-not-string-literal.stderr
@@ -0,0 +1,8 @@
+error: expected string literal
+  --> $DIR/extenv-arg-2-not-string-literal.rs:1:25
+   |
+LL | fn main() { env!("one", 10); }
+   |                         ^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/extenv/extenv-no-args.rs b/src/test/ui/extenv/extenv-no-args.rs
new file mode 100644
index 0000000..9f221ed
--- /dev/null
+++ b/src/test/ui/extenv/extenv-no-args.rs
@@ -0,0 +1 @@
+fn main() { env!(); } //~ ERROR: env! takes 1 or 2 arguments
diff --git a/src/test/ui/extenv/extenv-no-args.stderr b/src/test/ui/extenv/extenv-no-args.stderr
new file mode 100644
index 0000000..acdde84
--- /dev/null
+++ b/src/test/ui/extenv/extenv-no-args.stderr
@@ -0,0 +1,8 @@
+error: env! takes 1 or 2 arguments
+  --> $DIR/extenv-no-args.rs:1:13
+   |
+LL | fn main() { env!(); }
+   |             ^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/extenv/extenv-not-defined-custom.rs b/src/test/ui/extenv/extenv-not-defined-custom.rs
new file mode 100644
index 0000000..30b7278
--- /dev/null
+++ b/src/test/ui/extenv/extenv-not-defined-custom.rs
@@ -0,0 +1 @@
+fn main() { env!("__HOPEFULLY_NOT_DEFINED__", "my error message"); } //~ ERROR: my error message
diff --git a/src/test/ui/extenv/extenv-not-defined-custom.stderr b/src/test/ui/extenv/extenv-not-defined-custom.stderr
new file mode 100644
index 0000000..523982d
--- /dev/null
+++ b/src/test/ui/extenv/extenv-not-defined-custom.stderr
@@ -0,0 +1,8 @@
+error: my error message
+  --> $DIR/extenv-not-defined-custom.rs:1:13
+   |
+LL | fn main() { env!("__HOPEFULLY_NOT_DEFINED__", "my error message"); }
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/extenv/extenv-not-defined-default.rs b/src/test/ui/extenv/extenv-not-defined-default.rs
new file mode 100644
index 0000000..30a06a2
--- /dev/null
+++ b/src/test/ui/extenv/extenv-not-defined-default.rs
@@ -0,0 +1,4 @@
+fn main() {
+    env!("__HOPEFULLY_NOT_DEFINED__");
+    //~^ ERROR: environment variable `__HOPEFULLY_NOT_DEFINED__` not defined
+}
diff --git a/src/test/ui/extenv/extenv-not-defined-default.stderr b/src/test/ui/extenv/extenv-not-defined-default.stderr
new file mode 100644
index 0000000..4bfe330
--- /dev/null
+++ b/src/test/ui/extenv/extenv-not-defined-default.stderr
@@ -0,0 +1,8 @@
+error: environment variable `__HOPEFULLY_NOT_DEFINED__` not defined
+  --> $DIR/extenv-not-defined-default.rs:2:5
+   |
+LL |     env!("__HOPEFULLY_NOT_DEFINED__");
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/extenv/extenv-not-string-literal.rs b/src/test/ui/extenv/extenv-not-string-literal.rs
new file mode 100644
index 0000000..3eaa0b5
--- /dev/null
+++ b/src/test/ui/extenv/extenv-not-string-literal.rs
@@ -0,0 +1 @@
+fn main() { env!(10, "two"); } //~ ERROR: expected string literal
diff --git a/src/test/ui/extenv/extenv-not-string-literal.stderr b/src/test/ui/extenv/extenv-not-string-literal.stderr
new file mode 100644
index 0000000..342a9f7
--- /dev/null
+++ b/src/test/ui/extenv/extenv-not-string-literal.stderr
@@ -0,0 +1,8 @@
+error: expected string literal
+  --> $DIR/extenv-not-string-literal.rs:1:18
+   |
+LL | fn main() { env!(10, "two"); }
+   |                  ^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/extenv/extenv-too-many-args.rs b/src/test/ui/extenv/extenv-too-many-args.rs
new file mode 100644
index 0000000..1adbee5
--- /dev/null
+++ b/src/test/ui/extenv/extenv-too-many-args.rs
@@ -0,0 +1 @@
+fn main() { env!("one", "two", "three"); } //~ ERROR: env! takes 1 or 2 arguments
diff --git a/src/test/ui/extenv/extenv-too-many-args.stderr b/src/test/ui/extenv/extenv-too-many-args.stderr
new file mode 100644
index 0000000..3351da0
--- /dev/null
+++ b/src/test/ui/extenv/extenv-too-many-args.stderr
@@ -0,0 +1,8 @@
+error: env! takes 1 or 2 arguments
+  --> $DIR/extenv-too-many-args.rs:1:13
+   |
+LL | fn main() { env!("one", "two", "three"); }
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/extenv/issue-55897.rs b/src/test/ui/extenv/issue-55897.rs
new file mode 100644
index 0000000..bd151c8
--- /dev/null
+++ b/src/test/ui/extenv/issue-55897.rs
@@ -0,0 +1,15 @@
+use prelude::*; //~ ERROR unresolved import `prelude`
+
+mod unresolved_env {
+    use env;
+
+    include!(concat!(env!("NON_EXISTENT"), "/data.rs"));
+    //~^ ERROR cannot determine resolution for the macro `env`
+}
+
+mod nonexistent_env {
+    include!(concat!(env!("NON_EXISTENT"), "/data.rs"));
+    //~^ ERROR environment variable `NON_EXISTENT` not defined
+}
+
+fn main() {}
diff --git a/src/test/ui/extenv/issue-55897.stderr b/src/test/ui/extenv/issue-55897.stderr
new file mode 100644
index 0000000..9f6570a
--- /dev/null
+++ b/src/test/ui/extenv/issue-55897.stderr
@@ -0,0 +1,26 @@
+error: environment variable `NON_EXISTENT` not defined
+  --> $DIR/issue-55897.rs:11:22
+   |
+LL |     include!(concat!(env!("NON_EXISTENT"), "/data.rs"));
+   |                      ^^^^^^^^^^^^^^^^^^^^
+
+error[E0432]: unresolved import `prelude`
+  --> $DIR/issue-55897.rs:1:5
+   |
+LL | use prelude::*;
+   |     ^^^^^^^
+   |     |
+   |     unresolved import
+   |     help: a similar path exists: `std::prelude`
+
+error: cannot determine resolution for the macro `env`
+  --> $DIR/issue-55897.rs:6:22
+   |
+LL |     include!(concat!(env!("NON_EXISTENT"), "/data.rs"));
+   |                      ^^^
+   |
+   = note: import resolution is stuck, try simplifying macro imports
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/extern-prelude-fail.rs b/src/test/ui/extern-prelude-fail.rs
new file mode 100644
index 0000000..7d38702
--- /dev/null
+++ b/src/test/ui/extern-prelude-fail.rs
@@ -0,0 +1,9 @@
+// compile-flags:--extern extern_prelude
+// aux-build:extern-prelude.rs
+
+// Extern prelude names are not available by absolute paths
+
+fn main() {
+    use extern_prelude::S; //~ ERROR unresolved import `extern_prelude`
+    let s = ::extern_prelude::S; //~ ERROR failed to resolve
+}
diff --git a/src/test/ui/extern-prelude-fail.stderr b/src/test/ui/extern-prelude-fail.stderr
new file mode 100644
index 0000000..ad148c0
--- /dev/null
+++ b/src/test/ui/extern-prelude-fail.stderr
@@ -0,0 +1,16 @@
+error[E0432]: unresolved import `extern_prelude`
+  --> $DIR/extern-prelude-fail.rs:7:9
+   |
+LL |     use extern_prelude::S;
+   |         ^^^^^^^^^^^^^^ maybe a missing `extern crate extern_prelude;`?
+
+error[E0433]: failed to resolve: maybe a missing `extern crate extern_prelude;`?
+  --> $DIR/extern-prelude-fail.rs:8:15
+   |
+LL |     let s = ::extern_prelude::S;
+   |               ^^^^^^^^^^^^^^ maybe a missing `extern crate extern_prelude;`?
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0432, E0433.
+For more information about an error, try `rustc --explain E0432`.
diff --git a/src/test/ui/extern-prelude.rs b/src/test/ui/extern-prelude.rs
new file mode 100644
index 0000000..0e52f2c
--- /dev/null
+++ b/src/test/ui/extern-prelude.rs
@@ -0,0 +1,31 @@
+// compile-pass
+// compile-flags:--extern extern_prelude --extern Vec
+// aux-build:extern-prelude.rs
+// aux-build:extern-prelude-vec.rs
+
+fn basic() {
+    // It works
+    let s = extern_prelude::S;
+    s.external();
+}
+
+fn shadow_mod() {
+    // Local module shadows `extern_prelude` from extern prelude
+    mod extern_prelude {
+        pub struct S;
+
+        impl S {
+            pub fn internal(&self) {}
+        }
+    }
+
+    let s = extern_prelude::S;
+    s.internal(); // OK
+}
+
+fn shadow_prelude() {
+    // Extern prelude shadows standard library prelude
+    let x = Vec::new(0f32, ()); // OK
+}
+
+fn main() {}
diff --git a/src/test/ui/extern/auxiliary/invalid-utf8.txt b/src/test/ui/extern/auxiliary/invalid-utf8.txt
new file mode 100644
index 0000000..dc1115b
--- /dev/null
+++ b/src/test/ui/extern/auxiliary/invalid-utf8.txt
@@ -0,0 +1 @@
+Ã(
\ No newline at end of file
diff --git a/src/test/ui/extern/auxiliary/m1.rs b/src/test/ui/extern/auxiliary/m1.rs
new file mode 100644
index 0000000..b76b432
--- /dev/null
+++ b/src/test/ui/extern/auxiliary/m1.rs
@@ -0,0 +1 @@
+pub fn foo() {}
diff --git a/src/test/ui/extern/auxiliary/m2.rs b/src/test/ui/extern/auxiliary/m2.rs
new file mode 100644
index 0000000..c5c0bc6
--- /dev/null
+++ b/src/test/ui/extern/auxiliary/m2.rs
@@ -0,0 +1 @@
+pub fn bar() {}
diff --git a/src/test/ui/extern/extern-const.fixed b/src/test/ui/extern/extern-const.fixed
new file mode 100644
index 0000000..fb17934
--- /dev/null
+++ b/src/test/ui/extern/extern-const.fixed
@@ -0,0 +1,25 @@
+// Check extern items cannot be const + `rustfix` suggests using
+// extern static.
+//
+// #54388: an unused reference to an undefined static may or may not
+// compile. To sidestep this by using one that *is* defined.
+
+// run-rustfix
+// ignore-wasm32 no external library to link to.
+// compile-flags: -g -Z continue-parse-after-error
+#![feature(rustc_private)]
+extern crate libc;
+
+#[link(name = "rust_test_helpers", kind = "static")]
+extern "C" {
+    static rust_dbg_static_mut: libc::c_int; //~ ERROR extern items cannot be `const`
+}
+
+fn main() {
+    // We suggest turning the (illegal) extern `const` into an extern `static`,
+    // but this also requires `unsafe` (a deny-by-default lint at comment time,
+    // future error; Issue #36247)
+    unsafe {
+        let _x = rust_dbg_static_mut;
+    }
+}
diff --git a/src/test/ui/extern/extern-const.rs b/src/test/ui/extern/extern-const.rs
new file mode 100644
index 0000000..f2585f5
--- /dev/null
+++ b/src/test/ui/extern/extern-const.rs
@@ -0,0 +1,25 @@
+// Check extern items cannot be const + `rustfix` suggests using
+// extern static.
+//
+// #54388: an unused reference to an undefined static may or may not
+// compile. To sidestep this by using one that *is* defined.
+
+// run-rustfix
+// ignore-wasm32 no external library to link to.
+// compile-flags: -g -Z continue-parse-after-error
+#![feature(rustc_private)]
+extern crate libc;
+
+#[link(name = "rust_test_helpers", kind = "static")]
+extern "C" {
+    const rust_dbg_static_mut: libc::c_int; //~ ERROR extern items cannot be `const`
+}
+
+fn main() {
+    // We suggest turning the (illegal) extern `const` into an extern `static`,
+    // but this also requires `unsafe` (a deny-by-default lint at comment time,
+    // future error; Issue #36247)
+    unsafe {
+        let _x = rust_dbg_static_mut;
+    }
+}
diff --git a/src/test/ui/extern/extern-const.stderr b/src/test/ui/extern/extern-const.stderr
new file mode 100644
index 0000000..77406be
--- /dev/null
+++ b/src/test/ui/extern/extern-const.stderr
@@ -0,0 +1,8 @@
+error: extern items cannot be `const`
+  --> $DIR/extern-const.rs:15:5
+   |
+LL |     const rust_dbg_static_mut: libc::c_int;
+   |     ^^^^^ help: try using a static value: `static`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/extern/extern-crate-rename.rs b/src/test/ui/extern/extern-crate-rename.rs
new file mode 100644
index 0000000..fc8afc3
--- /dev/null
+++ b/src/test/ui/extern/extern-crate-rename.rs
@@ -0,0 +1,8 @@
+// aux-build:m1.rs
+// aux-build:m2.rs
+
+
+extern crate m1;
+extern crate m2 as m1; //~ ERROR is defined multiple times
+
+fn main() {}
diff --git a/src/test/ui/extern/extern-crate-rename.stderr b/src/test/ui/extern/extern-crate-rename.stderr
new file mode 100644
index 0000000..787c11f
--- /dev/null
+++ b/src/test/ui/extern/extern-crate-rename.stderr
@@ -0,0 +1,17 @@
+error[E0259]: the name `m1` is defined multiple times
+  --> $DIR/extern-crate-rename.rs:6:1
+   |
+LL | extern crate m1;
+   | ---------------- previous import of the extern crate `m1` here
+LL | extern crate m2 as m1;
+   | ^^^^^^^^^^^^^^^^^^^^^^ `m1` reimported here
+   |
+   = note: `m1` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | extern crate m2 as other_m1;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0259`.
diff --git a/src/test/ui/extern/extern-crate-visibility.rs b/src/test/ui/extern/extern-crate-visibility.rs
new file mode 100644
index 0000000..b51e443
--- /dev/null
+++ b/src/test/ui/extern/extern-crate-visibility.rs
@@ -0,0 +1,24 @@
+mod foo {
+    extern crate core;
+}
+
+// Check that private crates can be used from outside their modules, albeit with warnings
+use foo::core::cell; //~ ERROR extern crate `core` is private
+
+fn f() {
+    foo::core::cell::Cell::new(0); //~ ERROR extern crate `core` is private
+
+    use foo::*;
+    mod core {} // Check that private crates are not glob imported
+}
+
+mod bar {
+    pub extern crate core;
+}
+
+mod baz {
+    pub use bar::*;
+    use self::core::cell; // Check that public extern crates are glob imported
+}
+
+fn main() {}
diff --git a/src/test/ui/extern/extern-crate-visibility.stderr b/src/test/ui/extern/extern-crate-visibility.stderr
new file mode 100644
index 0000000..8bc9f9a
--- /dev/null
+++ b/src/test/ui/extern/extern-crate-visibility.stderr
@@ -0,0 +1,15 @@
+error[E0603]: extern crate `core` is private
+  --> $DIR/extern-crate-visibility.rs:6:10
+   |
+LL | use foo::core::cell;
+   |          ^^^^
+
+error[E0603]: extern crate `core` is private
+  --> $DIR/extern-crate-visibility.rs:9:10
+   |
+LL |     foo::core::cell::Cell::new(0);
+   |          ^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0603`.
diff --git a/src/test/ui/extern/extern-macro.rs b/src/test/ui/extern/extern-macro.rs
new file mode 100644
index 0000000..ab974e6
--- /dev/null
+++ b/src/test/ui/extern/extern-macro.rs
@@ -0,0 +1,6 @@
+// #41719
+
+fn main() {
+    enum Foo {}
+    let _ = Foo::bar!(); //~ ERROR failed to resolve: partially resolved path in a macro
+}
diff --git a/src/test/ui/extern/extern-macro.stderr b/src/test/ui/extern/extern-macro.stderr
new file mode 100644
index 0000000..5b7a720
--- /dev/null
+++ b/src/test/ui/extern/extern-macro.stderr
@@ -0,0 +1,9 @@
+error[E0433]: failed to resolve: partially resolved path in a macro
+  --> $DIR/extern-macro.rs:5:13
+   |
+LL |     let _ = Foo::bar!();
+   |             ^^^^^^^^ partially resolved path in a macro
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/extern/extern-main-fn.rs b/src/test/ui/extern/extern-main-fn.rs
new file mode 100644
index 0000000..dacebfb
--- /dev/null
+++ b/src/test/ui/extern/extern-main-fn.rs
@@ -0,0 +1 @@
+extern fn main() {} //~ ERROR: main function has wrong type [E0580]
diff --git a/src/test/ui/extern/extern-main-fn.stderr b/src/test/ui/extern/extern-main-fn.stderr
new file mode 100644
index 0000000..14f0640
--- /dev/null
+++ b/src/test/ui/extern/extern-main-fn.stderr
@@ -0,0 +1,12 @@
+error[E0580]: main function has wrong type
+  --> $DIR/extern-main-fn.rs:1:1
+   |
+LL | extern fn main() {}
+   | ^^^^^^^^^^^^^^^^ expected "Rust" fn, found "C" fn
+   |
+   = note: expected type `fn()`
+              found type `extern "C" fn()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0580`.
diff --git a/src/test/ui/extern/extern-types-distinct-types.rs b/src/test/ui/extern/extern-types-distinct-types.rs
new file mode 100644
index 0000000..000ba54
--- /dev/null
+++ b/src/test/ui/extern/extern-types-distinct-types.rs
@@ -0,0 +1,12 @@
+#![feature(extern_types)]
+
+extern {
+    type A;
+    type B;
+}
+
+fn foo(r: &A) -> &B {
+    r //~ ERROR mismatched types
+}
+
+fn main() { }
diff --git a/src/test/ui/extern/extern-types-distinct-types.stderr b/src/test/ui/extern/extern-types-distinct-types.stderr
new file mode 100644
index 0000000..eb632ee
--- /dev/null
+++ b/src/test/ui/extern/extern-types-distinct-types.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/extern-types-distinct-types.rs:9:5
+   |
+LL |     r
+   |     ^ expected extern type `B`, found extern type `A`
+   |
+   = note: expected type `&B`
+              found type `&A`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/extern/extern-types-not-sync-send.rs b/src/test/ui/extern/extern-types-not-sync-send.rs
new file mode 100644
index 0000000..3af8b9b
--- /dev/null
+++ b/src/test/ui/extern/extern-types-not-sync-send.rs
@@ -0,0 +1,18 @@
+// Make sure extern types are !Sync and !Send.
+
+#![feature(extern_types)]
+
+extern {
+    type A;
+}
+
+fn assert_sync<T: ?Sized + Sync>() { }
+fn assert_send<T: ?Sized + Send>() { }
+
+fn main() {
+    assert_sync::<A>();
+    //~^ ERROR `A` cannot be shared between threads safely [E0277]
+
+    assert_send::<A>();
+    //~^ ERROR `A` cannot be sent between threads safely [E0277]
+}
diff --git a/src/test/ui/extern/extern-types-not-sync-send.stderr b/src/test/ui/extern/extern-types-not-sync-send.stderr
new file mode 100644
index 0000000..bc9d96d
--- /dev/null
+++ b/src/test/ui/extern/extern-types-not-sync-send.stderr
@@ -0,0 +1,29 @@
+error[E0277]: `A` cannot be shared between threads safely
+  --> $DIR/extern-types-not-sync-send.rs:13:5
+   |
+LL |     assert_sync::<A>();
+   |     ^^^^^^^^^^^^^^^^ `A` cannot be shared between threads safely
+   |
+   = help: the trait `std::marker::Sync` is not implemented for `A`
+note: required by `assert_sync`
+  --> $DIR/extern-types-not-sync-send.rs:9:1
+   |
+LL | fn assert_sync<T: ?Sized + Sync>() { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: `A` cannot be sent between threads safely
+  --> $DIR/extern-types-not-sync-send.rs:16:5
+   |
+LL |     assert_send::<A>();
+   |     ^^^^^^^^^^^^^^^^ `A` cannot be sent between threads safely
+   |
+   = help: the trait `std::marker::Send` is not implemented for `A`
+note: required by `assert_send`
+  --> $DIR/extern-types-not-sync-send.rs:10:1
+   |
+LL | fn assert_send<T: ?Sized + Send>() { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/extern/extern-types-unsized.rs b/src/test/ui/extern/extern-types-unsized.rs
new file mode 100644
index 0000000..a296ae0
--- /dev/null
+++ b/src/test/ui/extern/extern-types-unsized.rs
@@ -0,0 +1,33 @@
+// Make sure extern types are !Sized.
+
+#![feature(extern_types)]
+
+extern {
+    type A;
+}
+
+struct Foo {
+    x: u8,
+    tail: A,
+}
+
+struct Bar<T: ?Sized> {
+    x: u8,
+    tail: T,
+}
+
+fn assert_sized<T>() { }
+
+fn main() {
+    assert_sized::<A>();
+    //~^ ERROR the size for values of type
+
+    assert_sized::<Foo>();
+    //~^ ERROR the size for values of type
+
+    assert_sized::<Bar<A>>();
+    //~^ ERROR the size for values of type
+
+    assert_sized::<Bar<Bar<A>>>();
+    //~^ ERROR the size for values of type
+}
diff --git a/src/test/ui/extern/extern-types-unsized.stderr b/src/test/ui/extern/extern-types-unsized.stderr
new file mode 100644
index 0000000..4e4f555
--- /dev/null
+++ b/src/test/ui/extern/extern-types-unsized.stderr
@@ -0,0 +1,63 @@
+error[E0277]: the size for values of type `A` cannot be known at compilation time
+  --> $DIR/extern-types-unsized.rs:22:5
+   |
+LL |     assert_sized::<A>();
+   |     ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `A`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+note: required by `assert_sized`
+  --> $DIR/extern-types-unsized.rs:19:1
+   |
+LL | fn assert_sized<T>() { }
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the size for values of type `A` cannot be known at compilation time
+  --> $DIR/extern-types-unsized.rs:25:5
+   |
+LL |     assert_sized::<Foo>();
+   |     ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: within `Foo`, the trait `std::marker::Sized` is not implemented for `A`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: required because it appears within the type `Foo`
+note: required by `assert_sized`
+  --> $DIR/extern-types-unsized.rs:19:1
+   |
+LL | fn assert_sized<T>() { }
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the size for values of type `A` cannot be known at compilation time
+  --> $DIR/extern-types-unsized.rs:28:5
+   |
+LL |     assert_sized::<Bar<A>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: within `Bar<A>`, the trait `std::marker::Sized` is not implemented for `A`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: required because it appears within the type `Bar<A>`
+note: required by `assert_sized`
+  --> $DIR/extern-types-unsized.rs:19:1
+   |
+LL | fn assert_sized<T>() { }
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the size for values of type `A` cannot be known at compilation time
+  --> $DIR/extern-types-unsized.rs:31:5
+   |
+LL |     assert_sized::<Bar<Bar<A>>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: within `Bar<Bar<A>>`, the trait `std::marker::Sized` is not implemented for `A`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: required because it appears within the type `Bar<A>`
+   = note: required because it appears within the type `Bar<Bar<A>>`
+note: required by `assert_sized`
+  --> $DIR/extern-types-unsized.rs:19:1
+   |
+LL | fn assert_sized<T>() { }
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/extern/extern-with-type-bounds.rs b/src/test/ui/extern/extern-with-type-bounds.rs
new file mode 100644
index 0000000..8f9683e
--- /dev/null
+++ b/src/test/ui/extern/extern-with-type-bounds.rs
@@ -0,0 +1,20 @@
+#![feature(intrinsics)]
+
+extern "rust-intrinsic" {
+    // Real example from libcore
+    fn type_id<T: ?Sized + 'static>() -> u64;
+
+    // Silent bounds made explicit to make sure they are actually
+    // resolved.
+    fn transmute<T: Sized, U: Sized>(val: T) -> U;
+
+    // Bounds aren't checked right now, so this should work
+    // even though it's incorrect.
+    fn size_of<T: Clone>() -> usize;
+
+    // Unresolved bounds should still error.
+    fn align_of<T: NoSuchTrait>() -> usize;
+    //~^ ERROR cannot find trait `NoSuchTrait` in this scope
+}
+
+fn main() {}
diff --git a/src/test/ui/extern/extern-with-type-bounds.stderr b/src/test/ui/extern/extern-with-type-bounds.stderr
new file mode 100644
index 0000000..acd0596
--- /dev/null
+++ b/src/test/ui/extern/extern-with-type-bounds.stderr
@@ -0,0 +1,9 @@
+error[E0405]: cannot find trait `NoSuchTrait` in this scope
+  --> $DIR/extern-with-type-bounds.rs:16:20
+   |
+LL |     fn align_of<T: NoSuchTrait>() -> usize;
+   |                    ^^^^^^^^^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0405`.
diff --git a/src/test/ui/extern/extern-wrong-value-type.rs b/src/test/ui/extern/extern-wrong-value-type.rs
new file mode 100644
index 0000000..aba5242
--- /dev/null
+++ b/src/test/ui/extern/extern-wrong-value-type.rs
@@ -0,0 +1,11 @@
+extern fn f() {
+}
+
+fn is_fn<F>(_: F) where F: Fn() {}
+
+fn main() {
+    // extern functions are extern "C" fn
+    let _x: extern "C" fn() = f; // OK
+    is_fn(f);
+    //~^ ERROR expected a `std::ops::Fn<()>` closure, found `extern "C" fn() {f}`
+}
diff --git a/src/test/ui/extern/extern-wrong-value-type.stderr b/src/test/ui/extern/extern-wrong-value-type.stderr
new file mode 100644
index 0000000..dce33f3
--- /dev/null
+++ b/src/test/ui/extern/extern-wrong-value-type.stderr
@@ -0,0 +1,17 @@
+error[E0277]: expected a `std::ops::Fn<()>` closure, found `extern "C" fn() {f}`
+  --> $DIR/extern-wrong-value-type.rs:9:5
+   |
+LL |     is_fn(f);
+   |     ^^^^^ expected an `Fn<()>` closure, found `extern "C" fn() {f}`
+   |
+   = help: the trait `std::ops::Fn<()>` is not implemented for `extern "C" fn() {f}`
+   = note: wrap the `extern "C" fn() {f}` in a closure with no arguments: `|| { /* code */ }
+note: required by `is_fn`
+  --> $DIR/extern-wrong-value-type.rs:4:1
+   |
+LL | fn is_fn<F>(_: F) where F: Fn() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/extern/external-doc-error.rs b/src/test/ui/extern/external-doc-error.rs
new file mode 100644
index 0000000..e17dda6
--- /dev/null
+++ b/src/test/ui/extern/external-doc-error.rs
@@ -0,0 +1,32 @@
+// normalize-stderr-test: "not-a-file.md:.*\(" -> "not-a-file.md: $$FILE_NOT_FOUND_MSG ("
+
+#![feature(external_doc)]
+
+#[doc(include = "not-a-file.md")]
+pub struct SomeStruct; //~^ ERROR couldn't read
+                       //~| HELP external doc paths are relative to the crate root
+
+#[doc(include = "auxiliary/invalid-utf8.txt")]
+pub struct InvalidUtf8; //~^ ERROR wasn't a utf-8 file
+
+#[doc(include)]
+pub struct MissingPath; //~^ ERROR expected path
+                        //~| HELP provide a file path with `=`
+                        //~| SUGGESTION include = "<path>"
+
+#[doc(include("../README.md"))]
+pub struct InvalidPathSyntax; //~^ ERROR expected path
+                              //~| HELP provide a file path with `=`
+                              //~| SUGGESTION include = "../README.md"
+
+#[doc(include = 123)]
+pub struct InvalidPathType; //~^ ERROR expected path
+                            //~| HELP provide a file path with `=`
+                            //~| SUGGESTION include = "<path>"
+
+#[doc(include(123))]
+pub struct InvalidPathSyntaxAndType; //~^ ERROR expected path
+                                     //~| HELP provide a file path with `=`
+                                     //~| SUGGESTION include = "<path>"
+
+fn main() {}
diff --git a/src/test/ui/extern/external-doc-error.stderr b/src/test/ui/extern/external-doc-error.stderr
new file mode 100644
index 0000000..a3be327
--- /dev/null
+++ b/src/test/ui/extern/external-doc-error.stderr
@@ -0,0 +1,40 @@
+error: couldn't read $DIR/not-a-file.md: $FILE_NOT_FOUND_MSG (os error 2)
+  --> $DIR/external-doc-error.rs:5:17
+   |
+LL | #[doc(include = "not-a-file.md")]
+   |                 ^^^^^^^^^^^^^^^ couldn't read file
+   |
+   = help: external doc paths are relative to the crate root
+
+error: $DIR/auxiliary/invalid-utf8.txt wasn't a utf-8 file
+  --> $DIR/external-doc-error.rs:9:17
+   |
+LL | #[doc(include = "auxiliary/invalid-utf8.txt")]
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ contains invalid utf-8
+
+error: expected path to external documentation
+  --> $DIR/external-doc-error.rs:12:7
+   |
+LL | #[doc(include)]
+   |       ^^^^^^^ help: provide a file path with `=`: `include = "<path>"`
+
+error: expected path to external documentation
+  --> $DIR/external-doc-error.rs:17:7
+   |
+LL | #[doc(include("../README.md"))]
+   |       ^^^^^^^^^^^^^^^^^^^^^^^ help: provide a file path with `=`: `include = "../README.md"`
+
+error: expected path to external documentation
+  --> $DIR/external-doc-error.rs:22:7
+   |
+LL | #[doc(include = 123)]
+   |       ^^^^^^^^^^^^^ help: provide a file path with `=`: `include = "<path>"`
+
+error: expected path to external documentation
+  --> $DIR/external-doc-error.rs:27:7
+   |
+LL | #[doc(include(123))]
+   |       ^^^^^^^^^^^^ help: provide a file path with `=`: `include = "<path>"`
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/extoption_env-no-args.rs b/src/test/ui/extoption_env-no-args.rs
new file mode 100644
index 0000000..bc5f77b
--- /dev/null
+++ b/src/test/ui/extoption_env-no-args.rs
@@ -0,0 +1 @@
+fn main() { option_env!(); } //~ ERROR: option_env! takes 1 argument
diff --git a/src/test/ui/extoption_env-no-args.stderr b/src/test/ui/extoption_env-no-args.stderr
new file mode 100644
index 0000000..386d517
--- /dev/null
+++ b/src/test/ui/extoption_env-no-args.stderr
@@ -0,0 +1,8 @@
+error: option_env! takes 1 argument
+  --> $DIR/extoption_env-no-args.rs:1:13
+   |
+LL | fn main() { option_env!(); }
+   |             ^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/extoption_env-not-string-literal.rs b/src/test/ui/extoption_env-not-string-literal.rs
new file mode 100644
index 0000000..27c3a8e
--- /dev/null
+++ b/src/test/ui/extoption_env-not-string-literal.rs
@@ -0,0 +1 @@
+fn main() { option_env!(10); } //~ ERROR: argument must be a string literal
diff --git a/src/test/ui/extoption_env-not-string-literal.stderr b/src/test/ui/extoption_env-not-string-literal.stderr
new file mode 100644
index 0000000..2727519
--- /dev/null
+++ b/src/test/ui/extoption_env-not-string-literal.stderr
@@ -0,0 +1,8 @@
+error: argument must be a string literal
+  --> $DIR/extoption_env-not-string-literal.rs:1:25
+   |
+LL | fn main() { option_env!(10); }
+   |                         ^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/extoption_env-too-many-args.rs b/src/test/ui/extoption_env-too-many-args.rs
new file mode 100644
index 0000000..ecc8b61
--- /dev/null
+++ b/src/test/ui/extoption_env-too-many-args.rs
@@ -0,0 +1 @@
+fn main() { option_env!("one", "two"); } //~ ERROR: option_env! takes 1 argument
diff --git a/src/test/ui/extoption_env-too-many-args.stderr b/src/test/ui/extoption_env-too-many-args.stderr
new file mode 100644
index 0000000..2ec5594
--- /dev/null
+++ b/src/test/ui/extoption_env-too-many-args.stderr
@@ -0,0 +1,8 @@
+error: option_env! takes 1 argument
+  --> $DIR/extoption_env-too-many-args.rs:1:13
+   |
+LL | fn main() { option_env!("one", "two"); }
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/fail-no-dead-code-core.rs b/src/test/ui/fail-no-dead-code-core.rs
new file mode 100644
index 0000000..bc74e80
--- /dev/null
+++ b/src/test/ui/fail-no-dead-code-core.rs
@@ -0,0 +1,18 @@
+#![deny(dead_code)]
+#![allow(unreachable_code)]
+
+#[macro_use]
+extern crate core;
+
+fn foo() { //~ ERROR function is never used
+
+    // none of these should have any dead_code exposed to the user
+    panic!();
+
+    panic!("foo");
+
+    panic!("bar {}", "baz")
+}
+
+
+fn main() {}
diff --git a/src/test/ui/fail-no-dead-code-core.stderr b/src/test/ui/fail-no-dead-code-core.stderr
new file mode 100644
index 0000000..2540242
--- /dev/null
+++ b/src/test/ui/fail-no-dead-code-core.stderr
@@ -0,0 +1,14 @@
+error: function is never used: `foo`
+  --> $DIR/fail-no-dead-code-core.rs:7:1
+   |
+LL | fn foo() {
+   | ^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/fail-no-dead-code-core.rs:1:9
+   |
+LL | #![deny(dead_code)]
+   |         ^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/fail-no-dead-code.rs b/src/test/ui/fail-no-dead-code.rs
new file mode 100644
index 0000000..2b69985
--- /dev/null
+++ b/src/test/ui/fail-no-dead-code.rs
@@ -0,0 +1,15 @@
+#![deny(dead_code)]
+#![allow(unreachable_code)]
+
+fn foo() { //~ ERROR function is never used
+
+    // none of these should have any dead_code exposed to the user
+    panic!();
+
+    panic!("foo");
+
+    panic!("bar {}", "baz")
+}
+
+
+fn main() {}
diff --git a/src/test/ui/fail-no-dead-code.stderr b/src/test/ui/fail-no-dead-code.stderr
new file mode 100644
index 0000000..8babcff
--- /dev/null
+++ b/src/test/ui/fail-no-dead-code.stderr
@@ -0,0 +1,14 @@
+error: function is never used: `foo`
+  --> $DIR/fail-no-dead-code.rs:4:1
+   |
+LL | fn foo() {
+   | ^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/fail-no-dead-code.rs:1:9
+   |
+LL | #![deny(dead_code)]
+   |         ^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/fail-simple.rs b/src/test/ui/fail-simple.rs
new file mode 100644
index 0000000..cd81a5d
--- /dev/null
+++ b/src/test/ui/fail-simple.rs
@@ -0,0 +1,3 @@
+fn main() {
+    panic!(@); //~ ERROR no rules expected the token `@`
+}
diff --git a/src/test/ui/fail-simple.stderr b/src/test/ui/fail-simple.stderr
new file mode 100644
index 0000000..26ed918
--- /dev/null
+++ b/src/test/ui/fail-simple.stderr
@@ -0,0 +1,8 @@
+error: no rules expected the token `@`
+  --> $DIR/fail-simple.rs:2:12
+   |
+LL |     panic!(@);
+   |            ^ no rules expected this token in macro call
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/fat-ptr-cast.rs b/src/test/ui/fat-ptr-cast.rs
new file mode 100644
index 0000000..eb419ba2
--- /dev/null
+++ b/src/test/ui/fat-ptr-cast.rs
@@ -0,0 +1,24 @@
+trait Trait {}
+
+// Make sure casts between thin-pointer <-> fat pointer obey RFC401
+fn main() {
+    let a: &[i32] = &[1, 2, 3];
+    let b: Box<[i32]> = Box::new([1, 2, 3]);
+    let p = a as *const [i32];
+    let q = a.as_ptr();
+
+    a as usize; //~ ERROR casting
+    a as isize; //~ ERROR casting
+    a as i16; //~ ERROR casting `&[i32]` as `i16` is invalid
+    a as u32; //~ ERROR casting `&[i32]` as `u32` is invalid
+    b as usize; //~ ERROR non-primitive cast
+    p as usize;
+    //~^ ERROR casting
+
+    // #22955
+    q as *const [i32]; //~ ERROR cannot cast
+
+    // #21397
+    let t: *mut (Trait + 'static) = 0 as *mut _; //~ ERROR casting
+    let mut fail: *const str = 0 as *const str; //~ ERROR casting
+}
diff --git a/src/test/ui/fat-ptr-cast.stderr b/src/test/ui/fat-ptr-cast.stderr
new file mode 100644
index 0000000..fb16024
--- /dev/null
+++ b/src/test/ui/fat-ptr-cast.stderr
@@ -0,0 +1,70 @@
+error[E0606]: casting `&[i32]` as `usize` is invalid
+  --> $DIR/fat-ptr-cast.rs:10:5
+   |
+LL |     a as usize;
+   |     ^^^^^^^^^^
+   |
+   = help: cast through a raw pointer first
+
+error[E0606]: casting `&[i32]` as `isize` is invalid
+  --> $DIR/fat-ptr-cast.rs:11:5
+   |
+LL |     a as isize;
+   |     ^^^^^^^^^^
+   |
+   = help: cast through a raw pointer first
+
+error[E0606]: casting `&[i32]` as `i16` is invalid
+  --> $DIR/fat-ptr-cast.rs:12:5
+   |
+LL |     a as i16;
+   |     ^^^^^^^^
+   |
+   = help: cast through a raw pointer first
+
+error[E0606]: casting `&[i32]` as `u32` is invalid
+  --> $DIR/fat-ptr-cast.rs:13:5
+   |
+LL |     a as u32;
+   |     ^^^^^^^^
+   |
+   = help: cast through a raw pointer first
+
+error[E0605]: non-primitive cast: `std::boxed::Box<[i32]>` as `usize`
+  --> $DIR/fat-ptr-cast.rs:14:5
+   |
+LL |     b as usize;
+   |     ^^^^^^^^^^
+   |
+   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+
+error[E0606]: casting `*const [i32]` as `usize` is invalid
+  --> $DIR/fat-ptr-cast.rs:15:5
+   |
+LL |     p as usize;
+   |     ^^^^^^^^^^
+   |
+   = help: cast through a thin pointer first
+
+error[E0607]: cannot cast thin pointer `*const i32` to fat pointer `*const [i32]`
+  --> $DIR/fat-ptr-cast.rs:19:5
+   |
+LL |     q as *const [i32];
+   |     ^^^^^^^^^^^^^^^^^
+
+error[E0606]: casting `usize` as `*mut (dyn Trait + 'static)` is invalid
+  --> $DIR/fat-ptr-cast.rs:22:37
+   |
+LL |     let t: *mut (Trait + 'static) = 0 as *mut _;
+   |                                     ^^^^^^^^^^^
+
+error[E0606]: casting `usize` as `*const str` is invalid
+  --> $DIR/fat-ptr-cast.rs:23:32
+   |
+LL |     let mut fail: *const str = 0 as *const str;
+   |                                ^^^^^^^^^^^^^^^
+
+error: aborting due to 9 previous errors
+
+Some errors occurred: E0605, E0606, E0607.
+For more information about an error, try `rustc --explain E0605`.
diff --git a/src/test/ui/feature-gate-optimize_attribute.rs b/src/test/ui/feature-gate-optimize_attribute.rs
new file mode 100644
index 0000000..c1f7510
--- /dev/null
+++ b/src/test/ui/feature-gate-optimize_attribute.rs
@@ -0,0 +1,18 @@
+#![crate_type="rlib"]
+#![optimize(speed)] //~ ERROR #54882
+
+#[optimize(size)] //~ ERROR #54882
+mod module {
+
+#[optimize(size)] //~ ERROR #54882
+fn size() {}
+
+#[optimize(speed)] //~ ERROR #54882
+fn speed() {}
+
+#[optimize(banana)]
+//~^ ERROR #54882
+//~| ERROR E0722
+fn not_known() {}
+
+}
diff --git a/src/test/ui/feature-gate-optimize_attribute.stderr b/src/test/ui/feature-gate-optimize_attribute.stderr
new file mode 100644
index 0000000..7635af6
--- /dev/null
+++ b/src/test/ui/feature-gate-optimize_attribute.stderr
@@ -0,0 +1,50 @@
+error[E0658]: #[optimize] attribute is an unstable feature (see issue #54882)
+  --> $DIR/feature-gate-optimize_attribute.rs:7:1
+   |
+LL | #[optimize(size)]
+   | ^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(optimize_attribute)] to the crate attributes to enable
+
+error[E0658]: #[optimize] attribute is an unstable feature (see issue #54882)
+  --> $DIR/feature-gate-optimize_attribute.rs:10:1
+   |
+LL | #[optimize(speed)]
+   | ^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(optimize_attribute)] to the crate attributes to enable
+
+error[E0658]: #[optimize] attribute is an unstable feature (see issue #54882)
+  --> $DIR/feature-gate-optimize_attribute.rs:13:1
+   |
+LL | #[optimize(banana)]
+   | ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(optimize_attribute)] to the crate attributes to enable
+
+error[E0658]: #[optimize] attribute is an unstable feature (see issue #54882)
+  --> $DIR/feature-gate-optimize_attribute.rs:4:1
+   |
+LL | #[optimize(size)]
+   | ^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(optimize_attribute)] to the crate attributes to enable
+
+error[E0658]: #[optimize] attribute is an unstable feature (see issue #54882)
+  --> $DIR/feature-gate-optimize_attribute.rs:2:1
+   |
+LL | #![optimize(speed)]
+   | ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(optimize_attribute)] to the crate attributes to enable
+
+error[E0722]: invalid argument
+  --> $DIR/feature-gate-optimize_attribute.rs:13:12
+   |
+LL | #[optimize(banana)]
+   |            ^^^^^^
+
+error: aborting due to 6 previous errors
+
+Some errors occurred: E0658, E0722.
+For more information about an error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gate/allow-features-empty.rs b/src/test/ui/feature-gate/allow-features-empty.rs
new file mode 100644
index 0000000..8325005
--- /dev/null
+++ b/src/test/ui/feature-gate/allow-features-empty.rs
@@ -0,0 +1,10 @@
+// compile-flags: -Z allow_features=
+// Note: This test uses rustc internal flags because they will never stabilize.
+
+#![feature(rustc_diagnostic_macros)] //~ ERROR
+
+#![feature(rustc_const_unstable)] //~ ERROR
+
+#![feature(lang_items)] //~ ERROR
+
+fn main() {}
diff --git a/src/test/ui/feature-gate/allow-features-empty.stderr b/src/test/ui/feature-gate/allow-features-empty.stderr
new file mode 100644
index 0000000..cce2c40
--- /dev/null
+++ b/src/test/ui/feature-gate/allow-features-empty.stderr
@@ -0,0 +1,21 @@
+error[E0725]: the feature `rustc_diagnostic_macros` is not in the list of allowed features
+  --> $DIR/allow-features-empty.rs:4:12
+   |
+LL | #![feature(rustc_diagnostic_macros)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0725]: the feature `rustc_const_unstable` is not in the list of allowed features
+  --> $DIR/allow-features-empty.rs:6:12
+   |
+LL | #![feature(rustc_const_unstable)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+
+error[E0725]: the feature `lang_items` is not in the list of allowed features
+  --> $DIR/allow-features-empty.rs:8:12
+   |
+LL | #![feature(lang_items)]
+   |            ^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0725`.
diff --git a/src/test/ui/feature-gate/allow-features.rs b/src/test/ui/feature-gate/allow-features.rs
new file mode 100644
index 0000000..1cebc8f
--- /dev/null
+++ b/src/test/ui/feature-gate/allow-features.rs
@@ -0,0 +1,10 @@
+// compile-flags: -Z allow_features=rustc_diagnostic_macros,lang_items
+// Note: This test uses rustc internal flags because they will never stabilize.
+
+#![feature(rustc_diagnostic_macros)]
+
+#![feature(rustc_const_unstable)] //~ ERROR
+
+#![feature(lang_items)]
+
+fn main() {}
diff --git a/src/test/ui/feature-gate/allow-features.stderr b/src/test/ui/feature-gate/allow-features.stderr
new file mode 100644
index 0000000..b13560f
--- /dev/null
+++ b/src/test/ui/feature-gate/allow-features.stderr
@@ -0,0 +1,9 @@
+error[E0725]: the feature `rustc_const_unstable` is not in the list of allowed features
+  --> $DIR/allow-features.rs:6:12
+   |
+LL | #![feature(rustc_const_unstable)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0725`.
diff --git a/src/test/ui/feature-gate/duplicate-features.rs b/src/test/ui/feature-gate/duplicate-features.rs
new file mode 100644
index 0000000..d8f7818
--- /dev/null
+++ b/src/test/ui/feature-gate/duplicate-features.rs
@@ -0,0 +1,9 @@
+#![allow(stable_features)]
+
+#![feature(rust1)]
+#![feature(rust1)] //~ ERROR the feature `rust1` has already been declared
+
+#![feature(if_let)]
+#![feature(if_let)] //~ ERROR the feature `if_let` has already been declared
+
+fn main() {}
diff --git a/src/test/ui/feature-gate/duplicate-features.stderr b/src/test/ui/feature-gate/duplicate-features.stderr
new file mode 100644
index 0000000..dbde806
--- /dev/null
+++ b/src/test/ui/feature-gate/duplicate-features.stderr
@@ -0,0 +1,15 @@
+error[E0636]: the feature `if_let` has already been declared
+  --> $DIR/duplicate-features.rs:7:12
+   |
+LL | #![feature(if_let)]
+   |            ^^^^^^
+
+error[E0636]: the feature `rust1` has already been declared
+  --> $DIR/duplicate-features.rs:4:12
+   |
+LL | #![feature(rust1)]
+   |            ^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0636`.
diff --git a/src/test/ui/feature-gate/feature-gate-c_variadic.rs b/src/test/ui/feature-gate/feature-gate-c_variadic.rs
new file mode 100644
index 0000000..5801a2a
--- /dev/null
+++ b/src/test/ui/feature-gate/feature-gate-c_variadic.rs
@@ -0,0 +1,4 @@
+#![crate_type="lib"]
+
+pub unsafe extern "C" fn test(_: i32, ap: ...) { }
+//~^ C-varaidic functions are unstable
diff --git a/src/test/ui/feature-gate/feature-gate-c_variadic.stderr b/src/test/ui/feature-gate/feature-gate-c_variadic.stderr
new file mode 100644
index 0000000..a876e16
--- /dev/null
+++ b/src/test/ui/feature-gate/feature-gate-c_variadic.stderr
@@ -0,0 +1,11 @@
+error[E0658]: C-varaidic functions are unstable (see issue #44930)
+  --> $DIR/feature-gate-c_variadic.rs:3:1
+   |
+LL | pub unsafe extern "C" fn test(_: i32, ap: ...) { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(c_variadic)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gate/feature-gate-static-nobundle-2.rs b/src/test/ui/feature-gate/feature-gate-static-nobundle-2.rs
new file mode 100644
index 0000000..92844f9
--- /dev/null
+++ b/src/test/ui/feature-gate/feature-gate-static-nobundle-2.rs
@@ -0,0 +1,6 @@
+//~ ERROR kind="static-nobundle" is feature gated
+// Test the behavior of rustc when non-existent library is statically linked
+
+// compile-flags: -l static-nobundle=nonexistent
+
+fn main() {}
diff --git a/src/test/ui/feature-gate/feature-gate-static-nobundle-2.stderr b/src/test/ui/feature-gate/feature-gate-static-nobundle-2.stderr
new file mode 100644
index 0000000..419c219
--- /dev/null
+++ b/src/test/ui/feature-gate/feature-gate-static-nobundle-2.stderr
@@ -0,0 +1,7 @@
+error[E0658]: kind="static-nobundle" is feature gated (see issue #37403)
+   |
+   = help: add #![feature(static_nobundle)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-bench.rs b/src/test/ui/feature-gate/issue-43106-gating-of-bench.rs
new file mode 100644
index 0000000..2d88689
--- /dev/null
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-bench.rs
@@ -0,0 +1,17 @@
+// error-pattern: `main` function not found
+
+// At time of authorship, a crate-level #![bench] with no `--test`
+// will cause compilation to error unconditionally with "main function
+// not found" (despite having one), similar to #[bench].
+//
+// (The non-crate level cases are in
+// issue-43106-gating-of-builtin-attrs.rs.)
+
+// See issue-12997-1.rs and issue-12997-2.rs to see how `#[bench]` is
+// handled in "weird places" when `--test` is passed.
+
+#![feature(custom_inner_attributes)]
+
+#![bench                   = "4100"]
+
+fn main() { }
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-bench.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-bench.stderr
new file mode 100644
index 0000000..503ef02
--- /dev/null
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-bench.stderr
@@ -0,0 +1,7 @@
+error[E0601]: `main` function not found in crate `issue_43106_gating_of_bench`
+   |
+   = note: consider adding a `main` function to `$DIR/issue-43106-gating-of-bench.rs`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0601`.
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.rs b/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.rs
new file mode 100644
index 0000000..b1a8cba
--- /dev/null
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.rs
@@ -0,0 +1,795 @@
+// This test enumerates as many compiler-builtin ungated attributes as
+// possible (that is, all the mutually compatible ones), and checks
+// that we get "expected" (*) warnings for each in the various weird
+// places that users might put them in the syntax.
+//
+// (*): The word "expected" is in quotes above because the cases where
+// warnings are and are not emitted might not match a user's intuition
+// nor the rustc developers' intent. I am really just trying to
+// capture today's behavior in a test, not so that it become enshrined
+// as the absolute behavior going forward, but rather so that we do
+// not change the behavior in the future without even being *aware* of
+// the change when it happens.
+//
+// At the time of authoring, the attributes here are listed in the
+// order that they occur in libsyntax/feature_gate.rs.
+//
+// Any builtin attributes that:
+//
+//  - are not stable, or
+//
+//  - could not be included here covering the same cases as the other
+//    attributes without raising an *error* from rustc (note though
+//    that warnings are of course expected)
+//
+// have their own test case referenced by filename in an inline
+// comment.
+//
+// The test feeds numeric inputs to each attribute that accepts them
+// without error. We do this for two reasons: (1.) to exercise how
+// inputs are handled by each, and (2.) to ease searching for related
+// occurrences in the source text.
+
+#![warn(unused_attributes, unknown_lints)]
+#![allow(stable_features)]
+
+// UNGATED WHITE-LISTED BUILT-IN ATTRIBUTES
+
+#![warn(x5400)] //~ WARN unknown lint: `x5400`
+#![allow(x5300)] //~ WARN unknown lint: `x5300`
+#![forbid(x5200)] //~ WARN unknown lint: `x5200`
+#![deny(x5100)] //~ WARN unknown lint: `x5100`
+#![macro_use] // (allowed if no argument; see issue-43160-gating-of-macro_use.rs)
+#![macro_export] //~ WARN unused attribute
+#![plugin_registrar] //~ WARN unused attribute
+// skipping testing of cfg
+// skipping testing of cfg_attr
+#![main] //~ WARN unused attribute
+#![start] //~ WARN unused attribute
+// see issue-43106-gating-of-test.rs for crate-level; but non crate-level is below at "4200"
+// see issue-43106-gating-of-bench.rs for crate-level; but non crate-level is below at "4100"
+#![repr()]
+//~^ WARN unused attribute
+#![path = "3800"] //~ WARN unused attribute
+#![automatically_derived] //~ WARN unused attribute
+#![no_mangle]
+#![no_link] //~ WARN unused attribute
+// see issue-43106-gating-of-derive.rs
+#![should_panic] //~ WARN unused attribute
+#![ignore] //~ WARN unused attribute
+#![no_implicit_prelude]
+#![reexport_test_harness_main = "2900"]
+// see gated-link-args.rs
+// see issue-43106-gating-of-macro_escape.rs for crate-level; but non crate-level is below at "2700"
+// (cannot easily test gating of crate-level #[no_std]; but non crate-level is below at "2600")
+#![proc_macro_derive()] //~ WARN unused attribute
+#![doc = "2400"]
+#![cold]
+#![export_name = "2200"]
+// see issue-43106-gating-of-inline.rs
+#![link()]
+#![link_name = "1900"]
+#![link_section = "1800"]
+#![no_builtins] // Yikes, dupe'd on BUILTIN_ATTRIBUTES list (see "0300")
+#![no_mangle] // Yikes, dupe'd on BUILTIN_ATTRIBUTES list (see "3500")
+// see issue-43106-gating-of-rustc_deprecated.rs
+#![must_use]
+// see issue-43106-gating-of-stable.rs
+// see issue-43106-gating-of-unstable.rs
+// see issue-43106-gating-of-deprecated.rs
+#![windows_subsystem = "1000"]
+
+// UNGATED CRATE-LEVEL BUILT-IN ATTRIBUTES
+
+#![crate_name = "0900"]
+#![crate_type = "bin"] // cannot pass "0800" here
+
+// For #![crate_id], see issue #43142. (I cannot bear to enshrine current behavior in a test)
+
+// FIXME(#44232) we should warn that this isn't used.
+#![feature(rust1)]
+
+// For #![no_start], see issue #43144. (I cannot bear to enshrine current behavior in a test)
+
+// (cannot easily gating state of crate-level #[no_main]; but non crate-level is below at "0400")
+#![no_builtins]
+#![recursion_limit = "0200"]
+#![type_length_limit = "0100"]
+
+// USES OF BUILT-IN ATTRIBUTES IN OTHER ("UNUSUAL") PLACES
+
+#[warn(x5400)]
+//~^ WARN unknown lint: `x5400`
+mod warn {
+    mod inner { #![warn(x5400)] }
+    //~^ WARN unknown lint: `x5400`
+
+    #[warn(x5400)] fn f() { }
+    //~^ WARN unknown lint: `x5400`
+
+    #[warn(x5400)] struct S;
+    //~^ WARN unknown lint: `x5400`
+
+    #[warn(x5400)] type T = S;
+    //~^ WARN unknown lint: `x5400`
+
+    #[warn(x5400)] impl S { }
+    //~^ WARN unknown lint: `x5400`
+}
+
+#[allow(x5300)]
+//~^ WARN unknown lint: `x5300`
+mod allow {
+    mod inner { #![allow(x5300)] }
+    //~^ WARN unknown lint: `x5300`
+
+    #[allow(x5300)] fn f() { }
+    //~^ WARN unknown lint: `x5300`
+
+    #[allow(x5300)] struct S;
+    //~^ WARN unknown lint: `x5300`
+
+    #[allow(x5300)] type T = S;
+    //~^ WARN unknown lint: `x5300`
+
+    #[allow(x5300)] impl S { }
+    //~^ WARN unknown lint: `x5300`
+}
+
+#[forbid(x5200)]
+//~^ WARN unknown lint: `x5200`
+mod forbid {
+    mod inner { #![forbid(x5200)] }
+    //~^ WARN unknown lint: `x5200`
+
+    #[forbid(x5200)] fn f() { }
+    //~^ WARN unknown lint: `x5200`
+
+    #[forbid(x5200)] struct S;
+    //~^ WARN unknown lint: `x5200`
+
+    #[forbid(x5200)] type T = S;
+    //~^ WARN unknown lint: `x5200`
+
+    #[forbid(x5200)] impl S { }
+    //~^ WARN unknown lint: `x5200`
+}
+
+#[deny(x5100)]
+//~^ WARN unknown lint: `x5100`
+mod deny {
+    mod inner { #![deny(x5100)] }
+    //~^ WARN unknown lint: `x5100`
+
+    #[deny(x5100)] fn f() { }
+    //~^ WARN unknown lint: `x5100`
+
+    #[deny(x5100)] struct S;
+    //~^ WARN unknown lint: `x5100`
+
+    #[deny(x5100)] type T = S;
+    //~^ WARN unknown lint: `x5100`
+
+    #[deny(x5100)] impl S { }
+    //~^ WARN unknown lint: `x5100`
+}
+
+#[macro_use]
+mod macro_use {
+    mod inner { #![macro_use] }
+
+    #[macro_use] fn f() { }
+    //~^ WARN unused attribute
+
+    #[macro_use] struct S;
+    //~^ WARN unused attribute
+
+    #[macro_use] type T = S;
+    //~^ WARN unused attribute
+
+    #[macro_use] impl S { }
+    //~^ WARN unused attribute
+}
+
+#[macro_export]
+//~^ WARN unused attribute
+mod macro_export {
+    mod inner { #![macro_export] }
+    //~^ WARN unused attribute
+
+    #[macro_export] fn f() { }
+    //~^ WARN unused attribute
+
+    #[macro_export] struct S;
+    //~^ WARN unused attribute
+
+    #[macro_export] type T = S;
+    //~^ WARN unused attribute
+
+    #[macro_export] impl S { }
+    //~^ WARN unused attribute
+}
+
+#[plugin_registrar]
+//~^ WARN unused attribute
+mod plugin_registrar {
+    mod inner { #![plugin_registrar] }
+    //~^ WARN unused attribute
+
+    // for `fn f()` case, see gated-plugin_registrar.rs
+
+    #[plugin_registrar] struct S;
+    //~^ WARN unused attribute
+
+    #[plugin_registrar] type T = S;
+    //~^ WARN unused attribute
+
+    #[plugin_registrar] impl S { }
+    //~^ WARN unused attribute
+}
+
+#[main]
+//~^ WARN unused attribute
+mod main {
+    mod inner { #![main] }
+    //~^ WARN unused attribute
+
+    // for `fn f()` case, see feature-gate-main.rs
+
+    #[main] struct S;
+    //~^ WARN unused attribute
+
+    #[main] type T = S;
+    //~^ WARN unused attribute
+
+    #[main] impl S { }
+    //~^ WARN unused attribute
+}
+
+#[start]
+//~^ WARN unused attribute
+mod start {
+    mod inner { #![start] }
+    //~^ WARN unused attribute
+
+    // for `fn f()` case, see feature-gate-start.rs
+
+    #[start] struct S;
+    //~^ WARN unused attribute
+
+    #[start] type T = S;
+    //~^ WARN unused attribute
+
+    #[start] impl S { }
+    //~^ WARN unused attribute
+}
+
+// At time of unit test authorship, if compiling without `--test` then
+// non-crate-level #[test] attributes seem to be ignored.
+
+#[test]
+mod test { mod inner { #![test] }
+
+    fn f() { }
+
+    struct S;
+
+    type T = S;
+
+    impl S { }
+}
+
+// At time of unit test authorship, if compiling without `--test` then
+// non-crate-level #[bench] attributes seem to be ignored.
+
+#[bench]
+mod bench {
+    mod inner { #![bench] }
+
+    #[bench]
+    struct S;
+
+    #[bench]
+    type T = S;
+
+    #[bench]
+    impl S { }
+}
+
+#[repr()]
+mod repr {
+    mod inner { #![repr()] }
+
+    #[repr()] fn f() { }
+
+    struct S;
+
+    #[repr()] type T = S;
+
+    #[repr()] impl S { }
+}
+
+#[path = "3800"]
+mod path {
+    mod inner { #![path="3800"] }
+
+    #[path = "3800"] fn f() { }
+    //~^ WARN unused attribute
+
+    #[path = "3800"]  struct S;
+    //~^ WARN unused attribute
+
+    #[path = "3800"] type T = S;
+    //~^ WARN unused attribute
+
+    #[path = "3800"] impl S { }
+    //~^ WARN unused attribute
+}
+
+#[automatically_derived]
+//~^ WARN unused attribute
+mod automatically_derived {
+    mod inner { #![automatically_derived] }
+    //~^ WARN unused attribute
+
+    #[automatically_derived] fn f() { }
+    //~^ WARN unused attribute
+
+    #[automatically_derived] struct S;
+    //~^ WARN unused attribute
+
+    #[automatically_derived] type T = S;
+    //~^ WARN unused attribute
+
+    #[automatically_derived] impl S { }
+    //~^ WARN unused attribute
+}
+
+#[no_mangle]
+mod no_mangle {
+    mod inner { #![no_mangle] }
+
+    #[no_mangle] fn f() { }
+
+    #[no_mangle] struct S;
+
+    #[no_mangle] type T = S;
+
+    #[no_mangle] impl S { }
+}
+
+#[no_link]
+//~^ WARN unused attribute
+mod no_link {
+    mod inner { #![no_link] }
+    //~^ WARN unused attribute
+
+    #[no_link] fn f() { }
+    //~^ WARN unused attribute
+
+    #[no_link] struct S;
+    //~^ WARN unused attribute
+
+    #[no_link]type T = S;
+    //~^ WARN unused attribute
+
+    #[no_link] impl S { }
+    //~^ WARN unused attribute
+}
+
+#[should_panic]
+//~^ WARN unused attribute
+mod should_panic {
+    mod inner { #![should_panic] }
+    //~^ WARN unused attribute
+
+    #[should_panic] fn f() { }
+    //~^ WARN unused attribute
+
+    #[should_panic] struct S;
+    //~^ WARN unused attribute
+
+    #[should_panic] type T = S;
+    //~^ WARN unused attribute
+
+    #[should_panic] impl S { }
+    //~^ WARN unused attribute
+}
+
+#[ignore]
+//~^ WARN unused attribute
+mod ignore {
+    mod inner { #![ignore] }
+    //~^ WARN unused attribute
+
+    #[ignore] fn f() { }
+    //~^ WARN unused attribute
+
+    #[ignore] struct S;
+    //~^ WARN unused attribute
+
+    #[ignore] type T = S;
+    //~^ WARN unused attribute
+
+    #[ignore] impl S { }
+    //~^ WARN unused attribute
+}
+
+#[no_implicit_prelude]
+//~^ WARN unused attribute
+mod no_implicit_prelude {
+    mod inner { #![no_implicit_prelude] }
+    //~^ WARN unused attribute
+
+    #[no_implicit_prelude] fn f() { }
+    //~^ WARN unused attribute
+
+    #[no_implicit_prelude] struct S;
+    //~^ WARN unused attribute
+
+    #[no_implicit_prelude] type T = S;
+    //~^ WARN unused attribute
+
+    #[no_implicit_prelude] impl S { }
+    //~^ WARN unused attribute
+}
+
+#[reexport_test_harness_main = "2900"]
+//~^ WARN unused attribute
+mod reexport_test_harness_main {
+    mod inner { #![reexport_test_harness_main="2900"] }
+    //~^ WARN unused attribute
+
+    #[reexport_test_harness_main = "2900"] fn f() { }
+    //~^ WARN unused attribute
+
+    #[reexport_test_harness_main = "2900"] struct S;
+    //~^ WARN unused attribute
+
+    #[reexport_test_harness_main = "2900"] type T = S;
+    //~^ WARN unused attribute
+
+    #[reexport_test_harness_main = "2900"] impl S { }
+    //~^ WARN unused attribute
+}
+
+// Cannot feed "2700" to `#[macro_escape]` without signaling an error.
+#[macro_escape]
+//~^ WARN macro_escape is a deprecated synonym for macro_use
+mod macro_escape {
+    mod inner { #![macro_escape] }
+    //~^ WARN macro_escape is a deprecated synonym for macro_use
+
+    #[macro_escape] fn f() { }
+    //~^ WARN unused attribute
+
+    #[macro_escape] struct S;
+    //~^ WARN unused attribute
+
+    #[macro_escape] type T = S;
+    //~^ WARN unused attribute
+
+    #[macro_escape] impl S { }
+    //~^ WARN unused attribute
+}
+
+#[no_std]
+//~^ WARN unused attribute
+//~| WARN crate-level attribute should be an inner attribute
+mod no_std {
+    mod inner { #![no_std] }
+    //~^ WARN unused attribute
+    //~| WARN crate-level attribute should be in the root module
+
+    #[no_std] fn f() { }
+    //~^ WARN unused attribute
+    //~| WARN crate-level attribute should be an inner attribute
+
+    #[no_std] struct S;
+    //~^ WARN unused attribute
+    //~| WARN crate-level attribute should be an inner attribute
+
+    #[no_std] type T = S;
+    //~^ WARN unused attribute
+    //~| WARN crate-level attribute should be an inner attribute
+
+    #[no_std] impl S { }
+    //~^ WARN unused attribute
+    //~| WARN crate-level attribute should be an inner attribute
+}
+
+// At time of authorship, #[proc_macro_derive = "2500"] signals error
+// when it occurs on a mod (apart from crate-level). Therefore it goes
+// into its own file; see issue-43106-gating-of-proc_macro_derive.rs
+
+#[doc = "2400"]
+mod doc {
+    mod inner { #![doc="2400"] }
+
+    #[doc = "2400"] fn f() { }
+
+    #[doc = "2400"] struct S;
+
+    #[doc = "2400"] type T = S;
+
+    #[doc = "2400"] impl S { }
+}
+
+#[cold]
+mod cold {
+    mod inner { #![cold] }
+
+    #[cold] fn f() { }
+
+    #[cold] struct S;
+
+    #[cold] type T = S;
+
+    #[cold] impl S { }
+}
+
+#[export_name = "2200"]
+mod export_name {
+    mod inner { #![export_name="2200"] }
+
+    #[export_name = "2200"] fn f() { }
+
+    #[export_name = "2200"] struct S;
+
+    #[export_name = "2200"] type T = S;
+
+    #[export_name = "2200"] impl S { }
+}
+
+// Note that this test has a `skip-codegen`, so it
+// will never invoke the linker. These are here nonetheless to point
+// out that we allow them at non-crate-level (though I do not know
+// whether they have the same effect here as at crate-level).
+
+#[link()]
+mod link {
+    mod inner { #![link()] }
+
+    #[link()] fn f() { }
+
+    #[link()] struct S;
+
+    #[link()] type T = S;
+
+    #[link()] impl S { }
+}
+
+#[link_name = "1900"]
+mod link_name {
+    mod inner { #![link_name="1900"] }
+
+    #[link_name = "1900"] fn f() { }
+
+    #[link_name = "1900"] struct S;
+
+    #[link_name = "1900"] type T = S;
+
+    #[link_name = "1900"] impl S { }
+}
+
+#[link_section = "1800"]
+mod link_section {
+    mod inner { #![link_section="1800"] }
+
+    #[link_section = "1800"] fn f() { }
+
+    #[link_section = "1800"] struct S;
+
+    #[link_section = "1800"] type T = S;
+
+    #[link_section = "1800"] impl S { }
+}
+
+struct StructForDeprecated;
+
+#[deprecated]
+mod deprecated {
+    mod inner { #![deprecated] }
+
+    #[deprecated] fn f() { }
+
+    #[deprecated] struct S1;
+
+    #[deprecated] type T = super::StructForDeprecated;
+
+    #[deprecated] impl super::StructForDeprecated { }
+}
+
+#[must_use]
+mod must_use {
+    mod inner { #![must_use] }
+
+    #[must_use] fn f() { }
+
+    #[must_use] struct S;
+
+    #[must_use] type T = S;
+
+    #[must_use] impl S { }
+}
+
+#[windows_subsystem = "1000"]
+mod windows_subsystem {
+    mod inner { #![windows_subsystem="1000"] }
+
+    #[windows_subsystem = "1000"] fn f() { }
+
+    #[windows_subsystem = "1000"] struct S;
+
+    #[windows_subsystem = "1000"] type T = S;
+
+    #[windows_subsystem = "1000"] impl S { }
+}
+
+// BROKEN USES OF CRATE-LEVEL BUILT-IN ATTRIBUTES
+
+#[crate_name = "0900"]
+//~^ WARN unused attribute
+//~| WARN crate-level attribute should be an inner attribute
+mod crate_name {
+    mod inner { #![crate_name="0900"] }
+    //~^ WARN unused attribute
+    //~| WARN crate-level attribute should be in the root module
+
+    #[crate_name = "0900"] fn f() { }
+    //~^ WARN unused attribute
+    //~| WARN crate-level attribute should be an inner attribute
+
+    #[crate_name = "0900"] struct S;
+    //~^ WARN unused attribute
+    //~| WARN crate-level attribute should be an inner attribute
+
+    #[crate_name = "0900"] type T = S;
+    //~^ WARN unused attribute
+    //~| WARN crate-level attribute should be an inner attribute
+
+    #[crate_name = "0900"] impl S { }
+    //~^ WARN unused attribute
+    //~| WARN crate-level attribute should be an inner attribute
+}
+
+#[crate_type = "0800"]
+//~^ WARN unused attribute
+//~| WARN crate-level attribute should be an inner attribute
+mod crate_type {
+    mod inner { #![crate_type="0800"] }
+    //~^ WARN unused attribute
+    //~| WARN crate-level attribute should be in the root module
+
+    #[crate_type = "0800"] fn f() { }
+    //~^ WARN unused attribute
+    //~| WARN crate-level attribute should be an inner attribute
+
+    #[crate_type = "0800"] struct S;
+    //~^ WARN unused attribute
+    //~| WARN crate-level attribute should be an inner attribute
+
+    #[crate_type = "0800"] type T = S;
+    //~^ WARN unused attribute
+    //~| WARN crate-level attribute should be an inner attribute
+
+    #[crate_type = "0800"] impl S { }
+    //~^ WARN unused attribute
+    //~| WARN crate-level attribute should be an inner attribute
+}
+
+#[feature(x0600)]
+//~^ WARN unused attribute
+//~| WARN crate-level attribute should be an inner attribute
+mod feature {
+    mod inner { #![feature(x0600)] }
+    //~^ WARN unused attribute
+    //~| WARN crate-level attribute should be in the root module
+
+    #[feature(x0600)] fn f() { }
+    //~^ WARN unused attribute
+    //~| WARN crate-level attribute should be an inner attribute
+
+    #[feature(x0600)] struct S;
+    //~^ WARN unused attribute
+    //~| WARN crate-level attribute should be an inner attribute
+
+    #[feature(x0600)] type T = S;
+    //~^ WARN unused attribute
+    //~| WARN crate-level attribute should be an inner attribute
+
+    #[feature(x0600)] impl S { }
+    //~^ WARN unused attribute
+    //~| WARN crate-level attribute should be an inner attribute
+}
+
+
+#[no_main]
+//~^ WARN unused attribute
+//~| WARN crate-level attribute should be an inner attribute
+mod no_main_1 {
+    mod inner { #![no_main] }
+    //~^ WARN unused attribute
+    //~| WARN crate-level attribute should be in the root module
+
+    #[no_main] fn f() { }
+    //~^ WARN unused attribute
+    //~| WARN crate-level attribute should be an inner attribute
+
+    #[no_main] struct S;
+    //~^ WARN unused attribute
+    //~| WARN crate-level attribute should be an inner attribute
+
+    #[no_main] type T = S;
+    //~^ WARN unused attribute
+    //~| WARN crate-level attribute should be an inner attribute
+
+    #[no_main] impl S { }
+    //~^ WARN unused attribute
+    //~| WARN crate-level attribute should be an inner attribute
+}
+
+#[no_builtins]
+mod no_builtins {
+    mod inner { #![no_builtins] }
+
+    #[no_builtins] fn f() { }
+
+    #[no_builtins] struct S;
+
+    #[no_builtins] type T = S;
+
+    #[no_builtins] impl S { }
+}
+
+#[recursion_limit="0200"]
+//~^ WARN unused attribute
+//~| WARN crate-level attribute should be an inner attribute
+mod recursion_limit {
+    mod inner { #![recursion_limit="0200"] }
+    //~^ WARN unused attribute
+    //~| WARN crate-level attribute should be in the root module
+
+    #[recursion_limit="0200"] fn f() { }
+    //~^ WARN unused attribute
+    //~| WARN crate-level attribute should be an inner attribute
+
+    #[recursion_limit="0200"] struct S;
+    //~^ WARN unused attribute
+    //~| WARN crate-level attribute should be an inner attribute
+
+    #[recursion_limit="0200"] type T = S;
+    //~^ WARN unused attribute
+    //~| WARN crate-level attribute should be an inner attribute
+
+    #[recursion_limit="0200"] impl S { }
+    //~^ WARN unused attribute
+    //~| WARN crate-level attribute should be an inner attribute
+}
+
+#[type_length_limit="0100"]
+//~^ WARN unused attribute
+//~| WARN crate-level attribute should be an inner attribute
+mod type_length_limit {
+    mod inner { #![type_length_limit="0100"] }
+    //~^ WARN unused attribute
+    //~| WARN crate-level attribute should be in the root module
+
+    #[type_length_limit="0100"] fn f() { }
+    //~^ WARN unused attribute
+    //~| WARN crate-level attribute should be an inner attribute
+
+    #[type_length_limit="0100"] struct S;
+    //~^ WARN unused attribute
+    //~| WARN crate-level attribute should be an inner attribute
+
+    #[type_length_limit="0100"] type T = S;
+    //~^ WARN unused attribute
+    //~| WARN crate-level attribute should be an inner attribute
+
+    #[type_length_limit="0100"] impl S { }
+    //~^ WARN unused attribute
+    //~| WARN crate-level attribute should be an inner attribute
+}
+
+fn main() {}
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr
new file mode 100644
index 0000000..c539e24
--- /dev/null
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr
@@ -0,0 +1,1182 @@
+warning: unknown lint: `x5400`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:38:9
+   |
+LL | #![warn(x5400)]
+   |         ^^^^^
+   |
+note: lint level defined here
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:33:28
+   |
+LL | #![warn(unused_attributes, unknown_lints)]
+   |                            ^^^^^^^^^^^^^
+
+warning: unknown lint: `x5300`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:39:10
+   |
+LL | #![allow(x5300)]
+   |          ^^^^^
+
+warning: unknown lint: `x5200`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:40:11
+   |
+LL | #![forbid(x5200)]
+   |           ^^^^^
+
+warning: unknown lint: `x5100`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:41:9
+   |
+LL | #![deny(x5100)]
+   |         ^^^^^
+
+warning: unknown lint: `x5400`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:101:8
+   |
+LL | #[warn(x5400)]
+   |        ^^^^^
+
+warning: unknown lint: `x5400`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:104:25
+   |
+LL |     mod inner { #![warn(x5400)] }
+   |                         ^^^^^
+
+warning: unknown lint: `x5400`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:107:12
+   |
+LL |     #[warn(x5400)] fn f() { }
+   |            ^^^^^
+
+warning: unknown lint: `x5400`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:110:12
+   |
+LL |     #[warn(x5400)] struct S;
+   |            ^^^^^
+
+warning: unknown lint: `x5400`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:113:12
+   |
+LL |     #[warn(x5400)] type T = S;
+   |            ^^^^^
+
+warning: unknown lint: `x5400`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:116:12
+   |
+LL |     #[warn(x5400)] impl S { }
+   |            ^^^^^
+
+warning: unknown lint: `x5300`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:120:9
+   |
+LL | #[allow(x5300)]
+   |         ^^^^^
+
+warning: unknown lint: `x5300`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:123:26
+   |
+LL |     mod inner { #![allow(x5300)] }
+   |                          ^^^^^
+
+warning: unknown lint: `x5300`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:126:13
+   |
+LL |     #[allow(x5300)] fn f() { }
+   |             ^^^^^
+
+warning: unknown lint: `x5300`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:129:13
+   |
+LL |     #[allow(x5300)] struct S;
+   |             ^^^^^
+
+warning: unknown lint: `x5300`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:132:13
+   |
+LL |     #[allow(x5300)] type T = S;
+   |             ^^^^^
+
+warning: unknown lint: `x5300`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:135:13
+   |
+LL |     #[allow(x5300)] impl S { }
+   |             ^^^^^
+
+warning: unknown lint: `x5200`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:139:10
+   |
+LL | #[forbid(x5200)]
+   |          ^^^^^
+
+warning: unknown lint: `x5200`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:142:27
+   |
+LL |     mod inner { #![forbid(x5200)] }
+   |                           ^^^^^
+
+warning: unknown lint: `x5200`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:145:14
+   |
+LL |     #[forbid(x5200)] fn f() { }
+   |              ^^^^^
+
+warning: unknown lint: `x5200`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:148:14
+   |
+LL |     #[forbid(x5200)] struct S;
+   |              ^^^^^
+
+warning: unknown lint: `x5200`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:151:14
+   |
+LL |     #[forbid(x5200)] type T = S;
+   |              ^^^^^
+
+warning: unknown lint: `x5200`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:154:14
+   |
+LL |     #[forbid(x5200)] impl S { }
+   |              ^^^^^
+
+warning: unknown lint: `x5100`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:158:8
+   |
+LL | #[deny(x5100)]
+   |        ^^^^^
+
+warning: unknown lint: `x5100`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:161:25
+   |
+LL |     mod inner { #![deny(x5100)] }
+   |                         ^^^^^
+
+warning: unknown lint: `x5100`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:164:12
+   |
+LL |     #[deny(x5100)] fn f() { }
+   |            ^^^^^
+
+warning: unknown lint: `x5100`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:167:12
+   |
+LL |     #[deny(x5100)] struct S;
+   |            ^^^^^
+
+warning: unknown lint: `x5100`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:170:12
+   |
+LL |     #[deny(x5100)] type T = S;
+   |            ^^^^^
+
+warning: unknown lint: `x5100`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:173:12
+   |
+LL |     #[deny(x5100)] impl S { }
+   |            ^^^^^
+
+warning: macro_escape is a deprecated synonym for macro_use
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:457:1
+   |
+LL | #[macro_escape]
+   | ^^^^^^^^^^^^^^^
+
+warning: macro_escape is a deprecated synonym for macro_use
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:460:17
+   |
+LL |     mod inner { #![macro_escape] }
+   |                 ^^^^^^^^^^^^^^^^
+   |
+   = help: consider an outer attribute, #[macro_use] mod ...
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:181:5
+   |
+LL |     #[macro_use] fn f() { }
+   |     ^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:33:9
+   |
+LL | #![warn(unused_attributes, unknown_lints)]
+   |         ^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:184:5
+   |
+LL |     #[macro_use] struct S;
+   |     ^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:187:5
+   |
+LL |     #[macro_use] type T = S;
+   |     ^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:190:5
+   |
+LL |     #[macro_use] impl S { }
+   |     ^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:197:17
+   |
+LL |     mod inner { #![macro_export] }
+   |                 ^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:200:5
+   |
+LL |     #[macro_export] fn f() { }
+   |     ^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:203:5
+   |
+LL |     #[macro_export] struct S;
+   |     ^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:206:5
+   |
+LL |     #[macro_export] type T = S;
+   |     ^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:209:5
+   |
+LL |     #[macro_export] impl S { }
+   |     ^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:194:1
+   |
+LL | #[macro_export]
+   | ^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:216:17
+   |
+LL |     mod inner { #![plugin_registrar] }
+   |                 ^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:221:5
+   |
+LL |     #[plugin_registrar] struct S;
+   |     ^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:224:5
+   |
+LL |     #[plugin_registrar] type T = S;
+   |     ^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:227:5
+   |
+LL |     #[plugin_registrar] impl S { }
+   |     ^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:213:1
+   |
+LL | #[plugin_registrar]
+   | ^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:234:17
+   |
+LL |     mod inner { #![main] }
+   |                 ^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:239:5
+   |
+LL |     #[main] struct S;
+   |     ^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:242:5
+   |
+LL |     #[main] type T = S;
+   |     ^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:245:5
+   |
+LL |     #[main] impl S { }
+   |     ^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:231:1
+   |
+LL | #[main]
+   | ^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:252:17
+   |
+LL |     mod inner { #![start] }
+   |                 ^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:257:5
+   |
+LL |     #[start] struct S;
+   |     ^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:260:5
+   |
+LL |     #[start] type T = S;
+   |     ^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:263:5
+   |
+LL |     #[start] impl S { }
+   |     ^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:249:1
+   |
+LL | #[start]
+   | ^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:316:5
+   |
+LL |     #[path = "3800"] fn f() { }
+   |     ^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:319:5
+   |
+LL |     #[path = "3800"]  struct S;
+   |     ^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:322:5
+   |
+LL |     #[path = "3800"] type T = S;
+   |     ^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:325:5
+   |
+LL |     #[path = "3800"] impl S { }
+   |     ^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:332:17
+   |
+LL |     mod inner { #![automatically_derived] }
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:335:5
+   |
+LL |     #[automatically_derived] fn f() { }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:338:5
+   |
+LL |     #[automatically_derived] struct S;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:341:5
+   |
+LL |     #[automatically_derived] type T = S;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:344:5
+   |
+LL |     #[automatically_derived] impl S { }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:329:1
+   |
+LL | #[automatically_derived]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:364:17
+   |
+LL |     mod inner { #![no_link] }
+   |                 ^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:367:5
+   |
+LL |     #[no_link] fn f() { }
+   |     ^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:370:5
+   |
+LL |     #[no_link] struct S;
+   |     ^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:373:5
+   |
+LL |     #[no_link]type T = S;
+   |     ^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:376:5
+   |
+LL |     #[no_link] impl S { }
+   |     ^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:361:1
+   |
+LL | #[no_link]
+   | ^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:383:17
+   |
+LL |     mod inner { #![should_panic] }
+   |                 ^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:386:5
+   |
+LL |     #[should_panic] fn f() { }
+   |     ^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:389:5
+   |
+LL |     #[should_panic] struct S;
+   |     ^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:392:5
+   |
+LL |     #[should_panic] type T = S;
+   |     ^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:395:5
+   |
+LL |     #[should_panic] impl S { }
+   |     ^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:380:1
+   |
+LL | #[should_panic]
+   | ^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:402:17
+   |
+LL |     mod inner { #![ignore] }
+   |                 ^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:405:5
+   |
+LL |     #[ignore] fn f() { }
+   |     ^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:408:5
+   |
+LL |     #[ignore] struct S;
+   |     ^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:411:5
+   |
+LL |     #[ignore] type T = S;
+   |     ^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:414:5
+   |
+LL |     #[ignore] impl S { }
+   |     ^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:399:1
+   |
+LL | #[ignore]
+   | ^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:421:17
+   |
+LL |     mod inner { #![no_implicit_prelude] }
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:424:5
+   |
+LL |     #[no_implicit_prelude] fn f() { }
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:427:5
+   |
+LL |     #[no_implicit_prelude] struct S;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:430:5
+   |
+LL |     #[no_implicit_prelude] type T = S;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:433:5
+   |
+LL |     #[no_implicit_prelude] impl S { }
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:418:1
+   |
+LL | #[no_implicit_prelude]
+   | ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:440:17
+   |
+LL |     mod inner { #![reexport_test_harness_main="2900"] }
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:443:5
+   |
+LL |     #[reexport_test_harness_main = "2900"] fn f() { }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:446:5
+   |
+LL |     #[reexport_test_harness_main = "2900"] struct S;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:449:5
+   |
+LL |     #[reexport_test_harness_main = "2900"] type T = S;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:452:5
+   |
+LL |     #[reexport_test_harness_main = "2900"] impl S { }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:437:1
+   |
+LL | #[reexport_test_harness_main = "2900"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:463:5
+   |
+LL |     #[macro_escape] fn f() { }
+   |     ^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:466:5
+   |
+LL |     #[macro_escape] struct S;
+   |     ^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:469:5
+   |
+LL |     #[macro_escape] type T = S;
+   |     ^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:472:5
+   |
+LL |     #[macro_escape] impl S { }
+   |     ^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:480:17
+   |
+LL |     mod inner { #![no_std] }
+   |                 ^^^^^^^^^^
+
+warning: crate-level attribute should be in the root module
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:480:17
+   |
+LL |     mod inner { #![no_std] }
+   |                 ^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:484:5
+   |
+LL |     #[no_std] fn f() { }
+   |     ^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:484:5
+   |
+LL |     #[no_std] fn f() { }
+   |     ^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:488:5
+   |
+LL |     #[no_std] struct S;
+   |     ^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:488:5
+   |
+LL |     #[no_std] struct S;
+   |     ^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:492:5
+   |
+LL |     #[no_std] type T = S;
+   |     ^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:492:5
+   |
+LL |     #[no_std] type T = S;
+   |     ^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:496:5
+   |
+LL |     #[no_std] impl S { }
+   |     ^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:496:5
+   |
+LL |     #[no_std] impl S { }
+   |     ^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:476:1
+   |
+LL | #[no_std]
+   | ^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:476:1
+   |
+LL | #[no_std]
+   | ^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:635:17
+   |
+LL |     mod inner { #![crate_name="0900"] }
+   |                 ^^^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be in the root module
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:635:17
+   |
+LL |     mod inner { #![crate_name="0900"] }
+   |                 ^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:639:5
+   |
+LL |     #[crate_name = "0900"] fn f() { }
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:639:5
+   |
+LL |     #[crate_name = "0900"] fn f() { }
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:643:5
+   |
+LL |     #[crate_name = "0900"] struct S;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:643:5
+   |
+LL |     #[crate_name = "0900"] struct S;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:647:5
+   |
+LL |     #[crate_name = "0900"] type T = S;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:647:5
+   |
+LL |     #[crate_name = "0900"] type T = S;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:651:5
+   |
+LL |     #[crate_name = "0900"] impl S { }
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:651:5
+   |
+LL |     #[crate_name = "0900"] impl S { }
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:631:1
+   |
+LL | #[crate_name = "0900"]
+   | ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:631:1
+   |
+LL | #[crate_name = "0900"]
+   | ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:660:17
+   |
+LL |     mod inner { #![crate_type="0800"] }
+   |                 ^^^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be in the root module
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:660:17
+   |
+LL |     mod inner { #![crate_type="0800"] }
+   |                 ^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:664:5
+   |
+LL |     #[crate_type = "0800"] fn f() { }
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:664:5
+   |
+LL |     #[crate_type = "0800"] fn f() { }
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:668:5
+   |
+LL |     #[crate_type = "0800"] struct S;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:668:5
+   |
+LL |     #[crate_type = "0800"] struct S;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:672:5
+   |
+LL |     #[crate_type = "0800"] type T = S;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:672:5
+   |
+LL |     #[crate_type = "0800"] type T = S;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:676:5
+   |
+LL |     #[crate_type = "0800"] impl S { }
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:676:5
+   |
+LL |     #[crate_type = "0800"] impl S { }
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:656:1
+   |
+LL | #[crate_type = "0800"]
+   | ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:656:1
+   |
+LL | #[crate_type = "0800"]
+   | ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:685:17
+   |
+LL |     mod inner { #![feature(x0600)] }
+   |                 ^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be in the root module
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:685:17
+   |
+LL |     mod inner { #![feature(x0600)] }
+   |                 ^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:689:5
+   |
+LL |     #[feature(x0600)] fn f() { }
+   |     ^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:689:5
+   |
+LL |     #[feature(x0600)] fn f() { }
+   |     ^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:693:5
+   |
+LL |     #[feature(x0600)] struct S;
+   |     ^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:693:5
+   |
+LL |     #[feature(x0600)] struct S;
+   |     ^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:697:5
+   |
+LL |     #[feature(x0600)] type T = S;
+   |     ^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:697:5
+   |
+LL |     #[feature(x0600)] type T = S;
+   |     ^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:701:5
+   |
+LL |     #[feature(x0600)] impl S { }
+   |     ^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:701:5
+   |
+LL |     #[feature(x0600)] impl S { }
+   |     ^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:681:1
+   |
+LL | #[feature(x0600)]
+   | ^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:681:1
+   |
+LL | #[feature(x0600)]
+   | ^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:711:17
+   |
+LL |     mod inner { #![no_main] }
+   |                 ^^^^^^^^^^^
+
+warning: crate-level attribute should be in the root module
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:711:17
+   |
+LL |     mod inner { #![no_main] }
+   |                 ^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:715:5
+   |
+LL |     #[no_main] fn f() { }
+   |     ^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:715:5
+   |
+LL |     #[no_main] fn f() { }
+   |     ^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:719:5
+   |
+LL |     #[no_main] struct S;
+   |     ^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:719:5
+   |
+LL |     #[no_main] struct S;
+   |     ^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:723:5
+   |
+LL |     #[no_main] type T = S;
+   |     ^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:723:5
+   |
+LL |     #[no_main] type T = S;
+   |     ^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:727:5
+   |
+LL |     #[no_main] impl S { }
+   |     ^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:727:5
+   |
+LL |     #[no_main] impl S { }
+   |     ^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:707:1
+   |
+LL | #[no_main]
+   | ^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:707:1
+   |
+LL | #[no_main]
+   | ^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:749:17
+   |
+LL |     mod inner { #![recursion_limit="0200"] }
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be in the root module
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:749:17
+   |
+LL |     mod inner { #![recursion_limit="0200"] }
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:753:5
+   |
+LL |     #[recursion_limit="0200"] fn f() { }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:753:5
+   |
+LL |     #[recursion_limit="0200"] fn f() { }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:757:5
+   |
+LL |     #[recursion_limit="0200"] struct S;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:757:5
+   |
+LL |     #[recursion_limit="0200"] struct S;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:761:5
+   |
+LL |     #[recursion_limit="0200"] type T = S;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:761:5
+   |
+LL |     #[recursion_limit="0200"] type T = S;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:765:5
+   |
+LL |     #[recursion_limit="0200"] impl S { }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:765:5
+   |
+LL |     #[recursion_limit="0200"] impl S { }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:745:1
+   |
+LL | #[recursion_limit="0200"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:745:1
+   |
+LL | #[recursion_limit="0200"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:774:17
+   |
+LL |     mod inner { #![type_length_limit="0100"] }
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be in the root module
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:774:17
+   |
+LL |     mod inner { #![type_length_limit="0100"] }
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:778:5
+   |
+LL |     #[type_length_limit="0100"] fn f() { }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:778:5
+   |
+LL |     #[type_length_limit="0100"] fn f() { }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:782:5
+   |
+LL |     #[type_length_limit="0100"] struct S;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:782:5
+   |
+LL |     #[type_length_limit="0100"] struct S;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:786:5
+   |
+LL |     #[type_length_limit="0100"] type T = S;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:786:5
+   |
+LL |     #[type_length_limit="0100"] type T = S;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:790:5
+   |
+LL |     #[type_length_limit="0100"] impl S { }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:790:5
+   |
+LL |     #[type_length_limit="0100"] impl S { }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:770:1
+   |
+LL | #[type_length_limit="0100"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:770:1
+   |
+LL | #[type_length_limit="0100"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:43:1
+   |
+LL | #![macro_export]
+   | ^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:44:1
+   |
+LL | #![plugin_registrar]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:47:1
+   |
+LL | #![main]
+   | ^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:48:1
+   |
+LL | #![start]
+   | ^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:51:1
+   |
+LL | #![repr()]
+   | ^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:53:1
+   |
+LL | #![path = "3800"]
+   | ^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:54:1
+   |
+LL | #![automatically_derived]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:56:1
+   |
+LL | #![no_link]
+   | ^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:58:1
+   |
+LL | #![should_panic]
+   | ^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:59:1
+   |
+LL | #![ignore]
+   | ^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:65:1
+   |
+LL | #![proc_macro_derive()]
+   | ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: invalid windows subsystem `1000`, only `windows` and `console` are allowed
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-deprecated.rs b/src/test/ui/feature-gate/issue-43106-gating-of-deprecated.rs
new file mode 100644
index 0000000..360d570
--- /dev/null
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-deprecated.rs
@@ -0,0 +1,13 @@
+// This test just shows that a crate-level `#![deprecated]` does not
+// signal a warning or error. (This file sits on its own because a
+// crate-level `#![deprecated]` causes all that crate's item
+// definitions to be deprecated, which is a pain to work with.)
+//
+// (For non-crate-level cases, see issue-43106-gating-of-builtin-attrs.rs)
+
+// compile-pass
+// skip-codegen
+
+#![deprecated]
+
+fn main() {}
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-derive-2.rs b/src/test/ui/feature-gate/issue-43106-gating-of-derive-2.rs
new file mode 100644
index 0000000..5f276f6
--- /dev/null
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-derive-2.rs
@@ -0,0 +1,17 @@
+// This test checks cases where the derive-macro does not exist.
+
+mod derive {
+    #[derive(x3300)]
+    //~^ ERROR cannot find derive macro `x3300` in this scope
+    union U { f: i32 }
+
+    #[derive(x3300)]
+    //~^ ERROR cannot find derive macro `x3300` in this scope
+    enum E { }
+
+    #[derive(x3300)]
+    //~^ ERROR cannot find derive macro `x3300` in this scope
+    struct S;
+}
+
+fn main() {}
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-derive-2.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-derive-2.stderr
new file mode 100644
index 0000000..be3536a
--- /dev/null
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-derive-2.stderr
@@ -0,0 +1,20 @@
+error: cannot find derive macro `x3300` in this scope
+  --> $DIR/issue-43106-gating-of-derive-2.rs:4:14
+   |
+LL |     #[derive(x3300)]
+   |              ^^^^^
+
+error: cannot find derive macro `x3300` in this scope
+  --> $DIR/issue-43106-gating-of-derive-2.rs:8:14
+   |
+LL |     #[derive(x3300)]
+   |              ^^^^^
+
+error: cannot find derive macro `x3300` in this scope
+  --> $DIR/issue-43106-gating-of-derive-2.rs:12:14
+   |
+LL |     #[derive(x3300)]
+   |              ^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-derive.rs b/src/test/ui/feature-gate/issue-43106-gating-of-derive.rs
new file mode 100644
index 0000000..1397412
--- /dev/null
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-derive.rs
@@ -0,0 +1,35 @@
+// `#![derive]` raises errors when it occurs at contexts other than ADT
+// definitions.
+
+#![derive(Debug)]
+//~^ ERROR `derive` may only be applied to structs, enums and unions
+
+#[derive(Debug)]
+//~^ ERROR `derive` may only be applied to structs, enums and unions
+mod derive {
+    mod inner { #![derive(Debug)] }
+    //~^ ERROR `derive` may only be applied to structs, enums and unions
+
+    #[derive(Debug)]
+    //~^ ERROR `derive` may only be applied to structs, enums and unions
+    fn derive() { }
+
+    #[derive(Copy, Clone)] // (can't derive Debug for unions)
+    union U { f: i32 }
+
+    #[derive(Debug)]
+    struct S;
+
+    #[derive(Debug)]
+    enum E { }
+
+    #[derive(Debug)]
+    //~^ ERROR `derive` may only be applied to structs, enums and unions
+    type T = S;
+
+    #[derive(Debug)]
+    //~^ ERROR `derive` may only be applied to structs, enums and unions
+    impl S { }
+}
+
+fn main() {}
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-derive.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-derive.stderr
new file mode 100644
index 0000000..25f1609
--- /dev/null
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-derive.stderr
@@ -0,0 +1,38 @@
+error: `derive` may only be applied to structs, enums and unions
+  --> $DIR/issue-43106-gating-of-derive.rs:4:1
+   |
+LL | #![derive(Debug)]
+   | ^^^^^^^^^^^^^^^^^ help: try an outer attribute: `#[derive(Debug)]`
+
+error: `derive` may only be applied to structs, enums and unions
+  --> $DIR/issue-43106-gating-of-derive.rs:7:1
+   |
+LL | #[derive(Debug)]
+   | ^^^^^^^^^^^^^^^^
+
+error: `derive` may only be applied to structs, enums and unions
+  --> $DIR/issue-43106-gating-of-derive.rs:10:17
+   |
+LL |     mod inner { #![derive(Debug)] }
+   |                 ^^^^^^^^^^^^^^^^^ help: try an outer attribute: `#[derive(Debug)]`
+
+error: `derive` may only be applied to structs, enums and unions
+  --> $DIR/issue-43106-gating-of-derive.rs:13:5
+   |
+LL |     #[derive(Debug)]
+   |     ^^^^^^^^^^^^^^^^
+
+error: `derive` may only be applied to structs, enums and unions
+  --> $DIR/issue-43106-gating-of-derive.rs:26:5
+   |
+LL |     #[derive(Debug)]
+   |     ^^^^^^^^^^^^^^^^
+
+error: `derive` may only be applied to structs, enums and unions
+  --> $DIR/issue-43106-gating-of-derive.rs:30:5
+   |
+LL |     #[derive(Debug)]
+   |     ^^^^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-inline.rs b/src/test/ui/feature-gate/issue-43106-gating-of-inline.rs
new file mode 100644
index 0000000..bb9e6d4
--- /dev/null
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-inline.rs
@@ -0,0 +1,31 @@
+// This is testing whether `#[inline]` signals an error or warning
+// when put in "weird" places.
+//
+// (This file sits on its own because it actually signals an error,
+// which would mess up the treatment of other cases in
+// issue-43106-gating-of-builtin-attrs.rs)
+
+// Crate-level is accepted, though it is almost certainly unused?
+#![inline]
+
+#[inline]
+//~^ ERROR attribute should be applied to function or closure
+mod inline {
+    mod inner { #![inline] }
+    //~^ ERROR attribute should be applied to function or closure
+
+    #[inline = "2100"] fn f() { }
+    //~^ WARN attribute must be of the form
+    //~| WARN this was previously accepted
+
+    #[inline] struct S;
+    //~^ ERROR attribute should be applied to function or closure
+
+    #[inline] type T = S;
+    //~^ ERROR attribute should be applied to function or closure
+
+    #[inline] impl S { }
+    //~^ ERROR attribute should be applied to function or closure
+}
+
+fn main() {}
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-inline.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-inline.stderr
new file mode 100644
index 0000000..ef89a88
--- /dev/null
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-inline.stderr
@@ -0,0 +1,52 @@
+warning: attribute must be of the form `#[inline]` or `#[inline(always|never)]`
+  --> $DIR/issue-43106-gating-of-inline.rs:17:5
+   |
+LL |     #[inline = "2100"] fn f() { }
+   |     ^^^^^^^^^^^^^^^^^^
+   |
+   = note: #[warn(ill_formed_attribute_input)] on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
+
+error[E0518]: attribute should be applied to function or closure
+  --> $DIR/issue-43106-gating-of-inline.rs:11:1
+   |
+LL |   #[inline]
+   |   ^^^^^^^^^
+LL |
+LL | / mod inline {
+LL | |     mod inner { #![inline] }
+LL | |
+LL | |
+...  |
+LL | |
+LL | | }
+   | |_- not a function or closure
+
+error[E0518]: attribute should be applied to function or closure
+  --> $DIR/issue-43106-gating-of-inline.rs:14:17
+   |
+LL |     mod inner { #![inline] }
+   |     ------------^^^^^^^^^^-- not a function or closure
+
+error[E0518]: attribute should be applied to function or closure
+  --> $DIR/issue-43106-gating-of-inline.rs:21:5
+   |
+LL |     #[inline] struct S;
+   |     ^^^^^^^^^ --------- not a function or closure
+
+error[E0518]: attribute should be applied to function or closure
+  --> $DIR/issue-43106-gating-of-inline.rs:24:5
+   |
+LL |     #[inline] type T = S;
+   |     ^^^^^^^^^ ----------- not a function or closure
+
+error[E0518]: attribute should be applied to function or closure
+  --> $DIR/issue-43106-gating-of-inline.rs:27:5
+   |
+LL |     #[inline] impl S { }
+   |     ^^^^^^^^^ ---------- not a function or closure
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0518`.
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-macro_escape.rs b/src/test/ui/feature-gate/issue-43106-gating-of-macro_escape.rs
new file mode 100644
index 0000000..98ca344
--- /dev/null
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-macro_escape.rs
@@ -0,0 +1,11 @@
+// Testing that crate-level `#![macro_escape]` is not gated beyond a
+// depecation warning.  This file sits on its own, because crate-level
+// `#![macro_escape]` is incompatible with crate-level `#![macro_use]`
+// already present in issue-43106-gating-of-builtin-attrs.
+
+// compile-pass
+
+#![macro_escape]
+//~^ WARN macro_escape is a deprecated synonym for macro_use
+
+fn main() {}
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-macro_escape.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-macro_escape.stderr
new file mode 100644
index 0000000..9fb9633
--- /dev/null
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-macro_escape.stderr
@@ -0,0 +1,8 @@
+warning: macro_escape is a deprecated synonym for macro_use
+  --> $DIR/issue-43106-gating-of-macro_escape.rs:8:1
+   |
+LL | #![macro_escape]
+   | ^^^^^^^^^^^^^^^^
+   |
+   = help: consider an outer attribute, #[macro_use] mod ...
+
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-macro_use.rs b/src/test/ui/feature-gate/issue-43106-gating-of-macro_use.rs
new file mode 100644
index 0000000..725f2e0
--- /dev/null
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-macro_use.rs
@@ -0,0 +1,25 @@
+// This is just a check-list of the cases where feeding arguments to
+// `#[macro_use]` is rejected. (The cases where no error is emitted
+// corresponds to cases where the attribute is currently unused, so we
+// get that warning; see issue-43106-gating-of-builtin-attrs.rs
+
+#![macro_use(my_macro)]
+//~^ ERROR arguments to macro_use are not allowed here
+
+#[macro_use(my_macro)]
+//~^ ERROR arguments to macro_use are not allowed here
+mod macro_escape {
+    mod inner { #![macro_use(my_macro)] }
+    //~^ ERROR arguments to macro_use are not allowed here
+
+    #[macro_use = "2700"] struct S;
+    //~^ ERROR attribute must be of the form
+
+    #[macro_use] fn f() { }
+
+    #[macro_use] type T = S;
+
+    #[macro_use] impl S { }
+}
+
+fn main() { }
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-macro_use.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-macro_use.stderr
new file mode 100644
index 0000000..8074528
--- /dev/null
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-macro_use.stderr
@@ -0,0 +1,26 @@
+error: arguments to macro_use are not allowed here
+  --> $DIR/issue-43106-gating-of-macro_use.rs:6:1
+   |
+LL | #![macro_use(my_macro)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: arguments to macro_use are not allowed here
+  --> $DIR/issue-43106-gating-of-macro_use.rs:9:1
+   |
+LL | #[macro_use(my_macro)]
+   | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: arguments to macro_use are not allowed here
+  --> $DIR/issue-43106-gating-of-macro_use.rs:12:17
+   |
+LL |     mod inner { #![macro_use(my_macro)] }
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: attribute must be of the form `#[macro_use]` or `#[macro_use(name1, name2, ...)]`
+  --> $DIR/issue-43106-gating-of-macro_use.rs:15:5
+   |
+LL |     #[macro_use = "2700"] struct S;
+   |     ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-proc_macro_derive.rs b/src/test/ui/feature-gate/issue-43106-gating-of-proc_macro_derive.rs
new file mode 100644
index 0000000..a94ffd6
--- /dev/null
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-proc_macro_derive.rs
@@ -0,0 +1,34 @@
+// At time of authorship, #[proc_macro_derive = "2500"] will emit an
+// error when it occurs on a mod (apart from crate-level), but will
+// not descend further into the mod for other occurrences of the same
+// error.
+//
+// This file sits on its own because the "weird" occurrences here
+// signal errors, making it incompatible with the "warnings only"
+// nature of issue-43106-gating-of-builtin-attrs.rs
+
+#[proc_macro_derive()]
+//~^ ERROR the `#[proc_macro_derive]` attribute may only be used on bare functions
+mod proc_macro_derive1 {
+    mod inner { #![proc_macro_derive()] }
+    // (no error issued here if there was one on outer module)
+}
+
+mod proc_macro_derive2 {
+    mod inner { #![proc_macro_derive()] }
+    //~^ ERROR the `#[proc_macro_derive]` attribute may only be used on bare functions
+
+    #[proc_macro_derive()] fn f() { }
+    //~^ ERROR the `#[proc_macro_derive]` attribute is only usable with crates of the `proc-macro`
+
+    #[proc_macro_derive()] struct S;
+    //~^ ERROR the `#[proc_macro_derive]` attribute may only be used on bare functions
+
+    #[proc_macro_derive()] type T = S;
+    //~^ ERROR the `#[proc_macro_derive]` attribute may only be used on bare functions
+
+    #[proc_macro_derive()] impl S { }
+    //~^ ERROR the `#[proc_macro_derive]` attribute may only be used on bare functions
+}
+
+fn main() {}
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-proc_macro_derive.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-proc_macro_derive.stderr
new file mode 100644
index 0000000..e202b47
--- /dev/null
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-proc_macro_derive.stderr
@@ -0,0 +1,38 @@
+error: the `#[proc_macro_derive]` attribute may only be used on bare functions
+  --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:10:1
+   |
+LL | #[proc_macro_derive()]
+   | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: the `#[proc_macro_derive]` attribute may only be used on bare functions
+  --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:18:17
+   |
+LL |     mod inner { #![proc_macro_derive()] }
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: the `#[proc_macro_derive]` attribute is only usable with crates of the `proc-macro` crate type
+  --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:21:5
+   |
+LL |     #[proc_macro_derive()] fn f() { }
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error: the `#[proc_macro_derive]` attribute may only be used on bare functions
+  --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:24:5
+   |
+LL |     #[proc_macro_derive()] struct S;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error: the `#[proc_macro_derive]` attribute may only be used on bare functions
+  --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:27:5
+   |
+LL |     #[proc_macro_derive()] type T = S;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error: the `#[proc_macro_derive]` attribute may only be used on bare functions
+  --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:30:5
+   |
+LL |     #[proc_macro_derive()] impl S { }
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-rustc_deprecated.rs b/src/test/ui/feature-gate/issue-43106-gating-of-rustc_deprecated.rs
new file mode 100644
index 0000000..60873f9
--- /dev/null
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-rustc_deprecated.rs
@@ -0,0 +1,29 @@
+// Testing gating of `#[rustc_deprecated]` in "weird" places.
+//
+// This file sits on its own because these signal errors, making
+// this test incompatible with the "warnings only" nature of
+// issue-43106-gating-of-builtin-attrs.rs
+
+#![rustc_deprecated()]
+//~^ ERROR stability attributes may not be used outside of the standard library
+
+#[rustc_deprecated()]
+//~^ ERROR stability attributes may not be used outside of the standard library
+mod rustc_deprecated {
+    mod inner { #![rustc_deprecated()] }
+    //~^ ERROR stability attributes may not be used outside of the standard library
+
+    #[rustc_deprecated()] fn f() { }
+    //~^ ERROR stability attributes may not be used outside of the standard library
+
+    #[rustc_deprecated()] struct S;
+    //~^ ERROR stability attributes may not be used outside of the standard library
+
+    #[rustc_deprecated()] type T = S;
+    //~^ ERROR stability attributes may not be used outside of the standard library
+
+    #[rustc_deprecated()] impl S { }
+    //~^ ERROR stability attributes may not be used outside of the standard library
+}
+
+fn main() {}
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-rustc_deprecated.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-rustc_deprecated.stderr
new file mode 100644
index 0000000..4eead36
--- /dev/null
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-rustc_deprecated.stderr
@@ -0,0 +1,44 @@
+error: stability attributes may not be used outside of the standard library
+  --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:7:1
+   |
+LL | #![rustc_deprecated()]
+   | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: stability attributes may not be used outside of the standard library
+  --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:10:1
+   |
+LL | #[rustc_deprecated()]
+   | ^^^^^^^^^^^^^^^^^^^^^
+
+error: stability attributes may not be used outside of the standard library
+  --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:13:17
+   |
+LL |     mod inner { #![rustc_deprecated()] }
+   |                 ^^^^^^^^^^^^^^^^^^^^^^
+
+error: stability attributes may not be used outside of the standard library
+  --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:16:5
+   |
+LL |     #[rustc_deprecated()] fn f() { }
+   |     ^^^^^^^^^^^^^^^^^^^^^
+
+error: stability attributes may not be used outside of the standard library
+  --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:19:5
+   |
+LL |     #[rustc_deprecated()] struct S;
+   |     ^^^^^^^^^^^^^^^^^^^^^
+
+error: stability attributes may not be used outside of the standard library
+  --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:22:5
+   |
+LL |     #[rustc_deprecated()] type T = S;
+   |     ^^^^^^^^^^^^^^^^^^^^^
+
+error: stability attributes may not be used outside of the standard library
+  --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:25:5
+   |
+LL |     #[rustc_deprecated()] impl S { }
+   |     ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 7 previous errors
+
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-stable.rs b/src/test/ui/feature-gate/issue-43106-gating-of-stable.rs
new file mode 100644
index 0000000..e3ac274
--- /dev/null
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-stable.rs
@@ -0,0 +1,29 @@
+// Testing gating of `#[stable]` in "weird" places.
+//
+// This file sits on its own because these signal errors, making
+// this test incompatible with the "warnings only" nature of
+// issue-43106-gating-of-builtin-attrs.rs
+
+#![stable()]
+//~^ ERROR stability attributes may not be used outside of the standard library
+
+#[stable()]
+//~^ ERROR stability attributes may not be used outside of the standard library
+mod stable {
+    mod inner { #![stable()] }
+    //~^ ERROR stability attributes may not be used outside of the standard library
+
+    #[stable()] fn f() { }
+    //~^ ERROR stability attributes may not be used outside of the standard library
+
+    #[stable()] struct S;
+    //~^ ERROR stability attributes may not be used outside of the standard library
+
+    #[stable()] type T = S;
+    //~^ ERROR stability attributes may not be used outside of the standard library
+
+    #[stable()] impl S { }
+    //~^ ERROR stability attributes may not be used outside of the standard library
+}
+
+fn main() {}
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-stable.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-stable.stderr
new file mode 100644
index 0000000..03410ea
--- /dev/null
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-stable.stderr
@@ -0,0 +1,44 @@
+error: stability attributes may not be used outside of the standard library
+  --> $DIR/issue-43106-gating-of-stable.rs:7:1
+   |
+LL | #![stable()]
+   | ^^^^^^^^^^^^
+
+error: stability attributes may not be used outside of the standard library
+  --> $DIR/issue-43106-gating-of-stable.rs:10:1
+   |
+LL | #[stable()]
+   | ^^^^^^^^^^^
+
+error: stability attributes may not be used outside of the standard library
+  --> $DIR/issue-43106-gating-of-stable.rs:13:17
+   |
+LL |     mod inner { #![stable()] }
+   |                 ^^^^^^^^^^^^
+
+error: stability attributes may not be used outside of the standard library
+  --> $DIR/issue-43106-gating-of-stable.rs:16:5
+   |
+LL |     #[stable()] fn f() { }
+   |     ^^^^^^^^^^^
+
+error: stability attributes may not be used outside of the standard library
+  --> $DIR/issue-43106-gating-of-stable.rs:19:5
+   |
+LL |     #[stable()] struct S;
+   |     ^^^^^^^^^^^
+
+error: stability attributes may not be used outside of the standard library
+  --> $DIR/issue-43106-gating-of-stable.rs:22:5
+   |
+LL |     #[stable()] type T = S;
+   |     ^^^^^^^^^^^
+
+error: stability attributes may not be used outside of the standard library
+  --> $DIR/issue-43106-gating-of-stable.rs:25:5
+   |
+LL |     #[stable()] impl S { }
+   |     ^^^^^^^^^^^
+
+error: aborting due to 7 previous errors
+
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-test.rs b/src/test/ui/feature-gate/issue-43106-gating-of-test.rs
new file mode 100644
index 0000000..c0c49d3
--- /dev/null
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-test.rs
@@ -0,0 +1,12 @@
+// error-pattern: `main` function not found
+
+// At time of authorship, crate-level #[test] attribute with no
+// `--test` signals unconditional error complaining of missing main
+// function (despite having one), similar to #[bench].
+//
+// (The non-crate level cases are in
+// issue-43106-gating-of-builtin-attrs.rs.)
+
+#![test                    = "4200"]
+
+fn main() { }
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-test.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-test.stderr
new file mode 100644
index 0000000..2ab35be
--- /dev/null
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-test.stderr
@@ -0,0 +1,7 @@
+error[E0601]: `main` function not found in crate `issue_43106_gating_of_test`
+   |
+   = note: consider adding a `main` function to `$DIR/issue-43106-gating-of-test.rs`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0601`.
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-unstable.rs b/src/test/ui/feature-gate/issue-43106-gating-of-unstable.rs
new file mode 100644
index 0000000..8d519c3
--- /dev/null
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-unstable.rs
@@ -0,0 +1,29 @@
+// Testing gating of `#[unstable]` in "weird" places.
+//
+// This file sits on its own because these signal errors, making
+// this test incompatible with the "warnings only" nature of
+// issue-43106-gating-of-builtin-attrs.rs
+
+#![unstable()]
+//~^ ERROR stability attributes may not be used outside of the standard library
+
+#[unstable()]
+//~^ ERROR stability attributes may not be used outside of the standard library
+mod unstable {
+    mod inner { #![unstable()] }
+    //~^ ERROR stability attributes may not be used outside of the standard library
+
+    #[unstable()] fn f() { }
+    //~^ ERROR stability attributes may not be used outside of the standard library
+
+    #[unstable()] struct S;
+    //~^ ERROR stability attributes may not be used outside of the standard library
+
+    #[unstable()] type T = S;
+    //~^ ERROR stability attributes may not be used outside of the standard library
+
+    #[unstable()] impl S { }
+    //~^ ERROR stability attributes may not be used outside of the standard library
+}
+
+fn main() {}
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-unstable.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-unstable.stderr
new file mode 100644
index 0000000..5952b38
--- /dev/null
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-unstable.stderr
@@ -0,0 +1,44 @@
+error: stability attributes may not be used outside of the standard library
+  --> $DIR/issue-43106-gating-of-unstable.rs:7:1
+   |
+LL | #![unstable()]
+   | ^^^^^^^^^^^^^^
+
+error: stability attributes may not be used outside of the standard library
+  --> $DIR/issue-43106-gating-of-unstable.rs:10:1
+   |
+LL | #[unstable()]
+   | ^^^^^^^^^^^^^
+
+error: stability attributes may not be used outside of the standard library
+  --> $DIR/issue-43106-gating-of-unstable.rs:13:17
+   |
+LL |     mod inner { #![unstable()] }
+   |                 ^^^^^^^^^^^^^^
+
+error: stability attributes may not be used outside of the standard library
+  --> $DIR/issue-43106-gating-of-unstable.rs:16:5
+   |
+LL |     #[unstable()] fn f() { }
+   |     ^^^^^^^^^^^^^
+
+error: stability attributes may not be used outside of the standard library
+  --> $DIR/issue-43106-gating-of-unstable.rs:19:5
+   |
+LL |     #[unstable()] struct S;
+   |     ^^^^^^^^^^^^^
+
+error: stability attributes may not be used outside of the standard library
+  --> $DIR/issue-43106-gating-of-unstable.rs:22:5
+   |
+LL |     #[unstable()] type T = S;
+   |     ^^^^^^^^^^^^^
+
+error: stability attributes may not be used outside of the standard library
+  --> $DIR/issue-43106-gating-of-unstable.rs:25:5
+   |
+LL |     #[unstable()] impl S { }
+   |     ^^^^^^^^^^^^^
+
+error: aborting due to 7 previous errors
+
diff --git a/src/test/ui/feature-gate/issue-49983-see-issue-0.rs b/src/test/ui/feature-gate/issue-49983-see-issue-0.rs
new file mode 100644
index 0000000..eeb80d0
--- /dev/null
+++ b/src/test/ui/feature-gate/issue-49983-see-issue-0.rs
@@ -0,0 +1,6 @@
+extern crate core;
+
+// error should not say "(see issue #0)"
+#[allow(unused_imports)] use core::ptr::Unique; //~ ERROR use of unstable library feature
+
+fn main() {}
diff --git a/src/test/ui/feature-gate/issue-49983-see-issue-0.stderr b/src/test/ui/feature-gate/issue-49983-see-issue-0.stderr
new file mode 100644
index 0000000..8377532
--- /dev/null
+++ b/src/test/ui/feature-gate/issue-49983-see-issue-0.stderr
@@ -0,0 +1,11 @@
+error[E0658]: use of unstable library feature 'ptr_internals': use NonNull instead and consider PhantomData<T> (if you also use #[may_dangle]), Send, and/or Sync
+  --> $DIR/issue-49983-see-issue-0.rs:4:30
+   |
+LL | #[allow(unused_imports)] use core::ptr::Unique;
+   |                              ^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(ptr_internals)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gate/stability-attribute-consistency.rs b/src/test/ui/feature-gate/stability-attribute-consistency.rs
new file mode 100644
index 0000000..caafd8b
--- /dev/null
+++ b/src/test/ui/feature-gate/stability-attribute-consistency.rs
@@ -0,0 +1,16 @@
+#![stable(feature = "stable_test_feature", since = "1.0.0")]
+
+#![feature(staged_api)]
+
+#[stable(feature = "foo", since = "1.0.0")]
+fn foo_stable_1_0_0() {}
+
+#[stable(feature = "foo", since = "1.29.0")]
+//~^ ERROR feature `foo` is declared stable since 1.29.0
+fn foo_stable_1_29_0() {}
+
+#[unstable(feature = "foo", issue = "0")]
+//~^ ERROR feature `foo` is declared unstable
+fn foo_unstable() {}
+
+fn main() {}
diff --git a/src/test/ui/feature-gate/stability-attribute-consistency.stderr b/src/test/ui/feature-gate/stability-attribute-consistency.stderr
new file mode 100644
index 0000000..191b25d
--- /dev/null
+++ b/src/test/ui/feature-gate/stability-attribute-consistency.stderr
@@ -0,0 +1,15 @@
+error[E0711]: feature `foo` is declared stable since 1.29.0, but was previously declared stable since 1.0.0
+  --> $DIR/stability-attribute-consistency.rs:8:1
+   |
+LL | #[stable(feature = "foo", since = "1.29.0")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0711]: feature `foo` is declared unstable, but was previously declared stable
+  --> $DIR/stability-attribute-consistency.rs:12:1
+   |
+LL | #[unstable(feature = "foo", issue = "0")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0711`.
diff --git a/src/test/ui/feature-gate/unknown-feature.rs b/src/test/ui/feature-gate/unknown-feature.rs
new file mode 100644
index 0000000..20fd932
--- /dev/null
+++ b/src/test/ui/feature-gate/unknown-feature.rs
@@ -0,0 +1,3 @@
+#![feature(unknown_rust_feature)] //~ ERROR unknown feature
+
+fn main() {}
diff --git a/src/test/ui/feature-gate/unknown-feature.stderr b/src/test/ui/feature-gate/unknown-feature.stderr
new file mode 100644
index 0000000..e5c0587
--- /dev/null
+++ b/src/test/ui/feature-gate/unknown-feature.stderr
@@ -0,0 +1,9 @@
+error[E0635]: unknown feature `unknown_rust_feature`
+  --> $DIR/unknown-feature.rs:1:12
+   |
+LL | #![feature(unknown_rust_feature)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0635`.
diff --git a/src/test/ui/feature-gated-feature-in-macro-arg.rs b/src/test/ui/feature-gated-feature-in-macro-arg.rs
new file mode 100644
index 0000000..1285cca
--- /dev/null
+++ b/src/test/ui/feature-gated-feature-in-macro-arg.rs
@@ -0,0 +1,14 @@
+// tests that input to a macro is checked for use of gated features. If this
+// test succeeds due to the acceptance of a feature, pick a new feature to
+// test. Not ideal, but oh well :(
+
+fn main() {
+    let a = &[1, 2, 3];
+    println!("{}", {
+        extern "rust-intrinsic" { //~ ERROR intrinsics are subject to change
+            fn atomic_fence();
+        }
+        atomic_fence();
+        42
+    });
+}
diff --git a/src/test/ui/feature-gated-feature-in-macro-arg.stderr b/src/test/ui/feature-gated-feature-in-macro-arg.stderr
new file mode 100644
index 0000000..5cbd102
--- /dev/null
+++ b/src/test/ui/feature-gated-feature-in-macro-arg.stderr
@@ -0,0 +1,13 @@
+error[E0658]: intrinsics are subject to change
+  --> $DIR/feature-gated-feature-in-macro-arg.rs:8:9
+   |
+LL | /         extern "rust-intrinsic" {
+LL | |             fn atomic_fence();
+LL | |         }
+   | |_________^
+   |
+   = help: add #![feature(intrinsics)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/auxiliary/cfg-target-thread-local.rs b/src/test/ui/feature-gates/auxiliary/cfg-target-thread-local.rs
new file mode 100644
index 0000000..bd5c8f8
--- /dev/null
+++ b/src/test/ui/feature-gates/auxiliary/cfg-target-thread-local.rs
@@ -0,0 +1,7 @@
+#![feature(thread_local)]
+#![feature(cfg_target_thread_local)]
+#![crate_type = "lib"]
+
+#[no_mangle]
+#[cfg_attr(target_thread_local, thread_local)]
+pub static FOO: u32 = 3;
diff --git a/src/test/ui/feature-gates/auxiliary/pub_dep.rs b/src/test/ui/feature-gates/auxiliary/pub_dep.rs
new file mode 100644
index 0000000..3ebafd9
--- /dev/null
+++ b/src/test/ui/feature-gates/auxiliary/pub_dep.rs
@@ -0,0 +1 @@
+pub struct PubType;
diff --git a/src/test/ui/feature-gates/auxiliary/re_rebalance_coherence_lib.rs b/src/test/ui/feature-gates/auxiliary/re_rebalance_coherence_lib.rs
new file mode 100644
index 0000000..c8d027b
--- /dev/null
+++ b/src/test/ui/feature-gates/auxiliary/re_rebalance_coherence_lib.rs
@@ -0,0 +1,23 @@
+
+pub trait Backend{}
+pub trait SupportsDefaultKeyword {}
+
+impl SupportsDefaultKeyword for Postgres {}
+
+pub struct Postgres;
+
+impl Backend for Postgres {}
+
+pub struct AstPass<DB>(::std::marker::PhantomData<DB>);
+
+pub trait QueryFragment<DB: Backend> {}
+
+
+#[derive(Debug, Clone, Copy)]
+pub struct BatchInsert<'a, T: 'a, Tab> {
+    _marker: ::std::marker::PhantomData<(&'a T, Tab)>,
+}
+
+impl<'a, T:'a, Tab, DB> QueryFragment<DB> for BatchInsert<'a, T, Tab>
+where DB: SupportsDefaultKeyword + Backend,
+{}
diff --git a/src/test/ui/feature-gates/feature-gate-abi-msp430-interrupt.rs b/src/test/ui/feature-gates/feature-gate-abi-msp430-interrupt.rs
new file mode 100644
index 0000000..37c39b6
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-abi-msp430-interrupt.rs
@@ -0,0 +1,9 @@
+// Test that the MSP430 interrupt ABI cannot be used when msp430_interrupt
+// feature gate is not used.
+
+extern "msp430-interrupt" fn foo() {}
+//~^ ERROR msp430-interrupt ABI is experimental and subject to change
+
+fn main() {
+    foo();
+}
diff --git a/src/test/ui/feature-gates/feature-gate-abi-msp430-interrupt.stderr b/src/test/ui/feature-gates/feature-gate-abi-msp430-interrupt.stderr
new file mode 100644
index 0000000..6b3c169
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-abi-msp430-interrupt.stderr
@@ -0,0 +1,11 @@
+error[E0658]: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
+  --> $DIR/feature-gate-abi-msp430-interrupt.rs:4:1
+   |
+LL | extern "msp430-interrupt" fn foo() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_msp430_interrupt)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-abi.rs b/src/test/ui/feature-gates/feature-gate-abi.rs
new file mode 100644
index 0000000..41c9f79
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-abi.rs
@@ -0,0 +1,95 @@
+// only-x86_64
+// ignore-tidy-linelength
+// gate-test-intrinsics
+// gate-test-platform_intrinsics
+// gate-test-abi_vectorcall
+// gate-test-abi_thiscall
+// gate-test-abi_ptx
+// gate-test-abi_x86_interrupt
+// gate-test-abi_amdgpu_kernel
+
+// Functions
+extern "rust-intrinsic" fn f1() {} //~ ERROR intrinsics are subject to change
+extern "platform-intrinsic" fn f2() {} //~ ERROR platform intrinsics are experimental
+extern "vectorcall" fn f3() {} //~ ERROR vectorcall is experimental and subject to change
+extern "rust-call" fn f4() {} //~ ERROR rust-call ABI is subject to change
+extern "msp430-interrupt" fn f5() {} //~ ERROR msp430-interrupt ABI is experimental
+extern "ptx-kernel" fn f6() {} //~ ERROR PTX ABIs are experimental and subject to change
+extern "x86-interrupt" fn f7() {} //~ ERROR x86-interrupt ABI is experimental
+extern "thiscall" fn f8() {} //~ ERROR thiscall is experimental and subject to change
+extern "amdgpu-kernel" fn f9() {} //~ ERROR amdgpu-kernel ABI is experimental and subject to change
+
+// Methods in trait definition
+trait Tr {
+    extern "rust-intrinsic" fn m1(); //~ ERROR intrinsics are subject to change
+    extern "platform-intrinsic" fn m2(); //~ ERROR platform intrinsics are experimental
+    extern "vectorcall" fn m3(); //~ ERROR vectorcall is experimental and subject to change
+    extern "rust-call" fn m4(); //~ ERROR rust-call ABI is subject to change
+    extern "msp430-interrupt" fn m5(); //~ ERROR msp430-interrupt ABI is experimental
+    extern "ptx-kernel" fn m6(); //~ ERROR PTX ABIs are experimental and subject to change
+    extern "x86-interrupt" fn m7(); //~ ERROR x86-interrupt ABI is experimental
+    extern "thiscall" fn m8(); //~ ERROR thiscall is experimental and subject to change
+    extern "amdgpu-kernel" fn m9(); //~ ERROR amdgpu-kernel ABI is experimental and subject to change
+
+    extern "rust-intrinsic" fn dm1() {} //~ ERROR intrinsics are subject to change
+    extern "platform-intrinsic" fn dm2() {} //~ ERROR platform intrinsics are experimental
+    extern "vectorcall" fn dm3() {} //~ ERROR vectorcall is experimental and subject to change
+    extern "rust-call" fn dm4() {} //~ ERROR rust-call ABI is subject to change
+    extern "msp430-interrupt" fn dm5() {} //~ ERROR msp430-interrupt ABI is experimental
+    extern "ptx-kernel" fn dm6() {} //~ ERROR PTX ABIs are experimental and subject to change
+    extern "x86-interrupt" fn dm7() {} //~ ERROR x86-interrupt ABI is experimental
+    extern "thiscall" fn dm8() {} //~ ERROR thiscall is experimental and subject to change
+    extern "amdgpu-kernel" fn dm9() {} //~ ERROR amdgpu-kernel ABI is experimental and subject to change
+}
+
+struct S;
+
+// Methods in trait impl
+impl Tr for S {
+    extern "rust-intrinsic" fn m1() {} //~ ERROR intrinsics are subject to change
+    extern "platform-intrinsic" fn m2() {} //~ ERROR platform intrinsics are experimental
+    extern "vectorcall" fn m3() {} //~ ERROR vectorcall is experimental and subject to change
+    extern "rust-call" fn m4() {} //~ ERROR rust-call ABI is subject to change
+    extern "msp430-interrupt" fn m5() {} //~ ERROR msp430-interrupt ABI is experimental
+    extern "ptx-kernel" fn m6() {} //~ ERROR PTX ABIs are experimental and subject to change
+    extern "x86-interrupt" fn m7() {} //~ ERROR x86-interrupt ABI is experimental
+    extern "thiscall" fn m8() {} //~ ERROR thiscall is experimental and subject to change
+    extern "amdgpu-kernel" fn m9() {} //~ ERROR amdgpu-kernel ABI is experimental and subject to change
+}
+
+// Methods in inherent impl
+impl S {
+    extern "rust-intrinsic" fn im1() {} //~ ERROR intrinsics are subject to change
+    extern "platform-intrinsic" fn im2() {} //~ ERROR platform intrinsics are experimental
+    extern "vectorcall" fn im3() {} //~ ERROR vectorcall is experimental and subject to change
+    extern "rust-call" fn im4() {} //~ ERROR rust-call ABI is subject to change
+    extern "msp430-interrupt" fn im5() {} //~ ERROR msp430-interrupt ABI is experimental
+    extern "ptx-kernel" fn im6() {} //~ ERROR PTX ABIs are experimental and subject to change
+    extern "x86-interrupt" fn im7() {} //~ ERROR x86-interrupt ABI is experimental
+    extern "thiscall" fn im8() {} //~ ERROR thiscall is experimental and subject to change
+    extern "amdgpu-kernel" fn im9() {} //~ ERROR amdgpu-kernel ABI is experimental and subject to change
+}
+
+// Function pointer types
+type A1 = extern "rust-intrinsic" fn(); //~ ERROR intrinsics are subject to change
+type A2 = extern "platform-intrinsic" fn(); //~ ERROR platform intrinsics are experimental
+type A3 = extern "vectorcall" fn(); //~ ERROR vectorcall is experimental and subject to change
+type A4 = extern "rust-call" fn(); //~ ERROR rust-call ABI is subject to change
+type A5 = extern "msp430-interrupt" fn(); //~ ERROR msp430-interrupt ABI is experimental
+type A6 = extern "ptx-kernel" fn (); //~ ERROR PTX ABIs are experimental and subject to change
+type A7 = extern "x86-interrupt" fn(); //~ ERROR x86-interrupt ABI is experimental
+type A8 = extern "thiscall" fn(); //~ ERROR thiscall is experimental and subject to change
+type A9 = extern "amdgpu-kernel" fn(); //~ ERROR amdgpu-kernel ABI is experimental and subject to change
+
+// Foreign modules
+extern "rust-intrinsic" {} //~ ERROR intrinsics are subject to change
+extern "platform-intrinsic" {} //~ ERROR platform intrinsics are experimental
+extern "vectorcall" {} //~ ERROR vectorcall is experimental and subject to change
+extern "rust-call" {} //~ ERROR rust-call ABI is subject to change
+extern "msp430-interrupt" {} //~ ERROR msp430-interrupt ABI is experimental
+extern "ptx-kernel" {} //~ ERROR PTX ABIs are experimental and subject to change
+extern "x86-interrupt" {} //~ ERROR x86-interrupt ABI is experimental
+extern "thiscall" {} //~ ERROR thiscall is experimental and subject to change
+extern "amdgpu-kernel" {} //~ ERROR amdgpu-kernel ABI is experimental and subject to change
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-abi.stderr b/src/test/ui/feature-gates/feature-gate-abi.stderr
new file mode 100644
index 0000000..7417f31
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-abi.stderr
@@ -0,0 +1,507 @@
+error[E0658]: intrinsics are subject to change
+  --> $DIR/feature-gate-abi.rs:12:1
+   |
+LL | extern "rust-intrinsic" fn f1() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(intrinsics)] to the crate attributes to enable
+
+error[E0658]: platform intrinsics are experimental and possibly buggy (see issue #27731)
+  --> $DIR/feature-gate-abi.rs:13:1
+   |
+LL | extern "platform-intrinsic" fn f2() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(platform_intrinsics)] to the crate attributes to enable
+
+error[E0658]: vectorcall is experimental and subject to change
+  --> $DIR/feature-gate-abi.rs:14:1
+   |
+LL | extern "vectorcall" fn f3() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_vectorcall)] to the crate attributes to enable
+
+error[E0658]: rust-call ABI is subject to change (see issue #29625)
+  --> $DIR/feature-gate-abi.rs:15:1
+   |
+LL | extern "rust-call" fn f4() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unboxed_closures)] to the crate attributes to enable
+
+error[E0658]: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
+  --> $DIR/feature-gate-abi.rs:16:1
+   |
+LL | extern "msp430-interrupt" fn f5() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_msp430_interrupt)] to the crate attributes to enable
+
+error[E0658]: PTX ABIs are experimental and subject to change (see issue #38788)
+  --> $DIR/feature-gate-abi.rs:17:1
+   |
+LL | extern "ptx-kernel" fn f6() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_ptx)] to the crate attributes to enable
+
+error[E0658]: x86-interrupt ABI is experimental and subject to change (see issue #40180)
+  --> $DIR/feature-gate-abi.rs:18:1
+   |
+LL | extern "x86-interrupt" fn f7() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_x86_interrupt)] to the crate attributes to enable
+
+error[E0658]: thiscall is experimental and subject to change
+  --> $DIR/feature-gate-abi.rs:19:1
+   |
+LL | extern "thiscall" fn f8() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_thiscall)] to the crate attributes to enable
+
+error[E0658]: amdgpu-kernel ABI is experimental and subject to change (see issue #51575)
+  --> $DIR/feature-gate-abi.rs:20:1
+   |
+LL | extern "amdgpu-kernel" fn f9() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_amdgpu_kernel)] to the crate attributes to enable
+
+error[E0658]: intrinsics are subject to change
+  --> $DIR/feature-gate-abi.rs:24:5
+   |
+LL |     extern "rust-intrinsic" fn m1();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(intrinsics)] to the crate attributes to enable
+
+error[E0658]: platform intrinsics are experimental and possibly buggy (see issue #27731)
+  --> $DIR/feature-gate-abi.rs:25:5
+   |
+LL |     extern "platform-intrinsic" fn m2();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(platform_intrinsics)] to the crate attributes to enable
+
+error[E0658]: vectorcall is experimental and subject to change
+  --> $DIR/feature-gate-abi.rs:26:5
+   |
+LL |     extern "vectorcall" fn m3();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_vectorcall)] to the crate attributes to enable
+
+error[E0658]: rust-call ABI is subject to change (see issue #29625)
+  --> $DIR/feature-gate-abi.rs:27:5
+   |
+LL |     extern "rust-call" fn m4();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unboxed_closures)] to the crate attributes to enable
+
+error[E0658]: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
+  --> $DIR/feature-gate-abi.rs:28:5
+   |
+LL |     extern "msp430-interrupt" fn m5();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_msp430_interrupt)] to the crate attributes to enable
+
+error[E0658]: PTX ABIs are experimental and subject to change (see issue #38788)
+  --> $DIR/feature-gate-abi.rs:29:5
+   |
+LL |     extern "ptx-kernel" fn m6();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_ptx)] to the crate attributes to enable
+
+error[E0658]: x86-interrupt ABI is experimental and subject to change (see issue #40180)
+  --> $DIR/feature-gate-abi.rs:30:5
+   |
+LL |     extern "x86-interrupt" fn m7();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_x86_interrupt)] to the crate attributes to enable
+
+error[E0658]: thiscall is experimental and subject to change
+  --> $DIR/feature-gate-abi.rs:31:5
+   |
+LL |     extern "thiscall" fn m8();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_thiscall)] to the crate attributes to enable
+
+error[E0658]: amdgpu-kernel ABI is experimental and subject to change (see issue #51575)
+  --> $DIR/feature-gate-abi.rs:32:5
+   |
+LL |     extern "amdgpu-kernel" fn m9();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_amdgpu_kernel)] to the crate attributes to enable
+
+error[E0658]: intrinsics are subject to change
+  --> $DIR/feature-gate-abi.rs:34:5
+   |
+LL |     extern "rust-intrinsic" fn dm1() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(intrinsics)] to the crate attributes to enable
+
+error[E0658]: platform intrinsics are experimental and possibly buggy (see issue #27731)
+  --> $DIR/feature-gate-abi.rs:35:5
+   |
+LL |     extern "platform-intrinsic" fn dm2() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(platform_intrinsics)] to the crate attributes to enable
+
+error[E0658]: vectorcall is experimental and subject to change
+  --> $DIR/feature-gate-abi.rs:36:5
+   |
+LL |     extern "vectorcall" fn dm3() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_vectorcall)] to the crate attributes to enable
+
+error[E0658]: rust-call ABI is subject to change (see issue #29625)
+  --> $DIR/feature-gate-abi.rs:37:5
+   |
+LL |     extern "rust-call" fn dm4() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unboxed_closures)] to the crate attributes to enable
+
+error[E0658]: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
+  --> $DIR/feature-gate-abi.rs:38:5
+   |
+LL |     extern "msp430-interrupt" fn dm5() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_msp430_interrupt)] to the crate attributes to enable
+
+error[E0658]: PTX ABIs are experimental and subject to change (see issue #38788)
+  --> $DIR/feature-gate-abi.rs:39:5
+   |
+LL |     extern "ptx-kernel" fn dm6() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_ptx)] to the crate attributes to enable
+
+error[E0658]: x86-interrupt ABI is experimental and subject to change (see issue #40180)
+  --> $DIR/feature-gate-abi.rs:40:5
+   |
+LL |     extern "x86-interrupt" fn dm7() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_x86_interrupt)] to the crate attributes to enable
+
+error[E0658]: thiscall is experimental and subject to change
+  --> $DIR/feature-gate-abi.rs:41:5
+   |
+LL |     extern "thiscall" fn dm8() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_thiscall)] to the crate attributes to enable
+
+error[E0658]: amdgpu-kernel ABI is experimental and subject to change (see issue #51575)
+  --> $DIR/feature-gate-abi.rs:42:5
+   |
+LL |     extern "amdgpu-kernel" fn dm9() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_amdgpu_kernel)] to the crate attributes to enable
+
+error[E0658]: intrinsics are subject to change
+  --> $DIR/feature-gate-abi.rs:49:5
+   |
+LL |     extern "rust-intrinsic" fn m1() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(intrinsics)] to the crate attributes to enable
+
+error[E0658]: platform intrinsics are experimental and possibly buggy (see issue #27731)
+  --> $DIR/feature-gate-abi.rs:50:5
+   |
+LL |     extern "platform-intrinsic" fn m2() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(platform_intrinsics)] to the crate attributes to enable
+
+error[E0658]: vectorcall is experimental and subject to change
+  --> $DIR/feature-gate-abi.rs:51:5
+   |
+LL |     extern "vectorcall" fn m3() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_vectorcall)] to the crate attributes to enable
+
+error[E0658]: rust-call ABI is subject to change (see issue #29625)
+  --> $DIR/feature-gate-abi.rs:52:5
+   |
+LL |     extern "rust-call" fn m4() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unboxed_closures)] to the crate attributes to enable
+
+error[E0658]: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
+  --> $DIR/feature-gate-abi.rs:53:5
+   |
+LL |     extern "msp430-interrupt" fn m5() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_msp430_interrupt)] to the crate attributes to enable
+
+error[E0658]: PTX ABIs are experimental and subject to change (see issue #38788)
+  --> $DIR/feature-gate-abi.rs:54:5
+   |
+LL |     extern "ptx-kernel" fn m6() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_ptx)] to the crate attributes to enable
+
+error[E0658]: x86-interrupt ABI is experimental and subject to change (see issue #40180)
+  --> $DIR/feature-gate-abi.rs:55:5
+   |
+LL |     extern "x86-interrupt" fn m7() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_x86_interrupt)] to the crate attributes to enable
+
+error[E0658]: thiscall is experimental and subject to change
+  --> $DIR/feature-gate-abi.rs:56:5
+   |
+LL |     extern "thiscall" fn m8() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_thiscall)] to the crate attributes to enable
+
+error[E0658]: amdgpu-kernel ABI is experimental and subject to change (see issue #51575)
+  --> $DIR/feature-gate-abi.rs:57:5
+   |
+LL |     extern "amdgpu-kernel" fn m9() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_amdgpu_kernel)] to the crate attributes to enable
+
+error[E0658]: intrinsics are subject to change
+  --> $DIR/feature-gate-abi.rs:62:5
+   |
+LL |     extern "rust-intrinsic" fn im1() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(intrinsics)] to the crate attributes to enable
+
+error[E0658]: platform intrinsics are experimental and possibly buggy (see issue #27731)
+  --> $DIR/feature-gate-abi.rs:63:5
+   |
+LL |     extern "platform-intrinsic" fn im2() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(platform_intrinsics)] to the crate attributes to enable
+
+error[E0658]: vectorcall is experimental and subject to change
+  --> $DIR/feature-gate-abi.rs:64:5
+   |
+LL |     extern "vectorcall" fn im3() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_vectorcall)] to the crate attributes to enable
+
+error[E0658]: rust-call ABI is subject to change (see issue #29625)
+  --> $DIR/feature-gate-abi.rs:65:5
+   |
+LL |     extern "rust-call" fn im4() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unboxed_closures)] to the crate attributes to enable
+
+error[E0658]: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
+  --> $DIR/feature-gate-abi.rs:66:5
+   |
+LL |     extern "msp430-interrupt" fn im5() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_msp430_interrupt)] to the crate attributes to enable
+
+error[E0658]: PTX ABIs are experimental and subject to change (see issue #38788)
+  --> $DIR/feature-gate-abi.rs:67:5
+   |
+LL |     extern "ptx-kernel" fn im6() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_ptx)] to the crate attributes to enable
+
+error[E0658]: x86-interrupt ABI is experimental and subject to change (see issue #40180)
+  --> $DIR/feature-gate-abi.rs:68:5
+   |
+LL |     extern "x86-interrupt" fn im7() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_x86_interrupt)] to the crate attributes to enable
+
+error[E0658]: thiscall is experimental and subject to change
+  --> $DIR/feature-gate-abi.rs:69:5
+   |
+LL |     extern "thiscall" fn im8() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_thiscall)] to the crate attributes to enable
+
+error[E0658]: amdgpu-kernel ABI is experimental and subject to change (see issue #51575)
+  --> $DIR/feature-gate-abi.rs:70:5
+   |
+LL |     extern "amdgpu-kernel" fn im9() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_amdgpu_kernel)] to the crate attributes to enable
+
+error[E0658]: intrinsics are subject to change
+  --> $DIR/feature-gate-abi.rs:74:11
+   |
+LL | type A1 = extern "rust-intrinsic" fn();
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(intrinsics)] to the crate attributes to enable
+
+error[E0658]: platform intrinsics are experimental and possibly buggy (see issue #27731)
+  --> $DIR/feature-gate-abi.rs:75:11
+   |
+LL | type A2 = extern "platform-intrinsic" fn();
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(platform_intrinsics)] to the crate attributes to enable
+
+error[E0658]: vectorcall is experimental and subject to change
+  --> $DIR/feature-gate-abi.rs:76:11
+   |
+LL | type A3 = extern "vectorcall" fn();
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_vectorcall)] to the crate attributes to enable
+
+error[E0658]: rust-call ABI is subject to change (see issue #29625)
+  --> $DIR/feature-gate-abi.rs:77:11
+   |
+LL | type A4 = extern "rust-call" fn();
+   |           ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unboxed_closures)] to the crate attributes to enable
+
+error[E0658]: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
+  --> $DIR/feature-gate-abi.rs:78:11
+   |
+LL | type A5 = extern "msp430-interrupt" fn();
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_msp430_interrupt)] to the crate attributes to enable
+
+error[E0658]: PTX ABIs are experimental and subject to change (see issue #38788)
+  --> $DIR/feature-gate-abi.rs:79:11
+   |
+LL | type A6 = extern "ptx-kernel" fn ();
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_ptx)] to the crate attributes to enable
+
+error[E0658]: x86-interrupt ABI is experimental and subject to change (see issue #40180)
+  --> $DIR/feature-gate-abi.rs:80:11
+   |
+LL | type A7 = extern "x86-interrupt" fn();
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_x86_interrupt)] to the crate attributes to enable
+
+error[E0658]: thiscall is experimental and subject to change
+  --> $DIR/feature-gate-abi.rs:81:11
+   |
+LL | type A8 = extern "thiscall" fn();
+   |           ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_thiscall)] to the crate attributes to enable
+
+error[E0658]: amdgpu-kernel ABI is experimental and subject to change (see issue #51575)
+  --> $DIR/feature-gate-abi.rs:82:11
+   |
+LL | type A9 = extern "amdgpu-kernel" fn();
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_amdgpu_kernel)] to the crate attributes to enable
+
+error[E0658]: intrinsics are subject to change
+  --> $DIR/feature-gate-abi.rs:85:1
+   |
+LL | extern "rust-intrinsic" {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(intrinsics)] to the crate attributes to enable
+
+error[E0658]: platform intrinsics are experimental and possibly buggy (see issue #27731)
+  --> $DIR/feature-gate-abi.rs:86:1
+   |
+LL | extern "platform-intrinsic" {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(platform_intrinsics)] to the crate attributes to enable
+
+error[E0658]: vectorcall is experimental and subject to change
+  --> $DIR/feature-gate-abi.rs:87:1
+   |
+LL | extern "vectorcall" {}
+   | ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_vectorcall)] to the crate attributes to enable
+
+error[E0658]: rust-call ABI is subject to change (see issue #29625)
+  --> $DIR/feature-gate-abi.rs:88:1
+   |
+LL | extern "rust-call" {}
+   | ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unboxed_closures)] to the crate attributes to enable
+
+error[E0658]: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
+  --> $DIR/feature-gate-abi.rs:89:1
+   |
+LL | extern "msp430-interrupt" {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_msp430_interrupt)] to the crate attributes to enable
+
+error[E0658]: PTX ABIs are experimental and subject to change (see issue #38788)
+  --> $DIR/feature-gate-abi.rs:90:1
+   |
+LL | extern "ptx-kernel" {}
+   | ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_ptx)] to the crate attributes to enable
+
+error[E0658]: x86-interrupt ABI is experimental and subject to change (see issue #40180)
+  --> $DIR/feature-gate-abi.rs:91:1
+   |
+LL | extern "x86-interrupt" {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_x86_interrupt)] to the crate attributes to enable
+
+error[E0658]: thiscall is experimental and subject to change
+  --> $DIR/feature-gate-abi.rs:92:1
+   |
+LL | extern "thiscall" {}
+   | ^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_thiscall)] to the crate attributes to enable
+
+error[E0658]: amdgpu-kernel ABI is experimental and subject to change (see issue #51575)
+  --> $DIR/feature-gate-abi.rs:93:1
+   |
+LL | extern "amdgpu-kernel" {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_amdgpu_kernel)] to the crate attributes to enable
+
+error: aborting due to 63 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-abi_unadjusted.rs b/src/test/ui/feature-gates/feature-gate-abi_unadjusted.rs
new file mode 100644
index 0000000..35a7d73
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-abi_unadjusted.rs
@@ -0,0 +1,7 @@
+extern "unadjusted" fn foo() {
+//~^ ERROR: unadjusted ABI is an implementation detail and perma-unstable
+}
+
+fn main() {
+    foo();
+}
diff --git a/src/test/ui/feature-gates/feature-gate-abi_unadjusted.stderr b/src/test/ui/feature-gates/feature-gate-abi_unadjusted.stderr
new file mode 100644
index 0000000..fb32ebb
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-abi_unadjusted.stderr
@@ -0,0 +1,13 @@
+error[E0658]: unadjusted ABI is an implementation detail and perma-unstable
+  --> $DIR/feature-gate-abi_unadjusted.rs:1:1
+   |
+LL | / extern "unadjusted" fn foo() {
+LL | |
+LL | | }
+   | |_^
+   |
+   = help: add #![feature(abi_unadjusted)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-alloc-error-handler.rs b/src/test/ui/feature-gates/feature-gate-alloc-error-handler.rs
new file mode 100644
index 0000000..daa2bb5
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-alloc-error-handler.rs
@@ -0,0 +1,14 @@
+// compile-flags:-C panic=abort
+
+#![no_std]
+#![no_main]
+
+use core::alloc::Layout;
+
+#[alloc_error_handler] //~ ERROR #[alloc_error_handler] is an unstable feature (see issue #51540)
+fn oom(info: Layout) -> ! {
+    loop {}
+}
+
+#[panic_handler]
+fn panic(_: &core::panic::PanicInfo) -> ! { loop {} }
diff --git a/src/test/ui/feature-gates/feature-gate-alloc-error-handler.stderr b/src/test/ui/feature-gates/feature-gate-alloc-error-handler.stderr
new file mode 100644
index 0000000..5e64ac5
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-alloc-error-handler.stderr
@@ -0,0 +1,11 @@
+error[E0658]: #[alloc_error_handler] is an unstable feature (see issue #51540)
+  --> $DIR/feature-gate-alloc-error-handler.rs:8:1
+   |
+LL | #[alloc_error_handler]
+   | ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(alloc_error_handler)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-allocator_internals.rs b/src/test/ui/feature-gates/feature-gate-allocator_internals.rs
new file mode 100644
index 0000000..2045857
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-allocator_internals.rs
@@ -0,0 +1,4 @@
+#![default_lib_allocator] //~ ERROR: attribute is an experimental feature
+
+fn main() {}
+
diff --git a/src/test/ui/feature-gates/feature-gate-allocator_internals.stderr b/src/test/ui/feature-gates/feature-gate-allocator_internals.stderr
new file mode 100644
index 0000000..c41dca0
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-allocator_internals.stderr
@@ -0,0 +1,11 @@
+error[E0658]: the `#[default_lib_allocator]` attribute is an experimental feature
+  --> $DIR/feature-gate-allocator_internals.rs:1:1
+   |
+LL | #![default_lib_allocator]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(allocator_internals)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-allow-internal-unsafe-nested-macro.rs b/src/test/ui/feature-gates/feature-gate-allow-internal-unsafe-nested-macro.rs
new file mode 100644
index 0000000..9f604aa
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-allow-internal-unsafe-nested-macro.rs
@@ -0,0 +1,17 @@
+// gate-test-allow_internal_unsafe
+
+#![allow(unused_macros)]
+
+macro_rules! bar {
+    () => {
+        // more layers don't help:
+        #[allow_internal_unsafe] //~ ERROR allow_internal_unsafe side-steps
+        macro_rules! baz {
+            () => {}
+        }
+    }
+}
+
+bar!();
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-allow-internal-unsafe-nested-macro.stderr b/src/test/ui/feature-gates/feature-gate-allow-internal-unsafe-nested-macro.stderr
new file mode 100644
index 0000000..27324d7
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-allow-internal-unsafe-nested-macro.stderr
@@ -0,0 +1,14 @@
+error[E0658]: allow_internal_unsafe side-steps the unsafe_code lint
+  --> $DIR/feature-gate-allow-internal-unsafe-nested-macro.rs:8:9
+   |
+LL |         #[allow_internal_unsafe]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | bar!();
+   | ------- in this macro invocation
+   |
+   = help: add #![feature(allow_internal_unsafe)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-allow-internal-unstable-nested-macro.rs b/src/test/ui/feature-gates/feature-gate-allow-internal-unstable-nested-macro.rs
new file mode 100644
index 0000000..ee48f95
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-allow-internal-unstable-nested-macro.rs
@@ -0,0 +1,17 @@
+// gate-test-allow_internal_unstable
+
+#![allow(unused_macros)]
+
+macro_rules! bar {
+    () => {
+        // more layers don't help:
+        #[allow_internal_unstable()] //~ ERROR allow_internal_unstable side-steps
+        macro_rules! baz {
+            () => {}
+        }
+    }
+}
+
+bar!();
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-allow-internal-unstable-nested-macro.stderr b/src/test/ui/feature-gates/feature-gate-allow-internal-unstable-nested-macro.stderr
new file mode 100644
index 0000000..76afd21
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-allow-internal-unstable-nested-macro.stderr
@@ -0,0 +1,14 @@
+error[E0658]: allow_internal_unstable side-steps feature gating and stability checks
+  --> $DIR/feature-gate-allow-internal-unstable-nested-macro.rs:8:9
+   |
+LL |         #[allow_internal_unstable()]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | bar!();
+   | ------- in this macro invocation
+   |
+   = help: add #![feature(allow_internal_unstable)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-allow-internal-unstable-struct.rs b/src/test/ui/feature-gates/feature-gate-allow-internal-unstable-struct.rs
new file mode 100644
index 0000000..ede9690
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-allow-internal-unstable-struct.rs
@@ -0,0 +1,7 @@
+// checks that this attribute is caught on non-macro items.
+// this needs a different test since this is done after expansion
+
+#[allow_internal_unstable()] //~ ERROR allow_internal_unstable side-steps
+struct S;
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-allow-internal-unstable-struct.stderr b/src/test/ui/feature-gates/feature-gate-allow-internal-unstable-struct.stderr
new file mode 100644
index 0000000..d512e56
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-allow-internal-unstable-struct.stderr
@@ -0,0 +1,11 @@
+error[E0658]: allow_internal_unstable side-steps feature gating and stability checks
+  --> $DIR/feature-gate-allow-internal-unstable-struct.rs:4:1
+   |
+LL | #[allow_internal_unstable()]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(allow_internal_unstable)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-allow-internal-unstable.rs b/src/test/ui/feature-gates/feature-gate-allow-internal-unstable.rs
new file mode 100644
index 0000000..0a1b6ac
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-allow-internal-unstable.rs
@@ -0,0 +1,8 @@
+#![allow(unused_macros)]
+
+#[allow_internal_unstable()] //~ ERROR allow_internal_unstable side-steps
+macro_rules! foo {
+    () => {}
+}
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-allow-internal-unstable.stderr b/src/test/ui/feature-gates/feature-gate-allow-internal-unstable.stderr
new file mode 100644
index 0000000..baba7f4
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-allow-internal-unstable.stderr
@@ -0,0 +1,11 @@
+error[E0658]: allow_internal_unstable side-steps feature gating and stability checks
+  --> $DIR/feature-gate-allow-internal-unstable.rs:3:1
+   |
+LL | #[allow_internal_unstable()]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(allow_internal_unstable)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-allow_fail.rs b/src/test/ui/feature-gates/feature-gate-allow_fail.rs
new file mode 100644
index 0000000..f9ad485
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-allow_fail.rs
@@ -0,0 +1,8 @@
+// check that #[allow_fail] is feature-gated
+
+#[allow_fail] //~ ERROR allow_fail attribute is currently unstable
+fn ok_to_fail() {
+    assert!(false);
+}
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-allow_fail.stderr b/src/test/ui/feature-gates/feature-gate-allow_fail.stderr
new file mode 100644
index 0000000..5de1706
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-allow_fail.stderr
@@ -0,0 +1,11 @@
+error[E0658]: allow_fail attribute is currently unstable (see issue #46488)
+  --> $DIR/feature-gate-allow_fail.rs:3:1
+   |
+LL | #[allow_fail]
+   | ^^^^^^^^^^^^^
+   |
+   = help: add #![feature(allow_fail)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-arbitrary-self-types.rs b/src/test/ui/feature-gates/feature-gate-arbitrary-self-types.rs
new file mode 100644
index 0000000..6e0b71b
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-arbitrary-self-types.rs
@@ -0,0 +1,29 @@
+use std::{
+    ops::Deref,
+};
+
+struct Ptr<T: ?Sized>(Box<T>);
+
+impl<T: ?Sized> Deref for Ptr<T> {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        &*self.0
+    }
+}
+
+trait Foo {
+    fn foo(self: Ptr<Self>); //~ ERROR `Ptr<Self>` cannot be used as the type of `self` without
+}
+
+struct Bar;
+
+impl Foo for Bar {
+    fn foo(self: Ptr<Self>) {} //~ ERROR `Ptr<Bar>` cannot be used as the type of `self` without
+}
+
+impl Bar {
+    fn bar(self: Box<Ptr<Self>>) {} //~ ERROR `std::boxed::Box<Ptr<Bar>>` cannot be used as the
+}
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-arbitrary-self-types.stderr b/src/test/ui/feature-gates/feature-gate-arbitrary-self-types.stderr
new file mode 100644
index 0000000..e1089bc
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-arbitrary-self-types.stderr
@@ -0,0 +1,30 @@
+error[E0658]: `Ptr<Self>` cannot be used as the type of `self` without the `arbitrary_self_types` feature (see issue #44874)
+  --> $DIR/feature-gate-arbitrary-self-types.rs:16:18
+   |
+LL |     fn foo(self: Ptr<Self>);
+   |                  ^^^^^^^^^
+   |
+   = help: add #![feature(arbitrary_self_types)] to the crate attributes to enable
+   = help: consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`
+
+error[E0658]: `Ptr<Bar>` cannot be used as the type of `self` without the `arbitrary_self_types` feature (see issue #44874)
+  --> $DIR/feature-gate-arbitrary-self-types.rs:22:18
+   |
+LL |     fn foo(self: Ptr<Self>) {}
+   |                  ^^^^^^^^^
+   |
+   = help: add #![feature(arbitrary_self_types)] to the crate attributes to enable
+   = help: consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`
+
+error[E0658]: `std::boxed::Box<Ptr<Bar>>` cannot be used as the type of `self` without the `arbitrary_self_types` feature (see issue #44874)
+  --> $DIR/feature-gate-arbitrary-self-types.rs:26:18
+   |
+LL |     fn bar(self: Box<Ptr<Self>>) {}
+   |                  ^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(arbitrary_self_types)] to the crate attributes to enable
+   = help: consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.rs b/src/test/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.rs
new file mode 100644
index 0000000..f7e9411
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.rs
@@ -0,0 +1,18 @@
+struct Foo;
+
+impl Foo {
+    fn foo(self: *const Self) {}
+    //~^ ERROR `*const Foo` cannot be used as the type of `self` without
+}
+
+trait Bar {
+    fn bar(self: *const Self);
+    //~^ ERROR `*const Self` cannot be used as the type of `self` without
+}
+
+impl Bar for () {
+    fn bar(self: *const Self) {}
+    //~^ ERROR `*const ()` cannot be used as the type of `self` without
+}
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr b/src/test/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr
new file mode 100644
index 0000000..f35438f
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr
@@ -0,0 +1,30 @@
+error[E0658]: `*const Self` cannot be used as the type of `self` without the `arbitrary_self_types` feature (see issue #44874)
+  --> $DIR/feature-gate-arbitrary_self_types-raw-pointer.rs:9:18
+   |
+LL |     fn bar(self: *const Self);
+   |                  ^^^^^^^^^^^
+   |
+   = help: add #![feature(arbitrary_self_types)] to the crate attributes to enable
+   = help: consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`
+
+error[E0658]: `*const Foo` cannot be used as the type of `self` without the `arbitrary_self_types` feature (see issue #44874)
+  --> $DIR/feature-gate-arbitrary_self_types-raw-pointer.rs:4:18
+   |
+LL |     fn foo(self: *const Self) {}
+   |                  ^^^^^^^^^^^
+   |
+   = help: add #![feature(arbitrary_self_types)] to the crate attributes to enable
+   = help: consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`
+
+error[E0658]: `*const ()` cannot be used as the type of `self` without the `arbitrary_self_types` feature (see issue #44874)
+  --> $DIR/feature-gate-arbitrary_self_types-raw-pointer.rs:14:18
+   |
+LL |     fn bar(self: *const Self) {}
+   |                  ^^^^^^^^^^^
+   |
+   = help: add #![feature(arbitrary_self_types)] to the crate attributes to enable
+   = help: consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-asm.rs b/src/test/ui/feature-gates/feature-gate-asm.rs
new file mode 100644
index 0000000..572d9f2
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-asm.rs
@@ -0,0 +1,5 @@
+fn main() {
+    unsafe {
+        asm!(""); //~ ERROR inline assembly is not stable enough
+    }
+}
diff --git a/src/test/ui/feature-gates/feature-gate-asm.stderr b/src/test/ui/feature-gates/feature-gate-asm.stderr
new file mode 100644
index 0000000..6ad0ea6
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-asm.stderr
@@ -0,0 +1,11 @@
+error[E0658]: inline assembly is not stable enough for use and is subject to change (see issue #29722)
+  --> $DIR/feature-gate-asm.rs:3:9
+   |
+LL |         asm!("");
+   |         ^^^^^^^^^
+   |
+   = help: add #![feature(asm)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-asm2.rs b/src/test/ui/feature-gates/feature-gate-asm2.rs
new file mode 100644
index 0000000..259b0a14
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-asm2.rs
@@ -0,0 +1,7 @@
+// gate-test-asm
+
+fn main() {
+    unsafe {
+        println!("{:?}", asm!("")); //~ ERROR inline assembly is not stable
+    }
+}
diff --git a/src/test/ui/feature-gates/feature-gate-asm2.stderr b/src/test/ui/feature-gates/feature-gate-asm2.stderr
new file mode 100644
index 0000000..466f202
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-asm2.stderr
@@ -0,0 +1,11 @@
+error[E0658]: inline assembly is not stable enough for use and is subject to change (see issue #29722)
+  --> $DIR/feature-gate-asm2.rs:5:26
+   |
+LL |         println!("{:?}", asm!(""));
+   |                          ^^^^^^^^
+   |
+   = help: add #![feature(asm)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-assoc-type-defaults.rs b/src/test/ui/feature-gates/feature-gate-assoc-type-defaults.rs
new file mode 100644
index 0000000..d7c6a9f
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-assoc-type-defaults.rs
@@ -0,0 +1,7 @@
+// gate-test-associated_type_defaults
+
+trait Foo {
+    type Bar = u8; //~ ERROR associated type defaults are unstable
+}
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-assoc-type-defaults.stderr b/src/test/ui/feature-gates/feature-gate-assoc-type-defaults.stderr
new file mode 100644
index 0000000..fe206d3
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-assoc-type-defaults.stderr
@@ -0,0 +1,11 @@
+error[E0658]: associated type defaults are unstable (see issue #29661)
+  --> $DIR/feature-gate-assoc-type-defaults.rs:4:5
+   |
+LL |     type Bar = u8;
+   |     ^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(associated_type_defaults)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-async-await-2015-edition.rs b/src/test/ui/feature-gates/feature-gate-async-await-2015-edition.rs
new file mode 100644
index 0000000..b6ab8ae
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-async-await-2015-edition.rs
@@ -0,0 +1,11 @@
+// edition:2015
+
+#![feature(futures_api)]
+
+async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition
+                  //~^ ERROR async fn is unstable
+
+fn main() {
+    let _ = async {}; //~ ERROR cannot find struct, variant or union type `async`
+    let _ = async || { true }; //~ ERROR cannot find value `async` in this scope
+}
diff --git a/src/test/ui/feature-gates/feature-gate-async-await-2015-edition.stderr b/src/test/ui/feature-gates/feature-gate-async-await-2015-edition.stderr
new file mode 100644
index 0000000..b67949b
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-async-await-2015-edition.stderr
@@ -0,0 +1,30 @@
+error[E0670]: `async fn` is not permitted in the 2015 edition
+  --> $DIR/feature-gate-async-await-2015-edition.rs:5:1
+   |
+LL | async fn foo() {}
+   | ^^^^^
+
+error[E0422]: cannot find struct, variant or union type `async` in this scope
+  --> $DIR/feature-gate-async-await-2015-edition.rs:9:13
+   |
+LL |     let _ = async {};
+   |             ^^^^^ not found in this scope
+
+error[E0425]: cannot find value `async` in this scope
+  --> $DIR/feature-gate-async-await-2015-edition.rs:10:13
+   |
+LL |     let _ = async || { true };
+   |             ^^^^^ not found in this scope
+
+error[E0658]: async fn is unstable (see issue #50547)
+  --> $DIR/feature-gate-async-await-2015-edition.rs:5:1
+   |
+LL | async fn foo() {}
+   | ^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(async_await)] to the crate attributes to enable
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0422, E0425, E0658, E0670.
+For more information about an error, try `rustc --explain E0422`.
diff --git a/src/test/ui/feature-gates/feature-gate-async-await.rs b/src/test/ui/feature-gates/feature-gate-async-await.rs
new file mode 100644
index 0000000..7ee0356
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-async-await.rs
@@ -0,0 +1,10 @@
+// edition:2018
+
+#![feature(futures_api)]
+
+async fn foo() {} //~ ERROR async fn is unstable
+
+fn main() {
+    let _ = async {}; //~ ERROR async blocks are unstable
+    let _ = async || {}; //~ ERROR async closures are unstable
+}
diff --git a/src/test/ui/feature-gates/feature-gate-async-await.stderr b/src/test/ui/feature-gates/feature-gate-async-await.stderr
new file mode 100644
index 0000000..beec287
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-async-await.stderr
@@ -0,0 +1,27 @@
+error[E0658]: async fn is unstable (see issue #50547)
+  --> $DIR/feature-gate-async-await.rs:5:1
+   |
+LL | async fn foo() {}
+   | ^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(async_await)] to the crate attributes to enable
+
+error[E0658]: async blocks are unstable (see issue #50547)
+  --> $DIR/feature-gate-async-await.rs:8:13
+   |
+LL |     let _ = async {};
+   |             ^^^^^^^^
+   |
+   = help: add #![feature(async_await)] to the crate attributes to enable
+
+error[E0658]: async closures are unstable (see issue #50547)
+  --> $DIR/feature-gate-async-await.rs:9:13
+   |
+LL |     let _ = async || {};
+   |             ^^^^^^^^^^^
+   |
+   = help: add #![feature(async_await)] to the crate attributes to enable
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-box-expr.rs b/src/test/ui/feature-gates/feature-gate-box-expr.rs
new file mode 100644
index 0000000..870253d
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-box-expr.rs
@@ -0,0 +1,14 @@
+// gate-test-box_syntax
+
+// Check that `box EXPR` is feature-gated.
+//
+// See also feature-gate-placement-expr.rs
+//
+// (Note that the two tests are separated since the checks appear to
+// be performed at distinct phases, with an abort_if_errors call
+// separating them.)
+
+fn main() {
+    let x = box 'c'; //~ ERROR box expression syntax is experimental
+    println!("x: {}", x);
+}
diff --git a/src/test/ui/feature-gates/feature-gate-box-expr.stderr b/src/test/ui/feature-gates/feature-gate-box-expr.stderr
new file mode 100644
index 0000000..7b20204
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-box-expr.stderr
@@ -0,0 +1,11 @@
+error[E0658]: box expression syntax is experimental; you can call `Box::new` instead. (see issue #49733)
+  --> $DIR/feature-gate-box-expr.rs:12:13
+   |
+LL |     let x = box 'c';
+   |             ^^^^^^^
+   |
+   = help: add #![feature(box_syntax)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-box_patterns.rs b/src/test/ui/feature-gates/feature-gate-box_patterns.rs
new file mode 100644
index 0000000..8bec16a
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-box_patterns.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let box x = Box::new('c'); //~ ERROR box pattern syntax is experimental
+    println!("x: {}", x);
+}
diff --git a/src/test/ui/feature-gates/feature-gate-box_patterns.stderr b/src/test/ui/feature-gates/feature-gate-box_patterns.stderr
new file mode 100644
index 0000000..39404aa
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-box_patterns.stderr
@@ -0,0 +1,11 @@
+error[E0658]: box pattern syntax is experimental (see issue #29641)
+  --> $DIR/feature-gate-box_patterns.rs:2:9
+   |
+LL |     let box x = Box::new('c');
+   |         ^^^^^
+   |
+   = help: add #![feature(box_patterns)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-box_syntax.rs b/src/test/ui/feature-gates/feature-gate-box_syntax.rs
new file mode 100644
index 0000000..df0c604
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-box_syntax.rs
@@ -0,0 +1,6 @@
+// Test that the use of the box syntax is gated by `box_syntax` feature gate.
+
+fn main() {
+    let x = box 3;
+    //~^ ERROR box expression syntax is experimental; you can call `Box::new` instead.
+}
diff --git a/src/test/ui/feature-gates/feature-gate-box_syntax.stderr b/src/test/ui/feature-gates/feature-gate-box_syntax.stderr
new file mode 100644
index 0000000..f144d11
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-box_syntax.stderr
@@ -0,0 +1,11 @@
+error[E0658]: box expression syntax is experimental; you can call `Box::new` instead. (see issue #49733)
+  --> $DIR/feature-gate-box_syntax.rs:4:13
+   |
+LL |     let x = box 3;
+   |             ^^^^^
+   |
+   = help: add #![feature(box_syntax)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.rs b/src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.rs
new file mode 100644
index 0000000..db1a7da
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.rs
@@ -0,0 +1,90 @@
+#![feature(intrinsics, lang_items, no_core)]
+
+#![crate_type="rlib"]
+#![no_core]
+
+extern "rust-intrinsic" {
+    fn atomic_xadd<T>(dst: *mut T, src: T) -> T;
+}
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+
+#[cfg(target_has_atomic = "8")]
+//~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+pub unsafe fn atomic_u8(x: *mut u8) {
+    atomic_xadd(x, 1);
+    atomic_xadd(x, 1);
+}
+#[cfg(target_has_atomic = "8")]
+//~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+pub unsafe fn atomic_i8(x: *mut i8) {
+    atomic_xadd(x, 1);
+}
+#[cfg(target_has_atomic = "16")]
+//~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+pub unsafe fn atomic_u16(x: *mut u16) {
+    atomic_xadd(x, 1);
+}
+#[cfg(target_has_atomic = "16")]
+//~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+pub unsafe fn atomic_i16(x: *mut i16) {
+    atomic_xadd(x, 1);
+}
+#[cfg(target_has_atomic = "32")]
+//~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+pub unsafe fn atomic_u32(x: *mut u32) {
+    atomic_xadd(x, 1);
+}
+#[cfg(target_has_atomic = "32")]
+//~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+pub unsafe fn atomic_i32(x: *mut i32) {
+    atomic_xadd(x, 1);
+}
+#[cfg(target_has_atomic = "64")]
+//~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+pub unsafe fn atomic_u64(x: *mut u64) {
+    atomic_xadd(x, 1);
+}
+#[cfg(target_has_atomic = "64")]
+//~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+pub unsafe fn atomic_i64(x: *mut i64) {
+    atomic_xadd(x, 1);
+}
+#[cfg(target_has_atomic = "128")]
+//~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+pub unsafe fn atomic_u128(x: *mut u128) {
+    atomic_xadd(x, 1);
+}
+#[cfg(target_has_atomic = "128")]
+//~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+pub unsafe fn atomic_i128(x: *mut i128) {
+    atomic_xadd(x, 1);
+}
+#[cfg(target_has_atomic = "ptr")]
+//~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+pub unsafe fn atomic_usize(x: *mut usize) {
+    atomic_xadd(x, 1);
+}
+#[cfg(target_has_atomic = "ptr")]
+//~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+pub unsafe fn atomic_isize(x: *mut isize) {
+    atomic_xadd(x, 1);
+}
+
+fn main() {
+    cfg!(target_has_atomic = "8");
+    //~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+    cfg!(target_has_atomic = "16");
+    //~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+    cfg!(target_has_atomic = "32");
+    //~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+    cfg!(target_has_atomic = "64");
+    //~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+    cfg!(target_has_atomic = "128");
+    //~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+    cfg!(target_has_atomic = "ptr");
+    //~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+}
diff --git a/src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.stderr b/src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.stderr
new file mode 100644
index 0000000..a2d5669
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.stderr
@@ -0,0 +1,147 @@
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+  --> $DIR/feature-gate-cfg-target-has-atomic.rs:15:7
+   |
+LL | #[cfg(target_has_atomic = "8")]
+   |       ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
+
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+  --> $DIR/feature-gate-cfg-target-has-atomic.rs:21:7
+   |
+LL | #[cfg(target_has_atomic = "8")]
+   |       ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
+
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+  --> $DIR/feature-gate-cfg-target-has-atomic.rs:26:7
+   |
+LL | #[cfg(target_has_atomic = "16")]
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
+
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+  --> $DIR/feature-gate-cfg-target-has-atomic.rs:31:7
+   |
+LL | #[cfg(target_has_atomic = "16")]
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
+
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+  --> $DIR/feature-gate-cfg-target-has-atomic.rs:36:7
+   |
+LL | #[cfg(target_has_atomic = "32")]
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
+
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+  --> $DIR/feature-gate-cfg-target-has-atomic.rs:41:7
+   |
+LL | #[cfg(target_has_atomic = "32")]
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
+
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+  --> $DIR/feature-gate-cfg-target-has-atomic.rs:46:7
+   |
+LL | #[cfg(target_has_atomic = "64")]
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
+
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+  --> $DIR/feature-gate-cfg-target-has-atomic.rs:51:7
+   |
+LL | #[cfg(target_has_atomic = "64")]
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
+
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+  --> $DIR/feature-gate-cfg-target-has-atomic.rs:56:7
+   |
+LL | #[cfg(target_has_atomic = "128")]
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
+
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+  --> $DIR/feature-gate-cfg-target-has-atomic.rs:61:7
+   |
+LL | #[cfg(target_has_atomic = "128")]
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
+
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+  --> $DIR/feature-gate-cfg-target-has-atomic.rs:66:7
+   |
+LL | #[cfg(target_has_atomic = "ptr")]
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
+
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+  --> $DIR/feature-gate-cfg-target-has-atomic.rs:71:7
+   |
+LL | #[cfg(target_has_atomic = "ptr")]
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
+
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+  --> $DIR/feature-gate-cfg-target-has-atomic.rs:78:10
+   |
+LL |     cfg!(target_has_atomic = "8");
+   |          ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
+
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+  --> $DIR/feature-gate-cfg-target-has-atomic.rs:80:10
+   |
+LL |     cfg!(target_has_atomic = "16");
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
+
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+  --> $DIR/feature-gate-cfg-target-has-atomic.rs:82:10
+   |
+LL |     cfg!(target_has_atomic = "32");
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
+
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+  --> $DIR/feature-gate-cfg-target-has-atomic.rs:84:10
+   |
+LL |     cfg!(target_has_atomic = "64");
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
+
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+  --> $DIR/feature-gate-cfg-target-has-atomic.rs:86:10
+   |
+LL |     cfg!(target_has_atomic = "128");
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
+
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+  --> $DIR/feature-gate-cfg-target-has-atomic.rs:88:10
+   |
+LL |     cfg!(target_has_atomic = "ptr");
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
+
+error: aborting due to 18 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-cfg-target-thread-local.rs b/src/test/ui/feature-gates/feature-gate-cfg-target-thread-local.rs
new file mode 100644
index 0000000..54db750
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-cfg-target-thread-local.rs
@@ -0,0 +1,17 @@
+// ignore-windows
+// aux-build:cfg-target-thread-local.rs
+
+#![feature(thread_local)]
+
+extern crate cfg_target_thread_local;
+
+extern {
+    #[cfg_attr(target_thread_local, thread_local)]
+    //~^ `cfg(target_thread_local)` is experimental and subject to change (see issue #29594)
+
+    static FOO: u32;
+}
+
+fn main() {
+    assert_eq!(FOO, 3);
+}
diff --git a/src/test/ui/feature-gates/feature-gate-cfg-target-thread-local.stderr b/src/test/ui/feature-gates/feature-gate-cfg-target-thread-local.stderr
new file mode 100644
index 0000000..672fb14
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-cfg-target-thread-local.stderr
@@ -0,0 +1,11 @@
+error[E0658]: `cfg(target_thread_local)` is experimental and subject to change (see issue #29594)
+  --> $DIR/feature-gate-cfg-target-thread-local.rs:9:16
+   |
+LL |     #[cfg_attr(target_thread_local, thread_local)]
+   |                ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(cfg_target_thread_local)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-compiler-builtins.rs b/src/test/ui/feature-gates/feature-gate-compiler-builtins.rs
new file mode 100644
index 0000000..10a9749
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-compiler-builtins.rs
@@ -0,0 +1,4 @@
+#![compiler_builtins] //~ ERROR the `#[compiler_builtins]` attribute is
+
+fn main() {}
+
diff --git a/src/test/ui/feature-gates/feature-gate-compiler-builtins.stderr b/src/test/ui/feature-gates/feature-gate-compiler-builtins.stderr
new file mode 100644
index 0000000..278a184
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-compiler-builtins.stderr
@@ -0,0 +1,11 @@
+error[E0658]: the `#[compiler_builtins]` attribute is used to identify the `compiler_builtins` crate which contains compiler-rt intrinsics and will never be stable
+  --> $DIR/feature-gate-compiler-builtins.rs:1:1
+   |
+LL | #![compiler_builtins]
+   | ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(compiler_builtins)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-concat_idents.rs b/src/test/ui/feature-gates/feature-gate-concat_idents.rs
new file mode 100644
index 0000000..68caf3d
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-concat_idents.rs
@@ -0,0 +1,9 @@
+const XY_1: i32 = 10;
+
+fn main() {
+    const XY_2: i32 = 20;
+    let a = concat_idents!(X, Y_1); //~ ERROR `concat_idents` is not stable
+    let b = concat_idents!(X, Y_2); //~ ERROR `concat_idents` is not stable
+    assert_eq!(a, 10);
+    assert_eq!(b, 20);
+}
diff --git a/src/test/ui/feature-gates/feature-gate-concat_idents.stderr b/src/test/ui/feature-gates/feature-gate-concat_idents.stderr
new file mode 100644
index 0000000..3f4ce6d
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-concat_idents.stderr
@@ -0,0 +1,19 @@
+error[E0658]: `concat_idents` is not stable enough for use and is subject to change (see issue #29599)
+  --> $DIR/feature-gate-concat_idents.rs:5:13
+   |
+LL |     let a = concat_idents!(X, Y_1);
+   |             ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(concat_idents)] to the crate attributes to enable
+
+error[E0658]: `concat_idents` is not stable enough for use and is subject to change (see issue #29599)
+  --> $DIR/feature-gate-concat_idents.rs:6:13
+   |
+LL |     let b = concat_idents!(X, Y_2);
+   |             ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(concat_idents)] to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-concat_idents2.rs b/src/test/ui/feature-gates/feature-gate-concat_idents2.rs
new file mode 100644
index 0000000..0cc6c57
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-concat_idents2.rs
@@ -0,0 +1,6 @@
+// gate-test-concat_idents
+
+fn main() {
+    concat_idents!(a, b); //~ ERROR `concat_idents` is not stable enough
+                          //~| ERROR cannot find value `ab` in this scope
+}
diff --git a/src/test/ui/feature-gates/feature-gate-concat_idents2.stderr b/src/test/ui/feature-gates/feature-gate-concat_idents2.stderr
new file mode 100644
index 0000000..105b3d5
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-concat_idents2.stderr
@@ -0,0 +1,18 @@
+error[E0658]: `concat_idents` is not stable enough for use and is subject to change (see issue #29599)
+  --> $DIR/feature-gate-concat_idents2.rs:4:5
+   |
+LL |     concat_idents!(a, b);
+   |     ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(concat_idents)] to the crate attributes to enable
+
+error[E0425]: cannot find value `ab` in this scope
+  --> $DIR/feature-gate-concat_idents2.rs:4:5
+   |
+LL |     concat_idents!(a, b);
+   |     ^^^^^^^^^^^^^^^^^^^^^ not found in this scope
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0425, E0658.
+For more information about an error, try `rustc --explain E0425`.
diff --git a/src/test/ui/feature-gates/feature-gate-concat_idents3.rs b/src/test/ui/feature-gates/feature-gate-concat_idents3.rs
new file mode 100644
index 0000000..2882e7a
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-concat_idents3.rs
@@ -0,0 +1,9 @@
+// gate-test-concat_idents
+
+const XY_1: i32 = 10;
+
+fn main() {
+    const XY_2: i32 = 20;
+    assert_eq!(10, concat_idents!(X, Y_1)); //~ ERROR `concat_idents` is not stable
+    assert_eq!(20, concat_idents!(X, Y_2)); //~ ERROR `concat_idents` is not stable
+}
diff --git a/src/test/ui/feature-gates/feature-gate-concat_idents3.stderr b/src/test/ui/feature-gates/feature-gate-concat_idents3.stderr
new file mode 100644
index 0000000..9568b1d
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-concat_idents3.stderr
@@ -0,0 +1,19 @@
+error[E0658]: `concat_idents` is not stable enough for use and is subject to change (see issue #29599)
+  --> $DIR/feature-gate-concat_idents3.rs:7:20
+   |
+LL |     assert_eq!(10, concat_idents!(X, Y_1));
+   |                    ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(concat_idents)] to the crate attributes to enable
+
+error[E0658]: `concat_idents` is not stable enough for use and is subject to change (see issue #29599)
+  --> $DIR/feature-gate-concat_idents3.rs:8:20
+   |
+LL |     assert_eq!(20, concat_idents!(X, Y_2));
+   |                    ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(concat_idents)] to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-const-indexing.rs b/src/test/ui/feature-gates/feature-gate-const-indexing.rs
new file mode 100644
index 0000000..4df1c7d
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-const-indexing.rs
@@ -0,0 +1,8 @@
+// compile-pass
+
+fn main() {
+    const ARR: [i32; 6] = [42, 43, 44, 45, 46, 47];
+    const IDX: usize = 3;
+    const VAL: i32 = ARR[IDX];
+    const BLUB: [i32; (ARR[0] - 41) as usize] = [5];
+}
diff --git a/src/test/ui/feature-gates/feature-gate-const_fn.rs b/src/test/ui/feature-gates/feature-gate-const_fn.rs
new file mode 100644
index 0000000..f46d1dc
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-const_fn.rs
@@ -0,0 +1,37 @@
+// Test use of advanced const fn without the `const_fn` feature gate.
+
+const fn foo() -> usize { 0 } // ok
+
+trait Foo {
+    const fn foo() -> u32; //~ ERROR const fn is unstable
+                           //~| ERROR trait fns cannot be declared const
+    const fn bar() -> u32 { 0 } //~ ERROR const fn is unstable
+                                //~| ERROR trait fns cannot be declared const
+}
+
+impl Foo for u32 {
+    const fn foo() -> u32 { 0 } //~ ERROR trait fns cannot be declared const
+}
+
+trait Bar {}
+
+impl dyn Bar {
+    const fn baz() -> u32 { 0 } // ok
+}
+
+static FOO: usize = foo();
+const BAR: usize = foo();
+
+macro_rules! constant {
+    ($n:ident: $t:ty = $v:expr) => {
+        const $n: $t = $v;
+    }
+}
+
+constant! {
+    BAZ: usize = foo()
+}
+
+fn main() {
+    let x: [usize; foo()] = [];
+}
diff --git a/src/test/ui/feature-gates/feature-gate-const_fn.stderr b/src/test/ui/feature-gates/feature-gate-const_fn.stderr
new file mode 100644
index 0000000..7f88d30
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-const_fn.stderr
@@ -0,0 +1,38 @@
+error[E0379]: trait fns cannot be declared const
+  --> $DIR/feature-gate-const_fn.rs:6:5
+   |
+LL |     const fn foo() -> u32;
+   |     ^^^^^ trait fns cannot be const
+
+error[E0379]: trait fns cannot be declared const
+  --> $DIR/feature-gate-const_fn.rs:8:5
+   |
+LL |     const fn bar() -> u32 { 0 }
+   |     ^^^^^ trait fns cannot be const
+
+error[E0379]: trait fns cannot be declared const
+  --> $DIR/feature-gate-const_fn.rs:13:5
+   |
+LL |     const fn foo() -> u32 { 0 }
+   |     ^^^^^ trait fns cannot be const
+
+error[E0658]: const fn is unstable (see issue #57563)
+  --> $DIR/feature-gate-const_fn.rs:6:5
+   |
+LL |     const fn foo() -> u32;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0658]: const fn is unstable (see issue #57563)
+  --> $DIR/feature-gate-const_fn.rs:8:5
+   |
+LL |     const fn bar() -> u32 { 0 }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error: aborting due to 5 previous errors
+
+Some errors occurred: E0379, E0658.
+For more information about an error, try `rustc --explain E0379`.
diff --git a/src/test/ui/feature-gates/feature-gate-const_generics.rs b/src/test/ui/feature-gates/feature-gate-const_generics.rs
new file mode 100644
index 0000000..fe1ded1
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-const_generics.rs
@@ -0,0 +1,5 @@
+fn foo<const X: ()>() {} //~ ERROR const generics are unstable
+
+struct Foo<const X: usize>([(); X]); //~ ERROR const generics are unstable
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-const_generics.stderr b/src/test/ui/feature-gates/feature-gate-const_generics.stderr
new file mode 100644
index 0000000..dce4000
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-const_generics.stderr
@@ -0,0 +1,19 @@
+error[E0658]: const generics are unstable (see issue #44580)
+  --> $DIR/feature-gate-const_generics.rs:1:14
+   |
+LL | fn foo<const X: ()>() {}
+   |              ^
+   |
+   = help: add #![feature(const_generics)] to the crate attributes to enable
+
+error[E0658]: const generics are unstable (see issue #44580)
+  --> $DIR/feature-gate-const_generics.rs:3:18
+   |
+LL | struct Foo<const X: usize>([(); X]);
+   |                  ^
+   |
+   = help: add #![feature(const_generics)] to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-const_transmute.rs b/src/test/ui/feature-gates/feature-gate-const_transmute.rs
new file mode 100644
index 0000000..3c4e6de
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-const_transmute.rs
@@ -0,0 +1,9 @@
+use std::mem;
+
+#[repr(transparent)]
+struct Foo(u32);
+
+const TRANSMUTED_U32: u32 = unsafe { mem::transmute(Foo(3)) };
+//~^ ERROR The use of std::mem::transmute() is gated in constants (see issue #53605)
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-const_transmute.stderr b/src/test/ui/feature-gates/feature-gate-const_transmute.stderr
new file mode 100644
index 0000000..2e07a9e
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-const_transmute.stderr
@@ -0,0 +1,11 @@
+error[E0658]: The use of std::mem::transmute() is gated in constants (see issue #53605)
+  --> $DIR/feature-gate-const_transmute.rs:6:38
+   |
+LL | const TRANSMUTED_U32: u32 = unsafe { mem::transmute(Foo(3)) };
+   |                                      ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_transmute)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-crate_visibility_modifier.rs b/src/test/ui/feature-gates/feature-gate-crate_visibility_modifier.rs
new file mode 100644
index 0000000..0e3f6b1
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-crate_visibility_modifier.rs
@@ -0,0 +1,8 @@
+crate struct Bender { //~ ERROR `crate` visibility modifier is experimental
+    earth: bool,
+    fire: bool,
+    air: bool,
+    water: bool,
+}
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-crate_visibility_modifier.stderr b/src/test/ui/feature-gates/feature-gate-crate_visibility_modifier.stderr
new file mode 100644
index 0000000..25b26de
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-crate_visibility_modifier.stderr
@@ -0,0 +1,11 @@
+error[E0658]: `crate` visibility modifier is experimental (see issue #53120)
+  --> $DIR/feature-gate-crate_visibility_modifier.rs:1:1
+   |
+LL | crate struct Bender {
+   | ^^^^^
+   |
+   = help: add #![feature(crate_visibility_modifier)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-custom_attribute.rs b/src/test/ui/feature-gates/feature-gate-custom_attribute.rs
new file mode 100644
index 0000000..f31c9d5
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-custom_attribute.rs
@@ -0,0 +1,23 @@
+// Check that literals in attributes parse just fine.
+
+
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+#[fake_attr] //~ ERROR attribute `fake_attr` is currently unknown
+#[fake_attr(100)] //~ ERROR attribute `fake_attr` is currently unknown
+#[fake_attr(1, 2, 3)] //~ ERROR attribute `fake_attr` is currently unknown
+#[fake_attr("hello")] //~ ERROR attribute `fake_attr` is currently unknown
+#[fake_attr(name = "hello")] //~ ERROR attribute `fake_attr` is currently unknown
+#[fake_attr(1, "hi", key = 12, true, false)] //~ ERROR attribute `fake_attr` is currently unknown
+#[fake_attr(key = "hello", val = 10)] //~ ERROR attribute `fake_attr` is currently unknown
+#[fake_attr(key("hello"), val(10))] //~ ERROR attribute `fake_attr` is currently unknown
+#[fake_attr(enabled = true, disabled = false)] //~ ERROR attribute `fake_attr` is currently unknown
+#[fake_attr(true)] //~ ERROR attribute `fake_attr` is currently unknown
+#[fake_attr(pi = 3.14159)] //~ ERROR attribute `fake_attr` is currently unknown
+#[fake_attr(b"hi")] //~ ERROR attribute `fake_attr` is currently unknown
+#[fake_doc(r"doc")] //~ ERROR attribute `fake_doc` is currently unknown
+struct Q {  }
+
+
+fn main() { }
diff --git a/src/test/ui/feature-gates/feature-gate-custom_attribute.stderr b/src/test/ui/feature-gates/feature-gate-custom_attribute.stderr
new file mode 100644
index 0000000..8b79c75
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-custom_attribute.stderr
@@ -0,0 +1,107 @@
+error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute.rs:7:3
+   |
+LL | #[fake_attr]
+   |   ^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute.rs:8:3
+   |
+LL | #[fake_attr(100)]
+   |   ^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute.rs:9:3
+   |
+LL | #[fake_attr(1, 2, 3)]
+   |   ^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute.rs:10:3
+   |
+LL | #[fake_attr("hello")]
+   |   ^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute.rs:11:3
+   |
+LL | #[fake_attr(name = "hello")]
+   |   ^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute.rs:12:3
+   |
+LL | #[fake_attr(1, "hi", key = 12, true, false)]
+   |   ^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute.rs:13:3
+   |
+LL | #[fake_attr(key = "hello", val = 10)]
+   |   ^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute.rs:14:3
+   |
+LL | #[fake_attr(key("hello"), val(10))]
+   |   ^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute.rs:15:3
+   |
+LL | #[fake_attr(enabled = true, disabled = false)]
+   |   ^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute.rs:16:3
+   |
+LL | #[fake_attr(true)]
+   |   ^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute.rs:17:3
+   |
+LL | #[fake_attr(pi = 3.14159)]
+   |   ^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute.rs:18:3
+   |
+LL | #[fake_attr(b"hi")]
+   |   ^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error[E0658]: The attribute `fake_doc` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute.rs:19:3
+   |
+LL | #[fake_doc(r"doc")]
+   |   ^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error: aborting due to 13 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-custom_attribute2.rs b/src/test/ui/feature-gates/feature-gate-custom_attribute2.rs
new file mode 100644
index 0000000..2137a2a
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-custom_attribute2.rs
@@ -0,0 +1,60 @@
+// This test ensures that attributes on formals in generic parameter
+// lists are included when we are checking for unstable attributes.
+
+// gate-test-custom_attribute
+
+struct StLt<#[lt_struct] 'a>(&'a u32);
+//~^ ERROR The attribute `lt_struct` is currently unknown to the compiler
+struct StTy<#[ty_struct] I>(I);
+//~^ ERROR The attribute `ty_struct` is currently unknown to the compiler
+
+enum EnLt<#[lt_enum] 'b> { A(&'b u32), B }
+//~^ ERROR The attribute `lt_enum` is currently unknown to the compiler
+enum EnTy<#[ty_enum] J> { A(J), B }
+//~^ ERROR The attribute `ty_enum` is currently unknown to the compiler
+
+trait TrLt<#[lt_trait] 'c> { fn foo(&self, _: &'c [u32]) -> &'c u32; }
+//~^ ERROR The attribute `lt_trait` is currently unknown to the compiler
+trait TrTy<#[ty_trait] K> { fn foo(&self, _: K); }
+//~^ ERROR The attribute `ty_trait` is currently unknown to the compiler
+
+type TyLt<#[lt_type] 'd> = &'d u32;
+//~^ ERROR The attribute `lt_type` is currently unknown to the compiler
+type TyTy<#[ty_type] L> = (L, );
+//~^ ERROR The attribute `ty_type` is currently unknown to the compiler
+
+impl<#[lt_inherent] 'e> StLt<'e> { }
+//~^ ERROR The attribute `lt_inherent` is currently unknown to the compiler
+impl<#[ty_inherent] M> StTy<M> { }
+//~^ ERROR The attribute `ty_inherent` is currently unknown to the compiler
+
+impl<#[lt_impl_for] 'f> TrLt<'f> for StLt<'f> {
+    //~^ ERROR The attribute `lt_impl_for` is currently unknown to the compiler
+    fn foo(&self, _: &'f [u32]) -> &'f u32 { loop { } }
+}
+impl<#[ty_impl_for] N> TrTy<N> for StTy<N> {
+    //~^ ERROR The attribute `ty_impl_for` is currently unknown to the compiler
+    fn foo(&self, _: N) { }
+}
+
+fn f_lt<#[lt_fn] 'g>(_: &'g [u32]) -> &'g u32 { loop { } }
+//~^ ERROR The attribute `lt_fn` is currently unknown to the compiler
+fn f_ty<#[ty_fn] O>(_: O) { }
+//~^ ERROR The attribute `ty_fn` is currently unknown to the compiler
+
+impl<I> StTy<I> {
+    fn m_lt<#[lt_meth] 'h>(_: &'h [u32]) -> &'h u32 { loop { } }
+    //~^ ERROR The attribute `lt_meth` is currently unknown to the compiler
+    fn m_ty<#[ty_meth] P>(_: P) { }
+    //~^ ERROR The attribute `ty_meth` is currently unknown to the compiler
+}
+
+fn hof_lt<Q>(_: Q)
+    where Q: for <#[lt_hof] 'i> Fn(&'i [u32]) -> &'i u32
+    //~^ ERROR The attribute `lt_hof` is currently unknown to the compiler
+{
+}
+
+fn main() {
+
+}
diff --git a/src/test/ui/feature-gates/feature-gate-custom_attribute2.stderr b/src/test/ui/feature-gates/feature-gate-custom_attribute2.stderr
new file mode 100644
index 0000000..560ceda
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-custom_attribute2.stderr
@@ -0,0 +1,139 @@
+error[E0658]: The attribute `lt_struct` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute2.rs:6:13
+   |
+LL | struct StLt<#[lt_struct] 'a>(&'a u32);
+   |             ^^^^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error[E0658]: The attribute `ty_struct` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute2.rs:8:13
+   |
+LL | struct StTy<#[ty_struct] I>(I);
+   |             ^^^^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error[E0658]: The attribute `lt_enum` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute2.rs:11:11
+   |
+LL | enum EnLt<#[lt_enum] 'b> { A(&'b u32), B }
+   |           ^^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error[E0658]: The attribute `ty_enum` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute2.rs:13:11
+   |
+LL | enum EnTy<#[ty_enum] J> { A(J), B }
+   |           ^^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error[E0658]: The attribute `lt_trait` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute2.rs:16:12
+   |
+LL | trait TrLt<#[lt_trait] 'c> { fn foo(&self, _: &'c [u32]) -> &'c u32; }
+   |            ^^^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error[E0658]: The attribute `ty_trait` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute2.rs:18:12
+   |
+LL | trait TrTy<#[ty_trait] K> { fn foo(&self, _: K); }
+   |            ^^^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error[E0658]: The attribute `lt_type` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute2.rs:21:11
+   |
+LL | type TyLt<#[lt_type] 'd> = &'d u32;
+   |           ^^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error[E0658]: The attribute `ty_type` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute2.rs:23:11
+   |
+LL | type TyTy<#[ty_type] L> = (L, );
+   |           ^^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error[E0658]: The attribute `lt_inherent` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute2.rs:26:6
+   |
+LL | impl<#[lt_inherent] 'e> StLt<'e> { }
+   |      ^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error[E0658]: The attribute `ty_inherent` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute2.rs:28:6
+   |
+LL | impl<#[ty_inherent] M> StTy<M> { }
+   |      ^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error[E0658]: The attribute `lt_impl_for` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute2.rs:31:6
+   |
+LL | impl<#[lt_impl_for] 'f> TrLt<'f> for StLt<'f> {
+   |      ^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error[E0658]: The attribute `ty_impl_for` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute2.rs:35:6
+   |
+LL | impl<#[ty_impl_for] N> TrTy<N> for StTy<N> {
+   |      ^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error[E0658]: The attribute `lt_fn` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute2.rs:40:9
+   |
+LL | fn f_lt<#[lt_fn] 'g>(_: &'g [u32]) -> &'g u32 { loop { } }
+   |         ^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error[E0658]: The attribute `ty_fn` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute2.rs:42:9
+   |
+LL | fn f_ty<#[ty_fn] O>(_: O) { }
+   |         ^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error[E0658]: The attribute `lt_meth` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute2.rs:46:13
+   |
+LL |     fn m_lt<#[lt_meth] 'h>(_: &'h [u32]) -> &'h u32 { loop { } }
+   |             ^^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error[E0658]: The attribute `ty_meth` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute2.rs:48:13
+   |
+LL |     fn m_ty<#[ty_meth] P>(_: P) { }
+   |             ^^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error[E0658]: The attribute `lt_hof` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute2.rs:53:19
+   |
+LL |     where Q: for <#[lt_hof] 'i> Fn(&'i [u32]) -> &'i u32
+   |                   ^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error: aborting due to 17 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-custom_test_frameworks.rs b/src/test/ui/feature-gates/feature-gate-custom_test_frameworks.rs
new file mode 100644
index 0000000..0a20049
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-custom_test_frameworks.rs
@@ -0,0 +1,3 @@
+#![test_runner(main)] //~ ERROR custom test frameworks are an unstable feature
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-custom_test_frameworks.stderr b/src/test/ui/feature-gates/feature-gate-custom_test_frameworks.stderr
new file mode 100644
index 0000000..bac23b3
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-custom_test_frameworks.stderr
@@ -0,0 +1,11 @@
+error[E0658]: custom test frameworks are an unstable feature (see issue #50297)
+  --> $DIR/feature-gate-custom_test_frameworks.rs:1:1
+   |
+LL | #![test_runner(main)]
+   | ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(custom_test_frameworks)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-decl_macro.rs b/src/test/ui/feature-gates/feature-gate-decl_macro.rs
new file mode 100644
index 0000000..ca0dafd
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-decl_macro.rs
@@ -0,0 +1,5 @@
+#![allow(unused_macros)]
+
+macro m() {} //~ ERROR `macro` is experimental (see issue #39412)
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-decl_macro.stderr b/src/test/ui/feature-gates/feature-gate-decl_macro.stderr
new file mode 100644
index 0000000..2d4b622
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-decl_macro.stderr
@@ -0,0 +1,11 @@
+error[E0658]: `macro` is experimental (see issue #39412)
+  --> $DIR/feature-gate-decl_macro.rs:3:1
+   |
+LL | macro m() {}
+   | ^^^^^^^^^^^^
+   |
+   = help: add #![feature(decl_macro)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-default_type_parameter_fallback.rs b/src/test/ui/feature-gates/feature-gate-default_type_parameter_fallback.rs
new file mode 100644
index 0000000..33038e2
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-default_type_parameter_fallback.rs
@@ -0,0 +1,12 @@
+#![allow(unused)]
+
+fn avg<T=i32>(_: T) {}
+//~^ ERROR defaults for type parameters are only allowed
+//~| WARN this was previously accepted
+
+struct S<T>(T);
+impl<T=i32> S<T> {}
+//~^ ERROR defaults for type parameters are only allowed
+//~| WARN this was previously accepted
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-default_type_parameter_fallback.stderr b/src/test/ui/feature-gates/feature-gate-default_type_parameter_fallback.stderr
new file mode 100644
index 0000000..ac8cd10
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-default_type_parameter_fallback.stderr
@@ -0,0 +1,21 @@
+error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions.
+  --> $DIR/feature-gate-default_type_parameter_fallback.rs:3:8
+   |
+LL | fn avg<T=i32>(_: T) {}
+   |        ^
+   |
+   = note: #[deny(invalid_type_param_default)] on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
+
+error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions.
+  --> $DIR/feature-gate-default_type_parameter_fallback.rs:8:6
+   |
+LL | impl<T=i32> S<T> {}
+   |      ^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/feature-gates/feature-gate-doc_alias.rs b/src/test/ui/feature-gates/feature-gate-doc_alias.rs
new file mode 100644
index 0000000..d7980f8
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-doc_alias.rs
@@ -0,0 +1,4 @@
+#[doc(alias = "foo")] //~ ERROR: #[doc(alias = "...")] is experimental
+pub struct Foo;
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-doc_alias.stderr b/src/test/ui/feature-gates/feature-gate-doc_alias.stderr
new file mode 100644
index 0000000..c585a96
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-doc_alias.stderr
@@ -0,0 +1,11 @@
+error[E0658]: #[doc(alias = "...")] is experimental (see issue #50146)
+  --> $DIR/feature-gate-doc_alias.rs:1:1
+   |
+LL | #[doc(alias = "foo")]
+   | ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(doc_alias)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-doc_cfg-cfg-rustdoc.rs b/src/test/ui/feature-gates/feature-gate-doc_cfg-cfg-rustdoc.rs
new file mode 100644
index 0000000..17ea582
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-doc_cfg-cfg-rustdoc.rs
@@ -0,0 +1,4 @@
+#[cfg(rustdoc)] //~ ERROR: `cfg(rustdoc)` is experimental and subject to change
+pub struct SomeStruct;
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-doc_cfg-cfg-rustdoc.stderr b/src/test/ui/feature-gates/feature-gate-doc_cfg-cfg-rustdoc.stderr
new file mode 100644
index 0000000..f018ff4
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-doc_cfg-cfg-rustdoc.stderr
@@ -0,0 +1,11 @@
+error[E0658]: `cfg(rustdoc)` is experimental and subject to change (see issue #43781)
+  --> $DIR/feature-gate-doc_cfg-cfg-rustdoc.rs:1:7
+   |
+LL | #[cfg(rustdoc)]
+   |       ^^^^^^^
+   |
+   = help: add #![feature(doc_cfg)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-doc_cfg.rs b/src/test/ui/feature-gates/feature-gate-doc_cfg.rs
new file mode 100644
index 0000000..f131298
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-doc_cfg.rs
@@ -0,0 +1,2 @@
+#[doc(cfg(unix))] //~ ERROR: #[doc(cfg(...))] is experimental
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-doc_cfg.stderr b/src/test/ui/feature-gates/feature-gate-doc_cfg.stderr
new file mode 100644
index 0000000..2a0aa4f
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-doc_cfg.stderr
@@ -0,0 +1,11 @@
+error[E0658]: #[doc(cfg(...))] is experimental (see issue #43781)
+  --> $DIR/feature-gate-doc_cfg.rs:1:1
+   |
+LL | #[doc(cfg(unix))]
+   | ^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(doc_cfg)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-doc_keyword.rs b/src/test/ui/feature-gates/feature-gate-doc_keyword.rs
new file mode 100644
index 0000000..b08940e
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-doc_keyword.rs
@@ -0,0 +1,5 @@
+#[doc(keyword = "match")] //~ ERROR: #[doc(keyword = "...")] is experimental
+/// wonderful
+mod foo{}
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-doc_keyword.stderr b/src/test/ui/feature-gates/feature-gate-doc_keyword.stderr
new file mode 100644
index 0000000..c2cc1dc
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-doc_keyword.stderr
@@ -0,0 +1,11 @@
+error[E0658]: #[doc(keyword = "...")] is experimental (see issue #51315)
+  --> $DIR/feature-gate-doc_keyword.rs:1:1
+   |
+LL | #[doc(keyword = "match")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(doc_keyword)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-doc_masked.rs b/src/test/ui/feature-gates/feature-gate-doc_masked.rs
new file mode 100644
index 0000000..034c5cf
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-doc_masked.rs
@@ -0,0 +1,4 @@
+#[doc(masked)] //~ ERROR: #[doc(masked)] is experimental
+extern crate std as realstd;
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-doc_masked.stderr b/src/test/ui/feature-gates/feature-gate-doc_masked.stderr
new file mode 100644
index 0000000..77d3a6f
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-doc_masked.stderr
@@ -0,0 +1,11 @@
+error[E0658]: #[doc(masked)] is experimental (see issue #44027)
+  --> $DIR/feature-gate-doc_masked.rs:1:1
+   |
+LL | #[doc(masked)]
+   | ^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(doc_masked)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-doc_spotlight.rs b/src/test/ui/feature-gates/feature-gate-doc_spotlight.rs
new file mode 100644
index 0000000..28b689b
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-doc_spotlight.rs
@@ -0,0 +1,4 @@
+#[doc(spotlight)] //~ ERROR: #[doc(spotlight)] is experimental
+trait SomeTrait {}
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-doc_spotlight.stderr b/src/test/ui/feature-gates/feature-gate-doc_spotlight.stderr
new file mode 100644
index 0000000..60f5c08
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-doc_spotlight.stderr
@@ -0,0 +1,11 @@
+error[E0658]: #[doc(spotlight)] is experimental (see issue #45040)
+  --> $DIR/feature-gate-doc_spotlight.rs:1:1
+   |
+LL | #[doc(spotlight)]
+   | ^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(doc_spotlight)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-dropck-ugeh-2.rs b/src/test/ui/feature-gates/feature-gate-dropck-ugeh-2.rs
new file mode 100644
index 0000000..3325201
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-dropck-ugeh-2.rs
@@ -0,0 +1,12 @@
+#![deny(deprecated)]
+#![feature(dropck_parametricity)]
+
+struct Foo;
+
+impl Drop for Foo {
+    #[unsafe_destructor_blind_to_params]
+    //~^ ERROR use of deprecated attribute `dropck_parametricity`
+    fn drop(&mut self) {}
+}
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-dropck-ugeh-2.stderr b/src/test/ui/feature-gates/feature-gate-dropck-ugeh-2.stderr
new file mode 100644
index 0000000..b6a4745
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-dropck-ugeh-2.stderr
@@ -0,0 +1,14 @@
+error: use of deprecated attribute `dropck_parametricity`: unsafe_destructor_blind_to_params has been replaced by may_dangle and will be removed in the future. See https://github.com/rust-lang/rust/issues/34761
+  --> $DIR/feature-gate-dropck-ugeh-2.rs:7:5
+   |
+LL |     #[unsafe_destructor_blind_to_params]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace this attribute with `#[may_dangle]`
+   |
+note: lint level defined here
+  --> $DIR/feature-gate-dropck-ugeh-2.rs:1:9
+   |
+LL | #![deny(deprecated)]
+   |         ^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/feature-gates/feature-gate-dropck-ugeh.rs b/src/test/ui/feature-gates/feature-gate-dropck-ugeh.rs
new file mode 100644
index 0000000..a2377cd
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-dropck-ugeh.rs
@@ -0,0 +1,29 @@
+// gate-test-dropck_parametricity
+
+// Ensure that attempts to use the unsafe attribute are feature-gated.
+// Example adapted from RFC 1238 text (just left out the feature gate).
+
+// https://github.com/rust-lang/rfcs/blob/master/text/1238-nonparametric-dropck.md
+//     #example-of-the-unguarded-escape-hatch
+
+use std::cell::Cell;
+
+struct Concrete<'a>(u32, Cell<Option<&'a Concrete<'a>>>);
+
+struct Foo<T> { data: Vec<T> }
+
+impl<T> Drop for Foo<T> {
+    #[unsafe_destructor_blind_to_params] // This is the UGEH attribute
+    //~^ ERROR unsafe_destructor_blind_to_params has been replaced
+    //~| WARN use of deprecated attribute `dropck_parametricity`
+    fn drop(&mut self) { }
+}
+
+fn main() {
+    let mut foo = Foo {  data: Vec::new() };
+    foo.data.push(Concrete(0, Cell::new(None)));
+    foo.data.push(Concrete(0, Cell::new(None)));
+
+    foo.data[0].1.set(Some(&foo.data[1]));
+    foo.data[1].1.set(Some(&foo.data[0]));
+}
diff --git a/src/test/ui/feature-gates/feature-gate-dropck-ugeh.stderr b/src/test/ui/feature-gates/feature-gate-dropck-ugeh.stderr
new file mode 100644
index 0000000..bc62fc0
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-dropck-ugeh.stderr
@@ -0,0 +1,19 @@
+error[E0658]: unsafe_destructor_blind_to_params has been replaced by may_dangle and will be removed in the future (see issue #28498)
+  --> $DIR/feature-gate-dropck-ugeh.rs:16:5
+   |
+LL |     #[unsafe_destructor_blind_to_params] // This is the UGEH attribute
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(dropck_parametricity)] to the crate attributes to enable
+
+warning: use of deprecated attribute `dropck_parametricity`: unsafe_destructor_blind_to_params has been replaced by may_dangle and will be removed in the future. See https://github.com/rust-lang/rust/issues/34761
+  --> $DIR/feature-gate-dropck-ugeh.rs:16:5
+   |
+LL |     #[unsafe_destructor_blind_to_params] // This is the UGEH attribute
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace this attribute with `#[may_dangle]`
+   |
+   = note: #[warn(deprecated)] on by default
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-exclusive-range-pattern.rs b/src/test/ui/feature-gates/feature-gate-exclusive-range-pattern.rs
new file mode 100644
index 0000000..ded08b9
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-exclusive-range-pattern.rs
@@ -0,0 +1,6 @@
+pub fn main() {
+    match 22 {
+        0 .. 3 => {} //~ ERROR exclusive range pattern syntax is experimental
+        _ => {}
+    }
+}
diff --git a/src/test/ui/feature-gates/feature-gate-exclusive-range-pattern.stderr b/src/test/ui/feature-gates/feature-gate-exclusive-range-pattern.stderr
new file mode 100644
index 0000000..afb4021
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-exclusive-range-pattern.stderr
@@ -0,0 +1,11 @@
+error[E0658]: exclusive range pattern syntax is experimental (see issue #37854)
+  --> $DIR/feature-gate-exclusive-range-pattern.rs:3:9
+   |
+LL |         0 .. 3 => {}
+   |         ^^^^^^
+   |
+   = help: add #![feature(exclusive_range_pattern)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.rs b/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.rs
new file mode 100644
index 0000000..dce8cf4
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.rs
@@ -0,0 +1,9 @@
+#![feature(never_type)]
+fn foo() -> Result<u32, !> {
+    Ok(123)
+}
+
+fn main() {
+    let Ok(_x) = foo(); //~ ERROR refutable pattern in local binding
+}
+
diff --git a/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr b/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr
new file mode 100644
index 0000000..dd4ca1f
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr
@@ -0,0 +1,9 @@
+error[E0005]: refutable pattern in local binding: `Err(_)` not covered
+  --> $DIR/feature-gate-exhaustive-patterns.rs:7:9
+   |
+LL |     let Ok(_x) = foo();
+   |         ^^^^^^ pattern `Err(_)` not covered
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0005`.
diff --git a/src/test/ui/feature-gates/feature-gate-existential-type.rs b/src/test/ui/feature-gates/feature-gate-existential-type.rs
new file mode 100644
index 0000000..6dfd2d1
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-existential-type.rs
@@ -0,0 +1,17 @@
+// Check that existential types must be ungated to use the `existential` keyword
+
+existential type Foo: std::fmt::Debug; //~ ERROR existential types are unstable
+
+trait Bar {
+    type Baa: std::fmt::Debug;
+    fn define() -> Self::Baa;
+}
+
+impl Bar for () {
+    existential type Baa: std::fmt::Debug; //~ ERROR existential types are unstable
+    fn define() -> Self::Baa { 0 }
+}
+
+fn define() -> Foo { 0 }
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-existential-type.stderr b/src/test/ui/feature-gates/feature-gate-existential-type.stderr
new file mode 100644
index 0000000..6b8b850
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-existential-type.stderr
@@ -0,0 +1,19 @@
+error[E0658]: existential types are unstable (see issue #34511)
+  --> $DIR/feature-gate-existential-type.rs:3:1
+   |
+LL | existential type Foo: std::fmt::Debug;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(existential_type)] to the crate attributes to enable
+
+error[E0658]: existential types are unstable (see issue #34511)
+  --> $DIR/feature-gate-existential-type.rs:11:5
+   |
+LL |     existential type Baa: std::fmt::Debug;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(existential_type)] to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-extern_absolute_paths.rs b/src/test/ui/feature-gates/feature-gate-extern_absolute_paths.rs
new file mode 100644
index 0000000..cff273c
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-extern_absolute_paths.rs
@@ -0,0 +1,5 @@
+use core::default; //~ ERROR unresolved import `core`
+
+fn main() {
+    let _: u8 = ::core::default::Default(); //~ ERROR failed to resolve
+}
diff --git a/src/test/ui/feature-gates/feature-gate-extern_absolute_paths.stderr b/src/test/ui/feature-gates/feature-gate-extern_absolute_paths.stderr
new file mode 100644
index 0000000..e31d888
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-extern_absolute_paths.stderr
@@ -0,0 +1,16 @@
+error[E0432]: unresolved import `core`
+  --> $DIR/feature-gate-extern_absolute_paths.rs:1:5
+   |
+LL | use core::default;
+   |     ^^^^ maybe a missing `extern crate core;`?
+
+error[E0433]: failed to resolve: maybe a missing `extern crate core;`?
+  --> $DIR/feature-gate-extern_absolute_paths.rs:4:19
+   |
+LL |     let _: u8 = ::core::default::Default();
+   |                   ^^^^ maybe a missing `extern crate core;`?
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0432, E0433.
+For more information about an error, try `rustc --explain E0432`.
diff --git a/src/test/ui/feature-gates/feature-gate-extern_prelude.rs b/src/test/ui/feature-gates/feature-gate-extern_prelude.rs
new file mode 100644
index 0000000..237099e
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-extern_prelude.rs
@@ -0,0 +1 @@
+can-only-test-this-in-run-make-fulldeps //~ ERROR expected one of `!` or `::`, found `-`
diff --git a/src/test/ui/feature-gates/feature-gate-extern_prelude.stderr b/src/test/ui/feature-gates/feature-gate-extern_prelude.stderr
new file mode 100644
index 0000000..c15a8b3
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-extern_prelude.stderr
@@ -0,0 +1,8 @@
+error: expected one of `!` or `::`, found `-`
+  --> $DIR/feature-gate-extern_prelude.rs:1:4
+   |
+LL | can-only-test-this-in-run-make-fulldeps
+   |    ^ expected one of `!` or `::` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/feature-gates/feature-gate-extern_types.rs b/src/test/ui/feature-gates/feature-gate-extern_types.rs
new file mode 100644
index 0000000..6bdc96f
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-extern_types.rs
@@ -0,0 +1,5 @@
+extern {
+    type T; //~ ERROR extern types are experimental
+}
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-extern_types.stderr b/src/test/ui/feature-gates/feature-gate-extern_types.stderr
new file mode 100644
index 0000000..7035d85
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-extern_types.stderr
@@ -0,0 +1,11 @@
+error[E0658]: extern types are experimental (see issue #43467)
+  --> $DIR/feature-gate-extern_types.rs:2:5
+   |
+LL |     type T;
+   |     ^^^^^^^
+   |
+   = help: add #![feature(extern_types)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-external_doc.rs b/src/test/ui/feature-gates/feature-gate-external_doc.rs
new file mode 100644
index 0000000..e3ffb88
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-external_doc.rs
@@ -0,0 +1,2 @@
+#[doc(include="asdf.md")] //~ ERROR: #[doc(include = "...")] is experimental
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-external_doc.stderr b/src/test/ui/feature-gates/feature-gate-external_doc.stderr
new file mode 100644
index 0000000..16507bf
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-external_doc.stderr
@@ -0,0 +1,11 @@
+error[E0658]: #[doc(include = "...")] is experimental (see issue #44732)
+  --> $DIR/feature-gate-external_doc.rs:1:1
+   |
+LL | #[doc(include="asdf.md")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(external_doc)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-feature-gate.rs b/src/test/ui/feature-gates/feature-gate-feature-gate.rs
new file mode 100644
index 0000000..3c98e16
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-feature-gate.rs
@@ -0,0 +1,4 @@
+#![forbid(unstable_features)]
+#![feature(intrinsics)] //~ ERROR unstable feature
+
+fn main() { }
diff --git a/src/test/ui/feature-gates/feature-gate-feature-gate.stderr b/src/test/ui/feature-gates/feature-gate-feature-gate.stderr
new file mode 100644
index 0000000..d794042
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-feature-gate.stderr
@@ -0,0 +1,14 @@
+error: unstable feature
+  --> $DIR/feature-gate-feature-gate.rs:2:12
+   |
+LL | #![feature(intrinsics)]
+   |            ^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/feature-gate-feature-gate.rs:1:11
+   |
+LL | #![forbid(unstable_features)]
+   |           ^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/feature-gates/feature-gate-ffi_returns_twice.rs b/src/test/ui/feature-gates/feature-gate-ffi_returns_twice.rs
new file mode 100644
index 0000000..d3df6e5
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-ffi_returns_twice.rs
@@ -0,0 +1,7 @@
+// ignore-tidy-linelength
+#![crate_type = "lib"]
+
+extern {
+    #[ffi_returns_twice] //~ ERROR the `#[ffi_returns_twice]` attribute is an experimental feature (see issue #58314)
+    pub fn foo();
+}
diff --git a/src/test/ui/feature-gates/feature-gate-ffi_returns_twice.stderr b/src/test/ui/feature-gates/feature-gate-ffi_returns_twice.stderr
new file mode 100644
index 0000000..f85ce8e
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-ffi_returns_twice.stderr
@@ -0,0 +1,11 @@
+error[E0658]: the `#[ffi_returns_twice]` attribute is an experimental feature (see issue #58314)
+  --> $DIR/feature-gate-ffi_returns_twice.rs:5:5
+   |
+LL |     #[ffi_returns_twice]
+   |     ^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(ffi_returns_twice)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-format_args_nl.rs b/src/test/ui/feature-gates/feature-gate-format_args_nl.rs
new file mode 100644
index 0000000..aeee2fb
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-format_args_nl.rs
@@ -0,0 +1,3 @@
+fn main() {
+    format_args_nl!(""); //~ ERROR `format_args_nl` is only for internal language use
+}
diff --git a/src/test/ui/feature-gates/feature-gate-format_args_nl.stderr b/src/test/ui/feature-gates/feature-gate-format_args_nl.stderr
new file mode 100644
index 0000000..58d2c790f
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-format_args_nl.stderr
@@ -0,0 +1,11 @@
+error[E0658]: `format_args_nl` is only for internal language use and is subject to change
+  --> $DIR/feature-gate-format_args_nl.rs:2:5
+   |
+LL |     format_args_nl!("");
+   |     ^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(format_args_nl)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-fundamental.rs b/src/test/ui/feature-gates/feature-gate-fundamental.rs
new file mode 100644
index 0000000..70e0133
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-fundamental.rs
@@ -0,0 +1,4 @@
+#[fundamental] //~ ERROR the `#[fundamental]` attribute is an experimental feature
+struct Fundamental;
+
+fn main() { }
diff --git a/src/test/ui/feature-gates/feature-gate-fundamental.stderr b/src/test/ui/feature-gates/feature-gate-fundamental.stderr
new file mode 100644
index 0000000..9faf2a8
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-fundamental.stderr
@@ -0,0 +1,11 @@
+error[E0658]: the `#[fundamental]` attribute is an experimental feature (see issue #29635)
+  --> $DIR/feature-gate-fundamental.rs:1:1
+   |
+LL | #[fundamental]
+   | ^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(fundamental)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-generators.rs b/src/test/ui/feature-gates/feature-gate-generators.rs
new file mode 100644
index 0000000..cee930f
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-generators.rs
@@ -0,0 +1,4 @@
+fn main() {
+    yield true; //~ ERROR yield syntax is experimental
+                //~^ ERROR yield statement outside of generator literal
+}
diff --git a/src/test/ui/feature-gates/feature-gate-generators.stderr b/src/test/ui/feature-gates/feature-gate-generators.stderr
new file mode 100644
index 0000000..554eeae
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-generators.stderr
@@ -0,0 +1,18 @@
+error[E0658]: yield syntax is experimental (see issue #43122)
+  --> $DIR/feature-gate-generators.rs:2:5
+   |
+LL |     yield true;
+   |     ^^^^^^^^^^
+   |
+   = help: add #![feature(generators)] to the crate attributes to enable
+
+error[E0627]: yield statement outside of generator literal
+  --> $DIR/feature-gate-generators.rs:2:5
+   |
+LL |     yield true;
+   |     ^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0627, E0658.
+For more information about an error, try `rustc --explain E0627`.
diff --git a/src/test/ui/feature-gates/feature-gate-generic_associated_types.rs b/src/test/ui/feature-gates/feature-gate-generic_associated_types.rs
new file mode 100644
index 0000000..17548d7
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-generic_associated_types.rs
@@ -0,0 +1,30 @@
+use std::ops::Deref;
+
+trait PointerFamily<U> {
+    type Pointer<T>: Deref<Target = T>;
+    //~^ ERROR generic associated types are unstable
+    type Pointer2<T>: Deref<Target = T> where T: Clone, U: Clone;
+    //~^ ERROR generic associated types are unstable
+    //~| ERROR where clauses on associated types are unstable
+}
+
+struct Foo;
+
+impl PointerFamily<u32> for Foo {
+    type Pointer<Usize> = Box<Usize>;
+    //~^ ERROR generic associated types are unstable
+    type Pointer2<U32> = Box<U32>;
+    //~^ ERROR generic associated types are unstable
+}
+
+trait Bar {
+    type Assoc where Self: Sized;
+    //~^ ERROR where clauses on associated types are unstable
+}
+
+impl Bar for Foo {
+    type Assoc where Self: Sized = Foo;
+    //~^ ERROR where clauses on associated types are unstable
+}
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-generic_associated_types.stderr b/src/test/ui/feature-gates/feature-gate-generic_associated_types.stderr
new file mode 100644
index 0000000..8a207c9
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-generic_associated_types.stderr
@@ -0,0 +1,59 @@
+error[E0658]: generic associated types are unstable (see issue #44265)
+  --> $DIR/feature-gate-generic_associated_types.rs:4:5
+   |
+LL |     type Pointer<T>: Deref<Target = T>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(generic_associated_types)] to the crate attributes to enable
+
+error[E0658]: generic associated types are unstable (see issue #44265)
+  --> $DIR/feature-gate-generic_associated_types.rs:6:5
+   |
+LL |     type Pointer2<T>: Deref<Target = T> where T: Clone, U: Clone;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(generic_associated_types)] to the crate attributes to enable
+
+error[E0658]: where clauses on associated types are unstable (see issue #44265)
+  --> $DIR/feature-gate-generic_associated_types.rs:6:5
+   |
+LL |     type Pointer2<T>: Deref<Target = T> where T: Clone, U: Clone;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(generic_associated_types)] to the crate attributes to enable
+
+error[E0658]: generic associated types are unstable (see issue #44265)
+  --> $DIR/feature-gate-generic_associated_types.rs:14:5
+   |
+LL |     type Pointer<Usize> = Box<Usize>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(generic_associated_types)] to the crate attributes to enable
+
+error[E0658]: generic associated types are unstable (see issue #44265)
+  --> $DIR/feature-gate-generic_associated_types.rs:16:5
+   |
+LL |     type Pointer2<U32> = Box<U32>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(generic_associated_types)] to the crate attributes to enable
+
+error[E0658]: where clauses on associated types are unstable (see issue #44265)
+  --> $DIR/feature-gate-generic_associated_types.rs:21:5
+   |
+LL |     type Assoc where Self: Sized;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(generic_associated_types)] to the crate attributes to enable
+
+error[E0658]: where clauses on associated types are unstable (see issue #44265)
+  --> $DIR/feature-gate-generic_associated_types.rs:26:5
+   |
+LL |     type Assoc where Self: Sized = Foo;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(generic_associated_types)] to the crate attributes to enable
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-global_asm.rs b/src/test/ui/feature-gates/feature-gate-global_asm.rs
new file mode 100644
index 0000000..8c9f22e
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-global_asm.rs
@@ -0,0 +1,3 @@
+global_asm!(""); //~ ERROR `global_asm!` is not stable
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-global_asm.stderr b/src/test/ui/feature-gates/feature-gate-global_asm.stderr
new file mode 100644
index 0000000..fb9b47b
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-global_asm.stderr
@@ -0,0 +1,11 @@
+error[E0658]: `global_asm!` is not stable enough for use and is subject to change (see issue #35119)
+  --> $DIR/feature-gate-global_asm.rs:1:1
+   |
+LL | global_asm!("");
+   | ^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(global_asm)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-impl_trait_in_bindings.rs b/src/test/ui/feature-gates/feature-gate-impl_trait_in_bindings.rs
new file mode 100644
index 0000000..39cc64f
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-impl_trait_in_bindings.rs
@@ -0,0 +1,11 @@
+const FOO: impl Copy = 42;
+//~^ ERROR `impl Trait` not allowed
+
+static BAR: impl Copy = 42;
+//~^ ERROR `impl Trait` not allowed
+
+fn main() {
+    let foo = impl Copy = 42;
+//~^ ERROR expected expression, found keyword `impl`
+    let foo: impl Copy = 42;
+}
diff --git a/src/test/ui/feature-gates/feature-gate-impl_trait_in_bindings.stderr b/src/test/ui/feature-gates/feature-gate-impl_trait_in_bindings.stderr
new file mode 100644
index 0000000..a54e7e1
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-impl_trait_in_bindings.stderr
@@ -0,0 +1,25 @@
+error: expected expression, found keyword `impl`
+  --> $DIR/feature-gate-impl_trait_in_bindings.rs:8:15
+   |
+LL |     let foo = impl Copy = 42;
+   |               ^^^^ expected expression
+
+error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+  --> $DIR/feature-gate-impl_trait_in_bindings.rs:1:12
+   |
+LL | const FOO: impl Copy = 42;
+   |            ^^^^^^^^^
+   |
+   = help: add #![feature(impl_trait_in_bindings)] to the crate attributes to enable
+
+error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+  --> $DIR/feature-gate-impl_trait_in_bindings.rs:4:13
+   |
+LL | static BAR: impl Copy = 42;
+   |             ^^^^^^^^^
+   |
+   = help: add #![feature(impl_trait_in_bindings)] to the crate attributes to enable
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0562`.
diff --git a/src/test/ui/feature-gates/feature-gate-in_band_lifetimes.rs b/src/test/ui/feature-gates/feature-gate-in_band_lifetimes.rs
new file mode 100644
index 0000000..0e5f968
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-in_band_lifetimes.rs
@@ -0,0 +1,62 @@
+#![allow(warnings)]
+
+fn foo(x: &'x u8) -> &'x u8 { x }
+//~^ ERROR use of undeclared lifetime name
+//~^^ ERROR use of undeclared lifetime name
+
+struct X<'a>(&'a u8);
+
+impl<'a> X<'a> {
+    fn inner(&self) -> &'a u8 {
+        self.0
+    }
+}
+
+impl<'a> X<'b> {
+//~^ ERROR use of undeclared lifetime name
+    fn inner_2(&self) -> &'b u8 {
+    //~^ ERROR use of undeclared lifetime name
+        self.0
+    }
+}
+
+impl X<'b> {
+//~^ ERROR use of undeclared lifetime name
+    fn inner_3(&self) -> &'b u8 {
+    //~^ ERROR use of undeclared lifetime name
+        self.0
+    }
+}
+
+struct Y<T>(T);
+
+impl Y<&'a u8> {
+    //~^ ERROR use of undeclared lifetime name
+    fn inner(&self) -> &'a u8 {
+    //~^ ERROR use of undeclared lifetime name
+        self.0
+    }
+}
+
+trait MyTrait<'a> {
+    fn my_lifetime(&self) -> &'a u8;
+    fn any_lifetime() -> &'b u8;
+    //~^ ERROR use of undeclared lifetime name
+    fn borrowed_lifetime(&'b self) -> &'b u8;
+    //~^ ERROR use of undeclared lifetime name
+    //~^^ ERROR use of undeclared lifetime name
+}
+
+impl MyTrait<'a> for Y<&'a u8> {
+//~^ ERROR use of undeclared lifetime name
+//~^^ ERROR use of undeclared lifetime name
+    fn my_lifetime(&self) -> &'a u8 { self.0 }
+    //~^ ERROR use of undeclared lifetime name
+    fn any_lifetime() -> &'b u8 { &0 }
+    //~^ ERROR use of undeclared lifetime name
+    fn borrowed_lifetime(&'b self) -> &'b u8 { &*self.0 }
+    //~^ ERROR use of undeclared lifetime name
+    //~^^ ERROR use of undeclared lifetime name
+}
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-in_band_lifetimes.stderr b/src/test/ui/feature-gates/feature-gate-in_band_lifetimes.stderr
new file mode 100644
index 0000000..5c64bf6
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-in_band_lifetimes.stderr
@@ -0,0 +1,105 @@
+error[E0261]: use of undeclared lifetime name `'x`
+  --> $DIR/feature-gate-in_band_lifetimes.rs:3:12
+   |
+LL | fn foo(x: &'x u8) -> &'x u8 { x }
+   |            ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'x`
+  --> $DIR/feature-gate-in_band_lifetimes.rs:3:23
+   |
+LL | fn foo(x: &'x u8) -> &'x u8 { x }
+   |                       ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'b`
+  --> $DIR/feature-gate-in_band_lifetimes.rs:15:12
+   |
+LL | impl<'a> X<'b> {
+   |            ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'b`
+  --> $DIR/feature-gate-in_band_lifetimes.rs:17:27
+   |
+LL |     fn inner_2(&self) -> &'b u8 {
+   |                           ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'b`
+  --> $DIR/feature-gate-in_band_lifetimes.rs:23:8
+   |
+LL | impl X<'b> {
+   |        ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'b`
+  --> $DIR/feature-gate-in_band_lifetimes.rs:25:27
+   |
+LL |     fn inner_3(&self) -> &'b u8 {
+   |                           ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/feature-gate-in_band_lifetimes.rs:33:9
+   |
+LL | impl Y<&'a u8> {
+   |         ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/feature-gate-in_band_lifetimes.rs:35:25
+   |
+LL |     fn inner(&self) -> &'a u8 {
+   |                         ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'b`
+  --> $DIR/feature-gate-in_band_lifetimes.rs:43:27
+   |
+LL |     fn any_lifetime() -> &'b u8;
+   |                           ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'b`
+  --> $DIR/feature-gate-in_band_lifetimes.rs:45:27
+   |
+LL |     fn borrowed_lifetime(&'b self) -> &'b u8;
+   |                           ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'b`
+  --> $DIR/feature-gate-in_band_lifetimes.rs:45:40
+   |
+LL |     fn borrowed_lifetime(&'b self) -> &'b u8;
+   |                                        ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/feature-gate-in_band_lifetimes.rs:50:14
+   |
+LL | impl MyTrait<'a> for Y<&'a u8> {
+   |              ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/feature-gate-in_band_lifetimes.rs:50:25
+   |
+LL | impl MyTrait<'a> for Y<&'a u8> {
+   |                         ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/feature-gate-in_band_lifetimes.rs:53:31
+   |
+LL |     fn my_lifetime(&self) -> &'a u8 { self.0 }
+   |                               ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'b`
+  --> $DIR/feature-gate-in_band_lifetimes.rs:55:27
+   |
+LL |     fn any_lifetime() -> &'b u8 { &0 }
+   |                           ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'b`
+  --> $DIR/feature-gate-in_band_lifetimes.rs:57:27
+   |
+LL |     fn borrowed_lifetime(&'b self) -> &'b u8 { &*self.0 }
+   |                           ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'b`
+  --> $DIR/feature-gate-in_band_lifetimes.rs:57:40
+   |
+LL |     fn borrowed_lifetime(&'b self) -> &'b u8 { &*self.0 }
+   |                                        ^^ undeclared lifetime
+
+error: aborting due to 17 previous errors
+
+For more information about this error, try `rustc --explain E0261`.
diff --git a/src/test/ui/feature-gates/feature-gate-infer_static_outlives_requirements.rs b/src/test/ui/feature-gates/feature-gate-infer_static_outlives_requirements.rs
new file mode 100644
index 0000000..65792a7
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-infer_static_outlives_requirements.rs
@@ -0,0 +1,12 @@
+// Needs an explicit where clause stating outlives condition. (RFC 2093)
+
+// Type T needs to outlive lifetime 'static.
+struct Foo<U> {
+    bar: Bar<U> //~ ERROR the parameter type `U` may not live long enough [E0310]
+}
+struct Bar<T: 'static> {
+    x: T,
+}
+
+
+fn main() { }
diff --git a/src/test/ui/feature-gates/feature-gate-infer_static_outlives_requirements.stderr b/src/test/ui/feature-gates/feature-gate-infer_static_outlives_requirements.stderr
new file mode 100644
index 0000000..689a375
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-infer_static_outlives_requirements.stderr
@@ -0,0 +1,17 @@
+error[E0310]: the parameter type `U` may not live long enough
+  --> $DIR/feature-gate-infer_static_outlives_requirements.rs:5:5
+   |
+LL | struct Foo<U> {
+   |            - help: consider adding an explicit lifetime bound `U: 'static`...
+LL |     bar: Bar<U>
+   |     ^^^^^^^^^^^
+   |
+note: ...so that the type `U` will meet its required lifetime bounds
+  --> $DIR/feature-gate-infer_static_outlives_requirements.rs:5:5
+   |
+LL |     bar: Bar<U>
+   |     ^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0310`.
diff --git a/src/test/ui/feature-gates/feature-gate-intrinsics.rs b/src/test/ui/feature-gates/feature-gate-intrinsics.rs
new file mode 100644
index 0000000..d1da943
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-intrinsics.rs
@@ -0,0 +1,7 @@
+extern "rust-intrinsic" {   //~ ERROR intrinsics are subject to change
+    fn bar(); //~ ERROR unrecognized intrinsic function: `bar`
+}
+
+extern "rust-intrinsic" fn baz() {} //~ ERROR intrinsics are subject to change
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-intrinsics.stderr b/src/test/ui/feature-gates/feature-gate-intrinsics.stderr
new file mode 100644
index 0000000..5b032c6
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-intrinsics.stderr
@@ -0,0 +1,28 @@
+error[E0658]: intrinsics are subject to change
+  --> $DIR/feature-gate-intrinsics.rs:1:1
+   |
+LL | / extern "rust-intrinsic" {
+LL | |     fn bar();
+LL | | }
+   | |_^
+   |
+   = help: add #![feature(intrinsics)] to the crate attributes to enable
+
+error[E0658]: intrinsics are subject to change
+  --> $DIR/feature-gate-intrinsics.rs:5:1
+   |
+LL | extern "rust-intrinsic" fn baz() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(intrinsics)] to the crate attributes to enable
+
+error[E0093]: unrecognized intrinsic function: `bar`
+  --> $DIR/feature-gate-intrinsics.rs:2:5
+   |
+LL |     fn bar();
+   |     ^^^^^^^^^ unrecognized intrinsic
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0093, E0658.
+For more information about an error, try `rustc --explain E0093`.
diff --git a/src/test/ui/feature-gates/feature-gate-is_sorted.rs b/src/test/ui/feature-gates/feature-gate-is_sorted.rs
new file mode 100644
index 0000000..078ecc5
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-is_sorted.rs
@@ -0,0 +1,13 @@
+fn main() {
+    // Assert `Iterator` methods are feature gated
+    assert!([1, 2, 2, 9].iter().is_sorted());
+    //~^ ERROR: use of unstable library feature 'is_sorted': new API
+    assert!(![-2i32, -1, 0, 3].iter().is_sorted_by_key(|n| n.abs()));
+    //~^ ERROR: use of unstable library feature 'is_sorted': new API
+
+    // Assert `[T]` methods are feature gated
+    assert!([1, 2, 2, 9].is_sorted());
+    //~^ ERROR: use of unstable library feature 'is_sorted': new API
+    assert!(![-2i32, -1, 0, 3].is_sorted_by_key(|n| n.abs()));
+    //~^ ERROR: use of unstable library feature 'is_sorted': new API
+}
diff --git a/src/test/ui/feature-gates/feature-gate-is_sorted.stderr b/src/test/ui/feature-gates/feature-gate-is_sorted.stderr
new file mode 100644
index 0000000..8230c1e
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-is_sorted.stderr
@@ -0,0 +1,35 @@
+error[E0658]: use of unstable library feature 'is_sorted': new API (see issue #53485)
+  --> $DIR/feature-gate-is_sorted.rs:3:33
+   |
+LL |     assert!([1, 2, 2, 9].iter().is_sorted());
+   |                                 ^^^^^^^^^
+   |
+   = help: add #![feature(is_sorted)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'is_sorted': new API (see issue #53485)
+  --> $DIR/feature-gate-is_sorted.rs:5:39
+   |
+LL |     assert!(![-2i32, -1, 0, 3].iter().is_sorted_by_key(|n| n.abs()));
+   |                                       ^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(is_sorted)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'is_sorted': new API (see issue #53485)
+  --> $DIR/feature-gate-is_sorted.rs:9:26
+   |
+LL |     assert!([1, 2, 2, 9].is_sorted());
+   |                          ^^^^^^^^^
+   |
+   = help: add #![feature(is_sorted)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'is_sorted': new API (see issue #53485)
+  --> $DIR/feature-gate-is_sorted.rs:11:32
+   |
+LL |     assert!(![-2i32, -1, 0, 3].is_sorted_by_key(|n| n.abs()));
+   |                                ^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(is_sorted)] to the crate attributes to enable
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-label_break_value.rs b/src/test/ui/feature-gates/feature-gate-label_break_value.rs
new file mode 100644
index 0000000..6fc38f4
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-label_break_value.rs
@@ -0,0 +1,5 @@
+pub fn main() {
+    'a: { //~ ERROR labels on blocks are unstable
+        break 'a;
+    }
+}
diff --git a/src/test/ui/feature-gates/feature-gate-label_break_value.stderr b/src/test/ui/feature-gates/feature-gate-label_break_value.stderr
new file mode 100644
index 0000000..b23db3c
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-label_break_value.stderr
@@ -0,0 +1,11 @@
+error[E0658]: labels on blocks are unstable (see issue #48594)
+  --> $DIR/feature-gate-label_break_value.rs:2:5
+   |
+LL |     'a: {
+   |     ^^
+   |
+   = help: add #![feature(label_break_value)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-lang-items.rs b/src/test/ui/feature-gates/feature-gate-lang-items.rs
new file mode 100644
index 0000000..93262f2
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-lang-items.rs
@@ -0,0 +1,5 @@
+#[lang = "foo"] //~ ERROR language items are subject to change
+                //~^ ERROR definition of an unknown language item: `foo`
+trait Foo {}
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-lang-items.stderr b/src/test/ui/feature-gates/feature-gate-lang-items.stderr
new file mode 100644
index 0000000..f4c238d
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-lang-items.stderr
@@ -0,0 +1,18 @@
+error[E0658]: language items are subject to change
+  --> $DIR/feature-gate-lang-items.rs:1:1
+   |
+LL | #[lang = "foo"]
+   | ^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(lang_items)] to the crate attributes to enable
+
+error[E0522]: definition of an unknown language item: `foo`
+  --> $DIR/feature-gate-lang-items.rs:1:1
+   |
+LL | #[lang = "foo"]
+   | ^^^^^^^^^^^^^^^ definition of unknown language item `foo`
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0522, E0658.
+For more information about an error, try `rustc --explain E0522`.
diff --git a/src/test/ui/feature-gates/feature-gate-link_args.rs b/src/test/ui/feature-gates/feature-gate-link_args.rs
new file mode 100644
index 0000000..49948da
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-link_args.rs
@@ -0,0 +1,18 @@
+// Test that `#[link_args]` attribute is gated by `link_args`
+// feature gate, both when it occurs where expected (atop
+// `extern { }` blocks) and where unexpected.
+
+// sidestep warning (which is correct, but misleading for
+// purposes of this test)
+#![allow(unused_attributes)]
+
+#![link_args = "-l unexpected_use_as_inner_attr_on_mod"]
+//~^ ERROR the `link_args` attribute is experimental
+
+#[link_args = "-l expected_use_case"]
+//~^ ERROR the `link_args` attribute is experimental
+extern {}
+
+#[link_args = "-l unexected_use_on_non_extern_item"]
+//~^ ERROR: the `link_args` attribute is experimental
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-link_args.stderr b/src/test/ui/feature-gates/feature-gate-link_args.stderr
new file mode 100644
index 0000000..c43377f
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-link_args.stderr
@@ -0,0 +1,27 @@
+error[E0658]: the `link_args` attribute is experimental and not portable across platforms, it is recommended to use `#[link(name = "foo")] instead (see issue #29596)
+  --> $DIR/feature-gate-link_args.rs:12:1
+   |
+LL | #[link_args = "-l expected_use_case"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(link_args)] to the crate attributes to enable
+
+error[E0658]: the `link_args` attribute is experimental and not portable across platforms, it is recommended to use `#[link(name = "foo")] instead (see issue #29596)
+  --> $DIR/feature-gate-link_args.rs:16:1
+   |
+LL | #[link_args = "-l unexected_use_on_non_extern_item"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(link_args)] to the crate attributes to enable
+
+error[E0658]: the `link_args` attribute is experimental and not portable across platforms, it is recommended to use `#[link(name = "foo")] instead (see issue #29596)
+  --> $DIR/feature-gate-link_args.rs:9:1
+   |
+LL | #![link_args = "-l unexpected_use_as_inner_attr_on_mod"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(link_args)] to the crate attributes to enable
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-link_cfg.rs b/src/test/ui/feature-gates/feature-gate-link_cfg.rs
new file mode 100644
index 0000000..1905346
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-link_cfg.rs
@@ -0,0 +1,5 @@
+#[link(name = "foo", cfg(foo))]
+//~^ ERROR: is feature gated
+extern {}
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-link_cfg.stderr b/src/test/ui/feature-gates/feature-gate-link_cfg.stderr
new file mode 100644
index 0000000..b5ac5fd
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-link_cfg.stderr
@@ -0,0 +1,11 @@
+error[E0658]: is feature gated (see issue #37406)
+  --> $DIR/feature-gate-link_cfg.rs:1:1
+   |
+LL | #[link(name = "foo", cfg(foo))]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(link_cfg)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-link_llvm_intrinsics.rs b/src/test/ui/feature-gates/feature-gate-link_llvm_intrinsics.rs
new file mode 100644
index 0000000..1c7f331
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-link_llvm_intrinsics.rs
@@ -0,0 +1,8 @@
+extern {
+    #[link_name = "llvm.sqrt.f32"]
+    fn sqrt(x: f32) -> f32;
+    //~^ ERROR linking to LLVM intrinsics is experimental
+}
+
+fn main(){
+}
diff --git a/src/test/ui/feature-gates/feature-gate-link_llvm_intrinsics.stderr b/src/test/ui/feature-gates/feature-gate-link_llvm_intrinsics.stderr
new file mode 100644
index 0000000..a6cfc99
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-link_llvm_intrinsics.stderr
@@ -0,0 +1,11 @@
+error[E0658]: linking to LLVM intrinsics is experimental (see issue #29602)
+  --> $DIR/feature-gate-link_llvm_intrinsics.rs:3:5
+   |
+LL |     fn sqrt(x: f32) -> f32;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(link_llvm_intrinsics)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-linkage.rs b/src/test/ui/feature-gates/feature-gate-linkage.rs
new file mode 100644
index 0000000..70f33cc
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-linkage.rs
@@ -0,0 +1,6 @@
+extern {
+    #[linkage = "extern_weak"] static foo: isize;
+    //~^ ERROR: the `linkage` attribute is experimental and not portable
+}
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-linkage.stderr b/src/test/ui/feature-gates/feature-gate-linkage.stderr
new file mode 100644
index 0000000..1399a84
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-linkage.stderr
@@ -0,0 +1,11 @@
+error[E0658]: the `linkage` attribute is experimental and not portable across platforms (see issue #29603)
+  --> $DIR/feature-gate-linkage.rs:2:5
+   |
+LL |     #[linkage = "extern_weak"] static foo: isize;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(linkage)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-lint-reasons.rs b/src/test/ui/feature-gates/feature-gate-lint-reasons.rs
new file mode 100644
index 0000000..1a7b9c9
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-lint-reasons.rs
@@ -0,0 +1,4 @@
+#![warn(nonstandard_style, reason = "the standard should be respected")]
+//~^ ERROR lint reasons are experimental
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-lint-reasons.stderr b/src/test/ui/feature-gates/feature-gate-lint-reasons.stderr
new file mode 100644
index 0000000..6a36d9f
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-lint-reasons.stderr
@@ -0,0 +1,11 @@
+error[E0658]: lint reasons are experimental (see issue #54503)
+  --> $DIR/feature-gate-lint-reasons.rs:1:28
+   |
+LL | #![warn(nonstandard_style, reason = "the standard should be respected")]
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(lint_reasons)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-log_syntax.rs b/src/test/ui/feature-gates/feature-gate-log_syntax.rs
new file mode 100644
index 0000000..181f66c
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-log_syntax.rs
@@ -0,0 +1,3 @@
+fn main() {
+    log_syntax!() //~ ERROR `log_syntax!` is not stable enough
+}
diff --git a/src/test/ui/feature-gates/feature-gate-log_syntax.stderr b/src/test/ui/feature-gates/feature-gate-log_syntax.stderr
new file mode 100644
index 0000000..f29ee0b
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-log_syntax.stderr
@@ -0,0 +1,11 @@
+error[E0658]: `log_syntax!` is not stable enough for use and is subject to change (see issue #29598)
+  --> $DIR/feature-gate-log_syntax.rs:2:5
+   |
+LL |     log_syntax!()
+   |     ^^^^^^^^^^^^^
+   |
+   = help: add #![feature(log_syntax)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-log_syntax.stdout b/src/test/ui/feature-gates/feature-gate-log_syntax.stdout
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-log_syntax.stdout
@@ -0,0 +1 @@
+
diff --git a/src/test/ui/feature-gates/feature-gate-log_syntax2.rs b/src/test/ui/feature-gates/feature-gate-log_syntax2.rs
new file mode 100644
index 0000000..a3906dc
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-log_syntax2.rs
@@ -0,0 +1,5 @@
+// gate-test-log_syntax
+
+fn main() {
+    println!("{:?}", log_syntax!()); //~ ERROR `log_syntax!` is not stable
+}
diff --git a/src/test/ui/feature-gates/feature-gate-log_syntax2.stderr b/src/test/ui/feature-gates/feature-gate-log_syntax2.stderr
new file mode 100644
index 0000000..c5a9b49
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-log_syntax2.stderr
@@ -0,0 +1,11 @@
+error[E0658]: `log_syntax!` is not stable enough for use and is subject to change (see issue #29598)
+  --> $DIR/feature-gate-log_syntax2.rs:4:22
+   |
+LL |     println!("{:?}", log_syntax!());
+   |                      ^^^^^^^^^^^^^
+   |
+   = help: add #![feature(log_syntax)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-log_syntax2.stdout b/src/test/ui/feature-gates/feature-gate-log_syntax2.stdout
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-log_syntax2.stdout
@@ -0,0 +1 @@
+
diff --git a/src/test/ui/feature-gates/feature-gate-macros_in_extern.rs b/src/test/ui/feature-gates/feature-gate-macros_in_extern.rs
new file mode 100644
index 0000000..125af64
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-macros_in_extern.rs
@@ -0,0 +1,27 @@
+#![feature(decl_macro)]
+
+macro_rules! returns_isize(
+    ($ident:ident) => (
+        fn $ident() -> isize;
+    )
+);
+
+macro takes_u32_returns_u32($ident:ident) {
+    fn $ident (arg: u32) -> u32;
+}
+
+macro_rules! emits_nothing(
+    () => ()
+);
+
+#[link(name = "rust_test_helpers", kind = "static")]
+extern {
+    returns_isize!(rust_get_test_int);
+    //~^ ERROR macro invocations in `extern {}` blocks are experimental
+    takes_u32_returns_u32!(rust_dbg_extern_identity_u32);
+    //~^ ERROR macro invocations in `extern {}` blocks are experimental
+    emits_nothing!();
+    //~^ ERROR macro invocations in `extern {}` blocks are experimental
+}
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-macros_in_extern.stderr b/src/test/ui/feature-gates/feature-gate-macros_in_extern.stderr
new file mode 100644
index 0000000..affef0f
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-macros_in_extern.stderr
@@ -0,0 +1,27 @@
+error[E0658]: macro invocations in `extern {}` blocks are experimental (see issue #49476)
+  --> $DIR/feature-gate-macros_in_extern.rs:19:5
+   |
+LL |     returns_isize!(rust_get_test_int);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(macros_in_extern)] to the crate attributes to enable
+
+error[E0658]: macro invocations in `extern {}` blocks are experimental (see issue #49476)
+  --> $DIR/feature-gate-macros_in_extern.rs:21:5
+   |
+LL |     takes_u32_returns_u32!(rust_dbg_extern_identity_u32);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(macros_in_extern)] to the crate attributes to enable
+
+error[E0658]: macro invocations in `extern {}` blocks are experimental (see issue #49476)
+  --> $DIR/feature-gate-macros_in_extern.rs:23:5
+   |
+LL |     emits_nothing!();
+   |     ^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(macros_in_extern)] to the crate attributes to enable
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-main.rs b/src/test/ui/feature-gates/feature-gate-main.rs
new file mode 100644
index 0000000..681bdca
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-main.rs
@@ -0,0 +1,2 @@
+#[main]
+fn foo() {} //~ ERROR: declaration of a nonstandard #[main] function may change over time
diff --git a/src/test/ui/feature-gates/feature-gate-main.stderr b/src/test/ui/feature-gates/feature-gate-main.stderr
new file mode 100644
index 0000000..870cf1a
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-main.stderr
@@ -0,0 +1,11 @@
+error[E0658]: declaration of a nonstandard #[main] function may change over time, for now a top-level `fn main()` is required (see issue #29634)
+  --> $DIR/feature-gate-main.rs:2:1
+   |
+LL | fn foo() {}
+   | ^^^^^^^^^^^
+   |
+   = help: add #![feature(main)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-marker_trait_attr.rs b/src/test/ui/feature-gates/feature-gate-marker_trait_attr.rs
new file mode 100644
index 0000000..2b1b5bb
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-marker_trait_attr.rs
@@ -0,0 +1,9 @@
+use std::fmt::{Debug, Display};
+
+#[marker] trait ExplicitMarker {}
+//~^ ERROR marker traits is an experimental feature (see issue #29864)
+
+impl<T: Display> ExplicitMarker for T {}
+impl<T: Debug> ExplicitMarker for T {}
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-marker_trait_attr.stderr b/src/test/ui/feature-gates/feature-gate-marker_trait_attr.stderr
new file mode 100644
index 0000000..e916df1
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-marker_trait_attr.stderr
@@ -0,0 +1,11 @@
+error[E0658]: marker traits is an experimental feature (see issue #29864)
+  --> $DIR/feature-gate-marker_trait_attr.rs:3:1
+   |
+LL | #[marker] trait ExplicitMarker {}
+   | ^^^^^^^^^
+   |
+   = help: add #![feature(marker_trait_attr)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-may-dangle.rs b/src/test/ui/feature-gates/feature-gate-may-dangle.rs
new file mode 100644
index 0000000..20896e4
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-may-dangle.rs
@@ -0,0 +1,11 @@
+// gate-test-dropck_eyepatch
+
+// Check that `may_dangle` is rejected if `dropck_eyepatch` feature gate is absent.
+
+struct Pt<A>(A);
+unsafe impl<#[may_dangle] A> Drop for Pt<A> {
+    //~^ ERROR may_dangle has unstable semantics and may be removed in the future
+    fn drop(&mut self) { }
+}
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-may-dangle.stderr b/src/test/ui/feature-gates/feature-gate-may-dangle.stderr
new file mode 100644
index 0000000..6d21147
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-may-dangle.stderr
@@ -0,0 +1,11 @@
+error[E0658]: may_dangle has unstable semantics and may be removed in the future (see issue #34761)
+  --> $DIR/feature-gate-may-dangle.rs:6:13
+   |
+LL | unsafe impl<#[may_dangle] A> Drop for Pt<A> {
+   |             ^^^^^^^^^^^^^
+   |
+   = help: add #![feature(dropck_eyepatch)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-min_const_fn.rs b/src/test/ui/feature-gates/feature-gate-min_const_fn.rs
new file mode 100644
index 0000000..669631d
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-min_const_fn.rs
@@ -0,0 +1,37 @@
+// Test use of min_const_fn without feature gate.
+
+const fn foo() -> usize { 0 } // stabilized
+
+trait Foo {
+    const fn foo() -> u32; //~ ERROR const fn is unstable
+                           //~| ERROR trait fns cannot be declared const
+    const fn bar() -> u32 { 0 } //~ ERROR const fn is unstable
+                                //~| ERROR trait fns cannot be declared const
+}
+
+impl Foo for u32 {
+    const fn foo() -> u32 { 0 } //~ ERROR trait fns cannot be declared const
+}
+
+trait Bar {}
+
+impl dyn Bar {
+    const fn baz() -> u32 { 0 } // stabilized
+}
+
+static FOO: usize = foo();
+const BAR: usize = foo();
+
+macro_rules! constant {
+    ($n:ident: $t:ty = $v:expr) => {
+        const $n: $t = $v;
+    }
+}
+
+constant! {
+    BAZ: usize = foo()
+}
+
+fn main() {
+    let x: [usize; foo()] = [];
+}
diff --git a/src/test/ui/feature-gates/feature-gate-min_const_fn.stderr b/src/test/ui/feature-gates/feature-gate-min_const_fn.stderr
new file mode 100644
index 0000000..f6666b4
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-min_const_fn.stderr
@@ -0,0 +1,38 @@
+error[E0379]: trait fns cannot be declared const
+  --> $DIR/feature-gate-min_const_fn.rs:6:5
+   |
+LL |     const fn foo() -> u32;
+   |     ^^^^^ trait fns cannot be const
+
+error[E0379]: trait fns cannot be declared const
+  --> $DIR/feature-gate-min_const_fn.rs:8:5
+   |
+LL |     const fn bar() -> u32 { 0 }
+   |     ^^^^^ trait fns cannot be const
+
+error[E0379]: trait fns cannot be declared const
+  --> $DIR/feature-gate-min_const_fn.rs:13:5
+   |
+LL |     const fn foo() -> u32 { 0 }
+   |     ^^^^^ trait fns cannot be const
+
+error[E0658]: const fn is unstable (see issue #57563)
+  --> $DIR/feature-gate-min_const_fn.rs:6:5
+   |
+LL |     const fn foo() -> u32;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0658]: const fn is unstable (see issue #57563)
+  --> $DIR/feature-gate-min_const_fn.rs:8:5
+   |
+LL |     const fn bar() -> u32 { 0 }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error: aborting due to 5 previous errors
+
+Some errors occurred: E0379, E0658.
+For more information about an error, try `rustc --explain E0379`.
diff --git a/src/test/ui/feature-gates/feature-gate-naked_functions.rs b/src/test/ui/feature-gates/feature-gate-naked_functions.rs
new file mode 100644
index 0000000..16a51a1
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-naked_functions.rs
@@ -0,0 +1,11 @@
+#[naked]
+//~^ the `#[naked]` attribute is an experimental feature
+fn naked() {}
+
+#[naked]
+//~^ the `#[naked]` attribute is an experimental feature
+fn naked_2() -> isize {
+    0
+}
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-naked_functions.stderr b/src/test/ui/feature-gates/feature-gate-naked_functions.stderr
new file mode 100644
index 0000000..2ff5ef1
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-naked_functions.stderr
@@ -0,0 +1,19 @@
+error[E0658]: the `#[naked]` attribute is an experimental feature (see issue #32408)
+  --> $DIR/feature-gate-naked_functions.rs:1:1
+   |
+LL | #[naked]
+   | ^^^^^^^^
+   |
+   = help: add #![feature(naked_functions)] to the crate attributes to enable
+
+error[E0658]: the `#[naked]` attribute is an experimental feature (see issue #32408)
+  --> $DIR/feature-gate-naked_functions.rs:5:1
+   |
+LL | #[naked]
+   | ^^^^^^^^
+   |
+   = help: add #![feature(naked_functions)] to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-needs-allocator.rs b/src/test/ui/feature-gates/feature-gate-needs-allocator.rs
new file mode 100644
index 0000000..a3f91d0
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-needs-allocator.rs
@@ -0,0 +1,4 @@
+#![needs_allocator] //~ ERROR the `#[needs_allocator]` attribute is
+
+fn main() {}
+
diff --git a/src/test/ui/feature-gates/feature-gate-needs-allocator.stderr b/src/test/ui/feature-gates/feature-gate-needs-allocator.stderr
new file mode 100644
index 0000000..012664e
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-needs-allocator.stderr
@@ -0,0 +1,11 @@
+error[E0658]: the `#[needs_allocator]` attribute is an experimental feature
+  --> $DIR/feature-gate-needs-allocator.rs:1:1
+   |
+LL | #![needs_allocator]
+   | ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(allocator_internals)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-negate-unsigned.rs b/src/test/ui/feature-gates/feature-gate-negate-unsigned.rs
new file mode 100644
index 0000000..05e04f3
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-negate-unsigned.rs
@@ -0,0 +1,18 @@
+// Test that negating unsigned integers doesn't compile
+
+struct S;
+impl std::ops::Neg for S {
+    type Output = u32;
+    fn neg(self) -> u32 { 0 }
+}
+
+fn main() {
+    let _max: usize = -1;
+    //~^ ERROR cannot apply unary operator `-` to type `usize`
+
+    let x = 5u8;
+    let _y = -x;
+    //~^ ERROR cannot apply unary operator `-` to type `u8`
+
+    -S; // should not trigger the gate; issue 26840
+}
diff --git a/src/test/ui/feature-gates/feature-gate-negate-unsigned.stderr b/src/test/ui/feature-gates/feature-gate-negate-unsigned.stderr
new file mode 100644
index 0000000..aa84c27
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-negate-unsigned.stderr
@@ -0,0 +1,19 @@
+error[E0600]: cannot apply unary operator `-` to type `usize`
+  --> $DIR/feature-gate-negate-unsigned.rs:10:23
+   |
+LL |     let _max: usize = -1;
+   |                       ^^ cannot apply unary operator `-`
+   |
+   = note: unsigned values cannot be negated
+
+error[E0600]: cannot apply unary operator `-` to type `u8`
+  --> $DIR/feature-gate-negate-unsigned.rs:14:14
+   |
+LL |     let _y = -x;
+   |              ^^ cannot apply unary operator `-`
+   |
+   = note: unsigned values cannot be negated
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0600`.
diff --git a/src/test/ui/feature-gates/feature-gate-never_type.rs b/src/test/ui/feature-gates/feature-gate-never_type.rs
new file mode 100644
index 0000000..be8c27d
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-never_type.rs
@@ -0,0 +1,17 @@
+// Test that ! errors when used in illegal positions with feature(never_type) disabled
+
+trait Foo {
+    type Wub;
+}
+
+type Ma = (u32, !, i32); //~ ERROR type is experimental
+type Meeshka = Vec<!>; //~ ERROR type is experimental
+type Mow = &'static fn(!) -> !; //~ ERROR type is experimental
+type Skwoz = &'static mut !; //~ ERROR type is experimental
+
+impl Foo for Meeshka {
+    type Wub = !; //~ ERROR type is experimental
+}
+
+fn main() {
+}
diff --git a/src/test/ui/feature-gates/feature-gate-never_type.stderr b/src/test/ui/feature-gates/feature-gate-never_type.stderr
new file mode 100644
index 0000000..13166db
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-never_type.stderr
@@ -0,0 +1,43 @@
+error[E0658]: The `!` type is experimental (see issue #35121)
+  --> $DIR/feature-gate-never_type.rs:7:17
+   |
+LL | type Ma = (u32, !, i32);
+   |                 ^
+   |
+   = help: add #![feature(never_type)] to the crate attributes to enable
+
+error[E0658]: The `!` type is experimental (see issue #35121)
+  --> $DIR/feature-gate-never_type.rs:8:20
+   |
+LL | type Meeshka = Vec<!>;
+   |                    ^
+   |
+   = help: add #![feature(never_type)] to the crate attributes to enable
+
+error[E0658]: The `!` type is experimental (see issue #35121)
+  --> $DIR/feature-gate-never_type.rs:9:24
+   |
+LL | type Mow = &'static fn(!) -> !;
+   |                        ^
+   |
+   = help: add #![feature(never_type)] to the crate attributes to enable
+
+error[E0658]: The `!` type is experimental (see issue #35121)
+  --> $DIR/feature-gate-never_type.rs:10:27
+   |
+LL | type Skwoz = &'static mut !;
+   |                           ^
+   |
+   = help: add #![feature(never_type)] to the crate attributes to enable
+
+error[E0658]: The `!` type is experimental (see issue #35121)
+  --> $DIR/feature-gate-never_type.rs:13:16
+   |
+LL |     type Wub = !;
+   |                ^
+   |
+   = help: add #![feature(never_type)] to the crate attributes to enable
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-nll.rs b/src/test/ui/feature-gates/feature-gate-nll.rs
new file mode 100644
index 0000000..14c48fb
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-nll.rs
@@ -0,0 +1,18 @@
+// This is a test checking that if you do not opt into NLL then you
+// should not get the effects of NLL applied to the test.
+
+// Don't use 2018 edition, since that turns on NLL (migration mode).
+// edition:2015
+
+// Don't use compare-mode=nll, since that turns on NLL.
+// ignore-compare-mode-nll
+
+
+#![allow(dead_code)]
+
+fn main() {
+    let mut x = 33;
+
+    let p = &x;
+    x = 22; //~ ERROR cannot assign to `x` because it is borrowed [E0506]
+}
diff --git a/src/test/ui/feature-gates/feature-gate-nll.stderr b/src/test/ui/feature-gates/feature-gate-nll.stderr
new file mode 100644
index 0000000..cc004e3
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-nll.stderr
@@ -0,0 +1,11 @@
+error[E0506]: cannot assign to `x` because it is borrowed
+  --> $DIR/feature-gate-nll.rs:17:5
+   |
+LL |     let p = &x;
+   |              - borrow of `x` occurs here
+LL |     x = 22;
+   |     ^^^^^^ assignment to borrowed `x` occurs here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/feature-gates/feature-gate-no-debug-2.rs b/src/test/ui/feature-gates/feature-gate-no-debug-2.rs
new file mode 100644
index 0000000..b399bd2
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-no-debug-2.rs
@@ -0,0 +1,5 @@
+#![deny(deprecated)]
+#![feature(no_debug)]
+
+#[no_debug] //~ ERROR use of deprecated attribute `no_debug`
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-no-debug-2.stderr b/src/test/ui/feature-gates/feature-gate-no-debug-2.stderr
new file mode 100644
index 0000000..1f8f114
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-no-debug-2.stderr
@@ -0,0 +1,14 @@
+error: use of deprecated attribute `no_debug`: the `#[no_debug]` attribute was an experimental feature that has been deprecated due to lack of demand. See https://github.com/rust-lang/rust/issues/29721
+  --> $DIR/feature-gate-no-debug-2.rs:4:1
+   |
+LL | #[no_debug]
+   | ^^^^^^^^^^^ help: remove this attribute
+   |
+note: lint level defined here
+  --> $DIR/feature-gate-no-debug-2.rs:1:9
+   |
+LL | #![deny(deprecated)]
+   |         ^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/feature-gates/feature-gate-no-debug.rs b/src/test/ui/feature-gates/feature-gate-no-debug.rs
new file mode 100644
index 0000000..a472c4c
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-no-debug.rs
@@ -0,0 +1,4 @@
+#![allow(deprecated)]
+
+#[no_debug] //~ ERROR the `#[no_debug]` attribute was
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-no-debug.stderr b/src/test/ui/feature-gates/feature-gate-no-debug.stderr
new file mode 100644
index 0000000..1ee2ec3
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-no-debug.stderr
@@ -0,0 +1,11 @@
+error[E0658]: the `#[no_debug]` attribute was an experimental feature that has been deprecated due to lack of demand (see issue #29721)
+  --> $DIR/feature-gate-no-debug.rs:3:1
+   |
+LL | #[no_debug]
+   | ^^^^^^^^^^^
+   |
+   = help: add #![feature(no_debug)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-no_core.rs b/src/test/ui/feature-gates/feature-gate-no_core.rs
new file mode 100644
index 0000000..40178ed
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-no_core.rs
@@ -0,0 +1,5 @@
+#![crate_type = "rlib"]
+
+#![no_core] //~ ERROR no_core is experimental
+
+pub struct S {}
diff --git a/src/test/ui/feature-gates/feature-gate-no_core.stderr b/src/test/ui/feature-gates/feature-gate-no_core.stderr
new file mode 100644
index 0000000..279f219
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-no_core.stderr
@@ -0,0 +1,11 @@
+error[E0658]: no_core is experimental (see issue #29639)
+  --> $DIR/feature-gate-no_core.rs:3:1
+   |
+LL | #![no_core]
+   | ^^^^^^^^^^^
+   |
+   = help: add #![feature(no_core)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-non_ascii_idents.rs b/src/test/ui/feature-gates/feature-gate-non_ascii_idents.rs
new file mode 100644
index 0000000..11ff540
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-non_ascii_idents.rs
@@ -0,0 +1,33 @@
+extern crate core as bäz; //~ ERROR non-ascii idents
+
+use föö::bar; //~ ERROR non-ascii idents
+
+mod föö { //~ ERROR non-ascii idents
+    pub fn bar() {}
+}
+
+fn bär( //~ ERROR non-ascii idents
+    bäz: isize //~ ERROR non-ascii idents
+    ) {
+    let _ö: isize; //~ ERROR non-ascii idents
+
+    match (1, 2) {
+        (_ä, _) => {} //~ ERROR non-ascii idents
+    }
+}
+
+struct Föö { //~ ERROR non-ascii idents
+    föö: isize //~ ERROR non-ascii idents
+}
+
+enum Bär { //~ ERROR non-ascii idents
+    Bäz { //~ ERROR non-ascii idents
+        qüx: isize //~ ERROR non-ascii idents
+    }
+}
+
+extern {
+    fn qüx();  //~ ERROR non-ascii idents
+}
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-non_ascii_idents.stderr b/src/test/ui/feature-gates/feature-gate-non_ascii_idents.stderr
new file mode 100644
index 0000000..5e4c464
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-non_ascii_idents.stderr
@@ -0,0 +1,107 @@
+error[E0658]: non-ascii idents are not fully supported. (see issue #55467)
+  --> $DIR/feature-gate-non_ascii_idents.rs:1:22
+   |
+LL | extern crate core as bäz;
+   |                      ^^^
+   |
+   = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
+
+error[E0658]: non-ascii idents are not fully supported. (see issue #55467)
+  --> $DIR/feature-gate-non_ascii_idents.rs:3:5
+   |
+LL | use föö::bar;
+   |     ^^^
+   |
+   = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
+
+error[E0658]: non-ascii idents are not fully supported. (see issue #55467)
+  --> $DIR/feature-gate-non_ascii_idents.rs:5:5
+   |
+LL | mod föö {
+   |     ^^^
+   |
+   = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
+
+error[E0658]: non-ascii idents are not fully supported. (see issue #55467)
+  --> $DIR/feature-gate-non_ascii_idents.rs:9:4
+   |
+LL | fn bär(
+   |    ^^^
+   |
+   = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
+
+error[E0658]: non-ascii idents are not fully supported. (see issue #55467)
+  --> $DIR/feature-gate-non_ascii_idents.rs:10:5
+   |
+LL |     bäz: isize
+   |     ^^^
+   |
+   = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
+
+error[E0658]: non-ascii idents are not fully supported. (see issue #55467)
+  --> $DIR/feature-gate-non_ascii_idents.rs:12:9
+   |
+LL |     let _ö: isize;
+   |         ^^
+   |
+   = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
+
+error[E0658]: non-ascii idents are not fully supported. (see issue #55467)
+  --> $DIR/feature-gate-non_ascii_idents.rs:15:10
+   |
+LL |         (_ä, _) => {}
+   |          ^^
+   |
+   = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
+
+error[E0658]: non-ascii idents are not fully supported. (see issue #55467)
+  --> $DIR/feature-gate-non_ascii_idents.rs:19:8
+   |
+LL | struct Föö {
+   |        ^^^
+   |
+   = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
+
+error[E0658]: non-ascii idents are not fully supported. (see issue #55467)
+  --> $DIR/feature-gate-non_ascii_idents.rs:20:5
+   |
+LL |     föö: isize
+   |     ^^^
+   |
+   = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
+
+error[E0658]: non-ascii idents are not fully supported. (see issue #55467)
+  --> $DIR/feature-gate-non_ascii_idents.rs:23:6
+   |
+LL | enum Bär {
+   |      ^^^
+   |
+   = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
+
+error[E0658]: non-ascii idents are not fully supported. (see issue #55467)
+  --> $DIR/feature-gate-non_ascii_idents.rs:24:5
+   |
+LL |     Bäz {
+   |     ^^^
+   |
+   = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
+
+error[E0658]: non-ascii idents are not fully supported. (see issue #55467)
+  --> $DIR/feature-gate-non_ascii_idents.rs:25:9
+   |
+LL |         qüx: isize
+   |         ^^^
+   |
+   = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
+
+error[E0658]: non-ascii idents are not fully supported. (see issue #55467)
+  --> $DIR/feature-gate-non_ascii_idents.rs:30:8
+   |
+LL |     fn qüx();
+   |        ^^^
+   |
+   = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
+
+error: aborting due to 13 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-non_exhaustive.rs b/src/test/ui/feature-gates/feature-gate-non_exhaustive.rs
new file mode 100644
index 0000000..b3e2e3d
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-non_exhaustive.rs
@@ -0,0 +1,10 @@
+//#![feature(non_exhaustive)]
+
+#[non_exhaustive] //~ERROR non exhaustive is an experimental feature (see issue #44109)
+pub enum NonExhaustiveEnum {
+    Unit,
+    Tuple(u32),
+    Struct { field: u32 }
+}
+
+fn main() { }
diff --git a/src/test/ui/feature-gates/feature-gate-non_exhaustive.stderr b/src/test/ui/feature-gates/feature-gate-non_exhaustive.stderr
new file mode 100644
index 0000000..524f779
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-non_exhaustive.stderr
@@ -0,0 +1,11 @@
+error[E0658]: non exhaustive is an experimental feature (see issue #44109)
+  --> $DIR/feature-gate-non_exhaustive.rs:3:1
+   |
+LL | #[non_exhaustive]
+   | ^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(non_exhaustive)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-omit-gdb-pretty-printer-section.rs b/src/test/ui/feature-gates/feature-gate-omit-gdb-pretty-printer-section.rs
new file mode 100644
index 0000000..66bf797
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-omit-gdb-pretty-printer-section.rs
@@ -0,0 +1,2 @@
+#[omit_gdb_pretty_printer_section] //~ ERROR the `#[omit_gdb_pretty_printer_section]` attribute is
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-omit-gdb-pretty-printer-section.stderr b/src/test/ui/feature-gates/feature-gate-omit-gdb-pretty-printer-section.stderr
new file mode 100644
index 0000000..6834248
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-omit-gdb-pretty-printer-section.stderr
@@ -0,0 +1,11 @@
+error[E0658]: the `#[omit_gdb_pretty_printer_section]` attribute is just used for the Rust test suite
+  --> $DIR/feature-gate-omit-gdb-pretty-printer-section.rs:1:1
+   |
+LL | #[omit_gdb_pretty_printer_section]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(omit_gdb_pretty_printer_section)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-on-unimplemented.rs b/src/test/ui/feature-gates/feature-gate-on-unimplemented.rs
new file mode 100644
index 0000000..bec1531
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-on-unimplemented.rs
@@ -0,0 +1,9 @@
+// Test that `#[rustc_on_unimplemented]` is gated by `on_unimplemented` feature
+// gate.
+
+#[rustc_on_unimplemented = "test error `{Self}` with `{Bar}`"]
+//~^ ERROR the `#[rustc_on_unimplemented]` attribute is an experimental feature
+trait Foo<Bar>
+{}
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-on-unimplemented.stderr b/src/test/ui/feature-gates/feature-gate-on-unimplemented.stderr
new file mode 100644
index 0000000..32bfb20
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-on-unimplemented.stderr
@@ -0,0 +1,11 @@
+error[E0658]: the `#[rustc_on_unimplemented]` attribute is an experimental feature (see issue #29628)
+  --> $DIR/feature-gate-on-unimplemented.rs:4:1
+   |
+LL | #[rustc_on_unimplemented = "test error `{Self}` with `{Bar}`"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(on_unimplemented)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-optin-builtin-traits.rs b/src/test/ui/feature-gates/feature-gate-optin-builtin-traits.rs
new file mode 100644
index 0000000..35c05b7
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-optin-builtin-traits.rs
@@ -0,0 +1,12 @@
+// Test that default and negative trait implementations are gated by
+// `optin_builtin_traits` feature gate
+
+struct DummyStruct;
+
+auto trait AutoDummyTrait {}
+//~^ ERROR auto traits are experimental and possibly buggy
+
+impl !AutoDummyTrait for DummyStruct {}
+//~^ ERROR negative trait bounds are not yet fully implemented; use marker types for now
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-optin-builtin-traits.stderr b/src/test/ui/feature-gates/feature-gate-optin-builtin-traits.stderr
new file mode 100644
index 0000000..e5d0a86
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-optin-builtin-traits.stderr
@@ -0,0 +1,19 @@
+error[E0658]: auto traits are experimental and possibly buggy (see issue #13231)
+  --> $DIR/feature-gate-optin-builtin-traits.rs:6:1
+   |
+LL | auto trait AutoDummyTrait {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(optin_builtin_traits)] to the crate attributes to enable
+
+error[E0658]: negative trait bounds are not yet fully implemented; use marker types for now (see issue #13231)
+  --> $DIR/feature-gate-optin-builtin-traits.rs:9:1
+   |
+LL | impl !AutoDummyTrait for DummyStruct {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(optin_builtin_traits)] to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-overlapping_marker_traits.rs b/src/test/ui/feature-gates/feature-gate-overlapping_marker_traits.rs
new file mode 100644
index 0000000..6922d6f
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-overlapping_marker_traits.rs
@@ -0,0 +1,9 @@
+use std::fmt::{Debug, Display};
+
+trait MyMarker {}
+
+impl<T: Display> MyMarker for T {}
+impl<T: Debug> MyMarker for T {}
+//~^ ERROR E0119
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-overlapping_marker_traits.stderr b/src/test/ui/feature-gates/feature-gate-overlapping_marker_traits.stderr
new file mode 100644
index 0000000..5ce4c5c
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-overlapping_marker_traits.stderr
@@ -0,0 +1,11 @@
+error[E0119]: conflicting implementations of trait `MyMarker`:
+  --> $DIR/feature-gate-overlapping_marker_traits.rs:6:1
+   |
+LL | impl<T: Display> MyMarker for T {}
+   | ------------------------------- first implementation here
+LL | impl<T: Debug> MyMarker for T {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/feature-gates/feature-gate-plugin.rs b/src/test/ui/feature-gates/feature-gate-plugin.rs
new file mode 100644
index 0000000..977a555
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-plugin.rs
@@ -0,0 +1,6 @@
+// Test that `#![plugin(...)]` attribute is gated by `plugin` feature gate
+
+#![plugin(foo)]
+//~^ ERROR compiler plugins are experimental and possibly buggy
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-plugin.stderr b/src/test/ui/feature-gates/feature-gate-plugin.stderr
new file mode 100644
index 0000000..0feebb6
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-plugin.stderr
@@ -0,0 +1,11 @@
+error[E0658]: compiler plugins are experimental and possibly buggy (see issue #29597)
+  --> $DIR/feature-gate-plugin.rs:3:1
+   |
+LL | #![plugin(foo)]
+   | ^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(plugin)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-plugin_registrar.rs b/src/test/ui/feature-gates/feature-gate-plugin_registrar.rs
new file mode 100644
index 0000000..0e357f8
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-plugin_registrar.rs
@@ -0,0 +1,8 @@
+// Test that `#[plugin_registrar]` attribute is gated by `plugin_registrar`
+// feature gate.
+
+// the registration function isn't typechecked yet
+#[plugin_registrar]
+pub fn registrar() {}
+//~^ ERROR compiler plugins are experimental
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-plugin_registrar.stderr b/src/test/ui/feature-gates/feature-gate-plugin_registrar.stderr
new file mode 100644
index 0000000..6464d40
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-plugin_registrar.stderr
@@ -0,0 +1,11 @@
+error[E0658]: compiler plugins are experimental and possibly buggy (see issue #29597)
+  --> $DIR/feature-gate-plugin_registrar.rs:6:1
+   |
+LL | pub fn registrar() {}
+   | ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(plugin_registrar)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-precise_pointer_size_matching.rs b/src/test/ui/feature-gates/feature-gate-precise_pointer_size_matching.rs
new file mode 100644
index 0000000..1208552
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-precise_pointer_size_matching.rs
@@ -0,0 +1,14 @@
+#![feature(exclusive_range_pattern)]
+
+use std::usize::MAX;
+
+fn main() {
+    match 0usize { //~ERROR non-exhaustive patterns: `_` not covered
+        0..=MAX => {}
+    }
+
+    match 0isize { //~ERROR non-exhaustive patterns: `_` not covered
+        1..=20 => {}
+        -5..3 => {}
+    }
+}
diff --git a/src/test/ui/feature-gates/feature-gate-precise_pointer_size_matching.stderr b/src/test/ui/feature-gates/feature-gate-precise_pointer_size_matching.stderr
new file mode 100644
index 0000000..12b796d
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-precise_pointer_size_matching.stderr
@@ -0,0 +1,19 @@
+error[E0004]: non-exhaustive patterns: `_` not covered
+  --> $DIR/feature-gate-precise_pointer_size_matching.rs:6:11
+   |
+LL |     match 0usize {
+   |           ^^^^^^ pattern `_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `_` not covered
+  --> $DIR/feature-gate-precise_pointer_size_matching.rs:10:11
+   |
+LL |     match 0isize {
+   |           ^^^^^^ pattern `_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/feature-gates/feature-gate-prelude_import.rs b/src/test/ui/feature-gates/feature-gate-prelude_import.rs
new file mode 100644
index 0000000..a338bf9
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-prelude_import.rs
@@ -0,0 +1,4 @@
+#[prelude_import] //~ ERROR `#[prelude_import]` is for use by rustc only
+use std::prelude::v1::*;
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-prelude_import.stderr b/src/test/ui/feature-gates/feature-gate-prelude_import.stderr
new file mode 100644
index 0000000..7501954
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-prelude_import.stderr
@@ -0,0 +1,11 @@
+error[E0658]: `#[prelude_import]` is for use by rustc only
+  --> $DIR/feature-gate-prelude_import.rs:1:1
+   |
+LL | #[prelude_import]
+   | ^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(prelude_import)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-profiler-runtime.rs b/src/test/ui/feature-gates/feature-gate-profiler-runtime.rs
new file mode 100644
index 0000000..f8a7096
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-profiler-runtime.rs
@@ -0,0 +1,3 @@
+#![profiler_runtime] //~ ERROR the `#[profiler_runtime]` attribute is
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-profiler-runtime.stderr b/src/test/ui/feature-gates/feature-gate-profiler-runtime.stderr
new file mode 100644
index 0000000..1f33540
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-profiler-runtime.stderr
@@ -0,0 +1,11 @@
+error[E0658]: the `#[profiler_runtime]` attribute is used to identify the `profiler_builtins` crate which contains the profiler runtime and will never be stable
+  --> $DIR/feature-gate-profiler-runtime.rs:1:1
+   |
+LL | #![profiler_runtime]
+   | ^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(profiler_runtime)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-public_private_dependencies.rs b/src/test/ui/feature-gates/feature-gate-public_private_dependencies.rs
new file mode 100644
index 0000000..b8fb4b8
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-public_private_dependencies.rs
@@ -0,0 +1,20 @@
+// This test is different from other feature gate tests.
+// Instead of checking that an error occurs without the feature gate,
+// it checks that *no* errors/warnings occurs without the feature gate.
+// This is due to the fact that 'public_private_dependencies' just enables
+// a lint, so disabling it shouldn't cause any code to stop compiling.
+
+// run-pass
+// aux-build:pub_dep.rs
+
+// Without ![feature(public_private_dependencies)],
+// this should do nothing/
+#![deny(exported_private_dependencies)]
+
+extern crate pub_dep;
+
+pub struct Foo {
+    pub field: pub_dep::PubType
+}
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-re-rebalance-coherence.rs b/src/test/ui/feature-gates/feature-gate-re-rebalance-coherence.rs
new file mode 100644
index 0000000..505a453
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-re-rebalance-coherence.rs
@@ -0,0 +1,13 @@
+// Test that the use of the box syntax is gated by `re-rebalance-coherence` feature gate.
+
+// aux-build:re_rebalance_coherence_lib.rs
+
+extern crate re_rebalance_coherence_lib as lib;
+use lib::*;
+
+struct Oracle;
+impl Backend for Oracle {}
+impl<'a, T:'a, Tab> QueryFragment<Oracle> for BatchInsert<'a, T, Tab> {}
+//~^ ERROR E0210
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-re-rebalance-coherence.stderr b/src/test/ui/feature-gates/feature-gate-re-rebalance-coherence.stderr
new file mode 100644
index 0000000..5972e61
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-re-rebalance-coherence.stderr
@@ -0,0 +1,11 @@
+error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
+  --> $DIR/feature-gate-re-rebalance-coherence.rs:10:1
+   |
+LL | impl<'a, T:'a, Tab> QueryFragment<Oracle> for BatchInsert<'a, T, Tab> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type
+   |
+   = note: only traits defined in the current crate can be implemented for a type parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0210`.
diff --git a/src/test/ui/feature-gates/feature-gate-repr-simd.rs b/src/test/ui/feature-gates/feature-gate-repr-simd.rs
new file mode 100644
index 0000000..9d28f43
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-repr-simd.rs
@@ -0,0 +1,8 @@
+#[repr(simd)] //~ error: SIMD types are experimental
+struct Foo(u64, u64);
+
+#[repr(C)] //~ warn: conflicting representation hints
+#[repr(simd)] //~ error: SIMD types are experimental
+struct Bar(u64, u64);
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-repr-simd.stderr b/src/test/ui/feature-gates/feature-gate-repr-simd.stderr
new file mode 100644
index 0000000..c47ce70
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-repr-simd.stderr
@@ -0,0 +1,28 @@
+error[E0658]: SIMD types are experimental and possibly buggy (see issue #27731)
+  --> $DIR/feature-gate-repr-simd.rs:1:1
+   |
+LL | #[repr(simd)]
+   | ^^^^^^^^^^^^^
+   |
+   = help: add #![feature(repr_simd)] to the crate attributes to enable
+
+error[E0658]: SIMD types are experimental and possibly buggy (see issue #27731)
+  --> $DIR/feature-gate-repr-simd.rs:5:1
+   |
+LL | #[repr(simd)]
+   | ^^^^^^^^^^^^^
+   |
+   = help: add #![feature(repr_simd)] to the crate attributes to enable
+
+warning[E0566]: conflicting representation hints
+  --> $DIR/feature-gate-repr-simd.rs:4:8
+   |
+LL | #[repr(C)]
+   |        ^
+LL | #[repr(simd)]
+   |        ^^^^
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0566, E0658.
+For more information about an error, try `rustc --explain E0566`.
diff --git a/src/test/ui/feature-gates/feature-gate-repr128.rs b/src/test/ui/feature-gates/feature-gate-repr128.rs
new file mode 100644
index 0000000..0290874
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-repr128.rs
@@ -0,0 +1,6 @@
+#[repr(u128)]
+enum A { //~ ERROR repr with 128-bit type is unstable
+    A(u64)
+}
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-repr128.stderr b/src/test/ui/feature-gates/feature-gate-repr128.stderr
new file mode 100644
index 0000000..a2fd659
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-repr128.stderr
@@ -0,0 +1,13 @@
+error[E0658]: repr with 128-bit type is unstable (see issue #35118)
+  --> $DIR/feature-gate-repr128.rs:2:1
+   |
+LL | / enum A {
+LL | |     A(u64)
+LL | | }
+   | |_^
+   |
+   = help: add #![feature(repr128)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-repr_align_enum.rs b/src/test/ui/feature-gates/feature-gate-repr_align_enum.rs
new file mode 100644
index 0000000..f8e68a9
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-repr_align_enum.rs
@@ -0,0 +1,10 @@
+#[repr(align(16))]
+struct Foo(u64);
+
+#[repr(align(8))] //~ ERROR `#[repr(align(x))]` on enums is experimental (see issue #57996)
+enum Bar {
+    Foo { foo: Foo },
+    Baz,
+}
+
+fn main() { }
diff --git a/src/test/ui/feature-gates/feature-gate-repr_align_enum.stderr b/src/test/ui/feature-gates/feature-gate-repr_align_enum.stderr
new file mode 100644
index 0000000..ae4066c
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-repr_align_enum.stderr
@@ -0,0 +1,11 @@
+error[E0658]: `#[repr(align(x))]` on enums is experimental (see issue #57996)
+  --> $DIR/feature-gate-repr_align_enum.rs:4:1
+   |
+LL | #[repr(align(8))]
+   | ^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(repr_align_enum)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-rustc-attrs-1.rs b/src/test/ui/feature-gates/feature-gate-rustc-attrs-1.rs
new file mode 100644
index 0000000..f7ff3eb
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-rustc-attrs-1.rs
@@ -0,0 +1,8 @@
+// ignore-tidy-linelength
+
+// Test that `#[rustc_*]` attributes are gated by `rustc_attrs` feature gate.
+
+#[rustc_variance] //~ ERROR the `#[rustc_variance]` attribute is just used for rustc unit tests and will never be stable
+#[rustc_error] //~ ERROR the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-rustc-attrs-1.stderr b/src/test/ui/feature-gates/feature-gate-rustc-attrs-1.stderr
new file mode 100644
index 0000000..73cd28f
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-rustc-attrs-1.stderr
@@ -0,0 +1,19 @@
+error[E0658]: the `#[rustc_variance]` attribute is just used for rustc unit tests and will never be stable (see issue #29642)
+  --> $DIR/feature-gate-rustc-attrs-1.rs:5:1
+   |
+LL | #[rustc_variance]
+   | ^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(rustc_attrs)] to the crate attributes to enable
+
+error[E0658]: the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable (see issue #29642)
+  --> $DIR/feature-gate-rustc-attrs-1.rs:6:1
+   |
+LL | #[rustc_error]
+   | ^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(rustc_attrs)] to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-rustc-attrs.rs b/src/test/ui/feature-gates/feature-gate-rustc-attrs.rs
new file mode 100644
index 0000000..5ec413c
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-rustc-attrs.rs
@@ -0,0 +1,6 @@
+// Test that `#[rustc_*]` attributes are gated by `rustc_attrs` feature gate.
+
+#[rustc_foo]
+//~^ ERROR unless otherwise specified, attributes with the prefix `rustc_` are reserved
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr b/src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr
new file mode 100644
index 0000000..40e6d6d
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr
@@ -0,0 +1,11 @@
+error[E0658]: unless otherwise specified, attributes with the prefix `rustc_` are reserved for internal compiler diagnostics (see issue #29642)
+  --> $DIR/feature-gate-rustc-attrs.rs:3:3
+   |
+LL | #[rustc_foo]
+   |   ^^^^^^^^^
+   |
+   = help: add #![feature(rustc_attrs)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-rustc-diagnostic-macros.rs b/src/test/ui/feature-gates/feature-gate-rustc-diagnostic-macros.rs
new file mode 100644
index 0000000..63c2c31
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-rustc-diagnostic-macros.rs
@@ -0,0 +1,13 @@
+// Test that diagnostic macros are gated by `rustc_diagnostic_macros` feature
+// gate
+
+__register_diagnostic!(E0001);
+//~^ ERROR cannot find macro `__register_diagnostic!` in this scope
+
+fn main() {
+    __diagnostic_used!(E0001);
+    //~^ ERROR cannot find macro `__diagnostic_used!` in this scope
+}
+
+__build_diagnostic_array!(DIAGNOSTICS);
+//~^ ERROR cannot find macro `__build_diagnostic_array!` in this scope
diff --git a/src/test/ui/feature-gates/feature-gate-rustc-diagnostic-macros.stderr b/src/test/ui/feature-gates/feature-gate-rustc-diagnostic-macros.stderr
new file mode 100644
index 0000000..478bc09
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-rustc-diagnostic-macros.stderr
@@ -0,0 +1,20 @@
+error: cannot find macro `__build_diagnostic_array!` in this scope
+  --> $DIR/feature-gate-rustc-diagnostic-macros.rs:12:1
+   |
+LL | __build_diagnostic_array!(DIAGNOSTICS);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: cannot find macro `__register_diagnostic!` in this scope
+  --> $DIR/feature-gate-rustc-diagnostic-macros.rs:4:1
+   |
+LL | __register_diagnostic!(E0001);
+   | ^^^^^^^^^^^^^^^^^^^^^
+
+error: cannot find macro `__diagnostic_used!` in this scope
+  --> $DIR/feature-gate-rustc-diagnostic-macros.rs:8:5
+   |
+LL |     __diagnostic_used!(E0001);
+   |     ^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/feature-gates/feature-gate-rustc_const_unstable.rs b/src/test/ui/feature-gates/feature-gate-rustc_const_unstable.rs
new file mode 100644
index 0000000..a85f2f4
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-rustc_const_unstable.rs
@@ -0,0 +1,13 @@
+// Test internal const fn feature gate.
+
+#![feature(staged_api)]
+#![feature(const_fn)]
+//#![feature(rustc_const_unstable)]
+
+#[stable(feature="zing", since="1.0.0")]
+#[rustc_const_unstable(feature="fzzzzzt")] //~ERROR internal feature
+pub const fn bazinga() {}
+
+fn main() {
+}
+
diff --git a/src/test/ui/feature-gates/feature-gate-rustc_const_unstable.stderr b/src/test/ui/feature-gates/feature-gate-rustc_const_unstable.stderr
new file mode 100644
index 0000000..8f584c3
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-rustc_const_unstable.stderr
@@ -0,0 +1,11 @@
+error[E0658]: the `#[rustc_const_unstable]` attribute is an internal feature
+  --> $DIR/feature-gate-rustc_const_unstable.rs:8:1
+   |
+LL | #[rustc_const_unstable(feature="fzzzzzt")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(rustc_const_unstable)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-sanitizer-runtime.rs b/src/test/ui/feature-gates/feature-gate-sanitizer-runtime.rs
new file mode 100644
index 0000000..3b972c1
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-sanitizer-runtime.rs
@@ -0,0 +1,3 @@
+#![sanitizer_runtime] //~ ERROR the `#[sanitizer_runtime]` attribute is
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-sanitizer-runtime.stderr b/src/test/ui/feature-gates/feature-gate-sanitizer-runtime.stderr
new file mode 100644
index 0000000..71d9890
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-sanitizer-runtime.stderr
@@ -0,0 +1,11 @@
+error[E0658]: the `#[sanitizer_runtime]` attribute is used to identify crates that contain the runtime of a sanitizer and will never be stable
+  --> $DIR/feature-gate-sanitizer-runtime.rs:1:1
+   |
+LL | #![sanitizer_runtime]
+   | ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(sanitizer_runtime)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-simd-ffi.rs b/src/test/ui/feature-gates/feature-gate-simd-ffi.rs
new file mode 100644
index 0000000..0425e39
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-simd-ffi.rs
@@ -0,0 +1,13 @@
+#![feature(repr_simd)]
+#![allow(dead_code)]
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+struct LocalSimd(u8, u8);
+
+extern {
+    fn baz() -> LocalSimd; //~ ERROR use of SIMD type
+    fn qux(x: LocalSimd); //~ ERROR use of SIMD type
+}
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-simd-ffi.stderr b/src/test/ui/feature-gates/feature-gate-simd-ffi.stderr
new file mode 100644
index 0000000..11e095f
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-simd-ffi.stderr
@@ -0,0 +1,18 @@
+error: use of SIMD type `LocalSimd` in FFI is highly experimental and may result in invalid code
+  --> $DIR/feature-gate-simd-ffi.rs:9:17
+   |
+LL |     fn baz() -> LocalSimd;
+   |                 ^^^^^^^^^
+   |
+   = help: add #![feature(simd_ffi)] to the crate attributes to enable
+
+error: use of SIMD type `LocalSimd` in FFI is highly experimental and may result in invalid code
+  --> $DIR/feature-gate-simd-ffi.rs:10:15
+   |
+LL |     fn qux(x: LocalSimd);
+   |               ^^^^^^^^^
+   |
+   = help: add #![feature(simd_ffi)] to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/feature-gates/feature-gate-simd.rs b/src/test/ui/feature-gates/feature-gate-simd.rs
new file mode 100644
index 0000000..d01d33d
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-simd.rs
@@ -0,0 +1,11 @@
+// pretty-expanded FIXME #23616
+
+#[repr(simd)] //~ ERROR SIMD types are experimental
+struct RGBA {
+    r: f32,
+    g: f32,
+    b: f32,
+    a: f32
+}
+
+pub fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-simd.stderr b/src/test/ui/feature-gates/feature-gate-simd.stderr
new file mode 100644
index 0000000..b37f138
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-simd.stderr
@@ -0,0 +1,11 @@
+error[E0658]: SIMD types are experimental and possibly buggy (see issue #27731)
+  --> $DIR/feature-gate-simd.rs:3:1
+   |
+LL | #[repr(simd)]
+   | ^^^^^^^^^^^^^
+   |
+   = help: add #![feature(repr_simd)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-slice-patterns.rs b/src/test/ui/feature-gates/feature-gate-slice-patterns.rs
new file mode 100644
index 0000000..0165321
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-slice-patterns.rs
@@ -0,0 +1,17 @@
+// Test that slice pattern syntax with `..` is gated by `slice_patterns` feature gate
+
+fn main() {
+    let x = [1, 2, 3, 4, 5];
+    match x {
+        [1, 2, ..] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized
+        [1, .., 5] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized
+        [.., 4, 5] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized
+    }
+
+    let x = [ 1, 2, 3, 4, 5 ];
+    match x {
+        [ xs.., 4, 5 ] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized
+        [ 1, xs.., 5 ] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized
+        [ 1, 2, xs.. ] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized
+    }
+}
diff --git a/src/test/ui/feature-gates/feature-gate-slice-patterns.stderr b/src/test/ui/feature-gates/feature-gate-slice-patterns.stderr
new file mode 100644
index 0000000..58eb575
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-slice-patterns.stderr
@@ -0,0 +1,51 @@
+error[E0658]: syntax for subslices in slice patterns is not yet stabilized (see issue #23121)
+  --> $DIR/feature-gate-slice-patterns.rs:6:16
+   |
+LL |         [1, 2, ..] => {}
+   |                ^^
+   |
+   = help: add #![feature(slice_patterns)] to the crate attributes to enable
+
+error[E0658]: syntax for subslices in slice patterns is not yet stabilized (see issue #23121)
+  --> $DIR/feature-gate-slice-patterns.rs:7:13
+   |
+LL |         [1, .., 5] => {}
+   |             ^^
+   |
+   = help: add #![feature(slice_patterns)] to the crate attributes to enable
+
+error[E0658]: syntax for subslices in slice patterns is not yet stabilized (see issue #23121)
+  --> $DIR/feature-gate-slice-patterns.rs:8:10
+   |
+LL |         [.., 4, 5] => {}
+   |          ^^
+   |
+   = help: add #![feature(slice_patterns)] to the crate attributes to enable
+
+error[E0658]: syntax for subslices in slice patterns is not yet stabilized (see issue #23121)
+  --> $DIR/feature-gate-slice-patterns.rs:13:11
+   |
+LL |         [ xs.., 4, 5 ] => {}
+   |           ^^
+   |
+   = help: add #![feature(slice_patterns)] to the crate attributes to enable
+
+error[E0658]: syntax for subslices in slice patterns is not yet stabilized (see issue #23121)
+  --> $DIR/feature-gate-slice-patterns.rs:14:14
+   |
+LL |         [ 1, xs.., 5 ] => {}
+   |              ^^
+   |
+   = help: add #![feature(slice_patterns)] to the crate attributes to enable
+
+error[E0658]: syntax for subslices in slice patterns is not yet stabilized (see issue #23121)
+  --> $DIR/feature-gate-slice-patterns.rs:15:17
+   |
+LL |         [ 1, 2, xs.. ] => {}
+   |                 ^^
+   |
+   = help: add #![feature(slice_patterns)] to the crate attributes to enable
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-staged_api.rs b/src/test/ui/feature-gates/feature-gate-staged_api.rs
new file mode 100644
index 0000000..2571ab5
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-staged_api.rs
@@ -0,0 +1,14 @@
+#![stable(feature = "a", since = "b")]
+//~^ ERROR stability attributes may not be used outside of the standard library
+mod inner_private_module {
+    // UnnameableTypeAlias isn't marked as reachable, so no stability annotation is required here
+    pub type UnnameableTypeAlias = u8;
+}
+
+#[stable(feature = "a", since = "b")]
+//~^ ERROR stability attributes may not be used outside of the standard library
+pub fn f() -> inner_private_module::UnnameableTypeAlias {
+    0
+}
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-staged_api.stderr b/src/test/ui/feature-gates/feature-gate-staged_api.stderr
new file mode 100644
index 0000000..f0db47f
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-staged_api.stderr
@@ -0,0 +1,14 @@
+error: stability attributes may not be used outside of the standard library
+  --> $DIR/feature-gate-staged_api.rs:1:1
+   |
+LL | #![stable(feature = "a", since = "b")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: stability attributes may not be used outside of the standard library
+  --> $DIR/feature-gate-staged_api.rs:8:1
+   |
+LL | #[stable(feature = "a", since = "b")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/feature-gates/feature-gate-start.rs b/src/test/ui/feature-gates/feature-gate-start.rs
new file mode 100644
index 0000000..46a1279
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-start.rs
@@ -0,0 +1,3 @@
+#[start]
+fn foo(_: isize, _: *const *const u8) -> isize { 0 }
+//~^ ERROR a #[start] function is an experimental feature
diff --git a/src/test/ui/feature-gates/feature-gate-start.stderr b/src/test/ui/feature-gates/feature-gate-start.stderr
new file mode 100644
index 0000000..d39e5f3
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-start.stderr
@@ -0,0 +1,11 @@
+error[E0658]: a #[start] function is an experimental feature whose signature may change over time (see issue #29633)
+  --> $DIR/feature-gate-start.rs:2:1
+   |
+LL | fn foo(_: isize, _: *const *const u8) -> isize { 0 }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(start)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-static-nobundle.rs b/src/test/ui/feature-gates/feature-gate-static-nobundle.rs
new file mode 100644
index 0000000..1ce6c54
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-static-nobundle.rs
@@ -0,0 +1,5 @@
+#[link(name="foo", kind="static-nobundle")]
+//~^ ERROR: kind="static-nobundle" is feature gated
+extern {}
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-static-nobundle.stderr b/src/test/ui/feature-gates/feature-gate-static-nobundle.stderr
new file mode 100644
index 0000000..2e80275
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-static-nobundle.stderr
@@ -0,0 +1,11 @@
+error[E0658]: kind="static-nobundle" is feature gated (see issue #37403)
+  --> $DIR/feature-gate-static-nobundle.rs:1:1
+   |
+LL | #[link(name="foo", kind="static-nobundle")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(static_nobundle)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-stmt_expr_attributes.rs b/src/test/ui/feature-gates/feature-gate-stmt_expr_attributes.rs
new file mode 100644
index 0000000..3e5b626
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-stmt_expr_attributes.rs
@@ -0,0 +1,4 @@
+const X: i32 = #[allow(dead_code)] 8;
+//~^ ERROR attributes on expressions are experimental. (see issue #15701)
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-stmt_expr_attributes.stderr b/src/test/ui/feature-gates/feature-gate-stmt_expr_attributes.stderr
new file mode 100644
index 0000000..4318edd
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-stmt_expr_attributes.stderr
@@ -0,0 +1,11 @@
+error[E0658]: attributes on expressions are experimental. (see issue #15701)
+  --> $DIR/feature-gate-stmt_expr_attributes.rs:1:16
+   |
+LL | const X: i32 = #[allow(dead_code)] 8;
+   |                ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(stmt_expr_attributes)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-thread_local.rs b/src/test/ui/feature-gates/feature-gate-thread_local.rs
new file mode 100644
index 0000000..0efae1f
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-thread_local.rs
@@ -0,0 +1,11 @@
+// Test that `#[thread_local]` attribute is gated by `thread_local`
+// feature gate.
+//
+// (Note that the `thread_local!` macro is explicitly *not* gated; it
+// is given permission to expand into this unstable attribute even
+// when the surrounding context does not have permission to use it.)
+
+#[thread_local] //~ ERROR `#[thread_local]` is an experimental feature
+static FOO: i32 = 3;
+
+pub fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-thread_local.stderr b/src/test/ui/feature-gates/feature-gate-thread_local.stderr
new file mode 100644
index 0000000..38064a6
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-thread_local.stderr
@@ -0,0 +1,11 @@
+error[E0658]: `#[thread_local]` is an experimental feature, and does not currently handle destructors. (see issue #29594)
+  --> $DIR/feature-gate-thread_local.rs:8:1
+   |
+LL | #[thread_local]
+   | ^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(thread_local)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-trace_macros.rs b/src/test/ui/feature-gates/feature-gate-trace_macros.rs
new file mode 100644
index 0000000..07159b7
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-trace_macros.rs
@@ -0,0 +1,3 @@
+fn main() {
+    trace_macros!(true); //~ ERROR: `trace_macros` is not stable
+}
diff --git a/src/test/ui/feature-gates/feature-gate-trace_macros.stderr b/src/test/ui/feature-gates/feature-gate-trace_macros.stderr
new file mode 100644
index 0000000..ee22bd2
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-trace_macros.stderr
@@ -0,0 +1,11 @@
+error[E0658]: `trace_macros` is not stable enough for use and is subject to change (see issue #29598)
+  --> $DIR/feature-gate-trace_macros.rs:2:5
+   |
+LL |     trace_macros!(true);
+   |     ^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(trace_macros)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-trait-alias.rs b/src/test/ui/feature-gates/feature-gate-trait-alias.rs
new file mode 100644
index 0000000..819085a
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-trait-alias.rs
@@ -0,0 +1,4 @@
+trait Foo = Default;
+//~^ ERROR trait aliases are experimental
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-trait-alias.stderr b/src/test/ui/feature-gates/feature-gate-trait-alias.stderr
new file mode 100644
index 0000000..bb833c4
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-trait-alias.stderr
@@ -0,0 +1,11 @@
+error[E0658]: trait aliases are experimental (see issue #41517)
+  --> $DIR/feature-gate-trait-alias.rs:1:1
+   |
+LL | trait Foo = Default;
+   | ^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(trait_alias)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-trivial_bounds-lint.rs b/src/test/ui/feature-gates/feature-gate-trivial_bounds-lint.rs
new file mode 100644
index 0000000..8f68d5d
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-trivial_bounds-lint.rs
@@ -0,0 +1,8 @@
+// run-pass
+
+#![allow(unused)]
+#![deny(trivial_bounds)] // Ignored without the trivial_bounds feature flag.
+
+struct A where i32: Copy;
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-trivial_bounds.rs b/src/test/ui/feature-gates/feature-gate-trivial_bounds.rs
new file mode 100644
index 0000000..e5028f2
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-trivial_bounds.rs
@@ -0,0 +1,69 @@
+#![allow(unused)]
+#![allow(type_alias_bounds)]
+
+pub trait Foo {
+    fn test(&self);
+}
+
+fn generic_function<X: Foo>(x: X) {}
+
+enum E where i32: Foo { V } //~ ERROR
+
+struct S where i32: Foo; //~ ERROR
+
+trait T where i32: Foo {} //~ ERROR
+
+union U where i32: Foo { f: i32 } //~ ERROR
+
+type Y where i32: Foo = (); // OK - bound is ignored
+
+impl Foo for () where i32: Foo { //~ ERROR
+    fn test(&self) {
+        3i32.test();
+        Foo::test(&4i32);
+        generic_function(5i32);
+    }
+}
+
+fn f() where i32: Foo //~ ERROR
+{
+    let s = S;
+    3i32.test();
+    Foo::test(&4i32);
+    generic_function(5i32);
+}
+
+fn use_op(s: String) -> String where String: ::std::ops::Neg<Output=String> { //~ ERROR
+    -s
+}
+
+fn use_for() where i32: Iterator { //~ ERROR
+    for _ in 2i32 {}
+}
+
+trait A {}
+
+impl A for i32 {}
+
+struct Dst<X: ?Sized> {
+    x: X,
+}
+
+struct TwoStrs(str, str) where str: Sized; //~ ERROR
+
+
+fn unsized_local() where Dst<A>: Sized { //~ ERROR
+    let x: Dst<A> = *(Box::new(Dst { x: 1 }) as Box<Dst<A>>);
+}
+
+fn return_str() -> str where str: Sized { //~ ERROR
+    *"Sized".to_string().into_boxed_str()
+}
+
+// This is currently accepted because the function pointer isn't
+// considered global.
+fn global_hr(x: fn(&())) where fn(&()): Foo { // OK
+    x.test();
+}
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-trivial_bounds.stderr b/src/test/ui/feature-gates/feature-gate-trivial_bounds.stderr
new file mode 100644
index 0000000..b04a6e4
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-trivial_bounds.stderr
@@ -0,0 +1,131 @@
+error[E0277]: the trait bound `i32: Foo` is not satisfied
+  --> $DIR/feature-gate-trivial_bounds.rs:10:1
+   |
+LL | enum E where i32: Foo { V }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `i32`
+   |
+   = help: see issue #48214
+   = help: add #![feature(trivial_bounds)] to the crate attributes to enable
+
+error[E0277]: the trait bound `i32: Foo` is not satisfied
+  --> $DIR/feature-gate-trivial_bounds.rs:12:1
+   |
+LL | struct S where i32: Foo;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `i32`
+   |
+   = help: see issue #48214
+   = help: add #![feature(trivial_bounds)] to the crate attributes to enable
+
+error[E0277]: the trait bound `i32: Foo` is not satisfied
+  --> $DIR/feature-gate-trivial_bounds.rs:14:1
+   |
+LL | trait T where i32: Foo {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `i32`
+   |
+   = help: see issue #48214
+   = help: add #![feature(trivial_bounds)] to the crate attributes to enable
+
+error[E0277]: the trait bound `i32: Foo` is not satisfied
+  --> $DIR/feature-gate-trivial_bounds.rs:16:1
+   |
+LL | union U where i32: Foo { f: i32 }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `i32`
+   |
+   = help: see issue #48214
+   = help: add #![feature(trivial_bounds)] to the crate attributes to enable
+
+error[E0277]: the trait bound `i32: Foo` is not satisfied
+  --> $DIR/feature-gate-trivial_bounds.rs:20:1
+   |
+LL | / impl Foo for () where i32: Foo {
+LL | |     fn test(&self) {
+LL | |         3i32.test();
+LL | |         Foo::test(&4i32);
+LL | |         generic_function(5i32);
+LL | |     }
+LL | | }
+   | |_^ the trait `Foo` is not implemented for `i32`
+   |
+   = help: see issue #48214
+   = help: add #![feature(trivial_bounds)] to the crate attributes to enable
+
+error[E0277]: the trait bound `i32: Foo` is not satisfied
+  --> $DIR/feature-gate-trivial_bounds.rs:28:1
+   |
+LL | / fn f() where i32: Foo
+LL | | {
+LL | |     let s = S;
+LL | |     3i32.test();
+LL | |     Foo::test(&4i32);
+LL | |     generic_function(5i32);
+LL | | }
+   | |_^ the trait `Foo` is not implemented for `i32`
+   |
+   = help: see issue #48214
+   = help: add #![feature(trivial_bounds)] to the crate attributes to enable
+
+error[E0277]: the trait bound `std::string::String: std::ops::Neg` is not satisfied
+  --> $DIR/feature-gate-trivial_bounds.rs:36:1
+   |
+LL | / fn use_op(s: String) -> String where String: ::std::ops::Neg<Output=String> {
+LL | |     -s
+LL | | }
+   | |_^ the trait `std::ops::Neg` is not implemented for `std::string::String`
+   |
+   = help: see issue #48214
+   = help: add #![feature(trivial_bounds)] to the crate attributes to enable
+
+error[E0277]: `i32` is not an iterator
+  --> $DIR/feature-gate-trivial_bounds.rs:40:1
+   |
+LL | / fn use_for() where i32: Iterator {
+LL | |     for _ in 2i32 {}
+LL | | }
+   | |_^ `i32` is not an iterator
+   |
+   = help: the trait `std::iter::Iterator` is not implemented for `i32`
+   = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
+   = help: see issue #48214
+   = help: add #![feature(trivial_bounds)] to the crate attributes to enable
+
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+  --> $DIR/feature-gate-trivial_bounds.rs:52:1
+   |
+LL | struct TwoStrs(str, str) where str: Sized;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `str`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = help: see issue #48214
+   = help: add #![feature(trivial_bounds)] to the crate attributes to enable
+
+error[E0277]: the size for values of type `(dyn A + 'static)` cannot be known at compilation time
+  --> $DIR/feature-gate-trivial_bounds.rs:55:1
+   |
+LL | / fn unsized_local() where Dst<A>: Sized {
+LL | |     let x: Dst<A> = *(Box::new(Dst { x: 1 }) as Box<Dst<A>>);
+LL | | }
+   | |_^ doesn't have a size known at compile-time
+   |
+   = help: within `Dst<(dyn A + 'static)>`, the trait `std::marker::Sized` is not implemented for `(dyn A + 'static)`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: required because it appears within the type `Dst<(dyn A + 'static)>`
+   = help: see issue #48214
+   = help: add #![feature(trivial_bounds)] to the crate attributes to enable
+
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+  --> $DIR/feature-gate-trivial_bounds.rs:59:1
+   |
+LL | / fn return_str() -> str where str: Sized {
+LL | |     *"Sized".to_string().into_boxed_str()
+LL | | }
+   | |_^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `str`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = help: see issue #48214
+   = help: add #![feature(trivial_bounds)] to the crate attributes to enable
+
+error: aborting due to 11 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/feature-gates/feature-gate-try_blocks.rs b/src/test/ui/feature-gates/feature-gate-try_blocks.rs
new file mode 100644
index 0000000..06cadd8
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-try_blocks.rs
@@ -0,0 +1,9 @@
+// compile-flags: --edition 2018
+
+pub fn main() {
+    let try_result: Option<_> = try { //~ ERROR `try` expression is experimental
+        let x = 5;
+        x
+    };
+    assert_eq!(try_result, Some(5));
+}
diff --git a/src/test/ui/feature-gates/feature-gate-try_blocks.stderr b/src/test/ui/feature-gates/feature-gate-try_blocks.stderr
new file mode 100644
index 0000000..74ad0e7
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-try_blocks.stderr
@@ -0,0 +1,15 @@
+error[E0658]: `try` expression is experimental (see issue #31436)
+  --> $DIR/feature-gate-try_blocks.rs:4:33
+   |
+LL |       let try_result: Option<_> = try {
+   |  _________________________________^
+LL | |         let x = 5;
+LL | |         x
+LL | |     };
+   | |_____^
+   |
+   = help: add #![feature(try_blocks)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-try_reserve.rs b/src/test/ui/feature-gates/feature-gate-try_reserve.rs
new file mode 100644
index 0000000..a19dd58
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-try_reserve.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let v = Vec::new();
+    v.try_reserve(10); //~ ERROR: use of unstable library feature 'try_reserve'
+}
diff --git a/src/test/ui/feature-gates/feature-gate-try_reserve.stderr b/src/test/ui/feature-gates/feature-gate-try_reserve.stderr
new file mode 100644
index 0000000..61a3249
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-try_reserve.stderr
@@ -0,0 +1,11 @@
+error[E0658]: use of unstable library feature 'try_reserve': new API (see issue #48043)
+  --> $DIR/feature-gate-try_reserve.rs:3:7
+   |
+LL |     v.try_reserve(10);
+   |       ^^^^^^^^^^^
+   |
+   = help: add #![feature(try_reserve)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-type_alias_enum_variants.rs b/src/test/ui/feature-gates/feature-gate-type_alias_enum_variants.rs
new file mode 100644
index 0000000..c7d3304
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-type_alias_enum_variants.rs
@@ -0,0 +1,19 @@
+enum Foo {
+    Bar(i32),
+    Baz { i: i32 },
+}
+
+type Alias = Foo;
+
+fn main() {
+    let t = Alias::Bar(0);
+    //~^ ERROR enum variants on type aliases are experimental
+    let t = Alias::Baz { i: 0 };
+    //~^ ERROR enum variants on type aliases are experimental
+    match t {
+        Alias::Bar(_i) => {}
+        //~^ ERROR enum variants on type aliases are experimental
+        Alias::Baz { i: _i } => {}
+        //~^ ERROR enum variants on type aliases are experimental
+    }
+}
diff --git a/src/test/ui/feature-gates/feature-gate-type_alias_enum_variants.stderr b/src/test/ui/feature-gates/feature-gate-type_alias_enum_variants.stderr
new file mode 100644
index 0000000..43535af
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-type_alias_enum_variants.stderr
@@ -0,0 +1,34 @@
+error: enum variants on type aliases are experimental
+  --> $DIR/feature-gate-type_alias_enum_variants.rs:9:13
+   |
+LL |     let t = Alias::Bar(0);
+   |             ^^^^^^^^^^
+   |
+   = help: add `#![feature(type_alias_enum_variants)]` to the crate attributes to enable
+
+error: enum variants on type aliases are experimental
+  --> $DIR/feature-gate-type_alias_enum_variants.rs:11:13
+   |
+LL |     let t = Alias::Baz { i: 0 };
+   |             ^^^^^^^^^^
+   |
+   = help: add `#![feature(type_alias_enum_variants)]` to the crate attributes to enable
+
+error: enum variants on type aliases are experimental
+  --> $DIR/feature-gate-type_alias_enum_variants.rs:14:9
+   |
+LL |         Alias::Bar(_i) => {}
+   |         ^^^^^^^^^^^^^^
+   |
+   = help: add `#![feature(type_alias_enum_variants)]` to the crate attributes to enable
+
+error: enum variants on type aliases are experimental
+  --> $DIR/feature-gate-type_alias_enum_variants.rs:16:9
+   |
+LL |         Alias::Baz { i: _i } => {}
+   |         ^^^^^^^^^^
+   |
+   = help: add `#![feature(type_alias_enum_variants)]` to the crate attributes to enable
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/feature-gates/feature-gate-type_ascription.rs b/src/test/ui/feature-gates/feature-gate-type_ascription.rs
new file mode 100644
index 0000000..e42e340
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-type_ascription.rs
@@ -0,0 +1,5 @@
+// Type ascription is feature gated
+
+fn main() {
+    let a = 10: u8; //~ ERROR type ascription is experimental
+}
diff --git a/src/test/ui/feature-gates/feature-gate-type_ascription.stderr b/src/test/ui/feature-gates/feature-gate-type_ascription.stderr
new file mode 100644
index 0000000..13dbb60
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-type_ascription.stderr
@@ -0,0 +1,11 @@
+error[E0658]: type ascription is experimental (see issue #23416)
+  --> $DIR/feature-gate-type_ascription.rs:4:13
+   |
+LL |     let a = 10: u8;
+   |             ^^^^^^
+   |
+   = help: add #![feature(type_ascription)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.rs b/src/test/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.rs
new file mode 100644
index 0000000..ff6e2b8
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.rs
@@ -0,0 +1,33 @@
+// Test that manual impls of the `Fn` traits are not possible without
+// a feature gate. In fact, the specialized check for these cases
+// never triggers (yet), because they encounter other problems around
+// angle bracket vs parentheses notation.
+
+#![feature(fn_traits)]
+
+struct Foo;
+impl Fn<()> for Foo {
+//~^ ERROR the precise format of `Fn`-family traits' type parameters is subject to change
+    extern "rust-call" fn call(self, args: ()) -> () {}
+    //~^ ERROR rust-call ABI is subject to change
+}
+struct Foo1;
+impl FnOnce() for Foo1 {
+//~^ ERROR associated type bindings are not allowed here
+    extern "rust-call" fn call_once(self, args: ()) -> () {}
+    //~^ ERROR rust-call ABI is subject to change
+}
+struct Bar;
+impl FnMut<()> for Bar {
+//~^ ERROR the precise format of `Fn`-family traits' type parameters is subject to change
+    extern "rust-call" fn call_mut(&self, args: ()) -> () {}
+    //~^ ERROR rust-call ABI is subject to change
+}
+struct Baz;
+impl FnOnce<()> for Baz {
+//~^ ERROR the precise format of `Fn`-family traits' type parameters is subject to change
+    extern "rust-call" fn call_once(&self, args: ()) -> () {}
+    //~^ ERROR rust-call ABI is subject to change
+}
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr b/src/test/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr
new file mode 100644
index 0000000..865b87e
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr
@@ -0,0 +1,66 @@
+error[E0658]: rust-call ABI is subject to change (see issue #29625)
+  --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:11:5
+   |
+LL |     extern "rust-call" fn call(self, args: ()) -> () {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unboxed_closures)] to the crate attributes to enable
+
+error[E0658]: rust-call ABI is subject to change (see issue #29625)
+  --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:17:5
+   |
+LL |     extern "rust-call" fn call_once(self, args: ()) -> () {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unboxed_closures)] to the crate attributes to enable
+
+error[E0658]: rust-call ABI is subject to change (see issue #29625)
+  --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:23:5
+   |
+LL |     extern "rust-call" fn call_mut(&self, args: ()) -> () {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unboxed_closures)] to the crate attributes to enable
+
+error[E0658]: rust-call ABI is subject to change (see issue #29625)
+  --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:29:5
+   |
+LL |     extern "rust-call" fn call_once(&self, args: ()) -> () {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unboxed_closures)] to the crate attributes to enable
+
+error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change. Use parenthetical notation (Fn(Foo, Bar) -> Baz) instead (see issue #29625)
+  --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:9:6
+   |
+LL | impl Fn<()> for Foo {
+   |      ^^^^^^
+   |
+   = help: add #![feature(unboxed_closures)] to the crate attributes to enable
+
+error[E0229]: associated type bindings are not allowed here
+  --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:15:12
+   |
+LL | impl FnOnce() for Foo1 {
+   |            ^^ associated type not allowed here
+
+error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change. Use parenthetical notation (Fn(Foo, Bar) -> Baz) instead (see issue #29625)
+  --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:21:6
+   |
+LL | impl FnMut<()> for Bar {
+   |      ^^^^^^^^^
+   |
+   = help: add #![feature(unboxed_closures)] to the crate attributes to enable
+
+error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change. Use parenthetical notation (Fn(Foo, Bar) -> Baz) instead (see issue #29625)
+  --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:27:6
+   |
+LL | impl FnOnce<()> for Baz {
+   |      ^^^^^^^^^^
+   |
+   = help: add #![feature(unboxed_closures)] to the crate attributes to enable
+
+error: aborting due to 8 previous errors
+
+Some errors occurred: E0229, E0658.
+For more information about an error, try `rustc --explain E0229`.
diff --git a/src/test/ui/feature-gates/feature-gate-unboxed-closures-method-calls.rs b/src/test/ui/feature-gates/feature-gate-unboxed-closures-method-calls.rs
new file mode 100644
index 0000000..42f7c5f
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-unboxed-closures-method-calls.rs
@@ -0,0 +1,9 @@
+#![allow(dead_code)]
+
+fn foo<F: Fn()>(mut f: F) {
+    f.call(()); //~ ERROR use of unstable library feature 'fn_traits'
+    f.call_mut(()); //~ ERROR use of unstable library feature 'fn_traits'
+    f.call_once(()); //~ ERROR use of unstable library feature 'fn_traits'
+}
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-unboxed-closures-method-calls.stderr b/src/test/ui/feature-gates/feature-gate-unboxed-closures-method-calls.stderr
new file mode 100644
index 0000000..519f652
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-unboxed-closures-method-calls.stderr
@@ -0,0 +1,27 @@
+error[E0658]: use of unstable library feature 'fn_traits' (see issue #29625)
+  --> $DIR/feature-gate-unboxed-closures-method-calls.rs:4:7
+   |
+LL |     f.call(());
+   |       ^^^^
+   |
+   = help: add #![feature(fn_traits)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'fn_traits' (see issue #29625)
+  --> $DIR/feature-gate-unboxed-closures-method-calls.rs:5:7
+   |
+LL |     f.call_mut(());
+   |       ^^^^^^^^
+   |
+   = help: add #![feature(fn_traits)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'fn_traits' (see issue #29625)
+  --> $DIR/feature-gate-unboxed-closures-method-calls.rs:6:7
+   |
+LL |     f.call_once(());
+   |       ^^^^^^^^^
+   |
+   = help: add #![feature(fn_traits)] to the crate attributes to enable
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-unboxed-closures-ufcs-calls.rs b/src/test/ui/feature-gates/feature-gate-unboxed-closures-ufcs-calls.rs
new file mode 100644
index 0000000..25c9049
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-unboxed-closures-ufcs-calls.rs
@@ -0,0 +1,9 @@
+#![allow(dead_code)]
+
+fn foo<F: Fn()>(mut f: F) {
+    Fn::call(&f, ()); //~ ERROR use of unstable library feature 'fn_traits'
+    FnMut::call_mut(&mut f, ()); //~ ERROR use of unstable library feature 'fn_traits'
+    FnOnce::call_once(f, ()); //~ ERROR use of unstable library feature 'fn_traits'
+}
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-unboxed-closures-ufcs-calls.stderr b/src/test/ui/feature-gates/feature-gate-unboxed-closures-ufcs-calls.stderr
new file mode 100644
index 0000000..a49a8b4
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-unboxed-closures-ufcs-calls.stderr
@@ -0,0 +1,27 @@
+error[E0658]: use of unstable library feature 'fn_traits' (see issue #29625)
+  --> $DIR/feature-gate-unboxed-closures-ufcs-calls.rs:4:5
+   |
+LL |     Fn::call(&f, ());
+   |     ^^^^^^^^
+   |
+   = help: add #![feature(fn_traits)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'fn_traits' (see issue #29625)
+  --> $DIR/feature-gate-unboxed-closures-ufcs-calls.rs:5:5
+   |
+LL |     FnMut::call_mut(&mut f, ());
+   |     ^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(fn_traits)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'fn_traits' (see issue #29625)
+  --> $DIR/feature-gate-unboxed-closures-ufcs-calls.rs:6:5
+   |
+LL |     FnOnce::call_once(f, ());
+   |     ^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(fn_traits)] to the crate attributes to enable
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-unboxed-closures.rs b/src/test/ui/feature-gates/feature-gate-unboxed-closures.rs
new file mode 100644
index 0000000..c3f5c99
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-unboxed-closures.rs
@@ -0,0 +1,17 @@
+#![feature(fn_traits)]
+
+struct Test;
+
+impl FnOnce<(u32, u32)> for Test {
+//~^ ERROR the precise format of `Fn`-family traits' type parameters is subject to change
+    type Output = u32;
+
+    extern "rust-call" fn call_once(self, (a, b): (u32, u32)) -> u32 {
+        a + b
+    }
+    //~^^^ ERROR rust-call ABI is subject to change (see issue #29625)
+}
+
+fn main() {
+    assert_eq!(Test(1u32, 2u32), 3u32);
+}
diff --git a/src/test/ui/feature-gates/feature-gate-unboxed-closures.stderr b/src/test/ui/feature-gates/feature-gate-unboxed-closures.stderr
new file mode 100644
index 0000000..e7b1fc5
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-unboxed-closures.stderr
@@ -0,0 +1,21 @@
+error[E0658]: rust-call ABI is subject to change (see issue #29625)
+  --> $DIR/feature-gate-unboxed-closures.rs:9:5
+   |
+LL | /     extern "rust-call" fn call_once(self, (a, b): (u32, u32)) -> u32 {
+LL | |         a + b
+LL | |     }
+   | |_____^
+   |
+   = help: add #![feature(unboxed_closures)] to the crate attributes to enable
+
+error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change. Use parenthetical notation (Fn(Foo, Bar) -> Baz) instead (see issue #29625)
+  --> $DIR/feature-gate-unboxed-closures.rs:5:6
+   |
+LL | impl FnOnce<(u32, u32)> for Test {
+   |      ^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unboxed_closures)] to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-underscore_const_names.rs b/src/test/ui/feature-gates/feature-gate-underscore_const_names.rs
new file mode 100644
index 0000000..6b97c24
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-underscore_const_names.rs
@@ -0,0 +1,14 @@
+trait Trt {}
+struct Str {}
+
+impl Trt for Str {}
+
+const _ : () = {
+//~^ ERROR is unstable
+    use std::marker::PhantomData;
+    struct ImplementsTrait<T: Trt>(PhantomData<T>);
+    let _ = ImplementsTrait::<Str>(PhantomData);
+    ()
+};
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-underscore_const_names.stderr b/src/test/ui/feature-gates/feature-gate-underscore_const_names.stderr
new file mode 100644
index 0000000..ef93bb9
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-underscore_const_names.stderr
@@ -0,0 +1,17 @@
+error[E0658]: naming constants with `_` is unstable (see issue #54912)
+  --> $DIR/feature-gate-underscore_const_names.rs:6:1
+   |
+LL | / const _ : () = {
+LL | |
+LL | |     use std::marker::PhantomData;
+LL | |     struct ImplementsTrait<T: Trt>(PhantomData<T>);
+LL | |     let _ = ImplementsTrait::<Str>(PhantomData);
+LL | |     ()
+LL | | };
+   | |__^
+   |
+   = help: add #![feature(underscore_const_names)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-unsized_locals.rs b/src/test/ui/feature-gates/feature-gate-unsized_locals.rs
new file mode 100644
index 0000000..a8f81f3
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-unsized_locals.rs
@@ -0,0 +1,5 @@
+fn f(f: FnOnce()) {}
+//~^ ERROR E0277
+
+fn main() {
+}
diff --git a/src/test/ui/feature-gates/feature-gate-unsized_locals.stderr b/src/test/ui/feature-gates/feature-gate-unsized_locals.stderr
new file mode 100644
index 0000000..bde39cb
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-unsized_locals.stderr
@@ -0,0 +1,14 @@
+error[E0277]: the size for values of type `(dyn std::ops::FnOnce() + 'static)` cannot be known at compilation time
+  --> $DIR/feature-gate-unsized_locals.rs:1:6
+   |
+LL | fn f(f: FnOnce()) {}
+   |      ^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `(dyn std::ops::FnOnce() + 'static)`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: all local variables must have a statically known size
+   = help: unsized locals are gated as an unstable feature
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/feature-gates/feature-gate-unsized_tuple_coercion.rs b/src/test/ui/feature-gates/feature-gate-unsized_tuple_coercion.rs
new file mode 100644
index 0000000..f781bc9
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-unsized_tuple_coercion.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let _ : &(Send,) = &((),);
+    //~^ ERROR unsized tuple coercion is not stable enough
+}
diff --git a/src/test/ui/feature-gates/feature-gate-unsized_tuple_coercion.stderr b/src/test/ui/feature-gates/feature-gate-unsized_tuple_coercion.stderr
new file mode 100644
index 0000000..c2f5df4
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-unsized_tuple_coercion.stderr
@@ -0,0 +1,11 @@
+error[E0658]: unsized tuple coercion is not stable enough for use and is subject to change (see issue #42877)
+  --> $DIR/feature-gate-unsized_tuple_coercion.rs:2:24
+   |
+LL |     let _ : &(Send,) = &((),);
+   |                        ^^^^^^
+   |
+   = help: add #![feature(unsized_tuple_coercion)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-untagged_unions.rs b/src/test/ui/feature-gates/feature-gate-untagged_unions.rs
new file mode 100644
index 0000000..3bac3d8
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-untagged_unions.rs
@@ -0,0 +1,25 @@
+union U1 { // OK
+    a: u8,
+}
+
+union U2<T: Copy> { // OK
+    a: T,
+}
+
+union U3 { //~ ERROR unions with non-`Copy` fields are unstable
+    a: String,
+}
+
+union U4<T> { //~ ERROR unions with non-`Copy` fields are unstable
+    a: T,
+}
+
+union U5 { //~ ERROR unions with `Drop` implementations are unstable
+    a: u8,
+}
+
+impl Drop for U5 {
+    fn drop(&mut self) {}
+}
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-untagged_unions.stderr b/src/test/ui/feature-gates/feature-gate-untagged_unions.stderr
new file mode 100644
index 0000000..6faa052
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-untagged_unions.stderr
@@ -0,0 +1,33 @@
+error[E0658]: unions with non-`Copy` fields are unstable (see issue #32836)
+  --> $DIR/feature-gate-untagged_unions.rs:9:1
+   |
+LL | / union U3 {
+LL | |     a: String,
+LL | | }
+   | |_^
+   |
+   = help: add #![feature(untagged_unions)] to the crate attributes to enable
+
+error[E0658]: unions with non-`Copy` fields are unstable (see issue #32836)
+  --> $DIR/feature-gate-untagged_unions.rs:13:1
+   |
+LL | / union U4<T> {
+LL | |     a: T,
+LL | | }
+   | |_^
+   |
+   = help: add #![feature(untagged_unions)] to the crate attributes to enable
+
+error[E0658]: unions with `Drop` implementations are unstable (see issue #32836)
+  --> $DIR/feature-gate-untagged_unions.rs:17:1
+   |
+LL | / union U5 {
+LL | |     a: u8,
+LL | | }
+   | |_^
+   |
+   = help: add #![feature(untagged_unions)] to the crate attributes to enable
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-unwind-attributes.rs b/src/test/ui/feature-gates/feature-gate-unwind-attributes.rs
new file mode 100644
index 0000000..e0cb9c8
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-unwind-attributes.rs
@@ -0,0 +1,18 @@
+// compile-flags: -C no-prepopulate-passes -Cpasses=name-anon-globals
+
+#![crate_type = "lib"]
+
+extern {
+// CHECK: Function Attrs: nounwind
+// CHECK-NEXT: declare void @extern_fn
+    fn extern_fn();
+// CHECK-NOT: Function Attrs: nounwind
+// CHECK: declare void @unwinding_extern_fn
+    #[unwind(allowed)] //~ ERROR #[unwind] is experimental
+    fn unwinding_extern_fn();
+}
+
+pub unsafe fn force_declare() {
+    extern_fn();
+    unwinding_extern_fn();
+}
diff --git a/src/test/ui/feature-gates/feature-gate-unwind-attributes.stderr b/src/test/ui/feature-gates/feature-gate-unwind-attributes.stderr
new file mode 100644
index 0000000..149ce9e
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-unwind-attributes.stderr
@@ -0,0 +1,11 @@
+error[E0658]: #[unwind] is experimental (see issue #58760)
+  --> $DIR/feature-gate-unwind-attributes.rs:11:5
+   |
+LL |     #[unwind(allowed)]
+   |     ^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unwind_attributes)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/underscore_const_names_feature_gate.rs b/src/test/ui/feature-gates/underscore_const_names_feature_gate.rs
new file mode 100644
index 0000000..e50bbf5
--- /dev/null
+++ b/src/test/ui/feature-gates/underscore_const_names_feature_gate.rs
@@ -0,0 +1,3 @@
+const _: () = (); //~ ERROR is unstable
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/underscore_const_names_feature_gate.stderr b/src/test/ui/feature-gates/underscore_const_names_feature_gate.stderr
new file mode 100644
index 0000000..83b3017
--- /dev/null
+++ b/src/test/ui/feature-gates/underscore_const_names_feature_gate.stderr
@@ -0,0 +1,11 @@
+error[E0658]: naming constants with `_` is unstable (see issue #54912)
+  --> $DIR/underscore_const_names_feature_gate.rs:1:1
+   |
+LL | const _: () = ();
+   | ^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(underscore_const_names)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/ffi_returns_twice.rs b/src/test/ui/ffi_returns_twice.rs
new file mode 100644
index 0000000..93c372e
--- /dev/null
+++ b/src/test/ui/ffi_returns_twice.rs
@@ -0,0 +1,6 @@
+// ignore-tidy-linelength
+#![feature(ffi_returns_twice)]
+#![crate_type = "lib"]
+
+#[ffi_returns_twice] //~ ERROR `#[ffi_returns_twice]` may only be used on foreign functions
+pub fn foo() {}
diff --git a/src/test/ui/ffi_returns_twice.stderr b/src/test/ui/ffi_returns_twice.stderr
new file mode 100644
index 0000000..e4137c7
--- /dev/null
+++ b/src/test/ui/ffi_returns_twice.stderr
@@ -0,0 +1,9 @@
+error[E0724]: `#[ffi_returns_twice]` may only be used on foreign functions
+  --> $DIR/ffi_returns_twice.rs:5:1
+   |
+LL | #[ffi_returns_twice]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0724`.
diff --git a/src/test/ui/float-literal-inference-restrictions.rs b/src/test/ui/float-literal-inference-restrictions.rs
new file mode 100644
index 0000000..34079b6
--- /dev/null
+++ b/src/test/ui/float-literal-inference-restrictions.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let x: f32 = 1; //~ ERROR mismatched types
+    let y: f32 = 1f64; //~ ERROR mismatched types
+}
diff --git a/src/test/ui/float-literal-inference-restrictions.stderr b/src/test/ui/float-literal-inference-restrictions.stderr
new file mode 100644
index 0000000..6ac49b7
--- /dev/null
+++ b/src/test/ui/float-literal-inference-restrictions.stderr
@@ -0,0 +1,21 @@
+error[E0308]: mismatched types
+  --> $DIR/float-literal-inference-restrictions.rs:2:18
+   |
+LL |     let x: f32 = 1;
+   |                  ^
+   |                  |
+   |                  expected f32, found integer
+   |                  help: use a float literal: `1.0`
+   |
+   = note: expected type `f32`
+              found type `{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/float-literal-inference-restrictions.rs:3:18
+   |
+LL |     let y: f32 = 1f64;
+   |                  ^^^^ expected f32, found f64
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/fmt/format-string-error-2.rs b/src/test/ui/fmt/format-string-error-2.rs
new file mode 100644
index 0000000..5c25ae5
--- /dev/null
+++ b/src/test/ui/fmt/format-string-error-2.rs
@@ -0,0 +1,87 @@
+// ignore-tidy-tab
+
+fn main() {
+    format!("{
+    a");
+    //~^ ERROR invalid format string
+    format!("{ \
+
+    b");
+    //~^ ERROR invalid format string
+    format!(r#"{ \
+
+    rawc"#);
+    //~^^^ ERROR invalid format string
+    format!(r#"{ \n
+\n
+    rawd"#);
+    //~^^^ ERROR invalid format string
+    format!("{ \n
+\n
+    e");
+    //~^ ERROR invalid format string
+    format!("
+    {
+    a");
+    //~^ ERROR invalid format string
+    format!("
+    {
+    a
+    ");
+    //~^^ ERROR invalid format string
+    format!("  \
+    { \
+    	\
+    b");
+    //~^ ERROR invalid format string
+    format!("  \
+    { \
+    	\
+    b \
+
+    ");
+    //~^^^ ERROR invalid format string
+    format!(r#"
+raw  { \
+
+    c"#);
+    //~^^^ ERROR invalid format string
+    format!(r#"
+raw  { \n
+\n
+    d"#);
+    //~^^^ ERROR invalid format string
+    format!("
+  { \n
+\n
+    e");
+    //~^ ERROR invalid format string
+
+    format!("
+    {asdf
+    }
+    ", asdf=1);
+    // ok - this is supported
+    format!("
+    {
+    asdf}
+    ", asdf=1);
+    //~^^ ERROR invalid format string
+    println!("\t{}");
+    //~^ ERROR 1 positional argument in format string
+
+    // note: `\x7B` is `{`
+    println!("\x7B}\u{8} {", 1);
+    //~^ ERROR invalid format string: expected `'}'` but string was terminated
+
+    println!("\x7B}\u8 {", 1);
+    //~^ ERROR incorrect unicode escape sequence
+    //~| ERROR argument never used
+
+    // note: raw strings don't escape `\xFF` and `\u{FF}` sequences
+    println!(r#"\x7B}\u{8} {"#, 1);
+    //~^ ERROR invalid format string: unmatched `}` found
+
+    println!(r#"\x7B}\u8 {"#, 1);
+    //~^ ERROR invalid format string: unmatched `}` found
+}
diff --git a/src/test/ui/fmt/format-string-error-2.stderr b/src/test/ui/fmt/format-string-error-2.stderr
new file mode 100644
index 0000000..66d35a1
--- /dev/null
+++ b/src/test/ui/fmt/format-string-error-2.stderr
@@ -0,0 +1,185 @@
+error: incorrect unicode escape sequence
+  --> $DIR/format-string-error-2.rs:77:20
+   |
+LL |     println!("\x7B}\u8 {", 1);
+   |                    ^^-
+   |                    |
+   |                    help: format of unicode escape sequences uses braces: `\u{8}`
+
+error: invalid format string: expected `'}'`, found `'a'`
+  --> $DIR/format-string-error-2.rs:5:5
+   |
+LL |     format!("{
+   |              - because of this opening brace
+LL |     a");
+   |     ^ expected `}` in format string
+   |
+   = note: if you intended to print `{`, you can escape it using `{{`
+
+error: invalid format string: expected `'}'`, found `'b'`
+  --> $DIR/format-string-error-2.rs:9:5
+   |
+LL |     format!("{ \
+   |              - because of this opening brace
+LL | 
+LL |     b");
+   |     ^ expected `}` in format string
+   |
+   = note: if you intended to print `{`, you can escape it using `{{`
+
+error: invalid format string: expected `'}'`, found `'\'`
+  --> $DIR/format-string-error-2.rs:11:18
+   |
+LL |     format!(r#"{ \
+   |                - ^ expected `}` in format string
+   |                |
+   |                because of this opening brace
+   |
+   = note: if you intended to print `{`, you can escape it using `{{`
+
+error: invalid format string: expected `'}'`, found `'\'`
+  --> $DIR/format-string-error-2.rs:15:18
+   |
+LL |     format!(r#"{ \n
+   |                - ^ expected `}` in format string
+   |                |
+   |                because of this opening brace
+   |
+   = note: if you intended to print `{`, you can escape it using `{{`
+
+error: invalid format string: expected `'}'`, found `'e'`
+  --> $DIR/format-string-error-2.rs:21:5
+   |
+LL |     format!("{ \n
+   |              - because of this opening brace
+LL | \n
+LL |     e");
+   |     ^ expected `}` in format string
+   |
+   = note: if you intended to print `{`, you can escape it using `{{`
+
+error: invalid format string: expected `'}'`, found `'a'`
+  --> $DIR/format-string-error-2.rs:25:5
+   |
+LL |     {
+   |     - because of this opening brace
+LL |     a");
+   |     ^ expected `}` in format string
+   |
+   = note: if you intended to print `{`, you can escape it using `{{`
+
+error: invalid format string: expected `'}'`, found `'a'`
+  --> $DIR/format-string-error-2.rs:29:5
+   |
+LL |     {
+   |     - because of this opening brace
+LL |     a
+   |     ^ expected `}` in format string
+   |
+   = note: if you intended to print `{`, you can escape it using `{{`
+
+error: invalid format string: expected `'}'`, found `'b'`
+  --> $DIR/format-string-error-2.rs:35:5
+   |
+LL |     { \
+   |     - because of this opening brace
+LL |         \
+LL |     b");
+   |     ^ expected `}` in format string
+   |
+   = note: if you intended to print `{`, you can escape it using `{{`
+
+error: invalid format string: expected `'}'`, found `'b'`
+  --> $DIR/format-string-error-2.rs:40:5
+   |
+LL |     { \
+   |     - because of this opening brace
+LL |         \
+LL |     b \
+   |     ^ expected `}` in format string
+   |
+   = note: if you intended to print `{`, you can escape it using `{{`
+
+error: invalid format string: expected `'}'`, found `'\'`
+  --> $DIR/format-string-error-2.rs:45:8
+   |
+LL | raw  { \
+   |      - ^ expected `}` in format string
+   |      |
+   |      because of this opening brace
+   |
+   = note: if you intended to print `{`, you can escape it using `{{`
+
+error: invalid format string: expected `'}'`, found `'\'`
+  --> $DIR/format-string-error-2.rs:50:8
+   |
+LL | raw  { \n
+   |      - ^ expected `}` in format string
+   |      |
+   |      because of this opening brace
+   |
+   = note: if you intended to print `{`, you can escape it using `{{`
+
+error: invalid format string: expected `'}'`, found `'e'`
+  --> $DIR/format-string-error-2.rs:57:5
+   |
+LL |   { \n
+   |   - because of this opening brace
+LL | \n
+LL |     e");
+   |     ^ expected `}` in format string
+   |
+   = note: if you intended to print `{`, you can escape it using `{{`
+
+error: invalid format string: expected `'}'`, found `'a'`
+  --> $DIR/format-string-error-2.rs:67:5
+   |
+LL |     {
+   |     - because of this opening brace
+LL |     asdf}
+   |     ^ expected `}` in format string
+   |
+   = note: if you intended to print `{`, you can escape it using `{{`
+
+error: 1 positional argument in format string, but no arguments were given
+  --> $DIR/format-string-error-2.rs:70:17
+   |
+LL |     println!("\t{}");
+   |                 ^^
+
+error: invalid format string: expected `'}'` but string was terminated
+  --> $DIR/format-string-error-2.rs:74:27
+   |
+LL |     println!("\x7B}\u{8} {", 1);
+   |                          -^ expected `'}'` in format string
+   |                          |
+   |                          because of this opening brace
+   |
+   = note: if you intended to print `{`, you can escape it using `{{`
+
+error: argument never used
+  --> $DIR/format-string-error-2.rs:77:28
+   |
+LL |     println!("\x7B}\u8 {", 1);
+   |              ------------  ^ argument never used
+   |              |
+   |              formatting specifier missing
+
+error: invalid format string: unmatched `}` found
+  --> $DIR/format-string-error-2.rs:82:21
+   |
+LL |     println!(r#"\x7B}\u{8} {"#, 1);
+   |                     ^ unmatched `}` in format string
+   |
+   = note: if you intended to print `}`, you can escape it using `}}`
+
+error: invalid format string: unmatched `}` found
+  --> $DIR/format-string-error-2.rs:85:21
+   |
+LL |     println!(r#"\x7B}\u8 {"#, 1);
+   |                     ^ unmatched `}` in format string
+   |
+   = note: if you intended to print `}`, you can escape it using `}}`
+
+error: aborting due to 19 previous errors
+
diff --git a/src/test/ui/fmt/format-string-error.rs b/src/test/ui/fmt/format-string-error.rs
new file mode 100644
index 0000000..cca949a
--- /dev/null
+++ b/src/test/ui/fmt/format-string-error.rs
@@ -0,0 +1,51 @@
+// ignore-tidy-tab
+
+fn main() {
+    println!("{");
+    //~^ ERROR invalid format string: expected `'}'` but string was terminated
+    println!("{{}}");
+    println!("}");
+    //~^ ERROR invalid format string: unmatched `}` found
+    let _ = format!("{_foo}", _foo = 6usize);
+    //~^ ERROR invalid format string: invalid argument name `_foo`
+    let _ = format!("{_}", _ = 6usize);
+    //~^ ERROR invalid format string: invalid argument name `_`
+    let _ = format!("{");
+    //~^ ERROR invalid format string: expected `'}'` but string was terminated
+    let _ = format!("}");
+    //~^ ERROR invalid format string: unmatched `}` found
+    let _ = format!("{\\}");
+    //~^ ERROR invalid format string: expected `'}'`, found `'\\'`
+    let _ = format!("\n\n\n{\n\n\n");
+    //~^ ERROR invalid format string
+    let _ = format!(r###"
+
+
+
+	{"###);
+    //~^ ERROR invalid format string
+    let _ = format!(r###"
+
+
+
+	{
+
+"###);
+    //~^ ERROR invalid format string
+    let _ = format!(r###"
+
+
+
+	}
+
+"###);
+    //~^^^ ERROR invalid format string
+    let _ = format!(r###"
+
+
+
+        }
+
+"###);
+    //~^^^ ERROR invalid format string: unmatched `}` found
+}
diff --git a/src/test/ui/fmt/format-string-error.stderr b/src/test/ui/fmt/format-string-error.stderr
new file mode 100644
index 0000000..3dc122a
--- /dev/null
+++ b/src/test/ui/fmt/format-string-error.stderr
@@ -0,0 +1,111 @@
+error: invalid format string: expected `'}'` but string was terminated
+  --> $DIR/format-string-error.rs:4:16
+   |
+LL |     println!("{");
+   |               -^ expected `'}'` in format string
+   |               |
+   |               because of this opening brace
+   |
+   = note: if you intended to print `{`, you can escape it using `{{`
+
+error: invalid format string: unmatched `}` found
+  --> $DIR/format-string-error.rs:7:15
+   |
+LL |     println!("}");
+   |               ^ unmatched `}` in format string
+   |
+   = note: if you intended to print `}`, you can escape it using `}}`
+
+error: invalid format string: invalid argument name `_foo`
+  --> $DIR/format-string-error.rs:9:23
+   |
+LL |     let _ = format!("{_foo}", _foo = 6usize);
+   |                       ^^^^ invalid argument name in format string
+   |
+   = note: argument names cannot start with an underscore
+
+error: invalid format string: invalid argument name `_`
+  --> $DIR/format-string-error.rs:11:23
+   |
+LL |     let _ = format!("{_}", _ = 6usize);
+   |                       ^ invalid argument name in format string
+   |
+   = note: argument names cannot start with an underscore
+
+error: invalid format string: expected `'}'` but string was terminated
+  --> $DIR/format-string-error.rs:13:23
+   |
+LL |     let _ = format!("{");
+   |                      -^ expected `'}'` in format string
+   |                      |
+   |                      because of this opening brace
+   |
+   = note: if you intended to print `{`, you can escape it using `{{`
+
+error: invalid format string: unmatched `}` found
+  --> $DIR/format-string-error.rs:15:22
+   |
+LL |     let _ = format!("}");
+   |                      ^ unmatched `}` in format string
+   |
+   = note: if you intended to print `}`, you can escape it using `}}`
+
+error: invalid format string: expected `'}'`, found `'\'`
+  --> $DIR/format-string-error.rs:17:23
+   |
+LL |     let _ = format!("{\}");
+   |                      -^ expected `}` in format string
+   |                      |
+   |                      because of this opening brace
+   |
+   = note: if you intended to print `{`, you can escape it using `{{`
+
+error: invalid format string: expected `'}'` but string was terminated
+  --> $DIR/format-string-error.rs:19:35
+   |
+LL |     let _ = format!("\n\n\n{\n\n\n");
+   |                            -      ^ expected `'}'` in format string
+   |                            |
+   |                            because of this opening brace
+   |
+   = note: if you intended to print `{`, you can escape it using `{{`
+
+error: invalid format string: expected `'}'` but string was terminated
+  --> $DIR/format-string-error.rs:25:3
+   |
+LL |     {"###);
+   |     -^ expected `'}'` in format string
+   |     |
+   |     because of this opening brace
+   |
+   = note: if you intended to print `{`, you can escape it using `{{`
+
+error: invalid format string: expected `'}'` but string was terminated
+  --> $DIR/format-string-error.rs:33:1
+   |
+LL |     {
+   |     - because of this opening brace
+LL | 
+LL | "###);
+   | ^ expected `'}'` in format string
+   |
+   = note: if you intended to print `{`, you can escape it using `{{`
+
+error: invalid format string: unmatched `}` found
+  --> $DIR/format-string-error.rs:39:2
+   |
+LL |     }
+   |     ^ unmatched `}` in format string
+   |
+   = note: if you intended to print `}`, you can escape it using `}}`
+
+error: invalid format string: unmatched `}` found
+  --> $DIR/format-string-error.rs:47:9
+   |
+LL |         }
+   |         ^ unmatched `}` in format string
+   |
+   = note: if you intended to print `}`, you can escape it using `}}`
+
+error: aborting due to 12 previous errors
+
diff --git a/src/test/ui/fmt/send-sync.rs b/src/test/ui/fmt/send-sync.rs
new file mode 100644
index 0000000..95ec68d
--- /dev/null
+++ b/src/test/ui/fmt/send-sync.rs
@@ -0,0 +1,10 @@
+fn send<T: Send>(_: T) {}
+fn sync<T: Sync>(_: T) {}
+
+fn main() {
+    // `Cell` is not `Sync`, so `&Cell` is neither `Sync` nor `Send`,
+    // `std::fmt::Arguments` used to forget this...
+    let c = std::cell::Cell::new(42);
+    send(format_args!("{:?}", c)); //~ ERROR E0277
+    sync(format_args!("{:?}", c)); //~ ERROR E0277
+}
diff --git a/src/test/ui/fmt/send-sync.stderr b/src/test/ui/fmt/send-sync.stderr
new file mode 100644
index 0000000..1f698c9
--- /dev/null
+++ b/src/test/ui/fmt/send-sync.stderr
@@ -0,0 +1,43 @@
+error[E0277]: `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely
+  --> $DIR/send-sync.rs:8:5
+   |
+LL |     send(format_args!("{:?}", c));
+   |     ^^^^ `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely
+   |
+   = help: within `[std::fmt::ArgumentV1<'_>]`, the trait `std::marker::Sync` is not implemented for `*mut (dyn std::ops::Fn() + 'static)`
+   = note: required because it appears within the type `std::marker::PhantomData<*mut (dyn std::ops::Fn() + 'static)>`
+   = note: required because it appears within the type `core::fmt::Void`
+   = note: required because it appears within the type `&core::fmt::Void`
+   = note: required because it appears within the type `std::fmt::ArgumentV1<'_>`
+   = note: required because it appears within the type `[std::fmt::ArgumentV1<'_>]`
+   = note: required because of the requirements on the impl of `std::marker::Send` for `&[std::fmt::ArgumentV1<'_>]`
+   = note: required because it appears within the type `std::fmt::Arguments<'_>`
+note: required by `send`
+  --> $DIR/send-sync.rs:1:1
+   |
+LL | fn send<T: Send>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely
+  --> $DIR/send-sync.rs:9:5
+   |
+LL |     sync(format_args!("{:?}", c));
+   |     ^^^^ `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely
+   |
+   = help: within `std::fmt::Arguments<'_>`, the trait `std::marker::Sync` is not implemented for `*mut (dyn std::ops::Fn() + 'static)`
+   = note: required because it appears within the type `std::marker::PhantomData<*mut (dyn std::ops::Fn() + 'static)>`
+   = note: required because it appears within the type `core::fmt::Void`
+   = note: required because it appears within the type `&core::fmt::Void`
+   = note: required because it appears within the type `std::fmt::ArgumentV1<'_>`
+   = note: required because it appears within the type `[std::fmt::ArgumentV1<'_>]`
+   = note: required because it appears within the type `&[std::fmt::ArgumentV1<'_>]`
+   = note: required because it appears within the type `std::fmt::Arguments<'_>`
+note: required by `sync`
+  --> $DIR/send-sync.rs:2:1
+   |
+LL | fn sync<T: Sync>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/fn-in-pat.rs b/src/test/ui/fn-in-pat.rs
new file mode 100644
index 0000000..ed76b2c
--- /dev/null
+++ b/src/test/ui/fn-in-pat.rs
@@ -0,0 +1,16 @@
+struct A {}
+
+impl A {
+    fn new() {}
+}
+
+fn hof<F>(_: F) where F: FnMut(()) {}
+
+fn ice() {
+    hof(|c| match c {
+        A::new() => (), //~ ERROR expected tuple struct/variant, found method
+        _ => ()
+    })
+}
+
+fn main() {}
diff --git a/src/test/ui/fn-in-pat.stderr b/src/test/ui/fn-in-pat.stderr
new file mode 100644
index 0000000..eee97fe
--- /dev/null
+++ b/src/test/ui/fn-in-pat.stderr
@@ -0,0 +1,9 @@
+error[E0164]: expected tuple struct/variant, found method `<A>::new`
+  --> $DIR/fn-in-pat.rs:11:9
+   |
+LL |         A::new() => (),
+   |         ^^^^^^^^ not a tuple variant or struct
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0164`.
diff --git a/src/test/ui/fn/fn-bad-block-type.rs b/src/test/ui/fn/fn-bad-block-type.rs
new file mode 100644
index 0000000..01dcff0
--- /dev/null
+++ b/src/test/ui/fn/fn-bad-block-type.rs
@@ -0,0 +1,5 @@
+// error-pattern:mismatched types
+
+fn f() -> isize { true }
+
+fn main() { }
diff --git a/src/test/ui/fn/fn-bad-block-type.stderr b/src/test/ui/fn/fn-bad-block-type.stderr
new file mode 100644
index 0000000..5abee94
--- /dev/null
+++ b/src/test/ui/fn/fn-bad-block-type.stderr
@@ -0,0 +1,11 @@
+error[E0308]: mismatched types
+  --> $DIR/fn-bad-block-type.rs:3:19
+   |
+LL | fn f() -> isize { true }
+   |           -----   ^^^^ expected isize, found bool
+   |           |
+   |           expected `isize` because of return type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/fn/fn-closure-mutable-capture.nll.stderr b/src/test/ui/fn/fn-closure-mutable-capture.nll.stderr
new file mode 100644
index 0000000..f7ab56d
--- /dev/null
+++ b/src/test/ui/fn/fn-closure-mutable-capture.nll.stderr
@@ -0,0 +1,15 @@
+error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure
+  --> $DIR/fn-closure-mutable-capture.rs:5:17
+   |
+LL |     bar(move || x = 1);
+   |                 ^^^^^ cannot assign
+   |
+help: consider changing this to accept closures that implement `FnMut`
+  --> $DIR/fn-closure-mutable-capture.rs:5:9
+   |
+LL |     bar(move || x = 1);
+   |         ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/fn/fn-closure-mutable-capture.rs b/src/test/ui/fn/fn-closure-mutable-capture.rs
new file mode 100644
index 0000000..a37ecef
--- /dev/null
+++ b/src/test/ui/fn/fn-closure-mutable-capture.rs
@@ -0,0 +1,10 @@
+pub fn bar<F: Fn()>(_f: F) {}
+
+pub fn foo() {
+    let mut x = 0;
+    bar(move || x = 1);
+    //~^ ERROR cannot assign to captured outer variable in an `Fn` closure
+    //~| NOTE `Fn` closures cannot capture their enclosing environment for modifications
+}
+
+fn main() {}
diff --git a/src/test/ui/fn/fn-closure-mutable-capture.stderr b/src/test/ui/fn/fn-closure-mutable-capture.stderr
new file mode 100644
index 0000000..84a5989
--- /dev/null
+++ b/src/test/ui/fn/fn-closure-mutable-capture.stderr
@@ -0,0 +1,16 @@
+error[E0594]: cannot assign to captured outer variable in an `Fn` closure
+  --> $DIR/fn-closure-mutable-capture.rs:5:17
+   |
+LL |     bar(move || x = 1);
+   |                 ^^^^^
+   |
+   = note: `Fn` closures cannot capture their enclosing environment for modifications
+help: consider changing this closure to take self by mutable reference
+  --> $DIR/fn-closure-mutable-capture.rs:5:9
+   |
+LL |     bar(move || x = 1);
+   |         ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/fn/fn-compare-mismatch.rs b/src/test/ui/fn/fn-compare-mismatch.rs
new file mode 100644
index 0000000..d734d54
--- /dev/null
+++ b/src/test/ui/fn/fn-compare-mismatch.rs
@@ -0,0 +1,7 @@
+fn main() {
+    fn f() { }
+    fn g() { }
+    let x = f == g;
+    //~^ ERROR binary operation `==` cannot be applied
+    //~| ERROR mismatched types
+}
diff --git a/src/test/ui/fn/fn-compare-mismatch.stderr b/src/test/ui/fn/fn-compare-mismatch.stderr
new file mode 100644
index 0000000..07b93d9
--- /dev/null
+++ b/src/test/ui/fn/fn-compare-mismatch.stderr
@@ -0,0 +1,23 @@
+error[E0369]: binary operation `==` cannot be applied to type `fn() {main::f}`
+  --> $DIR/fn-compare-mismatch.rs:4:15
+   |
+LL |     let x = f == g;
+   |             - ^^ - fn() {main::g}
+   |             |
+   |             fn() {main::f}
+   |
+   = note: an implementation of `std::cmp::PartialEq` might be missing for `fn() {main::f}`
+
+error[E0308]: mismatched types
+  --> $DIR/fn-compare-mismatch.rs:4:18
+   |
+LL |     let x = f == g;
+   |                  ^ expected fn item, found a different fn item
+   |
+   = note: expected type `fn() {main::f}`
+              found type `fn() {main::g}`
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0308, E0369.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/fn/fn-item-type.rs b/src/test/ui/fn/fn-item-type.rs
new file mode 100644
index 0000000..e71172d7
--- /dev/null
+++ b/src/test/ui/fn/fn-item-type.rs
@@ -0,0 +1,33 @@
+// Test that the types of distinct fn items are not compatible by
+// default. See also `run-pass/fn-item-type-*.rs`.
+
+fn foo<T>(x: isize) -> isize { x * 2 }
+fn bar<T>(x: isize) -> isize { x * 4 }
+
+fn eq<T>(x: T, y: T) { }
+
+trait Foo { fn foo() { /* this is a default fn */ } }
+impl<T> Foo for T { /* `foo` is still default here */ }
+
+fn main() {
+    eq(foo::<u8>, bar::<u8>);
+    //~^ ERROR mismatched types
+    //~|  expected type `fn(isize) -> isize {foo::<u8>}`
+    //~|  found type `fn(isize) -> isize {bar::<u8>}`
+    //~|  expected fn item, found a different fn item
+
+    eq(foo::<u8>, foo::<i8>);
+    //~^ ERROR mismatched types
+    //~| expected u8, found i8
+
+    eq(bar::<String>, bar::<Vec<u8>>);
+    //~^ ERROR mismatched types
+    //~|  expected type `fn(isize) -> isize {bar::<std::string::String>}`
+    //~|  found type `fn(isize) -> isize {bar::<std::vec::Vec<u8>>}`
+    //~|  expected struct `std::string::String`, found struct `std::vec::Vec`
+
+    // Make sure we distinguish between trait methods correctly.
+    eq(<u8 as Foo>::foo, <u16 as Foo>::foo);
+    //~^ ERROR mismatched types
+    //~| expected u8, found u16
+}
diff --git a/src/test/ui/fn/fn-item-type.stderr b/src/test/ui/fn/fn-item-type.stderr
new file mode 100644
index 0000000..d52646c
--- /dev/null
+++ b/src/test/ui/fn/fn-item-type.stderr
@@ -0,0 +1,39 @@
+error[E0308]: mismatched types
+  --> $DIR/fn-item-type.rs:13:19
+   |
+LL |     eq(foo::<u8>, bar::<u8>);
+   |                   ^^^^^^^^^ expected fn item, found a different fn item
+   |
+   = note: expected type `fn(isize) -> isize {foo::<u8>}`
+              found type `fn(isize) -> isize {bar::<u8>}`
+
+error[E0308]: mismatched types
+  --> $DIR/fn-item-type.rs:19:19
+   |
+LL |     eq(foo::<u8>, foo::<i8>);
+   |                   ^^^^^^^^^ expected u8, found i8
+   |
+   = note: expected type `fn(isize) -> isize {foo::<u8>}`
+              found type `fn(isize) -> isize {foo::<i8>}`
+
+error[E0308]: mismatched types
+  --> $DIR/fn-item-type.rs:23:23
+   |
+LL |     eq(bar::<String>, bar::<Vec<u8>>);
+   |                       ^^^^^^^^^^^^^^ expected struct `std::string::String`, found struct `std::vec::Vec`
+   |
+   = note: expected type `fn(isize) -> isize {bar::<std::string::String>}`
+              found type `fn(isize) -> isize {bar::<std::vec::Vec<u8>>}`
+
+error[E0308]: mismatched types
+  --> $DIR/fn-item-type.rs:30:26
+   |
+LL |     eq(<u8 as Foo>::foo, <u16 as Foo>::foo);
+   |                          ^^^^^^^^^^^^^^^^^ expected u8, found u16
+   |
+   = note: expected type `fn() {<u8 as Foo>::foo}`
+              found type `fn() {<u16 as Foo>::foo}`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/fn/fn-trait-formatting.rs b/src/test/ui/fn/fn-trait-formatting.rs
new file mode 100644
index 0000000..21da39d
--- /dev/null
+++ b/src/test/ui/fn/fn-trait-formatting.rs
@@ -0,0 +1,21 @@
+#![feature(box_syntax)]
+
+fn needs_fn<F>(x: F) where F: Fn(isize) -> isize {}
+
+fn main() {
+    let _: () = (box |_: isize| {}) as Box<FnOnce(isize)>;
+    //~^ ERROR mismatched types
+    //~| expected type `()`
+    //~| found type `std::boxed::Box<dyn std::ops::FnOnce(isize)>`
+    let _: () = (box |_: isize, isize| {}) as Box<Fn(isize, isize)>;
+    //~^ ERROR mismatched types
+    //~| expected type `()`
+    //~| found type `std::boxed::Box<dyn std::ops::Fn(isize, isize)>`
+    let _: () = (box || -> isize { unimplemented!() }) as Box<FnMut() -> isize>;
+    //~^ ERROR mismatched types
+    //~| expected type `()`
+    //~| found type `std::boxed::Box<dyn std::ops::FnMut() -> isize>`
+
+    needs_fn(1);
+    //~^ ERROR expected a `std::ops::Fn<(isize,)>` closure, found `{integer}`
+}
diff --git a/src/test/ui/fn/fn-trait-formatting.stderr b/src/test/ui/fn/fn-trait-formatting.stderr
new file mode 100644
index 0000000..bbccb57
--- /dev/null
+++ b/src/test/ui/fn/fn-trait-formatting.stderr
@@ -0,0 +1,44 @@
+error[E0308]: mismatched types
+  --> $DIR/fn-trait-formatting.rs:6:17
+   |
+LL |     let _: () = (box |_: isize| {}) as Box<FnOnce(isize)>;
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found struct `std::boxed::Box`
+   |
+   = note: expected type `()`
+              found type `std::boxed::Box<dyn std::ops::FnOnce(isize)>`
+
+error[E0308]: mismatched types
+  --> $DIR/fn-trait-formatting.rs:10:17
+   |
+LL |     let _: () = (box |_: isize, isize| {}) as Box<Fn(isize, isize)>;
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found struct `std::boxed::Box`
+   |
+   = note: expected type `()`
+              found type `std::boxed::Box<dyn std::ops::Fn(isize, isize)>`
+
+error[E0308]: mismatched types
+  --> $DIR/fn-trait-formatting.rs:14:17
+   |
+LL |     let _: () = (box || -> isize { unimplemented!() }) as Box<FnMut() -> isize>;
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found struct `std::boxed::Box`
+   |
+   = note: expected type `()`
+              found type `std::boxed::Box<dyn std::ops::FnMut() -> isize>`
+
+error[E0277]: expected a `std::ops::Fn<(isize,)>` closure, found `{integer}`
+  --> $DIR/fn-trait-formatting.rs:19:5
+   |
+LL |     needs_fn(1);
+   |     ^^^^^^^^ expected an `Fn<(isize,)>` closure, found `{integer}`
+   |
+   = help: the trait `std::ops::Fn<(isize,)>` is not implemented for `{integer}`
+note: required by `needs_fn`
+  --> $DIR/fn-trait-formatting.rs:3:1
+   |
+LL | fn needs_fn<F>(x: F) where F: Fn(isize) -> isize {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0277, E0308.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/fn_must_use.rs b/src/test/ui/fn_must_use.rs
new file mode 100644
index 0000000..8519cf7
--- /dev/null
+++ b/src/test/ui/fn_must_use.rs
@@ -0,0 +1,76 @@
+// compile-pass
+
+#![warn(unused_must_use)]
+
+#[derive(PartialEq, Eq)]
+struct MyStruct {
+    n: usize,
+}
+
+impl MyStruct {
+    #[must_use]
+    fn need_to_use_this_method_value(&self) -> usize {
+        self.n
+    }
+
+    #[must_use]
+    fn need_to_use_this_associated_function_value() -> isize {
+        -1
+    }
+}
+
+trait EvenNature {
+    #[must_use = "no side effects"]
+    fn is_even(&self) -> bool;
+}
+
+impl EvenNature for MyStruct {
+    fn is_even(&self) -> bool {
+        self.n % 2 == 0
+    }
+}
+
+trait Replaceable {
+    fn replace(&mut self, substitute: usize) -> usize;
+}
+
+impl Replaceable for MyStruct {
+    // ↓ N.b.: `#[must_use]` attribute on a particular trait implementation
+    // method won't work; the attribute should be on the method signature in
+    // the trait's definition.
+    #[must_use]
+    fn replace(&mut self, substitute: usize) -> usize {
+        let previously = self.n;
+        self.n = substitute;
+        previously
+    }
+}
+
+#[must_use = "it's important"]
+fn need_to_use_this_value() -> bool {
+    false
+}
+
+fn main() {
+    need_to_use_this_value(); //~ WARN unused return value
+
+    let mut m = MyStruct { n: 2 };
+    let n = MyStruct { n: 3 };
+
+    m.need_to_use_this_method_value(); //~ WARN unused return value
+    m.is_even(); // trait method!
+    //~^ WARN unused return value
+
+    MyStruct::need_to_use_this_associated_function_value();
+    //~^ WARN unused return value
+
+    m.replace(3); // won't warn (annotation needs to be in trait definition)
+
+    // comparison methods are `must_use`
+    2.eq(&3); //~ WARN unused return value
+    m.eq(&n); //~ WARN unused return value
+
+    // lint includes comparison operators
+    2 == 3; //~ WARN unused comparison
+    m == n; //~ WARN unused comparison
+}
diff --git a/src/test/ui/fn_must_use.stderr b/src/test/ui/fn_must_use.stderr
new file mode 100644
index 0000000..5a1a4e3
--- /dev/null
+++ b/src/test/ui/fn_must_use.stderr
@@ -0,0 +1,57 @@
+warning: unused return value of `need_to_use_this_value` that must be used
+  --> $DIR/fn_must_use.rs:55:5
+   |
+LL |     need_to_use_this_value();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/fn_must_use.rs:3:9
+   |
+LL | #![warn(unused_must_use)]
+   |         ^^^^^^^^^^^^^^^
+   = note: it's important
+
+warning: unused return value of `MyStruct::need_to_use_this_method_value` that must be used
+  --> $DIR/fn_must_use.rs:60:5
+   |
+LL |     m.need_to_use_this_method_value();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused return value of `EvenNature::is_even` that must be used
+  --> $DIR/fn_must_use.rs:61:5
+   |
+LL |     m.is_even(); // trait method!
+   |     ^^^^^^^^^^^^
+   |
+   = note: no side effects
+
+warning: unused return value of `MyStruct::need_to_use_this_associated_function_value` that must be used
+  --> $DIR/fn_must_use.rs:64:5
+   |
+LL |     MyStruct::need_to_use_this_associated_function_value();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused return value of `std::cmp::PartialEq::eq` that must be used
+  --> $DIR/fn_must_use.rs:70:5
+   |
+LL |     2.eq(&3);
+   |     ^^^^^^^^^
+
+warning: unused return value of `std::cmp::PartialEq::eq` that must be used
+  --> $DIR/fn_must_use.rs:71:5
+   |
+LL |     m.eq(&n);
+   |     ^^^^^^^^^
+
+warning: unused comparison that must be used
+  --> $DIR/fn_must_use.rs:74:5
+   |
+LL |     2 == 3;
+   |     ^^^^^^
+
+warning: unused comparison that must be used
+  --> $DIR/fn_must_use.rs:75:5
+   |
+LL |     m == n;
+   |     ^^^^^^
+
diff --git a/src/test/ui/for/for-c-in-str.rs b/src/test/ui/for/for-c-in-str.rs
new file mode 100644
index 0000000..43b1a04
--- /dev/null
+++ b/src/test/ui/for/for-c-in-str.rs
@@ -0,0 +1,11 @@
+// E0277 should point exclusively at line 14, not the entire for loop span
+
+fn main() {
+    for c in "asdf" {
+    //~^ ERROR `&str` is not an iterator
+    //~| NOTE `&str` is not an iterator
+    //~| HELP the trait `std::iter::Iterator` is not implemented for `&str`
+    //~| NOTE required by `std::iter::IntoIterator::into_iter`
+        println!("");
+    }
+}
diff --git a/src/test/ui/for/for-c-in-str.stderr b/src/test/ui/for/for-c-in-str.stderr
new file mode 100644
index 0000000..9185399
--- /dev/null
+++ b/src/test/ui/for/for-c-in-str.stderr
@@ -0,0 +1,12 @@
+error[E0277]: `&str` is not an iterator
+  --> $DIR/for-c-in-str.rs:4:14
+   |
+LL |     for c in "asdf" {
+   |              ^^^^^^ `&str` is not an iterator; try calling `.chars()` or `.bytes()`
+   |
+   = help: the trait `std::iter::Iterator` is not implemented for `&str`
+   = note: required by `std::iter::IntoIterator::into_iter`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/for/for-expn.rs b/src/test/ui/for/for-expn.rs
new file mode 100644
index 0000000..b9c4bbe
--- /dev/null
+++ b/src/test/ui/for/for-expn.rs
@@ -0,0 +1,9 @@
+// Test that an error on a sub-expresson in a for loop has the correct span.
+
+fn main() {
+    // Odd formatting to make sure we get the right span.
+    for t in &
+      foo //~ ERROR cannot find value `foo` in this scope
+    {
+    }
+}
diff --git a/src/test/ui/for/for-expn.stderr b/src/test/ui/for/for-expn.stderr
new file mode 100644
index 0000000..cdb2115
--- /dev/null
+++ b/src/test/ui/for/for-expn.stderr
@@ -0,0 +1,9 @@
+error[E0425]: cannot find value `foo` in this scope
+  --> $DIR/for-expn.rs:6:7
+   |
+LL |       foo
+   |       ^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/for/for-loop-bogosity.rs b/src/test/ui/for/for-loop-bogosity.rs
new file mode 100644
index 0000000..9341dea
--- /dev/null
+++ b/src/test/ui/for/for-loop-bogosity.rs
@@ -0,0 +1,21 @@
+struct MyStruct {
+    x: isize,
+    y: isize,
+}
+
+impl MyStruct {
+    fn next(&mut self) -> Option<isize> {
+        Some(self.x)
+    }
+}
+
+pub fn main() {
+    let mut bogus = MyStruct {
+        x: 1,
+        y: 2,
+    };
+    for x in bogus {
+    //~^ ERROR `MyStruct` is not an iterator
+        drop(x);
+    }
+}
diff --git a/src/test/ui/for/for-loop-bogosity.stderr b/src/test/ui/for/for-loop-bogosity.stderr
new file mode 100644
index 0000000..fe6ac52
--- /dev/null
+++ b/src/test/ui/for/for-loop-bogosity.stderr
@@ -0,0 +1,12 @@
+error[E0277]: `MyStruct` is not an iterator
+  --> $DIR/for-loop-bogosity.rs:17:14
+   |
+LL |     for x in bogus {
+   |              ^^^^^ `MyStruct` is not an iterator
+   |
+   = help: the trait `std::iter::Iterator` is not implemented for `MyStruct`
+   = note: required by `std::iter::IntoIterator::into_iter`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/for/for-loop-refutable-pattern-error-message.rs b/src/test/ui/for/for-loop-refutable-pattern-error-message.rs
new file mode 100644
index 0000000..221951c
--- /dev/null
+++ b/src/test/ui/for/for-loop-refutable-pattern-error-message.rs
@@ -0,0 +1,3 @@
+fn main() {
+    for &1 in [1].iter() {} //~ ERROR refutable pattern in `for` loop binding
+}
diff --git a/src/test/ui/for/for-loop-refutable-pattern-error-message.stderr b/src/test/ui/for/for-loop-refutable-pattern-error-message.stderr
new file mode 100644
index 0000000..da2b0dc
--- /dev/null
+++ b/src/test/ui/for/for-loop-refutable-pattern-error-message.stderr
@@ -0,0 +1,9 @@
+error[E0005]: refutable pattern in `for` loop binding: `&-2147483648i32..=0i32` not covered
+  --> $DIR/for-loop-refutable-pattern-error-message.rs:2:9
+   |
+LL |     for &1 in [1].iter() {}
+   |         ^^ pattern `&-2147483648i32..=0i32` not covered
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0005`.
diff --git a/src/test/ui/for/for-loop-type-error.rs b/src/test/ui/for/for-loop-type-error.rs
new file mode 100644
index 0000000..879fa47
--- /dev/null
+++ b/src/test/ui/for/for-loop-type-error.rs
@@ -0,0 +1,6 @@
+pub fn main() {
+    let x = () + (); //~ ERROR binary operation
+
+    // this shouldn't have a flow-on error:
+    for _ in x {}
+}
diff --git a/src/test/ui/for/for-loop-type-error.stderr b/src/test/ui/for/for-loop-type-error.stderr
new file mode 100644
index 0000000..588e7a0
--- /dev/null
+++ b/src/test/ui/for/for-loop-type-error.stderr
@@ -0,0 +1,13 @@
+error[E0369]: binary operation `+` cannot be applied to type `()`
+  --> $DIR/for-loop-type-error.rs:2:16
+   |
+LL |     let x = () + ();
+   |             -- ^ -- ()
+   |             |
+   |             ()
+   |
+   = note: an implementation of `std::ops::Add` might be missing for `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0369`.
diff --git a/src/test/ui/for/for-loop-unconstrained-element-type.rs b/src/test/ui/for/for-loop-unconstrained-element-type.rs
new file mode 100644
index 0000000..0c7a351
--- /dev/null
+++ b/src/test/ui/for/for-loop-unconstrained-element-type.rs
@@ -0,0 +1,9 @@
+// Test that `for` loops don't introduce artificial
+// constraints on the type of the binding (`i`).
+// Subtle changes in the desugaring can cause the
+// type of elements in the vector to (incorrectly)
+// fallback to `!` or `()`.
+
+fn main() {
+    for i in Vec::new() { } //~ ERROR type annotations needed
+}
diff --git a/src/test/ui/for/for-loop-unconstrained-element-type.stderr b/src/test/ui/for/for-loop-unconstrained-element-type.stderr
new file mode 100644
index 0000000..02fdb80
--- /dev/null
+++ b/src/test/ui/for/for-loop-unconstrained-element-type.stderr
@@ -0,0 +1,12 @@
+error[E0282]: type annotations needed
+  --> $DIR/for-loop-unconstrained-element-type.rs:8:14
+   |
+LL |     for i in Vec::new() { }
+   |              ^^^^^^^^^^
+   |              |
+   |              cannot infer type
+   |              the element type for this iterator is not specified
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/foreign-fn-return-lifetime.fixed b/src/test/ui/foreign-fn-return-lifetime.fixed
new file mode 100644
index 0000000..143d634
--- /dev/null
+++ b/src/test/ui/foreign-fn-return-lifetime.fixed
@@ -0,0 +1,8 @@
+// run-rustfix
+
+extern "C" {
+    pub fn g(_: &u8) -> &u8; // OK
+    pub fn f() -> &'static u8; //~ ERROR missing lifetime specifier
+}
+
+fn main() {}
diff --git a/src/test/ui/foreign-fn-return-lifetime.rs b/src/test/ui/foreign-fn-return-lifetime.rs
new file mode 100644
index 0000000..76fe50a
--- /dev/null
+++ b/src/test/ui/foreign-fn-return-lifetime.rs
@@ -0,0 +1,8 @@
+// run-rustfix
+
+extern "C" {
+    pub fn g(_: &u8) -> &u8; // OK
+    pub fn f() -> &u8; //~ ERROR missing lifetime specifier
+}
+
+fn main() {}
diff --git a/src/test/ui/foreign-fn-return-lifetime.stderr b/src/test/ui/foreign-fn-return-lifetime.stderr
new file mode 100644
index 0000000..575da18
--- /dev/null
+++ b/src/test/ui/foreign-fn-return-lifetime.stderr
@@ -0,0 +1,11 @@
+error[E0106]: missing lifetime specifier
+  --> $DIR/foreign-fn-return-lifetime.rs:5:19
+   |
+LL |     pub fn f() -> &u8;
+   |                   ^ help: consider giving it a 'static lifetime: `&'static`
+   |
+   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0106`.
diff --git a/src/test/ui/foreign-unsafe-fn-called.rs b/src/test/ui/foreign-unsafe-fn-called.rs
new file mode 100644
index 0000000..9352efa
--- /dev/null
+++ b/src/test/ui/foreign-unsafe-fn-called.rs
@@ -0,0 +1,10 @@
+mod test {
+    extern {
+        pub fn free();
+    }
+}
+
+fn main() {
+    test::free();
+    //~^ ERROR call to unsafe function is unsafe
+}
diff --git a/src/test/ui/foreign-unsafe-fn-called.stderr b/src/test/ui/foreign-unsafe-fn-called.stderr
new file mode 100644
index 0000000..afc9632
--- /dev/null
+++ b/src/test/ui/foreign-unsafe-fn-called.stderr
@@ -0,0 +1,11 @@
+error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
+  --> $DIR/foreign-unsafe-fn-called.rs:8:5
+   |
+LL |     test::free();
+   |     ^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/fully-qualified-type/fully-qualified-type-name1.rs b/src/test/ui/fully-qualified-type/fully-qualified-type-name1.rs
new file mode 100644
index 0000000..7e5b884
--- /dev/null
+++ b/src/test/ui/fully-qualified-type/fully-qualified-type-name1.rs
@@ -0,0 +1,10 @@
+// Test that we use fully-qualified type names in error messages.
+
+fn main() {
+    let x: Option<usize>;
+    x = 5;
+    //~^ ERROR mismatched types
+    //~| expected type `std::option::Option<usize>`
+    //~| found type `{integer}`
+    //~| expected enum `std::option::Option`, found integer
+}
diff --git a/src/test/ui/fully-qualified-type/fully-qualified-type-name1.stderr b/src/test/ui/fully-qualified-type/fully-qualified-type-name1.stderr
new file mode 100644
index 0000000..62ded3e
--- /dev/null
+++ b/src/test/ui/fully-qualified-type/fully-qualified-type-name1.stderr
@@ -0,0 +1,15 @@
+error[E0308]: mismatched types
+  --> $DIR/fully-qualified-type-name1.rs:5:9
+   |
+LL |     x = 5;
+   |         ^
+   |         |
+   |         expected enum `std::option::Option`, found integer
+   |         help: try using a variant of the expected type: `Some(5)`
+   |
+   = note: expected type `std::option::Option<usize>`
+              found type `{integer}`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/fully-qualified-type/fully-qualified-type-name2.rs b/src/test/ui/fully-qualified-type/fully-qualified-type-name2.rs
new file mode 100644
index 0000000..21eda1a
--- /dev/null
+++ b/src/test/ui/fully-qualified-type/fully-qualified-type-name2.rs
@@ -0,0 +1,20 @@
+// Test that we use fully-qualified type names in error messages.
+
+mod x {
+    pub enum Foo { }
+}
+
+mod y {
+    pub enum Foo { }
+}
+
+fn bar(x: x::Foo) -> y::Foo {
+    return x;
+    //~^ ERROR mismatched types
+    //~| expected type `y::Foo`
+    //~| found type `x::Foo`
+    //~| expected enum `y::Foo`, found enum `x::Foo`
+}
+
+fn main() {
+}
diff --git a/src/test/ui/fully-qualified-type/fully-qualified-type-name2.stderr b/src/test/ui/fully-qualified-type/fully-qualified-type-name2.stderr
new file mode 100644
index 0000000..47bb5e4
--- /dev/null
+++ b/src/test/ui/fully-qualified-type/fully-qualified-type-name2.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/fully-qualified-type-name2.rs:12:12
+   |
+LL | fn bar(x: x::Foo) -> y::Foo {
+   |                      ------ expected `y::Foo` because of return type
+LL |     return x;
+   |            ^ expected enum `y::Foo`, found enum `x::Foo`
+   |
+   = note: expected type `y::Foo`
+              found type `x::Foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/fully-qualified-type/fully-qualified-type-name3.rs b/src/test/ui/fully-qualified-type/fully-qualified-type-name3.rs
new file mode 100644
index 0000000..22faa66
--- /dev/null
+++ b/src/test/ui/fully-qualified-type/fully-qualified-type-name3.rs
@@ -0,0 +1,14 @@
+// Test that we use fully-qualified type names in error messages.
+
+// ignore-test
+
+type T1 = usize;
+type T2 = isize;
+
+fn bar(x: T1) -> T2 {
+    return x;
+    //~^ ERROR mismatched types: expected `T2`, found `T1`
+}
+
+fn main() {
+}
diff --git a/src/test/ui/fully-qualified-type/fully-qualified-type-name4.rs b/src/test/ui/fully-qualified-type/fully-qualified-type-name4.rs
new file mode 100644
index 0000000..88910a7
--- /dev/null
+++ b/src/test/ui/fully-qualified-type/fully-qualified-type-name4.rs
@@ -0,0 +1,14 @@
+// Test that we use fully-qualified type names in error messages.
+
+use std::option::Option;
+
+fn bar(x: usize) -> Option<usize> {
+    return x;
+    //~^ ERROR mismatched types
+    //~| expected type `std::option::Option<usize>`
+    //~| found type `usize`
+    //~| expected enum `std::option::Option`, found usize
+}
+
+fn main() {
+}
diff --git a/src/test/ui/fully-qualified-type/fully-qualified-type-name4.stderr b/src/test/ui/fully-qualified-type/fully-qualified-type-name4.stderr
new file mode 100644
index 0000000..b341879
--- /dev/null
+++ b/src/test/ui/fully-qualified-type/fully-qualified-type-name4.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/fully-qualified-type-name4.rs:6:12
+   |
+LL | fn bar(x: usize) -> Option<usize> {
+   |                     ------------- expected `std::option::Option<usize>` because of return type
+LL |     return x;
+   |            ^ expected enum `std::option::Option`, found usize
+   |
+   = note: expected type `std::option::Option<usize>`
+              found type `usize`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/functional-struct-update/functional-struct-update-noncopyable.nll.stderr b/src/test/ui/functional-struct-update/functional-struct-update-noncopyable.nll.stderr
new file mode 100644
index 0000000..e7b4575
--- /dev/null
+++ b/src/test/ui/functional-struct-update/functional-struct-update-noncopyable.nll.stderr
@@ -0,0 +1,9 @@
+error[E0509]: cannot move out of type `A`, which implements the `Drop` trait
+  --> $DIR/functional-struct-update-noncopyable.rs:12:14
+   |
+LL |     let _b = A { y: Arc::new(3), ..a };
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0509`.
diff --git a/src/test/ui/functional-struct-update/functional-struct-update-noncopyable.rs b/src/test/ui/functional-struct-update/functional-struct-update-noncopyable.rs
new file mode 100644
index 0000000..a9d7d9c
--- /dev/null
+++ b/src/test/ui/functional-struct-update/functional-struct-update-noncopyable.rs
@@ -0,0 +1,14 @@
+// issue 7327
+
+use std::sync::Arc;
+
+struct A { y: Arc<isize>, x: Arc<isize> }
+
+impl Drop for A {
+    fn drop(&mut self) { println!("x={}", *self.x); }
+}
+fn main() {
+    let a = A { y: Arc::new(1), x: Arc::new(2) };
+    let _b = A { y: Arc::new(3), ..a }; //~ ERROR cannot move out of type `A`
+    let _c = a;
+}
diff --git a/src/test/ui/functional-struct-update/functional-struct-update-noncopyable.stderr b/src/test/ui/functional-struct-update/functional-struct-update-noncopyable.stderr
new file mode 100644
index 0000000..5549adc
--- /dev/null
+++ b/src/test/ui/functional-struct-update/functional-struct-update-noncopyable.stderr
@@ -0,0 +1,9 @@
+error[E0509]: cannot move out of type `A`, which implements the `Drop` trait
+  --> $DIR/functional-struct-update-noncopyable.rs:12:36
+   |
+LL |     let _b = A { y: Arc::new(3), ..a };
+   |                                    ^ cannot move out of here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0509`.
diff --git a/src/test/ui/functional-struct-update/functional-struct-update-respects-privacy.rs b/src/test/ui/functional-struct-update/functional-struct-update-respects-privacy.rs
new file mode 100644
index 0000000..7ae5302
--- /dev/null
+++ b/src/test/ui/functional-struct-update/functional-struct-update-respects-privacy.rs
@@ -0,0 +1,32 @@
+// RFC 736 (and Issue 21407): functional struct update should respect privacy.
+
+// The `foo` module attempts to maintains an invariant that each `S`
+// has a unique `u64` id.
+use self::foo::S;
+mod foo {
+    use std::cell::{UnsafeCell};
+
+    static mut COUNT : UnsafeCell<u64> = UnsafeCell::new(1);
+
+    pub struct S { pub a: u8, pub b: String, secret_uid: u64 }
+
+    pub fn make_secrets(a: u8, b: String) -> S {
+        let val = unsafe { let p = COUNT.get(); let val = *p; *p = val + 1; val };
+        println!("creating {}, uid {}", b, val);
+        S { a: a, b: b, secret_uid: val }
+    }
+
+    impl Drop for S {
+        fn drop(&mut self) {
+            println!("dropping {}, uid {}", self.b, self.secret_uid);
+        }
+    }
+}
+
+fn main() {
+    let s_1 = foo::make_secrets(3, format!("ess one"));
+    let s_2 = foo::S { b: format!("ess two"), ..s_1 }; // FRU ...
+    //~^ ERROR field `secret_uid` of struct `foo::S` is private
+    println!("main forged an S named: {}", s_2.b);
+    // at end of scope, ... both s_1 *and* s_2 get dropped.  Boom!
+}
diff --git a/src/test/ui/functional-struct-update/functional-struct-update-respects-privacy.stderr b/src/test/ui/functional-struct-update/functional-struct-update-respects-privacy.stderr
new file mode 100644
index 0000000..2aeffc3
--- /dev/null
+++ b/src/test/ui/functional-struct-update/functional-struct-update-respects-privacy.stderr
@@ -0,0 +1,9 @@
+error[E0451]: field `secret_uid` of struct `foo::S` is private
+  --> $DIR/functional-struct-update-respects-privacy.rs:28:49
+   |
+LL |     let s_2 = foo::S { b: format!("ess two"), ..s_1 }; // FRU ...
+   |                                                 ^^^ field `secret_uid` is private
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0451`.
diff --git a/src/test/ui/future-incompatible-lint-group.rs b/src/test/ui/future-incompatible-lint-group.rs
new file mode 100644
index 0000000..3630f08
--- /dev/null
+++ b/src/test/ui/future-incompatible-lint-group.rs
@@ -0,0 +1,8 @@
+#![deny(future_incompatible)]
+
+trait Tr {
+    fn f(u8) {} //~ ERROR anonymous parameters are deprecated
+                //~^ WARN this was previously accepted
+}
+
+fn main() {}
diff --git a/src/test/ui/future-incompatible-lint-group.stderr b/src/test/ui/future-incompatible-lint-group.stderr
new file mode 100644
index 0000000..65c37e0
--- /dev/null
+++ b/src/test/ui/future-incompatible-lint-group.stderr
@@ -0,0 +1,17 @@
+error: anonymous parameters are deprecated and will be removed in the next edition.
+  --> $DIR/future-incompatible-lint-group.rs:4:10
+   |
+LL |     fn f(u8) {}
+   |          ^^ help: Try naming the parameter or explicitly ignoring it: `_: u8`
+   |
+note: lint level defined here
+  --> $DIR/future-incompatible-lint-group.rs:1:9
+   |
+LL | #![deny(future_incompatible)]
+   |         ^^^^^^^^^^^^^^^^^^^
+   = note: #[deny(anonymous_parameters)] implied by #[deny(future_incompatible)]
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #41686 <https://github.com/rust-lang/rust/issues/41686>
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/gated-bad-feature.rs b/src/test/ui/gated-bad-feature.rs
new file mode 100644
index 0000000..fb4cc94
--- /dev/null
+++ b/src/test/ui/gated-bad-feature.rs
@@ -0,0 +1,14 @@
+#![feature(
+    foo_bar_baz,
+    foo(bar),
+    foo = "baz"
+)]
+//~^^^ ERROR: malformed feature
+//~^^^ ERROR: malformed feature
+
+#![feature] //~ ERROR: attribute must be of the form
+#![feature = "foo"] //~ ERROR: attribute must be of the form
+
+#![feature(test_removed_feature)] //~ ERROR: feature has been removed
+
+fn main() {}
diff --git a/src/test/ui/gated-bad-feature.stderr b/src/test/ui/gated-bad-feature.stderr
new file mode 100644
index 0000000..b208da3
--- /dev/null
+++ b/src/test/ui/gated-bad-feature.stderr
@@ -0,0 +1,34 @@
+error[E0556]: malformed feature, expected just one word
+  --> $DIR/gated-bad-feature.rs:3:5
+   |
+LL |     foo(bar),
+   |     ^^^^^^^^
+
+error[E0556]: malformed feature, expected just one word
+  --> $DIR/gated-bad-feature.rs:4:5
+   |
+LL |     foo = "baz"
+   |     ^^^^^^^^^^^
+
+error[E0557]: feature has been removed
+  --> $DIR/gated-bad-feature.rs:12:12
+   |
+LL | #![feature(test_removed_feature)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+
+error: attribute must be of the form `#[feature(name1, name1, ...)]`
+  --> $DIR/gated-bad-feature.rs:9:1
+   |
+LL | #![feature]
+   | ^^^^^^^^^^^
+
+error: attribute must be of the form `#[feature(name1, name1, ...)]`
+  --> $DIR/gated-bad-feature.rs:10:1
+   |
+LL | #![feature = "foo"]
+   | ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
+
+Some errors occurred: E0556, E0557.
+For more information about an error, try `rustc --explain E0556`.
diff --git a/src/test/ui/generator-yielding-or-returning-itself.rs b/src/test/ui/generator-yielding-or-returning-itself.rs
new file mode 100644
index 0000000..30788e3
--- /dev/null
+++ b/src/test/ui/generator-yielding-or-returning-itself.rs
@@ -0,0 +1,35 @@
+#![feature(generator_trait)]
+#![feature(generators)]
+
+// Test that we cannot create a generator that returns a value of its
+// own type.
+
+use std::ops::Generator;
+
+pub fn want_cyclic_generator_return<T>(_: T)
+    where T: Generator<Yield = (), Return = T>
+{
+}
+
+fn supply_cyclic_generator_return() {
+    want_cyclic_generator_return(|| {
+        //~^ ERROR type mismatch
+        if false { yield None.unwrap(); }
+        None.unwrap()
+    })
+}
+
+pub fn want_cyclic_generator_yield<T>(_: T)
+    where T: Generator<Yield = T, Return = ()>
+{
+}
+
+fn supply_cyclic_generator_yield() {
+    want_cyclic_generator_yield(|| {
+        //~^ ERROR type mismatch
+        if false { yield None.unwrap(); }
+        None.unwrap()
+    })
+}
+
+fn main() { }
diff --git a/src/test/ui/generator-yielding-or-returning-itself.stderr b/src/test/ui/generator-yielding-or-returning-itself.stderr
new file mode 100644
index 0000000..5834aed
--- /dev/null
+++ b/src/test/ui/generator-yielding-or-returning-itself.stderr
@@ -0,0 +1,39 @@
+error[E0271]: type mismatch resolving `<[generator@$DIR/generator-yielding-or-returning-itself.rs:15:34: 19:6 _] as std::ops::Generator>::Return == [generator@$DIR/generator-yielding-or-returning-itself.rs:15:34: 19:6 _]`
+  --> $DIR/generator-yielding-or-returning-itself.rs:15:5
+   |
+LL |     want_cyclic_generator_return(|| {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size
+   |
+   = note: closures cannot capture themselves or take themselves as argument;
+           this error may be the result of a recent compiler bug-fix,
+           see https://github.com/rust-lang/rust/issues/46062 for more details
+note: required by `want_cyclic_generator_return`
+  --> $DIR/generator-yielding-or-returning-itself.rs:9:1
+   |
+LL | / pub fn want_cyclic_generator_return<T>(_: T)
+LL | |     where T: Generator<Yield = (), Return = T>
+LL | | {
+LL | | }
+   | |_^
+
+error[E0271]: type mismatch resolving `<[generator@$DIR/generator-yielding-or-returning-itself.rs:28:33: 32:6 _] as std::ops::Generator>::Yield == [generator@$DIR/generator-yielding-or-returning-itself.rs:28:33: 32:6 _]`
+  --> $DIR/generator-yielding-or-returning-itself.rs:28:5
+   |
+LL |     want_cyclic_generator_yield(|| {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size
+   |
+   = note: closures cannot capture themselves or take themselves as argument;
+           this error may be the result of a recent compiler bug-fix,
+           see https://github.com/rust-lang/rust/issues/46062 for more details
+note: required by `want_cyclic_generator_yield`
+  --> $DIR/generator-yielding-or-returning-itself.rs:22:1
+   |
+LL | / pub fn want_cyclic_generator_yield<T>(_: T)
+LL | |     where T: Generator<Yield = T, Return = ()>
+LL | | {
+LL | | }
+   | |_^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/generator/auto-trait-regions.rs b/src/test/ui/generator/auto-trait-regions.rs
new file mode 100644
index 0000000..46d7289
--- /dev/null
+++ b/src/test/ui/generator/auto-trait-regions.rs
@@ -0,0 +1,50 @@
+#![feature(generators)]
+#![feature(optin_builtin_traits)]
+
+auto trait Foo {}
+
+struct No;
+
+impl !Foo for No {}
+
+struct A<'a, 'b>(&'a mut bool, &'b mut bool, No);
+
+impl<'a, 'b: 'a> Foo for A<'a, 'b> {}
+
+struct OnlyFooIfStaticRef(No);
+impl Foo for &'static OnlyFooIfStaticRef {}
+
+struct OnlyFooIfRef(No);
+impl<'a> Foo for &'a OnlyFooIfRef {}
+
+fn assert_foo<T: Foo>(f: T) {}
+
+fn main() {
+    // Make sure 'static is erased for generator interiors so we can't match it in trait selection
+    let x: &'static _ = &OnlyFooIfStaticRef(No);
+    let gen = || {
+        let x = x;
+        yield;
+        assert_foo(x);
+    };
+    assert_foo(gen);
+    //~^ ERROR implementation of `Foo` is not general enough
+
+    // Allow impls which matches any lifetime
+    let x = &OnlyFooIfRef(No);
+    let gen = || {
+        let x = x;
+        yield;
+        assert_foo(x);
+    };
+    assert_foo(gen); // ok
+
+    // Disallow impls which relates lifetimes in the generator interior
+    let gen = || {
+        let a = A(&mut true, &mut true, No);
+        yield;
+        assert_foo(a);
+    };
+    assert_foo(gen);
+    //~^ ERROR not general enough
+}
diff --git a/src/test/ui/generator/auto-trait-regions.stderr b/src/test/ui/generator/auto-trait-regions.stderr
new file mode 100644
index 0000000..92f92e2
--- /dev/null
+++ b/src/test/ui/generator/auto-trait-regions.stderr
@@ -0,0 +1,20 @@
+error: implementation of `Foo` is not general enough
+  --> $DIR/auto-trait-regions.rs:30:5
+   |
+LL |     assert_foo(gen);
+   |     ^^^^^^^^^^
+   |
+   = note: `Foo` would have to be implemented for the type `&'0 OnlyFooIfStaticRef`, for any lifetime `'0`
+   = note: but `Foo` is actually implemented for the type `&'1 OnlyFooIfStaticRef`, for some specific lifetime `'1`
+
+error: implementation of `Foo` is not general enough
+  --> $DIR/auto-trait-regions.rs:48:5
+   |
+LL |     assert_foo(gen);
+   |     ^^^^^^^^^^
+   |
+   = note: `Foo` would have to be implemented for the type `A<'0, '1>`, for any two lifetimes `'0` and `'1`
+   = note: but `Foo` is actually implemented for the type `A<'_, '2>`, for some specific lifetime `'2`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/generator/borrowing.nll.stderr b/src/test/ui/generator/borrowing.nll.stderr
new file mode 100644
index 0000000..3d58873
--- /dev/null
+++ b/src/test/ui/generator/borrowing.nll.stderr
@@ -0,0 +1,34 @@
+error[E0597]: `a` does not live long enough
+  --> $DIR/borrowing.rs:9:33
+   |
+LL |         Pin::new(&mut || yield &a).resume()
+   |                       ----------^
+   |                       |         |
+   |                       |         borrowed value does not live long enough
+   |                       value captured here by generator
+   |                       a temporary with access to the borrow is created here ...
+LL |
+LL |     };
+   |     -- ... and the borrow might be used here, when that temporary is dropped and runs the destructor for generator
+   |     |
+   |     `a` dropped here while still borrowed
+   |
+   = note: The temporary is part of an expression at the end of a block. Consider forcing this temporary to be dropped sooner, before the block's local variables are dropped. For example, you could save the expression's value in a new local variable `x` and then make `x` be the expression at the end of the block.
+
+error[E0597]: `a` does not live long enough
+  --> $DIR/borrowing.rs:16:20
+   |
+LL |     let _b = {
+   |         -- borrow later stored here
+LL |         let a = 3;
+LL |         || {
+   |         -- value captured here by generator
+LL |             yield &a
+   |                    ^ borrowed value does not live long enough
+...
+LL |     };
+   |     - `a` dropped here while still borrowed
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/generator/borrowing.rs b/src/test/ui/generator/borrowing.rs
new file mode 100644
index 0000000..9f8fc74
--- /dev/null
+++ b/src/test/ui/generator/borrowing.rs
@@ -0,0 +1,21 @@
+#![feature(generators, generator_trait)]
+
+use std::ops::Generator;
+use std::pin::Pin;
+
+fn main() {
+    let _b = {
+        let a = 3;
+        Pin::new(&mut || yield &a).resume()
+        //~^ ERROR: `a` does not live long enough
+    };
+
+    let _b = {
+        let a = 3;
+        || {
+            yield &a
+            //~^ ERROR: `a` does not live long enough
+        }
+    };
+}
+
diff --git a/src/test/ui/generator/borrowing.stderr b/src/test/ui/generator/borrowing.stderr
new file mode 100644
index 0000000..38502aa
--- /dev/null
+++ b/src/test/ui/generator/borrowing.stderr
@@ -0,0 +1,30 @@
+error[E0597]: `a` does not live long enough
+  --> $DIR/borrowing.rs:9:33
+   |
+LL |         Pin::new(&mut || yield &a).resume()
+   |                       --        ^ borrowed value does not live long enough
+   |                       |
+   |                       capture occurs here
+LL |
+LL |     };
+   |     - borrowed value only lives until here
+...
+LL | }
+   | - borrowed value needs to live until here
+
+error[E0597]: `a` does not live long enough
+  --> $DIR/borrowing.rs:16:20
+   |
+LL |         || {
+   |         -- capture occurs here
+LL |             yield &a
+   |                    ^ borrowed value does not live long enough
+...
+LL |     };
+   |     - borrowed value only lives until here
+LL | }
+   | - borrowed value needs to live until here
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/generator/dropck.nll.stderr b/src/test/ui/generator/dropck.nll.stderr
new file mode 100644
index 0000000..8bb860f
--- /dev/null
+++ b/src/test/ui/generator/dropck.nll.stderr
@@ -0,0 +1,34 @@
+error[E0597]: `*cell` does not live long enough
+  --> $DIR/dropck.rs:10:40
+   |
+LL |     let ref_ = Box::leak(Box::new(Some(cell.borrow_mut())));
+   |                                        ^^^^ borrowed value does not live long enough
+...
+LL | }
+   | -
+   | |
+   | `*cell` dropped here while still borrowed
+   | borrow might be used here, when `gen` is dropped and runs the destructor for generator
+   |
+   = note: values in a scope are dropped in the opposite order they are defined
+
+error[E0597]: `ref_` does not live long enough
+  --> $DIR/dropck.rs:15:18
+   |
+LL |     gen = || {
+   |           -- value captured here by generator
+LL |         // but the generator can use it to drop a `Ref<'a, i32>`.
+LL |         let _d = ref_.take();
+   |                  ^^^^ borrowed value does not live long enough
+...
+LL | }
+   | -
+   | |
+   | `ref_` dropped here while still borrowed
+   | borrow might be used here, when `gen` is dropped and runs the destructor for generator
+   |
+   = note: values in a scope are dropped in the opposite order they are defined
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/generator/dropck.rs b/src/test/ui/generator/dropck.rs
new file mode 100644
index 0000000..65c61fb
--- /dev/null
+++ b/src/test/ui/generator/dropck.rs
@@ -0,0 +1,20 @@
+#![feature(generators, generator_trait, box_leak)]
+
+use std::cell::RefCell;
+use std::ops::Generator;
+use std::pin::Pin;
+
+fn main() {
+    let (mut gen, cell);
+    cell = Box::new(RefCell::new(0));
+    let ref_ = Box::leak(Box::new(Some(cell.borrow_mut())));
+    //~^ ERROR `*cell` does not live long enough [E0597]
+    // the upvar is the non-dropck `&mut Option<Ref<'a, i32>>`.
+    gen = || {
+        // but the generator can use it to drop a `Ref<'a, i32>`.
+        let _d = ref_.take(); //~ ERROR `ref_` does not live long enough
+        yield;
+    };
+    Pin::new(&mut gen).resume();
+    // drops the RefCell and then the Ref, leading to use-after-free
+}
diff --git a/src/test/ui/generator/dropck.stderr b/src/test/ui/generator/dropck.stderr
new file mode 100644
index 0000000..977f388
--- /dev/null
+++ b/src/test/ui/generator/dropck.stderr
@@ -0,0 +1,28 @@
+error[E0597]: `*cell` does not live long enough
+  --> $DIR/dropck.rs:10:40
+   |
+LL |     let ref_ = Box::leak(Box::new(Some(cell.borrow_mut())));
+   |                                        ^^^^ borrowed value does not live long enough
+...
+LL | }
+   | - `*cell` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error[E0597]: `ref_` does not live long enough
+  --> $DIR/dropck.rs:15:18
+   |
+LL |     gen = || {
+   |           -- capture occurs here
+LL |         // but the generator can use it to drop a `Ref<'a, i32>`.
+LL |         let _d = ref_.take();
+   |                  ^^^^ borrowed value does not live long enough
+...
+LL | }
+   | - borrowed value dropped before borrower
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/generator/generator-region-requirements.ast.stderr b/src/test/ui/generator/generator-region-requirements.ast.stderr
new file mode 100644
index 0000000..8a96d18
--- /dev/null
+++ b/src/test/ui/generator/generator-region-requirements.ast.stderr
@@ -0,0 +1,12 @@
+error[E0621]: explicit lifetime required in the type of `x`
+  --> $DIR/generator-region-requirements.rs:16:51
+   |
+LL | fn dangle(x: &mut i32) -> &'static mut i32 {
+   |              -------- help: add explicit lifetime `'static` to the type of `x`: `&'static mut i32`
+...
+LL |             GeneratorState::Complete(c) => return c,
+   |                                                   ^ lifetime `'static` required
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/generator/generator-region-requirements.nll.stderr b/src/test/ui/generator/generator-region-requirements.nll.stderr
new file mode 100644
index 0000000..8a96d18
--- /dev/null
+++ b/src/test/ui/generator/generator-region-requirements.nll.stderr
@@ -0,0 +1,12 @@
+error[E0621]: explicit lifetime required in the type of `x`
+  --> $DIR/generator-region-requirements.rs:16:51
+   |
+LL | fn dangle(x: &mut i32) -> &'static mut i32 {
+   |              -------- help: add explicit lifetime `'static` to the type of `x`: `&'static mut i32`
+...
+LL |             GeneratorState::Complete(c) => return c,
+   |                                                   ^ lifetime `'static` required
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/generator/generator-region-requirements.rs b/src/test/ui/generator/generator-region-requirements.rs
new file mode 100644
index 0000000..9738f6c
--- /dev/null
+++ b/src/test/ui/generator/generator-region-requirements.rs
@@ -0,0 +1,24 @@
+// revisions: ast nll
+// ignore-compare-mode-nll
+
+#![feature(generators, generator_trait)]
+#![cfg_attr(nll, feature(nll))]
+use std::ops::{Generator, GeneratorState};
+use std::pin::Pin;
+
+fn dangle(x: &mut i32) -> &'static mut i32 {
+    let mut g = || {
+        yield;
+        x
+    };
+    loop {
+        match Pin::new(&mut g).resume() {
+            GeneratorState::Complete(c) => return c,
+//[nll]~^ ERROR explicit lifetime required
+//[ast]~^^ ERROR explicit lifetime required
+            GeneratorState::Yielded(_) => (),
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/generator/generator-with-nll.rs b/src/test/ui/generator/generator-with-nll.rs
new file mode 100644
index 0000000..87afa57
--- /dev/null
+++ b/src/test/ui/generator/generator-with-nll.rs
@@ -0,0 +1,13 @@
+#![feature(generators)]
+#![feature(nll)]
+
+fn main() {
+    || {
+        // The reference in `_a` is a Legal with NLL since it ends before the yield
+        let _a = &mut true;
+        let b = &mut true;
+        //~^ borrow may still be in use when generator yields
+        yield ();
+        println!("{}", b);
+    };
+}
diff --git a/src/test/ui/generator/generator-with-nll.stderr b/src/test/ui/generator/generator-with-nll.stderr
new file mode 100644
index 0000000..bd5abb2
--- /dev/null
+++ b/src/test/ui/generator/generator-with-nll.stderr
@@ -0,0 +1,12 @@
+error[E0626]: borrow may still be in use when generator yields
+  --> $DIR/generator-with-nll.rs:8:17
+   |
+LL |         let b = &mut true;
+   |                 ^^^^^^^^^
+LL |
+LL |         yield ();
+   |         -------- possible yield occurs here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0626`.
diff --git a/src/test/ui/generator/issue-48048.rs b/src/test/ui/generator/issue-48048.rs
new file mode 100644
index 0000000..992bbc9
--- /dev/null
+++ b/src/test/ui/generator/issue-48048.rs
@@ -0,0 +1,13 @@
+#![feature(generators)]
+
+fn main() {
+    let x = (|_| {},);
+
+    || {
+        let x = x;
+
+        x.0({ //~ ERROR borrow may still be in use when generator yields
+            yield;
+        });
+    };
+}
diff --git a/src/test/ui/generator/issue-48048.stderr b/src/test/ui/generator/issue-48048.stderr
new file mode 100644
index 0000000..2342358
--- /dev/null
+++ b/src/test/ui/generator/issue-48048.stderr
@@ -0,0 +1,11 @@
+error[E0626]: borrow may still be in use when generator yields
+  --> $DIR/issue-48048.rs:9:9
+   |
+LL |         x.0({
+   |         ^^^
+LL |             yield;
+   |             ----- possible yield occurs here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0626`.
diff --git a/src/test/ui/generator/issue-53548-1.rs b/src/test/ui/generator/issue-53548-1.rs
new file mode 100644
index 0000000..df11800
--- /dev/null
+++ b/src/test/ui/generator/issue-53548-1.rs
@@ -0,0 +1,20 @@
+// A variant of #53548 that does not actually require generators,
+// but which encountered the same ICE/error. See `issue-53548.rs`
+// for details.
+//
+// compile-pass
+
+use std::cell::RefCell;
+use std::rc::Rc;
+
+trait Trait: 'static {}
+
+struct Store<C> {
+    inner: Rc<RefCell<Option<C>>>,
+}
+
+fn main() {
+    let store = Store::<Box<for<'a> fn(&(dyn Trait + 'a))>> {
+        inner: Default::default(),
+    };
+}
diff --git a/src/test/ui/generator/issue-53548.rs b/src/test/ui/generator/issue-53548.rs
new file mode 100644
index 0000000..00fdb91
--- /dev/null
+++ b/src/test/ui/generator/issue-53548.rs
@@ -0,0 +1,39 @@
+// Regression test for #53548. The `Box<dyn Trait>` type below is
+// expanded to `Box<dyn Trait + 'static>`, but the generator "witness"
+// that results is `for<'r> { Box<dyn Trait + 'r> }`. The WF code was
+// encountering an ICE (when debug-assertions were enabled) and an
+// unexpected compilation error (without debug-asserions) when trying
+// to process this `'r` region bound. In particular, to be WF, the
+// region bound must meet the requirements of the trait, and hence we
+// got `for<'r> { 'r: 'static }`. This would ICE because the `Binder`
+// constructor we were using was assering that no higher-ranked
+// regions were involved (because the WF code is supposed to skip
+// those). The error (if debug-asserions were disabled) came because
+// we obviously cannot prove that `'r: 'static` for any region `'r`.
+// Pursuant with our "lazy WF" strategy for higher-ranked regions, the
+// fix is not to require that `for<'r> { 'r: 'static }` holds (this is
+// also analogous to what we would do for higher-ranked regions
+// appearing within the trait in other positions).
+//
+// compile-pass
+
+#![feature(generators)]
+
+use std::cell::RefCell;
+use std::rc::Rc;
+
+trait Trait: 'static {}
+
+struct Store<C> {
+    inner: Rc<RefCell<Option<C>>>,
+}
+
+fn main() {
+    Box::new(static move || {
+        let store = Store::<Box<dyn Trait>> {
+            inner: Default::default(),
+        };
+        yield ();
+    });
+}
+
diff --git a/src/test/ui/generator/no-arguments-on-generators.rs b/src/test/ui/generator/no-arguments-on-generators.rs
new file mode 100644
index 0000000..344c117
--- /dev/null
+++ b/src/test/ui/generator/no-arguments-on-generators.rs
@@ -0,0 +1,7 @@
+#![feature(generators)]
+
+fn main() {
+    let gen = |start| { //~ ERROR generators cannot have explicit arguments
+        yield;
+    };
+}
diff --git a/src/test/ui/generator/no-arguments-on-generators.stderr b/src/test/ui/generator/no-arguments-on-generators.stderr
new file mode 100644
index 0000000..47a12bb
--- /dev/null
+++ b/src/test/ui/generator/no-arguments-on-generators.stderr
@@ -0,0 +1,9 @@
+error[E0628]: generators cannot have explicit arguments
+  --> $DIR/no-arguments-on-generators.rs:4:15
+   |
+LL |     let gen = |start| {
+   |               ^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0628`.
diff --git a/src/test/ui/generator/not-send-sync.rs b/src/test/ui/generator/not-send-sync.rs
new file mode 100644
index 0000000..ae0a288
--- /dev/null
+++ b/src/test/ui/generator/not-send-sync.rs
@@ -0,0 +1,21 @@
+#![feature(generators)]
+
+use std::cell::Cell;
+
+fn main() {
+    fn assert_sync<T: Sync>(_: T) {}
+    fn assert_send<T: Send>(_: T) {}
+
+    assert_sync(|| {
+        //~^ ERROR: E0277
+        let a = Cell::new(2);
+        yield;
+    });
+
+    let a = Cell::new(2);
+    assert_send(|| {
+        //~^ ERROR: E0277
+        drop(&a);
+        yield;
+    });
+}
diff --git a/src/test/ui/generator/not-send-sync.stderr b/src/test/ui/generator/not-send-sync.stderr
new file mode 100644
index 0000000..7ea9832
--- /dev/null
+++ b/src/test/ui/generator/not-send-sync.stderr
@@ -0,0 +1,33 @@
+error[E0277]: `std::cell::Cell<i32>` cannot be shared between threads safely
+  --> $DIR/not-send-sync.rs:16:5
+   |
+LL |     assert_send(|| {
+   |     ^^^^^^^^^^^ `std::cell::Cell<i32>` cannot be shared between threads safely
+   |
+   = help: the trait `std::marker::Sync` is not implemented for `std::cell::Cell<i32>`
+   = note: required because of the requirements on the impl of `std::marker::Send` for `&std::cell::Cell<i32>`
+   = note: required because it appears within the type `[generator@$DIR/not-send-sync.rs:16:17: 20:6 a:&std::cell::Cell<i32> _]`
+note: required by `main::assert_send`
+  --> $DIR/not-send-sync.rs:7:5
+   |
+LL |     fn assert_send<T: Send>(_: T) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: `std::cell::Cell<i32>` cannot be shared between threads safely
+  --> $DIR/not-send-sync.rs:9:5
+   |
+LL |     assert_sync(|| {
+   |     ^^^^^^^^^^^ `std::cell::Cell<i32>` cannot be shared between threads safely
+   |
+   = help: within `[generator@$DIR/not-send-sync.rs:9:17: 13:6 {std::cell::Cell<i32>, ()}]`, the trait `std::marker::Sync` is not implemented for `std::cell::Cell<i32>`
+   = note: required because it appears within the type `{std::cell::Cell<i32>, ()}`
+   = note: required because it appears within the type `[generator@$DIR/not-send-sync.rs:9:17: 13:6 {std::cell::Cell<i32>, ()}]`
+note: required by `main::assert_sync`
+  --> $DIR/not-send-sync.rs:6:5
+   |
+LL |     fn assert_sync<T: Sync>(_: T) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/generator/pattern-borrow.rs b/src/test/ui/generator/pattern-borrow.rs
new file mode 100644
index 0000000..d193637
--- /dev/null
+++ b/src/test/ui/generator/pattern-borrow.rs
@@ -0,0 +1,17 @@
+#![feature(generators)]
+
+enum Test { A(i32), B, }
+
+fn main() { }
+
+fn fun(test: Test) {
+    move || {
+        if let Test::A(ref _a) = test { //~ ERROR borrow may still be in use when generator yields
+            yield ();
+            _a.use_ref();
+        }
+    };
+}
+
+trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { }  }
+impl<T> Fake for T { }
diff --git a/src/test/ui/generator/pattern-borrow.stderr b/src/test/ui/generator/pattern-borrow.stderr
new file mode 100644
index 0000000..d78da51
--- /dev/null
+++ b/src/test/ui/generator/pattern-borrow.stderr
@@ -0,0 +1,11 @@
+error[E0626]: borrow may still be in use when generator yields
+  --> $DIR/pattern-borrow.rs:9:24
+   |
+LL |         if let Test::A(ref _a) = test {
+   |                        ^^^^^^
+LL |             yield ();
+   |             -------- possible yield occurs here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0626`.
diff --git a/src/test/ui/generator/ref-escapes-but-not-over-yield.nll.stderr b/src/test/ui/generator/ref-escapes-but-not-over-yield.nll.stderr
new file mode 100644
index 0000000..01eea62
--- /dev/null
+++ b/src/test/ui/generator/ref-escapes-but-not-over-yield.nll.stderr
@@ -0,0 +1,15 @@
+error[E0521]: borrowed data escapes outside of generator
+  --> $DIR/ref-escapes-but-not-over-yield.rs:11:9
+   |
+LL |     let mut a = &3;
+   |         ----- `a` is declared here, outside of the generator body
+...
+LL |         a = &b;
+   |         ^^^^--
+   |         |   |
+   |         |   borrow is only valid in the generator body
+   |         reference to `b` escapes the generator body here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0521`.
diff --git a/src/test/ui/generator/ref-escapes-but-not-over-yield.rs b/src/test/ui/generator/ref-escapes-but-not-over-yield.rs
new file mode 100644
index 0000000..8c57658
--- /dev/null
+++ b/src/test/ui/generator/ref-escapes-but-not-over-yield.rs
@@ -0,0 +1,16 @@
+#![feature(generators)]
+
+fn foo(x: &i32) {
+    // In this case, a reference to `b` escapes the generator, but not
+    // because of a yield. We see that there is no yield in the scope of
+    // `b` and give the more generic error message.
+    let mut a = &3;
+    let mut b = move || {
+        yield();
+        let b = 5;
+        a = &b;
+        //~^ ERROR `b` does not live long enough
+    };
+}
+
+fn main() { }
diff --git a/src/test/ui/generator/ref-escapes-but-not-over-yield.stderr b/src/test/ui/generator/ref-escapes-but-not-over-yield.stderr
new file mode 100644
index 0000000..20a06ab
--- /dev/null
+++ b/src/test/ui/generator/ref-escapes-but-not-over-yield.stderr
@@ -0,0 +1,14 @@
+error[E0597]: `b` does not live long enough
+  --> $DIR/ref-escapes-but-not-over-yield.rs:11:14
+   |
+LL |         a = &b;
+   |              ^ borrowed value does not live long enough
+LL |
+LL |     };
+   |     - `b` dropped here while still borrowed
+LL | }
+   | - borrowed value needs to live until here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/generator/sized-yield.rs b/src/test/ui/generator/sized-yield.rs
new file mode 100644
index 0000000..f64849b
--- /dev/null
+++ b/src/test/ui/generator/sized-yield.rs
@@ -0,0 +1,14 @@
+#![feature(generators, generator_trait)]
+
+use std::ops::Generator;
+use std::pin::Pin;
+
+fn main() {
+   let s = String::from("foo");
+   let mut gen = move || {
+   //~^ ERROR the size for values of type
+       yield s[..];
+   };
+   Pin::new(&mut gen).resume();
+   //~^ ERROR the size for values of type
+}
diff --git a/src/test/ui/generator/sized-yield.stderr b/src/test/ui/generator/sized-yield.stderr
new file mode 100644
index 0000000..c2caac7
--- /dev/null
+++ b/src/test/ui/generator/sized-yield.stderr
@@ -0,0 +1,26 @@
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+  --> $DIR/sized-yield.rs:8:26
+   |
+LL |      let mut gen = move || {
+   |  __________________________^
+LL | |
+LL | |        yield s[..];
+LL | |    };
+   | |____^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `str`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: the yield type of a generator must have a statically known size
+
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+  --> $DIR/sized-yield.rs:12:23
+   |
+LL |    Pin::new(&mut gen).resume();
+   |                       ^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `str`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/generator/static-not-unpin.rs b/src/test/ui/generator/static-not-unpin.rs
new file mode 100644
index 0000000..b271e98
--- /dev/null
+++ b/src/test/ui/generator/static-not-unpin.rs
@@ -0,0 +1,15 @@
+#![feature(generators)]
+
+// normalize-stderr-test "std::pin::Unpin" -> "std::marker::Unpin"
+
+use std::marker::Unpin;
+
+fn assert_unpin<T: Unpin>(_: T) {
+}
+
+fn main() {
+    let mut generator = static || {
+        yield;
+    };
+    assert_unpin(generator); //~ ERROR std::marker::Unpin` is not satisfied
+}
diff --git a/src/test/ui/generator/static-not-unpin.stderr b/src/test/ui/generator/static-not-unpin.stderr
new file mode 100644
index 0000000..404d306
--- /dev/null
+++ b/src/test/ui/generator/static-not-unpin.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `[static generator@$DIR/static-not-unpin.rs:11:25: 13:6 _]: std::marker::Unpin` is not satisfied
+  --> $DIR/static-not-unpin.rs:14:5
+   |
+LL |     assert_unpin(generator);
+   |     ^^^^^^^^^^^^ the trait `std::marker::Unpin` is not implemented for `[static generator@$DIR/static-not-unpin.rs:11:25: 13:6 _]`
+   |
+note: required by `assert_unpin`
+  --> $DIR/static-not-unpin.rs:7:1
+   |
+LL | fn assert_unpin<T: Unpin>(_: T) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/generator/yield-in-args.nll.stderr b/src/test/ui/generator/yield-in-args.nll.stderr
new file mode 100644
index 0000000..ee6d22c
--- /dev/null
+++ b/src/test/ui/generator/yield-in-args.nll.stderr
@@ -0,0 +1,9 @@
+error[E0626]: borrow may still be in use when generator yields
+  --> $DIR/yield-in-args.rs:8:13
+   |
+LL |         foo(&b, yield);
+   |             ^^  ----- possible yield occurs here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0626`.
diff --git a/src/test/ui/generator/yield-in-args.rs b/src/test/ui/generator/yield-in-args.rs
new file mode 100644
index 0000000..80110af
--- /dev/null
+++ b/src/test/ui/generator/yield-in-args.rs
@@ -0,0 +1,10 @@
+#![feature(generators)]
+
+fn foo(_b: &bool, _a: ()) {}
+
+fn main() {
+    || {
+        let b = true;
+        foo(&b, yield); //~ ERROR
+    };
+}
diff --git a/src/test/ui/generator/yield-in-args.stderr b/src/test/ui/generator/yield-in-args.stderr
new file mode 100644
index 0000000..2f22dea
--- /dev/null
+++ b/src/test/ui/generator/yield-in-args.stderr
@@ -0,0 +1,9 @@
+error[E0626]: borrow may still be in use when generator yields
+  --> $DIR/yield-in-args.rs:8:14
+   |
+LL |         foo(&b, yield);
+   |              ^  ----- possible yield occurs here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0626`.
diff --git a/src/test/ui/generator/yield-in-const.rs b/src/test/ui/generator/yield-in-const.rs
new file mode 100644
index 0000000..f6f11b9
--- /dev/null
+++ b/src/test/ui/generator/yield-in-const.rs
@@ -0,0 +1,6 @@
+#![feature(generators)]
+
+const A: u8 = { yield 3u8; 3u8};
+//~^ ERROR yield statement outside
+
+fn main() {}
diff --git a/src/test/ui/generator/yield-in-const.stderr b/src/test/ui/generator/yield-in-const.stderr
new file mode 100644
index 0000000..e531bd6
--- /dev/null
+++ b/src/test/ui/generator/yield-in-const.stderr
@@ -0,0 +1,9 @@
+error[E0627]: yield statement outside of generator literal
+  --> $DIR/yield-in-const.rs:3:17
+   |
+LL | const A: u8 = { yield 3u8; 3u8};
+   |                 ^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0627`.
diff --git a/src/test/ui/generator/yield-in-function.rs b/src/test/ui/generator/yield-in-function.rs
new file mode 100644
index 0000000..b737d3b
--- /dev/null
+++ b/src/test/ui/generator/yield-in-function.rs
@@ -0,0 +1,4 @@
+#![feature(generators)]
+
+fn main() { yield; }
+//~^ ERROR yield statement outside
diff --git a/src/test/ui/generator/yield-in-function.stderr b/src/test/ui/generator/yield-in-function.stderr
new file mode 100644
index 0000000..981c9f8
--- /dev/null
+++ b/src/test/ui/generator/yield-in-function.stderr
@@ -0,0 +1,9 @@
+error[E0627]: yield statement outside of generator literal
+  --> $DIR/yield-in-function.rs:3:13
+   |
+LL | fn main() { yield; }
+   |             ^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0627`.
diff --git a/src/test/ui/generator/yield-in-static.rs b/src/test/ui/generator/yield-in-static.rs
new file mode 100644
index 0000000..12c9cce
--- /dev/null
+++ b/src/test/ui/generator/yield-in-static.rs
@@ -0,0 +1,6 @@
+#![feature(generators)]
+
+static B: u8 = { yield 3u8; 3u8};
+//~^ ERROR yield statement outside
+
+fn main() {}
diff --git a/src/test/ui/generator/yield-in-static.stderr b/src/test/ui/generator/yield-in-static.stderr
new file mode 100644
index 0000000..46d341f
--- /dev/null
+++ b/src/test/ui/generator/yield-in-static.stderr
@@ -0,0 +1,9 @@
+error[E0627]: yield statement outside of generator literal
+  --> $DIR/yield-in-static.rs:3:18
+   |
+LL | static B: u8 = { yield 3u8; 3u8};
+   |                  ^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0627`.
diff --git a/src/test/ui/generator/yield-while-iterating.nll.stderr b/src/test/ui/generator/yield-while-iterating.nll.stderr
new file mode 100644
index 0000000..43e29ce
--- /dev/null
+++ b/src/test/ui/generator/yield-while-iterating.nll.stderr
@@ -0,0 +1,25 @@
+error[E0626]: borrow may still be in use when generator yields
+  --> $DIR/yield-while-iterating.rs:13:18
+   |
+LL |         for p in &x {
+   |                  ^^
+LL |             yield();
+   |             ------- possible yield occurs here
+
+error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
+  --> $DIR/yield-while-iterating.rs:58:20
+   |
+LL |     let mut b = || {
+   |                 -- mutable borrow occurs here
+LL |         for p in &mut x {
+   |                       - first borrow occurs due to use of `x` in generator
+...
+LL |     println!("{}", x[0]);
+   |                    ^ immutable borrow occurs here
+LL |     Pin::new(&mut b).resume();
+   |              ------ mutable borrow later used here
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0502, E0626.
+For more information about an error, try `rustc --explain E0502`.
diff --git a/src/test/ui/generator/yield-while-iterating.rs b/src/test/ui/generator/yield-while-iterating.rs
new file mode 100644
index 0000000..e42781d
--- /dev/null
+++ b/src/test/ui/generator/yield-while-iterating.rs
@@ -0,0 +1,75 @@
+#![feature(generators, generator_trait)]
+
+use std::ops::{GeneratorState, Generator};
+use std::cell::Cell;
+use std::pin::Pin;
+
+fn yield_during_iter_owned_data(x: Vec<i32>) {
+    // The generator owns `x`, so we error out when yielding with a
+    // reference to it.  This winds up becoming a rather confusing
+    // regionck error -- in particular, we would freeze with the
+    // reference in scope, and it doesn't live long enough.
+    let _b = move || {
+        for p in &x { //~ ERROR
+            yield();
+        }
+    };
+}
+
+fn yield_during_iter_borrowed_slice(x: &[i32]) {
+    let _b = move || {
+        for p in x {
+            yield();
+        }
+    };
+}
+
+fn yield_during_iter_borrowed_slice_2() {
+    let mut x = vec![22_i32];
+    let _b = || {
+        for p in &x {
+            yield();
+        }
+    };
+    println!("{:?}", x);
+}
+
+fn yield_during_iter_borrowed_slice_3() {
+    // OK to take a mutable ref to `x` and yield
+    // up pointers from it:
+    let mut x = vec![22_i32];
+    let mut b = || {
+        for p in &mut x {
+            yield p;
+        }
+    };
+    Pin::new(&mut b).resume();
+}
+
+fn yield_during_iter_borrowed_slice_4() {
+    // ...but not OK to do that while reading
+    // from `x` too
+    let mut x = vec![22_i32];
+    let mut b = || {
+        for p in &mut x {
+            yield p;
+        }
+    };
+    println!("{}", x[0]); //~ ERROR
+    Pin::new(&mut b).resume();
+}
+
+fn yield_during_range_iter() {
+    // Should be OK.
+    let mut b = || {
+        let v = vec![1,2,3];
+        let len = v.len();
+        for i in 0..len {
+            let x = v[i];
+            yield x;
+        }
+    };
+    Pin::new(&mut b).resume();
+}
+
+fn main() { }
diff --git a/src/test/ui/generator/yield-while-iterating.stderr b/src/test/ui/generator/yield-while-iterating.stderr
new file mode 100644
index 0000000..bcfe4f6
--- /dev/null
+++ b/src/test/ui/generator/yield-while-iterating.stderr
@@ -0,0 +1,26 @@
+error[E0626]: borrow may still be in use when generator yields
+  --> $DIR/yield-while-iterating.rs:13:19
+   |
+LL |         for p in &x {
+   |                   ^
+LL |             yield();
+   |             ------- possible yield occurs here
+
+error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
+  --> $DIR/yield-while-iterating.rs:58:20
+   |
+LL |     let mut b = || {
+   |                 -- mutable borrow occurs here
+LL |         for p in &mut x {
+   |                       - previous borrow occurs due to use of `x` in closure
+...
+LL |     println!("{}", x[0]);
+   |                    ^ immutable borrow occurs here
+LL |     Pin::new(&mut b).resume();
+LL | }
+   | - mutable borrow ends here
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0502, E0626.
+For more information about an error, try `rustc --explain E0502`.
diff --git a/src/test/ui/generator/yield-while-local-borrowed.rs b/src/test/ui/generator/yield-while-local-borrowed.rs
new file mode 100644
index 0000000..38061e7
--- /dev/null
+++ b/src/test/ui/generator/yield-while-local-borrowed.rs
@@ -0,0 +1,53 @@
+// compile-flags: -Z borrowck=compare
+
+#![feature(generators, generator_trait)]
+
+use std::ops::{GeneratorState, Generator};
+use std::cell::Cell;
+use std::pin::Pin;
+
+fn borrow_local_inline() {
+    // Not OK to yield with a borrow of a temporary.
+    //
+    // (This error occurs because the region shows up in the type of
+    // `b` and gets extended by region inference.)
+    let mut b = move || {
+        let a = &mut 3;
+        //~^ ERROR borrow may still be in use when generator yields (Ast)
+        //~| ERROR borrow may still be in use when generator yields (Mir)
+        yield();
+        println!("{}", a);
+    };
+    Pin::new(&mut b).resume();
+}
+
+fn borrow_local_inline_done() {
+    // No error here -- `a` is not in scope at the point of `yield`.
+    let mut b = move || {
+        {
+            let a = &mut 3;
+        }
+        yield();
+    };
+    Pin::new(&mut b).resume();
+}
+
+fn borrow_local() {
+    // Not OK to yield with a borrow of a temporary.
+    //
+    // (This error occurs because the region shows up in the type of
+    // `b` and gets extended by region inference.)
+    let mut b = move || {
+        let a = 3;
+        {
+            let b = &a;
+            //~^ ERROR borrow may still be in use when generator yields (Ast)
+            //~| ERROR borrow may still be in use when generator yields (Mir)
+            yield();
+            println!("{}", b);
+        }
+    };
+    Pin::new(&mut b).resume();
+}
+
+fn main() { }
diff --git a/src/test/ui/generator/yield-while-local-borrowed.stderr b/src/test/ui/generator/yield-while-local-borrowed.stderr
new file mode 100644
index 0000000..56f425b
--- /dev/null
+++ b/src/test/ui/generator/yield-while-local-borrowed.stderr
@@ -0,0 +1,39 @@
+error[E0626]: borrow may still be in use when generator yields (Ast)
+  --> $DIR/yield-while-local-borrowed.rs:15:22
+   |
+LL |         let a = &mut 3;
+   |                      ^
+...
+LL |         yield();
+   |         ------- possible yield occurs here
+
+error[E0626]: borrow may still be in use when generator yields (Ast)
+  --> $DIR/yield-while-local-borrowed.rs:43:22
+   |
+LL |             let b = &a;
+   |                      ^
+...
+LL |             yield();
+   |             ------- possible yield occurs here
+
+error[E0626]: borrow may still be in use when generator yields (Mir)
+  --> $DIR/yield-while-local-borrowed.rs:15:17
+   |
+LL |         let a = &mut 3;
+   |                 ^^^^^^
+...
+LL |         yield();
+   |         ------- possible yield occurs here
+
+error[E0626]: borrow may still be in use when generator yields (Mir)
+  --> $DIR/yield-while-local-borrowed.rs:43:21
+   |
+LL |             let b = &a;
+   |                     ^^
+...
+LL |             yield();
+   |             ------- possible yield occurs here
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0626`.
diff --git a/src/test/ui/generator/yield-while-ref-reborrowed.nll.stderr b/src/test/ui/generator/yield-while-ref-reborrowed.nll.stderr
new file mode 100644
index 0000000..4c37cd3
--- /dev/null
+++ b/src/test/ui/generator/yield-while-ref-reborrowed.nll.stderr
@@ -0,0 +1,16 @@
+error[E0501]: cannot borrow `x` as immutable because previous closure requires unique access
+  --> $DIR/yield-while-ref-reborrowed.rs:36:20
+   |
+LL |     let mut b = || {
+   |                 -- generator construction occurs here
+LL |         let a = &mut *x;
+   |                       - first borrow occurs due to use of `x` in generator
+...
+LL |     println!("{}", x);
+   |                    ^ second borrow occurs here
+LL |     Pin::new(&mut b).resume();
+   |              ------ first borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0501`.
diff --git a/src/test/ui/generator/yield-while-ref-reborrowed.rs b/src/test/ui/generator/yield-while-ref-reborrowed.rs
new file mode 100644
index 0000000..f54a4f4
--- /dev/null
+++ b/src/test/ui/generator/yield-while-ref-reborrowed.rs
@@ -0,0 +1,40 @@
+#![feature(generators, generator_trait)]
+
+use std::ops::{GeneratorState, Generator};
+use std::cell::Cell;
+use std::pin::Pin;
+
+fn reborrow_shared_ref(x: &i32) {
+    // This is OK -- we have a borrow live over the yield, but it's of
+    // data that outlives the generator.
+    let mut b = move || {
+        let a = &*x;
+        yield();
+        println!("{}", a);
+    };
+    Pin::new(&mut b).resume();
+}
+
+fn reborrow_mutable_ref(x: &mut i32) {
+    // This is OK -- we have a borrow live over the yield, but it's of
+    // data that outlives the generator.
+    let mut b = move || {
+        let a = &mut *x;
+        yield();
+        println!("{}", a);
+    };
+    Pin::new(&mut b).resume();
+}
+
+fn reborrow_mutable_ref_2(x: &mut i32) {
+    // ...but not OK to go on using `x`.
+    let mut b = || {
+        let a = &mut *x;
+        yield();
+        println!("{}", a);
+    };
+    println!("{}", x); //~ ERROR
+    Pin::new(&mut b).resume();
+}
+
+fn main() { }
diff --git a/src/test/ui/generator/yield-while-ref-reborrowed.stderr b/src/test/ui/generator/yield-while-ref-reborrowed.stderr
new file mode 100644
index 0000000..155f277
--- /dev/null
+++ b/src/test/ui/generator/yield-while-ref-reborrowed.stderr
@@ -0,0 +1,17 @@
+error[E0501]: cannot borrow `x` as immutable because previous closure requires unique access
+  --> $DIR/yield-while-ref-reborrowed.rs:36:20
+   |
+LL |     let mut b = || {
+   |                 -- closure construction occurs here
+LL |         let a = &mut *x;
+   |                       - previous borrow occurs due to use of `x` in closure
+...
+LL |     println!("{}", x);
+   |                    ^ borrow occurs here
+LL |     Pin::new(&mut b).resume();
+LL | }
+   | - borrow from closure ends here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0501`.
diff --git a/src/test/ui/generic/generic-arg-mismatch-recover.rs b/src/test/ui/generic/generic-arg-mismatch-recover.rs
new file mode 100644
index 0000000..f4e15fb
--- /dev/null
+++ b/src/test/ui/generic/generic-arg-mismatch-recover.rs
@@ -0,0 +1,11 @@
+struct Foo<'a, T: 'a>(&'a T);
+
+struct Bar<'a>(&'a ());
+
+fn main() {
+    Foo::<'static, 'static, ()>(&0); //~ ERROR wrong number of lifetime arguments
+    //~^ ERROR mismatched types
+
+    Bar::<'static, 'static, ()>(&()); //~ ERROR wrong number of lifetime arguments
+    //~^ ERROR wrong number of type arguments
+}
diff --git a/src/test/ui/generic/generic-arg-mismatch-recover.stderr b/src/test/ui/generic/generic-arg-mismatch-recover.stderr
new file mode 100644
index 0000000..e16ad91
--- /dev/null
+++ b/src/test/ui/generic/generic-arg-mismatch-recover.stderr
@@ -0,0 +1,31 @@
+error[E0107]: wrong number of lifetime arguments: expected 1, found 2
+  --> $DIR/generic-arg-mismatch-recover.rs:6:20
+   |
+LL |     Foo::<'static, 'static, ()>(&0);
+   |                    ^^^^^^^ unexpected lifetime argument
+
+error[E0308]: mismatched types
+  --> $DIR/generic-arg-mismatch-recover.rs:6:33
+   |
+LL |     Foo::<'static, 'static, ()>(&0);
+   |                                 ^^ expected (), found integer
+   |
+   = note: expected type `&'static ()`
+              found type `&{integer}`
+
+error[E0107]: wrong number of lifetime arguments: expected 1, found 2
+  --> $DIR/generic-arg-mismatch-recover.rs:9:20
+   |
+LL |     Bar::<'static, 'static, ()>(&());
+   |                    ^^^^^^^ unexpected lifetime argument
+
+error[E0107]: wrong number of type arguments: expected 0, found 1
+  --> $DIR/generic-arg-mismatch-recover.rs:9:29
+   |
+LL |     Bar::<'static, 'static, ()>(&());
+   |                             ^^ unexpected type argument
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0107, E0308.
+For more information about an error, try `rustc --explain E0107`.
diff --git a/src/test/ui/generic/generic-extern-lifetime.rs b/src/test/ui/generic/generic-extern-lifetime.rs
new file mode 100644
index 0000000..22bcd44
--- /dev/null
+++ b/src/test/ui/generic/generic-extern-lifetime.rs
@@ -0,0 +1,15 @@
+// Test to make sure the names of the lifetimes are correctly resolved
+// in extern blocks.
+
+extern {
+   pub fn life<'a>(x:&'a i32);
+   pub fn life2<'b>(x:&'a i32, y:&'b i32); //~ ERROR use of undeclared lifetime name `'a`
+   pub fn life3<'a>(x:&'a i32, y:&i32) -> &'a i32;
+   pub fn life4<'b>(x: for<'c> fn(&'a i32)); //~ ERROR use of undeclared lifetime name `'a`
+   pub fn life5<'b>(x: for<'c> fn(&'b i32));
+   pub fn life6<'b>(x: for<'c> fn(&'c i32));
+   pub fn life7<'b>() -> for<'c> fn(&'a i32); //~ ERROR use of undeclared lifetime name `'a`
+   pub fn life8<'b>() -> for<'c> fn(&'b i32);
+   pub fn life9<'b>() -> for<'c> fn(&'c i32);
+}
+fn main() {}
diff --git a/src/test/ui/generic/generic-extern-lifetime.stderr b/src/test/ui/generic/generic-extern-lifetime.stderr
new file mode 100644
index 0000000..39372c9
--- /dev/null
+++ b/src/test/ui/generic/generic-extern-lifetime.stderr
@@ -0,0 +1,21 @@
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/generic-extern-lifetime.rs:6:24
+   |
+LL |    pub fn life2<'b>(x:&'a i32, y:&'b i32);
+   |                        ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/generic-extern-lifetime.rs:8:36
+   |
+LL |    pub fn life4<'b>(x: for<'c> fn(&'a i32));
+   |                                    ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/generic-extern-lifetime.rs:11:38
+   |
+LL |    pub fn life7<'b>() -> for<'c> fn(&'a i32);
+   |                                      ^^ undeclared lifetime
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0261`.
diff --git a/src/test/ui/generic/generic-extern.rs b/src/test/ui/generic/generic-extern.rs
new file mode 100644
index 0000000..e52a885
--- /dev/null
+++ b/src/test/ui/generic/generic-extern.rs
@@ -0,0 +1,7 @@
+extern {
+    fn foo<T>(); //~ ERROR foreign items may not have type parameters
+}
+
+fn main() {
+    foo::<i32>();
+}
diff --git a/src/test/ui/generic/generic-extern.stderr b/src/test/ui/generic/generic-extern.stderr
new file mode 100644
index 0000000..e7625ab
--- /dev/null
+++ b/src/test/ui/generic/generic-extern.stderr
@@ -0,0 +1,11 @@
+error[E0044]: foreign items may not have type parameters
+  --> $DIR/generic-extern.rs:2:5
+   |
+LL |     fn foo<T>();
+   |     ^^^^^^^^^^^^ can't have type parameters
+   |
+   = help: use specialization instead of type parameters by replacing them with concrete types like `u32`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0044`.
diff --git a/src/test/ui/generic/generic-impl-less-params-with-defaults.rs b/src/test/ui/generic/generic-impl-less-params-with-defaults.rs
new file mode 100644
index 0000000..abbf640
--- /dev/null
+++ b/src/test/ui/generic/generic-impl-less-params-with-defaults.rs
@@ -0,0 +1,13 @@
+use std::marker;
+
+struct Foo<A, B, C = (A, B)>(
+    marker::PhantomData<(A,B,C)>);
+
+impl<A, B, C> Foo<A, B, C> {
+    fn new() -> Foo<A, B, C> {Foo(marker::PhantomData)}
+}
+
+fn main() {
+    Foo::<isize>::new();
+    //~^ ERROR wrong number of type arguments
+}
diff --git a/src/test/ui/generic/generic-impl-less-params-with-defaults.stderr b/src/test/ui/generic/generic-impl-less-params-with-defaults.stderr
new file mode 100644
index 0000000..22b00e1
--- /dev/null
+++ b/src/test/ui/generic/generic-impl-less-params-with-defaults.stderr
@@ -0,0 +1,9 @@
+error[E0107]: wrong number of type arguments: expected at least 2, found 1
+  --> $DIR/generic-impl-less-params-with-defaults.rs:11:5
+   |
+LL |     Foo::<isize>::new();
+   |     ^^^^^^^^^^^^^^^^^ expected at least 2 type arguments
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0107`.
diff --git a/src/test/ui/generic/generic-impl-more-params-with-defaults.rs b/src/test/ui/generic/generic-impl-more-params-with-defaults.rs
new file mode 100644
index 0000000..a14fb70
--- /dev/null
+++ b/src/test/ui/generic/generic-impl-more-params-with-defaults.rs
@@ -0,0 +1,15 @@
+use std::marker;
+
+struct Heap;
+
+struct Vec<T, A = Heap>(
+    marker::PhantomData<(T,A)>);
+
+impl<T, A> Vec<T, A> {
+    fn new() -> Vec<T, A> {Vec(marker::PhantomData)}
+}
+
+fn main() {
+    Vec::<isize, Heap, bool>::new();
+    //~^ ERROR wrong number of type arguments
+}
diff --git a/src/test/ui/generic/generic-impl-more-params-with-defaults.stderr b/src/test/ui/generic/generic-impl-more-params-with-defaults.stderr
new file mode 100644
index 0000000..66950d4
--- /dev/null
+++ b/src/test/ui/generic/generic-impl-more-params-with-defaults.stderr
@@ -0,0 +1,9 @@
+error[E0107]: wrong number of type arguments: expected at most 2, found 3
+  --> $DIR/generic-impl-more-params-with-defaults.rs:13:5
+   |
+LL |     Vec::<isize, Heap, bool>::new();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected at most 2 type arguments
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0107`.
diff --git a/src/test/ui/generic/generic-lifetime-trait-impl.rs b/src/test/ui/generic/generic-lifetime-trait-impl.rs
new file mode 100644
index 0000000..6ffaba1
--- /dev/null
+++ b/src/test/ui/generic/generic-lifetime-trait-impl.rs
@@ -0,0 +1,23 @@
+// This code used to produce an ICE on the definition of trait Bar
+// with the following message:
+//
+// Type parameter out of range when substituting in region 'a (root
+// type=fn(Self) -> 'astr) (space=FnSpace, index=0)
+//
+// Regression test for issue #16218.
+
+trait Bar<'a> {
+    fn dummy(&'a self);
+}
+
+trait Foo<'a> {
+    fn dummy(&'a self) { }
+    fn bar<'b, T: Bar<'b>>(self) -> &'b str;
+}
+
+impl<'a> Foo<'a> for &'a str {
+    fn bar<T: Bar<'a>>(self) -> &'a str { panic!() } //~ ERROR lifetime
+}
+
+fn main() {
+}
diff --git a/src/test/ui/generic/generic-lifetime-trait-impl.stderr b/src/test/ui/generic/generic-lifetime-trait-impl.stderr
new file mode 100644
index 0000000..4ae5098
--- /dev/null
+++ b/src/test/ui/generic/generic-lifetime-trait-impl.stderr
@@ -0,0 +1,12 @@
+error[E0195]: lifetime parameters or bounds on method `bar` do not match the trait declaration
+  --> $DIR/generic-lifetime-trait-impl.rs:19:11
+   |
+LL |     fn bar<'b, T: Bar<'b>>(self) -> &'b str;
+   |           ---------------- lifetimes in impl do not match this method in trait
+...
+LL |     fn bar<T: Bar<'a>>(self) -> &'a str { panic!() }
+   |           ^^^^^^^^^^^^ lifetimes do not match method in trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0195`.
diff --git a/src/test/ui/generic/generic-no-mangle.rs b/src/test/ui/generic/generic-no-mangle.rs
new file mode 100644
index 0000000..994aebc
--- /dev/null
+++ b/src/test/ui/generic/generic-no-mangle.rs
@@ -0,0 +1,15 @@
+#![deny(no_mangle_generic_items)]
+
+#[no_mangle]
+pub fn foo<T>() {} //~ ERROR functions generic over types or consts must be mangled
+
+#[no_mangle]
+pub extern fn bar<T>() {} //~ ERROR functions generic over types or consts must be mangled
+
+#[no_mangle]
+pub fn baz(x: &i32) -> &i32 { x }
+
+#[no_mangle]
+pub fn qux<'a>(x: &'a i32) -> &i32 { x }
+
+fn main() {}
diff --git a/src/test/ui/generic/generic-no-mangle.stderr b/src/test/ui/generic/generic-no-mangle.stderr
new file mode 100644
index 0000000..f055a3a
--- /dev/null
+++ b/src/test/ui/generic/generic-no-mangle.stderr
@@ -0,0 +1,24 @@
+error: functions generic over types or consts must be mangled
+  --> $DIR/generic-no-mangle.rs:4:1
+   |
+LL | #[no_mangle]
+   | ------------ help: remove this attribute
+LL | pub fn foo<T>() {}
+   | ^^^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/generic-no-mangle.rs:1:9
+   |
+LL | #![deny(no_mangle_generic_items)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: functions generic over types or consts must be mangled
+  --> $DIR/generic-no-mangle.rs:7:1
+   |
+LL | #[no_mangle]
+   | ------------ help: remove this attribute
+LL | pub extern fn bar<T>() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/generic/generic-non-trailing-defaults.rs b/src/test/ui/generic/generic-non-trailing-defaults.rs
new file mode 100644
index 0000000..8d9883d
--- /dev/null
+++ b/src/test/ui/generic/generic-non-trailing-defaults.rs
@@ -0,0 +1,10 @@
+struct Heap;
+
+struct Vec<A = Heap, T>(A, T);
+//~^ ERROR type parameters with a default must be trailing
+
+struct Foo<A, B = Vec<C>, C>(A, B, C);
+//~^ ERROR type parameters with a default must be trailing
+//~| ERROR type parameters with a default cannot use forward declared identifiers
+
+fn main() {}
diff --git a/src/test/ui/generic/generic-non-trailing-defaults.stderr b/src/test/ui/generic/generic-non-trailing-defaults.stderr
new file mode 100644
index 0000000..fb359f6
--- /dev/null
+++ b/src/test/ui/generic/generic-non-trailing-defaults.stderr
@@ -0,0 +1,21 @@
+error: type parameters with a default must be trailing
+  --> $DIR/generic-non-trailing-defaults.rs:3:12
+   |
+LL | struct Vec<A = Heap, T>(A, T);
+   |            ^
+
+error: type parameters with a default must be trailing
+  --> $DIR/generic-non-trailing-defaults.rs:6:15
+   |
+LL | struct Foo<A, B = Vec<C>, C>(A, B, C);
+   |               ^
+
+error[E0128]: type parameters with a default cannot use forward declared identifiers
+  --> $DIR/generic-non-trailing-defaults.rs:6:23
+   |
+LL | struct Foo<A, B = Vec<C>, C>(A, B, C);
+   |                       ^ defaulted type parameters cannot be forward declared
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0128`.
diff --git a/src/test/ui/generic/generic-param-attrs.rs b/src/test/ui/generic/generic-param-attrs.rs
new file mode 100644
index 0000000..601d2a9
--- /dev/null
+++ b/src/test/ui/generic/generic-param-attrs.rs
@@ -0,0 +1,44 @@
+// This test previously ensured that attributes on formals in generic parameter
+// lists are rejected without a feature gate.
+//
+// (We are prefixing all tested features with `rustc_`, to ensure that
+// the attributes themselves won't be rejected by the compiler when
+// using `rustc_attrs` feature. There is a separate compile-fail/ test
+// ensuring that the attribute feature-gating works in this context.)
+
+// compile-pass
+
+#![feature(rustc_attrs)]
+#![allow(dead_code)]
+
+struct StLt<#[rustc_lt_struct] 'a>(&'a u32);
+struct StTy<#[rustc_ty_struct] I>(I);
+enum EnLt<#[rustc_lt_enum] 'b> { A(&'b u32), B }
+enum EnTy<#[rustc_ty_enum] J> { A(J), B }
+trait TrLt<#[rustc_lt_trait] 'c> { fn foo(&self, _: &'c [u32]) -> &'c u32; }
+trait TrTy<#[rustc_ty_trait] K> { fn foo(&self, _: K); }
+type TyLt<#[rustc_lt_type] 'd> = &'d u32;
+type TyTy<#[rustc_ty_type] L> = (L, );
+
+impl<#[rustc_lt_inherent] 'e> StLt<'e> { }
+impl<#[rustc_ty_inherent] M> StTy<M> { }
+impl<#[rustc_lt_impl_for] 'f> TrLt<'f> for StLt<'f> {
+    fn foo(&self, _: &'f [u32]) -> &'f u32 { loop { } }
+}
+impl<#[rustc_ty_impl_for] N> TrTy<N> for StTy<N> {
+    fn foo(&self, _: N) { }
+}
+
+fn f_lt<#[rustc_lt_fn] 'g>(_: &'g [u32]) -> &'g u32 { loop { } }
+fn f_ty<#[rustc_ty_fn] O>(_: O) { }
+
+impl<I> StTy<I> {
+    fn m_lt<#[rustc_lt_meth] 'h>(_: &'h [u32]) -> &'h u32 { loop { } }
+    fn m_ty<#[rustc_ty_meth] P>(_: P) { }
+}
+
+fn hof_lt<Q>(_: Q)
+    where Q: for <#[rustc_lt_hof] 'i> Fn(&'i [u32]) -> &'i u32
+{}
+
+fn main() {}
diff --git a/src/test/ui/generic/generic-type-less-params-with-defaults.rs b/src/test/ui/generic/generic-type-less-params-with-defaults.rs
new file mode 100644
index 0000000..3aa0339
--- /dev/null
+++ b/src/test/ui/generic/generic-type-less-params-with-defaults.rs
@@ -0,0 +1,11 @@
+use std::marker;
+
+struct Heap;
+
+struct Vec<T, A = Heap>(
+    marker::PhantomData<(T,A)>);
+
+fn main() {
+    let _: Vec;
+    //~^ ERROR wrong number of type arguments: expected at least 1, found 0 [E0107]
+}
diff --git a/src/test/ui/generic/generic-type-less-params-with-defaults.stderr b/src/test/ui/generic/generic-type-less-params-with-defaults.stderr
new file mode 100644
index 0000000..a4cc832
--- /dev/null
+++ b/src/test/ui/generic/generic-type-less-params-with-defaults.stderr
@@ -0,0 +1,9 @@
+error[E0107]: wrong number of type arguments: expected at least 1, found 0
+  --> $DIR/generic-type-less-params-with-defaults.rs:9:12
+   |
+LL |     let _: Vec;
+   |            ^^^ expected at least 1 type argument
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0107`.
diff --git a/src/test/ui/generic/generic-type-more-params-with-defaults.rs b/src/test/ui/generic/generic-type-more-params-with-defaults.rs
new file mode 100644
index 0000000..2713f08
--- /dev/null
+++ b/src/test/ui/generic/generic-type-more-params-with-defaults.rs
@@ -0,0 +1,11 @@
+use std::marker;
+
+struct Heap;
+
+struct Vec<T, A = Heap>(
+    marker::PhantomData<(T,A)>);
+
+fn main() {
+    let _: Vec<isize, Heap, bool>;
+    //~^ ERROR wrong number of type arguments: expected at most 2, found 3 [E0107]
+}
diff --git a/src/test/ui/generic/generic-type-more-params-with-defaults.stderr b/src/test/ui/generic/generic-type-more-params-with-defaults.stderr
new file mode 100644
index 0000000..5031930
--- /dev/null
+++ b/src/test/ui/generic/generic-type-more-params-with-defaults.stderr
@@ -0,0 +1,9 @@
+error[E0107]: wrong number of type arguments: expected at most 2, found 3
+  --> $DIR/generic-type-more-params-with-defaults.rs:9:12
+   |
+LL |     let _: Vec<isize, Heap, bool>;
+   |            ^^^^^^^^^^^^^^^^^^^^^^ expected at most 2 type arguments
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0107`.
diff --git a/src/test/ui/generic/generic-type-params-forward-mention.rs b/src/test/ui/generic/generic-type-params-forward-mention.rs
new file mode 100644
index 0000000..ac0cab2
--- /dev/null
+++ b/src/test/ui/generic/generic-type-params-forward-mention.rs
@@ -0,0 +1,6 @@
+// Ensure that we get an error and not an ICE for this problematic case.
+struct Foo<T = Option<U>, U = bool>(T, U);
+//~^ ERROR type parameters with a default cannot use forward declared identifiers
+fn main() {
+    let x: Foo;
+}
diff --git a/src/test/ui/generic/generic-type-params-forward-mention.stderr b/src/test/ui/generic/generic-type-params-forward-mention.stderr
new file mode 100644
index 0000000..97389c3
--- /dev/null
+++ b/src/test/ui/generic/generic-type-params-forward-mention.stderr
@@ -0,0 +1,9 @@
+error[E0128]: type parameters with a default cannot use forward declared identifiers
+  --> $DIR/generic-type-params-forward-mention.rs:2:23
+   |
+LL | struct Foo<T = Option<U>, U = bool>(T, U);
+   |                       ^ defaulted type parameters cannot be forward declared
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0128`.
diff --git a/src/test/ui/generic/generic-type-params-name-repr.rs b/src/test/ui/generic/generic-type-params-name-repr.rs
new file mode 100644
index 0000000..7e074aa
--- /dev/null
+++ b/src/test/ui/generic/generic-type-params-name-repr.rs
@@ -0,0 +1,51 @@
+use std::marker;
+
+struct A;
+struct B;
+struct C;
+struct Foo<T = A, U = B, V = C>(marker::PhantomData<(T,U,V)>);
+
+struct Hash<T>(marker::PhantomData<T>);
+struct HashMap<K, V, H = Hash<K>>(marker::PhantomData<(K,V,H)>);
+
+fn main() {
+    // Ensure that the printed type doesn't include the default type params...
+    let _: Foo<isize> = ();
+    //~^ ERROR mismatched types
+    //~| expected type `Foo<isize>`
+    //~| found type `()`
+    //~| expected struct `Foo`, found ()
+
+    // ...even when they're present, but the same types as the defaults.
+    let _: Foo<isize, B, C> = ();
+    //~^ ERROR mismatched types
+    //~| expected type `Foo<isize>`
+    //~| found type `()`
+    //~| expected struct `Foo`, found ()
+
+    // Including cases where the default is using previous type params.
+    let _: HashMap<String, isize> = ();
+    //~^ ERROR mismatched types
+    //~| expected type `HashMap<std::string::String, isize>`
+    //~| found type `()`
+    //~| expected struct `HashMap`, found ()
+    let _: HashMap<String, isize, Hash<String>> = ();
+    //~^ ERROR mismatched types
+    //~| expected type `HashMap<std::string::String, isize>`
+    //~| found type `()`
+    //~| expected struct `HashMap`, found ()
+
+    // But not when there's a different type in between.
+    let _: Foo<A, isize, C> = ();
+    //~^ ERROR mismatched types
+    //~| expected type `Foo<A, isize>`
+    //~| found type `()`
+    //~| expected struct `Foo`, found ()
+
+    // And don't print <> at all when there's just defaults.
+    let _: Foo<A, B, C> = ();
+    //~^ ERROR mismatched types
+    //~| expected type `Foo`
+    //~| found type `()`
+    //~| expected struct `Foo`, found ()
+}
diff --git a/src/test/ui/generic/generic-type-params-name-repr.stderr b/src/test/ui/generic/generic-type-params-name-repr.stderr
new file mode 100644
index 0000000..2aa9caf
--- /dev/null
+++ b/src/test/ui/generic/generic-type-params-name-repr.stderr
@@ -0,0 +1,57 @@
+error[E0308]: mismatched types
+  --> $DIR/generic-type-params-name-repr.rs:13:25
+   |
+LL |     let _: Foo<isize> = ();
+   |                         ^^ expected struct `Foo`, found ()
+   |
+   = note: expected type `Foo<isize>`
+              found type `()`
+
+error[E0308]: mismatched types
+  --> $DIR/generic-type-params-name-repr.rs:20:31
+   |
+LL |     let _: Foo<isize, B, C> = ();
+   |                               ^^ expected struct `Foo`, found ()
+   |
+   = note: expected type `Foo<isize>`
+              found type `()`
+
+error[E0308]: mismatched types
+  --> $DIR/generic-type-params-name-repr.rs:27:37
+   |
+LL |     let _: HashMap<String, isize> = ();
+   |                                     ^^ expected struct `HashMap`, found ()
+   |
+   = note: expected type `HashMap<std::string::String, isize>`
+              found type `()`
+
+error[E0308]: mismatched types
+  --> $DIR/generic-type-params-name-repr.rs:32:51
+   |
+LL |     let _: HashMap<String, isize, Hash<String>> = ();
+   |                                                   ^^ expected struct `HashMap`, found ()
+   |
+   = note: expected type `HashMap<std::string::String, isize>`
+              found type `()`
+
+error[E0308]: mismatched types
+  --> $DIR/generic-type-params-name-repr.rs:39:31
+   |
+LL |     let _: Foo<A, isize, C> = ();
+   |                               ^^ expected struct `Foo`, found ()
+   |
+   = note: expected type `Foo<A, isize>`
+              found type `()`
+
+error[E0308]: mismatched types
+  --> $DIR/generic-type-params-name-repr.rs:46:27
+   |
+LL |     let _: Foo<A, B, C> = ();
+   |                           ^^ expected struct `Foo`, found ()
+   |
+   = note: expected type `Foo`
+              found type `()`
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/glob-cycles.rs b/src/test/ui/glob-cycles.rs
new file mode 100644
index 0000000..84f9e5d
--- /dev/null
+++ b/src/test/ui/glob-cycles.rs
@@ -0,0 +1,19 @@
+// compile-pass
+// skip-codegen
+mod foo {
+    pub use bar::*;
+    pub use main as f;
+}
+
+mod bar {
+    pub use foo::*;
+}
+
+pub use foo::*;
+pub use baz::*;
+mod baz {
+    pub use super::*;
+}
+
+
+pub fn main() {}
diff --git a/src/test/ui/glob-resolve1.rs b/src/test/ui/glob-resolve1.rs
new file mode 100644
index 0000000..63c435c
--- /dev/null
+++ b/src/test/ui/glob-resolve1.rs
@@ -0,0 +1,31 @@
+// Make sure that globs only bring in public things.
+
+use bar::*;
+
+mod bar {
+    use self::fpriv as import;
+    fn fpriv() {}
+    extern {
+        fn epriv();
+    }
+    enum A { A1 }
+    pub enum B { B1 }
+
+    struct C;
+
+    type D = isize;
+}
+
+fn foo<T>() {}
+
+fn main() {
+    fpriv(); //~ ERROR cannot find function `fpriv` in this scope
+    epriv(); //~ ERROR cannot find function `epriv` in this scope
+    B; //~ ERROR expected value, found enum `B`
+    C; //~ ERROR cannot find value `C` in this scope
+    import(); //~ ERROR: cannot find function `import` in this scope
+
+    foo::<A>(); //~ ERROR: cannot find type `A` in this scope
+    foo::<C>(); //~ ERROR: cannot find type `C` in this scope
+    foo::<D>(); //~ ERROR: cannot find type `D` in this scope
+}
diff --git a/src/test/ui/glob-resolve1.stderr b/src/test/ui/glob-resolve1.stderr
new file mode 100644
index 0000000..c252a6e
--- /dev/null
+++ b/src/test/ui/glob-resolve1.stderr
@@ -0,0 +1,88 @@
+error[E0425]: cannot find function `fpriv` in this scope
+  --> $DIR/glob-resolve1.rs:22:5
+   |
+LL |     fpriv();
+   |     ^^^^^ not found in this scope
+help: possible candidate is found in another module, you can import it into scope
+   |
+LL | use bar::fpriv;
+   |
+
+error[E0425]: cannot find function `epriv` in this scope
+  --> $DIR/glob-resolve1.rs:23:5
+   |
+LL |     epriv();
+   |     ^^^^^ not found in this scope
+help: possible candidate is found in another module, you can import it into scope
+   |
+LL | use bar::epriv;
+   |
+
+error[E0423]: expected value, found enum `B`
+  --> $DIR/glob-resolve1.rs:24:5
+   |
+LL |     B;
+   |     ^ help: try using the enum's variant: `B::B1`
+
+error[E0425]: cannot find value `C` in this scope
+  --> $DIR/glob-resolve1.rs:25:5
+   |
+LL |     C;
+   |     ^ not found in this scope
+help: possible candidate is found in another module, you can import it into scope
+   |
+LL | use bar::C;
+   |
+
+error[E0425]: cannot find function `import` in this scope
+  --> $DIR/glob-resolve1.rs:26:5
+   |
+LL |     import();
+   |     ^^^^^^ not found in this scope
+
+error[E0412]: cannot find type `A` in this scope
+  --> $DIR/glob-resolve1.rs:28:11
+   |
+LL |     foo::<A>();
+   |           ^
+help: an enum with a similar name exists
+   |
+LL |     foo::<B>();
+   |           ^
+help: possible candidate is found in another module, you can import it into scope
+   |
+LL | use bar::A;
+   |
+
+error[E0412]: cannot find type `C` in this scope
+  --> $DIR/glob-resolve1.rs:29:11
+   |
+LL |     foo::<C>();
+   |           ^
+help: an enum with a similar name exists
+   |
+LL |     foo::<B>();
+   |           ^
+help: possible candidate is found in another module, you can import it into scope
+   |
+LL | use bar::C;
+   |
+
+error[E0412]: cannot find type `D` in this scope
+  --> $DIR/glob-resolve1.rs:30:11
+   |
+LL |     foo::<D>();
+   |           ^
+help: an enum with a similar name exists
+   |
+LL |     foo::<B>();
+   |           ^
+help: possible candidate is found in another module, you can import it into scope
+   |
+LL | use bar::D;
+   |
+
+error: aborting due to 8 previous errors
+
+Some errors occurred: E0412, E0423, E0425.
+For more information about an error, try `rustc --explain E0412`.
diff --git a/src/test/ui/hashmap-iter-value-lifetime.nll.stderr b/src/test/ui/hashmap-iter-value-lifetime.nll.stderr
new file mode 100644
index 0000000..f7626b1
--- /dev/null
+++ b/src/test/ui/hashmap-iter-value-lifetime.nll.stderr
@@ -0,0 +1,15 @@
+error[E0502]: cannot borrow `my_stuff` as mutable because it is also borrowed as immutable
+  --> $DIR/hashmap-iter-value-lifetime.rs:7:5
+   |
+LL |     let (_, thing) = my_stuff.iter().next().unwrap();
+   |                      -------- immutable borrow occurs here
+LL | 
+LL |     my_stuff.clear();
+   |     ^^^^^^^^^^^^^^^^ mutable borrow occurs here
+LL | 
+LL |     println!("{}", *thing);
+   |                    ------ immutable borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/hashmap-iter-value-lifetime.rs b/src/test/ui/hashmap-iter-value-lifetime.rs
new file mode 100644
index 0000000..260ea8c
--- /dev/null
+++ b/src/test/ui/hashmap-iter-value-lifetime.rs
@@ -0,0 +1,10 @@
+fn main() {
+    let mut my_stuff = std::collections::HashMap::new();
+    my_stuff.insert(0, 42);
+
+    let (_, thing) = my_stuff.iter().next().unwrap();
+
+    my_stuff.clear(); //~ ERROR cannot borrow
+
+    println!("{}", *thing);
+}
diff --git a/src/test/ui/hashmap-iter-value-lifetime.stderr b/src/test/ui/hashmap-iter-value-lifetime.stderr
new file mode 100644
index 0000000..0f7e04d
--- /dev/null
+++ b/src/test/ui/hashmap-iter-value-lifetime.stderr
@@ -0,0 +1,15 @@
+error[E0502]: cannot borrow `my_stuff` as mutable because it is also borrowed as immutable
+  --> $DIR/hashmap-iter-value-lifetime.rs:7:5
+   |
+LL |     let (_, thing) = my_stuff.iter().next().unwrap();
+   |                      -------- immutable borrow occurs here
+LL | 
+LL |     my_stuff.clear();
+   |     ^^^^^^^^ mutable borrow occurs here
+...
+LL | }
+   | - immutable borrow ends here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/hashmap-lifetimes.nll.stderr b/src/test/ui/hashmap-lifetimes.nll.stderr
new file mode 100644
index 0000000..497c7d1
--- /dev/null
+++ b/src/test/ui/hashmap-lifetimes.nll.stderr
@@ -0,0 +1,13 @@
+error[E0502]: cannot borrow `my_stuff` as mutable because it is also borrowed as immutable
+  --> $DIR/hashmap-lifetimes.rs:6:5
+   |
+LL |     let mut it = my_stuff.iter();
+   |                  -------- immutable borrow occurs here
+LL |     my_stuff.insert(1, 43);
+   |     ^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
+LL |     it;
+   |     -- immutable borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/hashmap-lifetimes.rs b/src/test/ui/hashmap-lifetimes.rs
new file mode 100644
index 0000000..295bf3b
--- /dev/null
+++ b/src/test/ui/hashmap-lifetimes.rs
@@ -0,0 +1,8 @@
+fn main() {
+    let mut my_stuff = std::collections::HashMap::new();
+    my_stuff.insert(0, 42);
+
+    let mut it = my_stuff.iter();
+    my_stuff.insert(1, 43); //~ ERROR cannot borrow
+    it;
+}
diff --git a/src/test/ui/hashmap-lifetimes.stderr b/src/test/ui/hashmap-lifetimes.stderr
new file mode 100644
index 0000000..728946c
--- /dev/null
+++ b/src/test/ui/hashmap-lifetimes.stderr
@@ -0,0 +1,14 @@
+error[E0502]: cannot borrow `my_stuff` as mutable because it is also borrowed as immutable
+  --> $DIR/hashmap-lifetimes.rs:6:5
+   |
+LL |     let mut it = my_stuff.iter();
+   |                  -------- immutable borrow occurs here
+LL |     my_stuff.insert(1, 43);
+   |     ^^^^^^^^ mutable borrow occurs here
+LL |     it;
+LL | }
+   | - immutable borrow ends here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/hello_world/main.rs b/src/test/ui/hello_world/main.rs
new file mode 100644
index 0000000..f790af6
--- /dev/null
+++ b/src/test/ui/hello_world/main.rs
@@ -0,0 +1,7 @@
+// compile-pass
+
+// Test that compiling hello world succeeds with no output of any kind.
+
+fn main() {
+    println!("Hello, world!");
+}
diff --git a/src/test/ui/hidden-rt-injection.rs b/src/test/ui/hidden-rt-injection.rs
new file mode 100644
index 0000000..3ca04f9
--- /dev/null
+++ b/src/test/ui/hidden-rt-injection.rs
@@ -0,0 +1,8 @@
+// This is testing that users can't access the runtime crate.
+
+mod m {
+    // The rt has been called both 'native' and 'rt'
+    use native; //~ ERROR unresolved import
+}
+
+fn main() { }
diff --git a/src/test/ui/hidden-rt-injection.stderr b/src/test/ui/hidden-rt-injection.stderr
new file mode 100644
index 0000000..3e288b7
--- /dev/null
+++ b/src/test/ui/hidden-rt-injection.stderr
@@ -0,0 +1,9 @@
+error[E0432]: unresolved import `native`
+  --> $DIR/hidden-rt-injection.rs:5:9
+   |
+LL |     use native;
+   |         ^^^^^^ no `native` in the root
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/hidden-rt-injection2.rs b/src/test/ui/hidden-rt-injection2.rs
new file mode 100644
index 0000000..2af113c
--- /dev/null
+++ b/src/test/ui/hidden-rt-injection2.rs
@@ -0,0 +1,8 @@
+// This is testing that users can't access the runtime crate.
+
+mod m {
+    // The rt has been called both 'native' and 'rt'
+    use rt; //~ ERROR unresolved import
+}
+
+fn main() { }
diff --git a/src/test/ui/hidden-rt-injection2.stderr b/src/test/ui/hidden-rt-injection2.stderr
new file mode 100644
index 0000000..73f89b5
--- /dev/null
+++ b/src/test/ui/hidden-rt-injection2.stderr
@@ -0,0 +1,9 @@
+error[E0432]: unresolved import `rt`
+  --> $DIR/hidden-rt-injection2.rs:5:9
+   |
+LL |     use rt;
+   |         ^^ no `rt` in the root
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/higher-lifetime-bounds.rs b/src/test/ui/higher-lifetime-bounds.rs
new file mode 100644
index 0000000..546f4d4
--- /dev/null
+++ b/src/test/ui/higher-lifetime-bounds.rs
@@ -0,0 +1,69 @@
+#![allow(dead_code, non_camel_case_types)]
+
+// Test that bounds on higher-kinded lifetime binders are rejected.
+
+fn bar1<'a, 'b>(
+    x: &'a i32,
+    y: &'b i32,
+    f: for<'xa, 'xb: 'xa+'xa> fn(&'xa i32, &'xb i32) -> &'xa i32)
+    //~^ ERROR lifetime bounds cannot be used in this context
+{
+    // If the bound in f's type would matter, the call below would (have to)
+    // be rejected.
+    f(x, y);
+}
+
+fn bar2<'a, 'b, F: for<'xa, 'xb: 'xa> Fn(&'xa i32, &'xb i32) -> &'xa i32>(
+    //~^ ERROR lifetime bounds cannot be used in this context
+    x: &'a i32,
+    y: &'b i32,
+    f: F)
+{
+    // If the bound in f's type would matter, the call below would (have to)
+    // be rejected.
+    f(x, y);
+}
+
+fn bar3<'a, 'b, F>(
+    x: &'a i32,
+    y: &'b i32,
+    f: F)
+    where F: for<'xa, 'xb: 'xa> Fn(&'xa i32, &'xb i32) -> &'xa i32
+    //~^ ERROR lifetime bounds cannot be used in this context
+{
+    // If the bound in f's type would matter, the call below would (have to)
+    // be rejected.
+    f(x, y);
+}
+
+fn bar4<'a, 'b, F>(
+    x: &'a i32,
+    y: &'b i32,
+    f: F)
+    where for<'xa, 'xb: 'xa> F: Fn(&'xa i32, &'xb i32) -> &'xa i32
+    //~^ ERROR lifetime bounds cannot be used in this context
+{
+    // If the bound in f's type would matter, the call below would (have to)
+    // be rejected.
+    f(x, y);
+}
+
+struct S1<F: for<'xa, 'xb: 'xa> Fn(&'xa i32, &'xb i32) -> &'xa i32>(F);
+//~^ ERROR lifetime bounds cannot be used in this context
+struct S2<F>(F) where F: for<'xa, 'xb: 'xa> Fn(&'xa i32, &'xb i32) -> &'xa i32;
+//~^ ERROR lifetime bounds cannot be used in this context
+struct S3<F>(F) where for<'xa, 'xb: 'xa> F: Fn(&'xa i32, &'xb i32) -> &'xa i32;
+//~^ ERROR lifetime bounds cannot be used in this context
+
+struct S_fnty(for<'xa, 'xb: 'xa> fn(&'xa i32, &'xb i32) -> &'xa i32);
+//~^ ERROR lifetime bounds cannot be used in this context
+
+type T1 = Box<for<'xa, 'xb: 'xa> Fn(&'xa i32, &'xb i32) -> &'xa i32>;
+//~^ ERROR lifetime bounds cannot be used in this context
+
+fn main() {
+    let _ : Option<for<'xa, 'xb: 'xa> fn(&'xa i32, &'xb i32) -> &'xa i32> = None;
+    //~^ ERROR lifetime bounds cannot be used in this context
+    let _ : Option<Box<for<'xa, 'xb: 'xa> Fn(&'xa i32, &'xb i32) -> &'xa i32>> = None;
+    //~^ ERROR lifetime bounds cannot be used in this context
+}
diff --git a/src/test/ui/higher-lifetime-bounds.stderr b/src/test/ui/higher-lifetime-bounds.stderr
new file mode 100644
index 0000000..431a89f
--- /dev/null
+++ b/src/test/ui/higher-lifetime-bounds.stderr
@@ -0,0 +1,68 @@
+error: lifetime bounds cannot be used in this context
+  --> $DIR/higher-lifetime-bounds.rs:8:22
+   |
+LL |     f: for<'xa, 'xb: 'xa+'xa> fn(&'xa i32, &'xb i32) -> &'xa i32)
+   |                      ^^^ ^^^
+
+error: lifetime bounds cannot be used in this context
+  --> $DIR/higher-lifetime-bounds.rs:16:34
+   |
+LL | fn bar2<'a, 'b, F: for<'xa, 'xb: 'xa> Fn(&'xa i32, &'xb i32) -> &'xa i32>(
+   |                                  ^^^
+
+error: lifetime bounds cannot be used in this context
+  --> $DIR/higher-lifetime-bounds.rs:31:28
+   |
+LL |     where F: for<'xa, 'xb: 'xa> Fn(&'xa i32, &'xb i32) -> &'xa i32
+   |                            ^^^
+
+error: lifetime bounds cannot be used in this context
+  --> $DIR/higher-lifetime-bounds.rs:43:25
+   |
+LL |     where for<'xa, 'xb: 'xa> F: Fn(&'xa i32, &'xb i32) -> &'xa i32
+   |                         ^^^
+
+error: lifetime bounds cannot be used in this context
+  --> $DIR/higher-lifetime-bounds.rs:51:28
+   |
+LL | struct S1<F: for<'xa, 'xb: 'xa> Fn(&'xa i32, &'xb i32) -> &'xa i32>(F);
+   |                            ^^^
+
+error: lifetime bounds cannot be used in this context
+  --> $DIR/higher-lifetime-bounds.rs:53:40
+   |
+LL | struct S2<F>(F) where F: for<'xa, 'xb: 'xa> Fn(&'xa i32, &'xb i32) -> &'xa i32;
+   |                                        ^^^
+
+error: lifetime bounds cannot be used in this context
+  --> $DIR/higher-lifetime-bounds.rs:55:37
+   |
+LL | struct S3<F>(F) where for<'xa, 'xb: 'xa> F: Fn(&'xa i32, &'xb i32) -> &'xa i32;
+   |                                     ^^^
+
+error: lifetime bounds cannot be used in this context
+  --> $DIR/higher-lifetime-bounds.rs:58:29
+   |
+LL | struct S_fnty(for<'xa, 'xb: 'xa> fn(&'xa i32, &'xb i32) -> &'xa i32);
+   |                             ^^^
+
+error: lifetime bounds cannot be used in this context
+  --> $DIR/higher-lifetime-bounds.rs:61:29
+   |
+LL | type T1 = Box<for<'xa, 'xb: 'xa> Fn(&'xa i32, &'xb i32) -> &'xa i32>;
+   |                             ^^^
+
+error: lifetime bounds cannot be used in this context
+  --> $DIR/higher-lifetime-bounds.rs:65:34
+   |
+LL |     let _ : Option<for<'xa, 'xb: 'xa> fn(&'xa i32, &'xb i32) -> &'xa i32> = None;
+   |                                  ^^^
+
+error: lifetime bounds cannot be used in this context
+  --> $DIR/higher-lifetime-bounds.rs:67:38
+   |
+LL |     let _ : Option<Box<for<'xa, 'xb: 'xa> Fn(&'xa i32, &'xb i32) -> &'xa i32>> = None;
+   |                                      ^^^
+
+error: aborting due to 11 previous errors
+
diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr
new file mode 100644
index 0000000..8e2b0b8
--- /dev/null
+++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr
@@ -0,0 +1,16 @@
+error[E0308]: mismatched types
+  --> $DIR/hr-subtype.rs:39:26
+   |
+LL |               gimme::<$t1>(None::<$t2>);
+   |                            ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a
+...
+LL | / check! { bound_a_b_ret_a_vs_bound_a_ret_a: (for<'a,'b> fn(&'a u32, &'b u32) -> &'a u32,
+LL | |                                             for<'a>    fn(&'a u32, &'a u32) -> &'a u32) }
+   | |_________________________________________________________________________________________- in this macro invocation
+   |
+   = note: expected type `std::option::Option<for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32>`
+              found type `std::option::Option<for<'a> fn(&'a u32, &'a u32) -> &'a u32>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_b_vs_bound_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_vs_bound_a.stderr
new file mode 100644
index 0000000..dbb5018
--- /dev/null
+++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_vs_bound_a.stderr
@@ -0,0 +1,16 @@
+error[E0308]: mismatched types
+  --> $DIR/hr-subtype.rs:39:26
+   |
+LL |               gimme::<$t1>(None::<$t2>);
+   |                            ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a
+...
+LL | / check! { bound_a_b_vs_bound_a: (for<'a,'b> fn(&'a u32, &'b u32),
+LL | |                                 for<'a>    fn(&'a u32, &'a u32)) }
+   | |__________________________________________________________________- in this macro invocation
+   |
+   = note: expected type `std::option::Option<for<'a, 'b> fn(&'a u32, &'b u32)>`
+              found type `std::option::Option<for<'a> fn(&'a u32, &'a u32)>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr
new file mode 100644
index 0000000..9ec36f4
--- /dev/null
+++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr
@@ -0,0 +1,14 @@
+error: compilation successful
+  --> $DIR/hr-subtype.rs:100:1
+   |
+LL | / fn main() {
+LL | |
+LL | |
+LL | |
+LL | |
+LL | |
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr
new file mode 100644
index 0000000..9ec36f4
--- /dev/null
+++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr
@@ -0,0 +1,14 @@
+error: compilation successful
+  --> $DIR/hr-subtype.rs:100:1
+   |
+LL | / fn main() {
+LL | |
+LL | |
+LL | |
+LL | |
+LL | |
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr
new file mode 100644
index 0000000..db9892b
--- /dev/null
+++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr
@@ -0,0 +1,16 @@
+error[E0308]: mismatched types
+  --> $DIR/hr-subtype.rs:39:26
+   |
+LL |               gimme::<$t1>(None::<$t2>);
+   |                            ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a
+...
+LL | / check! { bound_a_vs_free_x: (for<'a> fn(&'a u32),
+LL | |                              fn(&'x u32)) }
+   | |___________________________________________- in this macro invocation
+   |
+   = note: expected type `std::option::Option<for<'a> fn(&'a u32)>`
+              found type `std::option::Option<fn(&'x u32)>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_b_vs_bound_co_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_b_vs_bound_co_a.stderr
new file mode 100644
index 0000000..e9fb734
--- /dev/null
+++ b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_b_vs_bound_co_a.stderr
@@ -0,0 +1,16 @@
+error[E0308]: mismatched types
+  --> $DIR/hr-subtype.rs:39:26
+   |
+LL |               gimme::<$t1>(None::<$t2>);
+   |                            ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a
+...
+LL | / check! { bound_co_a_b_vs_bound_co_a: (for<'a,'b> fn(Co<'a>, Co<'b>),
+LL | |                                       for<'a>    fn(Co<'a>, Co<'a>)) }
+   | |______________________________________________________________________- in this macro invocation
+   |
+   = note: expected type `std::option::Option<for<'a, 'b> fn(Co<'a>, Co<'b>)>`
+              found type `std::option::Option<for<'a> fn(Co<'a>, Co<'a>)>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_co_b_ret_contra_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_co_b_ret_contra_a.stderr
new file mode 100644
index 0000000..d0e80fa
--- /dev/null
+++ b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_co_b_ret_contra_a.stderr
@@ -0,0 +1,16 @@
+error[E0308]: mismatched types
+  --> $DIR/hr-subtype.rs:39:26
+   |
+LL |               gimme::<$t1>(None::<$t2>);
+   |                            ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a
+...
+LL | / check! { bound_co_a_co_b_ret_contra_a: (for<'a,'b> fn(Co<'a>, Co<'b>) -> Contra<'a>,
+LL | |                                         for<'a>    fn(Co<'a>, Co<'a>) -> Contra<'a>) }
+   | |______________________________________________________________________________________- in this macro invocation
+   |
+   = note: expected type `std::option::Option<for<'a, 'b> fn(Co<'a>, Co<'b>) -> Contra<'a>>`
+              found type `std::option::Option<for<'a> fn(Co<'a>, Co<'a>) -> Contra<'a>>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr
new file mode 100644
index 0000000..9ec36f4
--- /dev/null
+++ b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr
@@ -0,0 +1,14 @@
+error: compilation successful
+  --> $DIR/hr-subtype.rs:100:1
+   |
+LL | / fn main() {
+LL | |
+LL | |
+LL | |
+LL | |
+LL | |
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_contra_a_contra_b_ret_co_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_contra_a_contra_b_ret_co_a.stderr
new file mode 100644
index 0000000..3605ecf
--- /dev/null
+++ b/src/test/ui/hr-subtype/hr-subtype.bound_contra_a_contra_b_ret_co_a.stderr
@@ -0,0 +1,16 @@
+error[E0308]: mismatched types
+  --> $DIR/hr-subtype.rs:39:26
+   |
+LL |               gimme::<$t1>(None::<$t2>);
+   |                            ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a
+...
+LL | / check! { bound_contra_a_contra_b_ret_co_a: (for<'a,'b> fn(Contra<'a>, Contra<'b>) -> Co<'a>,
+LL | |                                             for<'a>    fn(Contra<'a>, Contra<'a>) -> Co<'a>) }
+   | |______________________________________________________________________________________________- in this macro invocation
+   |
+   = note: expected type `std::option::Option<for<'a, 'b> fn(Contra<'a>, Contra<'b>) -> Co<'a>>`
+              found type `std::option::Option<for<'a> fn(Contra<'a>, Contra<'a>) -> Co<'a>>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr
new file mode 100644
index 0000000..fae6e9b
--- /dev/null
+++ b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr
@@ -0,0 +1,16 @@
+error[E0308]: mismatched types
+  --> $DIR/hr-subtype.rs:39:26
+   |
+LL |               gimme::<$t1>(None::<$t2>);
+   |                            ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a
+...
+LL | / check! { bound_inv_a_b_vs_bound_inv_a: (for<'a,'b> fn(Inv<'a>, Inv<'b>),
+LL | |                                         for<'a>    fn(Inv<'a>, Inv<'a>)) }
+   | |__________________________________________________________________________- in this macro invocation
+   |
+   = note: expected type `std::option::Option<for<'a, 'b> fn(Inv<'a>, Inv<'b>)>`
+              found type `std::option::Option<for<'a> fn(Inv<'a>, Inv<'a>)>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr
new file mode 100644
index 0000000..9ec36f4
--- /dev/null
+++ b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr
@@ -0,0 +1,14 @@
+error: compilation successful
+  --> $DIR/hr-subtype.rs:100:1
+   |
+LL | / fn main() {
+LL | |
+LL | |
+LL | |
+LL | |
+LL | |
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.stderr b/src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.stderr
new file mode 100644
index 0000000..979f64f
--- /dev/null
+++ b/src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.stderr
@@ -0,0 +1,65 @@
+error[E0308]: mismatched types
+  --> $DIR/hr-subtype.rs:33:26
+   |
+LL |               gimme::<$t2>(None::<$t1>);
+   |                            ^^^^^^^^^^^ lifetime mismatch
+...
+LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>),
+LL | |                                     fn(Inv<'y>)) }
+   | |__________________________________________________- in this macro invocation
+   |
+   = note: expected type `std::option::Option<fn(Inv<'y>)>`
+              found type `std::option::Option<fn(Inv<'x>)>`
+note: the lifetime 'x as defined on the function body at 32:20...
+  --> $DIR/hr-subtype.rs:32:20
+   |
+LL |           fn subtype<'x,'y:'x,'z:'y>() {
+   |                      ^^
+...
+LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>),
+LL | |                                     fn(Inv<'y>)) }
+   | |__________________________________________________- in this macro invocation
+note: ...does not necessarily outlive the lifetime 'y as defined on the function body at 32:23
+  --> $DIR/hr-subtype.rs:32:23
+   |
+LL |           fn subtype<'x,'y:'x,'z:'y>() {
+   |                         ^^
+...
+LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>),
+LL | |                                     fn(Inv<'y>)) }
+   | |__________________________________________________- in this macro invocation
+
+error[E0308]: mismatched types
+  --> $DIR/hr-subtype.rs:39:26
+   |
+LL |               gimme::<$t1>(None::<$t2>);
+   |                            ^^^^^^^^^^^ lifetime mismatch
+...
+LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>),
+LL | |                                     fn(Inv<'y>)) }
+   | |__________________________________________________- in this macro invocation
+   |
+   = note: expected type `std::option::Option<fn(Inv<'x>)>`
+              found type `std::option::Option<fn(Inv<'y>)>`
+note: the lifetime 'x as defined on the function body at 38:22...
+  --> $DIR/hr-subtype.rs:38:22
+   |
+LL |           fn supertype<'x,'y:'x,'z:'y>() {
+   |                        ^^
+...
+LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>),
+LL | |                                     fn(Inv<'y>)) }
+   | |__________________________________________________- in this macro invocation
+note: ...does not necessarily outlive the lifetime 'y as defined on the function body at 38:25
+  --> $DIR/hr-subtype.rs:38:25
+   |
+LL |           fn supertype<'x,'y:'x,'z:'y>() {
+   |                           ^^
+...
+LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>),
+LL | |                                     fn(Inv<'y>)) }
+   | |__________________________________________________- in this macro invocation
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr b/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr
new file mode 100644
index 0000000..9ec36f4
--- /dev/null
+++ b/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr
@@ -0,0 +1,14 @@
+error: compilation successful
+  --> $DIR/hr-subtype.rs:100:1
+   |
+LL | / fn main() {
+LL | |
+LL | |
+LL | |
+LL | |
+LL | |
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.stderr b/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.stderr
new file mode 100644
index 0000000..3b6aff5
--- /dev/null
+++ b/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.stderr
@@ -0,0 +1,34 @@
+error[E0308]: mismatched types
+  --> $DIR/hr-subtype.rs:39:26
+   |
+LL |               gimme::<$t1>(None::<$t2>);
+   |                            ^^^^^^^^^^^ lifetime mismatch
+...
+LL | / check! { free_x_vs_free_y: (fn(&'x u32),
+LL | |                             fn(&'y u32)) }
+   | |__________________________________________- in this macro invocation
+   |
+   = note: expected type `std::option::Option<fn(&'x u32)>`
+              found type `std::option::Option<fn(&'y u32)>`
+note: the lifetime 'x as defined on the function body at 38:22...
+  --> $DIR/hr-subtype.rs:38:22
+   |
+LL |           fn supertype<'x,'y:'x,'z:'y>() {
+   |                        ^^
+...
+LL | / check! { free_x_vs_free_y: (fn(&'x u32),
+LL | |                             fn(&'y u32)) }
+   | |__________________________________________- in this macro invocation
+note: ...does not necessarily outlive the lifetime 'y as defined on the function body at 38:25
+  --> $DIR/hr-subtype.rs:38:25
+   |
+LL |           fn supertype<'x,'y:'x,'z:'y>() {
+   |                           ^^
+...
+LL | / check! { free_x_vs_free_y: (fn(&'x u32),
+LL | |                             fn(&'y u32)) }
+   | |__________________________________________- in this macro invocation
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/hr-subtype/hr-subtype.rs b/src/test/ui/hr-subtype/hr-subtype.rs
new file mode 100644
index 0000000..2f7c1e6
--- /dev/null
+++ b/src/test/ui/hr-subtype/hr-subtype.rs
@@ -0,0 +1,106 @@
+// Targeted tests for the higher-ranked subtyping code.
+
+#![feature(rustc_attrs)]
+#![allow(dead_code)]
+
+// revisions: bound_a_vs_bound_a
+// revisions: bound_a_vs_bound_b
+// revisions: bound_inv_a_vs_bound_inv_b
+// revisions: bound_co_a_vs_bound_co_b
+// revisions: bound_a_vs_free_x
+// revisions: free_x_vs_free_x
+// revisions: free_x_vs_free_y
+// revisions: free_inv_x_vs_free_inv_y
+// revisions: bound_a_b_vs_bound_a
+// revisions: bound_co_a_b_vs_bound_co_a
+// revisions: bound_contra_a_contra_b_ret_co_a
+// revisions: bound_co_a_co_b_ret_contra_a
+// revisions: bound_inv_a_b_vs_bound_inv_a
+// revisions: bound_a_b_ret_a_vs_bound_a_ret_a
+
+fn gimme<T>(_: Option<T>) { }
+
+struct Inv<'a> { x: *mut &'a u32 }
+
+struct Co<'a> { x: fn(&'a u32) }
+
+struct Contra<'a> { x: &'a u32 }
+
+macro_rules! check {
+    ($rev:ident: ($t1:ty, $t2:ty)) => {
+        #[cfg($rev)]
+        fn subtype<'x,'y:'x,'z:'y>() {
+            gimme::<$t2>(None::<$t1>);
+            //[free_inv_x_vs_free_inv_y]~^ ERROR
+        }
+
+        #[cfg($rev)]
+        fn supertype<'x,'y:'x,'z:'y>() {
+            gimme::<$t1>(None::<$t2>);
+            //[bound_a_vs_free_x]~^ ERROR
+            //[free_x_vs_free_y]~^^ ERROR
+            //[bound_inv_a_b_vs_bound_inv_a]~^^^ ERROR
+            //[bound_a_b_ret_a_vs_bound_a_ret_a]~^^^^ ERROR
+            //[free_inv_x_vs_free_inv_y]~^^^^^ ERROR
+            //[bound_a_b_vs_bound_a]~^^^^^^ ERROR mismatched types
+            //[bound_co_a_co_b_ret_contra_a]~^^^^^^^ ERROR
+            //[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^ ERROR
+            //[bound_co_a_b_vs_bound_co_a]~^^^^^^^^^ ERROR
+        }
+    }
+}
+
+// If both have bound regions, they are equivalent, regardless of
+// variant.
+check! { bound_a_vs_bound_a: (for<'a> fn(&'a u32),
+                              for<'a> fn(&'a u32)) }
+check! { bound_a_vs_bound_b: (for<'a> fn(&'a u32),
+                              for<'b> fn(&'b u32)) }
+check! { bound_inv_a_vs_bound_inv_b: (for<'a> fn(Inv<'a>),
+                                      for<'b> fn(Inv<'b>)) }
+check! { bound_co_a_vs_bound_co_b: (for<'a> fn(Co<'a>),
+                                    for<'b> fn(Co<'b>)) }
+
+// Bound is a subtype of free.
+check! { bound_a_vs_free_x: (for<'a> fn(&'a u32),
+                             fn(&'x u32)) }
+
+// Two free regions are relatable if subtyping holds.
+check! { free_x_vs_free_x: (fn(&'x u32),
+                            fn(&'x u32)) }
+check! { free_x_vs_free_y: (fn(&'x u32),
+                            fn(&'y u32)) }
+check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>),
+                                    fn(Inv<'y>)) }
+
+// Somewhat surprisingly, a fn taking two distinct bound lifetimes and
+// a fn taking one bound lifetime can be interchangeable, but only if
+// we are co- or contra-variant with respect to both lifetimes.
+//
+// The reason is:
+// - if we are covariant, then 'a and 'b can be set to the call-site
+//   intersection;
+// - if we are contravariant, then 'a can be inferred to 'static.
+check! { bound_a_b_vs_bound_a: (for<'a,'b> fn(&'a u32, &'b u32),
+                                for<'a>    fn(&'a u32, &'a u32)) }
+check! { bound_co_a_b_vs_bound_co_a: (for<'a,'b> fn(Co<'a>, Co<'b>),
+                                      for<'a>    fn(Co<'a>, Co<'a>)) }
+check! { bound_contra_a_contra_b_ret_co_a: (for<'a,'b> fn(Contra<'a>, Contra<'b>) -> Co<'a>,
+                                            for<'a>    fn(Contra<'a>, Contra<'a>) -> Co<'a>) }
+check! { bound_co_a_co_b_ret_contra_a: (for<'a,'b> fn(Co<'a>, Co<'b>) -> Contra<'a>,
+                                        for<'a>    fn(Co<'a>, Co<'a>) -> Contra<'a>) }
+
+// If we make those lifetimes invariant, then the two types are not interchangeable.
+check! { bound_inv_a_b_vs_bound_inv_a: (for<'a,'b> fn(Inv<'a>, Inv<'b>),
+                                        for<'a>    fn(Inv<'a>, Inv<'a>)) }
+check! { bound_a_b_ret_a_vs_bound_a_ret_a: (for<'a,'b> fn(&'a u32, &'b u32) -> &'a u32,
+                                            for<'a>    fn(&'a u32, &'a u32) -> &'a u32) }
+
+#[rustc_error]
+fn main() {
+//[bound_a_vs_bound_a]~^ ERROR compilation successful
+//[bound_a_vs_bound_b]~^^ ERROR compilation successful
+//[bound_inv_a_vs_bound_inv_b]~^^^ ERROR compilation successful
+//[bound_co_a_vs_bound_co_b]~^^^^ ERROR compilation successful
+//[free_x_vs_free_x]~^^^^^ ERROR compilation successful
+}
diff --git a/src/test/ui/hrtb/hrtb-cache-issue-54302.rs b/src/test/ui/hrtb/hrtb-cache-issue-54302.rs
new file mode 100644
index 0000000..a20d03c
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-cache-issue-54302.rs
@@ -0,0 +1,24 @@
+// Regression test for #54302.
+//
+// We were incorrectly using the "evaluation cache" (which ignored
+// region results) to conclude that `&'static str: Deserialize`, even
+// though it would require that `for<'de> 'de: 'static`, which is
+// clearly false.
+
+trait Deserialize<'de> {}
+
+trait DeserializeOwned: for<'de> Deserialize<'de> {}
+impl<T> DeserializeOwned for T where T: for<'de> Deserialize<'de> {}
+
+// Based on this impl, `&'static str` only implements Deserialize<'static>.
+// It does not implement for<'de> Deserialize<'de>.
+impl<'de: 'a, 'a> Deserialize<'de> for &'a str {}
+
+fn main() {
+    fn assert_deserialize_owned<T: DeserializeOwned>() {}
+    assert_deserialize_owned::<&'static str>(); //~ ERROR
+
+    // It correctly does not implement for<'de> Deserialize<'de>.
+    // fn assert_hrtb<T: for<'de> Deserialize<'de>>() {}
+    // assert_hrtb::<&'static str>();
+}
diff --git a/src/test/ui/hrtb/hrtb-cache-issue-54302.stderr b/src/test/ui/hrtb/hrtb-cache-issue-54302.stderr
new file mode 100644
index 0000000..77a5491
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-cache-issue-54302.stderr
@@ -0,0 +1,11 @@
+error: implementation of `Deserialize` is not general enough
+  --> $DIR/hrtb-cache-issue-54302.rs:19:5
+   |
+LL |     assert_deserialize_owned::<&'static str>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `&'static str` must implement `Deserialize<'0>`, for any lifetime `'0`
+   = note: but `&str` actually implements `Deserialize<'1>`, for some specific lifetime `'1`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/hrtb/hrtb-conflate-regions.rs b/src/test/ui/hrtb/hrtb-conflate-regions.rs
new file mode 100644
index 0000000..3913036
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-conflate-regions.rs
@@ -0,0 +1,30 @@
+// Test that an impl with only one bound region `'a` cannot be used to
+// satisfy a constraint where there are two bound regions.
+
+trait Foo<X> {
+    fn foo(&self, x: X) { }
+}
+
+fn want_foo2<T>()
+    where T : for<'a,'b> Foo<(&'a isize, &'b isize)>
+{
+}
+
+fn want_foo1<T>()
+    where T : for<'z> Foo<(&'z isize, &'z isize)>
+{
+}
+
+///////////////////////////////////////////////////////////////////////////
+// Expressed as a where clause
+
+struct SomeStruct;
+
+impl<'a> Foo<(&'a isize, &'a isize)> for SomeStruct
+{
+}
+
+fn a() { want_foo1::<SomeStruct>(); } // OK -- foo wants just one region
+fn b() { want_foo2::<SomeStruct>(); } //~ ERROR
+
+fn main() { }
diff --git a/src/test/ui/hrtb/hrtb-conflate-regions.stderr b/src/test/ui/hrtb/hrtb-conflate-regions.stderr
new file mode 100644
index 0000000..3fb6baa
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-conflate-regions.stderr
@@ -0,0 +1,20 @@
+error[E0277]: the trait bound `for<'a, 'b> SomeStruct: Foo<(&'a isize, &'b isize)>` is not satisfied
+  --> $DIR/hrtb-conflate-regions.rs:28:10
+   |
+LL | fn b() { want_foo2::<SomeStruct>(); }
+   |          ^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a, 'b> Foo<(&'a isize, &'b isize)>` is not implemented for `SomeStruct`
+   |
+   = help: the following implementations were found:
+             <SomeStruct as Foo<(&'a isize, &'a isize)>>
+note: required by `want_foo2`
+  --> $DIR/hrtb-conflate-regions.rs:8:1
+   |
+LL | / fn want_foo2<T>()
+LL | |     where T : for<'a,'b> Foo<(&'a isize, &'b isize)>
+LL | | {
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/hrtb/hrtb-debruijn-in-receiver.nll.stderr b/src/test/ui/hrtb/hrtb-debruijn-in-receiver.nll.stderr
new file mode 100644
index 0000000..70d5b3c
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-debruijn-in-receiver.nll.stderr
@@ -0,0 +1,14 @@
+error[E0499]: cannot borrow `foo` as mutable more than once at a time
+  --> $DIR/hrtb-debruijn-in-receiver.rs:17:5
+   |
+LL |     foo.insert();
+   |     --- first mutable borrow occurs here
+LL |     foo.insert();
+   |     ^^^
+   |     |
+   |     second mutable borrow occurs here
+   |     first borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/hrtb/hrtb-debruijn-in-receiver.rs b/src/test/ui/hrtb/hrtb-debruijn-in-receiver.rs
new file mode 100644
index 0000000..05d3e1a
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-debruijn-in-receiver.rs
@@ -0,0 +1,18 @@
+// Test the case where the `Self` type has a bound lifetime that must
+// be adjusted in the fn signature. Issue #19537.
+
+use std::collections::HashMap;
+
+struct Foo<'a> {
+    map: HashMap<usize, &'a str>
+}
+
+impl<'a> Foo<'a> {
+    fn new() -> Foo<'a> { panic!() }
+    fn insert(&'a mut self) { }
+}
+fn main() {
+    let mut foo = Foo::new();
+    foo.insert();
+    foo.insert(); //~ ERROR cannot borrow
+}
diff --git a/src/test/ui/hrtb/hrtb-debruijn-in-receiver.stderr b/src/test/ui/hrtb/hrtb-debruijn-in-receiver.stderr
new file mode 100644
index 0000000..e498a9a
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-debruijn-in-receiver.stderr
@@ -0,0 +1,13 @@
+error[E0499]: cannot borrow `foo` as mutable more than once at a time
+  --> $DIR/hrtb-debruijn-in-receiver.rs:17:5
+   |
+LL |     foo.insert();
+   |     --- first mutable borrow occurs here
+LL |     foo.insert();
+   |     ^^^ second mutable borrow occurs here
+LL | }
+   | - first borrow ends here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/hrtb/hrtb-exists-forall-fn.rs b/src/test/ui/hrtb/hrtb-exists-forall-fn.rs
new file mode 100644
index 0000000..828331c
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-exists-forall-fn.rs
@@ -0,0 +1,18 @@
+// Test a `exists<'a> { forall<'b> { 'a = 'b } }` pattern -- which should not compile!
+//
+// In particular, we test this pattern in trait solving, where it is not connected
+// to any part of the source code.
+
+fn foo<'a>() -> fn(&'a u32) {
+    panic!()
+}
+
+fn main() {
+    // Here, proving that `fn(&'a u32) <: for<'b> fn(&'b u32)`:
+    //
+    // - instantiates `'b` with a placeholder `!b`,
+    // - requires that `&!b u32 <: &'a u32` and hence that `!b: 'a`,
+    // - but we can never know this.
+
+    let _: for<'b> fn(&'b u32) = foo(); //~ ERROR mismatched types
+}
diff --git a/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr b/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr
new file mode 100644
index 0000000..d893cd6
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/hrtb-exists-forall-fn.rs:17:34
+   |
+LL |     let _: for<'b> fn(&'b u32) = foo();
+   |                                  ^^^^^ expected concrete lifetime, found bound lifetime parameter 'b
+   |
+   = note: expected type `for<'b> fn(&'b u32)`
+              found type `fn(&u32)`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs
new file mode 100644
index 0000000..4c1d4d2
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs
@@ -0,0 +1,36 @@
+// Test a case where variance and higher-ranked types interact in surprising ways.
+//
+// In particular, we test this pattern in trait solving, where it is not connected
+// to any part of the source code.
+
+trait Trait<T> {}
+
+fn foo<T>()
+where
+    T: Trait<for<'b> fn(&'b u32)>,
+{
+}
+
+impl<'a> Trait<fn(&'a u32)> for () {}
+
+fn main() {
+    // Here, proving that `(): Trait<for<'b> fn(&'b u32)>` uses the impl:
+    //
+    // - The impl provides the clause `forall<'a> { (): Trait<fn(&'a u32)> }`
+    // - We instantiate `'a` existentially to get `(): Trait<fn(&?a u32)>`
+    // - We unify `fn(&?a u32)` with `for<'b> fn(&'b u32)` -- this does a
+    //   "bidirectional" subtyping check, so we wind up with:
+    //   - `fn(&?a u32) <: for<'b> fn(&'b u32)` :-
+    //     - `&'!b u32 <: &?a u32`
+    //     - `!'b: ?a` -- solveable if `?a` is inferred to `'empty`
+    //   - `for<'b> fn(&'b u32) <: fn(&?a u32)` :-
+    //     - `&?a u32 u32 <: &?b u32`
+    //     - `?a: ?b` -- solveable if `?b` is also inferred to `'empty`
+    // - So the subtyping check succeeds, somewhat surprisingly.
+    //   This is because we can use `'empty`.
+    //
+    // NB. *However*, the reinstated leak-check gives an error here.
+
+    foo::<()>();
+    //~^ ERROR not satisfied
+}
diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr
new file mode 100644
index 0000000..7f2ca03
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr
@@ -0,0 +1,21 @@
+error[E0277]: the trait bound `(): Trait<for<'b> fn(&'b u32)>` is not satisfied
+  --> $DIR/hrtb-exists-forall-trait-contravariant.rs:34:5
+   |
+LL |     foo::<()>();
+   |     ^^^^^^^^^ the trait `Trait<for<'b> fn(&'b u32)>` is not implemented for `()`
+   |
+   = help: the following implementations were found:
+             <() as Trait<fn(&'a u32)>>
+note: required by `foo`
+  --> $DIR/hrtb-exists-forall-trait-contravariant.rs:8:1
+   |
+LL | / fn foo<T>()
+LL | | where
+LL | |     T: Trait<for<'b> fn(&'b u32)>,
+LL | | {
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.rs b/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.rs
new file mode 100644
index 0000000..95b57d6
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.rs
@@ -0,0 +1,38 @@
+// Test a case where variance and higher-ranked types interact in surprising ways.
+//
+// In particular, we test this pattern in trait solving, where it is not connected
+// to any part of the source code.
+
+trait Trait<T> {}
+
+fn foo<T>()
+where
+    T: Trait<for<'b> fn(fn(&'b u32))>,
+{
+}
+
+impl<'a> Trait<fn(fn(&'a u32))> for () {}
+
+fn main() {
+    // Here, proving that `(): Trait<for<'b> fn(&'b u32)>` uses the impl:
+    //
+    // - The impl provides the clause `forall<'a> { (): Trait<fn(fn(&'a u32))> }`
+    // - We instantiate `'a` existentially to get `(): Trait<fn(fn(&?a u32))>`
+    // - We unify `fn(fn(&?a u32))` with `for<'b> fn(fn(&'b u32))` -- this does a
+    //   "bidirectional" subtyping check, so we wind up with:
+    //   - `fn(fn(&?a u32)) <: for<'b> fn(fn(&'b u32))` :-
+    //     - `fn(&!b u32) <: fn(&?a u32)`
+    //       - `&?a u32 <: &!b u32`
+    //         - `?a: !'b` -- solveable if `?a` is inferred to `'static`
+    //   - `for<'b> fn(fn(&'b u32)) <: fn(fn(&?a u32))` :-
+    //     - `fn(&?a u32) <: fn(&?b u32)`
+    //       - `&?b u32 <: &?a u32`
+    //         - `?b: ?a` -- solveable if `?b` is inferred to `'static`
+    // - So the subtyping check succeeds, somewhat surprisingly.
+    //   This is because we can use `'static`.
+    //
+    // NB. *However*, the reinstated leak-check gives an error here.
+
+    foo::<()>();
+    //~^ ERROR not satisfied
+}
diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.stderr b/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.stderr
new file mode 100644
index 0000000..cd5982e
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.stderr
@@ -0,0 +1,21 @@
+error[E0277]: the trait bound `(): Trait<for<'b> fn(fn(&'b u32))>` is not satisfied
+  --> $DIR/hrtb-exists-forall-trait-covariant.rs:36:5
+   |
+LL |     foo::<()>();
+   |     ^^^^^^^^^ the trait `Trait<for<'b> fn(fn(&'b u32))>` is not implemented for `()`
+   |
+   = help: the following implementations were found:
+             <() as Trait<fn(fn(&'a u32))>>
+note: required by `foo`
+  --> $DIR/hrtb-exists-forall-trait-covariant.rs:8:1
+   |
+LL | / fn foo<T>()
+LL | | where
+LL | |     T: Trait<for<'b> fn(fn(&'b u32))>,
+LL | | {
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.rs b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.rs
new file mode 100644
index 0000000..827a68b
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.rs
@@ -0,0 +1,29 @@
+// Test a `exists<'a> { forall<'b> { 'a = 'b } }` pattern -- which should not compile!
+//
+// In particular, we test this pattern in trait solving, where it is not connected
+// to any part of the source code.
+
+use std::cell::Cell;
+
+trait Trait<T> {}
+
+fn foo<T>()
+where
+    T: Trait<for<'b> fn(Cell<&'b u32>)>,
+{
+}
+
+impl<'a> Trait<fn(Cell<&'a u32>)> for () {}
+
+fn main() {
+    // Here, proving that `(): Trait<for<'b> fn(&'b u32)>` uses the impl:
+    //
+    // - The impl provides the clause `forall<'a> { (): Trait<fn(&'a u32)> }`
+    // - We instantiate `'a` existentially to get `(): Trait<fn(&?a u32)>`
+    // - We unify `fn(&?a u32)` with `for<'b> fn(&'b u32)`
+    //   - This requires (among other things) instantiating `'b` universally,
+    //     yielding `fn(&!b u32)`, in a fresh universe U1
+    //   - So we get `?a = !b` but the universe U0 assigned to `?a` cannot name `!b`.
+
+    foo::<()>(); //~ ERROR not satisfied
+}
diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr
new file mode 100644
index 0000000..f10e427
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr
@@ -0,0 +1,21 @@
+error[E0277]: the trait bound `(): Trait<for<'b> fn(std::cell::Cell<&'b u32>)>` is not satisfied
+  --> $DIR/hrtb-exists-forall-trait-invariant.rs:28:5
+   |
+LL |     foo::<()>();
+   |     ^^^^^^^^^ the trait `Trait<for<'b> fn(std::cell::Cell<&'b u32>)>` is not implemented for `()`
+   |
+   = help: the following implementations were found:
+             <() as Trait<fn(std::cell::Cell<&'a u32>)>>
+note: required by `foo`
+  --> $DIR/hrtb-exists-forall-trait-invariant.rs:10:1
+   |
+LL | / fn foo<T>()
+LL | | where
+LL | |     T: Trait<for<'b> fn(Cell<&'b u32>)>,
+LL | | {
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.rs b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.rs
new file mode 100644
index 0000000..f9ae142
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.rs
@@ -0,0 +1,50 @@
+// Test HRTB supertraits with several levels of expansion required.
+
+trait Foo<'tcx>
+{
+    fn foo(&'tcx self) -> &'tcx isize;
+}
+
+trait Bar<'ccx>
+    : for<'tcx> Foo<'tcx>
+{
+    fn bar(&'ccx self) -> &'ccx isize;
+}
+
+trait Baz
+    : for<'ccx> Bar<'ccx>
+{
+    fn dummy(&self);
+}
+
+trait Qux
+    : Bar<'static>
+{
+    fn dummy(&self);
+}
+
+fn want_foo_for_any_tcx<F>(f: &F)
+    where F : for<'tcx> Foo<'tcx>
+{
+}
+
+fn want_bar_for_any_ccx<B>(b: &B)
+    where B : for<'ccx> Bar<'ccx>
+{
+}
+
+fn want_baz<B>(b: &B)
+    where B : Baz
+{
+    want_foo_for_any_tcx(b);
+    want_bar_for_any_ccx(b);
+}
+
+fn want_qux<B>(b: &B)
+    where B : Qux
+{
+    want_foo_for_any_tcx(b);
+    want_bar_for_any_ccx(b); //~ ERROR
+}
+
+fn main() {}
diff --git a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr
new file mode 100644
index 0000000..b5d945f
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr
@@ -0,0 +1,19 @@
+error[E0277]: the trait bound `for<'ccx> B: Bar<'ccx>` is not satisfied
+  --> $DIR/hrtb-higher-ranker-supertraits-transitive.rs:47:5
+   |
+LL |     want_bar_for_any_ccx(b);
+   |     ^^^^^^^^^^^^^^^^^^^^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B`
+   |
+   = help: consider adding a `where for<'ccx> B: Bar<'ccx>` bound
+note: required by `want_bar_for_any_ccx`
+  --> $DIR/hrtb-higher-ranker-supertraits-transitive.rs:31:1
+   |
+LL | / fn want_bar_for_any_ccx<B>(b: &B)
+LL | |     where B : for<'ccx> Bar<'ccx>
+LL | | {
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.rs b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.rs
new file mode 100644
index 0000000..48ebe50
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.rs
@@ -0,0 +1,48 @@
+// Test a trait (`Bar`) with a higher-ranked supertrait.
+
+trait Foo<'tcx>
+{
+    fn foo(&'tcx self) -> &'tcx isize;
+}
+
+trait Bar<'ccx>
+    : for<'tcx> Foo<'tcx>
+{
+    fn bar(&'ccx self) -> &'ccx isize;
+}
+
+fn want_foo_for_some_tcx<'x,F>(f: &'x F)
+    where F : Foo<'x>
+{
+    want_foo_for_some_tcx(f);
+    want_foo_for_any_tcx(f); //~ ERROR not satisfied
+}
+
+fn want_foo_for_any_tcx<F>(f: &F)
+    where F : for<'tcx> Foo<'tcx>
+{
+    want_foo_for_some_tcx(f);
+    want_foo_for_any_tcx(f);
+}
+
+fn want_bar_for_some_ccx<'x,B>(b: &B)
+    where B : Bar<'x>
+{
+    want_foo_for_some_tcx(b);
+    want_foo_for_any_tcx(b);
+
+    want_bar_for_some_ccx(b);
+    want_bar_for_any_ccx(b); //~ ERROR not satisfied
+}
+
+fn want_bar_for_any_ccx<B>(b: &B)
+    where B : for<'ccx> Bar<'ccx>
+{
+    want_foo_for_some_tcx(b);
+    want_foo_for_any_tcx(b);
+
+    want_bar_for_some_ccx(b);
+    want_bar_for_any_ccx(b);
+}
+
+fn main() {}
diff --git a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr
new file mode 100644
index 0000000..20a8fd4
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr
@@ -0,0 +1,40 @@
+error[E0277]: the trait bound `for<'tcx> F: Foo<'tcx>` is not satisfied
+  --> $DIR/hrtb-higher-ranker-supertraits.rs:18:5
+   |
+LL |     want_foo_for_any_tcx(f);
+   |     ^^^^^^^^^^^^^^^^^^^^ the trait `for<'tcx> Foo<'tcx>` is not implemented for `F`
+   |
+   = help: consider adding a `where for<'tcx> F: Foo<'tcx>` bound
+note: required by `want_foo_for_any_tcx`
+  --> $DIR/hrtb-higher-ranker-supertraits.rs:21:1
+   |
+LL | / fn want_foo_for_any_tcx<F>(f: &F)
+LL | |     where F : for<'tcx> Foo<'tcx>
+LL | | {
+LL | |     want_foo_for_some_tcx(f);
+LL | |     want_foo_for_any_tcx(f);
+LL | | }
+   | |_^
+
+error[E0277]: the trait bound `for<'ccx> B: Bar<'ccx>` is not satisfied
+  --> $DIR/hrtb-higher-ranker-supertraits.rs:35:5
+   |
+LL |     want_bar_for_any_ccx(b);
+   |     ^^^^^^^^^^^^^^^^^^^^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B`
+   |
+   = help: consider adding a `where for<'ccx> B: Bar<'ccx>` bound
+note: required by `want_bar_for_any_ccx`
+  --> $DIR/hrtb-higher-ranker-supertraits.rs:38:1
+   |
+LL | / fn want_bar_for_any_ccx<B>(b: &B)
+LL | |     where B : for<'ccx> Bar<'ccx>
+LL | | {
+LL | |     want_foo_for_some_tcx(b);
+...  |
+LL | |     want_bar_for_any_ccx(b);
+LL | | }
+   | |_^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/hrtb/hrtb-identity-fn-borrows.ast.nll.stderr b/src/test/ui/hrtb/hrtb-identity-fn-borrows.ast.nll.stderr
new file mode 100644
index 0000000..2b69b3f
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-identity-fn-borrows.ast.nll.stderr
@@ -0,0 +1,14 @@
+error[E0506]: cannot assign to `x` because it is borrowed
+  --> $DIR/hrtb-identity-fn-borrows.rs:17:5
+   |
+LL |     let y = f.call(&x);
+   |                    -- borrow of `x` occurs here
+LL |     x = 5;
+   |     ^^^^^ assignment to borrowed `x` occurs here
+...
+LL |     drop(y);
+   |          - borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/hrtb/hrtb-identity-fn-borrows.ast.stderr b/src/test/ui/hrtb/hrtb-identity-fn-borrows.ast.stderr
new file mode 100644
index 0000000..6f055aa
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-identity-fn-borrows.ast.stderr
@@ -0,0 +1,11 @@
+error[E0506]: cannot assign to `x` because it is borrowed
+  --> $DIR/hrtb-identity-fn-borrows.rs:17:5
+   |
+LL |     let y = f.call(&x);
+   |                     - borrow of `x` occurs here
+LL |     x = 5;
+   |     ^^^^^ assignment to borrowed `x` occurs here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/hrtb/hrtb-identity-fn-borrows.mir.stderr b/src/test/ui/hrtb/hrtb-identity-fn-borrows.mir.stderr
new file mode 100644
index 0000000..2b69b3f
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-identity-fn-borrows.mir.stderr
@@ -0,0 +1,14 @@
+error[E0506]: cannot assign to `x` because it is borrowed
+  --> $DIR/hrtb-identity-fn-borrows.rs:17:5
+   |
+LL |     let y = f.call(&x);
+   |                    -- borrow of `x` occurs here
+LL |     x = 5;
+   |     ^^^^^ assignment to borrowed `x` occurs here
+...
+LL |     drop(y);
+   |          - borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/hrtb/hrtb-identity-fn-borrows.rs b/src/test/ui/hrtb/hrtb-identity-fn-borrows.rs
new file mode 100644
index 0000000..35b39a9
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-identity-fn-borrows.rs
@@ -0,0 +1,30 @@
+// Test that the `'a` in the where clause correctly links the region
+// of the output to the region of the input.
+
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+trait FnLike<A,R> {
+    fn call(&self, arg: A) -> R;
+}
+
+fn call_repeatedly<F>(f: F)
+    where F : for<'a> FnLike<&'a isize, &'a isize>
+{
+    // Result is stored: cannot re-assign `x`
+    let mut x = 3;
+    let y = f.call(&x);
+    x = 5; //[ast]~ ERROR cannot assign
+           //[mir]~^ ERROR cannot assign to `x` because it is borrowed
+
+    // Result is not stored: can re-assign `x`
+    let mut x = 3;
+    f.call(&x);
+    f.call(&x);
+    f.call(&x);
+    x = 5;
+    drop(y);
+}
+
+fn main() {
+}
diff --git a/src/test/ui/hrtb/hrtb-just-for-static.rs b/src/test/ui/hrtb/hrtb-just-for-static.rs
new file mode 100644
index 0000000..88d5ce8
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-just-for-static.rs
@@ -0,0 +1,33 @@
+// Test a case where you have an impl of `Foo<X>` for all `X` that
+// is being applied to `for<'a> Foo<&'a mut X>`. Issue #19730.
+
+trait Foo<X> {
+    fn foo(&self, x: X) { }
+}
+
+fn want_hrtb<T>()
+    where T : for<'a> Foo<&'a isize>
+{
+}
+
+// AnyInt implements Foo<&'a isize> for any 'a, so it is a match.
+struct AnyInt;
+impl<'a> Foo<&'a isize> for AnyInt { }
+fn give_any() {
+    want_hrtb::<AnyInt>()
+}
+
+// StaticInt only implements Foo<&'static isize>, so it is an error.
+struct StaticInt;
+impl Foo<&'static isize> for StaticInt { }
+fn give_static() {
+    want_hrtb::<StaticInt>() //~ ERROR
+}
+
+// AnyInt implements Foo<&'a isize> for any 'a, so it is a match.
+impl<'a> Foo<&'a isize> for &'a u32 { }
+fn give_some<'a>() {
+    want_hrtb::<&'a u32>() //~ ERROR
+}
+
+fn main() { }
diff --git a/src/test/ui/hrtb/hrtb-just-for-static.stderr b/src/test/ui/hrtb/hrtb-just-for-static.stderr
new file mode 100644
index 0000000..115851d
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-just-for-static.stderr
@@ -0,0 +1,37 @@
+error[E0277]: the trait bound `for<'a> StaticInt: Foo<&'a isize>` is not satisfied
+  --> $DIR/hrtb-just-for-static.rs:24:5
+   |
+LL |     want_hrtb::<StaticInt>()
+   |     ^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Foo<&'a isize>` is not implemented for `StaticInt`
+   |
+   = help: the following implementations were found:
+             <StaticInt as Foo<&'static isize>>
+note: required by `want_hrtb`
+  --> $DIR/hrtb-just-for-static.rs:8:1
+   |
+LL | / fn want_hrtb<T>()
+LL | |     where T : for<'a> Foo<&'a isize>
+LL | | {
+LL | | }
+   | |_^
+
+error[E0277]: the trait bound `for<'a> &'a u32: Foo<&'a isize>` is not satisfied
+  --> $DIR/hrtb-just-for-static.rs:30:5
+   |
+LL |     want_hrtb::<&'a u32>()
+   |     ^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Foo<&'a isize>` is not implemented for `&'a u32`
+   |
+   = help: the following implementations were found:
+             <&'a u32 as Foo<&'a isize>>
+note: required by `want_hrtb`
+  --> $DIR/hrtb-just-for-static.rs:8:1
+   |
+LL | / fn want_hrtb<T>()
+LL | |     where T : for<'a> Foo<&'a isize>
+LL | | {
+LL | | }
+   | |_^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/hrtb/hrtb-perfect-forwarding.rs b/src/test/ui/hrtb/hrtb-perfect-forwarding.rs
new file mode 100644
index 0000000..63db695
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-perfect-forwarding.rs
@@ -0,0 +1,56 @@
+// Test a case where you have an impl of `Foo<X>` for all `X` that
+// is being applied to `for<'a> Foo<&'a mut X>`. Issue #19730.
+
+trait Foo<X> {
+    fn foo(&mut self, x: X) { }
+}
+
+trait Bar<X> {
+    fn bar(&mut self, x: X) { }
+}
+
+impl<'a,X,F> Foo<X> for &'a mut F
+    where F : Foo<X> + Bar<X>
+{
+}
+
+impl<'a,X,F> Bar<X> for &'a mut F
+    where F : Bar<X>
+{
+}
+
+fn no_hrtb<'b,T>(mut t: T)
+    where T : Bar<&'b isize>
+{
+    // OK -- `T : Bar<&'b isize>`, and thus the impl above ensures that
+    // `&mut T : Bar<&'b isize>`.
+    no_hrtb(&mut t);
+}
+
+fn bar_hrtb<T>(mut t: T)
+    where T : for<'b> Bar<&'b isize>
+{
+    // OK -- `T : for<'b> Bar<&'b isize>`, and thus the impl above
+    // ensures that `&mut T : for<'b> Bar<&'b isize>`.  This is an
+    // example of a "perfect forwarding" impl.
+    bar_hrtb(&mut t);
+}
+
+fn foo_hrtb_bar_not<'b,T>(mut t: T)
+    where T : for<'a> Foo<&'a isize> + Bar<&'b isize>
+{
+    // Not OK -- The forwarding impl for `Foo` requires that `Bar` also
+    // be implemented. Thus to satisfy `&mut T : for<'a> Foo<&'a
+    // isize>`, we require `T : for<'a> Bar<&'a isize>`, but the where
+    // clause only specifies `T : Bar<&'b isize>`.
+    foo_hrtb_bar_not(&mut t); //~ ERROR mismatched types
+}
+
+fn foo_hrtb_bar_hrtb<T>(mut t: T)
+    where T : for<'a> Foo<&'a isize> + for<'b> Bar<&'b isize>
+{
+    // OK -- now we have `T : for<'b> Bar&'b isize>`.
+    foo_hrtb_bar_hrtb(&mut t);
+}
+
+fn main() { }
diff --git a/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr b/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr
new file mode 100644
index 0000000..9bc8cd6
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/hrtb-perfect-forwarding.rs:46:5
+   |
+LL |     foo_hrtb_bar_not(&mut t);
+   |     ^^^^^^^^^^^^^^^^ one type is more general than the other
+   |
+   = note: expected type `Bar<&'a isize>`
+              found type `Bar<&'b isize>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/hrtb/issue-46989.rs b/src/test/ui/hrtb/issue-46989.rs
new file mode 100644
index 0000000..2c85905
--- /dev/null
+++ b/src/test/ui/hrtb/issue-46989.rs
@@ -0,0 +1,42 @@
+// Regression test for #46989:
+//
+// In the move to universes, this test started passing.
+// It is not necessarily WRONG to do so, but it was a bit
+// surprising. The reason that it passed is that when we were
+// asked to prove that
+//
+//     for<'a> fn(&'a i32): Foo
+//
+// we were able to use the impl below to prove
+//
+//     fn(&'empty i32): Foo
+//
+// and then we were able to prove that
+//
+//     fn(&'empty i32) = for<'a> fn(&'a i32)
+//
+// This last fact is somewhat surprising, but essentially "falls out"
+// from handling variance correctly. In particular, consider the subtyping
+// relations. First:
+//
+//     fn(&'empty i32) <: for<'a> fn(&'a i32)
+//
+// This holds because -- intuitively -- a fn that takes a reference but doesn't use
+// it can be given a reference with any lifetime. Similarly, the opposite direction:
+//
+//     for<'a> fn(&'a i32) <: fn(&'empty i32)
+//
+// holds because 'a can be instantiated to 'empty.
+
+trait Foo {
+
+}
+
+impl<A> Foo for fn(A) { }
+
+fn assert_foo<T: Foo>() {}
+
+fn main() {
+    assert_foo::<fn(&i32)>();
+    //~^ ERROR the trait bound `for<'r> fn(&'r i32): Foo` is not satisfied
+}
diff --git a/src/test/ui/hrtb/issue-46989.stderr b/src/test/ui/hrtb/issue-46989.stderr
new file mode 100644
index 0000000..b308291
--- /dev/null
+++ b/src/test/ui/hrtb/issue-46989.stderr
@@ -0,0 +1,17 @@
+error[E0277]: the trait bound `for<'r> fn(&'r i32): Foo` is not satisfied
+  --> $DIR/issue-46989.rs:40:5
+   |
+LL |     assert_foo::<fn(&i32)>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `for<'r> fn(&'r i32)`
+   |
+   = help: the following implementations were found:
+             <fn(A) as Foo>
+note: required by `assert_foo`
+  --> $DIR/issue-46989.rs:37:1
+   |
+LL | fn assert_foo<T: Foo>() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/hrtb/issue-57639.rs b/src/test/ui/hrtb/issue-57639.rs
new file mode 100644
index 0000000..4bcaef3
--- /dev/null
+++ b/src/test/ui/hrtb/issue-57639.rs
@@ -0,0 +1,29 @@
+// Regression test for #57639:
+//
+// In the move to universes, this test stopped working. The problem
+// was that when the trait solver was asked to prove `for<'a> T::Item:
+// Foo<'a>` as part of WF checking, it wound up "eagerly committing"
+// to the where clause, which says that `T::Item: Foo<'a>`, but it
+// should instead have been using the bound found in the trait
+// declaration. Pre-universe, this used to work out ok because we got
+// "eager errors" due to the leak check.
+//
+// See [this comment on GitHub][c] for more details.
+//
+// run-pass
+//
+// [c]: https://github.com/rust-lang/rust/issues/57639#issuecomment-455685861
+
+trait Foo<'a> {}
+
+trait Bar {
+    type Item: for<'a> Foo<'a>;
+}
+
+fn foo<'a, T>(_: T)
+where
+    T: Bar,
+    T::Item: Foo<'a>,
+{}
+
+fn main() { }
diff --git a/src/test/ui/hrtb/issue-58451.rs b/src/test/ui/hrtb/issue-58451.rs
new file mode 100644
index 0000000..229e505
--- /dev/null
+++ b/src/test/ui/hrtb/issue-58451.rs
@@ -0,0 +1,13 @@
+// Regression test for #58451:
+//
+// Error reporting here encountered an ICE in the shift to universes.
+
+fn f<I>(i: I)
+where
+    I: IntoIterator,
+    I::Item: for<'a> Into<&'a ()>,
+{}
+
+fn main() {
+    f(&[f()]); //~ ERROR this function takes 1 parameter
+}
diff --git a/src/test/ui/hrtb/issue-58451.stderr b/src/test/ui/hrtb/issue-58451.stderr
new file mode 100644
index 0000000..4648c01
--- /dev/null
+++ b/src/test/ui/hrtb/issue-58451.stderr
@@ -0,0 +1,16 @@
+error[E0061]: this function takes 1 parameter but 0 parameters were supplied
+  --> $DIR/issue-58451.rs:12:9
+   |
+LL | / fn f<I>(i: I)
+LL | | where
+LL | |     I: IntoIterator,
+LL | |     I::Item: for<'a> Into<&'a ()>,
+LL | | {}
+   | |__- defined here
+...
+LL |       f(&[f()]);
+   |           ^^^ expected 1 parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0061`.
diff --git a/src/test/ui/huge-array-simple.rs b/src/test/ui/huge-array-simple.rs
new file mode 100644
index 0000000..8b244a4
--- /dev/null
+++ b/src/test/ui/huge-array-simple.rs
@@ -0,0 +1,16 @@
+// error-pattern: too big for the current architecture
+
+// normalize-stderr-test "; \d+]" -> "; N]"
+#![allow(exceeding_bitshifts)]
+
+#[cfg(target_pointer_width = "64")]
+fn main() {
+    let _fat : [u8; (1<<61)+(1<<31)] =
+        [0; (1u64<<61) as usize +(1u64<<31) as usize];
+}
+
+#[cfg(target_pointer_width = "32")]
+fn main() {
+    let _fat : [u8; (1<<31)+(1<<15)] =
+        [0; (1u32<<31) as usize +(1u32<<15) as usize];
+}
diff --git a/src/test/ui/huge-array-simple.stderr b/src/test/ui/huge-array-simple.stderr
new file mode 100644
index 0000000..3e9c862
--- /dev/null
+++ b/src/test/ui/huge-array-simple.stderr
@@ -0,0 +1,4 @@
+error: the type `[u8; N]` is too big for the current architecture
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/huge-array.rs b/src/test/ui/huge-array.rs
new file mode 100644
index 0000000..0608b23
--- /dev/null
+++ b/src/test/ui/huge-array.rs
@@ -0,0 +1,10 @@
+// error-pattern:; 1518600000
+
+fn generic<T: Copy>(t: T) {
+    let s: [T; 1518600000] = [t; 1518600000];
+}
+
+fn main() {
+    let x: [u8; 1518599999] = [0; 1518599999];
+    generic::<[u8; 1518599999]>(x);
+}
diff --git a/src/test/ui/huge-array.stderr b/src/test/ui/huge-array.stderr
new file mode 100644
index 0000000..38d9eff
--- /dev/null
+++ b/src/test/ui/huge-array.stderr
@@ -0,0 +1,4 @@
+error: the type `[[u8; 1518599999]; 1518600000]` is too big for the current architecture
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/huge-enum.rs b/src/test/ui/huge-enum.rs
new file mode 100644
index 0000000..71c8fd5
--- /dev/null
+++ b/src/test/ui/huge-enum.rs
@@ -0,0 +1,12 @@
+// normalize-stderr-test "std::option::Option<\[u32; \d+\]>" -> "TYPE"
+// normalize-stderr-test "\[u32; \d+\]" -> "TYPE"
+
+#[cfg(target_pointer_width = "32")]
+fn main() {
+    let big: Option<[u32; (1<<29)-1]> = None;
+}
+
+#[cfg(target_pointer_width = "64")]
+fn main() {
+    let big: Option<[u32; (1<<45)-1]> = None;
+}
diff --git a/src/test/ui/huge-enum.stderr b/src/test/ui/huge-enum.stderr
new file mode 100644
index 0000000..67cae3d
--- /dev/null
+++ b/src/test/ui/huge-enum.stderr
@@ -0,0 +1,4 @@
+error: the type `TYPE` is too big for the current architecture
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/huge-struct.rs b/src/test/ui/huge-struct.rs
new file mode 100644
index 0000000..74e43cc
--- /dev/null
+++ b/src/test/ui/huge-struct.rs
@@ -0,0 +1,46 @@
+// normalize-stderr-test "S32" -> "SXX"
+// normalize-stderr-test "S1M" -> "SXX"
+// error-pattern: too big for the current
+
+struct S32<T> {
+    v0: T,
+    v1: T,
+    v2: T,
+    v3: T,
+    v4: T,
+    v5: T,
+    v6: T,
+    v7: T,
+    v8: T,
+    u9: T,
+    v10: T,
+    v11: T,
+    v12: T,
+    v13: T,
+    v14: T,
+    v15: T,
+    v16: T,
+    v17: T,
+    v18: T,
+    v19: T,
+    v20: T,
+    v21: T,
+    v22: T,
+    v23: T,
+    v24: T,
+    u25: T,
+    v26: T,
+    v27: T,
+    v28: T,
+    v29: T,
+    v30: T,
+    v31: T,
+}
+
+struct S1k<T> { val: S32<S32<T>> }
+
+struct S1M<T> { val: S1k<S1k<T>> }
+
+fn main() {
+    let fat: Option<S1M<S1M<S1M<u32>>>> = None;
+}
diff --git a/src/test/ui/huge-struct.stderr b/src/test/ui/huge-struct.stderr
new file mode 100644
index 0000000..06b084b
--- /dev/null
+++ b/src/test/ui/huge-struct.stderr
@@ -0,0 +1,4 @@
+error: the type `SXX<SXX<SXX<u32>>>` is too big for the current architecture
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/hygiene/arguments.rs b/src/test/ui/hygiene/arguments.rs
new file mode 100644
index 0000000..f0f732f
--- /dev/null
+++ b/src/test/ui/hygiene/arguments.rs
@@ -0,0 +1,17 @@
+// ignore-pretty pretty-printing is unhygienic
+
+#![feature(decl_macro)]
+
+macro m($t:ty, $e:expr) {
+    mod foo {
+        #[allow(unused)]
+        struct S;
+        pub(super) fn f(_: $t) {}
+    }
+    foo::f($e);
+}
+
+fn main() {
+    struct S;
+    m!(S, S); //~ ERROR cannot find type `S` in this scope
+}
diff --git a/src/test/ui/hygiene/arguments.stderr b/src/test/ui/hygiene/arguments.stderr
new file mode 100644
index 0000000..d072086
--- /dev/null
+++ b/src/test/ui/hygiene/arguments.stderr
@@ -0,0 +1,9 @@
+error[E0412]: cannot find type `S` in this scope
+  --> $DIR/arguments.rs:16:8
+   |
+LL |     m!(S, S);
+   |        ^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/src/test/ui/hygiene/assoc_item_ctxt.rs b/src/test/ui/hygiene/assoc_item_ctxt.rs
new file mode 100644
index 0000000..65593d1
--- /dev/null
+++ b/src/test/ui/hygiene/assoc_item_ctxt.rs
@@ -0,0 +1,42 @@
+// ignore-pretty pretty-printing is unhygienic
+
+#![feature(decl_macro)]
+#![allow(unused)]
+
+mod ok {
+    macro mac_trait_item($method: ident) {
+        fn $method();
+    }
+
+    trait Tr {
+        mac_trait_item!(method);
+    }
+
+    macro mac_trait_impl() {
+        impl Tr for u8 { // OK
+            fn method() {} // OK
+        }
+    }
+
+    mac_trait_impl!();
+}
+
+mod error {
+    macro mac_trait_item() {
+        fn method();
+    }
+
+    trait Tr {
+        mac_trait_item!();
+    }
+
+    macro mac_trait_impl() {
+        impl Tr for u8 { //~ ERROR not all trait items implemented, missing: `method`
+            fn method() {} //~ ERROR method `method` is not a member of trait `Tr`
+        }
+    }
+
+    mac_trait_impl!();
+}
+
+fn main() {}
diff --git a/src/test/ui/hygiene/assoc_item_ctxt.stderr b/src/test/ui/hygiene/assoc_item_ctxt.stderr
new file mode 100644
index 0000000..ebe38b7
--- /dev/null
+++ b/src/test/ui/hygiene/assoc_item_ctxt.stderr
@@ -0,0 +1,25 @@
+error[E0407]: method `method` is not a member of trait `Tr`
+  --> $DIR/assoc_item_ctxt.rs:35:13
+   |
+LL |             fn method() {}
+   |             ^^^^^^^^^^^^^^ not a member of trait `Tr`
+...
+LL |     mac_trait_impl!();
+   |     ------------------ in this macro invocation
+
+error[E0046]: not all trait items implemented, missing: `method`
+  --> $DIR/assoc_item_ctxt.rs:34:9
+   |
+LL |         fn method();
+   |         ------------ `method` from trait
+...
+LL |         impl Tr for u8 {
+   |         ^^^^^^^^^^^^^^ missing `method` in implementation
+...
+LL |     mac_trait_impl!();
+   |     ------------------ in this macro invocation
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0046, E0407.
+For more information about an error, try `rustc --explain E0046`.
diff --git a/src/test/ui/hygiene/assoc_ty_bindings.rs b/src/test/ui/hygiene/assoc_ty_bindings.rs
new file mode 100644
index 0000000..eb0ca6a
--- /dev/null
+++ b/src/test/ui/hygiene/assoc_ty_bindings.rs
@@ -0,0 +1,39 @@
+// ignore-pretty pretty-printing is unhygienic
+
+#![feature(decl_macro, associated_type_defaults)]
+// compile-pass
+// skip-codegen
+trait Base {
+    type AssocTy;
+    fn f();
+}
+trait Derived: Base {
+    fn g();
+}
+
+macro mac() {
+    type A = Base<AssocTy = u8>;
+    type B = Derived<AssocTy = u8>;
+
+    impl Base for u8 {
+        type AssocTy = u8;
+        fn f() {
+            let _: Self::AssocTy;
+        }
+    }
+    impl Derived for u8 {
+        fn g() {
+            let _: Self::AssocTy;
+        }
+    }
+
+    fn h<T: Base, U: Derived>() {
+        let _: T::AssocTy;
+        let _: U::AssocTy;
+    }
+}
+
+mac!();
+
+
+fn main() {}
diff --git a/src/test/ui/hygiene/auxiliary/intercrate.rs b/src/test/ui/hygiene/auxiliary/intercrate.rs
new file mode 100644
index 0000000..10d399b
--- /dev/null
+++ b/src/test/ui/hygiene/auxiliary/intercrate.rs
@@ -0,0 +1,46 @@
+#![feature(decl_macro)]
+
+pub mod foo {
+    pub use self::bar::m;
+    mod bar {
+        fn f() -> u32 { 1 }
+        pub macro m() {
+            f();
+        }
+    }
+}
+
+pub struct SomeType;
+
+// `$crate`
+pub macro uses_dollar_crate_modern() {
+    type Alias = $crate::SomeType;
+}
+
+pub macro define_uses_dollar_crate_modern_nested($uses_dollar_crate_modern_nested: ident) {
+    macro $uses_dollar_crate_modern_nested() {
+        type AliasCrateModernNested = $crate::SomeType;
+    }
+}
+
+#[macro_export]
+macro_rules! define_uses_dollar_crate_legacy_nested {
+    () => {
+        macro_rules! uses_dollar_crate_legacy_nested {
+            () => {
+                type AliasLegacyNested = $crate::SomeType;
+            }
+        }
+    }
+}
+
+// `crate`
+pub macro uses_crate_modern() {
+    type AliasCrate = crate::SomeType;
+}
+
+pub macro define_uses_crate_modern_nested($uses_crate_modern_nested: ident) {
+    macro $uses_crate_modern_nested() {
+        type AliasCrateModernNested = crate::SomeType;
+    }
+}
diff --git a/src/test/ui/hygiene/auxiliary/local_inner_macros.rs b/src/test/ui/hygiene/auxiliary/local_inner_macros.rs
new file mode 100644
index 0000000..4296ae2
--- /dev/null
+++ b/src/test/ui/hygiene/auxiliary/local_inner_macros.rs
@@ -0,0 +1,19 @@
+#[macro_export]
+macro_rules! helper1 {
+    () => ( struct S; )
+}
+
+#[macro_export(local_inner_macros)]
+macro_rules! helper2 {
+    () => ( helper1!(); )
+}
+
+#[macro_export(local_inner_macros)]
+macro_rules! public_macro {
+    () => ( helper2!(); )
+}
+
+#[macro_export(local_inner_macros)]
+macro_rules! public_macro_dynamic {
+    ($helper: ident) => ( $helper!(); )
+}
diff --git a/src/test/ui/hygiene/auxiliary/transparent-basic.rs b/src/test/ui/hygiene/auxiliary/transparent-basic.rs
new file mode 100644
index 0000000..0d045d0
--- /dev/null
+++ b/src/test/ui/hygiene/auxiliary/transparent-basic.rs
@@ -0,0 +1,6 @@
+#![feature(decl_macro, rustc_attrs)]
+
+#[rustc_transparent_macro]
+pub macro dollar_crate() {
+    let s = $crate::S;
+}
diff --git a/src/test/ui/hygiene/dollar-crate-modern.rs b/src/test/ui/hygiene/dollar-crate-modern.rs
new file mode 100644
index 0000000..380ad20
--- /dev/null
+++ b/src/test/ui/hygiene/dollar-crate-modern.rs
@@ -0,0 +1,25 @@
+// Make sure `$crate` and `crate` work in for basic cases of nested macros.
+
+// compile-pass
+// aux-build:intercrate.rs
+
+#![feature(decl_macro, crate_in_paths)]
+
+extern crate intercrate;
+
+// `$crate`
+intercrate::uses_dollar_crate_modern!();
+
+intercrate::define_uses_dollar_crate_modern_nested!(uses_dollar_crate_modern_nested);
+uses_dollar_crate_modern_nested!();
+
+intercrate::define_uses_dollar_crate_legacy_nested!();
+uses_dollar_crate_legacy_nested!();
+
+// `crate`
+intercrate::uses_crate_modern!();
+
+intercrate::define_uses_crate_modern_nested!(uses_crate_modern_nested);
+uses_crate_modern_nested!();
+
+fn main() {}
diff --git a/src/test/ui/hygiene/dollar-crate-modern.stderr b/src/test/ui/hygiene/dollar-crate-modern.stderr
new file mode 100644
index 0000000..69bbc52
--- /dev/null
+++ b/src/test/ui/hygiene/dollar-crate-modern.stderr
@@ -0,0 +1,8 @@
+warning: the feature `crate_in_paths` has been stable since 1.30.0 and no longer requires an attribute to enable
+  --> $DIR/dollar-crate-modern.rs:6:24
+   |
+LL | #![feature(decl_macro, crate_in_paths)]
+   |                        ^^^^^^^^^^^^^^
+   |
+   = note: #[warn(stable_features)] on by default
+
diff --git a/src/test/ui/hygiene/expansion-info-reset.rs b/src/test/ui/hygiene/expansion-info-reset.rs
new file mode 100644
index 0000000..5c384c4
--- /dev/null
+++ b/src/test/ui/hygiene/expansion-info-reset.rs
@@ -0,0 +1,7 @@
+// FIXME: Investigate why expansion info for a single expansion id is reset from
+// `MacroBang(format_args)` to `MacroAttribute(derive(Clone))` (issue #52363).
+
+fn main() {
+    format_args!({ #[derive(Clone)] struct S; });
+    //~^ ERROR format argument must be a string literal
+}
diff --git a/src/test/ui/hygiene/expansion-info-reset.stderr b/src/test/ui/hygiene/expansion-info-reset.stderr
new file mode 100644
index 0000000..9dd954b
--- /dev/null
+++ b/src/test/ui/hygiene/expansion-info-reset.stderr
@@ -0,0 +1,12 @@
+error: format argument must be a string literal
+  --> $DIR/expansion-info-reset.rs:5:18
+   |
+LL |     format_args!({ #[derive(Clone)] struct S; });
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: you might be missing a string literal to format with
+   |
+LL |     format_args!("{}", { #[derive(Clone)] struct S; });
+   |                  ^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/hygiene/fields-definition.rs b/src/test/ui/hygiene/fields-definition.rs
new file mode 100644
index 0000000..173c357
--- /dev/null
+++ b/src/test/ui/hygiene/fields-definition.rs
@@ -0,0 +1,22 @@
+#![feature(decl_macro)]
+
+macro modern($a: ident) {
+    struct Modern {
+        a: u8,
+        $a: u8, // OK
+    }
+}
+
+macro_rules! legacy {
+    ($a: ident) => {
+        struct Legacy {
+            a: u8,
+            $a: u8, //~ ERROR field `a` is already declared
+        }
+    }
+}
+
+modern!(a);
+legacy!(a);
+
+fn main() {}
diff --git a/src/test/ui/hygiene/fields-definition.stderr b/src/test/ui/hygiene/fields-definition.stderr
new file mode 100644
index 0000000..a30650d
--- /dev/null
+++ b/src/test/ui/hygiene/fields-definition.stderr
@@ -0,0 +1,14 @@
+error[E0124]: field `a` is already declared
+  --> $DIR/fields-definition.rs:14:17
+   |
+LL |             a: u8,
+   |             ----- `a` first declared here
+LL |             $a: u8,
+   |                 ^^ field already declared
+...
+LL | legacy!(a);
+   | ----------- in this macro invocation
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0124`.
diff --git a/src/test/ui/hygiene/fields-move.nll.stderr b/src/test/ui/hygiene/fields-move.nll.stderr
new file mode 100644
index 0000000..562f60e
--- /dev/null
+++ b/src/test/ui/hygiene/fields-move.nll.stderr
@@ -0,0 +1,38 @@
+error[E0382]: use of moved value: `foo.x`
+  --> $DIR/fields-move.rs:18:9
+   |
+LL |         $foo.x
+   |         ^^^^^^ value used here after move
+...
+LL |     assert_two_copies(copy_modern!(foo), foo.x);
+   |                                          ----- value moved here
+LL |     assert_two_copies(copy_legacy!(foo), foo.x);
+   |                       ----------------- in this macro invocation
+   |
+   = note: move occurs because `foo.x` has type `NonCopy`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `foo.x`
+  --> $DIR/fields-move.rs:28:42
+   |
+LL |    $foo.x
+   |    ------ value moved here
+...
+LL |     assert_two_copies(copy_modern!(foo), foo.x);
+   |                                          ^^^^^ value used here after move
+   |
+   = note: move occurs because `foo.x` has type `NonCopy`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `foo.x`
+  --> $DIR/fields-move.rs:29:42
+   |
+LL |         $foo.x
+   |         ------ value moved here
+...
+LL |     assert_two_copies(copy_legacy!(foo), foo.x);
+   |                                          ^^^^^ value used here after move
+   |
+   = note: move occurs because `foo.x` has type `NonCopy`, which does not implement the `Copy` trait
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/hygiene/fields-move.rs b/src/test/ui/hygiene/fields-move.rs
new file mode 100644
index 0000000..401ad97
--- /dev/null
+++ b/src/test/ui/hygiene/fields-move.rs
@@ -0,0 +1,30 @@
+// issue #46314
+
+#![feature(decl_macro)]
+
+#[derive(Debug)]
+struct NonCopy(String);
+
+struct Foo {
+    x: NonCopy,
+}
+
+macro copy_modern($foo: ident) {
+   $foo.x
+}
+
+macro_rules! copy_legacy {
+    ($foo: ident) => {
+        $foo.x //~ ERROR use of moved value: `foo.x`
+    }
+}
+
+fn assert_two_copies(a: NonCopy, b: NonCopy) {
+   println!("Got two copies: {:?}, {:?}", a, b);
+}
+
+fn main() {
+    let foo = Foo { x: NonCopy("foo".into()) };
+    assert_two_copies(copy_modern!(foo), foo.x); //~ ERROR use of moved value: `foo.x`
+    assert_two_copies(copy_legacy!(foo), foo.x); //~ ERROR use of moved value: `foo.x`
+}
diff --git a/src/test/ui/hygiene/fields-move.stderr b/src/test/ui/hygiene/fields-move.stderr
new file mode 100644
index 0000000..43d55fd
--- /dev/null
+++ b/src/test/ui/hygiene/fields-move.stderr
@@ -0,0 +1,39 @@
+error[E0382]: use of moved value: `foo.x`
+  --> $DIR/fields-move.rs:28:42
+   |
+LL |    $foo.x
+   |    ------ value moved here
+...
+LL |     assert_two_copies(copy_modern!(foo), foo.x);
+   |                                          ^^^^^ value used here after move
+   |
+   = note: move occurs because `foo.x` has type `NonCopy`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `foo.x`
+  --> $DIR/fields-move.rs:18:9
+   |
+LL |    $foo.x
+   |    ------ value moved here
+...
+LL |         $foo.x
+   |         ^^^^^^ value used here after move
+...
+LL |     assert_two_copies(copy_legacy!(foo), foo.x);
+   |                       ----------------- in this macro invocation
+   |
+   = note: move occurs because `foo.x` has type `NonCopy`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `foo.x`
+  --> $DIR/fields-move.rs:29:42
+   |
+LL |    $foo.x
+   |    ------ value moved here
+...
+LL |     assert_two_copies(copy_legacy!(foo), foo.x);
+   |                                          ^^^^^ value used here after move
+   |
+   = note: move occurs because `foo.x` has type `NonCopy`, which does not implement the `Copy` trait
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/hygiene/fields-numeric-borrowck.nll.stderr b/src/test/ui/hygiene/fields-numeric-borrowck.nll.stderr
new file mode 100644
index 0000000..fb90825
--- /dev/null
+++ b/src/test/ui/hygiene/fields-numeric-borrowck.nll.stderr
@@ -0,0 +1,14 @@
+error[E0499]: cannot borrow `s.0` as mutable more than once at a time
+  --> $DIR/fields-numeric-borrowck.rs:6:16
+   |
+LL |     let borrow1 = &mut s.0;
+   |                   -------- first mutable borrow occurs here
+LL |     let S { 0: ref mut borrow2 } = s;
+   |                ^^^^^^^^^^^^^^^ second mutable borrow occurs here
+...
+LL |     borrow1.use_mut();
+   |     ------- first borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/hygiene/fields-numeric-borrowck.rs b/src/test/ui/hygiene/fields-numeric-borrowck.rs
new file mode 100644
index 0000000..9536bab
--- /dev/null
+++ b/src/test/ui/hygiene/fields-numeric-borrowck.rs
@@ -0,0 +1,13 @@
+struct S(u8);
+
+fn main() {
+    let mut s = S(0);
+    let borrow1 = &mut s.0;
+    let S { 0: ref mut borrow2 } = s;
+    //~^ ERROR cannot borrow `s.0` as mutable more than once at a time
+    borrow2.use_mut();
+    borrow1.use_mut();
+}
+
+trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { }  }
+impl<T> Fake for T { }
diff --git a/src/test/ui/hygiene/fields-numeric-borrowck.stderr b/src/test/ui/hygiene/fields-numeric-borrowck.stderr
new file mode 100644
index 0000000..11b5fd70
--- /dev/null
+++ b/src/test/ui/hygiene/fields-numeric-borrowck.stderr
@@ -0,0 +1,14 @@
+error[E0499]: cannot borrow `s.0` as mutable more than once at a time
+  --> $DIR/fields-numeric-borrowck.rs:6:16
+   |
+LL |     let borrow1 = &mut s.0;
+   |                        --- first mutable borrow occurs here
+LL |     let S { 0: ref mut borrow2 } = s;
+   |                ^^^^^^^^^^^^^^^ second mutable borrow occurs here
+...
+LL | }
+   | - first borrow ends here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/hygiene/fields.rs b/src/test/ui/hygiene/fields.rs
new file mode 100644
index 0000000..597019c
--- /dev/null
+++ b/src/test/ui/hygiene/fields.rs
@@ -0,0 +1,30 @@
+// ignore-pretty pretty-printing is unhygienic
+
+#![feature(decl_macro)]
+
+mod foo {
+    struct S { x: u32 }
+    struct T(u32);
+
+    pub macro m($S:ident, $x:ident) {{
+        struct $S {
+            $x: u32,
+            x: i32,
+        }
+
+        let s = S { x: 0 }; //~ ERROR type `foo::S` is private
+        let _ = s.x; //~ ERROR type `foo::S` is private
+
+        let t = T(0); //~ ERROR type `foo::T` is private
+        let _ = t.0; //~ ERROR type `foo::T` is private
+
+        let s = $S { $x: 0, x: 1 };
+        assert_eq!((s.$x, s.x), (0, 1));
+        s
+    }}
+}
+
+fn main() {
+    let s = foo::m!(S, x);
+    assert_eq!(s.x, 0);
+}
diff --git a/src/test/ui/hygiene/fields.stderr b/src/test/ui/hygiene/fields.stderr
new file mode 100644
index 0000000..20ea4e9
--- /dev/null
+++ b/src/test/ui/hygiene/fields.stderr
@@ -0,0 +1,38 @@
+error: type `foo::S` is private
+  --> $DIR/fields.rs:15:17
+   |
+LL |         let s = S { x: 0 };
+   |                 ^^^^^^^^^^
+...
+LL |     let s = foo::m!(S, x);
+   |             ------------- in this macro invocation
+
+error: type `foo::S` is private
+  --> $DIR/fields.rs:16:17
+   |
+LL |         let _ = s.x;
+   |                 ^
+...
+LL |     let s = foo::m!(S, x);
+   |             ------------- in this macro invocation
+
+error: type `foo::T` is private
+  --> $DIR/fields.rs:18:17
+   |
+LL |         let t = T(0);
+   |                 ^^^^
+...
+LL |     let s = foo::m!(S, x);
+   |             ------------- in this macro invocation
+
+error: type `foo::T` is private
+  --> $DIR/fields.rs:19:17
+   |
+LL |         let _ = t.0;
+   |                 ^
+...
+LL |     let s = foo::m!(S, x);
+   |             ------------- in this macro invocation
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/hygiene/for-loop.rs b/src/test/ui/hygiene/for-loop.rs
new file mode 100644
index 0000000..2e5ae43
--- /dev/null
+++ b/src/test/ui/hygiene/for-loop.rs
@@ -0,0 +1,8 @@
+// for-loops are expanded in the front end, and use an `iter` ident in their expansion. Check that
+// `iter` is not accessible inside the for loop.
+
+fn main() {
+    for _ in 0..10 {
+        iter.next();  //~ ERROR cannot find value `iter` in this scope
+    }
+}
diff --git a/src/test/ui/hygiene/for-loop.stderr b/src/test/ui/hygiene/for-loop.stderr
new file mode 100644
index 0000000..932c951
--- /dev/null
+++ b/src/test/ui/hygiene/for-loop.stderr
@@ -0,0 +1,9 @@
+error[E0425]: cannot find value `iter` in this scope
+  --> $DIR/for-loop.rs:6:9
+   |
+LL |         iter.next();
+   |         ^^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/hygiene/generate-mod.rs b/src/test/ui/hygiene/generate-mod.rs
new file mode 100644
index 0000000..089d74f
--- /dev/null
+++ b/src/test/ui/hygiene/generate-mod.rs
@@ -0,0 +1,49 @@
+// This is an equivalent of issue #50504, but for declarative macros.
+
+#![feature(decl_macro, rustc_attrs)]
+
+macro genmod($FromOutside: ident, $Outer: ident) {
+    type A = $FromOutside;
+    struct $Outer;
+    mod inner {
+        type A = $FromOutside; // `FromOutside` shouldn't be available from here
+        type Inner = $Outer; // `Outer` shouldn't be available from here
+    }
+}
+
+#[rustc_transparent_macro]
+macro genmod_transparent() {
+    type A = FromOutside;
+    struct Outer;
+    mod inner {
+        type A = FromOutside; //~ ERROR cannot find type `FromOutside` in this scope
+        type Inner = Outer; //~ ERROR cannot find type `Outer` in this scope
+    }
+}
+
+macro_rules! genmod_legacy { () => {
+    type A = FromOutside;
+    struct Outer;
+    mod inner {
+        type A = FromOutside; //~ ERROR cannot find type `FromOutside` in this scope
+        type Inner = Outer; //~ ERROR cannot find type `Outer` in this scope
+    }
+}}
+
+fn check() {
+    struct FromOutside;
+    genmod!(FromOutside, Outer); //~ ERROR cannot find type `FromOutside` in this scope
+                                 //~| ERROR cannot find type `Outer` in this scope
+}
+
+fn check_transparent() {
+    struct FromOutside;
+    genmod_transparent!();
+}
+
+fn check_legacy() {
+    struct FromOutside;
+    genmod_legacy!();
+}
+
+fn main() {}
diff --git a/src/test/ui/hygiene/generate-mod.stderr b/src/test/ui/hygiene/generate-mod.stderr
new file mode 100644
index 0000000..5e2c56d
--- /dev/null
+++ b/src/test/ui/hygiene/generate-mod.stderr
@@ -0,0 +1,51 @@
+error[E0412]: cannot find type `FromOutside` in this scope
+  --> $DIR/generate-mod.rs:35:13
+   |
+LL |     genmod!(FromOutside, Outer);
+   |             ^^^^^^^^^^^ not found in this scope
+
+error[E0412]: cannot find type `Outer` in this scope
+  --> $DIR/generate-mod.rs:35:26
+   |
+LL |     genmod!(FromOutside, Outer);
+   |                          ^^^^^ not found in this scope
+
+error[E0412]: cannot find type `FromOutside` in this scope
+  --> $DIR/generate-mod.rs:19:18
+   |
+LL |         type A = FromOutside;
+   |                  ^^^^^^^^^^^ not found in this scope
+...
+LL |     genmod_transparent!();
+   |     ---------------------- in this macro invocation
+
+error[E0412]: cannot find type `Outer` in this scope
+  --> $DIR/generate-mod.rs:20:22
+   |
+LL |         type Inner = Outer;
+   |                      ^^^^^ not found in this scope
+...
+LL |     genmod_transparent!();
+   |     ---------------------- in this macro invocation
+
+error[E0412]: cannot find type `FromOutside` in this scope
+  --> $DIR/generate-mod.rs:28:18
+   |
+LL |         type A = FromOutside;
+   |                  ^^^^^^^^^^^ not found in this scope
+...
+LL |     genmod_legacy!();
+   |     ----------------- in this macro invocation
+
+error[E0412]: cannot find type `Outer` in this scope
+  --> $DIR/generate-mod.rs:29:22
+   |
+LL |         type Inner = Outer;
+   |                      ^^^^^ not found in this scope
+...
+LL |     genmod_legacy!();
+   |     ----------------- in this macro invocation
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/src/test/ui/hygiene/globs.rs b/src/test/ui/hygiene/globs.rs
new file mode 100644
index 0000000..a3f466e
--- /dev/null
+++ b/src/test/ui/hygiene/globs.rs
@@ -0,0 +1,72 @@
+#![feature(decl_macro)]
+
+mod foo {
+    pub fn f() {}
+}
+
+mod bar {
+    pub fn g() {}
+}
+
+macro m($($t:tt)*) {
+    $($t)*
+    use foo::*;
+    f();
+    g(); //~ ERROR cannot find function `g` in this scope
+}
+
+fn main() {
+    m! {
+        use bar::*;
+        g();
+        f(); //~ ERROR cannot find function `f` in this scope
+    }
+}
+
+n!(f);
+macro n($i:ident) {
+    mod foo {
+        pub fn $i() -> u32 { 0 }
+        pub fn f() {}
+
+        mod test {
+            use super::*;
+            fn g() {
+                let _: u32 = $i();
+                let _: () = f();
+            }
+        }
+
+        macro n($j:ident) {
+            mod test {
+                use super::*;
+                fn g() {
+                    let _: u32 = $i();
+                    let _: () = f();
+                    $j();
+                }
+            }
+        }
+        macro n_with_super($j:ident) {
+            mod test {
+                use super::*;
+                fn g() {
+                    let _: u32 = $i();
+                    let _: () = f();
+                    super::$j();
+                }
+            }
+        }
+
+        n!(f); //~ ERROR cannot find function `f` in this scope
+        n_with_super!(f);
+        mod test2 {
+            super::n! {
+                f //~ ERROR cannot find function `f` in this scope
+            }
+            super::n_with_super! {
+                f
+            }
+        }
+    }
+}
diff --git a/src/test/ui/hygiene/globs.stderr b/src/test/ui/hygiene/globs.stderr
new file mode 100644
index 0000000..7e0f4e4
--- /dev/null
+++ b/src/test/ui/hygiene/globs.stderr
@@ -0,0 +1,59 @@
+error[E0425]: cannot find function `f` in this scope
+  --> $DIR/globs.rs:22:9
+   |
+LL |         f();
+   |         ^ not found in this scope
+help: possible candidates are found in other modules, you can import them into scope
+   |
+LL | use foo::f;
+   |
+LL | use foo::f;
+   |
+LL | use foo::f;
+   |
+
+error[E0425]: cannot find function `g` in this scope
+  --> $DIR/globs.rs:15:5
+   |
+LL |       g();
+   |       ^ not found in this scope
+...
+LL | /     m! {
+LL | |         use bar::*;
+LL | |         g();
+LL | |         f();
+LL | |     }
+   | |_____- in this macro invocation
+help: possible candidates are found in other modules, you can import them into scope
+   |
+LL | use bar::g;
+   |
+LL | use foo::test2::test::g;
+   |
+LL | use foo::test2::test::g;
+   |
+LL | use foo::test::g;
+   |
+and 2 other candidates
+
+error[E0425]: cannot find function `f` in this scope
+  --> $DIR/globs.rs:61:12
+   |
+LL | n!(f);
+   | ------ in this macro invocation
+...
+LL |         n!(f);
+   |            ^ not found in this scope
+
+error[E0425]: cannot find function `f` in this scope
+  --> $DIR/globs.rs:65:17
+   |
+LL | n!(f);
+   | ------ in this macro invocation
+...
+LL |                 f
+   |                 ^ not found in this scope
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/hygiene/hygienic-label-1.rs b/src/test/ui/hygiene/hygienic-label-1.rs
new file mode 100644
index 0000000..66361ee
--- /dev/null
+++ b/src/test/ui/hygiene/hygienic-label-1.rs
@@ -0,0 +1,7 @@
+macro_rules! foo {
+    () => { break 'x; } //~ ERROR use of undeclared label `'x`
+}
+
+pub fn main() {
+    'x: loop { foo!() }
+}
diff --git a/src/test/ui/hygiene/hygienic-label-1.stderr b/src/test/ui/hygiene/hygienic-label-1.stderr
new file mode 100644
index 0000000..80cd154
--- /dev/null
+++ b/src/test/ui/hygiene/hygienic-label-1.stderr
@@ -0,0 +1,12 @@
+error[E0426]: use of undeclared label `'x`
+  --> $DIR/hygienic-label-1.rs:2:19
+   |
+LL |     () => { break 'x; }
+   |                   ^^ did you mean `'x`?
+...
+LL |     'x: loop { foo!() }
+   |                ------ in this macro invocation
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0426`.
diff --git a/src/test/ui/hygiene/hygienic-label-2.rs b/src/test/ui/hygiene/hygienic-label-2.rs
new file mode 100644
index 0000000..43e01a9
--- /dev/null
+++ b/src/test/ui/hygiene/hygienic-label-2.rs
@@ -0,0 +1,7 @@
+macro_rules! foo {
+    ($e: expr) => { 'x: loop { $e } }
+}
+
+pub fn main() {
+    foo!(break 'x); //~ ERROR use of undeclared label `'x`
+}
diff --git a/src/test/ui/hygiene/hygienic-label-2.stderr b/src/test/ui/hygiene/hygienic-label-2.stderr
new file mode 100644
index 0000000..c20cbd9
--- /dev/null
+++ b/src/test/ui/hygiene/hygienic-label-2.stderr
@@ -0,0 +1,9 @@
+error[E0426]: use of undeclared label `'x`
+  --> $DIR/hygienic-label-2.rs:6:16
+   |
+LL |     foo!(break 'x);
+   |                ^^ did you mean `'x`?
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0426`.
diff --git a/src/test/ui/hygiene/hygienic-label-3.rs b/src/test/ui/hygiene/hygienic-label-3.rs
new file mode 100644
index 0000000..a81eb84
--- /dev/null
+++ b/src/test/ui/hygiene/hygienic-label-3.rs
@@ -0,0 +1,9 @@
+macro_rules! foo {
+    () => { break 'x; } //~ ERROR use of undeclared label `'x`
+}
+
+pub fn main() {
+    'x: for _ in 0..1 {
+        foo!()
+    };
+}
diff --git a/src/test/ui/hygiene/hygienic-label-3.stderr b/src/test/ui/hygiene/hygienic-label-3.stderr
new file mode 100644
index 0000000..b5839fe
--- /dev/null
+++ b/src/test/ui/hygiene/hygienic-label-3.stderr
@@ -0,0 +1,12 @@
+error[E0426]: use of undeclared label `'x`
+  --> $DIR/hygienic-label-3.rs:2:19
+   |
+LL |     () => { break 'x; }
+   |                   ^^ did you mean `'x`?
+...
+LL |         foo!()
+   |         ------ in this macro invocation
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0426`.
diff --git a/src/test/ui/hygiene/hygienic-label-4.rs b/src/test/ui/hygiene/hygienic-label-4.rs
new file mode 100644
index 0000000..a7e1f0e
--- /dev/null
+++ b/src/test/ui/hygiene/hygienic-label-4.rs
@@ -0,0 +1,7 @@
+macro_rules! foo {
+    ($e: expr) => { 'x: for _ in 0..1 { $e } }
+}
+
+pub fn main() {
+    foo!(break 'x); //~ ERROR use of undeclared label `'x`
+}
diff --git a/src/test/ui/hygiene/hygienic-label-4.stderr b/src/test/ui/hygiene/hygienic-label-4.stderr
new file mode 100644
index 0000000..1dd7489
--- /dev/null
+++ b/src/test/ui/hygiene/hygienic-label-4.stderr
@@ -0,0 +1,9 @@
+error[E0426]: use of undeclared label `'x`
+  --> $DIR/hygienic-label-4.rs:6:16
+   |
+LL |     foo!(break 'x);
+   |                ^^ did you mean `'x`?
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0426`.
diff --git a/src/test/ui/hygiene/impl_items.rs b/src/test/ui/hygiene/impl_items.rs
new file mode 100644
index 0000000..37794c6
--- /dev/null
+++ b/src/test/ui/hygiene/impl_items.rs
@@ -0,0 +1,34 @@
+// ignore-pretty pretty-printing is unhygienic
+
+#![feature(decl_macro)]
+
+mod foo {
+    struct S;
+    impl S {
+        fn f(&self) {}
+    }
+
+    pub macro m() {
+        let _: () = S.f(); //~ ERROR type `for<'r> fn(&'r foo::S) {foo::S::f}` is private
+    }
+}
+
+struct S;
+
+macro m($f:ident) {
+    impl S {
+        fn f(&self) -> u32 { 0 }
+        fn $f(&self) -> i32 { 0 }
+    }
+    fn f() {
+        let _: u32 = S.f();
+        let _: i32 = S.$f();
+    }
+}
+
+m!(f);
+
+fn main() {
+    let _: i32 = S.f();
+    foo::m!();
+}
diff --git a/src/test/ui/hygiene/impl_items.stderr b/src/test/ui/hygiene/impl_items.stderr
new file mode 100644
index 0000000..418c2c7
--- /dev/null
+++ b/src/test/ui/hygiene/impl_items.stderr
@@ -0,0 +1,11 @@
+error: type `for<'r> fn(&'r foo::S) {foo::S::f}` is private
+  --> $DIR/impl_items.rs:12:23
+   |
+LL |         let _: () = S.f();
+   |                       ^
+...
+LL |     foo::m!();
+   |     ---------- in this macro invocation
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/hygiene/intercrate.rs b/src/test/ui/hygiene/intercrate.rs
new file mode 100644
index 0000000..2acbc89
--- /dev/null
+++ b/src/test/ui/hygiene/intercrate.rs
@@ -0,0 +1,12 @@
+// ignore-pretty pretty-printing is unhygienic
+
+// aux-build:intercrate.rs
+
+#![feature(decl_macro)]
+
+extern crate intercrate;
+
+fn main() {
+    assert_eq!(intercrate::foo::m!(), 1);
+    //~^ ERROR type `fn() -> u32 {intercrate::foo::bar::f}` is private
+}
diff --git a/src/test/ui/hygiene/intercrate.stderr b/src/test/ui/hygiene/intercrate.stderr
new file mode 100644
index 0000000..30a5570
--- /dev/null
+++ b/src/test/ui/hygiene/intercrate.stderr
@@ -0,0 +1,10 @@
+error: type `fn() -> u32 {intercrate::foo::bar::f}` is private
+  --> $DIR/intercrate.rs:10:16
+   |
+LL |     assert_eq!(intercrate::foo::m!(), 1);
+   |                ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/hygiene/local_inner_macros.rs b/src/test/ui/hygiene/local_inner_macros.rs
new file mode 100644
index 0000000..f4c1a93
--- /dev/null
+++ b/src/test/ui/hygiene/local_inner_macros.rs
@@ -0,0 +1,19 @@
+// compile-pass
+// aux-build:local_inner_macros.rs
+
+extern crate local_inner_macros;
+
+use local_inner_macros::{public_macro, public_macro_dynamic};
+
+public_macro!();
+
+macro_rules! local_helper {
+    () => ( struct Z; )
+}
+
+public_macro_dynamic!(local_helper);
+
+fn main() {
+    let s = S;
+    let z = Z;
+}
diff --git a/src/test/ui/hygiene/nested_macro_privacy.rs b/src/test/ui/hygiene/nested_macro_privacy.rs
new file mode 100644
index 0000000..bee90e2
--- /dev/null
+++ b/src/test/ui/hygiene/nested_macro_privacy.rs
@@ -0,0 +1,17 @@
+#![feature(decl_macro)]
+
+macro n($foo:ident, $S:ident, $i:ident, $m:ident) {
+    mod $foo {
+        #[derive(Default)]
+        pub struct $S { $i: u32 }
+        pub macro $m($e:expr) { $e.$i }
+    }
+}
+
+n!(foo, S, i, m);
+
+fn main() {
+    use foo::{S, m};
+    S::default().i; //~ ERROR field `i` of struct `foo::S` is private
+    m!(S::default()); // ok
+}
diff --git a/src/test/ui/hygiene/nested_macro_privacy.stderr b/src/test/ui/hygiene/nested_macro_privacy.stderr
new file mode 100644
index 0000000..6e78cb8
--- /dev/null
+++ b/src/test/ui/hygiene/nested_macro_privacy.stderr
@@ -0,0 +1,9 @@
+error[E0616]: field `i` of struct `foo::S` is private
+  --> $DIR/nested_macro_privacy.rs:15:5
+   |
+LL |     S::default().i;
+   |     ^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0616`.
diff --git a/src/test/ui/hygiene/no_implicit_prelude-2018.rs b/src/test/ui/hygiene/no_implicit_prelude-2018.rs
new file mode 100644
index 0000000..3ad7435
--- /dev/null
+++ b/src/test/ui/hygiene/no_implicit_prelude-2018.rs
@@ -0,0 +1,11 @@
+// edition:2018
+
+#[no_implicit_prelude]
+mod bar {
+    fn f() {
+        ::std::print!(""); // OK
+        print!(); //~ ERROR cannot find macro `print!` in this scope
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/hygiene/no_implicit_prelude-2018.stderr b/src/test/ui/hygiene/no_implicit_prelude-2018.stderr
new file mode 100644
index 0000000..e7ae7af
--- /dev/null
+++ b/src/test/ui/hygiene/no_implicit_prelude-2018.stderr
@@ -0,0 +1,10 @@
+error: cannot find macro `print!` in this scope
+  --> $DIR/no_implicit_prelude-2018.rs:7:9
+   |
+LL |         print!();
+   |         ^^^^^
+   |
+   = help: have you added the `#[macro_use]` on the module/import?
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/hygiene/no_implicit_prelude.rs b/src/test/ui/hygiene/no_implicit_prelude.rs
new file mode 100644
index 0000000..1cd05f4
--- /dev/null
+++ b/src/test/ui/hygiene/no_implicit_prelude.rs
@@ -0,0 +1,20 @@
+#![feature(decl_macro)]
+
+mod foo {
+    pub macro m() { Vec::new(); ().clone() }
+    fn f() { ::bar::m!(); }
+}
+
+#[no_implicit_prelude]
+mod bar {
+    pub macro m() {
+        Vec::new(); //~ ERROR failed to resolve
+        ().clone() //~ ERROR no method named `clone` found
+    }
+    fn f() {
+        ::foo::m!();
+        println!(); //~ ERROR cannot find macro `print!` in this scope
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/hygiene/no_implicit_prelude.stderr b/src/test/ui/hygiene/no_implicit_prelude.stderr
new file mode 100644
index 0000000..7948f16
--- /dev/null
+++ b/src/test/ui/hygiene/no_implicit_prelude.stderr
@@ -0,0 +1,35 @@
+error[E0433]: failed to resolve: use of undeclared type or module `Vec`
+  --> $DIR/no_implicit_prelude.rs:11:9
+   |
+LL |     fn f() { ::bar::m!(); }
+   |              ------------ in this macro invocation
+...
+LL |         Vec::new();
+   |         ^^^ use of undeclared type or module `Vec`
+
+error: cannot find macro `print!` in this scope
+  --> $DIR/no_implicit_prelude.rs:16:9
+   |
+LL |         println!();
+   |         ^^^^^^^^^^^
+   |
+   = help: have you added the `#[macro_use]` on the module/import?
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error[E0599]: no method named `clone` found for type `()` in the current scope
+  --> $DIR/no_implicit_prelude.rs:12:12
+   |
+LL |     fn f() { ::bar::m!(); }
+   |              ------------ in this macro invocation
+...
+LL |         ().clone()
+   |            ^^^^^
+   |
+   = help: items from traits can only be used if the trait is in scope
+   = note: the following trait is implemented but not in scope, perhaps add a `use` for it:
+           `use std::clone::Clone;`
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0433, E0599.
+For more information about an error, try `rustc --explain E0433`.
diff --git a/src/test/ui/hygiene/pattern-macro.rs b/src/test/ui/hygiene/pattern-macro.rs
new file mode 100644
index 0000000..e5d6a3a
--- /dev/null
+++ b/src/test/ui/hygiene/pattern-macro.rs
@@ -0,0 +1,6 @@
+macro_rules! foo { () => ( x ) }
+
+fn main() {
+    let foo!() = 2;
+    x + 1; //~ ERROR cannot find value `x` in this scope
+}
diff --git a/src/test/ui/hygiene/pattern-macro.stderr b/src/test/ui/hygiene/pattern-macro.stderr
new file mode 100644
index 0000000..edd0591
--- /dev/null
+++ b/src/test/ui/hygiene/pattern-macro.stderr
@@ -0,0 +1,9 @@
+error[E0425]: cannot find value `x` in this scope
+  --> $DIR/pattern-macro.rs:5:5
+   |
+LL |     x + 1;
+   |     ^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/hygiene/privacy.rs b/src/test/ui/hygiene/privacy.rs
new file mode 100644
index 0000000..78d2555
--- /dev/null
+++ b/src/test/ui/hygiene/privacy.rs
@@ -0,0 +1,18 @@
+#![feature(decl_macro)]
+
+mod foo {
+    fn f() {}
+
+    pub macro m($e:expr) {
+        f();
+        self::f();
+        ::foo::f();
+        $e
+    }
+}
+
+fn main() {
+    foo::m!(
+        foo::f() //~ ERROR `f` is private
+    );
+}
diff --git a/src/test/ui/hygiene/privacy.stderr b/src/test/ui/hygiene/privacy.stderr
new file mode 100644
index 0000000..80fb4dd
--- /dev/null
+++ b/src/test/ui/hygiene/privacy.stderr
@@ -0,0 +1,9 @@
+error[E0603]: function `f` is private
+  --> $DIR/privacy.rs:16:14
+   |
+LL |         foo::f()
+   |              ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0603`.
diff --git a/src/test/ui/hygiene/trait_items.rs b/src/test/ui/hygiene/trait_items.rs
new file mode 100644
index 0000000..a116c5b
--- /dev/null
+++ b/src/test/ui/hygiene/trait_items.rs
@@ -0,0 +1,21 @@
+#![feature(decl_macro)]
+
+mod foo {
+    pub trait T {
+        fn f(&self) {}
+    }
+    impl T for () {}
+}
+
+mod bar {
+    use foo::*;
+    pub macro m() { ().f() }
+    fn f() { ::baz::m!(); }
+}
+
+mod baz {
+    pub macro m() { ().f() } //~ ERROR no method named `f` found for type `()` in the current scope
+    fn f() { ::bar::m!(); }
+}
+
+fn main() {}
diff --git a/src/test/ui/hygiene/trait_items.stderr b/src/test/ui/hygiene/trait_items.stderr
new file mode 100644
index 0000000..4192b97
--- /dev/null
+++ b/src/test/ui/hygiene/trait_items.stderr
@@ -0,0 +1,16 @@
+error[E0599]: no method named `f` found for type `()` in the current scope
+  --> $DIR/trait_items.rs:17:24
+   |
+LL |     fn f() { ::baz::m!(); }
+   |              ------------ in this macro invocation
+...
+LL |     pub macro m() { ().f() }
+   |                        ^
+   |
+   = help: items from traits can only be used if the trait is in scope
+   = note: the following trait is implemented but not in scope, perhaps add a `use` for it:
+           `use foo::T;`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/hygiene/transparent-basic.rs b/src/test/ui/hygiene/transparent-basic.rs
new file mode 100644
index 0000000..0a86234
--- /dev/null
+++ b/src/test/ui/hygiene/transparent-basic.rs
@@ -0,0 +1,43 @@
+// compile-pass
+// aux-build:transparent-basic.rs
+
+#![feature(decl_macro, rustc_attrs)]
+
+extern crate transparent_basic;
+
+#[rustc_transparent_macro]
+macro binding() {
+    let x = 10;
+}
+
+#[rustc_transparent_macro]
+macro label() {
+    break 'label
+}
+
+macro_rules! legacy {
+    () => {
+        binding!();
+        let y = x;
+    }
+}
+
+fn legacy_interaction1() {
+    legacy!();
+}
+
+struct S;
+
+fn check_dollar_crate() {
+    // `$crate::S` inside the macro resolves to `S` from this crate.
+    transparent_basic::dollar_crate!();
+}
+
+fn main() {
+    binding!();
+    let y = x;
+
+    'label: loop {
+        label!();
+    }
+}
diff --git a/src/test/ui/if-else-type-mismatch.rs b/src/test/ui/if-else-type-mismatch.rs
new file mode 100644
index 0000000..583c3d0
--- /dev/null
+++ b/src/test/ui/if-else-type-mismatch.rs
@@ -0,0 +1,46 @@
+fn main() {
+    let _ = if true {
+        1i32
+    } else {
+        2u32
+    };
+    //~^^ ERROR if and else have incompatible types
+    let _ = if true { 42i32 } else { 42u32 };
+    //~^ ERROR if and else have incompatible types
+    let _ = if true {
+        3u32;
+    } else {
+        4u32
+    };
+    //~^^ ERROR if and else have incompatible types
+    let _ = if true {
+        5u32
+    } else {
+        6u32;
+    };
+    //~^^ ERROR if and else have incompatible types
+    let _ = if true {
+        7i32;
+    } else {
+        8u32
+    };
+    //~^^ ERROR if and else have incompatible types
+    let _ = if true {
+        9i32
+    } else {
+        10u32;
+    };
+    //~^^ ERROR if and else have incompatible types
+    let _ = if true {
+
+    } else {
+        11u32
+    };
+    //~^^ ERROR if and else have incompatible types
+    let _ = if true {
+        12i32
+    } else {
+
+    };
+    //~^^^ ERROR if and else have incompatible types
+}
diff --git a/src/test/ui/if-else-type-mismatch.stderr b/src/test/ui/if-else-type-mismatch.stderr
new file mode 100644
index 0000000..b418c96
--- /dev/null
+++ b/src/test/ui/if-else-type-mismatch.stderr
@@ -0,0 +1,130 @@
+error[E0308]: if and else have incompatible types
+  --> $DIR/if-else-type-mismatch.rs:5:9
+   |
+LL |       let _ = if true {
+   |  _____________-
+LL | |         1i32
+   | |         ---- expected because of this
+LL | |     } else {
+LL | |         2u32
+   | |         ^^^^ expected i32, found u32
+LL | |     };
+   | |_____- if and else have incompatible types
+   |
+   = note: expected type `i32`
+              found type `u32`
+
+error[E0308]: if and else have incompatible types
+  --> $DIR/if-else-type-mismatch.rs:8:38
+   |
+LL |     let _ = if true { 42i32 } else { 42u32 };
+   |                       -----          ^^^^^ expected i32, found u32
+   |                       |
+   |                       expected because of this
+   |
+   = note: expected type `i32`
+              found type `u32`
+
+error[E0308]: if and else have incompatible types
+  --> $DIR/if-else-type-mismatch.rs:13:9
+   |
+LL |       let _ = if true {
+   |  _____________-
+LL | |         3u32;
+   | |         -----
+   | |         |   |
+   | |         |   help: consider removing this semicolon
+   | |         expected because of this
+LL | |     } else {
+LL | |         4u32
+   | |         ^^^^ expected (), found u32
+LL | |     };
+   | |_____- if and else have incompatible types
+   |
+   = note: expected type `()`
+              found type `u32`
+
+error[E0308]: if and else have incompatible types
+  --> $DIR/if-else-type-mismatch.rs:19:9
+   |
+LL |       let _ = if true {
+   |  _____________-
+LL | |         5u32
+   | |         ---- expected because of this
+LL | |     } else {
+LL | |         6u32;
+   | |         ^^^^-
+   | |         |   |
+   | |         |   help: consider removing this semicolon
+   | |         expected u32, found ()
+LL | |     };
+   | |_____- if and else have incompatible types
+   |
+   = note: expected type `u32`
+              found type `()`
+
+error[E0308]: if and else have incompatible types
+  --> $DIR/if-else-type-mismatch.rs:25:9
+   |
+LL |       let _ = if true {
+   |  _____________-
+LL | |         7i32;
+   | |         ----- expected because of this
+LL | |     } else {
+LL | |         8u32
+   | |         ^^^^ expected (), found u32
+LL | |     };
+   | |_____- if and else have incompatible types
+   |
+   = note: expected type `()`
+              found type `u32`
+
+error[E0308]: if and else have incompatible types
+  --> $DIR/if-else-type-mismatch.rs:31:9
+   |
+LL |       let _ = if true {
+   |  _____________-
+LL | |         9i32
+   | |         ---- expected because of this
+LL | |     } else {
+LL | |         10u32;
+   | |         ^^^^^^ expected i32, found ()
+LL | |     };
+   | |_____- if and else have incompatible types
+   |
+   = note: expected type `i32`
+              found type `()`
+
+error[E0308]: if and else have incompatible types
+  --> $DIR/if-else-type-mismatch.rs:37:9
+   |
+LL |       let _ = if true {
+   |  _____________________-
+LL | |
+LL | |     } else {
+   | |_____- expected because of this
+LL |           11u32
+   |           ^^^^^ expected (), found u32
+   |
+   = note: expected type `()`
+              found type `u32`
+
+error[E0308]: if and else have incompatible types
+  --> $DIR/if-else-type-mismatch.rs:42:12
+   |
+LL |       let _ = if true {
+   |               ------- if and else have incompatible types
+LL |           12i32
+   |           ----- expected because of this
+LL |       } else {
+   |  ____________^
+LL | |
+LL | |     };
+   | |_____^ expected i32, found ()
+   |
+   = note: expected type `i32`
+              found type `()`
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/if/if-branch-types.rs b/src/test/ui/if/if-branch-types.rs
new file mode 100644
index 0000000..b79a49e
--- /dev/null
+++ b/src/test/ui/if/if-branch-types.rs
@@ -0,0 +1,5 @@
+fn main() {
+    let x = if true { 10i32 } else { 10u32 };
+    //~^ ERROR if and else have incompatible types
+    //~| expected i32, found u32
+}
diff --git a/src/test/ui/if/if-branch-types.stderr b/src/test/ui/if/if-branch-types.stderr
new file mode 100644
index 0000000..74b925f
--- /dev/null
+++ b/src/test/ui/if/if-branch-types.stderr
@@ -0,0 +1,14 @@
+error[E0308]: if and else have incompatible types
+  --> $DIR/if-branch-types.rs:2:38
+   |
+LL |     let x = if true { 10i32 } else { 10u32 };
+   |                       -----          ^^^^^ expected i32, found u32
+   |                       |
+   |                       expected because of this
+   |
+   = note: expected type `i32`
+              found type `u32`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/if/if-let-arm-types.rs b/src/test/ui/if/if-let-arm-types.rs
new file mode 100644
index 0000000..819f5dd
--- /dev/null
+++ b/src/test/ui/if/if-let-arm-types.rs
@@ -0,0 +1,11 @@
+fn main() {
+    if let Some(b) = None {
+        //~^ NOTE if let` arms have incompatible types
+        ()
+    } else {
+        1
+    };
+    //~^^ ERROR: `if let` arms have incompatible types
+    //~| NOTE expected (), found integer
+    //~| NOTE expected type `()`
+}
diff --git a/src/test/ui/if/if-let-arm-types.stderr b/src/test/ui/if/if-let-arm-types.stderr
new file mode 100644
index 0000000..b986973
--- /dev/null
+++ b/src/test/ui/if/if-let-arm-types.stderr
@@ -0,0 +1,18 @@
+error[E0308]: `if let` arms have incompatible types
+  --> $DIR/if-let-arm-types.rs:6:9
+   |
+LL | /     if let Some(b) = None {
+LL | |
+LL | |         ()
+LL | |     } else {
+LL | |         1
+   | |         ^ expected (), found integer
+LL | |     };
+   | |_____- `if let` arms have incompatible types
+   |
+   = note: expected type `()`
+              found type `{integer}`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/if/if-let.rs b/src/test/ui/if/if-let.rs
new file mode 100644
index 0000000..741685f
--- /dev/null
+++ b/src/test/ui/if/if-let.rs
@@ -0,0 +1,47 @@
+// compile-pass
+
+fn macros() {
+    macro_rules! foo{
+        ($p:pat, $e:expr, $b:block) => {{
+            if let $p = $e $b
+        }}
+    }
+    macro_rules! bar{
+        ($p:pat, $e:expr, $b:block) => {{
+            foo!($p, $e, $b)
+        }}
+    }
+
+    foo!(a, 1, { //~ WARN irrefutable if-let
+        println!("irrefutable pattern");
+    });
+    bar!(a, 1, { //~ WARN irrefutable if-let
+        println!("irrefutable pattern");
+    });
+}
+
+pub fn main() {
+    if let a = 1 { //~ WARN irrefutable if-let
+        println!("irrefutable pattern");
+    }
+
+    if let a = 1 { //~ WARN irrefutable if-let
+        println!("irrefutable pattern");
+    } else if true {
+        println!("else-if in irrefutable if-let");
+    } else {
+        println!("else in irrefutable if-let");
+    }
+
+    if let 1 = 2 {
+        println!("refutable pattern");
+    } else if let a = 1 { //~ WARN irrefutable if-let
+        println!("irrefutable pattern");
+    }
+
+    if true {
+        println!("if");
+    } else if let a = 1 { //~ WARN irrefutable if-let
+        println!("irrefutable pattern");
+    }
+}
diff --git a/src/test/ui/if/if-let.stderr b/src/test/ui/if/if-let.stderr
new file mode 100644
index 0000000..04bca1b
--- /dev/null
+++ b/src/test/ui/if/if-let.stderr
@@ -0,0 +1,62 @@
+warning: irrefutable if-let pattern
+  --> $DIR/if-let.rs:6:13
+   |
+LL |               if let $p = $e $b
+   |               ^^
+...
+LL | /     foo!(a, 1, {
+LL | |         println!("irrefutable pattern");
+LL | |     });
+   | |_______- in this macro invocation
+   |
+   = note: #[warn(irrefutable_let_patterns)] on by default
+
+warning: irrefutable if-let pattern
+  --> $DIR/if-let.rs:6:13
+   |
+LL |               if let $p = $e $b
+   |               ^^
+...
+LL | /     bar!(a, 1, {
+LL | |         println!("irrefutable pattern");
+LL | |     });
+   | |_______- in this macro invocation
+
+warning: irrefutable if-let pattern
+  --> $DIR/if-let.rs:24:5
+   |
+LL | /     if let a = 1 {
+LL | |         println!("irrefutable pattern");
+LL | |     }
+   | |_____^
+
+warning: irrefutable if-let pattern
+  --> $DIR/if-let.rs:28:5
+   |
+LL | /     if let a = 1 {
+LL | |         println!("irrefutable pattern");
+LL | |     } else if true {
+LL | |         println!("else-if in irrefutable if-let");
+LL | |     } else {
+LL | |         println!("else in irrefutable if-let");
+LL | |     }
+   | |_____^
+
+warning: irrefutable if-let pattern
+  --> $DIR/if-let.rs:38:12
+   |
+LL |       } else if let a = 1 {
+   |  ____________^
+LL | |         println!("irrefutable pattern");
+LL | |     }
+   | |_____^
+
+warning: irrefutable if-let pattern
+  --> $DIR/if-let.rs:44:12
+   |
+LL |       } else if let a = 1 {
+   |  ____________^
+LL | |         println!("irrefutable pattern");
+LL | |     }
+   | |_____^
+
diff --git a/src/test/ui/if/if-loop.rs b/src/test/ui/if/if-loop.rs
new file mode 100644
index 0000000..c799df2
--- /dev/null
+++ b/src/test/ui/if/if-loop.rs
@@ -0,0 +1,10 @@
+// compile-pass
+// skip-codegen
+#![allow(warnings)]
+// This used to ICE because the "if" being unreachable was not handled correctly
+fn err() {
+    if loop {} {}
+}
+
+
+fn main() {}
diff --git a/src/test/ui/if/if-typeck.rs b/src/test/ui/if/if-typeck.rs
new file mode 100644
index 0000000..d8c262b
--- /dev/null
+++ b/src/test/ui/if/if-typeck.rs
@@ -0,0 +1,10 @@
+// error-pattern:mismatched types
+// issue #513
+
+fn f() { }
+
+fn main() {
+
+    // f is not a bool
+    if f { }
+}
diff --git a/src/test/ui/if/if-typeck.stderr b/src/test/ui/if/if-typeck.stderr
new file mode 100644
index 0000000..714d3eb
--- /dev/null
+++ b/src/test/ui/if/if-typeck.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/if-typeck.rs:9:8
+   |
+LL |     if f { }
+   |        ^ expected bool, found fn item
+   |
+   = note: expected type `bool`
+              found type `fn() {f}`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/if/if-without-block.rs b/src/test/ui/if/if-without-block.rs
new file mode 100644
index 0000000..3dde0ed
--- /dev/null
+++ b/src/test/ui/if/if-without-block.rs
@@ -0,0 +1,9 @@
+fn main() {
+    let n = 1;
+    if 5 == {
+    //~^ NOTE this `if` statement has a condition, but no block
+        println!("five");
+    }
+}
+//~^ ERROR expected `{`, found `}`
+//~| NOTE expected `{`
diff --git a/src/test/ui/if/if-without-block.stderr b/src/test/ui/if/if-without-block.stderr
new file mode 100644
index 0000000..1e45045
--- /dev/null
+++ b/src/test/ui/if/if-without-block.stderr
@@ -0,0 +1,11 @@
+error: expected `{`, found `}`
+  --> $DIR/if-without-block.rs:7:1
+   |
+LL |     if 5 == {
+   |     -- this `if` statement has a condition, but no block
+...
+LL | }
+   | ^ expected `{`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/if/if-without-else-as-fn-expr.rs b/src/test/ui/if/if-without-else-as-fn-expr.rs
new file mode 100644
index 0000000..67e4445
--- /dev/null
+++ b/src/test/ui/if/if-without-else-as-fn-expr.rs
@@ -0,0 +1,25 @@
+fn foo(bar: usize) -> usize {
+    if bar % 5 == 0 {
+        return 3;
+    }
+    //~^^^ ERROR if may be missing an else clause
+}
+
+fn foo2(bar: usize) -> usize {
+    let x: usize = if bar % 5 == 0 {
+        return 3;
+    };
+    //~^^^ ERROR if may be missing an else clause
+    x
+}
+
+fn foo3(bar: usize) -> usize {
+    if bar % 5 == 0 {
+        3
+    }
+    //~^^^ ERROR if may be missing an else clause
+}
+
+fn main() {
+    let _ = foo(1);
+}
diff --git a/src/test/ui/if/if-without-else-as-fn-expr.stderr b/src/test/ui/if/if-without-else-as-fn-expr.stderr
new file mode 100644
index 0000000..0ba7272
--- /dev/null
+++ b/src/test/ui/if/if-without-else-as-fn-expr.stderr
@@ -0,0 +1,49 @@
+error[E0317]: if may be missing an else clause
+  --> $DIR/if-without-else-as-fn-expr.rs:2:5
+   |
+LL |   fn foo(bar: usize) -> usize {
+   |                         ----- expected `usize` because of this return type
+LL | /     if bar % 5 == 0 {
+LL | |         return 3;
+LL | |     }
+   | |_____^ expected usize, found ()
+   |
+   = note: expected type `usize`
+              found type `()`
+   = note: `if` expressions without `else` evaluate to `()`
+   = help: consider adding an `else` block that evaluates to the expected type
+
+error[E0317]: if may be missing an else clause
+  --> $DIR/if-without-else-as-fn-expr.rs:9:20
+   |
+LL |       let x: usize = if bar % 5 == 0 {
+   |  _________-__________^
+   | |         |
+   | |         expected because of this assignment
+LL | |         return 3;
+LL | |     };
+   | |_____^ expected usize, found ()
+   |
+   = note: expected type `usize`
+              found type `()`
+   = note: `if` expressions without `else` evaluate to `()`
+   = help: consider adding an `else` block that evaluates to the expected type
+
+error[E0317]: if may be missing an else clause
+  --> $DIR/if-without-else-as-fn-expr.rs:17:5
+   |
+LL |   fn foo3(bar: usize) -> usize {
+   |                          ----- expected `usize` because of this return type
+LL | /     if bar % 5 == 0 {
+LL | |         3
+LL | |     }
+   | |_____^ expected usize, found ()
+   |
+   = note: expected type `usize`
+              found type `()`
+   = note: `if` expressions without `else` evaluate to `()`
+   = help: consider adding an `else` block that evaluates to the expected type
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0317`.
diff --git a/src/test/ui/if/if-without-else-result.rs b/src/test/ui/if/if-without-else-result.rs
new file mode 100644
index 0000000..cd7fde4
--- /dev/null
+++ b/src/test/ui/if/if-without-else-result.rs
@@ -0,0 +1,8 @@
+fn main() {
+    let a = if true { true };
+    //~^ ERROR if may be missing an else clause [E0317]
+    //~| expected type `()`
+    //~| found type `bool`
+    //~| expected (), found bool
+    println!("{}", a);
+}
diff --git a/src/test/ui/if/if-without-else-result.stderr b/src/test/ui/if/if-without-else-result.stderr
new file mode 100644
index 0000000..ddb013a
--- /dev/null
+++ b/src/test/ui/if/if-without-else-result.stderr
@@ -0,0 +1,17 @@
+error[E0317]: if may be missing an else clause
+  --> $DIR/if-without-else-result.rs:2:13
+   |
+LL |     let a = if true { true };
+   |             ^^^^^^^^^^----^^
+   |             |         |
+   |             |         found here
+   |             expected (), found bool
+   |
+   = note: expected type `()`
+              found type `bool`
+   = note: `if` expressions without `else` evaluate to `()`
+   = help: consider adding an `else` block that evaluates to the expected type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0317`.
diff --git a/src/test/ui/if/ifmt-bad-arg.rs b/src/test/ui/if/ifmt-bad-arg.rs
new file mode 100644
index 0000000..a57221a
--- /dev/null
+++ b/src/test/ui/if/ifmt-bad-arg.rs
@@ -0,0 +1,78 @@
+fn main() {
+    // bad arguments to the format! call
+
+    // bad number of arguments, see #44954 (originally #15780)
+
+    format!("{}");
+    //~^ ERROR: 1 positional argument in format string, but no arguments were given
+
+    format!("{1}", 1);
+    //~^ ERROR: invalid reference to positional argument 1 (there is 1 argument)
+    //~^^ ERROR: argument never used
+
+    format!("{} {}");
+    //~^ ERROR: 2 positional arguments in format string, but no arguments were given
+
+    format!("{0} {1}", 1);
+    //~^ ERROR: invalid reference to positional argument 1 (there is 1 argument)
+
+    format!("{0} {1} {2}", 1, 2);
+    //~^ ERROR: invalid reference to positional argument 2 (there are 2 arguments)
+
+    format!("{} {value} {} {}", 1, value=2);
+    //~^ ERROR: invalid reference to positional argument 2 (there are 2 arguments)
+    format!("{name} {value} {} {} {} {} {} {}", 0, name=1, value=2);
+    //~^ ERROR: invalid reference to positional arguments 3, 4 and 5 (there are 3 arguments)
+
+    format!("{} {foo} {} {bar} {}", 1, 2, 3);
+    //~^ ERROR: there is no argument named `foo`
+    //~^^ ERROR: there is no argument named `bar`
+
+    format!("{foo}");                //~ ERROR: no argument named `foo`
+    format!("", 1, 2);               //~ ERROR: multiple unused formatting arguments
+    format!("{}", 1, 2);             //~ ERROR: argument never used
+    format!("{1}", 1, 2);            //~ ERROR: argument never used
+    format!("{}", 1, foo=2);         //~ ERROR: named argument never used
+    format!("{foo}", 1, foo=2);      //~ ERROR: argument never used
+    format!("", foo=2);              //~ ERROR: named argument never used
+    format!("{} {}", 1, 2, foo=1, bar=2);  //~ ERROR: multiple unused formatting arguments
+
+    format!("{foo}", foo=1, foo=2);  //~ ERROR: duplicate argument
+    format!("", foo=1, 2);           //~ ERROR: positional arguments cannot follow
+
+    // bad named arguments, #35082
+
+    format!("{valuea} {valueb}", valuea=5, valuec=7);
+    //~^ ERROR there is no argument named `valueb`
+    //~^^ ERROR named argument never used
+
+    // bad syntax of the format string
+
+    format!("{"); //~ ERROR: expected `'}'` but string was terminated
+
+    format!("foo } bar"); //~ ERROR: unmatched `}` found
+    format!("foo }"); //~ ERROR: unmatched `}` found
+
+    format!("foo %s baz", "bar"); //~ ERROR: argument never used
+
+    format!(r##"
+
+        {foo}
+
+    "##);
+    //~^^^ ERROR: there is no argument named `foo`
+
+    // bad syntax in format string with multiple newlines, #53836
+    format!("first number: {}
+second number: {}
+third number: {}
+fourth number: {}
+fifth number: {}
+sixth number: {}
+seventh number: {}
+eighth number: {}
+ninth number: {
+tenth number: {}",
+        1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+    //~^^ ERROR: invalid format string
+}
diff --git a/src/test/ui/if/ifmt-bad-arg.stderr b/src/test/ui/if/ifmt-bad-arg.stderr
new file mode 100644
index 0000000..65be86e
--- /dev/null
+++ b/src/test/ui/if/ifmt-bad-arg.stderr
@@ -0,0 +1,222 @@
+error: 1 positional argument in format string, but no arguments were given
+  --> $DIR/ifmt-bad-arg.rs:6:14
+   |
+LL |     format!("{}");
+   |              ^^
+
+error: invalid reference to positional argument 1 (there is 1 argument)
+  --> $DIR/ifmt-bad-arg.rs:9:14
+   |
+LL |     format!("{1}", 1);
+   |              ^^^
+   |
+   = note: positional arguments are zero-based
+
+error: argument never used
+  --> $DIR/ifmt-bad-arg.rs:9:20
+   |
+LL |     format!("{1}", 1);
+   |             -----  ^ argument never used
+   |             |
+   |             formatting specifier missing
+
+error: 2 positional arguments in format string, but no arguments were given
+  --> $DIR/ifmt-bad-arg.rs:13:14
+   |
+LL |     format!("{} {}");
+   |              ^^ ^^
+
+error: invalid reference to positional argument 1 (there is 1 argument)
+  --> $DIR/ifmt-bad-arg.rs:16:18
+   |
+LL |     format!("{0} {1}", 1);
+   |                  ^^^
+   |
+   = note: positional arguments are zero-based
+
+error: invalid reference to positional argument 2 (there are 2 arguments)
+  --> $DIR/ifmt-bad-arg.rs:19:22
+   |
+LL |     format!("{0} {1} {2}", 1, 2);
+   |                      ^^^
+   |
+   = note: positional arguments are zero-based
+
+error: invalid reference to positional argument 2 (there are 2 arguments)
+  --> $DIR/ifmt-bad-arg.rs:22:28
+   |
+LL |     format!("{} {value} {} {}", 1, value=2);
+   |                            ^^
+   |
+   = note: positional arguments are zero-based
+
+error: invalid reference to positional arguments 3, 4 and 5 (there are 3 arguments)
+  --> $DIR/ifmt-bad-arg.rs:24:38
+   |
+LL |     format!("{name} {value} {} {} {} {} {} {}", 0, name=1, value=2);
+   |                                      ^^ ^^ ^^
+   |
+   = note: positional arguments are zero-based
+
+error: there is no argument named `foo`
+  --> $DIR/ifmt-bad-arg.rs:27:17
+   |
+LL |     format!("{} {foo} {} {bar} {}", 1, 2, 3);
+   |                 ^^^^^
+
+error: there is no argument named `bar`
+  --> $DIR/ifmt-bad-arg.rs:27:26
+   |
+LL |     format!("{} {foo} {} {bar} {}", 1, 2, 3);
+   |                          ^^^^^
+
+error: there is no argument named `foo`
+  --> $DIR/ifmt-bad-arg.rs:31:14
+   |
+LL |     format!("{foo}");
+   |              ^^^^^
+
+error: multiple unused formatting arguments
+  --> $DIR/ifmt-bad-arg.rs:32:17
+   |
+LL |     format!("", 1, 2);
+   |             --  ^  ^ argument never used
+   |             |   |
+   |             |   argument never used
+   |             multiple missing formatting specifiers
+
+error: argument never used
+  --> $DIR/ifmt-bad-arg.rs:33:22
+   |
+LL |     format!("{}", 1, 2);
+   |             ----     ^ argument never used
+   |             |
+   |             formatting specifier missing
+
+error: argument never used
+  --> $DIR/ifmt-bad-arg.rs:34:20
+   |
+LL |     format!("{1}", 1, 2);
+   |             -----  ^ argument never used
+   |             |
+   |             formatting specifier missing
+
+error: named argument never used
+  --> $DIR/ifmt-bad-arg.rs:35:26
+   |
+LL |     format!("{}", 1, foo=2);
+   |             ----         ^ named argument never used
+   |             |
+   |             formatting specifier missing
+
+error: argument never used
+  --> $DIR/ifmt-bad-arg.rs:36:22
+   |
+LL |     format!("{foo}", 1, foo=2);
+   |             -------  ^ argument never used
+   |             |
+   |             formatting specifier missing
+
+error: named argument never used
+  --> $DIR/ifmt-bad-arg.rs:37:21
+   |
+LL |     format!("", foo=2);
+   |             --      ^ named argument never used
+   |             |
+   |             formatting specifier missing
+
+error: multiple unused formatting arguments
+  --> $DIR/ifmt-bad-arg.rs:38:32
+   |
+LL |     format!("{} {}", 1, 2, foo=1, bar=2);
+   |             -------            ^      ^ named argument never used
+   |             |                  |
+   |             |                  named argument never used
+   |             multiple missing formatting specifiers
+
+error: duplicate argument named `foo`
+  --> $DIR/ifmt-bad-arg.rs:40:33
+   |
+LL |     format!("{foo}", foo=1, foo=2);
+   |                                 ^
+   |
+note: previously here
+  --> $DIR/ifmt-bad-arg.rs:40:26
+   |
+LL |     format!("{foo}", foo=1, foo=2);
+   |                          ^
+
+error: expected ident, positional arguments cannot follow named arguments
+  --> $DIR/ifmt-bad-arg.rs:41:24
+   |
+LL |     format!("", foo=1, 2);
+   |                        ^
+
+error: there is no argument named `valueb`
+  --> $DIR/ifmt-bad-arg.rs:45:23
+   |
+LL |     format!("{valuea} {valueb}", valuea=5, valuec=7);
+   |                       ^^^^^^^^
+
+error: named argument never used
+  --> $DIR/ifmt-bad-arg.rs:45:51
+   |
+LL |     format!("{valuea} {valueb}", valuea=5, valuec=7);
+   |             -------------------                   ^ named argument never used
+   |             |
+   |             formatting specifier missing
+
+error: invalid format string: expected `'}'` but string was terminated
+  --> $DIR/ifmt-bad-arg.rs:51:15
+   |
+LL |     format!("{");
+   |              -^ expected `'}'` in format string
+   |              |
+   |              because of this opening brace
+   |
+   = note: if you intended to print `{`, you can escape it using `{{`
+
+error: invalid format string: unmatched `}` found
+  --> $DIR/ifmt-bad-arg.rs:53:18
+   |
+LL |     format!("foo } bar");
+   |                  ^ unmatched `}` in format string
+   |
+   = note: if you intended to print `}`, you can escape it using `}}`
+
+error: invalid format string: unmatched `}` found
+  --> $DIR/ifmt-bad-arg.rs:54:18
+   |
+LL |     format!("foo }");
+   |                  ^ unmatched `}` in format string
+   |
+   = note: if you intended to print `}`, you can escape it using `}}`
+
+error: argument never used
+  --> $DIR/ifmt-bad-arg.rs:56:27
+   |
+LL |     format!("foo %s baz", "bar");
+   |                  --       ^^^^^ argument never used
+   |                  |
+   |                  help: format specifiers use curly braces: `{}`
+   |
+   = note: printf formatting not supported; see the documentation for `std::fmt`
+
+error: there is no argument named `foo`
+  --> $DIR/ifmt-bad-arg.rs:60:9
+   |
+LL |         {foo}
+   |         ^^^^^
+
+error: invalid format string: expected `'}'`, found `'t'`
+  --> $DIR/ifmt-bad-arg.rs:75:1
+   |
+LL | ninth number: {
+   |               - because of this opening brace
+LL | tenth number: {}",
+   | ^ expected `}` in format string
+   |
+   = note: if you intended to print `{`, you can escape it using `{{`
+
+error: aborting due to 28 previous errors
+
diff --git a/src/test/ui/if/ifmt-bad-format-args.rs b/src/test/ui/if/ifmt-bad-format-args.rs
new file mode 100644
index 0000000..ba73015
--- /dev/null
+++ b/src/test/ui/if/ifmt-bad-format-args.rs
@@ -0,0 +1,4 @@
+fn main() {
+    format_args!(); //~ ERROR: requires at least a format string argument
+    format_args!(|| {}); //~ ERROR: must be a string literal
+}
diff --git a/src/test/ui/if/ifmt-bad-format-args.stderr b/src/test/ui/if/ifmt-bad-format-args.stderr
new file mode 100644
index 0000000..9dc2b8f
--- /dev/null
+++ b/src/test/ui/if/ifmt-bad-format-args.stderr
@@ -0,0 +1,18 @@
+error: requires at least a format string argument
+  --> $DIR/ifmt-bad-format-args.rs:2:5
+   |
+LL |     format_args!();
+   |     ^^^^^^^^^^^^^^^
+
+error: format argument must be a string literal
+  --> $DIR/ifmt-bad-format-args.rs:3:18
+   |
+LL |     format_args!(|| {});
+   |                  ^^^^^
+help: you might be missing a string literal to format with
+   |
+LL |     format_args!("{}", || {});
+   |                  ^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/if/ifmt-unimpl.rs b/src/test/ui/if/ifmt-unimpl.rs
new file mode 100644
index 0000000..65daae4
--- /dev/null
+++ b/src/test/ui/if/ifmt-unimpl.rs
@@ -0,0 +1,4 @@
+fn main() {
+    format!("{:X}", "3");
+    //~^ ERROR: `str: std::fmt::UpperHex` is not satisfied
+}
diff --git a/src/test/ui/if/ifmt-unimpl.stderr b/src/test/ui/if/ifmt-unimpl.stderr
new file mode 100644
index 0000000..7a7e4b3
--- /dev/null
+++ b/src/test/ui/if/ifmt-unimpl.stderr
@@ -0,0 +1,12 @@
+error[E0277]: the trait bound `str: std::fmt::UpperHex` is not satisfied
+  --> $DIR/ifmt-unimpl.rs:2:21
+   |
+LL |     format!("{:X}", "3");
+   |                     ^^^ the trait `std::fmt::UpperHex` is not implemented for `str`
+   |
+   = note: required because of the requirements on the impl of `std::fmt::UpperHex` for `&str`
+   = note: required by `std::fmt::UpperHex::fmt`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/if/ifmt-unknown-trait.rs b/src/test/ui/if/ifmt-unknown-trait.rs
new file mode 100644
index 0000000..158152c8
--- /dev/null
+++ b/src/test/ui/if/ifmt-unknown-trait.rs
@@ -0,0 +1,4 @@
+fn main() {
+    format!("{:notimplemented}", "3");
+    //~^ ERROR: unknown format trait `notimplemented`
+}
diff --git a/src/test/ui/if/ifmt-unknown-trait.stderr b/src/test/ui/if/ifmt-unknown-trait.stderr
new file mode 100644
index 0000000..9ea367c
--- /dev/null
+++ b/src/test/ui/if/ifmt-unknown-trait.stderr
@@ -0,0 +1,8 @@
+error: unknown format trait `notimplemented`
+  --> $DIR/ifmt-unknown-trait.rs:2:34
+   |
+LL |     format!("{:notimplemented}", "3");
+   |                                  ^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/illegal-ufcs-drop.rs b/src/test/ui/illegal-ufcs-drop.rs
new file mode 100644
index 0000000..5c07266
--- /dev/null
+++ b/src/test/ui/illegal-ufcs-drop.rs
@@ -0,0 +1,9 @@
+struct Foo;
+
+impl Drop for Foo {
+    fn drop(&mut self) {}
+}
+
+fn main() {
+    Drop::drop(&mut Foo) //~ ERROR explicit use of destructor method
+}
diff --git a/src/test/ui/illegal-ufcs-drop.stderr b/src/test/ui/illegal-ufcs-drop.stderr
new file mode 100644
index 0000000..d35d376
--- /dev/null
+++ b/src/test/ui/illegal-ufcs-drop.stderr
@@ -0,0 +1,9 @@
+error[E0040]: explicit use of destructor method
+  --> $DIR/illegal-ufcs-drop.rs:8:5
+   |
+LL |     Drop::drop(&mut Foo)
+   |     ^^^^^^^^^^ explicit destructor calls not allowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0040`.
diff --git a/src/test/ui/immut-function-arguments.ast.nll.stderr b/src/test/ui/immut-function-arguments.ast.nll.stderr
new file mode 100644
index 0000000..5085f36
--- /dev/null
+++ b/src/test/ui/immut-function-arguments.ast.nll.stderr
@@ -0,0 +1,19 @@
+error[E0594]: cannot assign to `*y`, as `y` is not declared as mutable
+  --> $DIR/immut-function-arguments.rs:5:5
+   |
+LL | fn f(y: Box<isize>) {
+   |      - help: consider changing this to be mutable: `mut y`
+LL |     *y = 5;
+   |     ^^^^^^ cannot assign
+
+error[E0594]: cannot assign to `*q`, as `q` is not declared as mutable
+  --> $DIR/immut-function-arguments.rs:10:35
+   |
+LL |     let _frob = |q: Box<isize>| { *q = 2; };
+   |                  -                ^^^^^^ cannot assign
+   |                  |
+   |                  help: consider changing this to be mutable: `mut q`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/immut-function-arguments.ast.stderr b/src/test/ui/immut-function-arguments.ast.stderr
new file mode 100644
index 0000000..f371a13
--- /dev/null
+++ b/src/test/ui/immut-function-arguments.ast.stderr
@@ -0,0 +1,19 @@
+error[E0594]: cannot assign to immutable `Box` content `*y`
+  --> $DIR/immut-function-arguments.rs:5:5
+   |
+LL | fn f(y: Box<isize>) {
+   |      - help: make this binding mutable: `mut y`
+LL |     *y = 5;
+   |     ^^^^^^ cannot borrow as mutable
+
+error[E0594]: cannot assign to immutable `Box` content `*q`
+  --> $DIR/immut-function-arguments.rs:10:35
+   |
+LL |     let _frob = |q: Box<isize>| { *q = 2; };
+   |                  -                ^^^^^^ cannot borrow as mutable
+   |                  |
+   |                  help: make this binding mutable: `mut q`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/immut-function-arguments.mir.stderr b/src/test/ui/immut-function-arguments.mir.stderr
new file mode 100644
index 0000000..5085f36
--- /dev/null
+++ b/src/test/ui/immut-function-arguments.mir.stderr
@@ -0,0 +1,19 @@
+error[E0594]: cannot assign to `*y`, as `y` is not declared as mutable
+  --> $DIR/immut-function-arguments.rs:5:5
+   |
+LL | fn f(y: Box<isize>) {
+   |      - help: consider changing this to be mutable: `mut y`
+LL |     *y = 5;
+   |     ^^^^^^ cannot assign
+
+error[E0594]: cannot assign to `*q`, as `q` is not declared as mutable
+  --> $DIR/immut-function-arguments.rs:10:35
+   |
+LL |     let _frob = |q: Box<isize>| { *q = 2; };
+   |                  -                ^^^^^^ cannot assign
+   |                  |
+   |                  help: consider changing this to be mutable: `mut q`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/immut-function-arguments.rs b/src/test/ui/immut-function-arguments.rs
new file mode 100644
index 0000000..2cc9c69
--- /dev/null
+++ b/src/test/ui/immut-function-arguments.rs
@@ -0,0 +1,14 @@
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+fn f(y: Box<isize>) {
+    *y = 5; //[ast]~ ERROR cannot assign
+            //[mir]~^ ERROR cannot assign
+}
+
+fn g() {
+    let _frob = |q: Box<isize>| { *q = 2; }; //[ast]~ ERROR cannot assign
+    //[mir]~^ ERROR cannot assign
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-bounds-checking.rs b/src/test/ui/impl-bounds-checking.rs
new file mode 100644
index 0000000..5e65a27
--- /dev/null
+++ b/src/test/ui/impl-bounds-checking.rs
@@ -0,0 +1,14 @@
+pub trait Clone2 {
+    fn clone(&self) -> Self;
+}
+
+
+trait Getter<T: Clone2> {
+    fn get(&self) -> T;
+}
+
+impl Getter<isize> for isize { //~ ERROR `isize: Clone2` is not satisfied
+    fn get(&self) -> isize { *self }
+}
+
+fn main() { }
diff --git a/src/test/ui/impl-bounds-checking.stderr b/src/test/ui/impl-bounds-checking.stderr
new file mode 100644
index 0000000..b52f3d6
--- /dev/null
+++ b/src/test/ui/impl-bounds-checking.stderr
@@ -0,0 +1,9 @@
+error[E0277]: the trait bound `isize: Clone2` is not satisfied
+  --> $DIR/impl-bounds-checking.rs:10:6
+   |
+LL | impl Getter<isize> for isize {
+   |      ^^^^^^^^^^^^^ the trait `Clone2` is not implemented for `isize`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/impl-duplicate-methods.rs b/src/test/ui/impl-duplicate-methods.rs
new file mode 100644
index 0000000..adb09d7
--- /dev/null
+++ b/src/test/ui/impl-duplicate-methods.rs
@@ -0,0 +1,9 @@
+struct Foo;
+
+impl Foo {
+    fn orange(&self) {}
+    fn orange(&self) {}
+    //~^ ERROR duplicate definition
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-duplicate-methods.stderr b/src/test/ui/impl-duplicate-methods.stderr
new file mode 100644
index 0000000..b6dc488
--- /dev/null
+++ b/src/test/ui/impl-duplicate-methods.stderr
@@ -0,0 +1,11 @@
+error[E0201]: duplicate definitions with name `orange`:
+  --> $DIR/impl-duplicate-methods.rs:5:5
+   |
+LL |     fn orange(&self) {}
+   |     ------------------- previous definition of `orange` here
+LL |     fn orange(&self) {}
+   |     ^^^^^^^^^^^^^^^^^^^ duplicate definition
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0201`.
diff --git a/src/test/ui/impl-header-lifetime-elision/assoc-type.rs b/src/test/ui/impl-header-lifetime-elision/assoc-type.rs
new file mode 100644
index 0000000..44c46e4
--- /dev/null
+++ b/src/test/ui/impl-header-lifetime-elision/assoc-type.rs
@@ -0,0 +1,25 @@
+// Test that we do not yet support elision in associated types, even
+// when there is just one name we could take from the impl header.
+
+#![allow(warnings)]
+
+trait MyTrait {
+    type Output;
+}
+
+impl MyTrait for &i32 {
+    type Output = &i32;
+    //~^ ERROR missing lifetime specifier
+}
+
+impl MyTrait for &u32 {
+    type Output = &'_ i32;
+    //~^ ERROR missing lifetime specifier
+}
+
+// This is what you have to do:
+impl<'a> MyTrait for &'a f32 {
+    type Output = &'a f32;
+}
+
+fn main() { }
diff --git a/src/test/ui/impl-header-lifetime-elision/assoc-type.stderr b/src/test/ui/impl-header-lifetime-elision/assoc-type.stderr
new file mode 100644
index 0000000..492ca87
--- /dev/null
+++ b/src/test/ui/impl-header-lifetime-elision/assoc-type.stderr
@@ -0,0 +1,15 @@
+error[E0106]: missing lifetime specifier
+  --> $DIR/assoc-type.rs:11:19
+   |
+LL |     type Output = &i32;
+   |                   ^ expected lifetime parameter
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/assoc-type.rs:16:20
+   |
+LL |     type Output = &'_ i32;
+   |                    ^^ expected lifetime parameter
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0106`.
diff --git a/src/test/ui/impl-header-lifetime-elision/dyn-trait.rs b/src/test/ui/impl-header-lifetime-elision/dyn-trait.rs
new file mode 100644
index 0000000..d4ad706
--- /dev/null
+++ b/src/test/ui/impl-header-lifetime-elision/dyn-trait.rs
@@ -0,0 +1,31 @@
+// Test that `impl MyTrait<'_> for &i32` is equivalent to `impl<'a,
+// 'b> MyTrait<'a> for &'b i32`.
+
+#![allow(warnings)]
+
+use std::fmt::Debug;
+
+// Equivalent to `Box<dyn Debug + 'static>`:
+trait StaticTrait { }
+impl StaticTrait for Box<dyn Debug> { }
+
+// Equivalent to `Box<dyn Debug + 'static>`:
+trait NotStaticTrait { }
+impl NotStaticTrait for Box<dyn Debug + '_> { }
+
+fn static_val<T: StaticTrait>(_: T) {
+}
+
+fn with_dyn_debug_static<'a>(x: Box<dyn Debug + 'a>) {
+    static_val(x); //~ ERROR cannot infer
+}
+
+fn not_static_val<T: NotStaticTrait>(_: T) {
+}
+
+fn with_dyn_debug_not_static<'a>(x: Box<dyn Debug + 'a>) {
+    not_static_val(x); // OK
+}
+
+fn main() {
+}
diff --git a/src/test/ui/impl-header-lifetime-elision/dyn-trait.stderr b/src/test/ui/impl-header-lifetime-elision/dyn-trait.stderr
new file mode 100644
index 0000000..af120fa
--- /dev/null
+++ b/src/test/ui/impl-header-lifetime-elision/dyn-trait.stderr
@@ -0,0 +1,22 @@
+error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
+  --> $DIR/dyn-trait.rs:20:16
+   |
+LL |     static_val(x);
+   |                ^
+   |
+note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 19:26...
+  --> $DIR/dyn-trait.rs:19:26
+   |
+LL | fn with_dyn_debug_static<'a>(x: Box<dyn Debug + 'a>) {
+   |                          ^^
+   = note: ...so that the expression is assignable:
+           expected std::boxed::Box<dyn std::fmt::Debug>
+              found std::boxed::Box<(dyn std::fmt::Debug + 'a)>
+   = note: but, the lifetime must be valid for the static lifetime...
+   = note: ...so that the types are compatible:
+           expected StaticTrait
+              found StaticTrait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0495`.
diff --git a/src/test/ui/impl-header-lifetime-elision/explicit-and-elided-same-header.rs b/src/test/ui/impl-header-lifetime-elision/explicit-and-elided-same-header.rs
new file mode 100644
index 0000000..6301ac4
--- /dev/null
+++ b/src/test/ui/impl-header-lifetime-elision/explicit-and-elided-same-header.rs
@@ -0,0 +1,13 @@
+// run-pass
+
+#![allow(warnings)]
+
+// This works for functions...
+fn foo<'a>(x: &str, y: &'a str) {}
+
+// ...so this should work for impls
+impl<'a> Foo<&str> for &'a str {}
+trait Foo<T> {}
+
+fn main() {
+}
diff --git a/src/test/ui/impl-header-lifetime-elision/inherent-impl.rs b/src/test/ui/impl-header-lifetime-elision/inherent-impl.rs
new file mode 100644
index 0000000..20d778d
--- /dev/null
+++ b/src/test/ui/impl-header-lifetime-elision/inherent-impl.rs
@@ -0,0 +1,9 @@
+// compile-pass
+
+struct Foo<'a>(&'a u8);
+
+impl Foo<'_> {
+    fn x() {}
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-header-lifetime-elision/path-elided.rs b/src/test/ui/impl-header-lifetime-elision/path-elided.rs
new file mode 100644
index 0000000..6532b0a
--- /dev/null
+++ b/src/test/ui/impl-header-lifetime-elision/path-elided.rs
@@ -0,0 +1,11 @@
+#![allow(warnings)]
+
+trait MyTrait { }
+
+struct Foo<'a> { x: &'a u32 }
+
+impl MyTrait for Foo {
+    //~^ ERROR missing lifetime specifier
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-header-lifetime-elision/path-elided.stderr b/src/test/ui/impl-header-lifetime-elision/path-elided.stderr
new file mode 100644
index 0000000..c9287ff
--- /dev/null
+++ b/src/test/ui/impl-header-lifetime-elision/path-elided.stderr
@@ -0,0 +1,9 @@
+error[E0106]: missing lifetime specifier
+  --> $DIR/path-elided.rs:7:18
+   |
+LL | impl MyTrait for Foo {
+   |                  ^^^ expected lifetime parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0106`.
diff --git a/src/test/ui/impl-header-lifetime-elision/path-underscore.rs b/src/test/ui/impl-header-lifetime-elision/path-underscore.rs
new file mode 100644
index 0000000..f39ba57
--- /dev/null
+++ b/src/test/ui/impl-header-lifetime-elision/path-underscore.rs
@@ -0,0 +1,34 @@
+// Test that `impl MyTrait for Foo<'_>` works.
+
+// run-pass
+
+#![allow(warnings)]
+
+trait MyTrait { }
+
+struct Foo<'a> { x: &'a u32 }
+
+impl MyTrait for Foo<'_> {
+}
+
+fn impls_my_trait<T: MyTrait>() { }
+
+fn impls_my_trait_val<T: MyTrait>(_: T) {
+    impls_my_trait::<T>();
+}
+
+fn random_where_clause()
+where for<'a> Foo<'a>: MyTrait { }
+
+fn main() {
+    let x = 22;
+    let f = Foo { x: &x };
+
+    // This type is `Foo<'x>` for a local lifetime `'x`; so the impl
+    // must apply to any lifetime to apply to this.
+    impls_my_trait_val(f);
+
+    impls_my_trait::<Foo<'static>>();
+
+    random_where_clause();
+}
diff --git a/src/test/ui/impl-header-lifetime-elision/ref-underscore.rs b/src/test/ui/impl-header-lifetime-elision/ref-underscore.rs
new file mode 100644
index 0000000..5be04d0
--- /dev/null
+++ b/src/test/ui/impl-header-lifetime-elision/ref-underscore.rs
@@ -0,0 +1,30 @@
+// Test that `impl MyTrait for &i32` works and is equivalent to any lifetime.
+
+// run-pass
+
+#![allow(warnings)]
+
+trait MyTrait { }
+
+impl MyTrait for &i32 {
+}
+
+fn impls_my_trait<T: MyTrait>() { }
+
+fn impls_my_trait_val<T: MyTrait>(_: T) {
+    impls_my_trait::<T>();
+}
+
+fn random_where_clause()
+where for<'a> &'a i32: MyTrait { }
+
+fn main() {
+    let x = 22;
+    let f = &x;
+
+    impls_my_trait_val(f);
+
+    impls_my_trait::<&'static i32>();
+
+    random_where_clause();
+}
diff --git a/src/test/ui/impl-header-lifetime-elision/trait-elided.rs b/src/test/ui/impl-header-lifetime-elision/trait-elided.rs
new file mode 100644
index 0000000..3979eda
--- /dev/null
+++ b/src/test/ui/impl-header-lifetime-elision/trait-elided.rs
@@ -0,0 +1,9 @@
+#![allow(warnings)]
+
+trait MyTrait<'a> { }
+
+impl MyTrait for u32 {
+    //~^ ERROR missing lifetime specifier
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-header-lifetime-elision/trait-elided.stderr b/src/test/ui/impl-header-lifetime-elision/trait-elided.stderr
new file mode 100644
index 0000000..b742db1
--- /dev/null
+++ b/src/test/ui/impl-header-lifetime-elision/trait-elided.stderr
@@ -0,0 +1,9 @@
+error[E0106]: missing lifetime specifier
+  --> $DIR/trait-elided.rs:5:6
+   |
+LL | impl MyTrait for u32 {
+   |      ^^^^^^^ expected lifetime parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0106`.
diff --git a/src/test/ui/impl-header-lifetime-elision/trait-underscore.rs b/src/test/ui/impl-header-lifetime-elision/trait-underscore.rs
new file mode 100644
index 0000000..3e13b04
--- /dev/null
+++ b/src/test/ui/impl-header-lifetime-elision/trait-underscore.rs
@@ -0,0 +1,35 @@
+// Test that `impl MyTrait<'_> for &i32` is equivalent to `impl<'a,
+// 'b> MyTrait<'a> for &'b i32`.
+//
+// run-pass
+
+#![allow(warnings)]
+
+trait MyTrait<'a> { }
+
+// This is equivalent to `MyTrait<'a> for &'b i32`, which is proven by
+// the code below.
+impl MyTrait<'_> for &i32 {
+}
+
+// When called, T will be `&'x i32` for some `'x`, so since we can
+// prove that `&'x i32: for<'a> MyTrait<'a>, then we know that the
+// lifetime parameter above is disconnected.
+fn impls_my_trait<T: for<'a> MyTrait<'a>>() { }
+
+fn impls_my_trait_val<T: for<'a> MyTrait<'a>>(_: T) {
+    impls_my_trait::<T>();
+}
+
+fn random_where_clause()
+where for<'a, 'b> &'a i32: MyTrait<'b> { }
+
+fn main() {
+    let x = 22;
+    let f = &x;
+    impls_my_trait_val(f);
+
+    impls_my_trait::<&'static i32>();
+
+    random_where_clause();
+}
diff --git a/src/test/ui/impl-trait/associated-existential-type-generic-trait.rs b/src/test/ui/impl-trait/associated-existential-type-generic-trait.rs
new file mode 100644
index 0000000..26bd435
--- /dev/null
+++ b/src/test/ui/impl-trait/associated-existential-type-generic-trait.rs
@@ -0,0 +1,30 @@
+#![feature(existential_type)]
+// compile-pass
+
+trait Bar {}
+struct Dummy<U>(U);
+impl<V> Bar for Dummy<V> {}
+
+trait Foo<T> {
+    type Assoc: Bar;
+    fn foo(t: T) -> Self::Assoc;
+}
+
+impl<W> Foo<W> for i32 {
+    existential type Assoc: Bar;
+    fn foo(w: W) -> Self::Assoc {
+        Dummy(w)
+    }
+}
+
+struct NonGeneric;
+impl Bar for NonGeneric {}
+
+impl<W> Foo<W> for u32 {
+    existential type Assoc: Bar;
+    fn foo(_: W) -> Self::Assoc {
+        NonGeneric
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/associated-existential-type-trivial.rs b/src/test/ui/impl-trait/associated-existential-type-trivial.rs
new file mode 100644
index 0000000..cc974ff
--- /dev/null
+++ b/src/test/ui/impl-trait/associated-existential-type-trivial.rs
@@ -0,0 +1,20 @@
+#![feature(existential_type)]
+// compile-pass
+
+trait Bar {}
+struct Dummy;
+impl Bar for Dummy {}
+
+trait Foo {
+    type Assoc: Bar;
+    fn foo() -> Self::Assoc;
+}
+
+impl Foo for i32 {
+    existential type Assoc: Bar;
+    fn foo() -> Self::Assoc {
+        Dummy
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/associated-existential-type.rs b/src/test/ui/impl-trait/associated-existential-type.rs
new file mode 100644
index 0000000..38511bd0
--- /dev/null
+++ b/src/test/ui/impl-trait/associated-existential-type.rs
@@ -0,0 +1,24 @@
+#![feature(existential_type)]
+// compile-pass
+
+trait Bar {}
+struct Dummy;
+impl Bar for Dummy {}
+
+trait Foo {
+    type Assoc: Bar;
+    fn foo() -> Self::Assoc;
+    fn bar() -> Self::Assoc;
+}
+
+impl Foo for i32 {
+    existential type Assoc: Bar;
+    fn foo() -> Self::Assoc {
+        Dummy
+    }
+    fn bar() -> Self::Assoc {
+        Dummy
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/auto-trait-leak.rs b/src/test/ui/impl-trait/auto-trait-leak.rs
new file mode 100644
index 0000000..ea0be0b
--- /dev/null
+++ b/src/test/ui/impl-trait/auto-trait-leak.rs
@@ -0,0 +1,27 @@
+// ignore-tidy-linelength
+
+use std::cell::Cell;
+use std::rc::Rc;
+
+fn send<T: Send>(_: T) {}
+
+fn main() {
+}
+
+// Cycles should work as the deferred obligations are
+// independently resolved and only require the concrete
+// return type, which can't depend on the obligation.
+fn cycle1() -> impl Clone {
+    //~^ ERROR cycle detected
+    //~| ERROR cycle detected
+    send(cycle2().clone());
+    //~^ ERROR cannot be sent between threads safely
+
+    Rc::new(Cell::new(5))
+}
+
+fn cycle2() -> impl Clone {
+    send(cycle1().clone());
+
+    Rc::new(String::from("foo"))
+}
diff --git a/src/test/ui/impl-trait/auto-trait-leak.stderr b/src/test/ui/impl-trait/auto-trait-leak.stderr
new file mode 100644
index 0000000..4e79dfc
--- /dev/null
+++ b/src/test/ui/impl-trait/auto-trait-leak.stderr
@@ -0,0 +1,89 @@
+error[E0391]: cycle detected when processing `cycle1::{{opaque}}#0`
+  --> $DIR/auto-trait-leak.rs:14:16
+   |
+LL | fn cycle1() -> impl Clone {
+   |                ^^^^^^^^^^
+   |
+note: ...which requires processing `cycle1`...
+  --> $DIR/auto-trait-leak.rs:14:1
+   |
+LL | fn cycle1() -> impl Clone {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`...
+note: ...which requires processing `cycle2::{{opaque}}#0`...
+  --> $DIR/auto-trait-leak.rs:23:16
+   |
+LL | fn cycle2() -> impl Clone {
+   |                ^^^^^^^^^^
+note: ...which requires processing `cycle2`...
+  --> $DIR/auto-trait-leak.rs:23:1
+   |
+LL | fn cycle2() -> impl Clone {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`...
+   = note: ...which again requires processing `cycle1::{{opaque}}#0`, completing the cycle
+note: cycle used when checking item types in top-level module
+  --> $DIR/auto-trait-leak.rs:3:1
+   |
+LL | / use std::cell::Cell;
+LL | | use std::rc::Rc;
+LL | |
+LL | | fn send<T: Send>(_: T) {}
+...  |
+LL | |     Rc::new(String::from("foo"))
+LL | | }
+   | |_^
+
+error[E0391]: cycle detected when processing `cycle1::{{opaque}}#0`
+  --> $DIR/auto-trait-leak.rs:14:16
+   |
+LL | fn cycle1() -> impl Clone {
+   |                ^^^^^^^^^^
+   |
+note: ...which requires processing `cycle1`...
+  --> $DIR/auto-trait-leak.rs:14:1
+   |
+LL | fn cycle1() -> impl Clone {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`...
+note: ...which requires processing `cycle2::{{opaque}}#0`...
+  --> $DIR/auto-trait-leak.rs:23:16
+   |
+LL | fn cycle2() -> impl Clone {
+   |                ^^^^^^^^^^
+note: ...which requires processing `cycle2`...
+  --> $DIR/auto-trait-leak.rs:23:1
+   |
+LL | fn cycle2() -> impl Clone {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: ...which again requires processing `cycle1::{{opaque}}#0`, completing the cycle
+note: cycle used when checking item types in top-level module
+  --> $DIR/auto-trait-leak.rs:3:1
+   |
+LL | / use std::cell::Cell;
+LL | | use std::rc::Rc;
+LL | |
+LL | | fn send<T: Send>(_: T) {}
+...  |
+LL | |     Rc::new(String::from("foo"))
+LL | | }
+   | |_^
+
+error[E0277]: `std::rc::Rc<std::string::String>` cannot be sent between threads safely
+  --> $DIR/auto-trait-leak.rs:17:5
+   |
+LL |     send(cycle2().clone());
+   |     ^^^^ `std::rc::Rc<std::string::String>` cannot be sent between threads safely
+   |
+   = help: within `impl std::clone::Clone`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<std::string::String>`
+   = note: required because it appears within the type `impl std::clone::Clone`
+note: required by `send`
+  --> $DIR/auto-trait-leak.rs:6:1
+   |
+LL | fn send<T: Send>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0277, E0391.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/impl-trait/auto-trait-leak2.rs b/src/test/ui/impl-trait/auto-trait-leak2.rs
new file mode 100644
index 0000000..a373edc
--- /dev/null
+++ b/src/test/ui/impl-trait/auto-trait-leak2.rs
@@ -0,0 +1,28 @@
+// ignore-tidy-linelength
+
+use std::cell::Cell;
+use std::rc::Rc;
+
+// Fast path, main can see the concrete type returned.
+fn before() -> impl Fn(i32) {
+    let p = Rc::new(Cell::new(0));
+    move |x| p.set(x)
+}
+
+fn send<T: Send>(_: T) {}
+
+fn main() {
+    send(before());
+    //~^ ERROR `std::rc::Rc<std::cell::Cell<i32>>` cannot be sent between threads safely
+
+    send(after());
+    //~^ ERROR `std::rc::Rc<std::cell::Cell<i32>>` cannot be sent between threads safely
+}
+
+// Deferred path, main has to wait until typeck finishes,
+// to check if the return type of after is Send.
+fn after() -> impl Fn(i32) {
+    let p = Rc::new(Cell::new(0));
+    move |x| p.set(x)
+}
+
diff --git a/src/test/ui/impl-trait/auto-trait-leak2.stderr b/src/test/ui/impl-trait/auto-trait-leak2.stderr
new file mode 100644
index 0000000..4e427d3
--- /dev/null
+++ b/src/test/ui/impl-trait/auto-trait-leak2.stderr
@@ -0,0 +1,33 @@
+error[E0277]: `std::rc::Rc<std::cell::Cell<i32>>` cannot be sent between threads safely
+  --> $DIR/auto-trait-leak2.rs:15:5
+   |
+LL |     send(before());
+   |     ^^^^ `std::rc::Rc<std::cell::Cell<i32>>` cannot be sent between threads safely
+   |
+   = help: within `impl std::ops::Fn<(i32,)>`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<std::cell::Cell<i32>>`
+   = note: required because it appears within the type `[closure@$DIR/auto-trait-leak2.rs:9:5: 9:22 p:std::rc::Rc<std::cell::Cell<i32>>]`
+   = note: required because it appears within the type `impl std::ops::Fn<(i32,)>`
+note: required by `send`
+  --> $DIR/auto-trait-leak2.rs:12:1
+   |
+LL | fn send<T: Send>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: `std::rc::Rc<std::cell::Cell<i32>>` cannot be sent between threads safely
+  --> $DIR/auto-trait-leak2.rs:18:5
+   |
+LL |     send(after());
+   |     ^^^^ `std::rc::Rc<std::cell::Cell<i32>>` cannot be sent between threads safely
+   |
+   = help: within `impl std::ops::Fn<(i32,)>`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<std::cell::Cell<i32>>`
+   = note: required because it appears within the type `[closure@$DIR/auto-trait-leak2.rs:26:5: 26:22 p:std::rc::Rc<std::cell::Cell<i32>>]`
+   = note: required because it appears within the type `impl std::ops::Fn<(i32,)>`
+note: required by `send`
+  --> $DIR/auto-trait-leak2.rs:12:1
+   |
+LL | fn send<T: Send>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/impl-trait/auxiliary/extra-item.rs b/src/test/ui/impl-trait/auxiliary/extra-item.rs
new file mode 100644
index 0000000..8eaeafa
--- /dev/null
+++ b/src/test/ui/impl-trait/auxiliary/extra-item.rs
@@ -0,0 +1 @@
+pub trait MyTrait {}
diff --git a/src/test/ui/impl-trait/auxiliary/no_method_suggested_traits.rs b/src/test/ui/impl-trait/auxiliary/no_method_suggested_traits.rs
new file mode 100644
index 0000000..cefb17e
--- /dev/null
+++ b/src/test/ui/impl-trait/auxiliary/no_method_suggested_traits.rs
@@ -0,0 +1,36 @@
+pub use reexport::Reexported;
+
+pub struct Foo;
+pub enum Bar { X }
+
+pub mod foo {
+    pub trait PubPub {
+        fn method(&self) {}
+
+        fn method3(&self) {}
+    }
+
+    impl PubPub for u32 {}
+    impl PubPub for i32 {}
+}
+pub mod bar {
+    trait PubPriv {
+        fn method(&self);
+    }
+}
+mod qux {
+    pub trait PrivPub {
+        fn method(&self);
+    }
+}
+mod quz {
+    trait PrivPriv {
+        fn method(&self);
+    }
+}
+
+mod reexport {
+    pub trait Reexported {
+        fn method(&self);
+    }
+}
diff --git a/src/test/ui/impl-trait/bindings-opaque.rs b/src/test/ui/impl-trait/bindings-opaque.rs
new file mode 100644
index 0000000..5f62332
--- /dev/null
+++ b/src/test/ui/impl-trait/bindings-opaque.rs
@@ -0,0 +1,16 @@
+#![feature(impl_trait_in_bindings)]
+
+const FOO: impl Copy = 42;
+
+static BAR: impl Copy = 42;
+
+fn main() {
+    let foo: impl Copy = 42;
+
+    let _ = FOO.count_ones();
+//~^ ERROR no method
+    let _ = BAR.count_ones();
+//~^ ERROR no method
+    let _ = foo.count_ones();
+//~^ ERROR no method
+}
diff --git a/src/test/ui/impl-trait/bindings-opaque.stderr b/src/test/ui/impl-trait/bindings-opaque.stderr
new file mode 100644
index 0000000..8b2514c
--- /dev/null
+++ b/src/test/ui/impl-trait/bindings-opaque.stderr
@@ -0,0 +1,21 @@
+error[E0599]: no method named `count_ones` found for type `impl std::marker::Copy` in the current scope
+  --> $DIR/bindings-opaque.rs:10:17
+   |
+LL |     let _ = FOO.count_ones();
+   |                 ^^^^^^^^^^
+
+error[E0599]: no method named `count_ones` found for type `impl std::marker::Copy` in the current scope
+  --> $DIR/bindings-opaque.rs:12:17
+   |
+LL |     let _ = BAR.count_ones();
+   |                 ^^^^^^^^^^
+
+error[E0599]: no method named `count_ones` found for type `impl std::marker::Copy` in the current scope
+  --> $DIR/bindings-opaque.rs:14:17
+   |
+LL |     let _ = foo.count_ones();
+   |                 ^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/impl-trait/bindings.rs b/src/test/ui/impl-trait/bindings.rs
new file mode 100644
index 0000000..91d0926
--- /dev/null
+++ b/src/test/ui/impl-trait/bindings.rs
@@ -0,0 +1,29 @@
+#![feature(impl_trait_in_bindings)]
+
+fn a<T: Clone>(x: T) {
+    const foo: impl Clone = x;
+    //~^ ERROR attempt to use a non-constant value in a constant
+}
+
+fn b<T: Clone>(x: T) {
+    let _ = move || {
+        const foo: impl Clone = x;
+        //~^ ERROR attempt to use a non-constant value in a constant
+    };
+}
+
+trait Foo<T: Clone> {
+    fn a(x: T) {
+        const foo: impl Clone = x;
+        //~^ ERROR attempt to use a non-constant value in a constant
+    }
+}
+
+impl<T: Clone> Foo<T> for i32 {
+    fn a(x: T) {
+        const foo: impl Clone = x;
+        //~^ ERROR attempt to use a non-constant value in a constant
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/impl-trait/bindings.stderr b/src/test/ui/impl-trait/bindings.stderr
new file mode 100644
index 0000000..a5bf583
--- /dev/null
+++ b/src/test/ui/impl-trait/bindings.stderr
@@ -0,0 +1,27 @@
+error[E0435]: attempt to use a non-constant value in a constant
+  --> $DIR/bindings.rs:4:29
+   |
+LL |     const foo: impl Clone = x;
+   |                             ^ non-constant value
+
+error[E0435]: attempt to use a non-constant value in a constant
+  --> $DIR/bindings.rs:10:33
+   |
+LL |         const foo: impl Clone = x;
+   |                                 ^ non-constant value
+
+error[E0435]: attempt to use a non-constant value in a constant
+  --> $DIR/bindings.rs:17:33
+   |
+LL |         const foo: impl Clone = x;
+   |                                 ^ non-constant value
+
+error[E0435]: attempt to use a non-constant value in a constant
+  --> $DIR/bindings.rs:24:33
+   |
+LL |         const foo: impl Clone = x;
+   |                                 ^ non-constant value
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0435`.
diff --git a/src/test/ui/impl-trait/closure-calling-parent-fn.rs b/src/test/ui/impl-trait/closure-calling-parent-fn.rs
new file mode 100644
index 0000000..cb5f78b
--- /dev/null
+++ b/src/test/ui/impl-trait/closure-calling-parent-fn.rs
@@ -0,0 +1,14 @@
+#![feature(nll)]
+
+// Regression test for #54593: the MIR type checker was going wrong
+// when a closure returns the `impl Copy` from its parent fn. It was
+// (incorrectly) replacing the `impl Copy` in its return type with the
+// hidden type (`()`) but that type resulted from a recursive call to
+// `foo` and hence is treated opaquely within the closure body.  This
+// resulted in a failed subtype relationship.
+//
+// run-pass
+
+fn foo() -> impl Copy { || foo(); }
+fn bar() -> impl Copy { || bar(); }
+fn main() { }
diff --git a/src/test/ui/impl-trait/deprecated_annotation.rs b/src/test/ui/impl-trait/deprecated_annotation.rs
new file mode 100644
index 0000000..dd9f5fd
--- /dev/null
+++ b/src/test/ui/impl-trait/deprecated_annotation.rs
@@ -0,0 +1,19 @@
+// compile-pass
+
+#![deny(warnings)]
+
+#[deprecated]
+trait Deprecated {}
+
+#[deprecated]
+struct DeprecatedTy;
+
+#[allow(deprecated)]
+impl Deprecated for DeprecatedTy {}
+
+#[allow(deprecated)]
+fn foo() -> impl Deprecated { DeprecatedTy }
+
+fn main() {
+    foo();
+}
diff --git a/src/test/ui/impl-trait/equality.rs b/src/test/ui/impl-trait/equality.rs
new file mode 100644
index 0000000..f6b0853
--- /dev/null
+++ b/src/test/ui/impl-trait/equality.rs
@@ -0,0 +1,43 @@
+#![feature(specialization)]
+
+trait Foo: Copy + ToString {}
+
+impl<T: Copy + ToString> Foo for T {}
+
+fn hide<T: Foo>(x: T) -> impl Foo {
+    x
+}
+
+fn two(x: bool) -> impl Foo {
+    if x {
+        return 1_i32;
+    }
+    0_u32
+    //~^ ERROR mismatched types
+    //~| expected i32, found u32
+}
+
+fn sum_to(n: u32) -> impl Foo {
+    if n == 0 {
+        0
+    } else {
+        n + sum_to(n - 1)
+        //~^ ERROR cannot add `impl Foo` to `u32`
+    }
+}
+
+trait Leak: Sized {
+    type T;
+    fn leak(self) -> Self::T;
+}
+impl<T> Leak for T {
+    default type T = ();
+    default fn leak(self) -> Self::T { panic!() }
+}
+impl Leak for i32 {
+    type T = i32;
+    fn leak(self) -> i32 { self }
+}
+
+fn main() {
+}
diff --git a/src/test/ui/impl-trait/equality.stderr b/src/test/ui/impl-trait/equality.stderr
new file mode 100644
index 0000000..6cd9d07
--- /dev/null
+++ b/src/test/ui/impl-trait/equality.stderr
@@ -0,0 +1,27 @@
+error[E0308]: mismatched types
+  --> $DIR/equality.rs:15:5
+   |
+LL | fn two(x: bool) -> impl Foo {
+   |                    -------- expected because this return type...
+LL |     if x {
+LL |         return 1_i32;
+   |                ----- ...is found to be `i32` here
+LL |     }
+LL |     0_u32
+   |     ^^^^^ expected i32, found u32
+   |
+   = note: expected type `i32`
+              found type `u32`
+
+error[E0277]: cannot add `impl Foo` to `u32`
+  --> $DIR/equality.rs:24:11
+   |
+LL |         n + sum_to(n - 1)
+   |           ^ no implementation for `u32 + impl Foo`
+   |
+   = help: the trait `std::ops::Add<impl Foo>` is not implemented for `u32`
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0277, E0308.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/impl-trait/equality2.rs b/src/test/ui/impl-trait/equality2.rs
new file mode 100644
index 0000000..a01779e
--- /dev/null
+++ b/src/test/ui/impl-trait/equality2.rs
@@ -0,0 +1,44 @@
+#![feature(specialization)]
+
+trait Foo: Copy + ToString {}
+
+impl<T: Copy + ToString> Foo for T {}
+
+fn hide<T: Foo>(x: T) -> impl Foo {
+    x
+}
+
+trait Leak: Sized {
+    type T;
+    fn leak(self) -> Self::T;
+}
+impl<T> Leak for T {
+    default type T = ();
+    default fn leak(self) -> Self::T { panic!() }
+}
+impl Leak for i32 {
+    type T = i32;
+    fn leak(self) -> i32 { self }
+}
+
+fn main() {
+    let _: u32 = hide(0_u32);
+    //~^ ERROR mismatched types
+    //~| expected type `u32`
+    //~| found type `impl Foo`
+    //~| expected u32, found opaque type
+
+    let _: i32 = Leak::leak(hide(0_i32));
+    //~^ ERROR mismatched types
+    //~| expected type `i32`
+    //~| found type `<impl Foo as Leak>::T`
+    //~| expected i32, found associated type
+
+    let mut x = (hide(0_u32), hide(0_i32));
+    x = (x.1,
+    //~^ ERROR mismatched types
+    //~| expected u32, found i32
+         x.0);
+    //~^ ERROR mismatched types
+    //~| expected i32, found u32
+}
diff --git a/src/test/ui/impl-trait/equality2.stderr b/src/test/ui/impl-trait/equality2.stderr
new file mode 100644
index 0000000..3e6181a
--- /dev/null
+++ b/src/test/ui/impl-trait/equality2.stderr
@@ -0,0 +1,39 @@
+error[E0308]: mismatched types
+  --> $DIR/equality2.rs:25:18
+   |
+LL |     let _: u32 = hide(0_u32);
+   |                  ^^^^^^^^^^^ expected u32, found opaque type
+   |
+   = note: expected type `u32`
+              found type `impl Foo`
+
+error[E0308]: mismatched types
+  --> $DIR/equality2.rs:31:18
+   |
+LL |     let _: i32 = Leak::leak(hide(0_i32));
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^ expected i32, found associated type
+   |
+   = note: expected type `i32`
+              found type `<impl Foo as Leak>::T`
+
+error[E0308]: mismatched types
+  --> $DIR/equality2.rs:38:10
+   |
+LL |     x = (x.1,
+   |          ^^^ expected u32, found i32
+   |
+   = note: expected type `impl Foo` (u32)
+              found type `impl Foo` (i32)
+
+error[E0308]: mismatched types
+  --> $DIR/equality2.rs:41:10
+   |
+LL |          x.0);
+   |          ^^^ expected i32, found u32
+   |
+   = note: expected type `impl Foo` (i32)
+              found type `impl Foo` (u32)
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/impl-trait/existential-minimal.rs b/src/test/ui/impl-trait/existential-minimal.rs
new file mode 100644
index 0000000..c93c6a4
--- /dev/null
+++ b/src/test/ui/impl-trait/existential-minimal.rs
@@ -0,0 +1,5 @@
+// compile-pass
+
+fn main() {}
+
+fn foo() -> impl std::fmt::Debug { "cake" }
diff --git a/src/test/ui/impl-trait/existential_type_in_fn_body.rs b/src/test/ui/impl-trait/existential_type_in_fn_body.rs
new file mode 100644
index 0000000..b29ae06
--- /dev/null
+++ b/src/test/ui/impl-trait/existential_type_in_fn_body.rs
@@ -0,0 +1,12 @@
+// compile-pass
+
+#![feature(existential_type)]
+
+use std::fmt::Debug;
+
+fn main() {
+    existential type Existential: Debug;
+
+    fn f() -> Existential {}
+    println!("{:?}", f());
+}
diff --git a/src/test/ui/impl-trait/extra-item.rs b/src/test/ui/impl-trait/extra-item.rs
new file mode 100644
index 0000000..d82237c
--- /dev/null
+++ b/src/test/ui/impl-trait/extra-item.rs
@@ -0,0 +1,10 @@
+// aux-build:extra-item.rs
+// compile-flags:--extern extra_item
+
+struct S;
+
+impl extra_item::MyTrait for S {
+    fn extra() {} //~ ERROR method `extra` is not a member of trait `extra_item::MyTrait`
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/extra-item.stderr b/src/test/ui/impl-trait/extra-item.stderr
new file mode 100644
index 0000000..728bcc0
--- /dev/null
+++ b/src/test/ui/impl-trait/extra-item.stderr
@@ -0,0 +1,9 @@
+error[E0407]: method `extra` is not a member of trait `extra_item::MyTrait`
+  --> $DIR/extra-item.rs:7:5
+   |
+LL |     fn extra() {}
+   |     ^^^^^^^^^^^^^ not a member of trait `extra_item::MyTrait`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0407`.
diff --git a/src/test/ui/impl-trait/impl-generic-mismatch-ab.rs b/src/test/ui/impl-trait/impl-generic-mismatch-ab.rs
new file mode 100644
index 0000000..6c9b119
--- /dev/null
+++ b/src/test/ui/impl-trait/impl-generic-mismatch-ab.rs
@@ -0,0 +1,12 @@
+use std::fmt::Debug;
+
+trait Foo {
+    fn foo<A: Debug>(&self, a: &A, b: &impl Debug);
+}
+
+impl Foo for () {
+    fn foo<B: Debug>(&self, a: &impl Debug, b: &B) { }
+    //~^ ERROR method `foo` has an incompatible type for trait
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/impl-generic-mismatch-ab.stderr b/src/test/ui/impl-trait/impl-generic-mismatch-ab.stderr
new file mode 100644
index 0000000..357e6b0
--- /dev/null
+++ b/src/test/ui/impl-trait/impl-generic-mismatch-ab.stderr
@@ -0,0 +1,15 @@
+error[E0053]: method `foo` has an incompatible type for trait
+  --> $DIR/impl-generic-mismatch-ab.rs:8:32
+   |
+LL |     fn foo<A: Debug>(&self, a: &A, b: &impl Debug);
+   |                                -- type in trait
+...
+LL |     fn foo<B: Debug>(&self, a: &impl Debug, b: &B) { }
+   |                                ^^^^^^^^^^^ expected type parameter, found a different type parameter
+   |
+   = note: expected type `fn(&(), &B, &impl Debug)`
+              found type `fn(&(), &impl Debug, &B)`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0053`.
diff --git a/src/test/ui/impl-trait/impl-generic-mismatch.rs b/src/test/ui/impl-trait/impl-generic-mismatch.rs
new file mode 100644
index 0000000..f4fba4c
--- /dev/null
+++ b/src/test/ui/impl-trait/impl-generic-mismatch.rs
@@ -0,0 +1,35 @@
+// ignore-musl
+// ignore-x86
+
+use std::fmt::Debug;
+
+trait Foo {
+    fn foo(&self, _: &impl Debug);
+}
+
+impl Foo for () {
+    fn foo<U: Debug>(&self, _: &U) { }
+    //~^ Error method `foo` has incompatible signature for trait
+}
+
+trait Bar {
+    fn bar<U: Debug>(&self, _: &U);
+}
+
+impl Bar for () {
+    fn bar(&self, _: &impl Debug) { }
+    //~^ Error method `bar` has incompatible signature for trait
+}
+
+// With non-local trait (#49841):
+
+use std::hash::{Hash, Hasher};
+
+struct X;
+
+impl Hash for X {
+    fn hash(&self, hasher: &mut impl Hasher) {}
+    //~^ Error method `hash` has incompatible signature for trait
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/impl-generic-mismatch.stderr b/src/test/ui/impl-trait/impl-generic-mismatch.stderr
new file mode 100644
index 0000000..fae8da9
--- /dev/null
+++ b/src/test/ui/impl-trait/impl-generic-mismatch.stderr
@@ -0,0 +1,40 @@
+error[E0643]: method `foo` has incompatible signature for trait
+  --> $DIR/impl-generic-mismatch.rs:11:12
+   |
+LL |     fn foo(&self, _: &impl Debug);
+   |                       ---------- declaration in trait here
+...
+LL |     fn foo<U: Debug>(&self, _: &U) { }
+   |            ^ expected `impl Trait`, found generic parameter
+help: try removing the generic parameter and using `impl Trait` instead
+   |
+LL |     fn foo(&self, _: &impl Debug) { }
+   |          --           ^^^^^^^^^^
+
+error[E0643]: method `bar` has incompatible signature for trait
+  --> $DIR/impl-generic-mismatch.rs:20:23
+   |
+LL |     fn bar<U: Debug>(&self, _: &U);
+   |            - declaration in trait here
+...
+LL |     fn bar(&self, _: &impl Debug) { }
+   |                       ^^^^^^^^^^ expected generic parameter, found `impl Trait`
+help: try changing the `impl Trait` argument to a generic parameter
+   |
+LL |     fn bar<U: Debug>(&self, _: &U) { }
+   |           ^^^^^^^^^^            ^
+
+error[E0643]: method `hash` has incompatible signature for trait
+  --> $DIR/impl-generic-mismatch.rs:31:33
+   |
+LL |     fn hash(&self, hasher: &mut impl Hasher) {}
+   |                                 ^^^^^^^^^^^ expected generic parameter, found `impl Trait`
+   | 
+  ::: $SRC_DIR/libcore/hash/mod.rs:LL:COL
+   |
+LL |     fn hash<H: Hasher>(&self, state: &mut H);
+   |             - declaration in trait here
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0643`.
diff --git a/src/test/ui/impl-trait/impl-trait-plus-priority.rs b/src/test/ui/impl-trait/impl-trait-plus-priority.rs
new file mode 100644
index 0000000..2e4f048
--- /dev/null
+++ b/src/test/ui/impl-trait/impl-trait-plus-priority.rs
@@ -0,0 +1,49 @@
+// compile-flags: -Z parse-only -Z continue-parse-after-error
+
+fn f() -> impl A + {} // OK
+fn f() -> impl A + B {} // OK
+fn f() -> dyn A + B {} // OK
+fn f() -> A + B {} // OK
+
+impl S {
+    fn f(self) -> impl A + { // OK
+        let _ = |a, b| -> impl A + {}; // OK
+    }
+    fn f(self) -> impl A + B { // OK
+        let _ = |a, b| -> impl A + B {}; // OK
+    }
+    fn f(self) -> dyn A + B { // OK
+        let _ = |a, b| -> dyn A + B {}; // OK
+    }
+    fn f(self) -> A + B { // OK
+        let _ = |a, b| -> A + B {}; // OK
+    }
+}
+
+type A = fn() -> impl A +;
+//~^ ERROR ambiguous `+` in a type
+type A = fn() -> impl A + B;
+//~^ ERROR ambiguous `+` in a type
+type A = fn() -> dyn A + B;
+//~^ ERROR ambiguous `+` in a type
+type A = fn() -> A + B;
+//~^ ERROR expected a path on the left-hand side of `+`, not `fn() -> A`
+
+type A = Fn() -> impl A +;
+//~^ ERROR ambiguous `+` in a type
+type A = Fn() -> impl A + B;
+//~^ ERROR ambiguous `+` in a type
+type A = Fn() -> dyn A + B;
+//~^ ERROR ambiguous `+` in a type
+type A = Fn() -> A + B; // OK, interpreted as `(Fn() -> A) + B` for compatibility
+
+type A = &impl A +;
+//~^ ERROR ambiguous `+` in a type
+type A = &impl A + B;
+//~^ ERROR ambiguous `+` in a type
+type A = &dyn A + B;
+//~^ ERROR ambiguous `+` in a type
+type A = &A + B;
+//~^ ERROR expected a path on the left-hand side of `+`, not `&A`
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/impl-trait-plus-priority.stderr b/src/test/ui/impl-trait/impl-trait-plus-priority.stderr
new file mode 100644
index 0000000..205d9b0
--- /dev/null
+++ b/src/test/ui/impl-trait/impl-trait-plus-priority.stderr
@@ -0,0 +1,69 @@
+error: ambiguous `+` in a type
+  --> $DIR/impl-trait-plus-priority.rs:23:18
+   |
+LL | type A = fn() -> impl A +;
+   |                  ^^^^^^^^ help: use parentheses to disambiguate: `(impl A)`
+
+error: ambiguous `+` in a type
+  --> $DIR/impl-trait-plus-priority.rs:25:18
+   |
+LL | type A = fn() -> impl A + B;
+   |                  ^^^^^^^^^^ help: use parentheses to disambiguate: `(impl A + B)`
+
+error: ambiguous `+` in a type
+  --> $DIR/impl-trait-plus-priority.rs:27:18
+   |
+LL | type A = fn() -> dyn A + B;
+   |                  ^^^^^^^^^ help: use parentheses to disambiguate: `(dyn A + B)`
+
+error[E0178]: expected a path on the left-hand side of `+`, not `fn() -> A`
+  --> $DIR/impl-trait-plus-priority.rs:29:10
+   |
+LL | type A = fn() -> A + B;
+   |          ^^^^^^^^^^^^^ perhaps you forgot parentheses?
+
+error: ambiguous `+` in a type
+  --> $DIR/impl-trait-plus-priority.rs:32:18
+   |
+LL | type A = Fn() -> impl A +;
+   |                  ^^^^^^^^ help: use parentheses to disambiguate: `(impl A)`
+
+error: ambiguous `+` in a type
+  --> $DIR/impl-trait-plus-priority.rs:34:18
+   |
+LL | type A = Fn() -> impl A + B;
+   |                  ^^^^^^^^^^ help: use parentheses to disambiguate: `(impl A + B)`
+
+error: ambiguous `+` in a type
+  --> $DIR/impl-trait-plus-priority.rs:36:18
+   |
+LL | type A = Fn() -> dyn A + B;
+   |                  ^^^^^^^^^ help: use parentheses to disambiguate: `(dyn A + B)`
+
+error: ambiguous `+` in a type
+  --> $DIR/impl-trait-plus-priority.rs:40:11
+   |
+LL | type A = &impl A +;
+   |           ^^^^^^^^ help: use parentheses to disambiguate: `(impl A)`
+
+error: ambiguous `+` in a type
+  --> $DIR/impl-trait-plus-priority.rs:42:11
+   |
+LL | type A = &impl A + B;
+   |           ^^^^^^^^^^ help: use parentheses to disambiguate: `(impl A + B)`
+
+error: ambiguous `+` in a type
+  --> $DIR/impl-trait-plus-priority.rs:44:11
+   |
+LL | type A = &dyn A + B;
+   |           ^^^^^^^^^ help: use parentheses to disambiguate: `(dyn A + B)`
+
+error[E0178]: expected a path on the left-hand side of `+`, not `&A`
+  --> $DIR/impl-trait-plus-priority.rs:46:10
+   |
+LL | type A = &A + B;
+   |          ^^^^^^ help: try adding parentheses: `&(A + B)`
+
+error: aborting due to 11 previous errors
+
+For more information about this error, try `rustc --explain E0178`.
diff --git a/src/test/ui/impl-trait/impl_trait_projections.rs b/src/test/ui/impl-trait/impl_trait_projections.rs
new file mode 100644
index 0000000..fd0986d
--- /dev/null
+++ b/src/test/ui/impl-trait/impl_trait_projections.rs
@@ -0,0 +1,39 @@
+use std::fmt::Debug;
+use std::option;
+
+fn parametrized_type_is_allowed() -> Option<impl Debug> {
+    Some(5i32)
+}
+
+fn path_parametrized_type_is_allowed() -> option::Option<impl Debug> {
+    Some(5i32)
+}
+
+fn projection_is_disallowed(x: impl Iterator) -> <impl Iterator>::Item {
+//~^ ERROR `impl Trait` is not allowed in path parameters
+//~^^ ERROR ambiguous associated type
+    x.next().unwrap()
+}
+
+fn projection_with_named_trait_is_disallowed(x: impl Iterator)
+    -> <impl Iterator as Iterator>::Item
+//~^ ERROR `impl Trait` is not allowed in path parameters
+{
+    x.next().unwrap()
+}
+
+fn projection_with_named_trait_inside_path_is_disallowed()
+    -> <::std::ops::Range<impl Debug> as Iterator>::Item
+//~^ ERROR `impl Trait` is not allowed in path parameters
+{
+    (1i32..100).next().unwrap()
+}
+
+fn projection_from_impl_trait_inside_dyn_trait_is_disallowed()
+    -> <dyn Iterator<Item = impl Debug> as Iterator>::Item
+//~^ ERROR `impl Trait` is not allowed in path parameters
+{
+    panic!()
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/impl_trait_projections.stderr b/src/test/ui/impl-trait/impl_trait_projections.stderr
new file mode 100644
index 0000000..4e9bcf3
--- /dev/null
+++ b/src/test/ui/impl-trait/impl_trait_projections.stderr
@@ -0,0 +1,34 @@
+error[E0667]: `impl Trait` is not allowed in path parameters
+  --> $DIR/impl_trait_projections.rs:12:51
+   |
+LL | fn projection_is_disallowed(x: impl Iterator) -> <impl Iterator>::Item {
+   |                                                   ^^^^^^^^^^^^^
+
+error[E0667]: `impl Trait` is not allowed in path parameters
+  --> $DIR/impl_trait_projections.rs:19:9
+   |
+LL |     -> <impl Iterator as Iterator>::Item
+   |         ^^^^^^^^^^^^^
+
+error[E0667]: `impl Trait` is not allowed in path parameters
+  --> $DIR/impl_trait_projections.rs:26:27
+   |
+LL |     -> <::std::ops::Range<impl Debug> as Iterator>::Item
+   |                           ^^^^^^^^^^
+
+error[E0667]: `impl Trait` is not allowed in path parameters
+  --> $DIR/impl_trait_projections.rs:33:29
+   |
+LL |     -> <dyn Iterator<Item = impl Debug> as Iterator>::Item
+   |                             ^^^^^^^^^^
+
+error[E0223]: ambiguous associated type
+  --> $DIR/impl_trait_projections.rs:12:50
+   |
+LL | fn projection_is_disallowed(x: impl Iterator) -> <impl Iterator>::Item {
+   |                                                  ^^^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<impl std::iter::Iterator as Trait>::Item`
+
+error: aborting due to 5 previous errors
+
+Some errors occurred: E0223, E0667.
+For more information about an error, try `rustc --explain E0223`.
diff --git a/src/test/ui/impl-trait/infinite-impl-trait-issue-38064.rs b/src/test/ui/impl-trait/infinite-impl-trait-issue-38064.rs
new file mode 100644
index 0000000..150a801
--- /dev/null
+++ b/src/test/ui/impl-trait/infinite-impl-trait-issue-38064.rs
@@ -0,0 +1,25 @@
+// Test that attempts to construct infinite types via impl trait fail
+// in a graceful way.
+//
+// Regression test for #38064.
+
+trait Quux {}
+
+fn foo() -> impl Quux { //~ opaque type expands to a recursive type
+    struct Foo<T>(T);
+    impl<T> Quux for Foo<T> {}
+    Foo(bar())
+}
+
+fn bar() -> impl Quux { //~ opaque type expands to a recursive type
+    struct Bar<T>(T);
+    impl<T> Quux for Bar<T> {}
+    Bar(foo())
+}
+
+// effectively:
+//     struct Foo(Bar);
+//     struct Bar(Foo);
+// should produce an error about infinite size
+
+fn main() { foo(); }
diff --git a/src/test/ui/impl-trait/infinite-impl-trait-issue-38064.stderr b/src/test/ui/impl-trait/infinite-impl-trait-issue-38064.stderr
new file mode 100644
index 0000000..fb48ecd
--- /dev/null
+++ b/src/test/ui/impl-trait/infinite-impl-trait-issue-38064.stderr
@@ -0,0 +1,19 @@
+error[E0720]: opaque type expands to a recursive type
+  --> $DIR/infinite-impl-trait-issue-38064.rs:8:13
+   |
+LL | fn foo() -> impl Quux {
+   |             ^^^^^^^^^ expands to self-referential type
+   |
+   = note: expanded type is `foo::Foo<bar::Bar<impl Quux>>`
+
+error[E0720]: opaque type expands to a recursive type
+  --> $DIR/infinite-impl-trait-issue-38064.rs:14:13
+   |
+LL | fn bar() -> impl Quux {
+   |             ^^^^^^^^^ expands to self-referential type
+   |
+   = note: expanded type is `bar::Bar<foo::Foo<impl Quux>>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0720`.
diff --git a/src/test/ui/impl-trait/issue-21659-show-relevant-trait-impls-3.rs b/src/test/ui/impl-trait/issue-21659-show-relevant-trait-impls-3.rs
new file mode 100644
index 0000000..2bff01b
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-21659-show-relevant-trait-impls-3.rs
@@ -0,0 +1,22 @@
+trait Foo<A> {
+    fn foo(&self, a: A) -> A {
+        a
+    }
+}
+
+trait NotRelevant<A> {
+    fn nr(&self, a: A) -> A {
+        a
+    }
+}
+
+struct Bar;
+
+impl NotRelevant<usize> for Bar {}
+
+fn main() {
+    let f1 = Bar;
+
+    f1.foo(1usize);
+    //~^ error: method named `foo` found for type `Bar` in the current scope
+}
diff --git a/src/test/ui/impl-trait/issue-21659-show-relevant-trait-impls-3.stderr b/src/test/ui/impl-trait/issue-21659-show-relevant-trait-impls-3.stderr
new file mode 100644
index 0000000..666418f
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-21659-show-relevant-trait-impls-3.stderr
@@ -0,0 +1,16 @@
+error[E0599]: no method named `foo` found for type `Bar` in the current scope
+  --> $DIR/issue-21659-show-relevant-trait-impls-3.rs:20:8
+   |
+LL | struct Bar;
+   | ----------- method `foo` not found for this
+...
+LL |     f1.foo(1usize);
+   |        ^^^
+   |
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following trait defines an item `foo`, perhaps you need to implement it:
+           candidate #1: `Foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/impl-trait/issue-42479.rs b/src/test/ui/impl-trait/issue-42479.rs
new file mode 100644
index 0000000..2da15ac
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-42479.rs
@@ -0,0 +1,17 @@
+// compile-pass
+
+use std::iter::once;
+
+struct Foo {
+    x: i32,
+}
+
+impl Foo {
+    fn inside(&self) -> impl Iterator<Item = &i32> {
+        once(&self.x)
+    }
+}
+
+fn main() {
+    println!("hi");
+}
diff --git a/src/test/ui/impl-trait/issue-49376.rs b/src/test/ui/impl-trait/issue-49376.rs
new file mode 100644
index 0000000..13671b8
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-49376.rs
@@ -0,0 +1,23 @@
+// compile-pass
+
+// Tests for nested self-reference which caused a stack overflow.
+
+use std::fmt::Debug;
+use std::ops::*;
+
+fn gen() -> impl PartialOrd + PartialEq + Debug { }
+
+struct Bar {}
+trait Foo<T = Self> {}
+trait FooNested<T = Option<Self>> {}
+impl Foo for Bar {}
+impl FooNested for Bar {}
+
+fn foo() -> impl Foo + FooNested {
+    Bar {}
+}
+
+fn test_impl_ops() -> impl Add + Sub + Mul + Div { 1 }
+fn test_impl_assign_ops() -> impl AddAssign + SubAssign + MulAssign + DivAssign { 1 }
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issue-52128.rs b/src/test/ui/impl-trait/issue-52128.rs
new file mode 100644
index 0000000..eb4456a
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-52128.rs
@@ -0,0 +1,25 @@
+// compile-pass
+
+#![deny(warnings)]
+
+use std::collections::BTreeMap;
+
+pub struct RangeMap {
+    map: BTreeMap<Range, u8>,
+}
+
+#[derive(Eq, PartialEq, Ord, PartialOrd)]
+struct Range;
+
+impl RangeMap {
+    fn iter_with_range<'a>(&'a self) -> impl Iterator<Item = (&'a Range, &'a u8)> + 'a {
+        self.map.range(Range..Range)
+    }
+
+    pub fn iter<'a>(&'a self) -> impl Iterator<Item = &'a u8> + 'a {
+        self.iter_with_range().map(|(_, data)| data)
+    }
+
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issue-55608-captures-empty-region.rs b/src/test/ui/impl-trait/issue-55608-captures-empty-region.rs
new file mode 100644
index 0000000..7ebc348
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-55608-captures-empty-region.rs
@@ -0,0 +1,22 @@
+// This used to ICE because it creates an `impl Trait` that captures a
+// hidden empty region.
+
+#![feature(conservative_impl_trait)]
+
+fn server() -> impl FilterBase2 { //~ ERROR [E0700]
+    segment2(|| { loop { } }).map2(|| "")
+}
+
+trait FilterBase2 {
+    fn map2<F>(self, _fn: F) -> Map2<F> where Self: Sized { loop { } }
+}
+
+struct Map2<F> { _func: F }
+
+impl<F> FilterBase2 for Map2<F> { }
+
+fn segment2<F>(_fn: F) -> Map2<F> where F: Fn() -> Result<(), ()> {
+    loop { }
+}
+
+fn main() { server(); }
diff --git a/src/test/ui/impl-trait/issue-55608-captures-empty-region.stderr b/src/test/ui/impl-trait/issue-55608-captures-empty-region.stderr
new file mode 100644
index 0000000..6311a7f
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-55608-captures-empty-region.stderr
@@ -0,0 +1,11 @@
+error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+  --> $DIR/issue-55608-captures-empty-region.rs:6:16
+   |
+LL | fn server() -> impl FilterBase2 {
+   |                ^^^^^^^^^^^^^^^^
+   |
+   = note: hidden type `Map2<[closure@$DIR/issue-55608-captures-empty-region.rs:7:36: 7:41]>` captures an empty lifetime
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0700`.
diff --git a/src/test/ui/impl-trait/issue-57979-deeply-nested-impl-trait-in-assoc-proj.rs b/src/test/ui/impl-trait/issue-57979-deeply-nested-impl-trait-in-assoc-proj.rs
new file mode 100644
index 0000000..5eef6a3
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-57979-deeply-nested-impl-trait-in-assoc-proj.rs
@@ -0,0 +1,42 @@
+// rust-lang/rust#57979 : the initial support for `impl Trait` didn't
+// properly check syntax hidden behind an associated type projection,
+// but it did catch *some cases*. This is checking that we continue to
+// properly emit errors for those, even with the new
+// future-incompatibility warnings.
+//
+// issue-57979-nested-impl-trait-in-assoc-proj.rs shows the main case
+// that we were previously failing to catch.
+
+struct Deeper<T>(T);
+
+mod allowed {
+    #![allow(nested_impl_trait)]
+
+    pub trait Foo<T> { }
+    pub trait Bar { }
+    pub trait Quux { type Assoc; }
+    pub fn demo(_: impl Quux<Assoc=super::Deeper<impl Foo<impl Bar>>>) { }
+    //~^ ERROR nested `impl Trait` is not allowed
+}
+
+mod warned {
+    #![warn(nested_impl_trait)]
+
+    pub trait Foo<T> { }
+    pub trait Bar { }
+    pub trait Quux { type Assoc; }
+    pub fn demo(_: impl Quux<Assoc=super::Deeper<impl Foo<impl Bar>>>) { }
+    //~^ ERROR nested `impl Trait` is not allowed
+}
+
+mod denied {
+    #![deny(nested_impl_trait)]
+
+    pub trait Foo<T> { }
+    pub trait Bar { }
+    pub trait Quux { type Assoc; }
+    pub fn demo(_: impl Quux<Assoc=super::Deeper<impl Foo<impl Bar>>>) { }
+    //~^ ERROR nested `impl Trait` is not allowed
+}
+
+fn main() { }
diff --git a/src/test/ui/impl-trait/issue-57979-deeply-nested-impl-trait-in-assoc-proj.stderr b/src/test/ui/impl-trait/issue-57979-deeply-nested-impl-trait-in-assoc-proj.stderr
new file mode 100644
index 0000000..2b6f15e
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-57979-deeply-nested-impl-trait-in-assoc-proj.stderr
@@ -0,0 +1,30 @@
+error[E0666]: nested `impl Trait` is not allowed
+  --> $DIR/issue-57979-deeply-nested-impl-trait-in-assoc-proj.rs:18:59
+   |
+LL |     pub fn demo(_: impl Quux<Assoc=super::Deeper<impl Foo<impl Bar>>>) { }
+   |                                                  ---------^^^^^^^^-
+   |                                                  |        |
+   |                                                  |        nested `impl Trait` here
+   |                                                  outer `impl Trait`
+
+error[E0666]: nested `impl Trait` is not allowed
+  --> $DIR/issue-57979-deeply-nested-impl-trait-in-assoc-proj.rs:28:59
+   |
+LL |     pub fn demo(_: impl Quux<Assoc=super::Deeper<impl Foo<impl Bar>>>) { }
+   |                                                  ---------^^^^^^^^-
+   |                                                  |        |
+   |                                                  |        nested `impl Trait` here
+   |                                                  outer `impl Trait`
+
+error[E0666]: nested `impl Trait` is not allowed
+  --> $DIR/issue-57979-deeply-nested-impl-trait-in-assoc-proj.rs:38:59
+   |
+LL |     pub fn demo(_: impl Quux<Assoc=super::Deeper<impl Foo<impl Bar>>>) { }
+   |                                                  ---------^^^^^^^^-
+   |                                                  |        |
+   |                                                  |        nested `impl Trait` here
+   |                                                  outer `impl Trait`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0666`.
diff --git a/src/test/ui/impl-trait/issue-57979-impl-trait-in-path.rs b/src/test/ui/impl-trait/issue-57979-impl-trait-in-path.rs
new file mode 100644
index 0000000..84fcb5e
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-57979-impl-trait-in-path.rs
@@ -0,0 +1,37 @@
+// rust-lang/rust#57979 : the initial support for `impl Trait` didn't
+// properly check syntax hidden behind an associated type projection.
+// Here we test behavior of occurrences of `impl Trait` within a path
+// component in that context.
+
+mod allowed {
+    #![allow(nested_impl_trait)]
+
+    pub trait Bar { }
+    pub trait Quux<T> { type Assoc; }
+    pub fn demo(_: impl Quux<(), Assoc=<() as Quux<impl Bar>>::Assoc>) { }
+    impl<T> Quux<T> for () { type Assoc = u32; }
+}
+
+mod warned {
+    #![warn(nested_impl_trait)]
+
+    pub trait Bar { }
+    pub trait Quux<T> { type Assoc; }
+    pub fn demo(_: impl Quux<(), Assoc=<() as Quux<impl Bar>>::Assoc>) { }
+    //~^ WARN `impl Trait` is not allowed in path parameters
+    //~| WARN will become a hard error in a future release!
+    impl<T> Quux<T> for () { type Assoc = u32; }
+}
+
+mod denied {
+    #![deny(nested_impl_trait)]
+
+    pub trait Bar { }
+    pub trait Quux<T> { type Assoc; }
+    pub fn demo(_: impl Quux<(), Assoc=<() as Quux<impl Bar>>::Assoc>) { }
+    //~^ ERROR `impl Trait` is not allowed in path parameters
+    //~| WARN will become a hard error in a future release!
+    impl<T> Quux<T> for () { type Assoc = u32; }
+}
+
+fn main() { }
diff --git a/src/test/ui/impl-trait/issue-57979-impl-trait-in-path.stderr b/src/test/ui/impl-trait/issue-57979-impl-trait-in-path.stderr
new file mode 100644
index 0000000..982ecba
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-57979-impl-trait-in-path.stderr
@@ -0,0 +1,30 @@
+warning: `impl Trait` is not allowed in path parameters
+  --> $DIR/issue-57979-impl-trait-in-path.rs:20:52
+   |
+LL |     pub fn demo(_: impl Quux<(), Assoc=<() as Quux<impl Bar>>::Assoc>) { }
+   |                                                    ^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/issue-57979-impl-trait-in-path.rs:16:13
+   |
+LL |     #![warn(nested_impl_trait)]
+   |             ^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #59014 <https://github.com/rust-lang/rust/issues/59014>
+
+error: `impl Trait` is not allowed in path parameters
+  --> $DIR/issue-57979-impl-trait-in-path.rs:31:52
+   |
+LL |     pub fn demo(_: impl Quux<(), Assoc=<() as Quux<impl Bar>>::Assoc>) { }
+   |                                                    ^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/issue-57979-impl-trait-in-path.rs:27:13
+   |
+LL |     #![deny(nested_impl_trait)]
+   |             ^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #59014 <https://github.com/rust-lang/rust/issues/59014>
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/impl-trait/issue-57979-nested-impl-trait-in-assoc-proj.rs b/src/test/ui/impl-trait/issue-57979-nested-impl-trait-in-assoc-proj.rs
new file mode 100644
index 0000000..5c20ffc
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-57979-nested-impl-trait-in-assoc-proj.rs
@@ -0,0 +1,37 @@
+// rust-lang/rust#57979 : the initial support for `impl Trait` didn't
+// properly check syntax hidden behind an associated type projection.
+// Here we test behavior of occurrences of `impl Trait` within an
+// `impl Trait` in that context.
+
+mod allowed {
+    #![allow(nested_impl_trait)]
+
+    pub trait Foo<T> { }
+    pub trait Bar { }
+    pub trait Quux { type Assoc; }
+    pub fn demo(_: impl Quux<Assoc=impl Foo<impl Bar>>) { }
+}
+
+mod warned {
+    #![warn(nested_impl_trait)]
+
+    pub trait Foo<T> { }
+    pub trait Bar { }
+    pub trait Quux { type Assoc; }
+    pub fn demo(_: impl Quux<Assoc=impl Foo<impl Bar>>) { }
+    //~^ WARN nested `impl Trait` is not allowed
+    //~| WARN will become a hard error in a future release!
+}
+
+mod denied {
+    #![deny(nested_impl_trait)]
+
+    pub trait Foo<T> { }
+    pub trait Bar { }
+    pub trait Quux { type Assoc; }
+    pub fn demo(_: impl Quux<Assoc=impl Foo<impl Bar>>) { }
+    //~^ ERROR nested `impl Trait` is not allowed
+    //~| WARN will become a hard error in a future release!
+}
+
+fn main() { }
diff --git a/src/test/ui/impl-trait/issue-57979-nested-impl-trait-in-assoc-proj.stderr b/src/test/ui/impl-trait/issue-57979-nested-impl-trait-in-assoc-proj.stderr
new file mode 100644
index 0000000..508aea2
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-57979-nested-impl-trait-in-assoc-proj.stderr
@@ -0,0 +1,36 @@
+warning: nested `impl Trait` is not allowed
+  --> $DIR/issue-57979-nested-impl-trait-in-assoc-proj.rs:21:45
+   |
+LL |     pub fn demo(_: impl Quux<Assoc=impl Foo<impl Bar>>) { }
+   |                                    ---------^^^^^^^^-
+   |                                    |        |
+   |                                    |        nested `impl Trait` here
+   |                                    outer `impl Trait`
+   |
+note: lint level defined here
+  --> $DIR/issue-57979-nested-impl-trait-in-assoc-proj.rs:16:13
+   |
+LL |     #![warn(nested_impl_trait)]
+   |             ^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #59014 <https://github.com/rust-lang/rust/issues/59014>
+
+error: nested `impl Trait` is not allowed
+  --> $DIR/issue-57979-nested-impl-trait-in-assoc-proj.rs:32:45
+   |
+LL |     pub fn demo(_: impl Quux<Assoc=impl Foo<impl Bar>>) { }
+   |                                    ---------^^^^^^^^-
+   |                                    |        |
+   |                                    |        nested `impl Trait` here
+   |                                    outer `impl Trait`
+   |
+note: lint level defined here
+  --> $DIR/issue-57979-nested-impl-trait-in-assoc-proj.rs:27:13
+   |
+LL |     #![deny(nested_impl_trait)]
+   |             ^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #59014 <https://github.com/rust-lang/rust/issues/59014>
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/impl-trait/method-suggestion-no-duplication.rs b/src/test/ui/impl-trait/method-suggestion-no-duplication.rs
new file mode 100644
index 0000000..32f3517
--- /dev/null
+++ b/src/test/ui/impl-trait/method-suggestion-no-duplication.rs
@@ -0,0 +1,11 @@
+// issue #21405
+// ignore-tidy-linelength
+
+struct Foo;
+
+fn foo<F>(f: F) where F: FnMut(Foo) {}
+
+fn main() {
+    foo(|s| s.is_empty());
+    //~^ ERROR no method named `is_empty` found
+}
diff --git a/src/test/ui/impl-trait/method-suggestion-no-duplication.stderr b/src/test/ui/impl-trait/method-suggestion-no-duplication.stderr
new file mode 100644
index 0000000..8da1ce4
--- /dev/null
+++ b/src/test/ui/impl-trait/method-suggestion-no-duplication.stderr
@@ -0,0 +1,16 @@
+error[E0599]: no method named `is_empty` found for type `Foo` in the current scope
+  --> $DIR/method-suggestion-no-duplication.rs:9:15
+   |
+LL | struct Foo;
+   | ----------- method `is_empty` not found for this
+...
+LL |     foo(|s| s.is_empty());
+   |               ^^^^^^^^
+   |
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following trait defines an item `is_empty`, perhaps you need to implement it:
+           candidate #1: `std::iter::ExactSizeIterator`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs
new file mode 100644
index 0000000..1c3b5ac
--- /dev/null
+++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs
@@ -0,0 +1,27 @@
+use std::fmt::Debug;
+
+fn elided(x: &i32) -> impl Copy { x }
+//~^ ERROR cannot infer an appropriate lifetime
+
+fn explicit<'a>(x: &'a i32) -> impl Copy { x }
+//~^ ERROR cannot infer an appropriate lifetime
+
+trait LifetimeTrait<'a> {}
+impl<'a> LifetimeTrait<'a> for &'a i32 {}
+
+fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
+//~^ ERROR cannot infer an appropriate lifetime
+
+// Tests that a closure type contianing 'b cannot be returned from a type where
+// only 'a was expected.
+fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) {
+    //~^ ERROR lifetime mismatch
+    move |_| println!("{}", y)
+}
+
+fn ty_param_wont_outlive_static<T:Debug>(x: T) -> impl Debug + 'static {
+    //~^ ERROR the parameter type `T` may not live long enough
+    x
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr
new file mode 100644
index 0000000..9339a83
--- /dev/null
+++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr
@@ -0,0 +1,81 @@
+error: cannot infer an appropriate lifetime
+  --> $DIR/must_outlive_least_region_or_bound.rs:3:35
+   |
+LL | fn elided(x: &i32) -> impl Copy { x }
+   |                       ---------   ^ ...but this borrow...
+   |                       |
+   |                       this return type evaluates to the `'static` lifetime...
+   |
+note: ...can't outlive the anonymous lifetime #1 defined on the function body at 3:1
+  --> $DIR/must_outlive_least_region_or_bound.rs:3:1
+   |
+LL | fn elided(x: &i32) -> impl Copy { x }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: you can add a constraint to the return type to make it last less than `'static` and match the anonymous lifetime #1 defined on the function body at 3:1
+   |
+LL | fn elided(x: &i32) -> impl Copy + '_ { x }
+   |                       ^^^^^^^^^^^^^^
+
+error: cannot infer an appropriate lifetime
+  --> $DIR/must_outlive_least_region_or_bound.rs:6:44
+   |
+LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x }
+   |                                ---------   ^ ...but this borrow...
+   |                                |
+   |                                this return type evaluates to the `'static` lifetime...
+   |
+note: ...can't outlive the lifetime 'a as defined on the function body at 6:13
+  --> $DIR/must_outlive_least_region_or_bound.rs:6:13
+   |
+LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x }
+   |             ^^
+help: you can add a constraint to the return type to make it last less than `'static` and match the lifetime 'a as defined on the function body at 6:13
+   |
+LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x }
+   |                                ^^^^^^^^^^^^^^
+
+error: cannot infer an appropriate lifetime
+  --> $DIR/must_outlive_least_region_or_bound.rs:12:69
+   |
+LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
+   |                                  --------------------------------   ^ ...but this borrow...
+   |                                  |
+   |                                  this return type evaluates to the `'static` lifetime...
+   |
+note: ...can't outlive the lifetime 'a as defined on the function body at 12:15
+  --> $DIR/must_outlive_least_region_or_bound.rs:12:15
+   |
+LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
+   |               ^^
+help: you can add a constraint to the return type to make it last less than `'static` and match the lifetime 'a as defined on the function body at 12:15
+   |
+LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static + 'a { x }
+   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0623]: lifetime mismatch
+  --> $DIR/must_outlive_least_region_or_bound.rs:17:61
+   |
+LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) {
+   |                                                 -------     ^^^^^^^^^^^^^^^^
+   |                                                 |           |
+   |                                                 |           ...but data from `y` is returned here
+   |                                                 this parameter and the return type are declared with different lifetimes...
+
+error[E0310]: the parameter type `T` may not live long enough
+  --> $DIR/must_outlive_least_region_or_bound.rs:22:51
+   |
+LL | fn ty_param_wont_outlive_static<T:Debug>(x: T) -> impl Debug + 'static {
+   |                                 --                ^^^^^^^^^^^^^^^^^^^^
+   |                                 |
+   |                                 help: consider adding an explicit lifetime bound `T: 'static`...
+   |
+note: ...so that the type `T` will meet its required lifetime bounds
+  --> $DIR/must_outlive_least_region_or_bound.rs:22:51
+   |
+LL | fn ty_param_wont_outlive_static<T:Debug>(x: T) -> impl Debug + 'static {
+   |                                                   ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
+
+Some errors occurred: E0310, E0623.
+For more information about an error, try `rustc --explain E0310`.
diff --git a/src/test/ui/impl-trait/needs_least_region_or_bound.rs b/src/test/ui/impl-trait/needs_least_region_or_bound.rs
new file mode 100644
index 0000000..2a5b365
--- /dev/null
+++ b/src/test/ui/impl-trait/needs_least_region_or_bound.rs
@@ -0,0 +1,11 @@
+use std::fmt::Debug;
+
+trait MultiRegionTrait<'a, 'b> {}
+impl<'a, 'b> MultiRegionTrait<'a, 'b> for (&'a u32, &'b u32) {}
+
+fn no_least_region<'a, 'b>(x: &'a u32, y: &'b u32) -> impl MultiRegionTrait<'a, 'b> {
+//~^ ERROR ambiguous lifetime bound
+    (x, y)
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/needs_least_region_or_bound.stderr b/src/test/ui/impl-trait/needs_least_region_or_bound.stderr
new file mode 100644
index 0000000..f1b4d9c
--- /dev/null
+++ b/src/test/ui/impl-trait/needs_least_region_or_bound.stderr
@@ -0,0 +1,8 @@
+error: ambiguous lifetime bound in `impl Trait`
+  --> $DIR/needs_least_region_or_bound.rs:6:55
+   |
+LL | fn no_least_region<'a, 'b>(x: &'a u32, y: &'b u32) -> impl MultiRegionTrait<'a, 'b> {
+   |                                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ neither `'a` nor `'b` outlives the other
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/impl-trait/no-method-suggested-traits.rs b/src/test/ui/impl-trait/no-method-suggested-traits.rs
new file mode 100644
index 0000000..c912873
--- /dev/null
+++ b/src/test/ui/impl-trait/no-method-suggested-traits.rs
@@ -0,0 +1,77 @@
+// aux-build:no_method_suggested_traits.rs
+extern crate no_method_suggested_traits;
+
+struct Foo;
+enum Bar { X }
+
+mod foo {
+    pub trait Bar {
+        fn method(&self) {}
+
+        fn method2(&self) {}
+    }
+
+    impl Bar for u32 {}
+
+    impl Bar for char {}
+}
+
+fn main() {
+    // test the values themselves, and autoderef.
+
+
+    1u32.method();
+    //~^ ERROR no method named
+    //~|items from traits can only be used if the trait is in scope
+    std::rc::Rc::new(&mut Box::new(&1u32)).method();
+    //~^items from traits can only be used if the trait is in scope
+    //~| ERROR no method named `method` found for type
+
+    'a'.method();
+    //~^ ERROR no method named
+    std::rc::Rc::new(&mut Box::new(&'a')).method();
+    //~^ ERROR no method named
+
+    1i32.method();
+    //~^ ERROR no method named
+    std::rc::Rc::new(&mut Box::new(&1i32)).method();
+    //~^ ERROR no method named
+
+    Foo.method();
+    //~^ ERROR no method named
+    std::rc::Rc::new(&mut Box::new(&Foo)).method();
+    //~^ ERROR no method named
+
+    1u64.method2();
+    //~^ ERROR no method named
+    std::rc::Rc::new(&mut Box::new(&1u64)).method2();
+    //~^ ERROR no method named
+
+    no_method_suggested_traits::Foo.method2();
+    //~^ ERROR no method named
+    std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Foo)).method2();
+    //~^ ERROR no method named
+    no_method_suggested_traits::Bar::X.method2();
+    //~^ ERROR no method named
+    std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Bar::X)).method2();
+    //~^ ERROR no method named
+
+    Foo.method3();
+    //~^ ERROR no method named
+    std::rc::Rc::new(&mut Box::new(&Foo)).method3();
+    //~^ ERROR no method named
+    Bar::X.method3();
+    //~^ ERROR no method named
+    std::rc::Rc::new(&mut Box::new(&Bar::X)).method3();
+    //~^ ERROR no method named
+
+    // should have no help:
+    1_usize.method3(); //~ ERROR no method named
+    std::rc::Rc::new(&mut Box::new(&1_usize)).method3(); //~ ERROR no method named
+    no_method_suggested_traits::Foo.method3();  //~ ERROR no method named
+    std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Foo)).method3();
+    //~^ ERROR no method named
+    no_method_suggested_traits::Bar::X.method3();  //~ ERROR no method named
+    std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Bar::X)).method3();
+    //~^ ERROR no method named
+}
diff --git a/src/test/ui/impl-trait/no-method-suggested-traits.stderr b/src/test/ui/impl-trait/no-method-suggested-traits.stderr
new file mode 100644
index 0000000..d980d7c
--- /dev/null
+++ b/src/test/ui/impl-trait/no-method-suggested-traits.stderr
@@ -0,0 +1,258 @@
+error[E0599]: no method named `method` found for type `u32` in the current scope
+  --> $DIR/no-method-suggested-traits.rs:23:10
+   |
+LL |     1u32.method();
+   |          ^^^^^^
+   |
+   = help: items from traits can only be used if the trait is in scope
+help: the following traits are implemented but not in scope, perhaps add a `use` for one of them:
+   |
+LL | use foo::Bar;
+   |
+LL | use no_method_suggested_traits::foo::PubPub;
+   |
+LL | use no_method_suggested_traits::qux::PrivPub;
+   |
+LL | use no_method_suggested_traits::Reexported;
+   |
+
+error[E0599]: no method named `method` found for type `std::rc::Rc<&mut std::boxed::Box<&u32>>` in the current scope
+  --> $DIR/no-method-suggested-traits.rs:26:44
+   |
+LL |     std::rc::Rc::new(&mut Box::new(&1u32)).method();
+   |                                            ^^^^^^
+   |
+   = help: items from traits can only be used if the trait is in scope
+help: the following traits are implemented but not in scope, perhaps add a `use` for one of them:
+   |
+LL | use foo::Bar;
+   |
+LL | use no_method_suggested_traits::foo::PubPub;
+   |
+LL | use no_method_suggested_traits::qux::PrivPub;
+   |
+LL | use no_method_suggested_traits::Reexported;
+   |
+
+error[E0599]: no method named `method` found for type `char` in the current scope
+  --> $DIR/no-method-suggested-traits.rs:30:9
+   |
+LL |     'a'.method();
+   |         ^^^^^^
+   |
+   = help: items from traits can only be used if the trait is in scope
+help: the following trait is implemented but not in scope, perhaps add a `use` for it:
+   |
+LL | use foo::Bar;
+   |
+
+error[E0599]: no method named `method` found for type `std::rc::Rc<&mut std::boxed::Box<&char>>` in the current scope
+  --> $DIR/no-method-suggested-traits.rs:32:43
+   |
+LL |     std::rc::Rc::new(&mut Box::new(&'a')).method();
+   |                                           ^^^^^^
+   |
+   = help: items from traits can only be used if the trait is in scope
+help: the following trait is implemented but not in scope, perhaps add a `use` for it:
+   |
+LL | use foo::Bar;
+   |
+
+error[E0599]: no method named `method` found for type `i32` in the current scope
+  --> $DIR/no-method-suggested-traits.rs:35:10
+   |
+LL |     1i32.method();
+   |          ^^^^^^
+   |
+   = help: items from traits can only be used if the trait is in scope
+help: the following trait is implemented but not in scope, perhaps add a `use` for it:
+   |
+LL | use no_method_suggested_traits::foo::PubPub;
+   |
+
+error[E0599]: no method named `method` found for type `std::rc::Rc<&mut std::boxed::Box<&i32>>` in the current scope
+  --> $DIR/no-method-suggested-traits.rs:37:44
+   |
+LL |     std::rc::Rc::new(&mut Box::new(&1i32)).method();
+   |                                            ^^^^^^
+   |
+   = help: items from traits can only be used if the trait is in scope
+help: the following trait is implemented but not in scope, perhaps add a `use` for it:
+   |
+LL | use no_method_suggested_traits::foo::PubPub;
+   |
+
+error[E0599]: no method named `method` found for type `Foo` in the current scope
+  --> $DIR/no-method-suggested-traits.rs:40:9
+   |
+LL | struct Foo;
+   | ----------- method `method` not found for this
+...
+LL |     Foo.method();
+   |         ^^^^^^
+   |
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following traits define an item `method`, perhaps you need to implement one of them:
+           candidate #1: `foo::Bar`
+           candidate #2: `no_method_suggested_traits::foo::PubPub`
+           candidate #3: `no_method_suggested_traits::qux::PrivPub`
+           candidate #4: `no_method_suggested_traits::Reexported`
+
+error[E0599]: no method named `method` found for type `std::rc::Rc<&mut std::boxed::Box<&Foo>>` in the current scope
+  --> $DIR/no-method-suggested-traits.rs:42:43
+   |
+LL |     std::rc::Rc::new(&mut Box::new(&Foo)).method();
+   |                                           ^^^^^^
+   |
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following traits define an item `method`, perhaps you need to implement one of them:
+           candidate #1: `foo::Bar`
+           candidate #2: `no_method_suggested_traits::foo::PubPub`
+           candidate #3: `no_method_suggested_traits::qux::PrivPub`
+           candidate #4: `no_method_suggested_traits::Reexported`
+
+error[E0599]: no method named `method2` found for type `u64` in the current scope
+  --> $DIR/no-method-suggested-traits.rs:45:10
+   |
+LL |     1u64.method2();
+   |          ^^^^^^^
+   |
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following trait defines an item `method2`, perhaps you need to implement it:
+           candidate #1: `foo::Bar`
+
+error[E0599]: no method named `method2` found for type `std::rc::Rc<&mut std::boxed::Box<&u64>>` in the current scope
+  --> $DIR/no-method-suggested-traits.rs:47:44
+   |
+LL |     std::rc::Rc::new(&mut Box::new(&1u64)).method2();
+   |                                            ^^^^^^^
+   |
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following trait defines an item `method2`, perhaps you need to implement it:
+           candidate #1: `foo::Bar`
+
+error[E0599]: no method named `method2` found for type `no_method_suggested_traits::Foo` in the current scope
+  --> $DIR/no-method-suggested-traits.rs:50:37
+   |
+LL |     no_method_suggested_traits::Foo.method2();
+   |                                     ^^^^^^^
+   |
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following trait defines an item `method2`, perhaps you need to implement it:
+           candidate #1: `foo::Bar`
+
+error[E0599]: no method named `method2` found for type `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Foo>>` in the current scope
+  --> $DIR/no-method-suggested-traits.rs:52:71
+   |
+LL |     std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Foo)).method2();
+   |                                                                       ^^^^^^^
+   |
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following trait defines an item `method2`, perhaps you need to implement it:
+           candidate #1: `foo::Bar`
+
+error[E0599]: no method named `method2` found for type `no_method_suggested_traits::Bar` in the current scope
+  --> $DIR/no-method-suggested-traits.rs:54:40
+   |
+LL |     no_method_suggested_traits::Bar::X.method2();
+   |                                        ^^^^^^^
+   |
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following trait defines an item `method2`, perhaps you need to implement it:
+           candidate #1: `foo::Bar`
+
+error[E0599]: no method named `method2` found for type `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Bar>>` in the current scope
+  --> $DIR/no-method-suggested-traits.rs:56:74
+   |
+LL |     std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Bar::X)).method2();
+   |                                                                          ^^^^^^^
+   |
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following trait defines an item `method2`, perhaps you need to implement it:
+           candidate #1: `foo::Bar`
+
+error[E0599]: no method named `method3` found for type `Foo` in the current scope
+  --> $DIR/no-method-suggested-traits.rs:59:9
+   |
+LL | struct Foo;
+   | ----------- method `method3` not found for this
+...
+LL |     Foo.method3();
+   |         ^^^^^^^
+   |
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following trait defines an item `method3`, perhaps you need to implement it:
+           candidate #1: `no_method_suggested_traits::foo::PubPub`
+
+error[E0599]: no method named `method3` found for type `std::rc::Rc<&mut std::boxed::Box<&Foo>>` in the current scope
+  --> $DIR/no-method-suggested-traits.rs:61:43
+   |
+LL |     std::rc::Rc::new(&mut Box::new(&Foo)).method3();
+   |                                           ^^^^^^^
+   |
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following trait defines an item `method3`, perhaps you need to implement it:
+           candidate #1: `no_method_suggested_traits::foo::PubPub`
+
+error[E0599]: no method named `method3` found for type `Bar` in the current scope
+  --> $DIR/no-method-suggested-traits.rs:63:12
+   |
+LL | enum Bar { X }
+   | -------- method `method3` not found for this
+...
+LL |     Bar::X.method3();
+   |            ^^^^^^^
+   |
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following trait defines an item `method3`, perhaps you need to implement it:
+           candidate #1: `no_method_suggested_traits::foo::PubPub`
+
+error[E0599]: no method named `method3` found for type `std::rc::Rc<&mut std::boxed::Box<&Bar>>` in the current scope
+  --> $DIR/no-method-suggested-traits.rs:65:46
+   |
+LL |     std::rc::Rc::new(&mut Box::new(&Bar::X)).method3();
+   |                                              ^^^^^^^
+   |
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following trait defines an item `method3`, perhaps you need to implement it:
+           candidate #1: `no_method_suggested_traits::foo::PubPub`
+
+error[E0599]: no method named `method3` found for type `usize` in the current scope
+  --> $DIR/no-method-suggested-traits.rs:69:13
+   |
+LL |     1_usize.method3();
+   |             ^^^^^^^
+
+error[E0599]: no method named `method3` found for type `std::rc::Rc<&mut std::boxed::Box<&usize>>` in the current scope
+  --> $DIR/no-method-suggested-traits.rs:70:47
+   |
+LL |     std::rc::Rc::new(&mut Box::new(&1_usize)).method3();
+   |                                               ^^^^^^^
+
+error[E0599]: no method named `method3` found for type `no_method_suggested_traits::Foo` in the current scope
+  --> $DIR/no-method-suggested-traits.rs:71:37
+   |
+LL |     no_method_suggested_traits::Foo.method3();
+   |                                     ^^^^^^^
+
+error[E0599]: no method named `method3` found for type `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Foo>>` in the current scope
+  --> $DIR/no-method-suggested-traits.rs:72:71
+   |
+LL |     std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Foo)).method3();
+   |                                                                       ^^^^^^^
+
+error[E0599]: no method named `method3` found for type `no_method_suggested_traits::Bar` in the current scope
+  --> $DIR/no-method-suggested-traits.rs:74:40
+   |
+LL |     no_method_suggested_traits::Bar::X.method3();
+   |                                        ^^^^^^^
+
+error[E0599]: no method named `method3` found for type `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Bar>>` in the current scope
+  --> $DIR/no-method-suggested-traits.rs:75:74
+   |
+LL |     std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Bar::X)).method3();
+   |                                                                          ^^^^^^^
+
+error: aborting due to 24 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/impl-trait/no-trait.rs b/src/test/ui/impl-trait/no-trait.rs
new file mode 100644
index 0000000..9ce668f
--- /dev/null
+++ b/src/test/ui/impl-trait/no-trait.rs
@@ -0,0 +1,3 @@
+fn f() -> impl 'static {} //~ ERROR at least one trait must be specified
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/no-trait.stderr b/src/test/ui/impl-trait/no-trait.stderr
new file mode 100644
index 0000000..3a636f2
--- /dev/null
+++ b/src/test/ui/impl-trait/no-trait.stderr
@@ -0,0 +1,8 @@
+error: at least one trait must be specified
+  --> $DIR/no-trait.rs:1:11
+   |
+LL | fn f() -> impl 'static {}
+   |           ^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/impl-trait/recursive-async-impl-trait-type.rs b/src/test/ui/impl-trait/recursive-async-impl-trait-type.rs
new file mode 100644
index 0000000..4064252
--- /dev/null
+++ b/src/test/ui/impl-trait/recursive-async-impl-trait-type.rs
@@ -0,0 +1,11 @@
+// edition:2018
+// Test that impl trait does not allow creating recursive types that are
+// otherwise forbidden when using `async` and `await`.
+
+#![feature(await_macro, async_await, futures_api, generators)]
+
+async fn recursive_async_function() -> () { //~ ERROR
+    await!(recursive_async_function());
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/recursive-async-impl-trait-type.stderr b/src/test/ui/impl-trait/recursive-async-impl-trait-type.stderr
new file mode 100644
index 0000000..abc9ff5
--- /dev/null
+++ b/src/test/ui/impl-trait/recursive-async-impl-trait-type.stderr
@@ -0,0 +1,11 @@
+error[E0720]: opaque type expands to a recursive type
+  --> $DIR/recursive-async-impl-trait-type.rs:7:40
+   |
+LL | async fn recursive_async_function() -> () {
+   |                                        ^^ expands to self-referential type
+   |
+   = note: expanded type is `std::future::GenFuture<[static generator@$DIR/recursive-async-impl-trait-type.rs:7:43: 9:2 {impl std::future::Future, ()}]>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0720`.
diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type.rs b/src/test/ui/impl-trait/recursive-impl-trait-type.rs
new file mode 100644
index 0000000..869876d
--- /dev/null
+++ b/src/test/ui/impl-trait/recursive-impl-trait-type.rs
@@ -0,0 +1,77 @@
+// Test that impl trait does not allow creating recursive types that are
+// otherwise forbidden.
+
+#![feature(futures_api, generators)]
+
+fn option(i: i32) -> impl Sized { //~ ERROR
+    if i < 0 {
+        None
+    } else {
+        Some((option(i - 1), i))
+    }
+}
+
+fn tuple() -> impl Sized { //~ ERROR
+    (tuple(),)
+}
+
+fn array() -> impl Sized { //~ ERROR
+    [array()]
+}
+
+fn ptr() -> impl Sized { //~ ERROR
+    &ptr() as *const _
+}
+
+fn fn_ptr() -> impl Sized { //~ ERROR
+    fn_ptr as fn() -> _
+}
+
+fn closure_capture() -> impl Sized { //~ ERROR
+    let x = closure_capture();
+    move || { x; }
+}
+
+fn closure_ref_capture() -> impl Sized { //~ ERROR
+    let x = closure_ref_capture();
+    move || { &x; }
+}
+
+fn closure_sig() -> impl Sized { //~ ERROR
+    || closure_sig()
+}
+
+fn generator_sig() -> impl Sized { //~ ERROR
+    || generator_sig()
+}
+
+fn generator_capture() -> impl Sized { //~ ERROR
+    let x = generator_capture();
+    move || { yield; x; }
+}
+
+fn substs_change<T>() -> impl Sized { //~ ERROR
+    (substs_change::<&T>(),)
+}
+
+fn generator_hold() -> impl Sized { //~ ERROR
+    move || {
+        let x = generator_hold();
+        yield;
+        x;
+    }
+}
+
+fn use_fn_ptr() -> impl Sized { // OK, error already reported
+    fn_ptr()
+}
+
+fn mutual_recursion() -> impl Sync { //~ ERROR
+    mutual_recursion_b()
+}
+
+fn mutual_recursion_b() -> impl Sized { //~ ERROR
+    mutual_recursion()
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type.stderr b/src/test/ui/impl-trait/recursive-impl-trait-type.stderr
new file mode 100644
index 0000000..fce234e
--- /dev/null
+++ b/src/test/ui/impl-trait/recursive-impl-trait-type.stderr
@@ -0,0 +1,115 @@
+error[E0720]: opaque type expands to a recursive type
+  --> $DIR/recursive-impl-trait-type.rs:6:22
+   |
+LL | fn option(i: i32) -> impl Sized {
+   |                      ^^^^^^^^^^ expands to self-referential type
+   |
+   = note: expanded type is `std::option::Option<(impl Sized, i32)>`
+
+error[E0720]: opaque type expands to a recursive type
+  --> $DIR/recursive-impl-trait-type.rs:14:15
+   |
+LL | fn tuple() -> impl Sized {
+   |               ^^^^^^^^^^ expands to self-referential type
+   |
+   = note: expanded type is `(impl Sized,)`
+
+error[E0720]: opaque type expands to a recursive type
+  --> $DIR/recursive-impl-trait-type.rs:18:15
+   |
+LL | fn array() -> impl Sized {
+   |               ^^^^^^^^^^ expands to self-referential type
+   |
+   = note: expanded type is `[impl Sized; 1]`
+
+error[E0720]: opaque type expands to a recursive type
+  --> $DIR/recursive-impl-trait-type.rs:22:13
+   |
+LL | fn ptr() -> impl Sized {
+   |             ^^^^^^^^^^ expands to self-referential type
+   |
+   = note: expanded type is `*const impl Sized`
+
+error[E0720]: opaque type expands to a recursive type
+  --> $DIR/recursive-impl-trait-type.rs:26:16
+   |
+LL | fn fn_ptr() -> impl Sized {
+   |                ^^^^^^^^^^ expands to self-referential type
+   |
+   = note: expanded type is `fn() -> impl Sized`
+
+error[E0720]: opaque type expands to a recursive type
+  --> $DIR/recursive-impl-trait-type.rs:30:25
+   |
+LL | fn closure_capture() -> impl Sized {
+   |                         ^^^^^^^^^^ expands to self-referential type
+   |
+   = note: expanded type is `[closure@$DIR/recursive-impl-trait-type.rs:32:5: 32:19 x:impl Sized]`
+
+error[E0720]: opaque type expands to a recursive type
+  --> $DIR/recursive-impl-trait-type.rs:35:29
+   |
+LL | fn closure_ref_capture() -> impl Sized {
+   |                             ^^^^^^^^^^ expands to self-referential type
+   |
+   = note: expanded type is `[closure@$DIR/recursive-impl-trait-type.rs:37:5: 37:20 x:impl Sized]`
+
+error[E0720]: opaque type expands to a recursive type
+  --> $DIR/recursive-impl-trait-type.rs:40:21
+   |
+LL | fn closure_sig() -> impl Sized {
+   |                     ^^^^^^^^^^ expands to self-referential type
+   |
+   = note: expanded type is `[closure@$DIR/recursive-impl-trait-type.rs:41:5: 41:21]`
+
+error[E0720]: opaque type expands to a recursive type
+  --> $DIR/recursive-impl-trait-type.rs:44:23
+   |
+LL | fn generator_sig() -> impl Sized {
+   |                       ^^^^^^^^^^ expands to self-referential type
+   |
+   = note: expanded type is `[closure@$DIR/recursive-impl-trait-type.rs:45:5: 45:23]`
+
+error[E0720]: opaque type expands to a recursive type
+  --> $DIR/recursive-impl-trait-type.rs:48:27
+   |
+LL | fn generator_capture() -> impl Sized {
+   |                           ^^^^^^^^^^ expands to self-referential type
+   |
+   = note: expanded type is `[generator@$DIR/recursive-impl-trait-type.rs:50:5: 50:26 x:impl Sized {()}]`
+
+error[E0720]: opaque type expands to a recursive type
+  --> $DIR/recursive-impl-trait-type.rs:53:26
+   |
+LL | fn substs_change<T>() -> impl Sized {
+   |                          ^^^^^^^^^^ expands to self-referential type
+   |
+   = note: expanded type is `(impl Sized,)`
+
+error[E0720]: opaque type expands to a recursive type
+  --> $DIR/recursive-impl-trait-type.rs:57:24
+   |
+LL | fn generator_hold() -> impl Sized {
+   |                        ^^^^^^^^^^ expands to self-referential type
+   |
+   = note: expanded type is `[generator@$DIR/recursive-impl-trait-type.rs:58:5: 62:6 {impl Sized, ()}]`
+
+error[E0720]: opaque type expands to a recursive type
+  --> $DIR/recursive-impl-trait-type.rs:69:26
+   |
+LL | fn mutual_recursion() -> impl Sync {
+   |                          ^^^^^^^^^ expands to self-referential type
+   |
+   = note: type resolves to itself
+
+error[E0720]: opaque type expands to a recursive type
+  --> $DIR/recursive-impl-trait-type.rs:73:28
+   |
+LL | fn mutual_recursion_b() -> impl Sized {
+   |                            ^^^^^^^^^^ expands to self-referential type
+   |
+   = note: type resolves to itself
+
+error: aborting due to 14 previous errors
+
+For more information about this error, try `rustc --explain E0720`.
diff --git a/src/test/ui/impl-trait/region-escape-via-bound-contravariant-closure.rs b/src/test/ui/impl-trait/region-escape-via-bound-contravariant-closure.rs
new file mode 100644
index 0000000..cb40d90
--- /dev/null
+++ b/src/test/ui/impl-trait/region-escape-via-bound-contravariant-closure.rs
@@ -0,0 +1,20 @@
+// In contrast to `region-escape-via-bound-invariant`, in this case we
+// *can* return a value of type `&'x u32`, even though `'x` does not
+// appear in the bounds. This is because `&` is contravariant, and so
+// we are *actually* returning a `&'y u32`.
+//
+// See https://github.com/rust-lang/rust/issues/46541 for more details.
+
+// run-pass
+
+#![allow(dead_code)]
+#![feature(in_band_lifetimes)]
+#![feature(nll)]
+
+fn foo(x: &'x u32) -> impl Fn() -> &'y u32
+where 'x: 'y
+{
+    move || x
+}
+
+fn main() { }
diff --git a/src/test/ui/impl-trait/region-escape-via-bound-contravariant.rs b/src/test/ui/impl-trait/region-escape-via-bound-contravariant.rs
new file mode 100644
index 0000000..e2310a3
--- /dev/null
+++ b/src/test/ui/impl-trait/region-escape-via-bound-contravariant.rs
@@ -0,0 +1,24 @@
+// In contrast to `region-escape-via-bound-invariant`, in this case we
+// *can* return a value of type `&'x u32`, even though `'x` does not
+// appear in the bounds. This is because `&` is contravariant, and so
+// we are *actually* returning a `&'y u32`.
+//
+// See https://github.com/rust-lang/rust/issues/46541 for more details.
+
+// run-pass
+
+#![allow(dead_code)]
+#![feature(in_band_lifetimes)]
+#![feature(nll)]
+
+trait Trait<'a> { }
+
+impl Trait<'b> for &'a u32 { }
+
+fn foo(x: &'x u32) -> impl Trait<'y>
+where 'x: 'y
+{
+    x
+}
+
+fn main() { }
diff --git a/src/test/ui/impl-trait/region-escape-via-bound.rs b/src/test/ui/impl-trait/region-escape-via-bound.rs
new file mode 100644
index 0000000..d62aec8
--- /dev/null
+++ b/src/test/ui/impl-trait/region-escape-via-bound.rs
@@ -0,0 +1,23 @@
+// Test that we do not allow the region `'x` to escape in the impl
+// trait **even though** `'y` escapes, which outlives `'x`.
+//
+// See https://github.com/rust-lang/rust/issues/46541 for more details.
+
+#![allow(dead_code)]
+#![feature(in_band_lifetimes)]
+#![feature(nll)]
+
+use std::cell::Cell;
+
+trait Trait<'a> { }
+
+impl Trait<'b> for Cell<&'a u32> { }
+
+fn foo(x: Cell<&'x u32>) -> impl Trait<'y>
+    //~^ ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds [E0700]
+where 'x: 'y
+{
+    x
+}
+
+fn main() { }
diff --git a/src/test/ui/impl-trait/region-escape-via-bound.stderr b/src/test/ui/impl-trait/region-escape-via-bound.stderr
new file mode 100644
index 0000000..81b44b7
--- /dev/null
+++ b/src/test/ui/impl-trait/region-escape-via-bound.stderr
@@ -0,0 +1,15 @@
+error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+  --> $DIR/region-escape-via-bound.rs:16:29
+   |
+LL | fn foo(x: Cell<&'x u32>) -> impl Trait<'y>
+   |                             ^^^^^^^^^^^^^^
+   |
+note: hidden type `std::cell::Cell<&'x u32>` captures the lifetime 'x as defined on the function body at 18:7
+  --> $DIR/region-escape-via-bound.rs:18:7
+   |
+LL | where 'x: 'y
+   |       ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0700`.
diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.rs b/src/test/ui/impl-trait/static-return-lifetime-infered.rs
new file mode 100644
index 0000000..96f3652
--- /dev/null
+++ b/src/test/ui/impl-trait/static-return-lifetime-infered.rs
@@ -0,0 +1,16 @@
+struct A {
+    x: [(u32, u32); 10]
+}
+
+impl A {
+    fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
+        self.x.iter().map(|a| a.0)
+    }
+    //~^^ ERROR cannot infer an appropriate lifetime
+    fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
+        self.x.iter().map(|a| a.0)
+    }
+    //~^^ ERROR cannot infer an appropriate lifetime
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr
new file mode 100644
index 0000000..0bc0180
--- /dev/null
+++ b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr
@@ -0,0 +1,44 @@
+error: cannot infer an appropriate lifetime
+  --> $DIR/static-return-lifetime-infered.rs:7:16
+   |
+LL |     fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
+   |                                   ----------------------- this return type evaluates to the `'static` lifetime...
+LL |         self.x.iter().map(|a| a.0)
+   |         ------ ^^^^
+   |         |
+   |         ...but this borrow...
+   |
+note: ...can't outlive the anonymous lifetime #1 defined on the method body at 6:5
+  --> $DIR/static-return-lifetime-infered.rs:6:5
+   |
+LL | /     fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
+LL | |         self.x.iter().map(|a| a.0)
+LL | |     }
+   | |_____^
+help: you can add a constraint to the return type to make it last less than `'static` and match the anonymous lifetime #1 defined on the method body at 6:5
+   |
+LL |     fn iter_values_anon(&self) -> impl Iterator<Item=u32> + '_ {
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: cannot infer an appropriate lifetime
+  --> $DIR/static-return-lifetime-infered.rs:11:16
+   |
+LL |     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
+   |                                     ----------------------- this return type evaluates to the `'static` lifetime...
+LL |         self.x.iter().map(|a| a.0)
+   |         ------ ^^^^
+   |         |
+   |         ...but this borrow...
+   |
+note: ...can't outlive the lifetime 'a as defined on the method body at 10:20
+  --> $DIR/static-return-lifetime-infered.rs:10:20
+   |
+LL |     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
+   |                    ^^
+help: you can add a constraint to the return type to make it last less than `'static` and match the lifetime 'a as defined on the method body at 10:20
+   |
+LL |     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> + 'a {
+   |                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/impl-trait/trait_type.rs b/src/test/ui/impl-trait/trait_type.rs
new file mode 100644
index 0000000..638fefc
--- /dev/null
+++ b/src/test/ui/impl-trait/trait_type.rs
@@ -0,0 +1,24 @@
+struct MyType;
+struct MyType2;
+struct MyType3;
+struct MyType4;
+
+impl std::fmt::Display for MyType {
+   fn fmt(&self, x: &str) -> () { }
+   //~^ ERROR method `fmt` has an incompatible type
+}
+
+impl std::fmt::Display for MyType2 {
+   fn fmt(&self) -> () { }
+   //~^ ERROR method `fmt` has 1 parameter
+}
+
+impl std::fmt::Display for MyType3 {
+   fn fmt() -> () { }
+   //~^ ERROR method `fmt` has a `&self` declaration in the trait
+}
+
+impl std::fmt::Display for MyType4 {}
+//~^ ERROR not all trait items
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/trait_type.stderr b/src/test/ui/impl-trait/trait_type.stderr
new file mode 100644
index 0000000..a1f6b73
--- /dev/null
+++ b/src/test/ui/impl-trait/trait_type.stderr
@@ -0,0 +1,37 @@
+error[E0053]: method `fmt` has an incompatible type for trait
+  --> $DIR/trait_type.rs:7:4
+   |
+LL |    fn fmt(&self, x: &str) -> () { }
+   |    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ in mutability
+   |
+   = note: expected type `fn(&MyType, &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error>`
+              found type `fn(&MyType, &str)`
+
+error[E0050]: method `fmt` has 1 parameter but the declaration in trait `std::fmt::Display::fmt` has 2
+  --> $DIR/trait_type.rs:12:11
+   |
+LL |    fn fmt(&self) -> () { }
+   |           ^^^^^ expected 2 parameters, found 1
+   |
+   = note: `fmt` from trait: `fn(&Self, &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error>`
+
+error[E0186]: method `fmt` has a `&self` declaration in the trait, but not in the impl
+  --> $DIR/trait_type.rs:17:4
+   |
+LL |    fn fmt() -> () { }
+   |    ^^^^^^^^^^^^^^ expected `&self` in impl
+   |
+   = note: `fmt` from trait: `fn(&Self, &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error>`
+
+error[E0046]: not all trait items implemented, missing: `fmt`
+  --> $DIR/trait_type.rs:21:1
+   |
+LL | impl std::fmt::Display for MyType4 {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `fmt` in implementation
+   |
+   = note: `fmt` from trait: `fn(&Self, &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error>`
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0046, E0050, E0053, E0186.
+For more information about an error, try `rustc --explain E0046`.
diff --git a/src/test/ui/impl-trait/type_parameters_captured.rs b/src/test/ui/impl-trait/type_parameters_captured.rs
new file mode 100644
index 0000000..6c9c9d4
--- /dev/null
+++ b/src/test/ui/impl-trait/type_parameters_captured.rs
@@ -0,0 +1,12 @@
+use std::fmt::Debug;
+
+trait Any {}
+impl<T> Any for T {}
+
+// Check that type parameters are captured and not considered 'static
+fn foo<T>(x: T) -> impl Any + 'static {
+    //~^ ERROR the parameter type `T` may not live long enough
+    x
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/type_parameters_captured.stderr b/src/test/ui/impl-trait/type_parameters_captured.stderr
new file mode 100644
index 0000000..708b479
--- /dev/null
+++ b/src/test/ui/impl-trait/type_parameters_captured.stderr
@@ -0,0 +1,17 @@
+error[E0310]: the parameter type `T` may not live long enough
+  --> $DIR/type_parameters_captured.rs:7:20
+   |
+LL | fn foo<T>(x: T) -> impl Any + 'static {
+   |        -           ^^^^^^^^^^^^^^^^^^
+   |        |
+   |        help: consider adding an explicit lifetime bound `T: 'static`...
+   |
+note: ...so that the type `T` will meet its required lifetime bounds
+  --> $DIR/type_parameters_captured.rs:7:20
+   |
+LL | fn foo<T>(x: T) -> impl Any + 'static {
+   |                    ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0310`.
diff --git a/src/test/ui/impl-trait/universal-issue-48703.rs b/src/test/ui/impl-trait/universal-issue-48703.rs
new file mode 100644
index 0000000..e434e10
--- /dev/null
+++ b/src/test/ui/impl-trait/universal-issue-48703.rs
@@ -0,0 +1,9 @@
+#![feature(universal_impl_trait)]
+
+use std::fmt::Debug;
+
+fn foo<T>(x: impl Debug) { }
+
+fn main() {
+    foo::<String>('a'); //~ ERROR cannot provide explicit type parameters
+}
diff --git a/src/test/ui/impl-trait/universal-issue-48703.stderr b/src/test/ui/impl-trait/universal-issue-48703.stderr
new file mode 100644
index 0000000..26ed8db
--- /dev/null
+++ b/src/test/ui/impl-trait/universal-issue-48703.stderr
@@ -0,0 +1,9 @@
+error[E0632]: cannot provide explicit type parameters when `impl Trait` is used in argument position.
+  --> $DIR/universal-issue-48703.rs:8:5
+   |
+LL |     foo::<String>('a');
+   |     ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0632`.
diff --git a/src/test/ui/impl-trait/universal-mismatched-type.rs b/src/test/ui/impl-trait/universal-mismatched-type.rs
new file mode 100644
index 0000000..e9129bb
--- /dev/null
+++ b/src/test/ui/impl-trait/universal-mismatched-type.rs
@@ -0,0 +1,7 @@
+use std::fmt::Debug;
+
+fn foo(x: impl Debug) -> String {
+    x //~ ERROR mismatched types
+}
+
+fn main() { }
diff --git a/src/test/ui/impl-trait/universal-mismatched-type.stderr b/src/test/ui/impl-trait/universal-mismatched-type.stderr
new file mode 100644
index 0000000..d223b96
--- /dev/null
+++ b/src/test/ui/impl-trait/universal-mismatched-type.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/universal-mismatched-type.rs:4:5
+   |
+LL | fn foo(x: impl Debug) -> String {
+   |                          ------ expected `std::string::String` because of return type
+LL |     x
+   |     ^ expected struct `std::string::String`, found type parameter
+   |
+   = note: expected type `std::string::String`
+              found type `impl Debug`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/impl-trait/universal-turbofish-in-method-issue-50950.rs b/src/test/ui/impl-trait/universal-turbofish-in-method-issue-50950.rs
new file mode 100644
index 0000000..d3d5616
--- /dev/null
+++ b/src/test/ui/impl-trait/universal-turbofish-in-method-issue-50950.rs
@@ -0,0 +1,17 @@
+use std::any::Any;
+pub struct EventHandler {
+}
+
+impl EventHandler
+{
+    pub fn handle_event<T: Any>(&mut self, _efunc: impl FnMut(T)) {}
+}
+
+struct TestEvent(i32);
+
+fn main() {
+    let mut evt = EventHandler {};
+    evt.handle_event::<TestEvent, fn(TestEvent)>(|_evt| {
+        //~^ ERROR cannot provide explicit type parameters
+    });
+}
diff --git a/src/test/ui/impl-trait/universal-turbofish-in-method-issue-50950.stderr b/src/test/ui/impl-trait/universal-turbofish-in-method-issue-50950.stderr
new file mode 100644
index 0000000..b7fc4d1
--- /dev/null
+++ b/src/test/ui/impl-trait/universal-turbofish-in-method-issue-50950.stderr
@@ -0,0 +1,9 @@
+error[E0632]: cannot provide explicit type parameters when `impl Trait` is used in argument position.
+  --> $DIR/universal-turbofish-in-method-issue-50950.rs:14:9
+   |
+LL |     evt.handle_event::<TestEvent, fn(TestEvent)>(|_evt| {
+   |         ^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0632`.
diff --git a/src/test/ui/impl-trait/universal-two-impl-traits.rs b/src/test/ui/impl-trait/universal-two-impl-traits.rs
new file mode 100644
index 0000000..1ed47d8
--- /dev/null
+++ b/src/test/ui/impl-trait/universal-two-impl-traits.rs
@@ -0,0 +1,9 @@
+use std::fmt::Debug;
+
+fn foo(x: impl Debug, y: impl Debug) -> String {
+    let mut a = x;
+    a = y; //~ ERROR mismatched
+    format!("{:?}", a)
+}
+
+fn main() { }
diff --git a/src/test/ui/impl-trait/universal-two-impl-traits.stderr b/src/test/ui/impl-trait/universal-two-impl-traits.stderr
new file mode 100644
index 0000000..145d6a8
--- /dev/null
+++ b/src/test/ui/impl-trait/universal-two-impl-traits.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/universal-two-impl-traits.rs:5:9
+   |
+LL |     a = y;
+   |         ^ expected type parameter, found a different type parameter
+   |
+   = note: expected type `impl Debug` (type parameter)
+              found type `impl Debug` (type parameter)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/impl-trait/universal_wrong_bounds.rs b/src/test/ui/impl-trait/universal_wrong_bounds.rs
new file mode 100644
index 0000000..56a13ea
--- /dev/null
+++ b/src/test/ui/impl-trait/universal_wrong_bounds.rs
@@ -0,0 +1,14 @@
+use std::fmt::Display;
+
+fn foo(f: impl Display + Clone) -> String {
+    wants_debug(f);
+    wants_display(f);
+    wants_clone(f);
+}
+
+fn wants_debug(g: impl Debug) { } //~ ERROR cannot find
+fn wants_display(g: impl Debug) { } //~ ERROR cannot find
+fn wants_clone(g: impl Clone) { }
+
+fn main() {
+}
diff --git a/src/test/ui/impl-trait/universal_wrong_bounds.stderr b/src/test/ui/impl-trait/universal_wrong_bounds.stderr
new file mode 100644
index 0000000..1fd3ebf
--- /dev/null
+++ b/src/test/ui/impl-trait/universal_wrong_bounds.stderr
@@ -0,0 +1,23 @@
+error[E0405]: cannot find trait `Debug` in this scope
+  --> $DIR/universal_wrong_bounds.rs:9:24
+   |
+LL | fn wants_debug(g: impl Debug) { }
+   |                        ^^^^^ not found in this scope
+help: possible candidate is found in another module, you can import it into scope
+   |
+LL | use std::fmt::Debug;
+   |
+
+error[E0405]: cannot find trait `Debug` in this scope
+  --> $DIR/universal_wrong_bounds.rs:10:26
+   |
+LL | fn wants_display(g: impl Debug) { }
+   |                          ^^^^^ not found in this scope
+help: possible candidate is found in another module, you can import it into scope
+   |
+LL | use std::fmt::Debug;
+   |
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0405`.
diff --git a/src/test/ui/impl-trait/where-allowed.rs b/src/test/ui/impl-trait/where-allowed.rs
new file mode 100644
index 0000000..31bc9f4
--- /dev/null
+++ b/src/test/ui/impl-trait/where-allowed.rs
@@ -0,0 +1,224 @@
+//! A simple test for testing many permutations of allowedness of
+//! impl Trait
+use std::fmt::Debug;
+
+// Allowed
+fn in_parameters(_: impl Debug) { panic!() }
+
+// Allowed
+fn in_return() -> impl Debug { panic!() }
+
+// Allowed
+fn in_adt_in_parameters(_: Vec<impl Debug>) { panic!() }
+
+// Allowed
+fn in_adt_in_return() -> Vec<impl Debug> { panic!() }
+
+// Disallowed
+fn in_fn_parameter_in_parameters(_: fn(impl Debug)) { panic!() }
+//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+
+// Disallowed
+fn in_fn_return_in_parameters(_: fn() -> impl Debug) { panic!() }
+//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+
+// Disallowed
+fn in_fn_parameter_in_return() -> fn(impl Debug) { panic!() }
+//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+
+// Disallowed
+fn in_fn_return_in_return() -> fn() -> impl Debug { panic!() }
+//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+
+// Disallowed
+fn in_dyn_Fn_parameter_in_parameters(_: &dyn Fn(impl Debug)) { panic!() }
+//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+
+// Disallowed
+fn in_dyn_Fn_return_in_parameters(_: &dyn Fn() -> impl Debug) { panic!() }
+//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+
+// Disallowed
+fn in_dyn_Fn_parameter_in_return() -> &'static dyn Fn(impl Debug) { panic!() }
+//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+
+// Disallowed
+fn in_dyn_Fn_return_in_return() -> &'static dyn Fn() -> impl Debug { panic!() }
+//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+
+// Disallowed
+fn in_impl_Fn_parameter_in_parameters(_: &impl Fn(impl Debug)) { panic!() }
+//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+//~^^ ERROR nested `impl Trait` is not allowed
+
+// Disallowed
+fn in_impl_Fn_return_in_parameters(_: &impl Fn() -> impl Debug) { panic!() }
+//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+
+// Disallowed
+fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic!() }
+//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+//~^^ ERROR nested `impl Trait` is not allowed
+
+// Disallowed
+fn in_impl_Fn_return_in_return() -> &'static impl Fn() -> impl Debug { panic!() }
+//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+
+// Disallowed
+fn in_Fn_parameter_in_generics<F: Fn(impl Debug)> (_: F) { panic!() }
+//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+
+// Disallowed
+fn in_Fn_return_in_generics<F: Fn() -> impl Debug> (_: F) { panic!() }
+//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+
+
+// Allowed
+fn in_impl_Trait_in_parameters(_: impl Iterator<Item = impl Iterator>) { panic!() }
+
+// Allowed
+fn in_impl_Trait_in_return() -> impl IntoIterator<Item = impl IntoIterator> {
+    vec![vec![0; 10], vec![12; 7], vec![8; 3]]
+}
+
+// Disallowed
+struct InBraceStructField { x: impl Debug }
+//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+
+// Disallowed
+struct InAdtInBraceStructField { x: Vec<impl Debug> }
+//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+
+// Disallowed
+struct InTupleStructField(impl Debug);
+//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+
+// Disallowed
+enum InEnum {
+    InBraceVariant { x: impl Debug },
+    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+    InTupleVariant(impl Debug),
+    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+}
+
+// Allowed
+trait InTraitDefnParameters {
+    fn in_parameters(_: impl Debug);
+}
+
+// Disallowed
+trait InTraitDefnReturn {
+    fn in_return() -> impl Debug;
+    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+}
+
+// Allowed and disallowed in trait impls
+trait DummyTrait {
+    type Out;
+    fn in_trait_impl_parameter(_: impl Debug);
+    fn in_trait_impl_return() -> Self::Out;
+}
+impl DummyTrait for () {
+    type Out = impl Debug;
+    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+
+    fn in_trait_impl_parameter(_: impl Debug) { }
+    // Allowed
+
+    fn in_trait_impl_return() -> impl Debug { () }
+    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+}
+
+// Allowed
+struct DummyType;
+impl DummyType {
+    fn in_inherent_impl_parameters(_: impl Debug) { }
+    fn in_inherent_impl_return() -> impl Debug { () }
+}
+
+// Disallowed
+extern "C" {
+    fn in_foreign_parameters(_: impl Debug);
+    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+
+    fn in_foreign_return() -> impl Debug;
+    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+}
+
+// Allowed
+extern "C" fn in_extern_fn_parameters(_: impl Debug) {
+}
+
+// Allowed
+extern "C" fn in_extern_fn_return() -> impl Debug {
+    22
+}
+
+type InTypeAlias<R> = impl Debug;
+//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+
+type InReturnInTypeAlias<R> = fn() -> impl Debug;
+//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+
+// Disallowed in impl headers
+impl PartialEq<impl Debug> for () {
+    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+}
+
+// Disallowed in impl headers
+impl PartialEq<()> for impl Debug {
+    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+}
+
+// Disallowed in inherent impls
+impl impl Debug {
+    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+}
+
+// Disallowed in inherent impls
+struct InInherentImplAdt<T> { t: T }
+impl InInherentImplAdt<impl Debug> {
+    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+}
+
+// Disallowed in where clauses
+fn in_fn_where_clause()
+    where impl Debug: Debug
+//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+{
+}
+
+// Disallowed in where clauses
+fn in_adt_in_fn_where_clause()
+    where Vec<impl Debug>: Debug
+//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+{
+}
+
+// Disallowed
+fn in_trait_parameter_in_fn_where_clause<T>()
+    where T: PartialEq<impl Debug>
+//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+{
+}
+
+// Disallowed
+fn in_Fn_parameter_in_fn_where_clause<T>()
+    where T: Fn(impl Debug)
+//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+{
+}
+
+// Disallowed
+fn in_Fn_return_in_fn_where_clause<T>()
+    where T: Fn() -> impl Debug
+//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+{
+}
+
+fn main() {
+    let _in_local_variable: impl Fn() = || {};
+    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+    let _in_return_in_local_variable = || -> impl Fn() { || {} };
+    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+}
diff --git a/src/test/ui/impl-trait/where-allowed.stderr b/src/test/ui/impl-trait/where-allowed.stderr
new file mode 100644
index 0000000..7218e82
--- /dev/null
+++ b/src/test/ui/impl-trait/where-allowed.stderr
@@ -0,0 +1,246 @@
+error[E0666]: nested `impl Trait` is not allowed
+  --> $DIR/where-allowed.rs:50:51
+   |
+LL | fn in_impl_Fn_parameter_in_parameters(_: &impl Fn(impl Debug)) { panic!() }
+   |                                           --------^^^^^^^^^^-
+   |                                           |       |
+   |                                           |       nested `impl Trait` here
+   |                                           outer `impl Trait`
+
+error[E0666]: nested `impl Trait` is not allowed
+  --> $DIR/where-allowed.rs:59:57
+   |
+LL | fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic!() }
+   |                                                 --------^^^^^^^^^^-
+   |                                                 |       |
+   |                                                 |       nested `impl Trait` here
+   |                                                 outer `impl Trait`
+
+error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+  --> $DIR/where-allowed.rs:18:40
+   |
+LL | fn in_fn_parameter_in_parameters(_: fn(impl Debug)) { panic!() }
+   |                                        ^^^^^^^^^^
+
+error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+  --> $DIR/where-allowed.rs:22:42
+   |
+LL | fn in_fn_return_in_parameters(_: fn() -> impl Debug) { panic!() }
+   |                                          ^^^^^^^^^^
+
+error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+  --> $DIR/where-allowed.rs:26:38
+   |
+LL | fn in_fn_parameter_in_return() -> fn(impl Debug) { panic!() }
+   |                                      ^^^^^^^^^^
+
+error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+  --> $DIR/where-allowed.rs:30:40
+   |
+LL | fn in_fn_return_in_return() -> fn() -> impl Debug { panic!() }
+   |                                        ^^^^^^^^^^
+
+error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+  --> $DIR/where-allowed.rs:34:49
+   |
+LL | fn in_dyn_Fn_parameter_in_parameters(_: &dyn Fn(impl Debug)) { panic!() }
+   |                                                 ^^^^^^^^^^
+
+error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+  --> $DIR/where-allowed.rs:38:51
+   |
+LL | fn in_dyn_Fn_return_in_parameters(_: &dyn Fn() -> impl Debug) { panic!() }
+   |                                                   ^^^^^^^^^^
+
+error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+  --> $DIR/where-allowed.rs:42:55
+   |
+LL | fn in_dyn_Fn_parameter_in_return() -> &'static dyn Fn(impl Debug) { panic!() }
+   |                                                       ^^^^^^^^^^
+
+error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+  --> $DIR/where-allowed.rs:46:57
+   |
+LL | fn in_dyn_Fn_return_in_return() -> &'static dyn Fn() -> impl Debug { panic!() }
+   |                                                         ^^^^^^^^^^
+
+error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+  --> $DIR/where-allowed.rs:50:51
+   |
+LL | fn in_impl_Fn_parameter_in_parameters(_: &impl Fn(impl Debug)) { panic!() }
+   |                                                   ^^^^^^^^^^
+
+error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+  --> $DIR/where-allowed.rs:55:53
+   |
+LL | fn in_impl_Fn_return_in_parameters(_: &impl Fn() -> impl Debug) { panic!() }
+   |                                                     ^^^^^^^^^^
+
+error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+  --> $DIR/where-allowed.rs:59:57
+   |
+LL | fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic!() }
+   |                                                         ^^^^^^^^^^
+
+error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+  --> $DIR/where-allowed.rs:64:59
+   |
+LL | fn in_impl_Fn_return_in_return() -> &'static impl Fn() -> impl Debug { panic!() }
+   |                                                           ^^^^^^^^^^
+
+error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+  --> $DIR/where-allowed.rs:68:38
+   |
+LL | fn in_Fn_parameter_in_generics<F: Fn(impl Debug)> (_: F) { panic!() }
+   |                                      ^^^^^^^^^^
+
+error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+  --> $DIR/where-allowed.rs:72:40
+   |
+LL | fn in_Fn_return_in_generics<F: Fn() -> impl Debug> (_: F) { panic!() }
+   |                                        ^^^^^^^^^^
+
+error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+  --> $DIR/where-allowed.rs:85:32
+   |
+LL | struct InBraceStructField { x: impl Debug }
+   |                                ^^^^^^^^^^
+
+error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+  --> $DIR/where-allowed.rs:89:41
+   |
+LL | struct InAdtInBraceStructField { x: Vec<impl Debug> }
+   |                                         ^^^^^^^^^^
+
+error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+  --> $DIR/where-allowed.rs:93:27
+   |
+LL | struct InTupleStructField(impl Debug);
+   |                           ^^^^^^^^^^
+
+error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+  --> $DIR/where-allowed.rs:98:25
+   |
+LL |     InBraceVariant { x: impl Debug },
+   |                         ^^^^^^^^^^
+
+error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+  --> $DIR/where-allowed.rs:100:20
+   |
+LL |     InTupleVariant(impl Debug),
+   |                    ^^^^^^^^^^
+
+error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+  --> $DIR/where-allowed.rs:111:23
+   |
+LL |     fn in_return() -> impl Debug;
+   |                       ^^^^^^^^^^
+
+error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+  --> $DIR/where-allowed.rs:122:16
+   |
+LL |     type Out = impl Debug;
+   |                ^^^^^^^^^^
+
+error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+  --> $DIR/where-allowed.rs:128:34
+   |
+LL |     fn in_trait_impl_return() -> impl Debug { () }
+   |                                  ^^^^^^^^^^
+
+error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+  --> $DIR/where-allowed.rs:141:33
+   |
+LL |     fn in_foreign_parameters(_: impl Debug);
+   |                                 ^^^^^^^^^^
+
+error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+  --> $DIR/where-allowed.rs:144:31
+   |
+LL |     fn in_foreign_return() -> impl Debug;
+   |                               ^^^^^^^^^^
+
+error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+  --> $DIR/where-allowed.rs:157:23
+   |
+LL | type InTypeAlias<R> = impl Debug;
+   |                       ^^^^^^^^^^
+
+error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+  --> $DIR/where-allowed.rs:160:39
+   |
+LL | type InReturnInTypeAlias<R> = fn() -> impl Debug;
+   |                                       ^^^^^^^^^^
+
+error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+  --> $DIR/where-allowed.rs:164:16
+   |
+LL | impl PartialEq<impl Debug> for () {
+   |                ^^^^^^^^^^
+
+error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+  --> $DIR/where-allowed.rs:169:24
+   |
+LL | impl PartialEq<()> for impl Debug {
+   |                        ^^^^^^^^^^
+
+error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+  --> $DIR/where-allowed.rs:174:6
+   |
+LL | impl impl Debug {
+   |      ^^^^^^^^^^
+
+error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+  --> $DIR/where-allowed.rs:180:24
+   |
+LL | impl InInherentImplAdt<impl Debug> {
+   |                        ^^^^^^^^^^
+
+error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+  --> $DIR/where-allowed.rs:186:11
+   |
+LL |     where impl Debug: Debug
+   |           ^^^^^^^^^^
+
+error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+  --> $DIR/where-allowed.rs:193:15
+   |
+LL |     where Vec<impl Debug>: Debug
+   |               ^^^^^^^^^^
+
+error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+  --> $DIR/where-allowed.rs:200:24
+   |
+LL |     where T: PartialEq<impl Debug>
+   |                        ^^^^^^^^^^
+
+error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+  --> $DIR/where-allowed.rs:207:17
+   |
+LL |     where T: Fn(impl Debug)
+   |                 ^^^^^^^^^^
+
+error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+  --> $DIR/where-allowed.rs:214:22
+   |
+LL |     where T: Fn() -> impl Debug
+   |                      ^^^^^^^^^^
+
+error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+  --> $DIR/where-allowed.rs:220:29
+   |
+LL |     let _in_local_variable: impl Fn() = || {};
+   |                             ^^^^^^^^^
+   |
+   = help: add #![feature(impl_trait_in_bindings)] to the crate attributes to enable
+
+error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+  --> $DIR/where-allowed.rs:222:46
+   |
+LL |     let _in_return_in_local_variable = || -> impl Fn() { || {} };
+   |                                              ^^^^^^^^^
+
+error: aborting due to 39 previous errors
+
+Some errors occurred: E0562, E0666.
+For more information about an error, try `rustc --explain E0562`.
diff --git a/src/test/ui/impl-unused-rps-in-assoc-type.rs b/src/test/ui/impl-unused-rps-in-assoc-type.rs
new file mode 100644
index 0000000..ea41997
--- /dev/null
+++ b/src/test/ui/impl-unused-rps-in-assoc-type.rs
@@ -0,0 +1,18 @@
+// Test that lifetime parameters must be constrained if they appear in
+// an associated type def'n. Issue #22077.
+
+trait Fun {
+    type Output;
+    fn call<'x>(&'x self) -> Self::Output;
+}
+
+struct Holder { x: String }
+
+impl<'a> Fun for Holder { //~ ERROR E0207
+    type Output = &'a str;
+    fn call<'b>(&'b self) -> &'b str {
+        &self.x[..]
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/impl-unused-rps-in-assoc-type.stderr b/src/test/ui/impl-unused-rps-in-assoc-type.stderr
new file mode 100644
index 0000000..c7ad1b4
--- /dev/null
+++ b/src/test/ui/impl-unused-rps-in-assoc-type.stderr
@@ -0,0 +1,9 @@
+error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates
+  --> $DIR/impl-unused-rps-in-assoc-type.rs:11:6
+   |
+LL | impl<'a> Fun for Holder {
+   |      ^^ unconstrained lifetime parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0207`.
diff --git a/src/test/ui/impl-unused-tps-inherent.rs b/src/test/ui/impl-unused-tps-inherent.rs
new file mode 100644
index 0000000..83a228e
--- /dev/null
+++ b/src/test/ui/impl-unused-tps-inherent.rs
@@ -0,0 +1,25 @@
+struct MyType;
+
+struct MyType1<T>(T);
+
+trait Bar {
+    type Out;
+}
+
+impl<T> MyType {
+    //~^ ERROR  the type parameter `T` is not constrained
+}
+
+impl<T> MyType1<T> {
+    // OK, T is used in `Foo<T>`.
+}
+
+impl<T,U> MyType1<T> {
+    //~^ ERROR  the type parameter `U` is not constrained
+}
+
+impl<T,U> MyType1<T> where T: Bar<Out=U> {
+    // OK, T is used in `Foo<T>`.
+}
+
+fn main() { }
diff --git a/src/test/ui/impl-unused-tps-inherent.stderr b/src/test/ui/impl-unused-tps-inherent.stderr
new file mode 100644
index 0000000..43f63cf
--- /dev/null
+++ b/src/test/ui/impl-unused-tps-inherent.stderr
@@ -0,0 +1,15 @@
+error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates
+  --> $DIR/impl-unused-tps-inherent.rs:9:6
+   |
+LL | impl<T> MyType {
+   |      ^ unconstrained type parameter
+
+error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates
+  --> $DIR/impl-unused-tps-inherent.rs:17:8
+   |
+LL | impl<T,U> MyType1<T> {
+   |        ^ unconstrained type parameter
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0207`.
diff --git a/src/test/ui/impl-unused-tps.rs b/src/test/ui/impl-unused-tps.rs
new file mode 100644
index 0000000..7cc1ae6
--- /dev/null
+++ b/src/test/ui/impl-unused-tps.rs
@@ -0,0 +1,62 @@
+trait Foo<A> {
+    fn get(&self, A: &A) { }
+}
+
+trait Bar {
+    type Out;
+}
+
+impl<T> Foo<T> for [isize;0] {
+    // OK, T is used in `Foo<T>`.
+}
+
+impl<T,U> Foo<T> for [isize;1] {
+    //~^ ERROR the type parameter `U` is not constrained
+}
+
+impl<T,U> Foo<T> for [isize;2] where T : Bar<Out=U> {
+    // OK, `U` is now constrained by the output type parameter.
+}
+
+impl<T:Bar<Out=U>,U> Foo<T> for [isize;3] {
+    // OK, same as above but written differently.
+}
+
+impl<T,U> Foo<T> for U {
+    // OK, T, U are used everywhere. Note that the coherence check
+    // hasn't executed yet, so no errors about overlap.
+}
+
+impl<T,U> Bar for T {
+    //~^ ERROR the type parameter `U` is not constrained
+
+    type Out = U;
+
+    // Using `U` in an associated type within the impl is not good enough!
+}
+
+impl<T,U> Bar for T
+    where T : Bar<Out=U>
+{
+    //~^^^ ERROR the type parameter `U` is not constrained
+
+    // This crafty self-referential attempt is still no good.
+}
+
+impl<T,U,V> Foo<T> for T
+    where (T,U): Bar<Out=V>
+{
+    //~^^^ ERROR the type parameter `U` is not constrained
+    //~|   ERROR the type parameter `V` is not constrained
+
+    // Here, `V` is bound by an output type parameter, but the inputs
+    // are not themselves constrained.
+}
+
+impl<T,U,V> Foo<(T,U)> for T
+    where (T,U): Bar<Out=V>
+{
+    // As above, but both T and U ARE constrained.
+}
+
+fn main() { }
diff --git a/src/test/ui/impl-unused-tps.stderr b/src/test/ui/impl-unused-tps.stderr
new file mode 100644
index 0000000..053ab91
--- /dev/null
+++ b/src/test/ui/impl-unused-tps.stderr
@@ -0,0 +1,33 @@
+error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates
+  --> $DIR/impl-unused-tps.rs:13:8
+   |
+LL | impl<T,U> Foo<T> for [isize;1] {
+   |        ^ unconstrained type parameter
+
+error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates
+  --> $DIR/impl-unused-tps.rs:30:8
+   |
+LL | impl<T,U> Bar for T {
+   |        ^ unconstrained type parameter
+
+error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates
+  --> $DIR/impl-unused-tps.rs:38:8
+   |
+LL | impl<T,U> Bar for T
+   |        ^ unconstrained type parameter
+
+error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates
+  --> $DIR/impl-unused-tps.rs:46:8
+   |
+LL | impl<T,U,V> Foo<T> for T
+   |        ^ unconstrained type parameter
+
+error[E0207]: the type parameter `V` is not constrained by the impl trait, self type, or predicates
+  --> $DIR/impl-unused-tps.rs:46:10
+   |
+LL | impl<T,U,V> Foo<T> for T
+   |          ^ unconstrained type parameter
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0207`.
diff --git a/src/test/ui/implicit-method-bind.rs b/src/test/ui/implicit-method-bind.rs
new file mode 100644
index 0000000..5e27516
--- /dev/null
+++ b/src/test/ui/implicit-method-bind.rs
@@ -0,0 +1,3 @@
+fn main() {
+    let _f = 10i32.abs; //~ ERROR attempted to take value of method
+}
diff --git a/src/test/ui/implicit-method-bind.stderr b/src/test/ui/implicit-method-bind.stderr
new file mode 100644
index 0000000..968272d
--- /dev/null
+++ b/src/test/ui/implicit-method-bind.stderr
@@ -0,0 +1,9 @@
+error[E0615]: attempted to take value of method `abs` on type `i32`
+  --> $DIR/implicit-method-bind.rs:2:20
+   |
+LL |     let _f = 10i32.abs;
+   |                    ^^^ help: use parentheses to call the method: `abs()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0615`.
diff --git a/src/test/ui/import.rs b/src/test/ui/import.rs
new file mode 100644
index 0000000..3170dd2
--- /dev/null
+++ b/src/test/ui/import.rs
@@ -0,0 +1,17 @@
+use zed::bar;
+use zed::baz; //~ ERROR unresolved import `zed::baz` [E0432]
+              //~| no `baz` in `zed`
+              //~| HELP a similar name exists in the module
+              //~| SUGGESTION bar
+
+
+mod zed {
+    pub fn bar() { println!("bar"); }
+    use foo; //~ ERROR unresolved import `foo` [E0432]
+             //~^ no `foo` in the root
+}
+
+fn main() {
+    zed::foo(); //~ ERROR `foo` is private
+    bar();
+}
diff --git a/src/test/ui/import.stderr b/src/test/ui/import.stderr
new file mode 100644
index 0000000..685fff2
--- /dev/null
+++ b/src/test/ui/import.stderr
@@ -0,0 +1,25 @@
+error[E0432]: unresolved import `zed::baz`
+  --> $DIR/import.rs:2:5
+   |
+LL | use zed::baz;
+   |     ^^^^^---
+   |     |    |
+   |     |    help: a similar name exists in the module: `bar`
+   |     no `baz` in `zed`
+
+error[E0432]: unresolved import `foo`
+  --> $DIR/import.rs:10:9
+   |
+LL |     use foo;
+   |         ^^^ no `foo` in the root
+
+error[E0603]: unresolved item `foo` is private
+  --> $DIR/import.rs:15:10
+   |
+LL |     zed::foo();
+   |          ^^^
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0432, E0603.
+For more information about an error, try `rustc --explain E0432`.
diff --git a/src/test/ui/import2.rs b/src/test/ui/import2.rs
new file mode 100644
index 0000000..036d6bc
--- /dev/null
+++ b/src/test/ui/import2.rs
@@ -0,0 +1,10 @@
+use baz::zed::bar; //~ ERROR unresolved import `baz::zed` [E0432]
+                   //~^ could not find `zed` in `baz`
+
+mod baz {}
+mod zed {
+    pub fn bar() { println!("bar3"); }
+}
+fn main() {
+    bar();
+}
diff --git a/src/test/ui/import2.stderr b/src/test/ui/import2.stderr
new file mode 100644
index 0000000..da88897
--- /dev/null
+++ b/src/test/ui/import2.stderr
@@ -0,0 +1,9 @@
+error[E0432]: unresolved import `baz::zed`
+  --> $DIR/import2.rs:1:10
+   |
+LL | use baz::zed::bar;
+   |          ^^^ could not find `zed` in `baz`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/import3.rs b/src/test/ui/import3.rs
new file mode 100644
index 0000000..2c6ac9a
--- /dev/null
+++ b/src/test/ui/import3.rs
@@ -0,0 +1,4 @@
+// error-pattern: unresolved
+use main::bar;
+
+fn main() { println!("foo"); }
diff --git a/src/test/ui/import3.stderr b/src/test/ui/import3.stderr
new file mode 100644
index 0000000..73b9b27
--- /dev/null
+++ b/src/test/ui/import3.stderr
@@ -0,0 +1,9 @@
+error[E0432]: unresolved import `main`
+  --> $DIR/import3.rs:2:5
+   |
+LL | use main::bar;
+   |     ^^^^ maybe a missing `extern crate main;`?
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/import4.rs b/src/test/ui/import4.rs
new file mode 100644
index 0000000..ba3b7fb
--- /dev/null
+++ b/src/test/ui/import4.rs
@@ -0,0 +1,7 @@
+// error-pattern: import
+
+
+mod a { pub use b::foo; }
+mod b { pub use a::foo; }
+
+fn main() { println!("loop"); }
diff --git a/src/test/ui/import4.stderr b/src/test/ui/import4.stderr
new file mode 100644
index 0000000..e0b478f
--- /dev/null
+++ b/src/test/ui/import4.stderr
@@ -0,0 +1,9 @@
+error[E0432]: unresolved import `a::foo`
+  --> $DIR/import4.rs:5:17
+   |
+LL | mod b { pub use a::foo; }
+   |                 ^^^^^^ no `foo` in `a`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/imports/auxiliary/gensymed.rs b/src/test/ui/imports/auxiliary/gensymed.rs
new file mode 100644
index 0000000..bbb19f5
--- /dev/null
+++ b/src/test/ui/imports/auxiliary/gensymed.rs
@@ -0,0 +1,3 @@
+// edition:2018
+
+mod std {}
diff --git a/src/test/ui/imports/auxiliary/glob-conflict.rs b/src/test/ui/imports/auxiliary/glob-conflict.rs
new file mode 100644
index 0000000..c83db64
--- /dev/null
+++ b/src/test/ui/imports/auxiliary/glob-conflict.rs
@@ -0,0 +1,13 @@
+mod m1 {
+    pub fn f() {}
+}
+mod m2 {
+    pub fn f(_: u8) {}
+}
+
+pub use m1::*;
+pub use m2::*;
+
+pub mod glob {
+    pub use *;
+}
diff --git a/src/test/ui/imports/auxiliary/import_crate_var.rs b/src/test/ui/imports/auxiliary/import_crate_var.rs
new file mode 100644
index 0000000..a273b10
--- /dev/null
+++ b/src/test/ui/imports/auxiliary/import_crate_var.rs
@@ -0,0 +1,7 @@
+pub fn f() {}
+
+#[macro_export]
+macro_rules! m { () => {
+    use $crate;
+    import_crate_var::f();
+} }
diff --git a/src/test/ui/imports/auxiliary/issue-55811.rs b/src/test/ui/imports/auxiliary/issue-55811.rs
new file mode 100644
index 0000000..877e4cd
--- /dev/null
+++ b/src/test/ui/imports/auxiliary/issue-55811.rs
@@ -0,0 +1,5 @@
+mod m {}
+
+// These two imports should not conflict when this crate is loaded from some other crate.
+use m::{};
+use m::{};
diff --git a/src/test/ui/imports/auxiliary/issue-56125.rs b/src/test/ui/imports/auxiliary/issue-56125.rs
new file mode 100644
index 0000000..8e07975
--- /dev/null
+++ b/src/test/ui/imports/auxiliary/issue-56125.rs
@@ -0,0 +1,11 @@
+pub mod issue_56125 {}
+
+pub mod last_segment {
+    pub mod issue_56125 {}
+}
+
+pub mod non_last_segment {
+    pub mod non_last_segment {
+        pub mod issue_56125 {}
+    }
+}
diff --git a/src/test/ui/imports/auxiliary/two_macros.rs b/src/test/ui/imports/auxiliary/two_macros.rs
new file mode 100644
index 0000000..92c2114
--- /dev/null
+++ b/src/test/ui/imports/auxiliary/two_macros.rs
@@ -0,0 +1,5 @@
+#[macro_export]
+macro_rules! m { ($($t:tt)*) => { $($t)* } }
+
+#[macro_export]
+macro_rules! n { ($($t:tt)*) => { $($t)* } }
diff --git a/src/test/ui/imports/duplicate.rs b/src/test/ui/imports/duplicate.rs
new file mode 100644
index 0000000..db65389
--- /dev/null
+++ b/src/test/ui/imports/duplicate.rs
@@ -0,0 +1,51 @@
+mod a {
+    pub fn foo() {}
+}
+
+mod b {
+    pub fn foo() {}
+}
+
+mod c {
+    pub use a::foo;
+}
+
+mod d {
+    use a::foo;
+    use a::foo; //~ ERROR the name `foo` is defined multiple times
+}
+
+mod e {
+    pub use a::*;
+    pub use c::*; // ok
+}
+
+mod f {
+    pub use a::*;
+    pub use b::*;
+}
+
+mod g {
+    pub use a::*;
+    pub use f::*;
+}
+
+fn main() {
+    e::foo();
+    f::foo(); //~ ERROR `foo` is ambiguous
+    g::foo();
+}
+
+mod ambiguous_module_errors {
+    pub mod m1 { pub use super::m1 as foo; pub fn bar() {} }
+    pub mod m2 { pub use super::m2 as foo; }
+
+    use self::m1::*;
+    use self::m2::*;
+
+    use self::foo::bar; //~ ERROR `foo` is ambiguous
+
+    fn f() {
+        foo::bar(); //~ ERROR `foo` is ambiguous
+    }
+}
diff --git a/src/test/ui/imports/duplicate.stderr b/src/test/ui/imports/duplicate.stderr
new file mode 100644
index 0000000..cc897b2
--- /dev/null
+++ b/src/test/ui/imports/duplicate.stderr
@@ -0,0 +1,71 @@
+error[E0252]: the name `foo` is defined multiple times
+  --> $DIR/duplicate.rs:15:9
+   |
+LL |     use a::foo;
+   |         ------ previous import of the value `foo` here
+LL |     use a::foo;
+   |         ^^^^^^ `foo` reimported here
+   |
+   = note: `foo` must be defined only once in the value namespace of this module
+
+error[E0659]: `foo` is ambiguous (glob import vs glob import in the same module)
+  --> $DIR/duplicate.rs:46:15
+   |
+LL |     use self::foo::bar;
+   |               ^^^ ambiguous name
+   |
+note: `foo` could refer to the module imported here
+  --> $DIR/duplicate.rs:43:9
+   |
+LL |     use self::m1::*;
+   |         ^^^^^^^^^^^
+   = help: consider adding an explicit import of `foo` to disambiguate
+note: `foo` could also refer to the module imported here
+  --> $DIR/duplicate.rs:44:9
+   |
+LL |     use self::m2::*;
+   |         ^^^^^^^^^^^
+   = help: consider adding an explicit import of `foo` to disambiguate
+
+error[E0659]: `foo` is ambiguous (glob import vs glob import in the same module)
+  --> $DIR/duplicate.rs:35:8
+   |
+LL |     f::foo();
+   |        ^^^ ambiguous name
+   |
+note: `foo` could refer to the function imported here
+  --> $DIR/duplicate.rs:24:13
+   |
+LL |     pub use a::*;
+   |             ^^^^
+   = help: consider adding an explicit import of `foo` to disambiguate
+note: `foo` could also refer to the function imported here
+  --> $DIR/duplicate.rs:25:13
+   |
+LL |     pub use b::*;
+   |             ^^^^
+   = help: consider adding an explicit import of `foo` to disambiguate
+
+error[E0659]: `foo` is ambiguous (glob import vs glob import in the same module)
+  --> $DIR/duplicate.rs:49:9
+   |
+LL |         foo::bar();
+   |         ^^^ ambiguous name
+   |
+note: `foo` could refer to the module imported here
+  --> $DIR/duplicate.rs:43:9
+   |
+LL |     use self::m1::*;
+   |         ^^^^^^^^^^^
+   = help: consider adding an explicit import of `foo` to disambiguate
+note: `foo` could also refer to the module imported here
+  --> $DIR/duplicate.rs:44:9
+   |
+LL |     use self::m2::*;
+   |         ^^^^^^^^^^^
+   = help: consider adding an explicit import of `foo` to disambiguate
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0252, E0659.
+For more information about an error, try `rustc --explain E0252`.
diff --git a/src/test/ui/imports/extern-crate-self/extern-crate-self-fail.rs b/src/test/ui/imports/extern-crate-self/extern-crate-self-fail.rs
new file mode 100644
index 0000000..defa0e2
--- /dev/null
+++ b/src/test/ui/imports/extern-crate-self/extern-crate-self-fail.rs
@@ -0,0 +1,6 @@
+extern crate self; //~ ERROR `extern crate self;` requires renaming
+
+#[macro_use] //~ ERROR `macro_use` is not supported on `extern crate self`
+extern crate self as foo;
+
+fn main() {}
diff --git a/src/test/ui/imports/extern-crate-self/extern-crate-self-fail.stderr b/src/test/ui/imports/extern-crate-self/extern-crate-self-fail.stderr
new file mode 100644
index 0000000..f26bb2f
--- /dev/null
+++ b/src/test/ui/imports/extern-crate-self/extern-crate-self-fail.stderr
@@ -0,0 +1,14 @@
+error: `extern crate self;` requires renaming
+  --> $DIR/extern-crate-self-fail.rs:1:1
+   |
+LL | extern crate self;
+   | ^^^^^^^^^^^^^^^^^^ help: try: `extern crate self as name;`
+
+error: `macro_use` is not supported on `extern crate self`
+  --> $DIR/extern-crate-self-fail.rs:3:1
+   |
+LL | #[macro_use]
+   | ^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/imports/extern-crate-self/extern-crate-self-macro-alias.rs b/src/test/ui/imports/extern-crate-self/extern-crate-self-macro-alias.rs
new file mode 100644
index 0000000..7968352
--- /dev/null
+++ b/src/test/ui/imports/extern-crate-self/extern-crate-self-macro-alias.rs
@@ -0,0 +1,16 @@
+// run-pass
+
+// Test that a macro can correctly expand the alias
+// in an `extern crate self as ALIAS` item.
+
+fn the_answer() -> usize { 42 }
+
+macro_rules! alias_self {
+    ($alias:ident) => { extern crate self as $alias; }
+}
+
+alias_self!(the_alias);
+
+fn main() {
+    assert_eq!(the_alias::the_answer(), 42);
+}
diff --git a/src/test/ui/imports/extern-crate-self/extern-crate-self-macro-item.rs b/src/test/ui/imports/extern-crate-self/extern-crate-self-macro-item.rs
new file mode 100644
index 0000000..9c93979
--- /dev/null
+++ b/src/test/ui/imports/extern-crate-self/extern-crate-self-macro-item.rs
@@ -0,0 +1,12 @@
+// compile-pass
+
+// Test that `extern crate self;` is accepted
+// syntactically as an item for use in a macro.
+
+macro_rules! accept_item { ($x:item) => {} }
+
+accept_item! {
+    extern crate self;
+}
+
+fn main() {}
diff --git a/src/test/ui/imports/extern-crate-self/extern-crate-self-macro-self.rs b/src/test/ui/imports/extern-crate-self/extern-crate-self-macro-self.rs
new file mode 100644
index 0000000..009a92e
--- /dev/null
+++ b/src/test/ui/imports/extern-crate-self/extern-crate-self-macro-self.rs
@@ -0,0 +1,16 @@
+// run-pass
+
+// Test that a macro can correctly expand `self` in
+// an `extern crate self as ALIAS` item.
+
+fn the_answer() -> usize { 42 }
+
+macro_rules! extern_something {
+    ($alias:ident) => { extern crate $alias as the_alias; }
+}
+
+extern_something!(self);
+
+fn main() {
+    assert_eq!(the_alias::the_answer(), 42);
+}
diff --git a/src/test/ui/imports/extern-crate-self/extern-crate-self-pass.rs b/src/test/ui/imports/extern-crate-self/extern-crate-self-pass.rs
new file mode 100644
index 0000000..6f6343a
--- /dev/null
+++ b/src/test/ui/imports/extern-crate-self/extern-crate-self-pass.rs
@@ -0,0 +1,13 @@
+// compile-pass
+
+extern crate self as foo;
+
+struct S;
+
+mod m {
+    fn check() {
+        foo::S; // OK
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/imports/extern-crate-used.rs b/src/test/ui/imports/extern-crate-used.rs
new file mode 100644
index 0000000..2d91cbc
--- /dev/null
+++ b/src/test/ui/imports/extern-crate-used.rs
@@ -0,0 +1,28 @@
+// Extern crate items are marked as used if they are used
+// through extern prelude entries introduced by them.
+
+// edition:2018
+
+#![deny(unused_extern_crates)]
+
+extern crate core as iso1; //~ ERROR `extern crate` is not idiomatic in the new edition
+extern crate core as iso2; //~ ERROR `extern crate` is not idiomatic in the new edition
+extern crate core as iso3; //~ ERROR `extern crate` is not idiomatic in the new edition
+extern crate core as iso4; //~ ERROR `extern crate` is not idiomatic in the new edition
+
+// Doesn't introduce its extern prelude entry, so it's still considered unused.
+extern crate core; //~ ERROR unused extern crate
+
+mod m {
+    use iso1::any as are_you_okay1;
+    use ::iso2::any as are_you_okay2;
+    type AreYouOkay1 = iso3::any::Any;
+    type AreYouOkay2 = ::iso4::any::Any;
+
+    use core::any as are_you_okay3;
+    use ::core::any as are_you_okay4;
+    type AreYouOkay3 = core::any::Any;
+    type AreYouOkay4 = ::core::any::Any;
+}
+
+fn main() {}
diff --git a/src/test/ui/imports/extern-crate-used.stderr b/src/test/ui/imports/extern-crate-used.stderr
new file mode 100644
index 0000000..c0783fe
--- /dev/null
+++ b/src/test/ui/imports/extern-crate-used.stderr
@@ -0,0 +1,38 @@
+error: `extern crate` is not idiomatic in the new edition
+  --> $DIR/extern-crate-used.rs:8:1
+   |
+LL | extern crate core as iso1;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `use`
+   |
+note: lint level defined here
+  --> $DIR/extern-crate-used.rs:6:9
+   |
+LL | #![deny(unused_extern_crates)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: `extern crate` is not idiomatic in the new edition
+  --> $DIR/extern-crate-used.rs:9:1
+   |
+LL | extern crate core as iso2;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `use`
+
+error: `extern crate` is not idiomatic in the new edition
+  --> $DIR/extern-crate-used.rs:10:1
+   |
+LL | extern crate core as iso3;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `use`
+
+error: `extern crate` is not idiomatic in the new edition
+  --> $DIR/extern-crate-used.rs:11:1
+   |
+LL | extern crate core as iso4;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `use`
+
+error: unused extern crate
+  --> $DIR/extern-crate-used.rs:14:1
+   |
+LL | extern crate core;
+   | ^^^^^^^^^^^^^^^^^^ help: remove it
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/ui/imports/extern-prelude-extern-crate-absolute-expanded.rs b/src/test/ui/imports/extern-prelude-extern-crate-absolute-expanded.rs
new file mode 100644
index 0000000..cf91a97
--- /dev/null
+++ b/src/test/ui/imports/extern-prelude-extern-crate-absolute-expanded.rs
@@ -0,0 +1,16 @@
+// compile-pass
+// edition:2018
+
+macro_rules! define_iso { () => {
+    extern crate std as iso;
+}}
+
+::iso::thread_local! {
+    static S: u8 = 0;
+}
+
+define_iso!();
+
+fn main() {
+    let s = S;
+}
diff --git a/src/test/ui/imports/extern-prelude-extern-crate-cfg.rs b/src/test/ui/imports/extern-prelude-extern-crate-cfg.rs
new file mode 100644
index 0000000..6117e5f
--- /dev/null
+++ b/src/test/ui/imports/extern-prelude-extern-crate-cfg.rs
@@ -0,0 +1,16 @@
+// compile-pass
+// compile-flags:--cfg my_feature
+
+#![no_std]
+
+#[cfg(my_feature)]
+extern crate std;
+
+mod m {
+    #[cfg(my_feature)]
+    fn conditional() {
+        std::vec::Vec::<u8>::new(); // OK
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/imports/extern-prelude-extern-crate-fail.rs b/src/test/ui/imports/extern-prelude-extern-crate-fail.rs
new file mode 100644
index 0000000..6b70efe
--- /dev/null
+++ b/src/test/ui/imports/extern-prelude-extern-crate-fail.rs
@@ -0,0 +1,22 @@
+// aux-build:two_macros.rs
+// compile-flags:--extern non_existent
+
+mod n {
+    extern crate two_macros;
+}
+
+mod m {
+    fn check() {
+        two_macros::m!(); //~ ERROR failed to resolve: use of undeclared type or module `two_macros`
+    }
+}
+
+macro_rules! define_std_as_non_existent {
+    () => {
+        extern crate std as non_existent;
+        //~^ ERROR `extern crate` items cannot shadow names passed with `--extern`
+    }
+}
+define_std_as_non_existent!();
+
+fn main() {}
diff --git a/src/test/ui/imports/extern-prelude-extern-crate-fail.stderr b/src/test/ui/imports/extern-prelude-extern-crate-fail.stderr
new file mode 100644
index 0000000..e067432
--- /dev/null
+++ b/src/test/ui/imports/extern-prelude-extern-crate-fail.stderr
@@ -0,0 +1,18 @@
+error: macro-expanded `extern crate` items cannot shadow names passed with `--extern`
+  --> $DIR/extern-prelude-extern-crate-fail.rs:16:9
+   |
+LL |         extern crate std as non_existent;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | define_std_as_non_existent!();
+   | ------------------------------ in this macro invocation
+
+error[E0433]: failed to resolve: use of undeclared type or module `two_macros`
+  --> $DIR/extern-prelude-extern-crate-fail.rs:10:9
+   |
+LL |         two_macros::m!();
+   |         ^^^^^^^^^^ use of undeclared type or module `two_macros`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/imports/extern-prelude-extern-crate-pass.rs b/src/test/ui/imports/extern-prelude-extern-crate-pass.rs
new file mode 100644
index 0000000..bb4cf6c
--- /dev/null
+++ b/src/test/ui/imports/extern-prelude-extern-crate-pass.rs
@@ -0,0 +1,12 @@
+// compile-pass
+// aux-build:two_macros.rs
+
+extern crate two_macros;
+
+mod m {
+    fn check() {
+        two_macros::m!(); // OK
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/imports/extern-prelude-extern-crate-restricted-shadowing.rs b/src/test/ui/imports/extern-prelude-extern-crate-restricted-shadowing.rs
new file mode 100644
index 0000000..6ff3ab7
--- /dev/null
+++ b/src/test/ui/imports/extern-prelude-extern-crate-restricted-shadowing.rs
@@ -0,0 +1,26 @@
+// aux-build:two_macros.rs
+
+macro_rules! define_vec {
+    () => {
+        extern crate std as Vec;
+    }
+}
+
+define_vec!();
+
+mod m {
+    fn check() {
+        Vec::panic!(); //~ ERROR `Vec` is ambiguous
+    }
+}
+
+macro_rules! define_other_core {
+    () => {
+        extern crate std as core;
+        //~^ ERROR macro-expanded `extern crate` items cannot shadow names passed with `--extern`
+    }
+}
+
+define_other_core!();
+
+fn main() {}
diff --git a/src/test/ui/imports/extern-prelude-extern-crate-restricted-shadowing.stderr b/src/test/ui/imports/extern-prelude-extern-crate-restricted-shadowing.stderr
new file mode 100644
index 0000000..24b1b58
--- /dev/null
+++ b/src/test/ui/imports/extern-prelude-extern-crate-restricted-shadowing.stderr
@@ -0,0 +1,28 @@
+error: macro-expanded `extern crate` items cannot shadow names passed with `--extern`
+  --> $DIR/extern-prelude-extern-crate-restricted-shadowing.rs:19:9
+   |
+LL |         extern crate std as core;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | define_other_core!();
+   | --------------------- in this macro invocation
+
+error[E0659]: `Vec` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
+  --> $DIR/extern-prelude-extern-crate-restricted-shadowing.rs:13:9
+   |
+LL |         Vec::panic!();
+   |         ^^^ ambiguous name
+   |
+   = note: `Vec` could refer to a struct from prelude
+note: `Vec` could also refer to the extern crate imported here
+  --> $DIR/extern-prelude-extern-crate-restricted-shadowing.rs:5:9
+   |
+LL |         extern crate std as Vec;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | define_vec!();
+   | -------------- in this macro invocation
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0659`.
diff --git a/src/test/ui/imports/extern-prelude-extern-crate-shadowing.rs b/src/test/ui/imports/extern-prelude-extern-crate-shadowing.rs
new file mode 100644
index 0000000..c5adeaf
--- /dev/null
+++ b/src/test/ui/imports/extern-prelude-extern-crate-shadowing.rs
@@ -0,0 +1,12 @@
+// compile-pass
+// aux-build:two_macros.rs
+
+extern crate two_macros as core;
+
+mod m {
+    fn check() {
+        core::m!(); // OK
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/imports/gensymed.rs b/src/test/ui/imports/gensymed.rs
new file mode 100644
index 0000000..3174410
--- /dev/null
+++ b/src/test/ui/imports/gensymed.rs
@@ -0,0 +1,7 @@
+// compile-pass
+// edition:2018
+// aux-build:gensymed.rs
+
+extern crate gensymed;
+
+fn main() {}
diff --git a/src/test/ui/imports/glob-conflict-cross-crate.rs b/src/test/ui/imports/glob-conflict-cross-crate.rs
new file mode 100644
index 0000000..c8b1852
--- /dev/null
+++ b/src/test/ui/imports/glob-conflict-cross-crate.rs
@@ -0,0 +1,8 @@
+// aux-build:glob-conflict.rs
+
+extern crate glob_conflict;
+
+fn main() {
+    glob_conflict::f(); //~ ERROR cannot find function `f` in module `glob_conflict`
+    glob_conflict::glob::f(); //~ ERROR cannot find function `f` in module `glob_conflict::glob`
+}
diff --git a/src/test/ui/imports/glob-conflict-cross-crate.stderr b/src/test/ui/imports/glob-conflict-cross-crate.stderr
new file mode 100644
index 0000000..ad70b7d
--- /dev/null
+++ b/src/test/ui/imports/glob-conflict-cross-crate.stderr
@@ -0,0 +1,15 @@
+error[E0425]: cannot find function `f` in module `glob_conflict`
+  --> $DIR/glob-conflict-cross-crate.rs:6:20
+   |
+LL |     glob_conflict::f();
+   |                    ^ not found in `glob_conflict`
+
+error[E0425]: cannot find function `f` in module `glob_conflict::glob`
+  --> $DIR/glob-conflict-cross-crate.rs:7:26
+   |
+LL |     glob_conflict::glob::f();
+   |                          ^ not found in `glob_conflict::glob`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/imports/glob-shadowing.rs b/src/test/ui/imports/glob-shadowing.rs
new file mode 100644
index 0000000..3a33b592
--- /dev/null
+++ b/src/test/ui/imports/glob-shadowing.rs
@@ -0,0 +1,34 @@
+#![feature(decl_macro)]
+
+mod m {
+    pub macro env($e: expr) { $e }
+    pub macro fenv() { 0 }
+}
+
+mod glob_in_normal_module {
+    use m::*;
+    fn check() {
+        let x = env!("PATH"); //~ ERROR `env` is ambiguous
+    }
+}
+
+mod glob_in_block_module {
+    fn block() {
+        use m::*;
+        fn check() {
+            let x = env!("PATH"); //~ ERROR `env` is ambiguous
+        }
+    }
+}
+
+mod glob_shadows_item {
+    pub macro fenv($e: expr) { $e }
+    fn block() {
+        use m::*;
+        fn check() {
+            let x = fenv!(); //~ ERROR `fenv` is ambiguous
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/imports/glob-shadowing.stderr b/src/test/ui/imports/glob-shadowing.stderr
new file mode 100644
index 0000000..7962fcb
--- /dev/null
+++ b/src/test/ui/imports/glob-shadowing.stderr
@@ -0,0 +1,51 @@
+error[E0659]: `env` is ambiguous (glob import vs any other name from outer scope during import/macro resolution)
+  --> $DIR/glob-shadowing.rs:11:17
+   |
+LL |         let x = env!("PATH");
+   |                 ^^^ ambiguous name
+   |
+   = note: `env` could refer to a built-in macro
+note: `env` could also refer to the macro imported here
+  --> $DIR/glob-shadowing.rs:9:9
+   |
+LL |     use m::*;
+   |         ^^^^
+   = help: consider adding an explicit import of `env` to disambiguate
+   = help: or use `self::env` to refer to this macro unambiguously
+
+error[E0659]: `env` is ambiguous (glob import vs any other name from outer scope during import/macro resolution)
+  --> $DIR/glob-shadowing.rs:19:21
+   |
+LL |             let x = env!("PATH");
+   |                     ^^^ ambiguous name
+   |
+   = note: `env` could refer to a built-in macro
+note: `env` could also refer to the macro imported here
+  --> $DIR/glob-shadowing.rs:17:13
+   |
+LL |         use m::*;
+   |             ^^^^
+   = help: consider adding an explicit import of `env` to disambiguate
+
+error[E0659]: `fenv` is ambiguous (glob import vs any other name from outer scope during import/macro resolution)
+  --> $DIR/glob-shadowing.rs:29:21
+   |
+LL |             let x = fenv!();
+   |                     ^^^^ ambiguous name
+   |
+note: `fenv` could refer to the macro imported here
+  --> $DIR/glob-shadowing.rs:27:13
+   |
+LL |         use m::*;
+   |             ^^^^
+   = help: consider adding an explicit import of `fenv` to disambiguate
+note: `fenv` could also refer to the macro defined here
+  --> $DIR/glob-shadowing.rs:25:5
+   |
+LL |     pub macro fenv($e: expr) { $e }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: use `self::fenv` to refer to this macro unambiguously
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0659`.
diff --git a/src/test/ui/imports/import-crate-var.rs b/src/test/ui/imports/import-crate-var.rs
new file mode 100644
index 0000000..ab26050
--- /dev/null
+++ b/src/test/ui/imports/import-crate-var.rs
@@ -0,0 +1,12 @@
+// aux-build:import_crate_var.rs
+
+// compile-pass
+// skip-codegen
+#[macro_use] extern crate import_crate_var;
+
+
+fn main() {
+    m!();
+    //~^ WARN `$crate` may not be imported
+    //~| NOTE `use $crate;` was erroneously allowed and will become a hard error
+}
diff --git a/src/test/ui/imports/import-crate-var.stderr b/src/test/ui/imports/import-crate-var.stderr
new file mode 100644
index 0000000..4c358a8
--- /dev/null
+++ b/src/test/ui/imports/import-crate-var.stderr
@@ -0,0 +1,9 @@
+warning: `$crate` may not be imported
+  --> $DIR/import-crate-var.rs:9:5
+   |
+LL |     m!();
+   |     ^^^^^
+   |
+   = note: `use $crate;` was erroneously allowed and will become a hard error in a future release
+   = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
diff --git a/src/test/ui/imports/import-from-missing.rs b/src/test/ui/imports/import-from-missing.rs
new file mode 100644
index 0000000..8eae700
--- /dev/null
+++ b/src/test/ui/imports/import-from-missing.rs
@@ -0,0 +1,12 @@
+use spam::{ham, eggs}; //~ ERROR unresolved import `spam::eggs` [E0432]
+                       //~^ no `eggs` in `spam`
+
+mod spam {
+    pub fn ham() { }
+}
+
+fn main() {
+    ham();
+    // Expect eggs to pass because the compiler inserts a fake name for it
+    eggs();
+}
diff --git a/src/test/ui/imports/import-from-missing.stderr b/src/test/ui/imports/import-from-missing.stderr
new file mode 100644
index 0000000..4254bfb
--- /dev/null
+++ b/src/test/ui/imports/import-from-missing.stderr
@@ -0,0 +1,9 @@
+error[E0432]: unresolved import `spam::eggs`
+  --> $DIR/import-from-missing.rs:1:17
+   |
+LL | use spam::{ham, eggs};
+   |                 ^^^^ no `eggs` in `spam`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/imports/import-glob-0.rs b/src/test/ui/imports/import-glob-0.rs
new file mode 100644
index 0000000..37a0d15
--- /dev/null
+++ b/src/test/ui/imports/import-glob-0.rs
@@ -0,0 +1,16 @@
+use module_of_many_things::*;
+
+mod module_of_many_things {
+    pub fn f1() { println!("f1"); }
+    pub fn f2() { println!("f2"); }
+    fn f3() { println!("f3"); }
+    pub fn f4() { println!("f4"); }
+}
+
+
+fn main() {
+    f1();
+    f2();
+    f999(); //~ ERROR cannot find function `f999` in this scope
+    f4();
+}
diff --git a/src/test/ui/imports/import-glob-0.stderr b/src/test/ui/imports/import-glob-0.stderr
new file mode 100644
index 0000000..820ff1b
--- /dev/null
+++ b/src/test/ui/imports/import-glob-0.stderr
@@ -0,0 +1,9 @@
+error[E0425]: cannot find function `f999` in this scope
+  --> $DIR/import-glob-0.rs:14:5
+   |
+LL |     f999();
+   |     ^^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/imports/import-glob-circular.rs b/src/test/ui/imports/import-glob-circular.rs
new file mode 100644
index 0000000..e47fa87
--- /dev/null
+++ b/src/test/ui/imports/import-glob-circular.rs
@@ -0,0 +1,19 @@
+mod circ1 {
+    pub use circ2::f2;
+    pub fn f1() { println!("f1"); }
+    pub fn common() -> usize { return 0; }
+}
+
+mod circ2 {
+    pub use circ1::f1;
+    pub fn f2() { println!("f2"); }
+    pub fn common() -> usize { return 1; }
+}
+
+mod test {
+    use circ1::*;
+
+    fn test() { f1066(); } //~ ERROR cannot find function `f1066` in this scope
+}
+
+fn main() {}
diff --git a/src/test/ui/imports/import-glob-circular.stderr b/src/test/ui/imports/import-glob-circular.stderr
new file mode 100644
index 0000000..86bbea5
--- /dev/null
+++ b/src/test/ui/imports/import-glob-circular.stderr
@@ -0,0 +1,9 @@
+error[E0425]: cannot find function `f1066` in this scope
+  --> $DIR/import-glob-circular.rs:16:17
+   |
+LL |     fn test() { f1066(); }
+   |                 ^^^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/imports/import-loop-2.rs b/src/test/ui/imports/import-loop-2.rs
new file mode 100644
index 0000000..14a85dd
--- /dev/null
+++ b/src/test/ui/imports/import-loop-2.rs
@@ -0,0 +1,13 @@
+// error-pattern:import
+
+mod a {
+    pub use b::x;
+}
+
+mod b {
+    pub use a::x;
+
+    fn main() { let y = x; }
+}
+
+fn main() {}
diff --git a/src/test/ui/imports/import-loop-2.stderr b/src/test/ui/imports/import-loop-2.stderr
new file mode 100644
index 0000000..1abfcde
--- /dev/null
+++ b/src/test/ui/imports/import-loop-2.stderr
@@ -0,0 +1,9 @@
+error[E0432]: unresolved import `a::x`
+  --> $DIR/import-loop-2.rs:8:13
+   |
+LL |     pub use a::x;
+   |             ^^^^ no `x` in `a`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/imports/import-loop.rs b/src/test/ui/imports/import-loop.rs
new file mode 100644
index 0000000..b487834
--- /dev/null
+++ b/src/test/ui/imports/import-loop.rs
@@ -0,0 +1,9 @@
+// error-pattern:import
+
+use y::x;
+
+mod y {
+    pub use y::x;
+}
+
+fn main() { }
diff --git a/src/test/ui/imports/import-loop.stderr b/src/test/ui/imports/import-loop.stderr
new file mode 100644
index 0000000..b87bfb1
--- /dev/null
+++ b/src/test/ui/imports/import-loop.stderr
@@ -0,0 +1,9 @@
+error[E0432]: unresolved import `y::x`
+  --> $DIR/import-loop.rs:6:13
+   |
+LL |     pub use y::x;
+   |             ^^^^ no `x` in `y`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/imports/import-prefix-macro-1.rs b/src/test/ui/imports/import-prefix-macro-1.rs
new file mode 100644
index 0000000..91cfd37
--- /dev/null
+++ b/src/test/ui/imports/import-prefix-macro-1.rs
@@ -0,0 +1,16 @@
+mod a {
+    pub mod b {
+        pub mod c {
+            pub struct S;
+            pub struct Z;
+        }
+    }
+}
+
+macro_rules! import {
+    ($p: path) => (use $p {S, Z}); //~ERROR expected one of `::`, `;`, or `as`, found `{`
+}
+
+import! { a::b::c }
+
+fn main() {}
diff --git a/src/test/ui/imports/import-prefix-macro-1.stderr b/src/test/ui/imports/import-prefix-macro-1.stderr
new file mode 100644
index 0000000..577f128
--- /dev/null
+++ b/src/test/ui/imports/import-prefix-macro-1.stderr
@@ -0,0 +1,11 @@
+error: expected one of `::`, `;`, or `as`, found `{`
+  --> $DIR/import-prefix-macro-1.rs:11:27
+   |
+LL |     ($p: path) => (use $p {S, Z});
+   |                           ^ expected one of `::`, `;`, or `as` here
+...
+LL | import! { a::b::c }
+   | ------------------- in this macro invocation
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/imports/import-prefix-macro-2.rs b/src/test/ui/imports/import-prefix-macro-2.rs
new file mode 100644
index 0000000..952d161
--- /dev/null
+++ b/src/test/ui/imports/import-prefix-macro-2.rs
@@ -0,0 +1,16 @@
+mod a {
+    pub mod b {
+        pub mod c {
+            pub struct S;
+            pub struct Z;
+        }
+    }
+}
+
+macro_rules! import {
+    ($p: path) => (use ::$p {S, Z}); //~ERROR  expected identifier, found `a::b::c`
+}
+
+import! { a::b::c }
+
+fn main() {}
diff --git a/src/test/ui/imports/import-prefix-macro-2.stderr b/src/test/ui/imports/import-prefix-macro-2.stderr
new file mode 100644
index 0000000..8428dce
--- /dev/null
+++ b/src/test/ui/imports/import-prefix-macro-2.stderr
@@ -0,0 +1,11 @@
+error: expected identifier, found `a::b::c`
+  --> $DIR/import-prefix-macro-2.rs:11:26
+   |
+LL |     ($p: path) => (use ::$p {S, Z});
+   |                          ^^ expected identifier
+...
+LL | import! { a::b::c }
+   | ------------------- in this macro invocation
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/imports/import-trait-method.rs b/src/test/ui/imports/import-trait-method.rs
new file mode 100644
index 0000000..97dd68f
--- /dev/null
+++ b/src/test/ui/imports/import-trait-method.rs
@@ -0,0 +1,7 @@
+trait Foo {
+    fn foo();
+}
+
+use Foo::foo; //~ ERROR not directly importable
+
+fn main() { foo(); }
diff --git a/src/test/ui/imports/import-trait-method.stderr b/src/test/ui/imports/import-trait-method.stderr
new file mode 100644
index 0000000..3c26907
--- /dev/null
+++ b/src/test/ui/imports/import-trait-method.stderr
@@ -0,0 +1,9 @@
+error[E0253]: `foo` is not directly importable
+  --> $DIR/import-trait-method.rs:5:5
+   |
+LL | use Foo::foo;
+   |     ^^^^^^^^ cannot be imported directly
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0253`.
diff --git a/src/test/ui/imports/issue-53140.rs b/src/test/ui/imports/issue-53140.rs
new file mode 100644
index 0000000..dbfba2c
--- /dev/null
+++ b/src/test/ui/imports/issue-53140.rs
@@ -0,0 +1,11 @@
+// compile-pass
+
+mod m {
+    pub struct S(u8);
+
+    use S as Z;
+}
+
+use m::*;
+
+fn main() {}
diff --git a/src/test/ui/imports/issue-53269.rs b/src/test/ui/imports/issue-53269.rs
new file mode 100644
index 0000000..444a16f
--- /dev/null
+++ b/src/test/ui/imports/issue-53269.rs
@@ -0,0 +1,11 @@
+// Ambiguity between a `macro_rules` macro and a non-existent import recovered as `Def::Err`
+
+macro_rules! mac { () => () }
+
+mod m {
+    use nonexistent_module::mac; //~ ERROR unresolved import `nonexistent_module`
+
+    mac!(); //~ ERROR `mac` is ambiguous
+}
+
+fn main() {}
diff --git a/src/test/ui/imports/issue-53269.stderr b/src/test/ui/imports/issue-53269.stderr
new file mode 100644
index 0000000..fc4ca3d
--- /dev/null
+++ b/src/test/ui/imports/issue-53269.stderr
@@ -0,0 +1,28 @@
+error[E0432]: unresolved import `nonexistent_module`
+  --> $DIR/issue-53269.rs:6:9
+   |
+LL |     use nonexistent_module::mac;
+   |         ^^^^^^^^^^^^^^^^^^ maybe a missing `extern crate nonexistent_module;`?
+
+error[E0659]: `mac` is ambiguous (`macro_rules` vs non-`macro_rules` from other module)
+  --> $DIR/issue-53269.rs:8:5
+   |
+LL |     mac!();
+   |     ^^^ ambiguous name
+   |
+note: `mac` could refer to the macro defined here
+  --> $DIR/issue-53269.rs:3:1
+   |
+LL | macro_rules! mac { () => () }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: `mac` could also refer to the unresolved item imported here
+  --> $DIR/issue-53269.rs:6:9
+   |
+LL |     use nonexistent_module::mac;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+   = help: use `self::mac` to refer to this unresolved item unambiguously
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0432, E0659.
+For more information about an error, try `rustc --explain E0432`.
diff --git a/src/test/ui/imports/issue-53512.rs b/src/test/ui/imports/issue-53512.rs
new file mode 100644
index 0000000..61d9353
--- /dev/null
+++ b/src/test/ui/imports/issue-53512.rs
@@ -0,0 +1,7 @@
+// Macro from prelude is shadowed by non-existent import recovered as `Def::Err`.
+
+use std::assert; //~ ERROR unresolved import `std::assert`
+
+fn main() {
+    assert!(true);
+}
diff --git a/src/test/ui/imports/issue-53512.stderr b/src/test/ui/imports/issue-53512.stderr
new file mode 100644
index 0000000..f902fc4
--- /dev/null
+++ b/src/test/ui/imports/issue-53512.stderr
@@ -0,0 +1,9 @@
+error[E0432]: unresolved import `std::assert`
+  --> $DIR/issue-53512.rs:3:5
+   |
+LL | use std::assert;
+   |     ^^^^^^^^^^^ no `assert` in the root
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/imports/issue-55457.rs b/src/test/ui/imports/issue-55457.rs
new file mode 100644
index 0000000..9c6750f
--- /dev/null
+++ b/src/test/ui/imports/issue-55457.rs
@@ -0,0 +1,8 @@
+use NonExistent; //~ ERROR unresolved import `NonExistent`
+use non_existent::non_existent; //~ ERROR unresolved import `non_existent`
+
+#[non_existent] //~ ERROR cannot determine resolution for the attribute macro `non_existent`
+#[derive(NonExistent)] //~ ERROR cannot determine resolution for the derive macro `NonExistent`
+struct S;
+
+fn main() {}
diff --git a/src/test/ui/imports/issue-55457.stderr b/src/test/ui/imports/issue-55457.stderr
new file mode 100644
index 0000000..86a76c1
--- /dev/null
+++ b/src/test/ui/imports/issue-55457.stderr
@@ -0,0 +1,34 @@
+error[E0432]: unresolved import `NonExistent`
+  --> $DIR/issue-55457.rs:1:5
+   |
+LL | use NonExistent;
+   |     ^^^^^^^^^^^
+   |     |
+   |     no `NonExistent` in the root
+   |     help: a similar name exists in the module: `non_existent`
+
+error[E0432]: unresolved import `non_existent`
+  --> $DIR/issue-55457.rs:2:5
+   |
+LL | use non_existent::non_existent;
+   |     ^^^^^^^^^^^^ maybe a missing `extern crate non_existent;`?
+
+error: cannot determine resolution for the derive macro `NonExistent`
+  --> $DIR/issue-55457.rs:5:10
+   |
+LL | #[derive(NonExistent)]
+   |          ^^^^^^^^^^^
+   |
+   = note: import resolution is stuck, try simplifying macro imports
+
+error: cannot determine resolution for the attribute macro `non_existent`
+  --> $DIR/issue-55457.rs:4:3
+   |
+LL | #[non_existent]
+   |   ^^^^^^^^^^^^
+   |
+   = note: import resolution is stuck, try simplifying macro imports
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/imports/issue-55811.rs b/src/test/ui/imports/issue-55811.rs
new file mode 100644
index 0000000..9531677
--- /dev/null
+++ b/src/test/ui/imports/issue-55811.rs
@@ -0,0 +1,6 @@
+// compile-pass
+// aux-build:issue-55811.rs
+
+extern crate issue_55811;
+
+fn main() {}
diff --git a/src/test/ui/imports/issue-55884-1.rs b/src/test/ui/imports/issue-55884-1.rs
new file mode 100644
index 0000000..21744aa
--- /dev/null
+++ b/src/test/ui/imports/issue-55884-1.rs
@@ -0,0 +1,21 @@
+mod m {
+    mod m1 {
+        pub struct S {}
+    }
+    mod m2 {
+        // Note this derive, it makes this struct macro-expanded,
+        // so it doesn't appear in time to participate in the initial resolution of `use m::S`,
+        // only in the later validation pass.
+        #[derive(Default)]
+        pub struct S {}
+    }
+
+    // Create a glob vs glob ambiguity
+    pub use self::m1::*;
+    pub use self::m2::*;
+}
+
+fn main() {
+    use m::S; //~ ERROR `S` is ambiguous
+    let s = S {};
+}
diff --git a/src/test/ui/imports/issue-55884-1.stderr b/src/test/ui/imports/issue-55884-1.stderr
new file mode 100644
index 0000000..a7a7cc8
--- /dev/null
+++ b/src/test/ui/imports/issue-55884-1.stderr
@@ -0,0 +1,22 @@
+error[E0659]: `S` is ambiguous (glob import vs glob import in the same module)
+  --> $DIR/issue-55884-1.rs:19:12
+   |
+LL |     use m::S;
+   |            ^ ambiguous name
+   |
+note: `S` could refer to the struct imported here
+  --> $DIR/issue-55884-1.rs:14:13
+   |
+LL |     pub use self::m1::*;
+   |             ^^^^^^^^^^^
+   = help: consider adding an explicit import of `S` to disambiguate
+note: `S` could also refer to the struct imported here
+  --> $DIR/issue-55884-1.rs:15:13
+   |
+LL |     pub use self::m2::*;
+   |             ^^^^^^^^^^^
+   = help: consider adding an explicit import of `S` to disambiguate
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0659`.
diff --git a/src/test/ui/imports/issue-55884-2.rs b/src/test/ui/imports/issue-55884-2.rs
new file mode 100644
index 0000000..1b4f652
--- /dev/null
+++ b/src/test/ui/imports/issue-55884-2.rs
@@ -0,0 +1,14 @@
+mod options {
+    pub struct ParseOptions {}
+}
+
+mod parser {
+    pub use options::*;
+    // Private single import shadows public glob import, but arrives too late for initial
+    // resolution of `use parser::ParseOptions` because it depends on that resolution itself.
+    use ParseOptions;
+}
+
+pub use parser::ParseOptions; //~ ERROR struct `ParseOptions` is private
+
+fn main() {}
diff --git a/src/test/ui/imports/issue-55884-2.stderr b/src/test/ui/imports/issue-55884-2.stderr
new file mode 100644
index 0000000..d3b43783
--- /dev/null
+++ b/src/test/ui/imports/issue-55884-2.stderr
@@ -0,0 +1,9 @@
+error[E0603]: struct `ParseOptions` is private
+  --> $DIR/issue-55884-2.rs:12:17
+   |
+LL | pub use parser::ParseOptions;
+   |                 ^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0603`.
diff --git a/src/test/ui/imports/issue-56125.rs b/src/test/ui/imports/issue-56125.rs
new file mode 100644
index 0000000..ec5747b
--- /dev/null
+++ b/src/test/ui/imports/issue-56125.rs
@@ -0,0 +1,21 @@
+// edition:2018
+// compile-flags:--extern issue_56125
+// aux-build:issue-56125.rs
+
+mod m1 {
+    use issue_56125::last_segment::*;
+    //~^ ERROR `issue_56125` is ambiguous
+}
+
+mod m2 {
+    use issue_56125::non_last_segment::non_last_segment::*;
+    //~^ ERROR `issue_56125` is ambiguous
+}
+
+mod m3 {
+    mod empty {}
+    use empty::issue_56125; //~ ERROR unresolved import `empty::issue_56125`
+    use issue_56125::*; //~ ERROR `issue_56125` is ambiguous
+}
+
+fn main() {}
diff --git a/src/test/ui/imports/issue-56125.stderr b/src/test/ui/imports/issue-56125.stderr
new file mode 100644
index 0000000..26d2fa0
--- /dev/null
+++ b/src/test/ui/imports/issue-56125.stderr
@@ -0,0 +1,55 @@
+error[E0432]: unresolved import `empty::issue_56125`
+  --> $DIR/issue-56125.rs:17:9
+   |
+LL |     use empty::issue_56125;
+   |         ^^^^^^^^^^^^^^^^^^ no `issue_56125` in `m3::empty`
+
+error[E0659]: `issue_56125` is ambiguous (name vs any other name during import resolution)
+  --> $DIR/issue-56125.rs:6:9
+   |
+LL |     use issue_56125::last_segment::*;
+   |         ^^^^^^^^^^^ ambiguous name
+   |
+   = note: `issue_56125` could refer to an extern crate passed with `--extern`
+   = help: use `::issue_56125` to refer to this extern crate unambiguously
+note: `issue_56125` could also refer to the module imported here
+  --> $DIR/issue-56125.rs:6:9
+   |
+LL |     use issue_56125::last_segment::*;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: use `self::issue_56125` to refer to this module unambiguously
+
+error[E0659]: `issue_56125` is ambiguous (name vs any other name during import resolution)
+  --> $DIR/issue-56125.rs:11:9
+   |
+LL |     use issue_56125::non_last_segment::non_last_segment::*;
+   |         ^^^^^^^^^^^ ambiguous name
+   |
+   = note: `issue_56125` could refer to an extern crate passed with `--extern`
+   = help: use `::issue_56125` to refer to this extern crate unambiguously
+note: `issue_56125` could also refer to the module imported here
+  --> $DIR/issue-56125.rs:11:9
+   |
+LL |     use issue_56125::non_last_segment::non_last_segment::*;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: use `self::issue_56125` to refer to this module unambiguously
+
+error[E0659]: `issue_56125` is ambiguous (name vs any other name during import resolution)
+  --> $DIR/issue-56125.rs:18:9
+   |
+LL |     use issue_56125::*;
+   |         ^^^^^^^^^^^ ambiguous name
+   |
+   = note: `issue_56125` could refer to an extern crate passed with `--extern`
+   = help: use `::issue_56125` to refer to this extern crate unambiguously
+note: `issue_56125` could also refer to the module imported here
+  --> $DIR/issue-56125.rs:18:9
+   |
+LL |     use issue_56125::*;
+   |         ^^^^^^^^^^^^^^
+   = help: use `self::issue_56125` to refer to this module unambiguously
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0432, E0659.
+For more information about an error, try `rustc --explain E0432`.
diff --git a/src/test/ui/imports/issue-56263.rs b/src/test/ui/imports/issue-56263.rs
new file mode 100644
index 0000000..4113d43
--- /dev/null
+++ b/src/test/ui/imports/issue-56263.rs
@@ -0,0 +1,8 @@
+// compile-pass
+// edition:2018
+
+use ::std;
+
+fn main() {
+    let std = 10;
+}
diff --git a/src/test/ui/imports/issue-57015.rs b/src/test/ui/imports/issue-57015.rs
new file mode 100644
index 0000000..27688fd
--- /dev/null
+++ b/src/test/ui/imports/issue-57015.rs
@@ -0,0 +1,13 @@
+mod glob_ok {
+    pub mod something {
+        pub mod something_else {}
+    }
+}
+
+mod single_err {}
+
+use glob_ok::*; // glob_ok::something
+use single_err::something; //~ ERROR unresolved import `single_err::something`
+use something::something_else;
+
+fn main() {}
diff --git a/src/test/ui/imports/issue-57015.stderr b/src/test/ui/imports/issue-57015.stderr
new file mode 100644
index 0000000..d200d23
--- /dev/null
+++ b/src/test/ui/imports/issue-57015.stderr
@@ -0,0 +1,9 @@
+error[E0432]: unresolved import `single_err::something`
+  --> $DIR/issue-57015.rs:10:5
+   |
+LL | use single_err::something;
+   |     ^^^^^^^^^^^^^^^^^^^^^ no `something` in `single_err`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/imports/issue-57539.rs b/src/test/ui/imports/issue-57539.rs
new file mode 100644
index 0000000..90b74eb
--- /dev/null
+++ b/src/test/ui/imports/issue-57539.rs
@@ -0,0 +1,8 @@
+// edition:2018
+
+mod core {
+    use core; //~ ERROR `core` is ambiguous
+    use crate::*;
+}
+
+fn main() {}
diff --git a/src/test/ui/imports/issue-57539.stderr b/src/test/ui/imports/issue-57539.stderr
new file mode 100644
index 0000000..ebf27ca
--- /dev/null
+++ b/src/test/ui/imports/issue-57539.stderr
@@ -0,0 +1,18 @@
+error[E0659]: `core` is ambiguous (name vs any other name during import resolution)
+  --> $DIR/issue-57539.rs:4:9
+   |
+LL |     use core;
+   |         ^^^^ ambiguous name
+   |
+   = note: `core` could refer to a built-in extern crate
+   = help: use `::core` to refer to this extern crate unambiguously
+note: `core` could also refer to the module imported here
+  --> $DIR/issue-57539.rs:5:9
+   |
+LL |     use crate::*;
+   |         ^^^^^^^^
+   = help: use `self::core` to refer to this module unambiguously
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0659`.
diff --git a/src/test/ui/imports/local-modularized-tricky-fail-1.rs b/src/test/ui/imports/local-modularized-tricky-fail-1.rs
new file mode 100644
index 0000000..d1cb6b0
--- /dev/null
+++ b/src/test/ui/imports/local-modularized-tricky-fail-1.rs
@@ -0,0 +1,47 @@
+#![feature(decl_macro)]
+
+macro_rules! define_exported { () => {
+    #[macro_export]
+    macro_rules! exported {
+        () => ()
+    }
+}}
+macro_rules! define_panic { () => {
+    #[macro_export]
+    macro_rules! panic {
+        () => ()
+    }
+}}
+macro_rules! define_include { () => {
+    #[macro_export]
+    macro_rules! include {
+        () => ()
+    }
+}}
+
+use inner1::*;
+
+mod inner1 {
+    pub macro exported() {}
+}
+
+exported!(); //~ ERROR `exported` is ambiguous
+
+mod inner2 {
+    define_exported!();
+}
+
+fn main() {
+    panic!(); //~ ERROR `panic` is ambiguous
+              //~| ERROR `panic` is ambiguous
+}
+
+mod inner3 {
+    define_panic!();
+}
+
+mod inner4 {
+    define_include!();
+}
+
+include!(); //~ ERROR `include` is ambiguous
diff --git a/src/test/ui/imports/local-modularized-tricky-fail-1.stderr b/src/test/ui/imports/local-modularized-tricky-fail-1.stderr
new file mode 100644
index 0000000..d7ae8e6
--- /dev/null
+++ b/src/test/ui/imports/local-modularized-tricky-fail-1.stderr
@@ -0,0 +1,84 @@
+error[E0659]: `exported` is ambiguous (glob import vs macro-expanded name in the same module during import/macro resolution)
+  --> $DIR/local-modularized-tricky-fail-1.rs:28:1
+   |
+LL | exported!();
+   | ^^^^^^^^ ambiguous name
+   |
+note: `exported` could refer to the macro defined here
+  --> $DIR/local-modularized-tricky-fail-1.rs:5:5
+   |
+LL | /     macro_rules! exported {
+LL | |         () => ()
+LL | |     }
+   | |_____^
+...
+LL |       define_exported!();
+   |       ------------------- in this macro invocation
+note: `exported` could also refer to the macro imported here
+  --> $DIR/local-modularized-tricky-fail-1.rs:22:5
+   |
+LL | use inner1::*;
+   |     ^^^^^^^^^
+   = help: consider adding an explicit import of `exported` to disambiguate
+
+error[E0659]: `include` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
+  --> $DIR/local-modularized-tricky-fail-1.rs:47:1
+   |
+LL | include!();
+   | ^^^^^^^ ambiguous name
+   |
+   = note: `include` could refer to a built-in macro
+note: `include` could also refer to the macro defined here
+  --> $DIR/local-modularized-tricky-fail-1.rs:17:5
+   |
+LL | /     macro_rules! include {
+LL | |         () => ()
+LL | |     }
+   | |_____^
+...
+LL |       define_include!();
+   |       ------------------ in this macro invocation
+   = help: use `crate::include` to refer to this macro unambiguously
+
+error[E0659]: `panic` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
+  --> $DIR/local-modularized-tricky-fail-1.rs:35:5
+   |
+LL |     panic!();
+   |     ^^^^^ ambiguous name
+   |
+   = note: `panic` could refer to a macro from prelude
+note: `panic` could also refer to the macro defined here
+  --> $DIR/local-modularized-tricky-fail-1.rs:11:5
+   |
+LL | /     macro_rules! panic {
+LL | |         () => ()
+LL | |     }
+   | |_____^
+...
+LL |       define_panic!();
+   |       ---------------- in this macro invocation
+   = help: use `crate::panic` to refer to this macro unambiguously
+
+error[E0659]: `panic` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
+  --> $DIR/local-modularized-tricky-fail-1.rs:35:5
+   |
+LL |     panic!();
+   |     ^^^^^^^^^ ambiguous name
+   |
+   = note: `panic` could refer to a macro from prelude
+note: `panic` could also refer to the macro defined here
+  --> $DIR/local-modularized-tricky-fail-1.rs:11:5
+   |
+LL | /     macro_rules! panic {
+LL | |         () => ()
+LL | |     }
+   | |_____^
+...
+LL |       define_panic!();
+   |       ---------------- in this macro invocation
+   = help: use `crate::panic` to refer to this macro unambiguously
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0659`.
diff --git a/src/test/ui/imports/local-modularized-tricky-fail-2.rs b/src/test/ui/imports/local-modularized-tricky-fail-2.rs
new file mode 100644
index 0000000..e637eda
--- /dev/null
+++ b/src/test/ui/imports/local-modularized-tricky-fail-2.rs
@@ -0,0 +1,48 @@
+// `#[macro_export] macro_rules` that doesn't originate from macro expansions can be placed
+// into the root module soon enough to act as usual items and shadow globs and preludes.
+
+#![feature(decl_macro)]
+
+// `macro_export` shadows globs
+use inner1::*;
+
+mod inner1 {
+    pub macro exported() {}
+}
+
+exported!();
+
+mod deep {
+    fn deep() {
+        type Deeper = [u8; {
+            #[macro_export]
+            macro_rules! exported {
+                () => ( struct Б; ) //~ ERROR non-ascii idents are not fully supported
+            }
+
+            0
+        }];
+    }
+}
+
+// `macro_export` shadows std prelude
+fn main() {
+    panic!();
+}
+
+mod inner3 {
+    #[macro_export]
+    macro_rules! panic {
+        () => ( struct Г; ) //~ ERROR non-ascii idents are not fully supported
+    }
+}
+
+// `macro_export` shadows builtin macros
+include!();
+
+mod inner4 {
+    #[macro_export]
+    macro_rules! include {
+        () => ( struct Д; ) //~ ERROR non-ascii idents are not fully supported
+    }
+}
diff --git a/src/test/ui/imports/local-modularized-tricky-fail-2.stderr b/src/test/ui/imports/local-modularized-tricky-fail-2.stderr
new file mode 100644
index 0000000..a26f0cb
--- /dev/null
+++ b/src/test/ui/imports/local-modularized-tricky-fail-2.stderr
@@ -0,0 +1,36 @@
+error[E0658]: non-ascii idents are not fully supported. (see issue #55467)
+  --> $DIR/local-modularized-tricky-fail-2.rs:20:32
+   |
+LL | exported!();
+   | ------------ in this macro invocation
+...
+LL |                 () => ( struct Б; )
+   |                                ^
+   |
+   = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
+
+error[E0658]: non-ascii idents are not fully supported. (see issue #55467)
+  --> $DIR/local-modularized-tricky-fail-2.rs:36:24
+   |
+LL |     panic!();
+   |     --------- in this macro invocation
+...
+LL |         () => ( struct Г; )
+   |                        ^
+   |
+   = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
+
+error[E0658]: non-ascii idents are not fully supported. (see issue #55467)
+  --> $DIR/local-modularized-tricky-fail-2.rs:46:24
+   |
+LL | include!();
+   | ----------- in this macro invocation
+...
+LL |         () => ( struct Д; )
+   |                        ^
+   |
+   = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/imports/local-modularized-tricky-fail-3.rs b/src/test/ui/imports/local-modularized-tricky-fail-3.rs
new file mode 100644
index 0000000..386de88
--- /dev/null
+++ b/src/test/ui/imports/local-modularized-tricky-fail-3.rs
@@ -0,0 +1,22 @@
+// Crate-local macro expanded `macro_export` macros cannot be accessed with module-relative paths.
+
+macro_rules! define_exported { () => {
+    #[macro_export]
+    macro_rules! exported {
+        () => ()
+    }
+}}
+
+define_exported!();
+
+mod m {
+    use exported;
+    //~^ ERROR macro-expanded `macro_export` macros from the current crate cannot
+    //~| WARN this was previously accepted
+}
+
+fn main() {
+    ::exported!();
+    //~^ ERROR macro-expanded `macro_export` macros from the current crate cannot
+    //~| WARN this was previously accepted
+}
diff --git a/src/test/ui/imports/local-modularized-tricky-fail-3.stderr b/src/test/ui/imports/local-modularized-tricky-fail-3.stderr
new file mode 100644
index 0000000..6bece2b
--- /dev/null
+++ b/src/test/ui/imports/local-modularized-tricky-fail-3.stderr
@@ -0,0 +1,41 @@
+error: macro-expanded `macro_export` macros from the current crate cannot be referred to by absolute paths
+  --> $DIR/local-modularized-tricky-fail-3.rs:13:9
+   |
+LL |     use exported;
+   |         ^^^^^^^^
+   |
+   = note: #[deny(macro_expanded_macro_exports_accessed_by_absolute_paths)] on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #52234 <https://github.com/rust-lang/rust/issues/52234>
+note: the macro is defined here
+  --> $DIR/local-modularized-tricky-fail-3.rs:5:5
+   |
+LL | /     macro_rules! exported {
+LL | |         () => ()
+LL | |     }
+   | |_____^
+...
+LL |   define_exported!();
+   |   ------------------- in this macro invocation
+
+error: macro-expanded `macro_export` macros from the current crate cannot be referred to by absolute paths
+  --> $DIR/local-modularized-tricky-fail-3.rs:19:5
+   |
+LL |     ::exported!();
+   |     ^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #52234 <https://github.com/rust-lang/rust/issues/52234>
+note: the macro is defined here
+  --> $DIR/local-modularized-tricky-fail-3.rs:5:5
+   |
+LL | /     macro_rules! exported {
+LL | |         () => ()
+LL | |     }
+   | |_____^
+...
+LL |   define_exported!();
+   |   ------------------- in this macro invocation
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/imports/local-modularized-tricky-pass.rs b/src/test/ui/imports/local-modularized-tricky-pass.rs
new file mode 100644
index 0000000..59aac95
--- /dev/null
+++ b/src/test/ui/imports/local-modularized-tricky-pass.rs
@@ -0,0 +1,19 @@
+// compile-pass
+
+macro_rules! define_exported { () => {
+    #[macro_export]
+    macro_rules! exported {
+        () => ()
+    }
+}}
+
+mod inner1 {
+    use super::*;
+    exported!();
+}
+
+mod inner2 {
+    define_exported!();
+}
+
+fn main() {}
diff --git a/src/test/ui/imports/local-modularized.rs b/src/test/ui/imports/local-modularized.rs
new file mode 100644
index 0000000..a073fe2
--- /dev/null
+++ b/src/test/ui/imports/local-modularized.rs
@@ -0,0 +1,35 @@
+// compile-pass
+
+#[macro_export(local_inner_macros)]
+macro_rules! dollar_crate_exported {
+    (1) => { $crate::exported!(); };
+    (2) => { exported!(); };
+}
+
+// Before `exported` is defined
+exported!();
+
+mod inner {
+
+    ::exported!();
+    crate::exported!();
+    dollar_crate_exported!(1);
+    dollar_crate_exported!(2);
+
+    mod inner_inner {
+        #[macro_export]
+        macro_rules! exported {
+            () => ()
+        }
+    }
+
+    // After `exported` is defined
+    ::exported!();
+    crate::exported!();
+    dollar_crate_exported!(1);
+    dollar_crate_exported!(2);
+}
+
+exported!();
+
+fn main() {}
diff --git a/src/test/ui/imports/macro-paths.rs b/src/test/ui/imports/macro-paths.rs
new file mode 100644
index 0000000..cc584e0
--- /dev/null
+++ b/src/test/ui/imports/macro-paths.rs
@@ -0,0 +1,28 @@
+// aux-build:two_macros.rs
+
+extern crate two_macros;
+
+mod foo {
+    pub mod bar {
+        pub use two_macros::m;
+    }
+}
+
+fn f() {
+    use foo::*;
+    bar::m! { //~ ERROR ambiguous
+        mod bar { pub use two_macros::m; }
+    }
+}
+
+pub mod baz {
+    pub use two_macros::m;
+}
+
+fn g() {
+    baz::m! { //~ ERROR ambiguous
+        mod baz { pub use two_macros::m; }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/imports/macro-paths.stderr b/src/test/ui/imports/macro-paths.stderr
new file mode 100644
index 0000000..a5b9000
--- /dev/null
+++ b/src/test/ui/imports/macro-paths.stderr
@@ -0,0 +1,41 @@
+error[E0659]: `bar` is ambiguous (glob import vs macro-expanded name in the same module during import/macro resolution)
+  --> $DIR/macro-paths.rs:13:5
+   |
+LL |     bar::m! {
+   |     ^^^ ambiguous name
+   |
+note: `bar` could refer to the module defined here
+  --> $DIR/macro-paths.rs:14:9
+   |
+LL |         mod bar { pub use two_macros::m; }
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: `bar` could also refer to the module imported here
+  --> $DIR/macro-paths.rs:12:9
+   |
+LL |     use foo::*;
+   |         ^^^^^^
+   = help: consider adding an explicit import of `bar` to disambiguate
+
+error[E0659]: `baz` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
+  --> $DIR/macro-paths.rs:23:5
+   |
+LL |     baz::m! {
+   |     ^^^ ambiguous name
+   |
+note: `baz` could refer to the module defined here
+  --> $DIR/macro-paths.rs:24:9
+   |
+LL |         mod baz { pub use two_macros::m; }
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: `baz` could also refer to the module defined here
+  --> $DIR/macro-paths.rs:18:1
+   |
+LL | / pub mod baz {
+LL | |     pub use two_macros::m;
+LL | | }
+   | |_^
+   = help: use `crate::baz` to refer to this module unambiguously
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0659`.
diff --git a/src/test/ui/imports/macros.rs b/src/test/ui/imports/macros.rs
new file mode 100644
index 0000000..f2a22ad
--- /dev/null
+++ b/src/test/ui/imports/macros.rs
@@ -0,0 +1,41 @@
+// aux-build:two_macros.rs
+
+extern crate two_macros; // two identity macros `m` and `n`
+
+mod foo {
+    pub use two_macros::n as m;
+}
+
+mod m1 {
+    m!(use two_macros::*;);
+    use foo::m; // This shadows the glob import
+}
+
+mod m2 {
+    use two_macros::*;
+    m! { //~ ERROR ambiguous
+        use foo::m;
+    }
+}
+
+mod m3 {
+    use two_macros::m;
+    fn f() {
+        use two_macros::n as m; // This shadows the above import
+        m!();
+    }
+
+    fn g() {
+        m! { //~ ERROR ambiguous
+            use two_macros::n as m;
+        }
+    }
+}
+
+mod m4 {
+    macro_rules! m { () => {} }
+    use two_macros::m;
+    m!();
+}
+
+fn main() {}
diff --git a/src/test/ui/imports/macros.stderr b/src/test/ui/imports/macros.stderr
new file mode 100644
index 0000000..3b9e6fe
--- /dev/null
+++ b/src/test/ui/imports/macros.stderr
@@ -0,0 +1,39 @@
+error[E0659]: `m` is ambiguous (glob import vs macro-expanded name in the same module during import/macro resolution)
+  --> $DIR/macros.rs:16:5
+   |
+LL |     m! {
+   |     ^ ambiguous name
+   |
+note: `m` could refer to the macro imported here
+  --> $DIR/macros.rs:17:13
+   |
+LL |         use foo::m;
+   |             ^^^^^^
+note: `m` could also refer to the macro imported here
+  --> $DIR/macros.rs:15:9
+   |
+LL |     use two_macros::*;
+   |         ^^^^^^^^^^^^^
+   = help: consider adding an explicit import of `m` to disambiguate
+
+error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
+  --> $DIR/macros.rs:29:9
+   |
+LL |         m! {
+   |         ^ ambiguous name
+   |
+note: `m` could refer to the macro imported here
+  --> $DIR/macros.rs:30:17
+   |
+LL |             use two_macros::n as m;
+   |                 ^^^^^^^^^^^^^^^^^^
+note: `m` could also refer to the macro imported here
+  --> $DIR/macros.rs:22:9
+   |
+LL |     use two_macros::m;
+   |         ^^^^^^^^^^^^^
+   = help: use `self::m` to refer to this macro unambiguously
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0659`.
diff --git a/src/test/ui/imports/reexports.rs b/src/test/ui/imports/reexports.rs
new file mode 100644
index 0000000..b0a591b
--- /dev/null
+++ b/src/test/ui/imports/reexports.rs
@@ -0,0 +1,32 @@
+mod a {
+    fn foo() {}
+    mod foo {}
+
+    mod a {
+        pub use super::foo; //~ ERROR cannot be re-exported
+        pub use super::*; //~ ERROR must import something with the glob's visibility
+    }
+}
+
+mod b {
+    pub fn foo() {}
+    mod foo { pub struct S; }
+
+    pub mod a {
+        pub use super::foo; // This is OK since the value `foo` is visible enough.
+        fn f(_: foo::S) {} // `foo` is imported in the type namespace (but not `pub` re-exported).
+    }
+
+    pub mod b {
+        pub use super::*; // This is also OK since the value `foo` is visible enough.
+        fn f(_: foo::S) {} // Again, the module `foo` is imported (but not `pub` re-exported).
+    }
+}
+
+mod c {
+    // Test that `foo` is not re-exported.
+    use b::a::foo::S; //~ ERROR `foo`
+    use b::b::foo::S as T; //~ ERROR `foo`
+}
+
+fn main() {}
diff --git a/src/test/ui/imports/reexports.stderr b/src/test/ui/imports/reexports.stderr
new file mode 100644
index 0000000..7726343
--- /dev/null
+++ b/src/test/ui/imports/reexports.stderr
@@ -0,0 +1,34 @@
+error[E0364]: `foo` is private, and cannot be re-exported
+  --> $DIR/reexports.rs:6:17
+   |
+LL |         pub use super::foo;
+   |                 ^^^^^^^^^^
+   |
+note: consider marking `foo` as `pub` in the imported module
+  --> $DIR/reexports.rs:6:17
+   |
+LL |         pub use super::foo;
+   |                 ^^^^^^^^^^
+
+error: A non-empty glob must import something with the glob's visibility
+  --> $DIR/reexports.rs:7:17
+   |
+LL |         pub use super::*;
+   |                 ^^^^^^^^
+
+error[E0603]: module `foo` is private
+  --> $DIR/reexports.rs:28:15
+   |
+LL |     use b::a::foo::S;
+   |               ^^^
+
+error[E0603]: module `foo` is private
+  --> $DIR/reexports.rs:29:15
+   |
+LL |     use b::b::foo::S as T;
+   |               ^^^
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0364, E0603.
+For more information about an error, try `rustc --explain E0364`.
diff --git a/src/test/ui/imports/rfc-1560-warning-cycle.rs b/src/test/ui/imports/rfc-1560-warning-cycle.rs
new file mode 100644
index 0000000..cfa7179
--- /dev/null
+++ b/src/test/ui/imports/rfc-1560-warning-cycle.rs
@@ -0,0 +1,13 @@
+pub struct Foo;
+
+mod bar {
+    struct Foo;
+
+    mod baz {
+        use *;
+        use bar::*;
+        fn f(_: Foo) {} //~ ERROR `Foo` is ambiguous
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/imports/rfc-1560-warning-cycle.stderr b/src/test/ui/imports/rfc-1560-warning-cycle.stderr
new file mode 100644
index 0000000..d79c719
--- /dev/null
+++ b/src/test/ui/imports/rfc-1560-warning-cycle.stderr
@@ -0,0 +1,22 @@
+error[E0659]: `Foo` is ambiguous (glob import vs glob import in the same module)
+  --> $DIR/rfc-1560-warning-cycle.rs:9:17
+   |
+LL |         fn f(_: Foo) {}
+   |                 ^^^ ambiguous name
+   |
+note: `Foo` could refer to the struct imported here
+  --> $DIR/rfc-1560-warning-cycle.rs:7:13
+   |
+LL |         use *;
+   |             ^
+   = help: consider adding an explicit import of `Foo` to disambiguate
+note: `Foo` could also refer to the struct imported here
+  --> $DIR/rfc-1560-warning-cycle.rs:8:13
+   |
+LL |         use bar::*;
+   |             ^^^^^^
+   = help: consider adding an explicit import of `Foo` to disambiguate
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0659`.
diff --git a/src/test/ui/imports/shadow_builtin_macros.rs b/src/test/ui/imports/shadow_builtin_macros.rs
new file mode 100644
index 0000000..02c27d5
--- /dev/null
+++ b/src/test/ui/imports/shadow_builtin_macros.rs
@@ -0,0 +1,52 @@
+// aux-build:two_macros.rs
+
+mod foo {
+    extern crate two_macros;
+    pub use self::two_macros::m as panic;
+}
+
+mod m1 {
+    use foo::panic; // ok
+    fn f() { panic!(); }
+}
+
+mod m2 {
+    use foo::*;
+    fn f() { panic!(); } //~ ERROR ambiguous
+}
+
+mod m3 {
+    ::two_macros::m!(use foo::panic;);
+    fn f() { panic!(); } //~ ERROR ambiguous
+}
+
+mod m4 {
+    macro_rules! panic { () => {} } // ok
+    panic!();
+}
+
+mod m5 {
+    macro_rules! m { () => {
+        macro_rules! panic { () => {} }
+    } }
+    m!();
+    panic!(); //~ ERROR `panic` is ambiguous
+}
+
+#[macro_use(n)]
+extern crate two_macros;
+mod bar {
+    pub use two_macros::m as n;
+}
+
+mod m6 {
+    use bar::n; // ok
+    n!();
+}
+
+mod m7 {
+    use bar::*;
+    n!(); //~ ERROR ambiguous
+}
+
+fn main() {}
diff --git a/src/test/ui/imports/shadow_builtin_macros.stderr b/src/test/ui/imports/shadow_builtin_macros.stderr
new file mode 100644
index 0000000..c84226e
--- /dev/null
+++ b/src/test/ui/imports/shadow_builtin_macros.stderr
@@ -0,0 +1,67 @@
+error[E0659]: `panic` is ambiguous (glob import vs any other name from outer scope during import/macro resolution)
+  --> $DIR/shadow_builtin_macros.rs:15:14
+   |
+LL |     fn f() { panic!(); }
+   |              ^^^^^ ambiguous name
+   |
+   = note: `panic` could refer to a macro from prelude
+note: `panic` could also refer to the macro imported here
+  --> $DIR/shadow_builtin_macros.rs:14:9
+   |
+LL |     use foo::*;
+   |         ^^^^^^
+   = help: consider adding an explicit import of `panic` to disambiguate
+   = help: or use `self::panic` to refer to this macro unambiguously
+
+error[E0659]: `panic` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
+  --> $DIR/shadow_builtin_macros.rs:20:14
+   |
+LL |     fn f() { panic!(); }
+   |              ^^^^^ ambiguous name
+   |
+   = note: `panic` could refer to a macro from prelude
+note: `panic` could also refer to the macro imported here
+  --> $DIR/shadow_builtin_macros.rs:19:26
+   |
+LL |     ::two_macros::m!(use foo::panic;);
+   |                          ^^^^^^^^^^
+   = help: use `self::panic` to refer to this macro unambiguously
+
+error[E0659]: `panic` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
+  --> $DIR/shadow_builtin_macros.rs:33:5
+   |
+LL |     panic!();
+   |     ^^^^^ ambiguous name
+   |
+   = note: `panic` could refer to a macro from prelude
+note: `panic` could also refer to the macro defined here
+  --> $DIR/shadow_builtin_macros.rs:30:9
+   |
+LL |         macro_rules! panic { () => {} }
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     } }
+LL |     m!();
+   |     ----- in this macro invocation
+
+error[E0659]: `n` is ambiguous (glob import vs any other name from outer scope during import/macro resolution)
+  --> $DIR/shadow_builtin_macros.rs:49:5
+   |
+LL |     n!();
+   |     ^ ambiguous name
+   |
+note: `n` could refer to the macro imported here
+  --> $DIR/shadow_builtin_macros.rs:48:9
+   |
+LL |     use bar::*;
+   |         ^^^^^^
+   = help: consider adding an explicit import of `n` to disambiguate
+   = help: or use `self::n` to refer to this macro unambiguously
+note: `n` could also refer to the macro imported here
+  --> $DIR/shadow_builtin_macros.rs:36:13
+   |
+LL | #[macro_use(n)]
+   |             ^
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0659`.
diff --git a/src/test/ui/imports/unused-macro-use.rs b/src/test/ui/imports/unused-macro-use.rs
new file mode 100644
index 0000000..9f63eb4
--- /dev/null
+++ b/src/test/ui/imports/unused-macro-use.rs
@@ -0,0 +1,11 @@
+#![deny(unused)]
+
+#[macro_use] //~ ERROR unused `#[macro_use]` import
+extern crate core;
+
+#[macro_use(
+    panic //~ ERROR unused `#[macro_use]` import
+)]
+extern crate core as core_2;
+
+fn main() {}
diff --git a/src/test/ui/imports/unused-macro-use.stderr b/src/test/ui/imports/unused-macro-use.stderr
new file mode 100644
index 0000000..7868314
--- /dev/null
+++ b/src/test/ui/imports/unused-macro-use.stderr
@@ -0,0 +1,21 @@
+error: unused `#[macro_use]` import
+  --> $DIR/unused-macro-use.rs:3:1
+   |
+LL | #[macro_use]
+   | ^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/unused-macro-use.rs:1:9
+   |
+LL | #![deny(unused)]
+   |         ^^^^^^
+   = note: #[deny(unused_imports)] implied by #[deny(unused)]
+
+error: unused `#[macro_use]` import
+  --> $DIR/unused-macro-use.rs:7:5
+   |
+LL |     panic
+   |     ^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/imports/unused.rs b/src/test/ui/imports/unused.rs
new file mode 100644
index 0000000..c22e95e
--- /dev/null
+++ b/src/test/ui/imports/unused.rs
@@ -0,0 +1,27 @@
+#![deny(unused)]
+
+mod foo {
+    fn f() {}
+
+    mod m1 {
+        pub(super) use super::f; //~ ERROR unused
+    }
+
+    mod m2 {
+        #[allow(unused)]
+        use super::m1::*; // (despite this glob import)
+    }
+
+    mod m3 {
+        pub(super) use super::f; // Check that this is counted as used (cf. issue #36249).
+    }
+
+    pub mod m4 {
+        use super::m3::*;
+        pub fn g() { f(); }
+    }
+}
+
+fn main() {
+    foo::m4::g();
+}
diff --git a/src/test/ui/imports/unused.stderr b/src/test/ui/imports/unused.stderr
new file mode 100644
index 0000000..259ed95
--- /dev/null
+++ b/src/test/ui/imports/unused.stderr
@@ -0,0 +1,15 @@
+error: unused import: `super::f`
+  --> $DIR/unused.rs:7:24
+   |
+LL |         pub(super) use super::f;
+   |                        ^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/unused.rs:1:9
+   |
+LL | #![deny(unused)]
+   |         ^^^^^^
+   = note: #[deny(unused_imports)] implied by #[deny(unused)]
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/impossible_range.rs b/src/test/ui/impossible_range.rs
new file mode 100644
index 0000000..6345af0
--- /dev/null
+++ b/src/test/ui/impossible_range.rs
@@ -0,0 +1,17 @@
+// Make sure that invalid ranges generate an error during HIR lowering, not an ICE
+
+pub fn main() {
+    ..;
+    0..;
+    ..1;
+    0..1;
+    ..=; //~ERROR inclusive range with no end
+         //~^HELP bounded at the end
+}
+
+fn _foo1() {
+    ..=1;
+    0..=1;
+    0..=; //~ERROR inclusive range with no end
+          //~^HELP bounded at the end
+}
diff --git a/src/test/ui/impossible_range.stderr b/src/test/ui/impossible_range.stderr
new file mode 100644
index 0000000..091fe37
--- /dev/null
+++ b/src/test/ui/impossible_range.stderr
@@ -0,0 +1,19 @@
+error[E0586]: inclusive range with no end
+  --> $DIR/impossible_range.rs:8:8
+   |
+LL |     ..=;
+   |        ^
+   |
+   = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
+
+error[E0586]: inclusive range with no end
+  --> $DIR/impossible_range.rs:15:9
+   |
+LL |     0..=;
+   |         ^
+   |
+   = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0586`.
diff --git a/src/test/ui/in-band-lifetimes/E0687.rs b/src/test/ui/in-band-lifetimes/E0687.rs
new file mode 100644
index 0000000..2e262dd
--- /dev/null
+++ b/src/test/ui/in-band-lifetimes/E0687.rs
@@ -0,0 +1,16 @@
+#![allow(warnings)]
+#![feature(in_band_lifetimes)]
+
+fn foo(x: fn(&'a u32)) {} //~ ERROR must be explicitly
+
+fn bar(x: &Fn(&'a u32)) {} //~ ERROR must be explicitly
+
+fn baz(x: fn(&'a u32), y: &'a u32) {} //~ ERROR must be explicitly
+
+struct Foo<'a> { x: &'a u32 }
+
+impl Foo<'a> {
+    fn bar(&self, x: fn(&'a u32)) {} //~ ERROR must be explicitly
+}
+
+fn main() {}
diff --git a/src/test/ui/in-band-lifetimes/E0687.stderr b/src/test/ui/in-band-lifetimes/E0687.stderr
new file mode 100644
index 0000000..7aea2f2
--- /dev/null
+++ b/src/test/ui/in-band-lifetimes/E0687.stderr
@@ -0,0 +1,27 @@
+error[E0687]: lifetimes used in `fn` or `Fn` syntax must be explicitly declared using `<...>` binders
+  --> $DIR/E0687.rs:4:15
+   |
+LL | fn foo(x: fn(&'a u32)) {}
+   |               ^^ in-band lifetime definition
+
+error[E0687]: lifetimes used in `fn` or `Fn` syntax must be explicitly declared using `<...>` binders
+  --> $DIR/E0687.rs:6:16
+   |
+LL | fn bar(x: &Fn(&'a u32)) {}
+   |                ^^ in-band lifetime definition
+
+error[E0687]: lifetimes used in `fn` or `Fn` syntax must be explicitly declared using `<...>` binders
+  --> $DIR/E0687.rs:8:15
+   |
+LL | fn baz(x: fn(&'a u32), y: &'a u32) {}
+   |               ^^ in-band lifetime definition
+
+error[E0687]: lifetimes used in `fn` or `Fn` syntax must be explicitly declared using `<...>` binders
+  --> $DIR/E0687.rs:13:26
+   |
+LL |     fn bar(&self, x: fn(&'a u32)) {}
+   |                          ^^ in-band lifetime definition
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0687`.
diff --git a/src/test/ui/in-band-lifetimes/E0687_where.rs b/src/test/ui/in-band-lifetimes/E0687_where.rs
new file mode 100644
index 0000000..6cf8053
--- /dev/null
+++ b/src/test/ui/in-band-lifetimes/E0687_where.rs
@@ -0,0 +1,8 @@
+#![allow(warnings)]
+#![feature(in_band_lifetimes)]
+
+fn bar<F>(x: &F) where F: Fn(&'a u32) {} //~ ERROR must be explicitly
+
+fn baz(x: &impl Fn(&'a u32)) {} //~ ERROR must be explicitly
+
+fn main() {}
diff --git a/src/test/ui/in-band-lifetimes/E0687_where.stderr b/src/test/ui/in-band-lifetimes/E0687_where.stderr
new file mode 100644
index 0000000..af0f966
--- /dev/null
+++ b/src/test/ui/in-band-lifetimes/E0687_where.stderr
@@ -0,0 +1,15 @@
+error[E0687]: lifetimes used in `fn` or `Fn` syntax must be explicitly declared using `<...>` binders
+  --> $DIR/E0687_where.rs:4:31
+   |
+LL | fn bar<F>(x: &F) where F: Fn(&'a u32) {}
+   |                               ^^ in-band lifetime definition
+
+error[E0687]: lifetimes used in `fn` or `Fn` syntax must be explicitly declared using `<...>` binders
+  --> $DIR/E0687_where.rs:6:21
+   |
+LL | fn baz(x: &impl Fn(&'a u32)) {}
+   |                     ^^ in-band lifetime definition
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0687`.
diff --git a/src/test/ui/in-band-lifetimes/E0688.rs b/src/test/ui/in-band-lifetimes/E0688.rs
new file mode 100644
index 0000000..a4e1f01
--- /dev/null
+++ b/src/test/ui/in-band-lifetimes/E0688.rs
@@ -0,0 +1,16 @@
+#![allow(warnings)]
+#![feature(in_band_lifetimes)]
+
+fn foo<'a>(x: &'a u32, y: &'b u32) {} //~ ERROR cannot mix
+
+struct Foo<'a> { x: &'a u32 }
+
+impl Foo<'a> {
+    fn bar<'b>(x: &'a u32, y: &'b u32, z: &'c u32) {} //~ ERROR cannot mix
+}
+
+impl<'b> Foo<'a> { //~ ERROR cannot mix
+    fn baz() {}
+}
+
+fn main() {}
diff --git a/src/test/ui/in-band-lifetimes/E0688.stderr b/src/test/ui/in-band-lifetimes/E0688.stderr
new file mode 100644
index 0000000..afefcd9
--- /dev/null
+++ b/src/test/ui/in-band-lifetimes/E0688.stderr
@@ -0,0 +1,27 @@
+error[E0688]: cannot mix in-band and explicit lifetime definitions
+  --> $DIR/E0688.rs:4:28
+   |
+LL | fn foo<'a>(x: &'a u32, y: &'b u32) {}
+   |        --                  ^^ in-band lifetime definition here
+   |        |
+   |        explicit lifetime definition here
+
+error[E0688]: cannot mix in-band and explicit lifetime definitions
+  --> $DIR/E0688.rs:9:44
+   |
+LL |     fn bar<'b>(x: &'a u32, y: &'b u32, z: &'c u32) {}
+   |            --                              ^^ in-band lifetime definition here
+   |            |
+   |            explicit lifetime definition here
+
+error[E0688]: cannot mix in-band and explicit lifetime definitions
+  --> $DIR/E0688.rs:12:14
+   |
+LL | impl<'b> Foo<'a> {
+   |      --      ^^ in-band lifetime definition here
+   |      |
+   |      explicit lifetime definition here
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0688`.
diff --git a/src/test/ui/in-band-lifetimes/elided-lifetimes.fixed b/src/test/ui/in-band-lifetimes/elided-lifetimes.fixed
new file mode 100644
index 0000000..29c570d
--- /dev/null
+++ b/src/test/ui/in-band-lifetimes/elided-lifetimes.fixed
@@ -0,0 +1,87 @@
+// run-rustfix
+// edition:2018
+
+#![allow(unused)]
+#![deny(elided_lifetimes_in_paths)]
+//~^ NOTE lint level defined here
+
+use std::cell::{RefCell, Ref};
+
+
+struct Foo<'a> { x: &'a u32 }
+
+fn foo(x: &Foo<'_>) {
+    //~^ ERROR hidden lifetime parameters in types are deprecated
+    //~| HELP indicate the anonymous lifetime
+}
+
+fn bar(x: &Foo<'_>) {}
+
+
+struct Wrapped<'a>(&'a str);
+
+struct WrappedWithBow<'a> {
+    gift: &'a str
+}
+
+struct MatchedSet<'a, 'b> {
+    one: &'a str,
+    another: &'b str,
+}
+
+fn wrap_gift(gift: &str) -> Wrapped<'_> {
+    //~^ ERROR hidden lifetime parameters in types are deprecated
+    //~| HELP indicate the anonymous lifetime
+    Wrapped(gift)
+}
+
+fn wrap_gift_with_bow(gift: &str) -> WrappedWithBow<'_> {
+    //~^ ERROR hidden lifetime parameters in types are deprecated
+    //~| HELP indicate the anonymous lifetime
+    WrappedWithBow { gift }
+}
+
+fn inspect_matched_set(set: MatchedSet<'_, '_>) {
+    //~^ ERROR hidden lifetime parameters in types are deprecated
+    //~| HELP indicate the anonymous lifetime
+    println!("{} {}", set.one, set.another);
+}
+
+macro_rules! autowrapper {
+    ($type_name:ident, $fn_name:ident, $lt:lifetime) => {
+        struct $type_name<$lt> {
+            gift: &$lt str
+        }
+
+        fn $fn_name(gift: &str) -> $type_name<'_> {
+            //~^ ERROR hidden lifetime parameters in types are deprecated
+            //~| HELP indicate the anonymous lifetime
+            $type_name { gift }
+        }
+    }
+}
+
+autowrapper!(Autowrapped, autowrap_gift, 'a);
+//~^ NOTE in this expansion of autowrapper!
+//~| NOTE in this expansion of autowrapper!
+
+macro_rules! anytuple_ref_ty {
+    ($($types:ty),*) => {
+        Ref<'_, ($($types),*)>
+        //~^ ERROR hidden lifetime parameters in types are deprecated
+        //~| HELP indicate the anonymous lifetime
+    }
+}
+
+fn main() {
+    let honesty = RefCell::new((4, 'e'));
+    let loyalty: Ref<'_, (u32, char)> = honesty.borrow();
+    //~^ ERROR hidden lifetime parameters in types are deprecated
+    //~| HELP indicate the anonymous lifetime
+    let generosity = Ref::map(loyalty, |t| &t.0);
+
+    let laughter = RefCell::new((true, "magic"));
+    let yellow: anytuple_ref_ty!(bool, &str) = laughter.borrow();
+    //~^ NOTE in this expansion of anytuple_ref_ty!
+    //~| NOTE in this expansion of anytuple_ref_ty!
+}
diff --git a/src/test/ui/in-band-lifetimes/elided-lifetimes.rs b/src/test/ui/in-band-lifetimes/elided-lifetimes.rs
new file mode 100644
index 0000000..e59c9b4
--- /dev/null
+++ b/src/test/ui/in-band-lifetimes/elided-lifetimes.rs
@@ -0,0 +1,87 @@
+// run-rustfix
+// edition:2018
+
+#![allow(unused)]
+#![deny(elided_lifetimes_in_paths)]
+//~^ NOTE lint level defined here
+
+use std::cell::{RefCell, Ref};
+
+
+struct Foo<'a> { x: &'a u32 }
+
+fn foo(x: &Foo) {
+    //~^ ERROR hidden lifetime parameters in types are deprecated
+    //~| HELP indicate the anonymous lifetime
+}
+
+fn bar(x: &Foo<'_>) {}
+
+
+struct Wrapped<'a>(&'a str);
+
+struct WrappedWithBow<'a> {
+    gift: &'a str
+}
+
+struct MatchedSet<'a, 'b> {
+    one: &'a str,
+    another: &'b str,
+}
+
+fn wrap_gift(gift: &str) -> Wrapped {
+    //~^ ERROR hidden lifetime parameters in types are deprecated
+    //~| HELP indicate the anonymous lifetime
+    Wrapped(gift)
+}
+
+fn wrap_gift_with_bow(gift: &str) -> WrappedWithBow {
+    //~^ ERROR hidden lifetime parameters in types are deprecated
+    //~| HELP indicate the anonymous lifetime
+    WrappedWithBow { gift }
+}
+
+fn inspect_matched_set(set: MatchedSet) {
+    //~^ ERROR hidden lifetime parameters in types are deprecated
+    //~| HELP indicate the anonymous lifetime
+    println!("{} {}", set.one, set.another);
+}
+
+macro_rules! autowrapper {
+    ($type_name:ident, $fn_name:ident, $lt:lifetime) => {
+        struct $type_name<$lt> {
+            gift: &$lt str
+        }
+
+        fn $fn_name(gift: &str) -> $type_name {
+            //~^ ERROR hidden lifetime parameters in types are deprecated
+            //~| HELP indicate the anonymous lifetime
+            $type_name { gift }
+        }
+    }
+}
+
+autowrapper!(Autowrapped, autowrap_gift, 'a);
+//~^ NOTE in this expansion of autowrapper!
+//~| NOTE in this expansion of autowrapper!
+
+macro_rules! anytuple_ref_ty {
+    ($($types:ty),*) => {
+        Ref<($($types),*)>
+        //~^ ERROR hidden lifetime parameters in types are deprecated
+        //~| HELP indicate the anonymous lifetime
+    }
+}
+
+fn main() {
+    let honesty = RefCell::new((4, 'e'));
+    let loyalty: Ref<(u32, char)> = honesty.borrow();
+    //~^ ERROR hidden lifetime parameters in types are deprecated
+    //~| HELP indicate the anonymous lifetime
+    let generosity = Ref::map(loyalty, |t| &t.0);
+
+    let laughter = RefCell::new((true, "magic"));
+    let yellow: anytuple_ref_ty!(bool, &str) = laughter.borrow();
+    //~^ NOTE in this expansion of anytuple_ref_ty!
+    //~| NOTE in this expansion of anytuple_ref_ty!
+}
diff --git a/src/test/ui/in-band-lifetimes/elided-lifetimes.stderr b/src/test/ui/in-band-lifetimes/elided-lifetimes.stderr
new file mode 100644
index 0000000..5c50d7e
--- /dev/null
+++ b/src/test/ui/in-band-lifetimes/elided-lifetimes.stderr
@@ -0,0 +1,56 @@
+error: hidden lifetime parameters in types are deprecated
+  --> $DIR/elided-lifetimes.rs:13:12
+   |
+LL | fn foo(x: &Foo) {
+   |            ^^^- help: indicate the anonymous lifetime: `<'_>`
+   |
+note: lint level defined here
+  --> $DIR/elided-lifetimes.rs:5:9
+   |
+LL | #![deny(elided_lifetimes_in_paths)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: hidden lifetime parameters in types are deprecated
+  --> $DIR/elided-lifetimes.rs:32:29
+   |
+LL | fn wrap_gift(gift: &str) -> Wrapped {
+   |                             ^^^^^^^- help: indicate the anonymous lifetime: `<'_>`
+
+error: hidden lifetime parameters in types are deprecated
+  --> $DIR/elided-lifetimes.rs:38:38
+   |
+LL | fn wrap_gift_with_bow(gift: &str) -> WrappedWithBow {
+   |                                      ^^^^^^^^^^^^^^- help: indicate the anonymous lifetime: `<'_>`
+
+error: hidden lifetime parameters in types are deprecated
+  --> $DIR/elided-lifetimes.rs:44:29
+   |
+LL | fn inspect_matched_set(set: MatchedSet) {
+   |                             ^^^^^^^^^^- help: indicate the anonymous lifetimes: `<'_, '_>`
+
+error: hidden lifetime parameters in types are deprecated
+  --> $DIR/elided-lifetimes.rs:56:36
+   |
+LL |         fn $fn_name(gift: &str) -> $type_name {
+   |                                    ^^^^^^^^^^- help: indicate the anonymous lifetime: `<'_>`
+...
+LL | autowrapper!(Autowrapped, autowrap_gift, 'a);
+   | --------------------------------------------- in this macro invocation
+
+error: hidden lifetime parameters in types are deprecated
+  --> $DIR/elided-lifetimes.rs:78:18
+   |
+LL |     let loyalty: Ref<(u32, char)> = honesty.borrow();
+   |                  ^^^^^^^^^^^^^^^^ help: indicate the anonymous lifetime: `Ref<'_, (u32, char)>`
+
+error: hidden lifetime parameters in types are deprecated
+  --> $DIR/elided-lifetimes.rs:70:9
+   |
+LL |         Ref<($($types),*)>
+   |         ^^^^^^^^^^^^^^^^^^ help: indicate the anonymous lifetime: `Ref<'_, ($($types),*)>`
+...
+LL |     let yellow: anytuple_ref_ty!(bool, &str) = laughter.borrow();
+   |                 ---------------------------- in this macro invocation
+
+error: aborting due to 7 previous errors
+
diff --git a/src/test/ui/in-band-lifetimes/mismatched.rs b/src/test/ui/in-band-lifetimes/mismatched.rs
new file mode 100644
index 0000000..11c41ea
--- /dev/null
+++ b/src/test/ui/in-band-lifetimes/mismatched.rs
@@ -0,0 +1,8 @@
+#![allow(warnings)]
+#![feature(in_band_lifetimes)]
+
+fn foo(x: &'a u32, y: &u32) -> &'a u32 { y } //~ ERROR explicit lifetime required
+
+fn foo2(x: &'a u32, y: &'b u32) -> &'a u32 { y } //~ ERROR lifetime mismatch
+
+fn main() {}
diff --git a/src/test/ui/in-band-lifetimes/mismatched.stderr b/src/test/ui/in-band-lifetimes/mismatched.stderr
new file mode 100644
index 0000000..9d33aaf
--- /dev/null
+++ b/src/test/ui/in-band-lifetimes/mismatched.stderr
@@ -0,0 +1,20 @@
+error[E0621]: explicit lifetime required in the type of `y`
+  --> $DIR/mismatched.rs:4:42
+   |
+LL | fn foo(x: &'a u32, y: &u32) -> &'a u32 { y }
+   |                       ----               ^ lifetime `'a` required
+   |                       |
+   |                       help: add explicit lifetime `'a` to the type of `y`: `&'a u32`
+
+error[E0623]: lifetime mismatch
+  --> $DIR/mismatched.rs:6:46
+   |
+LL | fn foo2(x: &'a u32, y: &'b u32) -> &'a u32 { y }
+   |                        -------     -------   ^ ...but data from `y` is returned here
+   |                        |
+   |                        this parameter and the return type are declared with different lifetimes...
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0621, E0623.
+For more information about an error, try `rustc --explain E0621`.
diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait.rs b/src/test/ui/in-band-lifetimes/mismatched_trait.rs
new file mode 100644
index 0000000..221f4fc
--- /dev/null
+++ b/src/test/ui/in-band-lifetimes/mismatched_trait.rs
@@ -0,0 +1,10 @@
+#![allow(warnings)]
+#![feature(in_band_lifetimes)]
+
+trait Get {
+    fn baz(&self, x: &'a u32, y: &u32) -> &'a u32 {
+        y //~ ERROR explicit lifetime required
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait.stderr b/src/test/ui/in-band-lifetimes/mismatched_trait.stderr
new file mode 100644
index 0000000..ac66daa
--- /dev/null
+++ b/src/test/ui/in-band-lifetimes/mismatched_trait.stderr
@@ -0,0 +1,11 @@
+error[E0621]: explicit lifetime required in the type of `y`
+  --> $DIR/mismatched_trait.rs:6:9
+   |
+LL |     fn baz(&self, x: &'a u32, y: &u32) -> &'a u32 {
+   |                                  ---- help: add explicit lifetime `'a` to the type of `y`: `&'a u32`
+LL |         y
+   |         ^ lifetime `'a` required
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.rs b/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.rs
new file mode 100644
index 0000000..d4535ac
--- /dev/null
+++ b/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.rs
@@ -0,0 +1,14 @@
+use std::ops::Deref;
+trait Trait {}
+
+struct Struct;
+
+impl Deref for Struct {
+    type Target = Trait;
+    fn deref(&self) -> &Trait {
+        unimplemented!();
+    }
+}
+//~^^^^ ERROR cannot infer an appropriate lifetime for lifetime parameter
+
+fn main() {}
diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr b/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr
new file mode 100644
index 0000000..fbd312a
--- /dev/null
+++ b/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr
@@ -0,0 +1,21 @@
+error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in generic type due to conflicting requirements
+  --> $DIR/mismatched_trait_impl-2.rs:8:5
+   |
+LL |     fn deref(&self) -> &Trait {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 8:5...
+  --> $DIR/mismatched_trait_impl-2.rs:8:5
+   |
+LL | /     fn deref(&self) -> &Trait {
+LL | |         unimplemented!();
+LL | |     }
+   | |_____^
+   = note: ...but the lifetime must also be valid for the static lifetime...
+   = note: ...so that the method type is compatible with trait:
+           expected fn(&Struct) -> &(dyn Trait + 'static)
+              found fn(&Struct) -> &dyn Trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0495`.
diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait_impl.rs b/src/test/ui/in-band-lifetimes/mismatched_trait_impl.rs
new file mode 100644
index 0000000..654d2bd
--- /dev/null
+++ b/src/test/ui/in-band-lifetimes/mismatched_trait_impl.rs
@@ -0,0 +1,14 @@
+#![allow(warnings)]
+#![feature(in_band_lifetimes)]
+
+trait Get {
+    fn foo(&self, x: &'a u32, y: &u32) -> &'a u32;
+}
+
+impl Get for i32 {
+    fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { //~ ERROR cannot infer
+        x
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr b/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr
new file mode 100644
index 0000000..a80ebaf
--- /dev/null
+++ b/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr
@@ -0,0 +1,25 @@
+error[E0495]: cannot infer an appropriate lifetime for lifetime parameter 'a in generic type due to conflicting requirements
+  --> $DIR/mismatched_trait_impl.rs:9:5
+   |
+LL |     fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the method body at 9:5...
+  --> $DIR/mismatched_trait_impl.rs:9:5
+   |
+LL | /     fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 {
+LL | |         x
+LL | |     }
+   | |_____^
+note: ...but the lifetime must also be valid for the lifetime 'a as defined on the method body at 9:32...
+  --> $DIR/mismatched_trait_impl.rs:9:32
+   |
+LL |     fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 {
+   |                                ^^
+   = note: ...so that the method type is compatible with trait:
+           expected fn(&i32, &'a u32, &u32) -> &'a u32
+              found fn(&i32, &u32, &u32) -> &u32
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0495`.
diff --git a/src/test/ui/in-band-lifetimes/mut_while_borrow.nll.stderr b/src/test/ui/in-band-lifetimes/mut_while_borrow.nll.stderr
new file mode 100644
index 0000000..f96ff9d
--- /dev/null
+++ b/src/test/ui/in-band-lifetimes/mut_while_borrow.nll.stderr
@@ -0,0 +1,13 @@
+error[E0506]: cannot assign to `p` because it is borrowed
+  --> $DIR/mut_while_borrow.rs:9:5
+   |
+LL |     let r = foo(&p);
+   |                 -- borrow of `p` occurs here
+LL |     p += 1;
+   |     ^^^^^^ assignment to borrowed `p` occurs here
+LL |     println!("{}", r);
+   |                    - borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/in-band-lifetimes/mut_while_borrow.rs b/src/test/ui/in-band-lifetimes/mut_while_borrow.rs
new file mode 100644
index 0000000..97e8ed0
--- /dev/null
+++ b/src/test/ui/in-band-lifetimes/mut_while_borrow.rs
@@ -0,0 +1,11 @@
+#![allow(warnings)]
+#![feature(in_band_lifetimes)]
+
+fn foo(x: &'a u32) -> &'a u32 { x }
+
+fn main() {
+    let mut p = 3;
+    let r = foo(&p);
+    p += 1; //~ ERROR cannot assign to `p` because it is borrowed
+    println!("{}", r);
+}
diff --git a/src/test/ui/in-band-lifetimes/mut_while_borrow.stderr b/src/test/ui/in-band-lifetimes/mut_while_borrow.stderr
new file mode 100644
index 0000000..556c15d
--- /dev/null
+++ b/src/test/ui/in-band-lifetimes/mut_while_borrow.stderr
@@ -0,0 +1,11 @@
+error[E0506]: cannot assign to `p` because it is borrowed
+  --> $DIR/mut_while_borrow.rs:9:5
+   |
+LL |     let r = foo(&p);
+   |                  - borrow of `p` occurs here
+LL |     p += 1;
+   |     ^^^^^^ assignment to borrowed `p` occurs here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/in-band-lifetimes/no_in_band_in_struct.rs b/src/test/ui/in-band-lifetimes/no_in_band_in_struct.rs
new file mode 100644
index 0000000..9b0c0cd
--- /dev/null
+++ b/src/test/ui/in-band-lifetimes/no_in_band_in_struct.rs
@@ -0,0 +1,12 @@
+#![allow(warnings)]
+#![feature(in_band_lifetimes)]
+
+struct Foo {
+    x: &'test u32, //~ ERROR undeclared lifetime
+}
+
+enum Bar {
+    Baz(&'test u32), //~ ERROR undeclared lifetime
+}
+
+fn main() {}
diff --git a/src/test/ui/in-band-lifetimes/no_in_band_in_struct.stderr b/src/test/ui/in-band-lifetimes/no_in_band_in_struct.stderr
new file mode 100644
index 0000000..a270dd0
--- /dev/null
+++ b/src/test/ui/in-band-lifetimes/no_in_band_in_struct.stderr
@@ -0,0 +1,15 @@
+error[E0261]: use of undeclared lifetime name `'test`
+  --> $DIR/no_in_band_in_struct.rs:5:9
+   |
+LL |     x: &'test u32,
+   |         ^^^^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'test`
+  --> $DIR/no_in_band_in_struct.rs:9:10
+   |
+LL |     Baz(&'test u32),
+   |          ^^^^^ undeclared lifetime
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0261`.
diff --git a/src/test/ui/in-band-lifetimes/no_introducing_in_band_in_locals.rs b/src/test/ui/in-band-lifetimes/no_introducing_in_band_in_locals.rs
new file mode 100644
index 0000000..c1c40af
--- /dev/null
+++ b/src/test/ui/in-band-lifetimes/no_introducing_in_band_in_locals.rs
@@ -0,0 +1,13 @@
+#![allow(warnings)]
+#![feature(in_band_lifetimes)]
+
+fn foo(x: &u32) {
+    let y: &'test u32 = x; //~ ERROR use of undeclared lifetime
+}
+
+fn foo2(x: &u32) {}
+fn bar() {
+    let y: fn(&'test u32) = foo2; //~ ERROR use of undeclared lifetime
+}
+
+fn main() {}
diff --git a/src/test/ui/in-band-lifetimes/no_introducing_in_band_in_locals.stderr b/src/test/ui/in-band-lifetimes/no_introducing_in_band_in_locals.stderr
new file mode 100644
index 0000000..c307066
--- /dev/null
+++ b/src/test/ui/in-band-lifetimes/no_introducing_in_band_in_locals.stderr
@@ -0,0 +1,15 @@
+error[E0261]: use of undeclared lifetime name `'test`
+  --> $DIR/no_introducing_in_band_in_locals.rs:5:13
+   |
+LL |     let y: &'test u32 = x;
+   |             ^^^^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'test`
+  --> $DIR/no_introducing_in_band_in_locals.rs:10:16
+   |
+LL |     let y: fn(&'test u32) = foo2;
+   |                ^^^^^ undeclared lifetime
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0261`.
diff --git a/src/test/ui/in-band-lifetimes/shadow.rs b/src/test/ui/in-band-lifetimes/shadow.rs
new file mode 100644
index 0000000..27b5d57
--- /dev/null
+++ b/src/test/ui/in-band-lifetimes/shadow.rs
@@ -0,0 +1,11 @@
+#![allow(warnings)]
+#![feature(in_band_lifetimes)]
+
+struct Foo<T>(T);
+
+impl Foo<&'s u8> {
+    fn bar<'s>(&self, x: &'s u8) {} //~ ERROR shadows a lifetime name
+    fn baz(x: for<'s> fn(&'s u32)) {} //~ ERROR shadows a lifetime name
+}
+
+fn main() {}
diff --git a/src/test/ui/in-band-lifetimes/shadow.stderr b/src/test/ui/in-band-lifetimes/shadow.stderr
new file mode 100644
index 0000000..a0a15d3
--- /dev/null
+++ b/src/test/ui/in-band-lifetimes/shadow.stderr
@@ -0,0 +1,20 @@
+error[E0496]: lifetime name `'s` shadows a lifetime name that is already in scope
+  --> $DIR/shadow.rs:7:12
+   |
+LL | impl Foo<&'s u8> {
+   |           -- first declared here
+LL |     fn bar<'s>(&self, x: &'s u8) {}
+   |            ^^ lifetime 's already in scope
+
+error[E0496]: lifetime name `'s` shadows a lifetime name that is already in scope
+  --> $DIR/shadow.rs:8:19
+   |
+LL | impl Foo<&'s u8> {
+   |           -- first declared here
+LL |     fn bar<'s>(&self, x: &'s u8) {}
+LL |     fn baz(x: for<'s> fn(&'s u32)) {}
+   |                   ^^ lifetime 's already in scope
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0496`.
diff --git a/src/test/ui/inaccessible-test-modules.rs b/src/test/ui/inaccessible-test-modules.rs
new file mode 100644
index 0000000..7095ec2
--- /dev/null
+++ b/src/test/ui/inaccessible-test-modules.rs
@@ -0,0 +1,9 @@
+// compile-flags:--test
+
+// the `--test` harness creates modules with these textual names, but
+// they should be inaccessible from normal code.
+use __test as x; //~ ERROR unresolved import `__test`
+use __test_reexports as y; //~ ERROR unresolved import `__test_reexports`
+
+#[test]
+fn baz() {}
diff --git a/src/test/ui/inaccessible-test-modules.stderr b/src/test/ui/inaccessible-test-modules.stderr
new file mode 100644
index 0000000..b6a817e
--- /dev/null
+++ b/src/test/ui/inaccessible-test-modules.stderr
@@ -0,0 +1,21 @@
+error[E0432]: unresolved import `__test`
+  --> $DIR/inaccessible-test-modules.rs:5:5
+   |
+LL | use __test as x;
+   |     ------^^^^^
+   |     |
+   |     no `__test` in the root
+   |     help: a similar name exists in the module: `test`
+
+error[E0432]: unresolved import `__test_reexports`
+  --> $DIR/inaccessible-test-modules.rs:6:5
+   |
+LL | use __test_reexports as y;
+   |     ----------------^^^^^
+   |     |
+   |     no `__test_reexports` in the root
+   |     help: a similar name exists in the module: `__test_reexports`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/include-macros/file.txt b/src/test/ui/include-macros/file.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/test/ui/include-macros/file.txt
diff --git a/src/test/ui/include-macros/mismatched-types.rs b/src/test/ui/include-macros/mismatched-types.rs
new file mode 100644
index 0000000..83fa378
--- /dev/null
+++ b/src/test/ui/include-macros/mismatched-types.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let b: &[u8] = include_str!("file.txt");    //~ ERROR mismatched types
+    let s: &str = include_bytes!("file.txt");   //~ ERROR mismatched types
+}
diff --git a/src/test/ui/include-macros/mismatched-types.stderr b/src/test/ui/include-macros/mismatched-types.stderr
new file mode 100644
index 0000000..33204f1
--- /dev/null
+++ b/src/test/ui/include-macros/mismatched-types.stderr
@@ -0,0 +1,21 @@
+error[E0308]: mismatched types
+  --> $DIR/mismatched-types.rs:2:20
+   |
+LL |     let b: &[u8] = include_str!("file.txt");
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^ expected slice, found str
+   |
+   = note: expected type `&[u8]`
+              found type `&'static str`
+
+error[E0308]: mismatched types
+  --> $DIR/mismatched-types.rs:3:19
+   |
+LL |     let s: &str = include_bytes!("file.txt");
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected str, found array of 0 elements
+   |
+   = note: expected type `&str`
+              found type `&'static [u8; 0]`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/index-bot.rs b/src/test/ui/index-bot.rs
new file mode 100644
index 0000000..e69c401
--- /dev/null
+++ b/src/test/ui/index-bot.rs
@@ -0,0 +1,3 @@
+fn main() {
+    (return)[0]; //~ ERROR cannot index into a value of type `!`
+}
diff --git a/src/test/ui/index-bot.stderr b/src/test/ui/index-bot.stderr
new file mode 100644
index 0000000..b5d7829
--- /dev/null
+++ b/src/test/ui/index-bot.stderr
@@ -0,0 +1,9 @@
+error[E0608]: cannot index into a value of type `!`
+  --> $DIR/index-bot.rs:2:5
+   |
+LL |     (return)[0];
+   |     ^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0608`.
diff --git a/src/test/ui/index-help.rs b/src/test/ui/index-help.rs
new file mode 100644
index 0000000..66571ec
--- /dev/null
+++ b/src/test/ui/index-help.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let x = vec![1];
+    x[0i32]; //~ ERROR E0277
+}
diff --git a/src/test/ui/index-help.stderr b/src/test/ui/index-help.stderr
new file mode 100644
index 0000000..cd4d835
--- /dev/null
+++ b/src/test/ui/index-help.stderr
@@ -0,0 +1,12 @@
+error[E0277]: the type `[{integer}]` cannot be indexed by `i32`
+  --> $DIR/index-help.rs:3:5
+   |
+LL |     x[0i32];
+   |     ^^^^^^^ slice indices are of type `usize` or ranges of `usize`
+   |
+   = help: the trait `std::slice::SliceIndex<[{integer}]>` is not implemented for `i32`
+   = note: required because of the requirements on the impl of `std::ops::Index<i32>` for `std::vec::Vec<{integer}>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/index_message.rs b/src/test/ui/index_message.rs
new file mode 100644
index 0000000..87e0cde
--- /dev/null
+++ b/src/test/ui/index_message.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let z = ();
+    let _ = z[0]; //~ ERROR cannot index into a value of type `()`
+}
diff --git a/src/test/ui/index_message.stderr b/src/test/ui/index_message.stderr
new file mode 100644
index 0000000..6c2b126
--- /dev/null
+++ b/src/test/ui/index_message.stderr
@@ -0,0 +1,9 @@
+error[E0608]: cannot index into a value of type `()`
+  --> $DIR/index_message.rs:3:13
+   |
+LL |     let _ = z[0];
+   |             ^^^^ help: to access tuple elements, use: `z.0`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0608`.
diff --git a/src/test/ui/indexing-requires-a-uint.rs b/src/test/ui/indexing-requires-a-uint.rs
new file mode 100644
index 0000000..dbe9b44
--- /dev/null
+++ b/src/test/ui/indexing-requires-a-uint.rs
@@ -0,0 +1,14 @@
+// Make sure that indexing an array is only valid with a `usize`, not any other
+// integral type.
+
+fn main() {
+    fn bar<T>(_: T) {}
+    [0][0u8]; //~ ERROR: the type `[{integer}]` cannot be indexed by `u8`
+
+    [0][0]; // should infer to be a usize
+
+    let i = 0;      // i is an IntVar
+    [0][i];         // i should be locked to usize
+    bar::<isize>(i);  // i should not be re-coerced back to an isize
+    //~^ ERROR: mismatched types
+}
diff --git a/src/test/ui/indexing-requires-a-uint.stderr b/src/test/ui/indexing-requires-a-uint.stderr
new file mode 100644
index 0000000..0b87958
--- /dev/null
+++ b/src/test/ui/indexing-requires-a-uint.stderr
@@ -0,0 +1,19 @@
+error[E0277]: the type `[{integer}]` cannot be indexed by `u8`
+  --> $DIR/indexing-requires-a-uint.rs:6:5
+   |
+LL |     [0][0u8];
+   |     ^^^^^^^^ slice indices are of type `usize` or ranges of `usize`
+   |
+   = help: the trait `std::slice::SliceIndex<[{integer}]>` is not implemented for `u8`
+   = note: required because of the requirements on the impl of `std::ops::Index<u8>` for `[{integer}]`
+
+error[E0308]: mismatched types
+  --> $DIR/indexing-requires-a-uint.rs:12:18
+   |
+LL |     bar::<isize>(i);  // i should not be re-coerced back to an isize
+   |                  ^ expected isize, found usize
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0277, E0308.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/inference/auxiliary/inference_unstable_iterator.rs b/src/test/ui/inference/auxiliary/inference_unstable_iterator.rs
new file mode 100644
index 0000000..0dc0970
--- /dev/null
+++ b/src/test/ui/inference/auxiliary/inference_unstable_iterator.rs
@@ -0,0 +1,14 @@
+#![feature(staged_api)]
+
+#![stable(feature = "ipu_iterator", since = "1.0.0")]
+
+#[stable(feature = "ipu_iterator", since = "1.0.0")]
+pub trait IpuIterator {
+    #[unstable(feature = "ipu_flatten", issue = "99999")]
+    fn ipu_flatten(&self) -> u32 {
+        0
+    }
+}
+
+#[stable(feature = "ipu_iterator", since = "1.0.0")]
+impl IpuIterator for char {}
diff --git a/src/test/ui/inference/auxiliary/inference_unstable_itertools.rs b/src/test/ui/inference/auxiliary/inference_unstable_itertools.rs
new file mode 100644
index 0000000..964f35d
--- /dev/null
+++ b/src/test/ui/inference/auxiliary/inference_unstable_itertools.rs
@@ -0,0 +1,7 @@
+pub trait IpuItertools {
+    fn ipu_flatten(&self) -> u32 {
+        1
+    }
+}
+
+impl IpuItertools for char {}
diff --git a/src/test/ui/inference/inference-variable-behind-raw-pointer.rs b/src/test/ui/inference/inference-variable-behind-raw-pointer.rs
new file mode 100644
index 0000000..513b15e
--- /dev/null
+++ b/src/test/ui/inference/inference-variable-behind-raw-pointer.rs
@@ -0,0 +1,9 @@
+// compile-pass
+
+// tests that the following code compiles, but produces a future-compatibility warning
+
+fn main() {
+    let data = std::ptr::null();
+    let _ = &data as *const *const ();
+    if data.is_null() {}
+}
diff --git a/src/test/ui/inference/inference-variable-behind-raw-pointer.stderr b/src/test/ui/inference/inference-variable-behind-raw-pointer.stderr
new file mode 100644
index 0000000..52cf68a
--- /dev/null
+++ b/src/test/ui/inference/inference-variable-behind-raw-pointer.stderr
@@ -0,0 +1,10 @@
+warning: type annotations needed
+  --> $DIR/inference-variable-behind-raw-pointer.rs:8:13
+   |
+LL |     if data.is_null() {}
+   |             ^^^^^^^
+   |
+   = note: #[warn(tyvar_behind_raw_pointer)] on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #46906 <https://github.com/rust-lang/rust/issues/46906>
+
diff --git a/src/test/ui/inference/inference_unstable.rs b/src/test/ui/inference/inference_unstable.rs
new file mode 100644
index 0000000..0b95770
--- /dev/null
+++ b/src/test/ui/inference/inference_unstable.rs
@@ -0,0 +1,19 @@
+// Ensures #[unstable] functions without opting in the corresponding #![feature]
+// will not break inference.
+
+// aux-build:inference_unstable_iterator.rs
+// aux-build:inference_unstable_itertools.rs
+// run-pass
+
+extern crate inference_unstable_iterator;
+extern crate inference_unstable_itertools;
+
+#[allow(unused_imports)]
+use inference_unstable_iterator::IpuIterator;
+use inference_unstable_itertools::IpuItertools;
+
+fn main() {
+    assert_eq!('x'.ipu_flatten(), 1);
+    //~^ WARN a method with this name may be added to the standard library in the future
+    //~^^ WARN once this method is added to the standard library, the ambiguity may cause an error
+}
diff --git a/src/test/ui/inference/inference_unstable.stderr b/src/test/ui/inference/inference_unstable.stderr
new file mode 100644
index 0000000..dda203b
--- /dev/null
+++ b/src/test/ui/inference/inference_unstable.stderr
@@ -0,0 +1,12 @@
+warning: a method with this name may be added to the standard library in the future
+  --> $DIR/inference_unstable.rs:16:20
+   |
+LL |     assert_eq!('x'.ipu_flatten(), 1);
+   |                    ^^^^^^^^^^^
+   |
+   = note: #[warn(unstable_name_collisions)] on by default
+   = warning: once this method is added to the standard library, the ambiguity may cause an error or change in behavior!
+   = note: for more information, see issue #48919 <https://github.com/rust-lang/rust/issues/48919>
+   = help: call with fully qualified syntax `inference_unstable_itertools::IpuItertools::ipu_flatten(...)` to keep using the current method
+   = help: add #![feature(ipu_flatten)] to the crate attributes to enable `inference_unstable_iterator::IpuIterator::ipu_flatten`
+
diff --git a/src/test/ui/inference/inference_unstable_featured.rs b/src/test/ui/inference/inference_unstable_featured.rs
new file mode 100644
index 0000000..792b29a
--- /dev/null
+++ b/src/test/ui/inference/inference_unstable_featured.rs
@@ -0,0 +1,17 @@
+// There should be E0034 "multiple applicable items in scope" if we opt-in for
+// the feature.
+
+// aux-build:inference_unstable_iterator.rs
+// aux-build:inference_unstable_itertools.rs
+
+#![feature(ipu_flatten)]
+
+extern crate inference_unstable_iterator;
+extern crate inference_unstable_itertools;
+
+use inference_unstable_iterator::IpuIterator;
+use inference_unstable_itertools::IpuItertools;
+
+fn main() {
+    assert_eq!('x'.ipu_flatten(), 0);   //~ ERROR E0034
+}
diff --git a/src/test/ui/inference/inference_unstable_featured.stderr b/src/test/ui/inference/inference_unstable_featured.stderr
new file mode 100644
index 0000000..08cdb8c
--- /dev/null
+++ b/src/test/ui/inference/inference_unstable_featured.stderr
@@ -0,0 +1,12 @@
+error[E0034]: multiple applicable items in scope
+  --> $DIR/inference_unstable_featured.rs:16:20
+   |
+LL |     assert_eq!('x'.ipu_flatten(), 0);
+   |                    ^^^^^^^^^^^ multiple `ipu_flatten` found
+   |
+   = note: candidate #1 is defined in an impl of the trait `inference_unstable_iterator::IpuIterator` for the type `char`
+   = note: candidate #2 is defined in an impl of the trait `inference_unstable_itertools::IpuItertools` for the type `char`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0034`.
diff --git a/src/test/ui/inference/inference_unstable_forced.rs b/src/test/ui/inference/inference_unstable_forced.rs
new file mode 100644
index 0000000..649b3ed
--- /dev/null
+++ b/src/test/ui/inference/inference_unstable_forced.rs
@@ -0,0 +1,12 @@
+// If the unstable API is the only possible solution,
+// still emit E0658 "use of unstable library feature".
+
+// aux-build:inference_unstable_iterator.rs
+
+extern crate inference_unstable_iterator;
+
+use inference_unstable_iterator::IpuIterator;
+
+fn main() {
+    assert_eq!('x'.ipu_flatten(), 0);   //~ ERROR E0658
+}
diff --git a/src/test/ui/inference/inference_unstable_forced.stderr b/src/test/ui/inference/inference_unstable_forced.stderr
new file mode 100644
index 0000000..067bf44
--- /dev/null
+++ b/src/test/ui/inference/inference_unstable_forced.stderr
@@ -0,0 +1,11 @@
+error[E0658]: use of unstable library feature 'ipu_flatten' (see issue #99999)
+  --> $DIR/inference_unstable_forced.rs:11:20
+   |
+LL |     assert_eq!('x'.ipu_flatten(), 0);
+   |                    ^^^^^^^^^^^
+   |
+   = help: add #![feature(ipu_flatten)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/infinite/infinite-autoderef.rs b/src/test/ui/infinite/infinite-autoderef.rs
new file mode 100644
index 0000000..6d6908e
--- /dev/null
+++ b/src/test/ui/infinite/infinite-autoderef.rs
@@ -0,0 +1,27 @@
+// error-pattern: reached the recursion limit while auto-dereferencing
+
+#![feature(box_syntax)]
+
+use std::ops::Deref;
+
+struct Foo;
+
+impl Deref for Foo {
+    type Target = Foo;
+
+    fn deref(&self) -> &Foo {
+        self
+    }
+}
+
+pub fn main() {
+    let mut x;
+    loop {
+        x = box x;
+        x.foo;
+        x.bar();
+    }
+
+    Foo.foo;
+    Foo.bar();
+}
diff --git a/src/test/ui/infinite/infinite-autoderef.stderr b/src/test/ui/infinite/infinite-autoderef.stderr
new file mode 100644
index 0000000..9e4b0a0
--- /dev/null
+++ b/src/test/ui/infinite/infinite-autoderef.stderr
@@ -0,0 +1,52 @@
+error[E0308]: mismatched types
+  --> $DIR/infinite-autoderef.rs:20:13
+   |
+LL |         x = box x;
+   |             ^^^^^
+   |             |
+   |             cyclic type of infinite size
+   |             help: try using a conversion method: `box x.to_string()`
+
+error[E0055]: reached the recursion limit while auto-dereferencing `Foo`
+  --> $DIR/infinite-autoderef.rs:25:5
+   |
+LL |     Foo.foo;
+   |     ^^^^^^^ deref recursion limit reached
+   |
+   = help: consider adding a `#![recursion_limit="128"]` attribute to your crate
+
+error[E0055]: reached the recursion limit while auto-dereferencing `Foo`
+  --> $DIR/infinite-autoderef.rs:25:9
+   |
+LL |     Foo.foo;
+   |         ^^^ deref recursion limit reached
+   |
+   = help: consider adding a `#![recursion_limit="128"]` attribute to your crate
+
+error[E0609]: no field `foo` on type `Foo`
+  --> $DIR/infinite-autoderef.rs:25:9
+   |
+LL |     Foo.foo;
+   |         ^^^ unknown field
+
+error[E0055]: reached the recursion limit while auto-dereferencing `Foo`
+  --> $DIR/infinite-autoderef.rs:26:9
+   |
+LL |     Foo.bar();
+   |         ^^^ deref recursion limit reached
+   |
+   = help: consider adding a `#![recursion_limit="128"]` attribute to your crate
+
+error[E0599]: no method named `bar` found for type `Foo` in the current scope
+  --> $DIR/infinite-autoderef.rs:26:9
+   |
+LL | struct Foo;
+   | ----------- method `bar` not found for this
+...
+LL |     Foo.bar();
+   |         ^^^
+
+error: aborting due to 6 previous errors
+
+Some errors occurred: E0055, E0308, E0599, E0609.
+For more information about an error, try `rustc --explain E0055`.
diff --git a/src/test/ui/infinite/infinite-instantiation.rs b/src/test/ui/infinite/infinite-instantiation.rs
new file mode 100644
index 0000000..4220c88
--- /dev/null
+++ b/src/test/ui/infinite/infinite-instantiation.rs
@@ -0,0 +1,34 @@
+//
+// We get an error message at the top of file (dummy span).
+// This is not helpful, but also kind of annoying to prevent,
+// so for now just live with it.
+// This test case was originally for issue #2258.
+
+trait ToOpt: Sized {
+    fn to_option(&self) -> Option<Self>;
+}
+
+impl ToOpt for usize {
+    fn to_option(&self) -> Option<usize> {
+        Some(*self)
+    }
+}
+
+impl<T:Clone> ToOpt for Option<T> {
+    fn to_option(&self) -> Option<Option<T>> {
+        Some((*self).clone())
+    }
+}
+
+fn function<T:ToOpt + Clone>(counter: usize, t: T) {
+//~^ ERROR reached the recursion limit while instantiating `function::<std::option::Option<
+    if counter > 0 {
+        function(counter - 1, t.to_option());
+        // FIXME(#4287) Error message should be here. It should be
+        // a type error to instantiate `test` at a type other than T.
+    }
+}
+
+fn main() {
+    function(22, 22);
+}
diff --git a/src/test/ui/infinite/infinite-instantiation.stderr b/src/test/ui/infinite/infinite-instantiation.stderr
new file mode 100644
index 0000000..976b9e3
--- /dev/null
+++ b/src/test/ui/infinite/infinite-instantiation.stderr
@@ -0,0 +1,14 @@
+error: reached the recursion limit while instantiating `function::<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<usize>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+  --> $DIR/infinite-instantiation.rs:23:1
+   |
+LL | / fn function<T:ToOpt + Clone>(counter: usize, t: T) {
+LL | |
+LL | |     if counter > 0 {
+LL | |         function(counter - 1, t.to_option());
+...  |
+LL | |     }
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/infinite/infinite-macro-expansion.rs b/src/test/ui/infinite/infinite-macro-expansion.rs
new file mode 100644
index 0000000..968d836
--- /dev/null
+++ b/src/test/ui/infinite/infinite-macro-expansion.rs
@@ -0,0 +1,7 @@
+macro_rules! recursive {
+    () => (recursive!()) //~ ERROR recursion limit reached while expanding the macro `recursive`
+}
+
+fn main() {
+    recursive!()
+}
diff --git a/src/test/ui/infinite/infinite-macro-expansion.stderr b/src/test/ui/infinite/infinite-macro-expansion.stderr
new file mode 100644
index 0000000..0faf29f
--- /dev/null
+++ b/src/test/ui/infinite/infinite-macro-expansion.stderr
@@ -0,0 +1,13 @@
+error: recursion limit reached while expanding the macro `recursive`
+  --> $DIR/infinite-macro-expansion.rs:2:12
+   |
+LL |     () => (recursive!())
+   |            ^^^^^^^^^^^^
+...
+LL |     recursive!()
+   |     ------------ in this macro invocation
+   |
+   = help: consider adding a `#![recursion_limit="128"]` attribute to your crate
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/infinite/infinite-recursion-const-fn.rs b/src/test/ui/infinite/infinite-recursion-const-fn.rs
new file mode 100644
index 0000000..020c417
--- /dev/null
+++ b/src/test/ui/infinite/infinite-recursion-const-fn.rs
@@ -0,0 +1,7 @@
+//https://github.com/rust-lang/rust/issues/31364
+
+const fn a() -> usize { b() } //~ ERROR evaluation of constant value failed
+const fn b() -> usize { a() }
+const ARR: [i32; a()] = [5; 6];
+
+fn main(){}
diff --git a/src/test/ui/infinite/infinite-recursion-const-fn.stderr b/src/test/ui/infinite/infinite-recursion-const-fn.stderr
new file mode 100644
index 0000000..9e0530d
--- /dev/null
+++ b/src/test/ui/infinite/infinite-recursion-const-fn.stderr
@@ -0,0 +1,66 @@
+error[E0080]: evaluation of constant value failed
+  --> $DIR/infinite-recursion-const-fn.rs:3:25
+   |
+LL | const fn a() -> usize { b() }
+   |                         ^^^
+   |                         |
+   |                         reached the configured maximum number of stack frames
+   |                         inside call to `b` at $DIR/infinite-recursion-const-fn.rs:3:25
+LL | const fn b() -> usize { a() }
+   |                         ---
+   |                         |
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:4:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:4:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:4:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:4:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:4:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:4:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:4:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:4:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:4:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:4:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:4:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:4:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:4:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:4:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:4:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:4:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:4:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:4:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:4:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:4:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:4:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:4:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:4:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:4:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:4:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:4:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:4:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:4:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:4:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:4:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:4:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:4:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:4:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:4:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:4:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:4:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:4:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:4:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:4:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:4:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:4:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:4:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:4:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:4:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:4:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:4:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:4:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:4:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:4:25
+LL | const ARR: [i32; a()] = [5; 6];
+   |                  --- inside call to `a` at $DIR/infinite-recursion-const-fn.rs:5:18
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/infinite/infinite-tag-type-recursion.rs b/src/test/ui/infinite/infinite-tag-type-recursion.rs
new file mode 100644
index 0000000..87a9e08
--- /dev/null
+++ b/src/test/ui/infinite/infinite-tag-type-recursion.rs
@@ -0,0 +1,4 @@
+enum MList { Cons(isize, MList), Nil }
+//~^ ERROR recursive type `MList` has infinite size
+
+fn main() { let a = MList::Cons(10, MList::Cons(11, MList::Nil)); }
diff --git a/src/test/ui/infinite/infinite-tag-type-recursion.stderr b/src/test/ui/infinite/infinite-tag-type-recursion.stderr
new file mode 100644
index 0000000..88dad00
--- /dev/null
+++ b/src/test/ui/infinite/infinite-tag-type-recursion.stderr
@@ -0,0 +1,13 @@
+error[E0072]: recursive type `MList` has infinite size
+  --> $DIR/infinite-tag-type-recursion.rs:1:1
+   |
+LL | enum MList { Cons(isize, MList), Nil }
+   | ^^^^^^^^^^               ----- recursive without indirection
+   | |
+   | recursive type has infinite size
+   |
+   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `MList` representable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0072`.
diff --git a/src/test/ui/infinite/infinite-vec-type-recursion.rs b/src/test/ui/infinite/infinite-vec-type-recursion.rs
new file mode 100644
index 0000000..3568182
--- /dev/null
+++ b/src/test/ui/infinite/infinite-vec-type-recursion.rs
@@ -0,0 +1,4 @@
+type X = Vec<X>;
+//~^ ERROR cycle detected
+
+fn main() { let b: X = Vec::new(); }
diff --git a/src/test/ui/infinite/infinite-vec-type-recursion.stderr b/src/test/ui/infinite/infinite-vec-type-recursion.stderr
new file mode 100644
index 0000000..be0db56
--- /dev/null
+++ b/src/test/ui/infinite/infinite-vec-type-recursion.stderr
@@ -0,0 +1,19 @@
+error[E0391]: cycle detected when processing `X`
+  --> $DIR/infinite-vec-type-recursion.rs:1:14
+   |
+LL | type X = Vec<X>;
+   |              ^
+   |
+   = note: ...which again requires processing `X`, completing the cycle
+note: cycle used when collecting item types in top-level module
+  --> $DIR/infinite-vec-type-recursion.rs:1:1
+   |
+LL | / type X = Vec<X>;
+LL | |
+LL | |
+LL | | fn main() { let b: X = Vec::new(); }
+   | |____________________________________^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/init-unsafe.rs b/src/test/ui/init-unsafe.rs
new file mode 100644
index 0000000..92b21c4
--- /dev/null
+++ b/src/test/ui/init-unsafe.rs
@@ -0,0 +1,8 @@
+#![feature(core_intrinsics)]
+
+use std::intrinsics::{init};
+
+// Test that the `init` intrinsic is really unsafe
+pub fn main() {
+    let stuff = init::<isize>(); //~ ERROR call to unsafe function is unsafe
+}
diff --git a/src/test/ui/init-unsafe.stderr b/src/test/ui/init-unsafe.stderr
new file mode 100644
index 0000000..857142d
--- /dev/null
+++ b/src/test/ui/init-unsafe.stderr
@@ -0,0 +1,11 @@
+error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
+  --> $DIR/init-unsafe.rs:7:17
+   |
+LL |     let stuff = init::<isize>();
+   |                 ^^^^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/inline-asm-bad-constraint.rs b/src/test/ui/inline-asm-bad-constraint.rs
new file mode 100644
index 0000000..cf72aff
--- /dev/null
+++ b/src/test/ui/inline-asm-bad-constraint.rs
@@ -0,0 +1,39 @@
+// Test that the compiler will catch invalid inline assembly constraints.
+
+// ignore-emscripten
+
+#![feature(asm)]
+
+extern "C" {
+    fn foo(a: usize);
+}
+
+fn main() {
+    bad_register_constraint();
+    bad_input();
+    wrong_size_output();
+}
+
+// Issue #54130
+fn bad_register_constraint() {
+    let rax: u64;
+    unsafe {
+        asm!("" :"={rax"(rax)) //~ ERROR E0668
+    };
+    println!("Accumulator is: {}", rax);
+}
+
+// Issue #54376
+fn bad_input() {
+    unsafe {
+        asm!("callq $0" : : "0"(foo)) //~ ERROR E0668
+    };
+}
+
+fn wrong_size_output() {
+    let rax: u64 = 0;
+    unsafe {
+        asm!("addb $1, $0" : "={rax}"((0i32, rax))); //~ ERROR E0668
+    }
+    println!("rax: {}", rax);
+}
diff --git a/src/test/ui/inline-asm-bad-constraint.stderr b/src/test/ui/inline-asm-bad-constraint.stderr
new file mode 100644
index 0000000..59066e5
--- /dev/null
+++ b/src/test/ui/inline-asm-bad-constraint.stderr
@@ -0,0 +1,21 @@
+error[E0668]: malformed inline assembly
+  --> $DIR/inline-asm-bad-constraint.rs:21:9
+   |
+LL |         asm!("" :"={rax"(rax))
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0668]: malformed inline assembly
+  --> $DIR/inline-asm-bad-constraint.rs:29:9
+   |
+LL |         asm!("callq $0" : : "0"(foo))
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0668]: malformed inline assembly
+  --> $DIR/inline-asm-bad-constraint.rs:36:9
+   |
+LL |         asm!("addb $1, $0" : "={rax}"((0i32, rax)));
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0668`.
diff --git a/src/test/ui/inline-asm-bad-operand.rs b/src/test/ui/inline-asm-bad-operand.rs
new file mode 100644
index 0000000..4cfe100
--- /dev/null
+++ b/src/test/ui/inline-asm-bad-operand.rs
@@ -0,0 +1,58 @@
+// Test that the compiler will catch passing invalid values to inline assembly
+// operands.
+
+// ignore-emscripten
+
+#![feature(asm)]
+
+#[repr(C)]
+struct MyPtr(usize);
+
+fn main() {
+    issue_37433();
+    issue_37437();
+    issue_40187();
+    issue_54067();
+    multiple_errors();
+}
+
+fn issue_37433() {
+    unsafe {
+        asm!("" :: "r"("")); //~ ERROR E0669
+    }
+
+    unsafe {
+        let target = MyPtr(0);
+        asm!("ret" : : "{rdi}"(target)); //~ ERROR E0669
+    }
+}
+
+fn issue_37437() {
+    let hello: &str = "hello";
+    // this should fail...
+    unsafe { asm!("" :: "i"(hello)) }; //~ ERROR E0669
+    // but this should succeed.
+    unsafe { asm!("" :: "r"(hello.as_ptr())) };
+}
+
+fn issue_40187() {
+    let arr: [u8; 1] = [0; 1];
+    unsafe {
+        asm!("movups $1, %xmm0"::"m"(arr)); //~ ERROR E0669
+    }
+}
+
+fn issue_54067() {
+    let addr: Option<u32> = Some(123);
+    unsafe {
+        asm!("mov sp, $0"::"r"(addr)); //~ ERROR E0669
+    }
+}
+
+fn multiple_errors() {
+    let addr: (u32, u32) = (1, 2);
+    unsafe {
+        asm!("mov sp, $0"::"r"(addr), //~ ERROR E0669
+                           "r"("hello e0669")); //~ ERROR E0669
+    }
+}
diff --git a/src/test/ui/inline-asm-bad-operand.stderr b/src/test/ui/inline-asm-bad-operand.stderr
new file mode 100644
index 0000000..3bb1cdd
--- /dev/null
+++ b/src/test/ui/inline-asm-bad-operand.stderr
@@ -0,0 +1,45 @@
+error[E0669]: invalid value for constraint in inline assembly
+  --> $DIR/inline-asm-bad-operand.rs:21:24
+   |
+LL |         asm!("" :: "r"(""));
+   |                        ^^
+
+error[E0669]: invalid value for constraint in inline assembly
+  --> $DIR/inline-asm-bad-operand.rs:26:32
+   |
+LL |         asm!("ret" : : "{rdi}"(target));
+   |                                ^^^^^^
+
+error[E0669]: invalid value for constraint in inline assembly
+  --> $DIR/inline-asm-bad-operand.rs:33:29
+   |
+LL |     unsafe { asm!("" :: "i"(hello)) };
+   |                             ^^^^^
+
+error[E0669]: invalid value for constraint in inline assembly
+  --> $DIR/inline-asm-bad-operand.rs:41:38
+   |
+LL |         asm!("movups $1, %xmm0"::"m"(arr));
+   |                                      ^^^
+
+error[E0669]: invalid value for constraint in inline assembly
+  --> $DIR/inline-asm-bad-operand.rs:48:32
+   |
+LL |         asm!("mov sp, $0"::"r"(addr));
+   |                                ^^^^
+
+error[E0669]: invalid value for constraint in inline assembly
+  --> $DIR/inline-asm-bad-operand.rs:55:32
+   |
+LL |         asm!("mov sp, $0"::"r"(addr),
+   |                                ^^^^
+
+error[E0669]: invalid value for constraint in inline assembly
+  --> $DIR/inline-asm-bad-operand.rs:56:32
+   |
+LL |                            "r"("hello e0669"));
+   |                                ^^^^^^^^^^^^^
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0669`.
diff --git a/src/test/ui/inner-static-type-parameter.rs b/src/test/ui/inner-static-type-parameter.rs
new file mode 100644
index 0000000..c08ccd2
--- /dev/null
+++ b/src/test/ui/inner-static-type-parameter.rs
@@ -0,0 +1,11 @@
+// see #9186
+
+enum Bar<T> { What } //~ ERROR parameter `T` is never used
+
+fn foo<T>() {
+    static a: Bar<T> = Bar::What;
+//~^ ERROR can't use generic parameters from outer function
+}
+
+fn main() {
+}
diff --git a/src/test/ui/inner-static-type-parameter.stderr b/src/test/ui/inner-static-type-parameter.stderr
new file mode 100644
index 0000000..3c14e21
--- /dev/null
+++ b/src/test/ui/inner-static-type-parameter.stderr
@@ -0,0 +1,22 @@
+error[E0401]: can't use generic parameters from outer function
+  --> $DIR/inner-static-type-parameter.rs:6:19
+   |
+LL | fn foo<T>() {
+   |    --- - type variable from outer function
+   |    |
+   |    try adding a local generic parameter in this method instead
+LL |     static a: Bar<T> = Bar::What;
+   |                   ^ use of generic parameter from outer function
+
+error[E0392]: parameter `T` is never used
+  --> $DIR/inner-static-type-parameter.rs:3:10
+   |
+LL | enum Bar<T> { What }
+   |          ^ unused type parameter
+   |
+   = help: consider removing `T` or using a marker such as `std::marker::PhantomData`
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0392, E0401.
+For more information about an error, try `rustc --explain E0392`.
diff --git a/src/test/ui/integer-literal-suffix-inference.rs b/src/test/ui/integer-literal-suffix-inference.rs
new file mode 100644
index 0000000..2da3286
--- /dev/null
+++ b/src/test/ui/integer-literal-suffix-inference.rs
@@ -0,0 +1,162 @@
+fn main() {
+
+    // the smallest positive values that need these types
+    let a8: i8 = 8;
+    let a16: i16 = 128;
+    let a32: i32 = 32_768;
+    let a64: i64 = 2_147_483_648;
+
+    // the smallest negative values that need these types
+    let c8: i8 = -9;
+    let c16: i16 = -129;
+    let c32: i32 = -32_769;
+    let c64: i64 = -2_147_483_649;
+
+    fn id_i8(n: i8) -> i8 { n }
+    fn id_i16(n: i16) -> i16 { n }
+    fn id_i32(n: i32) -> i32 { n }
+    fn id_i64(n: i64) -> i64 { n }
+
+    // the smallest values that need these types
+    let b8: u8 = 16;
+    let b16: u16 = 256;
+    let b32: u32 = 65_536;
+    let b64: u64 = 4_294_967_296;
+
+    fn id_u8(n: u8) -> u8 { n }
+    fn id_u16(n: u16) -> u16 { n }
+    fn id_u32(n: u32) -> u32 { n }
+    fn id_u64(n: u64) -> u64 { n }
+
+    id_i8(a8); // ok
+    id_i8(a16);
+    //~^ ERROR mismatched types
+    //~| expected i8, found i16
+    id_i8(a32);
+    //~^ ERROR mismatched types
+    //~| expected i8, found i32
+    id_i8(a64);
+    //~^ ERROR mismatched types
+    //~| expected i8, found i64
+
+    id_i16(a8);
+    //~^ ERROR mismatched types
+    //~| expected i16, found i8
+    id_i16(a16); // ok
+    id_i16(a32);
+    //~^ ERROR mismatched types
+    //~| expected i16, found i32
+    id_i16(a64);
+    //~^ ERROR mismatched types
+    //~| expected i16, found i64
+
+    id_i32(a8);
+    //~^ ERROR mismatched types
+    //~| expected i32, found i8
+    id_i32(a16);
+    //~^ ERROR mismatched types
+    //~| expected i32, found i16
+    id_i32(a32); // ok
+    id_i32(a64);
+    //~^ ERROR mismatched types
+    //~| expected i32, found i64
+
+    id_i64(a8);
+    //~^ ERROR mismatched types
+    //~| expected i64, found i8
+    id_i64(a16);
+    //~^ ERROR mismatched types
+    //~| expected i64, found i16
+    id_i64(a32);
+    //~^ ERROR mismatched types
+    //~| expected i64, found i32
+    id_i64(a64); // ok
+
+    id_i8(c8); // ok
+    id_i8(c16);
+    //~^ ERROR mismatched types
+    //~| expected i8, found i16
+    id_i8(c32);
+    //~^ ERROR mismatched types
+    //~| expected i8, found i32
+    id_i8(c64);
+    //~^ ERROR mismatched types
+    //~| expected i8, found i64
+
+    id_i16(c8);
+    //~^ ERROR mismatched types
+    //~| expected i16, found i8
+    id_i16(c16); // ok
+    id_i16(c32);
+    //~^ ERROR mismatched types
+    //~| expected i16, found i32
+    id_i16(c64);
+    //~^ ERROR mismatched types
+    //~| expected i16, found i64
+
+    id_i32(c8);
+    //~^ ERROR mismatched types
+    //~| expected i32, found i8
+    id_i32(c16);
+    //~^ ERROR mismatched types
+    //~| expected i32, found i16
+    id_i32(c32); // ok
+    id_i32(c64);
+    //~^ ERROR mismatched types
+    //~| expected i32, found i64
+
+    id_i64(a8);
+    //~^ ERROR mismatched types
+    //~| expected i64, found i8
+    id_i64(a16);
+    //~^ ERROR mismatched types
+    //~| expected i64, found i16
+    id_i64(a32);
+    //~^ ERROR mismatched types
+    //~| expected i64, found i32
+    id_i64(a64); // ok
+
+    id_u8(b8); // ok
+    id_u8(b16);
+    //~^ ERROR mismatched types
+    //~| expected u8, found u16
+    id_u8(b32);
+    //~^ ERROR mismatched types
+    //~| expected u8, found u32
+    id_u8(b64);
+    //~^ ERROR mismatched types
+    //~| expected u8, found u64
+
+    id_u16(b8);
+    //~^ ERROR mismatched types
+    //~| expected u16, found u8
+    id_u16(b16); // ok
+    id_u16(b32);
+    //~^ ERROR mismatched types
+    //~| expected u16, found u32
+    id_u16(b64);
+    //~^ ERROR mismatched types
+    //~| expected u16, found u64
+
+    id_u32(b8);
+    //~^ ERROR mismatched types
+    //~| expected u32, found u8
+    id_u32(b16);
+    //~^ ERROR mismatched types
+    //~| expected u32, found u16
+    id_u32(b32); // ok
+    id_u32(b64);
+    //~^ ERROR mismatched types
+    //~| expected u32, found u64
+
+    id_u64(b8);
+    //~^ ERROR mismatched types
+    //~| expected u64, found u8
+    id_u64(b16);
+    //~^ ERROR mismatched types
+    //~| expected u64, found u16
+    id_u64(b32);
+    //~^ ERROR mismatched types
+    //~| expected u64, found u32
+    id_u64(b64); // ok
+}
diff --git a/src/test/ui/integer-literal-suffix-inference.stderr b/src/test/ui/integer-literal-suffix-inference.stderr
new file mode 100644
index 0000000..04c8633
--- /dev/null
+++ b/src/test/ui/integer-literal-suffix-inference.stderr
@@ -0,0 +1,291 @@
+error[E0308]: mismatched types
+  --> $DIR/integer-literal-suffix-inference.rs:32:11
+   |
+LL |     id_i8(a16);
+   |           ^^^ expected i8, found i16
+
+error[E0308]: mismatched types
+  --> $DIR/integer-literal-suffix-inference.rs:35:11
+   |
+LL |     id_i8(a32);
+   |           ^^^ expected i8, found i32
+
+error[E0308]: mismatched types
+  --> $DIR/integer-literal-suffix-inference.rs:38:11
+   |
+LL |     id_i8(a64);
+   |           ^^^ expected i8, found i64
+
+error[E0308]: mismatched types
+  --> $DIR/integer-literal-suffix-inference.rs:42:12
+   |
+LL |     id_i16(a8);
+   |            ^^ expected i16, found i8
+help: you can cast an `i8` to `i16`, which will sign-extend the source value
+   |
+LL |     id_i16(a8.into());
+   |            ^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/integer-literal-suffix-inference.rs:46:12
+   |
+LL |     id_i16(a32);
+   |            ^^^ expected i16, found i32
+
+error[E0308]: mismatched types
+  --> $DIR/integer-literal-suffix-inference.rs:49:12
+   |
+LL |     id_i16(a64);
+   |            ^^^ expected i16, found i64
+
+error[E0308]: mismatched types
+  --> $DIR/integer-literal-suffix-inference.rs:53:12
+   |
+LL |     id_i32(a8);
+   |            ^^ expected i32, found i8
+help: you can cast an `i8` to `i32`, which will sign-extend the source value
+   |
+LL |     id_i32(a8.into());
+   |            ^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/integer-literal-suffix-inference.rs:56:12
+   |
+LL |     id_i32(a16);
+   |            ^^^ expected i32, found i16
+help: you can cast an `i16` to `i32`, which will sign-extend the source value
+   |
+LL |     id_i32(a16.into());
+   |            ^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/integer-literal-suffix-inference.rs:60:12
+   |
+LL |     id_i32(a64);
+   |            ^^^ expected i32, found i64
+
+error[E0308]: mismatched types
+  --> $DIR/integer-literal-suffix-inference.rs:64:12
+   |
+LL |     id_i64(a8);
+   |            ^^ expected i64, found i8
+help: you can cast an `i8` to `i64`, which will sign-extend the source value
+   |
+LL |     id_i64(a8.into());
+   |            ^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/integer-literal-suffix-inference.rs:67:12
+   |
+LL |     id_i64(a16);
+   |            ^^^ expected i64, found i16
+help: you can cast an `i16` to `i64`, which will sign-extend the source value
+   |
+LL |     id_i64(a16.into());
+   |            ^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/integer-literal-suffix-inference.rs:70:12
+   |
+LL |     id_i64(a32);
+   |            ^^^ expected i64, found i32
+help: you can cast an `i32` to `i64`, which will sign-extend the source value
+   |
+LL |     id_i64(a32.into());
+   |            ^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/integer-literal-suffix-inference.rs:76:11
+   |
+LL |     id_i8(c16);
+   |           ^^^ expected i8, found i16
+
+error[E0308]: mismatched types
+  --> $DIR/integer-literal-suffix-inference.rs:79:11
+   |
+LL |     id_i8(c32);
+   |           ^^^ expected i8, found i32
+
+error[E0308]: mismatched types
+  --> $DIR/integer-literal-suffix-inference.rs:82:11
+   |
+LL |     id_i8(c64);
+   |           ^^^ expected i8, found i64
+
+error[E0308]: mismatched types
+  --> $DIR/integer-literal-suffix-inference.rs:86:12
+   |
+LL |     id_i16(c8);
+   |            ^^ expected i16, found i8
+help: you can cast an `i8` to `i16`, which will sign-extend the source value
+   |
+LL |     id_i16(c8.into());
+   |            ^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/integer-literal-suffix-inference.rs:90:12
+   |
+LL |     id_i16(c32);
+   |            ^^^ expected i16, found i32
+
+error[E0308]: mismatched types
+  --> $DIR/integer-literal-suffix-inference.rs:93:12
+   |
+LL |     id_i16(c64);
+   |            ^^^ expected i16, found i64
+
+error[E0308]: mismatched types
+  --> $DIR/integer-literal-suffix-inference.rs:97:12
+   |
+LL |     id_i32(c8);
+   |            ^^ expected i32, found i8
+help: you can cast an `i8` to `i32`, which will sign-extend the source value
+   |
+LL |     id_i32(c8.into());
+   |            ^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/integer-literal-suffix-inference.rs:100:12
+   |
+LL |     id_i32(c16);
+   |            ^^^ expected i32, found i16
+help: you can cast an `i16` to `i32`, which will sign-extend the source value
+   |
+LL |     id_i32(c16.into());
+   |            ^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/integer-literal-suffix-inference.rs:104:12
+   |
+LL |     id_i32(c64);
+   |            ^^^ expected i32, found i64
+
+error[E0308]: mismatched types
+  --> $DIR/integer-literal-suffix-inference.rs:108:12
+   |
+LL |     id_i64(a8);
+   |            ^^ expected i64, found i8
+help: you can cast an `i8` to `i64`, which will sign-extend the source value
+   |
+LL |     id_i64(a8.into());
+   |            ^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/integer-literal-suffix-inference.rs:111:12
+   |
+LL |     id_i64(a16);
+   |            ^^^ expected i64, found i16
+help: you can cast an `i16` to `i64`, which will sign-extend the source value
+   |
+LL |     id_i64(a16.into());
+   |            ^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/integer-literal-suffix-inference.rs:114:12
+   |
+LL |     id_i64(a32);
+   |            ^^^ expected i64, found i32
+help: you can cast an `i32` to `i64`, which will sign-extend the source value
+   |
+LL |     id_i64(a32.into());
+   |            ^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/integer-literal-suffix-inference.rs:120:11
+   |
+LL |     id_u8(b16);
+   |           ^^^ expected u8, found u16
+
+error[E0308]: mismatched types
+  --> $DIR/integer-literal-suffix-inference.rs:123:11
+   |
+LL |     id_u8(b32);
+   |           ^^^ expected u8, found u32
+
+error[E0308]: mismatched types
+  --> $DIR/integer-literal-suffix-inference.rs:126:11
+   |
+LL |     id_u8(b64);
+   |           ^^^ expected u8, found u64
+
+error[E0308]: mismatched types
+  --> $DIR/integer-literal-suffix-inference.rs:130:12
+   |
+LL |     id_u16(b8);
+   |            ^^ expected u16, found u8
+help: you can cast an `u8` to `u16`, which will zero-extend the source value
+   |
+LL |     id_u16(b8.into());
+   |            ^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/integer-literal-suffix-inference.rs:134:12
+   |
+LL |     id_u16(b32);
+   |            ^^^ expected u16, found u32
+
+error[E0308]: mismatched types
+  --> $DIR/integer-literal-suffix-inference.rs:137:12
+   |
+LL |     id_u16(b64);
+   |            ^^^ expected u16, found u64
+
+error[E0308]: mismatched types
+  --> $DIR/integer-literal-suffix-inference.rs:141:12
+   |
+LL |     id_u32(b8);
+   |            ^^ expected u32, found u8
+help: you can cast an `u8` to `u32`, which will zero-extend the source value
+   |
+LL |     id_u32(b8.into());
+   |            ^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/integer-literal-suffix-inference.rs:144:12
+   |
+LL |     id_u32(b16);
+   |            ^^^ expected u32, found u16
+help: you can cast an `u16` to `u32`, which will zero-extend the source value
+   |
+LL |     id_u32(b16.into());
+   |            ^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/integer-literal-suffix-inference.rs:148:12
+   |
+LL |     id_u32(b64);
+   |            ^^^ expected u32, found u64
+
+error[E0308]: mismatched types
+  --> $DIR/integer-literal-suffix-inference.rs:152:12
+   |
+LL |     id_u64(b8);
+   |            ^^ expected u64, found u8
+help: you can cast an `u8` to `u64`, which will zero-extend the source value
+   |
+LL |     id_u64(b8.into());
+   |            ^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/integer-literal-suffix-inference.rs:155:12
+   |
+LL |     id_u64(b16);
+   |            ^^^ expected u64, found u16
+help: you can cast an `u16` to `u64`, which will zero-extend the source value
+   |
+LL |     id_u64(b16.into());
+   |            ^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/integer-literal-suffix-inference.rs:158:12
+   |
+LL |     id_u64(b32);
+   |            ^^^ expected u64, found u32
+help: you can cast an `u32` to `u64`, which will zero-extend the source value
+   |
+LL |     id_u64(b32.into());
+   |            ^^^^^^^^^^
+
+error: aborting due to 36 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/integral-indexing.rs b/src/test/ui/integral-indexing.rs
new file mode 100644
index 0000000..f076dfc
--- /dev/null
+++ b/src/test/ui/integral-indexing.rs
@@ -0,0 +1,16 @@
+pub fn main() {
+    let v: Vec<isize> = vec![0, 1, 2, 3, 4, 5];
+    let s: String = "abcdef".to_string();
+    v[3_usize];
+    v[3];
+    v[3u8];  //~ERROR : the type `[isize]` cannot be indexed by `u8`
+    v[3i8];  //~ERROR : the type `[isize]` cannot be indexed by `i8`
+    v[3u32]; //~ERROR : the type `[isize]` cannot be indexed by `u32`
+    v[3i32]; //~ERROR : the type `[isize]` cannot be indexed by `i32`
+    s.as_bytes()[3_usize];
+    s.as_bytes()[3];
+    s.as_bytes()[3u8];  //~ERROR : the type `[u8]` cannot be indexed by `u8`
+    s.as_bytes()[3i8];  //~ERROR : the type `[u8]` cannot be indexed by `i8`
+    s.as_bytes()[3u32]; //~ERROR : the type `[u8]` cannot be indexed by `u32`
+    s.as_bytes()[3i32]; //~ERROR : the type `[u8]` cannot be indexed by `i32`
+}
diff --git a/src/test/ui/integral-indexing.stderr b/src/test/ui/integral-indexing.stderr
new file mode 100644
index 0000000..28ef593
--- /dev/null
+++ b/src/test/ui/integral-indexing.stderr
@@ -0,0 +1,75 @@
+error[E0277]: the type `[isize]` cannot be indexed by `u8`
+  --> $DIR/integral-indexing.rs:6:5
+   |
+LL |     v[3u8];
+   |     ^^^^^^ slice indices are of type `usize` or ranges of `usize`
+   |
+   = help: the trait `std::slice::SliceIndex<[isize]>` is not implemented for `u8`
+   = note: required because of the requirements on the impl of `std::ops::Index<u8>` for `std::vec::Vec<isize>`
+
+error[E0277]: the type `[isize]` cannot be indexed by `i8`
+  --> $DIR/integral-indexing.rs:7:5
+   |
+LL |     v[3i8];
+   |     ^^^^^^ slice indices are of type `usize` or ranges of `usize`
+   |
+   = help: the trait `std::slice::SliceIndex<[isize]>` is not implemented for `i8`
+   = note: required because of the requirements on the impl of `std::ops::Index<i8>` for `std::vec::Vec<isize>`
+
+error[E0277]: the type `[isize]` cannot be indexed by `u32`
+  --> $DIR/integral-indexing.rs:8:5
+   |
+LL |     v[3u32];
+   |     ^^^^^^^ slice indices are of type `usize` or ranges of `usize`
+   |
+   = help: the trait `std::slice::SliceIndex<[isize]>` is not implemented for `u32`
+   = note: required because of the requirements on the impl of `std::ops::Index<u32>` for `std::vec::Vec<isize>`
+
+error[E0277]: the type `[isize]` cannot be indexed by `i32`
+  --> $DIR/integral-indexing.rs:9:5
+   |
+LL |     v[3i32];
+   |     ^^^^^^^ slice indices are of type `usize` or ranges of `usize`
+   |
+   = help: the trait `std::slice::SliceIndex<[isize]>` is not implemented for `i32`
+   = note: required because of the requirements on the impl of `std::ops::Index<i32>` for `std::vec::Vec<isize>`
+
+error[E0277]: the type `[u8]` cannot be indexed by `u8`
+  --> $DIR/integral-indexing.rs:12:5
+   |
+LL |     s.as_bytes()[3u8];
+   |     ^^^^^^^^^^^^^^^^^ slice indices are of type `usize` or ranges of `usize`
+   |
+   = help: the trait `std::slice::SliceIndex<[u8]>` is not implemented for `u8`
+   = note: required because of the requirements on the impl of `std::ops::Index<u8>` for `[u8]`
+
+error[E0277]: the type `[u8]` cannot be indexed by `i8`
+  --> $DIR/integral-indexing.rs:13:5
+   |
+LL |     s.as_bytes()[3i8];
+   |     ^^^^^^^^^^^^^^^^^ slice indices are of type `usize` or ranges of `usize`
+   |
+   = help: the trait `std::slice::SliceIndex<[u8]>` is not implemented for `i8`
+   = note: required because of the requirements on the impl of `std::ops::Index<i8>` for `[u8]`
+
+error[E0277]: the type `[u8]` cannot be indexed by `u32`
+  --> $DIR/integral-indexing.rs:14:5
+   |
+LL |     s.as_bytes()[3u32];
+   |     ^^^^^^^^^^^^^^^^^^ slice indices are of type `usize` or ranges of `usize`
+   |
+   = help: the trait `std::slice::SliceIndex<[u8]>` is not implemented for `u32`
+   = note: required because of the requirements on the impl of `std::ops::Index<u32>` for `[u8]`
+
+error[E0277]: the type `[u8]` cannot be indexed by `i32`
+  --> $DIR/integral-indexing.rs:15:5
+   |
+LL |     s.as_bytes()[3i32];
+   |     ^^^^^^^^^^^^^^^^^^ slice indices are of type `usize` or ranges of `usize`
+   |
+   = help: the trait `std::slice::SliceIndex<[u8]>` is not implemented for `i32`
+   = note: required because of the requirements on the impl of `std::ops::Index<i32>` for `[u8]`
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/integral-variable-unification-error.rs b/src/test/ui/integral-variable-unification-error.rs
new file mode 100644
index 0000000..3eefcde
--- /dev/null
+++ b/src/test/ui/integral-variable-unification-error.rs
@@ -0,0 +1,8 @@
+fn main() {
+    let mut x = 2;
+    x = 5.0;
+    //~^ ERROR mismatched types
+    //~| expected type `{integer}`
+    //~| found type `{float}`
+    //~| expected integer, found floating-point number
+}
diff --git a/src/test/ui/integral-variable-unification-error.stderr b/src/test/ui/integral-variable-unification-error.stderr
new file mode 100644
index 0000000..262203b
--- /dev/null
+++ b/src/test/ui/integral-variable-unification-error.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/integral-variable-unification-error.rs:3:9
+   |
+LL |     x = 5.0;
+   |         ^^^ expected integer, found floating-point number
+   |
+   = note: expected type `{integer}`
+              found type `{float}`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/interior-mutability/interior-mutability.rs b/src/test/ui/interior-mutability/interior-mutability.rs
new file mode 100644
index 0000000..ddc882c
--- /dev/null
+++ b/src/test/ui/interior-mutability/interior-mutability.rs
@@ -0,0 +1,7 @@
+use std::cell::Cell;
+use std::panic::catch_unwind;
+fn main() {
+    let mut x = Cell::new(22);
+    catch_unwind(|| { x.set(23); });
+    //~^ ERROR the type `std::cell::UnsafeCell<i32>` may contain interior mutability and a
+}
diff --git a/src/test/ui/interior-mutability/interior-mutability.stderr b/src/test/ui/interior-mutability/interior-mutability.stderr
new file mode 100644
index 0000000..31390bc
--- /dev/null
+++ b/src/test/ui/interior-mutability/interior-mutability.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the type `std::cell::UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
+  --> $DIR/interior-mutability.rs:5:5
+   |
+LL |     catch_unwind(|| { x.set(23); });
+   |     ^^^^^^^^^^^^ `std::cell::UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
+   |
+   = help: within `std::cell::Cell<i32>`, the trait `std::panic::RefUnwindSafe` is not implemented for `std::cell::UnsafeCell<i32>`
+   = note: required because it appears within the type `std::cell::Cell<i32>`
+   = note: required because of the requirements on the impl of `std::panic::UnwindSafe` for `&std::cell::Cell<i32>`
+   = note: required because it appears within the type `[closure@$DIR/interior-mutability.rs:5:18: 5:35 x:&std::cell::Cell<i32>]`
+   = note: required by `std::panic::catch_unwind`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/internal/auxiliary/internal_unstable.rs b/src/test/ui/internal/auxiliary/internal_unstable.rs
new file mode 100644
index 0000000..7c79dcb
--- /dev/null
+++ b/src/test/ui/internal/auxiliary/internal_unstable.rs
@@ -0,0 +1,92 @@
+#![feature(staged_api, allow_internal_unstable)]
+#![stable(feature = "stable", since = "1.0.0")]
+
+#[unstable(feature = "function", issue = "0")]
+pub fn unstable() {}
+
+
+#[stable(feature = "stable", since = "1.0.0")]
+pub struct Foo {
+    #[unstable(feature = "struct_field", issue = "0")]
+    pub x: u8
+}
+
+impl Foo {
+    #[unstable(feature = "method", issue = "0")]
+    pub fn method(&self) {}
+}
+
+#[stable(feature = "stable", since = "1.0.0")]
+pub struct Bar {
+    #[unstable(feature = "struct2_field", issue = "0")]
+    pub x: u8
+}
+
+#[stable(feature = "stable", since = "1.0.0")]
+#[allow_internal_unstable(function)]
+#[macro_export]
+macro_rules! call_unstable_allow {
+    () => { $crate::unstable() }
+}
+
+#[stable(feature = "stable", since = "1.0.0")]
+#[allow_internal_unstable(struct_field)]
+#[macro_export]
+macro_rules! construct_unstable_allow {
+    ($e: expr) => {
+        $crate::Foo { x: $e }
+    }
+}
+
+#[stable(feature = "stable", since = "1.0.0")]
+#[allow_internal_unstable(method)]
+#[macro_export]
+macro_rules! call_method_allow {
+    ($e: expr) => { $e.method() }
+}
+
+#[stable(feature = "stable", since = "1.0.0")]
+#[allow_internal_unstable(struct_field, struct2_field)]
+#[macro_export]
+macro_rules! access_field_allow {
+    ($e: expr) => { $e.x }
+}
+
+#[stable(feature = "stable", since = "1.0.0")]
+#[allow_internal_unstable()]
+#[macro_export]
+macro_rules! pass_through_allow {
+    ($e: expr) => { $e }
+}
+
+#[stable(feature = "stable", since = "1.0.0")]
+#[macro_export]
+macro_rules! call_unstable_noallow {
+    () => { $crate::unstable() }
+}
+
+#[stable(feature = "stable", since = "1.0.0")]
+#[macro_export]
+macro_rules! construct_unstable_noallow {
+    ($e: expr) => {
+        $crate::Foo { x: $e }
+    }
+}
+
+#[stable(feature = "stable", since = "1.0.0")]
+#[macro_export]
+macro_rules! call_method_noallow {
+    ($e: expr) => { $e.method() }
+}
+
+#[stable(feature = "stable", since = "1.0.0")]
+#[macro_export]
+macro_rules! access_field_noallow {
+    ($e: expr) => { $e.x }
+}
+
+#[stable(feature = "stable", since = "1.0.0")]
+#[macro_export]
+macro_rules! pass_through_noallow {
+    ($e: expr) => { $e }
+}
diff --git a/src/test/ui/internal/internal-unstable-noallow.rs b/src/test/ui/internal/internal-unstable-noallow.rs
new file mode 100644
index 0000000..616f666
--- /dev/null
+++ b/src/test/ui/internal/internal-unstable-noallow.rs
@@ -0,0 +1,23 @@
+// this has to be separate to internal-unstable.rs because these tests
+// have error messages pointing deep into the internals of the
+// cross-crate macros, and hence need to use error-pattern instead of
+// the // ~ form.
+
+// aux-build:internal_unstable.rs
+// error-pattern:use of unstable library feature 'function'
+// error-pattern:use of unstable library feature 'struct_field'
+// error-pattern:use of unstable library feature 'method'
+// error-pattern:use of unstable library feature 'struct2_field'
+
+#[macro_use]
+extern crate internal_unstable;
+
+fn main() {
+    call_unstable_noallow!();
+
+    construct_unstable_noallow!(0);
+
+    |x: internal_unstable::Foo| { call_method_noallow!(x) };
+
+    |x: internal_unstable::Bar| { access_field_noallow!(x) };
+}
diff --git a/src/test/ui/internal/internal-unstable-noallow.stderr b/src/test/ui/internal/internal-unstable-noallow.stderr
new file mode 100644
index 0000000..7247f68
--- /dev/null
+++ b/src/test/ui/internal/internal-unstable-noallow.stderr
@@ -0,0 +1,39 @@
+error[E0658]: use of unstable library feature 'function'
+  --> $DIR/internal-unstable-noallow.rs:16:5
+   |
+LL |     call_unstable_noallow!();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(function)] to the crate attributes to enable
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error[E0658]: use of unstable library feature 'struct_field'
+  --> $DIR/internal-unstable-noallow.rs:18:5
+   |
+LL |     construct_unstable_noallow!(0);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(struct_field)] to the crate attributes to enable
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error[E0658]: use of unstable library feature 'method'
+  --> $DIR/internal-unstable-noallow.rs:20:35
+   |
+LL |     |x: internal_unstable::Foo| { call_method_noallow!(x) };
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(method)] to the crate attributes to enable
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error[E0658]: use of unstable library feature 'struct2_field'
+  --> $DIR/internal-unstable-noallow.rs:22:35
+   |
+LL |     |x: internal_unstable::Bar| { access_field_noallow!(x) };
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(struct2_field)] to the crate attributes to enable
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/internal/internal-unstable-thread-local.rs b/src/test/ui/internal/internal-unstable-thread-local.rs
new file mode 100644
index 0000000..b9194c6
--- /dev/null
+++ b/src/test/ui/internal/internal-unstable-thread-local.rs
@@ -0,0 +1,11 @@
+// aux-build:internal_unstable.rs
+
+#![allow(dead_code)]
+
+extern crate internal_unstable;
+
+
+thread_local!(static FOO: () = ());
+thread_local!(static BAR: () = internal_unstable::unstable()); //~ ERROR use of unstable
+
+fn main() {}
diff --git a/src/test/ui/internal/internal-unstable-thread-local.stderr b/src/test/ui/internal/internal-unstable-thread-local.stderr
new file mode 100644
index 0000000..603bdc3
--- /dev/null
+++ b/src/test/ui/internal/internal-unstable-thread-local.stderr
@@ -0,0 +1,11 @@
+error[E0658]: use of unstable library feature 'function'
+  --> $DIR/internal-unstable-thread-local.rs:9:32
+   |
+LL | thread_local!(static BAR: () = internal_unstable::unstable());
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(function)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/internal/internal-unstable.rs b/src/test/ui/internal/internal-unstable.rs
new file mode 100644
index 0000000..e09a5d8
--- /dev/null
+++ b/src/test/ui/internal/internal-unstable.rs
@@ -0,0 +1,42 @@
+// aux-build:internal_unstable.rs
+
+#![feature(allow_internal_unstable)]
+
+#[macro_use]
+extern crate internal_unstable;
+
+macro_rules! foo {
+    ($e: expr, $f: expr) => {{
+        $e;
+        $f;
+        internal_unstable::unstable(); //~ ERROR use of unstable
+    }}
+}
+
+#[allow_internal_unstable(function)]
+macro_rules! bar {
+    ($e: expr) => {{
+        foo!($e,
+             internal_unstable::unstable());
+        internal_unstable::unstable();
+    }}
+}
+
+fn main() {
+    // ok, the instability is contained.
+    call_unstable_allow!();
+    construct_unstable_allow!(0);
+    |x: internal_unstable::Foo| { call_method_allow!(x) };
+    |x: internal_unstable::Bar| { access_field_allow!(x) };
+
+    // bad.
+    pass_through_allow!(internal_unstable::unstable()); //~ ERROR use of unstable
+
+    pass_through_noallow!(internal_unstable::unstable()); //~ ERROR use of unstable
+
+
+
+    println!("{:?}", internal_unstable::unstable()); //~ ERROR use of unstable
+
+    bar!(internal_unstable::unstable()); //~ ERROR use of unstable
+}
diff --git a/src/test/ui/internal/internal-unstable.stderr b/src/test/ui/internal/internal-unstable.stderr
new file mode 100644
index 0000000..5c14fed
--- /dev/null
+++ b/src/test/ui/internal/internal-unstable.stderr
@@ -0,0 +1,46 @@
+error[E0658]: use of unstable library feature 'function'
+  --> $DIR/internal-unstable.rs:33:25
+   |
+LL |     pass_through_allow!(internal_unstable::unstable());
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(function)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'function'
+  --> $DIR/internal-unstable.rs:35:27
+   |
+LL |     pass_through_noallow!(internal_unstable::unstable());
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(function)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'function'
+  --> $DIR/internal-unstable.rs:39:22
+   |
+LL |     println!("{:?}", internal_unstable::unstable());
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(function)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'function'
+  --> $DIR/internal-unstable.rs:41:10
+   |
+LL |     bar!(internal_unstable::unstable());
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(function)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'function'
+  --> $DIR/internal-unstable.rs:12:9
+   |
+LL |         internal_unstable::unstable();
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     bar!(internal_unstable::unstable());
+   |     ------------------------------------ in this macro invocation
+   |
+   = help: add #![feature(function)] to the crate attributes to enable
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/invalid-module-declaration/auxiliary/foo/bar.rs b/src/test/ui/invalid-module-declaration/auxiliary/foo/bar.rs
new file mode 100644
index 0000000..bcfd7dc
--- /dev/null
+++ b/src/test/ui/invalid-module-declaration/auxiliary/foo/bar.rs
@@ -0,0 +1 @@
+pub mod baz;
diff --git a/src/test/ui/invalid-module-declaration/auxiliary/foo/mod.rs b/src/test/ui/invalid-module-declaration/auxiliary/foo/mod.rs
new file mode 100644
index 0000000..46f285c
--- /dev/null
+++ b/src/test/ui/invalid-module-declaration/auxiliary/foo/mod.rs
@@ -0,0 +1 @@
+pub mod bar;
diff --git a/src/test/ui/invalid-module-declaration/invalid-module-declaration.rs b/src/test/ui/invalid-module-declaration/invalid-module-declaration.rs
new file mode 100644
index 0000000..3b1cd9f
--- /dev/null
+++ b/src/test/ui/invalid-module-declaration/invalid-module-declaration.rs
@@ -0,0 +1,7 @@
+// ignore-tidy-linelength
+
+mod auxiliary {
+    mod foo;
+}
+
+fn main() {}
diff --git a/src/test/ui/invalid-module-declaration/invalid-module-declaration.stderr b/src/test/ui/invalid-module-declaration/invalid-module-declaration.stderr
new file mode 100644
index 0000000..c95df5b
--- /dev/null
+++ b/src/test/ui/invalid-module-declaration/invalid-module-declaration.stderr
@@ -0,0 +1,11 @@
+error[E0583]: file not found for module `baz`
+  --> $DIR/auxiliary/foo/bar.rs:1:9
+   |
+LL | pub mod baz;
+   |         ^^^
+   |
+   = help: name the file either bar/baz.rs or bar/baz/mod.rs inside the directory "$DIR/auxiliary/foo"
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0583`.
diff --git a/src/test/ui/invalid-self-argument/bare-fn-start.rs b/src/test/ui/invalid-self-argument/bare-fn-start.rs
new file mode 100644
index 0000000..741ba5f
--- /dev/null
+++ b/src/test/ui/invalid-self-argument/bare-fn-start.rs
@@ -0,0 +1,5 @@
+fn a(&self) { }
+//~^ ERROR unexpected `self` argument in function
+//~| NOTE `self` is only valid as the first argument of an associated function
+
+fn main() { }
diff --git a/src/test/ui/invalid-self-argument/bare-fn-start.stderr b/src/test/ui/invalid-self-argument/bare-fn-start.stderr
new file mode 100644
index 0000000..6a878b6
--- /dev/null
+++ b/src/test/ui/invalid-self-argument/bare-fn-start.stderr
@@ -0,0 +1,8 @@
+error: unexpected `self` argument in function
+  --> $DIR/bare-fn-start.rs:1:7
+   |
+LL | fn a(&self) { }
+   |       ^^^^ `self` is only valid as the first argument of an associated function
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/invalid-self-argument/bare-fn.rs b/src/test/ui/invalid-self-argument/bare-fn.rs
new file mode 100644
index 0000000..704fa99
--- /dev/null
+++ b/src/test/ui/invalid-self-argument/bare-fn.rs
@@ -0,0 +1,5 @@
+fn b(foo: u32, &mut self) { }
+//~^ ERROR unexpected `self` argument in function
+//~| NOTE `self` is only valid as the first argument of an associated function
+
+fn main() { }
diff --git a/src/test/ui/invalid-self-argument/bare-fn.stderr b/src/test/ui/invalid-self-argument/bare-fn.stderr
new file mode 100644
index 0000000..b13f746
--- /dev/null
+++ b/src/test/ui/invalid-self-argument/bare-fn.stderr
@@ -0,0 +1,8 @@
+error: unexpected `self` argument in function
+  --> $DIR/bare-fn.rs:1:21
+   |
+LL | fn b(foo: u32, &mut self) { }
+   |                     ^^^^ `self` is only valid as the first argument of an associated function
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/invalid-self-argument/trait-fn.rs b/src/test/ui/invalid-self-argument/trait-fn.rs
new file mode 100644
index 0000000..31e867b
--- /dev/null
+++ b/src/test/ui/invalid-self-argument/trait-fn.rs
@@ -0,0 +1,11 @@
+struct Foo {}
+
+impl Foo {
+    fn c(foo: u32, self) {}
+    //~^ ERROR unexpected `self` argument in function
+    //~| NOTE `self` is only valid as the first argument of an associated function
+
+    fn good(&mut self, foo: u32) {}
+}
+
+fn main() { }
diff --git a/src/test/ui/invalid-self-argument/trait-fn.stderr b/src/test/ui/invalid-self-argument/trait-fn.stderr
new file mode 100644
index 0000000..b3c2cc5
--- /dev/null
+++ b/src/test/ui/invalid-self-argument/trait-fn.stderr
@@ -0,0 +1,8 @@
+error: unexpected `self` argument in function
+  --> $DIR/trait-fn.rs:4:20
+   |
+LL |     fn c(foo: u32, self) {}
+   |                    ^^^^ `self` is only valid as the first argument of an associated function
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/invalid/invalid-crate-type.rs b/src/test/ui/invalid/invalid-crate-type.rs
new file mode 100644
index 0000000..6c44c3b
--- /dev/null
+++ b/src/test/ui/invalid/invalid-crate-type.rs
@@ -0,0 +1,48 @@
+// regression test for issue 11256
+#![crate_type="foo"]    //~ ERROR invalid `crate_type` value
+
+// Tests for suggestions (#53958)
+
+#![crate_type="statoclib"]
+//~^ ERROR invalid `crate_type` value
+//~| HELP did you mean
+//~| SUGGESTION staticlib
+
+#![crate_type="procmacro"]
+//~^ ERROR invalid `crate_type` value
+//~| HELP did you mean
+//~| SUGGESTION proc-macro
+
+#![crate_type="static-lib"]
+//~^ ERROR invalid `crate_type` value
+//~| HELP did you mean
+//~| SUGGESTION staticlib
+
+#![crate_type="drylib"]
+//~^ ERROR invalid `crate_type` value
+//~| HELP did you mean
+//~| SUGGESTION dylib
+
+#![crate_type="dlib"]
+//~^ ERROR invalid `crate_type` value
+//~| HELP did you mean
+//~| SUGGESTION rlib
+
+#![crate_type="lob"]
+//~^ ERROR invalid `crate_type` value
+//~| HELP did you mean
+//~| SUGGESTION lib
+
+#![crate_type="bon"]
+//~^ ERROR invalid `crate_type` value
+//~| HELP did you mean
+//~| SUGGESTION bin
+
+#![crate_type="cdalib"]
+//~^ ERROR invalid `crate_type` value
+//~| HELP did you mean
+//~| SUGGESTION cdylib
+
+fn main() {
+    return
+}
diff --git a/src/test/ui/invalid/invalid-crate-type.stderr b/src/test/ui/invalid/invalid-crate-type.stderr
new file mode 100644
index 0000000..030dc96
--- /dev/null
+++ b/src/test/ui/invalid/invalid-crate-type.stderr
@@ -0,0 +1,58 @@
+error: invalid `crate_type` value
+  --> $DIR/invalid-crate-type.rs:2:15
+   |
+LL | #![crate_type="foo"]
+   |               ^^^^^
+   |
+   = note: #[deny(unknown_crate_types)] on by default
+
+error: invalid `crate_type` value
+  --> $DIR/invalid-crate-type.rs:6:15
+   |
+LL | #![crate_type="statoclib"]
+   |               ^^^^^^^^^^^ help: did you mean: `"staticlib"`
+
+error: invalid `crate_type` value
+  --> $DIR/invalid-crate-type.rs:11:15
+   |
+LL | #![crate_type="procmacro"]
+   |               ^^^^^^^^^^^ help: did you mean: `"proc-macro"`
+
+error: invalid `crate_type` value
+  --> $DIR/invalid-crate-type.rs:16:15
+   |
+LL | #![crate_type="static-lib"]
+   |               ^^^^^^^^^^^^ help: did you mean: `"staticlib"`
+
+error: invalid `crate_type` value
+  --> $DIR/invalid-crate-type.rs:21:15
+   |
+LL | #![crate_type="drylib"]
+   |               ^^^^^^^^ help: did you mean: `"dylib"`
+
+error: invalid `crate_type` value
+  --> $DIR/invalid-crate-type.rs:26:15
+   |
+LL | #![crate_type="dlib"]
+   |               ^^^^^^ help: did you mean: `"rlib"`
+
+error: invalid `crate_type` value
+  --> $DIR/invalid-crate-type.rs:31:15
+   |
+LL | #![crate_type="lob"]
+   |               ^^^^^ help: did you mean: `"lib"`
+
+error: invalid `crate_type` value
+  --> $DIR/invalid-crate-type.rs:36:15
+   |
+LL | #![crate_type="bon"]
+   |               ^^^^^ help: did you mean: `"bin"`
+
+error: invalid `crate_type` value
+  --> $DIR/invalid-crate-type.rs:41:15
+   |
+LL | #![crate_type="cdalib"]
+   |               ^^^^^^^^ help: did you mean: `"cdylib"`
+
+error: aborting due to 9 previous errors
+
diff --git a/src/test/ui/invalid/invalid-inline.rs b/src/test/ui/invalid/invalid-inline.rs
new file mode 100644
index 0000000..8aa8f99
--- /dev/null
+++ b/src/test/ui/invalid/invalid-inline.rs
@@ -0,0 +1,19 @@
+#![allow(dead_code)]
+
+#[inline(please_no)] //~ ERROR invalid argument
+fn a() {
+}
+
+#[inline(please,no)] //~ ERROR expected one argument
+fn b() {
+}
+
+#[inline()] //~ ERROR expected one argument
+fn c() {
+}
+
+fn main() {
+    a();
+    b();
+    c();
+}
diff --git a/src/test/ui/invalid/invalid-inline.stderr b/src/test/ui/invalid/invalid-inline.stderr
new file mode 100644
index 0000000..ce29951
--- /dev/null
+++ b/src/test/ui/invalid/invalid-inline.stderr
@@ -0,0 +1,22 @@
+error[E0535]: invalid argument
+  --> $DIR/invalid-inline.rs:3:10
+   |
+LL | #[inline(please_no)]
+   |          ^^^^^^^^^
+
+error[E0534]: expected one argument
+  --> $DIR/invalid-inline.rs:7:1
+   |
+LL | #[inline(please,no)]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error[E0534]: expected one argument
+  --> $DIR/invalid-inline.rs:11:1
+   |
+LL | #[inline()]
+   | ^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0534, E0535.
+For more information about an error, try `rustc --explain E0534`.
diff --git a/src/test/ui/invalid/invalid-macro-matcher.rs b/src/test/ui/invalid/invalid-macro-matcher.rs
new file mode 100644
index 0000000..ff79d4e
--- /dev/null
+++ b/src/test/ui/invalid/invalid-macro-matcher.rs
@@ -0,0 +1,8 @@
+#![allow(unused_macros)]
+
+macro_rules! invalid {
+    _ => (); //~ ERROR invalid macro matcher
+}
+
+fn main() {
+}
diff --git a/src/test/ui/invalid/invalid-macro-matcher.stderr b/src/test/ui/invalid/invalid-macro-matcher.stderr
new file mode 100644
index 0000000..dbe025b
--- /dev/null
+++ b/src/test/ui/invalid/invalid-macro-matcher.stderr
@@ -0,0 +1,8 @@
+error: invalid macro matcher; matchers must be contained in balanced delimiters
+  --> $DIR/invalid-macro-matcher.rs:4:5
+   |
+LL |     _ => ();
+   |     ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/invalid/invalid-path-in-const.rs b/src/test/ui/invalid/invalid-path-in-const.rs
new file mode 100644
index 0000000..51eb860
--- /dev/null
+++ b/src/test/ui/invalid/invalid-path-in-const.rs
@@ -0,0 +1,4 @@
+fn main() {
+    fn f(a: [u8; u32::DOESNOTEXIST]) {}
+    //~^ ERROR no associated item named `DOESNOTEXIST` found for type `u32`
+}
diff --git a/src/test/ui/invalid/invalid-path-in-const.stderr b/src/test/ui/invalid/invalid-path-in-const.stderr
new file mode 100644
index 0000000..a14ab7d
--- /dev/null
+++ b/src/test/ui/invalid/invalid-path-in-const.stderr
@@ -0,0 +1,9 @@
+error[E0599]: no associated item named `DOESNOTEXIST` found for type `u32` in the current scope
+  --> $DIR/invalid-path-in-const.rs:2:23
+   |
+LL |     fn f(a: [u8; u32::DOESNOTEXIST]) {}
+   |                       ^^^^^^^^^^^^ associated item not found in `u32`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/invalid/invalid-plugin-attr.rs b/src/test/ui/invalid/invalid-plugin-attr.rs
new file mode 100644
index 0000000..2cbd523
--- /dev/null
+++ b/src/test/ui/invalid/invalid-plugin-attr.rs
@@ -0,0 +1,7 @@
+#![deny(unused_attributes)]
+#![feature(plugin)]
+
+#[plugin(bla)]  //~ ERROR unused attribute
+                //~^ ERROR should be an inner attribute
+
+fn main() {}
diff --git a/src/test/ui/invalid/invalid-plugin-attr.stderr b/src/test/ui/invalid/invalid-plugin-attr.stderr
new file mode 100644
index 0000000..c7b2ce4
--- /dev/null
+++ b/src/test/ui/invalid/invalid-plugin-attr.stderr
@@ -0,0 +1,20 @@
+error: unused attribute
+  --> $DIR/invalid-plugin-attr.rs:4:1
+   |
+LL | #[plugin(bla)]
+   | ^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/invalid-plugin-attr.rs:1:9
+   |
+LL | #![deny(unused_attributes)]
+   |         ^^^^^^^^^^^^^^^^^
+
+error: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+  --> $DIR/invalid-plugin-attr.rs:4:1
+   |
+LL | #[plugin(bla)]
+   | ^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/invalid/invalid-variadic-function.rs b/src/test/ui/invalid/invalid-variadic-function.rs
new file mode 100644
index 0000000..8d23f0e
--- /dev/null
+++ b/src/test/ui/invalid/invalid-variadic-function.rs
@@ -0,0 +1,3 @@
+extern "C" fn foo(x: u8, ...);
+//~^ ERROR only foreign functions are allowed to be C-variadic
+//~| ERROR expected one of `->`, `where`, or `{`, found `;`
diff --git a/src/test/ui/invalid/invalid-variadic-function.stderr b/src/test/ui/invalid/invalid-variadic-function.stderr
new file mode 100644
index 0000000..b2dbf8b
--- /dev/null
+++ b/src/test/ui/invalid/invalid-variadic-function.stderr
@@ -0,0 +1,14 @@
+error: only foreign functions are allowed to be C-variadic
+  --> $DIR/invalid-variadic-function.rs:1:26
+   |
+LL | extern "C" fn foo(x: u8, ...);
+   |                          ^^^
+
+error: expected one of `->`, `where`, or `{`, found `;`
+  --> $DIR/invalid-variadic-function.rs:1:30
+   |
+LL | extern "C" fn foo(x: u8, ...);
+   |                              ^ expected one of `->`, `where`, or `{` here
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/invalid_crate_type_syntax.rs b/src/test/ui/invalid_crate_type_syntax.rs
new file mode 100644
index 0000000..8157ccd
--- /dev/null
+++ b/src/test/ui/invalid_crate_type_syntax.rs
@@ -0,0 +1,6 @@
+// regression test for issue 16974
+#![crate_type(lib)]  //~ ERROR attribute must be of the form
+
+fn my_lib_fn() {}
+
+fn main() {}
diff --git a/src/test/ui/invalid_crate_type_syntax.stderr b/src/test/ui/invalid_crate_type_syntax.stderr
new file mode 100644
index 0000000..cb3faed
--- /dev/null
+++ b/src/test/ui/invalid_crate_type_syntax.stderr
@@ -0,0 +1,8 @@
+error: attribute must be of the form `#[crate_type = "bin|lib|..."]`
+  --> $DIR/invalid_crate_type_syntax.rs:2:1
+   |
+LL | #![crate_type(lib)]
+   | ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/invalid_dispatch_from_dyn_impls.rs b/src/test/ui/invalid_dispatch_from_dyn_impls.rs
new file mode 100644
index 0000000..c471689
--- /dev/null
+++ b/src/test/ui/invalid_dispatch_from_dyn_impls.rs
@@ -0,0 +1,42 @@
+#![feature(unsize, dispatch_from_dyn)]
+
+use std::{
+    ops::DispatchFromDyn,
+    marker::{Unsize, PhantomData},
+};
+
+struct WrapperWithExtraField<T>(T, i32);
+
+impl<T, U> DispatchFromDyn<WrapperWithExtraField<U>> for WrapperWithExtraField<T>
+where
+    T: DispatchFromDyn<U>,
+{} //~^^^ ERROR [E0378]
+
+
+struct MultiplePointers<T: ?Sized>{
+    ptr1: *const T,
+    ptr2: *const T,
+}
+
+impl<T: ?Sized, U: ?Sized> DispatchFromDyn<MultiplePointers<U>> for MultiplePointers<T>
+where
+    T: Unsize<U>,
+{} //~^^^ ERROR [E0378]
+
+
+struct NothingToCoerce<T: ?Sized> {
+    data: PhantomData<T>,
+}
+
+impl<T: ?Sized, U: ?Sized> DispatchFromDyn<NothingToCoerce<T>> for NothingToCoerce<U> {}
+//~^ ERROR [E0378]
+
+#[repr(C)]
+struct HasReprC<T: ?Sized>(Box<T>);
+
+impl<T: ?Sized, U: ?Sized> DispatchFromDyn<HasReprC<U>> for HasReprC<T>
+where
+    T: Unsize<U>,
+{} //~^^^ ERROR [E0378]
+
+fn main() {}
diff --git a/src/test/ui/invalid_dispatch_from_dyn_impls.stderr b/src/test/ui/invalid_dispatch_from_dyn_impls.stderr
new file mode 100644
index 0000000..bd01646
--- /dev/null
+++ b/src/test/ui/invalid_dispatch_from_dyn_impls.stderr
@@ -0,0 +1,41 @@
+error[E0378]: the trait `DispatchFromDyn` may only be implemented for structs containing the field being coerced, `PhantomData` fields, and nothing else
+  --> $DIR/invalid_dispatch_from_dyn_impls.rs:10:1
+   |
+LL | / impl<T, U> DispatchFromDyn<WrapperWithExtraField<U>> for WrapperWithExtraField<T>
+LL | | where
+LL | |     T: DispatchFromDyn<U>,
+LL | | {}
+   | |__^
+   |
+   = note: extra field `1` of type `i32` is not allowed
+
+error[E0378]: implementing the `DispatchFromDyn` trait requires multiple coercions
+  --> $DIR/invalid_dispatch_from_dyn_impls.rs:21:1
+   |
+LL | / impl<T: ?Sized, U: ?Sized> DispatchFromDyn<MultiplePointers<U>> for MultiplePointers<T>
+LL | | where
+LL | |     T: Unsize<U>,
+LL | | {}
+   | |__^
+   |
+   = note: the trait `DispatchFromDyn` may only be implemented for a coercion between structures with a single field being coerced
+   = note: currently, 2 fields need coercions: `ptr1` (`*const T` to `*const U`), `ptr2` (`*const T` to `*const U`)
+
+error[E0378]: the trait `DispatchFromDyn` may only be implemented for a coercion between structures with a single field being coerced, none found
+  --> $DIR/invalid_dispatch_from_dyn_impls.rs:31:1
+   |
+LL | impl<T: ?Sized, U: ?Sized> DispatchFromDyn<NothingToCoerce<T>> for NothingToCoerce<U> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0378]: structs implementing `DispatchFromDyn` may not have `#[repr(packed)]` or `#[repr(C)]`
+  --> $DIR/invalid_dispatch_from_dyn_impls.rs:37:1
+   |
+LL | / impl<T: ?Sized, U: ?Sized> DispatchFromDyn<HasReprC<U>> for HasReprC<T>
+LL | | where
+LL | |     T: Unsize<U>,
+LL | | {}
+   | |__^
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0378`.
diff --git a/src/test/ui/issue-59508-1.rs b/src/test/ui/issue-59508-1.rs
new file mode 100644
index 0000000..4fbed9b
--- /dev/null
+++ b/src/test/ui/issue-59508-1.rs
@@ -0,0 +1,18 @@
+#![allow(dead_code)]
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+// This test checks that generic parameter re-ordering diagnostic suggestions mention that
+// consts come after types and lifetimes when the `const_generics` feature is enabled.
+// We cannot run rustfix on this test because of the above const generics warning.
+
+struct A;
+
+impl A {
+    pub fn do_things<T, 'a, 'b: 'a>() {
+    //~^ ERROR lifetime parameters must be declared prior to type parameters
+        println!("panic");
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issue-59508-1.stderr b/src/test/ui/issue-59508-1.stderr
new file mode 100644
index 0000000..8fb7d7c
--- /dev/null
+++ b/src/test/ui/issue-59508-1.stderr
@@ -0,0 +1,14 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/issue-59508-1.rs:2:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+
+error: lifetime parameters must be declared prior to type parameters
+  --> $DIR/issue-59508-1.rs:12:25
+   |
+LL |     pub fn do_things<T, 'a, 'b: 'a>() {
+   |                     ----^^--^^----- help: reorder the parameters: lifetimes, then types, then consts: `<'a, 'b: 'a, T>`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issue-59508.fixed b/src/test/ui/issue-59508.fixed
new file mode 100644
index 0000000..b5c60a1
--- /dev/null
+++ b/src/test/ui/issue-59508.fixed
@@ -0,0 +1,16 @@
+// run-rustfix
+
+#![allow(dead_code)]
+
+// This test checks that generic parameter re-ordering diagnostic suggestions contain bounds.
+
+struct A;
+
+impl A {
+    pub fn do_things<'a, 'b: 'a, T>() {
+    //~^ ERROR lifetime parameters must be declared prior to type parameters
+        println!("panic");
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issue-59508.rs b/src/test/ui/issue-59508.rs
new file mode 100644
index 0000000..0b39c5d
--- /dev/null
+++ b/src/test/ui/issue-59508.rs
@@ -0,0 +1,16 @@
+// run-rustfix
+
+#![allow(dead_code)]
+
+// This test checks that generic parameter re-ordering diagnostic suggestions contain bounds.
+
+struct A;
+
+impl A {
+    pub fn do_things<T, 'a, 'b: 'a>() {
+    //~^ ERROR lifetime parameters must be declared prior to type parameters
+        println!("panic");
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issue-59508.stderr b/src/test/ui/issue-59508.stderr
new file mode 100644
index 0000000..c0fdb2e
--- /dev/null
+++ b/src/test/ui/issue-59508.stderr
@@ -0,0 +1,8 @@
+error: lifetime parameters must be declared prior to type parameters
+  --> $DIR/issue-59508.rs:10:25
+   |
+LL |     pub fn do_things<T, 'a, 'b: 'a>() {
+   |                     ----^^--^^----- help: reorder the parameters: lifetimes, then types: `<'a, 'b: 'a, T>`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/auxiliary/empty-struct.rs b/src/test/ui/issues/auxiliary/empty-struct.rs
new file mode 100644
index 0000000..3fb40f6
--- /dev/null
+++ b/src/test/ui/issues/auxiliary/empty-struct.rs
@@ -0,0 +1,9 @@
+pub struct XEmpty1 {}
+pub struct XEmpty2;
+pub struct XEmpty6();
+
+pub enum XE {
+    XEmpty3 {},
+    XEmpty4,
+    XEmpty5(),
+}
diff --git a/src/test/ui/issues/auxiliary/issue-11680.rs b/src/test/ui/issues/auxiliary/issue-11680.rs
new file mode 100644
index 0000000..74abbf0
--- /dev/null
+++ b/src/test/ui/issues/auxiliary/issue-11680.rs
@@ -0,0 +1,9 @@
+enum Foo {
+    Bar(isize)
+}
+
+pub mod test {
+    enum Foo {
+        Bar(isize)
+    }
+}
diff --git a/src/test/ui/issues/auxiliary/issue-16725.rs b/src/test/ui/issues/auxiliary/issue-16725.rs
new file mode 100644
index 0000000..b75b5e2
--- /dev/null
+++ b/src/test/ui/issues/auxiliary/issue-16725.rs
@@ -0,0 +1,3 @@
+extern {
+    fn bar();
+}
diff --git a/src/test/ui/issues/auxiliary/issue-17718-const-privacy.rs b/src/test/ui/issues/auxiliary/issue-17718-const-privacy.rs
new file mode 100644
index 0000000..93cf4bf
--- /dev/null
+++ b/src/test/ui/issues/auxiliary/issue-17718-const-privacy.rs
@@ -0,0 +1,8 @@
+pub use foo::FOO2;
+
+pub const FOO: usize = 3;
+const BAR: usize = 3;
+
+mod foo {
+    pub const FOO2: usize = 3;
+}
diff --git a/src/test/ui/issues/auxiliary/issue-19163.rs b/src/test/ui/issues/auxiliary/issue-19163.rs
new file mode 100644
index 0000000..0c0d9e4
--- /dev/null
+++ b/src/test/ui/issues/auxiliary/issue-19163.rs
@@ -0,0 +1,6 @@
+#![crate_type = "lib"]
+
+#[macro_export]
+macro_rules! mywrite {
+    ($dst:expr, $($arg:tt)*) => ($dst.write_fmt(format_args!($($arg)*)))
+}
diff --git a/src/test/ui/issues/auxiliary/issue-1920.rs b/src/test/ui/issues/auxiliary/issue-1920.rs
new file mode 100644
index 0000000..1548cb9
--- /dev/null
+++ b/src/test/ui/issues/auxiliary/issue-1920.rs
@@ -0,0 +1,4 @@
+// Just exporting some type to test for correct diagnostics when this
+// crate is pulled in at a non-root location in client crate.
+
+pub struct S;
diff --git a/src/test/ui/issues/auxiliary/issue-21146-inc.rs b/src/test/ui/issues/auxiliary/issue-21146-inc.rs
new file mode 100644
index 0000000..32a3b9d
--- /dev/null
+++ b/src/test/ui/issues/auxiliary/issue-21146-inc.rs
@@ -0,0 +1,3 @@
+// include file for issue-21146.rs
+
+parse_error
diff --git a/src/test/ui/issues/auxiliary/issue-21202.rs b/src/test/ui/issues/auxiliary/issue-21202.rs
new file mode 100644
index 0000000..e3daa1b
--- /dev/null
+++ b/src/test/ui/issues/auxiliary/issue-21202.rs
@@ -0,0 +1,6 @@
+pub mod A {
+    pub struct Foo;
+    impl Foo {
+        fn foo(&self) { }
+    }
+}
diff --git a/src/test/ui/issues/auxiliary/issue-29181.rs b/src/test/ui/issues/auxiliary/issue-29181.rs
new file mode 100644
index 0000000..bd1a9be
--- /dev/null
+++ b/src/test/ui/issues/auxiliary/issue-29181.rs
@@ -0,0 +1,5 @@
+#![crate_type="lib"]
+
+pub mod foo {
+    pub use super::*;
+}
diff --git a/src/test/ui/issues/auxiliary/issue-30123-aux.rs b/src/test/ui/issues/auxiliary/issue-30123-aux.rs
new file mode 100644
index 0000000..07c743e
--- /dev/null
+++ b/src/test/ui/issues/auxiliary/issue-30123-aux.rs
@@ -0,0 +1,23 @@
+use std::marker::PhantomData;
+
+pub struct Directed;
+pub struct Undirected;
+
+pub struct Graph<N, E, Ty = Directed> {
+    nodes: Vec<PhantomData<N>>,
+    edges: Vec<PhantomData<E>>,
+    ty: PhantomData<Ty>,
+}
+
+
+impl<N, E> Graph<N, E, Directed> {
+    pub fn new() -> Self {
+        Graph{nodes: Vec::new(), edges: Vec::new(), ty: PhantomData}
+    }
+}
+
+impl<N, E> Graph<N, E, Undirected> {
+    pub fn new_undirected() -> Self {
+        Graph{nodes: Vec::new(), edges: Vec::new(), ty: PhantomData}
+    }
+}
diff --git a/src/test/ui/issues/auxiliary/issue-30535.rs b/src/test/ui/issues/auxiliary/issue-30535.rs
new file mode 100644
index 0000000..3608d4a
--- /dev/null
+++ b/src/test/ui/issues/auxiliary/issue-30535.rs
@@ -0,0 +1,5 @@
+#![crate_type="lib"]
+
+pub enum Foo {
+    FooV { data: () }
+}
diff --git a/src/test/ui/issues/auxiliary/issue-36708.rs b/src/test/ui/issues/auxiliary/issue-36708.rs
new file mode 100644
index 0000000..bd8580f
--- /dev/null
+++ b/src/test/ui/issues/auxiliary/issue-36708.rs
@@ -0,0 +1,5 @@
+#![crate_type = "lib"]
+
+pub trait Foo {
+    fn foo();
+}
diff --git a/src/test/ui/issues/auxiliary/issue-36881-aux.rs b/src/test/ui/issues/auxiliary/issue-36881-aux.rs
new file mode 100644
index 0000000..e373b64
--- /dev/null
+++ b/src/test/ui/issues/auxiliary/issue-36881-aux.rs
@@ -0,0 +1 @@
+pub trait Foo {}
diff --git a/src/test/ui/issues/auxiliary/issue-41549.rs b/src/test/ui/issues/auxiliary/issue-41549.rs
new file mode 100644
index 0000000..b7bd375
--- /dev/null
+++ b/src/test/ui/issues/auxiliary/issue-41549.rs
@@ -0,0 +1,3 @@
+pub trait Trait {
+    const CONST: u32;
+}
diff --git a/src/test/ui/issues/auxiliary/issue-52489.rs b/src/test/ui/issues/auxiliary/issue-52489.rs
new file mode 100644
index 0000000..c649930
--- /dev/null
+++ b/src/test/ui/issues/auxiliary/issue-52489.rs
@@ -0,0 +1,3 @@
+#![crate_type = "lib"]
+#![unstable(feature = "issue_52489_unstable", issue = "0")]
+#![feature(staged_api)]
diff --git a/src/test/ui/issues/auxiliary/issue-52891.rs b/src/test/ui/issues/auxiliary/issue-52891.rs
new file mode 100644
index 0000000..0759811
--- /dev/null
+++ b/src/test/ui/issues/auxiliary/issue-52891.rs
@@ -0,0 +1,33 @@
+pub mod a {
+    pub mod inner {
+    }
+}
+
+pub mod b {
+    pub mod inner {
+    }
+}
+
+pub mod c {}
+
+pub mod d {}
+
+pub mod e {}
+
+pub mod f {}
+
+pub mod g {}
+
+pub mod h {}
+
+pub mod i {}
+
+pub mod j {}
+
+pub mod k {}
+
+pub mod l {}
+
+pub mod m {}
+
+pub mod n {}
diff --git a/src/test/ui/issues/auxiliary/issue-56943.rs b/src/test/ui/issues/auxiliary/issue-56943.rs
new file mode 100644
index 0000000..65b9beb
--- /dev/null
+++ b/src/test/ui/issues/auxiliary/issue-56943.rs
@@ -0,0 +1,3 @@
+pub struct S;
+mod m { pub struct S; }
+pub use crate::m::S as S2;
diff --git a/src/test/ui/issues/auxiliary/issue-5844-aux.rs b/src/test/ui/issues/auxiliary/issue-5844-aux.rs
new file mode 100644
index 0000000..ea83378
--- /dev/null
+++ b/src/test/ui/issues/auxiliary/issue-5844-aux.rs
@@ -0,0 +1,3 @@
+extern "C" {
+    pub fn rand() -> u32;
+}
diff --git a/src/test/ui/issues/auxiliary/lint-stability.rs b/src/test/ui/issues/auxiliary/lint-stability.rs
new file mode 100644
index 0000000..3188d70
--- /dev/null
+++ b/src/test/ui/issues/auxiliary/lint-stability.rs
@@ -0,0 +1,188 @@
+#![crate_name="lint_stability"]
+#![crate_type = "lib"]
+#![feature(staged_api)]
+#![feature(associated_type_defaults)]
+#![stable(feature = "lint_stability", since = "1.0.0")]
+
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+#[rustc_deprecated(since = "1.0.0", reason = "text")]
+pub fn deprecated() {}
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+#[rustc_deprecated(since = "1.0.0", reason = "text")]
+pub fn deprecated_text() {}
+
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+#[rustc_deprecated(since = "99.99.99", reason = "text")]
+pub fn deprecated_future() {}
+
+#[unstable(feature = "unstable_test_feature", issue = "0")]
+#[rustc_deprecated(since = "1.0.0", reason = "text")]
+pub fn deprecated_unstable() {}
+#[unstable(feature = "unstable_test_feature", issue = "0")]
+#[rustc_deprecated(since = "1.0.0", reason = "text")]
+pub fn deprecated_unstable_text() {}
+
+#[unstable(feature = "unstable_test_feature", issue = "0")]
+pub fn unstable() {}
+#[unstable(feature = "unstable_test_feature", reason = "text", issue = "0")]
+pub fn unstable_text() {}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+pub fn stable() {}
+#[stable(feature = "rust1", since = "1.0.0")]
+pub fn stable_text() {}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct MethodTester;
+
+impl MethodTester {
+    #[stable(feature = "stable_test_feature", since = "1.0.0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    pub fn method_deprecated(&self) {}
+    #[stable(feature = "stable_test_feature", since = "1.0.0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    pub fn method_deprecated_text(&self) {}
+
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    pub fn method_deprecated_unstable(&self) {}
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    pub fn method_deprecated_unstable_text(&self) {}
+
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    pub fn method_unstable(&self) {}
+    #[unstable(feature = "unstable_test_feature", reason = "text", issue = "0")]
+    pub fn method_unstable_text(&self) {}
+
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn method_stable(&self) {}
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn method_stable_text(&self) {}
+}
+
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+pub trait Trait {
+    #[stable(feature = "stable_test_feature", since = "1.0.0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    fn trait_deprecated(&self) {}
+    #[stable(feature = "stable_test_feature", since = "1.0.0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    fn trait_deprecated_text(&self) {}
+
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    fn trait_deprecated_unstable(&self) {}
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    fn trait_deprecated_unstable_text(&self) {}
+
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    fn trait_unstable(&self) {}
+    #[unstable(feature = "unstable_test_feature", reason = "text", issue = "0")]
+    fn trait_unstable_text(&self) {}
+
+    #[stable(feature = "rust1", since = "1.0.0")]
+    fn trait_stable(&self) {}
+    #[stable(feature = "rust1", since = "1.0.0")]
+    fn trait_stable_text(&self) {}
+}
+
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+pub trait TraitWithAssociatedTypes {
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    type TypeUnstable = u8;
+    #[stable(feature = "stable_test_feature", since = "1.0.0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    type TypeDeprecated = u8;
+}
+
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+impl Trait for MethodTester {}
+
+#[unstable(feature = "unstable_test_feature", issue = "0")]
+pub trait UnstableTrait { fn dummy(&self) { } }
+
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+#[rustc_deprecated(since = "1.0.0", reason = "text")]
+pub trait DeprecatedTrait {
+    #[stable(feature = "stable_test_feature", since = "1.0.0")] fn dummy(&self) { }
+}
+
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+#[rustc_deprecated(since = "1.0.0", reason = "text")]
+pub struct DeprecatedStruct {
+    #[stable(feature = "stable_test_feature", since = "1.0.0")] pub i: isize
+}
+#[unstable(feature = "unstable_test_feature", issue = "0")]
+#[rustc_deprecated(since = "1.0.0", reason = "text")]
+pub struct DeprecatedUnstableStruct {
+    #[stable(feature = "stable_test_feature", since = "1.0.0")] pub i: isize
+}
+#[unstable(feature = "unstable_test_feature", issue = "0")]
+pub struct UnstableStruct {
+    #[stable(feature = "stable_test_feature", since = "1.0.0")] pub i: isize
+}
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct StableStruct {
+    #[stable(feature = "stable_test_feature", since = "1.0.0")] pub i: isize
+}
+#[unstable(feature = "unstable_test_feature", issue = "0")]
+pub enum UnstableEnum {}
+#[stable(feature = "rust1", since = "1.0.0")]
+pub enum StableEnum {}
+
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+#[rustc_deprecated(since = "1.0.0", reason = "text")]
+pub struct DeprecatedUnitStruct;
+#[unstable(feature = "unstable_test_feature", issue = "0")]
+#[rustc_deprecated(since = "1.0.0", reason = "text")]
+pub struct DeprecatedUnstableUnitStruct;
+#[unstable(feature = "unstable_test_feature", issue = "0")]
+pub struct UnstableUnitStruct;
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct StableUnitStruct;
+
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+pub enum Enum {
+    #[stable(feature = "stable_test_feature", since = "1.0.0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    DeprecatedVariant,
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    DeprecatedUnstableVariant,
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    UnstableVariant,
+
+    #[stable(feature = "rust1", since = "1.0.0")]
+    StableVariant,
+}
+
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+#[rustc_deprecated(since = "1.0.0", reason = "text")]
+pub struct DeprecatedTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub isize);
+#[unstable(feature = "unstable_test_feature", issue = "0")]
+#[rustc_deprecated(since = "1.0.0", reason = "text")]
+pub struct DeprecatedUnstableTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub isize);
+#[unstable(feature = "unstable_test_feature", issue = "0")]
+pub struct UnstableTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub isize);
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct StableTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub isize);
+
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+#[macro_export]
+macro_rules! macro_test {
+    () => (deprecated());
+}
+
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+#[macro_export]
+macro_rules! macro_test_arg {
+    ($func:expr) => ($func);
+}
+
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+#[macro_export]
+macro_rules! macro_test_arg_nested {
+    ($func:ident) => (macro_test_arg!($func()));
+}
diff --git a/src/test/ui/issues/auxiliary/private-trait-xc.rs b/src/test/ui/issues/auxiliary/private-trait-xc.rs
new file mode 100644
index 0000000..481a48a
--- /dev/null
+++ b/src/test/ui/issues/auxiliary/private-trait-xc.rs
@@ -0,0 +1 @@
+trait Foo {}
diff --git a/src/test/ui/issues/auxiliary/xcrate-issue-43189-a.rs b/src/test/ui/issues/auxiliary/xcrate-issue-43189-a.rs
new file mode 100644
index 0000000..9ab570f
--- /dev/null
+++ b/src/test/ui/issues/auxiliary/xcrate-issue-43189-a.rs
@@ -0,0 +1,7 @@
+#![crate_type="lib"]
+
+
+pub trait A {
+    fn a(&self) {}
+}
+impl A for () {}
diff --git a/src/test/ui/issues/auxiliary/xcrate-issue-43189-b.rs b/src/test/ui/issues/auxiliary/xcrate-issue-43189-b.rs
new file mode 100644
index 0000000..31dfb05
--- /dev/null
+++ b/src/test/ui/issues/auxiliary/xcrate-issue-43189-b.rs
@@ -0,0 +1,3 @@
+#![crate_type="lib"]
+
+pub extern crate xcrate_issue_43189_a;
diff --git a/src/test/ui/issues/auxiliary/xcrate-issue-46112-rexport-core.rs b/src/test/ui/issues/auxiliary/xcrate-issue-46112-rexport-core.rs
new file mode 100644
index 0000000..2b517b5
--- /dev/null
+++ b/src/test/ui/issues/auxiliary/xcrate-issue-46112-rexport-core.rs
@@ -0,0 +1,3 @@
+#![crate_type="lib"]
+
+pub extern crate core;
diff --git a/src/test/ui/issues/issue-10176.rs b/src/test/ui/issues/issue-10176.rs
new file mode 100644
index 0000000..ff0619b
--- /dev/null
+++ b/src/test/ui/issues/issue-10176.rs
@@ -0,0 +1,9 @@
+fn f() -> isize {
+    (return 1, return 2)
+//~^ ERROR mismatched types
+//~| expected type `isize`
+//~| found type `(!, !)`
+//~| expected isize, found tuple
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-10176.stderr b/src/test/ui/issues/issue-10176.stderr
new file mode 100644
index 0000000..4548244
--- /dev/null
+++ b/src/test/ui/issues/issue-10176.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-10176.rs:2:5
+   |
+LL | fn f() -> isize {
+   |           ----- expected `isize` because of return type
+LL |     (return 1, return 2)
+   |     ^^^^^^^^^^^^^^^^^^^^ expected isize, found tuple
+   |
+   = note: expected type `isize`
+              found type `(!, !)`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-10200.rs b/src/test/ui/issues/issue-10200.rs
new file mode 100644
index 0000000..12867a8
--- /dev/null
+++ b/src/test/ui/issues/issue-10200.rs
@@ -0,0 +1,9 @@
+struct Foo(bool);
+fn foo(_: usize) -> Foo { Foo(false) }
+
+fn main() {
+    match Foo(true) {
+        foo(x) //~ ERROR expected tuple struct/variant, found function `foo`
+        => ()
+    }
+}
diff --git a/src/test/ui/issues/issue-10200.stderr b/src/test/ui/issues/issue-10200.stderr
new file mode 100644
index 0000000..544716e
--- /dev/null
+++ b/src/test/ui/issues/issue-10200.stderr
@@ -0,0 +1,9 @@
+error[E0532]: expected tuple struct/variant, found function `foo`
+  --> $DIR/issue-10200.rs:6:9
+   |
+LL |         foo(x)
+   |         ^^^ help: a tuple struct with a similar name exists: `Foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0532`.
diff --git a/src/test/ui/issues/issue-10291.rs b/src/test/ui/issues/issue-10291.rs
new file mode 100644
index 0000000..877b0ab
--- /dev/null
+++ b/src/test/ui/issues/issue-10291.rs
@@ -0,0 +1,7 @@
+fn test<'x>(x: &'x isize) {
+    drop::<Box<for<'z> FnMut(&'z isize) -> &'z isize>>(Box::new(|z| {
+        x //~ ERROR E0312
+    }));
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-10291.stderr b/src/test/ui/issues/issue-10291.stderr
new file mode 100644
index 0000000..89ffd45
--- /dev/null
+++ b/src/test/ui/issues/issue-10291.stderr
@@ -0,0 +1,23 @@
+error[E0312]: lifetime of reference outlives lifetime of borrowed content...
+  --> $DIR/issue-10291.rs:3:9
+   |
+LL |         x
+   |         ^
+   |
+note: ...the reference is valid for the anonymous lifetime #2 defined on the body at 2:65...
+  --> $DIR/issue-10291.rs:2:65
+   |
+LL |       drop::<Box<for<'z> FnMut(&'z isize) -> &'z isize>>(Box::new(|z| {
+   |  _________________________________________________________________^
+LL | |         x
+LL | |     }));
+   | |_____^
+note: ...but the borrowed content is only valid for the lifetime 'x as defined on the function body at 1:9
+  --> $DIR/issue-10291.rs:1:9
+   |
+LL | fn test<'x>(x: &'x isize) {
+   |         ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0312`.
diff --git a/src/test/ui/issues/issue-10396.rs b/src/test/ui/issues/issue-10396.rs
new file mode 100644
index 0000000..d8e9aec
--- /dev/null
+++ b/src/test/ui/issues/issue-10396.rs
@@ -0,0 +1,14 @@
+// compile-pass
+#![allow(dead_code)]
+#[derive(Debug)]
+enum Foo<'s> {
+    V(&'s str)
+}
+
+fn f(arr: &[&Foo]) {
+    for &f in arr {
+        println!("{:?}", f);
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-10398.nll.stderr b/src/test/ui/issues/issue-10398.nll.stderr
new file mode 100644
index 0000000..f5f4974
--- /dev/null
+++ b/src/test/ui/issues/issue-10398.nll.stderr
@@ -0,0 +1,13 @@
+error[E0382]: use of moved value: `x`
+  --> $DIR/issue-10398.rs:7:14
+   |
+LL |         let _a = x;
+   |                  - value moved here
+LL |         drop(x);
+   |              ^ value used here after move
+   |
+   = note: move occurs because `x` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/issues/issue-10398.rs b/src/test/ui/issues/issue-10398.rs
new file mode 100644
index 0000000..0405b2d
--- /dev/null
+++ b/src/test/ui/issues/issue-10398.rs
@@ -0,0 +1,11 @@
+#![feature(box_syntax)]
+
+fn main() {
+    let x: Box<_> = box 1;
+    let f = move|| {
+        let _a = x;
+        drop(x);
+        //~^ ERROR: use of moved value: `x`
+    };
+    f();
+}
diff --git a/src/test/ui/issues/issue-10398.stderr b/src/test/ui/issues/issue-10398.stderr
new file mode 100644
index 0000000..ceb2cfe
--- /dev/null
+++ b/src/test/ui/issues/issue-10398.stderr
@@ -0,0 +1,13 @@
+error[E0382]: use of moved value: `x`
+  --> $DIR/issue-10398.rs:7:14
+   |
+LL |         let _a = x;
+   |             -- value moved here
+LL |         drop(x);
+   |              ^ value used here after move
+   |
+   = note: move occurs because `x` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/issues/issue-10401.rs b/src/test/ui/issues/issue-10401.rs
new file mode 100644
index 0000000..d77ff381
--- /dev/null
+++ b/src/test/ui/issues/issue-10401.rs
@@ -0,0 +1,5 @@
+fn main() {
+    let mut a = "a";
+    a += { "b" };
+    //~^ ERROR: binary assignment operation `+=` cannot be applied
+}
diff --git a/src/test/ui/issues/issue-10401.stderr b/src/test/ui/issues/issue-10401.stderr
new file mode 100644
index 0000000..1f68abc
--- /dev/null
+++ b/src/test/ui/issues/issue-10401.stderr
@@ -0,0 +1,11 @@
+error[E0368]: binary assignment operation `+=` cannot be applied to type `&str`
+  --> $DIR/issue-10401.rs:3:5
+   |
+LL |     a += { "b" };
+   |     -^^^^^^^^^^^
+   |     |
+   |     cannot use `+=` on type `&str`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0368`.
diff --git a/src/test/ui/issues/issue-10412.rs b/src/test/ui/issues/issue-10412.rs
new file mode 100644
index 0000000..a0bc2fc
--- /dev/null
+++ b/src/test/ui/issues/issue-10412.rs
@@ -0,0 +1,22 @@
+trait Serializable<'self, T> { //~ ERROR lifetimes cannot use keyword names
+    fn serialize(val : &'self T) -> Vec<u8>; //~ ERROR lifetimes cannot use keyword names
+    fn deserialize(repr : &[u8]) -> &'self T; //~ ERROR lifetimes cannot use keyword names
+}
+
+impl<'self> Serializable<str> for &'self str { //~ ERROR lifetimes cannot use keyword names
+    //~^ ERROR lifetimes cannot use keyword names
+    //~| ERROR missing lifetime specifier
+    fn serialize(val : &'self str) -> Vec<u8> { //~ ERROR lifetimes cannot use keyword names
+        vec![1]
+    }
+    fn deserialize(repr: &[u8]) -> &'self str { //~ ERROR lifetimes cannot use keyword names
+        "hi"
+    }
+}
+
+fn main() {
+    println!("hello");
+    let x = "foo".to_string();
+    let y = x;
+    println!("{}", y);
+}
diff --git a/src/test/ui/issues/issue-10412.stderr b/src/test/ui/issues/issue-10412.stderr
new file mode 100644
index 0000000..4892081
--- /dev/null
+++ b/src/test/ui/issues/issue-10412.stderr
@@ -0,0 +1,51 @@
+error: lifetimes cannot use keyword names
+  --> $DIR/issue-10412.rs:1:20
+   |
+LL | trait Serializable<'self, T> {
+   |                    ^^^^^
+
+error: lifetimes cannot use keyword names
+  --> $DIR/issue-10412.rs:2:25
+   |
+LL |     fn serialize(val : &'self T) -> Vec<u8>;
+   |                         ^^^^^
+
+error: lifetimes cannot use keyword names
+  --> $DIR/issue-10412.rs:3:38
+   |
+LL |     fn deserialize(repr : &[u8]) -> &'self T;
+   |                                      ^^^^^
+
+error: lifetimes cannot use keyword names
+  --> $DIR/issue-10412.rs:6:6
+   |
+LL | impl<'self> Serializable<str> for &'self str {
+   |      ^^^^^
+
+error: lifetimes cannot use keyword names
+  --> $DIR/issue-10412.rs:6:36
+   |
+LL | impl<'self> Serializable<str> for &'self str {
+   |                                    ^^^^^
+
+error: lifetimes cannot use keyword names
+  --> $DIR/issue-10412.rs:9:25
+   |
+LL |     fn serialize(val : &'self str) -> Vec<u8> {
+   |                         ^^^^^
+
+error: lifetimes cannot use keyword names
+  --> $DIR/issue-10412.rs:12:37
+   |
+LL |     fn deserialize(repr: &[u8]) -> &'self str {
+   |                                     ^^^^^
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/issue-10412.rs:6:13
+   |
+LL | impl<'self> Serializable<str> for &'self str {
+   |             ^^^^^^^^^^^^^^^^^ expected lifetime parameter
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0106`.
diff --git a/src/test/ui/issues/issue-10456.rs b/src/test/ui/issues/issue-10456.rs
new file mode 100644
index 0000000..4b54836
--- /dev/null
+++ b/src/test/ui/issues/issue-10456.rs
@@ -0,0 +1,25 @@
+// compile-pass
+// pretty-expanded FIXME #23616
+
+pub struct Foo;
+
+pub trait Bar {
+    fn bar(&self);
+}
+
+pub trait Baz {
+    fn baz(&self) { }
+}
+
+impl<T: Baz> Bar for T {
+    fn bar(&self) {}
+}
+
+impl Baz for Foo {}
+
+pub fn foo(t: Box<Foo>) {
+    t.bar(); // ~Foo doesn't implement Baz
+    (*t).bar(); // ok b/c Foo implements Baz
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-10465.rs b/src/test/ui/issues/issue-10465.rs
new file mode 100644
index 0000000..d899c3f
--- /dev/null
+++ b/src/test/ui/issues/issue-10465.rs
@@ -0,0 +1,23 @@
+pub mod a {
+    pub trait A {
+        fn foo(&self);
+    }
+
+}
+pub mod b {
+    use a::A;
+
+    pub struct B;
+    impl A for B { fn foo(&self) {} }
+
+    pub mod c {
+        use b::B;
+
+        fn foo(b: &B) {
+            b.foo(); //~ ERROR: no method named `foo` found
+        }
+    }
+
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-10465.stderr b/src/test/ui/issues/issue-10465.stderr
new file mode 100644
index 0000000..6efbd8e
--- /dev/null
+++ b/src/test/ui/issues/issue-10465.stderr
@@ -0,0 +1,13 @@
+error[E0599]: no method named `foo` found for type `&b::B` in the current scope
+  --> $DIR/issue-10465.rs:17:15
+   |
+LL |             b.foo();
+   |               ^^^
+   |
+   = help: items from traits can only be used if the trait is in scope
+   = note: the following trait is implemented but not in scope, perhaps add a `use` for it:
+           `use a::A;`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/issues/issue-10536.rs b/src/test/ui/issues/issue-10536.rs
new file mode 100644
index 0000000..ceb44ec
--- /dev/null
+++ b/src/test/ui/issues/issue-10536.rs
@@ -0,0 +1,23 @@
+// We only want to assert that this doesn't ICE, we don't particularly care
+// about whether it nor it fails to compile.
+
+macro_rules! foo{
+    () => {{
+        macro_rules! bar{() => (())}
+        1
+    }}
+}
+
+pub fn main() {
+    foo!();
+
+    assert!({one! two()});
+    //~^ ERROR macros that expand to items
+    //~| ERROR cannot find macro `one!` in this scope
+    //~| ERROR mismatched types
+
+    // regardless of whether nested macro_rules works, the following should at
+    // least throw a conventional error.
+    assert!({one! two});
+    //~^ ERROR expected `(` or `{`, found `}`
+}
diff --git a/src/test/ui/issues/issue-10536.stderr b/src/test/ui/issues/issue-10536.stderr
new file mode 100644
index 0000000..584cdf4
--- /dev/null
+++ b/src/test/ui/issues/issue-10536.stderr
@@ -0,0 +1,38 @@
+error: macros that expand to items must be delimited with braces or followed by a semicolon
+  --> $DIR/issue-10536.rs:14:22
+   |
+LL |     assert!({one! two()});
+   |                      ^^
+help: change the delimiters to curly braces
+   |
+LL |     assert!({one! two {}});
+   |                       ^^
+help: add a semicolon
+   |
+LL |     assert!({one! two();});
+   |                        ^
+
+error: expected `(` or `{`, found `}`
+  --> $DIR/issue-10536.rs:21:22
+   |
+LL |     assert!({one! two});
+   |                      ^ expected `(` or `{`
+
+error: cannot find macro `one!` in this scope
+  --> $DIR/issue-10536.rs:14:14
+   |
+LL |     assert!({one! two()});
+   |              ^^^
+
+error[E0308]: mismatched types
+  --> $DIR/issue-10536.rs:14:13
+   |
+LL |     assert!({one! two()});
+   |             ^^^^^^^^^^^^ expected bool, found ()
+   |
+   = note: expected type `bool`
+              found type `()`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-10545.rs b/src/test/ui/issues/issue-10545.rs
new file mode 100644
index 0000000..acd0714
--- /dev/null
+++ b/src/test/ui/issues/issue-10545.rs
@@ -0,0 +1,9 @@
+mod a {
+    struct S;
+    impl S { }
+}
+
+fn foo(_: a::S) { //~ ERROR: struct `S` is private
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-10545.stderr b/src/test/ui/issues/issue-10545.stderr
new file mode 100644
index 0000000..59d4fed
--- /dev/null
+++ b/src/test/ui/issues/issue-10545.stderr
@@ -0,0 +1,9 @@
+error[E0603]: struct `S` is private
+  --> $DIR/issue-10545.rs:6:14
+   |
+LL | fn foo(_: a::S) {
+   |              ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0603`.
diff --git a/src/test/ui/issues/issue-10656.rs b/src/test/ui/issues/issue-10656.rs
new file mode 100644
index 0000000..8918dad
--- /dev/null
+++ b/src/test/ui/issues/issue-10656.rs
@@ -0,0 +1,3 @@
+#![deny(missing_docs)]
+#![crate_type="lib"]
+//~^^ ERROR missing documentation for crate
diff --git a/src/test/ui/issues/issue-10656.stderr b/src/test/ui/issues/issue-10656.stderr
new file mode 100644
index 0000000..818457f
--- /dev/null
+++ b/src/test/ui/issues/issue-10656.stderr
@@ -0,0 +1,15 @@
+error: missing documentation for crate
+  --> $DIR/issue-10656.rs:1:1
+   |
+LL | / #![deny(missing_docs)]
+LL | | #![crate_type="lib"]
+   | |____________________^
+   |
+note: lint level defined here
+  --> $DIR/issue-10656.rs:1:9
+   |
+LL | #![deny(missing_docs)]
+   |         ^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-10763.rs b/src/test/ui/issues/issue-10763.rs
new file mode 100644
index 0000000..f2d4c5b
--- /dev/null
+++ b/src/test/ui/issues/issue-10763.rs
@@ -0,0 +1,7 @@
+// compile-pass
+#![allow(dead_code)]
+// pretty-expanded FIXME #23616
+
+extern "Rust" fn foo() {}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-10764.rs b/src/test/ui/issues/issue-10764.rs
new file mode 100644
index 0000000..8fa3607
--- /dev/null
+++ b/src/test/ui/issues/issue-10764.rs
@@ -0,0 +1,5 @@
+fn f(_: extern "Rust" fn()) {}
+extern fn bar() {}
+
+fn main() { f(bar) }
+//~^ ERROR mismatched types
diff --git a/src/test/ui/issues/issue-10764.stderr b/src/test/ui/issues/issue-10764.stderr
new file mode 100644
index 0000000..c5f1887
--- /dev/null
+++ b/src/test/ui/issues/issue-10764.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-10764.rs:4:15
+   |
+LL | fn main() { f(bar) }
+   |               ^^^ expected "Rust" fn, found "C" fn
+   |
+   = note: expected type `fn()`
+              found type `extern "C" fn() {bar}`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-10853.rs b/src/test/ui/issues/issue-10853.rs
new file mode 100644
index 0000000..0b74ead
--- /dev/null
+++ b/src/test/ui/issues/issue-10853.rs
@@ -0,0 +1,15 @@
+// compile-pass
+// pretty-expanded FIXME #23616
+
+#![deny(missing_docs)]
+#![doc="module"]
+
+#[doc="struct"]
+pub struct Foo;
+
+pub fn foo() {
+    #![doc="fn"]
+}
+
+#[doc="main"]
+pub fn main() {}
diff --git a/src/test/ui/issues/issue-10877.rs b/src/test/ui/issues/issue-10877.rs
new file mode 100644
index 0000000..b57929b
--- /dev/null
+++ b/src/test/ui/issues/issue-10877.rs
@@ -0,0 +1,14 @@
+struct Foo { x: isize }
+extern {
+    fn foo(1: ());
+    //~^ ERROR: patterns aren't allowed in foreign function declarations
+    fn bar((): isize);
+    //~^ ERROR: patterns aren't allowed in foreign function declarations
+    fn baz(Foo { x }: isize);
+    //~^ ERROR: patterns aren't allowed in foreign function declarations
+    fn qux((x,y): ());
+    //~^ ERROR: patterns aren't allowed in foreign function declarations
+    fn this_is_actually_ok(a: usize);
+    fn and_so_is_this(_: usize);
+}
+fn main() {}
diff --git a/src/test/ui/issues/issue-10877.stderr b/src/test/ui/issues/issue-10877.stderr
new file mode 100644
index 0000000..0f9dc21
--- /dev/null
+++ b/src/test/ui/issues/issue-10877.stderr
@@ -0,0 +1,27 @@
+error[E0130]: patterns aren't allowed in foreign function declarations
+  --> $DIR/issue-10877.rs:3:12
+   |
+LL |     fn foo(1: ());
+   |            ^ pattern not allowed in foreign function
+
+error[E0130]: patterns aren't allowed in foreign function declarations
+  --> $DIR/issue-10877.rs:5:12
+   |
+LL |     fn bar((): isize);
+   |            ^^ pattern not allowed in foreign function
+
+error[E0130]: patterns aren't allowed in foreign function declarations
+  --> $DIR/issue-10877.rs:7:12
+   |
+LL |     fn baz(Foo { x }: isize);
+   |            ^^^^^^^^^ pattern not allowed in foreign function
+
+error[E0130]: patterns aren't allowed in foreign function declarations
+  --> $DIR/issue-10877.rs:9:12
+   |
+LL |     fn qux((x,y): ());
+   |            ^^^^^ pattern not allowed in foreign function
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0130`.
diff --git a/src/test/ui/issues/issue-10902.rs b/src/test/ui/issues/issue-10902.rs
new file mode 100644
index 0000000..672386b
--- /dev/null
+++ b/src/test/ui/issues/issue-10902.rs
@@ -0,0 +1,21 @@
+// compile-pass
+#![allow(dead_code)]
+// pretty-expanded FIXME #23616
+
+pub mod two_tuple {
+    pub trait T { fn dummy(&self) { } }
+    pub struct P<'a>(&'a (T + 'a), &'a (T + 'a));
+    pub fn f<'a>(car: &'a T, cdr: &'a T) -> P<'a> {
+        P(car, cdr)
+    }
+}
+
+pub mod two_fields {
+    pub trait T { fn dummy(&self) { } }
+    pub struct P<'a> { car: &'a (T + 'a), cdr: &'a (T + 'a) }
+    pub fn f<'a>(car: &'a T, cdr: &'a T) -> P<'a> {
+        P{ car: car, cdr: cdr }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-10969.rs b/src/test/ui/issues/issue-10969.rs
new file mode 100644
index 0000000..0b78fc1
--- /dev/null
+++ b/src/test/ui/issues/issue-10969.rs
@@ -0,0 +1,7 @@
+fn func(i: i32) {
+    i(); //~ERROR expected function, found `i32`
+}
+fn main() {
+    let i = 0i32;
+    i(); //~ERROR expected function, found `i32`
+}
diff --git a/src/test/ui/issues/issue-10969.stderr b/src/test/ui/issues/issue-10969.stderr
new file mode 100644
index 0000000..9e28a66
--- /dev/null
+++ b/src/test/ui/issues/issue-10969.stderr
@@ -0,0 +1,23 @@
+error[E0618]: expected function, found `i32`
+  --> $DIR/issue-10969.rs:2:5
+   |
+LL | fn func(i: i32) {
+   |         - `i32` defined here
+LL |     i();
+   |     ^--
+   |     |
+   |     call expression requires function
+
+error[E0618]: expected function, found `i32`
+  --> $DIR/issue-10969.rs:6:5
+   |
+LL |     let i = 0i32;
+   |         - `i32` defined here
+LL |     i();
+   |     ^--
+   |     |
+   |     call expression requires function
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0618`.
diff --git a/src/test/ui/issues/issue-10991.rs b/src/test/ui/issues/issue-10991.rs
new file mode 100644
index 0000000..c36829f
--- /dev/null
+++ b/src/test/ui/issues/issue-10991.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let nil = ();
+    let _t = nil as usize; //~ ERROR: non-primitive cast: `()` as `usize`
+}
diff --git a/src/test/ui/issues/issue-10991.stderr b/src/test/ui/issues/issue-10991.stderr
new file mode 100644
index 0000000..f12539b
--- /dev/null
+++ b/src/test/ui/issues/issue-10991.stderr
@@ -0,0 +1,11 @@
+error[E0605]: non-primitive cast: `()` as `usize`
+  --> $DIR/issue-10991.rs:3:14
+   |
+LL |     let _t = nil as usize;
+   |              ^^^^^^^^^^^^
+   |
+   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0605`.
diff --git a/src/test/ui/issues/issue-11004.rs b/src/test/ui/issues/issue-11004.rs
new file mode 100644
index 0000000..10ef1f5
--- /dev/null
+++ b/src/test/ui/issues/issue-11004.rs
@@ -0,0 +1,27 @@
+use std::mem;
+
+struct A { x: i32, y: f64 }
+
+#[cfg(not(works))]
+unsafe fn access(n:*mut A) -> (i32, f64) {
+    let x : i32 = n.x; //~ no field `x` on type `*mut A`
+    let y : f64 = n.y; //~ no field `y` on type `*mut A`
+    (x, y)
+}
+
+#[cfg(works)]
+unsafe fn access(n:*mut A) -> (i32, f64) {
+    let x : i32 = (*n).x;
+    let y : f64 = (*n).y;
+    (x, y)
+}
+
+fn main() {
+    let a :  A = A { x: 3, y: 3.14 };
+    let p : &A = &a;
+    let (x,y) = unsafe {
+        let n : *mut A = mem::transmute(p);
+        access(n)
+    };
+    println!("x: {}, y: {}", x, y);
+}
diff --git a/src/test/ui/issues/issue-11004.stderr b/src/test/ui/issues/issue-11004.stderr
new file mode 100644
index 0000000..b5831e4
--- /dev/null
+++ b/src/test/ui/issues/issue-11004.stderr
@@ -0,0 +1,19 @@
+error[E0609]: no field `x` on type `*mut A`
+  --> $DIR/issue-11004.rs:7:21
+   |
+LL |     let x : i32 = n.x;
+   |                   --^
+   |                   |
+   |                   help: `n` is a raw pointer; try dereferencing it: `(*n).x`
+
+error[E0609]: no field `y` on type `*mut A`
+  --> $DIR/issue-11004.rs:8:21
+   |
+LL |     let y : f64 = n.y;
+   |                   --^
+   |                   |
+   |                   help: `n` is a raw pointer; try dereferencing it: `(*n).y`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0609`.
diff --git a/src/test/ui/issues/issue-11154.rs b/src/test/ui/issues/issue-11154.rs
new file mode 100644
index 0000000..7513abd
--- /dev/null
+++ b/src/test/ui/issues/issue-11154.rs
@@ -0,0 +1,5 @@
+// compile-flags: -C lto -C prefer-dynamic
+
+// error-pattern: cannot prefer dynamic linking
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-11154.stderr b/src/test/ui/issues/issue-11154.stderr
new file mode 100644
index 0000000..8eec8b3
--- /dev/null
+++ b/src/test/ui/issues/issue-11154.stderr
@@ -0,0 +1,6 @@
+error: cannot prefer dynamic linking when performing LTO
+
+note: only 'staticlib', 'bin', and 'cdylib' outputs are supported with LTO
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-11192.nll.stderr b/src/test/ui/issues/issue-11192.nll.stderr
new file mode 100644
index 0000000..2a9d913
--- /dev/null
+++ b/src/test/ui/issues/issue-11192.nll.stderr
@@ -0,0 +1,17 @@
+error[E0502]: cannot borrow `*ptr` as immutable because it is also borrowed as mutable
+  --> $DIR/issue-11192.rs:20:10
+   |
+LL |     let mut test = |foo: &Foo| {
+   |                    ----------- mutable borrow occurs here
+LL |         println!("access {}", foo.x);
+LL |         ptr = box Foo { x: ptr.x + 1 };
+   |         --- first borrow occurs due to use of `ptr` in closure
+...
+LL |     test(&*ptr);
+   |     ---- ^^^^^ immutable borrow occurs here
+   |     |
+   |     mutable borrow later used by call
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/issues/issue-11192.rs b/src/test/ui/issues/issue-11192.rs
new file mode 100644
index 0000000..3bf9167
--- /dev/null
+++ b/src/test/ui/issues/issue-11192.rs
@@ -0,0 +1,22 @@
+#![feature(box_syntax)]
+
+struct Foo {
+    x: isize
+}
+
+impl Drop for Foo {
+    fn drop(&mut self) {
+        println!("drop {}", self.x);
+    }
+}
+
+fn main() {
+    let mut ptr: Box<_> = box Foo { x: 0 };
+    let mut test = |foo: &Foo| {
+        println!("access {}", foo.x);
+        ptr = box Foo { x: ptr.x + 1 };
+        println!("access {}", foo.x);
+    };
+    test(&*ptr);
+    //~^ ERROR: cannot borrow `*ptr` as immutable
+}
diff --git a/src/test/ui/issues/issue-11192.stderr b/src/test/ui/issues/issue-11192.stderr
new file mode 100644
index 0000000..ce90b16
--- /dev/null
+++ b/src/test/ui/issues/issue-11192.stderr
@@ -0,0 +1,18 @@
+error[E0502]: cannot borrow `*ptr` as immutable because `ptr` is also borrowed as mutable
+  --> $DIR/issue-11192.rs:20:11
+   |
+LL |     let mut test = |foo: &Foo| {
+   |                    ----------- mutable borrow occurs here
+LL |         println!("access {}", foo.x);
+LL |         ptr = box Foo { x: ptr.x + 1 };
+   |         --- previous borrow occurs due to use of `ptr` in closure
+...
+LL |     test(&*ptr);
+   |           ^^^^ immutable borrow occurs here
+LL |
+LL | }
+   | - mutable borrow ends here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/issues/issue-11319.rs b/src/test/ui/issues/issue-11319.rs
new file mode 100644
index 0000000..726c437
--- /dev/null
+++ b/src/test/ui/issues/issue-11319.rs
@@ -0,0 +1,14 @@
+fn main() {
+    match Some(10) {
+    //~^ NOTE `match` arms have incompatible types
+        Some(5) => false,
+        //~^ NOTE this is found to be of type `bool`
+        Some(2) => true,
+        //~^ NOTE this is found to be of type `bool`
+        None    => (),
+        //~^ ERROR match arms have incompatible types
+        //~| NOTE expected bool, found ()
+        //~| NOTE expected type `bool`
+        _       => true
+    }
+}
diff --git a/src/test/ui/issues/issue-11319.stderr b/src/test/ui/issues/issue-11319.stderr
new file mode 100644
index 0000000..6179f9d
--- /dev/null
+++ b/src/test/ui/issues/issue-11319.stderr
@@ -0,0 +1,24 @@
+error[E0308]: match arms have incompatible types
+  --> $DIR/issue-11319.rs:8:20
+   |
+LL | /     match Some(10) {
+LL | |
+LL | |         Some(5) => false,
+   | |                    ----- this is found to be of type `bool`
+LL | |
+LL | |         Some(2) => true,
+   | |                    ---- this is found to be of type `bool`
+LL | |
+LL | |         None    => (),
+   | |                    ^^ expected bool, found ()
+...  |
+LL | |         _       => true
+LL | |     }
+   | |_____- `match` arms have incompatible types
+   |
+   = note: expected type `bool`
+              found type `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-11374.rs b/src/test/ui/issues/issue-11374.rs
new file mode 100644
index 0000000..f00da0a
--- /dev/null
+++ b/src/test/ui/issues/issue-11374.rs
@@ -0,0 +1,27 @@
+use std::io::{self, Read};
+use std::vec;
+
+pub struct Container<'a> {
+    reader: &'a mut Read
+}
+
+impl<'a> Container<'a> {
+    pub fn wrap<'s>(reader: &'s mut io::Read) -> Container<'s> {
+        Container { reader: reader }
+    }
+
+    pub fn read_to(&mut self, vec: &mut [u8]) {
+        self.reader.read(vec);
+    }
+}
+
+pub fn for_stdin<'a>() -> Container<'a> {
+    let mut r = io::stdin();
+    Container::wrap(&mut r as &mut io::Read)
+}
+
+fn main() {
+    let mut c = for_stdin();
+    let mut v = Vec::new();
+    c.read_to(v); //~ ERROR E0308
+}
diff --git a/src/test/ui/issues/issue-11374.stderr b/src/test/ui/issues/issue-11374.stderr
new file mode 100644
index 0000000..8d7e6c8
--- /dev/null
+++ b/src/test/ui/issues/issue-11374.stderr
@@ -0,0 +1,15 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-11374.rs:26:15
+   |
+LL |     c.read_to(v);
+   |               ^
+   |               |
+   |               expected &mut [u8], found struct `std::vec::Vec`
+   |               help: consider mutably borrowing here: `&mut v`
+   |
+   = note: expected type `&mut [u8]`
+              found type `std::vec::Vec<_>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-11384.rs b/src/test/ui/issues/issue-11384.rs
new file mode 100644
index 0000000..59d85b1
--- /dev/null
+++ b/src/test/ui/issues/issue-11384.rs
@@ -0,0 +1,10 @@
+// compile-pass
+// pretty-expanded FIXME #23616
+
+trait Common { fn dummy(&self) { } }
+
+impl<'t, T> Common for (T, &'t T) {}
+
+impl<'t, T> Common for (&'t T, T) {}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-11493.ast.stderr b/src/test/ui/issues/issue-11493.ast.stderr
new file mode 100644
index 0000000..a5f8aef
--- /dev/null
+++ b/src/test/ui/issues/issue-11493.ast.stderr
@@ -0,0 +1,16 @@
+error[E0597]: borrowed value does not live long enough (Ast)
+  --> $DIR/issue-11493.rs:10:35
+   |
+LL |     let y = x.as_ref().unwrap_or(&id(5));
+   |                                   ^^^^^ - temporary value dropped here while still borrowed
+   |                                   |
+   |                                   temporary value does not live long enough
+...
+LL | }
+   | - temporary value needs to live until here
+   |
+   = note: consider using a `let` binding to increase its lifetime
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/issues/issue-11493.mir.stderr b/src/test/ui/issues/issue-11493.mir.stderr
new file mode 100644
index 0000000..a5f8aef
--- /dev/null
+++ b/src/test/ui/issues/issue-11493.mir.stderr
@@ -0,0 +1,16 @@
+error[E0597]: borrowed value does not live long enough (Ast)
+  --> $DIR/issue-11493.rs:10:35
+   |
+LL |     let y = x.as_ref().unwrap_or(&id(5));
+   |                                   ^^^^^ - temporary value dropped here while still borrowed
+   |                                   |
+   |                                   temporary value does not live long enough
+...
+LL | }
+   | - temporary value needs to live until here
+   |
+   = note: consider using a `let` binding to increase its lifetime
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/issues/issue-11493.rs b/src/test/ui/issues/issue-11493.rs
new file mode 100644
index 0000000..4fdc32b
--- /dev/null
+++ b/src/test/ui/issues/issue-11493.rs
@@ -0,0 +1,14 @@
+// This file must never have a trailing newline
+//
+// revisions: ast mir
+// compile-flags: -Z borrowck=compare
+
+fn id<T>(x: T) -> T { x }
+
+fn main() {
+    let x = Some(3);
+    let y = x.as_ref().unwrap_or(&id(5));
+    //[ast]~^ ERROR borrowed value does not live long enough (Ast)
+    //[mir]~^^ ERROR borrowed value does not live long enough (Ast)
+    // This actually passes in mir
+}
diff --git a/src/test/ui/issues/issue-11515.rs b/src/test/ui/issues/issue-11515.rs
new file mode 100644
index 0000000..7eab2a2
--- /dev/null
+++ b/src/test/ui/issues/issue-11515.rs
@@ -0,0 +1,10 @@
+#![feature(box_syntax)]
+
+struct Test {
+    func: Box<FnMut()+'static>
+}
+
+fn main() {
+    let closure: Box<Fn()+'static> = Box::new(|| ());
+    let test = box Test { func: closure }; //~ ERROR mismatched types
+}
diff --git a/src/test/ui/issues/issue-11515.stderr b/src/test/ui/issues/issue-11515.stderr
new file mode 100644
index 0000000..0ab0c7d
--- /dev/null
+++ b/src/test/ui/issues/issue-11515.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-11515.rs:9:33
+   |
+LL |     let test = box Test { func: closure };
+   |                                 ^^^^^^^ expected trait `std::ops::FnMut`, found trait `std::ops::Fn`
+   |
+   = note: expected type `std::boxed::Box<(dyn std::ops::FnMut() + 'static)>`
+              found type `std::boxed::Box<(dyn std::ops::Fn() + 'static)>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-11592.rs b/src/test/ui/issues/issue-11592.rs
new file mode 100644
index 0000000..e2028bd
--- /dev/null
+++ b/src/test/ui/issues/issue-11592.rs
@@ -0,0 +1,11 @@
+// compile-pass
+//! Ensure the private trait Bar isn't complained about.
+
+#![deny(missing_docs)]
+
+mod foo {
+    trait Bar { fn bar(&self) { } }
+    impl Bar for i8 { fn bar(&self) { } }
+}
+
+fn main() { }
diff --git a/src/test/ui/issues/issue-11593.rs b/src/test/ui/issues/issue-11593.rs
new file mode 100644
index 0000000..8bf034e
--- /dev/null
+++ b/src/test/ui/issues/issue-11593.rs
@@ -0,0 +1,10 @@
+// aux-build:private-trait-xc.rs
+
+extern crate private_trait_xc;
+
+struct Bar;
+
+impl private_trait_xc::Foo for Bar {}
+//~^ ERROR: trait `Foo` is private
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-11593.stderr b/src/test/ui/issues/issue-11593.stderr
new file mode 100644
index 0000000..c3e4412
--- /dev/null
+++ b/src/test/ui/issues/issue-11593.stderr
@@ -0,0 +1,9 @@
+error[E0603]: trait `Foo` is private
+  --> $DIR/issue-11593.rs:7:24
+   |
+LL | impl private_trait_xc::Foo for Bar {}
+   |                        ^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0603`.
diff --git a/src/test/ui/issues/issue-11612.rs b/src/test/ui/issues/issue-11612.rs
new file mode 100644
index 0000000..4d6f465
--- /dev/null
+++ b/src/test/ui/issues/issue-11612.rs
@@ -0,0 +1,24 @@
+// compile-pass
+#![allow(dead_code)]
+// #11612
+// We weren't updating the auto adjustments with all the resolved
+// type information after type check.
+
+// pretty-expanded FIXME #23616
+
+trait A { fn dummy(&self) { } }
+
+struct B<'a, T:'a> {
+    f: &'a T
+}
+
+impl<'a, T> A for B<'a, T> {}
+
+fn foo(_: &A) {}
+
+fn bar<G>(b: &B<G>) {
+    foo(b);       // Coercion should work
+    foo(b as &A); // Explicit cast should work as well
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-11680.rs b/src/test/ui/issues/issue-11680.rs
new file mode 100644
index 0000000..bfa8f5c
--- /dev/null
+++ b/src/test/ui/issues/issue-11680.rs
@@ -0,0 +1,11 @@
+// aux-build:issue-11680.rs
+
+extern crate issue_11680 as other;
+
+fn main() {
+    let _b = other::Foo::Bar(1);
+    //~^ ERROR: enum `Foo` is private
+
+    let _b = other::test::Foo::Bar(1);
+    //~^ ERROR: enum `Foo` is private
+}
diff --git a/src/test/ui/issues/issue-11680.stderr b/src/test/ui/issues/issue-11680.stderr
new file mode 100644
index 0000000..35cb247
--- /dev/null
+++ b/src/test/ui/issues/issue-11680.stderr
@@ -0,0 +1,15 @@
+error[E0603]: enum `Foo` is private
+  --> $DIR/issue-11680.rs:6:21
+   |
+LL |     let _b = other::Foo::Bar(1);
+   |                     ^^^
+
+error[E0603]: enum `Foo` is private
+  --> $DIR/issue-11680.rs:9:27
+   |
+LL |     let _b = other::test::Foo::Bar(1);
+   |                           ^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0603`.
diff --git a/src/test/ui/issues/issue-11681.nll.stderr b/src/test/ui/issues/issue-11681.nll.stderr
new file mode 100644
index 0000000..f2f9307
--- /dev/null
+++ b/src/test/ui/issues/issue-11681.nll.stderr
@@ -0,0 +1,11 @@
+error[E0515]: cannot return value referencing temporary value
+  --> $DIR/issue-11681.rs:13:10
+   |
+LL |   let testValue = &Test;
+   |                    ---- temporary value created here
+LL |   return testValue;
+   |          ^^^^^^^^^ returns a value referencing data owned by the current function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/src/test/ui/issues/issue-11681.rs b/src/test/ui/issues/issue-11681.rs
new file mode 100644
index 0000000..8294ca6
--- /dev/null
+++ b/src/test/ui/issues/issue-11681.rs
@@ -0,0 +1,19 @@
+// This tests verifies that unary structs and enum variants
+// are treated as rvalues and their lifetime is not bounded to
+// the static scope.
+
+struct Test;
+
+impl Drop for Test {
+    fn drop (&mut self) {}
+}
+
+fn createTest<'a>() -> &'a Test {
+  let testValue = &Test; //~ ERROR borrowed value does not live long enough
+  return testValue;
+}
+
+
+pub fn main() {
+    createTest();
+}
diff --git a/src/test/ui/issues/issue-11681.stderr b/src/test/ui/issues/issue-11681.stderr
new file mode 100644
index 0000000..f59ddb0
--- /dev/null
+++ b/src/test/ui/issues/issue-11681.stderr
@@ -0,0 +1,18 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/issue-11681.rs:12:20
+   |
+LL |   let testValue = &Test;
+   |                    ^^^^ temporary value does not live long enough
+LL |   return testValue;
+LL | }
+   | - temporary value only lives until here
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 11:15...
+  --> $DIR/issue-11681.rs:11:15
+   |
+LL | fn createTest<'a>() -> &'a Test {
+   |               ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/issues/issue-11692-1.rs b/src/test/ui/issues/issue-11692-1.rs
new file mode 100644
index 0000000..70b712c
--- /dev/null
+++ b/src/test/ui/issues/issue-11692-1.rs
@@ -0,0 +1,3 @@
+fn main() {
+    print!(testo!()); //~ ERROR cannot find macro `testo!` in this scope
+}
diff --git a/src/test/ui/issues/issue-11692-1.stderr b/src/test/ui/issues/issue-11692-1.stderr
new file mode 100644
index 0000000..bfd1647
--- /dev/null
+++ b/src/test/ui/issues/issue-11692-1.stderr
@@ -0,0 +1,8 @@
+error: cannot find macro `testo!` in this scope
+  --> $DIR/issue-11692-1.rs:2:12
+   |
+LL |     print!(testo!());
+   |            ^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-11692-2.rs b/src/test/ui/issues/issue-11692-2.rs
new file mode 100644
index 0000000..61be284
--- /dev/null
+++ b/src/test/ui/issues/issue-11692-2.rs
@@ -0,0 +1,3 @@
+fn main() {
+    concat!(test!()); //~ ERROR cannot find macro `test!` in this scope
+}
diff --git a/src/test/ui/issues/issue-11692-2.stderr b/src/test/ui/issues/issue-11692-2.stderr
new file mode 100644
index 0000000..740c355
--- /dev/null
+++ b/src/test/ui/issues/issue-11692-2.stderr
@@ -0,0 +1,8 @@
+error: cannot find macro `test!` in this scope
+  --> $DIR/issue-11692-2.rs:2:13
+   |
+LL |     concat!(test!());
+   |             ^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-11740.rs b/src/test/ui/issues/issue-11740.rs
new file mode 100644
index 0000000..47bdf08
--- /dev/null
+++ b/src/test/ui/issues/issue-11740.rs
@@ -0,0 +1,28 @@
+// compile-pass
+// skip-codegen
+#![allow(warnings)]
+struct Attr {
+    name: String,
+    value: String,
+}
+
+struct Element {
+    attrs: Vec<Box<Attr>>,
+}
+
+impl Element {
+    pub unsafe fn get_attr<'a>(&'a self, name: &str) {
+        self.attrs
+            .iter()
+            .find(|attr| {
+                      let attr: &&Box<Attr> = std::mem::transmute(attr);
+                      true
+                  });
+    }
+}
+
+
+fn main() {
+    let element = Element { attrs: Vec::new() };
+    let _ = unsafe { element.get_attr("foo") };
+}
diff --git a/src/test/ui/issues/issue-11771.rs b/src/test/ui/issues/issue-11771.rs
new file mode 100644
index 0000000..c69cd1e
--- /dev/null
+++ b/src/test/ui/issues/issue-11771.rs
@@ -0,0 +1,11 @@
+fn main() {
+    let x = ();
+    1 +
+    x //~^ ERROR E0277
+    ;
+
+    let x: () = ();
+    1 +
+    x //~^ ERROR E0277
+    ;
+}
diff --git a/src/test/ui/issues/issue-11771.stderr b/src/test/ui/issues/issue-11771.stderr
new file mode 100644
index 0000000..e78d842
--- /dev/null
+++ b/src/test/ui/issues/issue-11771.stderr
@@ -0,0 +1,19 @@
+error[E0277]: cannot add `()` to `{integer}`
+  --> $DIR/issue-11771.rs:3:7
+   |
+LL |     1 +
+   |       ^ no implementation for `{integer} + ()`
+   |
+   = help: the trait `std::ops::Add<()>` is not implemented for `{integer}`
+
+error[E0277]: cannot add `()` to `{integer}`
+  --> $DIR/issue-11771.rs:8:7
+   |
+LL |     1 +
+   |       ^ no implementation for `{integer} + ()`
+   |
+   = help: the trait `std::ops::Add<()>` is not implemented for `{integer}`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-11844.rs b/src/test/ui/issues/issue-11844.rs
new file mode 100644
index 0000000..bb06f00
--- /dev/null
+++ b/src/test/ui/issues/issue-11844.rs
@@ -0,0 +1,10 @@
+#![feature(box_syntax)]
+
+fn main() {
+    let a = Some(box 1);
+    match a {
+        Ok(a) => //~ ERROR: mismatched types
+            println!("{}",a),
+        None => panic!()
+    }
+}
diff --git a/src/test/ui/issues/issue-11844.stderr b/src/test/ui/issues/issue-11844.stderr
new file mode 100644
index 0000000..1c4321f
--- /dev/null
+++ b/src/test/ui/issues/issue-11844.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-11844.rs:6:9
+   |
+LL |     match a {
+   |           - this match expression has type `std::option::Option<std::boxed::Box<{integer}>>`
+LL |         Ok(a) =>
+   |         ^^^^^ expected enum `std::option::Option`, found enum `std::result::Result`
+   |
+   = note: expected type `std::option::Option<std::boxed::Box<{integer}>>`
+              found type `std::result::Result<_, _>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-11869.rs b/src/test/ui/issues/issue-11869.rs
new file mode 100644
index 0000000..e62879f
--- /dev/null
+++ b/src/test/ui/issues/issue-11869.rs
@@ -0,0 +1,17 @@
+// compile-pass
+#![allow(dead_code)]
+// pretty-expanded FIXME #23616
+
+struct A {
+    a: String
+}
+
+fn borrow<'a>(binding: &'a A) -> &'a str {
+    match &*binding.a {
+        "in" => "in_",
+        "ref" => "ref_",
+        ident => ident
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-11873.nll.stderr b/src/test/ui/issues/issue-11873.nll.stderr
new file mode 100644
index 0000000..4475bdf
--- /dev/null
+++ b/src/test/ui/issues/issue-11873.nll.stderr
@@ -0,0 +1,16 @@
+error[E0505]: cannot move out of `v` because it is borrowed
+  --> $DIR/issue-11873.rs:4:14
+   |
+LL |     let mut f = || v.push(2);
+   |                 -- - borrow occurs due to use in closure
+   |                 |
+   |                 borrow of `v` occurs here
+LL |     let _w = v;
+   |              ^ move out of `v` occurs here
+LL | 
+LL |     f();
+   |     - borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0505`.
diff --git a/src/test/ui/issues/issue-11873.rs b/src/test/ui/issues/issue-11873.rs
new file mode 100644
index 0000000..d3bd05c
--- /dev/null
+++ b/src/test/ui/issues/issue-11873.rs
@@ -0,0 +1,7 @@
+fn main() {
+    let mut v = vec![1];
+    let mut f = || v.push(2);
+    let _w = v; //~ ERROR: cannot move out of `v`
+
+    f();
+}
diff --git a/src/test/ui/issues/issue-11873.stderr b/src/test/ui/issues/issue-11873.stderr
new file mode 100644
index 0000000..63bb4e7
--- /dev/null
+++ b/src/test/ui/issues/issue-11873.stderr
@@ -0,0 +1,11 @@
+error[E0505]: cannot move out of `v` because it is borrowed
+  --> $DIR/issue-11873.rs:4:9
+   |
+LL |     let mut f = || v.push(2);
+   |                 -- borrow of `v` occurs here
+LL |     let _w = v;
+   |         ^^ move out of `v` occurs here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0505`.
diff --git a/src/test/ui/issues/issue-12028.rs b/src/test/ui/issues/issue-12028.rs
new file mode 100644
index 0000000..d553545
--- /dev/null
+++ b/src/test/ui/issues/issue-12028.rs
@@ -0,0 +1,40 @@
+// Test an example where we fail to infer the type parameter H. This
+// is because there is really nothing constraining it. At one time, we
+// would infer based on the where clauses in scope, but that no longer
+// works.
+
+trait Hash<H> {
+    fn hash2(&self, hasher: &H) -> u64;
+}
+
+trait Stream {
+    fn input(&mut self, bytes: &[u8]);
+    fn result(&self) -> u64;
+}
+
+trait StreamHasher {
+    type S : Stream;
+    fn stream(&self) -> Self::S;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+trait StreamHash<H: StreamHasher>: Hash<H> {
+    fn input_stream(&self, stream: &mut H::S);
+}
+
+impl<H: StreamHasher> Hash<H> for u8 {
+    fn hash2(&self, hasher: &H) -> u64 {
+        let mut stream = hasher.stream();
+        self.input_stream(&mut stream); //~ ERROR type annotations required
+        Stream::result(&stream)
+    }
+}
+
+impl<H: StreamHasher> StreamHash<H> for u8 {
+    fn input_stream(&self, stream: &mut H::S) {
+        Stream::input(stream, &[*self]);
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-12028.stderr b/src/test/ui/issues/issue-12028.stderr
new file mode 100644
index 0000000..64694c7
--- /dev/null
+++ b/src/test/ui/issues/issue-12028.stderr
@@ -0,0 +1,9 @@
+error[E0284]: type annotations required: cannot resolve `<_ as StreamHasher>::S == <H as StreamHasher>::S`
+  --> $DIR/issue-12028.rs:29:14
+   |
+LL |         self.input_stream(&mut stream);
+   |              ^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0284`.
diff --git a/src/test/ui/issues/issue-12041.nll.stderr b/src/test/ui/issues/issue-12041.nll.stderr
new file mode 100644
index 0000000..d95cc89
--- /dev/null
+++ b/src/test/ui/issues/issue-12041.nll.stderr
@@ -0,0 +1,11 @@
+error[E0382]: use of moved value: `tx`
+  --> $DIR/issue-12041.rs:8:22
+   |
+LL |             let tx = tx;
+   |                      ^^ value moved here, in previous iteration of loop
+   |
+   = note: move occurs because `tx` has type `std::sync::mpsc::Sender<i32>`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/issues/issue-12041.rs b/src/test/ui/issues/issue-12041.rs
new file mode 100644
index 0000000..091e8fe
--- /dev/null
+++ b/src/test/ui/issues/issue-12041.rs
@@ -0,0 +1,13 @@
+use std::sync::mpsc::channel;
+use std::thread;
+
+fn main() {
+    let (tx, rx) = channel();
+    let _t = thread::spawn(move|| -> () {
+        loop {
+            let tx = tx;
+            //~^ ERROR: use of moved value: `tx`
+            tx.send(1);
+        }
+    });
+}
diff --git a/src/test/ui/issues/issue-12041.stderr b/src/test/ui/issues/issue-12041.stderr
new file mode 100644
index 0000000..48544c0
--- /dev/null
+++ b/src/test/ui/issues/issue-12041.stderr
@@ -0,0 +1,11 @@
+error[E0382]: use of moved value: `tx`
+  --> $DIR/issue-12041.rs:8:17
+   |
+LL |             let tx = tx;
+   |                 ^^ value moved here in previous iteration of loop
+   |
+   = note: move occurs because `tx` has type `std::sync::mpsc::Sender<i32>`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/issues/issue-12116.rs b/src/test/ui/issues/issue-12116.rs
new file mode 100644
index 0000000..8b391cd
--- /dev/null
+++ b/src/test/ui/issues/issue-12116.rs
@@ -0,0 +1,21 @@
+#![feature(box_patterns)]
+#![feature(box_syntax)]
+#![allow(dead_code)]
+#![allow(unused_variables)]
+#![deny(unreachable_patterns)]
+
+enum IntList {
+    Cons(isize, Box<IntList>),
+    Nil
+}
+
+fn tail(source_list: &IntList) -> IntList {
+    match source_list {
+        &IntList::Cons(val, box ref next_list) => tail(next_list),
+        &IntList::Cons(val, box IntList::Nil)  => IntList::Cons(val, box IntList::Nil),
+//~^ ERROR unreachable pattern
+        _                          => panic!()
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-12116.stderr b/src/test/ui/issues/issue-12116.stderr
new file mode 100644
index 0000000..10db4f1
--- /dev/null
+++ b/src/test/ui/issues/issue-12116.stderr
@@ -0,0 +1,14 @@
+error: unreachable pattern
+  --> $DIR/issue-12116.rs:15:9
+   |
+LL |         &IntList::Cons(val, box IntList::Nil)  => IntList::Cons(val, box IntList::Nil),
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/issue-12116.rs:5:9
+   |
+LL | #![deny(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-12127.rs b/src/test/ui/issues/issue-12127.rs
new file mode 100644
index 0000000..bb2c273
--- /dev/null
+++ b/src/test/ui/issues/issue-12127.rs
@@ -0,0 +1,14 @@
+#![feature(box_syntax, unboxed_closures)]
+
+fn to_fn_once<A,F:FnOnce<A>>(f: F) -> F { f }
+fn do_it(x: &isize) { }
+
+fn main() {
+    let x: Box<_> = box 22;
+    let f = to_fn_once(move|| do_it(&*x));
+    to_fn_once(move|| {
+        f();
+        f();
+        //~^ ERROR: use of moved value: `f`
+    })()
+}
diff --git a/src/test/ui/issues/issue-12127.stderr b/src/test/ui/issues/issue-12127.stderr
new file mode 100644
index 0000000..2283b12
--- /dev/null
+++ b/src/test/ui/issues/issue-12127.stderr
@@ -0,0 +1,13 @@
+error[E0382]: use of moved value: `f`
+  --> $DIR/issue-12127.rs:11:9
+   |
+LL |         f();
+   |         - value moved here
+LL |         f();
+   |         ^ value used here after move
+   |
+   = note: move occurs because `f` has type `[closure@$DIR/issue-12127.rs:8:24: 8:41 x:std::boxed::Box<isize>]`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/issues/issue-12187-1.rs b/src/test/ui/issues/issue-12187-1.rs
new file mode 100644
index 0000000..37ff468
--- /dev/null
+++ b/src/test/ui/issues/issue-12187-1.rs
@@ -0,0 +1,8 @@
+fn new<T>() -> &'static T {
+    panic!()
+}
+
+fn main() {
+    let &v = new();
+    //~^ ERROR type annotations needed [E0282]
+}
diff --git a/src/test/ui/issues/issue-12187-1.stderr b/src/test/ui/issues/issue-12187-1.stderr
new file mode 100644
index 0000000..f8df4f8
--- /dev/null
+++ b/src/test/ui/issues/issue-12187-1.stderr
@@ -0,0 +1,12 @@
+error[E0282]: type annotations needed
+  --> $DIR/issue-12187-1.rs:6:10
+   |
+LL |     let &v = new();
+   |         -^
+   |         ||
+   |         |cannot infer type
+   |         consider giving the pattern a type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/issues/issue-12187-2.rs b/src/test/ui/issues/issue-12187-2.rs
new file mode 100644
index 0000000..a1cdb84
--- /dev/null
+++ b/src/test/ui/issues/issue-12187-2.rs
@@ -0,0 +1,8 @@
+fn new<'r, T>() -> &'r T {
+    panic!()
+}
+
+fn main() {
+    let &v = new();
+    //~^ ERROR type annotations needed [E0282]
+}
diff --git a/src/test/ui/issues/issue-12187-2.stderr b/src/test/ui/issues/issue-12187-2.stderr
new file mode 100644
index 0000000..c40ae04
--- /dev/null
+++ b/src/test/ui/issues/issue-12187-2.stderr
@@ -0,0 +1,12 @@
+error[E0282]: type annotations needed
+  --> $DIR/issue-12187-2.rs:6:10
+   |
+LL |     let &v = new();
+   |         -^
+   |         ||
+   |         |cannot infer type
+   |         consider giving the pattern a type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/issues/issue-12369.rs b/src/test/ui/issues/issue-12369.rs
new file mode 100644
index 0000000..8df8efef
--- /dev/null
+++ b/src/test/ui/issues/issue-12369.rs
@@ -0,0 +1,12 @@
+#![feature(slice_patterns)]
+#![deny(unreachable_patterns)]
+
+fn main() {
+    let sl = vec![1,2,3];
+    let v: isize = match &*sl {
+        &[] => 0,
+        &[a,b,c] => 3,
+        &[a, ref rest..] => a,
+        &[10,a, ref rest..] => 10 //~ ERROR: unreachable pattern
+    };
+}
diff --git a/src/test/ui/issues/issue-12369.stderr b/src/test/ui/issues/issue-12369.stderr
new file mode 100644
index 0000000..fec9078
--- /dev/null
+++ b/src/test/ui/issues/issue-12369.stderr
@@ -0,0 +1,14 @@
+error: unreachable pattern
+  --> $DIR/issue-12369.rs:10:9
+   |
+LL |         &[10,a, ref rest..] => 10
+   |         ^^^^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/issue-12369.rs:2:9
+   |
+LL | #![deny(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-12470.nll.stderr b/src/test/ui/issues/issue-12470.nll.stderr
new file mode 100644
index 0000000..c97e591
--- /dev/null
+++ b/src/test/ui/issues/issue-12470.nll.stderr
@@ -0,0 +1,11 @@
+error[E0515]: cannot return value referencing local data `*b`
+  --> $DIR/issue-12470.rs:29:5
+   |
+LL |     let bb: &B = &*b;
+   |                  --- `*b` is borrowed here
+LL |     make_a(bb)
+   |     ^^^^^^^^^^ returns a value referencing data owned by the current function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/src/test/ui/issues/issue-12470.rs b/src/test/ui/issues/issue-12470.rs
new file mode 100644
index 0000000..acf1b76
--- /dev/null
+++ b/src/test/ui/issues/issue-12470.rs
@@ -0,0 +1,34 @@
+#![feature(box_syntax)]
+
+trait X {
+    fn get_i(&self) -> isize;
+}
+
+
+struct B {
+    i: isize
+}
+
+impl X for B {
+    fn get_i(&self) -> isize {
+        self.i
+    }
+}
+
+struct A<'a> {
+    p: &'a (X+'a)
+}
+
+fn make_a<'a>(p: &'a X) -> A<'a> {
+    A { p: p }
+}
+
+fn make_make_a<'a>() -> A<'a> {
+    let b: Box<B> = box B {i:1};
+    let bb: &B = &*b;    //~ ERROR does not live long enough
+    make_a(bb)
+}
+
+fn main() {
+    let _a = make_make_a();
+}
diff --git a/src/test/ui/issues/issue-12470.stderr b/src/test/ui/issues/issue-12470.stderr
new file mode 100644
index 0000000..fadfb75
--- /dev/null
+++ b/src/test/ui/issues/issue-12470.stderr
@@ -0,0 +1,18 @@
+error[E0597]: `*b` does not live long enough
+  --> $DIR/issue-12470.rs:28:19
+   |
+LL |     let bb: &B = &*b;
+   |                   ^^ borrowed value does not live long enough
+LL |     make_a(bb)
+LL | }
+   | - borrowed value only lives until here
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 26:16...
+  --> $DIR/issue-12470.rs:26:16
+   |
+LL | fn make_make_a<'a>() -> A<'a> {
+   |                ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/issues/issue-1251.rs b/src/test/ui/issues/issue-1251.rs
new file mode 100644
index 0000000..84a14a8
--- /dev/null
+++ b/src/test/ui/issues/issue-1251.rs
@@ -0,0 +1,19 @@
+// compile-pass
+#![allow(unused_attributes)]
+#![allow(dead_code)]
+// pretty-expanded FIXME #23616
+// ignore-wasm32-bare no libc to test ffi with
+
+#![feature(rustc_private)]
+
+#![crate_id="rust_get_test_int"]
+
+mod rustrt {
+    extern crate libc;
+
+    extern {
+        pub fn rust_get_test_int() -> libc::intptr_t;
+    }
+}
+
+pub fn main() { }
diff --git a/src/test/ui/issues/issue-12511.rs b/src/test/ui/issues/issue-12511.rs
new file mode 100644
index 0000000..ea83e3f
--- /dev/null
+++ b/src/test/ui/issues/issue-12511.rs
@@ -0,0 +1,8 @@
+trait T1 : T2 {
+//~^ ERROR cycle detected
+}
+
+trait T2 : T1 {
+}
+
+fn main() { }
diff --git a/src/test/ui/issues/issue-12511.stderr b/src/test/ui/issues/issue-12511.stderr
new file mode 100644
index 0000000..37e38ff
--- /dev/null
+++ b/src/test/ui/issues/issue-12511.stderr
@@ -0,0 +1,21 @@
+error[E0391]: cycle detected when computing the supertraits of `T1`
+  --> $DIR/issue-12511.rs:1:12
+   |
+LL | trait T1 : T2 {
+   |            ^^
+   |
+note: ...which requires computing the supertraits of `T2`...
+  --> $DIR/issue-12511.rs:5:12
+   |
+LL | trait T2 : T1 {
+   |            ^^
+   = note: ...which again requires computing the supertraits of `T1`, completing the cycle
+note: cycle used when collecting item types in top-level module
+  --> $DIR/issue-12511.rs:1:1
+   |
+LL | trait T1 : T2 {
+   | ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/issues/issue-12552.rs b/src/test/ui/issues/issue-12552.rs
new file mode 100644
index 0000000..b7f71dd
--- /dev/null
+++ b/src/test/ui/issues/issue-12552.rs
@@ -0,0 +1,11 @@
+// this code used to cause an ICE
+
+fn main() {
+  let t = Err(0);
+  match t {
+    Some(k) => match k { //~ ERROR mismatched types
+      a => println!("{}", a)
+    },
+    None => () //~ ERROR mismatched types
+  }
+}
diff --git a/src/test/ui/issues/issue-12552.stderr b/src/test/ui/issues/issue-12552.stderr
new file mode 100644
index 0000000..6eaac1b
--- /dev/null
+++ b/src/test/ui/issues/issue-12552.stderr
@@ -0,0 +1,23 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-12552.rs:6:5
+   |
+LL |   match t {
+   |         - this match expression has type `std::result::Result<_, {integer}>`
+LL |     Some(k) => match k {
+   |     ^^^^^^^ expected enum `std::result::Result`, found enum `std::option::Option`
+   |
+   = note: expected type `std::result::Result<_, {integer}>`
+              found type `std::option::Option<_>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-12552.rs:9:5
+   |
+LL |     None => ()
+   |     ^^^^ expected enum `std::result::Result`, found enum `std::option::Option`
+   |
+   = note: expected type `std::result::Result<_, {integer}>`
+              found type `std::option::Option<_>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-12567.nll.stderr b/src/test/ui/issues/issue-12567.nll.stderr
new file mode 100644
index 0000000..17388df
--- /dev/null
+++ b/src/test/ui/issues/issue-12567.nll.stderr
@@ -0,0 +1,45 @@
+error[E0508]: cannot move out of type `[T]`, a non-copy slice
+  --> $DIR/issue-12567.rs:4:11
+   |
+LL |     match (l1, l2) {
+   |           ^^^^^^^^ cannot move out of here
+LL |         (&[], &[]) => println!("both empty"),
+LL |         (&[], &[hd, ..]) | (&[hd, ..], &[])
+   |                 -- data moved here
+...
+LL |         (&[hd1, ..], &[hd2, ..])
+   |                        --- ...and here
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/issue-12567.rs:6:17
+   |
+LL |         (&[], &[hd, ..]) | (&[hd, ..], &[])
+   |                 ^^
+...
+LL |         (&[hd1, ..], &[hd2, ..])
+   |                        ^^^
+
+error[E0508]: cannot move out of type `[T]`, a non-copy slice
+  --> $DIR/issue-12567.rs:4:11
+   |
+LL |     match (l1, l2) {
+   |           ^^^^^^^^ cannot move out of here
+LL |         (&[], &[]) => println!("both empty"),
+LL |         (&[], &[hd, ..]) | (&[hd, ..], &[])
+   |                 -- data moved here
+...
+LL |         (&[hd1, ..], &[hd2, ..])
+   |            --- ...and here
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/issue-12567.rs:6:17
+   |
+LL |         (&[], &[hd, ..]) | (&[hd, ..], &[])
+   |                 ^^
+...
+LL |         (&[hd1, ..], &[hd2, ..])
+   |            ^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0508`.
diff --git a/src/test/ui/issues/issue-12567.rs b/src/test/ui/issues/issue-12567.rs
new file mode 100644
index 0000000..1e1debe
--- /dev/null
+++ b/src/test/ui/issues/issue-12567.rs
@@ -0,0 +1,17 @@
+#![feature(slice_patterns)]
+
+fn match_vecs<'a, T>(l1: &'a [T], l2: &'a [T]) {
+    match (l1, l2) {
+        (&[], &[]) => println!("both empty"),
+        (&[], &[hd, ..]) | (&[hd, ..], &[])
+            => println!("one empty"),
+        //~^^ ERROR: cannot move out of type `[T]`, a non-copy slice
+        //~^^^ ERROR: cannot move out of type `[T]`, a non-copy slice
+        (&[hd1, ..], &[hd2, ..])
+            => println!("both nonempty"),
+        //~^^ ERROR: cannot move out of type `[T]`, a non-copy slice
+        //~^^^ ERROR: cannot move out of type `[T]`, a non-copy slice
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-12567.stderr b/src/test/ui/issues/issue-12567.stderr
new file mode 100644
index 0000000..15f723f
--- /dev/null
+++ b/src/test/ui/issues/issue-12567.stderr
@@ -0,0 +1,39 @@
+error[E0508]: cannot move out of type `[T]`, a non-copy slice
+  --> $DIR/issue-12567.rs:6:16
+   |
+LL |         (&[], &[hd, ..]) | (&[hd, ..], &[])
+   |                ^--^^^^^
+   |                ||
+   |                |hint: to prevent move, use `ref hd` or `ref mut hd`
+   |                cannot move out of here
+
+error[E0508]: cannot move out of type `[T]`, a non-copy slice
+  --> $DIR/issue-12567.rs:6:30
+   |
+LL |         (&[], &[hd, ..]) | (&[hd, ..], &[])
+   |                              ^--^^^^^
+   |                              ||
+   |                              |hint: to prevent move, use `ref hd` or `ref mut hd`
+   |                              cannot move out of here
+
+error[E0508]: cannot move out of type `[T]`, a non-copy slice
+  --> $DIR/issue-12567.rs:10:11
+   |
+LL |         (&[hd1, ..], &[hd2, ..])
+   |           ^---^^^^^
+   |           ||
+   |           |hint: to prevent move, use `ref hd1` or `ref mut hd1`
+   |           cannot move out of here
+
+error[E0508]: cannot move out of type `[T]`, a non-copy slice
+  --> $DIR/issue-12567.rs:10:23
+   |
+LL |         (&[hd1, ..], &[hd2, ..])
+   |                       ^---^^^^^
+   |                       ||
+   |                       |hint: to prevent move, use `ref hd2` or `ref mut hd2`
+   |                       cannot move out of here
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0508`.
diff --git a/src/test/ui/issues/issue-12729.rs b/src/test/ui/issues/issue-12729.rs
new file mode 100644
index 0000000..c2572c7
--- /dev/null
+++ b/src/test/ui/issues/issue-12729.rs
@@ -0,0 +1,14 @@
+// compile-pass
+#![allow(dead_code)]
+// pretty-expanded FIXME #23616
+
+pub struct Foo;
+
+mod bar {
+    use Foo;
+
+    impl Foo {
+        fn baz(&self) {}
+    }
+}
+fn main() {}
diff --git a/src/test/ui/issues/issue-12796.rs b/src/test/ui/issues/issue-12796.rs
new file mode 100644
index 0000000..942d6b9
--- /dev/null
+++ b/src/test/ui/issues/issue-12796.rs
@@ -0,0 +1,9 @@
+trait Trait {
+    fn outer(&self) {
+        fn inner(_: &Self) {
+            //~^ ERROR can't use generic parameters from outer function
+        }
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/issues/issue-12796.stderr b/src/test/ui/issues/issue-12796.stderr
new file mode 100644
index 0000000..a01fd2d
--- /dev/null
+++ b/src/test/ui/issues/issue-12796.stderr
@@ -0,0 +1,12 @@
+error[E0401]: can't use generic parameters from outer function
+  --> $DIR/issue-12796.rs:3:22
+   |
+LL |         fn inner(_: &Self) {
+   |                      ^^^^
+   |                      |
+   |                      use of generic parameter from outer function
+   |                      can't use `Self` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0401`.
diff --git a/src/test/ui/issues/issue-12863.rs b/src/test/ui/issues/issue-12863.rs
new file mode 100644
index 0000000..d7941a7
--- /dev/null
+++ b/src/test/ui/issues/issue-12863.rs
@@ -0,0 +1,7 @@
+mod foo { pub fn bar() {} }
+
+fn main() {
+    match () {
+        foo::bar => {} //~ ERROR expected unit struct/variant or constant, found function `foo::bar`
+    }
+}
diff --git a/src/test/ui/issues/issue-12863.stderr b/src/test/ui/issues/issue-12863.stderr
new file mode 100644
index 0000000..bec70a5
--- /dev/null
+++ b/src/test/ui/issues/issue-12863.stderr
@@ -0,0 +1,9 @@
+error[E0532]: expected unit struct/variant or constant, found function `foo::bar`
+  --> $DIR/issue-12863.rs:5:9
+   |
+LL |         foo::bar => {}
+   |         ^^^^^^^^ not a unit struct/variant or constant
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0532`.
diff --git a/src/test/ui/issues/issue-12997-1.rs b/src/test/ui/issues/issue-12997-1.rs
new file mode 100644
index 0000000..d00980e
--- /dev/null
+++ b/src/test/ui/issues/issue-12997-1.rs
@@ -0,0 +1,9 @@
+// compile-flags: --test
+
+//! Test that makes sure wrongly-typed bench functions aren't ignored
+
+#[bench]
+fn foo() { } //~ ERROR functions used as benches
+
+#[bench]
+fn bar(x: isize, y: isize) { } //~ ERROR functions used as benches
diff --git a/src/test/ui/issues/issue-12997-1.stderr b/src/test/ui/issues/issue-12997-1.stderr
new file mode 100644
index 0000000..e036896
--- /dev/null
+++ b/src/test/ui/issues/issue-12997-1.stderr
@@ -0,0 +1,14 @@
+error: functions used as benches must have signature `fn(&mut Bencher) -> impl Termination`
+  --> $DIR/issue-12997-1.rs:6:1
+   |
+LL | fn foo() { }
+   | ^^^^^^^^^^^^
+
+error: functions used as benches must have signature `fn(&mut Bencher) -> impl Termination`
+  --> $DIR/issue-12997-1.rs:9:1
+   |
+LL | fn bar(x: isize, y: isize) { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/issues/issue-12997-2.rs b/src/test/ui/issues/issue-12997-2.rs
new file mode 100644
index 0000000..8bf1a37
--- /dev/null
+++ b/src/test/ui/issues/issue-12997-2.rs
@@ -0,0 +1,7 @@
+// compile-flags: --test
+
+//! Test that makes sure wrongly-typed bench functions are rejected
+
+#[bench]
+fn bar(x: isize) { }
+//~^ ERROR mismatched types
diff --git a/src/test/ui/issues/issue-12997-2.stderr b/src/test/ui/issues/issue-12997-2.stderr
new file mode 100644
index 0000000..e608c42
--- /dev/null
+++ b/src/test/ui/issues/issue-12997-2.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-12997-2.rs:6:1
+   |
+LL | fn bar(x: isize) { }
+   | ^^^^^^^^^^^^^^^^^^^^ expected isize, found mutable reference
+   |
+   = note: expected type `isize`
+              found type `&mut test::Bencher`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-13033.rs b/src/test/ui/issues/issue-13033.rs
new file mode 100644
index 0000000..a6c9e97
--- /dev/null
+++ b/src/test/ui/issues/issue-13033.rs
@@ -0,0 +1,14 @@
+trait Foo {
+    fn bar(&mut self, other: &mut Foo);
+}
+
+struct Baz;
+
+impl Foo for Baz {
+    fn bar(&mut self, other: &Foo) {}
+    //~^ ERROR method `bar` has an incompatible type for trait
+    //~| expected type `fn(&mut Baz, &mut dyn Foo)`
+    //~| found type `fn(&mut Baz, &dyn Foo)`
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-13033.stderr b/src/test/ui/issues/issue-13033.stderr
new file mode 100644
index 0000000..d1e8eb3
--- /dev/null
+++ b/src/test/ui/issues/issue-13033.stderr
@@ -0,0 +1,19 @@
+error[E0053]: method `bar` has an incompatible type for trait
+  --> $DIR/issue-13033.rs:8:30
+   |
+LL |     fn bar(&mut self, other: &mut Foo);
+   |                              -------- type in trait
+...
+LL |     fn bar(&mut self, other: &Foo) {}
+   |                              ^^^^ types differ in mutability
+   |
+   = note: expected type `fn(&mut Baz, &mut dyn Foo)`
+              found type `fn(&mut Baz, &dyn Foo)`
+help: consider change the type to match the mutability in trait
+   |
+LL |     fn bar(&mut self, other: &mut Foo) {}
+   |                              ^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0053`.
diff --git a/src/test/ui/issues/issue-13058.rs b/src/test/ui/issues/issue-13058.rs
new file mode 100644
index 0000000..a5806fe
--- /dev/null
+++ b/src/test/ui/issues/issue-13058.rs
@@ -0,0 +1,27 @@
+use std::ops::Range;
+
+trait Itble<'r, T, I: Iterator<Item=T>> { fn iter(&'r self) -> I; }
+
+impl<'r> Itble<'r, usize, Range<usize>> for (usize, usize) {
+    fn iter(&'r self) -> Range<usize> {
+        let &(min, max) = self;
+        min..max
+    }
+}
+
+fn check<'r, I: Iterator<Item=usize>, T: Itble<'r, usize, I>>(cont: &T) -> bool
+{
+    let cont_iter = cont.iter();
+//~^ ERROR explicit lifetime required in the type of `cont` [E0621]
+    let result = cont_iter.fold(Some(0), |state, val| {
+        state.map_or(None, |mask| {
+            let bit = 1 << val;
+            if mask & bit == 0 {Some(mask|bit)} else {None}
+        })
+    });
+    result.is_some()
+}
+
+fn main() {
+    check(&(3, 5));
+}
diff --git a/src/test/ui/issues/issue-13058.stderr b/src/test/ui/issues/issue-13058.stderr
new file mode 100644
index 0000000..53a2c98
--- /dev/null
+++ b/src/test/ui/issues/issue-13058.stderr
@@ -0,0 +1,12 @@
+error[E0621]: explicit lifetime required in the type of `cont`
+  --> $DIR/issue-13058.rs:14:26
+   |
+LL | fn check<'r, I: Iterator<Item=usize>, T: Itble<'r, usize, I>>(cont: &T) -> bool
+   |                                                                     -- help: add explicit lifetime `'r` to the type of `cont`: `&'r T`
+LL | {
+LL |     let cont_iter = cont.iter();
+   |                          ^^^^ lifetime `'r` required
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/issues/issue-13105.rs b/src/test/ui/issues/issue-13105.rs
new file mode 100644
index 0000000..0e11804
--- /dev/null
+++ b/src/test/ui/issues/issue-13105.rs
@@ -0,0 +1,9 @@
+// compile-pass
+// pretty-expanded FIXME #23616
+
+trait Foo {
+    #[allow(anonymous_parameters)]
+    fn quux(u8) {}
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-13167.rs b/src/test/ui/issues/issue-13167.rs
new file mode 100644
index 0000000..dcc25a4
--- /dev/null
+++ b/src/test/ui/issues/issue-13167.rs
@@ -0,0 +1,22 @@
+// compile-pass
+// pretty-expanded FIXME #23616
+
+use std::slice;
+
+pub struct PhfMapEntries<'a, T: 'a> {
+    iter: slice::Iter<'a, (&'static str, T)>,
+}
+
+impl<'a, T> Iterator for PhfMapEntries<'a, T> {
+    type Item = (&'static str, &'a T);
+
+    fn next(&mut self) -> Option<(&'static str, &'a T)> {
+        self.iter.by_ref().map(|&(key, ref value)| (key, value)).next()
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.iter.size_hint()
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-13214.rs b/src/test/ui/issues/issue-13214.rs
new file mode 100644
index 0000000..af2d95c
--- /dev/null
+++ b/src/test/ui/issues/issue-13214.rs
@@ -0,0 +1,23 @@
+// compile-pass
+#![allow(dead_code)]
+// defining static with struct that contains enum
+// with &'static str variant used to cause ICE
+
+// pretty-expanded FIXME #23616
+
+pub enum Foo {
+    Bar,
+    Baz(&'static str),
+}
+
+pub static TEST: Test = Test {
+    foo: Foo::Bar,
+    c: 'a'
+};
+
+pub struct Test {
+    foo: Foo,
+    c: char,
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-13352.rs b/src/test/ui/issues/issue-13352.rs
new file mode 100644
index 0000000..c711e3b
--- /dev/null
+++ b/src/test/ui/issues/issue-13352.rs
@@ -0,0 +1,11 @@
+// ignore-cloudabi no std::process
+
+fn foo(_: Box<FnMut()>) {}
+
+fn main() {
+    foo(loop {
+        std::process::exit(0);
+    });
+    2_usize + (loop {});
+    //~^ ERROR E0277
+}
diff --git a/src/test/ui/issues/issue-13352.stderr b/src/test/ui/issues/issue-13352.stderr
new file mode 100644
index 0000000..58ac74b
--- /dev/null
+++ b/src/test/ui/issues/issue-13352.stderr
@@ -0,0 +1,11 @@
+error[E0277]: cannot add `()` to `usize`
+  --> $DIR/issue-13352.rs:9:13
+   |
+LL |     2_usize + (loop {});
+   |             ^ no implementation for `usize + ()`
+   |
+   = help: the trait `std::ops::Add<()>` is not implemented for `usize`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-13359.rs b/src/test/ui/issues/issue-13359.rs
new file mode 100644
index 0000000..7409426
--- /dev/null
+++ b/src/test/ui/issues/issue-13359.rs
@@ -0,0 +1,13 @@
+fn foo(_s: i16) { }
+
+fn bar(_s: u32) { }
+
+fn main() {
+    foo(1*(1 as isize));
+    //~^ ERROR mismatched types
+    //~| expected i16, found isize
+
+    bar(1*(1 as usize));
+    //~^ ERROR mismatched types
+    //~| expected u32, found usize
+}
diff --git a/src/test/ui/issues/issue-13359.stderr b/src/test/ui/issues/issue-13359.stderr
new file mode 100644
index 0000000..00b7fbd
--- /dev/null
+++ b/src/test/ui/issues/issue-13359.stderr
@@ -0,0 +1,15 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-13359.rs:6:9
+   |
+LL |     foo(1*(1 as isize));
+   |         ^^^^^^^^^^^^^^ expected i16, found isize
+
+error[E0308]: mismatched types
+  --> $DIR/issue-13359.rs:10:9
+   |
+LL |     bar(1*(1 as usize));
+   |         ^^^^^^^^^^^^^^ expected u32, found usize
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-13404.rs b/src/test/ui/issues/issue-13404.rs
new file mode 100644
index 0000000..c5af827
--- /dev/null
+++ b/src/test/ui/issues/issue-13404.rs
@@ -0,0 +1,10 @@
+use a::f;
+use b::f; //~ ERROR: unresolved import `b::f` [E0432]
+          //~^ no `f` in `b`
+
+mod a { pub fn f() {} }
+mod b { }
+
+fn main() {
+    f();
+}
diff --git a/src/test/ui/issues/issue-13404.stderr b/src/test/ui/issues/issue-13404.stderr
new file mode 100644
index 0000000..1f50deb
--- /dev/null
+++ b/src/test/ui/issues/issue-13404.stderr
@@ -0,0 +1,9 @@
+error[E0432]: unresolved import `b::f`
+  --> $DIR/issue-13404.rs:2:5
+   |
+LL | use b::f;
+   |     ^^^^ no `f` in `b`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/issues/issue-13405.rs b/src/test/ui/issues/issue-13405.rs
new file mode 100644
index 0000000..32965cb
--- /dev/null
+++ b/src/test/ui/issues/issue-13405.rs
@@ -0,0 +1,20 @@
+// compile-pass
+#![allow(dead_code)]
+#![allow(unused_variables)]
+// pretty-expanded FIXME #23616
+
+struct Foo<'a> {
+    i: &'a bool,
+    j: Option<&'a isize>,
+}
+
+impl<'a> Foo<'a> {
+    fn bar(&mut self, j: &isize) {
+        let child = Foo {
+            i: self.i,
+            j: Some(j)
+        };
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-13407.rs b/src/test/ui/issues/issue-13407.rs
new file mode 100644
index 0000000..322e67c
--- /dev/null
+++ b/src/test/ui/issues/issue-13407.rs
@@ -0,0 +1,10 @@
+mod A {
+    struct C;
+}
+
+fn main() {
+    A::C = 1;
+    //~^ ERROR: invalid left-hand side expression
+    //~| ERROR: mismatched types
+    //~| ERROR: struct `C` is private
+}
diff --git a/src/test/ui/issues/issue-13407.stderr b/src/test/ui/issues/issue-13407.stderr
new file mode 100644
index 0000000..1f4c7df
--- /dev/null
+++ b/src/test/ui/issues/issue-13407.stderr
@@ -0,0 +1,25 @@
+error[E0603]: unit struct `C` is private
+  --> $DIR/issue-13407.rs:6:8
+   |
+LL |     A::C = 1;
+   |        ^
+
+error[E0308]: mismatched types
+  --> $DIR/issue-13407.rs:6:12
+   |
+LL |     A::C = 1;
+   |            ^ expected struct `A::C`, found integer
+   |
+   = note: expected type `A::C`
+              found type `{integer}`
+
+error[E0070]: invalid left-hand side expression
+  --> $DIR/issue-13407.rs:6:5
+   |
+LL |     A::C = 1;
+   |     ^^^^^^^^ left-hand of expression not valid
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0070, E0308, E0603.
+For more information about an error, try `rustc --explain E0070`.
diff --git a/src/test/ui/issues/issue-13446.rs b/src/test/ui/issues/issue-13446.rs
new file mode 100644
index 0000000..9f1fc42
--- /dev/null
+++ b/src/test/ui/issues/issue-13446.rs
@@ -0,0 +1,6 @@
+// Used to cause ICE
+
+static VEC: [u32; 256] = vec![];
+//~^ ERROR mismatched types
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-13446.stderr b/src/test/ui/issues/issue-13446.stderr
new file mode 100644
index 0000000..a27bfed
--- /dev/null
+++ b/src/test/ui/issues/issue-13446.stderr
@@ -0,0 +1,13 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-13446.rs:3:26
+   |
+LL | static VEC: [u32; 256] = vec![];
+   |                          ^^^^^^ expected array of 256 elements, found struct `std::vec::Vec`
+   |
+   = note: expected type `[u32; 256]`
+              found type `std::vec::Vec<_>`
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-13466.rs b/src/test/ui/issues/issue-13466.rs
new file mode 100644
index 0000000..c285bfa
--- /dev/null
+++ b/src/test/ui/issues/issue-13466.rs
@@ -0,0 +1,20 @@
+// Regression test for #13466
+
+pub fn main() {
+    // The expected arm type `Option<T>` has one type parameter, while
+    // the actual arm `Result<T, E>` has two. typeck should not be
+    // tricked into looking up a non-existing second type parameter.
+    let _x: usize = match Some(1) {
+        Ok(u) => u,
+        //~^ ERROR mismatched types
+        //~| expected type `std::option::Option<{integer}>`
+        //~| found type `std::result::Result<_, _>`
+        //~| expected enum `std::option::Option`, found enum `std::result::Result`
+
+        Err(e) => panic!(e)
+        //~^ ERROR mismatched types
+        //~| expected type `std::option::Option<{integer}>`
+        //~| found type `std::result::Result<_, _>`
+        //~| expected enum `std::option::Option`, found enum `std::result::Result`
+    };
+}
diff --git a/src/test/ui/issues/issue-13466.stderr b/src/test/ui/issues/issue-13466.stderr
new file mode 100644
index 0000000..6625589
--- /dev/null
+++ b/src/test/ui/issues/issue-13466.stderr
@@ -0,0 +1,26 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-13466.rs:8:9
+   |
+LL |     let _x: usize = match Some(1) {
+   |                           ------- this match expression has type `std::option::Option<{integer}>`
+LL |         Ok(u) => u,
+   |         ^^^^^ expected enum `std::option::Option`, found enum `std::result::Result`
+   |
+   = note: expected type `std::option::Option<{integer}>`
+              found type `std::result::Result<_, _>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-13466.rs:14:9
+   |
+LL |     let _x: usize = match Some(1) {
+   |                           ------- this match expression has type `std::option::Option<{integer}>`
+...
+LL |         Err(e) => panic!(e)
+   |         ^^^^^^ expected enum `std::option::Option`, found enum `std::result::Result`
+   |
+   = note: expected type `std::option::Option<{integer}>`
+              found type `std::result::Result<_, _>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-13482-2.rs b/src/test/ui/issues/issue-13482-2.rs
new file mode 100644
index 0000000..bbcb954
--- /dev/null
+++ b/src/test/ui/issues/issue-13482-2.rs
@@ -0,0 +1,9 @@
+// compile-flags:-Z verbose
+
+fn main() {
+    let x = [1,2];
+    let y = match x {
+        [] => None, //~ ERROR pattern requires 0 elements but array has 2
+        [a,_] => Some(a)
+    };
+}
diff --git a/src/test/ui/issues/issue-13482-2.stderr b/src/test/ui/issues/issue-13482-2.stderr
new file mode 100644
index 0000000..ccab958
--- /dev/null
+++ b/src/test/ui/issues/issue-13482-2.stderr
@@ -0,0 +1,9 @@
+error[E0527]: pattern requires 0 elements but array has 2
+  --> $DIR/issue-13482-2.rs:6:9
+   |
+LL |         [] => None,
+   |         ^^ expected 2 elements
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0527`.
diff --git a/src/test/ui/issues/issue-13482.rs b/src/test/ui/issues/issue-13482.rs
new file mode 100644
index 0000000..244b323
--- /dev/null
+++ b/src/test/ui/issues/issue-13482.rs
@@ -0,0 +1,7 @@
+fn main() {
+  let x = [1,2];
+  let y = match x {
+    [] => None, //~ ERROR pattern requires 0 elements but array has 2
+    [a,_] => Some(a)
+  };
+}
diff --git a/src/test/ui/issues/issue-13482.stderr b/src/test/ui/issues/issue-13482.stderr
new file mode 100644
index 0000000..3eb05f5
--- /dev/null
+++ b/src/test/ui/issues/issue-13482.stderr
@@ -0,0 +1,9 @@
+error[E0527]: pattern requires 0 elements but array has 2
+  --> $DIR/issue-13482.rs:4:5
+   |
+LL |     [] => None,
+   |     ^^ expected 2 elements
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0527`.
diff --git a/src/test/ui/issues/issue-13483.rs b/src/test/ui/issues/issue-13483.rs
new file mode 100644
index 0000000..cb53523
--- /dev/null
+++ b/src/test/ui/issues/issue-13483.rs
@@ -0,0 +1,15 @@
+fn main() {
+    if true {
+    } else if { //~ ERROR missing condition
+    } else {
+    }
+}
+
+fn foo() {
+    if true {
+    } else if { //~ ERROR missing condition
+    }
+    bar();
+}
+
+fn bar() {}
diff --git a/src/test/ui/issues/issue-13483.stderr b/src/test/ui/issues/issue-13483.stderr
new file mode 100644
index 0000000..739f061
--- /dev/null
+++ b/src/test/ui/issues/issue-13483.stderr
@@ -0,0 +1,14 @@
+error: missing condition for `if` statemement
+  --> $DIR/issue-13483.rs:3:14
+   |
+LL |     } else if {
+   |              ^ expected if condition here
+
+error: missing condition for `if` statemement
+  --> $DIR/issue-13483.rs:10:14
+   |
+LL |     } else if {
+   |              ^ expected if condition here
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/issues/issue-13497-2.nll.stderr b/src/test/ui/issues/issue-13497-2.nll.stderr
new file mode 100644
index 0000000..8ad9210
--- /dev/null
+++ b/src/test/ui/issues/issue-13497-2.nll.stderr
@@ -0,0 +1,14 @@
+error[E0515]: cannot return value referencing local variable `rawLines`
+  --> $DIR/issue-13497-2.rs:3:5
+   |
+LL |       rawLines
+   |       ^-------
+   |       |
+   |  _____`rawLines` is borrowed here
+   | |
+LL | |         .iter().map(|l| l.trim()).collect()
+   | |___________________________________________^ returns a value referencing data owned by the current function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/src/test/ui/issues/issue-13497-2.rs b/src/test/ui/issues/issue-13497-2.rs
new file mode 100644
index 0000000..a39ae4f
--- /dev/null
+++ b/src/test/ui/issues/issue-13497-2.rs
@@ -0,0 +1,7 @@
+fn read_lines_borrowed<'a>() -> Vec<&'a str> {
+    let rawLines: Vec<String> = vec!["foo  ".to_string(), "  bar".to_string()];
+    rawLines //~ ERROR `rawLines` does not live long enough
+        .iter().map(|l| l.trim()).collect()
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-13497-2.stderr b/src/test/ui/issues/issue-13497-2.stderr
new file mode 100644
index 0000000..5fde55c
--- /dev/null
+++ b/src/test/ui/issues/issue-13497-2.stderr
@@ -0,0 +1,18 @@
+error[E0597]: `rawLines` does not live long enough
+  --> $DIR/issue-13497-2.rs:3:5
+   |
+LL |     rawLines
+   |     ^^^^^^^^ borrowed value does not live long enough
+LL |         .iter().map(|l| l.trim()).collect()
+LL | }
+   | - borrowed value only lives until here
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 1:24...
+  --> $DIR/issue-13497-2.rs:1:24
+   |
+LL | fn read_lines_borrowed<'a>() -> Vec<&'a str> {
+   |                        ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/issues/issue-13497.rs b/src/test/ui/issues/issue-13497.rs
new file mode 100644
index 0000000..4b2795a
--- /dev/null
+++ b/src/test/ui/issues/issue-13497.rs
@@ -0,0 +1,8 @@
+fn read_lines_borrowed1() -> Vec<
+    &str //~ ERROR missing lifetime specifier
+> {
+    let rawLines: Vec<String> = vec!["foo  ".to_string(), "  bar".to_string()];
+    rawLines.iter().map(|l| l.trim()).collect()
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-13497.stderr b/src/test/ui/issues/issue-13497.stderr
new file mode 100644
index 0000000..b72f027
--- /dev/null
+++ b/src/test/ui/issues/issue-13497.stderr
@@ -0,0 +1,11 @@
+error[E0106]: missing lifetime specifier
+  --> $DIR/issue-13497.rs:2:5
+   |
+LL |     &str
+   |     ^ help: consider giving it a 'static lifetime: `&'static`
+   |
+   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0106`.
diff --git a/src/test/ui/issues/issue-1362.rs b/src/test/ui/issues/issue-1362.rs
new file mode 100644
index 0000000..6fd43f5
--- /dev/null
+++ b/src/test/ui/issues/issue-1362.rs
@@ -0,0 +1,8 @@
+// Regression test for issue #1362 - without that fix the span will be bogus
+// no-reformat
+fn main() {
+  let x: u32 = 20i32; //~ ERROR mismatched types
+}
+// NOTE: Do not add any extra lines as the line number the error is
+// on is significant; an error later in the source file might not
+// trigger the bug.
diff --git a/src/test/ui/issues/issue-1362.stderr b/src/test/ui/issues/issue-1362.stderr
new file mode 100644
index 0000000..5fef849
--- /dev/null
+++ b/src/test/ui/issues/issue-1362.stderr
@@ -0,0 +1,9 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-1362.rs:4:16
+   |
+LL |   let x: u32 = 20i32;
+   |                ^^^^^ expected u32, found i32
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-13641.rs b/src/test/ui/issues/issue-13641.rs
new file mode 100644
index 0000000..198cea4
--- /dev/null
+++ b/src/test/ui/issues/issue-13641.rs
@@ -0,0 +1,13 @@
+mod a {
+    struct Foo;
+    impl Foo { pub fn new() {} }
+    enum Bar {}
+    impl Bar { pub fn new() {} }
+}
+
+fn main() {
+    a::Foo::new();
+    //~^ ERROR: struct `Foo` is private
+    a::Bar::new();
+    //~^ ERROR: enum `Bar` is private
+}
diff --git a/src/test/ui/issues/issue-13641.stderr b/src/test/ui/issues/issue-13641.stderr
new file mode 100644
index 0000000..8e5001e
--- /dev/null
+++ b/src/test/ui/issues/issue-13641.stderr
@@ -0,0 +1,15 @@
+error[E0603]: struct `Foo` is private
+  --> $DIR/issue-13641.rs:9:8
+   |
+LL |     a::Foo::new();
+   |        ^^^
+
+error[E0603]: enum `Bar` is private
+  --> $DIR/issue-13641.rs:11:8
+   |
+LL |     a::Bar::new();
+   |        ^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0603`.
diff --git a/src/test/ui/issues/issue-13703.rs b/src/test/ui/issues/issue-13703.rs
new file mode 100644
index 0000000..212fff7
--- /dev/null
+++ b/src/test/ui/issues/issue-13703.rs
@@ -0,0 +1,6 @@
+// compile-pass
+// pretty-expanded FIXME #23616
+
+pub struct Foo<'a, 'b: 'a> { foo: &'a &'b isize }
+pub fn foo<'a, 'b>(x: Foo<'a, 'b>, _o: Option<&   &   ()>) { let _y = x.foo; }
+fn main() {}
diff --git a/src/test/ui/issues/issue-13727.rs b/src/test/ui/issues/issue-13727.rs
new file mode 100644
index 0000000..7fb565e
--- /dev/null
+++ b/src/test/ui/issues/issue-13727.rs
@@ -0,0 +1,15 @@
+#![allow(overflowing_literals)]
+#![deny(unreachable_patterns)]
+
+fn test(val: u8) {
+  match val {
+    256 => print!("0b1110\n"),
+    512 => print!("0b1111\n"),
+    //~^ ERROR: unreachable pattern
+    _   => print!("fail\n"),
+  }
+}
+
+fn main() {
+  test(1);
+}
diff --git a/src/test/ui/issues/issue-13727.stderr b/src/test/ui/issues/issue-13727.stderr
new file mode 100644
index 0000000..4d10665
--- /dev/null
+++ b/src/test/ui/issues/issue-13727.stderr
@@ -0,0 +1,14 @@
+error: unreachable pattern
+  --> $DIR/issue-13727.rs:7:5
+   |
+LL |     512 => print!("0b1111\n"),
+   |     ^^^
+   |
+note: lint level defined here
+  --> $DIR/issue-13727.rs:2:9
+   |
+LL | #![deny(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-13775.rs b/src/test/ui/issues/issue-13775.rs
new file mode 100644
index 0000000..39e42dc
--- /dev/null
+++ b/src/test/ui/issues/issue-13775.rs
@@ -0,0 +1,9 @@
+// compile-pass
+// pretty-expanded FIXME #23616
+
+trait Foo {
+    #[allow(anonymous_parameters)]
+    fn bar(&self, isize) {}
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-13837.rs b/src/test/ui/issues/issue-13837.rs
new file mode 100644
index 0000000..d475ce1
--- /dev/null
+++ b/src/test/ui/issues/issue-13837.rs
@@ -0,0 +1,13 @@
+// compile-pass
+#![allow(dead_code)]
+// pretty-expanded FIXME #23616
+
+struct TestStruct {
+    x: *const [isize; 2]
+}
+
+unsafe impl Sync for TestStruct {}
+
+static TEST_VALUE : TestStruct = TestStruct{x: 0x1234 as *const [isize; 2]};
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-13847.rs b/src/test/ui/issues/issue-13847.rs
new file mode 100644
index 0000000..06a0304
--- /dev/null
+++ b/src/test/ui/issues/issue-13847.rs
@@ -0,0 +1,3 @@
+fn main() {
+    return.is_failure //~ ERROR no field `is_failure` on type `!`
+}
diff --git a/src/test/ui/issues/issue-13847.stderr b/src/test/ui/issues/issue-13847.stderr
new file mode 100644
index 0000000..52b8dc0
--- /dev/null
+++ b/src/test/ui/issues/issue-13847.stderr
@@ -0,0 +1,9 @@
+error[E0609]: no field `is_failure` on type `!`
+  --> $DIR/issue-13847.rs:2:12
+   |
+LL |     return.is_failure
+   |            ^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0609`.
diff --git a/src/test/ui/issues/issue-13853-2.rs b/src/test/ui/issues/issue-13853-2.rs
new file mode 100644
index 0000000..b58f2bd
--- /dev/null
+++ b/src/test/ui/issues/issue-13853-2.rs
@@ -0,0 +1,6 @@
+trait FromStructReader<'a> { }
+trait ResponseHook {
+     fn get(&self);
+}
+fn foo(res : Box<ResponseHook>) { res.get } //~ ERROR attempted to take value of method
+fn main() {}
diff --git a/src/test/ui/issues/issue-13853-2.stderr b/src/test/ui/issues/issue-13853-2.stderr
new file mode 100644
index 0000000..0853f5c
--- /dev/null
+++ b/src/test/ui/issues/issue-13853-2.stderr
@@ -0,0 +1,9 @@
+error[E0615]: attempted to take value of method `get` on type `std::boxed::Box<(dyn ResponseHook + 'static)>`
+  --> $DIR/issue-13853-2.rs:5:39
+   |
+LL | fn foo(res : Box<ResponseHook>) { res.get }
+   |                                       ^^^ help: use parentheses to call the method: `get()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0615`.
diff --git a/src/test/ui/issues/issue-13853-5.rs b/src/test/ui/issues/issue-13853-5.rs
new file mode 100644
index 0000000..2afdf95
--- /dev/null
+++ b/src/test/ui/issues/issue-13853-5.rs
@@ -0,0 +1,13 @@
+trait Deserializer<'a> { }
+
+trait Deserializable {
+    fn deserialize_token<'a, D: Deserializer<'a>>(_: D, _: &'a str) -> Self;
+}
+
+impl<'a, T: Deserializable> Deserializable for &'a str {
+    //~^ ERROR type parameter `T` is not constrained
+    fn deserialize_token<D: Deserializer<'a>>(_x: D, _y: &'a str) -> &'a str {
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-13853-5.stderr b/src/test/ui/issues/issue-13853-5.stderr
new file mode 100644
index 0000000..3d8f824
--- /dev/null
+++ b/src/test/ui/issues/issue-13853-5.stderr
@@ -0,0 +1,9 @@
+error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates
+  --> $DIR/issue-13853-5.rs:7:10
+   |
+LL | impl<'a, T: Deserializable> Deserializable for &'a str {
+   |          ^ unconstrained type parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0207`.
diff --git a/src/test/ui/issues/issue-13853.rs b/src/test/ui/issues/issue-13853.rs
new file mode 100644
index 0000000..ac9886d
--- /dev/null
+++ b/src/test/ui/issues/issue-13853.rs
@@ -0,0 +1,38 @@
+trait Node {
+    fn zomg();
+}
+
+trait Graph<N: Node> {
+    fn nodes<'a, I: Iterator<Item=&'a N>>(&'a self) -> I
+        where N: 'a;
+}
+
+impl<N: Node> Graph<N> for Vec<N> {
+    fn nodes<'a, I: Iterator<Item=&'a N>>(&self) -> I
+        where N: 'a
+    {
+        self.iter() //~ ERROR mismatched types
+    }
+}
+
+struct Stuff;
+
+impl Node for Stuff {
+    fn zomg() {
+        println!("zomg");
+    }
+}
+
+fn iterate<N: Node, G: Graph<N>>(graph: &G) {
+    for node in graph.iter() { //~ ERROR no method named `iter` found
+        node.zomg();
+    }
+}
+
+pub fn main() {
+    let graph = Vec::new();
+
+    graph.push(Stuff);
+
+    iterate(graph); //~ ERROR mismatched types
+}
diff --git a/src/test/ui/issues/issue-13853.stderr b/src/test/ui/issues/issue-13853.stderr
new file mode 100644
index 0000000..b4efd55
--- /dev/null
+++ b/src/test/ui/issues/issue-13853.stderr
@@ -0,0 +1,34 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-13853.rs:14:9
+   |
+LL |     fn nodes<'a, I: Iterator<Item=&'a N>>(&self) -> I
+   |                                                     - expected `I` because of return type
+...
+LL |         self.iter()
+   |         ^^^^^^^^^^^ expected type parameter, found struct `std::slice::Iter`
+   |
+   = note: expected type `I`
+              found type `std::slice::Iter<'_, N>`
+
+error[E0599]: no method named `iter` found for type `&G` in the current scope
+  --> $DIR/issue-13853.rs:27:23
+   |
+LL |     for node in graph.iter() {
+   |                       ^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/issue-13853.rs:37:13
+   |
+LL |     iterate(graph);
+   |             ^^^^^
+   |             |
+   |             expected reference, found struct `std::vec::Vec`
+   |             help: consider borrowing here: `&graph`
+   |
+   = note: expected type `&_`
+              found type `std::vec::Vec<Stuff>`
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0308, E0599.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-14082.rs b/src/test/ui/issues/issue-14082.rs
new file mode 100644
index 0000000..4849077
--- /dev/null
+++ b/src/test/ui/issues/issue-14082.rs
@@ -0,0 +1,20 @@
+// compile-pass
+// pretty-expanded FIXME #23616
+
+#![allow(unused_imports, dead_code)]
+
+use foo::Foo;
+
+mod foo {
+    pub use m::Foo; // this should shadow d::Foo
+}
+
+mod m {
+    pub struct Foo;
+}
+
+mod d {
+    pub struct Foo;
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-14091-2.rs b/src/test/ui/issues/issue-14091-2.rs
new file mode 100644
index 0000000..e2f6b18
--- /dev/null
+++ b/src/test/ui/issues/issue-14091-2.rs
@@ -0,0 +1,17 @@
+//
+
+// Very
+
+// sensitive
+pub struct BytePos(pub u32);
+
+// to particular
+
+// line numberings / offsets
+
+fn main() {
+    let x = BytePos(1);
+
+    assert!(x, x);
+    //~^ ERROR cannot apply unary operator `!` to type `BytePos`
+}
diff --git a/src/test/ui/issues/issue-14091-2.stderr b/src/test/ui/issues/issue-14091-2.stderr
new file mode 100644
index 0000000..2d6e956
--- /dev/null
+++ b/src/test/ui/issues/issue-14091-2.stderr
@@ -0,0 +1,11 @@
+error[E0600]: cannot apply unary operator `!` to type `BytePos`
+  --> $DIR/issue-14091-2.rs:15:5
+   |
+LL |     assert!(x, x);
+   |     ^^^^^^^^^^^^^^ cannot apply unary operator `!`
+   |
+   = note: an implementation of `std::ops::Not` might be missing for `BytePos`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0600`.
diff --git a/src/test/ui/issues/issue-14091.rs b/src/test/ui/issues/issue-14091.rs
new file mode 100644
index 0000000..0ee20de
--- /dev/null
+++ b/src/test/ui/issues/issue-14091.rs
@@ -0,0 +1,4 @@
+fn main(){
+    assert!(1,1);
+    //~^ ERROR mismatched types
+}
diff --git a/src/test/ui/issues/issue-14091.stderr b/src/test/ui/issues/issue-14091.stderr
new file mode 100644
index 0000000..24a0766
--- /dev/null
+++ b/src/test/ui/issues/issue-14091.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-14091.rs:2:5
+   |
+LL |     assert!(1,1);
+   |     ^^^^^^^^^^^^^ expected bool, found integer
+   |
+   = note: expected type `bool`
+              found type `{integer}`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-14092.rs b/src/test/ui/issues/issue-14092.rs
new file mode 100644
index 0000000..77da6ba
--- /dev/null
+++ b/src/test/ui/issues/issue-14092.rs
@@ -0,0 +1,4 @@
+fn fn1(0: Box) {}
+        //~^ ERROR wrong number of type arguments: expected 1, found 0 [E0107]
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-14092.stderr b/src/test/ui/issues/issue-14092.stderr
new file mode 100644
index 0000000..626830e
--- /dev/null
+++ b/src/test/ui/issues/issue-14092.stderr
@@ -0,0 +1,9 @@
+error[E0107]: wrong number of type arguments: expected 1, found 0
+  --> $DIR/issue-14092.rs:1:11
+   |
+LL | fn fn1(0: Box) {}
+   |           ^^^ expected 1 type argument
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0107`.
diff --git a/src/test/ui/issues/issue-14221.rs b/src/test/ui/issues/issue-14221.rs
new file mode 100644
index 0000000..282c411
--- /dev/null
+++ b/src/test/ui/issues/issue-14221.rs
@@ -0,0 +1,21 @@
+#![deny(unreachable_patterns)]
+#![allow(unused_variables)]
+#![allow(non_snake_case)]
+
+pub enum E {
+    A,
+    B,
+}
+
+pub mod b {
+    pub fn key(e: ::E) -> &'static str {
+        match e {
+            A => "A",
+//~^ WARN pattern binding `A` is named the same as one of the variants of the type `E`
+            B => "B", //~ ERROR: unreachable pattern
+//~^ WARN pattern binding `B` is named the same as one of the variants of the type `E`
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-14221.stderr b/src/test/ui/issues/issue-14221.stderr
new file mode 100644
index 0000000..3e5e25a
--- /dev/null
+++ b/src/test/ui/issues/issue-14221.stderr
@@ -0,0 +1,30 @@
+warning[E0170]: pattern binding `A` is named the same as one of the variants of the type `E`
+  --> $DIR/issue-14221.rs:13:13
+   |
+LL |             A => "A",
+   |             ^ help: to match on the variant, qualify the path: `E::A`
+
+warning[E0170]: pattern binding `B` is named the same as one of the variants of the type `E`
+  --> $DIR/issue-14221.rs:15:13
+   |
+LL |             B => "B",
+   |             ^ help: to match on the variant, qualify the path: `E::B`
+
+error: unreachable pattern
+  --> $DIR/issue-14221.rs:15:13
+   |
+LL |             A => "A",
+   |             - matches any value
+LL |
+LL |             B => "B",
+   |             ^ unreachable pattern
+   |
+note: lint level defined here
+  --> $DIR/issue-14221.rs:1:9
+   |
+LL | #![deny(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0170`.
diff --git a/src/test/ui/issues/issue-14227.rs b/src/test/ui/issues/issue-14227.rs
new file mode 100644
index 0000000..5de3867
--- /dev/null
+++ b/src/test/ui/issues/issue-14227.rs
@@ -0,0 +1,10 @@
+#![allow(safe_extern_statics, warnings)]
+
+extern {
+    pub static symbol: u32;
+}
+static CRASH: u32 = symbol;
+//~^ ERROR could not evaluate static initializer
+//~| tried to read from foreign (extern) static
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-14227.stderr b/src/test/ui/issues/issue-14227.stderr
new file mode 100644
index 0000000..88e99e2
--- /dev/null
+++ b/src/test/ui/issues/issue-14227.stderr
@@ -0,0 +1,9 @@
+error[E0080]: could not evaluate static initializer
+  --> $DIR/issue-14227.rs:6:21
+   |
+LL | static CRASH: u32 = symbol;
+   |                     ^^^^^^ tried to read from foreign (extern) static
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/issues/issue-14254.rs b/src/test/ui/issues/issue-14254.rs
new file mode 100644
index 0000000..3ad388d
--- /dev/null
+++ b/src/test/ui/issues/issue-14254.rs
@@ -0,0 +1,93 @@
+// compile-pass
+// pretty-expanded FIXME #23616
+
+trait Foo: Sized {
+    fn bar(&self);
+    fn baz(&self) { }
+    fn bah(_: Option<Self>) { }
+}
+
+struct BarTy {
+    x : isize,
+    y : f64,
+}
+
+impl BarTy {
+    fn a() {}
+    fn b(&self) {}
+}
+
+// If these fail, it's necessary to update rustc_resolve and the cfail tests.
+impl Foo for *const BarTy {
+    fn bar(&self) {
+        self.baz();
+        BarTy::a();
+        Foo::bah(None::<*const BarTy>);
+    }
+}
+
+// If these fail, it's necessary to update rustc_resolve and the cfail tests.
+impl<'a> Foo for &'a BarTy {
+    fn bar(&self) {
+        self.baz();
+        self.x;
+        self.y;
+        BarTy::a();
+        Foo::bah(None::<&BarTy>);
+        self.b();
+    }
+}
+
+// If these fail, it's necessary to update rustc_resolve and the cfail tests.
+impl<'a> Foo for &'a mut BarTy {
+    fn bar(&self) {
+        self.baz();
+        self.x;
+        self.y;
+        BarTy::a();
+        Foo::bah(None::<&mut BarTy>);
+        self.b();
+    }
+}
+
+// If these fail, it's necessary to update rustc_resolve and the cfail tests.
+impl Foo for Box<BarTy> {
+    fn bar(&self) {
+        self.baz();
+        Foo::bah(None::<Box<BarTy>>);
+    }
+}
+
+// If these fail, it's necessary to update rustc_resolve and the cfail tests.
+impl Foo for *const isize {
+    fn bar(&self) {
+        self.baz();
+        Foo::bah(None::<*const isize>);
+    }
+}
+
+// If these fail, it's necessary to update rustc_resolve and the cfail tests.
+impl<'a> Foo for &'a isize {
+    fn bar(&self) {
+        self.baz();
+        Foo::bah(None::<&isize>);
+    }
+}
+
+// If these fail, it's necessary to update rustc_resolve and the cfail tests.
+impl<'a> Foo for &'a mut isize {
+    fn bar(&self) {
+        self.baz();
+        Foo::bah(None::<&mut isize>);
+    }
+}
+
+// If these fail, it's necessary to update rustc_resolve and the cfail tests.
+impl Foo for Box<isize> {
+    fn bar(&self) {
+        self.baz();
+        Foo::bah(None::<Box<isize>>);
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-14285.rs b/src/test/ui/issues/issue-14285.rs
new file mode 100644
index 0000000..934d72a
--- /dev/null
+++ b/src/test/ui/issues/issue-14285.rs
@@ -0,0 +1,17 @@
+trait Foo {
+    fn dummy(&self) { }
+}
+
+struct A;
+
+impl Foo for A {}
+
+struct B<'a>(&'a (Foo+'a));
+
+fn foo<'a>(a: &Foo) -> B<'a> {
+    B(a)    //~ ERROR explicit lifetime required in the type of `a` [E0621]
+}
+
+fn main() {
+    let _test = foo(&A);
+}
diff --git a/src/test/ui/issues/issue-14285.stderr b/src/test/ui/issues/issue-14285.stderr
new file mode 100644
index 0000000..c180ed0
--- /dev/null
+++ b/src/test/ui/issues/issue-14285.stderr
@@ -0,0 +1,11 @@
+error[E0621]: explicit lifetime required in the type of `a`
+  --> $DIR/issue-14285.rs:12:5
+   |
+LL | fn foo<'a>(a: &Foo) -> B<'a> {
+   |               ---- help: add explicit lifetime `'a` to the type of `a`: `&'a (dyn Foo + 'a)`
+LL |     B(a)
+   |     ^^^^ lifetime `'a` required
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/issues/issue-14309.rs b/src/test/ui/issues/issue-14309.rs
new file mode 100644
index 0000000..d0e532a
--- /dev/null
+++ b/src/test/ui/issues/issue-14309.rs
@@ -0,0 +1,39 @@
+#![deny(improper_ctypes)]
+#![allow(dead_code)]
+
+struct A {
+    x: i32
+}
+
+#[repr(C, packed)]
+struct B {
+    x: i32,
+    y: A
+}
+
+#[repr(C)]
+struct C {
+    x: i32
+}
+
+type A2 = A;
+type B2 = B;
+type C2 = C;
+
+#[repr(C)]
+struct D {
+    x: C,
+    y: A
+}
+
+extern "C" {
+    fn foo(x: A); //~ ERROR type `A` which is not FFI-safe
+    fn bar(x: B); //~ ERROR type `A`
+    fn baz(x: C);
+    fn qux(x: A2); //~ ERROR type `A`
+    fn quux(x: B2); //~ ERROR type `A`
+    fn corge(x: C2);
+    fn fred(x: D); //~ ERROR type `A`
+}
+
+fn main() { }
diff --git a/src/test/ui/issues/issue-14309.stderr b/src/test/ui/issues/issue-14309.stderr
new file mode 100644
index 0000000..4376876
--- /dev/null
+++ b/src/test/ui/issues/issue-14309.stderr
@@ -0,0 +1,82 @@
+error: `extern` block uses type `A` which is not FFI-safe: this struct has unspecified layout
+  --> $DIR/issue-14309.rs:30:15
+   |
+LL |     fn foo(x: A);
+   |               ^
+   |
+note: lint level defined here
+  --> $DIR/issue-14309.rs:1:9
+   |
+LL | #![deny(improper_ctypes)]
+   |         ^^^^^^^^^^^^^^^
+   = help: consider adding a #[repr(C)] or #[repr(transparent)] attribute to this struct
+note: type defined here
+  --> $DIR/issue-14309.rs:4:1
+   |
+LL | / struct A {
+LL | |     x: i32
+LL | | }
+   | |_^
+
+error: `extern` block uses type `A` which is not FFI-safe: this struct has unspecified layout
+  --> $DIR/issue-14309.rs:31:15
+   |
+LL |     fn bar(x: B);
+   |               ^
+   |
+   = help: consider adding a #[repr(C)] or #[repr(transparent)] attribute to this struct
+note: type defined here
+  --> $DIR/issue-14309.rs:4:1
+   |
+LL | / struct A {
+LL | |     x: i32
+LL | | }
+   | |_^
+
+error: `extern` block uses type `A` which is not FFI-safe: this struct has unspecified layout
+  --> $DIR/issue-14309.rs:33:15
+   |
+LL |     fn qux(x: A2);
+   |               ^^
+   |
+   = help: consider adding a #[repr(C)] or #[repr(transparent)] attribute to this struct
+note: type defined here
+  --> $DIR/issue-14309.rs:4:1
+   |
+LL | / struct A {
+LL | |     x: i32
+LL | | }
+   | |_^
+
+error: `extern` block uses type `A` which is not FFI-safe: this struct has unspecified layout
+  --> $DIR/issue-14309.rs:34:16
+   |
+LL |     fn quux(x: B2);
+   |                ^^
+   |
+   = help: consider adding a #[repr(C)] or #[repr(transparent)] attribute to this struct
+note: type defined here
+  --> $DIR/issue-14309.rs:4:1
+   |
+LL | / struct A {
+LL | |     x: i32
+LL | | }
+   | |_^
+
+error: `extern` block uses type `A` which is not FFI-safe: this struct has unspecified layout
+  --> $DIR/issue-14309.rs:36:16
+   |
+LL |     fn fred(x: D);
+   |                ^
+   |
+   = help: consider adding a #[repr(C)] or #[repr(transparent)] attribute to this struct
+note: type defined here
+  --> $DIR/issue-14309.rs:4:1
+   |
+LL | / struct A {
+LL | |     x: i32
+LL | | }
+   | |_^
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/ui/issues/issue-14330.rs b/src/test/ui/issues/issue-14330.rs
new file mode 100644
index 0000000..d8f225e
--- /dev/null
+++ b/src/test/ui/issues/issue-14330.rs
@@ -0,0 +1,7 @@
+// compile-pass
+#![allow(unused_imports)]
+// pretty-expanded FIXME #23616
+
+#[macro_use] extern crate std as std2;
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-14366.rs b/src/test/ui/issues/issue-14366.rs
new file mode 100644
index 0000000..a6298f2
--- /dev/null
+++ b/src/test/ui/issues/issue-14366.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let _x = "test" as &::std::any::Any;
+    //~^ ERROR the size for values of type
+}
diff --git a/src/test/ui/issues/issue-14366.stderr b/src/test/ui/issues/issue-14366.stderr
new file mode 100644
index 0000000..a3588bb
--- /dev/null
+++ b/src/test/ui/issues/issue-14366.stderr
@@ -0,0 +1,13 @@
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+  --> $DIR/issue-14366.rs:2:14
+   |
+LL |     let _x = "test" as &::std::any::Any;
+   |              ^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `str`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: required for the cast to the object type `dyn std::any::Any`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-1448-2.rs b/src/test/ui/issues/issue-1448-2.rs
new file mode 100644
index 0000000..829e81b
--- /dev/null
+++ b/src/test/ui/issues/issue-1448-2.rs
@@ -0,0 +1,7 @@
+// Regression test for issue #1448 and #1386
+
+fn foo(a: u32) -> u32 { a }
+
+fn main() {
+    println!("{}", foo(10i32)); //~ ERROR mismatched types
+}
diff --git a/src/test/ui/issues/issue-1448-2.stderr b/src/test/ui/issues/issue-1448-2.stderr
new file mode 100644
index 0000000..487b061
--- /dev/null
+++ b/src/test/ui/issues/issue-1448-2.stderr
@@ -0,0 +1,9 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-1448-2.rs:6:24
+   |
+LL |     println!("{}", foo(10i32));
+   |                        ^^^^^ expected u32, found i32
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-14541.rs b/src/test/ui/issues/issue-14541.rs
new file mode 100644
index 0000000..705c3d3
--- /dev/null
+++ b/src/test/ui/issues/issue-14541.rs
@@ -0,0 +1,12 @@
+struct Vec2 { y: f32 }
+struct Vec3 { y: f32, z: f32 }
+
+fn make(v: Vec2) {
+    let Vec3 { y: _, z: _ } = v;
+    //~^ ERROR mismatched types
+    //~| expected type `Vec2`
+    //~| found type `Vec3`
+    //~| expected struct `Vec2`, found struct `Vec3`
+}
+
+fn main() { }
diff --git a/src/test/ui/issues/issue-14541.stderr b/src/test/ui/issues/issue-14541.stderr
new file mode 100644
index 0000000..aa0ae5c
--- /dev/null
+++ b/src/test/ui/issues/issue-14541.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-14541.rs:5:9
+   |
+LL |     let Vec3 { y: _, z: _ } = v;
+   |         ^^^^^^^^^^^^^^^^^^^ expected struct `Vec2`, found struct `Vec3`
+   |
+   = note: expected type `Vec2`
+              found type `Vec3`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-14721.rs b/src/test/ui/issues/issue-14721.rs
new file mode 100644
index 0000000..a5c47dd
--- /dev/null
+++ b/src/test/ui/issues/issue-14721.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let foo = "str";
+    println!("{}", foo.desc); //~ no field `desc` on type `&str`
+}
diff --git a/src/test/ui/issues/issue-14721.stderr b/src/test/ui/issues/issue-14721.stderr
new file mode 100644
index 0000000..49ebb29
--- /dev/null
+++ b/src/test/ui/issues/issue-14721.stderr
@@ -0,0 +1,9 @@
+error[E0609]: no field `desc` on type `&str`
+  --> $DIR/issue-14721.rs:3:24
+   |
+LL |     println!("{}", foo.desc);
+   |                        ^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0609`.
diff --git a/src/test/ui/issues/issue-1476.rs b/src/test/ui/issues/issue-1476.rs
new file mode 100644
index 0000000..138570a
--- /dev/null
+++ b/src/test/ui/issues/issue-1476.rs
@@ -0,0 +1,3 @@
+fn main() {
+    println!("{}", x); //~ ERROR cannot find value `x` in this scope
+}
diff --git a/src/test/ui/issues/issue-1476.stderr b/src/test/ui/issues/issue-1476.stderr
new file mode 100644
index 0000000..670bd54
--- /dev/null
+++ b/src/test/ui/issues/issue-1476.stderr
@@ -0,0 +1,9 @@
+error[E0425]: cannot find value `x` in this scope
+  --> $DIR/issue-1476.rs:2:20
+   |
+LL |     println!("{}", x);
+   |                    ^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/issues/issue-14772.rs b/src/test/ui/issues/issue-14772.rs
new file mode 100644
index 0000000..8f67452
--- /dev/null
+++ b/src/test/ui/issues/issue-14772.rs
@@ -0,0 +1,6 @@
+// compile-flags: --test
+
+#[test]
+mod foo {} //~ ERROR only functions may be used as tests
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-14772.stderr b/src/test/ui/issues/issue-14772.stderr
new file mode 100644
index 0000000..253fec5
--- /dev/null
+++ b/src/test/ui/issues/issue-14772.stderr
@@ -0,0 +1,8 @@
+error: only functions may be used as tests
+  --> $DIR/issue-14772.rs:4:1
+   |
+LL | mod foo {}
+   | ^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-14837.rs b/src/test/ui/issues/issue-14837.rs
new file mode 100644
index 0000000..5438780
--- /dev/null
+++ b/src/test/ui/issues/issue-14837.rs
@@ -0,0 +1,11 @@
+// compile-pass
+// pretty-expanded FIXME #23616
+
+#[deny(dead_code)]
+pub enum Foo {
+    Bar {
+        baz: isize
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/issues/issue-14845.rs b/src/test/ui/issues/issue-14845.rs
new file mode 100644
index 0000000..d9b20e1
--- /dev/null
+++ b/src/test/ui/issues/issue-14845.rs
@@ -0,0 +1,11 @@
+struct X {
+    a: [u8; 1]
+}
+
+fn main() {
+    let x = X { a: [0] };
+    let _f = &x.a as *mut u8; //~ ERROR casting
+
+    let local: [u8; 1] = [0];
+    let _v = &local as *mut u8; //~ ERROR casting
+}
diff --git a/src/test/ui/issues/issue-14845.stderr b/src/test/ui/issues/issue-14845.stderr
new file mode 100644
index 0000000..2fa9fba
--- /dev/null
+++ b/src/test/ui/issues/issue-14845.stderr
@@ -0,0 +1,15 @@
+error[E0606]: casting `&[u8; 1]` as `*mut u8` is invalid
+  --> $DIR/issue-14845.rs:7:14
+   |
+LL |     let _f = &x.a as *mut u8;
+   |              ^^^^^^^^^^^^^^^
+
+error[E0606]: casting `&[u8; 1]` as `*mut u8` is invalid
+  --> $DIR/issue-14845.rs:10:14
+   |
+LL |     let _v = &local as *mut u8;
+   |              ^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0606`.
diff --git a/src/test/ui/issues/issue-14853.rs b/src/test/ui/issues/issue-14853.rs
new file mode 100644
index 0000000..4ce6e31
--- /dev/null
+++ b/src/test/ui/issues/issue-14853.rs
@@ -0,0 +1,20 @@
+use std::fmt::Debug;
+
+trait Str {}
+
+trait Something: Sized {
+    fn yay<T: Debug>(_: Option<Self>, thing: &[T]);
+}
+
+struct X { data: u32 }
+
+impl Something for X {
+    fn yay<T: Str>(_:Option<X>, thing: &[T]) {
+    //~^ ERROR E0276
+    }
+}
+
+fn main() {
+    let arr = &["one", "two", "three"];
+    println!("{:?}", Something::yay(None::<X>, arr));
+}
diff --git a/src/test/ui/issues/issue-14853.stderr b/src/test/ui/issues/issue-14853.stderr
new file mode 100644
index 0000000..6fc1055
--- /dev/null
+++ b/src/test/ui/issues/issue-14853.stderr
@@ -0,0 +1,12 @@
+error[E0276]: impl has stricter requirements than trait
+  --> $DIR/issue-14853.rs:12:5
+   |
+LL |     fn yay<T: Debug>(_: Option<Self>, thing: &[T]);
+   |     ----------------------------------------------- definition of `yay` from trait
+...
+LL |     fn yay<T: Str>(_:Option<X>, thing: &[T]) {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `T: Str`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0276`.
diff --git a/src/test/ui/issues/issue-14901.rs b/src/test/ui/issues/issue-14901.rs
new file mode 100644
index 0000000..61b2b64
--- /dev/null
+++ b/src/test/ui/issues/issue-14901.rs
@@ -0,0 +1,18 @@
+// compile-pass
+pub trait Reader {}
+
+enum Wrapper<'a> {
+    WrapReader(&'a (Reader + 'a))
+}
+
+trait Wrap<'a> {
+    fn wrap(self) -> Wrapper<'a>;
+}
+
+impl<'a, R: Reader> Wrap<'a> for &'a mut R {
+    fn wrap(self) -> Wrapper<'a> {
+        Wrapper::WrapReader(self as &'a mut Reader)
+    }
+}
+
+pub fn main() {}
diff --git a/src/test/ui/issues/issue-14915.rs b/src/test/ui/issues/issue-14915.rs
new file mode 100644
index 0000000..294533f
--- /dev/null
+++ b/src/test/ui/issues/issue-14915.rs
@@ -0,0 +1,8 @@
+#![feature(box_syntax)]
+
+fn main() {
+    let x: Box<isize> = box 0;
+
+    println!("{}", x + 1);
+    //~^ ERROR binary operation `+` cannot be applied to type `std::boxed::Box<isize>`
+}
diff --git a/src/test/ui/issues/issue-14915.stderr b/src/test/ui/issues/issue-14915.stderr
new file mode 100644
index 0000000..e8de443
--- /dev/null
+++ b/src/test/ui/issues/issue-14915.stderr
@@ -0,0 +1,13 @@
+error[E0369]: binary operation `+` cannot be applied to type `std::boxed::Box<isize>`
+  --> $DIR/issue-14915.rs:6:22
+   |
+LL |     println!("{}", x + 1);
+   |                    - ^ - {integer}
+   |                    |
+   |                    std::boxed::Box<isize>
+   |
+   = note: an implementation of `std::ops::Add` might be missing for `std::boxed::Box<isize>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0369`.
diff --git a/src/test/ui/issues/issue-14933.rs b/src/test/ui/issues/issue-14933.rs
new file mode 100644
index 0000000..9249ba3
--- /dev/null
+++ b/src/test/ui/issues/issue-14933.rs
@@ -0,0 +1,6 @@
+// compile-pass
+// pretty-expanded FIXME #23616
+
+pub type BigRat<T = isize> = T;
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-14936.rs b/src/test/ui/issues/issue-14936.rs
new file mode 100644
index 0000000..bd3c99a
--- /dev/null
+++ b/src/test/ui/issues/issue-14936.rs
@@ -0,0 +1,48 @@
+// compile-pass
+#![allow(unused_macros)]
+#![allow(dead_code)]
+#![feature(asm)]
+
+type History = Vec<&'static str>;
+
+fn wrap<A>(x:A, which: &'static str, history: &mut History) -> A {
+    history.push(which);
+    x
+}
+
+macro_rules! demo {
+    ( $output_constraint:tt ) => {
+        {
+            let mut x: isize = 0;
+            let y: isize = 1;
+
+            let mut history: History = vec![];
+            unsafe {
+                asm!("mov ($1), $0"
+                     : $output_constraint (*wrap(&mut x, "out", &mut history))
+                     : "r"(&wrap(y, "in", &mut history))
+                     :: "volatile");
+            }
+            assert_eq!((x,y), (1,1));
+            let b: &[_] = &["out", "in"];
+            assert_eq!(history, b);
+        }
+    }
+}
+
+#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+fn main() {
+    fn out_write_only_expr_then_in_expr() {
+        demo!("=r")
+    }
+
+    fn out_read_write_expr_then_in_expr() {
+        demo!("+r")
+    }
+
+    out_write_only_expr_then_in_expr();
+    out_read_write_expr_then_in_expr();
+}
+
+#[cfg(all(not(target_arch = "x86"), not(target_arch = "x86_64")))]
+pub fn main() {}
diff --git a/src/test/ui/issues/issue-14959.rs b/src/test/ui/issues/issue-14959.rs
new file mode 100644
index 0000000..78ae21e
--- /dev/null
+++ b/src/test/ui/issues/issue-14959.rs
@@ -0,0 +1,55 @@
+// compile-pass
+// pretty-expanded FIXME #23616
+
+#![feature(fn_traits, unboxed_closures)]
+
+use std::ops::Fn;
+
+trait Response { fn dummy(&self) { } }
+trait Request { fn dummy(&self) { } }
+trait Ingot<R, S> {
+    fn enter(&mut self, _: &mut R, _: &mut S, a: &mut Alloy) -> Status;
+}
+
+#[allow(dead_code)]
+struct HelloWorld;
+
+struct SendFile;
+struct Alloy;
+enum Status {
+    Continue
+}
+
+impl Alloy {
+    fn find<T>(&self) -> Option<T> {
+        None
+    }
+}
+
+impl<'b> Fn<(&'b mut (Response+'b),)> for SendFile {
+    extern "rust-call" fn call(&self, (_res,): (&'b mut (Response+'b),)) {}
+}
+
+impl<'b> FnMut<(&'b mut (Response+'b),)> for SendFile {
+    extern "rust-call" fn call_mut(&mut self, (_res,): (&'b mut (Response+'b),)) {
+        self.call((_res,))
+    }
+}
+
+impl<'b> FnOnce<(&'b mut (Response+'b),)> for SendFile {
+    type Output = ();
+
+    extern "rust-call" fn call_once(self, (_res,): (&'b mut (Response+'b),)) {
+        self.call((_res,))
+    }
+}
+
+impl<Rq: Request, Rs: Response> Ingot<Rq, Rs> for HelloWorld {
+    fn enter(&mut self, _req: &mut Rq, res: &mut Rs, alloy: &mut Alloy) -> Status {
+        let send_file = alloy.find::<SendFile>().unwrap();
+        send_file(res);
+        Status::Continue
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-15034.rs b/src/test/ui/issues/issue-15034.rs
new file mode 100644
index 0000000..9ea6ed8
--- /dev/null
+++ b/src/test/ui/issues/issue-15034.rs
@@ -0,0 +1,22 @@
+pub struct Lexer<'a> {
+    input: &'a str,
+}
+
+impl<'a> Lexer<'a> {
+    pub fn new(input: &'a str) -> Lexer<'a> {
+        Lexer { input: input }
+    }
+}
+
+struct Parser<'a> {
+    lexer: &'a mut Lexer<'a>,
+}
+
+impl<'a> Parser<'a> {
+    pub fn new(lexer: &'a mut Lexer) -> Parser<'a> {
+        Parser { lexer: lexer }
+        //~^ ERROR explicit lifetime required in the type of `lexer` [E0621]
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-15034.stderr b/src/test/ui/issues/issue-15034.stderr
new file mode 100644
index 0000000..3ede5ba
--- /dev/null
+++ b/src/test/ui/issues/issue-15034.stderr
@@ -0,0 +1,11 @@
+error[E0621]: explicit lifetime required in the type of `lexer`
+  --> $DIR/issue-15034.rs:17:25
+   |
+LL |     pub fn new(lexer: &'a mut Lexer) -> Parser<'a> {
+   |                       ------------- help: add explicit lifetime `'a` to the type of `lexer`: `&'a mut Lexer<'a>`
+LL |         Parser { lexer: lexer }
+   |                         ^^^^^ lifetime `'a` required
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/issues/issue-15094.rs b/src/test/ui/issues/issue-15094.rs
new file mode 100644
index 0000000..dea85df
--- /dev/null
+++ b/src/test/ui/issues/issue-15094.rs
@@ -0,0 +1,26 @@
+#![feature(fn_traits, unboxed_closures)]
+
+use std::{fmt, ops};
+
+struct Debuger<T> {
+    x: T
+}
+
+impl<T: fmt::Debug> ops::FnOnce<(),> for Debuger<T> {
+    type Output = ();
+    fn call_once(self, _args: ()) {
+    //~^ ERROR `call_once` has an incompatible type for trait
+    //~| expected type `extern "rust-call" fn
+    //~| found type `fn
+        println!("{:?}", self.x);
+    }
+}
+
+fn make_shower<T>(x: T) -> Debuger<T> {
+    Debuger { x: x }
+}
+
+pub fn main() {
+    let show3 = make_shower(3);
+    show3();
+}
diff --git a/src/test/ui/issues/issue-15094.stderr b/src/test/ui/issues/issue-15094.stderr
new file mode 100644
index 0000000..07e1471
--- /dev/null
+++ b/src/test/ui/issues/issue-15094.stderr
@@ -0,0 +1,12 @@
+error[E0053]: method `call_once` has an incompatible type for trait
+  --> $DIR/issue-15094.rs:11:5
+   |
+LL |     fn call_once(self, _args: ()) {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected "rust-call" fn, found "Rust" fn
+   |
+   = note: expected type `extern "rust-call" fn(Debuger<T>, ())`
+              found type `fn(Debuger<T>, ())`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0053`.
diff --git a/src/test/ui/issues/issue-15108.rs b/src/test/ui/issues/issue-15108.rs
new file mode 100644
index 0000000..d2b56c0
--- /dev/null
+++ b/src/test/ui/issues/issue-15108.rs
@@ -0,0 +1,4 @@
+// compile-pass
+// pretty-expanded FIXME #23616
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-15129.rs b/src/test/ui/issues/issue-15129.rs
new file mode 100644
index 0000000..ed134c1
--- /dev/null
+++ b/src/test/ui/issues/issue-15129.rs
@@ -0,0 +1,17 @@
+pub enum T {
+    T1(()),
+    T2(())
+}
+
+pub enum V {
+    V1(isize),
+    V2(bool)
+}
+
+fn main() {
+    match (T::T1(()), V::V2(true)) {
+    //~^ ERROR non-exhaustive patterns: `(T1(()), V2(_))` not covered
+        (T::T1(()), V::V1(i)) => (),
+        (T::T2(()), V::V2(b)) => ()
+    }
+}
diff --git a/src/test/ui/issues/issue-15129.stderr b/src/test/ui/issues/issue-15129.stderr
new file mode 100644
index 0000000..b93fa14
--- /dev/null
+++ b/src/test/ui/issues/issue-15129.stderr
@@ -0,0 +1,11 @@
+error[E0004]: non-exhaustive patterns: `(T1(()), V2(_))` not covered
+  --> $DIR/issue-15129.rs:12:11
+   |
+LL |     match (T::T1(()), V::V2(true)) {
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `(T1(()), V2(_))` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/issues/issue-15167.rs b/src/test/ui/issues/issue-15167.rs
new file mode 100644
index 0000000..a2653c1
--- /dev/null
+++ b/src/test/ui/issues/issue-15167.rs
@@ -0,0 +1,26 @@
+// macro f should not be able to inject a reference to 'n'.
+
+macro_rules! f { () => (n) }
+//~^ ERROR cannot find value `n` in this scope
+//~| ERROR cannot find value `n` in this scope
+//~| ERROR cannot find value `n` in this scope
+//~| ERROR cannot find value `n` in this scope
+
+fn main() -> (){
+    for n in 0..1 {
+        println!("{}", f!());
+    }
+
+    if let Some(n) = None {
+        println!("{}", f!());
+    }
+
+    if false {
+    } else if let Some(n) = None {
+        println!("{}", f!());
+    }
+
+    while let Some(n) = None {
+        println!("{}", f!());
+    }
+}
diff --git a/src/test/ui/issues/issue-15167.stderr b/src/test/ui/issues/issue-15167.stderr
new file mode 100644
index 0000000..1c488bf
--- /dev/null
+++ b/src/test/ui/issues/issue-15167.stderr
@@ -0,0 +1,39 @@
+error[E0425]: cannot find value `n` in this scope
+  --> $DIR/issue-15167.rs:3:25
+   |
+LL | macro_rules! f { () => (n) }
+   |                         ^ not found in this scope
+...
+LL |         println!("{}", f!());
+   |                        ---- in this macro invocation
+
+error[E0425]: cannot find value `n` in this scope
+  --> $DIR/issue-15167.rs:3:25
+   |
+LL | macro_rules! f { () => (n) }
+   |                         ^ not found in this scope
+...
+LL |         println!("{}", f!());
+   |                        ---- in this macro invocation
+
+error[E0425]: cannot find value `n` in this scope
+  --> $DIR/issue-15167.rs:3:25
+   |
+LL | macro_rules! f { () => (n) }
+   |                         ^ not found in this scope
+...
+LL |         println!("{}", f!());
+   |                        ---- in this macro invocation
+
+error[E0425]: cannot find value `n` in this scope
+  --> $DIR/issue-15167.rs:3:25
+   |
+LL | macro_rules! f { () => (n) }
+   |                         ^ not found in this scope
+...
+LL |         println!("{}", f!());
+   |                        ---- in this macro invocation
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/issues/issue-15207.rs b/src/test/ui/issues/issue-15207.rs
new file mode 100644
index 0000000..356e55a
--- /dev/null
+++ b/src/test/ui/issues/issue-15207.rs
@@ -0,0 +1,6 @@
+fn main() {
+    loop {
+        break.push(1) //~ ERROR no method named `push` found for type `!`
+        ;
+    }
+}
diff --git a/src/test/ui/issues/issue-15207.stderr b/src/test/ui/issues/issue-15207.stderr
new file mode 100644
index 0000000..2d90eb8
--- /dev/null
+++ b/src/test/ui/issues/issue-15207.stderr
@@ -0,0 +1,9 @@
+error[E0599]: no method named `push` found for type `!` in the current scope
+  --> $DIR/issue-15207.rs:3:15
+   |
+LL |         break.push(1)
+   |               ^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/issues/issue-15260.rs b/src/test/ui/issues/issue-15260.rs
new file mode 100644
index 0000000..64fc3df3d
--- /dev/null
+++ b/src/test/ui/issues/issue-15260.rs
@@ -0,0 +1,25 @@
+struct Foo {
+    a: usize,
+}
+
+fn main() {
+    let Foo {
+        a: _,
+        a: _
+        //~^ ERROR field `a` bound multiple times in the pattern
+    } = Foo { a: 29 };
+
+    let Foo {
+        a,
+        a: _
+        //~^ ERROR field `a` bound multiple times in the pattern
+    } = Foo { a: 29 };
+
+    let Foo {
+        a,
+        a: _,
+        //~^ ERROR field `a` bound multiple times in the pattern
+        a: x
+        //~^ ERROR field `a` bound multiple times in the pattern
+    } = Foo { a: 29 };
+}
diff --git a/src/test/ui/issues/issue-15260.stderr b/src/test/ui/issues/issue-15260.stderr
new file mode 100644
index 0000000..4a30411
--- /dev/null
+++ b/src/test/ui/issues/issue-15260.stderr
@@ -0,0 +1,36 @@
+error[E0025]: field `a` bound multiple times in the pattern
+  --> $DIR/issue-15260.rs:8:9
+   |
+LL |         a: _,
+   |         ---- first use of `a`
+LL |         a: _
+   |         ^^^^ multiple uses of `a` in pattern
+
+error[E0025]: field `a` bound multiple times in the pattern
+  --> $DIR/issue-15260.rs:14:9
+   |
+LL |         a,
+   |         - first use of `a`
+LL |         a: _
+   |         ^^^^ multiple uses of `a` in pattern
+
+error[E0025]: field `a` bound multiple times in the pattern
+  --> $DIR/issue-15260.rs:20:9
+   |
+LL |         a,
+   |         - first use of `a`
+LL |         a: _,
+   |         ^^^^ multiple uses of `a` in pattern
+
+error[E0025]: field `a` bound multiple times in the pattern
+  --> $DIR/issue-15260.rs:22:9
+   |
+LL |         a,
+   |         - first use of `a`
+...
+LL |         a: x
+   |         ^^^^ multiple uses of `a` in pattern
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0025`.
diff --git a/src/test/ui/issues/issue-15261.rs b/src/test/ui/issues/issue-15261.rs
new file mode 100644
index 0000000..4119cb0
--- /dev/null
+++ b/src/test/ui/issues/issue-15261.rs
@@ -0,0 +1,11 @@
+// compile-pass
+#![allow(dead_code)]
+#![allow(non_upper_case_globals)]
+
+// pretty-expanded FIXME #23616
+
+static mut n_mut: usize = 0;
+
+static n: &'static usize = unsafe{ &n_mut };
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-15381.rs b/src/test/ui/issues/issue-15381.rs
new file mode 100644
index 0000000..e58c866
--- /dev/null
+++ b/src/test/ui/issues/issue-15381.rs
@@ -0,0 +1,8 @@
+fn main() {
+    let values: Vec<u8> = vec![1,2,3,4,5,6,7,8];
+
+    for &[x,y,z] in values.chunks(3).filter(|&xs| xs.len() == 3) {
+        //~^ ERROR refutable pattern in `for` loop binding: `&[]` not covered
+        println!("y={}", y);
+    }
+}
diff --git a/src/test/ui/issues/issue-15381.stderr b/src/test/ui/issues/issue-15381.stderr
new file mode 100644
index 0000000..8152737
--- /dev/null
+++ b/src/test/ui/issues/issue-15381.stderr
@@ -0,0 +1,9 @@
+error[E0005]: refutable pattern in `for` loop binding: `&[]` not covered
+  --> $DIR/issue-15381.rs:4:9
+   |
+LL |     for &[x,y,z] in values.chunks(3).filter(|&xs| xs.len() == 3) {
+   |         ^^^^^^^^ pattern `&[]` not covered
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0005`.
diff --git a/src/test/ui/issues/issue-15524.rs b/src/test/ui/issues/issue-15524.rs
new file mode 100644
index 0000000..eb7ec41
--- /dev/null
+++ b/src/test/ui/issues/issue-15524.rs
@@ -0,0 +1,16 @@
+const N: isize = 1;
+
+enum Foo {
+    A = 1,
+    B = 1,
+    //~^ ERROR discriminant value `1` already exists
+    C = 0,
+    D,
+    //~^ ERROR discriminant value `1` already exists
+
+    E = N,
+    //~^ ERROR discriminant value `1` already exists
+
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-15524.stderr b/src/test/ui/issues/issue-15524.stderr
new file mode 100644
index 0000000..1702dad
--- /dev/null
+++ b/src/test/ui/issues/issue-15524.stderr
@@ -0,0 +1,29 @@
+error[E0081]: discriminant value `1` already exists
+  --> $DIR/issue-15524.rs:5:9
+   |
+LL |     A = 1,
+   |         - first use of `1`
+LL |     B = 1,
+   |         ^ enum already has `1`
+
+error[E0081]: discriminant value `1` already exists
+  --> $DIR/issue-15524.rs:8:5
+   |
+LL |     A = 1,
+   |         - first use of `1`
+...
+LL |     D,
+   |     ^ enum already has `1`
+
+error[E0081]: discriminant value `1` already exists
+  --> $DIR/issue-15524.rs:11:9
+   |
+LL |     A = 1,
+   |         - first use of `1`
+...
+LL |     E = N,
+   |         ^ enum already has `1`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0081`.
diff --git a/src/test/ui/issues/issue-15689-2.rs b/src/test/ui/issues/issue-15689-2.rs
new file mode 100644
index 0000000..4a13261
--- /dev/null
+++ b/src/test/ui/issues/issue-15689-2.rs
@@ -0,0 +1,10 @@
+// compile-pass
+#![allow(dead_code)]
+// pretty-expanded FIXME #23616
+
+#[derive(Clone)]
+enum Test<'a> {
+    Slice(&'a isize)
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-15735.rs b/src/test/ui/issues/issue-15735.rs
new file mode 100644
index 0000000..20634cc
--- /dev/null
+++ b/src/test/ui/issues/issue-15735.rs
@@ -0,0 +1,17 @@
+// compile-pass
+#![allow(dead_code)]
+struct A<'a> {
+    a: &'a i32,
+    b: &'a i32,
+}
+
+impl <'a> A<'a> {
+    fn foo<'b>(&'b self) {
+        A {
+            a: self.a,
+            b: self.b,
+        };
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/issues/issue-15756.rs b/src/test/ui/issues/issue-15756.rs
new file mode 100644
index 0000000..e0861de
--- /dev/null
+++ b/src/test/ui/issues/issue-15756.rs
@@ -0,0 +1,14 @@
+use std::slice::Chunks;
+use std::slice::ChunksMut;
+
+fn dft_iter<'a, T>(arg1: Chunks<'a,T>, arg2: ChunksMut<'a,T>)
+{
+    for
+    &mut something
+    //~^ ERROR the size for values of type
+    in arg2
+    {
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-15756.stderr b/src/test/ui/issues/issue-15756.stderr
new file mode 100644
index 0000000..987bc51
--- /dev/null
+++ b/src/test/ui/issues/issue-15756.stderr
@@ -0,0 +1,14 @@
+error[E0277]: the size for values of type `[T]` cannot be known at compilation time
+  --> $DIR/issue-15756.rs:7:10
+   |
+LL |     &mut something
+   |          ^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `[T]`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: all local variables must have a statically known size
+   = help: unsized locals are gated as an unstable feature
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-15783.rs b/src/test/ui/issues/issue-15783.rs
new file mode 100644
index 0000000..77eae91
--- /dev/null
+++ b/src/test/ui/issues/issue-15783.rs
@@ -0,0 +1,14 @@
+pub fn foo(params: Option<&[&str]>) -> usize {
+    params.unwrap().first().unwrap().len()
+}
+
+fn main() {
+    let name = "Foo";
+    let x = Some(&[name]);
+    let msg = foo(x);
+//~^ ERROR mismatched types
+//~| expected type `std::option::Option<&[&str]>`
+//~| found type `std::option::Option<&[&str; 1]>`
+//~| expected slice, found array of 1 elements
+    assert_eq!(msg, 3);
+}
diff --git a/src/test/ui/issues/issue-15783.stderr b/src/test/ui/issues/issue-15783.stderr
new file mode 100644
index 0000000..595fe40
--- /dev/null
+++ b/src/test/ui/issues/issue-15783.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-15783.rs:8:19
+   |
+LL |     let msg = foo(x);
+   |                   ^ expected slice, found array of 1 elements
+   |
+   = note: expected type `std::option::Option<&[&str]>`
+              found type `std::option::Option<&[&str; 1]>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-15896.rs b/src/test/ui/issues/issue-15896.rs
new file mode 100644
index 0000000..3054af7
--- /dev/null
+++ b/src/test/ui/issues/issue-15896.rs
@@ -0,0 +1,18 @@
+// Regression test for #15896. It used to ICE rustc.
+
+fn main() {
+    enum R { REB(()) }
+    struct Tau { t: usize }
+    enum E { B(R, Tau) }
+
+    let e = E::B(R::REB(()), Tau { t: 3 });
+    let u = match e {
+        E::B(
+          Tau{t: x},
+          //~^ ERROR mismatched types
+          //~| expected type `main::R`
+          //~| found type `main::Tau`
+          //~| expected enum `main::R`, found struct `main::Tau`
+          _) => x,
+    };
+}
diff --git a/src/test/ui/issues/issue-15896.stderr b/src/test/ui/issues/issue-15896.stderr
new file mode 100644
index 0000000..de9757d
--- /dev/null
+++ b/src/test/ui/issues/issue-15896.stderr
@@ -0,0 +1,15 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-15896.rs:11:11
+   |
+LL |     let u = match e {
+   |                   - this match expression has type `main::R`
+LL |         E::B(
+LL |           Tau{t: x},
+   |           ^^^^^^^^^ expected enum `main::R`, found struct `main::Tau`
+   |
+   = note: expected type `main::R`
+              found type `main::Tau`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-15919.rs b/src/test/ui/issues/issue-15919.rs
new file mode 100644
index 0000000..19ecf2f
--- /dev/null
+++ b/src/test/ui/issues/issue-15919.rs
@@ -0,0 +1,12 @@
+// error-pattern: too big for the current architecture
+// normalize-stderr-test "\[usize; \d+\]" -> "[usize; N]"
+
+#[cfg(target_pointer_width = "32")]
+fn main() {
+    let x = [0usize; 0xffff_ffff];
+}
+
+#[cfg(target_pointer_width = "64")]
+fn main() {
+    let x = [0usize; 0xffff_ffff_ffff_ffff];
+}
diff --git a/src/test/ui/issues/issue-15919.stderr b/src/test/ui/issues/issue-15919.stderr
new file mode 100644
index 0000000..e4e88cc
--- /dev/null
+++ b/src/test/ui/issues/issue-15919.stderr
@@ -0,0 +1,4 @@
+error: the type `[usize; N]` is too big for the current architecture
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-15965.rs b/src/test/ui/issues/issue-15965.rs
new file mode 100644
index 0000000..eef4900
--- /dev/null
+++ b/src/test/ui/issues/issue-15965.rs
@@ -0,0 +1,7 @@
+fn main() {
+    return
+        { return () }
+//~^ ERROR type annotations needed [E0282]
+    ()
+    ;
+}
diff --git a/src/test/ui/issues/issue-15965.stderr b/src/test/ui/issues/issue-15965.stderr
new file mode 100644
index 0000000..90377c1
--- /dev/null
+++ b/src/test/ui/issues/issue-15965.stderr
@@ -0,0 +1,13 @@
+error[E0282]: type annotations needed
+  --> $DIR/issue-15965.rs:3:9
+   |
+LL | /         { return () }
+LL | |
+LL | |     ()
+   | |______^ cannot infer type
+   |
+   = note: type must be known at this point
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/issues/issue-16048.rs b/src/test/ui/issues/issue-16048.rs
new file mode 100644
index 0000000..5910481
--- /dev/null
+++ b/src/test/ui/issues/issue-16048.rs
@@ -0,0 +1,28 @@
+trait NoLifetime {
+    fn get<'p, T : Test<'p>>(&self) -> T;
+    //~^ NOTE lifetimes in impl do not match this method in trait
+}
+
+trait Test<'p> {
+    fn new(buf: &'p mut [u8]) -> Self;
+}
+
+struct Foo<'a> {
+    buf: &'a mut [u8],
+}
+
+impl<'a> Test<'a> for Foo<'a> {
+    fn new(buf: &'a mut [u8]) -> Foo<'a> {
+        Foo { buf: buf }
+    }
+}
+
+impl<'a> NoLifetime for Foo<'a> {
+    fn get<'p, T : Test<'a>>(&self) -> T {
+    //~^ ERROR E0195
+    //~| NOTE lifetimes do not match method in trait
+        return *self as T;
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-16048.stderr b/src/test/ui/issues/issue-16048.stderr
new file mode 100644
index 0000000..18e59bd
--- /dev/null
+++ b/src/test/ui/issues/issue-16048.stderr
@@ -0,0 +1,12 @@
+error[E0195]: lifetime parameters or bounds on method `get` do not match the trait declaration
+  --> $DIR/issue-16048.rs:21:11
+   |
+LL |     fn get<'p, T : Test<'p>>(&self) -> T;
+   |           ------------------ lifetimes in impl do not match this method in trait
+...
+LL |     fn get<'p, T : Test<'a>>(&self) -> T {
+   |           ^^^^^^^^^^^^^^^^^^ lifetimes do not match method in trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0195`.
diff --git a/src/test/ui/issues/issue-16098.rs b/src/test/ui/issues/issue-16098.rs
new file mode 100644
index 0000000..a1131f8
--- /dev/null
+++ b/src/test/ui/issues/issue-16098.rs
@@ -0,0 +1,16 @@
+macro_rules! prob1 {
+    (0) => {
+        0
+    };
+    ($n:expr) => {
+        if ($n % 3 == 0) || ($n % 5 == 0) {
+            $n + prob1!($n - 1); //~ ERROR recursion limit reached while expanding the macro `prob1`
+        } else {
+            prob1!($n - 1);
+        }
+    };
+}
+
+fn main() {
+    println!("Problem 1: {}", prob1!(1000));
+}
diff --git a/src/test/ui/issues/issue-16098.stderr b/src/test/ui/issues/issue-16098.stderr
new file mode 100644
index 0000000..cdab76c
--- /dev/null
+++ b/src/test/ui/issues/issue-16098.stderr
@@ -0,0 +1,13 @@
+error: recursion limit reached while expanding the macro `prob1`
+  --> $DIR/issue-16098.rs:7:18
+   |
+LL |             $n + prob1!($n - 1);
+   |                  ^^^^^^^^^^^^^^
+...
+LL |     println!("Problem 1: {}", prob1!(1000));
+   |                               ------------ in this macro invocation
+   |
+   = help: consider adding a `#![recursion_limit="128"]` attribute to your crate
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-16149.rs b/src/test/ui/issues/issue-16149.rs
new file mode 100644
index 0000000..7f0cad9
--- /dev/null
+++ b/src/test/ui/issues/issue-16149.rs
@@ -0,0 +1,11 @@
+extern {
+    static externalValue: isize;
+}
+
+fn main() {
+    let boolValue = match 42 {
+        externalValue => true,
+        //~^ ERROR match bindings cannot shadow statics
+        _ => false
+    };
+}
diff --git a/src/test/ui/issues/issue-16149.stderr b/src/test/ui/issues/issue-16149.stderr
new file mode 100644
index 0000000..bb80984
--- /dev/null
+++ b/src/test/ui/issues/issue-16149.stderr
@@ -0,0 +1,12 @@
+error[E0530]: match bindings cannot shadow statics
+  --> $DIR/issue-16149.rs:7:9
+   |
+LL |     static externalValue: isize;
+   |     ---------------------------- the static `externalValue` is defined here
+...
+LL |         externalValue => true,
+   |         ^^^^^^^^^^^^^ cannot be named the same as a static
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0530`.
diff --git a/src/test/ui/issues/issue-16250.rs b/src/test/ui/issues/issue-16250.rs
new file mode 100644
index 0000000..bf01627
--- /dev/null
+++ b/src/test/ui/issues/issue-16250.rs
@@ -0,0 +1,10 @@
+#![deny(warnings)]
+
+pub struct Foo;
+
+extern {
+    pub fn foo(x: (Foo)); //~ ERROR unspecified layout
+}
+
+fn main() {
+}
diff --git a/src/test/ui/issues/issue-16250.stderr b/src/test/ui/issues/issue-16250.stderr
new file mode 100644
index 0000000..a8ff254
--- /dev/null
+++ b/src/test/ui/issues/issue-16250.stderr
@@ -0,0 +1,21 @@
+error: `extern` block uses type `Foo` which is not FFI-safe: this struct has unspecified layout
+  --> $DIR/issue-16250.rs:6:20
+   |
+LL |     pub fn foo(x: (Foo));
+   |                    ^^^
+   |
+note: lint level defined here
+  --> $DIR/issue-16250.rs:1:9
+   |
+LL | #![deny(warnings)]
+   |         ^^^^^^^^
+   = note: #[deny(improper_ctypes)] implied by #[deny(warnings)]
+   = help: consider adding a #[repr(C)] or #[repr(transparent)] attribute to this struct
+note: type defined here
+  --> $DIR/issue-16250.rs:3:1
+   |
+LL | pub struct Foo;
+   | ^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-16338.rs b/src/test/ui/issues/issue-16338.rs
new file mode 100644
index 0000000..7567740
--- /dev/null
+++ b/src/test/ui/issues/issue-16338.rs
@@ -0,0 +1,10 @@
+struct Slice<T> {
+    data: *const T,
+    len: usize,
+}
+
+fn main() {
+    let Slice { data: data, len: len } = "foo";
+    //~^ ERROR mismatched types
+    //~| found type `Slice<_>`
+}
diff --git a/src/test/ui/issues/issue-16338.stderr b/src/test/ui/issues/issue-16338.stderr
new file mode 100644
index 0000000..af8c39d
--- /dev/null
+++ b/src/test/ui/issues/issue-16338.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-16338.rs:7:9
+   |
+LL |     let Slice { data: data, len: len } = "foo";
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected str, found struct `Slice`
+   |
+   = note: expected type `str`
+              found type `Slice<_>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-16401.rs b/src/test/ui/issues/issue-16401.rs
new file mode 100644
index 0000000..7135b7d
--- /dev/null
+++ b/src/test/ui/issues/issue-16401.rs
@@ -0,0 +1,15 @@
+struct Slice<T> {
+    data: *const T,
+    len: usize,
+}
+
+fn main() {
+    match () {
+        Slice { data: data, len: len } => (),
+        //~^ ERROR mismatched types
+        //~| expected type `()`
+        //~| found type `Slice<_>`
+        //~| expected (), found struct `Slice`
+        _ => unreachable!()
+    }
+}
diff --git a/src/test/ui/issues/issue-16401.stderr b/src/test/ui/issues/issue-16401.stderr
new file mode 100644
index 0000000..1779d0b
--- /dev/null
+++ b/src/test/ui/issues/issue-16401.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-16401.rs:8:9
+   |
+LL |     match () {
+   |           -- this match expression has type `()`
+LL |         Slice { data: data, len: len } => (),
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found struct `Slice`
+   |
+   = note: expected type `()`
+              found type `Slice<_>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-16538.rs b/src/test/ui/issues/issue-16538.rs
new file mode 100644
index 0000000..a990c07
--- /dev/null
+++ b/src/test/ui/issues/issue-16538.rs
@@ -0,0 +1,17 @@
+#![allow(safe_extern_statics)]
+
+mod Y {
+    pub type X = usize;
+    extern {
+        pub static x: *const usize;
+    }
+    pub fn foo(value: *const X) -> *const X {
+        value
+    }
+}
+
+static foo: *const Y::X = Y::foo(Y::x as *const Y::X);
+//~^ ERROR `*const usize` cannot be shared between threads safely [E0277]
+//~| ERROR E0015
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-16538.stderr b/src/test/ui/issues/issue-16538.stderr
new file mode 100644
index 0000000..78c7d31
--- /dev/null
+++ b/src/test/ui/issues/issue-16538.stderr
@@ -0,0 +1,19 @@
+error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
+  --> $DIR/issue-16538.rs:13:27
+   |
+LL | static foo: *const Y::X = Y::foo(Y::x as *const Y::X);
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: `*const usize` cannot be shared between threads safely
+  --> $DIR/issue-16538.rs:13:1
+   |
+LL | static foo: *const Y::X = Y::foo(Y::x as *const Y::X);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const usize` cannot be shared between threads safely
+   |
+   = help: the trait `std::marker::Sync` is not implemented for `*const usize`
+   = note: shared static variables must have a type that implements `Sync`
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0015, E0277.
+For more information about an error, try `rustc --explain E0015`.
diff --git a/src/test/ui/issues/issue-16562.rs b/src/test/ui/issues/issue-16562.rs
new file mode 100644
index 0000000..e16a351
--- /dev/null
+++ b/src/test/ui/issues/issue-16562.rs
@@ -0,0 +1,17 @@
+trait MatrixShape {}
+
+struct Col<D, C> {
+    data: D,
+    col: C,
+}
+
+trait Collection { fn len(&self) -> usize; }
+
+impl<T, M: MatrixShape> Collection for Col<M, usize> {
+//~^ ERROR type parameter `T` is not constrained
+    fn len(&self) -> usize {
+        unimplemented!()
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-16562.stderr b/src/test/ui/issues/issue-16562.stderr
new file mode 100644
index 0000000..3fe7507
--- /dev/null
+++ b/src/test/ui/issues/issue-16562.stderr
@@ -0,0 +1,9 @@
+error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates
+  --> $DIR/issue-16562.rs:10:6
+   |
+LL | impl<T, M: MatrixShape> Collection for Col<M, usize> {
+   |      ^ unconstrained type parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0207`.
diff --git a/src/test/ui/issues/issue-16596.rs b/src/test/ui/issues/issue-16596.rs
new file mode 100644
index 0000000..3aa6c20
--- /dev/null
+++ b/src/test/ui/issues/issue-16596.rs
@@ -0,0 +1,22 @@
+// compile-pass
+#![allow(dead_code)]
+
+trait MatrixRow { fn dummy(&self) { }}
+
+struct Mat;
+
+impl<'a> MatrixRow for &'a Mat {}
+
+struct Rows<M: MatrixRow> {
+    mat: M,
+}
+
+impl<'a> Iterator for Rows<&'a Mat> {
+    type Item = ();
+
+    fn next(&mut self) -> Option<()> {
+        unimplemented!()
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-16668.rs b/src/test/ui/issues/issue-16668.rs
new file mode 100644
index 0000000..f69ca46
--- /dev/null
+++ b/src/test/ui/issues/issue-16668.rs
@@ -0,0 +1,20 @@
+// compile-pass
+#![allow(dead_code)]
+struct Parser<'a, I, O> {
+    parse: Box<FnMut(I) -> Result<O, String> + 'a>
+}
+
+impl<'a, I: 'a, O: 'a> Parser<'a, I, O> {
+    fn compose<K: 'a>(mut self, mut rhs: Parser<'a, O, K>) -> Parser<'a, I, K> {
+        Parser {
+            parse: Box::new(move |x: I| {
+                match (self.parse)(x) {
+                    Ok(r) => (rhs.parse)(r),
+                    Err(e) => Err(e)
+                }
+            })
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-16683.rs b/src/test/ui/issues/issue-16683.rs
new file mode 100644
index 0000000..bbbd4da
--- /dev/null
+++ b/src/test/ui/issues/issue-16683.rs
@@ -0,0 +1,8 @@
+trait T<'a> {
+    fn a(&'a self) -> &'a bool;
+    fn b(&self) {
+        self.a(); //~ ERROR cannot infer
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-16683.stderr b/src/test/ui/issues/issue-16683.stderr
new file mode 100644
index 0000000..a047893
--- /dev/null
+++ b/src/test/ui/issues/issue-16683.stderr
@@ -0,0 +1,30 @@
+error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
+  --> $DIR/issue-16683.rs:4:14
+   |
+LL |         self.a();
+   |              ^
+   |
+note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 3:5...
+  --> $DIR/issue-16683.rs:3:5
+   |
+LL | /     fn b(&self) {
+LL | |         self.a();
+LL | |     }
+   | |_____^
+note: ...so that reference does not outlive borrowed content
+  --> $DIR/issue-16683.rs:4:9
+   |
+LL |         self.a();
+   |         ^^^^
+note: but, the lifetime must be valid for the lifetime 'a as defined on the trait at 1:9...
+  --> $DIR/issue-16683.rs:1:9
+   |
+LL | trait T<'a> {
+   |         ^^
+   = note: ...so that the types are compatible:
+           expected &'a Self
+              found &Self
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0495`.
diff --git a/src/test/ui/issues/issue-16725.rs b/src/test/ui/issues/issue-16725.rs
new file mode 100644
index 0000000..2cf8a60
--- /dev/null
+++ b/src/test/ui/issues/issue-16725.rs
@@ -0,0 +1,8 @@
+// aux-build:issue-16725.rs
+
+extern crate issue_16725 as foo;
+
+fn main() {
+    unsafe { foo::bar(); }
+    //~^ ERROR: function `bar` is private
+}
diff --git a/src/test/ui/issues/issue-16725.stderr b/src/test/ui/issues/issue-16725.stderr
new file mode 100644
index 0000000..562ad94
--- /dev/null
+++ b/src/test/ui/issues/issue-16725.stderr
@@ -0,0 +1,9 @@
+error[E0603]: function `bar` is private
+  --> $DIR/issue-16725.rs:6:19
+   |
+LL |     unsafe { foo::bar(); }
+   |                   ^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0603`.
diff --git a/src/test/ui/issues/issue-16922.rs b/src/test/ui/issues/issue-16922.rs
new file mode 100644
index 0000000..1e86551
--- /dev/null
+++ b/src/test/ui/issues/issue-16922.rs
@@ -0,0 +1,10 @@
+use std::any::Any;
+
+fn foo<T: Any>(value: &T) -> Box<Any> {
+    Box::new(value) as Box<Any>
+    //~^ ERROR explicit lifetime required in the type of `value` [E0621]
+}
+
+fn main() {
+    let _ = foo(&5);
+}
diff --git a/src/test/ui/issues/issue-16922.stderr b/src/test/ui/issues/issue-16922.stderr
new file mode 100644
index 0000000..1f3b3fe
--- /dev/null
+++ b/src/test/ui/issues/issue-16922.stderr
@@ -0,0 +1,11 @@
+error[E0621]: explicit lifetime required in the type of `value`
+  --> $DIR/issue-16922.rs:4:5
+   |
+LL | fn foo<T: Any>(value: &T) -> Box<Any> {
+   |                       -- help: add explicit lifetime `'static` to the type of `value`: `&'static T`
+LL |     Box::new(value) as Box<Any>
+   |     ^^^^^^^^^^^^^^^ lifetime `'static` required
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/issues/issue-16939.rs b/src/test/ui/issues/issue-16939.rs
new file mode 100644
index 0000000..ad72483
--- /dev/null
+++ b/src/test/ui/issues/issue-16939.rs
@@ -0,0 +1,8 @@
+// Make sure we don't ICE when making an overloaded call with the
+// wrong arity.
+
+fn _foo<F: Fn()> (f: F) {
+    |t| f(t); //~ ERROR E0057
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-16939.stderr b/src/test/ui/issues/issue-16939.stderr
new file mode 100644
index 0000000..5df2119
--- /dev/null
+++ b/src/test/ui/issues/issue-16939.stderr
@@ -0,0 +1,9 @@
+error[E0057]: this function takes 0 parameters but 1 parameter was supplied
+  --> $DIR/issue-16939.rs:5:9
+   |
+LL |     |t| f(t);
+   |         ^^^^ expected 0 parameters
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0057`.
diff --git a/src/test/ui/issues/issue-16966.rs b/src/test/ui/issues/issue-16966.rs
new file mode 100644
index 0000000..9c61883
--- /dev/null
+++ b/src/test/ui/issues/issue-16966.rs
@@ -0,0 +1,4 @@
+fn main() {
+    panic!(std::default::Default::default());
+    //~^ ERROR type annotations needed
+}
diff --git a/src/test/ui/issues/issue-16966.stderr b/src/test/ui/issues/issue-16966.stderr
new file mode 100644
index 0000000..13e77fe
--- /dev/null
+++ b/src/test/ui/issues/issue-16966.stderr
@@ -0,0 +1,11 @@
+error[E0282]: type annotations needed
+  --> $DIR/issue-16966.rs:2:5
+   |
+LL |     panic!(std::default::Default::default());
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for `M`
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/issues/issue-1697.rs b/src/test/ui/issues/issue-1697.rs
new file mode 100644
index 0000000..30b2558
--- /dev/null
+++ b/src/test/ui/issues/issue-1697.rs
@@ -0,0 +1,6 @@
+// Testing that we don't fail abnormally after hitting the errors
+
+use unresolved::*; //~ ERROR unresolved import `unresolved` [E0432]
+                   //~^ maybe a missing `extern crate unresolved;`?
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-1697.stderr b/src/test/ui/issues/issue-1697.stderr
new file mode 100644
index 0000000..6ae5bd1
--- /dev/null
+++ b/src/test/ui/issues/issue-1697.stderr
@@ -0,0 +1,9 @@
+error[E0432]: unresolved import `unresolved`
+  --> $DIR/issue-1697.rs:3:5
+   |
+LL | use unresolved::*;
+   |     ^^^^^^^^^^ maybe a missing `extern crate unresolved;`?
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/issues/issue-16994.rs b/src/test/ui/issues/issue-16994.rs
new file mode 100644
index 0000000..d356ce8
--- /dev/null
+++ b/src/test/ui/issues/issue-16994.rs
@@ -0,0 +1,10 @@
+// compile-pass
+// skip-codegen
+fn cb<'a,T>(_x: Box<Fn((&'a i32, &'a (Vec<&'static i32>, bool))) -> T>) -> T {
+    panic!()
+}
+
+
+fn main() {
+    cb(Box::new(|(k, &(ref v, b))| (*k, v.clone(), b)));
+}
diff --git a/src/test/ui/issues/issue-17001.rs b/src/test/ui/issues/issue-17001.rs
new file mode 100644
index 0000000..68cb286
--- /dev/null
+++ b/src/test/ui/issues/issue-17001.rs
@@ -0,0 +1,5 @@
+mod foo {}
+
+fn main() {
+    let p = foo { x: () }; //~ ERROR expected struct, variant or union type, found module `foo`
+}
diff --git a/src/test/ui/issues/issue-17001.stderr b/src/test/ui/issues/issue-17001.stderr
new file mode 100644
index 0000000..d7e6069
--- /dev/null
+++ b/src/test/ui/issues/issue-17001.stderr
@@ -0,0 +1,9 @@
+error[E0574]: expected struct, variant or union type, found module `foo`
+  --> $DIR/issue-17001.rs:4:13
+   |
+LL |     let p = foo { x: () };
+   |             ^^^ not a struct, variant or union type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0574`.
diff --git a/src/test/ui/issues/issue-17025.rs b/src/test/ui/issues/issue-17025.rs
new file mode 100644
index 0000000..6b7b6d0
--- /dev/null
+++ b/src/test/ui/issues/issue-17025.rs
@@ -0,0 +1,13 @@
+// ignore-test the unsized enum no longer compiles
+
+enum A {
+    B(char),
+    C([Box<A>]),
+}
+
+fn c(c:char) {
+    A::B(c);
+    //~^ ERROR cannot move a value of type A: the size of A cannot be statically determined
+}
+
+pub fn main() {}
diff --git a/src/test/ui/issues/issue-17033.rs b/src/test/ui/issues/issue-17033.rs
new file mode 100644
index 0000000..d39b568
--- /dev/null
+++ b/src/test/ui/issues/issue-17033.rs
@@ -0,0 +1,8 @@
+fn f<'r>(p: &'r mut fn(p: &mut ())) {
+    (*p)(()) //~  ERROR mismatched types
+             //~| expected type `&mut ()`
+             //~| found type `()`
+             //~| expected &mut (), found ()
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-17033.stderr b/src/test/ui/issues/issue-17033.stderr
new file mode 100644
index 0000000..ba78aa2
--- /dev/null
+++ b/src/test/ui/issues/issue-17033.stderr
@@ -0,0 +1,15 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-17033.rs:2:10
+   |
+LL |     (*p)(())
+   |          ^^
+   |          |
+   |          expected &mut (), found ()
+   |          help: consider mutably borrowing here: `&mut ()`
+   |
+   = note: expected type `&mut ()`
+              found type `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-17121.rs b/src/test/ui/issues/issue-17121.rs
new file mode 100644
index 0000000..706350f
--- /dev/null
+++ b/src/test/ui/issues/issue-17121.rs
@@ -0,0 +1,32 @@
+// compile-pass
+#![allow(dead_code)]
+// pretty-expanded FIXME #23616
+// ignore-cloudabi no std::fs
+
+use std::fs::File;
+use std::io::{self, BufReader, Read};
+
+struct Lexer<R: Read>
+{
+    reader: BufReader<R>,
+}
+
+impl<R: Read> Lexer<R>
+{
+    pub fn new_from_reader(r: R) -> Lexer<R>
+    {
+        Lexer{reader: BufReader::new(r)}
+    }
+
+    pub fn new_from_file(p: &str) -> io::Result<Lexer<File>>
+    {
+        Ok(Lexer::new_from_reader(File::open(p)?))
+    }
+
+    pub fn new_from_str<'a>(s: &'a str) -> Lexer<&'a [u8]>
+    {
+        Lexer::new_from_reader(s.as_bytes())
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-17252.rs b/src/test/ui/issues/issue-17252.rs
new file mode 100644
index 0000000..7141e48
--- /dev/null
+++ b/src/test/ui/issues/issue-17252.rs
@@ -0,0 +1,10 @@
+const FOO: usize = FOO; //~ ERROR E0391
+
+fn main() {
+    let _x: [u8; FOO]; // caused stack overflow prior to fix
+    let _y: usize = 1 + {
+        const BAR: usize = BAR;
+        let _z: [u8; BAR]; // caused stack overflow prior to fix
+        1
+    };
+}
diff --git a/src/test/ui/issues/issue-17252.stderr b/src/test/ui/issues/issue-17252.stderr
new file mode 100644
index 0000000..da3e2e7
--- /dev/null
+++ b/src/test/ui/issues/issue-17252.stderr
@@ -0,0 +1,16 @@
+error[E0391]: cycle detected when processing `FOO`
+  --> $DIR/issue-17252.rs:1:20
+   |
+LL | const FOO: usize = FOO;
+   |                    ^^^
+   |
+   = note: ...which again requires processing `FOO`, completing the cycle
+note: cycle used when processing `main::{{constant}}#0`
+  --> $DIR/issue-17252.rs:4:18
+   |
+LL |     let _x: [u8; FOO]; // caused stack overflow prior to fix
+   |                  ^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/issues/issue-17263.ast.stderr b/src/test/ui/issues/issue-17263.ast.stderr
new file mode 100644
index 0000000..823f2c7
--- /dev/null
+++ b/src/test/ui/issues/issue-17263.ast.stderr
@@ -0,0 +1,26 @@
+error[E0499]: cannot borrow `x` (via `x.b`) as mutable more than once at a time
+  --> $DIR/issue-17263.rs:17:34
+   |
+LL |     let (a, b) = (&mut x.a, &mut x.b);
+   |                        ---       ^^^ second mutable borrow occurs here (via `x.b`)
+   |                        |
+   |                        first mutable borrow occurs here (via `x.a`)
+...
+LL | }
+   | - first borrow ends here
+
+error[E0502]: cannot borrow `foo` (via `foo.b`) as immutable because `foo` is also borrowed as mutable (via `foo.a`)
+  --> $DIR/issue-17263.rs:21:32
+   |
+LL |     let (c, d) = (&mut foo.a, &foo.b);
+   |                        -----   ^^^^^ immutable borrow of `foo.b` -- which overlaps with `foo.a` -- occurs here
+   |                        |
+   |                        mutable borrow occurs here (via `foo.a`)
+...
+LL | }
+   | - mutable borrow ends here
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0499, E0502.
+For more information about an error, try `rustc --explain E0499`.
diff --git a/src/test/ui/issues/issue-17263.nll.stderr b/src/test/ui/issues/issue-17263.nll.stderr
new file mode 100644
index 0000000..5604037
--- /dev/null
+++ b/src/test/ui/issues/issue-17263.nll.stderr
@@ -0,0 +1,14 @@
+error: compilation successful
+  --> $DIR/issue-17263.rs:15:1
+   |
+LL | / fn main() {
+LL | |     let mut x: Box<_> = box Foo { a: 1, b: 2 };
+LL | |     let (a, b) = (&mut x.a, &mut x.b);
+LL | |
+...  |
+LL | |     use_mut(a);
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-17263.rs b/src/test/ui/issues/issue-17263.rs
new file mode 100644
index 0000000..754f3b9
--- /dev/null
+++ b/src/test/ui/issues/issue-17263.rs
@@ -0,0 +1,35 @@
+// This checks diagnostic quality for cases where AST-borrowck treated
+// `Box<T>` as other types (see rust-lang/rfcs#130). NLL again treats
+// `Box<T>` specially. We capture the differences via revisions.
+
+// revisions: ast nll
+//[ast]compile-flags: -Z borrowck=ast
+//[nll]compile-flags: -Z borrowck=migrate -Z two-phase-borrows
+
+// don't worry about the --compare-mode=nll on this test.
+// ignore-compare-mode-nll
+#![feature(box_syntax, rustc_attrs)]
+
+struct Foo { a: isize, b: isize }
+#[rustc_error] // rust-lang/rust#49855
+fn main() { //[nll]~ ERROR compilation successful
+    let mut x: Box<_> = box Foo { a: 1, b: 2 };
+    let (a, b) = (&mut x.a, &mut x.b);
+    //[ast]~^ ERROR cannot borrow `x` (via `x.b`) as mutable more than once at a time
+
+    let mut foo: Box<_> = box Foo { a: 1, b: 2 };
+    let (c, d) = (&mut foo.a, &foo.b);
+    //[ast]~^ ERROR cannot borrow `foo` (via `foo.b`) as immutable
+
+    // We explicitly use the references created above to illustrate
+    // that NLL is accepting this code *not* because of artificially
+    // short lifetimes, but rather because it understands that all the
+    // references are of disjoint parts of memory.
+    use_imm(d);
+    use_mut(c);
+    use_mut(b);
+    use_mut(a);
+}
+
+fn use_mut<T>(_: &mut T) { }
+fn use_imm<T>(_: &T) { }
diff --git a/src/test/ui/issues/issue-17336.rs b/src/test/ui/issues/issue-17336.rs
new file mode 100644
index 0000000..e2c0e8b
--- /dev/null
+++ b/src/test/ui/issues/issue-17336.rs
@@ -0,0 +1,9 @@
+// compile-pass
+#![allow(unused_must_use)]
+#[allow(dead_code)]
+fn check(a: &str) {
+    let x = a as *const str;
+    x == x;
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-17337.rs b/src/test/ui/issues/issue-17337.rs
new file mode 100644
index 0000000..1126ab7
--- /dev/null
+++ b/src/test/ui/issues/issue-17337.rs
@@ -0,0 +1,17 @@
+#![feature(staged_api)]
+#![deny(deprecated)]
+
+#![unstable(feature = "unstable_test_feature", issue = "0")]
+
+struct Foo;
+
+impl Foo {
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    fn foo(self) {}
+}
+
+fn main() {
+    Foo
+    .foo(); //~ ERROR use of deprecated item
+}
diff --git a/src/test/ui/issues/issue-17337.stderr b/src/test/ui/issues/issue-17337.stderr
new file mode 100644
index 0000000..8973afb
--- /dev/null
+++ b/src/test/ui/issues/issue-17337.stderr
@@ -0,0 +1,14 @@
+error: use of deprecated item 'Foo::foo': text
+  --> $DIR/issue-17337.rs:16:6
+   |
+LL |     .foo();
+   |      ^^^
+   |
+note: lint level defined here
+  --> $DIR/issue-17337.rs:2:9
+   |
+LL | #![deny(deprecated)]
+   |         ^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-17373.rs b/src/test/ui/issues/issue-17373.rs
new file mode 100644
index 0000000..dc3be48
--- /dev/null
+++ b/src/test/ui/issues/issue-17373.rs
@@ -0,0 +1,4 @@
+fn main() {
+    *return //~ ERROR type `!` cannot be dereferenced
+    ;
+}
diff --git a/src/test/ui/issues/issue-17373.stderr b/src/test/ui/issues/issue-17373.stderr
new file mode 100644
index 0000000..5c429d1
--- /dev/null
+++ b/src/test/ui/issues/issue-17373.stderr
@@ -0,0 +1,9 @@
+error[E0614]: type `!` cannot be dereferenced
+  --> $DIR/issue-17373.rs:2:5
+   |
+LL |     *return
+   |     ^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0614`.
diff --git a/src/test/ui/issues/issue-17385.nll.stderr b/src/test/ui/issues/issue-17385.nll.stderr
new file mode 100644
index 0000000..28c2226
--- /dev/null
+++ b/src/test/ui/issues/issue-17385.nll.stderr
@@ -0,0 +1,24 @@
+error[E0382]: use of moved value: `foo`
+  --> $DIR/issue-17385.rs:19:11
+   |
+LL |     let foo = X(1);
+   |         --- move occurs because `foo` has type `X`, which does not implement the `Copy` trait
+LL |     drop(foo);
+   |          --- value moved here
+LL |     match foo {
+LL |         X(1) => (),
+   |           ^ value used here after move
+
+error[E0382]: use of moved value: `e`
+  --> $DIR/issue-17385.rs:25:11
+   |
+LL |     let e = Enum::Variant2;
+   |         - move occurs because `e` has type `Enum`, which does not implement the `Copy` trait
+LL |     drop(e);
+   |          - value moved here
+LL |     match e {
+   |           ^ value used here after move
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/issues/issue-17385.rs b/src/test/ui/issues/issue-17385.rs
new file mode 100644
index 0000000..7400aad
--- /dev/null
+++ b/src/test/ui/issues/issue-17385.rs
@@ -0,0 +1,29 @@
+struct X(isize);
+
+enum Enum {
+    Variant1,
+    Variant2
+}
+
+impl Drop for X {
+    fn drop(&mut self) {}
+}
+impl Drop for Enum {
+    fn drop(&mut self) {}
+}
+
+fn main() {
+    let foo = X(1);
+    drop(foo);
+    match foo { //~ ERROR use of moved value
+        X(1) => (),
+        _ => unreachable!()
+    }
+
+    let e = Enum::Variant2;
+    drop(e);
+    match e { //~ ERROR use of moved value
+        Enum::Variant1 => unreachable!(),
+        Enum::Variant2 => ()
+    }
+}
diff --git a/src/test/ui/issues/issue-17385.stderr b/src/test/ui/issues/issue-17385.stderr
new file mode 100644
index 0000000..ee55d86
--- /dev/null
+++ b/src/test/ui/issues/issue-17385.stderr
@@ -0,0 +1,23 @@
+error[E0382]: use of moved value: `foo`
+  --> $DIR/issue-17385.rs:18:11
+   |
+LL |     drop(foo);
+   |          --- value moved here
+LL |     match foo {
+   |           ^^^ value used here after move
+   |
+   = note: move occurs because `foo` has type `X`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `e`
+  --> $DIR/issue-17385.rs:25:11
+   |
+LL |     drop(e);
+   |          - value moved here
+LL |     match e {
+   |           ^ value used here after move
+   |
+   = note: move occurs because `e` has type `Enum`, which does not implement the `Copy` trait
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/issues/issue-17405.rs b/src/test/ui/issues/issue-17405.rs
new file mode 100644
index 0000000..14781a7
--- /dev/null
+++ b/src/test/ui/issues/issue-17405.rs
@@ -0,0 +1,9 @@
+enum Foo {
+    Bar(isize)
+}
+
+fn main() {
+    match Foo::Bar(1) {
+        Foo { i } => () //~ ERROR expected struct, variant or union type, found enum `Foo`
+    }
+}
diff --git a/src/test/ui/issues/issue-17405.stderr b/src/test/ui/issues/issue-17405.stderr
new file mode 100644
index 0000000..37274e2
--- /dev/null
+++ b/src/test/ui/issues/issue-17405.stderr
@@ -0,0 +1,9 @@
+error[E0574]: expected struct, variant or union type, found enum `Foo`
+  --> $DIR/issue-17405.rs:7:9
+   |
+LL |         Foo { i } => ()
+   |         ^^^ not a struct, variant or union type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0574`.
diff --git a/src/test/ui/issues/issue-17431-1.rs b/src/test/ui/issues/issue-17431-1.rs
new file mode 100644
index 0000000..3b692cc
--- /dev/null
+++ b/src/test/ui/issues/issue-17431-1.rs
@@ -0,0 +1,6 @@
+struct Foo { foo: Option<Option<Foo>> }
+//~^ ERROR recursive type `Foo` has infinite size
+
+impl Foo { fn bar(&self) {} }
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-17431-1.stderr b/src/test/ui/issues/issue-17431-1.stderr
new file mode 100644
index 0000000..eb5a136
--- /dev/null
+++ b/src/test/ui/issues/issue-17431-1.stderr
@@ -0,0 +1,13 @@
+error[E0072]: recursive type `Foo` has infinite size
+  --> $DIR/issue-17431-1.rs:1:1
+   |
+LL | struct Foo { foo: Option<Option<Foo>> }
+   | ^^^^^^^^^^   ------------------------ recursive without indirection
+   | |
+   | recursive type has infinite size
+   |
+   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Foo` representable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0072`.
diff --git a/src/test/ui/issues/issue-17431-2.rs b/src/test/ui/issues/issue-17431-2.rs
new file mode 100644
index 0000000..9ed97f6
--- /dev/null
+++ b/src/test/ui/issues/issue-17431-2.rs
@@ -0,0 +1,9 @@
+struct Baz { q: Option<Foo> }
+//~^ ERROR recursive type `Baz` has infinite size
+
+struct Foo { q: Option<Baz> }
+//~^ ERROR recursive type `Foo` has infinite size
+
+impl Foo { fn bar(&self) {} }
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-17431-2.stderr b/src/test/ui/issues/issue-17431-2.stderr
new file mode 100644
index 0000000..3a7b0e9
--- /dev/null
+++ b/src/test/ui/issues/issue-17431-2.stderr
@@ -0,0 +1,23 @@
+error[E0072]: recursive type `Baz` has infinite size
+  --> $DIR/issue-17431-2.rs:1:1
+   |
+LL | struct Baz { q: Option<Foo> }
+   | ^^^^^^^^^^   -------------- recursive without indirection
+   | |
+   | recursive type has infinite size
+   |
+   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Baz` representable
+
+error[E0072]: recursive type `Foo` has infinite size
+  --> $DIR/issue-17431-2.rs:4:1
+   |
+LL | struct Foo { q: Option<Baz> }
+   | ^^^^^^^^^^   -------------- recursive without indirection
+   | |
+   | recursive type has infinite size
+   |
+   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Foo` representable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0072`.
diff --git a/src/test/ui/issues/issue-17431-3.rs b/src/test/ui/issues/issue-17431-3.rs
new file mode 100644
index 0000000..83a63a8
--- /dev/null
+++ b/src/test/ui/issues/issue-17431-3.rs
@@ -0,0 +1,8 @@
+use std::sync::Mutex;
+
+struct Foo { foo: Mutex<Option<Foo>> }
+//~^ ERROR recursive type `Foo` has infinite size
+
+impl Foo { fn bar(&self) {} }
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-17431-3.stderr b/src/test/ui/issues/issue-17431-3.stderr
new file mode 100644
index 0000000..675a2e2
--- /dev/null
+++ b/src/test/ui/issues/issue-17431-3.stderr
@@ -0,0 +1,13 @@
+error[E0072]: recursive type `Foo` has infinite size
+  --> $DIR/issue-17431-3.rs:3:1
+   |
+LL | struct Foo { foo: Mutex<Option<Foo>> }
+   | ^^^^^^^^^^   ----------------------- recursive without indirection
+   | |
+   | recursive type has infinite size
+   |
+   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Foo` representable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0072`.
diff --git a/src/test/ui/issues/issue-17431-4.rs b/src/test/ui/issues/issue-17431-4.rs
new file mode 100644
index 0000000..48f0dba
--- /dev/null
+++ b/src/test/ui/issues/issue-17431-4.rs
@@ -0,0 +1,8 @@
+use std::marker;
+
+struct Foo<T> { foo: Option<Option<Foo<T>>>, marker: marker::PhantomData<T> }
+//~^ ERROR recursive type `Foo` has infinite size
+
+impl<T> Foo<T> { fn bar(&self) {} }
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-17431-4.stderr b/src/test/ui/issues/issue-17431-4.stderr
new file mode 100644
index 0000000..aff9071
--- /dev/null
+++ b/src/test/ui/issues/issue-17431-4.stderr
@@ -0,0 +1,13 @@
+error[E0072]: recursive type `Foo` has infinite size
+  --> $DIR/issue-17431-4.rs:3:1
+   |
+LL | struct Foo<T> { foo: Option<Option<Foo<T>>>, marker: marker::PhantomData<T> }
+   | ^^^^^^^^^^^^^   --------------------------- recursive without indirection
+   | |
+   | recursive type has infinite size
+   |
+   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Foo` representable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0072`.
diff --git a/src/test/ui/issues/issue-17431-5.rs b/src/test/ui/issues/issue-17431-5.rs
new file mode 100644
index 0000000..0fd6ee6
--- /dev/null
+++ b/src/test/ui/issues/issue-17431-5.rs
@@ -0,0 +1,11 @@
+use std::marker;
+
+struct Foo { foo: Bar<Foo> }
+
+struct Bar<T> { x: Bar<Foo> , marker: marker::PhantomData<T> }
+//~^ ERROR recursive type `Bar` has infinite size
+
+impl Foo { fn foo(&self) {} }
+
+fn main() {
+}
diff --git a/src/test/ui/issues/issue-17431-5.stderr b/src/test/ui/issues/issue-17431-5.stderr
new file mode 100644
index 0000000..537f9f3
--- /dev/null
+++ b/src/test/ui/issues/issue-17431-5.stderr
@@ -0,0 +1,13 @@
+error[E0072]: recursive type `Bar` has infinite size
+  --> $DIR/issue-17431-5.rs:5:1
+   |
+LL | struct Bar<T> { x: Bar<Foo> , marker: marker::PhantomData<T> }
+   | ^^^^^^^^^^^^^   ----------- recursive without indirection
+   | |
+   | recursive type has infinite size
+   |
+   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Bar` representable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0072`.
diff --git a/src/test/ui/issues/issue-17431-6.rs b/src/test/ui/issues/issue-17431-6.rs
new file mode 100644
index 0000000..b7e4987
--- /dev/null
+++ b/src/test/ui/issues/issue-17431-6.rs
@@ -0,0 +1,8 @@
+use std::sync::Mutex;
+
+enum Foo { X(Mutex<Option<Foo>>) }
+//~^ ERROR recursive type `Foo` has infinite size
+
+impl Foo { fn bar(self) {} }
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-17431-6.stderr b/src/test/ui/issues/issue-17431-6.stderr
new file mode 100644
index 0000000..cb2dab9
--- /dev/null
+++ b/src/test/ui/issues/issue-17431-6.stderr
@@ -0,0 +1,13 @@
+error[E0072]: recursive type `Foo` has infinite size
+  --> $DIR/issue-17431-6.rs:3:1
+   |
+LL | enum Foo { X(Mutex<Option<Foo>>) }
+   | ^^^^^^^^     ------------------ recursive without indirection
+   | |
+   | recursive type has infinite size
+   |
+   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Foo` representable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0072`.
diff --git a/src/test/ui/issues/issue-17431-7.rs b/src/test/ui/issues/issue-17431-7.rs
new file mode 100644
index 0000000..4fd7862
--- /dev/null
+++ b/src/test/ui/issues/issue-17431-7.rs
@@ -0,0 +1,6 @@
+enum Foo { Voo(Option<Option<Foo>>) }
+//~^ ERROR recursive type `Foo` has infinite size
+
+impl Foo { fn bar(&self) {} }
+
+fn main() { }
diff --git a/src/test/ui/issues/issue-17431-7.stderr b/src/test/ui/issues/issue-17431-7.stderr
new file mode 100644
index 0000000..de70851
--- /dev/null
+++ b/src/test/ui/issues/issue-17431-7.stderr
@@ -0,0 +1,13 @@
+error[E0072]: recursive type `Foo` has infinite size
+  --> $DIR/issue-17431-7.rs:1:1
+   |
+LL | enum Foo { Voo(Option<Option<Foo>>) }
+   | ^^^^^^^^       ------------------- recursive without indirection
+   | |
+   | recursive type has infinite size
+   |
+   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Foo` representable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0072`.
diff --git a/src/test/ui/issues/issue-17441.rs b/src/test/ui/issues/issue-17441.rs
new file mode 100644
index 0000000..cfb2fe6
--- /dev/null
+++ b/src/test/ui/issues/issue-17441.rs
@@ -0,0 +1,13 @@
+fn main() {
+    let _foo = &[1_usize, 2] as [usize];
+    //~^ ERROR cast to unsized type: `&[usize; 2]` as `[usize]`
+
+    let _bar = Box::new(1_usize) as std::fmt::Debug;
+    //~^ ERROR cast to unsized type: `std::boxed::Box<usize>` as `dyn std::fmt::Debug`
+
+    let _baz = 1_usize as std::fmt::Debug;
+    //~^ ERROR cast to unsized type: `usize` as `dyn std::fmt::Debug`
+
+    let _quux = [1_usize, 2] as [usize];
+    //~^ ERROR cast to unsized type: `[usize; 2]` as `[usize]`
+}
diff --git a/src/test/ui/issues/issue-17441.stderr b/src/test/ui/issues/issue-17441.stderr
new file mode 100644
index 0000000..436ee73
--- /dev/null
+++ b/src/test/ui/issues/issue-17441.stderr
@@ -0,0 +1,47 @@
+error[E0620]: cast to unsized type: `&[usize; 2]` as `[usize]`
+  --> $DIR/issue-17441.rs:2:16
+   |
+LL |     let _foo = &[1_usize, 2] as [usize];
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: consider using an implicit coercion to `&[usize]` instead
+  --> $DIR/issue-17441.rs:2:16
+   |
+LL |     let _foo = &[1_usize, 2] as [usize];
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0620]: cast to unsized type: `std::boxed::Box<usize>` as `dyn std::fmt::Debug`
+  --> $DIR/issue-17441.rs:5:16
+   |
+LL |     let _bar = Box::new(1_usize) as std::fmt::Debug;
+   |                ^^^^^^^^^^^^^^^^^^^^^---------------
+   |                                     |
+   |                                     help: try casting to a `Box` instead: `Box<std::fmt::Debug>`
+
+error[E0620]: cast to unsized type: `usize` as `dyn std::fmt::Debug`
+  --> $DIR/issue-17441.rs:8:16
+   |
+LL |     let _baz = 1_usize as std::fmt::Debug;
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: consider using a box or reference as appropriate
+  --> $DIR/issue-17441.rs:8:16
+   |
+LL |     let _baz = 1_usize as std::fmt::Debug;
+   |                ^^^^^^^
+
+error[E0620]: cast to unsized type: `[usize; 2]` as `[usize]`
+  --> $DIR/issue-17441.rs:11:17
+   |
+LL |     let _quux = [1_usize, 2] as [usize];
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: consider using a box or reference as appropriate
+  --> $DIR/issue-17441.rs:11:17
+   |
+LL |     let _quux = [1_usize, 2] as [usize];
+   |                 ^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0620`.
diff --git a/src/test/ui/issues/issue-17444.rs b/src/test/ui/issues/issue-17444.rs
new file mode 100644
index 0000000..906b443
--- /dev/null
+++ b/src/test/ui/issues/issue-17444.rs
@@ -0,0 +1,8 @@
+enum Test {
+    Foo = 0
+}
+
+fn main() {
+    let _x = Test::Foo as *const isize;
+    //~^ ERROR casting `Test` as `*const isize` is invalid
+}
diff --git a/src/test/ui/issues/issue-17444.stderr b/src/test/ui/issues/issue-17444.stderr
new file mode 100644
index 0000000..1097079
--- /dev/null
+++ b/src/test/ui/issues/issue-17444.stderr
@@ -0,0 +1,9 @@
+error[E0606]: casting `Test` as `*const isize` is invalid
+  --> $DIR/issue-17444.rs:6:14
+   |
+LL |     let _x = Test::Foo as *const isize;
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0606`.
diff --git a/src/test/ui/issues/issue-17450.rs b/src/test/ui/issues/issue-17450.rs
new file mode 100644
index 0000000..70f33e3
--- /dev/null
+++ b/src/test/ui/issues/issue-17450.rs
@@ -0,0 +1,7 @@
+// compile-pass
+#![allow(dead_code, warnings)]
+
+static mut x: isize = 3;
+static mut y: isize = unsafe { x };
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-17458.rs b/src/test/ui/issues/issue-17458.rs
new file mode 100644
index 0000000..444e94d
--- /dev/null
+++ b/src/test/ui/issues/issue-17458.rs
@@ -0,0 +1,6 @@
+static X: usize = unsafe { 0 as *const usize as usize };
+//~^ ERROR: casting pointers to integers in statics is unstable
+
+fn main() {
+    assert_eq!(X, 0);
+}
diff --git a/src/test/ui/issues/issue-17458.stderr b/src/test/ui/issues/issue-17458.stderr
new file mode 100644
index 0000000..a1a8ed9
--- /dev/null
+++ b/src/test/ui/issues/issue-17458.stderr
@@ -0,0 +1,11 @@
+error[E0658]: casting pointers to integers in statics is unstable (see issue #51910)
+  --> $DIR/issue-17458.rs:1:28
+   |
+LL | static X: usize = unsafe { 0 as *const usize as usize };
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_raw_ptr_to_usize_cast)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/issues/issue-17545.nll.stderr b/src/test/ui/issues/issue-17545.nll.stderr
new file mode 100644
index 0000000..79a1e09
--- /dev/null
+++ b/src/test/ui/issues/issue-17545.nll.stderr
@@ -0,0 +1,16 @@
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/issue-17545.rs:7:10
+   |
+LL |   pub fn foo<'a, F: Fn(&'a ())>(bar: F) {
+   |              -- lifetime `'a` defined here
+LL | /     bar.call((
+LL | |         &id(()),
+   | |          ^^^^^^ creates a temporary which is freed while still in use
+LL | |     ));
+   | |      -- temporary value is freed at the end of this statement
+   | |______|
+   |        argument requires that borrow lasts for `'a`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/src/test/ui/issues/issue-17545.rs b/src/test/ui/issues/issue-17545.rs
new file mode 100644
index 0000000..d62c0b9
--- /dev/null
+++ b/src/test/ui/issues/issue-17545.rs
@@ -0,0 +1,10 @@
+#![feature(fn_traits)]
+
+fn id<T>(x: T) -> T { x }
+
+pub fn foo<'a, F: Fn(&'a ())>(bar: F) {
+    bar.call((
+        &id(()), //~ ERROR borrowed value does not live long enough
+    ));
+}
+fn main() {}
diff --git a/src/test/ui/issues/issue-17545.stderr b/src/test/ui/issues/issue-17545.stderr
new file mode 100644
index 0000000..c4acaf2
--- /dev/null
+++ b/src/test/ui/issues/issue-17545.stderr
@@ -0,0 +1,18 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/issue-17545.rs:7:10
+   |
+LL |         &id(()),
+   |          ^^^^^^ temporary value does not live long enough
+LL |     ));
+   |       - temporary value only lives until here
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 5:12...
+  --> $DIR/issue-17545.rs:5:12
+   |
+LL | pub fn foo<'a, F: Fn(&'a ())>(bar: F) {
+   |            ^^
+   = note: consider using a `let` binding to increase its lifetime
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/issues/issue-17546.rs b/src/test/ui/issues/issue-17546.rs
new file mode 100644
index 0000000..dbfdad2
--- /dev/null
+++ b/src/test/ui/issues/issue-17546.rs
@@ -0,0 +1,40 @@
+use foo::MyEnum::Result;
+use foo::NoResult; // Through a re-export
+
+mod foo {
+    pub use self::MyEnum::NoResult;
+
+    pub enum MyEnum {
+        Result,
+        NoResult
+    }
+
+    fn new() -> NoResult<MyEnum, String> {
+        //~^ ERROR expected type, found variant `NoResult`
+        unimplemented!()
+    }
+}
+
+mod bar {
+    use foo::MyEnum::Result;
+    use foo;
+
+    fn new() -> Result<foo::MyEnum, String> {
+        //~^ ERROR expected type, found variant `Result`
+        unimplemented!()
+    }
+}
+
+fn new() -> Result<foo::MyEnum, String> {
+    //~^ ERROR expected type, found variant `Result`
+    unimplemented!()
+}
+
+fn newer() -> NoResult<foo::MyEnum, String> {
+    //~^ ERROR expected type, found variant `NoResult`
+    unimplemented!()
+}
+
+fn main() {
+    let _ = new();
+}
diff --git a/src/test/ui/issues/issue-17546.stderr b/src/test/ui/issues/issue-17546.stderr
new file mode 100644
index 0000000..1fbb229
--- /dev/null
+++ b/src/test/ui/issues/issue-17546.stderr
@@ -0,0 +1,65 @@
+error[E0573]: expected type, found variant `NoResult`
+  --> $DIR/issue-17546.rs:12:17
+   |
+LL |     fn new() -> NoResult<MyEnum, String> {
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^
+help: try using the variant's enum
+   |
+LL |     fn new() -> foo::MyEnum {
+   |                 ^^^^^^^^^^^
+help: an enum with a similar name exists
+   |
+LL |     fn new() -> Result<MyEnum, String> {
+   |                 ^^^^^^
+
+error[E0573]: expected type, found variant `Result`
+  --> $DIR/issue-17546.rs:22:17
+   |
+LL |     fn new() -> Result<foo::MyEnum, String> {
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a type
+help: possible better candidates are found in other modules, you can import them into scope
+   |
+LL |     use std::fmt::Result;
+   |
+LL |     use std::io::Result;
+   |
+LL |     use std::prelude::v1::Result;
+   |
+LL |     use std::result::Result;
+   |
+and 1 other candidates
+
+error[E0573]: expected type, found variant `Result`
+  --> $DIR/issue-17546.rs:28:13
+   |
+LL | fn new() -> Result<foo::MyEnum, String> {
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a type
+help: possible better candidates are found in other modules, you can import them into scope
+   |
+LL | use std::fmt::Result;
+   |
+LL | use std::io::Result;
+   |
+LL | use std::prelude::v1::Result;
+   |
+LL | use std::result::Result;
+   |
+and 1 other candidates
+
+error[E0573]: expected type, found variant `NoResult`
+  --> $DIR/issue-17546.rs:33:15
+   |
+LL | fn newer() -> NoResult<foo::MyEnum, String> {
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: try using the variant's enum
+   |
+LL | fn newer() -> foo::MyEnum {
+   |               ^^^^^^^^^^^
+help: an enum with a similar name exists
+   |
+LL | fn newer() -> Result<foo::MyEnum, String> {
+   |               ^^^^^^
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0573`.
diff --git a/src/test/ui/issues/issue-17551.rs b/src/test/ui/issues/issue-17551.rs
new file mode 100644
index 0000000..a65957c
--- /dev/null
+++ b/src/test/ui/issues/issue-17551.rs
@@ -0,0 +1,8 @@
+use std::marker;
+
+struct B<T>(marker::PhantomData<T>);
+
+fn main() {
+    let foo = B(marker::PhantomData); //~ ERROR type annotations needed
+    let closure = || foo;
+}
diff --git a/src/test/ui/issues/issue-17551.stderr b/src/test/ui/issues/issue-17551.stderr
new file mode 100644
index 0000000..40e7727
--- /dev/null
+++ b/src/test/ui/issues/issue-17551.stderr
@@ -0,0 +1,11 @@
+error[E0282]: type annotations needed
+  --> $DIR/issue-17551.rs:6:15
+   |
+LL |     let foo = B(marker::PhantomData);
+   |         ---   ^ cannot infer type for `T`
+   |         |
+   |         consider giving `foo` a type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/issues/issue-17651.rs b/src/test/ui/issues/issue-17651.rs
new file mode 100644
index 0000000..7629a5a
--- /dev/null
+++ b/src/test/ui/issues/issue-17651.rs
@@ -0,0 +1,7 @@
+// Test that moves of unsized values within closures are caught
+// and rejected.
+
+fn main() {
+    (|| Box::new(*(&[0][..])))();
+    //~^ ERROR the size for values of type
+}
diff --git a/src/test/ui/issues/issue-17651.stderr b/src/test/ui/issues/issue-17651.stderr
new file mode 100644
index 0000000..ce9af15
--- /dev/null
+++ b/src/test/ui/issues/issue-17651.stderr
@@ -0,0 +1,13 @@
+error[E0277]: the size for values of type `[{integer}]` cannot be known at compilation time
+  --> $DIR/issue-17651.rs:5:9
+   |
+LL |     (|| Box::new(*(&[0][..])))();
+   |         ^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `[{integer}]`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: required by `std::boxed::Box::<T>::new`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-17718-const-bad-values.rs b/src/test/ui/issues/issue-17718-const-bad-values.rs
new file mode 100644
index 0000000..97657f8
--- /dev/null
+++ b/src/test/ui/issues/issue-17718-const-bad-values.rs
@@ -0,0 +1,9 @@
+const C1: &'static mut [usize] = &mut [];
+//~^ ERROR: references in constants may only refer to immutable values
+
+static mut S: usize = 3;
+const C2: &'static mut usize = unsafe { &mut S };
+//~^ ERROR: constants cannot refer to statics
+//~| ERROR: references in constants may only refer to immutable values
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-17718-const-bad-values.stderr b/src/test/ui/issues/issue-17718-const-bad-values.stderr
new file mode 100644
index 0000000..95ef2b1
--- /dev/null
+++ b/src/test/ui/issues/issue-17718-const-bad-values.stderr
@@ -0,0 +1,22 @@
+error[E0017]: references in constants may only refer to immutable values
+  --> $DIR/issue-17718-const-bad-values.rs:1:34
+   |
+LL | const C1: &'static mut [usize] = &mut [];
+   |                                  ^^^^^^^ constants require immutable values
+
+error[E0017]: references in constants may only refer to immutable values
+  --> $DIR/issue-17718-const-bad-values.rs:5:41
+   |
+LL | const C2: &'static mut usize = unsafe { &mut S };
+   |                                         ^^^^^^ constants require immutable values
+
+error[E0013]: constants cannot refer to statics, use a constant instead
+  --> $DIR/issue-17718-const-bad-values.rs:5:41
+   |
+LL | const C2: &'static mut usize = unsafe { &mut S };
+   |                                         ^^^^^^
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0013, E0017.
+For more information about an error, try `rustc --explain E0013`.
diff --git a/src/test/ui/issues/issue-17718-const-borrow.rs b/src/test/ui/issues/issue-17718-const-borrow.rs
new file mode 100644
index 0000000..8a31bd0
--- /dev/null
+++ b/src/test/ui/issues/issue-17718-const-borrow.rs
@@ -0,0 +1,14 @@
+use std::cell::UnsafeCell;
+
+const A: UnsafeCell<usize> = UnsafeCell::new(1);
+const B: &'static UnsafeCell<usize> = &A;
+//~^ ERROR: cannot borrow a constant which may contain interior mutability
+
+struct C { a: UnsafeCell<usize> }
+const D: C = C { a: UnsafeCell::new(1) };
+const E: &'static UnsafeCell<usize> = &D.a;
+//~^ ERROR: cannot borrow a constant which may contain interior mutability
+const F: &'static C = &D;
+//~^ ERROR: cannot borrow a constant which may contain interior mutability
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-17718-const-borrow.stderr b/src/test/ui/issues/issue-17718-const-borrow.stderr
new file mode 100644
index 0000000..b433004
--- /dev/null
+++ b/src/test/ui/issues/issue-17718-const-borrow.stderr
@@ -0,0 +1,21 @@
+error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
+  --> $DIR/issue-17718-const-borrow.rs:4:39
+   |
+LL | const B: &'static UnsafeCell<usize> = &A;
+   |                                       ^^
+
+error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
+  --> $DIR/issue-17718-const-borrow.rs:9:39
+   |
+LL | const E: &'static UnsafeCell<usize> = &D.a;
+   |                                       ^^^^
+
+error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
+  --> $DIR/issue-17718-const-borrow.rs:11:23
+   |
+LL | const F: &'static C = &D;
+   |                       ^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0492`.
diff --git a/src/test/ui/issues/issue-17718-const-destructors.rs b/src/test/ui/issues/issue-17718-const-destructors.rs
new file mode 100644
index 0000000..133420b
--- /dev/null
+++ b/src/test/ui/issues/issue-17718-const-destructors.rs
@@ -0,0 +1,10 @@
+// compile-pass
+#![allow(dead_code)]
+struct A;
+impl Drop for A {
+    fn drop(&mut self) {}
+}
+
+const FOO: A = A;
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-17718-const-naming.rs b/src/test/ui/issues/issue-17718-const-naming.rs
new file mode 100644
index 0000000..d30b958
--- /dev/null
+++ b/src/test/ui/issues/issue-17718-const-naming.rs
@@ -0,0 +1,8 @@
+#![warn(unused)]
+#![deny(warnings)]
+
+const foo: isize = 3;
+//~^ ERROR: should have an upper case name
+//~^^ ERROR: constant item is never used
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-17718-const-naming.stderr b/src/test/ui/issues/issue-17718-const-naming.stderr
new file mode 100644
index 0000000..b92acec
--- /dev/null
+++ b/src/test/ui/issues/issue-17718-const-naming.stderr
@@ -0,0 +1,28 @@
+error: constant item is never used: `foo`
+  --> $DIR/issue-17718-const-naming.rs:4:1
+   |
+LL | const foo: isize = 3;
+   | ^^^^^^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/issue-17718-const-naming.rs:2:9
+   |
+LL | #![deny(warnings)]
+   |         ^^^^^^^^
+   = note: #[deny(dead_code)] implied by #[deny(warnings)]
+
+error: constant `foo` should have an upper case name
+  --> $DIR/issue-17718-const-naming.rs:4:7
+   |
+LL | const foo: isize = 3;
+   |       ^^^ help: convert the identifier to upper case: `FOO`
+   |
+note: lint level defined here
+  --> $DIR/issue-17718-const-naming.rs:2:9
+   |
+LL | #![deny(warnings)]
+   |         ^^^^^^^^
+   = note: #[deny(non_upper_case_globals)] implied by #[deny(warnings)]
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/issues/issue-17718-const-privacy.rs b/src/test/ui/issues/issue-17718-const-privacy.rs
new file mode 100644
index 0000000..6ab3a60
--- /dev/null
+++ b/src/test/ui/issues/issue-17718-const-privacy.rs
@@ -0,0 +1,16 @@
+// aux-build:issue-17718-const-privacy.rs
+
+extern crate issue_17718_const_privacy as other;
+
+use a::B; //~ ERROR: constant `B` is private
+use other::{
+    FOO,
+    BAR, //~ ERROR: constant `BAR` is private
+    FOO2,
+};
+
+mod a {
+    const B: usize = 3;
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-17718-const-privacy.stderr b/src/test/ui/issues/issue-17718-const-privacy.stderr
new file mode 100644
index 0000000..0b0de8a
--- /dev/null
+++ b/src/test/ui/issues/issue-17718-const-privacy.stderr
@@ -0,0 +1,15 @@
+error[E0603]: constant `B` is private
+  --> $DIR/issue-17718-const-privacy.rs:5:8
+   |
+LL | use a::B;
+   |        ^
+
+error[E0603]: constant `BAR` is private
+  --> $DIR/issue-17718-const-privacy.rs:8:5
+   |
+LL |     BAR,
+   |     ^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0603`.
diff --git a/src/test/ui/issues/issue-17718-constants-not-static.nll.stderr b/src/test/ui/issues/issue-17718-constants-not-static.nll.stderr
new file mode 100644
index 0000000..8f3acae
--- /dev/null
+++ b/src/test/ui/issues/issue-17718-constants-not-static.nll.stderr
@@ -0,0 +1,12 @@
+error[E0515]: cannot return reference to temporary value
+  --> $DIR/issue-17718-constants-not-static.rs:5:30
+   |
+LL | fn foo() -> &'static usize { &id(FOO) }
+   |                              ^-------
+   |                              ||
+   |                              |temporary value created here
+   |                              returns a reference to data owned by the current function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/src/test/ui/issues/issue-17718-constants-not-static.rs b/src/test/ui/issues/issue-17718-constants-not-static.rs
new file mode 100644
index 0000000..e857b90
--- /dev/null
+++ b/src/test/ui/issues/issue-17718-constants-not-static.rs
@@ -0,0 +1,9 @@
+fn id<T>(x: T) -> T { x }
+
+const FOO: usize = 3;
+
+fn foo() -> &'static usize { &id(FOO) }
+//~^ ERROR: borrowed value does not live long enough
+
+fn main() {
+}
diff --git a/src/test/ui/issues/issue-17718-constants-not-static.stderr b/src/test/ui/issues/issue-17718-constants-not-static.stderr
new file mode 100644
index 0000000..2a5b9d7
--- /dev/null
+++ b/src/test/ui/issues/issue-17718-constants-not-static.stderr
@@ -0,0 +1,13 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/issue-17718-constants-not-static.rs:5:31
+   |
+LL | fn foo() -> &'static usize { &id(FOO) }
+   |                               ^^^^^^^ - temporary value only lives until here
+   |                               |
+   |                               temporary value does not live long enough
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/issues/issue-17718-patterns.rs b/src/test/ui/issues/issue-17718-patterns.rs
new file mode 100644
index 0000000..2ca0f67
--- /dev/null
+++ b/src/test/ui/issues/issue-17718-patterns.rs
@@ -0,0 +1,12 @@
+static A1: usize = 1;
+static mut A2: usize = 1;
+const A3: usize = 1;
+
+fn main() {
+    match 1 {
+        A1 => {} //~ ERROR: match bindings cannot shadow statics
+        A2 => {} //~ ERROR: match bindings cannot shadow statics
+        A3 => {}
+        _ => {}
+    }
+}
diff --git a/src/test/ui/issues/issue-17718-patterns.stderr b/src/test/ui/issues/issue-17718-patterns.stderr
new file mode 100644
index 0000000..109091c
--- /dev/null
+++ b/src/test/ui/issues/issue-17718-patterns.stderr
@@ -0,0 +1,21 @@
+error[E0530]: match bindings cannot shadow statics
+  --> $DIR/issue-17718-patterns.rs:7:9
+   |
+LL | static A1: usize = 1;
+   | --------------------- the static `A1` is defined here
+...
+LL |         A1 => {}
+   |         ^^ cannot be named the same as a static
+
+error[E0530]: match bindings cannot shadow statics
+  --> $DIR/issue-17718-patterns.rs:8:9
+   |
+LL | static mut A2: usize = 1;
+   | ------------------------- the static `A2` is defined here
+...
+LL |         A2 => {}
+   |         ^^ cannot be named the same as a static
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0530`.
diff --git a/src/test/ui/issues/issue-17718-references.rs b/src/test/ui/issues/issue-17718-references.rs
new file mode 100644
index 0000000..03d5f8b
--- /dev/null
+++ b/src/test/ui/issues/issue-17718-references.rs
@@ -0,0 +1,24 @@
+#![allow(warnings)]
+
+struct Struct { a: usize }
+
+const C: usize = 1;
+static S: usize = 1;
+
+const T1: &'static usize = &C;
+const T2: &'static usize = &S; //~ ERROR: constants cannot refer to statics
+static T3: &'static usize = &C;
+static T4: &'static usize = &S;
+
+const T5: usize = C;
+const T6: usize = S; //~ ERROR: constants cannot refer to statics
+static T7: usize = C;
+static T8: usize = S;
+
+const T9: Struct = Struct { a: C };
+const T10: Struct = Struct { a: S };
+//~^ ERROR: constants cannot refer to statics
+static T11: Struct = Struct { a: C };
+static T12: Struct = Struct { a: S };
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-17718-references.stderr b/src/test/ui/issues/issue-17718-references.stderr
new file mode 100644
index 0000000..15c3e67
--- /dev/null
+++ b/src/test/ui/issues/issue-17718-references.stderr
@@ -0,0 +1,21 @@
+error[E0013]: constants cannot refer to statics, use a constant instead
+  --> $DIR/issue-17718-references.rs:9:28
+   |
+LL | const T2: &'static usize = &S;
+   |                            ^^
+
+error[E0013]: constants cannot refer to statics, use a constant instead
+  --> $DIR/issue-17718-references.rs:14:19
+   |
+LL | const T6: usize = S;
+   |                   ^
+
+error[E0013]: constants cannot refer to statics, use a constant instead
+  --> $DIR/issue-17718-references.rs:19:33
+   |
+LL | const T10: Struct = Struct { a: S };
+   |                                 ^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0013`.
diff --git a/src/test/ui/issues/issue-17718-static-move.nll.stderr b/src/test/ui/issues/issue-17718-static-move.nll.stderr
new file mode 100644
index 0000000..c3e6267
--- /dev/null
+++ b/src/test/ui/issues/issue-17718-static-move.nll.stderr
@@ -0,0 +1,12 @@
+error[E0507]: cannot move out of static item
+  --> $DIR/issue-17718-static-move.rs:6:14
+   |
+LL |     let _a = FOO;
+   |              ^^^
+   |              |
+   |              cannot move out of static item
+   |              help: consider borrowing here: `&FOO`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/issues/issue-17718-static-move.rs b/src/test/ui/issues/issue-17718-static-move.rs
new file mode 100644
index 0000000..015487a
--- /dev/null
+++ b/src/test/ui/issues/issue-17718-static-move.rs
@@ -0,0 +1,7 @@
+struct Foo;
+const INIT: Foo = Foo;
+static FOO: Foo = INIT;
+
+fn main() {
+    let _a = FOO; //~ ERROR: cannot move out of static item
+}
diff --git a/src/test/ui/issues/issue-17718-static-move.stderr b/src/test/ui/issues/issue-17718-static-move.stderr
new file mode 100644
index 0000000..064a991
--- /dev/null
+++ b/src/test/ui/issues/issue-17718-static-move.stderr
@@ -0,0 +1,12 @@
+error[E0507]: cannot move out of static item
+  --> $DIR/issue-17718-static-move.rs:6:14
+   |
+LL |     let _a = FOO;
+   |              ^^^
+   |              |
+   |              cannot move out of static item
+   |              help: consider using a reference instead: `&FOO`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/issues/issue-17718-static-sync.rs b/src/test/ui/issues/issue-17718-static-sync.rs
new file mode 100644
index 0000000..dccbde6
--- /dev/null
+++ b/src/test/ui/issues/issue-17718-static-sync.rs
@@ -0,0 +1,12 @@
+#![feature(optin_builtin_traits)]
+
+use std::marker::Sync;
+
+struct Foo;
+impl !Sync for Foo {}
+
+static FOO: usize = 3;
+static BAR: Foo = Foo;
+//~^ ERROR: `Foo` cannot be shared between threads safely [E0277]
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-17718-static-sync.stderr b/src/test/ui/issues/issue-17718-static-sync.stderr
new file mode 100644
index 0000000..7f162a9
--- /dev/null
+++ b/src/test/ui/issues/issue-17718-static-sync.stderr
@@ -0,0 +1,12 @@
+error[E0277]: `Foo` cannot be shared between threads safely
+  --> $DIR/issue-17718-static-sync.rs:9:1
+   |
+LL | static BAR: Foo = Foo;
+   | ^^^^^^^^^^^^^^^^^^^^^^ `Foo` cannot be shared between threads safely
+   |
+   = help: the trait `std::marker::Sync` is not implemented for `Foo`
+   = note: shared static variables must have a type that implements `Sync`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-17728.rs b/src/test/ui/issues/issue-17728.rs
new file mode 100644
index 0000000..15cea1d
--- /dev/null
+++ b/src/test/ui/issues/issue-17728.rs
@@ -0,0 +1,123 @@
+use std::fmt::{Debug, Formatter, Error};
+use std::collections::HashMap;
+
+trait HasInventory {
+    fn getInventory<'s>(&'s self) -> &'s mut Inventory;
+    fn addToInventory(&self, item: &Item);
+    fn removeFromInventory(&self, itemName: &str) -> bool;
+}
+
+trait TraversesWorld {
+    fn attemptTraverse(&self, room: &Room, directionStr: &str) -> Result<&Room, &str> {
+        let direction = str_to_direction(directionStr);
+        let maybe_room = room.direction_to_room.get(&direction);
+        match maybe_room {
+            Some(entry) => Ok(entry),
+            //~^ ERROR lifetime mismatch [E0623]
+            _ => Err("Direction does not exist in room.")
+        }
+    }
+}
+
+
+#[derive(Debug, Eq, PartialEq, Hash)]
+enum RoomDirection {
+    West,
+    East,
+    North,
+    South,
+    Up,
+    Down,
+    In,
+    Out,
+
+    None
+}
+
+struct Room {
+    description: String,
+    items: Vec<Item>,
+    direction_to_room: HashMap<RoomDirection, Room>,
+}
+
+impl Room {
+    fn new(description: &'static str) -> Room {
+        Room {
+            description: description.to_string(),
+            items: Vec::new(),
+            direction_to_room: HashMap::new()
+        }
+    }
+
+    fn add_direction(&mut self, direction: RoomDirection, room: Room) {
+        self.direction_to_room.insert(direction, room);
+    }
+}
+
+struct Item {
+    name: String,
+}
+
+struct Inventory {
+    items: Vec<Item>,
+}
+
+impl Inventory {
+    fn new() -> Inventory {
+        Inventory {
+            items: Vec::new()
+        }
+    }
+}
+
+struct Player {
+    name: String,
+    inventory: Inventory,
+}
+
+impl Player {
+    fn new(name: &'static str) -> Player {
+        Player {
+            name: name.to_string(),
+            inventory: Inventory::new()
+        }
+    }
+}
+
+impl TraversesWorld for Player {
+}
+
+impl Debug for Player {
+    fn fmt(&self, formatter: &mut Formatter) -> Result<(), Error> {
+        formatter.write_str("Player{ name:");
+        formatter.write_str(&self.name);
+        formatter.write_str(" }");
+        Ok(())
+    }
+}
+
+fn str_to_direction(to_parse: &str) -> RoomDirection {
+    match to_parse {
+        "w" | "west" => RoomDirection::West,
+        "e" | "east" => RoomDirection::East,
+        "n" | "north" => RoomDirection::North,
+        "s" | "south" => RoomDirection::South,
+        "in" => RoomDirection::In,
+        "out" => RoomDirection::Out,
+        "up" => RoomDirection::Up,
+        "down" => RoomDirection::Down,
+        _ => None
+    }
+        //~^^ ERROR match arms have incompatible types
+}
+
+fn main() {
+    let mut player = Player::new("Test player");
+    let mut room = Room::new("A test room");
+    println!("Made a player: {:?}", player);
+    println!("Direction parse: {:?}", str_to_direction("east"));
+    match player.attemptTraverse(&room, "west") {
+        Ok(_) => println!("Was able to move west"),
+        Err(msg) => println!("Not able to move west: {}", msg)
+    };
+}
diff --git a/src/test/ui/issues/issue-17728.stderr b/src/test/ui/issues/issue-17728.stderr
new file mode 100644
index 0000000..2c2efad
--- /dev/null
+++ b/src/test/ui/issues/issue-17728.stderr
@@ -0,0 +1,33 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/issue-17728.rs:15:28
+   |
+LL |     fn attemptTraverse(&self, room: &Room, directionStr: &str) -> Result<&Room, &str> {
+   |                                     -----                         -------------------
+   |                                     |
+   |                                     this parameter and the return type are declared with different lifetimes...
+...
+LL |             Some(entry) => Ok(entry),
+   |                            ^^^^^^^^^ ...but data from `room` is returned here
+
+error[E0308]: match arms have incompatible types
+  --> $DIR/issue-17728.rs:109:14
+   |
+LL | /     match to_parse {
+LL | |         "w" | "west" => RoomDirection::West,
+LL | |         "e" | "east" => RoomDirection::East,
+LL | |         "n" | "north" => RoomDirection::North,
+...  |
+LL | |         "down" => RoomDirection::Down,
+   | |                   ------------------- this and all prior arms are found to be of type `RoomDirection`
+LL | |         _ => None
+   | |              ^^^^ expected enum `RoomDirection`, found enum `std::option::Option`
+LL | |     }
+   | |_____- `match` arms have incompatible types
+   |
+   = note: expected type `RoomDirection`
+              found type `std::option::Option<_>`
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0308, E0623.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-17732.rs b/src/test/ui/issues/issue-17732.rs
new file mode 100644
index 0000000..7993bbb
--- /dev/null
+++ b/src/test/ui/issues/issue-17732.rs
@@ -0,0 +1,12 @@
+// compile-pass
+#![allow(dead_code)]
+// pretty-expanded FIXME #23616
+
+trait Person {
+    type string;
+    fn dummy(&self) { }
+}
+
+struct Someone<P: Person>(std::marker::PhantomData<P>);
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-17740.rs b/src/test/ui/issues/issue-17740.rs
new file mode 100644
index 0000000..c131b89
--- /dev/null
+++ b/src/test/ui/issues/issue-17740.rs
@@ -0,0 +1,18 @@
+struct Foo<'a> {
+    data: &'a[u8],
+}
+
+impl <'a> Foo<'a>{
+    fn bar(self: &mut Foo) {
+    //~^ mismatched method receiver
+    //~| expected type `Foo<'a>`
+    //~| found type `Foo<'_>`
+    //~| lifetime mismatch
+    //~| mismatched method receiver
+    //~| expected type `Foo<'a>`
+    //~| found type `Foo<'_>`
+    //~| lifetime mismatch
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-17740.stderr b/src/test/ui/issues/issue-17740.stderr
new file mode 100644
index 0000000..7ab0fa4
--- /dev/null
+++ b/src/test/ui/issues/issue-17740.stderr
@@ -0,0 +1,53 @@
+error[E0308]: mismatched method receiver
+  --> $DIR/issue-17740.rs:6:18
+   |
+LL |     fn bar(self: &mut Foo) {
+   |                  ^^^^^^^^ lifetime mismatch
+   |
+   = note: expected type `Foo<'a>`
+              found type `Foo<'_>`
+note: the anonymous lifetime #2 defined on the method body at 6:5...
+  --> $DIR/issue-17740.rs:6:5
+   |
+LL | /     fn bar(self: &mut Foo) {
+LL | |
+LL | |
+LL | |
+...  |
+LL | |
+LL | |     }
+   | |_____^
+note: ...does not necessarily outlive the lifetime 'a as defined on the impl at 5:7
+  --> $DIR/issue-17740.rs:5:7
+   |
+LL | impl <'a> Foo<'a>{
+   |       ^^
+
+error[E0308]: mismatched method receiver
+  --> $DIR/issue-17740.rs:6:18
+   |
+LL |     fn bar(self: &mut Foo) {
+   |                  ^^^^^^^^ lifetime mismatch
+   |
+   = note: expected type `Foo<'a>`
+              found type `Foo<'_>`
+note: the lifetime 'a as defined on the impl at 5:7...
+  --> $DIR/issue-17740.rs:5:7
+   |
+LL | impl <'a> Foo<'a>{
+   |       ^^
+note: ...does not necessarily outlive the anonymous lifetime #2 defined on the method body at 6:5
+  --> $DIR/issue-17740.rs:6:5
+   |
+LL | /     fn bar(self: &mut Foo) {
+LL | |
+LL | |
+LL | |
+...  |
+LL | |
+LL | |     }
+   | |_____^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-17746.rs b/src/test/ui/issues/issue-17746.rs
new file mode 100644
index 0000000..45c5b85
--- /dev/null
+++ b/src/test/ui/issues/issue-17746.rs
@@ -0,0 +1,25 @@
+// compile-pass
+#![allow(dead_code)]
+// Regression test for #17746
+
+fn main() {}
+
+struct A;
+
+impl A {
+    fn b(&mut self) {
+        self.a()
+    }
+}
+
+trait Foo {
+    fn dummy(&self) {}
+}
+trait Bar {
+    fn a(&self);
+}
+
+impl Foo for A {}
+impl<T> Bar for T where T: Foo {
+    fn a(&self) {}
+}
diff --git a/src/test/ui/issues/issue-17758.rs b/src/test/ui/issues/issue-17758.rs
new file mode 100644
index 0000000..d0dbd34
--- /dev/null
+++ b/src/test/ui/issues/issue-17758.rs
@@ -0,0 +1,12 @@
+// Test that regionck suggestions in a provided method of a trait
+// don't ICE
+
+trait Foo<'a> {
+    fn foo(&'a self);
+    fn bar(&self) {
+        self.foo();
+        //~^ ERROR cannot infer
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-17758.stderr b/src/test/ui/issues/issue-17758.stderr
new file mode 100644
index 0000000..28a1be5
--- /dev/null
+++ b/src/test/ui/issues/issue-17758.stderr
@@ -0,0 +1,31 @@
+error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
+  --> $DIR/issue-17758.rs:7:14
+   |
+LL |         self.foo();
+   |              ^^^
+   |
+note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 6:5...
+  --> $DIR/issue-17758.rs:6:5
+   |
+LL | /     fn bar(&self) {
+LL | |         self.foo();
+LL | |
+LL | |     }
+   | |_____^
+note: ...so that reference does not outlive borrowed content
+  --> $DIR/issue-17758.rs:7:9
+   |
+LL |         self.foo();
+   |         ^^^^
+note: but, the lifetime must be valid for the lifetime 'a as defined on the trait at 4:11...
+  --> $DIR/issue-17758.rs:4:11
+   |
+LL | trait Foo<'a> {
+   |           ^^
+   = note: ...so that the types are compatible:
+           expected &'a Self
+              found &Self
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0495`.
diff --git a/src/test/ui/issues/issue-17800.rs b/src/test/ui/issues/issue-17800.rs
new file mode 100644
index 0000000..45879d6
--- /dev/null
+++ b/src/test/ui/issues/issue-17800.rs
@@ -0,0 +1,12 @@
+enum MyOption<T> {
+    MySome(T),
+    MyNone,
+}
+
+fn main() {
+    match MyOption::MySome(42) {
+        MyOption::MySome { x: 42 } => (),
+        //~^ ERROR variant `MyOption::MySome` does not have a field named `x`
+        _ => (),
+    }
+}
diff --git a/src/test/ui/issues/issue-17800.stderr b/src/test/ui/issues/issue-17800.stderr
new file mode 100644
index 0000000..6efc7f0
--- /dev/null
+++ b/src/test/ui/issues/issue-17800.stderr
@@ -0,0 +1,12 @@
+error[E0026]: variant `MyOption::MySome` does not have a field named `x`
+  --> $DIR/issue-17800.rs:8:28
+   |
+LL |         MyOption::MySome { x: 42 } => (),
+   |                            ^
+   |                            |
+   |                            variant `MyOption::MySome` does not have this field
+   |                            help: a field with a similar name exists: `0`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0026`.
diff --git a/src/test/ui/issues/issue-17904-2.rs b/src/test/ui/issues/issue-17904-2.rs
new file mode 100644
index 0000000..9603da0
--- /dev/null
+++ b/src/test/ui/issues/issue-17904-2.rs
@@ -0,0 +1,6 @@
+// Test that we can parse a unit struct with a where clause, even if
+// it leads to an error later on since `T` is unused.
+
+struct Foo<T> where T: Copy; //~ ERROR parameter `T` is never used
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-17904-2.stderr b/src/test/ui/issues/issue-17904-2.stderr
new file mode 100644
index 0000000..b8fabd3
--- /dev/null
+++ b/src/test/ui/issues/issue-17904-2.stderr
@@ -0,0 +1,11 @@
+error[E0392]: parameter `T` is never used
+  --> $DIR/issue-17904-2.rs:4:12
+   |
+LL | struct Foo<T> where T: Copy;
+   |            ^ unused type parameter
+   |
+   = help: consider removing `T` or using a marker such as `std::marker::PhantomData`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0392`.
diff --git a/src/test/ui/issues/issue-17904.rs b/src/test/ui/issues/issue-17904.rs
new file mode 100644
index 0000000..2fe5495
--- /dev/null
+++ b/src/test/ui/issues/issue-17904.rs
@@ -0,0 +1,14 @@
+// compile-pass
+#![allow(dead_code)]
+// Test that we can parse where clauses on various forms of tuple
+// structs.
+
+// pretty-expanded FIXME #23616
+
+struct Bar<T>(T) where T: Copy;
+struct Bleh<T, U>(T, U) where T: Copy, U: Sized;
+struct Baz<T> where T: Copy {
+    field: T
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-17905-2.rs b/src/test/ui/issues/issue-17905-2.rs
new file mode 100644
index 0000000..259d945
--- /dev/null
+++ b/src/test/ui/issues/issue-17905-2.rs
@@ -0,0 +1,18 @@
+#[derive(Debug)]
+struct Pair<T, V> (T, V);
+
+impl Pair<
+    &str,
+    isize
+> {
+    fn say(self: &Pair<&str, isize>) {
+//~^ ERROR mismatched method receiver
+//~| ERROR mismatched method receiver
+        println!("{:?}", self);
+    }
+}
+
+fn main() {
+    let result = &Pair("shane", 1);
+    result.say();
+}
diff --git a/src/test/ui/issues/issue-17905-2.stderr b/src/test/ui/issues/issue-17905-2.stderr
new file mode 100644
index 0000000..e3909e0
--- /dev/null
+++ b/src/test/ui/issues/issue-17905-2.stderr
@@ -0,0 +1,49 @@
+error[E0308]: mismatched method receiver
+  --> $DIR/issue-17905-2.rs:8:18
+   |
+LL |     fn say(self: &Pair<&str, isize>) {
+   |                  ^^^^^^^^^^^^^^^^^^ lifetime mismatch
+   |
+   = note: expected type `Pair<&str, _>`
+              found type `Pair<&str, _>`
+note: the anonymous lifetime #2 defined on the method body at 8:5...
+  --> $DIR/issue-17905-2.rs:8:5
+   |
+LL | /     fn say(self: &Pair<&str, isize>) {
+LL | |
+LL | |
+LL | |         println!("{:?}", self);
+LL | |     }
+   | |_____^
+note: ...does not necessarily outlive the lifetime '_ as defined on the impl at 5:5
+  --> $DIR/issue-17905-2.rs:5:5
+   |
+LL |     &str,
+   |     ^
+
+error[E0308]: mismatched method receiver
+  --> $DIR/issue-17905-2.rs:8:18
+   |
+LL |     fn say(self: &Pair<&str, isize>) {
+   |                  ^^^^^^^^^^^^^^^^^^ lifetime mismatch
+   |
+   = note: expected type `Pair<&str, _>`
+              found type `Pair<&str, _>`
+note: the lifetime '_ as defined on the impl at 5:5...
+  --> $DIR/issue-17905-2.rs:5:5
+   |
+LL |     &str,
+   |     ^
+note: ...does not necessarily outlive the anonymous lifetime #2 defined on the method body at 8:5
+  --> $DIR/issue-17905-2.rs:8:5
+   |
+LL | /     fn say(self: &Pair<&str, isize>) {
+LL | |
+LL | |
+LL | |         println!("{:?}", self);
+LL | |     }
+   | |_____^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-17905.rs b/src/test/ui/issues/issue-17905.rs
new file mode 100644
index 0000000..95133a4
--- /dev/null
+++ b/src/test/ui/issues/issue-17905.rs
@@ -0,0 +1,18 @@
+// run-pass
+
+#[derive(Debug)]
+struct Pair<T, V> (T, V);
+
+impl Pair<
+    &str,
+    isize
+> {
+    fn say(&self) {
+        println!("{:?}", self);
+    }
+}
+
+fn main() {
+    let result = &Pair("shane", 1);
+    result.say();
+}
diff --git a/src/test/ui/issues/issue-17913.rs b/src/test/ui/issues/issue-17913.rs
new file mode 100644
index 0000000..b0c4ef5
--- /dev/null
+++ b/src/test/ui/issues/issue-17913.rs
@@ -0,0 +1,18 @@
+// normalize-stderr-test "\[&usize; \d+\]" -> "[&usize; N]"
+// error-pattern: too big for the current architecture
+
+#![feature(box_syntax)]
+
+#[cfg(target_pointer_width = "64")]
+fn main() {
+    let n = 0_usize;
+    let a: Box<_> = box [&n; 0xF000000000000000_usize];
+    println!("{}", a[0xFFFFFF_usize]);
+}
+
+#[cfg(target_pointer_width = "32")]
+fn main() {
+    let n = 0_usize;
+    let a: Box<_> = box [&n; 0xFFFFFFFF_usize];
+    println!("{}", a[0xFFFFFF_usize]);
+}
diff --git a/src/test/ui/issues/issue-17913.stderr b/src/test/ui/issues/issue-17913.stderr
new file mode 100644
index 0000000..ae388c4
--- /dev/null
+++ b/src/test/ui/issues/issue-17913.stderr
@@ -0,0 +1,4 @@
+error: the type `[&usize; N]` is too big for the current architecture
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-17933.rs b/src/test/ui/issues/issue-17933.rs
new file mode 100644
index 0000000..c649b64
--- /dev/null
+++ b/src/test/ui/issues/issue-17933.rs
@@ -0,0 +1,9 @@
+pub static X: usize = 1;
+
+fn main() {
+    match 1 {
+        self::X => { },
+        //~^ ERROR expected unit struct/variant or constant, found static `self::X`
+        _       => { },
+    }
+}
diff --git a/src/test/ui/issues/issue-17933.stderr b/src/test/ui/issues/issue-17933.stderr
new file mode 100644
index 0000000..e48a650
--- /dev/null
+++ b/src/test/ui/issues/issue-17933.stderr
@@ -0,0 +1,9 @@
+error[E0532]: expected unit struct/variant or constant, found static `self::X`
+  --> $DIR/issue-17933.rs:5:9
+   |
+LL |         self::X => { },
+   |         ^^^^^^^ not a unit struct/variant or constant
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0532`.
diff --git a/src/test/ui/issues/issue-17954.nll.stderr b/src/test/ui/issues/issue-17954.nll.stderr
new file mode 100644
index 0000000..e08375f
--- /dev/null
+++ b/src/test/ui/issues/issue-17954.nll.stderr
@@ -0,0 +1,12 @@
+error[E0712]: thread-local variable borrowed past end of function
+  --> $DIR/issue-17954.rs:7:13
+   |
+LL |     let a = &FOO;
+   |             ^^^^ thread-local variables cannot be borrowed beyond the end of the function
+...
+LL | }
+   | - end of enclosing function is here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0712`.
diff --git a/src/test/ui/issues/issue-17954.rs b/src/test/ui/issues/issue-17954.rs
new file mode 100644
index 0000000..a8fbf237
--- /dev/null
+++ b/src/test/ui/issues/issue-17954.rs
@@ -0,0 +1,16 @@
+#![feature(thread_local)]
+
+#[thread_local]
+static FOO: u8 = 3;
+
+fn main() {
+    let a = &FOO;
+    //~^ ERROR borrowed value does not live long enough
+    //~| does not live long enough
+    //~| NOTE borrowed value must be valid for the static lifetime
+
+    std::thread::spawn(move || {
+        println!("{}", a);
+    });
+}
+//~^ NOTE borrowed value only lives until here
diff --git a/src/test/ui/issues/issue-17954.stderr b/src/test/ui/issues/issue-17954.stderr
new file mode 100644
index 0000000..458bef5
--- /dev/null
+++ b/src/test/ui/issues/issue-17954.stderr
@@ -0,0 +1,14 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/issue-17954.rs:7:14
+   |
+LL |     let a = &FOO;
+   |              ^^^ borrowed value does not live long enough
+...
+LL | }
+   | - borrowed value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/issues/issue-17959.rs b/src/test/ui/issues/issue-17959.rs
new file mode 100644
index 0000000..d56f346e
--- /dev/null
+++ b/src/test/ui/issues/issue-17959.rs
@@ -0,0 +1,21 @@
+extern crate core;
+
+use core::ops::Drop;
+
+trait Bar {}
+
+struct G<T: ?Sized> {
+    _ptr: *const T
+}
+
+impl<T> Drop for G<T> {
+//~^ ERROR: The requirement `T: std::marker::Sized` is added only by the Drop impl. [E0367]
+    fn drop(&mut self) {
+        if !self._ptr.is_null() {
+        }
+    }
+}
+
+fn main() {
+    let x:G<Bar>;
+}
diff --git a/src/test/ui/issues/issue-17959.stderr b/src/test/ui/issues/issue-17959.stderr
new file mode 100644
index 0000000..de742e4
--- /dev/null
+++ b/src/test/ui/issues/issue-17959.stderr
@@ -0,0 +1,23 @@
+error[E0367]: The requirement `T: std::marker::Sized` is added only by the Drop impl.
+  --> $DIR/issue-17959.rs:11:1
+   |
+LL | / impl<T> Drop for G<T> {
+LL | |
+LL | |     fn drop(&mut self) {
+LL | |         if !self._ptr.is_null() {
+LL | |         }
+LL | |     }
+LL | | }
+   | |_^
+   |
+note: The same requirement must be part of the struct/enum definition
+  --> $DIR/issue-17959.rs:7:1
+   |
+LL | / struct G<T: ?Sized> {
+LL | |     _ptr: *const T
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0367`.
diff --git a/src/test/ui/issues/issue-17994.rs b/src/test/ui/issues/issue-17994.rs
new file mode 100644
index 0000000..39b0a7e
--- /dev/null
+++ b/src/test/ui/issues/issue-17994.rs
@@ -0,0 +1,3 @@
+trait Tr {}
+type Huh<T> where T: Tr = isize; //~  ERROR type parameter `T` is unused
+fn main() {}
diff --git a/src/test/ui/issues/issue-17994.stderr b/src/test/ui/issues/issue-17994.stderr
new file mode 100644
index 0000000..61e1e49
--- /dev/null
+++ b/src/test/ui/issues/issue-17994.stderr
@@ -0,0 +1,9 @@
+error[E0091]: type parameter `T` is unused
+  --> $DIR/issue-17994.rs:2:10
+   |
+LL | type Huh<T> where T: Tr = isize;
+   |          ^ unused type parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0091`.
diff --git a/src/test/ui/issues/issue-17999.rs b/src/test/ui/issues/issue-17999.rs
new file mode 100644
index 0000000..941f1e7
--- /dev/null
+++ b/src/test/ui/issues/issue-17999.rs
@@ -0,0 +1,10 @@
+#![deny(unused_variables)]
+
+fn main() {
+    for _ in 1..101 {
+        let x = (); //~ ERROR: unused variable: `x`
+        match () {
+            a => {} //~ ERROR: unused variable: `a`
+        }
+    }
+}
diff --git a/src/test/ui/issues/issue-17999.stderr b/src/test/ui/issues/issue-17999.stderr
new file mode 100644
index 0000000..b9ae033
--- /dev/null
+++ b/src/test/ui/issues/issue-17999.stderr
@@ -0,0 +1,20 @@
+error: unused variable: `x`
+  --> $DIR/issue-17999.rs:5:13
+   |
+LL |         let x = ();
+   |             ^ help: consider prefixing with an underscore: `_x`
+   |
+note: lint level defined here
+  --> $DIR/issue-17999.rs:1:9
+   |
+LL | #![deny(unused_variables)]
+   |         ^^^^^^^^^^^^^^^^
+
+error: unused variable: `a`
+  --> $DIR/issue-17999.rs:7:13
+   |
+LL |             a => {}
+   |             ^ help: consider prefixing with an underscore: `_a`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/issues/issue-18058.rs b/src/test/ui/issues/issue-18058.rs
new file mode 100644
index 0000000..cced667
--- /dev/null
+++ b/src/test/ui/issues/issue-18058.rs
@@ -0,0 +1,4 @@
+impl Undefined {}
+//~^ ERROR cannot find type `Undefined` in this scope
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-18058.stderr b/src/test/ui/issues/issue-18058.stderr
new file mode 100644
index 0000000..18159ff
--- /dev/null
+++ b/src/test/ui/issues/issue-18058.stderr
@@ -0,0 +1,9 @@
+error[E0412]: cannot find type `Undefined` in this scope
+  --> $DIR/issue-18058.rs:1:6
+   |
+LL | impl Undefined {}
+   |      ^^^^^^^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/src/test/ui/issues/issue-18083.rs b/src/test/ui/issues/issue-18083.rs
new file mode 100644
index 0000000..c2cf291
--- /dev/null
+++ b/src/test/ui/issues/issue-18083.rs
@@ -0,0 +1,25 @@
+// compile-pass
+#![allow(dead_code)]
+#![allow(unused_imports)]
+// These crossed imports should resolve fine, and not block on
+// each other and be reported as unresolved.
+
+mod a {
+    use b::{B};
+    pub use self::inner::A;
+
+    mod inner {
+        pub struct A;
+    }
+}
+
+mod b {
+    use a::{A};
+    pub use self::inner::B;
+
+    mod inner {
+        pub struct B;
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-18088.rs b/src/test/ui/issues/issue-18088.rs
new file mode 100644
index 0000000..67000d9
--- /dev/null
+++ b/src/test/ui/issues/issue-18088.rs
@@ -0,0 +1,8 @@
+// compile-pass
+
+pub trait Indexable<T>: std::ops::Index<usize, Output = T> {
+    fn index2(&self, i: usize) -> &T {
+        &self[i]
+    }
+}
+fn main() {}
diff --git a/src/test/ui/issues/issue-18107.rs b/src/test/ui/issues/issue-18107.rs
new file mode 100644
index 0000000..184d122
--- /dev/null
+++ b/src/test/ui/issues/issue-18107.rs
@@ -0,0 +1,13 @@
+pub trait AbstractRenderer {}
+
+fn _create_render(_: &()) ->
+    AbstractRenderer
+//~^ ERROR the size for values of type
+{
+    match 0 {
+        _ => unimplemented!()
+    }
+}
+
+fn main() {
+}
diff --git a/src/test/ui/issues/issue-18107.stderr b/src/test/ui/issues/issue-18107.stderr
new file mode 100644
index 0000000..23b58c3
--- /dev/null
+++ b/src/test/ui/issues/issue-18107.stderr
@@ -0,0 +1,13 @@
+error[E0277]: the size for values of type `(dyn AbstractRenderer + 'static)` cannot be known at compilation time
+  --> $DIR/issue-18107.rs:4:5
+   |
+LL |     AbstractRenderer
+   |     ^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `(dyn AbstractRenderer + 'static)`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: the return type of a function must have a statically known size
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-18118-2.rs b/src/test/ui/issues/issue-18118-2.rs
new file mode 100644
index 0000000..6d52156
--- /dev/null
+++ b/src/test/ui/issues/issue-18118-2.rs
@@ -0,0 +1,7 @@
+pub fn main() {
+    const z: &'static isize = {
+        static p: isize = 3;
+        &p
+        //~^ ERROR constants cannot refer to statics, use a constant instead
+    };
+}
diff --git a/src/test/ui/issues/issue-18118-2.stderr b/src/test/ui/issues/issue-18118-2.stderr
new file mode 100644
index 0000000..4e848c2
--- /dev/null
+++ b/src/test/ui/issues/issue-18118-2.stderr
@@ -0,0 +1,9 @@
+error[E0013]: constants cannot refer to statics, use a constant instead
+  --> $DIR/issue-18118-2.rs:4:9
+   |
+LL |         &p
+   |         ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0013`.
diff --git a/src/test/ui/issues/issue-18118.nll.stderr b/src/test/ui/issues/issue-18118.nll.stderr
new file mode 100644
index 0000000..49798a1
--- /dev/null
+++ b/src/test/ui/issues/issue-18118.nll.stderr
@@ -0,0 +1,14 @@
+error[E0597]: `p` does not live long enough
+  --> $DIR/issue-18118.rs:4:9
+   |
+LL |         &p
+   |         ^^
+   |         |
+   |         borrowed value does not live long enough
+   |         using this value as a constant requires that `p` is borrowed for `'static`
+LL |     };
+   |     - `p` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/issues/issue-18118.rs b/src/test/ui/issues/issue-18118.rs
new file mode 100644
index 0000000..f58a3de
--- /dev/null
+++ b/src/test/ui/issues/issue-18118.rs
@@ -0,0 +1,6 @@
+pub fn main() {
+    const z: &'static isize = {
+        let p = 3;
+        &p //~ ERROR `p` does not live long enough
+    };
+}
diff --git a/src/test/ui/issues/issue-18118.stderr b/src/test/ui/issues/issue-18118.stderr
new file mode 100644
index 0000000..07fa1f6
--- /dev/null
+++ b/src/test/ui/issues/issue-18118.stderr
@@ -0,0 +1,13 @@
+error[E0597]: `p` does not live long enough
+  --> $DIR/issue-18118.rs:4:10
+   |
+LL |         &p
+   |          ^ borrowed value does not live long enough
+LL |     };
+   |     - borrowed value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/issues/issue-18119.rs b/src/test/ui/issues/issue-18119.rs
new file mode 100644
index 0000000..e48dc51
--- /dev/null
+++ b/src/test/ui/issues/issue-18119.rs
@@ -0,0 +1,12 @@
+const X: u8 = 1;
+static Y: u8 = 1;
+fn foo() {}
+
+impl X {}
+//~^ ERROR expected type, found constant `X`
+impl Y {}
+//~^ ERROR expected type, found static `Y`
+impl foo {}
+//~^ ERROR expected type, found function `foo`
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-18119.stderr b/src/test/ui/issues/issue-18119.stderr
new file mode 100644
index 0000000..ddee5a9
--- /dev/null
+++ b/src/test/ui/issues/issue-18119.stderr
@@ -0,0 +1,21 @@
+error[E0573]: expected type, found constant `X`
+  --> $DIR/issue-18119.rs:5:6
+   |
+LL | impl X {}
+   |      ^ not a type
+
+error[E0573]: expected type, found static `Y`
+  --> $DIR/issue-18119.rs:7:6
+   |
+LL | impl Y {}
+   |      ^ not a type
+
+error[E0573]: expected type, found function `foo`
+  --> $DIR/issue-18119.rs:9:6
+   |
+LL | impl foo {}
+   |      ^^^ not a type
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0573`.
diff --git a/src/test/ui/issues/issue-18159.rs b/src/test/ui/issues/issue-18159.rs
new file mode 100644
index 0000000..bd347d6
--- /dev/null
+++ b/src/test/ui/issues/issue-18159.rs
@@ -0,0 +1,3 @@
+fn main() {
+    let x; //~ ERROR type annotations needed
+}
diff --git a/src/test/ui/issues/issue-18159.stderr b/src/test/ui/issues/issue-18159.stderr
new file mode 100644
index 0000000..6048344
--- /dev/null
+++ b/src/test/ui/issues/issue-18159.stderr
@@ -0,0 +1,12 @@
+error[E0282]: type annotations needed
+  --> $DIR/issue-18159.rs:2:9
+   |
+LL |     let x;
+   |         ^
+   |         |
+   |         cannot infer type
+   |         consider giving `x` a type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/issues/issue-18183.rs b/src/test/ui/issues/issue-18183.rs
new file mode 100644
index 0000000..64476d1
--- /dev/null
+++ b/src/test/ui/issues/issue-18183.rs
@@ -0,0 +1,3 @@
+pub struct Foo<Bar=Bar>(Bar); //~ ERROR E0128
+pub struct Baz(Foo);
+fn main() {}
diff --git a/src/test/ui/issues/issue-18183.stderr b/src/test/ui/issues/issue-18183.stderr
new file mode 100644
index 0000000..c8f8ac9
--- /dev/null
+++ b/src/test/ui/issues/issue-18183.stderr
@@ -0,0 +1,9 @@
+error[E0128]: type parameters with a default cannot use forward declared identifiers
+  --> $DIR/issue-18183.rs:1:20
+   |
+LL | pub struct Foo<Bar=Bar>(Bar);
+   |                    ^^^ defaulted type parameters cannot be forward declared
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0128`.
diff --git a/src/test/ui/issues/issue-18188.rs b/src/test/ui/issues/issue-18188.rs
new file mode 100644
index 0000000..8e39dc1
--- /dev/null
+++ b/src/test/ui/issues/issue-18188.rs
@@ -0,0 +1,22 @@
+// compile-pass
+// pretty-expanded FIXME #23616
+
+pub trait Promisable: Send + Sync {}
+impl<T: Send + Sync> Promisable for T {}
+
+pub fn propagate<'a, T, E, F, G>(mut action: F)
+    -> Box<FnMut(Result<T, E>) -> Result<T, E> + 'a>
+    where
+        T: Promisable + Clone + 'a,
+        E: Promisable + Clone + 'a,
+        F: FnMut(&T) -> Result<T, E> + Send + 'a,
+        G: FnMut(Result<T, E>) -> Result<T, E> + 'a {
+    Box::new(move |result: Result<T, E>| {
+        match result {
+            Ok(ref t) => action(t),
+            Err(ref e) => Err(e.clone()),
+        }
+    })
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-1821.rs b/src/test/ui/issues/issue-1821.rs
new file mode 100644
index 0000000..0177b70
--- /dev/null
+++ b/src/test/ui/issues/issue-1821.rs
@@ -0,0 +1,13 @@
+// compile-pass
+#![allow(dead_code)]
+#![allow(non_camel_case_types)]
+
+// Issue #1821 - Don't recurse trying to typecheck this
+
+
+// pretty-expanded FIXME #23616
+
+enum t {
+    foo(Vec<t>)
+}
+pub fn main() {}
diff --git a/src/test/ui/issues/issue-18294.rs b/src/test/ui/issues/issue-18294.rs
new file mode 100644
index 0000000..1c2229f
--- /dev/null
+++ b/src/test/ui/issues/issue-18294.rs
@@ -0,0 +1,5 @@
+fn main() {
+    const X: u32 = 1;
+    const Y: usize = unsafe { &X as *const u32 as usize }; //~ ERROR is unstable
+    println!("{}", Y);
+}
diff --git a/src/test/ui/issues/issue-18294.stderr b/src/test/ui/issues/issue-18294.stderr
new file mode 100644
index 0000000..a7d0392
--- /dev/null
+++ b/src/test/ui/issues/issue-18294.stderr
@@ -0,0 +1,11 @@
+error[E0658]: casting pointers to integers in constants is unstable (see issue #51910)
+  --> $DIR/issue-18294.rs:3:31
+   |
+LL |     const Y: usize = unsafe { &X as *const u32 as usize };
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_raw_ptr_to_usize_cast)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/issues/issue-18389.rs b/src/test/ui/issues/issue-18389.rs
new file mode 100644
index 0000000..654dfb6
--- /dev/null
+++ b/src/test/ui/issues/issue-18389.rs
@@ -0,0 +1,18 @@
+use std::any::Any;
+use std::any::TypeId;
+
+trait Private<P, R> {
+    fn call(&self, p: P, r: R);
+}
+pub trait Public: Private<
+//~^ ERROR private trait `Private<<Self as Public>::P, <Self as Public>::R>` in public interface
+    <Self as Public>::P,
+    <Self as Public>::R
+> {
+    type P;
+    type R;
+
+    fn call_inner(&self);
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-18389.stderr b/src/test/ui/issues/issue-18389.stderr
new file mode 100644
index 0000000..090487e
--- /dev/null
+++ b/src/test/ui/issues/issue-18389.stderr
@@ -0,0 +1,18 @@
+error[E0445]: private trait `Private<<Self as Public>::P, <Self as Public>::R>` in public interface
+  --> $DIR/issue-18389.rs:7:1
+   |
+LL |   trait Private<P, R> {
+   |   - `Private<<Self as Public>::P, <Self as Public>::R>` declared as private
+...
+LL | / pub trait Public: Private<
+LL | |
+LL | |     <Self as Public>::P,
+LL | |     <Self as Public>::R
+...  |
+LL | |     fn call_inner(&self);
+LL | | }
+   | |_^ can't leak private trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0445`.
diff --git a/src/test/ui/issues/issue-18400.rs b/src/test/ui/issues/issue-18400.rs
new file mode 100644
index 0000000..fdd1151
--- /dev/null
+++ b/src/test/ui/issues/issue-18400.rs
@@ -0,0 +1,26 @@
+trait Set<T> {
+    fn contains(&self, _: T) -> bool;
+    fn set(&mut self, _: T);
+}
+
+impl<'a, T, S> Set<&'a [T]> for S where
+    T: Copy,
+    S: Set<T>,
+{
+    fn contains(&self, bits: &[T]) -> bool {
+        bits.iter().all(|&bit| self.contains(bit))
+    }
+
+    fn set(&mut self, bits: &[T]) {
+        for &bit in bits {
+            self.set(bit)
+        }
+    }
+}
+
+fn main() {
+    let bits: &[_] = &[0, 1];
+
+    0.contains(bits);
+    //~^ ERROR overflow
+}
diff --git a/src/test/ui/issues/issue-18400.stderr b/src/test/ui/issues/issue-18400.stderr
new file mode 100644
index 0000000..9c496ca
--- /dev/null
+++ b/src/test/ui/issues/issue-18400.stderr
@@ -0,0 +1,75 @@
+error[E0275]: overflow evaluating the requirement `_: std::marker::Sized`
+  --> $DIR/issue-18400.rs:24:7
+   |
+LL |     0.contains(bits);
+   |       ^^^^^^^^
+   |
+   = help: consider adding a `#![recursion_limit="128"]` attribute to your crate
+   = note: required because of the requirements on the impl of `Set<&[_]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[_]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[_]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[_]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[_]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[_]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[_]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[_]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[_]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/src/test/ui/issues/issue-18423.rs b/src/test/ui/issues/issue-18423.rs
new file mode 100644
index 0000000..c072e6b
--- /dev/null
+++ b/src/test/ui/issues/issue-18423.rs
@@ -0,0 +1,8 @@
+// Test that `Box` cannot be used with a lifetime argument.
+
+struct Foo<'a> {
+    x: Box<'a, isize> //~ ERROR wrong number of lifetime arguments
+}
+
+pub fn main() {
+}
diff --git a/src/test/ui/issues/issue-18423.stderr b/src/test/ui/issues/issue-18423.stderr
new file mode 100644
index 0000000..141fd27
--- /dev/null
+++ b/src/test/ui/issues/issue-18423.stderr
@@ -0,0 +1,9 @@
+error[E0107]: wrong number of lifetime arguments: expected 0, found 1
+  --> $DIR/issue-18423.rs:4:12
+   |
+LL |     x: Box<'a, isize>
+   |            ^^ unexpected lifetime argument
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0107`.
diff --git a/src/test/ui/issues/issue-18446-2.rs b/src/test/ui/issues/issue-18446-2.rs
new file mode 100644
index 0000000..2f05ece
--- /dev/null
+++ b/src/test/ui/issues/issue-18446-2.rs
@@ -0,0 +1,13 @@
+// compile-pass
+#![allow(dead_code)]
+// Test that methods in trait impls should override default methods.
+
+trait T {
+    fn foo(&self) -> i32 { 0 }
+}
+
+impl<'a> T + 'a {
+    fn foo(&self) -> i32 { 1 }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-18446.rs b/src/test/ui/issues/issue-18446.rs
new file mode 100644
index 0000000..64c89df
--- /dev/null
+++ b/src/test/ui/issues/issue-18446.rs
@@ -0,0 +1,19 @@
+// Test that name clashes between the method in an impl for the type
+// and the method in the trait when both are in the same scope.
+
+trait T {
+    fn foo(&self);
+}
+
+impl<'a> T + 'a {
+    fn foo(&self) {}
+}
+
+impl T for i32 {
+    fn foo(&self) {}
+}
+
+fn main() {
+    let x: &T = &0i32;
+    x.foo(); //~ ERROR multiple applicable items in scope [E0034]
+}
diff --git a/src/test/ui/issues/issue-18446.stderr b/src/test/ui/issues/issue-18446.stderr
new file mode 100644
index 0000000..e6afc4c
--- /dev/null
+++ b/src/test/ui/issues/issue-18446.stderr
@@ -0,0 +1,21 @@
+error[E0034]: multiple applicable items in scope
+  --> $DIR/issue-18446.rs:18:7
+   |
+LL |     x.foo();
+   |       ^^^ multiple `foo` found
+   |
+note: candidate #1 is defined in an impl for the type `dyn T`
+  --> $DIR/issue-18446.rs:9:5
+   |
+LL |     fn foo(&self) {}
+   |     ^^^^^^^^^^^^^
+note: candidate #2 is defined in the trait `T`
+  --> $DIR/issue-18446.rs:5:5
+   |
+LL |     fn foo(&self);
+   |     ^^^^^^^^^^^^^^
+   = help: to disambiguate the method call, write `T::foo(&x)` instead
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0034`.
diff --git a/src/test/ui/issues/issue-18532.rs b/src/test/ui/issues/issue-18532.rs
new file mode 100644
index 0000000..31fd879
--- /dev/null
+++ b/src/test/ui/issues/issue-18532.rs
@@ -0,0 +1,7 @@
+// Test that overloaded call parameter checking does not ICE
+// when a type error or unconstrained type variable propagates
+// into it.
+
+fn main() {
+    (return)((),()); //~ ERROR expected function, found `!`
+}
diff --git a/src/test/ui/issues/issue-18532.stderr b/src/test/ui/issues/issue-18532.stderr
new file mode 100644
index 0000000..4c224eb
--- /dev/null
+++ b/src/test/ui/issues/issue-18532.stderr
@@ -0,0 +1,11 @@
+error[E0618]: expected function, found `!`
+  --> $DIR/issue-18532.rs:6:5
+   |
+LL |     (return)((),());
+   |     ^^^^^^^^-------
+   |     |
+   |     call expression requires function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0618`.
diff --git a/src/test/ui/issues/issue-18566.nll.stderr b/src/test/ui/issues/issue-18566.nll.stderr
new file mode 100644
index 0000000..8db7893
--- /dev/null
+++ b/src/test/ui/issues/issue-18566.nll.stderr
@@ -0,0 +1,12 @@
+error[E0499]: cannot borrow `*s` as mutable more than once at a time
+  --> $DIR/issue-18566.rs:23:19
+   |
+LL |     MyPtr(s).poke(s);
+   |           -  ---- ^ second mutable borrow occurs here
+   |           |  |
+   |           |  first borrow later used by call
+   |           first mutable borrow occurs here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/issues/issue-18566.rs b/src/test/ui/issues/issue-18566.rs
new file mode 100644
index 0000000..9da904a
--- /dev/null
+++ b/src/test/ui/issues/issue-18566.rs
@@ -0,0 +1,25 @@
+use std::ops::Deref;
+
+struct MyPtr<'a>(&'a mut usize);
+impl<'a> Deref for MyPtr<'a> {
+    type Target = usize;
+
+    fn deref<'b>(&'b self) -> &'b usize { self.0 }
+}
+
+trait Tr {
+    fn poke(&self, s: &mut usize);
+}
+
+impl Tr for usize {
+    fn poke(&self, s: &mut usize)  {
+        *s = 2;
+    }
+}
+
+fn main() {
+    let s = &mut 1;
+
+    MyPtr(s).poke(s);
+    //~^ ERROR cannot borrow `*s` as mutable more than once at a time
+}
diff --git a/src/test/ui/issues/issue-18566.stderr b/src/test/ui/issues/issue-18566.stderr
new file mode 100644
index 0000000..90c3af4
--- /dev/null
+++ b/src/test/ui/issues/issue-18566.stderr
@@ -0,0 +1,12 @@
+error[E0499]: cannot borrow `*s` as mutable more than once at a time
+  --> $DIR/issue-18566.rs:23:19
+   |
+LL |     MyPtr(s).poke(s);
+   |           -       ^- first borrow ends here
+   |           |       |
+   |           |       second mutable borrow occurs here
+   |           first mutable borrow occurs here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/issues/issue-18611.rs b/src/test/ui/issues/issue-18611.rs
new file mode 100644
index 0000000..91a765f
--- /dev/null
+++ b/src/test/ui/issues/issue-18611.rs
@@ -0,0 +1,9 @@
+fn add_state(op: <isize as HasState>::State) {
+//~^ ERROR `isize: HasState` is not satisfied
+}
+
+trait HasState {
+    type State;
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-18611.stderr b/src/test/ui/issues/issue-18611.stderr
new file mode 100644
index 0000000..22c3470
--- /dev/null
+++ b/src/test/ui/issues/issue-18611.stderr
@@ -0,0 +1,11 @@
+error[E0277]: the trait bound `isize: HasState` is not satisfied
+  --> $DIR/issue-18611.rs:1:1
+   |
+LL | / fn add_state(op: <isize as HasState>::State) {
+LL | |
+LL | | }
+   | |_^ the trait `HasState` is not implemented for `isize`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-1866.rs b/src/test/ui/issues/issue-1866.rs
new file mode 100644
index 0000000..3de547b
--- /dev/null
+++ b/src/test/ui/issues/issue-1866.rs
@@ -0,0 +1,27 @@
+// compile-pass
+#![allow(dead_code)]
+#![allow(non_camel_case_types)]
+
+// pretty-expanded FIXME #23616
+
+mod a {
+    pub type rust_task = usize;
+    pub mod rustrt {
+        use super::rust_task;
+        extern {
+            pub fn rust_task_is_unwinding(rt: *const rust_task) -> bool;
+        }
+    }
+}
+
+mod b {
+    pub type rust_task = bool;
+    pub mod rustrt {
+        use super::rust_task;
+        extern {
+            pub fn rust_task_is_unwinding(rt: *const rust_task) -> bool;
+        }
+    }
+}
+
+pub fn main() { }
diff --git a/src/test/ui/issues/issue-1871.rs b/src/test/ui/issues/issue-1871.rs
new file mode 100644
index 0000000..f7a2bdd
--- /dev/null
+++ b/src/test/ui/issues/issue-1871.rs
@@ -0,0 +1,12 @@
+// Tests that we don't generate a spurious error about f.honk's type
+// being undeterminable
+fn main() {
+  let f = 42;
+
+  let _g = if f < 5 {
+      f.honk() //~ ERROR no method named `honk` found
+  }
+  else {
+      ()
+  };
+}
diff --git a/src/test/ui/issues/issue-1871.stderr b/src/test/ui/issues/issue-1871.stderr
new file mode 100644
index 0000000..fecd689
--- /dev/null
+++ b/src/test/ui/issues/issue-1871.stderr
@@ -0,0 +1,9 @@
+error[E0599]: no method named `honk` found for type `{integer}` in the current scope
+  --> $DIR/issue-1871.rs:7:9
+   |
+LL |       f.honk()
+   |         ^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/issues/issue-18738.rs b/src/test/ui/issues/issue-18738.rs
new file mode 100644
index 0000000..c3bd022
--- /dev/null
+++ b/src/test/ui/issues/issue-18738.rs
@@ -0,0 +1,17 @@
+// compile-pass
+#![allow(dead_code)]
+#[derive(Eq, PartialEq, PartialOrd, Ord)]
+enum Test<'a> {
+    Int(&'a isize),
+    Slice(&'a [u8]),
+}
+
+#[derive(Eq, PartialEq, PartialOrd, Ord)]
+struct Version {
+    vendor_info: &'static str
+}
+
+#[derive(Eq, PartialEq, PartialOrd, Ord)]
+struct Foo(&'static str);
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-18783.nll.stderr b/src/test/ui/issues/issue-18783.nll.stderr
new file mode 100644
index 0000000..047b425
--- /dev/null
+++ b/src/test/ui/issues/issue-18783.nll.stderr
@@ -0,0 +1,33 @@
+error[E0499]: cannot borrow `y` as mutable more than once at a time
+  --> $DIR/issue-18783.rs:7:21
+   |
+LL |     c.push(Box::new(|| y = 0));
+   |                     -- - first borrow occurs due to use of `y` in closure
+   |                     |
+   |                     first mutable borrow occurs here
+LL |     c.push(Box::new(|| y = 0));
+   |                     ^^ - second borrow occurs due to use of `y` in closure
+   |                     |
+   |                     second mutable borrow occurs here
+LL |
+LL | }
+   | - first borrow might be used here, when `c` is dropped and runs the destructor for type `std::cell::RefCell<std::vec::Vec<std::boxed::Box<dyn std::ops::FnMut()>>>`
+
+error[E0499]: cannot borrow `y` as mutable more than once at a time
+  --> $DIR/issue-18783.rs:16:29
+   |
+LL |     Push::push(&c, Box::new(|| y = 0));
+   |                             -- - first borrow occurs due to use of `y` in closure
+   |                             |
+   |                             first mutable borrow occurs here
+LL |     Push::push(&c, Box::new(|| y = 0));
+   |                             ^^ - second borrow occurs due to use of `y` in closure
+   |                             |
+   |                             second mutable borrow occurs here
+LL |
+LL | }
+   | - first borrow might be used here, when `c` is dropped and runs the destructor for type `std::cell::RefCell<std::vec::Vec<std::boxed::Box<dyn std::ops::FnMut()>>>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/issues/issue-18783.rs b/src/test/ui/issues/issue-18783.rs
new file mode 100644
index 0000000..b84a1ad
--- /dev/null
+++ b/src/test/ui/issues/issue-18783.rs
@@ -0,0 +1,28 @@
+use std::cell::RefCell;
+
+fn main() {
+    let mut y = 1;
+    let c = RefCell::new(vec![]);
+    c.push(Box::new(|| y = 0));
+    c.push(Box::new(|| y = 0));
+//~^ ERROR cannot borrow `y` as mutable more than once at a time
+}
+
+fn ufcs() {
+    let mut y = 1;
+    let c = RefCell::new(vec![]);
+
+    Push::push(&c, Box::new(|| y = 0));
+    Push::push(&c, Box::new(|| y = 0));
+//~^ ERROR cannot borrow `y` as mutable more than once at a time
+}
+
+trait Push<'c> {
+    fn push<'f: 'c>(&self, push: Box<FnMut() + 'f>);
+}
+
+impl<'c> Push<'c> for RefCell<Vec<Box<FnMut() + 'c>>> {
+    fn push<'f: 'c>(&self, fun: Box<FnMut() + 'f>) {
+        self.borrow_mut().push(fun)
+    }
+}
diff --git a/src/test/ui/issues/issue-18783.stderr b/src/test/ui/issues/issue-18783.stderr
new file mode 100644
index 0000000..f88c425
--- /dev/null
+++ b/src/test/ui/issues/issue-18783.stderr
@@ -0,0 +1,33 @@
+error[E0499]: cannot borrow `y` as mutable more than once at a time
+  --> $DIR/issue-18783.rs:7:21
+   |
+LL |     c.push(Box::new(|| y = 0));
+   |                     -- - previous borrow occurs due to use of `y` in closure
+   |                     |
+   |                     first mutable borrow occurs here
+LL |     c.push(Box::new(|| y = 0));
+   |                     ^^ - borrow occurs due to use of `y` in closure
+   |                     |
+   |                     second mutable borrow occurs here
+LL |
+LL | }
+   | - first borrow ends here
+
+error[E0499]: cannot borrow `y` as mutable more than once at a time
+  --> $DIR/issue-18783.rs:16:29
+   |
+LL |     Push::push(&c, Box::new(|| y = 0));
+   |                             -- - previous borrow occurs due to use of `y` in closure
+   |                             |
+   |                             first mutable borrow occurs here
+LL |     Push::push(&c, Box::new(|| y = 0));
+   |                             ^^ - borrow occurs due to use of `y` in closure
+   |                             |
+   |                             second mutable borrow occurs here
+LL |
+LL | }
+   | - first borrow ends here
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/issues/issue-18809.rs b/src/test/ui/issues/issue-18809.rs
new file mode 100644
index 0000000..fb31666
--- /dev/null
+++ b/src/test/ui/issues/issue-18809.rs
@@ -0,0 +1,12 @@
+// compile-pass
+trait Tup {
+    type T0;
+    type T1;
+}
+
+impl Tup for isize {
+    type T0 = f32;
+    type T1 = ();
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-18819.rs b/src/test/ui/issues/issue-18819.rs
new file mode 100644
index 0000000..80db056
--- /dev/null
+++ b/src/test/ui/issues/issue-18819.rs
@@ -0,0 +1,18 @@
+trait Foo {
+    type Item;
+}
+
+struct X;
+
+impl Foo for X {
+    type Item = bool;
+}
+
+fn print_x(_: &Foo<Item=bool>, extra: &str) {
+    println!("{}", extra);
+}
+
+fn main() {
+    print_x(X);
+    //~^ ERROR E0061
+}
diff --git a/src/test/ui/issues/issue-18819.stderr b/src/test/ui/issues/issue-18819.stderr
new file mode 100644
index 0000000..eb7e4ad
--- /dev/null
+++ b/src/test/ui/issues/issue-18819.stderr
@@ -0,0 +1,12 @@
+error[E0061]: this function takes 2 parameters but 1 parameter was supplied
+  --> $DIR/issue-18819.rs:16:5
+   |
+LL | fn print_x(_: &Foo<Item=bool>, extra: &str) {
+   | ------------------------------------------- defined here
+...
+LL |     print_x(X);
+   |     ^^^^^^^^^^ expected 2 parameters
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0061`.
diff --git a/src/test/ui/issues/issue-18906.rs b/src/test/ui/issues/issue-18906.rs
new file mode 100644
index 0000000..0b9625b1
--- /dev/null
+++ b/src/test/ui/issues/issue-18906.rs
@@ -0,0 +1,30 @@
+// compile-pass
+#![allow(dead_code)]
+// pretty-expanded FIXME #23616
+
+pub trait Borrow<Borrowed: ?Sized> {
+        fn borrow(&self) -> &Borrowed;
+}
+
+impl<T: Sized> Borrow<T> for T {
+        fn borrow(&self) -> &T { self }
+}
+
+trait Foo {
+        fn foo(&self, other: &Self);
+}
+
+fn bar<K, Q>(k: &K, q: &Q) where K: Borrow<Q>, Q: Foo {
+    q.foo(k.borrow())
+}
+
+struct MyTree<K>(K);
+
+impl<K> MyTree<K> {
+    // This caused a failure in #18906
+    fn bar<Q>(k: &K, q: &Q) where K: Borrow<Q>, Q: Foo {
+        q.foo(k.borrow())
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-18919.rs b/src/test/ui/issues/issue-18919.rs
new file mode 100644
index 0000000..9db3084
--- /dev/null
+++ b/src/test/ui/issues/issue-18919.rs
@@ -0,0 +1,7 @@
+type FuncType<'f> = Fn(&isize) -> isize + 'f;
+
+fn ho_func(f: Option<FuncType>) {
+    //~^ ERROR the size for values of type
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-18919.stderr b/src/test/ui/issues/issue-18919.stderr
new file mode 100644
index 0000000..8752865
--- /dev/null
+++ b/src/test/ui/issues/issue-18919.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the size for values of type `dyn for<'r> std::ops::Fn(&'r isize) -> isize` cannot be known at compilation time
+  --> $DIR/issue-18919.rs:3:1
+   |
+LL | / fn ho_func(f: Option<FuncType>) {
+LL | |
+LL | | }
+   | |_^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `dyn for<'r> std::ops::Fn(&'r isize) -> isize`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: required by `std::option::Option`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-18937.rs b/src/test/ui/issues/issue-18937.rs
new file mode 100644
index 0000000..f382476
--- /dev/null
+++ b/src/test/ui/issues/issue-18937.rs
@@ -0,0 +1,40 @@
+// Regression test for #18937.
+
+use std::fmt;
+
+#[derive(Debug)]
+struct MyString<'a>(&'a String);
+
+struct B {
+    list: Vec<Box<fmt::Debug>>,
+}
+
+trait A<'a> {
+    fn foo<F>(&mut self, f: F)
+        where F: fmt::Debug + 'a,
+              Self: Sized;
+}
+
+impl<'a> A<'a> for B {
+    fn foo<F>(&mut self, f: F) //~ ERROR impl has stricter
+        where F: fmt::Debug + 'static,
+    {
+        self.list.push(Box::new(f));
+    }
+}
+
+fn main() {
+    let mut b = B { list: Vec::new() };
+
+    // Create a borrowed pointer, put it in `b`, then drop what's borrowing it
+    let a = "hello".to_string();
+    b.foo(MyString(&a));
+
+    // Drop the data which `b` has a reference to
+    drop(a);
+
+    // Use the data, probably segfaulting
+    for b in b.list.iter() {
+        println!("{:?}", b);
+    }
+}
diff --git a/src/test/ui/issues/issue-18937.stderr b/src/test/ui/issues/issue-18937.stderr
new file mode 100644
index 0000000..ac302ca
--- /dev/null
+++ b/src/test/ui/issues/issue-18937.stderr
@@ -0,0 +1,18 @@
+error[E0276]: impl has stricter requirements than trait
+  --> $DIR/issue-18937.rs:19:5
+   |
+LL | /     fn foo<F>(&mut self, f: F)
+LL | |         where F: fmt::Debug + 'a,
+LL | |               Self: Sized;
+   | |__________________________- definition of `foo` from trait
+...
+LL | /     fn foo<F>(&mut self, f: F)
+LL | |         where F: fmt::Debug + 'static,
+LL | |     {
+LL | |         self.list.push(Box::new(f));
+LL | |     }
+   | |_____^ impl has extra requirement `F: 'static`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0276`.
diff --git a/src/test/ui/issues/issue-18959.rs b/src/test/ui/issues/issue-18959.rs
new file mode 100644
index 0000000..b078009
--- /dev/null
+++ b/src/test/ui/issues/issue-18959.rs
@@ -0,0 +1,20 @@
+pub trait Foo { fn foo<T>(&self, ext_thing: &T); }
+pub trait Bar: Foo { }
+impl<T: Foo> Bar for T { }
+
+pub struct Thing;
+impl Foo for Thing {
+    fn foo<T>(&self, _: &T) {}
+}
+
+#[inline(never)]
+fn foo(b: &Bar) {
+    //~^ ERROR E0038
+    b.foo(&0)
+}
+
+fn main() {
+    let mut thing = Thing;
+    let test: &Bar = &mut thing;
+    foo(test);
+}
diff --git a/src/test/ui/issues/issue-18959.stderr b/src/test/ui/issues/issue-18959.stderr
new file mode 100644
index 0000000..9393901
--- /dev/null
+++ b/src/test/ui/issues/issue-18959.stderr
@@ -0,0 +1,11 @@
+error[E0038]: the trait `Bar` cannot be made into an object
+  --> $DIR/issue-18959.rs:11:1
+   |
+LL | fn foo(b: &Bar) {
+   | ^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object
+   |
+   = note: method `foo` has generic type parameters
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/issues/issue-18988.rs b/src/test/ui/issues/issue-18988.rs
new file mode 100644
index 0000000..e039348
--- /dev/null
+++ b/src/test/ui/issues/issue-18988.rs
@@ -0,0 +1,11 @@
+// compile-pass
+#![allow(dead_code)]
+pub trait Foo : Send { }
+
+pub struct MyFoo {
+    children: Vec<Box<Foo>>,
+}
+
+impl Foo for MyFoo { }
+
+pub fn main() { }
diff --git a/src/test/ui/issues/issue-1900.rs b/src/test/ui/issues/issue-1900.rs
new file mode 100644
index 0000000..761bd31
--- /dev/null
+++ b/src/test/ui/issues/issue-1900.rs
@@ -0,0 +1,2 @@
+fn main<T>() { }
+//~^ ERROR `main` function is not allowed to have generic parameters
diff --git a/src/test/ui/issues/issue-1900.stderr b/src/test/ui/issues/issue-1900.stderr
new file mode 100644
index 0000000..ce41366
--- /dev/null
+++ b/src/test/ui/issues/issue-1900.stderr
@@ -0,0 +1,9 @@
+error[E0131]: `main` function is not allowed to have generic parameters
+  --> $DIR/issue-1900.rs:1:8
+   |
+LL | fn main<T>() { }
+   |        ^^^ `main` cannot have generic parameters
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0131`.
diff --git a/src/test/ui/issues/issue-19037.rs b/src/test/ui/issues/issue-19037.rs
new file mode 100644
index 0000000..4efc071
--- /dev/null
+++ b/src/test/ui/issues/issue-19037.rs
@@ -0,0 +1,20 @@
+// compile-pass
+#![allow(dead_code)]
+// pretty-expanded FIXME #23616
+
+struct Str([u8]);
+
+#[derive(Clone)]
+struct CharSplits<'a, Sep> {
+    string: &'a Str,
+    sep: Sep,
+    allow_trailing_empty: bool,
+    only_ascii: bool,
+    finished: bool,
+}
+
+fn clone(s: &Str) -> &Str {
+    Clone::clone(&s)
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-19081.rs b/src/test/ui/issues/issue-19081.rs
new file mode 100644
index 0000000..b487cdd
--- /dev/null
+++ b/src/test/ui/issues/issue-19081.rs
@@ -0,0 +1,14 @@
+// compile-pass
+pub trait Hasher {
+    type State;
+
+    fn hash<T: Hash<
+        <Self as Hasher>::State
+    >>(&self, value: &T) -> u64;
+}
+
+pub trait Hash<S> {
+    fn hash(&self, state: &mut S);
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-19086.rs b/src/test/ui/issues/issue-19086.rs
new file mode 100644
index 0000000..9802814
--- /dev/null
+++ b/src/test/ui/issues/issue-19086.rs
@@ -0,0 +1,13 @@
+use Foo::FooB;
+
+enum Foo {
+    FooB { x: i32, y: i32 }
+}
+
+fn main() {
+    let f = FooB { x: 3, y: 4 };
+    match f {
+        FooB(a, b) => println!("{} {}", a, b),
+        //~^ ERROR expected tuple struct/variant, found struct variant `FooB`
+    }
+}
diff --git a/src/test/ui/issues/issue-19086.stderr b/src/test/ui/issues/issue-19086.stderr
new file mode 100644
index 0000000..d2b9b90
--- /dev/null
+++ b/src/test/ui/issues/issue-19086.stderr
@@ -0,0 +1,9 @@
+error[E0532]: expected tuple struct/variant, found struct variant `FooB`
+  --> $DIR/issue-19086.rs:10:9
+   |
+LL |         FooB(a, b) => println!("{} {}", a, b),
+   |         ^^^^ did you mean `FooB { /* fields */ }`?
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0532`.
diff --git a/src/test/ui/issues/issue-19097.rs b/src/test/ui/issues/issue-19097.rs
new file mode 100644
index 0000000..8055e106
--- /dev/null
+++ b/src/test/ui/issues/issue-19097.rs
@@ -0,0 +1,14 @@
+// compile-pass
+#![allow(dead_code)]
+// regression test for #19097
+
+struct Foo<T>(T);
+
+impl<'a, T> Foo<&'a T> {
+    fn foo(&self) {}
+}
+impl<'a, T> Foo<&'a mut T> {
+    fn foo(&self) {}
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-19098.rs b/src/test/ui/issues/issue-19098.rs
new file mode 100644
index 0000000..690fe94
--- /dev/null
+++ b/src/test/ui/issues/issue-19098.rs
@@ -0,0 +1,12 @@
+// compile-pass
+pub trait Handler {
+    fn handle(&self, _: &mut String);
+}
+
+impl<F> Handler for F where F: for<'a, 'b> Fn(&'a mut String) {
+    fn handle(&self, st: &mut String) {
+        self(st)
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-19100.fixed b/src/test/ui/issues/issue-19100.fixed
new file mode 100644
index 0000000..6dc8f7d
--- /dev/null
+++ b/src/test/ui/issues/issue-19100.fixed
@@ -0,0 +1,30 @@
+// run-pass
+// run-rustfix
+
+#![allow(non_snake_case)]
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+#[derive(Copy, Clone)]
+enum Foo {
+    Bar,
+    Baz
+}
+
+impl Foo {
+    fn foo(&self) {
+        match self {
+            &
+Foo::Bar if true
+//~^ WARN pattern binding `Bar` is named the same as one of the variants of the type `Foo`
+=> println!("bar"),
+            &
+Foo::Baz if false
+//~^ WARN pattern binding `Baz` is named the same as one of the variants of the type `Foo`
+=> println!("baz"),
+_ => ()
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-19100.rs b/src/test/ui/issues/issue-19100.rs
new file mode 100644
index 0000000..cfdc7c9
--- /dev/null
+++ b/src/test/ui/issues/issue-19100.rs
@@ -0,0 +1,30 @@
+// run-pass
+// run-rustfix
+
+#![allow(non_snake_case)]
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+#[derive(Copy, Clone)]
+enum Foo {
+    Bar,
+    Baz
+}
+
+impl Foo {
+    fn foo(&self) {
+        match self {
+            &
+Bar if true
+//~^ WARN pattern binding `Bar` is named the same as one of the variants of the type `Foo`
+=> println!("bar"),
+            &
+Baz if false
+//~^ WARN pattern binding `Baz` is named the same as one of the variants of the type `Foo`
+=> println!("baz"),
+_ => ()
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-19100.stderr b/src/test/ui/issues/issue-19100.stderr
new file mode 100644
index 0000000..1ab1347
--- /dev/null
+++ b/src/test/ui/issues/issue-19100.stderr
@@ -0,0 +1,12 @@
+warning[E0170]: pattern binding `Bar` is named the same as one of the variants of the type `Foo`
+  --> $DIR/issue-19100.rs:18:1
+   |
+LL | Bar if true
+   | ^^^ help: to match on the variant, qualify the path: `Foo::Bar`
+
+warning[E0170]: pattern binding `Baz` is named the same as one of the variants of the type `Foo`
+  --> $DIR/issue-19100.rs:22:1
+   |
+LL | Baz if false
+   | ^^^ help: to match on the variant, qualify the path: `Foo::Baz`
+
diff --git a/src/test/ui/issues/issue-19102.rs b/src/test/ui/issues/issue-19102.rs
new file mode 100644
index 0000000..962cd8d
--- /dev/null
+++ b/src/test/ui/issues/issue-19102.rs
@@ -0,0 +1,12 @@
+// compile-pass
+#![allow(unused_imports)]
+#![deny(unused_qualifications)]
+
+use self::A::B;
+
+#[derive(PartialEq)]
+pub enum A {
+    B,
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-19129-1.rs b/src/test/ui/issues/issue-19129-1.rs
new file mode 100644
index 0000000..4be2cc6
--- /dev/null
+++ b/src/test/ui/issues/issue-19129-1.rs
@@ -0,0 +1,16 @@
+// compile-pass
+// pretty-expanded FIXME #23616
+
+trait Trait<Input> {
+    type Output;
+
+    fn method() -> <Self as Trait<Input>>::Output;
+}
+
+impl<T> Trait<T> for () {
+    type Output = ();
+
+    fn method() {}
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-19129-2.rs b/src/test/ui/issues/issue-19129-2.rs
new file mode 100644
index 0000000..d11ef8a
--- /dev/null
+++ b/src/test/ui/issues/issue-19129-2.rs
@@ -0,0 +1,11 @@
+// compile-pass
+#![allow(unused_variables)]
+// pretty-expanded FIXME #23616
+
+trait Trait<Input> {
+    type Output;
+
+    fn method(&self, i: Input) -> bool { false }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-19163.nll.stderr b/src/test/ui/issues/issue-19163.nll.stderr
new file mode 100644
index 0000000..af509aa
--- /dev/null
+++ b/src/test/ui/issues/issue-19163.nll.stderr
@@ -0,0 +1,9 @@
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/issue-19163.rs:9:14
+   |
+LL |     mywrite!(&v, "Hello world");
+   |              ^^ cannot borrow as mutable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/issues/issue-19163.rs b/src/test/ui/issues/issue-19163.rs
new file mode 100644
index 0000000..20d3244
--- /dev/null
+++ b/src/test/ui/issues/issue-19163.rs
@@ -0,0 +1,11 @@
+// aux-build:issue-19163.rs
+
+#[macro_use] extern crate issue_19163;
+
+use std::io::Write;
+
+fn main() {
+    let mut v = vec![];
+    mywrite!(&v, "Hello world");
+ //~^ error: cannot borrow immutable borrowed content as mutable
+}
diff --git a/src/test/ui/issues/issue-19163.stderr b/src/test/ui/issues/issue-19163.stderr
new file mode 100644
index 0000000..242ceae
--- /dev/null
+++ b/src/test/ui/issues/issue-19163.stderr
@@ -0,0 +1,9 @@
+error[E0596]: cannot borrow immutable borrowed content as mutable
+  --> $DIR/issue-19163.rs:9:14
+   |
+LL |     mywrite!(&v, "Hello world");
+   |              ^^ cannot borrow as mutable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/issues/issue-1920-1.rs b/src/test/ui/issues/issue-1920-1.rs
new file mode 100644
index 0000000..996052d
--- /dev/null
+++ b/src/test/ui/issues/issue-1920-1.rs
@@ -0,0 +1,14 @@
+//! Test that absolute path names are correct when a crate is not linked into the root namespace
+
+// aux-build:issue-1920.rs
+
+mod foo {
+    pub extern crate issue_1920;
+}
+
+fn assert_clone<T>() where T : Clone { }
+
+fn main() {
+    assert_clone::<foo::issue_1920::S>();
+    //~^ ERROR `foo::issue_1920::S: std::clone::Clone` is not satisfied
+}
diff --git a/src/test/ui/issues/issue-1920-1.stderr b/src/test/ui/issues/issue-1920-1.stderr
new file mode 100644
index 0000000..b3ac050
--- /dev/null
+++ b/src/test/ui/issues/issue-1920-1.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `foo::issue_1920::S: std::clone::Clone` is not satisfied
+  --> $DIR/issue-1920-1.rs:12:5
+   |
+LL |     assert_clone::<foo::issue_1920::S>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::clone::Clone` is not implemented for `foo::issue_1920::S`
+   |
+note: required by `assert_clone`
+  --> $DIR/issue-1920-1.rs:9:1
+   |
+LL | fn assert_clone<T>() where T : Clone { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-1920-2.rs b/src/test/ui/issues/issue-1920-2.rs
new file mode 100644
index 0000000..56d842e
--- /dev/null
+++ b/src/test/ui/issues/issue-1920-2.rs
@@ -0,0 +1,12 @@
+//! Test that when a crate is linked under another name that name is used in global paths
+
+// aux-build:issue-1920.rs
+
+extern crate issue_1920 as bar;
+
+fn assert_clone<T>() where T : Clone { }
+
+fn main() {
+    assert_clone::<bar::S>();
+    //~^ ERROR `bar::S: std::clone::Clone` is not satisfied
+}
diff --git a/src/test/ui/issues/issue-1920-2.stderr b/src/test/ui/issues/issue-1920-2.stderr
new file mode 100644
index 0000000..a000a87
--- /dev/null
+++ b/src/test/ui/issues/issue-1920-2.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `bar::S: std::clone::Clone` is not satisfied
+  --> $DIR/issue-1920-2.rs:10:5
+   |
+LL |     assert_clone::<bar::S>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^ the trait `std::clone::Clone` is not implemented for `bar::S`
+   |
+note: required by `assert_clone`
+  --> $DIR/issue-1920-2.rs:7:1
+   |
+LL | fn assert_clone<T>() where T : Clone { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-1920-3.rs b/src/test/ui/issues/issue-1920-3.rs
new file mode 100644
index 0000000..83f3fdb
--- /dev/null
+++ b/src/test/ui/issues/issue-1920-3.rs
@@ -0,0 +1,16 @@
+//! Test that when a crate is linked multiple times that the shortest absolute path name is used
+
+// aux-build:issue-1920.rs
+
+mod foo {
+    pub extern crate issue_1920;
+}
+
+extern crate issue_1920;
+
+fn assert_clone<T>() where T : Clone { }
+
+fn main() {
+    assert_clone::<foo::issue_1920::S>();
+    //~^ ERROR `issue_1920::S: std::clone::Clone` is not satisfied
+}
diff --git a/src/test/ui/issues/issue-1920-3.stderr b/src/test/ui/issues/issue-1920-3.stderr
new file mode 100644
index 0000000..62e47a6
--- /dev/null
+++ b/src/test/ui/issues/issue-1920-3.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `issue_1920::S: std::clone::Clone` is not satisfied
+  --> $DIR/issue-1920-3.rs:14:5
+   |
+LL |     assert_clone::<foo::issue_1920::S>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::clone::Clone` is not implemented for `issue_1920::S`
+   |
+note: required by `assert_clone`
+  --> $DIR/issue-1920-3.rs:11:1
+   |
+LL | fn assert_clone<T>() where T : Clone { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-19244-1.rs b/src/test/ui/issues/issue-19244-1.rs
new file mode 100644
index 0000000..77fab7c
--- /dev/null
+++ b/src/test/ui/issues/issue-19244-1.rs
@@ -0,0 +1,6 @@
+const TUP: (usize,) = (42,);
+
+fn main() {
+    let a: [isize; TUP.1];
+    //~^ ERROR no field `1` on type `(usize,)`
+}
diff --git a/src/test/ui/issues/issue-19244-1.stderr b/src/test/ui/issues/issue-19244-1.stderr
new file mode 100644
index 0000000..1eb5305
--- /dev/null
+++ b/src/test/ui/issues/issue-19244-1.stderr
@@ -0,0 +1,9 @@
+error[E0609]: no field `1` on type `(usize,)`
+  --> $DIR/issue-19244-1.rs:4:24
+   |
+LL |     let a: [isize; TUP.1];
+   |                        ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0609`.
diff --git a/src/test/ui/issues/issue-19244-2.rs b/src/test/ui/issues/issue-19244-2.rs
new file mode 100644
index 0000000..c9a68b0
--- /dev/null
+++ b/src/test/ui/issues/issue-19244-2.rs
@@ -0,0 +1,7 @@
+struct MyStruct { field: usize }
+const STRUCT: MyStruct = MyStruct { field: 42 };
+
+fn main() {
+    let a: [isize; STRUCT.nonexistent_field];
+    //~^ no field `nonexistent_field` on type `MyStruct`
+}
diff --git a/src/test/ui/issues/issue-19244-2.stderr b/src/test/ui/issues/issue-19244-2.stderr
new file mode 100644
index 0000000..54529fd
--- /dev/null
+++ b/src/test/ui/issues/issue-19244-2.stderr
@@ -0,0 +1,11 @@
+error[E0609]: no field `nonexistent_field` on type `MyStruct`
+  --> $DIR/issue-19244-2.rs:5:27
+   |
+LL |     let a: [isize; STRUCT.nonexistent_field];
+   |                           ^^^^^^^^^^^^^^^^^ unknown field
+   |
+   = note: available fields are: `field`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0609`.
diff --git a/src/test/ui/issues/issue-19380.rs b/src/test/ui/issues/issue-19380.rs
new file mode 100644
index 0000000..efbc5a0
--- /dev/null
+++ b/src/test/ui/issues/issue-19380.rs
@@ -0,0 +1,18 @@
+trait Qiz {
+  fn qiz();
+}
+
+struct Foo;
+impl Qiz for Foo {
+  fn qiz() {}
+}
+
+struct Bar {
+  foos: &'static [&'static (Qiz + 'static)]
+//~^ ERROR E0038
+}
+
+const FOO : Foo = Foo;
+const BAR : Bar = Bar { foos: &[&FOO]};
+
+fn main() { }
diff --git a/src/test/ui/issues/issue-19380.stderr b/src/test/ui/issues/issue-19380.stderr
new file mode 100644
index 0000000..060e160
--- /dev/null
+++ b/src/test/ui/issues/issue-19380.stderr
@@ -0,0 +1,11 @@
+error[E0038]: the trait `Qiz` cannot be made into an object
+  --> $DIR/issue-19380.rs:11:3
+   |
+LL |   foos: &'static [&'static (Qiz + 'static)]
+   |   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Qiz` cannot be made into an object
+   |
+   = note: method `qiz` has no receiver
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/issues/issue-19398.rs b/src/test/ui/issues/issue-19398.rs
new file mode 100644
index 0000000..5daa14b
--- /dev/null
+++ b/src/test/ui/issues/issue-19398.rs
@@ -0,0 +1,12 @@
+// compile-pass
+// pretty-expanded FIXME #23616
+
+trait T {
+    unsafe extern "Rust" fn foo(&self);
+}
+
+impl T for () {
+    unsafe extern "Rust" fn foo(&self) {}
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-19404.rs b/src/test/ui/issues/issue-19404.rs
new file mode 100644
index 0000000..cdec74f
--- /dev/null
+++ b/src/test/ui/issues/issue-19404.rs
@@ -0,0 +1,37 @@
+// compile-pass
+#![allow(dead_code)]
+#![allow(unused_variables)]
+use std::any::TypeId;
+use std::rc::Rc;
+
+type Fp<T> = Rc<T>;
+
+struct Engine;
+
+trait Component: 'static {}
+impl Component for Engine {}
+
+trait Env {
+    fn get_component_type_id(&self, type_id: TypeId) -> Option<Fp<Component>>;
+}
+
+impl<'a> Env+'a {
+    fn get_component<T: Component>(&self) -> Option<Fp<T>> {
+        let x = self.get_component_type_id(TypeId::of::<T>());
+        None
+    }
+}
+
+trait Figment {
+    fn init(&mut self, env: &Env);
+}
+
+struct MyFigment;
+
+impl Figment for MyFigment {
+    fn init(&mut self, env: &Env) {
+        let engine = env.get_component::<Engine>();
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-19479.rs b/src/test/ui/issues/issue-19479.rs
new file mode 100644
index 0000000..8b78952
--- /dev/null
+++ b/src/test/ui/issues/issue-19479.rs
@@ -0,0 +1,19 @@
+// compile-pass
+// pretty-expanded FIXME #23616
+
+trait Base {
+    fn dummy(&self) { }
+}
+trait AssocA {
+    type X: Base;
+    fn dummy(&self) { }
+}
+trait AssocB {
+    type Y: Base;
+    fn dummy(&self) { }
+}
+impl<T: AssocA> AssocB for T {
+    type Y = <T as AssocA>::X;
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-19482.rs b/src/test/ui/issues/issue-19482.rs
new file mode 100644
index 0000000..6ba3349
--- /dev/null
+++ b/src/test/ui/issues/issue-19482.rs
@@ -0,0 +1,13 @@
+// Test that a partially specified trait object with unspecified associated
+// type does not type-check.
+
+trait Foo {
+    type A;
+
+    fn dummy(&self) { }
+}
+
+fn bar(x: &Foo) {}
+//~^ ERROR the associated type `A` (from the trait `Foo`) must be specified
+
+pub fn main() {}
diff --git a/src/test/ui/issues/issue-19482.stderr b/src/test/ui/issues/issue-19482.stderr
new file mode 100644
index 0000000..a8894f8
--- /dev/null
+++ b/src/test/ui/issues/issue-19482.stderr
@@ -0,0 +1,12 @@
+error[E0191]: the value of the associated type `A` (from the trait `Foo`) must be specified
+  --> $DIR/issue-19482.rs:10:12
+   |
+LL |     type A;
+   |     ------- `A` defined here
+...
+LL | fn bar(x: &Foo) {}
+   |            ^^^ associated type `A` must be specified
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0191`.
diff --git a/src/test/ui/issues/issue-19498.rs b/src/test/ui/issues/issue-19498.rs
new file mode 100644
index 0000000..5fe6742
--- /dev/null
+++ b/src/test/ui/issues/issue-19498.rs
@@ -0,0 +1,13 @@
+use self::A;
+use self::B;
+mod A {} //~ ERROR the name `A` is defined multiple times
+//~| `A` redefined here
+pub mod B {} //~ ERROR the name `B` is defined multiple times
+//~| `B` redefined here
+mod C {
+    use C::D;
+    mod D {} //~ ERROR the name `D` is defined multiple times
+    //~| `D` redefined here
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-19498.stderr b/src/test/ui/issues/issue-19498.stderr
new file mode 100644
index 0000000..cc1d649
--- /dev/null
+++ b/src/test/ui/issues/issue-19498.stderr
@@ -0,0 +1,47 @@
+error[E0255]: the name `A` is defined multiple times
+  --> $DIR/issue-19498.rs:3:1
+   |
+LL | use self::A;
+   |     ------- previous import of the module `A` here
+LL | use self::B;
+LL | mod A {}
+   | ^^^^^ `A` redefined here
+   |
+   = note: `A` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | use self::A as OtherA;
+   |     ^^^^^^^^^^^^^^^^^
+
+error[E0255]: the name `B` is defined multiple times
+  --> $DIR/issue-19498.rs:5:1
+   |
+LL | use self::B;
+   |     ------- previous import of the module `B` here
+...
+LL | pub mod B {}
+   | ^^^^^^^^^ `B` redefined here
+   |
+   = note: `B` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | use self::B as OtherB;
+   |     ^^^^^^^^^^^^^^^^^
+
+error[E0255]: the name `D` is defined multiple times
+  --> $DIR/issue-19498.rs:9:5
+   |
+LL |     use C::D;
+   |         ---- previous import of the module `D` here
+LL |     mod D {}
+   |     ^^^^^ `D` redefined here
+   |
+   = note: `D` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL |     use C::D as OtherD;
+   |         ^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0255`.
diff --git a/src/test/ui/issues/issue-19521.rs b/src/test/ui/issues/issue-19521.rs
new file mode 100644
index 0000000..a2a32a2
--- /dev/null
+++ b/src/test/ui/issues/issue-19521.rs
@@ -0,0 +1,3 @@
+fn main() {
+    "".homura()(); //~ ERROR no method named `homura` found
+}
diff --git a/src/test/ui/issues/issue-19521.stderr b/src/test/ui/issues/issue-19521.stderr
new file mode 100644
index 0000000..a43368b
--- /dev/null
+++ b/src/test/ui/issues/issue-19521.stderr
@@ -0,0 +1,9 @@
+error[E0599]: no method named `homura` found for type `&'static str` in the current scope
+  --> $DIR/issue-19521.rs:2:8
+   |
+LL |     "".homura()();
+   |        ^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/issues/issue-19538.rs b/src/test/ui/issues/issue-19538.rs
new file mode 100644
index 0000000..9f0b08d
--- /dev/null
+++ b/src/test/ui/issues/issue-19538.rs
@@ -0,0 +1,20 @@
+trait Foo {
+    fn foo<T>(&self, val: T);
+}
+
+trait Bar: Foo { }
+
+pub struct Thing;
+
+impl Foo for Thing {
+    fn foo<T>(&self, val: T) { }
+}
+
+impl Bar for Thing { }
+
+fn main() {
+    let mut thing = Thing;
+    let test: &mut Bar = &mut thing;
+    //~^ ERROR E0038
+    //~| ERROR E0038
+}
diff --git a/src/test/ui/issues/issue-19538.stderr b/src/test/ui/issues/issue-19538.stderr
new file mode 100644
index 0000000..d0f05a4
--- /dev/null
+++ b/src/test/ui/issues/issue-19538.stderr
@@ -0,0 +1,20 @@
+error[E0038]: the trait `Bar` cannot be made into an object
+  --> $DIR/issue-19538.rs:17:15
+   |
+LL |     let test: &mut Bar = &mut thing;
+   |               ^^^^^^^^ the trait `Bar` cannot be made into an object
+   |
+   = note: method `foo` has generic type parameters
+
+error[E0038]: the trait `Bar` cannot be made into an object
+  --> $DIR/issue-19538.rs:17:26
+   |
+LL |     let test: &mut Bar = &mut thing;
+   |                          ^^^^^^^^^^ the trait `Bar` cannot be made into an object
+   |
+   = note: method `foo` has generic type parameters
+   = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&mut dyn Bar>` for `&mut Thing`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/issues/issue-19601.rs b/src/test/ui/issues/issue-19601.rs
new file mode 100644
index 0000000..faaa2db
--- /dev/null
+++ b/src/test/ui/issues/issue-19601.rs
@@ -0,0 +1,9 @@
+// compile-pass
+// skip-codegen
+#![allow(warnings)]
+trait A<T> {}
+struct B<T> where B<T>: A<B<T>> { t: T }
+
+
+fn main() {
+}
diff --git a/src/test/ui/issues/issue-1962.rs b/src/test/ui/issues/issue-1962.rs
new file mode 100644
index 0000000..e9ab3b5
--- /dev/null
+++ b/src/test/ui/issues/issue-1962.rs
@@ -0,0 +1,8 @@
+// compile-flags: -D while-true
+fn main() {
+  let mut i = 0;
+  while true  { //~ ERROR denote infinite loops with `loop
+    i += 1;
+    if i == 5 { break; }
+  }
+}
diff --git a/src/test/ui/issues/issue-1962.stderr b/src/test/ui/issues/issue-1962.stderr
new file mode 100644
index 0000000..afef59c
--- /dev/null
+++ b/src/test/ui/issues/issue-1962.stderr
@@ -0,0 +1,10 @@
+error: denote infinite loops with `loop { ... }`
+  --> $DIR/issue-1962.rs:4:3
+   |
+LL |   while true  {
+   |   ^^^^^^^^^^ help: use `loop`
+   |
+   = note: requested on the command line with `-D while-true`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-19631.rs b/src/test/ui/issues/issue-19631.rs
new file mode 100644
index 0000000..8c58331
--- /dev/null
+++ b/src/test/ui/issues/issue-19631.rs
@@ -0,0 +1,16 @@
+// compile-pass
+#![allow(dead_code)]
+// pretty-expanded FIXME #23616
+
+trait PoolManager {
+    type C;
+    fn dummy(&self) { }
+}
+
+struct InnerPool<M> {
+    manager: M,
+}
+
+impl<M> InnerPool<M> where M: PoolManager {}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-19632.rs b/src/test/ui/issues/issue-19632.rs
new file mode 100644
index 0000000..b032b67
--- /dev/null
+++ b/src/test/ui/issues/issue-19632.rs
@@ -0,0 +1,14 @@
+// compile-pass
+#![allow(dead_code)]
+// pretty-expanded FIXME #23616
+
+trait PoolManager {
+    type C;
+    fn dummy(&self) { }
+}
+
+struct InnerPool<M: PoolManager> {
+    manager: M,
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-19660.rs b/src/test/ui/issues/issue-19660.rs
new file mode 100644
index 0000000..400ac31
--- /dev/null
+++ b/src/test/ui/issues/issue-19660.rs
@@ -0,0 +1,15 @@
+// error-pattern: requires `copy` lang_item
+
+#![feature(lang_items, start, no_core)]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized { }
+
+struct S;
+
+#[start]
+fn main(_: isize, _: *const *const u8) -> isize {
+    let _ = S;
+    0
+}
diff --git a/src/test/ui/issues/issue-19660.stderr b/src/test/ui/issues/issue-19660.stderr
new file mode 100644
index 0000000..f5d903f
--- /dev/null
+++ b/src/test/ui/issues/issue-19660.stderr
@@ -0,0 +1,4 @@
+error: requires `copy` lang_item
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-19692.rs b/src/test/ui/issues/issue-19692.rs
new file mode 100644
index 0000000..99eccc8
--- /dev/null
+++ b/src/test/ui/issues/issue-19692.rs
@@ -0,0 +1,8 @@
+struct Homura;
+
+fn akemi(homura: Homura) {
+    let Some(ref madoka) = Some(homura.kaname()); //~ ERROR no method named `kaname` found
+    madoka.clone();
+}
+
+fn main() { }
diff --git a/src/test/ui/issues/issue-19692.stderr b/src/test/ui/issues/issue-19692.stderr
new file mode 100644
index 0000000..5e576f1
--- /dev/null
+++ b/src/test/ui/issues/issue-19692.stderr
@@ -0,0 +1,12 @@
+error[E0599]: no method named `kaname` found for type `Homura` in the current scope
+  --> $DIR/issue-19692.rs:4:40
+   |
+LL | struct Homura;
+   | -------------- method `kaname` not found for this
+...
+LL |     let Some(ref madoka) = Some(homura.kaname());
+   |                                        ^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/issues/issue-19707.rs b/src/test/ui/issues/issue-19707.rs
new file mode 100644
index 0000000..6bc7132
--- /dev/null
+++ b/src/test/ui/issues/issue-19707.rs
@@ -0,0 +1,7 @@
+#![allow(dead_code)]
+
+type Foo = fn(&u8, &u8) -> &u8; //~ ERROR missing lifetime specifier
+
+fn bar<F: Fn(&u8, &u8) -> &u8>(f: &F) {} //~ ERROR missing lifetime specifier
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-19707.stderr b/src/test/ui/issues/issue-19707.stderr
new file mode 100644
index 0000000..c85ce0e
--- /dev/null
+++ b/src/test/ui/issues/issue-19707.stderr
@@ -0,0 +1,19 @@
+error[E0106]: missing lifetime specifier
+  --> $DIR/issue-19707.rs:3:28
+   |
+LL | type Foo = fn(&u8, &u8) -> &u8;
+   |                            ^ expected lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/issue-19707.rs:5:27
+   |
+LL | fn bar<F: Fn(&u8, &u8) -> &u8>(f: &F) {}
+   |                           ^ expected lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0106`.
diff --git a/src/test/ui/issues/issue-19734.rs b/src/test/ui/issues/issue-19734.rs
new file mode 100644
index 0000000..b730e19
--- /dev/null
+++ b/src/test/ui/issues/issue-19734.rs
@@ -0,0 +1,8 @@
+fn main() {}
+
+struct Type;
+
+impl Type {
+    undef!();
+    //~^ ERROR cannot find macro `undef!` in this scope
+}
diff --git a/src/test/ui/issues/issue-19734.stderr b/src/test/ui/issues/issue-19734.stderr
new file mode 100644
index 0000000..fc1a7d0
--- /dev/null
+++ b/src/test/ui/issues/issue-19734.stderr
@@ -0,0 +1,8 @@
+error: cannot find macro `undef!` in this scope
+  --> $DIR/issue-19734.rs:6:5
+   |
+LL |     undef!();
+   |     ^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-19850.rs b/src/test/ui/issues/issue-19850.rs
new file mode 100644
index 0000000..fb64ef8
--- /dev/null
+++ b/src/test/ui/issues/issue-19850.rs
@@ -0,0 +1,22 @@
+// compile-pass
+#![allow(unused_variables)]
+// Test that `<Type as Trait>::Output` and `Self::Output` are accepted as type annotations in let
+// bindings
+
+// pretty-expanded FIXME #23616
+
+trait Int {
+    fn one() -> Self;
+    fn leading_zeros(self) -> usize;
+}
+
+trait Foo {
+    type T : Int;
+
+    fn test(&self) {
+        let r: <Self as Foo>::T = Int::one();
+        let r: Self::T = Int::one();
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-19883.rs b/src/test/ui/issues/issue-19883.rs
new file mode 100644
index 0000000..5cf4220
--- /dev/null
+++ b/src/test/ui/issues/issue-19883.rs
@@ -0,0 +1,16 @@
+trait From<Src> {
+    type Output;
+
+    fn from(src: Src) -> <Self as From<Src>>::Output;
+}
+
+trait To: Sized {
+    fn to<Dst: From<Self>>(self) ->
+        <Dst as From<Self>>::Dst
+        //~^ ERROR cannot find associated type `Dst` in trait `From`
+    {
+        From::from(self)
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-19883.stderr b/src/test/ui/issues/issue-19883.stderr
new file mode 100644
index 0000000..e370b2e
--- /dev/null
+++ b/src/test/ui/issues/issue-19883.stderr
@@ -0,0 +1,9 @@
+error[E0576]: cannot find associated type `Dst` in trait `From`
+  --> $DIR/issue-19883.rs:9:30
+   |
+LL |         <Dst as From<Self>>::Dst
+   |                              ^^^ not found in `From`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0576`.
diff --git a/src/test/ui/issues/issue-19922.rs b/src/test/ui/issues/issue-19922.rs
new file mode 100644
index 0000000..fede86f
--- /dev/null
+++ b/src/test/ui/issues/issue-19922.rs
@@ -0,0 +1,8 @@
+enum Homura {
+    Akemi { madoka: () }
+}
+
+fn main() {
+    let homura = Homura::Akemi { kaname: () };
+    //~^ ERROR variant `Homura::Akemi` has no field named `kaname`
+}
diff --git a/src/test/ui/issues/issue-19922.stderr b/src/test/ui/issues/issue-19922.stderr
new file mode 100644
index 0000000..826b2ac
--- /dev/null
+++ b/src/test/ui/issues/issue-19922.stderr
@@ -0,0 +1,11 @@
+error[E0559]: variant `Homura::Akemi` has no field named `kaname`
+  --> $DIR/issue-19922.rs:6:34
+   |
+LL |     let homura = Homura::Akemi { kaname: () };
+   |                                  ^^^^^^ `Homura::Akemi` does not have this field
+   |
+   = note: available fields are: `madoka`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0559`.
diff --git a/src/test/ui/issues/issue-19982.rs b/src/test/ui/issues/issue-19982.rs
new file mode 100644
index 0000000..6b5a4b2
--- /dev/null
+++ b/src/test/ui/issues/issue-19982.rs
@@ -0,0 +1,22 @@
+// compile-pass
+
+#![feature(fn_traits, unboxed_closures)]
+
+#[allow(dead_code)]
+struct Foo;
+
+impl Fn<(&(),)> for Foo {
+    extern "rust-call" fn call(&self, (_,): (&(),)) {}
+}
+
+impl FnMut<(&(),)> for Foo {
+    extern "rust-call" fn call_mut(&mut self, (_,): (&(),)) {}
+}
+
+impl FnOnce<(&(),)> for Foo {
+    type Output = ();
+
+    extern "rust-call" fn call_once(self, (_,): (&(),)) {}
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-19991.rs b/src/test/ui/issues/issue-19991.rs
new file mode 100644
index 0000000..e9094ec
--- /dev/null
+++ b/src/test/ui/issues/issue-19991.rs
@@ -0,0 +1,11 @@
+// Test if the sugared if-let construct correctly prints "missing an else clause" when an else
+// clause does not exist, instead of the unsympathetic "match arms have incompatible types"
+
+fn main() {
+    if let Some(homura) = Some("madoka") { //~  ERROR missing an else clause
+                                           //~| expected type `()`
+                                           //~| found type `{integer}`
+                                           //~| expected (), found integer
+        765
+    };
+}
diff --git a/src/test/ui/issues/issue-19991.stderr b/src/test/ui/issues/issue-19991.stderr
new file mode 100644
index 0000000..4c6d150
--- /dev/null
+++ b/src/test/ui/issues/issue-19991.stderr
@@ -0,0 +1,17 @@
+error[E0317]: if may be missing an else clause
+  --> $DIR/issue-19991.rs:5:5
+   |
+LL | /     if let Some(homura) = Some("madoka") {
+LL | |
+LL | |
+LL | |
+LL | |         765
+LL | |     };
+   | |_____^ expected (), found integer
+   |
+   = note: expected type `()`
+              found type `{integer}`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0317`.
diff --git a/src/test/ui/issues/issue-20005.rs b/src/test/ui/issues/issue-20005.rs
new file mode 100644
index 0000000..6d63c9e
--- /dev/null
+++ b/src/test/ui/issues/issue-20005.rs
@@ -0,0 +1,15 @@
+trait From<Src> {
+    type Result;
+
+    fn from(src: Src) -> Self::Result;
+}
+
+trait To {
+    fn to<Dst>(  //~ ERROR the size for values of type
+        self
+    ) -> <Dst as From<Self>>::Result where Dst: From<Self> {
+        From::from(self)
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-20005.stderr b/src/test/ui/issues/issue-20005.stderr
new file mode 100644
index 0000000..e271005
--- /dev/null
+++ b/src/test/ui/issues/issue-20005.stderr
@@ -0,0 +1,22 @@
+error[E0277]: the size for values of type `Self` cannot be known at compilation time
+  --> $DIR/issue-20005.rs:8:5
+   |
+LL | /     fn to<Dst>(
+LL | |         self
+LL | |     ) -> <Dst as From<Self>>::Result where Dst: From<Self> {
+LL | |         From::from(self)
+LL | |     }
+   | |_____^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `Self`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = help: consider adding a `where Self: std::marker::Sized` bound
+note: required by `From`
+  --> $DIR/issue-20005.rs:1:1
+   |
+LL | trait From<Src> {
+   | ^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-20009.rs b/src/test/ui/issues/issue-20009.rs
new file mode 100644
index 0000000..6228d04
--- /dev/null
+++ b/src/test/ui/issues/issue-20009.rs
@@ -0,0 +1,13 @@
+// compile-pass
+// Check that associated types are `Sized`
+
+// pretty-expanded FIXME #23616
+
+trait Trait {
+    type Output;
+
+    fn is_sized(&self) -> Self::Output;
+    fn wasnt_sized(&self) -> Self::Output { loop {} }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-20091.rs b/src/test/ui/issues/issue-20091.rs
new file mode 100644
index 0000000..4d86a17
--- /dev/null
+++ b/src/test/ui/issues/issue-20091.rs
@@ -0,0 +1,24 @@
+// compile-pass
+#![allow(stable_features)]
+
+// ignore-cloudabi no processes
+// ignore-emscripten no processes
+
+#![feature(os)]
+
+#[cfg(unix)]
+fn main() {
+    use std::process::Command;
+    use std::env;
+    use std::os::unix::prelude::*;
+    use std::ffi::OsStr;
+
+    if env::args().len() == 1 {
+        assert!(Command::new(&env::current_exe().unwrap())
+                        .arg(<OsStr as OsStrExt>::from_bytes(b"\xff"))
+                        .status().unwrap().success())
+    }
+}
+
+#[cfg(windows)]
+fn main() {}
diff --git a/src/test/ui/issues/issue-20162.rs b/src/test/ui/issues/issue-20162.rs
new file mode 100644
index 0000000..b7f9cae
--- /dev/null
+++ b/src/test/ui/issues/issue-20162.rs
@@ -0,0 +1,7 @@
+struct X { x: i32 }
+
+fn main() {
+    let mut b: Vec<X> = vec![];
+    b.sort();
+    //~^ ERROR `X: std::cmp::Ord` is not satisfied
+}
diff --git a/src/test/ui/issues/issue-20162.stderr b/src/test/ui/issues/issue-20162.stderr
new file mode 100644
index 0000000..1d0d6d5
--- /dev/null
+++ b/src/test/ui/issues/issue-20162.stderr
@@ -0,0 +1,9 @@
+error[E0277]: the trait bound `X: std::cmp::Ord` is not satisfied
+  --> $DIR/issue-20162.rs:5:7
+   |
+LL |     b.sort();
+   |       ^^^^ the trait `std::cmp::Ord` is not implemented for `X`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-20186.rs b/src/test/ui/issues/issue-20186.rs
new file mode 100644
index 0000000..98d856e
--- /dev/null
+++ b/src/test/ui/issues/issue-20186.rs
@@ -0,0 +1,16 @@
+// compile-pass
+#![allow(dead_code)]
+#![allow(unused_variables)]
+struct Foo;
+
+impl Foo {
+    fn putc(&self, b: u8) { }
+
+    fn puts(&self, s: &str) {
+        for byte in s.bytes() {
+            self.putc(byte)
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-20225.rs b/src/test/ui/issues/issue-20225.rs
new file mode 100644
index 0000000..b15f2a6
--- /dev/null
+++ b/src/test/ui/issues/issue-20225.rs
@@ -0,0 +1,25 @@
+#![feature(fn_traits, unboxed_closures)]
+
+struct Foo;
+
+impl<'a, T> Fn<(&'a T,)> for Foo {
+  extern "rust-call" fn call(&self, (_,): (T,)) {}
+  //~^ ERROR: has an incompatible type for trait
+  //~| expected reference
+}
+
+impl<'a, T> FnMut<(&'a T,)> for Foo {
+  extern "rust-call" fn call_mut(&mut self, (_,): (T,)) {}
+  //~^ ERROR: has an incompatible type for trait
+  //~| expected reference
+}
+
+impl<'a, T> FnOnce<(&'a T,)> for Foo {
+  type Output = ();
+
+  extern "rust-call" fn call_once(self, (_,): (T,)) {}
+  //~^ ERROR: has an incompatible type for trait
+  //~| expected reference
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-20225.stderr b/src/test/ui/issues/issue-20225.stderr
new file mode 100644
index 0000000..5ab23cb
--- /dev/null
+++ b/src/test/ui/issues/issue-20225.stderr
@@ -0,0 +1,30 @@
+error[E0053]: method `call` has an incompatible type for trait
+  --> $DIR/issue-20225.rs:6:3
+   |
+LL |   extern "rust-call" fn call(&self, (_,): (T,)) {}
+   |   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected reference, found type parameter
+   |
+   = note: expected type `extern "rust-call" fn(&Foo, (&'a T,))`
+              found type `extern "rust-call" fn(&Foo, (T,))`
+
+error[E0053]: method `call_mut` has an incompatible type for trait
+  --> $DIR/issue-20225.rs:12:3
+   |
+LL |   extern "rust-call" fn call_mut(&mut self, (_,): (T,)) {}
+   |   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected reference, found type parameter
+   |
+   = note: expected type `extern "rust-call" fn(&mut Foo, (&'a T,))`
+              found type `extern "rust-call" fn(&mut Foo, (T,))`
+
+error[E0053]: method `call_once` has an incompatible type for trait
+  --> $DIR/issue-20225.rs:20:3
+   |
+LL |   extern "rust-call" fn call_once(self, (_,): (T,)) {}
+   |   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected reference, found type parameter
+   |
+   = note: expected type `extern "rust-call" fn(Foo, (&'a T,))`
+              found type `extern "rust-call" fn(Foo, (T,))`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0053`.
diff --git a/src/test/ui/issues/issue-20261.rs b/src/test/ui/issues/issue-20261.rs
new file mode 100644
index 0000000..5283936
--- /dev/null
+++ b/src/test/ui/issues/issue-20261.rs
@@ -0,0 +1,7 @@
+fn main() {
+    // N.B., this (almost) typechecks when default binding modes are enabled.
+    for (ref i,) in [].iter() {
+        i.clone();
+        //~^ ERROR type annotations needed
+    }
+}
diff --git a/src/test/ui/issues/issue-20261.stderr b/src/test/ui/issues/issue-20261.stderr
new file mode 100644
index 0000000..5665f58
--- /dev/null
+++ b/src/test/ui/issues/issue-20261.stderr
@@ -0,0 +1,13 @@
+error[E0282]: type annotations needed
+  --> $DIR/issue-20261.rs:4:11
+   |
+LL |     for (ref i,) in [].iter() {
+   |                     --------- the element type for this iterator is not specified
+LL |         i.clone();
+   |           ^^^^^ cannot infer type
+   |
+   = note: type must be known at this point
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/issues/issue-20313.rs b/src/test/ui/issues/issue-20313.rs
new file mode 100644
index 0000000..4149ab4
--- /dev/null
+++ b/src/test/ui/issues/issue-20313.rs
@@ -0,0 +1,7 @@
+extern {
+    #[link_name = "llvm.sqrt.f32"]
+    fn sqrt(x: f32) -> f32; //~ ERROR linking to LLVM intrinsics is experimental
+}
+
+fn main(){
+}
diff --git a/src/test/ui/issues/issue-20313.stderr b/src/test/ui/issues/issue-20313.stderr
new file mode 100644
index 0000000..87e2e89
--- /dev/null
+++ b/src/test/ui/issues/issue-20313.stderr
@@ -0,0 +1,11 @@
+error[E0658]: linking to LLVM intrinsics is experimental (see issue #29602)
+  --> $DIR/issue-20313.rs:3:5
+   |
+LL |     fn sqrt(x: f32) -> f32;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(link_llvm_intrinsics)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/issues/issue-20396.rs b/src/test/ui/issues/issue-20396.rs
new file mode 100644
index 0000000..b6dfffb
--- /dev/null
+++ b/src/test/ui/issues/issue-20396.rs
@@ -0,0 +1,16 @@
+// compile-pass
+// pretty-expanded FIXME #23616
+
+#![allow(dead_code)]
+
+trait Foo<T> {
+    fn noop(&self, _: T);
+}
+
+enum Bar<T> { Bla(T) }
+
+struct Baz<'a> {
+    inner: for<'b> Foo<Bar<&'b ()>> + 'a,
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-20413.rs b/src/test/ui/issues/issue-20413.rs
new file mode 100644
index 0000000..7eb6d5c
--- /dev/null
+++ b/src/test/ui/issues/issue-20413.rs
@@ -0,0 +1,16 @@
+trait Foo {
+  fn answer(self);
+}
+
+struct NoData<T>;
+//~^ ERROR: parameter `T` is never used
+
+impl<T> Foo for T where NoData<T>: Foo {
+//~^ ERROR: overflow evaluating the requirement
+  fn answer(self) {
+  //~^ ERROR: overflow evaluating the requirement
+    let val: NoData<T> = NoData;
+  }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-20413.stderr b/src/test/ui/issues/issue-20413.stderr
new file mode 100644
index 0000000..893f4fa
--- /dev/null
+++ b/src/test/ui/issues/issue-20413.stderr
@@ -0,0 +1,173 @@
+error[E0392]: parameter `T` is never used
+  --> $DIR/issue-20413.rs:5:15
+   |
+LL | struct NoData<T>;
+   |               ^ unused type parameter
+   |
+   = help: consider removing `T` or using a marker such as `std::marker::PhantomData`
+
+error[E0275]: overflow evaluating the requirement `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Foo`
+  --> $DIR/issue-20413.rs:8:1
+   |
+LL | / impl<T> Foo for T where NoData<T>: Foo {
+LL | |
+LL | |   fn answer(self) {
+LL | |
+LL | |     let val: NoData<T> = NoData;
+LL | |   }
+LL | | }
+   | |_^
+   |
+   = help: consider adding a `#![recursion_limit="128"]` attribute to your crate
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<T>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<T>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<T>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<T>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<T>`
+note: required by `Foo`
+  --> $DIR/issue-20413.rs:1:1
+   |
+LL | trait Foo {
+   | ^^^^^^^^^
+
+error[E0275]: overflow evaluating the requirement `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Foo`
+  --> $DIR/issue-20413.rs:10:3
+   |
+LL | /   fn answer(self) {
+LL | |
+LL | |     let val: NoData<T> = NoData;
+LL | |   }
+   | |___^
+   |
+   = help: consider adding a `#![recursion_limit="128"]` attribute to your crate
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<T>>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<T>>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<T>>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<T>>`
+   = note: required because of the requirements on the impl of `Foo` for `NoData<T>`
+note: required by `Foo`
+  --> $DIR/issue-20413.rs:1:1
+   |
+LL | trait Foo {
+   | ^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0275, E0392.
+For more information about an error, try `rustc --explain E0275`.
diff --git a/src/test/ui/issues/issue-20414.rs b/src/test/ui/issues/issue-20414.rs
new file mode 100644
index 0000000..1653a9d
--- /dev/null
+++ b/src/test/ui/issues/issue-20414.rs
@@ -0,0 +1,21 @@
+// compile-pass
+#![allow(dead_code)]
+// pretty-expanded FIXME #23616
+
+trait Trait {
+        fn method(self) -> isize;
+}
+
+struct Wrapper<T> {
+        field: T
+}
+
+impl<'a, T> Trait for &'a Wrapper<T> where &'a T: Trait {
+    fn method(self) -> isize {
+        let r: &'a T = &self.field;
+        Trait::method(r); // these should both work
+        r.method()
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-20433.rs b/src/test/ui/issues/issue-20433.rs
new file mode 100644
index 0000000..a663239
--- /dev/null
+++ b/src/test/ui/issues/issue-20433.rs
@@ -0,0 +1,8 @@
+fn main() {}
+
+struct The;
+
+impl The {
+    fn iceman(c: Vec<[i32]>) {}
+    //~^ ERROR the size for values of type
+}
diff --git a/src/test/ui/issues/issue-20433.stderr b/src/test/ui/issues/issue-20433.stderr
new file mode 100644
index 0000000..f7cb28e
--- /dev/null
+++ b/src/test/ui/issues/issue-20433.stderr
@@ -0,0 +1,13 @@
+error[E0277]: the size for values of type `[i32]` cannot be known at compilation time
+  --> $DIR/issue-20433.rs:6:5
+   |
+LL |     fn iceman(c: Vec<[i32]>) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `[i32]`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: required by `std::vec::Vec`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-20454.rs b/src/test/ui/issues/issue-20454.rs
new file mode 100644
index 0000000..d4920c0
--- /dev/null
+++ b/src/test/ui/issues/issue-20454.rs
@@ -0,0 +1,13 @@
+// compile-pass
+#![allow(unused_must_use)]
+use std::thread;
+
+fn _foo() {
+    thread::spawn(move || { // no need for -> ()
+        loop {
+            println!("hello");
+        }
+    }).join();
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-20605.rs b/src/test/ui/issues/issue-20605.rs
new file mode 100644
index 0000000..11a2a57
--- /dev/null
+++ b/src/test/ui/issues/issue-20605.rs
@@ -0,0 +1,6 @@
+fn changer<'a>(mut things: Box<Iterator<Item=&'a mut u8>>) {
+    for item in *things { *item = 0 }
+//~^ ERROR the size for values of type
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-20605.stderr b/src/test/ui/issues/issue-20605.stderr
new file mode 100644
index 0000000..89df58d
--- /dev/null
+++ b/src/test/ui/issues/issue-20605.stderr
@@ -0,0 +1,13 @@
+error[E0277]: the size for values of type `dyn std::iter::Iterator<Item = &mut u8>` cannot be known at compilation time
+  --> $DIR/issue-20605.rs:2:17
+   |
+LL |     for item in *things { *item = 0 }
+   |                 ^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `dyn std::iter::Iterator<Item = &mut u8>`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: required by `std::iter::IntoIterator::into_iter`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-20616-1.rs b/src/test/ui/issues/issue-20616-1.rs
new file mode 100644
index 0000000..49e9cb3
--- /dev/null
+++ b/src/test/ui/issues/issue-20616-1.rs
@@ -0,0 +1,36 @@
+// We need all these 9 issue-20616-N.rs files
+// because we can only catch one parsing error at a time
+
+
+
+type Type_1_<'a, T> = &'a T;
+
+
+type Type_1<'a T> = &'a T; //~ error: expected one of `,`, `:`, or `>`, found `T`
+
+
+//type Type_2 = Type_1_<'static ()>; // error: expected `,` or `>` after lifetime name, found `(`
+
+
+//type Type_3<T> = Box<T,,>; // error: expected type, found `,`
+
+
+//type Type_4<T> = Type_1_<'static,, T>; // error: expected type, found `,`
+
+
+type Type_5_<'a> = Type_1_<'a, ()>;
+
+
+//type Type_5<'a> = Type_1_<'a, (),,>; // error: expected type, found `,`
+
+
+//type Type_6 = Type_5_<'a,,>; // error: expected type, found `,`
+
+
+//type Type_7 = Box<(),,>; // error: expected type, found `,`
+
+
+//type Type_8<'a,,> = &'a (); // error: expected ident, found `,`
+
+
+//type Type_9<T,,> = Box<T>; // error: expected ident, found `,`
diff --git a/src/test/ui/issues/issue-20616-1.stderr b/src/test/ui/issues/issue-20616-1.stderr
new file mode 100644
index 0000000..143486c
--- /dev/null
+++ b/src/test/ui/issues/issue-20616-1.stderr
@@ -0,0 +1,8 @@
+error: expected one of `,`, `:`, or `>`, found `T`
+  --> $DIR/issue-20616-1.rs:9:16
+   |
+LL | type Type_1<'a T> = &'a T;
+   |                ^ expected one of `,`, `:`, or `>` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-20616-2.rs b/src/test/ui/issues/issue-20616-2.rs
new file mode 100644
index 0000000..2f2c690
--- /dev/null
+++ b/src/test/ui/issues/issue-20616-2.rs
@@ -0,0 +1,36 @@
+// We need all these 9 issue-20616-N.rs files
+// because we can only catch one parsing error at a time
+
+
+
+type Type_1_<'a, T> = &'a T;
+
+
+//type Type_1<'a T> = &'a T; // error: expected `,` or `>` after lifetime name, found `T`
+
+
+type Type_2 = Type_1_<'static ()>; //~ error: expected one of `,` or `>`, found `(`
+
+
+//type Type_3<T> = Box<T,,>; // error: expected type, found `,`
+
+
+//type Type_4<T> = Type_1_<'static,, T>; // error: expected type, found `,`
+
+
+type Type_5_<'a> = Type_1_<'a, ()>;
+
+
+//type Type_5<'a> = Type_1_<'a, (),,>; // error: expected type, found `,`
+
+
+//type Type_6 = Type_5_<'a,,>; // error: expected type, found `,`
+
+
+//type Type_7 = Box<(),,>; // error: expected type, found `,`
+
+
+//type Type_8<'a,,> = &'a (); // error: expected ident, found `,`
+
+
+//type Type_9<T,,> = Box<T>; // error: expected ident, found `,`
diff --git a/src/test/ui/issues/issue-20616-2.stderr b/src/test/ui/issues/issue-20616-2.stderr
new file mode 100644
index 0000000..1152dec
--- /dev/null
+++ b/src/test/ui/issues/issue-20616-2.stderr
@@ -0,0 +1,8 @@
+error: expected one of `,` or `>`, found `(`
+  --> $DIR/issue-20616-2.rs:12:31
+   |
+LL | type Type_2 = Type_1_<'static ()>;
+   |                               ^ expected one of `,` or `>` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-20616-3.rs b/src/test/ui/issues/issue-20616-3.rs
new file mode 100644
index 0000000..9bfd5bf
--- /dev/null
+++ b/src/test/ui/issues/issue-20616-3.rs
@@ -0,0 +1,35 @@
+// We need all these 9 issue-20616-N.rs files
+// because we can only catch one parsing error at a time
+
+type Type_1_<'a, T> = &'a T;
+
+
+//type Type_1<'a T> = &'a T; // error: expected `,` or `>` after lifetime name, found `T`
+
+
+//type Type_2 = Type_1_<'static ()>; // error: expected `,` or `>` after lifetime name, found `(`
+
+
+type Type_3<T> = Box<T,,>;
+//~^ error: expected one of `>`, const, identifier, lifetime, or type, found `,`
+
+
+//type Type_4<T> = Type_1_<'static,, T>; // error: expected type, found `,`
+
+
+type Type_5_<'a> = Type_1_<'a, ()>;
+
+
+//type Type_5<'a> = Type_1_<'a, (),,>; // error: expected type, found `,`
+
+
+//type Type_6 = Type_5_<'a,,>; // error: expected type, found `,`
+
+
+//type Type_7 = Box<(),,>; // error: expected type, found `,`
+
+
+//type Type_8<'a,,> = &'a (); // error: expected ident, found `,`
+
+
+//type Type_9<T,,> = Box<T>; // error: expected ident, found `,`
diff --git a/src/test/ui/issues/issue-20616-3.stderr b/src/test/ui/issues/issue-20616-3.stderr
new file mode 100644
index 0000000..f51fb94
--- /dev/null
+++ b/src/test/ui/issues/issue-20616-3.stderr
@@ -0,0 +1,8 @@
+error: expected one of `>`, const, identifier, lifetime, or type, found `,`
+  --> $DIR/issue-20616-3.rs:13:24
+   |
+LL | type Type_3<T> = Box<T,,>;
+   |                        ^ expected one of `>`, const, identifier, lifetime, or type here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-20616-4.rs b/src/test/ui/issues/issue-20616-4.rs
new file mode 100644
index 0000000..e9a34a0
--- /dev/null
+++ b/src/test/ui/issues/issue-20616-4.rs
@@ -0,0 +1,35 @@
+// We need all these 9 issue-20616-N.rs files
+// because we can only catch one parsing error at a time
+
+type Type_1_<'a, T> = &'a T;
+
+
+//type Type_1<'a T> = &'a T; // error: expected `,` or `>` after lifetime name, found `T`
+
+
+//type Type_2 = Type_1_<'static ()>; // error: expected `,` or `>` after lifetime name, found `(`
+
+
+//type Type_3<T> = Box<T,,>; // error: expected type, found `,`
+
+
+type Type_4<T> = Type_1_<'static,, T>;
+//~^ error: expected one of `>`, const, identifier, lifetime, or type, found `,`
+
+
+type Type_5_<'a> = Type_1_<'a, ()>;
+
+
+//type Type_5<'a> = Type_1_<'a, (),,>; // error: expected type, found `,`
+
+
+//type Type_6 = Type_5_<'a,,>; // error: expected type, found `,`
+
+
+//type Type_7 = Box<(),,>; // error: expected type, found `,`
+
+
+//type Type_8<'a,,> = &'a (); // error: expected ident, found `,`
+
+
+//type Type_9<T,,> = Box<T>; // error: expected ident, found `,`
diff --git a/src/test/ui/issues/issue-20616-4.stderr b/src/test/ui/issues/issue-20616-4.stderr
new file mode 100644
index 0000000..22a6554
--- /dev/null
+++ b/src/test/ui/issues/issue-20616-4.stderr
@@ -0,0 +1,8 @@
+error: expected one of `>`, const, identifier, lifetime, or type, found `,`
+  --> $DIR/issue-20616-4.rs:16:34
+   |
+LL | type Type_4<T> = Type_1_<'static,, T>;
+   |                                  ^ expected one of `>`, const, identifier, lifetime, or type here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-20616-5.rs b/src/test/ui/issues/issue-20616-5.rs
new file mode 100644
index 0000000..2386251
--- /dev/null
+++ b/src/test/ui/issues/issue-20616-5.rs
@@ -0,0 +1,35 @@
+// We need all these 9 issue-20616-N.rs files
+// because we can only catch one parsing error at a time
+
+type Type_1_<'a, T> = &'a T;
+
+
+//type Type_1<'a T> = &'a T; // error: expected `,` or `>` after lifetime name, found `T`
+
+
+//type Type_2 = Type_1_<'static ()>; // error: expected `,` or `>` after lifetime name, found `(`
+
+
+//type Type_3<T> = Box<T,,>; // error: expected type, found `,`
+
+
+//type Type_4<T> = Type_1_<'static,, T>; // error: expected type, found `,`
+
+
+type Type_5_<'a> = Type_1_<'a, ()>;
+
+
+type Type_5<'a> = Type_1_<'a, (),,>;
+//~^ error: expected one of `>`, const, identifier, lifetime, or type, found `,`
+
+
+//type Type_6 = Type_5_<'a,,>; // error: expected type, found `,`
+
+
+//type Type_7 = Box<(),,>; // error: expected type, found `,`
+
+
+//type Type_8<'a,,> = &'a (); // error: expected ident, found `,`
+
+
+//type Type_9<T,,> = Box<T>; // error: expected ident, found `,`
diff --git a/src/test/ui/issues/issue-20616-5.stderr b/src/test/ui/issues/issue-20616-5.stderr
new file mode 100644
index 0000000..d83fc41
--- /dev/null
+++ b/src/test/ui/issues/issue-20616-5.stderr
@@ -0,0 +1,8 @@
+error: expected one of `>`, const, identifier, lifetime, or type, found `,`
+  --> $DIR/issue-20616-5.rs:22:34
+   |
+LL | type Type_5<'a> = Type_1_<'a, (),,>;
+   |                                  ^ expected one of `>`, const, identifier, lifetime, or type here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-20616-6.rs b/src/test/ui/issues/issue-20616-6.rs
new file mode 100644
index 0000000..dc327f3
--- /dev/null
+++ b/src/test/ui/issues/issue-20616-6.rs
@@ -0,0 +1,35 @@
+// We need all these 9 issue-20616-N.rs files
+// because we can only catch one parsing error at a time
+
+type Type_1_<'a, T> = &'a T;
+
+
+//type Type_1<'a T> = &'a T; // error: expected `,` or `>` after lifetime name, found `T`
+
+
+//type Type_2 = Type_1_<'static ()>; // error: expected `,` or `>` after lifetime name, found `(`
+
+
+//type Type_3<T> = Box<T,,>; // error: expected type, found `,`
+
+
+//type Type_4<T> = Type_1_<'static,, T>; // error: expected type, found `,`
+
+
+type Type_5_<'a> = Type_1_<'a, ()>;
+
+
+//type Type_5<'a> = Type_1_<'a, (),,>; // error: expected type, found `,`
+
+
+type Type_6 = Type_5_<'a,,>;
+//~^ error: expected one of `>`, const, identifier, lifetime, or type, found `,`
+
+
+//type Type_7 = Box<(),,>; // error: expected type, found `,`
+
+
+//type Type_8<'a,,> = &'a (); // error: expected ident, found `,`
+
+
+//type Type_9<T,,> = Box<T>; // error: expected ident, found `,`
diff --git a/src/test/ui/issues/issue-20616-6.stderr b/src/test/ui/issues/issue-20616-6.stderr
new file mode 100644
index 0000000..0740df5
--- /dev/null
+++ b/src/test/ui/issues/issue-20616-6.stderr
@@ -0,0 +1,8 @@
+error: expected one of `>`, const, identifier, lifetime, or type, found `,`
+  --> $DIR/issue-20616-6.rs:25:26
+   |
+LL | type Type_6 = Type_5_<'a,,>;
+   |                          ^ expected one of `>`, const, identifier, lifetime, or type here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-20616-7.rs b/src/test/ui/issues/issue-20616-7.rs
new file mode 100644
index 0000000..ffd1620
--- /dev/null
+++ b/src/test/ui/issues/issue-20616-7.rs
@@ -0,0 +1,35 @@
+// We need all these 9 issue-20616-N.rs files
+// because we can only catch one parsing error at a time
+
+type Type_1_<'a, T> = &'a T;
+
+
+//type Type_1<'a T> = &'a T; // error: expected `,` or `>` after lifetime name, found `T`
+
+
+//type Type_2 = Type_1_<'static ()>; // error: expected `,` or `>` after lifetime name, found `(`
+
+
+//type Type_3<T> = Box<T,,>; // error: expected type, found `,`
+
+
+//type Type_4<T> = Type_1_<'static,, T>; // error: expected type, found `,`
+
+
+type Type_5_<'a> = Type_1_<'a, ()>;
+
+
+//type Type_5<'a> = Type_1_<'a, (),,>; // error: expected type, found `,`
+
+
+//type Type_6 = Type_5_<'a,,>; // error: expected type, found `,`
+
+
+type Type_7 = Box<(),,>;
+//~^ error: expected one of `>`, const, identifier, lifetime, or type, found `,`
+
+
+//type Type_8<'a,,> = &'a (); // error: expected ident, found `,`
+
+
+//type Type_9<T,,> = Box<T>; // error: expected ident, found `,`
diff --git a/src/test/ui/issues/issue-20616-7.stderr b/src/test/ui/issues/issue-20616-7.stderr
new file mode 100644
index 0000000..c0e1083
--- /dev/null
+++ b/src/test/ui/issues/issue-20616-7.stderr
@@ -0,0 +1,8 @@
+error: expected one of `>`, const, identifier, lifetime, or type, found `,`
+  --> $DIR/issue-20616-7.rs:28:22
+   |
+LL | type Type_7 = Box<(),,>;
+   |                      ^ expected one of `>`, const, identifier, lifetime, or type here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-20616-8.rs b/src/test/ui/issues/issue-20616-8.rs
new file mode 100644
index 0000000..c9e8b61
--- /dev/null
+++ b/src/test/ui/issues/issue-20616-8.rs
@@ -0,0 +1,35 @@
+// We need all these 9 issue-20616-N.rs files
+// because we can only catch one parsing error at a time
+
+type Type_1_<'a, T> = &'a T;
+
+
+//type Type_1<'a T> = &'a T; // error: expected `,` or `>` after lifetime name, found `T`
+
+
+//type Type_2 = Type_1_<'static ()>; // error: expected `,` or `>` after lifetime name, found `(`
+
+
+//type Type_3<T> = Box<T,,>; // error: expected type, found `,`
+
+
+//type Type_4<T> = Type_1_<'static,, T>; // error: expected type, found `,`
+
+
+type Type_5_<'a> = Type_1_<'a, ()>;
+
+
+//type Type_5<'a> = Type_1_<'a, (),,>; // error: expected type, found `,`
+
+
+//type Type_6 = Type_5_<'a,,>; // error: expected type, found `,`
+
+
+//type Type_7 = Box<(),,>; // error: expected type, found `,`
+
+
+type Type_8<'a,,> = &'a ();
+//~^ error: expected one of `>`, `const`, identifier, or lifetime, found `,`
+
+
+//type Type_9<T,,> = Box<T>; // error: expected identifier, found `,`
diff --git a/src/test/ui/issues/issue-20616-8.stderr b/src/test/ui/issues/issue-20616-8.stderr
new file mode 100644
index 0000000..0ef9192
--- /dev/null
+++ b/src/test/ui/issues/issue-20616-8.stderr
@@ -0,0 +1,8 @@
+error: expected one of `>`, `const`, identifier, or lifetime, found `,`
+  --> $DIR/issue-20616-8.rs:31:16
+   |
+LL | type Type_8<'a,,> = &'a ();
+   |                ^ expected one of `>`, `const`, identifier, or lifetime here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-20616-9.rs b/src/test/ui/issues/issue-20616-9.rs
new file mode 100644
index 0000000..1c509f2
--- /dev/null
+++ b/src/test/ui/issues/issue-20616-9.rs
@@ -0,0 +1,35 @@
+// We need all these 9 issue-20616-N.rs files
+// because we can only catch one parsing error at a time
+
+type Type_1_<'a, T> = &'a T;
+
+
+//type Type_1<'a T> = &'a T; // error: expected `,` or `>` after lifetime name, found `T`
+
+
+//type Type_2 = Type_1_<'static ()>; // error: expected `,` or `>` after lifetime name, found `(`
+
+
+//type Type_3<T> = Box<T,,>; // error: expected type, found `,`
+
+
+//type Type_4<T> = Type_1_<'static,, T>; // error: expected type, found `,`
+
+
+type Type_5_<'a> = Type_1_<'a, ()>;
+
+
+//type Type_5<'a> = Type_1_<'a, (),,>; // error: expected type, found `,`
+
+
+//type Type_6 = Type_5_<'a,,>; // error: expected type, found `,`
+
+
+//type Type_7 = Box<(),,>; // error: expected type, found `,`
+
+
+//type Type_8<'a,,> = &'a (); // error: expected identifier, found `,`
+
+
+type Type_9<T,,> = Box<T>;
+//~^ error: expected one of `>`, `const`, identifier, or lifetime, found `,`
diff --git a/src/test/ui/issues/issue-20616-9.stderr b/src/test/ui/issues/issue-20616-9.stderr
new file mode 100644
index 0000000..5fd1400
--- /dev/null
+++ b/src/test/ui/issues/issue-20616-9.stderr
@@ -0,0 +1,8 @@
+error: expected one of `>`, `const`, identifier, or lifetime, found `,`
+  --> $DIR/issue-20616-9.rs:34:15
+   |
+LL | type Type_9<T,,> = Box<T>;
+   |               ^ expected one of `>`, `const`, identifier, or lifetime here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-2063-resource.rs b/src/test/ui/issues/issue-2063-resource.rs
new file mode 100644
index 0000000..6ed3e02
--- /dev/null
+++ b/src/test/ui/issues/issue-2063-resource.rs
@@ -0,0 +1,14 @@
+// compile-pass
+#![allow(dead_code)]
+// test that autoderef of a type like this does not
+// cause compiler to loop.  Note that no instances
+// of such a type could ever be constructed.
+
+struct S {
+  x: X,
+  to_str: (),
+}
+
+struct X(Box<S>);
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-20644.rs b/src/test/ui/issues/issue-20644.rs
new file mode 100644
index 0000000..db32344
--- /dev/null
+++ b/src/test/ui/issues/issue-20644.rs
@@ -0,0 +1,35 @@
+// compile-pass
+#![allow(dead_code)]
+#![allow(unused_imports)]
+#![allow(stable_features)]
+
+// A reduced version of the rustbook ice. The problem this encountered
+// had to do with codegen ignoring binders.
+
+// pretty-expanded FIXME #23616
+// ignore-cloudabi no std::fs
+
+#![feature(os)]
+
+use std::iter;
+use std::os;
+use std::fs::File;
+use std::io::prelude::*;
+use std::env;
+use std::path::Path;
+
+pub fn parse_summary<R: Read>(_: R, _: &Path) {
+     let path_from_root = Path::new("");
+     Path::new(&iter::repeat("../")
+               .take(path_from_root.components().count() - 1)
+               .collect::<String>());
+ }
+
+fn foo() {
+    let cwd = env::current_dir().unwrap();
+    let src = cwd.clone();
+    let summary = File::open(&src.join("SUMMARY.md")).unwrap();
+    let _ = parse_summary(summary, &src);
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-20692.rs b/src/test/ui/issues/issue-20692.rs
new file mode 100644
index 0000000..ea89bca
--- /dev/null
+++ b/src/test/ui/issues/issue-20692.rs
@@ -0,0 +1,11 @@
+trait Array: Sized {}
+
+fn f<T: Array>(x: &T) {
+    let _ = x
+    //~^ ERROR `Array` cannot be made into an object
+    as
+    &Array;
+    //~^ ERROR `Array` cannot be made into an object
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-20692.stderr b/src/test/ui/issues/issue-20692.stderr
new file mode 100644
index 0000000..acc223c
--- /dev/null
+++ b/src/test/ui/issues/issue-20692.stderr
@@ -0,0 +1,20 @@
+error[E0038]: the trait `Array` cannot be made into an object
+  --> $DIR/issue-20692.rs:7:5
+   |
+LL |     &Array;
+   |     ^^^^^^ the trait `Array` cannot be made into an object
+   |
+   = note: the trait cannot require that `Self : Sized`
+
+error[E0038]: the trait `Array` cannot be made into an object
+  --> $DIR/issue-20692.rs:4:13
+   |
+LL |     let _ = x
+   |             ^ the trait `Array` cannot be made into an object
+   |
+   = note: the trait cannot require that `Self : Sized`
+   = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Array>` for `&T`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/issues/issue-20714.rs b/src/test/ui/issues/issue-20714.rs
new file mode 100644
index 0000000..0a4817c
--- /dev/null
+++ b/src/test/ui/issues/issue-20714.rs
@@ -0,0 +1,5 @@
+struct G;
+
+fn main() {
+    let g = G(); //~ ERROR: expected function, found `G`
+}
diff --git a/src/test/ui/issues/issue-20714.stderr b/src/test/ui/issues/issue-20714.stderr
new file mode 100644
index 0000000..456aff0
--- /dev/null
+++ b/src/test/ui/issues/issue-20714.stderr
@@ -0,0 +1,14 @@
+error[E0618]: expected function, found `G`
+  --> $DIR/issue-20714.rs:4:13
+   |
+LL | struct G;
+   | --------- `G` defined here
+...
+LL |     let g = G();
+   |             ^--
+   |             |
+   |             call expression requires function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0618`.
diff --git a/src/test/ui/issues/issue-20763-1.rs b/src/test/ui/issues/issue-20763-1.rs
new file mode 100644
index 0000000..c5b2852
--- /dev/null
+++ b/src/test/ui/issues/issue-20763-1.rs
@@ -0,0 +1,29 @@
+// compile-pass
+#![allow(dead_code)]
+// pretty-expanded FIXME #23616
+
+trait T0 {
+    type O;
+    fn dummy(&self) { }
+}
+
+struct S<A>(A);
+impl<A> T0 for S<A> { type O = A; }
+
+trait T1: T0 {
+    // this looks okay but as we see below, `f` is unusable
+    fn m0<F: Fn(<Self as T0>::O) -> bool>(self, f: F) -> bool;
+}
+
+// complains about the bounds on F here not being required by the trait
+impl<A> T1 for S<A> {
+    fn m0<F: Fn(A) -> bool>(self, f: F) -> bool { f(self.0) }
+}
+
+// // complains about mismatched types: <S<A> as T0>::O vs. A
+// impl<A> T1 for S<A>
+// {
+//     fn m0<F: Fn(<Self as T0>::O) -> bool>(self, f: F) -> bool { f(self.0) }
+// }
+
+fn main() { }
diff --git a/src/test/ui/issues/issue-20763-2.rs b/src/test/ui/issues/issue-20763-2.rs
new file mode 100644
index 0000000..cfa252b
--- /dev/null
+++ b/src/test/ui/issues/issue-20763-2.rs
@@ -0,0 +1,24 @@
+// compile-pass
+#![allow(dead_code)]
+// pretty-expanded FIXME #23616
+
+trait T0 {
+    type O;
+    fn dummy(&self) { }
+}
+
+struct S<A>(A);
+impl<A> T0 for S<A> { type O = A; }
+
+trait T1: T0 {
+    // this looks okay but as we see below, `f` is unusable
+    fn m0<F: Fn(<Self as T0>::O) -> bool>(self, f: F) -> bool;
+}
+
+// complains about mismatched types: <S<A> as T0>::O vs. A
+impl<A> T1 for S<A>
+{
+    fn m0<F: Fn(<Self as T0>::O) -> bool>(self, f: F) -> bool { f(self.0) }
+}
+
+fn main() { }
diff --git a/src/test/ui/issues/issue-20772.rs b/src/test/ui/issues/issue-20772.rs
new file mode 100644
index 0000000..36551e7
--- /dev/null
+++ b/src/test/ui/issues/issue-20772.rs
@@ -0,0 +1,6 @@
+trait T : Iterator<Item=Self::Item>
+//~^ ERROR cycle detected
+//~| ERROR associated type `Item` not found for `Self`
+{}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-20772.stderr b/src/test/ui/issues/issue-20772.stderr
new file mode 100644
index 0000000..e67fedc
--- /dev/null
+++ b/src/test/ui/issues/issue-20772.stderr
@@ -0,0 +1,29 @@
+error[E0391]: cycle detected when computing the supertraits of `T`
+  --> $DIR/issue-20772.rs:1:1
+   |
+LL | / trait T : Iterator<Item=Self::Item>
+LL | |
+LL | |
+LL | | {}
+   | |__^
+   |
+   = note: ...which again requires computing the supertraits of `T`, completing the cycle
+note: cycle used when collecting item types in top-level module
+  --> $DIR/issue-20772.rs:1:1
+   |
+LL | / trait T : Iterator<Item=Self::Item>
+LL | |
+LL | |
+LL | | {}
+   | |__^
+
+error[E0220]: associated type `Item` not found for `Self`
+  --> $DIR/issue-20772.rs:1:25
+   |
+LL | trait T : Iterator<Item=Self::Item>
+   |                         ^^^^^^^^^^ associated type `Item` not found
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0220, E0391.
+For more information about an error, try `rustc --explain E0220`.
diff --git a/src/test/ui/issues/issue-20797.rs b/src/test/ui/issues/issue-20797.rs
new file mode 100644
index 0000000..e504b47
--- /dev/null
+++ b/src/test/ui/issues/issue-20797.rs
@@ -0,0 +1,94 @@
+// compile-pass
+// ignore-cloudabi no std::fs
+
+// Regression test for #20797.
+
+use std::default::Default;
+use std::io;
+use std::fs;
+use std::path::PathBuf;
+
+pub trait PathExtensions {
+    fn is_dir(&self) -> bool { false }
+}
+
+impl PathExtensions for PathBuf {}
+
+/// A strategy for acquiring more subpaths to walk.
+pub trait Strategy {
+    type P: PathExtensions;
+    /// Gets additional subpaths from a given path.
+    fn get_more(&self, item: &Self::P) -> io::Result<Vec<Self::P>>;
+    /// Determine whether a path should be walked further.
+    /// This is run against each item from `get_more()`.
+    fn prune(&self, p: &Self::P) -> bool;
+}
+
+/// The basic fully-recursive strategy. Nothing is pruned.
+#[derive(Copy, Clone, Default)]
+pub struct Recursive;
+
+impl Strategy for Recursive {
+    type P = PathBuf;
+    fn get_more(&self, p: &PathBuf) -> io::Result<Vec<PathBuf>> {
+        Ok(fs::read_dir(p).unwrap().map(|s| s.unwrap().path()).collect())
+    }
+
+    fn prune(&self, _: &PathBuf) -> bool { false }
+}
+
+/// A directory walker of `P` using strategy `S`.
+pub struct Subpaths<S: Strategy> {
+    stack: Vec<S::P>,
+    strategy: S,
+}
+
+impl<S: Strategy> Subpaths<S> {
+    /// Creates a directory walker with a root path and strategy.
+    pub fn new(p: &S::P, strategy: S) -> io::Result<Subpaths<S>> {
+        let stack = strategy.get_more(p)?;
+        Ok(Subpaths { stack: stack, strategy: strategy })
+    }
+}
+
+impl<S: Default + Strategy> Subpaths<S> {
+    /// Creates a directory walker with a root path and a default strategy.
+    pub fn walk(p: &S::P) -> io::Result<Subpaths<S>> {
+        Subpaths::new(p, Default::default())
+    }
+}
+
+impl<S: Default + Strategy> Default for Subpaths<S> {
+    fn default() -> Subpaths<S> {
+        Subpaths { stack: Vec::new(), strategy: Default::default() }
+    }
+}
+
+impl<S: Strategy> Iterator for Subpaths<S> {
+    type Item = S::P;
+    fn next (&mut self) -> Option<S::P> {
+        let mut opt_path = self.stack.pop();
+        while opt_path.is_some() && self.strategy.prune(opt_path.as_ref().unwrap()) {
+            opt_path = self.stack.pop();
+        }
+        match opt_path {
+            Some(path) => {
+                if path.is_dir() {
+                    let result = self.strategy.get_more(&path);
+                    match result {
+                        Ok(dirs) => { self.stack.extend(dirs); },
+                        Err(..) => { }
+                    }
+                }
+                Some(path)
+            }
+            None => None,
+        }
+    }
+}
+
+fn _foo() {
+    let _walker: Subpaths<Recursive> = Subpaths::walk(&PathBuf::from("/home")).unwrap();
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-20801.nll.stderr b/src/test/ui/issues/issue-20801.nll.stderr
new file mode 100644
index 0000000..adcbe55
--- /dev/null
+++ b/src/test/ui/issues/issue-20801.nll.stderr
@@ -0,0 +1,39 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/issue-20801.rs:26:22
+   |
+LL |     let a = unsafe { *mut_ref() };
+   |                      ^^^^^^^^^^
+   |                      |
+   |                      cannot move out of borrowed content
+   |                      help: consider removing the `*`: `mut_ref()`
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/issue-20801.rs:29:22
+   |
+LL |     let b = unsafe { *imm_ref() };
+   |                      ^^^^^^^^^^
+   |                      |
+   |                      cannot move out of borrowed content
+   |                      help: consider removing the `*`: `imm_ref()`
+
+error[E0507]: cannot move out of dereference of raw pointer
+  --> $DIR/issue-20801.rs:32:22
+   |
+LL |     let c = unsafe { *mut_ptr() };
+   |                      ^^^^^^^^^^
+   |                      |
+   |                      cannot move out of dereference of raw pointer
+   |                      help: consider removing the `*`: `mut_ptr()`
+
+error[E0507]: cannot move out of dereference of raw pointer
+  --> $DIR/issue-20801.rs:35:22
+   |
+LL |     let d = unsafe { *const_ptr() };
+   |                      ^^^^^^^^^^^^
+   |                      |
+   |                      cannot move out of dereference of raw pointer
+   |                      help: consider removing the `*`: `const_ptr()`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/issues/issue-20801.rs b/src/test/ui/issues/issue-20801.rs
new file mode 100644
index 0000000..6f8ce66
--- /dev/null
+++ b/src/test/ui/issues/issue-20801.rs
@@ -0,0 +1,37 @@
+// We used to ICE when moving out of a `*mut T` or `*const T`.
+
+struct T(u8);
+
+static mut GLOBAL_MUT_T: T = T(0);
+
+static GLOBAL_T: T = T(0);
+
+fn imm_ref() -> &'static T {
+    unsafe { &GLOBAL_T }
+}
+
+fn mut_ref() -> &'static mut T {
+    unsafe { &mut GLOBAL_MUT_T }
+}
+
+fn mut_ptr() -> *mut T {
+    unsafe { 0 as *mut T }
+}
+
+fn const_ptr() -> *const T {
+    unsafe { 0 as *const T }
+}
+
+pub fn main() {
+    let a = unsafe { *mut_ref() };
+    //~^ ERROR cannot move out of borrowed content
+
+    let b = unsafe { *imm_ref() };
+    //~^ ERROR cannot move out of borrowed content
+
+    let c = unsafe { *mut_ptr() };
+    //~^ ERROR cannot move out of dereference of raw pointer
+
+    let d = unsafe { *const_ptr() };
+    //~^ ERROR cannot move out of dereference of raw pointer
+}
diff --git a/src/test/ui/issues/issue-20801.stderr b/src/test/ui/issues/issue-20801.stderr
new file mode 100644
index 0000000..3e27391
--- /dev/null
+++ b/src/test/ui/issues/issue-20801.stderr
@@ -0,0 +1,27 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/issue-20801.rs:26:22
+   |
+LL |     let a = unsafe { *mut_ref() };
+   |                      ^^^^^^^^^^ cannot move out of borrowed content
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/issue-20801.rs:29:22
+   |
+LL |     let b = unsafe { *imm_ref() };
+   |                      ^^^^^^^^^^ cannot move out of borrowed content
+
+error[E0507]: cannot move out of dereference of raw pointer
+  --> $DIR/issue-20801.rs:32:22
+   |
+LL |     let c = unsafe { *mut_ptr() };
+   |                      ^^^^^^^^^^ cannot move out of dereference of raw pointer
+
+error[E0507]: cannot move out of dereference of raw pointer
+  --> $DIR/issue-20801.rs:35:22
+   |
+LL |     let d = unsafe { *const_ptr() };
+   |                      ^^^^^^^^^^^^ cannot move out of dereference of raw pointer
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/issues/issue-20825-2.rs b/src/test/ui/issues/issue-20825-2.rs
new file mode 100644
index 0000000..cceed54
--- /dev/null
+++ b/src/test/ui/issues/issue-20825-2.rs
@@ -0,0 +1,10 @@
+// compile-pass
+pub trait Subscriber {
+    type Input;
+}
+
+pub trait Processor: Subscriber<Input = <Self as Processor>::Input> {
+    type Input;
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-20825.rs b/src/test/ui/issues/issue-20825.rs
new file mode 100644
index 0000000..516c304
--- /dev/null
+++ b/src/test/ui/issues/issue-20825.rs
@@ -0,0 +1,10 @@
+pub trait Subscriber {
+    type Input;
+}
+
+pub trait Processor: Subscriber<Input = Self::Input> {
+    //~^ ERROR cycle detected
+    type Input;
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-20825.stderr b/src/test/ui/issues/issue-20825.stderr
new file mode 100644
index 0000000..5f9709d
--- /dev/null
+++ b/src/test/ui/issues/issue-20825.stderr
@@ -0,0 +1,16 @@
+error[E0391]: cycle detected when computing the supertraits of `Processor`
+  --> $DIR/issue-20825.rs:5:1
+   |
+LL | pub trait Processor: Subscriber<Input = Self::Input> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: ...which again requires computing the supertraits of `Processor`, completing the cycle
+note: cycle used when collecting item types in top-level module
+  --> $DIR/issue-20825.rs:5:1
+   |
+LL | pub trait Processor: Subscriber<Input = Self::Input> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/issues/issue-20831-debruijn.rs b/src/test/ui/issues/issue-20831-debruijn.rs
new file mode 100644
index 0000000..6d3c733
--- /dev/null
+++ b/src/test/ui/issues/issue-20831-debruijn.rs
@@ -0,0 +1,41 @@
+// Regression test for #20831: debruijn index account was thrown off
+// by the (anonymous) lifetime in `<Self as Publisher>::Output`
+// below. Note that changing to a named lifetime made the problem go
+// away.
+
+use std::cell::RefCell;
+use std::ops::{Shl, Shr};
+
+pub trait Subscriber {
+    type Input;
+}
+
+pub trait Publisher<'a> {
+    type Output;
+    fn subscribe(&mut self, _: Box<Subscriber<Input=Self::Output> + 'a>);
+}
+
+pub trait Processor<'a> : Subscriber + Publisher<'a> { }
+
+impl<'a, P> Processor<'a> for P where P : Subscriber + Publisher<'a> { }
+
+struct MyStruct<'a> {
+    sub: Box<Subscriber<Input=u64> + 'a>
+}
+
+impl<'a> Publisher<'a> for MyStruct<'a> {
+    type Output = u64;
+    fn subscribe(&mut self, t : Box<Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
+        // Not obvious, but there is an implicit lifetime here -------^
+        //~^^ ERROR cannot infer
+        //~| ERROR mismatched types
+        //~| ERROR mismatched types
+        //
+        // The fact that `Publisher` is using an implicit lifetime is
+        // what was causing the debruijn accounting to be off, so
+        // leave it that way!
+        self.sub = t;
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-20831-debruijn.stderr b/src/test/ui/issues/issue-20831-debruijn.stderr
new file mode 100644
index 0000000..e20869a
--- /dev/null
+++ b/src/test/ui/issues/issue-20831-debruijn.stderr
@@ -0,0 +1,98 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-20831-debruijn.rs:28:5
+   |
+LL | /     fn subscribe(&mut self, t : Box<Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
+LL | |         // Not obvious, but there is an implicit lifetime here -------^
+LL | |
+LL | |
+...  |
+LL | |         self.sub = t;
+LL | |     }
+   | |_____^ lifetime mismatch
+   |
+   = note: expected type `'a`
+              found type `'_`
+note: the anonymous lifetime #2 defined on the method body at 28:5...
+  --> $DIR/issue-20831-debruijn.rs:28:5
+   |
+LL | /     fn subscribe(&mut self, t : Box<Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
+LL | |         // Not obvious, but there is an implicit lifetime here -------^
+LL | |
+LL | |
+...  |
+LL | |         self.sub = t;
+LL | |     }
+   | |_____^
+note: ...does not necessarily outlive the lifetime 'a as defined on the impl at 26:6
+  --> $DIR/issue-20831-debruijn.rs:26:6
+   |
+LL | impl<'a> Publisher<'a> for MyStruct<'a> {
+   |      ^^
+
+error[E0308]: mismatched types
+  --> $DIR/issue-20831-debruijn.rs:28:5
+   |
+LL | /     fn subscribe(&mut self, t : Box<Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
+LL | |         // Not obvious, but there is an implicit lifetime here -------^
+LL | |
+LL | |
+...  |
+LL | |         self.sub = t;
+LL | |     }
+   | |_____^ lifetime mismatch
+   |
+   = note: expected type `'a`
+              found type `'_`
+note: the lifetime 'a as defined on the impl at 26:6...
+  --> $DIR/issue-20831-debruijn.rs:26:6
+   |
+LL | impl<'a> Publisher<'a> for MyStruct<'a> {
+   |      ^^
+note: ...does not necessarily outlive the anonymous lifetime #2 defined on the method body at 28:5
+  --> $DIR/issue-20831-debruijn.rs:28:5
+   |
+LL | /     fn subscribe(&mut self, t : Box<Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
+LL | |         // Not obvious, but there is an implicit lifetime here -------^
+LL | |
+LL | |
+...  |
+LL | |         self.sub = t;
+LL | |     }
+   | |_____^
+
+error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
+  --> $DIR/issue-20831-debruijn.rs:28:5
+   |
+LL | /     fn subscribe(&mut self, t : Box<Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
+LL | |         // Not obvious, but there is an implicit lifetime here -------^
+LL | |
+LL | |
+...  |
+LL | |         self.sub = t;
+LL | |     }
+   | |_____^
+   |
+note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the method body at 28:5...
+  --> $DIR/issue-20831-debruijn.rs:28:5
+   |
+LL | /     fn subscribe(&mut self, t : Box<Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
+LL | |         // Not obvious, but there is an implicit lifetime here -------^
+LL | |
+LL | |
+...  |
+LL | |         self.sub = t;
+LL | |     }
+   | |_____^
+note: ...but the lifetime must also be valid for the lifetime 'a as defined on the impl at 26:6...
+  --> $DIR/issue-20831-debruijn.rs:26:6
+   |
+LL | impl<'a> Publisher<'a> for MyStruct<'a> {
+   |      ^^
+   = note: ...so that the types are compatible:
+           expected Publisher<'_>
+              found Publisher<'_>
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0308, E0495.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-20939.rs b/src/test/ui/issues/issue-20939.rs
new file mode 100644
index 0000000..259fff2
--- /dev/null
+++ b/src/test/ui/issues/issue-20939.rs
@@ -0,0 +1,6 @@
+trait Foo {}
+
+impl<'a> Foo for Foo+'a {}
+//~^ ERROR the object type `(dyn Foo + 'a)` automatically implements the trait `Foo`
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-20939.stderr b/src/test/ui/issues/issue-20939.stderr
new file mode 100644
index 0000000..d15a519
--- /dev/null
+++ b/src/test/ui/issues/issue-20939.stderr
@@ -0,0 +1,9 @@
+error[E0371]: the object type `(dyn Foo + 'a)` automatically implements the trait `Foo`
+  --> $DIR/issue-20939.rs:3:1
+   |
+LL | impl<'a> Foo for Foo+'a {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Foo + 'a)` automatically implements trait `Foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0371`.
diff --git a/src/test/ui/issues/issue-2111.rs b/src/test/ui/issues/issue-2111.rs
new file mode 100644
index 0000000..7e5835e
--- /dev/null
+++ b/src/test/ui/issues/issue-2111.rs
@@ -0,0 +1,12 @@
+fn foo(a: Option<usize>, b: Option<usize>) {
+  match (a,b) {
+  //~^ ERROR: non-exhaustive patterns: `(None, None)` not covered
+    (Some(a), Some(b)) if a == b => { }
+    (Some(_), None) |
+    (None, Some(_)) => { }
+  }
+}
+
+fn main() {
+  foo(None, None);
+}
diff --git a/src/test/ui/issues/issue-2111.stderr b/src/test/ui/issues/issue-2111.stderr
new file mode 100644
index 0000000..90fdb48
--- /dev/null
+++ b/src/test/ui/issues/issue-2111.stderr
@@ -0,0 +1,11 @@
+error[E0004]: non-exhaustive patterns: `(None, None)` not covered
+  --> $DIR/issue-2111.rs:2:9
+   |
+LL |   match (a,b) {
+   |         ^^^^^ pattern `(None, None)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/issues/issue-21140.rs b/src/test/ui/issues/issue-21140.rs
new file mode 100644
index 0000000..86d4e63
--- /dev/null
+++ b/src/test/ui/issues/issue-21140.rs
@@ -0,0 +1,6 @@
+// compile-pass
+pub trait Trait where Self::Out: std::fmt::Display {
+    type Out;
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-21146.rs b/src/test/ui/issues/issue-21146.rs
new file mode 100644
index 0000000..19eaffc
--- /dev/null
+++ b/src/test/ui/issues/issue-21146.rs
@@ -0,0 +1,3 @@
+// error-pattern: expected one of `!` or `::`, found `<eof>`
+include!("auxiliary/issue-21146-inc.rs");
+fn main() {}
diff --git a/src/test/ui/issues/issue-21146.stderr b/src/test/ui/issues/issue-21146.stderr
new file mode 100644
index 0000000..2798196
--- /dev/null
+++ b/src/test/ui/issues/issue-21146.stderr
@@ -0,0 +1,8 @@
+error: expected one of `!` or `::`, found `<eof>`
+  --> $DIR/auxiliary/issue-21146-inc.rs:3:1
+   |
+LL | parse_error
+   | ^^^^^^^^^^^ expected one of `!` or `::` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-21160.rs b/src/test/ui/issues/issue-21160.rs
new file mode 100644
index 0000000..4673356
--- /dev/null
+++ b/src/test/ui/issues/issue-21160.rs
@@ -0,0 +1,11 @@
+struct Bar;
+
+impl Bar {
+    fn hash<T>(&self, _: T) {}
+}
+
+#[derive(Hash)]
+struct Foo(Bar);
+//~^ error: `Bar: std::hash::Hash` is not satisfied
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-21160.stderr b/src/test/ui/issues/issue-21160.stderr
new file mode 100644
index 0000000..e32343e
--- /dev/null
+++ b/src/test/ui/issues/issue-21160.stderr
@@ -0,0 +1,11 @@
+error[E0277]: the trait bound `Bar: std::hash::Hash` is not satisfied
+  --> $DIR/issue-21160.rs:8:12
+   |
+LL | struct Foo(Bar);
+   |            ^^^ the trait `std::hash::Hash` is not implemented for `Bar`
+   |
+   = note: required by `std::hash::Hash::hash`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-21174-2.rs b/src/test/ui/issues/issue-21174-2.rs
new file mode 100644
index 0000000..145b062
--- /dev/null
+++ b/src/test/ui/issues/issue-21174-2.rs
@@ -0,0 +1,13 @@
+// compile-pass
+#![allow(dead_code)]
+#![allow(unused_variables)]
+trait Trait<'a> {
+    type A;
+    type B;
+}
+
+fn foo<'a, T: Trait<'a>>(value: T::A) {
+    let new: T::B = unsafe { std::mem::transmute_copy(&value) };
+}
+
+fn main() { }
diff --git a/src/test/ui/issues/issue-21174.rs b/src/test/ui/issues/issue-21174.rs
new file mode 100644
index 0000000..0782742
--- /dev/null
+++ b/src/test/ui/issues/issue-21174.rs
@@ -0,0 +1,11 @@
+trait Trait<'a> {
+    type A;
+    type B;
+}
+
+fn foo<'a, T: Trait<'a>>(value: T::A) {
+    let new: T::B = unsafe { std::mem::transmute(value) };
+//~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types
+}
+
+fn main() { }
diff --git a/src/test/ui/issues/issue-21174.stderr b/src/test/ui/issues/issue-21174.stderr
new file mode 100644
index 0000000..5ac5a86
--- /dev/null
+++ b/src/test/ui/issues/issue-21174.stderr
@@ -0,0 +1,12 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/issue-21174.rs:7:30
+   |
+LL |     let new: T::B = unsafe { std::mem::transmute(value) };
+   |                              ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: source type: `<T as Trait<'a>>::A` (size can vary because of <T as Trait>::A)
+   = note: target type: `<T as Trait<'a>>::B` (size can vary because of <T as Trait>::B)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0512`.
diff --git a/src/test/ui/issues/issue-21177.rs b/src/test/ui/issues/issue-21177.rs
new file mode 100644
index 0000000..9d15369
--- /dev/null
+++ b/src/test/ui/issues/issue-21177.rs
@@ -0,0 +1,10 @@
+trait Trait {
+    type A;
+    type B;
+}
+
+fn foo<T: Trait<A = T::B>>() { }
+//~^ ERROR cycle detected
+//~| ERROR associated type `B` not found for `T`
+
+fn main() { }
diff --git a/src/test/ui/issues/issue-21177.stderr b/src/test/ui/issues/issue-21177.stderr
new file mode 100644
index 0000000..c3d2c6f
--- /dev/null
+++ b/src/test/ui/issues/issue-21177.stderr
@@ -0,0 +1,23 @@
+error[E0391]: cycle detected when computing the bounds for type parameter `T`
+  --> $DIR/issue-21177.rs:6:21
+   |
+LL | fn foo<T: Trait<A = T::B>>() { }
+   |                     ^^^^
+   |
+   = note: ...which again requires computing the bounds for type parameter `T`, completing the cycle
+note: cycle used when processing `foo`
+  --> $DIR/issue-21177.rs:6:21
+   |
+LL | fn foo<T: Trait<A = T::B>>() { }
+   |                     ^^^^
+
+error[E0220]: associated type `B` not found for `T`
+  --> $DIR/issue-21177.rs:6:21
+   |
+LL | fn foo<T: Trait<A = T::B>>() { }
+   |                     ^^^^ associated type `B` not found
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0220, E0391.
+For more information about an error, try `rustc --explain E0220`.
diff --git a/src/test/ui/issues/issue-21202.rs b/src/test/ui/issues/issue-21202.rs
new file mode 100644
index 0000000..2c5f139
--- /dev/null
+++ b/src/test/ui/issues/issue-21202.rs
@@ -0,0 +1,15 @@
+// aux-build:issue-21202.rs
+
+extern crate issue_21202 as crate1;
+
+use crate1::A;
+
+mod B {
+    use crate1::A::Foo;
+    fn bar(f: Foo) {
+        Foo::foo(&f);
+        //~^ ERROR: method `foo` is private
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/issues/issue-21202.stderr b/src/test/ui/issues/issue-21202.stderr
new file mode 100644
index 0000000..d19e42d
--- /dev/null
+++ b/src/test/ui/issues/issue-21202.stderr
@@ -0,0 +1,9 @@
+error[E0624]: method `foo` is private
+  --> $DIR/issue-21202.rs:10:9
+   |
+LL |         Foo::foo(&f);
+   |         ^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0624`.
diff --git a/src/test/ui/issues/issue-21245.rs b/src/test/ui/issues/issue-21245.rs
new file mode 100644
index 0000000..edf482a
--- /dev/null
+++ b/src/test/ui/issues/issue-21245.rs
@@ -0,0 +1,56 @@
+// compile-pass
+#![allow(dead_code)]
+// Regression test for issue #21245. Check that we are able to infer
+// the types in these examples correctly. It used to be that
+// insufficient type propagation caused the type of the iterator to be
+// incorrectly unified with the `*const` type to which it is coerced.
+
+// pretty-expanded FIXME #23616
+
+use std::ptr;
+
+trait IntoIterator {
+    type Iter: Iterator;
+
+    fn into_iter2(self) -> Self::Iter;
+}
+
+impl<I> IntoIterator for I where I: Iterator {
+    type Iter = I;
+
+    fn into_iter2(self) -> I {
+        self
+    }
+}
+
+fn desugared_for_loop_bad<T>(v: Vec<T>) {
+    match IntoIterator::into_iter2(v.iter()) {
+        mut iter => {
+            loop {
+                match ::std::iter::Iterator::next(&mut iter) {
+                    ::std::option::Option::Some(x) => {
+                        unsafe { ptr::read(x); }
+                    },
+                    ::std::option::Option::None => break
+                }
+            }
+        }
+    }
+}
+
+fn desugared_for_loop_good<T>(v: Vec<T>) {
+    match v.iter().into_iter() {
+        mut iter => {
+            loop {
+                match ::std::iter::Iterator::next(&mut iter) {
+                    ::std::option::Option::Some(x) => {
+                        unsafe { ptr::read(x); }
+                    },
+                    ::std::option::Option::None => break
+                }
+            }
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-21332.rs b/src/test/ui/issues/issue-21332.rs
new file mode 100644
index 0000000..db157f0
--- /dev/null
+++ b/src/test/ui/issues/issue-21332.rs
@@ -0,0 +1,10 @@
+struct S;
+
+impl Iterator for S {
+    type Item = i32;
+    fn next(&mut self) -> Result<i32, i32> { Ok(7) }
+    //~^ ERROR method `next` has an incompatible type for trait
+    //~| expected enum `std::option::Option`, found enum `std::result::Result`
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-21332.stderr b/src/test/ui/issues/issue-21332.stderr
new file mode 100644
index 0000000..693b2be
--- /dev/null
+++ b/src/test/ui/issues/issue-21332.stderr
@@ -0,0 +1,12 @@
+error[E0053]: method `next` has an incompatible type for trait
+  --> $DIR/issue-21332.rs:5:5
+   |
+LL |     fn next(&mut self) -> Result<i32, i32> { Ok(7) }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `std::option::Option`, found enum `std::result::Result`
+   |
+   = note: expected type `fn(&mut S) -> std::option::Option<i32>`
+              found type `fn(&mut S) -> std::result::Result<i32, i32>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0053`.
diff --git a/src/test/ui/issues/issue-21356.rs b/src/test/ui/issues/issue-21356.rs
new file mode 100644
index 0000000..ae62392
--- /dev/null
+++ b/src/test/ui/issues/issue-21356.rs
@@ -0,0 +1,6 @@
+#![allow(unused_macros)]
+
+macro_rules! test { ($wrong:t_ty ..) => () }
+                  //~^ ERROR: invalid fragment specifier `t_ty`
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-21356.stderr b/src/test/ui/issues/issue-21356.stderr
new file mode 100644
index 0000000..17014c6
--- /dev/null
+++ b/src/test/ui/issues/issue-21356.stderr
@@ -0,0 +1,10 @@
+error: invalid fragment specifier `t_ty`
+  --> $DIR/issue-21356.rs:3:22
+   |
+LL | macro_rules! test { ($wrong:t_ty ..) => () }
+   |                      ^^^^^^^^^^^
+   |
+   = help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-21363.rs b/src/test/ui/issues/issue-21363.rs
new file mode 100644
index 0000000..5e30db1
--- /dev/null
+++ b/src/test/ui/issues/issue-21363.rs
@@ -0,0 +1,15 @@
+// compile-pass
+// pretty-expanded FIXME #23616
+
+#![no_implicit_prelude]
+
+trait Iterator {
+    type Item;
+    fn dummy(&self) { }
+}
+
+impl<'a, T> Iterator for &'a mut (Iterator<Item=T> + 'a) {
+    type Item = T;
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-21402.rs b/src/test/ui/issues/issue-21402.rs
new file mode 100644
index 0000000..518d3cf
--- /dev/null
+++ b/src/test/ui/issues/issue-21402.rs
@@ -0,0 +1,12 @@
+// compile-pass
+#![allow(dead_code)]
+// pretty-expanded FIXME #23616
+
+#[derive(Hash)]
+struct Foo {
+    a: Vec<bool>,
+    b: (bool, bool),
+    c: [bool; 2],
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-21449.rs b/src/test/ui/issues/issue-21449.rs
new file mode 100644
index 0000000..00ce2b7
--- /dev/null
+++ b/src/test/ui/issues/issue-21449.rs
@@ -0,0 +1,6 @@
+mod MyMod {}
+
+fn main() {
+    let myVar = MyMod { T: 0 };
+    //~^ ERROR expected struct, variant or union type, found module `MyMod`
+}
diff --git a/src/test/ui/issues/issue-21449.stderr b/src/test/ui/issues/issue-21449.stderr
new file mode 100644
index 0000000..ecaf6fa
--- /dev/null
+++ b/src/test/ui/issues/issue-21449.stderr
@@ -0,0 +1,9 @@
+error[E0574]: expected struct, variant or union type, found module `MyMod`
+  --> $DIR/issue-21449.rs:4:17
+   |
+LL |     let myVar = MyMod { T: 0 };
+   |                 ^^^^^ not a struct, variant or union type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0574`.
diff --git a/src/test/ui/issues/issue-2149.rs b/src/test/ui/issues/issue-2149.rs
new file mode 100644
index 0000000..d46f0e6
--- /dev/null
+++ b/src/test/ui/issues/issue-2149.rs
@@ -0,0 +1,15 @@
+trait VecMonad<A> {
+    fn bind<B, F>(&self, f: F) where F: FnMut(A) -> Vec<B>;
+}
+
+impl<A> VecMonad<A> for Vec<A> {
+    fn bind<B, F>(&self, mut f: F) where F: FnMut(A) -> Vec<B> {
+        let mut r = panic!();
+        for elt in self { r = r + f(*elt); }
+        //~^ ERROR E0277
+   }
+}
+fn main() {
+    ["hi"].bind(|x| [x] );
+    //~^ ERROR no method named `bind` found for type `[&str; 1]` in the current scope
+}
diff --git a/src/test/ui/issues/issue-2149.stderr b/src/test/ui/issues/issue-2149.stderr
new file mode 100644
index 0000000..82dbf34
--- /dev/null
+++ b/src/test/ui/issues/issue-2149.stderr
@@ -0,0 +1,22 @@
+error[E0277]: cannot add `std::vec::Vec<B>` to `()`
+  --> $DIR/issue-2149.rs:8:33
+   |
+LL |         for elt in self { r = r + f(*elt); }
+   |                                 ^ no implementation for `() + std::vec::Vec<B>`
+   |
+   = help: the trait `std::ops::Add<std::vec::Vec<B>>` is not implemented for `()`
+
+error[E0599]: no method named `bind` found for type `[&str; 1]` in the current scope
+  --> $DIR/issue-2149.rs:13:12
+   |
+LL |     ["hi"].bind(|x| [x] );
+   |            ^^^^
+   |
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following trait defines an item `bind`, perhaps you need to implement it:
+           candidate #1: `VecMonad`
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0277, E0599.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-2150.rs b/src/test/ui/issues/issue-2150.rs
new file mode 100644
index 0000000..baa1dde
--- /dev/null
+++ b/src/test/ui/issues/issue-2150.rs
@@ -0,0 +1,12 @@
+#![deny(unreachable_code)]
+#![allow(unused_variables)]
+#![allow(dead_code)]
+
+fn fail_len(v: Vec<isize> ) -> usize {
+    let mut i = 3;
+    panic!();
+    for x in &v { i += 1; }
+    //~^ ERROR: unreachable statement
+    return i;
+}
+fn main() {}
diff --git a/src/test/ui/issues/issue-2150.stderr b/src/test/ui/issues/issue-2150.stderr
new file mode 100644
index 0000000..59000f3
--- /dev/null
+++ b/src/test/ui/issues/issue-2150.stderr
@@ -0,0 +1,14 @@
+error: unreachable statement
+  --> $DIR/issue-2150.rs:8:5
+   |
+LL |     for x in &v { i += 1; }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/issue-2150.rs:1:9
+   |
+LL | #![deny(unreachable_code)]
+   |         ^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-2151.rs b/src/test/ui/issues/issue-2151.rs
new file mode 100644
index 0000000..32fba4c
--- /dev/null
+++ b/src/test/ui/issues/issue-2151.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let x = panic!();
+    x.clone(); //~ ERROR type annotations needed
+}
diff --git a/src/test/ui/issues/issue-2151.stderr b/src/test/ui/issues/issue-2151.stderr
new file mode 100644
index 0000000..a2bcc8a
--- /dev/null
+++ b/src/test/ui/issues/issue-2151.stderr
@@ -0,0 +1,13 @@
+error[E0282]: type annotations needed
+  --> $DIR/issue-2151.rs:3:5
+   |
+LL |     let x = panic!();
+   |         - consider giving `x` a type
+LL |     x.clone();
+   |     ^ cannot infer type
+   |
+   = note: type must be known at this point
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/issues/issue-21520.rs b/src/test/ui/issues/issue-21520.rs
new file mode 100644
index 0000000..450448f
--- /dev/null
+++ b/src/test/ui/issues/issue-21520.rs
@@ -0,0 +1,22 @@
+// compile-pass
+#![allow(dead_code)]
+// Test that the requirement (in `Bar`) that `T::Bar : 'static` does
+// not wind up propagating to `T`.
+
+// pretty-expanded FIXME #23616
+
+pub trait Foo {
+    type Bar;
+
+    fn foo(&self) -> Self;
+}
+
+pub struct Static<T:'static>(T);
+
+struct Bar<T:Foo>
+    where T::Bar : 'static
+{
+    x: Static<Option<T::Bar>>
+}
+
+fn main() { }
diff --git a/src/test/ui/issues/issue-21546.rs b/src/test/ui/issues/issue-21546.rs
new file mode 100644
index 0000000..9f3974b
--- /dev/null
+++ b/src/test/ui/issues/issue-21546.rs
@@ -0,0 +1,49 @@
+// Also works as a test for #14564
+
+#[allow(non_snake_case)]
+mod Foo { }
+
+#[allow(dead_code)]
+struct Foo;
+//~^ ERROR the name `Foo` is defined multiple times
+
+#[allow(non_snake_case)]
+mod Bar { }
+
+#[allow(dead_code)]
+struct Bar(i32);
+//~^ ERROR the name `Bar` is defined multiple times
+
+
+#[allow(dead_code)]
+struct Baz(i32);
+
+#[allow(non_snake_case)]
+mod Baz { }
+//~^ ERROR the name `Baz` is defined multiple times
+
+
+#[allow(dead_code)]
+struct Qux { x: bool }
+
+#[allow(non_snake_case)]
+mod Qux { }
+//~^ ERROR the name `Qux` is defined multiple times
+
+
+#[allow(dead_code)]
+struct Quux;
+
+#[allow(non_snake_case)]
+mod Quux { }
+//~^ ERROR the name `Quux` is defined multiple times
+
+
+#[allow(dead_code)]
+enum Corge { A, B }
+
+#[allow(non_snake_case)]
+mod Corge { }
+//~^ ERROR the name `Corge` is defined multiple times
+
+fn main() { }
diff --git a/src/test/ui/issues/issue-21546.stderr b/src/test/ui/issues/issue-21546.stderr
new file mode 100644
index 0000000..5fd06fc
--- /dev/null
+++ b/src/test/ui/issues/issue-21546.stderr
@@ -0,0 +1,69 @@
+error[E0428]: the name `Foo` is defined multiple times
+  --> $DIR/issue-21546.rs:7:1
+   |
+LL | mod Foo { }
+   | ------- previous definition of the module `Foo` here
+...
+LL | struct Foo;
+   | ^^^^^^^^^^^ `Foo` redefined here
+   |
+   = note: `Foo` must be defined only once in the type namespace of this module
+
+error[E0428]: the name `Bar` is defined multiple times
+  --> $DIR/issue-21546.rs:14:1
+   |
+LL | mod Bar { }
+   | ------- previous definition of the module `Bar` here
+...
+LL | struct Bar(i32);
+   | ^^^^^^^^^^^^^^^^ `Bar` redefined here
+   |
+   = note: `Bar` must be defined only once in the type namespace of this module
+
+error[E0428]: the name `Baz` is defined multiple times
+  --> $DIR/issue-21546.rs:22:1
+   |
+LL | struct Baz(i32);
+   | ---------------- previous definition of the type `Baz` here
+...
+LL | mod Baz { }
+   | ^^^^^^^ `Baz` redefined here
+   |
+   = note: `Baz` must be defined only once in the type namespace of this module
+
+error[E0428]: the name `Qux` is defined multiple times
+  --> $DIR/issue-21546.rs:30:1
+   |
+LL | struct Qux { x: bool }
+   | ---------- previous definition of the type `Qux` here
+...
+LL | mod Qux { }
+   | ^^^^^^^ `Qux` redefined here
+   |
+   = note: `Qux` must be defined only once in the type namespace of this module
+
+error[E0428]: the name `Quux` is defined multiple times
+  --> $DIR/issue-21546.rs:38:1
+   |
+LL | struct Quux;
+   | ------------ previous definition of the type `Quux` here
+...
+LL | mod Quux { }
+   | ^^^^^^^^ `Quux` redefined here
+   |
+   = note: `Quux` must be defined only once in the type namespace of this module
+
+error[E0428]: the name `Corge` is defined multiple times
+  --> $DIR/issue-21546.rs:46:1
+   |
+LL | enum Corge { A, B }
+   | ---------- previous definition of the type `Corge` here
+...
+LL | mod Corge { }
+   | ^^^^^^^^^ `Corge` redefined here
+   |
+   = note: `Corge` must be defined only once in the type namespace of this module
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0428`.
diff --git a/src/test/ui/issues/issue-21554.rs b/src/test/ui/issues/issue-21554.rs
new file mode 100644
index 0000000..c176b12
--- /dev/null
+++ b/src/test/ui/issues/issue-21554.rs
@@ -0,0 +1,6 @@
+struct Inches(i32);
+
+fn main() {
+    Inches as f32;
+    //~^ ERROR casting
+}
diff --git a/src/test/ui/issues/issue-21554.stderr b/src/test/ui/issues/issue-21554.stderr
new file mode 100644
index 0000000..6ea552a
--- /dev/null
+++ b/src/test/ui/issues/issue-21554.stderr
@@ -0,0 +1,9 @@
+error[E0606]: casting `fn(i32) -> Inches {Inches}` as `f32` is invalid
+  --> $DIR/issue-21554.rs:4:5
+   |
+LL |     Inches as f32;
+   |     ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0606`.
diff --git a/src/test/ui/issues/issue-21562.rs b/src/test/ui/issues/issue-21562.rs
new file mode 100644
index 0000000..e31316d
--- /dev/null
+++ b/src/test/ui/issues/issue-21562.rs
@@ -0,0 +1,19 @@
+// compile-pass
+#![allow(dead_code)]
+#![allow(non_upper_case_globals)]
+
+extern crate core;
+use core::marker::Sync;
+
+static SARRAY: [i32; 1] = [11];
+
+struct MyStruct {
+    pub arr: *const [i32],
+}
+unsafe impl Sync for MyStruct {}
+
+static mystruct: MyStruct = MyStruct {
+    arr: &SARRAY
+};
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-21600.nll.stderr b/src/test/ui/issues/issue-21600.nll.stderr
new file mode 100644
index 0000000..21f3774
--- /dev/null
+++ b/src/test/ui/issues/issue-21600.nll.stderr
@@ -0,0 +1,34 @@
+error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
+  --> $DIR/issue-21600.rs:14:20
+   |
+LL |         call_it(|| x.gen_mut());
+   |                    ^ cannot borrow as mutable
+   |
+help: consider changing this to accept closures that implement `FnMut`
+  --> $DIR/issue-21600.rs:14:17
+   |
+LL |         call_it(|| x.gen_mut());
+   |                 ^^^^^^^^^^^^^^
+
+error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
+  --> $DIR/issue-21600.rs:14:17
+   |
+LL |         call_it(|| x.gen_mut());
+   |                 ^^ - mutable borrow occurs due to use of `x` in closure
+   |                 |
+   |                 cannot borrow as mutable
+   |
+help: consider changing this to accept closures that implement `FnMut`
+  --> $DIR/issue-21600.rs:12:13
+   |
+LL |       call_it(|| {
+   |  _____________^
+LL | |         call_it(|| x.gen());
+LL | |         call_it(|| x.gen_mut());
+LL | |
+LL | |     });
+   | |_____^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/issues/issue-21600.rs b/src/test/ui/issues/issue-21600.rs
new file mode 100644
index 0000000..1efc873
--- /dev/null
+++ b/src/test/ui/issues/issue-21600.rs
@@ -0,0 +1,17 @@
+fn call_it<F>(f: F) where F: Fn() { f(); }
+
+struct A;
+
+impl A {
+    fn gen(&self) {}
+    fn gen_mut(&mut self) {}
+}
+
+fn main() {
+    let mut x = A;
+    call_it(|| {
+        call_it(|| x.gen());
+        call_it(|| x.gen_mut()); //~ ERROR cannot borrow data mutably in a captured outer
+        //~^ ERROR cannot borrow data mutably in a captured outer
+    });
+}
diff --git a/src/test/ui/issues/issue-21600.stderr b/src/test/ui/issues/issue-21600.stderr
new file mode 100644
index 0000000..a20838c
--- /dev/null
+++ b/src/test/ui/issues/issue-21600.stderr
@@ -0,0 +1,32 @@
+error[E0387]: cannot borrow data mutably in a captured outer variable in an `Fn` closure
+  --> $DIR/issue-21600.rs:14:17
+   |
+LL |         call_it(|| x.gen_mut());
+   |                 ^^
+   |
+help: consider changing this to accept closures that implement `FnMut`
+  --> $DIR/issue-21600.rs:12:13
+   |
+LL |       call_it(|| {
+   |  _____________^
+LL | |         call_it(|| x.gen());
+LL | |         call_it(|| x.gen_mut());
+LL | |
+LL | |     });
+   | |_____^
+
+error[E0387]: cannot borrow data mutably in a captured outer variable in an `Fn` closure
+  --> $DIR/issue-21600.rs:14:20
+   |
+LL |         call_it(|| x.gen_mut());
+   |                    ^
+   |
+help: consider changing this closure to take self by mutable reference
+  --> $DIR/issue-21600.rs:14:17
+   |
+LL |         call_it(|| x.gen_mut());
+   |                 ^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0387`.
diff --git a/src/test/ui/issues/issue-21622.rs b/src/test/ui/issues/issue-21622.rs
new file mode 100644
index 0000000..2b80f2f
--- /dev/null
+++ b/src/test/ui/issues/issue-21622.rs
@@ -0,0 +1,21 @@
+// compile-pass
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+struct Index;
+
+impl Index {
+    fn new() -> Self { Index }
+}
+
+fn user() {
+    let new = Index::new;
+
+    fn inner() {
+        let index = Index::new();
+    }
+
+    let index2 = new();
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-21634.rs b/src/test/ui/issues/issue-21634.rs
new file mode 100644
index 0000000..8941bb1
--- /dev/null
+++ b/src/test/ui/issues/issue-21634.rs
@@ -0,0 +1,20 @@
+// compile-pass
+#![allow(stable_features)]
+
+#![feature(cfg_target_feature)]
+
+#[cfg(any(not(target_arch = "x86"), target_feature = "sse2"))]
+fn main() {
+    if let Ok(x) = "3.1415".parse::<f64>() {
+        assert_eq!(false, x <= 0.0);
+    }
+    if let Ok(x) = "3.1415".parse::<f64>() {
+        assert_eq!(3.1415, x + 0.0);
+    }
+    if let Ok(mut x) = "3.1415".parse::<f64>() {
+        assert_eq!(8.1415, { x += 5.0; x });
+    }
+}
+
+#[cfg(all(target_arch = "x86", not(target_feature = "sse2")))]
+fn main() {}
diff --git a/src/test/ui/issues/issue-21701.rs b/src/test/ui/issues/issue-21701.rs
new file mode 100644
index 0000000..fb2d5a4
--- /dev/null
+++ b/src/test/ui/issues/issue-21701.rs
@@ -0,0 +1,15 @@
+fn foo<U>(t: U) {
+    let y = t();
+//~^ ERROR: expected function, found `U`
+}
+
+struct Bar;
+
+pub fn some_func() {
+    let f = Bar();
+//~^ ERROR: expected function, found `Bar`
+}
+
+fn main() {
+    foo(|| { 1 });
+}
diff --git a/src/test/ui/issues/issue-21701.stderr b/src/test/ui/issues/issue-21701.stderr
new file mode 100644
index 0000000..77bb380
--- /dev/null
+++ b/src/test/ui/issues/issue-21701.stderr
@@ -0,0 +1,24 @@
+error[E0618]: expected function, found `U`
+  --> $DIR/issue-21701.rs:2:13
+   |
+LL | fn foo<U>(t: U) {
+   |           - `U` defined here
+LL |     let y = t();
+   |             ^--
+   |             |
+   |             call expression requires function
+
+error[E0618]: expected function, found `Bar`
+  --> $DIR/issue-21701.rs:9:13
+   |
+LL | struct Bar;
+   | ----------- `Bar` defined here
+...
+LL |     let f = Bar();
+   |             ^^^--
+   |             |
+   |             call expression requires function
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0618`.
diff --git a/src/test/ui/issues/issue-21726.rs b/src/test/ui/issues/issue-21726.rs
new file mode 100644
index 0000000..f206597
--- /dev/null
+++ b/src/test/ui/issues/issue-21726.rs
@@ -0,0 +1,38 @@
+// compile-pass
+#![allow(dead_code)]
+// Regression test for #21726: an issue arose around the rules for
+// subtyping of projection types that resulted in an unconstrained
+// region, yielding region inference failures.
+
+// pretty-expanded FIXME #23616
+
+fn main() { }
+
+fn foo<'a>(s: &'a str) {
+    let b: B<()> = B::new(s, ());
+    b.get_short();
+}
+
+trait IntoRef<'a> {
+    type T: Clone;
+    fn into_ref(self, _: &'a str) -> Self::T;
+}
+
+impl<'a> IntoRef<'a> for () {
+    type T = &'a str;
+    fn into_ref(self, s: &'a str) -> &'a str {
+        s
+    }
+}
+
+struct B<'a, P: IntoRef<'a>>(P::T);
+
+impl<'a, P: IntoRef<'a>> B<'a, P> {
+    fn new(s: &'a str, i: P) -> B<'a, P> {
+        B(i.into_ref(s))
+    }
+
+    fn get_short(&self) -> P::T {
+        self.0.clone()
+    }
+}
diff --git a/src/test/ui/issues/issue-21763.rs b/src/test/ui/issues/issue-21763.rs
new file mode 100644
index 0000000..29ee5f9
--- /dev/null
+++ b/src/test/ui/issues/issue-21763.rs
@@ -0,0 +1,11 @@
+// Regression test for HashMap only impl'ing Send/Sync if its contents do
+
+use std::collections::HashMap;
+use std::rc::Rc;
+
+fn foo<T: Send>() {}
+
+fn main() {
+    foo::<HashMap<Rc<()>, Rc<()>>>();
+    //~^ ERROR `std::rc::Rc<()>` cannot be sent between threads safely
+}
diff --git a/src/test/ui/issues/issue-21763.stderr b/src/test/ui/issues/issue-21763.stderr
new file mode 100644
index 0000000..62cc887
--- /dev/null
+++ b/src/test/ui/issues/issue-21763.stderr
@@ -0,0 +1,20 @@
+error[E0277]: `std::rc::Rc<()>` cannot be sent between threads safely
+  --> $DIR/issue-21763.rs:9:5
+   |
+LL |     foo::<HashMap<Rc<()>, Rc<()>>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `std::rc::Rc<()>` cannot be sent between threads safely
+   |
+   = help: within `std::collections::HashMap<std::rc::Rc<()>, std::rc::Rc<()>>`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<()>`
+   = note: required because it appears within the type `(std::rc::Rc<()>, std::rc::Rc<()>)`
+   = note: required because it appears within the type `std::marker::PhantomData<(std::rc::Rc<()>, std::rc::Rc<()>)>`
+   = note: required because it appears within the type `std::collections::hash::table::RawTable<std::rc::Rc<()>, std::rc::Rc<()>>`
+   = note: required because it appears within the type `std::collections::HashMap<std::rc::Rc<()>, std::rc::Rc<()>>`
+note: required by `foo`
+  --> $DIR/issue-21763.rs:6:1
+   |
+LL | fn foo<T: Send>() {}
+   | ^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-21837.rs b/src/test/ui/issues/issue-21837.rs
new file mode 100644
index 0000000..213119b
--- /dev/null
+++ b/src/test/ui/issues/issue-21837.rs
@@ -0,0 +1,10 @@
+pub trait Bound {}
+pub struct Foo<T: Bound>(T);
+
+pub trait Trait1 {}
+impl<T: Bound> Trait1 for Foo<T> {}
+
+pub trait Trait2 {}
+impl<T> Trait2 for Foo<T> {} //~ ERROR the trait bound `T: Bound` is not satisfied
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-21837.stderr b/src/test/ui/issues/issue-21837.stderr
new file mode 100644
index 0000000..3111d3a
--- /dev/null
+++ b/src/test/ui/issues/issue-21837.stderr
@@ -0,0 +1,16 @@
+error[E0277]: the trait bound `T: Bound` is not satisfied
+  --> $DIR/issue-21837.rs:8:9
+   |
+LL | impl<T> Trait2 for Foo<T> {}
+   |         ^^^^^^ the trait `Bound` is not implemented for `T`
+   |
+   = help: consider adding a `where T: Bound` bound
+note: required by `Foo`
+  --> $DIR/issue-21837.rs:2:1
+   |
+LL | pub struct Foo<T: Bound>(T);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-21891.rs b/src/test/ui/issues/issue-21891.rs
new file mode 100644
index 0000000..9b1e44c
--- /dev/null
+++ b/src/test/ui/issues/issue-21891.rs
@@ -0,0 +1,12 @@
+// compile-pass
+#![allow(dead_code)]
+#![allow(non_upper_case_globals)]
+
+// pretty-expanded FIXME #23616
+
+static foo: [usize; 3] = [1, 2, 3];
+
+static slice_1: &'static [usize] = &foo;
+static slice_2: &'static [usize] = &foo;
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-21946.rs b/src/test/ui/issues/issue-21946.rs
new file mode 100644
index 0000000..2d99769
--- /dev/null
+++ b/src/test/ui/issues/issue-21946.rs
@@ -0,0 +1,13 @@
+trait Foo {
+    type A;
+}
+
+struct FooStruct;
+
+impl Foo for FooStruct {
+//~^ ERROR overflow evaluating the requirement `<FooStruct as Foo>::A`
+    type A = <FooStruct as Foo>::A;
+    //~^ ERROR overflow evaluating the requirement `<FooStruct as Foo>::A`
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-21946.stderr b/src/test/ui/issues/issue-21946.stderr
new file mode 100644
index 0000000..5ac49f6
--- /dev/null
+++ b/src/test/ui/issues/issue-21946.stderr
@@ -0,0 +1,15 @@
+error[E0275]: overflow evaluating the requirement `<FooStruct as Foo>::A`
+  --> $DIR/issue-21946.rs:7:6
+   |
+LL | impl Foo for FooStruct {
+   |      ^^^
+
+error[E0275]: overflow evaluating the requirement `<FooStruct as Foo>::A`
+  --> $DIR/issue-21946.rs:9:5
+   |
+LL |     type A = <FooStruct as Foo>::A;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/src/test/ui/issues/issue-21950.rs b/src/test/ui/issues/issue-21950.rs
new file mode 100644
index 0000000..0f78b37
--- /dev/null
+++ b/src/test/ui/issues/issue-21950.rs
@@ -0,0 +1,10 @@
+// ignore-tidy-linelength
+
+use std::ops::Add;
+
+fn main() {
+    let x = &10 as
+            &Add;
+            //~^ ERROR E0393
+            //~| ERROR E0191
+}
diff --git a/src/test/ui/issues/issue-21950.stderr b/src/test/ui/issues/issue-21950.stderr
new file mode 100644
index 0000000..bda2e3c
--- /dev/null
+++ b/src/test/ui/issues/issue-21950.stderr
@@ -0,0 +1,18 @@
+error[E0393]: the type parameter `Rhs` must be explicitly specified
+  --> $DIR/issue-21950.rs:7:14
+   |
+LL |             &Add;
+   |              ^^^ missing reference to `Rhs`
+   |
+   = note: because of the default `Self` reference, type parameters must be specified on object types
+
+error[E0191]: the value of the associated type `Output` (from the trait `std::ops::Add`) must be specified
+  --> $DIR/issue-21950.rs:7:14
+   |
+LL |             &Add;
+   |              ^^^ associated type `Output` must be specified
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0191, E0393.
+For more information about an error, try `rustc --explain E0191`.
diff --git a/src/test/ui/issues/issue-21974.rs b/src/test/ui/issues/issue-21974.rs
new file mode 100644
index 0000000..f49eb23
--- /dev/null
+++ b/src/test/ui/issues/issue-21974.rs
@@ -0,0 +1,18 @@
+// Test that (for now) we report an ambiguity error here, because
+// specific trait relationships are ignored for the purposes of trait
+// matching. This behavior should likely be improved such that this
+// test passes. See #21974 for more details.
+
+trait Foo {
+    fn foo(self);
+}
+
+fn foo<'a,'b,T>(x: &'a T, y: &'b T) //~ ERROR type annotations required
+    where &'a T : Foo,
+          &'b T : Foo
+{
+    x.foo();
+    y.foo();
+}
+
+fn main() { }
diff --git a/src/test/ui/issues/issue-21974.stderr b/src/test/ui/issues/issue-21974.stderr
new file mode 100644
index 0000000..85e59d7
--- /dev/null
+++ b/src/test/ui/issues/issue-21974.stderr
@@ -0,0 +1,21 @@
+error[E0283]: type annotations required: cannot resolve `&'a T: Foo`
+  --> $DIR/issue-21974.rs:10:1
+   |
+LL | / fn foo<'a,'b,T>(x: &'a T, y: &'b T)
+LL | |     where &'a T : Foo,
+LL | |           &'b T : Foo
+LL | | {
+LL | |     x.foo();
+LL | |     y.foo();
+LL | | }
+   | |_^
+   |
+note: required by `Foo`
+  --> $DIR/issue-21974.rs:6:1
+   |
+LL | trait Foo {
+   | ^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0283`.
diff --git a/src/test/ui/issues/issue-22034.rs b/src/test/ui/issues/issue-22034.rs
new file mode 100644
index 0000000..75ac78a
--- /dev/null
+++ b/src/test/ui/issues/issue-22034.rs
@@ -0,0 +1,11 @@
+#![feature(rustc_private)]
+
+extern crate libc;
+
+fn main() {
+    let ptr: *mut () = 0 as *mut _;
+    let _: &mut Fn() = unsafe {
+        &mut *(ptr as *mut Fn())
+        //~^ ERROR expected a `std::ops::Fn<()>` closure, found `()`
+    };
+}
diff --git a/src/test/ui/issues/issue-22034.stderr b/src/test/ui/issues/issue-22034.stderr
new file mode 100644
index 0000000..de2d315
--- /dev/null
+++ b/src/test/ui/issues/issue-22034.stderr
@@ -0,0 +1,13 @@
+error[E0277]: expected a `std::ops::Fn<()>` closure, found `()`
+  --> $DIR/issue-22034.rs:8:16
+   |
+LL |         &mut *(ptr as *mut Fn())
+   |                ^^^ expected an `Fn<()>` closure, found `()`
+   |
+   = help: the trait `std::ops::Fn<()>` is not implemented for `()`
+   = note: wrap the `()` in a closure with no arguments: `|| { /* code */ }
+   = note: required for the cast to the object type `dyn std::ops::Fn()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-22037.rs b/src/test/ui/issues/issue-22037.rs
new file mode 100644
index 0000000..b9eb41b
--- /dev/null
+++ b/src/test/ui/issues/issue-22037.rs
@@ -0,0 +1,17 @@
+trait A {
+    type Output;
+    fn a(&self) -> <Self as A>::X;
+    //~^ ERROR cannot find associated type `X` in trait `A`
+}
+
+impl A for u32 {
+    type Output = u32;
+    fn a(&self) -> u32 {
+        0
+    }
+}
+
+fn main() {
+    let a: u32 = 0;
+    let b: u32 = a.a();
+}
diff --git a/src/test/ui/issues/issue-22037.stderr b/src/test/ui/issues/issue-22037.stderr
new file mode 100644
index 0000000..6156285
--- /dev/null
+++ b/src/test/ui/issues/issue-22037.stderr
@@ -0,0 +1,9 @@
+error[E0576]: cannot find associated type `X` in trait `A`
+  --> $DIR/issue-22037.rs:3:33
+   |
+LL |     fn a(&self) -> <Self as A>::X;
+   |                                 ^ not found in `A`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0576`.
diff --git a/src/test/ui/issues/issue-22066.rs b/src/test/ui/issues/issue-22066.rs
new file mode 100644
index 0000000..8c0b664
--- /dev/null
+++ b/src/test/ui/issues/issue-22066.rs
@@ -0,0 +1,12 @@
+// compile-pass
+pub trait LineFormatter<'a> {
+    type Iter: Iterator<Item=&'a str> + 'a;
+    fn iter(&'a self, line: &'a str) -> Self::Iter;
+
+    fn dimensions(&'a self, line: &'a str) {
+        let iter: Self::Iter = self.iter(line);
+        <_ as IntoIterator>::into_iter(iter);
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-22289.rs b/src/test/ui/issues/issue-22289.rs
new file mode 100644
index 0000000..b683834
--- /dev/null
+++ b/src/test/ui/issues/issue-22289.rs
@@ -0,0 +1,3 @@
+fn main() {
+    0 as &std::any::Any; //~ ERROR non-primitive cast
+}
diff --git a/src/test/ui/issues/issue-22289.stderr b/src/test/ui/issues/issue-22289.stderr
new file mode 100644
index 0000000..e9846b8
--- /dev/null
+++ b/src/test/ui/issues/issue-22289.stderr
@@ -0,0 +1,11 @@
+error[E0605]: non-primitive cast: `i32` as `&(dyn std::any::Any + 'static)`
+  --> $DIR/issue-22289.rs:2:5
+   |
+LL |     0 as &std::any::Any;
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0605`.
diff --git a/src/test/ui/issues/issue-22312.rs b/src/test/ui/issues/issue-22312.rs
new file mode 100644
index 0000000..f7ebdb0
--- /dev/null
+++ b/src/test/ui/issues/issue-22312.rs
@@ -0,0 +1,17 @@
+use std::ops::Index;
+
+pub trait Array2D: Index<usize> {
+    fn rows(&self) -> usize;
+    fn columns(&self) -> usize;
+    fn get<'a>(&'a self, y: usize, x: usize) -> Option<&'a <Self as Index<usize>>::Output> {
+        if y >= self.rows() || x >= self.columns() {
+            return None;
+        }
+        let i = y * self.columns() + x;
+        let indexer = &(*self as &Index<usize, Output = <Self as Index<usize>>::Output>);
+        //~^ERROR non-primitive cast
+        Some(indexer.index(i))
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-22312.stderr b/src/test/ui/issues/issue-22312.stderr
new file mode 100644
index 0000000..6a012b2
--- /dev/null
+++ b/src/test/ui/issues/issue-22312.stderr
@@ -0,0 +1,11 @@
+error[E0605]: non-primitive cast: `Self` as `&dyn std::ops::Index<usize, Output = <Self as std::ops::Index<usize>>::Output>`
+  --> $DIR/issue-22312.rs:11:24
+   |
+LL |         let indexer = &(*self as &Index<usize, Output = <Self as Index<usize>>::Output>);
+   |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0605`.
diff --git a/src/test/ui/issues/issue-22356.rs b/src/test/ui/issues/issue-22356.rs
new file mode 100644
index 0000000..3f3b1d3
--- /dev/null
+++ b/src/test/ui/issues/issue-22356.rs
@@ -0,0 +1,34 @@
+// compile-pass
+#![allow(type_alias_bounds)]
+
+// pretty-expanded FIXME #23616
+
+use std::marker::PhantomData;
+
+pub struct Handle<T, I>(T, I);
+
+impl<T, I> Handle<T, I> {
+    pub fn get_info(&self) -> &I {
+        let Handle(_, ref info) = *self;
+        info
+    }
+}
+
+pub struct BufferHandle<D: Device, T> {
+    raw: RawBufferHandle<D>,
+    _marker: PhantomData<T>,
+}
+
+impl<D: Device, T> BufferHandle<D, T> {
+    pub fn get_info(&self) -> &String {
+        self.raw.get_info()
+    }
+}
+
+pub type RawBufferHandle<D: Device> = Handle<<D as Device>::Buffer, String>;
+
+pub trait Device {
+    type Buffer;
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-22370.rs b/src/test/ui/issues/issue-22370.rs
new file mode 100644
index 0000000..44eef2d
--- /dev/null
+++ b/src/test/ui/issues/issue-22370.rs
@@ -0,0 +1,8 @@
+// ignore-tidy-linelength
+
+trait A<T=Self> {}
+
+fn f(a: &A) {}
+//~^ ERROR E0393
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-22370.stderr b/src/test/ui/issues/issue-22370.stderr
new file mode 100644
index 0000000..5d76d84
--- /dev/null
+++ b/src/test/ui/issues/issue-22370.stderr
@@ -0,0 +1,11 @@
+error[E0393]: the type parameter `T` must be explicitly specified
+  --> $DIR/issue-22370.rs:5:10
+   |
+LL | fn f(a: &A) {}
+   |          ^ missing reference to `T`
+   |
+   = note: because of the default `Self` reference, type parameters must be specified on object types
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0393`.
diff --git a/src/test/ui/issues/issue-22375.rs b/src/test/ui/issues/issue-22375.rs
new file mode 100644
index 0000000..bae7b2b
--- /dev/null
+++ b/src/test/ui/issues/issue-22375.rs
@@ -0,0 +1,4 @@
+// compile-pass
+trait A<T: A<T>> {}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-22384.rs b/src/test/ui/issues/issue-22384.rs
new file mode 100644
index 0000000..98988f2
--- /dev/null
+++ b/src/test/ui/issues/issue-22384.rs
@@ -0,0 +1,8 @@
+trait Trait {
+    fn foo();
+}
+
+fn main() {
+    <<i32 as Copy>::foobar as Trait>::foo();
+    //~^ ERROR cannot find associated type `foobar` in trait `Copy`
+}
diff --git a/src/test/ui/issues/issue-22384.stderr b/src/test/ui/issues/issue-22384.stderr
new file mode 100644
index 0000000..1f767a4
--- /dev/null
+++ b/src/test/ui/issues/issue-22384.stderr
@@ -0,0 +1,9 @@
+error[E0576]: cannot find associated type `foobar` in trait `Copy`
+  --> $DIR/issue-22384.rs:6:21
+   |
+LL |     <<i32 as Copy>::foobar as Trait>::foo();
+   |                     ^^^^^^ not found in `Copy`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0576`.
diff --git a/src/test/ui/issues/issue-22434.rs b/src/test/ui/issues/issue-22434.rs
new file mode 100644
index 0000000..0d7d67c
--- /dev/null
+++ b/src/test/ui/issues/issue-22434.rs
@@ -0,0 +1,8 @@
+pub trait Foo {
+    type A;
+}
+
+type I<'a> = &'a (Foo + 'a);
+//~^ ERROR the value of the associated type `A` (from the trait `Foo`) must be specified
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-22434.stderr b/src/test/ui/issues/issue-22434.stderr
new file mode 100644
index 0000000..bbdbeb6
--- /dev/null
+++ b/src/test/ui/issues/issue-22434.stderr
@@ -0,0 +1,12 @@
+error[E0191]: the value of the associated type `A` (from the trait `Foo`) must be specified
+  --> $DIR/issue-22434.rs:5:19
+   |
+LL |     type A;
+   |     ------- `A` defined here
+...
+LL | type I<'a> = &'a (Foo + 'a);
+   |                   ^^^^^^^^ associated type `A` must be specified
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0191`.
diff --git a/src/test/ui/issues/issue-22468.rs b/src/test/ui/issues/issue-22468.rs
new file mode 100644
index 0000000..197a19c
--- /dev/null
+++ b/src/test/ui/issues/issue-22468.rs
@@ -0,0 +1,9 @@
+fn main() {
+    let foo = "bar";
+    let x = foo("baz");
+    //~^ ERROR: expected function, found `&str`
+}
+
+fn foo(file: &str) -> bool {
+    true
+}
diff --git a/src/test/ui/issues/issue-22468.stderr b/src/test/ui/issues/issue-22468.stderr
new file mode 100644
index 0000000..8d8601b
--- /dev/null
+++ b/src/test/ui/issues/issue-22468.stderr
@@ -0,0 +1,13 @@
+error[E0618]: expected function, found `&str`
+  --> $DIR/issue-22468.rs:3:13
+   |
+LL |     let foo = "bar";
+   |         --- `&str` defined here
+LL |     let x = foo("baz");
+   |             ^^^-------
+   |             |
+   |             call expression requires function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0618`.
diff --git a/src/test/ui/issues/issue-22471.rs b/src/test/ui/issues/issue-22471.rs
new file mode 100644
index 0000000..a22c7e6
--- /dev/null
+++ b/src/test/ui/issues/issue-22471.rs
@@ -0,0 +1,7 @@
+// compile-pass
+#![allow(dead_code)]
+#![allow(type_alias_bounds)]
+
+type Foo<T> where T: Copy = Box<T>;
+
+fn main(){}
diff --git a/src/test/ui/issues/issue-22560.rs b/src/test/ui/issues/issue-22560.rs
new file mode 100644
index 0000000..d91211e
--- /dev/null
+++ b/src/test/ui/issues/issue-22560.rs
@@ -0,0 +1,12 @@
+// ignore-tidy-linelength
+
+use std::ops::{Add, Sub};
+
+type Test = Add +
+            //~^ ERROR E0393
+            //~| ERROR E0191
+            Sub;
+            //~^ ERROR E0393
+            //~| ERROR E0225
+
+fn main() { }
diff --git a/src/test/ui/issues/issue-22560.stderr b/src/test/ui/issues/issue-22560.stderr
new file mode 100644
index 0000000..694a4af
--- /dev/null
+++ b/src/test/ui/issues/issue-22560.stderr
@@ -0,0 +1,36 @@
+error[E0393]: the type parameter `Rhs` must be explicitly specified
+  --> $DIR/issue-22560.rs:5:13
+   |
+LL | type Test = Add +
+   |             ^^^ missing reference to `Rhs`
+   |
+   = note: because of the default `Self` reference, type parameters must be specified on object types
+
+error[E0393]: the type parameter `Rhs` must be explicitly specified
+  --> $DIR/issue-22560.rs:8:13
+   |
+LL |             Sub;
+   |             ^^^ missing reference to `Rhs`
+   |
+   = note: because of the default `Self` reference, type parameters must be specified on object types
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+  --> $DIR/issue-22560.rs:8:13
+   |
+LL |             Sub;
+   |             ^^^ non-auto additional trait
+
+error[E0191]: the value of the associated type `Output` (from the trait `std::ops::Add`) must be specified
+  --> $DIR/issue-22560.rs:5:13
+   |
+LL |   type Test = Add +
+   |  _____________^
+LL | |
+LL | |
+LL | |             Sub;
+   | |_______________^ associated type `Output` must be specified
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0191, E0225, E0393.
+For more information about an error, try `rustc --explain E0191`.
diff --git a/src/test/ui/issues/issue-22599.rs b/src/test/ui/issues/issue-22599.rs
new file mode 100644
index 0000000..05096e5
--- /dev/null
+++ b/src/test/ui/issues/issue-22599.rs
@@ -0,0 +1,10 @@
+#![deny(unused_variables)]
+
+fn f(_: i32) {}
+
+fn main() {
+    let mut v = 0;
+    f(v);
+    v = match 0 { a => 0 }; //~ ERROR: unused variable: `a`
+    f(v);
+}
diff --git a/src/test/ui/issues/issue-22599.stderr b/src/test/ui/issues/issue-22599.stderr
new file mode 100644
index 0000000..1223429
--- /dev/null
+++ b/src/test/ui/issues/issue-22599.stderr
@@ -0,0 +1,14 @@
+error: unused variable: `a`
+  --> $DIR/issue-22599.rs:8:19
+   |
+LL |     v = match 0 { a => 0 };
+   |                   ^ help: consider prefixing with an underscore: `_a`
+   |
+note: lint level defined here
+  --> $DIR/issue-22599.rs:1:9
+   |
+LL | #![deny(unused_variables)]
+   |         ^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-22603.rs b/src/test/ui/issues/issue-22603.rs
new file mode 100644
index 0000000..e298316
--- /dev/null
+++ b/src/test/ui/issues/issue-22603.rs
@@ -0,0 +1,14 @@
+// skip-codegen
+// compile-pass
+#![feature(unboxed_closures, fn_traits)]
+struct Foo;
+
+impl<A> FnOnce<(A,)> for Foo {
+    type Output = ();
+    extern "rust-call" fn call_once(self, (_,): (A,)) {
+    }
+}
+
+fn main() {
+    println!("{:?}", Foo("bar"));
+}
diff --git a/src/test/ui/issues/issue-22638.rs b/src/test/ui/issues/issue-22638.rs
new file mode 100644
index 0000000..fab2440
--- /dev/null
+++ b/src/test/ui/issues/issue-22638.rs
@@ -0,0 +1,61 @@
+// normalize-stderr-test: "<\[closure@.+`" -> "$$CLOSURE`"
+
+#![allow(unused)]
+
+#![recursion_limit = "20"]
+#![type_length_limit = "20000000"]
+#![crate_type = "rlib"]
+
+#[derive(Clone)]
+struct A (B);
+
+impl A {
+    pub fn matches<F: Fn()>(&self, f: &F) {
+        let &A(ref term) = self;
+        term.matches(f);
+    }
+}
+
+#[derive(Clone)]
+enum B {
+    Variant1,
+    Variant2(C),
+}
+
+impl B {
+    pub fn matches<F: Fn()>(&self, f: &F) {
+        match self {
+            &B::Variant2(ref factor) => {
+                factor.matches(&|| ())
+            }
+            _ => unreachable!("")
+        }
+    }
+}
+
+#[derive(Clone)]
+struct C (D);
+
+impl C {
+    pub fn matches<F: Fn()>(&self, f: &F) {
+        let &C(ref base) = self;
+        base.matches(&|| {
+            C(base.clone()).matches(f)
+        })
+    }
+}
+
+#[derive(Clone)]
+struct D (Box<A>);
+
+impl D {
+    pub fn matches<F: Fn()>(&self, f: &F) {
+        //~^ ERROR reached the type-length limit while instantiating `D::matches::<[closure
+        let &D(ref a) = self;
+        a.matches(f)
+    }
+}
+
+pub fn matches() {
+    A(B::Variant1).matches(&(|| ()))
+}
diff --git a/src/test/ui/issues/issue-22638.stderr b/src/test/ui/issues/issue-22638.stderr
new file mode 100644
index 0000000..b60e1c2
--- /dev/null
+++ b/src/test/ui/issues/issue-22638.stderr
@@ -0,0 +1,14 @@
+error: reached the type-length limit while instantiating `D::matches::$CLOSURE`
+  --> $DIR/issue-22638.rs:52:5
+   |
+LL | /     pub fn matches<F: Fn()>(&self, f: &F) {
+LL | |
+LL | |         let &D(ref a) = self;
+LL | |         a.matches(f)
+LL | |     }
+   | |_____^
+   |
+   = note: consider adding a `#![type_length_limit="26214380"]` attribute to your crate
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-22644.rs b/src/test/ui/issues/issue-22644.rs
new file mode 100644
index 0000000..9244ff5
--- /dev/null
+++ b/src/test/ui/issues/issue-22644.rs
@@ -0,0 +1,35 @@
+#![feature(type_ascription)]
+
+fn main() {
+    let a : usize = 0;
+    let long_name : usize = 0;
+
+    println!("{}", a as usize > long_name);
+    println!("{}", a as usize < long_name); //~ ERROR `<` is interpreted as a start of generic
+    println!("{}{}", a as usize < long_name, long_name);
+    //~^ ERROR `<` is interpreted as a start of generic
+    println!("{}", a as usize < 4); //~ ERROR `<` is interpreted as a start of generic
+    println!("{}", a: usize > long_name);
+    println!("{}{}", a: usize < long_name, long_name);
+    //~^ ERROR `<` is interpreted as a start of generic
+    println!("{}", a: usize < 4); //~ ERROR `<` is interpreted as a start of generic
+
+    println!("{}", a
+                   as
+                   usize
+                   < //~ ERROR `<` is interpreted as a start of generic
+                   4);
+    println!("{}", a
+
+
+                   as
+
+
+                   usize
+                   < //~ ERROR `<` is interpreted as a start of generic
+                   5);
+
+    println!("{}", a as usize << long_name); //~ ERROR `<` is interpreted as a start of generic
+
+    println!("{}", a: &mut 4); //~ ERROR expected type, found `4`
+}
diff --git a/src/test/ui/issues/issue-22644.stderr b/src/test/ui/issues/issue-22644.stderr
new file mode 100644
index 0000000..a28ea0d
--- /dev/null
+++ b/src/test/ui/issues/issue-22644.stderr
@@ -0,0 +1,101 @@
+error: `<` is interpreted as a start of generic arguments for `usize`, not a comparison
+  --> $DIR/issue-22644.rs:8:31
+   |
+LL |     println!("{}", a as usize < long_name);
+   |                    ---------- ^ --------- interpreted as generic arguments
+   |                    |          |
+   |                    |          not interpreted as comparison
+   |                    help: try comparing the cast value: `(a as usize)`
+
+error: `<` is interpreted as a start of generic arguments for `usize`, not a comparison
+  --> $DIR/issue-22644.rs:9:33
+   |
+LL |     println!("{}{}", a as usize < long_name, long_name);
+   |                      ---------- ^ -------------------- interpreted as generic arguments
+   |                      |          |
+   |                      |          not interpreted as comparison
+   |                      help: try comparing the cast value: `(a as usize)`
+
+error: `<` is interpreted as a start of generic arguments for `usize`, not a comparison
+  --> $DIR/issue-22644.rs:11:31
+   |
+LL |     println!("{}", a as usize < 4);
+   |                    ---------- ^ - interpreted as generic arguments
+   |                    |          |
+   |                    |          not interpreted as comparison
+   |                    help: try comparing the cast value: `(a as usize)`
+
+error: `<` is interpreted as a start of generic arguments for `usize`, not a comparison
+  --> $DIR/issue-22644.rs:13:31
+   |
+LL |     println!("{}{}", a: usize < long_name, long_name);
+   |                      -------- ^ -------------------- interpreted as generic arguments
+   |                      |        |
+   |                      |        not interpreted as comparison
+   |                      help: try comparing the cast value: `(a: usize)`
+
+error: `<` is interpreted as a start of generic arguments for `usize`, not a comparison
+  --> $DIR/issue-22644.rs:15:29
+   |
+LL |     println!("{}", a: usize < 4);
+   |                    -------- ^ - interpreted as generic arguments
+   |                    |        |
+   |                    |        not interpreted as comparison
+   |                    help: try comparing the cast value: `(a: usize)`
+
+error: `<` is interpreted as a start of generic arguments for `usize`, not a comparison
+  --> $DIR/issue-22644.rs:20:20
+   |
+LL |                    <
+   |                    ^ not interpreted as comparison
+LL |                    4);
+   |                    - interpreted as generic arguments
+help: try comparing the cast value
+   |
+LL |     println!("{}", (a
+LL |                    as
+LL |                    usize)
+   |
+
+error: `<` is interpreted as a start of generic arguments for `usize`, not a comparison
+  --> $DIR/issue-22644.rs:29:20
+   |
+LL |                    <
+   |                    ^ not interpreted as comparison
+LL |                    5);
+   |                    - interpreted as generic arguments
+help: try comparing the cast value
+   |
+LL |     println!("{}", (a
+LL | 
+LL | 
+LL |                    as
+LL | 
+LL | 
+ ...
+
+error: `<` is interpreted as a start of generic arguments for `usize`, not a shift
+  --> $DIR/issue-22644.rs:32:31
+   |
+LL |     println!("{}", a as usize << long_name);
+   |                    ---------- ^^ --------- interpreted as generic arguments
+   |                    |          |
+   |                    |          not interpreted as shift
+   |                    help: try shifting the cast value: `(a as usize)`
+
+error: expected type, found `4`
+  --> $DIR/issue-22644.rs:34:28
+   |
+LL |     println!("{}", a: &mut 4);
+   |                            ^ expecting a type here because of type ascription
+   |
+   = note: type ascription is a nightly-only feature that lets you annotate an expression with a type: `<expr>: <type>`
+note: this expression expects an ascribed type after the colon
+  --> $DIR/issue-22644.rs:34:20
+   |
+LL |     println!("{}", a: &mut 4);
+   |                    ^
+   = help: this might be indicative of a syntax error elsewhere
+
+error: aborting due to 9 previous errors
+
diff --git a/src/test/ui/issues/issue-22673.rs b/src/test/ui/issues/issue-22673.rs
new file mode 100644
index 0000000..ba8057b
--- /dev/null
+++ b/src/test/ui/issues/issue-22673.rs
@@ -0,0 +1,6 @@
+trait Expr : PartialEq<Self::Item> {
+    //~^ ERROR: cycle detected
+    type Item;
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-22673.stderr b/src/test/ui/issues/issue-22673.stderr
new file mode 100644
index 0000000..9e7e4b2
--- /dev/null
+++ b/src/test/ui/issues/issue-22673.stderr
@@ -0,0 +1,16 @@
+error[E0391]: cycle detected when computing the supertraits of `Expr`
+  --> $DIR/issue-22673.rs:1:1
+   |
+LL | trait Expr : PartialEq<Self::Item> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: ...which again requires computing the supertraits of `Expr`, completing the cycle
+note: cycle used when collecting item types in top-level module
+  --> $DIR/issue-22673.rs:1:1
+   |
+LL | trait Expr : PartialEq<Self::Item> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/issues/issue-22684.rs b/src/test/ui/issues/issue-22684.rs
new file mode 100644
index 0000000..a5b0427
--- /dev/null
+++ b/src/test/ui/issues/issue-22684.rs
@@ -0,0 +1,18 @@
+mod foo {
+    pub struct Foo;
+    impl Foo {
+        fn bar(&self) {}
+    }
+
+    pub trait Baz {
+        fn bar(&self) -> bool { true }
+    }
+    impl Baz for Foo {}
+}
+
+fn main() {
+    use foo::Baz;
+
+    // Check that `bar` resolves to the trait method, not the inherent impl method.
+    let _: () = foo::Foo.bar(); //~ ERROR mismatched types
+}
diff --git a/src/test/ui/issues/issue-22684.stderr b/src/test/ui/issues/issue-22684.stderr
new file mode 100644
index 0000000..738123e
--- /dev/null
+++ b/src/test/ui/issues/issue-22684.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-22684.rs:17:17
+   |
+LL |     let _: () = foo::Foo.bar();
+   |                 ^^^^^^^^^^^^^^ expected (), found bool
+   |
+   = note: expected type `()`
+              found type `bool`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-22706.rs b/src/test/ui/issues/issue-22706.rs
new file mode 100644
index 0000000..28e8a72
--- /dev/null
+++ b/src/test/ui/issues/issue-22706.rs
@@ -0,0 +1,3 @@
+fn is_copy<T: ::std::marker<i32>::Copy>() {}
+//~^ ERROR type arguments are not allowed for this type [E0109]
+fn main() {}
diff --git a/src/test/ui/issues/issue-22706.stderr b/src/test/ui/issues/issue-22706.stderr
new file mode 100644
index 0000000..c592939
--- /dev/null
+++ b/src/test/ui/issues/issue-22706.stderr
@@ -0,0 +1,9 @@
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/issue-22706.rs:1:29
+   |
+LL | fn is_copy<T: ::std::marker<i32>::Copy>() {}
+   |                             ^^^ type argument not allowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0109`.
diff --git a/src/test/ui/issues/issue-22777.rs b/src/test/ui/issues/issue-22777.rs
new file mode 100644
index 0000000..f9b2646
--- /dev/null
+++ b/src/test/ui/issues/issue-22777.rs
@@ -0,0 +1,48 @@
+// compile-pass
+// This test is reduced from libsyntax.  It is just checking that we
+// can successfully deal with a "deep" structure, which the drop-check
+// was hitting a recursion limit on at one point.
+
+// pretty-expanded FIXME #23616
+
+#![allow(non_camel_case_types)]
+
+pub fn noop_fold_impl_item() -> SmallVector<ImplItem> {
+    loop  { }
+}
+
+pub struct SmallVector<T>(P<T>);
+pub struct ImplItem(P<S01_Method>);
+
+struct P<T>(Box<T>);
+
+struct S01_Method(P<S02_Generics>);
+struct S02_Generics(P<S03_TyParam>);
+struct S03_TyParam(P<S04_TyParamBound>);
+struct S04_TyParamBound(S05_PolyTraitRef);
+struct S05_PolyTraitRef(S06_TraitRef);
+struct S06_TraitRef(S07_Path);
+struct S07_Path(Vec<S08_PathSegment>);
+struct S08_PathSegment(S09_GenericArgs);
+struct S09_GenericArgs(P<S10_ParenthesizedParameterData>);
+struct S10_ParenthesizedParameterData(Option<P<S11_Ty>>);
+struct S11_Ty(P<S12_Expr>);
+struct S12_Expr(P<S13_Block>);
+struct S13_Block(Vec<P<S14_Stmt>>);
+struct S14_Stmt(P<S15_Decl>);
+struct S15_Decl(P<S16_Local>);
+struct S16_Local(P<S17_Pat>);
+struct S17_Pat(P<S18_Mac>);
+struct S18_Mac(Vec<P<S19_TokenTree>>);
+struct S19_TokenTree(P<S20_Token>);
+struct S20_Token(P<S21_Nonterminal>);
+struct S21_Nonterminal(P<S22_Item>);
+struct S22_Item(P<S23_EnumDef>);
+struct S23_EnumDef(Vec<P<S24_Variant>>);
+struct S24_Variant(P<S25_VariantKind>);
+struct S25_VariantKind(P<S26_StructDef>);
+struct S26_StructDef(Vec<P<S27_StructField>>);
+struct S27_StructField(P<S28_StructFieldKind>);
+struct S28_StructFieldKind;
+
+pub fn main() {}
diff --git a/src/test/ui/issues/issue-22781.rs b/src/test/ui/issues/issue-22781.rs
new file mode 100644
index 0000000..5df3d88
--- /dev/null
+++ b/src/test/ui/issues/issue-22781.rs
@@ -0,0 +1,15 @@
+// compile-pass
+#![allow(unused_variables)]
+use std::collections::HashMap;
+use std::collections::hash_map::Entry::Vacant;
+
+pub fn foo() {
+    type F = Box<Fn(&()) + 'static>;
+    let mut map: HashMap<(), F> = HashMap::new();
+    let x: &mut F = match map.entry(()) {
+        Vacant(_) => unimplemented!(),
+        _ => unimplemented!()
+    };
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-22789.rs b/src/test/ui/issues/issue-22789.rs
new file mode 100644
index 0000000..e668012
--- /dev/null
+++ b/src/test/ui/issues/issue-22789.rs
@@ -0,0 +1,7 @@
+// compile-pass
+// skip-codegen
+#![feature(unboxed_closures, fn_traits)]
+fn main() {
+    let k = |x: i32| { x + 1 };
+    Fn::call(&k, (0,));
+}
diff --git a/src/test/ui/issues/issue-2281-part1.rs b/src/test/ui/issues/issue-2281-part1.rs
new file mode 100644
index 0000000..8340ade
--- /dev/null
+++ b/src/test/ui/issues/issue-2281-part1.rs
@@ -0,0 +1 @@
+fn main() { println!("{}", foobar); } //~ ERROR cannot find value `foobar` in this scope
diff --git a/src/test/ui/issues/issue-2281-part1.stderr b/src/test/ui/issues/issue-2281-part1.stderr
new file mode 100644
index 0000000..c2391a7
--- /dev/null
+++ b/src/test/ui/issues/issue-2281-part1.stderr
@@ -0,0 +1,9 @@
+error[E0425]: cannot find value `foobar` in this scope
+  --> $DIR/issue-2281-part1.rs:1:28
+   |
+LL | fn main() { println!("{}", foobar); }
+   |                            ^^^^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/issues/issue-22814.rs b/src/test/ui/issues/issue-22814.rs
new file mode 100644
index 0000000..b008c75
--- /dev/null
+++ b/src/test/ui/issues/issue-22814.rs
@@ -0,0 +1,13 @@
+// compile-pass
+trait Test {}
+
+macro_rules! test {
+( $($name:ident)+) => (
+    impl<$($name: Test),*> Test for ($($name,)*) {
+    }
+)
+}
+
+test!(A B C);
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-22872.rs b/src/test/ui/issues/issue-22872.rs
new file mode 100644
index 0000000..8ef4af1
--- /dev/null
+++ b/src/test/ui/issues/issue-22872.rs
@@ -0,0 +1,24 @@
+trait Wrap<'b> {
+    fn foo(&'b mut self);
+}
+
+struct Wrapper<P>(P);
+
+impl<'b, P> Wrap<'b> for Wrapper<P>
+where P: Process<'b>,
+      <P as Process<'b>>::Item: Iterator {
+    fn foo(&mut self) {}
+}
+
+
+pub trait Process<'a> {
+    type Item;
+    fn bar(&'a self);
+}
+
+fn push_process<P>(process: P) where P: Process<'static> {
+    let _: Box<for<'b> Wrap<'b>> = Box::new(Wrapper(process));
+//~^ ERROR is not an iterator
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-22872.stderr b/src/test/ui/issues/issue-22872.stderr
new file mode 100644
index 0000000..ebd096f
--- /dev/null
+++ b/src/test/ui/issues/issue-22872.stderr
@@ -0,0 +1,14 @@
+error[E0277]: `<P as Process<'_>>::Item` is not an iterator
+  --> $DIR/issue-22872.rs:20:36
+   |
+LL |     let _: Box<for<'b> Wrap<'b>> = Box::new(Wrapper(process));
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^ `<P as Process<'_>>::Item` is not an iterator
+   |
+   = help: the trait `std::iter::Iterator` is not implemented for `<P as Process<'_>>::Item`
+   = help: consider adding a `where <P as Process<'_>>::Item: std::iter::Iterator` bound
+   = note: required because of the requirements on the impl of `for<'b> Wrap<'b>` for `Wrapper<P>`
+   = note: required for the cast to the object type `dyn for<'b> Wrap<'b>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-22874.rs b/src/test/ui/issues/issue-22874.rs
new file mode 100644
index 0000000..37c6c81
--- /dev/null
+++ b/src/test/ui/issues/issue-22874.rs
@@ -0,0 +1,10 @@
+struct Table {
+    rows: [[String]],
+    //~^ ERROR the size for values of type
+}
+
+fn f(table: &Table) -> &[String] {
+    &table.rows[0]
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-22874.stderr b/src/test/ui/issues/issue-22874.stderr
new file mode 100644
index 0000000..229f99f
--- /dev/null
+++ b/src/test/ui/issues/issue-22874.stderr
@@ -0,0 +1,13 @@
+error[E0277]: the size for values of type `[std::string::String]` cannot be known at compilation time
+  --> $DIR/issue-22874.rs:2:5
+   |
+LL |     rows: [[String]],
+   |     ^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `[std::string::String]`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: slice and array elements must have `Sized` type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-22886.rs b/src/test/ui/issues/issue-22886.rs
new file mode 100644
index 0000000..f8b576e
--- /dev/null
+++ b/src/test/ui/issues/issue-22886.rs
@@ -0,0 +1,21 @@
+// Regression test for #22886.
+
+fn crash_please() {
+    let mut iter = Newtype(Some(Box::new(0)));
+    let saved = iter.next().unwrap();
+    println!("{}", saved);
+    iter.0 = None;
+    println!("{}", saved);
+}
+
+struct Newtype(Option<Box<usize>>);
+
+impl<'a> Iterator for Newtype { //~ ERROR E0207
+    type Item = &'a Box<usize>;
+
+    fn next(&mut self) -> Option<&Box<usize>> {
+        self.0.as_ref()
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/issues/issue-22886.stderr b/src/test/ui/issues/issue-22886.stderr
new file mode 100644
index 0000000..c4b3965
--- /dev/null
+++ b/src/test/ui/issues/issue-22886.stderr
@@ -0,0 +1,9 @@
+error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates
+  --> $DIR/issue-22886.rs:13:6
+   |
+LL | impl<'a> Iterator for Newtype {
+   |      ^^ unconstrained lifetime parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0207`.
diff --git a/src/test/ui/issues/issue-22894.rs b/src/test/ui/issues/issue-22894.rs
new file mode 100644
index 0000000..f5b26de
--- /dev/null
+++ b/src/test/ui/issues/issue-22894.rs
@@ -0,0 +1,4 @@
+// compile-pass
+#[allow(dead_code)]
+static X: &'static str = &*"";
+fn main() {}
diff --git a/src/test/ui/issues/issue-22933-1.rs b/src/test/ui/issues/issue-22933-1.rs
new file mode 100644
index 0000000..1bf8cb0
--- /dev/null
+++ b/src/test/ui/issues/issue-22933-1.rs
@@ -0,0 +1,25 @@
+// compile-pass
+// skip-codegen
+#![allow(warnings)]
+struct CNFParser {
+    token: char,
+}
+
+impl CNFParser {
+    fn is_whitespace(c: char) -> bool {
+        c == ' ' || c == '\n'
+    }
+
+    fn consume_whitespace(&mut self) {
+        self.consume_while(&(CNFParser::is_whitespace))
+    }
+
+    fn consume_while(&mut self, p: &Fn(char) -> bool) {
+        while p(self.token) {
+            return
+        }
+    }
+}
+
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-22933-2.rs b/src/test/ui/issues/issue-22933-2.rs
new file mode 100644
index 0000000..68d9ef2
--- /dev/null
+++ b/src/test/ui/issues/issue-22933-2.rs
@@ -0,0 +1,8 @@
+enum Delicious {
+    Pie      = 0x1,
+    Apple    = 0x2,
+    ApplePie = Delicious::Apple as isize | Delicious::PIE as isize,
+    //~^ ERROR no variant named `PIE` found for type `Delicious`
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-22933-2.stderr b/src/test/ui/issues/issue-22933-2.stderr
new file mode 100644
index 0000000..23b1474
--- /dev/null
+++ b/src/test/ui/issues/issue-22933-2.stderr
@@ -0,0 +1,12 @@
+error[E0599]: no variant named `PIE` found for type `Delicious` in the current scope
+  --> $DIR/issue-22933-2.rs:4:55
+   |
+LL | enum Delicious {
+   | -------------- variant `PIE` not found here
+...
+LL |     ApplePie = Delicious::Apple as isize | Delicious::PIE as isize,
+   |                                                       ^^^ variant not found in `Delicious`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/issues/issue-22933-3.rs b/src/test/ui/issues/issue-22933-3.rs
new file mode 100644
index 0000000..8518ed3
--- /dev/null
+++ b/src/test/ui/issues/issue-22933-3.rs
@@ -0,0 +1,4 @@
+const FOO: [u32; u8::MIN as usize] = [];
+//~^ ERROR no associated item named `MIN` found for type `u8`
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-22933-3.stderr b/src/test/ui/issues/issue-22933-3.stderr
new file mode 100644
index 0000000..b1afda6
--- /dev/null
+++ b/src/test/ui/issues/issue-22933-3.stderr
@@ -0,0 +1,9 @@
+error[E0599]: no associated item named `MIN` found for type `u8` in the current scope
+  --> $DIR/issue-22933-3.rs:1:22
+   |
+LL | const FOO: [u32; u8::MIN as usize] = [];
+   |                      ^^^ associated item not found in `u8`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/issues/issue-23024.rs b/src/test/ui/issues/issue-23024.rs
new file mode 100644
index 0000000..0639ce3
--- /dev/null
+++ b/src/test/ui/issues/issue-23024.rs
@@ -0,0 +1,13 @@
+#![feature(box_syntax)]
+use std::any::Any;
+
+fn main()
+{
+    fn h(x:i32) -> i32 {3*x}
+    let mut vfnfer:Vec<Box<Any>> = vec![];
+    vfnfer.push(box h);
+    println!("{:?}",(vfnfer[0] as Fn)(3));
+    //~^ ERROR the precise format of `Fn`-family traits'
+    //~| ERROR wrong number of type arguments: expected 1, found 0 [E0107]
+    //~| ERROR the value of the associated type `Output` (from the trait `std::ops::FnOnce`)
+}
diff --git a/src/test/ui/issues/issue-23024.stderr b/src/test/ui/issues/issue-23024.stderr
new file mode 100644
index 0000000..a972b36
--- /dev/null
+++ b/src/test/ui/issues/issue-23024.stderr
@@ -0,0 +1,24 @@
+error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change. Use parenthetical notation (Fn(Foo, Bar) -> Baz) instead (see issue #29625)
+  --> $DIR/issue-23024.rs:9:35
+   |
+LL |     println!("{:?}",(vfnfer[0] as Fn)(3));
+   |                                   ^^
+   |
+   = help: add #![feature(unboxed_closures)] to the crate attributes to enable
+
+error[E0107]: wrong number of type arguments: expected 1, found 0
+  --> $DIR/issue-23024.rs:9:35
+   |
+LL |     println!("{:?}",(vfnfer[0] as Fn)(3));
+   |                                   ^^ expected 1 type argument
+
+error[E0191]: the value of the associated type `Output` (from the trait `std::ops::FnOnce`) must be specified
+  --> $DIR/issue-23024.rs:9:35
+   |
+LL |     println!("{:?}",(vfnfer[0] as Fn)(3));
+   |                                   ^^ associated type `Output` must be specified
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0107, E0191, E0658.
+For more information about an error, try `rustc --explain E0107`.
diff --git a/src/test/ui/issues/issue-23041.rs b/src/test/ui/issues/issue-23041.rs
new file mode 100644
index 0000000..a18e858
--- /dev/null
+++ b/src/test/ui/issues/issue-23041.rs
@@ -0,0 +1,7 @@
+use std::any::Any;
+fn main()
+{
+    fn bar(x:i32) ->i32 { 3*x };
+    let b:Box<Any> = Box::new(bar as fn(_)->_);
+    b.downcast_ref::<fn(_)->_>(); //~ ERROR E0282
+}
diff --git a/src/test/ui/issues/issue-23041.stderr b/src/test/ui/issues/issue-23041.stderr
new file mode 100644
index 0000000..401086b
--- /dev/null
+++ b/src/test/ui/issues/issue-23041.stderr
@@ -0,0 +1,9 @@
+error[E0282]: type annotations needed
+  --> $DIR/issue-23041.rs:6:22
+   |
+LL |     b.downcast_ref::<fn(_)->_>();
+   |                      ^^^^^^^^ cannot infer type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/issues/issue-23046.rs b/src/test/ui/issues/issue-23046.rs
new file mode 100644
index 0000000..898654b
--- /dev/null
+++ b/src/test/ui/issues/issue-23046.rs
@@ -0,0 +1,20 @@
+pub enum Expr<'var, VAR> {
+    Let(Box<Expr<'var, VAR>>,
+        Box<for<'v> Fn(Expr<'v, VAR>) -> Expr<'v, VAR> + 'var>)
+}
+
+pub fn add<'var, VAR>
+                      (a: Expr<'var, VAR>, b: Expr<'var, VAR>) -> Expr<'var, VAR> {
+    loop {}
+}
+
+pub fn let_<'var, VAR, F: for<'v> Fn(Expr<'v, VAR>) -> Expr<'v, VAR>>
+                       (a: Expr<'var, VAR>, b: F) -> Expr<'var, VAR> {
+    loop {}
+}
+
+fn main() {
+    let ex = |x| { //~ ERROR type annotations needed
+        let_(add(x,x), |y| {
+            let_(add(x, x), |x|x)})};
+}
diff --git a/src/test/ui/issues/issue-23046.stderr b/src/test/ui/issues/issue-23046.stderr
new file mode 100644
index 0000000..aab90a9
--- /dev/null
+++ b/src/test/ui/issues/issue-23046.stderr
@@ -0,0 +1,9 @@
+error[E0282]: type annotations needed
+  --> $DIR/issue-23046.rs:17:15
+   |
+LL |     let ex = |x| {
+   |               ^ consider giving this closure parameter a type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/issues/issue-23073.rs b/src/test/ui/issues/issue-23073.rs
new file mode 100644
index 0000000..a0ca913
--- /dev/null
+++ b/src/test/ui/issues/issue-23073.rs
@@ -0,0 +1,9 @@
+#![feature(associated_type_defaults)]
+
+trait Foo { type T; }
+trait Bar {
+    type Foo: Foo;
+    type FooT = <<Self as Bar>::Foo>::T; //~ ERROR ambiguous associated type
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-23073.stderr b/src/test/ui/issues/issue-23073.stderr
new file mode 100644
index 0000000..3a10a1a
--- /dev/null
+++ b/src/test/ui/issues/issue-23073.stderr
@@ -0,0 +1,9 @@
+error[E0223]: ambiguous associated type
+  --> $DIR/issue-23073.rs:6:17
+   |
+LL |     type FooT = <<Self as Bar>::Foo>::T;
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<<Self as Bar>::Foo as Trait>::T`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0223`.
diff --git a/src/test/ui/issues/issue-23080-2.rs b/src/test/ui/issues/issue-23080-2.rs
new file mode 100644
index 0000000..750b7e1
--- /dev/null
+++ b/src/test/ui/issues/issue-23080-2.rs
@@ -0,0 +1,17 @@
+// ignore-tidy-linelength
+
+//~^^ ERROR
+
+#![feature(optin_builtin_traits)]
+
+unsafe auto trait Trait {
+//~^ ERROR E0380
+    type Output;
+}
+
+fn call_method<T: Trait>(x: T) {}
+
+fn main() {
+    // ICE
+    call_method(());
+}
diff --git a/src/test/ui/issues/issue-23080-2.stderr b/src/test/ui/issues/issue-23080-2.stderr
new file mode 100644
index 0000000..3899846
--- /dev/null
+++ b/src/test/ui/issues/issue-23080-2.stderr
@@ -0,0 +1,18 @@
+error[E0380]: auto traits cannot have methods or associated items
+  --> $DIR/issue-23080-2.rs:7:1
+   |
+LL | / unsafe auto trait Trait {
+LL | |
+LL | |     type Output;
+LL | | }
+   | |_^
+
+error[E0275]: overflow evaluating the requirement `<() as Trait>::Output`
+   |
+   = note: required because of the requirements on the impl of `Trait` for `()`
+   = note: required because of the requirements on the impl of `Trait` for `()`
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0275, E0380.
+For more information about an error, try `rustc --explain E0275`.
diff --git a/src/test/ui/issues/issue-23080.rs b/src/test/ui/issues/issue-23080.rs
new file mode 100644
index 0000000..e25a2d9
--- /dev/null
+++ b/src/test/ui/issues/issue-23080.rs
@@ -0,0 +1,19 @@
+// ignore-tidy-linelength
+
+#![feature(optin_builtin_traits)]
+
+unsafe auto trait Trait {
+//~^ ERROR E0380
+    fn method(&self) {
+        println!("Hello");
+    }
+}
+
+fn call_method<T: Trait>(x: T) {
+    x.method();
+}
+
+fn main() {
+    // ICE
+    call_method(());
+}
diff --git a/src/test/ui/issues/issue-23080.stderr b/src/test/ui/issues/issue-23080.stderr
new file mode 100644
index 0000000..ed843e7
--- /dev/null
+++ b/src/test/ui/issues/issue-23080.stderr
@@ -0,0 +1,14 @@
+error[E0380]: auto traits cannot have methods or associated items
+  --> $DIR/issue-23080.rs:5:1
+   |
+LL | / unsafe auto trait Trait {
+LL | |
+LL | |     fn method(&self) {
+LL | |         println!("Hello");
+LL | |     }
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0380`.
diff --git a/src/test/ui/issues/issue-2311-2.rs b/src/test/ui/issues/issue-2311-2.rs
new file mode 100644
index 0000000..40cda23
--- /dev/null
+++ b/src/test/ui/issues/issue-2311-2.rs
@@ -0,0 +1,26 @@
+// compile-pass
+#![allow(dead_code)]
+#![allow(non_camel_case_types)]
+
+
+trait clam<A> {
+    fn get(self) -> A;
+}
+
+struct foo<A> {
+    x: A,
+}
+
+impl<A> foo<A> {
+   pub fn bar<B,C:clam<A>>(&self, _c: C) -> B {
+     panic!();
+   }
+}
+
+fn foo<A>(b: A) -> foo<A> {
+    foo {
+        x: b
+    }
+}
+
+pub fn main() { }
diff --git a/src/test/ui/issues/issue-2311.rs b/src/test/ui/issues/issue-2311.rs
new file mode 100644
index 0000000..07b9951
--- /dev/null
+++ b/src/test/ui/issues/issue-2311.rs
@@ -0,0 +1,11 @@
+// compile-pass
+#![allow(non_camel_case_types)]
+
+// pretty-expanded FIXME #23616
+
+trait clam<A> { fn get(self) -> A; }
+trait foo<A> {
+   fn bar<B,C:clam<A>>(&self, c: C) -> B;
+}
+
+pub fn main() { }
diff --git a/src/test/ui/issues/issue-2312.rs b/src/test/ui/issues/issue-2312.rs
new file mode 100644
index 0000000..1fc7b5a
--- /dev/null
+++ b/src/test/ui/issues/issue-2312.rs
@@ -0,0 +1,16 @@
+// compile-pass
+#![allow(dead_code)]
+#![allow(non_camel_case_types)]
+
+// Testing that the B's are resolved
+
+
+trait clam<A> { fn get(self) -> A; }
+
+struct foo(isize);
+
+impl foo {
+    pub fn bar<B,C:clam<B>>(&self, _c: C) -> B { panic!(); }
+}
+
+pub fn main() { }
diff --git a/src/test/ui/issues/issue-23122-1.rs b/src/test/ui/issues/issue-23122-1.rs
new file mode 100644
index 0000000..d6f6465
--- /dev/null
+++ b/src/test/ui/issues/issue-23122-1.rs
@@ -0,0 +1,13 @@
+trait Next {
+    type Next: Next;
+}
+
+struct GetNext<T: Next> { t: T }
+
+impl<T: Next> Next for GetNext<T> {
+    //~^ ERROR overflow evaluating the requirement
+    type Next = <GetNext<T> as Next>::Next;
+    //~^ ERROR overflow evaluating the requirement
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-23122-1.stderr b/src/test/ui/issues/issue-23122-1.stderr
new file mode 100644
index 0000000..1b752b7
--- /dev/null
+++ b/src/test/ui/issues/issue-23122-1.stderr
@@ -0,0 +1,15 @@
+error[E0275]: overflow evaluating the requirement `<GetNext<T> as Next>::Next`
+  --> $DIR/issue-23122-1.rs:7:15
+   |
+LL | impl<T: Next> Next for GetNext<T> {
+   |               ^^^^
+
+error[E0275]: overflow evaluating the requirement `<GetNext<T> as Next>::Next`
+  --> $DIR/issue-23122-1.rs:9:5
+   |
+LL |     type Next = <GetNext<T> as Next>::Next;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/src/test/ui/issues/issue-23122-2.rs b/src/test/ui/issues/issue-23122-2.rs
new file mode 100644
index 0000000..695712d
--- /dev/null
+++ b/src/test/ui/issues/issue-23122-2.rs
@@ -0,0 +1,13 @@
+trait Next {
+    type Next: Next;
+}
+
+struct GetNext<T: Next> { t: T }
+
+impl<T: Next> Next for GetNext<T> {
+    //~^ ERROR overflow evaluating the requirement
+    type Next = <GetNext<T::Next> as Next>::Next;
+    //~^ ERROR overflow evaluating the requirement
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-23122-2.stderr b/src/test/ui/issues/issue-23122-2.stderr
new file mode 100644
index 0000000..b122dd4
--- /dev/null
+++ b/src/test/ui/issues/issue-23122-2.stderr
@@ -0,0 +1,21 @@
+error[E0275]: overflow evaluating the requirement `<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<T as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next: std::marker::Sized`
+  --> $DIR/issue-23122-2.rs:7:15
+   |
+LL | impl<T: Next> Next for GetNext<T> {
+   |               ^^^^
+   |
+   = help: consider adding a `#![recursion_limit="128"]` attribute to your crate
+   = note: required because of the requirements on the impl of `Next` for `GetNext<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<T as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>`
+
+error[E0275]: overflow evaluating the requirement `<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<T as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next: std::marker::Sized`
+  --> $DIR/issue-23122-2.rs:9:5
+   |
+LL |     type Next = <GetNext<T::Next> as Next>::Next;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding a `#![recursion_limit="128"]` attribute to your crate
+   = note: required because of the requirements on the impl of `Next` for `GetNext<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<T as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/src/test/ui/issues/issue-23173.rs b/src/test/ui/issues/issue-23173.rs
new file mode 100644
index 0000000..2922ebd
--- /dev/null
+++ b/src/test/ui/issues/issue-23173.rs
@@ -0,0 +1,17 @@
+enum Token { LeftParen, RightParen, Plus, Minus, /* etc */ }
+struct Struct {
+    a: usize,
+}
+
+fn use_token(token: &Token) { unimplemented!() }
+
+fn main() {
+    use_token(&Token::Homura);
+    //~^ ERROR no variant named `Homura`
+    Struct::method();
+    //~^ ERROR no function or associated item named `method` found for type
+    Struct::method;
+    //~^ ERROR no function or associated item named `method` found for type
+    Struct::Assoc;
+    //~^ ERROR no associated item named `Assoc` found for type `Struct` in
+}
diff --git a/src/test/ui/issues/issue-23173.stderr b/src/test/ui/issues/issue-23173.stderr
new file mode 100644
index 0000000..75dba88
--- /dev/null
+++ b/src/test/ui/issues/issue-23173.stderr
@@ -0,0 +1,39 @@
+error[E0599]: no variant named `Homura` found for type `Token` in the current scope
+  --> $DIR/issue-23173.rs:9:23
+   |
+LL | enum Token { LeftParen, RightParen, Plus, Minus, /* etc */ }
+   | ---------- variant `Homura` not found here
+...
+LL |     use_token(&Token::Homura);
+   |                       ^^^^^^ variant not found in `Token`
+
+error[E0599]: no function or associated item named `method` found for type `Struct` in the current scope
+  --> $DIR/issue-23173.rs:11:13
+   |
+LL | struct Struct {
+   | ------------- function or associated item `method` not found for this
+...
+LL |     Struct::method();
+   |             ^^^^^^ function or associated item not found in `Struct`
+
+error[E0599]: no function or associated item named `method` found for type `Struct` in the current scope
+  --> $DIR/issue-23173.rs:13:13
+   |
+LL | struct Struct {
+   | ------------- function or associated item `method` not found for this
+...
+LL |     Struct::method;
+   |             ^^^^^^ function or associated item not found in `Struct`
+
+error[E0599]: no associated item named `Assoc` found for type `Struct` in the current scope
+  --> $DIR/issue-23173.rs:15:13
+   |
+LL | struct Struct {
+   | ------------- associated item `Assoc` not found for this
+...
+LL |     Struct::Assoc;
+   |             ^^^^^ associated item not found in `Struct`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/issues/issue-23189.rs b/src/test/ui/issues/issue-23189.rs
new file mode 100644
index 0000000..e552635
--- /dev/null
+++ b/src/test/ui/issues/issue-23189.rs
@@ -0,0 +1,5 @@
+mod module {}
+
+fn main() {
+    let _ = module { x: 0 }; //~ERROR expected struct
+}
diff --git a/src/test/ui/issues/issue-23189.stderr b/src/test/ui/issues/issue-23189.stderr
new file mode 100644
index 0000000..ed06521
--- /dev/null
+++ b/src/test/ui/issues/issue-23189.stderr
@@ -0,0 +1,9 @@
+error[E0574]: expected struct, variant or union type, found module `module`
+  --> $DIR/issue-23189.rs:4:13
+   |
+LL |     let _ = module { x: 0 };
+   |             ^^^^^^ not a struct, variant or union type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0574`.
diff --git a/src/test/ui/issues/issue-23217.rs b/src/test/ui/issues/issue-23217.rs
new file mode 100644
index 0000000..11426df
--- /dev/null
+++ b/src/test/ui/issues/issue-23217.rs
@@ -0,0 +1,6 @@
+pub enum SomeEnum {
+    B = SomeEnum::A,
+    //~^ ERROR no variant named `A` found for type `SomeEnum`
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-23217.stderr b/src/test/ui/issues/issue-23217.stderr
new file mode 100644
index 0000000..2a98242
--- /dev/null
+++ b/src/test/ui/issues/issue-23217.stderr
@@ -0,0 +1,14 @@
+error[E0599]: no variant named `A` found for type `SomeEnum` in the current scope
+  --> $DIR/issue-23217.rs:2:19
+   |
+LL | pub enum SomeEnum {
+   | ----------------- variant `A` not found here
+LL |     B = SomeEnum::A,
+   |                   ^
+   |                   |
+   |                   variant not found in `SomeEnum`
+   |                   help: did you mean: `B`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/issues/issue-23253.rs b/src/test/ui/issues/issue-23253.rs
new file mode 100644
index 0000000..22b55c2
--- /dev/null
+++ b/src/test/ui/issues/issue-23253.rs
@@ -0,0 +1,6 @@
+enum Foo { Bar }
+
+fn main() {
+    Foo::Bar.a;
+    //~^ no field `a` on type `Foo`
+}
diff --git a/src/test/ui/issues/issue-23253.stderr b/src/test/ui/issues/issue-23253.stderr
new file mode 100644
index 0000000..be5714c
--- /dev/null
+++ b/src/test/ui/issues/issue-23253.stderr
@@ -0,0 +1,9 @@
+error[E0609]: no field `a` on type `Foo`
+  --> $DIR/issue-23253.rs:4:14
+   |
+LL |     Foo::Bar.a;
+   |              ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0609`.
diff --git a/src/test/ui/issues/issue-23281.rs b/src/test/ui/issues/issue-23281.rs
new file mode 100644
index 0000000..98a0495
--- /dev/null
+++ b/src/test/ui/issues/issue-23281.rs
@@ -0,0 +1,10 @@
+// ignore-tidy-linelength
+
+pub struct Struct;
+
+impl Struct {
+    pub fn function(funs: Vec<Fn() -> ()>) {}
+    //~^ ERROR the size for values of type
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-23281.stderr b/src/test/ui/issues/issue-23281.stderr
new file mode 100644
index 0000000..1e57774a
--- /dev/null
+++ b/src/test/ui/issues/issue-23281.stderr
@@ -0,0 +1,13 @@
+error[E0277]: the size for values of type `(dyn std::ops::Fn() + 'static)` cannot be known at compilation time
+  --> $DIR/issue-23281.rs:6:5
+   |
+LL |     pub fn function(funs: Vec<Fn() -> ()>) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `(dyn std::ops::Fn() + 'static)`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: required by `std::vec::Vec`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-2330.rs b/src/test/ui/issues/issue-2330.rs
new file mode 100644
index 0000000..4560cab
--- /dev/null
+++ b/src/test/ui/issues/issue-2330.rs
@@ -0,0 +1,13 @@
+enum Chan { }
+
+trait Channel<T> {
+    fn send(&self, v: T);
+}
+
+// `Chan` is not a trait, it's an enum
+impl Chan for isize { //~ ERROR expected trait, found enum `Chan`
+    fn send(&self, v: isize) { panic!() }
+}
+
+fn main() {
+}
diff --git a/src/test/ui/issues/issue-2330.stderr b/src/test/ui/issues/issue-2330.stderr
new file mode 100644
index 0000000..877cf68
--- /dev/null
+++ b/src/test/ui/issues/issue-2330.stderr
@@ -0,0 +1,9 @@
+error[E0404]: expected trait, found enum `Chan`
+  --> $DIR/issue-2330.rs:8:6
+   |
+LL | impl Chan for isize {
+   |      ^^^^ not a trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0404`.
diff --git a/src/test/ui/issues/issue-23302-1.rs b/src/test/ui/issues/issue-23302-1.rs
new file mode 100644
index 0000000..24e79dc
--- /dev/null
+++ b/src/test/ui/issues/issue-23302-1.rs
@@ -0,0 +1,7 @@
+// Check that an enum with recursion in the discriminant throws
+// the appropriate error (rather than, say, blowing the stack).
+enum X {
+    A = X::A as isize, //~ ERROR E0391
+}
+
+fn main() { }
diff --git a/src/test/ui/issues/issue-23302-1.stderr b/src/test/ui/issues/issue-23302-1.stderr
new file mode 100644
index 0000000..43effc0
--- /dev/null
+++ b/src/test/ui/issues/issue-23302-1.stderr
@@ -0,0 +1,16 @@
+error[E0391]: cycle detected when processing `X::A::{{constant}}#0`
+  --> $DIR/issue-23302-1.rs:4:9
+   |
+LL |     A = X::A as isize,
+   |         ^^^^^^^^^^^^^
+   |
+   = note: ...which again requires processing `X::A::{{constant}}#0`, completing the cycle
+note: cycle used when const-evaluating `X::A::{{constant}}#0`
+  --> $DIR/issue-23302-1.rs:4:9
+   |
+LL |     A = X::A as isize,
+   |         ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/issues/issue-23302-2.rs b/src/test/ui/issues/issue-23302-2.rs
new file mode 100644
index 0000000..e89c7ea
--- /dev/null
+++ b/src/test/ui/issues/issue-23302-2.rs
@@ -0,0 +1,8 @@
+// Since `Y::B` here defaults to `Y::A+1`, this is also a
+// recursive definition.
+enum Y {
+    A = Y::B as isize, //~ ERROR E0391
+    B,
+}
+
+fn main() { }
diff --git a/src/test/ui/issues/issue-23302-2.stderr b/src/test/ui/issues/issue-23302-2.stderr
new file mode 100644
index 0000000..707d4fa
--- /dev/null
+++ b/src/test/ui/issues/issue-23302-2.stderr
@@ -0,0 +1,16 @@
+error[E0391]: cycle detected when processing `Y::A::{{constant}}#0`
+  --> $DIR/issue-23302-2.rs:4:9
+   |
+LL |     A = Y::B as isize,
+   |         ^^^^^^^^^^^^^
+   |
+   = note: ...which again requires processing `Y::A::{{constant}}#0`, completing the cycle
+note: cycle used when const-evaluating `Y::A::{{constant}}#0`
+  --> $DIR/issue-23302-2.rs:4:9
+   |
+LL |     A = Y::B as isize,
+   |         ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/issues/issue-23302-3.rs b/src/test/ui/issues/issue-23302-3.rs
new file mode 100644
index 0000000..da75f33
--- /dev/null
+++ b/src/test/ui/issues/issue-23302-3.rs
@@ -0,0 +1,5 @@
+const A: i32 = B; //~ ERROR cycle detected
+
+const B: i32 = A;
+
+fn main() { }
diff --git a/src/test/ui/issues/issue-23302-3.stderr b/src/test/ui/issues/issue-23302-3.stderr
new file mode 100644
index 0000000..a7d6439
--- /dev/null
+++ b/src/test/ui/issues/issue-23302-3.stderr
@@ -0,0 +1,27 @@
+error[E0391]: cycle detected when const checking if rvalue is promotable to static `A`
+  --> $DIR/issue-23302-3.rs:1:1
+   |
+LL | const A: i32 = B;
+   | ^^^^^^^^^^^^^^^^^
+   |
+note: ...which requires checking which parts of `A` are promotable to static...
+  --> $DIR/issue-23302-3.rs:1:16
+   |
+LL | const A: i32 = B;
+   |                ^
+note: ...which requires const checking if rvalue is promotable to static `B`...
+  --> $DIR/issue-23302-3.rs:3:1
+   |
+LL | const B: i32 = A;
+   | ^^^^^^^^^^^^^^^^^
+note: ...which requires checking which parts of `B` are promotable to static...
+  --> $DIR/issue-23302-3.rs:3:16
+   |
+LL | const B: i32 = A;
+   |                ^
+   = note: ...which again requires const checking if rvalue is promotable to static `A`, completing the cycle
+   = note: cycle used when running analysis passes on this crate
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/issues/issue-23406.rs b/src/test/ui/issues/issue-23406.rs
new file mode 100644
index 0000000..9d77af0
--- /dev/null
+++ b/src/test/ui/issues/issue-23406.rs
@@ -0,0 +1,15 @@
+// compile-pass
+#![allow(dead_code)]
+trait Inner {
+    type T;
+}
+
+impl<'a> Inner for &'a i32 {
+    type T = i32;
+}
+
+fn f<'a>(x: &'a i32) -> <&'a i32 as Inner>::T {
+    *x
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-23442.rs b/src/test/ui/issues/issue-23442.rs
new file mode 100644
index 0000000..c3b613a
--- /dev/null
+++ b/src/test/ui/issues/issue-23442.rs
@@ -0,0 +1,23 @@
+// compile-pass
+#![allow(dead_code)]
+use std::marker::PhantomData;
+
+pub struct UnionedKeys<'a,K>
+    where K: UnifyKey + 'a
+{
+    table: &'a mut UnificationTable<K>,
+    root_key: K,
+    stack: Vec<K>,
+}
+
+pub trait UnifyKey {
+    type Value;
+}
+
+pub struct UnificationTable<K:UnifyKey> {
+    values: Delegate<K>,
+}
+
+pub struct Delegate<K>(PhantomData<K>);
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-23458.rs b/src/test/ui/issues/issue-23458.rs
new file mode 100644
index 0000000..90b3f1f
--- /dev/null
+++ b/src/test/ui/issues/issue-23458.rs
@@ -0,0 +1,10 @@
+#![feature(asm)]
+
+// only-x86_64
+
+fn main() {
+    unsafe {
+        asm!("int $3"); //~ ERROR too few operands for instruction
+                        //~| ERROR invalid operand in inline asm
+    }
+}
diff --git a/src/test/ui/issues/issue-23458.stderr b/src/test/ui/issues/issue-23458.stderr
new file mode 100644
index 0000000..aff0f82
--- /dev/null
+++ b/src/test/ui/issues/issue-23458.stderr
@@ -0,0 +1,17 @@
+error: invalid operand in inline asm: 'int $3'
+  --> $DIR/issue-23458.rs:7:9
+   |
+LL |         asm!("int $3");
+   |         ^^^^^^^^^^^^^^^
+
+error: <inline asm>:1:2: error: too few operands for instruction
+        int 
+        ^
+
+  --> $DIR/issue-23458.rs:7:9
+   |
+LL |         asm!("int $3");
+   |         ^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/issues/issue-23477.rs b/src/test/ui/issues/issue-23477.rs
new file mode 100644
index 0000000..f363e6a
--- /dev/null
+++ b/src/test/ui/issues/issue-23477.rs
@@ -0,0 +1,15 @@
+// compile-pass
+// compiler-flags: -g
+
+pub struct Dst {
+    pub a: (),
+    pub b: (),
+    pub data: [u8],
+}
+
+pub unsafe fn borrow(bytes: &[u8]) -> &Dst {
+    let dst: &Dst = std::mem::transmute((bytes.as_ptr(), bytes.len()));
+    dst
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-23543.rs b/src/test/ui/issues/issue-23543.rs
new file mode 100644
index 0000000..843e1a8
--- /dev/null
+++ b/src/test/ui/issues/issue-23543.rs
@@ -0,0 +1,11 @@
+pub trait A: Copy {}
+
+struct Foo;
+
+pub trait D {
+    fn f<T>(self)
+        where T<Bogus = Foo>: A;
+        //~^ ERROR associated type bindings are not allowed here [E0229]
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-23543.stderr b/src/test/ui/issues/issue-23543.stderr
new file mode 100644
index 0000000..ebb70af
--- /dev/null
+++ b/src/test/ui/issues/issue-23543.stderr
@@ -0,0 +1,9 @@
+error[E0229]: associated type bindings are not allowed here
+  --> $DIR/issue-23543.rs:7:17
+   |
+LL |         where T<Bogus = Foo>: A;
+   |                 ^^^^^^^^^^^ associated type not allowed here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0229`.
diff --git a/src/test/ui/issues/issue-23544.rs b/src/test/ui/issues/issue-23544.rs
new file mode 100644
index 0000000..6ad00b2
--- /dev/null
+++ b/src/test/ui/issues/issue-23544.rs
@@ -0,0 +1,9 @@
+pub trait A: Copy {}
+
+pub trait D {
+    fn f<T>(self)
+        where T<Bogus = Self::AlsoBogus>: A;
+        //~^ ERROR associated type bindings are not allowed here [E0229]
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-23544.stderr b/src/test/ui/issues/issue-23544.stderr
new file mode 100644
index 0000000..c912bac
--- /dev/null
+++ b/src/test/ui/issues/issue-23544.stderr
@@ -0,0 +1,9 @@
+error[E0229]: associated type bindings are not allowed here
+  --> $DIR/issue-23544.rs:5:17
+   |
+LL |         where T<Bogus = Self::AlsoBogus>: A;
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^ associated type not allowed here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0229`.
diff --git a/src/test/ui/issues/issue-23550.rs b/src/test/ui/issues/issue-23550.rs
new file mode 100644
index 0000000..370d5c5
--- /dev/null
+++ b/src/test/ui/issues/issue-23550.rs
@@ -0,0 +1,22 @@
+// compile-pass
+#![feature(core_intrinsics)]
+#![allow(warnings)]
+
+use std::intrinsics;
+
+#[derive(Copy, Clone)]
+struct Wrap(i64);
+
+// These volatile intrinsics used to cause an ICE
+
+unsafe fn test_bool(p: &mut bool, v: bool) {
+    intrinsics::volatile_load(p);
+    intrinsics::volatile_store(p, v);
+}
+
+unsafe fn test_immediate_fca(p: &mut Wrap, v: Wrap) {
+    intrinsics::volatile_load(p);
+    intrinsics::volatile_store(p, v);
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-23589.rs b/src/test/ui/issues/issue-23589.rs
new file mode 100644
index 0000000..1c640af
--- /dev/null
+++ b/src/test/ui/issues/issue-23589.rs
@@ -0,0 +1,5 @@
+fn main() {
+    let v: Vec(&str) = vec!['1', '2'];
+    //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
+    //~| ERROR mismatched types
+}
diff --git a/src/test/ui/issues/issue-23589.stderr b/src/test/ui/issues/issue-23589.stderr
new file mode 100644
index 0000000..bc2007b
--- /dev/null
+++ b/src/test/ui/issues/issue-23589.stderr
@@ -0,0 +1,22 @@
+error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
+  --> $DIR/issue-23589.rs:2:15
+   |
+LL |     let v: Vec(&str) = vec!['1', '2'];
+   |               ^^^^^^
+   |               |
+   |               only `Fn` traits may use parentheses
+   |               help: use angle brackets instead: `<&str>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-23589.rs:2:29
+   |
+LL |     let v: Vec(&str) = vec!['1', '2'];
+   |                             ^^^ expected &str, found char
+   |
+   = note: expected type `&str`
+              found type `char`
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0214, E0308.
+For more information about an error, try `rustc --explain E0214`.
diff --git a/src/test/ui/issues/issue-23595-2.rs b/src/test/ui/issues/issue-23595-2.rs
new file mode 100644
index 0000000..2bfee7a
--- /dev/null
+++ b/src/test/ui/issues/issue-23595-2.rs
@@ -0,0 +1,10 @@
+#![feature(associated_type_defaults)]
+
+pub struct C<AType: A> {a:AType}
+
+pub trait A {
+    type B = C<Self::anything_here_kills_it>;
+    //~^ ERROR: associated type `anything_here_kills_it` not found for `Self`
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-23595-2.stderr b/src/test/ui/issues/issue-23595-2.stderr
new file mode 100644
index 0000000..f1004db
--- /dev/null
+++ b/src/test/ui/issues/issue-23595-2.stderr
@@ -0,0 +1,9 @@
+error[E0220]: associated type `anything_here_kills_it` not found for `Self`
+  --> $DIR/issue-23595-2.rs:6:16
+   |
+LL |     type B = C<Self::anything_here_kills_it>;
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ associated type `anything_here_kills_it` not found
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0220`.
diff --git a/src/test/ui/issues/issue-23649-3.rs b/src/test/ui/issues/issue-23649-3.rs
new file mode 100644
index 0000000..718fe60
--- /dev/null
+++ b/src/test/ui/issues/issue-23649-3.rs
@@ -0,0 +1,5 @@
+// compile-pass
+#[derive(PartialEq)]
+struct Slice { slice: [u8] }
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-23716.rs b/src/test/ui/issues/issue-23716.rs
new file mode 100644
index 0000000..e9139c0
--- /dev/null
+++ b/src/test/ui/issues/issue-23716.rs
@@ -0,0 +1,17 @@
+static foo: i32 = 0;
+
+fn bar(foo: i32) {}
+//~^ ERROR function parameters cannot shadow statics
+//~| cannot be named the same as a static
+
+mod submod {
+    pub static answer: i32 = 42;
+}
+
+use self::submod::answer;
+
+fn question(answer: i32) {}
+//~^ ERROR function parameters cannot shadow statics
+//~| cannot be named the same as a static
+fn main() {
+}
diff --git a/src/test/ui/issues/issue-23716.stderr b/src/test/ui/issues/issue-23716.stderr
new file mode 100644
index 0000000..e7bebfb
--- /dev/null
+++ b/src/test/ui/issues/issue-23716.stderr
@@ -0,0 +1,21 @@
+error[E0530]: function parameters cannot shadow statics
+  --> $DIR/issue-23716.rs:3:8
+   |
+LL | static foo: i32 = 0;
+   | -------------------- the static `foo` is defined here
+LL | 
+LL | fn bar(foo: i32) {}
+   |        ^^^ cannot be named the same as a static
+
+error[E0530]: function parameters cannot shadow statics
+  --> $DIR/issue-23716.rs:13:13
+   |
+LL | use self::submod::answer;
+   |     -------------------- the static `answer` is imported here
+LL | 
+LL | fn question(answer: i32) {}
+   |             ^^^^^^ cannot be named the same as a static
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0530`.
diff --git a/src/test/ui/issues/issue-23966.rs b/src/test/ui/issues/issue-23966.rs
new file mode 100644
index 0000000..5fdec28
--- /dev/null
+++ b/src/test/ui/issues/issue-23966.rs
@@ -0,0 +1,4 @@
+fn main() {
+    "".chars().fold(|_, _| (), ());
+    //~^ ERROR E0277
+}
diff --git a/src/test/ui/issues/issue-23966.stderr b/src/test/ui/issues/issue-23966.stderr
new file mode 100644
index 0000000..ac64067
--- /dev/null
+++ b/src/test/ui/issues/issue-23966.stderr
@@ -0,0 +1,11 @@
+error[E0277]: expected a `std::ops::FnMut<(_, char)>` closure, found `()`
+  --> $DIR/issue-23966.rs:2:16
+   |
+LL |     "".chars().fold(|_, _| (), ());
+   |                ^^^^ expected an `FnMut<(_, char)>` closure, found `()`
+   |
+   = help: the trait `std::ops::FnMut<(_, char)>` is not implemented for `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-24013.rs b/src/test/ui/issues/issue-24013.rs
new file mode 100644
index 0000000..c6d3016
--- /dev/null
+++ b/src/test/ui/issues/issue-24013.rs
@@ -0,0 +1,7 @@
+fn main() {
+    use std::mem::{transmute, swap};
+    let a = 1;
+    let b = 2;
+    unsafe {swap::<&mut _>(transmute(&a), transmute(&b))};
+    //~^ ERROR type annotations needed
+}
diff --git a/src/test/ui/issues/issue-24013.stderr b/src/test/ui/issues/issue-24013.stderr
new file mode 100644
index 0000000..4e3cb88
--- /dev/null
+++ b/src/test/ui/issues/issue-24013.stderr
@@ -0,0 +1,9 @@
+error[E0282]: type annotations needed
+  --> $DIR/issue-24013.rs:5:20
+   |
+LL |     unsafe {swap::<&mut _>(transmute(&a), transmute(&b))};
+   |                    ^^^^^^ cannot infer type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/issues/issue-24036.rs b/src/test/ui/issues/issue-24036.rs
new file mode 100644
index 0000000..2f501b9
--- /dev/null
+++ b/src/test/ui/issues/issue-24036.rs
@@ -0,0 +1,16 @@
+fn closure_to_loc() {
+    let mut x = |c| c + 1;
+    x = |c| c + 1;
+    //~^ ERROR mismatched types
+}
+
+fn closure_from_match() {
+    let x = match 1usize {
+        1 => |c| c + 1,
+        2 => |c| c - 1,
+        _ => |c| c - 1
+    };
+    //~^^^ ERROR match arms have incompatible types
+}
+
+fn main() { }
diff --git a/src/test/ui/issues/issue-24036.stderr b/src/test/ui/issues/issue-24036.stderr
new file mode 100644
index 0000000..fa9935f
--- /dev/null
+++ b/src/test/ui/issues/issue-24036.stderr
@@ -0,0 +1,32 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-24036.rs:3:9
+   |
+LL |     x = |c| c + 1;
+   |         ^^^^^^^^^ expected closure, found a different closure
+   |
+   = note: expected type `[closure@$DIR/issue-24036.rs:2:17: 2:26]`
+              found type `[closure@$DIR/issue-24036.rs:3:9: 3:18]`
+   = note: no two closures, even if identical, have the same type
+   = help: consider boxing your closure and/or using it as a trait object
+
+error[E0308]: match arms have incompatible types
+  --> $DIR/issue-24036.rs:10:14
+   |
+LL |       let x = match 1usize {
+   |  _____________-
+LL | |         1 => |c| c + 1,
+   | |              --------- this is found to be of type `[closure@$DIR/issue-24036.rs:9:14: 9:23]`
+LL | |         2 => |c| c - 1,
+   | |              ^^^^^^^^^ expected closure, found a different closure
+LL | |         _ => |c| c - 1
+LL | |     };
+   | |_____- `match` arms have incompatible types
+   |
+   = note: expected type `[closure@$DIR/issue-24036.rs:9:14: 9:23]`
+              found type `[closure@$DIR/issue-24036.rs:10:14: 10:23]`
+   = note: no two closures, even if identical, have the same type
+   = help: consider boxing your closure and/or using it as a trait object
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-24081.rs b/src/test/ui/issues/issue-24081.rs
new file mode 100644
index 0000000..10983ce
--- /dev/null
+++ b/src/test/ui/issues/issue-24081.rs
@@ -0,0 +1,18 @@
+use std::ops::Add;
+use std::ops::Sub;
+use std::ops::Mul;
+use std::ops::Div;
+use std::ops::Rem;
+
+type Add = bool; //~ ERROR the name `Add` is defined multiple times
+//~| `Add` redefined here
+struct Sub { x: f32 } //~ ERROR the name `Sub` is defined multiple times
+//~| `Sub` redefined here
+enum Mul { A, B } //~ ERROR the name `Mul` is defined multiple times
+//~| `Mul` redefined here
+mod Div { } //~ ERROR the name `Div` is defined multiple times
+//~| `Div` redefined here
+trait Rem {  } //~ ERROR the name `Rem` is defined multiple times
+//~| `Rem` redefined here
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-24081.stderr b/src/test/ui/issues/issue-24081.stderr
new file mode 100644
index 0000000..647048c
--- /dev/null
+++ b/src/test/ui/issues/issue-24081.stderr
@@ -0,0 +1,78 @@
+error[E0255]: the name `Add` is defined multiple times
+  --> $DIR/issue-24081.rs:7:1
+   |
+LL | use std::ops::Add;
+   |     ------------- previous import of the trait `Add` here
+...
+LL | type Add = bool;
+   | ^^^^^^^^^^^^^^^^ `Add` redefined here
+   |
+   = note: `Add` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | use std::ops::Add as OtherAdd;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0255]: the name `Sub` is defined multiple times
+  --> $DIR/issue-24081.rs:9:1
+   |
+LL | use std::ops::Sub;
+   |     ------------- previous import of the trait `Sub` here
+...
+LL | struct Sub { x: f32 }
+   | ^^^^^^^^^^ `Sub` redefined here
+   |
+   = note: `Sub` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | use std::ops::Sub as OtherSub;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0255]: the name `Mul` is defined multiple times
+  --> $DIR/issue-24081.rs:11:1
+   |
+LL | use std::ops::Mul;
+   |     ------------- previous import of the trait `Mul` here
+...
+LL | enum Mul { A, B }
+   | ^^^^^^^^ `Mul` redefined here
+   |
+   = note: `Mul` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | use std::ops::Mul as OtherMul;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0255]: the name `Div` is defined multiple times
+  --> $DIR/issue-24081.rs:13:1
+   |
+LL | use std::ops::Div;
+   |     ------------- previous import of the trait `Div` here
+...
+LL | mod Div { }
+   | ^^^^^^^ `Div` redefined here
+   |
+   = note: `Div` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | use std::ops::Div as OtherDiv;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0255]: the name `Rem` is defined multiple times
+  --> $DIR/issue-24081.rs:15:1
+   |
+LL | use std::ops::Rem;
+   |     ------------- previous import of the trait `Rem` here
+...
+LL | trait Rem {  }
+   | ^^^^^^^^^ `Rem` redefined here
+   |
+   = note: `Rem` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | use std::ops::Rem as OtherRem;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0255`.
diff --git a/src/test/ui/issues/issue-24085.rs b/src/test/ui/issues/issue-24085.rs
new file mode 100644
index 0000000..d066477
--- /dev/null
+++ b/src/test/ui/issues/issue-24085.rs
@@ -0,0 +1,19 @@
+// compile-pass
+#![allow(dead_code)]
+// Regression test for #24085. Errors were occurring in region
+// inference due to the requirement that `'a:b'`, which was getting
+// incorrectly codegened in connection with the closure below.
+
+#[derive(Copy,Clone)]
+struct Path<'a:'b, 'b> {
+    x: &'a i32,
+    tail: Option<&'b Path<'a, 'b>>
+}
+
+#[allow(dead_code, unconditional_recursion)]
+fn foo<'a,'b,F>(p: Path<'a, 'b>, mut f: F)
+                where F: for<'c> FnMut(Path<'a, 'c>) {
+    foo(p, |x| f(x))
+}
+
+fn main() { }
diff --git a/src/test/ui/issues/issue-24161.rs b/src/test/ui/issues/issue-24161.rs
new file mode 100644
index 0000000..99b09ba
--- /dev/null
+++ b/src/test/ui/issues/issue-24161.rs
@@ -0,0 +1,11 @@
+// compile-pass
+#![allow(dead_code)]
+#[derive(Copy,Clone)]
+struct Functions {
+    a: fn(u32) -> u32,
+    b: extern "C" fn(u32) -> u32,
+    c: unsafe fn(u32) -> u32,
+    d: unsafe extern "C" fn(u32) -> u32
+}
+
+pub fn main() {}
diff --git a/src/test/ui/issues/issue-24204.rs b/src/test/ui/issues/issue-24204.rs
new file mode 100644
index 0000000..61671b3
--- /dev/null
+++ b/src/test/ui/issues/issue-24204.rs
@@ -0,0 +1,17 @@
+#![allow(dead_code)]
+
+trait MultiDispatch<T> {
+    type O;
+}
+
+trait Trait: Sized {
+    type A: MultiDispatch<Self::B, O = Self>;
+    type B;
+
+    fn new<U>(u: U) -> <Self::A as MultiDispatch<U>>::O where Self::A : MultiDispatch<U>;
+}
+
+fn test<T: Trait<B=i32>>(b: i32) -> T where T::A: MultiDispatch<i32> { T::new(b) }
+//~^ ERROR type mismatch resolving
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-24204.stderr b/src/test/ui/issues/issue-24204.stderr
new file mode 100644
index 0000000..8e04c0d
--- /dev/null
+++ b/src/test/ui/issues/issue-24204.stderr
@@ -0,0 +1,17 @@
+error[E0271]: type mismatch resolving `<<T as Trait>::A as MultiDispatch<i32>>::O == T`
+  --> $DIR/issue-24204.rs:14:1
+   |
+LL | fn test<T: Trait<B=i32>>(b: i32) -> T where T::A: MultiDispatch<i32> { T::new(b) }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found type parameter
+   |
+   = note: expected type `<<T as Trait>::A as MultiDispatch<i32>>::O`
+              found type `T`
+note: required by `Trait`
+  --> $DIR/issue-24204.rs:7:1
+   |
+LL | trait Trait: Sized {
+   | ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/issues/issue-24227.rs b/src/test/ui/issues/issue-24227.rs
new file mode 100644
index 0000000..83e12ca
--- /dev/null
+++ b/src/test/ui/issues/issue-24227.rs
@@ -0,0 +1,18 @@
+// compile-pass
+// This resulted in an ICE. Test for future-proofing
+// Issue #24227
+
+#![allow(unused)]
+
+struct Foo<'a> {
+    x: &'a u8
+}
+
+impl<'a> Foo<'a> {
+    fn foo() {
+        let mut tmp: Self;
+    }
+
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-24267-flow-exit.nll.stderr b/src/test/ui/issues/issue-24267-flow-exit.nll.stderr
new file mode 100644
index 0000000..3b4f276
--- /dev/null
+++ b/src/test/ui/issues/issue-24267-flow-exit.nll.stderr
@@ -0,0 +1,15 @@
+error[E0381]: borrow of possibly uninitialized variable: `x`
+  --> $DIR/issue-24267-flow-exit.rs:12:20
+   |
+LL |     println!("{}", x);
+   |                    ^ use of possibly uninitialized `x`
+
+error[E0381]: borrow of possibly uninitialized variable: `x`
+  --> $DIR/issue-24267-flow-exit.rs:18:20
+   |
+LL |     println!("{}", x);
+   |                    ^ use of possibly uninitialized `x`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/issues/issue-24267-flow-exit.rs b/src/test/ui/issues/issue-24267-flow-exit.rs
new file mode 100644
index 0000000..ce3a799
--- /dev/null
+++ b/src/test/ui/issues/issue-24267-flow-exit.rs
@@ -0,0 +1,19 @@
+// Ensure that we reject code when a nonlocal exit (`break`,
+// `continue`) causes us to pop over a needed assignment.
+
+pub fn main() {
+    foo1();
+    foo2();
+}
+
+pub fn foo1() {
+    let x: i32;
+    loop { x = break; }
+    println!("{}", x); //~ ERROR use of possibly uninitialized variable: `x`
+}
+
+pub fn foo2() {
+    let x: i32;
+    for _ in 0..10 { x = continue; }
+    println!("{}", x); //~ ERROR use of possibly uninitialized variable: `x`
+}
diff --git a/src/test/ui/issues/issue-24267-flow-exit.stderr b/src/test/ui/issues/issue-24267-flow-exit.stderr
new file mode 100644
index 0000000..2b9e2ee
--- /dev/null
+++ b/src/test/ui/issues/issue-24267-flow-exit.stderr
@@ -0,0 +1,15 @@
+error[E0381]: use of possibly uninitialized variable: `x`
+  --> $DIR/issue-24267-flow-exit.rs:12:20
+   |
+LL |     println!("{}", x);
+   |                    ^ use of possibly uninitialized `x`
+
+error[E0381]: use of possibly uninitialized variable: `x`
+  --> $DIR/issue-24267-flow-exit.rs:18:20
+   |
+LL |     println!("{}", x);
+   |                    ^ use of possibly uninitialized `x`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/issues/issue-24322.rs b/src/test/ui/issues/issue-24322.rs
new file mode 100644
index 0000000..6567fca
--- /dev/null
+++ b/src/test/ui/issues/issue-24322.rs
@@ -0,0 +1,9 @@
+struct B;
+
+impl B {
+    fn func(&self) -> u32 { 42 }
+}
+
+fn main() {
+    let x: &fn(&B) -> u32 = &B::func; //~ ERROR mismatched types
+}
diff --git a/src/test/ui/issues/issue-24322.stderr b/src/test/ui/issues/issue-24322.stderr
new file mode 100644
index 0000000..def373c
--- /dev/null
+++ b/src/test/ui/issues/issue-24322.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-24322.rs:8:29
+   |
+LL |     let x: &fn(&B) -> u32 = &B::func;
+   |                             ^^^^^^^^ expected fn pointer, found fn item
+   |
+   = note: expected type `&for<'r> fn(&'r B) -> u32`
+              found type `&for<'r> fn(&'r B) -> u32 {B::func}`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-24338.rs b/src/test/ui/issues/issue-24338.rs
new file mode 100644
index 0000000..fafeff0
--- /dev/null
+++ b/src/test/ui/issues/issue-24338.rs
@@ -0,0 +1,21 @@
+//
+// compile-pass
+
+trait DictLike<'a> {
+    type ItemsIterator: Iterator<Item=u8>;
+    fn get(c: Self::ItemsIterator) {
+        c.into_iter();
+    }
+}
+
+trait DictLike2<'a> {
+    type ItemsIterator: Iterator<Item=u8>;
+
+    fn items(&self) -> Self::ItemsIterator;
+
+    fn get(&self)  {
+        for _ in self.items() {}
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-24352.rs b/src/test/ui/issues/issue-24352.rs
new file mode 100644
index 0000000..5c8246d
--- /dev/null
+++ b/src/test/ui/issues/issue-24352.rs
@@ -0,0 +1,4 @@
+fn main() {
+    1.0f64 - 1.0;
+    1.0f64 - 1 //~ ERROR E0277
+}
diff --git a/src/test/ui/issues/issue-24352.stderr b/src/test/ui/issues/issue-24352.stderr
new file mode 100644
index 0000000..a315ca8
--- /dev/null
+++ b/src/test/ui/issues/issue-24352.stderr
@@ -0,0 +1,11 @@
+error[E0277]: cannot subtract `{integer}` from `f64`
+  --> $DIR/issue-24352.rs:3:12
+   |
+LL |     1.0f64 - 1
+   |            ^ no implementation for `f64 - {integer}`
+   |
+   = help: the trait `std::ops::Sub<{integer}>` is not implemented for `f64`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-24357.nll.stderr b/src/test/ui/issues/issue-24357.nll.stderr
new file mode 100644
index 0000000..a9c43a8
--- /dev/null
+++ b/src/test/ui/issues/issue-24357.nll.stderr
@@ -0,0 +1,16 @@
+error[E0382]: use of moved value: `x`
+  --> $DIR/issue-24357.rs:6:12
+   |
+LL |    let x = NoCopy;
+   |        - move occurs because `x` has type `NoCopy`, which does not implement the `Copy` trait
+LL |    let f = move || { let y = x; };
+   |            -------           - variable moved due to use in closure
+   |            |
+   |            value moved into closure here
+LL |
+LL |    let z = x;
+   |            ^ value used here after move
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/issues/issue-24357.rs b/src/test/ui/issues/issue-24357.rs
new file mode 100644
index 0000000..84f263f
--- /dev/null
+++ b/src/test/ui/issues/issue-24357.rs
@@ -0,0 +1,10 @@
+struct NoCopy;
+fn main() {
+   let x = NoCopy;
+   let f = move || { let y = x; };
+   //~^ NOTE value moved (into closure) here
+   let z = x;
+   //~^ ERROR use of moved value: `x`
+   //~| NOTE value used here after move
+   //~| NOTE move occurs because `x` has type `NoCopy`
+}
diff --git a/src/test/ui/issues/issue-24357.stderr b/src/test/ui/issues/issue-24357.stderr
new file mode 100644
index 0000000..ced24ff
--- /dev/null
+++ b/src/test/ui/issues/issue-24357.stderr
@@ -0,0 +1,14 @@
+error[E0382]: use of moved value: `x`
+  --> $DIR/issue-24357.rs:6:8
+   |
+LL |    let f = move || { let y = x; };
+   |            ------- value moved (into closure) here
+LL |
+LL |    let z = x;
+   |        ^ value used here after move
+   |
+   = note: move occurs because `x` has type `NoCopy`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/issues/issue-24363.rs b/src/test/ui/issues/issue-24363.rs
new file mode 100644
index 0000000..a5b45f1
--- /dev/null
+++ b/src/test/ui/issues/issue-24363.rs
@@ -0,0 +1,6 @@
+fn main() {
+    1.create_a_type_error[ //~ `{integer}` is a primitive type and therefore doesn't have fields
+        ()+() //~ ERROR binary operation `+` cannot be applied
+              //   ^ ensure that we typeck the inner expression ^
+    ];
+}
diff --git a/src/test/ui/issues/issue-24363.stderr b/src/test/ui/issues/issue-24363.stderr
new file mode 100644
index 0000000..6f269ba
--- /dev/null
+++ b/src/test/ui/issues/issue-24363.stderr
@@ -0,0 +1,20 @@
+error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields
+  --> $DIR/issue-24363.rs:2:7
+   |
+LL |     1.create_a_type_error[
+   |       ^^^^^^^^^^^^^^^^^^^
+
+error[E0369]: binary operation `+` cannot be applied to type `()`
+  --> $DIR/issue-24363.rs:3:11
+   |
+LL |         ()+()
+   |         --^-- ()
+   |         |
+   |         ()
+   |
+   = note: an implementation of `std::ops::Add` might be missing for `()`
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0369, E0610.
+For more information about an error, try `rustc --explain E0369`.
diff --git a/src/test/ui/issues/issue-24365.rs b/src/test/ui/issues/issue-24365.rs
new file mode 100644
index 0000000..eca104b
--- /dev/null
+++ b/src/test/ui/issues/issue-24365.rs
@@ -0,0 +1,19 @@
+pub enum Attribute {
+    Code {attr_name_idx: u16},
+}
+
+pub enum Foo {
+    Bar
+}
+
+fn test(a: Foo) {
+    println!("{}", a.b); //~ no field `b` on type `Foo`
+}
+
+fn main() {
+    let x = Attribute::Code {
+        attr_name_idx: 42,
+    };
+    let z = (&x).attr_name_idx; //~ no field `attr_name_idx` on type `&Attribute`
+    let y = x.attr_name_idx; //~ no field `attr_name_idx` on type `Attribute`
+}
diff --git a/src/test/ui/issues/issue-24365.stderr b/src/test/ui/issues/issue-24365.stderr
new file mode 100644
index 0000000..f9eead8
--- /dev/null
+++ b/src/test/ui/issues/issue-24365.stderr
@@ -0,0 +1,21 @@
+error[E0609]: no field `b` on type `Foo`
+  --> $DIR/issue-24365.rs:10:22
+   |
+LL |     println!("{}", a.b);
+   |                      ^
+
+error[E0609]: no field `attr_name_idx` on type `&Attribute`
+  --> $DIR/issue-24365.rs:17:18
+   |
+LL |     let z = (&x).attr_name_idx;
+   |                  ^^^^^^^^^^^^^
+
+error[E0609]: no field `attr_name_idx` on type `Attribute`
+  --> $DIR/issue-24365.rs:18:15
+   |
+LL |     let y = x.attr_name_idx;
+   |               ^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0609`.
diff --git a/src/test/ui/issues/issue-24389.rs b/src/test/ui/issues/issue-24389.rs
new file mode 100644
index 0000000..da48a76
--- /dev/null
+++ b/src/test/ui/issues/issue-24389.rs
@@ -0,0 +1,11 @@
+// compile-pass
+#![allow(dead_code)]
+
+struct Foo;
+
+impl Foo {
+    fn new() -> Self { Foo }
+    fn bar() { Self::new(); }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-24424.rs b/src/test/ui/issues/issue-24424.rs
new file mode 100644
index 0000000..8b8c5bc
--- /dev/null
+++ b/src/test/ui/issues/issue-24424.rs
@@ -0,0 +1,7 @@
+trait Trait1<'l0, T0> {}
+trait Trait0<'l0>  {}
+
+impl <'l0, 'l1, T0> Trait1<'l0, T0> for bool where T0 : Trait0<'l0>, T0 : Trait0<'l1> {}
+//~^ ERROR type annotations required: cannot resolve `T0: Trait0<'l0>`
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-24424.stderr b/src/test/ui/issues/issue-24424.stderr
new file mode 100644
index 0000000..4c6ac01
--- /dev/null
+++ b/src/test/ui/issues/issue-24424.stderr
@@ -0,0 +1,15 @@
+error[E0283]: type annotations required: cannot resolve `T0: Trait0<'l0>`
+  --> $DIR/issue-24424.rs:4:1
+   |
+LL | impl <'l0, 'l1, T0> Trait1<'l0, T0> for bool where T0 : Trait0<'l0>, T0 : Trait0<'l1> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: required by `Trait0`
+  --> $DIR/issue-24424.rs:2:1
+   |
+LL | trait Trait0<'l0>  {}
+   | ^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0283`.
diff --git a/src/test/ui/issues/issue-24434.rs b/src/test/ui/issues/issue-24434.rs
new file mode 100644
index 0000000..7b270ce
--- /dev/null
+++ b/src/test/ui/issues/issue-24434.rs
@@ -0,0 +1,8 @@
+// compile-pass
+#![allow(unused_attributes)]
+// compile-flags:--cfg set1
+
+#![cfg_attr(set1, feature(custom_attribute))]
+
+#![foobar]
+fn main() {}
diff --git a/src/test/ui/issues/issue-24446.rs b/src/test/ui/issues/issue-24446.rs
new file mode 100644
index 0000000..c5e1b49
--- /dev/null
+++ b/src/test/ui/issues/issue-24446.rs
@@ -0,0 +1,6 @@
+fn main() {
+    static foo: Fn() -> u32 = || -> u32 {
+        //~^ ERROR the size for values of type
+        0
+    };
+}
diff --git a/src/test/ui/issues/issue-24446.stderr b/src/test/ui/issues/issue-24446.stderr
new file mode 100644
index 0000000..ffec73b
--- /dev/null
+++ b/src/test/ui/issues/issue-24446.stderr
@@ -0,0 +1,12 @@
+error[E0277]: the size for values of type `(dyn std::ops::Fn() -> u32 + 'static)` cannot be known at compilation time
+  --> $DIR/issue-24446.rs:2:17
+   |
+LL |     static foo: Fn() -> u32 = || -> u32 {
+   |                 ^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `(dyn std::ops::Fn() -> u32 + 'static)`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-24682.rs b/src/test/ui/issues/issue-24682.rs
new file mode 100644
index 0000000..0d1ab73
--- /dev/null
+++ b/src/test/ui/issues/issue-24682.rs
@@ -0,0 +1,21 @@
+trait A: Sized {
+    type N;
+    fn x() ->
+        Self<
+          N= //~ ERROR associated type bindings are not allowed here
+          Self::N> {
+        loop {}
+    }
+    fn y(&self) ->
+        std
+           <N=()> //~ ERROR associated type bindings are not allowed here
+           ::option::Option<()>
+    { None }
+    fn z(&self) ->
+        u32<N=()> //~ ERROR associated type bindings are not allowed here
+    { 42 }
+
+}
+
+fn main() {
+}
diff --git a/src/test/ui/issues/issue-24682.stderr b/src/test/ui/issues/issue-24682.stderr
new file mode 100644
index 0000000..e1943bf
--- /dev/null
+++ b/src/test/ui/issues/issue-24682.stderr
@@ -0,0 +1,22 @@
+error[E0229]: associated type bindings are not allowed here
+  --> $DIR/issue-24682.rs:5:11
+   |
+LL | /           N=
+LL | |           Self::N> {
+   | |_________________^ associated type not allowed here
+
+error[E0229]: associated type bindings are not allowed here
+  --> $DIR/issue-24682.rs:11:13
+   |
+LL |            <N=()>
+   |             ^^^^ associated type not allowed here
+
+error[E0229]: associated type bindings are not allowed here
+  --> $DIR/issue-24682.rs:15:13
+   |
+LL |         u32<N=()>
+   |             ^^^^ associated type not allowed here
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0229`.
diff --git a/src/test/ui/issues/issue-24819.rs b/src/test/ui/issues/issue-24819.rs
new file mode 100644
index 0000000..1155e8d
--- /dev/null
+++ b/src/test/ui/issues/issue-24819.rs
@@ -0,0 +1,11 @@
+use std::collections::HashSet;
+
+fn main() {
+    let mut v = Vec::new();
+    foo(&mut v);
+    //~^ ERROR mismatched types
+    //~| expected struct `std::collections::HashSet`, found struct `std::vec::Vec`
+}
+
+fn foo(h: &mut HashSet<u32>) {
+}
diff --git a/src/test/ui/issues/issue-24819.stderr b/src/test/ui/issues/issue-24819.stderr
new file mode 100644
index 0000000..5f1cd0a
--- /dev/null
+++ b/src/test/ui/issues/issue-24819.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-24819.rs:5:9
+   |
+LL |     foo(&mut v);
+   |         ^^^^^^ expected struct `std::collections::HashSet`, found struct `std::vec::Vec`
+   |
+   = note: expected type `&mut std::collections::HashSet<u32>`
+              found type `&mut std::vec::Vec<_>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-2487-a.rs b/src/test/ui/issues/issue-2487-a.rs
new file mode 100644
index 0000000..36e121d
--- /dev/null
+++ b/src/test/ui/issues/issue-2487-a.rs
@@ -0,0 +1,32 @@
+// compile-pass
+#![allow(dead_code)]
+#![allow(non_camel_case_types)]
+
+// pretty-expanded FIXME #23616
+
+struct socket {
+    sock: isize,
+
+}
+
+impl Drop for socket {
+    fn drop(&mut self) {}
+}
+
+impl socket {
+    pub fn set_identity(&self)  {
+        closure(|| setsockopt_bytes(self.sock.clone()))
+    }
+}
+
+fn socket() -> socket {
+    socket {
+        sock: 1
+    }
+}
+
+fn closure<F>(f: F) where F: FnOnce() { f() }
+
+fn setsockopt_bytes(_sock: isize) { }
+
+pub fn main() {}
diff --git a/src/test/ui/issues/issue-24883.rs b/src/test/ui/issues/issue-24883.rs
new file mode 100644
index 0000000..1aa62d3
--- /dev/null
+++ b/src/test/ui/issues/issue-24883.rs
@@ -0,0 +1,18 @@
+// compile-pass
+// skip-codegen
+mod a {
+    pub mod b { pub struct Foo; }
+
+    pub mod c {
+        use super::b;
+        pub struct Bar(pub b::Foo);
+    }
+
+    pub use self::c::*;
+}
+
+
+fn main() {
+    let _ = a::c::Bar(a::b::Foo);
+    let _ = a::Bar(a::b::Foo);
+}
diff --git a/src/test/ui/issues/issue-2502.rs b/src/test/ui/issues/issue-2502.rs
new file mode 100644
index 0000000..29b68c9
--- /dev/null
+++ b/src/test/ui/issues/issue-2502.rs
@@ -0,0 +1,24 @@
+// compile-pass
+#![allow(dead_code)]
+#![allow(non_camel_case_types)]
+
+
+// pretty-expanded FIXME #23616
+
+struct font<'a> {
+    fontbuf: &'a Vec<u8> ,
+}
+
+impl<'a> font<'a> {
+    pub fn buf(&self) -> &'a Vec<u8> {
+        self.fontbuf
+    }
+}
+
+fn font(fontbuf: &Vec<u8> ) -> font {
+    font {
+        fontbuf: fontbuf
+    }
+}
+
+pub fn main() { }
diff --git a/src/test/ui/issues/issue-25076.rs b/src/test/ui/issues/issue-25076.rs
new file mode 100644
index 0000000..6c5a553
--- /dev/null
+++ b/src/test/ui/issues/issue-25076.rs
@@ -0,0 +1,11 @@
+struct S;
+
+trait InOut<T> { type Out; }
+
+fn do_fold<B, F: InOut<B, Out=B>>(init: B, f: F) {}
+
+fn bot<T>() -> T { loop {} }
+
+fn main() {
+    do_fold(bot(), ()); //~ ERROR `(): InOut<_>` is not satisfied
+}
diff --git a/src/test/ui/issues/issue-25076.stderr b/src/test/ui/issues/issue-25076.stderr
new file mode 100644
index 0000000..435ab13
--- /dev/null
+++ b/src/test/ui/issues/issue-25076.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `(): InOut<_>` is not satisfied
+  --> $DIR/issue-25076.rs:10:5
+   |
+LL |     do_fold(bot(), ());
+   |     ^^^^^^^ the trait `InOut<_>` is not implemented for `()`
+   |
+note: required by `do_fold`
+  --> $DIR/issue-25076.rs:5:1
+   |
+LL | fn do_fold<B, F: InOut<B, Out=B>>(init: B, f: F) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-25180.rs b/src/test/ui/issues/issue-25180.rs
new file mode 100644
index 0000000..739d571d
--- /dev/null
+++ b/src/test/ui/issues/issue-25180.rs
@@ -0,0 +1,7 @@
+// compile-pass
+#![allow(dead_code)]
+#![allow(non_upper_case_globals)]
+
+const x: &'static Fn() = &|| println!("ICE here");
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-25368.rs b/src/test/ui/issues/issue-25368.rs
new file mode 100644
index 0000000..8b4dbb6
--- /dev/null
+++ b/src/test/ui/issues/issue-25368.rs
@@ -0,0 +1,13 @@
+use std::sync::mpsc::channel;
+use std::thread::spawn;
+use std::marker::PhantomData;
+
+struct Foo<T> {foo: PhantomData<T>}
+
+fn main() {
+    let (tx, rx) = channel();
+
+    spawn(move || {
+        tx.send(Foo{ foo: PhantomData }); //~ ERROR E0282
+    });
+}
diff --git a/src/test/ui/issues/issue-25368.stderr b/src/test/ui/issues/issue-25368.stderr
new file mode 100644
index 0000000..3ad6a25
--- /dev/null
+++ b/src/test/ui/issues/issue-25368.stderr
@@ -0,0 +1,12 @@
+error[E0282]: type annotations needed
+  --> $DIR/issue-25368.rs:11:17
+   |
+LL |     let (tx, rx) = channel();
+   |         -------- consider giving the pattern a type
+...
+LL |         tx.send(Foo{ foo: PhantomData });
+   |                 ^^^ cannot infer type for `T`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/issues/issue-25385.rs b/src/test/ui/issues/issue-25385.rs
new file mode 100644
index 0000000..adad6c3
--- /dev/null
+++ b/src/test/ui/issues/issue-25385.rs
@@ -0,0 +1,12 @@
+macro_rules! foo {
+    ($e:expr) => { $e.foo() }
+    //~^ ERROR no method named `foo` found for type `i32` in the current scope
+}
+
+fn main() {
+    let a = 1i32;
+    foo!(a);
+
+    foo!(1i32.foo());
+    //~^ ERROR no method named `foo` found for type `i32` in the current scope
+}
diff --git a/src/test/ui/issues/issue-25385.stderr b/src/test/ui/issues/issue-25385.stderr
new file mode 100644
index 0000000..e170a9d
--- /dev/null
+++ b/src/test/ui/issues/issue-25385.stderr
@@ -0,0 +1,18 @@
+error[E0599]: no method named `foo` found for type `i32` in the current scope
+  --> $DIR/issue-25385.rs:2:23
+   |
+LL |     ($e:expr) => { $e.foo() }
+   |                       ^^^
+...
+LL |     foo!(a);
+   |     -------- in this macro invocation
+
+error[E0599]: no method named `foo` found for type `i32` in the current scope
+  --> $DIR/issue-25385.rs:10:15
+   |
+LL |     foo!(1i32.foo());
+   |               ^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/issues/issue-25386.rs b/src/test/ui/issues/issue-25386.rs
new file mode 100644
index 0000000..607c9fc
--- /dev/null
+++ b/src/test/ui/issues/issue-25386.rs
@@ -0,0 +1,28 @@
+mod stuff {
+    pub struct Item {
+        c_object: Box<CObj>,
+    }
+    pub struct CObj {
+        name: Option<String>,
+    }
+    impl Item {
+        pub fn new() -> Item {
+            Item {
+                c_object: Box::new(CObj { name: None }),
+            }
+        }
+    }
+}
+
+macro_rules! check_ptr_exist {
+    ($var:expr, $member:ident) => (
+        (*$var.c_object).$member.is_some()
+        //~^ ERROR field `name` of struct `stuff::CObj` is private
+        //~^^ ERROR field `c_object` of struct `stuff::Item` is private
+    );
+}
+
+fn main() {
+    let item = stuff::Item::new();
+    println!("{}", check_ptr_exist!(item, name));
+}
diff --git a/src/test/ui/issues/issue-25386.stderr b/src/test/ui/issues/issue-25386.stderr
new file mode 100644
index 0000000..eabb139
--- /dev/null
+++ b/src/test/ui/issues/issue-25386.stderr
@@ -0,0 +1,21 @@
+error[E0616]: field `c_object` of struct `stuff::Item` is private
+  --> $DIR/issue-25386.rs:19:11
+   |
+LL |         (*$var.c_object).$member.is_some()
+   |           ^^^^^^^^^^^^^
+...
+LL |     println!("{}", check_ptr_exist!(item, name));
+   |                    ---------------------------- in this macro invocation
+
+error[E0616]: field `name` of struct `stuff::CObj` is private
+  --> $DIR/issue-25386.rs:19:9
+   |
+LL |         (*$var.c_object).$member.is_some()
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     println!("{}", check_ptr_exist!(item, name));
+   |                    ---------------------------- in this macro invocation
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0616`.
diff --git a/src/test/ui/issues/issue-25394.rs b/src/test/ui/issues/issue-25394.rs
new file mode 100644
index 0000000..d1638aa
--- /dev/null
+++ b/src/test/ui/issues/issue-25394.rs
@@ -0,0 +1,6 @@
+// compile-pass
+#![allow(dead_code)]
+#[derive(Debug)]
+struct Row<T>([T]);
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-25396.rs b/src/test/ui/issues/issue-25396.rs
new file mode 100644
index 0000000..301658d
--- /dev/null
+++ b/src/test/ui/issues/issue-25396.rs
@@ -0,0 +1,29 @@
+#![allow(non_camel_case_types)]
+
+use foo::baz;
+use bar::baz; //~ ERROR the name `baz` is defined multiple times
+
+use foo::Quux;
+use bar::Quux; //~ ERROR the name `Quux` is defined multiple times
+
+use foo::blah;
+use bar::blah; //~ ERROR the name `blah` is defined multiple times
+
+use foo::WOMP;
+use bar::WOMP; //~ ERROR the name `WOMP` is defined multiple times
+
+fn main() {}
+
+mod foo {
+    pub mod baz {}
+    pub trait Quux { }
+    pub type blah = (f64, u32);
+    pub const WOMP: u8 = 5;
+}
+
+mod bar {
+    pub mod baz {}
+    pub type Quux = i32;
+    pub struct blah { x: i8 }
+    pub const WOMP: i8 = -5;
+}
diff --git a/src/test/ui/issues/issue-25396.stderr b/src/test/ui/issues/issue-25396.stderr
new file mode 100644
index 0000000..38dc9ef
--- /dev/null
+++ b/src/test/ui/issues/issue-25396.stderr
@@ -0,0 +1,59 @@
+error[E0252]: the name `baz` is defined multiple times
+  --> $DIR/issue-25396.rs:4:5
+   |
+LL | use foo::baz;
+   |     -------- previous import of the module `baz` here
+LL | use bar::baz;
+   |     ^^^^^^^^ `baz` reimported here
+   |
+   = note: `baz` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | use bar::baz as other_baz;
+   |     ^^^^^^^^^^^^^^^^^^^^^
+
+error[E0252]: the name `Quux` is defined multiple times
+  --> $DIR/issue-25396.rs:7:5
+   |
+LL | use foo::Quux;
+   |     --------- previous import of the trait `Quux` here
+LL | use bar::Quux;
+   |     ^^^^^^^^^ `Quux` reimported here
+   |
+   = note: `Quux` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | use bar::Quux as OtherQuux;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0252]: the name `blah` is defined multiple times
+  --> $DIR/issue-25396.rs:10:5
+   |
+LL | use foo::blah;
+   |     --------- previous import of the type `blah` here
+LL | use bar::blah;
+   |     ^^^^^^^^^ `blah` reimported here
+   |
+   = note: `blah` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | use bar::blah as other_blah;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0252]: the name `WOMP` is defined multiple times
+  --> $DIR/issue-25396.rs:13:5
+   |
+LL | use foo::WOMP;
+   |     --------- previous import of the value `WOMP` here
+LL | use bar::WOMP;
+   |     ^^^^^^^^^ `WOMP` reimported here
+   |
+   = note: `WOMP` must be defined only once in the value namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | use bar::WOMP as OtherWOMP;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0252`.
diff --git a/src/test/ui/issues/issue-25439.rs b/src/test/ui/issues/issue-25439.rs
new file mode 100644
index 0000000..4f73ff3
--- /dev/null
+++ b/src/test/ui/issues/issue-25439.rs
@@ -0,0 +1,9 @@
+struct Helper<'a, F: 'a>(&'a F);
+
+fn fix<F>(f: F) -> i32 where F: Fn(Helper<F>, i32) -> i32 {
+    f(Helper(&f), 8)
+}
+
+fn main() {
+    fix(|_, x| x); //~ ERROR closure/generator type that references itself [E0644]
+}
diff --git a/src/test/ui/issues/issue-25439.stderr b/src/test/ui/issues/issue-25439.stderr
new file mode 100644
index 0000000..9b04148
--- /dev/null
+++ b/src/test/ui/issues/issue-25439.stderr
@@ -0,0 +1,13 @@
+error[E0644]: closure/generator type that references itself
+  --> $DIR/issue-25439.rs:8:9
+   |
+LL |     fix(|_, x| x);
+   |         ^^^^^^^^ cyclic type of infinite size
+   |
+   = note: closures cannot capture themselves or take themselves as argument;
+           this error may be the result of a recent compiler bug-fix,
+           see https://github.com/rust-lang/rust/issues/46062 for more details
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0644`.
diff --git a/src/test/ui/issues/issue-25579.ast.nll.stderr b/src/test/ui/issues/issue-25579.ast.nll.stderr
new file mode 100644
index 0000000..107f88b
--- /dev/null
+++ b/src/test/ui/issues/issue-25579.ast.nll.stderr
@@ -0,0 +1,9 @@
+error: compilation successful
+  --> $DIR/issue-25579.rs:21:1
+   |
+LL | / fn main() {
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-25579.ast.stderr b/src/test/ui/issues/issue-25579.ast.stderr
new file mode 100644
index 0000000..a44cc95
--- /dev/null
+++ b/src/test/ui/issues/issue-25579.ast.stderr
@@ -0,0 +1,21 @@
+error[E0499]: cannot borrow `l.0` as mutable more than once at a time
+  --> $DIR/issue-25579.rs:14:32
+   |
+LL |         &mut Sexpression::Cons(ref mut expr) => {
+   |                                ^^^^^^^^^^^^ mutable borrow starts here in previous iteration of loop
+...
+LL | }
+   | - mutable borrow ends here
+
+error[E0506]: cannot assign to `l` because it is borrowed
+  --> $DIR/issue-25579.rs:15:13
+   |
+LL |         &mut Sexpression::Cons(ref mut expr) => {
+   |                                ------------ borrow of `l` occurs here
+LL |             l = &mut **expr;
+   |             ^^^^^^^^^^^^^^^ assignment to borrowed `l` occurs here
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0499, E0506.
+For more information about an error, try `rustc --explain E0499`.
diff --git a/src/test/ui/issues/issue-25579.mir.stderr b/src/test/ui/issues/issue-25579.mir.stderr
new file mode 100644
index 0000000..107f88b
--- /dev/null
+++ b/src/test/ui/issues/issue-25579.mir.stderr
@@ -0,0 +1,9 @@
+error: compilation successful
+  --> $DIR/issue-25579.rs:21:1
+   |
+LL | / fn main() {
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-25579.rs b/src/test/ui/issues/issue-25579.rs
new file mode 100644
index 0000000..1813253
--- /dev/null
+++ b/src/test/ui/issues/issue-25579.rs
@@ -0,0 +1,22 @@
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+#![feature(rustc_attrs)]
+
+enum Sexpression {
+    Num(()),
+    Cons(&'static mut Sexpression)
+}
+
+fn causes_error_in_ast(mut l: &mut Sexpression) {
+    loop { match l {
+        &mut Sexpression::Num(ref mut n) => {},
+        &mut Sexpression::Cons(ref mut expr) => { //[ast]~ ERROR [E0499]
+            l = &mut **expr; //[ast]~ ERROR [E0506]
+        }
+    }}
+}
+
+#[rustc_error]
+fn main() { //[mir]~ ERROR compilation successful
+}
diff --git a/src/test/ui/issues/issue-25700.nll.stderr b/src/test/ui/issues/issue-25700.nll.stderr
new file mode 100644
index 0000000..fa309a5
--- /dev/null
+++ b/src/test/ui/issues/issue-25700.nll.stderr
@@ -0,0 +1,13 @@
+error[E0382]: use of moved value: `t`
+  --> $DIR/issue-25700.rs:13:10
+   |
+LL |     let t = S::<()>(None);
+   |         - move occurs because `t` has type `S<()>`, which does not implement the `Copy` trait
+LL |     drop(t);
+   |          - value moved here
+LL |     drop(t);
+   |          ^ value used here after move
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/issues/issue-25700.rs b/src/test/ui/issues/issue-25700.rs
new file mode 100644
index 0000000..45c452d
--- /dev/null
+++ b/src/test/ui/issues/issue-25700.rs
@@ -0,0 +1,14 @@
+struct S<T: 'static>(Option<&'static T>);
+
+trait Tr { type Out; }
+impl<T> Tr for T { type Out = T; }
+
+impl<T: 'static> Copy for S<T> where S<T>: Tr<Out=T> {}
+impl<T: 'static> Clone for S<T> where S<T>: Tr<Out=T> {
+    fn clone(&self) -> Self { *self }
+}
+fn main() {
+    let t = S::<()>(None);
+    drop(t);
+    drop(t); //~ ERROR use of moved value
+}
diff --git a/src/test/ui/issues/issue-25700.stderr b/src/test/ui/issues/issue-25700.stderr
new file mode 100644
index 0000000..4a203c7
--- /dev/null
+++ b/src/test/ui/issues/issue-25700.stderr
@@ -0,0 +1,13 @@
+error[E0382]: use of moved value: `t`
+  --> $DIR/issue-25700.rs:13:10
+   |
+LL |     drop(t);
+   |          - value moved here
+LL |     drop(t);
+   |          ^ value used here after move
+   |
+   = note: move occurs because `t` has type `S<()>`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/issues/issue-25793.nll.stderr b/src/test/ui/issues/issue-25793.nll.stderr
new file mode 100644
index 0000000..daea9cd
--- /dev/null
+++ b/src/test/ui/issues/issue-25793.nll.stderr
@@ -0,0 +1,16 @@
+error[E0503]: cannot use `self.width` because it was mutably borrowed
+  --> $DIR/issue-25793.rs:4:9
+   |
+LL |         $this.width.unwrap()
+   |         ^^^^^^^^^^^ use of borrowed `*self`
+...
+LL |         let r = &mut *self;
+   |                 ---------- borrow of `*self` occurs here
+LL |         r.get_size(width!(self))
+   |           -------- ------------ in this macro invocation
+   |           |
+   |           borrow later used by call
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0503`.
diff --git a/src/test/ui/issues/issue-25793.rs b/src/test/ui/issues/issue-25793.rs
new file mode 100644
index 0000000..6c8dacc
--- /dev/null
+++ b/src/test/ui/issues/issue-25793.rs
@@ -0,0 +1,26 @@
+#![feature(rustc_attrs)]
+macro_rules! width(
+    ($this:expr) => {
+        $this.width.unwrap()
+        //~^ ERROR cannot use `self.width` because it was mutably borrowed
+    }
+);
+
+struct HasInfo {
+    width: Option<usize>
+}
+
+impl HasInfo {
+    fn get_size(&mut self, n: usize) -> usize {
+        n
+    }
+
+    fn get_other(&mut self) -> usize {
+        let r = &mut *self;
+        r.get_size(width!(self))
+    }
+    // Above is like `self.get_size(width!(self))`, but it
+    // deliberately avoids NLL's two phase borrow feature.
+}
+
+fn main() { }
diff --git a/src/test/ui/issues/issue-25793.stderr b/src/test/ui/issues/issue-25793.stderr
new file mode 100644
index 0000000..e8d208c
--- /dev/null
+++ b/src/test/ui/issues/issue-25793.stderr
@@ -0,0 +1,14 @@
+error[E0503]: cannot use `self.width` because it was mutably borrowed
+  --> $DIR/issue-25793.rs:4:9
+   |
+LL |         $this.width.unwrap()
+   |         ^^^^^^^^^^^ use of borrowed `*self`
+...
+LL |         let r = &mut *self;
+   |                      ----- borrow of `*self` occurs here
+LL |         r.get_size(width!(self))
+   |                    ------------ in this macro invocation
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0503`.
diff --git a/src/test/ui/issues/issue-25826.rs b/src/test/ui/issues/issue-25826.rs
new file mode 100644
index 0000000..36a69cf
--- /dev/null
+++ b/src/test/ui/issues/issue-25826.rs
@@ -0,0 +1,6 @@
+fn id<T>(t: T) -> T { t }
+fn main() {
+    const A: bool = unsafe { id::<u8> as *const () < id::<u16> as *const () };
+    //~^ ERROR comparing raw pointers inside constant
+    println!("{}", A);
+}
diff --git a/src/test/ui/issues/issue-25826.stderr b/src/test/ui/issues/issue-25826.stderr
new file mode 100644
index 0000000..dc547f7c
--- /dev/null
+++ b/src/test/ui/issues/issue-25826.stderr
@@ -0,0 +1,11 @@
+error[E0658]: comparing raw pointers inside constant (see issue #53020)
+  --> $DIR/issue-25826.rs:3:30
+   |
+LL |     const A: bool = unsafe { id::<u8> as *const () < id::<u16> as *const () };
+   |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_compare_raw_pointers)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/issues/issue-2590.nll.stderr b/src/test/ui/issues/issue-2590.nll.stderr
new file mode 100644
index 0000000..e19e83d
--- /dev/null
+++ b/src/test/ui/issues/issue-2590.nll.stderr
@@ -0,0 +1,9 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/issue-2590.rs:11:9
+   |
+LL |         self.tokens
+   |         ^^^^^^^^^^^ cannot move out of borrowed content
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/issues/issue-2590.rs b/src/test/ui/issues/issue-2590.rs
new file mode 100644
index 0000000..28d023d
--- /dev/null
+++ b/src/test/ui/issues/issue-2590.rs
@@ -0,0 +1,15 @@
+struct Parser {
+    tokens: Vec<isize> ,
+}
+
+trait Parse {
+    fn parse(&self) -> Vec<isize> ;
+}
+
+impl Parse for Parser {
+    fn parse(&self) -> Vec<isize> {
+        self.tokens //~ ERROR cannot move out of borrowed content
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-2590.stderr b/src/test/ui/issues/issue-2590.stderr
new file mode 100644
index 0000000..c50652d
--- /dev/null
+++ b/src/test/ui/issues/issue-2590.stderr
@@ -0,0 +1,9 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/issue-2590.rs:11:9
+   |
+LL |         self.tokens
+   |         ^^^^ cannot move out of borrowed content
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/issues/issue-25901.rs b/src/test/ui/issues/issue-25901.rs
new file mode 100644
index 0000000..a139ad0
--- /dev/null
+++ b/src/test/ui/issues/issue-25901.rs
@@ -0,0 +1,14 @@
+struct A;
+struct B;
+
+static S: &'static B = &A;
+//~^ ERROR calls in statics are limited to constant functions
+
+use std::ops::Deref;
+
+impl Deref for A {
+    type Target = B;
+    fn deref(&self)->&B { static B_: B = B; &B_ }
+}
+
+fn main(){}
diff --git a/src/test/ui/issues/issue-25901.stderr b/src/test/ui/issues/issue-25901.stderr
new file mode 100644
index 0000000..d6eb3760
--- /dev/null
+++ b/src/test/ui/issues/issue-25901.stderr
@@ -0,0 +1,9 @@
+error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
+  --> $DIR/issue-25901.rs:4:24
+   |
+LL | static S: &'static B = &A;
+   |                        ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0015`.
diff --git a/src/test/ui/issues/issue-26056.rs b/src/test/ui/issues/issue-26056.rs
new file mode 100644
index 0000000..0d9973b
--- /dev/null
+++ b/src/test/ui/issues/issue-26056.rs
@@ -0,0 +1,22 @@
+trait MapLookup<Q> {
+    type MapValue;
+}
+
+impl<K> MapLookup<K> for K {
+    type MapValue = K;
+}
+
+trait Map: MapLookup<<Self as Map>::Key> {
+    type Key;
+}
+
+impl<K> Map for K {
+    type Key = K;
+}
+
+
+fn main() {
+    let _ = &()
+        as &Map<Key=u32,MapValue=u32>;
+    //~^ ERROR E0038
+}
diff --git a/src/test/ui/issues/issue-26056.stderr b/src/test/ui/issues/issue-26056.stderr
new file mode 100644
index 0000000..44fabd0
--- /dev/null
+++ b/src/test/ui/issues/issue-26056.stderr
@@ -0,0 +1,11 @@
+error[E0038]: the trait `Map` cannot be made into an object
+  --> $DIR/issue-26056.rs:20:13
+   |
+LL |         as &Map<Key=u32,MapValue=u32>;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Map` cannot be made into an object
+   |
+   = note: the trait cannot use `Self` as a type parameter in the supertraits or where-clauses
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/issues/issue-26093.rs b/src/test/ui/issues/issue-26093.rs
new file mode 100644
index 0000000..7895c90
--- /dev/null
+++ b/src/test/ui/issues/issue-26093.rs
@@ -0,0 +1,10 @@
+macro_rules! not_a_place {
+    ($thing:expr) => {
+        $thing = 42;
+        //~^ ERROR invalid left-hand side expression
+    }
+}
+
+fn main() {
+    not_a_place!(99);
+}
diff --git a/src/test/ui/issues/issue-26093.stderr b/src/test/ui/issues/issue-26093.stderr
new file mode 100644
index 0000000..947c52f
--- /dev/null
+++ b/src/test/ui/issues/issue-26093.stderr
@@ -0,0 +1,12 @@
+error[E0070]: invalid left-hand side expression
+  --> $DIR/issue-26093.rs:3:9
+   |
+LL |         $thing = 42;
+   |         ^^^^^^^^^^^ left-hand of expression not valid
+...
+LL |     not_a_place!(99);
+   |     ----------------- in this macro invocation
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0070`.
diff --git a/src/test/ui/issues/issue-26094.rs b/src/test/ui/issues/issue-26094.rs
new file mode 100644
index 0000000..b943384
--- /dev/null
+++ b/src/test/ui/issues/issue-26094.rs
@@ -0,0 +1,13 @@
+macro_rules! some_macro {
+    ($other: expr) => ({
+        $other(None)
+        //~^ this function takes 0 parameters but 1 parameter was supplied
+    })
+}
+
+fn some_function() {}
+
+fn main() {
+    some_macro!(some_function);
+    //~^ in this expansion of some_macro!
+}
diff --git a/src/test/ui/issues/issue-26094.stderr b/src/test/ui/issues/issue-26094.stderr
new file mode 100644
index 0000000..36b2d3d
--- /dev/null
+++ b/src/test/ui/issues/issue-26094.stderr
@@ -0,0 +1,15 @@
+error[E0061]: this function takes 0 parameters but 1 parameter was supplied
+  --> $DIR/issue-26094.rs:3:9
+   |
+LL |         $other(None)
+   |         ^^^^^^^^^^^^ expected 0 parameters
+...
+LL | fn some_function() {}
+   | ------------------ defined here
+...
+LL |     some_macro!(some_function);
+   |     --------------------------- in this macro invocation
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0061`.
diff --git a/src/test/ui/issues/issue-26095.rs b/src/test/ui/issues/issue-26095.rs
new file mode 100644
index 0000000..707cf1d
--- /dev/null
+++ b/src/test/ui/issues/issue-26095.rs
@@ -0,0 +1,23 @@
+// compile-pass
+#![allow(dead_code)]
+#![allow(non_upper_case_globals)]
+
+
+trait HasNumber<T> {
+    const Number: usize;
+}
+
+enum One {}
+enum Two {}
+
+enum Foo {}
+
+impl<T> HasNumber<T> for One {
+    const Number: usize = 1;
+}
+
+impl<T> HasNumber<T> for Two {
+    const Number: usize = 2;
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-2611-3.rs b/src/test/ui/issues/issue-2611-3.rs
new file mode 100644
index 0000000..5d4b656
--- /dev/null
+++ b/src/test/ui/issues/issue-2611-3.rs
@@ -0,0 +1,19 @@
+// compile-pass
+#![allow(dead_code)]
+// Tests that impls are allowed to have looser, more permissive bounds
+// than the traits require.
+
+
+trait A {
+  fn b<C:Sync,D>(&self, x: C) -> C;
+}
+
+struct E {
+ f: isize
+}
+
+impl A for E {
+  fn b<F,G>(&self, _x: F) -> F { panic!() }
+}
+
+pub fn main() {}
diff --git a/src/test/ui/issues/issue-26158.rs b/src/test/ui/issues/issue-26158.rs
new file mode 100644
index 0000000..11f47b6
--- /dev/null
+++ b/src/test/ui/issues/issue-26158.rs
@@ -0,0 +1,6 @@
+#![feature(slice_patterns)]
+
+fn main() {
+    let x: &[u32] = &[];
+    let &[[ref _a, ref _b..]..] = x; //~ ERROR refutable pattern
+}
diff --git a/src/test/ui/issues/issue-26158.stderr b/src/test/ui/issues/issue-26158.stderr
new file mode 100644
index 0000000..3a4dd79
--- /dev/null
+++ b/src/test/ui/issues/issue-26158.stderr
@@ -0,0 +1,9 @@
+error[E0005]: refutable pattern in local binding: `&[]` not covered
+  --> $DIR/issue-26158.rs:5:9
+   |
+LL |     let &[[ref _a, ref _b..]..] = x;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^ pattern `&[]` not covered
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0005`.
diff --git a/src/test/ui/issues/issue-26205.rs b/src/test/ui/issues/issue-26205.rs
new file mode 100644
index 0000000..01b7165
--- /dev/null
+++ b/src/test/ui/issues/issue-26205.rs
@@ -0,0 +1,31 @@
+// compile-pass
+#![allow(dead_code)]
+use std::ops::{Deref, DerefMut};
+
+struct Foo;
+
+impl Foo {
+    fn foo_mut(&mut self) {}
+}
+
+struct Bar(Foo);
+
+impl Deref for Bar {
+    type Target = Foo;
+
+    fn deref(&self) -> &Foo {
+        &self.0
+    }
+}
+
+impl DerefMut for Bar {
+    fn deref_mut(&mut self) -> &mut Foo {
+        &mut self.0
+    }
+}
+
+fn test(mut bar: Box<Bar>) {
+    bar.foo_mut();
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-26217.rs b/src/test/ui/issues/issue-26217.rs
new file mode 100644
index 0000000..05e0462
--- /dev/null
+++ b/src/test/ui/issues/issue-26217.rs
@@ -0,0 +1,10 @@
+fn foo<T>() where for<'a> T: 'a {}
+
+fn bar<'a>() {
+    foo::<&'a i32>();
+    //~^ ERROR the type `&'a i32` does not fulfill the required lifetime
+}
+
+fn main() {
+    bar();
+}
diff --git a/src/test/ui/issues/issue-26217.stderr b/src/test/ui/issues/issue-26217.stderr
new file mode 100644
index 0000000..be9da56
--- /dev/null
+++ b/src/test/ui/issues/issue-26217.stderr
@@ -0,0 +1,11 @@
+error[E0477]: the type `&'a i32` does not fulfill the required lifetime
+  --> $DIR/issue-26217.rs:4:5
+   |
+LL |     foo::<&'a i32>();
+   |     ^^^^^^^^^^^^^^
+   |
+   = note: type must satisfy the static lifetime
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0477`.
diff --git a/src/test/ui/issues/issue-26237.rs b/src/test/ui/issues/issue-26237.rs
new file mode 100644
index 0000000..71e9667
--- /dev/null
+++ b/src/test/ui/issues/issue-26237.rs
@@ -0,0 +1,12 @@
+macro_rules! macro_panic {
+    ($not_a_function:expr, $some_argument:ident) => {
+        $not_a_function($some_argument)
+    }
+}
+
+fn main() {
+    let mut value_a = 0;
+    let mut value_b = 0;
+    macro_panic!(value_a, value_b);
+    //~^ ERROR expected function, found `{integer}`
+}
diff --git a/src/test/ui/issues/issue-26237.stderr b/src/test/ui/issues/issue-26237.stderr
new file mode 100644
index 0000000..f58c1bf
--- /dev/null
+++ b/src/test/ui/issues/issue-26237.stderr
@@ -0,0 +1,15 @@
+error[E0618]: expected function, found `{integer}`
+  --> $DIR/issue-26237.rs:10:18
+   |
+LL |         $not_a_function($some_argument)
+   |         ------------------------------- call expression requires function
+...
+LL |     let mut value_a = 0;
+   |         ----------- `{integer}` defined here
+LL |     let mut value_b = 0;
+LL |     macro_panic!(value_a, value_b);
+   |                  ^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0618`.
diff --git a/src/test/ui/issues/issue-26262.rs b/src/test/ui/issues/issue-26262.rs
new file mode 100644
index 0000000..41135db
--- /dev/null
+++ b/src/test/ui/issues/issue-26262.rs
@@ -0,0 +1,22 @@
+// Check that projections don't count as constraining type parameters.
+
+struct S<T>(T);
+
+trait Tr { type Assoc; fn test(); }
+
+impl<T: Tr> S<T::Assoc> {
+//~^ ERROR the type parameter `T` is not constrained
+    fn foo(self, _: T) {
+        T::test();
+    }
+}
+
+trait Trait1<T> { type Bar; }
+trait Trait2<'x> { type Foo; }
+
+impl<'a,T: Trait2<'a>> Trait1<<T as Trait2<'a>>::Foo> for T {
+//~^ ERROR the lifetime parameter `'a` is not constrained
+    type Bar = &'a ();
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-26262.stderr b/src/test/ui/issues/issue-26262.stderr
new file mode 100644
index 0000000..90e2d0d
--- /dev/null
+++ b/src/test/ui/issues/issue-26262.stderr
@@ -0,0 +1,15 @@
+error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates
+  --> $DIR/issue-26262.rs:7:6
+   |
+LL | impl<T: Tr> S<T::Assoc> {
+   |      ^ unconstrained type parameter
+
+error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates
+  --> $DIR/issue-26262.rs:17:6
+   |
+LL | impl<'a,T: Trait2<'a>> Trait1<<T as Trait2<'a>>::Foo> for T {
+   |      ^^ unconstrained lifetime parameter
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0207`.
diff --git a/src/test/ui/issues/issue-26448-1.rs b/src/test/ui/issues/issue-26448-1.rs
new file mode 100644
index 0000000..7d2d75b
--- /dev/null
+++ b/src/test/ui/issues/issue-26448-1.rs
@@ -0,0 +1,13 @@
+// run-pass
+
+pub trait Foo<T> {
+    fn foo(self) -> T;
+}
+
+impl<'a, T> Foo<T> for &'a str where &'a str: Into<T> {
+    fn foo(self) -> T {
+        panic!();
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-26448-2.rs b/src/test/ui/issues/issue-26448-2.rs
new file mode 100644
index 0000000..17e7c1f
--- /dev/null
+++ b/src/test/ui/issues/issue-26448-2.rs
@@ -0,0 +1,21 @@
+// run-pass
+
+pub struct Bar<T> {
+    items: Vec<&'static str>,
+    inner: T,
+}
+
+pub trait IntoBar<T> {
+    fn into_bar(self) -> Bar<T>;
+}
+
+impl<'a, T> IntoBar<T> for &'a str where &'a str: Into<T> {
+    fn into_bar(self) -> Bar<T> {
+        Bar {
+            items: Vec::new(),
+            inner: self.into(),
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-26448-3.rs b/src/test/ui/issues/issue-26448-3.rs
new file mode 100644
index 0000000..e57352e
--- /dev/null
+++ b/src/test/ui/issues/issue-26448-3.rs
@@ -0,0 +1,25 @@
+// run-pass
+
+pub struct Item {
+    _inner: &'static str,
+}
+
+pub struct Bar<T> {
+    items: Vec<Item>,
+    inner: T,
+}
+
+pub trait IntoBar<T> {
+    fn into_bar(self) -> Bar<T>;
+}
+
+impl<'a, T> IntoBar<T> for &'a str where &'a str: Into<T> {
+    fn into_bar(self) -> Bar<T> {
+        Bar {
+            items: Vec::new(),
+            inner: self.into(),
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-26459.rs b/src/test/ui/issues/issue-26459.rs
new file mode 100644
index 0000000..79791e0
--- /dev/null
+++ b/src/test/ui/issues/issue-26459.rs
@@ -0,0 +1,6 @@
+fn main() {
+    match 'a' {
+        char{ch} => true
+        //~^ ERROR expected struct, variant or union type, found builtin type `char`
+    };
+}
diff --git a/src/test/ui/issues/issue-26459.stderr b/src/test/ui/issues/issue-26459.stderr
new file mode 100644
index 0000000..1873692
--- /dev/null
+++ b/src/test/ui/issues/issue-26459.stderr
@@ -0,0 +1,9 @@
+error[E0574]: expected struct, variant or union type, found builtin type `char`
+  --> $DIR/issue-26459.rs:3:9
+   |
+LL |         char{ch} => true
+   |         ^^^^ not a struct, variant or union type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0574`.
diff --git a/src/test/ui/issues/issue-26472.rs b/src/test/ui/issues/issue-26472.rs
new file mode 100644
index 0000000..4eb38d1
--- /dev/null
+++ b/src/test/ui/issues/issue-26472.rs
@@ -0,0 +1,13 @@
+mod sub {
+    pub struct S { len: usize }
+    impl S {
+        pub fn new() -> S { S { len: 0 } }
+        pub fn len(&self) -> usize { self.len }
+    }
+}
+
+fn main() {
+    let s = sub::S::new();
+    let v = s.len; //~ ERROR field `len` of struct `sub::S` is private
+    s.len = v; //~ ERROR field `len` of struct `sub::S` is private
+}
diff --git a/src/test/ui/issues/issue-26472.stderr b/src/test/ui/issues/issue-26472.stderr
new file mode 100644
index 0000000..245ebea
--- /dev/null
+++ b/src/test/ui/issues/issue-26472.stderr
@@ -0,0 +1,17 @@
+error[E0616]: field `len` of struct `sub::S` is private
+  --> $DIR/issue-26472.rs:11:13
+   |
+LL |     let v = s.len;
+   |             ^^---
+   |               |
+   |               help: a method `len` also exists, call it with parentheses: `len()`
+
+error[E0616]: field `len` of struct `sub::S` is private
+  --> $DIR/issue-26472.rs:12:5
+   |
+LL |     s.len = v;
+   |     ^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0616`.
diff --git a/src/test/ui/issues/issue-26548.rs b/src/test/ui/issues/issue-26548.rs
new file mode 100644
index 0000000..5b6c77d
--- /dev/null
+++ b/src/test/ui/issues/issue-26548.rs
@@ -0,0 +1,11 @@
+//~ ERROR cycle detected when computing layout of
+//~| NOTE ...which requires computing layout of
+//~| NOTE ...which again requires computing layout of
+
+trait Mirror { type It: ?Sized; }
+impl<T: ?Sized> Mirror for T { type It = Self; }
+struct S(Option<<S as Mirror>::It>);
+
+fn main() { //~ NOTE cycle used when processing `main`
+    let _s = S(None);
+}
diff --git a/src/test/ui/issues/issue-26548.stderr b/src/test/ui/issues/issue-26548.stderr
new file mode 100644
index 0000000..7c1789c
--- /dev/null
+++ b/src/test/ui/issues/issue-26548.stderr
@@ -0,0 +1,13 @@
+error[E0391]: cycle detected when computing layout of `std::option::Option<S>`
+   |
+   = note: ...which requires computing layout of `S`...
+   = note: ...which again requires computing layout of `std::option::Option<S>`, completing the cycle
+note: cycle used when processing `main`
+  --> $DIR/issue-26548.rs:9:1
+   |
+LL | fn main() {
+   | ^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/issues/issue-26614.rs b/src/test/ui/issues/issue-26614.rs
new file mode 100644
index 0000000..11c2202
--- /dev/null
+++ b/src/test/ui/issues/issue-26614.rs
@@ -0,0 +1,17 @@
+// compile-pass
+// skip-codegen
+#![allow(warnings)]
+trait Mirror {
+    type It;
+}
+
+impl<T> Mirror for T {
+    type It = Self;
+}
+
+
+
+fn main() {
+    let c: <u32 as Mirror>::It = 5;
+    const CCCC: <u32 as Mirror>::It = 5;
+}
diff --git a/src/test/ui/issues/issue-26619.nll.stderr b/src/test/ui/issues/issue-26619.nll.stderr
new file mode 100644
index 0000000..d1157cd
--- /dev/null
+++ b/src/test/ui/issues/issue-26619.nll.stderr
@@ -0,0 +1,11 @@
+error[E0515]: cannot return value referencing function parameter
+  --> $DIR/issue-26619.rs:7:76
+   |
+LL |         for s in vec!["1|2".to_string()].into_iter().filter_map(|ref line| self.make_entry(line)) {
+   |                                                                  --------  ^^^^^^^^^^^^^^^^^^^^^ returns a value referencing data owned by the current function
+   |                                                                  |
+   |                                                                  function parameter borrowed here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/src/test/ui/issues/issue-26619.rs b/src/test/ui/issues/issue-26619.rs
new file mode 100644
index 0000000..cd89c67
--- /dev/null
+++ b/src/test/ui/issues/issue-26619.rs
@@ -0,0 +1,24 @@
+#![feature(slice_patterns)]
+
+pub struct History<'a> { pub _s: &'a str }
+
+impl<'a> History<'a> {
+    pub fn get_page(&self) {
+        for s in vec!["1|2".to_string()].into_iter().filter_map(|ref line| self.make_entry(line)) {
+            //~^ ERROR borrowed value does not live long enough
+            println!("{:?}", s);
+        }
+    }
+
+    fn make_entry(&self, s: &'a String) -> Option<&str> {
+        let parts: Vec<_> = s.split('|').collect();
+        println!("{:?} -> {:?}", s, parts);
+
+        if let [commit, ..] = &parts[..] { Some(commit) } else { None }
+    }
+}
+
+fn main() {
+    let h = History{ _s: "" };
+    h.get_page();
+}
diff --git a/src/test/ui/issues/issue-26619.stderr b/src/test/ui/issues/issue-26619.stderr
new file mode 100644
index 0000000..3ac6c4e
--- /dev/null
+++ b/src/test/ui/issues/issue-26619.stderr
@@ -0,0 +1,12 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/issue-26619.rs:7:66
+   |
+LL |         for s in vec!["1|2".to_string()].into_iter().filter_map(|ref line| self.make_entry(line)) {
+   |                                                                  ^^^^^^^^                      -- temporary value needs to live until here
+   |                                                                  |                             |
+   |                                                                  |                             temporary value dropped here while still borrowed
+   |                                                                  temporary value does not live long enough
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/issues/issue-26638.rs b/src/test/ui/issues/issue-26638.rs
new file mode 100644
index 0000000..0f5ed5c
--- /dev/null
+++ b/src/test/ui/issues/issue-26638.rs
@@ -0,0 +1,10 @@
+fn parse_type(iter: Box<Iterator<Item=&str>+'static>) -> &str { iter.next() }
+//~^ ERROR missing lifetime specifier [E0106]
+
+fn parse_type_2(iter: fn(&u8)->&u8) -> &str { iter() }
+//~^ ERROR missing lifetime specifier [E0106]
+
+fn parse_type_3() -> &str { unimplemented!() }
+//~^ ERROR missing lifetime specifier [E0106]
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-26638.stderr b/src/test/ui/issues/issue-26638.stderr
new file mode 100644
index 0000000..64c2cd4
--- /dev/null
+++ b/src/test/ui/issues/issue-26638.stderr
@@ -0,0 +1,27 @@
+error[E0106]: missing lifetime specifier
+  --> $DIR/issue-26638.rs:1:58
+   |
+LL | fn parse_type(iter: Box<Iterator<Item=&str>+'static>) -> &str { iter.next() }
+   |                                                          ^ expected lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but the signature does not say which one of `iter`'s 2 lifetimes it is borrowed from
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/issue-26638.rs:4:40
+   |
+LL | fn parse_type_2(iter: fn(&u8)->&u8) -> &str { iter() }
+   |                                        ^ help: consider giving it an explicit bounded or 'static lifetime: `&'static`
+   |
+   = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/issue-26638.rs:7:22
+   |
+LL | fn parse_type_3() -> &str { unimplemented!() }
+   |                      ^ help: consider giving it a 'static lifetime: `&'static`
+   |
+   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0106`.
diff --git a/src/test/ui/issues/issue-26646.rs b/src/test/ui/issues/issue-26646.rs
new file mode 100644
index 0000000..6aa5e03
--- /dev/null
+++ b/src/test/ui/issues/issue-26646.rs
@@ -0,0 +1,12 @@
+// compile-pass
+#![deny(unused_attributes)]
+
+#[repr(C)]
+#[repr(packed)]
+pub struct Foo;
+
+#[repr(packed)]
+#[repr(C)]
+pub struct Bar;
+
+fn main() { }
diff --git a/src/test/ui/issues/issue-26812.rs b/src/test/ui/issues/issue-26812.rs
new file mode 100644
index 0000000..b2494a9
--- /dev/null
+++ b/src/test/ui/issues/issue-26812.rs
@@ -0,0 +1,6 @@
+#![feature(default_type_parameter_fallback)]
+
+fn avg<T=T::Item>(_: T) {}
+//~^ ERROR type parameters with a default cannot use forward declared identifiers
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-26812.stderr b/src/test/ui/issues/issue-26812.stderr
new file mode 100644
index 0000000..8d507a7
--- /dev/null
+++ b/src/test/ui/issues/issue-26812.stderr
@@ -0,0 +1,9 @@
+error[E0128]: type parameters with a default cannot use forward declared identifiers
+  --> $DIR/issue-26812.rs:3:10
+   |
+LL | fn avg<T=T::Item>(_: T) {}
+   |          ^^^^^^^ defaulted type parameters cannot be forward declared
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0128`.
diff --git a/src/test/ui/issues/issue-26886.rs b/src/test/ui/issues/issue-26886.rs
new file mode 100644
index 0000000..6e6d406
--- /dev/null
+++ b/src/test/ui/issues/issue-26886.rs
@@ -0,0 +1,8 @@
+use std::sync::{self, Arc};
+use std::sync::Arc; //~ ERROR the name `Arc` is defined multiple times
+                    //~| `Arc` must be defined only once in the type namespace of this module
+use std::sync; //~ ERROR the name `sync` is defined multiple times
+               //~| `sync` must be defined only once in the type namespace of this module
+
+fn main() {
+}
diff --git a/src/test/ui/issues/issue-26886.stderr b/src/test/ui/issues/issue-26886.stderr
new file mode 100644
index 0000000..e2b925e
--- /dev/null
+++ b/src/test/ui/issues/issue-26886.stderr
@@ -0,0 +1,24 @@
+error[E0252]: the name `Arc` is defined multiple times
+  --> $DIR/issue-26886.rs:2:5
+   |
+LL | use std::sync::{self, Arc};
+   |                       --- previous import of the type `Arc` here
+LL | use std::sync::Arc;
+   |     ^^^^^^^^^^^^^^ `Arc` reimported here
+   |
+   = note: `Arc` must be defined only once in the type namespace of this module
+
+error[E0252]: the name `sync` is defined multiple times
+  --> $DIR/issue-26886.rs:4:5
+   |
+LL | use std::sync::{self, Arc};
+   |                 ---- previous import of the module `sync` here
+...
+LL | use std::sync;
+   |     ^^^^^^^^^ `sync` reimported here
+   |
+   = note: `sync` must be defined only once in the type namespace of this module
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0252`.
diff --git a/src/test/ui/issues/issue-26905.rs b/src/test/ui/issues/issue-26905.rs
new file mode 100644
index 0000000..0cd166f
--- /dev/null
+++ b/src/test/ui/issues/issue-26905.rs
@@ -0,0 +1,24 @@
+#![feature(unsize, coerce_unsized)]
+
+// Verfies that non-PhantomData ZSTs still cause coercions to fail.
+// They might have additional semantics that we don't want to bulldoze.
+
+use std::marker::{Unsize, PhantomData};
+use std::ops::CoerceUnsized;
+
+struct NotPhantomData<T: ?Sized>(PhantomData<T>);
+
+struct MyRc<T: ?Sized> {
+    _ptr: *const T,
+    _boo: NotPhantomData<T>,
+}
+
+impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<MyRc<U>> for MyRc<T>{ } //~ERROR
+
+fn main() {
+    let data = [1, 2, 3];
+    let iter = data.iter();
+    let x = MyRc { _ptr: &iter, _boo: NotPhantomData(PhantomData) };
+    let _y: MyRc<Iterator<Item=&u32>> = x;
+}
+
diff --git a/src/test/ui/issues/issue-26905.stderr b/src/test/ui/issues/issue-26905.stderr
new file mode 100644
index 0000000..10dbb73
--- /dev/null
+++ b/src/test/ui/issues/issue-26905.stderr
@@ -0,0 +1,12 @@
+error[E0375]: implementing the trait `CoerceUnsized` requires multiple coercions
+  --> $DIR/issue-26905.rs:16:40
+   |
+LL | impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<MyRc<U>> for MyRc<T>{ }
+   |                                        ^^^^^^^^^^^^^^^^^^^^^^ requires multiple coercions
+   |
+   = note: `CoerceUnsized` may only be implemented for a coercion between structures with one field being coerced
+   = note: currently, 2 fields need coercions: `_ptr` (`*const T` to `*const U`), `_boo` (`NotPhantomData<T>` to `NotPhantomData<U>`)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0375`.
diff --git a/src/test/ui/issues/issue-26930.rs b/src/test/ui/issues/issue-26930.rs
new file mode 100644
index 0000000..abf6b93
--- /dev/null
+++ b/src/test/ui/issues/issue-26930.rs
@@ -0,0 +1,10 @@
+// compile-pass
+// skip-codegen
+#![allow(unused)]
+extern crate core;
+use core as core_export;
+use self::x::*;
+mod x {}
+
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-26948.rs b/src/test/ui/issues/issue-26948.rs
new file mode 100644
index 0000000..832c964
--- /dev/null
+++ b/src/test/ui/issues/issue-26948.rs
@@ -0,0 +1,6 @@
+fn main() {
+    enum Foo { A { x: u32 } }
+    let orig = Foo::A { x: 5 };
+    Foo::A { x: 6, ..orig };
+    //~^ ERROR functional record update syntax requires a struct
+}
diff --git a/src/test/ui/issues/issue-26948.stderr b/src/test/ui/issues/issue-26948.stderr
new file mode 100644
index 0000000..faede16
--- /dev/null
+++ b/src/test/ui/issues/issue-26948.stderr
@@ -0,0 +1,9 @@
+error[E0436]: functional record update syntax requires a struct
+  --> $DIR/issue-26948.rs:4:22
+   |
+LL |     Foo::A { x: 6, ..orig };
+   |                      ^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0436`.
diff --git a/src/test/ui/issues/issue-26997.rs b/src/test/ui/issues/issue-26997.rs
new file mode 100644
index 0000000..dd48440
--- /dev/null
+++ b/src/test/ui/issues/issue-26997.rs
@@ -0,0 +1,14 @@
+// compile-pass
+#![allow(dead_code)]
+pub struct Foo {
+    x: isize,
+    y: isize
+}
+
+impl Foo {
+    pub extern fn foo_new() -> Foo {
+        Foo { x: 21, y: 33 }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-27008.rs b/src/test/ui/issues/issue-27008.rs
new file mode 100644
index 0000000..b37ea6f
--- /dev/null
+++ b/src/test/ui/issues/issue-27008.rs
@@ -0,0 +1,9 @@
+struct S;
+
+fn main() {
+    let b = [0; S];
+    //~^ ERROR mismatched types
+    //~| expected type `usize`
+    //~| found type `S`
+    //~| expected usize, found struct `S`
+}
diff --git a/src/test/ui/issues/issue-27008.stderr b/src/test/ui/issues/issue-27008.stderr
new file mode 100644
index 0000000..c45d757
--- /dev/null
+++ b/src/test/ui/issues/issue-27008.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-27008.rs:4:17
+   |
+LL |     let b = [0; S];
+   |                 ^ expected usize, found struct `S`
+   |
+   = note: expected type `usize`
+              found type `S`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-27033.rs b/src/test/ui/issues/issue-27033.rs
new file mode 100644
index 0000000..a23819a
--- /dev/null
+++ b/src/test/ui/issues/issue-27033.rs
@@ -0,0 +1,12 @@
+fn main() {
+    match Some(1) {
+        None @ _ => {} //~ ERROR match bindings cannot shadow unit variants
+    };
+    const C: u8 = 1;
+    match 1 {
+        C @ 2 => { //~ ERROR match bindings cannot shadow constant
+            println!("{}", C);
+        }
+        _ => {}
+    };
+}
diff --git a/src/test/ui/issues/issue-27033.stderr b/src/test/ui/issues/issue-27033.stderr
new file mode 100644
index 0000000..ab95433
--- /dev/null
+++ b/src/test/ui/issues/issue-27033.stderr
@@ -0,0 +1,18 @@
+error[E0530]: match bindings cannot shadow unit variants
+  --> $DIR/issue-27033.rs:3:9
+   |
+LL |         None @ _ => {}
+   |         ^^^^ cannot be named the same as a unit variant
+
+error[E0530]: match bindings cannot shadow constants
+  --> $DIR/issue-27033.rs:7:9
+   |
+LL |     const C: u8 = 1;
+   |     ---------------- the constant `C` is defined here
+LL |     match 1 {
+LL |         C @ 2 => {
+   |         ^ cannot be named the same as a constant
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0530`.
diff --git a/src/test/ui/issues/issue-27042.rs b/src/test/ui/issues/issue-27042.rs
new file mode 100644
index 0000000..8c77585
--- /dev/null
+++ b/src/test/ui/issues/issue-27042.rs
@@ -0,0 +1,16 @@
+// Regression test for #27042. Test that a loop's label is included in its span.
+
+fn main() {
+    let _: i32 =
+        'a: // in this case, the citation is just the `break`:
+        loop { break }; //~ ERROR mismatched types
+    let _: i32 =
+        'b: //~ ERROR mismatched types
+        while true { break }; // but here we cite the whole loop
+    let _: i32 =
+        'c: //~ ERROR mismatched types
+        for _ in None { break }; // but here we cite the whole loop
+    let _: i32 =
+        'd: //~ ERROR mismatched types
+        while let Some(_) = None { break };
+}
diff --git a/src/test/ui/issues/issue-27042.stderr b/src/test/ui/issues/issue-27042.stderr
new file mode 100644
index 0000000..cce7d24
--- /dev/null
+++ b/src/test/ui/issues/issue-27042.stderr
@@ -0,0 +1,42 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-27042.rs:6:16
+   |
+LL |         loop { break };
+   |                ^^^^^ expected (), found i32
+   |
+   = note: expected type `()`
+              found type `i32`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-27042.rs:8:9
+   |
+LL | /         'b:
+LL | |         while true { break }; // but here we cite the whole loop
+   | |____________________________^ expected i32, found ()
+   |
+   = note: expected type `i32`
+              found type `()`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-27042.rs:11:9
+   |
+LL | /         'c:
+LL | |         for _ in None { break }; // but here we cite the whole loop
+   | |_______________________________^ expected i32, found ()
+   |
+   = note: expected type `i32`
+              found type `()`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-27042.rs:14:9
+   |
+LL | /         'd:
+LL | |         while let Some(_) = None { break };
+   | |__________________________________________^ expected i32, found ()
+   |
+   = note: expected type `i32`
+              found type `()`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-27060-2.rs b/src/test/ui/issues/issue-27060-2.rs
new file mode 100644
index 0000000..a001ce1
--- /dev/null
+++ b/src/test/ui/issues/issue-27060-2.rs
@@ -0,0 +1,6 @@
+#[repr(packed)]
+pub struct Bad<T: ?Sized> {
+    data: T, //~ ERROR the size for values of type
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-27060-2.stderr b/src/test/ui/issues/issue-27060-2.stderr
new file mode 100644
index 0000000..f7227c3
--- /dev/null
+++ b/src/test/ui/issues/issue-27060-2.stderr
@@ -0,0 +1,14 @@
+error[E0277]: the size for values of type `T` cannot be known at compilation time
+  --> $DIR/issue-27060-2.rs:3:5
+   |
+LL |     data: T,
+   |     ^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `T`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = help: consider adding a `where T: std::marker::Sized` bound
+   = note: the last field of a packed struct may only have a dynamically sized type if it does not need drop to be run
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-27060.rs b/src/test/ui/issues/issue-27060.rs
new file mode 100644
index 0000000..4caad03
--- /dev/null
+++ b/src/test/ui/issues/issue-27060.rs
@@ -0,0 +1,33 @@
+#[repr(packed)]
+pub struct Good {
+    data: &'static u32,
+    data2: [&'static u32; 2],
+    aligned: [u8; 32],
+}
+
+#[repr(packed)]
+pub struct JustArray {
+    array: [u32]
+}
+
+#[deny(safe_packed_borrows)]
+fn main() {
+    let good = Good {
+        data: &0,
+        data2: [&0, &0],
+        aligned: [0; 32]
+    };
+
+    unsafe {
+        let _ = &good.data; // ok
+        let _ = &good.data2[0]; // ok
+    }
+
+    let _ = &good.data; //~ ERROR borrow of packed field is unsafe
+                        //~| hard error
+    let _ = &good.data2[0]; //~ ERROR borrow of packed field is unsafe
+                            //~| hard error
+    let _ = &*good.data; // ok, behind a pointer
+    let _ = &good.aligned; // ok, has align 1
+    let _ = &good.aligned[2]; // ok, has align 1
+}
diff --git a/src/test/ui/issues/issue-27060.stderr b/src/test/ui/issues/issue-27060.stderr
new file mode 100644
index 0000000..bc44c1a
--- /dev/null
+++ b/src/test/ui/issues/issue-27060.stderr
@@ -0,0 +1,27 @@
+error: borrow of packed field is unsafe and requires unsafe function or block (error E0133)
+  --> $DIR/issue-27060.rs:26:13
+   |
+LL |     let _ = &good.data;
+   |             ^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/issue-27060.rs:13:8
+   |
+LL | #[deny(safe_packed_borrows)]
+   |        ^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #46043 <https://github.com/rust-lang/rust/issues/46043>
+   = note: fields of packed structs might be misaligned: dereferencing a misaligned pointer or even just creating a misaligned reference is undefined behavior
+
+error: borrow of packed field is unsafe and requires unsafe function or block (error E0133)
+  --> $DIR/issue-27060.rs:28:13
+   |
+LL |     let _ = &good.data2[0];
+   |             ^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #46043 <https://github.com/rust-lang/rust/issues/46043>
+   = note: fields of packed structs might be misaligned: dereferencing a misaligned pointer or even just creating a misaligned reference is undefined behavior
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/issues/issue-27078.rs b/src/test/ui/issues/issue-27078.rs
new file mode 100644
index 0000000..ae6ec62
--- /dev/null
+++ b/src/test/ui/issues/issue-27078.rs
@@ -0,0 +1,11 @@
+#![feature(associated_consts)]
+
+trait Foo {
+    const BAR: i32;
+    fn foo(self) -> &'static i32 {
+        //~^ ERROR the size for values of type
+        &<Self>::BAR
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-27078.stderr b/src/test/ui/issues/issue-27078.stderr
new file mode 100644
index 0000000..76cc3e7
--- /dev/null
+++ b/src/test/ui/issues/issue-27078.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the size for values of type `Self` cannot be known at compilation time
+  --> $DIR/issue-27078.rs:5:12
+   |
+LL |     fn foo(self) -> &'static i32 {
+   |            ^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `Self`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = help: consider adding a `where Self: std::marker::Sized` bound
+   = note: all local variables must have a statically known size
+   = help: unsized locals are gated as an unstable feature
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-27105.rs b/src/test/ui/issues/issue-27105.rs
new file mode 100644
index 0000000..5f0dff1
--- /dev/null
+++ b/src/test/ui/issues/issue-27105.rs
@@ -0,0 +1,15 @@
+// compile-pass
+use std::cell::RefCell;
+use std::rc::Rc;
+
+pub struct Callbacks {
+    callbacks: Vec<Rc<RefCell<FnMut(i32)>>>,
+}
+
+impl Callbacks {
+    pub fn register<F: FnMut(i32)+'static>(&mut self, callback: F) {
+        self.callbacks.push(Rc::new(RefCell::new(callback)));
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-2718-a.rs b/src/test/ui/issues/issue-2718-a.rs
new file mode 100644
index 0000000..188168b
--- /dev/null
+++ b/src/test/ui/issues/issue-2718-a.rs
@@ -0,0 +1,12 @@
+pub struct SendPacket<T> {
+    p: T
+}
+
+mod pingpong {
+    use SendPacket;
+    pub type Ping = SendPacket<Pong>;
+    pub struct Pong(SendPacket<Ping>);
+    //~^ ERROR recursive type `pingpong::Pong` has infinite size
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-2718-a.stderr b/src/test/ui/issues/issue-2718-a.stderr
new file mode 100644
index 0000000..0f52c79
--- /dev/null
+++ b/src/test/ui/issues/issue-2718-a.stderr
@@ -0,0 +1,14 @@
+error[E0072]: recursive type `pingpong::Pong` has infinite size
+  --> $DIR/issue-2718-a.rs:8:5
+   |
+LL |     pub struct Pong(SendPacket<Ping>);
+   |     ^^^^^^^^^^^^^^^^----------------^^
+   |     |               |
+   |     |               recursive without indirection
+   |     recursive type has infinite size
+   |
+   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `pingpong::Pong` representable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0072`.
diff --git a/src/test/ui/issues/issue-27281.rs b/src/test/ui/issues/issue-27281.rs
new file mode 100644
index 0000000..8403d9b
--- /dev/null
+++ b/src/test/ui/issues/issue-27281.rs
@@ -0,0 +1,17 @@
+// compile-pass
+pub trait Trait<'a> {
+    type T;
+    type U;
+    fn foo(&self, s: &'a ()) -> &'a ();
+}
+
+impl<'a> Trait<'a> for () {
+    type T = &'a ();
+    type U = Self::T;
+
+    fn foo(&self, s: &'a ()) -> &'a () {
+        let t: Self::T = s; t
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-27282-move-match-input-into-guard.rs b/src/test/ui/issues/issue-27282-move-match-input-into-guard.rs
new file mode 100644
index 0000000..0721b05
--- /dev/null
+++ b/src/test/ui/issues/issue-27282-move-match-input-into-guard.rs
@@ -0,0 +1,22 @@
+// Issue 27282: Example 2: This sidesteps the AST checks disallowing
+// mutable borrows in match guards by hiding the mutable borrow in a
+// guard behind a move (of the mutably borrowed match input) within a
+// closure.
+//
+// This example is not rejected by AST borrowck (and then reliably
+// reaches the panic code when executed, despite the compiler warning
+// about that match arm being unreachable.
+
+#![feature(nll)]
+
+fn main() {
+    let b = &mut true;
+    match b {
+        &mut false => {},
+        _ if { (|| { let bar = b; *bar = false; })();
+                     false } => { },
+        &mut true => { println!("You might think we should get here"); },
+        //~^ ERROR use of moved value: `b` [E0382]
+        _ => panic!("surely we could never get here, since rustc warns it is unreachable."),
+    }
+}
diff --git a/src/test/ui/issues/issue-27282-move-match-input-into-guard.stderr b/src/test/ui/issues/issue-27282-move-match-input-into-guard.stderr
new file mode 100644
index 0000000..6993419
--- /dev/null
+++ b/src/test/ui/issues/issue-27282-move-match-input-into-guard.stderr
@@ -0,0 +1,17 @@
+error[E0382]: use of moved value: `b`
+  --> $DIR/issue-27282-move-match-input-into-guard.rs:18:14
+   |
+LL |     let b = &mut true;
+   |         - move occurs because `b` has type `&mut bool`, which does not implement the `Copy` trait
+...
+LL |         _ if { (|| { let bar = b; *bar = false; })();
+   |                 --             - variable moved due to use in closure
+   |                 |
+   |                 value moved into closure here
+LL |                      false } => { },
+LL |         &mut true => { println!("You might think we should get here"); },
+   |              ^^^^ value used here after move
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/issues/issue-27282-move-ref-mut-into-guard.rs b/src/test/ui/issues/issue-27282-move-ref-mut-into-guard.rs
new file mode 100644
index 0000000..1312aff
--- /dev/null
+++ b/src/test/ui/issues/issue-27282-move-ref-mut-into-guard.rs
@@ -0,0 +1,18 @@
+// Issue 27282: Example 1: This sidesteps the AST checks disallowing
+// mutable borrows in match guards by hiding the mutable borrow in a
+// guard behind a move (of the ref mut pattern id) within a closure.
+//
+// This example is not rejected by AST borrowck (and then reliably
+// segfaults when executed).
+
+#![feature(nll)]
+
+fn main() {
+    match Some(&4) {
+        None => {},
+        ref mut foo
+            if { (|| { let bar = foo; bar.take() })(); false } => {},
+        //~^ ERROR cannot move out of borrowed content [E0507]
+        Some(s) => std::process::exit(*s),
+    }
+}
diff --git a/src/test/ui/issues/issue-27282-move-ref-mut-into-guard.stderr b/src/test/ui/issues/issue-27282-move-ref-mut-into-guard.stderr
new file mode 100644
index 0000000..b5973ba
--- /dev/null
+++ b/src/test/ui/issues/issue-27282-move-ref-mut-into-guard.stderr
@@ -0,0 +1,9 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/issue-27282-move-ref-mut-into-guard.rs:14:18
+   |
+LL |             if { (|| { let bar = foo; bar.take() })(); false } => {},
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-1.rs b/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-1.rs
new file mode 100644
index 0000000..3fb13d6
--- /dev/null
+++ b/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-1.rs
@@ -0,0 +1,33 @@
+// This is testing an attempt to corrupt the discriminant of the match
+// arm in a guard, followed by an attempt to continue matching on that
+// corrupted discriminant in the remaining match arms.
+//
+// Basically this is testing that our new NLL feature of emitting a
+// fake read on each match arm is catching cases like this.
+//
+// This case is interesting because it includes a guard that
+// diverges, and therefore a single final fake-read at the very end
+// after the final match arm would not suffice.
+
+#![feature(nll)]
+
+struct ForceFnOnce;
+
+fn main() {
+    let mut x = &mut Some(&2);
+    let force_fn_once = ForceFnOnce;
+    match x {
+        &mut None => panic!("unreachable"),
+        &mut Some(&_) if {
+            // ForceFnOnce needed to exploit #27282
+            (|| { *x = None; drop(force_fn_once); })();
+            //~^ ERROR cannot mutably borrow `x` in match guard [E0510]
+            false
+        } => {}
+        &mut Some(&a) if { // this binds to garbage if we've corrupted discriminant
+            println!("{}", a);
+            panic!()
+        } => {}
+        _ => panic!("unreachable"),
+    }
+}
diff --git a/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-1.stderr b/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-1.stderr
new file mode 100644
index 0000000..199407a
--- /dev/null
+++ b/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-1.stderr
@@ -0,0 +1,14 @@
+error[E0510]: cannot mutably borrow `x` in match guard
+  --> $DIR/issue-27282-mutate-before-diverging-arm-1.rs:23:14
+   |
+LL |     match x {
+   |           - value is immutable in match guard
+...
+LL |             (|| { *x = None; drop(force_fn_once); })();
+   |              ^^    - borrow occurs due to use of `x` in closure
+   |              |
+   |              cannot mutably borrow
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0510`.
diff --git a/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-2.rs b/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-2.rs
new file mode 100644
index 0000000..f5eaae9
--- /dev/null
+++ b/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-2.rs
@@ -0,0 +1,42 @@
+// This is testing an attempt to corrupt the discriminant of the match
+// arm in a guard, followed by an attempt to continue matching on that
+// corrupted discriminant in the remaining match arms.
+//
+// Basically this is testing that our new NLL feature of emitting a
+// fake read on each match arm is catching cases like this.
+//
+// This case is interesting because it includes a guard that
+// diverges, and therefore a single final fake-read at the very end
+// after the final match arm would not suffice.
+//
+// It is also interesting because the access to the corrupted data
+// occurs in the pattern-match itself, and not in the guard
+// expression.
+
+#![feature(nll)]
+
+struct ForceFnOnce;
+
+fn main() {
+    let mut x = &mut Some(&2);
+    let force_fn_once = ForceFnOnce;
+    match x {
+        &mut None => panic!("unreachable"),
+        &mut Some(&_)
+            if {
+                // ForceFnOnce needed to exploit #27282
+                (|| { *x = None; drop(force_fn_once); })();
+                //~^ ERROR cannot mutably borrow `x` in match guard [E0510]
+                false
+            } => {}
+
+        // this segfaults if we corrupted the discriminant, because
+        // the compiler gets to *assume* that it cannot be the `None`
+        // case, even though that was the effect of the guard.
+        &mut Some(&2)
+            if {
+                panic!()
+            } => {}
+        _ => panic!("unreachable"),
+    }
+}
diff --git a/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-2.stderr b/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-2.stderr
new file mode 100644
index 0000000..3c72cb0
--- /dev/null
+++ b/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-2.stderr
@@ -0,0 +1,14 @@
+error[E0510]: cannot mutably borrow `x` in match guard
+  --> $DIR/issue-27282-mutate-before-diverging-arm-2.rs:28:18
+   |
+LL |     match x {
+   |           - value is immutable in match guard
+...
+LL |                 (|| { *x = None; drop(force_fn_once); })();
+   |                  ^^    - borrow occurs due to use of `x` in closure
+   |                  |
+   |                  cannot mutably borrow
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0510`.
diff --git a/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-3.rs b/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-3.rs
new file mode 100644
index 0000000..4cf5bcd
--- /dev/null
+++ b/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-3.rs
@@ -0,0 +1,30 @@
+// This is testing an attempt to corrupt the discriminant of the match
+// arm in a guard, followed by an attempt to continue matching on that
+// corrupted discriminant in the remaining match arms.
+//
+// Basically this is testing that our new NLL feature of emitting a
+// fake read on each match arm is catching cases like this.
+//
+// This case is interesting because a borrow of **x is untracked, because **x is
+// immutable. However, for matches we care that **x refers to the same value
+// until we have chosen a match arm.
+#![feature(nll)]
+struct ForceFnOnce;
+fn main() {
+    let mut x = &mut &Some(&2);
+    let force_fn_once = ForceFnOnce;
+    match **x {
+        None => panic!("unreachable"),
+        Some(&_) if {
+            // ForceFnOnce needed to exploit #27282
+            (|| { *x = &None; drop(force_fn_once); })();
+            //~^ ERROR cannot mutably borrow `x` in match guard [E0510]
+            false
+        } => {}
+        Some(&a) if { // this binds to garbage if we've corrupted discriminant
+            println!("{}", a);
+            panic!()
+        } => {}
+        _ => panic!("unreachable"),
+    }
+}
diff --git a/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-3.stderr b/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-3.stderr
new file mode 100644
index 0000000..f46a42d
--- /dev/null
+++ b/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-3.stderr
@@ -0,0 +1,14 @@
+error[E0510]: cannot mutably borrow `x` in match guard
+  --> $DIR/issue-27282-mutate-before-diverging-arm-3.rs:20:14
+   |
+LL |     match **x {
+   |           --- value is immutable in match guard
+...
+LL |             (|| { *x = &None; drop(force_fn_once); })();
+   |              ^^    - borrow occurs due to use of `x` in closure
+   |              |
+   |              cannot mutably borrow
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0510`.
diff --git a/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.rs b/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.rs
new file mode 100644
index 0000000..c79b187
--- /dev/null
+++ b/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.rs
@@ -0,0 +1,22 @@
+// Issue 27282: This is a variation on issue-27282-move-ref-mut-into-guard.rs
+//
+// It reborrows instead of moving the `ref mut` pattern borrow. This
+// means that our conservative check for mutation in guards will
+// reject it. But I want to make sure that we continue to reject it
+// (under NLL) even when that conservaive check goes away.
+
+
+#![feature(bind_by_move_pattern_guards)]
+#![feature(nll)]
+
+fn main() {
+    let mut b = &mut true;
+    match b {
+        &mut false => {},
+        ref mut r if { (|| { let bar = &mut *r; **bar = false; })();
+        //~^ ERROR cannot borrow `r` as mutable, as it is immutable for the pattern guard
+                             false } => { &mut *r; },
+        &mut true => { println!("You might think we should get here"); },
+        _ => panic!("surely we could never get here, since rustc warns it is unreachable."),
+    }
+}
diff --git a/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.stderr b/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.stderr
new file mode 100644
index 0000000..3a10928
--- /dev/null
+++ b/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.stderr
@@ -0,0 +1,13 @@
+error[E0596]: cannot borrow `r` as mutable, as it is immutable for the pattern guard
+  --> $DIR/issue-27282-reborrow-ref-mut-in-guard.rs:16:25
+   |
+LL |         ref mut r if { (|| { let bar = &mut *r; **bar = false; })();
+   |                         ^^                   - mutable borrow occurs due to use of `r` in closure
+   |                         |
+   |                         cannot borrow as mutable
+   |
+   = note: variables bound in patterns are immutable until the end of the pattern guard
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/issues/issue-27340.rs b/src/test/ui/issues/issue-27340.rs
new file mode 100644
index 0000000..61c77cc
--- /dev/null
+++ b/src/test/ui/issues/issue-27340.rs
@@ -0,0 +1,6 @@
+struct Foo;
+#[derive(Copy, Clone)]
+//~^ ERROR the trait `Copy` may not be implemented for this type
+struct Bar(Foo);
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-27340.stderr b/src/test/ui/issues/issue-27340.stderr
new file mode 100644
index 0000000..05b213b
--- /dev/null
+++ b/src/test/ui/issues/issue-27340.stderr
@@ -0,0 +1,12 @@
+error[E0204]: the trait `Copy` may not be implemented for this type
+  --> $DIR/issue-27340.rs:2:10
+   |
+LL | #[derive(Copy, Clone)]
+   |          ^^^^
+LL |
+LL | struct Bar(Foo);
+   |            --- this field does not implement `Copy`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0204`.
diff --git a/src/test/ui/issues/issue-27433.rs b/src/test/ui/issues/issue-27433.rs
new file mode 100644
index 0000000..156ae68
--- /dev/null
+++ b/src/test/ui/issues/issue-27433.rs
@@ -0,0 +1,5 @@
+fn main() {
+    let foo = 42u32;
+    const FOO : u32 = foo;
+                   //~^ ERROR attempt to use a non-constant value in a constant
+}
diff --git a/src/test/ui/issues/issue-27433.stderr b/src/test/ui/issues/issue-27433.stderr
new file mode 100644
index 0000000..e232d17
--- /dev/null
+++ b/src/test/ui/issues/issue-27433.stderr
@@ -0,0 +1,9 @@
+error[E0435]: attempt to use a non-constant value in a constant
+  --> $DIR/issue-27433.rs:3:23
+   |
+LL |     const FOO : u32 = foo;
+   |                       ^^^ non-constant value
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0435`.
diff --git a/src/test/ui/issues/issue-2748-a.rs b/src/test/ui/issues/issue-2748-a.rs
new file mode 100644
index 0000000..683a931
--- /dev/null
+++ b/src/test/ui/issues/issue-2748-a.rs
@@ -0,0 +1,17 @@
+// compile-pass
+#![allow(dead_code)]
+#![allow(non_snake_case)]
+
+// pretty-expanded FIXME #23616
+
+struct CMap<'a> {
+    buf: &'a [u8],
+}
+
+fn CMap(buf: &[u8]) -> CMap {
+    CMap {
+        buf: buf
+    }
+}
+
+pub fn main() { }
diff --git a/src/test/ui/issues/issue-27583.rs b/src/test/ui/issues/issue-27583.rs
new file mode 100644
index 0000000..763e9eb
--- /dev/null
+++ b/src/test/ui/issues/issue-27583.rs
@@ -0,0 +1,47 @@
+// compile-pass
+// Regression test for issue #27583. Unclear how useful this will be
+// going forward, since the issue in question was EXTREMELY sensitive
+// to compiler internals (like the precise numbering of nodes), but
+// what the hey.
+
+#![allow(warnings)]
+
+use std::cell::Cell;
+use std::marker::PhantomData;
+
+pub trait Delegate<'tcx> { }
+
+pub struct InferCtxt<'a, 'tcx: 'a> {
+    x: PhantomData<&'a Cell<&'tcx ()>>
+}
+
+pub struct MemCategorizationContext<'t, 'a: 't, 'tcx : 'a> {
+    x: &'t InferCtxt<'a, 'tcx>,
+}
+
+pub struct ExprUseVisitor<'d, 't, 'a: 't, 'tcx:'a+'d> {
+    typer: &'t InferCtxt<'a, 'tcx>,
+    mc: MemCategorizationContext<'t, 'a, 'tcx>,
+    delegate: &'d mut (Delegate<'tcx>+'d),
+}
+
+impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
+    pub fn new(delegate: &'d mut Delegate<'tcx>,
+               typer: &'t InferCtxt<'a, 'tcx>)
+               -> ExprUseVisitor<'d,'t,'a,'tcx>
+    {
+        ExprUseVisitor {
+            typer: typer,
+            mc: MemCategorizationContext::new(typer),
+            delegate: delegate,
+        }
+    }
+}
+
+impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
+    pub fn new(typer: &'t InferCtxt<'a, 'tcx>) -> MemCategorizationContext<'t, 'a, 'tcx> {
+        MemCategorizationContext { x: typer }
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/issues/issue-27592.nll.stderr b/src/test/ui/issues/issue-27592.nll.stderr
new file mode 100644
index 0000000..9d3eaa9
--- /dev/null
+++ b/src/test/ui/issues/issue-27592.nll.stderr
@@ -0,0 +1,21 @@
+error[E0515]: cannot return value referencing temporary value
+  --> $DIR/issue-27592.rs:16:14
+   |
+LL |     write(|| format_args!("{}", String::from("Hello world")));
+   |              ^^^^^^^^^^^^^^^^^^^---------------------------^
+   |              |                  |
+   |              |                  temporary value created here
+   |              returns a value referencing data owned by the current function
+
+error[E0515]: cannot return value referencing temporary value
+  --> $DIR/issue-27592.rs:16:14
+   |
+LL |     write(|| format_args!("{}", String::from("Hello world")));
+   |              ^^^^^^^^^^^^^----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |              |            |
+   |              |            temporary value created here
+   |              returns a value referencing data owned by the current function
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/src/test/ui/issues/issue-27592.rs b/src/test/ui/issues/issue-27592.rs
new file mode 100644
index 0000000..6006f9a
--- /dev/null
+++ b/src/test/ui/issues/issue-27592.rs
@@ -0,0 +1,19 @@
+// Regression test for issue #27592.
+
+fn write<'a, F: ::std::ops::FnOnce()->::std::fmt::Arguments<'a> + 'a>(fcn: F) {
+    use std::fmt::Write;
+    let _ = match fcn() { a => write!(&mut Stream, "{}", a), };
+}
+
+struct Stream;
+impl ::std::fmt::Write for Stream {
+    fn write_str(&mut self, _s: &str) -> ::std::fmt::Result {
+        Ok( () )
+    }
+}
+
+fn main() {
+    write(|| format_args!("{}", String::from("Hello world")));
+    //~^ ERROR borrowed value does not live long enough
+    //~| ERROR borrowed value does not live long enough
+}
diff --git a/src/test/ui/issues/issue-27592.stderr b/src/test/ui/issues/issue-27592.stderr
new file mode 100644
index 0000000..0f62abe
--- /dev/null
+++ b/src/test/ui/issues/issue-27592.stderr
@@ -0,0 +1,21 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/issue-27592.rs:16:27
+   |
+LL |     write(|| format_args!("{}", String::from("Hello world")));
+   |                           ^^^^                             -- temporary value needs to live until here
+   |                           |                                |
+   |                           |                                temporary value dropped here while still borrowed
+   |                           temporary value does not live long enough
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/issue-27592.rs:16:33
+   |
+LL |     write(|| format_args!("{}", String::from("Hello world")));
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^-- temporary value needs to live until here
+   |                                 |                          |
+   |                                 |                          temporary value dropped here while still borrowed
+   |                                 temporary value does not live long enough
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/issues/issue-27815.rs b/src/test/ui/issues/issue-27815.rs
new file mode 100644
index 0000000..9e53014
--- /dev/null
+++ b/src/test/ui/issues/issue-27815.rs
@@ -0,0 +1,12 @@
+mod A {}
+
+fn main() {
+    let u = A { x: 1 }; //~ ERROR expected struct, variant or union type, found module `A`
+    let v = u32 { x: 1 }; //~ ERROR expected struct, variant or union type, found builtin type `u32`
+    match () {
+        A { x: 1 } => {}
+        //~^ ERROR expected struct, variant or union type, found module `A`
+        u32 { x: 1 } => {}
+        //~^ ERROR expected struct, variant or union type, found builtin type `u32`
+    }
+}
diff --git a/src/test/ui/issues/issue-27815.stderr b/src/test/ui/issues/issue-27815.stderr
new file mode 100644
index 0000000..43f78cc
--- /dev/null
+++ b/src/test/ui/issues/issue-27815.stderr
@@ -0,0 +1,27 @@
+error[E0574]: expected struct, variant or union type, found module `A`
+  --> $DIR/issue-27815.rs:4:13
+   |
+LL |     let u = A { x: 1 };
+   |             ^ not a struct, variant or union type
+
+error[E0574]: expected struct, variant or union type, found builtin type `u32`
+  --> $DIR/issue-27815.rs:5:13
+   |
+LL |     let v = u32 { x: 1 };
+   |             ^^^ not a struct, variant or union type
+
+error[E0574]: expected struct, variant or union type, found module `A`
+  --> $DIR/issue-27815.rs:7:9
+   |
+LL |         A { x: 1 } => {}
+   |         ^ not a struct, variant or union type
+
+error[E0574]: expected struct, variant or union type, found builtin type `u32`
+  --> $DIR/issue-27815.rs:9:9
+   |
+LL |         u32 { x: 1 } => {}
+   |         ^^^ not a struct, variant or union type
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0574`.
diff --git a/src/test/ui/issues/issue-27842.rs b/src/test/ui/issues/issue-27842.rs
new file mode 100644
index 0000000..3bcfa13
--- /dev/null
+++ b/src/test/ui/issues/issue-27842.rs
@@ -0,0 +1,11 @@
+fn main() {
+    let tup = (0, 1, 2);
+    // the case where we show a suggestion
+    let _ = tup[0];
+    //~^ ERROR cannot index into a value of type
+
+    // the case where we show just a general hint
+    let i = 0_usize;
+    let _ = tup[i];
+    //~^ ERROR cannot index into a value of type
+}
diff --git a/src/test/ui/issues/issue-27842.stderr b/src/test/ui/issues/issue-27842.stderr
new file mode 100644
index 0000000..784666a
--- /dev/null
+++ b/src/test/ui/issues/issue-27842.stderr
@@ -0,0 +1,17 @@
+error[E0608]: cannot index into a value of type `({integer}, {integer}, {integer})`
+  --> $DIR/issue-27842.rs:4:13
+   |
+LL |     let _ = tup[0];
+   |             ^^^^^^ help: to access tuple elements, use: `tup.0`
+
+error[E0608]: cannot index into a value of type `({integer}, {integer}, {integer})`
+  --> $DIR/issue-27842.rs:9:13
+   |
+LL |     let _ = tup[i];
+   |             ^^^^^^
+   |
+   = help: to access tuple elements, use tuple indexing syntax (e.g., `tuple.0`)
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0608`.
diff --git a/src/test/ui/issues/issue-27889.rs b/src/test/ui/issues/issue-27889.rs
new file mode 100644
index 0000000..22de7c7
--- /dev/null
+++ b/src/test/ui/issues/issue-27889.rs
@@ -0,0 +1,23 @@
+// compile-pass
+#![allow(unused_assignments)]
+#![allow(unused_variables)]
+// Test that a field can have the same name in different variants
+// of an enum
+
+pub enum Foo {
+    X { foo: u32 },
+    Y { foo: u32 }
+}
+
+pub fn foo(mut x: Foo) {
+    let mut y = None;
+    let mut z = None;
+    if let Foo::X { ref foo } = x {
+        z = Some(foo);
+    }
+    if let Foo::Y { ref mut foo } = x {
+        y = Some(foo);
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-27895.rs b/src/test/ui/issues/issue-27895.rs
new file mode 100644
index 0000000..0018ac1
--- /dev/null
+++ b/src/test/ui/issues/issue-27895.rs
@@ -0,0 +1,10 @@
+fn main() {
+    let i = 5;
+    let index = 6;
+
+    match i {
+        0..=index => println!("winner"),
+        //~^ ERROR runtime values cannot be referenced in patterns
+        _ => println!("hello"),
+    }
+}
diff --git a/src/test/ui/issues/issue-27895.stderr b/src/test/ui/issues/issue-27895.stderr
new file mode 100644
index 0000000..55bd938
--- /dev/null
+++ b/src/test/ui/issues/issue-27895.stderr
@@ -0,0 +1,9 @@
+error[E0080]: runtime values cannot be referenced in patterns
+  --> $DIR/issue-27895.rs:6:13
+   |
+LL |         0..=index => println!("winner"),
+   |             ^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/issues/issue-27942.rs b/src/test/ui/issues/issue-27942.rs
new file mode 100644
index 0000000..34b34de
--- /dev/null
+++ b/src/test/ui/issues/issue-27942.rs
@@ -0,0 +1,14 @@
+pub trait Resources<'a> {}
+
+pub trait Buffer<'a, R: Resources<'a>> {
+
+    fn select(&self) -> BufferViewHandle<R>;
+    //~^ ERROR mismatched types
+    //~| lifetime mismatch
+    //~| ERROR mismatched types
+    //~| lifetime mismatch
+}
+
+pub struct BufferViewHandle<'a, R: 'a+Resources<'a>>(&'a R);
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-27942.stderr b/src/test/ui/issues/issue-27942.stderr
new file mode 100644
index 0000000..e039595
--- /dev/null
+++ b/src/test/ui/issues/issue-27942.stderr
@@ -0,0 +1,41 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-27942.rs:5:5
+   |
+LL |     fn select(&self) -> BufferViewHandle<R>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
+   |
+   = note: expected type `Resources<'_>`
+              found type `Resources<'a>`
+note: the anonymous lifetime #1 defined on the method body at 5:5...
+  --> $DIR/issue-27942.rs:5:5
+   |
+LL |     fn select(&self) -> BufferViewHandle<R>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...does not necessarily outlive the lifetime 'a as defined on the trait at 3:18
+  --> $DIR/issue-27942.rs:3:18
+   |
+LL | pub trait Buffer<'a, R: Resources<'a>> {
+   |                  ^^
+
+error[E0308]: mismatched types
+  --> $DIR/issue-27942.rs:5:5
+   |
+LL |     fn select(&self) -> BufferViewHandle<R>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
+   |
+   = note: expected type `Resources<'_>`
+              found type `Resources<'a>`
+note: the lifetime 'a as defined on the trait at 3:18...
+  --> $DIR/issue-27942.rs:3:18
+   |
+LL | pub trait Buffer<'a, R: Resources<'a>> {
+   |                  ^^
+note: ...does not necessarily outlive the anonymous lifetime #1 defined on the method body at 5:5
+  --> $DIR/issue-27942.rs:5:5
+   |
+LL |     fn select(&self) -> BufferViewHandle<R>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-2804-2.rs b/src/test/ui/issues/issue-2804-2.rs
new file mode 100644
index 0000000..d515742
--- /dev/null
+++ b/src/test/ui/issues/issue-2804-2.rs
@@ -0,0 +1,12 @@
+// compile-pass
+#![allow(dead_code)]
+// Minimized version of issue-2804.rs. Both check that callee IDs don't
+// clobber the previous node ID in a macro expr
+
+use std::collections::HashMap;
+
+fn add_interfaces(managed_ip: String, device: HashMap<String, isize>)  {
+     println!("{}, {}", managed_ip, device["interfaces"]);
+}
+
+pub fn main() {}
diff --git a/src/test/ui/issues/issue-28075.rs b/src/test/ui/issues/issue-28075.rs
new file mode 100644
index 0000000..6b4ea46
--- /dev/null
+++ b/src/test/ui/issues/issue-28075.rs
@@ -0,0 +1,13 @@
+// Unstable entities should be caught in import lists
+
+// aux-build:lint-stability.rs
+
+#![allow(warnings)]
+
+extern crate lint_stability;
+
+use lint_stability::{unstable, deprecated};
+//~^ ERROR use of unstable library feature 'unstable_test_feature'
+
+fn main() {
+}
diff --git a/src/test/ui/issues/issue-28075.stderr b/src/test/ui/issues/issue-28075.stderr
new file mode 100644
index 0000000..323be5c
--- /dev/null
+++ b/src/test/ui/issues/issue-28075.stderr
@@ -0,0 +1,11 @@
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/issue-28075.rs:9:22
+   |
+LL | use lint_stability::{unstable, deprecated};
+   |                      ^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/issues/issue-28098.rs b/src/test/ui/issues/issue-28098.rs
new file mode 100644
index 0000000..c4addac
--- /dev/null
+++ b/src/test/ui/issues/issue-28098.rs
@@ -0,0 +1,25 @@
+fn main() {
+    let _ = Iterator::next(&mut ());
+    //~^ ERROR `()` is not an iterator
+
+    for _ in false {}
+    //~^ ERROR `bool` is not an iterator
+
+    let _ = Iterator::next(&mut ());
+    //~^ ERROR `()` is not an iterator
+
+    other()
+}
+
+pub fn other() {
+    // check errors are still reported globally
+
+    let _ = Iterator::next(&mut ());
+    //~^ ERROR `()` is not an iterator
+
+    let _ = Iterator::next(&mut ());
+    //~^ ERROR `()` is not an iterator
+
+    for _ in false {}
+    //~^ ERROR `bool` is not an iterator
+}
diff --git a/src/test/ui/issues/issue-28098.stderr b/src/test/ui/issues/issue-28098.stderr
new file mode 100644
index 0000000..30f7819
--- /dev/null
+++ b/src/test/ui/issues/issue-28098.stderr
@@ -0,0 +1,57 @@
+error[E0277]: `()` is not an iterator
+  --> $DIR/issue-28098.rs:2:13
+   |
+LL |     let _ = Iterator::next(&mut ());
+   |             ^^^^^^^^^^^^^^ `()` is not an iterator
+   |
+   = help: the trait `std::iter::Iterator` is not implemented for `()`
+   = note: required by `std::iter::Iterator::next`
+
+error[E0277]: `bool` is not an iterator
+  --> $DIR/issue-28098.rs:5:14
+   |
+LL |     for _ in false {}
+   |              ^^^^^ `bool` is not an iterator
+   |
+   = help: the trait `std::iter::Iterator` is not implemented for `bool`
+   = note: required by `std::iter::IntoIterator::into_iter`
+
+error[E0277]: `()` is not an iterator
+  --> $DIR/issue-28098.rs:8:13
+   |
+LL |     let _ = Iterator::next(&mut ());
+   |             ^^^^^^^^^^^^^^ `()` is not an iterator
+   |
+   = help: the trait `std::iter::Iterator` is not implemented for `()`
+   = note: required by `std::iter::Iterator::next`
+
+error[E0277]: `()` is not an iterator
+  --> $DIR/issue-28098.rs:17:13
+   |
+LL |     let _ = Iterator::next(&mut ());
+   |             ^^^^^^^^^^^^^^ `()` is not an iterator
+   |
+   = help: the trait `std::iter::Iterator` is not implemented for `()`
+   = note: required by `std::iter::Iterator::next`
+
+error[E0277]: `()` is not an iterator
+  --> $DIR/issue-28098.rs:20:13
+   |
+LL |     let _ = Iterator::next(&mut ());
+   |             ^^^^^^^^^^^^^^ `()` is not an iterator
+   |
+   = help: the trait `std::iter::Iterator` is not implemented for `()`
+   = note: required by `std::iter::Iterator::next`
+
+error[E0277]: `bool` is not an iterator
+  --> $DIR/issue-28098.rs:23:14
+   |
+LL |     for _ in false {}
+   |              ^^^^^ `bool` is not an iterator
+   |
+   = help: the trait `std::iter::Iterator` is not implemented for `bool`
+   = note: required by `std::iter::IntoIterator::into_iter`
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-28105.rs b/src/test/ui/issues/issue-28105.rs
new file mode 100644
index 0000000..6026cbb
--- /dev/null
+++ b/src/test/ui/issues/issue-28105.rs
@@ -0,0 +1,8 @@
+// Make sure that a continue span actually contains the keyword.
+
+fn main() {
+    continue //~ ERROR `continue` outside of loop
+    ;
+    break //~ ERROR `break` outside of loop
+    ;
+}
diff --git a/src/test/ui/issues/issue-28105.stderr b/src/test/ui/issues/issue-28105.stderr
new file mode 100644
index 0000000..0e1b90e
--- /dev/null
+++ b/src/test/ui/issues/issue-28105.stderr
@@ -0,0 +1,15 @@
+error[E0268]: `continue` outside of loop
+  --> $DIR/issue-28105.rs:4:5
+   |
+LL |     continue
+   |     ^^^^^^^^ cannot break outside of a loop
+
+error[E0268]: `break` outside of loop
+  --> $DIR/issue-28105.rs:6:5
+   |
+LL |     break
+   |     ^^^^^ cannot break outside of a loop
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0268`.
diff --git a/src/test/ui/issues/issue-28109.rs b/src/test/ui/issues/issue-28109.rs
new file mode 100644
index 0000000..755a539
--- /dev/null
+++ b/src/test/ui/issues/issue-28109.rs
@@ -0,0 +1,12 @@
+// Make sure that label for continue and break is spanned correctly
+
+fn main() {
+    loop {
+        continue
+        'b //~ ERROR use of undeclared label
+        ;
+        break
+        'c //~ ERROR use of undeclared label
+        ;
+    }
+}
diff --git a/src/test/ui/issues/issue-28109.stderr b/src/test/ui/issues/issue-28109.stderr
new file mode 100644
index 0000000..0f918d3
--- /dev/null
+++ b/src/test/ui/issues/issue-28109.stderr
@@ -0,0 +1,15 @@
+error[E0426]: use of undeclared label `'b`
+  --> $DIR/issue-28109.rs:6:9
+   |
+LL |         'b
+   |         ^^ undeclared label `'b`
+
+error[E0426]: use of undeclared label `'c`
+  --> $DIR/issue-28109.rs:9:9
+   |
+LL |         'c
+   |         ^^ undeclared label `'c`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0426`.
diff --git a/src/test/ui/issues/issue-28113.rs b/src/test/ui/issues/issue-28113.rs
new file mode 100644
index 0000000..e5bd7aa
--- /dev/null
+++ b/src/test/ui/issues/issue-28113.rs
@@ -0,0 +1,8 @@
+#![allow(warnings)]
+
+const X: u8 =
+    || -> u8 { 5 }()
+    //~^ ERROR calls in constants are limited to constant functions
+;
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-28113.stderr b/src/test/ui/issues/issue-28113.stderr
new file mode 100644
index 0000000..3d274d7
--- /dev/null
+++ b/src/test/ui/issues/issue-28113.stderr
@@ -0,0 +1,9 @@
+error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
+  --> $DIR/issue-28113.rs:4:5
+   |
+LL |     || -> u8 { 5 }()
+   |     ^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0015`.
diff --git a/src/test/ui/issues/issue-28134.rs b/src/test/ui/issues/issue-28134.rs
new file mode 100644
index 0000000..2bd4f93
--- /dev/null
+++ b/src/test/ui/issues/issue-28134.rs
@@ -0,0 +1,3 @@
+// compile-flags: --test
+
+#![test] //~ ERROR only functions may be used as tests
diff --git a/src/test/ui/issues/issue-28134.stderr b/src/test/ui/issues/issue-28134.stderr
new file mode 100644
index 0000000..b918948
--- /dev/null
+++ b/src/test/ui/issues/issue-28134.stderr
@@ -0,0 +1,8 @@
+error: only functions may be used as tests
+  --> $DIR/issue-28134.rs:3:1
+   |
+LL | #![test]
+   | ^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-2823.rs b/src/test/ui/issues/issue-2823.rs
new file mode 100644
index 0000000..7b443b4
--- /dev/null
+++ b/src/test/ui/issues/issue-2823.rs
@@ -0,0 +1,14 @@
+struct C {
+    x: isize,
+}
+
+impl Drop for C {
+    fn drop(&mut self) {
+        println!("dropping: {}", self.x);
+    }
+}
+
+fn main() {
+    let c = C{ x: 2};
+    let _d = c.clone(); //~ ERROR no method named `clone` found
+}
diff --git a/src/test/ui/issues/issue-2823.stderr b/src/test/ui/issues/issue-2823.stderr
new file mode 100644
index 0000000..4c1dfb8
--- /dev/null
+++ b/src/test/ui/issues/issue-2823.stderr
@@ -0,0 +1,16 @@
+error[E0599]: no method named `clone` found for type `C` in the current scope
+  --> $DIR/issue-2823.rs:13:16
+   |
+LL | struct C {
+   | -------- method `clone` not found for this
+...
+LL |     let _d = c.clone();
+   |                ^^^^^
+   |
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following trait defines an item `clone`, perhaps you need to implement it:
+           candidate #1: `std::clone::Clone`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/issues/issue-28279.rs b/src/test/ui/issues/issue-28279.rs
new file mode 100644
index 0000000..c770c50
--- /dev/null
+++ b/src/test/ui/issues/issue-28279.rs
@@ -0,0 +1,21 @@
+// compile-pass
+#![allow(dead_code)]
+use std::rc::Rc;
+
+fn test1() -> Rc<for<'a> Fn(&'a usize) + 'static> {
+    if let Some(_) = Some(1) {
+        loop{}
+    } else {
+        loop{}
+    }
+}
+
+fn test2() -> *mut (for<'a> Fn(&'a usize) + 'static) {
+    if let Some(_) = Some(1) {
+        loop{}
+    } else {
+        loop{}
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-28324.rs b/src/test/ui/issues/issue-28324.rs
new file mode 100644
index 0000000..73e8cd6
--- /dev/null
+++ b/src/test/ui/issues/issue-28324.rs
@@ -0,0 +1,11 @@
+#![allow(safe_extern_statics)]
+
+extern {
+    static error_message_count: u32;
+}
+
+pub static BAZ: u32 = *&error_message_count;
+//~^ ERROR could not evaluate static initializer
+//~| tried to read from foreign (extern) static
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-28324.stderr b/src/test/ui/issues/issue-28324.stderr
new file mode 100644
index 0000000..bbd02ba
--- /dev/null
+++ b/src/test/ui/issues/issue-28324.stderr
@@ -0,0 +1,9 @@
+error[E0080]: could not evaluate static initializer
+  --> $DIR/issue-28324.rs:7:23
+   |
+LL | pub static BAZ: u32 = *&error_message_count;
+   |                       ^^^^^^^^^^^^^^^^^^^^^ tried to read from foreign (extern) static
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/issues/issue-28344.rs b/src/test/ui/issues/issue-28344.rs
new file mode 100644
index 0000000..4da7ee2
--- /dev/null
+++ b/src/test/ui/issues/issue-28344.rs
@@ -0,0 +1,11 @@
+use std::ops::BitXor;
+
+fn main() {
+    let x: u8 = BitXor::bitor(0 as u8, 0 as u8);
+    //~^ ERROR must be specified
+    //~| no function or associated item named
+
+    let g = BitXor::bitor;
+    //~^ ERROR must be specified
+    //~| no function or associated item named
+}
diff --git a/src/test/ui/issues/issue-28344.stderr b/src/test/ui/issues/issue-28344.stderr
new file mode 100644
index 0000000..fcd98b1
--- /dev/null
+++ b/src/test/ui/issues/issue-28344.stderr
@@ -0,0 +1,34 @@
+error[E0191]: the value of the associated type `Output` (from the trait `std::ops::BitXor`) must be specified
+  --> $DIR/issue-28344.rs:4:17
+   |
+LL |     let x: u8 = BitXor::bitor(0 as u8, 0 as u8);
+   |                 ^^^^^^^^^^^^^ associated type `Output` must be specified
+
+error[E0599]: no function or associated item named `bitor` found for type `dyn std::ops::BitXor<_>` in the current scope
+  --> $DIR/issue-28344.rs:4:25
+   |
+LL |     let x: u8 = BitXor::bitor(0 as u8, 0 as u8);
+   |                         ^^^^^
+   |                         |
+   |                         function or associated item not found in `dyn std::ops::BitXor<_>`
+   |                         help: did you mean: `bitxor`
+
+error[E0191]: the value of the associated type `Output` (from the trait `std::ops::BitXor`) must be specified
+  --> $DIR/issue-28344.rs:8:13
+   |
+LL |     let g = BitXor::bitor;
+   |             ^^^^^^^^^^^^^ associated type `Output` must be specified
+
+error[E0599]: no function or associated item named `bitor` found for type `dyn std::ops::BitXor<_>` in the current scope
+  --> $DIR/issue-28344.rs:8:21
+   |
+LL |     let g = BitXor::bitor;
+   |                     ^^^^^
+   |                     |
+   |                     function or associated item not found in `dyn std::ops::BitXor<_>`
+   |                     help: did you mean: `bitxor`
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0191, E0599.
+For more information about an error, try `rustc --explain E0191`.
diff --git a/src/test/ui/issues/issue-28388-1.rs b/src/test/ui/issues/issue-28388-1.rs
new file mode 100644
index 0000000..14de621
--- /dev/null
+++ b/src/test/ui/issues/issue-28388-1.rs
@@ -0,0 +1,5 @@
+// Prefix in imports with empty braces should be resolved and checked privacy, stability, etc.
+
+use foo::{}; //~ ERROR unresolved import `foo`
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-28388-1.stderr b/src/test/ui/issues/issue-28388-1.stderr
new file mode 100644
index 0000000..7f5e47a
--- /dev/null
+++ b/src/test/ui/issues/issue-28388-1.stderr
@@ -0,0 +1,9 @@
+error[E0432]: unresolved import `foo`
+  --> $DIR/issue-28388-1.rs:3:5
+   |
+LL | use foo::{};
+   |     ^^^^^^^ no `foo` in the root
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/issues/issue-28388-2.rs b/src/test/ui/issues/issue-28388-2.rs
new file mode 100644
index 0000000..024b038
--- /dev/null
+++ b/src/test/ui/issues/issue-28388-2.rs
@@ -0,0 +1,10 @@
+// Prefix in imports with empty braces should be resolved and checked privacy, stability, etc.
+
+mod m {
+    mod n {}
+}
+
+use m::n::{};
+//~^ ERROR module `n` is private
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-28388-2.stderr b/src/test/ui/issues/issue-28388-2.stderr
new file mode 100644
index 0000000..7bbe0bc
--- /dev/null
+++ b/src/test/ui/issues/issue-28388-2.stderr
@@ -0,0 +1,9 @@
+error[E0603]: module `n` is private
+  --> $DIR/issue-28388-2.rs:7:8
+   |
+LL | use m::n::{};
+   |        ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0603`.
diff --git a/src/test/ui/issues/issue-28388-3.rs b/src/test/ui/issues/issue-28388-3.rs
new file mode 100644
index 0000000..7ba9935
--- /dev/null
+++ b/src/test/ui/issues/issue-28388-3.rs
@@ -0,0 +1,11 @@
+// Prefix in imports with empty braces should be resolved and checked privacy, stability, etc.
+
+// aux-build:lint-stability.rs
+
+extern crate lint_stability;
+
+use lint_stability::UnstableEnum::{};
+//~^ ERROR use of unstable library feature 'unstable_test_feature'
+use lint_stability::StableEnum::{}; // OK
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-28388-3.stderr b/src/test/ui/issues/issue-28388-3.stderr
new file mode 100644
index 0000000..2eb8249
--- /dev/null
+++ b/src/test/ui/issues/issue-28388-3.stderr
@@ -0,0 +1,11 @@
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/issue-28388-3.rs:7:5
+   |
+LL | use lint_stability::UnstableEnum::{};
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/issues/issue-28433.rs b/src/test/ui/issues/issue-28433.rs
new file mode 100644
index 0000000..2bbb32b
--- /dev/null
+++ b/src/test/ui/issues/issue-28433.rs
@@ -0,0 +1,14 @@
+// compile-flags: -Z continue-parse-after-error
+
+enum Bird {
+    pub Duck,
+    //~^ ERROR unnecessary visibility qualifier
+    Goose,
+    pub(crate) Dove
+    //~^ ERROR unnecessary visibility qualifier
+}
+
+
+fn main() {
+    let y = Bird::Goose;
+}
diff --git a/src/test/ui/issues/issue-28433.stderr b/src/test/ui/issues/issue-28433.stderr
new file mode 100644
index 0000000..cfdbf6c
--- /dev/null
+++ b/src/test/ui/issues/issue-28433.stderr
@@ -0,0 +1,14 @@
+error: unnecessary visibility qualifier
+  --> $DIR/issue-28433.rs:4:5
+   |
+LL |     pub Duck,
+   |     ^^^ `pub` not permitted here
+
+error: unnecessary visibility qualifier
+  --> $DIR/issue-28433.rs:7:5
+   |
+LL |     pub(crate) Dove
+   |     ^^^^^^^^^^ `pub` not permitted here
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/issues/issue-28472.rs b/src/test/ui/issues/issue-28472.rs
new file mode 100644
index 0000000..17d74ea
--- /dev/null
+++ b/src/test/ui/issues/issue-28472.rs
@@ -0,0 +1,14 @@
+// Check that the visibility modifier is included in the span of foreign items.
+
+extern {
+  fn foo();
+
+  pub //~ ERROR the name `foo` is defined multiple times
+  fn foo();
+
+  pub //~ ERROR the name `foo` is defined multiple times
+  static mut foo: u32;
+}
+
+fn main() {
+}
diff --git a/src/test/ui/issues/issue-28472.stderr b/src/test/ui/issues/issue-28472.stderr
new file mode 100644
index 0000000..92b5982
--- /dev/null
+++ b/src/test/ui/issues/issue-28472.stderr
@@ -0,0 +1,27 @@
+error[E0428]: the name `foo` is defined multiple times
+  --> $DIR/issue-28472.rs:6:3
+   |
+LL |     fn foo();
+   |     --------- previous definition of the value `foo` here
+LL | 
+LL | /   pub
+LL | |   fn foo();
+   | |___________^ `foo` redefined here
+   |
+   = note: `foo` must be defined only once in the value namespace of this module
+
+error[E0428]: the name `foo` is defined multiple times
+  --> $DIR/issue-28472.rs:9:3
+   |
+LL |     fn foo();
+   |     --------- previous definition of the value `foo` here
+...
+LL | /   pub
+LL | |   static mut foo: u32;
+   | |______________________^ `foo` redefined here
+   |
+   = note: `foo` must be defined only once in the value namespace of this module
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0428`.
diff --git a/src/test/ui/issues/issue-2848.rs b/src/test/ui/issues/issue-2848.rs
new file mode 100644
index 0000000..e0049bf
--- /dev/null
+++ b/src/test/ui/issues/issue-2848.rs
@@ -0,0 +1,17 @@
+#[allow(non_camel_case_types)]
+
+mod bar {
+    pub enum foo {
+        alpha,
+        beta,
+        charlie
+    }
+}
+
+fn main() {
+    use bar::foo::{alpha, charlie};
+    match alpha {
+      alpha | beta => {} //~  ERROR variable `beta` is not bound in all patterns
+      charlie => {}
+    }
+}
diff --git a/src/test/ui/issues/issue-2848.stderr b/src/test/ui/issues/issue-2848.stderr
new file mode 100644
index 0000000..71ed7d7
--- /dev/null
+++ b/src/test/ui/issues/issue-2848.stderr
@@ -0,0 +1,11 @@
+error[E0408]: variable `beta` is not bound in all patterns
+  --> $DIR/issue-2848.rs:14:7
+   |
+LL |       alpha | beta => {}
+   |       ^^^^^   ---- variable not in all patterns
+   |       |
+   |       pattern doesn't bind `beta`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0408`.
diff --git a/src/test/ui/issues/issue-2849.rs b/src/test/ui/issues/issue-2849.rs
new file mode 100644
index 0000000..787ab0e
--- /dev/null
+++ b/src/test/ui/issues/issue-2849.rs
@@ -0,0 +1,8 @@
+enum Foo { Alpha, Beta(isize) }
+
+fn main() {
+    match Foo::Alpha {
+      Foo::Alpha | Foo::Beta(i) => {}
+      //~^ ERROR variable `i` is not bound in all patterns
+    }
+}
diff --git a/src/test/ui/issues/issue-2849.stderr b/src/test/ui/issues/issue-2849.stderr
new file mode 100644
index 0000000..9027098
--- /dev/null
+++ b/src/test/ui/issues/issue-2849.stderr
@@ -0,0 +1,11 @@
+error[E0408]: variable `i` is not bound in all patterns
+  --> $DIR/issue-2849.rs:5:7
+   |
+LL |       Foo::Alpha | Foo::Beta(i) => {}
+   |       ^^^^^^^^^^             - variable not in all patterns
+   |       |
+   |       pattern doesn't bind `i`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0408`.
diff --git a/src/test/ui/issues/issue-28561.rs b/src/test/ui/issues/issue-28561.rs
new file mode 100644
index 0000000..9dcce99
--- /dev/null
+++ b/src/test/ui/issues/issue-28561.rs
@@ -0,0 +1,111 @@
+// compile-pass
+#[derive(Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
+struct Array<T> {
+    f00: [T; 00],
+    f01: [T; 01],
+    f02: [T; 02],
+    f03: [T; 03],
+    f04: [T; 04],
+    f05: [T; 05],
+    f06: [T; 06],
+    f07: [T; 07],
+    f08: [T; 08],
+    f09: [T; 09],
+    f10: [T; 10],
+    f11: [T; 11],
+    f12: [T; 12],
+    f13: [T; 13],
+    f14: [T; 14],
+    f15: [T; 15],
+    f16: [T; 16],
+    f17: [T; 17],
+    f18: [T; 18],
+    f19: [T; 19],
+    f20: [T; 20],
+    f21: [T; 21],
+    f22: [T; 22],
+    f23: [T; 23],
+    f24: [T; 24],
+    f25: [T; 25],
+    f26: [T; 26],
+    f27: [T; 27],
+    f28: [T; 28],
+    f29: [T; 29],
+    f30: [T; 30],
+    f31: [T; 31],
+    f32: [T; 32],
+}
+
+// FIXME(#44580): merge with `Array` once `[T; N]: Clone` where `T: Clone`
+#[derive(Clone, Copy)]
+struct CopyArray<T: Copy> {
+    f00: [T; 00],
+    f01: [T; 01],
+    f02: [T; 02],
+    f03: [T; 03],
+    f04: [T; 04],
+    f05: [T; 05],
+    f06: [T; 06],
+    f07: [T; 07],
+    f08: [T; 08],
+    f09: [T; 09],
+    f10: [T; 10],
+    f11: [T; 11],
+    f12: [T; 12],
+    f13: [T; 13],
+    f14: [T; 14],
+    f15: [T; 15],
+    f16: [T; 16],
+    f17: [T; 17],
+    f18: [T; 18],
+    f19: [T; 19],
+    f20: [T; 20],
+    f21: [T; 21],
+    f22: [T; 22],
+    f23: [T; 23],
+    f24: [T; 24],
+    f25: [T; 25],
+    f26: [T; 26],
+    f27: [T; 27],
+    f28: [T; 28],
+    f29: [T; 29],
+    f30: [T; 30],
+    f31: [T; 31],
+    f32: [T; 32],
+}
+
+#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
+struct Fn<A, B, C, D, E, F, G, H, I, J, K, L> {
+    f00: fn(),
+    f01: fn(A),
+    f02: fn(A, B),
+    f03: fn(A, B, C),
+    f04: fn(A, B, C, D),
+    f05: fn(A, B, C, D, E),
+    f06: fn(A, B, C, D, E, F),
+    f07: fn(A, B, C, D, E, F, G),
+    f08: fn(A, B, C, D, E, F, G, H),
+    f09: fn(A, B, C, D, E, F, G, H, I),
+    f10: fn(A, B, C, D, E, F, G, H, I, J),
+    f11: fn(A, B, C, D, E, F, G, H, I, J, K),
+    f12: fn(A, B, C, D, E, F, G, H, I, J, K, L),
+}
+
+#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
+struct Tuple<A, B, C, D, E, F, G, H, I, J, K, L> {
+    f00: (),
+    f01: (A),
+    f02: (A, B),
+    f03: (A, B, C),
+    f04: (A, B, C, D),
+    f05: (A, B, C, D, E),
+    f06: (A, B, C, D, E, F),
+    f07: (A, B, C, D, E, F, G),
+    f08: (A, B, C, D, E, F, G, H),
+    f09: (A, B, C, D, E, F, G, H, I),
+    f10: (A, B, C, D, E, F, G, H, I, J),
+    f11: (A, B, C, D, E, F, G, H, I, J, K),
+    f12: (A, B, C, D, E, F, G, H, I, J, K, L),
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-28568.rs b/src/test/ui/issues/issue-28568.rs
new file mode 100644
index 0000000..ce51115
--- /dev/null
+++ b/src/test/ui/issues/issue-28568.rs
@@ -0,0 +1,12 @@
+struct MyStruct;
+
+impl Drop for MyStruct {
+    fn drop(&mut self) { }
+}
+
+impl Drop for MyStruct {
+//~^ ERROR conflicting implementations of trait
+    fn drop(&mut self) { }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-28568.stderr b/src/test/ui/issues/issue-28568.stderr
new file mode 100644
index 0000000..7729b9d
--- /dev/null
+++ b/src/test/ui/issues/issue-28568.stderr
@@ -0,0 +1,12 @@
+error[E0119]: conflicting implementations of trait `std::ops::Drop` for type `MyStruct`:
+  --> $DIR/issue-28568.rs:7:1
+   |
+LL | impl Drop for MyStruct {
+   | ---------------------- first implementation here
+...
+LL | impl Drop for MyStruct {
+   | ^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `MyStruct`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/issues/issue-28576.rs b/src/test/ui/issues/issue-28576.rs
new file mode 100644
index 0000000..de665d5
--- /dev/null
+++ b/src/test/ui/issues/issue-28576.rs
@@ -0,0 +1,12 @@
+pub trait Foo<RHS=Self> {
+    type Assoc;
+}
+
+pub trait Bar: Foo<Assoc=()> {
+    fn new(&self, b: &
+           Bar //~ ERROR the trait `Bar` cannot be made into an object
+              <Assoc=()>
+    );
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-28576.stderr b/src/test/ui/issues/issue-28576.stderr
new file mode 100644
index 0000000..cf6174b
--- /dev/null
+++ b/src/test/ui/issues/issue-28576.stderr
@@ -0,0 +1,12 @@
+error[E0038]: the trait `Bar` cannot be made into an object
+  --> $DIR/issue-28576.rs:7:12
+   |
+LL | /            Bar
+LL | |               <Assoc=()>
+   | |________________________^ the trait `Bar` cannot be made into an object
+   |
+   = note: the trait cannot use `Self` as a type parameter in the supertraits or where-clauses
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/issues/issue-28586.rs b/src/test/ui/issues/issue-28586.rs
new file mode 100644
index 0000000..4d286be
--- /dev/null
+++ b/src/test/ui/issues/issue-28586.rs
@@ -0,0 +1,7 @@
+// Regression test for issue #28586
+
+pub trait Foo {}
+impl Foo for [u8; usize::BYTES] {}
+//~^ ERROR no associated item named `BYTES` found for type `usize`
+
+fn main() { }
diff --git a/src/test/ui/issues/issue-28586.stderr b/src/test/ui/issues/issue-28586.stderr
new file mode 100644
index 0000000..d19c4af
--- /dev/null
+++ b/src/test/ui/issues/issue-28586.stderr
@@ -0,0 +1,9 @@
+error[E0599]: no associated item named `BYTES` found for type `usize` in the current scope
+  --> $DIR/issue-28586.rs:4:26
+   |
+LL | impl Foo for [u8; usize::BYTES] {}
+   |                          ^^^^^ associated item not found in `usize`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/issues/issue-28600.rs b/src/test/ui/issues/issue-28600.rs
new file mode 100644
index 0000000..44a8592
--- /dev/null
+++ b/src/test/ui/issues/issue-28600.rs
@@ -0,0 +1,14 @@
+// compile-pass
+// #28600 ICE: pub extern fn with parameter type &str inside struct impl
+
+struct Test;
+
+impl Test {
+    #[allow(dead_code)]
+    #[allow(unused_variables)]
+    pub extern fn test(val: &str) {
+
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-28625.rs b/src/test/ui/issues/issue-28625.rs
new file mode 100644
index 0000000..15a6a63
--- /dev/null
+++ b/src/test/ui/issues/issue-28625.rs
@@ -0,0 +1,22 @@
+// normalize-stderr-test "\d+ bits" -> "N bits"
+
+trait Bar {
+    type Bar;
+}
+
+struct ArrayPeano<T: Bar> {
+    data: T::Bar,
+}
+
+fn foo<T>(a: &ArrayPeano<T>) -> &[T] where T: Bar {
+    unsafe { std::mem::transmute(a) } //~ ERROR cannot transmute between types of different sizes
+}
+
+impl Bar for () {
+    type Bar = ();
+}
+
+fn main() {
+    let x: ArrayPeano<()> = ArrayPeano { data: () };
+    foo(&x);
+}
diff --git a/src/test/ui/issues/issue-28625.stderr b/src/test/ui/issues/issue-28625.stderr
new file mode 100644
index 0000000..7ee0cd4
--- /dev/null
+++ b/src/test/ui/issues/issue-28625.stderr
@@ -0,0 +1,12 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/issue-28625.rs:12:14
+   |
+LL |     unsafe { std::mem::transmute(a) }
+   |              ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: source type: `&ArrayPeano<T>` (N bits)
+   = note: target type: `&[T]` (N bits)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0512`.
diff --git a/src/test/ui/issues/issue-28776.rs b/src/test/ui/issues/issue-28776.rs
new file mode 100644
index 0000000..e564ebc
--- /dev/null
+++ b/src/test/ui/issues/issue-28776.rs
@@ -0,0 +1,6 @@
+use std::ptr;
+
+fn main() {
+    (&ptr::write)(1 as *mut _, 42);
+    //~^ ERROR E0133
+}
diff --git a/src/test/ui/issues/issue-28776.stderr b/src/test/ui/issues/issue-28776.stderr
new file mode 100644
index 0000000..7faac88
--- /dev/null
+++ b/src/test/ui/issues/issue-28776.stderr
@@ -0,0 +1,11 @@
+error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
+  --> $DIR/issue-28776.rs:4:5
+   |
+LL |     (&ptr::write)(1 as *mut _, 42);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/issues/issue-28822.rs b/src/test/ui/issues/issue-28822.rs
new file mode 100644
index 0000000..7381c34
--- /dev/null
+++ b/src/test/ui/issues/issue-28822.rs
@@ -0,0 +1,7 @@
+// compile-pass
+#![allow(dead_code)]
+
+fn main() {}
+
+const fn size_ofs(_: usize) {}
+const fn size_ofs2(_foo: usize) {}
diff --git a/src/test/ui/issues/issue-28837.rs b/src/test/ui/issues/issue-28837.rs
new file mode 100644
index 0000000..114473f
--- /dev/null
+++ b/src/test/ui/issues/issue-28837.rs
@@ -0,0 +1,35 @@
+struct A;
+
+fn main() {
+    let a = A;
+
+    a + a; //~ ERROR binary operation `+` cannot be applied to type `A`
+
+    a - a; //~ ERROR binary operation `-` cannot be applied to type `A`
+
+    a * a; //~ ERROR binary operation `*` cannot be applied to type `A`
+
+    a / a; //~ ERROR binary operation `/` cannot be applied to type `A`
+
+    a % a; //~ ERROR binary operation `%` cannot be applied to type `A`
+
+    a & a; //~ ERROR binary operation `&` cannot be applied to type `A`
+
+    a | a; //~ ERROR binary operation `|` cannot be applied to type `A`
+
+    a << a; //~ ERROR binary operation `<<` cannot be applied to type `A`
+
+    a >> a; //~ ERROR binary operation `>>` cannot be applied to type `A`
+
+    a == a; //~ ERROR binary operation `==` cannot be applied to type `A`
+
+    a != a; //~ ERROR binary operation `!=` cannot be applied to type `A`
+
+    a < a; //~ ERROR binary operation `<` cannot be applied to type `A`
+
+    a <= a; //~ ERROR binary operation `<=` cannot be applied to type `A`
+
+    a > a; //~ ERROR binary operation `>` cannot be applied to type `A`
+
+    a >= a; //~ ERROR binary operation `>=` cannot be applied to type `A`
+}
diff --git a/src/test/ui/issues/issue-28837.stderr b/src/test/ui/issues/issue-28837.stderr
new file mode 100644
index 0000000..ac2a9f2
--- /dev/null
+++ b/src/test/ui/issues/issue-28837.stderr
@@ -0,0 +1,153 @@
+error[E0369]: binary operation `+` cannot be applied to type `A`
+  --> $DIR/issue-28837.rs:6:7
+   |
+LL |     a + a;
+   |     - ^ - A
+   |     |
+   |     A
+   |
+   = note: an implementation of `std::ops::Add` might be missing for `A`
+
+error[E0369]: binary operation `-` cannot be applied to type `A`
+  --> $DIR/issue-28837.rs:8:7
+   |
+LL |     a - a;
+   |     - ^ - A
+   |     |
+   |     A
+   |
+   = note: an implementation of `std::ops::Sub` might be missing for `A`
+
+error[E0369]: binary operation `*` cannot be applied to type `A`
+  --> $DIR/issue-28837.rs:10:7
+   |
+LL |     a * a;
+   |     - ^ - A
+   |     |
+   |     A
+   |
+   = note: an implementation of `std::ops::Mul` might be missing for `A`
+
+error[E0369]: binary operation `/` cannot be applied to type `A`
+  --> $DIR/issue-28837.rs:12:7
+   |
+LL |     a / a;
+   |     - ^ - A
+   |     |
+   |     A
+   |
+   = note: an implementation of `std::ops::Div` might be missing for `A`
+
+error[E0369]: binary operation `%` cannot be applied to type `A`
+  --> $DIR/issue-28837.rs:14:7
+   |
+LL |     a % a;
+   |     - ^ - A
+   |     |
+   |     A
+   |
+   = note: an implementation of `std::ops::Rem` might be missing for `A`
+
+error[E0369]: binary operation `&` cannot be applied to type `A`
+  --> $DIR/issue-28837.rs:16:7
+   |
+LL |     a & a;
+   |     - ^ - A
+   |     |
+   |     A
+   |
+   = note: an implementation of `std::ops::BitAnd` might be missing for `A`
+
+error[E0369]: binary operation `|` cannot be applied to type `A`
+  --> $DIR/issue-28837.rs:18:7
+   |
+LL |     a | a;
+   |     - ^ - A
+   |     |
+   |     A
+   |
+   = note: an implementation of `std::ops::BitOr` might be missing for `A`
+
+error[E0369]: binary operation `<<` cannot be applied to type `A`
+  --> $DIR/issue-28837.rs:20:7
+   |
+LL |     a << a;
+   |     - ^^ - A
+   |     |
+   |     A
+   |
+   = note: an implementation of `std::ops::Shl` might be missing for `A`
+
+error[E0369]: binary operation `>>` cannot be applied to type `A`
+  --> $DIR/issue-28837.rs:22:7
+   |
+LL |     a >> a;
+   |     - ^^ - A
+   |     |
+   |     A
+   |
+   = note: an implementation of `std::ops::Shr` might be missing for `A`
+
+error[E0369]: binary operation `==` cannot be applied to type `A`
+  --> $DIR/issue-28837.rs:24:7
+   |
+LL |     a == a;
+   |     - ^^ - A
+   |     |
+   |     A
+   |
+   = note: an implementation of `std::cmp::PartialEq` might be missing for `A`
+
+error[E0369]: binary operation `!=` cannot be applied to type `A`
+  --> $DIR/issue-28837.rs:26:7
+   |
+LL |     a != a;
+   |     - ^^ - A
+   |     |
+   |     A
+   |
+   = note: an implementation of `std::cmp::PartialEq` might be missing for `A`
+
+error[E0369]: binary operation `<` cannot be applied to type `A`
+  --> $DIR/issue-28837.rs:28:7
+   |
+LL |     a < a;
+   |     - ^ - A
+   |     |
+   |     A
+   |
+   = note: an implementation of `std::cmp::PartialOrd` might be missing for `A`
+
+error[E0369]: binary operation `<=` cannot be applied to type `A`
+  --> $DIR/issue-28837.rs:30:7
+   |
+LL |     a <= a;
+   |     - ^^ - A
+   |     |
+   |     A
+   |
+   = note: an implementation of `std::cmp::PartialOrd` might be missing for `A`
+
+error[E0369]: binary operation `>` cannot be applied to type `A`
+  --> $DIR/issue-28837.rs:32:7
+   |
+LL |     a > a;
+   |     - ^ - A
+   |     |
+   |     A
+   |
+   = note: an implementation of `std::cmp::PartialOrd` might be missing for `A`
+
+error[E0369]: binary operation `>=` cannot be applied to type `A`
+  --> $DIR/issue-28837.rs:34:7
+   |
+LL |     a >= a;
+   |     - ^^ - A
+   |     |
+   |     A
+   |
+   = note: an implementation of `std::cmp::PartialOrd` might be missing for `A`
+
+error: aborting due to 15 previous errors
+
+For more information about this error, try `rustc --explain E0369`.
diff --git a/src/test/ui/issues/issue-28848.rs b/src/test/ui/issues/issue-28848.rs
new file mode 100644
index 0000000..a625023
--- /dev/null
+++ b/src/test/ui/issues/issue-28848.rs
@@ -0,0 +1,13 @@
+struct Foo<'a, 'b: 'a>(&'a &'b ());
+
+impl<'a, 'b> Foo<'a, 'b> {
+    fn xmute(a: &'b ()) -> &'a () {
+        unreachable!()
+    }
+}
+
+pub fn foo<'a, 'b>(u: &'b ()) -> &'a () {
+    Foo::<'a, 'b>::xmute(u) //~ ERROR lifetime bound not satisfied
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-28848.stderr b/src/test/ui/issues/issue-28848.stderr
new file mode 100644
index 0000000..5f0f202
--- /dev/null
+++ b/src/test/ui/issues/issue-28848.stderr
@@ -0,0 +1,20 @@
+error[E0478]: lifetime bound not satisfied
+  --> $DIR/issue-28848.rs:10:5
+   |
+LL |     Foo::<'a, 'b>::xmute(u)
+   |     ^^^^^^^^^^^^^^^^^^^^
+   |
+note: lifetime parameter instantiated with the lifetime 'b as defined on the function body at 9:16
+  --> $DIR/issue-28848.rs:9:16
+   |
+LL | pub fn foo<'a, 'b>(u: &'b ()) -> &'a () {
+   |                ^^
+note: but lifetime parameter must outlive the lifetime 'a as defined on the function body at 9:12
+  --> $DIR/issue-28848.rs:9:12
+   |
+LL | pub fn foo<'a, 'b>(u: &'b ()) -> &'a () {
+   |            ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0478`.
diff --git a/src/test/ui/issues/issue-28871.rs b/src/test/ui/issues/issue-28871.rs
new file mode 100644
index 0000000..b7e02b8
--- /dev/null
+++ b/src/test/ui/issues/issue-28871.rs
@@ -0,0 +1,24 @@
+// compile-pass
+// Regression test for #28871. The problem is that rustc encountered
+// two ways to project, one from a where clause and one from the where
+// clauses on the trait definition. (In fact, in this case, the where
+// clauses originated from the trait definition as well.) The true
+// cause of the error is that the trait definition where clauses are
+// not being normalized, and hence the two sources are considered in
+// conflict, and not a duplicate. Hacky solution is to prefer where
+// clauses over the data found in the trait definition.
+
+trait T {
+    type T;
+}
+
+struct S;
+impl T for S {
+    type T = S;
+}
+
+trait T2 {
+    type T: Iterator<Item=<S as T>::T>;
+}
+
+fn main() { }
diff --git a/src/test/ui/issues/issue-28936.rs b/src/test/ui/issues/issue-28936.rs
new file mode 100644
index 0000000..5365adf
--- /dev/null
+++ b/src/test/ui/issues/issue-28936.rs
@@ -0,0 +1,27 @@
+// compile-pass
+pub type Session = i32;
+pub struct StreamParser<'a, T> {
+    _tokens: T,
+    _session: &'a mut Session,
+}
+
+impl<'a, T> StreamParser<'a, T> {
+    pub fn thing(&mut self) -> bool { true }
+}
+
+pub fn parse_stream<T: Iterator<Item=i32>, U, F>(
+        _session: &mut Session, _tokens: T, _f: F) -> U
+    where F: Fn(&mut StreamParser<T>) -> U { panic!(); }
+
+pub fn thing(session: &mut Session) {
+    let mut stream = vec![1, 2, 3].into_iter();
+
+    let _b = parse_stream(session,
+                          stream.by_ref(),
+                          // replacing the above with the following fixes it
+                          //&mut stream,
+                          |p| p.thing());
+
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-28971.rs b/src/test/ui/issues/issue-28971.rs
new file mode 100644
index 0000000..3f0d2fa
--- /dev/null
+++ b/src/test/ui/issues/issue-28971.rs
@@ -0,0 +1,18 @@
+// This should not cause an ICE
+
+enum Foo {
+    Bar(u8)
+}
+fn main(){
+    foo(|| {
+        match Foo::Bar(1) {
+            Foo::Baz(..) => (),
+            //~^ ERROR no variant named `Baz` found for type `Foo`
+            _ => (),
+        }
+    });
+}
+
+fn foo<F>(f: F) where F: FnMut() {
+    f();
+}
diff --git a/src/test/ui/issues/issue-28971.stderr b/src/test/ui/issues/issue-28971.stderr
new file mode 100644
index 0000000..4781f7a
--- /dev/null
+++ b/src/test/ui/issues/issue-28971.stderr
@@ -0,0 +1,15 @@
+error[E0599]: no variant named `Baz` found for type `Foo` in the current scope
+  --> $DIR/issue-28971.rs:9:18
+   |
+LL | enum Foo {
+   | -------- variant `Baz` not found here
+...
+LL |             Foo::Baz(..) => (),
+   |                  ^^^
+   |                  |
+   |                  variant not found in `Foo`
+   |                  help: did you mean: `Bar`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/issues/issue-28992-empty.rs b/src/test/ui/issues/issue-28992-empty.rs
new file mode 100644
index 0000000..22961fc
--- /dev/null
+++ b/src/test/ui/issues/issue-28992-empty.rs
@@ -0,0 +1,16 @@
+// Can't use constants as tuple struct patterns
+
+
+const C1: i32 = 0;
+
+struct S;
+
+impl S {
+    const C2: i32 = 0;
+}
+
+fn main() {
+    if let C1(..) = 0 {} //~ ERROR expected tuple struct/variant, found constant `C1`
+    if let S::C2(..) = 0 {}
+    //~^ ERROR expected tuple struct/variant, found associated constant `<S>::C2`
+}
diff --git a/src/test/ui/issues/issue-28992-empty.stderr b/src/test/ui/issues/issue-28992-empty.stderr
new file mode 100644
index 0000000..68be372
--- /dev/null
+++ b/src/test/ui/issues/issue-28992-empty.stderr
@@ -0,0 +1,16 @@
+error[E0532]: expected tuple struct/variant, found constant `C1`
+  --> $DIR/issue-28992-empty.rs:13:12
+   |
+LL |     if let C1(..) = 0 {}
+   |            ^^ not a tuple struct/variant
+
+error[E0164]: expected tuple struct/variant, found associated constant `<S>::C2`
+  --> $DIR/issue-28992-empty.rs:14:12
+   |
+LL |     if let S::C2(..) = 0 {}
+   |            ^^^^^^^^^ not a tuple variant or struct
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0164, E0532.
+For more information about an error, try `rustc --explain E0164`.
diff --git a/src/test/ui/issues/issue-28999.rs b/src/test/ui/issues/issue-28999.rs
new file mode 100644
index 0000000..4f6fa41
--- /dev/null
+++ b/src/test/ui/issues/issue-28999.rs
@@ -0,0 +1,11 @@
+// compile-pass
+pub struct Xyz<'a, V> {
+    pub v: (V, &'a u32),
+}
+
+pub fn eq<'a, 's, 't, V>(this: &'s Xyz<'a, V>, other: &'t Xyz<'a, V>) -> bool
+        where V: PartialEq {
+    this.v == other.v
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-29030.rs b/src/test/ui/issues/issue-29030.rs
new file mode 100644
index 0000000..9ac7742
--- /dev/null
+++ b/src/test/ui/issues/issue-29030.rs
@@ -0,0 +1,9 @@
+// compile-pass
+#![allow(dead_code)]
+#[derive(Debug)]
+struct Message<'a, P: 'a = &'a [u8]> {
+    header: &'a [u8],
+    payload: P,
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-29037.rs b/src/test/ui/issues/issue-29037.rs
new file mode 100644
index 0000000..e0eb71f
--- /dev/null
+++ b/src/test/ui/issues/issue-29037.rs
@@ -0,0 +1,24 @@
+// compile-pass
+#![allow(dead_code)]
+// This test ensures that each pointer type `P<X>` is covariant in `X`.
+
+use std::rc::Rc;
+use std::sync::Arc;
+
+fn a<'r>(x: Box<&'static str>) -> Box<&'r str> {
+    x
+}
+
+fn b<'r, 'w>(x: &'w &'static str) -> &'w &'r str {
+    x
+}
+
+fn c<'r>(x: Arc<&'static str>) -> Arc<&'r str> {
+    x
+}
+
+fn d<'r>(x: Rc<&'static str>) -> Rc<&'r str> {
+    x
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-2904.rs b/src/test/ui/issues/issue-2904.rs
new file mode 100644
index 0000000..7755b7e
--- /dev/null
+++ b/src/test/ui/issues/issue-2904.rs
@@ -0,0 +1,79 @@
+// compile-pass
+#![allow(unused_must_use)]
+#![allow(dead_code)]
+#![allow(unused_mut)]
+#![allow(non_camel_case_types)]
+
+// Map representation
+
+use std::fmt;
+use std::io::prelude::*;
+use square::{bot, wall, rock, lambda, closed_lift, open_lift, earth, empty};
+
+enum square {
+    bot,
+    wall,
+    rock,
+    lambda,
+    closed_lift,
+    open_lift,
+    earth,
+    empty
+}
+
+impl fmt::Debug for square {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{}", match *self {
+          bot => { "R".to_string() }
+          wall => { "#".to_string() }
+          rock => { "*".to_string() }
+          lambda => { "\\".to_string() }
+          closed_lift => { "L".to_string() }
+          open_lift => { "O".to_string() }
+          earth => { ".".to_string() }
+          empty => { " ".to_string() }
+        })
+    }
+}
+
+fn square_from_char(c: char) -> square {
+    match c  {
+      'R'  => { bot }
+      '#'  => { wall }
+      '*'  => { rock }
+      '\\' => { lambda }
+      'L'  => { closed_lift }
+      'O'  => { open_lift }
+      '.'  => { earth }
+      ' '  => { empty }
+      _ => {
+        println!("invalid square: {}", c);
+        panic!()
+      }
+    }
+}
+
+fn read_board_grid<rdr:'static + Read>(mut input: rdr)
+                   -> Vec<Vec<square>> {
+    let mut input: &mut Read = &mut input;
+    let mut grid = Vec::new();
+    let mut line = [0; 10];
+    input.read(&mut line);
+    let mut row = Vec::new();
+    for c in &line {
+        row.push(square_from_char(*c as char))
+    }
+    grid.push(row);
+    let width = grid[0].len();
+    for row in &grid { assert_eq!(row.len(), width) }
+    grid
+}
+
+mod test {
+    #[test]
+    pub fn trivial_to_string() {
+        assert_eq!(lambda.to_string(), "\\")
+    }
+}
+
+pub fn main() {}
diff --git a/src/test/ui/issues/issue-29048.rs b/src/test/ui/issues/issue-29048.rs
new file mode 100644
index 0000000..6c4b618
--- /dev/null
+++ b/src/test/ui/issues/issue-29048.rs
@@ -0,0 +1,12 @@
+// compile-pass
+pub struct Chan;
+pub struct ChanSelect<'c, T> {
+    chans: Vec<(&'c Chan, T)>,
+}
+impl<'c, T> ChanSelect<'c, T> {
+    pub fn add_recv_ret(&mut self, chan: &'c Chan, ret: T)
+    {
+        self.chans.push((chan, ret));
+    }
+}
+fn main() {}
diff --git a/src/test/ui/issues/issue-29071.rs b/src/test/ui/issues/issue-29071.rs
new file mode 100644
index 0000000..1ea4a54
--- /dev/null
+++ b/src/test/ui/issues/issue-29071.rs
@@ -0,0 +1,16 @@
+// compile-pass
+#![allow(dead_code)]
+#![allow(non_upper_case_globals)]
+
+fn ret() -> u32 {
+    static x: u32 = 10;
+    x & if true { 10u32 } else { 20u32 } & x
+}
+
+fn ret2() -> &'static u32 {
+    static x: u32 = 10;
+    if true { 10u32; } else { 20u32; }
+    &x
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-29084.rs b/src/test/ui/issues/issue-29084.rs
new file mode 100644
index 0000000..86b348d
--- /dev/null
+++ b/src/test/ui/issues/issue-29084.rs
@@ -0,0 +1,15 @@
+macro_rules! foo {
+    ($d:expr) => {{
+        fn bar(d: u8) { }
+        bar(&mut $d);
+        //~^ ERROR mismatched types
+        //~| expected u8, found &mut u8
+        //~| expected type `u8`
+        //~| found type `&mut u8`
+    }}
+}
+
+fn main() {
+    foo!(0u8);
+    //~^ in this expansion of foo!
+}
diff --git a/src/test/ui/issues/issue-29084.stderr b/src/test/ui/issues/issue-29084.stderr
new file mode 100644
index 0000000..cb4bf6a
--- /dev/null
+++ b/src/test/ui/issues/issue-29084.stderr
@@ -0,0 +1,15 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-29084.rs:4:13
+   |
+LL |         bar(&mut $d);
+   |             ^^^^^^^ expected u8, found &mut u8
+...
+LL |     foo!(0u8);
+   |     ---------- in this macro invocation
+   |
+   = note: expected type `u8`
+              found type `&mut u8`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-29124.rs b/src/test/ui/issues/issue-29124.rs
new file mode 100644
index 0000000..1cd3f84
--- /dev/null
+++ b/src/test/ui/issues/issue-29124.rs
@@ -0,0 +1,19 @@
+struct Ret;
+struct Obj;
+
+impl Obj {
+    fn func() -> Ret {
+        Ret
+    }
+}
+
+fn func() -> Ret {
+    Ret
+}
+
+fn main() {
+    Obj::func.x();
+    //~^ ERROR no method named `x` found for type `fn() -> Ret {Obj::func}` in the current scope
+    func.x();
+    //~^ ERROR no method named `x` found for type `fn() -> Ret {func}` in the current scope
+}
diff --git a/src/test/ui/issues/issue-29124.stderr b/src/test/ui/issues/issue-29124.stderr
new file mode 100644
index 0000000..3beb728
--- /dev/null
+++ b/src/test/ui/issues/issue-29124.stderr
@@ -0,0 +1,19 @@
+error[E0599]: no method named `x` found for type `fn() -> Ret {Obj::func}` in the current scope
+  --> $DIR/issue-29124.rs:15:15
+   |
+LL |     Obj::func.x();
+   |               ^
+   |
+   = note: Obj::func is a function, perhaps you wish to call it
+
+error[E0599]: no method named `x` found for type `fn() -> Ret {func}` in the current scope
+  --> $DIR/issue-29124.rs:17:10
+   |
+LL |     func.x();
+   |          ^
+   |
+   = note: func is a function, perhaps you wish to call it
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/issues/issue-29147.rs b/src/test/ui/issues/issue-29147.rs
new file mode 100644
index 0000000..7ec96b9
--- /dev/null
+++ b/src/test/ui/issues/issue-29147.rs
@@ -0,0 +1,22 @@
+#![recursion_limit="1024"]
+
+pub struct S0<T>(T,T);
+pub struct S1<T>(Option<Box<S0<S0<T>>>>,Option<Box<S0<S0<T>>>>);
+pub struct S2<T>(Option<Box<S1<S1<T>>>>,Option<Box<S1<S1<T>>>>);
+pub struct S3<T>(Option<Box<S2<S2<T>>>>,Option<Box<S2<S2<T>>>>);
+pub struct S4<T>(Option<Box<S3<S3<T>>>>,Option<Box<S3<S3<T>>>>);
+pub struct S5<T>(Option<Box<S4<S4<T>>>>,Option<Box<S4<S4<T>>>>,Option<T>);
+
+trait Foo { fn xxx(&self); }
+trait Bar {} // anything local or #[fundamental]
+
+impl<T> Foo for T where T: Bar, T: Sync {
+    fn xxx(&self) {}
+}
+
+impl Foo for S5<u32> { fn xxx(&self) {} }
+impl Foo for S5<u64> { fn xxx(&self) {} }
+
+fn main() {
+    let _ = <S5<_>>::xxx; //~ ERROR cannot resolve `S5<_>: Foo`
+}
diff --git a/src/test/ui/issues/issue-29147.stderr b/src/test/ui/issues/issue-29147.stderr
new file mode 100644
index 0000000..3b42186
--- /dev/null
+++ b/src/test/ui/issues/issue-29147.stderr
@@ -0,0 +1,15 @@
+error[E0283]: type annotations required: cannot resolve `S5<_>: Foo`
+  --> $DIR/issue-29147.rs:21:13
+   |
+LL |     let _ = <S5<_>>::xxx;
+   |             ^^^^^^^^^^^^
+   |
+note: required by `Foo::xxx`
+  --> $DIR/issue-29147.rs:10:13
+   |
+LL | trait Foo { fn xxx(&self); }
+   |             ^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0283`.
diff --git a/src/test/ui/issues/issue-29161.rs b/src/test/ui/issues/issue-29161.rs
new file mode 100644
index 0000000..d80405a
--- /dev/null
+++ b/src/test/ui/issues/issue-29161.rs
@@ -0,0 +1,15 @@
+mod a {
+    struct A;
+
+    impl Default for A {
+        pub fn default() -> A { //~ ERROR unnecessary visibility qualifier
+            A
+        }
+    }
+}
+
+
+fn main() {
+    a::A::default();
+    //~^ ERROR struct `A` is private
+ }
diff --git a/src/test/ui/issues/issue-29161.stderr b/src/test/ui/issues/issue-29161.stderr
new file mode 100644
index 0000000..50c257a
--- /dev/null
+++ b/src/test/ui/issues/issue-29161.stderr
@@ -0,0 +1,16 @@
+error[E0449]: unnecessary visibility qualifier
+  --> $DIR/issue-29161.rs:5:9
+   |
+LL |         pub fn default() -> A {
+   |         ^^^ `pub` not permitted here because it's implied
+
+error[E0603]: struct `A` is private
+  --> $DIR/issue-29161.rs:13:8
+   |
+LL |     a::A::default();
+   |        ^
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0449, E0603.
+For more information about an error, try `rustc --explain E0449`.
diff --git a/src/test/ui/issues/issue-29181.rs b/src/test/ui/issues/issue-29181.rs
new file mode 100644
index 0000000..45752ad
--- /dev/null
+++ b/src/test/ui/issues/issue-29181.rs
@@ -0,0 +1,7 @@
+// aux-build:issue-29181.rs
+
+extern crate issue_29181 as foo;
+
+fn main() {
+    0.homura(); //~ ERROR no method named `homura` found
+}
diff --git a/src/test/ui/issues/issue-29181.stderr b/src/test/ui/issues/issue-29181.stderr
new file mode 100644
index 0000000..0920142
--- /dev/null
+++ b/src/test/ui/issues/issue-29181.stderr
@@ -0,0 +1,9 @@
+error[E0599]: no method named `homura` found for type `{integer}` in the current scope
+  --> $DIR/issue-29181.rs:6:7
+   |
+LL |     0.homura();
+   |       ^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/issues/issue-29184.rs b/src/test/ui/issues/issue-29184.rs
new file mode 100644
index 0000000..c77e364
--- /dev/null
+++ b/src/test/ui/issues/issue-29184.rs
@@ -0,0 +1,3 @@
+fn main() {
+    let x: typeof(92) = 92; //~ ERROR `typeof` is a reserved keyword
+}
diff --git a/src/test/ui/issues/issue-29184.stderr b/src/test/ui/issues/issue-29184.stderr
new file mode 100644
index 0000000..87d3632
--- /dev/null
+++ b/src/test/ui/issues/issue-29184.stderr
@@ -0,0 +1,9 @@
+error[E0516]: `typeof` is a reserved keyword but unimplemented
+  --> $DIR/issue-29184.rs:2:12
+   |
+LL |     let x: typeof(92) = 92;
+   |            ^^^^^^^^^^ reserved keyword
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0516`.
diff --git a/src/test/ui/issues/issue-29276.rs b/src/test/ui/issues/issue-29276.rs
new file mode 100644
index 0000000..2a0358b
--- /dev/null
+++ b/src/test/ui/issues/issue-29276.rs
@@ -0,0 +1,5 @@
+// compile-pass
+#![allow(dead_code)]
+struct S([u8; { struct Z; 0 }]);
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-2937.rs b/src/test/ui/issues/issue-2937.rs
new file mode 100644
index 0000000..335df5c
--- /dev/null
+++ b/src/test/ui/issues/issue-2937.rs
@@ -0,0 +1,6 @@
+use m::f as x; //~ ERROR unresolved import `m::f` [E0432]
+               //~^ no `f` in `m`
+
+mod m {}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-2937.stderr b/src/test/ui/issues/issue-2937.stderr
new file mode 100644
index 0000000..4286348
--- /dev/null
+++ b/src/test/ui/issues/issue-2937.stderr
@@ -0,0 +1,9 @@
+error[E0432]: unresolved import `m::f`
+  --> $DIR/issue-2937.rs:1:5
+   |
+LL | use m::f as x;
+   |     ^^^^^^^^^ no `f` in `m`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/issues/issue-2951.rs b/src/test/ui/issues/issue-2951.rs
new file mode 100644
index 0000000..e0ae3ff
--- /dev/null
+++ b/src/test/ui/issues/issue-2951.rs
@@ -0,0 +1,11 @@
+fn foo<T, U>(x: T, y: U) {
+    let mut xx = x;
+    xx = y;
+    //~^  ERROR mismatched types
+    //~| expected type `T`
+    //~| found type `U`
+    //~| expected type parameter, found a different type parameter
+}
+
+fn main() {
+}
diff --git a/src/test/ui/issues/issue-2951.stderr b/src/test/ui/issues/issue-2951.stderr
new file mode 100644
index 0000000..58e28c1
--- /dev/null
+++ b/src/test/ui/issues/issue-2951.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-2951.rs:3:10
+   |
+LL |     xx = y;
+   |          ^ expected type parameter, found a different type parameter
+   |
+   = note: expected type `T`
+              found type `U`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-29516.rs b/src/test/ui/issues/issue-29516.rs
new file mode 100644
index 0000000..8082694
--- /dev/null
+++ b/src/test/ui/issues/issue-29516.rs
@@ -0,0 +1,19 @@
+// compile-pass
+#![feature(optin_builtin_traits)]
+
+auto trait NotSame {}
+
+impl<A> !NotSame for (A, A) {}
+
+trait OneOfEach {}
+
+impl<A> OneOfEach for (A,) {}
+
+impl<A, B> OneOfEach for (A, B)
+where
+    (B,): OneOfEach,
+    (A, B): NotSame,
+{
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-29540.rs b/src/test/ui/issues/issue-29540.rs
new file mode 100644
index 0000000..b68205e
--- /dev/null
+++ b/src/test/ui/issues/issue-29540.rs
@@ -0,0 +1,492 @@
+// compile-pass
+#[derive(Debug)]
+pub struct Config {
+    pub name: String,
+    pub cluster: String,
+    pub debug_none: String,
+    pub debug_lockdep: String,
+    pub debug_context: String,
+    pub debug_crush: String,
+    pub debug_mds: String,
+    pub debug_mds_balancer: String,
+    pub debug_mds_locker: String,
+    pub debug_mds_log: String,
+    pub debug_mds_log_expire: String,
+    pub debug_mds_migrator: String,
+    pub debug_buffer: String,
+    pub debug_timer: String,
+    pub debug_filer: String,
+    pub debug_striper: String,
+    pub debug_objecter: String,
+    pub debug_rados: String,
+    pub debug_rbd: String,
+    pub debug_journaler: String,
+    pub debug_objectcacher: String,
+    pub debug_client: String,
+    pub debug_osd: String,
+    pub debug_optracker: String,
+    pub debug_objclass: String,
+    pub debug_filestore: String,
+    pub debug_keyvaluestore: String,
+    pub debug_journal: String,
+    pub debug_ms: String,
+    pub debug_mon: String,
+    pub debug_monc: String,
+    pub debug_paxos: String,
+    pub debug_tp: String,
+    pub debug_auth: String,
+    pub debug_crypto: String,
+    pub debug_finisher: String,
+    pub debug_heartbeatmap: String,
+    pub debug_perfcounter: String,
+    pub debug_rgw: String,
+    pub debug_civetweb: String,
+    pub debug_javaclient: String,
+    pub debug_asok: String,
+    pub debug_throttle: String,
+    pub host: String,
+    pub fsid: String,
+    pub public_addr: String,
+    pub cluster_addr: String,
+    pub public_network: String,
+    pub cluster_network: String,
+    pub num_client: String,
+    pub monmap: String,
+    pub mon_host: String,
+    pub lockdep: String,
+    pub run_dir: String,
+    pub admin_socket: String,
+    pub daemonize: String,
+    pub pid_file: String,
+    pub chdir: String,
+    pub max_open_files: String,
+    pub restapi_log_level: String,
+    pub restapi_base_url: String,
+    pub fatal_signal_handlers: String,
+    pub log_file: String,
+    pub log_max_new: String,
+    pub log_max_recent: String,
+    pub log_to_stderr: String,
+    pub err_to_stderr: String,
+    pub log_to_syslog: String,
+    pub err_to_syslog: String,
+    pub log_flush_on_exit: String,
+    pub log_stop_at_utilization: String,
+    pub clog_to_monitors: String,
+    pub clog_to_syslog: String,
+    pub clog_to_syslog_level: String,
+    pub clog_to_syslog_facility: String,
+    pub mon_cluster_log_to_syslog: String,
+    pub mon_cluster_log_to_syslog_level: String,
+    pub mon_cluster_log_to_syslog_facility: String,
+    pub mon_cluster_log_file: String,
+    pub mon_cluster_log_file_level: String,
+    pub key: String,
+    pub keyfile: String,
+    pub keyring: String,
+    pub heartbeat_interval: String,
+    pub heartbeat_file: String,
+    pub heartbeat_inject_failure: String,
+    pub perf: String,
+    pub ms_tcp_nodelay: String,
+    pub ms_tcp_rcvbuf: String,
+    pub ms_initial_backoff: String,
+    pub ms_max_backoff: String,
+    pub ms_nocrc: String,
+    pub ms_die_on_bad_msg: String,
+    pub ms_die_on_unhandled_msg: String,
+    pub ms_die_on_old_message: String,
+    pub ms_dispatch_throttle_bytes: String,
+    pub ms_bind_ipv6: String,
+    pub ms_bind_port_min: String,
+    pub ms_bind_port_max: String,
+    pub ms_rwthread_stack_bytes: String,
+    pub ms_tcp_read_timeout: String,
+    pub ms_pq_max_tokens_per_priority: String,
+    pub ms_pq_min_cost: String,
+    pub ms_inject_socket_failures: String,
+    pub ms_inject_delay_type: String,
+    pub ms_inject_delay_msg_type: String,
+    pub ms_inject_delay_max: String,
+    pub ms_inject_delay_probability: String,
+    pub ms_inject_internal_delays: String,
+    pub ms_dump_on_send: String,
+    pub inject_early_sigterm: String,
+    pub mon_data: String,
+    pub mon_initial_members: String,
+    pub mon_sync_fs_threshold: String,
+    pub mon_compact_on_start: String,
+    pub mon_compact_on_bootstrap: String,
+    pub mon_compact_on_trim: String,
+    pub mon_tick_interval: String,
+    pub mon_subscribe_interval: String,
+    pub mon_delta_reset_interval: String,
+    pub mon_osd_laggy_halflife: String,
+    pub mon_osd_laggy_weight: String,
+    pub mon_osd_adjust_heartbeat_grace: String,
+    pub mon_osd_adjust_down_out_interval: String,
+    pub mon_osd_auto_mark_in: String,
+    pub mon_osd_auto_mark_auto_out_in: String,
+    pub mon_osd_auto_mark_new_in: String,
+    pub mon_osd_down_out_interval: String,
+    pub mon_osd_down_out_subtree_limit: String,
+    pub mon_osd_min_up_ratio: String,
+    pub mon_osd_min_in_ratio: String,
+    pub mon_osd_max_op_age: String,
+    pub mon_osd_max_split_count: String,
+    pub mon_osd_allow_primary_temp: String,
+    pub mon_osd_allow_primary_affinity: String,
+    pub mon_stat_smooth_intervals: String,
+    pub mon_lease: String,
+    pub mon_lease_renew_interval: String,
+    pub mon_lease_ack_timeout: String,
+    pub mon_clock_drift_allowed: String,
+    pub mon_clock_drift_warn_backoff: String,
+    pub mon_timecheck_interval: String,
+    pub mon_accept_timeout: String,
+    pub mon_pg_create_interval: String,
+    pub mon_pg_stuck_threshold: String,
+    pub mon_pg_warn_min_per_osd: String,
+    pub mon_pg_warn_max_object_skew: String,
+    pub mon_pg_warn_min_objects: String,
+    pub mon_pg_warn_min_pool_objects: String,
+    pub mon_cache_target_full_warn_ratio: String,
+    pub mon_osd_full_ratio: String,
+    pub mon_osd_nearfull_ratio: String,
+    pub mon_globalid_prealloc: String,
+    pub mon_osd_report_timeout: String,
+    pub mon_force_standby_active: String,
+    pub mon_warn_on_old_mons: String,
+    pub mon_warn_on_legacy_crush_tunables: String,
+    pub mon_warn_on_osd_down_out_interval_zero: String,
+    pub mon_warn_on_cache_pools_without_hit_sets: String,
+    pub mon_min_osdmap_epochs: String,
+    pub mon_max_pgmap_epochs: String,
+    pub mon_max_log_epochs: String,
+    pub mon_max_mdsmap_epochs: String,
+    pub mon_max_osd: String,
+    pub mon_probe_timeout: String,
+    pub mon_slurp_timeout: String,
+    pub mon_slurp_bytes: String,
+    pub mon_client_bytes: String,
+    pub mon_daemon_bytes: String,
+    pub mon_max_log_entries_per_event: String,
+    pub mon_health_data_update_interval: String,
+    pub mon_data_avail_crit: String,
+    pub mon_data_avail_warn: String,
+    pub mon_config_key_max_entry_size: String,
+    pub mon_sync_timeout: String,
+    pub mon_sync_max_payload_size: String,
+    pub mon_sync_debug: String,
+    pub mon_sync_debug_leader: String,
+    pub mon_sync_debug_provider: String,
+    pub mon_sync_debug_provider_fallback: String,
+    pub mon_inject_sync_get_chunk_delay: String,
+    pub mon_osd_min_down_reporters: String,
+    pub mon_osd_min_down_reports: String,
+    pub mon_osd_force_trim_to: String,
+    pub mon_mds_force_trim_to: String,
+    pub mon_advanced_debug_mode: String,
+    pub mon_debug_dump_transactions: String,
+    pub mon_debug_dump_location: String,
+    pub mon_sync_provider_kill_at: String,
+    pub mon_sync_requester_kill_at: String,
+    pub mon_leveldb_write_buffer_size: String,
+    pub mon_leveldb_cache_size: String,
+    pub mon_leveldb_block_size: String,
+    pub mon_leveldb_bloom_size: String,
+    pub mon_leveldb_max_open_files: String,
+    pub mon_leveldb_compression: String,
+    pub mon_leveldb_paranoid: String,
+    pub mon_leveldb_log: String,
+    pub mon_leveldb_size_warn: String,
+    pub mon_force_quorum_join: String,
+    pub paxos_stash_full_interval: String,
+    pub paxos_max_join_drift: String,
+    pub paxos_propose_interval: String,
+    pub paxos_min_wait: String,
+    pub paxos_min: String,
+    pub paxos_trim_min: String,
+    pub paxos_trim_max: String,
+    pub paxos_service_trim_min: String,
+    pub paxos_service_trim_max: String,
+    pub paxos_kill_at: String,
+    pub clock_offset: String,
+    pub auth_cluster_required: String,
+    pub auth_service_required: String,
+    pub auth_client_required: String,
+    pub auth_supported: String,
+    pub cephx_require_signatures: String,
+    pub cephx_cluster_require_signatures: String,
+    pub cephx_service_require_signatures: String,
+    pub cephx_sign_messages: String,
+    pub auth_mon_ticket_ttl: String,
+    pub auth_service_ticket_ttl: String,
+    pub auth_debug: String,
+    pub mon_client_hunt_interval: String,
+    pub mon_client_ping_interval: String,
+    pub mon_client_ping_timeout: String,
+    pub mon_client_hunt_interval_backoff: String,
+    pub mon_client_hunt_interval_max_multiple: String,
+    pub mon_client_max_log_entries_per_message: String,
+    pub mon_max_pool_pg_num: String,
+    pub mon_pool_quota_warn_threshold: String,
+    pub mon_pool_quota_crit_threshold: String,
+    pub client_cache_size: String,
+    pub client_cache_mid: String,
+    pub client_use_random_mds: String,
+    pub client_mount_timeout: String,
+    pub client_tick_interval: String,
+    pub client_trace: String,
+    pub client_readahead_min: String,
+    pub client_readahead_max_bytes: String,
+    pub client_readahead_max_periods: String,
+    pub client_snapdir: String,
+    pub client_mountpoint: String,
+    pub client_notify_timeout: String,
+    pub osd_client_watch_timeout: String,
+    pub client_caps_release_delay: String,
+    pub client_oc: String,
+    pub client_oc_size: String,
+    pub client_oc_max_dirty: String,
+    pub client_oc_target_dirty: String,
+    pub client_oc_max_dirty_age: String,
+    pub client_oc_max_objects: String,
+    pub client_debug_force_sync_read: String,
+    pub client_debug_inject_tick_delay: String,
+    pub client_max_inline_size: String,
+    pub fuse_use_invalidate_cb: String,
+    pub fuse_allow_other: String,
+    pub fuse_default_permissions: String,
+    pub fuse_big_writes: String,
+    pub fuse_atomic_o_trunc: String,
+    pub fuse_debug: String,
+    pub fuse_multithreaded: String,
+    pub crush_location: String,
+    pub objecter_tick_interval: String,
+    pub objecter_timeout: String,
+    pub objecter_inflight_op_bytes: String,
+    pub objecter_inflight_ops: String,
+    pub journaler_allow_split_entries: String,
+    pub journaler_write_head_interval: String,
+    pub journaler_prefetch_periods: String,
+    pub journaler_prezero_periods: String,
+    pub journaler_batch_interval: String,
+    pub journaler_batch_max: String,
+    pub mds_data: String,
+    pub mds_max_file_size: String,
+    pub mds_cache_size: String,
+    pub mds_cache_mid: String,
+    pub mds_mem_max: String,
+    pub mds_dir_max_commit_size: String,
+    pub mds_decay_halflife: String,
+    pub mds_beacon_interval: String,
+    pub mds_beacon_grace: String,
+    pub mds_enforce_unique_name: String,
+    pub mds_blacklist_interval: String,
+    pub mds_session_timeout: String,
+    pub mds_freeze_tree_timeout: String,
+    pub mds_session_autoclose: String,
+    pub mds_reconnect_timeout: String,
+    pub mds_tick_interval: String,
+    pub mds_dirstat_min_interval: String,
+    pub mds_scatter_nudge_interval: String,
+    pub mds_client_prealloc_inos: String,
+    pub mds_early_reply: String,
+    pub mds_default_dir_hash: String,
+    pub mds_log: String,
+    pub mds_log_skip_corrupt_events: String,
+    pub mds_log_max_events: String,
+    pub mds_log_segment_size: String,
+    pub mds_log_max_segments: String,
+    pub mds_log_max_expiring: String,
+    pub mds_bal_sample_interval: String,
+    pub mds_bal_replicate_threshold: String,
+    pub mds_bal_unreplicate_threshold: String,
+    pub mds_bal_frag: String,
+    pub mds_bal_split_size: String,
+    pub mds_bal_split_rd: String,
+    pub mds_bal_split_wr: String,
+    pub mds_bal_split_bits: String,
+    pub mds_bal_merge_size: String,
+    pub mds_bal_merge_rd: String,
+    pub mds_bal_merge_wr: String,
+    pub mds_bal_interval: String,
+    pub mds_bal_fragment_interval: String,
+    pub mds_bal_idle_threshold: String,
+    pub mds_bal_max: String,
+    pub mds_bal_max_until: String,
+    pub mds_bal_mode: String,
+    pub mds_bal_min_rebalance: String,
+    pub mds_bal_min_start: String,
+    pub mds_bal_need_min: String,
+    pub mds_bal_need_max: String,
+    pub mds_bal_midchunk: String,
+    pub mds_bal_minchunk: String,
+    pub mds_bal_target_removal_min: String,
+    pub mds_bal_target_removal_max: String,
+    pub mds_replay_interval: String,
+    pub mds_shutdown_check: String,
+    pub mds_thrash_exports: String,
+    pub mds_thrash_fragments: String,
+    pub mds_dump_cache_on_map: String,
+    pub mds_dump_cache_after_rejoin: String,
+    pub mds_verify_scatter: String,
+    pub mds_debug_scatterstat: String,
+    pub mds_debug_frag: String,
+    pub mds_debug_auth_pins: String,
+    pub mds_debug_subtrees: String,
+    pub mds_kill_mdstable_at: String,
+    pub mds_kill_export_at: String,
+    pub mds_kill_import_at: String,
+    pub mds_kill_link_at: String,
+    pub mds_kill_rename_at: String,
+    pub mds_kill_openc_at: String,
+    pub mds_kill_journal_at: String,
+    pub mds_kill_journal_expire_at: String,
+    pub mds_kill_journal_replay_at: String,
+    pub mds_kill_create_at: String,
+    pub mds_open_remote_link_mode: String,
+    pub mds_inject_traceless_reply_probability: String,
+    pub mds_wipe_sessions: String,
+    pub mds_wipe_ino_prealloc: String,
+    pub mds_skip_ino: String,
+    pub max_mds: String,
+    pub mds_standby_for_name: String,
+    pub mds_standby_for_rank: String,
+    pub mds_standby_replay: String,
+    pub osd_compact_leveldb_on_mount: String,
+    pub osd_max_backfills: String,
+    pub osd_backfill_full_ratio: String,
+    pub osd_backfill_retry_interval: String,
+    pub osd_agent_max_ops: String,
+    pub osd_agent_min_evict_effort: String,
+    pub osd_agent_quantize_effort: String,
+    pub osd_agent_delay_time: String,
+    pub osd_agent_hist_halflife: String,
+    pub osd_agent_slop: String,
+    pub osd_uuid: String,
+    pub osd_data: String,
+    pub osd_journal: String,
+    pub osd_journal_size: String,
+    pub osd_max_write_size: String,
+    pub osd_max_pgls: String,
+    pub osd_client_message_size_cap: String,
+    pub osd_client_message_cap: String,
+    pub osd_pg_bits: String,
+    pub osd_pgp_bits: String,
+    pub osd_crush_chooseleaf_type: String,
+    pub osd_pool_default_crush_rule: String,
+    pub osd_pool_default_crush_replicated_ruleset: String,
+    pub osd_pool_erasure_code_stripe_width: String,
+    pub osd_pool_default_size: String,
+    pub osd_pool_default_min_size: String,
+    pub osd_pool_default_pg_num: String,
+    pub osd_pool_default_pgp_num: String,
+    pub osd_pool_default_erasure_code_directory: String,
+    pub osd_pool_default_erasure_code_profile: String,
+    pub osd_erasure_code_plugins: String,
+    pub osd_pool_default_flags: String,
+    pub osd_pool_default_flag_hashpspool: String,
+    pub osd_pool_default_hit_set_bloom_fpp: String,
+    pub osd_pool_default_cache_target_dirty_ratio: String,
+    pub osd_pool_default_cache_target_full_ratio: String,
+    pub osd_pool_default_cache_min_flush_age: String,
+    pub osd_pool_default_cache_min_evict_age: String,
+    pub osd_hit_set_min_size: String,
+    pub osd_hit_set_max_size: String,
+    pub osd_hit_set_namespace: String,
+    pub osd_tier_default_cache_mode: String,
+    pub osd_tier_default_cache_hit_set_count: String,
+    pub osd_tier_default_cache_hit_set_period: String,
+    pub osd_tier_default_cache_hit_set_type: String,
+    pub osd_map_dedup: String,
+    pub osd_map_max_advance: String,
+    pub osd_map_cache_size: String,
+    pub osd_map_message_max: String,
+    pub osd_map_share_max_epochs: String,
+    pub osd_op_threads: String,
+    pub osd_peering_wq_batch_size: String,
+    pub osd_op_pq_max_tokens_per_priority: String,
+    pub osd_op_pq_min_cost: String,
+    pub osd_disk_threads: String,
+    pub osd_disk_thread_ioprio_class: String,
+    pub osd_disk_thread_ioprio_priority: String,
+    pub osd_recovery_threads: String,
+    pub osd_recover_clone_overlap: String,
+    pub osd_recover_clone_overlap_limit: String,
+    pub osd_backfill_scan_min: String,
+    pub osd_backfill_scan_max: String,
+    pub osd_op_thread_timeout: String,
+    pub osd_recovery_thread_timeout: String,
+    pub osd_snap_trim_thread_timeout: String,
+    pub osd_snap_trim_sleep: String,
+    pub osd_scrub_thread_timeout: String,
+    pub osd_scrub_finalize_thread_timeout: String,
+    pub osd_scrub_invalid_stats: String,
+    pub osd_remove_thread_timeout: String,
+    pub osd_command_thread_timeout: String,
+    pub osd_age: String,
+    pub osd_age_time: String,
+    pub osd_heartbeat_addr: String,
+    pub osd_heartbeat_interval: String,
+    pub osd_heartbeat_grace: String,
+    pub osd_heartbeat_min_peers: String,
+    pub osd_pg_max_concurrent_snap_trims: String,
+    pub osd_heartbeat_min_healthy_ratio: String,
+    pub osd_mon_heartbeat_interval: String,
+    pub osd_mon_report_interval_max: String,
+    pub osd_mon_report_interval_min: String,
+    pub osd_pg_stat_report_interval_max: String,
+    pub osd_mon_ack_timeout: String,
+    pub osd_default_data_pool_replay_window: String,
+    pub osd_preserve_trimmed_log: String,
+    pub osd_auto_mark_unfound_lost: String,
+    pub osd_recovery_delay_start: String,
+    pub osd_recovery_max_active: String,
+    pub osd_recovery_max_single_start: String,
+    pub osd_recovery_max_chunk: String,
+    pub osd_copyfrom_max_chunk: String,
+    pub osd_push_per_object_cost: String,
+    pub osd_max_push_cost: String,
+    pub osd_max_push_objects: String,
+    pub osd_recovery_forget_lost_objects: String,
+    pub osd_max_scrubs: String,
+    pub osd_scrub_load_threshold: String,
+    pub osd_scrub_min_interval: String,
+    pub osd_scrub_max_interval: String,
+    pub osd_scrub_chunk_min: String,
+    pub osd_scrub_chunk_max: String,
+    pub osd_scrub_sleep: String,
+    pub osd_deep_scrub_interval: String,
+    pub osd_deep_scrub_stride: String,
+    pub osd_scan_list_ping_tp_interval: String,
+    pub osd_auto_weight: String,
+    pub osd_class_dir: String,
+    pub osd_open_classes_on_start: String,
+    pub osd_check_for_log_corruption: String,
+    pub osd_use_stale_snap: String,
+    pub osd_rollback_to_cluster_snap: String,
+    pub osd_default_notify_timeout: String,
+    pub osd_kill_backfill_at: String,
+    pub osd_pg_epoch_persisted_max_stale: String,
+    pub osd_min_pg_log_entries: String,
+    pub osd_max_pg_log_entries: String,
+    pub osd_op_complaint_time: String,
+    pub osd_command_max_records: String,
+    pub osd_op_log_threshold: String,
+    pub osd_verify_sparse_read_holes: String,
+    pub osd_debug_drop_ping_probability: String,
+    pub osd_debug_drop_ping_duration: String,
+    pub osd_debug_drop_pg_create_probability: String,
+    pub osd_debug_drop_pg_create_duration: String,
+    pub osd_debug_drop_op_probability: String,
+    pub osd_debug_op_order: String,
+    pub osd_debug_verify_snaps_on_info: String,
+    pub osd_debug_verify_stray_on_activate: String,
+    pub osd_debug_skip_full_check_in_backfill_reservation: String,
+    pub osd_debug_reject_backfill_probability: String,
+    pub osd_enable_op_tracker: String,
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-29710.rs b/src/test/ui/issues/issue-29710.rs
new file mode 100644
index 0000000..58907e7
--- /dev/null
+++ b/src/test/ui/issues/issue-29710.rs
@@ -0,0 +1,11 @@
+// compile-pass
+#![deny(unused_results)]
+#![allow(dead_code)]
+
+#[derive(Debug)]
+struct A(usize);
+
+#[derive(Debug)]
+struct B { a: usize }
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-29723.rs b/src/test/ui/issues/issue-29723.rs
new file mode 100644
index 0000000..41db52a
--- /dev/null
+++ b/src/test/ui/issues/issue-29723.rs
@@ -0,0 +1,16 @@
+#![feature(nll)]
+
+// test for https://github.com/rust-lang/rust/issues/29723
+
+fn main() {
+    let s = String::new();
+    let _s = match 0 {
+        0 if { drop(s); false } => String::from("oops"),
+        _ => {
+            // This should trigger an error,
+            // s could have been moved from.
+            s
+            //~^ ERROR use of moved value: `s`
+        }
+    };
+}
diff --git a/src/test/ui/issues/issue-29723.stderr b/src/test/ui/issues/issue-29723.stderr
new file mode 100644
index 0000000..7928af5
--- /dev/null
+++ b/src/test/ui/issues/issue-29723.stderr
@@ -0,0 +1,15 @@
+error[E0382]: use of moved value: `s`
+  --> $DIR/issue-29723.rs:12:13
+   |
+LL |     let s = String::new();
+   |         - move occurs because `s` has type `std::string::String`, which does not implement the `Copy` trait
+LL |     let _s = match 0 {
+LL |         0 if { drop(s); false } => String::from("oops"),
+   |                     - value moved here
+...
+LL |             s
+   |             ^ value used here after move
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/issues/issue-29740.rs b/src/test/ui/issues/issue-29740.rs
new file mode 100644
index 0000000..f37d868
--- /dev/null
+++ b/src/test/ui/issues/issue-29740.rs
@@ -0,0 +1,317 @@
+// compile-pass
+#![allow(dead_code)]
+// Regression test for #29740. Inefficient MIR matching algorithms
+// generated way too much code for this sort of case, leading to OOM.
+#![allow(non_snake_case)]
+
+pub mod KeyboardEventConstants {
+    pub const DOM_KEY_LOCATION_STANDARD: u32 = 0;
+    pub const DOM_KEY_LOCATION_LEFT: u32 = 1;
+    pub const DOM_KEY_LOCATION_RIGHT: u32 = 2;
+    pub const DOM_KEY_LOCATION_NUMPAD: u32 = 3;
+} // mod KeyboardEventConstants
+
+pub enum Key {
+    Space,
+    Apostrophe,
+    Comma,
+    Minus,
+    Period,
+    Slash,
+    Num0,
+    Num1,
+    Num2,
+    Num3,
+    Num4,
+    Num5,
+    Num6,
+    Num7,
+    Num8,
+    Num9,
+    Semicolon,
+    Equal,
+    A,
+    B,
+    C,
+    D,
+    E,
+    F,
+    G,
+    H,
+    I,
+    J,
+    K,
+    L,
+    M,
+    N,
+    O,
+    P,
+    Q,
+    R,
+    S,
+    T,
+    U,
+    V,
+    W,
+    X,
+    Y,
+    Z,
+    LeftBracket,
+    Backslash,
+    RightBracket,
+    GraveAccent,
+    World1,
+    World2,
+
+    Escape,
+    Enter,
+    Tab,
+    Backspace,
+    Insert,
+    Delete,
+    Right,
+    Left,
+    Down,
+    Up,
+    PageUp,
+    PageDown,
+    Home,
+    End,
+    CapsLock,
+    ScrollLock,
+    NumLock,
+    PrintScreen,
+    Pause,
+    F1,
+    F2,
+    F3,
+    F4,
+    F5,
+    F6,
+    F7,
+    F8,
+    F9,
+    F10,
+    F11,
+    F12,
+    F13,
+    F14,
+    F15,
+    F16,
+    F17,
+    F18,
+    F19,
+    F20,
+    F21,
+    F22,
+    F23,
+    F24,
+    F25,
+    Kp0,
+    Kp1,
+    Kp2,
+    Kp3,
+    Kp4,
+    Kp5,
+    Kp6,
+    Kp7,
+    Kp8,
+    Kp9,
+    KpDecimal,
+    KpDivide,
+    KpMultiply,
+    KpSubtract,
+    KpAdd,
+    KpEnter,
+    KpEqual,
+    LeftShift,
+    LeftControl,
+    LeftAlt,
+    LeftSuper,
+    RightShift,
+    RightControl,
+    RightAlt,
+    RightSuper,
+    Menu,
+}
+
+fn key_from_string(key_string: &str, location: u32) -> Option<Key> {
+    match key_string {
+        " " => Some(Key::Space),
+        "\"" => Some(Key::Apostrophe),
+        "'" => Some(Key::Apostrophe),
+        "<" => Some(Key::Comma),
+        "," => Some(Key::Comma),
+        "_" => Some(Key::Minus),
+        "-" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Minus),
+        ">" => Some(Key::Period),
+        "." if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Period),
+        "?" => Some(Key::Slash),
+        "/" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Slash),
+        "~" => Some(Key::GraveAccent),
+        "`" => Some(Key::GraveAccent),
+        ")" => Some(Key::Num0),
+        "0" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Num0),
+        "!" => Some(Key::Num1),
+        "1" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Num1),
+        "@" => Some(Key::Num2),
+        "2" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Num2),
+        "#" => Some(Key::Num3),
+        "3" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Num3),
+        "$" => Some(Key::Num4),
+        "4" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Num4),
+        "%" => Some(Key::Num5),
+        "5" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Num5),
+        "^" => Some(Key::Num6),
+        "6" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Num6),
+        "&" => Some(Key::Num7),
+        "7" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Num7),
+        "*" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Num8),
+        "8" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Num8),
+        "(" => Some(Key::Num9),
+        "9" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Num9),
+        ":" => Some(Key::Semicolon),
+        ";" => Some(Key::Semicolon),
+        "+" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Equal),
+        "=" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Equal),
+        "A" => Some(Key::A),
+        "a" => Some(Key::A),
+        "B" => Some(Key::B),
+        "b" => Some(Key::B),
+        "C" => Some(Key::C),
+        "c" => Some(Key::C),
+        "D" => Some(Key::D),
+        "d" => Some(Key::D),
+        "E" => Some(Key::E),
+        "e" => Some(Key::E),
+        "F" => Some(Key::F),
+        "f" => Some(Key::F),
+        "G" => Some(Key::G),
+        "g" => Some(Key::G),
+        "H" => Some(Key::H),
+        "h" => Some(Key::H),
+        "I" => Some(Key::I),
+        "i" => Some(Key::I),
+        "J" => Some(Key::J),
+        "j" => Some(Key::J),
+        "K" => Some(Key::K),
+        "k" => Some(Key::K),
+        "L" => Some(Key::L),
+        "l" => Some(Key::L),
+        "M" => Some(Key::M),
+        "m" => Some(Key::M),
+        "N" => Some(Key::N),
+        "n" => Some(Key::N),
+        "O" => Some(Key::O),
+        "o" => Some(Key::O),
+        "P" => Some(Key::P),
+        "p" => Some(Key::P),
+        "Q" => Some(Key::Q),
+        "q" => Some(Key::Q),
+        "R" => Some(Key::R),
+        "r" => Some(Key::R),
+        "S" => Some(Key::S),
+        "s" => Some(Key::S),
+        "T" => Some(Key::T),
+        "t" => Some(Key::T),
+        "U" => Some(Key::U),
+        "u" => Some(Key::U),
+        "V" => Some(Key::V),
+        "v" => Some(Key::V),
+        "W" => Some(Key::W),
+        "w" => Some(Key::W),
+        "X" => Some(Key::X),
+        "x" => Some(Key::X),
+        "Y" => Some(Key::Y),
+        "y" => Some(Key::Y),
+        "Z" => Some(Key::Z),
+        "z" => Some(Key::Z),
+        "{" => Some(Key::LeftBracket),
+        "[" => Some(Key::LeftBracket),
+        "|" => Some(Key::Backslash),
+        "\\" => Some(Key::Backslash),
+        "}" => Some(Key::RightBracket),
+        "]" => Some(Key::RightBracket),
+        "Escape" => Some(Key::Escape),
+        "Enter" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD
+                => Some(Key::Enter),
+        "Tab" => Some(Key::Tab),
+        "Backspace" => Some(Key::Backspace),
+        "Insert" => Some(Key::Insert),
+        "Delete" => Some(Key::Delete),
+        "ArrowRight" => Some(Key::Right),
+        "ArrowLeft" => Some(Key::Left),
+        "ArrowDown" => Some(Key::Down),
+        "ArrowUp" => Some(Key::Up),
+        "PageUp" => Some(Key::PageUp),
+        "PageDown" => Some(Key::PageDown),
+        "Home" => Some(Key::Home),
+        "End" => Some(Key::End),
+        "CapsLock" => Some(Key::CapsLock),
+        "ScrollLock" => Some(Key::ScrollLock),
+        "NumLock" => Some(Key::NumLock),
+        "PrintScreen" => Some(Key::PrintScreen),
+        "Pause" => Some(Key::Pause),
+        "F1" => Some(Key::F1),
+        "F2" => Some(Key::F2),
+        "F3" => Some(Key::F3),
+        "F4" => Some(Key::F4),
+        "F5" => Some(Key::F5),
+        "F6" => Some(Key::F6),
+        "F7" => Some(Key::F7),
+        "F8" => Some(Key::F8),
+        "F9" => Some(Key::F9),
+        "F10" => Some(Key::F10),
+        "F11" => Some(Key::F11),
+        "F12" => Some(Key::F12),
+        "F13" => Some(Key::F13),
+        "F14" => Some(Key::F14),
+        "F15" => Some(Key::F15),
+        "F16" => Some(Key::F16),
+        "F17" => Some(Key::F17),
+        "F18" => Some(Key::F18),
+        "F19" => Some(Key::F19),
+        "F20" => Some(Key::F20),
+        "F21" => Some(Key::F21),
+        "F22" => Some(Key::F22),
+        "F23" => Some(Key::F23),
+        "F24" => Some(Key::F24),
+        "F25" => Some(Key::F25),
+        "0" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::Kp0),
+        "1" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::Kp1),
+        "2" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::Kp2),
+        "3" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::Kp3),
+        "4" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::Kp4),
+        "5" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::Kp5),
+        "6" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::Kp6),
+        "7" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::Kp7),
+        "8" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::Kp8),
+        "9" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::Kp9),
+        "." if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::KpDecimal),
+        "/" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::KpDivide),
+        "*" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::KpMultiply),
+        "-" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::KpSubtract),
+        "+" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::KpAdd),
+        "Enter" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD
+                => Some(Key::KpEnter),
+        "=" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::KpEqual),
+        "Shift" if location == KeyboardEventConstants::DOM_KEY_LOCATION_LEFT
+                => Some(Key::LeftShift),
+        "Control" if location == KeyboardEventConstants::DOM_KEY_LOCATION_LEFT
+                => Some(Key::LeftControl),
+        "Alt" if location == KeyboardEventConstants::DOM_KEY_LOCATION_LEFT => Some(Key::LeftAlt),
+        "Super" if location == KeyboardEventConstants::DOM_KEY_LOCATION_LEFT
+                => Some(Key::LeftSuper),
+        "Shift" if location == KeyboardEventConstants::DOM_KEY_LOCATION_RIGHT
+                => Some(Key::RightShift),
+        "Control" if location == KeyboardEventConstants::DOM_KEY_LOCATION_RIGHT
+                => Some(Key::RightControl),
+        "Alt" if location == KeyboardEventConstants::DOM_KEY_LOCATION_RIGHT => Some(Key::RightAlt),
+        "Super" if location == KeyboardEventConstants::DOM_KEY_LOCATION_RIGHT
+                => Some(Key::RightSuper),
+        "ContextMenu" => Some(Key::Menu),
+        _ => None
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/issues/issue-29743.rs b/src/test/ui/issues/issue-29743.rs
new file mode 100644
index 0000000..5bc3b0c
--- /dev/null
+++ b/src/test/ui/issues/issue-29743.rs
@@ -0,0 +1,8 @@
+//
+// compile-pass
+
+fn main() {
+    let mut i = [1, 2, 3];
+    i[i[0]] = 0;
+    i[i[0] - 1] = 0;
+}
diff --git a/src/test/ui/issues/issue-29857.rs b/src/test/ui/issues/issue-29857.rs
new file mode 100644
index 0000000..5aff968
--- /dev/null
+++ b/src/test/ui/issues/issue-29857.rs
@@ -0,0 +1,21 @@
+// compile-pass
+// skip-codegen
+
+use std::marker::PhantomData;
+
+pub trait Foo<P> {}
+
+impl <P, T: Foo<P>> Foo<P> for Option<T> {}
+
+pub struct Qux<T> (PhantomData<*mut T>);
+
+impl<T> Foo<*mut T> for Option<Qux<T>> {}
+
+pub trait Bar {
+    type Output: 'static;
+}
+
+impl<T: 'static, W: Bar<Output = T>> Foo<*mut T> for W {}
+
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-29861.rs b/src/test/ui/issues/issue-29861.rs
new file mode 100644
index 0000000..58f8eb5
--- /dev/null
+++ b/src/test/ui/issues/issue-29861.rs
@@ -0,0 +1,20 @@
+pub trait MakeRef<'a> {
+    type Ref;
+}
+impl<'a, T: 'a> MakeRef<'a> for T {
+    type Ref = &'a T;
+}
+
+pub trait MakeRef2 {
+    type Ref2;
+}
+impl<'a, T: 'a> MakeRef2 for T {
+//~^ ERROR the lifetime parameter `'a` is not constrained
+    type Ref2 = <T as MakeRef<'a>>::Ref;
+}
+
+fn foo() -> <String as MakeRef2>::Ref2 { &String::from("foo") }
+
+fn main() {
+    println!("{}", foo());
+}
diff --git a/src/test/ui/issues/issue-29861.stderr b/src/test/ui/issues/issue-29861.stderr
new file mode 100644
index 0000000..d9d3cf3
--- /dev/null
+++ b/src/test/ui/issues/issue-29861.stderr
@@ -0,0 +1,9 @@
+error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates
+  --> $DIR/issue-29861.rs:11:6
+   |
+LL | impl<'a, T: 'a> MakeRef2 for T {
+   |      ^^ unconstrained lifetime parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0207`.
diff --git a/src/test/ui/issues/issue-2995.rs b/src/test/ui/issues/issue-2995.rs
new file mode 100644
index 0000000..0da7909
--- /dev/null
+++ b/src/test/ui/issues/issue-2995.rs
@@ -0,0 +1,5 @@
+fn bad (p: *const isize) {
+    let _q: &isize = p as &isize; //~ ERROR non-primitive cast
+}
+
+fn main() { }
diff --git a/src/test/ui/issues/issue-2995.stderr b/src/test/ui/issues/issue-2995.stderr
new file mode 100644
index 0000000..c316780
--- /dev/null
+++ b/src/test/ui/issues/issue-2995.stderr
@@ -0,0 +1,11 @@
+error[E0605]: non-primitive cast: `*const isize` as `&isize`
+  --> $DIR/issue-2995.rs:2:22
+   |
+LL |     let _q: &isize = p as &isize;
+   |                      ^^^^^^^^^^^
+   |
+   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0605`.
diff --git a/src/test/ui/issues/issue-30007.rs b/src/test/ui/issues/issue-30007.rs
new file mode 100644
index 0000000..918a821
--- /dev/null
+++ b/src/test/ui/issues/issue-30007.rs
@@ -0,0 +1,7 @@
+macro_rules! t {
+    () => ( String ; );     //~ ERROR macro expansion ignores token `;`
+}
+
+fn main() {
+    let i: Vec<t!()>;
+}
diff --git a/src/test/ui/issues/issue-30007.stderr b/src/test/ui/issues/issue-30007.stderr
new file mode 100644
index 0000000..87e770e
--- /dev/null
+++ b/src/test/ui/issues/issue-30007.stderr
@@ -0,0 +1,13 @@
+error: macro expansion ignores token `;` and any following
+  --> $DIR/issue-30007.rs:2:20
+   |
+LL |     () => ( String ; );
+   |                    ^
+...
+LL |     let i: Vec<t!()>;
+   |                ---- caused by the macro expansion here
+   |
+   = note: the usage of `t!` is likely invalid in type context
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-30079.rs b/src/test/ui/issues/issue-30079.rs
new file mode 100644
index 0000000..a02a932
--- /dev/null
+++ b/src/test/ui/issues/issue-30079.rs
@@ -0,0 +1,39 @@
+struct SemiPriv;
+
+mod m1 {
+    struct Priv;
+    impl ::SemiPriv {
+        pub fn f(_: Priv) {} //~ WARN private type `m1::Priv` in public interface
+        //~^ WARNING hard error
+    }
+
+    impl Priv {
+        pub fn f(_: Priv) {} // ok
+    }
+}
+
+mod m2 {
+    struct Priv;
+    impl ::std::ops::Deref for ::SemiPriv {
+        type Target = Priv; //~ ERROR private type `m2::Priv` in public interface
+        fn deref(&self) -> &Self::Target { unimplemented!() }
+    }
+
+    impl ::std::ops::Deref for Priv {
+        type Target = Priv; // ok
+        fn deref(&self) -> &Self::Target { unimplemented!() }
+    }
+}
+
+trait SemiPrivTrait {
+    type Assoc;
+}
+
+mod m3 {
+    struct Priv;
+    impl ::SemiPrivTrait for () {
+        type Assoc = Priv; //~ ERROR private type `m3::Priv` in public interface
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-30079.stderr b/src/test/ui/issues/issue-30079.stderr
new file mode 100644
index 0000000..57ca572
--- /dev/null
+++ b/src/test/ui/issues/issue-30079.stderr
@@ -0,0 +1,31 @@
+warning: private type `m1::Priv` in public interface (error E0446)
+  --> $DIR/issue-30079.rs:6:9
+   |
+LL |         pub fn f(_: Priv) {}
+   |         ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: #[warn(private_in_public)] on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
+
+error[E0446]: private type `m2::Priv` in public interface
+  --> $DIR/issue-30079.rs:18:9
+   |
+LL |     struct Priv;
+   |     - `m2::Priv` declared as private
+LL |     impl ::std::ops::Deref for ::SemiPriv {
+LL |         type Target = Priv;
+   |         ^^^^^^^^^^^^^^^^^^^ can't leak private type
+
+error[E0446]: private type `m3::Priv` in public interface
+  --> $DIR/issue-30079.rs:35:9
+   |
+LL |     struct Priv;
+   |     - `m3::Priv` declared as private
+LL |     impl ::SemiPrivTrait for () {
+LL |         type Assoc = Priv;
+   |         ^^^^^^^^^^^^^^^^^^ can't leak private type
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0446`.
diff --git a/src/test/ui/issues/issue-3008-1.rs b/src/test/ui/issues/issue-3008-1.rs
new file mode 100644
index 0000000..1124969
--- /dev/null
+++ b/src/test/ui/issues/issue-3008-1.rs
@@ -0,0 +1,12 @@
+enum Foo {
+    Foo_(Bar)
+}
+
+enum Bar {
+    //~^ ERROR recursive type `Bar` has infinite size
+    BarNone,
+    BarSome(Bar)
+}
+
+fn main() {
+}
diff --git a/src/test/ui/issues/issue-3008-1.stderr b/src/test/ui/issues/issue-3008-1.stderr
new file mode 100644
index 0000000..f122741
--- /dev/null
+++ b/src/test/ui/issues/issue-3008-1.stderr
@@ -0,0 +1,14 @@
+error[E0072]: recursive type `Bar` has infinite size
+  --> $DIR/issue-3008-1.rs:5:1
+   |
+LL | enum Bar {
+   | ^^^^^^^^ recursive type has infinite size
+...
+LL |     BarSome(Bar)
+   |             --- recursive without indirection
+   |
+   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Bar` representable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0072`.
diff --git a/src/test/ui/issues/issue-3008-2.rs b/src/test/ui/issues/issue-3008-2.rs
new file mode 100644
index 0000000..5846c69
--- /dev/null
+++ b/src/test/ui/issues/issue-3008-2.rs
@@ -0,0 +1,6 @@
+enum Foo { Foo_(Bar) }
+struct Bar { x: Bar }
+//~^ ERROR E0072
+
+fn main() {
+}
diff --git a/src/test/ui/issues/issue-3008-2.stderr b/src/test/ui/issues/issue-3008-2.stderr
new file mode 100644
index 0000000..acc15f4
--- /dev/null
+++ b/src/test/ui/issues/issue-3008-2.stderr
@@ -0,0 +1,13 @@
+error[E0072]: recursive type `Bar` has infinite size
+  --> $DIR/issue-3008-2.rs:2:1
+   |
+LL | struct Bar { x: Bar }
+   | ^^^^^^^^^^   ------ recursive without indirection
+   | |
+   | recursive type has infinite size
+   |
+   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Bar` representable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0072`.
diff --git a/src/test/ui/issues/issue-3008-3.rs b/src/test/ui/issues/issue-3008-3.rs
new file mode 100644
index 0000000..212eb2e
--- /dev/null
+++ b/src/test/ui/issues/issue-3008-3.rs
@@ -0,0 +1,10 @@
+use std::marker;
+
+enum E1 { V1(E2<E1>), }
+enum E2<T> { V2(E2<E1>, marker::PhantomData<T>), }
+//~^ ERROR recursive type `E2` has infinite size
+
+impl E1 { fn foo(&self) {} }
+
+fn main() {
+}
diff --git a/src/test/ui/issues/issue-3008-3.stderr b/src/test/ui/issues/issue-3008-3.stderr
new file mode 100644
index 0000000..d08a3d9
--- /dev/null
+++ b/src/test/ui/issues/issue-3008-3.stderr
@@ -0,0 +1,13 @@
+error[E0072]: recursive type `E2` has infinite size
+  --> $DIR/issue-3008-3.rs:4:1
+   |
+LL | enum E2<T> { V2(E2<E1>, marker::PhantomData<T>), }
+   | ^^^^^^^^^^      ------ recursive without indirection
+   | |
+   | recursive type has infinite size
+   |
+   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `E2` representable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0072`.
diff --git a/src/test/ui/issues/issue-30123.rs b/src/test/ui/issues/issue-30123.rs
new file mode 100644
index 0000000..4fc32e0
--- /dev/null
+++ b/src/test/ui/issues/issue-30123.rs
@@ -0,0 +1,9 @@
+// aux-build:issue-30123-aux.rs
+
+extern crate issue_30123_aux;
+use issue_30123_aux::*;
+
+fn main() {
+    let ug = Graph::<i32, i32>::new_undirected();
+    //~^ ERROR no function or associated item named `new_undirected` found for type
+}
diff --git a/src/test/ui/issues/issue-30123.stderr b/src/test/ui/issues/issue-30123.stderr
new file mode 100644
index 0000000..32bbd4d
--- /dev/null
+++ b/src/test/ui/issues/issue-30123.stderr
@@ -0,0 +1,9 @@
+error[E0599]: no function or associated item named `new_undirected` found for type `issue_30123_aux::Graph<i32, i32>` in the current scope
+  --> $DIR/issue-30123.rs:7:33
+   |
+LL |     let ug = Graph::<i32, i32>::new_undirected();
+   |                                 ^^^^^^^^^^^^^^ function or associated item not found in `issue_30123_aux::Graph<i32, i32>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/issues/issue-3021-b.rs b/src/test/ui/issues/issue-3021-b.rs
new file mode 100644
index 0000000..f1630af
--- /dev/null
+++ b/src/test/ui/issues/issue-3021-b.rs
@@ -0,0 +1,14 @@
+fn siphash(k0 : u64) {
+
+    struct SipHash {
+        v0: u64,
+    }
+
+    impl SipHash {
+        pub fn reset(&mut self) {
+           self.v0 = k0 ^ 0x736f6d6570736575; //~ ERROR can't capture dynamic environment
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-3021-b.stderr b/src/test/ui/issues/issue-3021-b.stderr
new file mode 100644
index 0000000..72289c5
--- /dev/null
+++ b/src/test/ui/issues/issue-3021-b.stderr
@@ -0,0 +1,11 @@
+error[E0434]: can't capture dynamic environment in a fn item
+  --> $DIR/issue-3021-b.rs:9:22
+   |
+LL |            self.v0 = k0 ^ 0x736f6d6570736575;
+   |                      ^^
+   |
+   = help: use the `|| { ... }` closure form instead
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0434`.
diff --git a/src/test/ui/issues/issue-3021-c.rs b/src/test/ui/issues/issue-3021-c.rs
new file mode 100644
index 0000000..94ed1fd
--- /dev/null
+++ b/src/test/ui/issues/issue-3021-c.rs
@@ -0,0 +1,9 @@
+fn siphash<T>() {
+
+    trait U {
+        fn g(&self, x: T) -> T;  //~ ERROR can't use generic parameters from outer function
+        //~^ ERROR can't use generic parameters from outer function
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-3021-c.stderr b/src/test/ui/issues/issue-3021-c.stderr
new file mode 100644
index 0000000..cef30ac
--- /dev/null
+++ b/src/test/ui/issues/issue-3021-c.stderr
@@ -0,0 +1,25 @@
+error[E0401]: can't use generic parameters from outer function
+  --> $DIR/issue-3021-c.rs:4:24
+   |
+LL | fn siphash<T>() {
+   |            - type variable from outer function
+...
+LL |         fn g(&self, x: T) -> T;
+   |            -           ^ use of generic parameter from outer function
+   |            |
+   |            help: try using a local generic parameter instead: `g<T>`
+
+error[E0401]: can't use generic parameters from outer function
+  --> $DIR/issue-3021-c.rs:4:30
+   |
+LL | fn siphash<T>() {
+   |            - type variable from outer function
+...
+LL |         fn g(&self, x: T) -> T;
+   |            -                 ^ use of generic parameter from outer function
+   |            |
+   |            help: try using a local generic parameter instead: `g<T>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0401`.
diff --git a/src/test/ui/issues/issue-3021-d.rs b/src/test/ui/issues/issue-3021-d.rs
new file mode 100644
index 0000000..1fb0002
--- /dev/null
+++ b/src/test/ui/issues/issue-3021-d.rs
@@ -0,0 +1,28 @@
+trait SipHash {
+    fn result(&self) -> u64;
+    fn reset(&self);
+}
+
+fn siphash(k0 : u64, k1 : u64) {
+    struct SipState {
+        v0: u64,
+        v1: u64,
+    }
+
+    fn mk_result(st : &SipState) -> u64 {
+
+        let v0 = st.v0;
+        let v1 = st.v1;
+        return v0 ^ v1;
+    }
+
+   impl SipHash for SipState {
+        fn reset(&self) {
+            self.v0 = k0 ^ 0x736f6d6570736575; //~ ERROR can't capture dynamic environment
+            self.v1 = k1 ^ 0x646f72616e646f6d; //~ ERROR can't capture dynamic environment
+        }
+        fn result(&self) -> u64 { return mk_result(self); }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-3021-d.stderr b/src/test/ui/issues/issue-3021-d.stderr
new file mode 100644
index 0000000..39e6e8c
--- /dev/null
+++ b/src/test/ui/issues/issue-3021-d.stderr
@@ -0,0 +1,19 @@
+error[E0434]: can't capture dynamic environment in a fn item
+  --> $DIR/issue-3021-d.rs:21:23
+   |
+LL |             self.v0 = k0 ^ 0x736f6d6570736575;
+   |                       ^^
+   |
+   = help: use the `|| { ... }` closure form instead
+
+error[E0434]: can't capture dynamic environment in a fn item
+  --> $DIR/issue-3021-d.rs:22:23
+   |
+LL |             self.v1 = k1 ^ 0x646f72616e646f6d;
+   |                       ^^
+   |
+   = help: use the `|| { ... }` closure form instead
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0434`.
diff --git a/src/test/ui/issues/issue-3021.rs b/src/test/ui/issues/issue-3021.rs
new file mode 100644
index 0000000..a672261
--- /dev/null
+++ b/src/test/ui/issues/issue-3021.rs
@@ -0,0 +1,18 @@
+trait SipHash {
+    fn reset(&self);
+}
+
+fn siphash(k0 : u64) {
+    struct SipState {
+        v0: u64,
+    }
+
+    impl SipHash for SipState {
+        fn reset(&self) {
+           self.v0 = k0 ^ 0x736f6d6570736575; //~ ERROR can't capture dynamic environment
+        }
+    }
+    panic!();
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-3021.stderr b/src/test/ui/issues/issue-3021.stderr
new file mode 100644
index 0000000..d5b015e
--- /dev/null
+++ b/src/test/ui/issues/issue-3021.stderr
@@ -0,0 +1,11 @@
+error[E0434]: can't capture dynamic environment in a fn item
+  --> $DIR/issue-3021.rs:12:22
+   |
+LL |            self.v0 = k0 ^ 0x736f6d6570736575;
+   |                      ^^
+   |
+   = help: use the `|| { ... }` closure form instead
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0434`.
diff --git a/src/test/ui/issues/issue-30225.rs b/src/test/ui/issues/issue-30225.rs
new file mode 100644
index 0000000..4231533
--- /dev/null
+++ b/src/test/ui/issues/issue-30225.rs
@@ -0,0 +1,38 @@
+// Regression test for #30225, which was an ICE that would trigger as
+// a result of a poor interaction between trait result caching and
+// type inference. Specifically, at that time, unification could cause
+// unrelated type variables to become instantiated, if subtyping
+// relationships existed. These relationships are now propagated
+// through obligations and hence everything works out fine.
+
+trait Foo<U,V> : Sized {
+    fn foo(self, u: Option<U>, v: Option<V>) {}
+}
+
+struct A;
+struct B;
+
+impl Foo<A, B> for () {}      // impl A
+impl Foo<u32, u32> for u32 {} // impl B, creating ambiguity
+
+fn toxic() {
+    // cache the resolution <() as Foo<$0,$1>> = impl A
+    let u = None;
+    let v = None;
+    Foo::foo((), u, v);
+}
+
+fn bomb() {
+    let mut u = None; // type is Option<$0>
+    let mut v = None; // type is Option<$1>
+    let mut x = None; // type is Option<$2>
+
+    Foo::foo(x.unwrap(),u,v); // register <$2 as Foo<$0, $1>>
+    u = v; // mark $0 and $1 in a subtype relationship
+    //~^ ERROR mismatched types
+    x = Some(()); // set $2 = (), allowing impl selection
+                  // to proceed for <() as Foo<$0, $1>> = impl A.
+                  // kaboom, this *used* to trigge an ICE
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-30225.stderr b/src/test/ui/issues/issue-30225.stderr
new file mode 100644
index 0000000..64a56e3
--- /dev/null
+++ b/src/test/ui/issues/issue-30225.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-30225.rs:31:9
+   |
+LL |     u = v; // mark $0 and $1 in a subtype relationship
+   |         ^ expected struct `A`, found struct `B`
+   |
+   = note: expected type `A`
+              found type `B`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-30236.rs b/src/test/ui/issues/issue-30236.rs
new file mode 100644
index 0000000..02f899b
--- /dev/null
+++ b/src/test/ui/issues/issue-30236.rs
@@ -0,0 +1,8 @@
+type Foo<
+    Unused //~ ERROR type parameter `Unused` is unused
+    > = u8;
+
+fn main() {
+
+}
+
diff --git a/src/test/ui/issues/issue-30236.stderr b/src/test/ui/issues/issue-30236.stderr
new file mode 100644
index 0000000..64cbd58
--- /dev/null
+++ b/src/test/ui/issues/issue-30236.stderr
@@ -0,0 +1,9 @@
+error[E0091]: type parameter `Unused` is unused
+  --> $DIR/issue-30236.rs:2:5
+   |
+LL |     Unused
+   |     ^^^^^^ unused type parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0091`.
diff --git a/src/test/ui/issues/issue-30240-b.rs b/src/test/ui/issues/issue-30240-b.rs
new file mode 100644
index 0000000..2df0684
--- /dev/null
+++ b/src/test/ui/issues/issue-30240-b.rs
@@ -0,0 +1,16 @@
+#![deny(unreachable_patterns)]
+
+fn main() {
+    match "world" {
+        "hello" => {}
+        _ => {},
+    }
+
+    match "world" {
+        ref _x if false => {}
+        "hello" => {}
+        "hello" => {} //~ ERROR unreachable pattern
+        _ => {},
+    }
+}
+
diff --git a/src/test/ui/issues/issue-30240-b.stderr b/src/test/ui/issues/issue-30240-b.stderr
new file mode 100644
index 0000000..e0dd479
--- /dev/null
+++ b/src/test/ui/issues/issue-30240-b.stderr
@@ -0,0 +1,14 @@
+error: unreachable pattern
+  --> $DIR/issue-30240-b.rs:12:9
+   |
+LL |         "hello" => {}
+   |         ^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/issue-30240-b.rs:1:9
+   |
+LL | #![deny(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-30240.rs b/src/test/ui/issues/issue-30240.rs
new file mode 100644
index 0000000..a0c0d16
--- /dev/null
+++ b/src/test/ui/issues/issue-30240.rs
@@ -0,0 +1,10 @@
+fn main() {
+    match "world" { //~ ERROR non-exhaustive patterns: `&_`
+        "hello" => {}
+    }
+
+    match "world" { //~ ERROR non-exhaustive patterns: `&_`
+        ref _x if false => {}
+        "hello" => {}
+    }
+}
diff --git a/src/test/ui/issues/issue-30240.stderr b/src/test/ui/issues/issue-30240.stderr
new file mode 100644
index 0000000..8b683b4
--- /dev/null
+++ b/src/test/ui/issues/issue-30240.stderr
@@ -0,0 +1,19 @@
+error[E0004]: non-exhaustive patterns: `&_` not covered
+  --> $DIR/issue-30240.rs:2:11
+   |
+LL |     match "world" {
+   |           ^^^^^^^ pattern `&_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `&_` not covered
+  --> $DIR/issue-30240.rs:6:11
+   |
+LL |     match "world" {
+   |           ^^^^^^^ pattern `&_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/issues/issue-30255.rs b/src/test/ui/issues/issue-30255.rs
new file mode 100644
index 0000000..6970a12
--- /dev/null
+++ b/src/test/ui/issues/issue-30255.rs
@@ -0,0 +1,24 @@
+//
+// Test that lifetime elision error messages correctly omit parameters
+// with no elided lifetimes
+
+struct S<'a> {
+    field: &'a i32,
+}
+
+fn f(a: &S, b: i32) -> &i32 {
+//~^ ERROR missing lifetime specifier [E0106]
+    panic!();
+}
+
+fn g(a: &S, b: bool, c: &i32) -> &i32 {
+//~^ ERROR missing lifetime specifier [E0106]
+    panic!();
+}
+
+fn h(a: &bool, b: bool, c: &S, d: &i32) -> &i32 {
+//~^ ERROR missing lifetime specifier [E0106]
+    panic!();
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-30255.stderr b/src/test/ui/issues/issue-30255.stderr
new file mode 100644
index 0000000..c53129b
--- /dev/null
+++ b/src/test/ui/issues/issue-30255.stderr
@@ -0,0 +1,27 @@
+error[E0106]: missing lifetime specifier
+  --> $DIR/issue-30255.rs:9:24
+   |
+LL | fn f(a: &S, b: i32) -> &i32 {
+   |                        ^ expected lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but the signature does not say which one of `a`'s 2 lifetimes it is borrowed from
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/issue-30255.rs:14:34
+   |
+LL | fn g(a: &S, b: bool, c: &i32) -> &i32 {
+   |                                  ^ expected lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from one of `a`'s 2 lifetimes or `c`
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/issue-30255.rs:19:44
+   |
+LL | fn h(a: &bool, b: bool, c: &S, d: &i32) -> &i32 {
+   |                                            ^ expected lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `a`, one of `c`'s 2 lifetimes, or `d`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0106`.
diff --git a/src/test/ui/issues/issue-30302.rs b/src/test/ui/issues/issue-30302.rs
new file mode 100644
index 0000000..c37d4f2
--- /dev/null
+++ b/src/test/ui/issues/issue-30302.rs
@@ -0,0 +1,20 @@
+#![allow(dead_code)]
+#![allow(unused_variables)]
+#![allow(non_snake_case)]
+#![deny(unreachable_patterns)]
+
+enum Stack<T> {
+    Nil,
+    Cons(T, Box<Stack<T>>)
+}
+
+fn is_empty<T>(s: Stack<T>) -> bool {
+    match s {
+        Nil => true,
+//~^ WARN pattern binding `Nil` is named the same as one of the variants of the type `Stack`
+        _ => false
+//~^ ERROR unreachable pattern
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-30302.stderr b/src/test/ui/issues/issue-30302.stderr
new file mode 100644
index 0000000..d762d6f
--- /dev/null
+++ b/src/test/ui/issues/issue-30302.stderr
@@ -0,0 +1,24 @@
+warning[E0170]: pattern binding `Nil` is named the same as one of the variants of the type `Stack`
+  --> $DIR/issue-30302.rs:13:9
+   |
+LL |         Nil => true,
+   |         ^^^ help: to match on the variant, qualify the path: `Stack::Nil`
+
+error: unreachable pattern
+  --> $DIR/issue-30302.rs:15:9
+   |
+LL |         Nil => true,
+   |         --- matches any value
+LL |
+LL |         _ => false
+   |         ^ unreachable pattern
+   |
+note: lint level defined here
+  --> $DIR/issue-30302.rs:4:9
+   |
+LL | #![deny(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0170`.
diff --git a/src/test/ui/issues/issue-30355.rs b/src/test/ui/issues/issue-30355.rs
new file mode 100644
index 0000000..6ff5b37
--- /dev/null
+++ b/src/test/ui/issues/issue-30355.rs
@@ -0,0 +1,9 @@
+pub struct X([u8]);
+
+pub static Y: &'static X = {
+    const Y: &'static [u8] = b"";
+    &X(*Y)
+    //~^ ERROR E0277
+};
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-30355.stderr b/src/test/ui/issues/issue-30355.stderr
new file mode 100644
index 0000000..48b151c
--- /dev/null
+++ b/src/test/ui/issues/issue-30355.stderr
@@ -0,0 +1,14 @@
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/issue-30355.rs:5:6
+   |
+LL |     &X(*Y)
+   |      ^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `[u8]`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: all function arguments must have a statically known size
+   = help: unsized locals are gated as an unstable feature
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-3038.rs b/src/test/ui/issues/issue-3038.rs
new file mode 100644
index 0000000..cf3ba00
--- /dev/null
+++ b/src/test/ui/issues/issue-3038.rs
@@ -0,0 +1,26 @@
+enum F { G(isize, isize) }
+
+enum H { I(J, K) }
+
+enum J { L(isize, isize) }
+enum K { M(isize, isize) }
+
+fn main()
+{
+
+    let _z = match F::G(1, 2) {
+      F::G(x, x) => { println!("{}", x + x); }
+      //~^ ERROR identifier `x` is bound more than once in the same pattern
+    };
+
+    let _z = match H::I(J::L(1, 2), K::M(3, 4)) {
+      H::I(J::L(x, _), K::M(_, x))
+      //~^ ERROR identifier `x` is bound more than once in the same pattern
+        => { println!("{}", x + x); }
+    };
+
+    let _z = match (1, 2) {
+        (x, x) => { x } //~ ERROR identifier `x` is bound more than once in the same pattern
+    };
+
+}
diff --git a/src/test/ui/issues/issue-3038.stderr b/src/test/ui/issues/issue-3038.stderr
new file mode 100644
index 0000000..210da2c
--- /dev/null
+++ b/src/test/ui/issues/issue-3038.stderr
@@ -0,0 +1,21 @@
+error[E0416]: identifier `x` is bound more than once in the same pattern
+  --> $DIR/issue-3038.rs:12:15
+   |
+LL |       F::G(x, x) => { println!("{}", x + x); }
+   |               ^ used in a pattern more than once
+
+error[E0416]: identifier `x` is bound more than once in the same pattern
+  --> $DIR/issue-3038.rs:17:32
+   |
+LL |       H::I(J::L(x, _), K::M(_, x))
+   |                                ^ used in a pattern more than once
+
+error[E0416]: identifier `x` is bound more than once in the same pattern
+  --> $DIR/issue-3038.rs:23:13
+   |
+LL |         (x, x) => { x }
+   |             ^ used in a pattern more than once
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0416`.
diff --git a/src/test/ui/issues/issue-30438-a.nll.stderr b/src/test/ui/issues/issue-30438-a.nll.stderr
new file mode 100644
index 0000000..53845af
--- /dev/null
+++ b/src/test/ui/issues/issue-30438-a.nll.stderr
@@ -0,0 +1,12 @@
+error[E0515]: cannot return reference to temporary value
+  --> $DIR/issue-30438-a.rs:12:16
+   |
+LL |         return &Test { s: &self.s};
+   |                ^------------------
+   |                ||
+   |                |temporary value created here
+   |                returns a reference to data owned by the current function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/src/test/ui/issues/issue-30438-a.rs b/src/test/ui/issues/issue-30438-a.rs
new file mode 100644
index 0000000..8900821
--- /dev/null
+++ b/src/test/ui/issues/issue-30438-a.rs
@@ -0,0 +1,23 @@
+// Original regression test for Issue #30438.
+
+use std::ops::Index;
+
+struct Test<'a> {
+    s: &'a String
+}
+
+impl <'a> Index<usize> for Test<'a> {
+    type Output = Test<'a>;
+    fn index(&self, _: usize) -> &Self::Output {
+        return &Test { s: &self.s};
+        //~^ ERROR: borrowed value does not live long enough
+    }
+}
+
+fn main() {
+    let s = "Hello World".to_string();
+    let test = Test{s: &s};
+    let r = &test[0];
+    println!("{}", test.s); // OK since test is valid
+    println!("{}", r.s); // Segfault since value pointed by r has already been dropped
+}
diff --git a/src/test/ui/issues/issue-30438-a.stderr b/src/test/ui/issues/issue-30438-a.stderr
new file mode 100644
index 0000000..89f8e62
--- /dev/null
+++ b/src/test/ui/issues/issue-30438-a.stderr
@@ -0,0 +1,21 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/issue-30438-a.rs:12:17
+   |
+LL |         return &Test { s: &self.s};
+   |                 ^^^^^^^^^^^^^^^^^^- temporary value only lives until here
+   |                 |
+   |                 temporary value does not live long enough
+   |
+note: borrowed value must be valid for the anonymous lifetime #1 defined on the method body at 11:5...
+  --> $DIR/issue-30438-a.rs:11:5
+   |
+LL | /     fn index(&self, _: usize) -> &Self::Output {
+LL | |         return &Test { s: &self.s};
+LL | |
+LL | |     }
+   | |_____^
+   = note: consider using a `let` binding to increase its lifetime
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/issues/issue-30438-b.nll.stderr b/src/test/ui/issues/issue-30438-b.nll.stderr
new file mode 100644
index 0000000..fd6bd25
--- /dev/null
+++ b/src/test/ui/issues/issue-30438-b.nll.stderr
@@ -0,0 +1,12 @@
+error[E0515]: cannot return reference to temporary value
+  --> $DIR/issue-30438-b.rs:13:9
+   |
+LL |         &Test { s: &self.s}
+   |         ^------------------
+   |         ||
+   |         |temporary value created here
+   |         returns a reference to data owned by the current function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/src/test/ui/issues/issue-30438-b.rs b/src/test/ui/issues/issue-30438-b.rs
new file mode 100644
index 0000000..b84211b
--- /dev/null
+++ b/src/test/ui/issues/issue-30438-b.rs
@@ -0,0 +1,24 @@
+// Modified regression test for Issue #30438 that exposed an
+// independent issue (see discussion on ticket).
+
+use std::ops::Index;
+
+struct Test<'a> {
+    s: &'a String
+}
+
+impl <'a> Index<usize> for Test<'a> {
+    type Output = Test<'a>;
+    fn index(&self, _: usize) -> &Self::Output {
+        &Test { s: &self.s}
+        //~^ ERROR: borrowed value does not live long enough
+    }
+}
+
+fn main() {
+    let s = "Hello World".to_string();
+    let test = Test{s: &s};
+    let r = &test[0];
+    println!("{}", test.s); // OK since test is valid
+    println!("{}", r.s); // Segfault since value pointed by r has already been dropped
+}
diff --git a/src/test/ui/issues/issue-30438-b.stderr b/src/test/ui/issues/issue-30438-b.stderr
new file mode 100644
index 0000000..49208ed
--- /dev/null
+++ b/src/test/ui/issues/issue-30438-b.stderr
@@ -0,0 +1,21 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/issue-30438-b.rs:13:10
+   |
+LL |         &Test { s: &self.s}
+   |          ^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+LL |
+LL |     }
+   |     - temporary value only lives until here
+   |
+note: borrowed value must be valid for the anonymous lifetime #1 defined on the method body at 12:5...
+  --> $DIR/issue-30438-b.rs:12:5
+   |
+LL | /     fn index(&self, _: usize) -> &Self::Output {
+LL | |         &Test { s: &self.s}
+LL | |
+LL | |     }
+   | |_____^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/issues/issue-30438-c.nll.stderr b/src/test/ui/issues/issue-30438-c.nll.stderr
new file mode 100644
index 0000000..7c00108
--- /dev/null
+++ b/src/test/ui/issues/issue-30438-c.nll.stderr
@@ -0,0 +1,9 @@
+error[E0515]: cannot return reference to local variable `x`
+  --> $DIR/issue-30438-c.rs:9:5
+   |
+LL |     &x
+   |     ^^ returns a reference to data owned by the current function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/src/test/ui/issues/issue-30438-c.rs b/src/test/ui/issues/issue-30438-c.rs
new file mode 100644
index 0000000..75caf0a
--- /dev/null
+++ b/src/test/ui/issues/issue-30438-c.rs
@@ -0,0 +1,20 @@
+// Simplified regression test for #30438, inspired by arielb1.
+
+trait Trait { type Out; }
+
+struct Test<'a> { s: &'a str }
+
+fn silly<'y, 'z>(_s: &'y Test<'z>) -> &'y <Test<'z> as Trait>::Out where 'z: 'static {
+    let x = Test { s: "this cannot last" };
+    &x
+    //~^ ERROR: `x` does not live long enough
+}
+
+impl<'b> Trait for Test<'b> { type Out = Test<'b>; }
+
+fn main() {
+    let orig = Test { s: "Hello World" };
+    let r = silly(&orig);
+    println!("{}", orig.s); // OK since `orig` is valid
+    println!("{}", r.s); // Segfault (method does not return a sane value)
+}
diff --git a/src/test/ui/issues/issue-30438-c.stderr b/src/test/ui/issues/issue-30438-c.stderr
new file mode 100644
index 0000000..a003e27
--- /dev/null
+++ b/src/test/ui/issues/issue-30438-c.stderr
@@ -0,0 +1,18 @@
+error[E0597]: `x` does not live long enough
+  --> $DIR/issue-30438-c.rs:9:6
+   |
+LL |     &x
+   |      ^ borrowed value does not live long enough
+LL |
+LL | }
+   | - borrowed value only lives until here
+   |
+note: borrowed value must be valid for the lifetime 'y as defined on the function body at 7:10...
+  --> $DIR/issue-30438-c.rs:7:10
+   |
+LL | fn silly<'y, 'z>(_s: &'y Test<'z>) -> &'y <Test<'z> as Trait>::Out where 'z: 'static {
+   |          ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/issues/issue-3044.rs b/src/test/ui/issues/issue-3044.rs
new file mode 100644
index 0000000..26db04b
--- /dev/null
+++ b/src/test/ui/issues/issue-3044.rs
@@ -0,0 +1,6 @@
+fn main() {
+    let needlesArr: Vec<char> = vec!['a', 'f'];
+    needlesArr.iter().fold(|x, y| {
+    });
+    //~^^ ERROR this function takes 2 parameters but 1 parameter was supplied
+}
diff --git a/src/test/ui/issues/issue-3044.stderr b/src/test/ui/issues/issue-3044.stderr
new file mode 100644
index 0000000..35a85b6
--- /dev/null
+++ b/src/test/ui/issues/issue-3044.stderr
@@ -0,0 +1,9 @@
+error[E0061]: this function takes 2 parameters but 1 parameter was supplied
+  --> $DIR/issue-3044.rs:3:23
+   |
+LL |     needlesArr.iter().fold(|x, y| {
+   |                       ^^^^ expected 2 parameters
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0061`.
diff --git a/src/test/ui/issues/issue-30535.rs b/src/test/ui/issues/issue-30535.rs
new file mode 100644
index 0000000..d48f00d
--- /dev/null
+++ b/src/test/ui/issues/issue-30535.rs
@@ -0,0 +1,9 @@
+// aux-build:issue-30535.rs
+
+extern crate issue_30535 as foo;
+
+fn bar(
+    _: foo::Foo::FooV //~ ERROR expected type, found variant `foo::Foo::FooV`
+) {}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-30535.stderr b/src/test/ui/issues/issue-30535.stderr
new file mode 100644
index 0000000..e369293
--- /dev/null
+++ b/src/test/ui/issues/issue-30535.stderr
@@ -0,0 +1,12 @@
+error[E0573]: expected type, found variant `foo::Foo::FooV`
+  --> $DIR/issue-30535.rs:6:8
+   |
+LL |     _: foo::Foo::FooV
+   |        ^^^^^^^^^^^^^^
+   |        |
+   |        not a type
+   |        help: try using the variant's enum: `foo::Foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0573`.
diff --git a/src/test/ui/issues/issue-30560.rs b/src/test/ui/issues/issue-30560.rs
new file mode 100644
index 0000000..c848a1c
--- /dev/null
+++ b/src/test/ui/issues/issue-30560.rs
@@ -0,0 +1,12 @@
+type Alias = ();
+use Alias::*;
+//~^ ERROR unresolved import `Alias` [E0432]
+//~| not a module `Alias`
+use std::io::Result::*;
+//~^ ERROR unresolved import `std::io::Result` [E0432]
+//~| not a module `Result`
+
+trait T {}
+use T::*; //~ ERROR items in traits are not importable
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-30560.stderr b/src/test/ui/issues/issue-30560.stderr
new file mode 100644
index 0000000..5225f19
--- /dev/null
+++ b/src/test/ui/issues/issue-30560.stderr
@@ -0,0 +1,21 @@
+error: items in traits are not importable.
+  --> $DIR/issue-30560.rs:10:5
+   |
+LL | use T::*;
+   |     ^^^^
+
+error[E0432]: unresolved import `Alias`
+  --> $DIR/issue-30560.rs:2:5
+   |
+LL | use Alias::*;
+   |     ^^^^^ not a module `Alias`
+
+error[E0432]: unresolved import `std::io::Result`
+  --> $DIR/issue-30560.rs:5:14
+   |
+LL | use std::io::Result::*;
+   |              ^^^^^^ not a module `Result`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/issues/issue-30589.rs b/src/test/ui/issues/issue-30589.rs
new file mode 100644
index 0000000..94eb583
--- /dev/null
+++ b/src/test/ui/issues/issue-30589.rs
@@ -0,0 +1,9 @@
+use std::fmt;
+
+impl fmt::Display for DecoderError { //~ ERROR cannot find type `DecoderError` in this scope
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "Missing data: {}", self.0)
+    }
+}
+fn main() {
+}
diff --git a/src/test/ui/issues/issue-30589.stderr b/src/test/ui/issues/issue-30589.stderr
new file mode 100644
index 0000000..4b88547
--- /dev/null
+++ b/src/test/ui/issues/issue-30589.stderr
@@ -0,0 +1,9 @@
+error[E0412]: cannot find type `DecoderError` in this scope
+  --> $DIR/issue-30589.rs:3:23
+   |
+LL | impl fmt::Display for DecoderError {
+   |                       ^^^^^^^^^^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/src/test/ui/issues/issue-30730.rs b/src/test/ui/issues/issue-30730.rs
new file mode 100644
index 0000000..d6be90c
--- /dev/null
+++ b/src/test/ui/issues/issue-30730.rs
@@ -0,0 +1,5 @@
+#![warn(unused)]
+#![deny(warnings)]
+use std::thread;
+//~^ ERROR: unused import
+fn main() {}
diff --git a/src/test/ui/issues/issue-30730.stderr b/src/test/ui/issues/issue-30730.stderr
new file mode 100644
index 0000000..0a90107
--- /dev/null
+++ b/src/test/ui/issues/issue-30730.stderr
@@ -0,0 +1,15 @@
+error: unused import: `std::thread`
+  --> $DIR/issue-30730.rs:3:5
+   |
+LL | use std::thread;
+   |     ^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/issue-30730.rs:2:9
+   |
+LL | #![deny(warnings)]
+   |         ^^^^^^^^
+   = note: #[deny(unused_imports)] implied by #[deny(warnings)]
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-3080.rs b/src/test/ui/issues/issue-3080.rs
new file mode 100644
index 0000000..883f3bf
--- /dev/null
+++ b/src/test/ui/issues/issue-3080.rs
@@ -0,0 +1,8 @@
+struct X(());
+impl X {
+    pub unsafe fn with(&self) { }
+}
+
+fn main() {
+    X(()).with(); //~ ERROR requires unsafe function or block
+}
diff --git a/src/test/ui/issues/issue-3080.stderr b/src/test/ui/issues/issue-3080.stderr
new file mode 100644
index 0000000..138d6df
--- /dev/null
+++ b/src/test/ui/issues/issue-3080.stderr
@@ -0,0 +1,11 @@
+error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
+  --> $DIR/issue-3080.rs:7:5
+   |
+LL |     X(()).with();
+   |     ^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/issues/issue-3096-1.rs b/src/test/ui/issues/issue-3096-1.rs
new file mode 100644
index 0000000..edc3b32
--- /dev/null
+++ b/src/test/ui/issues/issue-3096-1.rs
@@ -0,0 +1,3 @@
+fn main() {
+    match () { } //~ ERROR non-exhaustive
+}
diff --git a/src/test/ui/issues/issue-3096-1.stderr b/src/test/ui/issues/issue-3096-1.stderr
new file mode 100644
index 0000000..c5a7fa7
--- /dev/null
+++ b/src/test/ui/issues/issue-3096-1.stderr
@@ -0,0 +1,11 @@
+error[E0004]: non-exhaustive patterns: type `()` is non-empty
+  --> $DIR/issue-3096-1.rs:2:11
+   |
+LL |     match () { }
+   |           ^^
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/issues/issue-3096-2.rs b/src/test/ui/issues/issue-3096-2.rs
new file mode 100644
index 0000000..a26e425
--- /dev/null
+++ b/src/test/ui/issues/issue-3096-2.rs
@@ -0,0 +1,6 @@
+enum Bottom { }
+
+fn main() {
+    let x = &() as *const () as *const Bottom;
+    match x { } //~ ERROR non-exhaustive patterns
+}
diff --git a/src/test/ui/issues/issue-3096-2.stderr b/src/test/ui/issues/issue-3096-2.stderr
new file mode 100644
index 0000000..6f2e0e7
--- /dev/null
+++ b/src/test/ui/issues/issue-3096-2.stderr
@@ -0,0 +1,11 @@
+error[E0004]: non-exhaustive patterns: type `*const Bottom` is non-empty
+  --> $DIR/issue-3096-2.rs:5:11
+   |
+LL |     match x { }
+   |           ^
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/issues/issue-3099-a.rs b/src/test/ui/issues/issue-3099-a.rs
new file mode 100644
index 0000000..9c3d8cf
--- /dev/null
+++ b/src/test/ui/issues/issue-3099-a.rs
@@ -0,0 +1,5 @@
+enum A { B, C }
+
+enum A { D, E } //~ ERROR the name `A` is defined multiple times
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-3099-a.stderr b/src/test/ui/issues/issue-3099-a.stderr
new file mode 100644
index 0000000..d6e0a79
--- /dev/null
+++ b/src/test/ui/issues/issue-3099-a.stderr
@@ -0,0 +1,14 @@
+error[E0428]: the name `A` is defined multiple times
+  --> $DIR/issue-3099-a.rs:3:1
+   |
+LL | enum A { B, C }
+   | ------ previous definition of the type `A` here
+LL | 
+LL | enum A { D, E }
+   | ^^^^^^ `A` redefined here
+   |
+   = note: `A` must be defined only once in the type namespace of this module
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0428`.
diff --git a/src/test/ui/issues/issue-3099-b.rs b/src/test/ui/issues/issue-3099-b.rs
new file mode 100644
index 0000000..71952c3
--- /dev/null
+++ b/src/test/ui/issues/issue-3099-b.rs
@@ -0,0 +1,5 @@
+pub mod a {}
+
+pub mod a {} //~ ERROR the name `a` is defined multiple times
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-3099-b.stderr b/src/test/ui/issues/issue-3099-b.stderr
new file mode 100644
index 0000000..3ba8b18
--- /dev/null
+++ b/src/test/ui/issues/issue-3099-b.stderr
@@ -0,0 +1,14 @@
+error[E0428]: the name `a` is defined multiple times
+  --> $DIR/issue-3099-b.rs:3:1
+   |
+LL | pub mod a {}
+   | --------- previous definition of the module `a` here
+LL | 
+LL | pub mod a {}
+   | ^^^^^^^^^ `a` redefined here
+   |
+   = note: `a` must be defined only once in the type namespace of this module
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0428`.
diff --git a/src/test/ui/issues/issue-3099.rs b/src/test/ui/issues/issue-3099.rs
new file mode 100644
index 0000000..ee75b35
--- /dev/null
+++ b/src/test/ui/issues/issue-3099.rs
@@ -0,0 +1,11 @@
+fn a(x: String) -> String {
+    format!("First function with {}", x)
+}
+
+fn a(x: String, y: String) -> String { //~ ERROR the name `a` is defined multiple times
+    format!("Second function with {} and {}", x, y)
+}
+
+fn main() {
+    println!("Result: ");
+}
diff --git a/src/test/ui/issues/issue-3099.stderr b/src/test/ui/issues/issue-3099.stderr
new file mode 100644
index 0000000..32ee2e1
--- /dev/null
+++ b/src/test/ui/issues/issue-3099.stderr
@@ -0,0 +1,14 @@
+error[E0428]: the name `a` is defined multiple times
+  --> $DIR/issue-3099.rs:5:1
+   |
+LL | fn a(x: String) -> String {
+   | ------------------------- previous definition of the value `a` here
+...
+LL | fn a(x: String, y: String) -> String {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `a` redefined here
+   |
+   = note: `a` must be defined only once in the value namespace of this module
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0428`.
diff --git a/src/test/ui/issues/issue-31011.rs b/src/test/ui/issues/issue-31011.rs
new file mode 100644
index 0000000..4dead04
--- /dev/null
+++ b/src/test/ui/issues/issue-31011.rs
@@ -0,0 +1,29 @@
+macro_rules! log {
+    ( $ctx:expr, $( $args:expr),* ) => {
+        if $ctx.trace {
+        //~^ no field `trace` on type `&T`
+            println!( $( $args, )* );
+        }
+    }
+}
+
+// Create a structure.
+struct Foo {
+  trace: bool,
+}
+
+// Generic wrapper calls log! with a structure.
+fn wrap<T>(context: &T) -> ()
+{
+    log!(context, "entered wrapper");
+    //~^ in this expansion of log!
+}
+
+fn main() {
+    // Create a structure.
+    let x = Foo { trace: true };
+    log!(x, "run started");
+    // Apply a closure which accesses internal fields.
+    wrap(&x);
+    log!(x, "run finished");
+}
diff --git a/src/test/ui/issues/issue-31011.stderr b/src/test/ui/issues/issue-31011.stderr
new file mode 100644
index 0000000..ab00695
--- /dev/null
+++ b/src/test/ui/issues/issue-31011.stderr
@@ -0,0 +1,12 @@
+error[E0609]: no field `trace` on type `&T`
+  --> $DIR/issue-31011.rs:3:17
+   |
+LL |         if $ctx.trace {
+   |                 ^^^^^
+...
+LL |     log!(context, "entered wrapper");
+   |     --------------------------------- in this macro invocation
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0609`.
diff --git a/src/test/ui/issues/issue-31076.rs b/src/test/ui/issues/issue-31076.rs
new file mode 100644
index 0000000..e453107
--- /dev/null
+++ b/src/test/ui/issues/issue-31076.rs
@@ -0,0 +1,17 @@
+#![feature(no_core, lang_items)]
+#![no_core]
+
+#[lang="sized"]
+trait Sized {}
+
+#[lang="add"]
+trait Add<T> {}
+
+impl Add<i32> for i32 {}
+
+fn main() {
+    let x = 5 + 6;
+    //~^ ERROR binary operation `+` cannot be applied to type `{integer}`
+    let y = 5i32 + 6i32;
+    //~^ ERROR binary operation `+` cannot be applied to type `i32`
+}
diff --git a/src/test/ui/issues/issue-31076.stderr b/src/test/ui/issues/issue-31076.stderr
new file mode 100644
index 0000000..60a3be1
--- /dev/null
+++ b/src/test/ui/issues/issue-31076.stderr
@@ -0,0 +1,23 @@
+error[E0369]: binary operation `+` cannot be applied to type `{integer}`
+  --> $DIR/issue-31076.rs:13:15
+   |
+LL |     let x = 5 + 6;
+   |             - ^ - {integer}
+   |             |
+   |             {integer}
+   |
+   = note: an implementation of `std::ops::Add` might be missing for `{integer}`
+
+error[E0369]: binary operation `+` cannot be applied to type `i32`
+  --> $DIR/issue-31076.rs:15:18
+   |
+LL |     let y = 5i32 + 6i32;
+   |             ---- ^ ---- i32
+   |             |
+   |             i32
+   |
+   = note: an implementation of `std::ops::Add` might be missing for `i32`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0369`.
diff --git a/src/test/ui/issues/issue-31109.rs b/src/test/ui/issues/issue-31109.rs
new file mode 100644
index 0000000..37c23905
--- /dev/null
+++ b/src/test/ui/issues/issue-31109.rs
@@ -0,0 +1,6 @@
+fn main() {
+    // FIXME(#31407) this error should go away, but in the meantime we test that it
+    // is accompanied by a somewhat useful error message.
+    let _: f64 = 1234567890123456789012345678901234567890e-340;
+    //~^ ERROR could not evaluate float literal (see issue #31407)
+}
diff --git a/src/test/ui/issues/issue-31109.stderr b/src/test/ui/issues/issue-31109.stderr
new file mode 100644
index 0000000..d354f61
--- /dev/null
+++ b/src/test/ui/issues/issue-31109.stderr
@@ -0,0 +1,8 @@
+error: could not evaluate float literal (see issue #31407)
+  --> $DIR/issue-31109.rs:4:18
+   |
+LL |     let _: f64 = 1234567890123456789012345678901234567890e-340;
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-31173.rs b/src/test/ui/issues/issue-31173.rs
new file mode 100644
index 0000000..6df8066
--- /dev/null
+++ b/src/test/ui/issues/issue-31173.rs
@@ -0,0 +1,17 @@
+use std::vec::IntoIter;
+
+pub fn get_tok(it: &mut IntoIter<u8>) {
+    let mut found_e = false;
+
+    let temp: Vec<u8> = it.take_while(|&x| {
+        found_e = true;
+        false
+    })
+        .cloned()
+        //~^ ERROR type mismatch resolving
+        //~| expected type `u8`
+        //~| found type `&_`
+        .collect(); //~ ERROR no method named `collect`
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-31173.stderr b/src/test/ui/issues/issue-31173.stderr
new file mode 100644
index 0000000..d5f8cc8
--- /dev/null
+++ b/src/test/ui/issues/issue-31173.stderr
@@ -0,0 +1,23 @@
+error[E0271]: type mismatch resolving `<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 9:6 found_e:_]> as std::iter::Iterator>::Item == &_`
+  --> $DIR/issue-31173.rs:10:10
+   |
+LL |         .cloned()
+   |          ^^^^^^ expected u8, found reference
+   |
+   = note: expected type `u8`
+              found type `&_`
+
+error[E0599]: no method named `collect` found for type `std::iter::Cloned<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 9:6 found_e:_]>>` in the current scope
+  --> $DIR/issue-31173.rs:14:10
+   |
+LL |         .collect();
+   |          ^^^^^^^
+   |
+   = note: the method `collect` exists but the following trait bounds were not satisfied:
+           `&mut std::iter::Cloned<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 9:6 found_e:_]>> : std::iter::Iterator`
+           `std::iter::Cloned<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 9:6 found_e:_]>> : std::iter::Iterator`
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0271, E0599.
+For more information about an error, try `rustc --explain E0271`.
diff --git a/src/test/ui/issues/issue-31212.rs b/src/test/ui/issues/issue-31212.rs
new file mode 100644
index 0000000..556f0d1
--- /dev/null
+++ b/src/test/ui/issues/issue-31212.rs
@@ -0,0 +1,10 @@
+// This checks that a path that cannot be resolved because of an indeterminate import
+// does not trigger an ICE.
+
+mod foo {
+    pub use self::*; //~ ERROR unresolved
+}
+
+fn main() {
+    foo::f(); //~ ERROR cannot find function `f` in module `foo`
+}
diff --git a/src/test/ui/issues/issue-31212.stderr b/src/test/ui/issues/issue-31212.stderr
new file mode 100644
index 0000000..5daf900
--- /dev/null
+++ b/src/test/ui/issues/issue-31212.stderr
@@ -0,0 +1,16 @@
+error[E0432]: unresolved import `self::*`
+  --> $DIR/issue-31212.rs:5:13
+   |
+LL |     pub use self::*;
+   |             ^^^^^^^ cannot glob-import a module into itself
+
+error[E0425]: cannot find function `f` in module `foo`
+  --> $DIR/issue-31212.rs:9:10
+   |
+LL |     foo::f();
+   |          ^ not found in `foo`
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0425, E0432.
+For more information about an error, try `rustc --explain E0425`.
diff --git a/src/test/ui/issues/issue-31221.rs b/src/test/ui/issues/issue-31221.rs
new file mode 100644
index 0000000..e03f1ec
--- /dev/null
+++ b/src/test/ui/issues/issue-31221.rs
@@ -0,0 +1,34 @@
+#![allow(dead_code)]
+#![allow(unused_variables)]
+#![allow(non_snake_case)]
+#![deny(unreachable_patterns)]
+
+#[derive(Clone, Copy)]
+enum Enum {
+    Var1,
+    Var2,
+}
+
+fn main() {
+    use Enum::*;
+    let s = Var1;
+    match s {
+        Var1 => (),
+        Var3 => (),
+        Var2 => (),
+        //~^ ERROR unreachable pattern
+    };
+    match &s {
+        &Var1 => (),
+        &Var3 => (),
+        &Var2 => (),
+        //~^ ERROR unreachable pattern
+    };
+    let t = (Var1, Var1);
+    match t {
+        (Var1, b) => (),
+        (c, d) => (),
+        anything => ()
+        //~^ ERROR unreachable pattern
+    };
+}
diff --git a/src/test/ui/issues/issue-31221.stderr b/src/test/ui/issues/issue-31221.stderr
new file mode 100644
index 0000000..0f3b4ba
--- /dev/null
+++ b/src/test/ui/issues/issue-31221.stderr
@@ -0,0 +1,32 @@
+error: unreachable pattern
+  --> $DIR/issue-31221.rs:18:9
+   |
+LL |         Var3 => (),
+   |         ---- matches any value
+LL |         Var2 => (),
+   |         ^^^^ unreachable pattern
+   |
+note: lint level defined here
+  --> $DIR/issue-31221.rs:4:9
+   |
+LL | #![deny(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/issue-31221.rs:24:9
+   |
+LL |         &Var3 => (),
+   |         ----- matches any value
+LL |         &Var2 => (),
+   |         ^^^^^ unreachable pattern
+
+error: unreachable pattern
+  --> $DIR/issue-31221.rs:31:9
+   |
+LL |         (c, d) => (),
+   |         ------ matches any value
+LL |         anything => ()
+   |         ^^^^^^^^ unreachable pattern
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/issues/issue-31260.rs b/src/test/ui/issues/issue-31260.rs
new file mode 100644
index 0000000..f7e717c
--- /dev/null
+++ b/src/test/ui/issues/issue-31260.rs
@@ -0,0 +1,15 @@
+// compile-pass
+#![allow(dead_code)]
+pub struct Struct<K: 'static> {
+    pub field: K,
+}
+
+static STRUCT: Struct<&'static [u8]> = Struct {
+    field: {&[1]}
+};
+
+static STRUCT2: Struct<&'static [u8]> = Struct {
+    field: &[1]
+};
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-3149.rs b/src/test/ui/issues/issue-3149.rs
new file mode 100644
index 0000000..c9a6f53
--- /dev/null
+++ b/src/test/ui/issues/issue-3149.rs
@@ -0,0 +1,26 @@
+// compile-pass
+#![allow(dead_code)]
+#![allow(non_snake_case)]
+// pretty-expanded FIXME #23616
+
+fn Matrix4<T>(m11: T, m12: T, m13: T, m14: T,
+              m21: T, m22: T, m23: T, m24: T,
+              m31: T, m32: T, m33: T, m34: T,
+              m41: T, m42: T, m43: T, m44: T)
+              -> Matrix4<T> {
+    Matrix4 {
+        m11: m11, m12: m12, m13: m13, m14: m14,
+        m21: m21, m22: m22, m23: m23, m24: m24,
+        m31: m31, m32: m32, m33: m33, m34: m34,
+        m41: m41, m42: m42, m43: m43, m44: m44
+    }
+}
+
+struct Matrix4<T> {
+    m11: T, m12: T, m13: T, m14: T,
+    m21: T, m22: T, m23: T, m24: T,
+    m31: T, m32: T, m33: T, m34: T,
+    m41: T, m42: T, m43: T, m44: T,
+}
+
+pub fn main() {}
diff --git a/src/test/ui/issues/issue-31511.rs b/src/test/ui/issues/issue-31511.rs
new file mode 100644
index 0000000..53fecb0
--- /dev/null
+++ b/src/test/ui/issues/issue-31511.rs
@@ -0,0 +1,6 @@
+fn cast_thin_to_fat(x: *const ()) {
+    x as *const [u8];
+    //~^ ERROR: cannot cast thin pointer `*const ()` to fat pointer `*const [u8]`
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-31511.stderr b/src/test/ui/issues/issue-31511.stderr
new file mode 100644
index 0000000..cb29918
--- /dev/null
+++ b/src/test/ui/issues/issue-31511.stderr
@@ -0,0 +1,9 @@
+error[E0607]: cannot cast thin pointer `*const ()` to fat pointer `*const [u8]`
+  --> $DIR/issue-31511.rs:2:5
+   |
+LL |     x as *const [u8];
+   |     ^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0607`.
diff --git a/src/test/ui/issues/issue-3154.rs b/src/test/ui/issues/issue-3154.rs
new file mode 100644
index 0000000..91c7203
--- /dev/null
+++ b/src/test/ui/issues/issue-3154.rs
@@ -0,0 +1,11 @@
+struct Thing<'a, Q:'a> {
+    x: &'a Q
+}
+
+fn thing<'a,Q>(x: &Q) -> Thing<'a,Q> {
+    Thing { x: x } //~ ERROR explicit lifetime required in the type of `x` [E0621]
+}
+
+fn main() {
+    thing(&());
+}
diff --git a/src/test/ui/issues/issue-3154.stderr b/src/test/ui/issues/issue-3154.stderr
new file mode 100644
index 0000000..da2af83
--- /dev/null
+++ b/src/test/ui/issues/issue-3154.stderr
@@ -0,0 +1,11 @@
+error[E0621]: explicit lifetime required in the type of `x`
+  --> $DIR/issue-3154.rs:6:5
+   |
+LL | fn thing<'a,Q>(x: &Q) -> Thing<'a,Q> {
+   |                   -- help: add explicit lifetime `'a` to the type of `x`: `&'a Q`
+LL |     Thing { x: x }
+   |     ^^^^^^^^^^^^^^ lifetime `'a` required
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/issues/issue-31561.rs b/src/test/ui/issues/issue-31561.rs
new file mode 100644
index 0000000..87b19fe5
--- /dev/null
+++ b/src/test/ui/issues/issue-31561.rs
@@ -0,0 +1,10 @@
+enum Thing {
+    Foo(u8),
+    Bar,
+    Baz
+}
+
+fn main() {
+    let Thing::Foo(y) = Thing::Foo(1);
+    //~^ ERROR refutable pattern in local binding: `Bar` not covered
+}
diff --git a/src/test/ui/issues/issue-31561.stderr b/src/test/ui/issues/issue-31561.stderr
new file mode 100644
index 0000000..246137a
--- /dev/null
+++ b/src/test/ui/issues/issue-31561.stderr
@@ -0,0 +1,16 @@
+error[E0005]: refutable pattern in local binding: `Bar` not covered
+  --> $DIR/issue-31561.rs:8:9
+   |
+LL | / enum Thing {
+LL | |     Foo(u8),
+LL | |     Bar,
+LL | |     Baz
+LL | | }
+   | |_- `Thing` defined here
+...
+LL |       let Thing::Foo(y) = Thing::Foo(1);
+   |           ^^^^^^^^^^^^^ pattern `Bar` not covered
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0005`.
diff --git a/src/test/ui/issues/issue-31597.rs b/src/test/ui/issues/issue-31597.rs
new file mode 100644
index 0000000..3962f13
--- /dev/null
+++ b/src/test/ui/issues/issue-31597.rs
@@ -0,0 +1,29 @@
+// compile-pass
+#![allow(dead_code)]
+trait Make {
+    type Out;
+
+    fn make() -> Self::Out;
+}
+
+impl Make for () {
+    type Out = ();
+
+    fn make() -> Self::Out {}
+}
+
+// Also make sure we don't hit an ICE when the projection can't be known
+fn f<T: Make>() -> <T as Make>::Out { loop {} }
+
+// ...and that it works with a blanket impl
+trait Tr {
+    type Assoc;
+}
+
+impl<T: Make> Tr for T {
+    type Assoc = ();
+}
+
+fn g<T: Make>() -> <T as Tr>::Assoc { }
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-31769.rs b/src/test/ui/issues/issue-31769.rs
new file mode 100644
index 0000000..794c1d1
--- /dev/null
+++ b/src/test/ui/issues/issue-31769.rs
@@ -0,0 +1,4 @@
+fn main() {
+    #[inline] struct Foo;  //~ ERROR attribute should be applied to function or closure
+    #[repr(C)] fn foo() {} //~ ERROR attribute should be applied to struct, enum or union
+}
diff --git a/src/test/ui/issues/issue-31769.stderr b/src/test/ui/issues/issue-31769.stderr
new file mode 100644
index 0000000..29fcefc
--- /dev/null
+++ b/src/test/ui/issues/issue-31769.stderr
@@ -0,0 +1,16 @@
+error[E0518]: attribute should be applied to function or closure
+  --> $DIR/issue-31769.rs:2:5
+   |
+LL |     #[inline] struct Foo;
+   |     ^^^^^^^^^ ----------- not a function or closure
+
+error[E0517]: attribute should be applied to struct, enum or union
+  --> $DIR/issue-31769.rs:3:12
+   |
+LL |     #[repr(C)] fn foo() {}
+   |            ^   ----------- not a struct, enum or union
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0517, E0518.
+For more information about an error, try `rustc --explain E0517`.
diff --git a/src/test/ui/issues/issue-31804.rs b/src/test/ui/issues/issue-31804.rs
new file mode 100644
index 0000000..d056b77
--- /dev/null
+++ b/src/test/ui/issues/issue-31804.rs
@@ -0,0 +1,6 @@
+// Test that error recovery in the parser to an EOF does not give an infinite
+// spew of errors.
+
+fn main() {
+    let
+} //~ ERROR expected pattern, found `}`
diff --git a/src/test/ui/issues/issue-31804.stderr b/src/test/ui/issues/issue-31804.stderr
new file mode 100644
index 0000000..76e68b0
--- /dev/null
+++ b/src/test/ui/issues/issue-31804.stderr
@@ -0,0 +1,8 @@
+error: expected pattern, found `}`
+  --> $DIR/issue-31804.rs:6:1
+   |
+LL | }
+   | ^ expected pattern
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-31845.rs b/src/test/ui/issues/issue-31845.rs
new file mode 100644
index 0000000..f6dc115
--- /dev/null
+++ b/src/test/ui/issues/issue-31845.rs
@@ -0,0 +1,12 @@
+// Checks lexical scopes cannot see through normal module boundaries
+
+fn f() {
+    fn g() {}
+    mod foo {
+        fn h() {
+           g(); //~ ERROR cannot find function `g` in this scope
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-31845.stderr b/src/test/ui/issues/issue-31845.stderr
new file mode 100644
index 0000000..10cb398
--- /dev/null
+++ b/src/test/ui/issues/issue-31845.stderr
@@ -0,0 +1,9 @@
+error[E0425]: cannot find function `g` in this scope
+  --> $DIR/issue-31845.rs:7:12
+   |
+LL |            g();
+   |            ^ help: a function with a similar name exists: `h`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/issues/issue-31910.rs b/src/test/ui/issues/issue-31910.rs
new file mode 100644
index 0000000..c62ed89
--- /dev/null
+++ b/src/test/ui/issues/issue-31910.rs
@@ -0,0 +1,11 @@
+enum Enum<T: Trait> {
+    X = Trait::Number,
+    //~^ ERROR mismatched types
+    //~| expected isize, found i32
+}
+
+trait Trait {
+    const Number: i32 = 1;
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-31910.stderr b/src/test/ui/issues/issue-31910.stderr
new file mode 100644
index 0000000..c58702d
--- /dev/null
+++ b/src/test/ui/issues/issue-31910.stderr
@@ -0,0 +1,9 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-31910.rs:2:9
+   |
+LL |     X = Trait::Number,
+   |         ^^^^^^^^^^^^^ expected isize, found i32
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-31924-non-snake-ffi.rs b/src/test/ui/issues/issue-31924-non-snake-ffi.rs
new file mode 100644
index 0000000..5e2336c
--- /dev/null
+++ b/src/test/ui/issues/issue-31924-non-snake-ffi.rs
@@ -0,0 +1,8 @@
+// compile-pass
+// skip-codegen
+#![deny(non_snake_case)]
+#[no_mangle]
+pub extern "C" fn SparklingGenerationForeignFunctionInterface() {}
+
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-32004.rs b/src/test/ui/issues/issue-32004.rs
new file mode 100644
index 0000000..aeddb00
--- /dev/null
+++ b/src/test/ui/issues/issue-32004.rs
@@ -0,0 +1,19 @@
+enum Foo {
+    Bar(i32),
+    Baz
+}
+
+struct S;
+
+fn main() {
+    match Foo::Baz {
+        Foo::Bar => {}
+        //~^ ERROR expected unit struct/variant or constant, found tuple variant `Foo::Bar`
+        _ => {}
+    }
+
+    match S {
+        S(()) => {}
+        //~^ ERROR expected tuple struct/variant, found unit struct `S`
+    }
+}
diff --git a/src/test/ui/issues/issue-32004.stderr b/src/test/ui/issues/issue-32004.stderr
new file mode 100644
index 0000000..f8c418b
--- /dev/null
+++ b/src/test/ui/issues/issue-32004.stderr
@@ -0,0 +1,17 @@
+error[E0532]: expected unit struct/variant or constant, found tuple variant `Foo::Bar`
+  --> $DIR/issue-32004.rs:10:9
+   |
+LL |         Foo::Bar => {}
+   |         ^^^^^---
+   |              |
+   |              help: a unit variant with a similar name exists: `Baz`
+
+error[E0532]: expected tuple struct/variant, found unit struct `S`
+  --> $DIR/issue-32004.rs:16:9
+   |
+LL |         S(()) => {}
+   |         ^ not a tuple struct/variant
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0532`.
diff --git a/src/test/ui/issues/issue-32086.rs b/src/test/ui/issues/issue-32086.rs
new file mode 100644
index 0000000..3188377
--- /dev/null
+++ b/src/test/ui/issues/issue-32086.rs
@@ -0,0 +1,7 @@
+struct S(u8);
+const C: S = S(10);
+
+fn main() {
+    let C(a) = S(11); //~ ERROR expected tuple struct/variant, found constant `C`
+    let C(..) = S(11); //~ ERROR expected tuple struct/variant, found constant `C`
+}
diff --git a/src/test/ui/issues/issue-32086.stderr b/src/test/ui/issues/issue-32086.stderr
new file mode 100644
index 0000000..b5a120c
--- /dev/null
+++ b/src/test/ui/issues/issue-32086.stderr
@@ -0,0 +1,15 @@
+error[E0532]: expected tuple struct/variant, found constant `C`
+  --> $DIR/issue-32086.rs:5:9
+   |
+LL |     let C(a) = S(11);
+   |         ^ help: a tuple struct with a similar name exists: `S`
+
+error[E0532]: expected tuple struct/variant, found constant `C`
+  --> $DIR/issue-32086.rs:6:9
+   |
+LL |     let C(..) = S(11);
+   |         ^ help: a tuple struct with a similar name exists: `S`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0532`.
diff --git a/src/test/ui/issues/issue-32119.rs b/src/test/ui/issues/issue-32119.rs
new file mode 100644
index 0000000..ea8824b
--- /dev/null
+++ b/src/test/ui/issues/issue-32119.rs
@@ -0,0 +1,19 @@
+// compile-pass
+// skip-codegen
+#![allow(dead_code)]
+pub type T = ();
+mod foo { pub use super::T; }
+mod bar { pub use super::T; }
+
+pub use foo::*;
+pub use bar::*;
+
+mod baz {
+    pub type T = ();
+    mod foo { pub use super::T as S; }
+    mod bar { pub use super::foo::S as T; }
+    pub use self::bar::*;
+}
+
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-3214.rs b/src/test/ui/issues/issue-3214.rs
new file mode 100644
index 0000000..9a727aa
--- /dev/null
+++ b/src/test/ui/issues/issue-3214.rs
@@ -0,0 +1,11 @@
+fn foo<T>() {
+    struct Foo {
+        x: T, //~ ERROR can't use generic parameters from outer function
+    }
+
+    impl<T> Drop for Foo<T> {
+        //~^ ERROR wrong number of type arguments
+        fn drop(&mut self) {}
+    }
+}
+fn main() { }
diff --git a/src/test/ui/issues/issue-3214.stderr b/src/test/ui/issues/issue-3214.stderr
new file mode 100644
index 0000000..9c25856
--- /dev/null
+++ b/src/test/ui/issues/issue-3214.stderr
@@ -0,0 +1,21 @@
+error[E0401]: can't use generic parameters from outer function
+  --> $DIR/issue-3214.rs:3:12
+   |
+LL | fn foo<T>() {
+   |    --- - type variable from outer function
+   |    |
+   |    try adding a local generic parameter in this method instead
+LL |     struct Foo {
+LL |         x: T,
+   |            ^ use of generic parameter from outer function
+
+error[E0107]: wrong number of type arguments: expected 0, found 1
+  --> $DIR/issue-3214.rs:6:26
+   |
+LL |     impl<T> Drop for Foo<T> {
+   |                          ^ unexpected type argument
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0107, E0401.
+For more information about an error, try `rustc --explain E0107`.
diff --git a/src/test/ui/issues/issue-32201.rs b/src/test/ui/issues/issue-32201.rs
new file mode 100644
index 0000000..e22c160
--- /dev/null
+++ b/src/test/ui/issues/issue-32201.rs
@@ -0,0 +1,13 @@
+extern {
+    fn foo(a: i32, ...);
+}
+
+fn bar(_: *const u8) {}
+
+fn main() {
+    unsafe {
+        foo(0, bar);
+        //~^ ERROR can't pass `fn(*const u8) {bar}` to variadic function
+        //~| HELP cast the value to `fn(*const u8)`
+    }
+}
diff --git a/src/test/ui/issues/issue-32201.stderr b/src/test/ui/issues/issue-32201.stderr
new file mode 100644
index 0000000..cedb587
--- /dev/null
+++ b/src/test/ui/issues/issue-32201.stderr
@@ -0,0 +1,9 @@
+error[E0617]: can't pass `fn(*const u8) {bar}` to variadic function
+  --> $DIR/issue-32201.rs:9:16
+   |
+LL |         foo(0, bar);
+   |                ^^^ help: cast the value to `fn(*const u8)`: `bar as fn(*const u8)`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0617`.
diff --git a/src/test/ui/issues/issue-32222.rs b/src/test/ui/issues/issue-32222.rs
new file mode 100644
index 0000000..91f53ab
--- /dev/null
+++ b/src/test/ui/issues/issue-32222.rs
@@ -0,0 +1,25 @@
+// compile-pass
+// skip-codegen
+#![allow(warnings)]
+
+mod foo {
+    pub fn bar() {}
+}
+
+pub use foo::*;
+use b::bar;
+
+mod foobar {
+    use super::*;
+}
+
+mod a {
+    pub mod bar {}
+}
+
+mod b {
+    pub use a::bar;
+}
+
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-32323.rs b/src/test/ui/issues/issue-32323.rs
new file mode 100644
index 0000000..5078f55
--- /dev/null
+++ b/src/test/ui/issues/issue-32323.rs
@@ -0,0 +1,8 @@
+pub trait Tr<'a> {
+    type Out;
+}
+
+pub fn f<'a, T: Tr<'a>>() -> <T as Tr<'a>>::Out {}
+//~^ ERROR mismatched types
+
+pub fn main() {}
diff --git a/src/test/ui/issues/issue-32323.stderr b/src/test/ui/issues/issue-32323.stderr
new file mode 100644
index 0000000..0339fdc
--- /dev/null
+++ b/src/test/ui/issues/issue-32323.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-32323.rs:5:30
+   |
+LL | pub fn f<'a, T: Tr<'a>>() -> <T as Tr<'a>>::Out {}
+   |        -                     ^^^^^^^^^^^^^^^^^^ expected associated type, found ()
+   |        |
+   |        this function's body doesn't return
+   |
+   = note: expected type `<T as Tr<'a>>::Out`
+              found type `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-32324.rs b/src/test/ui/issues/issue-32324.rs
new file mode 100644
index 0000000..9abbe32
--- /dev/null
+++ b/src/test/ui/issues/issue-32324.rs
@@ -0,0 +1,24 @@
+// compile-pass
+#![allow(dead_code)]
+
+trait Resources {
+    type Buffer: Copy;
+}
+
+#[derive(Copy, Clone)]
+struct ConstantBufferSet<R: Resources>(
+    pub R::Buffer
+);
+
+#[derive(Copy, Clone)]
+enum It {}
+impl Resources for It {
+    type Buffer = u8;
+}
+
+#[derive(Copy, Clone)]
+enum Command {
+    BindConstantBuffers(ConstantBufferSet<It>)
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-32326.rs b/src/test/ui/issues/issue-32326.rs
new file mode 100644
index 0000000..e928c66
--- /dev/null
+++ b/src/test/ui/issues/issue-32326.rs
@@ -0,0 +1,10 @@
+// Regression test for #32326. We ran out of memory because we
+// attempted to expand this case up to the recursion limit, and 2^N is
+// too big.
+
+enum Expr { //~ ERROR E0072
+    Plus(Expr, Expr),
+    Literal(i64),
+}
+
+fn main() { }
diff --git a/src/test/ui/issues/issue-32326.stderr b/src/test/ui/issues/issue-32326.stderr
new file mode 100644
index 0000000..5967627
--- /dev/null
+++ b/src/test/ui/issues/issue-32326.stderr
@@ -0,0 +1,15 @@
+error[E0072]: recursive type `Expr` has infinite size
+  --> $DIR/issue-32326.rs:5:1
+   |
+LL | enum Expr {
+   | ^^^^^^^^^ recursive type has infinite size
+LL |     Plus(Expr, Expr),
+   |          ----  ---- recursive without indirection
+   |          |
+   |          recursive without indirection
+   |
+   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Expr` representable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0072`.
diff --git a/src/test/ui/issues/issue-32354-suggest-import-rename.fixed b/src/test/ui/issues/issue-32354-suggest-import-rename.fixed
new file mode 100644
index 0000000..27f1b896
--- /dev/null
+++ b/src/test/ui/issues/issue-32354-suggest-import-rename.fixed
@@ -0,0 +1,16 @@
+// run-rustfix
+
+#![allow(unused_imports)]
+
+pub mod extension1 {
+    pub trait ConstructorExtension {}
+}
+
+pub mod extension2 {
+    pub trait ConstructorExtension {}
+}
+
+use extension1::ConstructorExtension;
+use extension2::ConstructorExtension as OtherConstructorExtension; //~ ERROR is defined multiple times
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-32354-suggest-import-rename.rs b/src/test/ui/issues/issue-32354-suggest-import-rename.rs
new file mode 100644
index 0000000..5a7f234
--- /dev/null
+++ b/src/test/ui/issues/issue-32354-suggest-import-rename.rs
@@ -0,0 +1,16 @@
+// run-rustfix
+
+#![allow(unused_imports)]
+
+pub mod extension1 {
+    pub trait ConstructorExtension {}
+}
+
+pub mod extension2 {
+    pub trait ConstructorExtension {}
+}
+
+use extension1::ConstructorExtension;
+use extension2::ConstructorExtension; //~ ERROR is defined multiple times
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-32354-suggest-import-rename.stderr b/src/test/ui/issues/issue-32354-suggest-import-rename.stderr
new file mode 100644
index 0000000..9668430
--- /dev/null
+++ b/src/test/ui/issues/issue-32354-suggest-import-rename.stderr
@@ -0,0 +1,17 @@
+error[E0252]: the name `ConstructorExtension` is defined multiple times
+  --> $DIR/issue-32354-suggest-import-rename.rs:14:5
+   |
+LL | use extension1::ConstructorExtension;
+   |     -------------------------------- previous import of the trait `ConstructorExtension` here
+LL | use extension2::ConstructorExtension;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ConstructorExtension` reimported here
+   |
+   = note: `ConstructorExtension` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | use extension2::ConstructorExtension as OtherConstructorExtension;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0252`.
diff --git a/src/test/ui/issues/issue-32377.rs b/src/test/ui/issues/issue-32377.rs
new file mode 100644
index 0000000..555f6ab
--- /dev/null
+++ b/src/test/ui/issues/issue-32377.rs
@@ -0,0 +1,19 @@
+// normalize-stderr-test "\d+ bits" -> "N bits"
+
+use std::mem;
+use std::marker::PhantomData;
+
+trait Foo {
+    type Error;
+}
+
+struct Bar<U: Foo> {
+    stream: PhantomData<U::Error>,
+}
+
+fn foo<U: Foo>(x: [usize; 2]) -> Bar<U> {
+    unsafe { mem::transmute(x) }
+    //~^ ERROR cannot transmute between types of different sizes, or dependently-sized types
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-32377.stderr b/src/test/ui/issues/issue-32377.stderr
new file mode 100644
index 0000000..5e870eb
--- /dev/null
+++ b/src/test/ui/issues/issue-32377.stderr
@@ -0,0 +1,12 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/issue-32377.rs:15:14
+   |
+LL |     unsafe { mem::transmute(x) }
+   |              ^^^^^^^^^^^^^^
+   |
+   = note: source type: `[usize; 2]` (N bits)
+   = note: target type: `Bar<U>` (N bits)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0512`.
diff --git a/src/test/ui/issues/issue-32655.rs b/src/test/ui/issues/issue-32655.rs
new file mode 100644
index 0000000..4634179
--- /dev/null
+++ b/src/test/ui/issues/issue-32655.rs
@@ -0,0 +1,22 @@
+#![allow(dead_code)]
+#![feature(rustc_attrs)]
+
+macro_rules! foo (
+    () => (
+        #[derive_Clone] //~ ERROR attribute `derive_Clone` is currently unknown
+        struct T;
+    );
+);
+
+macro_rules! bar (
+    ($e:item) => ($e)
+);
+
+foo!();
+
+bar!(
+    #[derive_Clone] //~ ERROR attribute `derive_Clone` is currently unknown
+    struct S;
+);
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-32655.stderr b/src/test/ui/issues/issue-32655.stderr
new file mode 100644
index 0000000..7b3c8e7
--- /dev/null
+++ b/src/test/ui/issues/issue-32655.stderr
@@ -0,0 +1,22 @@
+error[E0658]: The attribute `derive_Clone` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/issue-32655.rs:6:11
+   |
+LL |         #[derive_Clone]
+   |           ^^^^^^^^^^^^
+...
+LL | foo!();
+   | ------- in this macro invocation
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error[E0658]: The attribute `derive_Clone` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/issue-32655.rs:18:7
+   |
+LL |     #[derive_Clone]
+   |       ^^^^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/issues/issue-32709.rs b/src/test/ui/issues/issue-32709.rs
new file mode 100644
index 0000000..c05bfdc
--- /dev/null
+++ b/src/test/ui/issues/issue-32709.rs
@@ -0,0 +1,8 @@
+// Make sure that the span of try shorthand does not include the trailing
+// semicolon;
+fn a() -> Result<i32, ()> {
+    Err(5)?; //~ ERROR
+    Ok(1)
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-32709.stderr b/src/test/ui/issues/issue-32709.stderr
new file mode 100644
index 0000000..9127c75
--- /dev/null
+++ b/src/test/ui/issues/issue-32709.stderr
@@ -0,0 +1,11 @@
+error[E0277]: the trait bound `(): std::convert::From<{integer}>` is not satisfied
+  --> $DIR/issue-32709.rs:4:5
+   |
+LL |     Err(5)?;
+   |     ^^^^^^^ the trait `std::convert::From<{integer}>` is not implemented for `()`
+   |
+   = note: required by `std::convert::From::from`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-32782.rs b/src/test/ui/issues/issue-32782.rs
new file mode 100644
index 0000000..e3aa9f3
--- /dev/null
+++ b/src/test/ui/issues/issue-32782.rs
@@ -0,0 +1,13 @@
+macro_rules! bar (
+    () => ()
+);
+
+macro_rules! foo (
+    () => (
+        #[allow_internal_unstable] //~ ERROR allow_internal_unstable side-steps
+        bar!();
+    );
+);
+
+foo!();
+fn main() {}
diff --git a/src/test/ui/issues/issue-32782.stderr b/src/test/ui/issues/issue-32782.stderr
new file mode 100644
index 0000000..886f529
--- /dev/null
+++ b/src/test/ui/issues/issue-32782.stderr
@@ -0,0 +1,14 @@
+error[E0658]: allow_internal_unstable side-steps feature gating and stability checks
+  --> $DIR/issue-32782.rs:7:9
+   |
+LL |         #[allow_internal_unstable]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | foo!();
+   | ------- in this macro invocation
+   |
+   = help: add #![feature(allow_internal_unstable)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/issues/issue-32797.rs b/src/test/ui/issues/issue-32797.rs
new file mode 100644
index 0000000..5ceb7f4
--- /dev/null
+++ b/src/test/ui/issues/issue-32797.rs
@@ -0,0 +1,15 @@
+// compile-pass
+// skip-codegen
+
+pub use bar::*;
+mod bar {
+    pub use super::*;
+}
+
+pub use baz::*;
+mod baz {
+    pub use main as f;
+}
+
+
+pub fn main() {}
diff --git a/src/test/ui/issues/issue-32829-2.rs b/src/test/ui/issues/issue-32829-2.rs
new file mode 100644
index 0000000..c93c84b
--- /dev/null
+++ b/src/test/ui/issues/issue-32829-2.rs
@@ -0,0 +1,73 @@
+// ignore-tidy-linelength
+
+const bad : u32 = {
+    {
+        5;
+        0
+    }
+};
+
+const bad_two : u32 = {
+    {
+        invalid();
+        //~^ ERROR: calls in constants are limited to constant functions, tuple structs and tuple variants
+        0
+    }
+};
+
+const bad_three : u32 = {
+    {
+        valid();
+        0
+    }
+};
+
+static bad_four : u32 = {
+    {
+        5;
+        0
+    }
+};
+
+static bad_five : u32 = {
+    {
+        invalid();
+        //~^ ERROR: calls in statics are limited to constant functions, tuple structs and tuple variants
+        0
+    }
+};
+
+static bad_six : u32 = {
+    {
+        valid();
+        0
+    }
+};
+
+static mut bad_seven : u32 = {
+    {
+        5;
+        0
+    }
+};
+
+static mut bad_eight : u32 = {
+    {
+        invalid();
+        //~^ ERROR: calls in statics are limited to constant functions, tuple structs and tuple variants
+        0
+    }
+};
+
+static mut bad_nine : u32 = {
+    {
+        valid();
+        0
+    }
+};
+
+
+fn invalid() {}
+const fn valid() {}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-32829-2.stderr b/src/test/ui/issues/issue-32829-2.stderr
new file mode 100644
index 0000000..8d7423f
--- /dev/null
+++ b/src/test/ui/issues/issue-32829-2.stderr
@@ -0,0 +1,21 @@
+error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
+  --> $DIR/issue-32829-2.rs:12:9
+   |
+LL |         invalid();
+   |         ^^^^^^^^^
+
+error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
+  --> $DIR/issue-32829-2.rs:34:9
+   |
+LL |         invalid();
+   |         ^^^^^^^^^
+
+error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
+  --> $DIR/issue-32829-2.rs:56:9
+   |
+LL |         invalid();
+   |         ^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0015`.
diff --git a/src/test/ui/issues/issue-32829.rs b/src/test/ui/issues/issue-32829.rs
new file mode 100644
index 0000000..adfee7b
--- /dev/null
+++ b/src/test/ui/issues/issue-32829.rs
@@ -0,0 +1,6 @@
+static S : u64 = { { panic!("foo"); 0 } };
+//~^ ERROR panicking in statics is unstable
+
+fn main() {
+    println!("{:?}", S);
+}
diff --git a/src/test/ui/issues/issue-32829.stderr b/src/test/ui/issues/issue-32829.stderr
new file mode 100644
index 0000000..037f541
--- /dev/null
+++ b/src/test/ui/issues/issue-32829.stderr
@@ -0,0 +1,12 @@
+error[E0658]: panicking in statics is unstable (see issue #51999)
+  --> $DIR/issue-32829.rs:1:22
+   |
+LL | static S : u64 = { { panic!("foo"); 0 } };
+   |                      ^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_panic)] to the crate attributes to enable
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/issues/issue-32833.rs b/src/test/ui/issues/issue-32833.rs
new file mode 100644
index 0000000..379eedd
--- /dev/null
+++ b/src/test/ui/issues/issue-32833.rs
@@ -0,0 +1,7 @@
+use bar::Foo; //~ ERROR unresolved import `bar::Foo` [E0432]
+              //~^ no `Foo` in `bar`
+mod bar {
+    use Foo;
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-32833.stderr b/src/test/ui/issues/issue-32833.stderr
new file mode 100644
index 0000000..430cc0f
--- /dev/null
+++ b/src/test/ui/issues/issue-32833.stderr
@@ -0,0 +1,9 @@
+error[E0432]: unresolved import `bar::Foo`
+  --> $DIR/issue-32833.rs:1:5
+   |
+LL | use bar::Foo;
+   |     ^^^^^^^^ no `Foo` in `bar`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/issues/issue-32922.rs b/src/test/ui/issues/issue-32922.rs
new file mode 100644
index 0000000..b06b63c
--- /dev/null
+++ b/src/test/ui/issues/issue-32922.rs
@@ -0,0 +1,32 @@
+// compile-pass
+// skip-codegen
+#![allow(warnings)]
+
+macro_rules! foo { () => {
+    let x = 1;
+    macro_rules! bar { () => {x} }
+    let _ = bar!();
+}}
+
+macro_rules! m { // test issue #31856
+    ($n:ident) => (
+        let a = 1;
+        let $n = a;
+    )
+}
+
+macro_rules! baz {
+    ($i:ident) => {
+        let mut $i = 2;
+        $i = $i + 1;
+    }
+}
+
+
+fn main() {
+    foo! {};
+    bar! {};
+
+    let mut a = true;
+    baz!(a);
+}
diff --git a/src/test/ui/issues/issue-32950.rs b/src/test/ui/issues/issue-32950.rs
new file mode 100644
index 0000000..27d68a1
--- /dev/null
+++ b/src/test/ui/issues/issue-32950.rs
@@ -0,0 +1,9 @@
+#![feature(concat_idents)]
+
+#[derive(Debug)]
+struct Baz<T>(
+    concat_idents!(Foo, Bar) //~ ERROR `derive` cannot be used on items with type macros
+                             //~^ ERROR cannot find type `FooBar` in this scope
+);
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-32950.stderr b/src/test/ui/issues/issue-32950.stderr
new file mode 100644
index 0000000..3cdf35a
--- /dev/null
+++ b/src/test/ui/issues/issue-32950.stderr
@@ -0,0 +1,15 @@
+error: `derive` cannot be used on items with type macros
+  --> $DIR/issue-32950.rs:5:5
+   |
+LL |     concat_idents!(Foo, Bar)
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0412]: cannot find type `FooBar` in this scope
+  --> $DIR/issue-32950.rs:5:5
+   |
+LL |     concat_idents!(Foo, Bar)
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/src/test/ui/issues/issue-32963.rs b/src/test/ui/issues/issue-32963.rs
new file mode 100644
index 0000000..be59d35
--- /dev/null
+++ b/src/test/ui/issues/issue-32963.rs
@@ -0,0 +1,11 @@
+use std::mem;
+
+trait Misc {}
+
+fn size_of_copy<T: Copy+?Sized>() -> usize { mem::size_of::<T>() }
+
+fn main() {
+    size_of_copy::<Misc+Copy>();
+    //~^ ERROR only auto traits can be used as additional traits in a trait object
+    //~| ERROR the trait bound `dyn Misc: std::marker::Copy` is not satisfied
+}
diff --git a/src/test/ui/issues/issue-32963.stderr b/src/test/ui/issues/issue-32963.stderr
new file mode 100644
index 0000000..3e22ea7
--- /dev/null
+++ b/src/test/ui/issues/issue-32963.stderr
@@ -0,0 +1,22 @@
+error[E0225]: only auto traits can be used as additional traits in a trait object
+  --> $DIR/issue-32963.rs:8:25
+   |
+LL |     size_of_copy::<Misc+Copy>();
+   |                         ^^^^ non-auto additional trait
+
+error[E0277]: the trait bound `dyn Misc: std::marker::Copy` is not satisfied
+  --> $DIR/issue-32963.rs:8:5
+   |
+LL |     size_of_copy::<Misc+Copy>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `dyn Misc`
+   |
+note: required by `size_of_copy`
+  --> $DIR/issue-32963.rs:5:1
+   |
+LL | fn size_of_copy<T: Copy+?Sized>() -> usize { mem::size_of::<T>() }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0225, E0277.
+For more information about an error, try `rustc --explain E0225`.
diff --git a/src/test/ui/issues/issue-32995-2.rs b/src/test/ui/issues/issue-32995-2.rs
new file mode 100644
index 0000000..2234f68
--- /dev/null
+++ b/src/test/ui/issues/issue-32995-2.rs
@@ -0,0 +1,18 @@
+#![allow(unused)]
+
+fn main() {
+    { fn f<X: ::std::marker()::Send>() {} }
+    //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
+    //~| WARN previously accepted
+
+    { fn f() -> impl ::std::marker()::Send { } }
+    //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
+    //~| WARN previously accepted
+}
+
+#[derive(Clone)]
+struct X;
+
+impl ::std::marker()::Copy for X {}
+//~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
+//~| WARN previously accepted
diff --git a/src/test/ui/issues/issue-32995-2.stderr b/src/test/ui/issues/issue-32995-2.stderr
new file mode 100644
index 0000000..104b76c
--- /dev/null
+++ b/src/test/ui/issues/issue-32995-2.stderr
@@ -0,0 +1,30 @@
+error: parenthesized type parameters may only be used with a `Fn` trait
+  --> $DIR/issue-32995-2.rs:4:28
+   |
+LL |     { fn f<X: ::std::marker()::Send>() {} }
+   |                            ^^
+   |
+   = note: #[deny(parenthesized_params_in_types_and_modules)] on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #42238 <https://github.com/rust-lang/rust/issues/42238>
+
+error: parenthesized type parameters may only be used with a `Fn` trait
+  --> $DIR/issue-32995-2.rs:8:35
+   |
+LL |     { fn f() -> impl ::std::marker()::Send { } }
+   |                                   ^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #42238 <https://github.com/rust-lang/rust/issues/42238>
+
+error: parenthesized type parameters may only be used with a `Fn` trait
+  --> $DIR/issue-32995-2.rs:16:19
+   |
+LL | impl ::std::marker()::Copy for X {}
+   |                   ^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #42238 <https://github.com/rust-lang/rust/issues/42238>
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/issues/issue-32995.rs b/src/test/ui/issues/issue-32995.rs
new file mode 100644
index 0000000..c32fb63
--- /dev/null
+++ b/src/test/ui/issues/issue-32995.rs
@@ -0,0 +1,33 @@
+#![allow(unused)]
+
+fn main() {
+    let x: usize() = 1;
+    //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
+    //~| WARN previously accepted
+
+    let b: ::std::boxed()::Box<_> = Box::new(1);
+    //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
+    //~| WARN previously accepted
+
+    let p = ::std::str::()::from_utf8(b"foo").unwrap();
+    //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
+    //~| WARN previously accepted
+
+    let p = ::std::str::from_utf8::()(b"foo").unwrap();
+    //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
+    //~| WARN previously accepted
+
+    let o : Box<::std::marker()::Send> = Box::new(1);
+    //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
+    //~| WARN previously accepted
+
+    let o : Box<Send + ::std::marker()::Sync> = Box::new(1);
+    //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
+    //~| WARN previously accepted
+}
+
+fn foo<X:Default>() {
+    let d : X() = Default::default();
+    //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
+    //~| WARN previously accepted
+}
diff --git a/src/test/ui/issues/issue-32995.stderr b/src/test/ui/issues/issue-32995.stderr
new file mode 100644
index 0000000..97b4b7fa
--- /dev/null
+++ b/src/test/ui/issues/issue-32995.stderr
@@ -0,0 +1,66 @@
+error: parenthesized type parameters may only be used with a `Fn` trait
+  --> $DIR/issue-32995.rs:4:17
+   |
+LL |     let x: usize() = 1;
+   |                 ^^
+   |
+   = note: #[deny(parenthesized_params_in_types_and_modules)] on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #42238 <https://github.com/rust-lang/rust/issues/42238>
+
+error: parenthesized type parameters may only be used with a `Fn` trait
+  --> $DIR/issue-32995.rs:8:24
+   |
+LL |     let b: ::std::boxed()::Box<_> = Box::new(1);
+   |                        ^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #42238 <https://github.com/rust-lang/rust/issues/42238>
+
+error: parenthesized type parameters may only be used with a `Fn` trait
+  --> $DIR/issue-32995.rs:12:25
+   |
+LL |     let p = ::std::str::()::from_utf8(b"foo").unwrap();
+   |                         ^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #42238 <https://github.com/rust-lang/rust/issues/42238>
+
+error: parenthesized type parameters may only be used with a `Fn` trait
+  --> $DIR/issue-32995.rs:16:36
+   |
+LL |     let p = ::std::str::from_utf8::()(b"foo").unwrap();
+   |                                    ^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #42238 <https://github.com/rust-lang/rust/issues/42238>
+
+error: parenthesized type parameters may only be used with a `Fn` trait
+  --> $DIR/issue-32995.rs:20:30
+   |
+LL |     let o : Box<::std::marker()::Send> = Box::new(1);
+   |                              ^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #42238 <https://github.com/rust-lang/rust/issues/42238>
+
+error: parenthesized type parameters may only be used with a `Fn` trait
+  --> $DIR/issue-32995.rs:24:37
+   |
+LL |     let o : Box<Send + ::std::marker()::Sync> = Box::new(1);
+   |                                     ^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #42238 <https://github.com/rust-lang/rust/issues/42238>
+
+error: parenthesized type parameters may only be used with a `Fn` trait
+  --> $DIR/issue-32995.rs:30:14
+   |
+LL |     let d : X() = Default::default();
+   |              ^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #42238 <https://github.com/rust-lang/rust/issues/42238>
+
+error: aborting due to 7 previous errors
+
diff --git a/src/test/ui/issues/issue-33140-hack-boundaries.rs b/src/test/ui/issues/issue-33140-hack-boundaries.rs
new file mode 100644
index 0000000..fbdef51
--- /dev/null
+++ b/src/test/ui/issues/issue-33140-hack-boundaries.rs
@@ -0,0 +1,80 @@
+#![feature(optin_builtin_traits)]
+#![allow(order_dependent_trait_objects)]
+
+// Check that the issue #33140 hack does not allow unintended things.
+
+// OK
+trait Trait0 {
+}
+
+impl Trait0 for dyn Send {}
+impl Trait0 for dyn Send {}
+
+// Problem 1: associated types
+trait Trait1 {
+    fn my_fn(&self) {}
+}
+
+impl Trait1 for dyn Send {}
+impl Trait1 for dyn Send {}
+//~^ ERROR E0119
+
+// Problem 2: negative impl
+trait Trait2 {
+}
+
+impl Trait2 for dyn Send {}
+impl !Trait2 for dyn Send {}
+//~^ ERROR E0119
+
+
+// Problem 3: type parameter
+trait Trait3<T: ?Sized> {
+}
+
+impl Trait3<dyn Sync> for dyn Send {}
+impl Trait3<dyn Sync> for dyn Send {}
+//~^ ERROR E0119
+
+// Problem 4a: not a trait object - generic
+trait Trait4a {
+}
+
+impl<T: ?Sized> Trait4a for T {}
+impl Trait4a for dyn Send {}
+//~^ ERROR E0119
+
+// Problem 4b: not a trait object - misc
+trait Trait4b {
+}
+
+impl Trait4b for () {}
+impl Trait4b for () {}
+//~^ ERROR E0119
+
+// Problem 4c: not a principal-less trait object
+trait Trait4c {
+}
+
+impl Trait4c for dyn Trait1 + Send {}
+impl Trait4c for dyn Trait1 + Send {}
+//~^ ERROR E0119
+
+// Problem 4d: lifetimes
+trait Trait4d {
+}
+
+impl<'a> Trait4d for dyn Send + 'a {}
+impl<'a> Trait4d for dyn Send + 'a {}
+//~^ ERROR E0119
+
+
+// Problem 5: where-clauses
+trait Trait5 {
+}
+
+impl Trait5 for dyn Send {}
+impl Trait5 for dyn Send where u32: Copy {}
+//~^ ERROR E0119
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-33140-hack-boundaries.stderr b/src/test/ui/issues/issue-33140-hack-boundaries.stderr
new file mode 100644
index 0000000..95aaa55
--- /dev/null
+++ b/src/test/ui/issues/issue-33140-hack-boundaries.stderr
@@ -0,0 +1,67 @@
+error[E0119]: conflicting implementations of trait `Trait1` for type `(dyn std::marker::Send + 'static)`:
+  --> $DIR/issue-33140-hack-boundaries.rs:19:1
+   |
+LL | impl Trait1 for dyn Send {}
+   | ------------------------ first implementation here
+LL | impl Trait1 for dyn Send {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + 'static)`
+
+error[E0119]: conflicting implementations of trait `Trait2` for type `(dyn std::marker::Send + 'static)`:
+  --> $DIR/issue-33140-hack-boundaries.rs:27:1
+   |
+LL | impl Trait2 for dyn Send {}
+   | ------------------------ first implementation here
+LL | impl !Trait2 for dyn Send {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + 'static)`
+
+error[E0119]: conflicting implementations of trait `Trait3<(dyn std::marker::Sync + 'static)>` for type `(dyn std::marker::Send + 'static)`:
+  --> $DIR/issue-33140-hack-boundaries.rs:36:1
+   |
+LL | impl Trait3<dyn Sync> for dyn Send {}
+   | ---------------------------------- first implementation here
+LL | impl Trait3<dyn Sync> for dyn Send {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + 'static)`
+
+error[E0119]: conflicting implementations of trait `Trait4a` for type `(dyn std::marker::Send + 'static)`:
+  --> $DIR/issue-33140-hack-boundaries.rs:44:1
+   |
+LL | impl<T: ?Sized> Trait4a for T {}
+   | ----------------------------- first implementation here
+LL | impl Trait4a for dyn Send {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + 'static)`
+
+error[E0119]: conflicting implementations of trait `Trait4b` for type `()`:
+  --> $DIR/issue-33140-hack-boundaries.rs:52:1
+   |
+LL | impl Trait4b for () {}
+   | ------------------- first implementation here
+LL | impl Trait4b for () {}
+   | ^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()`
+
+error[E0119]: conflicting implementations of trait `Trait4c` for type `(dyn Trait1 + std::marker::Send + 'static)`:
+  --> $DIR/issue-33140-hack-boundaries.rs:60:1
+   |
+LL | impl Trait4c for dyn Trait1 + Send {}
+   | ---------------------------------- first implementation here
+LL | impl Trait4c for dyn Trait1 + Send {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Trait1 + std::marker::Send + 'static)`
+
+error[E0119]: conflicting implementations of trait `Trait4d` for type `dyn std::marker::Send`:
+  --> $DIR/issue-33140-hack-boundaries.rs:68:1
+   |
+LL | impl<'a> Trait4d for dyn Send + 'a {}
+   | ---------------------------------- first implementation here
+LL | impl<'a> Trait4d for dyn Send + 'a {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `dyn std::marker::Send`
+
+error[E0119]: conflicting implementations of trait `Trait5` for type `(dyn std::marker::Send + 'static)`:
+  --> $DIR/issue-33140-hack-boundaries.rs:77:1
+   |
+LL | impl Trait5 for dyn Send {}
+   | ------------------------ first implementation here
+LL | impl Trait5 for dyn Send where u32: Copy {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + 'static)`
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/issues/issue-33140-traitobject-crate.rs b/src/test/ui/issues/issue-33140-traitobject-crate.rs
new file mode 100644
index 0000000..2b644817
--- /dev/null
+++ b/src/test/ui/issues/issue-33140-traitobject-crate.rs
@@ -0,0 +1,101 @@
+// compile-pass
+
+#![warn(order_dependent_trait_objects)]
+
+// Check that traitobject 0.1.0 compiles
+
+//! # traitobject
+//!
+//! Unsafe helpers for working with raw TraitObjects.
+
+/// A trait implemented for all trait objects.
+///
+/// Implementations for all traits in std are provided.
+pub unsafe trait Trait {}
+
+unsafe impl Trait for ::std::any::Any + Send { }
+unsafe impl Trait for ::std::any::Any + Sync { }
+unsafe impl Trait for ::std::any::Any + Send + Sync { }
+unsafe impl<T: ?Sized> Trait for ::std::borrow::Borrow<T> + Send { }
+unsafe impl<T: ?Sized> Trait for ::std::borrow::Borrow<T> + Sync { }
+unsafe impl<T: ?Sized> Trait for ::std::borrow::Borrow<T> + Send + Sync { }
+unsafe impl<T: ?Sized> Trait for ::std::borrow::BorrowMut<T> + Send { }
+unsafe impl<T: ?Sized> Trait for ::std::borrow::BorrowMut<T> + Sync { }
+unsafe impl<T: ?Sized> Trait for ::std::borrow::BorrowMut<T> + Send + Sync { }
+unsafe impl<T: ?Sized> Trait for ::std::convert::AsMut<T> + Send { }
+unsafe impl<T: ?Sized> Trait for ::std::convert::AsMut<T> + Sync { }
+unsafe impl<T: ?Sized> Trait for ::std::convert::AsMut<T> + Send + Sync { }
+unsafe impl<T: ?Sized> Trait for ::std::convert::AsRef<T> + Send { }
+unsafe impl<T: ?Sized> Trait for ::std::convert::AsRef<T> + Sync { }
+unsafe impl<T: ?Sized> Trait for ::std::convert::AsRef<T> + Send + Sync { }
+unsafe impl Trait for ::std::error::Error + Send { }
+unsafe impl Trait for ::std::error::Error + Sync { }
+unsafe impl Trait for ::std::error::Error + Send + Sync { }
+unsafe impl Trait for ::std::fmt::Binary + Send { }
+unsafe impl Trait for ::std::fmt::Binary + Sync { }
+unsafe impl Trait for ::std::fmt::Binary + Send + Sync { }
+unsafe impl Trait for ::std::fmt::Debug + Send { }
+unsafe impl Trait for ::std::fmt::Debug + Sync { }
+unsafe impl Trait for ::std::fmt::Debug + Send + Sync { }
+unsafe impl Trait for ::std::fmt::Display + Send { }
+unsafe impl Trait for ::std::fmt::Display + Sync { }
+unsafe impl Trait for ::std::fmt::Display + Send + Sync { }
+unsafe impl Trait for ::std::fmt::LowerExp + Send { }
+unsafe impl Trait for ::std::fmt::LowerExp + Sync { }
+unsafe impl Trait for ::std::fmt::LowerExp + Send + Sync { }
+unsafe impl Trait for ::std::fmt::LowerHex + Send { }
+unsafe impl Trait for ::std::fmt::LowerHex + Sync { }
+unsafe impl Trait for ::std::fmt::LowerHex + Send + Sync { }
+unsafe impl Trait for ::std::fmt::Octal + Send { }
+unsafe impl Trait for ::std::fmt::Octal + Sync { }
+unsafe impl Trait for ::std::fmt::Octal + Send + Sync { }
+unsafe impl Trait for ::std::fmt::Pointer + Send { }
+unsafe impl Trait for ::std::fmt::Pointer + Sync { }
+unsafe impl Trait for ::std::fmt::Pointer + Send + Sync { }
+unsafe impl Trait for ::std::fmt::UpperExp + Send { }
+unsafe impl Trait for ::std::fmt::UpperExp + Sync { }
+unsafe impl Trait for ::std::fmt::UpperExp + Send + Sync { }
+unsafe impl Trait for ::std::fmt::UpperHex + Send { }
+unsafe impl Trait for ::std::fmt::UpperHex + Sync { }
+unsafe impl Trait for ::std::fmt::UpperHex + Send + Sync { }
+unsafe impl Trait for ::std::fmt::Write + Send { }
+unsafe impl Trait for ::std::fmt::Write + Sync { }
+unsafe impl Trait for ::std::fmt::Write + Send + Sync { }
+unsafe impl Trait for ::std::hash::Hasher + Send { }
+unsafe impl Trait for ::std::hash::Hasher + Sync { }
+unsafe impl Trait for ::std::hash::Hasher + Send + Sync { }
+unsafe impl Trait for ::std::io::BufRead + Send { }
+unsafe impl Trait for ::std::io::BufRead + Sync { }
+unsafe impl Trait for ::std::io::BufRead + Send + Sync { }
+unsafe impl Trait for ::std::io::Read + Send { }
+unsafe impl Trait for ::std::io::Read + Sync { }
+unsafe impl Trait for ::std::io::Read + Send + Sync { }
+unsafe impl Trait for ::std::io::Seek + Send { }
+unsafe impl Trait for ::std::io::Seek + Sync { }
+unsafe impl Trait for ::std::io::Seek + Send + Sync { }
+unsafe impl Trait for ::std::io::Write + Send { }
+unsafe impl Trait for ::std::io::Write + Sync { }
+unsafe impl Trait for ::std::io::Write + Send + Sync { }
+unsafe impl<T, I> Trait for ::std::iter::IntoIterator<IntoIter=I, Item=T> { }
+unsafe impl<T> Trait for ::std::iter::Iterator<Item=T> + Send { }
+unsafe impl<T> Trait for ::std::iter::Iterator<Item=T> + Sync { }
+unsafe impl<T> Trait for ::std::iter::Iterator<Item=T> + Send + Sync { }
+unsafe impl Trait for ::std::marker::Send + Send { }
+unsafe impl Trait for ::std::marker::Send + Sync { }
+unsafe impl Trait for ::std::marker::Send + Send + Sync { }
+unsafe impl Trait for ::std::marker::Sync + Send { }
+unsafe impl Trait for ::std::marker::Sync + Sync { }
+unsafe impl Trait for ::std::marker::Sync + Send + Sync { }
+unsafe impl Trait for ::std::ops::Drop + Send { }
+unsafe impl Trait for ::std::ops::Drop + Sync { }
+unsafe impl Trait for ::std::ops::Drop + Send + Sync { }
+unsafe impl Trait for ::std::string::ToString + Send { }
+unsafe impl Trait for ::std::string::ToString + Sync { }
+unsafe impl Trait for ::std::string::ToString + Send + Sync { }
+fn assert_trait<T: Trait + ?Sized>() {}
+
+fn main() {
+    assert_trait::<dyn Send>();
+    assert_trait::<dyn Sync>();
+    assert_trait::<dyn Send + Sync>();
+}
diff --git a/src/test/ui/issues/issue-33140-traitobject-crate.stderr b/src/test/ui/issues/issue-33140-traitobject-crate.stderr
new file mode 100644
index 0000000..6f71e79
--- /dev/null
+++ b/src/test/ui/issues/issue-33140-traitobject-crate.stderr
@@ -0,0 +1,39 @@
+warning: conflicting implementations of trait `Trait` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`: (E0119)
+  --> $DIR/issue-33140-traitobject-crate.rs:85:1
+   |
+LL | unsafe impl Trait for ::std::marker::Send + Sync { }
+   | ------------------------------------------------ first implementation here
+LL | unsafe impl Trait for ::std::marker::Send + Send + Sync { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + std::marker::Sync + 'static)`
+   |
+note: lint level defined here
+  --> $DIR/issue-33140-traitobject-crate.rs:3:9
+   |
+LL | #![warn(order_dependent_trait_objects)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #56484 <https://github.com/rust-lang/rust/issues/56484>
+
+warning: conflicting implementations of trait `Trait` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`: (E0119)
+  --> $DIR/issue-33140-traitobject-crate.rs:86:1
+   |
+LL | unsafe impl Trait for ::std::marker::Send + Send + Sync { }
+   | ------------------------------------------------------- first implementation here
+LL | unsafe impl Trait for ::std::marker::Sync + Send { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + std::marker::Sync + 'static)`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #56484 <https://github.com/rust-lang/rust/issues/56484>
+
+warning: conflicting implementations of trait `Trait` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`: (E0119)
+  --> $DIR/issue-33140-traitobject-crate.rs:88:1
+   |
+LL | unsafe impl Trait for ::std::marker::Sync + Send { }
+   | ------------------------------------------------ first implementation here
+LL | unsafe impl Trait for ::std::marker::Sync + Sync { }
+LL | unsafe impl Trait for ::std::marker::Sync + Send + Sync { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + std::marker::Sync + 'static)`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #56484 <https://github.com/rust-lang/rust/issues/56484>
+
diff --git a/src/test/ui/issues/issue-33140.rs b/src/test/ui/issues/issue-33140.rs
new file mode 100644
index 0000000..930e242
--- /dev/null
+++ b/src/test/ui/issues/issue-33140.rs
@@ -0,0 +1,47 @@
+trait Trait {
+    fn xyz() -> bool;
+}
+
+impl Trait for dyn Send + Sync {
+    fn xyz() -> bool { false }
+}
+
+impl Trait for dyn Sync + Send {
+//~^ ERROR conflicting implementations
+    fn xyz() -> bool { true }
+}
+
+trait Trait2 {
+    fn uvw() -> bool;
+}
+
+impl Trait2 for dyn Send + Sync {
+    fn uvw() -> bool { false }
+}
+
+impl Trait2 for dyn Sync + Send + Sync {
+//~^ ERROR conflicting implementations
+    fn uvw() -> bool { true }
+}
+
+struct Foo<T: ?Sized>(T);
+impl Foo<dyn Send + Sync> {
+    fn abc() -> bool { //~ ERROR duplicate definitions with name `abc`
+        false
+    }
+}
+
+impl Foo<dyn Sync + Send> {
+    fn abc() -> bool {
+        true
+    }
+}
+
+fn main() {
+    assert_eq!(<Send+Sync>::xyz(), false);
+    assert_eq!(<Sync+Send>::xyz(), true);
+    assert_eq!(<Send+Sync>::uvw(), false);
+    assert_eq!(<Sync+Send+Sync>::uvw(), true);
+    assert_eq!(<Foo<Send+Sync>>::abc(), false);
+    assert_eq!(<Foo<Sync+Send>>::abc(), true);
+}
diff --git a/src/test/ui/issues/issue-33140.stderr b/src/test/ui/issues/issue-33140.stderr
new file mode 100644
index 0000000..43065a2
--- /dev/null
+++ b/src/test/ui/issues/issue-33140.stderr
@@ -0,0 +1,35 @@
+error[E0119]: conflicting implementations of trait `Trait` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`:
+  --> $DIR/issue-33140.rs:9:1
+   |
+LL | impl Trait for dyn Send + Sync {
+   | ------------------------------ first implementation here
+...
+LL | impl Trait for dyn Sync + Send {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + std::marker::Sync + 'static)`
+
+error[E0119]: conflicting implementations of trait `Trait2` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`:
+  --> $DIR/issue-33140.rs:22:1
+   |
+LL | impl Trait2 for dyn Send + Sync {
+   | ------------------------------- first implementation here
+...
+LL | impl Trait2 for dyn Sync + Send + Sync {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + std::marker::Sync + 'static)`
+
+error[E0592]: duplicate definitions with name `abc`
+  --> $DIR/issue-33140.rs:29:5
+   |
+LL | /     fn abc() -> bool {
+LL | |         false
+LL | |     }
+   | |_____^ duplicate definitions for `abc`
+...
+LL | /     fn abc() -> bool {
+LL | |         true
+LL | |     }
+   | |_____- other definition for `abc`
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0119, E0592.
+For more information about an error, try `rustc --explain E0119`.
diff --git a/src/test/ui/issues/issue-33241.rs b/src/test/ui/issues/issue-33241.rs
new file mode 100644
index 0000000..4c5052a
--- /dev/null
+++ b/src/test/ui/issues/issue-33241.rs
@@ -0,0 +1,14 @@
+// compile-pass
+// skip-codegen
+
+use std::fmt;
+
+// CoerceUnsized is not implemented for tuples. You can still create
+// an unsized tuple by transmuting a trait object.
+fn any<T>() -> T { unreachable!() }
+
+
+fn main() {
+    let t: &(u8, fmt::Debug) = any();
+    println!("{:?}", &t.1);
+}
diff --git a/src/test/ui/issues/issue-33264.rs b/src/test/ui/issues/issue-33264.rs
new file mode 100644
index 0000000..7cba4df
--- /dev/null
+++ b/src/test/ui/issues/issue-33264.rs
@@ -0,0 +1,30 @@
+// compile-pass
+// only-x86_64
+
+#![allow(dead_code, non_upper_case_globals)]
+#![feature(asm)]
+
+#[repr(C)]
+pub struct D32x4(f32,f32,f32,f32);
+
+impl D32x4 {
+    fn add(&self, vec: Self) -> Self {
+        unsafe {
+            let ret: Self;
+            asm!("
+                 movaps $1, %xmm1
+                 movaps $2, %xmm2
+                 addps %xmm1, %xmm2
+                 movaps $xmm1, $0
+                 "
+                 : "=r"(ret)
+                 : "1"(self), "2"(vec)
+                 : "xmm1", "xmm2"
+                 );
+            ret
+        }
+    }
+}
+
+fn main() { }
+
diff --git a/src/test/ui/issues/issue-33287.rs b/src/test/ui/issues/issue-33287.rs
new file mode 100644
index 0000000..c6e1f4d
--- /dev/null
+++ b/src/test/ui/issues/issue-33287.rs
@@ -0,0 +1,11 @@
+// compile-pass
+#![allow(dead_code)]
+#![allow(unused_variables)]
+const A: [u32; 1] = [0];
+
+fn test() {
+    let range = A[1]..;
+}
+
+fn main() { }
+
diff --git a/src/test/ui/issues/issue-33293.rs b/src/test/ui/issues/issue-33293.rs
new file mode 100644
index 0000000..d367037
--- /dev/null
+++ b/src/test/ui/issues/issue-33293.rs
@@ -0,0 +1,6 @@
+fn main() {
+    match 0 {
+        aaa::bbb(_) => ()
+        //~^ ERROR failed to resolve: use of undeclared type or module `aaa`
+    };
+}
diff --git a/src/test/ui/issues/issue-33293.stderr b/src/test/ui/issues/issue-33293.stderr
new file mode 100644
index 0000000..6b7333f
--- /dev/null
+++ b/src/test/ui/issues/issue-33293.stderr
@@ -0,0 +1,9 @@
+error[E0433]: failed to resolve: use of undeclared type or module `aaa`
+  --> $DIR/issue-33293.rs:3:9
+   |
+LL |         aaa::bbb(_) => ()
+   |         ^^^ use of undeclared type or module `aaa`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/issues/issue-3344.rs b/src/test/ui/issues/issue-3344.rs
new file mode 100644
index 0000000..de764b3
--- /dev/null
+++ b/src/test/ui/issues/issue-3344.rs
@@ -0,0 +1,7 @@
+#[derive(PartialEq)]
+struct Thing(usize);
+impl PartialOrd for Thing { //~ ERROR not all trait items implemented, missing: `partial_cmp`
+    fn le(&self, other: &Thing) -> bool { true }
+    fn ge(&self, other: &Thing) -> bool { true }
+}
+fn main() {}
diff --git a/src/test/ui/issues/issue-3344.stderr b/src/test/ui/issues/issue-3344.stderr
new file mode 100644
index 0000000..6593e07
--- /dev/null
+++ b/src/test/ui/issues/issue-3344.stderr
@@ -0,0 +1,11 @@
+error[E0046]: not all trait items implemented, missing: `partial_cmp`
+  --> $DIR/issue-3344.rs:3:1
+   |
+LL | impl PartialOrd for Thing {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^ missing `partial_cmp` in implementation
+   |
+   = note: `partial_cmp` from trait: `fn(&Self, &Rhs) -> std::option::Option<std::cmp::Ordering>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0046`.
diff --git a/src/test/ui/issues/issue-33464.rs b/src/test/ui/issues/issue-33464.rs
new file mode 100644
index 0000000..a0edb5f
--- /dev/null
+++ b/src/test/ui/issues/issue-33464.rs
@@ -0,0 +1,10 @@
+// Make sure that the spans of import errors are correct.
+
+use abc::one_el;
+//~^ ERROR
+use abc::{a, bbb, cccccc};
+//~^ ERROR
+use a_very_long_name::{el, el2};
+//~^ ERROR
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-33464.stderr b/src/test/ui/issues/issue-33464.stderr
new file mode 100644
index 0000000..bbf8d21
--- /dev/null
+++ b/src/test/ui/issues/issue-33464.stderr
@@ -0,0 +1,21 @@
+error[E0432]: unresolved import `abc`
+  --> $DIR/issue-33464.rs:3:5
+   |
+LL | use abc::one_el;
+   |     ^^^ maybe a missing `extern crate abc;`?
+
+error[E0432]: unresolved import `abc`
+  --> $DIR/issue-33464.rs:5:5
+   |
+LL | use abc::{a, bbb, cccccc};
+   |     ^^^ maybe a missing `extern crate abc;`?
+
+error[E0432]: unresolved import `a_very_long_name`
+  --> $DIR/issue-33464.rs:7:5
+   |
+LL | use a_very_long_name::{el, el2};
+   |     ^^^^^^^^^^^^^^^^ maybe a missing `extern crate a_very_long_name;`?
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/issues/issue-33504.rs b/src/test/ui/issues/issue-33504.rs
new file mode 100644
index 0000000..89cc06e
--- /dev/null
+++ b/src/test/ui/issues/issue-33504.rs
@@ -0,0 +1,9 @@
+// Shadowing a unit-like enum in a closure
+
+struct Test;
+
+fn main() {
+    || {
+        let Test = 1; //~ ERROR mismatched types
+    };
+}
diff --git a/src/test/ui/issues/issue-33504.stderr b/src/test/ui/issues/issue-33504.stderr
new file mode 100644
index 0000000..7af555e
--- /dev/null
+++ b/src/test/ui/issues/issue-33504.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-33504.rs:7:13
+   |
+LL |         let Test = 1;
+   |             ^^^^ expected integer, found struct `Test`
+   |
+   = note: expected type `{integer}`
+              found type `Test`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-33525.rs b/src/test/ui/issues/issue-33525.rs
new file mode 100644
index 0000000..74f21ef
--- /dev/null
+++ b/src/test/ui/issues/issue-33525.rs
@@ -0,0 +1,5 @@
+fn main() {
+    a; //~ ERROR cannot find value `a`
+    "".lorem; //~ ERROR no field
+    "".ipsum; //~ ERROR no field
+}
diff --git a/src/test/ui/issues/issue-33525.stderr b/src/test/ui/issues/issue-33525.stderr
new file mode 100644
index 0000000..584b903
--- /dev/null
+++ b/src/test/ui/issues/issue-33525.stderr
@@ -0,0 +1,22 @@
+error[E0425]: cannot find value `a` in this scope
+  --> $DIR/issue-33525.rs:2:5
+   |
+LL |     a;
+   |     ^ not found in this scope
+
+error[E0609]: no field `lorem` on type `&'static str`
+  --> $DIR/issue-33525.rs:3:8
+   |
+LL |     "".lorem;
+   |        ^^^^^
+
+error[E0609]: no field `ipsum` on type `&'static str`
+  --> $DIR/issue-33525.rs:4:8
+   |
+LL |     "".ipsum;
+   |        ^^^^^
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0425, E0609.
+For more information about an error, try `rustc --explain E0425`.
diff --git a/src/test/ui/issues/issue-33571.rs b/src/test/ui/issues/issue-33571.rs
new file mode 100644
index 0000000..223bbc3
--- /dev/null
+++ b/src/test/ui/issues/issue-33571.rs
@@ -0,0 +1,6 @@
+#[derive(Clone,
+         Sync, //~ ERROR this unsafe trait should be implemented explicitly
+         Copy)]
+enum Foo {}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-33571.stderr b/src/test/ui/issues/issue-33571.stderr
new file mode 100644
index 0000000..5d83a08
--- /dev/null
+++ b/src/test/ui/issues/issue-33571.stderr
@@ -0,0 +1,8 @@
+error: this unsafe trait should be implemented explicitly
+  --> $DIR/issue-33571.rs:2:10
+   |
+LL |          Sync,
+   |          ^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-33819.nll.stderr b/src/test/ui/issues/issue-33819.nll.stderr
new file mode 100644
index 0000000..8bc2d82
--- /dev/null
+++ b/src/test/ui/issues/issue-33819.nll.stderr
@@ -0,0 +1,12 @@
+error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable
+  --> $DIR/issue-33819.rs:4:34
+   |
+LL |         Some(ref v) => { let a = &mut v; },
+   |                                  ^^^^^^
+   |                                  |
+   |                                  cannot borrow as mutable
+   |                                  try removing `&mut` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/issues/issue-33819.rs b/src/test/ui/issues/issue-33819.rs
new file mode 100644
index 0000000..7f25ebd1
--- /dev/null
+++ b/src/test/ui/issues/issue-33819.rs
@@ -0,0 +1,9 @@
+fn main() {
+    let mut op = Some(2);
+    match op {
+        Some(ref v) => { let a = &mut v; },
+        //~^ ERROR:cannot borrow immutable
+        //~| cannot borrow mutably
+        None => {},
+    }
+}
diff --git a/src/test/ui/issues/issue-33819.stderr b/src/test/ui/issues/issue-33819.stderr
new file mode 100644
index 0000000..09b8835
--- /dev/null
+++ b/src/test/ui/issues/issue-33819.stderr
@@ -0,0 +1,9 @@
+error[E0596]: cannot borrow immutable local variable `v` as mutable
+  --> $DIR/issue-33819.rs:4:39
+   |
+LL |         Some(ref v) => { let a = &mut v; },
+   |                                       ^ cannot borrow mutably
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/issues/issue-33903.rs b/src/test/ui/issues/issue-33903.rs
new file mode 100644
index 0000000..98544ac
--- /dev/null
+++ b/src/test/ui/issues/issue-33903.rs
@@ -0,0 +1,11 @@
+// compile-pass
+#![allow(dead_code)]
+// Issue 33903:
+// Built-in indexing should be used even when the index is not
+// trivially an integer
+// Only built-in indexing can be used in constant expressions
+
+const FOO: i32 = [12, 34][0 + 1];
+
+fn main() {}
+
diff --git a/src/test/ui/issues/issue-33941.rs b/src/test/ui/issues/issue-33941.rs
new file mode 100644
index 0000000..ccaa633
--- /dev/null
+++ b/src/test/ui/issues/issue-33941.rs
@@ -0,0 +1,6 @@
+use std::collections::HashMap;
+
+fn main() {
+    for _ in HashMap::new().iter().cloned() {} //~ ERROR type mismatch
+    //~^ ERROR type mismatch
+}
diff --git a/src/test/ui/issues/issue-33941.stderr b/src/test/ui/issues/issue-33941.stderr
new file mode 100644
index 0000000..596921e
--- /dev/null
+++ b/src/test/ui/issues/issue-33941.stderr
@@ -0,0 +1,22 @@
+error[E0271]: type mismatch resolving `<std::collections::hash_map::Iter<'_, _, _> as std::iter::Iterator>::Item == &_`
+  --> $DIR/issue-33941.rs:4:36
+   |
+LL |     for _ in HashMap::new().iter().cloned() {}
+   |                                    ^^^^^^ expected tuple, found reference
+   |
+   = note: expected type `(&_, &_)`
+              found type `&_`
+
+error[E0271]: type mismatch resolving `<std::collections::hash_map::Iter<'_, _, _> as std::iter::Iterator>::Item == &_`
+  --> $DIR/issue-33941.rs:4:14
+   |
+LL |     for _ in HashMap::new().iter().cloned() {}
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected tuple, found reference
+   |
+   = note: expected type `(&_, &_)`
+              found type `&_`
+   = note: required because of the requirements on the impl of `std::iter::Iterator` for `std::iter::Cloned<std::collections::hash_map::Iter<'_, _, _>>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/issues/issue-34028.rs b/src/test/ui/issues/issue-34028.rs
new file mode 100644
index 0000000..8ebc730
--- /dev/null
+++ b/src/test/ui/issues/issue-34028.rs
@@ -0,0 +1,12 @@
+// compile-pass
+// skip-codegen
+
+macro_rules! m {
+    () => { #[cfg(any())] fn f() {} }
+}
+
+trait T {}
+impl T for () { m!(); }
+
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-34047.rs b/src/test/ui/issues/issue-34047.rs
new file mode 100644
index 0000000..5519617
--- /dev/null
+++ b/src/test/ui/issues/issue-34047.rs
@@ -0,0 +1,8 @@
+const C: u8 = 0;
+
+fn main() {
+    match 1u8 {
+        mut C => {} //~ ERROR match bindings cannot shadow constants
+        _ => {}
+    }
+}
diff --git a/src/test/ui/issues/issue-34047.stderr b/src/test/ui/issues/issue-34047.stderr
new file mode 100644
index 0000000..f770ded5
--- /dev/null
+++ b/src/test/ui/issues/issue-34047.stderr
@@ -0,0 +1,12 @@
+error[E0530]: match bindings cannot shadow constants
+  --> $DIR/issue-34047.rs:5:13
+   |
+LL | const C: u8 = 0;
+   | ---------------- the constant `C` is defined here
+...
+LL |         mut C => {}
+   |             ^ cannot be named the same as a constant
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0530`.
diff --git a/src/test/ui/issues/issue-34171.rs b/src/test/ui/issues/issue-34171.rs
new file mode 100644
index 0000000..25a5f72
--- /dev/null
+++ b/src/test/ui/issues/issue-34171.rs
@@ -0,0 +1,12 @@
+// compile-pass
+// skip-codegen
+
+macro_rules! null { ($i:tt) => {} }
+macro_rules! apply_null {
+    ($i:item) => { null! { $i } }
+}
+
+
+fn main() {
+    apply_null!(#[cfg(all())] fn f() {});
+}
diff --git a/src/test/ui/issues/issue-34194.rs b/src/test/ui/issues/issue-34194.rs
new file mode 100644
index 0000000..b65de91
--- /dev/null
+++ b/src/test/ui/issues/issue-34194.rs
@@ -0,0 +1,11 @@
+// compile-pass
+#![allow(dead_code)]
+
+struct A {
+    a: &'static (),
+}
+
+static B: &'static A = &A { a: &() };
+static C: &'static A = &B;
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-34209.rs b/src/test/ui/issues/issue-34209.rs
new file mode 100644
index 0000000..50095be
--- /dev/null
+++ b/src/test/ui/issues/issue-34209.rs
@@ -0,0 +1,12 @@
+enum S {
+    A,
+}
+
+fn bug(l: S) {
+    match l {
+        S::B { } => { },
+        //~^ ERROR no variant `B` on enum `S`
+    }
+}
+
+fn main () {}
diff --git a/src/test/ui/issues/issue-34209.stderr b/src/test/ui/issues/issue-34209.stderr
new file mode 100644
index 0000000..79aba89
--- /dev/null
+++ b/src/test/ui/issues/issue-34209.stderr
@@ -0,0 +1,8 @@
+error: no variant `B` on enum `S`
+  --> $DIR/issue-34209.rs:7:9
+   |
+LL |         S::B { } => { },
+   |         ^^^^ help: did you mean: `S::A`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-34222-1.rs b/src/test/ui/issues/issue-34222-1.rs
new file mode 100644
index 0000000..d36dddc
--- /dev/null
+++ b/src/test/ui/issues/issue-34222-1.rs
@@ -0,0 +1,3 @@
+fn main() {
+    /// comment //~ ERROR found a documentation comment that doesn't document anything
+}
diff --git a/src/test/ui/issues/issue-34222-1.stderr b/src/test/ui/issues/issue-34222-1.stderr
new file mode 100644
index 0000000..0799656
--- /dev/null
+++ b/src/test/ui/issues/issue-34222-1.stderr
@@ -0,0 +1,11 @@
+error[E0585]: found a documentation comment that doesn't document anything
+  --> $DIR/issue-34222-1.rs:2:5
+   |
+LL |     /// comment
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: doc comments must come before what they document, maybe a comment was intended with `//`?
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0585`.
diff --git a/src/test/ui/issues/issue-34229.rs b/src/test/ui/issues/issue-34229.rs
new file mode 100644
index 0000000..13e627a
--- /dev/null
+++ b/src/test/ui/issues/issue-34229.rs
@@ -0,0 +1,5 @@
+#[derive(PartialEq)] struct Comparable;
+#[derive(PartialEq, PartialOrd)] struct Nope(Comparable);
+//~^ ERROR can't compare `Comparable`
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-34229.stderr b/src/test/ui/issues/issue-34229.stderr
new file mode 100644
index 0000000..c57f80c
--- /dev/null
+++ b/src/test/ui/issues/issue-34229.stderr
@@ -0,0 +1,12 @@
+error[E0277]: can't compare `Comparable` with `Comparable`
+  --> $DIR/issue-34229.rs:2:46
+   |
+LL | #[derive(PartialEq, PartialOrd)] struct Nope(Comparable);
+   |                                              ^^^^^^^^^^ no implementation for `Comparable < Comparable` and `Comparable > Comparable`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `Comparable`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-3424.rs b/src/test/ui/issues/issue-3424.rs
new file mode 100644
index 0000000..a9ba5f5
--- /dev/null
+++ b/src/test/ui/issues/issue-3424.rs
@@ -0,0 +1,20 @@
+// compile-pass
+#![allow(dead_code)]
+#![allow(non_camel_case_types)]
+// rustc --test ignores2.rs && ./ignores2
+
+pub struct Path;
+
+type rsrc_loader = Box<FnMut(&Path) -> Result<String, String>>;
+
+fn tester()
+{
+    let mut loader: rsrc_loader = Box::new(move |_path| {
+        Ok("more blah".to_string())
+    });
+
+    let path = Path;
+    assert!(loader(&path).is_ok());
+}
+
+pub fn main() {}
diff --git a/src/test/ui/issues/issue-34255-1.rs b/src/test/ui/issues/issue-34255-1.rs
new file mode 100644
index 0000000..b107193
--- /dev/null
+++ b/src/test/ui/issues/issue-34255-1.rs
@@ -0,0 +1,10 @@
+enum Test {
+    Drill {
+        field: i32,
+    }
+}
+
+fn main() {
+    Test::Drill(field: 42);
+    //~^ ERROR expected type, found
+}
diff --git a/src/test/ui/issues/issue-34255-1.stderr b/src/test/ui/issues/issue-34255-1.stderr
new file mode 100644
index 0000000..7899c8d
--- /dev/null
+++ b/src/test/ui/issues/issue-34255-1.stderr
@@ -0,0 +1,16 @@
+error: expected type, found `42`
+  --> $DIR/issue-34255-1.rs:8:24
+   |
+LL |     Test::Drill(field: 42);
+   |                        ^^ expecting a type here because of type ascription
+   |
+   = note: type ascription is a nightly-only feature that lets you annotate an expression with a type: `<expr>: <type>`
+note: this expression expects an ascribed type after the colon
+  --> $DIR/issue-34255-1.rs:8:17
+   |
+LL |     Test::Drill(field: 42);
+   |                 ^^^^^
+   = help: this might be indicative of a syntax error elsewhere
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-34334.rs b/src/test/ui/issues/issue-34334.rs
new file mode 100644
index 0000000..928d217
--- /dev/null
+++ b/src/test/ui/issues/issue-34334.rs
@@ -0,0 +1,10 @@
+fn main () {
+    let sr: Vec<(u32, _, _) = vec![];
+    //~^ ERROR expected one of `,` or `>`, found `=`
+    //~| ERROR expected value, found struct `Vec`
+    //~| ERROR mismatched types
+    //~| ERROR invalid left-hand side expression
+    //~| ERROR expected expression, found reserved identifier `_`
+    let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect();
+    //~^ ERROR no method named `iter` found for type `()` in the current scope
+}
diff --git a/src/test/ui/issues/issue-34334.stderr b/src/test/ui/issues/issue-34334.stderr
new file mode 100644
index 0000000..51ea0c6
--- /dev/null
+++ b/src/test/ui/issues/issue-34334.stderr
@@ -0,0 +1,47 @@
+error: expected expression, found reserved identifier `_`
+  --> $DIR/issue-34334.rs:2:23
+   |
+LL |     let sr: Vec<(u32, _, _) = vec![];
+   |                       ^ expected expression
+
+error: expected one of `,` or `>`, found `=`
+  --> $DIR/issue-34334.rs:2:29
+   |
+LL |     let sr: Vec<(u32, _, _) = vec![];
+   |         ---                 ^ expected one of `,` or `>` here
+   |         | |
+   |         | help: use `=` if you meant to assign
+   |         while parsing the type for `sr`
+
+error[E0423]: expected value, found struct `Vec`
+  --> $DIR/issue-34334.rs:2:13
+   |
+LL |     let sr: Vec<(u32, _, _) = vec![];
+   |             ^^^ did you mean `Vec { /* fields */ }`?
+
+error[E0308]: mismatched types
+  --> $DIR/issue-34334.rs:2:31
+   |
+LL |     let sr: Vec<(u32, _, _) = vec![];
+   |                               ^^^^^^ expected bool, found struct `std::vec::Vec`
+   |
+   = note: expected type `bool`
+              found type `std::vec::Vec<_>`
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error[E0070]: invalid left-hand side expression
+  --> $DIR/issue-34334.rs:2:13
+   |
+LL |     let sr: Vec<(u32, _, _) = vec![];
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^ left-hand of expression not valid
+
+error[E0599]: no method named `iter` found for type `()` in the current scope
+  --> $DIR/issue-34334.rs:8:36
+   |
+LL |     let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect();
+   |                                    ^^^^
+
+error: aborting due to 6 previous errors
+
+Some errors occurred: E0070, E0308, E0423, E0599.
+For more information about an error, try `rustc --explain E0070`.
diff --git a/src/test/ui/issues/issue-34349.rs b/src/test/ui/issues/issue-34349.rs
new file mode 100644
index 0000000..d861802
--- /dev/null
+++ b/src/test/ui/issues/issue-34349.rs
@@ -0,0 +1,22 @@
+// This is a regression test for a problem encountered around upvar
+// inference and trait caching: in particular, we were entering a
+// temporary closure kind during inference, and then caching results
+// based on that temporary kind, which led to no error being reported
+// in this particular test.
+
+fn main() {
+    let inc = || {};
+    inc();
+
+    fn apply<F>(f: F) where F: Fn() {
+        f()
+    }
+
+    let mut farewell = "goodbye".to_owned();
+    let diary = || { //~ ERROR E0525
+        farewell.push_str("!!!");
+        println!("Then I screamed {}.", farewell);
+    };
+
+    apply(diary);
+}
diff --git a/src/test/ui/issues/issue-34349.stderr b/src/test/ui/issues/issue-34349.stderr
new file mode 100644
index 0000000..d0b5196
--- /dev/null
+++ b/src/test/ui/issues/issue-34349.stderr
@@ -0,0 +1,14 @@
+error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnMut`
+  --> $DIR/issue-34349.rs:16:17
+   |
+LL |     let diary = || {
+   |                 ^^ this closure implements `FnMut`, not `Fn`
+LL |         farewell.push_str("!!!");
+   |         -------- closure is `FnMut` because it mutates the variable `farewell` here
+...
+LL |     apply(diary);
+   |     ----- the requirement to implement `Fn` derives from here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0525`.
diff --git a/src/test/ui/issues/issue-34373.rs b/src/test/ui/issues/issue-34373.rs
new file mode 100644
index 0000000..ca24e37
--- /dev/null
+++ b/src/test/ui/issues/issue-34373.rs
@@ -0,0 +1,11 @@
+#![allow(warnings)]
+
+trait Trait<T> {
+    fn foo(_: T) {}
+}
+
+pub struct Foo<T = Box<Trait<DefaultFoo>>>;  //~ ERROR cycle detected
+type DefaultFoo = Foo;
+
+fn main() {
+}
diff --git a/src/test/ui/issues/issue-34373.stderr b/src/test/ui/issues/issue-34373.stderr
new file mode 100644
index 0000000..f260a84
--- /dev/null
+++ b/src/test/ui/issues/issue-34373.stderr
@@ -0,0 +1,27 @@
+error[E0391]: cycle detected when processing `Foo::T`
+  --> $DIR/issue-34373.rs:7:30
+   |
+LL | pub struct Foo<T = Box<Trait<DefaultFoo>>>;
+   |                              ^^^^^^^^^^
+   |
+note: ...which requires processing `DefaultFoo`...
+  --> $DIR/issue-34373.rs:8:19
+   |
+LL | type DefaultFoo = Foo;
+   |                   ^^^
+   = note: ...which again requires processing `Foo::T`, completing the cycle
+note: cycle used when collecting item types in top-level module
+  --> $DIR/issue-34373.rs:1:1
+   |
+LL | / #![allow(warnings)]
+LL | |
+LL | | trait Trait<T> {
+LL | |     fn foo(_: T) {}
+...  |
+LL | | fn main() {
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/issues/issue-34418.rs b/src/test/ui/issues/issue-34418.rs
new file mode 100644
index 0000000..6a86c27
--- /dev/null
+++ b/src/test/ui/issues/issue-34418.rs
@@ -0,0 +1,22 @@
+// compile-pass
+// skip-codegen
+#![allow(unused)]
+
+macro_rules! make_item {
+    () => { fn f() {} }
+}
+
+macro_rules! make_stmt {
+    () => { let x = 0; }
+}
+
+fn f() {
+    make_item! {}
+}
+
+fn g() {
+    make_stmt! {}
+}
+
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-34721.rs b/src/test/ui/issues/issue-34721.rs
new file mode 100644
index 0000000..226c214
--- /dev/null
+++ b/src/test/ui/issues/issue-34721.rs
@@ -0,0 +1,34 @@
+#![feature(nll)]
+
+pub trait Foo {
+    fn zero(self) -> Self;
+}
+
+impl Foo for u32 {
+    fn zero(self) -> u32 { 0u32 }
+}
+
+pub mod bar {
+    pub use Foo;
+    pub fn bar<T: Foo>(x: T) -> T {
+      x.zero()
+    }
+}
+
+mod baz {
+    use bar;
+    use Foo;
+    pub fn baz<T: Foo>(x: T) -> T {
+        if 0 == 1 {
+            bar::bar(x.zero())
+        } else {
+            x.zero()
+        };
+        x.zero()
+        //~^ ERROR use of moved value
+    }
+}
+
+fn main() {
+    let _ = baz::baz(0u32);
+}
diff --git a/src/test/ui/issues/issue-34721.stderr b/src/test/ui/issues/issue-34721.stderr
new file mode 100644
index 0000000..2ed7b54
--- /dev/null
+++ b/src/test/ui/issues/issue-34721.stderr
@@ -0,0 +1,20 @@
+error[E0382]: use of moved value: `x`
+  --> $DIR/issue-34721.rs:27:9
+   |
+LL |     pub fn baz<T: Foo>(x: T) -> T {
+   |                -       - move occurs because `x` has type `T`, which does not implement the `Copy` trait
+   |                |
+   |                consider adding a `Copy` constraint to this type argument
+LL |         if 0 == 1 {
+LL |             bar::bar(x.zero())
+   |                      - value moved here
+LL |         } else {
+LL |             x.zero()
+   |             - value moved here
+LL |         };
+LL |         x.zero()
+   |         ^ value used here after move
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/issues/issue-34751.rs b/src/test/ui/issues/issue-34751.rs
new file mode 100644
index 0000000..cca06c5
--- /dev/null
+++ b/src/test/ui/issues/issue-34751.rs
@@ -0,0 +1,11 @@
+// compile-pass
+#![allow(dead_code)]
+// #34751 ICE: 'rustc' panicked at 'assertion failed: !substs.has_regions_escaping_depth(0)'
+
+#[allow(dead_code)]
+
+use std::marker::PhantomData;
+
+fn f<'a>(PhantomData::<&'a u8>: PhantomData<&'a u8>) {}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-3477.rs b/src/test/ui/issues/issue-3477.rs
new file mode 100644
index 0000000..ae17e7d
--- /dev/null
+++ b/src/test/ui/issues/issue-3477.rs
@@ -0,0 +1,5 @@
+fn main() {
+    let _p: char = 100;
+    //~^ ERROR mismatched types
+    //~| expected char, found u8
+}
diff --git a/src/test/ui/issues/issue-3477.stderr b/src/test/ui/issues/issue-3477.stderr
new file mode 100644
index 0000000..1b7f597
--- /dev/null
+++ b/src/test/ui/issues/issue-3477.stderr
@@ -0,0 +1,9 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-3477.rs:2:20
+   |
+LL |     let _p: char = 100;
+   |                    ^^^ expected char, found u8
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-34780.rs b/src/test/ui/issues/issue-34780.rs
new file mode 100644
index 0000000..bfe444e
--- /dev/null
+++ b/src/test/ui/issues/issue-34780.rs
@@ -0,0 +1,11 @@
+// compile-pass
+#![allow(stable_features)]
+#![feature(associated_consts)]
+
+use std::marker::PhantomData;
+
+trait Tr<'a> {
+    const C: PhantomData<&'a u8> = PhantomData::<&'a u8>;
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-34839.rs b/src/test/ui/issues/issue-34839.rs
new file mode 100644
index 0000000..01669f0
--- /dev/null
+++ b/src/test/ui/issues/issue-34839.rs
@@ -0,0 +1,22 @@
+// compile-pass
+// skip-codegen
+#![allow(dead_code)]
+
+trait RegularExpression: Sized {
+    type Text;
+}
+
+struct ExecNoSyncStr<'a>(&'a u8);
+
+impl<'c> RegularExpression for ExecNoSyncStr<'c> {
+    type Text = u8;
+}
+
+struct FindCaptures<'t, R>(&'t R::Text) where R: RegularExpression, R::Text: 't;
+
+enum FindCapturesInner<'r, 't> {
+    Dynamic(FindCaptures<'t, ExecNoSyncStr<'r>>),
+}
+
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-35075.rs b/src/test/ui/issues/issue-35075.rs
new file mode 100644
index 0000000..0e54131
--- /dev/null
+++ b/src/test/ui/issues/issue-35075.rs
@@ -0,0 +1,9 @@
+struct Bar<T> {
+    inner: Foo<T> //~ ERROR cannot find type `Foo` in this scope
+}
+
+enum Baz<T> {
+    Foo(Foo<T>) //~ ERROR cannot find type `Foo` in this scope
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-35075.stderr b/src/test/ui/issues/issue-35075.stderr
new file mode 100644
index 0000000..2aeb6b1
--- /dev/null
+++ b/src/test/ui/issues/issue-35075.stderr
@@ -0,0 +1,23 @@
+error[E0412]: cannot find type `Foo` in this scope
+  --> $DIR/issue-35075.rs:2:12
+   |
+LL |     inner: Foo<T>
+   |            ^^^ not found in this scope
+help: there is an enum variant `Baz::Foo`; try using the variant's enum
+   |
+LL |     inner: Baz
+   |            ^^^
+
+error[E0412]: cannot find type `Foo` in this scope
+  --> $DIR/issue-35075.rs:6:9
+   |
+LL |     Foo(Foo<T>)
+   |         ^^^ not found in this scope
+help: there is an enum variant `Baz::Foo`; try using the variant's enum
+   |
+LL |     Foo(Baz)
+   |         ^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/src/test/ui/issues/issue-35139.rs b/src/test/ui/issues/issue-35139.rs
new file mode 100644
index 0000000..1ee00fc
--- /dev/null
+++ b/src/test/ui/issues/issue-35139.rs
@@ -0,0 +1,26 @@
+use std::fmt;
+
+pub trait MethodType {
+    type GetProp: ?Sized;
+}
+
+pub struct MTFn;
+
+impl<'a> MethodType for MTFn { //~ ERROR E0207
+    type GetProp = fmt::Debug + 'a;
+}
+
+fn bad(a: Box<<MTFn as MethodType>::GetProp>) -> Box<fmt::Debug+'static> {
+    a
+}
+
+fn dangling(a: &str) -> Box<fmt::Debug> {
+    bad(Box::new(a))
+}
+
+fn main() {
+    let mut s = "hello".to_string();
+    let x = dangling(&s);
+    s = String::new();
+    println!("{:?}", x);
+}
diff --git a/src/test/ui/issues/issue-35139.stderr b/src/test/ui/issues/issue-35139.stderr
new file mode 100644
index 0000000..79e889b
--- /dev/null
+++ b/src/test/ui/issues/issue-35139.stderr
@@ -0,0 +1,9 @@
+error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates
+  --> $DIR/issue-35139.rs:9:6
+   |
+LL | impl<'a> MethodType for MTFn {
+   |      ^^ unconstrained lifetime parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0207`.
diff --git a/src/test/ui/issues/issue-3521-2.rs b/src/test/ui/issues/issue-3521-2.rs
new file mode 100644
index 0000000..871394f
--- /dev/null
+++ b/src/test/ui/issues/issue-3521-2.rs
@@ -0,0 +1,8 @@
+fn main() {
+    let foo = 100;
+
+    static y: isize = foo + 1;
+    //~^ ERROR attempt to use a non-constant value in a constant
+
+    println!("{}", y);
+}
diff --git a/src/test/ui/issues/issue-3521-2.stderr b/src/test/ui/issues/issue-3521-2.stderr
new file mode 100644
index 0000000..d54bbbc
--- /dev/null
+++ b/src/test/ui/issues/issue-3521-2.stderr
@@ -0,0 +1,9 @@
+error[E0435]: attempt to use a non-constant value in a constant
+  --> $DIR/issue-3521-2.rs:4:23
+   |
+LL |     static y: isize = foo + 1;
+   |                       ^^^ non-constant value
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0435`.
diff --git a/src/test/ui/issues/issue-3521.rs b/src/test/ui/issues/issue-3521.rs
new file mode 100644
index 0000000..9e72dd2
--- /dev/null
+++ b/src/test/ui/issues/issue-3521.rs
@@ -0,0 +1,11 @@
+fn main() {
+    let foo = 100;
+
+    #[derive(Debug)]
+    enum Stuff {
+        Bar = foo
+        //~^ ERROR attempt to use a non-constant value in a constant
+    }
+
+    println!("{:?}", Stuff::Bar);
+}
diff --git a/src/test/ui/issues/issue-3521.stderr b/src/test/ui/issues/issue-3521.stderr
new file mode 100644
index 0000000..ae19987
--- /dev/null
+++ b/src/test/ui/issues/issue-3521.stderr
@@ -0,0 +1,9 @@
+error[E0435]: attempt to use a non-constant value in a constant
+  --> $DIR/issue-3521.rs:6:15
+   |
+LL |         Bar = foo
+   |               ^^^ non-constant value
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0435`.
diff --git a/src/test/ui/issues/issue-35241.rs b/src/test/ui/issues/issue-35241.rs
new file mode 100644
index 0000000..2fa7624
--- /dev/null
+++ b/src/test/ui/issues/issue-35241.rs
@@ -0,0 +1,5 @@
+struct Foo(u32);
+
+fn test() -> Foo { Foo } //~ ERROR mismatched types
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-35241.stderr b/src/test/ui/issues/issue-35241.stderr
new file mode 100644
index 0000000..8fda58a
--- /dev/null
+++ b/src/test/ui/issues/issue-35241.stderr
@@ -0,0 +1,16 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-35241.rs:3:20
+   |
+LL | fn test() -> Foo { Foo }
+   |              ---   ^^^
+   |              |     |
+   |              |     expected struct `Foo`, found fn item
+   |              |     did you mean `Foo(/* fields */)`?
+   |              expected `Foo` because of return type
+   |
+   = note: expected type `Foo`
+              found type `fn(u32) -> Foo {Foo}`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-35376.rs b/src/test/ui/issues/issue-35376.rs
new file mode 100644
index 0000000..2a80c9f
--- /dev/null
+++ b/src/test/ui/issues/issue-35376.rs
@@ -0,0 +1,42 @@
+// compile-pass
+#![feature(specialization)]
+
+fn main() {}
+
+pub trait Alpha<T> { }
+
+pub trait Beta {
+    type Event;
+}
+
+pub trait Delta {
+    type Handle;
+    fn process(&self);
+}
+
+pub struct Parent<A, T>(A, T);
+
+impl<A, T> Delta for Parent<A, T>
+where A: Alpha<T::Handle>,
+      T: Delta,
+      T::Handle: Beta<Event = <Handle as Beta>::Event> {
+    type Handle = Handle;
+    default fn process(&self) {
+        unimplemented!()
+    }
+}
+
+impl<A, T> Delta for Parent<A, T>
+where A: Alpha<T::Handle> + Alpha<Handle>,
+      T: Delta,
+      T::Handle: Beta<Event = <Handle as Beta>::Event> {
+      fn process(&self) {
+        unimplemented!()
+      }
+}
+
+pub struct Handle;
+
+impl Beta for Handle {
+    type Event = ();
+}
diff --git a/src/test/ui/issues/issue-35450.rs b/src/test/ui/issues/issue-35450.rs
new file mode 100644
index 0000000..ac4c163
--- /dev/null
+++ b/src/test/ui/issues/issue-35450.rs
@@ -0,0 +1,5 @@
+macro_rules! m { ($($t:tt)*) => { $($t)* } }
+
+fn main() {
+    m!($t); //~ ERROR expected expression
+}
diff --git a/src/test/ui/issues/issue-35450.stderr b/src/test/ui/issues/issue-35450.stderr
new file mode 100644
index 0000000..f206568
--- /dev/null
+++ b/src/test/ui/issues/issue-35450.stderr
@@ -0,0 +1,8 @@
+error: expected expression, found `$`
+  --> $DIR/issue-35450.rs:4:8
+   |
+LL |     m!($t);
+   |        ^ expected expression
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-35546.rs b/src/test/ui/issues/issue-35546.rs
new file mode 100644
index 0000000..19c0491
--- /dev/null
+++ b/src/test/ui/issues/issue-35546.rs
@@ -0,0 +1,20 @@
+// compile-pass
+#![allow(dead_code)]
+// Regression test for #35546. Check that we are able to codegen
+// this. Before we had problems because of the drop glue signature
+// around dropping a trait object (specifically, when dropping the
+// `value` field of `Node<Send>`).
+
+struct Node<T: ?Sized + Send> {
+    next: Option<Box<Node<Send>>>,
+    value: T,
+}
+
+fn clear(head: &mut Option<Box<Node<Send>>>) {
+    match head.take() {
+        Some(node) => *head = node.next,
+        None => (),
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-35570.rs b/src/test/ui/issues/issue-35570.rs
new file mode 100644
index 0000000..e809b46
--- /dev/null
+++ b/src/test/ui/issues/issue-35570.rs
@@ -0,0 +1,31 @@
+// compile-pass
+// skip-codegen
+
+use std::mem;
+
+trait Trait1<T> {}
+trait Trait2<'a> {
+  type Ty;
+}
+
+fn _ice(param: Box<for <'a> Trait1<<() as Trait2<'a>>::Ty>>) {
+    let _e: (usize, usize) = unsafe{mem::transmute(param)};
+}
+
+trait Lifetime<'a> {
+    type Out;
+}
+impl<'a> Lifetime<'a> for () {
+    type Out = &'a ();
+}
+fn foo<'a>(x: &'a ()) -> <() as Lifetime<'a>>::Out {
+    x
+}
+
+fn takes_lifetime(_f: for<'a> fn(&'a ()) -> <() as Lifetime<'a>>::Out) {
+}
+
+
+fn main() {
+    takes_lifetime(foo);
+}
diff --git a/src/test/ui/issues/issue-3563-2.rs b/src/test/ui/issues/issue-3563-2.rs
new file mode 100644
index 0000000..48f7c84
--- /dev/null
+++ b/src/test/ui/issues/issue-3563-2.rs
@@ -0,0 +1,14 @@
+// compile-pass
+// pretty-expanded FIXME #23616
+
+trait Canvas {
+    fn add_point(&self, point: &isize);
+    fn add_points(&self, shapes: &[isize]) {
+        for pt in shapes {
+            self.add_point(pt)
+        }
+    }
+
+}
+
+pub fn main() {}
diff --git a/src/test/ui/issues/issue-35668.rs b/src/test/ui/issues/issue-35668.rs
new file mode 100644
index 0000000..1b8ada5
--- /dev/null
+++ b/src/test/ui/issues/issue-35668.rs
@@ -0,0 +1,12 @@
+fn func<'a, T>(a: &'a [T]) -> impl Iterator<Item=&'a T> {
+    a.iter().map(|a| a*a)
+    //~^ ERROR binary operation `*` cannot be applied to type `&T`
+}
+
+fn main() {
+    let a = (0..30).collect::<Vec<_>>();
+
+    for k in func(&a) {
+        println!("{}", k);
+    }
+}
diff --git a/src/test/ui/issues/issue-35668.stderr b/src/test/ui/issues/issue-35668.stderr
new file mode 100644
index 0000000..59ca874
--- /dev/null
+++ b/src/test/ui/issues/issue-35668.stderr
@@ -0,0 +1,13 @@
+error[E0369]: binary operation `*` cannot be applied to type `&T`
+  --> $DIR/issue-35668.rs:2:23
+   |
+LL |     a.iter().map(|a| a*a)
+   |                      -^- &T
+   |                      |
+   |                      &T
+   |
+   = note: an implementation of `std::ops::Mul` might be missing for `&T`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0369`.
diff --git a/src/test/ui/issues/issue-35675.rs b/src/test/ui/issues/issue-35675.rs
new file mode 100644
index 0000000..fae5cdc
--- /dev/null
+++ b/src/test/ui/issues/issue-35675.rs
@@ -0,0 +1,42 @@
+// these two HELPs are actually in a new line between this line and the `enum Fruit` line
+enum Fruit {
+    Apple(i64),
+    Orange(i64),
+}
+
+fn should_return_fruit() -> Apple {
+    //~^ ERROR cannot find type `Apple` in this scope
+    Apple(5)
+    //~^ ERROR cannot find function `Apple` in this scope
+}
+
+fn should_return_fruit_too() -> Fruit::Apple {
+    //~^ ERROR expected type, found variant `Fruit::Apple`
+    Apple(5)
+    //~^ ERROR cannot find function `Apple` in this scope
+}
+
+fn foo() -> Ok {
+    //~^ ERROR expected type, found variant `Ok`
+    Ok(())
+}
+
+fn bar() -> Variant3 {
+    //~^ ERROR cannot find type `Variant3` in this scope
+}
+
+fn qux() -> Some {
+    //~^ ERROR expected type, found variant `Some`
+    Some(1)
+}
+
+fn main() {}
+
+mod x {
+    enum Enum {
+        Variant1,
+        Variant2(),
+        Variant3(usize),
+        Variant4 {},
+    }
+}
diff --git a/src/test/ui/issues/issue-35675.stderr b/src/test/ui/issues/issue-35675.stderr
new file mode 100644
index 0000000..3e4fd55
--- /dev/null
+++ b/src/test/ui/issues/issue-35675.stderr
@@ -0,0 +1,71 @@
+error[E0412]: cannot find type `Apple` in this scope
+  --> $DIR/issue-35675.rs:7:29
+   |
+LL | fn should_return_fruit() -> Apple {
+   |                             ^^^^^ not found in this scope
+help: there is an enum variant `Fruit::Apple`; try using the variant's enum
+   |
+LL | fn should_return_fruit() -> Fruit {
+   |                             ^^^^^
+
+error[E0425]: cannot find function `Apple` in this scope
+  --> $DIR/issue-35675.rs:9:5
+   |
+LL |     Apple(5)
+   |     ^^^^^ not found in this scope
+help: possible candidate is found in another module, you can import it into scope
+   |
+LL | use Fruit::Apple;
+   |
+
+error[E0573]: expected type, found variant `Fruit::Apple`
+  --> $DIR/issue-35675.rs:13:33
+   |
+LL | fn should_return_fruit_too() -> Fruit::Apple {
+   |                                 ^^^^^^^^^^^^
+   |                                 |
+   |                                 not a type
+   |                                 help: try using the variant's enum: `Fruit`
+
+error[E0425]: cannot find function `Apple` in this scope
+  --> $DIR/issue-35675.rs:15:5
+   |
+LL |     Apple(5)
+   |     ^^^^^ not found in this scope
+help: possible candidate is found in another module, you can import it into scope
+   |
+LL | use Fruit::Apple;
+   |
+
+error[E0573]: expected type, found variant `Ok`
+  --> $DIR/issue-35675.rs:19:13
+   |
+LL | fn foo() -> Ok {
+   |             ^^
+   |             |
+   |             not a type
+   |             help: try using the variant's enum: `std::result::Result`
+
+error[E0412]: cannot find type `Variant3` in this scope
+  --> $DIR/issue-35675.rs:24:13
+   |
+LL | fn bar() -> Variant3 {
+   |             ^^^^^^^^ not found in this scope
+help: there is an enum variant `x::Enum::Variant3`; try using the variant's enum
+   |
+LL | fn bar() -> x::Enum {
+   |             ^^^^^^^
+
+error[E0573]: expected type, found variant `Some`
+  --> $DIR/issue-35675.rs:28:13
+   |
+LL | fn qux() -> Some {
+   |             ^^^^
+   |             |
+   |             not a type
+   |             help: try using the variant's enum: `Option`
+
+error: aborting due to 7 previous errors
+
+Some errors occurred: E0412, E0425, E0573.
+For more information about an error, try `rustc --explain E0412`.
diff --git a/src/test/ui/issues/issue-35677.rs b/src/test/ui/issues/issue-35677.rs
new file mode 100644
index 0000000..ba2d503
--- /dev/null
+++ b/src/test/ui/issues/issue-35677.rs
@@ -0,0 +1,8 @@
+use std::collections::HashSet;
+
+fn is_subset<T>(this: &HashSet<T>, other: &HashSet<T>) -> bool {
+    this.is_subset(other)
+    //~^ ERROR no method named
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-35677.stderr b/src/test/ui/issues/issue-35677.stderr
new file mode 100644
index 0000000..99d99db
--- /dev/null
+++ b/src/test/ui/issues/issue-35677.stderr
@@ -0,0 +1,13 @@
+error[E0599]: no method named `is_subset` found for type `&std::collections::HashSet<T>` in the current scope
+  --> $DIR/issue-35677.rs:4:10
+   |
+LL |     this.is_subset(other)
+   |          ^^^^^^^^^
+   |
+   = note: the method `is_subset` exists but the following trait bounds were not satisfied:
+           `T : std::cmp::Eq`
+           `T : std::hash::Hash`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/issues/issue-35869.rs b/src/test/ui/issues/issue-35869.rs
new file mode 100644
index 0000000..b9b4c97
--- /dev/null
+++ b/src/test/ui/issues/issue-35869.rs
@@ -0,0 +1,21 @@
+trait Foo {
+    fn foo(_: fn(u8) -> ());
+    fn bar(_: Option<u8>);
+    fn baz(_: (u8, u16));
+    fn qux() -> u8;
+}
+
+struct Bar;
+
+impl Foo for Bar {
+    fn foo(_: fn(u16) -> ()) {}
+    //~^ ERROR method `foo` has an incompatible type for trait
+    fn bar(_: Option<u16>) {}
+    //~^ ERROR method `bar` has an incompatible type for trait
+    fn baz(_: (u16, u16)) {}
+    //~^ ERROR method `baz` has an incompatible type for trait
+    fn qux() -> u16 { 5u16 }
+    //~^ ERROR method `qux` has an incompatible type for trait
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-35869.stderr b/src/test/ui/issues/issue-35869.stderr
new file mode 100644
index 0000000..4ef840d
--- /dev/null
+++ b/src/test/ui/issues/issue-35869.stderr
@@ -0,0 +1,51 @@
+error[E0053]: method `foo` has an incompatible type for trait
+  --> $DIR/issue-35869.rs:11:15
+   |
+LL |     fn foo(_: fn(u8) -> ());
+   |               ------------ type in trait
+...
+LL |     fn foo(_: fn(u16) -> ()) {}
+   |               ^^^^^^^^^^^^^ expected u8, found u16
+   |
+   = note: expected type `fn(fn(u8))`
+              found type `fn(fn(u16))`
+
+error[E0053]: method `bar` has an incompatible type for trait
+  --> $DIR/issue-35869.rs:13:15
+   |
+LL |     fn bar(_: Option<u8>);
+   |               ---------- type in trait
+...
+LL |     fn bar(_: Option<u16>) {}
+   |               ^^^^^^^^^^^ expected u8, found u16
+   |
+   = note: expected type `fn(std::option::Option<u8>)`
+              found type `fn(std::option::Option<u16>)`
+
+error[E0053]: method `baz` has an incompatible type for trait
+  --> $DIR/issue-35869.rs:15:15
+   |
+LL |     fn baz(_: (u8, u16));
+   |               --------- type in trait
+...
+LL |     fn baz(_: (u16, u16)) {}
+   |               ^^^^^^^^^^ expected u8, found u16
+   |
+   = note: expected type `fn((u8, u16))`
+              found type `fn((u16, u16))`
+
+error[E0053]: method `qux` has an incompatible type for trait
+  --> $DIR/issue-35869.rs:17:17
+   |
+LL |     fn qux() -> u8;
+   |                 -- type in trait
+...
+LL |     fn qux() -> u16 { 5u16 }
+   |                 ^^^ expected u8, found u16
+   |
+   = note: expected type `fn() -> u8`
+              found type `fn() -> u16`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0053`.
diff --git a/src/test/ui/issues/issue-35976.rs b/src/test/ui/issues/issue-35976.rs
new file mode 100644
index 0000000..95c0cc9
--- /dev/null
+++ b/src/test/ui/issues/issue-35976.rs
@@ -0,0 +1,20 @@
+mod private {
+    pub trait Future {
+        fn wait(&self) where Self: Sized;
+    }
+
+    impl Future for Box<Future> {
+        fn wait(&self) { }
+    }
+}
+
+//use private::Future;
+
+fn bar(arg: Box<private::Future>) {
+    arg.wait();
+    //~^ ERROR the `wait` method cannot be invoked on a trait object
+}
+
+fn main() {
+
+}
diff --git a/src/test/ui/issues/issue-35976.stderr b/src/test/ui/issues/issue-35976.stderr
new file mode 100644
index 0000000..d12198d
--- /dev/null
+++ b/src/test/ui/issues/issue-35976.stderr
@@ -0,0 +1,12 @@
+error: the `wait` method cannot be invoked on a trait object
+  --> $DIR/issue-35976.rs:14:9
+   |
+LL |     arg.wait();
+   |         ^^^^
+help: another candidate was found in the following trait, perhaps add a `use` for it:
+   |
+LL | use private::Future;
+   |
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-35988.rs b/src/test/ui/issues/issue-35988.rs
new file mode 100644
index 0000000..5cf2f8e
--- /dev/null
+++ b/src/test/ui/issues/issue-35988.rs
@@ -0,0 +1,6 @@
+enum E {
+    V([Box<E>]),
+    //~^ ERROR the size for values of type
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-35988.stderr b/src/test/ui/issues/issue-35988.stderr
new file mode 100644
index 0000000..825c0de
--- /dev/null
+++ b/src/test/ui/issues/issue-35988.stderr
@@ -0,0 +1,13 @@
+error[E0277]: the size for values of type `[std::boxed::Box<E>]` cannot be known at compilation time
+  --> $DIR/issue-35988.rs:2:7
+   |
+LL |     V([Box<E>]),
+   |       ^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `[std::boxed::Box<E>]`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: no field of an enum variant may have a dynamically sized type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-3601.rs b/src/test/ui/issues/issue-3601.rs
new file mode 100644
index 0000000..e33359b
--- /dev/null
+++ b/src/test/ui/issues/issue-3601.rs
@@ -0,0 +1,34 @@
+#![feature(box_patterns)]
+#![feature(box_syntax)]
+
+struct HTMLImageData {
+    image: Option<String>
+}
+
+struct ElementData {
+    kind: Box<ElementKind>
+}
+
+enum ElementKind {
+    HTMLImageElement(HTMLImageData)
+}
+
+enum NodeKind {
+    Element(ElementData)
+}
+
+struct NodeData {
+    kind: Box<NodeKind>,
+}
+
+fn main() {
+    let mut id = HTMLImageData { image: None };
+    let ed = ElementData { kind: box ElementKind::HTMLImageElement(id) };
+    let n = NodeData {kind : box NodeKind::Element(ed)};
+    // n.b. span could be better
+    match n.kind {
+        box NodeKind::Element(ed) => match ed.kind { //~ ERROR non-exhaustive patterns
+            box ElementKind::HTMLImageElement(ref d) if d.image.is_some() => { true }
+        },
+    };
+}
diff --git a/src/test/ui/issues/issue-3601.stderr b/src/test/ui/issues/issue-3601.stderr
new file mode 100644
index 0000000..fa0fa334
--- /dev/null
+++ b/src/test/ui/issues/issue-3601.stderr
@@ -0,0 +1,11 @@
+error[E0004]: non-exhaustive patterns: `_` not covered
+  --> $DIR/issue-3601.rs:30:44
+   |
+LL |         box NodeKind::Element(ed) => match ed.kind {
+   |                                            ^^^^^^^ pattern `_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/issues/issue-36075.rs b/src/test/ui/issues/issue-36075.rs
new file mode 100644
index 0000000..c9ca2f7
--- /dev/null
+++ b/src/test/ui/issues/issue-36075.rs
@@ -0,0 +1,14 @@
+// compile-pass
+#![allow(dead_code)]
+trait DeclarationParser {
+    type Declaration;
+}
+
+struct DeclarationListParser<'i, I, P>
+    where P: DeclarationParser<Declaration = I>
+{
+    input: &'i (),
+    parser: P
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-36082.ast.nll.stderr b/src/test/ui/issues/issue-36082.ast.nll.stderr
new file mode 100644
index 0000000..6b3b13a
--- /dev/null
+++ b/src/test/ui/issues/issue-36082.ast.nll.stderr
@@ -0,0 +1,16 @@
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/issue-36082.rs:11:19
+   |
+LL |     let val: &_ = x.borrow().0;
+   |                   ^^^^^^^^^^  - temporary value is freed at the end of this statement
+   |                   |
+   |                   creates a temporary which is freed while still in use
+...
+LL |     println!("{}", val);
+   |                    --- borrow later used here
+   |
+   = note: consider using a `let` binding to create a longer lived value
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/src/test/ui/issues/issue-36082.ast.stderr b/src/test/ui/issues/issue-36082.ast.stderr
new file mode 100644
index 0000000..56e50e5
--- /dev/null
+++ b/src/test/ui/issues/issue-36082.ast.stderr
@@ -0,0 +1,16 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/issue-36082.rs:11:19
+   |
+LL |     let val: &_ = x.borrow().0;
+   |                   ^^^^^^^^^^  - temporary value dropped here while still borrowed
+   |                   |
+   |                   temporary value does not live long enough
+...
+LL | }
+   | - temporary value needs to live until here
+   |
+   = note: consider using a `let` binding to increase its lifetime
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/issues/issue-36082.mir.stderr b/src/test/ui/issues/issue-36082.mir.stderr
new file mode 100644
index 0000000..6b3b13a
--- /dev/null
+++ b/src/test/ui/issues/issue-36082.mir.stderr
@@ -0,0 +1,16 @@
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/issue-36082.rs:11:19
+   |
+LL |     let val: &_ = x.borrow().0;
+   |                   ^^^^^^^^^^  - temporary value is freed at the end of this statement
+   |                   |
+   |                   creates a temporary which is freed while still in use
+...
+LL |     println!("{}", val);
+   |                    --- borrow later used here
+   |
+   = note: consider using a `let` binding to create a longer lived value
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/src/test/ui/issues/issue-36082.rs b/src/test/ui/issues/issue-36082.rs
new file mode 100644
index 0000000..2658ef0
--- /dev/null
+++ b/src/test/ui/issues/issue-36082.rs
@@ -0,0 +1,23 @@
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+use std::cell::RefCell;
+
+fn main() {
+    let mut r = 0;
+    let s = 0;
+    let x = RefCell::new((&mut r,s));
+
+    let val: &_ = x.borrow().0;
+    //[ast]~^ ERROR borrowed value does not live long enough [E0597]
+    //[ast]~| NOTE temporary value dropped here while still borrowed
+    //[ast]~| NOTE temporary value does not live long enough
+    //[ast]~| NOTE consider using a `let` binding to increase its lifetime
+    //[mir]~^^^^^ ERROR temporary value dropped while borrowed [E0716]
+    //[mir]~| NOTE temporary value is freed at the end of this statement
+    //[mir]~| NOTE creates a temporary which is freed while still in use
+    //[mir]~| NOTE consider using a `let` binding to create a longer lived value
+    println!("{}", val);
+    //[mir]~^ borrow later used here
+}
+//[ast]~^ NOTE temporary value needs to live until here
diff --git a/src/test/ui/issues/issue-3609.rs b/src/test/ui/issues/issue-3609.rs
new file mode 100644
index 0000000..c76c183
--- /dev/null
+++ b/src/test/ui/issues/issue-3609.rs
@@ -0,0 +1,30 @@
+// compile-pass
+#![allow(unused_must_use)]
+#![allow(dead_code)]
+#![allow(unused_mut)]
+use std::thread;
+use std::sync::mpsc::Sender;
+
+type RingBuffer = Vec<f64> ;
+type SamplesFn = Box<FnMut(&RingBuffer) + Send>;
+
+enum Msg
+{
+    GetSamples(String, SamplesFn), // sample set name, callback which receives samples
+}
+
+fn foo(name: String, samples_chan: Sender<Msg>) {
+    thread::spawn(move|| {
+        let mut samples_chan = samples_chan;
+
+        let callback: SamplesFn = Box::new(move |buffer| {
+            for i in 0..buffer.len() {
+                println!("{}: {}", i, buffer[i])
+            }
+        });
+
+        samples_chan.send(Msg::GetSamples(name.clone(), callback));
+    }).join();
+}
+
+pub fn main() {}
diff --git a/src/test/ui/issues/issue-36116.rs b/src/test/ui/issues/issue-36116.rs
new file mode 100644
index 0000000..b4bfba4
--- /dev/null
+++ b/src/test/ui/issues/issue-36116.rs
@@ -0,0 +1,27 @@
+// Unnecessary path disambiguator is ok
+
+// compile-pass
+// skip-codegen
+#![allow(unused)]
+macro_rules! m {
+    ($p: path) => {
+        let _ = $p(0);
+        let _: $p;
+    }
+}
+
+struct Foo<T> {
+    _a: T,
+}
+
+struct S<T>(T);
+
+fn f() {
+    let f = Some(Foo { _a: 42 }).map(|a| a as Foo::<i32>);
+    let g: Foo::<i32> = Foo { _a: 42 };
+
+    m!(S::<u8>);
+}
+
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-36163.rs b/src/test/ui/issues/issue-36163.rs
new file mode 100644
index 0000000..340d2c3
--- /dev/null
+++ b/src/test/ui/issues/issue-36163.rs
@@ -0,0 +1,7 @@
+const A: isize = Foo::B as isize;
+
+enum Foo {
+    B = A, //~ ERROR E0391
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-36163.stderr b/src/test/ui/issues/issue-36163.stderr
new file mode 100644
index 0000000..4c3f726
--- /dev/null
+++ b/src/test/ui/issues/issue-36163.stderr
@@ -0,0 +1,21 @@
+error[E0391]: cycle detected when processing `Foo::B::{{constant}}#0`
+  --> $DIR/issue-36163.rs:4:9
+   |
+LL |     B = A,
+   |         ^
+   |
+note: ...which requires processing `A`...
+  --> $DIR/issue-36163.rs:1:18
+   |
+LL | const A: isize = Foo::B as isize;
+   |                  ^^^^^^^^^^^^^^^
+   = note: ...which again requires processing `Foo::B::{{constant}}#0`, completing the cycle
+note: cycle used when const-evaluating `Foo::B::{{constant}}#0`
+  --> $DIR/issue-36163.rs:4:9
+   |
+LL |     B = A,
+   |         ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/issues/issue-36299.rs b/src/test/ui/issues/issue-36299.rs
new file mode 100644
index 0000000..7b68420
--- /dev/null
+++ b/src/test/ui/issues/issue-36299.rs
@@ -0,0 +1,5 @@
+struct Foo<'a, A> {}
+//~^ ERROR parameter `'a` is never used
+//~| ERROR parameter `A` is never used
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-36299.stderr b/src/test/ui/issues/issue-36299.stderr
new file mode 100644
index 0000000..dce4bd3
--- /dev/null
+++ b/src/test/ui/issues/issue-36299.stderr
@@ -0,0 +1,19 @@
+error[E0392]: parameter `'a` is never used
+  --> $DIR/issue-36299.rs:1:12
+   |
+LL | struct Foo<'a, A> {}
+   |            ^^ unused type parameter
+   |
+   = help: consider removing `'a` or using a marker such as `std::marker::PhantomData`
+
+error[E0392]: parameter `A` is never used
+  --> $DIR/issue-36299.rs:1:16
+   |
+LL | struct Foo<'a, A> {}
+   |                ^ unused type parameter
+   |
+   = help: consider removing `A` or using a marker such as `std::marker::PhantomData`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0392`.
diff --git a/src/test/ui/issues/issue-36379.rs b/src/test/ui/issues/issue-36379.rs
new file mode 100644
index 0000000..b2da651
--- /dev/null
+++ b/src/test/ui/issues/issue-36379.rs
@@ -0,0 +1,7 @@
+// compile-pass
+// skip-codegen
+
+fn _test() -> impl Default { }
+
+
+fn main() { }
diff --git a/src/test/ui/issues/issue-36400.nll.stderr b/src/test/ui/issues/issue-36400.nll.stderr
new file mode 100644
index 0000000..3b37578
--- /dev/null
+++ b/src/test/ui/issues/issue-36400.nll.stderr
@@ -0,0 +1,11 @@
+error[E0596]: cannot borrow `*x` as mutable, as `x` is not declared as mutable
+  --> $DIR/issue-36400.rs:5:7
+   |
+LL |     let x = Box::new(3);
+   |         - help: consider changing this to be mutable: `mut x`
+LL |     f(&mut *x);
+   |       ^^^^^^^ cannot borrow as mutable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/issues/issue-36400.rs b/src/test/ui/issues/issue-36400.rs
new file mode 100644
index 0000000..5ba9eb2
--- /dev/null
+++ b/src/test/ui/issues/issue-36400.rs
@@ -0,0 +1,6 @@
+fn f(x: &mut u32) {}
+
+fn main() {
+    let x = Box::new(3);
+    f(&mut *x); //~ ERROR cannot borrow immutable
+}
diff --git a/src/test/ui/issues/issue-36400.stderr b/src/test/ui/issues/issue-36400.stderr
new file mode 100644
index 0000000..1494324
--- /dev/null
+++ b/src/test/ui/issues/issue-36400.stderr
@@ -0,0 +1,11 @@
+error[E0596]: cannot borrow immutable `Box` content `*x` as mutable
+  --> $DIR/issue-36400.rs:5:12
+   |
+LL |     let x = Box::new(3);
+   |         - help: make this binding mutable: `mut x`
+LL |     f(&mut *x);
+   |            ^^ cannot borrow as mutable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/issues/issue-36617.rs b/src/test/ui/issues/issue-36617.rs
new file mode 100644
index 0000000..8709268
--- /dev/null
+++ b/src/test/ui/issues/issue-36617.rs
@@ -0,0 +1,3 @@
+#![derive(Copy)] //~ ERROR `derive` may only be applied to structs, enums and unions
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-36617.stderr b/src/test/ui/issues/issue-36617.stderr
new file mode 100644
index 0000000..296fec4
--- /dev/null
+++ b/src/test/ui/issues/issue-36617.stderr
@@ -0,0 +1,8 @@
+error: `derive` may only be applied to structs, enums and unions
+  --> $DIR/issue-36617.rs:1:1
+   |
+LL | #![derive(Copy)]
+   | ^^^^^^^^^^^^^^^^ help: try an outer attribute: `#[derive(Copy)]`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-36638.rs b/src/test/ui/issues/issue-36638.rs
new file mode 100644
index 0000000..1d006fb
--- /dev/null
+++ b/src/test/ui/issues/issue-36638.rs
@@ -0,0 +1,10 @@
+// compile-flags: -Z continue-parse-after-error
+
+struct Foo<Self>(Self);
+//~^ ERROR expected identifier, found keyword `Self`
+//~^^ ERROR E0392
+
+trait Bar<Self> {}
+//~^ ERROR expected identifier, found keyword `Self`
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-36638.stderr b/src/test/ui/issues/issue-36638.stderr
new file mode 100644
index 0000000..1713430
--- /dev/null
+++ b/src/test/ui/issues/issue-36638.stderr
@@ -0,0 +1,23 @@
+error: expected identifier, found keyword `Self`
+  --> $DIR/issue-36638.rs:3:12
+   |
+LL | struct Foo<Self>(Self);
+   |            ^^^^ expected identifier, found keyword
+
+error: expected identifier, found keyword `Self`
+  --> $DIR/issue-36638.rs:7:11
+   |
+LL | trait Bar<Self> {}
+   |           ^^^^ expected identifier, found keyword
+
+error[E0392]: parameter `Self` is never used
+  --> $DIR/issue-36638.rs:3:12
+   |
+LL | struct Foo<Self>(Self);
+   |            ^^^^ unused type parameter
+   |
+   = help: consider removing `Self` or using a marker such as `std::marker::PhantomData`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0392`.
diff --git a/src/test/ui/issues/issue-3668-2.rs b/src/test/ui/issues/issue-3668-2.rs
new file mode 100644
index 0000000..525f6f5
--- /dev/null
+++ b/src/test/ui/issues/issue-3668-2.rs
@@ -0,0 +1,6 @@
+fn f(x:isize) {
+    static child: isize = x + 1;
+    //~^ ERROR attempt to use a non-constant value in a constant
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-3668-2.stderr b/src/test/ui/issues/issue-3668-2.stderr
new file mode 100644
index 0000000..d6a6e83
--- /dev/null
+++ b/src/test/ui/issues/issue-3668-2.stderr
@@ -0,0 +1,9 @@
+error[E0435]: attempt to use a non-constant value in a constant
+  --> $DIR/issue-3668-2.rs:2:27
+   |
+LL |     static child: isize = x + 1;
+   |                           ^ non-constant value
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0435`.
diff --git a/src/test/ui/issues/issue-3668.rs b/src/test/ui/issues/issue-3668.rs
new file mode 100644
index 0000000..0e1f19a
--- /dev/null
+++ b/src/test/ui/issues/issue-3668.rs
@@ -0,0 +1,14 @@
+struct P { child: Option<Box<P>> }
+trait PTrait {
+   fn getChildOption(&self) -> Option<Box<P>>;
+}
+
+impl PTrait for P {
+   fn getChildOption(&self) -> Option<Box<P>> {
+       static childVal: Box<P> = self.child.get();
+       //~^ ERROR attempt to use a non-constant value in a constant
+       panic!();
+   }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-3668.stderr b/src/test/ui/issues/issue-3668.stderr
new file mode 100644
index 0000000..98cd363
--- /dev/null
+++ b/src/test/ui/issues/issue-3668.stderr
@@ -0,0 +1,9 @@
+error[E0435]: attempt to use a non-constant value in a constant
+  --> $DIR/issue-3668.rs:8:34
+   |
+LL |        static childVal: Box<P> = self.child.get();
+   |                                  ^^^^ non-constant value
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0435`.
diff --git a/src/test/ui/issues/issue-36708.rs b/src/test/ui/issues/issue-36708.rs
new file mode 100644
index 0000000..c9d9f2a
--- /dev/null
+++ b/src/test/ui/issues/issue-36708.rs
@@ -0,0 +1,12 @@
+// aux-build:issue-36708.rs
+
+extern crate issue_36708 as lib;
+
+struct Bar;
+
+impl lib::Foo for Bar {
+    fn foo<T>() {}
+    //~^ ERROR E0049
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-36708.stderr b/src/test/ui/issues/issue-36708.stderr
new file mode 100644
index 0000000..835094c
--- /dev/null
+++ b/src/test/ui/issues/issue-36708.stderr
@@ -0,0 +1,9 @@
+error[E0049]: method `foo` has 1 type parameter but its trait declaration has 0 type parameters
+  --> $DIR/issue-36708.rs:8:11
+   |
+LL |     fn foo<T>() {}
+   |           ^^^ found 1 type parameter, expected 0
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0049`.
diff --git a/src/test/ui/issues/issue-36744-without-calls.rs b/src/test/ui/issues/issue-36744-without-calls.rs
new file mode 100644
index 0000000..57d63e6
--- /dev/null
+++ b/src/test/ui/issues/issue-36744-without-calls.rs
@@ -0,0 +1,13 @@
+// compile-pass
+// Tests for an LLVM abort when storing a lifetime-parametric fn into
+// context that is expecting one that is not lifetime-parametric
+// (i.e., has no `for <'_>`).
+
+pub struct A<'a>(&'a ());
+pub struct S<T>(T);
+
+pub fn bad<'s>(v: &mut S<fn(A<'s>)>, y: S<for<'b> fn(A<'b>)>) {
+    *v = y;
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-3680.rs b/src/test/ui/issues/issue-3680.rs
new file mode 100644
index 0000000..3604203
--- /dev/null
+++ b/src/test/ui/issues/issue-3680.rs
@@ -0,0 +1,9 @@
+fn main() {
+    match None {
+        Err(_) => ()
+        //~^ ERROR mismatched types
+        //~| expected type `std::option::Option<_>`
+        //~| found type `std::result::Result<_, _>`
+        //~| expected enum `std::option::Option`, found enum `std::result::Result`
+    }
+}
diff --git a/src/test/ui/issues/issue-3680.stderr b/src/test/ui/issues/issue-3680.stderr
new file mode 100644
index 0000000..51903cf
--- /dev/null
+++ b/src/test/ui/issues/issue-3680.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-3680.rs:3:9
+   |
+LL |     match None {
+   |           ---- this match expression has type `std::option::Option<_>`
+LL |         Err(_) => ()
+   |         ^^^^^^ expected enum `std::option::Option`, found enum `std::result::Result`
+   |
+   = note: expected type `std::option::Option<_>`
+              found type `std::result::Result<_, _>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-36839.rs b/src/test/ui/issues/issue-36839.rs
new file mode 100644
index 0000000..0944d07
--- /dev/null
+++ b/src/test/ui/issues/issue-36839.rs
@@ -0,0 +1,23 @@
+// compile-pass
+// skip-codegen
+
+pub trait Foo {
+    type Bar;
+}
+
+pub trait Broken {
+    type Assoc;
+    fn broken(&self) where Self::Assoc: Foo;
+}
+
+impl<T> Broken for T {
+    type Assoc = ();
+    fn broken(&self) where Self::Assoc: Foo {
+        let _x: <Self::Assoc as Foo>::Bar;
+    }
+}
+
+
+fn main() {
+    let _m: &Broken<Assoc=()> = &();
+}
diff --git a/src/test/ui/issues/issue-36881.rs b/src/test/ui/issues/issue-36881.rs
new file mode 100644
index 0000000..2b0508d
--- /dev/null
+++ b/src/test/ui/issues/issue-36881.rs
@@ -0,0 +1,7 @@
+// aux-build:issue-36881-aux.rs
+
+fn main() {
+    #[allow(unused_extern_crates)]
+    extern crate issue_36881_aux;
+    use issue_36881_aux::Foo; //~ ERROR unresolved import
+}
diff --git a/src/test/ui/issues/issue-36881.stderr b/src/test/ui/issues/issue-36881.stderr
new file mode 100644
index 0000000..2ec636f
--- /dev/null
+++ b/src/test/ui/issues/issue-36881.stderr
@@ -0,0 +1,9 @@
+error[E0432]: unresolved import `issue_36881_aux`
+  --> $DIR/issue-36881.rs:6:9
+   |
+LL |     use issue_36881_aux::Foo;
+   |         ^^^^^^^^^^^^^^^ maybe a missing `extern crate issue_36881_aux;`?
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/issues/issue-3702-2.rs b/src/test/ui/issues/issue-3702-2.rs
new file mode 100644
index 0000000..c3a92a2
--- /dev/null
+++ b/src/test/ui/issues/issue-3702-2.rs
@@ -0,0 +1,20 @@
+pub trait ToPrimitive {
+    fn to_int(&self) -> isize { 0 }
+}
+
+impl ToPrimitive for i32 {}
+impl ToPrimitive for isize {}
+
+trait Add {
+    fn to_int(&self) -> isize;
+    fn add_dynamic(&self, other: &Add) -> isize;
+}
+
+impl Add for isize {
+    fn to_int(&self) -> isize { *self }
+    fn add_dynamic(&self, other: &Add) -> isize {
+        self.to_int() + other.to_int() //~ ERROR multiple applicable items in scope
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/issues/issue-3702-2.stderr b/src/test/ui/issues/issue-3702-2.stderr
new file mode 100644
index 0000000..347a19b
--- /dev/null
+++ b/src/test/ui/issues/issue-3702-2.stderr
@@ -0,0 +1,20 @@
+error[E0034]: multiple applicable items in scope
+  --> $DIR/issue-3702-2.rs:16:14
+   |
+LL |         self.to_int() + other.to_int()
+   |              ^^^^^^ multiple `to_int` found
+   |
+note: candidate #1 is defined in an impl of the trait `ToPrimitive` for the type `isize`
+  --> $DIR/issue-3702-2.rs:2:5
+   |
+LL |     fn to_int(&self) -> isize { 0 }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+note: candidate #2 is defined in an impl of the trait `Add` for the type `isize`
+  --> $DIR/issue-3702-2.rs:14:5
+   |
+LL |     fn to_int(&self) -> isize { *self }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0034`.
diff --git a/src/test/ui/issues/issue-37026.rs b/src/test/ui/issues/issue-37026.rs
new file mode 100644
index 0000000..fd678a7
--- /dev/null
+++ b/src/test/ui/issues/issue-37026.rs
@@ -0,0 +1,8 @@
+// aux-build:empty-struct.rs
+
+extern crate empty_struct;
+
+fn main() {
+    let empty_struct::XEmpty2 = (); //~ ERROR mismatched types
+    let empty_struct::XEmpty6(..) = (); //~ ERROR mismatched types
+}
diff --git a/src/test/ui/issues/issue-37026.stderr b/src/test/ui/issues/issue-37026.stderr
new file mode 100644
index 0000000..1f81264
--- /dev/null
+++ b/src/test/ui/issues/issue-37026.stderr
@@ -0,0 +1,21 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-37026.rs:6:9
+   |
+LL |     let empty_struct::XEmpty2 = ();
+   |         ^^^^^^^^^^^^^^^^^^^^^ expected (), found struct `empty_struct::XEmpty2`
+   |
+   = note: expected type `()`
+              found type `empty_struct::XEmpty2`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-37026.rs:7:9
+   |
+LL |     let empty_struct::XEmpty6(..) = ();
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found struct `empty_struct::XEmpty6`
+   |
+   = note: expected type `()`
+              found type `empty_struct::XEmpty6`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-37051.rs b/src/test/ui/issues/issue-37051.rs
new file mode 100644
index 0000000..1ccf5b9
--- /dev/null
+++ b/src/test/ui/issues/issue-37051.rs
@@ -0,0 +1,20 @@
+// compile-pass
+// skip-codegen
+#![feature(associated_type_defaults)]
+#![allow(warnings)]
+trait State: Sized {
+    type NextState: State = StateMachineEnded;
+    fn execute(self) -> Option<Self::NextState>;
+}
+
+struct StateMachineEnded;
+
+impl State for StateMachineEnded {
+    fn execute(self) -> Option<Self::NextState> {
+        None
+    }
+}
+
+
+fn main() {
+}
diff --git a/src/test/ui/issues/issue-3707.rs b/src/test/ui/issues/issue-3707.rs
new file mode 100644
index 0000000..844a2dc
--- /dev/null
+++ b/src/test/ui/issues/issue-3707.rs
@@ -0,0 +1,18 @@
+struct Obj {
+    member: usize
+}
+
+impl Obj {
+    pub fn boom() -> bool {
+        return 1+1 == 2
+    }
+    pub fn chirp(&self) {
+        self.boom(); //~ ERROR no method named `boom` found for type `&Obj` in the current scope
+    }
+}
+
+fn main() {
+    let o = Obj { member: 0 };
+    o.chirp();
+    1 + 1;
+}
diff --git a/src/test/ui/issues/issue-3707.stderr b/src/test/ui/issues/issue-3707.stderr
new file mode 100644
index 0000000..05c8ce4
--- /dev/null
+++ b/src/test/ui/issues/issue-3707.stderr
@@ -0,0 +1,19 @@
+error[E0599]: no method named `boom` found for type `&Obj` in the current scope
+  --> $DIR/issue-3707.rs:10:14
+   |
+LL |         self.boom();
+   |         -----^^^^
+   |         |    |
+   |         |    this is an associated function, not a method
+   |         help: use associated function syntax instead: `&Obj::boom`
+   |
+   = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
+note: the candidate is defined in an impl for the type `Obj`
+  --> $DIR/issue-3707.rs:6:5
+   |
+LL |     pub fn boom() -> bool {
+   |     ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/issues/issue-37131.rs b/src/test/ui/issues/issue-37131.rs
new file mode 100644
index 0000000..aa3b6ea
--- /dev/null
+++ b/src/test/ui/issues/issue-37131.rs
@@ -0,0 +1,8 @@
+// Tests that compiling for a target which is not installed will result in a helpful
+// error message.
+
+// compile-flags: --target=thumbv6m-none-eabi
+// ignore-arm
+
+// error-pattern:target may not be installed
+fn main() { }
diff --git a/src/test/ui/issues/issue-37131.stderr b/src/test/ui/issues/issue-37131.stderr
new file mode 100644
index 0000000..660a693
--- /dev/null
+++ b/src/test/ui/issues/issue-37131.stderr
@@ -0,0 +1,7 @@
+error[E0463]: can't find crate for `std`
+   |
+   = note: the `thumbv6m-none-eabi` target may not be installed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0463`.
diff --git a/src/test/ui/issues/issue-37311-type-length-limit/issue-37311.rs b/src/test/ui/issues/issue-37311-type-length-limit/issue-37311.rs
new file mode 100644
index 0000000..9a8dafe
--- /dev/null
+++ b/src/test/ui/issues/issue-37311-type-length-limit/issue-37311.rs
@@ -0,0 +1,20 @@
+trait Mirror {
+    type Image;
+}
+
+impl<T> Mirror for T { type Image = T; }
+
+trait Foo {
+    fn recurse(&self);
+}
+
+impl<T> Foo for T {
+    #[allow(unconditional_recursion)]
+    fn recurse(&self) { //~ ERROR reached the type-length limit
+        (self, self).recurse();
+    }
+}
+
+fn main() {
+    ().recurse();
+}
diff --git a/src/test/ui/issues/issue-37311-type-length-limit/issue-37311.stderr b/src/test/ui/issues/issue-37311-type-length-limit/issue-37311.stderr
new file mode 100644
index 0000000..aead415
--- /dev/null
+++ b/src/test/ui/issues/issue-37311-type-length-limit/issue-37311.stderr
@@ -0,0 +1,12 @@
+error: reached the type-length limit while instantiating `<(&(&(&(&(&(&(&(&(&(&(&(&(&(&(&(...))))))))))))))) as Foo>::recurse`
+  --> $DIR/issue-37311.rs:13:5
+   |
+LL | /     fn recurse(&self) {
+LL | |         (self, self).recurse();
+LL | |     }
+   | |_____^
+   |
+   = note: consider adding a `#![type_length_limit="2097149"]` attribute to your crate
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-37323.rs b/src/test/ui/issues/issue-37323.rs
new file mode 100644
index 0000000..a7cf0cd
--- /dev/null
+++ b/src/test/ui/issues/issue-37323.rs
@@ -0,0 +1,19 @@
+// compile-pass
+
+#![feature(rustc_attrs)]
+#![allow(warnings)]
+
+#[derive(Debug)]
+struct Point {
+}
+
+struct NestedA<'a, 'b> {
+    x: &'a NestedB<'b>
+}
+
+struct NestedB<'a> {
+    x: &'a i32,
+}
+
+fn main() {
+}
diff --git a/src/test/ui/issues/issue-37366.rs b/src/test/ui/issues/issue-37366.rs
new file mode 100644
index 0000000..1c27960
--- /dev/null
+++ b/src/test/ui/issues/issue-37366.rs
@@ -0,0 +1,17 @@
+// ignore-emscripten
+// compile-pass
+// skip-codegen
+#![feature(asm)]
+
+macro_rules! interrupt_handler {
+    () => {
+        unsafe fn _interrupt_handler() {
+            asm!("pop  eax" :::: "intel");
+        }
+    }
+}
+interrupt_handler!{}
+
+
+fn main() {
+}
diff --git a/src/test/ui/issues/issue-37510.rs b/src/test/ui/issues/issue-37510.rs
new file mode 100644
index 0000000..465e680
--- /dev/null
+++ b/src/test/ui/issues/issue-37510.rs
@@ -0,0 +1,16 @@
+// compile-pass
+// skip-codegen
+
+fn foo(_: &mut i32) -> bool { true }
+
+
+fn main() {
+    let opt = Some(92);
+    let mut x = 62;
+
+    if let Some(_) = opt {
+
+    } else if foo(&mut x) {
+
+    }
+}
diff --git a/src/test/ui/issues/issue-37515.rs b/src/test/ui/issues/issue-37515.rs
new file mode 100644
index 0000000..090b9bb
--- /dev/null
+++ b/src/test/ui/issues/issue-37515.rs
@@ -0,0 +1,10 @@
+// skip-codegen
+// compile-pass
+#![warn(unused)]
+
+type Z = for<'x> Send;
+//~^ WARN type alias is never used
+
+
+fn main() {
+}
diff --git a/src/test/ui/issues/issue-37515.stderr b/src/test/ui/issues/issue-37515.stderr
new file mode 100644
index 0000000..1b49655
--- /dev/null
+++ b/src/test/ui/issues/issue-37515.stderr
@@ -0,0 +1,13 @@
+warning: type alias is never used: `Z`
+  --> $DIR/issue-37515.rs:5:1
+   |
+LL | type Z = for<'x> Send;
+   | ^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/issue-37515.rs:3:9
+   |
+LL | #![warn(unused)]
+   |         ^^^^^^
+   = note: #[warn(dead_code)] implied by #[warn(unused)]
+
diff --git a/src/test/ui/issues/issue-37534.rs b/src/test/ui/issues/issue-37534.rs
new file mode 100644
index 0000000..9386b45
--- /dev/null
+++ b/src/test/ui/issues/issue-37534.rs
@@ -0,0 +1,6 @@
+struct Foo<T: ?Hash> { }
+//~^ ERROR cannot find trait `Hash` in this scope
+//~^^ ERROR parameter `T` is never used
+//~^^^ WARN default bound relaxed for a type parameter, but this does nothing
+
+fn main() { }
diff --git a/src/test/ui/issues/issue-37534.stderr b/src/test/ui/issues/issue-37534.stderr
new file mode 100644
index 0000000..fe14354
--- /dev/null
+++ b/src/test/ui/issues/issue-37534.stderr
@@ -0,0 +1,28 @@
+error[E0405]: cannot find trait `Hash` in this scope
+  --> $DIR/issue-37534.rs:1:16
+   |
+LL | struct Foo<T: ?Hash> { }
+   |                ^^^^ not found in this scope
+help: possible candidate is found in another module, you can import it into scope
+   |
+LL | use std::hash::Hash;
+   |
+
+warning: default bound relaxed for a type parameter, but this does nothing because the given bound is not a default. Only `?Sized` is supported
+  --> $DIR/issue-37534.rs:1:12
+   |
+LL | struct Foo<T: ?Hash> { }
+   |            ^
+
+error[E0392]: parameter `T` is never used
+  --> $DIR/issue-37534.rs:1:12
+   |
+LL | struct Foo<T: ?Hash> { }
+   |            ^ unused type parameter
+   |
+   = help: consider removing `T` or using a marker such as `std::marker::PhantomData`
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0392, E0405.
+For more information about an error, try `rustc --explain E0392`.
diff --git a/src/test/ui/issues/issue-37550.rs b/src/test/ui/issues/issue-37550.rs
new file mode 100644
index 0000000..505c030
--- /dev/null
+++ b/src/test/ui/issues/issue-37550.rs
@@ -0,0 +1,6 @@
+const fn x() {
+    let t = true;
+    let x = || t; //~ ERROR function pointers in const fn are unstable
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-37550.stderr b/src/test/ui/issues/issue-37550.stderr
new file mode 100644
index 0000000..41f33a3
--- /dev/null
+++ b/src/test/ui/issues/issue-37550.stderr
@@ -0,0 +1,11 @@
+error[E0723]: function pointers in const fn are unstable (see issue #57563)
+  --> $DIR/issue-37550.rs:3:9
+   |
+LL |     let x = || t;
+   |         ^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0723`.
diff --git a/src/test/ui/issues/issue-37576.rs b/src/test/ui/issues/issue-37576.rs
new file mode 100644
index 0000000..e7f933a
--- /dev/null
+++ b/src/test/ui/issues/issue-37576.rs
@@ -0,0 +1,45 @@
+fn main() {
+    'test_1: while break 'test_1 {}
+    while break {}
+    //~^ ERROR `break` or `continue` with no label
+
+    'test_2: while let true = break 'test_2 {}
+    while let true = break {}
+    //~^ ERROR `break` or `continue` with no label
+
+    loop { 'test_3: while break 'test_3 {} }
+    loop { while break {} }
+    //~^ ERROR `break` or `continue` with no label
+
+    loop {
+        'test_4: while break 'test_4 {}
+        break;
+    }
+    loop {
+        while break {}
+        //~^ ERROR `break` or `continue` with no label
+        break;
+    }
+
+    'test_5: while continue 'test_5 {}
+    while continue {}
+    //~^ ERROR `break` or `continue` with no label
+
+    'test_6: while let true = continue 'test_6 {}
+    while let true = continue {}
+    //~^ ERROR `break` or `continue` with no label
+
+    loop { 'test_7: while continue 'test_7 {} }
+    loop { while continue {} }
+    //~^ ERROR `break` or `continue` with no label
+
+    loop {
+        'test_8: while continue 'test_8 {}
+        continue;
+    }
+    loop {
+        while continue {}
+        //~^ ERROR `break` or `continue` with no label
+        continue;
+    }
+}
diff --git a/src/test/ui/issues/issue-37576.stderr b/src/test/ui/issues/issue-37576.stderr
new file mode 100644
index 0000000..d19e1f4
--- /dev/null
+++ b/src/test/ui/issues/issue-37576.stderr
@@ -0,0 +1,51 @@
+error[E0590]: `break` or `continue` with no label in the condition of a `while` loop
+  --> $DIR/issue-37576.rs:3:11
+   |
+LL |     while break {}
+   |           ^^^^^ unlabeled `break` in the condition of a `while` loop
+
+error[E0590]: `break` or `continue` with no label in the condition of a `while` loop
+  --> $DIR/issue-37576.rs:7:22
+   |
+LL |     while let true = break {}
+   |                      ^^^^^ unlabeled `break` in the condition of a `while` loop
+
+error[E0590]: `break` or `continue` with no label in the condition of a `while` loop
+  --> $DIR/issue-37576.rs:11:18
+   |
+LL |     loop { while break {} }
+   |                  ^^^^^ unlabeled `break` in the condition of a `while` loop
+
+error[E0590]: `break` or `continue` with no label in the condition of a `while` loop
+  --> $DIR/issue-37576.rs:19:15
+   |
+LL |         while break {}
+   |               ^^^^^ unlabeled `break` in the condition of a `while` loop
+
+error[E0590]: `break` or `continue` with no label in the condition of a `while` loop
+  --> $DIR/issue-37576.rs:25:11
+   |
+LL |     while continue {}
+   |           ^^^^^^^^ unlabeled `continue` in the condition of a `while` loop
+
+error[E0590]: `break` or `continue` with no label in the condition of a `while` loop
+  --> $DIR/issue-37576.rs:29:22
+   |
+LL |     while let true = continue {}
+   |                      ^^^^^^^^ unlabeled `continue` in the condition of a `while` loop
+
+error[E0590]: `break` or `continue` with no label in the condition of a `while` loop
+  --> $DIR/issue-37576.rs:33:18
+   |
+LL |     loop { while continue {} }
+   |                  ^^^^^^^^ unlabeled `continue` in the condition of a `while` loop
+
+error[E0590]: `break` or `continue` with no label in the condition of a `while` loop
+  --> $DIR/issue-37576.rs:41:15
+   |
+LL |         while continue {}
+   |               ^^^^^^^^ unlabeled `continue` in the condition of a `while` loop
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0590`.
diff --git a/src/test/ui/issues/issue-37598.rs b/src/test/ui/issues/issue-37598.rs
new file mode 100644
index 0000000..209f797
--- /dev/null
+++ b/src/test/ui/issues/issue-37598.rs
@@ -0,0 +1,13 @@
+// compile-pass
+#![allow(dead_code)]
+#![feature(slice_patterns)]
+
+fn check(list: &[u8]) {
+    match list {
+        &[] => {},
+        &[_u1, _u2, ref _next..] => {},
+        &[_u1] => {},
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-3763.rs b/src/test/ui/issues/issue-3763.rs
new file mode 100644
index 0000000..5d17a30
--- /dev/null
+++ b/src/test/ui/issues/issue-3763.rs
@@ -0,0 +1,26 @@
+mod my_mod {
+    pub struct MyStruct {
+        priv_field: isize
+    }
+    pub fn MyStruct () -> MyStruct {
+        MyStruct {priv_field: 4}
+    }
+    impl MyStruct {
+        fn happyfun(&self) {}
+    }
+}
+
+fn main() {
+    let my_struct = my_mod::MyStruct();
+    let _woohoo = (&my_struct).priv_field;
+    //~^ ERROR field `priv_field` of struct `my_mod::MyStruct` is private
+
+    let _woohoo = (Box::new(my_struct)).priv_field;
+    //~^ ERROR field `priv_field` of struct `my_mod::MyStruct` is private
+
+    (&my_struct).happyfun();               //~ ERROR method `happyfun` is private
+
+    (Box::new(my_struct)).happyfun();          //~ ERROR method `happyfun` is private
+    let nope = my_struct.priv_field;
+    //~^ ERROR field `priv_field` of struct `my_mod::MyStruct` is private
+}
diff --git a/src/test/ui/issues/issue-3763.stderr b/src/test/ui/issues/issue-3763.stderr
new file mode 100644
index 0000000..cc95d22
--- /dev/null
+++ b/src/test/ui/issues/issue-3763.stderr
@@ -0,0 +1,34 @@
+error[E0616]: field `priv_field` of struct `my_mod::MyStruct` is private
+  --> $DIR/issue-3763.rs:15:19
+   |
+LL |     let _woohoo = (&my_struct).priv_field;
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0616]: field `priv_field` of struct `my_mod::MyStruct` is private
+  --> $DIR/issue-3763.rs:18:19
+   |
+LL |     let _woohoo = (Box::new(my_struct)).priv_field;
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0624]: method `happyfun` is private
+  --> $DIR/issue-3763.rs:21:18
+   |
+LL |     (&my_struct).happyfun();
+   |                  ^^^^^^^^
+
+error[E0624]: method `happyfun` is private
+  --> $DIR/issue-3763.rs:23:27
+   |
+LL |     (Box::new(my_struct)).happyfun();
+   |                           ^^^^^^^^
+
+error[E0616]: field `priv_field` of struct `my_mod::MyStruct` is private
+  --> $DIR/issue-3763.rs:24:16
+   |
+LL |     let nope = my_struct.priv_field;
+   |                ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
+
+Some errors occurred: E0616, E0624.
+For more information about an error, try `rustc --explain E0616`.
diff --git a/src/test/ui/issues/issue-37655.rs b/src/test/ui/issues/issue-37655.rs
new file mode 100644
index 0000000..bfc6406
--- /dev/null
+++ b/src/test/ui/issues/issue-37655.rs
@@ -0,0 +1,37 @@
+// compile-pass
+// Regression test for #37655. The problem was a false edge created by
+// coercion that wound up requiring that `'a` (in `split()`) outlive
+// `'b`, which shouldn't be necessary.
+
+#![allow(warnings)]
+
+trait SliceExt<T> {
+    type Item;
+
+    fn get_me<I>(&self, index: I) -> &I::Output
+        where I: SliceIndex<Self::Item>;
+}
+
+impl<T> SliceExt<T> for [T] {
+    type Item = T;
+
+    fn get_me<I>(&self, index: I) -> &I::Output
+        where I: SliceIndex<T>
+    {
+        panic!()
+    }
+}
+
+pub trait SliceIndex<T> {
+    type Output: ?Sized;
+}
+
+impl<T> SliceIndex<T> for usize {
+    type Output = T;
+}
+
+fn foo<'a, 'b>(split: &'b [&'a [u8]]) -> &'a [u8] {
+    split.get_me(0)
+}
+
+fn main() { }
diff --git a/src/test/ui/issues/issue-37665.rs b/src/test/ui/issues/issue-37665.rs
new file mode 100644
index 0000000..c20782a
--- /dev/null
+++ b/src/test/ui/issues/issue-37665.rs
@@ -0,0 +1,11 @@
+// compile-flags: -Z unpretty=mir
+// ignore-cloudabi no std::path
+
+use std::path::MAIN_SEPARATOR;
+
+fn main() {
+    let mut foo : String = "hello".to_string();
+    foo.push(MAIN_SEPARATOR);
+    println!("{}", foo);
+    let x: () = 0; //~ ERROR: mismatched types
+}
diff --git a/src/test/ui/issues/issue-37665.stderr b/src/test/ui/issues/issue-37665.stderr
new file mode 100644
index 0000000..c274946
--- /dev/null
+++ b/src/test/ui/issues/issue-37665.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-37665.rs:10:17
+   |
+LL |     let x: () = 0;
+   |                 ^ expected (), found integer
+   |
+   = note: expected type `()`
+              found type `{integer}`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-37725.rs b/src/test/ui/issues/issue-37725.rs
new file mode 100644
index 0000000..a572781
--- /dev/null
+++ b/src/test/ui/issues/issue-37725.rs
@@ -0,0 +1,10 @@
+// compile-pass
+#![allow(dead_code)]
+trait Foo {
+    fn foo(&self);
+}
+
+fn foo<'a>(s: &'a mut ()) where &'a mut (): Foo {
+    s.foo();
+}
+fn main() {}
diff --git a/src/test/ui/issues/issue-37733.rs b/src/test/ui/issues/issue-37733.rs
new file mode 100644
index 0000000..2dcb0cd
--- /dev/null
+++ b/src/test/ui/issues/issue-37733.rs
@@ -0,0 +1,7 @@
+// compile-pass
+#![allow(dead_code)]
+type A = for<> fn();
+
+type B = for<'a,> fn();
+
+pub fn main() {}
diff --git a/src/test/ui/issues/issue-3779.rs b/src/test/ui/issues/issue-3779.rs
new file mode 100644
index 0000000..901c1be
--- /dev/null
+++ b/src/test/ui/issues/issue-3779.rs
@@ -0,0 +1,8 @@
+struct S {
+    //~^ ERROR E0072
+    element: Option<S>
+}
+
+fn main() {
+    let x = S { element: None };
+}
diff --git a/src/test/ui/issues/issue-3779.stderr b/src/test/ui/issues/issue-3779.stderr
new file mode 100644
index 0000000..ba1e842
--- /dev/null
+++ b/src/test/ui/issues/issue-3779.stderr
@@ -0,0 +1,14 @@
+error[E0072]: recursive type `S` has infinite size
+  --> $DIR/issue-3779.rs:1:1
+   |
+LL | struct S {
+   | ^^^^^^^^ recursive type has infinite size
+LL |
+LL |     element: Option<S>
+   |     ------------------ recursive without indirection
+   |
+   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `S` representable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0072`.
diff --git a/src/test/ui/issues/issue-37884.rs b/src/test/ui/issues/issue-37884.rs
new file mode 100644
index 0000000..ee37481
--- /dev/null
+++ b/src/test/ui/issues/issue-37884.rs
@@ -0,0 +1,14 @@
+struct RepeatMut<'a, T>(T, &'a ());
+
+impl<'a, T: 'a> Iterator for RepeatMut<'a, T> {
+
+    type Item = &'a mut T;
+    fn next(&'a mut self) -> Option<Self::Item>
+    //~^ ERROR method not compatible with trait
+    //~| lifetime mismatch
+    {
+        Some(&mut self.0)
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-37884.stderr b/src/test/ui/issues/issue-37884.stderr
new file mode 100644
index 0000000..9a5f659
--- /dev/null
+++ b/src/test/ui/issues/issue-37884.stderr
@@ -0,0 +1,32 @@
+error[E0308]: method not compatible with trait
+  --> $DIR/issue-37884.rs:6:5
+   |
+LL | /     fn next(&'a mut self) -> Option<Self::Item>
+LL | |
+LL | |
+LL | |     {
+LL | |         Some(&mut self.0)
+LL | |     }
+   | |_____^ lifetime mismatch
+   |
+   = note: expected type `fn(&mut RepeatMut<'a, T>) -> std::option::Option<&mut T>`
+              found type `fn(&'a mut RepeatMut<'a, T>) -> std::option::Option<&mut T>`
+note: the anonymous lifetime #1 defined on the method body at 6:5...
+  --> $DIR/issue-37884.rs:6:5
+   |
+LL | /     fn next(&'a mut self) -> Option<Self::Item>
+LL | |
+LL | |
+LL | |     {
+LL | |         Some(&mut self.0)
+LL | |     }
+   | |_____^
+note: ...does not necessarily outlive the lifetime 'a as defined on the impl at 3:6
+  --> $DIR/issue-37884.rs:3:6
+   |
+LL | impl<'a, T: 'a> Iterator for RepeatMut<'a, T> {
+   |      ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-37887.rs b/src/test/ui/issues/issue-37887.rs
new file mode 100644
index 0000000..58f0c6b
--- /dev/null
+++ b/src/test/ui/issues/issue-37887.rs
@@ -0,0 +1,4 @@
+fn main() {
+    extern crate libc; //~ ERROR use of unstable
+    use libc::*; //~ ERROR unresolved import
+}
diff --git a/src/test/ui/issues/issue-37887.stderr b/src/test/ui/issues/issue-37887.stderr
new file mode 100644
index 0000000..24543a5
--- /dev/null
+++ b/src/test/ui/issues/issue-37887.stderr
@@ -0,0 +1,18 @@
+error[E0432]: unresolved import `libc`
+  --> $DIR/issue-37887.rs:3:9
+   |
+LL |     use libc::*;
+   |         ^^^^ maybe a missing `extern crate libc;`?
+
+error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead? (see issue #27812)
+  --> $DIR/issue-37887.rs:2:5
+   |
+LL |     extern crate libc;
+   |     ^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(rustc_private)] to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0432, E0658.
+For more information about an error, try `rustc --explain E0432`.
diff --git a/src/test/ui/issues/issue-38160.rs b/src/test/ui/issues/issue-38160.rs
new file mode 100644
index 0000000..a454211
--- /dev/null
+++ b/src/test/ui/issues/issue-38160.rs
@@ -0,0 +1,22 @@
+// compile-pass
+// skip-codegen
+#![feature(associated_consts)]
+#![allow(warnings)]
+trait MyTrait {
+    const MY_CONST: &'static str;
+}
+
+macro_rules! my_macro {
+    () => {
+        struct MyStruct;
+
+        impl MyTrait for MyStruct {
+            const MY_CONST: &'static str = stringify!(abc);
+        }
+    }
+}
+
+my_macro!();
+
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-3820.rs b/src/test/ui/issues/issue-3820.rs
new file mode 100644
index 0000000..fbf60ce
--- /dev/null
+++ b/src/test/ui/issues/issue-3820.rs
@@ -0,0 +1,15 @@
+struct Thing {
+    x: isize
+}
+
+impl Thing {
+    fn mul(&self, c: &isize) -> Thing {
+        Thing {x: self.x * *c}
+    }
+}
+
+fn main() {
+    let u = Thing {x: 2};
+    let _v = u.mul(&3); // This is ok
+    let w = u * 3; //~ ERROR binary operation `*` cannot be applied to type `Thing`
+}
diff --git a/src/test/ui/issues/issue-3820.stderr b/src/test/ui/issues/issue-3820.stderr
new file mode 100644
index 0000000..35eceb3
--- /dev/null
+++ b/src/test/ui/issues/issue-3820.stderr
@@ -0,0 +1,13 @@
+error[E0369]: binary operation `*` cannot be applied to type `Thing`
+  --> $DIR/issue-3820.rs:14:15
+   |
+LL |     let w = u * 3;
+   |             - ^ - {integer}
+   |             |
+   |             Thing
+   |
+   = note: an implementation of `std::ops::Mul` might be missing for `Thing`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0369`.
diff --git a/src/test/ui/issues/issue-38293.rs b/src/test/ui/issues/issue-38293.rs
new file mode 100644
index 0000000..3b13936
--- /dev/null
+++ b/src/test/ui/issues/issue-38293.rs
@@ -0,0 +1,16 @@
+// Test that `fn foo::bar::{self}` only imports `bar` in the type namespace.
+
+mod foo {
+    pub fn f() { }
+}
+use foo::f::{self}; //~ ERROR unresolved import `foo::f`
+
+mod bar {
+    pub fn baz() {}
+    pub mod baz {}
+}
+use bar::baz::{self};
+
+fn main() {
+    baz(); //~ ERROR expected function, found module `baz`
+}
diff --git a/src/test/ui/issues/issue-38293.stderr b/src/test/ui/issues/issue-38293.stderr
new file mode 100644
index 0000000..e0b2fe4f
--- /dev/null
+++ b/src/test/ui/issues/issue-38293.stderr
@@ -0,0 +1,20 @@
+error[E0432]: unresolved import `foo::f`
+  --> $DIR/issue-38293.rs:6:14
+   |
+LL | use foo::f::{self};
+   |              ^^^^ no `f` in `foo`
+
+error[E0423]: expected function, found module `baz`
+  --> $DIR/issue-38293.rs:15:5
+   |
+LL |     baz();
+   |     ^^^ not a function
+help: possible better candidate is found in another module, you can import it into scope
+   |
+LL | use bar::baz;
+   |
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0423, E0432.
+For more information about an error, try `rustc --explain E0423`.
diff --git a/src/test/ui/issues/issue-38381.rs b/src/test/ui/issues/issue-38381.rs
new file mode 100644
index 0000000..1351376
--- /dev/null
+++ b/src/test/ui/issues/issue-38381.rs
@@ -0,0 +1,9 @@
+// compile-pass
+// skip-codegen
+
+use std::ops::Deref;
+
+
+fn main() {
+    let _x: fn(&i32) -> <&i32 as Deref>::Target = unimplemented!();
+}
diff --git a/src/test/ui/issues/issue-38404.rs b/src/test/ui/issues/issue-38404.rs
new file mode 100644
index 0000000..cddd75e
--- /dev/null
+++ b/src/test/ui/issues/issue-38404.rs
@@ -0,0 +1,6 @@
+trait A<T>: std::ops::Add<Self> + Sized {}
+trait B<T>: A<T> {}
+trait C<T>: A<B<T, Output=usize>> {}
+//~^ ERROR the trait `B` cannot be made into an object
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-38404.stderr b/src/test/ui/issues/issue-38404.stderr
new file mode 100644
index 0000000..06bcf22
--- /dev/null
+++ b/src/test/ui/issues/issue-38404.stderr
@@ -0,0 +1,11 @@
+error[E0038]: the trait `B` cannot be made into an object
+  --> $DIR/issue-38404.rs:3:15
+   |
+LL | trait C<T>: A<B<T, Output=usize>> {}
+   |               ^^^^^^^^^^^^^^^^^^ the trait `B` cannot be made into an object
+   |
+   = note: the trait cannot use `Self` as a type parameter in the supertraits or where-clauses
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/issues/issue-38412.rs b/src/test/ui/issues/issue-38412.rs
new file mode 100644
index 0000000..a7c818d
--- /dev/null
+++ b/src/test/ui/issues/issue-38412.rs
@@ -0,0 +1,10 @@
+fn main() {
+    let Box(a) = loop { };
+    //~^ ERROR expected tuple struct/variant, found struct `Box`
+
+    // (The below is a trick to allow compiler to infer a type for
+    // variable `a` without attempting to ascribe a type to the
+    // pattern or otherwise attempting to name the Box type, which
+    // would run afoul of issue #22207)
+    let _b: *mut i32 = *a;
+}
diff --git a/src/test/ui/issues/issue-38412.stderr b/src/test/ui/issues/issue-38412.stderr
new file mode 100644
index 0000000..c44a0bf
--- /dev/null
+++ b/src/test/ui/issues/issue-38412.stderr
@@ -0,0 +1,9 @@
+error[E0532]: expected tuple struct/variant, found struct `Box`
+  --> $DIR/issue-38412.rs:2:9
+   |
+LL |     let Box(a) = loop { };
+   |         ^^^ constructor is not visible here due to private fields
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0532`.
diff --git a/src/test/ui/issues/issue-38458.rs b/src/test/ui/issues/issue-38458.rs
new file mode 100644
index 0000000..665a8fd
--- /dev/null
+++ b/src/test/ui/issues/issue-38458.rs
@@ -0,0 +1,5 @@
+const x: () = {
+    return; //~ ERROR return statement outside of function body
+};
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-38458.stderr b/src/test/ui/issues/issue-38458.stderr
new file mode 100644
index 0000000..c04a0111
--- /dev/null
+++ b/src/test/ui/issues/issue-38458.stderr
@@ -0,0 +1,9 @@
+error[E0572]: return statement outside of function body
+  --> $DIR/issue-38458.rs:2:5
+   |
+LL |     return;
+   |     ^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0572`.
diff --git a/src/test/ui/issues/issue-38604.rs b/src/test/ui/issues/issue-38604.rs
new file mode 100644
index 0000000..c172595
--- /dev/null
+++ b/src/test/ui/issues/issue-38604.rs
@@ -0,0 +1,16 @@
+trait Q<T:?Sized> {}
+trait Foo where u32: Q<Self> {
+    fn foo(&self);
+}
+
+impl Q<()> for u32 {}
+impl Foo for () {
+    fn foo(&self) {
+        println!("foo!");
+    }
+}
+
+fn main() {
+    let _f: Box<Foo> = //~ ERROR `Foo` cannot be made into an object
+        Box::new(()); //~ ERROR `Foo` cannot be made into an object
+}
diff --git a/src/test/ui/issues/issue-38604.stderr b/src/test/ui/issues/issue-38604.stderr
new file mode 100644
index 0000000..77b42b8
--- /dev/null
+++ b/src/test/ui/issues/issue-38604.stderr
@@ -0,0 +1,20 @@
+error[E0038]: the trait `Foo` cannot be made into an object
+  --> $DIR/issue-38604.rs:14:13
+   |
+LL |     let _f: Box<Foo> =
+   |             ^^^^^^^^ the trait `Foo` cannot be made into an object
+   |
+   = note: the trait cannot use `Self` as a type parameter in the supertraits or where-clauses
+
+error[E0038]: the trait `Foo` cannot be made into an object
+  --> $DIR/issue-38604.rs:15:9
+   |
+LL |         Box::new(());
+   |         ^^^^^^^^^^^^ the trait `Foo` cannot be made into an object
+   |
+   = note: the trait cannot use `Self` as a type parameter in the supertraits or where-clauses
+   = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<std::boxed::Box<dyn Foo>>` for `std::boxed::Box<()>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/issues/issue-38715.rs b/src/test/ui/issues/issue-38715.rs
new file mode 100644
index 0000000..850ffcd
--- /dev/null
+++ b/src/test/ui/issues/issue-38715.rs
@@ -0,0 +1,8 @@
+#[macro_export]
+macro_rules! foo { ($i:ident) => {} }
+
+#[macro_export]
+macro_rules! foo { () => {} } //~ ERROR a macro named `foo` has already been exported
+                              //~| WARN this was previously accepted
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-38715.stderr b/src/test/ui/issues/issue-38715.stderr
new file mode 100644
index 0000000..34e08bf
--- /dev/null
+++ b/src/test/ui/issues/issue-38715.stderr
@@ -0,0 +1,17 @@
+error: a macro named `foo` has already been exported
+  --> $DIR/issue-38715.rs:5:1
+   |
+LL | macro_rules! foo { () => {} }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `foo` already exported
+   |
+   = note: #[deny(duplicate_macro_exports)] on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #35896 <https://github.com/rust-lang/rust/issues/35896>
+note: previous macro export is now shadowed
+  --> $DIR/issue-38715.rs:2:1
+   |
+LL | macro_rules! foo { ($i:ident) => {} }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-38727.rs b/src/test/ui/issues/issue-38727.rs
new file mode 100644
index 0000000..d9f3263
--- /dev/null
+++ b/src/test/ui/issues/issue-38727.rs
@@ -0,0 +1,13 @@
+// compile-pass
+#![allow(dead_code)]
+#[repr(u64)]
+enum A {
+    A = 0u64,
+    B = !0u64,
+}
+
+fn cmp() -> A {
+    A::B
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-3874.rs b/src/test/ui/issues/issue-3874.rs
new file mode 100644
index 0000000..8a7eaf2
--- /dev/null
+++ b/src/test/ui/issues/issue-3874.rs
@@ -0,0 +1,12 @@
+// compile-pass
+#![allow(dead_code)]
+// pretty-expanded FIXME #23616
+
+enum PureCounter { PureCounterVariant(usize) }
+
+fn each<F>(thing: PureCounter, blk: F) where F: FnOnce(&usize) {
+    let PureCounter::PureCounterVariant(ref x) = thing;
+    blk(x);
+}
+
+pub fn main() {}
diff --git a/src/test/ui/issues/issue-38821.rs b/src/test/ui/issues/issue-38821.rs
new file mode 100644
index 0000000..6753860
--- /dev/null
+++ b/src/test/ui/issues/issue-38821.rs
@@ -0,0 +1,33 @@
+pub struct Nullable<T: NotNull>(T);
+
+pub trait NotNull {}
+
+pub trait IntoNullable {
+    type Nullable;
+}
+
+impl<T: NotNull> IntoNullable for T {
+    type Nullable = Nullable<T>;
+}
+
+impl<T: NotNull> IntoNullable for Nullable<T> {
+    type Nullable = Nullable<T>;
+}
+
+pub trait Expression {
+    type SqlType;
+}
+
+pub trait Column: Expression {}
+
+#[derive(Debug, Copy, Clone)]
+//~^ ERROR the trait bound `<Col as Expression>::SqlType: NotNull` is not satisfied
+pub enum ColumnInsertValue<Col, Expr> where
+    Col: Column,
+    Expr: Expression<SqlType=<Col::SqlType as IntoNullable>::Nullable>,
+{
+    Expression(Col, Expr),
+    Default(Col),
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-38821.stderr b/src/test/ui/issues/issue-38821.stderr
new file mode 100644
index 0000000..dbd204e
--- /dev/null
+++ b/src/test/ui/issues/issue-38821.stderr
@@ -0,0 +1,12 @@
+error[E0277]: the trait bound `<Col as Expression>::SqlType: NotNull` is not satisfied
+  --> $DIR/issue-38821.rs:23:17
+   |
+LL | #[derive(Debug, Copy, Clone)]
+   |                 ^^^^ the trait `NotNull` is not implemented for `<Col as Expression>::SqlType`
+   |
+   = help: consider adding a `where <Col as Expression>::SqlType: NotNull` bound
+   = note: required because of the requirements on the impl of `IntoNullable` for `<Col as Expression>::SqlType`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-38857.rs b/src/test/ui/issues/issue-38857.rs
new file mode 100644
index 0000000..81d881c
--- /dev/null
+++ b/src/test/ui/issues/issue-38857.rs
@@ -0,0 +1,5 @@
+fn main() {
+    let a = std::sys::imp::process::process_common::StdioPipes { ..panic!() };
+    //~^ ERROR failed to resolve: could not find `imp` in `sys` [E0433]
+    //~^^ ERROR module `sys` is private [E0603]
+}
diff --git a/src/test/ui/issues/issue-38857.stderr b/src/test/ui/issues/issue-38857.stderr
new file mode 100644
index 0000000..9385dc5
--- /dev/null
+++ b/src/test/ui/issues/issue-38857.stderr
@@ -0,0 +1,16 @@
+error[E0433]: failed to resolve: could not find `imp` in `sys`
+  --> $DIR/issue-38857.rs:2:23
+   |
+LL |     let a = std::sys::imp::process::process_common::StdioPipes { ..panic!() };
+   |                       ^^^ could not find `imp` in `sys`
+
+error[E0603]: module `sys` is private
+  --> $DIR/issue-38857.rs:2:18
+   |
+LL |     let a = std::sys::imp::process::process_common::StdioPipes { ..panic!() };
+   |                  ^^^
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0433, E0603.
+For more information about an error, try `rustc --explain E0433`.
diff --git a/src/test/ui/issues/issue-38868.rs b/src/test/ui/issues/issue-38868.rs
new file mode 100644
index 0000000..b0e5c37
--- /dev/null
+++ b/src/test/ui/issues/issue-38868.rs
@@ -0,0 +1,13 @@
+pub struct List<T> {
+    head: T,
+}
+
+impl Drop for List<i32> { //~ ERROR E0366
+    fn drop(&mut self) {
+        panic!()
+    }
+}
+
+fn main() {
+    List { head: 0 };
+}
diff --git a/src/test/ui/issues/issue-38868.stderr b/src/test/ui/issues/issue-38868.stderr
new file mode 100644
index 0000000..fe932c7
--- /dev/null
+++ b/src/test/ui/issues/issue-38868.stderr
@@ -0,0 +1,21 @@
+error[E0366]: Implementations of Drop cannot be specialized
+  --> $DIR/issue-38868.rs:5:1
+   |
+LL | / impl Drop for List<i32> {
+LL | |     fn drop(&mut self) {
+LL | |         panic!()
+LL | |     }
+LL | | }
+   | |_^
+   |
+note: Use same sequence of generic type and region parameters that is on the struct/enum definition
+  --> $DIR/issue-38868.rs:1:1
+   |
+LL | / pub struct List<T> {
+LL | |     head: T,
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0366`.
diff --git a/src/test/ui/issues/issue-38875/auxiliary/issue-38875-b.rs b/src/test/ui/issues/issue-38875/auxiliary/issue-38875-b.rs
new file mode 100644
index 0000000..e9f7fef
--- /dev/null
+++ b/src/test/ui/issues/issue-38875/auxiliary/issue-38875-b.rs
@@ -0,0 +1 @@
+pub const FOO: usize = *&0;
diff --git a/src/test/ui/issues/issue-38875/issue-38875.rs b/src/test/ui/issues/issue-38875/issue-38875.rs
new file mode 100644
index 0000000..df321b8
--- /dev/null
+++ b/src/test/ui/issues/issue-38875/issue-38875.rs
@@ -0,0 +1,8 @@
+// aux-build:issue-38875-b.rs
+// compile-pass
+
+extern crate issue_38875_b;
+
+fn main() {
+    let test_x = [0; issue_38875_b::FOO];
+}
diff --git a/src/test/ui/issues/issue-3888-2.rs b/src/test/ui/issues/issue-3888-2.rs
new file mode 100644
index 0000000..27d05b4
--- /dev/null
+++ b/src/test/ui/issues/issue-3888-2.rs
@@ -0,0 +1,9 @@
+// compile-pass
+#![allow(dead_code)]
+// pretty-expanded FIXME #23616
+
+fn vec_peek<'r, T>(v: &'r [T]) -> &'r [T] {
+    &v[1..5]
+}
+
+pub fn main() {}
diff --git a/src/test/ui/issues/issue-38919.rs b/src/test/ui/issues/issue-38919.rs
new file mode 100644
index 0000000..60a8793
--- /dev/null
+++ b/src/test/ui/issues/issue-38919.rs
@@ -0,0 +1,5 @@
+fn foo<T: Iterator>() {
+    T::Item; //~ ERROR no associated item named `Item` found for type `T` in the current scope
+}
+
+fn main() { }
diff --git a/src/test/ui/issues/issue-38919.stderr b/src/test/ui/issues/issue-38919.stderr
new file mode 100644
index 0000000..603d42c
--- /dev/null
+++ b/src/test/ui/issues/issue-38919.stderr
@@ -0,0 +1,9 @@
+error[E0599]: no associated item named `Item` found for type `T` in the current scope
+  --> $DIR/issue-38919.rs:2:8
+   |
+LL |     T::Item;
+   |        ^^^^ associated item not found in `T`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/issues/issue-38940.rs b/src/test/ui/issues/issue-38940.rs
new file mode 100644
index 0000000..1c78594
--- /dev/null
+++ b/src/test/ui/issues/issue-38940.rs
@@ -0,0 +1,46 @@
+// issue-38940: error printed twice for deref recursion limit exceeded
+// Test that the recursion limit can be changed. In this case, we have
+// deeply nested types that will fail the `Send` check by overflow
+// when the recursion limit is set very low.
+#![allow(dead_code)]
+#![recursion_limit="10"]
+macro_rules! link {
+    ($outer:ident, $inner:ident) => {
+        struct $outer($inner);
+        impl $outer {
+            fn new() -> $outer {
+                $outer($inner::new())
+            }
+        }
+        impl std::ops::Deref for $outer {
+            type Target = $inner;
+            fn deref(&self) -> &$inner {
+                &self.0
+            }
+        }
+    }
+}
+struct Bottom;
+impl Bottom {
+    fn new() -> Bottom {
+        Bottom
+    }
+}
+link!(Top, A);
+link!(A, B);
+link!(B, C);
+link!(C, D);
+link!(D, E);
+link!(E, F);
+link!(F, G);
+link!(G, H);
+link!(H, I);
+link!(I, J);
+link!(J, K);
+link!(K, Bottom);
+fn main() {
+    let t = Top::new();
+    let x: &Bottom = &t;
+    //~^ ERROR mismatched types
+    //~| ERROR reached the recursion limit while auto-dereferencing `I`
+}
diff --git a/src/test/ui/issues/issue-38940.stderr b/src/test/ui/issues/issue-38940.stderr
new file mode 100644
index 0000000..d94a710
--- /dev/null
+++ b/src/test/ui/issues/issue-38940.stderr
@@ -0,0 +1,21 @@
+error[E0055]: reached the recursion limit while auto-dereferencing `I`
+  --> $DIR/issue-38940.rs:43:22
+   |
+LL |     let x: &Bottom = &t;
+   |                      ^^ deref recursion limit reached
+   |
+   = help: consider adding a `#![recursion_limit="20"]` attribute to your crate
+
+error[E0308]: mismatched types
+  --> $DIR/issue-38940.rs:43:22
+   |
+LL |     let x: &Bottom = &t;
+   |                      ^^ expected struct `Bottom`, found struct `Top`
+   |
+   = note: expected type `&Bottom`
+              found type `&Top`
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0055, E0308.
+For more information about an error, try `rustc --explain E0055`.
diff --git a/src/test/ui/issues/issue-38954.rs b/src/test/ui/issues/issue-38954.rs
new file mode 100644
index 0000000..61df411
--- /dev/null
+++ b/src/test/ui/issues/issue-38954.rs
@@ -0,0 +1,4 @@
+fn _test(ref _p: str) {}
+//~^ ERROR the size for values of type
+
+fn main() { }
diff --git a/src/test/ui/issues/issue-38954.stderr b/src/test/ui/issues/issue-38954.stderr
new file mode 100644
index 0000000..a74d635
--- /dev/null
+++ b/src/test/ui/issues/issue-38954.stderr
@@ -0,0 +1,14 @@
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+  --> $DIR/issue-38954.rs:1:23
+   |
+LL | fn _test(ref _p: str) {}
+   |                       ^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `str`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: all function arguments must have a statically known size
+   = help: unsized locals are gated as an unstable feature
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-39089.rs b/src/test/ui/issues/issue-39089.rs
new file mode 100644
index 0000000..77be9d2
--- /dev/null
+++ b/src/test/ui/issues/issue-39089.rs
@@ -0,0 +1,5 @@
+// compile-pass
+#![allow(dead_code)]
+fn f<T: ?for<'a> Sized>() {}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-39175.rs b/src/test/ui/issues/issue-39175.rs
new file mode 100644
index 0000000..25225ca
--- /dev/null
+++ b/src/test/ui/issues/issue-39175.rs
@@ -0,0 +1,16 @@
+// This test ignores some platforms as the particular extension trait used
+// to demonstrate the issue is only available on unix. This is fine as
+// the fix to suggested paths is not platform-dependent and will apply on
+// these platforms also.
+
+// ignore-windows
+// ignore-cloudabi
+// ignore-emscripten
+
+use std::process::Command;
+// use std::os::unix::process::CommandExt;
+
+fn main() {
+    Command::new("echo").arg("hello").exec();
+//~^ ERROR no method named `exec`
+}
diff --git a/src/test/ui/issues/issue-39175.stderr b/src/test/ui/issues/issue-39175.stderr
new file mode 100644
index 0000000..6aee474
--- /dev/null
+++ b/src/test/ui/issues/issue-39175.stderr
@@ -0,0 +1,15 @@
+error[E0599]: no method named `exec` found for type `&mut std::process::Command` in the current scope
+  --> $DIR/issue-39175.rs:14:39
+   |
+LL |     Command::new("echo").arg("hello").exec();
+   |                                       ^^^^
+   |
+   = help: items from traits can only be used if the trait is in scope
+help: the following trait is implemented but not in scope, perhaps add a `use` for it:
+   |
+LL | use std::os::unix::process::CommandExt;
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/issues/issue-39211.rs b/src/test/ui/issues/issue-39211.rs
new file mode 100644
index 0000000..db101ae
--- /dev/null
+++ b/src/test/ui/issues/issue-39211.rs
@@ -0,0 +1,14 @@
+#![feature(associated_consts)]
+
+trait VecN {
+    const DIM: usize;
+}
+trait Mat {
+    type Row: VecN;
+}
+
+fn m<M: Mat>() {
+    let a = [3; M::Row::DIM]; //~ ERROR associated type `Row` not found for `M`
+}
+fn main() {
+}
diff --git a/src/test/ui/issues/issue-39211.stderr b/src/test/ui/issues/issue-39211.stderr
new file mode 100644
index 0000000..ea850ea
--- /dev/null
+++ b/src/test/ui/issues/issue-39211.stderr
@@ -0,0 +1,9 @@
+error[E0220]: associated type `Row` not found for `M`
+  --> $DIR/issue-39211.rs:11:17
+   |
+LL |     let a = [3; M::Row::DIM];
+   |                 ^^^^^^^^^^^ associated type `Row` not found
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0220`.
diff --git a/src/test/ui/issues/issue-39362.rs b/src/test/ui/issues/issue-39362.rs
new file mode 100644
index 0000000..ea3c8f8
--- /dev/null
+++ b/src/test/ui/issues/issue-39362.rs
@@ -0,0 +1,18 @@
+enum Foo {
+    Bar { bar: Bar, id: usize }
+}
+
+enum Bar {
+    A, B, C, D, E, F
+}
+
+fn test(f: Foo) {
+    match f {
+        //~^ ERROR non-exhaustive patterns
+        //~| patterns
+        Foo::Bar { bar: Bar::A, .. } => (),
+        Foo::Bar { bar: Bar::B, .. } => (),
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-39362.stderr b/src/test/ui/issues/issue-39362.stderr
new file mode 100644
index 0000000..55cd14a
--- /dev/null
+++ b/src/test/ui/issues/issue-39362.stderr
@@ -0,0 +1,16 @@
+error[E0004]: non-exhaustive patterns: `Bar { bar: C, .. }`, `Bar { bar: D, .. }`, `Bar { bar: E, .. }` and 1 more not covered
+  --> $DIR/issue-39362.rs:10:11
+   |
+LL | / enum Foo {
+LL | |     Bar { bar: Bar, id: usize }
+LL | | }
+   | |_- `Foo` defined here
+...
+LL |       match f {
+   |             ^ patterns `Bar { bar: C, .. }`, `Bar { bar: D, .. }`, `Bar { bar: E, .. }` and 1 more not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/issues/issue-39388.rs b/src/test/ui/issues/issue-39388.rs
new file mode 100644
index 0000000..e5b1cd9
--- /dev/null
+++ b/src/test/ui/issues/issue-39388.rs
@@ -0,0 +1,9 @@
+#![allow(unused_macros)]
+
+macro_rules! assign {
+    (($($a:tt)*) = ($($b:tt))*) => { //~ ERROR expected `*` or `+`
+        $($a)* = $($b)*
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-39388.stderr b/src/test/ui/issues/issue-39388.stderr
new file mode 100644
index 0000000..e04e16e
--- /dev/null
+++ b/src/test/ui/issues/issue-39388.stderr
@@ -0,0 +1,8 @@
+error: expected `*` or `+`
+  --> $DIR/issue-39388.rs:4:22
+   |
+LL |     (($($a:tt)*) = ($($b:tt))*) => {
+   |                      ^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-39404.rs b/src/test/ui/issues/issue-39404.rs
new file mode 100644
index 0000000..2229f2c
--- /dev/null
+++ b/src/test/ui/issues/issue-39404.rs
@@ -0,0 +1,7 @@
+#![allow(unused)]
+
+macro_rules! m { ($i) => {} }
+//~^ ERROR missing fragment specifier
+//~| WARN previously accepted
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-39404.stderr b/src/test/ui/issues/issue-39404.stderr
new file mode 100644
index 0000000..bffea49
--- /dev/null
+++ b/src/test/ui/issues/issue-39404.stderr
@@ -0,0 +1,12 @@
+error: missing fragment specifier
+  --> $DIR/issue-39404.rs:3:19
+   |
+LL | macro_rules! m { ($i) => {} }
+   |                   ^^
+   |
+   = note: #[deny(missing_fragment_specifier)] on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #40107 <https://github.com/rust-lang/rust/issues/40107>
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-39467.rs b/src/test/ui/issues/issue-39467.rs
new file mode 100644
index 0000000..077e5ce
--- /dev/null
+++ b/src/test/ui/issues/issue-39467.rs
@@ -0,0 +1,11 @@
+// compile-pass
+#![allow(dead_code)]
+macro_rules! expr { () => { () } }
+
+enum A {}
+
+impl A {
+    const A: () = expr!();
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-39559-2.rs b/src/test/ui/issues/issue-39559-2.rs
new file mode 100644
index 0000000..3a52e4d
--- /dev/null
+++ b/src/test/ui/issues/issue-39559-2.rs
@@ -0,0 +1,20 @@
+trait Dim {
+    fn dim() -> usize;
+}
+
+enum Dim3 {}
+
+impl Dim for Dim3 {
+    fn dim() -> usize {
+        3
+    }
+}
+
+fn main() {
+    let array: [usize; Dim3::dim()]
+    //~^ ERROR E0015
+    //~| ERROR E0080
+        = [0; Dim3::dim()];
+        //~^ ERROR E0015
+        //~| ERROR E0080
+}
diff --git a/src/test/ui/issues/issue-39559-2.stderr b/src/test/ui/issues/issue-39559-2.stderr
new file mode 100644
index 0000000..700dbe3
--- /dev/null
+++ b/src/test/ui/issues/issue-39559-2.stderr
@@ -0,0 +1,28 @@
+error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
+  --> $DIR/issue-39559-2.rs:14:24
+   |
+LL |     let array: [usize; Dim3::dim()]
+   |                        ^^^^^^^^^^^
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/issue-39559-2.rs:14:24
+   |
+LL |     let array: [usize; Dim3::dim()]
+   |                        ^^^^^^^^^^^ calling non-const function `<Dim3 as Dim>::dim`
+
+error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
+  --> $DIR/issue-39559-2.rs:17:15
+   |
+LL |         = [0; Dim3::dim()];
+   |               ^^^^^^^^^^^
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/issue-39559-2.rs:17:15
+   |
+LL |         = [0; Dim3::dim()];
+   |               ^^^^^^^^^^^ calling non-const function `<Dim3 as Dim>::dim`
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0015, E0080.
+For more information about an error, try `rustc --explain E0015`.
diff --git a/src/test/ui/issues/issue-39559.rs b/src/test/ui/issues/issue-39559.rs
new file mode 100644
index 0000000..5af48ca
--- /dev/null
+++ b/src/test/ui/issues/issue-39559.rs
@@ -0,0 +1,19 @@
+trait Dim {
+    fn dim() -> usize;
+}
+
+enum Dim3 {}
+
+impl Dim for Dim3 {
+    fn dim() -> usize {
+        3
+    }
+}
+
+pub struct Vector<T, D: Dim> {
+    entries: [T; D::dim()],
+    //~^ ERROR no function or associated item named `dim` found for type `D` in the current scope
+    _dummy: D,
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-39559.stderr b/src/test/ui/issues/issue-39559.stderr
new file mode 100644
index 0000000..aded0c2
--- /dev/null
+++ b/src/test/ui/issues/issue-39559.stderr
@@ -0,0 +1,13 @@
+error[E0599]: no function or associated item named `dim` found for type `D` in the current scope
+  --> $DIR/issue-39559.rs:14:21
+   |
+LL |     entries: [T; D::dim()],
+   |                     ^^^ function or associated item not found in `D`
+   |
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following trait defines an item `dim`, perhaps you need to implement it:
+           candidate #1: `Dim`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/issues/issue-39616.rs b/src/test/ui/issues/issue-39616.rs
new file mode 100644
index 0000000..3d8e28e
--- /dev/null
+++ b/src/test/ui/issues/issue-39616.rs
@@ -0,0 +1,5 @@
+fn foo(a: [0; 1]) {} //~ ERROR expected type, found `0`
+//~| ERROR expected one of `)`, `,`, `->`, `where`, or `{`, found `]`
+// FIXME(jseyfried): avoid emitting the second error (preexisting)
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-39616.stderr b/src/test/ui/issues/issue-39616.stderr
new file mode 100644
index 0000000..e24ffcd
--- /dev/null
+++ b/src/test/ui/issues/issue-39616.stderr
@@ -0,0 +1,14 @@
+error: expected type, found `0`
+  --> $DIR/issue-39616.rs:1:12
+   |
+LL | fn foo(a: [0; 1]) {}
+   |            ^
+
+error: expected one of `)`, `,`, `->`, `where`, or `{`, found `]`
+  --> $DIR/issue-39616.rs:1:16
+   |
+LL | fn foo(a: [0; 1]) {}
+   |                ^ expected one of `)`, `,`, `->`, `where`, or `{` here
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/issues/issue-39687.rs b/src/test/ui/issues/issue-39687.rs
new file mode 100644
index 0000000..cbb721f
--- /dev/null
+++ b/src/test/ui/issues/issue-39687.rs
@@ -0,0 +1,6 @@
+#![feature(fn_traits)]
+
+fn main() {
+    <fn() as Fn()>::call;
+    //~^ ERROR associated type bindings are not allowed here [E0229]
+}
diff --git a/src/test/ui/issues/issue-39687.stderr b/src/test/ui/issues/issue-39687.stderr
new file mode 100644
index 0000000..886de1d
--- /dev/null
+++ b/src/test/ui/issues/issue-39687.stderr
@@ -0,0 +1,9 @@
+error[E0229]: associated type bindings are not allowed here
+  --> $DIR/issue-39687.rs:4:16
+   |
+LL |     <fn() as Fn()>::call;
+   |                ^^ associated type not allowed here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0229`.
diff --git a/src/test/ui/issues/issue-3973.rs b/src/test/ui/issues/issue-3973.rs
new file mode 100644
index 0000000..4e00915
--- /dev/null
+++ b/src/test/ui/issues/issue-3973.rs
@@ -0,0 +1,25 @@
+struct Point {
+    x: f64,
+    y: f64,
+}
+
+trait ToString_ {
+    fn to_string(&self) -> String;
+}
+
+impl ToString_ for Point {
+    fn new(x: f64, y: f64) -> Point {
+    //~^ ERROR method `new` is not a member of trait `ToString_`
+        Point { x: x, y: y }
+    }
+
+    fn to_string(&self) -> String {
+        format!("({}, {})", self.x, self.y)
+    }
+}
+
+fn main() {
+    let p = Point::new(0.0, 0.0);
+    //~^ ERROR no function or associated item named `new` found for type `Point`
+    println!("{}", p.to_string());
+}
diff --git a/src/test/ui/issues/issue-3973.stderr b/src/test/ui/issues/issue-3973.stderr
new file mode 100644
index 0000000..576da4b
--- /dev/null
+++ b/src/test/ui/issues/issue-3973.stderr
@@ -0,0 +1,22 @@
+error[E0407]: method `new` is not a member of trait `ToString_`
+  --> $DIR/issue-3973.rs:11:5
+   |
+LL | /     fn new(x: f64, y: f64) -> Point {
+LL | |
+LL | |         Point { x: x, y: y }
+LL | |     }
+   | |_____^ not a member of trait `ToString_`
+
+error[E0599]: no function or associated item named `new` found for type `Point` in the current scope
+  --> $DIR/issue-3973.rs:22:20
+   |
+LL | struct Point {
+   | ------------ function or associated item `new` not found for this
+...
+LL |     let p = Point::new(0.0, 0.0);
+   |                    ^^^ function or associated item not found in `Point`
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0407, E0599.
+For more information about an error, try `rustc --explain E0407`.
diff --git a/src/test/ui/issues/issue-3979-2.rs b/src/test/ui/issues/issue-3979-2.rs
new file mode 100644
index 0000000..eec8c85
--- /dev/null
+++ b/src/test/ui/issues/issue-3979-2.rs
@@ -0,0 +1,18 @@
+// compile-pass
+// pretty-expanded FIXME #23616
+
+trait A {
+    fn a_method(&self);
+}
+
+trait B: A {
+    fn b_method(&self);
+}
+
+trait C: B {
+    fn c_method(&self) {
+        self.a_method();
+    }
+}
+
+pub fn main() {}
diff --git a/src/test/ui/issues/issue-39848.rs b/src/test/ui/issues/issue-39848.rs
new file mode 100644
index 0000000..5d1db7b
--- /dev/null
+++ b/src/test/ui/issues/issue-39848.rs
@@ -0,0 +1,10 @@
+macro_rules! get_opt {
+    ($tgt:expr, $field:ident) => {
+        if $tgt.has_$field() {}
+    }
+}
+
+fn main() {
+    get_opt!(bar, foo);
+    //~^ ERROR expected `{`, found `foo`
+}
diff --git a/src/test/ui/issues/issue-39848.stderr b/src/test/ui/issues/issue-39848.stderr
new file mode 100644
index 0000000..6eda03c
--- /dev/null
+++ b/src/test/ui/issues/issue-39848.stderr
@@ -0,0 +1,13 @@
+error: expected `{`, found `foo`
+  --> $DIR/issue-39848.rs:8:19
+   |
+LL |         if $tgt.has_$field() {}
+   |         --                 - help: try placing this code inside a block: `{ foo(); }`
+   |         |
+   |         this `if` statement has a condition, but no block
+...
+LL |     get_opt!(bar, foo);
+   |                   ^^^ expected `{`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-3991.rs b/src/test/ui/issues/issue-3991.rs
new file mode 100644
index 0000000..bc63aae
--- /dev/null
+++ b/src/test/ui/issues/issue-3991.rs
@@ -0,0 +1,16 @@
+// compile-pass
+#![allow(dead_code)]
+
+// pretty-expanded FIXME #23616
+
+struct HasNested {
+    nest: Vec<Vec<isize> > ,
+}
+
+impl HasNested {
+    fn method_push_local(&mut self) {
+        self.nest[0].push(0);
+    }
+}
+
+pub fn main() {}
diff --git a/src/test/ui/issues/issue-3993.rs b/src/test/ui/issues/issue-3993.rs
new file mode 100644
index 0000000..9dea54e
--- /dev/null
+++ b/src/test/ui/issues/issue-3993.rs
@@ -0,0 +1,10 @@
+use zoo::fly; //~ ERROR: function `fly` is private
+
+mod zoo {
+    fn fly() {}
+}
+
+
+fn main() {
+    fly();
+}
diff --git a/src/test/ui/issues/issue-3993.stderr b/src/test/ui/issues/issue-3993.stderr
new file mode 100644
index 0000000..ce594a3
--- /dev/null
+++ b/src/test/ui/issues/issue-3993.stderr
@@ -0,0 +1,9 @@
+error[E0603]: function `fly` is private
+  --> $DIR/issue-3993.rs:1:10
+   |
+LL | use zoo::fly;
+   |          ^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0603`.
diff --git a/src/test/ui/issues/issue-39970.rs b/src/test/ui/issues/issue-39970.rs
new file mode 100644
index 0000000..f51e3b5
--- /dev/null
+++ b/src/test/ui/issues/issue-39970.rs
@@ -0,0 +1,21 @@
+trait Array<'a> {
+    type Element: 'a;
+}
+
+trait Visit {
+    fn visit() {}
+}
+
+impl<'a> Array<'a> for () {
+    type Element = &'a ();
+}
+
+impl Visit for () where
+    //(): for<'a> Array<'a, Element=&'a ()>, // No ICE
+    (): for<'a> Array<'a, Element=()>, // ICE
+{}
+
+fn main() {
+    <() as Visit>::visit();
+    //~^ ERROR type mismatch resolving `for<'a> <() as Array<'a>>::Element == ()`
+}
diff --git a/src/test/ui/issues/issue-39970.stderr b/src/test/ui/issues/issue-39970.stderr
new file mode 100644
index 0000000..e4f1587
--- /dev/null
+++ b/src/test/ui/issues/issue-39970.stderr
@@ -0,0 +1,18 @@
+error[E0271]: type mismatch resolving `for<'a> <() as Array<'a>>::Element == ()`
+  --> $DIR/issue-39970.rs:19:5
+   |
+LL |     <() as Visit>::visit();
+   |     ^^^^^^^^^^^^^^^^^^^^ expected &(), found ()
+   |
+   = note: expected type `&()`
+              found type `()`
+   = note: required because of the requirements on the impl of `Visit` for `()`
+note: required by `Visit::visit`
+  --> $DIR/issue-39970.rs:6:5
+   |
+LL |     fn visit() {}
+   |     ^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/issues/issue-39974.rs b/src/test/ui/issues/issue-39974.rs
new file mode 100644
index 0000000..5c89a0d
--- /dev/null
+++ b/src/test/ui/issues/issue-39974.rs
@@ -0,0 +1,11 @@
+const LENGTH: f64 = 2;
+
+struct Thing {
+    f: [[f64; 2]; LENGTH],
+    //~^ ERROR mismatched types
+    //~| expected usize, found f64
+}
+
+fn main() {
+    let _t = Thing { f: [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]] };
+}
diff --git a/src/test/ui/issues/issue-39974.stderr b/src/test/ui/issues/issue-39974.stderr
new file mode 100644
index 0000000..41bfb6d
--- /dev/null
+++ b/src/test/ui/issues/issue-39974.stderr
@@ -0,0 +1,9 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-39974.rs:4:19
+   |
+LL |     f: [[f64; 2]; LENGTH],
+   |                   ^^^^^^ expected usize, found f64
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-39984.rs b/src/test/ui/issues/issue-39984.rs
new file mode 100644
index 0000000..5018b1c
--- /dev/null
+++ b/src/test/ui/issues/issue-39984.rs
@@ -0,0 +1,14 @@
+// compile-pass
+#![allow(dead_code)]
+#![allow(unreachable_code)]
+// Regression test for issue #39984.
+//
+// The key here is that the error type of the `Ok` call ought to be
+// constrained to `String`, even though it is dead-code.
+
+fn main() {}
+
+fn t() -> Result<(), String> {
+    return Err("".into());
+    Ok(())
+}
diff --git a/src/test/ui/issues/issue-40000.rs b/src/test/ui/issues/issue-40000.rs
new file mode 100644
index 0000000..320992c
--- /dev/null
+++ b/src/test/ui/issues/issue-40000.rs
@@ -0,0 +1,7 @@
+fn main() {
+    let bar: fn(&mut u32) = |_| {};
+
+    fn foo(x: Box<Fn(&i32)>) {}
+    let bar = Box::new(|x: &i32| {}) as Box<Fn(_)>;
+    foo(bar); //~ ERROR E0308
+}
diff --git a/src/test/ui/issues/issue-40000.stderr b/src/test/ui/issues/issue-40000.stderr
new file mode 100644
index 0000000..c48fb24
--- /dev/null
+++ b/src/test/ui/issues/issue-40000.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-40000.rs:6:9
+   |
+LL |     foo(bar);
+   |         ^^^ expected concrete lifetime, found bound lifetime parameter
+   |
+   = note: expected type `std::boxed::Box<(dyn for<'r> std::ops::Fn(&'r i32) + 'static)>`
+              found type `std::boxed::Box<dyn std::ops::Fn(_)>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-40136.rs b/src/test/ui/issues/issue-40136.rs
new file mode 100644
index 0000000..0849f54
--- /dev/null
+++ b/src/test/ui/issues/issue-40136.rs
@@ -0,0 +1,15 @@
+// compile-pass
+#![allow(dead_code)]
+
+macro_rules! m { () => { 0 } }
+
+trait T {
+   const C: i32 = m!();
+}
+
+struct S;
+impl S {
+    const C: i32 = m!();
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-4025.rs b/src/test/ui/issues/issue-4025.rs
new file mode 100644
index 0000000..fc036f3
--- /dev/null
+++ b/src/test/ui/issues/issue-4025.rs
@@ -0,0 +1,25 @@
+// compile-pass
+#![allow(dead_code)]
+#![allow(unused_mut)]
+/*
+# if b { x } else { y } requires identical types for x and y
+*/
+
+fn print1(b: bool, s1: &str, s2: &str) {
+    println!("{}", if b { s1 } else { s2 });
+}
+fn print2<'a, 'b>(b: bool, s1: &'a str, s2: &'b str) {
+    println!("{}", if b { s1 } else { s2 });
+}
+fn print3(b: bool, s1: &str, s2: &str) {
+    let mut s: &str;
+    if b { s = s1; } else { s = s2; }
+    println!("{}", s);
+}
+fn print4<'a, 'b>(b: bool, s1: &'a str, s2: &'b str) {
+    let mut s: &str;
+    if b { s = s1; } else { s = s2; }
+    println!("{}", s);
+}
+
+pub fn main() {}
diff --git a/src/test/ui/issues/issue-40288-2.rs b/src/test/ui/issues/issue-40288-2.rs
new file mode 100644
index 0000000..032a2e6
--- /dev/null
+++ b/src/test/ui/issues/issue-40288-2.rs
@@ -0,0 +1,31 @@
+fn prove_static<T: 'static + ?Sized>(_: &'static T) {}
+
+fn lifetime_transmute_slice<'a, T: ?Sized>(x: &'a T, y: &T) -> &'a T {
+    let mut out = [x];
+    {
+        let slice: &mut [_] = &mut out;
+        slice[0] = y;
+    }
+    out[0]
+    //~^ ERROR explicit lifetime required in the type of `y` [E0621]
+}
+
+struct Struct<T, U: ?Sized> {
+    head: T,
+    _tail: U
+}
+
+fn lifetime_transmute_struct<'a, T: ?Sized>(x: &'a T, y: &T) -> &'a T {
+    let mut out = Struct { head: x, _tail: [()] };
+    {
+        let dst: &mut Struct<_, [()]> = &mut out;
+        dst.head = y;
+    }
+    out.head
+    //~^ ERROR explicit lifetime required in the type of `y` [E0621]
+}
+
+fn main() {
+    prove_static(lifetime_transmute_slice("", &String::from("foo")));
+    prove_static(lifetime_transmute_struct("", &String::from("bar")));
+}
diff --git a/src/test/ui/issues/issue-40288-2.stderr b/src/test/ui/issues/issue-40288-2.stderr
new file mode 100644
index 0000000..2c64856
--- /dev/null
+++ b/src/test/ui/issues/issue-40288-2.stderr
@@ -0,0 +1,21 @@
+error[E0621]: explicit lifetime required in the type of `y`
+  --> $DIR/issue-40288-2.rs:9:5
+   |
+LL | fn lifetime_transmute_slice<'a, T: ?Sized>(x: &'a T, y: &T) -> &'a T {
+   |                                                         -- help: add explicit lifetime `'a` to the type of `y`: `&'a T`
+...
+LL |     out[0]
+   |     ^^^^^^ lifetime `'a` required
+
+error[E0621]: explicit lifetime required in the type of `y`
+  --> $DIR/issue-40288-2.rs:24:5
+   |
+LL | fn lifetime_transmute_struct<'a, T: ?Sized>(x: &'a T, y: &T) -> &'a T {
+   |                                                          -- help: add explicit lifetime `'a` to the type of `y`: `&'a T`
+...
+LL |     out.head
+   |     ^^^^^^^^ lifetime `'a` required
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/issues/issue-40288.nll.stderr b/src/test/ui/issues/issue-40288.nll.stderr
new file mode 100644
index 0000000..fb4ecab
--- /dev/null
+++ b/src/test/ui/issues/issue-40288.nll.stderr
@@ -0,0 +1,15 @@
+error[E0506]: cannot assign to `*refr` because it is borrowed
+  --> $DIR/issue-40288.rs:16:5
+   |
+LL |     save_ref(&*refr, &mut out);
+   |              ------ borrow of `*refr` occurs here
+...
+LL |     *refr = 3;
+   |     ^^^^^^^^^ assignment to borrowed `*refr` occurs here
+...
+LL |     println!("{:?}", out[0]);
+   |                      ------ borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/issues/issue-40288.rs b/src/test/ui/issues/issue-40288.rs
new file mode 100644
index 0000000..60204c1
--- /dev/null
+++ b/src/test/ui/issues/issue-40288.rs
@@ -0,0 +1,20 @@
+fn save_ref<'a>(refr: &'a i32, to: &mut [&'a i32]) {
+    for val in &mut *to {
+        *val = refr;
+    }
+}
+
+fn main() {
+    let ref init = 0i32;
+    let ref mut refr = 1i32;
+
+    let mut out = [init];
+
+    save_ref(&*refr, &mut out);
+
+    // This shouldn't be allowed as `refr` is borrowed
+    *refr = 3; //~ ERROR cannot assign to `*refr` because it is borrowed
+
+    // Prints 3?!
+    println!("{:?}", out[0]);
+}
diff --git a/src/test/ui/issues/issue-40288.stderr b/src/test/ui/issues/issue-40288.stderr
new file mode 100644
index 0000000..5e8ad32
--- /dev/null
+++ b/src/test/ui/issues/issue-40288.stderr
@@ -0,0 +1,12 @@
+error[E0506]: cannot assign to `*refr` because it is borrowed
+  --> $DIR/issue-40288.rs:16:5
+   |
+LL |     save_ref(&*refr, &mut out);
+   |               ----- borrow of `*refr` occurs here
+...
+LL |     *refr = 3;
+   |     ^^^^^^^^^ assignment to borrowed `*refr` occurs here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/issues/issue-40350.rs b/src/test/ui/issues/issue-40350.rs
new file mode 100644
index 0000000..b2cc004
--- /dev/null
+++ b/src/test/ui/issues/issue-40350.rs
@@ -0,0 +1,13 @@
+// compile-pass
+// skip-codegen
+#![allow(warnings)]
+
+enum E {
+    A = {
+        enum F { B }
+        0
+    }
+}
+
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-40402-ref-hints/issue-40402-1.nll.stderr b/src/test/ui/issues/issue-40402-ref-hints/issue-40402-1.nll.stderr
new file mode 100644
index 0000000..fbfbc0c
--- /dev/null
+++ b/src/test/ui/issues/issue-40402-ref-hints/issue-40402-1.nll.stderr
@@ -0,0 +1,12 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/issue-40402-1.rs:9:13
+   |
+LL |     let e = f.v[0];
+   |             ^^^^^^
+   |             |
+   |             cannot move out of borrowed content
+   |             help: consider borrowing here: `&f.v[0]`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/issues/issue-40402-ref-hints/issue-40402-1.rs b/src/test/ui/issues/issue-40402-ref-hints/issue-40402-1.rs
new file mode 100644
index 0000000..6bb0b6f
--- /dev/null
+++ b/src/test/ui/issues/issue-40402-ref-hints/issue-40402-1.rs
@@ -0,0 +1,10 @@
+// Check that we do not suggest `ref f` here in the `main()` function.
+struct Foo {
+    pub v: Vec<String>,
+}
+
+fn main() {
+    let mut f = Foo { v: Vec::new() };
+    f.v.push("hello".to_string());
+    let e = f.v[0]; //~ ERROR cannot move out of indexed content
+}
diff --git a/src/test/ui/issues/issue-40402-ref-hints/issue-40402-1.stderr b/src/test/ui/issues/issue-40402-ref-hints/issue-40402-1.stderr
new file mode 100644
index 0000000..5e7be1a
--- /dev/null
+++ b/src/test/ui/issues/issue-40402-ref-hints/issue-40402-1.stderr
@@ -0,0 +1,12 @@
+error[E0507]: cannot move out of indexed content
+  --> $DIR/issue-40402-1.rs:9:13
+   |
+LL |     let e = f.v[0];
+   |             ^^^^^^
+   |             |
+   |             cannot move out of indexed content
+   |             help: consider using a reference instead: `&f.v[0]`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/issues/issue-40402-ref-hints/issue-40402-2.nll.stderr b/src/test/ui/issues/issue-40402-ref-hints/issue-40402-2.nll.stderr
new file mode 100644
index 0000000..0c4a85b
--- /dev/null
+++ b/src/test/ui/issues/issue-40402-ref-hints/issue-40402-2.nll.stderr
@@ -0,0 +1,20 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/issue-40402-2.rs:5:18
+   |
+LL |     let (a, b) = x[0];
+   |          -  -    ^^^^
+   |          |  |    |
+   |          |  |    cannot move out of borrowed content
+   |          |  |    help: consider borrowing here: `&x[0]`
+   |          |  ...and here
+   |          data moved here
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/issue-40402-2.rs:5:10
+   |
+LL |     let (a, b) = x[0];
+   |          ^  ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/issues/issue-40402-ref-hints/issue-40402-2.rs b/src/test/ui/issues/issue-40402-ref-hints/issue-40402-2.rs
new file mode 100644
index 0000000..0b8f40c
--- /dev/null
+++ b/src/test/ui/issues/issue-40402-ref-hints/issue-40402-2.rs
@@ -0,0 +1,6 @@
+// Check that we do suggest `(ref a, ref b)` here, since `a` and `b`
+// are nested within a pattern
+fn main() {
+    let x = vec![(String::new(), String::new())];
+    let (a, b) = x[0]; //~ ERROR cannot move out of indexed content
+}
diff --git a/src/test/ui/issues/issue-40402-ref-hints/issue-40402-2.stderr b/src/test/ui/issues/issue-40402-ref-hints/issue-40402-2.stderr
new file mode 100644
index 0000000..b672029
--- /dev/null
+++ b/src/test/ui/issues/issue-40402-ref-hints/issue-40402-2.stderr
@@ -0,0 +1,12 @@
+error[E0507]: cannot move out of indexed content
+  --> $DIR/issue-40402-2.rs:5:18
+   |
+LL |     let (a, b) = x[0];
+   |          -  -    ^^^^ cannot move out of indexed content
+   |          |  |
+   |          |  ...and here (use `ref b` or `ref mut b`)
+   |          hint: to prevent move, use `ref a` or `ref mut a`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/issues/issue-40510-1.nll.stderr b/src/test/ui/issues/issue-40510-1.nll.stderr
new file mode 100644
index 0000000..44234cb
--- /dev/null
+++ b/src/test/ui/issues/issue-40510-1.nll.stderr
@@ -0,0 +1,13 @@
+warning: captured variable cannot escape `FnMut` closure body
+  --> $DIR/issue-40510-1.rs:8:9
+   |
+LL |     || {
+   |      - inferred to be a `FnMut` closure
+LL |         &mut x
+   |         ^^^^^^ returns a reference to a captured variable which escapes the closure body
+   |
+   = note: `FnMut` closures only have access to their captured variables while they are executing...
+   = note: ...therefore, they cannot allow references to captured variables to escape
+   = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
+   = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+
diff --git a/src/test/ui/issues/issue-40510-1.rs b/src/test/ui/issues/issue-40510-1.rs
new file mode 100644
index 0000000..dd8a6bc
--- /dev/null
+++ b/src/test/ui/issues/issue-40510-1.rs
@@ -0,0 +1,13 @@
+// compile-pass
+#![allow(unused)]
+
+fn f() {
+    let mut x: Box<()> = Box::new(());
+
+    || {
+        &mut x
+    };
+}
+
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-40510-2.rs b/src/test/ui/issues/issue-40510-2.rs
new file mode 100644
index 0000000..2304bad
--- /dev/null
+++ b/src/test/ui/issues/issue-40510-2.rs
@@ -0,0 +1,13 @@
+// compile-pass
+#![allow(unused)]
+
+fn f() {
+    let x: Box<()> = Box::new(());
+
+    || {
+        &x
+    };
+}
+
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-40510-3.nll.stderr b/src/test/ui/issues/issue-40510-3.nll.stderr
new file mode 100644
index 0000000..1297e14
--- /dev/null
+++ b/src/test/ui/issues/issue-40510-3.nll.stderr
@@ -0,0 +1,15 @@
+warning: captured variable cannot escape `FnMut` closure body
+  --> $DIR/issue-40510-3.rs:8:9
+   |
+LL |       || {
+   |        - inferred to be a `FnMut` closure
+LL | /         || {
+LL | |             x.push(())
+LL | |         }
+   | |_________^ returns a closure that contains a reference to a captured variable, which then escapes the closure body
+   |
+   = note: `FnMut` closures only have access to their captured variables while they are executing...
+   = note: ...therefore, they cannot allow references to captured variables to escape
+   = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
+   = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+
diff --git a/src/test/ui/issues/issue-40510-3.rs b/src/test/ui/issues/issue-40510-3.rs
new file mode 100644
index 0000000..bc95c46
--- /dev/null
+++ b/src/test/ui/issues/issue-40510-3.rs
@@ -0,0 +1,15 @@
+// compile-pass
+#![allow(unused)]
+
+fn f() {
+    let mut x: Vec<()> = Vec::new();
+
+    || {
+        || {
+            x.push(())
+        }
+    };
+}
+
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-40510-4.rs b/src/test/ui/issues/issue-40510-4.rs
new file mode 100644
index 0000000..45cd4fd
--- /dev/null
+++ b/src/test/ui/issues/issue-40510-4.rs
@@ -0,0 +1,15 @@
+// compile-pass
+#![allow(unused)]
+
+fn f() {
+    let x: Vec<()> = Vec::new();
+
+    || {
+        || {
+            x.len()
+        }
+    };
+}
+
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-40610.rs b/src/test/ui/issues/issue-40610.rs
new file mode 100644
index 0000000..104cf7f
--- /dev/null
+++ b/src/test/ui/issues/issue-40610.rs
@@ -0,0 +1,6 @@
+fn f(_: &[f32]) {}
+
+fn main() {
+    () + f(&[1.0]);
+    //~^ ERROR binary operation `+` cannot be applied to type `()`
+}
diff --git a/src/test/ui/issues/issue-40610.stderr b/src/test/ui/issues/issue-40610.stderr
new file mode 100644
index 0000000..9d57759
--- /dev/null
+++ b/src/test/ui/issues/issue-40610.stderr
@@ -0,0 +1,13 @@
+error[E0369]: binary operation `+` cannot be applied to type `()`
+  --> $DIR/issue-40610.rs:4:8
+   |
+LL |     () + f(&[1.0]);
+   |     -- ^ --------- ()
+   |     |
+   |     ()
+   |
+   = note: an implementation of `std::ops::Add` might be missing for `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0369`.
diff --git a/src/test/ui/issues/issue-40749.rs b/src/test/ui/issues/issue-40749.rs
new file mode 100644
index 0000000..14908c3
--- /dev/null
+++ b/src/test/ui/issues/issue-40749.rs
@@ -0,0 +1,6 @@
+fn main() {
+    [0; ..10];
+    //~^ ERROR mismatched types
+    //~| expected type `usize`
+    //~| found type `std::ops::RangeTo<{integer}>`
+}
diff --git a/src/test/ui/issues/issue-40749.stderr b/src/test/ui/issues/issue-40749.stderr
new file mode 100644
index 0000000..be050d4
--- /dev/null
+++ b/src/test/ui/issues/issue-40749.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-40749.rs:2:9
+   |
+LL |     [0; ..10];
+   |         ^^^^ expected usize, found struct `std::ops::RangeTo`
+   |
+   = note: expected type `usize`
+              found type `std::ops::RangeTo<{integer}>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-40782.rs b/src/test/ui/issues/issue-40782.rs
new file mode 100644
index 0000000..55fec04
--- /dev/null
+++ b/src/test/ui/issues/issue-40782.rs
@@ -0,0 +1,5 @@
+fn main() {
+    for i 0..2 { //~ ERROR missing `in`
+    }
+}
+
diff --git a/src/test/ui/issues/issue-40782.stderr b/src/test/ui/issues/issue-40782.stderr
new file mode 100644
index 0000000..fdc5746
--- /dev/null
+++ b/src/test/ui/issues/issue-40782.stderr
@@ -0,0 +1,8 @@
+error: missing `in` in `for` loop
+  --> $DIR/issue-40782.rs:2:10
+   |
+LL |     for i 0..2 {
+   |          ^ help: try adding `in` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-40827.rs b/src/test/ui/issues/issue-40827.rs
new file mode 100644
index 0000000..6e42c506
--- /dev/null
+++ b/src/test/ui/issues/issue-40827.rs
@@ -0,0 +1,17 @@
+use std::rc::Rc;
+use std::sync::Arc;
+
+struct Foo(Arc<Bar>);
+
+enum Bar {
+    A(Rc<Foo>),
+    B(Option<Foo>),
+}
+
+fn f<T: Send>(_: T) {}
+
+fn main() {
+    f(Foo(Arc::new(Bar::B(None))));
+    //~^ ERROR E0277
+    //~| ERROR E0277
+}
diff --git a/src/test/ui/issues/issue-40827.stderr b/src/test/ui/issues/issue-40827.stderr
new file mode 100644
index 0000000..96b411b
--- /dev/null
+++ b/src/test/ui/issues/issue-40827.stderr
@@ -0,0 +1,35 @@
+error[E0277]: `std::rc::Rc<Foo>` cannot be sent between threads safely
+  --> $DIR/issue-40827.rs:14:5
+   |
+LL |     f(Foo(Arc::new(Bar::B(None))));
+   |     ^ `std::rc::Rc<Foo>` cannot be sent between threads safely
+   |
+   = help: within `Bar`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<Foo>`
+   = note: required because it appears within the type `Bar`
+   = note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Arc<Bar>`
+   = note: required because it appears within the type `Foo`
+note: required by `f`
+  --> $DIR/issue-40827.rs:11:1
+   |
+LL | fn f<T: Send>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: `std::rc::Rc<Foo>` cannot be shared between threads safely
+  --> $DIR/issue-40827.rs:14:5
+   |
+LL |     f(Foo(Arc::new(Bar::B(None))));
+   |     ^ `std::rc::Rc<Foo>` cannot be shared between threads safely
+   |
+   = help: within `Bar`, the trait `std::marker::Sync` is not implemented for `std::rc::Rc<Foo>`
+   = note: required because it appears within the type `Bar`
+   = note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Arc<Bar>`
+   = note: required because it appears within the type `Foo`
+note: required by `f`
+  --> $DIR/issue-40827.rs:11:1
+   |
+LL | fn f<T: Send>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-40845.rs b/src/test/ui/issues/issue-40845.rs
new file mode 100644
index 0000000..c9102f4
--- /dev/null
+++ b/src/test/ui/issues/issue-40845.rs
@@ -0,0 +1,6 @@
+trait T { m!(); } //~ ERROR cannot find macro `m!` in this scope
+
+struct S;
+impl S { m!(); } //~ ERROR cannot find macro `m!` in this scope
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-40845.stderr b/src/test/ui/issues/issue-40845.stderr
new file mode 100644
index 0000000..a8be38e
--- /dev/null
+++ b/src/test/ui/issues/issue-40845.stderr
@@ -0,0 +1,14 @@
+error: cannot find macro `m!` in this scope
+  --> $DIR/issue-40845.rs:4:10
+   |
+LL | impl S { m!(); }
+   |          ^
+
+error: cannot find macro `m!` in this scope
+  --> $DIR/issue-40845.rs:1:11
+   |
+LL | trait T { m!(); }
+   |           ^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/issues/issue-40861.rs b/src/test/ui/issues/issue-40861.rs
new file mode 100644
index 0000000..d8a8384
--- /dev/null
+++ b/src/test/ui/issues/issue-40861.rs
@@ -0,0 +1,6 @@
+fn f(_: &[f32]) {}
+
+fn main() {
+    ()[f(&[1.0])];
+    //~^ ERROR cannot index into a value of type `()`
+}
diff --git a/src/test/ui/issues/issue-40861.stderr b/src/test/ui/issues/issue-40861.stderr
new file mode 100644
index 0000000..84e38b9
--- /dev/null
+++ b/src/test/ui/issues/issue-40861.stderr
@@ -0,0 +1,11 @@
+error[E0608]: cannot index into a value of type `()`
+  --> $DIR/issue-40861.rs:4:5
+   |
+LL |     ()[f(&[1.0])];
+   |     ^^^^^^^^^^^^^
+   |
+   = help: to access tuple elements, use tuple indexing syntax (e.g., `tuple.0`)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0608`.
diff --git a/src/test/ui/issues/issue-40962.rs b/src/test/ui/issues/issue-40962.rs
new file mode 100644
index 0000000..50d9276
--- /dev/null
+++ b/src/test/ui/issues/issue-40962.rs
@@ -0,0 +1,11 @@
+// compile-pass
+macro_rules! m {
+    ($i:meta) => {
+        #[derive($i)]
+        struct S;
+    }
+}
+
+m!(Clone);
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-41139.nll.stderr b/src/test/ui/issues/issue-41139.nll.stderr
new file mode 100644
index 0000000..4dd017b
--- /dev/null
+++ b/src/test/ui/issues/issue-41139.nll.stderr
@@ -0,0 +1,9 @@
+error[E0161]: cannot move a value of type dyn Trait: the size of dyn Trait cannot be statically determined
+  --> $DIR/issue-41139.rs:6:23
+   |
+LL |     let t : &Trait = &get_function()();
+   |                       ^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0161`.
diff --git a/src/test/ui/issues/issue-41139.rs b/src/test/ui/issues/issue-41139.rs
new file mode 100644
index 0000000..0bfbea1
--- /dev/null
+++ b/src/test/ui/issues/issue-41139.rs
@@ -0,0 +1,8 @@
+trait Trait {}
+
+fn get_function<'a>() -> &'a Fn() -> Trait { panic!("") }
+
+fn main() {
+    let t : &Trait = &get_function()();
+    //~^ ERROR cannot move a value of type (dyn Trait + 'static)
+}
diff --git a/src/test/ui/issues/issue-41139.stderr b/src/test/ui/issues/issue-41139.stderr
new file mode 100644
index 0000000..3e3de7b
--- /dev/null
+++ b/src/test/ui/issues/issue-41139.stderr
@@ -0,0 +1,9 @@
+error[E0161]: cannot move a value of type (dyn Trait + 'static): the size of (dyn Trait + 'static) cannot be statically determined
+  --> $DIR/issue-41139.rs:6:23
+   |
+LL |     let t : &Trait = &get_function()();
+   |                       ^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0161`.
diff --git a/src/test/ui/issues/issue-41229-ref-str.rs b/src/test/ui/issues/issue-41229-ref-str.rs
new file mode 100644
index 0000000..fe5e6cd
--- /dev/null
+++ b/src/test/ui/issues/issue-41229-ref-str.rs
@@ -0,0 +1,4 @@
+pub fn example(ref s: str) {}
+//~^ ERROR the size for values of type
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-41229-ref-str.stderr b/src/test/ui/issues/issue-41229-ref-str.stderr
new file mode 100644
index 0000000..bcca911
--- /dev/null
+++ b/src/test/ui/issues/issue-41229-ref-str.stderr
@@ -0,0 +1,14 @@
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+  --> $DIR/issue-41229-ref-str.rs:1:28
+   |
+LL | pub fn example(ref s: str) {}
+   |                            ^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `str`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: all function arguments must have a statically known size
+   = help: unsized locals are gated as an unstable feature
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-41255.rs b/src/test/ui/issues/issue-41255.rs
new file mode 100644
index 0000000..395ab86
--- /dev/null
+++ b/src/test/ui/issues/issue-41255.rs
@@ -0,0 +1,40 @@
+// Matching against float literals should result in a linter error
+
+#![feature(exclusive_range_pattern)]
+#![allow(unused)]
+#![forbid(illegal_floating_point_literal_pattern)]
+
+fn main() {
+    let x = 42.0;
+    match x {
+        5.0 => {}, //~ ERROR floating-point types cannot be used in patterns
+                   //~| WARNING hard error
+        5.0f32 => {}, //~ ERROR floating-point types cannot be used in patterns
+                      //~| WARNING hard error
+        -5.0 => {}, //~ ERROR floating-point types cannot be used in patterns
+                    //~| WARNING hard error
+        1.0 .. 33.0 => {}, //~ ERROR floating-point types cannot be used in patterns
+                           //~| WARNING hard error
+                           //~| ERROR floating-point types cannot be used in patterns
+                           //~| WARNING hard error
+        39.0 ..= 70.0 => {}, //~ ERROR floating-point types cannot be used in patterns
+                             //~| WARNING hard error
+                             //~| ERROR floating-point types cannot be used in patterns
+                             //~| WARNING hard error
+        _ => {},
+    };
+    let y = 5.0;
+    // Same for tuples
+    match (x, 5) {
+        (3.14, 1) => {}, //~ ERROR floating-point types cannot be used
+                         //~| WARNING hard error
+        _ => {},
+    }
+    // Or structs
+    struct Foo { x: f32 };
+    match (Foo { x }) {
+        Foo { x: 2.0 } => {}, //~ ERROR floating-point types cannot be used
+                              //~| WARNING hard error
+        _ => {},
+    }
+}
diff --git a/src/test/ui/issues/issue-41255.stderr b/src/test/ui/issues/issue-41255.stderr
new file mode 100644
index 0000000..9ccfc9a
--- /dev/null
+++ b/src/test/ui/issues/issue-41255.stderr
@@ -0,0 +1,88 @@
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-41255.rs:10:9
+   |
+LL |         5.0 => {},
+   |         ^^^
+   |
+note: lint level defined here
+  --> $DIR/issue-41255.rs:5:11
+   |
+LL | #![forbid(illegal_floating_point_literal_pattern)]
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-41255.rs:12:9
+   |
+LL |         5.0f32 => {},
+   |         ^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-41255.rs:14:10
+   |
+LL |         -5.0 => {},
+   |          ^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-41255.rs:16:9
+   |
+LL |         1.0 .. 33.0 => {},
+   |         ^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-41255.rs:16:16
+   |
+LL |         1.0 .. 33.0 => {},
+   |                ^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-41255.rs:20:9
+   |
+LL |         39.0 ..= 70.0 => {},
+   |         ^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-41255.rs:20:18
+   |
+LL |         39.0 ..= 70.0 => {},
+   |                  ^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-41255.rs:29:10
+   |
+LL |         (3.14, 1) => {},
+   |          ^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-41255.rs:36:18
+   |
+LL |         Foo { x: 2.0 } => {},
+   |                  ^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: aborting due to 9 previous errors
+
diff --git a/src/test/ui/issues/issue-41272.rs b/src/test/ui/issues/issue-41272.rs
new file mode 100644
index 0000000..4a43e11
--- /dev/null
+++ b/src/test/ui/issues/issue-41272.rs
@@ -0,0 +1,21 @@
+// compile-pass
+#![allow(dead_code)]
+struct Foo;
+
+impl Foo {
+    fn bar(&mut self) -> bool { true }
+}
+
+fn error(foo: &mut Foo) {
+    if let Some(_) = Some(true) {
+    } else if foo.bar() {}
+}
+
+fn ok(foo: &mut Foo) {
+    if let Some(_) = Some(true) {
+    } else {
+        if foo.bar() {}
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-41298.rs b/src/test/ui/issues/issue-41298.rs
new file mode 100644
index 0000000..e8eeaba
--- /dev/null
+++ b/src/test/ui/issues/issue-41298.rs
@@ -0,0 +1,8 @@
+// compile-pass
+#![allow(dead_code)]
+struct Function<T, F> { t: T, f: F }
+
+impl<T, R> Function<T, fn() -> R> { fn foo() { } }
+impl<T, R> Function<T, fn() -> R> { fn bar() { } }
+
+fn main() { }
diff --git a/src/test/ui/issues/issue-41394.rs b/src/test/ui/issues/issue-41394.rs
new file mode 100644
index 0000000..45318f6
--- /dev/null
+++ b/src/test/ui/issues/issue-41394.rs
@@ -0,0 +1,11 @@
+enum Foo {
+    A = "" + 1
+    //~^ ERROR binary operation `+` cannot be applied to type `&str`
+}
+
+enum Bar {
+    A = Foo::A as isize
+    //~^ ERROR evaluation of constant value failed
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-41394.stderr b/src/test/ui/issues/issue-41394.stderr
new file mode 100644
index 0000000..5de5889
--- /dev/null
+++ b/src/test/ui/issues/issue-41394.stderr
@@ -0,0 +1,20 @@
+error[E0369]: binary operation `+` cannot be applied to type `&str`
+  --> $DIR/issue-41394.rs:2:12
+   |
+LL |     A = "" + 1
+   |         -- ^ - {integer}
+   |         |
+   |         &str
+   |
+   = note: an implementation of `std::ops::Add` might be missing for `&str`
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/issue-41394.rs:7:9
+   |
+LL |     A = Foo::A as isize
+   |         ^^^^^^^^^^^^^^^ referenced constant has errors
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0080, E0369.
+For more information about an error, try `rustc --explain E0080`.
diff --git a/src/test/ui/issues/issue-41549.rs b/src/test/ui/issues/issue-41549.rs
new file mode 100644
index 0000000..d19926a
--- /dev/null
+++ b/src/test/ui/issues/issue-41549.rs
@@ -0,0 +1,12 @@
+// aux-build:issue-41549.rs
+
+
+extern crate issue_41549;
+
+struct S;
+
+impl issue_41549::Trait for S {
+    const CONST: () = (); //~ ERROR incompatible type for trait
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-41549.stderr b/src/test/ui/issues/issue-41549.stderr
new file mode 100644
index 0000000..5e102dc
--- /dev/null
+++ b/src/test/ui/issues/issue-41549.stderr
@@ -0,0 +1,12 @@
+error[E0326]: implemented const `CONST` has an incompatible type for trait
+  --> $DIR/issue-41549.rs:9:18
+   |
+LL |     const CONST: () = ();
+   |                  ^^ expected u32, found ()
+   |
+   = note: expected type `u32`
+              found type `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0326`.
diff --git a/src/test/ui/issues/issue-41628.rs b/src/test/ui/issues/issue-41628.rs
new file mode 100644
index 0000000..b837a1e
--- /dev/null
+++ b/src/test/ui/issues/issue-41628.rs
@@ -0,0 +1,7 @@
+// compile-pass
+#![deny(dead_code)]
+
+#[used]
+static FOO: u32 = 0;
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-41652/auxiliary/issue-41652-b.rs b/src/test/ui/issues/issue-41652/auxiliary/issue-41652-b.rs
new file mode 100644
index 0000000..2ce21b0
--- /dev/null
+++ b/src/test/ui/issues/issue-41652/auxiliary/issue-41652-b.rs
@@ -0,0 +1,6 @@
+pub trait Tr {
+    // Note: The function needs to be declared over multiple lines to reproduce
+    // the crash. DO NOT reformat.
+    fn f()
+        where Self: Sized;
+}
diff --git a/src/test/ui/issues/issue-41652/issue-41652.rs b/src/test/ui/issues/issue-41652/issue-41652.rs
new file mode 100644
index 0000000..d8a6f4c
--- /dev/null
+++ b/src/test/ui/issues/issue-41652/issue-41652.rs
@@ -0,0 +1,14 @@
+// aux-build:issue-41652-b.rs
+
+extern crate issue_41652_b;
+
+struct S;
+
+impl issue_41652_b::Tr for S {
+    fn f() {
+        3.f()
+        //~^ ERROR can't call method `f` on ambiguous numeric type `{integer}`
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-41652/issue-41652.stderr b/src/test/ui/issues/issue-41652/issue-41652.stderr
new file mode 100644
index 0000000..3c71536
--- /dev/null
+++ b/src/test/ui/issues/issue-41652/issue-41652.stderr
@@ -0,0 +1,13 @@
+error[E0689]: can't call method `f` on ambiguous numeric type `{integer}`
+  --> $DIR/issue-41652.rs:9:11
+   |
+LL |         3.f()
+   |           ^
+help: you must specify a concrete type for this numeric value, like `i32`
+   |
+LL |         3_i32.f()
+   |         ^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0689`.
diff --git a/src/test/ui/issues/issue-41726.nll.stderr b/src/test/ui/issues/issue-41726.nll.stderr
new file mode 100644
index 0000000..c92753d
--- /dev/null
+++ b/src/test/ui/issues/issue-41726.nll.stderr
@@ -0,0 +1,11 @@
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/issue-41726.rs:5:9
+   |
+LL |         things[src.as_str()].sort();
+   |         ^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable
+   |
+   = help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `std::collections::HashMap<std::string::String, std::vec::Vec<std::string::String>>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/issues/issue-41726.rs b/src/test/ui/issues/issue-41726.rs
new file mode 100644
index 0000000..41dcaa8
--- /dev/null
+++ b/src/test/ui/issues/issue-41726.rs
@@ -0,0 +1,7 @@
+use std::collections::HashMap;
+fn main() {
+    let things: HashMap<String, Vec<String>> = HashMap::new();
+    for src in things.keys() {
+        things[src.as_str()].sort(); //~ ERROR cannot borrow immutable
+    }
+}
diff --git a/src/test/ui/issues/issue-41726.stderr b/src/test/ui/issues/issue-41726.stderr
new file mode 100644
index 0000000..e29c163
--- /dev/null
+++ b/src/test/ui/issues/issue-41726.stderr
@@ -0,0 +1,11 @@
+error[E0596]: cannot borrow immutable indexed content as mutable
+  --> $DIR/issue-41726.rs:5:9
+   |
+LL |         things[src.as_str()].sort();
+   |         ^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable
+   |
+   = help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `std::collections::HashMap<std::string::String, std::vec::Vec<std::string::String>>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/issues/issue-41742.rs b/src/test/ui/issues/issue-41742.rs
new file mode 100644
index 0000000..afe311b
--- /dev/null
+++ b/src/test/ui/issues/issue-41742.rs
@@ -0,0 +1,25 @@
+use std::ops::{Index, IndexMut};
+
+struct S;
+struct H;
+
+impl S {
+    fn f(&mut self) {}
+}
+
+impl Index<u32> for H {
+    type Output = S;
+    fn index(&self, index: u32) -> &S {
+        unimplemented!()
+    }
+}
+
+impl IndexMut<u32> for H {
+    fn index_mut(&mut self, index: u32) -> &mut S {
+        unimplemented!()
+    }
+}
+
+fn main() {
+    H["?"].f(); //~ ERROR mismatched types
+}
diff --git a/src/test/ui/issues/issue-41742.stderr b/src/test/ui/issues/issue-41742.stderr
new file mode 100644
index 0000000..f205abf
--- /dev/null
+++ b/src/test/ui/issues/issue-41742.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-41742.rs:24:7
+   |
+LL |     H["?"].f();
+   |       ^^^ expected u32, found reference
+   |
+   = note: expected type `u32`
+              found type `&'static str`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-41776.rs b/src/test/ui/issues/issue-41776.rs
new file mode 100644
index 0000000..24696d8
--- /dev/null
+++ b/src/test/ui/issues/issue-41776.rs
@@ -0,0 +1,3 @@
+fn main() {
+    include!(line!()); //~ ERROR argument must be a string literal
+}
diff --git a/src/test/ui/issues/issue-41776.stderr b/src/test/ui/issues/issue-41776.stderr
new file mode 100644
index 0000000..e06873b
--- /dev/null
+++ b/src/test/ui/issues/issue-41776.stderr
@@ -0,0 +1,8 @@
+error: argument must be a string literal
+  --> $DIR/issue-41776.rs:2:14
+   |
+LL |     include!(line!());
+   |              ^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-41880.rs b/src/test/ui/issues/issue-41880.rs
new file mode 100644
index 0000000..16facc5
--- /dev/null
+++ b/src/test/ui/issues/issue-41880.rs
@@ -0,0 +1,29 @@
+fn iterate<T, F>(initial: T, f: F) -> Iterate<T, F> {
+    Iterate {
+        state: initial,
+        f: f,
+    }
+}
+
+pub struct Iterate<T, F> {
+    state: T,
+    f: F
+}
+
+impl<T: Clone, F> Iterator for Iterate<T, F> where F: Fn(&T) -> T {
+    type Item = T;
+
+    #[inline]
+    fn next(&mut self) -> Option<Self::Item> {
+        self.state = (self.f)(&self.state);
+        Some(self.state.clone())
+    }
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) { (std::usize::MAX, None) }
+}
+
+fn main() {
+    let a = iterate(0, |x| x+1);
+    println!("{:?}", a.iter().take(10).collect::<Vec<usize>>());
+    //~^ ERROR no method named `iter` found for type `Iterate<{integer}
+}
diff --git a/src/test/ui/issues/issue-41880.stderr b/src/test/ui/issues/issue-41880.stderr
new file mode 100644
index 0000000..359a234
--- /dev/null
+++ b/src/test/ui/issues/issue-41880.stderr
@@ -0,0 +1,12 @@
+error[E0599]: no method named `iter` found for type `Iterate<{integer}, [closure@$DIR/issue-41880.rs:26:24: 26:31]>` in the current scope
+  --> $DIR/issue-41880.rs:27:24
+   |
+LL | pub struct Iterate<T, F> {
+   | ------------------------ method `iter` not found for this
+...
+LL |     println!("{:?}", a.iter().take(10).collect::<Vec<usize>>());
+   |                        ^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/issues/issue-41936-variance-coerce-unsized-cycle.rs b/src/test/ui/issues/issue-41936-variance-coerce-unsized-cycle.rs
new file mode 100644
index 0000000..4dddc48
--- /dev/null
+++ b/src/test/ui/issues/issue-41936-variance-coerce-unsized-cycle.rs
@@ -0,0 +1,30 @@
+// compile-pass
+#![allow(dead_code)]
+// Regression test for #41936. The coerce-unsized trait check in
+// coherence was using subtyping, which triggered variance
+// computation, which failed because it required type info for fields
+// that had not (yet) been computed.
+
+#![feature(unsize)]
+#![feature(coerce_unsized)]
+
+use std::{marker,ops};
+
+// Change the array to a non-array, and error disappears
+// Adding a new field to the end keeps the error
+struct LogDataBuf([u8;8]);
+
+struct Aref<T: ?Sized>
+{
+    // Inner structure triggers the error, removing the inner removes the message.
+    ptr: Box<ArefInner<T>>,
+}
+impl<T: ?Sized + marker::Unsize<U>, U: ?Sized> ops::CoerceUnsized<Aref<U>> for Aref<T> {}
+
+struct ArefInner<T: ?Sized>
+{
+    // Even with this field commented out, the error is raised.
+    data: T,
+}
+
+fn main(){}
diff --git a/src/test/ui/issues/issue-41974.rs b/src/test/ui/issues/issue-41974.rs
new file mode 100644
index 0000000..7875b43
--- /dev/null
+++ b/src/test/ui/issues/issue-41974.rs
@@ -0,0 +1,14 @@
+#[derive(Copy, Clone)]
+struct Flags;
+
+trait A {
+}
+
+impl<T> Drop for T where T: A { //~ ERROR E0119
+                                //~^ ERROR E0120
+                                //~| ERROR E0210
+    fn drop(&mut self) {
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-41974.stderr b/src/test/ui/issues/issue-41974.stderr
new file mode 100644
index 0000000..54fa48e
--- /dev/null
+++ b/src/test/ui/issues/issue-41974.stderr
@@ -0,0 +1,29 @@
+error[E0119]: conflicting implementations of trait `std::ops::Drop` for type `std::boxed::Box<_>`:
+  --> $DIR/issue-41974.rs:7:1
+   |
+LL | impl<T> Drop for T where T: A {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: conflicting implementation in crate `alloc`:
+           - impl<T> std::ops::Drop for std::boxed::Box<T>
+             where T: ?Sized;
+   = note: downstream crates may implement trait `A` for type `std::boxed::Box<_>`
+
+error[E0120]: the Drop trait may only be implemented on structures
+  --> $DIR/issue-41974.rs:7:18
+   |
+LL | impl<T> Drop for T where T: A {
+   |                  ^ implementing Drop requires a struct
+
+error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
+  --> $DIR/issue-41974.rs:7:1
+   |
+LL | impl<T> Drop for T where T: A {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type
+   |
+   = note: only traits defined in the current crate can be implemented for a type parameter
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0119, E0120, E0210.
+For more information about an error, try `rustc --explain E0119`.
diff --git a/src/test/ui/issues/issue-41998.rs b/src/test/ui/issues/issue-41998.rs
new file mode 100644
index 0000000..e54bc20
--- /dev/null
+++ b/src/test/ui/issues/issue-41998.rs
@@ -0,0 +1,10 @@
+// compile-pass
+
+
+fn main() {
+    if ('x' as char) < ('y' as char) {
+        print!("x");
+    } else {
+        print!("y");
+    }
+}
diff --git a/src/test/ui/issues/issue-4201.rs b/src/test/ui/issues/issue-4201.rs
new file mode 100644
index 0000000..2f1d6d2
--- /dev/null
+++ b/src/test/ui/issues/issue-4201.rs
@@ -0,0 +1,11 @@
+fn main() {
+    let a = if true {
+        0
+    } else if false {
+//~^ ERROR if may be missing an else clause
+//~| expected type `()`
+//~| found type `{integer}`
+//~| expected (), found integer
+        1
+    };
+}
diff --git a/src/test/ui/issues/issue-4201.stderr b/src/test/ui/issues/issue-4201.stderr
new file mode 100644
index 0000000..dd76fae
--- /dev/null
+++ b/src/test/ui/issues/issue-4201.stderr
@@ -0,0 +1,22 @@
+error[E0317]: if may be missing an else clause
+  --> $DIR/issue-4201.rs:4:12
+   |
+LL |       } else if false {
+   |  ____________^
+LL | |
+LL | |
+LL | |
+LL | |
+LL | |         1
+   | |         - found here
+LL | |     };
+   | |_____^ expected (), found integer
+   |
+   = note: expected type `()`
+              found type `{integer}`
+   = note: `if` expressions without `else` evaluate to `()`
+   = help: consider adding an `else` block that evaluates to the expected type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0317`.
diff --git a/src/test/ui/issues/issue-42060.rs b/src/test/ui/issues/issue-42060.rs
new file mode 100644
index 0000000..da7c030
--- /dev/null
+++ b/src/test/ui/issues/issue-42060.rs
@@ -0,0 +1,12 @@
+fn main() {
+    let thing = ();
+    let other: typeof(thing) = thing; //~ ERROR attempt to use a non-constant value in a constant
+    //~^ ERROR `typeof` is a reserved keyword but unimplemented [E0516]
+}
+
+fn f(){
+    let q = 1;
+    <typeof(q)>::N //~ ERROR attempt to use a non-constant value in a constant
+    //~^ ERROR `typeof` is a reserved keyword but unimplemented [E0516]
+}
+
diff --git a/src/test/ui/issues/issue-42060.stderr b/src/test/ui/issues/issue-42060.stderr
new file mode 100644
index 0000000..6f42c86
--- /dev/null
+++ b/src/test/ui/issues/issue-42060.stderr
@@ -0,0 +1,28 @@
+error[E0435]: attempt to use a non-constant value in a constant
+  --> $DIR/issue-42060.rs:3:23
+   |
+LL |     let other: typeof(thing) = thing;
+   |                       ^^^^^ non-constant value
+
+error[E0435]: attempt to use a non-constant value in a constant
+  --> $DIR/issue-42060.rs:9:13
+   |
+LL |     <typeof(q)>::N
+   |             ^ non-constant value
+
+error[E0516]: `typeof` is a reserved keyword but unimplemented
+  --> $DIR/issue-42060.rs:3:16
+   |
+LL |     let other: typeof(thing) = thing;
+   |                ^^^^^^^^^^^^^ reserved keyword
+
+error[E0516]: `typeof` is a reserved keyword but unimplemented
+  --> $DIR/issue-42060.rs:9:6
+   |
+LL |     <typeof(q)>::N
+   |      ^^^^^^^^^ reserved keyword
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0435, E0516.
+For more information about an error, try `rustc --explain E0435`.
diff --git a/src/test/ui/issues/issue-42106.nll.stderr b/src/test/ui/issues/issue-42106.nll.stderr
new file mode 100644
index 0000000..d5a9d23
--- /dev/null
+++ b/src/test/ui/issues/issue-42106.nll.stderr
@@ -0,0 +1,13 @@
+error[E0502]: cannot borrow `*collection` as mutable because it is also borrowed as immutable
+  --> $DIR/issue-42106.rs:3:5
+   |
+LL |     let _a = &collection;
+   |              ----------- immutable borrow occurs here
+LL |     collection.swap(1, 2);
+   |     ^^^^^^^^^^ mutable borrow occurs here
+LL |     _a.use_ref();
+   |     -- immutable borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/issues/issue-42106.rs b/src/test/ui/issues/issue-42106.rs
new file mode 100644
index 0000000..5e68869
--- /dev/null
+++ b/src/test/ui/issues/issue-42106.rs
@@ -0,0 +1,10 @@
+fn do_something<T>(collection: &mut Vec<T>) {
+    let _a = &collection;
+    collection.swap(1, 2); //~ ERROR also borrowed as immutable
+    _a.use_ref();
+}
+
+fn main() { }
+
+trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { }  }
+impl<T> Fake for T { }
diff --git a/src/test/ui/issues/issue-42106.stderr b/src/test/ui/issues/issue-42106.stderr
new file mode 100644
index 0000000..9e3ce98
--- /dev/null
+++ b/src/test/ui/issues/issue-42106.stderr
@@ -0,0 +1,14 @@
+error[E0502]: cannot borrow `*collection` as mutable because `collection` is also borrowed as immutable
+  --> $DIR/issue-42106.rs:3:5
+   |
+LL |     let _a = &collection;
+   |               ---------- immutable borrow occurs here
+LL |     collection.swap(1, 2);
+   |     ^^^^^^^^^^ mutable borrow occurs here
+LL |     _a.use_ref();
+LL | }
+   | - immutable borrow ends here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/issues/issue-42312.rs b/src/test/ui/issues/issue-42312.rs
new file mode 100644
index 0000000..b1c651f
--- /dev/null
+++ b/src/test/ui/issues/issue-42312.rs
@@ -0,0 +1,11 @@
+use std::ops::Deref;
+
+pub trait Foo {
+    fn baz(_: Self::Target) where Self: Deref {}
+    //~^ ERROR the size for values of type
+}
+
+pub fn f(_: ToString) {}
+//~^ ERROR the size for values of type
+
+fn main() { }
diff --git a/src/test/ui/issues/issue-42312.stderr b/src/test/ui/issues/issue-42312.stderr
new file mode 100644
index 0000000..20c8d08
--- /dev/null
+++ b/src/test/ui/issues/issue-42312.stderr
@@ -0,0 +1,26 @@
+error[E0277]: the size for values of type `<Self as std::ops::Deref>::Target` cannot be known at compilation time
+  --> $DIR/issue-42312.rs:4:29
+   |
+LL |     fn baz(_: Self::Target) where Self: Deref {}
+   |                             ^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `<Self as std::ops::Deref>::Target`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = help: consider adding a `where <Self as std::ops::Deref>::Target: std::marker::Sized` bound
+   = note: all function arguments must have a statically known size
+   = help: unsized locals are gated as an unstable feature
+
+error[E0277]: the size for values of type `(dyn std::string::ToString + 'static)` cannot be known at compilation time
+  --> $DIR/issue-42312.rs:8:23
+   |
+LL | pub fn f(_: ToString) {}
+   |                       ^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `(dyn std::string::ToString + 'static)`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: all function arguments must have a statically known size
+   = help: unsized locals are gated as an unstable feature
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-42344.nll.stderr b/src/test/ui/issues/issue-42344.nll.stderr
new file mode 100644
index 0000000..5cffa1b
--- /dev/null
+++ b/src/test/ui/issues/issue-42344.nll.stderr
@@ -0,0 +1,9 @@
+error[E0596]: cannot borrow `*TAB[_]` as mutable, as `TAB` is an immutable static item
+  --> $DIR/issue-42344.rs:4:5
+   |
+LL |     TAB[0].iter_mut();
+   |     ^^^^^^ cannot borrow as mutable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/issues/issue-42344.rs b/src/test/ui/issues/issue-42344.rs
new file mode 100644
index 0000000..5f1bb4f
--- /dev/null
+++ b/src/test/ui/issues/issue-42344.rs
@@ -0,0 +1,7 @@
+static TAB: [&mut [u8]; 0] = [];
+
+pub unsafe fn test() {
+    TAB[0].iter_mut(); //~ ERROR cannot borrow data mutably in a `&` reference [E0389]
+}
+
+pub fn main() {}
diff --git a/src/test/ui/issues/issue-42344.stderr b/src/test/ui/issues/issue-42344.stderr
new file mode 100644
index 0000000..6bf26c2
--- /dev/null
+++ b/src/test/ui/issues/issue-42344.stderr
@@ -0,0 +1,9 @@
+error[E0389]: cannot borrow data mutably in a `&` reference
+  --> $DIR/issue-42344.rs:4:5
+   |
+LL |     TAB[0].iter_mut();
+   |     ^^^^^^ assignment into an immutable reference
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0389`.
diff --git a/src/test/ui/issues/issue-42467.rs b/src/test/ui/issues/issue-42467.rs
new file mode 100644
index 0000000..9ad515b
--- /dev/null
+++ b/src/test/ui/issues/issue-42467.rs
@@ -0,0 +1,24 @@
+// compile-pass
+#![allow(dead_code)]
+struct Foo<T>(T);
+
+struct IntoIter<T>(T);
+
+impl<'a, T: 'a> Iterator for IntoIter<T> {
+    type Item = ();
+
+    fn next(&mut self) -> Option<()> {
+        None
+    }
+}
+
+impl<T> IntoIterator for Foo<T> {
+    type Item = ();
+    type IntoIter = IntoIter<T>;
+
+    fn into_iter(self) -> IntoIter<T> {
+        IntoIter(self.0)
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-4265.rs b/src/test/ui/issues/issue-4265.rs
new file mode 100644
index 0000000..2596079
--- /dev/null
+++ b/src/test/ui/issues/issue-4265.rs
@@ -0,0 +1,14 @@
+struct Foo {
+      baz: usize
+}
+
+impl Foo {
+    fn bar() {
+        Foo { baz: 0 }.bar();
+    }
+
+    fn bar() { //~ ERROR duplicate definitions
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-4265.stderr b/src/test/ui/issues/issue-4265.stderr
new file mode 100644
index 0000000..4faf5d3
--- /dev/null
+++ b/src/test/ui/issues/issue-4265.stderr
@@ -0,0 +1,15 @@
+error[E0201]: duplicate definitions with name `bar`:
+  --> $DIR/issue-4265.rs:10:5
+   |
+LL | /     fn bar() {
+LL | |         Foo { baz: 0 }.bar();
+LL | |     }
+   | |_____- previous definition of `bar` here
+LL | 
+LL | /     fn bar() {
+LL | |     }
+   | |_____^ duplicate definition
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0201`.
diff --git a/src/test/ui/issues/issue-42755.rs b/src/test/ui/issues/issue-42755.rs
new file mode 100644
index 0000000..65796fc
--- /dev/null
+++ b/src/test/ui/issues/issue-42755.rs
@@ -0,0 +1,7 @@
+macro_rules! foo {
+    ($($p:vis)*) => {} //~ ERROR repetition matches empty token tree
+}
+
+foo!(a);
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-42755.stderr b/src/test/ui/issues/issue-42755.stderr
new file mode 100644
index 0000000..12047e2
--- /dev/null
+++ b/src/test/ui/issues/issue-42755.stderr
@@ -0,0 +1,8 @@
+error: repetition matches empty token tree
+  --> $DIR/issue-42755.rs:2:7
+   |
+LL |     ($($p:vis)*) => {}
+   |       ^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-42796.nll.stderr b/src/test/ui/issues/issue-42796.nll.stderr
new file mode 100644
index 0000000..d9dfbc9
--- /dev/null
+++ b/src/test/ui/issues/issue-42796.nll.stderr
@@ -0,0 +1,14 @@
+error[E0382]: borrow of moved value: `s`
+  --> $DIR/issue-42796.rs:18:20
+   |
+LL |     let s = "Hello!".to_owned();
+   |         - move occurs because `s` has type `std::string::String`, which does not implement the `Copy` trait
+LL |     let mut s_copy = s;
+   |                      - value moved here
+...
+LL |     println!("{}", s);
+   |                    ^ value borrowed here after move
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/issues/issue-42796.rs b/src/test/ui/issues/issue-42796.rs
new file mode 100644
index 0000000..98b9127
--- /dev/null
+++ b/src/test/ui/issues/issue-42796.rs
@@ -0,0 +1,19 @@
+pub trait Mirror<Smoke> {
+    type Image;
+}
+
+impl<T, Smoke> Mirror<Smoke> for T {
+    type Image = T;
+}
+
+pub fn poison<S>(victim: String) where <String as Mirror<S>>::Image: Copy {
+    loop { drop(victim); }
+}
+
+fn main() {
+    let s = "Hello!".to_owned();
+    let mut s_copy = s;
+    s_copy.push_str("World!");
+    "0wned!".to_owned();
+    println!("{}", s); //~ ERROR use of moved value
+}
diff --git a/src/test/ui/issues/issue-42796.stderr b/src/test/ui/issues/issue-42796.stderr
new file mode 100644
index 0000000..d180e64
--- /dev/null
+++ b/src/test/ui/issues/issue-42796.stderr
@@ -0,0 +1,14 @@
+error[E0382]: use of moved value: `s`
+  --> $DIR/issue-42796.rs:18:20
+   |
+LL |     let mut s_copy = s;
+   |         ---------- value moved here
+...
+LL |     println!("{}", s);
+   |                    ^ value used here after move
+   |
+   = note: move occurs because `s` has type `std::string::String`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/issues/issue-42880.rs b/src/test/ui/issues/issue-42880.rs
new file mode 100644
index 0000000..b61ba80
--- /dev/null
+++ b/src/test/ui/issues/issue-42880.rs
@@ -0,0 +1,8 @@
+type Value = String;
+
+fn main() {
+    let f = |&Value::String(_)| (); //~ ERROR no associated item named
+
+    let vec: Vec<Value> = Vec::new();
+    vec.last().map(f);
+}
diff --git a/src/test/ui/issues/issue-42880.stderr b/src/test/ui/issues/issue-42880.stderr
new file mode 100644
index 0000000..763bb9a
--- /dev/null
+++ b/src/test/ui/issues/issue-42880.stderr
@@ -0,0 +1,9 @@
+error[E0599]: no associated item named `String` found for type `std::string::String` in the current scope
+  --> $DIR/issue-42880.rs:4:22
+   |
+LL |     let f = |&Value::String(_)| ();
+   |                      ^^^^^^ associated item not found in `std::string::String`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/issues/issue-42944.rs b/src/test/ui/issues/issue-42944.rs
new file mode 100644
index 0000000..9d74667
--- /dev/null
+++ b/src/test/ui/issues/issue-42944.rs
@@ -0,0 +1,19 @@
+mod foo {
+    pub struct B(());
+}
+
+mod bar {
+    use foo::B;
+
+    fn foo() {
+        B(()); //~ ERROR expected function, found struct `B` [E0423]
+    }
+}
+
+mod baz {
+    fn foo() {
+        B(()); //~ ERROR cannot find function `B` in this scope [E0425]
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-42944.stderr b/src/test/ui/issues/issue-42944.stderr
new file mode 100644
index 0000000..0613be0
--- /dev/null
+++ b/src/test/ui/issues/issue-42944.stderr
@@ -0,0 +1,20 @@
+error[E0423]: expected function, found struct `B`
+  --> $DIR/issue-42944.rs:9:9
+   |
+LL |         B(());
+   |         ^ constructor is not visible here due to private fields
+
+error[E0425]: cannot find function `B` in this scope
+  --> $DIR/issue-42944.rs:15:9
+   |
+LL |         B(());
+   |         ^ not found in this scope
+help: possible candidate is found in another module, you can import it into scope
+   |
+LL |     use foo::B;
+   |
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0423, E0425.
+For more information about an error, try `rustc --explain E0423`.
diff --git a/src/test/ui/issues/issue-42954.fixed b/src/test/ui/issues/issue-42954.fixed
new file mode 100644
index 0000000..a73054c
--- /dev/null
+++ b/src/test/ui/issues/issue-42954.fixed
@@ -0,0 +1,14 @@
+// run-rustfix
+
+#![allow(unused_must_use, unused_comparisons)]
+
+macro_rules! is_plainly_printable {
+    ($i: ident) => {
+        ($i as u32) < 0 //~ `<` is interpreted as a start of generic arguments
+    };
+}
+
+fn main() {
+    let c = 'a';
+    is_plainly_printable!(c);
+}
diff --git a/src/test/ui/issues/issue-42954.rs b/src/test/ui/issues/issue-42954.rs
new file mode 100644
index 0000000..5f9b0e3
--- /dev/null
+++ b/src/test/ui/issues/issue-42954.rs
@@ -0,0 +1,14 @@
+// run-rustfix
+
+#![allow(unused_must_use, unused_comparisons)]
+
+macro_rules! is_plainly_printable {
+    ($i: ident) => {
+        $i as u32 < 0 //~ `<` is interpreted as a start of generic arguments
+    };
+}
+
+fn main() {
+    let c = 'a';
+    is_plainly_printable!(c);
+}
diff --git a/src/test/ui/issues/issue-42954.stderr b/src/test/ui/issues/issue-42954.stderr
new file mode 100644
index 0000000..8c35088
--- /dev/null
+++ b/src/test/ui/issues/issue-42954.stderr
@@ -0,0 +1,14 @@
+error: `<` is interpreted as a start of generic arguments for `u32`, not a comparison
+  --> $DIR/issue-42954.rs:7:19
+   |
+LL |         $i as u32 < 0
+   |         --------- ^ - interpreted as generic arguments
+   |         |         |
+   |         |         not interpreted as comparison
+   |         help: try comparing the cast value: `($i as u32)`
+...
+LL |     is_plainly_printable!(c);
+   |     ------------------------- in this macro invocation
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-42956.rs b/src/test/ui/issues/issue-42956.rs
new file mode 100644
index 0000000..34cb046
--- /dev/null
+++ b/src/test/ui/issues/issue-42956.rs
@@ -0,0 +1,26 @@
+// compile-pass
+#![allow(dead_code)]
+#![allow(stable_features)]
+#![feature(associated_consts)]
+
+impl A for i32 {
+    type Foo = u32;
+}
+impl B for u32 {
+    const BAR: i32 = 0;
+}
+
+trait A {
+    type Foo: B;
+}
+
+trait B {
+    const BAR: i32;
+}
+
+fn generic<T: A>() {
+    // This panics if the universal function call syntax is used as well
+    println!("{}", T::Foo::BAR);
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-43023.rs b/src/test/ui/issues/issue-43023.rs
new file mode 100644
index 0000000..072243d
--- /dev/null
+++ b/src/test/ui/issues/issue-43023.rs
@@ -0,0 +1,20 @@
+struct S;
+
+impl S {
+    #[derive(Debug)] //~ ERROR `derive` may only be applied to structs, enums and unions
+    fn f() {
+        file!();
+    }
+}
+
+trait Tr1 {
+    #[derive(Debug)] //~ ERROR `derive` may only be applied to structs, enums and unions
+    fn f();
+}
+
+trait Tr2 {
+    #[derive(Debug)] //~ ERROR `derive` may only be applied to structs, enums and unions
+    type F;
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-43023.stderr b/src/test/ui/issues/issue-43023.stderr
new file mode 100644
index 0000000..206a516
--- /dev/null
+++ b/src/test/ui/issues/issue-43023.stderr
@@ -0,0 +1,20 @@
+error: `derive` may only be applied to structs, enums and unions
+  --> $DIR/issue-43023.rs:4:5
+   |
+LL |     #[derive(Debug)]
+   |     ^^^^^^^^^^^^^^^^
+
+error: `derive` may only be applied to structs, enums and unions
+  --> $DIR/issue-43023.rs:11:5
+   |
+LL |     #[derive(Debug)]
+   |     ^^^^^^^^^^^^^^^^
+
+error: `derive` may only be applied to structs, enums and unions
+  --> $DIR/issue-43023.rs:16:5
+   |
+LL |     #[derive(Debug)]
+   |     ^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/issues/issue-43057.rs b/src/test/ui/issues/issue-43057.rs
new file mode 100644
index 0000000..3ed64bb
--- /dev/null
+++ b/src/test/ui/issues/issue-43057.rs
@@ -0,0 +1,14 @@
+// compile-pass
+#![allow(unused)]
+
+macro_rules! column {
+    ($i:ident) => {
+        $i
+    };
+}
+
+fn foo() -> ! {
+    panic!();
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-43105.rs b/src/test/ui/issues/issue-43105.rs
new file mode 100644
index 0000000..f61b65b
--- /dev/null
+++ b/src/test/ui/issues/issue-43105.rs
@@ -0,0 +1,13 @@
+fn xyz() -> u8 { 42 }
+
+const NUM: u8 = xyz();
+//~^ ERROR calls in constants are limited to constant functions, tuple structs and tuple variants
+//~| ERROR any use of this value will cause an error [const_err]
+
+fn main() {
+    match 1 {
+        NUM => unimplemented!(),
+        //~^ ERROR could not evaluate constant pattern
+        _ => unimplemented!(),
+    }
+}
diff --git a/src/test/ui/issues/issue-43105.stderr b/src/test/ui/issues/issue-43105.stderr
new file mode 100644
index 0000000..378fbe6d
--- /dev/null
+++ b/src/test/ui/issues/issue-43105.stderr
@@ -0,0 +1,25 @@
+error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
+  --> $DIR/issue-43105.rs:3:17
+   |
+LL | const NUM: u8 = xyz();
+   |                 ^^^^^
+
+error: any use of this value will cause an error
+  --> $DIR/issue-43105.rs:3:17
+   |
+LL | const NUM: u8 = xyz();
+   | ----------------^^^^^-
+   |                 |
+   |                 calling non-const function `xyz`
+   |
+   = note: #[deny(const_err)] on by default
+
+error: could not evaluate constant pattern
+  --> $DIR/issue-43105.rs:9:9
+   |
+LL |         NUM => unimplemented!(),
+   |         ^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0015`.
diff --git a/src/test/ui/issues/issue-43162.rs b/src/test/ui/issues/issue-43162.rs
new file mode 100644
index 0000000..782eb42
--- /dev/null
+++ b/src/test/ui/issues/issue-43162.rs
@@ -0,0 +1,8 @@
+fn foo() -> bool {
+    //~^ ERROR E0308
+    break true; //~ ERROR E0268
+}
+
+fn main() {
+    break {}; //~ ERROR E0268
+}
diff --git a/src/test/ui/issues/issue-43162.stderr b/src/test/ui/issues/issue-43162.stderr
new file mode 100644
index 0000000..d3ff900
--- /dev/null
+++ b/src/test/ui/issues/issue-43162.stderr
@@ -0,0 +1,30 @@
+error[E0268]: `break` outside of loop
+  --> $DIR/issue-43162.rs:3:5
+   |
+LL |     break true;
+   |     ^^^^^^^^^^ cannot break outside of a loop
+
+error[E0268]: `break` outside of loop
+  --> $DIR/issue-43162.rs:7:5
+   |
+LL |     break {};
+   |     ^^^^^^^^ cannot break outside of a loop
+
+error[E0308]: mismatched types
+  --> $DIR/issue-43162.rs:1:13
+   |
+LL | fn foo() -> bool {
+   |    ---      ^^^^ expected bool, found ()
+   |    |
+   |    this function's body doesn't return
+LL |
+LL |     break true;
+   |               - help: consider removing this semicolon
+   |
+   = note: expected type `bool`
+              found type `()`
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0268, E0308.
+For more information about an error, try `rustc --explain E0268`.
diff --git a/src/test/ui/issues/issue-43189.rs b/src/test/ui/issues/issue-43189.rs
new file mode 100644
index 0000000..f4f4dce
--- /dev/null
+++ b/src/test/ui/issues/issue-43189.rs
@@ -0,0 +1,12 @@
+// Issue 46112: An extern crate pub re-exporting libcore was causing
+// paths rooted from `std` to be misrendered in the diagnostic output.
+
+// ignore-windows
+// aux-build:xcrate-issue-43189-a.rs
+// aux-build:xcrate-issue-43189-b.rs
+
+extern crate xcrate_issue_43189_b;
+fn main() {
+    ().a();
+    //~^ ERROR no method named `a` found for type `()` in the current scope [E0599]
+}
diff --git a/src/test/ui/issues/issue-43189.stderr b/src/test/ui/issues/issue-43189.stderr
new file mode 100644
index 0000000..e364650
--- /dev/null
+++ b/src/test/ui/issues/issue-43189.stderr
@@ -0,0 +1,15 @@
+error[E0599]: no method named `a` found for type `()` in the current scope
+  --> $DIR/issue-43189.rs:10:8
+   |
+LL |     ().a();
+   |        ^
+   |
+   = help: items from traits can only be used if the trait is in scope
+help: the following trait is implemented but not in scope, perhaps add a `use` for it:
+   |
+LL | use xcrate_issue_43189_b::xcrate_issue_43189_a::A;
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/issues/issue-43196.rs b/src/test/ui/issues/issue-43196.rs
new file mode 100644
index 0000000..81e5205
--- /dev/null
+++ b/src/test/ui/issues/issue-43196.rs
@@ -0,0 +1,7 @@
+fn main() {
+    |
+}
+//~^ ERROR expected `|`, found `}`
+|
+//~^ ERROR expected item, found `|`
+
diff --git a/src/test/ui/issues/issue-43196.stderr b/src/test/ui/issues/issue-43196.stderr
new file mode 100644
index 0000000..32efe23
--- /dev/null
+++ b/src/test/ui/issues/issue-43196.stderr
@@ -0,0 +1,16 @@
+error: expected `|`, found `}`
+  --> $DIR/issue-43196.rs:3:1
+   |
+LL |     |
+   |      - expected `|` here
+LL | }
+   | ^ unexpected token
+
+error: expected item, found `|`
+  --> $DIR/issue-43196.rs:5:1
+   |
+LL | |
+   | ^ expected item
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/issues/issue-4321.rs b/src/test/ui/issues/issue-4321.rs
new file mode 100644
index 0000000..9715f2e
--- /dev/null
+++ b/src/test/ui/issues/issue-4321.rs
@@ -0,0 +1,8 @@
+fn main() {
+    let tup = (true, true);
+    println!("foo {:}", match tup { //~ ERROR non-exhaustive patterns: `(true, false)` not covered
+        (false, false) => "foo",
+        (false, true) => "bar",
+        (true, true) => "baz"
+    });
+}
diff --git a/src/test/ui/issues/issue-4321.stderr b/src/test/ui/issues/issue-4321.stderr
new file mode 100644
index 0000000..afb4fe7
--- /dev/null
+++ b/src/test/ui/issues/issue-4321.stderr
@@ -0,0 +1,11 @@
+error[E0004]: non-exhaustive patterns: `(true, false)` not covered
+  --> $DIR/issue-4321.rs:3:31
+   |
+LL |     println!("foo {:}", match tup {
+   |                               ^^^ pattern `(true, false)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/issues/issue-43250.rs b/src/test/ui/issues/issue-43250.rs
new file mode 100644
index 0000000..24d70d2
--- /dev/null
+++ b/src/test/ui/issues/issue-43250.rs
@@ -0,0 +1,13 @@
+fn main() {
+    let mut y;
+    const C: u32 = 0;
+    macro_rules! m {
+        ($a:expr) => {
+            let $a = 0;
+        }
+    }
+    m!(y);
+    //~^ ERROR arbitrary expressions aren't allowed in patterns
+    m!(C);
+    //~^ ERROR arbitrary expressions aren't allowed in patterns
+}
diff --git a/src/test/ui/issues/issue-43250.stderr b/src/test/ui/issues/issue-43250.stderr
new file mode 100644
index 0000000..f729c5c
--- /dev/null
+++ b/src/test/ui/issues/issue-43250.stderr
@@ -0,0 +1,14 @@
+error: arbitrary expressions aren't allowed in patterns
+  --> $DIR/issue-43250.rs:9:8
+   |
+LL |     m!(y);
+   |        ^
+
+error: arbitrary expressions aren't allowed in patterns
+  --> $DIR/issue-43250.rs:11:8
+   |
+LL |     m!(C);
+   |        ^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/issues/issue-4335.nll.stderr b/src/test/ui/issues/issue-4335.nll.stderr
new file mode 100644
index 0000000..5ac3bdb
--- /dev/null
+++ b/src/test/ui/issues/issue-4335.nll.stderr
@@ -0,0 +1,30 @@
+error[E0507]: cannot move out of captured variable in an `FnMut` closure
+  --> $DIR/issue-4335.rs:6:20
+   |
+LL | fn f<'r, T>(v: &'r T) -> Box<FnMut() -> T + 'r> {
+   |             - captured outer variable
+LL |     id(Box::new(|| *v))
+   |                    ^^ cannot move out of captured variable in an `FnMut` closure
+
+error[E0373]: closure may outlive the current function, but it borrows `v`, which is owned by the current function
+  --> $DIR/issue-4335.rs:6:17
+   |
+LL |     id(Box::new(|| *v))
+   |                 ^^  - `v` is borrowed here
+   |                 |
+   |                 may outlive borrowed value `v`
+   |
+note: closure is returned here
+  --> $DIR/issue-4335.rs:6:5
+   |
+LL |     id(Box::new(|| *v))
+   |     ^^^^^^^^^^^^^^^^^^^
+help: to force the closure to take ownership of `v` (and any other referenced variables), use the `move` keyword
+   |
+LL |     id(Box::new(move || *v))
+   |                 ^^^^^^^
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0373, E0507.
+For more information about an error, try `rustc --explain E0373`.
diff --git a/src/test/ui/issues/issue-4335.rs b/src/test/ui/issues/issue-4335.rs
new file mode 100644
index 0000000..d3c9954
--- /dev/null
+++ b/src/test/ui/issues/issue-4335.rs
@@ -0,0 +1,14 @@
+#![feature(fn_traits)]
+
+fn id<T>(t: T) -> T { t }
+
+fn f<'r, T>(v: &'r T) -> Box<FnMut() -> T + 'r> {
+    id(Box::new(|| *v))
+        //~^ ERROR E0373
+        //~| ERROR E0507
+}
+
+fn main() {
+    let v = &5;
+    println!("{}", f(v).call_mut(()));
+}
diff --git a/src/test/ui/issues/issue-4335.stderr b/src/test/ui/issues/issue-4335.stderr
new file mode 100644
index 0000000..9ef8e16
--- /dev/null
+++ b/src/test/ui/issues/issue-4335.stderr
@@ -0,0 +1,22 @@
+error[E0373]: closure may outlive the current function, but it borrows `v`, which is owned by the current function
+  --> $DIR/issue-4335.rs:6:17
+   |
+LL |     id(Box::new(|| *v))
+   |                 ^^  - `v` is borrowed here
+   |                 |
+   |                 may outlive borrowed value `v`
+help: to force the closure to take ownership of `v` (and any other referenced variables), use the `move` keyword
+   |
+LL |     id(Box::new(move || *v))
+   |                 ^^^^^^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/issue-4335.rs:6:20
+   |
+LL |     id(Box::new(|| *v))
+   |                    ^^ cannot move out of borrowed content
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0373, E0507.
+For more information about an error, try `rustc --explain E0373`.
diff --git a/src/test/ui/issues/issue-43355.rs b/src/test/ui/issues/issue-43355.rs
new file mode 100644
index 0000000..809300d
--- /dev/null
+++ b/src/test/ui/issues/issue-43355.rs
@@ -0,0 +1,20 @@
+pub trait Trait1<X> {
+    type Output;
+}
+
+pub trait Trait2<X> {}
+
+pub struct A;
+
+impl<X, T> Trait1<X> for T where T: Trait2<X> {
+    type Output = ();
+}
+
+impl<X> Trait1<Box<X>> for A {
+//~^ ERROR conflicting implementations of trait
+//~| hard error
+//~| downstream crates may implement trait `Trait2<std::boxed::Box<_>>` for type `A`
+    type Output = i32;
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-43355.stderr b/src/test/ui/issues/issue-43355.stderr
new file mode 100644
index 0000000..039f104
--- /dev/null
+++ b/src/test/ui/issues/issue-43355.stderr
@@ -0,0 +1,16 @@
+error: conflicting implementations of trait `Trait1<std::boxed::Box<_>>` for type `A`: (E0119)
+  --> $DIR/issue-43355.rs:13:1
+   |
+LL | impl<X, T> Trait1<X> for T where T: Trait2<X> {
+   | --------------------------------------------- first implementation here
+...
+LL | impl<X> Trait1<Box<X>> for A {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `A`
+   |
+   = note: #[deny(incoherent_fundamental_impls)] on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #46205 <https://github.com/rust-lang/rust/issues/46205>
+   = note: downstream crates may implement trait `Trait2<std::boxed::Box<_>>` for type `A`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-43357.rs b/src/test/ui/issues/issue-43357.rs
new file mode 100644
index 0000000..6b8e7de
--- /dev/null
+++ b/src/test/ui/issues/issue-43357.rs
@@ -0,0 +1,11 @@
+// compile-pass
+#![allow(dead_code)]
+trait Trait {
+    type Output;
+}
+
+fn f<T: Trait>() {
+    std::mem::size_of::<T::Output>();
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-43420-no-over-suggest.rs b/src/test/ui/issues/issue-43420-no-over-suggest.rs
new file mode 100644
index 0000000..4365bff
--- /dev/null
+++ b/src/test/ui/issues/issue-43420-no-over-suggest.rs
@@ -0,0 +1,9 @@
+// check that we substitute type parameters before we suggest anything - otherwise
+// we would suggest function such as `as_slice` for the `&[u16]`.
+
+fn foo(b: &[u16]) {}
+
+fn main() {
+    let a: Vec<u8> = Vec::new();
+    foo(&a); //~ ERROR mismatched types
+}
diff --git a/src/test/ui/issues/issue-43420-no-over-suggest.stderr b/src/test/ui/issues/issue-43420-no-over-suggest.stderr
new file mode 100644
index 0000000..7a3722e
--- /dev/null
+++ b/src/test/ui/issues/issue-43420-no-over-suggest.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-43420-no-over-suggest.rs:8:9
+   |
+LL |     foo(&a);
+   |         ^^ expected slice, found struct `std::vec::Vec`
+   |
+   = note: expected type `&[u16]`
+              found type `&std::vec::Vec<u8>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-43424.rs b/src/test/ui/issues/issue-43424.rs
new file mode 100644
index 0000000..b3f76d8
--- /dev/null
+++ b/src/test/ui/issues/issue-43424.rs
@@ -0,0 +1,12 @@
+#![allow(unused)]
+
+macro_rules! m {
+    ($attr_path: path) => {
+        #[$attr_path]
+        fn f() {}
+    }
+}
+
+m!(inline<u8>); //~ ERROR: unexpected generic arguments in path
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-43424.stderr b/src/test/ui/issues/issue-43424.stderr
new file mode 100644
index 0000000..6274a79
--- /dev/null
+++ b/src/test/ui/issues/issue-43424.stderr
@@ -0,0 +1,8 @@
+error: unexpected generic arguments in path
+  --> $DIR/issue-43424.rs:10:4
+   |
+LL | m!(inline<u8>);
+   |    ^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-43431.rs b/src/test/ui/issues/issue-43431.rs
new file mode 100644
index 0000000..e7ec351
--- /dev/null
+++ b/src/test/ui/issues/issue-43431.rs
@@ -0,0 +1,14 @@
+#![feature(fn_traits)]
+
+trait CallSingle<A, B> {
+    fn call(&self, a: A) -> B where Self: Sized, Self: Fn(A) -> B;
+}
+
+impl<A, B, F: Fn(A) -> B> CallSingle<A, B> for F {
+    fn call(&self, a: A) -> B {
+        <Self as Fn(A) -> B>::call(self, (a,))
+        //~^ ERROR associated type bindings are not allowed here
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-43431.stderr b/src/test/ui/issues/issue-43431.stderr
new file mode 100644
index 0000000..4edb528
--- /dev/null
+++ b/src/test/ui/issues/issue-43431.stderr
@@ -0,0 +1,9 @@
+error[E0229]: associated type bindings are not allowed here
+  --> $DIR/issue-43431.rs:9:27
+   |
+LL |         <Self as Fn(A) -> B>::call(self, (a,))
+   |                           ^ associated type not allowed here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0229`.
diff --git a/src/test/ui/issues/issue-43483.rs b/src/test/ui/issues/issue-43483.rs
new file mode 100644
index 0000000..a123ae4
--- /dev/null
+++ b/src/test/ui/issues/issue-43483.rs
@@ -0,0 +1,16 @@
+// compile-pass
+#![allow(dead_code)]
+#![allow(unused_variables)]
+trait VecN {
+    const DIM: usize;
+}
+
+trait Mat {
+    type Row: VecN;
+}
+
+fn m<M: Mat>() {
+    let x = M::Row::DIM;
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-4366-2.rs b/src/test/ui/issues/issue-4366-2.rs
new file mode 100644
index 0000000..c777b75
--- /dev/null
+++ b/src/test/ui/issues/issue-4366-2.rs
@@ -0,0 +1,26 @@
+// ensures that 'use foo:*' doesn't import non-public item
+
+use m1::*;
+
+mod foo {
+    pub fn foo() {}
+}
+mod a {
+    pub mod b {
+        use foo::foo;
+        type Bar = isize;
+    }
+    pub mod sub {
+        use a::b::*;
+        fn sub() -> Bar { 1 }
+        //~^ ERROR cannot find type `Bar` in this scope
+    }
+}
+
+mod m1 {
+    fn foo() {}
+}
+
+fn main() {
+    foo(); //~ ERROR expected function, found module `foo`
+}
diff --git a/src/test/ui/issues/issue-4366-2.stderr b/src/test/ui/issues/issue-4366-2.stderr
new file mode 100644
index 0000000..76f08d7
--- /dev/null
+++ b/src/test/ui/issues/issue-4366-2.stderr
@@ -0,0 +1,26 @@
+error[E0412]: cannot find type `Bar` in this scope
+  --> $DIR/issue-4366-2.rs:15:21
+   |
+LL |         fn sub() -> Bar { 1 }
+   |                     ^^^ not found in this scope
+help: possible candidate is found in another module, you can import it into scope
+   |
+LL |         use a::b::Bar;
+   |
+
+error[E0423]: expected function, found module `foo`
+  --> $DIR/issue-4366-2.rs:25:5
+   |
+LL |     foo();
+   |     ^^^ not a function
+help: possible better candidates are found in other modules, you can import them into scope
+   |
+LL | use foo::foo;
+   |
+LL | use m1::foo;
+   |
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0412, E0423.
+For more information about an error, try `rustc --explain E0412`.
diff --git a/src/test/ui/issues/issue-4366.rs b/src/test/ui/issues/issue-4366.rs
new file mode 100644
index 0000000..9ec2e58
--- /dev/null
+++ b/src/test/ui/issues/issue-4366.rs
@@ -0,0 +1,26 @@
+// regression test for issue 4366
+
+// ensures that 'use foo:*' doesn't import non-public 'use' statements in the
+// module 'foo'
+
+use m1::*;
+
+mod foo {
+    pub fn foo() {}
+}
+mod a {
+    pub mod b {
+        use foo::foo;
+        type Bar = isize;
+    }
+    pub mod sub {
+        use a::b::*;
+        fn sub() -> isize { foo(); 1 } //~ ERROR cannot find function `foo` in this scope
+    }
+}
+
+mod m1 {
+    fn foo() {}
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-4366.stderr b/src/test/ui/issues/issue-4366.stderr
new file mode 100644
index 0000000..c59ab00
--- /dev/null
+++ b/src/test/ui/issues/issue-4366.stderr
@@ -0,0 +1,15 @@
+error[E0425]: cannot find function `foo` in this scope
+  --> $DIR/issue-4366.rs:18:29
+   |
+LL |         fn sub() -> isize { foo(); 1 }
+   |                             ^^^ not found in this scope
+help: possible candidates are found in other modules, you can import them into scope
+   |
+LL |         use foo::foo;
+   |
+LL |         use m1::foo;
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/issues/issue-43733.rs b/src/test/ui/issues/issue-43733.rs
new file mode 100644
index 0000000..91192e3
--- /dev/null
+++ b/src/test/ui/issues/issue-43733.rs
@@ -0,0 +1,33 @@
+#![feature(const_fn)]
+#![feature(thread_local)]
+#![feature(cfg_target_thread_local, thread_local_internals)]
+
+type Foo = std::cell::RefCell<String>;
+
+#[cfg(target_thread_local)]
+#[thread_local]
+static __KEY: std::thread::__FastLocalKeyInner<Foo> =
+    std::thread::__FastLocalKeyInner::new();
+
+#[cfg(not(target_thread_local))]
+static __KEY: std::thread::__OsLocalKeyInner<Foo> =
+    std::thread::__OsLocalKeyInner::new();
+
+fn __getit() -> std::option::Option<
+    &'static std::cell::UnsafeCell<
+        std::option::Option<Foo>>>
+{
+    __KEY.get() //~ ERROR call to unsafe function is unsafe
+}
+
+static FOO: std::thread::LocalKey<Foo> =
+    std::thread::LocalKey::new(__getit, Default::default);
+//~^ ERROR call to unsafe function is unsafe
+
+fn main() {
+    FOO.with(|foo| println!("{}", foo.borrow()));
+    std::thread::spawn(|| {
+        FOO.with(|foo| *foo.borrow_mut() += "foo");
+    }).join().unwrap();
+    FOO.with(|foo| println!("{}", foo.borrow()));
+}
diff --git a/src/test/ui/issues/issue-43733.stderr b/src/test/ui/issues/issue-43733.stderr
new file mode 100644
index 0000000..c48f9ba
--- /dev/null
+++ b/src/test/ui/issues/issue-43733.stderr
@@ -0,0 +1,19 @@
+error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
+  --> $DIR/issue-43733.rs:20:5
+   |
+LL |     __KEY.get()
+   |     ^^^^^^^^^^^ call to unsafe function
+   |
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
+  --> $DIR/issue-43733.rs:24:5
+   |
+LL |     std::thread::LocalKey::new(__getit, Default::default);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/issues/issue-43784-associated-type.rs b/src/test/ui/issues/issue-43784-associated-type.rs
new file mode 100644
index 0000000..fb58ad6
--- /dev/null
+++ b/src/test/ui/issues/issue-43784-associated-type.rs
@@ -0,0 +1,17 @@
+pub trait Partial<X: ?Sized>: Copy {
+}
+
+pub trait Complete {
+    type Assoc: Partial<Self>;
+}
+
+impl<T> Partial<T> for T::Assoc where
+    T: Complete
+{
+}
+
+impl<T> Complete for T { //~ ERROR the trait bound `T: std::marker::Copy` is not satisfied
+    type Assoc = T;
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-43784-associated-type.stderr b/src/test/ui/issues/issue-43784-associated-type.stderr
new file mode 100644
index 0000000..fc05d28
--- /dev/null
+++ b/src/test/ui/issues/issue-43784-associated-type.stderr
@@ -0,0 +1,11 @@
+error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
+  --> $DIR/issue-43784-associated-type.rs:13:9
+   |
+LL | impl<T> Complete for T {
+   |         ^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
+   |
+   = help: consider adding a `where T: std::marker::Copy` bound
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-43784-supertrait.rs b/src/test/ui/issues/issue-43784-supertrait.rs
new file mode 100644
index 0000000..3c03433
--- /dev/null
+++ b/src/test/ui/issues/issue-43784-supertrait.rs
@@ -0,0 +1,10 @@
+pub trait Partial: Copy {
+}
+
+pub trait Complete: Partial {
+}
+
+impl<T> Partial for T where T: Complete {}
+impl<T> Complete for T {} //~ ERROR the trait bound `T: std::marker::Copy` is not satisfied
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-43784-supertrait.stderr b/src/test/ui/issues/issue-43784-supertrait.stderr
new file mode 100644
index 0000000..4c423f2
--- /dev/null
+++ b/src/test/ui/issues/issue-43784-supertrait.stderr
@@ -0,0 +1,11 @@
+error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
+  --> $DIR/issue-43784-supertrait.rs:8:9
+   |
+LL | impl<T> Complete for T {}
+   |         ^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
+   |
+   = help: consider adding a `where T: std::marker::Copy` bound
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-43806.rs b/src/test/ui/issues/issue-43806.rs
new file mode 100644
index 0000000..cbfbfa35
--- /dev/null
+++ b/src/test/ui/issues/issue-43806.rs
@@ -0,0 +1,23 @@
+// run-pass
+
+#![deny(unused_results)]
+
+enum Void {}
+
+fn foo() {}
+
+fn bar() -> ! {
+    loop {}
+}
+
+fn baz() -> Void {
+    loop {}
+}
+
+fn qux() {
+    foo();
+    bar();
+    baz();
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-43925.rs b/src/test/ui/issues/issue-43925.rs
new file mode 100644
index 0000000..1f3bee3
--- /dev/null
+++ b/src/test/ui/issues/issue-43925.rs
@@ -0,0 +1,4 @@
+#[link(name="foo", cfg("rlib"))] //~ ERROR invalid argument for `cfg(..)`
+extern {}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-43925.stderr b/src/test/ui/issues/issue-43925.stderr
new file mode 100644
index 0000000..739ace1
--- /dev/null
+++ b/src/test/ui/issues/issue-43925.stderr
@@ -0,0 +1,8 @@
+error: invalid argument for `cfg(..)`
+  --> $DIR/issue-43925.rs:1:24
+   |
+LL | #[link(name="foo", cfg("rlib"))]
+   |                        ^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-43926.rs b/src/test/ui/issues/issue-43926.rs
new file mode 100644
index 0000000..c56a796
--- /dev/null
+++ b/src/test/ui/issues/issue-43926.rs
@@ -0,0 +1,4 @@
+#[link(name="foo", cfg())] //~ ERROR `cfg()` must have an argument
+extern {}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-43926.stderr b/src/test/ui/issues/issue-43926.stderr
new file mode 100644
index 0000000..d9d6b3a
--- /dev/null
+++ b/src/test/ui/issues/issue-43926.stderr
@@ -0,0 +1,8 @@
+error: `cfg()` must have an argument
+  --> $DIR/issue-43926.rs:1:20
+   |
+LL | #[link(name="foo", cfg())]
+   |                    ^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-43988.rs b/src/test/ui/issues/issue-43988.rs
new file mode 100644
index 0000000..74667d7
--- /dev/null
+++ b/src/test/ui/issues/issue-43988.rs
@@ -0,0 +1,38 @@
+#![feature(stmt_expr_attributes)]
+
+fn main() {
+
+    #[inline]
+    let _a = 4;
+    //~^^ ERROR attribute should be applied to function or closure
+
+
+    #[inline(XYZ)]
+    let _b = 4;
+    //~^^ ERROR attribute should be applied to function or closure
+
+    #[repr(nothing)]
+    let _x = 0;
+    //~^^ ERROR attribute should not be applied to a statement
+
+    #[repr(something_not_real)]
+    loop {
+        ()
+    };
+    //~^^^^ ERROR attribute should not be applied to an expression
+
+    #[repr]
+    let _y = "123";
+    //~^^ ERROR attribute should not be applied to a statement
+    //~| ERROR attribute must be of the form
+
+    fn foo() {}
+
+    #[inline(ABC)]
+    foo();
+    //~^^ ERROR attribute should be applied to function or closure
+
+    let _z = #[repr] 1;
+    //~^ ERROR attribute should not be applied to an expression
+    //~| ERROR attribute must be of the form
+}
diff --git a/src/test/ui/issues/issue-43988.stderr b/src/test/ui/issues/issue-43988.stderr
new file mode 100644
index 0000000..6fe41a3
--- /dev/null
+++ b/src/test/ui/issues/issue-43988.stderr
@@ -0,0 +1,72 @@
+error: attribute must be of the form `#[repr(C, packed, ...)]`
+  --> $DIR/issue-43988.rs:24:5
+   |
+LL |     #[repr]
+   |     ^^^^^^^
+
+error: attribute must be of the form `#[repr(C, packed, ...)]`
+  --> $DIR/issue-43988.rs:35:14
+   |
+LL |     let _z = #[repr] 1;
+   |              ^^^^^^^
+
+error[E0518]: attribute should be applied to function or closure
+  --> $DIR/issue-43988.rs:5:5
+   |
+LL |     #[inline]
+   |     ^^^^^^^^^
+LL |     let _a = 4;
+   |     ----------- not a function or closure
+
+error[E0518]: attribute should be applied to function or closure
+  --> $DIR/issue-43988.rs:10:5
+   |
+LL |     #[inline(XYZ)]
+   |     ^^^^^^^^^^^^^^
+LL |     let _b = 4;
+   |     ----------- not a function or closure
+
+error[E0517]: attribute should not be applied to a statement
+  --> $DIR/issue-43988.rs:14:5
+   |
+LL |     #[repr(nothing)]
+   |     ^^^^^^^^^^^^^^^^
+LL |     let _x = 0;
+   |     ----------- not a struct, enum or union
+
+error[E0517]: attribute should not be applied to an expression
+  --> $DIR/issue-43988.rs:18:5
+   |
+LL |       #[repr(something_not_real)]
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | /     loop {
+LL | |         ()
+LL | |     };
+   | |_____- not defining a struct, enum or union
+
+error[E0517]: attribute should not be applied to a statement
+  --> $DIR/issue-43988.rs:24:5
+   |
+LL |     #[repr]
+   |     ^^^^^^^
+LL |     let _y = "123";
+   |     --------------- not a struct, enum or union
+
+error[E0518]: attribute should be applied to function or closure
+  --> $DIR/issue-43988.rs:31:5
+   |
+LL |     #[inline(ABC)]
+   |     ^^^^^^^^^^^^^^
+LL |     foo();
+   |     ----- not a function or closure
+
+error[E0517]: attribute should not be applied to an expression
+  --> $DIR/issue-43988.rs:35:14
+   |
+LL |     let _z = #[repr] 1;
+   |              ^^^^^^^ - not defining a struct, enum or union
+
+error: aborting due to 9 previous errors
+
+Some errors occurred: E0517, E0518.
+For more information about an error, try `rustc --explain E0517`.
diff --git a/src/test/ui/issues/issue-44005.rs b/src/test/ui/issues/issue-44005.rs
new file mode 100644
index 0000000..e2625fd
--- /dev/null
+++ b/src/test/ui/issues/issue-44005.rs
@@ -0,0 +1,30 @@
+// compile-pass
+pub trait Foo<'a> {
+    type Bar;
+    fn foo(&'a self) -> Self::Bar;
+}
+
+impl<'a, 'b, T: 'a> Foo<'a> for &'b T {
+    type Bar = &'a T;
+    fn foo(&'a self) -> &'a T {
+        self
+    }
+}
+
+pub fn uncallable<T, F>(x: T, f: F)
+    where T: for<'a> Foo<'a>,
+          F: for<'a> Fn(<T as Foo<'a>>::Bar)
+{
+    f(x.foo());
+}
+
+pub fn catalyst(x: &i32) {
+    broken(x, |_| {})
+}
+
+pub fn broken<F: Fn(&i32)>(x: &i32, f: F) {
+    uncallable(x, |y| f(y));
+}
+
+fn main() { }
+
diff --git a/src/test/ui/issues/issue-44021.rs b/src/test/ui/issues/issue-44021.rs
new file mode 100644
index 0000000..0b9558c
--- /dev/null
+++ b/src/test/ui/issues/issue-44021.rs
@@ -0,0 +1,6 @@
+struct MyStruct;
+impl MyStruct {
+    fn f() {|x, y} //~ ERROR expected one of `:`, `@`, or `|`, found `}`
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-44021.stderr b/src/test/ui/issues/issue-44021.stderr
new file mode 100644
index 0000000..9450008
--- /dev/null
+++ b/src/test/ui/issues/issue-44021.stderr
@@ -0,0 +1,8 @@
+error: expected one of `:`, `@`, or `|`, found `}`
+  --> $DIR/issue-44021.rs:3:18
+   |
+LL |     fn f() {|x, y}
+   |                  ^ expected one of `:`, `@`, or `|` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-44023.rs b/src/test/ui/issues/issue-44023.rs
new file mode 100644
index 0000000..4c38ddf
--- /dev/null
+++ b/src/test/ui/issues/issue-44023.rs
@@ -0,0 +1,6 @@
+#![feature(non_ascii_idents)]
+
+pub fn main () {}
+
+fn საჭმელად_გემრიელი_სადილი ( ) -> isize { //~ ERROR mismatched types
+}
diff --git a/src/test/ui/issues/issue-44023.stderr b/src/test/ui/issues/issue-44023.stderr
new file mode 100644
index 0000000..153be36
--- /dev/null
+++ b/src/test/ui/issues/issue-44023.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-44023.rs:5:36
+   |
+LL | fn საჭმელად_გემრიელი_სადილი ( ) -> isize {
+   |    ------------------------        ^^^^^ expected isize, found ()
+   |    |
+   |    this function's body doesn't return
+   |
+   = note: expected type `isize`
+              found type `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-44056.rs b/src/test/ui/issues/issue-44056.rs
new file mode 100644
index 0000000..8ed3714
--- /dev/null
+++ b/src/test/ui/issues/issue-44056.rs
@@ -0,0 +1,6 @@
+// compile-pass
+// only-x86_64
+// no-prefer-dynamic
+// compile-flags: -Ctarget-feature=+avx -Clto
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-44078.rs b/src/test/ui/issues/issue-44078.rs
new file mode 100644
index 0000000..b8c0e28
--- /dev/null
+++ b/src/test/ui/issues/issue-44078.rs
@@ -0,0 +1,3 @@
+fn main() {
+    "😊""; //~ ERROR unterminated double quote
+}
diff --git a/src/test/ui/issues/issue-44078.stderr b/src/test/ui/issues/issue-44078.stderr
new file mode 100644
index 0000000..43b49e4
--- /dev/null
+++ b/src/test/ui/issues/issue-44078.stderr
@@ -0,0 +1,10 @@
+error: unterminated double quote string
+  --> $DIR/issue-44078.rs:2:8
+   |
+LL |       "😊"";
+   |  _________^
+LL | | }
+   | |__^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-44127.rs b/src/test/ui/issues/issue-44127.rs
new file mode 100644
index 0000000..21b2e68
--- /dev/null
+++ b/src/test/ui/issues/issue-44127.rs
@@ -0,0 +1,17 @@
+// run-pass
+
+#![feature(decl_macro)]
+
+pub struct Foo {
+    bar: u32,
+}
+pub macro pattern($a:pat) {
+    Foo { bar: $a }
+}
+
+fn main() {
+    match (Foo { bar: 3 }) {
+        pattern!(3) => println!("Test OK"),
+        _ => unreachable!(),
+    }
+}
diff --git a/src/test/ui/issues/issue-44239.rs b/src/test/ui/issues/issue-44239.rs
new file mode 100644
index 0000000..99a865f
--- /dev/null
+++ b/src/test/ui/issues/issue-44239.rs
@@ -0,0 +1,9 @@
+fn main() {
+    let n = 0;
+
+    struct Foo;
+    impl Foo {
+        const N: usize = n;
+        //~^ ERROR attempt to use a non-constant value
+    }
+}
diff --git a/src/test/ui/issues/issue-44239.stderr b/src/test/ui/issues/issue-44239.stderr
new file mode 100644
index 0000000..bc5a6a0
--- /dev/null
+++ b/src/test/ui/issues/issue-44239.stderr
@@ -0,0 +1,9 @@
+error[E0435]: attempt to use a non-constant value in a constant
+  --> $DIR/issue-44239.rs:6:26
+   |
+LL |         const N: usize = n;
+   |                          ^ non-constant value
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0435`.
diff --git a/src/test/ui/issues/issue-44247.rs b/src/test/ui/issues/issue-44247.rs
new file mode 100644
index 0000000..b45d541
--- /dev/null
+++ b/src/test/ui/issues/issue-44247.rs
@@ -0,0 +1,19 @@
+// compile-pass
+#![allow(dead_code)]
+trait T {
+    type X;
+    const X: Self::X;
+}
+fn foo<X: T>() {
+    let _: X::X = X::X;
+}
+
+trait S {
+    const X: Self::X;
+    type X;
+}
+fn bar<X: S>() {
+    let _: X::X = X::X;
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-44255.rs b/src/test/ui/issues/issue-44255.rs
new file mode 100644
index 0000000..2245032
--- /dev/null
+++ b/src/test/ui/issues/issue-44255.rs
@@ -0,0 +1,29 @@
+// run-pass
+
+use std::marker::PhantomData;
+
+fn main() {
+    let _arr = [1; <Multiply<Five, Five>>::VAL];
+}
+
+trait TypeVal<T> {
+    const VAL: T;
+}
+
+struct Five;
+
+impl TypeVal<usize> for Five {
+    const VAL: usize = 5;
+}
+
+struct Multiply<N, M> {
+    _n: PhantomData<N>,
+    _m: PhantomData<M>,
+}
+
+impl<N, M> TypeVal<usize> for Multiply<N, M>
+    where N: TypeVal<usize>,
+          M: TypeVal<usize>,
+{
+    const VAL: usize = N::VAL * M::VAL;
+}
diff --git a/src/test/ui/issues/issue-44373-2.rs b/src/test/ui/issues/issue-44373-2.rs
new file mode 100644
index 0000000..ab92bf4
--- /dev/null
+++ b/src/test/ui/issues/issue-44373-2.rs
@@ -0,0 +1,12 @@
+// compile-pass
+#![allow(dead_code)]
+// compile-flags: -Z borrowck=compare
+
+struct Foo(bool);
+
+struct Container(&'static [&'static Foo]);
+
+static FOO: Foo = Foo(true);
+static CONTAINER: Container = Container(&[&FOO]);
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-44373.nll.stderr b/src/test/ui/issues/issue-44373.nll.stderr
new file mode 100644
index 0000000..6f92fbb
--- /dev/null
+++ b/src/test/ui/issues/issue-44373.nll.stderr
@@ -0,0 +1,13 @@
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/issue-44373.rs:4:42
+   |
+LL |     let _val: &'static [&'static u32] = &[&FOO];
+   |               -----------------------    ^^^^^^ creates a temporary which is freed while still in use
+   |               |
+   |               type annotation requires that borrow lasts for `'static`
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/src/test/ui/issues/issue-44373.rs b/src/test/ui/issues/issue-44373.rs
new file mode 100644
index 0000000..13e9fa9
--- /dev/null
+++ b/src/test/ui/issues/issue-44373.rs
@@ -0,0 +1,5 @@
+static FOO: u32 = 50;
+
+fn main() {
+    let _val: &'static [&'static u32] = &[&FOO]; //~ ERROR borrowed value does not live long enough
+}
diff --git a/src/test/ui/issues/issue-44373.stderr b/src/test/ui/issues/issue-44373.stderr
new file mode 100644
index 0000000..c529558
--- /dev/null
+++ b/src/test/ui/issues/issue-44373.stderr
@@ -0,0 +1,13 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/issue-44373.rs:4:42
+   |
+LL |     let _val: &'static [&'static u32] = &[&FOO];
+   |                                          ^^^^^^ temporary value does not live long enough
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/issues/issue-44402.rs b/src/test/ui/issues/issue-44402.rs
new file mode 100644
index 0000000..7a2eaac
--- /dev/null
+++ b/src/test/ui/issues/issue-44402.rs
@@ -0,0 +1,32 @@
+// compile-pass
+#![allow(dead_code)]
+#![feature(never_type)]
+#![feature(exhaustive_patterns)]
+
+// Regression test for inhabitedness check. The old
+// cache used to cause us to incorrectly decide
+// that `test_b` was invalid.
+
+struct Foo {
+    field1: !,
+    field2: Option<&'static Bar>,
+}
+
+struct Bar {
+    field1: &'static Foo
+}
+
+fn test_a() {
+    let x: Option<Foo> = None;
+    match x { None => () }
+}
+
+fn test_b() {
+    let x: Option<Bar> = None;
+    match x {
+        Some(_) => (),
+        None => ()
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/issues/issue-44406.rs b/src/test/ui/issues/issue-44406.rs
new file mode 100644
index 0000000..83bbf88
--- /dev/null
+++ b/src/test/ui/issues/issue-44406.rs
@@ -0,0 +1,10 @@
+macro_rules! foo {
+    ($rest: tt) => {
+        bar(baz: $rest)
+    }
+}
+
+fn main() {
+    foo!(true); //~ ERROR expected type, found keyword
+    //~^ ERROR expected identifier, found keyword
+}
diff --git a/src/test/ui/issues/issue-44406.stderr b/src/test/ui/issues/issue-44406.stderr
new file mode 100644
index 0000000..14b3b8c
--- /dev/null
+++ b/src/test/ui/issues/issue-44406.stderr
@@ -0,0 +1,21 @@
+error: expected identifier, found keyword `true`
+  --> $DIR/issue-44406.rs:8:10
+   |
+LL |     foo!(true);
+   |          ^^^^ expected identifier, found keyword
+help: you can escape reserved keywords to use them as identifiers
+   |
+LL |     foo!(r#true);
+   |          ^^^^^^
+
+error: expected type, found keyword `true`
+  --> $DIR/issue-44406.rs:8:10
+   |
+LL |         bar(baz: $rest)
+   |                - help: try using a semicolon: `;`
+...
+LL |     foo!(true);
+   |          ^^^^ expecting a type here because of type ascription
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/issues/issue-44415.rs b/src/test/ui/issues/issue-44415.rs
new file mode 100644
index 0000000..763f857
--- /dev/null
+++ b/src/test/ui/issues/issue-44415.rs
@@ -0,0 +1,11 @@
+#![feature(core_intrinsics)]
+
+use std::intrinsics;
+
+struct Foo {
+    bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
+    //~^ ERROR cycle detected when const-evaluating + checking
+    x: usize,
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-44415.stderr b/src/test/ui/issues/issue-44415.stderr
new file mode 100644
index 0000000..df8e804
--- /dev/null
+++ b/src/test/ui/issues/issue-44415.stderr
@@ -0,0 +1,28 @@
+error[E0391]: cycle detected when const-evaluating + checking `Foo::bytes::{{constant}}#0`
+  --> $DIR/issue-44415.rs:6:17
+   |
+LL |     bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
+   |                 ^^^^^^
+   |
+note: ...which requires const-evaluating `Foo::bytes::{{constant}}#0`...
+  --> $DIR/issue-44415.rs:6:26
+   |
+LL |     bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: ...which requires computing layout of `Foo`...
+   = note: ...which requires normalizing `ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: All, def_id: None }, value: [u8; _] }`...
+note: ...which requires const-evaluating + checking `Foo::bytes::{{constant}}#0`...
+  --> $DIR/issue-44415.rs:6:17
+   |
+LL |     bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
+   |                 ^^^^^^
+   = note: ...which again requires const-evaluating + checking `Foo::bytes::{{constant}}#0`, completing the cycle
+note: cycle used when processing `Foo`
+  --> $DIR/issue-44415.rs:5:1
+   |
+LL | struct Foo {
+   | ^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/issues/issue-4464.rs b/src/test/ui/issues/issue-4464.rs
new file mode 100644
index 0000000..c20c1ca
--- /dev/null
+++ b/src/test/ui/issues/issue-4464.rs
@@ -0,0 +1,7 @@
+// compile-pass
+#![allow(dead_code)]
+// pretty-expanded FIXME #23616
+
+fn broken(v: &[u8], i: usize, j: usize) -> &[u8] { &v[i..j] }
+
+pub fn main() {}
diff --git a/src/test/ui/issues/issue-44730.rs b/src/test/ui/issues/issue-44730.rs
new file mode 100644
index 0000000..7dae6c8
--- /dev/null
+++ b/src/test/ui/issues/issue-44730.rs
@@ -0,0 +1,15 @@
+// compile-pass
+//! dox
+
+#![deny(missing_docs)]
+
+macro_rules! doc {
+    ($e:expr) => (
+        #[doc = $e]
+        pub struct Foo;
+    )
+}
+
+doc!("a");
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-44851.rs b/src/test/ui/issues/issue-44851.rs
new file mode 100644
index 0000000..697b4dc
--- /dev/null
+++ b/src/test/ui/issues/issue-44851.rs
@@ -0,0 +1,15 @@
+// compile-pass
+macro_rules! a {
+    () => { "a" }
+}
+
+macro_rules! b {
+    ($doc:expr) => {
+        #[doc = $doc]
+        pub struct B;
+    }
+}
+
+b!(a!());
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-45087-unreachable-unsafe.rs b/src/test/ui/issues/issue-45087-unreachable-unsafe.rs
new file mode 100644
index 0000000..5edf7a4
--- /dev/null
+++ b/src/test/ui/issues/issue-45087-unreachable-unsafe.rs
@@ -0,0 +1,5 @@
+fn main() {
+    return;
+    *(1 as *mut u32) = 42;
+    //~^ ERROR dereference of raw pointer is unsafe
+}
diff --git a/src/test/ui/issues/issue-45087-unreachable-unsafe.stderr b/src/test/ui/issues/issue-45087-unreachable-unsafe.stderr
new file mode 100644
index 0000000..d112d7f
--- /dev/null
+++ b/src/test/ui/issues/issue-45087-unreachable-unsafe.stderr
@@ -0,0 +1,11 @@
+error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
+  --> $DIR/issue-45087-unreachable-unsafe.rs:3:5
+   |
+LL |     *(1 as *mut u32) = 42;
+   |     ^^^^^^^^^^^^^^^^^^^^^ dereference of raw pointer
+   |
+   = note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/issues/issue-45107-unnecessary-unsafe-in-closure.rs b/src/test/ui/issues/issue-45107-unnecessary-unsafe-in-closure.rs
new file mode 100644
index 0000000..de275ff
--- /dev/null
+++ b/src/test/ui/issues/issue-45107-unnecessary-unsafe-in-closure.rs
@@ -0,0 +1,25 @@
+#[deny(unused_unsafe)]
+fn main() {
+    let mut v = Vec::<i32>::with_capacity(24);
+
+    unsafe {
+        let f = |v: &mut Vec<_>| {
+            unsafe { //~ ERROR unnecessary `unsafe`
+                v.set_len(24);
+                |w: &mut Vec<u32>| { unsafe { //~ ERROR unnecessary `unsafe`
+                    w.set_len(32);
+                } };
+            }
+            |x: &mut Vec<u32>| { unsafe { //~ ERROR unnecessary `unsafe`
+                x.set_len(40);
+            } };
+        };
+
+        v.set_len(0);
+        f(&mut v);
+    }
+
+    |y: &mut Vec<u32>| { unsafe {
+        y.set_len(48);
+    } };
+}
diff --git a/src/test/ui/issues/issue-45107-unnecessary-unsafe-in-closure.stderr b/src/test/ui/issues/issue-45107-unnecessary-unsafe-in-closure.stderr
new file mode 100644
index 0000000..71fbba5
--- /dev/null
+++ b/src/test/ui/issues/issue-45107-unnecessary-unsafe-in-closure.stderr
@@ -0,0 +1,35 @@
+error: unnecessary `unsafe` block
+  --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:7:13
+   |
+LL |     unsafe {
+   |     ------ because it's nested under this `unsafe` block
+LL |         let f = |v: &mut Vec<_>| {
+LL |             unsafe {
+   |             ^^^^^^ unnecessary `unsafe` block
+   |
+note: lint level defined here
+  --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:1:8
+   |
+LL | #[deny(unused_unsafe)]
+   |        ^^^^^^^^^^^^^
+
+error: unnecessary `unsafe` block
+  --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:9:38
+   |
+LL |     unsafe {
+   |     ------ because it's nested under this `unsafe` block
+...
+LL |                 |w: &mut Vec<u32>| { unsafe {
+   |                                      ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:13:34
+   |
+LL |     unsafe {
+   |     ------ because it's nested under this `unsafe` block
+...
+LL |             |x: &mut Vec<u32>| { unsafe {
+   |                                  ^^^^^^ unnecessary `unsafe` block
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/issues/issue-45157.rs b/src/test/ui/issues/issue-45157.rs
new file mode 100644
index 0000000..22ea254
--- /dev/null
+++ b/src/test/ui/issues/issue-45157.rs
@@ -0,0 +1,33 @@
+#![allow(unused)]
+#![feature(nll)]
+
+// ignore-tidy-linelength
+
+#[derive(Clone, Copy, Default)]
+struct S {
+    a: u8,
+    b: u8,
+}
+#[derive(Clone, Copy, Default)]
+struct Z {
+    c: u8,
+    d: u8,
+}
+
+union U {
+    s: S,
+    z: Z,
+}
+
+fn main() {
+    unsafe {
+        let mut u = U { s: Default::default() };
+
+        let mref = &mut u.s.a;
+        *mref = 22;
+
+        let nref = &u.z.c;
+        //~^ ERROR cannot borrow `u` (via `u.z.c`) as immutable because it is also borrowed as mutable (via `u.s.a`) [E0502]
+        println!("{} {}", mref, nref)
+    }
+}
diff --git a/src/test/ui/issues/issue-45157.stderr b/src/test/ui/issues/issue-45157.stderr
new file mode 100644
index 0000000..fbfa1d1
--- /dev/null
+++ b/src/test/ui/issues/issue-45157.stderr
@@ -0,0 +1,17 @@
+error[E0502]: cannot borrow `u` (via `u.z.c`) as immutable because it is also borrowed as mutable (via `u.s.a`)
+  --> $DIR/issue-45157.rs:29:20
+   |
+LL |         let mref = &mut u.s.a;
+   |                    ---------- mutable borrow occurs here (via `u.s.a`)
+...
+LL |         let nref = &u.z.c;
+   |                    ^^^^^^ immutable borrow of `u.z.c` -- which overlaps with `u.s.a` -- occurs here
+LL |
+LL |         println!("{} {}", mref, nref)
+   |                           ---- mutable borrow later used here
+   |
+   = note: `u.z.c` is a field of the union `U`, so it overlaps the field `u.s.a`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/issues/issue-4517.rs b/src/test/ui/issues/issue-4517.rs
new file mode 100644
index 0000000..bbe81f3
--- /dev/null
+++ b/src/test/ui/issues/issue-4517.rs
@@ -0,0 +1,10 @@
+fn bar(int_param: usize) {}
+
+fn main() {
+    let foo: [u8; 4] = [1; 4];
+    bar(foo);
+    //~^ ERROR mismatched types
+    //~| expected type `usize`
+    //~| found type `[u8; 4]`
+    //~| expected usize, found array of 4 elements
+}
diff --git a/src/test/ui/issues/issue-4517.stderr b/src/test/ui/issues/issue-4517.stderr
new file mode 100644
index 0000000..7d88e55
--- /dev/null
+++ b/src/test/ui/issues/issue-4517.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-4517.rs:5:9
+   |
+LL |     bar(foo);
+   |         ^^^ expected usize, found array of 4 elements
+   |
+   = note: expected type `usize`
+              found type `[u8; 4]`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-45199.ast.nll.stderr b/src/test/ui/issues/issue-45199.ast.nll.stderr
new file mode 100644
index 0000000..c6ae7c9
--- /dev/null
+++ b/src/test/ui/issues/issue-45199.ast.nll.stderr
@@ -0,0 +1,36 @@
+error[E0384]: cannot assign twice to immutable variable `b`
+  --> $DIR/issue-45199.rs:10:5
+   |
+LL |     let b: Box<isize>;
+   |         - help: make this binding mutable: `mut b`
+...
+LL |     b = Box::new(1);
+   |     - first assignment to `b`
+LL |
+LL |     b = Box::new(2);
+   |     ^ cannot assign twice to immutable variable
+
+error[E0384]: cannot assign twice to immutable variable `b`
+  --> $DIR/issue-45199.rs:21:5
+   |
+LL |     let b = Box::new(1);
+   |         -
+   |         |
+   |         first assignment to `b`
+   |         help: make this binding mutable: `mut b`
+...
+LL |     b = Box::new(2);
+   |     ^ cannot assign twice to immutable variable
+
+error[E0384]: cannot assign to immutable argument `b`
+  --> $DIR/issue-45199.rs:30:5
+   |
+LL | fn test_args(b: Box<i32>) {
+   |              - help: make this binding mutable: `mut b`
+...
+LL |     b = Box::new(2);
+   |     ^ cannot assign to immutable argument
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0384`.
diff --git a/src/test/ui/issues/issue-45199.ast.stderr b/src/test/ui/issues/issue-45199.ast.stderr
new file mode 100644
index 0000000..9dfd8e8
--- /dev/null
+++ b/src/test/ui/issues/issue-45199.ast.stderr
@@ -0,0 +1,30 @@
+error[E0384]: cannot assign twice to immutable variable `b`
+  --> $DIR/issue-45199.rs:10:5
+   |
+LL |     b = Box::new(1);
+   |     --------------- first assignment to `b`
+LL |
+LL |     b = Box::new(2);
+   |     ^^^^^^^^^^^^^^^ cannot assign twice to immutable variable
+
+error[E0384]: cannot assign twice to immutable variable `b`
+  --> $DIR/issue-45199.rs:21:5
+   |
+LL |     let b = Box::new(1);
+   |         - first assignment to `b`
+...
+LL |     b = Box::new(2);
+   |     ^^^^^^^^^^^^^^^ cannot assign twice to immutable variable
+
+error[E0384]: cannot assign twice to immutable variable `b`
+  --> $DIR/issue-45199.rs:30:5
+   |
+LL | fn test_args(b: Box<i32>) {
+   |              - first assignment to `b`
+...
+LL |     b = Box::new(2);
+   |     ^^^^^^^^^^^^^^^ cannot assign twice to immutable variable
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0384`.
diff --git a/src/test/ui/issues/issue-45199.mir.stderr b/src/test/ui/issues/issue-45199.mir.stderr
new file mode 100644
index 0000000..c6ae7c9
--- /dev/null
+++ b/src/test/ui/issues/issue-45199.mir.stderr
@@ -0,0 +1,36 @@
+error[E0384]: cannot assign twice to immutable variable `b`
+  --> $DIR/issue-45199.rs:10:5
+   |
+LL |     let b: Box<isize>;
+   |         - help: make this binding mutable: `mut b`
+...
+LL |     b = Box::new(1);
+   |     - first assignment to `b`
+LL |
+LL |     b = Box::new(2);
+   |     ^ cannot assign twice to immutable variable
+
+error[E0384]: cannot assign twice to immutable variable `b`
+  --> $DIR/issue-45199.rs:21:5
+   |
+LL |     let b = Box::new(1);
+   |         -
+   |         |
+   |         first assignment to `b`
+   |         help: make this binding mutable: `mut b`
+...
+LL |     b = Box::new(2);
+   |     ^ cannot assign twice to immutable variable
+
+error[E0384]: cannot assign to immutable argument `b`
+  --> $DIR/issue-45199.rs:30:5
+   |
+LL | fn test_args(b: Box<i32>) {
+   |              - help: make this binding mutable: `mut b`
+...
+LL |     b = Box::new(2);
+   |     ^ cannot assign to immutable argument
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0384`.
diff --git a/src/test/ui/issues/issue-45199.rs b/src/test/ui/issues/issue-45199.rs
new file mode 100644
index 0000000..bb55534
--- /dev/null
+++ b/src/test/ui/issues/issue-45199.rs
@@ -0,0 +1,36 @@
+// revisions: ast mir
+//[mir]compile-flags: -Zborrowck=mir
+
+fn test_drop_replace() {
+    let b: Box<isize>;
+    //[mir]~^ HELP make this binding mutable
+    //[mir]~| SUGGESTION 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
+                        //[mir]~^ ERROR cannot assign twice to immutable variable `b`
+                        //[ast]~| NOTE cannot assign twice to immutable
+                        //[mir]~| NOTE cannot assign twice to immutable
+}
+
+fn test_call() {
+    let b = Box::new(1);    //[ast]~ NOTE first assignment
+                            //[mir]~^ NOTE first assignment
+                            //[mir]~| HELP make this binding mutable
+                            //[mir]~| SUGGESTION 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
+                            //[mir]~| NOTE cannot assign twice to immutable
+}
+
+fn test_args(b: Box<i32>) {  //[ast]~ NOTE first assignment
+                                //[mir]~^ HELP make this binding mutable
+                                //[mir]~| SUGGESTION 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
+                                //[mir]~| NOTE cannot assign to immutable argument
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-45296.rs b/src/test/ui/issues/issue-45296.rs
new file mode 100644
index 0000000..f242c1d
--- /dev/null
+++ b/src/test/ui/issues/issue-45296.rs
@@ -0,0 +1,5 @@
+fn main() {
+    let unused = ();
+
+    #![allow(unused_variables)] //~ ERROR not permitted in this context
+}
diff --git a/src/test/ui/issues/issue-45296.stderr b/src/test/ui/issues/issue-45296.stderr
new file mode 100644
index 0000000..bc14d20
--- /dev/null
+++ b/src/test/ui/issues/issue-45296.stderr
@@ -0,0 +1,10 @@
+error: an inner attribute is not permitted in this context
+  --> $DIR/issue-45296.rs:4:7
+   |
+LL |     #![allow(unused_variables)]
+   |       ^
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-45425.rs b/src/test/ui/issues/issue-45425.rs
new file mode 100644
index 0000000..a2ef85a
--- /dev/null
+++ b/src/test/ui/issues/issue-45425.rs
@@ -0,0 +1,12 @@
+// compile-pass
+#![allow(dead_code)]
+use std::ops::Add;
+
+fn ref_add<T>(a: &T, b: &T) -> T
+where
+    for<'x> &'x T: Add<&'x T, Output = T>,
+{
+    a + b
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-45562.fixed b/src/test/ui/issues/issue-45562.fixed
new file mode 100644
index 0000000..c23f590
--- /dev/null
+++ b/src/test/ui/issues/issue-45562.fixed
@@ -0,0 +1,6 @@
+// run-rustfix
+
+#[no_mangle] pub static RAH: usize = 5;
+//~^ ERROR const items should never be #[no_mangle]
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-45562.rs b/src/test/ui/issues/issue-45562.rs
new file mode 100644
index 0000000..8ac4f67
--- /dev/null
+++ b/src/test/ui/issues/issue-45562.rs
@@ -0,0 +1,6 @@
+// run-rustfix
+
+#[no_mangle] pub const RAH: usize = 5;
+//~^ ERROR const items should never be #[no_mangle]
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-45562.stderr b/src/test/ui/issues/issue-45562.stderr
new file mode 100644
index 0000000..b97b9cd
--- /dev/null
+++ b/src/test/ui/issues/issue-45562.stderr
@@ -0,0 +1,12 @@
+error: const items should never be #[no_mangle]
+  --> $DIR/issue-45562.rs:3:14
+   |
+LL | #[no_mangle] pub const RAH: usize = 5;
+   |              ---------^^^^^^^^^^^^^^^^
+   |              |
+   |              help: try a static value: `pub static`
+   |
+   = note: #[deny(no_mangle_const_items)] on by default
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-45696-long-live-borrows-in-boxes.rs b/src/test/ui/issues/issue-45696-long-live-borrows-in-boxes.rs
new file mode 100644
index 0000000..9f86cae
--- /dev/null
+++ b/src/test/ui/issues/issue-45696-long-live-borrows-in-boxes.rs
@@ -0,0 +1,123 @@
+// rust-lang/rust#45696: This test is checking that we can return
+// mutable borrows owned by boxes even when the boxes are dropped.
+//
+// We will explicitly test AST-borrowck, NLL, and migration modes;
+// thus we will also skip the automated compare-mode=nll.
+
+// revisions: ast nll migrate
+// ignore-compare-mode-nll
+
+#![cfg_attr(nll, feature(nll))]
+//[migrate]compile-flags: -Z borrowck=migrate -Z two-phase-borrows
+
+// run-pass
+
+// This function shows quite directly what is going on: We have a
+// reborrow of contents within the box.
+fn return_borrow_from_dropped_box_1(x: Box<&mut u32>) -> &mut u32 { &mut **x }
+
+// This function is the way you'll probably see this in practice (the
+// reborrow is now implicit).
+fn return_borrow_from_dropped_box_2(x: Box<&mut u32>) -> &mut u32 { *x }
+
+// For the remaining tests we just add some fields or other
+// indirection to ensure that the compiler isn't just special-casing
+// the above `Box<&mut T>` as the only type that would work.
+
+// Here we add a tuple of indirection between the box and the
+// reference.
+type BoxedTup<'a, 'b> = Box<(&'a mut u32, &'b mut u32)>;
+
+fn return_borrow_of_field_from_dropped_box_1<'a>(x: BoxedTup<'a, '_>) -> &'a mut u32 {
+    &mut *x.0
+}
+
+fn return_borrow_of_field_from_dropped_box_2<'a>(x: BoxedTup<'a, '_>) -> &'a mut u32 {
+    x.0
+}
+
+fn return_borrow_from_dropped_tupled_box_1<'a>(x: (BoxedTup<'a, '_>, &mut u32)) -> &'a mut u32 {
+    &mut *(x.0).0
+}
+
+fn return_borrow_from_dropped_tupled_box_2<'a>(x: (BoxedTup<'a, '_>, &mut u32)) -> &'a mut u32 {
+    (x.0).0
+}
+
+fn basic_tests() {
+    let mut x = 2;
+    let mut y = 3;
+    let mut z = 4;
+    *return_borrow_from_dropped_box_1(Box::new(&mut x)) += 10;
+    assert_eq!((x, y, z), (12, 3, 4));
+    *return_borrow_from_dropped_box_2(Box::new(&mut x)) += 10;
+    assert_eq!((x, y, z), (22, 3, 4));
+    *return_borrow_of_field_from_dropped_box_1(Box::new((&mut x, &mut y))) += 10;
+    assert_eq!((x, y, z), (32, 3, 4));
+    *return_borrow_of_field_from_dropped_box_2(Box::new((&mut x, &mut y))) += 10;
+    assert_eq!((x, y, z), (42, 3, 4));
+    *return_borrow_from_dropped_tupled_box_1((Box::new((&mut x, &mut y)), &mut z)) += 10;
+    assert_eq!((x, y, z), (52, 3, 4));
+    *return_borrow_from_dropped_tupled_box_2((Box::new((&mut x, &mut y)), &mut z)) += 10;
+    assert_eq!((x, y, z), (62, 3, 4));
+}
+
+// These scribbling tests have been transcribed from
+// issue-45696-scribble-on-boxed-borrow.rs
+//
+// In the context of that file, these tests are meant to show cases
+// that should be *accepted* by the compiler, so here we are actually
+// checking that the code we get when they are compiled matches our
+// expectations.
+
+struct Scribble<'a>(&'a mut u32);
+
+impl<'a> Drop for Scribble<'a> { fn drop(&mut self) { *self.0 = 42; } }
+
+// this is okay, in both AST-borrowck and NLL: The `Scribble` here *has*
+// to strictly outlive `'a`
+fn borrowed_scribble<'a>(s: &'a mut Scribble) -> &'a mut u32 {
+    &mut *s.0
+}
+
+// this, by analogy to previous case, is also okay.
+fn boxed_borrowed_scribble<'a>(s: Box<&'a mut Scribble>) -> &'a mut u32 {
+    &mut *(*s).0
+}
+
+// this, by analogy to previous case, is also okay.
+fn boxed_boxed_borrowed_scribble<'a>(s: Box<Box<&'a mut Scribble>>) -> &'a mut u32 {
+    &mut *(**s).0
+}
+
+fn scribbling_tests() {
+    let mut x = 1;
+    {
+        let mut long_lived = Scribble(&mut x);
+        *borrowed_scribble(&mut long_lived) += 10;
+        assert_eq!(*long_lived.0, 11);
+        // (Scribble dtor runs here, after `&mut`-borrow above ends)
+    }
+    assert_eq!(x, 42);
+    x = 1;
+    {
+        let mut long_lived = Scribble(&mut x);
+        *boxed_borrowed_scribble(Box::new(&mut long_lived)) += 10;
+        assert_eq!(*long_lived.0, 11);
+        // (Scribble dtor runs here, after `&mut`-borrow above ends)
+    }
+    assert_eq!(x, 42);
+    x = 1;
+    {
+        let mut long_lived = Scribble(&mut x);
+        *boxed_boxed_borrowed_scribble(Box::new(Box::new(&mut long_lived))) += 10;
+        assert_eq!(*long_lived.0, 11);
+        // (Scribble dtor runs here, after `&mut`-borrow above ends)
+    }
+    assert_eq!(x, 42);
+}
+
+fn main() {
+    basic_tests();
+    scribbling_tests();
+}
diff --git a/src/test/ui/issues/issue-45696-no-variant-box-recur.rs b/src/test/ui/issues/issue-45696-no-variant-box-recur.rs
new file mode 100644
index 0000000..867da22
--- /dev/null
+++ b/src/test/ui/issues/issue-45696-no-variant-box-recur.rs
@@ -0,0 +1,56 @@
+// rust-lang/rust#45696: This test checks the compiler won't infinite
+// loop when you declare a variable of type `struct A(Box<A>, ...);`
+// (which is impossible to construct but *is* possible to declare; see
+// also issues #4287, #44933, and #52852).
+//
+// We will explicitly test AST-borrowck, NLL, and migration modes;
+// thus we will also skip the automated compare-mode=nll.
+
+// revisions: ast nll migrate
+// ignore-compare-mode-nll
+
+#![cfg_attr(nll, feature(nll))]
+//[migrate]compile-flags: -Z borrowck=migrate -Z two-phase-borrows
+
+// run-pass
+
+// This test has structs and functions that are by definition unusable
+// all over the place, so just go ahead and allow dead_code
+#![allow(dead_code)]
+
+// direct regular recursion with indirect ownership via box
+struct C { field: Box<C> }
+
+// direct non-regular recursion with indirect ownership via box
+struct D { field: Box<(D, D)> }
+
+// indirect regular recursion with indirect ownership via box.
+struct E { field: F }
+struct F { field: Box<E> }
+
+// indirect non-regular recursion with indirect ownership via box.
+struct G { field: (H, H) }
+struct H { field: Box<G> }
+
+// These enums are cases that are not currently hit by the
+// `visit_terminator_drop` recursion down a type's structural
+// definition.
+//
+// But it seems prudent to include them in this test as variants on
+// the above, in that they are similarly non-constructable data types
+// with destructors that would diverge.
+enum I { One(Box<I>) }
+enum J { One(Box<J>), Two(Box<J>) }
+
+fn impossible_to_call_c(_c: C) { }
+fn impossible_to_call_d(_d: D) { }
+fn impossible_to_call_e(_e: E) { }
+fn impossible_to_call_f(_f: F) { }
+fn impossible_to_call_g(_g: G) { }
+fn impossible_to_call_h(_h: H) { }
+fn impossible_to_call_i(_i: I) { }
+fn impossible_to_call_j(_j: J) { }
+
+fn main() {
+
+}
diff --git a/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.ast.stderr b/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.ast.stderr
new file mode 100644
index 0000000..0aaba52
--- /dev/null
+++ b/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.ast.stderr
@@ -0,0 +1,14 @@
+error: compilation successful
+  --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:82:1
+   |
+LL | / fn main() {
+LL | |
+LL | |     let mut x = 1;
+LL | |     {
+...  |
+LL | |     *boxed_boxed_scribbled(Box::new(Box::new(Scribble(&mut x)))) += 10;
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.migrate.stderr b/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.migrate.stderr
new file mode 100644
index 0000000..f8aab23
--- /dev/null
+++ b/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.migrate.stderr
@@ -0,0 +1,57 @@
+warning[E0713]: borrow may still be in use when destructor runs
+  --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:53:5
+   |
+LL | fn scribbled<'a>(s: Scribble<'a>) -> &'a mut u32 {
+   |              -- lifetime `'a` defined here
+LL |     &mut *s.0
+   |     ^^^^^^^^^ returning this value requires that `*s.0` is borrowed for `'a`
+...
+LL | }
+   | - here, drop of `s` needs exclusive access to `*s.0`, because the type `Scribble<'_>` implements the `Drop` trait
+   |
+   = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
+   = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+
+warning[E0713]: borrow may still be in use when destructor runs
+  --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:64:5
+   |
+LL | fn boxed_scribbled<'a>(s: Box<Scribble<'a>>) -> &'a mut u32 {
+   |                    -- lifetime `'a` defined here
+LL |     &mut *(*s).0
+   |     ^^^^^^^^^^^^ returning this value requires that `*s.0` is borrowed for `'a`
+...
+LL | }
+   | - here, drop of `s` needs exclusive access to `*s.0`, because the type `Scribble<'_>` implements the `Drop` trait
+   |
+   = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
+   = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+
+warning[E0713]: borrow may still be in use when destructor runs
+  --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:75:5
+   |
+LL | fn boxed_boxed_scribbled<'a>(s: Box<Box<Scribble<'a>>>) -> &'a mut u32 {
+   |                          -- lifetime `'a` defined here
+LL |     &mut *(**s).0
+   |     ^^^^^^^^^^^^^ returning this value requires that `*s.0` is borrowed for `'a`
+...
+LL | }
+   | - here, drop of `s` needs exclusive access to `*s.0`, because the type `Scribble<'_>` implements the `Drop` trait
+   |
+   = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
+   = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+
+error: compilation successful
+  --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:82:1
+   |
+LL | / fn main() {
+LL | |
+LL | |     let mut x = 1;
+LL | |     {
+...  |
+LL | |     *boxed_boxed_scribbled(Box::new(Box::new(Scribble(&mut x)))) += 10;
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0713`.
diff --git a/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.nll.stderr b/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.nll.stderr
new file mode 100644
index 0000000..bfb5832
--- /dev/null
+++ b/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.nll.stderr
@@ -0,0 +1,36 @@
+error[E0713]: borrow may still be in use when destructor runs
+  --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:53:5
+   |
+LL | fn scribbled<'a>(s: Scribble<'a>) -> &'a mut u32 {
+   |              -- lifetime `'a` defined here
+LL |     &mut *s.0
+   |     ^^^^^^^^^ returning this value requires that `*s.0` is borrowed for `'a`
+...
+LL | }
+   | - here, drop of `s` needs exclusive access to `*s.0`, because the type `Scribble<'_>` implements the `Drop` trait
+
+error[E0713]: borrow may still be in use when destructor runs
+  --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:64:5
+   |
+LL | fn boxed_scribbled<'a>(s: Box<Scribble<'a>>) -> &'a mut u32 {
+   |                    -- lifetime `'a` defined here
+LL |     &mut *(*s).0
+   |     ^^^^^^^^^^^^ returning this value requires that `*s.0` is borrowed for `'a`
+...
+LL | }
+   | - here, drop of `s` needs exclusive access to `*s.0`, because the type `Scribble<'_>` implements the `Drop` trait
+
+error[E0713]: borrow may still be in use when destructor runs
+  --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:75:5
+   |
+LL | fn boxed_boxed_scribbled<'a>(s: Box<Box<Scribble<'a>>>) -> &'a mut u32 {
+   |                          -- lifetime `'a` defined here
+LL |     &mut *(**s).0
+   |     ^^^^^^^^^^^^^ returning this value requires that `*s.0` is borrowed for `'a`
+...
+LL | }
+   | - here, drop of `s` needs exclusive access to `*s.0`, because the type `Scribble<'_>` implements the `Drop` trait
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0713`.
diff --git a/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.rs b/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.rs
new file mode 100644
index 0000000..fc56a2a
--- /dev/null
+++ b/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.rs
@@ -0,0 +1,103 @@
+// rust-lang/rust#45696: This test is checking that we *cannot* return
+// mutable borrows that would be scribbled over by destructors before
+// the return occurs.
+//
+// We will explicitly test AST-borrowck, NLL, and migration modes;
+// thus we will also skip the automated compare-mode=nll.
+
+// revisions: ast nll migrate
+// ignore-compare-mode-nll
+
+// This test is going to pass in the ast and migrate revisions,
+// because the AST-borrowck accepted this code in the past (see notes
+// below). So we use `#[rustc_error]` to keep the outcome as an error
+// in all scenarios, and rely on the stderr files to show what the
+// actual behavior is. (See rust-lang/rust#49855.)
+#![feature(rustc_attrs)]
+
+#![cfg_attr(nll, feature(nll))]
+//[migrate]compile-flags: -Z borrowck=migrate -Z two-phase-borrows
+
+struct Scribble<'a>(&'a mut u32);
+
+impl<'a> Drop for Scribble<'a> { fn drop(&mut self) { *self.0 = 42; } }
+
+// this is okay, in both AST-borrowck and NLL: The `Scribble` here *has*
+// to strictly outlive `'a`
+fn borrowed_scribble<'a>(s: &'a mut Scribble) -> &'a mut u32 {
+    &mut *s.0
+}
+
+// this, by analogy to previous case, is also okay.
+fn boxed_borrowed_scribble<'a>(s: Box<&'a mut Scribble>) -> &'a mut u32 {
+    &mut *(*s).0
+}
+
+// this, by analogy to previous case, is also okay.
+fn boxed_boxed_borrowed_scribble<'a>(s: Box<Box<&'a mut Scribble>>) -> &'a mut u32 {
+    &mut *(**s).0
+}
+
+// this is not okay: in between the time that we take the mutable
+// borrow and the caller receives it as a return value, the drop of
+// `s` will scribble on it, violating our aliasing guarantees.
+//
+// * (Maybe in the future the two-phase borrows system will be
+//   extended to support this case. But for now, it is an error in
+//   NLL, even with two-phase borrows.)
+//
+// In any case, the AST-borrowck was not smart enough to know that
+// this should be an error. (Which is perhaps the essence of why
+// rust-lang/rust#45696 arose in the first place.)
+fn scribbled<'a>(s: Scribble<'a>) -> &'a mut u32 {
+    &mut *s.0 //[nll]~ ERROR borrow may still be in use when destructor runs [E0713]
+    //[migrate]~^ WARNING borrow may still be in use when destructor runs [E0713]
+    //[migrate]~| WARNING this error has been downgraded to a warning for backwards compatibility
+    //[migrate]~| WARNING this represents potential undefined behavior in your code
+}
+
+// This, by analogy to previous case, is *also* not okay.
+//
+// (But again, AST-borrowck was not smart enogh to know that this
+// should be an error.)
+fn boxed_scribbled<'a>(s: Box<Scribble<'a>>) -> &'a mut u32 {
+    &mut *(*s).0 //[nll]~ ERROR borrow may still be in use when destructor runs [E0713]
+    //[migrate]~^ WARNING borrow may still be in use when destructor runs [E0713]
+    //[migrate]~| WARNING this error has been downgraded to a warning for backwards compatibility
+    //[migrate]~| WARNING this represents potential undefined behavior in your code
+}
+
+// This, by analogy to previous case, is *also* not okay.
+//
+// (But again, AST-borrowck was not smart enogh to know that this
+// should be an error.)
+fn boxed_boxed_scribbled<'a>(s: Box<Box<Scribble<'a>>>) -> &'a mut u32 {
+    &mut *(**s).0 //[nll]~ ERROR borrow may still be in use when destructor runs [E0713]
+    //[migrate]~^ WARNING borrow may still be in use when destructor runs [E0713]
+    //[migrate]~| WARNING this error has been downgraded to a warning for backwards compatibility
+    //[migrate]~| WARNING this represents potential undefined behavior in your code
+}
+
+#[rustc_error]
+fn main() { //[ast]~ ERROR compilation successful
+     //[migrate]~^ ERROR compilation successful
+    let mut x = 1;
+    {
+        let mut long_lived = Scribble(&mut x);
+        *borrowed_scribble(&mut long_lived) += 10;
+        // (Scribble dtor runs here, after `&mut`-borrow above ends)
+    }
+    {
+        let mut long_lived = Scribble(&mut x);
+        *boxed_borrowed_scribble(Box::new(&mut long_lived)) += 10;
+        // (Scribble dtor runs here, after `&mut`-borrow above ends)
+    }
+    {
+        let mut long_lived = Scribble(&mut x);
+        *boxed_boxed_borrowed_scribble(Box::new(Box::new(&mut long_lived))) += 10;
+        // (Scribble dtor runs here, after `&mut`-borrow above ends)
+    }
+    *scribbled(Scribble(&mut x)) += 10;
+    *boxed_scribbled(Box::new(Scribble(&mut x))) += 10;
+    *boxed_boxed_scribbled(Box::new(Box::new(Scribble(&mut x)))) += 10;
+}
diff --git a/src/test/ui/issues/issue-45697-1.rs b/src/test/ui/issues/issue-45697-1.rs
new file mode 100644
index 0000000..c9b267c
--- /dev/null
+++ b/src/test/ui/issues/issue-45697-1.rs
@@ -0,0 +1,26 @@
+// Test that assignments to an `&mut` pointer which is found in a
+// borrowed (but otherwise non-aliasable) location is illegal.
+
+// compile-flags: -Z borrowck=compare -C overflow-checks=on
+
+struct S<'a> {
+    pointer: &'a mut isize
+}
+
+fn copy_borrowed_ptr<'a>(p: &'a mut S<'a>) -> S<'a> {
+    S { pointer: &mut *p.pointer }
+}
+
+fn main() {
+    let mut x = 1;
+
+    {
+        let mut y = S { pointer: &mut x };
+        let z = copy_borrowed_ptr(&mut y);
+        *y.pointer += 1;
+        //~^ ERROR cannot assign to `*y.pointer` because it is borrowed (Ast) [E0506]
+        //~| ERROR cannot use `*y.pointer` because it was mutably borrowed (Mir) [E0503]
+        //~| ERROR cannot assign to `*y.pointer` because it is borrowed (Mir) [E0506]
+        *z.pointer += 1;
+    }
+}
diff --git a/src/test/ui/issues/issue-45697-1.stderr b/src/test/ui/issues/issue-45697-1.stderr
new file mode 100644
index 0000000..8d39072
--- /dev/null
+++ b/src/test/ui/issues/issue-45697-1.stderr
@@ -0,0 +1,34 @@
+error[E0506]: cannot assign to `*y.pointer` because it is borrowed (Ast)
+  --> $DIR/issue-45697-1.rs:20:9
+   |
+LL |         let z = copy_borrowed_ptr(&mut y);
+   |                                        - borrow of `*y.pointer` occurs here
+LL |         *y.pointer += 1;
+   |         ^^^^^^^^^^^^^^^ assignment to borrowed `*y.pointer` occurs here
+
+error[E0503]: cannot use `*y.pointer` because it was mutably borrowed (Mir)
+  --> $DIR/issue-45697-1.rs:20:9
+   |
+LL |         let z = copy_borrowed_ptr(&mut y);
+   |                                   ------ borrow of `y` occurs here
+LL |         *y.pointer += 1;
+   |         ^^^^^^^^^^^^^^^ use of borrowed `y`
+...
+LL |         *z.pointer += 1;
+   |         --------------- borrow later used here
+
+error[E0506]: cannot assign to `*y.pointer` because it is borrowed (Mir)
+  --> $DIR/issue-45697-1.rs:20:9
+   |
+LL |         let z = copy_borrowed_ptr(&mut y);
+   |                                   ------ borrow of `*y.pointer` occurs here
+LL |         *y.pointer += 1;
+   |         ^^^^^^^^^^^^^^^ assignment to borrowed `*y.pointer` occurs here
+...
+LL |         *z.pointer += 1;
+   |         --------------- borrow later used here
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0503, E0506.
+For more information about an error, try `rustc --explain E0503`.
diff --git a/src/test/ui/issues/issue-45697.rs b/src/test/ui/issues/issue-45697.rs
new file mode 100644
index 0000000..5bb3043
--- /dev/null
+++ b/src/test/ui/issues/issue-45697.rs
@@ -0,0 +1,26 @@
+// Test that assignments to an `&mut` pointer which is found in a
+// borrowed (but otherwise non-aliasable) location is illegal.
+
+// compile-flags: -Z borrowck=compare -C overflow-checks=off
+
+struct S<'a> {
+    pointer: &'a mut isize
+}
+
+fn copy_borrowed_ptr<'a>(p: &'a mut S<'a>) -> S<'a> {
+    S { pointer: &mut *p.pointer }
+}
+
+fn main() {
+    let mut x = 1;
+
+    {
+        let mut y = S { pointer: &mut x };
+        let z = copy_borrowed_ptr(&mut y);
+        *y.pointer += 1;
+        //~^ ERROR cannot assign to `*y.pointer` because it is borrowed (Ast) [E0506]
+        //~| ERROR cannot use `*y.pointer` because it was mutably borrowed (Mir) [E0503]
+        //~| ERROR cannot assign to `*y.pointer` because it is borrowed (Mir) [E0506]
+        *z.pointer += 1;
+    }
+}
diff --git a/src/test/ui/issues/issue-45697.stderr b/src/test/ui/issues/issue-45697.stderr
new file mode 100644
index 0000000..5085d36
--- /dev/null
+++ b/src/test/ui/issues/issue-45697.stderr
@@ -0,0 +1,34 @@
+error[E0506]: cannot assign to `*y.pointer` because it is borrowed (Ast)
+  --> $DIR/issue-45697.rs:20:9
+   |
+LL |         let z = copy_borrowed_ptr(&mut y);
+   |                                        - borrow of `*y.pointer` occurs here
+LL |         *y.pointer += 1;
+   |         ^^^^^^^^^^^^^^^ assignment to borrowed `*y.pointer` occurs here
+
+error[E0503]: cannot use `*y.pointer` because it was mutably borrowed (Mir)
+  --> $DIR/issue-45697.rs:20:9
+   |
+LL |         let z = copy_borrowed_ptr(&mut y);
+   |                                   ------ borrow of `y` occurs here
+LL |         *y.pointer += 1;
+   |         ^^^^^^^^^^^^^^^ use of borrowed `y`
+...
+LL |         *z.pointer += 1;
+   |         --------------- borrow later used here
+
+error[E0506]: cannot assign to `*y.pointer` because it is borrowed (Mir)
+  --> $DIR/issue-45697.rs:20:9
+   |
+LL |         let z = copy_borrowed_ptr(&mut y);
+   |                                   ------ borrow of `*y.pointer` occurs here
+LL |         *y.pointer += 1;
+   |         ^^^^^^^^^^^^^^^ assignment to borrowed `*y.pointer` occurs here
+...
+LL |         *z.pointer += 1;
+   |         --------------- borrow later used here
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0503, E0506.
+For more information about an error, try `rustc --explain E0503`.
diff --git a/src/test/ui/issues/issue-45729-unsafe-in-generator.rs b/src/test/ui/issues/issue-45729-unsafe-in-generator.rs
new file mode 100644
index 0000000..638a199
--- /dev/null
+++ b/src/test/ui/issues/issue-45729-unsafe-in-generator.rs
@@ -0,0 +1,9 @@
+#![feature(generators)]
+
+fn main() {
+    let _ = || {
+        *(1 as *mut u32) = 42;
+        //~^ ERROR dereference of raw pointer is unsafe
+        yield;
+    };
+}
diff --git a/src/test/ui/issues/issue-45729-unsafe-in-generator.stderr b/src/test/ui/issues/issue-45729-unsafe-in-generator.stderr
new file mode 100644
index 0000000..2aab680
--- /dev/null
+++ b/src/test/ui/issues/issue-45729-unsafe-in-generator.stderr
@@ -0,0 +1,11 @@
+error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
+  --> $DIR/issue-45729-unsafe-in-generator.rs:5:9
+   |
+LL |         *(1 as *mut u32) = 42;
+   |         ^^^^^^^^^^^^^^^^^^^^^ dereference of raw pointer
+   |
+   = note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/issues/issue-45730.rs b/src/test/ui/issues/issue-45730.rs
new file mode 100644
index 0000000..5709125
--- /dev/null
+++ b/src/test/ui/issues/issue-45730.rs
@@ -0,0 +1,9 @@
+use std::fmt;
+fn main() {
+    let x: *const _ = 0 as _; //~ ERROR cannot cast
+
+    let x: *const _ = 0 as *const _; //~ ERROR cannot cast
+    let y: Option<*const fmt::Debug> = Some(x) as _;
+
+    let x = 0 as *const i32 as *const _ as *mut _; //~ ERROR cannot cast
+}
diff --git a/src/test/ui/issues/issue-45730.stderr b/src/test/ui/issues/issue-45730.stderr
new file mode 100644
index 0000000..3c400d6
--- /dev/null
+++ b/src/test/ui/issues/issue-45730.stderr
@@ -0,0 +1,33 @@
+error[E0641]: cannot cast to a pointer of an unknown kind
+  --> $DIR/issue-45730.rs:3:23
+   |
+LL |     let x: *const _ = 0 as _;
+   |                       ^^^^^-
+   |                            |
+   |                            help: consider giving more type information
+   |
+   = note: The type information given here is insufficient to check whether the pointer cast is valid
+
+error[E0641]: cannot cast to a pointer of an unknown kind
+  --> $DIR/issue-45730.rs:5:23
+   |
+LL |     let x: *const _ = 0 as *const _;
+   |                       ^^^^^--------
+   |                            |
+   |                            help: consider giving more type information
+   |
+   = note: The type information given here is insufficient to check whether the pointer cast is valid
+
+error[E0641]: cannot cast to a pointer of an unknown kind
+  --> $DIR/issue-45730.rs:8:13
+   |
+LL |     let x = 0 as *const i32 as *const _ as *mut _;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^------
+   |                                            |
+   |                                            help: consider giving more type information
+   |
+   = note: The type information given here is insufficient to check whether the pointer cast is valid
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0641`.
diff --git a/src/test/ui/issues/issue-45799-bad-extern-crate-rename-suggestion-formatting.fixed b/src/test/ui/issues/issue-45799-bad-extern-crate-rename-suggestion-formatting.fixed
new file mode 100644
index 0000000..b463848
--- /dev/null
+++ b/src/test/ui/issues/issue-45799-bad-extern-crate-rename-suggestion-formatting.fixed
@@ -0,0 +1,5 @@
+// run-rustfix
+
+extern crate std as other_std;
+fn main() {}
+//~^^ ERROR the name `std` is defined multiple times [E0259]
diff --git a/src/test/ui/issues/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs b/src/test/ui/issues/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs
new file mode 100644
index 0000000..1b491ac
--- /dev/null
+++ b/src/test/ui/issues/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs
@@ -0,0 +1,5 @@
+// run-rustfix
+
+extern crate std;
+fn main() {}
+//~^^ ERROR the name `std` is defined multiple times [E0259]
diff --git a/src/test/ui/issues/issue-45799-bad-extern-crate-rename-suggestion-formatting.stderr b/src/test/ui/issues/issue-45799-bad-extern-crate-rename-suggestion-formatting.stderr
new file mode 100644
index 0000000..25aca4c
--- /dev/null
+++ b/src/test/ui/issues/issue-45799-bad-extern-crate-rename-suggestion-formatting.stderr
@@ -0,0 +1,15 @@
+error[E0259]: the name `std` is defined multiple times
+  --> $DIR/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs:3:1
+   |
+LL | extern crate std;
+   | ^^^^^^^^^^^^^^^^^ `std` reimported here
+   |
+   = note: `std` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | extern crate std as other_std;
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0259`.
diff --git a/src/test/ui/issues/issue-45801.rs b/src/test/ui/issues/issue-45801.rs
new file mode 100644
index 0000000..780baa8
--- /dev/null
+++ b/src/test/ui/issues/issue-45801.rs
@@ -0,0 +1,25 @@
+struct Params;
+
+pub trait Plugin<E: ?Sized> {
+    type Error;
+}
+
+pub trait Pluggable {
+    fn get_ref<P: Plugin<Self>>(&mut self) -> Option<P::Error> {
+        None
+    }
+}
+
+struct Foo;
+impl Plugin<Foo> for Params {
+    type Error = ();
+}
+
+impl<T: Copy> Pluggable for T {}
+
+fn handle(req: &mut i32) {
+    req.get_ref::<Params>();
+    //~^ ERROR the trait bound `Params: Plugin<i32>` is not satisfied
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-45801.stderr b/src/test/ui/issues/issue-45801.stderr
new file mode 100644
index 0000000..099cf4e
--- /dev/null
+++ b/src/test/ui/issues/issue-45801.stderr
@@ -0,0 +1,12 @@
+error[E0277]: the trait bound `Params: Plugin<i32>` is not satisfied
+  --> $DIR/issue-45801.rs:21:9
+   |
+LL |     req.get_ref::<Params>();
+   |         ^^^^^^^ the trait `Plugin<i32>` is not implemented for `Params`
+   |
+   = help: the following implementations were found:
+             <Params as Plugin<Foo>>
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-45829/auxiliary/issue-45829-a.rs b/src/test/ui/issues/issue-45829/auxiliary/issue-45829-a.rs
new file mode 100644
index 0000000..e9f7fef
--- /dev/null
+++ b/src/test/ui/issues/issue-45829/auxiliary/issue-45829-a.rs
@@ -0,0 +1 @@
+pub const FOO: usize = *&0;
diff --git a/src/test/ui/issues/issue-45829/auxiliary/issue-45829-b.rs b/src/test/ui/issues/issue-45829/auxiliary/issue-45829-b.rs
new file mode 100644
index 0000000..e9f7fef
--- /dev/null
+++ b/src/test/ui/issues/issue-45829/auxiliary/issue-45829-b.rs
@@ -0,0 +1 @@
+pub const FOO: usize = *&0;
diff --git a/src/test/ui/issues/issue-45829/import-self.rs b/src/test/ui/issues/issue-45829/import-self.rs
new file mode 100644
index 0000000..6cb18e1
--- /dev/null
+++ b/src/test/ui/issues/issue-45829/import-self.rs
@@ -0,0 +1,19 @@
+mod foo {
+    pub struct A;
+    pub struct B;
+}
+
+use foo::{self};
+//~^ ERROR is defined multiple times
+
+use foo as self;
+//~^ ERROR expected identifier
+
+use foo::self;
+//~^ ERROR `self` imports are only allowed within a { } list
+
+use foo::A;
+use foo::{self as A};
+//~^ ERROR is defined multiple times
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-45829/import-self.stderr b/src/test/ui/issues/issue-45829/import-self.stderr
new file mode 100644
index 0000000..2a7277b
--- /dev/null
+++ b/src/test/ui/issues/issue-45829/import-self.stderr
@@ -0,0 +1,45 @@
+error: expected identifier, found keyword `self`
+  --> $DIR/import-self.rs:9:12
+   |
+LL | use foo as self;
+   |            ^^^^ expected identifier, found keyword
+
+error[E0429]: `self` imports are only allowed within a { } list
+  --> $DIR/import-self.rs:12:5
+   |
+LL | use foo::self;
+   |     ^^^^^^^^^
+
+error[E0255]: the name `foo` is defined multiple times
+  --> $DIR/import-self.rs:6:11
+   |
+LL | mod foo {
+   | ------- previous definition of the module `foo` here
+...
+LL | use foo::{self};
+   |           ^^^^ `foo` reimported here
+   |
+   = note: `foo` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | use foo::{self as other_foo};
+   |           ^^^^^^^^^^^^^^^^^
+
+error[E0252]: the name `A` is defined multiple times
+  --> $DIR/import-self.rs:16:11
+   |
+LL | use foo::A;
+   |     ------ previous import of the type `A` here
+LL | use foo::{self as A};
+   |           ^^^^^^^^^ `A` reimported here
+   |
+   = note: `A` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | use foo::{self as OtherA};
+   |           ^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0252, E0255, E0429.
+For more information about an error, try `rustc --explain E0252`.
diff --git a/src/test/ui/issues/issue-45829/import-twice.rs b/src/test/ui/issues/issue-45829/import-twice.rs
new file mode 100644
index 0000000..e5a8bb7
--- /dev/null
+++ b/src/test/ui/issues/issue-45829/import-twice.rs
@@ -0,0 +1,9 @@
+mod foo {
+    pub struct A;
+    pub struct B;
+}
+
+use foo::{A, A};
+//~^ ERROR is defined multiple times
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-45829/import-twice.stderr b/src/test/ui/issues/issue-45829/import-twice.stderr
new file mode 100644
index 0000000..656b011
--- /dev/null
+++ b/src/test/ui/issues/issue-45829/import-twice.stderr
@@ -0,0 +1,13 @@
+error[E0252]: the name `A` is defined multiple times
+  --> $DIR/import-twice.rs:6:14
+   |
+LL | use foo::{A, A};
+   |           -  ^ `A` reimported here
+   |           |
+   |           previous import of the type `A` here
+   |
+   = note: `A` must be defined only once in the type namespace of this module
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0252`.
diff --git a/src/test/ui/issues/issue-45829/issue-45829.rs b/src/test/ui/issues/issue-45829/issue-45829.rs
new file mode 100644
index 0000000..1e76e4b
--- /dev/null
+++ b/src/test/ui/issues/issue-45829/issue-45829.rs
@@ -0,0 +1,9 @@
+mod foo {
+    pub struct A;
+    pub struct B;
+}
+
+use foo::{A, B as A};
+//~^ ERROR is defined multiple times
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-45829/issue-45829.stderr b/src/test/ui/issues/issue-45829/issue-45829.stderr
new file mode 100644
index 0000000..a7ebc71
--- /dev/null
+++ b/src/test/ui/issues/issue-45829/issue-45829.stderr
@@ -0,0 +1,17 @@
+error[E0252]: the name `A` is defined multiple times
+  --> $DIR/issue-45829.rs:6:14
+   |
+LL | use foo::{A, B as A};
+   |           -  ^^^^^^ `A` reimported here
+   |           |
+   |           previous import of the type `A` here
+   |
+   = note: `A` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | use foo::{A, B as OtherA};
+   |              ^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0252`.
diff --git a/src/test/ui/issues/issue-45829/rename-extern-vs-use.rs b/src/test/ui/issues/issue-45829/rename-extern-vs-use.rs
new file mode 100644
index 0000000..aef7aa3
--- /dev/null
+++ b/src/test/ui/issues/issue-45829/rename-extern-vs-use.rs
@@ -0,0 +1,11 @@
+// aux-build:issue-45829-b.rs
+
+mod foo {
+    pub mod bar {}
+}
+
+use foo::bar;
+extern crate issue_45829_b as bar;
+//~^ ERROR the name `bar` is defined multiple times
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-45829/rename-extern-vs-use.stderr b/src/test/ui/issues/issue-45829/rename-extern-vs-use.stderr
new file mode 100644
index 0000000..98fd8a6
--- /dev/null
+++ b/src/test/ui/issues/issue-45829/rename-extern-vs-use.stderr
@@ -0,0 +1,17 @@
+error[E0254]: the name `bar` is defined multiple times
+  --> $DIR/rename-extern-vs-use.rs:8:1
+   |
+LL | use foo::bar;
+   |     -------- previous import of the module `bar` here
+LL | extern crate issue_45829_b as bar;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `bar` reimported here
+   |
+   = note: `bar` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | extern crate issue_45829_b as other_bar;
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0254`.
diff --git a/src/test/ui/issues/issue-45829/rename-extern-with-tab.rs b/src/test/ui/issues/issue-45829/rename-extern-with-tab.rs
new file mode 100644
index 0000000..0da8b82
--- /dev/null
+++ b/src/test/ui/issues/issue-45829/rename-extern-with-tab.rs
@@ -0,0 +1,8 @@
+// aux-build:issue-45829-a.rs
+// aux-build:issue-45829-b.rs
+
+extern crate issue_45829_a;
+extern  crate    issue_45829_b  as  issue_45829_a;
+//~^ ERROR is defined multiple times
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-45829/rename-extern-with-tab.stderr b/src/test/ui/issues/issue-45829/rename-extern-with-tab.stderr
new file mode 100644
index 0000000..2c4e8ce
--- /dev/null
+++ b/src/test/ui/issues/issue-45829/rename-extern-with-tab.stderr
@@ -0,0 +1,17 @@
+error[E0259]: the name `issue_45829_a` is defined multiple times
+  --> $DIR/rename-extern-with-tab.rs:5:1
+   |
+LL | extern crate issue_45829_a;
+   | --------------------------- previous import of the extern crate `issue_45829_a` here
+LL | extern  crate    issue_45829_b  as  issue_45829_a;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `issue_45829_a` reimported here
+   |
+   = note: `issue_45829_a` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | extern crate issue_45829_b as other_issue_45829_a;
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0259`.
diff --git a/src/test/ui/issues/issue-45829/rename-extern.rs b/src/test/ui/issues/issue-45829/rename-extern.rs
new file mode 100644
index 0000000..7dbda69
--- /dev/null
+++ b/src/test/ui/issues/issue-45829/rename-extern.rs
@@ -0,0 +1,8 @@
+// aux-build:issue-45829-a.rs
+// aux-build:issue-45829-b.rs
+
+extern crate issue_45829_a;
+extern crate issue_45829_b as issue_45829_a;
+//~^ ERROR is defined multiple times
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-45829/rename-extern.stderr b/src/test/ui/issues/issue-45829/rename-extern.stderr
new file mode 100644
index 0000000..209ae22
--- /dev/null
+++ b/src/test/ui/issues/issue-45829/rename-extern.stderr
@@ -0,0 +1,17 @@
+error[E0259]: the name `issue_45829_a` is defined multiple times
+  --> $DIR/rename-extern.rs:5:1
+   |
+LL | extern crate issue_45829_a;
+   | --------------------------- previous import of the extern crate `issue_45829_a` here
+LL | extern crate issue_45829_b as issue_45829_a;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `issue_45829_a` reimported here
+   |
+   = note: `issue_45829_a` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | extern crate issue_45829_b as other_issue_45829_a;
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0259`.
diff --git a/src/test/ui/issues/issue-45829/rename-use-vs-extern.rs b/src/test/ui/issues/issue-45829/rename-use-vs-extern.rs
new file mode 100644
index 0000000..0cf3a77
--- /dev/null
+++ b/src/test/ui/issues/issue-45829/rename-use-vs-extern.rs
@@ -0,0 +1,7 @@
+// aux-build:issue-45829-b.rs
+
+extern crate issue_45829_b;
+use std as issue_45829_b;
+//~^ ERROR is defined multiple times
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-45829/rename-use-vs-extern.stderr b/src/test/ui/issues/issue-45829/rename-use-vs-extern.stderr
new file mode 100644
index 0000000..6b917d5
--- /dev/null
+++ b/src/test/ui/issues/issue-45829/rename-use-vs-extern.stderr
@@ -0,0 +1,17 @@
+error[E0254]: the name `issue_45829_b` is defined multiple times
+  --> $DIR/rename-use-vs-extern.rs:4:5
+   |
+LL | extern crate issue_45829_b;
+   | --------------------------- previous import of the extern crate `issue_45829_b` here
+LL | use std as issue_45829_b;
+   |     ^^^^^^^^^^^^^^^^^^^^ `issue_45829_b` reimported here
+   |
+   = note: `issue_45829_b` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | use std as other_issue_45829_b;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0254`.
diff --git a/src/test/ui/issues/issue-45829/rename-use-with-tabs.rs b/src/test/ui/issues/issue-45829/rename-use-with-tabs.rs
new file mode 100644
index 0000000..86c5fa0
--- /dev/null
+++ b/src/test/ui/issues/issue-45829/rename-use-with-tabs.rs
@@ -0,0 +1,12 @@
+mod foo {
+    pub struct A;
+
+    pub mod bar {
+        pub struct B;
+    }
+}
+
+use foo::{A, bar::B    as    A};
+//~^ ERROR is defined multiple times
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-45829/rename-use-with-tabs.stderr b/src/test/ui/issues/issue-45829/rename-use-with-tabs.stderr
new file mode 100644
index 0000000..3baad6c
--- /dev/null
+++ b/src/test/ui/issues/issue-45829/rename-use-with-tabs.stderr
@@ -0,0 +1,17 @@
+error[E0252]: the name `A` is defined multiple times
+  --> $DIR/rename-use-with-tabs.rs:9:14
+   |
+LL | use foo::{A, bar::B    as    A};
+   |           -  ^^^^^^^^^^^^^^^^^ `A` reimported here
+   |           |
+   |           previous import of the type `A` here
+   |
+   = note: `A` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | use foo::{A, bar::B as OtherA};
+   |              ^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0252`.
diff --git a/src/test/ui/issues/issue-45829/rename-with-path.rs b/src/test/ui/issues/issue-45829/rename-with-path.rs
new file mode 100644
index 0000000..e278a87
--- /dev/null
+++ b/src/test/ui/issues/issue-45829/rename-with-path.rs
@@ -0,0 +1,4 @@
+use std::{collections::HashMap as A, sync::Arc as A};
+//~^ ERROR is defined multiple times
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-45829/rename-with-path.stderr b/src/test/ui/issues/issue-45829/rename-with-path.stderr
new file mode 100644
index 0000000..ba83eea
--- /dev/null
+++ b/src/test/ui/issues/issue-45829/rename-with-path.stderr
@@ -0,0 +1,17 @@
+error[E0252]: the name `A` is defined multiple times
+  --> $DIR/rename-with-path.rs:1:38
+   |
+LL | use std::{collections::HashMap as A, sync::Arc as A};
+   |           -------------------------  ^^^^^^^^^^^^^^ `A` reimported here
+   |           |
+   |           previous import of the type `A` here
+   |
+   = note: `A` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | use std::{collections::HashMap as A, sync::Arc as OtherA};
+   |                                      ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0252`.
diff --git a/src/test/ui/issues/issue-45829/rename.rs b/src/test/ui/issues/issue-45829/rename.rs
new file mode 100644
index 0000000..1c45956
--- /dev/null
+++ b/src/test/ui/issues/issue-45829/rename.rs
@@ -0,0 +1,7 @@
+use core;
+use std as core;
+//~^ ERROR is defined multiple times
+
+fn main() {
+    1 + 1;
+}
diff --git a/src/test/ui/issues/issue-45829/rename.stderr b/src/test/ui/issues/issue-45829/rename.stderr
new file mode 100644
index 0000000..8f12d92
--- /dev/null
+++ b/src/test/ui/issues/issue-45829/rename.stderr
@@ -0,0 +1,17 @@
+error[E0252]: the name `core` is defined multiple times
+  --> $DIR/rename.rs:2:5
+   |
+LL | use core;
+   |     ---- previous import of the module `core` here
+LL | use std as core;
+   |     ^^^^^^^^^^^ `core` reimported here
+   |
+   = note: `core` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | use std as other_core;
+   |     ^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0252`.
diff --git a/src/test/ui/issues/issue-45965.rs b/src/test/ui/issues/issue-45965.rs
new file mode 100644
index 0000000..15649f7
--- /dev/null
+++ b/src/test/ui/issues/issue-45965.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let a = |r: f64| if r != 0.0(r != 0.0) { 1.0 } else { 0.0 };
+    //~^ ERROR expected function, found `{float}`
+}
diff --git a/src/test/ui/issues/issue-45965.stderr b/src/test/ui/issues/issue-45965.stderr
new file mode 100644
index 0000000..f3eaa91
--- /dev/null
+++ b/src/test/ui/issues/issue-45965.stderr
@@ -0,0 +1,11 @@
+error[E0618]: expected function, found `{float}`
+  --> $DIR/issue-45965.rs:2:30
+   |
+LL |     let a = |r: f64| if r != 0.0(r != 0.0) { 1.0 } else { 0.0 };
+   |                              ^^^----------
+   |                              |
+   |                              call expression requires function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0618`.
diff --git a/src/test/ui/issues/issue-46023.ast.nll.stderr b/src/test/ui/issues/issue-46023.ast.nll.stderr
new file mode 100644
index 0000000..05dbe42
--- /dev/null
+++ b/src/test/ui/issues/issue-46023.ast.nll.stderr
@@ -0,0 +1,12 @@
+error[E0594]: cannot assign to `x`, as it is not declared as mutable
+  --> $DIR/issue-46023.rs:8:9
+   |
+LL |     let x = 0;
+   |         - help: consider changing this to be mutable: `mut x`
+...
+LL |         x = 1;
+   |         ^^^^^ cannot assign
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/issues/issue-46023.ast.stderr b/src/test/ui/issues/issue-46023.ast.stderr
new file mode 100644
index 0000000..ace48f8
--- /dev/null
+++ b/src/test/ui/issues/issue-46023.ast.stderr
@@ -0,0 +1,12 @@
+error[E0594]: cannot assign to captured outer variable in an `FnMut` closure
+  --> $DIR/issue-46023.rs:8:9
+   |
+LL |     let x = 0;
+   |         - help: consider making `x` mutable: `mut x`
+...
+LL |         x = 1;
+   |         ^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/issues/issue-46023.mir.stderr b/src/test/ui/issues/issue-46023.mir.stderr
new file mode 100644
index 0000000..05dbe42
--- /dev/null
+++ b/src/test/ui/issues/issue-46023.mir.stderr
@@ -0,0 +1,12 @@
+error[E0594]: cannot assign to `x`, as it is not declared as mutable
+  --> $DIR/issue-46023.rs:8:9
+   |
+LL |     let x = 0;
+   |         - help: consider changing this to be mutable: `mut x`
+...
+LL |         x = 1;
+   |         ^^^^^ cannot assign
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/issues/issue-46023.rs b/src/test/ui/issues/issue-46023.rs
new file mode 100644
index 0000000..a9ecbbe
--- /dev/null
+++ b/src/test/ui/issues/issue-46023.rs
@@ -0,0 +1,12 @@
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+fn main() {
+    let x = 0;
+
+    (move || {
+        x = 1;
+        //[mir]~^ ERROR cannot assign to `x`, as it is not declared as mutable [E0594]
+        //[ast]~^^ ERROR cannot assign to captured outer variable in an `FnMut` closure [E0594]
+    })()
+}
diff --git a/src/test/ui/issues/issue-46036.rs b/src/test/ui/issues/issue-46036.rs
new file mode 100644
index 0000000..c517bbe
--- /dev/null
+++ b/src/test/ui/issues/issue-46036.rs
@@ -0,0 +1,13 @@
+// Issue 46036: [NLL] false edges on infinite loops
+// Infinite loops should create false edges to the cleanup block.
+#![feature(nll)]
+
+struct Foo { x: &'static u32 }
+
+fn foo() {
+    let a = 3;
+    let foo = Foo { x: &a }; //~ ERROR E0597
+    loop { }
+}
+
+fn main() { }
diff --git a/src/test/ui/issues/issue-46036.stderr b/src/test/ui/issues/issue-46036.stderr
new file mode 100644
index 0000000..9c1746e
--- /dev/null
+++ b/src/test/ui/issues/issue-46036.stderr
@@ -0,0 +1,15 @@
+error[E0597]: `a` does not live long enough
+  --> $DIR/issue-46036.rs:9:24
+   |
+LL |     let foo = Foo { x: &a };
+   |                        ^^
+   |                        |
+   |                        borrowed value does not live long enough
+   |                        requires that `a` is borrowed for `'static`
+LL |     loop { }
+LL | }
+   | - `a` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/issues/issue-46101.rs b/src/test/ui/issues/issue-46101.rs
new file mode 100644
index 0000000..2d9111e
--- /dev/null
+++ b/src/test/ui/issues/issue-46101.rs
@@ -0,0 +1,4 @@
+#![feature(use_extern_macros)]
+trait Foo {}
+#[derive(Foo::Anything)] //~ ERROR failed to resolve: partially resolved path in a derive macro
+struct S;
diff --git a/src/test/ui/issues/issue-46101.stderr b/src/test/ui/issues/issue-46101.stderr
new file mode 100644
index 0000000..3ad5383
--- /dev/null
+++ b/src/test/ui/issues/issue-46101.stderr
@@ -0,0 +1,14 @@
+error[E0433]: failed to resolve: partially resolved path in a derive macro
+  --> $DIR/issue-46101.rs:3:10
+   |
+LL | #[derive(Foo::Anything)]
+   |          ^^^^^^^^^^^^^ partially resolved path in a derive macro
+
+error[E0601]: `main` function not found in crate `issue_46101`
+   |
+   = note: consider adding a `main` function to `$DIR/issue-46101.rs`
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0433, E0601.
+For more information about an error, try `rustc --explain E0433`.
diff --git a/src/test/ui/issues/issue-46112.rs b/src/test/ui/issues/issue-46112.rs
new file mode 100644
index 0000000..0cdd2c2
--- /dev/null
+++ b/src/test/ui/issues/issue-46112.rs
@@ -0,0 +1,10 @@
+// Issue 46112: An extern crate pub re-exporting libcore was causing
+// paths rooted from `std` to be misrendered in the diagnostic output.
+
+// ignore-windows
+// aux-build:xcrate-issue-46112-rexport-core.rs
+
+extern crate xcrate_issue_46112_rexport_core;
+fn test(r: Result<Option<()>, &'static str>) { }
+fn main() { test(Ok(())); }
+//~^ mismatched types
diff --git a/src/test/ui/issues/issue-46112.stderr b/src/test/ui/issues/issue-46112.stderr
new file mode 100644
index 0000000..939d945
--- /dev/null
+++ b/src/test/ui/issues/issue-46112.stderr
@@ -0,0 +1,15 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-46112.rs:9:21
+   |
+LL | fn main() { test(Ok(())); }
+   |                     ^^
+   |                     |
+   |                     expected enum `std::option::Option`, found ()
+   |                     help: try using a variant of the expected type: `Some(())`
+   |
+   = note: expected type `std::option::Option<()>`
+              found type `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-46186.rs b/src/test/ui/issues/issue-46186.rs
new file mode 100644
index 0000000..9dfd61f
--- /dev/null
+++ b/src/test/ui/issues/issue-46186.rs
@@ -0,0 +1,6 @@
+struct Struct {
+    a: usize,
+};
+//~^ ERROR expected item, found `;`
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-46186.stderr b/src/test/ui/issues/issue-46186.stderr
new file mode 100644
index 0000000..eb0dbb8
--- /dev/null
+++ b/src/test/ui/issues/issue-46186.stderr
@@ -0,0 +1,10 @@
+error: expected item, found `;`
+  --> $DIR/issue-46186.rs:3:2
+   |
+LL | };
+   |  ^ help: remove this semicolon
+   |
+   = help: braced struct declarations are not followed by a semicolon
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-46302.rs b/src/test/ui/issues/issue-46302.rs
new file mode 100644
index 0000000..ba681d8
--- /dev/null
+++ b/src/test/ui/issues/issue-46302.rs
@@ -0,0 +1,9 @@
+fn foo() {
+  let s = "abc";
+  let u: &str = if true { s[..2] } else { s };
+  //~^ ERROR mismatched types
+}
+
+fn main() {
+    foo();
+}
diff --git a/src/test/ui/issues/issue-46302.stderr b/src/test/ui/issues/issue-46302.stderr
new file mode 100644
index 0000000..8eb3a4d
--- /dev/null
+++ b/src/test/ui/issues/issue-46302.stderr
@@ -0,0 +1,15 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-46302.rs:3:27
+   |
+LL |   let u: &str = if true { s[..2] } else { s };
+   |                           ^^^^^^
+   |                           |
+   |                           expected &str, found str
+   |                           help: consider borrowing here: `&s[..2]`
+   |
+   = note: expected type `&str`
+              found type `str`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-46311.rs b/src/test/ui/issues/issue-46311.rs
new file mode 100644
index 0000000..1233a49
--- /dev/null
+++ b/src/test/ui/issues/issue-46311.rs
@@ -0,0 +1,4 @@
+fn main() {
+    'break: loop { //~ ERROR invalid label name `'break`
+    }
+}
diff --git a/src/test/ui/issues/issue-46311.stderr b/src/test/ui/issues/issue-46311.stderr
new file mode 100644
index 0000000..d72d647
--- /dev/null
+++ b/src/test/ui/issues/issue-46311.stderr
@@ -0,0 +1,8 @@
+error: invalid label name `'break`
+  --> $DIR/issue-46311.rs:2:5
+   |
+LL |     'break: loop {
+   |     ^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-46332.rs b/src/test/ui/issues/issue-46332.rs
new file mode 100644
index 0000000..bed74e3
--- /dev/null
+++ b/src/test/ui/issues/issue-46332.rs
@@ -0,0 +1,11 @@
+// Original Levenshtein distance for both of this is 1. We improved accuracy with
+// additional case insensitive comparison.
+
+struct TyUint {}
+
+struct TyInt {}
+
+fn main() {
+    TyUInt {};
+    //~^ ERROR cannot find struct, variant or union type `TyUInt` in this scope
+}
diff --git a/src/test/ui/issues/issue-46332.stderr b/src/test/ui/issues/issue-46332.stderr
new file mode 100644
index 0000000..812a500
--- /dev/null
+++ b/src/test/ui/issues/issue-46332.stderr
@@ -0,0 +1,9 @@
+error[E0422]: cannot find struct, variant or union type `TyUInt` in this scope
+  --> $DIR/issue-46332.rs:9:5
+   |
+LL |     TyUInt {};
+   |     ^^^^^^ help: a struct with a similar name exists: `TyUint`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0422`.
diff --git a/src/test/ui/issues/issue-46438.rs b/src/test/ui/issues/issue-46438.rs
new file mode 100644
index 0000000..d78b958
--- /dev/null
+++ b/src/test/ui/issues/issue-46438.rs
@@ -0,0 +1,13 @@
+macro_rules! m {
+    ($my_type: ty) => {
+        impl $my_type for u8 {}
+    }
+}
+
+trait Tr {}
+
+m!(Tr);
+
+m!(&'static u8); //~ ERROR expected a trait, found type
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-46438.stderr b/src/test/ui/issues/issue-46438.stderr
new file mode 100644
index 0000000..c1fad44
--- /dev/null
+++ b/src/test/ui/issues/issue-46438.stderr
@@ -0,0 +1,8 @@
+error: expected a trait, found type
+  --> $DIR/issue-46438.rs:11:4
+   |
+LL | m!(&'static u8);
+   |    ^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-46471-1.rs b/src/test/ui/issues/issue-46471-1.rs
new file mode 100644
index 0000000..3cf3f35
--- /dev/null
+++ b/src/test/ui/issues/issue-46471-1.rs
@@ -0,0 +1,11 @@
+// compile-flags: -Z borrowck=compare
+
+fn main() {
+    let y = {
+        let mut z = 0;
+        &mut z
+    };
+    //~^^ ERROR `z` does not live long enough (Ast) [E0597]
+    //~| ERROR `z` does not live long enough (Mir) [E0597]
+    println!("{}", y);
+}
diff --git a/src/test/ui/issues/issue-46471-1.stderr b/src/test/ui/issues/issue-46471-1.stderr
new file mode 100644
index 0000000..51026c9
--- /dev/null
+++ b/src/test/ui/issues/issue-46471-1.stderr
@@ -0,0 +1,25 @@
+error[E0597]: `z` does not live long enough (Ast)
+  --> $DIR/issue-46471-1.rs:6:14
+   |
+LL |         &mut z
+   |              ^ borrowed value does not live long enough
+LL |     };
+   |     - `z` dropped here while still borrowed
+...
+LL | }
+   | - borrowed value needs to live until here
+
+error[E0597]: `z` does not live long enough (Mir)
+  --> $DIR/issue-46471-1.rs:6:9
+   |
+LL |         &mut z
+   |         ^^^^^^
+   |         |
+   |         borrowed value does not live long enough
+   |         borrow later used here
+LL |     };
+   |     - `z` dropped here while still borrowed
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/issues/issue-46471.rs b/src/test/ui/issues/issue-46471.rs
new file mode 100644
index 0000000..0905c8b
--- /dev/null
+++ b/src/test/ui/issues/issue-46471.rs
@@ -0,0 +1,10 @@
+// compile-flags: -Z borrowck=compare
+
+fn foo() -> &'static u32 {
+    let x = 0;
+    &x
+    //~^ ERROR `x` does not live long enough (Ast) [E0597]
+    //~| ERROR cannot return reference to local variable `x` (Mir) [E0515]
+}
+
+fn main() { }
diff --git a/src/test/ui/issues/issue-46471.stderr b/src/test/ui/issues/issue-46471.stderr
new file mode 100644
index 0000000..903b658
--- /dev/null
+++ b/src/test/ui/issues/issue-46471.stderr
@@ -0,0 +1,21 @@
+error[E0597]: `x` does not live long enough (Ast)
+  --> $DIR/issue-46471.rs:5:6
+   |
+LL |     &x
+   |      ^ borrowed value does not live long enough
+...
+LL | }
+   | - borrowed value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0515]: cannot return reference to local variable `x` (Mir)
+  --> $DIR/issue-46471.rs:5:5
+   |
+LL |     &x
+   |     ^^ returns a reference to data owned by the current function
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0515, E0597.
+For more information about an error, try `rustc --explain E0515`.
diff --git a/src/test/ui/issues/issue-46472.rs b/src/test/ui/issues/issue-46472.rs
new file mode 100644
index 0000000..88f97e9
--- /dev/null
+++ b/src/test/ui/issues/issue-46472.rs
@@ -0,0 +1,9 @@
+// compile-flags: -Z borrowck=compare
+
+fn bar<'a>() -> &'a mut u32 {
+    &mut 4
+    //~^ ERROR borrowed value does not live long enough (Ast) [E0597]
+    //~| ERROR cannot return reference to temporary value (Mir) [E0515]
+}
+
+fn main() { }
diff --git a/src/test/ui/issues/issue-46472.stderr b/src/test/ui/issues/issue-46472.stderr
new file mode 100644
index 0000000..2d81fa0
--- /dev/null
+++ b/src/test/ui/issues/issue-46472.stderr
@@ -0,0 +1,28 @@
+error[E0597]: borrowed value does not live long enough (Ast)
+  --> $DIR/issue-46472.rs:4:10
+   |
+LL |     &mut 4
+   |          ^ temporary value does not live long enough
+...
+LL | }
+   | - temporary value only lives until here
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 3:8...
+  --> $DIR/issue-46472.rs:3:8
+   |
+LL | fn bar<'a>() -> &'a mut u32 {
+   |        ^^
+
+error[E0515]: cannot return reference to temporary value (Mir)
+  --> $DIR/issue-46472.rs:4:5
+   |
+LL |     &mut 4
+   |     ^^^^^-
+   |     |    |
+   |     |    temporary value created here
+   |     returns a reference to data owned by the current function
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0515, E0597.
+For more information about an error, try `rustc --explain E0515`.
diff --git a/src/test/ui/issues/issue-46576.rs b/src/test/ui/issues/issue-46576.rs
new file mode 100644
index 0000000..821d272
--- /dev/null
+++ b/src/test/ui/issues/issue-46576.rs
@@ -0,0 +1,23 @@
+// ignore-cloudabi no std::fs support
+
+#![allow(dead_code)]
+#![deny(unused_imports)]
+
+use std::fs::File;
+use std::io::{BufRead, BufReader, Read};
+//~^ ERROR unused import: `BufRead`
+
+pub fn read_from_file(path: &str) {
+    let file = File::open(&path).unwrap();
+    let mut reader = BufReader::new(file);
+    let mut s = String::new();
+    reader.read_to_string(&mut s).unwrap();
+}
+
+pub fn read_lines(s: &str) {
+    for _line in s.lines() {
+
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-46576.stderr b/src/test/ui/issues/issue-46576.stderr
new file mode 100644
index 0000000..4b66219
--- /dev/null
+++ b/src/test/ui/issues/issue-46576.stderr
@@ -0,0 +1,14 @@
+error: unused import: `BufRead`
+  --> $DIR/issue-46576.rs:7:15
+   |
+LL | use std::io::{BufRead, BufReader, Read};
+   |               ^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/issue-46576.rs:4:9
+   |
+LL | #![deny(unused_imports)]
+   |         ^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-46604.ast.nll.stderr b/src/test/ui/issues/issue-46604.ast.nll.stderr
new file mode 100644
index 0000000..f43588c
--- /dev/null
+++ b/src/test/ui/issues/issue-46604.ast.nll.stderr
@@ -0,0 +1,16 @@
+error[E0017]: references in statics may only refer to immutable values
+  --> $DIR/issue-46604.rs:4:25
+   |
+LL | static buf: &mut [u8] = &mut [1u8,2,3,4,5,7];
+   |                         ^^^^^^^^^^^^^^^^^^^^ statics require immutable values
+
+error[E0594]: cannot assign to `buf[_]`, as `buf` is an immutable static item
+  --> $DIR/issue-46604.rs:10:5
+   |
+LL |     buf[0]=2;
+   |     ^^^^^^^^ cannot assign
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0017, E0594.
+For more information about an error, try `rustc --explain E0017`.
diff --git a/src/test/ui/issues/issue-46604.ast.stderr b/src/test/ui/issues/issue-46604.ast.stderr
new file mode 100644
index 0000000..2ee1ac2
--- /dev/null
+++ b/src/test/ui/issues/issue-46604.ast.stderr
@@ -0,0 +1,16 @@
+error[E0017]: references in statics may only refer to immutable values
+  --> $DIR/issue-46604.rs:4:25
+   |
+LL | static buf: &mut [u8] = &mut [1u8,2,3,4,5,7];
+   |                         ^^^^^^^^^^^^^^^^^^^^ statics require immutable values
+
+error[E0389]: cannot assign to data in a `&` reference
+  --> $DIR/issue-46604.rs:10:5
+   |
+LL |     buf[0]=2;
+   |     ^^^^^^^^ assignment into an immutable reference
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0017, E0389.
+For more information about an error, try `rustc --explain E0017`.
diff --git a/src/test/ui/issues/issue-46604.mir.stderr b/src/test/ui/issues/issue-46604.mir.stderr
new file mode 100644
index 0000000..f43588c
--- /dev/null
+++ b/src/test/ui/issues/issue-46604.mir.stderr
@@ -0,0 +1,16 @@
+error[E0017]: references in statics may only refer to immutable values
+  --> $DIR/issue-46604.rs:4:25
+   |
+LL | static buf: &mut [u8] = &mut [1u8,2,3,4,5,7];
+   |                         ^^^^^^^^^^^^^^^^^^^^ statics require immutable values
+
+error[E0594]: cannot assign to `buf[_]`, as `buf` is an immutable static item
+  --> $DIR/issue-46604.rs:10:5
+   |
+LL |     buf[0]=2;
+   |     ^^^^^^^^ cannot assign
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0017, E0594.
+For more information about an error, try `rustc --explain E0017`.
diff --git a/src/test/ui/issues/issue-46604.rs b/src/test/ui/issues/issue-46604.rs
new file mode 100644
index 0000000..34fe3af
--- /dev/null
+++ b/src/test/ui/issues/issue-46604.rs
@@ -0,0 +1,12 @@
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+static buf: &mut [u8] = &mut [1u8,2,3,4,5,7];   //[ast]~ ERROR E0017
+                                                //[mir]~^ ERROR E0017
+fn write<T: AsRef<[u8]>>(buffer: T) { }
+
+fn main() {
+    write(&buf);
+    buf[0]=2;                                   //[ast]~ ERROR E0389
+                                                //[mir]~^ ERROR E0594
+}
diff --git a/src/test/ui/issues/issue-46756-consider-borrowing-cast-or-binexpr.fixed b/src/test/ui/issues/issue-46756-consider-borrowing-cast-or-binexpr.fixed
new file mode 100644
index 0000000..8668d8a
--- /dev/null
+++ b/src/test/ui/issues/issue-46756-consider-borrowing-cast-or-binexpr.fixed
@@ -0,0 +1,16 @@
+// run-rustfix
+
+#![allow(unused)]
+
+fn light_flows_our_war_of_mocking_words(and_yet: &usize) -> usize {
+    and_yet + 1
+}
+
+fn main() {
+    let behold: isize = 2;
+    let with_tears: usize = 3;
+    light_flows_our_war_of_mocking_words(&(behold as usize));
+    //~^ ERROR mismatched types [E0308]
+    light_flows_our_war_of_mocking_words(&(with_tears + 4));
+    //~^ ERROR mismatched types [E0308]
+}
diff --git a/src/test/ui/issues/issue-46756-consider-borrowing-cast-or-binexpr.rs b/src/test/ui/issues/issue-46756-consider-borrowing-cast-or-binexpr.rs
new file mode 100644
index 0000000..c849461
--- /dev/null
+++ b/src/test/ui/issues/issue-46756-consider-borrowing-cast-or-binexpr.rs
@@ -0,0 +1,16 @@
+// run-rustfix
+
+#![allow(unused)]
+
+fn light_flows_our_war_of_mocking_words(and_yet: &usize) -> usize {
+    and_yet + 1
+}
+
+fn main() {
+    let behold: isize = 2;
+    let with_tears: usize = 3;
+    light_flows_our_war_of_mocking_words(behold as usize);
+    //~^ ERROR mismatched types [E0308]
+    light_flows_our_war_of_mocking_words(with_tears + 4);
+    //~^ ERROR mismatched types [E0308]
+}
diff --git a/src/test/ui/issues/issue-46756-consider-borrowing-cast-or-binexpr.stderr b/src/test/ui/issues/issue-46756-consider-borrowing-cast-or-binexpr.stderr
new file mode 100644
index 0000000..1eeca3e
--- /dev/null
+++ b/src/test/ui/issues/issue-46756-consider-borrowing-cast-or-binexpr.stderr
@@ -0,0 +1,27 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-46756-consider-borrowing-cast-or-binexpr.rs:12:42
+   |
+LL |     light_flows_our_war_of_mocking_words(behold as usize);
+   |                                          ^^^^^^^^^^^^^^^
+   |                                          |
+   |                                          expected &usize, found usize
+   |                                          help: consider borrowing here: `&(behold as usize)`
+   |
+   = note: expected type `&usize`
+              found type `usize`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-46756-consider-borrowing-cast-or-binexpr.rs:14:42
+   |
+LL |     light_flows_our_war_of_mocking_words(with_tears + 4);
+   |                                          ^^^^^^^^^^^^^^
+   |                                          |
+   |                                          expected &usize, found usize
+   |                                          help: consider borrowing here: `&(with_tears + 4)`
+   |
+   = note: expected type `&usize`
+              found type `usize`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-46771.rs b/src/test/ui/issues/issue-46771.rs
new file mode 100644
index 0000000..2b5241e
--- /dev/null
+++ b/src/test/ui/issues/issue-46771.rs
@@ -0,0 +1,4 @@
+fn main() {
+    struct Foo;
+    (1 .. 2).find(|_| Foo(0) == 0); //~ ERROR expected function, found `main::Foo`
+}
diff --git a/src/test/ui/issues/issue-46771.stderr b/src/test/ui/issues/issue-46771.stderr
new file mode 100644
index 0000000..76c86d7
--- /dev/null
+++ b/src/test/ui/issues/issue-46771.stderr
@@ -0,0 +1,13 @@
+error[E0618]: expected function, found `main::Foo`
+  --> $DIR/issue-46771.rs:3:23
+   |
+LL |     struct Foo;
+   |     ----------- `main::Foo` defined here
+LL |     (1 .. 2).find(|_| Foo(0) == 0);
+   |                       ^^^---
+   |                       |
+   |                       call expression requires function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0618`.
diff --git a/src/test/ui/issues/issue-46843.rs b/src/test/ui/issues/issue-46843.rs
new file mode 100644
index 0000000..a310de6
--- /dev/null
+++ b/src/test/ui/issues/issue-46843.rs
@@ -0,0 +1,12 @@
+enum Thing { This, That }
+
+fn non_const() -> Thing {
+    Thing::This
+}
+
+pub const Q: i32 = match non_const() { //~ ERROR E0015
+    Thing::This => 1, //~ ERROR unimplemented expression type
+    Thing::That => 0
+};
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-46843.stderr b/src/test/ui/issues/issue-46843.stderr
new file mode 100644
index 0000000..c252f0d0
--- /dev/null
+++ b/src/test/ui/issues/issue-46843.stderr
@@ -0,0 +1,16 @@
+error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
+  --> $DIR/issue-46843.rs:7:26
+   |
+LL | pub const Q: i32 = match non_const() {
+   |                          ^^^^^^^^^^^
+
+error[E0019]: constant contains unimplemented expression type
+  --> $DIR/issue-46843.rs:8:5
+   |
+LL |     Thing::This => 1,
+   |     ^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0015, E0019.
+For more information about an error, try `rustc --explain E0015`.
diff --git a/src/test/ui/issues/issue-46959.rs b/src/test/ui/issues/issue-46959.rs
new file mode 100644
index 0000000..e1147ac
--- /dev/null
+++ b/src/test/ui/issues/issue-46959.rs
@@ -0,0 +1,9 @@
+// compile-pass
+#![deny(non_camel_case_types)]
+
+#[allow(dead_code)]
+fn qqq(lol: impl Iterator<Item=u32>) -> impl Iterator<Item=u64> {
+        lol.map(|x|x as u64)
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-46964.rs b/src/test/ui/issues/issue-46964.rs
new file mode 100644
index 0000000..4688c9b
--- /dev/null
+++ b/src/test/ui/issues/issue-46964.rs
@@ -0,0 +1,19 @@
+// compile-pass
+mod my_mod {
+    #[derive(Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash)]
+    pub struct Name<'a> {
+        source: &'a str,
+    }
+
+    pub const JSON: Name = Name { source: "JSON" };
+}
+
+pub fn crash() -> bool {
+  match (my_mod::JSON, None) {
+    (_, Some(my_mod::JSON)) => true,
+    (my_mod::JSON, None) => true,
+    _ => false,
+  }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-46983.rs b/src/test/ui/issues/issue-46983.rs
new file mode 100644
index 0000000..a5c1e17
--- /dev/null
+++ b/src/test/ui/issues/issue-46983.rs
@@ -0,0 +1,8 @@
+#![feature(nll)]
+
+fn foo(x: &u32) -> &'static u32 {
+    &*x
+    //~^ ERROR explicit lifetime required in the type of `x` [E0621]
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-46983.stderr b/src/test/ui/issues/issue-46983.stderr
new file mode 100644
index 0000000..43d351e
--- /dev/null
+++ b/src/test/ui/issues/issue-46983.stderr
@@ -0,0 +1,11 @@
+error[E0621]: explicit lifetime required in the type of `x`
+  --> $DIR/issue-46983.rs:4:5
+   |
+LL | fn foo(x: &u32) -> &'static u32 {
+   |           ---- help: add explicit lifetime `'static` to the type of `x`: `&'static u32`
+LL |     &*x
+   |     ^^^ lifetime `'static` required
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/issues/issue-47073-zero-padded-tuple-struct-indices.rs b/src/test/ui/issues/issue-47073-zero-padded-tuple-struct-indices.rs
new file mode 100644
index 0000000..6cd1f14
--- /dev/null
+++ b/src/test/ui/issues/issue-47073-zero-padded-tuple-struct-indices.rs
@@ -0,0 +1,12 @@
+type Guilty = bool;
+type FineDollars = u32;
+
+struct Verdict(Guilty, Option<FineDollars>);
+
+fn main() {
+    let justice = Verdict(true, Some(2718));
+    let _condemned = justice.00;
+    //~^ ERROR no field `00` on type `Verdict`
+    let _punishment = justice.001;
+    //~^ ERROR no field `001` on type `Verdict`
+}
diff --git a/src/test/ui/issues/issue-47073-zero-padded-tuple-struct-indices.stderr b/src/test/ui/issues/issue-47073-zero-padded-tuple-struct-indices.stderr
new file mode 100644
index 0000000..5e1b816
--- /dev/null
+++ b/src/test/ui/issues/issue-47073-zero-padded-tuple-struct-indices.stderr
@@ -0,0 +1,17 @@
+error[E0609]: no field `00` on type `Verdict`
+  --> $DIR/issue-47073-zero-padded-tuple-struct-indices.rs:8:30
+   |
+LL |     let _condemned = justice.00;
+   |                              ^^ help: a field with a similar name exists: `0`
+
+error[E0609]: no field `001` on type `Verdict`
+  --> $DIR/issue-47073-zero-padded-tuple-struct-indices.rs:10:31
+   |
+LL |     let _punishment = justice.001;
+   |                               ^^^ unknown field
+   |
+   = note: available fields are: `0`, `1`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0609`.
diff --git a/src/test/ui/issues/issue-47094.rs b/src/test/ui/issues/issue-47094.rs
new file mode 100644
index 0000000..6c78a3b
--- /dev/null
+++ b/src/test/ui/issues/issue-47094.rs
@@ -0,0 +1,16 @@
+// compile-pass
+
+#[repr(C,u8)]
+enum Foo {
+    A,
+    B,
+}
+
+#[repr(C)]
+#[repr(u8)]
+enum Bar {
+    A,
+    B,
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-47094.stderr b/src/test/ui/issues/issue-47094.stderr
new file mode 100644
index 0000000..16bcec0
--- /dev/null
+++ b/src/test/ui/issues/issue-47094.stderr
@@ -0,0 +1,14 @@
+warning[E0566]: conflicting representation hints
+  --> $DIR/issue-47094.rs:3:8
+   |
+LL | #[repr(C,u8)]
+   |        ^ ^^
+
+warning[E0566]: conflicting representation hints
+  --> $DIR/issue-47094.rs:9:8
+   |
+LL | #[repr(C)]
+   |        ^
+LL | #[repr(u8)]
+   |        ^^
+
diff --git a/src/test/ui/issues/issue-47184.rs b/src/test/ui/issues/issue-47184.rs
new file mode 100644
index 0000000..04f1146
--- /dev/null
+++ b/src/test/ui/issues/issue-47184.rs
@@ -0,0 +1,6 @@
+#![feature(nll)]
+
+fn main() {
+    let _vec: Vec<&'static String> = vec![&String::new()];
+    //~^ ERROR temporary value dropped while borrowed [E0716]
+}
diff --git a/src/test/ui/issues/issue-47184.stderr b/src/test/ui/issues/issue-47184.stderr
new file mode 100644
index 0000000..2b4d576
--- /dev/null
+++ b/src/test/ui/issues/issue-47184.stderr
@@ -0,0 +1,12 @@
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/issue-47184.rs:4:44
+   |
+LL |     let _vec: Vec<&'static String> = vec![&String::new()];
+   |               --------------------         ^^^^^^^^^^^^^ - temporary value is freed at the end of this statement
+   |               |                            |
+   |               |                            creates a temporary which is freed while still in use
+   |               type annotation requires that borrow lasts for `'static`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/src/test/ui/issues/issue-47309.rs b/src/test/ui/issues/issue-47309.rs
new file mode 100644
index 0000000..a9aeecb
--- /dev/null
+++ b/src/test/ui/issues/issue-47309.rs
@@ -0,0 +1,21 @@
+// Make sure that the mono-item collector does not crash when trying to
+// instantiate a default impl of a method with lifetime parameters.
+// See https://github.com/rust-lang/rust/issues/47309
+
+// compile-flags:-Clink-dead-code
+// compile-pass
+
+#![crate_type="rlib"]
+
+pub trait EnvFuture {
+    type Item;
+
+    fn boxed_result<'a>(self) where Self: Sized, Self::Item: 'a, {
+    }
+}
+
+struct Foo;
+
+impl<'a> EnvFuture for &'a Foo {
+    type Item = ();
+}
diff --git a/src/test/ui/issues/issue-4736.rs b/src/test/ui/issues/issue-4736.rs
new file mode 100644
index 0000000..799d2d4
--- /dev/null
+++ b/src/test/ui/issues/issue-4736.rs
@@ -0,0 +1,5 @@
+struct NonCopyable(());
+
+fn main() {
+    let z = NonCopyable{ p: () }; //~ ERROR struct `NonCopyable` has no field named `p`
+}
diff --git a/src/test/ui/issues/issue-4736.stderr b/src/test/ui/issues/issue-4736.stderr
new file mode 100644
index 0000000..b4ac126
--- /dev/null
+++ b/src/test/ui/issues/issue-4736.stderr
@@ -0,0 +1,9 @@
+error[E0560]: struct `NonCopyable` has no field named `p`
+  --> $DIR/issue-4736.rs:4:26
+   |
+LL |     let z = NonCopyable{ p: () };
+   |                          ^ help: a field with a similar name exists: `0`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0560`.
diff --git a/src/test/ui/issues/issue-47377.rs b/src/test/ui/issues/issue-47377.rs
new file mode 100644
index 0000000..7a2e0fe
--- /dev/null
+++ b/src/test/ui/issues/issue-47377.rs
@@ -0,0 +1,6 @@
+// ignore-tidy-tab
+fn main() {
+ 	let b = "hello";
+ 	let _a = b + ", World!";
+ 	//~^ ERROR E0369
+}
diff --git a/src/test/ui/issues/issue-47377.stderr b/src/test/ui/issues/issue-47377.stderr
new file mode 100644
index 0000000..8846613
--- /dev/null
+++ b/src/test/ui/issues/issue-47377.stderr
@@ -0,0 +1,16 @@
+error[E0369]: binary operation `+` cannot be applied to type `&str`
+  --> $DIR/issue-47377.rs:4:14
+   |
+LL |      let _a = b + ", World!";
+   |               - ^ ---------- &str
+   |               | |
+   |               | `+` can't be used to concatenate two `&str` strings
+   |               &str
+help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left
+   |
+LL |      let _a = b.to_owned() + ", World!";
+   |               ^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0369`.
diff --git a/src/test/ui/issues/issue-47380.rs b/src/test/ui/issues/issue-47380.rs
new file mode 100644
index 0000000..61e0966
--- /dev/null
+++ b/src/test/ui/issues/issue-47380.rs
@@ -0,0 +1,5 @@
+fn main() {
+    let b = "hello";
+    println!("🦀🦀🦀🦀🦀"); let _a = b + ", World!";
+    //~^ ERROR E0369
+}
diff --git a/src/test/ui/issues/issue-47380.stderr b/src/test/ui/issues/issue-47380.stderr
new file mode 100644
index 0000000..d69101e
--- /dev/null
+++ b/src/test/ui/issues/issue-47380.stderr
@@ -0,0 +1,16 @@
+error[E0369]: binary operation `+` cannot be applied to type `&str`
+  --> $DIR/issue-47380.rs:3:35
+   |
+LL |     println!("🦀🦀🦀🦀🦀"); let _a = b + ", World!";
+   |                                      - ^ ---------- &str
+   |                                      | |
+   |                                      | `+` can't be used to concatenate two `&str` strings
+   |                                      &str
+help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left
+   |
+LL |     println!("🦀🦀🦀🦀🦀"); let _a = b.to_owned() + ", World!";
+   |                                      ^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0369`.
diff --git a/src/test/ui/issues/issue-47412.rs b/src/test/ui/issues/issue-47412.rs
new file mode 100644
index 0000000..2d1ea72
--- /dev/null
+++ b/src/test/ui/issues/issue-47412.rs
@@ -0,0 +1,21 @@
+#[derive(Copy, Clone)]
+enum Void {}
+
+// Tests that we detect unsafe places (specifically, union fields and
+// raw pointer dereferences), even when they're matched on while having
+// an uninhabited type (equivalent to `std::intrinsics::unreachable()`).
+
+fn union_field() {
+    union Union { unit: (), void: Void }
+    let u = Union { unit: () };
+    match u.void {}
+    //~^ ERROR access to union field is unsafe
+}
+
+fn raw_ptr_deref() {
+    let ptr = std::ptr::null::<Void>();
+    match *ptr {}
+    //~^ ERROR dereference of raw pointer is unsafe
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-47412.stderr b/src/test/ui/issues/issue-47412.stderr
new file mode 100644
index 0000000..0f003c4
--- /dev/null
+++ b/src/test/ui/issues/issue-47412.stderr
@@ -0,0 +1,19 @@
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/issue-47412.rs:11:11
+   |
+LL |     match u.void {}
+   |           ^^^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
+  --> $DIR/issue-47412.rs:17:11
+   |
+LL |     match *ptr {}
+   |           ^^^^ dereference of raw pointer
+   |
+   = note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/issues/issue-47511.rs b/src/test/ui/issues/issue-47511.rs
new file mode 100644
index 0000000..0f33b52
--- /dev/null
+++ b/src/test/ui/issues/issue-47511.rs
@@ -0,0 +1,25 @@
+// Regression test for #47511: anonymous lifetimes can appear
+// unconstrained in a return type, but only if they appear just once
+// in the input, as the input to a projection.
+
+fn f(_: X) -> X {
+    //~^ ERROR return type references an anonymous lifetime
+    unimplemented!()
+}
+
+fn g<'a>(_: X<'a>) -> X<'a> {
+    //~^ ERROR return type references lifetime `'a`, which is not constrained
+    unimplemented!()
+}
+
+type X<'a> = <&'a () as Trait>::Value;
+
+trait Trait {
+    type Value;
+}
+
+impl<'a> Trait for &'a () {
+    type Value = ();
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-47511.stderr b/src/test/ui/issues/issue-47511.stderr
new file mode 100644
index 0000000..42f2cd1
--- /dev/null
+++ b/src/test/ui/issues/issue-47511.stderr
@@ -0,0 +1,17 @@
+error[E0581]: return type references an anonymous lifetime which is not constrained by the fn input types
+  --> $DIR/issue-47511.rs:5:15
+   |
+LL | fn f(_: X) -> X {
+   |               ^
+   |
+   = note: lifetimes appearing in an associated type are not considered constrained
+
+error[E0581]: return type references lifetime `'a`, which is not constrained by the fn input types
+  --> $DIR/issue-47511.rs:10:23
+   |
+LL | fn g<'a>(_: X<'a>) -> X<'a> {
+   |                       ^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0581`.
diff --git a/src/test/ui/issues/issue-47623.rs b/src/test/ui/issues/issue-47623.rs
new file mode 100644
index 0000000..ad8aa4c
--- /dev/null
+++ b/src/test/ui/issues/issue-47623.rs
@@ -0,0 +1,3 @@
+use self; //~ERROR `self` imports are only allowed within a { } list
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-47623.stderr b/src/test/ui/issues/issue-47623.stderr
new file mode 100644
index 0000000..53968a2
--- /dev/null
+++ b/src/test/ui/issues/issue-47623.stderr
@@ -0,0 +1,9 @@
+error[E0429]: `self` imports are only allowed within a { } list
+  --> $DIR/issue-47623.rs:1:5
+   |
+LL | use self;
+   |     ^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0429`.
diff --git a/src/test/ui/issues/issue-47646.rs b/src/test/ui/issues/issue-47646.rs
new file mode 100644
index 0000000..c3c07bf
--- /dev/null
+++ b/src/test/ui/issues/issue-47646.rs
@@ -0,0 +1,16 @@
+#![allow(warnings)]
+#![feature(nll)]
+
+use std::collections::BinaryHeap;
+
+fn main() {
+    let mut heap: BinaryHeap<i32> = BinaryHeap::new();
+    let borrow = heap.peek_mut();
+
+    match (borrow, ()) {
+        (Some(_), ()) => {
+            println!("{:?}", heap); //~ ERROR cannot borrow `heap` as immutable
+        }
+        _ => {}
+    };
+}
diff --git a/src/test/ui/issues/issue-47646.stderr b/src/test/ui/issues/issue-47646.stderr
new file mode 100644
index 0000000..db9f227
--- /dev/null
+++ b/src/test/ui/issues/issue-47646.stderr
@@ -0,0 +1,18 @@
+error[E0502]: cannot borrow `heap` as immutable because it is also borrowed as mutable
+  --> $DIR/issue-47646.rs:12:30
+   |
+LL |     let borrow = heap.peek_mut();
+   |                  ---- mutable borrow occurs here
+LL | 
+LL |     match (borrow, ()) {
+   |           ------------ a temporary with access to the mutable borrow is created here ...
+LL |         (Some(_), ()) => {
+LL |             println!("{:?}", heap);
+   |                              ^^^^ immutable borrow occurs here
+...
+LL |     };
+   |      - ... and the mutable borrow might be used here, when that temporary is dropped and runs the destructor for type `(std::option::Option<std::collections::binary_heap::PeekMut<'_, i32>>, ())`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/issues/issue-47673.rs b/src/test/ui/issues/issue-47673.rs
new file mode 100644
index 0000000..6d7b8f9
--- /dev/null
+++ b/src/test/ui/issues/issue-47673.rs
@@ -0,0 +1,6 @@
+// compile-pass
+#![allow(unused_imports)]
+
+use {{}, {}};
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-47703-1.rs b/src/test/ui/issues/issue-47703-1.rs
new file mode 100644
index 0000000..9add314
--- /dev/null
+++ b/src/test/ui/issues/issue-47703-1.rs
@@ -0,0 +1,25 @@
+// compile-pass
+#![allow(dead_code)]
+#![feature(nll)]
+
+struct AtomicRefMut<'a> {
+    value: &'a mut i32,
+    borrow: AtomicBorrowRefMut,
+}
+
+struct AtomicBorrowRefMut {
+}
+
+impl Drop for AtomicBorrowRefMut {
+    fn drop(&mut self) {
+    }
+}
+
+fn map(orig: AtomicRefMut) -> AtomicRefMut {
+    AtomicRefMut {
+        value: orig.value,
+        borrow: orig.borrow,
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-47703-tuple.rs b/src/test/ui/issues/issue-47703-tuple.rs
new file mode 100644
index 0000000..850771c
--- /dev/null
+++ b/src/test/ui/issues/issue-47703-tuple.rs
@@ -0,0 +1,13 @@
+// compile-pass
+#![allow(dead_code)]
+#![feature(nll)]
+
+struct WithDrop;
+
+impl Drop for WithDrop {
+    fn drop(&mut self) {}
+}
+
+fn consume(x: (&mut (), WithDrop)) -> &mut () { x.0 }
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-47703.rs b/src/test/ui/issues/issue-47703.rs
new file mode 100644
index 0000000..06b17e9
--- /dev/null
+++ b/src/test/ui/issues/issue-47703.rs
@@ -0,0 +1,20 @@
+// compile-pass
+#![allow(dead_code)]
+#![feature(nll)]
+
+struct MyStruct<'a> {
+    field: &'a mut (),
+    field2: WithDrop
+}
+
+struct WithDrop;
+
+impl Drop for WithDrop {
+    fn drop(&mut self) {}
+}
+
+impl<'a> MyStruct<'a> {
+    fn consume(self) -> &'a mut () { self.field }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-47706-trait.rs b/src/test/ui/issues/issue-47706-trait.rs
new file mode 100644
index 0000000..8fb4e085
--- /dev/null
+++ b/src/test/ui/issues/issue-47706-trait.rs
@@ -0,0 +1,8 @@
+trait T {
+    fn f(&self, _: ()) {
+        None::<()>.map(Self::f);
+    }
+    //~^^ ERROR function is expected to take a single 0-tuple as argument
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-47706-trait.stderr b/src/test/ui/issues/issue-47706-trait.stderr
new file mode 100644
index 0000000..5f8f856
--- /dev/null
+++ b/src/test/ui/issues/issue-47706-trait.stderr
@@ -0,0 +1,11 @@
+error[E0593]: function is expected to take a single 0-tuple as argument, but it takes 2 distinct arguments
+  --> $DIR/issue-47706-trait.rs:3:20
+   |
+LL |     fn f(&self, _: ()) {
+   |     ------------------ takes 2 distinct arguments
+LL |         None::<()>.map(Self::f);
+   |                    ^^^ expected function that takes a single 0-tuple as argument
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0593`.
diff --git a/src/test/ui/issues/issue-47706.rs b/src/test/ui/issues/issue-47706.rs
new file mode 100644
index 0000000..f47c1e6
--- /dev/null
+++ b/src/test/ui/issues/issue-47706.rs
@@ -0,0 +1,29 @@
+pub struct Foo {
+    foo: Option<i32>,
+}
+
+impl Foo {
+    pub fn new(foo: Option<i32>, _: ()) -> Foo {
+        Foo { foo }
+    }
+
+    pub fn map(self) -> Option<Foo> {
+        self.foo.map(Foo::new)
+    }
+    //~^^ ERROR function is expected to take 1 argument, but it takes 2 arguments [E0593]
+}
+
+enum Qux {
+    Bar(i32),
+}
+
+fn foo<F>(f: F)
+where
+    F: Fn(),
+{
+}
+
+fn main() {
+    foo(Qux::Bar);
+}
+//~^^ ERROR function is expected to take 0 arguments, but it takes 1 argument [E0593]
diff --git a/src/test/ui/issues/issue-47706.stderr b/src/test/ui/issues/issue-47706.stderr
new file mode 100644
index 0000000..fa2e00c
--- /dev/null
+++ b/src/test/ui/issues/issue-47706.stderr
@@ -0,0 +1,31 @@
+error[E0593]: function is expected to take 1 argument, but it takes 2 arguments
+  --> $DIR/issue-47706.rs:11:18
+   |
+LL |     pub fn new(foo: Option<i32>, _: ()) -> Foo {
+   |     ------------------------------------------ takes 2 arguments
+...
+LL |         self.foo.map(Foo::new)
+   |                  ^^^ expected function that takes 1 argument
+
+error[E0593]: function is expected to take 0 arguments, but it takes 1 argument
+  --> $DIR/issue-47706.rs:27:5
+   |
+LL |     Bar(i32),
+   |     -------- takes 1 argument
+...
+LL |     foo(Qux::Bar);
+   |     ^^^ expected function that takes 0 arguments
+   |
+note: required by `foo`
+  --> $DIR/issue-47706.rs:20:1
+   |
+LL | / fn foo<F>(f: F)
+LL | | where
+LL | |     F: Fn(),
+LL | | {
+LL | | }
+   | |_^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0593`.
diff --git a/src/test/ui/issues/issue-47715.rs b/src/test/ui/issues/issue-47715.rs
new file mode 100644
index 0000000..478ac6a
--- /dev/null
+++ b/src/test/ui/issues/issue-47715.rs
@@ -0,0 +1,28 @@
+trait Foo {}
+
+trait Bar<T> {}
+
+trait Iterable {
+    type Item;
+}
+
+struct Container<T: Iterable<Item = impl Foo>> {
+    //~^ ERROR `impl Trait` not allowed
+    field: T
+}
+
+enum Enum<T: Iterable<Item = impl Foo>> {
+    //~^ ERROR `impl Trait` not allowed
+    A(T),
+}
+
+union Union<T: Iterable<Item = impl Foo> + Copy> {
+    //~^ ERROR `impl Trait` not allowed
+    x: T,
+}
+
+type Type<T: Iterable<Item = impl Foo>> = T;
+//~^ ERROR `impl Trait` not allowed
+
+fn main() {
+}
diff --git a/src/test/ui/issues/issue-47715.stderr b/src/test/ui/issues/issue-47715.stderr
new file mode 100644
index 0000000..296de36
--- /dev/null
+++ b/src/test/ui/issues/issue-47715.stderr
@@ -0,0 +1,27 @@
+error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+  --> $DIR/issue-47715.rs:9:37
+   |
+LL | struct Container<T: Iterable<Item = impl Foo>> {
+   |                                     ^^^^^^^^
+
+error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+  --> $DIR/issue-47715.rs:14:30
+   |
+LL | enum Enum<T: Iterable<Item = impl Foo>> {
+   |                              ^^^^^^^^
+
+error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+  --> $DIR/issue-47715.rs:19:32
+   |
+LL | union Union<T: Iterable<Item = impl Foo> + Copy> {
+   |                                ^^^^^^^^
+
+error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+  --> $DIR/issue-47715.rs:24:30
+   |
+LL | type Type<T: Iterable<Item = impl Foo>> = T;
+   |                              ^^^^^^^^
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0562`.
diff --git a/src/test/ui/issues/issue-47722.rs b/src/test/ui/issues/issue-47722.rs
new file mode 100644
index 0000000..c9bc614
--- /dev/null
+++ b/src/test/ui/issues/issue-47722.rs
@@ -0,0 +1,19 @@
+// compile-pass
+#![allow(dead_code)]
+
+// Tests that automatic coercions from &mut T to *mut T
+// allow borrows of T to expire immediately - essentially, that
+// they work identically to 'foo as *mut T'
+#![feature(nll)]
+
+struct SelfReference {
+    self_reference: *mut SelfReference,
+}
+
+impl SelfReference {
+    fn set_self_ref(&mut self) {
+        self.self_reference = self;
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-47789.rs b/src/test/ui/issues/issue-47789.rs
new file mode 100644
index 0000000..d15a27a
--- /dev/null
+++ b/src/test/ui/issues/issue-47789.rs
@@ -0,0 +1,13 @@
+// compile-pass
+#![allow(dead_code)]
+#![allow(non_upper_case_globals)]
+
+#![feature(nll)]
+
+static mut x: &'static u32 = &0;
+
+fn foo() {
+    unsafe { x = &1; }
+}
+
+fn main() { }
diff --git a/src/test/ui/issues/issue-48131.rs b/src/test/ui/issues/issue-48131.rs
new file mode 100644
index 0000000..b3cc350
--- /dev/null
+++ b/src/test/ui/issues/issue-48131.rs
@@ -0,0 +1,29 @@
+// This note is annotated because the purpose of the test
+// is to ensure that certain other notes are not generated.
+#![deny(unused_unsafe)] //~ NOTE
+
+// (test that no note is generated on this unsafe fn)
+pub unsafe fn a() {
+    fn inner() {
+        unsafe { /* unnecessary */ } //~ ERROR unnecessary `unsafe`
+                                     //~^ NOTE
+    }
+
+    inner()
+}
+
+pub fn b() {
+    // (test that no note is generated on this unsafe block)
+    unsafe {
+        fn inner() {
+            unsafe { /* unnecessary */ } //~ ERROR unnecessary `unsafe`
+                                         //~^ NOTE
+        }
+
+        let () = ::std::mem::uninitialized();
+
+        inner()
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-48131.stderr b/src/test/ui/issues/issue-48131.stderr
new file mode 100644
index 0000000..adc36e2
--- /dev/null
+++ b/src/test/ui/issues/issue-48131.stderr
@@ -0,0 +1,20 @@
+error: unnecessary `unsafe` block
+  --> $DIR/issue-48131.rs:8:9
+   |
+LL |         unsafe { /* unnecessary */ }
+   |         ^^^^^^ unnecessary `unsafe` block
+   |
+note: lint level defined here
+  --> $DIR/issue-48131.rs:3:9
+   |
+LL | #![deny(unused_unsafe)]
+   |         ^^^^^^^^^^^^^
+
+error: unnecessary `unsafe` block
+  --> $DIR/issue-48131.rs:19:13
+   |
+LL |             unsafe { /* unnecessary */ }
+   |             ^^^^^^ unnecessary `unsafe` block
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/issues/issue-48132.rs b/src/test/ui/issues/issue-48132.rs
new file mode 100644
index 0000000..b3cef78
--- /dev/null
+++ b/src/test/ui/issues/issue-48132.rs
@@ -0,0 +1,32 @@
+// Regression test for #48132. This was failing due to problems around
+// the projection caching and dropck type enumeration.
+
+// run-pass
+
+#![feature(nll)]
+#![allow(warnings)]
+
+struct Inner<I, V> {
+    iterator: I,
+    item: V,
+}
+
+struct Outer<I: Iterator> {
+    inner: Inner<I, I::Item>,
+}
+
+fn outer<I>(iterator: I) -> Outer<I>
+where I: Iterator,
+      I::Item: Default,
+{
+    Outer {
+        inner: Inner {
+            iterator: iterator,
+            item: Default::default(),
+        }
+    }
+}
+
+fn main() {
+    outer(std::iter::once(&1).cloned());
+}
diff --git a/src/test/ui/issues/issue-48179.rs b/src/test/ui/issues/issue-48179.rs
new file mode 100644
index 0000000..245f13b
--- /dev/null
+++ b/src/test/ui/issues/issue-48179.rs
@@ -0,0 +1,41 @@
+// Regression test for #48132. This was failing due to problems around
+// the projection caching and dropck type enumeration.
+
+// run-pass
+
+#![feature(nll)]
+#![allow(warnings)]
+
+pub struct Container<T: Iterator> {
+    value: Option<T::Item>,
+}
+
+impl<T: Iterator> Container<T> {
+    pub fn new(iter: T) -> Self {
+        panic!()
+    }
+}
+
+pub struct Wrapper<'a> {
+    content: &'a Content,
+}
+
+impl<'a, 'de> Wrapper<'a> {
+    pub fn new(content: &'a Content) -> Self {
+        Wrapper {
+            content: content,
+        }
+    }
+}
+
+pub struct Content;
+
+fn crash_it(content: Content) {
+    let items = vec![content];
+    let map = items.iter().map(|ref o| Wrapper::new(o));
+
+    let mut map_visitor = Container::new(map);
+
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-48276.rs b/src/test/ui/issues/issue-48276.rs
new file mode 100644
index 0000000..f55c056
--- /dev/null
+++ b/src/test/ui/issues/issue-48276.rs
@@ -0,0 +1,33 @@
+// Regression test for issue #48276 - ICE when self type does not match what is
+// required by a trait and regions are involved.
+
+trait MyFrom<A> {
+    fn from(a: A) -> Self;
+}
+
+struct A;
+
+impl<'a, 'b> MyFrom<A> for &'a str {
+    fn from(self: &'a Self) -> &'b str {
+        //~^ ERROR: method `from` has a `&self` declaration in the impl, but not in the trait
+        "asdf"
+    }
+}
+
+struct B;
+
+impl From<A> for B {
+    fn from(&self) -> B {
+        //~^ ERROR: method `from` has a `&self` declaration in the impl, but not in the trait
+        B
+    }
+}
+
+impl From<A> for &'static str {
+    fn from(&self) -> &'static str {
+        //~^ ERROR: method `from` has a `&self` declaration in the impl, but not in the trait
+        ""
+    }
+}
+
+fn main(){}
diff --git a/src/test/ui/issues/issue-48276.stderr b/src/test/ui/issues/issue-48276.stderr
new file mode 100644
index 0000000..370905e
--- /dev/null
+++ b/src/test/ui/issues/issue-48276.stderr
@@ -0,0 +1,28 @@
+error[E0185]: method `from` has a `&self` declaration in the impl, but not in the trait
+  --> $DIR/issue-48276.rs:11:5
+   |
+LL |     fn from(a: A) -> Self;
+   |     ---------------------- trait method declared without `&self`
+...
+LL |     fn from(self: &'a Self) -> &'b str {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&self` used in impl
+
+error[E0185]: method `from` has a `&self` declaration in the impl, but not in the trait
+  --> $DIR/issue-48276.rs:20:5
+   |
+LL |     fn from(&self) -> B {
+   |     ^^^^^^^^^^^^^^^^^^^ `&self` used in impl
+   |
+   = note: `from` from trait: `fn(T) -> Self`
+
+error[E0185]: method `from` has a `&self` declaration in the impl, but not in the trait
+  --> $DIR/issue-48276.rs:27:5
+   |
+LL |     fn from(&self) -> &'static str {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&self` used in impl
+   |
+   = note: `from` from trait: `fn(T) -> Self`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0185`.
diff --git a/src/test/ui/issues/issue-4830.rs b/src/test/ui/issues/issue-4830.rs
new file mode 100644
index 0000000..cf94094
--- /dev/null
+++ b/src/test/ui/issues/issue-4830.rs
@@ -0,0 +1,11 @@
+// compile-pass
+#![allow(dead_code)]
+
+// pretty-expanded FIXME #23616
+
+pub struct Scheduler {
+    /// The event loop used to drive the scheduler and perform I/O
+    event_loop: Box<isize>
+}
+
+pub fn main() { }
diff --git a/src/test/ui/issues/issue-48364.rs b/src/test/ui/issues/issue-48364.rs
new file mode 100644
index 0000000..14ee75e
--- /dev/null
+++ b/src/test/ui/issues/issue-48364.rs
@@ -0,0 +1,6 @@
+fn foo() -> bool {
+    b"".starts_with(stringify!(foo))
+    //~^ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-48364.stderr b/src/test/ui/issues/issue-48364.stderr
new file mode 100644
index 0000000..7a1ba5b
--- /dev/null
+++ b/src/test/ui/issues/issue-48364.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-48364.rs:2:21
+   |
+LL |     b"".starts_with(stringify!(foo))
+   |                     ^^^^^^^^^^^^^^^ expected slice, found str
+   |
+   = note: expected type `&[u8]`
+              found type `&'static str`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-48551.rs b/src/test/ui/issues/issue-48551.rs
new file mode 100644
index 0000000..b5dd673
--- /dev/null
+++ b/src/test/ui/issues/issue-48551.rs
@@ -0,0 +1,34 @@
+// compile-pass
+// Regression test for #48551. Covers a case where duplicate candidates
+// arose during associated type projection.
+
+use std::ops::{Mul, MulAssign};
+
+pub trait ClosedMul<Right>: Sized + Mul<Right, Output = Self> + MulAssign<Right> {}
+impl<T, Right> ClosedMul<Right> for T
+where
+    T: Mul<Right, Output = T> + MulAssign<Right>,
+{
+}
+
+pub trait InnerSpace: ClosedMul<<Self as InnerSpace>::Real> {
+    type Real;
+}
+
+pub trait FiniteDimVectorSpace: ClosedMul<<Self as FiniteDimVectorSpace>::Field> {
+    type Field;
+}
+
+pub trait FiniteDimInnerSpace
+    : InnerSpace + FiniteDimVectorSpace<Field = <Self as InnerSpace>::Real> {
+}
+
+pub trait EuclideanSpace: ClosedMul<<Self as EuclideanSpace>::Real> {
+    type Coordinates: FiniteDimInnerSpace<Real = Self::Real>
+        + Mul<Self::Real, Output = Self::Coordinates>
+        + MulAssign<Self::Real>;
+
+    type Real;
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-48636.fixed b/src/test/ui/issues/issue-48636.fixed
new file mode 100644
index 0000000..87c19a3
--- /dev/null
+++ b/src/test/ui/issues/issue-48636.fixed
@@ -0,0 +1,12 @@
+// run-rustfix
+
+#![allow(dead_code)]
+
+struct S {
+    x: u8,
+    /// The ID of the parent core
+    y: u8,
+}
+//~^^^ ERROR found a documentation comment that doesn't document anything
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-48636.rs b/src/test/ui/issues/issue-48636.rs
new file mode 100644
index 0000000..8610dc2
--- /dev/null
+++ b/src/test/ui/issues/issue-48636.rs
@@ -0,0 +1,12 @@
+// run-rustfix
+
+#![allow(dead_code)]
+
+struct S {
+    x: u8
+    /// The ID of the parent core
+    y: u8,
+}
+//~^^^ ERROR found a documentation comment that doesn't document anything
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-48636.stderr b/src/test/ui/issues/issue-48636.stderr
new file mode 100644
index 0000000..462723d
--- /dev/null
+++ b/src/test/ui/issues/issue-48636.stderr
@@ -0,0 +1,13 @@
+error[E0585]: found a documentation comment that doesn't document anything
+  --> $DIR/issue-48636.rs:7:5
+   |
+LL |     x: u8
+   |          - help: missing comma here: `,`
+LL |     /// The ID of the parent core
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: doc comments must come before what they document, maybe a comment was intended with `//`?
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0585`.
diff --git a/src/test/ui/issues/issue-48728.rs b/src/test/ui/issues/issue-48728.rs
new file mode 100644
index 0000000..8405a30
--- /dev/null
+++ b/src/test/ui/issues/issue-48728.rs
@@ -0,0 +1,13 @@
+// Regression test for #48728, an ICE that occurred computing
+// coherence "help" information.
+
+#[derive(Clone)] //~ ERROR conflicting implementations of trait `std::clone::Clone`
+struct Node<T: ?Sized>(Box<T>);
+
+impl<T: Clone + ?Sized> Clone for Node<[T]> {
+    fn clone(&self) -> Self {
+        Node(Box::clone(&self.0))
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-48728.stderr b/src/test/ui/issues/issue-48728.stderr
new file mode 100644
index 0000000..99a9bf9
--- /dev/null
+++ b/src/test/ui/issues/issue-48728.stderr
@@ -0,0 +1,14 @@
+error[E0119]: conflicting implementations of trait `std::clone::Clone` for type `Node<[_]>`:
+  --> $DIR/issue-48728.rs:4:10
+   |
+LL | #[derive(Clone)]
+   |          ^^^^^ conflicting implementation for `Node<[_]>`
+...
+LL | impl<T: Clone + ?Sized> Clone for Node<[T]> {
+   | ------------------------------------------- first implementation here
+   |
+   = note: upstream crates may add new impl of trait `std::clone::Clone` for type `[_]` in future versions
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/issues/issue-48803.rs b/src/test/ui/issues/issue-48803.rs
new file mode 100644
index 0000000..bc1bc29
--- /dev/null
+++ b/src/test/ui/issues/issue-48803.rs
@@ -0,0 +1,15 @@
+#![feature(nll)]
+
+fn flatten<'a, 'b, T>(x: &'a &'b T) -> &'a T {
+    x
+}
+
+fn main() {
+    let mut x = "original";
+    let y = &x;
+    let z = &y;
+    let w = flatten(z);
+    x = "modified";
+    //~^ ERROR cannot assign to `x` because it is borrowed [E0506]
+    println!("{}", w); // prints "modified"
+}
diff --git a/src/test/ui/issues/issue-48803.stderr b/src/test/ui/issues/issue-48803.stderr
new file mode 100644
index 0000000..9a6da9e
--- /dev/null
+++ b/src/test/ui/issues/issue-48803.stderr
@@ -0,0 +1,15 @@
+error[E0506]: cannot assign to `x` because it is borrowed
+  --> $DIR/issue-48803.rs:12:5
+   |
+LL |     let y = &x;
+   |             -- borrow of `x` occurs here
+...
+LL |     x = "modified";
+   |     ^^^^^^^^^^^^^^ assignment to borrowed `x` occurs here
+LL |
+LL |     println!("{}", w); // prints "modified"
+   |                    - borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/issues/issue-48838.rs b/src/test/ui/issues/issue-48838.rs
new file mode 100644
index 0000000..057a424
--- /dev/null
+++ b/src/test/ui/issues/issue-48838.rs
@@ -0,0 +1,5 @@
+enum Functions {
+    Square = |x| x, //~ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-48838.stderr b/src/test/ui/issues/issue-48838.stderr
new file mode 100644
index 0000000..3007d67
--- /dev/null
+++ b/src/test/ui/issues/issue-48838.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-48838.rs:2:14
+   |
+LL |     Square = |x| x,
+   |              ^^^^^ expected isize, found closure
+   |
+   = note: expected type `isize`
+              found type `[closure@$DIR/issue-48838.rs:2:14: 2:19]`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-49040.rs b/src/test/ui/issues/issue-49040.rs
new file mode 100644
index 0000000..a5f05d2
--- /dev/null
+++ b/src/test/ui/issues/issue-49040.rs
@@ -0,0 +1,2 @@
+#![allow(unused_variables)]; //~ ERROR expected item, found `;`
+fn foo() {}
diff --git a/src/test/ui/issues/issue-49040.stderr b/src/test/ui/issues/issue-49040.stderr
new file mode 100644
index 0000000..de78b8d
--- /dev/null
+++ b/src/test/ui/issues/issue-49040.stderr
@@ -0,0 +1,13 @@
+error: expected item, found `;`
+  --> $DIR/issue-49040.rs:1:28
+   |
+LL | #![allow(unused_variables)];
+   |                            ^ help: remove this semicolon
+
+error[E0601]: `main` function not found in crate `issue_49040`
+   |
+   = note: consider adding a `main` function to `$DIR/issue-49040.rs`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0601`.
diff --git a/src/test/ui/issues/issue-49074.rs b/src/test/ui/issues/issue-49074.rs
new file mode 100644
index 0000000..ad66e42
--- /dev/null
+++ b/src/test/ui/issues/issue-49074.rs
@@ -0,0 +1,13 @@
+// Check that unknown attribute error is shown even if there are unresolved macros.
+
+#[marco_use] // typo
+//~^ ERROR The attribute `marco_use` is currently unknown to the compiler
+mod foo {
+    macro_rules! bar {
+        () => ();
+    }
+}
+
+fn main() {
+   bar!(); //~ ERROR cannot find macro `bar!` in this scope
+}
diff --git a/src/test/ui/issues/issue-49074.stderr b/src/test/ui/issues/issue-49074.stderr
new file mode 100644
index 0000000..b41d913
--- /dev/null
+++ b/src/test/ui/issues/issue-49074.stderr
@@ -0,0 +1,19 @@
+error[E0658]: The attribute `marco_use` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/issue-49074.rs:3:3
+   |
+LL | #[marco_use] // typo
+   |   ^^^^^^^^^ help: a built-in attribute with a similar name exists: `macro_use`
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error: cannot find macro `bar!` in this scope
+  --> $DIR/issue-49074.rs:12:4
+   |
+LL |    bar!();
+   |    ^^^
+   |
+   = help: have you added the `#[macro_use]` on the module/import?
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/issues/issue-49257.rs b/src/test/ui/issues/issue-49257.rs
new file mode 100644
index 0000000..a7fa19d5
--- /dev/null
+++ b/src/test/ui/issues/issue-49257.rs
@@ -0,0 +1,14 @@
+// Test for #49257:
+// emits good diagnostics for `..` pattern fragments not in the last position.
+
+#![allow(unused)]
+
+struct Point { x: u8, y: u8 }
+
+fn main() {
+    let p = Point { x: 0, y: 0 };
+    let Point { .., y, } = p; //~ ERROR expected `}`, found `,`
+    let Point { .., y } = p; //~ ERROR expected `}`, found `,`
+    let Point { .., } = p; //~ ERROR expected `}`, found `,`
+    let Point { .. } = p;
+}
diff --git a/src/test/ui/issues/issue-49257.stderr b/src/test/ui/issues/issue-49257.stderr
new file mode 100644
index 0000000..43a505c
--- /dev/null
+++ b/src/test/ui/issues/issue-49257.stderr
@@ -0,0 +1,38 @@
+error: expected `}`, found `,`
+  --> $DIR/issue-49257.rs:10:19
+   |
+LL |     let Point { .., y, } = p;
+   |                 --^
+   |                 | |
+   |                 | expected `}`
+   |                 `..` must be at the end and cannot have a trailing comma
+help: move the `..` to the end of the field list
+   |
+LL |     let Point { y, .. } = p;
+   |                --  ^^^^
+
+error: expected `}`, found `,`
+  --> $DIR/issue-49257.rs:11:19
+   |
+LL |     let Point { .., y } = p;
+   |                 --^
+   |                 | |
+   |                 | expected `}`
+   |                 `..` must be at the end and cannot have a trailing comma
+help: move the `..` to the end of the field list
+   |
+LL |     let Point { y , .. } = p;
+   |                -- ^^^^^^
+
+error: expected `}`, found `,`
+  --> $DIR/issue-49257.rs:12:19
+   |
+LL |     let Point { .., } = p;
+   |                 --^
+   |                 | |
+   |                 | expected `}`
+   |                 | help: remove this comma
+   |                 `..` must be at the end and cannot have a trailing comma
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/issues/issue-4935.rs b/src/test/ui/issues/issue-4935.rs
new file mode 100644
index 0000000..3b258c3
--- /dev/null
+++ b/src/test/ui/issues/issue-4935.rs
@@ -0,0 +1,6 @@
+// Regression test for issue #4935
+
+fn foo(a: usize) {}
+//~^ defined here
+fn main() { foo(5, 6) }
+//~^ ERROR this function takes 1 parameter but 2 parameters were supplied
diff --git a/src/test/ui/issues/issue-4935.stderr b/src/test/ui/issues/issue-4935.stderr
new file mode 100644
index 0000000..a99581f
--- /dev/null
+++ b/src/test/ui/issues/issue-4935.stderr
@@ -0,0 +1,12 @@
+error[E0061]: this function takes 1 parameter but 2 parameters were supplied
+  --> $DIR/issue-4935.rs:5:13
+   |
+LL | fn foo(a: usize) {}
+   | ---------------- defined here
+LL |
+LL | fn main() { foo(5, 6) }
+   |             ^^^^^^^^^ expected 1 parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0061`.
diff --git a/src/test/ui/issues/issue-49556.rs b/src/test/ui/issues/issue-49556.rs
new file mode 100644
index 0000000..b8fcc64
--- /dev/null
+++ b/src/test/ui/issues/issue-49556.rs
@@ -0,0 +1,13 @@
+// compile-pass
+fn iter<'a>(data: &'a [usize]) -> impl Iterator<Item = usize> + 'a {
+    data.iter()
+        .map(
+            |x| x // fn(&'a usize) -> &'(ReScope) usize
+        )
+        .map(
+            |x| *x // fn(&'(ReScope) usize) -> usize
+        )
+}
+
+fn main() {
+}
diff --git a/src/test/ui/issues/issue-49579.rs b/src/test/ui/issues/issue-49579.rs
new file mode 100644
index 0000000..34f277a
--- /dev/null
+++ b/src/test/ui/issues/issue-49579.rs
@@ -0,0 +1,17 @@
+// compile-pass
+// ignore-emscripten no i128 support
+
+#![feature(nll)]
+
+fn fibs(n: u32) -> impl Iterator<Item=u128> {
+    (0 .. n)
+    .scan((0, 1), |st, _| {
+        *st = (st.1, st.0 + st.1);
+        Some(*st)
+    })
+    .map(&|(f, _)| f)
+}
+
+fn main() {
+    println!("{:?}", fibs(10).collect::<Vec<_>>());
+}
diff --git a/src/test/ui/issues/issue-4968.rs b/src/test/ui/issues/issue-4968.rs
new file mode 100644
index 0000000..383b9ec
--- /dev/null
+++ b/src/test/ui/issues/issue-4968.rs
@@ -0,0 +1,10 @@
+// Regression test for issue #4968
+
+const A: (isize,isize) = (4,2);
+fn main() {
+    match 42 { A => () }
+    //~^ ERROR mismatched types
+    //~| expected type `{integer}`
+    //~| found type `(isize, isize)`
+    //~| expected integer, found tuple
+}
diff --git a/src/test/ui/issues/issue-4968.stderr b/src/test/ui/issues/issue-4968.stderr
new file mode 100644
index 0000000..a925783
--- /dev/null
+++ b/src/test/ui/issues/issue-4968.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-4968.rs:5:16
+   |
+LL |     match 42 { A => () }
+   |                ^ expected integer, found tuple
+   |
+   = note: expected type `{integer}`
+              found type `(isize, isize)`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-4972.rs b/src/test/ui/issues/issue-4972.rs
new file mode 100644
index 0000000..9c95a97
--- /dev/null
+++ b/src/test/ui/issues/issue-4972.rs
@@ -0,0 +1,18 @@
+#![feature(box_patterns)]
+#![feature(box_syntax)]
+
+trait MyTrait {
+    fn dummy(&self) {}
+}
+
+pub enum TraitWrapper {
+    A(Box<MyTrait+'static>),
+}
+
+fn get_tw_map(tw: &TraitWrapper) -> &MyTrait {
+    match *tw {
+        TraitWrapper::A(box ref map) => map, //~ ERROR cannot be dereferenced
+    }
+}
+
+pub fn main() {}
diff --git a/src/test/ui/issues/issue-4972.stderr b/src/test/ui/issues/issue-4972.stderr
new file mode 100644
index 0000000..b1947e2
--- /dev/null
+++ b/src/test/ui/issues/issue-4972.stderr
@@ -0,0 +1,9 @@
+error[E0033]: type `std::boxed::Box<(dyn MyTrait + 'static)>` cannot be dereferenced
+  --> $DIR/issue-4972.rs:14:25
+   |
+LL |         TraitWrapper::A(box ref map) => map,
+   |                         ^^^^^^^^^^^ type `std::boxed::Box<(dyn MyTrait + 'static)>` cannot be dereferenced
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0033`.
diff --git a/src/test/ui/issues/issue-49824.nll.stderr b/src/test/ui/issues/issue-49824.nll.stderr
new file mode 100644
index 0000000..bfa0705
--- /dev/null
+++ b/src/test/ui/issues/issue-49824.nll.stderr
@@ -0,0 +1,29 @@
+warning: captured variable cannot escape `FnMut` closure body
+  --> $DIR/issue-49824.rs:12:9
+   |
+LL |       || {
+   |        - inferred to be a `FnMut` closure
+LL | /         || {
+LL | |             let _y = &mut x;
+LL | |         }
+   | |_________^ returns a closure that contains a reference to a captured variable, which then escapes the closure body
+   |
+   = note: `FnMut` closures only have access to their captured variables while they are executing...
+   = note: ...therefore, they cannot allow references to captured variables to escape
+   = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
+   = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+
+error: compilation successful
+  --> $DIR/issue-49824.rs:8:1
+   |
+LL | / fn main() {
+LL | |
+LL | |     let mut x = 0;
+LL | |     || {
+...  |
+LL | |     };
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-49824.rs b/src/test/ui/issues/issue-49824.rs
new file mode 100644
index 0000000..58cada5
--- /dev/null
+++ b/src/test/ui/issues/issue-49824.rs
@@ -0,0 +1,16 @@
+#![feature(rustc_attrs)]
+
+// This test checks that a failure occurs with NLL but does not fail with the
+// legacy AST output. Check issue-49824.nll.stderr for expected compilation error
+// output under NLL and #49824 for more information.
+
+#[rustc_error]
+fn main() {
+    //~^ compilation successful
+    let mut x = 0;
+    || {
+        || {
+            let _y = &mut x;
+        }
+    };
+}
diff --git a/src/test/ui/issues/issue-49824.stderr b/src/test/ui/issues/issue-49824.stderr
new file mode 100644
index 0000000..4ad537f
--- /dev/null
+++ b/src/test/ui/issues/issue-49824.stderr
@@ -0,0 +1,14 @@
+error: compilation successful
+  --> $DIR/issue-49824.rs:8:1
+   |
+LL | / fn main() {
+LL | |
+LL | |     let mut x = 0;
+LL | |     || {
+...  |
+LL | |     };
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-49851/compiler-builtins-error.rs b/src/test/ui/issues/issue-49851/compiler-builtins-error.rs
new file mode 100644
index 0000000..0163da0
--- /dev/null
+++ b/src/test/ui/issues/issue-49851/compiler-builtins-error.rs
@@ -0,0 +1,11 @@
+//~ ERROR 1:1: 1:1: can't find crate for `core` [E0463]
+// http://rust-lang.org/COPYRIGHT.
+//
+
+// compile-flags: --target thumbv7em-none-eabihf
+#![deny(unsafe_code)]
+#![deny(warnings)]
+#![no_std]
+
+extern crate cortex_m;
+
diff --git a/src/test/ui/issues/issue-49851/compiler-builtins-error.stderr b/src/test/ui/issues/issue-49851/compiler-builtins-error.stderr
new file mode 100644
index 0000000..7e23e0f
--- /dev/null
+++ b/src/test/ui/issues/issue-49851/compiler-builtins-error.stderr
@@ -0,0 +1,7 @@
+error[E0463]: can't find crate for `core`
+   |
+   = note: the `thumbv7em-none-eabihf` target may not be installed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0463`.
diff --git a/src/test/ui/issues/issue-49934.rs b/src/test/ui/issues/issue-49934.rs
new file mode 100644
index 0000000..ad410f3
--- /dev/null
+++ b/src/test/ui/issues/issue-49934.rs
@@ -0,0 +1,42 @@
+// compile-pass
+
+#![feature(stmt_expr_attributes)]
+#![warn(unused_attributes)] //~ NOTE lint level defined here
+
+fn foo<#[derive(Debug)] T>() { //~ WARN unused attribute
+    match 0 {
+        #[derive(Debug)] //~ WARN unused attribute
+        _ => (),
+    }
+}
+
+fn main() {
+    // fold_stmt (Item)
+    #[allow(dead_code)]
+    #[derive(Debug)] // should not warn
+    struct Foo;
+
+    // fold_stmt (Mac)
+    #[derive(Debug)]
+    //~^ WARN `#[derive]` does nothing on macro invocations
+    //~| NOTE this may become a hard error in a future release
+    println!("Hello, world!");
+
+    // fold_stmt (Semi)
+    #[derive(Debug)] //~ WARN unused attribute
+    "Hello, world!";
+
+    // fold_stmt (Local)
+    #[derive(Debug)] //~ WARN unused attribute
+    let _ = "Hello, world!";
+
+    // visit_expr
+    let _ = #[derive(Debug)] "Hello, world!";
+    //~^ WARN unused attribute
+
+    let _ = [
+        // filter_map_expr
+        #[derive(Debug)] //~ WARN unused attribute
+        "Hello, world!"
+    ];
+}
diff --git a/src/test/ui/issues/issue-49934.stderr b/src/test/ui/issues/issue-49934.stderr
new file mode 100644
index 0000000..6ca751a
--- /dev/null
+++ b/src/test/ui/issues/issue-49934.stderr
@@ -0,0 +1,50 @@
+warning: `#[derive]` does nothing on macro invocations
+  --> $DIR/issue-49934.rs:20:5
+   |
+LL |     #[derive(Debug)]
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = note: this may become a hard error in a future release
+
+warning: unused attribute
+  --> $DIR/issue-49934.rs:6:8
+   |
+LL | fn foo<#[derive(Debug)] T>() {
+   |        ^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/issue-49934.rs:4:9
+   |
+LL | #![warn(unused_attributes)]
+   |         ^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-49934.rs:8:9
+   |
+LL |         #[derive(Debug)]
+   |         ^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-49934.rs:26:5
+   |
+LL |     #[derive(Debug)]
+   |     ^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-49934.rs:30:5
+   |
+LL |     #[derive(Debug)]
+   |     ^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-49934.rs:34:13
+   |
+LL |     let _ = #[derive(Debug)] "Hello, world!";
+   |             ^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-49934.rs:39:9
+   |
+LL |         #[derive(Debug)]
+   |         ^^^^^^^^^^^^^^^^
+
diff --git a/src/test/ui/issues/issue-50187.rs b/src/test/ui/issues/issue-50187.rs
new file mode 100644
index 0000000..cda1c4d
--- /dev/null
+++ b/src/test/ui/issues/issue-50187.rs
@@ -0,0 +1,39 @@
+// compile-pass
+
+#![feature(decl_macro)]
+
+mod type_ns {
+    pub type A = u8;
+}
+mod value_ns {
+    pub const A: u8 = 0;
+}
+mod macro_ns {
+    pub macro A() {}
+}
+
+mod merge2 {
+    pub use type_ns::A;
+    pub use value_ns::A;
+}
+mod merge3 {
+    pub use type_ns::A;
+    pub use value_ns::A;
+    pub use macro_ns::A;
+}
+
+mod use2 {
+    pub use merge2::A;
+}
+mod use3 {
+    pub use merge3::A;
+}
+
+fn main() {
+    type B2 = use2::A;
+    let a2 = use2::A;
+
+    type B3 = use3::A;
+    let a3 = use3::A;
+    use3::A!();
+}
diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/option-deref.rs b/src/test/ui/issues/issue-50264-inner-deref-trait/option-deref.rs
new file mode 100644
index 0000000..f82eafc
--- /dev/null
+++ b/src/test/ui/issues/issue-50264-inner-deref-trait/option-deref.rs
@@ -0,0 +1,6 @@
+#![feature(inner_deref)]
+
+fn main() {
+    let _result = &Some(42).deref();
+//~^ ERROR no method named `deref` found for type `std::option::Option<{integer}>`
+}
diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/option-deref.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/option-deref.stderr
new file mode 100644
index 0000000..e916b7d
--- /dev/null
+++ b/src/test/ui/issues/issue-50264-inner-deref-trait/option-deref.stderr
@@ -0,0 +1,12 @@
+error[E0599]: no method named `deref` found for type `std::option::Option<{integer}>` in the current scope
+  --> $DIR/option-deref.rs:4:29
+   |
+LL |     let _result = &Some(42).deref();
+   |                             ^^^^^
+   |
+   = note: the method `deref` exists but the following trait bounds were not satisfied:
+           `{integer} : std::ops::Deref`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-deref-err.rs b/src/test/ui/issues/issue-50264-inner-deref-trait/result-deref-err.rs
new file mode 100644
index 0000000..4be2000
--- /dev/null
+++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-deref-err.rs
@@ -0,0 +1,6 @@
+#![feature(inner_deref)]
+
+fn main() {
+    let _result = &Err(41).deref_err();
+//~^ ERROR no method named `deref_err` found
+}
diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-deref-err.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-deref-err.stderr
new file mode 100644
index 0000000..96d6814
--- /dev/null
+++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-deref-err.stderr
@@ -0,0 +1,12 @@
+error[E0599]: no method named `deref_err` found for type `std::result::Result<_, {integer}>` in the current scope
+  --> $DIR/result-deref-err.rs:4:28
+   |
+LL |     let _result = &Err(41).deref_err();
+   |                            ^^^^^^^^^ help: did you mean: `deref_ok`
+   |
+   = note: the method `deref_err` exists but the following trait bounds were not satisfied:
+           `{integer} : std::ops::Deref`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-deref-ok.rs b/src/test/ui/issues/issue-50264-inner-deref-trait/result-deref-ok.rs
new file mode 100644
index 0000000..a706cde
--- /dev/null
+++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-deref-ok.rs
@@ -0,0 +1,6 @@
+#![feature(inner_deref)]
+
+fn main() {
+    let _result = &Ok(42).deref_ok();
+//~^ ERROR no method named `deref_ok` found
+}
diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-deref-ok.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-deref-ok.stderr
new file mode 100644
index 0000000..5937051
--- /dev/null
+++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-deref-ok.stderr
@@ -0,0 +1,12 @@
+error[E0599]: no method named `deref_ok` found for type `std::result::Result<{integer}, _>` in the current scope
+  --> $DIR/result-deref-ok.rs:4:27
+   |
+LL |     let _result = &Ok(42).deref_ok();
+   |                           ^^^^^^^^
+   |
+   = note: the method `deref_ok` exists but the following trait bounds were not satisfied:
+           `{integer} : std::ops::Deref`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-deref.rs b/src/test/ui/issues/issue-50264-inner-deref-trait/result-deref.rs
new file mode 100644
index 0000000..43a68e3
--- /dev/null
+++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-deref.rs
@@ -0,0 +1,6 @@
+#![feature(inner_deref)]
+
+fn main() {
+    let _result = &Ok(42).deref();
+//~^ ERROR no method named `deref` found
+}
diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-deref.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-deref.stderr
new file mode 100644
index 0000000..05baa79
--- /dev/null
+++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-deref.stderr
@@ -0,0 +1,12 @@
+error[E0599]: no method named `deref` found for type `std::result::Result<{integer}, _>` in the current scope
+  --> $DIR/result-deref.rs:4:27
+   |
+LL |     let _result = &Ok(42).deref();
+   |                           ^^^^^
+   |
+   = note: the method `deref` exists but the following trait bounds were not satisfied:
+           `{integer} : std::ops::Deref`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/issues/issue-50403.rs b/src/test/ui/issues/issue-50403.rs
new file mode 100644
index 0000000..012057f
--- /dev/null
+++ b/src/test/ui/issues/issue-50403.rs
@@ -0,0 +1,5 @@
+#![feature(concat_idents)]
+
+fn main() {
+    let x = concat_idents!(); //~ ERROR concat_idents! takes 1 or more arguments
+}
diff --git a/src/test/ui/issues/issue-50403.stderr b/src/test/ui/issues/issue-50403.stderr
new file mode 100644
index 0000000..d20a98e
--- /dev/null
+++ b/src/test/ui/issues/issue-50403.stderr
@@ -0,0 +1,8 @@
+error: concat_idents! takes 1 or more arguments.
+  --> $DIR/issue-50403.rs:4:13
+   |
+LL |     let x = concat_idents!();
+   |             ^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-50411.rs b/src/test/ui/issues/issue-50411.rs
new file mode 100644
index 0000000..1ba47d3
--- /dev/null
+++ b/src/test/ui/issues/issue-50411.rs
@@ -0,0 +1,11 @@
+// Regression test for #50411: the MIR inliner was causing problems
+// here because it would inline promoted code (which had already had
+// elaborate-drops invoked on it) and then try to elaboate drops a
+// second time. Uncool.
+
+// compile-flags:-Zmir-opt-level=3
+// compile-pass
+
+fn main() {
+    let _ = (0 .. 1).filter(|_| [1].iter().all(|_| true)).count();
+}
diff --git a/src/test/ui/issues/issue-50471.rs b/src/test/ui/issues/issue-50471.rs
new file mode 100644
index 0000000..6868d48
--- /dev/null
+++ b/src/test/ui/issues/issue-50471.rs
@@ -0,0 +1,9 @@
+// compile-pass
+
+fn main() {
+    assert!({false});
+
+    assert!(r"\u{41}" == "A");
+
+    assert!(r"\u{".is_empty());
+}
diff --git a/src/test/ui/issues/issue-50480.rs b/src/test/ui/issues/issue-50480.rs
new file mode 100644
index 0000000..31dbb75
--- /dev/null
+++ b/src/test/ui/issues/issue-50480.rs
@@ -0,0 +1,7 @@
+#[derive(Clone, Copy)]
+//~^ ERROR the trait `Copy` may not be implemented for this type
+struct Foo(NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+//~^ ERROR cannot find type `NotDefined` in this scope
+//~| ERROR `i32` is not an iterator
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-50480.stderr b/src/test/ui/issues/issue-50480.stderr
new file mode 100644
index 0000000..fb111e8
--- /dev/null
+++ b/src/test/ui/issues/issue-50480.stderr
@@ -0,0 +1,30 @@
+error[E0412]: cannot find type `NotDefined` in this scope
+  --> $DIR/issue-50480.rs:3:12
+   |
+LL | struct Foo(NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+   |            ^^^^^^^^^^ not found in this scope
+
+error[E0277]: `i32` is not an iterator
+  --> $DIR/issue-50480.rs:3:24
+   |
+LL | struct Foo(NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+   |                        ^^^^^^^^^^^^^^^^^^^^^^^ `i32` is not an iterator
+   |
+   = help: the trait `std::iter::Iterator` is not implemented for `i32`
+   = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
+
+error[E0204]: the trait `Copy` may not be implemented for this type
+  --> $DIR/issue-50480.rs:1:17
+   |
+LL | #[derive(Clone, Copy)]
+   |                 ^^^^
+LL |
+LL | struct Foo(NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+   |                                                 --------  ------ this field does not implement `Copy`
+   |                                                 |
+   |                                                 this field does not implement `Copy`
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0204, E0277, E0412.
+For more information about an error, try `rustc --explain E0204`.
diff --git a/src/test/ui/issues/issue-50576.rs b/src/test/ui/issues/issue-50576.rs
new file mode 100644
index 0000000..e0c36b8
--- /dev/null
+++ b/src/test/ui/issues/issue-50576.rs
@@ -0,0 +1,6 @@
+fn main() {
+    |bool: [u8; break 'L]| 0;
+    //~^ ERROR [E0426]
+    //~| ERROR [E0268]
+    Vec::<[u8; break]>::new(); //~ ERROR [E0268]
+}
diff --git a/src/test/ui/issues/issue-50576.stderr b/src/test/ui/issues/issue-50576.stderr
new file mode 100644
index 0000000..22d9782
--- /dev/null
+++ b/src/test/ui/issues/issue-50576.stderr
@@ -0,0 +1,22 @@
+error[E0426]: use of undeclared label `'L`
+  --> $DIR/issue-50576.rs:2:23
+   |
+LL |     |bool: [u8; break 'L]| 0;
+   |                       ^^ undeclared label `'L`
+
+error[E0268]: `break` outside of loop
+  --> $DIR/issue-50576.rs:2:17
+   |
+LL |     |bool: [u8; break 'L]| 0;
+   |                 ^^^^^^^^ cannot break outside of a loop
+
+error[E0268]: `break` outside of loop
+  --> $DIR/issue-50576.rs:5:16
+   |
+LL |     Vec::<[u8; break]>::new();
+   |                ^^^^^ cannot break outside of a loop
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0268, E0426.
+For more information about an error, try `rustc --explain E0268`.
diff --git a/src/test/ui/issues/issue-50577.rs b/src/test/ui/issues/issue-50577.rs
new file mode 100644
index 0000000..f0f1dc6
--- /dev/null
+++ b/src/test/ui/issues/issue-50577.rs
@@ -0,0 +1,6 @@
+fn main() {
+    enum Foo {
+        Drop = assert_eq!(1, 1)
+        //~^ ERROR if may be missing an else clause
+    }
+}
diff --git a/src/test/ui/issues/issue-50577.stderr b/src/test/ui/issues/issue-50577.stderr
new file mode 100644
index 0000000..0c3ba2e
--- /dev/null
+++ b/src/test/ui/issues/issue-50577.stderr
@@ -0,0 +1,18 @@
+error[E0317]: if may be missing an else clause
+  --> $DIR/issue-50577.rs:3:16
+   |
+LL |         Drop = assert_eq!(1, 1)
+   |                ^^^^^^^^^^^^^^^^
+   |                |
+   |                expected (), found isize
+   |                found here
+   |
+   = note: expected type `()`
+              found type `isize`
+   = note: `if` expressions without `else` evaluate to `()`
+   = help: consider adding an `else` block that evaluates to the expected type
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0317`.
diff --git a/src/test/ui/issues/issue-50581.rs b/src/test/ui/issues/issue-50581.rs
new file mode 100644
index 0000000..12bb993
--- /dev/null
+++ b/src/test/ui/issues/issue-50581.rs
@@ -0,0 +1,3 @@
+fn main() {
+    |_: [u8; break]| (); //~ ERROR [E0268]
+}
diff --git a/src/test/ui/issues/issue-50581.stderr b/src/test/ui/issues/issue-50581.stderr
new file mode 100644
index 0000000..01a5f9b
--- /dev/null
+++ b/src/test/ui/issues/issue-50581.stderr
@@ -0,0 +1,9 @@
+error[E0268]: `break` outside of loop
+  --> $DIR/issue-50581.rs:2:14
+   |
+LL |     |_: [u8; break]| ();
+   |              ^^^^^ cannot break outside of a loop
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0268`.
diff --git a/src/test/ui/issues/issue-50582.rs b/src/test/ui/issues/issue-50582.rs
new file mode 100644
index 0000000..1358e0b
--- /dev/null
+++ b/src/test/ui/issues/issue-50582.rs
@@ -0,0 +1,4 @@
+fn main() {
+    Vec::<[(); 1 + for x in 0..1 {}]>::new();
+    //~^ ERROR cannot add
+}
diff --git a/src/test/ui/issues/issue-50582.stderr b/src/test/ui/issues/issue-50582.stderr
new file mode 100644
index 0000000..226f5a3
--- /dev/null
+++ b/src/test/ui/issues/issue-50582.stderr
@@ -0,0 +1,11 @@
+error[E0277]: cannot add `()` to `{integer}`
+  --> $DIR/issue-50582.rs:2:18
+   |
+LL |     Vec::<[(); 1 + for x in 0..1 {}]>::new();
+   |                  ^ no implementation for `{integer} + ()`
+   |
+   = help: the trait `std::ops::Add<()>` is not implemented for `{integer}`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-50585.rs b/src/test/ui/issues/issue-50585.rs
new file mode 100644
index 0000000..ca2ece8
--- /dev/null
+++ b/src/test/ui/issues/issue-50585.rs
@@ -0,0 +1,4 @@
+fn main() {
+    |y: Vec<[(); for x in 0..2 {}]>| {};
+    //~^ ERROR mismatched types
+}
diff --git a/src/test/ui/issues/issue-50585.stderr b/src/test/ui/issues/issue-50585.stderr
new file mode 100644
index 0000000..4c41da8
--- /dev/null
+++ b/src/test/ui/issues/issue-50585.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-50585.rs:2:18
+   |
+LL |     |y: Vec<[(); for x in 0..2 {}]>| {};
+   |                  ^^^^^^^^^^^^^^^^ expected usize, found ()
+   |
+   = note: expected type `usize`
+              found type `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-50599.rs b/src/test/ui/issues/issue-50599.rs
new file mode 100644
index 0000000..78a20cf
--- /dev/null
+++ b/src/test/ui/issues/issue-50599.rs
@@ -0,0 +1,6 @@
+fn main() {
+    const N: u32 = 1_000;
+    const M: usize = (f64::from(N) * std::f64::LOG10_2) as usize; //~ ERROR cannot find value
+    let mut digits = [0u32; M];
+    //~^ ERROR evaluation of constant value failed
+}
diff --git a/src/test/ui/issues/issue-50599.stderr b/src/test/ui/issues/issue-50599.stderr
new file mode 100644
index 0000000..e0c9bea
--- /dev/null
+++ b/src/test/ui/issues/issue-50599.stderr
@@ -0,0 +1,22 @@
+error[E0425]: cannot find value `LOG10_2` in module `std::f64`
+  --> $DIR/issue-50599.rs:3:48
+   |
+LL |     const M: usize = (f64::from(N) * std::f64::LOG10_2) as usize;
+   |                                                ^^^^^^^ not found in `std::f64`
+help: possible candidates are found in other modules, you can import them into scope
+   |
+LL | use std::f32::consts::LOG10_2;
+   |
+LL | use std::f64::consts::LOG10_2;
+   |
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/issue-50599.rs:4:29
+   |
+LL |     let mut digits = [0u32; M];
+   |                             ^ referenced constant has errors
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0080, E0425.
+For more information about an error, try `rustc --explain E0080`.
diff --git a/src/test/ui/issues/issue-50600.rs b/src/test/ui/issues/issue-50600.rs
new file mode 100644
index 0000000..963e607
--- /dev/null
+++ b/src/test/ui/issues/issue-50600.rs
@@ -0,0 +1,5 @@
+struct Foo (
+    fn([u8; |x: u8| {}]), //~ ERROR mismatched types
+);
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-50600.stderr b/src/test/ui/issues/issue-50600.stderr
new file mode 100644
index 0000000..2d97c27
--- /dev/null
+++ b/src/test/ui/issues/issue-50600.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-50600.rs:2:13
+   |
+LL |     fn([u8; |x: u8| {}]),
+   |             ^^^^^^^^^^ expected usize, found closure
+   |
+   = note: expected type `usize`
+              found type `[closure@$DIR/issue-50600.rs:2:13: 2:23]`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-50618.rs b/src/test/ui/issues/issue-50618.rs
new file mode 100644
index 0000000..5f762bc
--- /dev/null
+++ b/src/test/ui/issues/issue-50618.rs
@@ -0,0 +1,19 @@
+struct Point {
+    pub x: u64,
+    pub y: u64,
+}
+
+const TEMPLATE: Point = Point {
+    x: 0,
+    y: 0
+};
+
+fn main() {
+    let _ = || {
+        Point {
+            nonexistent: 0,
+            //~^ ERROR struct `Point` has no field named `nonexistent`
+            ..TEMPLATE
+        }
+    };
+}
diff --git a/src/test/ui/issues/issue-50618.stderr b/src/test/ui/issues/issue-50618.stderr
new file mode 100644
index 0000000..1ac5dde
--- /dev/null
+++ b/src/test/ui/issues/issue-50618.stderr
@@ -0,0 +1,11 @@
+error[E0560]: struct `Point` has no field named `nonexistent`
+  --> $DIR/issue-50618.rs:14:13
+   |
+LL |             nonexistent: 0,
+   |             ^^^^^^^^^^^ `Point` does not have this field
+   |
+   = note: available fields are: `x`, `y`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0560`.
diff --git a/src/test/ui/issues/issue-5062.rs b/src/test/ui/issues/issue-5062.rs
new file mode 100644
index 0000000..2db0a8e
--- /dev/null
+++ b/src/test/ui/issues/issue-5062.rs
@@ -0,0 +1,2 @@
+fn main() { format!("{:?}", None); }
+    //~^ ERROR type annotations needed [E0282]
diff --git a/src/test/ui/issues/issue-5062.stderr b/src/test/ui/issues/issue-5062.stderr
new file mode 100644
index 0000000..0f5c6d8
--- /dev/null
+++ b/src/test/ui/issues/issue-5062.stderr
@@ -0,0 +1,9 @@
+error[E0282]: type annotations needed
+  --> $DIR/issue-5062.rs:1:29
+   |
+LL | fn main() { format!("{:?}", None); }
+   |                             ^^^^ cannot infer type for `T`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/issues/issue-5067.rs b/src/test/ui/issues/issue-5067.rs
new file mode 100644
index 0000000..616fd09
--- /dev/null
+++ b/src/test/ui/issues/issue-5067.rs
@@ -0,0 +1,75 @@
+#![allow(unused_macros)]
+
+// Tests that repetition matchers cannot match the empty token tree (since that would be
+// ambiguous).
+
+// edition:2018
+
+macro_rules! foo {
+    ( $()* ) => {};
+    //~^ ERROR repetition matches empty token tree
+    ( $()+ ) => {};
+    //~^ ERROR repetition matches empty token tree
+    ( $()? ) => {};
+    //~^ ERROR repetition matches empty token tree
+    ( $(),* ) => {}; // PASS
+    ( $(),+ ) => {}; // PASS
+    // `?` cannot have a separator...
+    ( [$()*] ) => {};
+    //~^ ERROR repetition matches empty token tree
+    ( [$()+] ) => {};
+    //~^ ERROR repetition matches empty token tree
+    ( [$()?] ) => {};
+    //~^ ERROR repetition matches empty token tree
+    ( [$(),*] ) => {}; // PASS
+    ( [$(),+] ) => {}; // PASS
+    // `?` cannot have a separator...
+    ( $($()* $(),* $(a)* $(a),* )* ) => {};
+    //~^ ERROR repetition matches empty token tree
+    ( $($()* $(),* $(a)* $(a),* )+ ) => {};
+    //~^ ERROR repetition matches empty token tree
+    ( $($()* $(),* $(a)* $(a),* )? ) => {};
+    //~^ ERROR repetition matches empty token tree
+    ( $($()? $(),* $(a)? $(a),* )* ) => {};
+    //~^ ERROR repetition matches empty token tree
+    ( $($()? $(),* $(a)? $(a),* )+ ) => {};
+    //~^ ERROR repetition matches empty token tree
+    ( $($()? $(),* $(a)? $(a),* )? ) => {};
+    //~^ ERROR repetition matches empty token tree
+    ( $(a     $(),* $(a)* $(a),* )* ) => {}; // PASS
+    ( $($(a)+ $(),* $(a)* $(a),* )+ ) => {}; // PASS
+    ( $($(a)+ $(),* $(a)* $(a),* )? ) => {}; // PASS
+
+    ( $(a     $(),* $(a)? $(a),* )* ) => {}; // PASS
+    ( $($(a)+ $(),* $(a)? $(a),* )+ ) => {}; // PASS
+    ( $($(a)+ $(),* $(a)? $(a),* )? ) => {}; // PASS
+
+    ( $(a $()+)* ) => {};
+    //~^ ERROR repetition matches empty token tree
+    ( $(a $()*)+ ) => {};
+    //~^ ERROR repetition matches empty token tree
+    ( $(a $()+)? ) => {};
+    //~^ ERROR repetition matches empty token tree
+    ( $(a $()?)+ ) => {};
+    //~^ ERROR repetition matches empty token tree
+}
+
+// --- Original Issue --- //
+
+macro_rules! make_vec {
+    (a $e1:expr $($(, a $e2:expr)*)*) => ([$e1 $($(, $e2)*)*]);
+    //~^ ERROR repetition matches empty token tree
+}
+
+fn main() {
+    let _ = make_vec![a 1, a 2, a 3];
+}
+
+// --- Minified Issue --- //
+
+macro_rules! m {
+    ( $()* ) => {};
+    //~^ ERROR repetition matches empty token tree
+}
+
+m!();
diff --git a/src/test/ui/issues/issue-5067.stderr b/src/test/ui/issues/issue-5067.stderr
new file mode 100644
index 0000000..7ffc607
--- /dev/null
+++ b/src/test/ui/issues/issue-5067.stderr
@@ -0,0 +1,110 @@
+error: repetition matches empty token tree
+  --> $DIR/issue-5067.rs:9:8
+   |
+LL |     ( $()* ) => {};
+   |        ^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-5067.rs:11:8
+   |
+LL |     ( $()+ ) => {};
+   |        ^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-5067.rs:13:8
+   |
+LL |     ( $()? ) => {};
+   |        ^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-5067.rs:18:9
+   |
+LL |     ( [$()*] ) => {};
+   |         ^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-5067.rs:20:9
+   |
+LL |     ( [$()+] ) => {};
+   |         ^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-5067.rs:22:9
+   |
+LL |     ( [$()?] ) => {};
+   |         ^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-5067.rs:27:8
+   |
+LL |     ( $($()* $(),* $(a)* $(a),* )* ) => {};
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-5067.rs:29:8
+   |
+LL |     ( $($()* $(),* $(a)* $(a),* )+ ) => {};
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-5067.rs:31:8
+   |
+LL |     ( $($()* $(),* $(a)* $(a),* )? ) => {};
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-5067.rs:33:8
+   |
+LL |     ( $($()? $(),* $(a)? $(a),* )* ) => {};
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-5067.rs:35:8
+   |
+LL |     ( $($()? $(),* $(a)? $(a),* )+ ) => {};
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-5067.rs:37:8
+   |
+LL |     ( $($()? $(),* $(a)? $(a),* )? ) => {};
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-5067.rs:47:12
+   |
+LL |     ( $(a $()+)* ) => {};
+   |            ^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-5067.rs:49:12
+   |
+LL |     ( $(a $()*)+ ) => {};
+   |            ^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-5067.rs:51:12
+   |
+LL |     ( $(a $()+)? ) => {};
+   |            ^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-5067.rs:53:12
+   |
+LL |     ( $(a $()?)+ ) => {};
+   |            ^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-5067.rs:60:18
+   |
+LL |     (a $e1:expr $($(, a $e2:expr)*)*) => ([$e1 $($(, $e2)*)*]);
+   |                  ^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-5067.rs:71:8
+   |
+LL |     ( $()* ) => {};
+   |        ^^
+
+error: aborting due to 18 previous errors
+
diff --git a/src/test/ui/issues/issue-50688.rs b/src/test/ui/issues/issue-50688.rs
new file mode 100644
index 0000000..88f898b
--- /dev/null
+++ b/src/test/ui/issues/issue-50688.rs
@@ -0,0 +1,3 @@
+fn main() {
+    [1; || {}]; //~ ERROR mismatched types
+}
diff --git a/src/test/ui/issues/issue-50688.stderr b/src/test/ui/issues/issue-50688.stderr
new file mode 100644
index 0000000..13eec83
--- /dev/null
+++ b/src/test/ui/issues/issue-50688.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-50688.rs:2:9
+   |
+LL |     [1; || {}];
+   |         ^^^^^ expected usize, found closure
+   |
+   = note: expected type `usize`
+              found type `[closure@$DIR/issue-50688.rs:2:9: 2:14]`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-50714-1.rs b/src/test/ui/issues/issue-50714-1.rs
new file mode 100644
index 0000000..31de3f3
--- /dev/null
+++ b/src/test/ui/issues/issue-50714-1.rs
@@ -0,0 +1,12 @@
+// Regression test for issue 50714, make sure that this isn't a linker error.
+
+#![no_std]
+#![feature(start)]
+
+extern crate std;
+
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize where fn(&()): Eq { //~ ERROR [E0647]
+    0
+}
+
diff --git a/src/test/ui/issues/issue-50714-1.stderr b/src/test/ui/issues/issue-50714-1.stderr
new file mode 100644
index 0000000..427b200
--- /dev/null
+++ b/src/test/ui/issues/issue-50714-1.stderr
@@ -0,0 +1,9 @@
+error[E0647]: start function is not allowed to have a `where` clause
+  --> $DIR/issue-50714-1.rs:9:56
+   |
+LL | fn start(_: isize, _: *const *const u8) -> isize where fn(&()): Eq {
+   |                                                        ^^^^^^^^^^^ start function cannot have a `where` clause
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0647`.
diff --git a/src/test/ui/issues/issue-50714.rs b/src/test/ui/issues/issue-50714.rs
new file mode 100644
index 0000000..3683d4b
--- /dev/null
+++ b/src/test/ui/issues/issue-50714.rs
@@ -0,0 +1,4 @@
+// Regression test for issue 50714, make sure that this isn't a linker error.
+
+fn main() where fn(&()): Eq {} //~ ERROR [E0646]
+
diff --git a/src/test/ui/issues/issue-50714.stderr b/src/test/ui/issues/issue-50714.stderr
new file mode 100644
index 0000000..e048f39
--- /dev/null
+++ b/src/test/ui/issues/issue-50714.stderr
@@ -0,0 +1,9 @@
+error[E0646]: `main` function is not allowed to have a `where` clause
+  --> $DIR/issue-50714.rs:3:17
+   |
+LL | fn main() where fn(&()): Eq {}
+   |                 ^^^^^^^^^^^ `main` cannot have a `where` clause
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0646`.
diff --git a/src/test/ui/issues/issue-50761.rs b/src/test/ui/issues/issue-50761.rs
new file mode 100644
index 0000000..bcf3ebc
--- /dev/null
+++ b/src/test/ui/issues/issue-50761.rs
@@ -0,0 +1,23 @@
+// Confirm that we don't accidentally divide or mod by zero in llvm_type
+
+// compile-pass
+
+mod a {
+    pub trait A {}
+}
+
+mod b {
+    pub struct Builder {}
+
+    pub fn new() -> Builder {
+        Builder {}
+    }
+
+    impl Builder {
+        pub fn with_a(&mut self, _a: fn() -> ::a::A) {}
+    }
+}
+
+pub use self::b::new;
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-50781.rs b/src/test/ui/issues/issue-50781.rs
new file mode 100644
index 0000000..edf8d82
--- /dev/null
+++ b/src/test/ui/issues/issue-50781.rs
@@ -0,0 +1,19 @@
+#![deny(where_clauses_object_safety)]
+
+trait Trait {}
+
+trait X {
+    fn foo(&self) where Self: Trait; //~ ERROR the trait `X` cannot be made into an object
+    //~^ WARN this was previously accepted by the compiler but is being phased out
+}
+
+impl X for () {
+    fn foo(&self) {}
+}
+
+impl Trait for dyn X {}
+
+pub fn main() {
+    // Check that this does not segfault.
+    <X as X>::foo(&());
+}
diff --git a/src/test/ui/issues/issue-50781.stderr b/src/test/ui/issues/issue-50781.stderr
new file mode 100644
index 0000000..c98f78c
--- /dev/null
+++ b/src/test/ui/issues/issue-50781.stderr
@@ -0,0 +1,17 @@
+error: the trait `X` cannot be made into an object
+  --> $DIR/issue-50781.rs:6:5
+   |
+LL |     fn foo(&self) where Self: Trait;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/issue-50781.rs:1:9
+   |
+LL | #![deny(where_clauses_object_safety)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #51443 <https://github.com/rust-lang/rust/issues/51443>
+   = note: method `foo` references the `Self` type in where clauses
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-50802.rs b/src/test/ui/issues/issue-50802.rs
new file mode 100644
index 0000000..dece559
--- /dev/null
+++ b/src/test/ui/issues/issue-50802.rs
@@ -0,0 +1,8 @@
+#[allow(unreachable_code)]
+
+fn main() {
+    loop {
+        break while continue { //~ ERROR E0590
+        }
+    }
+}
diff --git a/src/test/ui/issues/issue-50802.stderr b/src/test/ui/issues/issue-50802.stderr
new file mode 100644
index 0000000..e064fab
--- /dev/null
+++ b/src/test/ui/issues/issue-50802.stderr
@@ -0,0 +1,9 @@
+error[E0590]: `break` or `continue` with no label in the condition of a `while` loop
+  --> $DIR/issue-50802.rs:5:21
+   |
+LL |         break while continue {
+   |                     ^^^^^^^^ unlabeled `continue` in the condition of a `while` loop
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0590`.
diff --git a/src/test/ui/issues/issue-50825-1.rs b/src/test/ui/issues/issue-50825-1.rs
new file mode 100644
index 0000000..ee43160
--- /dev/null
+++ b/src/test/ui/issues/issue-50825-1.rs
@@ -0,0 +1,22 @@
+// run-pass
+// regression test for issue #50825
+// Make sure that the `impl` bound (): X<T = ()> is preferred over
+// the (): X bound in the where clause.
+
+trait X {
+    type T;
+}
+
+trait Y<U>: X {
+    fn foo(x: &Self::T);
+}
+
+impl X for () {
+    type T = ();
+}
+
+impl<T> Y<Vec<T>> for () where (): Y<T> {
+    fn foo(_x: &()) {}
+}
+
+fn main () {}
diff --git a/src/test/ui/issues/issue-50825.rs b/src/test/ui/issues/issue-50825.rs
new file mode 100644
index 0000000..1ece2e9
--- /dev/null
+++ b/src/test/ui/issues/issue-50825.rs
@@ -0,0 +1,15 @@
+// run-pass
+// regression test for issue #50825
+// Make sure that the built-in bound {integer}: Sized is preferred over
+// the u64: Sized bound in the where clause.
+
+fn foo(y: &[()])
+where
+    u64: Sized,
+{
+    y[0]
+}
+
+fn main () {
+    foo(&[()]);
+}
diff --git a/src/test/ui/issues/issue-5099.rs b/src/test/ui/issues/issue-5099.rs
new file mode 100644
index 0000000..d00fff3
--- /dev/null
+++ b/src/test/ui/issues/issue-5099.rs
@@ -0,0 +1,3 @@
+trait B < A > { fn a() -> A { this.a } } //~ ERROR cannot find value `this` in this scope
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-5099.stderr b/src/test/ui/issues/issue-5099.stderr
new file mode 100644
index 0000000..cc11db9
--- /dev/null
+++ b/src/test/ui/issues/issue-5099.stderr
@@ -0,0 +1,9 @@
+error[E0425]: cannot find value `this` in this scope
+  --> $DIR/issue-5099.rs:1:31
+   |
+LL | trait B < A > { fn a() -> A { this.a } }
+   |                               ^^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/issues/issue-50993.rs b/src/test/ui/issues/issue-50993.rs
new file mode 100644
index 0000000..772c45d
--- /dev/null
+++ b/src/test/ui/issues/issue-50993.rs
@@ -0,0 +1,8 @@
+// compile-flags: --crate-type dylib --target thumbv7em-none-eabihf
+// compile-pass
+// error-pattern: dropping unsupported crate type `dylib` for target `thumbv7em-none-eabihf`
+
+#![feature(no_core)]
+
+#![no_std]
+#![no_core]
diff --git a/src/test/ui/issues/issue-50993.stderr b/src/test/ui/issues/issue-50993.stderr
new file mode 100644
index 0000000..d7b33a2
--- /dev/null
+++ b/src/test/ui/issues/issue-50993.stderr
@@ -0,0 +1,2 @@
+warning: dropping unsupported crate type `dylib` for target `thumbv7em-none-eabihf`
+
diff --git a/src/test/ui/issues/issue-5100.rs b/src/test/ui/issues/issue-5100.rs
new file mode 100644
index 0000000..505dfbb
--- /dev/null
+++ b/src/test/ui/issues/issue-5100.rs
@@ -0,0 +1,57 @@
+#![feature(box_patterns)]
+#![feature(box_syntax)]
+
+enum A { B, C }
+
+fn main() {
+    match (true, false) {
+        A::B => (),
+//~^ ERROR mismatched types
+//~| expected type `(bool, bool)`
+//~| found type `A`
+//~| expected tuple, found enum `A`
+        _ => ()
+    }
+
+    match (true, false) {
+        (true, false, false) => ()
+//~^ ERROR mismatched types
+//~| expected type `(bool, bool)`
+//~| found type `(_, _, _)`
+//~| expected a tuple with 2 elements, found one with 3 elements
+    }
+
+    match (true, false) {
+        (true, false, false) => ()
+//~^ ERROR mismatched types
+//~| expected type `(bool, bool)`
+//~| found type `(_, _, _)`
+//~| expected a tuple with 2 elements, found one with 3 elements
+    }
+
+    match (true, false) {
+        box (true, false) => ()
+//~^ ERROR mismatched types
+//~| expected type `(bool, bool)`
+//~| found type `std::boxed::Box<_>`
+    }
+
+    match (true, false) {
+        &(true, false) => ()
+//~^ ERROR mismatched types
+//~| expected type `(bool, bool)`
+//~| found type `&_`
+//~| expected tuple, found reference
+    }
+
+
+    let v = [('a', 'b')   //~ ERROR expected function, found `(char, char)`
+             ('c', 'd'),
+             ('e', 'f')];
+
+    for &(x,y) in &v {} // should be OK
+
+    // Make sure none of the errors above were fatal
+    let x: char = true; //~  ERROR mismatched types
+                        //~| expected char, found bool
+}
diff --git a/src/test/ui/issues/issue-5100.stderr b/src/test/ui/issues/issue-5100.stderr
new file mode 100644
index 0000000..0c1a028
--- /dev/null
+++ b/src/test/ui/issues/issue-5100.stderr
@@ -0,0 +1,65 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-5100.rs:8:9
+   |
+LL |         A::B => (),
+   |         ^^^^ expected tuple, found enum `A`
+   |
+   = note: expected type `(bool, bool)`
+              found type `A`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-5100.rs:17:9
+   |
+LL |         (true, false, false) => ()
+   |         ^^^^^^^^^^^^^^^^^^^^ expected a tuple with 2 elements, found one with 3 elements
+   |
+   = note: expected type `(bool, bool)`
+              found type `(_, _, _)`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-5100.rs:25:9
+   |
+LL |         (true, false, false) => ()
+   |         ^^^^^^^^^^^^^^^^^^^^ expected a tuple with 2 elements, found one with 3 elements
+   |
+   = note: expected type `(bool, bool)`
+              found type `(_, _, _)`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-5100.rs:33:9
+   |
+LL |     match (true, false) {
+   |           ------------- this match expression has type `(bool, bool)`
+LL |         box (true, false) => ()
+   |         ^^^^^^^^^^^^^^^^^ expected tuple, found struct `std::boxed::Box`
+   |
+   = note: expected type `(bool, bool)`
+              found type `std::boxed::Box<_>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-5100.rs:40:9
+   |
+LL |         &(true, false) => ()
+   |         ^^^^^^^^^^^^^^ expected tuple, found reference
+   |
+   = note: expected type `(bool, bool)`
+              found type `&_`
+
+error[E0618]: expected function, found `(char, char)`
+  --> $DIR/issue-5100.rs:48:14
+   |
+LL |       let v = [('a', 'b')
+   |  ______________-^^^^^^^^^
+LL | |              ('c', 'd'),
+   | |_______________________- call expression requires function
+
+error[E0308]: mismatched types
+  --> $DIR/issue-5100.rs:55:19
+   |
+LL |     let x: char = true;
+   |                   ^^^^ expected char, found bool
+
+error: aborting due to 7 previous errors
+
+Some errors occurred: E0308, E0618.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-51022.rs b/src/test/ui/issues/issue-51022.rs
new file mode 100644
index 0000000..cebdfe0
--- /dev/null
+++ b/src/test/ui/issues/issue-51022.rs
@@ -0,0 +1,2 @@
+fn main<'a>() { }
+    //~^ ERROR `main` function is not allowed to have generic parameters [E0131]
diff --git a/src/test/ui/issues/issue-51022.stderr b/src/test/ui/issues/issue-51022.stderr
new file mode 100644
index 0000000..5e196bd
--- /dev/null
+++ b/src/test/ui/issues/issue-51022.stderr
@@ -0,0 +1,9 @@
+error[E0131]: `main` function is not allowed to have generic parameters
+  --> $DIR/issue-51022.rs:1:8
+   |
+LL | fn main<'a>() { }
+   |        ^^^^ `main` cannot have generic parameters
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0131`.
diff --git a/src/test/ui/issues/issue-51044.rs b/src/test/ui/issues/issue-51044.rs
new file mode 100644
index 0000000..628d787
--- /dev/null
+++ b/src/test/ui/issues/issue-51044.rs
@@ -0,0 +1,30 @@
+// run-pass
+// regression test for issue #50825
+// Check that the feature gate normalizes associated types.
+
+#![allow(dead_code)]
+struct Foo<T>(T);
+struct Duck;
+struct Quack;
+
+trait Hello<A> where A: Animal {
+}
+
+trait Animal {
+    type Noise;
+}
+
+trait Loud<R>  {
+}
+
+impl Loud<Quack> for f32 {
+}
+
+impl Animal for Duck {
+    type Noise = Quack;
+}
+
+impl Hello<Duck> for Foo<f32> where f32: Loud<<Duck as Animal>::Noise> {
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-51102.rs b/src/test/ui/issues/issue-51102.rs
new file mode 100644
index 0000000..41446cd
--- /dev/null
+++ b/src/test/ui/issues/issue-51102.rs
@@ -0,0 +1,38 @@
+enum SimpleEnum {
+    NoState,
+}
+
+struct SimpleStruct {
+    no_state_here: u64,
+}
+
+fn main() {
+    let _ = |simple| {
+        match simple {
+            SimpleStruct {
+                state: 0,
+                //~^ struct `SimpleStruct` does not have a field named `state` [E0026]
+                ..
+            } => (),
+        }
+    };
+
+    let _ = |simple| {
+        match simple {
+            SimpleStruct {
+                no_state_here: 0,
+                no_state_here: 1
+                //~^ ERROR field `no_state_here` bound multiple times in the pattern [E0025]
+            } => (),
+        }
+    };
+
+    let _ = |simple| {
+        match simple {
+            SimpleEnum::NoState {
+                state: 0
+                //~^ ERROR variant `SimpleEnum::NoState` does not have a field named `state` [E0026]
+            } => (),
+        }
+    };
+}
diff --git a/src/test/ui/issues/issue-51102.stderr b/src/test/ui/issues/issue-51102.stderr
new file mode 100644
index 0000000..4d4b977
--- /dev/null
+++ b/src/test/ui/issues/issue-51102.stderr
@@ -0,0 +1,24 @@
+error[E0026]: struct `SimpleStruct` does not have a field named `state`
+  --> $DIR/issue-51102.rs:13:17
+   |
+LL |                 state: 0,
+   |                 ^^^^^ struct `SimpleStruct` does not have this field
+
+error[E0025]: field `no_state_here` bound multiple times in the pattern
+  --> $DIR/issue-51102.rs:24:17
+   |
+LL |                 no_state_here: 0,
+   |                 ---------------- first use of `no_state_here`
+LL |                 no_state_here: 1
+   |                 ^^^^^^^^^^^^^^^^ multiple uses of `no_state_here` in pattern
+
+error[E0026]: variant `SimpleEnum::NoState` does not have a field named `state`
+  --> $DIR/issue-51102.rs:33:17
+   |
+LL |                 state: 0
+   |                 ^^^^^ variant `SimpleEnum::NoState` does not have this field
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0025, E0026.
+For more information about an error, try `rustc --explain E0025`.
diff --git a/src/test/ui/issues/issue-51116.rs b/src/test/ui/issues/issue-51116.rs
new file mode 100644
index 0000000..c0a74a6
--- /dev/null
+++ b/src/test/ui/issues/issue-51116.rs
@@ -0,0 +1,14 @@
+fn main() {
+    let tiles = Default::default();
+    for row in &mut tiles {
+        for tile in row {
+            //~^ NOTE the element type for this iterator is not specified
+            *tile = 0;
+            //~^ ERROR type annotations needed
+            //~| NOTE cannot infer type
+            //~| NOTE type must be known at this point
+        }
+    }
+
+    let tiles: [[usize; 3]; 3] = tiles;
+}
diff --git a/src/test/ui/issues/issue-51116.stderr b/src/test/ui/issues/issue-51116.stderr
new file mode 100644
index 0000000..8501ae6
--- /dev/null
+++ b/src/test/ui/issues/issue-51116.stderr
@@ -0,0 +1,14 @@
+error[E0282]: type annotations needed
+  --> $DIR/issue-51116.rs:6:13
+   |
+LL |         for tile in row {
+   |                     --- the element type for this iterator is not specified
+LL |
+LL |             *tile = 0;
+   |             ^^^^^ cannot infer type
+   |
+   = note: type must be known at this point
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/issues/issue-51244.nll.stderr b/src/test/ui/issues/issue-51244.nll.stderr
new file mode 100644
index 0000000..c9108395
--- /dev/null
+++ b/src/test/ui/issues/issue-51244.nll.stderr
@@ -0,0 +1,11 @@
+error[E0594]: cannot assign to `*my_ref` which is behind a `&` reference
+  --> $DIR/issue-51244.rs:3:5
+   |
+LL |     let ref my_ref @ _ = 0;
+   |         -------------- help: consider changing this to be a mutable reference: `ref mut my_ref @ _`
+LL |     *my_ref = 0;
+   |     ^^^^^^^^^^^ `my_ref` is a `&` reference, so the data it refers to cannot be written
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/issues/issue-51244.rs b/src/test/ui/issues/issue-51244.rs
new file mode 100644
index 0000000..d365181
--- /dev/null
+++ b/src/test/ui/issues/issue-51244.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let ref my_ref @ _ = 0;
+    *my_ref = 0; //~ ERROR cannot assign to immutable borrowed content `*my_ref` [E0594]
+}
diff --git a/src/test/ui/issues/issue-51244.stderr b/src/test/ui/issues/issue-51244.stderr
new file mode 100644
index 0000000..f798b5f
--- /dev/null
+++ b/src/test/ui/issues/issue-51244.stderr
@@ -0,0 +1,11 @@
+error[E0594]: cannot assign to immutable borrowed content `*my_ref`
+  --> $DIR/issue-51244.rs:3:5
+   |
+LL |     let ref my_ref @ _ = 0;
+   |         -------------- help: use a mutable reference instead: `ref mut my_ref @ _`
+LL |     *my_ref = 0;
+   |     ^^^^^^^^^^^ cannot borrow as mutable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/issues/issue-51279.rs b/src/test/ui/issues/issue-51279.rs
new file mode 100644
index 0000000..f8f3626
--- /dev/null
+++ b/src/test/ui/issues/issue-51279.rs
@@ -0,0 +1,27 @@
+pub struct X<#[cfg(none)] 'a, #[cfg(none)] T>(&'a T);
+//~^ ERROR #[cfg] cannot be applied on a generic parameter
+//~^^ ERROR #[cfg] cannot be applied on a generic parameter
+
+impl<#[cfg(none)] 'a, #[cfg(none)] T> X<'a, T> {}
+//~^ ERROR #[cfg] cannot be applied on a generic parameter
+//~^^ ERROR #[cfg] cannot be applied on a generic parameter
+
+pub fn f<#[cfg(none)] 'a, #[cfg(none)] T>(_: &'a T) {}
+//~^ ERROR #[cfg] cannot be applied on a generic parameter
+//~^^ ERROR #[cfg] cannot be applied on a generic parameter
+
+#[cfg(none)]
+pub struct Y<#[cfg(none)] T>(T); // shouldn't care when the entire item is stripped out
+
+struct M<T>(*const T);
+
+impl<#[cfg_attr(none, may_dangle)] T> Drop for M<T> {
+    //~^ ERROR #[cfg_attr] cannot be applied on a generic parameter
+    fn drop(&mut self) {}
+}
+
+type Z<#[ignored] 'a, #[cfg(none)] T> = X<'a, T>;
+//~^ ERROR #[cfg] cannot be applied on a generic parameter
+//~| ERROR attribute `ignored` is currently unknown to the compiler
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-51279.stderr b/src/test/ui/issues/issue-51279.stderr
new file mode 100644
index 0000000..bc33eac
--- /dev/null
+++ b/src/test/ui/issues/issue-51279.stderr
@@ -0,0 +1,59 @@
+error: #[cfg] cannot be applied on a generic parameter
+  --> $DIR/issue-51279.rs:1:14
+   |
+LL | pub struct X<#[cfg(none)] 'a, #[cfg(none)] T>(&'a T);
+   |              ^^^^^^^^^^^^
+
+error: #[cfg] cannot be applied on a generic parameter
+  --> $DIR/issue-51279.rs:1:31
+   |
+LL | pub struct X<#[cfg(none)] 'a, #[cfg(none)] T>(&'a T);
+   |                               ^^^^^^^^^^^^
+
+error: #[cfg] cannot be applied on a generic parameter
+  --> $DIR/issue-51279.rs:5:6
+   |
+LL | impl<#[cfg(none)] 'a, #[cfg(none)] T> X<'a, T> {}
+   |      ^^^^^^^^^^^^
+
+error: #[cfg] cannot be applied on a generic parameter
+  --> $DIR/issue-51279.rs:5:23
+   |
+LL | impl<#[cfg(none)] 'a, #[cfg(none)] T> X<'a, T> {}
+   |                       ^^^^^^^^^^^^
+
+error: #[cfg] cannot be applied on a generic parameter
+  --> $DIR/issue-51279.rs:9:10
+   |
+LL | pub fn f<#[cfg(none)] 'a, #[cfg(none)] T>(_: &'a T) {}
+   |          ^^^^^^^^^^^^
+
+error: #[cfg] cannot be applied on a generic parameter
+  --> $DIR/issue-51279.rs:9:27
+   |
+LL | pub fn f<#[cfg(none)] 'a, #[cfg(none)] T>(_: &'a T) {}
+   |                           ^^^^^^^^^^^^
+
+error: #[cfg_attr] cannot be applied on a generic parameter
+  --> $DIR/issue-51279.rs:18:6
+   |
+LL | impl<#[cfg_attr(none, may_dangle)] T> Drop for M<T> {
+   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: #[cfg] cannot be applied on a generic parameter
+  --> $DIR/issue-51279.rs:23:23
+   |
+LL | type Z<#[ignored] 'a, #[cfg(none)] T> = X<'a, T>;
+   |                       ^^^^^^^^^^^^
+
+error[E0658]: The attribute `ignored` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/issue-51279.rs:23:8
+   |
+LL | type Z<#[ignored] 'a, #[cfg(none)] T> = X<'a, T>;
+   |        ^^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error: aborting due to 9 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/issues/issue-51515.rs b/src/test/ui/issues/issue-51515.rs
new file mode 100644
index 0000000..64d9822
--- /dev/null
+++ b/src/test/ui/issues/issue-51515.rs
@@ -0,0 +1,14 @@
+#![feature(nll)]
+
+fn main() {
+    let foo = &16;
+    //~^ HELP consider changing this to be a mutable reference
+    //~| SUGGESTION &mut 16
+    *foo = 32;
+    //~^ ERROR cannot assign to `*foo` which is behind a `&` reference
+    let bar = foo;
+    //~^ HELP consider changing this to be a mutable reference
+    //~| SUGGESTION &mut i32
+    *bar = 64;
+    //~^ ERROR cannot assign to `*bar` which is behind a `&` reference
+}
diff --git a/src/test/ui/issues/issue-51515.stderr b/src/test/ui/issues/issue-51515.stderr
new file mode 100644
index 0000000..bcfed6d
--- /dev/null
+++ b/src/test/ui/issues/issue-51515.stderr
@@ -0,0 +1,21 @@
+error[E0594]: cannot assign to `*foo` which is behind a `&` reference
+  --> $DIR/issue-51515.rs:7:5
+   |
+LL |     let foo = &16;
+   |               --- help: consider changing this to be a mutable reference: `&mut 16`
+...
+LL |     *foo = 32;
+   |     ^^^^^^^^^ `foo` is a `&` reference, so the data it refers to cannot be written
+
+error[E0594]: cannot assign to `*bar` which is behind a `&` reference
+  --> $DIR/issue-51515.rs:12:5
+   |
+LL |     let bar = foo;
+   |         --- help: consider changing this to be a mutable reference: `&mut i32`
+...
+LL |     *bar = 64;
+   |     ^^^^^^^^^ `bar` is a `&` reference, so the data it refers to cannot be written
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/issues/issue-5153.rs b/src/test/ui/issues/issue-5153.rs
new file mode 100644
index 0000000..551880a
--- /dev/null
+++ b/src/test/ui/issues/issue-5153.rs
@@ -0,0 +1,12 @@
+trait Foo {
+    fn foo(self: Box<Self>);
+}
+
+impl Foo for isize {
+    fn foo(self: Box<isize>) { }
+}
+
+fn main() {
+    (&5isize as &Foo).foo();
+    //~^ ERROR: no method named `foo` found for type `&dyn Foo` in the current scope
+}
diff --git a/src/test/ui/issues/issue-5153.stderr b/src/test/ui/issues/issue-5153.stderr
new file mode 100644
index 0000000..48adfee
--- /dev/null
+++ b/src/test/ui/issues/issue-5153.stderr
@@ -0,0 +1,13 @@
+error[E0599]: no method named `foo` found for type `&dyn Foo` in the current scope
+  --> $DIR/issue-5153.rs:10:23
+   |
+LL |     (&5isize as &Foo).foo();
+   |                       ^^^
+   |
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following trait defines an item `foo`, perhaps you need to implement it:
+           candidate #1: `Foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/issues/issue-51602.rs b/src/test/ui/issues/issue-51602.rs
new file mode 100644
index 0000000..0e96ca9
--- /dev/null
+++ b/src/test/ui/issues/issue-51602.rs
@@ -0,0 +1,6 @@
+fn main(){
+    if i in 1..10 {
+//~^ ERROR expected `{`, found keyword `in`
+        break;
+    }
+}
diff --git a/src/test/ui/issues/issue-51602.stderr b/src/test/ui/issues/issue-51602.stderr
new file mode 100644
index 0000000..1ad69c0
--- /dev/null
+++ b/src/test/ui/issues/issue-51602.stderr
@@ -0,0 +1,10 @@
+error: expected `{`, found keyword `in`
+  --> $DIR/issue-51602.rs:2:10
+   |
+LL |     if i in 1..10 {
+   |     --   ^^ expected `{`
+   |     |
+   |     this `if` statement has a condition, but no block
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-51632-try-desugar-incompatible-types.rs b/src/test/ui/issues/issue-51632-try-desugar-incompatible-types.rs
new file mode 100644
index 0000000..bb74f0e
--- /dev/null
+++ b/src/test/ui/issues/issue-51632-try-desugar-incompatible-types.rs
@@ -0,0 +1,12 @@
+#![allow(dead_code)]
+
+fn missing_discourses() -> Result<isize, ()> {
+    Ok(1)
+}
+
+fn forbidden_narratives() -> Result<isize, ()> {
+    missing_discourses()?
+    //~^ ERROR try expression alternatives have incompatible types
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-51632-try-desugar-incompatible-types.stderr b/src/test/ui/issues/issue-51632-try-desugar-incompatible-types.stderr
new file mode 100644
index 0000000..8f36a3f
--- /dev/null
+++ b/src/test/ui/issues/issue-51632-try-desugar-incompatible-types.stderr
@@ -0,0 +1,12 @@
+error[E0308]: try expression alternatives have incompatible types
+  --> $DIR/issue-51632-try-desugar-incompatible-types.rs:8:5
+   |
+LL |     missing_discourses()?
+   |     ^^^^^^^^^^^^^^^^^^^^^ expected enum `std::result::Result`, found isize
+   |
+   = note: expected type `std::result::Result<isize, ()>`
+              found type `isize`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-51655.rs b/src/test/ui/issues/issue-51655.rs
new file mode 100644
index 0000000..989fcc0
--- /dev/null
+++ b/src/test/ui/issues/issue-51655.rs
@@ -0,0 +1,14 @@
+// compile-pass
+#![allow(dead_code)]
+
+const PATH_DOT: &[u8] = &[b'.'];
+
+fn match_slice(element: &[u8]) {
+    match element {
+        &[] => {}
+        PATH_DOT => {}
+        _ => {}
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-51714.rs b/src/test/ui/issues/issue-51714.rs
new file mode 100644
index 0000000..4885e4a
--- /dev/null
+++ b/src/test/ui/issues/issue-51714.rs
@@ -0,0 +1,14 @@
+fn main() {
+    |_:  [_; return || {}] | {};
+    //~^ ERROR return statement outside of function body
+
+    [(); return || {}];
+    //~^ ERROR return statement outside of function body
+
+    [(); return |ice| {}];
+    //~^ ERROR return statement outside of function body
+
+    [(); return while let Some(n) = Some(0) {}];
+    //~^ ERROR return statement outside of function body
+    //~^^ WARN irrefutable while-let pattern
+}
diff --git a/src/test/ui/issues/issue-51714.stderr b/src/test/ui/issues/issue-51714.stderr
new file mode 100644
index 0000000..df11f6b
--- /dev/null
+++ b/src/test/ui/issues/issue-51714.stderr
@@ -0,0 +1,35 @@
+error[E0572]: return statement outside of function body
+  --> $DIR/issue-51714.rs:2:14
+   |
+LL |     |_:  [_; return || {}] | {};
+   |              ^^^^^^^^^^^^
+
+error[E0572]: return statement outside of function body
+  --> $DIR/issue-51714.rs:5:10
+   |
+LL |     [(); return || {}];
+   |          ^^^^^^^^^^^^
+
+error[E0572]: return statement outside of function body
+  --> $DIR/issue-51714.rs:8:10
+   |
+LL |     [(); return |ice| {}];
+   |          ^^^^^^^^^^^^^^^
+
+error[E0572]: return statement outside of function body
+  --> $DIR/issue-51714.rs:11:10
+   |
+LL |     [(); return while let Some(n) = Some(0) {}];
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: irrefutable while-let pattern
+  --> $DIR/issue-51714.rs:11:17
+   |
+LL |     [(); return while let Some(n) = Some(0) {}];
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: #[warn(irrefutable_let_patterns)] on by default
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0572`.
diff --git a/src/test/ui/issues/issue-51848.rs b/src/test/ui/issues/issue-51848.rs
new file mode 100644
index 0000000..4792bdd6
--- /dev/null
+++ b/src/test/ui/issues/issue-51848.rs
@@ -0,0 +1,20 @@
+// In case of macro expansion, the errors should be matched using the deepest callsite in the
+// macro call stack whose span is in the current file
+
+macro_rules! macro_with_error {
+    ( ) => {
+        println!("{"); //~ ERROR invalid
+    };
+}
+
+fn foo() {
+
+}
+
+fn main() {
+    macro_with_error!();
+    //^ In case of a local macro we want the error to be matched in the macro definition, not here
+
+    println!("}"); //~ ERROR invalid
+    //^ In case of an external macro we want the error to be matched here
+}
diff --git a/src/test/ui/issues/issue-51848.stderr b/src/test/ui/issues/issue-51848.stderr
new file mode 100644
index 0000000..31faaab
--- /dev/null
+++ b/src/test/ui/issues/issue-51848.stderr
@@ -0,0 +1,23 @@
+error: invalid format string: expected `'}'` but string was terminated
+  --> $DIR/issue-51848.rs:6:20
+   |
+LL |         println!("{");
+   |                   -^ expected `'}'` in format string
+   |                   |
+   |                   because of this opening brace
+...
+LL |     macro_with_error!();
+   |     -------------------- in this macro invocation
+   |
+   = note: if you intended to print `{`, you can escape it using `{{`
+
+error: invalid format string: unmatched `}` found
+  --> $DIR/issue-51848.rs:18:15
+   |
+LL |     println!("}");
+   |               ^ unmatched `}` in format string
+   |
+   = note: if you intended to print `}`, you can escape it using `}}`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/issues/issue-51874.rs b/src/test/ui/issues/issue-51874.rs
new file mode 100644
index 0000000..d9d7e36
--- /dev/null
+++ b/src/test/ui/issues/issue-51874.rs
@@ -0,0 +1,3 @@
+fn main() {
+    let a = (1.0).pow(1.0); //~ ERROR can't call method `pow` on ambiguous numeric type
+}
diff --git a/src/test/ui/issues/issue-51874.stderr b/src/test/ui/issues/issue-51874.stderr
new file mode 100644
index 0000000..9b1a6bf
--- /dev/null
+++ b/src/test/ui/issues/issue-51874.stderr
@@ -0,0 +1,13 @@
+error[E0689]: can't call method `pow` on ambiguous numeric type `{float}`
+  --> $DIR/issue-51874.rs:2:19
+   |
+LL |     let a = (1.0).pow(1.0);
+   |                   ^^^
+help: you must specify a concrete type for this numeric value, like `f32`
+   |
+LL |     let a = (1.0_f32).pow(1.0);
+   |              ^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0689`.
diff --git a/src/test/ui/issues/issue-51947.rs b/src/test/ui/issues/issue-51947.rs
new file mode 100644
index 0000000..7b79807
--- /dev/null
+++ b/src/test/ui/issues/issue-51947.rs
@@ -0,0 +1,17 @@
+// compile-pass
+
+#![crate_type = "lib"]
+#![feature(linkage)]
+
+// MergeFunctions will merge these via an anonymous internal
+// backing function, which must be named if ThinLTO buffers are used
+
+#[linkage = "weak"]
+pub fn fn1(a: u32, b: u32, c: u32) -> u32 {
+    a + b + c
+}
+
+#[linkage = "weak"]
+pub fn fn2(a: u32, b: u32, c: u32) -> u32 {
+    a + b + c
+}
diff --git a/src/test/ui/issues/issue-52023-array-size-pointer-cast.rs b/src/test/ui/issues/issue-52023-array-size-pointer-cast.rs
new file mode 100644
index 0000000..63f1128
--- /dev/null
+++ b/src/test/ui/issues/issue-52023-array-size-pointer-cast.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let _ = [0; (&0 as *const i32) as usize]; //~ ERROR casting pointers to integers in constants
+    //~^ ERROR it is undefined behavior to use this value
+}
diff --git a/src/test/ui/issues/issue-52023-array-size-pointer-cast.stderr b/src/test/ui/issues/issue-52023-array-size-pointer-cast.stderr
new file mode 100644
index 0000000..60e0792
--- /dev/null
+++ b/src/test/ui/issues/issue-52023-array-size-pointer-cast.stderr
@@ -0,0 +1,20 @@
+error[E0658]: casting pointers to integers in constants is unstable (see issue #51910)
+  --> $DIR/issue-52023-array-size-pointer-cast.rs:2:17
+   |
+LL |     let _ = [0; (&0 as *const i32) as usize];
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_raw_ptr_to_usize_cast)] to the crate attributes to enable
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/issue-52023-array-size-pointer-cast.rs:2:17
+   |
+LL |     let _ = [0; (&0 as *const i32) as usize];
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0080, E0658.
+For more information about an error, try `rustc --explain E0080`.
diff --git a/src/test/ui/issues/issue-52049.nll.stderr b/src/test/ui/issues/issue-52049.nll.stderr
new file mode 100644
index 0000000..55929d8
--- /dev/null
+++ b/src/test/ui/issues/issue-52049.nll.stderr
@@ -0,0 +1,14 @@
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/issue-52049.rs:6:10
+   |
+LL |     foo(&unpromotable(5u32));
+   |     -----^^^^^^^^^^^^^^^^^^-
+   |     |    |
+   |     |    creates a temporary which is freed while still in use
+   |     argument requires that borrow lasts for `'static`
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/src/test/ui/issues/issue-52049.rs b/src/test/ui/issues/issue-52049.rs
new file mode 100644
index 0000000..23b21cf
--- /dev/null
+++ b/src/test/ui/issues/issue-52049.rs
@@ -0,0 +1,8 @@
+fn foo(_: &'static u32) {}
+
+fn unpromotable<T>(t: T) -> T { t }
+
+fn main() {
+    foo(&unpromotable(5u32));
+}
+//~^^ ERROR borrowed value does not live long enough
diff --git a/src/test/ui/issues/issue-52049.stderr b/src/test/ui/issues/issue-52049.stderr
new file mode 100644
index 0000000..4538176
--- /dev/null
+++ b/src/test/ui/issues/issue-52049.stderr
@@ -0,0 +1,13 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/issue-52049.rs:6:10
+   |
+LL |     foo(&unpromotable(5u32));
+   |          ^^^^^^^^^^^^^^^^^^ - temporary value only lives until here
+   |          |
+   |          temporary value does not live long enough
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/issues/issue-52057.rs b/src/test/ui/issues/issue-52057.rs
new file mode 100644
index 0000000..356efd5
--- /dev/null
+++ b/src/test/ui/issues/issue-52057.rs
@@ -0,0 +1,25 @@
+// Regression test for #52057. There is an implied bound
+// that `I: 'a` where `'a` is the lifetime of `self` in `parse_first`;
+// but to observe that, one must normalize first.
+//
+// run-pass
+
+#![feature(nll)]
+
+pub trait Parser {
+    type Input;
+
+    #[inline(always)]
+    fn parse_first(input: &mut Self::Input);
+}
+
+impl<'a, I, P: ?Sized> Parser for &'a mut P
+where
+    P: Parser<Input = I>,
+{
+    type Input = I;
+
+    fn parse_first(_: &mut Self::Input) {}
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-52060.rs b/src/test/ui/issues/issue-52060.rs
new file mode 100644
index 0000000..54eff22
--- /dev/null
+++ b/src/test/ui/issues/issue-52060.rs
@@ -0,0 +1,8 @@
+// Regression test for https://github.com/rust-lang/rust/issues/52060
+// The compiler shouldn't ICE in this case
+static A: &'static [u32] = &[1];
+static B: [u32; 1] = [0; A.len()];
+//~^ ERROR [E0013]
+//~| ERROR `core::slice::<impl [T]>::len` is not yet stable as a const fn
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-52060.stderr b/src/test/ui/issues/issue-52060.stderr
new file mode 100644
index 0000000..7c3f769
--- /dev/null
+++ b/src/test/ui/issues/issue-52060.stderr
@@ -0,0 +1,17 @@
+error[E0013]: constants cannot refer to statics, use a constant instead
+  --> $DIR/issue-52060.rs:4:26
+   |
+LL | static B: [u32; 1] = [0; A.len()];
+   |                          ^
+
+error: `core::slice::<impl [T]>::len` is not yet stable as a const fn
+  --> $DIR/issue-52060.rs:4:26
+   |
+LL | static B: [u32; 1] = [0; A.len()];
+   |                          ^^^^^^^
+   |
+   = help: add `#![feature(const_slice_len)]` to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0013`.
diff --git a/src/test/ui/issues/issue-52126-assign-op-invariance.nll.stderr b/src/test/ui/issues/issue-52126-assign-op-invariance.nll.stderr
new file mode 100644
index 0000000..d231f62
--- /dev/null
+++ b/src/test/ui/issues/issue-52126-assign-op-invariance.nll.stderr
@@ -0,0 +1,15 @@
+error[E0597]: `line` does not live long enough
+  --> $DIR/issue-52126-assign-op-invariance.rs:34:28
+   |
+LL |         let v: Vec<&str> = line.split_whitespace().collect();
+   |                            ^^^^ borrowed value does not live long enough
+...
+LL |         acc += cnt2;
+   |         --- borrow later used here
+...
+LL |     }
+   |     - `line` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/issues/issue-52126-assign-op-invariance.rs b/src/test/ui/issues/issue-52126-assign-op-invariance.rs
new file mode 100644
index 0000000..c96cfdf3
--- /dev/null
+++ b/src/test/ui/issues/issue-52126-assign-op-invariance.rs
@@ -0,0 +1,49 @@
+// Issue 52126: With respect to variance, the assign-op's like += were
+// accidentally lumped together with other binary op's. In both cases
+// we were coercing the LHS of the op to the expected supertype.
+//
+// The problem is that since the LHS of += is modified, we need the
+// parameter to be invariant with respect to the overall type, not
+// covariant.
+
+use std::collections::HashMap;
+use std::ops::AddAssign;
+
+pub fn main() {
+    panics();
+}
+
+pub struct Counter<'l> {
+    map: HashMap<&'l str, usize>,
+}
+
+impl<'l> AddAssign for Counter<'l>
+{
+    fn add_assign(&mut self, rhs: Counter<'l>) {
+        rhs.map.into_iter().for_each(|(key, val)| {
+            let count = self.map.entry(key).or_insert(0);
+            *count += val;
+        });
+    }
+}
+
+/// Often crashes, if not prints invalid strings.
+pub fn panics() {
+    let mut acc = Counter{map: HashMap::new()};
+    for line in vec!["123456789".to_string(), "12345678".to_string()] {
+        let v: Vec<&str> = line.split_whitespace().collect();
+        //~^ ERROR `line` does not live long enough
+        // println!("accumulator before add_assign {:?}", acc.map);
+        let mut map = HashMap::new();
+        for str_ref in v {
+            let e = map.entry(str_ref);
+            println!("entry: {:?}", e);
+            let count = e.or_insert(0);
+            *count += 1;
+        }
+        let cnt2 = Counter{map};
+        acc += cnt2;
+        // println!("accumulator after add_assign {:?}", acc.map);
+        // line gets dropped here but references are kept in acc.map
+    }
+}
diff --git a/src/test/ui/issues/issue-52126-assign-op-invariance.stderr b/src/test/ui/issues/issue-52126-assign-op-invariance.stderr
new file mode 100644
index 0000000..b07b8d5
--- /dev/null
+++ b/src/test/ui/issues/issue-52126-assign-op-invariance.stderr
@@ -0,0 +1,14 @@
+error[E0597]: `line` does not live long enough
+  --> $DIR/issue-52126-assign-op-invariance.rs:34:28
+   |
+LL |         let v: Vec<&str> = line.split_whitespace().collect();
+   |                            ^^^^ borrowed value does not live long enough
+...
+LL |     }
+   |     - `line` dropped here while still borrowed
+LL | }
+   | - borrowed value needs to live until here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/issues/issue-5216.rs b/src/test/ui/issues/issue-5216.rs
new file mode 100644
index 0000000..fd49088
--- /dev/null
+++ b/src/test/ui/issues/issue-5216.rs
@@ -0,0 +1,10 @@
+fn f() { }
+struct S(Box<FnMut()>);
+pub static C: S = S(f); //~ ERROR mismatched types
+
+
+fn g() { }
+type T = Box<FnMut()>;
+pub static D: T = g; //~ ERROR mismatched types
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-5216.stderr b/src/test/ui/issues/issue-5216.stderr
new file mode 100644
index 0000000..ccfe7e0
--- /dev/null
+++ b/src/test/ui/issues/issue-5216.stderr
@@ -0,0 +1,21 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-5216.rs:3:21
+   |
+LL | pub static C: S = S(f);
+   |                     ^ expected struct `std::boxed::Box`, found fn item
+   |
+   = note: expected type `std::boxed::Box<(dyn std::ops::FnMut() + 'static)>`
+              found type `fn() {f}`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-5216.rs:8:19
+   |
+LL | pub static D: T = g;
+   |                   ^ expected struct `std::boxed::Box`, found fn item
+   |
+   = note: expected type `std::boxed::Box<(dyn std::ops::FnMut() + 'static)>`
+              found type `fn() {g}`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-52213.rs b/src/test/ui/issues/issue-52213.rs
new file mode 100644
index 0000000..c4ce494
--- /dev/null
+++ b/src/test/ui/issues/issue-52213.rs
@@ -0,0 +1,14 @@
+fn transmute_lifetime<'a, 'b, T>(t: &'a (T,)) -> &'b T {
+    match (&t,) { //~ ERROR cannot infer an appropriate lifetime
+        ((u,),) => u,
+    }
+}
+
+fn main() {
+    let x = {
+        let y = Box::new((42,));
+        transmute_lifetime(&y)
+    };
+
+    println!("{}", x);
+}
diff --git a/src/test/ui/issues/issue-52213.stderr b/src/test/ui/issues/issue-52213.stderr
new file mode 100644
index 0000000..8d74b8e
--- /dev/null
+++ b/src/test/ui/issues/issue-52213.stderr
@@ -0,0 +1,28 @@
+error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
+  --> $DIR/issue-52213.rs:2:11
+   |
+LL |     match (&t,) {
+   |           ^^^^^
+   |
+note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 1:23...
+  --> $DIR/issue-52213.rs:1:23
+   |
+LL | fn transmute_lifetime<'a, 'b, T>(t: &'a (T,)) -> &'b T {
+   |                       ^^
+   = note: ...so that the types are compatible:
+           expected (&&(T,),)
+              found (&&'a (T,),)
+note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 1:27...
+  --> $DIR/issue-52213.rs:1:27
+   |
+LL | fn transmute_lifetime<'a, 'b, T>(t: &'a (T,)) -> &'b T {
+   |                           ^^
+note: ...so that reference does not outlive borrowed content
+  --> $DIR/issue-52213.rs:3:20
+   |
+LL |         ((u,),) => u,
+   |                    ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0495`.
diff --git a/src/test/ui/issues/issue-52240.nll.stderr b/src/test/ui/issues/issue-52240.nll.stderr
new file mode 100644
index 0000000..69b663b
--- /dev/null
+++ b/src/test/ui/issues/issue-52240.nll.stderr
@@ -0,0 +1,9 @@
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/issue-52240.rs:9:27
+   |
+LL |     if let (Some(Foo::Bar(ref mut val)), _) = (&arr.get(0), 0) {
+   |                           ^^^^^^^^^^^ cannot borrow as mutable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/issues/issue-52240.rs b/src/test/ui/issues/issue-52240.rs
new file mode 100644
index 0000000..9ac7e99
--- /dev/null
+++ b/src/test/ui/issues/issue-52240.rs
@@ -0,0 +1,16 @@
+// issue-52240: Can turn immutable into mut with `ref mut`
+
+enum Foo {
+    Bar(i32),
+}
+
+fn main() {
+    let arr = vec!(Foo::Bar(0));
+    if let (Some(Foo::Bar(ref mut val)), _) = (&arr.get(0), 0) {
+        //~^ ERROR cannot borrow field of immutable binding as mutable
+        *val = 9001;
+    }
+    match arr[0] {
+        Foo::Bar(ref s) => println!("{}", s)
+    }
+}
diff --git a/src/test/ui/issues/issue-52240.stderr b/src/test/ui/issues/issue-52240.stderr
new file mode 100644
index 0000000..c2c2524
--- /dev/null
+++ b/src/test/ui/issues/issue-52240.stderr
@@ -0,0 +1,9 @@
+error[E0596]: cannot borrow field of immutable binding as mutable
+  --> $DIR/issue-52240.rs:9:27
+   |
+LL |     if let (Some(Foo::Bar(ref mut val)), _) = (&arr.get(0), 0) {
+   |                           ^^^^^^^^^^^ cannot mutably borrow field of immutable binding
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/issues/issue-5239-1.rs b/src/test/ui/issues/issue-5239-1.rs
new file mode 100644
index 0000000..708ae34
--- /dev/null
+++ b/src/test/ui/issues/issue-5239-1.rs
@@ -0,0 +1,6 @@
+// Regression test for issue #5239
+
+fn main() {
+    let x = |ref x: isize| { x += 1; };
+    //~^ ERROR E0368
+}
diff --git a/src/test/ui/issues/issue-5239-1.stderr b/src/test/ui/issues/issue-5239-1.stderr
new file mode 100644
index 0000000..a95014f
--- /dev/null
+++ b/src/test/ui/issues/issue-5239-1.stderr
@@ -0,0 +1,15 @@
+error[E0368]: binary assignment operation `+=` cannot be applied to type `&isize`
+  --> $DIR/issue-5239-1.rs:4:30
+   |
+LL |     let x = |ref x: isize| { x += 1; };
+   |                              -^^^^^
+   |                              |
+   |                              cannot use `+=` on type `&isize`
+help: `+=` can be used on 'isize', you can dereference `x`
+   |
+LL |     let x = |ref x: isize| { *x += 1; };
+   |                              ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0368`.
diff --git a/src/test/ui/issues/issue-52489.rs b/src/test/ui/issues/issue-52489.rs
new file mode 100644
index 0000000..8efe216
--- /dev/null
+++ b/src/test/ui/issues/issue-52489.rs
@@ -0,0 +1,8 @@
+// edition:2018
+// aux-build:issue-52489.rs
+// compile-flags:--extern issue_52489
+
+use issue_52489;
+//~^ ERROR use of unstable library feature 'issue_52489_unstable'
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-52489.stderr b/src/test/ui/issues/issue-52489.stderr
new file mode 100644
index 0000000..339877f
--- /dev/null
+++ b/src/test/ui/issues/issue-52489.stderr
@@ -0,0 +1,11 @@
+error[E0658]: use of unstable library feature 'issue_52489_unstable'
+  --> $DIR/issue-52489.rs:5:5
+   |
+LL | use issue_52489;
+   |     ^^^^^^^^^^^
+   |
+   = help: add #![feature(issue_52489_unstable)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/issues/issue-52496.rs b/src/test/ui/issues/issue-52496.rs
new file mode 100644
index 0000000..4e94536
--- /dev/null
+++ b/src/test/ui/issues/issue-52496.rs
@@ -0,0 +1,12 @@
+struct Foo { bar: f64, baz: i64, bat: i64 }
+
+fn main() {
+    let _ = Foo { bar: .5, baz: 42 };
+    //~^ ERROR float literals must have an integer part
+    //~| ERROR missing field `bat` in initializer of `Foo`
+    let bar = 1.5f32;
+    let _ = Foo { bar.into(), bat: -1, . };
+    //~^ ERROR expected one of
+    //~| ERROR missing fields `bar`, `baz` in initializer of `Foo`
+    //~| ERROR expected identifier, found `.`
+}
diff --git a/src/test/ui/issues/issue-52496.stderr b/src/test/ui/issues/issue-52496.stderr
new file mode 100644
index 0000000..43009a1
--- /dev/null
+++ b/src/test/ui/issues/issue-52496.stderr
@@ -0,0 +1,37 @@
+error: float literals must have an integer part
+  --> $DIR/issue-52496.rs:4:24
+   |
+LL |     let _ = Foo { bar: .5, baz: 42 };
+   |                        ^^ help: must have an integer part: `0.5`
+
+error: expected one of `,` or `}`, found `.`
+  --> $DIR/issue-52496.rs:8:22
+   |
+LL |     let _ = Foo { bar.into(), bat: -1, . };
+   |             ---      ^ expected one of `,` or `}` here
+   |             |
+   |             while parsing this struct
+
+error: expected identifier, found `.`
+  --> $DIR/issue-52496.rs:8:40
+   |
+LL |     let _ = Foo { bar.into(), bat: -1, . };
+   |             ---                        ^ expected identifier
+   |             |
+   |             while parsing this struct
+
+error[E0063]: missing field `bat` in initializer of `Foo`
+  --> $DIR/issue-52496.rs:4:13
+   |
+LL |     let _ = Foo { bar: .5, baz: 42 };
+   |             ^^^ missing `bat`
+
+error[E0063]: missing fields `bar`, `baz` in initializer of `Foo`
+  --> $DIR/issue-52496.rs:8:13
+   |
+LL |     let _ = Foo { bar.into(), bat: -1, . };
+   |             ^^^ missing `bar`, `baz`
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0063`.
diff --git a/src/test/ui/issues/issue-52533-1.rs b/src/test/ui/issues/issue-52533-1.rs
new file mode 100644
index 0000000..c80f432
--- /dev/null
+++ b/src/test/ui/issues/issue-52533-1.rs
@@ -0,0 +1,11 @@
+#![allow(warnings)]
+
+struct Foo<'a, 'b, T: 'a + 'b> { x: &'a T, y: &'b T }
+
+fn gimme(_: impl for<'a, 'b, 'c> FnOnce(&'a Foo<'a, 'b, u32>,
+                                        &'a Foo<'a, 'c, u32>) -> &'a Foo<'a, 'b, u32>) { }
+
+fn main() {
+    gimme(|x, y| y)
+    //~^ ERROR mismatched types [E0308]
+}
diff --git a/src/test/ui/issues/issue-52533-1.stderr b/src/test/ui/issues/issue-52533-1.stderr
new file mode 100644
index 0000000..c719c00
--- /dev/null
+++ b/src/test/ui/issues/issue-52533-1.stderr
@@ -0,0 +1,22 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-52533-1.rs:9:18
+   |
+LL |     gimme(|x, y| y)
+   |                  ^ lifetime mismatch
+   |
+   = note: expected type `&Foo<'_, '_, u32>`
+              found type `&Foo<'_, '_, u32>`
+note: the anonymous lifetime #4 defined on the body at 9:11...
+  --> $DIR/issue-52533-1.rs:9:11
+   |
+LL |     gimme(|x, y| y)
+   |           ^^^^^^^^
+note: ...does not necessarily outlive the anonymous lifetime #3 defined on the body at 9:11
+  --> $DIR/issue-52533-1.rs:9:11
+   |
+LL |     gimme(|x, y| y)
+   |           ^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-52533.rs b/src/test/ui/issues/issue-52533.rs
new file mode 100644
index 0000000..a35f5a8
--- /dev/null
+++ b/src/test/ui/issues/issue-52533.rs
@@ -0,0 +1,7 @@
+fn foo(_: impl for<'a> FnOnce(&'a u32, &u32) -> &'a u32) {
+}
+
+fn main() {
+    foo(|a, b| b)
+    //~^ ERROR lifetime of reference outlives lifetime of borrowed content...
+}
diff --git a/src/test/ui/issues/issue-52533.stderr b/src/test/ui/issues/issue-52533.stderr
new file mode 100644
index 0000000..5865480
--- /dev/null
+++ b/src/test/ui/issues/issue-52533.stderr
@@ -0,0 +1,20 @@
+error[E0312]: lifetime of reference outlives lifetime of borrowed content...
+  --> $DIR/issue-52533.rs:5:16
+   |
+LL |     foo(|a, b| b)
+   |                ^
+   |
+note: ...the reference is valid for the anonymous lifetime #2 defined on the body at 5:9...
+  --> $DIR/issue-52533.rs:5:9
+   |
+LL |     foo(|a, b| b)
+   |         ^^^^^^^^
+note: ...but the borrowed content is only valid for the anonymous lifetime #3 defined on the body at 5:9
+  --> $DIR/issue-52533.rs:5:9
+   |
+LL |     foo(|a, b| b)
+   |         ^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0312`.
diff --git a/src/test/ui/issues/issue-52717.rs b/src/test/ui/issues/issue-52717.rs
new file mode 100644
index 0000000..f83232a
--- /dev/null
+++ b/src/test/ui/issues/issue-52717.rs
@@ -0,0 +1,13 @@
+enum A {
+  A {
+    foo: usize,
+  }
+}
+
+fn main() {
+  let x = A::A { foo: 3 };
+  match x {
+    A::A { fob } => { println!("{}", fob); }
+//~^ ERROR does not have a field named `fob`
+  }
+}
diff --git a/src/test/ui/issues/issue-52717.stderr b/src/test/ui/issues/issue-52717.stderr
new file mode 100644
index 0000000..468cdf2
--- /dev/null
+++ b/src/test/ui/issues/issue-52717.stderr
@@ -0,0 +1,12 @@
+error[E0026]: variant `A::A` does not have a field named `fob`
+  --> $DIR/issue-52717.rs:10:12
+   |
+LL |     A::A { fob } => { println!("{}", fob); }
+   |            ^^^
+   |            |
+   |            variant `A::A` does not have this field
+   |            help: a field with a similar name exists: `foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0026`.
diff --git a/src/test/ui/issues/issue-52891.fixed b/src/test/ui/issues/issue-52891.fixed
new file mode 100644
index 0000000..e694b5c
--- /dev/null
+++ b/src/test/ui/issues/issue-52891.fixed
@@ -0,0 +1,37 @@
+// aux-build:issue-52891.rs
+// run-rustfix
+
+#![allow(warnings)]
+
+extern crate issue_52891;
+
+// Check that we don't suggest renaming duplicate imports but instead
+// suggest removing one.
+
+use issue_52891::a;
+ //~ ERROR `a` is defined multiple times
+
+use issue_52891::{b, c}; //~ ERROR `a` is defined multiple times
+use issue_52891::{d, e}; //~ ERROR `a` is defined multiple times
+use issue_52891::{f, g}; //~ ERROR `a` is defined multiple times
+
+use issue_52891::{//~ ERROR `a` is defined multiple times
+    h,
+    i};
+use issue_52891::{j,
+    //~ ERROR `a` is defined multiple times
+    k};
+use issue_52891::{l,
+    m}; //~ ERROR `a` is defined multiple times
+
+use issue_52891::a::inner;
+use issue_52891::b::inner as other_inner; //~ ERROR `inner` is defined multiple times
+
+
+//~^ ERROR `issue_52891` is defined multiple times
+
+
+#[macro_use]
+use issue_52891::n; //~ ERROR `n` is defined multiple times
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-52891.rs b/src/test/ui/issues/issue-52891.rs
new file mode 100644
index 0000000..cd4b406
--- /dev/null
+++ b/src/test/ui/issues/issue-52891.rs
@@ -0,0 +1,38 @@
+// aux-build:issue-52891.rs
+// run-rustfix
+
+#![allow(warnings)]
+
+extern crate issue_52891;
+
+// Check that we don't suggest renaming duplicate imports but instead
+// suggest removing one.
+
+use issue_52891::a;
+use issue_52891::a; //~ ERROR `a` is defined multiple times
+
+use issue_52891::{a, b, c}; //~ ERROR `a` is defined multiple times
+use issue_52891::{d, a, e}; //~ ERROR `a` is defined multiple times
+use issue_52891::{f, g, a}; //~ ERROR `a` is defined multiple times
+
+use issue_52891::{a, //~ ERROR `a` is defined multiple times
+    h,
+    i};
+use issue_52891::{j,
+    a, //~ ERROR `a` is defined multiple times
+    k};
+use issue_52891::{l,
+    m,
+    a}; //~ ERROR `a` is defined multiple times
+
+use issue_52891::a::inner;
+use issue_52891::b::inner; //~ ERROR `inner` is defined multiple times
+
+use issue_52891::{self};
+//~^ ERROR `issue_52891` is defined multiple times
+
+use issue_52891::n;
+#[macro_use]
+use issue_52891::n; //~ ERROR `n` is defined multiple times
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-52891.stderr b/src/test/ui/issues/issue-52891.stderr
new file mode 100644
index 0000000..9173c02
--- /dev/null
+++ b/src/test/ui/issues/issue-52891.stderr
@@ -0,0 +1,131 @@
+error[E0252]: the name `a` is defined multiple times
+  --> $DIR/issue-52891.rs:12:5
+   |
+LL | use issue_52891::a;
+   |     -------------- previous import of the module `a` here
+LL | use issue_52891::a;
+   |     ^^^^^^^^^^^^^^ `a` reimported here
+   |
+   = note: `a` must be defined only once in the type namespace of this module
+
+error[E0252]: the name `a` is defined multiple times
+  --> $DIR/issue-52891.rs:14:19
+   |
+LL | use issue_52891::a;
+   |     -------------- previous import of the module `a` here
+...
+LL | use issue_52891::{a, b, c};
+   |                   ^--
+   |                   |
+   |                   `a` reimported here
+   |                   help: remove unnecessary import
+   |
+   = note: `a` must be defined only once in the type namespace of this module
+
+error[E0252]: the name `a` is defined multiple times
+  --> $DIR/issue-52891.rs:15:22
+   |
+LL | use issue_52891::a;
+   |     -------------- previous import of the module `a` here
+...
+LL | use issue_52891::{d, a, e};
+   |                      ^--
+   |                      |
+   |                      `a` reimported here
+   |                      help: remove unnecessary import
+   |
+   = note: `a` must be defined only once in the type namespace of this module
+
+error[E0252]: the name `a` is defined multiple times
+  --> $DIR/issue-52891.rs:16:25
+   |
+LL | use issue_52891::a;
+   |     -------------- previous import of the module `a` here
+...
+LL | use issue_52891::{f, g, a};
+   |                         ^ `a` reimported here
+   |
+   = note: `a` must be defined only once in the type namespace of this module
+
+error[E0252]: the name `a` is defined multiple times
+  --> $DIR/issue-52891.rs:18:19
+   |
+LL | use issue_52891::a;
+   |     -------------- previous import of the module `a` here
+...
+LL | use issue_52891::{a,
+   |                   ^--
+   |                   |
+   |                   `a` reimported here
+   |                   help: remove unnecessary import
+   |
+   = note: `a` must be defined only once in the type namespace of this module
+
+error[E0252]: the name `a` is defined multiple times
+  --> $DIR/issue-52891.rs:22:5
+   |
+LL | use issue_52891::a;
+   |     -------------- previous import of the module `a` here
+...
+LL |     a,
+   |     ^--
+   |     |
+   |     `a` reimported here
+   |     help: remove unnecessary import
+   |
+   = note: `a` must be defined only once in the type namespace of this module
+
+error[E0252]: the name `a` is defined multiple times
+  --> $DIR/issue-52891.rs:26:5
+   |
+LL | use issue_52891::a;
+   |     -------------- previous import of the module `a` here
+...
+LL |     a};
+   |     ^ `a` reimported here
+   |
+   = note: `a` must be defined only once in the type namespace of this module
+
+error[E0252]: the name `inner` is defined multiple times
+  --> $DIR/issue-52891.rs:29:5
+   |
+LL | use issue_52891::a::inner;
+   |     --------------------- previous import of the module `inner` here
+LL | use issue_52891::b::inner;
+   |     ^^^^^^^^^^^^^^^^^^^^^ `inner` reimported here
+   |
+   = note: `inner` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | use issue_52891::b::inner as other_inner;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0254]: the name `issue_52891` is defined multiple times
+  --> $DIR/issue-52891.rs:31:19
+   |
+LL | extern crate issue_52891;
+   | ------------------------- previous import of the extern crate `issue_52891` here
+...
+LL | use issue_52891::{self};
+   | ------------------^^^^--
+   | |                 |
+   | |                 `issue_52891` reimported here
+   | help: remove unnecessary import
+   |
+   = note: `issue_52891` must be defined only once in the type namespace of this module
+
+error[E0252]: the name `n` is defined multiple times
+  --> $DIR/issue-52891.rs:36:5
+   |
+LL | use issue_52891::n;
+   |     -------------- previous import of the module `n` here
+LL | #[macro_use]
+LL | use issue_52891::n;
+   |     ^^^^^^^^^^^^^^ `n` reimported here
+   |
+   = note: `n` must be defined only once in the type namespace of this module
+
+error: aborting due to 10 previous errors
+
+Some errors occurred: E0252, E0254.
+For more information about an error, try `rustc --explain E0252`.
diff --git a/src/test/ui/issues/issue-52992.rs b/src/test/ui/issues/issue-52992.rs
new file mode 100644
index 0000000..0fdf077
--- /dev/null
+++ b/src/test/ui/issues/issue-52992.rs
@@ -0,0 +1,27 @@
+// Regression test for an NLL-related ICE (#52992) -- computing
+// implied bounds was causing outlives relations that were not
+// properly handled.
+//
+// compile-pass
+
+#![feature(nll)]
+
+fn main() {}
+
+fn fail<'a>() -> Struct<'a, Generic<()>> {
+    Struct(&Generic(()))
+}
+
+struct Struct<'a, T>(&'a T) where
+    T: Trait + 'a,
+    T::AT: 'a; // only fails with this bound
+
+struct Generic<T>(T);
+
+trait Trait {
+    type AT;
+}
+
+impl<T> Trait for Generic<T> {
+    type AT = T; // only fails with a generic AT
+}
diff --git a/src/test/ui/issues/issue-53251.rs b/src/test/ui/issues/issue-53251.rs
new file mode 100644
index 0000000..0751b0a
--- /dev/null
+++ b/src/test/ui/issues/issue-53251.rs
@@ -0,0 +1,20 @@
+struct S;
+
+impl S {
+    fn f() {}
+}
+
+macro_rules! impl_add {
+    ($($n:ident)*) => {
+        $(
+            fn $n() {
+                S::f::<i64>();
+                //~^ ERROR wrong number of type arguments
+            }
+        )*
+    }
+}
+
+impl_add!(a b);
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-53251.stderr b/src/test/ui/issues/issue-53251.stderr
new file mode 100644
index 0000000..9fbffaf
--- /dev/null
+++ b/src/test/ui/issues/issue-53251.stderr
@@ -0,0 +1,12 @@
+error[E0107]: wrong number of type arguments: expected 0, found 1
+  --> $DIR/issue-53251.rs:11:24
+   |
+LL |                 S::f::<i64>();
+   |                        ^^^ unexpected type argument
+...
+LL | impl_add!(a b);
+   | --------------- in this macro invocation
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0107`.
diff --git a/src/test/ui/issues/issue-53300.rs b/src/test/ui/issues/issue-53300.rs
new file mode 100644
index 0000000..09f0fe9
--- /dev/null
+++ b/src/test/ui/issues/issue-53300.rs
@@ -0,0 +1,12 @@
+// issue 53300
+
+pub trait A {
+    fn add(&self, b: i32) -> i32;
+}
+
+fn addition() -> Wrapper<impl A> {}
+//~^ ERROR cannot find type `Wrapper` in this scope [E0412]
+
+fn main() {
+    let res = addition();
+}
diff --git a/src/test/ui/issues/issue-53300.stderr b/src/test/ui/issues/issue-53300.stderr
new file mode 100644
index 0000000..2fedef7
--- /dev/null
+++ b/src/test/ui/issues/issue-53300.stderr
@@ -0,0 +1,9 @@
+error[E0412]: cannot find type `Wrapper` in this scope
+  --> $DIR/issue-53300.rs:7:18
+   |
+LL | fn addition() -> Wrapper<impl A> {}
+   |                  ^^^^^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/src/test/ui/issues/issue-53348.rs b/src/test/ui/issues/issue-53348.rs
new file mode 100644
index 0000000..733413f
--- /dev/null
+++ b/src/test/ui/issues/issue-53348.rs
@@ -0,0 +1,16 @@
+fn main() {
+    let mut v = vec!["hello", "this", "is", "a", "test"];
+
+    let v2 = Vec::new();
+
+    v.into_iter().map(|s|s.to_owned()).collect::<Vec<_>>();
+
+    let mut a = String::new();
+    for i in v {
+        a = *i.to_string();
+        //~^ ERROR mismatched types
+        //~| NOTE expected struct `std::string::String`, found str
+        //~| NOTE expected type
+        v2.push(a);
+    }
+}
diff --git a/src/test/ui/issues/issue-53348.stderr b/src/test/ui/issues/issue-53348.stderr
new file mode 100644
index 0000000..ca07b1d
--- /dev/null
+++ b/src/test/ui/issues/issue-53348.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-53348.rs:10:13
+   |
+LL |         a = *i.to_string();
+   |             ^^^^^^^^^^^^^^ expected struct `std::string::String`, found str
+   |
+   = note: expected type `std::string::String`
+              found type `str`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-53419.rs b/src/test/ui/issues/issue-53419.rs
new file mode 100644
index 0000000..fc2a926
--- /dev/null
+++ b/src/test/ui/issues/issue-53419.rs
@@ -0,0 +1,9 @@
+//compile-pass
+
+struct Foo {
+    bar: for<'r> Fn(usize, &'r FnMut())
+}
+
+fn main() {
+}
+
diff --git a/src/test/ui/issues/issue-5353.rs b/src/test/ui/issues/issue-5353.rs
new file mode 100644
index 0000000..808b73e
--- /dev/null
+++ b/src/test/ui/issues/issue-5353.rs
@@ -0,0 +1,18 @@
+// compile-pass
+#![allow(dead_code)]
+// pretty-expanded FIXME #23616
+
+const INVALID_ENUM : u32 = 0;
+const INVALID_VALUE : u32 = 1;
+
+fn gl_err_str(err: u32) -> String
+{
+  match err
+  {
+    INVALID_ENUM => { "Invalid enum".to_string() },
+    INVALID_VALUE => { "Invalid value".to_string() },
+    _ => { "Unknown error".to_string() }
+  }
+}
+
+pub fn main() {}
diff --git a/src/test/ui/issues/issue-53565.rs b/src/test/ui/issues/issue-53565.rs
new file mode 100644
index 0000000..114a53a
--- /dev/null
+++ b/src/test/ui/issues/issue-53565.rs
@@ -0,0 +1,7 @@
+use std::time::{foo, bar, buzz};
+//~^ ERROR unresolved imports
+use std::time::{abc, def};
+//~^ ERROR unresolved imports
+fn main(){
+    println!("Hello World!");
+}
diff --git a/src/test/ui/issues/issue-53565.stderr b/src/test/ui/issues/issue-53565.stderr
new file mode 100644
index 0000000..71c3b2a
--- /dev/null
+++ b/src/test/ui/issues/issue-53565.stderr
@@ -0,0 +1,20 @@
+error[E0432]: unresolved imports `std::time::foo`, `std::time::bar`, `std::time::buzz`
+  --> $DIR/issue-53565.rs:1:17
+   |
+LL | use std::time::{foo, bar, buzz};
+   |                 ^^^  ^^^  ^^^^ no `buzz` in `time`
+   |                 |    |
+   |                 |    no `bar` in `time`
+   |                 no `foo` in `time`
+
+error[E0432]: unresolved imports `std::time::abc`, `std::time::def`
+  --> $DIR/issue-53565.rs:3:17
+   |
+LL | use std::time::{abc, def};
+   |                 ^^^  ^^^ no `def` in `time`
+   |                 |
+   |                 no `abc` in `time`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/issues/issue-53568.rs b/src/test/ui/issues/issue-53568.rs
new file mode 100644
index 0000000..60a6e16
--- /dev/null
+++ b/src/test/ui/issues/issue-53568.rs
@@ -0,0 +1,51 @@
+// Regression test for an NLL-related ICE (#53568) -- we failed to
+// resolve inference variables in "custom type-ops".
+//
+// compile-pass
+
+#![feature(nll)]
+#![allow(dead_code)]
+
+trait Future {
+    type Item;
+}
+
+impl<F, T> Future for F
+where F: Fn() -> T
+{
+    type Item = T;
+}
+
+trait Connect {}
+
+struct Connector<H> {
+    handler: H,
+}
+
+impl<H, T> Connect for Connector<H>
+where
+    T: 'static,
+    H: Future<Item = T>
+{
+}
+
+struct Client<C> {
+    connector: C,
+}
+
+fn build<C>(_connector: C) -> Client<C> {
+    unimplemented!()
+}
+
+fn client<H>(handler: H) -> Client<impl Connect>
+where H: Fn() + Copy
+{
+    let connector = Connector {
+        handler,
+    };
+    let client = build(connector);
+    client
+}
+
+fn main() { }
+
diff --git a/src/test/ui/issues/issue-5358-1.rs b/src/test/ui/issues/issue-5358-1.rs
new file mode 100644
index 0000000..6b23be2
--- /dev/null
+++ b/src/test/ui/issues/issue-5358-1.rs
@@ -0,0 +1,13 @@
+enum Either<T, U> { Left(T), Right(U) }
+struct S(Either<usize, usize>);
+
+fn main() {
+    match S(Either::Left(5)) {
+        Either::Right(_) => {}
+        //~^ ERROR mismatched types
+        //~| expected type `S`
+        //~| found type `Either<_, _>`
+        //~| expected struct `S`, found enum `Either`
+        _ => {}
+    }
+}
diff --git a/src/test/ui/issues/issue-5358-1.stderr b/src/test/ui/issues/issue-5358-1.stderr
new file mode 100644
index 0000000..649a0c1
--- /dev/null
+++ b/src/test/ui/issues/issue-5358-1.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-5358-1.rs:6:9
+   |
+LL |     match S(Either::Left(5)) {
+   |           ------------------ this match expression has type `S`
+LL |         Either::Right(_) => {}
+   |         ^^^^^^^^^^^^^^^^ expected struct `S`, found enum `Either`
+   |
+   = note: expected type `S`
+              found type `Either<_, _>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-53675-a-test-called-panic.rs b/src/test/ui/issues/issue-53675-a-test-called-panic.rs
new file mode 100644
index 0000000..8a35b36
--- /dev/null
+++ b/src/test/ui/issues/issue-53675-a-test-called-panic.rs
@@ -0,0 +1,36 @@
+// rust-lang/rust#53675: At one point the compiler errored when a test
+// named `panic` used the `assert!` macro in expression position.
+
+// compile-pass
+// compile-flags: --test
+
+mod in_expression_position {
+    #[test]
+    fn panic() {
+        assert!(true)
+    }
+}
+
+mod in_statement_position {
+    #[test]
+    fn panic() {
+        assert!(true);
+    }
+}
+
+mod what_if_we_use_panic_directly_in_expr {
+    #[test]
+    #[should_panic]
+    fn panic() {
+        panic!("in expr")
+    }
+}
+
+
+mod what_if_we_use_panic_directly_in_stmt {
+    #[test]
+    #[should_panic]
+    fn panic() {
+        panic!("in stmt");
+    }
+}
diff --git a/src/test/ui/issues/issue-53692.rs b/src/test/ui/issues/issue-53692.rs
new file mode 100644
index 0000000..30f344e
--- /dev/null
+++ b/src/test/ui/issues/issue-53692.rs
@@ -0,0 +1,17 @@
+fn main() {
+        let items = vec![1, 2, 3];
+        let ref_items: &[i32] = &items;
+        let items_clone: Vec<i32> = ref_items.clone();
+//~^ ERROR mismatched types
+
+        // in that case no suggestion will be triggered
+        let items_clone_2:Vec<i32> = items.clone();
+
+        let s = "hi";
+        let string: String = s.clone();
+//~^ ERROR mismatched types
+
+        // in that case no suggestion will be triggered
+        let s2 = "hi";
+        let string_2: String = s2.to_string();
+}
diff --git a/src/test/ui/issues/issue-53692.stderr b/src/test/ui/issues/issue-53692.stderr
new file mode 100644
index 0000000..2928d44
--- /dev/null
+++ b/src/test/ui/issues/issue-53692.stderr
@@ -0,0 +1,27 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-53692.rs:4:37
+   |
+LL |         let items_clone: Vec<i32> = ref_items.clone();
+   |                                     ^^^^^^^^^^^^^^^^^
+   |                                     |
+   |                                     expected struct `std::vec::Vec`, found &[i32]
+   |                                     help: try using a conversion method: `ref_items.to_vec()`
+   |
+   = note: expected type `std::vec::Vec<i32>`
+              found type `&[i32]`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-53692.rs:11:30
+   |
+LL |         let string: String = s.clone();
+   |                              ^^^^^^^^^
+   |                              |
+   |                              expected struct `std::string::String`, found &str
+   |                              help: try using a conversion method: `s.to_string()`
+   |
+   = note: expected type `std::string::String`
+              found type `&str`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-53712.rs b/src/test/ui/issues/issue-53712.rs
new file mode 100644
index 0000000..2353904
--- /dev/null
+++ b/src/test/ui/issues/issue-53712.rs
@@ -0,0 +1,9 @@
+// issue #53712: make the error generated by using tuple indexing on an array more specific
+
+fn main() {
+    let arr = [10, 20, 30, 40, 50];
+    arr.0;
+    //~^ ERROR no field `0` on type `[{integer}; 5]` [E0609]
+    //~| HELP instead of using tuple indexing, use array indexing
+    //~| SUGGESTION arr[0]
+}
diff --git a/src/test/ui/issues/issue-53712.stderr b/src/test/ui/issues/issue-53712.stderr
new file mode 100644
index 0000000..db85919
--- /dev/null
+++ b/src/test/ui/issues/issue-53712.stderr
@@ -0,0 +1,11 @@
+error[E0609]: no field `0` on type `[{integer}; 5]`
+  --> $DIR/issue-53712.rs:5:9
+   |
+LL |     arr.0;
+   |     ----^
+   |     |
+   |     help: instead of using tuple indexing, use array indexing: `arr[0]`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0609`.
diff --git a/src/test/ui/issues/issue-53787-inline-assembler-macro.rs b/src/test/ui/issues/issue-53787-inline-assembler-macro.rs
new file mode 100644
index 0000000..937bce1
--- /dev/null
+++ b/src/test/ui/issues/issue-53787-inline-assembler-macro.rs
@@ -0,0 +1,23 @@
+// Regression test for Issue #53787: Fix ICE when creating a label in inline assembler with macros.
+
+#![feature(asm)]
+
+macro_rules! fake_jump {
+    ($id:expr) => {
+        unsafe {
+            asm!(
+            "
+            jmp $0
+            lea eax, [ebx]
+            xor eax, 0xDEADBEEF
+            retn
+            $0:
+            "::"0"($id)::"volatile", "intel");
+        }
+    };
+}
+
+fn main() {
+    fake_jump!("FirstFunc"); //~ ERROR invalid value for constraint in inline assembly
+    println!("Hello, world!");
+}
diff --git a/src/test/ui/issues/issue-53787-inline-assembler-macro.stderr b/src/test/ui/issues/issue-53787-inline-assembler-macro.stderr
new file mode 100644
index 0000000..047ba34
--- /dev/null
+++ b/src/test/ui/issues/issue-53787-inline-assembler-macro.stderr
@@ -0,0 +1,9 @@
+error[E0669]: invalid value for constraint in inline assembly
+  --> $DIR/issue-53787-inline-assembler-macro.rs:21:16
+   |
+LL |     fake_jump!("FirstFunc");
+   |                ^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0669`.
diff --git a/src/test/ui/issues/issue-53840.rs b/src/test/ui/issues/issue-53840.rs
new file mode 100644
index 0000000..e854d24
--- /dev/null
+++ b/src/test/ui/issues/issue-53840.rs
@@ -0,0 +1,20 @@
+enum E {
+    Foo(String, String, String),
+}
+
+struct Bar {
+    a: String,
+    b: String,
+}
+
+fn main() {
+    let bar = Bar { a: "1".to_string(), b: "2".to_string() };
+    match E::Foo("".into(), "".into(), "".into()) {
+        E::Foo(a, b, ref c) => {}
+//~^ ERROR cannot bind by-move and by-ref in the same pattern
+    }
+    match bar {
+        Bar {a, ref b} => {}
+//~^ ERROR cannot bind by-move and by-ref in the same pattern
+    }
+}
diff --git a/src/test/ui/issues/issue-53840.stderr b/src/test/ui/issues/issue-53840.stderr
new file mode 100644
index 0000000..0032f60
--- /dev/null
+++ b/src/test/ui/issues/issue-53840.stderr
@@ -0,0 +1,20 @@
+error[E0009]: cannot bind by-move and by-ref in the same pattern
+  --> $DIR/issue-53840.rs:13:16
+   |
+LL |         E::Foo(a, b, ref c) => {}
+   |                ^  ^  ----- both by-ref and by-move used
+   |                |  |
+   |                |  by-move pattern here
+   |                by-move pattern here
+
+error[E0009]: cannot bind by-move and by-ref in the same pattern
+  --> $DIR/issue-53840.rs:17:14
+   |
+LL |         Bar {a, ref b} => {}
+   |              ^  ----- both by-ref and by-move used
+   |              |
+   |              by-move pattern here
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0009`.
diff --git a/src/test/ui/issues/issue-54302-cases.rs b/src/test/ui/issues/issue-54302-cases.rs
new file mode 100644
index 0000000..faa1162
--- /dev/null
+++ b/src/test/ui/issues/issue-54302-cases.rs
@@ -0,0 +1,85 @@
+trait Mirror {
+    type Image;
+    fn coerce(self) -> Self::Image;
+}
+
+impl<T> Mirror for T {
+    type Image = T;
+    fn coerce(self) -> Self { self }
+}
+
+trait Foo<'x, T> {
+    fn foo(self) -> &'x T;
+}
+
+impl<'s, 'x, T: 'x> Foo<'x, T> for &'s T where &'s T: Foo2<'x, T> {
+    fn foo(self) -> &'x T { self.foo2() }
+}
+
+trait Foo2<'x, T> {
+    fn foo2(self) -> &'x T;
+}
+
+// example 1 - fails leak check
+impl<'x> Foo2<'x, u32> for &'x u32
+{
+    fn foo2(self) -> &'x u32 { self }
+}
+
+// example 2 - OK with this issue
+impl<'x, 'a: 'x> Foo2<'x, i32> for &'a i32
+{
+    fn foo2(self) -> &'x i32 { self }
+}
+
+// example 3 - fails due to issue #XYZ + Leak-check
+impl<'x, T> Foo2<'x, u64> for T
+    where T: Mirror<Image=&'x u64>
+{
+    fn foo2(self) -> &'x u64 { self.coerce() }
+}
+
+// example 4 - fails due to issue #XYZ
+impl<'x, 'a: 'x, T> Foo2<'x, i64> for T
+    where T: Mirror<Image=&'a i64>
+{
+    fn foo2(self) -> &'x i64 { self.coerce() }
+}
+
+
+trait RefFoo<T> {
+    fn ref_foo(&self) -> &'static T;
+}
+
+impl<T> RefFoo<T> for T where for<'a> &'a T: Foo<'static, T> {
+    fn ref_foo(&self) -> &'static T {
+        self.foo()
+    }
+}
+
+
+fn coerce_lifetime1(a: &u32) -> &'static u32
+{
+    <u32 as RefFoo<u32>>::ref_foo(a)
+    //~^ ERROR not general enough
+}
+
+fn coerce_lifetime2(a: &i32) -> &'static i32
+{
+    <i32 as RefFoo<i32>>::ref_foo(a)
+    //~^ ERROR not general enough
+}
+
+fn coerce_lifetime3(a: &u64) -> &'static u64
+{
+    <u64 as RefFoo<u64>>::ref_foo(a)
+    //~^ ERROR not general enough
+}
+
+fn coerce_lifetime4(a: &i64) -> &'static i64
+{
+    <i64 as RefFoo<i64>>::ref_foo(a)
+    //~^ ERROR not general enough
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-54302-cases.stderr b/src/test/ui/issues/issue-54302-cases.stderr
new file mode 100644
index 0000000..9863761
--- /dev/null
+++ b/src/test/ui/issues/issue-54302-cases.stderr
@@ -0,0 +1,38 @@
+error: implementation of `Foo` is not general enough
+  --> $DIR/issue-54302-cases.rs:63:5
+   |
+LL |     <u32 as RefFoo<u32>>::ref_foo(a)
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `Foo<'static, u32>` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`
+   = note: but `Foo<'_, u32>` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1`
+
+error: implementation of `Foo` is not general enough
+  --> $DIR/issue-54302-cases.rs:69:5
+   |
+LL |     <i32 as RefFoo<i32>>::ref_foo(a)
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `Foo<'static, i32>` would have to be implemented for the type `&'0 i32`, for any lifetime `'0`
+   = note: but `Foo<'_, i32>` is actually implemented for the type `&'1 i32`, for some specific lifetime `'1`
+
+error: implementation of `Foo` is not general enough
+  --> $DIR/issue-54302-cases.rs:75:5
+   |
+LL |     <u64 as RefFoo<u64>>::ref_foo(a)
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `Foo<'static, u64>` would have to be implemented for the type `&'0 u64`, for any lifetime `'0`
+   = note: but `Foo<'_, u64>` is actually implemented for the type `&'1 u64`, for some specific lifetime `'1`
+
+error: implementation of `Foo` is not general enough
+  --> $DIR/issue-54302-cases.rs:81:5
+   |
+LL |     <i64 as RefFoo<i64>>::ref_foo(a)
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `Foo<'static, i64>` would have to be implemented for the type `&'0 i64`, for any lifetime `'0`
+   = note: but `Foo<'_, i64>` is actually implemented for the type `&'1 i64`, for some specific lifetime `'1`
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/issues/issue-54302.rs b/src/test/ui/issues/issue-54302.rs
new file mode 100644
index 0000000..1bfaebc
--- /dev/null
+++ b/src/test/ui/issues/issue-54302.rs
@@ -0,0 +1,19 @@
+trait Deserialize<'de> {}
+
+trait DeserializeOwned: for<'de> Deserialize<'de> {}
+impl<T> DeserializeOwned for T where T: for<'de> Deserialize<'de> {}
+
+// Based on this impl, `&'static str` only implements Deserialize<'static>.
+// It does not implement for<'de> Deserialize<'de>.
+impl<'de: 'a, 'a> Deserialize<'de> for &'a str {}
+
+fn main() {
+    // Then why does it implement DeserializeOwned? This compiles.
+    fn assert_deserialize_owned<T: DeserializeOwned>() {}
+    assert_deserialize_owned::<&'static str>();
+    //~^ ERROR not general enough
+
+    // It correctly does not implement for<'de> Deserialize<'de>.
+    //fn assert_hrtb<T: for<'de> Deserialize<'de>>() {}
+    //assert_hrtb::<&'static str>();
+}
diff --git a/src/test/ui/issues/issue-54302.stderr b/src/test/ui/issues/issue-54302.stderr
new file mode 100644
index 0000000..c6d0805
--- /dev/null
+++ b/src/test/ui/issues/issue-54302.stderr
@@ -0,0 +1,11 @@
+error: implementation of `Deserialize` is not general enough
+  --> $DIR/issue-54302.rs:13:5
+   |
+LL |     assert_deserialize_owned::<&'static str>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `&'static str` must implement `Deserialize<'0>`, for any lifetime `'0`
+   = note: but `&str` actually implements `Deserialize<'1>`, for some specific lifetime `'1`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-54348.rs b/src/test/ui/issues/issue-54348.rs
new file mode 100644
index 0000000..68d8380
--- /dev/null
+++ b/src/test/ui/issues/issue-54348.rs
@@ -0,0 +1,5 @@
+fn main() {
+    [1][0u64 as usize];
+    [1][1.5 as usize]; //~ ERROR index out of bounds
+    [1][1u64 as usize]; //~ ERROR index out of bounds
+}
diff --git a/src/test/ui/issues/issue-54348.stderr b/src/test/ui/issues/issue-54348.stderr
new file mode 100644
index 0000000..e39a1cb
--- /dev/null
+++ b/src/test/ui/issues/issue-54348.stderr
@@ -0,0 +1,16 @@
+error: index out of bounds: the len is 1 but the index is 1
+  --> $DIR/issue-54348.rs:3:5
+   |
+LL |     [1][1.5 as usize];
+   |     ^^^^^^^^^^^^^^^^^
+   |
+   = note: #[deny(const_err)] on by default
+
+error: index out of bounds: the len is 1 but the index is 1
+  --> $DIR/issue-54348.rs:4:5
+   |
+LL |     [1][1u64 as usize];
+   |     ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/issues/issue-54387.rs b/src/test/ui/issues/issue-54387.rs
new file mode 100644
index 0000000..ac1033a
--- /dev/null
+++ b/src/test/ui/issues/issue-54387.rs
@@ -0,0 +1,12 @@
+// compile-pass
+
+pub struct GstRc {
+    _obj: *const (),
+    _borrowed: bool,
+}
+
+const FOO: Option<GstRc> = None;
+
+fn main() {
+    let _meh = FOO;
+}
diff --git a/src/test/ui/issues/issue-5439.rs b/src/test/ui/issues/issue-5439.rs
new file mode 100644
index 0000000..cd03950
--- /dev/null
+++ b/src/test/ui/issues/issue-5439.rs
@@ -0,0 +1,21 @@
+#![feature(box_syntax)]
+
+struct Foo {
+    foo: isize,
+}
+
+struct Bar {
+    bar: isize,
+}
+
+impl Bar {
+    fn make_foo (&self, i: isize) -> Box<Foo> {
+        return box Foo { nonexistent: self, foo: i }; //~ ERROR: no field named
+    }
+}
+
+fn main () {
+    let bar = Bar { bar: 1 };
+    let foo = bar.make_foo(2);
+    println!("{}", foo.foo);
+}
diff --git a/src/test/ui/issues/issue-5439.stderr b/src/test/ui/issues/issue-5439.stderr
new file mode 100644
index 0000000..bd0cb67
--- /dev/null
+++ b/src/test/ui/issues/issue-5439.stderr
@@ -0,0 +1,11 @@
+error[E0560]: struct `Foo` has no field named `nonexistent`
+  --> $DIR/issue-5439.rs:13:26
+   |
+LL |         return box Foo { nonexistent: self, foo: i };
+   |                          ^^^^^^^^^^^ `Foo` does not have this field
+   |
+   = note: available fields are: `foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0560`.
diff --git a/src/test/ui/issues/issue-54410.rs b/src/test/ui/issues/issue-54410.rs
new file mode 100644
index 0000000..e3e8ca9
--- /dev/null
+++ b/src/test/ui/issues/issue-54410.rs
@@ -0,0 +1,8 @@
+extern "C" {
+    pub static mut symbol: [i8];
+    //~^ ERROR the size for values of type `[i8]` cannot be known at compilation time
+}
+
+fn main() {
+    println!("{:p}", unsafe { &symbol });
+}
diff --git a/src/test/ui/issues/issue-54410.stderr b/src/test/ui/issues/issue-54410.stderr
new file mode 100644
index 0000000..992c691
--- /dev/null
+++ b/src/test/ui/issues/issue-54410.stderr
@@ -0,0 +1,12 @@
+error[E0277]: the size for values of type `[i8]` cannot be known at compilation time
+  --> $DIR/issue-54410.rs:2:28
+   |
+LL |     pub static mut symbol: [i8];
+   |                            ^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `[i8]`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-54521-1.rs b/src/test/ui/issues/issue-54521-1.rs
new file mode 100644
index 0000000..d6a14a6
--- /dev/null
+++ b/src/test/ui/issues/issue-54521-1.rs
@@ -0,0 +1,16 @@
+// compile-pass
+
+// This test checks that the `remove extra angle brackets` error doesn't happen for some
+// potential edge-cases..
+
+struct X {
+    len: u32,
+}
+
+fn main() {
+    let x = X { len: 3 };
+
+    let _ = x.len > (3);
+
+    let _ = x.len >> (3);
+}
diff --git a/src/test/ui/issues/issue-54521-2.fixed b/src/test/ui/issues/issue-54521-2.fixed
new file mode 100644
index 0000000..a91c4fe
--- /dev/null
+++ b/src/test/ui/issues/issue-54521-2.fixed
@@ -0,0 +1,22 @@
+// run-rustfix
+
+// This test checks that the following error is emitted and the suggestion works:
+//
+// ```
+// let _ = Vec::<usize>>>::new();
+//                     ^^ help: remove extra angle brackets
+// ```
+
+fn main() {
+    let _ = Vec::<usize>::new();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = Vec::<usize>::new();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = Vec::<usize>::new();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = Vec::<usize>::new();
+    //~^ ERROR unmatched angle bracket
+}
diff --git a/src/test/ui/issues/issue-54521-2.rs b/src/test/ui/issues/issue-54521-2.rs
new file mode 100644
index 0000000..3639aac
--- /dev/null
+++ b/src/test/ui/issues/issue-54521-2.rs
@@ -0,0 +1,22 @@
+// run-rustfix
+
+// This test checks that the following error is emitted and the suggestion works:
+//
+// ```
+// let _ = Vec::<usize>>>::new();
+//                     ^^ help: remove extra angle brackets
+// ```
+
+fn main() {
+    let _ = Vec::<usize>>>>>::new();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = Vec::<usize>>>>::new();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = Vec::<usize>>>::new();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = Vec::<usize>>::new();
+    //~^ ERROR unmatched angle bracket
+}
diff --git a/src/test/ui/issues/issue-54521-2.stderr b/src/test/ui/issues/issue-54521-2.stderr
new file mode 100644
index 0000000..9556b83
--- /dev/null
+++ b/src/test/ui/issues/issue-54521-2.stderr
@@ -0,0 +1,26 @@
+error: unmatched angle brackets
+  --> $DIR/issue-54521-2.rs:11:25
+   |
+LL |     let _ = Vec::<usize>>>>>::new();
+   |                         ^^^^ help: remove extra angle brackets
+
+error: unmatched angle brackets
+  --> $DIR/issue-54521-2.rs:14:25
+   |
+LL |     let _ = Vec::<usize>>>>::new();
+   |                         ^^^ help: remove extra angle brackets
+
+error: unmatched angle brackets
+  --> $DIR/issue-54521-2.rs:17:25
+   |
+LL |     let _ = Vec::<usize>>>::new();
+   |                         ^^ help: remove extra angle brackets
+
+error: unmatched angle bracket
+  --> $DIR/issue-54521-2.rs:20:25
+   |
+LL |     let _ = Vec::<usize>>::new();
+   |                         ^ help: remove extra angle bracket
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/issues/issue-54521.fixed b/src/test/ui/issues/issue-54521.fixed
new file mode 100644
index 0000000..84ab686
--- /dev/null
+++ b/src/test/ui/issues/issue-54521.fixed
@@ -0,0 +1,22 @@
+// run-rustfix
+
+// This test checks that the following error is emitted and the suggestion works:
+//
+// ```
+// let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>();
+//                                                        ^^ help: remove extra angle brackets
+// ```
+
+fn main() {
+    let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>();
+    //~^ ERROR unmatched angle bracket
+}
diff --git a/src/test/ui/issues/issue-54521.rs b/src/test/ui/issues/issue-54521.rs
new file mode 100644
index 0000000..f1d6850
--- /dev/null
+++ b/src/test/ui/issues/issue-54521.rs
@@ -0,0 +1,22 @@
+// run-rustfix
+
+// This test checks that the following error is emitted and the suggestion works:
+//
+// ```
+// let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>();
+//                                                        ^^ help: remove extra angle brackets
+// ```
+
+fn main() {
+    let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>>>();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>>();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>();
+    //~^ ERROR unmatched angle bracket
+}
diff --git a/src/test/ui/issues/issue-54521.stderr b/src/test/ui/issues/issue-54521.stderr
new file mode 100644
index 0000000..ffefbfd
--- /dev/null
+++ b/src/test/ui/issues/issue-54521.stderr
@@ -0,0 +1,26 @@
+error: unmatched angle brackets
+  --> $DIR/issue-54521.rs:11:60
+   |
+LL |     let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>>>();
+   |                                                            ^^^^ help: remove extra angle brackets
+
+error: unmatched angle brackets
+  --> $DIR/issue-54521.rs:14:60
+   |
+LL |     let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>>();
+   |                                                            ^^^ help: remove extra angle brackets
+
+error: unmatched angle brackets
+  --> $DIR/issue-54521.rs:17:60
+   |
+LL |     let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>();
+   |                                                            ^^ help: remove extra angle brackets
+
+error: unmatched angle bracket
+  --> $DIR/issue-54521.rs:20:60
+   |
+LL |     let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>();
+   |                                                            ^ help: remove extra angle bracket
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/issues/issue-54582.rs b/src/test/ui/issues/issue-54582.rs
new file mode 100644
index 0000000..c2dbf36
--- /dev/null
+++ b/src/test/ui/issues/issue-54582.rs
@@ -0,0 +1,16 @@
+// run-pass
+
+pub trait Stage: Sync {}
+
+pub enum Enum {
+    A,
+    B,
+}
+
+impl Stage for Enum {}
+
+pub static ARRAY: [(&Stage, &str); 1] = [
+    (&Enum::A, ""),
+];
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-54943-1.rs b/src/test/ui/issues/issue-54943-1.rs
new file mode 100644
index 0000000..7750e34
--- /dev/null
+++ b/src/test/ui/issues/issue-54943-1.rs
@@ -0,0 +1,15 @@
+#![feature(nll)]
+
+// This test is a minimal version of an ICE in the dropck-eyepatch tests
+// found in the fix for #54943.
+
+// compile-pass
+
+fn foo<T>(_t: T) {
+}
+
+fn main() {
+    struct A<'a, B: 'a>(&'a B);
+    let (a1, a2): (String, A<_>) = (String::from("auto"), A(&"this"));
+    foo((a1, a2));
+}
diff --git a/src/test/ui/issues/issue-54943-2.rs b/src/test/ui/issues/issue-54943-2.rs
new file mode 100644
index 0000000..f829c38
--- /dev/null
+++ b/src/test/ui/issues/issue-54943-2.rs
@@ -0,0 +1,18 @@
+#![feature(nll)]
+
+// This test is a minimal version of an ICE in the dropck-eyepatch tests
+// found in the fix for #54943. In particular, this test is in unreachable
+// code as the initial fix for this ICE only worked if the code was reachable.
+
+// compile-pass
+
+fn foo<T>(_t: T) {
+}
+
+fn main() {
+    return;
+
+    struct A<'a, B: 'a>(&'a B);
+    let (a1, a2): (String, A<_>) = (String::from("auto"), A(&"this"));
+    foo((a1, a2));
+}
diff --git a/src/test/ui/issues/issue-54943-3.rs b/src/test/ui/issues/issue-54943-3.rs
new file mode 100644
index 0000000..185077b
--- /dev/null
+++ b/src/test/ui/issues/issue-54943-3.rs
@@ -0,0 +1,21 @@
+// compile-pass
+// FIXME(#54943) This test targets the scenario where proving the WF requirements requires
+// knowing the value of the `_` type present in the user type annotation - unfortunately, figuring
+// out the value of that `_` requires type-checking the surrounding code, but that code is dead,
+// so our NLL region checker doesn't have access to it. This test should actually fail to compile.
+
+#![feature(nll)]
+#![allow(warnings)]
+
+use std::fmt::Debug;
+
+fn foo<T: 'static + Debug>(_: T) { }
+
+fn bar<'a>() {
+    return;
+
+    let _x = foo::<Vec<_>>(Vec::<&'a u32>::new());
+    //~^ ERROR the type `&'a u32` does not fulfill the required lifetime [E0477]
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-54943.rs b/src/test/ui/issues/issue-54943.rs
new file mode 100644
index 0000000..ce4e010
--- /dev/null
+++ b/src/test/ui/issues/issue-54943.rs
@@ -0,0 +1,13 @@
+#![feature(nll)]
+#![allow(warnings)]
+
+fn foo<T: 'static>() { }
+
+fn boo<'a>() {
+    return;
+
+    let x = foo::<&'a u32>();
+    //~^ ERROR lifetime may not live long enough
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-54943.stderr b/src/test/ui/issues/issue-54943.stderr
new file mode 100644
index 0000000..aa68177
--- /dev/null
+++ b/src/test/ui/issues/issue-54943.stderr
@@ -0,0 +1,11 @@
+error: lifetime may not live long enough
+  --> $DIR/issue-54943.rs:9:13
+   |
+LL | fn boo<'a>() {
+   |        -- lifetime `'a` defined here
+...
+LL |     let x = foo::<&'a u32>();
+   |             ^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-54966.rs b/src/test/ui/issues/issue-54966.rs
new file mode 100644
index 0000000..0ed3c4b
--- /dev/null
+++ b/src/test/ui/issues/issue-54966.rs
@@ -0,0 +1,6 @@
+// issue-54966: ICE returning an unknown type with impl FnMut
+
+fn generate_duration() -> Oper<impl FnMut()> {}
+//~^ ERROR cannot find type `Oper` in this scope
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-54966.stderr b/src/test/ui/issues/issue-54966.stderr
new file mode 100644
index 0000000..aa9a61c
--- /dev/null
+++ b/src/test/ui/issues/issue-54966.stderr
@@ -0,0 +1,9 @@
+error[E0412]: cannot find type `Oper` in this scope
+  --> $DIR/issue-54966.rs:3:27
+   |
+LL | fn generate_duration() -> Oper<impl FnMut()> {}
+   |                           ^^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/src/test/ui/issues/issue-54974.rs b/src/test/ui/issues/issue-54974.rs
new file mode 100644
index 0000000..b2624ec
--- /dev/null
+++ b/src/test/ui/issues/issue-54974.rs
@@ -0,0 +1,16 @@
+// compile-pass
+// edition:2018
+
+#![feature(async_await, await_macro, futures_api)]
+
+use std::sync::Arc;
+
+trait SomeTrait: Send + Sync + 'static {
+    fn do_something(&self);
+}
+
+async fn my_task(obj: Arc<SomeTrait>) {
+    unimplemented!()
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-5500-1.ast.stderr b/src/test/ui/issues/issue-5500-1.ast.stderr
new file mode 100644
index 0000000..558e7b7
--- /dev/null
+++ b/src/test/ui/issues/issue-5500-1.ast.stderr
@@ -0,0 +1,15 @@
+error[E0594]: cannot assign to field `_iter.node` of immutable binding
+  --> $DIR/issue-5500-1.rs:12:5
+   |
+LL |       let _iter = TrieMapIterator{node: &a};
+   |           ----- help: make this binding mutable: `mut _iter`
+LL | /     _iter.node = &
+LL | |
+LL | |                    // MIR doesn't generate an error because the code isn't reachable. This is OK
+LL | |                    // because the test is here to check that the compiler doesn't ICE (cf. #5500).
+LL | |     panic!()
+   | |____________^ cannot mutably borrow field of immutable binding
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/issues/issue-5500-1.mir.stderr b/src/test/ui/issues/issue-5500-1.mir.stderr
new file mode 100644
index 0000000..92f803e
--- /dev/null
+++ b/src/test/ui/issues/issue-5500-1.mir.stderr
@@ -0,0 +1,15 @@
+error[E0594]: cannot assign to field `_iter.node` of immutable binding (Ast)
+  --> $DIR/issue-5500-1.rs:12:5
+   |
+LL |       let _iter = TrieMapIterator{node: &a};
+   |           ----- help: make this binding mutable: `mut _iter`
+LL | /     _iter.node = &
+LL | |
+LL | |                    // MIR doesn't generate an error because the code isn't reachable. This is OK
+LL | |                    // because the test is here to check that the compiler doesn't ICE (cf. #5500).
+LL | |     panic!()
+   | |____________^ cannot mutably borrow field of immutable binding
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/issues/issue-5500-1.rs b/src/test/ui/issues/issue-5500-1.rs
new file mode 100644
index 0000000..e804356
--- /dev/null
+++ b/src/test/ui/issues/issue-5500-1.rs
@@ -0,0 +1,17 @@
+// ignore-compare-mode-nll
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=compare
+
+struct TrieMapIterator<'a> {
+    node: &'a usize
+}
+
+fn main() {
+    let a = 5;
+    let _iter = TrieMapIterator{node: &a};
+    _iter.node = & //[ast]~ ERROR cannot assign to field `_iter.node` of immutable binding
+                   //[mir]~^ ERROR cannot assign to field `_iter.node` of immutable binding (Ast)
+                   // MIR doesn't generate an error because the code isn't reachable. This is OK
+                   // because the test is here to check that the compiler doesn't ICE (cf. #5500).
+    panic!()
+}
diff --git a/src/test/ui/issues/issue-55324.rs b/src/test/ui/issues/issue-55324.rs
new file mode 100644
index 0000000..6160fba
--- /dev/null
+++ b/src/test/ui/issues/issue-55324.rs
@@ -0,0 +1,14 @@
+// compile-pass
+// edition:2018
+
+#![feature(async_await, await_macro, futures_api)]
+
+use std::future::Future;
+
+#[allow(unused)]
+async fn foo<F: Future<Output = i32>>(x: &i32, future: F) -> i32 {
+    let y = await!(future);
+    *x + y
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-55511.nll.stderr b/src/test/ui/issues/issue-55511.nll.stderr
new file mode 100644
index 0000000..bf3e58e
--- /dev/null
+++ b/src/test/ui/issues/issue-55511.nll.stderr
@@ -0,0 +1,15 @@
+error[E0597]: `a` does not live long enough
+  --> $DIR/issue-55511.rs:13:28
+   |
+LL |     let b = Some(Cell::new(&a));
+   |                            ^^ borrowed value does not live long enough
+...
+LL |         <() as Foo<'static>>::C => { }
+   |         ----------------------- type annotation requires that `a` is borrowed for `'static`
+...
+LL | }
+   | - `a` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/issues/issue-55511.rs b/src/test/ui/issues/issue-55511.rs
new file mode 100644
index 0000000..4b9475b
--- /dev/null
+++ b/src/test/ui/issues/issue-55511.rs
@@ -0,0 +1,19 @@
+use std::cell::Cell;
+
+trait Foo<'a> {
+    const C: Option<Cell<&'a u32>>;
+}
+
+impl<'a, T> Foo<'a> for T {
+    const C: Option<Cell<&'a u32>> = None;
+}
+
+fn main() {
+    let a = 22;
+    let b = Some(Cell::new(&a));
+    //~^ ERROR `a` does not live long enough [E0597]
+    match b {
+        <() as Foo<'static>>::C => { }
+        _ => { }
+    }
+}
diff --git a/src/test/ui/issues/issue-55511.stderr b/src/test/ui/issues/issue-55511.stderr
new file mode 100644
index 0000000..24668f0
--- /dev/null
+++ b/src/test/ui/issues/issue-55511.stderr
@@ -0,0 +1,14 @@
+error[E0597]: `a` does not live long enough
+  --> $DIR/issue-55511.rs:13:29
+   |
+LL |     let b = Some(Cell::new(&a));
+   |                             ^ borrowed value does not live long enough
+...
+LL | }
+   | - borrowed value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/issues/issue-55587.rs b/src/test/ui/issues/issue-55587.rs
new file mode 100644
index 0000000..8b78749
--- /dev/null
+++ b/src/test/ui/issues/issue-55587.rs
@@ -0,0 +1,5 @@
+use std::path::Path;
+
+fn main() {
+    let Path::new(); //~ ERROR expected tuple struct/variant
+}
diff --git a/src/test/ui/issues/issue-55587.stderr b/src/test/ui/issues/issue-55587.stderr
new file mode 100644
index 0000000..1334f24
--- /dev/null
+++ b/src/test/ui/issues/issue-55587.stderr
@@ -0,0 +1,9 @@
+error[E0164]: expected tuple struct/variant, found method `<Path>::new`
+  --> $DIR/issue-55587.rs:4:9
+   |
+LL |     let Path::new();
+   |         ^^^^^^^^^^^ not a tuple variant or struct
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0164`.
diff --git a/src/test/ui/issues/issue-5572.rs b/src/test/ui/issues/issue-5572.rs
new file mode 100644
index 0000000..e5963a7
--- /dev/null
+++ b/src/test/ui/issues/issue-5572.rs
@@ -0,0 +1,7 @@
+// compile-pass
+#![allow(dead_code)]
+// pretty-expanded FIXME #23616
+
+fn foo<T: ::std::cmp::PartialEq>(_t: T) { }
+
+pub fn main() { }
diff --git a/src/test/ui/issues/issue-55731.rs b/src/test/ui/issues/issue-55731.rs
new file mode 100644
index 0000000..7b4f4e2
--- /dev/null
+++ b/src/test/ui/issues/issue-55731.rs
@@ -0,0 +1,52 @@
+use std::marker::PhantomData;
+
+trait DistributedIterator {
+    fn reduce(self)
+    where
+        Self: Sized,
+    {
+        unreachable!()
+    }
+}
+
+trait DistributedIteratorMulti<Source> {
+    type Item;
+}
+
+struct Connect<I>(PhantomData<fn(I)>);
+impl<I: for<'a> DistributedIteratorMulti<&'a ()>> DistributedIterator for Connect<I> where {}
+
+struct Cloned<Source>(PhantomData<fn(Source)>);
+impl<'a, Source> DistributedIteratorMulti<&'a Source> for Cloned<&'a Source> {
+    type Item = ();
+}
+
+struct Map<I, F> {
+    i: I,
+    f: F,
+}
+impl<I: DistributedIteratorMulti<Source>, F, Source> DistributedIteratorMulti<Source> for Map<I, F>
+where
+    F: A<<I as DistributedIteratorMulti<Source>>::Item>,
+{
+    type Item = ();
+}
+
+trait A<B> {}
+
+struct X;
+impl A<()> for X {}
+
+fn multi<I>(_reducer: I)
+where
+    I: for<'a> DistributedIteratorMulti<&'a ()>,
+{
+    DistributedIterator::reduce(Connect::<I>(PhantomData))
+}
+
+fn main() {
+    multi(Map { //~ ERROR implementation of `DistributedIteratorMulti` is not general enough
+        i: Cloned(PhantomData),
+        f: X,
+    });
+}
diff --git a/src/test/ui/issues/issue-55731.stderr b/src/test/ui/issues/issue-55731.stderr
new file mode 100644
index 0000000..f25e18e
--- /dev/null
+++ b/src/test/ui/issues/issue-55731.stderr
@@ -0,0 +1,11 @@
+error: implementation of `DistributedIteratorMulti` is not general enough
+  --> $DIR/issue-55731.rs:48:5
+   |
+LL |     multi(Map {
+   |     ^^^^^
+   |
+   = note: `DistributedIteratorMulti<&'0 ()>` would have to be implemented for the type `Cloned<&()>`, for any lifetime `'0`
+   = note: but `DistributedIteratorMulti<&'1 ()>` is actually implemented for the type `Cloned<&'1 ()>`, for some specific lifetime `'1`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-55796.rs b/src/test/ui/issues/issue-55796.rs
new file mode 100644
index 0000000..efdea5c
--- /dev/null
+++ b/src/test/ui/issues/issue-55796.rs
@@ -0,0 +1,26 @@
+pub trait EdgeTrait<N> {
+    fn target(&self) -> N;
+}
+
+pub trait Graph<'a> {
+    type Node;
+    type Edge: EdgeTrait<Self::Node>;
+    type NodesIter: Iterator<Item = Self::Node> + 'a;
+    type EdgesIter: Iterator<Item = Self::Edge> + 'a;
+
+    fn nodes(&'a self) -> Self::NodesIter;
+    fn out_edges(&'a self, u: &Self::Node) -> Self::EdgesIter;
+    fn in_edges(&'a self, u: &Self::Node) -> Self::EdgesIter;
+
+    fn out_neighbors(&'a self, u: &Self::Node) -> Box<Iterator<Item = Self::Node>> {
+        Box::new(self.out_edges(u).map(|e| e.target()))
+//~^ ERROR cannot infer
+    }
+
+    fn in_neighbors(&'a self, u: &Self::Node) -> Box<Iterator<Item = Self::Node>> {
+        Box::new(self.in_edges(u).map(|e| e.target()))
+//~^ ERROR cannot infer
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-55796.stderr b/src/test/ui/issues/issue-55796.stderr
new file mode 100644
index 0000000..7cf597d
--- /dev/null
+++ b/src/test/ui/issues/issue-55796.stderr
@@ -0,0 +1,45 @@
+error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
+  --> $DIR/issue-55796.rs:16:9
+   |
+LL |         Box::new(self.out_edges(u).map(|e| e.target()))
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: first, the lifetime cannot outlive the lifetime 'a as defined on the trait at 5:17...
+  --> $DIR/issue-55796.rs:5:17
+   |
+LL | pub trait Graph<'a> {
+   |                 ^^
+note: ...so that the type `std::iter::Map<<Self as Graph<'a>>::EdgesIter, [closure@$DIR/issue-55796.rs:16:40: 16:54]>` will meet its required lifetime bounds
+  --> $DIR/issue-55796.rs:16:9
+   |
+LL |         Box::new(self.out_edges(u).map(|e| e.target()))
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: but, the lifetime must be valid for the static lifetime...
+   = note: ...so that the expression is assignable:
+           expected std::boxed::Box<(dyn std::iter::Iterator<Item = <Self as Graph<'a>>::Node> + 'static)>
+              found std::boxed::Box<dyn std::iter::Iterator<Item = <Self as Graph<'a>>::Node>>
+
+error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
+  --> $DIR/issue-55796.rs:21:9
+   |
+LL |         Box::new(self.in_edges(u).map(|e| e.target()))
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: first, the lifetime cannot outlive the lifetime 'a as defined on the trait at 5:17...
+  --> $DIR/issue-55796.rs:5:17
+   |
+LL | pub trait Graph<'a> {
+   |                 ^^
+note: ...so that the type `std::iter::Map<<Self as Graph<'a>>::EdgesIter, [closure@$DIR/issue-55796.rs:21:39: 21:53]>` will meet its required lifetime bounds
+  --> $DIR/issue-55796.rs:21:9
+   |
+LL |         Box::new(self.in_edges(u).map(|e| e.target()))
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: but, the lifetime must be valid for the static lifetime...
+   = note: ...so that the expression is assignable:
+           expected std::boxed::Box<(dyn std::iter::Iterator<Item = <Self as Graph<'a>>::Node> + 'static)>
+              found std::boxed::Box<dyn std::iter::Iterator<Item = <Self as Graph<'a>>::Node>>
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0495`.
diff --git a/src/test/ui/issues/issue-55846.rs b/src/test/ui/issues/issue-55846.rs
new file mode 100644
index 0000000..bd76675
--- /dev/null
+++ b/src/test/ui/issues/issue-55846.rs
@@ -0,0 +1,39 @@
+// run-pass
+
+// Regression test for #55846, which once caused an ICE.
+
+use std::marker::PhantomData;
+
+struct Foo;
+
+struct Bar<A> {
+    a: PhantomData<A>,
+}
+
+impl Fooifier for Foo {
+    type Assoc = Foo;
+}
+
+trait Fooifier {
+    type Assoc;
+}
+
+trait Barifier<H> {
+    fn barify();
+}
+
+impl<H> Barifier<H> for Bar<H> {
+    fn barify() {
+        println!("All correct!");
+    }
+}
+
+impl Bar<<Foo as Fooifier>::Assoc> {
+    fn this_shouldnt_crash() {
+        <Self as Barifier<<Foo as Fooifier>::Assoc>>::barify();
+    }
+}
+
+fn main() {
+    Bar::<Foo>::this_shouldnt_crash();
+}
diff --git a/src/test/ui/issues/issue-56031.rs b/src/test/ui/issues/issue-56031.rs
new file mode 100644
index 0000000..b68f568
--- /dev/null
+++ b/src/test/ui/issues/issue-56031.rs
@@ -0,0 +1,6 @@
+struct T;
+
+impl for T {}
+//~^ ERROR missing trait in a trait impl
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-56031.stderr b/src/test/ui/issues/issue-56031.stderr
new file mode 100644
index 0000000..3d7acee
--- /dev/null
+++ b/src/test/ui/issues/issue-56031.stderr
@@ -0,0 +1,8 @@
+error: missing trait in a trait impl
+  --> $DIR/issue-56031.rs:3:5
+   |
+LL | impl for T {}
+   |     ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-56128.rs b/src/test/ui/issues/issue-56128.rs
new file mode 100644
index 0000000..3a3eccdc
--- /dev/null
+++ b/src/test/ui/issues/issue-56128.rs
@@ -0,0 +1,15 @@
+// Regression test for #56128. When this `pub(super) use...` gets
+// exploded in the HIR, we were not handling ids correctly.
+//
+// compile-pass
+
+mod bar {
+    pub(super) use self::baz::{x, y};
+
+    mod baz {
+        pub fn x() { }
+        pub fn y() { }
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/issues/issue-56199.rs b/src/test/ui/issues/issue-56199.rs
new file mode 100644
index 0000000..ba11582
--- /dev/null
+++ b/src/test/ui/issues/issue-56199.rs
@@ -0,0 +1,22 @@
+enum Foo {}
+struct Bar {}
+
+impl Foo {
+    fn foo() {
+        let _ = Self;
+        //~^ ERROR the `Self` constructor can only be used with tuple or unit structs
+        let _ = Self();
+        //~^ ERROR the `Self` constructor can only be used with tuple or unit structs
+    }
+}
+
+impl Bar {
+    fn bar() {
+        let _ = Self;
+        //~^ ERROR the `Self` constructor can only be used with tuple or unit structs
+        let _ = Self();
+        //~^ ERROR the `Self` constructor can only be used with tuple or unit structs
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-56199.stderr b/src/test/ui/issues/issue-56199.stderr
new file mode 100644
index 0000000..7aaf8e4
--- /dev/null
+++ b/src/test/ui/issues/issue-56199.stderr
@@ -0,0 +1,30 @@
+error: the `Self` constructor can only be used with tuple or unit structs
+  --> $DIR/issue-56199.rs:6:17
+   |
+LL |         let _ = Self;
+   |                 ^^^^
+   |
+   = help: did you mean to use one of the enum's variants?
+
+error: the `Self` constructor can only be used with tuple or unit structs
+  --> $DIR/issue-56199.rs:8:17
+   |
+LL |         let _ = Self();
+   |                 ^^^^
+   |
+   = help: did you mean to use one of the enum's variants?
+
+error: the `Self` constructor can only be used with tuple or unit structs
+  --> $DIR/issue-56199.rs:15:17
+   |
+LL |         let _ = Self;
+   |                 ^^^^ help: use curly brackets: `Self { /* fields */ }`
+
+error: the `Self` constructor can only be used with tuple or unit structs
+  --> $DIR/issue-56199.rs:17:17
+   |
+LL |         let _ = Self();
+   |                 ^^^^ help: use curly brackets: `Self { /* fields */ }`
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/issues/issue-56202.rs b/src/test/ui/issues/issue-56202.rs
new file mode 100644
index 0000000..bd222b7
--- /dev/null
+++ b/src/test/ui/issues/issue-56202.rs
@@ -0,0 +1,17 @@
+// compile-pass
+
+trait FooTrait {}
+
+trait BarTrait {
+    fn foo<T: FooTrait>(_: T) -> Self;
+}
+
+struct FooStruct(u32);
+
+impl BarTrait for FooStruct {
+    fn foo<T: FooTrait>(_: T) -> Self {
+        Self(u32::default())
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-56411-aux.rs b/src/test/ui/issues/issue-56411-aux.rs
new file mode 100644
index 0000000..bd689e9
--- /dev/null
+++ b/src/test/ui/issues/issue-56411-aux.rs
@@ -0,0 +1,5 @@
+// compile-pass
+
+struct T {}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-56411.rs b/src/test/ui/issues/issue-56411.rs
new file mode 100644
index 0000000..163651a
--- /dev/null
+++ b/src/test/ui/issues/issue-56411.rs
@@ -0,0 +1,18 @@
+macro_rules! import {
+    ( $(($path:expr, $name:ident)),* ) => {
+        $(
+            #[path = $path]
+            mod $name;
+            pub use self::$name;
+            //~^ ERROR the name `issue_56411_aux` is defined multiple times
+            //~| ERROR `issue_56411_aux` is private, and cannot be re-exported
+
+        )*
+    }
+}
+
+import!(("issue-56411-aux.rs", issue_56411_aux));
+
+fn main() {
+    println!("Hello, world!");
+}
diff --git a/src/test/ui/issues/issue-56411.stderr b/src/test/ui/issues/issue-56411.stderr
new file mode 100644
index 0000000..7b23b37
--- /dev/null
+++ b/src/test/ui/issues/issue-56411.stderr
@@ -0,0 +1,31 @@
+error[E0255]: the name `issue_56411_aux` is defined multiple times
+  --> $DIR/issue-56411.rs:6:21
+   |
+LL |             mod $name;
+   |             ---------- previous definition of the module `issue_56411_aux` here
+LL |             pub use self::$name;
+   |                     ^^^^^^^^^^^
+   |                     |
+   |                     `issue_56411_aux` reimported here
+   |                     you can use `as` to change the binding name of the import
+...
+LL | import!(("issue-56411-aux.rs", issue_56411_aux));
+   | ------------------------------------------------- in this macro invocation
+   |
+   = note: `issue_56411_aux` must be defined only once in the type namespace of this module
+
+error[E0365]: `issue_56411_aux` is private, and cannot be re-exported
+  --> $DIR/issue-56411.rs:6:21
+   |
+LL |             pub use self::$name;
+   |                     ^^^^^^^^^^^ re-export of private `issue_56411_aux`
+...
+LL | import!(("issue-56411-aux.rs", issue_56411_aux));
+   | ------------------------------------------------- in this macro invocation
+   |
+   = note: consider declaring type or module `issue_56411_aux` with `pub`
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0255, E0365.
+For more information about an error, try `rustc --explain E0255`.
diff --git a/src/test/ui/issues/issue-56488.rs b/src/test/ui/issues/issue-56488.rs
new file mode 100644
index 0000000..e2f3996
--- /dev/null
+++ b/src/test/ui/issues/issue-56488.rs
@@ -0,0 +1,13 @@
+// run-pass
+
+#![feature(trait_alias)]
+
+mod alpha {
+    pub trait A {}
+    pub trait C = A;
+}
+
+#[allow(unused_imports)]
+use alpha::C;
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-56685.rs b/src/test/ui/issues/issue-56685.rs
new file mode 100644
index 0000000..f320c99
--- /dev/null
+++ b/src/test/ui/issues/issue-56685.rs
@@ -0,0 +1,44 @@
+#![allow(dead_code)]
+#![deny(unused_variables)]
+
+// This test aims to check that unused variable suggestions update bindings in all
+// match arms.
+
+fn main() {
+    enum E {
+        A(i32,),
+        B(i32,),
+    }
+
+    match E::A(1) {
+        E::A(x) | E::B(x) => {}
+        //~^ ERROR unused variable: `x`
+    }
+
+    enum F {
+        A(i32, i32,),
+        B(i32, i32,),
+        C(i32, i32,),
+    }
+
+    let _ = match F::A(1, 2) {
+        F::A(x, y) | F::B(x, y) => { y },
+        //~^ ERROR unused variable: `x`
+        F::C(a, b) => { 3 }
+        //~^ ERROR unused variable: `a`
+        //~^^ ERROR unused variable: `b`
+    };
+
+    let _ = if let F::A(x, y) | F::B(x, y) = F::A(1, 2) {
+    //~^ ERROR unused variable: `x`
+        y
+    } else {
+        3
+    };
+
+    while let F::A(x, y) | F::B(x, y) = F::A(1, 2) {
+    //~^ ERROR unused variable: `x`
+        let _ = y;
+        break;
+    }
+}
diff --git a/src/test/ui/issues/issue-56685.stderr b/src/test/ui/issues/issue-56685.stderr
new file mode 100644
index 0000000..4a461c7
--- /dev/null
+++ b/src/test/ui/issues/issue-56685.stderr
@@ -0,0 +1,60 @@
+error: unused variable: `x`
+  --> $DIR/issue-56685.rs:14:14
+   |
+LL |         E::A(x) | E::B(x) => {}
+   |              ^         ^
+   |
+note: lint level defined here
+  --> $DIR/issue-56685.rs:2:9
+   |
+LL | #![deny(unused_variables)]
+   |         ^^^^^^^^^^^^^^^^
+help: consider prefixing with an underscore
+   |
+LL |         E::A(_x) | E::B(_x) => {}
+   |              ^^         ^^
+
+error: unused variable: `x`
+  --> $DIR/issue-56685.rs:25:14
+   |
+LL |         F::A(x, y) | F::B(x, y) => { y },
+   |              ^            ^
+help: consider prefixing with an underscore
+   |
+LL |         F::A(_x, y) | F::B(_x, y) => { y },
+   |              ^^            ^^
+
+error: unused variable: `a`
+  --> $DIR/issue-56685.rs:27:14
+   |
+LL |         F::C(a, b) => { 3 }
+   |              ^ help: consider prefixing with an underscore: `_a`
+
+error: unused variable: `b`
+  --> $DIR/issue-56685.rs:27:17
+   |
+LL |         F::C(a, b) => { 3 }
+   |                 ^ help: consider prefixing with an underscore: `_b`
+
+error: unused variable: `x`
+  --> $DIR/issue-56685.rs:32:25
+   |
+LL |     let _ = if let F::A(x, y) | F::B(x, y) = F::A(1, 2) {
+   |                         ^            ^
+help: consider prefixing with an underscore
+   |
+LL |     let _ = if let F::A(_x, y) | F::B(_x, y) = F::A(1, 2) {
+   |                         ^^            ^^
+
+error: unused variable: `x`
+  --> $DIR/issue-56685.rs:39:20
+   |
+LL |     while let F::A(x, y) | F::B(x, y) = F::A(1, 2) {
+   |                    ^            ^
+help: consider prefixing with an underscore
+   |
+LL |     while let F::A(_x, y) | F::B(_x, y) = F::A(1, 2) {
+   |                    ^^            ^^
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/issues/issue-56762.rs b/src/test/ui/issues/issue-56762.rs
new file mode 100644
index 0000000..97b66b2
--- /dev/null
+++ b/src/test/ui/issues/issue-56762.rs
@@ -0,0 +1,18 @@
+// only-x86_64
+const HUGE_SIZE: usize = !0usize / 8;
+
+
+pub struct TooBigArray {
+    arr: [u8; HUGE_SIZE],
+}
+
+impl TooBigArray {
+    pub const fn new() -> Self {
+        TooBigArray { arr: [0x00; HUGE_SIZE], }
+    }
+}
+
+static MY_TOO_BIG_ARRAY_1: TooBigArray = TooBigArray::new();
+static MY_TOO_BIG_ARRAY_2: [u8; HUGE_SIZE] = [0x00; HUGE_SIZE];
+
+fn main() { }
diff --git a/src/test/ui/issues/issue-56762.stderr b/src/test/ui/issues/issue-56762.stderr
new file mode 100644
index 0000000..83d5dc6
--- /dev/null
+++ b/src/test/ui/issues/issue-56762.stderr
@@ -0,0 +1,4 @@
+error: the type `[u8; 2305843009213693951]` is too big for the current architecture
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-56806.rs b/src/test/ui/issues/issue-56806.rs
new file mode 100644
index 0000000..b6454e5
--- /dev/null
+++ b/src/test/ui/issues/issue-56806.rs
@@ -0,0 +1,7 @@
+pub trait Trait {
+    fn dyn_instead_of_self(self: Box<dyn Trait>);
+    //~^ ERROR invalid method receiver type: std::boxed::Box<(dyn Trait + 'static)>
+}
+
+pub fn main() {
+}
diff --git a/src/test/ui/issues/issue-56806.stderr b/src/test/ui/issues/issue-56806.stderr
new file mode 100644
index 0000000..2dd3add
--- /dev/null
+++ b/src/test/ui/issues/issue-56806.stderr
@@ -0,0 +1,12 @@
+error[E0307]: invalid method receiver type: std::boxed::Box<(dyn Trait + 'static)>
+  --> $DIR/issue-56806.rs:2:34
+   |
+LL |     fn dyn_instead_of_self(self: Box<dyn Trait>);
+   |                                  ^^^^^^^^^^^^^^
+   |
+   = note: type must be `Self` or a type that dereferences to it
+   = help: consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0307`.
diff --git a/src/test/ui/issues/issue-56835.rs b/src/test/ui/issues/issue-56835.rs
new file mode 100644
index 0000000..4f976da
--- /dev/null
+++ b/src/test/ui/issues/issue-56835.rs
@@ -0,0 +1,9 @@
+pub struct Foo {}
+
+impl Foo {
+    fn bar(Self(foo): Self) {}
+    //~^ ERROR the `Self` constructor can only be used with tuple or unit structs
+    //~^^ ERROR expected tuple struct/variant, found self constructor `Self` [E0164]
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-56835.stderr b/src/test/ui/issues/issue-56835.stderr
new file mode 100644
index 0000000..f9fdf23
--- /dev/null
+++ b/src/test/ui/issues/issue-56835.stderr
@@ -0,0 +1,15 @@
+error: the `Self` constructor can only be used with tuple or unit structs
+  --> $DIR/issue-56835.rs:4:12
+   |
+LL |     fn bar(Self(foo): Self) {}
+   |            ^^^^^^^^^ help: use curly brackets: `Self { /* fields */ }`
+
+error[E0164]: expected tuple struct/variant, found self constructor `Self`
+  --> $DIR/issue-56835.rs:4:12
+   |
+LL |     fn bar(Self(foo): Self) {}
+   |            ^^^^^^^^^ not a tuple variant or struct
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0164`.
diff --git a/src/test/ui/issues/issue-56943.rs b/src/test/ui/issues/issue-56943.rs
new file mode 100644
index 0000000..8fc77ab
--- /dev/null
+++ b/src/test/ui/issues/issue-56943.rs
@@ -0,0 +1,8 @@
+// aux-build:issue-56943.rs
+
+extern crate issue_56943;
+
+fn main() {
+    let _: issue_56943::S = issue_56943::S2;
+    //~^ ERROR mismatched types [E0308]
+}
diff --git a/src/test/ui/issues/issue-56943.stderr b/src/test/ui/issues/issue-56943.stderr
new file mode 100644
index 0000000..2720205
--- /dev/null
+++ b/src/test/ui/issues/issue-56943.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-56943.rs:6:29
+   |
+LL |     let _: issue_56943::S = issue_56943::S2;
+   |                             ^^^^^^^^^^^^^^^ expected struct `issue_56943::S`, found struct `issue_56943::S2`
+   |
+   = note: expected type `issue_56943::S`
+              found type `issue_56943::S2`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-57156.rs b/src/test/ui/issues/issue-57156.rs
new file mode 100644
index 0000000..f20b0f4
--- /dev/null
+++ b/src/test/ui/issues/issue-57156.rs
@@ -0,0 +1,23 @@
+// compile-pass
+
+trait Foo<Args> {
+    type Output;
+}
+
+trait Bar<'a, T>: for<'s> Foo<&'s T, Output=bool> {
+    fn cb(&self) -> Box<dyn Bar<'a, T, Output=bool>>;
+}
+
+impl<'s> Foo<&'s ()> for () {
+    type Output = bool;
+}
+
+impl<'a> Bar<'a, ()> for () {
+    fn cb(&self) -> Box<dyn Bar<'a, (), Output=bool>> {
+        Box::new(*self)
+    }
+}
+
+fn main() {
+    let _t = ().cb();
+}
diff --git a/src/test/ui/issues/issue-57162.rs b/src/test/ui/issues/issue-57162.rs
new file mode 100644
index 0000000..abe0887
--- /dev/null
+++ b/src/test/ui/issues/issue-57162.rs
@@ -0,0 +1,7 @@
+// compile-pass
+
+trait Foo {}
+impl Foo for dyn Send {}
+
+impl<T: Sync + Sync> Foo for T {}
+fn main() {}
diff --git a/src/test/ui/issues/issue-57198-pass.rs b/src/test/ui/issues/issue-57198-pass.rs
new file mode 100644
index 0000000..3857def
--- /dev/null
+++ b/src/test/ui/issues/issue-57198-pass.rs
@@ -0,0 +1,9 @@
+// run-pass
+
+mod m {
+    pub fn r#for() {}
+}
+
+fn main() {
+    m::r#for();
+}
diff --git a/src/test/ui/issues/issue-57198.rs b/src/test/ui/issues/issue-57198.rs
new file mode 100644
index 0000000..714a46c
--- /dev/null
+++ b/src/test/ui/issues/issue-57198.rs
@@ -0,0 +1,8 @@
+mod m {
+    pub fn r#for() {}
+}
+
+fn main() {
+    m::for();
+    //~^ ERROR expected identifier, found keyword `for`
+}
diff --git a/src/test/ui/issues/issue-57198.stderr b/src/test/ui/issues/issue-57198.stderr
new file mode 100644
index 0000000..2ab552c
--- /dev/null
+++ b/src/test/ui/issues/issue-57198.stderr
@@ -0,0 +1,12 @@
+error: expected identifier, found keyword `for`
+  --> $DIR/issue-57198.rs:6:8
+   |
+LL |     m::for();
+   |        ^^^ expected identifier, found keyword
+help: you can escape reserved keywords to use them as identifiers
+   |
+LL |     m::r#for();
+   |        ^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-57362-1.rs b/src/test/ui/issues/issue-57362-1.rs
new file mode 100644
index 0000000..1fa417f
--- /dev/null
+++ b/src/test/ui/issues/issue-57362-1.rs
@@ -0,0 +1,23 @@
+// Test for issue #57362, ensuring that the self ty is shown in cases of higher-ranked lifetimes
+// conflicts: the `expected` and `found` trait refs would otherwise be printed the same, leading
+// to confusing notes such as:
+//  = note: expected type `Trait`
+//             found type `Trait`
+
+// from issue #57362
+trait Trait {
+    fn f(self);
+}
+
+impl<T> Trait for fn(&T) {
+    fn f(self) {
+        println!("f");
+    }
+}
+
+fn f() {
+    let a: fn(_) = |_: &u8| {};
+    a.f(); //~ ERROR no method named `f`
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-57362-1.stderr b/src/test/ui/issues/issue-57362-1.stderr
new file mode 100644
index 0000000..1d2ff76
--- /dev/null
+++ b/src/test/ui/issues/issue-57362-1.stderr
@@ -0,0 +1,14 @@
+error[E0599]: no method named `f` found for type `fn(&u8)` in the current scope
+  --> $DIR/issue-57362-1.rs:20:7
+   |
+LL |     a.f();
+   |       ^
+   |
+   = note: a is a function, perhaps you wish to call it
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following trait defines an item `f`, perhaps you need to implement it:
+           candidate #1: `Trait`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/issues/issue-57362-2.rs b/src/test/ui/issues/issue-57362-2.rs
new file mode 100644
index 0000000..870d7f2
--- /dev/null
+++ b/src/test/ui/issues/issue-57362-2.rs
@@ -0,0 +1,25 @@
+// Test for issue #57362, ensuring that the self ty is shown in cases of higher-ranked lifetimes
+// conflicts: the `expected` and `found` trait refs would otherwise be printed the same, leading
+// to confusing notes such as:
+//  = note: expected type `Trait`
+//             found type `Trait`
+
+// extracted from a similar issue: #57642
+trait X {
+    type G;
+    fn make_g() -> Self::G;
+}
+
+impl<'a> X for fn(&'a ()) {
+    type G = &'a ();
+
+    fn make_g() -> Self::G {
+        &()
+    }
+}
+
+fn g() {
+    let x = <fn (&())>::make_g(); //~ ERROR no function or associated item
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-57362-2.stderr b/src/test/ui/issues/issue-57362-2.stderr
new file mode 100644
index 0000000..2e713cc
--- /dev/null
+++ b/src/test/ui/issues/issue-57362-2.stderr
@@ -0,0 +1,13 @@
+error[E0599]: no function or associated item named `make_g` found for type `for<'r> fn(&'r ())` in the current scope
+  --> $DIR/issue-57362-2.rs:22:25
+   |
+LL |     let x = <fn (&())>::make_g();
+   |                         ^^^^^^ function or associated item not found in `for<'r> fn(&'r ())`
+   |
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following trait defines an item `make_g`, perhaps you need to implement it:
+           candidate #1: `X`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/issues/issue-57410-1.rs b/src/test/ui/issues/issue-57410-1.rs
new file mode 100644
index 0000000..dab77bd
--- /dev/null
+++ b/src/test/ui/issues/issue-57410-1.rs
@@ -0,0 +1,18 @@
+// compile-pass
+
+// Originally from #53925.
+// Tests that the `unreachable_pub` lint doesn't fire for `pub self::bar::Bar`.
+
+#![deny(unreachable_pub)]
+
+mod foo {
+    mod bar {
+        pub struct Bar;
+    }
+
+    pub use self::bar::Bar;
+}
+
+pub use foo::Bar;
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-57410.rs b/src/test/ui/issues/issue-57410.rs
new file mode 100644
index 0000000..0d697e5
--- /dev/null
+++ b/src/test/ui/issues/issue-57410.rs
@@ -0,0 +1,17 @@
+// compile-pass
+
+// Tests that the `unreachable_pub` lint doesn't fire for `pub self::imp::f`.
+
+#![deny(unreachable_pub)]
+
+mod m {
+    mod imp {
+        pub fn f() {}
+    }
+
+    pub use self::imp::f;
+}
+
+pub use self::m::f;
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-57472.rs b/src/test/ui/issues/issue-57472.rs
new file mode 100644
index 0000000..1131006
--- /dev/null
+++ b/src/test/ui/issues/issue-57472.rs
@@ -0,0 +1,35 @@
+#![crate_type="lib"]
+#![deny(unreachable_patterns)]
+
+mod test_struct {
+    // Test the exact copy of the minimal example
+    // posted in the issue.
+    pub struct Punned {
+        foo: [u8; 1],
+        bar: [u8; 1],
+    }
+
+    pub fn test(punned: Punned) {
+        match punned {
+            Punned { foo: [_], .. } => println!("foo"),
+            Punned { bar: [_], .. } => println!("bar"),
+            //~^ ERROR unreachable pattern [unreachable_patterns]
+        }
+    }
+}
+
+mod test_union {
+    // Test the same thing using a union.
+    pub union Punned {
+        foo: [u8; 1],
+        bar: [u8; 1],
+    }
+
+    pub fn test(punned: Punned) {
+        match punned {
+            Punned { foo: [_] } => println!("foo"),
+            Punned { bar: [_] } => println!("bar"),
+            //~^ ERROR unreachable pattern [unreachable_patterns]
+        }
+    }
+}
diff --git a/src/test/ui/issues/issue-57472.stderr b/src/test/ui/issues/issue-57472.stderr
new file mode 100644
index 0000000..b6dd7e2
--- /dev/null
+++ b/src/test/ui/issues/issue-57472.stderr
@@ -0,0 +1,20 @@
+error: unreachable pattern
+  --> $DIR/issue-57472.rs:15:13
+   |
+LL |             Punned { bar: [_], .. } => println!("bar"),
+   |             ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/issue-57472.rs:2:9
+   |
+LL | #![deny(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/issue-57472.rs:31:13
+   |
+LL |             Punned { bar: [_] } => println!("bar"),
+   |             ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/issues/issue-5754.rs b/src/test/ui/issues/issue-5754.rs
new file mode 100644
index 0000000..78e8701
--- /dev/null
+++ b/src/test/ui/issues/issue-5754.rs
@@ -0,0 +1,16 @@
+// compile-pass
+#![allow(dead_code)]
+#![allow(improper_ctypes)]
+
+// pretty-expanded FIXME #23616
+
+struct TwoDoubles {
+    r: f64,
+    i: f64
+}
+
+extern "C" {
+    fn rust_dbg_extern_identity_TwoDoubles(arg1: TwoDoubles) -> TwoDoubles;
+}
+
+pub fn main() {}
diff --git a/src/test/ui/issues/issue-57597.rs b/src/test/ui/issues/issue-57597.rs
new file mode 100644
index 0000000..ebeb3fe
--- /dev/null
+++ b/src/test/ui/issues/issue-57597.rs
@@ -0,0 +1,80 @@
+// Regression test for #57597.
+//
+// Make sure that nested matchers work correctly rather than causing an infinite loop or crash.
+
+// edition:2018
+
+macro_rules! foo1 {
+    ($($($i:ident)?)+) => {};
+    //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo2 {
+    ($($($i:ident)?)*) => {};
+    //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo3 {
+    ($($($i:ident)?)?) => {};
+    //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo4 {
+    ($($($($i:ident)?)?)?) => {};
+    //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo5 {
+    ($($($($i:ident)*)?)?) => {};
+    //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo6 {
+    ($($($($i:ident)?)*)?) => {};
+    //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo7 {
+    ($($($($i:ident)?)?)*) => {};
+    //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo8 {
+    ($($($($i:ident)*)*)?) => {};
+    //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo9 {
+    ($($($($i:ident)?)*)*) => {};
+    //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo10 {
+    ($($($($i:ident)?)*)+) => {};
+    //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo11 {
+    ($($($($i:ident)+)?)*) => {};
+    //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo12 {
+    ($($($($i:ident)+)*)?) => {};
+    //~^ ERROR repetition matches empty token tree
+}
+
+fn main() {
+    foo1!();
+    foo2!();
+    foo3!();
+    foo4!();
+    foo5!();
+    foo6!();
+    foo7!();
+    foo8!();
+    foo9!();
+    foo10!();
+    foo11!();
+    foo12!();
+}
diff --git a/src/test/ui/issues/issue-57597.stderr b/src/test/ui/issues/issue-57597.stderr
new file mode 100644
index 0000000..0a02ac8
--- /dev/null
+++ b/src/test/ui/issues/issue-57597.stderr
@@ -0,0 +1,74 @@
+error: repetition matches empty token tree
+  --> $DIR/issue-57597.rs:8:7
+   |
+LL |     ($($($i:ident)?)+) => {};
+   |       ^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-57597.rs:13:7
+   |
+LL |     ($($($i:ident)?)*) => {};
+   |       ^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-57597.rs:18:7
+   |
+LL |     ($($($i:ident)?)?) => {};
+   |       ^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-57597.rs:23:7
+   |
+LL |     ($($($($i:ident)?)?)?) => {};
+   |       ^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-57597.rs:28:7
+   |
+LL |     ($($($($i:ident)*)?)?) => {};
+   |       ^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-57597.rs:33:7
+   |
+LL |     ($($($($i:ident)?)*)?) => {};
+   |       ^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-57597.rs:38:7
+   |
+LL |     ($($($($i:ident)?)?)*) => {};
+   |       ^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-57597.rs:43:7
+   |
+LL |     ($($($($i:ident)*)*)?) => {};
+   |       ^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-57597.rs:48:7
+   |
+LL |     ($($($($i:ident)?)*)*) => {};
+   |       ^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-57597.rs:53:7
+   |
+LL |     ($($($($i:ident)?)*)+) => {};
+   |       ^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-57597.rs:58:7
+   |
+LL |     ($($($($i:ident)+)?)*) => {};
+   |       ^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-57597.rs:63:7
+   |
+LL |     ($($($($i:ident)+)*)?) => {};
+   |       ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 12 previous errors
+
diff --git a/src/test/ui/issues/issue-57684.fixed b/src/test/ui/issues/issue-57684.fixed
new file mode 100644
index 0000000..4a43220
--- /dev/null
+++ b/src/test/ui/issues/issue-57684.fixed
@@ -0,0 +1,37 @@
+// run-rustfix
+
+#![allow(warnings)]
+
+// This test checks that the following error is emitted when a `=` character is used to initialize
+// a struct field when a `:` is expected.
+//
+// ```
+// error: struct fields are initialized with a colon
+//   --> $DIR/issue-57684.rs:12:20
+//    |
+// LL |     let _ = X { f1 = 5 };
+//    |                    ^ help: replace equals symbol with a colon: `:`
+// ```
+
+struct X {
+    f1: i32,
+}
+
+struct Y {
+    f1: i32,
+    f2: i32,
+    f3: i32,
+}
+
+fn main() {
+    let _ = X { f1: 5 };
+    //~^ ERROR expected `:`, found `=`
+
+    let f3 = 3;
+    let _ = Y {
+        f1: 5,
+        //~^ ERROR expected `:`, found `=`
+        f2: 4,
+        f3,
+    };
+}
diff --git a/src/test/ui/issues/issue-57684.rs b/src/test/ui/issues/issue-57684.rs
new file mode 100644
index 0000000..7a62785
--- /dev/null
+++ b/src/test/ui/issues/issue-57684.rs
@@ -0,0 +1,37 @@
+// run-rustfix
+
+#![allow(warnings)]
+
+// This test checks that the following error is emitted when a `=` character is used to initialize
+// a struct field when a `:` is expected.
+//
+// ```
+// error: struct fields are initialized with a colon
+//   --> $DIR/issue-57684.rs:12:20
+//    |
+// LL |     let _ = X { f1 = 5 };
+//    |                    ^ help: replace equals symbol with a colon: `:`
+// ```
+
+struct X {
+    f1: i32,
+}
+
+struct Y {
+    f1: i32,
+    f2: i32,
+    f3: i32,
+}
+
+fn main() {
+    let _ = X { f1 = 5 };
+    //~^ ERROR expected `:`, found `=`
+
+    let f3 = 3;
+    let _ = Y {
+        f1 = 5,
+        //~^ ERROR expected `:`, found `=`
+        f2: 4,
+        f3,
+    };
+}
diff --git a/src/test/ui/issues/issue-57684.stderr b/src/test/ui/issues/issue-57684.stderr
new file mode 100644
index 0000000..514bbff
--- /dev/null
+++ b/src/test/ui/issues/issue-57684.stderr
@@ -0,0 +1,18 @@
+error: expected `:`, found `=`
+  --> $DIR/issue-57684.rs:27:20
+   |
+LL |     let _ = X { f1 = 5 };
+   |                   -^
+   |                   |
+   |                   help: replace equals symbol with a colon: `:`
+
+error: expected `:`, found `=`
+  --> $DIR/issue-57684.rs:32:12
+   |
+LL |         f1 = 5,
+   |           -^
+   |           |
+   |           help: replace equals symbol with a colon: `:`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/issues/issue-57741-1.rs b/src/test/ui/issues/issue-57741-1.rs
new file mode 100644
index 0000000..d0aae23
--- /dev/null
+++ b/src/test/ui/issues/issue-57741-1.rs
@@ -0,0 +1,18 @@
+#![allow(warnings)]
+
+// This tests that the `help: consider dereferencing the boxed value` suggestion isn't made
+// because the box doesn't deref to the type of the arm.
+
+enum S {
+    A { a: usize },
+    B { b: usize },
+}
+
+fn main() {
+    let x = Box::new(3u32);
+    let y = match x {
+        S::A { a } | S::B { b: a } => a,
+        //~^ ERROR mismatched types [E0308]
+        //~^^ ERROR mismatched types [E0308]
+    };
+}
diff --git a/src/test/ui/issues/issue-57741-1.stderr b/src/test/ui/issues/issue-57741-1.stderr
new file mode 100644
index 0000000..d36424b
--- /dev/null
+++ b/src/test/ui/issues/issue-57741-1.stderr
@@ -0,0 +1,25 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-57741-1.rs:14:9
+   |
+LL |     let y = match x {
+   |                   - this match expression has type `std::boxed::Box<u32>`
+LL |         S::A { a } | S::B { b: a } => a,
+   |         ^^^^^^^^^^ expected struct `std::boxed::Box`, found enum `S`
+   |
+   = note: expected type `std::boxed::Box<u32>`
+              found type `S`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-57741-1.rs:14:22
+   |
+LL |     let y = match x {
+   |                   - this match expression has type `std::boxed::Box<u32>`
+LL |         S::A { a } | S::B { b: a } => a,
+   |                      ^^^^^^^^^^^^^ expected struct `std::boxed::Box`, found enum `S`
+   |
+   = note: expected type `std::boxed::Box<u32>`
+              found type `S`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-57741.fixed b/src/test/ui/issues/issue-57741.fixed
new file mode 100644
index 0000000..4cae080
--- /dev/null
+++ b/src/test/ui/issues/issue-57741.fixed
@@ -0,0 +1,31 @@
+// run-rustfix
+
+#![allow(warnings)]
+
+// This tests that the `help: consider dereferencing the boxed value` suggestion is made and works.
+
+enum S {
+    A { a: usize },
+    B { b: usize },
+}
+
+enum T {
+    A(usize),
+    B(usize),
+}
+
+fn main() {
+    let x = Box::new(T::A(3));
+    let y = match *x {
+        T::A(a) | T::B(a) => a,
+        //~^ ERROR mismatched types [E0308]
+        //~^^ ERROR mismatched types [E0308]
+    };
+
+    let x = Box::new(S::A { a: 3 });
+    let y = match *x {
+        S::A { a } | S::B { b: a } => a,
+        //~^ ERROR mismatched types [E0308]
+        //~^^ ERROR mismatched types [E0308]
+    };
+}
diff --git a/src/test/ui/issues/issue-57741.rs b/src/test/ui/issues/issue-57741.rs
new file mode 100644
index 0000000..e265829
--- /dev/null
+++ b/src/test/ui/issues/issue-57741.rs
@@ -0,0 +1,31 @@
+// run-rustfix
+
+#![allow(warnings)]
+
+// This tests that the `help: consider dereferencing the boxed value` suggestion is made and works.
+
+enum S {
+    A { a: usize },
+    B { b: usize },
+}
+
+enum T {
+    A(usize),
+    B(usize),
+}
+
+fn main() {
+    let x = Box::new(T::A(3));
+    let y = match x {
+        T::A(a) | T::B(a) => a,
+        //~^ ERROR mismatched types [E0308]
+        //~^^ ERROR mismatched types [E0308]
+    };
+
+    let x = Box::new(S::A { a: 3 });
+    let y = match x {
+        S::A { a } | S::B { b: a } => a,
+        //~^ ERROR mismatched types [E0308]
+        //~^^ ERROR mismatched types [E0308]
+    };
+}
diff --git a/src/test/ui/issues/issue-57741.stderr b/src/test/ui/issues/issue-57741.stderr
new file mode 100644
index 0000000..a26b1d20
--- /dev/null
+++ b/src/test/ui/issues/issue-57741.stderr
@@ -0,0 +1,59 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-57741.rs:20:9
+   |
+LL |     let y = match x {
+   |                   -
+   |                   |
+   |                   this match expression has type `std::boxed::Box<T>`
+   |                   help: consider dereferencing the boxed value: `*x`
+LL |         T::A(a) | T::B(a) => a,
+   |         ^^^^^^^ expected struct `std::boxed::Box`, found enum `T`
+   |
+   = note: expected type `std::boxed::Box<T>`
+              found type `T`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-57741.rs:20:19
+   |
+LL |     let y = match x {
+   |                   -
+   |                   |
+   |                   this match expression has type `std::boxed::Box<T>`
+   |                   help: consider dereferencing the boxed value: `*x`
+LL |         T::A(a) | T::B(a) => a,
+   |                   ^^^^^^^ expected struct `std::boxed::Box`, found enum `T`
+   |
+   = note: expected type `std::boxed::Box<T>`
+              found type `T`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-57741.rs:27:9
+   |
+LL |     let y = match x {
+   |                   -
+   |                   |
+   |                   this match expression has type `std::boxed::Box<S>`
+   |                   help: consider dereferencing the boxed value: `*x`
+LL |         S::A { a } | S::B { b: a } => a,
+   |         ^^^^^^^^^^ expected struct `std::boxed::Box`, found enum `S`
+   |
+   = note: expected type `std::boxed::Box<S>`
+              found type `S`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-57741.rs:27:22
+   |
+LL |     let y = match x {
+   |                   -
+   |                   |
+   |                   this match expression has type `std::boxed::Box<S>`
+   |                   help: consider dereferencing the boxed value: `*x`
+LL |         S::A { a } | S::B { b: a } => a,
+   |                      ^^^^^^^^^^^^^ expected struct `std::boxed::Box`, found enum `S`
+   |
+   = note: expected type `std::boxed::Box<S>`
+              found type `S`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-57781.rs b/src/test/ui/issues/issue-57781.rs
new file mode 100644
index 0000000..f5015aa
--- /dev/null
+++ b/src/test/ui/issues/issue-57781.rs
@@ -0,0 +1,20 @@
+// run-pass
+
+use std::cell::UnsafeCell;
+use std::collections::HashMap;
+
+struct OnceCell<T> {
+    _value: UnsafeCell<Option<T>>,
+}
+
+impl<T> OnceCell<T> {
+    const INIT: OnceCell<T> = OnceCell {
+        _value: UnsafeCell::new(None),
+    };
+}
+
+pub fn crash<K, T>() {
+    let _ = OnceCell::<HashMap<K, T>>::INIT;
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-57819.fixed b/src/test/ui/issues/issue-57819.fixed
new file mode 100644
index 0000000..3fab21d
--- /dev/null
+++ b/src/test/ui/issues/issue-57819.fixed
@@ -0,0 +1,47 @@
+// run-rustfix
+
+#![allow(warnings)]
+
+// This test checks that the following error is emitted and the suggestion works:
+//
+// ```
+// let _ = vec![1, 2, 3].into_iter().collect::<<<Vec<usize>>();
+//                                            ^^ help: remove extra angle brackets
+// ```
+
+trait Foo {
+    type Output;
+}
+
+fn foo<T: Foo>() {
+    // More complex cases with more than one correct leading `<` character:
+
+    bar::<<T as Foo>::Output>();
+    //~^ ERROR unmatched angle bracket
+
+    bar::<<T as Foo>::Output>();
+    //~^ ERROR unmatched angle bracket
+
+    bar::<<T as Foo>::Output>();
+    //~^ ERROR unmatched angle bracket
+
+    bar::<<T as Foo>::Output>();
+}
+
+fn bar<T>() {}
+
+fn main() {
+    let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>();
+}
diff --git a/src/test/ui/issues/issue-57819.rs b/src/test/ui/issues/issue-57819.rs
new file mode 100644
index 0000000..5cafbf4
--- /dev/null
+++ b/src/test/ui/issues/issue-57819.rs
@@ -0,0 +1,47 @@
+// run-rustfix
+
+#![allow(warnings)]
+
+// This test checks that the following error is emitted and the suggestion works:
+//
+// ```
+// let _ = vec![1, 2, 3].into_iter().collect::<<<Vec<usize>>();
+//                                            ^^ help: remove extra angle brackets
+// ```
+
+trait Foo {
+    type Output;
+}
+
+fn foo<T: Foo>() {
+    // More complex cases with more than one correct leading `<` character:
+
+    bar::<<<<<T as Foo>::Output>();
+    //~^ ERROR unmatched angle bracket
+
+    bar::<<<<T as Foo>::Output>();
+    //~^ ERROR unmatched angle bracket
+
+    bar::<<<T as Foo>::Output>();
+    //~^ ERROR unmatched angle bracket
+
+    bar::<<T as Foo>::Output>();
+}
+
+fn bar<T>() {}
+
+fn main() {
+    let _ = vec![1, 2, 3].into_iter().collect::<<<<<Vec<usize>>();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = vec![1, 2, 3].into_iter().collect::<<<<Vec<usize>>();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = vec![1, 2, 3].into_iter().collect::<<<Vec<usize>>();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = vec![1, 2, 3].into_iter().collect::<<Vec<usize>>();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>();
+}
diff --git a/src/test/ui/issues/issue-57819.stderr b/src/test/ui/issues/issue-57819.stderr
new file mode 100644
index 0000000..493e983
--- /dev/null
+++ b/src/test/ui/issues/issue-57819.stderr
@@ -0,0 +1,44 @@
+error: unmatched angle brackets
+  --> $DIR/issue-57819.rs:19:10
+   |
+LL |     bar::<<<<<T as Foo>::Output>();
+   |          ^^^ help: remove extra angle brackets
+
+error: unmatched angle brackets
+  --> $DIR/issue-57819.rs:22:10
+   |
+LL |     bar::<<<<T as Foo>::Output>();
+   |          ^^ help: remove extra angle brackets
+
+error: unmatched angle bracket
+  --> $DIR/issue-57819.rs:25:10
+   |
+LL |     bar::<<<T as Foo>::Output>();
+   |          ^ help: remove extra angle bracket
+
+error: unmatched angle brackets
+  --> $DIR/issue-57819.rs:34:48
+   |
+LL |     let _ = vec![1, 2, 3].into_iter().collect::<<<<<Vec<usize>>();
+   |                                                ^^^^ help: remove extra angle brackets
+
+error: unmatched angle brackets
+  --> $DIR/issue-57819.rs:37:48
+   |
+LL |     let _ = vec![1, 2, 3].into_iter().collect::<<<<Vec<usize>>();
+   |                                                ^^^ help: remove extra angle brackets
+
+error: unmatched angle brackets
+  --> $DIR/issue-57819.rs:40:48
+   |
+LL |     let _ = vec![1, 2, 3].into_iter().collect::<<<Vec<usize>>();
+   |                                                ^^ help: remove extra angle brackets
+
+error: unmatched angle bracket
+  --> $DIR/issue-57819.rs:43:48
+   |
+LL |     let _ = vec![1, 2, 3].into_iter().collect::<<Vec<usize>>();
+   |                                                ^ help: remove extra angle bracket
+
+error: aborting due to 7 previous errors
+
diff --git a/src/test/ui/issues/issue-57843.rs b/src/test/ui/issues/issue-57843.rs
new file mode 100644
index 0000000..4660825
--- /dev/null
+++ b/src/test/ui/issues/issue-57843.rs
@@ -0,0 +1,24 @@
+// Regression test for an ICE that occurred with the universes code:
+//
+// The signature of the closure `|_|` was being inferred to
+// `exists<'r> fn(&'r u8)`. This should result in a type error since
+// the signature `for<'r> fn(&'r u8)` is required. However, due to a
+// bug in the type variable generalization code, the placeholder for
+// `'r` was leaking out into the writeback phase, causing an ICE.
+
+trait ClonableFn<T> {
+    fn clone(&self) -> Box<dyn Fn(T)>;
+}
+
+impl<T, F: 'static> ClonableFn<T> for F
+where F: Fn(T) + Clone {
+    fn clone(&self) -> Box<dyn Fn(T)> {
+        Box::new(self.clone())
+    }
+}
+
+struct Foo(Box<dyn for<'a> ClonableFn<&'a bool>>);
+
+fn main() {
+    Foo(Box::new(|_| ())); //~ ERROR mismatched types
+}
diff --git a/src/test/ui/issues/issue-57843.stderr b/src/test/ui/issues/issue-57843.stderr
new file mode 100644
index 0000000..57b206d
--- /dev/null
+++ b/src/test/ui/issues/issue-57843.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-57843.rs:23:9
+   |
+LL |     Foo(Box::new(|_| ()));
+   |         ^^^^^^^^^^^^^^^^ one type is more general than the other
+   |
+   = note: expected type `std::ops::FnOnce<(&'a bool,)>`
+              found type `std::ops::FnOnce<(&bool,)>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-57866.rs b/src/test/ui/issues/issue-57866.rs
new file mode 100644
index 0000000..77c50e5
--- /dev/null
+++ b/src/test/ui/issues/issue-57866.rs
@@ -0,0 +1,26 @@
+// compile-pass
+
+#![feature(type_alias_enum_variants)]
+
+enum Outer<T> {
+    A(T)
+}
+
+enum Inner {
+    A(i32)
+}
+
+type OuterAlias = Outer<Inner>;
+
+fn ice(x: OuterAlias) {
+    // Fine
+    match x {
+        OuterAlias::A(Inner::A(_)) => (),
+    }
+    // Not fine
+    match x {
+        OuterAlias::A(Inner::A(y)) => (),
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-58006.rs b/src/test/ui/issues/issue-58006.rs
new file mode 100644
index 0000000..1fb5fef
--- /dev/null
+++ b/src/test/ui/issues/issue-58006.rs
@@ -0,0 +1,15 @@
+#![feature(type_alias_enum_variants)]
+pub enum Enum {
+    A(usize),
+}
+
+impl Enum {
+    fn foo(&self) -> () {
+        match self {
+            Self::A => (),
+            //~^ ERROR expected unit struct/variant or constant, found tuple variant
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-58006.stderr b/src/test/ui/issues/issue-58006.stderr
new file mode 100644
index 0000000..c65e3e2
--- /dev/null
+++ b/src/test/ui/issues/issue-58006.stderr
@@ -0,0 +1,9 @@
+error[E0533]: expected unit struct/variant or constant, found tuple variant `<Self>::A`
+  --> $DIR/issue-58006.rs:9:13
+   |
+LL |             Self::A => (),
+   |             ^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0533`.
diff --git a/src/test/ui/issues/issue-5844.rs b/src/test/ui/issues/issue-5844.rs
new file mode 100644
index 0000000..b855e87
--- /dev/null
+++ b/src/test/ui/issues/issue-5844.rs
@@ -0,0 +1,7 @@
+//aux-build:issue-5844-aux.rs
+
+extern crate issue_5844_aux;
+
+fn main () {
+    issue_5844_aux::rand(); //~ ERROR: requires unsafe
+}
diff --git a/src/test/ui/issues/issue-5844.stderr b/src/test/ui/issues/issue-5844.stderr
new file mode 100644
index 0000000..ed5a3dc
--- /dev/null
+++ b/src/test/ui/issues/issue-5844.stderr
@@ -0,0 +1,11 @@
+error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
+  --> $DIR/issue-5844.rs:6:5
+   |
+LL |     issue_5844_aux::rand();
+   |     ^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/issues/issue-58712.rs b/src/test/ui/issues/issue-58712.rs
new file mode 100644
index 0000000..577709c
--- /dev/null
+++ b/src/test/ui/issues/issue-58712.rs
@@ -0,0 +1,15 @@
+struct AddrVec<H, A> {
+    h: H,
+    a: A,
+}
+
+impl<H> AddrVec<H, DeviceId> {
+    //~^ ERROR cannot find type `DeviceId` in this scope
+    pub fn device(&self) -> DeviceId {
+    //~^ ERROR cannot find type `DeviceId` in this scope
+        self.tail()
+    }
+}
+
+fn main() {}
+
diff --git a/src/test/ui/issues/issue-58712.stderr b/src/test/ui/issues/issue-58712.stderr
new file mode 100644
index 0000000..6164ad7
--- /dev/null
+++ b/src/test/ui/issues/issue-58712.stderr
@@ -0,0 +1,15 @@
+error[E0412]: cannot find type `DeviceId` in this scope
+  --> $DIR/issue-58712.rs:6:20
+   |
+LL | impl<H> AddrVec<H, DeviceId> {
+   |                    ^^^^^^^^ not found in this scope
+
+error[E0412]: cannot find type `DeviceId` in this scope
+  --> $DIR/issue-58712.rs:8:29
+   |
+LL |     pub fn device(&self) -> DeviceId {
+   |                             ^^^^^^^^ not found in this scope
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/src/test/ui/issues/issue-58734.rs b/src/test/ui/issues/issue-58734.rs
new file mode 100644
index 0000000..bbdfebe
--- /dev/null
+++ b/src/test/ui/issues/issue-58734.rs
@@ -0,0 +1,22 @@
+trait Trait {
+    fn exists(self) -> ();
+
+    fn not_object_safe() -> Self;
+}
+
+impl Trait for () {
+    fn exists(self) -> () {
+    }
+
+    fn not_object_safe() -> Self {
+        ()
+    }
+}
+
+fn main() {
+    // object-safe or not, this call is OK
+    Trait::exists(());
+    // no object safety error
+    Trait::nonexistent(());
+    //~^ ERROR no function or associated item named `nonexistent` found for type `dyn Trait`
+}
diff --git a/src/test/ui/issues/issue-58734.stderr b/src/test/ui/issues/issue-58734.stderr
new file mode 100644
index 0000000..07f2a04
--- /dev/null
+++ b/src/test/ui/issues/issue-58734.stderr
@@ -0,0 +1,9 @@
+error[E0599]: no function or associated item named `nonexistent` found for type `dyn Trait` in the current scope
+  --> $DIR/issue-58734.rs:20:12
+   |
+LL |     Trait::nonexistent(());
+   |            ^^^^^^^^^^^ function or associated item not found in `dyn Trait`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/issues/issue-5883.rs b/src/test/ui/issues/issue-5883.rs
new file mode 100644
index 0000000..b4a73ba
--- /dev/null
+++ b/src/test/ui/issues/issue-5883.rs
@@ -0,0 +1,13 @@
+trait A {}
+
+struct Struct {
+    r: A+'static
+}
+
+fn new_struct(r: A+'static)
+    -> Struct { //~^ ERROR the size for values of type
+    //~^ ERROR the size for values of type
+    Struct { r: r }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-5883.stderr b/src/test/ui/issues/issue-5883.stderr
new file mode 100644
index 0000000..7753881
--- /dev/null
+++ b/src/test/ui/issues/issue-5883.stderr
@@ -0,0 +1,25 @@
+error[E0277]: the size for values of type `(dyn A + 'static)` cannot be known at compilation time
+  --> $DIR/issue-5883.rs:7:15
+   |
+LL | fn new_struct(r: A+'static)
+   |               ^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `(dyn A + 'static)`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: all local variables must have a statically known size
+   = help: unsized locals are gated as an unstable feature
+
+error[E0277]: the size for values of type `(dyn A + 'static)` cannot be known at compilation time
+  --> $DIR/issue-5883.rs:8:8
+   |
+LL |     -> Struct {
+   |        ^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: within `Struct`, the trait `std::marker::Sized` is not implemented for `(dyn A + 'static)`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: required because it appears within the type `Struct`
+   = note: the return type of a function must have a statically known size
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-5884.rs b/src/test/ui/issues/issue-5884.rs
new file mode 100644
index 0000000..ad7067b
--- /dev/null
+++ b/src/test/ui/issues/issue-5884.rs
@@ -0,0 +1,20 @@
+// compile-pass
+#![allow(dead_code)]
+// pretty-expanded FIXME #23616
+
+#![feature(box_syntax)]
+
+pub struct Foo {
+    a: isize,
+}
+
+struct Bar<'a> {
+    a: Box<Option<isize>>,
+    b: &'a Foo,
+}
+
+fn check(a: Box<Foo>) {
+    let _ic = Bar{ b: &*a, a: box None };
+}
+
+pub fn main(){}
diff --git a/src/test/ui/issues/issue-58856-1.rs b/src/test/ui/issues/issue-58856-1.rs
new file mode 100644
index 0000000..db3984c
--- /dev/null
+++ b/src/test/ui/issues/issue-58856-1.rs
@@ -0,0 +1,6 @@
+impl A {
+    fn b(self>
+    //~^ ERROR expected one of `)`, `,`, or `:`, found `>`
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-58856-1.stderr b/src/test/ui/issues/issue-58856-1.stderr
new file mode 100644
index 0000000..20cdf55
--- /dev/null
+++ b/src/test/ui/issues/issue-58856-1.stderr
@@ -0,0 +1,11 @@
+error: expected one of `)`, `,`, or `:`, found `>`
+  --> $DIR/issue-58856-1.rs:2:14
+   |
+LL |     fn b(self>
+   |         -    ^
+   |         |    |
+   |         |    help: `)` may belong here
+   |         unclosed delimiter
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-58856-2.rs b/src/test/ui/issues/issue-58856-2.rs
new file mode 100644
index 0000000..acc38e4
--- /dev/null
+++ b/src/test/ui/issues/issue-58856-2.rs
@@ -0,0 +1,14 @@
+struct Empty;
+
+trait Howness {}
+
+impl Howness for () {
+    fn how_are_you(&self -> Empty {
+    //~^ ERROR expected one of `)` or `,`, found `->`
+    //~| ERROR method `how_are_you` is not a member of trait `Howness`
+        Empty
+    }
+}
+//~^ ERROR expected one of `async`, `const`, `crate`, `default`, `existential`, `extern`, `fn`,
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-58856-2.stderr b/src/test/ui/issues/issue-58856-2.stderr
new file mode 100644
index 0000000..b760fd6
--- /dev/null
+++ b/src/test/ui/issues/issue-58856-2.stderr
@@ -0,0 +1,30 @@
+error: expected one of `)` or `,`, found `->`
+  --> $DIR/issue-58856-2.rs:6:26
+   |
+LL |     fn how_are_you(&self -> Empty {
+   |                   -     -^^
+   |                   |     |
+   |                   |     help: `)` may belong here
+   |                   unclosed delimiter
+
+error: expected one of `async`, `const`, `crate`, `default`, `existential`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found `)`
+  --> $DIR/issue-58856-2.rs:11:1
+   |
+LL |     }
+   |      - expected one of 11 possible tokens here
+LL | }
+   | ^ unexpected token
+
+error[E0407]: method `how_are_you` is not a member of trait `Howness`
+  --> $DIR/issue-58856-2.rs:6:5
+   |
+LL | /     fn how_are_you(&self -> Empty {
+LL | |
+LL | |
+LL | |         Empty
+LL | |     }
+   | |_____^ not a member of trait `Howness`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0407`.
diff --git a/src/test/ui/issues/issue-58857.rs b/src/test/ui/issues/issue-58857.rs
new file mode 100644
index 0000000..392e4ea
--- /dev/null
+++ b/src/test/ui/issues/issue-58857.rs
@@ -0,0 +1,7 @@
+struct Conj<A> {a : A}
+trait Valid {}
+
+impl<A: !Valid> Conj<A>{}
+//~^ ERROR negative trait bounds are not supported
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-58857.stderr b/src/test/ui/issues/issue-58857.stderr
new file mode 100644
index 0000000..56e8721
--- /dev/null
+++ b/src/test/ui/issues/issue-58857.stderr
@@ -0,0 +1,9 @@
+error: negative trait bounds are not supported
+  --> $DIR/issue-58857.rs:4:7
+   |
+LL | impl<A: !Valid> Conj<A>{}
+   |       ^^^^^^^^ negative trait bounds are not supported
+   = help: remove the trait bound
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-58885.rs b/src/test/ui/issues/issue-58885.rs
new file mode 100644
index 0000000..5598991
--- /dev/null
+++ b/src/test/ui/issues/issue-58885.rs
@@ -0,0 +1,21 @@
+// compile-pass
+// edition:2018
+
+#![feature(async_await, await_macro, futures_api)]
+
+struct Xyz {
+    a: u64,
+}
+
+trait Foo {}
+
+impl Xyz {
+    async fn do_sth<'a>(
+        &'a self, foo: &'a dyn Foo
+    ) -> bool
+    {
+        true
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-5900.rs b/src/test/ui/issues/issue-5900.rs
new file mode 100644
index 0000000..5ac7acc
--- /dev/null
+++ b/src/test/ui/issues/issue-5900.rs
@@ -0,0 +1,15 @@
+// compile-pass
+#![allow(dead_code)]
+// pretty-expanded FIXME #23616
+
+pub mod foo {
+    use super::Bar;
+
+    pub struct FooStruct { bar : Bar }
+}
+
+pub enum Bar {
+    Bar0 = 0 as isize
+}
+
+pub fn main() {}
diff --git a/src/test/ui/issues/issue-59001.rs b/src/test/ui/issues/issue-59001.rs
new file mode 100644
index 0000000..a310653
--- /dev/null
+++ b/src/test/ui/issues/issue-59001.rs
@@ -0,0 +1,17 @@
+// compile-pass
+// edition:2018
+
+#![feature(async_await, await_macro, futures_api)]
+
+use std::future::Future;
+
+#[allow(unused)]
+async fn enter<'a, F, R>(mut callback: F)
+where
+    F: FnMut(&'a mut i32) -> R,
+    R: Future<Output = ()> + 'a,
+{
+    unimplemented!()
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-59029-1.rs b/src/test/ui/issues/issue-59029-1.rs
new file mode 100644
index 0000000..e98a4d0
--- /dev/null
+++ b/src/test/ui/issues/issue-59029-1.rs
@@ -0,0 +1,8 @@
+#![feature(trait_alias)]
+
+trait Svc<Req> { type Res; }
+
+trait MkSvc<Target, Req> = Svc<Target> where Self::Res: Svc<Req>;
+//~^ ERROR associated type `Res` not found for `Self`
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-59029-1.stderr b/src/test/ui/issues/issue-59029-1.stderr
new file mode 100644
index 0000000..ed1d98c
--- /dev/null
+++ b/src/test/ui/issues/issue-59029-1.stderr
@@ -0,0 +1,9 @@
+error[E0220]: associated type `Res` not found for `Self`
+  --> $DIR/issue-59029-1.rs:5:46
+   |
+LL | trait MkSvc<Target, Req> = Svc<Target> where Self::Res: Svc<Req>;
+   |                                              ^^^^^^^^^ associated type `Res` not found
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0220`.
diff --git a/src/test/ui/issues/issue-59029-2.rs b/src/test/ui/issues/issue-59029-2.rs
new file mode 100644
index 0000000..2bdb128
--- /dev/null
+++ b/src/test/ui/issues/issue-59029-2.rs
@@ -0,0 +1,8 @@
+// run-pass
+#![feature(trait_alias)]
+
+trait Svc<Req> { type Res; }
+
+trait MkSvc<Target, Req> = Svc<Target> where <Self as Svc<Target>>::Res: Svc<Req>;
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-5927.rs b/src/test/ui/issues/issue-5927.rs
new file mode 100644
index 0000000..847936c
--- /dev/null
+++ b/src/test/ui/issues/issue-5927.rs
@@ -0,0 +1,7 @@
+fn main() {
+    let z = match 3 {
+        x(1) => x(1) //~ ERROR cannot find tuple struct/variant `x` in this scope
+        //~^ ERROR cannot find function `x` in this scope
+    };
+    assert!(z == 3);
+}
diff --git a/src/test/ui/issues/issue-5927.stderr b/src/test/ui/issues/issue-5927.stderr
new file mode 100644
index 0000000..6b0a2b7
--- /dev/null
+++ b/src/test/ui/issues/issue-5927.stderr
@@ -0,0 +1,16 @@
+error[E0531]: cannot find tuple struct/variant `x` in this scope
+  --> $DIR/issue-5927.rs:3:9
+   |
+LL |         x(1) => x(1)
+   |         ^ not found in this scope
+
+error[E0425]: cannot find function `x` in this scope
+  --> $DIR/issue-5927.rs:3:17
+   |
+LL |         x(1) => x(1)
+   |                 ^ not found in this scope
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0425, E0531.
+For more information about an error, try `rustc --explain E0425`.
diff --git a/src/test/ui/issues/issue-5950.rs b/src/test/ui/issues/issue-5950.rs
new file mode 100644
index 0000000..19e0cfc
--- /dev/null
+++ b/src/test/ui/issues/issue-5950.rs
@@ -0,0 +1,9 @@
+// compile-pass
+
+// pretty-expanded FIXME #23616
+
+pub use local as local_alias;
+
+pub mod local { }
+
+pub fn main() {}
diff --git a/src/test/ui/issues/issue-5997-enum.rs b/src/test/ui/issues/issue-5997-enum.rs
new file mode 100644
index 0000000..3ff4e03
--- /dev/null
+++ b/src/test/ui/issues/issue-5997-enum.rs
@@ -0,0 +1,10 @@
+fn f<Z>() -> bool {
+    enum E { V(Z) }
+    //~^ ERROR can't use generic parameters from outer function
+    true
+}
+
+fn main() {
+    let b = f::<isize>();
+    assert!(b);
+}
diff --git a/src/test/ui/issues/issue-5997-enum.stderr b/src/test/ui/issues/issue-5997-enum.stderr
new file mode 100644
index 0000000..5c77814
--- /dev/null
+++ b/src/test/ui/issues/issue-5997-enum.stderr
@@ -0,0 +1,13 @@
+error[E0401]: can't use generic parameters from outer function
+  --> $DIR/issue-5997-enum.rs:2:16
+   |
+LL | fn f<Z>() -> bool {
+   |    - - type variable from outer function
+   |    |
+   |    try adding a local generic parameter in this method instead
+LL |     enum E { V(Z) }
+   |                ^ use of generic parameter from outer function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0401`.
diff --git a/src/test/ui/issues/issue-5997-struct.rs b/src/test/ui/issues/issue-5997-struct.rs
new file mode 100644
index 0000000..6cf510b
--- /dev/null
+++ b/src/test/ui/issues/issue-5997-struct.rs
@@ -0,0 +1,10 @@
+fn f<T>() -> bool {
+    struct S(T); //~ ERROR can't use generic parameters from outer function
+
+    true
+}
+
+fn main() {
+    let b = f::<isize>();
+    assert!(b);
+}
diff --git a/src/test/ui/issues/issue-5997-struct.stderr b/src/test/ui/issues/issue-5997-struct.stderr
new file mode 100644
index 0000000..cb1b514
--- /dev/null
+++ b/src/test/ui/issues/issue-5997-struct.stderr
@@ -0,0 +1,13 @@
+error[E0401]: can't use generic parameters from outer function
+  --> $DIR/issue-5997-struct.rs:2:14
+   |
+LL | fn f<T>() -> bool {
+   |    - - type variable from outer function
+   |    |
+   |    try adding a local generic parameter in this method instead
+LL |     struct S(T);
+   |              ^ use of generic parameter from outer function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0401`.
diff --git a/src/test/ui/issues/issue-60283.rs b/src/test/ui/issues/issue-60283.rs
new file mode 100644
index 0000000..e5a9caa
--- /dev/null
+++ b/src/test/ui/issues/issue-60283.rs
@@ -0,0 +1,17 @@
+pub trait Trait<'a> {
+    type Item;
+}
+
+impl<'a> Trait<'a> for () {
+    type Item = ();
+}
+
+pub fn foo<T, F>(_: T, _: F)
+where T: for<'a> Trait<'a>,
+      F: for<'a> FnMut(<T as Trait<'a>>::Item) {}
+
+fn main() {
+    foo((), drop)
+    //~^ ERROR type mismatch in function arguments
+    //~| ERROR type mismatch resolving
+}
diff --git a/src/test/ui/issues/issue-60283.stderr b/src/test/ui/issues/issue-60283.stderr
new file mode 100644
index 0000000..54cc2f3
--- /dev/null
+++ b/src/test/ui/issues/issue-60283.stderr
@@ -0,0 +1,35 @@
+error[E0631]: type mismatch in function arguments
+  --> $DIR/issue-60283.rs:14:5
+   |
+LL |     foo((), drop)
+   |     ^^^
+   |     |
+   |     expected signature of `for<'a> fn(<() as Trait<'a>>::Item) -> _`
+   |     found signature of `fn(_) -> _`
+   |
+note: required by `foo`
+  --> $DIR/issue-60283.rs:9:1
+   |
+LL | / pub fn foo<T, F>(_: T, _: F)
+LL | | where T: for<'a> Trait<'a>,
+LL | |       F: for<'a> FnMut(<T as Trait<'a>>::Item) {}
+   | |_________________________________________________^
+
+error[E0271]: type mismatch resolving `for<'a> <fn(_) {std::mem::drop::<_>} as std::ops::FnOnce<(<() as Trait<'a>>::Item,)>>::Output == ()`
+  --> $DIR/issue-60283.rs:14:5
+   |
+LL |     foo((), drop)
+   |     ^^^ expected bound lifetime parameter 'a, found concrete lifetime
+   |
+note: required by `foo`
+  --> $DIR/issue-60283.rs:9:1
+   |
+LL | / pub fn foo<T, F>(_: T, _: F)
+LL | | where T: for<'a> Trait<'a>,
+LL | |       F: for<'a> FnMut(<T as Trait<'a>>::Item) {}
+   | |_________________________________________________^
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0271, E0631.
+For more information about an error, try `rustc --explain E0271`.
diff --git a/src/test/ui/issues/issue-6341.rs b/src/test/ui/issues/issue-6341.rs
new file mode 100644
index 0000000..2b23ccd
--- /dev/null
+++ b/src/test/ui/issues/issue-6341.rs
@@ -0,0 +1,11 @@
+// compile-pass
+// pretty-expanded FIXME #23616
+
+#[derive(PartialEq)]
+struct A { x: usize }
+
+impl Drop for A {
+    fn drop(&mut self) {}
+}
+
+pub fn main() {}
diff --git a/src/test/ui/issues/issue-6458-2.rs b/src/test/ui/issues/issue-6458-2.rs
new file mode 100644
index 0000000..b18cae3
--- /dev/null
+++ b/src/test/ui/issues/issue-6458-2.rs
@@ -0,0 +1,5 @@
+fn main() {
+    // Unconstrained type:
+    format!("{:?}", None);
+    //~^ ERROR type annotations needed [E0282]
+}
diff --git a/src/test/ui/issues/issue-6458-2.stderr b/src/test/ui/issues/issue-6458-2.stderr
new file mode 100644
index 0000000..b5da2bf
--- /dev/null
+++ b/src/test/ui/issues/issue-6458-2.stderr
@@ -0,0 +1,9 @@
+error[E0282]: type annotations needed
+  --> $DIR/issue-6458-2.rs:3:21
+   |
+LL |     format!("{:?}", None);
+   |                     ^^^^ cannot infer type for `T`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/issues/issue-6458-3.rs b/src/test/ui/issues/issue-6458-3.rs
new file mode 100644
index 0000000..d4f8886
--- /dev/null
+++ b/src/test/ui/issues/issue-6458-3.rs
@@ -0,0 +1,6 @@
+use std::mem;
+
+fn main() {
+    mem::transmute(0);
+    //~^ ERROR type annotations needed [E0282]
+}
diff --git a/src/test/ui/issues/issue-6458-3.stderr b/src/test/ui/issues/issue-6458-3.stderr
new file mode 100644
index 0000000..784497c
--- /dev/null
+++ b/src/test/ui/issues/issue-6458-3.stderr
@@ -0,0 +1,9 @@
+error[E0282]: type annotations needed
+  --> $DIR/issue-6458-3.rs:4:5
+   |
+LL |     mem::transmute(0);
+   |     ^^^^^^^^^^^^^^ cannot infer type for `U`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/issues/issue-6458-4.rs b/src/test/ui/issues/issue-6458-4.rs
new file mode 100644
index 0000000..054a5c1
--- /dev/null
+++ b/src/test/ui/issues/issue-6458-4.rs
@@ -0,0 +1,7 @@
+fn foo(b: bool) -> Result<bool,String> { //~ ERROR mismatched types
+    Err("bar".to_string());
+}
+
+fn main() {
+    foo(false);
+}
diff --git a/src/test/ui/issues/issue-6458-4.stderr b/src/test/ui/issues/issue-6458-4.stderr
new file mode 100644
index 0000000..90b493e
--- /dev/null
+++ b/src/test/ui/issues/issue-6458-4.stderr
@@ -0,0 +1,16 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-6458-4.rs:1:20
+   |
+LL | fn foo(b: bool) -> Result<bool,String> {
+   |    ---             ^^^^^^^^^^^^^^^^^^^ expected enum `std::result::Result`, found ()
+   |    |
+   |    this function's body doesn't return
+LL |     Err("bar".to_string());
+   |                           - help: consider removing this semicolon
+   |
+   = note: expected type `std::result::Result<bool, std::string::String>`
+              found type `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-6458.rs b/src/test/ui/issues/issue-6458.rs
new file mode 100644
index 0000000..16718e9
--- /dev/null
+++ b/src/test/ui/issues/issue-6458.rs
@@ -0,0 +1,14 @@
+use std::marker;
+
+pub struct TypeWithState<State>(marker::PhantomData<State>);
+pub struct MyState;
+
+pub fn foo<State>(_: TypeWithState<State>) {}
+
+pub fn bar() {
+   foo(TypeWithState(marker::PhantomData));
+   //~^ ERROR type annotations needed [E0282]
+}
+
+fn main() {
+}
diff --git a/src/test/ui/issues/issue-6458.stderr b/src/test/ui/issues/issue-6458.stderr
new file mode 100644
index 0000000..d59d872
--- /dev/null
+++ b/src/test/ui/issues/issue-6458.stderr
@@ -0,0 +1,9 @@
+error[E0282]: type annotations needed
+  --> $DIR/issue-6458.rs:9:4
+   |
+LL |    foo(TypeWithState(marker::PhantomData));
+   |    ^^^ cannot infer type for `State`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/issues/issue-6470.rs b/src/test/ui/issues/issue-6470.rs
new file mode 100644
index 0000000..49a313f
--- /dev/null
+++ b/src/test/ui/issues/issue-6470.rs
@@ -0,0 +1,18 @@
+// compile-pass
+#![allow(dead_code)]
+#![allow(improper_ctypes)]
+
+// pretty-expanded FIXME #23616
+#![allow(non_snake_case)]
+
+pub mod Bar {
+    pub struct Foo {
+        v: isize,
+    }
+
+    extern {
+        pub fn foo(v: *const Foo) -> Foo;
+    }
+}
+
+pub fn main() { }
diff --git a/src/test/ui/issues/issue-6557.rs b/src/test/ui/issues/issue-6557.rs
new file mode 100644
index 0000000..aa091ca
--- /dev/null
+++ b/src/test/ui/issues/issue-6557.rs
@@ -0,0 +1,10 @@
+// compile-pass
+#![allow(dead_code)]
+// pretty-expanded FIXME #23616
+
+#![feature(box_patterns)]
+#![feature(box_syntax)]
+
+fn foo(box (_x, _y): Box<(isize, isize)>) {}
+
+pub fn main() {}
diff --git a/src/test/ui/issues/issue-6596-1.rs b/src/test/ui/issues/issue-6596-1.rs
new file mode 100644
index 0000000..5da5445
--- /dev/null
+++ b/src/test/ui/issues/issue-6596-1.rs
@@ -0,0 +1,10 @@
+macro_rules! e {
+    ($inp:ident) => (
+        $nonexistent
+        //~^ ERROR unknown macro variable `nonexistent`
+    );
+}
+
+fn main() {
+    e!(foo);
+}
diff --git a/src/test/ui/issues/issue-6596-1.stderr b/src/test/ui/issues/issue-6596-1.stderr
new file mode 100644
index 0000000..2a4ece2
--- /dev/null
+++ b/src/test/ui/issues/issue-6596-1.stderr
@@ -0,0 +1,11 @@
+error: unknown macro variable `nonexistent`
+  --> $DIR/issue-6596-1.rs:3:9
+   |
+LL |         $nonexistent
+   |         ^^^^^^^^^^^^ unknown macro variable
+...
+LL |     e!(foo);
+   |     -------- in this macro invocation
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-6596-2.rs b/src/test/ui/issues/issue-6596-2.rs
new file mode 100644
index 0000000..b19700e
--- /dev/null
+++ b/src/test/ui/issues/issue-6596-2.rs
@@ -0,0 +1,13 @@
+#![feature(macro_rules)]
+
+macro_rules! g {
+    ($inp:ident) => (
+        { $inp $nonexistent }
+        //~^ ERROR unknown macro variable `nonexistent`
+    );
+}
+
+fn main() {
+    let foo = 0;
+    g!(foo);
+}
diff --git a/src/test/ui/issues/issue-6596-2.stderr b/src/test/ui/issues/issue-6596-2.stderr
new file mode 100644
index 0000000..20fbe0f
--- /dev/null
+++ b/src/test/ui/issues/issue-6596-2.stderr
@@ -0,0 +1,11 @@
+error: unknown macro variable `nonexistent`
+  --> $DIR/issue-6596-2.rs:5:16
+   |
+LL |         { $inp $nonexistent }
+   |                ^^^^^^^^^^^^ unknown macro variable
+...
+LL |     g!(foo);
+   |     -------- in this macro invocation
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-6642.rs b/src/test/ui/issues/issue-6642.rs
new file mode 100644
index 0000000..f80f6ff
--- /dev/null
+++ b/src/test/ui/issues/issue-6642.rs
@@ -0,0 +1,9 @@
+struct A;
+impl A {
+    fn m(&self) {
+        fn x() {
+            self.m() //~ ERROR can't capture dynamic environment in a fn item
+        }
+    }
+}
+fn main() {}
diff --git a/src/test/ui/issues/issue-6642.stderr b/src/test/ui/issues/issue-6642.stderr
new file mode 100644
index 0000000..6668108
--- /dev/null
+++ b/src/test/ui/issues/issue-6642.stderr
@@ -0,0 +1,11 @@
+error[E0434]: can't capture dynamic environment in a fn item
+  --> $DIR/issue-6642.rs:5:13
+   |
+LL |             self.m()
+   |             ^^^^
+   |
+   = help: use the `|| { ... }` closure form instead
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0434`.
diff --git a/src/test/ui/issues/issue-6738.rs b/src/test/ui/issues/issue-6738.rs
new file mode 100644
index 0000000..a2f8dfe
--- /dev/null
+++ b/src/test/ui/issues/issue-6738.rs
@@ -0,0 +1,10 @@
+struct Foo<T> {
+    x: T,
+}
+impl<T> Foo<T> {
+    fn add(&mut self, v: Foo<T>){
+        self.x += v.x;
+        //~^ ERROR: binary assignment operation `+=` cannot be applied
+    }
+}
+fn main() {}
diff --git a/src/test/ui/issues/issue-6738.stderr b/src/test/ui/issues/issue-6738.stderr
new file mode 100644
index 0000000..82b670b
--- /dev/null
+++ b/src/test/ui/issues/issue-6738.stderr
@@ -0,0 +1,13 @@
+error[E0368]: binary assignment operation `+=` cannot be applied to type `T`
+  --> $DIR/issue-6738.rs:6:9
+   |
+LL |         self.x += v.x;
+   |         ------^^^^^^^
+   |         |
+   |         cannot use `+=` on type `T`
+   |
+   = note: `T` might need a bound for `std::ops::AddAssign`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0368`.
diff --git a/src/test/ui/issues/issue-6801.nll.stderr b/src/test/ui/issues/issue-6801.nll.stderr
new file mode 100644
index 0000000..dbb8e65
--- /dev/null
+++ b/src/test/ui/issues/issue-6801.nll.stderr
@@ -0,0 +1,16 @@
+error[E0505]: cannot move out of `x` because it is borrowed
+  --> $DIR/issue-6801.rs:19:13
+   |
+LL |       let sq =  || { *x * *x };
+   |                 --    - borrow occurs due to use in closure
+   |                 |
+   |                 borrow of `x` occurs here
+LL | 
+LL |       twice(x);
+   |             ^ move out of `x` occurs here
+LL |       invoke(sq);
+   |              -- borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0505`.
diff --git a/src/test/ui/issues/issue-6801.rs b/src/test/ui/issues/issue-6801.rs
new file mode 100644
index 0000000..694d86f
--- /dev/null
+++ b/src/test/ui/issues/issue-6801.rs
@@ -0,0 +1,21 @@
+// Creating a stack closure which references a box and then
+// transferring ownership of the box before invoking the stack
+// closure results in a crash.
+
+#![feature(box_syntax)]
+
+fn twice(x: Box<usize>) -> usize {
+     *x * 2
+}
+
+fn invoke<F>(f: F) where F: FnOnce() -> usize {
+     f();
+}
+
+fn main() {
+      let x  : Box<usize>  = box 9;
+      let sq =  || { *x * *x };
+
+      twice(x); //~ ERROR: cannot move out of
+      invoke(sq);
+}
diff --git a/src/test/ui/issues/issue-6801.stderr b/src/test/ui/issues/issue-6801.stderr
new file mode 100644
index 0000000..482e487
--- /dev/null
+++ b/src/test/ui/issues/issue-6801.stderr
@@ -0,0 +1,12 @@
+error[E0505]: cannot move out of `x` because it is borrowed
+  --> $DIR/issue-6801.rs:19:13
+   |
+LL |       let sq =  || { *x * *x };
+   |                 -- borrow of `x` occurs here
+LL | 
+LL |       twice(x);
+   |             ^ move out of `x` occurs here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0505`.
diff --git a/src/test/ui/issues/issue-6804.rs b/src/test/ui/issues/issue-6804.rs
new file mode 100644
index 0000000..da73e2b
--- /dev/null
+++ b/src/test/ui/issues/issue-6804.rs
@@ -0,0 +1,21 @@
+// Matching against NaN should result in a warning
+
+#![allow(unused)]
+#![deny(illegal_floating_point_literal_pattern)]
+
+use std::f64::NAN;
+
+fn main() {
+    let x = NAN;
+    match x {
+        NAN => {}, //~ ERROR floating-point types cannot be used
+        //~^ WARN this was previously accepted by the compiler but is being phased out
+        _ => {},
+    };
+
+    match [x, 1.0] {
+        [NAN, _] => {}, //~ ERROR floating-point types cannot be used
+        //~^ WARN this was previously accepted by the compiler but is being phased out
+        _ => {},
+    };
+}
diff --git a/src/test/ui/issues/issue-6804.stderr b/src/test/ui/issues/issue-6804.stderr
new file mode 100644
index 0000000..1c251ed
--- /dev/null
+++ b/src/test/ui/issues/issue-6804.stderr
@@ -0,0 +1,25 @@
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-6804.rs:11:9
+   |
+LL |         NAN => {},
+   |         ^^^
+   |
+note: lint level defined here
+  --> $DIR/issue-6804.rs:4:9
+   |
+LL | #![deny(illegal_floating_point_literal_pattern)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-6804.rs:17:10
+   |
+LL |         [NAN, _] => {},
+   |          ^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/issues/issue-6898.rs b/src/test/ui/issues/issue-6898.rs
new file mode 100644
index 0000000..608c0c8
--- /dev/null
+++ b/src/test/ui/issues/issue-6898.rs
@@ -0,0 +1,33 @@
+// compile-pass
+// pretty-expanded FIXME #23616
+
+use std::mem;
+
+/// Returns the size of a type
+pub fn size_of<T>() -> usize {
+    TypeInfo::size_of(None::<T>)
+}
+
+/// Returns the size of the type that `val` points to
+pub fn size_of_val<T>(val: &T) -> usize {
+    val.size_of_val()
+}
+
+pub trait TypeInfo: Sized {
+    fn size_of(_lame_type_hint: Option<Self>) -> usize;
+    fn size_of_val(&self) -> usize;
+}
+
+impl<T> TypeInfo for T {
+    /// The size of the type in bytes.
+    fn size_of(_lame_type_hint: Option<T>) -> usize {
+        mem::size_of::<T>()
+    }
+
+    /// Returns the size of the type of `self` in bytes.
+    fn size_of_val(&self) -> usize {
+        TypeInfo::size_of(None::<T>)
+    }
+}
+
+pub fn main() {}
diff --git a/src/test/ui/issues/issue-6936.rs b/src/test/ui/issues/issue-6936.rs
new file mode 100644
index 0000000..26531bb
--- /dev/null
+++ b/src/test/ui/issues/issue-6936.rs
@@ -0,0 +1,34 @@
+struct T;
+
+mod t1 {
+    type Foo = ::T;
+    mod Foo {} //~ ERROR the name `Foo` is defined multiple times
+}
+
+mod t2 {
+    type Foo = ::T;
+    struct Foo; //~ ERROR the name `Foo` is defined multiple times
+}
+
+mod t3 {
+    type Foo = ::T;
+    enum Foo {} //~ ERROR the name `Foo` is defined multiple times
+}
+
+mod t4 {
+    type Foo = ::T;
+    fn Foo() {} // ok
+}
+
+mod t5 {
+    type Bar<T> = T;
+    mod Bar {} //~ ERROR the name `Bar` is defined multiple times
+}
+
+mod t6 {
+    type Foo = ::T;
+    impl Foo {} // ok
+}
+
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-6936.stderr b/src/test/ui/issues/issue-6936.stderr
new file mode 100644
index 0000000..9292d60
--- /dev/null
+++ b/src/test/ui/issues/issue-6936.stderr
@@ -0,0 +1,43 @@
+error[E0428]: the name `Foo` is defined multiple times
+  --> $DIR/issue-6936.rs:5:5
+   |
+LL |     type Foo = ::T;
+   |     --------------- previous definition of the type `Foo` here
+LL |     mod Foo {}
+   |     ^^^^^^^ `Foo` redefined here
+   |
+   = note: `Foo` must be defined only once in the type namespace of this module
+
+error[E0428]: the name `Foo` is defined multiple times
+  --> $DIR/issue-6936.rs:10:5
+   |
+LL |     type Foo = ::T;
+   |     --------------- previous definition of the type `Foo` here
+LL |     struct Foo;
+   |     ^^^^^^^^^^^ `Foo` redefined here
+   |
+   = note: `Foo` must be defined only once in the type namespace of this module
+
+error[E0428]: the name `Foo` is defined multiple times
+  --> $DIR/issue-6936.rs:15:5
+   |
+LL |     type Foo = ::T;
+   |     --------------- previous definition of the type `Foo` here
+LL |     enum Foo {}
+   |     ^^^^^^^^ `Foo` redefined here
+   |
+   = note: `Foo` must be defined only once in the type namespace of this module
+
+error[E0428]: the name `Bar` is defined multiple times
+  --> $DIR/issue-6936.rs:25:5
+   |
+LL |     type Bar<T> = T;
+   |     ---------------- previous definition of the type `Bar` here
+LL |     mod Bar {}
+   |     ^^^^^^^ `Bar` redefined here
+   |
+   = note: `Bar` must be defined only once in the type namespace of this module
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0428`.
diff --git a/src/test/ui/issues/issue-6991.rs b/src/test/ui/issues/issue-6991.rs
new file mode 100644
index 0000000..e835ede
--- /dev/null
+++ b/src/test/ui/issues/issue-6991.rs
@@ -0,0 +1,8 @@
+// compile-pass
+#![allow(dead_code)]
+#![allow(non_upper_case_globals)]
+
+static x: &'static usize = &1;
+static y: usize = *x;
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-7013.rs b/src/test/ui/issues/issue-7013.rs
new file mode 100644
index 0000000..ee68aa8
--- /dev/null
+++ b/src/test/ui/issues/issue-7013.rs
@@ -0,0 +1,28 @@
+#![feature(box_syntax)]
+
+use std::cell::RefCell;
+use std::rc::Rc;
+
+trait Foo {
+    fn set(&mut self, v: Rc<RefCell<A>>);
+}
+
+struct B {
+    v: Option<Rc<RefCell<A>>>
+}
+
+impl Foo for B {
+    fn set(&mut self, v: Rc<RefCell<A>>)
+    {
+        self.v = Some(v);
+    }
+}
+
+struct A {
+    v: Box<Foo + Send>,
+}
+
+fn main() {
+    let a = A {v: box B{v: None} as Box<Foo+Send>};
+    //~^ ERROR `std::rc::Rc<std::cell::RefCell<A>>` cannot be sent between threads safely
+}
diff --git a/src/test/ui/issues/issue-7013.stderr b/src/test/ui/issues/issue-7013.stderr
new file mode 100644
index 0000000..22185c7
--- /dev/null
+++ b/src/test/ui/issues/issue-7013.stderr
@@ -0,0 +1,14 @@
+error[E0277]: `std::rc::Rc<std::cell::RefCell<A>>` cannot be sent between threads safely
+  --> $DIR/issue-7013.rs:26:19
+   |
+LL |     let a = A {v: box B{v: None} as Box<Foo+Send>};
+   |                   ^^^^^^^^^^^^^^ `std::rc::Rc<std::cell::RefCell<A>>` cannot be sent between threads safely
+   |
+   = help: within `B`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<std::cell::RefCell<A>>`
+   = note: required because it appears within the type `std::option::Option<std::rc::Rc<std::cell::RefCell<A>>>`
+   = note: required because it appears within the type `B`
+   = note: required for the cast to the object type `dyn Foo + std::marker::Send`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-7044.rs b/src/test/ui/issues/issue-7044.rs
new file mode 100644
index 0000000..a6e22bc
--- /dev/null
+++ b/src/test/ui/issues/issue-7044.rs
@@ -0,0 +1,4 @@
+static X: isize = 0;
+struct X; //~ ERROR the name `X` is defined multiple times
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-7044.stderr b/src/test/ui/issues/issue-7044.stderr
new file mode 100644
index 0000000..2ad67ec
--- /dev/null
+++ b/src/test/ui/issues/issue-7044.stderr
@@ -0,0 +1,13 @@
+error[E0428]: the name `X` is defined multiple times
+  --> $DIR/issue-7044.rs:2:1
+   |
+LL | static X: isize = 0;
+   | -------------------- previous definition of the value `X` here
+LL | struct X;
+   | ^^^^^^^^^ `X` redefined here
+   |
+   = note: `X` must be defined only once in the value namespace of this module
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0428`.
diff --git a/src/test/ui/issues/issue-7061.rs b/src/test/ui/issues/issue-7061.rs
new file mode 100644
index 0000000..66ae900
--- /dev/null
+++ b/src/test/ui/issues/issue-7061.rs
@@ -0,0 +1,10 @@
+struct BarStruct;
+
+impl<'a> BarStruct {
+    fn foo(&'a mut self) -> Box<BarStruct> { self }
+    //~^ ERROR mismatched types
+    //~| expected type `std::boxed::Box<BarStruct>`
+    //~| found type `&'a mut BarStruct`
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-7061.stderr b/src/test/ui/issues/issue-7061.stderr
new file mode 100644
index 0000000..96c539f
--- /dev/null
+++ b/src/test/ui/issues/issue-7061.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-7061.rs:4:46
+   |
+LL |     fn foo(&'a mut self) -> Box<BarStruct> { self }
+   |                             --------------   ^^^^ expected struct `std::boxed::Box`, found mutable reference
+   |                             |
+   |                             expected `std::boxed::Box<BarStruct>` because of return type
+   |
+   = note: expected type `std::boxed::Box<BarStruct>`
+              found type `&'a mut BarStruct`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-7092.rs b/src/test/ui/issues/issue-7092.rs
new file mode 100644
index 0000000..b49a262
--- /dev/null
+++ b/src/test/ui/issues/issue-7092.rs
@@ -0,0 +1,15 @@
+enum Whatever {
+}
+
+fn foo(x: Whatever) {
+    match x {
+        Some(field) =>
+//~^ ERROR mismatched types
+//~| expected type `Whatever`
+//~| found type `std::option::Option<_>`
+//~| expected enum `Whatever`, found enum `std::option::Option`
+            field.access(),
+    }
+}
+
+fn main(){}
diff --git a/src/test/ui/issues/issue-7092.stderr b/src/test/ui/issues/issue-7092.stderr
new file mode 100644
index 0000000..7bb6820
--- /dev/null
+++ b/src/test/ui/issues/issue-7092.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-7092.rs:6:9
+   |
+LL |     match x {
+   |           - this match expression has type `Whatever`
+LL |         Some(field) =>
+   |         ^^^^^^^^^^^ expected enum `Whatever`, found enum `std::option::Option`
+   |
+   = note: expected type `Whatever`
+              found type `std::option::Option<_>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-7246.rs b/src/test/ui/issues/issue-7246.rs
new file mode 100644
index 0000000..bf2794e
--- /dev/null
+++ b/src/test/ui/issues/issue-7246.rs
@@ -0,0 +1,10 @@
+#![deny(unreachable_code)]
+#![allow(dead_code)]
+
+use std::ptr;
+pub unsafe fn g() {
+    return;
+    if *ptr::null() {}; //~ ERROR unreachable
+}
+
+pub fn main() {}
diff --git a/src/test/ui/issues/issue-7246.stderr b/src/test/ui/issues/issue-7246.stderr
new file mode 100644
index 0000000..e049295
--- /dev/null
+++ b/src/test/ui/issues/issue-7246.stderr
@@ -0,0 +1,14 @@
+error: unreachable statement
+  --> $DIR/issue-7246.rs:7:5
+   |
+LL |     if *ptr::null() {};
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/issue-7246.rs:1:9
+   |
+LL | #![deny(unreachable_code)]
+   |         ^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-7268.rs b/src/test/ui/issues/issue-7268.rs
new file mode 100644
index 0000000..0b94fab
--- /dev/null
+++ b/src/test/ui/issues/issue-7268.rs
@@ -0,0 +1,10 @@
+// compile-pass
+#![allow(dead_code)]
+// pretty-expanded FIXME #23616
+
+fn foo<T: 'static>(_: T) {}
+
+fn bar<T>(x: &'static T) {
+    foo(x);
+}
+fn main() {}
diff --git a/src/test/ui/issues/issue-7364.rs b/src/test/ui/issues/issue-7364.rs
new file mode 100644
index 0000000..52ec9e4
--- /dev/null
+++ b/src/test/ui/issues/issue-7364.rs
@@ -0,0 +1,11 @@
+#![feature(box_syntax)]
+
+use std::cell::RefCell;
+
+// Regression test for issue 7364
+static boxed: Box<RefCell<isize>> = box RefCell::new(0);
+//~^ ERROR allocations are not allowed in statics
+//~| ERROR `std::cell::RefCell<isize>` cannot be shared between threads safely [E0277]
+//~| ERROR static contains unimplemented expression type
+
+fn main() { }
diff --git a/src/test/ui/issues/issue-7364.stderr b/src/test/ui/issues/issue-7364.stderr
new file mode 100644
index 0000000..52a99ce
--- /dev/null
+++ b/src/test/ui/issues/issue-7364.stderr
@@ -0,0 +1,27 @@
+error[E0010]: allocations are not allowed in statics
+  --> $DIR/issue-7364.rs:6:37
+   |
+LL | static boxed: Box<RefCell<isize>> = box RefCell::new(0);
+   |                                     ^^^^^^^^^^^^^^^^^^^ allocation not allowed in statics
+
+error[E0019]: static contains unimplemented expression type
+  --> $DIR/issue-7364.rs:6:41
+   |
+LL | static boxed: Box<RefCell<isize>> = box RefCell::new(0);
+   |                                         ^^^^^^^^^^^^^^^
+
+error[E0277]: `std::cell::RefCell<isize>` cannot be shared between threads safely
+  --> $DIR/issue-7364.rs:6:1
+   |
+LL | static boxed: Box<RefCell<isize>> = box RefCell::new(0);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `std::cell::RefCell<isize>` cannot be shared between threads safely
+   |
+   = help: the trait `std::marker::Sync` is not implemented for `std::cell::RefCell<isize>`
+   = note: required because of the requirements on the impl of `std::marker::Sync` for `std::ptr::Unique<std::cell::RefCell<isize>>`
+   = note: required because it appears within the type `std::boxed::Box<std::cell::RefCell<isize>>`
+   = note: shared static variables must have a type that implements `Sync`
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0010, E0019, E0277.
+For more information about an error, try `rustc --explain E0010`.
diff --git a/src/test/ui/issues/issue-7607-1.rs b/src/test/ui/issues/issue-7607-1.rs
new file mode 100644
index 0000000..5221f2c
--- /dev/null
+++ b/src/test/ui/issues/issue-7607-1.rs
@@ -0,0 +1,9 @@
+struct Foo {
+    x: isize
+}
+
+impl Fo { //~ ERROR cannot find type `Fo` in this scope
+    fn foo() {}
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-7607-1.stderr b/src/test/ui/issues/issue-7607-1.stderr
new file mode 100644
index 0000000..9320943
--- /dev/null
+++ b/src/test/ui/issues/issue-7607-1.stderr
@@ -0,0 +1,9 @@
+error[E0412]: cannot find type `Fo` in this scope
+  --> $DIR/issue-7607-1.rs:5:6
+   |
+LL | impl Fo {
+   |      ^^ help: a trait with a similar name exists: `Fn`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/src/test/ui/issues/issue-7607-2.rs b/src/test/ui/issues/issue-7607-2.rs
new file mode 100644
index 0000000..8b5c850
--- /dev/null
+++ b/src/test/ui/issues/issue-7607-2.rs
@@ -0,0 +1,16 @@
+// compile-pass
+#![allow(dead_code)]
+// pretty-expanded FIXME #23616
+
+pub mod a {
+    pub struct Foo { a: usize }
+}
+
+pub mod b {
+    use a::Foo;
+    impl Foo {
+        fn bar(&self) { }
+    }
+}
+
+pub fn main() { }
diff --git a/src/test/ui/issues/issue-7673-cast-generically-implemented-trait.rs b/src/test/ui/issues/issue-7673-cast-generically-implemented-trait.rs
new file mode 100644
index 0000000..7dd6b07
--- /dev/null
+++ b/src/test/ui/issues/issue-7673-cast-generically-implemented-trait.rs
@@ -0,0 +1,22 @@
+// compile-pass
+#![allow(dead_code)]
+// pretty-expanded FIXME #23616
+
+/*
+
+#7673 Polymorphically creating traits barely works
+
+*/
+
+#![feature(box_syntax)]
+
+pub fn main() {}
+
+trait A {
+    fn dummy(&self) { }
+}
+
+impl<T: 'static> A for T {}
+
+fn owned2<T: 'static>(a: Box<T>) { a as Box<A>; }
+fn owned3<T: 'static>(a: Box<T>) { box a as Box<A>; }
diff --git a/src/test/ui/issues/issue-7813.rs b/src/test/ui/issues/issue-7813.rs
new file mode 100644
index 0000000..ce549bd
--- /dev/null
+++ b/src/test/ui/issues/issue-7813.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let v = &[]; //~ ERROR type annotations needed
+    let it = v.iter();
+}
diff --git a/src/test/ui/issues/issue-7813.stderr b/src/test/ui/issues/issue-7813.stderr
new file mode 100644
index 0000000..45b9c91
--- /dev/null
+++ b/src/test/ui/issues/issue-7813.stderr
@@ -0,0 +1,11 @@
+error[E0282]: type annotations needed
+  --> $DIR/issue-7813.rs:2:13
+   |
+LL |     let v = &[];
+   |         -   ^^^ cannot infer type
+   |         |
+   |         consider giving `v` a type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/issues/issue-7867.rs b/src/test/ui/issues/issue-7867.rs
new file mode 100644
index 0000000..a1997fb
--- /dev/null
+++ b/src/test/ui/issues/issue-7867.rs
@@ -0,0 +1,14 @@
+enum A { B, C }
+
+mod foo { pub fn bar() {} }
+
+fn main() {
+    match (true, false) {
+        A::B => (),
+        //~^ ERROR mismatched types
+        //~| expected type `(bool, bool)`
+        //~| found type `A`
+        //~| expected tuple, found enum `A`
+        _ => ()
+    }
+}
diff --git a/src/test/ui/issues/issue-7867.stderr b/src/test/ui/issues/issue-7867.stderr
new file mode 100644
index 0000000..1d3a0ff
--- /dev/null
+++ b/src/test/ui/issues/issue-7867.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-7867.rs:7:9
+   |
+LL |         A::B => (),
+   |         ^^^^ expected tuple, found enum `A`
+   |
+   = note: expected type `(bool, bool)`
+              found type `A`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-7950.rs b/src/test/ui/issues/issue-7950.rs
new file mode 100644
index 0000000..7add8af
--- /dev/null
+++ b/src/test/ui/issues/issue-7950.rs
@@ -0,0 +1,8 @@
+// tests the good error message, not "missing module Foo" or something else unexpected
+
+struct Foo;
+
+fn main() {
+    Foo::bar();
+    //~^ ERROR no function or associated item named `bar` found for type `Foo`
+}
diff --git a/src/test/ui/issues/issue-7950.stderr b/src/test/ui/issues/issue-7950.stderr
new file mode 100644
index 0000000..bbeab40
--- /dev/null
+++ b/src/test/ui/issues/issue-7950.stderr
@@ -0,0 +1,12 @@
+error[E0599]: no function or associated item named `bar` found for type `Foo` in the current scope
+  --> $DIR/issue-7950.rs:6:10
+   |
+LL | struct Foo;
+   | ----------- function or associated item `bar` not found for this
+...
+LL |     Foo::bar();
+   |          ^^^ function or associated item not found in `Foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/issues/issue-7970a.rs b/src/test/ui/issues/issue-7970a.rs
new file mode 100644
index 0000000..dae9064
--- /dev/null
+++ b/src/test/ui/issues/issue-7970a.rs
@@ -0,0 +1,8 @@
+macro_rules! one_arg_macro {
+    ($fmt:expr) => (print!(concat!($fmt, "\n")));
+}
+
+fn main() {
+    one_arg_macro!();
+    //~^ ERROR unexpected end of macro invocation
+}
diff --git a/src/test/ui/issues/issue-7970a.stderr b/src/test/ui/issues/issue-7970a.stderr
new file mode 100644
index 0000000..5cfb62f
--- /dev/null
+++ b/src/test/ui/issues/issue-7970a.stderr
@@ -0,0 +1,11 @@
+error: unexpected end of macro invocation
+  --> $DIR/issue-7970a.rs:6:5
+   |
+LL | macro_rules! one_arg_macro {
+   | -------------------------- when calling this macro
+...
+LL |     one_arg_macro!();
+   |     ^^^^^^^^^^^^^^^^^ missing tokens in macro arguments
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-7970b.rs b/src/test/ui/issues/issue-7970b.rs
new file mode 100644
index 0000000..1c4abce
--- /dev/null
+++ b/src/test/ui/issues/issue-7970b.rs
@@ -0,0 +1,4 @@
+fn main() {}
+
+macro_rules! test {}
+//~^ ERROR unexpected end of macro invocation
diff --git a/src/test/ui/issues/issue-7970b.stderr b/src/test/ui/issues/issue-7970b.stderr
new file mode 100644
index 0000000..a62226a
--- /dev/null
+++ b/src/test/ui/issues/issue-7970b.stderr
@@ -0,0 +1,8 @@
+error: unexpected end of macro invocation
+  --> $DIR/issue-7970b.rs:3:1
+   |
+LL | macro_rules! test {}
+   | ^^^^^^^^^^^^^^^^^^^^ missing tokens in macro arguments
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-8153.rs b/src/test/ui/issues/issue-8153.rs
new file mode 100644
index 0000000..81a8f53
--- /dev/null
+++ b/src/test/ui/issues/issue-8153.rs
@@ -0,0 +1,16 @@
+// Test that duplicate methods in impls are not allowed
+
+struct Foo;
+
+trait Bar {
+    fn bar(&self) -> isize;
+}
+
+impl Bar for Foo {
+    fn bar(&self) -> isize {1}
+    fn bar(&self) -> isize {2} //~ ERROR duplicate definitions
+}
+
+fn main() {
+    println!("{}", Foo.bar());
+}
diff --git a/src/test/ui/issues/issue-8153.stderr b/src/test/ui/issues/issue-8153.stderr
new file mode 100644
index 0000000..4389c3d
--- /dev/null
+++ b/src/test/ui/issues/issue-8153.stderr
@@ -0,0 +1,11 @@
+error[E0201]: duplicate definitions with name `bar`:
+  --> $DIR/issue-8153.rs:11:5
+   |
+LL |     fn bar(&self) -> isize {1}
+   |     -------------------------- previous definition of `bar` here
+LL |     fn bar(&self) -> isize {2}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ duplicate definition
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0201`.
diff --git a/src/test/ui/issues/issue-8171-default-method-self-inherit-builtin-trait.rs b/src/test/ui/issues/issue-8171-default-method-self-inherit-builtin-trait.rs
new file mode 100644
index 0000000..e4dafc0
--- /dev/null
+++ b/src/test/ui/issues/issue-8171-default-method-self-inherit-builtin-trait.rs
@@ -0,0 +1,19 @@
+// compile-pass
+#![allow(dead_code)]
+// pretty-expanded FIXME #23616
+
+/*
+
+#8171 Self is not recognised as implementing kinds in default method implementations
+
+*/
+
+fn require_send<T: Send>(_: T){}
+
+trait TragicallySelfIsNotSend: Send + Sized {
+    fn x(self) {
+        require_send(self);
+    }
+}
+
+pub fn main(){}
diff --git a/src/test/ui/issues/issue-8208.rs b/src/test/ui/issues/issue-8208.rs
new file mode 100644
index 0000000..1c56693
--- /dev/null
+++ b/src/test/ui/issues/issue-8208.rs
@@ -0,0 +1,17 @@
+use self::*; //~ ERROR: unresolved import `self::*` [E0432]
+             //~^ cannot glob-import a module into itself
+
+mod foo {
+    use foo::*; //~ ERROR: unresolved import `foo::*` [E0432]
+                //~^ cannot glob-import a module into itself
+
+    mod bar {
+        use super::bar::*;
+        //~^ ERROR: unresolved import `super::bar::*` [E0432]
+        //~| cannot glob-import a module into itself
+    }
+
+}
+
+fn main() {
+}
diff --git a/src/test/ui/issues/issue-8208.stderr b/src/test/ui/issues/issue-8208.stderr
new file mode 100644
index 0000000..e59aea1
--- /dev/null
+++ b/src/test/ui/issues/issue-8208.stderr
@@ -0,0 +1,21 @@
+error[E0432]: unresolved import `self::*`
+  --> $DIR/issue-8208.rs:1:5
+   |
+LL | use self::*;
+   |     ^^^^^^^ cannot glob-import a module into itself
+
+error[E0432]: unresolved import `foo::*`
+  --> $DIR/issue-8208.rs:5:9
+   |
+LL |     use foo::*;
+   |         ^^^^^^ cannot glob-import a module into itself
+
+error[E0432]: unresolved import `super::bar::*`
+  --> $DIR/issue-8208.rs:9:13
+   |
+LL |         use super::bar::*;
+   |             ^^^^^^^^^^^^^ cannot glob-import a module into itself
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/issues/issue-8398.rs b/src/test/ui/issues/issue-8398.rs
new file mode 100644
index 0000000..bd37b85
--- /dev/null
+++ b/src/test/ui/issues/issue-8398.rs
@@ -0,0 +1,13 @@
+// compile-pass
+#![allow(dead_code)]
+// pretty-expanded FIXME #23616
+
+pub trait Writer {
+    fn write(&mut self, b: &[u8]) -> Result<(), ()>;
+}
+
+fn foo(a: &mut Writer) {
+    a.write(&[]).unwrap();
+}
+
+pub fn main(){}
diff --git a/src/test/ui/issues/issue-8460-const.rs b/src/test/ui/issues/issue-8460-const.rs
new file mode 100644
index 0000000..611d280
--- /dev/null
+++ b/src/test/ui/issues/issue-8460-const.rs
@@ -0,0 +1,67 @@
+#![deny(const_err)]
+
+use std::{isize, i8, i16, i32, i64};
+use std::thread;
+
+fn main() {
+    assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err());
+    //~^ ERROR attempt to divide with overflow
+    //~| ERROR this expression will panic at runtime
+    assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err());
+    //~^ ERROR attempt to divide with overflow
+    //~| ERROR this expression will panic at runtime
+    assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err());
+    //~^ ERROR attempt to divide with overflow
+    //~| ERROR this expression will panic at runtime
+    assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err());
+    //~^ ERROR attempt to divide with overflow
+    //~| ERROR this expression will panic at runtime
+    assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err());
+    //~^ ERROR attempt to divide with overflow
+    //~| ERROR this expression will panic at runtime
+    assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err());
+    //~^ ERROR attempt to divide by zero
+    //~| ERROR this expression will panic at runtime
+    assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err());
+    //~^ ERROR attempt to divide by zero
+    //~| ERROR this expression will panic at runtime
+    assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err());
+    //~^ ERROR attempt to divide by zero
+    //~| ERROR this expression will panic at runtime
+    assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err());
+    //~^ ERROR attempt to divide by zero
+    //~| ERROR this expression will panic at runtime
+    assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err());
+    //~^ ERROR attempt to divide by zero
+    //~| ERROR this expression will panic at runtime
+    assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err());
+    //~^ ERROR attempt to calculate the remainder with overflow
+    //~| ERROR this expression will panic at runtime
+    assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err());
+    //~^ ERROR attempt to calculate the remainder with overflow
+    //~| ERROR this expression will panic at runtime
+    assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err());
+    //~^ ERROR attempt to calculate the remainder with overflow
+    //~| ERROR this expression will panic at runtime
+    assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err());
+    //~^ ERROR attempt to calculate the remainder with overflow
+    //~| ERROR this expression will panic at runtime
+    assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err());
+    //~^ ERROR attempt to calculate the remainder with overflow
+    //~| ERROR this expression will panic at runtime
+    assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err());
+    //~^ ERROR attempt to calculate the remainder with a divisor of zero
+    //~| ERROR this expression will panic at runtime
+    assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err());
+    //~^ ERROR attempt to calculate the remainder with a divisor of zero
+    //~| ERROR this expression will panic at runtime
+    assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err());
+    //~^ ERROR attempt to calculate the remainder with a divisor of zero
+    //~| ERROR this expression will panic at runtime
+    assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err());
+    //~^ ERROR attempt to calculate the remainder with a divisor of zero
+    //~| ERROR this expression will panic at runtime
+    assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err());
+    //~^ ERROR attempt to calculate the remainder with a divisor of zero
+    //~| ERROR this expression will panic at runtime
+}
diff --git a/src/test/ui/issues/issue-8460-const.stderr b/src/test/ui/issues/issue-8460-const.stderr
new file mode 100644
index 0000000..31b1da4
--- /dev/null
+++ b/src/test/ui/issues/issue-8460-const.stderr
@@ -0,0 +1,248 @@
+error: attempt to divide with overflow
+  --> $DIR/issue-8460-const.rs:7:36
+   |
+LL |     assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/issue-8460-const.rs:1:9
+   |
+LL | #![deny(const_err)]
+   |         ^^^^^^^^^
+
+error: this expression will panic at runtime
+  --> $DIR/issue-8460-const.rs:7:36
+   |
+LL |     assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^^^^ attempt to divide with overflow
+
+error: attempt to divide with overflow
+  --> $DIR/issue-8460-const.rs:10:36
+   |
+LL |     assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^
+
+error: this expression will panic at runtime
+  --> $DIR/issue-8460-const.rs:10:36
+   |
+LL |     assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^ attempt to divide with overflow
+
+error: attempt to divide with overflow
+  --> $DIR/issue-8460-const.rs:13:36
+   |
+LL |     assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^^
+
+error: this expression will panic at runtime
+  --> $DIR/issue-8460-const.rs:13:36
+   |
+LL |     assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^^ attempt to divide with overflow
+
+error: attempt to divide with overflow
+  --> $DIR/issue-8460-const.rs:16:36
+   |
+LL |     assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^^
+
+error: this expression will panic at runtime
+  --> $DIR/issue-8460-const.rs:16:36
+   |
+LL |     assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^^ attempt to divide with overflow
+
+error: attempt to divide with overflow
+  --> $DIR/issue-8460-const.rs:19:36
+   |
+LL |     assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^^
+
+error: this expression will panic at runtime
+  --> $DIR/issue-8460-const.rs:19:36
+   |
+LL |     assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^^ attempt to divide with overflow
+
+error: attempt to divide by zero
+  --> $DIR/issue-8460-const.rs:22:36
+   |
+LL |     assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err());
+   |                                    ^^^^^^^^^^
+
+error: this expression will panic at runtime
+  --> $DIR/issue-8460-const.rs:22:36
+   |
+LL |     assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err());
+   |                                    ^^^^^^^^^^ attempt to divide by zero
+
+error: attempt to divide by zero
+  --> $DIR/issue-8460-const.rs:25:36
+   |
+LL |     assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err());
+   |                                    ^^^^^^^
+
+error: this expression will panic at runtime
+  --> $DIR/issue-8460-const.rs:25:36
+   |
+LL |     assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err());
+   |                                    ^^^^^^^ attempt to divide by zero
+
+error: attempt to divide by zero
+  --> $DIR/issue-8460-const.rs:28:36
+   |
+LL |     assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err());
+   |                                    ^^^^^^^^
+
+error: this expression will panic at runtime
+  --> $DIR/issue-8460-const.rs:28:36
+   |
+LL |     assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err());
+   |                                    ^^^^^^^^ attempt to divide by zero
+
+error: attempt to divide by zero
+  --> $DIR/issue-8460-const.rs:31:36
+   |
+LL |     assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err());
+   |                                    ^^^^^^^^
+
+error: this expression will panic at runtime
+  --> $DIR/issue-8460-const.rs:31:36
+   |
+LL |     assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err());
+   |                                    ^^^^^^^^ attempt to divide by zero
+
+error: attempt to divide by zero
+  --> $DIR/issue-8460-const.rs:34:36
+   |
+LL |     assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err());
+   |                                    ^^^^^^^^
+
+error: this expression will panic at runtime
+  --> $DIR/issue-8460-const.rs:34:36
+   |
+LL |     assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err());
+   |                                    ^^^^^^^^ attempt to divide by zero
+
+error: attempt to calculate the remainder with overflow
+  --> $DIR/issue-8460-const.rs:37:36
+   |
+LL |     assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^^^^
+
+error: this expression will panic at runtime
+  --> $DIR/issue-8460-const.rs:37:36
+   |
+LL |     assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^^^^ attempt to calculate the remainder with overflow
+
+error: attempt to calculate the remainder with overflow
+  --> $DIR/issue-8460-const.rs:40:36
+   |
+LL |     assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^
+
+error: this expression will panic at runtime
+  --> $DIR/issue-8460-const.rs:40:36
+   |
+LL |     assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^ attempt to calculate the remainder with overflow
+
+error: attempt to calculate the remainder with overflow
+  --> $DIR/issue-8460-const.rs:43:36
+   |
+LL |     assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^^
+
+error: this expression will panic at runtime
+  --> $DIR/issue-8460-const.rs:43:36
+   |
+LL |     assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow
+
+error: attempt to calculate the remainder with overflow
+  --> $DIR/issue-8460-const.rs:46:36
+   |
+LL |     assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^^
+
+error: this expression will panic at runtime
+  --> $DIR/issue-8460-const.rs:46:36
+   |
+LL |     assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow
+
+error: attempt to calculate the remainder with overflow
+  --> $DIR/issue-8460-const.rs:49:36
+   |
+LL |     assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^^
+
+error: this expression will panic at runtime
+  --> $DIR/issue-8460-const.rs:49:36
+   |
+LL |     assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow
+
+error: attempt to calculate the remainder with a divisor of zero
+  --> $DIR/issue-8460-const.rs:52:36
+   |
+LL |     assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err());
+   |                                    ^^^^^^^^^^
+
+error: this expression will panic at runtime
+  --> $DIR/issue-8460-const.rs:52:36
+   |
+LL |     assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err());
+   |                                    ^^^^^^^^^^ attempt to calculate the remainder with a divisor of zero
+
+error: attempt to calculate the remainder with a divisor of zero
+  --> $DIR/issue-8460-const.rs:55:36
+   |
+LL |     assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err());
+   |                                    ^^^^^^^
+
+error: this expression will panic at runtime
+  --> $DIR/issue-8460-const.rs:55:36
+   |
+LL |     assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err());
+   |                                    ^^^^^^^ attempt to calculate the remainder with a divisor of zero
+
+error: attempt to calculate the remainder with a divisor of zero
+  --> $DIR/issue-8460-const.rs:58:36
+   |
+LL |     assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err());
+   |                                    ^^^^^^^^
+
+error: this expression will panic at runtime
+  --> $DIR/issue-8460-const.rs:58:36
+   |
+LL |     assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err());
+   |                                    ^^^^^^^^ attempt to calculate the remainder with a divisor of zero
+
+error: attempt to calculate the remainder with a divisor of zero
+  --> $DIR/issue-8460-const.rs:61:36
+   |
+LL |     assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err());
+   |                                    ^^^^^^^^
+
+error: this expression will panic at runtime
+  --> $DIR/issue-8460-const.rs:61:36
+   |
+LL |     assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err());
+   |                                    ^^^^^^^^ attempt to calculate the remainder with a divisor of zero
+
+error: attempt to calculate the remainder with a divisor of zero
+  --> $DIR/issue-8460-const.rs:64:36
+   |
+LL |     assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err());
+   |                                    ^^^^^^^^
+
+error: this expression will panic at runtime
+  --> $DIR/issue-8460-const.rs:64:36
+   |
+LL |     assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err());
+   |                                    ^^^^^^^^ attempt to calculate the remainder with a divisor of zero
+
+error: aborting due to 40 previous errors
+
diff --git a/src/test/ui/issues/issue-8521.rs b/src/test/ui/issues/issue-8521.rs
new file mode 100644
index 0000000..7007c8a
--- /dev/null
+++ b/src/test/ui/issues/issue-8521.rs
@@ -0,0 +1,25 @@
+// compile-pass
+trait Foo1 {}
+
+trait A {}
+
+macro_rules! foo1(($t:path) => {
+    impl<T: $t> Foo1 for T {}
+});
+
+foo1!(A);
+
+trait Foo2 {}
+
+trait B<T> {}
+
+#[allow(unused)]
+struct C {}
+
+macro_rules! foo2(($t:path) => {
+    impl<T: $t> Foo2 for T {}
+});
+
+foo2!(B<C>);
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-8578.rs b/src/test/ui/issues/issue-8578.rs
new file mode 100644
index 0000000..4cc2123
--- /dev/null
+++ b/src/test/ui/issues/issue-8578.rs
@@ -0,0 +1,20 @@
+// compile-pass
+#![allow(dead_code)]
+#![allow(non_camel_case_types)]
+#![allow(non_upper_case_globals)]
+// pretty-expanded FIXME #23616
+
+pub struct UninterpretedOption_NamePart {
+    name_part: Option<String>,
+}
+
+impl<'a> UninterpretedOption_NamePart {
+    pub fn default_instance() -> &'static UninterpretedOption_NamePart {
+        static instance: UninterpretedOption_NamePart = UninterpretedOption_NamePart {
+            name_part: None,
+        };
+        &instance
+    }
+}
+
+pub fn main() {}
diff --git a/src/test/ui/issues/issue-8640.rs b/src/test/ui/issues/issue-8640.rs
new file mode 100644
index 0000000..51a02a3
--- /dev/null
+++ b/src/test/ui/issues/issue-8640.rs
@@ -0,0 +1,10 @@
+#[allow(unused_imports)]
+
+mod foo {
+    use baz::bar;
+    mod bar {}
+    //~^ ERROR the name `bar` is defined multiple times
+}
+mod baz { pub mod bar {} }
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-8640.stderr b/src/test/ui/issues/issue-8640.stderr
new file mode 100644
index 0000000..4ce6394
--- /dev/null
+++ b/src/test/ui/issues/issue-8640.stderr
@@ -0,0 +1,17 @@
+error[E0255]: the name `bar` is defined multiple times
+  --> $DIR/issue-8640.rs:5:5
+   |
+LL |     use baz::bar;
+   |         -------- previous import of the module `bar` here
+LL |     mod bar {}
+   |     ^^^^^^^ `bar` redefined here
+   |
+   = note: `bar` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL |     use baz::bar as other_bar;
+   |         ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0255`.
diff --git a/src/test/ui/issues/issue-8727.rs b/src/test/ui/issues/issue-8727.rs
new file mode 100644
index 0000000..473d237
--- /dev/null
+++ b/src/test/ui/issues/issue-8727.rs
@@ -0,0 +1,15 @@
+// Verify the compiler fails with an error on infinite function
+// recursions.
+
+fn generic<T>() {
+    generic::<Option<T>>();
+}
+//~^^^ ERROR reached the recursion limit while instantiating `generic::<std::option::Option<
+//~| WARN function cannot return without recursing
+
+
+
+fn main () {
+    // Use generic<T> at least once to trigger instantiation.
+    generic::<i32>();
+}
diff --git a/src/test/ui/issues/issue-8727.stderr b/src/test/ui/issues/issue-8727.stderr
new file mode 100644
index 0000000..dd23830
--- /dev/null
+++ b/src/test/ui/issues/issue-8727.stderr
@@ -0,0 +1,21 @@
+warning: function cannot return without recursing
+  --> $DIR/issue-8727.rs:4:1
+   |
+LL | fn generic<T>() {
+   | ^^^^^^^^^^^^^^^ cannot return without recursing
+LL |     generic::<Option<T>>();
+   |     ---------------------- recursive call site
+   |
+   = note: #[warn(unconditional_recursion)] on by default
+   = help: a `loop` may express intention better if this is on purpose
+
+error: reached the recursion limit while instantiating `generic::<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<i32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+  --> $DIR/issue-8727.rs:4:1
+   |
+LL | / fn generic<T>() {
+LL | |     generic::<Option<T>>();
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-8761.rs b/src/test/ui/issues/issue-8761.rs
new file mode 100644
index 0000000..e69927c
--- /dev/null
+++ b/src/test/ui/issues/issue-8761.rs
@@ -0,0 +1,10 @@
+enum Foo {
+    A = 1i64,
+    //~^ ERROR mismatched types
+    //~| expected isize, found i64
+    B = 2u8
+    //~^ ERROR mismatched types
+    //~| expected isize, found u8
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-8761.stderr b/src/test/ui/issues/issue-8761.stderr
new file mode 100644
index 0000000..fc0c140
--- /dev/null
+++ b/src/test/ui/issues/issue-8761.stderr
@@ -0,0 +1,15 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-8761.rs:2:9
+   |
+LL |     A = 1i64,
+   |         ^^^^ expected isize, found i64
+
+error[E0308]: mismatched types
+  --> $DIR/issue-8761.rs:5:9
+   |
+LL |     B = 2u8
+   |         ^^^ expected isize, found u8
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-8767.rs b/src/test/ui/issues/issue-8767.rs
new file mode 100644
index 0000000..972101a
--- /dev/null
+++ b/src/test/ui/issues/issue-8767.rs
@@ -0,0 +1,5 @@
+impl B { //~ ERROR cannot find type `B` in this scope
+}
+
+fn main() {
+}
diff --git a/src/test/ui/issues/issue-8767.stderr b/src/test/ui/issues/issue-8767.stderr
new file mode 100644
index 0000000..91d99f3
--- /dev/null
+++ b/src/test/ui/issues/issue-8767.stderr
@@ -0,0 +1,9 @@
+error[E0412]: cannot find type `B` in this scope
+  --> $DIR/issue-8767.rs:1:6
+   |
+LL | impl B {
+   |      ^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/src/test/ui/issues/issue-9110.rs b/src/test/ui/issues/issue-9110.rs
new file mode 100644
index 0000000..30acd61
--- /dev/null
+++ b/src/test/ui/issues/issue-9110.rs
@@ -0,0 +1,17 @@
+// compile-pass
+#![allow(dead_code)]
+// pretty-expanded FIXME #23616
+#![allow(non_snake_case)]
+
+macro_rules! silly_macro {
+    () => (
+        pub mod Qux {
+            pub struct Foo { x : u8 }
+            pub fn bar(_foo : Foo) {}
+        }
+    );
+}
+
+silly_macro!();
+
+pub fn main() {}
diff --git a/src/test/ui/issues/issue-9243.rs b/src/test/ui/issues/issue-9243.rs
new file mode 100644
index 0000000..e877dd6
--- /dev/null
+++ b/src/test/ui/issues/issue-9243.rs
@@ -0,0 +1,16 @@
+// compile-pass
+#![allow(dead_code)]
+// Regression test for issue 9243
+#![allow(non_upper_case_globals)]
+
+pub struct Test {
+    mem: isize,
+}
+
+pub static g_test: Test = Test {mem: 0};
+
+impl Drop for Test {
+    fn drop(&mut self) {}
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-9249.rs b/src/test/ui/issues/issue-9249.rs
new file mode 100644
index 0000000..e4e9c45
--- /dev/null
+++ b/src/test/ui/issues/issue-9249.rs
@@ -0,0 +1,6 @@
+// compile-pass
+#![allow(dead_code)]
+// pretty-expanded FIXME #23616
+
+static DATA:&'static [&'static str] = &["my string"];
+fn main() { }
diff --git a/src/test/ui/issues/issue-9575.rs b/src/test/ui/issues/issue-9575.rs
new file mode 100644
index 0000000..bac4ac1
--- /dev/null
+++ b/src/test/ui/issues/issue-9575.rs
@@ -0,0 +1,7 @@
+#![feature(start)]
+
+#[start]
+fn start(argc: isize, argv: *const *const u8, crate_map: *const u8) -> isize {
+    //~^ start function has wrong type
+   0
+}
diff --git a/src/test/ui/issues/issue-9575.stderr b/src/test/ui/issues/issue-9575.stderr
new file mode 100644
index 0000000..1483e42
--- /dev/null
+++ b/src/test/ui/issues/issue-9575.stderr
@@ -0,0 +1,12 @@
+error[E0308]: start function has wrong type
+  --> $DIR/issue-9575.rs:4:1
+   |
+LL | fn start(argc: isize, argv: *const *const u8, crate_map: *const u8) -> isize {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect number of function parameters
+   |
+   = note: expected type `fn(isize, *const *const u8) -> isize`
+              found type `fn(isize, *const *const u8, *const u8) -> isize`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-9719.rs b/src/test/ui/issues/issue-9719.rs
new file mode 100644
index 0000000..9686534
--- /dev/null
+++ b/src/test/ui/issues/issue-9719.rs
@@ -0,0 +1,41 @@
+// compile-pass
+#![allow(dead_code)]
+// pretty-expanded FIXME #23616
+
+mod a {
+    pub enum Enum<T> {
+        A(T),
+    }
+
+    pub trait X {
+        fn dummy(&self) { }
+    }
+    impl X for isize {}
+
+    pub struct Z<'a>(Enum<&'a (X+'a)>);
+    fn foo() { let x: isize = 42; let z = Z(Enum::A(&x as &X)); let _ = z; }
+}
+
+mod b {
+    trait X {
+        fn dummy(&self) { }
+    }
+    impl X for isize {}
+    struct Y<'a>{
+        x:Option<&'a (X+'a)>,
+    }
+
+    fn bar() {
+        let x: isize = 42;
+        let _y = Y { x: Some(&x as &X) };
+    }
+}
+
+mod c {
+    pub trait X { fn f(&self); }
+    impl X for isize { fn f(&self) {} }
+    pub struct Z<'a>(Option<&'a (X+'a)>);
+    fn main() { let x: isize = 42; let z = Z(Some(&x as &X)); let _ = z; }
+}
+
+pub fn main() {}
diff --git a/src/test/ui/issues/issue-9725.rs b/src/test/ui/issues/issue-9725.rs
new file mode 100644
index 0000000..360effb
--- /dev/null
+++ b/src/test/ui/issues/issue-9725.rs
@@ -0,0 +1,7 @@
+struct A { foo: isize }
+
+fn main() {
+    let A { foo, foo } = A { foo: 3 };
+    //~^ ERROR: identifier `foo` is bound more than once in the same pattern
+    //~^^ ERROR: field `foo` bound multiple times
+}
diff --git a/src/test/ui/issues/issue-9725.stderr b/src/test/ui/issues/issue-9725.stderr
new file mode 100644
index 0000000..eafe92e
--- /dev/null
+++ b/src/test/ui/issues/issue-9725.stderr
@@ -0,0 +1,18 @@
+error[E0416]: identifier `foo` is bound more than once in the same pattern
+  --> $DIR/issue-9725.rs:4:18
+   |
+LL |     let A { foo, foo } = A { foo: 3 };
+   |                  ^^^ used in a pattern more than once
+
+error[E0025]: field `foo` bound multiple times in the pattern
+  --> $DIR/issue-9725.rs:4:18
+   |
+LL |     let A { foo, foo } = A { foo: 3 };
+   |             ---  ^^^ multiple uses of `foo` in pattern
+   |             |
+   |             first use of `foo`
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0025, E0416.
+For more information about an error, try `rustc --explain E0025`.
diff --git a/src/test/ui/issues/issue-9814.rs b/src/test/ui/issues/issue-9814.rs
new file mode 100644
index 0000000..a87478e
--- /dev/null
+++ b/src/test/ui/issues/issue-9814.rs
@@ -0,0 +1,8 @@
+// Verify that single-variant enums can't be de-referenced
+// Regression test for issue #9814
+
+enum Foo { Bar(isize) }
+
+fn main() {
+    let _ = *Foo::Bar(2); //~ ERROR type `Foo` cannot be dereferenced
+}
diff --git a/src/test/ui/issues/issue-9814.stderr b/src/test/ui/issues/issue-9814.stderr
new file mode 100644
index 0000000..bd9e7df
--- /dev/null
+++ b/src/test/ui/issues/issue-9814.stderr
@@ -0,0 +1,9 @@
+error[E0614]: type `Foo` cannot be dereferenced
+  --> $DIR/issue-9814.rs:7:13
+   |
+LL |     let _ = *Foo::Bar(2);
+   |             ^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0614`.
diff --git a/src/test/ui/issues/issue-pr29383.rs b/src/test/ui/issues/issue-pr29383.rs
new file mode 100644
index 0000000..334fdac
--- /dev/null
+++ b/src/test/ui/issues/issue-pr29383.rs
@@ -0,0 +1,12 @@
+enum E {
+    A,
+    B,
+}
+
+fn main() {
+    match None {
+        None => {}
+        Some(E::A(..)) => {} //~ ERROR expected tuple struct/variant, found unit variant `E::A`
+        Some(E::B(..)) => {} //~ ERROR expected tuple struct/variant, found unit variant `E::B`
+    }
+}
diff --git a/src/test/ui/issues/issue-pr29383.stderr b/src/test/ui/issues/issue-pr29383.stderr
new file mode 100644
index 0000000..9695e1e
--- /dev/null
+++ b/src/test/ui/issues/issue-pr29383.stderr
@@ -0,0 +1,15 @@
+error[E0532]: expected tuple struct/variant, found unit variant `E::A`
+  --> $DIR/issue-pr29383.rs:9:14
+   |
+LL |         Some(E::A(..)) => {}
+   |              ^^^^ not a tuple struct/variant
+
+error[E0532]: expected tuple struct/variant, found unit variant `E::B`
+  --> $DIR/issue-pr29383.rs:10:14
+   |
+LL |         Some(E::B(..)) => {}
+   |              ^^^^ not a tuple struct/variant
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0532`.
diff --git a/src/test/ui/issues/type-arg-mismatch-due-to-impl-trait.rs b/src/test/ui/issues/type-arg-mismatch-due-to-impl-trait.rs
new file mode 100644
index 0000000..4a71932
--- /dev/null
+++ b/src/test/ui/issues/type-arg-mismatch-due-to-impl-trait.rs
@@ -0,0 +1,15 @@
+trait Foo {
+    type T;
+    fn foo(&self, t: Self::T);
+//~^ NOTE expected 0 type parameters
+}
+
+impl Foo for u32 {
+    type T = ();
+
+    fn foo(&self, t: impl Clone) {}
+//~^ ERROR method `foo` has 1 type parameter but its trait declaration has 0 type parameters
+//~| NOTE found 1 type parameter
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/type-arg-mismatch-due-to-impl-trait.stderr b/src/test/ui/issues/type-arg-mismatch-due-to-impl-trait.stderr
new file mode 100644
index 0000000..af7fdde
--- /dev/null
+++ b/src/test/ui/issues/type-arg-mismatch-due-to-impl-trait.stderr
@@ -0,0 +1,12 @@
+error[E0049]: method `foo` has 1 type parameter but its trait declaration has 0 type parameters
+  --> $DIR/type-arg-mismatch-due-to-impl-trait.rs:10:5
+   |
+LL |     fn foo(&self, t: Self::T);
+   |     -------------------------- expected 0 type parameters
+...
+LL |     fn foo(&self, t: impl Clone) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found 1 type parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0049`.
diff --git a/src/test/ui/iterators/array-of-ranges.rs b/src/test/ui/iterators/array-of-ranges.rs
new file mode 100644
index 0000000..d2dfc7e
--- /dev/null
+++ b/src/test/ui/iterators/array-of-ranges.rs
@@ -0,0 +1,23 @@
+fn main() {
+    for _ in [0..1] {}
+//~^ ERROR is not an iterator
+    for _ in [0..=1] {}
+//~^ ERROR is not an iterator
+    for _ in [0..] {}
+//~^ ERROR is not an iterator
+    for _ in [..1] {}
+//~^ ERROR is not an iterator
+    for _ in [..=1] {}
+//~^ ERROR is not an iterator
+    let start = 0;
+    let end = 0;
+    for _ in [start..end] {}
+//~^ ERROR is not an iterator
+    let array_of_range = [start..end];
+    for _ in array_of_range {}
+//~^ ERROR is not an iterator
+    for _ in [0..1, 2..3] {}
+//~^ ERROR is not an iterator
+    for _ in [0..=1] {}
+//~^ ERROR is not an iterator
+}
diff --git a/src/test/ui/iterators/array-of-ranges.stderr b/src/test/ui/iterators/array-of-ranges.stderr
new file mode 100644
index 0000000..3dbed9a
--- /dev/null
+++ b/src/test/ui/iterators/array-of-ranges.stderr
@@ -0,0 +1,93 @@
+error[E0277]: `[std::ops::Range<{integer}>; 1]` is not an iterator
+  --> $DIR/array-of-ranges.rs:2:14
+   |
+LL |     for _ in [0..1] {}
+   |              ^^^^^^ if you meant to iterate between two values, remove the square brackets
+   |
+   = help: the trait `std::iter::Iterator` is not implemented for `[std::ops::Range<{integer}>; 1]`
+   = note: `[start..end]` is an array of one `Range`; you might have meant to have a `Range` without the brackets: `start..end`
+   = note: required by `std::iter::IntoIterator::into_iter`
+
+error[E0277]: `[std::ops::RangeInclusive<{integer}>; 1]` is not an iterator
+  --> $DIR/array-of-ranges.rs:4:14
+   |
+LL |     for _ in [0..=1] {}
+   |              ^^^^^^^ if you meant to iterate between two values, remove the square brackets
+   |
+   = help: the trait `std::iter::Iterator` is not implemented for `[std::ops::RangeInclusive<{integer}>; 1]`
+   = note: `[start..=end]` is an array of one `RangeInclusive`; you might have meant to have a `RangeInclusive` without the brackets: `start..=end`
+   = note: required by `std::iter::IntoIterator::into_iter`
+
+error[E0277]: `[std::ops::RangeFrom<{integer}>; 1]` is not an iterator
+  --> $DIR/array-of-ranges.rs:6:14
+   |
+LL |     for _ in [0..] {}
+   |              ^^^^^ if you meant to iterate from a value onwards, remove the square brackets
+   |
+   = help: the trait `std::iter::Iterator` is not implemented for `[std::ops::RangeFrom<{integer}>; 1]`
+   = note: `[start..]` is an array of one `RangeFrom`; you might have meant to have a `RangeFrom` without the brackets: `start..`, keeping in mind that iterating over an unbounded iterator will run forever unless you `break` or `return` from within the loop
+   = note: required by `std::iter::IntoIterator::into_iter`
+
+error[E0277]: `[std::ops::RangeTo<{integer}>; 1]` is not an iterator
+  --> $DIR/array-of-ranges.rs:8:14
+   |
+LL |     for _ in [..1] {}
+   |              ^^^^^ if you meant to iterate until a value, remove the square brackets and add a starting value
+   |
+   = help: the trait `std::iter::Iterator` is not implemented for `[std::ops::RangeTo<{integer}>; 1]`
+   = note: `[..end]` is an array of one `RangeTo`; you might have meant to have a bounded `Range` without the brackets: `0..end`
+   = note: required by `std::iter::IntoIterator::into_iter`
+
+error[E0277]: `[std::ops::RangeToInclusive<{integer}>; 1]` is not an iterator
+  --> $DIR/array-of-ranges.rs:10:14
+   |
+LL |     for _ in [..=1] {}
+   |              ^^^^^^ if you meant to iterate until a value (including it), remove the square brackets and add a starting value
+   |
+   = help: the trait `std::iter::Iterator` is not implemented for `[std::ops::RangeToInclusive<{integer}>; 1]`
+   = note: `[..=end]` is an array of one `RangeToInclusive`; you might have meant to have a bounded `RangeInclusive` without the brackets: `0..=end`
+   = note: required by `std::iter::IntoIterator::into_iter`
+
+error[E0277]: `[std::ops::Range<{integer}>; 1]` is not an iterator
+  --> $DIR/array-of-ranges.rs:14:14
+   |
+LL |     for _ in [start..end] {}
+   |              ^^^^^^^^^^^^ if you meant to iterate between two values, remove the square brackets
+   |
+   = help: the trait `std::iter::Iterator` is not implemented for `[std::ops::Range<{integer}>; 1]`
+   = note: `[start..end]` is an array of one `Range`; you might have meant to have a `Range` without the brackets: `start..end`
+   = note: required by `std::iter::IntoIterator::into_iter`
+
+error[E0277]: `[std::ops::Range<{integer}>; 1]` is not an iterator
+  --> $DIR/array-of-ranges.rs:17:14
+   |
+LL |     for _ in array_of_range {}
+   |              ^^^^^^^^^^^^^^ if you meant to iterate between two values, remove the square brackets
+   |
+   = help: the trait `std::iter::Iterator` is not implemented for `[std::ops::Range<{integer}>; 1]`
+   = note: `[start..end]` is an array of one `Range`; you might have meant to have a `Range` without the brackets: `start..end`
+   = note: required by `std::iter::IntoIterator::into_iter`
+
+error[E0277]: `[std::ops::Range<{integer}>; 2]` is not an iterator
+  --> $DIR/array-of-ranges.rs:19:14
+   |
+LL |     for _ in [0..1, 2..3] {}
+   |              ^^^^^^^^^^^^ borrow the array with `&` or call `.iter()` on it to iterate over it
+   |
+   = help: the trait `std::iter::Iterator` is not implemented for `[std::ops::Range<{integer}>; 2]`
+   = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]`
+   = note: required by `std::iter::IntoIterator::into_iter`
+
+error[E0277]: `[std::ops::RangeInclusive<{integer}>; 1]` is not an iterator
+  --> $DIR/array-of-ranges.rs:21:14
+   |
+LL |     for _ in [0..=1] {}
+   |              ^^^^^^^ if you meant to iterate between two values, remove the square brackets
+   |
+   = help: the trait `std::iter::Iterator` is not implemented for `[std::ops::RangeInclusive<{integer}>; 1]`
+   = note: `[start..=end]` is an array of one `RangeInclusive`; you might have meant to have a `RangeInclusive` without the brackets: `start..=end`
+   = note: required by `std::iter::IntoIterator::into_iter`
+
+error: aborting due to 9 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/iterators/array.rs b/src/test/ui/iterators/array.rs
new file mode 100644
index 0000000..33c84f6
--- /dev/null
+++ b/src/test/ui/iterators/array.rs
@@ -0,0 +1,9 @@
+fn main() {
+    for _ in [1, 2] {}
+//~^ ERROR is not an iterator
+    let x = [1, 2];
+    for _ in x {}
+//~^ ERROR is not an iterator
+    for _ in [1.0, 2.0] {}
+//~^ ERROR is not an iterator
+}
diff --git a/src/test/ui/iterators/array.stderr b/src/test/ui/iterators/array.stderr
new file mode 100644
index 0000000..94731f1
--- /dev/null
+++ b/src/test/ui/iterators/array.stderr
@@ -0,0 +1,33 @@
+error[E0277]: `[{integer}; 2]` is not an iterator
+  --> $DIR/array.rs:2:14
+   |
+LL |     for _ in [1, 2] {}
+   |              ^^^^^^ borrow the array with `&` or call `.iter()` on it to iterate over it
+   |
+   = help: the trait `std::iter::Iterator` is not implemented for `[{integer}; 2]`
+   = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]`
+   = note: required by `std::iter::IntoIterator::into_iter`
+
+error[E0277]: `[{integer}; 2]` is not an iterator
+  --> $DIR/array.rs:5:14
+   |
+LL |     for _ in x {}
+   |              ^ borrow the array with `&` or call `.iter()` on it to iterate over it
+   |
+   = help: the trait `std::iter::Iterator` is not implemented for `[{integer}; 2]`
+   = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]`
+   = note: required by `std::iter::IntoIterator::into_iter`
+
+error[E0277]: `[{float}; 2]` is not an iterator
+  --> $DIR/array.rs:7:14
+   |
+LL |     for _ in [1.0, 2.0] {}
+   |              ^^^^^^^^^^ borrow the array with `&` or call `.iter()` on it to iterate over it
+   |
+   = help: the trait `std::iter::Iterator` is not implemented for `[{float}; 2]`
+   = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]`
+   = note: required by `std::iter::IntoIterator::into_iter`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/iterators/bound.rs b/src/test/ui/iterators/bound.rs
new file mode 100644
index 0000000..bdd99ef
--- /dev/null
+++ b/src/test/ui/iterators/bound.rs
@@ -0,0 +1,4 @@
+struct S<I: Iterator>(I);
+struct T(S<u8>);
+//~^ ERROR is not an iterator
+fn main() {}
diff --git a/src/test/ui/iterators/bound.stderr b/src/test/ui/iterators/bound.stderr
new file mode 100644
index 0000000..1405738
--- /dev/null
+++ b/src/test/ui/iterators/bound.stderr
@@ -0,0 +1,17 @@
+error[E0277]: `u8` is not an iterator
+  --> $DIR/bound.rs:2:10
+   |
+LL | struct T(S<u8>);
+   |          ^^^^^ `u8` is not an iterator
+   |
+   = help: the trait `std::iter::Iterator` is not implemented for `u8`
+   = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
+note: required by `S`
+  --> $DIR/bound.rs:1:1
+   |
+LL | struct S<I: Iterator>(I);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/iterators/integral.rs b/src/test/ui/iterators/integral.rs
new file mode 100644
index 0000000..7537c79
--- /dev/null
+++ b/src/test/ui/iterators/integral.rs
@@ -0,0 +1,26 @@
+fn main() {
+    for _ in 42 {}
+    //~^ ERROR `{integer}` is not an iterator
+    for _ in 42 as u8 {}
+    //~^ ERROR `u8` is not an iterator
+    for _ in 42 as i8 {}
+    //~^ ERROR `i8` is not an iterator
+    for _ in 42 as u16 {}
+    //~^ ERROR `u16` is not an iterator
+    for _ in 42 as i16 {}
+    //~^ ERROR `i16` is not an iterator
+    for _ in 42 as u32 {}
+    //~^ ERROR `u32` is not an iterator
+    for _ in 42 as i32 {}
+    //~^ ERROR `i32` is not an iterator
+    for _ in 42 as u64 {}
+    //~^ ERROR `u64` is not an iterator
+    for _ in 42 as i64 {}
+    //~^ ERROR `i64` is not an iterator
+    for _ in 42 as usize {}
+    //~^ ERROR `usize` is not an iterator
+    for _ in 42 as isize {}
+    //~^ ERROR `isize` is not an iterator
+    for _ in 42.0 {}
+    //~^ ERROR `{float}` is not an iterator
+}
diff --git a/src/test/ui/iterators/integral.stderr b/src/test/ui/iterators/integral.stderr
new file mode 100644
index 0000000..71e1e81
--- /dev/null
+++ b/src/test/ui/iterators/integral.stderr
@@ -0,0 +1,122 @@
+error[E0277]: `{integer}` is not an iterator
+  --> $DIR/integral.rs:2:14
+   |
+LL |     for _ in 42 {}
+   |              ^^ `{integer}` is not an iterator
+   |
+   = help: the trait `std::iter::Iterator` is not implemented for `{integer}`
+   = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
+   = note: required by `std::iter::IntoIterator::into_iter`
+
+error[E0277]: `u8` is not an iterator
+  --> $DIR/integral.rs:4:14
+   |
+LL |     for _ in 42 as u8 {}
+   |              ^^^^^^^^ `u8` is not an iterator
+   |
+   = help: the trait `std::iter::Iterator` is not implemented for `u8`
+   = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
+   = note: required by `std::iter::IntoIterator::into_iter`
+
+error[E0277]: `i8` is not an iterator
+  --> $DIR/integral.rs:6:14
+   |
+LL |     for _ in 42 as i8 {}
+   |              ^^^^^^^^ `i8` is not an iterator
+   |
+   = help: the trait `std::iter::Iterator` is not implemented for `i8`
+   = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
+   = note: required by `std::iter::IntoIterator::into_iter`
+
+error[E0277]: `u16` is not an iterator
+  --> $DIR/integral.rs:8:14
+   |
+LL |     for _ in 42 as u16 {}
+   |              ^^^^^^^^^ `u16` is not an iterator
+   |
+   = help: the trait `std::iter::Iterator` is not implemented for `u16`
+   = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
+   = note: required by `std::iter::IntoIterator::into_iter`
+
+error[E0277]: `i16` is not an iterator
+  --> $DIR/integral.rs:10:14
+   |
+LL |     for _ in 42 as i16 {}
+   |              ^^^^^^^^^ `i16` is not an iterator
+   |
+   = help: the trait `std::iter::Iterator` is not implemented for `i16`
+   = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
+   = note: required by `std::iter::IntoIterator::into_iter`
+
+error[E0277]: `u32` is not an iterator
+  --> $DIR/integral.rs:12:14
+   |
+LL |     for _ in 42 as u32 {}
+   |              ^^^^^^^^^ `u32` is not an iterator
+   |
+   = help: the trait `std::iter::Iterator` is not implemented for `u32`
+   = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
+   = note: required by `std::iter::IntoIterator::into_iter`
+
+error[E0277]: `i32` is not an iterator
+  --> $DIR/integral.rs:14:14
+   |
+LL |     for _ in 42 as i32 {}
+   |              ^^^^^^^^^ `i32` is not an iterator
+   |
+   = help: the trait `std::iter::Iterator` is not implemented for `i32`
+   = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
+   = note: required by `std::iter::IntoIterator::into_iter`
+
+error[E0277]: `u64` is not an iterator
+  --> $DIR/integral.rs:16:14
+   |
+LL |     for _ in 42 as u64 {}
+   |              ^^^^^^^^^ `u64` is not an iterator
+   |
+   = help: the trait `std::iter::Iterator` is not implemented for `u64`
+   = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
+   = note: required by `std::iter::IntoIterator::into_iter`
+
+error[E0277]: `i64` is not an iterator
+  --> $DIR/integral.rs:18:14
+   |
+LL |     for _ in 42 as i64 {}
+   |              ^^^^^^^^^ `i64` is not an iterator
+   |
+   = help: the trait `std::iter::Iterator` is not implemented for `i64`
+   = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
+   = note: required by `std::iter::IntoIterator::into_iter`
+
+error[E0277]: `usize` is not an iterator
+  --> $DIR/integral.rs:20:14
+   |
+LL |     for _ in 42 as usize {}
+   |              ^^^^^^^^^^^ `usize` is not an iterator
+   |
+   = help: the trait `std::iter::Iterator` is not implemented for `usize`
+   = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
+   = note: required by `std::iter::IntoIterator::into_iter`
+
+error[E0277]: `isize` is not an iterator
+  --> $DIR/integral.rs:22:14
+   |
+LL |     for _ in 42 as isize {}
+   |              ^^^^^^^^^^^ `isize` is not an iterator
+   |
+   = help: the trait `std::iter::Iterator` is not implemented for `isize`
+   = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
+   = note: required by `std::iter::IntoIterator::into_iter`
+
+error[E0277]: `{float}` is not an iterator
+  --> $DIR/integral.rs:24:14
+   |
+LL |     for _ in 42.0 {}
+   |              ^^^^ `{float}` is not an iterator
+   |
+   = help: the trait `std::iter::Iterator` is not implemented for `{float}`
+   = note: required by `std::iter::IntoIterator::into_iter`
+
+error: aborting due to 12 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/iterators/ranges.rs b/src/test/ui/iterators/ranges.rs
new file mode 100644
index 0000000..925d2d6
--- /dev/null
+++ b/src/test/ui/iterators/ranges.rs
@@ -0,0 +1,9 @@
+fn main() {
+    for _ in ..10 {}
+    //~^ ERROR E0277
+    for _ in ..=10 {}
+    //~^ ERROR E0277
+    for _ in 0..10 {}
+    for _ in 0..=10 {}
+    for _ in 0.. {}
+}
diff --git a/src/test/ui/iterators/ranges.stderr b/src/test/ui/iterators/ranges.stderr
new file mode 100644
index 0000000..e5e2d87
--- /dev/null
+++ b/src/test/ui/iterators/ranges.stderr
@@ -0,0 +1,23 @@
+error[E0277]: `std::ops::RangeTo<{integer}>` is not an iterator
+  --> $DIR/ranges.rs:2:14
+   |
+LL |     for _ in ..10 {}
+   |              ^^^^ if you meant to iterate until a value, add a starting value
+   |
+   = help: the trait `std::iter::Iterator` is not implemented for `std::ops::RangeTo<{integer}>`
+   = note: `..end` is a `RangeTo`, which cannot be iterated on; you might have meant to have a bounded `Range`: `0..end`
+   = note: required by `std::iter::IntoIterator::into_iter`
+
+error[E0277]: `std::ops::RangeToInclusive<{integer}>` is not an iterator
+  --> $DIR/ranges.rs:4:14
+   |
+LL |     for _ in ..=10 {}
+   |              ^^^^^ if you meant to iterate until a value (including it), add a starting value
+   |
+   = help: the trait `std::iter::Iterator` is not implemented for `std::ops::RangeToInclusive<{integer}>`
+   = note: `..=end` is a `RangeToInclusive`, which cannot be iterated on; you might have meant to have a bounded `RangeInclusive`: `0..=end`
+   = note: required by `std::iter::IntoIterator::into_iter`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/iterators/string.rs b/src/test/ui/iterators/string.rs
new file mode 100644
index 0000000..4373dca
--- /dev/null
+++ b/src/test/ui/iterators/string.rs
@@ -0,0 +1,6 @@
+fn main() {
+    for _ in "".to_owned() {}
+    //~^ ERROR `std::string::String` is not an iterator
+    for _ in "" {}
+    //~^ ERROR `&str` is not an iterator
+}
diff --git a/src/test/ui/iterators/string.stderr b/src/test/ui/iterators/string.stderr
new file mode 100644
index 0000000..927de95
--- /dev/null
+++ b/src/test/ui/iterators/string.stderr
@@ -0,0 +1,21 @@
+error[E0277]: `std::string::String` is not an iterator
+  --> $DIR/string.rs:2:14
+   |
+LL |     for _ in "".to_owned() {}
+   |              ^^^^^^^^^^^^^ `std::string::String` is not an iterator; try calling `.chars()` or `.bytes()`
+   |
+   = help: the trait `std::iter::Iterator` is not implemented for `std::string::String`
+   = note: required by `std::iter::IntoIterator::into_iter`
+
+error[E0277]: `&str` is not an iterator
+  --> $DIR/string.rs:4:14
+   |
+LL |     for _ in "" {}
+   |              ^^ `&str` is not an iterator; try calling `.chars()` or `.bytes()`
+   |
+   = help: the trait `std::iter::Iterator` is not implemented for `&str`
+   = note: required by `std::iter::IntoIterator::into_iter`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/keyword/extern/keyword-extern-as-identifier-expr.rs b/src/test/ui/keyword/extern/keyword-extern-as-identifier-expr.rs
new file mode 100644
index 0000000..b738eb4
--- /dev/null
+++ b/src/test/ui/keyword/extern/keyword-extern-as-identifier-expr.rs
@@ -0,0 +1,3 @@
+fn main() {
+    let s = extern::foo::Bar; //~ ERROR expected expression, found keyword `extern`
+}
diff --git a/src/test/ui/keyword/extern/keyword-extern-as-identifier-expr.stderr b/src/test/ui/keyword/extern/keyword-extern-as-identifier-expr.stderr
new file mode 100644
index 0000000..8bb89d2
--- /dev/null
+++ b/src/test/ui/keyword/extern/keyword-extern-as-identifier-expr.stderr
@@ -0,0 +1,8 @@
+error: expected expression, found keyword `extern`
+  --> $DIR/keyword-extern-as-identifier-expr.rs:2:13
+   |
+LL |     let s = extern::foo::Bar;
+   |             ^^^^^^ expected expression
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/keyword/extern/keyword-extern-as-identifier-pat.rs b/src/test/ui/keyword/extern/keyword-extern-as-identifier-pat.rs
new file mode 100644
index 0000000..f9b6bad
--- /dev/null
+++ b/src/test/ui/keyword/extern/keyword-extern-as-identifier-pat.rs
@@ -0,0 +1,3 @@
+fn main() {
+    let extern = 0; //~ ERROR expected pattern, found keyword `extern`
+}
diff --git a/src/test/ui/keyword/extern/keyword-extern-as-identifier-pat.stderr b/src/test/ui/keyword/extern/keyword-extern-as-identifier-pat.stderr
new file mode 100644
index 0000000..d7b9ad2
--- /dev/null
+++ b/src/test/ui/keyword/extern/keyword-extern-as-identifier-pat.stderr
@@ -0,0 +1,8 @@
+error: expected pattern, found keyword `extern`
+  --> $DIR/keyword-extern-as-identifier-pat.rs:2:9
+   |
+LL |     let extern = 0;
+   |         ^^^^^^ expected pattern
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/keyword/extern/keyword-extern-as-identifier-type.rs b/src/test/ui/keyword/extern/keyword-extern-as-identifier-type.rs
new file mode 100644
index 0000000..3845a9a
--- /dev/null
+++ b/src/test/ui/keyword/extern/keyword-extern-as-identifier-type.rs
@@ -0,0 +1,3 @@
+type A = extern::foo::bar; //~ ERROR expected `fn`, found `::`
+
+fn main() {}
diff --git a/src/test/ui/keyword/extern/keyword-extern-as-identifier-type.stderr b/src/test/ui/keyword/extern/keyword-extern-as-identifier-type.stderr
new file mode 100644
index 0000000..447c76a
--- /dev/null
+++ b/src/test/ui/keyword/extern/keyword-extern-as-identifier-type.stderr
@@ -0,0 +1,8 @@
+error: expected `fn`, found `::`
+  --> $DIR/keyword-extern-as-identifier-type.rs:1:16
+   |
+LL | type A = extern::foo::bar;
+   |                ^^ expected `fn` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.rs b/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.rs
new file mode 100644
index 0000000..b07de3e
--- /dev/null
+++ b/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.rs
@@ -0,0 +1,3 @@
+use extern::foo; //~ ERROR expected identifier, found keyword `extern`
+
+fn main() {}
diff --git a/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.stderr b/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.stderr
new file mode 100644
index 0000000..4b833f8
--- /dev/null
+++ b/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.stderr
@@ -0,0 +1,12 @@
+error: expected identifier, found keyword `extern`
+  --> $DIR/keyword-extern-as-identifier-use.rs:1:5
+   |
+LL | use extern::foo;
+   |     ^^^^^^ expected identifier, found keyword
+help: you can escape reserved keywords to use them as identifiers
+   |
+LL | use r#extern::foo;
+   |     ^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/keyword/keyword-false-as-identifier.rs b/src/test/ui/keyword/keyword-false-as-identifier.rs
new file mode 100644
index 0000000..6382f84
--- /dev/null
+++ b/src/test/ui/keyword/keyword-false-as-identifier.rs
@@ -0,0 +1,3 @@
+fn main() {
+    let false = 22; //~ error: mismatched types
+}
diff --git a/src/test/ui/keyword/keyword-false-as-identifier.stderr b/src/test/ui/keyword/keyword-false-as-identifier.stderr
new file mode 100644
index 0000000..9544604
--- /dev/null
+++ b/src/test/ui/keyword/keyword-false-as-identifier.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/keyword-false-as-identifier.rs:2:9
+   |
+LL |     let false = 22;
+   |         ^^^^^ expected integer, found bool
+   |
+   = note: expected type `{integer}`
+              found type `bool`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/keyword/keyword-self-as-identifier.rs b/src/test/ui/keyword/keyword-self-as-identifier.rs
new file mode 100644
index 0000000..b30002c
--- /dev/null
+++ b/src/test/ui/keyword/keyword-self-as-identifier.rs
@@ -0,0 +1,3 @@
+fn main() {
+    let Self = 22; //~ ERROR cannot find unit struct/variant or constant `Self` in this scope
+}
diff --git a/src/test/ui/keyword/keyword-self-as-identifier.stderr b/src/test/ui/keyword/keyword-self-as-identifier.stderr
new file mode 100644
index 0000000..be57c6a
--- /dev/null
+++ b/src/test/ui/keyword/keyword-self-as-identifier.stderr
@@ -0,0 +1,9 @@
+error[E0531]: cannot find unit struct/variant or constant `Self` in this scope
+  --> $DIR/keyword-self-as-identifier.rs:2:9
+   |
+LL |     let Self = 22;
+   |         ^^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0531`.
diff --git a/src/test/ui/keyword/keyword-super-as-identifier.rs b/src/test/ui/keyword/keyword-super-as-identifier.rs
new file mode 100644
index 0000000..d728b4f
--- /dev/null
+++ b/src/test/ui/keyword/keyword-super-as-identifier.rs
@@ -0,0 +1,3 @@
+fn main() {
+    let super = 22; //~ ERROR failed to resolve: there are too many initial `super`s
+}
diff --git a/src/test/ui/keyword/keyword-super-as-identifier.stderr b/src/test/ui/keyword/keyword-super-as-identifier.stderr
new file mode 100644
index 0000000..bbeaed9
--- /dev/null
+++ b/src/test/ui/keyword/keyword-super-as-identifier.stderr
@@ -0,0 +1,9 @@
+error[E0433]: failed to resolve: there are too many initial `super`s.
+  --> $DIR/keyword-super-as-identifier.rs:2:9
+   |
+LL |     let super = 22;
+   |         ^^^^^ there are too many initial `super`s.
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/keyword/keyword-super.rs b/src/test/ui/keyword/keyword-super.rs
new file mode 100644
index 0000000..a43e1e3
--- /dev/null
+++ b/src/test/ui/keyword/keyword-super.rs
@@ -0,0 +1,3 @@
+fn main() {
+    let super: isize; //~ ERROR failed to resolve: there are too many initial `super`s
+}
diff --git a/src/test/ui/keyword/keyword-super.stderr b/src/test/ui/keyword/keyword-super.stderr
new file mode 100644
index 0000000..63394c7
--- /dev/null
+++ b/src/test/ui/keyword/keyword-super.stderr
@@ -0,0 +1,9 @@
+error[E0433]: failed to resolve: there are too many initial `super`s.
+  --> $DIR/keyword-super.rs:2:9
+   |
+LL |     let super: isize;
+   |         ^^^^^ there are too many initial `super`s.
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/keyword/keyword-true-as-identifier.rs b/src/test/ui/keyword/keyword-true-as-identifier.rs
new file mode 100644
index 0000000..8c4ad7e
--- /dev/null
+++ b/src/test/ui/keyword/keyword-true-as-identifier.rs
@@ -0,0 +1,3 @@
+fn main() {
+    let true = 22; //~ error: mismatched types
+}
diff --git a/src/test/ui/keyword/keyword-true-as-identifier.stderr b/src/test/ui/keyword/keyword-true-as-identifier.stderr
new file mode 100644
index 0000000..36b1d88
--- /dev/null
+++ b/src/test/ui/keyword/keyword-true-as-identifier.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/keyword-true-as-identifier.rs:2:9
+   |
+LL |     let true = 22;
+   |         ^^^^ expected integer, found bool
+   |
+   = note: expected type `{integer}`
+              found type `bool`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/kindck/kindck-copy.rs b/src/test/ui/kindck/kindck-copy.rs
new file mode 100644
index 0000000..dadeb95
--- /dev/null
+++ b/src/test/ui/kindck/kindck-copy.rs
@@ -0,0 +1,71 @@
+// Test which of the builtin types are considered POD.
+
+use std::rc::Rc;
+
+fn assert_copy<T:Copy>() { }
+
+trait Dummy { }
+
+#[derive(Copy, Clone)]
+struct MyStruct {
+    x: isize,
+    y: isize,
+}
+
+struct MyNoncopyStruct {
+    x: Box<char>,
+}
+
+fn test<'a,T,U:Copy>(_: &'a isize) {
+    // lifetime pointers are ok...
+    assert_copy::<&'static isize>();
+    assert_copy::<&'a isize>();
+    assert_copy::<&'a str>();
+    assert_copy::<&'a [isize]>();
+
+    // ...unless they are mutable
+    assert_copy::<&'static mut isize>(); //~ ERROR : std::marker::Copy` is not satisfied
+    assert_copy::<&'a mut isize>();  //~ ERROR : std::marker::Copy` is not satisfied
+
+    // boxes are not ok
+    assert_copy::<Box<isize>>();   //~ ERROR : std::marker::Copy` is not satisfied
+    assert_copy::<String>();   //~ ERROR : std::marker::Copy` is not satisfied
+    assert_copy::<Vec<isize> >(); //~ ERROR : std::marker::Copy` is not satisfied
+    assert_copy::<Box<&'a mut isize>>(); //~ ERROR : std::marker::Copy` is not satisfied
+
+    // borrowed object types are generally ok
+    assert_copy::<&'a Dummy>();
+    assert_copy::<&'a (Dummy+Send)>();
+    assert_copy::<&'static (Dummy+Send)>();
+
+    // owned object types are not ok
+    assert_copy::<Box<Dummy>>(); //~ ERROR : std::marker::Copy` is not satisfied
+    assert_copy::<Box<Dummy+Send>>(); //~ ERROR : std::marker::Copy` is not satisfied
+
+    // mutable object types are not ok
+    assert_copy::<&'a mut (Dummy+Send)>();  //~ ERROR : std::marker::Copy` is not satisfied
+
+    // unsafe ptrs are ok
+    assert_copy::<*const isize>();
+    assert_copy::<*const &'a mut isize>();
+
+    // regular old ints and such are ok
+    assert_copy::<isize>();
+    assert_copy::<bool>();
+    assert_copy::<()>();
+
+    // tuples are ok
+    assert_copy::<(isize,isize)>();
+
+    // structs of POD are ok
+    assert_copy::<MyStruct>();
+
+    // structs containing non-POD are not ok
+    assert_copy::<MyNoncopyStruct>(); //~ ERROR : std::marker::Copy` is not satisfied
+
+    // ref counted types are not ok
+    assert_copy::<Rc<isize>>();   //~ ERROR : std::marker::Copy` is not satisfied
+}
+
+pub fn main() {
+}
diff --git a/src/test/ui/kindck/kindck-copy.stderr b/src/test/ui/kindck/kindck-copy.stderr
new file mode 100644
index 0000000..2680cb7
--- /dev/null
+++ b/src/test/ui/kindck/kindck-copy.stderr
@@ -0,0 +1,139 @@
+error[E0277]: the trait bound `&'static mut isize: std::marker::Copy` is not satisfied
+  --> $DIR/kindck-copy.rs:27:5
+   |
+LL |     assert_copy::<&'static mut isize>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `&'static mut isize`
+   |
+   = help: the following implementations were found:
+             <isize as std::marker::Copy>
+note: required by `assert_copy`
+  --> $DIR/kindck-copy.rs:5:1
+   |
+LL | fn assert_copy<T:Copy>() { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `&'a mut isize: std::marker::Copy` is not satisfied
+  --> $DIR/kindck-copy.rs:28:5
+   |
+LL |     assert_copy::<&'a mut isize>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `&'a mut isize`
+   |
+   = help: the following implementations were found:
+             <isize as std::marker::Copy>
+note: required by `assert_copy`
+  --> $DIR/kindck-copy.rs:5:1
+   |
+LL | fn assert_copy<T:Copy>() { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `std::boxed::Box<isize>: std::marker::Copy` is not satisfied
+  --> $DIR/kindck-copy.rs:31:5
+   |
+LL |     assert_copy::<Box<isize>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::boxed::Box<isize>`
+   |
+note: required by `assert_copy`
+  --> $DIR/kindck-copy.rs:5:1
+   |
+LL | fn assert_copy<T:Copy>() { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied
+  --> $DIR/kindck-copy.rs:32:5
+   |
+LL |     assert_copy::<String>();
+   |     ^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String`
+   |
+note: required by `assert_copy`
+  --> $DIR/kindck-copy.rs:5:1
+   |
+LL | fn assert_copy<T:Copy>() { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `std::vec::Vec<isize>: std::marker::Copy` is not satisfied
+  --> $DIR/kindck-copy.rs:33:5
+   |
+LL |     assert_copy::<Vec<isize> >();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::vec::Vec<isize>`
+   |
+note: required by `assert_copy`
+  --> $DIR/kindck-copy.rs:5:1
+   |
+LL | fn assert_copy<T:Copy>() { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `std::boxed::Box<&'a mut isize>: std::marker::Copy` is not satisfied
+  --> $DIR/kindck-copy.rs:34:5
+   |
+LL |     assert_copy::<Box<&'a mut isize>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::boxed::Box<&'a mut isize>`
+   |
+note: required by `assert_copy`
+  --> $DIR/kindck-copy.rs:5:1
+   |
+LL | fn assert_copy<T:Copy>() { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `std::boxed::Box<dyn Dummy>: std::marker::Copy` is not satisfied
+  --> $DIR/kindck-copy.rs:42:5
+   |
+LL |     assert_copy::<Box<Dummy>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::boxed::Box<dyn Dummy>`
+   |
+note: required by `assert_copy`
+  --> $DIR/kindck-copy.rs:5:1
+   |
+LL | fn assert_copy<T:Copy>() { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `std::boxed::Box<dyn Dummy + std::marker::Send>: std::marker::Copy` is not satisfied
+  --> $DIR/kindck-copy.rs:43:5
+   |
+LL |     assert_copy::<Box<Dummy+Send>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::boxed::Box<dyn Dummy + std::marker::Send>`
+   |
+note: required by `assert_copy`
+  --> $DIR/kindck-copy.rs:5:1
+   |
+LL | fn assert_copy<T:Copy>() { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `&'a mut (dyn Dummy + std::marker::Send + 'a): std::marker::Copy` is not satisfied
+  --> $DIR/kindck-copy.rs:46:5
+   |
+LL |     assert_copy::<&'a mut (Dummy+Send)>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `&'a mut (dyn Dummy + std::marker::Send + 'a)`
+   |
+note: required by `assert_copy`
+  --> $DIR/kindck-copy.rs:5:1
+   |
+LL | fn assert_copy<T:Copy>() { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `MyNoncopyStruct: std::marker::Copy` is not satisfied
+  --> $DIR/kindck-copy.rs:64:5
+   |
+LL |     assert_copy::<MyNoncopyStruct>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `MyNoncopyStruct`
+   |
+note: required by `assert_copy`
+  --> $DIR/kindck-copy.rs:5:1
+   |
+LL | fn assert_copy<T:Copy>() { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `std::rc::Rc<isize>: std::marker::Copy` is not satisfied
+  --> $DIR/kindck-copy.rs:67:5
+   |
+LL |     assert_copy::<Rc<isize>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::rc::Rc<isize>`
+   |
+note: required by `assert_copy`
+  --> $DIR/kindck-copy.rs:5:1
+   |
+LL | fn assert_copy<T:Copy>() { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 11 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/kindck/kindck-impl-type-params-2.rs b/src/test/ui/kindck/kindck-impl-type-params-2.rs
new file mode 100644
index 0000000..ac9cc1a
--- /dev/null
+++ b/src/test/ui/kindck/kindck-impl-type-params-2.rs
@@ -0,0 +1,15 @@
+#![feature(box_syntax)]
+
+trait Foo {
+}
+
+impl<T:Copy> Foo for T {
+}
+
+fn take_param<T:Foo>(foo: &T) { }
+
+fn main() {
+    let x: Box<_> = box 3;
+    take_param(&x);
+    //~^ ERROR `std::boxed::Box<{integer}>: std::marker::Copy` is not satisfied
+}
diff --git a/src/test/ui/kindck/kindck-impl-type-params-2.stderr b/src/test/ui/kindck/kindck-impl-type-params-2.stderr
new file mode 100644
index 0000000..bd971c9
--- /dev/null
+++ b/src/test/ui/kindck/kindck-impl-type-params-2.stderr
@@ -0,0 +1,16 @@
+error[E0277]: the trait bound `std::boxed::Box<{integer}>: std::marker::Copy` is not satisfied
+  --> $DIR/kindck-impl-type-params-2.rs:13:5
+   |
+LL |     take_param(&x);
+   |     ^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::boxed::Box<{integer}>`
+   |
+   = note: required because of the requirements on the impl of `Foo` for `std::boxed::Box<{integer}>`
+note: required by `take_param`
+  --> $DIR/kindck-impl-type-params-2.rs:9:1
+   |
+LL | fn take_param<T:Foo>(foo: &T) { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/kindck/kindck-impl-type-params.rs b/src/test/ui/kindck/kindck-impl-type-params.rs
new file mode 100644
index 0000000..a47e418
--- /dev/null
+++ b/src/test/ui/kindck/kindck-impl-type-params.rs
@@ -0,0 +1,50 @@
+// Issue #14061: tests the interaction between generic implementation
+// parameter bounds and trait objects.
+
+#![feature(box_syntax)]
+
+use std::marker;
+
+struct S<T>(marker::PhantomData<T>);
+
+trait Gettable<T> {
+    fn get(&self) -> T { panic!() }
+}
+
+impl<T: Send + Copy + 'static> Gettable<T> for S<T> {}
+
+fn f<T>(val: T) {
+    let t: S<T> = S(marker::PhantomData);
+    let a = &t as &Gettable<T>;
+    //~^ ERROR `T` cannot be sent between threads safely
+    //~| ERROR : std::marker::Copy` is not satisfied
+}
+
+fn g<T>(val: T) {
+    let t: S<T> = S(marker::PhantomData);
+    let a: &Gettable<T> = &t;
+    //~^ ERROR `T` cannot be sent between threads safely
+    //~| ERROR : std::marker::Copy` is not satisfied
+}
+
+fn foo<'a>() {
+    let t: S<&'a isize> = S(marker::PhantomData);
+    let a = &t as &Gettable<&'a isize>;
+    //~^ ERROR does not fulfill
+}
+
+fn foo2<'a>() {
+    let t: Box<S<String>> = box S(marker::PhantomData);
+    let a = t as Box<Gettable<String>>;
+    //~^ ERROR : std::marker::Copy` is not satisfied
+}
+
+fn foo3<'a>() {
+    struct Foo; // does not impl Copy
+
+    let t: Box<S<Foo>> = box S(marker::PhantomData);
+    let a: Box<Gettable<Foo>> = t;
+    //~^ ERROR : std::marker::Copy` is not satisfied
+}
+
+fn main() { }
diff --git a/src/test/ui/kindck/kindck-impl-type-params.stderr b/src/test/ui/kindck/kindck-impl-type-params.stderr
new file mode 100644
index 0000000..03cd480
--- /dev/null
+++ b/src/test/ui/kindck/kindck-impl-type-params.stderr
@@ -0,0 +1,72 @@
+error[E0277]: `T` cannot be sent between threads safely
+  --> $DIR/kindck-impl-type-params.rs:18:13
+   |
+LL |     let a = &t as &Gettable<T>;
+   |             ^^ `T` cannot be sent between threads safely
+   |
+   = help: the trait `std::marker::Send` is not implemented for `T`
+   = help: consider adding a `where T: std::marker::Send` bound
+   = note: required because of the requirements on the impl of `Gettable<T>` for `S<T>`
+   = note: required for the cast to the object type `dyn Gettable<T>`
+
+error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
+  --> $DIR/kindck-impl-type-params.rs:18:13
+   |
+LL |     let a = &t as &Gettable<T>;
+   |             ^^ the trait `std::marker::Copy` is not implemented for `T`
+   |
+   = help: consider adding a `where T: std::marker::Copy` bound
+   = note: required because of the requirements on the impl of `Gettable<T>` for `S<T>`
+   = note: required for the cast to the object type `dyn Gettable<T>`
+
+error[E0277]: `T` cannot be sent between threads safely
+  --> $DIR/kindck-impl-type-params.rs:25:27
+   |
+LL |     let a: &Gettable<T> = &t;
+   |                           ^^ `T` cannot be sent between threads safely
+   |
+   = help: the trait `std::marker::Send` is not implemented for `T`
+   = help: consider adding a `where T: std::marker::Send` bound
+   = note: required because of the requirements on the impl of `Gettable<T>` for `S<T>`
+   = note: required for the cast to the object type `dyn Gettable<T>`
+
+error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
+  --> $DIR/kindck-impl-type-params.rs:25:27
+   |
+LL |     let a: &Gettable<T> = &t;
+   |                           ^^ the trait `std::marker::Copy` is not implemented for `T`
+   |
+   = help: consider adding a `where T: std::marker::Copy` bound
+   = note: required because of the requirements on the impl of `Gettable<T>` for `S<T>`
+   = note: required for the cast to the object type `dyn Gettable<T>`
+
+error[E0477]: the type `&'a isize` does not fulfill the required lifetime
+  --> $DIR/kindck-impl-type-params.rs:32:13
+   |
+LL |     let a = &t as &Gettable<&'a isize>;
+   |             ^^
+   |
+   = note: type must satisfy the static lifetime
+
+error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied
+  --> $DIR/kindck-impl-type-params.rs:38:13
+   |
+LL |     let a = t as Box<Gettable<String>>;
+   |             ^ the trait `std::marker::Copy` is not implemented for `std::string::String`
+   |
+   = note: required because of the requirements on the impl of `Gettable<std::string::String>` for `S<std::string::String>`
+   = note: required for the cast to the object type `dyn Gettable<std::string::String>`
+
+error[E0277]: the trait bound `foo3::Foo: std::marker::Copy` is not satisfied
+  --> $DIR/kindck-impl-type-params.rs:46:33
+   |
+LL |     let a: Box<Gettable<Foo>> = t;
+   |                                 ^ the trait `std::marker::Copy` is not implemented for `foo3::Foo`
+   |
+   = note: required because of the requirements on the impl of `Gettable<foo3::Foo>` for `S<foo3::Foo>`
+   = note: required for the cast to the object type `dyn Gettable<foo3::Foo>`
+
+error: aborting due to 7 previous errors
+
+Some errors occurred: E0277, E0477.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/kindck/kindck-inherited-copy-bound.rs b/src/test/ui/kindck/kindck-inherited-copy-bound.rs
new file mode 100644
index 0000000..0134636
--- /dev/null
+++ b/src/test/ui/kindck/kindck-inherited-copy-bound.rs
@@ -0,0 +1,29 @@
+// Test that Copy bounds inherited by trait are checked.
+
+#![feature(box_syntax)]
+
+use std::any::Any;
+
+trait Foo : Copy {
+    fn foo(&self) {}
+}
+
+impl<T:Copy> Foo for T {
+}
+
+fn take_param<T:Foo>(foo: &T) { }
+
+fn a() {
+    let x: Box<_> = box 3;
+    take_param(&x); //~ ERROR E0277
+}
+
+fn b() {
+    let x: Box<_> = box 3;
+    let y = &x;
+    let z = &x as &Foo;
+    //~^ ERROR E0038
+    //~| ERROR E0038
+}
+
+fn main() { }
diff --git a/src/test/ui/kindck/kindck-inherited-copy-bound.stderr b/src/test/ui/kindck/kindck-inherited-copy-bound.stderr
new file mode 100644
index 0000000..1b7f9cd
--- /dev/null
+++ b/src/test/ui/kindck/kindck-inherited-copy-bound.stderr
@@ -0,0 +1,34 @@
+error[E0277]: the trait bound `std::boxed::Box<{integer}>: std::marker::Copy` is not satisfied
+  --> $DIR/kindck-inherited-copy-bound.rs:18:5
+   |
+LL |     take_param(&x);
+   |     ^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::boxed::Box<{integer}>`
+   |
+   = note: required because of the requirements on the impl of `Foo` for `std::boxed::Box<{integer}>`
+note: required by `take_param`
+  --> $DIR/kindck-inherited-copy-bound.rs:14:1
+   |
+LL | fn take_param<T:Foo>(foo: &T) { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0038]: the trait `Foo` cannot be made into an object
+  --> $DIR/kindck-inherited-copy-bound.rs:24:19
+   |
+LL |     let z = &x as &Foo;
+   |                   ^^^^ the trait `Foo` cannot be made into an object
+   |
+   = note: the trait cannot require that `Self : Sized`
+
+error[E0038]: the trait `Foo` cannot be made into an object
+  --> $DIR/kindck-inherited-copy-bound.rs:24:13
+   |
+LL |     let z = &x as &Foo;
+   |             ^^ the trait `Foo` cannot be made into an object
+   |
+   = note: the trait cannot require that `Self : Sized`
+   = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Foo>` for `&std::boxed::Box<{integer}>`
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0038, E0277.
+For more information about an error, try `rustc --explain E0038`.
diff --git a/src/test/ui/kindck/kindck-nonsendable-1.rs b/src/test/ui/kindck/kindck-nonsendable-1.rs
new file mode 100644
index 0000000..eaff5b1
--- /dev/null
+++ b/src/test/ui/kindck/kindck-nonsendable-1.rs
@@ -0,0 +1,11 @@
+use std::rc::Rc;
+
+fn foo(_x: Rc<usize>) {}
+
+fn bar<F:FnOnce() + Send>(_: F) { }
+
+fn main() {
+    let x = Rc::new(3);
+    bar(move|| foo(x));
+    //~^ ERROR `std::rc::Rc<usize>` cannot be sent between threads safely
+}
diff --git a/src/test/ui/kindck/kindck-nonsendable-1.stderr b/src/test/ui/kindck/kindck-nonsendable-1.stderr
new file mode 100644
index 0000000..2aacd27
--- /dev/null
+++ b/src/test/ui/kindck/kindck-nonsendable-1.stderr
@@ -0,0 +1,17 @@
+error[E0277]: `std::rc::Rc<usize>` cannot be sent between threads safely
+  --> $DIR/kindck-nonsendable-1.rs:9:5
+   |
+LL |     bar(move|| foo(x));
+   |     ^^^ `std::rc::Rc<usize>` cannot be sent between threads safely
+   |
+   = help: within `[closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:22 x:std::rc::Rc<usize>]`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<usize>`
+   = note: required because it appears within the type `[closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:22 x:std::rc::Rc<usize>]`
+note: required by `bar`
+  --> $DIR/kindck-nonsendable-1.rs:5:1
+   |
+LL | fn bar<F:FnOnce() + Send>(_: F) { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/kindck/kindck-send-object.rs b/src/test/ui/kindck/kindck-send-object.rs
new file mode 100644
index 0000000..97f46c3
--- /dev/null
+++ b/src/test/ui/kindck/kindck-send-object.rs
@@ -0,0 +1,26 @@
+// Test which of the builtin types are considered sendable. The tests
+// in this file all test the "kind" violates detected during kindck.
+// See all `regions-bounded-by-send.rs`
+
+fn assert_send<T:Send>() { }
+trait Dummy { }
+trait Message : Send { }
+
+// careful with object types, who knows what they close over...
+
+fn object_ref_with_static_bound_not_ok() {
+    assert_send::<&'static (Dummy+'static)>();
+    //~^ ERROR `(dyn Dummy + 'static)` cannot be shared between threads safely [E0277]
+}
+
+fn box_object_with_no_bound_not_ok<'a>() {
+    assert_send::<Box<Dummy>>();
+    //~^ ERROR `dyn Dummy` cannot be sent between threads safely
+}
+
+fn object_with_send_bound_ok() {
+    assert_send::<&'static (Dummy+Sync)>();
+    assert_send::<Box<Dummy+Send>>();
+}
+
+fn main() { }
diff --git a/src/test/ui/kindck/kindck-send-object.stderr b/src/test/ui/kindck/kindck-send-object.stderr
new file mode 100644
index 0000000..8d99356
--- /dev/null
+++ b/src/test/ui/kindck/kindck-send-object.stderr
@@ -0,0 +1,32 @@
+error[E0277]: `(dyn Dummy + 'static)` cannot be shared between threads safely
+  --> $DIR/kindck-send-object.rs:12:5
+   |
+LL |     assert_send::<&'static (Dummy+'static)>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'static)` cannot be shared between threads safely
+   |
+   = help: the trait `std::marker::Sync` is not implemented for `(dyn Dummy + 'static)`
+   = note: required because of the requirements on the impl of `std::marker::Send` for `&'static (dyn Dummy + 'static)`
+note: required by `assert_send`
+  --> $DIR/kindck-send-object.rs:5:1
+   |
+LL | fn assert_send<T:Send>() { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: `dyn Dummy` cannot be sent between threads safely
+  --> $DIR/kindck-send-object.rs:17:5
+   |
+LL |     assert_send::<Box<Dummy>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn Dummy` cannot be sent between threads safely
+   |
+   = help: the trait `std::marker::Send` is not implemented for `dyn Dummy`
+   = note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique<dyn Dummy>`
+   = note: required because it appears within the type `std::boxed::Box<dyn Dummy>`
+note: required by `assert_send`
+  --> $DIR/kindck-send-object.rs:5:1
+   |
+LL | fn assert_send<T:Send>() { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/kindck/kindck-send-object1.rs b/src/test/ui/kindck/kindck-send-object1.rs
new file mode 100644
index 0000000..3419854
--- /dev/null
+++ b/src/test/ui/kindck/kindck-send-object1.rs
@@ -0,0 +1,33 @@
+// Test which object types are considered sendable. This test
+// is broken into two parts because some errors occur in distinct
+// phases in the compiler. See kindck-send-object2.rs as well!
+
+fn assert_send<T:Send+'static>() { }
+trait Dummy { }
+
+// careful with object types, who knows what they close over...
+fn test51<'a>() {
+    assert_send::<&'a Dummy>();
+    //~^ ERROR `(dyn Dummy + 'a)` cannot be shared between threads safely [E0277]
+}
+fn test52<'a>() {
+    assert_send::<&'a (Dummy+Sync)>();
+    //~^ ERROR does not fulfill the required lifetime
+}
+
+// ...unless they are properly bounded
+fn test60() {
+    assert_send::<&'static (Dummy+Sync)>();
+}
+fn test61() {
+    assert_send::<Box<Dummy+Send>>();
+}
+
+// closure and object types can have lifetime bounds which make
+// them not ok
+fn test_71<'a>() {
+    assert_send::<Box<Dummy+'a>>();
+    //~^ ERROR `(dyn Dummy + 'a)` cannot be sent between threads safely
+}
+
+fn main() { }
diff --git a/src/test/ui/kindck/kindck-send-object1.stderr b/src/test/ui/kindck/kindck-send-object1.stderr
new file mode 100644
index 0000000..4f2d09a
--- /dev/null
+++ b/src/test/ui/kindck/kindck-send-object1.stderr
@@ -0,0 +1,41 @@
+error[E0277]: `(dyn Dummy + 'a)` cannot be shared between threads safely
+  --> $DIR/kindck-send-object1.rs:10:5
+   |
+LL |     assert_send::<&'a Dummy>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'a)` cannot be shared between threads safely
+   |
+   = help: the trait `std::marker::Sync` is not implemented for `(dyn Dummy + 'a)`
+   = note: required because of the requirements on the impl of `std::marker::Send` for `&'a (dyn Dummy + 'a)`
+note: required by `assert_send`
+  --> $DIR/kindck-send-object1.rs:5:1
+   |
+LL | fn assert_send<T:Send+'static>() { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0477]: the type `&'a (dyn Dummy + std::marker::Sync + 'a)` does not fulfill the required lifetime
+  --> $DIR/kindck-send-object1.rs:14:5
+   |
+LL |     assert_send::<&'a (Dummy+Sync)>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: type must satisfy the static lifetime
+
+error[E0277]: `(dyn Dummy + 'a)` cannot be sent between threads safely
+  --> $DIR/kindck-send-object1.rs:29:5
+   |
+LL |     assert_send::<Box<Dummy+'a>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'a)` cannot be sent between threads safely
+   |
+   = help: the trait `std::marker::Send` is not implemented for `(dyn Dummy + 'a)`
+   = note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique<(dyn Dummy + 'a)>`
+   = note: required because it appears within the type `std::boxed::Box<(dyn Dummy + 'a)>`
+note: required by `assert_send`
+  --> $DIR/kindck-send-object1.rs:5:1
+   |
+LL | fn assert_send<T:Send+'static>() { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0277, E0477.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/kindck/kindck-send-object2.rs b/src/test/ui/kindck/kindck-send-object2.rs
new file mode 100644
index 0000000..911ad98
--- /dev/null
+++ b/src/test/ui/kindck/kindck-send-object2.rs
@@ -0,0 +1,24 @@
+// Continue kindck-send-object1.rs.
+
+fn assert_send<T:Send>() { }
+trait Dummy { }
+
+fn test50() {
+    assert_send::<&'static Dummy>();
+    //~^ ERROR `(dyn Dummy + 'static)` cannot be shared between threads safely [E0277]
+}
+
+fn test53() {
+    assert_send::<Box<Dummy>>();
+    //~^ ERROR `dyn Dummy` cannot be sent between threads safely
+}
+
+// ...unless they are properly bounded
+fn test60() {
+    assert_send::<&'static (Dummy+Sync)>();
+}
+fn test61() {
+    assert_send::<Box<Dummy+Send>>();
+}
+
+fn main() { }
diff --git a/src/test/ui/kindck/kindck-send-object2.stderr b/src/test/ui/kindck/kindck-send-object2.stderr
new file mode 100644
index 0000000..db79989
--- /dev/null
+++ b/src/test/ui/kindck/kindck-send-object2.stderr
@@ -0,0 +1,32 @@
+error[E0277]: `(dyn Dummy + 'static)` cannot be shared between threads safely
+  --> $DIR/kindck-send-object2.rs:7:5
+   |
+LL |     assert_send::<&'static Dummy>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'static)` cannot be shared between threads safely
+   |
+   = help: the trait `std::marker::Sync` is not implemented for `(dyn Dummy + 'static)`
+   = note: required because of the requirements on the impl of `std::marker::Send` for `&'static (dyn Dummy + 'static)`
+note: required by `assert_send`
+  --> $DIR/kindck-send-object2.rs:3:1
+   |
+LL | fn assert_send<T:Send>() { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: `dyn Dummy` cannot be sent between threads safely
+  --> $DIR/kindck-send-object2.rs:12:5
+   |
+LL |     assert_send::<Box<Dummy>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn Dummy` cannot be sent between threads safely
+   |
+   = help: the trait `std::marker::Send` is not implemented for `dyn Dummy`
+   = note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique<dyn Dummy>`
+   = note: required because it appears within the type `std::boxed::Box<dyn Dummy>`
+note: required by `assert_send`
+  --> $DIR/kindck-send-object2.rs:3:1
+   |
+LL | fn assert_send<T:Send>() { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/kindck/kindck-send-owned.rs b/src/test/ui/kindck/kindck-send-owned.rs
new file mode 100644
index 0000000..65efb69
--- /dev/null
+++ b/src/test/ui/kindck/kindck-send-owned.rs
@@ -0,0 +1,16 @@
+// Test which of the builtin types are considered sendable.
+
+fn assert_send<T:Send>() { }
+
+// owned content are ok
+fn test30() { assert_send::<Box<isize>>(); }
+fn test31() { assert_send::<String>(); }
+fn test32() { assert_send::<Vec<isize> >(); }
+
+// but not if they own a bad thing
+fn test40() {
+    assert_send::<Box<*mut u8>>();
+    //~^ ERROR `*mut u8` cannot be sent between threads safely
+}
+
+fn main() { }
diff --git a/src/test/ui/kindck/kindck-send-owned.stderr b/src/test/ui/kindck/kindck-send-owned.stderr
new file mode 100644
index 0000000..75c757d
--- /dev/null
+++ b/src/test/ui/kindck/kindck-send-owned.stderr
@@ -0,0 +1,18 @@
+error[E0277]: `*mut u8` cannot be sent between threads safely
+  --> $DIR/kindck-send-owned.rs:12:5
+   |
+LL |     assert_send::<Box<*mut u8>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*mut u8` cannot be sent between threads safely
+   |
+   = help: the trait `std::marker::Send` is not implemented for `*mut u8`
+   = note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique<*mut u8>`
+   = note: required because it appears within the type `std::boxed::Box<*mut u8>`
+note: required by `assert_send`
+  --> $DIR/kindck-send-owned.rs:3:1
+   |
+LL | fn assert_send<T:Send>() { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/kindck/kindck-send-unsafe.rs b/src/test/ui/kindck/kindck-send-unsafe.rs
new file mode 100644
index 0000000..4ef30a7
--- /dev/null
+++ b/src/test/ui/kindck/kindck-send-unsafe.rs
@@ -0,0 +1,11 @@
+extern crate core;
+
+fn assert_send<T:Send>() { }
+
+fn test71<'a>() {
+    assert_send::<*mut &'a isize>();
+    //~^ ERROR `*mut &'a isize` cannot be sent between threads safely
+}
+
+fn main() {
+}
diff --git a/src/test/ui/kindck/kindck-send-unsafe.rs~rust-lang_master b/src/test/ui/kindck/kindck-send-unsafe.rs~rust-lang_master
new file mode 100644
index 0000000..3f0444e
--- /dev/null
+++ b/src/test/ui/kindck/kindck-send-unsafe.rs~rust-lang_master
@@ -0,0 +1,12 @@
+fn assert_send<T:Send>() { }
+
+// unsafe ptrs are ok unless they point at unsendable things
+fn test70() {
+    assert_send::<*mut int>();
+}
+fn test71<'a>() {
+    assert_send::<*mut &'a int>(); //~ ERROR does not fulfill the required lifetime
+}
+
+fn main() {
+}
diff --git a/src/test/ui/kindck/kindck-send-unsafe.stderr b/src/test/ui/kindck/kindck-send-unsafe.stderr
new file mode 100644
index 0000000..2fbb07a
--- /dev/null
+++ b/src/test/ui/kindck/kindck-send-unsafe.stderr
@@ -0,0 +1,16 @@
+error[E0277]: `*mut &'a isize` cannot be sent between threads safely
+  --> $DIR/kindck-send-unsafe.rs:6:5
+   |
+LL |     assert_send::<*mut &'a isize>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*mut &'a isize` cannot be sent between threads safely
+   |
+   = help: the trait `std::marker::Send` is not implemented for `*mut &'a isize`
+note: required by `assert_send`
+  --> $DIR/kindck-send-unsafe.rs:3:1
+   |
+LL | fn assert_send<T:Send>() { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/label/label-static.rs b/src/test/ui/label/label-static.rs
new file mode 100644
index 0000000..95e764d
--- /dev/null
+++ b/src/test/ui/label/label-static.rs
@@ -0,0 +1,5 @@
+fn main() {
+    'static: loop { //~ ERROR invalid label name `'static`
+        break 'static //~ ERROR invalid label name `'static`
+    }
+}
diff --git a/src/test/ui/label/label-static.stderr b/src/test/ui/label/label-static.stderr
new file mode 100644
index 0000000..1d3251d
--- /dev/null
+++ b/src/test/ui/label/label-static.stderr
@@ -0,0 +1,14 @@
+error: invalid label name `'static`
+  --> $DIR/label-static.rs:2:5
+   |
+LL |     'static: loop {
+   |     ^^^^^^^
+
+error: invalid label name `'static`
+  --> $DIR/label-static.rs:3:15
+   |
+LL |         break 'static
+   |               ^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/label/label-underscore.rs b/src/test/ui/label/label-underscore.rs
new file mode 100644
index 0000000..de67f3d
--- /dev/null
+++ b/src/test/ui/label/label-underscore.rs
@@ -0,0 +1,5 @@
+fn main() {
+    '_: loop { //~ ERROR invalid label name `'_`
+        break '_ //~ ERROR invalid label name `'_`
+    }
+}
diff --git a/src/test/ui/label/label-underscore.stderr b/src/test/ui/label/label-underscore.stderr
new file mode 100644
index 0000000..4558ec4
--- /dev/null
+++ b/src/test/ui/label/label-underscore.stderr
@@ -0,0 +1,14 @@
+error: invalid label name `'_`
+  --> $DIR/label-underscore.rs:2:5
+   |
+LL |     '_: loop {
+   |     ^^
+
+error: invalid label name `'_`
+  --> $DIR/label-underscore.rs:3:15
+   |
+LL |         break '_
+   |               ^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/label/label_break_value_continue.rs b/src/test/ui/label/label_break_value_continue.rs
new file mode 100644
index 0000000..e0deb30
--- /dev/null
+++ b/src/test/ui/label/label_break_value_continue.rs
@@ -0,0 +1,27 @@
+#![feature(label_break_value)]
+#![allow(unused_labels)]
+
+// Simple continue pointing to an unlabeled break should yield in an error
+fn continue_simple() {
+    'b: {
+        continue; //~ ERROR unlabeled `continue` inside of a labeled block
+    }
+}
+
+// Labeled continue pointing to an unlabeled break should yield in an error
+fn continue_labeled() {
+    'b: {
+        continue 'b; //~ ERROR `continue` pointing to a labeled block
+    }
+}
+
+// Simple continue that would cross a labeled block should yield in an error
+fn continue_crossing() {
+    loop {
+        'b: {
+            continue; //~ ERROR unlabeled `continue` inside of a labeled block
+        }
+    }
+}
+
+pub fn main() {}
diff --git a/src/test/ui/label/label_break_value_continue.stderr b/src/test/ui/label/label_break_value_continue.stderr
new file mode 100644
index 0000000..bd1dd59
--- /dev/null
+++ b/src/test/ui/label/label_break_value_continue.stderr
@@ -0,0 +1,30 @@
+error[E0695]: unlabeled `continue` inside of a labeled block
+  --> $DIR/label_break_value_continue.rs:7:9
+   |
+LL |         continue;
+   |         ^^^^^^^^ `continue` statements that would diverge to or through a labeled block need to bear a label
+
+error[E0696]: `continue` pointing to a labeled block
+  --> $DIR/label_break_value_continue.rs:14:9
+   |
+LL |         continue 'b;
+   |         ^^^^^^^^^^^ labeled blocks cannot be `continue`'d
+   |
+note: labeled block the continue points to
+  --> $DIR/label_break_value_continue.rs:13:5
+   |
+LL | /     'b: {
+LL | |         continue 'b;
+LL | |     }
+   | |_____^
+
+error[E0695]: unlabeled `continue` inside of a labeled block
+  --> $DIR/label_break_value_continue.rs:22:13
+   |
+LL |             continue;
+   |             ^^^^^^^^ `continue` statements that would diverge to or through a labeled block need to bear a label
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0695, E0696.
+For more information about an error, try `rustc --explain E0695`.
diff --git a/src/test/ui/label/label_break_value_illegal_uses.rs b/src/test/ui/label/label_break_value_illegal_uses.rs
new file mode 100644
index 0000000..81cb177
--- /dev/null
+++ b/src/test/ui/label/label_break_value_illegal_uses.rs
@@ -0,0 +1,21 @@
+#![feature(label_break_value)]
+
+// These are forbidden occurrences of label-break-value
+
+fn labeled_unsafe() {
+    unsafe 'b: {} //~ ERROR expected one of `extern`, `fn`, or `{`
+}
+
+fn labeled_if() {
+    if true 'b: {} //~ ERROR expected `{`, found `'b`
+}
+
+fn labeled_else() {
+    if true {} else 'b: {} //~ ERROR expected `{`, found `'b`
+}
+
+fn labeled_match() {
+    match false 'b: {} //~ ERROR expected one of `.`, `?`, `{`, or an operator
+}
+
+pub fn main() {}
diff --git a/src/test/ui/label/label_break_value_illegal_uses.stderr b/src/test/ui/label/label_break_value_illegal_uses.stderr
new file mode 100644
index 0000000..0b9754c
--- /dev/null
+++ b/src/test/ui/label/label_break_value_illegal_uses.stderr
@@ -0,0 +1,35 @@
+error: expected one of `extern`, `fn`, or `{`, found `'b`
+  --> $DIR/label_break_value_illegal_uses.rs:6:12
+   |
+LL |     unsafe 'b: {}
+   |            ^^ expected one of `extern`, `fn`, or `{` here
+
+error: expected `{`, found `'b`
+  --> $DIR/label_break_value_illegal_uses.rs:10:13
+   |
+LL |     if true 'b: {}
+   |     --      ^^----
+   |     |       |
+   |     |       expected `{`
+   |     |       help: try placing this code inside a block: `{ 'b: { } }`
+   |     this `if` statement has a condition, but no block
+
+error: expected `{`, found `'b`
+  --> $DIR/label_break_value_illegal_uses.rs:14:21
+   |
+LL |     if true {} else 'b: {}
+   |                     ^^----
+   |                     |
+   |                     expected `{`
+   |                     help: try placing this code inside a block: `{ 'b: { } }`
+
+error: expected one of `.`, `?`, `{`, or an operator, found `'b`
+  --> $DIR/label_break_value_illegal_uses.rs:18:17
+   |
+LL |     match false 'b: {}
+   |     -----       ^^ expected one of `.`, `?`, `{`, or an operator here
+   |     |
+   |     while parsing this match expression
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/label/label_break_value_unlabeled_break.rs b/src/test/ui/label/label_break_value_unlabeled_break.rs
new file mode 100644
index 0000000..fa0c70e
--- /dev/null
+++ b/src/test/ui/label/label_break_value_unlabeled_break.rs
@@ -0,0 +1,20 @@
+#![feature(label_break_value)]
+#![allow(unused_labels)]
+
+// Simple unlabeled break should yield in an error
+fn unlabeled_break_simple() {
+    'b: {
+        break; //~ ERROR unlabeled `break` inside of a labeled block
+    }
+}
+
+// Unlabeled break that would cross a labeled block should yield in an error
+fn unlabeled_break_crossing() {
+    loop {
+        'b: {
+            break; //~ ERROR unlabeled `break` inside of a labeled block
+        }
+    }
+}
+
+pub fn main() {}
diff --git a/src/test/ui/label/label_break_value_unlabeled_break.stderr b/src/test/ui/label/label_break_value_unlabeled_break.stderr
new file mode 100644
index 0000000..0c4f573
--- /dev/null
+++ b/src/test/ui/label/label_break_value_unlabeled_break.stderr
@@ -0,0 +1,15 @@
+error[E0695]: unlabeled `break` inside of a labeled block
+  --> $DIR/label_break_value_unlabeled_break.rs:7:9
+   |
+LL |         break;
+   |         ^^^^^ `break` statements that would diverge to or through a labeled block need to bear a label
+
+error[E0695]: unlabeled `break` inside of a labeled block
+  --> $DIR/label_break_value_unlabeled_break.rs:15:13
+   |
+LL |             break;
+   |             ^^^^^ `break` statements that would diverge to or through a labeled block need to bear a label
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0695`.
diff --git a/src/test/ui/lang-item-missing.rs b/src/test/ui/lang-item-missing.rs
new file mode 100644
index 0000000..4e26343
--- /dev/null
+++ b/src/test/ui/lang-item-missing.rs
@@ -0,0 +1,12 @@
+// Test that a missing lang item (in this case `sized`) does not cause an ICE,
+// see #17392.
+
+// error-pattern: requires `sized` lang_item
+
+#![feature(start, no_core)]
+#![no_core]
+
+#[start]
+fn start(argc: isize, argv: *const *const u8) -> isize {
+    0
+}
diff --git a/src/test/ui/lang-item-missing.stderr b/src/test/ui/lang-item-missing.stderr
new file mode 100644
index 0000000..f7516c7
--- /dev/null
+++ b/src/test/ui/lang-item-missing.stderr
@@ -0,0 +1,4 @@
+error: requires `sized` lang_item
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/layout/homogeneous-aggr-zero-sized-c-struct.rs b/src/test/ui/layout/homogeneous-aggr-zero-sized-c-struct.rs
new file mode 100644
index 0000000..622709e
--- /dev/null
+++ b/src/test/ui/layout/homogeneous-aggr-zero-sized-c-struct.rs
@@ -0,0 +1,36 @@
+#![feature(rustc_attrs)]
+
+// Show that `homogeneous_aggregate` code ignores zero-length C
+// arrays.  This matches the recent C standard, though not the
+// behavior of all older compilers, which somtimes consider `T[0]` to
+// be a "flexible array member" (see discussion on #56877 for
+// details).
+
+#[repr(C)]
+pub struct Foo {
+    x: u32
+}
+
+#[repr(C)]
+pub struct Middle {
+    pub a: f32,
+    pub foo: [Foo; 0],
+    pub b: f32,
+}
+
+#[rustc_layout(homogeneous_aggregate)]
+pub type TestMiddle = Middle;
+//~^ ERROR homogeneous_aggregate: Homogeneous
+
+#[repr(C)]
+pub struct Final {
+    pub a: f32,
+    pub b: f32,
+    pub foo: [Foo; 0],
+}
+
+#[rustc_layout(homogeneous_aggregate)]
+pub type TestFinal = Final;
+//~^ ERROR homogeneous_aggregate: Homogeneous
+
+fn main() { }
diff --git a/src/test/ui/layout/homogeneous-aggr-zero-sized-c-struct.stderr b/src/test/ui/layout/homogeneous-aggr-zero-sized-c-struct.stderr
new file mode 100644
index 0000000..0d44260
--- /dev/null
+++ b/src/test/ui/layout/homogeneous-aggr-zero-sized-c-struct.stderr
@@ -0,0 +1,14 @@
+error: homogeneous_aggregate: Homogeneous(Reg { kind: Float, size: Size { raw: 4 } })
+  --> $DIR/homogeneous-aggr-zero-sized-c-struct.rs:22:1
+   |
+LL | pub type TestMiddle = Middle;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: homogeneous_aggregate: Homogeneous(Reg { kind: Float, size: Size { raw: 4 } })
+  --> $DIR/homogeneous-aggr-zero-sized-c-struct.rs:33:1
+   |
+LL | pub type TestFinal = Final;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/layout/homogeneous-aggr-zero-sized-repr-rust.rs b/src/test/ui/layout/homogeneous-aggr-zero-sized-repr-rust.rs
new file mode 100644
index 0000000..4b42941
--- /dev/null
+++ b/src/test/ui/layout/homogeneous-aggr-zero-sized-repr-rust.rs
@@ -0,0 +1,73 @@
+#![feature(rustc_attrs)]
+
+// Regression test for #56877. We want to ensure that the presence of
+// `PhantomData` does not prevent `Bar` from being considered a
+// homogeneous aggregate.
+
+#[repr(C)]
+pub struct BaseCase {
+    pub a: f32,
+    pub b: f32,
+}
+
+#[repr(C)]
+pub struct WithPhantomData {
+    pub a: f32,
+    pub b: f32,
+    pub _unit: std::marker::PhantomData<()>,
+}
+
+pub struct EmptyRustStruct {
+}
+
+#[repr(C)]
+pub struct WithEmptyRustStruct {
+    pub a: f32,
+    pub b: f32,
+    pub _unit: EmptyRustStruct,
+}
+
+pub struct TransitivelyEmptyRustStruct {
+    field: EmptyRustStruct,
+    array: [u32; 0],
+}
+
+#[repr(C)]
+pub struct WithTransitivelyEmptyRustStruct {
+    pub a: f32,
+    pub b: f32,
+    pub _unit: TransitivelyEmptyRustStruct,
+}
+
+pub enum EmptyRustEnum {
+    Dummy,
+}
+
+#[repr(C)]
+pub struct WithEmptyRustEnum {
+    pub a: f32,
+    pub b: f32,
+    pub _unit: EmptyRustEnum,
+}
+
+#[rustc_layout(homogeneous_aggregate)]
+pub type Test1 = BaseCase;
+//~^ ERROR homogeneous_aggregate: Homogeneous(Reg { kind: Float, size: Size { raw: 4 } })
+
+#[rustc_layout(homogeneous_aggregate)]
+pub type Test2 = WithPhantomData;
+//~^ ERROR homogeneous_aggregate: Homogeneous(Reg { kind: Float, size: Size { raw: 4 } })
+
+#[rustc_layout(homogeneous_aggregate)]
+pub type Test3 = WithEmptyRustStruct;
+//~^ ERROR homogeneous_aggregate: Homogeneous(Reg { kind: Float, size: Size { raw: 4 } })
+
+#[rustc_layout(homogeneous_aggregate)]
+pub type Test4 = WithTransitivelyEmptyRustStruct;
+//~^ ERROR homogeneous_aggregate: Homogeneous(Reg { kind: Float, size: Size { raw: 4 } })
+
+#[rustc_layout(homogeneous_aggregate)]
+pub type Test5 = WithEmptyRustEnum;
+//~^ ERROR homogeneous_aggregate: Homogeneous(Reg { kind: Float, size: Size { raw: 4 } })
+
+fn main() { }
diff --git a/src/test/ui/layout/homogeneous-aggr-zero-sized-repr-rust.stderr b/src/test/ui/layout/homogeneous-aggr-zero-sized-repr-rust.stderr
new file mode 100644
index 0000000..be04ba3
--- /dev/null
+++ b/src/test/ui/layout/homogeneous-aggr-zero-sized-repr-rust.stderr
@@ -0,0 +1,32 @@
+error: homogeneous_aggregate: Homogeneous(Reg { kind: Float, size: Size { raw: 4 } })
+  --> $DIR/homogeneous-aggr-zero-sized-repr-rust.rs:54:1
+   |
+LL | pub type Test1 = BaseCase;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: homogeneous_aggregate: Homogeneous(Reg { kind: Float, size: Size { raw: 4 } })
+  --> $DIR/homogeneous-aggr-zero-sized-repr-rust.rs:58:1
+   |
+LL | pub type Test2 = WithPhantomData;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: homogeneous_aggregate: Homogeneous(Reg { kind: Float, size: Size { raw: 4 } })
+  --> $DIR/homogeneous-aggr-zero-sized-repr-rust.rs:62:1
+   |
+LL | pub type Test3 = WithEmptyRustStruct;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: homogeneous_aggregate: Homogeneous(Reg { kind: Float, size: Size { raw: 4 } })
+  --> $DIR/homogeneous-aggr-zero-sized-repr-rust.rs:66:1
+   |
+LL | pub type Test4 = WithTransitivelyEmptyRustStruct;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: homogeneous_aggregate: Homogeneous(Reg { kind: Float, size: Size { raw: 4 } })
+  --> $DIR/homogeneous-aggr-zero-sized-repr-rust.rs:70:1
+   |
+LL | pub type Test5 = WithEmptyRustEnum;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/ui/layout/zero-sized-array-union.rs b/src/test/ui/layout/zero-sized-array-union.rs
new file mode 100644
index 0000000..68b2182
--- /dev/null
+++ b/src/test/ui/layout/zero-sized-array-union.rs
@@ -0,0 +1,95 @@
+#![feature(rustc_attrs)]
+
+// Various tests around the behavior of zero-sized arrays and
+// unions. This matches the behavior of modern C compilers, though
+// older compilers (and sometimes clang) treat `T[0]` as a "flexible
+// array member". See more
+// details in #56877.
+
+#[derive(Copy, Clone)]
+#[repr(C)]
+struct Empty { }
+
+#[derive(Copy, Clone)]
+#[repr(C)]
+struct Empty2 {
+    e: Empty
+}
+
+#[derive(Copy, Clone)]
+#[repr(C)]
+struct Empty3 {
+    z: [f32; 0],
+}
+
+#[derive(Copy, Clone)]
+#[repr(C)]
+struct Empty4 {
+    e: Empty3
+}
+
+#[repr(C)]
+union U1 {
+    s: Empty
+}
+
+#[repr(C)]
+union U2 {
+    s: Empty2
+}
+
+#[repr(C)]
+union U3 {
+    s: Empty3
+}
+
+#[repr(C)]
+union U4 {
+    s: Empty4
+}
+
+#[repr(C)]
+struct Baz1 {
+    x: f32,
+    y: f32,
+    u: U1,
+}
+
+#[rustc_layout(homogeneous_aggregate)]
+type TestBaz1 = Baz1;
+//~^ ERROR homogeneous_aggregate: Homogeneous
+
+#[repr(C)]
+struct Baz2 {
+    x: f32,
+    y: f32,
+    u: U2,
+}
+
+#[rustc_layout(homogeneous_aggregate)]
+type TestBaz2 = Baz2;
+//~^ ERROR homogeneous_aggregate: Homogeneous
+
+#[repr(C)]
+struct Baz3 {
+    x: f32,
+    y: f32,
+    u: U3,
+}
+
+#[rustc_layout(homogeneous_aggregate)]
+type TestBaz3 = Baz3;
+//~^ ERROR homogeneous_aggregate: Homogeneous
+
+#[repr(C)]
+struct Baz4 {
+    x: f32,
+    y: f32,
+    u: U4,
+}
+
+#[rustc_layout(homogeneous_aggregate)]
+type TestBaz4 = Baz4;
+//~^ ERROR homogeneous_aggregate: Homogeneous
+
+fn main() { }
diff --git a/src/test/ui/layout/zero-sized-array-union.stderr b/src/test/ui/layout/zero-sized-array-union.stderr
new file mode 100644
index 0000000..1bb31aa
--- /dev/null
+++ b/src/test/ui/layout/zero-sized-array-union.stderr
@@ -0,0 +1,26 @@
+error: homogeneous_aggregate: Homogeneous(Reg { kind: Float, size: Size { raw: 4 } })
+  --> $DIR/zero-sized-array-union.rs:59:1
+   |
+LL | type TestBaz1 = Baz1;
+   | ^^^^^^^^^^^^^^^^^^^^^
+
+error: homogeneous_aggregate: Homogeneous(Reg { kind: Float, size: Size { raw: 4 } })
+  --> $DIR/zero-sized-array-union.rs:70:1
+   |
+LL | type TestBaz2 = Baz2;
+   | ^^^^^^^^^^^^^^^^^^^^^
+
+error: homogeneous_aggregate: Homogeneous(Reg { kind: Float, size: Size { raw: 4 } })
+  --> $DIR/zero-sized-array-union.rs:81:1
+   |
+LL | type TestBaz3 = Baz3;
+   | ^^^^^^^^^^^^^^^^^^^^^
+
+error: homogeneous_aggregate: Homogeneous(Reg { kind: Float, size: Size { raw: 4 } })
+  --> $DIR/zero-sized-array-union.rs:92:1
+   |
+LL | type TestBaz4 = Baz4;
+   | ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/lexical-scopes.rs b/src/test/ui/lexical-scopes.rs
new file mode 100644
index 0000000..46cfdf1
--- /dev/null
+++ b/src/test/ui/lexical-scopes.rs
@@ -0,0 +1,13 @@
+struct T { i: i32 }
+fn f<T>() {
+    let t = T { i: 0 }; //~ ERROR expected struct, variant or union type, found type parameter `T`
+}
+
+mod Foo {
+    pub fn f() {}
+}
+fn g<Foo>() {
+    Foo::f(); //~ ERROR no function or associated item named `f`
+}
+
+fn main() {}
diff --git a/src/test/ui/lexical-scopes.stderr b/src/test/ui/lexical-scopes.stderr
new file mode 100644
index 0000000..859eb04
--- /dev/null
+++ b/src/test/ui/lexical-scopes.stderr
@@ -0,0 +1,20 @@
+error[E0574]: expected struct, variant or union type, found type parameter `T`
+  --> $DIR/lexical-scopes.rs:3:13
+   |
+LL |     let t = T { i: 0 };
+   |             ^ not a struct, variant or union type
+help: possible better candidate is found in another module, you can import it into scope
+   |
+LL | use T;
+   |
+
+error[E0599]: no function or associated item named `f` found for type `Foo` in the current scope
+  --> $DIR/lexical-scopes.rs:10:10
+   |
+LL |     Foo::f();
+   |          ^ function or associated item not found in `Foo`
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0574, E0599.
+For more information about an error, try `rustc --explain E0574`.
diff --git a/src/test/ui/lifetime-before-type-params.rs b/src/test/ui/lifetime-before-type-params.rs
new file mode 100644
index 0000000..9b905d4
--- /dev/null
+++ b/src/test/ui/lifetime-before-type-params.rs
@@ -0,0 +1,9 @@
+#![allow(unused)]
+fn first<T, 'a, 'b>() {}
+//~^ ERROR lifetime parameters must be declared prior to type parameters
+fn second<'a, T, 'b>() {}
+//~^ ERROR lifetime parameters must be declared prior to type parameters
+fn third<T, U, 'a>() {}
+//~^ ERROR lifetime parameters must be declared prior to type parameters
+fn fourth<'a, T, 'b, U, 'c, V>() {}
+//~^ ERROR lifetime parameters must be declared prior to type parameters
diff --git a/src/test/ui/lifetime-before-type-params.stderr b/src/test/ui/lifetime-before-type-params.stderr
new file mode 100644
index 0000000..ffc6784
--- /dev/null
+++ b/src/test/ui/lifetime-before-type-params.stderr
@@ -0,0 +1,31 @@
+error: lifetime parameters must be declared prior to type parameters
+  --> $DIR/lifetime-before-type-params.rs:2:13
+   |
+LL | fn first<T, 'a, 'b>() {}
+   |         ----^^--^^- help: reorder the parameters: lifetimes, then types: `<'a, 'b, T>`
+
+error: lifetime parameters must be declared prior to type parameters
+  --> $DIR/lifetime-before-type-params.rs:4:18
+   |
+LL | fn second<'a, T, 'b>() {}
+   |          --------^^- help: reorder the parameters: lifetimes, then types: `<'a, 'b, T>`
+
+error: lifetime parameters must be declared prior to type parameters
+  --> $DIR/lifetime-before-type-params.rs:6:16
+   |
+LL | fn third<T, U, 'a>() {}
+   |         -------^^- help: reorder the parameters: lifetimes, then types: `<'a, T, U>`
+
+error: lifetime parameters must be declared prior to type parameters
+  --> $DIR/lifetime-before-type-params.rs:8:18
+   |
+LL | fn fourth<'a, T, 'b, U, 'c, V>() {}
+   |          --------^^-----^^---- help: reorder the parameters: lifetimes, then types: `<'a, 'b, 'c, T, U, V>`
+
+error[E0601]: `main` function not found in crate `lifetime_before_type_params`
+   |
+   = note: consider adding a `main` function to `$DIR/lifetime-before-type-params.rs`
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0601`.
diff --git a/src/test/ui/lifetime_starts_expressions.rs b/src/test/ui/lifetime_starts_expressions.rs
new file mode 100644
index 0000000..e009879
--- /dev/null
+++ b/src/test/ui/lifetime_starts_expressions.rs
@@ -0,0 +1,13 @@
+fn foo() -> u32 {
+    return 'label: loop { break 'label 42; };
+}
+
+fn bar() -> u32 {
+    loop { break 'label: loop { break 'label 42; }; }
+    //~^ ERROR expected identifier, found keyword `loop`
+    //~| ERROR expected type, found keyword `loop`
+}
+
+pub fn main() {
+    foo();
+}
diff --git a/src/test/ui/lifetime_starts_expressions.stderr b/src/test/ui/lifetime_starts_expressions.stderr
new file mode 100644
index 0000000..cb5a52a
--- /dev/null
+++ b/src/test/ui/lifetime_starts_expressions.stderr
@@ -0,0 +1,26 @@
+error: expected identifier, found keyword `loop`
+  --> $DIR/lifetime_starts_expressions.rs:6:26
+   |
+LL |     loop { break 'label: loop { break 'label 42; }; }
+   |                          ^^^^ expected identifier, found keyword
+help: you can escape reserved keywords to use them as identifiers
+   |
+LL |     loop { break 'label: r#loop { break 'label 42; }; }
+   |                          ^^^^^^
+
+error: expected type, found keyword `loop`
+  --> $DIR/lifetime_starts_expressions.rs:6:26
+   |
+LL |     loop { break 'label: loop { break 'label 42; }; }
+   |                          ^^^^ expecting a type here because of type ascription
+   |
+   = note: type ascription is a nightly-only feature that lets you annotate an expression with a type: `<expr>: <type>`
+note: this expression expects an ascribed type after the colon
+  --> $DIR/lifetime_starts_expressions.rs:6:12
+   |
+LL |     loop { break 'label: loop { break 'label 42; }; }
+   |            ^^^^^^^^^^^^
+   = help: this might be indicative of a syntax error elsewhere
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/lifetimes/auxiliary/lifetime_bound_will_change_warning_lib.rs b/src/test/ui/lifetimes/auxiliary/lifetime_bound_will_change_warning_lib.rs
new file mode 100644
index 0000000..58f1b81
--- /dev/null
+++ b/src/test/ui/lifetimes/auxiliary/lifetime_bound_will_change_warning_lib.rs
@@ -0,0 +1,11 @@
+#![crate_type = "rlib"]
+
+// Helper for testing that we get suitable warnings when lifetime
+// bound change will cause breakage.
+
+pub fn just_ref(x: &Fn()) {
+}
+
+pub fn ref_obj(x: &Box<Fn()>) {
+    // this will change to &Box<Fn()+'static>...
+}
diff --git a/src/test/ui/lifetimes/borrowck-let-suggestion.nll.stderr b/src/test/ui/lifetimes/borrowck-let-suggestion.nll.stderr
new file mode 100644
index 0000000..0e2fc0a
--- /dev/null
+++ b/src/test/ui/lifetimes/borrowck-let-suggestion.nll.stderr
@@ -0,0 +1,17 @@
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/borrowck-let-suggestion.rs:2:17
+   |
+LL |     let mut x = vec![1].iter();
+   |                 ^^^^^^^       - temporary value is freed at the end of this statement
+   |                 |
+   |                 creates a temporary which is freed while still in use
+LL |
+LL |     x.use_mut();
+   |     - borrow later used here
+   |
+   = note: consider using a `let` binding to create a longer lived value
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/src/test/ui/lifetimes/borrowck-let-suggestion.rs b/src/test/ui/lifetimes/borrowck-let-suggestion.rs
new file mode 100644
index 0000000..1deb0457
--- /dev/null
+++ b/src/test/ui/lifetimes/borrowck-let-suggestion.rs
@@ -0,0 +1,12 @@
+fn f() {
+    let mut x = vec![1].iter();
+    //~^ ERROR borrowed value does not live long enough
+    x.use_mut();
+}
+
+fn main() {
+    f();
+}
+
+trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { }  }
+impl<T> Fake for T { }
diff --git a/src/test/ui/lifetimes/borrowck-let-suggestion.stderr b/src/test/ui/lifetimes/borrowck-let-suggestion.stderr
new file mode 100644
index 0000000..7a95137
--- /dev/null
+++ b/src/test/ui/lifetimes/borrowck-let-suggestion.stderr
@@ -0,0 +1,17 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/borrowck-let-suggestion.rs:2:17
+   |
+LL |     let mut x = vec![1].iter();
+   |                 ^^^^^^^       - temporary value dropped here while still borrowed
+   |                 |
+   |                 temporary value does not live long enough
+...
+LL | }
+   | - temporary value needs to live until here
+   |
+   = note: consider using a `let` binding to increase its lifetime
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/lifetimes/lifetime-bound-will-change-warning.rs b/src/test/ui/lifetimes/lifetime-bound-will-change-warning.rs
new file mode 100644
index 0000000..5461f87
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-bound-will-change-warning.rs
@@ -0,0 +1,54 @@
+// aux-build:lifetime_bound_will_change_warning_lib.rs
+
+// Test that various corner cases cause an error. These are tests
+// that used to pass before we tweaked object defaults.
+
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+
+extern crate lifetime_bound_will_change_warning_lib as lib;
+
+fn just_ref(x: &Fn()) {
+}
+
+fn ref_obj(x: &Box<Fn()>) {
+    // this will change to &Box<Fn()+'static>...
+
+    // Note: no warning is issued here, because the type of `x` will change to 'static
+    if false { ref_obj(x); }
+}
+
+fn test1<'a>(x: &'a Box<Fn()+'a>) {
+    // just_ref will stay the same.
+    just_ref(&**x)
+}
+
+fn test1cc<'a>(x: &'a Box<Fn()+'a>) {
+    // same as test1, but cross-crate
+    lib::just_ref(&**x)
+}
+
+fn test2<'a>(x: &'a Box<Fn()+'a>) {
+    // but ref_obj will not, so warn.
+    ref_obj(x) //~ ERROR mismatched types
+}
+
+fn test2cc<'a>(x: &'a Box<Fn()+'a>) {
+    // same as test2, but cross crate
+    lib::ref_obj(x) //~ ERROR mismatched types
+}
+
+fn test3<'a>(x: &'a Box<Fn()+'static>) {
+    // here, we have a 'static bound, so even when ref_obj changes, no error results
+    ref_obj(x)
+}
+
+fn test3cc<'a>(x: &'a Box<Fn()+'static>) {
+    // same as test3, but cross crate
+    lib::ref_obj(x)
+}
+
+
+fn main() {
+}
diff --git a/src/test/ui/lifetimes/lifetime-bound-will-change-warning.stderr b/src/test/ui/lifetimes/lifetime-bound-will-change-warning.stderr
new file mode 100644
index 0000000..1af4bd5
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-bound-will-change-warning.stderr
@@ -0,0 +1,33 @@
+error[E0308]: mismatched types
+  --> $DIR/lifetime-bound-will-change-warning.rs:34:13
+   |
+LL |     ref_obj(x)
+   |             ^ lifetime mismatch
+   |
+   = note: expected type `&std::boxed::Box<(dyn std::ops::Fn() + 'static)>`
+              found type `&std::boxed::Box<(dyn std::ops::Fn() + 'a)>`
+note: the lifetime 'a as defined on the function body at 32:10...
+  --> $DIR/lifetime-bound-will-change-warning.rs:32:10
+   |
+LL | fn test2<'a>(x: &'a Box<Fn()+'a>) {
+   |          ^^
+   = note: ...does not necessarily outlive the static lifetime
+
+error[E0308]: mismatched types
+  --> $DIR/lifetime-bound-will-change-warning.rs:39:18
+   |
+LL |     lib::ref_obj(x)
+   |                  ^ lifetime mismatch
+   |
+   = note: expected type `&std::boxed::Box<(dyn std::ops::Fn() + 'static)>`
+              found type `&std::boxed::Box<(dyn std::ops::Fn() + 'a)>`
+note: the lifetime 'a as defined on the function body at 37:12...
+  --> $DIR/lifetime-bound-will-change-warning.rs:37:12
+   |
+LL | fn test2cc<'a>(x: &'a Box<Fn()+'a>) {
+   |            ^^
+   = note: ...does not necessarily outlive the static lifetime
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.rs b/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.rs
new file mode 100644
index 0000000..d2b782c
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.rs
@@ -0,0 +1,49 @@
+trait ListItem<'a> {
+    fn list_name() -> &'a str;
+}
+
+trait Collection { fn len(&self) -> usize; }
+
+// is now well formed. RFC 2093
+struct List<'a, T: ListItem<'a>> {
+    slice: &'a [T]
+}
+
+impl<'a, T: ListItem<'a>> Collection for List<'a, T> {
+    fn len(&self) -> usize {
+        0
+    }
+}
+
+struct Foo<T> {
+    foo: &'static T
+    //~^ ERROR may not live long enough
+}
+
+trait X<K>: Sized {
+    fn foo<'a, L: X<&'a Nested<K>>>();
+    //~^ ERROR may not live long enough
+
+    // check that we give a sane error for `Self`
+    fn bar<'a, L: X<&'a Nested<Self>>>();
+    //~^ ERROR may not live long enough
+
+    // check that we give a sane error for nested generics
+    fn baz<'a, L, M: X<&'a Nested<L>>>() {
+        //~^ ERROR may not live long enough
+    }
+}
+
+trait TraitB {}
+
+struct Nested<K>(K);
+impl<K> Nested<K> {
+    fn generic_in_parent<'a, L: X<&'a Nested<K>>>() {
+        //~^ ERROR may not live long enough
+    }
+    fn generic_in_child<'a, 'b, L: X<&'a Nested<M>>, M: 'b>() {
+        //~^ ERROR may not live long enough
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr b/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr
new file mode 100644
index 0000000..90bec01
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr
@@ -0,0 +1,101 @@
+error[E0310]: the parameter type `T` may not live long enough
+  --> $DIR/lifetime-doesnt-live-long-enough.rs:19:5
+   |
+LL | struct Foo<T> {
+   |            - help: consider adding an explicit lifetime bound `T: 'static`...
+LL |     foo: &'static T
+   |     ^^^^^^^^^^^^^^^
+   |
+note: ...so that the reference type `&'static T` does not outlive the data it points at
+  --> $DIR/lifetime-doesnt-live-long-enough.rs:19:5
+   |
+LL |     foo: &'static T
+   |     ^^^^^^^^^^^^^^^
+
+error[E0309]: the parameter type `K` may not live long enough
+  --> $DIR/lifetime-doesnt-live-long-enough.rs:24:5
+   |
+LL | trait X<K>: Sized {
+   |         - help: consider adding an explicit lifetime bound `K: 'a`...
+LL |     fn foo<'a, L: X<&'a Nested<K>>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: ...so that the reference type `&'a Nested<K>` does not outlive the data it points at
+  --> $DIR/lifetime-doesnt-live-long-enough.rs:24:5
+   |
+LL |     fn foo<'a, L: X<&'a Nested<K>>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0309]: the parameter type `Self` may not live long enough
+  --> $DIR/lifetime-doesnt-live-long-enough.rs:28:5
+   |
+LL |     fn bar<'a, L: X<&'a Nested<Self>>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding an explicit lifetime bound `Self: 'a`...
+note: ...so that the reference type `&'a Nested<Self>` does not outlive the data it points at
+  --> $DIR/lifetime-doesnt-live-long-enough.rs:28:5
+   |
+LL |     fn bar<'a, L: X<&'a Nested<Self>>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0309]: the parameter type `L` may not live long enough
+  --> $DIR/lifetime-doesnt-live-long-enough.rs:32:5
+   |
+LL |       fn baz<'a, L, M: X<&'a Nested<L>>>() {
+   |       ^          - help: consider adding an explicit lifetime bound `L: 'a`...
+   |  _____|
+   | |
+LL | |
+LL | |     }
+   | |_____^
+   |
+note: ...so that the reference type `&'a Nested<L>` does not outlive the data it points at
+  --> $DIR/lifetime-doesnt-live-long-enough.rs:32:5
+   |
+LL | /     fn baz<'a, L, M: X<&'a Nested<L>>>() {
+LL | |
+LL | |     }
+   | |_____^
+
+error[E0309]: the parameter type `K` may not live long enough
+  --> $DIR/lifetime-doesnt-live-long-enough.rs:41:5
+   |
+LL |   impl<K> Nested<K> {
+   |        - help: consider adding an explicit lifetime bound `K: 'a`...
+LL | /     fn generic_in_parent<'a, L: X<&'a Nested<K>>>() {
+LL | |
+LL | |     }
+   | |_____^
+   |
+note: ...so that the reference type `&'a Nested<K>` does not outlive the data it points at
+  --> $DIR/lifetime-doesnt-live-long-enough.rs:41:5
+   |
+LL | /     fn generic_in_parent<'a, L: X<&'a Nested<K>>>() {
+LL | |
+LL | |     }
+   | |_____^
+
+error[E0309]: the parameter type `M` may not live long enough
+  --> $DIR/lifetime-doesnt-live-long-enough.rs:44:5
+   |
+LL |       fn generic_in_child<'a, 'b, L: X<&'a Nested<M>>, M: 'b>() {
+   |       ^                                                -- help: consider adding an explicit lifetime bound `M: 'a`...
+   |  _____|
+   | |
+LL | |
+LL | |     }
+   | |_____^
+   |
+note: ...so that the reference type `&'a Nested<M>` does not outlive the data it points at
+  --> $DIR/lifetime-doesnt-live-long-enough.rs:44:5
+   |
+LL | /     fn generic_in_child<'a, 'b, L: X<&'a Nested<M>>, M: 'b>() {
+LL | |
+LL | |     }
+   | |_____^
+
+error: aborting due to 6 previous errors
+
+Some errors occurred: E0309, E0310.
+For more information about an error, try `rustc --explain E0309`.
diff --git a/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.rs b/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.rs
new file mode 100644
index 0000000..7a2eba5
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.rs
@@ -0,0 +1,45 @@
+// Lifetime annotation needed because we have no arguments.
+fn f() -> &isize {    //~ ERROR missing lifetime specifier
+    panic!()
+}
+
+// Lifetime annotation needed because we have two by-reference parameters.
+fn g(_x: &isize, _y: &isize) -> &isize {    //~ ERROR missing lifetime specifier
+    panic!()
+}
+
+struct Foo<'a> {
+    x: &'a isize,
+}
+
+// Lifetime annotation needed because we have two lifetimes: one as a parameter
+// and one on the reference.
+fn h(_x: &Foo) -> &isize { //~ ERROR missing lifetime specifier
+    panic!()
+}
+
+fn i(_x: isize) -> &isize { //~ ERROR missing lifetime specifier
+    panic!()
+}
+
+// Cases which used to work but now don't.
+
+type StaticStr = &'static str; // hides 'static
+trait WithLifetime<'a> {
+    type Output; // can hide 'a
+}
+
+// This worked because the type of the first argument contains
+// 'static, although StaticStr doesn't even have parameters.
+fn j(_x: StaticStr) -> &isize { //~ ERROR missing lifetime specifier
+    panic!()
+}
+
+// This worked because the compiler resolved the argument type
+// to <T as WithLifetime<'a>>::Output which has the hidden 'a.
+fn k<'a, T: WithLifetime<'a>>(_x: T::Output) -> &isize {
+//~^ ERROR missing lifetime specifier
+    panic!()
+}
+
+fn main() {}
diff --git a/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr b/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr
new file mode 100644
index 0000000..3f7c393
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr
@@ -0,0 +1,51 @@
+error[E0106]: missing lifetime specifier
+  --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:2:11
+   |
+LL | fn f() -> &isize {
+   |           ^ help: consider giving it a 'static lifetime: `&'static`
+   |
+   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:7:33
+   |
+LL | fn g(_x: &isize, _y: &isize) -> &isize {
+   |                                 ^ expected lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `_x` or `_y`
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:17:19
+   |
+LL | fn h(_x: &Foo) -> &isize {
+   |                   ^ expected lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but the signature does not say which one of `_x`'s 2 lifetimes it is borrowed from
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:21:20
+   |
+LL | fn i(_x: isize) -> &isize {
+   |                    ^ help: consider giving it an explicit bounded or 'static lifetime: `&'static`
+   |
+   = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:34:24
+   |
+LL | fn j(_x: StaticStr) -> &isize {
+   |                        ^ help: consider giving it an explicit bounded or 'static lifetime: `&'static`
+   |
+   = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:40:49
+   |
+LL | fn k<'a, T: WithLifetime<'a>>(_x: T::Output) -> &isize {
+   |                                                 ^ help: consider giving it an explicit bounded or 'static lifetime: `&'static`
+   |
+   = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0106`.
diff --git a/src/test/ui/lifetimes/lifetime-elision-return-type-trait.rs b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.rs
new file mode 100644
index 0000000..1c288a7
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.rs
@@ -0,0 +1,13 @@
+trait Future {
+    type Item;
+    type Error;
+}
+
+use std::error::Error;
+
+fn foo() -> impl Future<Item=(), Error=Box<Error>> {
+//~^ ERROR missing lifetime
+    Ok(())
+}
+
+fn main() {}
diff --git a/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr
new file mode 100644
index 0000000..b2a3d9a
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr
@@ -0,0 +1,11 @@
+error[E0106]: missing lifetime specifier
+  --> $DIR/lifetime-elision-return-type-trait.rs:8:44
+   |
+LL | fn foo() -> impl Future<Item=(), Error=Box<Error>> {
+   |                                            ^^^^^ help: consider giving it a 'static lifetime: `Error + 'static`
+   |
+   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0106`.
diff --git a/src/test/ui/lifetimes/lifetime-errors/42701_one_named_and_one_anonymous.rs b/src/test/ui/lifetimes/lifetime-errors/42701_one_named_and_one_anonymous.rs
new file mode 100644
index 0000000..b0c09c7
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/42701_one_named_and_one_anonymous.rs
@@ -0,0 +1,14 @@
+struct Foo {
+    field: i32,
+}
+
+fn foo2<'a>(a: &'a Foo, x: &i32) -> &'a i32 {
+    if true {
+        let p: &i32 = &a.field;
+        &*p
+    } else {
+        &*x //~ ERROR explicit lifetime
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/lifetimes/lifetime-errors/42701_one_named_and_one_anonymous.stderr b/src/test/ui/lifetimes/lifetime-errors/42701_one_named_and_one_anonymous.stderr
new file mode 100644
index 0000000..63d0087
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/42701_one_named_and_one_anonymous.stderr
@@ -0,0 +1,12 @@
+error[E0621]: explicit lifetime required in the type of `x`
+  --> $DIR/42701_one_named_and_one_anonymous.rs:10:9
+   |
+LL | fn foo2<'a>(a: &'a Foo, x: &i32) -> &'a i32 {
+   |                            ---- help: add explicit lifetime `'a` to the type of `x`: `&'a i32`
+...
+LL |         &*x
+   |         ^^^ lifetime `'a` required
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.rs b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.rs
new file mode 100644
index 0000000..35f70dd
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.rs
@@ -0,0 +1,20 @@
+#[derive(Clone)]
+enum Foo<'a> {
+    Bar(&'a str),
+}
+
+impl<'a> Foo<'a> {
+    fn bar(&self, other: Foo) -> Foo<'a> {
+        match *self {
+            Foo::Bar(s) => {
+                if s == "test" {
+                    other //~ ERROR explicit lifetime
+                } else {
+                    self.clone()
+                }
+            }
+        }
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.stderr b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.stderr
new file mode 100644
index 0000000..64aa836
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.stderr
@@ -0,0 +1,12 @@
+error[E0621]: explicit lifetime required in the type of `other`
+  --> $DIR/ex1-return-one-existing-name-early-bound-in-struct.rs:11:21
+   |
+LL |     fn bar(&self, other: Foo) -> Foo<'a> {
+   |                          --- help: add explicit lifetime `'a` to the type of `other`: `Foo<'a>`
+...
+LL |                     other
+   |                     ^^^^^ lifetime `'a` required
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-2.rs b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-2.rs
new file mode 100644
index 0000000..9b15b37
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-2.rs
@@ -0,0 +1,5 @@
+fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 {
+    if x > y { x } else { y } //~ ERROR explicit lifetime
+}
+
+fn main() { }
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-2.stderr b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-2.stderr
new file mode 100644
index 0000000..b40481e
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-2.stderr
@@ -0,0 +1,11 @@
+error[E0621]: explicit lifetime required in the type of `x`
+  --> $DIR/ex1-return-one-existing-name-if-else-2.rs:2:16
+   |
+LL | fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 {
+   |               ---- help: add explicit lifetime `'a` to the type of `x`: `&'a i32`
+LL |     if x > y { x } else { y }
+   |                ^ lifetime `'a` required
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-3.rs b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-3.rs
new file mode 100644
index 0000000..6b06212
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-3.rs
@@ -0,0 +1,5 @@
+fn foo<'a>((x, y): (&'a i32, &i32)) -> &'a i32 {
+    if x > y { x } else { y } //~ ERROR explicit lifetime
+}
+
+fn main () { }
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-3.stderr b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-3.stderr
new file mode 100644
index 0000000..194fd95
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-3.stderr
@@ -0,0 +1,11 @@
+error[E0621]: explicit lifetime required in parameter type
+  --> $DIR/ex1-return-one-existing-name-if-else-3.rs:2:27
+   |
+LL | fn foo<'a>((x, y): (&'a i32, &i32)) -> &'a i32 {
+   |                    --------------- help: add explicit lifetime `'a` to type: `(&'a i32, &'a i32)`
+LL |     if x > y { x } else { y }
+   |                           ^ lifetime `'a` required
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.rs b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.rs
new file mode 100644
index 0000000..7bc3fa6
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.rs
@@ -0,0 +1,8 @@
+trait Foo {
+
+fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 {
+   if x > y { x } else { y } //~ ERROR explicit lifetime
+   }
+}
+
+fn main() { }
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.stderr b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.stderr
new file mode 100644
index 0000000..64f4bd0
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.stderr
@@ -0,0 +1,11 @@
+error[E0621]: explicit lifetime required in the type of `x`
+  --> $DIR/ex1-return-one-existing-name-if-else-using-impl-2.rs:4:15
+   |
+LL | fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 {
+   |               ---- help: add explicit lifetime `'a` to the type of `x`: `&'a i32`
+LL |    if x > y { x } else { y }
+   |               ^ lifetime `'a` required
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.rs b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.rs
new file mode 100644
index 0000000..a1126d6
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.rs
@@ -0,0 +1,14 @@
+struct Foo {
+  field: i32
+}
+
+impl Foo {
+  fn foo<'a>(&'a self, x: &i32) -> &i32 {
+
+    if true { &self.field } else { x } //~ ERROR explicit lifetime
+
+  }
+
+}
+
+fn main() { }
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr
new file mode 100644
index 0000000..f764ec4
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr
@@ -0,0 +1,12 @@
+error[E0621]: explicit lifetime required in the type of `x`
+  --> $DIR/ex1-return-one-existing-name-if-else-using-impl-3.rs:8:36
+   |
+LL |   fn foo<'a>(&'a self, x: &i32) -> &i32 {
+   |                           ---- help: add explicit lifetime `'a` to the type of `x`: `&'a i32`
+LL | 
+LL |     if true { &self.field } else { x }
+   |                                    ^ lifetime `'a` required
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.rs b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.rs
new file mode 100644
index 0000000..12024bd
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.rs
@@ -0,0 +1,17 @@
+trait Foo {
+
+    fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32;
+
+}
+
+impl Foo for () {
+
+    fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 {
+
+        if x > y { x } else { y } //~ ERROR lifetime mismatch
+
+    }
+
+}
+
+fn main() {}
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.stderr b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.stderr
new file mode 100644
index 0000000..e9f5fc3
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.stderr
@@ -0,0 +1,14 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ex1-return-one-existing-name-if-else-using-impl.rs:11:20
+   |
+LL |     fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 {
+   |                   ----                 -------
+   |                   |
+   |                   this parameter and the return type are declared with different lifetimes...
+LL | 
+LL |         if x > y { x } else { y }
+   |                    ^ ...but data from `x` is returned here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else.rs b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else.rs
new file mode 100644
index 0000000..f72d567
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else.rs
@@ -0,0 +1,5 @@
+fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 {
+    if x > y { x } else { y } //~ ERROR explicit lifetime
+}
+
+fn main() { }
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else.stderr b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else.stderr
new file mode 100644
index 0000000..29a7069
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else.stderr
@@ -0,0 +1,11 @@
+error[E0621]: explicit lifetime required in the type of `y`
+  --> $DIR/ex1-return-one-existing-name-if-else.rs:2:27
+   |
+LL | fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 {
+   |                           ---- help: add explicit lifetime `'a` to the type of `y`: `&'a i32`
+LL |     if x > y { x } else { y }
+   |                           ^ lifetime `'a` required
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.rs b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.rs
new file mode 100644
index 0000000..ef5dd11
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.rs
@@ -0,0 +1,14 @@
+struct Foo {
+  field: i32
+}
+
+impl Foo {
+  fn foo<'a>(&self, x: &'a i32) -> &i32 {
+
+    x //~ ERROR lifetime mismatch
+
+  }
+
+}
+
+fn main() { }
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr
new file mode 100644
index 0000000..0d506f2
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr
@@ -0,0 +1,14 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ex1-return-one-existing-name-return-type-is-anon.rs:8:5
+   |
+LL |   fn foo<'a>(&self, x: &'a i32) -> &i32 {
+   |                        -------     ----
+   |                        |
+   |                        this parameter and the return type are declared with different lifetimes...
+LL | 
+LL |     x
+   |     ^ ...but data from `x` is returned here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-self-is-anon.rs b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-self-is-anon.rs
new file mode 100644
index 0000000..597d20d
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-self-is-anon.rs
@@ -0,0 +1,13 @@
+struct Foo {
+    field: i32,
+}
+
+impl Foo {
+    fn foo<'a>(&self, x: &'a Foo) -> &'a Foo {
+
+        if true { x } else { self } //~ ERROR lifetime mismatch
+
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-self-is-anon.stderr b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-self-is-anon.stderr
new file mode 100644
index 0000000..98a2361
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-self-is-anon.stderr
@@ -0,0 +1,14 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ex1-return-one-existing-name-self-is-anon.rs:8:30
+   |
+LL |     fn foo<'a>(&self, x: &'a Foo) -> &'a Foo {
+   |                -----                 -------
+   |                |
+   |                this parameter and the return type are declared with different lifetimes...
+LL | 
+LL |         if true { x } else { self }
+   |                              ^^^^ ...but data from `self` is returned here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.rs b/src/test/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.rs
new file mode 100644
index 0000000..d1263a4
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.rs
@@ -0,0 +1,5 @@
+fn foo(x: &i32, y: &i32) -> &i32 { //~ ERROR missing lifetime
+    if x > y { x } else { y }
+}
+
+fn main() { }
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr b/src/test/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr
new file mode 100644
index 0000000..a4e0d71
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr
@@ -0,0 +1,11 @@
+error[E0106]: missing lifetime specifier
+  --> $DIR/ex1b-return-no-names-if-else.rs:1:29
+   |
+LL | fn foo(x: &i32, y: &i32) -> &i32 {
+   |                             ^ expected lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `x` or `y`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0106`.
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name-2.rs b/src/test/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name-2.rs
new file mode 100644
index 0000000..998a48c
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name-2.rs
@@ -0,0 +1,9 @@
+struct Ref<'a, T: 'a> {
+    data: &'a T
+}
+
+fn foo<'a>(x: Ref<i32>, y: &mut Vec<Ref<'a, i32>>) {
+    y.push(x); //~ ERROR explicit lifetime
+}
+
+fn main() { }
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name-2.stderr b/src/test/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name-2.stderr
new file mode 100644
index 0000000..412cac4
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name-2.stderr
@@ -0,0 +1,11 @@
+error[E0621]: explicit lifetime required in the type of `x`
+  --> $DIR/ex2a-push-one-existing-name-2.rs:6:12
+   |
+LL | fn foo<'a>(x: Ref<i32>, y: &mut Vec<Ref<'a, i32>>) {
+   |               -------- help: add explicit lifetime `'a` to the type of `x`: `Ref<'a, i32>`
+LL |     y.push(x);
+   |            ^ lifetime `'a` required
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name-early-bound.rs b/src/test/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name-early-bound.rs
new file mode 100644
index 0000000..d18b50d
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name-early-bound.rs
@@ -0,0 +1,11 @@
+trait Foo<'a> {}
+impl<'a, T> Foo<'a> for T {}
+
+fn baz<'a, 'b, T>(x: &mut Vec<&'a T>, y: &T)
+    where i32: Foo<'a>,
+          u32: Foo<'b>
+{
+    x.push(y); //~ ERROR explicit lifetime required
+}
+fn main() {
+}
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name-early-bound.stderr b/src/test/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name-early-bound.stderr
new file mode 100644
index 0000000..30826c3
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name-early-bound.stderr
@@ -0,0 +1,12 @@
+error[E0621]: explicit lifetime required in the type of `y`
+  --> $DIR/ex2a-push-one-existing-name-early-bound.rs:8:12
+   |
+LL | fn baz<'a, 'b, T>(x: &mut Vec<&'a T>, y: &T)
+   |                                          -- help: add explicit lifetime `'a` to the type of `y`: `&'a T`
+...
+LL |     x.push(y);
+   |            ^ lifetime `'a` required
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name.rs b/src/test/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name.rs
new file mode 100644
index 0000000..5188ea1
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name.rs
@@ -0,0 +1,9 @@
+struct Ref<'a, T: 'a> {
+    data: &'a T
+}
+
+fn foo<'a>(x: &mut Vec<Ref<'a, i32>>, y: Ref<i32>) {
+    x.push(y); //~ ERROR explicit lifetime
+}
+
+fn main() { }
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name.stderr b/src/test/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name.stderr
new file mode 100644
index 0000000..13d0835
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name.stderr
@@ -0,0 +1,11 @@
+error[E0621]: explicit lifetime required in the type of `y`
+  --> $DIR/ex2a-push-one-existing-name.rs:6:12
+   |
+LL | fn foo<'a>(x: &mut Vec<Ref<'a, i32>>, y: Ref<i32>) {
+   |                                          -------- help: add explicit lifetime `'a` to the type of `y`: `Ref<'a, i32>`
+LL |     x.push(y);
+   |            ^ lifetime `'a` required
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex2b-push-no-existing-names.rs b/src/test/ui/lifetimes/lifetime-errors/ex2b-push-no-existing-names.rs
new file mode 100644
index 0000000..82e0c9b
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex2b-push-no-existing-names.rs
@@ -0,0 +1,9 @@
+struct Ref<'a, T: 'a> {
+    data: &'a T
+}
+
+fn foo(x: &mut Vec<Ref<i32>>, y: Ref<i32>) {
+    x.push(y); //~ ERROR lifetime mismatch
+}
+
+fn main() { }
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex2b-push-no-existing-names.stderr b/src/test/ui/lifetimes/lifetime-errors/ex2b-push-no-existing-names.stderr
new file mode 100644
index 0000000..e505c9c
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex2b-push-no-existing-names.stderr
@@ -0,0 +1,11 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ex2b-push-no-existing-names.rs:6:12
+   |
+LL | fn foo(x: &mut Vec<Ref<i32>>, y: Ref<i32>) {
+   |                    --------      -------- these two types are declared with different lifetimes...
+LL |     x.push(y);
+   |            ^ ...but data from `y` flows into `x` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex2c-push-inference-variable.rs b/src/test/ui/lifetimes/lifetime-errors/ex2c-push-inference-variable.rs
new file mode 100644
index 0000000..7f15aee
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex2c-push-inference-variable.rs
@@ -0,0 +1,10 @@
+struct Ref<'a, T: 'a> {
+    data: &'a T
+}
+
+fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
+    let z = Ref { data: y.data };
+    x.push(z); //~ ERROR lifetime mismatch
+}
+
+fn main() { }
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex2c-push-inference-variable.stderr b/src/test/ui/lifetimes/lifetime-errors/ex2c-push-inference-variable.stderr
new file mode 100644
index 0000000..63b1c6d
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex2c-push-inference-variable.stderr
@@ -0,0 +1,12 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ex2c-push-inference-variable.rs:7:12
+   |
+LL | fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
+   |                                   ------------      ------------ these two types are declared with different lifetimes...
+LL |     let z = Ref { data: y.data };
+LL |     x.push(z);
+   |            ^ ...but data from `y` flows into `x` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex2d-push-inference-variable-2.rs b/src/test/ui/lifetimes/lifetime-errors/ex2d-push-inference-variable-2.rs
new file mode 100644
index 0000000..ee77d9e
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex2d-push-inference-variable-2.rs
@@ -0,0 +1,11 @@
+struct Ref<'a, T: 'a> {
+    data: &'a T
+}
+
+fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
+    let a: &mut Vec<Ref<i32>> = x; //~ ERROR lifetime mismatch
+    let b = Ref { data: y.data };
+    a.push(b);
+}
+
+fn main() { }
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex2d-push-inference-variable-2.stderr b/src/test/ui/lifetimes/lifetime-errors/ex2d-push-inference-variable-2.stderr
new file mode 100644
index 0000000..2f669ef
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex2d-push-inference-variable-2.stderr
@@ -0,0 +1,11 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ex2d-push-inference-variable-2.rs:6:33
+   |
+LL | fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
+   |                                   ------------      ------------ these two types are declared with different lifetimes...
+LL |     let a: &mut Vec<Ref<i32>> = x;
+   |                                 ^ ...but data from `y` flows into `x` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex2e-push-inference-variable-3.rs b/src/test/ui/lifetimes/lifetime-errors/ex2e-push-inference-variable-3.rs
new file mode 100644
index 0000000..e2a795a
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex2e-push-inference-variable-3.rs
@@ -0,0 +1,11 @@
+struct Ref<'a, T: 'a> {
+    data: &'a T
+}
+
+fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
+    let a: &mut Vec<Ref<i32>> = x; //~ ERROR lifetime mismatch
+    let b = Ref { data: y.data };
+    Vec::push(a, b);
+}
+
+fn main() { }
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex2e-push-inference-variable-3.stderr b/src/test/ui/lifetimes/lifetime-errors/ex2e-push-inference-variable-3.stderr
new file mode 100644
index 0000000..258b680
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex2e-push-inference-variable-3.stderr
@@ -0,0 +1,11 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ex2e-push-inference-variable-3.rs:6:33
+   |
+LL | fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
+   |                                   ------------      ------------ these two types are declared with different lifetimes...
+LL |     let a: &mut Vec<Ref<i32>> = x;
+   |                                 ^ ...but data from `y` flows into `x` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.rs b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.rs
new file mode 100644
index 0000000..1ff96aa
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.rs
@@ -0,0 +1,5 @@
+fn foo(&mut (ref mut v, w): &mut (&u8, &u8), x: &u8) {
+    *v = x; //~ ERROR lifetime mismatch
+}
+
+fn main() { }
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.stderr
new file mode 100644
index 0000000..0aff80c
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.stderr
@@ -0,0 +1,11 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions-2.rs:2:10
+   |
+LL | fn foo(&mut (ref mut v, w): &mut (&u8, &u8), x: &u8) {
+   |                                   ---           --- these two types are declared with different lifetimes...
+LL |     *v = x;
+   |          ^ ...but data from `x` flows here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.rs b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.rs
new file mode 100644
index 0000000..c04b5d3
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.rs
@@ -0,0 +1,7 @@
+fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) {
+    z.push((x,y)); //~ ERROR lifetime mismatch
+    //~^ ERROR lifetime mismatch
+}
+
+fn main() { }
+
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.stderr
new file mode 100644
index 0000000..2e5ff67
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.stderr
@@ -0,0 +1,19 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions-3.rs:2:13
+   |
+LL | fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) {
+   |                     ---                 --- these two types are declared with different lifetimes...
+LL |     z.push((x,y));
+   |             ^ ...but data flows into `z` here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions-3.rs:2:15
+   |
+LL | fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) {
+   |                         ---                  --- these two types are declared with different lifetimes...
+LL |     z.push((x,y));
+   |               ^ ...but data flows into `z` here
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.rs b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.rs
new file mode 100644
index 0000000..94bb809
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.rs
@@ -0,0 +1,10 @@
+struct Ref<'a, 'b> {
+    a: &'a u32,
+    b: &'b u32,
+}
+
+fn foo(mut x: Ref, y: Ref) {
+    x.b = y.b; //~ ERROR lifetime mismatch
+}
+
+fn main() {}
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.stderr
new file mode 100644
index 0000000..8e41d7c
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.stderr
@@ -0,0 +1,11 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions-both-are-structs-2.rs:7:11
+   |
+LL | fn foo(mut x: Ref, y: Ref) {
+   |               ---     --- these two types are declared with different lifetimes...
+LL |     x.b = y.b;
+   |           ^^^ ...but data from `y` flows into `x` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.rs b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.rs
new file mode 100644
index 0000000..3b22aef
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.rs
@@ -0,0 +1,10 @@
+struct Ref<'a, 'b> {
+    a: &'a u32,
+    b: &'b u32,
+}
+
+fn foo(mut x: Ref) {
+    x.a = x.b; //~ ERROR lifetime mismatch
+}
+
+fn main() {}
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.stderr
new file mode 100644
index 0000000..da83ebc
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.stderr
@@ -0,0 +1,13 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions-both-are-structs-3.rs:7:11
+   |
+LL | fn foo(mut x: Ref) {
+   |               ---
+   |               |
+   |               this type is declared with multiple lifetimes...
+LL |     x.a = x.b;
+   |           ^^^ ...but data with one lifetime flows into the other here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.rs b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.rs
new file mode 100644
index 0000000..87f9cc1
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.rs
@@ -0,0 +1,12 @@
+struct Ref<'a> {
+    x: &'a u32,
+}
+
+fn foo<'a, 'b>(mut x: Vec<Ref<'a>>, y: Ref<'b>)
+    where &'a (): Sized,
+          &'b u32: Sized
+{
+    x.push(y); //~ ERROR lifetime mismatch
+}
+
+fn main() {}
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.stderr
new file mode 100644
index 0000000..374bbd9
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.stderr
@@ -0,0 +1,12 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions-both-are-structs-earlybound-regions.rs:9:12
+   |
+LL | fn foo<'a, 'b>(mut x: Vec<Ref<'a>>, y: Ref<'b>)
+   |                           -------      ------- these two types are declared with different lifetimes...
+...
+LL |     x.push(y);
+   |            ^ ...but data from `y` flows into `x` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.rs b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.rs
new file mode 100644
index 0000000..4be76c2
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.rs
@@ -0,0 +1,9 @@
+struct Ref<'a> {
+    x: &'a u32,
+}
+
+fn foo<'a, 'b>(mut x: Vec<Ref<'a>>, y: Ref<'b>) {
+    x.push(y); //~ ERROR lifetime mismatch
+}
+
+fn main() {}
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.stderr
new file mode 100644
index 0000000..94798d1
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.stderr
@@ -0,0 +1,11 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions-both-are-structs-latebound-regions.rs:6:12
+   |
+LL | fn foo<'a, 'b>(mut x: Vec<Ref<'a>>, y: Ref<'b>) {
+   |                           -------      ------- these two types are declared with different lifetimes...
+LL |     x.push(y);
+   |            ^ ...but data from `y` flows into `x` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs.rs b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs.rs
new file mode 100644
index 0000000..8fbb405
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs.rs
@@ -0,0 +1,9 @@
+struct Ref<'a> {
+    x: &'a u32,
+}
+
+fn foo(mut x: Vec<Ref>, y: Ref) {
+    x.push(y); //~ ERROR lifetime mismatch
+}
+
+fn main() {}
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs.stderr
new file mode 100644
index 0000000..9f5a79e
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs.stderr
@@ -0,0 +1,11 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions-both-are-structs.rs:6:12
+   |
+LL | fn foo(mut x: Vec<Ref>, y: Ref) {
+   |                   ---      --- these two types are declared with different lifetimes...
+LL |     x.push(y);
+   |            ^ ...but data from `y` flows into `x` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-latebound-regions.rs b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-latebound-regions.rs
new file mode 100644
index 0000000..7938d11
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-latebound-regions.rs
@@ -0,0 +1,5 @@
+fn foo<'a,'b>(x: &mut Vec<&'a u8>, y: &'b u8) {
+    x.push(y); //~ ERROR lifetime mismatch
+}
+
+fn main() { }
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-latebound-regions.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-latebound-regions.stderr
new file mode 100644
index 0000000..2c87f8d
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-latebound-regions.stderr
@@ -0,0 +1,11 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions-latebound-regions.rs:2:12
+   |
+LL | fn foo<'a,'b>(x: &mut Vec<&'a u8>, y: &'b u8) {
+   |                           ------      ------ these two types are declared with different lifetimes...
+LL |     x.push(y);
+   |            ^ ...but data from `y` flows into `x` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.rs b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.rs
new file mode 100644
index 0000000..1e6425c
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.rs
@@ -0,0 +1,7 @@
+struct Ref<'a, 'b> { a: &'a u32, b: &'b u32 }
+
+fn foo(mut x: Ref, y: &u32) {
+    y = x.b; //~ ERROR lifetime mismatch
+}
+
+fn main() { }
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.stderr
new file mode 100644
index 0000000..60b92ed
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.stderr
@@ -0,0 +1,13 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions-one-is-struct-2.rs:4:9
+   |
+LL | fn foo(mut x: Ref, y: &u32) {
+   |               ---     ----
+   |               |
+   |               these two types are declared with different lifetimes...
+LL |     y = x.b;
+   |         ^^^ ...but data from `x` flows into `y` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.rs b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.rs
new file mode 100644
index 0000000..0283836
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.rs
@@ -0,0 +1,7 @@
+struct Ref<'a, 'b> { a: &'a u32, b: &'b u32 }
+
+fn foo(mut y: Ref, x: &u32) {
+    y.b = x; //~ ERROR lifetime mismatch
+}
+
+fn main() { }
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.stderr
new file mode 100644
index 0000000..a220c8d
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.stderr
@@ -0,0 +1,11 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions-one-is-struct-3.rs:4:11
+   |
+LL | fn foo(mut y: Ref, x: &u32) {
+   |               ---     ---- these two types are declared with different lifetimes...
+LL |     y.b = x;
+   |           ^ ...but data from `x` flows into `y` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-4.rs b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-4.rs
new file mode 100644
index 0000000..0283836
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-4.rs
@@ -0,0 +1,7 @@
+struct Ref<'a, 'b> { a: &'a u32, b: &'b u32 }
+
+fn foo(mut y: Ref, x: &u32) {
+    y.b = x; //~ ERROR lifetime mismatch
+}
+
+fn main() { }
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-4.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-4.stderr
new file mode 100644
index 0000000..73472a8
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-4.stderr
@@ -0,0 +1,11 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions-one-is-struct-4.rs:4:11
+   |
+LL | fn foo(mut y: Ref, x: &u32) {
+   |               ---     ---- these two types are declared with different lifetimes...
+LL |     y.b = x;
+   |           ^ ...but data from `x` flows into `y` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct.rs b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct.rs
new file mode 100644
index 0000000..7c82751
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct.rs
@@ -0,0 +1,10 @@
+struct Ref<'a, 'b> {
+    a: &'a u32,
+    b: &'b u32,
+}
+
+fn foo(mut x: Ref, y: &u32) {
+    x.b = y; //~ ERROR lifetime mismatch
+}
+
+fn main() {}
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct.stderr
new file mode 100644
index 0000000..eb6e6f2
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct.stderr
@@ -0,0 +1,11 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions-one-is-struct.rs:7:11
+   |
+LL | fn foo(mut x: Ref, y: &u32) {
+   |               ---     ---- these two types are declared with different lifetimes...
+LL |     x.b = y;
+   |           ^ ...but data from `y` flows into `x` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.rs b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.rs
new file mode 100644
index 0000000..0985240
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.rs
@@ -0,0 +1,12 @@
+struct Foo {
+  field: i32
+}
+
+impl Foo {
+  fn foo<'a>(&self, x: &i32) -> &i32 {
+    x //~ ERROR lifetime mismatch
+  }
+}
+
+fn main() { }
+
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.stderr
new file mode 100644
index 0000000..199f880
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.stderr
@@ -0,0 +1,13 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions-return-type-is-anon.rs:7:5
+   |
+LL |   fn foo<'a>(&self, x: &i32) -> &i32 {
+   |                        ----     ----
+   |                        |
+   |                        this parameter and the return type are declared with different lifetimes...
+LL |     x
+   |     ^ ...but data from `x` is returned here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-self-is-anon.rs b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-self-is-anon.rs
new file mode 100644
index 0000000..33aa199
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-self-is-anon.rs
@@ -0,0 +1,12 @@
+struct Foo {
+    field: i32,
+}
+
+impl Foo {
+    fn foo<'a>(&self, x: &Foo) -> &Foo {
+        if true { x } else { self } //~ ERROR lifetime mismatch
+    }
+}
+
+fn main() {}
+
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-self-is-anon.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-self-is-anon.stderr
new file mode 100644
index 0000000..838f43b
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-self-is-anon.stderr
@@ -0,0 +1,13 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions-self-is-anon.rs:7:19
+   |
+LL |     fn foo<'a>(&self, x: &Foo) -> &Foo {
+   |                          ----     ----
+   |                          |
+   |                          this parameter and the return type are declared with different lifetimes...
+LL |         if true { x } else { self }
+   |                   ^ ...but data from `x` is returned here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.rs b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.rs
new file mode 100644
index 0000000..f9f1a75
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.rs
@@ -0,0 +1,5 @@
+fn foo(x:fn(&u8, &u8), y: Vec<&u8>, z: &u8) {
+  y.push(z); //~ ERROR lifetime mismatch
+}
+
+fn main() { }
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.stderr
new file mode 100644
index 0000000..d2cc3db
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.stderr
@@ -0,0 +1,11 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions-using-fn-items.rs:2:10
+   |
+LL | fn foo(x:fn(&u8, &u8), y: Vec<&u8>, z: &u8) {
+   |                               ---      --- these two types are declared with different lifetimes...
+LL |   y.push(z);
+   |          ^ ...but data from `z` flows into `y` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-impl-items.rs b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-impl-items.rs
new file mode 100644
index 0000000..6f95d5a
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-impl-items.rs
@@ -0,0 +1,9 @@
+trait Foo {
+    fn foo<'a>(x: &mut Vec<&u8>, y: &u8);
+}
+impl Foo for () {
+    fn foo(x: &mut Vec<&u8>, y: &u8) {
+        x.push(y); //~ ERROR lifetime mismatch
+    }
+}
+fn main() {}
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-impl-items.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-impl-items.stderr
new file mode 100644
index 0000000..e8b0208
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-impl-items.stderr
@@ -0,0 +1,11 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions-using-impl-items.rs:6:16
+   |
+LL |     fn foo(x: &mut Vec<&u8>, y: &u8) {
+   |                        ---      --- these two types are declared with different lifetimes...
+LL |         x.push(y);
+   |                ^ ...but data from `y` flows into `x` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.rs b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.rs
new file mode 100644
index 0000000..324a584
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.rs
@@ -0,0 +1,5 @@
+fn foo(x:Box<Fn(&u8, &u8)> , y: Vec<&u8>, z: &u8) {
+  y.push(z); //~ ERROR lifetime mismatch
+}
+
+fn main() { }
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.stderr
new file mode 100644
index 0000000..5ad85c9
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.stderr
@@ -0,0 +1,11 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions-using-trait-objects.rs:2:10
+   |
+LL | fn foo(x:Box<Fn(&u8, &u8)> , y: Vec<&u8>, z: &u8) {
+   |                 ---  --- these two types are declared with different lifetimes...
+LL |   y.push(z);
+   |          ^ ...but data from `z` flows into `y` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.rs b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.rs
new file mode 100644
index 0000000..44195da
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.rs
@@ -0,0 +1,5 @@
+fn foo(x: &mut Vec<&u8>, y: &u8) {
+    x.push(y); //~ ERROR lifetime mismatch
+}
+
+fn main() { }
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.stderr
new file mode 100644
index 0000000..b278482
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.stderr
@@ -0,0 +1,11 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions.rs:2:12
+   |
+LL | fn foo(x: &mut Vec<&u8>, y: &u8) {
+   |                    ---      --- these two types are declared with different lifetimes...
+LL |     x.push(y);
+   |            ^ ...but data from `y` flows into `x` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/lifetimes/lifetime-errors/liveness-assign-imm-local-notes.rs b/src/test/ui/lifetimes/lifetime-errors/liveness-assign-imm-local-notes.rs
new file mode 100644
index 0000000..99949e1
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/liveness-assign-imm-local-notes.rs
@@ -0,0 +1,44 @@
+// FIXME: Change to UI Test
+// Check notes are placed on an assignment that can actually precede the current assignment
+// Don't emit a first assignment for assignment in a loop.
+
+// compile-flags: -Zborrowck=compare
+
+fn test() {
+    let x;
+    if true {
+        x = 1;
+    } else {
+        x = 2;
+        x = 3;      //~ ERROR (Ast) [E0384]
+                    //~^ ERROR (Mir) [E0384]
+    }
+}
+
+fn test_in_loop() {
+    loop {
+        let x;
+        if true {
+            x = 1;
+        } else {
+            x = 2;
+            x = 3;      //~ ERROR (Ast) [E0384]
+                        //~^ ERROR (Mir) [E0384]
+        }
+    }
+}
+
+fn test_using_loop() {
+    let x;
+    loop {
+        if true {
+            x = 1;      //~ ERROR (Ast) [E0384]
+                        //~^ ERROR (Mir) [E0384]
+        } else {
+            x = 2;      //~ ERROR (Ast) [E0384]
+                        //~^ ERROR (Mir) [E0384]
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/lifetimes/lifetime-errors/liveness-assign-imm-local-notes.stderr b/src/test/ui/lifetimes/lifetime-errors/liveness-assign-imm-local-notes.stderr
new file mode 100644
index 0000000..e15290f
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/liveness-assign-imm-local-notes.stderr
@@ -0,0 +1,77 @@
+error[E0384]: cannot assign twice to immutable variable `x` (Ast)
+  --> $DIR/liveness-assign-imm-local-notes.rs:13:9
+   |
+LL |         x = 2;
+   |         ----- first assignment to `x`
+LL |         x = 3;
+   |         ^^^^^ cannot assign twice to immutable variable
+
+error[E0384]: cannot assign twice to immutable variable `x` (Ast)
+  --> $DIR/liveness-assign-imm-local-notes.rs:25:13
+   |
+LL |             x = 2;
+   |             ----- first assignment to `x`
+LL |             x = 3;
+   |             ^^^^^ cannot assign twice to immutable variable
+
+error[E0384]: cannot assign twice to immutable variable `x` (Ast)
+  --> $DIR/liveness-assign-imm-local-notes.rs:35:13
+   |
+LL |             x = 1;
+   |             ^^^^^ cannot assign twice to immutable variable
+
+error[E0384]: cannot assign twice to immutable variable `x` (Ast)
+  --> $DIR/liveness-assign-imm-local-notes.rs:38:13
+   |
+LL |             x = 1;
+   |             ----- first assignment to `x`
+...
+LL |             x = 2;
+   |             ^^^^^ cannot assign twice to immutable variable
+
+error[E0384]: cannot assign twice to immutable variable `x` (Mir)
+  --> $DIR/liveness-assign-imm-local-notes.rs:13:9
+   |
+LL |     let x;
+   |         - help: make this binding mutable: `mut x`
+...
+LL |         x = 2;
+   |         ----- first assignment to `x`
+LL |         x = 3;
+   |         ^^^^^ cannot assign twice to immutable variable
+
+error[E0384]: cannot assign twice to immutable variable `x` (Mir)
+  --> $DIR/liveness-assign-imm-local-notes.rs:25:13
+   |
+LL |         let x;
+   |             - help: make this binding mutable: `mut x`
+...
+LL |             x = 2;
+   |             ----- first assignment to `x`
+LL |             x = 3;
+   |             ^^^^^ cannot assign twice to immutable variable
+
+error[E0384]: cannot assign twice to immutable variable `x` (Mir)
+  --> $DIR/liveness-assign-imm-local-notes.rs:35:13
+   |
+LL |     let x;
+   |         - help: make this binding mutable: `mut x`
+...
+LL |             x = 1;
+   |             ^^^^^ cannot assign twice to immutable variable
+
+error[E0384]: cannot assign twice to immutable variable `x` (Mir)
+  --> $DIR/liveness-assign-imm-local-notes.rs:38:13
+   |
+LL |     let x;
+   |         - help: make this binding mutable: `mut x`
+...
+LL |             x = 1;
+   |             ----- first assignment to `x`
+...
+LL |             x = 2;
+   |             ^^^^^ cannot assign twice to immutable variable
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0384`.
diff --git a/src/test/ui/lifetimes/lifetime-no-keyword.rs b/src/test/ui/lifetimes/lifetime-no-keyword.rs
new file mode 100644
index 0000000..f466f44
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-no-keyword.rs
@@ -0,0 +1,7 @@
+fn foo<'a>(a: &'a isize) { }
+fn bar(a: &'static isize) { }
+fn baz<'let>(a: &'let isize) { } //~ ERROR lifetimes cannot use keyword names
+//~^ ERROR lifetimes cannot use keyword names
+fn zab<'self>(a: &'self isize) { } //~ ERROR lifetimes cannot use keyword names
+//~^ ERROR lifetimes cannot use keyword names
+fn main() { }
diff --git a/src/test/ui/lifetimes/lifetime-no-keyword.stderr b/src/test/ui/lifetimes/lifetime-no-keyword.stderr
new file mode 100644
index 0000000..ba8ceb8
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-no-keyword.stderr
@@ -0,0 +1,26 @@
+error: lifetimes cannot use keyword names
+  --> $DIR/lifetime-no-keyword.rs:3:8
+   |
+LL | fn baz<'let>(a: &'let isize) { }
+   |        ^^^^
+
+error: lifetimes cannot use keyword names
+  --> $DIR/lifetime-no-keyword.rs:3:18
+   |
+LL | fn baz<'let>(a: &'let isize) { }
+   |                  ^^^^
+
+error: lifetimes cannot use keyword names
+  --> $DIR/lifetime-no-keyword.rs:5:8
+   |
+LL | fn zab<'self>(a: &'self isize) { }
+   |        ^^^^^
+
+error: lifetimes cannot use keyword names
+  --> $DIR/lifetime-no-keyword.rs:5:19
+   |
+LL | fn zab<'self>(a: &'self isize) { }
+   |                   ^^^^^
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/linkage2.rs b/src/test/ui/linkage2.rs
new file mode 100644
index 0000000..6d1410a
--- /dev/null
+++ b/src/test/ui/linkage2.rs
@@ -0,0 +1,10 @@
+#![feature(linkage)]
+
+extern {
+    #[linkage = "extern_weak"] static foo: i32;
+    //~^ ERROR: must have type `*const T` or `*mut T`
+}
+
+fn main() {
+    println!("{}", unsafe { foo });
+}
diff --git a/src/test/ui/linkage2.stderr b/src/test/ui/linkage2.stderr
new file mode 100644
index 0000000..64213f1
--- /dev/null
+++ b/src/test/ui/linkage2.stderr
@@ -0,0 +1,8 @@
+error: must have type `*const T` or `*mut T`
+  --> $DIR/linkage2.rs:4:32
+   |
+LL |     #[linkage = "extern_weak"] static foo: i32;
+   |                                ^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/linkage3.rs b/src/test/ui/linkage3.rs
new file mode 100644
index 0000000..f094a0d
--- /dev/null
+++ b/src/test/ui/linkage3.rs
@@ -0,0 +1,10 @@
+#![feature(linkage)]
+
+extern {
+    #[linkage = "foo"] static foo: *const i32;
+    //~^ ERROR: invalid linkage specified
+}
+
+fn main() {
+    println!("{:?}", unsafe { foo });
+}
diff --git a/src/test/ui/linkage3.stderr b/src/test/ui/linkage3.stderr
new file mode 100644
index 0000000..a03593f
--- /dev/null
+++ b/src/test/ui/linkage3.stderr
@@ -0,0 +1,8 @@
+error: invalid linkage specified
+  --> $DIR/linkage3.rs:4:24
+   |
+LL |     #[linkage = "foo"] static foo: *const i32;
+   |                        ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/linkage4.rs b/src/test/ui/linkage4.rs
new file mode 100644
index 0000000..3b935f9
--- /dev/null
+++ b/src/test/ui/linkage4.rs
@@ -0,0 +1,5 @@
+#[linkage = "external"]
+static foo: isize = 0;
+//~^^ ERROR: the `linkage` attribute is experimental and not portable
+
+fn main() {}
diff --git a/src/test/ui/linkage4.stderr b/src/test/ui/linkage4.stderr
new file mode 100644
index 0000000..fd86671
--- /dev/null
+++ b/src/test/ui/linkage4.stderr
@@ -0,0 +1,11 @@
+error[E0658]: the `linkage` attribute is experimental and not portable across platforms (see issue #29603)
+  --> $DIR/linkage4.rs:1:1
+   |
+LL | #[linkage = "external"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(linkage)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/lint/auxiliary/inherited_stability.rs b/src/test/ui/lint/auxiliary/inherited_stability.rs
new file mode 100644
index 0000000..57af0d3
--- /dev/null
+++ b/src/test/ui/lint/auxiliary/inherited_stability.rs
@@ -0,0 +1,47 @@
+#![crate_name="inherited_stability"]
+#![crate_type = "lib"]
+#![unstable(feature = "unstable_test_feature", issue = "0")]
+#![feature(staged_api)]
+
+pub fn unstable() {}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+pub fn stable() {}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+pub mod stable_mod {
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    pub fn unstable() {}
+
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn stable() {}
+}
+
+#[unstable(feature = "unstable_test_feature", issue = "0")]
+pub mod unstable_mod {
+    #[stable(feature = "stable_test_feature", since = "1.0.0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    pub fn deprecated() {}
+
+    pub fn unstable() {}
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+pub trait Stable {
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    fn unstable(&self);
+
+    #[stable(feature = "rust1", since = "1.0.0")]
+    fn stable(&self);
+}
+
+impl Stable for usize {
+    fn unstable(&self) {}
+    fn stable(&self) {}
+}
+
+pub enum Unstable {
+    UnstableVariant,
+    #[stable(feature = "rust1", since = "1.0.0")]
+    StableVariant
+}
diff --git a/src/test/ui/lint/auxiliary/lint_output_format.rs b/src/test/ui/lint/auxiliary/lint_output_format.rs
new file mode 100644
index 0000000..5facb55
--- /dev/null
+++ b/src/test/ui/lint/auxiliary/lint_output_format.rs
@@ -0,0 +1,20 @@
+#![crate_name="lint_output_format"]
+#![crate_type = "lib"]
+#![feature(staged_api)]
+#![unstable(feature = "unstable_test_feature", issue = "0")]
+
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+#[rustc_deprecated(since = "1.0.0", reason = "text")]
+pub fn foo() -> usize {
+    20
+}
+
+#[unstable(feature = "unstable_test_feature", issue = "0")]
+pub fn bar() -> usize {
+    40
+}
+
+#[unstable(feature = "unstable_test_feature", issue = "0")]
+pub fn baz() -> usize {
+    30
+}
diff --git a/src/test/ui/lint/auxiliary/lint_stability.rs b/src/test/ui/lint/auxiliary/lint_stability.rs
new file mode 100644
index 0000000..3188d70
--- /dev/null
+++ b/src/test/ui/lint/auxiliary/lint_stability.rs
@@ -0,0 +1,188 @@
+#![crate_name="lint_stability"]
+#![crate_type = "lib"]
+#![feature(staged_api)]
+#![feature(associated_type_defaults)]
+#![stable(feature = "lint_stability", since = "1.0.0")]
+
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+#[rustc_deprecated(since = "1.0.0", reason = "text")]
+pub fn deprecated() {}
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+#[rustc_deprecated(since = "1.0.0", reason = "text")]
+pub fn deprecated_text() {}
+
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+#[rustc_deprecated(since = "99.99.99", reason = "text")]
+pub fn deprecated_future() {}
+
+#[unstable(feature = "unstable_test_feature", issue = "0")]
+#[rustc_deprecated(since = "1.0.0", reason = "text")]
+pub fn deprecated_unstable() {}
+#[unstable(feature = "unstable_test_feature", issue = "0")]
+#[rustc_deprecated(since = "1.0.0", reason = "text")]
+pub fn deprecated_unstable_text() {}
+
+#[unstable(feature = "unstable_test_feature", issue = "0")]
+pub fn unstable() {}
+#[unstable(feature = "unstable_test_feature", reason = "text", issue = "0")]
+pub fn unstable_text() {}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+pub fn stable() {}
+#[stable(feature = "rust1", since = "1.0.0")]
+pub fn stable_text() {}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct MethodTester;
+
+impl MethodTester {
+    #[stable(feature = "stable_test_feature", since = "1.0.0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    pub fn method_deprecated(&self) {}
+    #[stable(feature = "stable_test_feature", since = "1.0.0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    pub fn method_deprecated_text(&self) {}
+
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    pub fn method_deprecated_unstable(&self) {}
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    pub fn method_deprecated_unstable_text(&self) {}
+
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    pub fn method_unstable(&self) {}
+    #[unstable(feature = "unstable_test_feature", reason = "text", issue = "0")]
+    pub fn method_unstable_text(&self) {}
+
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn method_stable(&self) {}
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn method_stable_text(&self) {}
+}
+
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+pub trait Trait {
+    #[stable(feature = "stable_test_feature", since = "1.0.0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    fn trait_deprecated(&self) {}
+    #[stable(feature = "stable_test_feature", since = "1.0.0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    fn trait_deprecated_text(&self) {}
+
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    fn trait_deprecated_unstable(&self) {}
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    fn trait_deprecated_unstable_text(&self) {}
+
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    fn trait_unstable(&self) {}
+    #[unstable(feature = "unstable_test_feature", reason = "text", issue = "0")]
+    fn trait_unstable_text(&self) {}
+
+    #[stable(feature = "rust1", since = "1.0.0")]
+    fn trait_stable(&self) {}
+    #[stable(feature = "rust1", since = "1.0.0")]
+    fn trait_stable_text(&self) {}
+}
+
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+pub trait TraitWithAssociatedTypes {
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    type TypeUnstable = u8;
+    #[stable(feature = "stable_test_feature", since = "1.0.0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    type TypeDeprecated = u8;
+}
+
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+impl Trait for MethodTester {}
+
+#[unstable(feature = "unstable_test_feature", issue = "0")]
+pub trait UnstableTrait { fn dummy(&self) { } }
+
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+#[rustc_deprecated(since = "1.0.0", reason = "text")]
+pub trait DeprecatedTrait {
+    #[stable(feature = "stable_test_feature", since = "1.0.0")] fn dummy(&self) { }
+}
+
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+#[rustc_deprecated(since = "1.0.0", reason = "text")]
+pub struct DeprecatedStruct {
+    #[stable(feature = "stable_test_feature", since = "1.0.0")] pub i: isize
+}
+#[unstable(feature = "unstable_test_feature", issue = "0")]
+#[rustc_deprecated(since = "1.0.0", reason = "text")]
+pub struct DeprecatedUnstableStruct {
+    #[stable(feature = "stable_test_feature", since = "1.0.0")] pub i: isize
+}
+#[unstable(feature = "unstable_test_feature", issue = "0")]
+pub struct UnstableStruct {
+    #[stable(feature = "stable_test_feature", since = "1.0.0")] pub i: isize
+}
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct StableStruct {
+    #[stable(feature = "stable_test_feature", since = "1.0.0")] pub i: isize
+}
+#[unstable(feature = "unstable_test_feature", issue = "0")]
+pub enum UnstableEnum {}
+#[stable(feature = "rust1", since = "1.0.0")]
+pub enum StableEnum {}
+
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+#[rustc_deprecated(since = "1.0.0", reason = "text")]
+pub struct DeprecatedUnitStruct;
+#[unstable(feature = "unstable_test_feature", issue = "0")]
+#[rustc_deprecated(since = "1.0.0", reason = "text")]
+pub struct DeprecatedUnstableUnitStruct;
+#[unstable(feature = "unstable_test_feature", issue = "0")]
+pub struct UnstableUnitStruct;
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct StableUnitStruct;
+
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+pub enum Enum {
+    #[stable(feature = "stable_test_feature", since = "1.0.0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    DeprecatedVariant,
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    DeprecatedUnstableVariant,
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    UnstableVariant,
+
+    #[stable(feature = "rust1", since = "1.0.0")]
+    StableVariant,
+}
+
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+#[rustc_deprecated(since = "1.0.0", reason = "text")]
+pub struct DeprecatedTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub isize);
+#[unstable(feature = "unstable_test_feature", issue = "0")]
+#[rustc_deprecated(since = "1.0.0", reason = "text")]
+pub struct DeprecatedUnstableTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub isize);
+#[unstable(feature = "unstable_test_feature", issue = "0")]
+pub struct UnstableTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub isize);
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct StableTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub isize);
+
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+#[macro_export]
+macro_rules! macro_test {
+    () => (deprecated());
+}
+
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+#[macro_export]
+macro_rules! macro_test_arg {
+    ($func:expr) => ($func);
+}
+
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+#[macro_export]
+macro_rules! macro_test_arg_nested {
+    ($func:ident) => (macro_test_arg!($func()));
+}
diff --git a/src/test/ui/lint/auxiliary/lint_stability_fields.rs b/src/test/ui/lint/auxiliary/lint_stability_fields.rs
new file mode 100644
index 0000000..2787da7
--- /dev/null
+++ b/src/test/ui/lint/auxiliary/lint_stability_fields.rs
@@ -0,0 +1,51 @@
+#![feature(staged_api)]
+#![stable(feature = "rust1", since = "1.0.0")]
+
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct Stable {
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub inherit: u8, // it's a lie (stable doesn't inherit)
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    pub override1: u8,
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    pub override2: u8,
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct Stable2(#[stable(feature = "rust1", since = "1.0.0")] pub u8,
+                   #[unstable(feature = "unstable_test_feature", issue = "0")] pub u8,
+                   #[unstable(feature = "unstable_test_feature", issue = "0")]
+                   #[rustc_deprecated(since = "1.0.0", reason = "text")] pub u8);
+
+#[unstable(feature = "unstable_test_feature", issue = "0")]
+pub struct Unstable {
+    pub inherit: u8,
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub override1: u8,
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    pub override2: u8,
+}
+
+#[unstable(feature = "unstable_test_feature", issue = "0")]
+pub struct Unstable2(pub u8,
+                     #[stable(feature = "rust1", since = "1.0.0")] pub u8,
+                     #[unstable(feature = "unstable_test_feature", issue = "0")]
+                     #[rustc_deprecated(since = "1.0.0", reason = "text")] pub u8);
+
+#[unstable(feature = "unstable_test_feature", issue = "0")]
+#[rustc_deprecated(since = "1.0.0", reason = "text")]
+pub struct Deprecated {
+    pub inherit: u8,
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub override1: u8,
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    pub override2: u8,
+}
+
+#[unstable(feature = "unstable_test_feature", issue = "0")]
+#[rustc_deprecated(since = "1.0.0", reason = "text")]
+pub struct Deprecated2(pub u8,
+                       #[stable(feature = "rust1", since = "1.0.0")] pub u8,
+                       #[unstable(feature = "unstable_test_feature", issue = "0")] pub u8);
diff --git a/src/test/ui/lint/auxiliary/lint_unused_extern_crate.rs b/src/test/ui/lint/auxiliary/lint_unused_extern_crate.rs
new file mode 100644
index 0000000..b76b432
--- /dev/null
+++ b/src/test/ui/lint/auxiliary/lint_unused_extern_crate.rs
@@ -0,0 +1 @@
+pub fn foo() {}
diff --git a/src/test/ui/lint/auxiliary/lint_unused_extern_crate2.rs b/src/test/ui/lint/auxiliary/lint_unused_extern_crate2.rs
new file mode 100644
index 0000000..b76b432
--- /dev/null
+++ b/src/test/ui/lint/auxiliary/lint_unused_extern_crate2.rs
@@ -0,0 +1 @@
+pub fn foo() {}
diff --git a/src/test/ui/lint/auxiliary/lint_unused_extern_crate3.rs b/src/test/ui/lint/auxiliary/lint_unused_extern_crate3.rs
new file mode 100644
index 0000000..b76b432
--- /dev/null
+++ b/src/test/ui/lint/auxiliary/lint_unused_extern_crate3.rs
@@ -0,0 +1 @@
+pub fn foo() {}
diff --git a/src/test/ui/lint/auxiliary/lint_unused_extern_crate4.rs b/src/test/ui/lint/auxiliary/lint_unused_extern_crate4.rs
new file mode 100644
index 0000000..d11c69f
--- /dev/null
+++ b/src/test/ui/lint/auxiliary/lint_unused_extern_crate4.rs
@@ -0,0 +1 @@
+// intentionally empty
diff --git a/src/test/ui/lint/auxiliary/lint_unused_extern_crate5.rs b/src/test/ui/lint/auxiliary/lint_unused_extern_crate5.rs
new file mode 100644
index 0000000..d11c69f
--- /dev/null
+++ b/src/test/ui/lint/auxiliary/lint_unused_extern_crate5.rs
@@ -0,0 +1 @@
+// intentionally empty
diff --git a/src/test/ui/lint/auxiliary/lints-in-foreign-macros.rs b/src/test/ui/lint/auxiliary/lints-in-foreign-macros.rs
new file mode 100644
index 0000000..b969d9d
--- /dev/null
+++ b/src/test/ui/lint/auxiliary/lints-in-foreign-macros.rs
@@ -0,0 +1,14 @@
+#[macro_export]
+macro_rules! bar {
+    () => {use std::string::ToString;}
+}
+
+#[macro_export]
+macro_rules! baz {
+    ($i:item) => ($i)
+}
+
+#[macro_export]
+macro_rules! baz2 {
+    ($($i:tt)*) => ($($i)*)
+}
diff --git a/src/test/ui/lint/auxiliary/stability-cfg2.rs b/src/test/ui/lint/auxiliary/stability-cfg2.rs
new file mode 100644
index 0000000..8a28995
--- /dev/null
+++ b/src/test/ui/lint/auxiliary/stability-cfg2.rs
@@ -0,0 +1,5 @@
+// compile-flags:--cfg foo
+
+#![cfg_attr(foo, unstable(feature = "unstable_test_feature", issue = "0"))]
+#![cfg_attr(not(foo), stable(feature = "test_feature", since = "1.0.0"))]
+#![feature(staged_api)]
diff --git a/src/test/ui/lint/auxiliary/stability_cfg1.rs b/src/test/ui/lint/auxiliary/stability_cfg1.rs
new file mode 100644
index 0000000..2e027cc
--- /dev/null
+++ b/src/test/ui/lint/auxiliary/stability_cfg1.rs
@@ -0,0 +1,3 @@
+#![cfg_attr(foo, experimental)]
+#![cfg_attr(not(foo), stable(feature = "test_feature", since = "1.0.0"))]
+#![feature(staged_api)]
diff --git a/src/test/ui/lint/auxiliary/stability_cfg2.rs b/src/test/ui/lint/auxiliary/stability_cfg2.rs
new file mode 100644
index 0000000..8a28995
--- /dev/null
+++ b/src/test/ui/lint/auxiliary/stability_cfg2.rs
@@ -0,0 +1,5 @@
+// compile-flags:--cfg foo
+
+#![cfg_attr(foo, unstable(feature = "unstable_test_feature", issue = "0"))]
+#![cfg_attr(not(foo), stable(feature = "test_feature", since = "1.0.0"))]
+#![feature(staged_api)]
diff --git a/src/test/ui/lint/command-line-lint-group-allow.rs b/src/test/ui/lint/command-line-lint-group-allow.rs
new file mode 100644
index 0000000..ac98724
--- /dev/null
+++ b/src/test/ui/lint/command-line-lint-group-allow.rs
@@ -0,0 +1,6 @@
+// compile-flags: -A bad-style
+// compile-pass
+
+fn main() {
+    let _InappropriateCamelCasing = true;
+}
diff --git a/src/test/ui/lint/command-line-lint-group-deny.rs b/src/test/ui/lint/command-line-lint-group-deny.rs
new file mode 100644
index 0000000..da999f3
--- /dev/null
+++ b/src/test/ui/lint/command-line-lint-group-deny.rs
@@ -0,0 +1,5 @@
+// compile-flags: -D bad-style
+
+fn main() {
+    let _InappropriateCamelCasing = true; //~ ERROR should have a snake
+}
diff --git a/src/test/ui/lint/command-line-lint-group-deny.stderr b/src/test/ui/lint/command-line-lint-group-deny.stderr
new file mode 100644
index 0000000..04c3f6f
--- /dev/null
+++ b/src/test/ui/lint/command-line-lint-group-deny.stderr
@@ -0,0 +1,10 @@
+error: variable `_InappropriateCamelCasing` should have a snake case name
+  --> $DIR/command-line-lint-group-deny.rs:4:9
+   |
+LL |     let _InappropriateCamelCasing = true;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert the identifier to snake case: `_inappropriate_camel_casing`
+   |
+   = note: `-D non-snake-case` implied by `-D bad-style`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lint/command-line-lint-group-forbid.rs b/src/test/ui/lint/command-line-lint-group-forbid.rs
new file mode 100644
index 0000000..4e5c2ac
--- /dev/null
+++ b/src/test/ui/lint/command-line-lint-group-forbid.rs
@@ -0,0 +1,5 @@
+// compile-flags: -F bad-style
+
+fn main() {
+    let _InappropriateCamelCasing = true; //~ ERROR should have a snake
+}
diff --git a/src/test/ui/lint/command-line-lint-group-forbid.stderr b/src/test/ui/lint/command-line-lint-group-forbid.stderr
new file mode 100644
index 0000000..7367821
--- /dev/null
+++ b/src/test/ui/lint/command-line-lint-group-forbid.stderr
@@ -0,0 +1,10 @@
+error: variable `_InappropriateCamelCasing` should have a snake case name
+  --> $DIR/command-line-lint-group-forbid.rs:4:9
+   |
+LL |     let _InappropriateCamelCasing = true;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert the identifier to snake case: `_inappropriate_camel_casing`
+   |
+   = note: `-F non-snake-case` implied by `-F bad-style`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lint/command-line-lint-group-warn.rs b/src/test/ui/lint/command-line-lint-group-warn.rs
new file mode 100644
index 0000000..73dd656
--- /dev/null
+++ b/src/test/ui/lint/command-line-lint-group-warn.rs
@@ -0,0 +1,6 @@
+// compile-flags: -W bad-style
+// compile-pass
+
+fn main() {
+    let _InappropriateCamelCasing = true;
+}
diff --git a/src/test/ui/lint/command-line-lint-group-warn.stderr b/src/test/ui/lint/command-line-lint-group-warn.stderr
new file mode 100644
index 0000000..42a198f
--- /dev/null
+++ b/src/test/ui/lint/command-line-lint-group-warn.stderr
@@ -0,0 +1,8 @@
+warning: variable `_InappropriateCamelCasing` should have a snake case name
+  --> $DIR/command-line-lint-group-warn.rs:5:9
+   |
+LL |     let _InappropriateCamelCasing = true;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert the identifier to snake case: `_inappropriate_camel_casing`
+   |
+   = note: `-W non-snake-case` implied by `-W bad-style`
+
diff --git a/src/test/ui/lint/deny-overflowing-literals.rs b/src/test/ui/lint/deny-overflowing-literals.rs
new file mode 100644
index 0000000..ebd6654
--- /dev/null
+++ b/src/test/ui/lint/deny-overflowing-literals.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let x: u8 = 256;
+    //~^ error: literal out of range for u8
+}
diff --git a/src/test/ui/lint/deny-overflowing-literals.stderr b/src/test/ui/lint/deny-overflowing-literals.stderr
new file mode 100644
index 0000000..7313dd0
--- /dev/null
+++ b/src/test/ui/lint/deny-overflowing-literals.stderr
@@ -0,0 +1,10 @@
+error: literal out of range for u8
+  --> $DIR/deny-overflowing-literals.rs:2:17
+   |
+LL |     let x: u8 = 256;
+   |                 ^^^
+   |
+   = note: #[deny(overflowing_literals)] on by default
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lint/empty-lint-attributes.rs b/src/test/ui/lint/empty-lint-attributes.rs
new file mode 100644
index 0000000..1f0a953
--- /dev/null
+++ b/src/test/ui/lint/empty-lint-attributes.rs
@@ -0,0 +1,17 @@
+#![feature(lint_reasons)]
+
+// run-pass
+
+// Empty (and reason-only) lint attributes are legal—although we may want to
+// lint them in the future (Issue #55112).
+
+#![allow()]
+#![warn(reason = "observationalism")]
+
+#[forbid()]
+fn devoir() {}
+
+#[deny(reason = "ultion")]
+fn waldgrave() {}
+
+fn main() {}
diff --git a/src/test/ui/lint/inclusive-range-pattern-syntax.fixed b/src/test/ui/lint/inclusive-range-pattern-syntax.fixed
new file mode 100644
index 0000000..d52c651
--- /dev/null
+++ b/src/test/ui/lint/inclusive-range-pattern-syntax.fixed
@@ -0,0 +1,19 @@
+// compile-pass
+// run-rustfix
+
+#![warn(ellipsis_inclusive_range_patterns)]
+
+fn main() {
+    let despondency = 2;
+    match despondency {
+        1..=2 => {}
+        //~^ WARN `...` range patterns are deprecated
+        _ => {}
+    }
+
+    match &despondency {
+        &(1..=2) => {}
+        //~^ WARN `...` range patterns are deprecated
+        _ => {}
+    }
+}
diff --git a/src/test/ui/lint/inclusive-range-pattern-syntax.rs b/src/test/ui/lint/inclusive-range-pattern-syntax.rs
new file mode 100644
index 0000000..5174a8b
--- /dev/null
+++ b/src/test/ui/lint/inclusive-range-pattern-syntax.rs
@@ -0,0 +1,19 @@
+// compile-pass
+// run-rustfix
+
+#![warn(ellipsis_inclusive_range_patterns)]
+
+fn main() {
+    let despondency = 2;
+    match despondency {
+        1...2 => {}
+        //~^ WARN `...` range patterns are deprecated
+        _ => {}
+    }
+
+    match &despondency {
+        &1...2 => {}
+        //~^ WARN `...` range patterns are deprecated
+        _ => {}
+    }
+}
diff --git a/src/test/ui/lint/inclusive-range-pattern-syntax.stderr b/src/test/ui/lint/inclusive-range-pattern-syntax.stderr
new file mode 100644
index 0000000..7ad92a4
--- /dev/null
+++ b/src/test/ui/lint/inclusive-range-pattern-syntax.stderr
@@ -0,0 +1,18 @@
+warning: `...` range patterns are deprecated
+  --> $DIR/inclusive-range-pattern-syntax.rs:9:10
+   |
+LL |         1...2 => {}
+   |          ^^^ help: use `..=` for an inclusive range
+   |
+note: lint level defined here
+  --> $DIR/inclusive-range-pattern-syntax.rs:4:9
+   |
+LL | #![warn(ellipsis_inclusive_range_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: `...` range patterns are deprecated
+  --> $DIR/inclusive-range-pattern-syntax.rs:15:9
+   |
+LL |         &1...2 => {}
+   |         ^^^^^^ help: use `..=` for an inclusive range: `&(1..=2)`
+
diff --git a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs
new file mode 100644
index 0000000..7d3fd44
--- /dev/null
+++ b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs
@@ -0,0 +1,80 @@
+// compile-pass
+
+#![feature(box_syntax)]
+#![feature(box_patterns)]
+#![warn(unused)] // UI tests pass `-A unused` (#43896)
+
+struct SoulHistory {
+    corridors_of_light: usize,
+    hours_are_suns: bool,
+    endless_and_singing: bool
+}
+
+struct LovelyAmbition {
+    lips: usize,
+    fire: usize
+}
+
+#[derive(Clone, Copy)]
+enum Large {
+    Suit { case: () }
+}
+
+struct Tuple(Large, ());
+
+fn main() {
+    let i_think_continually = 2;
+    let who_from_the_womb_remembered = SoulHistory {
+        corridors_of_light: 5,
+        hours_are_suns: true,
+        endless_and_singing: true
+    };
+
+    let mut mut_unused_var = 1;
+
+    let (mut var, unused_var) = (1, 2);
+
+    if let SoulHistory { corridors_of_light,
+                         mut hours_are_suns,
+                         endless_and_singing: true } = who_from_the_womb_remembered {
+        hours_are_suns = false;
+    }
+
+    let the_spirit = LovelyAmbition { lips: 1, fire: 2 };
+    let LovelyAmbition { lips, fire } = the_spirit;
+    println!("{}", lips);
+
+    let bag = Large::Suit {
+        case: ()
+    };
+
+    // Plain struct
+    match bag {
+        Large::Suit { case } => {}
+    };
+
+    // Referenced struct
+    match &bag {
+        &Large::Suit { case } => {}
+    };
+
+    // Boxed struct
+    match box bag {
+        box Large::Suit { case } => {}
+    };
+
+    // Tuple with struct
+    match (bag,) {
+        (Large::Suit { case },) => {}
+    };
+
+    // Slice with struct
+    match [bag] {
+        [Large::Suit { case }] => {}
+    };
+
+    // Tuple struct with struct
+    match Tuple(bag, ()) {
+        Tuple(Large::Suit { case }, ()) => {}
+    };
+}
diff --git a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr
new file mode 100644
index 0000000..8fd98e0
--- /dev/null
+++ b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr
@@ -0,0 +1,124 @@
+warning: unused variable: `i_think_continually`
+  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:26:9
+   |
+LL |     let i_think_continually = 2;
+   |         ^^^^^^^^^^^^^^^^^^^ help: consider prefixing with an underscore: `_i_think_continually`
+   |
+note: lint level defined here
+  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:5:9
+   |
+LL | #![warn(unused)] // UI tests pass `-A unused` (#43896)
+   |         ^^^^^^
+   = note: #[warn(unused_variables)] implied by #[warn(unused)]
+
+warning: unused variable: `mut_unused_var`
+  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:33:13
+   |
+LL |     let mut mut_unused_var = 1;
+   |             ^^^^^^^^^^^^^^ help: consider prefixing with an underscore: `_mut_unused_var`
+
+warning: unused variable: `var`
+  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:35:14
+   |
+LL |     let (mut var, unused_var) = (1, 2);
+   |              ^^^ help: consider prefixing with an underscore: `_var`
+
+warning: unused variable: `unused_var`
+  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:35:19
+   |
+LL |     let (mut var, unused_var) = (1, 2);
+   |                   ^^^^^^^^^^ help: consider prefixing with an underscore: `_unused_var`
+
+warning: unused variable: `corridors_of_light`
+  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:37:26
+   |
+LL |     if let SoulHistory { corridors_of_light,
+   |                          ^^^^^^^^^^^^^^^^^^ help: try ignoring the field: `corridors_of_light: _`
+
+warning: variable `hours_are_suns` is assigned to, but never used
+  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:38:30
+   |
+LL |                          mut hours_are_suns,
+   |                              ^^^^^^^^^^^^^^
+   |
+   = note: consider using `_hours_are_suns` instead
+
+warning: value assigned to `hours_are_suns` is never read
+  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:40:9
+   |
+LL |         hours_are_suns = false;
+   |         ^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:5:9
+   |
+LL | #![warn(unused)] // UI tests pass `-A unused` (#43896)
+   |         ^^^^^^
+   = note: #[warn(unused_assignments)] implied by #[warn(unused)]
+   = help: maybe it is overwritten before being read?
+
+warning: unused variable: `fire`
+  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:44:32
+   |
+LL |     let LovelyAmbition { lips, fire } = the_spirit;
+   |                                ^^^^ help: try ignoring the field: `fire: _`
+
+warning: unused variable: `case`
+  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:53:23
+   |
+LL |         Large::Suit { case } => {}
+   |                       ^^^^ help: try ignoring the field: `case: _`
+
+warning: unused variable: `case`
+  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:58:24
+   |
+LL |         &Large::Suit { case } => {}
+   |                        ^^^^ help: try ignoring the field: `case: _`
+
+warning: unused variable: `case`
+  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:63:27
+   |
+LL |         box Large::Suit { case } => {}
+   |                           ^^^^ help: try ignoring the field: `case: _`
+
+warning: unused variable: `case`
+  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:68:24
+   |
+LL |         (Large::Suit { case },) => {}
+   |                        ^^^^ help: try ignoring the field: `case: _`
+
+warning: unused variable: `case`
+  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:73:24
+   |
+LL |         [Large::Suit { case }] => {}
+   |                        ^^^^ help: try ignoring the field: `case: _`
+
+warning: unused variable: `case`
+  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:78:29
+   |
+LL |         Tuple(Large::Suit { case }, ()) => {}
+   |                             ^^^^ help: try ignoring the field: `case: _`
+
+warning: variable does not need to be mutable
+  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:33:9
+   |
+LL |     let mut mut_unused_var = 1;
+   |         ----^^^^^^^^^^^^^^
+   |         |
+   |         help: remove this `mut`
+   |
+note: lint level defined here
+  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:5:9
+   |
+LL | #![warn(unused)] // UI tests pass `-A unused` (#43896)
+   |         ^^^^^^
+   = note: #[warn(unused_mut)] implied by #[warn(unused)]
+
+warning: variable does not need to be mutable
+  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:35:10
+   |
+LL |     let (mut var, unused_var) = (1, 2);
+   |          ----^^^
+   |          |
+   |          help: remove this `mut`
+
diff --git a/src/test/ui/lint/issue-47775-nested-macro-unnecessary-parens-arg.rs b/src/test/ui/lint/issue-47775-nested-macro-unnecessary-parens-arg.rs
new file mode 100644
index 0000000..8872c00
--- /dev/null
+++ b/src/test/ui/lint/issue-47775-nested-macro-unnecessary-parens-arg.rs
@@ -0,0 +1,30 @@
+// compile-pass
+
+#![warn(unused_parens)]
+
+macro_rules! the_worship_the_heart_lifts_above {
+    ( @as_expr, $e:expr) => { $e };
+    ( @generate_fn, $name:tt) => {
+        #[allow(dead_code)] fn the_moth_for_the_star<'a>() -> Option<&'a str> {
+            Some(the_worship_the_heart_lifts_above!( @as_expr, $name ))
+        }
+    };
+    ( $name:ident ) => { the_worship_the_heart_lifts_above!( @generate_fn, (stringify!($name))); }
+    // ↑ Notably, this does 𝘯𝘰𝘵 warn: we're declining to lint unused parens in
+    // function/method arguments inside of nested macros because of situations
+    // like those reported in Issue #47775
+}
+
+macro_rules! and_the_heavens_reject_not {
+    () => {
+        // ↓ But let's test that we still lint for unused parens around
+        // function args inside of simple, one-deep macros.
+        #[allow(dead_code)] fn the_night_for_the_morrow() -> Option<isize> { Some((2)) }
+        //~^ WARN unnecessary parentheses around function argument
+    }
+}
+
+the_worship_the_heart_lifts_above!(rah);
+and_the_heavens_reject_not!();
+
+fn main() {}
diff --git a/src/test/ui/lint/issue-47775-nested-macro-unnecessary-parens-arg.stderr b/src/test/ui/lint/issue-47775-nested-macro-unnecessary-parens-arg.stderr
new file mode 100644
index 0000000..57cdcd7
--- /dev/null
+++ b/src/test/ui/lint/issue-47775-nested-macro-unnecessary-parens-arg.stderr
@@ -0,0 +1,15 @@
+warning: unnecessary parentheses around function argument
+  --> $DIR/issue-47775-nested-macro-unnecessary-parens-arg.rs:22:83
+   |
+LL |         #[allow(dead_code)] fn the_night_for_the_morrow() -> Option<isize> { Some((2)) }
+   |                                                                                   ^^^ help: remove these parentheses
+...
+LL | and_the_heavens_reject_not!();
+   | ------------------------------ in this macro invocation
+   |
+note: lint level defined here
+  --> $DIR/issue-47775-nested-macro-unnecessary-parens-arg.rs:3:9
+   |
+LL | #![warn(unused_parens)]
+   |         ^^^^^^^^^^^^^
+
diff --git a/src/test/ui/lint/issue-54099-camel-case-underscore-types.rs b/src/test/ui/lint/issue-54099-camel-case-underscore-types.rs
new file mode 100644
index 0000000..e4be1ed
--- /dev/null
+++ b/src/test/ui/lint/issue-54099-camel-case-underscore-types.rs
@@ -0,0 +1,14 @@
+// compile-pass
+
+#![forbid(non_camel_case_types)]
+#![allow(dead_code)]
+
+// None of the following types should generate a warning
+struct _X {}
+struct __X {}
+struct __ {}
+struct X_ {}
+struct X__ {}
+struct X___ {}
+
+fn main() { }
diff --git a/src/test/ui/lint/issue-54538-unused-parens-lint.rs b/src/test/ui/lint/issue-54538-unused-parens-lint.rs
new file mode 100644
index 0000000..6ca5381
--- /dev/null
+++ b/src/test/ui/lint/issue-54538-unused-parens-lint.rs
@@ -0,0 +1,28 @@
+// compile-pass
+
+#![allow(unreachable_patterns)]
+#![allow(unused_variables)]
+#![warn(unused_parens)]
+
+fn main() {
+    match 1 {
+        (_) => {}         //~ WARNING: unnecessary parentheses around pattern
+        (y) => {}         //~ WARNING: unnecessary parentheses around pattern
+        (ref r) => {}     //~ WARNING: unnecessary parentheses around pattern
+        (e @ 1..=2) => {} //~ WARNING: unnecessary parentheses around outer pattern
+        (1..=2) => {}     // Non ambiguous range pattern should not warn
+        e @ (3..=4) => {} // Non ambiguous range pattern should not warn
+    }
+
+    match &1 {
+        (e @ &(1...2)) => {} //~ WARNING: unnecessary parentheses around outer pattern
+        &(_) => {}           //~ WARNING: unnecessary parentheses around pattern
+        e @ &(1...2) => {}   // Ambiguous range pattern should not warn
+        &(1..=2) => {}       // Ambiguous range pattern should not warn
+    }
+
+    match &1 {
+        e @ &(1...2) | e @ &(3..=4) => {} // Complex ambiguous pattern should not warn
+        &_ => {}
+    }
+}
diff --git a/src/test/ui/lint/issue-54538-unused-parens-lint.stderr b/src/test/ui/lint/issue-54538-unused-parens-lint.stderr
new file mode 100644
index 0000000..3cf321b
--- /dev/null
+++ b/src/test/ui/lint/issue-54538-unused-parens-lint.stderr
@@ -0,0 +1,42 @@
+warning: unnecessary parentheses around pattern
+  --> $DIR/issue-54538-unused-parens-lint.rs:9:9
+   |
+LL |         (_) => {}
+   |         ^^^ help: remove these parentheses
+   |
+note: lint level defined here
+  --> $DIR/issue-54538-unused-parens-lint.rs:5:9
+   |
+LL | #![warn(unused_parens)]
+   |         ^^^^^^^^^^^^^
+
+warning: unnecessary parentheses around pattern
+  --> $DIR/issue-54538-unused-parens-lint.rs:10:9
+   |
+LL |         (y) => {}
+   |         ^^^ help: remove these parentheses
+
+warning: unnecessary parentheses around pattern
+  --> $DIR/issue-54538-unused-parens-lint.rs:11:9
+   |
+LL |         (ref r) => {}
+   |         ^^^^^^^ help: remove these parentheses
+
+warning: unnecessary parentheses around pattern
+  --> $DIR/issue-54538-unused-parens-lint.rs:12:9
+   |
+LL |         (e @ 1..=2) => {}
+   |         ^^^^^^^^^^^ help: remove these parentheses
+
+warning: unnecessary parentheses around pattern
+  --> $DIR/issue-54538-unused-parens-lint.rs:18:9
+   |
+LL |         (e @ &(1...2)) => {}
+   |         ^^^^^^^^^^^^^^ help: remove these parentheses
+
+warning: unnecessary parentheses around pattern
+  --> $DIR/issue-54538-unused-parens-lint.rs:19:10
+   |
+LL |         &(_) => {}
+   |          ^^^ help: remove these parentheses
+
diff --git a/src/test/ui/lint/lint-attr-non-item-node.rs b/src/test/ui/lint/lint-attr-non-item-node.rs
new file mode 100644
index 0000000..3f05e83
--- /dev/null
+++ b/src/test/ui/lint/lint-attr-non-item-node.rs
@@ -0,0 +1,9 @@
+// Checks that lint attributes work on non-item AST nodes
+
+fn main() {
+    #[deny(unreachable_code)]
+    loop {
+        break;
+        "unreachable"; //~ ERROR unreachable statement
+    }
+}
diff --git a/src/test/ui/lint/lint-attr-non-item-node.stderr b/src/test/ui/lint/lint-attr-non-item-node.stderr
new file mode 100644
index 0000000..6eb72c0
--- /dev/null
+++ b/src/test/ui/lint/lint-attr-non-item-node.stderr
@@ -0,0 +1,14 @@
+error: unreachable statement
+  --> $DIR/lint-attr-non-item-node.rs:7:9
+   |
+LL |         "unreachable";
+   |         ^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/lint-attr-non-item-node.rs:4:12
+   |
+LL |     #[deny(unreachable_code)]
+   |            ^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lint/lint-change-warnings.rs b/src/test/ui/lint/lint-change-warnings.rs
new file mode 100644
index 0000000..37af3b7
--- /dev/null
+++ b/src/test/ui/lint/lint-change-warnings.rs
@@ -0,0 +1,21 @@
+#![deny(warnings)]
+#![allow(dead_code)]
+
+fn main() {
+    while true {} //~ ERROR: infinite
+}
+
+#[allow(warnings)]
+fn foo() {
+    while true {}
+}
+
+#[warn(warnings)]
+fn bar() {
+    while true {} //~ WARNING: infinite
+}
+
+#[forbid(warnings)]
+fn baz() {
+    while true {} //~ ERROR: infinite
+}
diff --git a/src/test/ui/lint/lint-change-warnings.stderr b/src/test/ui/lint/lint-change-warnings.stderr
new file mode 100644
index 0000000..c4b8ab5
--- /dev/null
+++ b/src/test/ui/lint/lint-change-warnings.stderr
@@ -0,0 +1,36 @@
+error: denote infinite loops with `loop { ... }`
+  --> $DIR/lint-change-warnings.rs:5:5
+   |
+LL |     while true {}
+   |     ^^^^^^^^^^ help: use `loop`
+   |
+note: lint level defined here
+  --> $DIR/lint-change-warnings.rs:1:9
+   |
+LL | #![deny(warnings)]
+   |         ^^^^^^^^
+   = note: #[deny(while_true)] implied by #[deny(warnings)]
+
+warning: denote infinite loops with `loop { ... }`
+  --> $DIR/lint-change-warnings.rs:15:5
+   |
+LL |     while true {}
+   |     ^^^^^^^^^^ help: use `loop`
+   |
+   = note: #[warn(while_true)] on by default
+
+error: denote infinite loops with `loop { ... }`
+  --> $DIR/lint-change-warnings.rs:20:5
+   |
+LL |     while true {}
+   |     ^^^^^^^^^^ help: use `loop`
+   |
+note: lint level defined here
+  --> $DIR/lint-change-warnings.rs:18:10
+   |
+LL | #[forbid(warnings)]
+   |          ^^^^^^^^
+   = note: #[forbid(while_true)] implied by #[forbid(warnings)]
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/lint/lint-ctypes-enum.rs b/src/test/ui/lint/lint-ctypes-enum.rs
new file mode 100644
index 0000000..f347c27
--- /dev/null
+++ b/src/test/ui/lint/lint-ctypes-enum.rs
@@ -0,0 +1,28 @@
+#![deny(improper_ctypes)]
+#![allow(dead_code)]
+
+enum Z { }
+enum U { A }
+enum B { C, D }
+enum T { E, F, G }
+
+#[repr(C)]
+enum ReprC { A, B, C }
+
+#[repr(u8)]
+enum U8 { A, B, C }
+
+#[repr(isize)]
+enum Isize { A, B, C }
+
+extern {
+   fn zf(x: Z);
+   fn uf(x: U); //~ ERROR enum has no representation hint
+   fn bf(x: B); //~ ERROR enum has no representation hint
+   fn tf(x: T); //~ ERROR enum has no representation hint
+   fn reprc(x: ReprC);
+   fn u8(x: U8);
+   fn isize(x: Isize);
+}
+
+pub fn main() { }
diff --git a/src/test/ui/lint/lint-ctypes-enum.stderr b/src/test/ui/lint/lint-ctypes-enum.stderr
new file mode 100644
index 0000000..92f76cf
--- /dev/null
+++ b/src/test/ui/lint/lint-ctypes-enum.stderr
@@ -0,0 +1,46 @@
+error: `extern` block uses type `U` which is not FFI-safe: enum has no representation hint
+  --> $DIR/lint-ctypes-enum.rs:20:13
+   |
+LL |    fn uf(x: U);
+   |             ^
+   |
+note: lint level defined here
+  --> $DIR/lint-ctypes-enum.rs:1:9
+   |
+LL | #![deny(improper_ctypes)]
+   |         ^^^^^^^^^^^^^^^
+   = help: consider adding a #[repr(...)] attribute to this enum
+note: type defined here
+  --> $DIR/lint-ctypes-enum.rs:5:1
+   |
+LL | enum U { A }
+   | ^^^^^^^^^^^^
+
+error: `extern` block uses type `B` which is not FFI-safe: enum has no representation hint
+  --> $DIR/lint-ctypes-enum.rs:21:13
+   |
+LL |    fn bf(x: B);
+   |             ^
+   |
+   = help: consider adding a #[repr(...)] attribute to this enum
+note: type defined here
+  --> $DIR/lint-ctypes-enum.rs:6:1
+   |
+LL | enum B { C, D }
+   | ^^^^^^^^^^^^^^^
+
+error: `extern` block uses type `T` which is not FFI-safe: enum has no representation hint
+  --> $DIR/lint-ctypes-enum.rs:22:13
+   |
+LL |    fn tf(x: T);
+   |             ^
+   |
+   = help: consider adding a #[repr(...)] attribute to this enum
+note: type defined here
+  --> $DIR/lint-ctypes-enum.rs:7:1
+   |
+LL | enum T { E, F, G }
+   | ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/lint/lint-ctypes.rs b/src/test/ui/lint/lint-ctypes.rs
new file mode 100644
index 0000000..816177a
--- /dev/null
+++ b/src/test/ui/lint/lint-ctypes.rs
@@ -0,0 +1,99 @@
+#![deny(improper_ctypes)]
+#![feature(rustc_private)]
+
+#![allow(private_in_public)]
+
+extern crate libc;
+
+use std::marker::PhantomData;
+
+trait Mirror { type It: ?Sized; }
+impl<T: ?Sized> Mirror for T { type It = Self; }
+#[repr(C)]
+pub struct StructWithProjection(*mut <StructWithProjection as Mirror>::It);
+#[repr(C)]
+pub struct StructWithProjectionAndLifetime<'a>(
+    &'a mut <StructWithProjectionAndLifetime<'a> as Mirror>::It
+);
+pub type I32Pair = (i32, i32);
+#[repr(C)]
+pub struct ZeroSize;
+pub type RustFn = fn();
+pub type RustBadRet = extern fn() -> Box<u32>;
+pub type CVoidRet = ();
+pub struct Foo;
+#[repr(transparent)]
+pub struct TransparentI128(i128);
+#[repr(transparent)]
+pub struct TransparentStr(&'static str);
+#[repr(transparent)]
+pub struct TransparentBadFn(RustBadRet);
+#[repr(transparent)]
+pub struct TransparentInt(u32);
+#[repr(transparent)]
+pub struct TransparentRef<'a>(&'a TransparentInt);
+#[repr(transparent)]
+pub struct TransparentLifetime<'a>(*const u8, PhantomData<&'a ()>);
+#[repr(transparent)]
+pub struct TransparentUnit<U>(f32, PhantomData<U>);
+#[repr(transparent)]
+pub struct TransparentCustomZst(i32, ZeroSize);
+
+#[repr(C)]
+pub struct ZeroSizeWithPhantomData(::std::marker::PhantomData<i32>);
+
+extern {
+    pub fn ptr_type1(size: *const Foo); //~ ERROR: uses type `Foo`
+    pub fn ptr_type2(size: *const Foo); //~ ERROR: uses type `Foo`
+    pub fn slice_type(p: &[u32]); //~ ERROR: uses type `[u32]`
+    pub fn str_type(p: &str); //~ ERROR: uses type `str`
+    pub fn box_type(p: Box<u32>); //~ ERROR uses type `std::boxed::Box<u32>`
+    pub fn char_type(p: char); //~ ERROR uses type `char`
+    pub fn i128_type(p: i128); //~ ERROR uses type `i128`
+    pub fn u128_type(p: u128); //~ ERROR uses type `u128`
+    pub fn trait_type(p: &Clone); //~ ERROR uses type `dyn std::clone::Clone`
+    pub fn tuple_type(p: (i32, i32)); //~ ERROR uses type `(i32, i32)`
+    pub fn tuple_type2(p: I32Pair); //~ ERROR uses type `(i32, i32)`
+    pub fn zero_size(p: ZeroSize); //~ ERROR struct has no fields
+    pub fn zero_size_phantom(p: ZeroSizeWithPhantomData); //~ ERROR composed only of PhantomData
+    pub fn zero_size_phantom_toplevel()
+        -> ::std::marker::PhantomData<bool>; //~ ERROR: composed only of PhantomData
+    pub fn fn_type(p: RustFn); //~ ERROR function pointer has Rust-specific
+    pub fn fn_type2(p: fn()); //~ ERROR function pointer has Rust-specific
+    pub fn fn_contained(p: RustBadRet); //~ ERROR: uses type `std::boxed::Box<u32>`
+    pub fn transparent_i128(p: TransparentI128); //~ ERROR: uses type `i128`
+    pub fn transparent_str(p: TransparentStr); //~ ERROR: uses type `str`
+    pub fn transparent_fn(p: TransparentBadFn); //~ ERROR: uses type `std::boxed::Box<u32>`
+
+    pub fn good3(fptr: Option<extern fn()>);
+    pub fn good4(aptr: &[u8; 4 as usize]);
+    pub fn good5(s: StructWithProjection);
+    pub fn good6(s: StructWithProjectionAndLifetime);
+    pub fn good7(fptr: extern fn() -> ());
+    pub fn good8(fptr: extern fn() -> !);
+    pub fn good9() -> ();
+    pub fn good10() -> CVoidRet;
+    pub fn good11(size: isize);
+    pub fn good12(size: usize);
+    pub fn good13(n: TransparentInt);
+    pub fn good14(p: TransparentRef);
+    pub fn good15(p: TransparentLifetime);
+    pub fn good16(p: TransparentUnit<ZeroSize>);
+    pub fn good17(p: TransparentCustomZst);
+    #[allow(improper_ctypes)]
+    pub fn good18(_: &String);
+}
+
+#[allow(improper_ctypes)]
+extern {
+    pub fn good19(_: &String);
+}
+
+#[cfg(not(target_arch = "wasm32"))]
+extern {
+    pub fn good1(size: *const libc::c_int);
+    pub fn good2(size: *const libc::c_uint);
+}
+
+fn main() {
+}
diff --git a/src/test/ui/lint/lint-ctypes.stderr b/src/test/ui/lint/lint-ctypes.stderr
new file mode 100644
index 0000000..67ba30a
--- /dev/null
+++ b/src/test/ui/lint/lint-ctypes.stderr
@@ -0,0 +1,170 @@
+error: `extern` block uses type `Foo` which is not FFI-safe: this struct has unspecified layout
+  --> $DIR/lint-ctypes.rs:46:28
+   |
+LL |     pub fn ptr_type1(size: *const Foo);
+   |                            ^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/lint-ctypes.rs:1:9
+   |
+LL | #![deny(improper_ctypes)]
+   |         ^^^^^^^^^^^^^^^
+   = help: consider adding a #[repr(C)] or #[repr(transparent)] attribute to this struct
+note: type defined here
+  --> $DIR/lint-ctypes.rs:24:1
+   |
+LL | pub struct Foo;
+   | ^^^^^^^^^^^^^^^
+
+error: `extern` block uses type `Foo` which is not FFI-safe: this struct has unspecified layout
+  --> $DIR/lint-ctypes.rs:47:28
+   |
+LL |     pub fn ptr_type2(size: *const Foo);
+   |                            ^^^^^^^^^^
+   |
+   = help: consider adding a #[repr(C)] or #[repr(transparent)] attribute to this struct
+note: type defined here
+  --> $DIR/lint-ctypes.rs:24:1
+   |
+LL | pub struct Foo;
+   | ^^^^^^^^^^^^^^^
+
+error: `extern` block uses type `[u32]` which is not FFI-safe: slices have no C equivalent
+  --> $DIR/lint-ctypes.rs:48:26
+   |
+LL |     pub fn slice_type(p: &[u32]);
+   |                          ^^^^^^
+   |
+   = help: consider using a raw pointer instead
+
+error: `extern` block uses type `str` which is not FFI-safe: string slices have no C equivalent
+  --> $DIR/lint-ctypes.rs:49:24
+   |
+LL |     pub fn str_type(p: &str);
+   |                        ^^^^
+   |
+   = help: consider using `*const u8` and a length instead
+
+error: `extern` block uses type `std::boxed::Box<u32>` which is not FFI-safe: this struct has unspecified layout
+  --> $DIR/lint-ctypes.rs:50:24
+   |
+LL |     pub fn box_type(p: Box<u32>);
+   |                        ^^^^^^^^
+   |
+   = help: consider adding a #[repr(C)] or #[repr(transparent)] attribute to this struct
+
+error: `extern` block uses type `char` which is not FFI-safe: the `char` type has no C equivalent
+  --> $DIR/lint-ctypes.rs:51:25
+   |
+LL |     pub fn char_type(p: char);
+   |                         ^^^^
+   |
+   = help: consider using `u32` or `libc::wchar_t` instead
+
+error: `extern` block uses type `i128` which is not FFI-safe: 128-bit integers don't currently have a known stable ABI
+  --> $DIR/lint-ctypes.rs:52:25
+   |
+LL |     pub fn i128_type(p: i128);
+   |                         ^^^^
+
+error: `extern` block uses type `u128` which is not FFI-safe: 128-bit integers don't currently have a known stable ABI
+  --> $DIR/lint-ctypes.rs:53:25
+   |
+LL |     pub fn u128_type(p: u128);
+   |                         ^^^^
+
+error: `extern` block uses type `dyn std::clone::Clone` which is not FFI-safe: trait objects have no C equivalent
+  --> $DIR/lint-ctypes.rs:54:26
+   |
+LL |     pub fn trait_type(p: &Clone);
+   |                          ^^^^^^
+
+error: `extern` block uses type `(i32, i32)` which is not FFI-safe: tuples have unspecified layout
+  --> $DIR/lint-ctypes.rs:55:26
+   |
+LL |     pub fn tuple_type(p: (i32, i32));
+   |                          ^^^^^^^^^^
+   |
+   = help: consider using a struct instead
+
+error: `extern` block uses type `(i32, i32)` which is not FFI-safe: tuples have unspecified layout
+  --> $DIR/lint-ctypes.rs:56:27
+   |
+LL |     pub fn tuple_type2(p: I32Pair);
+   |                           ^^^^^^^
+   |
+   = help: consider using a struct instead
+
+error: `extern` block uses type `ZeroSize` which is not FFI-safe: this struct has no fields
+  --> $DIR/lint-ctypes.rs:57:25
+   |
+LL |     pub fn zero_size(p: ZeroSize);
+   |                         ^^^^^^^^
+   |
+   = help: consider adding a member to this struct
+note: type defined here
+  --> $DIR/lint-ctypes.rs:20:1
+   |
+LL | pub struct ZeroSize;
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: `extern` block uses type `ZeroSizeWithPhantomData` which is not FFI-safe: composed only of PhantomData
+  --> $DIR/lint-ctypes.rs:58:33
+   |
+LL |     pub fn zero_size_phantom(p: ZeroSizeWithPhantomData);
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `extern` block uses type `std::marker::PhantomData<bool>` which is not FFI-safe: composed only of PhantomData
+  --> $DIR/lint-ctypes.rs:60:12
+   |
+LL |         -> ::std::marker::PhantomData<bool>;
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `extern` block uses type `fn()` which is not FFI-safe: this function pointer has Rust-specific calling convention
+  --> $DIR/lint-ctypes.rs:61:23
+   |
+LL |     pub fn fn_type(p: RustFn);
+   |                       ^^^^^^
+   |
+   = help: consider using an `extern fn(...) -> ...` function pointer instead
+
+error: `extern` block uses type `fn()` which is not FFI-safe: this function pointer has Rust-specific calling convention
+  --> $DIR/lint-ctypes.rs:62:24
+   |
+LL |     pub fn fn_type2(p: fn());
+   |                        ^^^^
+   |
+   = help: consider using an `extern fn(...) -> ...` function pointer instead
+
+error: `extern` block uses type `std::boxed::Box<u32>` which is not FFI-safe: this struct has unspecified layout
+  --> $DIR/lint-ctypes.rs:63:28
+   |
+LL |     pub fn fn_contained(p: RustBadRet);
+   |                            ^^^^^^^^^^
+   |
+   = help: consider adding a #[repr(C)] or #[repr(transparent)] attribute to this struct
+
+error: `extern` block uses type `i128` which is not FFI-safe: 128-bit integers don't currently have a known stable ABI
+  --> $DIR/lint-ctypes.rs:64:32
+   |
+LL |     pub fn transparent_i128(p: TransparentI128);
+   |                                ^^^^^^^^^^^^^^^
+
+error: `extern` block uses type `str` which is not FFI-safe: string slices have no C equivalent
+  --> $DIR/lint-ctypes.rs:65:31
+   |
+LL |     pub fn transparent_str(p: TransparentStr);
+   |                               ^^^^^^^^^^^^^^
+   |
+   = help: consider using `*const u8` and a length instead
+
+error: `extern` block uses type `std::boxed::Box<u32>` which is not FFI-safe: this struct has unspecified layout
+  --> $DIR/lint-ctypes.rs:66:30
+   |
+LL |     pub fn transparent_fn(p: TransparentBadFn);
+   |                              ^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding a #[repr(C)] or #[repr(transparent)] attribute to this struct
+
+error: aborting due to 20 previous errors
+
diff --git a/src/test/ui/lint/lint-dead-code-1.rs b/src/test/ui/lint/lint-dead-code-1.rs
new file mode 100644
index 0000000..09977f8
--- /dev/null
+++ b/src/test/ui/lint/lint-dead-code-1.rs
@@ -0,0 +1,110 @@
+#![no_std]
+#![allow(unused_variables)]
+#![allow(non_camel_case_types)]
+#![allow(non_upper_case_globals)]
+#![deny(dead_code)]
+
+#![crate_type="lib"]
+
+pub use foo2::Bar2;
+
+mod foo {
+    pub struct Bar; //~ ERROR: struct is never constructed
+}
+
+mod foo2 {
+    pub struct Bar2;
+}
+
+pub static pub_static: isize = 0;
+static priv_static: isize = 0; //~ ERROR: static item is never used
+const used_static: isize = 0;
+pub static used_static2: isize = used_static;
+const USED_STATIC: isize = 0;
+const STATIC_USED_IN_ENUM_DISCRIMINANT: isize = 10;
+
+pub const pub_const: isize = 0;
+const priv_const: isize = 0; //~ ERROR: constant item is never used
+const used_const: isize = 0;
+pub const used_const2: isize = used_const;
+const USED_CONST: isize = 1;
+const CONST_USED_IN_ENUM_DISCRIMINANT: isize = 11;
+
+pub type typ = *const UsedStruct4;
+pub struct PubStruct;
+struct PrivStruct; //~ ERROR: struct is never constructed
+struct UsedStruct1 {
+    #[allow(dead_code)]
+    x: isize
+}
+struct UsedStruct2(isize);
+struct UsedStruct3;
+pub struct UsedStruct4;
+// this struct is never used directly, but its method is, so we don't want
+// to warn it
+struct SemiUsedStruct;
+impl SemiUsedStruct {
+    fn la_la_la() {}
+}
+struct StructUsedAsField;
+pub struct StructUsedInEnum;
+struct StructUsedInGeneric;
+pub struct PubStruct2 {
+    #[allow(dead_code)]
+    struct_used_as_field: *const StructUsedAsField
+}
+
+pub enum pub_enum { foo1, bar1 }
+pub enum pub_enum2 { a(*const StructUsedInEnum) }
+pub enum pub_enum3 {
+    Foo = STATIC_USED_IN_ENUM_DISCRIMINANT,
+    Bar = CONST_USED_IN_ENUM_DISCRIMINANT,
+}
+
+enum priv_enum { foo2, bar2 } //~ ERROR: enum is never used
+enum used_enum {
+    foo3,
+    bar3 //~ ERROR variant is never constructed
+}
+
+fn f<T>() {}
+
+pub fn pub_fn() {
+    used_fn();
+    let used_struct1 = UsedStruct1 { x: 1 };
+    let used_struct2 = UsedStruct2(1);
+    let used_struct3 = UsedStruct3;
+    let e = used_enum::foo3;
+    SemiUsedStruct::la_la_la();
+
+    let i = 1;
+    match i {
+        USED_STATIC => (),
+        USED_CONST => (),
+        _ => ()
+    }
+    f::<StructUsedInGeneric>();
+}
+fn priv_fn() { //~ ERROR: function is never used
+    let unused_struct = PrivStruct;
+}
+fn used_fn() {}
+
+fn foo() { //~ ERROR: function is never used
+    bar();
+    let unused_enum = priv_enum::foo2;
+}
+
+fn bar() { //~ ERROR: function is never used
+    foo();
+}
+
+fn baz() -> impl Copy { //~ ERROR: function is never used
+    "I'm unused, too"
+}
+
+// Code with #[allow(dead_code)] should be marked live (and thus anything it
+// calls is marked live)
+#[allow(dead_code)]
+fn g() { h(); }
+fn h() {}
diff --git a/src/test/ui/lint/lint-dead-code-1.stderr b/src/test/ui/lint/lint-dead-code-1.stderr
new file mode 100644
index 0000000..be96c69
--- /dev/null
+++ b/src/test/ui/lint/lint-dead-code-1.stderr
@@ -0,0 +1,68 @@
+error: struct is never constructed: `Bar`
+  --> $DIR/lint-dead-code-1.rs:12:5
+   |
+LL |     pub struct Bar;
+   |     ^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/lint-dead-code-1.rs:5:9
+   |
+LL | #![deny(dead_code)]
+   |         ^^^^^^^^^
+
+error: static item is never used: `priv_static`
+  --> $DIR/lint-dead-code-1.rs:20:1
+   |
+LL | static priv_static: isize = 0;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: constant item is never used: `priv_const`
+  --> $DIR/lint-dead-code-1.rs:27:1
+   |
+LL | const priv_const: isize = 0;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: struct is never constructed: `PrivStruct`
+  --> $DIR/lint-dead-code-1.rs:35:1
+   |
+LL | struct PrivStruct;
+   | ^^^^^^^^^^^^^^^^^^
+
+error: enum is never used: `priv_enum`
+  --> $DIR/lint-dead-code-1.rs:64:1
+   |
+LL | enum priv_enum { foo2, bar2 }
+   | ^^^^^^^^^^^^^^
+
+error: variant is never constructed: `bar3`
+  --> $DIR/lint-dead-code-1.rs:67:5
+   |
+LL |     bar3
+   |     ^^^^
+
+error: function is never used: `priv_fn`
+  --> $DIR/lint-dead-code-1.rs:88:1
+   |
+LL | fn priv_fn() {
+   | ^^^^^^^^^^^^
+
+error: function is never used: `foo`
+  --> $DIR/lint-dead-code-1.rs:93:1
+   |
+LL | fn foo() {
+   | ^^^^^^^^
+
+error: function is never used: `bar`
+  --> $DIR/lint-dead-code-1.rs:98:1
+   |
+LL | fn bar() {
+   | ^^^^^^^^
+
+error: function is never used: `baz`
+  --> $DIR/lint-dead-code-1.rs:102:1
+   |
+LL | fn baz() -> impl Copy {
+   | ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 10 previous errors
+
diff --git a/src/test/ui/lint/lint-dead-code-2.rs b/src/test/ui/lint/lint-dead-code-2.rs
new file mode 100644
index 0000000..88db4f8
--- /dev/null
+++ b/src/test/ui/lint/lint-dead-code-2.rs
@@ -0,0 +1,41 @@
+#![allow(unused_variables)]
+#![deny(dead_code)]
+#![feature(main, start)]
+
+struct Foo;
+
+trait Bar {
+    fn bar1(&self);
+    fn bar2(&self) {
+        self.bar1();
+    }
+}
+
+impl Bar for Foo {
+    fn bar1(&self) {
+        live_fn();
+    }
+}
+
+fn live_fn() {}
+
+fn dead_fn() {} //~ ERROR: function is never used
+
+#[main]
+fn dead_fn2() {} //~ ERROR: function is never used
+
+fn used_fn() {}
+
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
+    used_fn();
+    let foo = Foo;
+    foo.bar2();
+    0
+}
+
+// this is not main
+fn main() { //~ ERROR: function is never used
+    dead_fn();
+    dead_fn2();
+}
diff --git a/src/test/ui/lint/lint-dead-code-2.stderr b/src/test/ui/lint/lint-dead-code-2.stderr
new file mode 100644
index 0000000..1226f98
--- /dev/null
+++ b/src/test/ui/lint/lint-dead-code-2.stderr
@@ -0,0 +1,26 @@
+error: function is never used: `dead_fn`
+  --> $DIR/lint-dead-code-2.rs:22:1
+   |
+LL | fn dead_fn() {}
+   | ^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/lint-dead-code-2.rs:2:9
+   |
+LL | #![deny(dead_code)]
+   |         ^^^^^^^^^
+
+error: function is never used: `dead_fn2`
+  --> $DIR/lint-dead-code-2.rs:25:1
+   |
+LL | fn dead_fn2() {}
+   | ^^^^^^^^^^^^^
+
+error: function is never used: `main`
+  --> $DIR/lint-dead-code-2.rs:38:1
+   |
+LL | fn main() {
+   | ^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/lint/lint-dead-code-3.rs b/src/test/ui/lint/lint-dead-code-3.rs
new file mode 100644
index 0000000..00b250f
--- /dev/null
+++ b/src/test/ui/lint/lint-dead-code-3.rs
@@ -0,0 +1,78 @@
+#![allow(unused_variables)]
+#![allow(non_camel_case_types)]
+#![deny(dead_code)]
+
+#![crate_type="lib"]
+
+
+pub use extern_foo as x;
+extern {
+    pub fn extern_foo();
+}
+
+struct Foo; //~ ERROR: struct is never constructed
+impl Foo {
+    fn foo(&self) { //~ ERROR: method is never used
+        bar()
+    }
+}
+
+fn bar() { //~ ERROR: function is never used
+    fn baz() {}
+
+    Foo.foo();
+    baz();
+}
+
+// no warning
+struct Foo2;
+impl Foo2 { fn foo2(&self) { bar2() } }
+fn bar2() {
+    fn baz2() {}
+
+    Foo2.foo2();
+    baz2();
+}
+
+pub fn pub_fn() {
+    let foo2_struct = Foo2;
+    foo2_struct.foo2();
+
+    blah::baz();
+}
+
+mod blah {
+    // not warned because it's used in the parameter of `free` and return of
+    // `malloc` below, which are also used.
+    enum c_void {}
+
+    extern {
+        fn free(p: *const c_void);
+        fn malloc(size: usize) -> *const c_void;
+    }
+
+    pub fn baz() {
+        unsafe { free(malloc(4)); }
+    }
+}
+
+enum c_void {} //~ ERROR: enum is never used
+extern {
+    fn free(p: *const c_void); //~ ERROR: foreign function is never used
+}
+
+// Check provided method
+mod inner {
+    pub trait Trait {
+        fn f(&self) { f(); }
+    }
+
+    impl Trait for isize {}
+
+    fn f() {}
+}
+
+pub fn foo() {
+    let a: &inner::Trait = &1_isize;
+    a.f();
+}
diff --git a/src/test/ui/lint/lint-dead-code-3.stderr b/src/test/ui/lint/lint-dead-code-3.stderr
new file mode 100644
index 0000000..2408da0
--- /dev/null
+++ b/src/test/ui/lint/lint-dead-code-3.stderr
@@ -0,0 +1,38 @@
+error: struct is never constructed: `Foo`
+  --> $DIR/lint-dead-code-3.rs:13:1
+   |
+LL | struct Foo;
+   | ^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/lint-dead-code-3.rs:3:9
+   |
+LL | #![deny(dead_code)]
+   |         ^^^^^^^^^
+
+error: method is never used: `foo`
+  --> $DIR/lint-dead-code-3.rs:15:5
+   |
+LL |     fn foo(&self) {
+   |     ^^^^^^^^^^^^^
+
+error: function is never used: `bar`
+  --> $DIR/lint-dead-code-3.rs:20:1
+   |
+LL | fn bar() {
+   | ^^^^^^^^
+
+error: enum is never used: `c_void`
+  --> $DIR/lint-dead-code-3.rs:59:1
+   |
+LL | enum c_void {}
+   | ^^^^^^^^^^^
+
+error: foreign function is never used: `free`
+  --> $DIR/lint-dead-code-3.rs:61:5
+   |
+LL |     fn free(p: *const c_void);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/ui/lint/lint-dead-code-4.rs b/src/test/ui/lint/lint-dead-code-4.rs
new file mode 100644
index 0000000..3f4a9e2
--- /dev/null
+++ b/src/test/ui/lint/lint-dead-code-4.rs
@@ -0,0 +1,83 @@
+#![allow(unused_variables)]
+#![allow(non_camel_case_types)]
+#![deny(dead_code)]
+
+struct Foo {
+    x: usize,
+    b: bool, //~ ERROR: field is never used
+}
+
+fn field_read(f: Foo) -> usize {
+    f.x.pow(2)
+}
+
+enum XYZ {
+    X, //~ ERROR variant is never constructed
+    Y { //~ ERROR variant is never constructed
+        a: String,
+        b: i32,
+        c: i32,
+    },
+    Z
+}
+
+enum ABC { //~ ERROR enum is never used
+    A,
+    B {
+        a: String,
+        b: i32,
+        c: i32,
+    },
+    C
+}
+
+// ensure struct variants get warning for their fields
+enum IJK {
+    I, //~ ERROR variant is never constructed
+    J {
+        a: String,
+        b: i32, //~ ERROR field is never used
+        c: i32, //~ ERROR field is never used
+    },
+    K //~ ERROR variant is never constructed
+
+}
+
+fn struct_variant_partial_use(b: IJK) -> String {
+    match b {
+        IJK::J { a, b: _, .. } => a,
+        _ => "".to_string()
+    }
+}
+
+fn field_match_in_patterns(b: XYZ) -> String {
+    match b {
+        XYZ::Y { a, b: _, .. } => a,
+        _ => "".to_string()
+    }
+}
+
+struct Bar {
+    x: usize, //~ ERROR: field is never used
+    b: bool,
+    c: bool, //~ ERROR: field is never used
+    _guard: ()
+}
+
+#[repr(C)]
+struct Baz {
+    x: u32,
+}
+
+fn field_match_in_let(f: Bar) -> bool {
+    let Bar { b, c: _, .. } = f;
+    b
+}
+
+fn main() {
+    field_read(Foo { x: 1, b: false });
+    field_match_in_patterns(XYZ::Z);
+    struct_variant_partial_use(IJK::J { a: "".into(), b: 1, c: -1 });
+    field_match_in_let(Bar { x: 42, b: true, c: false, _guard: () });
+    let _ = Baz { x: 0 };
+}
diff --git a/src/test/ui/lint/lint-dead-code-4.stderr b/src/test/ui/lint/lint-dead-code-4.stderr
new file mode 100644
index 0000000..b7ceee9
--- /dev/null
+++ b/src/test/ui/lint/lint-dead-code-4.stderr
@@ -0,0 +1,72 @@
+error: field is never used: `b`
+  --> $DIR/lint-dead-code-4.rs:7:5
+   |
+LL |     b: bool,
+   |     ^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/lint-dead-code-4.rs:3:9
+   |
+LL | #![deny(dead_code)]
+   |         ^^^^^^^^^
+
+error: variant is never constructed: `X`
+  --> $DIR/lint-dead-code-4.rs:15:5
+   |
+LL |     X,
+   |     ^
+
+error: variant is never constructed: `Y`
+  --> $DIR/lint-dead-code-4.rs:16:5
+   |
+LL | /     Y {
+LL | |         a: String,
+LL | |         b: i32,
+LL | |         c: i32,
+LL | |     },
+   | |_____^
+
+error: enum is never used: `ABC`
+  --> $DIR/lint-dead-code-4.rs:24:1
+   |
+LL | enum ABC {
+   | ^^^^^^^^
+
+error: variant is never constructed: `I`
+  --> $DIR/lint-dead-code-4.rs:36:5
+   |
+LL |     I,
+   |     ^
+
+error: field is never used: `b`
+  --> $DIR/lint-dead-code-4.rs:39:9
+   |
+LL |         b: i32,
+   |         ^^^^^^
+
+error: field is never used: `c`
+  --> $DIR/lint-dead-code-4.rs:40:9
+   |
+LL |         c: i32,
+   |         ^^^^^^
+
+error: variant is never constructed: `K`
+  --> $DIR/lint-dead-code-4.rs:42:5
+   |
+LL |     K
+   |     ^
+
+error: field is never used: `x`
+  --> $DIR/lint-dead-code-4.rs:61:5
+   |
+LL |     x: usize,
+   |     ^^^^^^^^
+
+error: field is never used: `c`
+  --> $DIR/lint-dead-code-4.rs:63:5
+   |
+LL |     c: bool,
+   |     ^^^^^^^
+
+error: aborting due to 10 previous errors
+
diff --git a/src/test/ui/lint/lint-dead-code-5.rs b/src/test/ui/lint/lint-dead-code-5.rs
new file mode 100644
index 0000000..764a23e
--- /dev/null
+++ b/src/test/ui/lint/lint-dead-code-5.rs
@@ -0,0 +1,30 @@
+#![allow(unused_variables)]
+#![deny(dead_code)]
+
+enum Enum1 {
+    Variant1(isize),
+    Variant2 //~ ERROR: variant is never constructed
+}
+
+enum Enum2 {
+    Variant3(bool),
+    #[allow(dead_code)]
+    Variant4(isize),
+    Variant5 { _x: isize }, //~ ERROR: variant is never constructed: `Variant5`
+    Variant6(isize), //~ ERROR: variant is never constructed: `Variant6`
+    _Variant7,
+}
+
+enum Enum3 { //~ ERROR: enum is never used
+    Variant8,
+    Variant9
+}
+
+fn main() {
+    let v = Enum1::Variant1(1);
+    match v {
+        Enum1::Variant1(_) => (),
+        Enum1::Variant2 => ()
+    }
+    let x = Enum2::Variant3(true);
+}
diff --git a/src/test/ui/lint/lint-dead-code-5.stderr b/src/test/ui/lint/lint-dead-code-5.stderr
new file mode 100644
index 0000000..740cfde
--- /dev/null
+++ b/src/test/ui/lint/lint-dead-code-5.stderr
@@ -0,0 +1,32 @@
+error: variant is never constructed: `Variant2`
+  --> $DIR/lint-dead-code-5.rs:6:5
+   |
+LL |     Variant2
+   |     ^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/lint-dead-code-5.rs:2:9
+   |
+LL | #![deny(dead_code)]
+   |         ^^^^^^^^^
+
+error: variant is never constructed: `Variant5`
+  --> $DIR/lint-dead-code-5.rs:13:5
+   |
+LL |     Variant5 { _x: isize },
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error: variant is never constructed: `Variant6`
+  --> $DIR/lint-dead-code-5.rs:14:5
+   |
+LL |     Variant6(isize),
+   |     ^^^^^^^^^^^^^^^
+
+error: enum is never used: `Enum3`
+  --> $DIR/lint-dead-code-5.rs:18:1
+   |
+LL | enum Enum3 {
+   | ^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/lint/lint-dead-code-impl-trait.rs b/src/test/ui/lint/lint-dead-code-impl-trait.rs
new file mode 100644
index 0000000..a2736d9
--- /dev/null
+++ b/src/test/ui/lint/lint-dead-code-impl-trait.rs
@@ -0,0 +1,18 @@
+#![deny(dead_code)]
+
+trait Trait {
+    type Type;
+}
+
+impl Trait for () {
+    type Type = ();
+}
+
+type Used = ();
+type Unused = (); //~ ERROR type alias is never used
+
+fn foo() -> impl Trait<Type = Used> {}
+
+fn main() {
+    foo();
+}
diff --git a/src/test/ui/lint/lint-dead-code-impl-trait.stderr b/src/test/ui/lint/lint-dead-code-impl-trait.stderr
new file mode 100644
index 0000000..61d0954
--- /dev/null
+++ b/src/test/ui/lint/lint-dead-code-impl-trait.stderr
@@ -0,0 +1,14 @@
+error: type alias is never used: `Unused`
+  --> $DIR/lint-dead-code-impl-trait.rs:12:1
+   |
+LL | type Unused = ();
+   | ^^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/lint-dead-code-impl-trait.rs:1:9
+   |
+LL | #![deny(dead_code)]
+   |         ^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lint/lint-dead-code-type-alias.rs b/src/test/ui/lint/lint-dead-code-type-alias.rs
new file mode 100644
index 0000000..86daf3e
--- /dev/null
+++ b/src/test/ui/lint/lint-dead-code-type-alias.rs
@@ -0,0 +1,10 @@
+#![deny(dead_code)]
+
+type Used = u8;
+type Unused = u8; //~ ERROR type alias is never used
+
+fn id(x: Used) -> Used { x }
+
+fn main() {
+    id(0);
+}
diff --git a/src/test/ui/lint/lint-dead-code-type-alias.stderr b/src/test/ui/lint/lint-dead-code-type-alias.stderr
new file mode 100644
index 0000000..4198ddf
--- /dev/null
+++ b/src/test/ui/lint/lint-dead-code-type-alias.stderr
@@ -0,0 +1,14 @@
+error: type alias is never used: `Unused`
+  --> $DIR/lint-dead-code-type-alias.rs:4:1
+   |
+LL | type Unused = u8;
+   | ^^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/lint-dead-code-type-alias.rs:1:9
+   |
+LL | #![deny(dead_code)]
+   |         ^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lint/lint-dead-code-variant.rs b/src/test/ui/lint/lint-dead-code-variant.rs
new file mode 100644
index 0000000..295ed16
--- /dev/null
+++ b/src/test/ui/lint/lint-dead-code-variant.rs
@@ -0,0 +1,12 @@
+#![deny(dead_code)]
+
+#[derive(Clone)]
+enum Enum {
+    Variant1, //~ ERROR: variant is never constructed
+    Variant2,
+}
+
+fn main() {
+    let e = Enum::Variant2;
+    e.clone();
+}
diff --git a/src/test/ui/lint/lint-dead-code-variant.stderr b/src/test/ui/lint/lint-dead-code-variant.stderr
new file mode 100644
index 0000000..a79432d
--- /dev/null
+++ b/src/test/ui/lint/lint-dead-code-variant.stderr
@@ -0,0 +1,14 @@
+error: variant is never constructed: `Variant1`
+  --> $DIR/lint-dead-code-variant.rs:5:5
+   |
+LL |     Variant1,
+   |     ^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/lint-dead-code-variant.rs:1:9
+   |
+LL | #![deny(dead_code)]
+   |         ^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lint/lint-directives-on-use-items-issue-10534.rs b/src/test/ui/lint/lint-directives-on-use-items-issue-10534.rs
new file mode 100644
index 0000000..e5cb0d3
--- /dev/null
+++ b/src/test/ui/lint/lint-directives-on-use-items-issue-10534.rs
@@ -0,0 +1,24 @@
+#![deny(unused_imports)]
+#![allow(non_upper_case_globals)]
+
+// The aim of this test is to ensure that deny/allow/warn directives
+// are applied to individual "use" statements instead of silently
+// ignored.
+
+#[allow(dead_code)]
+mod a { pub static x: isize = 3; pub static y: isize = 4; }
+
+mod b {
+    use a::x; //~ ERROR: unused import
+    #[allow(unused_imports)]
+    use a::y; // no error here
+}
+
+#[allow(unused_imports)]
+mod c {
+    use a::x;
+    #[deny(unused_imports)]
+    use a::y; //~ ERROR: unused import
+}
+
+fn main() {}
diff --git a/src/test/ui/lint/lint-directives-on-use-items-issue-10534.stderr b/src/test/ui/lint/lint-directives-on-use-items-issue-10534.stderr
new file mode 100644
index 0000000..020591c
--- /dev/null
+++ b/src/test/ui/lint/lint-directives-on-use-items-issue-10534.stderr
@@ -0,0 +1,26 @@
+error: unused import: `a::x`
+  --> $DIR/lint-directives-on-use-items-issue-10534.rs:12:9
+   |
+LL |     use a::x;
+   |         ^^^^
+   |
+note: lint level defined here
+  --> $DIR/lint-directives-on-use-items-issue-10534.rs:1:9
+   |
+LL | #![deny(unused_imports)]
+   |         ^^^^^^^^^^^^^^
+
+error: unused import: `a::y`
+  --> $DIR/lint-directives-on-use-items-issue-10534.rs:21:9
+   |
+LL |     use a::y;
+   |         ^^^^
+   |
+note: lint level defined here
+  --> $DIR/lint-directives-on-use-items-issue-10534.rs:20:12
+   |
+LL |     #[deny(unused_imports)]
+   |            ^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/lint/lint-exceeding-bitshifts.rs b/src/test/ui/lint/lint-exceeding-bitshifts.rs
new file mode 100644
index 0000000..0f397a7
--- /dev/null
+++ b/src/test/ui/lint/lint-exceeding-bitshifts.rs
@@ -0,0 +1,47 @@
+#![deny(exceeding_bitshifts, const_err)]
+#![allow(unused_variables)]
+#![allow(dead_code)]
+
+fn main() {
+      let n = 1u8 << 7;
+      let n = 1u8 << 8;   //~ ERROR: attempt to shift left with overflow
+      let n = 1u16 << 15;
+      let n = 1u16 << 16; //~ ERROR: attempt to shift left with overflow
+      let n = 1u32 << 31;
+      let n = 1u32 << 32; //~ ERROR: attempt to shift left with overflow
+      let n = 1u64 << 63;
+      let n = 1u64 << 64; //~ ERROR: attempt to shift left with overflow
+      let n = 1i8 << 7;
+      let n = 1i8 << 8;   //~ ERROR: attempt to shift left with overflow
+      let n = 1i16 << 15;
+      let n = 1i16 << 16; //~ ERROR: attempt to shift left with overflow
+      let n = 1i32 << 31;
+      let n = 1i32 << 32; //~ ERROR: attempt to shift left with overflow
+      let n = 1i64 << 63;
+      let n = 1i64 << 64; //~ ERROR: attempt to shift left with overflow
+
+      let n = 1u8 >> 7;
+      let n = 1u8 >> 8;   //~ ERROR: attempt to shift right with overflow
+      let n = 1u16 >> 15;
+      let n = 1u16 >> 16; //~ ERROR: attempt to shift right with overflow
+      let n = 1u32 >> 31;
+      let n = 1u32 >> 32; //~ ERROR: attempt to shift right with overflow
+      let n = 1u64 >> 63;
+      let n = 1u64 >> 64; //~ ERROR: attempt to shift right with overflow
+      let n = 1i8 >> 7;
+      let n = 1i8 >> 8;   //~ ERROR: attempt to shift right with overflow
+      let n = 1i16 >> 15;
+      let n = 1i16 >> 16; //~ ERROR: attempt to shift right with overflow
+      let n = 1i32 >> 31;
+      let n = 1i32 >> 32; //~ ERROR: attempt to shift right with overflow
+      let n = 1i64 >> 63;
+      let n = 1i64 >> 64; //~ ERROR: attempt to shift right with overflow
+
+      let n = 1u8;
+      let n = n << 7;
+      let n = n << 8; //~ ERROR: attempt to shift left with overflow
+
+      let n = 1u8 << -8; //~ ERROR: attempt to shift left with overflow
+
+      let n = 1i8<<(1isize+-1);
+}
diff --git a/src/test/ui/lint/lint-exceeding-bitshifts.stderr b/src/test/ui/lint/lint-exceeding-bitshifts.stderr
new file mode 100644
index 0000000..f9f168c
--- /dev/null
+++ b/src/test/ui/lint/lint-exceeding-bitshifts.stderr
@@ -0,0 +1,116 @@
+error: attempt to shift left with overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:7:15
+   |
+LL |       let n = 1u8 << 8;
+   |               ^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/lint-exceeding-bitshifts.rs:1:9
+   |
+LL | #![deny(exceeding_bitshifts, const_err)]
+   |         ^^^^^^^^^^^^^^^^^^^
+
+error: attempt to shift left with overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:9:15
+   |
+LL |       let n = 1u16 << 16;
+   |               ^^^^^^^^^^
+
+error: attempt to shift left with overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:11:15
+   |
+LL |       let n = 1u32 << 32;
+   |               ^^^^^^^^^^
+
+error: attempt to shift left with overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:13:15
+   |
+LL |       let n = 1u64 << 64;
+   |               ^^^^^^^^^^
+
+error: attempt to shift left with overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:15:15
+   |
+LL |       let n = 1i8 << 8;
+   |               ^^^^^^^^
+
+error: attempt to shift left with overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:17:15
+   |
+LL |       let n = 1i16 << 16;
+   |               ^^^^^^^^^^
+
+error: attempt to shift left with overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:19:15
+   |
+LL |       let n = 1i32 << 32;
+   |               ^^^^^^^^^^
+
+error: attempt to shift left with overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:21:15
+   |
+LL |       let n = 1i64 << 64;
+   |               ^^^^^^^^^^
+
+error: attempt to shift right with overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:24:15
+   |
+LL |       let n = 1u8 >> 8;
+   |               ^^^^^^^^
+
+error: attempt to shift right with overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:26:15
+   |
+LL |       let n = 1u16 >> 16;
+   |               ^^^^^^^^^^
+
+error: attempt to shift right with overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:28:15
+   |
+LL |       let n = 1u32 >> 32;
+   |               ^^^^^^^^^^
+
+error: attempt to shift right with overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:30:15
+   |
+LL |       let n = 1u64 >> 64;
+   |               ^^^^^^^^^^
+
+error: attempt to shift right with overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:32:15
+   |
+LL |       let n = 1i8 >> 8;
+   |               ^^^^^^^^
+
+error: attempt to shift right with overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:34:15
+   |
+LL |       let n = 1i16 >> 16;
+   |               ^^^^^^^^^^
+
+error: attempt to shift right with overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:36:15
+   |
+LL |       let n = 1i32 >> 32;
+   |               ^^^^^^^^^^
+
+error: attempt to shift right with overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:38:15
+   |
+LL |       let n = 1i64 >> 64;
+   |               ^^^^^^^^^^
+
+error: attempt to shift left with overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:42:15
+   |
+LL |       let n = n << 8;
+   |               ^^^^^^
+
+error: attempt to shift left with overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:44:15
+   |
+LL |       let n = 1u8 << -8;
+   |               ^^^^^^^^^
+
+error: aborting due to 18 previous errors
+
diff --git a/src/test/ui/lint/lint-exceeding-bitshifts2.rs b/src/test/ui/lint/lint-exceeding-bitshifts2.rs
new file mode 100644
index 0000000..bde4865
--- /dev/null
+++ b/src/test/ui/lint/lint-exceeding-bitshifts2.rs
@@ -0,0 +1,17 @@
+#![deny(exceeding_bitshifts, const_err)]
+#![allow(unused_variables)]
+#![allow(dead_code)]
+
+fn main() {
+      let n = 1u8 << (4+3);
+      let n = 1u8 << (4+4); //~ ERROR: attempt to shift left with overflow
+      let n = 1i64 >> [63][0];
+      let n = 1i64 >> [64][0]; // should be linting, needs to wait for const propagation
+
+      #[cfg(target_pointer_width = "32")]
+      const BITS: usize = 32;
+      #[cfg(target_pointer_width = "64")]
+      const BITS: usize = 64;
+      let n = 1_isize << BITS; //~ ERROR: attempt to shift left with overflow
+      let n = 1_usize << BITS; //~ ERROR: attempt to shift left with overflow
+}
diff --git a/src/test/ui/lint/lint-exceeding-bitshifts2.stderr b/src/test/ui/lint/lint-exceeding-bitshifts2.stderr
new file mode 100644
index 0000000..8a6d2a8
--- /dev/null
+++ b/src/test/ui/lint/lint-exceeding-bitshifts2.stderr
@@ -0,0 +1,26 @@
+error: attempt to shift left with overflow
+  --> $DIR/lint-exceeding-bitshifts2.rs:7:15
+   |
+LL |       let n = 1u8 << (4+4);
+   |               ^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/lint-exceeding-bitshifts2.rs:1:9
+   |
+LL | #![deny(exceeding_bitshifts, const_err)]
+   |         ^^^^^^^^^^^^^^^^^^^
+
+error: attempt to shift left with overflow
+  --> $DIR/lint-exceeding-bitshifts2.rs:15:15
+   |
+LL |       let n = 1_isize << BITS;
+   |               ^^^^^^^^^^^^^^^
+
+error: attempt to shift left with overflow
+  --> $DIR/lint-exceeding-bitshifts2.rs:16:15
+   |
+LL |       let n = 1_usize << BITS;
+   |               ^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/lint/lint-forbid-attr.rs b/src/test/ui/lint/lint-forbid-attr.rs
new file mode 100644
index 0000000..082b543
--- /dev/null
+++ b/src/test/ui/lint/lint-forbid-attr.rs
@@ -0,0 +1,6 @@
+#![forbid(deprecated)]
+
+#[allow(deprecated)]
+//~^ ERROR allow(deprecated) overruled by outer forbid(deprecated)
+fn main() {
+}
diff --git a/src/test/ui/lint/lint-forbid-attr.stderr b/src/test/ui/lint/lint-forbid-attr.stderr
new file mode 100644
index 0000000..6e1e2b3
--- /dev/null
+++ b/src/test/ui/lint/lint-forbid-attr.stderr
@@ -0,0 +1,12 @@
+error[E0453]: allow(deprecated) overruled by outer forbid(deprecated)
+  --> $DIR/lint-forbid-attr.rs:3:9
+   |
+LL | #![forbid(deprecated)]
+   |           ---------- `forbid` level set here
+LL | 
+LL | #[allow(deprecated)]
+   |         ^^^^^^^^^^ overruled by previous forbid
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0453`.
diff --git a/src/test/ui/lint/lint-forbid-cmdline.rs b/src/test/ui/lint/lint-forbid-cmdline.rs
new file mode 100644
index 0000000..150685c
--- /dev/null
+++ b/src/test/ui/lint/lint-forbid-cmdline.rs
@@ -0,0 +1,5 @@
+// compile-flags: -F deprecated
+
+#[allow(deprecated)] //~ ERROR allow(deprecated) overruled by outer forbid(deprecated)
+fn main() {
+}
diff --git a/src/test/ui/lint/lint-forbid-cmdline.stderr b/src/test/ui/lint/lint-forbid-cmdline.stderr
new file mode 100644
index 0000000..bece477
--- /dev/null
+++ b/src/test/ui/lint/lint-forbid-cmdline.stderr
@@ -0,0 +1,11 @@
+error[E0453]: allow(deprecated) overruled by outer forbid(deprecated)
+  --> $DIR/lint-forbid-cmdline.rs:3:9
+   |
+LL | #[allow(deprecated)]
+   |         ^^^^^^^^^^ overruled by previous forbid
+   |
+   = note: `forbid` lint level was set on command line
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0453`.
diff --git a/src/test/ui/lint/lint-forbid-internal-unsafe.rs b/src/test/ui/lint/lint-forbid-internal-unsafe.rs
new file mode 100644
index 0000000..b08fbf6
--- /dev/null
+++ b/src/test/ui/lint/lint-forbid-internal-unsafe.rs
@@ -0,0 +1,16 @@
+#![forbid(unsafe_code)]
+#![feature(allow_internal_unsafe)]
+
+#[allow_internal_unsafe]
+//~^ ERROR: `allow_internal_unsafe` allows defining
+macro_rules! evil {
+    ($e:expr) => {
+        unsafe {
+            $e
+        }
+    }
+}
+
+fn main() {
+    println!("{}", evil!(*(0 as *const u8)));
+}
diff --git a/src/test/ui/lint/lint-forbid-internal-unsafe.stderr b/src/test/ui/lint/lint-forbid-internal-unsafe.stderr
new file mode 100644
index 0000000..59dab11
--- /dev/null
+++ b/src/test/ui/lint/lint-forbid-internal-unsafe.stderr
@@ -0,0 +1,14 @@
+error: `allow_internal_unsafe` allows defining macros using unsafe without triggering the `unsafe_code` lint at their call site
+  --> $DIR/lint-forbid-internal-unsafe.rs:4:1
+   |
+LL | #[allow_internal_unsafe]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/lint-forbid-internal-unsafe.rs:1:11
+   |
+LL | #![forbid(unsafe_code)]
+   |           ^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lint/lint-group-nonstandard-style.rs b/src/test/ui/lint/lint-group-nonstandard-style.rs
new file mode 100644
index 0000000..bd7f327
--- /dev/null
+++ b/src/test/ui/lint/lint-group-nonstandard-style.rs
@@ -0,0 +1,26 @@
+#![deny(nonstandard_style)]
+#![allow(dead_code)]
+
+fn CamelCase() {} //~ ERROR should have a snake
+
+#[allow(nonstandard_style)]
+mod test {
+    fn CamelCase() {}
+
+    #[forbid(nonstandard_style)]
+    mod bad {
+        fn CamelCase() {} //~ ERROR should have a snake
+
+        static bad: isize = 1; //~ ERROR should have an upper
+    }
+
+    mod warn {
+        #![warn(nonstandard_style)]
+
+        fn CamelCase() {} //~ WARN should have a snake
+
+        struct snake_case; //~ WARN should have an upper camel
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/lint/lint-group-nonstandard-style.stderr b/src/test/ui/lint/lint-group-nonstandard-style.stderr
new file mode 100644
index 0000000..a365204
--- /dev/null
+++ b/src/test/ui/lint/lint-group-nonstandard-style.stderr
@@ -0,0 +1,67 @@
+warning: type `snake_case` should have an upper camel case name
+  --> $DIR/lint-group-nonstandard-style.rs:22:16
+   |
+LL |         struct snake_case;
+   |                ^^^^^^^^^^ help: convert the identifier to upper camel case: `SnakeCase`
+   |
+note: lint level defined here
+  --> $DIR/lint-group-nonstandard-style.rs:18:17
+   |
+LL |         #![warn(nonstandard_style)]
+   |                 ^^^^^^^^^^^^^^^^^
+   = note: #[warn(non_camel_case_types)] implied by #[warn(nonstandard_style)]
+
+error: function `CamelCase` should have a snake case name
+  --> $DIR/lint-group-nonstandard-style.rs:4:4
+   |
+LL | fn CamelCase() {}
+   |    ^^^^^^^^^ help: convert the identifier to snake case: `camel_case`
+   |
+note: lint level defined here
+  --> $DIR/lint-group-nonstandard-style.rs:1:9
+   |
+LL | #![deny(nonstandard_style)]
+   |         ^^^^^^^^^^^^^^^^^
+   = note: #[deny(non_snake_case)] implied by #[deny(nonstandard_style)]
+
+error: function `CamelCase` should have a snake case name
+  --> $DIR/lint-group-nonstandard-style.rs:12:12
+   |
+LL |         fn CamelCase() {}
+   |            ^^^^^^^^^ help: convert the identifier to snake case: `camel_case`
+   |
+note: lint level defined here
+  --> $DIR/lint-group-nonstandard-style.rs:10:14
+   |
+LL |     #[forbid(nonstandard_style)]
+   |              ^^^^^^^^^^^^^^^^^
+   = note: #[forbid(non_snake_case)] implied by #[forbid(nonstandard_style)]
+
+error: static variable `bad` should have an upper case name
+  --> $DIR/lint-group-nonstandard-style.rs:14:16
+   |
+LL |         static bad: isize = 1;
+   |                ^^^ help: convert the identifier to upper case: `BAD`
+   |
+note: lint level defined here
+  --> $DIR/lint-group-nonstandard-style.rs:10:14
+   |
+LL |     #[forbid(nonstandard_style)]
+   |              ^^^^^^^^^^^^^^^^^
+   = note: #[forbid(non_upper_case_globals)] implied by #[forbid(nonstandard_style)]
+
+warning: function `CamelCase` should have a snake case name
+  --> $DIR/lint-group-nonstandard-style.rs:20:12
+   |
+LL |         fn CamelCase() {}
+   |            ^^^^^^^^^ help: convert the identifier to snake case: `camel_case`
+   |
+note: lint level defined here
+  --> $DIR/lint-group-nonstandard-style.rs:18:17
+   |
+LL |         #![warn(nonstandard_style)]
+   |                 ^^^^^^^^^^^^^^^^^
+   = note: #[warn(non_snake_case)] implied by #[warn(nonstandard_style)]
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/lint/lint-impl-fn.rs b/src/test/ui/lint/lint-impl-fn.rs
new file mode 100644
index 0000000..46874d9
--- /dev/null
+++ b/src/test/ui/lint/lint-impl-fn.rs
@@ -0,0 +1,33 @@
+#![allow(while_true)]
+#![allow(dead_code)]
+
+struct A(isize);
+
+impl A {
+    fn foo(&self) { while true {} }
+
+    #[deny(while_true)]
+    fn bar(&self) { while true {} } //~ ERROR: infinite loops
+}
+
+#[deny(while_true)]
+mod foo {
+    struct B(isize);
+
+    impl B {
+        fn foo(&self) { while true {} } //~ ERROR: infinite loops
+
+        #[allow(while_true)]
+        fn bar(&self) { while true {} }
+    }
+}
+
+#[deny(while_true)]
+fn main() {
+    while true {} //~ ERROR: infinite loops
+}
+
+#[deny(while_true)]
+fn bar() {
+    while cfg!(unix) {} // no error
+}
diff --git a/src/test/ui/lint/lint-impl-fn.stderr b/src/test/ui/lint/lint-impl-fn.stderr
new file mode 100644
index 0000000..56f8511
--- /dev/null
+++ b/src/test/ui/lint/lint-impl-fn.stderr
@@ -0,0 +1,38 @@
+error: denote infinite loops with `loop { ... }`
+  --> $DIR/lint-impl-fn.rs:10:21
+   |
+LL |     fn bar(&self) { while true {} }
+   |                     ^^^^^^^^^^ help: use `loop`
+   |
+note: lint level defined here
+  --> $DIR/lint-impl-fn.rs:9:12
+   |
+LL |     #[deny(while_true)]
+   |            ^^^^^^^^^^
+
+error: denote infinite loops with `loop { ... }`
+  --> $DIR/lint-impl-fn.rs:27:5
+   |
+LL |     while true {}
+   |     ^^^^^^^^^^ help: use `loop`
+   |
+note: lint level defined here
+  --> $DIR/lint-impl-fn.rs:25:8
+   |
+LL | #[deny(while_true)]
+   |        ^^^^^^^^^^
+
+error: denote infinite loops with `loop { ... }`
+  --> $DIR/lint-impl-fn.rs:18:25
+   |
+LL |         fn foo(&self) { while true {} }
+   |                         ^^^^^^^^^^ help: use `loop`
+   |
+note: lint level defined here
+  --> $DIR/lint-impl-fn.rs:13:8
+   |
+LL | #[deny(while_true)]
+   |        ^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/lint/lint-incoherent-auto-trait-objects.rs b/src/test/ui/lint/lint-incoherent-auto-trait-objects.rs
new file mode 100644
index 0000000..0d18965
--- /dev/null
+++ b/src/test/ui/lint/lint-incoherent-auto-trait-objects.rs
@@ -0,0 +1,21 @@
+// ignore-tidy-linelength
+
+trait Foo {}
+
+impl Foo for dyn Send {}
+
+impl Foo for dyn Send + Send {}
+//~^ ERROR conflicting implementations
+//~| hard error
+
+impl Foo for dyn Send + Sync {}
+
+impl Foo for dyn Sync + Send {}
+//~^ ERROR conflicting implementations
+//~| hard error
+
+impl Foo for dyn Send + Sync + Send {}
+//~^ ERROR conflicting implementations
+//~| hard error
+
+fn main() {}
diff --git a/src/test/ui/lint/lint-incoherent-auto-trait-objects.stderr b/src/test/ui/lint/lint-incoherent-auto-trait-objects.stderr
new file mode 100644
index 0000000..928c92e
--- /dev/null
+++ b/src/test/ui/lint/lint-incoherent-auto-trait-objects.stderr
@@ -0,0 +1,39 @@
+error: conflicting implementations of trait `Foo` for type `(dyn std::marker::Send + 'static)`: (E0119)
+  --> $DIR/lint-incoherent-auto-trait-objects.rs:7:1
+   |
+LL | impl Foo for dyn Send {}
+   | --------------------- first implementation here
+LL | 
+LL | impl Foo for dyn Send + Send {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + 'static)`
+   |
+   = note: #[deny(order_dependent_trait_objects)] on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #56484 <https://github.com/rust-lang/rust/issues/56484>
+
+error: conflicting implementations of trait `Foo` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`: (E0119)
+  --> $DIR/lint-incoherent-auto-trait-objects.rs:13:1
+   |
+LL | impl Foo for dyn Send + Sync {}
+   | ---------------------------- first implementation here
+LL | 
+LL | impl Foo for dyn Sync + Send {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + std::marker::Sync + 'static)`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #56484 <https://github.com/rust-lang/rust/issues/56484>
+
+error: conflicting implementations of trait `Foo` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`: (E0119)
+  --> $DIR/lint-incoherent-auto-trait-objects.rs:17:1
+   |
+LL | impl Foo for dyn Sync + Send {}
+   | ---------------------------- first implementation here
+...
+LL | impl Foo for dyn Send + Sync + Send {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + std::marker::Sync + 'static)`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #56484 <https://github.com/rust-lang/rust/issues/56484>
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/lint/lint-lowercase-static-const-pattern-rename.rs b/src/test/ui/lint/lint-lowercase-static-const-pattern-rename.rs
new file mode 100644
index 0000000..8ca5af2
--- /dev/null
+++ b/src/test/ui/lint/lint-lowercase-static-const-pattern-rename.rs
@@ -0,0 +1,63 @@
+// compile-pass
+// Issue #7526: lowercase static constants in patterns look like bindings
+
+// This is similar to lint-lowercase-static-const-pattern.rs, except it
+// shows the expected usual workaround (choosing a different name for
+// the static definition) and also demonstrates that one can work
+// around this problem locally by renaming the constant in the `use`
+// form to an uppercase identifier that placates the lint.
+
+#![deny(non_upper_case_globals)]
+
+pub const A : isize = 97;
+
+fn f() {
+    let r = match (0,0) {
+        (0, A) => 0,
+        (x, y) => 1 + x + y,
+    };
+    assert_eq!(r, 1);
+    let r = match (0,97) {
+        (0, A) => 0,
+        (x, y) => 1 + x + y,
+    };
+    assert_eq!(r, 0);
+}
+
+mod m {
+    #[allow(non_upper_case_globals)]
+    pub const aha : isize = 7;
+}
+
+fn g() {
+    use self::m::aha as AHA;
+    let r = match (0,0) {
+        (0, AHA) => 0,
+        (x, y)   => 1 + x + y,
+    };
+    assert_eq!(r, 1);
+    let r = match (0,7) {
+        (0, AHA) => 0,
+        (x, y)   => 1 + x + y,
+    };
+    assert_eq!(r, 0);
+}
+
+fn h() {
+    let r = match (0,0) {
+        (0, self::m::aha) => 0,
+        (x, y)      => 1 + x + y,
+    };
+    assert_eq!(r, 1);
+    let r = match (0,7) {
+        (0, self::m::aha) => 0,
+        (x, y)      => 1 + x + y,
+    };
+    assert_eq!(r, 0);
+}
+
+pub fn main () {
+    f();
+    g();
+    h();
+}
diff --git a/src/test/ui/lint/lint-lowercase-static-const-pattern.rs b/src/test/ui/lint/lint-lowercase-static-const-pattern.rs
new file mode 100644
index 0000000..c2e159e
--- /dev/null
+++ b/src/test/ui/lint/lint-lowercase-static-const-pattern.rs
@@ -0,0 +1,51 @@
+// Issue #7526: lowercase static constants in patterns look like bindings
+
+#![allow(dead_code)]
+#![deny(non_upper_case_globals)]
+
+#[allow(non_upper_case_globals)]
+pub const a : isize = 97;
+
+fn f() {
+    let r = match (0,0) {
+        (0, a) => 0,
+        //~^ ERROR constant in pattern `a` should have an upper case name
+        (x, y) => 1 + x + y,
+    };
+    assert_eq!(r, 1);
+}
+
+mod m {
+    #[allow(non_upper_case_globals)]
+    pub const aha : isize = 7;
+}
+
+fn g() {
+    use self::m::aha;
+    let r = match (0,0) {
+        (0, aha) => 0,
+        //~^ ERROR constant in pattern `aha` should have an upper case name
+        (x, y)   => 1 + x + y,
+    };
+    assert_eq!(r, 1);
+}
+
+mod n {
+    pub const OKAY : isize = 8;
+}
+
+fn h() {
+    use self::n::OKAY as not_okay;
+    let r = match (0,0) {
+        (0, not_okay) => 0,
+//~^ ERROR constant in pattern `not_okay` should have an upper case name
+        (x, y)   => 1 + x + y,
+    };
+    assert_eq!(r, 1);
+}
+
+fn main () {
+    f();
+    g();
+    h();
+}
diff --git a/src/test/ui/lint/lint-lowercase-static-const-pattern.stderr b/src/test/ui/lint/lint-lowercase-static-const-pattern.stderr
new file mode 100644
index 0000000..d95510c
--- /dev/null
+++ b/src/test/ui/lint/lint-lowercase-static-const-pattern.stderr
@@ -0,0 +1,26 @@
+error: constant in pattern `a` should have an upper case name
+  --> $DIR/lint-lowercase-static-const-pattern.rs:11:13
+   |
+LL |         (0, a) => 0,
+   |             ^ help: convert the identifier to upper case: `A`
+   |
+note: lint level defined here
+  --> $DIR/lint-lowercase-static-const-pattern.rs:4:9
+   |
+LL | #![deny(non_upper_case_globals)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+
+error: constant in pattern `aha` should have an upper case name
+  --> $DIR/lint-lowercase-static-const-pattern.rs:26:13
+   |
+LL |         (0, aha) => 0,
+   |             ^^^ help: convert the identifier to upper case: `AHA`
+
+error: constant in pattern `not_okay` should have an upper case name
+  --> $DIR/lint-lowercase-static-const-pattern.rs:40:13
+   |
+LL |         (0, not_okay) => 0,
+   |             ^^^^^^^^ help: convert the identifier to upper case: `NOT_OKAY`
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/lint/lint-malformed.rs b/src/test/ui/lint/lint-malformed.rs
new file mode 100644
index 0000000..c97a432
--- /dev/null
+++ b/src/test/ui/lint/lint-malformed.rs
@@ -0,0 +1,4 @@
+#![deny = "foo"] //~ ERROR attribute must be of the form
+#![allow(bar = "baz")] //~ ERROR malformed lint attribute
+
+fn main() { }
diff --git a/src/test/ui/lint/lint-malformed.stderr b/src/test/ui/lint/lint-malformed.stderr
new file mode 100644
index 0000000..f5b9e2b
--- /dev/null
+++ b/src/test/ui/lint/lint-malformed.stderr
@@ -0,0 +1,15 @@
+error[E0452]: malformed lint attribute
+  --> $DIR/lint-malformed.rs:2:10
+   |
+LL | #![allow(bar = "baz")]
+   |          ^^^^^^^^^^^
+
+error: attribute must be of the form `#[deny(lint1, lint2, ..., /*opt*/ reason = "...")]`
+  --> $DIR/lint-malformed.rs:1:1
+   |
+LL | #![deny = "foo"]
+   | ^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0452`.
diff --git a/src/test/ui/lint/lint-misplaced-attr.rs b/src/test/ui/lint/lint-misplaced-attr.rs
new file mode 100644
index 0000000..e5ad7a5
--- /dev/null
+++ b/src/test/ui/lint/lint-misplaced-attr.rs
@@ -0,0 +1,12 @@
+// When denying at the crate level, be sure to not get random warnings from the
+// injected intrinsics by the compiler.
+
+#![deny(unused_attributes)]
+
+mod a {
+    #![crate_type = "bin"] //~ ERROR unused attribute
+                           //~^ ERROR should be in the root module
+}
+
+#[crate_type = "bin"] fn main() {} //~ ERROR unused attribute
+                                   //~^ ERROR should be an inner
diff --git a/src/test/ui/lint/lint-misplaced-attr.stderr b/src/test/ui/lint/lint-misplaced-attr.stderr
new file mode 100644
index 0000000..1419f85
--- /dev/null
+++ b/src/test/ui/lint/lint-misplaced-attr.stderr
@@ -0,0 +1,32 @@
+error: unused attribute
+  --> $DIR/lint-misplaced-attr.rs:7:5
+   |
+LL |     #![crate_type = "bin"]
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/lint-misplaced-attr.rs:4:9
+   |
+LL | #![deny(unused_attributes)]
+   |         ^^^^^^^^^^^^^^^^^
+
+error: crate-level attribute should be in the root module
+  --> $DIR/lint-misplaced-attr.rs:7:5
+   |
+LL |     #![crate_type = "bin"]
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error: unused attribute
+  --> $DIR/lint-misplaced-attr.rs:11:1
+   |
+LL | #[crate_type = "bin"] fn main() {}
+   | ^^^^^^^^^^^^^^^^^^^^^
+
+error: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+  --> $DIR/lint-misplaced-attr.rs:11:1
+   |
+LL | #[crate_type = "bin"] fn main() {}
+   | ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/lint/lint-missing-copy-implementations.rs b/src/test/ui/lint/lint-missing-copy-implementations.rs
new file mode 100644
index 0000000..918f40d
--- /dev/null
+++ b/src/test/ui/lint/lint-missing-copy-implementations.rs
@@ -0,0 +1,15 @@
+// See issue 19712
+
+#![deny(missing_copy_implementations)]
+
+mod inner {
+    pub struct Foo { //~ ERROR type could implement `Copy`; consider adding `impl Copy`
+        pub field: i32
+    }
+}
+
+pub fn foo() -> inner::Foo {
+    inner::Foo { field: 42 }
+}
+
+fn main() {}
diff --git a/src/test/ui/lint/lint-missing-copy-implementations.stderr b/src/test/ui/lint/lint-missing-copy-implementations.stderr
new file mode 100644
index 0000000..7b6674e
--- /dev/null
+++ b/src/test/ui/lint/lint-missing-copy-implementations.stderr
@@ -0,0 +1,16 @@
+error: type could implement `Copy`; consider adding `impl Copy`
+  --> $DIR/lint-missing-copy-implementations.rs:6:5
+   |
+LL | /     pub struct Foo {
+LL | |         pub field: i32
+LL | |     }
+   | |_____^
+   |
+note: lint level defined here
+  --> $DIR/lint-missing-copy-implementations.rs:3:9
+   |
+LL | #![deny(missing_copy_implementations)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lint/lint-missing-doc.rs b/src/test/ui/lint/lint-missing-doc.rs
new file mode 100644
index 0000000..a2466d2
--- /dev/null
+++ b/src/test/ui/lint/lint-missing-doc.rs
@@ -0,0 +1,186 @@
+// When denying at the crate level, be sure to not get random warnings from the
+// injected intrinsics by the compiler.
+#![deny(missing_docs)]
+#![allow(dead_code)]
+#![feature(associated_type_defaults)]
+
+//! Some garbage docs for the crate here
+#![doc="More garbage"]
+
+type Typedef = String;
+pub type PubTypedef = String; //~ ERROR: missing documentation for a type alias
+
+struct Foo {
+    a: isize,
+    b: isize,
+}
+
+pub struct PubFoo { //~ ERROR: missing documentation for a struct
+    pub a: isize,      //~ ERROR: missing documentation for a struct field
+    b: isize,
+}
+
+#[allow(missing_docs)]
+pub struct PubFoo2 {
+    pub a: isize,
+    pub c: isize,
+}
+
+mod module_no_dox {}
+pub mod pub_module_no_dox {} //~ ERROR: missing documentation for a module
+
+/// dox
+pub fn foo() {}
+pub fn foo2() {} //~ ERROR: missing documentation for a function
+fn foo3() {}
+#[allow(missing_docs)] pub fn foo4() {}
+
+/// dox
+pub trait A {
+    /// dox
+    fn foo(&self);
+    /// dox
+    fn foo_with_impl(&self) {}
+}
+
+#[allow(missing_docs)]
+trait B {
+    fn foo(&self);
+    fn foo_with_impl(&self) {}
+}
+
+pub trait C { //~ ERROR: missing documentation for a trait
+    fn foo(&self); //~ ERROR: missing documentation for a trait method
+    fn foo_with_impl(&self) {} //~ ERROR: missing documentation for a trait method
+}
+
+#[allow(missing_docs)]
+pub trait D {
+    fn dummy(&self) { }
+}
+
+/// dox
+pub trait E {
+    type AssociatedType; //~ ERROR: missing documentation for an associated type
+    type AssociatedTypeDef = Self; //~ ERROR: missing documentation for an associated type
+
+    /// dox
+    type DocumentedType;
+    /// dox
+    type DocumentedTypeDef = Self;
+    /// dox
+    fn dummy(&self) {}
+}
+
+impl Foo {
+    pub fn foo() {}
+    fn bar() {}
+}
+
+impl PubFoo {
+    pub fn foo() {} //~ ERROR: missing documentation for a method
+    /// dox
+    pub fn foo1() {}
+    fn foo2() {}
+    #[allow(missing_docs)] pub fn foo3() {}
+}
+
+#[allow(missing_docs)]
+trait F {
+    fn a();
+    fn b(&self);
+}
+
+// should need to redefine documentation for implementations of traits
+impl F for Foo {
+    fn a() {}
+    fn b(&self) {}
+}
+
+// It sure is nice if doc(hidden) implies allow(missing_docs), and that it
+// applies recursively
+#[doc(hidden)]
+mod a {
+    pub fn baz() {}
+    pub mod b {
+        pub fn baz() {}
+    }
+}
+
+enum Baz {
+    BazA {
+        a: isize,
+        b: isize
+    },
+    BarB
+}
+
+pub enum PubBaz { //~ ERROR: missing documentation for an enum
+    PubBazA { //~ ERROR: missing documentation for a variant
+        a: isize, //~ ERROR: missing documentation for a struct field
+    },
+}
+
+/// dox
+pub enum PubBaz2 {
+    /// dox
+    PubBaz2A {
+        /// dox
+        a: isize,
+    },
+}
+
+#[allow(missing_docs)]
+pub enum PubBaz3 {
+    PubBaz3A {
+        b: isize
+    },
+}
+
+#[doc(hidden)]
+pub fn baz() {}
+
+
+const FOO: u32 = 0;
+/// dox
+pub const FOO1: u32 = 0;
+#[allow(missing_docs)]
+pub const FOO2: u32 = 0;
+#[doc(hidden)]
+pub const FOO3: u32 = 0;
+pub const FOO4: u32 = 0; //~ ERROR: missing documentation for a const
+
+
+static BAR: u32 = 0;
+/// dox
+pub static BAR1: u32 = 0;
+#[allow(missing_docs)]
+pub static BAR2: u32 = 0;
+#[doc(hidden)]
+pub static BAR3: u32 = 0;
+pub static BAR4: u32 = 0; //~ ERROR: missing documentation for a static
+
+
+mod internal_impl {
+    /// dox
+    pub fn documented() {}
+    pub fn undocumented1() {} //~ ERROR: missing documentation for a function
+    pub fn undocumented2() {} //~ ERROR: missing documentation for a function
+    fn undocumented3() {}
+    /// dox
+    pub mod globbed {
+        /// dox
+        pub fn also_documented() {}
+        pub fn also_undocumented1() {} //~ ERROR: missing documentation for a function
+        fn also_undocumented2() {}
+    }
+}
+/// dox
+pub mod public_interface {
+    pub use internal_impl::documented as foo;
+    pub use internal_impl::undocumented1 as bar;
+    pub use internal_impl::{documented, undocumented2};
+    pub use internal_impl::globbed::*;
+}
+
+fn main() {}
diff --git a/src/test/ui/lint/lint-missing-doc.stderr b/src/test/ui/lint/lint-missing-doc.stderr
new file mode 100644
index 0000000..3532c93
--- /dev/null
+++ b/src/test/ui/lint/lint-missing-doc.stderr
@@ -0,0 +1,122 @@
+error: missing documentation for a type alias
+  --> $DIR/lint-missing-doc.rs:11:1
+   |
+LL | pub type PubTypedef = String;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/lint-missing-doc.rs:3:9
+   |
+LL | #![deny(missing_docs)]
+   |         ^^^^^^^^^^^^
+
+error: missing documentation for a struct
+  --> $DIR/lint-missing-doc.rs:18:1
+   |
+LL | pub struct PubFoo {
+   | ^^^^^^^^^^^^^^^^^
+
+error: missing documentation for a struct field
+  --> $DIR/lint-missing-doc.rs:19:5
+   |
+LL |     pub a: isize,
+   |     ^^^^^^^^^^^^
+
+error: missing documentation for a module
+  --> $DIR/lint-missing-doc.rs:30:1
+   |
+LL | pub mod pub_module_no_dox {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: missing documentation for a function
+  --> $DIR/lint-missing-doc.rs:34:1
+   |
+LL | pub fn foo2() {}
+   | ^^^^^^^^^^^^^
+
+error: missing documentation for a trait
+  --> $DIR/lint-missing-doc.rs:52:1
+   |
+LL | pub trait C {
+   | ^^^^^^^^^^^
+
+error: missing documentation for a trait method
+  --> $DIR/lint-missing-doc.rs:53:5
+   |
+LL |     fn foo(&self);
+   |     ^^^^^^^^^^^^^^
+
+error: missing documentation for a trait method
+  --> $DIR/lint-missing-doc.rs:54:5
+   |
+LL |     fn foo_with_impl(&self) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: missing documentation for an associated type
+  --> $DIR/lint-missing-doc.rs:64:5
+   |
+LL |     type AssociatedType;
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: missing documentation for an associated type
+  --> $DIR/lint-missing-doc.rs:65:5
+   |
+LL |     type AssociatedTypeDef = Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: missing documentation for a method
+  --> $DIR/lint-missing-doc.rs:81:5
+   |
+LL |     pub fn foo() {}
+   |     ^^^^^^^^^^^^
+
+error: missing documentation for an enum
+  --> $DIR/lint-missing-doc.rs:118:1
+   |
+LL | pub enum PubBaz {
+   | ^^^^^^^^^^^^^^^
+
+error: missing documentation for a variant
+  --> $DIR/lint-missing-doc.rs:119:5
+   |
+LL |     PubBazA {
+   |     ^^^^^^^
+
+error: missing documentation for a struct field
+  --> $DIR/lint-missing-doc.rs:120:9
+   |
+LL |         a: isize,
+   |         ^^^^^^^^
+
+error: missing documentation for a constant
+  --> $DIR/lint-missing-doc.rs:151:1
+   |
+LL | pub const FOO4: u32 = 0;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: missing documentation for a static
+  --> $DIR/lint-missing-doc.rs:161:1
+   |
+LL | pub static BAR4: u32 = 0;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: missing documentation for a function
+  --> $DIR/lint-missing-doc.rs:167:5
+   |
+LL |     pub fn undocumented1() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error: missing documentation for a function
+  --> $DIR/lint-missing-doc.rs:168:5
+   |
+LL |     pub fn undocumented2() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error: missing documentation for a function
+  --> $DIR/lint-missing-doc.rs:174:9
+   |
+LL |         pub fn also_undocumented1() {}
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 19 previous errors
+
diff --git a/src/test/ui/lint/lint-non-camel-case-types.rs b/src/test/ui/lint/lint-non-camel-case-types.rs
new file mode 100644
index 0000000..d3b119a
--- /dev/null
+++ b/src/test/ui/lint/lint-non-camel-case-types.rs
@@ -0,0 +1,36 @@
+#![forbid(non_camel_case_types)]
+#![allow(dead_code)]
+
+struct ONE_TWO_THREE;
+//~^ ERROR type `ONE_TWO_THREE` should have an upper camel case name
+
+struct foo { //~ ERROR type `foo` should have an upper camel case name
+    bar: isize,
+}
+
+enum foo2 { //~ ERROR type `foo2` should have an upper camel case name
+    Bar
+}
+
+struct foo3 { //~ ERROR type `foo3` should have an upper camel case name
+    bar: isize
+}
+
+type foo4 = isize; //~ ERROR type `foo4` should have an upper camel case name
+
+enum Foo5 {
+    bar //~ ERROR variant `bar` should have an upper camel case name
+}
+
+trait foo6 { //~ ERROR trait `foo6` should have an upper camel case name
+    fn dummy(&self) { }
+}
+
+fn f<ty>(_: ty) {} //~ ERROR type parameter `ty` should have an upper camel case name
+
+#[repr(C)]
+struct foo7 {
+    bar: isize,
+}
+
+fn main() { }
diff --git a/src/test/ui/lint/lint-non-camel-case-types.stderr b/src/test/ui/lint/lint-non-camel-case-types.stderr
new file mode 100644
index 0000000..432a16d
--- /dev/null
+++ b/src/test/ui/lint/lint-non-camel-case-types.stderr
@@ -0,0 +1,56 @@
+error: type `ONE_TWO_THREE` should have an upper camel case name
+  --> $DIR/lint-non-camel-case-types.rs:4:8
+   |
+LL | struct ONE_TWO_THREE;
+   |        ^^^^^^^^^^^^^ help: convert the identifier to upper camel case: `OneTwoThree`
+   |
+note: lint level defined here
+  --> $DIR/lint-non-camel-case-types.rs:1:11
+   |
+LL | #![forbid(non_camel_case_types)]
+   |           ^^^^^^^^^^^^^^^^^^^^
+
+error: type `foo` should have an upper camel case name
+  --> $DIR/lint-non-camel-case-types.rs:7:8
+   |
+LL | struct foo {
+   |        ^^^ help: convert the identifier to upper camel case: `Foo`
+
+error: type `foo2` should have an upper camel case name
+  --> $DIR/lint-non-camel-case-types.rs:11:6
+   |
+LL | enum foo2 {
+   |      ^^^^ help: convert the identifier to upper camel case: `Foo2`
+
+error: type `foo3` should have an upper camel case name
+  --> $DIR/lint-non-camel-case-types.rs:15:8
+   |
+LL | struct foo3 {
+   |        ^^^^ help: convert the identifier to upper camel case: `Foo3`
+
+error: type `foo4` should have an upper camel case name
+  --> $DIR/lint-non-camel-case-types.rs:19:6
+   |
+LL | type foo4 = isize;
+   |      ^^^^ help: convert the identifier to upper camel case: `Foo4`
+
+error: variant `bar` should have an upper camel case name
+  --> $DIR/lint-non-camel-case-types.rs:22:5
+   |
+LL |     bar
+   |     ^^^ help: convert the identifier to upper camel case: `Bar`
+
+error: trait `foo6` should have an upper camel case name
+  --> $DIR/lint-non-camel-case-types.rs:25:7
+   |
+LL | trait foo6 {
+   |       ^^^^ help: convert the identifier to upper camel case: `Foo6`
+
+error: type parameter `ty` should have an upper camel case name
+  --> $DIR/lint-non-camel-case-types.rs:29:6
+   |
+LL | fn f<ty>(_: ty) {}
+   |      ^^ help: convert the identifier to upper camel case: `Ty`
+
+error: aborting due to 8 previous errors
+
diff --git a/src/test/ui/lint/lint-non-camel-case-variant.rs b/src/test/ui/lint/lint-non-camel-case-variant.rs
new file mode 100644
index 0000000..1f06b28
--- /dev/null
+++ b/src/test/ui/lint/lint-non-camel-case-variant.rs
@@ -0,0 +1,10 @@
+// compile-pass
+
+#![deny(non_camel_case_types)]
+
+pub enum Foo {
+    #[allow(non_camel_case_types)]
+    bar
+}
+
+fn main() {}
diff --git a/src/test/ui/lint/lint-non-camel-case-with-trailing-underscores.rs b/src/test/ui/lint/lint-non-camel-case-with-trailing-underscores.rs
new file mode 100644
index 0000000..c2fdfb4
--- /dev/null
+++ b/src/test/ui/lint/lint-non-camel-case-with-trailing-underscores.rs
@@ -0,0 +1,11 @@
+// compile-pass
+
+#![allow(dead_code)]
+// This is ok because we often use the trailing underscore to mean 'prime'
+
+// pretty-expanded FIXME #23616
+
+#[forbid(non_camel_case_types)]
+type Foo_ = isize;
+
+pub fn main() { }
diff --git a/src/test/ui/lint/lint-non-snake-case-crate-2.rs b/src/test/ui/lint/lint-non-snake-case-crate-2.rs
new file mode 100644
index 0000000..1b763a9
--- /dev/null
+++ b/src/test/ui/lint/lint-non-snake-case-crate-2.rs
@@ -0,0 +1,6 @@
+// compile-flags: --crate-name NonSnakeCase
+// error-pattern: crate `NonSnakeCase` should have a snake case name
+
+#![deny(non_snake_case)]
+
+fn main() {}
diff --git a/src/test/ui/lint/lint-non-snake-case-crate-2.stderr b/src/test/ui/lint/lint-non-snake-case-crate-2.stderr
new file mode 100644
index 0000000..f330319
--- /dev/null
+++ b/src/test/ui/lint/lint-non-snake-case-crate-2.stderr
@@ -0,0 +1,11 @@
+error: crate `NonSnakeCase` should have a snake case name
+   |
+note: lint level defined here
+  --> $DIR/lint-non-snake-case-crate-2.rs:4:9
+   |
+LL | #![deny(non_snake_case)]
+   |         ^^^^^^^^^^^^^^
+   = help: convert the identifier to snake case: `non_snake_case`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lint/lint-non-snake-case-crate.rs b/src/test/ui/lint/lint-non-snake-case-crate.rs
new file mode 100644
index 0000000..e4e8426
--- /dev/null
+++ b/src/test/ui/lint/lint-non-snake-case-crate.rs
@@ -0,0 +1,5 @@
+#![crate_name = "NonSnakeCase"]
+//~^ ERROR crate `NonSnakeCase` should have a snake case name
+#![deny(non_snake_case)]
+
+fn main() {}
diff --git a/src/test/ui/lint/lint-non-snake-case-crate.stderr b/src/test/ui/lint/lint-non-snake-case-crate.stderr
new file mode 100644
index 0000000..5cfd60a
--- /dev/null
+++ b/src/test/ui/lint/lint-non-snake-case-crate.stderr
@@ -0,0 +1,14 @@
+error: crate `NonSnakeCase` should have a snake case name
+  --> $DIR/lint-non-snake-case-crate.rs:1:18
+   |
+LL | #![crate_name = "NonSnakeCase"]
+   |                  ^^^^^^^^^^^^ help: convert the identifier to snake case: `non_snake_case`
+   |
+note: lint level defined here
+  --> $DIR/lint-non-snake-case-crate.rs:3:9
+   |
+LL | #![deny(non_snake_case)]
+   |         ^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lint/lint-non-snake-case-functions.rs b/src/test/ui/lint/lint-non-snake-case-functions.rs
new file mode 100644
index 0000000..fa64a9f
--- /dev/null
+++ b/src/test/ui/lint/lint-non-snake-case-functions.rs
@@ -0,0 +1,44 @@
+#![deny(non_snake_case)]
+#![allow(dead_code)]
+
+struct Foo;
+
+impl Foo {
+    fn Foo_Method() {}
+    //~^ ERROR method `Foo_Method` should have a snake case name
+
+    // Don't allow two underscores in a row
+    fn foo__method(&self) {}
+    //~^ ERROR method `foo__method` should have a snake case name
+
+    pub fn xyZ(&mut self) {}
+    //~^ ERROR method `xyZ` should have a snake case name
+
+    fn render_HTML() {}
+    //~^ ERROR method `render_HTML` should have a snake case name
+}
+
+trait X {
+    fn ABC();
+    //~^ ERROR trait method `ABC` should have a snake case name
+
+    fn a_b_C(&self) {}
+    //~^ ERROR trait method `a_b_C` should have a snake case name
+
+    fn something__else(&mut self);
+    //~^ ERROR trait method `something__else` should have a snake case name
+}
+
+impl X for Foo {
+    // These errors should be caught at the trait definition not the impl
+    fn ABC() {}
+    fn something__else(&mut self) {}
+}
+
+fn Cookie() {}
+//~^ ERROR function `Cookie` should have a snake case name
+
+pub fn bi_S_Cuit() {}
+//~^ ERROR function `bi_S_Cuit` should have a snake case name
+
+fn main() { }
diff --git a/src/test/ui/lint/lint-non-snake-case-functions.stderr b/src/test/ui/lint/lint-non-snake-case-functions.stderr
new file mode 100644
index 0000000..49cbfa9
--- /dev/null
+++ b/src/test/ui/lint/lint-non-snake-case-functions.stderr
@@ -0,0 +1,62 @@
+error: method `Foo_Method` should have a snake case name
+  --> $DIR/lint-non-snake-case-functions.rs:7:8
+   |
+LL |     fn Foo_Method() {}
+   |        ^^^^^^^^^^ help: convert the identifier to snake case: `foo_method`
+   |
+note: lint level defined here
+  --> $DIR/lint-non-snake-case-functions.rs:1:9
+   |
+LL | #![deny(non_snake_case)]
+   |         ^^^^^^^^^^^^^^
+
+error: method `foo__method` should have a snake case name
+  --> $DIR/lint-non-snake-case-functions.rs:11:8
+   |
+LL |     fn foo__method(&self) {}
+   |        ^^^^^^^^^^^ help: convert the identifier to snake case: `foo_method`
+
+error: method `xyZ` should have a snake case name
+  --> $DIR/lint-non-snake-case-functions.rs:14:12
+   |
+LL |     pub fn xyZ(&mut self) {}
+   |            ^^^ help: convert the identifier to snake case: `xy_z`
+
+error: method `render_HTML` should have a snake case name
+  --> $DIR/lint-non-snake-case-functions.rs:17:8
+   |
+LL |     fn render_HTML() {}
+   |        ^^^^^^^^^^^ help: convert the identifier to snake case: `render_html`
+
+error: trait method `ABC` should have a snake case name
+  --> $DIR/lint-non-snake-case-functions.rs:22:8
+   |
+LL |     fn ABC();
+   |        ^^^ help: convert the identifier to snake case: `abc`
+
+error: trait method `a_b_C` should have a snake case name
+  --> $DIR/lint-non-snake-case-functions.rs:25:8
+   |
+LL |     fn a_b_C(&self) {}
+   |        ^^^^^ help: convert the identifier to snake case: `a_b_c`
+
+error: trait method `something__else` should have a snake case name
+  --> $DIR/lint-non-snake-case-functions.rs:28:8
+   |
+LL |     fn something__else(&mut self);
+   |        ^^^^^^^^^^^^^^^ help: convert the identifier to snake case: `something_else`
+
+error: function `Cookie` should have a snake case name
+  --> $DIR/lint-non-snake-case-functions.rs:38:4
+   |
+LL | fn Cookie() {}
+   |    ^^^^^^ help: convert the identifier to snake case: `cookie`
+
+error: function `bi_S_Cuit` should have a snake case name
+  --> $DIR/lint-non-snake-case-functions.rs:41:8
+   |
+LL | pub fn bi_S_Cuit() {}
+   |        ^^^^^^^^^ help: convert the identifier to snake case: `bi_s_cuit`
+
+error: aborting due to 9 previous errors
+
diff --git a/src/test/ui/lint/lint-non-snake-case-lifetimes.rs b/src/test/ui/lint/lint-non-snake-case-lifetimes.rs
new file mode 100644
index 0000000..de76d2d
--- /dev/null
+++ b/src/test/ui/lint/lint-non-snake-case-lifetimes.rs
@@ -0,0 +1,8 @@
+#![deny(non_snake_case)]
+#![allow(dead_code)]
+
+fn f<'FooBar>( //~ ERROR lifetime `'FooBar` should have a snake case name
+    _: &'FooBar ()
+) {}
+
+fn main() { }
diff --git a/src/test/ui/lint/lint-non-snake-case-lifetimes.stderr b/src/test/ui/lint/lint-non-snake-case-lifetimes.stderr
new file mode 100644
index 0000000..d638626
--- /dev/null
+++ b/src/test/ui/lint/lint-non-snake-case-lifetimes.stderr
@@ -0,0 +1,14 @@
+error: lifetime `'FooBar` should have a snake case name
+  --> $DIR/lint-non-snake-case-lifetimes.rs:4:6
+   |
+LL | fn f<'FooBar>(
+   |      ^^^^^^^ help: convert the identifier to snake case: `'foo_bar`
+   |
+note: lint level defined here
+  --> $DIR/lint-non-snake-case-lifetimes.rs:1:9
+   |
+LL | #![deny(non_snake_case)]
+   |         ^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lint/lint-non-snake-case-modules.rs b/src/test/ui/lint/lint-non-snake-case-modules.rs
new file mode 100644
index 0000000..73f1233
--- /dev/null
+++ b/src/test/ui/lint/lint-non-snake-case-modules.rs
@@ -0,0 +1,10 @@
+#![deny(non_snake_case)]
+#![allow(dead_code)]
+
+mod FooBar { //~ ERROR module `FooBar` should have a snake case name
+    pub struct S;
+}
+
+fn f(_: FooBar::S) { }
+
+fn main() { }
diff --git a/src/test/ui/lint/lint-non-snake-case-modules.stderr b/src/test/ui/lint/lint-non-snake-case-modules.stderr
new file mode 100644
index 0000000..847c43e
--- /dev/null
+++ b/src/test/ui/lint/lint-non-snake-case-modules.stderr
@@ -0,0 +1,14 @@
+error: module `FooBar` should have a snake case name
+  --> $DIR/lint-non-snake-case-modules.rs:4:5
+   |
+LL | mod FooBar {
+   |     ^^^^^^ help: convert the identifier to snake case: `foo_bar`
+   |
+note: lint level defined here
+  --> $DIR/lint-non-snake-case-modules.rs:1:9
+   |
+LL | #![deny(non_snake_case)]
+   |         ^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lint/lint-non-snake-case-no-lowercase-equivalent.rs b/src/test/ui/lint/lint-non-snake-case-no-lowercase-equivalent.rs
new file mode 100644
index 0000000..9a6487d
--- /dev/null
+++ b/src/test/ui/lint/lint-non-snake-case-no-lowercase-equivalent.rs
@@ -0,0 +1,12 @@
+// compile-pass
+
+#![allow(dead_code)]
+// pretty-expanded FIXME #23616
+
+#![feature(non_ascii_idents)]
+#![deny(non_snake_case)]
+
+// This name is neither upper nor lower case
+fn 你好() {}
+
+fn main() {}
diff --git a/src/test/ui/lint/lint-non-uppercase-associated-const.rs b/src/test/ui/lint/lint-non-uppercase-associated-const.rs
new file mode 100644
index 0000000..7b0d939
--- /dev/null
+++ b/src/test/ui/lint/lint-non-uppercase-associated-const.rs
@@ -0,0 +1,11 @@
+#![deny(non_upper_case_globals)]
+#![allow(dead_code)]
+
+struct Foo;
+
+impl Foo {
+    const not_upper: bool = true;
+}
+//~^^ ERROR associated constant `not_upper` should have an upper case name
+
+fn main() {}
diff --git a/src/test/ui/lint/lint-non-uppercase-associated-const.stderr b/src/test/ui/lint/lint-non-uppercase-associated-const.stderr
new file mode 100644
index 0000000..2185d5a
--- /dev/null
+++ b/src/test/ui/lint/lint-non-uppercase-associated-const.stderr
@@ -0,0 +1,14 @@
+error: associated constant `not_upper` should have an upper case name
+  --> $DIR/lint-non-uppercase-associated-const.rs:7:11
+   |
+LL |     const not_upper: bool = true;
+   |           ^^^^^^^^^ help: convert the identifier to upper case: `NOT_UPPER`
+   |
+note: lint level defined here
+  --> $DIR/lint-non-uppercase-associated-const.rs:1:9
+   |
+LL | #![deny(non_upper_case_globals)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lint/lint-non-uppercase-statics.rs b/src/test/ui/lint/lint-non-uppercase-statics.rs
new file mode 100644
index 0000000..5bd1430
--- /dev/null
+++ b/src/test/ui/lint/lint-non-uppercase-statics.rs
@@ -0,0 +1,11 @@
+#![forbid(non_upper_case_globals)]
+#![allow(dead_code)]
+
+static foo: isize = 1; //~ ERROR static variable `foo` should have an upper case name
+
+static mut bar: isize = 1; //~ ERROR static variable `bar` should have an upper case name
+
+#[no_mangle]
+pub static extern_foo: isize = 1; // OK, because #[no_mangle] supersedes the warning
+
+fn main() { }
diff --git a/src/test/ui/lint/lint-non-uppercase-statics.stderr b/src/test/ui/lint/lint-non-uppercase-statics.stderr
new file mode 100644
index 0000000..8b47727
--- /dev/null
+++ b/src/test/ui/lint/lint-non-uppercase-statics.stderr
@@ -0,0 +1,20 @@
+error: static variable `foo` should have an upper case name
+  --> $DIR/lint-non-uppercase-statics.rs:4:8
+   |
+LL | static foo: isize = 1;
+   |        ^^^ help: convert the identifier to upper case: `FOO`
+   |
+note: lint level defined here
+  --> $DIR/lint-non-uppercase-statics.rs:1:11
+   |
+LL | #![forbid(non_upper_case_globals)]
+   |           ^^^^^^^^^^^^^^^^^^^^^^
+
+error: static variable `bar` should have an upper case name
+  --> $DIR/lint-non-uppercase-statics.rs:6:12
+   |
+LL | static mut bar: isize = 1;
+   |            ^^^ help: convert the identifier to upper case: `BAR`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/lint/lint-nonstandard-style-unicode.rs b/src/test/ui/lint/lint-nonstandard-style-unicode.rs
new file mode 100644
index 0000000..a0b4130
--- /dev/null
+++ b/src/test/ui/lint/lint-nonstandard-style-unicode.rs
@@ -0,0 +1,16 @@
+// compile-pass
+
+#![allow(dead_code)]
+
+#![forbid(non_camel_case_types)]
+#![forbid(non_upper_case_globals)]
+#![feature(non_ascii_idents)]
+
+// Some scripts (e.g., hiragana) don't have a concept of
+// upper/lowercase
+
+struct ヒ;
+
+static ラ: usize = 0;
+
+pub fn main() {}
diff --git a/src/test/ui/lint/lint-obsolete-attr.rs b/src/test/ui/lint/lint-obsolete-attr.rs
new file mode 100644
index 0000000..149948b
--- /dev/null
+++ b/src/test/ui/lint/lint-obsolete-attr.rs
@@ -0,0 +1,12 @@
+// When denying at the crate level, be sure to not get random warnings from the
+// injected intrinsics by the compiler.
+
+#![deny(unused_attributes)]
+#![allow(dead_code)]
+#![feature(custom_attribute)]
+
+#[ab_isize="stdcall"] extern {} //~ ERROR unused attribute
+
+#[fixed_stack_segment] fn f() {} //~ ERROR unused attribute
+
+fn main() {}
diff --git a/src/test/ui/lint/lint-obsolete-attr.stderr b/src/test/ui/lint/lint-obsolete-attr.stderr
new file mode 100644
index 0000000..c06bd26
--- /dev/null
+++ b/src/test/ui/lint/lint-obsolete-attr.stderr
@@ -0,0 +1,20 @@
+error: unused attribute
+  --> $DIR/lint-obsolete-attr.rs:8:1
+   |
+LL | #[ab_isize="stdcall"] extern {}
+   | ^^^^^^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/lint-obsolete-attr.rs:4:9
+   |
+LL | #![deny(unused_attributes)]
+   |         ^^^^^^^^^^^^^^^^^
+
+error: unused attribute
+  --> $DIR/lint-obsolete-attr.rs:10:1
+   |
+LL | #[fixed_stack_segment] fn f() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/lint/lint-output-format-2.rs b/src/test/ui/lint/lint-output-format-2.rs
new file mode 100644
index 0000000..c9b33f0
--- /dev/null
+++ b/src/test/ui/lint/lint-output-format-2.rs
@@ -0,0 +1,15 @@
+// aux-build:lint_output_format.rs
+
+#![feature(unstable_test_feature)]
+// compile-pass
+
+extern crate lint_output_format;
+use lint_output_format::{foo, bar};
+//~^ WARNING use of deprecated item 'lint_output_format::foo': text
+
+
+fn main() {
+    let _x = foo();
+    //~^ WARNING use of deprecated item 'lint_output_format::foo': text
+    let _y = bar();
+}
diff --git a/src/test/ui/lint/lint-output-format-2.stderr b/src/test/ui/lint/lint-output-format-2.stderr
new file mode 100644
index 0000000..f4e6b06
--- /dev/null
+++ b/src/test/ui/lint/lint-output-format-2.stderr
@@ -0,0 +1,14 @@
+warning: use of deprecated item 'lint_output_format::foo': text
+  --> $DIR/lint-output-format-2.rs:7:26
+   |
+LL | use lint_output_format::{foo, bar};
+   |                          ^^^
+   |
+   = note: #[warn(deprecated)] on by default
+
+warning: use of deprecated item 'lint_output_format::foo': text
+  --> $DIR/lint-output-format-2.rs:12:14
+   |
+LL |     let _x = foo();
+   |              ^^^
+
diff --git a/src/test/ui/lint/lint-output-format.rs b/src/test/ui/lint/lint-output-format.rs
new file mode 100644
index 0000000..169a98c
--- /dev/null
+++ b/src/test/ui/lint/lint-output-format.rs
@@ -0,0 +1,12 @@
+// compile-flags: -F unused_features
+// aux-build:lint_output_format.rs
+
+#![allow(deprecated)]
+
+extern crate lint_output_format; //~ ERROR use of unstable library feature
+use lint_output_format::{foo, bar}; //~ ERROR use of unstable library feature
+
+fn main() {
+    let _x = foo();
+    let _y = bar(); //~ ERROR use of unstable library feature
+}
diff --git a/src/test/ui/lint/lint-output-format.stderr b/src/test/ui/lint/lint-output-format.stderr
new file mode 100644
index 0000000..21b1230
--- /dev/null
+++ b/src/test/ui/lint/lint-output-format.stderr
@@ -0,0 +1,27 @@
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-output-format.rs:6:1
+   |
+LL | extern crate lint_output_format;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-output-format.rs:7:31
+   |
+LL | use lint_output_format::{foo, bar};
+   |                               ^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-output-format.rs:11:14
+   |
+LL |     let _y = bar();
+   |              ^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/lint/lint-owned-heap-memory.rs b/src/test/ui/lint/lint-owned-heap-memory.rs
new file mode 100644
index 0000000..7ef18c2
--- /dev/null
+++ b/src/test/ui/lint/lint-owned-heap-memory.rs
@@ -0,0 +1,12 @@
+#![allow(dead_code)]
+#![forbid(box_pointers)]
+#![feature(box_syntax)]
+
+struct Foo {
+    x: Box<isize> //~ ERROR type uses owned
+}
+
+fn main() {
+    let _x : Foo = Foo {x : box 10};
+    //~^ ERROR type uses owned
+}
diff --git a/src/test/ui/lint/lint-owned-heap-memory.stderr b/src/test/ui/lint/lint-owned-heap-memory.stderr
new file mode 100644
index 0000000..c61b3d3
--- /dev/null
+++ b/src/test/ui/lint/lint-owned-heap-memory.stderr
@@ -0,0 +1,20 @@
+error: type uses owned (Box type) pointers: std::boxed::Box<isize>
+  --> $DIR/lint-owned-heap-memory.rs:6:5
+   |
+LL |     x: Box<isize>
+   |     ^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/lint-owned-heap-memory.rs:2:11
+   |
+LL | #![forbid(box_pointers)]
+   |           ^^^^^^^^^^^^
+
+error: type uses owned (Box type) pointers: std::boxed::Box<isize>
+  --> $DIR/lint-owned-heap-memory.rs:10:29
+   |
+LL |     let _x : Foo = Foo {x : box 10};
+   |                             ^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/lint/lint-qualification.rs b/src/test/ui/lint/lint-qualification.rs
new file mode 100644
index 0000000..2aa4526
--- /dev/null
+++ b/src/test/ui/lint/lint-qualification.rs
@@ -0,0 +1,19 @@
+#![deny(unused_qualifications)]
+
+mod foo {
+    pub fn bar() {}
+}
+
+fn main() {
+    use foo::bar;
+    foo::bar(); //~ ERROR: unnecessary qualification
+    bar();
+
+    let _ = || -> Result<(), ()> { try!(Ok(())); Ok(()) }; // issue #37345
+
+    macro_rules! m { () => {
+        $crate::foo::bar(); // issue #37357
+        ::foo::bar(); // issue #38682
+    } }
+    m!();
+}
diff --git a/src/test/ui/lint/lint-qualification.stderr b/src/test/ui/lint/lint-qualification.stderr
new file mode 100644
index 0000000..78f7e32
--- /dev/null
+++ b/src/test/ui/lint/lint-qualification.stderr
@@ -0,0 +1,14 @@
+error: unnecessary qualification
+  --> $DIR/lint-qualification.rs:9:5
+   |
+LL |     foo::bar();
+   |     ^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/lint-qualification.rs:1:9
+   |
+LL | #![deny(unused_qualifications)]
+   |         ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lint/lint-removed-allow.rs b/src/test/ui/lint/lint-removed-allow.rs
new file mode 100644
index 0000000..30ba4f0
--- /dev/null
+++ b/src/test/ui/lint/lint-removed-allow.rs
@@ -0,0 +1,8 @@
+// No warnings about removed lint when
+// allow(renamed_and_removed_lints)
+
+#![allow(renamed_and_removed_lints)]
+
+#[deny(raw_pointer_derive)]
+#[deny(unused_variables)]
+fn main() { let unused = (); } //~ ERROR unused
diff --git a/src/test/ui/lint/lint-removed-allow.stderr b/src/test/ui/lint/lint-removed-allow.stderr
new file mode 100644
index 0000000..32af738
--- /dev/null
+++ b/src/test/ui/lint/lint-removed-allow.stderr
@@ -0,0 +1,14 @@
+error: unused variable: `unused`
+  --> $DIR/lint-removed-allow.rs:8:17
+   |
+LL | fn main() { let unused = (); }
+   |                 ^^^^^^ help: consider prefixing with an underscore: `_unused`
+   |
+note: lint level defined here
+  --> $DIR/lint-removed-allow.rs:7:8
+   |
+LL | #[deny(unused_variables)]
+   |        ^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lint/lint-removed-cmdline.rs b/src/test/ui/lint/lint-removed-cmdline.rs
new file mode 100644
index 0000000..462beab
--- /dev/null
+++ b/src/test/ui/lint/lint-removed-cmdline.rs
@@ -0,0 +1,12 @@
+// The raw_pointer_derived lint warns about its removal
+// cc #30346
+
+// compile-flags:-D raw_pointer_derive
+
+// error-pattern:lint `raw_pointer_derive` has been removed
+// error-pattern:requested on the command line with `-D raw_pointer_derive`
+
+#![warn(unused)]
+
+#[deny(warnings)]
+fn main() { let unused = (); }
diff --git a/src/test/ui/lint/lint-removed-cmdline.stderr b/src/test/ui/lint/lint-removed-cmdline.stderr
new file mode 100644
index 0000000..d46ef6b
--- /dev/null
+++ b/src/test/ui/lint/lint-removed-cmdline.stderr
@@ -0,0 +1,19 @@
+warning: lint `raw_pointer_derive` has been removed: `using derive with raw pointers is ok`
+   |
+   = note: requested on the command line with `-D raw_pointer_derive`
+
+error: unused variable: `unused`
+  --> $DIR/lint-removed-cmdline.rs:12:17
+   |
+LL | fn main() { let unused = (); }
+   |                 ^^^^^^ help: consider prefixing with an underscore: `_unused`
+   |
+note: lint level defined here
+  --> $DIR/lint-removed-cmdline.rs:11:8
+   |
+LL | #[deny(warnings)]
+   |        ^^^^^^^^
+   = note: #[deny(unused_variables)] implied by #[deny(warnings)]
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lint/lint-removed.rs b/src/test/ui/lint/lint-removed.rs
new file mode 100644
index 0000000..92f4372
--- /dev/null
+++ b/src/test/ui/lint/lint-removed.rs
@@ -0,0 +1,8 @@
+// The raw_pointer_derived lint was removed, but is now reported by
+// the renamed_and_removed_lints lint, which means it's a warning by
+// default, and allowed in cargo dependency builds.
+// cc #30346
+
+#[deny(raw_pointer_derive)] //~ WARN `raw_pointer_derive` has been removed
+#[deny(unused_variables)]
+fn main() { let unused = (); } //~ ERROR unused
diff --git a/src/test/ui/lint/lint-removed.stderr b/src/test/ui/lint/lint-removed.stderr
new file mode 100644
index 0000000..cde494f
--- /dev/null
+++ b/src/test/ui/lint/lint-removed.stderr
@@ -0,0 +1,22 @@
+warning: lint `raw_pointer_derive` has been removed: `using derive with raw pointers is ok`
+  --> $DIR/lint-removed.rs:6:8
+   |
+LL | #[deny(raw_pointer_derive)]
+   |        ^^^^^^^^^^^^^^^^^^
+   |
+   = note: #[warn(renamed_and_removed_lints)] on by default
+
+error: unused variable: `unused`
+  --> $DIR/lint-removed.rs:8:17
+   |
+LL | fn main() { let unused = (); }
+   |                 ^^^^^^ help: consider prefixing with an underscore: `_unused`
+   |
+note: lint level defined here
+  --> $DIR/lint-removed.rs:7:8
+   |
+LL | #[deny(unused_variables)]
+   |        ^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lint/lint-renamed-allow.rs b/src/test/ui/lint/lint-renamed-allow.rs
new file mode 100644
index 0000000..9cf6f32
--- /dev/null
+++ b/src/test/ui/lint/lint-renamed-allow.rs
@@ -0,0 +1,8 @@
+// No warnings about renamed lint when
+// allow(renamed_and_removed_lints)
+
+#![allow(renamed_and_removed_lints)]
+
+#[deny(single_use_lifetime)]
+#[deny(unused)]
+fn main() { let unused = (); } //~ ERROR unused
diff --git a/src/test/ui/lint/lint-renamed-allow.stderr b/src/test/ui/lint/lint-renamed-allow.stderr
new file mode 100644
index 0000000..383a800
--- /dev/null
+++ b/src/test/ui/lint/lint-renamed-allow.stderr
@@ -0,0 +1,15 @@
+error: unused variable: `unused`
+  --> $DIR/lint-renamed-allow.rs:8:17
+   |
+LL | fn main() { let unused = (); }
+   |                 ^^^^^^ help: consider prefixing with an underscore: `_unused`
+   |
+note: lint level defined here
+  --> $DIR/lint-renamed-allow.rs:7:8
+   |
+LL | #[deny(unused)]
+   |        ^^^^^^
+   = note: #[deny(unused_variables)] implied by #[deny(unused)]
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lint/lint-renamed-cmdline.rs b/src/test/ui/lint/lint-renamed-cmdline.rs
new file mode 100644
index 0000000..c873771
--- /dev/null
+++ b/src/test/ui/lint/lint-renamed-cmdline.rs
@@ -0,0 +1,8 @@
+// compile-flags:-D bare_trait_object
+
+// error-pattern:lint `bare_trait_object` has been renamed to `bare_trait_objects`
+// error-pattern:requested on the command line with `-D bare_trait_object`
+// error-pattern:unused
+
+#[deny(unused)]
+fn main() { let unused = (); }
diff --git a/src/test/ui/lint/lint-renamed-cmdline.stderr b/src/test/ui/lint/lint-renamed-cmdline.stderr
new file mode 100644
index 0000000..6247ee0
--- /dev/null
+++ b/src/test/ui/lint/lint-renamed-cmdline.stderr
@@ -0,0 +1,19 @@
+warning: lint `bare_trait_object` has been renamed to `bare_trait_objects`
+   |
+   = note: requested on the command line with `-D bare_trait_object`
+
+error: unused variable: `unused`
+  --> $DIR/lint-renamed-cmdline.rs:8:17
+   |
+LL | fn main() { let unused = (); }
+   |                 ^^^^^^ help: consider prefixing with an underscore: `_unused`
+   |
+note: lint level defined here
+  --> $DIR/lint-renamed-cmdline.rs:7:8
+   |
+LL | #[deny(unused)]
+   |        ^^^^^^
+   = note: #[deny(unused_variables)] implied by #[deny(unused)]
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lint/lint-renamed.rs b/src/test/ui/lint/lint-renamed.rs
new file mode 100644
index 0000000..ca32994
--- /dev/null
+++ b/src/test/ui/lint/lint-renamed.rs
@@ -0,0 +1,4 @@
+#[deny(bare_trait_object)]
+//~^ WARN lint `bare_trait_object` has been renamed to `bare_trait_objects`
+#[deny(unused)]
+fn main() { let unused = (); } //~ ERROR unused
diff --git a/src/test/ui/lint/lint-renamed.stderr b/src/test/ui/lint/lint-renamed.stderr
new file mode 100644
index 0000000..2174b22
--- /dev/null
+++ b/src/test/ui/lint/lint-renamed.stderr
@@ -0,0 +1,23 @@
+warning: lint `bare_trait_object` has been renamed to `bare_trait_objects`
+  --> $DIR/lint-renamed.rs:1:8
+   |
+LL | #[deny(bare_trait_object)]
+   |        ^^^^^^^^^^^^^^^^^ help: use the new name: `bare_trait_objects`
+   |
+   = note: #[warn(renamed_and_removed_lints)] on by default
+
+error: unused variable: `unused`
+  --> $DIR/lint-renamed.rs:4:17
+   |
+LL | fn main() { let unused = (); }
+   |                 ^^^^^^ help: consider prefixing with an underscore: `_unused`
+   |
+note: lint level defined here
+  --> $DIR/lint-renamed.rs:3:8
+   |
+LL | #[deny(unused)]
+   |        ^^^^^^
+   = note: #[deny(unused_variables)] implied by #[deny(unused)]
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lint/lint-shorthand-field.rs b/src/test/ui/lint/lint-shorthand-field.rs
new file mode 100644
index 0000000..5e756d1
--- /dev/null
+++ b/src/test/ui/lint/lint-shorthand-field.rs
@@ -0,0 +1,54 @@
+#![allow(nonstandard_style, unused_variables)]
+#![deny(non_shorthand_field_patterns)]
+
+struct Foo {
+    x: isize,
+    y: isize,
+}
+
+fn main() {
+    {
+        let Foo {
+            x: x, //~ ERROR the `x:` in this pattern is redundant
+            y: ref y, //~ ERROR the `y:` in this pattern is redundant
+        } = Foo { x: 0, y: 0 };
+
+        let Foo {
+            x,
+            ref y,
+        } = Foo { x: 0, y: 0 };
+    }
+
+    {
+        const x: isize = 1;
+
+        match (Foo { x: 1, y: 1 }) {
+            Foo { x: x, ..} => {},
+            _ => {},
+        }
+    }
+
+    {
+        struct Bar {
+            x: x,
+        }
+
+        struct x;
+
+        match (Bar { x: x }) {
+            Bar { x: x } => {},
+        }
+    }
+
+    {
+        struct Bar {
+            x: Foo,
+        }
+
+        enum Foo { x }
+
+        match (Bar { x: Foo::x }) {
+            Bar { x: Foo::x } => {},
+        }
+    }
+}
diff --git a/src/test/ui/lint/lint-shorthand-field.stderr b/src/test/ui/lint/lint-shorthand-field.stderr
new file mode 100644
index 0000000..366ab55
--- /dev/null
+++ b/src/test/ui/lint/lint-shorthand-field.stderr
@@ -0,0 +1,24 @@
+error: the `x:` in this pattern is redundant
+  --> $DIR/lint-shorthand-field.rs:12:13
+   |
+LL |             x: x,
+   |             --^^
+   |             |
+   |             help: remove this
+   |
+note: lint level defined here
+  --> $DIR/lint-shorthand-field.rs:2:9
+   |
+LL | #![deny(non_shorthand_field_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: the `y:` in this pattern is redundant
+  --> $DIR/lint-shorthand-field.rs:13:13
+   |
+LL |             y: ref y,
+   |             --^^^^^^
+   |             |
+   |             help: remove this
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/lint/lint-stability-2.rs b/src/test/ui/lint/lint-stability-2.rs
new file mode 100644
index 0000000..12e7b08
--- /dev/null
+++ b/src/test/ui/lint/lint-stability-2.rs
@@ -0,0 +1,413 @@
+// aux-build:lint_stability.rs
+// aux-build:stability_cfg1.rs
+
+#![allow(deprecated)]
+#![allow(dead_code)]
+#![feature(staged_api)]
+
+#![stable(feature = "rust1", since = "1.0.0")]
+
+#[macro_use]
+extern crate lint_stability;
+
+mod cross_crate {
+    extern crate stability_cfg1;
+
+    use lint_stability::*;
+
+    fn test() {
+        type Foo = MethodTester;
+        let foo = MethodTester;
+
+        deprecated();
+        foo.method_deprecated();
+        Foo::method_deprecated(&foo);
+        <Foo>::method_deprecated(&foo);
+        foo.trait_deprecated();
+        Trait::trait_deprecated(&foo);
+        <Foo>::trait_deprecated(&foo);
+        <Foo as Trait>::trait_deprecated(&foo);
+
+        deprecated_text();
+        foo.method_deprecated_text();
+        Foo::method_deprecated_text(&foo);
+        <Foo>::method_deprecated_text(&foo);
+        foo.trait_deprecated_text();
+        Trait::trait_deprecated_text(&foo);
+        <Foo>::trait_deprecated_text(&foo);
+        <Foo as Trait>::trait_deprecated_text(&foo);
+
+        foo.method_deprecated_unstable();
+        //~^ ERROR use of unstable library feature
+        Foo::method_deprecated_unstable(&foo);
+        //~^ ERROR use of unstable library feature
+        <Foo>::method_deprecated_unstable(&foo);
+        //~^ ERROR use of unstable library feature
+        foo.trait_deprecated_unstable();
+        //~^ ERROR use of unstable library feature
+        <Foo>::trait_deprecated_unstable(&foo);
+        //~^ ERROR use of unstable library feature
+
+        foo.method_deprecated_unstable_text();
+        //~^ ERROR use of unstable library feature
+        Foo::method_deprecated_unstable_text(&foo);
+        //~^ ERROR use of unstable library feature
+        <Foo>::method_deprecated_unstable_text(&foo);
+        //~^ ERROR use of unstable library feature
+        foo.trait_deprecated_unstable_text();
+        //~^ ERROR use of unstable library feature
+        <Foo>::trait_deprecated_unstable_text(&foo);
+        //~^ ERROR use of unstable library feature
+
+        foo.method_unstable(); //~ ERROR use of unstable library feature
+        Foo::method_unstable(&foo); //~ ERROR use of unstable library feature
+        <Foo>::method_unstable(&foo); //~ ERROR use of unstable library feature
+        foo.trait_unstable(); //~ ERROR use of unstable library feature
+        <Foo>::trait_unstable(&foo); //~ ERROR use of unstable library feature
+
+        foo.method_unstable_text();
+        //~^ ERROR use of unstable library feature 'unstable_test_feature': text
+        Foo::method_unstable_text(&foo);
+        //~^ ERROR use of unstable library feature 'unstable_test_feature': text
+        <Foo>::method_unstable_text(&foo);
+        //~^ ERROR use of unstable library feature 'unstable_test_feature': text
+        foo.trait_unstable_text();
+        //~^ ERROR use of unstable library feature 'unstable_test_feature': text
+        <Foo>::trait_unstable_text(&foo);
+        //~^ ERROR use of unstable library feature 'unstable_test_feature': text
+
+        stable();
+        foo.method_stable();
+        Foo::method_stable(&foo);
+        <Foo>::method_stable(&foo);
+        foo.trait_stable();
+        Trait::trait_stable(&foo);
+        <Foo>::trait_stable(&foo);
+        <Foo as Trait>::trait_stable(&foo);
+
+        stable_text();
+        foo.method_stable_text();
+        Foo::method_stable_text(&foo);
+        <Foo>::method_stable_text(&foo);
+        foo.trait_stable_text();
+        Trait::trait_stable_text(&foo);
+        <Foo>::trait_stable_text(&foo);
+        <Foo as Trait>::trait_stable_text(&foo);
+
+        struct S2<T: TraitWithAssociatedTypes>(T::TypeDeprecated);
+
+        let _ = DeprecatedStruct {
+            i: 0
+        };
+        let _ = StableStruct { i: 0 };
+
+        let _ = DeprecatedUnitStruct;
+        let _ = StableUnitStruct;
+
+        let _ = Enum::DeprecatedVariant;
+        let _ = Enum::StableVariant;
+
+        let _ = DeprecatedTupleStruct (1);
+        let _ = StableTupleStruct (1);
+
+        // At the moment, the lint checker only checks stability in
+        // in the arguments of macros.
+        // Eventually, we will want to lint the contents of the
+        // macro in the module *defining* it. Also, stability levels
+        // on macros themselves are not yet linted.
+        macro_test_arg!(deprecated_text());
+        macro_test_arg!(macro_test_arg!(deprecated_text()));
+    }
+
+    fn test_method_param<Foo: Trait>(foo: Foo) {
+        foo.trait_deprecated();
+        Trait::trait_deprecated(&foo);
+        <Foo>::trait_deprecated(&foo);
+        <Foo as Trait>::trait_deprecated(&foo);
+        foo.trait_deprecated_text();
+        Trait::trait_deprecated_text(&foo);
+        <Foo>::trait_deprecated_text(&foo);
+        <Foo as Trait>::trait_deprecated_text(&foo);
+        foo.trait_deprecated_unstable();
+        //~^ ERROR use of unstable library feature
+        <Foo>::trait_deprecated_unstable(&foo);
+        //~^ ERROR use of unstable library feature
+        foo.trait_deprecated_unstable_text();
+        //~^ ERROR use of unstable library feature
+        <Foo>::trait_deprecated_unstable_text(&foo);
+        //~^ ERROR use of unstable library feature
+        foo.trait_unstable(); //~ ERROR use of unstable library feature
+        <Foo>::trait_unstable(&foo); //~ ERROR use of unstable library feature
+        foo.trait_unstable_text();
+        //~^ ERROR use of unstable library feature 'unstable_test_feature': text
+        <Foo>::trait_unstable_text(&foo);
+        //~^ ERROR use of unstable library feature 'unstable_test_feature': text
+        foo.trait_stable();
+        Trait::trait_stable(&foo);
+        <Foo>::trait_stable(&foo);
+        <Foo as Trait>::trait_stable(&foo);
+    }
+
+    fn test_method_object(foo: &Trait) {
+        foo.trait_deprecated();
+        foo.trait_deprecated_text();
+        foo.trait_deprecated_unstable();
+        //~^ ERROR use of unstable library feature
+        foo.trait_deprecated_unstable_text();
+        //~^ ERROR use of unstable library feature
+        foo.trait_unstable(); //~ ERROR use of unstable library feature
+        foo.trait_unstable_text();
+        //~^ ERROR use of unstable library feature 'unstable_test_feature': text
+        foo.trait_stable();
+    }
+
+    struct S;
+
+    impl DeprecatedTrait for S {}
+    trait LocalTrait2 : DeprecatedTrait { }
+}
+
+mod this_crate {
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    pub fn deprecated() {}
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    pub fn deprecated_text() {}
+
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    pub fn unstable() {}
+    #[unstable(feature = "unstable_test_feature", reason = "text", issue = "0")]
+    pub fn unstable_text() {}
+
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn stable() {}
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn stable_text() {}
+
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub struct MethodTester;
+
+    impl MethodTester {
+        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        #[rustc_deprecated(since = "1.0.0", reason = "text")]
+        pub fn method_deprecated(&self) {}
+        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        #[rustc_deprecated(since = "1.0.0", reason = "text")]
+        pub fn method_deprecated_text(&self) {}
+
+        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        pub fn method_unstable(&self) {}
+        #[unstable(feature = "unstable_test_feature", reason = "text", issue = "0")]
+        pub fn method_unstable_text(&self) {}
+
+        #[stable(feature = "rust1", since = "1.0.0")]
+        pub fn method_stable(&self) {}
+        #[stable(feature = "rust1", since = "1.0.0")]
+        pub fn method_stable_text(&self) {}
+    }
+
+    pub trait Trait {
+        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        #[rustc_deprecated(since = "1.0.0", reason = "text")]
+        fn trait_deprecated(&self) {}
+        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        #[rustc_deprecated(since = "1.0.0", reason = "text")]
+        fn trait_deprecated_text(&self) {}
+
+        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        fn trait_unstable(&self) {}
+        #[unstable(feature = "unstable_test_feature", reason = "text", issue = "0")]
+        fn trait_unstable_text(&self) {}
+
+        #[stable(feature = "rust1", since = "1.0.0")]
+        fn trait_stable(&self) {}
+        #[stable(feature = "rust1", since = "1.0.0")]
+        fn trait_stable_text(&self) {}
+    }
+
+    impl Trait for MethodTester {}
+
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    pub struct DeprecatedStruct {
+        #[stable(feature = "stable_test_feature", since = "1.0.0")] i: isize
+    }
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    pub struct UnstableStruct {
+        #[stable(feature = "stable_test_feature", since = "1.0.0")] i: isize
+    }
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub struct StableStruct {
+        #[stable(feature = "stable_test_feature", since = "1.0.0")] i: isize
+    }
+
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    pub struct DeprecatedUnitStruct;
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    pub struct UnstableUnitStruct;
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub struct StableUnitStruct;
+
+    pub enum Enum {
+        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        #[rustc_deprecated(since = "1.0.0", reason = "text")]
+        DeprecatedVariant,
+        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        UnstableVariant,
+
+        #[stable(feature = "rust1", since = "1.0.0")]
+        StableVariant,
+    }
+
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    pub struct DeprecatedTupleStruct(isize);
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    pub struct UnstableTupleStruct(isize);
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub struct StableTupleStruct(isize);
+
+    fn test() {
+        // Only the deprecated cases of the following should generate
+        // errors, because other stability attributes now have meaning
+        // only *across* crates, not within a single crate.
+
+        type Foo = MethodTester;
+        let foo = MethodTester;
+
+        deprecated();
+        foo.method_deprecated();
+        Foo::method_deprecated(&foo);
+        <Foo>::method_deprecated(&foo);
+        foo.trait_deprecated();
+        Trait::trait_deprecated(&foo);
+        <Foo>::trait_deprecated(&foo);
+        <Foo as Trait>::trait_deprecated(&foo);
+
+        deprecated_text();
+        foo.method_deprecated_text();
+        Foo::method_deprecated_text(&foo);
+        <Foo>::method_deprecated_text(&foo);
+        foo.trait_deprecated_text();
+        Trait::trait_deprecated_text(&foo);
+        <Foo>::trait_deprecated_text(&foo);
+        <Foo as Trait>::trait_deprecated_text(&foo);
+
+        unstable();
+        foo.method_unstable();
+        Foo::method_unstable(&foo);
+        <Foo>::method_unstable(&foo);
+        foo.trait_unstable();
+        Trait::trait_unstable(&foo);
+        <Foo>::trait_unstable(&foo);
+        <Foo as Trait>::trait_unstable(&foo);
+
+        unstable_text();
+        foo.method_unstable_text();
+        Foo::method_unstable_text(&foo);
+        <Foo>::method_unstable_text(&foo);
+        foo.trait_unstable_text();
+        Trait::trait_unstable_text(&foo);
+        <Foo>::trait_unstable_text(&foo);
+        <Foo as Trait>::trait_unstable_text(&foo);
+
+        stable();
+        foo.method_stable();
+        Foo::method_stable(&foo);
+        <Foo>::method_stable(&foo);
+        foo.trait_stable();
+        Trait::trait_stable(&foo);
+        <Foo>::trait_stable(&foo);
+        <Foo as Trait>::trait_stable(&foo);
+
+        stable_text();
+        foo.method_stable_text();
+        Foo::method_stable_text(&foo);
+        <Foo>::method_stable_text(&foo);
+        foo.trait_stable_text();
+        Trait::trait_stable_text(&foo);
+        <Foo>::trait_stable_text(&foo);
+        <Foo as Trait>::trait_stable_text(&foo);
+
+        let _ = DeprecatedStruct {
+            i: 0
+        };
+        let _ = UnstableStruct { i: 0 };
+        let _ = StableStruct { i: 0 };
+
+        let _ = DeprecatedUnitStruct;
+        let _ = UnstableUnitStruct;
+        let _ = StableUnitStruct;
+
+        let _ = Enum::DeprecatedVariant;
+        let _ = Enum::UnstableVariant;
+        let _ = Enum::StableVariant;
+
+        let _ = DeprecatedTupleStruct (1);
+        let _ = UnstableTupleStruct (1);
+        let _ = StableTupleStruct (1);
+    }
+
+    fn test_method_param<Foo: Trait>(foo: Foo) {
+        foo.trait_deprecated();
+        Trait::trait_deprecated(&foo);
+        <Foo>::trait_deprecated(&foo);
+        <Foo as Trait>::trait_deprecated(&foo);
+        foo.trait_deprecated_text();
+        Trait::trait_deprecated_text(&foo);
+        <Foo>::trait_deprecated_text(&foo);
+        <Foo as Trait>::trait_deprecated_text(&foo);
+        foo.trait_unstable();
+        Trait::trait_unstable(&foo);
+        <Foo>::trait_unstable(&foo);
+        <Foo as Trait>::trait_unstable(&foo);
+        foo.trait_unstable_text();
+        Trait::trait_unstable_text(&foo);
+        <Foo>::trait_unstable_text(&foo);
+        <Foo as Trait>::trait_unstable_text(&foo);
+        foo.trait_stable();
+        Trait::trait_stable(&foo);
+        <Foo>::trait_stable(&foo);
+        <Foo as Trait>::trait_stable(&foo);
+    }
+
+    fn test_method_object(foo: &Trait) {
+        foo.trait_deprecated();
+        foo.trait_deprecated_text();
+        foo.trait_unstable();
+        foo.trait_unstable_text();
+        foo.trait_stable();
+    }
+
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    fn test_fn_body() {
+        fn fn_in_body() {}
+        fn_in_body();
+    }
+
+    impl MethodTester {
+        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        #[rustc_deprecated(since = "1.0.0", reason = "text")]
+        fn test_method_body(&self) {
+            fn fn_in_body() {}
+            fn_in_body();
+        }
+    }
+
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    pub trait DeprecatedTrait {
+        fn dummy(&self) { }
+    }
+
+    struct S;
+
+    impl DeprecatedTrait for S { }
+
+    trait LocalTrait : DeprecatedTrait { }
+}
+
+fn main() {}
diff --git a/src/test/ui/lint/lint-stability-2.stderr b/src/test/ui/lint/lint-stability-2.stderr
new file mode 100644
index 0000000..808c16c
--- /dev/null
+++ b/src/test/ui/lint/lint-stability-2.stderr
@@ -0,0 +1,259 @@
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-2.rs:40:13
+   |
+LL |         foo.method_deprecated_unstable();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-2.rs:42:9
+   |
+LL |         Foo::method_deprecated_unstable(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-2.rs:44:9
+   |
+LL |         <Foo>::method_deprecated_unstable(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-2.rs:46:13
+   |
+LL |         foo.trait_deprecated_unstable();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-2.rs:48:9
+   |
+LL |         <Foo>::trait_deprecated_unstable(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-2.rs:51:13
+   |
+LL |         foo.method_deprecated_unstable_text();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-2.rs:53:9
+   |
+LL |         Foo::method_deprecated_unstable_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-2.rs:55:9
+   |
+LL |         <Foo>::method_deprecated_unstable_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-2.rs:57:13
+   |
+LL |         foo.trait_deprecated_unstable_text();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-2.rs:59:9
+   |
+LL |         <Foo>::trait_deprecated_unstable_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-2.rs:62:13
+   |
+LL |         foo.method_unstable();
+   |             ^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-2.rs:63:9
+   |
+LL |         Foo::method_unstable(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-2.rs:64:9
+   |
+LL |         <Foo>::method_unstable(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-2.rs:65:13
+   |
+LL |         foo.trait_unstable();
+   |             ^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-2.rs:66:9
+   |
+LL |         <Foo>::trait_unstable(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature': text
+  --> $DIR/lint-stability-2.rs:68:13
+   |
+LL |         foo.method_unstable_text();
+   |             ^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature': text
+  --> $DIR/lint-stability-2.rs:70:9
+   |
+LL |         Foo::method_unstable_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature': text
+  --> $DIR/lint-stability-2.rs:72:9
+   |
+LL |         <Foo>::method_unstable_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature': text
+  --> $DIR/lint-stability-2.rs:74:13
+   |
+LL |         foo.trait_unstable_text();
+   |             ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature': text
+  --> $DIR/lint-stability-2.rs:76:9
+   |
+LL |         <Foo>::trait_unstable_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-2.rs:131:13
+   |
+LL |         foo.trait_deprecated_unstable();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-2.rs:133:9
+   |
+LL |         <Foo>::trait_deprecated_unstable(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-2.rs:135:13
+   |
+LL |         foo.trait_deprecated_unstable_text();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-2.rs:137:9
+   |
+LL |         <Foo>::trait_deprecated_unstable_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-2.rs:139:13
+   |
+LL |         foo.trait_unstable();
+   |             ^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-2.rs:140:9
+   |
+LL |         <Foo>::trait_unstable(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature': text
+  --> $DIR/lint-stability-2.rs:141:13
+   |
+LL |         foo.trait_unstable_text();
+   |             ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature': text
+  --> $DIR/lint-stability-2.rs:143:9
+   |
+LL |         <Foo>::trait_unstable_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-2.rs:154:13
+   |
+LL |         foo.trait_deprecated_unstable();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-2.rs:156:13
+   |
+LL |         foo.trait_deprecated_unstable_text();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-2.rs:158:13
+   |
+LL |         foo.trait_unstable();
+   |             ^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature': text
+  --> $DIR/lint-stability-2.rs:159:13
+   |
+LL |         foo.trait_unstable_text();
+   |             ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error: aborting due to 32 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/lint/lint-stability-deprecated.rs b/src/test/ui/lint/lint-stability-deprecated.rs
new file mode 100644
index 0000000..bf574d7
--- /dev/null
+++ b/src/test/ui/lint/lint-stability-deprecated.rs
@@ -0,0 +1,463 @@
+// compile-pass
+// aux-build:lint_stability.rs
+// aux-build:inherited_stability.rs
+// aux-build:stability_cfg1.rs
+// aux-build:stability-cfg2.rs
+// ignore-tidy-linelength
+#![warn(deprecated)]
+#![allow(dead_code, unused_extern_crates)]
+#![feature(staged_api, unstable_test_feature)]
+
+#![stable(feature = "rust1", since = "1.0.0")]
+
+#[macro_use]
+extern crate lint_stability;
+
+mod cross_crate {
+    extern crate stability_cfg1;
+    extern crate stability_cfg2;
+
+    use lint_stability::*;
+
+    fn test() {
+        type Foo = MethodTester;
+        let foo = MethodTester;
+
+        deprecated(); //~ WARN use of deprecated item 'lint_stability::deprecated'
+        foo.method_deprecated(); //~ WARN use of deprecated item 'lint_stability::MethodTester::method_deprecated'
+        Foo::method_deprecated(&foo); //~ WARN use of deprecated item 'lint_stability::MethodTester::method_deprecated'
+        <Foo>::method_deprecated(&foo); //~ WARN use of deprecated item 'lint_stability::MethodTester::method_deprecated'
+        foo.trait_deprecated(); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated'
+        Trait::trait_deprecated(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated'
+        <Foo>::trait_deprecated(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated'
+        <Foo as Trait>::trait_deprecated(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated'
+
+        deprecated_text(); //~ WARN use of deprecated item 'lint_stability::deprecated_text': text
+        foo.method_deprecated_text(); //~ WARN use of deprecated item 'lint_stability::MethodTester::method_deprecated_text': text
+        Foo::method_deprecated_text(&foo); //~ WARN use of deprecated item 'lint_stability::MethodTester::method_deprecated_text': text
+        <Foo>::method_deprecated_text(&foo); //~ WARN use of deprecated item 'lint_stability::MethodTester::method_deprecated_text': text
+        foo.trait_deprecated_text(); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
+        Trait::trait_deprecated_text(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
+        <Foo>::trait_deprecated_text(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
+        <Foo as Trait>::trait_deprecated_text(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
+
+        deprecated_unstable(); //~ WARN use of deprecated item 'lint_stability::deprecated_unstable'
+        foo.method_deprecated_unstable(); //~ WARN use of deprecated item 'lint_stability::MethodTester::method_deprecated_unstable'
+        Foo::method_deprecated_unstable(&foo); //~ WARN use of deprecated item 'lint_stability::MethodTester::method_deprecated_unstable'
+        <Foo>::method_deprecated_unstable(&foo); //~ WARN use of deprecated item 'lint_stability::MethodTester::method_deprecated_unstable'
+        foo.trait_deprecated_unstable(); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable'
+        Trait::trait_deprecated_unstable(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable'
+        <Foo>::trait_deprecated_unstable(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable'
+        <Foo as Trait>::trait_deprecated_unstable(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable'
+
+        deprecated_unstable_text(); //~ WARN use of deprecated item 'lint_stability::deprecated_unstable_text': text
+        foo.method_deprecated_unstable_text(); //~ WARN use of deprecated item 'lint_stability::MethodTester::method_deprecated_unstable_text': text
+        Foo::method_deprecated_unstable_text(&foo); //~ WARN use of deprecated item 'lint_stability::MethodTester::method_deprecated_unstable_text': text
+        <Foo>::method_deprecated_unstable_text(&foo); //~ WARN use of deprecated item 'lint_stability::MethodTester::method_deprecated_unstable_text': text
+        foo.trait_deprecated_unstable_text(); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
+        Trait::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
+        <Foo>::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
+        <Foo as Trait>::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
+
+        unstable();
+        foo.method_unstable();
+        Foo::method_unstable(&foo);
+        <Foo>::method_unstable(&foo);
+        foo.trait_unstable();
+        Trait::trait_unstable(&foo);
+        <Foo>::trait_unstable(&foo);
+        <Foo as Trait>::trait_unstable(&foo);
+
+        unstable_text();
+        foo.method_unstable_text();
+        Foo::method_unstable_text(&foo);
+        <Foo>::method_unstable_text(&foo);
+        foo.trait_unstable_text();
+        Trait::trait_unstable_text(&foo);
+        <Foo>::trait_unstable_text(&foo);
+        <Foo as Trait>::trait_unstable_text(&foo);
+
+        stable();
+        foo.method_stable();
+        Foo::method_stable(&foo);
+        <Foo>::method_stable(&foo);
+        foo.trait_stable();
+        Trait::trait_stable(&foo);
+        <Foo>::trait_stable(&foo);
+        <Foo as Trait>::trait_stable(&foo);
+
+        stable_text();
+        foo.method_stable_text();
+        Foo::method_stable_text(&foo);
+        <Foo>::method_stable_text(&foo);
+        foo.trait_stable_text();
+        Trait::trait_stable_text(&foo);
+        <Foo>::trait_stable_text(&foo);
+        <Foo as Trait>::trait_stable_text(&foo);
+
+        struct S1<T: TraitWithAssociatedTypes>(T::TypeUnstable);
+        struct S2<T: TraitWithAssociatedTypes>(T::TypeDeprecated);
+        //~^ WARN use of deprecated item 'lint_stability::TraitWithAssociatedTypes::TypeDeprecated': text
+        type A = TraitWithAssociatedTypes<
+            TypeUnstable = u8,
+            TypeDeprecated = u16,
+            //~^ WARN use of deprecated item 'lint_stability::TraitWithAssociatedTypes::TypeDeprecated'
+        >;
+
+        let _ = DeprecatedStruct { //~ WARN use of deprecated item 'lint_stability::DeprecatedStruct'
+            i: 0 //~ WARN use of deprecated item 'lint_stability::DeprecatedStruct::i'
+        };
+        let _ = DeprecatedUnstableStruct {
+            //~^ WARN use of deprecated item 'lint_stability::DeprecatedUnstableStruct'
+            i: 0 //~ WARN use of deprecated item 'lint_stability::DeprecatedUnstableStruct::i'
+        };
+        let _ = UnstableStruct { i: 0 };
+        let _ = StableStruct { i: 0 };
+
+        let _ = DeprecatedUnitStruct; //~ WARN use of deprecated item 'lint_stability::DeprecatedUnitStruct'
+        let _ = DeprecatedUnstableUnitStruct; //~ WARN use of deprecated item 'lint_stability::DeprecatedUnstableUnitStruct'
+        let _ = UnstableUnitStruct;
+        let _ = StableUnitStruct;
+
+        let _ = Enum::DeprecatedVariant; //~ WARN use of deprecated item 'lint_stability::Enum::DeprecatedVariant'
+        let _ = Enum::DeprecatedUnstableVariant; //~ WARN use of deprecated item 'lint_stability::Enum::DeprecatedUnstableVariant'
+        let _ = Enum::UnstableVariant;
+        let _ = Enum::StableVariant;
+
+        let _ = DeprecatedTupleStruct (1); //~ WARN use of deprecated item 'lint_stability::DeprecatedTupleStruct'
+        let _ = DeprecatedUnstableTupleStruct (1); //~ WARN use of deprecated item 'lint_stability::DeprecatedUnstableTupleStruct'
+        let _ = UnstableTupleStruct (1);
+        let _ = StableTupleStruct (1);
+
+        // At the moment, the lint checker only checks stability in
+        // in the arguments of macros.
+        // Eventually, we will want to lint the contents of the
+        // macro in the module *defining* it. Also, stability levels
+        // on macros themselves are not yet linted.
+        macro_test_arg!(deprecated_text()); //~ WARN use of deprecated item 'lint_stability::deprecated_text': text
+        macro_test_arg!(deprecated_unstable_text()); //~ WARN use of deprecated item 'lint_stability::deprecated_unstable_text': text
+        macro_test_arg!(macro_test_arg!(deprecated_text())); //~ WARN use of deprecated item 'lint_stability::deprecated_text': text
+    }
+
+    fn test_method_param<Foo: Trait>(foo: Foo) {
+        foo.trait_deprecated(); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated'
+        Trait::trait_deprecated(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated'
+        <Foo>::trait_deprecated(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated'
+        <Foo as Trait>::trait_deprecated(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated'
+        foo.trait_deprecated_text(); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
+        Trait::trait_deprecated_text(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
+        <Foo>::trait_deprecated_text(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
+        <Foo as Trait>::trait_deprecated_text(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
+        foo.trait_deprecated_unstable(); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable'
+        Trait::trait_deprecated_unstable(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable'
+        <Foo>::trait_deprecated_unstable(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable'
+        <Foo as Trait>::trait_deprecated_unstable(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable'
+        foo.trait_deprecated_unstable_text(); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
+        Trait::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
+        <Foo>::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
+        <Foo as Trait>::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
+        foo.trait_unstable();
+        Trait::trait_unstable(&foo);
+        <Foo>::trait_unstable(&foo);
+        <Foo as Trait>::trait_unstable(&foo);
+        foo.trait_unstable_text();
+        Trait::trait_unstable_text(&foo);
+        <Foo>::trait_unstable_text(&foo);
+        <Foo as Trait>::trait_unstable_text(&foo);
+        foo.trait_stable();
+        Trait::trait_stable(&foo);
+        <Foo>::trait_stable(&foo);
+        <Foo as Trait>::trait_stable(&foo);
+    }
+
+    fn test_method_object(foo: &Trait) {
+        foo.trait_deprecated(); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated'
+        foo.trait_deprecated_text(); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
+        foo.trait_deprecated_unstable(); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable'
+        foo.trait_deprecated_unstable_text(); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
+        foo.trait_unstable();
+        foo.trait_unstable_text();
+        foo.trait_stable();
+    }
+
+    struct S;
+
+    impl UnstableTrait for S { }
+    impl DeprecatedTrait for S {} //~ WARN use of deprecated item 'lint_stability::DeprecatedTrait': text
+    trait LocalTrait : UnstableTrait { }
+    trait LocalTrait2 : DeprecatedTrait { } //~ WARN use of deprecated item 'lint_stability::DeprecatedTrait': text
+
+    impl Trait for S {
+        fn trait_stable(&self) {}
+        fn trait_unstable(&self) {}
+    }
+}
+
+mod inheritance {
+    extern crate inherited_stability;
+    use self::inherited_stability::*;
+
+    fn test_inheritance() {
+        unstable();
+        stable();
+
+        stable_mod::unstable();
+        stable_mod::stable();
+
+        unstable_mod::deprecated(); //~ WARN use of deprecated item 'inheritance::inherited_stability::unstable_mod::deprecated': text
+        unstable_mod::unstable();
+
+        let _ = Unstable::UnstableVariant;
+        let _ = Unstable::StableVariant;
+
+        let x: usize = 0;
+        x.unstable();
+        x.stable();
+    }
+}
+
+mod this_crate {
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    pub fn deprecated() {}
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    pub fn deprecated_text() {}
+
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    pub fn unstable() {}
+    #[unstable(feature = "unstable_test_feature", reason = "text", issue = "0")]
+    pub fn unstable_text() {}
+
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn stable() {}
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn stable_text() {}
+
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub struct MethodTester;
+
+    impl MethodTester {
+        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        #[rustc_deprecated(since = "1.0.0", reason = "text")]
+        pub fn method_deprecated(&self) {}
+        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        #[rustc_deprecated(since = "1.0.0", reason = "text")]
+        pub fn method_deprecated_text(&self) {}
+
+        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        pub fn method_unstable(&self) {}
+        #[unstable(feature = "unstable_test_feature", reason = "text", issue = "0")]
+        pub fn method_unstable_text(&self) {}
+
+        #[stable(feature = "rust1", since = "1.0.0")]
+        pub fn method_stable(&self) {}
+        #[stable(feature = "rust1", since = "1.0.0")]
+        pub fn method_stable_text(&self) {}
+    }
+
+    pub trait Trait {
+        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        #[rustc_deprecated(since = "1.0.0", reason = "text")]
+        fn trait_deprecated(&self) {}
+        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        #[rustc_deprecated(since = "1.0.0", reason = "text")]
+        fn trait_deprecated_text(&self) {}
+
+        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        fn trait_unstable(&self) {}
+        #[unstable(feature = "unstable_test_feature", reason = "text", issue = "0")]
+        fn trait_unstable_text(&self) {}
+
+        #[stable(feature = "rust1", since = "1.0.0")]
+        fn trait_stable(&self) {}
+        #[stable(feature = "rust1", since = "1.0.0")]
+        fn trait_stable_text(&self) {}
+    }
+
+    impl Trait for MethodTester {}
+
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    pub struct DeprecatedStruct {
+        #[stable(feature = "stable_test_feature", since = "1.0.0")] i: isize
+    }
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    pub struct UnstableStruct {
+        #[stable(feature = "stable_test_feature", since = "1.0.0")] i: isize
+    }
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub struct StableStruct {
+        #[stable(feature = "stable_test_feature", since = "1.0.0")] i: isize
+    }
+
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    pub struct DeprecatedUnitStruct;
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    pub struct UnstableUnitStruct;
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub struct StableUnitStruct;
+
+    pub enum Enum {
+        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        #[rustc_deprecated(since = "1.0.0", reason = "text")]
+        DeprecatedVariant,
+        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        UnstableVariant,
+
+        #[stable(feature = "rust1", since = "1.0.0")]
+        StableVariant,
+    }
+
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    pub struct DeprecatedTupleStruct(isize);
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    pub struct UnstableTupleStruct(isize);
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub struct StableTupleStruct(isize);
+
+    fn test() {
+        // Only the deprecated cases of the following should generate
+        // errors, because other stability attributes now have meaning
+        // only *across* crates, not within a single crate.
+
+        type Foo = MethodTester;
+        let foo = MethodTester;
+
+        deprecated(); //~ WARN use of deprecated item 'this_crate::deprecated'
+        foo.method_deprecated(); //~ WARN use of deprecated item 'this_crate::MethodTester::method_deprecated'
+        Foo::method_deprecated(&foo); //~ WARN use of deprecated item 'this_crate::MethodTester::method_deprecated'
+        <Foo>::method_deprecated(&foo); //~ WARN use of deprecated item 'this_crate::MethodTester::method_deprecated'
+        foo.trait_deprecated(); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated'
+        Trait::trait_deprecated(&foo); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated'
+        <Foo>::trait_deprecated(&foo); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated'
+        <Foo as Trait>::trait_deprecated(&foo); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated'
+
+        deprecated_text(); //~ WARN use of deprecated item 'this_crate::deprecated_text': text
+        foo.method_deprecated_text(); //~ WARN use of deprecated item 'this_crate::MethodTester::method_deprecated_text': text
+        Foo::method_deprecated_text(&foo); //~ WARN use of deprecated item 'this_crate::MethodTester::method_deprecated_text': text
+        <Foo>::method_deprecated_text(&foo); //~ WARN use of deprecated item 'this_crate::MethodTester::method_deprecated_text': text
+        foo.trait_deprecated_text(); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+        Trait::trait_deprecated_text(&foo); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+        <Foo>::trait_deprecated_text(&foo); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+        <Foo as Trait>::trait_deprecated_text(&foo); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+
+        unstable();
+        foo.method_unstable();
+        Foo::method_unstable(&foo);
+        <Foo>::method_unstable(&foo);
+        foo.trait_unstable();
+        Trait::trait_unstable(&foo);
+        <Foo>::trait_unstable(&foo);
+        <Foo as Trait>::trait_unstable(&foo);
+
+        unstable_text();
+        foo.method_unstable_text();
+        Foo::method_unstable_text(&foo);
+        <Foo>::method_unstable_text(&foo);
+        foo.trait_unstable_text();
+        Trait::trait_unstable_text(&foo);
+        <Foo>::trait_unstable_text(&foo);
+        <Foo as Trait>::trait_unstable_text(&foo);
+
+        stable();
+        foo.method_stable();
+        Foo::method_stable(&foo);
+        <Foo>::method_stable(&foo);
+        foo.trait_stable();
+        Trait::trait_stable(&foo);
+        <Foo>::trait_stable(&foo);
+        <Foo as Trait>::trait_stable(&foo);
+
+        stable_text();
+        foo.method_stable_text();
+        Foo::method_stable_text(&foo);
+        <Foo>::method_stable_text(&foo);
+        foo.trait_stable_text();
+        Trait::trait_stable_text(&foo);
+        <Foo>::trait_stable_text(&foo);
+        <Foo as Trait>::trait_stable_text(&foo);
+
+        let _ = DeprecatedStruct {
+            //~^ WARN use of deprecated item 'this_crate::DeprecatedStruct'
+            i: 0 //~ WARN use of deprecated item 'this_crate::DeprecatedStruct::i'
+        };
+        let _ = UnstableStruct { i: 0 };
+        let _ = StableStruct { i: 0 };
+
+        let _ = DeprecatedUnitStruct; //~ WARN use of deprecated item 'this_crate::DeprecatedUnitStruct'
+        let _ = UnstableUnitStruct;
+        let _ = StableUnitStruct;
+
+        let _ = Enum::DeprecatedVariant; //~ WARN use of deprecated item 'this_crate::Enum::DeprecatedVariant'
+        let _ = Enum::UnstableVariant;
+        let _ = Enum::StableVariant;
+
+        let _ = DeprecatedTupleStruct (1); //~ WARN use of deprecated item 'this_crate::DeprecatedTupleStruct'
+        let _ = UnstableTupleStruct (1);
+        let _ = StableTupleStruct (1);
+    }
+
+    fn test_method_param<Foo: Trait>(foo: Foo) {
+        foo.trait_deprecated(); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated'
+        Trait::trait_deprecated(&foo); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated'
+        <Foo>::trait_deprecated(&foo); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated'
+        <Foo as Trait>::trait_deprecated(&foo); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated'
+        foo.trait_deprecated_text(); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+        Trait::trait_deprecated_text(&foo); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+        <Foo>::trait_deprecated_text(&foo); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+        <Foo as Trait>::trait_deprecated_text(&foo); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+        foo.trait_unstable();
+        Trait::trait_unstable(&foo);
+        <Foo>::trait_unstable(&foo);
+        <Foo as Trait>::trait_unstable(&foo);
+        foo.trait_unstable_text();
+        Trait::trait_unstable_text(&foo);
+        <Foo>::trait_unstable_text(&foo);
+        <Foo as Trait>::trait_unstable_text(&foo);
+        foo.trait_stable();
+        Trait::trait_stable(&foo);
+        <Foo>::trait_stable(&foo);
+        <Foo as Trait>::trait_stable(&foo);
+    }
+
+    fn test_method_object(foo: &Trait) {
+        foo.trait_deprecated(); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated'
+        foo.trait_deprecated_text(); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+        foo.trait_unstable();
+        foo.trait_unstable_text();
+        foo.trait_stable();
+    }
+
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    fn test_fn_body() {
+        fn fn_in_body() {}
+        fn_in_body(); //~ WARN use of deprecated item 'this_crate::test_fn_body::fn_in_body': text
+    }
+
+    impl MethodTester {
+        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        #[rustc_deprecated(since = "1.0.0", reason = "text")]
+        fn test_method_body(&self) {
+            fn fn_in_body() {}
+            fn_in_body(); //~ WARN use of deprecated item 'this_crate::MethodTester::test_method_body::fn_in_body': text
+        }
+    }
+
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    pub trait DeprecatedTrait {
+        fn dummy(&self) { }
+    }
+
+    struct S;
+
+    impl DeprecatedTrait for S { } //~ WARN use of deprecated item 'this_crate::DeprecatedTrait'
+
+    trait LocalTrait : DeprecatedTrait { } //~ WARN use of deprecated item 'this_crate::DeprecatedTrait'
+}
+
+fn main() {}
diff --git a/src/test/ui/lint/lint-stability-deprecated.stderr b/src/test/ui/lint/lint-stability-deprecated.stderr
new file mode 100644
index 0000000..811004e
--- /dev/null
+++ b/src/test/ui/lint/lint-stability-deprecated.stderr
@@ -0,0 +1,636 @@
+warning: use of deprecated item 'lint_stability::deprecated': text
+  --> $DIR/lint-stability-deprecated.rs:26:9
+   |
+LL |         deprecated();
+   |         ^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/lint-stability-deprecated.rs:7:9
+   |
+LL | #![warn(deprecated)]
+   |         ^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::Trait::trait_deprecated': text
+  --> $DIR/lint-stability-deprecated.rs:31:9
+   |
+LL |         Trait::trait_deprecated(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::Trait::trait_deprecated': text
+  --> $DIR/lint-stability-deprecated.rs:33:9
+   |
+LL |         <Foo as Trait>::trait_deprecated(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::deprecated_text': text
+  --> $DIR/lint-stability-deprecated.rs:35:9
+   |
+LL |         deprecated_text();
+   |         ^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
+  --> $DIR/lint-stability-deprecated.rs:40:9
+   |
+LL |         Trait::trait_deprecated_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
+  --> $DIR/lint-stability-deprecated.rs:42:9
+   |
+LL |         <Foo as Trait>::trait_deprecated_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::deprecated_unstable': text
+  --> $DIR/lint-stability-deprecated.rs:44:9
+   |
+LL |         deprecated_unstable();
+   |         ^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable': text
+  --> $DIR/lint-stability-deprecated.rs:49:9
+   |
+LL |         Trait::trait_deprecated_unstable(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable': text
+  --> $DIR/lint-stability-deprecated.rs:51:9
+   |
+LL |         <Foo as Trait>::trait_deprecated_unstable(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::deprecated_unstable_text': text
+  --> $DIR/lint-stability-deprecated.rs:53:9
+   |
+LL |         deprecated_unstable_text();
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
+  --> $DIR/lint-stability-deprecated.rs:58:9
+   |
+LL |         Trait::trait_deprecated_unstable_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
+  --> $DIR/lint-stability-deprecated.rs:60:9
+   |
+LL |         <Foo as Trait>::trait_deprecated_unstable_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::DeprecatedStruct': text
+  --> $DIR/lint-stability-deprecated.rs:107:17
+   |
+LL |         let _ = DeprecatedStruct {
+   |                 ^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::DeprecatedUnstableStruct': text
+  --> $DIR/lint-stability-deprecated.rs:110:17
+   |
+LL |         let _ = DeprecatedUnstableStruct {
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::DeprecatedUnitStruct': text
+  --> $DIR/lint-stability-deprecated.rs:117:17
+   |
+LL |         let _ = DeprecatedUnitStruct;
+   |                 ^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::DeprecatedUnstableUnitStruct': text
+  --> $DIR/lint-stability-deprecated.rs:118:17
+   |
+LL |         let _ = DeprecatedUnstableUnitStruct;
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::Enum::DeprecatedVariant': text
+  --> $DIR/lint-stability-deprecated.rs:122:17
+   |
+LL |         let _ = Enum::DeprecatedVariant;
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::Enum::DeprecatedUnstableVariant': text
+  --> $DIR/lint-stability-deprecated.rs:123:17
+   |
+LL |         let _ = Enum::DeprecatedUnstableVariant;
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::DeprecatedTupleStruct': text
+  --> $DIR/lint-stability-deprecated.rs:127:17
+   |
+LL |         let _ = DeprecatedTupleStruct (1);
+   |                 ^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::DeprecatedUnstableTupleStruct': text
+  --> $DIR/lint-stability-deprecated.rs:128:17
+   |
+LL |         let _ = DeprecatedUnstableTupleStruct (1);
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::deprecated_text': text
+  --> $DIR/lint-stability-deprecated.rs:137:25
+   |
+LL |         macro_test_arg!(deprecated_text());
+   |                         ^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::deprecated_unstable_text': text
+  --> $DIR/lint-stability-deprecated.rs:138:25
+   |
+LL |         macro_test_arg!(deprecated_unstable_text());
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::deprecated_text': text
+  --> $DIR/lint-stability-deprecated.rs:139:41
+   |
+LL |         macro_test_arg!(macro_test_arg!(deprecated_text()));
+   |                                         ^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::Trait::trait_deprecated': text
+  --> $DIR/lint-stability-deprecated.rs:144:9
+   |
+LL |         Trait::trait_deprecated(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::Trait::trait_deprecated': text
+  --> $DIR/lint-stability-deprecated.rs:146:9
+   |
+LL |         <Foo as Trait>::trait_deprecated(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
+  --> $DIR/lint-stability-deprecated.rs:148:9
+   |
+LL |         Trait::trait_deprecated_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
+  --> $DIR/lint-stability-deprecated.rs:150:9
+   |
+LL |         <Foo as Trait>::trait_deprecated_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable': text
+  --> $DIR/lint-stability-deprecated.rs:152:9
+   |
+LL |         Trait::trait_deprecated_unstable(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable': text
+  --> $DIR/lint-stability-deprecated.rs:154:9
+   |
+LL |         <Foo as Trait>::trait_deprecated_unstable(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
+  --> $DIR/lint-stability-deprecated.rs:156:9
+   |
+LL |         Trait::trait_deprecated_unstable_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
+  --> $DIR/lint-stability-deprecated.rs:158:9
+   |
+LL |         <Foo as Trait>::trait_deprecated_unstable_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::DeprecatedTrait': text
+  --> $DIR/lint-stability-deprecated.rs:186:10
+   |
+LL |     impl DeprecatedTrait for S {}
+   |          ^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::DeprecatedTrait': text
+  --> $DIR/lint-stability-deprecated.rs:188:25
+   |
+LL |     trait LocalTrait2 : DeprecatedTrait { }
+   |                         ^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'inheritance::inherited_stability::unstable_mod::deprecated': text
+  --> $DIR/lint-stability-deprecated.rs:207:9
+   |
+LL |         unstable_mod::deprecated();
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'this_crate::deprecated': text
+  --> $DIR/lint-stability-deprecated.rs:329:9
+   |
+LL |         deprecated();
+   |         ^^^^^^^^^^
+
+warning: use of deprecated item 'this_crate::Trait::trait_deprecated': text
+  --> $DIR/lint-stability-deprecated.rs:334:9
+   |
+LL |         Trait::trait_deprecated(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'this_crate::Trait::trait_deprecated': text
+  --> $DIR/lint-stability-deprecated.rs:336:9
+   |
+LL |         <Foo as Trait>::trait_deprecated(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'this_crate::deprecated_text': text
+  --> $DIR/lint-stability-deprecated.rs:338:9
+   |
+LL |         deprecated_text();
+   |         ^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+  --> $DIR/lint-stability-deprecated.rs:343:9
+   |
+LL |         Trait::trait_deprecated_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+  --> $DIR/lint-stability-deprecated.rs:345:9
+   |
+LL |         <Foo as Trait>::trait_deprecated_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'this_crate::DeprecatedStruct': text
+  --> $DIR/lint-stability-deprecated.rs:383:17
+   |
+LL |         let _ = DeprecatedStruct {
+   |                 ^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'this_crate::DeprecatedUnitStruct': text
+  --> $DIR/lint-stability-deprecated.rs:390:17
+   |
+LL |         let _ = DeprecatedUnitStruct;
+   |                 ^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'this_crate::Enum::DeprecatedVariant': text
+  --> $DIR/lint-stability-deprecated.rs:394:17
+   |
+LL |         let _ = Enum::DeprecatedVariant;
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'this_crate::DeprecatedTupleStruct': text
+  --> $DIR/lint-stability-deprecated.rs:398:17
+   |
+LL |         let _ = DeprecatedTupleStruct (1);
+   |                 ^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'this_crate::Trait::trait_deprecated': text
+  --> $DIR/lint-stability-deprecated.rs:405:9
+   |
+LL |         Trait::trait_deprecated(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'this_crate::Trait::trait_deprecated': text
+  --> $DIR/lint-stability-deprecated.rs:407:9
+   |
+LL |         <Foo as Trait>::trait_deprecated(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+  --> $DIR/lint-stability-deprecated.rs:409:9
+   |
+LL |         Trait::trait_deprecated_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+  --> $DIR/lint-stability-deprecated.rs:411:9
+   |
+LL |         <Foo as Trait>::trait_deprecated_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'this_crate::test_fn_body::fn_in_body': text
+  --> $DIR/lint-stability-deprecated.rs:438:9
+   |
+LL |         fn_in_body();
+   |         ^^^^^^^^^^
+
+warning: use of deprecated item 'this_crate::DeprecatedTrait': text
+  --> $DIR/lint-stability-deprecated.rs:458:10
+   |
+LL |     impl DeprecatedTrait for S { }
+   |          ^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'this_crate::DeprecatedTrait': text
+  --> $DIR/lint-stability-deprecated.rs:460:24
+   |
+LL |     trait LocalTrait : DeprecatedTrait { }
+   |                        ^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'this_crate::MethodTester::test_method_body::fn_in_body': text
+  --> $DIR/lint-stability-deprecated.rs:446:13
+   |
+LL |             fn_in_body();
+   |             ^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::TraitWithAssociatedTypes::TypeDeprecated': text
+  --> $DIR/lint-stability-deprecated.rs:99:48
+   |
+LL |         struct S2<T: TraitWithAssociatedTypes>(T::TypeDeprecated);
+   |                                                ^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::TraitWithAssociatedTypes::TypeDeprecated': text
+  --> $DIR/lint-stability-deprecated.rs:103:13
+   |
+LL |             TypeDeprecated = u16,
+   |             ^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::MethodTester::method_deprecated': text
+  --> $DIR/lint-stability-deprecated.rs:27:13
+   |
+LL |         foo.method_deprecated();
+   |             ^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::MethodTester::method_deprecated': text
+  --> $DIR/lint-stability-deprecated.rs:28:9
+   |
+LL |         Foo::method_deprecated(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::MethodTester::method_deprecated': text
+  --> $DIR/lint-stability-deprecated.rs:29:9
+   |
+LL |         <Foo>::method_deprecated(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::Trait::trait_deprecated': text
+  --> $DIR/lint-stability-deprecated.rs:30:13
+   |
+LL |         foo.trait_deprecated();
+   |             ^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::Trait::trait_deprecated': text
+  --> $DIR/lint-stability-deprecated.rs:32:9
+   |
+LL |         <Foo>::trait_deprecated(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::MethodTester::method_deprecated_text': text
+  --> $DIR/lint-stability-deprecated.rs:36:13
+   |
+LL |         foo.method_deprecated_text();
+   |             ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::MethodTester::method_deprecated_text': text
+  --> $DIR/lint-stability-deprecated.rs:37:9
+   |
+LL |         Foo::method_deprecated_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::MethodTester::method_deprecated_text': text
+  --> $DIR/lint-stability-deprecated.rs:38:9
+   |
+LL |         <Foo>::method_deprecated_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
+  --> $DIR/lint-stability-deprecated.rs:39:13
+   |
+LL |         foo.trait_deprecated_text();
+   |             ^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
+  --> $DIR/lint-stability-deprecated.rs:41:9
+   |
+LL |         <Foo>::trait_deprecated_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::MethodTester::method_deprecated_unstable': text
+  --> $DIR/lint-stability-deprecated.rs:45:13
+   |
+LL |         foo.method_deprecated_unstable();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::MethodTester::method_deprecated_unstable': text
+  --> $DIR/lint-stability-deprecated.rs:46:9
+   |
+LL |         Foo::method_deprecated_unstable(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::MethodTester::method_deprecated_unstable': text
+  --> $DIR/lint-stability-deprecated.rs:47:9
+   |
+LL |         <Foo>::method_deprecated_unstable(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable': text
+  --> $DIR/lint-stability-deprecated.rs:48:13
+   |
+LL |         foo.trait_deprecated_unstable();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable': text
+  --> $DIR/lint-stability-deprecated.rs:50:9
+   |
+LL |         <Foo>::trait_deprecated_unstable(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::MethodTester::method_deprecated_unstable_text': text
+  --> $DIR/lint-stability-deprecated.rs:54:13
+   |
+LL |         foo.method_deprecated_unstable_text();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::MethodTester::method_deprecated_unstable_text': text
+  --> $DIR/lint-stability-deprecated.rs:55:9
+   |
+LL |         Foo::method_deprecated_unstable_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::MethodTester::method_deprecated_unstable_text': text
+  --> $DIR/lint-stability-deprecated.rs:56:9
+   |
+LL |         <Foo>::method_deprecated_unstable_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
+  --> $DIR/lint-stability-deprecated.rs:57:13
+   |
+LL |         foo.trait_deprecated_unstable_text();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
+  --> $DIR/lint-stability-deprecated.rs:59:9
+   |
+LL |         <Foo>::trait_deprecated_unstable_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::DeprecatedStruct::i': text
+  --> $DIR/lint-stability-deprecated.rs:108:13
+   |
+LL |             i: 0
+   |             ^^^^
+
+warning: use of deprecated item 'lint_stability::DeprecatedUnstableStruct::i': text
+  --> $DIR/lint-stability-deprecated.rs:112:13
+   |
+LL |             i: 0
+   |             ^^^^
+
+warning: use of deprecated item 'lint_stability::Trait::trait_deprecated': text
+  --> $DIR/lint-stability-deprecated.rs:143:13
+   |
+LL |         foo.trait_deprecated();
+   |             ^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::Trait::trait_deprecated': text
+  --> $DIR/lint-stability-deprecated.rs:145:9
+   |
+LL |         <Foo>::trait_deprecated(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
+  --> $DIR/lint-stability-deprecated.rs:147:13
+   |
+LL |         foo.trait_deprecated_text();
+   |             ^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
+  --> $DIR/lint-stability-deprecated.rs:149:9
+   |
+LL |         <Foo>::trait_deprecated_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable': text
+  --> $DIR/lint-stability-deprecated.rs:151:13
+   |
+LL |         foo.trait_deprecated_unstable();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable': text
+  --> $DIR/lint-stability-deprecated.rs:153:9
+   |
+LL |         <Foo>::trait_deprecated_unstable(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
+  --> $DIR/lint-stability-deprecated.rs:155:13
+   |
+LL |         foo.trait_deprecated_unstable_text();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
+  --> $DIR/lint-stability-deprecated.rs:157:9
+   |
+LL |         <Foo>::trait_deprecated_unstable_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::Trait::trait_deprecated': text
+  --> $DIR/lint-stability-deprecated.rs:174:13
+   |
+LL |         foo.trait_deprecated();
+   |             ^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
+  --> $DIR/lint-stability-deprecated.rs:175:13
+   |
+LL |         foo.trait_deprecated_text();
+   |             ^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable': text
+  --> $DIR/lint-stability-deprecated.rs:176:13
+   |
+LL |         foo.trait_deprecated_unstable();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
+  --> $DIR/lint-stability-deprecated.rs:177:13
+   |
+LL |         foo.trait_deprecated_unstable_text();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'this_crate::MethodTester::method_deprecated': text
+  --> $DIR/lint-stability-deprecated.rs:330:13
+   |
+LL |         foo.method_deprecated();
+   |             ^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'this_crate::MethodTester::method_deprecated': text
+  --> $DIR/lint-stability-deprecated.rs:331:9
+   |
+LL |         Foo::method_deprecated(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'this_crate::MethodTester::method_deprecated': text
+  --> $DIR/lint-stability-deprecated.rs:332:9
+   |
+LL |         <Foo>::method_deprecated(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'this_crate::Trait::trait_deprecated': text
+  --> $DIR/lint-stability-deprecated.rs:333:13
+   |
+LL |         foo.trait_deprecated();
+   |             ^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'this_crate::Trait::trait_deprecated': text
+  --> $DIR/lint-stability-deprecated.rs:335:9
+   |
+LL |         <Foo>::trait_deprecated(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'this_crate::MethodTester::method_deprecated_text': text
+  --> $DIR/lint-stability-deprecated.rs:339:13
+   |
+LL |         foo.method_deprecated_text();
+   |             ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'this_crate::MethodTester::method_deprecated_text': text
+  --> $DIR/lint-stability-deprecated.rs:340:9
+   |
+LL |         Foo::method_deprecated_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'this_crate::MethodTester::method_deprecated_text': text
+  --> $DIR/lint-stability-deprecated.rs:341:9
+   |
+LL |         <Foo>::method_deprecated_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+  --> $DIR/lint-stability-deprecated.rs:342:13
+   |
+LL |         foo.trait_deprecated_text();
+   |             ^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+  --> $DIR/lint-stability-deprecated.rs:344:9
+   |
+LL |         <Foo>::trait_deprecated_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'this_crate::DeprecatedStruct::i': text
+  --> $DIR/lint-stability-deprecated.rs:385:13
+   |
+LL |             i: 0
+   |             ^^^^
+
+warning: use of deprecated item 'this_crate::Trait::trait_deprecated': text
+  --> $DIR/lint-stability-deprecated.rs:404:13
+   |
+LL |         foo.trait_deprecated();
+   |             ^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'this_crate::Trait::trait_deprecated': text
+  --> $DIR/lint-stability-deprecated.rs:406:9
+   |
+LL |         <Foo>::trait_deprecated(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+  --> $DIR/lint-stability-deprecated.rs:408:13
+   |
+LL |         foo.trait_deprecated_text();
+   |             ^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+  --> $DIR/lint-stability-deprecated.rs:410:9
+   |
+LL |         <Foo>::trait_deprecated_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'this_crate::Trait::trait_deprecated': text
+  --> $DIR/lint-stability-deprecated.rs:427:13
+   |
+LL |         foo.trait_deprecated();
+   |             ^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+  --> $DIR/lint-stability-deprecated.rs:428:13
+   |
+LL |         foo.trait_deprecated_text();
+   |             ^^^^^^^^^^^^^^^^^^^^^
+
diff --git a/src/test/ui/lint/lint-stability-fields-deprecated.rs b/src/test/ui/lint/lint-stability-fields-deprecated.rs
new file mode 100644
index 0000000..9d5b7c5
--- /dev/null
+++ b/src/test/ui/lint/lint-stability-fields-deprecated.rs
@@ -0,0 +1,339 @@
+// aux-build:lint_stability_fields.rs
+
+#![deny(deprecated)]
+#![allow(dead_code)]
+#![feature(staged_api, unstable_test_feature)]
+
+#![stable(feature = "rust1", since = "1.0.0")]
+
+mod cross_crate {
+    extern crate lint_stability_fields;
+
+    use self::lint_stability_fields::*;
+
+    pub fn foo() {
+        let x = Stable {
+            inherit: 1,
+            override1: 2,
+            override2: 3,
+            //~^ ERROR use of deprecated item
+        };
+
+        let _ = x.inherit;
+        let _ = x.override1;
+        let _ = x.override2;
+        //~^ ERROR use of deprecated item
+
+        let Stable {
+            inherit: _,
+            override1: _,
+            override2: _
+            //~^ ERROR use of deprecated item
+        } = x;
+        // all fine
+        let Stable { .. } = x;
+
+        let x = Stable2(1, 2, 3);
+
+        let _ = x.0;
+        let _ = x.1;
+        let _ = x.2;
+        //~^ ERROR use of deprecated item
+
+        let Stable2(_,
+                   _,
+                   _)
+            //~^ ERROR use of deprecated item
+            = x;
+        // all fine
+        let Stable2(..) = x;
+
+
+        let x = Unstable {
+            inherit: 1,
+            override1: 2,
+            override2: 3,
+            //~^ ERROR use of deprecated item
+        };
+
+        let _ = x.inherit;
+        let _ = x.override1;
+        let _ = x.override2;
+        //~^ ERROR use of deprecated item
+
+        let Unstable {
+            inherit: _,
+            override1: _,
+            override2: _
+            //~^ ERROR use of deprecated item
+        } = x;
+
+        let Unstable
+            // the patterns are all fine:
+            { .. } = x;
+
+
+        let x = Unstable2(1, 2, 3);
+
+        let _ = x.0;
+        let _ = x.1;
+        let _ = x.2;
+        //~^ ERROR use of deprecated item
+
+        let Unstable2
+            (_,
+             _,
+             _)
+            //~^ ERROR use of deprecated item
+            = x;
+        let Unstable2
+            // the patterns are all fine:
+            (..) = x;
+
+
+        let x = Deprecated {
+            //~^ ERROR use of deprecated item
+            inherit: 1,
+            //~^ ERROR use of deprecated item
+            override1: 2,
+            //~^ ERROR use of deprecated item
+            override2: 3,
+            //~^ ERROR use of deprecated item
+        };
+
+        let _ = x.inherit;
+        //~^ ERROR use of deprecated item
+        let _ = x.override1;
+        //~^ ERROR use of deprecated item
+        let _ = x.override2;
+        //~^ ERROR use of deprecated item
+
+        let Deprecated {
+            //~^ ERROR use of deprecated item
+            inherit: _,
+            //~^ ERROR use of deprecated item
+            override1: _,
+            //~^ ERROR use of deprecated item
+            override2: _
+            //~^ ERROR use of deprecated item
+        } = x;
+
+        let Deprecated
+            //~^ ERROR use of deprecated item
+            // the patterns are all fine:
+            { .. } = x;
+
+        let x = Deprecated2(1, 2, 3);
+        //~^ ERROR use of deprecated item
+
+        let _ = x.0;
+        //~^ ERROR use of deprecated item
+        let _ = x.1;
+        //~^ ERROR use of deprecated item
+        let _ = x.2;
+        //~^ ERROR use of deprecated item
+
+        let Deprecated2
+        //~^ ERROR use of deprecated item
+            (_,
+             //~^ ERROR use of deprecated item
+             _,
+             //~^ ERROR use of deprecated item
+             _)
+             //~^ ERROR use of deprecated item
+            = x;
+        let Deprecated2
+        //~^ ERROR use of deprecated item
+            // the patterns are all fine:
+            (..) = x;
+    }
+}
+
+mod this_crate {
+    #[stable(feature = "rust1", since = "1.0.0")]
+    struct Stable {
+        inherit: u8,
+        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        override1: u8,
+        #[rustc_deprecated(since = "1.0.0", reason = "text")]
+        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        override2: u8,
+    }
+
+    #[stable(feature = "rust1", since = "1.0.0")]
+    struct Stable2(u8,
+                   #[stable(feature = "rust1", since = "1.0.0")] u8,
+                   #[unstable(feature = "unstable_test_feature", issue = "0")]
+                   #[rustc_deprecated(since = "1.0.0", reason = "text")] u8);
+
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    struct Unstable {
+        inherit: u8,
+        #[stable(feature = "rust1", since = "1.0.0")]
+        override1: u8,
+        #[rustc_deprecated(since = "1.0.0", reason = "text")]
+        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        override2: u8,
+    }
+
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    struct Unstable2(u8,
+                     #[stable(feature = "rust1", since = "1.0.0")] u8,
+                     #[unstable(feature = "unstable_test_feature", issue = "0")]
+                     #[rustc_deprecated(since = "1.0.0", reason = "text")] u8);
+
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    struct Deprecated {
+        inherit: u8,
+        #[stable(feature = "rust1", since = "1.0.0")]
+        override1: u8,
+        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        override2: u8,
+    }
+
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    struct Deprecated2(u8,
+                       #[stable(feature = "rust1", since = "1.0.0")] u8,
+                       #[unstable(feature = "unstable_test_feature", issue = "0")] u8);
+
+    pub fn foo() {
+        let x = Stable {
+            inherit: 1,
+            override1: 2,
+            override2: 3,
+            //~^ ERROR use of deprecated item
+        };
+
+        let _ = x.inherit;
+        let _ = x.override1;
+        let _ = x.override2;
+        //~^ ERROR use of deprecated item
+
+        let Stable {
+            inherit: _,
+            override1: _,
+            override2: _
+            //~^ ERROR use of deprecated item
+        } = x;
+        // all fine
+        let Stable { .. } = x;
+
+        let x = Stable2(1, 2, 3);
+
+        let _ = x.0;
+        let _ = x.1;
+        let _ = x.2;
+        //~^ ERROR use of deprecated item
+
+        let Stable2(_,
+                   _,
+                   _)
+            //~^ ERROR use of deprecated item
+            = x;
+        // all fine
+        let Stable2(..) = x;
+
+
+        let x = Unstable {
+            inherit: 1,
+            override1: 2,
+            override2: 3,
+            //~^ ERROR use of deprecated item
+        };
+
+        let _ = x.inherit;
+        let _ = x.override1;
+        let _ = x.override2;
+        //~^ ERROR use of deprecated item
+
+        let Unstable {
+            inherit: _,
+            override1: _,
+            override2: _
+            //~^ ERROR use of deprecated item
+        } = x;
+
+        let Unstable
+            // the patterns are all fine:
+            { .. } = x;
+
+
+        let x = Unstable2(1, 2, 3);
+
+        let _ = x.0;
+        let _ = x.1;
+        let _ = x.2;
+        //~^ ERROR use of deprecated item
+
+        let Unstable2
+            (_,
+             _,
+             _)
+            //~^ ERROR use of deprecated item
+            = x;
+        let Unstable2
+            // the patterns are all fine:
+            (..) = x;
+
+
+        let x = Deprecated {
+            //~^ ERROR use of deprecated item
+            inherit: 1,
+            //~^ ERROR use of deprecated item
+            override1: 2,
+            //~^ ERROR use of deprecated item
+            override2: 3,
+            //~^ ERROR use of deprecated item
+        };
+
+        let _ = x.inherit;
+        //~^ ERROR use of deprecated item
+        let _ = x.override1;
+        //~^ ERROR use of deprecated item
+        let _ = x.override2;
+        //~^ ERROR use of deprecated item
+
+        let Deprecated {
+            //~^ ERROR use of deprecated item
+            inherit: _,
+            //~^ ERROR use of deprecated item
+            override1: _,
+            //~^ ERROR use of deprecated item
+            override2: _
+            //~^ ERROR use of deprecated item
+        } = x;
+
+        let Deprecated
+            //~^ ERROR use of deprecated item
+            // the patterns are all fine:
+            { .. } = x;
+
+        let x = Deprecated2(1, 2, 3);
+        //~^ ERROR use of deprecated item
+
+        let _ = x.0;
+        //~^ ERROR use of deprecated item
+        let _ = x.1;
+        //~^ ERROR use of deprecated item
+        let _ = x.2;
+        //~^ ERROR use of deprecated item
+
+        let Deprecated2
+        //~^ ERROR use of deprecated item
+            (_,
+             //~^ ERROR use of deprecated item
+             _,
+             //~^ ERROR use of deprecated item
+             _)
+            //~^ ERROR use of deprecated item
+            = x;
+        let Deprecated2
+        //~^ ERROR use of deprecated item
+            // the patterns are all fine:
+            (..) = x;
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/lint/lint-stability-fields-deprecated.stderr b/src/test/ui/lint/lint-stability-fields-deprecated.stderr
new file mode 100644
index 0000000..488be75
--- /dev/null
+++ b/src/test/ui/lint/lint-stability-fields-deprecated.stderr
@@ -0,0 +1,380 @@
+error: use of deprecated item 'cross_crate::lint_stability_fields::Deprecated': text
+  --> $DIR/lint-stability-fields-deprecated.rs:94:17
+   |
+LL |         let x = Deprecated {
+   |                 ^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/lint-stability-fields-deprecated.rs:3:9
+   |
+LL | #![deny(deprecated)]
+   |         ^^^^^^^^^^
+
+error: use of deprecated item 'cross_crate::lint_stability_fields::Deprecated': text
+  --> $DIR/lint-stability-fields-deprecated.rs:111:13
+   |
+LL |         let Deprecated {
+   |             ^^^^^^^^^^
+
+error: use of deprecated item 'cross_crate::lint_stability_fields::Deprecated': text
+  --> $DIR/lint-stability-fields-deprecated.rs:121:13
+   |
+LL |         let Deprecated
+   |             ^^^^^^^^^^
+
+error: use of deprecated item 'cross_crate::lint_stability_fields::Deprecated2': text
+  --> $DIR/lint-stability-fields-deprecated.rs:126:17
+   |
+LL |         let x = Deprecated2(1, 2, 3);
+   |                 ^^^^^^^^^^^
+
+error: use of deprecated item 'cross_crate::lint_stability_fields::Deprecated2': text
+  --> $DIR/lint-stability-fields-deprecated.rs:136:13
+   |
+LL |         let Deprecated2
+   |             ^^^^^^^^^^^
+
+error: use of deprecated item 'cross_crate::lint_stability_fields::Deprecated2': text
+  --> $DIR/lint-stability-fields-deprecated.rs:145:13
+   |
+LL |         let Deprecated2
+   |             ^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::Deprecated': text
+  --> $DIR/lint-stability-fields-deprecated.rs:281:17
+   |
+LL |         let x = Deprecated {
+   |                 ^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::Deprecated': text
+  --> $DIR/lint-stability-fields-deprecated.rs:298:13
+   |
+LL |         let Deprecated {
+   |             ^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::Deprecated': text
+  --> $DIR/lint-stability-fields-deprecated.rs:308:13
+   |
+LL |         let Deprecated
+   |             ^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::Deprecated2': text
+  --> $DIR/lint-stability-fields-deprecated.rs:313:17
+   |
+LL |         let x = Deprecated2(1, 2, 3);
+   |                 ^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::Deprecated2': text
+  --> $DIR/lint-stability-fields-deprecated.rs:323:13
+   |
+LL |         let Deprecated2
+   |             ^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::Deprecated2': text
+  --> $DIR/lint-stability-fields-deprecated.rs:332:13
+   |
+LL |         let Deprecated2
+   |             ^^^^^^^^^^^
+
+error: use of deprecated item 'cross_crate::lint_stability_fields::Stable::override2': text
+  --> $DIR/lint-stability-fields-deprecated.rs:18:13
+   |
+LL |             override2: 3,
+   |             ^^^^^^^^^^^^
+
+error: use of deprecated item 'cross_crate::lint_stability_fields::Stable::override2': text
+  --> $DIR/lint-stability-fields-deprecated.rs:24:17
+   |
+LL |         let _ = x.override2;
+   |                 ^^^^^^^^^^^
+
+error: use of deprecated item 'cross_crate::lint_stability_fields::Stable::override2': text
+  --> $DIR/lint-stability-fields-deprecated.rs:30:13
+   |
+LL |             override2: _
+   |             ^^^^^^^^^^^^
+
+error: use of deprecated item 'cross_crate::lint_stability_fields::Stable2::2': text
+  --> $DIR/lint-stability-fields-deprecated.rs:40:17
+   |
+LL |         let _ = x.2;
+   |                 ^^^
+
+error: use of deprecated item 'cross_crate::lint_stability_fields::Stable2::2': text
+  --> $DIR/lint-stability-fields-deprecated.rs:45:20
+   |
+LL |                    _)
+   |                    ^
+
+error: use of deprecated item 'cross_crate::lint_stability_fields::Unstable::override2': text
+  --> $DIR/lint-stability-fields-deprecated.rs:55:13
+   |
+LL |             override2: 3,
+   |             ^^^^^^^^^^^^
+
+error: use of deprecated item 'cross_crate::lint_stability_fields::Unstable::override2': text
+  --> $DIR/lint-stability-fields-deprecated.rs:61:17
+   |
+LL |         let _ = x.override2;
+   |                 ^^^^^^^^^^^
+
+error: use of deprecated item 'cross_crate::lint_stability_fields::Unstable::override2': text
+  --> $DIR/lint-stability-fields-deprecated.rs:67:13
+   |
+LL |             override2: _
+   |             ^^^^^^^^^^^^
+
+error: use of deprecated item 'cross_crate::lint_stability_fields::Unstable2::2': text
+  --> $DIR/lint-stability-fields-deprecated.rs:80:17
+   |
+LL |         let _ = x.2;
+   |                 ^^^
+
+error: use of deprecated item 'cross_crate::lint_stability_fields::Unstable2::2': text
+  --> $DIR/lint-stability-fields-deprecated.rs:86:14
+   |
+LL |              _)
+   |              ^
+
+error: use of deprecated item 'cross_crate::lint_stability_fields::Deprecated::inherit': text
+  --> $DIR/lint-stability-fields-deprecated.rs:96:13
+   |
+LL |             inherit: 1,
+   |             ^^^^^^^^^^
+
+error: use of deprecated item 'cross_crate::lint_stability_fields::Deprecated::override1': text
+  --> $DIR/lint-stability-fields-deprecated.rs:98:13
+   |
+LL |             override1: 2,
+   |             ^^^^^^^^^^^^
+
+error: use of deprecated item 'cross_crate::lint_stability_fields::Deprecated::override2': text
+  --> $DIR/lint-stability-fields-deprecated.rs:100:13
+   |
+LL |             override2: 3,
+   |             ^^^^^^^^^^^^
+
+error: use of deprecated item 'cross_crate::lint_stability_fields::Deprecated::inherit': text
+  --> $DIR/lint-stability-fields-deprecated.rs:104:17
+   |
+LL |         let _ = x.inherit;
+   |                 ^^^^^^^^^
+
+error: use of deprecated item 'cross_crate::lint_stability_fields::Deprecated::override1': text
+  --> $DIR/lint-stability-fields-deprecated.rs:106:17
+   |
+LL |         let _ = x.override1;
+   |                 ^^^^^^^^^^^
+
+error: use of deprecated item 'cross_crate::lint_stability_fields::Deprecated::override2': text
+  --> $DIR/lint-stability-fields-deprecated.rs:108:17
+   |
+LL |         let _ = x.override2;
+   |                 ^^^^^^^^^^^
+
+error: use of deprecated item 'cross_crate::lint_stability_fields::Deprecated::inherit': text
+  --> $DIR/lint-stability-fields-deprecated.rs:113:13
+   |
+LL |             inherit: _,
+   |             ^^^^^^^^^^
+
+error: use of deprecated item 'cross_crate::lint_stability_fields::Deprecated::override1': text
+  --> $DIR/lint-stability-fields-deprecated.rs:115:13
+   |
+LL |             override1: _,
+   |             ^^^^^^^^^^^^
+
+error: use of deprecated item 'cross_crate::lint_stability_fields::Deprecated::override2': text
+  --> $DIR/lint-stability-fields-deprecated.rs:117:13
+   |
+LL |             override2: _
+   |             ^^^^^^^^^^^^
+
+error: use of deprecated item 'cross_crate::lint_stability_fields::Deprecated2::0': text
+  --> $DIR/lint-stability-fields-deprecated.rs:129:17
+   |
+LL |         let _ = x.0;
+   |                 ^^^
+
+error: use of deprecated item 'cross_crate::lint_stability_fields::Deprecated2::1': text
+  --> $DIR/lint-stability-fields-deprecated.rs:131:17
+   |
+LL |         let _ = x.1;
+   |                 ^^^
+
+error: use of deprecated item 'cross_crate::lint_stability_fields::Deprecated2::2': text
+  --> $DIR/lint-stability-fields-deprecated.rs:133:17
+   |
+LL |         let _ = x.2;
+   |                 ^^^
+
+error: use of deprecated item 'cross_crate::lint_stability_fields::Deprecated2::0': text
+  --> $DIR/lint-stability-fields-deprecated.rs:138:14
+   |
+LL |             (_,
+   |              ^
+
+error: use of deprecated item 'cross_crate::lint_stability_fields::Deprecated2::1': text
+  --> $DIR/lint-stability-fields-deprecated.rs:140:14
+   |
+LL |              _,
+   |              ^
+
+error: use of deprecated item 'cross_crate::lint_stability_fields::Deprecated2::2': text
+  --> $DIR/lint-stability-fields-deprecated.rs:142:14
+   |
+LL |              _)
+   |              ^
+
+error: use of deprecated item 'this_crate::Stable::override2': text
+  --> $DIR/lint-stability-fields-deprecated.rs:205:13
+   |
+LL |             override2: 3,
+   |             ^^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::Stable::override2': text
+  --> $DIR/lint-stability-fields-deprecated.rs:211:17
+   |
+LL |         let _ = x.override2;
+   |                 ^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::Stable::override2': text
+  --> $DIR/lint-stability-fields-deprecated.rs:217:13
+   |
+LL |             override2: _
+   |             ^^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::Stable2::2': text
+  --> $DIR/lint-stability-fields-deprecated.rs:227:17
+   |
+LL |         let _ = x.2;
+   |                 ^^^
+
+error: use of deprecated item 'this_crate::Stable2::2': text
+  --> $DIR/lint-stability-fields-deprecated.rs:232:20
+   |
+LL |                    _)
+   |                    ^
+
+error: use of deprecated item 'this_crate::Unstable::override2': text
+  --> $DIR/lint-stability-fields-deprecated.rs:242:13
+   |
+LL |             override2: 3,
+   |             ^^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::Unstable::override2': text
+  --> $DIR/lint-stability-fields-deprecated.rs:248:17
+   |
+LL |         let _ = x.override2;
+   |                 ^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::Unstable::override2': text
+  --> $DIR/lint-stability-fields-deprecated.rs:254:13
+   |
+LL |             override2: _
+   |             ^^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::Unstable2::2': text
+  --> $DIR/lint-stability-fields-deprecated.rs:267:17
+   |
+LL |         let _ = x.2;
+   |                 ^^^
+
+error: use of deprecated item 'this_crate::Unstable2::2': text
+  --> $DIR/lint-stability-fields-deprecated.rs:273:14
+   |
+LL |              _)
+   |              ^
+
+error: use of deprecated item 'this_crate::Deprecated::inherit': text
+  --> $DIR/lint-stability-fields-deprecated.rs:283:13
+   |
+LL |             inherit: 1,
+   |             ^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::Deprecated::override1': text
+  --> $DIR/lint-stability-fields-deprecated.rs:285:13
+   |
+LL |             override1: 2,
+   |             ^^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::Deprecated::override2': text
+  --> $DIR/lint-stability-fields-deprecated.rs:287:13
+   |
+LL |             override2: 3,
+   |             ^^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::Deprecated::inherit': text
+  --> $DIR/lint-stability-fields-deprecated.rs:291:17
+   |
+LL |         let _ = x.inherit;
+   |                 ^^^^^^^^^
+
+error: use of deprecated item 'this_crate::Deprecated::override1': text
+  --> $DIR/lint-stability-fields-deprecated.rs:293:17
+   |
+LL |         let _ = x.override1;
+   |                 ^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::Deprecated::override2': text
+  --> $DIR/lint-stability-fields-deprecated.rs:295:17
+   |
+LL |         let _ = x.override2;
+   |                 ^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::Deprecated::inherit': text
+  --> $DIR/lint-stability-fields-deprecated.rs:300:13
+   |
+LL |             inherit: _,
+   |             ^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::Deprecated::override1': text
+  --> $DIR/lint-stability-fields-deprecated.rs:302:13
+   |
+LL |             override1: _,
+   |             ^^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::Deprecated::override2': text
+  --> $DIR/lint-stability-fields-deprecated.rs:304:13
+   |
+LL |             override2: _
+   |             ^^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::Deprecated2::0': text
+  --> $DIR/lint-stability-fields-deprecated.rs:316:17
+   |
+LL |         let _ = x.0;
+   |                 ^^^
+
+error: use of deprecated item 'this_crate::Deprecated2::1': text
+  --> $DIR/lint-stability-fields-deprecated.rs:318:17
+   |
+LL |         let _ = x.1;
+   |                 ^^^
+
+error: use of deprecated item 'this_crate::Deprecated2::2': text
+  --> $DIR/lint-stability-fields-deprecated.rs:320:17
+   |
+LL |         let _ = x.2;
+   |                 ^^^
+
+error: use of deprecated item 'this_crate::Deprecated2::0': text
+  --> $DIR/lint-stability-fields-deprecated.rs:325:14
+   |
+LL |             (_,
+   |              ^
+
+error: use of deprecated item 'this_crate::Deprecated2::1': text
+  --> $DIR/lint-stability-fields-deprecated.rs:327:14
+   |
+LL |              _,
+   |              ^
+
+error: use of deprecated item 'this_crate::Deprecated2::2': text
+  --> $DIR/lint-stability-fields-deprecated.rs:329:14
+   |
+LL |              _)
+   |              ^
+
+error: aborting due to 62 previous errors
+
diff --git a/src/test/ui/lint/lint-stability-fields.rs b/src/test/ui/lint/lint-stability-fields.rs
new file mode 100644
index 0000000..9be8710
--- /dev/null
+++ b/src/test/ui/lint/lint-stability-fields.rs
@@ -0,0 +1,283 @@
+// aux-build:lint_stability_fields.rs
+#![allow(deprecated)]
+#![allow(dead_code)]
+#![feature(staged_api)]
+
+#![stable(feature = "rust1", since = "1.0.0")]
+
+mod cross_crate {
+    extern crate lint_stability_fields;
+
+    mod reexport {
+        #[stable(feature = "rust1", since = "1.0.0")]
+        pub use super::lint_stability_fields::*;
+    }
+
+    use self::lint_stability_fields::*;
+
+    pub fn foo() {
+        let x = Stable {
+            inherit: 1,
+            override1: 2, //~ ERROR use of unstable
+            override2: 3, //~ ERROR use of unstable
+        };
+
+        let _ = x.inherit;
+        let _ = x.override1; //~ ERROR use of unstable
+        let _ = x.override2; //~ ERROR use of unstable
+
+        let Stable {
+            inherit: _,
+            override1: _, //~ ERROR use of unstable
+            override2: _ //~ ERROR use of unstable
+        } = x;
+        // all fine
+        let Stable { .. } = x;
+
+        let x = Stable2(1, 2, 3);
+
+        let _ = x.0;
+        let _ = x.1; //~ ERROR use of unstable
+        let _ = x.2; //~ ERROR use of unstable
+
+        let Stable2(_,
+                   _, //~ ERROR use of unstable
+                   _) //~ ERROR use of unstable
+            = x;
+        // all fine
+        let Stable2(..) = x;
+
+
+        let x = Unstable { //~ ERROR use of unstable
+            inherit: 1, //~ ERROR use of unstable
+            override1: 2,
+            override2: 3, //~ ERROR use of unstable
+        };
+
+        let _ = x.inherit; //~ ERROR use of unstable
+        let _ = x.override1;
+        let _ = x.override2; //~ ERROR use of unstable
+
+        let Unstable { //~ ERROR use of unstable
+            inherit: _, //~ ERROR use of unstable
+            override1: _,
+            override2: _ //~ ERROR use of unstable
+        } = x;
+
+        let Unstable  //~ ERROR use of unstable
+            // the patterns are all fine:
+            { .. } = x;
+
+        // Unstable items are still unstable even when used through a stable "pub use".
+        let x = reexport::Unstable2(1, 2, 3); //~ ERROR use of unstable
+
+        let x = Unstable2(1, 2, 3); //~ ERROR use of unstable
+
+        let _ = x.0; //~ ERROR use of unstable
+        let _ = x.1;
+        let _ = x.2; //~ ERROR use of unstable
+
+        let Unstable2  //~ ERROR use of unstable
+            (_, //~ ERROR use of unstable
+             _,
+             _) //~ ERROR use of unstable
+            = x;
+        let Unstable2 //~ ERROR use of unstable
+            // the patterns are all fine:
+            (..) = x;
+
+
+        let x = Deprecated { //~ ERROR use of unstable
+            inherit: 1, //~ ERROR use of unstable
+            override1: 2,
+            override2: 3, //~ ERROR use of unstable
+        };
+
+        let _ = x.inherit; //~ ERROR use of unstable
+        let _ = x.override1;
+        let _ = x.override2; //~ ERROR use of unstable
+
+        let Deprecated { //~ ERROR use of unstable
+            inherit: _, //~ ERROR use of unstable
+            override1: _,
+            override2: _ //~ ERROR use of unstable
+        } = x;
+
+        let Deprecated //~ ERROR use of unstable
+            // the patterns are all fine:
+            { .. } = x;
+
+        let x = Deprecated2(1, 2, 3); //~ ERROR use of unstable
+
+        let _ = x.0; //~ ERROR use of unstable
+        let _ = x.1;
+        let _ = x.2; //~ ERROR use of unstable
+
+        let Deprecated2 //~ ERROR use of unstable
+            (_, //~ ERROR use of unstable
+             _,
+             _) //~ ERROR use of unstable
+            = x;
+        let Deprecated2 //~ ERROR use of unstable
+            // the patterns are all fine:
+            (..) = x;
+    }
+}
+
+mod this_crate {
+    #[stable(feature = "rust1", since = "1.0.0")]
+    struct Stable {
+        inherit: u8,
+        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        override1: u8,
+        #[rustc_deprecated(since = "1.0.0", reason = "text")]
+        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        override2: u8,
+    }
+
+    #[stable(feature = "rust1", since = "1.0.0")]
+    struct Stable2(u8,
+                   #[stable(feature = "rust1", since = "1.0.0")] u8,
+                   #[unstable(feature = "unstable_test_feature", issue = "0")]
+                   #[rustc_deprecated(since = "1.0.0", reason = "text")] u8);
+
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    struct Unstable {
+        inherit: u8,
+        #[stable(feature = "rust1", since = "1.0.0")]
+        override1: u8,
+        #[rustc_deprecated(since = "1.0.0", reason = "text")]
+        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        override2: u8,
+    }
+
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    struct Unstable2(u8,
+                     #[stable(feature = "rust1", since = "1.0.0")] u8,
+                     #[unstable(feature = "unstable_test_feature", issue = "0")]
+                     #[rustc_deprecated(since = "1.0.0", reason = "text")] u8);
+
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    struct Deprecated {
+        inherit: u8,
+        #[stable(feature = "rust1", since = "1.0.0")]
+        override1: u8,
+        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        override2: u8,
+    }
+
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    struct Deprecated2(u8,
+                       #[stable(feature = "rust1", since = "1.0.0")] u8,
+                       #[unstable(feature = "unstable_test_feature", issue = "0")] u8);
+
+    pub fn foo() {
+        let x = Stable {
+            inherit: 1,
+            override1: 2,
+            override2: 3,
+        };
+
+        let _ = x.inherit;
+        let _ = x.override1;
+        let _ = x.override2;
+
+        let Stable {
+            inherit: _,
+            override1: _,
+            override2: _
+        } = x;
+        // all fine
+        let Stable { .. } = x;
+
+        let x = Stable2(1, 2, 3);
+
+        let _ = x.0;
+        let _ = x.1;
+        let _ = x.2;
+
+        let Stable2(_,
+                   _,
+                   _)
+            = x;
+        // all fine
+        let Stable2(..) = x;
+
+
+        let x = Unstable {
+            inherit: 1,
+            override1: 2,
+            override2: 3,
+        };
+
+        let _ = x.inherit;
+        let _ = x.override1;
+        let _ = x.override2;
+
+        let Unstable {
+            inherit: _,
+            override1: _,
+            override2: _
+        } = x;
+
+        let Unstable
+            // the patterns are all fine:
+            { .. } = x;
+
+
+        let x = Unstable2(1, 2, 3);
+
+        let _ = x.0;
+        let _ = x.1;
+        let _ = x.2;
+
+        let Unstable2
+            (_,
+             _,
+             _)
+            = x;
+        let Unstable2
+            // the patterns are all fine:
+            (..) = x;
+
+
+        let x = Deprecated {
+            inherit: 1,
+            override1: 2,
+            override2: 3,
+        };
+
+        let _ = x.inherit;
+        let _ = x.override1;
+        let _ = x.override2;
+
+        let Deprecated {
+            inherit: _,
+            override1: _,
+            override2: _
+        } = x;
+
+        let Deprecated
+            // the patterns are all fine:
+            { .. } = x;
+
+        let x = Deprecated2(1, 2, 3);
+
+        let _ = x.0;
+        let _ = x.1;
+        let _ = x.2;
+
+        let Deprecated2
+            (_,
+             _,
+             _)
+            = x;
+        let Deprecated2
+            // the patterns are all fine:
+            (..) = x;
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/lint/lint-stability-fields.stderr b/src/test/ui/lint/lint-stability-fields.stderr
new file mode 100644
index 0000000..e80e745
--- /dev/null
+++ b/src/test/ui/lint/lint-stability-fields.stderr
@@ -0,0 +1,347 @@
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-fields.rs:51:17
+   |
+LL |         let x = Unstable {
+   |                 ^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-fields.rs:61:13
+   |
+LL |         let Unstable {
+   |             ^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-fields.rs:67:13
+   |
+LL |         let Unstable
+   |             ^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-fields.rs:72:17
+   |
+LL |         let x = reexport::Unstable2(1, 2, 3);
+   |                 ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-fields.rs:74:17
+   |
+LL |         let x = Unstable2(1, 2, 3);
+   |                 ^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-fields.rs:80:13
+   |
+LL |         let Unstable2
+   |             ^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-fields.rs:85:13
+   |
+LL |         let Unstable2
+   |             ^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-fields.rs:90:17
+   |
+LL |         let x = Deprecated {
+   |                 ^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-fields.rs:100:13
+   |
+LL |         let Deprecated {
+   |             ^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-fields.rs:106:13
+   |
+LL |         let Deprecated
+   |             ^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-fields.rs:110:17
+   |
+LL |         let x = Deprecated2(1, 2, 3);
+   |                 ^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-fields.rs:116:13
+   |
+LL |         let Deprecated2
+   |             ^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-fields.rs:121:13
+   |
+LL |         let Deprecated2
+   |             ^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-fields.rs:21:13
+   |
+LL |             override1: 2,
+   |             ^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-fields.rs:22:13
+   |
+LL |             override2: 3,
+   |             ^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-fields.rs:26:17
+   |
+LL |         let _ = x.override1;
+   |                 ^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-fields.rs:27:17
+   |
+LL |         let _ = x.override2;
+   |                 ^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-fields.rs:31:13
+   |
+LL |             override1: _,
+   |             ^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-fields.rs:32:13
+   |
+LL |             override2: _
+   |             ^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-fields.rs:40:17
+   |
+LL |         let _ = x.1;
+   |                 ^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-fields.rs:41:17
+   |
+LL |         let _ = x.2;
+   |                 ^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-fields.rs:44:20
+   |
+LL |                    _,
+   |                    ^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-fields.rs:45:20
+   |
+LL |                    _)
+   |                    ^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-fields.rs:52:13
+   |
+LL |             inherit: 1,
+   |             ^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-fields.rs:54:13
+   |
+LL |             override2: 3,
+   |             ^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-fields.rs:57:17
+   |
+LL |         let _ = x.inherit;
+   |                 ^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-fields.rs:59:17
+   |
+LL |         let _ = x.override2;
+   |                 ^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-fields.rs:62:13
+   |
+LL |             inherit: _,
+   |             ^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-fields.rs:64:13
+   |
+LL |             override2: _
+   |             ^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-fields.rs:76:17
+   |
+LL |         let _ = x.0;
+   |                 ^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-fields.rs:78:17
+   |
+LL |         let _ = x.2;
+   |                 ^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-fields.rs:81:14
+   |
+LL |             (_,
+   |              ^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-fields.rs:83:14
+   |
+LL |              _)
+   |              ^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-fields.rs:91:13
+   |
+LL |             inherit: 1,
+   |             ^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-fields.rs:93:13
+   |
+LL |             override2: 3,
+   |             ^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-fields.rs:96:17
+   |
+LL |         let _ = x.inherit;
+   |                 ^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-fields.rs:98:17
+   |
+LL |         let _ = x.override2;
+   |                 ^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-fields.rs:101:13
+   |
+LL |             inherit: _,
+   |             ^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-fields.rs:103:13
+   |
+LL |             override2: _
+   |             ^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-fields.rs:112:17
+   |
+LL |         let _ = x.0;
+   |                 ^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-fields.rs:114:17
+   |
+LL |         let _ = x.2;
+   |                 ^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-fields.rs:117:14
+   |
+LL |             (_,
+   |              ^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability-fields.rs:119:14
+   |
+LL |              _)
+   |              ^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error: aborting due to 43 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/lint/lint-stability.rs b/src/test/ui/lint/lint-stability.rs
new file mode 100644
index 0000000..3e4a387
--- /dev/null
+++ b/src/test/ui/lint/lint-stability.rs
@@ -0,0 +1,454 @@
+// aux-build:lint_stability.rs
+// aux-build:inherited_stability.rs
+// aux-build:stability_cfg1.rs
+// aux-build:stability-cfg2.rs
+
+#![allow(deprecated)]
+#![allow(dead_code)]
+#![feature(staged_api)]
+
+#![stable(feature = "rust1", since = "1.0.0")]
+
+#[macro_use]
+extern crate lint_stability;
+
+mod cross_crate {
+    extern crate stability_cfg1;
+    extern crate stability_cfg2; //~ ERROR use of unstable library feature
+
+    use lint_stability::*;
+
+    fn test() {
+        type Foo = MethodTester;
+        let foo = MethodTester;
+
+        deprecated();
+        foo.method_deprecated();
+        Foo::method_deprecated(&foo);
+        <Foo>::method_deprecated(&foo);
+        foo.trait_deprecated();
+        Trait::trait_deprecated(&foo);
+        <Foo>::trait_deprecated(&foo);
+        <Foo as Trait>::trait_deprecated(&foo);
+
+        deprecated_text();
+        foo.method_deprecated_text();
+        Foo::method_deprecated_text(&foo);
+        <Foo>::method_deprecated_text(&foo);
+        foo.trait_deprecated_text();
+        Trait::trait_deprecated_text(&foo);
+        <Foo>::trait_deprecated_text(&foo);
+        <Foo as Trait>::trait_deprecated_text(&foo);
+
+        deprecated_future(); // Fine; no error.
+
+        deprecated_unstable();
+        //~^ ERROR use of unstable library feature
+        Trait::trait_deprecated_unstable(&foo);
+        //~^ ERROR use of unstable library feature
+        <Foo as Trait>::trait_deprecated_unstable(&foo);
+        //~^ ERROR use of unstable library feature
+
+        deprecated_unstable_text();
+        //~^ ERROR use of unstable library feature
+        Trait::trait_deprecated_unstable_text(&foo);
+        //~^ ERROR use of unstable library feature
+        <Foo as Trait>::trait_deprecated_unstable_text(&foo);
+        //~^ ERROR use of unstable library feature
+
+        unstable(); //~ ERROR use of unstable library feature
+        Trait::trait_unstable(&foo); //~ ERROR use of unstable library feature
+        <Foo as Trait>::trait_unstable(&foo); //~ ERROR use of unstable library feature
+
+        unstable_text();
+        //~^ ERROR use of unstable library feature 'unstable_test_feature': text
+        Trait::trait_unstable_text(&foo);
+        //~^ ERROR use of unstable library feature 'unstable_test_feature': text
+        <Foo as Trait>::trait_unstable_text(&foo);
+        //~^ ERROR use of unstable library feature 'unstable_test_feature': text
+
+        stable();
+        foo.method_stable();
+        Foo::method_stable(&foo);
+        <Foo>::method_stable(&foo);
+        foo.trait_stable();
+        Trait::trait_stable(&foo);
+        <Foo>::trait_stable(&foo);
+        <Foo as Trait>::trait_stable(&foo);
+
+        stable_text();
+        foo.method_stable_text();
+        Foo::method_stable_text(&foo);
+        <Foo>::method_stable_text(&foo);
+        foo.trait_stable_text();
+        Trait::trait_stable_text(&foo);
+        <Foo>::trait_stable_text(&foo);
+        <Foo as Trait>::trait_stable_text(&foo);
+
+        struct S1<T: TraitWithAssociatedTypes>(T::TypeUnstable);
+        //~^ ERROR use of unstable library feature
+        struct S2<T: TraitWithAssociatedTypes>(T::TypeDeprecated);
+        type A = TraitWithAssociatedTypes<
+            TypeUnstable = u8, //~ ERROR use of unstable library feature
+            TypeDeprecated = u16,
+        >;
+
+        let _ = DeprecatedStruct {
+            i: 0
+        };
+        let _ = DeprecatedUnstableStruct {
+            //~^ ERROR use of unstable library feature
+            i: 0
+        };
+        let _ = UnstableStruct { i: 0 }; //~ ERROR use of unstable library feature
+        let _ = StableStruct { i: 0 };
+
+        let _ = DeprecatedUnitStruct;
+        let _ = DeprecatedUnstableUnitStruct;
+        //~^ ERROR use of unstable library feature
+        let _ = UnstableUnitStruct; //~ ERROR use of unstable library feature
+        let _ = StableUnitStruct;
+
+        let _ = Enum::DeprecatedVariant;
+        let _ = Enum::DeprecatedUnstableVariant;
+        //~^ ERROR use of unstable library feature
+        let _ = Enum::UnstableVariant; //~ ERROR use of unstable library feature
+        let _ = Enum::StableVariant;
+
+        let _ = DeprecatedTupleStruct (1);
+        let _ = DeprecatedUnstableTupleStruct (1);
+        //~^ ERROR use of unstable library feature
+        let _ = UnstableTupleStruct (1); //~ ERROR use of unstable library feature
+        let _ = StableTupleStruct (1);
+
+        // At the moment, the lint checker only checks stability in
+        // in the arguments of macros.
+        // Eventually, we will want to lint the contents of the
+        // macro in the module *defining* it. Also, stability levels
+        // on macros themselves are not yet linted.
+        macro_test_arg!(deprecated_text());
+        macro_test_arg!(deprecated_unstable_text());
+        //~^ ERROR use of unstable library feature
+        macro_test_arg!(macro_test_arg!(deprecated_text()));
+    }
+
+    fn test_method_param<Foo: Trait>(foo: Foo) {
+        foo.trait_deprecated();
+        Trait::trait_deprecated(&foo);
+        <Foo>::trait_deprecated(&foo);
+        <Foo as Trait>::trait_deprecated(&foo);
+        foo.trait_deprecated_text();
+        Trait::trait_deprecated_text(&foo);
+        <Foo>::trait_deprecated_text(&foo);
+        <Foo as Trait>::trait_deprecated_text(&foo);
+        Trait::trait_deprecated_unstable(&foo);
+        //~^ ERROR use of unstable library feature
+        <Foo as Trait>::trait_deprecated_unstable(&foo);
+        //~^ ERROR use of unstable library feature
+        Trait::trait_deprecated_unstable_text(&foo);
+        //~^ ERROR use of unstable library feature
+        <Foo as Trait>::trait_deprecated_unstable_text(&foo);
+        //~^ ERROR use of unstable library feature
+        Trait::trait_unstable(&foo); //~ ERROR use of unstable library feature
+        <Foo as Trait>::trait_unstable(&foo); //~ ERROR use of unstable library feature
+        Trait::trait_unstable_text(&foo);
+        //~^ ERROR use of unstable library feature 'unstable_test_feature': text
+        <Foo as Trait>::trait_unstable_text(&foo);
+        //~^ ERROR use of unstable library feature 'unstable_test_feature': text
+        foo.trait_stable();
+        Trait::trait_stable(&foo);
+        <Foo>::trait_stable(&foo);
+        <Foo as Trait>::trait_stable(&foo);
+    }
+
+    fn test_method_object(foo: &Trait) {
+        foo.trait_deprecated();
+        foo.trait_deprecated_text();
+        foo.trait_stable();
+    }
+
+    struct S;
+
+    impl UnstableTrait for S { } //~ ERROR use of unstable library feature
+    impl DeprecatedTrait for S {}
+    trait LocalTrait : UnstableTrait { } //~ ERROR use of unstable library feature
+    trait LocalTrait2 : DeprecatedTrait { }
+
+    impl Trait for S {
+        fn trait_stable(&self) {}
+        fn trait_unstable(&self) {} //~ ERROR use of unstable library feature
+    }
+}
+
+mod inheritance {
+    extern crate inherited_stability; //~ ERROR use of unstable library feature
+    use self::inherited_stability::*; //~ ERROR use of unstable library feature
+
+    fn test_inheritance() {
+        unstable(); //~ ERROR use of unstable library feature
+        stable();
+
+        stable_mod::unstable(); //~ ERROR use of unstable library feature
+        stable_mod::stable();
+
+        unstable_mod::deprecated();
+        unstable_mod::unstable(); //~ ERROR use of unstable library feature
+
+        let _ = Unstable::UnstableVariant; //~ ERROR use of unstable library feature
+        let _ = Unstable::StableVariant;
+
+        let x: usize = 0;
+        x.stable();
+    }
+}
+
+mod this_crate {
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    pub fn deprecated() {}
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    pub fn deprecated_text() {}
+
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_deprecated(since = "99.99.99", reason = "text")]
+    pub fn deprecated_future() {}
+
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    pub fn unstable() {}
+    #[unstable(feature = "unstable_test_feature", reason = "text", issue = "0")]
+    pub fn unstable_text() {}
+
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn stable() {}
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn stable_text() {}
+
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub struct MethodTester;
+
+    impl MethodTester {
+        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        #[rustc_deprecated(since = "1.0.0", reason = "text")]
+        pub fn method_deprecated(&self) {}
+        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        #[rustc_deprecated(since = "1.0.0", reason = "text")]
+        pub fn method_deprecated_text(&self) {}
+
+        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        pub fn method_unstable(&self) {}
+        #[unstable(feature = "unstable_test_feature", reason = "text", issue = "0")]
+        pub fn method_unstable_text(&self) {}
+
+        #[stable(feature = "rust1", since = "1.0.0")]
+        pub fn method_stable(&self) {}
+        #[stable(feature = "rust1", since = "1.0.0")]
+        pub fn method_stable_text(&self) {}
+    }
+
+    pub trait Trait {
+        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        #[rustc_deprecated(since = "1.0.0", reason = "text")]
+        fn trait_deprecated(&self) {}
+        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        #[rustc_deprecated(since = "1.0.0", reason = "text")]
+        fn trait_deprecated_text(&self) {}
+
+        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        fn trait_unstable(&self) {}
+        #[unstable(feature = "unstable_test_feature", reason = "text", issue = "0")]
+        fn trait_unstable_text(&self) {}
+
+        #[stable(feature = "rust1", since = "1.0.0")]
+        fn trait_stable(&self) {}
+        #[stable(feature = "rust1", since = "1.0.0")]
+        fn trait_stable_text(&self) {}
+    }
+
+    impl Trait for MethodTester {}
+
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    pub struct DeprecatedStruct {
+        #[stable(feature = "stable_test_feature", since = "1.0.0")] i: isize
+    }
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    pub struct UnstableStruct {
+        #[stable(feature = "stable_test_feature", since = "1.0.0")] i: isize
+    }
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub struct StableStruct {
+        #[stable(feature = "stable_test_feature", since = "1.0.0")] i: isize
+    }
+
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    pub struct DeprecatedUnitStruct;
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    pub struct UnstableUnitStruct;
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub struct StableUnitStruct;
+
+    pub enum Enum {
+        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        #[rustc_deprecated(since = "1.0.0", reason = "text")]
+        DeprecatedVariant,
+        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        UnstableVariant,
+
+        #[stable(feature = "rust1", since = "1.0.0")]
+        StableVariant,
+    }
+
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    pub struct DeprecatedTupleStruct(isize);
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    pub struct UnstableTupleStruct(isize);
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub struct StableTupleStruct(isize);
+
+    fn test() {
+        // Only the deprecated cases of the following should generate
+        // errors, because other stability attributes now have meaning
+        // only *across* crates, not within a single crate.
+
+        type Foo = MethodTester;
+        let foo = MethodTester;
+
+        deprecated();
+        foo.method_deprecated();
+        Foo::method_deprecated(&foo);
+        <Foo>::method_deprecated(&foo);
+        foo.trait_deprecated();
+        Trait::trait_deprecated(&foo);
+        <Foo>::trait_deprecated(&foo);
+        <Foo as Trait>::trait_deprecated(&foo);
+
+        deprecated_text();
+        foo.method_deprecated_text();
+        Foo::method_deprecated_text(&foo);
+        <Foo>::method_deprecated_text(&foo);
+        foo.trait_deprecated_text();
+        Trait::trait_deprecated_text(&foo);
+        <Foo>::trait_deprecated_text(&foo);
+        <Foo as Trait>::trait_deprecated_text(&foo);
+
+        deprecated_future();
+
+        unstable();
+        foo.method_unstable();
+        Foo::method_unstable(&foo);
+        <Foo>::method_unstable(&foo);
+        foo.trait_unstable();
+        Trait::trait_unstable(&foo);
+        <Foo>::trait_unstable(&foo);
+        <Foo as Trait>::trait_unstable(&foo);
+
+        unstable_text();
+        foo.method_unstable_text();
+        Foo::method_unstable_text(&foo);
+        <Foo>::method_unstable_text(&foo);
+        foo.trait_unstable_text();
+        Trait::trait_unstable_text(&foo);
+        <Foo>::trait_unstable_text(&foo);
+        <Foo as Trait>::trait_unstable_text(&foo);
+
+        stable();
+        foo.method_stable();
+        Foo::method_stable(&foo);
+        <Foo>::method_stable(&foo);
+        foo.trait_stable();
+        Trait::trait_stable(&foo);
+        <Foo>::trait_stable(&foo);
+        <Foo as Trait>::trait_stable(&foo);
+
+        stable_text();
+        foo.method_stable_text();
+        Foo::method_stable_text(&foo);
+        <Foo>::method_stable_text(&foo);
+        foo.trait_stable_text();
+        Trait::trait_stable_text(&foo);
+        <Foo>::trait_stable_text(&foo);
+        <Foo as Trait>::trait_stable_text(&foo);
+
+        let _ = DeprecatedStruct {
+            i: 0
+        };
+        let _ = UnstableStruct { i: 0 };
+        let _ = StableStruct { i: 0 };
+
+        let _ = DeprecatedUnitStruct;
+        let _ = UnstableUnitStruct;
+        let _ = StableUnitStruct;
+
+        let _ = Enum::DeprecatedVariant;
+        let _ = Enum::UnstableVariant;
+        let _ = Enum::StableVariant;
+
+        let _ = DeprecatedTupleStruct (1);
+        let _ = UnstableTupleStruct (1);
+        let _ = StableTupleStruct (1);
+    }
+
+    fn test_method_param<Foo: Trait>(foo: Foo) {
+        foo.trait_deprecated();
+        Trait::trait_deprecated(&foo);
+        <Foo>::trait_deprecated(&foo);
+        <Foo as Trait>::trait_deprecated(&foo);
+        foo.trait_deprecated_text();
+        Trait::trait_deprecated_text(&foo);
+        <Foo>::trait_deprecated_text(&foo);
+        <Foo as Trait>::trait_deprecated_text(&foo);
+        foo.trait_unstable();
+        Trait::trait_unstable(&foo);
+        <Foo>::trait_unstable(&foo);
+        <Foo as Trait>::trait_unstable(&foo);
+        foo.trait_unstable_text();
+        Trait::trait_unstable_text(&foo);
+        <Foo>::trait_unstable_text(&foo);
+        <Foo as Trait>::trait_unstable_text(&foo);
+        foo.trait_stable();
+        Trait::trait_stable(&foo);
+        <Foo>::trait_stable(&foo);
+        <Foo as Trait>::trait_stable(&foo);
+    }
+
+    fn test_method_object(foo: &Trait) {
+        foo.trait_deprecated();
+        foo.trait_deprecated_text();
+        foo.trait_unstable();
+        foo.trait_unstable_text();
+        foo.trait_stable();
+    }
+
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    fn test_fn_body() {
+        fn fn_in_body() {}
+        fn_in_body();
+    }
+
+    impl MethodTester {
+        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        #[rustc_deprecated(since = "1.0.0", reason = "text")]
+        fn test_method_body(&self) {
+            fn fn_in_body() {}
+            fn_in_body();
+        }
+    }
+
+    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    pub trait DeprecatedTrait {
+        fn dummy(&self) { }
+    }
+
+    struct S;
+
+    impl DeprecatedTrait for S { }
+
+    trait LocalTrait : DeprecatedTrait { }
+}
+
+fn main() {}
diff --git a/src/test/ui/lint/lint-stability.stderr b/src/test/ui/lint/lint-stability.stderr
new file mode 100644
index 0000000..dd7f718
--- /dev/null
+++ b/src/test/ui/lint/lint-stability.stderr
@@ -0,0 +1,331 @@
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability.rs:17:5
+   |
+LL |     extern crate stability_cfg2;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability.rs:45:9
+   |
+LL |         deprecated_unstable();
+   |         ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability.rs:47:9
+   |
+LL |         Trait::trait_deprecated_unstable(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability.rs:49:9
+   |
+LL |         <Foo as Trait>::trait_deprecated_unstable(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability.rs:52:9
+   |
+LL |         deprecated_unstable_text();
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability.rs:54:9
+   |
+LL |         Trait::trait_deprecated_unstable_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability.rs:56:9
+   |
+LL |         <Foo as Trait>::trait_deprecated_unstable_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability.rs:59:9
+   |
+LL |         unstable();
+   |         ^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability.rs:60:9
+   |
+LL |         Trait::trait_unstable(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability.rs:61:9
+   |
+LL |         <Foo as Trait>::trait_unstable(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature': text
+  --> $DIR/lint-stability.rs:63:9
+   |
+LL |         unstable_text();
+   |         ^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature': text
+  --> $DIR/lint-stability.rs:65:9
+   |
+LL |         Trait::trait_unstable_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature': text
+  --> $DIR/lint-stability.rs:67:9
+   |
+LL |         <Foo as Trait>::trait_unstable_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability.rs:99:17
+   |
+LL |         let _ = DeprecatedUnstableStruct {
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability.rs:103:17
+   |
+LL |         let _ = UnstableStruct { i: 0 };
+   |                 ^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability.rs:107:17
+   |
+LL |         let _ = DeprecatedUnstableUnitStruct;
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability.rs:109:17
+   |
+LL |         let _ = UnstableUnitStruct;
+   |                 ^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability.rs:113:17
+   |
+LL |         let _ = Enum::DeprecatedUnstableVariant;
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability.rs:115:17
+   |
+LL |         let _ = Enum::UnstableVariant;
+   |                 ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability.rs:119:17
+   |
+LL |         let _ = DeprecatedUnstableTupleStruct (1);
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability.rs:121:17
+   |
+LL |         let _ = UnstableTupleStruct (1);
+   |                 ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability.rs:130:25
+   |
+LL |         macro_test_arg!(deprecated_unstable_text());
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability.rs:144:9
+   |
+LL |         Trait::trait_deprecated_unstable(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability.rs:146:9
+   |
+LL |         <Foo as Trait>::trait_deprecated_unstable(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability.rs:148:9
+   |
+LL |         Trait::trait_deprecated_unstable_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability.rs:150:9
+   |
+LL |         <Foo as Trait>::trait_deprecated_unstable_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability.rs:152:9
+   |
+LL |         Trait::trait_unstable(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability.rs:153:9
+   |
+LL |         <Foo as Trait>::trait_unstable(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature': text
+  --> $DIR/lint-stability.rs:154:9
+   |
+LL |         Trait::trait_unstable_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature': text
+  --> $DIR/lint-stability.rs:156:9
+   |
+LL |         <Foo as Trait>::trait_unstable_text(&foo);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability.rs:172:10
+   |
+LL |     impl UnstableTrait for S { }
+   |          ^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability.rs:174:24
+   |
+LL |     trait LocalTrait : UnstableTrait { }
+   |                        ^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability.rs:179:9
+   |
+LL |         fn trait_unstable(&self) {}
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability.rs:184:5
+   |
+LL |     extern crate inherited_stability;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability.rs:185:9
+   |
+LL |     use self::inherited_stability::*;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability.rs:188:9
+   |
+LL |         unstable();
+   |         ^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability.rs:191:9
+   |
+LL |         stable_mod::unstable();
+   |         ^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability.rs:195:9
+   |
+LL |         unstable_mod::unstable();
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability.rs:197:17
+   |
+LL |         let _ = Unstable::UnstableVariant;
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability.rs:88:48
+   |
+LL |         struct S1<T: TraitWithAssociatedTypes>(T::TypeUnstable);
+   |                                                ^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/lint-stability.rs:92:13
+   |
+LL |             TypeUnstable = u8,
+   |             ^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error: aborting due to 41 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/lint/lint-stability2.rs b/src/test/ui/lint/lint-stability2.rs
new file mode 100644
index 0000000..9710d08
--- /dev/null
+++ b/src/test/ui/lint/lint-stability2.rs
@@ -0,0 +1,13 @@
+// aux-build:lint_stability.rs
+// error-pattern: use of deprecated item
+
+#![deny(deprecated)]
+
+#[macro_use]
+extern crate lint_stability;
+
+use lint_stability::*;
+
+fn main() {
+    macro_test!();
+}
diff --git a/src/test/ui/lint/lint-stability2.stderr b/src/test/ui/lint/lint-stability2.stderr
new file mode 100644
index 0000000..6599da5
--- /dev/null
+++ b/src/test/ui/lint/lint-stability2.stderr
@@ -0,0 +1,15 @@
+error: use of deprecated item 'lint_stability::deprecated': text
+  --> $DIR/lint-stability2.rs:12:5
+   |
+LL |     macro_test!();
+   |     ^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/lint-stability2.rs:4:9
+   |
+LL | #![deny(deprecated)]
+   |         ^^^^^^^^^^
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lint/lint-stability3.rs b/src/test/ui/lint/lint-stability3.rs
new file mode 100644
index 0000000..3d2cc68
--- /dev/null
+++ b/src/test/ui/lint/lint-stability3.rs
@@ -0,0 +1,14 @@
+// aux-build:lint_stability.rs
+// error-pattern: use of deprecated item
+
+#![deny(deprecated)]
+#![allow(warnings)]
+
+#[macro_use]
+extern crate lint_stability;
+
+use lint_stability::*;
+
+fn main() {
+    macro_test_arg_nested!(deprecated_text);
+}
diff --git a/src/test/ui/lint/lint-stability3.stderr b/src/test/ui/lint/lint-stability3.stderr
new file mode 100644
index 0000000..84274e6
--- /dev/null
+++ b/src/test/ui/lint/lint-stability3.stderr
@@ -0,0 +1,15 @@
+error: use of deprecated item 'lint_stability::deprecated_text': text
+  --> $DIR/lint-stability3.rs:13:5
+   |
+LL |     macro_test_arg_nested!(deprecated_text);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/lint-stability3.rs:4:9
+   |
+LL | #![deny(deprecated)]
+   |         ^^^^^^^^^^
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lint/lint-type-limits.rs b/src/test/ui/lint/lint-type-limits.rs
new file mode 100644
index 0000000..2b140f8
--- /dev/null
+++ b/src/test/ui/lint/lint-type-limits.rs
@@ -0,0 +1,27 @@
+#![allow(dead_code)]
+
+// compile-flags: -D unused-comparisons
+fn main() { }
+
+fn foo() {
+    let mut i = 100_usize;
+    while i >= 0 { //~ ERROR comparison is useless due to type limits
+        i -= 1;
+    }
+}
+
+fn bar() -> i8 {
+    return 123;
+}
+
+fn bleh() {
+    let u = 42u8;
+    let _ = u > 255; //~ ERROR comparison is useless due to type limits
+    let _ = 255 < u; //~ ERROR comparison is useless due to type limits
+    let _ = u < 0; //~ ERROR comparison is useless due to type limits
+    let _ = 0 > u; //~ ERROR comparison is useless due to type limits
+    let _ = u <= 255; //~ ERROR comparison is useless due to type limits
+    let _ = 255 >= u; //~ ERROR comparison is useless due to type limits
+    let _ = u >= 0; //~ ERROR comparison is useless due to type limits
+    let _ = 0 <= u; //~ ERROR comparison is useless due to type limits
+}
diff --git a/src/test/ui/lint/lint-type-limits.stderr b/src/test/ui/lint/lint-type-limits.stderr
new file mode 100644
index 0000000..71a2b3b
--- /dev/null
+++ b/src/test/ui/lint/lint-type-limits.stderr
@@ -0,0 +1,58 @@
+error: comparison is useless due to type limits
+  --> $DIR/lint-type-limits.rs:8:11
+   |
+LL |     while i >= 0 {
+   |           ^^^^^^
+   |
+   = note: requested on the command line with `-D unused-comparisons`
+
+error: comparison is useless due to type limits
+  --> $DIR/lint-type-limits.rs:19:13
+   |
+LL |     let _ = u > 255;
+   |             ^^^^^^^
+
+error: comparison is useless due to type limits
+  --> $DIR/lint-type-limits.rs:20:13
+   |
+LL |     let _ = 255 < u;
+   |             ^^^^^^^
+
+error: comparison is useless due to type limits
+  --> $DIR/lint-type-limits.rs:21:13
+   |
+LL |     let _ = u < 0;
+   |             ^^^^^
+
+error: comparison is useless due to type limits
+  --> $DIR/lint-type-limits.rs:22:13
+   |
+LL |     let _ = 0 > u;
+   |             ^^^^^
+
+error: comparison is useless due to type limits
+  --> $DIR/lint-type-limits.rs:23:13
+   |
+LL |     let _ = u <= 255;
+   |             ^^^^^^^^
+
+error: comparison is useless due to type limits
+  --> $DIR/lint-type-limits.rs:24:13
+   |
+LL |     let _ = 255 >= u;
+   |             ^^^^^^^^
+
+error: comparison is useless due to type limits
+  --> $DIR/lint-type-limits.rs:25:13
+   |
+LL |     let _ = u >= 0;
+   |             ^^^^^^
+
+error: comparison is useless due to type limits
+  --> $DIR/lint-type-limits.rs:26:13
+   |
+LL |     let _ = 0 <= u;
+   |             ^^^^^^
+
+error: aborting due to 9 previous errors
+
diff --git a/src/test/ui/lint/lint-type-limits2.rs b/src/test/ui/lint/lint-type-limits2.rs
new file mode 100644
index 0000000..c4486e0
--- /dev/null
+++ b/src/test/ui/lint/lint-type-limits2.rs
@@ -0,0 +1,15 @@
+#![allow(dead_code)]
+#![warn(overflowing_literals)]
+
+// compile-flags: -D unused-comparisons
+fn main() { }
+
+
+fn bar() -> i8 {
+    return 123;
+}
+
+fn baz() -> bool {
+    128 > bar() //~ ERROR comparison is useless due to type limits
+                //~| WARN literal out of range for i8
+}
diff --git a/src/test/ui/lint/lint-type-limits2.stderr b/src/test/ui/lint/lint-type-limits2.stderr
new file mode 100644
index 0000000..e7bc407
--- /dev/null
+++ b/src/test/ui/lint/lint-type-limits2.stderr
@@ -0,0 +1,22 @@
+error: comparison is useless due to type limits
+  --> $DIR/lint-type-limits2.rs:13:5
+   |
+LL |     128 > bar()
+   |     ^^^^^^^^^^^
+   |
+   = note: requested on the command line with `-D unused-comparisons`
+
+warning: literal out of range for i8
+  --> $DIR/lint-type-limits2.rs:13:5
+   |
+LL |     128 > bar()
+   |     ^^^
+   |
+note: lint level defined here
+  --> $DIR/lint-type-limits2.rs:2:9
+   |
+LL | #![warn(overflowing_literals)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lint/lint-type-limits3.rs b/src/test/ui/lint/lint-type-limits3.rs
new file mode 100644
index 0000000..a715c69
--- /dev/null
+++ b/src/test/ui/lint/lint-type-limits3.rs
@@ -0,0 +1,13 @@
+#![allow(dead_code)]
+#![warn(overflowing_literals)]
+
+// compile-flags: -D unused-comparisons
+fn main() { }
+
+fn qux() {
+    let mut i = 1i8;
+    while 200 != i { //~ ERROR comparison is useless due to type limits
+                     //~| WARN literal out of range for i8
+        i += 1;
+    }
+}
diff --git a/src/test/ui/lint/lint-type-limits3.stderr b/src/test/ui/lint/lint-type-limits3.stderr
new file mode 100644
index 0000000..742b669
--- /dev/null
+++ b/src/test/ui/lint/lint-type-limits3.stderr
@@ -0,0 +1,22 @@
+error: comparison is useless due to type limits
+  --> $DIR/lint-type-limits3.rs:9:11
+   |
+LL |     while 200 != i {
+   |           ^^^^^^^^
+   |
+   = note: requested on the command line with `-D unused-comparisons`
+
+warning: literal out of range for i8
+  --> $DIR/lint-type-limits3.rs:9:11
+   |
+LL |     while 200 != i {
+   |           ^^^
+   |
+note: lint level defined here
+  --> $DIR/lint-type-limits3.rs:2:9
+   |
+LL | #![warn(overflowing_literals)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lint/lint-type-overflow.rs b/src/test/ui/lint/lint-type-overflow.rs
new file mode 100644
index 0000000..847cdf3
--- /dev/null
+++ b/src/test/ui/lint/lint-type-overflow.rs
@@ -0,0 +1,47 @@
+//
+
+#![deny(overflowing_literals)]
+
+fn test(x: i8) {
+    println!("x {}", x);
+}
+
+#[allow(unused_variables)]
+fn main() {
+    let x1: u8 = 255; // should be OK
+    let x1: u8 = 256; //~ error: literal out of range for u8
+
+    let x1 = 255_u8; // should be OK
+    let x1 = 256_u8; //~ error: literal out of range for u8
+
+    let x2: i8 = -128; // should be OK
+    let x1: i8 = 128; //~ error: literal out of range for i8
+
+    let x3: i8 = -129; //~ error: literal out of range for i8
+    let x3: i8 = -(129); //~ error: literal out of range for i8
+    let x3: i8 = -{129}; //~ error: literal out of range for i8
+
+    test(1000); //~ error: literal out of range for i8
+
+    let x = 128_i8; //~ error: literal out of range for i8
+    let x = 127_i8;
+    let x = -128_i8;
+    let x = -(128_i8);
+    let x = -129_i8; //~ error: literal out of range for i8
+
+    let x: i32 = 2147483647; // should be OK
+    let x = 2147483647_i32; // should be OK
+    let x: i32 = 2147483648; //~ error: literal out of range for i32
+    let x = 2147483648_i32; //~ error: literal out of range for i32
+    let x: i32 = -2147483648; // should be OK
+    let x = -2147483648_i32; // should be OK
+    let x: i32 = -2147483649; //~ error: literal out of range for i32
+    let x = -2147483649_i32; //~ error: literal out of range for i32
+    let x = 2147483648; //~ error: literal out of range for i32
+
+    let x = 9223372036854775808_i64; //~ error: literal out of range for i64
+    let x = -9223372036854775808_i64; // should be OK
+    let x = 18446744073709551615_i64; //~ error: literal out of range for i64
+    let x: i64 = -9223372036854775809; //~ error: literal out of range for i64
+    let x = -9223372036854775809_i64; //~ error: literal out of range for i64
+}
diff --git a/src/test/ui/lint/lint-type-overflow.stderr b/src/test/ui/lint/lint-type-overflow.stderr
new file mode 100644
index 0000000..9da0074
--- /dev/null
+++ b/src/test/ui/lint/lint-type-overflow.stderr
@@ -0,0 +1,116 @@
+error: literal out of range for u8
+  --> $DIR/lint-type-overflow.rs:12:18
+   |
+LL |     let x1: u8 = 256;
+   |                  ^^^
+   |
+note: lint level defined here
+  --> $DIR/lint-type-overflow.rs:3:9
+   |
+LL | #![deny(overflowing_literals)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: literal out of range for u8
+  --> $DIR/lint-type-overflow.rs:15:14
+   |
+LL |     let x1 = 256_u8;
+   |              ^^^^^^
+
+error: literal out of range for i8
+  --> $DIR/lint-type-overflow.rs:18:18
+   |
+LL |     let x1: i8 = 128;
+   |                  ^^^
+
+error: literal out of range for i8
+  --> $DIR/lint-type-overflow.rs:20:19
+   |
+LL |     let x3: i8 = -129;
+   |                   ^^^
+
+error: literal out of range for i8
+  --> $DIR/lint-type-overflow.rs:21:19
+   |
+LL |     let x3: i8 = -(129);
+   |                   ^^^^^
+
+error: literal out of range for i8
+  --> $DIR/lint-type-overflow.rs:22:20
+   |
+LL |     let x3: i8 = -{129};
+   |                    ^^^
+
+error: literal out of range for i8
+  --> $DIR/lint-type-overflow.rs:24:10
+   |
+LL |     test(1000);
+   |          ^^^^
+
+error: literal out of range for i8
+  --> $DIR/lint-type-overflow.rs:26:13
+   |
+LL |     let x = 128_i8;
+   |             ^^^^^^
+
+error: literal out of range for i8
+  --> $DIR/lint-type-overflow.rs:30:14
+   |
+LL |     let x = -129_i8;
+   |              ^^^^^^
+
+error: literal out of range for i32
+  --> $DIR/lint-type-overflow.rs:34:18
+   |
+LL |     let x: i32 = 2147483648;
+   |                  ^^^^^^^^^^
+
+error: literal out of range for i32
+  --> $DIR/lint-type-overflow.rs:35:13
+   |
+LL |     let x = 2147483648_i32;
+   |             ^^^^^^^^^^^^^^
+
+error: literal out of range for i32
+  --> $DIR/lint-type-overflow.rs:38:19
+   |
+LL |     let x: i32 = -2147483649;
+   |                   ^^^^^^^^^^
+
+error: literal out of range for i32
+  --> $DIR/lint-type-overflow.rs:39:14
+   |
+LL |     let x = -2147483649_i32;
+   |              ^^^^^^^^^^^^^^
+
+error: literal out of range for i32
+  --> $DIR/lint-type-overflow.rs:40:13
+   |
+LL |     let x = 2147483648;
+   |             ^^^^^^^^^^
+
+error: literal out of range for i64
+  --> $DIR/lint-type-overflow.rs:42:13
+   |
+LL |     let x = 9223372036854775808_i64;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: literal out of range for i64
+  --> $DIR/lint-type-overflow.rs:44:13
+   |
+LL |     let x = 18446744073709551615_i64;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: literal out of range for i64
+  --> $DIR/lint-type-overflow.rs:45:19
+   |
+LL |     let x: i64 = -9223372036854775809;
+   |                   ^^^^^^^^^^^^^^^^^^^
+
+error: literal out of range for i64
+  --> $DIR/lint-type-overflow.rs:46:14
+   |
+LL |     let x = -9223372036854775809_i64;
+   |              ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 18 previous errors
+
diff --git a/src/test/ui/lint/lint-type-overflow2.rs b/src/test/ui/lint/lint-type-overflow2.rs
new file mode 100644
index 0000000..507e8d0
--- /dev/null
+++ b/src/test/ui/lint/lint-type-overflow2.rs
@@ -0,0 +1,15 @@
+// compile-flags: -O
+#![warn(overflowing_literals)]
+#![warn(const_err)]
+// compile-pass
+
+#[allow(unused_variables)]
+
+fn main() {
+    let x2: i8 = --128; //~ warn: literal out of range for i8
+
+    let x = -3.40282357e+38_f32; //~ warn: literal out of range for f32
+    let x =  3.40282357e+38_f32; //~ warn: literal out of range for f32
+    let x = -1.7976931348623159e+308_f64; //~ warn: literal out of range for f64
+    let x =  1.7976931348623159e+308_f64; //~ warn: literal out of range for f64
+}
diff --git a/src/test/ui/lint/lint-type-overflow2.stderr b/src/test/ui/lint/lint-type-overflow2.stderr
new file mode 100644
index 0000000..5255f6c
--- /dev/null
+++ b/src/test/ui/lint/lint-type-overflow2.stderr
@@ -0,0 +1,48 @@
+warning: literal out of range for i8
+  --> $DIR/lint-type-overflow2.rs:9:20
+   |
+LL |     let x2: i8 = --128;
+   |                    ^^^
+   |
+note: lint level defined here
+  --> $DIR/lint-type-overflow2.rs:2:9
+   |
+LL | #![warn(overflowing_literals)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+warning: literal out of range for f32
+  --> $DIR/lint-type-overflow2.rs:11:14
+   |
+LL |     let x = -3.40282357e+38_f32;
+   |              ^^^^^^^^^^^^^^^^^^
+
+warning: literal out of range for f32
+  --> $DIR/lint-type-overflow2.rs:12:14
+   |
+LL |     let x =  3.40282357e+38_f32;
+   |              ^^^^^^^^^^^^^^^^^^
+
+warning: literal out of range for f64
+  --> $DIR/lint-type-overflow2.rs:13:14
+   |
+LL |     let x = -1.7976931348623159e+308_f64;
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: literal out of range for f64
+  --> $DIR/lint-type-overflow2.rs:14:14
+   |
+LL |     let x =  1.7976931348623159e+308_f64;
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: this expression will panic at runtime
+  --> $DIR/lint-type-overflow2.rs:9:18
+   |
+LL |     let x2: i8 = --128;
+   |                  ^^^^^ attempt to negate with overflow
+   |
+note: lint level defined here
+  --> $DIR/lint-type-overflow2.rs:3:9
+   |
+LL | #![warn(const_err)]
+   |         ^^^^^^^^^
+
diff --git a/src/test/ui/lint/lint-unconditional-recursion.rs b/src/test/ui/lint/lint-unconditional-recursion.rs
new file mode 100644
index 0000000..44af117
--- /dev/null
+++ b/src/test/ui/lint/lint-unconditional-recursion.rs
@@ -0,0 +1,134 @@
+#![deny(unconditional_recursion)]
+
+#![allow(dead_code)]
+fn foo() { //~ ERROR function cannot return without recursing
+    foo();
+}
+
+fn bar() {
+    if true {
+        bar()
+    }
+}
+
+fn baz() { //~ ERROR function cannot return without recursing
+    if true {
+        baz()
+    } else {
+        baz()
+    }
+}
+
+fn qux() {
+    loop {}
+}
+
+fn quz() -> bool { //~ ERROR function cannot return without recursing
+    if true {
+        while quz() {}
+        true
+    } else {
+        loop { quz(); }
+    }
+}
+
+// Trait method calls.
+trait Foo {
+    fn bar(&self) { //~ ERROR function cannot return without recursing
+        self.bar()
+    }
+}
+
+impl Foo for Box<Foo+'static> {
+    fn bar(&self) { //~ ERROR function cannot return without recursing
+        loop {
+            self.bar()
+        }
+    }
+}
+
+// Trait method call with integer fallback after method resolution.
+impl Foo for i32 {
+    fn bar(&self) { //~ ERROR function cannot return without recursing
+        0.bar()
+    }
+}
+
+impl Foo for u32 {
+    fn bar(&self) {
+        0.bar()
+    }
+}
+
+// Trait method calls via paths.
+trait Foo2 {
+    fn bar(&self) { //~ ERROR function cannot return without recursing
+        Foo2::bar(self)
+    }
+}
+
+impl Foo2 for Box<Foo2+'static> {
+    fn bar(&self) { //~ ERROR function cannot return without recursing
+        loop {
+            Foo2::bar(self)
+        }
+    }
+}
+
+struct Baz;
+impl Baz {
+    // Inherent method call.
+    fn qux(&self) { //~ ERROR function cannot return without recursing
+        self.qux();
+    }
+
+    // Inherent method call via path.
+    fn as_ref(&self) -> &Self { //~ ERROR function cannot return without recursing
+        Baz::as_ref(self)
+    }
+}
+
+// Trait method calls to impls via paths.
+impl Default for Baz {
+    fn default() -> Baz { //~ ERROR function cannot return without recursing
+        let x = Default::default();
+        x
+    }
+}
+
+// Overloaded operators.
+impl std::ops::Deref for Baz {
+    type Target = ();
+    fn deref(&self) -> &() { //~ ERROR function cannot return without recursing
+        &**self
+    }
+}
+
+impl std::ops::Index<usize> for Baz {
+    type Output = Baz;
+    fn index(&self, x: usize) -> &Baz { //~ ERROR function cannot return without recursing
+        &self[x]
+    }
+}
+
+// Overloaded autoderef.
+struct Quux;
+impl std::ops::Deref for Quux {
+    type Target = Baz;
+    fn deref(&self) -> &Baz { //~ ERROR function cannot return without recursing
+        self.as_ref()
+    }
+}
+
+fn all_fine() {
+    let _f = all_fine;
+}
+
+// issue 26333
+trait Bar {
+    fn method<T: Bar>(&self, x: &T) {
+        x.method(x)
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/lint/lint-unconditional-recursion.stderr b/src/test/ui/lint/lint-unconditional-recursion.stderr
new file mode 100644
index 0000000..5d2e820
--- /dev/null
+++ b/src/test/ui/lint/lint-unconditional-recursion.stderr
@@ -0,0 +1,157 @@
+error: function cannot return without recursing
+  --> $DIR/lint-unconditional-recursion.rs:4:1
+   |
+LL | fn foo() {
+   | ^^^^^^^^ cannot return without recursing
+LL |     foo();
+   |     ----- recursive call site
+   |
+note: lint level defined here
+  --> $DIR/lint-unconditional-recursion.rs:1:9
+   |
+LL | #![deny(unconditional_recursion)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+   = help: a `loop` may express intention better if this is on purpose
+
+error: function cannot return without recursing
+  --> $DIR/lint-unconditional-recursion.rs:14:1
+   |
+LL | fn baz() {
+   | ^^^^^^^^ cannot return without recursing
+LL |     if true {
+LL |         baz()
+   |         ----- recursive call site
+LL |     } else {
+LL |         baz()
+   |         ----- recursive call site
+   |
+   = help: a `loop` may express intention better if this is on purpose
+
+error: function cannot return without recursing
+  --> $DIR/lint-unconditional-recursion.rs:26:1
+   |
+LL | fn quz() -> bool {
+   | ^^^^^^^^^^^^^^^^ cannot return without recursing
+LL |     if true {
+LL |         while quz() {}
+   |               ----- recursive call site
+...
+LL |         loop { quz(); }
+   |                ----- recursive call site
+   |
+   = help: a `loop` may express intention better if this is on purpose
+
+error: function cannot return without recursing
+  --> $DIR/lint-unconditional-recursion.rs:37:5
+   |
+LL |     fn bar(&self) {
+   |     ^^^^^^^^^^^^^ cannot return without recursing
+LL |         self.bar()
+   |         ---------- recursive call site
+   |
+   = help: a `loop` may express intention better if this is on purpose
+
+error: function cannot return without recursing
+  --> $DIR/lint-unconditional-recursion.rs:43:5
+   |
+LL |     fn bar(&self) {
+   |     ^^^^^^^^^^^^^ cannot return without recursing
+LL |         loop {
+LL |             self.bar()
+   |             ---------- recursive call site
+   |
+   = help: a `loop` may express intention better if this is on purpose
+
+error: function cannot return without recursing
+  --> $DIR/lint-unconditional-recursion.rs:52:5
+   |
+LL |     fn bar(&self) {
+   |     ^^^^^^^^^^^^^ cannot return without recursing
+LL |         0.bar()
+   |         ------- recursive call site
+   |
+   = help: a `loop` may express intention better if this is on purpose
+
+error: function cannot return without recursing
+  --> $DIR/lint-unconditional-recursion.rs:65:5
+   |
+LL |     fn bar(&self) {
+   |     ^^^^^^^^^^^^^ cannot return without recursing
+LL |         Foo2::bar(self)
+   |         --------------- recursive call site
+   |
+   = help: a `loop` may express intention better if this is on purpose
+
+error: function cannot return without recursing
+  --> $DIR/lint-unconditional-recursion.rs:71:5
+   |
+LL |     fn bar(&self) {
+   |     ^^^^^^^^^^^^^ cannot return without recursing
+LL |         loop {
+LL |             Foo2::bar(self)
+   |             --------------- recursive call site
+   |
+   = help: a `loop` may express intention better if this is on purpose
+
+error: function cannot return without recursing
+  --> $DIR/lint-unconditional-recursion.rs:81:5
+   |
+LL |     fn qux(&self) {
+   |     ^^^^^^^^^^^^^ cannot return without recursing
+LL |         self.qux();
+   |         ---------- recursive call site
+   |
+   = help: a `loop` may express intention better if this is on purpose
+
+error: function cannot return without recursing
+  --> $DIR/lint-unconditional-recursion.rs:86:5
+   |
+LL |     fn as_ref(&self) -> &Self {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
+LL |         Baz::as_ref(self)
+   |         ----------------- recursive call site
+   |
+   = help: a `loop` may express intention better if this is on purpose
+
+error: function cannot return without recursing
+  --> $DIR/lint-unconditional-recursion.rs:93:5
+   |
+LL |     fn default() -> Baz {
+   |     ^^^^^^^^^^^^^^^^^^^ cannot return without recursing
+LL |         let x = Default::default();
+   |                 ------------------ recursive call site
+   |
+   = help: a `loop` may express intention better if this is on purpose
+
+error: function cannot return without recursing
+  --> $DIR/lint-unconditional-recursion.rs:102:5
+   |
+LL |     fn deref(&self) -> &() {
+   |     ^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
+LL |         &**self
+   |          ------ recursive call site
+   |
+   = help: a `loop` may express intention better if this is on purpose
+
+error: function cannot return without recursing
+  --> $DIR/lint-unconditional-recursion.rs:109:5
+   |
+LL |     fn index(&self, x: usize) -> &Baz {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
+LL |         &self[x]
+   |          ------- recursive call site
+   |
+   = help: a `loop` may express intention better if this is on purpose
+
+error: function cannot return without recursing
+  --> $DIR/lint-unconditional-recursion.rs:118:5
+   |
+LL |     fn deref(&self) -> &Baz {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
+LL |         self.as_ref()
+   |         ---- recursive call site
+   |
+   = help: a `loop` may express intention better if this is on purpose
+
+error: aborting due to 14 previous errors
+
diff --git a/src/test/ui/lint/lint-unexported-no-mangle.rs b/src/test/ui/lint/lint-unexported-no-mangle.rs
new file mode 100644
index 0000000..5945c90
--- /dev/null
+++ b/src/test/ui/lint/lint-unexported-no-mangle.rs
@@ -0,0 +1,29 @@
+// compile-flags:-F private_no_mangle_fns -F no_mangle_const_items -F private_no_mangle_statics
+
+#[no_mangle]
+fn foo() {
+}
+
+#[allow(dead_code)]
+#[no_mangle]
+const FOO: u64 = 1; //~ ERROR const items should never be #[no_mangle]
+
+#[no_mangle]
+pub const PUB_FOO: u64 = 1; //~ ERROR const items should never be #[no_mangle]
+
+#[no_mangle]
+pub fn bar()  {
+}
+
+#[no_mangle]
+pub static BAR: u64 = 1;
+
+#[allow(dead_code)]
+#[no_mangle]
+static PRIVATE_BAR: u64 = 1;
+
+
+fn main() {
+    foo();
+    bar();
+}
diff --git a/src/test/ui/lint/lint-unexported-no-mangle.stderr b/src/test/ui/lint/lint-unexported-no-mangle.stderr
new file mode 100644
index 0000000..586ee8e
--- /dev/null
+++ b/src/test/ui/lint/lint-unexported-no-mangle.stderr
@@ -0,0 +1,28 @@
+warning: lint `private_no_mangle_fns` has been removed: `no longer a warning, #[no_mangle] functions always exported`
+   |
+   = note: requested on the command line with `-F private_no_mangle_fns`
+
+warning: lint `private_no_mangle_statics` has been removed: `no longer a warning, #[no_mangle] statics always exported`
+   |
+   = note: requested on the command line with `-F private_no_mangle_statics`
+
+error: const items should never be #[no_mangle]
+  --> $DIR/lint-unexported-no-mangle.rs:9:1
+   |
+LL | const FOO: u64 = 1;
+   | -----^^^^^^^^^^^^^^
+   | |
+   | help: try a static value: `pub static`
+   |
+   = note: requested on the command line with `-F no-mangle-const-items`
+
+error: const items should never be #[no_mangle]
+  --> $DIR/lint-unexported-no-mangle.rs:12:1
+   |
+LL | pub const PUB_FOO: u64 = 1;
+   | ---------^^^^^^^^^^^^^^^^^^
+   | |
+   | help: try a static value: `pub static`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/lint/lint-unknown-attr.rs b/src/test/ui/lint/lint-unknown-attr.rs
new file mode 100644
index 0000000..828b869
--- /dev/null
+++ b/src/test/ui/lint/lint-unknown-attr.rs
@@ -0,0 +1,11 @@
+// When denying at the crate level, be sure to not get random warnings from the
+// injected intrinsics by the compiler.
+
+#![feature(custom_attribute)]
+#![deny(unused_attributes)]
+
+#![mutable_doc] //~ ERROR unused attribute
+
+#[dance] mod a {} //~ ERROR unused attribute
+
+#[dance] fn main() {} //~ ERROR unused attribute
diff --git a/src/test/ui/lint/lint-unknown-attr.stderr b/src/test/ui/lint/lint-unknown-attr.stderr
new file mode 100644
index 0000000..9817760
--- /dev/null
+++ b/src/test/ui/lint/lint-unknown-attr.stderr
@@ -0,0 +1,26 @@
+error: unused attribute
+  --> $DIR/lint-unknown-attr.rs:9:1
+   |
+LL | #[dance] mod a {}
+   | ^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/lint-unknown-attr.rs:5:9
+   |
+LL | #![deny(unused_attributes)]
+   |         ^^^^^^^^^^^^^^^^^
+
+error: unused attribute
+  --> $DIR/lint-unknown-attr.rs:11:1
+   |
+LL | #[dance] fn main() {}
+   | ^^^^^^^^
+
+error: unused attribute
+  --> $DIR/lint-unknown-attr.rs:7:1
+   |
+LL | #![mutable_doc]
+   | ^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/lint/lint-unknown-feature-default.rs b/src/test/ui/lint/lint-unknown-feature-default.rs
new file mode 100644
index 0000000..e04363f
--- /dev/null
+++ b/src/test/ui/lint/lint-unknown-feature-default.rs
@@ -0,0 +1,10 @@
+// Tests the default for the unused_features lint
+
+#![allow(stable_features)]
+// FIXME(#44232) we should warn that this isn't used.
+#![feature(rust1)]
+
+// compile-pass
+
+
+fn main() { }
diff --git a/src/test/ui/lint/lint-unknown-feature.rs b/src/test/ui/lint/lint-unknown-feature.rs
new file mode 100644
index 0000000..c372a98
--- /dev/null
+++ b/src/test/ui/lint/lint-unknown-feature.rs
@@ -0,0 +1,10 @@
+#![warn(unused_features)]
+
+#![allow(stable_features)]
+// FIXME(#44232) we should warn that this isn't used.
+#![feature(rust1)]
+
+// compile-pass
+
+
+fn main() {}
diff --git a/src/test/ui/lint/lint-unknown-lint-cmdline.rs b/src/test/ui/lint/lint-unknown-lint-cmdline.rs
new file mode 100644
index 0000000..7f3f55f
--- /dev/null
+++ b/src/test/ui/lint/lint-unknown-lint-cmdline.rs
@@ -0,0 +1,9 @@
+// compile-flags:-D bogus -D dead_cod
+
+// error-pattern:unknown lint: `bogus`
+// error-pattern:requested on the command line with `-D bogus`
+// error-pattern:unknown lint: `dead_cod`
+// error-pattern:requested on the command line with `-D dead_cod`
+// error-pattern:did you mean: `dead_code`
+
+fn main() { }
diff --git a/src/test/ui/lint/lint-unknown-lint-cmdline.stderr b/src/test/ui/lint/lint-unknown-lint-cmdline.stderr
new file mode 100644
index 0000000..58fdae3
--- /dev/null
+++ b/src/test/ui/lint/lint-unknown-lint-cmdline.stderr
@@ -0,0 +1,12 @@
+error[E0602]: unknown lint: `bogus`
+   |
+   = note: requested on the command line with `-D bogus`
+
+error[E0602]: unknown lint: `dead_cod`
+   |
+   = help: did you mean: `dead_code`
+   = note: requested on the command line with `-D dead_cod`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0602`.
diff --git a/src/test/ui/lint/lint-unknown-lint.rs b/src/test/ui/lint/lint-unknown-lint.rs
new file mode 100644
index 0000000..c36a8b2
--- /dev/null
+++ b/src/test/ui/lint/lint-unknown-lint.rs
@@ -0,0 +1,9 @@
+#![deny(unknown_lints)]
+
+#![allow(not_a_real_lint)] //~ ERROR unknown lint
+
+#![deny(dead_cod)] //~ ERROR unknown lint
+                   //~| HELP did you mean
+                   //~| SUGGESTION dead_code
+
+fn main() {}
diff --git a/src/test/ui/lint/lint-unknown-lint.stderr b/src/test/ui/lint/lint-unknown-lint.stderr
new file mode 100644
index 0000000..b3ba6e3
--- /dev/null
+++ b/src/test/ui/lint/lint-unknown-lint.stderr
@@ -0,0 +1,20 @@
+error: unknown lint: `not_a_real_lint`
+  --> $DIR/lint-unknown-lint.rs:3:10
+   |
+LL | #![allow(not_a_real_lint)]
+   |          ^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/lint-unknown-lint.rs:1:9
+   |
+LL | #![deny(unknown_lints)]
+   |         ^^^^^^^^^^^^^
+
+error: unknown lint: `dead_cod`
+  --> $DIR/lint-unknown-lint.rs:5:9
+   |
+LL | #![deny(dead_cod)]
+   |         ^^^^^^^^ help: did you mean: `dead_code`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/lint/lint-unnecessary-import-braces.rs b/src/test/ui/lint/lint-unnecessary-import-braces.rs
new file mode 100644
index 0000000..9a3398a
--- /dev/null
+++ b/src/test/ui/lint/lint-unnecessary-import-braces.rs
@@ -0,0 +1,11 @@
+#![deny(unused_import_braces)]
+
+use test::{A}; //~ ERROR braces around A is unnecessary
+
+mod test {
+    use test::{self}; // OK
+    use test::{self as rename}; // OK
+    pub struct A;
+}
+
+fn main() {}
diff --git a/src/test/ui/lint/lint-unnecessary-import-braces.stderr b/src/test/ui/lint/lint-unnecessary-import-braces.stderr
new file mode 100644
index 0000000..41e274b
--- /dev/null
+++ b/src/test/ui/lint/lint-unnecessary-import-braces.stderr
@@ -0,0 +1,14 @@
+error: braces around A is unnecessary
+  --> $DIR/lint-unnecessary-import-braces.rs:3:1
+   |
+LL | use test::{A};
+   | ^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/lint-unnecessary-import-braces.rs:1:9
+   |
+LL | #![deny(unused_import_braces)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lint/lint-unnecessary-parens.rs b/src/test/ui/lint/lint-unnecessary-parens.rs
new file mode 100644
index 0000000..dc74d69
--- /dev/null
+++ b/src/test/ui/lint/lint-unnecessary-parens.rs
@@ -0,0 +1,45 @@
+#![deny(unused_parens)]
+
+#[derive(Eq, PartialEq)]
+struct X { y: bool }
+impl X {
+    fn foo(&self, conjunct: bool) -> bool { self.y && conjunct }
+}
+
+fn foo() -> isize {
+    return (1); //~ ERROR unnecessary parentheses around `return` value
+}
+fn bar(y: bool) -> X {
+    return (X { y }); //~ ERROR unnecessary parentheses around `return` value
+}
+
+fn main() {
+    foo();
+    bar((true)); //~ ERROR unnecessary parentheses around function argument
+
+    if (true) {} //~ ERROR unnecessary parentheses around `if` condition
+    while (true) {} //~ ERROR unnecessary parentheses around `while` condition
+    match (true) { //~ ERROR unnecessary parentheses around `match` head expression
+        _ => {}
+    }
+    if let 1 = (1) {} //~ ERROR unnecessary parentheses around `if let` head expression
+    while let 1 = (2) {} //~ ERROR unnecessary parentheses around `while let` head expression
+    let v = X { y: false };
+    // struct lits needs parens, so these shouldn't warn.
+    if (v == X { y: true }) {}
+    if (X { y: true } == v) {}
+    if (X { y: false }.y) {}
+
+    while (X { y: false }.foo(true)) {}
+    while (true | X { y: false }.y) {}
+
+    match (X { y: false }) {
+        _ => {}
+    }
+
+    X { y: false }.foo((true)); //~ ERROR unnecessary parentheses around method argument
+
+    let mut _a = (0); //~ ERROR unnecessary parentheses around assigned value
+    _a = (0); //~ ERROR unnecessary parentheses around assigned value
+    _a += (1); //~ ERROR unnecessary parentheses around assigned value
+}
diff --git a/src/test/ui/lint/lint-unnecessary-parens.stderr b/src/test/ui/lint/lint-unnecessary-parens.stderr
new file mode 100644
index 0000000..fe2ee38
--- /dev/null
+++ b/src/test/ui/lint/lint-unnecessary-parens.stderr
@@ -0,0 +1,80 @@
+error: unnecessary parentheses around `return` value
+  --> $DIR/lint-unnecessary-parens.rs:10:12
+   |
+LL |     return (1);
+   |            ^^^ help: remove these parentheses
+   |
+note: lint level defined here
+  --> $DIR/lint-unnecessary-parens.rs:1:9
+   |
+LL | #![deny(unused_parens)]
+   |         ^^^^^^^^^^^^^
+
+error: unnecessary parentheses around `return` value
+  --> $DIR/lint-unnecessary-parens.rs:13:12
+   |
+LL |     return (X { y });
+   |            ^^^^^^^^^ help: remove these parentheses
+
+error: unnecessary parentheses around function argument
+  --> $DIR/lint-unnecessary-parens.rs:18:9
+   |
+LL |     bar((true));
+   |         ^^^^^^ help: remove these parentheses
+
+error: unnecessary parentheses around `if` condition
+  --> $DIR/lint-unnecessary-parens.rs:20:8
+   |
+LL |     if (true) {}
+   |        ^^^^^^ help: remove these parentheses
+
+error: unnecessary parentheses around `while` condition
+  --> $DIR/lint-unnecessary-parens.rs:21:11
+   |
+LL |     while (true) {}
+   |           ^^^^^^ help: remove these parentheses
+
+error: unnecessary parentheses around `match` head expression
+  --> $DIR/lint-unnecessary-parens.rs:22:11
+   |
+LL |     match (true) {
+   |           ^^^^^^ help: remove these parentheses
+
+error: unnecessary parentheses around `if let` head expression
+  --> $DIR/lint-unnecessary-parens.rs:25:16
+   |
+LL |     if let 1 = (1) {}
+   |                ^^^ help: remove these parentheses
+
+error: unnecessary parentheses around `while let` head expression
+  --> $DIR/lint-unnecessary-parens.rs:26:19
+   |
+LL |     while let 1 = (2) {}
+   |                   ^^^ help: remove these parentheses
+
+error: unnecessary parentheses around method argument
+  --> $DIR/lint-unnecessary-parens.rs:40:24
+   |
+LL |     X { y: false }.foo((true));
+   |                        ^^^^^^ help: remove these parentheses
+
+error: unnecessary parentheses around assigned value
+  --> $DIR/lint-unnecessary-parens.rs:42:18
+   |
+LL |     let mut _a = (0);
+   |                  ^^^ help: remove these parentheses
+
+error: unnecessary parentheses around assigned value
+  --> $DIR/lint-unnecessary-parens.rs:43:10
+   |
+LL |     _a = (0);
+   |          ^^^ help: remove these parentheses
+
+error: unnecessary parentheses around assigned value
+  --> $DIR/lint-unnecessary-parens.rs:44:11
+   |
+LL |     _a += (1);
+   |           ^^^ help: remove these parentheses
+
+error: aborting due to 12 previous errors
+
diff --git a/src/test/ui/lint/lint-unsafe-code.rs b/src/test/ui/lint/lint-unsafe-code.rs
new file mode 100644
index 0000000..735f33f
--- /dev/null
+++ b/src/test/ui/lint/lint-unsafe-code.rs
@@ -0,0 +1,89 @@
+#![allow(unused_unsafe)]
+#![allow(dead_code)]
+#![deny(unsafe_code)]
+
+struct Bar;
+struct Bar2;
+struct Bar3;
+
+#[allow(unsafe_code)]
+mod allowed_unsafe {
+    fn allowed() { unsafe {} }
+    unsafe fn also_allowed() {}
+    unsafe trait AllowedUnsafe { }
+    unsafe impl AllowedUnsafe for super::Bar {}
+}
+
+macro_rules! unsafe_in_macro {
+    () => {
+        unsafe {} //~ ERROR: usage of an `unsafe` block
+    }
+}
+
+unsafe fn baz() {} //~ ERROR: declaration of an `unsafe` function
+unsafe trait Foo {} //~ ERROR: declaration of an `unsafe` trait
+unsafe impl Foo for Bar {} //~ ERROR: implementation of an `unsafe` trait
+
+trait Baz {
+    unsafe fn baz(&self); //~ ERROR: declaration of an `unsafe` method
+    unsafe fn provided(&self) {} //~ ERROR: implementation of an `unsafe` method
+    unsafe fn provided_override(&self) {} //~ ERROR: implementation of an `unsafe` method
+}
+
+impl Baz for Bar {
+    unsafe fn baz(&self) {} //~ ERROR: implementation of an `unsafe` method
+    unsafe fn provided_override(&self) {} //~ ERROR: implementation of an `unsafe` method
+}
+
+
+#[allow(unsafe_code)]
+trait A {
+    unsafe fn allowed_unsafe(&self);
+    unsafe fn allowed_unsafe_provided(&self) {}
+}
+
+#[allow(unsafe_code)]
+impl Baz for Bar2 {
+    unsafe fn baz(&self) {}
+    unsafe fn provided_override(&self) {}
+}
+
+impl Baz for Bar3 {
+    #[allow(unsafe_code)]
+    unsafe fn baz(&self) {}
+    unsafe fn provided_override(&self) {} //~ ERROR: implementation of an `unsafe` method
+}
+
+#[allow(unsafe_code)]
+unsafe trait B {
+    fn dummy(&self) {}
+}
+
+trait C {
+    #[allow(unsafe_code)]
+    unsafe fn baz(&self);
+    unsafe fn provided(&self) {} //~ ERROR: implementation of an `unsafe` method
+}
+
+impl C for Bar {
+    #[allow(unsafe_code)]
+    unsafe fn baz(&self) {}
+    unsafe fn provided(&self) {} //~ ERROR: implementation of an `unsafe` method
+}
+
+impl C for Bar2 {
+    unsafe fn baz(&self) {} //~ ERROR: implementation of an `unsafe` method
+}
+
+trait D {
+    #[allow(unsafe_code)]
+    unsafe fn unsafe_provided(&self) {}
+}
+
+impl D for Bar {}
+
+fn main() {
+    unsafe {} //~ ERROR: usage of an `unsafe` block
+
+    unsafe_in_macro!()
+}
diff --git a/src/test/ui/lint/lint-unsafe-code.stderr b/src/test/ui/lint/lint-unsafe-code.stderr
new file mode 100644
index 0000000..96ad0c3
--- /dev/null
+++ b/src/test/ui/lint/lint-unsafe-code.stderr
@@ -0,0 +1,95 @@
+error: declaration of an `unsafe` function
+  --> $DIR/lint-unsafe-code.rs:23:1
+   |
+LL | unsafe fn baz() {}
+   | ^^^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/lint-unsafe-code.rs:3:9
+   |
+LL | #![deny(unsafe_code)]
+   |         ^^^^^^^^^^^
+
+error: declaration of an `unsafe` trait
+  --> $DIR/lint-unsafe-code.rs:24:1
+   |
+LL | unsafe trait Foo {}
+   | ^^^^^^^^^^^^^^^^^^^
+
+error: implementation of an `unsafe` trait
+  --> $DIR/lint-unsafe-code.rs:25:1
+   |
+LL | unsafe impl Foo for Bar {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: declaration of an `unsafe` method
+  --> $DIR/lint-unsafe-code.rs:28:5
+   |
+LL |     unsafe fn baz(&self);
+   |     ^^^^^^^^^^^^^^^^^^^^^
+
+error: implementation of an `unsafe` method
+  --> $DIR/lint-unsafe-code.rs:29:5
+   |
+LL |     unsafe fn provided(&self) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: implementation of an `unsafe` method
+  --> $DIR/lint-unsafe-code.rs:30:5
+   |
+LL |     unsafe fn provided_override(&self) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: implementation of an `unsafe` method
+  --> $DIR/lint-unsafe-code.rs:34:5
+   |
+LL |     unsafe fn baz(&self) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: implementation of an `unsafe` method
+  --> $DIR/lint-unsafe-code.rs:35:5
+   |
+LL |     unsafe fn provided_override(&self) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: implementation of an `unsafe` method
+  --> $DIR/lint-unsafe-code.rs:54:5
+   |
+LL |     unsafe fn provided_override(&self) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: implementation of an `unsafe` method
+  --> $DIR/lint-unsafe-code.rs:65:5
+   |
+LL |     unsafe fn provided(&self) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: implementation of an `unsafe` method
+  --> $DIR/lint-unsafe-code.rs:71:5
+   |
+LL |     unsafe fn provided(&self) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: implementation of an `unsafe` method
+  --> $DIR/lint-unsafe-code.rs:75:5
+   |
+LL |     unsafe fn baz(&self) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: usage of an `unsafe` block
+  --> $DIR/lint-unsafe-code.rs:86:5
+   |
+LL |     unsafe {}
+   |     ^^^^^^^^^
+
+error: usage of an `unsafe` block
+  --> $DIR/lint-unsafe-code.rs:19:9
+   |
+LL |         unsafe {}
+   |         ^^^^^^^^^
+...
+LL |     unsafe_in_macro!()
+   |     ------------------ in this macro invocation
+
+error: aborting due to 14 previous errors
+
diff --git a/src/test/ui/lint/lint-unused-extern-crate.rs b/src/test/ui/lint/lint-unused-extern-crate.rs
new file mode 100644
index 0000000..d5e4da5
--- /dev/null
+++ b/src/test/ui/lint/lint-unused-extern-crate.rs
@@ -0,0 +1,35 @@
+// aux-build:lint_unused_extern_crate.rs
+// aux-build:lint_unused_extern_crate2.rs
+// aux-build:lint_unused_extern_crate3.rs
+// aux-build:lint_unused_extern_crate4.rs
+// aux-build:lint_unused_extern_crate5.rs
+
+#![deny(unused_extern_crates)]
+#![allow(unused_variables)]
+#![allow(deprecated)]
+
+extern crate lint_unused_extern_crate5; //~ ERROR: unused extern crate
+
+pub extern crate lint_unused_extern_crate4; // no error, it is re-exported
+
+extern crate lint_unused_extern_crate3; // no error, it is used
+
+extern crate lint_unused_extern_crate2; // no error, the use marks it as used
+                                        // even if imported objects aren't used
+
+extern crate lint_unused_extern_crate as other; // no error, the use * marks it as used
+
+#[allow(unused_imports)]
+use lint_unused_extern_crate2::foo as bar;
+
+use other::*;
+
+mod foo {
+    // Test that this is unused even though an earlier `extern crate` is used.
+    extern crate lint_unused_extern_crate2; //~ ERROR unused extern crate
+}
+
+fn main() {
+    lint_unused_extern_crate3::foo();
+    let y = foo();
+}
diff --git a/src/test/ui/lint/lint-unused-extern-crate.stderr b/src/test/ui/lint/lint-unused-extern-crate.stderr
new file mode 100644
index 0000000..aa4a8da
--- /dev/null
+++ b/src/test/ui/lint/lint-unused-extern-crate.stderr
@@ -0,0 +1,20 @@
+error: unused extern crate
+  --> $DIR/lint-unused-extern-crate.rs:11:1
+   |
+LL | extern crate lint_unused_extern_crate5;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
+   |
+note: lint level defined here
+  --> $DIR/lint-unused-extern-crate.rs:7:9
+   |
+LL | #![deny(unused_extern_crates)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: unused extern crate
+  --> $DIR/lint-unused-extern-crate.rs:29:5
+   |
+LL |     extern crate lint_unused_extern_crate2;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/lint/lint-unused-imports.rs b/src/test/ui/lint/lint-unused-imports.rs
new file mode 100644
index 0000000..4754d88
--- /dev/null
+++ b/src/test/ui/lint/lint-unused-imports.rs
@@ -0,0 +1,90 @@
+#![deny(unused_imports)]
+#![allow(dead_code)]
+
+use bar::c::cc as cal;
+
+use std::mem::*;            // shouldn't get errors for not using
+                            // everything imported
+use std::fmt::{};
+//~^ ERROR unused import: `std::fmt::{}`
+
+// Should get errors for both 'Some' and 'None'
+use std::option::Option::{Some, None};
+//~^ ERROR unused imports: `None`, `Some`
+
+use test::A;       //~ ERROR unused import: `test::A`
+// Be sure that if we just bring some methods into scope that they're also
+// counted as being used.
+use test::B;
+// But only when actually used: do not get confused by the method with the same name.
+use test::B2; //~ ERROR unused import: `test::B2`
+
+// Make sure this import is warned about when at least one of its imported names
+// is unused
+use test2::{foo, bar}; //~ ERROR unused import: `bar`
+
+mod test2 {
+    pub fn foo() {}
+    pub fn bar() {}
+}
+
+mod test {
+    pub trait A { fn a(&self) {} }
+    pub trait B { fn b(&self) {} }
+    pub trait B2 { fn b(&self) {} }
+    pub struct C;
+    impl A for C {}
+    impl B for C {}
+}
+
+mod foo {
+    pub struct Point{pub x: isize, pub y: isize}
+    pub struct Square{pub p: Point, pub h: usize, pub w: usize}
+}
+
+mod bar {
+    // Don't ignore on 'pub use' because we're not sure if it's used or not
+    pub use std::cmp::PartialEq;
+    pub struct Square;
+
+    pub mod c {
+        use foo::Point;
+        use foo::Square; //~ ERROR unused import: `foo::Square`
+        pub fn cc(_p: Point) -> super::Square {
+            fn f() -> super::Square {
+                super::Square
+            }
+            f()
+        }
+    }
+
+    #[allow(unused_imports)]
+    mod foo {
+        use std::cmp::PartialEq;
+    }
+}
+
+fn g() {
+    use self::g; //~ ERROR unused import: `self::g`
+    //~^ ERROR the item `g` is imported redundantly
+    fn f() {
+        self::g();
+    }
+}
+
+// cf. issue #35135.
+#[allow(unused_variables)]
+fn h() {
+    use test2::foo; //~ ERROR unused import: `test2::foo`
+    //~^ ERROR the item `foo` is imported redundantly
+    let foo = 0;
+}
+
+fn main() {
+    cal(foo::Point{x:3, y:9});
+    let mut a = 3;
+    let mut b = 4;
+    swap(&mut a, &mut b);
+    test::C.b();
+    let _a = foo();
+}
diff --git a/src/test/ui/lint/lint-unused-imports.stderr b/src/test/ui/lint/lint-unused-imports.stderr
new file mode 100644
index 0000000..96d71a2
--- /dev/null
+++ b/src/test/ui/lint/lint-unused-imports.stderr
@@ -0,0 +1,78 @@
+error: unused import: `std::fmt::{}`
+  --> $DIR/lint-unused-imports.rs:8:5
+   |
+LL | use std::fmt::{};
+   |     ^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/lint-unused-imports.rs:1:9
+   |
+LL | #![deny(unused_imports)]
+   |         ^^^^^^^^^^^^^^
+
+error: unused imports: `None`, `Some`
+  --> $DIR/lint-unused-imports.rs:12:27
+   |
+LL | use std::option::Option::{Some, None};
+   |                           ^^^^  ^^^^
+
+error: unused import: `test::A`
+  --> $DIR/lint-unused-imports.rs:15:5
+   |
+LL | use test::A;
+   |     ^^^^^^^
+
+error: unused import: `bar`
+  --> $DIR/lint-unused-imports.rs:24:18
+   |
+LL | use test2::{foo, bar};
+   |                  ^^^
+
+error: unused import: `foo::Square`
+  --> $DIR/lint-unused-imports.rs:52:13
+   |
+LL |         use foo::Square;
+   |             ^^^^^^^^^^^
+
+error: the item `g` is imported redundantly
+  --> $DIR/lint-unused-imports.rs:68:9
+   |
+LL | / fn g() {
+LL | |     use self::g;
+   | |         ^^^^^^^
+LL | |
+LL | |     fn f() {
+LL | |         self::g();
+LL | |     }
+LL | | }
+   | |_- the item `g` is already defined here
+
+error: unused import: `self::g`
+  --> $DIR/lint-unused-imports.rs:68:9
+   |
+LL |     use self::g;
+   |         ^^^^^^^
+
+error: the item `foo` is imported redundantly
+  --> $DIR/lint-unused-imports.rs:78:9
+   |
+LL | use test2::{foo, bar};
+   |             --- the item `foo` is already imported here
+...
+LL |     use test2::foo;
+   |         ^^^^^^^^^^
+
+error: unused import: `test2::foo`
+  --> $DIR/lint-unused-imports.rs:78:9
+   |
+LL |     use test2::foo;
+   |         ^^^^^^^^^^
+
+error: unused import: `test::B2`
+  --> $DIR/lint-unused-imports.rs:20:5
+   |
+LL | use test::B2;
+   |     ^^^^^^^^
+
+error: aborting due to 10 previous errors
+
diff --git a/src/test/ui/lint/lint-unused-mut-self.rs b/src/test/ui/lint/lint-unused-mut-self.rs
new file mode 100644
index 0000000..3c709d0
--- /dev/null
+++ b/src/test/ui/lint/lint-unused-mut-self.rs
@@ -0,0 +1,12 @@
+#![allow(unused_assignments)]
+#![allow(unused_variables)]
+#![allow(dead_code)]
+#![deny(unused_mut)]
+
+struct Foo;
+impl Foo {
+    fn foo(mut self) {} //~ ERROR: variable does not need to be mutable
+    fn bar(mut self: Box<Foo>) {} //~ ERROR: variable does not need to be mutable
+}
+
+fn main() {}
diff --git a/src/test/ui/lint/lint-unused-mut-self.stderr b/src/test/ui/lint/lint-unused-mut-self.stderr
new file mode 100644
index 0000000..b5f6b71
--- /dev/null
+++ b/src/test/ui/lint/lint-unused-mut-self.stderr
@@ -0,0 +1,24 @@
+error: variable does not need to be mutable
+  --> $DIR/lint-unused-mut-self.rs:8:12
+   |
+LL |     fn foo(mut self) {}
+   |            ----^^^^
+   |            |
+   |            help: remove this `mut`
+   |
+note: lint level defined here
+  --> $DIR/lint-unused-mut-self.rs:4:9
+   |
+LL | #![deny(unused_mut)]
+   |         ^^^^^^^^^^
+
+error: variable does not need to be mutable
+  --> $DIR/lint-unused-mut-self.rs:9:12
+   |
+LL |     fn bar(mut self: Box<Foo>) {}
+   |            ----^^^^
+   |            |
+   |            help: remove this `mut`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/lint/lint-unused-mut-variables.rs b/src/test/ui/lint/lint-unused-mut-variables.rs
new file mode 100644
index 0000000..da0236a
--- /dev/null
+++ b/src/test/ui/lint/lint-unused-mut-variables.rs
@@ -0,0 +1,132 @@
+// Exercise the unused_mut attribute in some positive and negative cases
+
+#![allow(unused_assignments)]
+#![allow(unused_variables)]
+#![allow(dead_code)]
+#![deny(unused_mut)]
+
+
+fn main() {
+    // negative cases
+    let mut a = 3; //~ ERROR: variable does not need to be mutable
+
+    let mut a = 2; //~ ERROR: variable does not need to be mutable
+
+    let mut b = 3; //~ ERROR: variable does not need to be mutable
+
+    let mut a = vec![3]; //~ ERROR: variable does not need to be mutable
+
+    let (mut a, b) = (1, 2); //~ ERROR: variable does not need to be mutable
+
+    let mut a; //~ ERROR: variable does not need to be mutable
+
+    a = 3;
+
+    let mut b; //~ ERROR: variable does not need to be mutable
+
+    if true {
+        b = 3;
+    } else {
+        b = 4;
+    }
+
+    match 30 {
+        mut x => {} //~ ERROR: variable does not need to be mutable
+
+    }
+    match (30, 2) {
+      (mut x, 1) | //~ ERROR: variable does not need to be mutable
+
+      (mut x, 2) |
+      (mut x, 3) => {
+      }
+      _ => {}
+    }
+
+    let x = |mut y: isize| 10; //~ ERROR: variable does not need to be mutable
+
+    fn what(mut foo: isize) {} //~ ERROR: variable does not need to be mutable
+
+
+    let mut a = &mut 5; //~ ERROR: variable does not need to be mutable
+
+    *a = 4;
+
+    let mut a = 5;
+    let mut b = (&mut a,); //~ ERROR: variable does not need to be mutable
+    *b.0 = 4;
+
+    let mut x = &mut 1; //~ ERROR: variable does not need to be mutable
+
+    let mut f = || {
+      *x += 1;
+    };
+    f();
+
+    fn mut_ref_arg(mut arg : &mut [u8]) -> &mut [u8] {
+        &mut arg[..] //~^ ERROR: variable does not need to be mutable
+
+    }
+
+    let mut v : &mut Vec<()> = &mut vec![]; //~ ERROR: variable does not need to be mutable
+
+    v.push(());
+
+    // positive cases
+    let mut a = 2;
+    a = 3;
+    let mut a = Vec::new();
+    a.push(3);
+    let mut a = Vec::new();
+    callback(|| {
+        a.push(3);
+    });
+    let mut a = Vec::new();
+    callback(|| {
+        callback(|| {
+            a.push(3);
+        });
+    });
+    let (mut a, b) = (1, 2);
+    a = 34;
+
+    match 30 {
+        mut x => {
+            x = 21;
+        }
+    }
+
+    match (30, 2) {
+      (mut x, 1) |
+      (mut x, 2) |
+      (mut x, 3) => {
+        x = 21
+      }
+      _ => {}
+    }
+
+    let x = |mut y: isize| y = 32;
+    fn nothing(mut foo: isize) { foo = 37; }
+
+    // leading underscore should avoid the warning, just like the
+    // unused variable lint.
+    let mut _allowed = 1;
+}
+
+fn callback<F>(f: F) where F: FnOnce() {}
+
+// make sure the lint attribute can be turned off
+#[allow(unused_mut)]
+fn foo(mut a: isize) {
+    let mut a = 3;
+    let mut b = vec![2];
+}
+
+// make sure the lint attribute can be turned off on let statements
+#[deny(unused_mut)]
+fn bar() {
+    #[allow(unused_mut)]
+    let mut a = 3;
+    let mut b = vec![2]; //~ ERROR: variable does not need to be mutable
+
+}
diff --git a/src/test/ui/lint/lint-unused-mut-variables.stderr b/src/test/ui/lint/lint-unused-mut-variables.stderr
new file mode 100644
index 0000000..e41d8f8
--- /dev/null
+++ b/src/test/ui/lint/lint-unused-mut-variables.stderr
@@ -0,0 +1,150 @@
+error: variable does not need to be mutable
+  --> $DIR/lint-unused-mut-variables.rs:46:14
+   |
+LL |     let x = |mut y: isize| 10;
+   |              ----^
+   |              |
+   |              help: remove this `mut`
+   |
+note: lint level defined here
+  --> $DIR/lint-unused-mut-variables.rs:6:9
+   |
+LL | #![deny(unused_mut)]
+   |         ^^^^^^^^^^
+
+error: variable does not need to be mutable
+  --> $DIR/lint-unused-mut-variables.rs:11:9
+   |
+LL |     let mut a = 3;
+   |         ----^
+   |         |
+   |         help: remove this `mut`
+
+error: variable does not need to be mutable
+  --> $DIR/lint-unused-mut-variables.rs:13:9
+   |
+LL |     let mut a = 2;
+   |         ----^
+   |         |
+   |         help: remove this `mut`
+
+error: variable does not need to be mutable
+  --> $DIR/lint-unused-mut-variables.rs:15:9
+   |
+LL |     let mut b = 3;
+   |         ----^
+   |         |
+   |         help: remove this `mut`
+
+error: variable does not need to be mutable
+  --> $DIR/lint-unused-mut-variables.rs:17:9
+   |
+LL |     let mut a = vec![3];
+   |         ----^
+   |         |
+   |         help: remove this `mut`
+
+error: variable does not need to be mutable
+  --> $DIR/lint-unused-mut-variables.rs:19:10
+   |
+LL |     let (mut a, b) = (1, 2);
+   |          ----^
+   |          |
+   |          help: remove this `mut`
+
+error: variable does not need to be mutable
+  --> $DIR/lint-unused-mut-variables.rs:21:9
+   |
+LL |     let mut a;
+   |         ----^
+   |         |
+   |         help: remove this `mut`
+
+error: variable does not need to be mutable
+  --> $DIR/lint-unused-mut-variables.rs:25:9
+   |
+LL |     let mut b;
+   |         ----^
+   |         |
+   |         help: remove this `mut`
+
+error: variable does not need to be mutable
+  --> $DIR/lint-unused-mut-variables.rs:34:9
+   |
+LL |         mut x => {}
+   |         ----^
+   |         |
+   |         help: remove this `mut`
+
+error: variable does not need to be mutable
+  --> $DIR/lint-unused-mut-variables.rs:38:8
+   |
+LL |       (mut x, 1) |
+   |        ----^
+   |        |
+   |        help: remove this `mut`
+
+error: variable does not need to be mutable
+  --> $DIR/lint-unused-mut-variables.rs:51:9
+   |
+LL |     let mut a = &mut 5;
+   |         ----^
+   |         |
+   |         help: remove this `mut`
+
+error: variable does not need to be mutable
+  --> $DIR/lint-unused-mut-variables.rs:56:9
+   |
+LL |     let mut b = (&mut a,);
+   |         ----^
+   |         |
+   |         help: remove this `mut`
+
+error: variable does not need to be mutable
+  --> $DIR/lint-unused-mut-variables.rs:59:9
+   |
+LL |     let mut x = &mut 1;
+   |         ----^
+   |         |
+   |         help: remove this `mut`
+
+error: variable does not need to be mutable
+  --> $DIR/lint-unused-mut-variables.rs:71:9
+   |
+LL |     let mut v : &mut Vec<()> = &mut vec![];
+   |         ----^
+   |         |
+   |         help: remove this `mut`
+
+error: variable does not need to be mutable
+  --> $DIR/lint-unused-mut-variables.rs:48:13
+   |
+LL |     fn what(mut foo: isize) {}
+   |             ----^^^
+   |             |
+   |             help: remove this `mut`
+
+error: variable does not need to be mutable
+  --> $DIR/lint-unused-mut-variables.rs:66:20
+   |
+LL |     fn mut_ref_arg(mut arg : &mut [u8]) -> &mut [u8] {
+   |                    ----^^^
+   |                    |
+   |                    help: remove this `mut`
+
+error: variable does not need to be mutable
+  --> $DIR/lint-unused-mut-variables.rs:130:9
+   |
+LL |     let mut b = vec![2];
+   |         ----^
+   |         |
+   |         help: remove this `mut`
+   |
+note: lint level defined here
+  --> $DIR/lint-unused-mut-variables.rs:126:8
+   |
+LL | #[deny(unused_mut)]
+   |        ^^^^^^^^^^
+
+error: aborting due to 17 previous errors
+
diff --git a/src/test/ui/lint/lint-uppercase-variables.rs b/src/test/ui/lint/lint-uppercase-variables.rs
new file mode 100644
index 0000000..86a3950
--- /dev/null
+++ b/src/test/ui/lint/lint-uppercase-variables.rs
@@ -0,0 +1,31 @@
+#![warn(unused)]
+#![allow(dead_code)]
+#![deny(non_snake_case)]
+
+mod foo {
+    pub enum Foo { Foo }
+}
+
+struct Something {
+    X: usize //~ ERROR structure field `X` should have a snake case name
+}
+
+fn test(Xx: usize) { //~ ERROR variable `Xx` should have a snake case name
+    println!("{}", Xx);
+}
+
+fn main() {
+    let Test: usize = 0; //~ ERROR variable `Test` should have a snake case name
+    println!("{}", Test);
+
+    match foo::Foo::Foo {
+        Foo => {}
+//~^ ERROR variable `Foo` should have a snake case name
+//~^^ WARN `Foo` is named the same as one of the variants of the type `foo::Foo`
+//~^^^ WARN unused variable: `Foo`
+    }
+
+    test(1);
+
+    let _ = Something { X: 0 };
+}
diff --git a/src/test/ui/lint/lint-uppercase-variables.stderr b/src/test/ui/lint/lint-uppercase-variables.stderr
new file mode 100644
index 0000000..40c1323
--- /dev/null
+++ b/src/test/ui/lint/lint-uppercase-variables.stderr
@@ -0,0 +1,52 @@
+warning[E0170]: pattern binding `Foo` is named the same as one of the variants of the type `foo::Foo`
+  --> $DIR/lint-uppercase-variables.rs:22:9
+   |
+LL |         Foo => {}
+   |         ^^^ help: to match on the variant, qualify the path: `foo::Foo::Foo`
+
+warning: unused variable: `Foo`
+  --> $DIR/lint-uppercase-variables.rs:22:9
+   |
+LL |         Foo => {}
+   |         ^^^ help: consider prefixing with an underscore: `_Foo`
+   |
+note: lint level defined here
+  --> $DIR/lint-uppercase-variables.rs:1:9
+   |
+LL | #![warn(unused)]
+   |         ^^^^^^
+   = note: #[warn(unused_variables)] implied by #[warn(unused)]
+
+error: structure field `X` should have a snake case name
+  --> $DIR/lint-uppercase-variables.rs:10:5
+   |
+LL |     X: usize
+   |     ^ help: convert the identifier to snake case: `x`
+   |
+note: lint level defined here
+  --> $DIR/lint-uppercase-variables.rs:3:9
+   |
+LL | #![deny(non_snake_case)]
+   |         ^^^^^^^^^^^^^^
+
+error: variable `Xx` should have a snake case name
+  --> $DIR/lint-uppercase-variables.rs:13:9
+   |
+LL | fn test(Xx: usize) {
+   |         ^^ help: convert the identifier to snake case: `xx`
+
+error: variable `Test` should have a snake case name
+  --> $DIR/lint-uppercase-variables.rs:18:9
+   |
+LL |     let Test: usize = 0;
+   |         ^^^^ help: convert the identifier to snake case: `test`
+
+error: variable `Foo` should have a snake case name
+  --> $DIR/lint-uppercase-variables.rs:22:9
+   |
+LL |         Foo => {}
+   |         ^^^ help: convert the identifier to snake case: `foo`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0170`.
diff --git a/src/test/ui/lint/lints-in-foreign-macros.rs b/src/test/ui/lint/lints-in-foreign-macros.rs
new file mode 100644
index 0000000..adef2f9
--- /dev/null
+++ b/src/test/ui/lint/lints-in-foreign-macros.rs
@@ -0,0 +1,21 @@
+// aux-build:lints-in-foreign-macros.rs
+// compile-pass
+
+#![warn(unused_imports)] //~ missing documentation for crate [missing_docs]
+#![warn(missing_docs)]
+
+#[macro_use]
+extern crate lints_in_foreign_macros;
+
+macro_rules! foo {
+    () => {use std::string::ToString;} //~ WARN: unused import
+}
+
+mod a { foo!(); }
+mod b { bar!(); }
+mod c { baz!(use std::string::ToString;); } //~ WARN: unused import
+mod d { baz2!(use std::string::ToString;); } //~ WARN: unused import
+baz!(pub fn undocumented() {}); //~ WARN: missing documentation for a function
+baz2!(pub fn undocumented2() {}); //~ WARN: missing documentation for a function
+
+fn main() {}
diff --git a/src/test/ui/lint/lints-in-foreign-macros.stderr b/src/test/ui/lint/lints-in-foreign-macros.stderr
new file mode 100644
index 0000000..3fc3c22
--- /dev/null
+++ b/src/test/ui/lint/lints-in-foreign-macros.stderr
@@ -0,0 +1,57 @@
+warning: unused import: `std::string::ToString`
+  --> $DIR/lints-in-foreign-macros.rs:11:16
+   |
+LL |     () => {use std::string::ToString;}
+   |                ^^^^^^^^^^^^^^^^^^^^^
+...
+LL | mod a { foo!(); }
+   |         ------- in this macro invocation
+   |
+note: lint level defined here
+  --> $DIR/lints-in-foreign-macros.rs:4:9
+   |
+LL | #![warn(unused_imports)]
+   |         ^^^^^^^^^^^^^^
+
+warning: unused import: `std::string::ToString`
+  --> $DIR/lints-in-foreign-macros.rs:16:18
+   |
+LL | mod c { baz!(use std::string::ToString;); }
+   |                  ^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused import: `std::string::ToString`
+  --> $DIR/lints-in-foreign-macros.rs:17:19
+   |
+LL | mod d { baz2!(use std::string::ToString;); }
+   |                   ^^^^^^^^^^^^^^^^^^^^^
+
+warning: missing documentation for crate
+  --> $DIR/lints-in-foreign-macros.rs:4:1
+   |
+LL | / #![warn(unused_imports)]
+LL | | #![warn(missing_docs)]
+LL | |
+LL | | #[macro_use]
+...  |
+LL | |
+LL | | fn main() {}
+   | |____________^
+   |
+note: lint level defined here
+  --> $DIR/lints-in-foreign-macros.rs:5:9
+   |
+LL | #![warn(missing_docs)]
+   |         ^^^^^^^^^^^^
+
+warning: missing documentation for a function
+  --> $DIR/lints-in-foreign-macros.rs:18:6
+   |
+LL | baz!(pub fn undocumented() {});
+   |      ^^^^^^^^^^^^^^^^^^^^^
+
+warning: missing documentation for a function
+  --> $DIR/lints-in-foreign-macros.rs:19:7
+   |
+LL | baz2!(pub fn undocumented2() {});
+   |       ^^^^^^^^^^^^^^^^^^^^^^
+
diff --git a/src/test/ui/lint/must-use-ops.rs b/src/test/ui/lint/must-use-ops.rs
new file mode 100644
index 0000000..60baa23
--- /dev/null
+++ b/src/test/ui/lint/must-use-ops.rs
@@ -0,0 +1,41 @@
+// Issue #50124 - Test warning for unused operator expressions
+
+// compile-pass
+
+#![warn(unused_must_use)]
+
+fn main() {
+    let val = 1;
+    let val_pointer = &val;
+
+// Comparison Operators
+    val == 1;
+    val < 1;
+    val <= 1;
+    val != 1;
+    val >= 1;
+    val > 1;
+
+// Arithmetic Operators
+    val + 2;
+    val - 2;
+    val / 2;
+    val * 2;
+    val % 2;
+
+// Logical Operators
+    true && true;
+    false || true;
+
+// Bitwise Operators
+    5 ^ val;
+    5 & val;
+    5 | val;
+    5 << val;
+    5 >> val;
+
+// Unary Operators
+    !val;
+    -val;
+    *val_pointer;
+}
diff --git a/src/test/ui/lint/must-use-ops.stderr b/src/test/ui/lint/must-use-ops.stderr
new file mode 100644
index 0000000..febb4c1
--- /dev/null
+++ b/src/test/ui/lint/must-use-ops.stderr
@@ -0,0 +1,132 @@
+warning: unused comparison that must be used
+  --> $DIR/must-use-ops.rs:12:5
+   |
+LL |     val == 1;
+   |     ^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/must-use-ops.rs:5:9
+   |
+LL | #![warn(unused_must_use)]
+   |         ^^^^^^^^^^^^^^^
+
+warning: unused comparison that must be used
+  --> $DIR/must-use-ops.rs:13:5
+   |
+LL |     val < 1;
+   |     ^^^^^^^
+
+warning: unused comparison that must be used
+  --> $DIR/must-use-ops.rs:14:5
+   |
+LL |     val <= 1;
+   |     ^^^^^^^^
+
+warning: unused comparison that must be used
+  --> $DIR/must-use-ops.rs:15:5
+   |
+LL |     val != 1;
+   |     ^^^^^^^^
+
+warning: unused comparison that must be used
+  --> $DIR/must-use-ops.rs:16:5
+   |
+LL |     val >= 1;
+   |     ^^^^^^^^
+
+warning: unused comparison that must be used
+  --> $DIR/must-use-ops.rs:17:5
+   |
+LL |     val > 1;
+   |     ^^^^^^^
+
+warning: unused arithmetic operation that must be used
+  --> $DIR/must-use-ops.rs:20:5
+   |
+LL |     val + 2;
+   |     ^^^^^^^
+
+warning: unused arithmetic operation that must be used
+  --> $DIR/must-use-ops.rs:21:5
+   |
+LL |     val - 2;
+   |     ^^^^^^^
+
+warning: unused arithmetic operation that must be used
+  --> $DIR/must-use-ops.rs:22:5
+   |
+LL |     val / 2;
+   |     ^^^^^^^
+
+warning: unused arithmetic operation that must be used
+  --> $DIR/must-use-ops.rs:23:5
+   |
+LL |     val * 2;
+   |     ^^^^^^^
+
+warning: unused arithmetic operation that must be used
+  --> $DIR/must-use-ops.rs:24:5
+   |
+LL |     val % 2;
+   |     ^^^^^^^
+
+warning: unused logical operation that must be used
+  --> $DIR/must-use-ops.rs:27:5
+   |
+LL |     true && true;
+   |     ^^^^^^^^^^^^
+
+warning: unused logical operation that must be used
+  --> $DIR/must-use-ops.rs:28:5
+   |
+LL |     false || true;
+   |     ^^^^^^^^^^^^^
+
+warning: unused bitwise operation that must be used
+  --> $DIR/must-use-ops.rs:31:5
+   |
+LL |     5 ^ val;
+   |     ^^^^^^^
+
+warning: unused bitwise operation that must be used
+  --> $DIR/must-use-ops.rs:32:5
+   |
+LL |     5 & val;
+   |     ^^^^^^^
+
+warning: unused bitwise operation that must be used
+  --> $DIR/must-use-ops.rs:33:5
+   |
+LL |     5 | val;
+   |     ^^^^^^^
+
+warning: unused bitwise operation that must be used
+  --> $DIR/must-use-ops.rs:34:5
+   |
+LL |     5 << val;
+   |     ^^^^^^^^
+
+warning: unused bitwise operation that must be used
+  --> $DIR/must-use-ops.rs:35:5
+   |
+LL |     5 >> val;
+   |     ^^^^^^^^
+
+warning: unused unary operation that must be used
+  --> $DIR/must-use-ops.rs:38:5
+   |
+LL |     !val;
+   |     ^^^^
+
+warning: unused unary operation that must be used
+  --> $DIR/must-use-ops.rs:39:5
+   |
+LL |     -val;
+   |     ^^^^
+
+warning: unused unary operation that must be used
+  --> $DIR/must-use-ops.rs:40:5
+   |
+LL |     *val_pointer;
+   |     ^^^^^^^^^^^^
+
diff --git a/src/test/ui/lint/must_use-trait.rs b/src/test/ui/lint/must_use-trait.rs
new file mode 100644
index 0000000..23df4fa
--- /dev/null
+++ b/src/test/ui/lint/must_use-trait.rs
@@ -0,0 +1,22 @@
+#![deny(unused_must_use)]
+
+#[must_use]
+trait Critical {}
+
+trait NotSoCritical {}
+
+trait DecidedlyUnimportant {}
+
+struct Anon;
+
+impl Critical for Anon {}
+impl NotSoCritical for Anon {}
+impl DecidedlyUnimportant for Anon {}
+
+fn get_critical() -> impl NotSoCritical + Critical + DecidedlyUnimportant {
+    Anon {}
+}
+
+fn main() {
+    get_critical(); //~ ERROR unused implementer of `Critical` that must be used
+}
diff --git a/src/test/ui/lint/must_use-trait.stderr b/src/test/ui/lint/must_use-trait.stderr
new file mode 100644
index 0000000..7e2b2f6
--- /dev/null
+++ b/src/test/ui/lint/must_use-trait.stderr
@@ -0,0 +1,14 @@
+error: unused implementer of `Critical` that must be used
+  --> $DIR/must_use-trait.rs:21:5
+   |
+LL |     get_critical();
+   |     ^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/must_use-trait.rs:1:9
+   |
+LL | #![deny(unused_must_use)]
+   |         ^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lint/must_use-unit.rs b/src/test/ui/lint/must_use-unit.rs
new file mode 100644
index 0000000..9256825
--- /dev/null
+++ b/src/test/ui/lint/must_use-unit.rs
@@ -0,0 +1,17 @@
+#![feature(never_type)]
+
+#![deny(unused_must_use)]
+
+#[must_use]
+fn foo() {}
+
+#[must_use]
+fn bar() -> ! {
+    unimplemented!()
+}
+
+fn main() {
+    foo(); //~ unused return value of `foo`
+
+    bar(); //~ unused return value of `bar`
+}
diff --git a/src/test/ui/lint/must_use-unit.stderr b/src/test/ui/lint/must_use-unit.stderr
new file mode 100644
index 0000000..f6229c0
--- /dev/null
+++ b/src/test/ui/lint/must_use-unit.stderr
@@ -0,0 +1,20 @@
+error: unused return value of `foo` that must be used
+  --> $DIR/must_use-unit.rs:14:5
+   |
+LL |     foo();
+   |     ^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/must_use-unit.rs:3:9
+   |
+LL | #![deny(unused_must_use)]
+   |         ^^^^^^^^^^^^^^^
+
+error: unused return value of `bar` that must be used
+  --> $DIR/must_use-unit.rs:16:5
+   |
+LL |     bar();
+   |     ^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/lint/no-unused-parens-return-block.rs b/src/test/ui/lint/no-unused-parens-return-block.rs
new file mode 100644
index 0000000..37dc519
--- /dev/null
+++ b/src/test/ui/lint/no-unused-parens-return-block.rs
@@ -0,0 +1,9 @@
+// run-pass
+
+#![deny(unused_parens)]
+#![allow(unreachable_code)]
+
+fn main() {
+    match (return) {} // ok
+    if (return) {} // ok
+}
diff --git a/src/test/ui/lint/not_found.rs b/src/test/ui/lint/not_found.rs
new file mode 100644
index 0000000..0b5a4eb
--- /dev/null
+++ b/src/test/ui/lint/not_found.rs
@@ -0,0 +1,13 @@
+// compile-pass
+
+// this tests the `unknown_lint` lint, especially the suggestions
+
+// the suggestion only appears if a lint with the lowercase name exists
+#[allow(FOO_BAR)]
+// the suggestion appears on all-uppercase names
+#[warn(DEAD_CODE)]
+// the suggestion appears also on mixed-case names
+#[deny(Warnings)]
+fn main() {
+    unimplemented!();
+}
diff --git a/src/test/ui/lint/not_found.stderr b/src/test/ui/lint/not_found.stderr
new file mode 100644
index 0000000..266cf10
--- /dev/null
+++ b/src/test/ui/lint/not_found.stderr
@@ -0,0 +1,20 @@
+warning: unknown lint: `FOO_BAR`
+  --> $DIR/not_found.rs:6:9
+   |
+LL | #[allow(FOO_BAR)]
+   |         ^^^^^^^
+   |
+   = note: #[warn(unknown_lints)] on by default
+
+warning: unknown lint: `DEAD_CODE`
+  --> $DIR/not_found.rs:8:8
+   |
+LL | #[warn(DEAD_CODE)]
+   |        ^^^^^^^^^ help: did you mean: `dead_code`
+
+warning: unknown lint: `Warnings`
+  --> $DIR/not_found.rs:10:8
+   |
+LL | #[deny(Warnings)]
+   |        ^^^^^^^^ help: did you mean: `warnings`
+
diff --git a/src/test/ui/lint/outer-forbid.rs b/src/test/ui/lint/outer-forbid.rs
new file mode 100644
index 0000000..950533c
--- /dev/null
+++ b/src/test/ui/lint/outer-forbid.rs
@@ -0,0 +1,18 @@
+// Forbidding a group (here, `unused`) overrules subsequent allowance of both
+// the group, and an individual lint in the group (here, `unused_variables`);
+// and, forbidding an individual lint (here, `non_snake_case`) overrules
+// subsequent allowance of a lint group containing it (here, `nonstandard_style`). See
+// Issue #42873.
+
+#![forbid(unused, non_snake_case)]
+
+#[allow(unused_variables)] //~ ERROR overruled
+fn foo() {}
+
+#[allow(unused)] //~ ERROR overruled
+fn bar() {}
+
+#[allow(nonstandard_style)] //~ ERROR overruled
+fn main() {
+    println!("hello forbidden world")
+}
diff --git a/src/test/ui/lint/outer-forbid.stderr b/src/test/ui/lint/outer-forbid.stderr
new file mode 100644
index 0000000..310a5d88
--- /dev/null
+++ b/src/test/ui/lint/outer-forbid.stderr
@@ -0,0 +1,30 @@
+error[E0453]: allow(unused_variables) overruled by outer forbid(unused)
+  --> $DIR/outer-forbid.rs:9:9
+   |
+LL | #![forbid(unused, non_snake_case)]
+   |           ------ `forbid` level set here
+LL | 
+LL | #[allow(unused_variables)]
+   |         ^^^^^^^^^^^^^^^^ overruled by previous forbid
+
+error[E0453]: allow(unused) overruled by outer forbid(unused)
+  --> $DIR/outer-forbid.rs:12:9
+   |
+LL | #![forbid(unused, non_snake_case)]
+   |           ------ `forbid` level set here
+...
+LL | #[allow(unused)]
+   |         ^^^^^^ overruled by previous forbid
+
+error[E0453]: allow(nonstandard_style) overruled by outer forbid(non_snake_case)
+  --> $DIR/outer-forbid.rs:15:9
+   |
+LL | #![forbid(unused, non_snake_case)]
+   |                   -------------- `forbid` level set here
+...
+LL | #[allow(nonstandard_style)]
+   |         ^^^^^^^^^^^^^^^^^ overruled by previous forbid
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0453`.
diff --git a/src/test/ui/lint/reasons-erroneous.rs b/src/test/ui/lint/reasons-erroneous.rs
new file mode 100644
index 0000000..e42b329
--- /dev/null
+++ b/src/test/ui/lint/reasons-erroneous.rs
@@ -0,0 +1,24 @@
+#![feature(lint_reasons)]
+
+#![warn(absolute_paths_not_starting_with_crate, reason = 0)]
+//~^ ERROR malformed lint attribute
+//~| HELP reason must be a string literal
+#![warn(anonymous_parameters, reason = b"consider these, for we have condemned them")]
+//~^ ERROR malformed lint attribute
+//~| HELP reason must be a string literal
+#![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")]
+//~^ ERROR malformed lint attribute
+#![warn(box_pointers, blerp = "or in league with robbers have reversed the signposts")]
+//~^ ERROR malformed lint attribute
+#![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))]
+//~^ ERROR malformed lint attribute
+#![warn(ellipsis_inclusive_range_patterns, reason = "born barren", reason = "a freak growth")]
+//~^ ERROR malformed lint attribute
+//~| HELP reason in lint attribute must come last
+#![warn(keyword_idents, reason = "root in rubble", macro_use_extern_crate)]
+//~^ ERROR malformed lint attribute
+//~| HELP reason in lint attribute must come last
+#![warn(missing_copy_implementations, reason)]
+//~^ WARN unknown lint
+
+fn main() {}
diff --git a/src/test/ui/lint/reasons-erroneous.stderr b/src/test/ui/lint/reasons-erroneous.stderr
new file mode 100644
index 0000000..6842686
--- /dev/null
+++ b/src/test/ui/lint/reasons-erroneous.stderr
@@ -0,0 +1,61 @@
+error[E0452]: malformed lint attribute
+  --> $DIR/reasons-erroneous.rs:3:58
+   |
+LL | #![warn(absolute_paths_not_starting_with_crate, reason = 0)]
+   |                                                          ^
+   |
+   = help: reason must be a string literal
+
+error[E0452]: malformed lint attribute
+  --> $DIR/reasons-erroneous.rs:6:40
+   |
+LL | #![warn(anonymous_parameters, reason = b"consider these, for we have condemned them")]
+   |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: reason must be a string literal
+
+error[E0452]: malformed lint attribute
+  --> $DIR/reasons-erroneous.rs:9:29
+   |
+LL | #![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")]
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0452]: malformed lint attribute
+  --> $DIR/reasons-erroneous.rs:11:23
+   |
+LL | #![warn(box_pointers, blerp = "or in league with robbers have reversed the signposts")]
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0452]: malformed lint attribute
+  --> $DIR/reasons-erroneous.rs:13:36
+   |
+LL | #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))]
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0452]: malformed lint attribute
+  --> $DIR/reasons-erroneous.rs:15:44
+   |
+LL | #![warn(ellipsis_inclusive_range_patterns, reason = "born barren", reason = "a freak growth")]
+   |                                            ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: reason in lint attribute must come last
+
+error[E0452]: malformed lint attribute
+  --> $DIR/reasons-erroneous.rs:18:25
+   |
+LL | #![warn(keyword_idents, reason = "root in rubble", macro_use_extern_crate)]
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: reason in lint attribute must come last
+
+warning: unknown lint: `reason`
+  --> $DIR/reasons-erroneous.rs:21:39
+   |
+LL | #![warn(missing_copy_implementations, reason)]
+   |                                       ^^^^^^
+   |
+   = note: #[warn(unknown_lints)] on by default
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0452`.
diff --git a/src/test/ui/lint/reasons-forbidden.rs b/src/test/ui/lint/reasons-forbidden.rs
new file mode 100644
index 0000000..19ab767
--- /dev/null
+++ b/src/test/ui/lint/reasons-forbidden.rs
@@ -0,0 +1,21 @@
+#![feature(lint_reasons)]
+
+#![forbid(
+    unsafe_code,
+    //~^ NOTE `forbid` level set here
+    reason = "our errors & omissions insurance policy doesn't cover unsafe Rust"
+)]
+
+use std::ptr;
+
+fn main() {
+    let a_billion_dollar_mistake = ptr::null();
+
+    #[allow(unsafe_code)]
+    //~^ ERROR allow(unsafe_code) overruled by outer forbid(unsafe_code)
+    //~| NOTE overruled by previous forbid
+    //~| NOTE our errors & omissions insurance policy doesn't cover unsafe Rust
+    unsafe {
+        *a_billion_dollar_mistake
+    }
+}
diff --git a/src/test/ui/lint/reasons-forbidden.stderr b/src/test/ui/lint/reasons-forbidden.stderr
new file mode 100644
index 0000000..ea09e59
--- /dev/null
+++ b/src/test/ui/lint/reasons-forbidden.stderr
@@ -0,0 +1,14 @@
+error[E0453]: allow(unsafe_code) overruled by outer forbid(unsafe_code)
+  --> $DIR/reasons-forbidden.rs:14:13
+   |
+LL |     unsafe_code,
+   |     ----------- `forbid` level set here
+...
+LL |     #[allow(unsafe_code)]
+   |             ^^^^^^^^^^^ overruled by previous forbid
+   |
+   = note: our errors & omissions insurance policy doesn't cover unsafe Rust
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0453`.
diff --git a/src/test/ui/lint/reasons.rs b/src/test/ui/lint/reasons.rs
new file mode 100644
index 0000000..eba91d9
--- /dev/null
+++ b/src/test/ui/lint/reasons.rs
@@ -0,0 +1,33 @@
+// compile-pass
+
+#![feature(lint_reasons)]
+
+#![warn(elided_lifetimes_in_paths,
+        //~^ NOTE lint level defined here
+        reason = "explicit anonymous lifetimes aid reasoning about ownership")]
+#![warn(
+    nonstandard_style,
+    //~^ NOTE lint level defined here
+    reason = r#"people shouldn't have to change their usual style habits
+to contribute to our project"#
+)]
+#![allow(unused, reason = "unused code has never killed anypony")]
+
+use std::fmt;
+
+pub struct CheaterDetectionMechanism {}
+
+impl fmt::Debug for CheaterDetectionMechanism {
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+        //~^ WARN hidden lifetime parameters in types are deprecated
+        //~| NOTE explicit anonymous lifetimes aid
+        //~| HELP indicate the anonymous lifetime
+        fmt.debug_struct("CheaterDetectionMechanism").finish()
+    }
+}
+
+fn main() {
+    let Social_exchange_psychology = CheaterDetectionMechanism {};
+    //~^ WARN should have a snake case name such as
+    //~| NOTE people shouldn't have to change their usual style habits
+}
diff --git a/src/test/ui/lint/reasons.stderr b/src/test/ui/lint/reasons.stderr
new file mode 100644
index 0000000..3bb1480
--- /dev/null
+++ b/src/test/ui/lint/reasons.stderr
@@ -0,0 +1,28 @@
+warning: hidden lifetime parameters in types are deprecated
+  --> $DIR/reasons.rs:21:29
+   |
+LL |     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+   |                             ^^^^^^^^^^^^^^- help: indicate the anonymous lifetime: `<'_>`
+   |
+   = note: explicit anonymous lifetimes aid reasoning about ownership
+note: lint level defined here
+  --> $DIR/reasons.rs:5:9
+   |
+LL | #![warn(elided_lifetimes_in_paths,
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: variable `Social_exchange_psychology` should have a snake case name
+  --> $DIR/reasons.rs:30:9
+   |
+LL |     let Social_exchange_psychology = CheaterDetectionMechanism {};
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert the identifier to snake case: `social_exchange_psychology`
+   |
+   = note: people shouldn't have to change their usual style habits
+           to contribute to our project
+note: lint level defined here
+  --> $DIR/reasons.rs:9:5
+   |
+LL |     nonstandard_style,
+   |     ^^^^^^^^^^^^^^^^^
+   = note: #[warn(non_snake_case)] implied by #[warn(nonstandard_style)]
+
diff --git a/src/test/ui/lint/suggestions.rs b/src/test/ui/lint/suggestions.rs
new file mode 100644
index 0000000..67bd6dd
--- /dev/null
+++ b/src/test/ui/lint/suggestions.rs
@@ -0,0 +1,67 @@
+// ignore-tidy-tab
+
+#![warn(unused_mut, unused_parens)] // UI tests pass `-A unused`—see Issue #43896
+#![feature(no_debug)]
+
+#[no_mangle] const DISCOVERY: usize = 1;
+//~^ ERROR const items should never be #[no_mangle]
+//~| HELP try a static value
+
+#[no_mangle]
+//~^ HELP remove this attribute
+pub fn defiant<T>(_t: T) {}
+//~^ WARN functions generic over types or consts must be mangled
+
+#[no_mangle]
+fn rio_grande() {}
+
+mod badlands {
+    // The private-no-mangle lints shouldn't suggest inserting `pub` when the
+    // item is already `pub` (but triggered the lint because, e.g., it's in a
+    // private module). (Issue #47383)
+    #[no_mangle] pub const DAUNTLESS: bool = true;
+    //~^ ERROR const items should never be #[no_mangle]
+    //~| HELP try a static value
+    #[no_mangle] pub fn val_jean<T>() {}
+    //~^ WARN functions generic over types or consts must be mangled
+    //~| HELP remove this attribute
+
+    // ... but we can suggest just-`pub` instead of restricted
+    #[no_mangle] pub(crate) const VETAR: bool = true;
+    //~^ ERROR const items should never be #[no_mangle]
+    //~| HELP try a static value
+    #[no_mangle] pub(crate) fn crossfield<T>() {}
+    //~^ WARN functions generic over types or consts must be mangled
+    //~| HELP remove this attribute
+}
+
+struct Equinox {
+    warp_factor: f32,
+}
+
+#[no_debug] // should suggest removal of deprecated attribute
+//~^ WARN deprecated
+//~| HELP remove this attribute
+fn main() {
+    while true {
+    //~^ WARN denote infinite loops
+    //~| HELP use `loop`
+        let mut registry_no = (format!("NX-{}", 74205));
+        //~^ WARN does not need to be mutable
+        //~| HELP remove this `mut`
+        //~| WARN unnecessary parentheses
+        //~| HELP remove these parentheses
+        // the line after `mut` has a `\t` at the beginning, this is on purpose
+        let mut
+	        b = 1;
+        //~^^ WARN does not need to be mutable
+        //~| HELP remove this `mut`
+        let d = Equinox { warp_factor: 9.975 };
+        match d {
+            Equinox { warp_factor: warp_factor } => {}
+            //~^ WARN this pattern is redundant
+            //~| HELP remove this
+        }
+        println!("{} {}", registry_no, b);
+    }
+}
diff --git a/src/test/ui/lint/suggestions.stderr b/src/test/ui/lint/suggestions.stderr
new file mode 100644
index 0000000..5aaa994
--- /dev/null
+++ b/src/test/ui/lint/suggestions.stderr
@@ -0,0 +1,119 @@
+warning: unnecessary parentheses around assigned value
+  --> $DIR/suggestions.rs:49:31
+   |
+LL |         let mut registry_no = (format!("NX-{}", 74205));
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove these parentheses
+   |
+note: lint level defined here
+  --> $DIR/suggestions.rs:3:21
+   |
+LL | #![warn(unused_mut, unused_parens)] // UI tests pass `-A unused`—see Issue #43896
+   |                     ^^^^^^^^^^^^^
+
+warning: use of deprecated attribute `no_debug`: the `#[no_debug]` attribute was an experimental feature that has been deprecated due to lack of demand. See https://github.com/rust-lang/rust/issues/29721
+  --> $DIR/suggestions.rs:42:1
+   |
+LL | #[no_debug] // should suggest removal of deprecated attribute
+   | ^^^^^^^^^^^ help: remove this attribute
+   |
+   = note: #[warn(deprecated)] on by default
+
+warning: variable does not need to be mutable
+  --> $DIR/suggestions.rs:49:13
+   |
+LL |         let mut registry_no = (format!("NX-{}", 74205));
+   |             ----^^^^^^^^^^^
+   |             |
+   |             help: remove this `mut`
+   |
+note: lint level defined here
+  --> $DIR/suggestions.rs:3:9
+   |
+LL | #![warn(unused_mut, unused_parens)] // UI tests pass `-A unused`—see Issue #43896
+   |         ^^^^^^^^^^
+
+warning: variable does not need to be mutable
+  --> $DIR/suggestions.rs:55:13
+   |
+LL |            let mut
+   |   _____________^
+   |  |_____________|
+   | ||
+LL | ||             b = 1;
+   | ||____________-^
+   |  |____________|
+   |               help: remove this `mut`
+
+error: const items should never be #[no_mangle]
+  --> $DIR/suggestions.rs:6:14
+   |
+LL | #[no_mangle] const DISCOVERY: usize = 1;
+   |              -----^^^^^^^^^^^^^^^^^^^^^^
+   |              |
+   |              help: try a static value: `pub static`
+   |
+   = note: #[deny(no_mangle_const_items)] on by default
+
+warning: functions generic over types or consts must be mangled
+  --> $DIR/suggestions.rs:12:1
+   |
+LL | #[no_mangle]
+   | ------------ help: remove this attribute
+LL |
+LL | pub fn defiant<T>(_t: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: #[warn(no_mangle_generic_items)] on by default
+
+warning: denote infinite loops with `loop { ... }`
+  --> $DIR/suggestions.rs:46:5
+   |
+LL |     while true {
+   |     ^^^^^^^^^^ help: use `loop`
+   |
+   = note: #[warn(while_true)] on by default
+
+warning: the `warp_factor:` in this pattern is redundant
+  --> $DIR/suggestions.rs:61:23
+   |
+LL |             Equinox { warp_factor: warp_factor } => {}
+   |                       ------------^^^^^^^^^^^^
+   |                       |
+   |                       help: remove this
+   |
+   = note: #[warn(non_shorthand_field_patterns)] on by default
+
+error: const items should never be #[no_mangle]
+  --> $DIR/suggestions.rs:22:18
+   |
+LL |     #[no_mangle] pub const DAUNTLESS: bool = true;
+   |                  ---------^^^^^^^^^^^^^^^^^^^^^^^^
+   |                  |
+   |                  help: try a static value: `pub static`
+
+warning: functions generic over types or consts must be mangled
+  --> $DIR/suggestions.rs:25:18
+   |
+LL |     #[no_mangle] pub fn val_jean<T>() {}
+   |     ------------ ^^^^^^^^^^^^^^^^^^^^^^^
+   |     |
+   |     help: remove this attribute
+
+error: const items should never be #[no_mangle]
+  --> $DIR/suggestions.rs:30:18
+   |
+LL |     #[no_mangle] pub(crate) const VETAR: bool = true;
+   |                  ----------------^^^^^^^^^^^^^^^^^^^^
+   |                  |
+   |                  help: try a static value: `pub static`
+
+warning: functions generic over types or consts must be mangled
+  --> $DIR/suggestions.rs:33:18
+   |
+LL |     #[no_mangle] pub(crate) fn crossfield<T>() {}
+   |     ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     |
+   |     help: remove this attribute
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/lint/test-inner-fn.rs b/src/test/ui/lint/test-inner-fn.rs
new file mode 100644
index 0000000..d419cc6
--- /dev/null
+++ b/src/test/ui/lint/test-inner-fn.rs
@@ -0,0 +1,19 @@
+// compile-flags: --test -D unnameable_test_items
+
+#[test]
+fn foo() {
+    #[test] //~ ERROR cannot test inner items [unnameable_test_items]
+    fn bar() {}
+    bar();
+}
+
+mod x {
+    #[test]
+    fn foo() {
+        #[test] //~ ERROR cannot test inner items [unnameable_test_items]
+        fn bar() {}
+        bar();
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/lint/test-inner-fn.stderr b/src/test/ui/lint/test-inner-fn.stderr
new file mode 100644
index 0000000..bf476a4
--- /dev/null
+++ b/src/test/ui/lint/test-inner-fn.stderr
@@ -0,0 +1,16 @@
+error: cannot test inner items
+  --> $DIR/test-inner-fn.rs:5:5
+   |
+LL |     #[test]
+   |     ^^^^^^^
+   |
+   = note: requested on the command line with `-D unnameable-test-items`
+
+error: cannot test inner items
+  --> $DIR/test-inner-fn.rs:13:9
+   |
+LL |         #[test]
+   |         ^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/lint/trivial-casts-featuring-type-ascription.rs b/src/test/ui/lint/trivial-casts-featuring-type-ascription.rs
new file mode 100644
index 0000000..96bf2dc
--- /dev/null
+++ b/src/test/ui/lint/trivial-casts-featuring-type-ascription.rs
@@ -0,0 +1,10 @@
+#![deny(trivial_casts, trivial_numeric_casts)]
+#![feature(type_ascription)]
+
+fn main() {
+    let lugubrious = 12i32 as i32;
+    //~^ ERROR trivial numeric cast
+    let haunted: &u32 = &99;
+    let _ = haunted as *const u32;
+    //~^ ERROR trivial cast
+}
diff --git a/src/test/ui/lint/trivial-casts-featuring-type-ascription.stderr b/src/test/ui/lint/trivial-casts-featuring-type-ascription.stderr
new file mode 100644
index 0000000..c1a4b39
--- /dev/null
+++ b/src/test/ui/lint/trivial-casts-featuring-type-ascription.stderr
@@ -0,0 +1,28 @@
+error: trivial numeric cast: `i32` as `i32`
+  --> $DIR/trivial-casts-featuring-type-ascription.rs:5:22
+   |
+LL |     let lugubrious = 12i32 as i32;
+   |                      ^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/trivial-casts-featuring-type-ascription.rs:1:24
+   |
+LL | #![deny(trivial_casts, trivial_numeric_casts)]
+   |                        ^^^^^^^^^^^^^^^^^^^^^
+   = help: cast can be replaced by coercion; this might require type ascription or a temporary variable
+
+error: trivial cast: `&u32` as `*const u32`
+  --> $DIR/trivial-casts-featuring-type-ascription.rs:8:13
+   |
+LL |     let _ = haunted as *const u32;
+   |             ^^^^^^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/trivial-casts-featuring-type-ascription.rs:1:9
+   |
+LL | #![deny(trivial_casts, trivial_numeric_casts)]
+   |         ^^^^^^^^^^^^^
+   = help: cast can be replaced by coercion; this might require type ascription or a temporary variable
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/lint/trivial-casts.rs b/src/test/ui/lint/trivial-casts.rs
new file mode 100644
index 0000000..b17de624
--- /dev/null
+++ b/src/test/ui/lint/trivial-casts.rs
@@ -0,0 +1,9 @@
+#![deny(trivial_casts, trivial_numeric_casts)]
+
+fn main() {
+    let lugubrious = 12i32 as i32;
+    //~^ ERROR trivial numeric cast
+    let haunted: &u32 = &99;
+    let _ = haunted as *const u32;
+    //~^ ERROR trivial cast
+}
diff --git a/src/test/ui/lint/trivial-casts.stderr b/src/test/ui/lint/trivial-casts.stderr
new file mode 100644
index 0000000..f411db1
--- /dev/null
+++ b/src/test/ui/lint/trivial-casts.stderr
@@ -0,0 +1,28 @@
+error: trivial numeric cast: `i32` as `i32`
+  --> $DIR/trivial-casts.rs:4:22
+   |
+LL |     let lugubrious = 12i32 as i32;
+   |                      ^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/trivial-casts.rs:1:24
+   |
+LL | #![deny(trivial_casts, trivial_numeric_casts)]
+   |                        ^^^^^^^^^^^^^^^^^^^^^
+   = help: cast can be replaced by coercion; this might require a temporary variable
+
+error: trivial cast: `&u32` as `*const u32`
+  --> $DIR/trivial-casts.rs:7:13
+   |
+LL |     let _ = haunted as *const u32;
+   |             ^^^^^^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/trivial-casts.rs:1:9
+   |
+LL | #![deny(trivial_casts, trivial_numeric_casts)]
+   |         ^^^^^^^^^^^^^
+   = help: cast can be replaced by coercion; this might require a temporary variable
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/lint/type-overflow.rs b/src/test/ui/lint/type-overflow.rs
new file mode 100644
index 0000000..64e5951
--- /dev/null
+++ b/src/test/ui/lint/type-overflow.rs
@@ -0,0 +1,22 @@
+// compile-pass
+#![warn(overflowing_literals)]
+
+fn main() {
+    let error = 255i8; //~WARNING literal out of range for i8
+
+    let ok = 0b1000_0001; // should be ok -> i32
+    let ok = 0b0111_1111i8; // should be ok -> 127i8
+
+    let fail = 0b1000_0001i8; //~WARNING literal out of range for i8
+
+    let fail = 0x8000_0000_0000_0000i64; //~WARNING literal out of range for i64
+
+    let fail = 0x1_FFFF_FFFFu32; //~WARNING literal out of range for u32
+
+    let fail: i128 = 0x8000_0000_0000_0000_0000_0000_0000_0000;
+    //~^ WARNING literal out of range for i128
+
+    let fail = 0x8FFF_FFFF_FFFF_FFFE; //~WARNING literal out of range for i32
+
+    let fail = -0b1111_1111i8; //~WARNING literal out of range for i8
+}
diff --git a/src/test/ui/lint/type-overflow.stderr b/src/test/ui/lint/type-overflow.stderr
new file mode 100644
index 0000000..5235c985
--- /dev/null
+++ b/src/test/ui/lint/type-overflow.stderr
@@ -0,0 +1,62 @@
+warning: literal out of range for i8
+  --> $DIR/type-overflow.rs:5:17
+   |
+LL |     let error = 255i8;
+   |                 ^^^^^
+   |
+note: lint level defined here
+  --> $DIR/type-overflow.rs:2:9
+   |
+LL | #![warn(overflowing_literals)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+warning: literal out of range for i8
+  --> $DIR/type-overflow.rs:10:16
+   |
+LL |     let fail = 0b1000_0001i8;
+   |                ^^^^^^^^^^^^^ help: consider using `u8` instead: `0b1000_0001u8`
+   |
+   = note: the literal `0b1000_0001i8` (decimal `129`) does not fit into an `i8` and will become `-127i8`
+
+warning: literal out of range for i64
+  --> $DIR/type-overflow.rs:12:16
+   |
+LL |     let fail = 0x8000_0000_0000_0000i64;
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `u64` instead: `0x8000_0000_0000_0000u64`
+   |
+   = note: the literal `0x8000_0000_0000_0000i64` (decimal `9223372036854775808`) does not fit into an `i64` and will become `-9223372036854775808i64`
+
+warning: literal out of range for u32
+  --> $DIR/type-overflow.rs:14:16
+   |
+LL |     let fail = 0x1_FFFF_FFFFu32;
+   |                ^^^^^^^^^^^^^^^^ help: consider using `u64` instead: `0x1_FFFF_FFFFu64`
+   |
+   = note: the literal `0x1_FFFF_FFFFu32` (decimal `8589934591`) does not fit into an `u32` and will become `4294967295u32`
+
+warning: literal out of range for i128
+  --> $DIR/type-overflow.rs:16:22
+   |
+LL |     let fail: i128 = 0x8000_0000_0000_0000_0000_0000_0000_0000;
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the literal `0x8000_0000_0000_0000_0000_0000_0000_0000` (decimal `170141183460469231731687303715884105728`) does not fit into an `i128` and will become `-170141183460469231731687303715884105728i128`
+   = help: consider using `u128` instead
+
+warning: literal out of range for i32
+  --> $DIR/type-overflow.rs:19:16
+   |
+LL |     let fail = 0x8FFF_FFFF_FFFF_FFFE;
+   |                ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the literal `0x8FFF_FFFF_FFFF_FFFE` (decimal `10376293541461622782`) does not fit into an `i32` and will become `-2i32`
+   = help: consider using `i128` instead
+
+warning: literal out of range for i8
+  --> $DIR/type-overflow.rs:21:17
+   |
+LL |     let fail = -0b1111_1111i8;
+   |                 ^^^^^^^^^^^^^ help: consider using `i16` instead: `0b1111_1111i16`
+   |
+   = note: the literal `0b1111_1111i8` (decimal `255`) does not fit into an `i8` and will become `-1i8`
+
diff --git a/src/test/ui/lint/unreachable_pub-pub_crate.rs b/src/test/ui/lint/unreachable_pub-pub_crate.rs
new file mode 100644
index 0000000..6739c7f
--- /dev/null
+++ b/src/test/ui/lint/unreachable_pub-pub_crate.rs
@@ -0,0 +1,66 @@
+// This is just like unreachable_pub.rs, but without the
+// `crate_visibility_modifier` feature (so that we can test the suggestions to
+// use `pub(crate)` that are given when that feature is off, as opposed to the
+// suggestions to use `crate` given when it is on). When that feature becomes
+// stable, this test can be deleted.
+
+// compile-pass
+
+
+#![allow(unused)]
+#![warn(unreachable_pub)]
+
+mod private_mod {
+    // non-leaked `pub` items in private module should be linted
+    pub use std::fmt;
+    pub use std::env::{Args}; // braced-use has different item spans than unbraced
+
+    pub struct Hydrogen {
+        // `pub` struct fields, too
+        pub neutrons: usize,
+        // (... but not more-restricted fields)
+        pub(crate) electrons: usize
+    }
+    impl Hydrogen {
+        // impls, too
+        pub fn count_neutrons(&self) -> usize { self.neutrons }
+        pub(crate) fn count_electrons(&self) -> usize { self.electrons }
+    }
+
+    pub enum Helium {}
+    pub union Lithium { c1: usize, c2: u8 }
+    pub fn beryllium() {}
+    pub trait Boron {}
+    pub const CARBON: usize = 1;
+    pub static NITROGEN: usize = 2;
+    pub type Oxygen = bool;
+
+    macro_rules! define_empty_struct_with_visibility {
+        ($visibility: vis, $name: ident) => { $visibility struct $name {} }
+    }
+    define_empty_struct_with_visibility!(pub, Fluorine);
+
+    extern {
+        pub fn catalyze() -> bool;
+    }
+
+    // items leaked through signatures (see `get_neon` below) are OK
+    pub struct Neon {}
+
+    // crate-visible items are OK
+    pub(crate) struct Sodium {}
+}
+
+pub mod public_mod {
+    // module is public: these are OK, too
+    pub struct Magnesium {}
+    pub(crate) struct Aluminum {}
+}
+
+pub fn get_neon() -> private_mod::Neon {
+    private_mod::Neon {}
+}
+
+fn main() {
+    let _ = get_neon();
+}
diff --git a/src/test/ui/lint/unreachable_pub-pub_crate.stderr b/src/test/ui/lint/unreachable_pub-pub_crate.stderr
new file mode 100644
index 0000000..2b3f74a
--- /dev/null
+++ b/src/test/ui/lint/unreachable_pub-pub_crate.stderr
@@ -0,0 +1,145 @@
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub-pub_crate.rs:15:5
+   |
+LL |     pub use std::fmt;
+   |     ---^^^^^^^^^^^^^^
+   |     |
+   |     help: consider restricting its visibility: `pub(crate)`
+   |
+note: lint level defined here
+  --> $DIR/unreachable_pub-pub_crate.rs:11:9
+   |
+LL | #![warn(unreachable_pub)]
+   |         ^^^^^^^^^^^^^^^
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub-pub_crate.rs:16:24
+   |
+LL |     pub use std::env::{Args}; // braced-use has different item spans than unbraced
+   |     ---                ^^^^
+   |     |
+   |     help: consider restricting its visibility: `pub(crate)`
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub-pub_crate.rs:18:5
+   |
+LL |     pub struct Hydrogen {
+   |     ---^^^^^^^^^^^^^^^^
+   |     |
+   |     help: consider restricting its visibility: `pub(crate)`
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` field
+  --> $DIR/unreachable_pub-pub_crate.rs:20:9
+   |
+LL |         pub neutrons: usize,
+   |         ---^^^^^^^^^^^^^^^^
+   |         |
+   |         help: consider restricting its visibility: `pub(crate)`
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub-pub_crate.rs:26:9
+   |
+LL |         pub fn count_neutrons(&self) -> usize { self.neutrons }
+   |         ---^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |         |
+   |         help: consider restricting its visibility: `pub(crate)`
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub-pub_crate.rs:30:5
+   |
+LL |     pub enum Helium {}
+   |     ---^^^^^^^^^^^^
+   |     |
+   |     help: consider restricting its visibility: `pub(crate)`
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub-pub_crate.rs:31:5
+   |
+LL |     pub union Lithium { c1: usize, c2: u8 }
+   |     ---^^^^^^^^^^^^^^
+   |     |
+   |     help: consider restricting its visibility: `pub(crate)`
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub-pub_crate.rs:32:5
+   |
+LL |     pub fn beryllium() {}
+   |     ---^^^^^^^^^^^^^^^
+   |     |
+   |     help: consider restricting its visibility: `pub(crate)`
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub-pub_crate.rs:33:5
+   |
+LL |     pub trait Boron {}
+   |     ---^^^^^^^^^^^^
+   |     |
+   |     help: consider restricting its visibility: `pub(crate)`
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub-pub_crate.rs:34:5
+   |
+LL |     pub const CARBON: usize = 1;
+   |     ---^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     |
+   |     help: consider restricting its visibility: `pub(crate)`
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub-pub_crate.rs:35:5
+   |
+LL |     pub static NITROGEN: usize = 2;
+   |     ---^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     |
+   |     help: consider restricting its visibility: `pub(crate)`
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub-pub_crate.rs:36:5
+   |
+LL |     pub type Oxygen = bool;
+   |     ---^^^^^^^^^^^^^^^^^^^^
+   |     |
+   |     help: consider restricting its visibility: `pub(crate)`
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub-pub_crate.rs:39:47
+   |
+LL |         ($visibility: vis, $name: ident) => { $visibility struct $name {} }
+   |                                               ^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     }
+LL |     define_empty_struct_with_visibility!(pub, Fluorine);
+   |     ----------------------------------------------------
+   |     |                                    |
+   |     |                                    help: consider restricting its visibility: `pub(crate)`
+   |     in this macro invocation
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub-pub_crate.rs:44:9
+   |
+LL |         pub fn catalyze() -> bool;
+   |         ---^^^^^^^^^^^^^^^^^^^^^^^
+   |         |
+   |         help: consider restricting its visibility: `pub(crate)`
+   |
+   = help: or consider exporting it for use by other crates
+
diff --git a/src/test/ui/lint/unreachable_pub.rs b/src/test/ui/lint/unreachable_pub.rs
new file mode 100644
index 0000000..12726b6
--- /dev/null
+++ b/src/test/ui/lint/unreachable_pub.rs
@@ -0,0 +1,61 @@
+// compile-pass
+
+#![feature(crate_visibility_modifier)]
+
+#![allow(unused)]
+#![warn(unreachable_pub)]
+
+mod private_mod {
+    // non-leaked `pub` items in private module should be linted
+    pub use std::fmt;
+    pub use std::env::{Args}; // braced-use has different item spans than unbraced
+
+    pub struct Hydrogen {
+        // `pub` struct fields, too
+        pub neutrons: usize,
+        // (... but not more-restricted fields)
+        crate electrons: usize
+    }
+    impl Hydrogen {
+        // impls, too
+        pub fn count_neutrons(&self) -> usize { self.neutrons }
+        crate fn count_electrons(&self) -> usize { self.electrons }
+    }
+
+    pub enum Helium {}
+    pub union Lithium { c1: usize, c2: u8 }
+    pub fn beryllium() {}
+    pub trait Boron {}
+    pub const CARBON: usize = 1;
+    pub static NITROGEN: usize = 2;
+    pub type Oxygen = bool;
+
+    macro_rules! define_empty_struct_with_visibility {
+        ($visibility: vis, $name: ident) => { $visibility struct $name {} }
+    }
+    define_empty_struct_with_visibility!(pub, Fluorine);
+
+    extern {
+        pub fn catalyze() -> bool;
+    }
+
+    // items leaked through signatures (see `get_neon` below) are OK
+    pub struct Neon {}
+
+    // crate-visible items are OK
+    crate struct Sodium {}
+}
+
+pub mod public_mod {
+    // module is public: these are OK, too
+    pub struct Magnesium {}
+    crate struct Aluminum {}
+}
+
+pub fn get_neon() -> private_mod::Neon {
+    private_mod::Neon {}
+}
+
+fn main() {
+    let _ = get_neon();
+}
diff --git a/src/test/ui/lint/unreachable_pub.stderr b/src/test/ui/lint/unreachable_pub.stderr
new file mode 100644
index 0000000..6352f3e
--- /dev/null
+++ b/src/test/ui/lint/unreachable_pub.stderr
@@ -0,0 +1,145 @@
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub.rs:10:5
+   |
+LL |     pub use std::fmt;
+   |     ---^^^^^^^^^^^^^^
+   |     |
+   |     help: consider restricting its visibility: `crate`
+   |
+note: lint level defined here
+  --> $DIR/unreachable_pub.rs:6:9
+   |
+LL | #![warn(unreachable_pub)]
+   |         ^^^^^^^^^^^^^^^
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub.rs:11:24
+   |
+LL |     pub use std::env::{Args}; // braced-use has different item spans than unbraced
+   |     ---                ^^^^
+   |     |
+   |     help: consider restricting its visibility: `crate`
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub.rs:13:5
+   |
+LL |     pub struct Hydrogen {
+   |     ---^^^^^^^^^^^^^^^^
+   |     |
+   |     help: consider restricting its visibility: `crate`
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` field
+  --> $DIR/unreachable_pub.rs:15:9
+   |
+LL |         pub neutrons: usize,
+   |         ---^^^^^^^^^^^^^^^^
+   |         |
+   |         help: consider restricting its visibility: `crate`
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub.rs:21:9
+   |
+LL |         pub fn count_neutrons(&self) -> usize { self.neutrons }
+   |         ---^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |         |
+   |         help: consider restricting its visibility: `crate`
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub.rs:25:5
+   |
+LL |     pub enum Helium {}
+   |     ---^^^^^^^^^^^^
+   |     |
+   |     help: consider restricting its visibility: `crate`
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub.rs:26:5
+   |
+LL |     pub union Lithium { c1: usize, c2: u8 }
+   |     ---^^^^^^^^^^^^^^
+   |     |
+   |     help: consider restricting its visibility: `crate`
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub.rs:27:5
+   |
+LL |     pub fn beryllium() {}
+   |     ---^^^^^^^^^^^^^^^
+   |     |
+   |     help: consider restricting its visibility: `crate`
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub.rs:28:5
+   |
+LL |     pub trait Boron {}
+   |     ---^^^^^^^^^^^^
+   |     |
+   |     help: consider restricting its visibility: `crate`
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub.rs:29:5
+   |
+LL |     pub const CARBON: usize = 1;
+   |     ---^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     |
+   |     help: consider restricting its visibility: `crate`
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub.rs:30:5
+   |
+LL |     pub static NITROGEN: usize = 2;
+   |     ---^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     |
+   |     help: consider restricting its visibility: `crate`
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub.rs:31:5
+   |
+LL |     pub type Oxygen = bool;
+   |     ---^^^^^^^^^^^^^^^^^^^^
+   |     |
+   |     help: consider restricting its visibility: `crate`
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub.rs:34:47
+   |
+LL |         ($visibility: vis, $name: ident) => { $visibility struct $name {} }
+   |                                               ^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     }
+LL |     define_empty_struct_with_visibility!(pub, Fluorine);
+   |     ----------------------------------------------------
+   |     |                                    |
+   |     |                                    help: consider restricting its visibility: `crate`
+   |     in this macro invocation
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub.rs:39:9
+   |
+LL |         pub fn catalyze() -> bool;
+   |         ---^^^^^^^^^^^^^^^^^^^^^^^
+   |         |
+   |         help: consider restricting its visibility: `crate`
+   |
+   = help: or consider exporting it for use by other crates
+
diff --git a/src/test/ui/lint/unused_labels.rs b/src/test/ui/lint/unused_labels.rs
new file mode 100644
index 0000000..26ab9fb
--- /dev/null
+++ b/src/test/ui/lint/unused_labels.rs
@@ -0,0 +1,86 @@
+// The output should warn when a loop label is not used. However, it
+// should also deal with the edge cases where a label is shadowed,
+// within nested loops
+
+// compile-pass
+
+#![feature(label_break_value)]
+#![warn(unused_labels)]
+
+fn main() {
+    'unused_while_label: while 0 == 0 {
+        //~^ WARN unused label
+    }
+
+    let opt = Some(0);
+    'unused_while_let_label: while let Some(_) = opt {
+        //~^ WARN unused label
+    }
+
+    'unused_for_label: for _ in 0..10 {
+        //~^ WARN unused label
+    }
+
+    'used_loop_label: loop {
+        break 'used_loop_label;
+    }
+
+    'used_loop_label_outer_1: for _ in 0..10 {
+        'used_loop_label_inner_1: for _ in 0..10 {
+            break 'used_loop_label_inner_1;
+        }
+        break 'used_loop_label_outer_1;
+    }
+
+    'used_loop_label_outer_2: for _ in 0..10 {
+        'unused_loop_label_inner_2: for _ in 0..10 {
+            //~^ WARN unused label
+            break 'used_loop_label_outer_2;
+        }
+    }
+
+    'unused_loop_label_outer_3: for _ in 0..10 {
+        //~^ WARN unused label
+        'used_loop_label_inner_3: for _ in 0..10 {
+            break 'used_loop_label_inner_3;
+        }
+    }
+
+    // You should be able to break the same label many times
+    'many_used: loop {
+        if true {
+            break 'many_used;
+        } else {
+            break 'many_used;
+        }
+    }
+
+    // Test breaking many times with the same inner label doesn't break the
+    // warning on the outer label
+    'many_used_shadowed: for _ in 0..10 {
+        //~^ WARN unused label
+        'many_used_shadowed: for _ in 0..10 {
+            //~^ WARN label name `'many_used_shadowed` shadows a label name that is already in scope
+            if 1 % 2 == 0 {
+                break 'many_used_shadowed;
+            } else {
+                break 'many_used_shadowed;
+            }
+        }
+    }
+
+    'unused_loop_label: loop {
+        //~^ WARN unused label
+        break;
+    }
+
+    // Make sure unused block labels give warnings...
+    'unused_block_label: {
+        //~^ WARN unused label
+    }
+
+    // ...and that used ones don't:
+    'used_block_label: {
+        break 'used_block_label;
+    }
+}
diff --git a/src/test/ui/lint/unused_labels.stderr b/src/test/ui/lint/unused_labels.stderr
new file mode 100644
index 0000000..08f8548
--- /dev/null
+++ b/src/test/ui/lint/unused_labels.stderr
@@ -0,0 +1,63 @@
+warning: unused label
+  --> $DIR/unused_labels.rs:11:5
+   |
+LL |     'unused_while_label: while 0 == 0 {
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/unused_labels.rs:8:9
+   |
+LL | #![warn(unused_labels)]
+   |         ^^^^^^^^^^^^^
+
+warning: unused label
+  --> $DIR/unused_labels.rs:16:5
+   |
+LL |     'unused_while_let_label: while let Some(_) = opt {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused label
+  --> $DIR/unused_labels.rs:20:5
+   |
+LL |     'unused_for_label: for _ in 0..10 {
+   |     ^^^^^^^^^^^^^^^^^
+
+warning: unused label
+  --> $DIR/unused_labels.rs:36:9
+   |
+LL |         'unused_loop_label_inner_2: for _ in 0..10 {
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused label
+  --> $DIR/unused_labels.rs:42:5
+   |
+LL |     'unused_loop_label_outer_3: for _ in 0..10 {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused label
+  --> $DIR/unused_labels.rs:60:5
+   |
+LL |     'many_used_shadowed: for _ in 0..10 {
+   |     ^^^^^^^^^^^^^^^^^^^
+
+warning: unused label
+  --> $DIR/unused_labels.rs:72:5
+   |
+LL |     'unused_loop_label: loop {
+   |     ^^^^^^^^^^^^^^^^^^
+
+warning: unused label
+  --> $DIR/unused_labels.rs:78:5
+   |
+LL |     'unused_block_label: {
+   |     ^^^^^^^^^^^^^^^^^^^
+
+warning: label name `'many_used_shadowed` shadows a label name that is already in scope
+  --> $DIR/unused_labels.rs:62:9
+   |
+LL |     'many_used_shadowed: for _ in 0..10 {
+   |     ------------------- first declared here
+LL |
+LL |         'many_used_shadowed: for _ in 0..10 {
+   |         ^^^^^^^^^^^^^^^^^^^ lifetime 'many_used_shadowed already in scope
+
diff --git a/src/test/ui/lint/unused_parens_json_suggestion.rs b/src/test/ui/lint/unused_parens_json_suggestion.rs
new file mode 100644
index 0000000..4462c53
--- /dev/null
+++ b/src/test/ui/lint/unused_parens_json_suggestion.rs
@@ -0,0 +1,25 @@
+// compile-flags: --error-format pretty-json -Zunstable-options
+// compile-pass
+
+// The output for humans should just highlight the whole span without showing
+// the suggested replacement, but we also want to test that suggested
+// replacement only removes one set of parentheses, rather than naïvely
+// stripping away any starting or ending parenthesis characters—hence this
+// test of the JSON error format.
+
+#![warn(unused_parens)]
+
+fn main() {
+    // We want to suggest the properly-balanced expression `1 / (2 + 3)`, not
+    // the malformed `1 / (2 + 3`
+    let _a = (1 / (2 + 3));
+    f();
+}
+
+fn f() -> bool {
+    loop {
+        if (break { return true }) {
+        }
+    }
+    false
+}
diff --git a/src/test/ui/lint/unused_parens_json_suggestion.stderr b/src/test/ui/lint/unused_parens_json_suggestion.stderr
new file mode 100644
index 0000000..07d96d5
--- /dev/null
+++ b/src/test/ui/lint/unused_parens_json_suggestion.stderr
@@ -0,0 +1,106 @@
+{
+  "message": "unnecessary parentheses around assigned value",
+  "code": {
+    "code": "unused_parens",
+    "explanation": null
+  },
+  "level": "warning",
+  "spans": [
+    {
+      "file_name": "$DIR/unused_parens_json_suggestion.rs",
+      "byte_start": 576,
+      "byte_end": 589,
+      "line_start": 15,
+      "line_end": 15,
+      "column_start": 14,
+      "column_end": 27,
+      "is_primary": true,
+      "text": [
+        {
+          "text": "    let _a = (1 / (2 + 3));",
+          "highlight_start": 14,
+          "highlight_end": 27
+        }
+      ],
+      "label": null,
+      "suggested_replacement": null,
+      "suggestion_applicability": null,
+      "expansion": null
+    }
+  ],
+  "children": [
+    {
+      "message": "lint level defined here",
+      "code": null,
+      "level": "note",
+      "spans": [
+        {
+          "file_name": "$DIR/unused_parens_json_suggestion.rs",
+          "byte_start": 422,
+          "byte_end": 435,
+          "line_start": 10,
+          "line_end": 10,
+          "column_start": 9,
+          "column_end": 22,
+          "is_primary": true,
+          "text": [
+            {
+              "text": "#![warn(unused_parens)]",
+              "highlight_start": 9,
+              "highlight_end": 22
+            }
+          ],
+          "label": null,
+          "suggested_replacement": null,
+          "suggestion_applicability": null,
+          "expansion": null
+        }
+      ],
+      "children": [],
+      "rendered": null
+    },
+    {
+      "message": "remove these parentheses",
+      "code": null,
+      "level": "help",
+      "spans": [
+        {
+          "file_name": "$DIR/unused_parens_json_suggestion.rs",
+          "byte_start": 576,
+          "byte_end": 589,
+          "line_start": 15,
+          "line_end": 15,
+          "column_start": 14,
+          "column_end": 27,
+          "is_primary": true,
+          "text": [
+            {
+              "text": "    let _a = (1 / (2 + 3));",
+              "highlight_start": 14,
+              "highlight_end": 27
+            }
+          ],
+          "label": null,
+          "suggested_replacement": "1 / (2 + 3)",
+          "suggestion_applicability": "MachineApplicable",
+          "expansion": null
+        }
+      ],
+      "children": [],
+      "rendered": null
+    }
+  ],
+  "rendered": "warning: unnecessary parentheses around assigned value
+  --> $DIR/unused_parens_json_suggestion.rs:15:14
+   |
+LL |     let _a = (1 / (2 + 3));
+   |              ^^^^^^^^^^^^^ help: remove these parentheses
+   |
+note: lint level defined here
+  --> $DIR/unused_parens_json_suggestion.rs:10:9
+   |
+LL | #![warn(unused_parens)]
+   |         ^^^^^^^^^^^^^
+
+"
+}
diff --git a/src/test/ui/lint/use-redundant.rs b/src/test/ui/lint/use-redundant.rs
new file mode 100644
index 0000000..328f823
--- /dev/null
+++ b/src/test/ui/lint/use-redundant.rs
@@ -0,0 +1,27 @@
+// compile-pass
+#![warn(unused_imports)]
+
+use crate::foo::Bar; //~ WARNING first import
+
+mod foo {
+    pub type Bar = i32;
+}
+
+fn baz() -> Bar {
+    3
+}
+
+mod m1 { pub struct S {} }
+mod m2 { pub struct S {} }
+
+use m1::*;
+use m2::*;
+
+fn main() {
+    use crate::foo::Bar; //~ WARNING redundant import
+    let _a: Bar = 3;
+    baz();
+
+    use m1::S; //~ WARNING redundant import
+    let _s = S {};
+}
diff --git a/src/test/ui/lint/use-redundant.stderr b/src/test/ui/lint/use-redundant.stderr
new file mode 100644
index 0000000..fbd9f81
--- /dev/null
+++ b/src/test/ui/lint/use-redundant.stderr
@@ -0,0 +1,27 @@
+warning: unused import: `m1::*`
+  --> $DIR/use-redundant.rs:17:5
+   |
+LL | use m1::*;
+   |     ^^^^^
+   |
+note: lint level defined here
+  --> $DIR/use-redundant.rs:2:9
+   |
+LL | #![warn(unused_imports)]
+   |         ^^^^^^^^^^^^^^
+
+warning: unused import: `m2::*`
+  --> $DIR/use-redundant.rs:18:5
+   |
+LL | use m2::*;
+   |     ^^^^^
+
+warning: the item `Bar` is imported redundantly
+  --> $DIR/use-redundant.rs:21:9
+   |
+LL | use crate::foo::Bar;
+   |     --------------- the item `Bar` is already imported here
+...
+LL |     use crate::foo::Bar;
+   |         ^^^^^^^^^^^^^^^
+
diff --git a/src/test/ui/lint/use_suggestion_json.rs b/src/test/ui/lint/use_suggestion_json.rs
new file mode 100644
index 0000000..3bdbaa5
--- /dev/null
+++ b/src/test/ui/lint/use_suggestion_json.rs
@@ -0,0 +1,12 @@
+// ignore-cloudabi
+// compile-flags: --error-format pretty-json -Zunstable-options
+
+// The output for humans should just highlight the whole span without showing
+// the suggested replacement, but we also want to test that suggested
+// replacement only removes one set of parentheses, rather than naïvely
+// stripping away any starting or ending parenthesis characters—hence this
+// test of the JSON error format.
+
+fn main() {
+    let x: Iter;
+}
diff --git a/src/test/ui/lint/use_suggestion_json.stderr b/src/test/ui/lint/use_suggestion_json.stderr
new file mode 100644
index 0000000..dee7f2f
--- /dev/null
+++ b/src/test/ui/lint/use_suggestion_json.stderr
@@ -0,0 +1,420 @@
+{
+  "message": "cannot find type `Iter` in this scope",
+  "code": {
+    "code": "E0412",
+    "explanation": "
+The type name used is not in scope.
+
+Erroneous code examples:
+
+```compile_fail,E0412
+impl Something {} // error: type name `Something` is not in scope
+
+// or:
+
+trait Foo {
+    fn bar(N); // error: type name `N` is not in scope
+}
+
+// or:
+
+fn foo(x: T) {} // type name `T` is not in scope
+```
+
+To fix this error, please verify you didn't misspell the type name, you did
+declare it or imported it into the scope. Examples:
+
+```
+struct Something;
+
+impl Something {} // ok!
+
+// or:
+
+trait Foo {
+    type N;
+
+    fn bar(_: Self::N); // ok!
+}
+
+// or:
+
+fn foo<T>(x: T) {} // ok!
+```
+
+Another case that causes this error is when a type is imported into a parent
+module. To fix this, you can follow the suggestion and use File directly or
+`use super::File;` which will import the types from the parent namespace. An
+example that causes this error is below:
+
+```compile_fail,E0412
+use std::fs::File;
+
+mod foo {
+    fn some_function(f: File) {}
+}
+```
+
+```
+use std::fs::File;
+
+mod foo {
+    // either
+    use super::File;
+    // or
+    // use std::fs::File;
+    fn foo(f: File) {}
+}
+# fn main() {} // don't insert it for us; that'll break imports
+```
+"
+  },
+  "level": "error",
+  "spans": [
+    {
+      "file_name": "$DIR/use_suggestion_json.rs",
+      "byte_start": 440,
+      "byte_end": 444,
+      "line_start": 11,
+      "line_end": 11,
+      "column_start": 12,
+      "column_end": 16,
+      "is_primary": true,
+      "text": [
+        {
+          "text": "    let x: Iter;",
+          "highlight_start": 12,
+          "highlight_end": 16
+        }
+      ],
+      "label": "not found in this scope",
+      "suggested_replacement": null,
+      "suggestion_applicability": null,
+      "expansion": null
+    }
+  ],
+  "children": [
+    {
+      "message": "possible candidates are found in other modules, you can import them into scope",
+      "code": null,
+      "level": "help",
+      "spans": [
+        {
+          "file_name": "$DIR/use_suggestion_json.rs",
+          "byte_start": 417,
+          "byte_end": 417,
+          "line_start": 10,
+          "line_end": 10,
+          "column_start": 1,
+          "column_end": 1,
+          "is_primary": true,
+          "text": [
+            {
+              "text": "fn main() {",
+              "highlight_start": 1,
+              "highlight_end": 1
+            }
+          ],
+          "label": null,
+          "suggested_replacement": "use std::collections::binary_heap::Iter;
+
+",
+          "suggestion_applicability": "Unspecified",
+          "expansion": null
+        },
+        {
+          "file_name": "$DIR/use_suggestion_json.rs",
+          "byte_start": 417,
+          "byte_end": 417,
+          "line_start": 10,
+          "line_end": 10,
+          "column_start": 1,
+          "column_end": 1,
+          "is_primary": true,
+          "text": [
+            {
+              "text": "fn main() {",
+              "highlight_start": 1,
+              "highlight_end": 1
+            }
+          ],
+          "label": null,
+          "suggested_replacement": "use std::collections::btree_map::Iter;
+
+",
+          "suggestion_applicability": "Unspecified",
+          "expansion": null
+        },
+        {
+          "file_name": "$DIR/use_suggestion_json.rs",
+          "byte_start": 417,
+          "byte_end": 417,
+          "line_start": 10,
+          "line_end": 10,
+          "column_start": 1,
+          "column_end": 1,
+          "is_primary": true,
+          "text": [
+            {
+              "text": "fn main() {",
+              "highlight_start": 1,
+              "highlight_end": 1
+            }
+          ],
+          "label": null,
+          "suggested_replacement": "use std::collections::btree_set::Iter;
+
+",
+          "suggestion_applicability": "Unspecified",
+          "expansion": null
+        },
+        {
+          "file_name": "$DIR/use_suggestion_json.rs",
+          "byte_start": 417,
+          "byte_end": 417,
+          "line_start": 10,
+          "line_end": 10,
+          "column_start": 1,
+          "column_end": 1,
+          "is_primary": true,
+          "text": [
+            {
+              "text": "fn main() {",
+              "highlight_start": 1,
+              "highlight_end": 1
+            }
+          ],
+          "label": null,
+          "suggested_replacement": "use std::collections::hash_map::Iter;
+
+",
+          "suggestion_applicability": "Unspecified",
+          "expansion": null
+        },
+        {
+          "file_name": "$DIR/use_suggestion_json.rs",
+          "byte_start": 417,
+          "byte_end": 417,
+          "line_start": 10,
+          "line_end": 10,
+          "column_start": 1,
+          "column_end": 1,
+          "is_primary": true,
+          "text": [
+            {
+              "text": "fn main() {",
+              "highlight_start": 1,
+              "highlight_end": 1
+            }
+          ],
+          "label": null,
+          "suggested_replacement": "use std::collections::hash_set::Iter;
+
+",
+          "suggestion_applicability": "Unspecified",
+          "expansion": null
+        },
+        {
+          "file_name": "$DIR/use_suggestion_json.rs",
+          "byte_start": 417,
+          "byte_end": 417,
+          "line_start": 10,
+          "line_end": 10,
+          "column_start": 1,
+          "column_end": 1,
+          "is_primary": true,
+          "text": [
+            {
+              "text": "fn main() {",
+              "highlight_start": 1,
+              "highlight_end": 1
+            }
+          ],
+          "label": null,
+          "suggested_replacement": "use std::collections::linked_list::Iter;
+
+",
+          "suggestion_applicability": "Unspecified",
+          "expansion": null
+        },
+        {
+          "file_name": "$DIR/use_suggestion_json.rs",
+          "byte_start": 417,
+          "byte_end": 417,
+          "line_start": 10,
+          "line_end": 10,
+          "column_start": 1,
+          "column_end": 1,
+          "is_primary": true,
+          "text": [
+            {
+              "text": "fn main() {",
+              "highlight_start": 1,
+              "highlight_end": 1
+            }
+          ],
+          "label": null,
+          "suggested_replacement": "use std::collections::vec_deque::Iter;
+
+",
+          "suggestion_applicability": "Unspecified",
+          "expansion": null
+        },
+        {
+          "file_name": "$DIR/use_suggestion_json.rs",
+          "byte_start": 417,
+          "byte_end": 417,
+          "line_start": 10,
+          "line_end": 10,
+          "column_start": 1,
+          "column_end": 1,
+          "is_primary": true,
+          "text": [
+            {
+              "text": "fn main() {",
+              "highlight_start": 1,
+              "highlight_end": 1
+            }
+          ],
+          "label": null,
+          "suggested_replacement": "use std::option::Iter;
+
+",
+          "suggestion_applicability": "Unspecified",
+          "expansion": null
+        },
+        {
+          "file_name": "$DIR/use_suggestion_json.rs",
+          "byte_start": 417,
+          "byte_end": 417,
+          "line_start": 10,
+          "line_end": 10,
+          "column_start": 1,
+          "column_end": 1,
+          "is_primary": true,
+          "text": [
+            {
+              "text": "fn main() {",
+              "highlight_start": 1,
+              "highlight_end": 1
+            }
+          ],
+          "label": null,
+          "suggested_replacement": "use std::path::Iter;
+
+",
+          "suggestion_applicability": "Unspecified",
+          "expansion": null
+        },
+        {
+          "file_name": "$DIR/use_suggestion_json.rs",
+          "byte_start": 417,
+          "byte_end": 417,
+          "line_start": 10,
+          "line_end": 10,
+          "column_start": 1,
+          "column_end": 1,
+          "is_primary": true,
+          "text": [
+            {
+              "text": "fn main() {",
+              "highlight_start": 1,
+              "highlight_end": 1
+            }
+          ],
+          "label": null,
+          "suggested_replacement": "use std::result::Iter;
+
+",
+          "suggestion_applicability": "Unspecified",
+          "expansion": null
+        },
+        {
+          "file_name": "$DIR/use_suggestion_json.rs",
+          "byte_start": 417,
+          "byte_end": 417,
+          "line_start": 10,
+          "line_end": 10,
+          "column_start": 1,
+          "column_end": 1,
+          "is_primary": true,
+          "text": [
+            {
+              "text": "fn main() {",
+              "highlight_start": 1,
+              "highlight_end": 1
+            }
+          ],
+          "label": null,
+          "suggested_replacement": "use std::slice::Iter;
+
+",
+          "suggestion_applicability": "Unspecified",
+          "expansion": null
+        },
+        {
+          "file_name": "$DIR/use_suggestion_json.rs",
+          "byte_start": 417,
+          "byte_end": 417,
+          "line_start": 10,
+          "line_end": 10,
+          "column_start": 1,
+          "column_end": 1,
+          "is_primary": true,
+          "text": [
+            {
+              "text": "fn main() {",
+              "highlight_start": 1,
+              "highlight_end": 1
+            }
+          ],
+          "label": null,
+          "suggested_replacement": "use std::sync::mpsc::Iter;
+
+",
+          "suggestion_applicability": "Unspecified",
+          "expansion": null
+        }
+      ],
+      "children": [],
+      "rendered": null
+    }
+  ],
+  "rendered": "error[E0412]: cannot find type `Iter` in this scope
+  --> $DIR/use_suggestion_json.rs:11:12
+   |
+LL |     let x: Iter;
+   |            ^^^^ not found in this scope
+help: possible candidates are found in other modules, you can import them into scope
+   |
+LL | use std::collections::binary_heap::Iter;
+   |
+LL | use std::collections::btree_map::Iter;
+   |
+LL | use std::collections::btree_set::Iter;
+   |
+LL | use std::collections::hash_map::Iter;
+   |
+and 8 other candidates
+
+"
+}
+{
+  "message": "aborting due to previous error",
+  "code": null,
+  "level": "error",
+  "spans": [],
+  "children": [],
+  "rendered": "error: aborting due to previous error
+
+"
+}
+{
+  "message": "For more information about this error, try `rustc --explain E0412`.",
+  "code": null,
+  "level": "",
+  "spans": [],
+  "children": [],
+  "rendered": "For more information about this error, try `rustc --explain E0412`.
+"
+}
diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.ast.nll.stderr b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.ast.nll.stderr
new file mode 100644
index 0000000..8376ee8
--- /dev/null
+++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.ast.nll.stderr
@@ -0,0 +1,12 @@
+error[E0384]: cannot assign twice to immutable variable `v`
+  --> $DIR/liveness-assign-imm-local-in-loop.rs:9:9
+   |
+LL |     let v: isize;
+   |         - help: make this binding mutable: `mut v`
+...
+LL |         v = 1;
+   |         ^^^^^ cannot assign twice to immutable variable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0384`.
diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.ast.stderr b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.ast.stderr
new file mode 100644
index 0000000..db2a482
--- /dev/null
+++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.ast.stderr
@@ -0,0 +1,9 @@
+error[E0384]: cannot assign twice to immutable variable `v`
+  --> $DIR/liveness-assign-imm-local-in-loop.rs:9:9
+   |
+LL |         v = 1;
+   |         ^^^^^ cannot assign twice to immutable variable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0384`.
diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.mir.stderr b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.mir.stderr
new file mode 100644
index 0000000..8376ee8
--- /dev/null
+++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.mir.stderr
@@ -0,0 +1,12 @@
+error[E0384]: cannot assign twice to immutable variable `v`
+  --> $DIR/liveness-assign-imm-local-in-loop.rs:9:9
+   |
+LL |     let v: isize;
+   |         - help: make this binding mutable: `mut v`
+...
+LL |         v = 1;
+   |         ^^^^^ cannot assign twice to immutable variable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0384`.
diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.rs b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.rs
new file mode 100644
index 0000000..59447ba
--- /dev/null
+++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.rs
@@ -0,0 +1,18 @@
+// revisions: ast mir
+//[mir]compile-flags: -Zborrowck=mir
+
+fn test() {
+    let v: isize;
+    //[mir]~^ HELP make this binding mutable
+    //[mir]~| SUGGESTION mut v
+    loop {
+        v = 1; //[ast]~ ERROR cannot assign twice to immutable variable
+               //[mir]~^ ERROR cannot assign twice to immutable variable `v`
+               //[ast]~| NOTE cannot assign twice to immutable variable
+               //[mir]~| NOTE cannot assign twice to immutable variable
+        v.clone(); // just to prevent liveness warnings
+    }
+}
+
+fn main() {
+}
diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.ast.nll.stderr b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.ast.nll.stderr
new file mode 100644
index 0000000..a6a1c73a
--- /dev/null
+++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.ast.nll.stderr
@@ -0,0 +1,15 @@
+error[E0384]: cannot assign twice to immutable variable `v`
+  --> $DIR/liveness-assign-imm-local-in-op-eq.rs:10:5
+   |
+LL |     let v: isize;
+   |         - help: make this binding mutable: `mut v`
+...
+LL |     v = 2;
+   |     ----- first assignment to `v`
+LL |
+LL |     v += 1;
+   |     ^^^^^^ cannot assign twice to immutable variable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0384`.
diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.ast.stderr b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.ast.stderr
new file mode 100644
index 0000000..b287edf
--- /dev/null
+++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.ast.stderr
@@ -0,0 +1,12 @@
+error[E0384]: cannot assign twice to immutable variable `v`
+  --> $DIR/liveness-assign-imm-local-in-op-eq.rs:10:5
+   |
+LL |     v = 2;
+   |     ----- first assignment to `v`
+LL |
+LL |     v += 1;
+   |     ^^^^^^ cannot assign twice to immutable variable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0384`.
diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.mir.stderr b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.mir.stderr
new file mode 100644
index 0000000..a6a1c73a
--- /dev/null
+++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.mir.stderr
@@ -0,0 +1,15 @@
+error[E0384]: cannot assign twice to immutable variable `v`
+  --> $DIR/liveness-assign-imm-local-in-op-eq.rs:10:5
+   |
+LL |     let v: isize;
+   |         - help: make this binding mutable: `mut v`
+...
+LL |     v = 2;
+   |     ----- first assignment to `v`
+LL |
+LL |     v += 1;
+   |     ^^^^^^ cannot assign twice to immutable variable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0384`.
diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.rs b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.rs
new file mode 100644
index 0000000..a2677f4
--- /dev/null
+++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.rs
@@ -0,0 +1,18 @@
+// revisions: ast mir
+//[mir]compile-flags: -Zborrowck=mir
+
+fn test() {
+    let v: isize;
+    //[mir]~^ HELP make this binding mutable
+    //[mir]~| SUGGESTION mut v
+    v = 2;  //[ast]~ NOTE first assignment
+            //[mir]~^ NOTE first assignment
+    v += 1; //[ast]~ ERROR cannot assign twice to immutable variable
+            //[mir]~^ ERROR cannot assign twice to immutable variable `v`
+            //[ast]~| NOTE cannot assign twice to immutable
+            //[mir]~| NOTE cannot assign twice to immutable
+    v.clone();
+}
+
+fn main() {
+}
diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.ast.nll.stderr b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.ast.nll.stderr
new file mode 100644
index 0000000..8316ffd
--- /dev/null
+++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.ast.nll.stderr
@@ -0,0 +1,15 @@
+error[E0384]: cannot assign twice to immutable variable `b`
+  --> $DIR/liveness-assign-imm-local-with-drop.rs:10:5
+   |
+LL |     let b = Box::new(1);
+   |         -
+   |         |
+   |         first assignment to `b`
+   |         help: make this binding mutable: `mut b`
+...
+LL |     b = Box::new(2);
+   |     ^ cannot assign twice to immutable variable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0384`.
diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.ast.stderr b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.ast.stderr
new file mode 100644
index 0000000..108ca48
--- /dev/null
+++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.ast.stderr
@@ -0,0 +1,12 @@
+error[E0384]: cannot assign twice to immutable variable `b`
+  --> $DIR/liveness-assign-imm-local-with-drop.rs:10:5
+   |
+LL |     let b = Box::new(1);
+   |         - first assignment to `b`
+...
+LL |     b = Box::new(2);
+   |     ^^^^^^^^^^^^^^^ cannot assign twice to immutable variable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0384`.
diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.mir.stderr b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.mir.stderr
new file mode 100644
index 0000000..8316ffd
--- /dev/null
+++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.mir.stderr
@@ -0,0 +1,15 @@
+error[E0384]: cannot assign twice to immutable variable `b`
+  --> $DIR/liveness-assign-imm-local-with-drop.rs:10:5
+   |
+LL |     let b = Box::new(1);
+   |         -
+   |         |
+   |         first assignment to `b`
+   |         help: make this binding mutable: `mut b`
+...
+LL |     b = Box::new(2);
+   |     ^ cannot assign twice to immutable variable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0384`.
diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.rs b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.rs
new file mode 100644
index 0000000..4a81dcd
--- /dev/null
+++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.rs
@@ -0,0 +1,18 @@
+// revisions: ast mir
+//[mir]compile-flags: -Zborrowck=mir
+
+fn test() {
+    let b = Box::new(1); //[ast]~ NOTE first assignment
+                         //[mir]~^ NOTE first assignment
+                         //[mir]~| HELP make this binding mutable
+                         //[mir]~| SUGGESTION 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`
+                     //[ast]~| NOTE cannot assign twice to immutable
+                     //[mir]~| NOTE cannot assign twice to immutable
+    drop(b);
+}
+
+fn main() {
+}
diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.ast.nll.stderr b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.ast.nll.stderr
new file mode 100644
index 0000000..5fa06f9
--- /dev/null
+++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.ast.nll.stderr
@@ -0,0 +1,15 @@
+error[E0384]: cannot assign twice to immutable variable `v`
+  --> $DIR/liveness-assign-imm-local-with-init.rs:10:5
+   |
+LL |     let v: isize = 1;
+   |         -
+   |         |
+   |         first assignment to `v`
+   |         help: make this binding mutable: `mut v`
+...
+LL |     v = 2;
+   |     ^^^^^ cannot assign twice to immutable variable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0384`.
diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.ast.stderr b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.ast.stderr
new file mode 100644
index 0000000..34fb160
--- /dev/null
+++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.ast.stderr
@@ -0,0 +1,12 @@
+error[E0384]: cannot assign twice to immutable variable `v`
+  --> $DIR/liveness-assign-imm-local-with-init.rs:10:5
+   |
+LL |     let v: isize = 1;
+   |         - first assignment to `v`
+...
+LL |     v = 2;
+   |     ^^^^^ cannot assign twice to immutable variable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0384`.
diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.mir.stderr b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.mir.stderr
new file mode 100644
index 0000000..5fa06f9
--- /dev/null
+++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.mir.stderr
@@ -0,0 +1,15 @@
+error[E0384]: cannot assign twice to immutable variable `v`
+  --> $DIR/liveness-assign-imm-local-with-init.rs:10:5
+   |
+LL |     let v: isize = 1;
+   |         -
+   |         |
+   |         first assignment to `v`
+   |         help: make this binding mutable: `mut v`
+...
+LL |     v = 2;
+   |     ^^^^^ cannot assign twice to immutable variable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0384`.
diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.rs b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.rs
new file mode 100644
index 0000000..2c59aaf
--- /dev/null
+++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.rs
@@ -0,0 +1,18 @@
+// revisions: ast mir
+//[mir]compile-flags: -Zborrowck=mir
+
+fn test() {
+    let v: isize = 1; //[ast]~ NOTE first assignment
+                      //[mir]~^ NOTE first assignment
+                      //[mir]~| HELP make this binding mutable
+                      //[mir]~| SUGGESTION mut v
+    v.clone();
+    v = 2; //[ast]~ ERROR cannot assign twice to immutable variable
+           //[mir]~^ ERROR cannot assign twice to immutable variable `v`
+           //[ast]~| NOTE cannot assign twice to immutable
+           //[mir]~| NOTE cannot assign twice to immutable
+    v.clone();
+}
+
+fn main() {
+}
diff --git a/src/test/ui/liveness/liveness-closure-require-ret.rs b/src/test/ui/liveness/liveness-closure-require-ret.rs
new file mode 100644
index 0000000..b86d1fe
--- /dev/null
+++ b/src/test/ui/liveness/liveness-closure-require-ret.rs
@@ -0,0 +1,2 @@
+fn force<F>(f: F) -> isize where F: FnOnce() -> isize { f() }
+fn main() { println!("{}", force(|| {})); } //~ ERROR mismatched types
diff --git a/src/test/ui/liveness/liveness-closure-require-ret.stderr b/src/test/ui/liveness/liveness-closure-require-ret.stderr
new file mode 100644
index 0000000..e8f185a
--- /dev/null
+++ b/src/test/ui/liveness/liveness-closure-require-ret.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/liveness-closure-require-ret.rs:2:37
+   |
+LL | fn main() { println!("{}", force(|| {})); }
+   |                                     ^^ expected isize, found ()
+   |
+   = note: expected type `isize`
+              found type `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/liveness/liveness-dead.rs b/src/test/ui/liveness/liveness-dead.rs
new file mode 100644
index 0000000..004663c
--- /dev/null
+++ b/src/test/ui/liveness/liveness-dead.rs
@@ -0,0 +1,39 @@
+#![allow(dead_code)]
+#![deny(unused_assignments)]
+
+fn f1(x: &mut isize) {
+    *x = 1; // no error
+}
+
+fn f2() {
+    let mut x: isize = 3; //~ ERROR: value assigned to `x` is never read
+    x = 4;
+    x.clone();
+}
+
+fn f3() {
+    let mut x: isize = 3;
+    x.clone();
+    x = 4; //~ ERROR: value assigned to `x` is never read
+}
+
+fn f4(mut x: i32) { //~ ERROR: value passed to `x` is never read
+    x = 4;
+    x.clone();
+}
+
+fn f5(mut x: i32) {
+    x.clone();
+    x = 4; //~ ERROR: value assigned to `x` is never read
+}
+
+// #22630
+fn f6() {
+    let mut done = false;
+    while !done {
+        done = true; // no error
+        continue;
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/liveness/liveness-dead.stderr b/src/test/ui/liveness/liveness-dead.stderr
new file mode 100644
index 0000000..d054b1d
--- /dev/null
+++ b/src/test/ui/liveness/liveness-dead.stderr
@@ -0,0 +1,39 @@
+error: value assigned to `x` is never read
+  --> $DIR/liveness-dead.rs:9:13
+   |
+LL |     let mut x: isize = 3;
+   |             ^
+   |
+note: lint level defined here
+  --> $DIR/liveness-dead.rs:2:9
+   |
+LL | #![deny(unused_assignments)]
+   |         ^^^^^^^^^^^^^^^^^^
+   = help: maybe it is overwritten before being read?
+
+error: value assigned to `x` is never read
+  --> $DIR/liveness-dead.rs:17:5
+   |
+LL |     x = 4;
+   |     ^
+   |
+   = help: maybe it is overwritten before being read?
+
+error: value passed to `x` is never read
+  --> $DIR/liveness-dead.rs:20:11
+   |
+LL | fn f4(mut x: i32) {
+   |           ^
+   |
+   = help: maybe it is overwritten before being read?
+
+error: value assigned to `x` is never read
+  --> $DIR/liveness-dead.rs:27:5
+   |
+LL |     x = 4;
+   |     ^
+   |
+   = help: maybe it is overwritten before being read?
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/liveness/liveness-forgot-ret.rs b/src/test/ui/liveness/liveness-forgot-ret.rs
new file mode 100644
index 0000000..b8c2bc7
--- /dev/null
+++ b/src/test/ui/liveness/liveness-forgot-ret.rs
@@ -0,0 +1,6 @@
+fn god_exists(a: isize) -> bool { return god_exists(a); }
+
+fn f(a: isize) -> isize { if god_exists(a) { return 5; }; }
+//~^ ERROR mismatched types
+
+fn main() { f(12); }
diff --git a/src/test/ui/liveness/liveness-forgot-ret.stderr b/src/test/ui/liveness/liveness-forgot-ret.stderr
new file mode 100644
index 0000000..a970b80
--- /dev/null
+++ b/src/test/ui/liveness/liveness-forgot-ret.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/liveness-forgot-ret.rs:3:19
+   |
+LL | fn f(a: isize) -> isize { if god_exists(a) { return 5; }; }
+   |    -              ^^^^^ expected isize, found ()
+   |    |
+   |    this function's body doesn't return
+   |
+   = note: expected type `isize`
+              found type `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/liveness/liveness-issue-2163.rs b/src/test/ui/liveness/liveness-issue-2163.rs
new file mode 100644
index 0000000..a632b5b
--- /dev/null
+++ b/src/test/ui/liveness/liveness-issue-2163.rs
@@ -0,0 +1,8 @@
+use std::vec::Vec;
+
+fn main() {
+    let a: Vec<isize> = Vec::new();
+    a.iter().all(|_| -> bool {
+        //~^ ERROR mismatched types
+    });
+}
diff --git a/src/test/ui/liveness/liveness-issue-2163.stderr b/src/test/ui/liveness/liveness-issue-2163.stderr
new file mode 100644
index 0000000..780a254
--- /dev/null
+++ b/src/test/ui/liveness/liveness-issue-2163.stderr
@@ -0,0 +1,15 @@
+error[E0308]: mismatched types
+  --> $DIR/liveness-issue-2163.rs:5:30
+   |
+LL |       a.iter().all(|_| -> bool {
+   |  ______________________________^
+LL | |
+LL | |     });
+   | |_____^ expected bool, found ()
+   |
+   = note: expected type `bool`
+              found type `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/liveness/liveness-missing-ret2.rs b/src/test/ui/liveness/liveness-missing-ret2.rs
new file mode 100644
index 0000000..a18669f
--- /dev/null
+++ b/src/test/ui/liveness/liveness-missing-ret2.rs
@@ -0,0 +1,7 @@
+fn f() -> isize { //~ ERROR mismatched types
+    // Make sure typestate doesn't interpret this match expression as
+    // the function result
+   match true { true => { } _ => {} };
+}
+
+fn main() { }
diff --git a/src/test/ui/liveness/liveness-missing-ret2.stderr b/src/test/ui/liveness/liveness-missing-ret2.stderr
new file mode 100644
index 0000000..ab7d411
--- /dev/null
+++ b/src/test/ui/liveness/liveness-missing-ret2.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/liveness-missing-ret2.rs:1:11
+   |
+LL | fn f() -> isize {
+   |    -      ^^^^^ expected isize, found ()
+   |    |
+   |    this function's body doesn't return
+   |
+   = note: expected type `isize`
+              found type `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/liveness/liveness-move-call-arg.nll.stderr b/src/test/ui/liveness/liveness-move-call-arg.nll.stderr
new file mode 100644
index 0000000..ab4460a
--- /dev/null
+++ b/src/test/ui/liveness/liveness-move-call-arg.nll.stderr
@@ -0,0 +1,12 @@
+error[E0382]: use of moved value: `x`
+  --> $DIR/liveness-move-call-arg.rs:9:14
+   |
+LL |     let x: Box<isize> = box 25;
+   |         - move occurs because `x` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+LL |     loop {
+LL |         take(x);
+   |              ^ value moved here, in previous iteration of loop
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/liveness/liveness-move-call-arg.rs b/src/test/ui/liveness/liveness-move-call-arg.rs
new file mode 100644
index 0000000..98d12f5
--- /dev/null
+++ b/src/test/ui/liveness/liveness-move-call-arg.rs
@@ -0,0 +1,11 @@
+#![feature(box_syntax)]
+
+fn take(_x: Box<isize>) {}
+
+fn main() {
+
+    let x: Box<isize> = box 25;
+    loop {
+        take(x); //~ ERROR use of moved value: `x`
+    }
+}
diff --git a/src/test/ui/liveness/liveness-move-call-arg.stderr b/src/test/ui/liveness/liveness-move-call-arg.stderr
new file mode 100644
index 0000000..c50c01e
--- /dev/null
+++ b/src/test/ui/liveness/liveness-move-call-arg.stderr
@@ -0,0 +1,11 @@
+error[E0382]: use of moved value: `x`
+  --> $DIR/liveness-move-call-arg.rs:9:14
+   |
+LL |         take(x);
+   |              ^ value moved here in previous iteration of loop
+   |
+   = note: move occurs because `x` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/liveness/liveness-move-in-loop.nll.stderr b/src/test/ui/liveness/liveness-move-in-loop.nll.stderr
new file mode 100644
index 0000000..150c1ec
--- /dev/null
+++ b/src/test/ui/liveness/liveness-move-in-loop.nll.stderr
@@ -0,0 +1,12 @@
+error[E0382]: use of moved value: `y`
+  --> $DIR/liveness-move-in-loop.rs:11:25
+   |
+LL |     let y: Box<isize> = box 42;
+   |         - move occurs because `y` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+...
+LL |                     x = y;
+   |                         ^ value moved here, in previous iteration of loop
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/liveness/liveness-move-in-loop.rs b/src/test/ui/liveness/liveness-move-in-loop.rs
new file mode 100644
index 0000000..eb3288a
--- /dev/null
+++ b/src/test/ui/liveness/liveness-move-in-loop.rs
@@ -0,0 +1,17 @@
+#![feature(box_syntax)]
+
+fn main() {
+    let y: Box<isize> = box 42;
+    let mut x: Box<isize>;
+    loop {
+        println!("{}", y);
+        loop {
+            loop {
+                loop {
+                    x = y; //~ ERROR use of moved value
+                    x.clone();
+                }
+            }
+        }
+    }
+}
diff --git a/src/test/ui/liveness/liveness-move-in-loop.stderr b/src/test/ui/liveness/liveness-move-in-loop.stderr
new file mode 100644
index 0000000..52e83a6
--- /dev/null
+++ b/src/test/ui/liveness/liveness-move-in-loop.stderr
@@ -0,0 +1,11 @@
+error[E0382]: use of moved value: `y`
+  --> $DIR/liveness-move-in-loop.rs:11:25
+   |
+LL |                     x = y;
+   |                         ^ value moved here in previous iteration of loop
+   |
+   = note: move occurs because `y` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/liveness/liveness-move-in-while.nll.stderr b/src/test/ui/liveness/liveness-move-in-while.nll.stderr
new file mode 100644
index 0000000..e1eed1b
--- /dev/null
+++ b/src/test/ui/liveness/liveness-move-in-while.nll.stderr
@@ -0,0 +1,14 @@
+error[E0382]: borrow of moved value: `y`
+  --> $DIR/liveness-move-in-while.rs:7:24
+   |
+LL |     let y: Box<isize> = box 42;
+   |         - move occurs because `y` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+...
+LL |         println!("{}", y);
+   |                        ^ value borrowed here after move
+LL |         while true { while true { while true { x = y; x.clone(); } } }
+   |                                                    - value moved here, in previous iteration of loop
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/liveness/liveness-move-in-while.rs b/src/test/ui/liveness/liveness-move-in-while.rs
new file mode 100644
index 0000000..a43e759
--- /dev/null
+++ b/src/test/ui/liveness/liveness-move-in-while.rs
@@ -0,0 +1,11 @@
+#![feature(box_syntax)]
+
+fn main() {
+    let y: Box<isize> = box 42;
+    let mut x: Box<isize>;
+    loop {
+        println!("{}", y); //~ ERROR use of moved value: `y`
+        while true { while true { while true { x = y; x.clone(); } } }
+        //~^ ERROR use of moved value: `y`
+    }
+}
diff --git a/src/test/ui/liveness/liveness-move-in-while.stderr b/src/test/ui/liveness/liveness-move-in-while.stderr
new file mode 100644
index 0000000..61b4cd8
--- /dev/null
+++ b/src/test/ui/liveness/liveness-move-in-while.stderr
@@ -0,0 +1,21 @@
+error[E0382]: use of moved value: `y`
+  --> $DIR/liveness-move-in-while.rs:7:24
+   |
+LL |         println!("{}", y);
+   |                        ^ value used here after move
+LL |         while true { while true { while true { x = y; x.clone(); } } }
+   |                                                    - value moved here
+   |
+   = note: move occurs because `y` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `y`
+  --> $DIR/liveness-move-in-while.rs:8:52
+   |
+LL |         while true { while true { while true { x = y; x.clone(); } } }
+   |                                                    ^ value moved here in previous iteration of loop
+   |
+   = note: move occurs because `y` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/liveness/liveness-return-last-stmt-semi.rs b/src/test/ui/liveness/liveness-return-last-stmt-semi.rs
new file mode 100644
index 0000000..e8909c4
--- /dev/null
+++ b/src/test/ui/liveness/liveness-return-last-stmt-semi.rs
@@ -0,0 +1,19 @@
+//
+// regression test for #8005
+
+macro_rules! test { () => { fn foo() -> i32 { 1; } } }
+                                           //~^ ERROR mismatched types
+
+fn no_return() -> i32 {} //~ ERROR mismatched types
+
+fn bar(x: u32) -> u32 { //~ ERROR mismatched types
+    x * 2;
+}
+
+fn baz(x: u64) -> u32 { //~ ERROR mismatched types
+    x * 2;
+}
+
+fn main() {
+    test!();
+}
diff --git a/src/test/ui/liveness/liveness-return-last-stmt-semi.stderr b/src/test/ui/liveness/liveness-return-last-stmt-semi.stderr
new file mode 100644
index 0000000..a5d9734
--- /dev/null
+++ b/src/test/ui/liveness/liveness-return-last-stmt-semi.stderr
@@ -0,0 +1,53 @@
+error[E0308]: mismatched types
+  --> $DIR/liveness-return-last-stmt-semi.rs:4:41
+   |
+LL | macro_rules! test { () => { fn foo() -> i32 { 1; } } }
+   |                                ---      ^^^    - help: consider removing this semicolon
+   |                                |        |
+   |                                |        expected i32, found ()
+   |                                this function's body doesn't return
+...
+LL |     test!();
+   |     -------- in this macro invocation
+   |
+   = note: expected type `i32`
+              found type `()`
+
+error[E0308]: mismatched types
+  --> $DIR/liveness-return-last-stmt-semi.rs:7:19
+   |
+LL | fn no_return() -> i32 {}
+   |    ---------      ^^^ expected i32, found ()
+   |    |
+   |    this function's body doesn't return
+   |
+   = note: expected type `i32`
+              found type `()`
+
+error[E0308]: mismatched types
+  --> $DIR/liveness-return-last-stmt-semi.rs:9:19
+   |
+LL | fn bar(x: u32) -> u32 {
+   |    ---            ^^^ expected u32, found ()
+   |    |
+   |    this function's body doesn't return
+LL |     x * 2;
+   |          - help: consider removing this semicolon
+   |
+   = note: expected type `u32`
+              found type `()`
+
+error[E0308]: mismatched types
+  --> $DIR/liveness-return-last-stmt-semi.rs:13:19
+   |
+LL | fn baz(x: u64) -> u32 {
+   |    ---            ^^^ expected u32, found ()
+   |    |
+   |    this function's body doesn't return
+   |
+   = note: expected type `u32`
+              found type `()`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/liveness/liveness-unused.rs b/src/test/ui/liveness/liveness-unused.rs
new file mode 100644
index 0000000..9c7be15
--- /dev/null
+++ b/src/test/ui/liveness/liveness-unused.rs
@@ -0,0 +1,141 @@
+#![warn(unused)]
+#![deny(unused_variables)]
+#![deny(unused_assignments)]
+#![allow(dead_code, non_camel_case_types, trivial_numeric_casts)]
+
+use std::ops::AddAssign;
+
+fn f1(x: isize) {
+    //~^ ERROR unused variable: `x`
+}
+
+fn f1b(x: &mut isize) {
+    //~^ ERROR unused variable: `x`
+}
+
+#[allow(unused_variables)]
+fn f1c(x: isize) {}
+
+fn f1d() {
+    let x: isize;
+    //~^ ERROR unused variable: `x`
+}
+
+fn f2() {
+    let x = 3;
+    //~^ ERROR unused variable: `x`
+}
+
+fn f3() {
+    let mut x = 3;
+    //~^ ERROR variable `x` is assigned to, but never used
+    x += 4;
+    //~^ ERROR value assigned to `x` is never read
+}
+
+fn f3b() {
+    let mut z = 3;
+    //~^ ERROR variable `z` is assigned to, but never used
+    loop {
+        z += 4;
+    }
+}
+
+#[allow(unused_variables)]
+fn f3c() {
+    let mut z = 3;
+    loop { z += 4; }
+}
+
+#[allow(unused_variables)]
+#[allow(unused_assignments)]
+fn f3d() {
+    let mut x = 3;
+    x += 4;
+}
+
+fn f4() {
+    match Some(3) {
+      Some(i) => {
+        //~^ ERROR unused variable: `i`
+      }
+      None => {}
+    }
+}
+
+enum tri {
+    a(isize), b(isize), c(isize)
+}
+
+fn f4b() -> isize {
+    match tri::a(3) {
+      tri::a(i) | tri::b(i) | tri::c(i) => {
+        i
+      }
+    }
+}
+
+fn f5a() {
+    for x in 1..10 { }
+    //~^ ERROR unused variable: `x`
+}
+
+fn f5b() {
+    for (x, _) in [1, 2, 3].iter().enumerate() { }
+    //~^ ERROR unused variable: `x`
+}
+
+fn f5c() {
+    for (_, x) in [1, 2, 3].iter().enumerate() {
+    //~^ ERROR unused variable: `x`
+        continue;
+        drop(*x as i32); //~ WARNING unreachable statement
+    }
+}
+
+struct View<'a>(&'a mut [i32]);
+
+impl<'a> AddAssign<i32> for View<'a> {
+    fn add_assign(&mut self, rhs: i32) {
+        for lhs in self.0.iter_mut() {
+            *lhs += rhs;
+        }
+    }
+}
+
+fn f6() {
+    let mut array = [1, 2, 3];
+    let mut v = View(&mut array);
+
+    // ensure an error shows up for x even if lhs of an overloaded add assign
+
+    let x;
+    //~^ ERROR variable `x` is assigned to, but never used
+
+    *({
+        x = 0;  //~ ERROR value assigned to `x` is never read
+        &mut v
+    }) += 1;
+}
+
+
+struct MutRef<'a>(&'a mut i32);
+
+impl<'a> AddAssign<i32> for MutRef<'a> {
+    fn add_assign(&mut self, rhs: i32) {
+        *self.0 += rhs;
+    }
+}
+
+fn f7() {
+    let mut a = 1;
+    {
+        // `b` does not trigger unused_variables
+        let mut b = MutRef(&mut a);
+        b += 1;
+    }
+    drop(a);
+}
+
+fn main() {
+}
diff --git a/src/test/ui/liveness/liveness-unused.stderr b/src/test/ui/liveness/liveness-unused.stderr
new file mode 100644
index 0000000..d607711
--- /dev/null
+++ b/src/test/ui/liveness/liveness-unused.stderr
@@ -0,0 +1,114 @@
+warning: unreachable statement
+  --> $DIR/liveness-unused.rs:92:9
+   |
+LL |         drop(*x as i32);
+   |         ^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/liveness-unused.rs:1:9
+   |
+LL | #![warn(unused)]
+   |         ^^^^^^
+   = note: #[warn(unreachable_code)] implied by #[warn(unused)]
+
+error: unused variable: `x`
+  --> $DIR/liveness-unused.rs:8:7
+   |
+LL | fn f1(x: isize) {
+   |       ^ help: consider prefixing with an underscore: `_x`
+   |
+note: lint level defined here
+  --> $DIR/liveness-unused.rs:2:9
+   |
+LL | #![deny(unused_variables)]
+   |         ^^^^^^^^^^^^^^^^
+
+error: unused variable: `x`
+  --> $DIR/liveness-unused.rs:12:8
+   |
+LL | fn f1b(x: &mut isize) {
+   |        ^ help: consider prefixing with an underscore: `_x`
+
+error: unused variable: `x`
+  --> $DIR/liveness-unused.rs:20:9
+   |
+LL |     let x: isize;
+   |         ^ help: consider prefixing with an underscore: `_x`
+
+error: unused variable: `x`
+  --> $DIR/liveness-unused.rs:25:9
+   |
+LL |     let x = 3;
+   |         ^ help: consider prefixing with an underscore: `_x`
+
+error: variable `x` is assigned to, but never used
+  --> $DIR/liveness-unused.rs:30:13
+   |
+LL |     let mut x = 3;
+   |             ^
+   |
+   = note: consider using `_x` instead
+
+error: value assigned to `x` is never read
+  --> $DIR/liveness-unused.rs:32:5
+   |
+LL |     x += 4;
+   |     ^
+   |
+note: lint level defined here
+  --> $DIR/liveness-unused.rs:3:9
+   |
+LL | #![deny(unused_assignments)]
+   |         ^^^^^^^^^^^^^^^^^^
+   = help: maybe it is overwritten before being read?
+
+error: variable `z` is assigned to, but never used
+  --> $DIR/liveness-unused.rs:37:13
+   |
+LL |     let mut z = 3;
+   |             ^
+   |
+   = note: consider using `_z` instead
+
+error: unused variable: `i`
+  --> $DIR/liveness-unused.rs:59:12
+   |
+LL |       Some(i) => {
+   |            ^ help: consider prefixing with an underscore: `_i`
+
+error: unused variable: `x`
+  --> $DIR/liveness-unused.rs:79:9
+   |
+LL |     for x in 1..10 { }
+   |         ^ help: consider prefixing with an underscore: `_x`
+
+error: unused variable: `x`
+  --> $DIR/liveness-unused.rs:84:10
+   |
+LL |     for (x, _) in [1, 2, 3].iter().enumerate() { }
+   |          ^ help: consider prefixing with an underscore: `_x`
+
+error: unused variable: `x`
+  --> $DIR/liveness-unused.rs:89:13
+   |
+LL |     for (_, x) in [1, 2, 3].iter().enumerate() {
+   |             ^ help: consider prefixing with an underscore: `_x`
+
+error: variable `x` is assigned to, but never used
+  --> $DIR/liveness-unused.rs:112:9
+   |
+LL |     let x;
+   |         ^
+   |
+   = note: consider using `_x` instead
+
+error: value assigned to `x` is never read
+  --> $DIR/liveness-unused.rs:116:9
+   |
+LL |         x = 0;
+   |         ^
+   |
+   = help: maybe it is overwritten before being read?
+
+error: aborting due to 13 previous errors
+
diff --git a/src/test/ui/liveness/liveness-use-after-move.nll.stderr b/src/test/ui/liveness/liveness-use-after-move.nll.stderr
new file mode 100644
index 0000000..383b89a
--- /dev/null
+++ b/src/test/ui/liveness/liveness-use-after-move.nll.stderr
@@ -0,0 +1,13 @@
+error[E0382]: borrow of moved value: `x`
+  --> $DIR/liveness-use-after-move.rs:6:20
+   |
+LL |     let x: Box<_> = box 5;
+   |         - move occurs because `x` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
+LL |     let y = x;
+   |             - value moved here
+LL |     println!("{}", *x);
+   |                    ^^ value borrowed here after move
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/liveness/liveness-use-after-move.rs b/src/test/ui/liveness/liveness-use-after-move.rs
new file mode 100644
index 0000000..157587c
--- /dev/null
+++ b/src/test/ui/liveness/liveness-use-after-move.rs
@@ -0,0 +1,8 @@
+#![feature(box_syntax)]
+
+fn main() {
+    let x: Box<_> = box 5;
+    let y = x;
+    println!("{}", *x); //~ ERROR use of moved value: `*x`
+    y.clone();
+}
diff --git a/src/test/ui/liveness/liveness-use-after-move.stderr b/src/test/ui/liveness/liveness-use-after-move.stderr
new file mode 100644
index 0000000..ce192ae
--- /dev/null
+++ b/src/test/ui/liveness/liveness-use-after-move.stderr
@@ -0,0 +1,13 @@
+error[E0382]: use of moved value: `*x`
+  --> $DIR/liveness-use-after-move.rs:6:20
+   |
+LL |     let y = x;
+   |         - value moved here
+LL |     println!("{}", *x);
+   |                    ^^ value used here after move
+   |
+   = note: move occurs because `x` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/liveness/liveness-use-after-send.nll.stderr b/src/test/ui/liveness/liveness-use-after-send.nll.stderr
new file mode 100644
index 0000000..ccf9499
--- /dev/null
+++ b/src/test/ui/liveness/liveness-use-after-send.nll.stderr
@@ -0,0 +1,13 @@
+error[E0382]: borrow of moved value: `message`
+  --> $DIR/liveness-use-after-send.rs:16:20
+   |
+LL | fn test00_start(ch: Chan<Box<isize>>, message: Box<isize>, _count: Box<isize>) {
+   |                                       ------- move occurs because `message` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+LL |     send(ch, message);
+   |              ------- value moved here
+LL |     println!("{}", message);
+   |                    ^^^^^^^ value borrowed here after move
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/liveness/liveness-use-after-send.rs b/src/test/ui/liveness/liveness-use-after-send.rs
new file mode 100644
index 0000000..7f2cc3c
--- /dev/null
+++ b/src/test/ui/liveness/liveness-use-after-send.rs
@@ -0,0 +1,19 @@
+use std::marker;
+
+fn send<T:Send + std::fmt::Debug>(ch: Chan<T>, data: T) {
+    println!("{:?}", ch);
+    println!("{:?}", data);
+    panic!();
+}
+
+#[derive(Debug)]
+struct Chan<T>(isize, marker::PhantomData<T>);
+
+// Tests that "log(debug, message);" is flagged as using
+// message after the send deinitializes it
+fn test00_start(ch: Chan<Box<isize>>, message: Box<isize>, _count: Box<isize>) {
+    send(ch, message);
+    println!("{}", message); //~ ERROR use of moved value: `message`
+}
+
+fn main() { panic!(); }
diff --git a/src/test/ui/liveness/liveness-use-after-send.stderr b/src/test/ui/liveness/liveness-use-after-send.stderr
new file mode 100644
index 0000000..2817328
--- /dev/null
+++ b/src/test/ui/liveness/liveness-use-after-send.stderr
@@ -0,0 +1,13 @@
+error[E0382]: use of moved value: `message`
+  --> $DIR/liveness-use-after-send.rs:16:20
+   |
+LL |     send(ch, message);
+   |              ------- value moved here
+LL |     println!("{}", message);
+   |                    ^^^^^^^ value used here after move
+   |
+   = note: move occurs because `message` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/loops/loop-break-value-no-repeat.rs b/src/test/ui/loops/loop-break-value-no-repeat.rs
new file mode 100644
index 0000000..1c0b7a0
--- /dev/null
+++ b/src/test/ui/loops/loop-break-value-no-repeat.rs
@@ -0,0 +1,14 @@
+#![allow(unused_variables)]
+
+use std::ptr;
+
+// Test that we only report **one** error here and that is that
+// `break` with an expression is illegal in this context. In
+// particular, we don't report any mismatched types error, which is
+// besides the point.
+
+fn main() {
+    for _ in &[1,2,3] {
+        break 22 //~ ERROR `break` with value from a `for` loop
+    }
+}
diff --git a/src/test/ui/loops/loop-break-value-no-repeat.stderr b/src/test/ui/loops/loop-break-value-no-repeat.stderr
new file mode 100644
index 0000000..066dce5
--- /dev/null
+++ b/src/test/ui/loops/loop-break-value-no-repeat.stderr
@@ -0,0 +1,13 @@
+error[E0571]: `break` with value from a `for` loop
+  --> $DIR/loop-break-value-no-repeat.rs:12:9
+   |
+LL |         break 22
+   |         ^^^^^^^^ can only break with a value inside `loop` or breakable block
+help: instead, use `break` on its own without a value inside this `for` loop
+   |
+LL |         break
+   |         ^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0571`.
diff --git a/src/test/ui/loops/loop-break-value.rs b/src/test/ui/loops/loop-break-value.rs
new file mode 100644
index 0000000..b80c847
--- /dev/null
+++ b/src/test/ui/loops/loop-break-value.rs
@@ -0,0 +1,93 @@
+#![feature(never_type)]
+
+fn main() {
+    let val: ! = loop { break break; };
+    //~^ ERROR mismatched types
+
+    loop {
+        if true {
+            break "asdf";
+        } else {
+            break 123; //~ ERROR mismatched types
+        }
+    };
+
+    let _: i32 = loop {
+        break "asdf"; //~ ERROR mismatched types
+    };
+
+    let _: i32 = 'outer_loop: loop {
+        loop {
+            break 'outer_loop "nope"; //~ ERROR mismatched types
+            break "ok";
+        };
+    };
+
+    'while_loop: while true {
+        break;
+        break (); //~ ERROR `break` with value from a `while` loop
+        loop {
+            break 'while_loop 123;
+            //~^ ERROR `break` with value from a `while` loop
+            break 456;
+            break 789;
+        };
+    }
+
+    while let Some(_) = Some(()) {
+        if break () { //~ ERROR `break` with value from a `while let` loop
+        }
+    }
+
+    while let Some(_) = Some(()) {
+        break None;
+        //~^ ERROR `break` with value from a `while let` loop
+    }
+
+    'while_let_loop: while let Some(_) = Some(()) {
+        loop {
+            break 'while_let_loop "nope";
+            //~^ ERROR `break` with value from a `while let` loop
+            break 33;
+        };
+    }
+
+    for _ in &[1,2,3] {
+        break (); //~ ERROR `break` with value from a `for` loop
+        break [()];
+        //~^ ERROR `break` with value from a `for` loop
+    }
+
+    'for_loop: for _ in &[1,2,3] {
+        loop {
+            break Some(3);
+            break 'for_loop Some(17);
+            //~^ ERROR `break` with value from a `for` loop
+        };
+    }
+
+    let _: i32 = 'a: loop {
+        let _: () = 'b: loop {
+            break ('c: loop {
+                break;
+                break 'c 123; //~ ERROR mismatched types
+            });
+            break 'a 123;
+        };
+    };
+
+    loop {
+        break (break, break); //~ ERROR mismatched types
+    };
+
+    loop {
+        break;
+        break 2; //~ ERROR mismatched types
+    };
+
+    loop {
+        break 2;
+        break; //~ ERROR mismatched types
+        break 4;
+    };
+}
diff --git a/src/test/ui/loops/loop-break-value.stderr b/src/test/ui/loops/loop-break-value.stderr
new file mode 100644
index 0000000..8823eec
--- /dev/null
+++ b/src/test/ui/loops/loop-break-value.stderr
@@ -0,0 +1,156 @@
+error[E0571]: `break` with value from a `while` loop
+  --> $DIR/loop-break-value.rs:28:9
+   |
+LL |         break ();
+   |         ^^^^^^^^ can only break with a value inside `loop` or breakable block
+help: instead, use `break` on its own without a value inside this `while` loop
+   |
+LL |         break;
+   |         ^^^^^
+
+error[E0571]: `break` with value from a `while` loop
+  --> $DIR/loop-break-value.rs:30:13
+   |
+LL |             break 'while_loop 123;
+   |             ^^^^^^^^^^^^^^^^^^^^^ can only break with a value inside `loop` or breakable block
+help: instead, use `break` on its own without a value inside this `while` loop
+   |
+LL |             break;
+   |             ^^^^^
+
+error[E0571]: `break` with value from a `while let` loop
+  --> $DIR/loop-break-value.rs:38:12
+   |
+LL |         if break () {
+   |            ^^^^^^^^ can only break with a value inside `loop` or breakable block
+help: instead, use `break` on its own without a value inside this `while let` loop
+   |
+LL |         if break {
+   |            ^^^^^
+
+error[E0571]: `break` with value from a `while let` loop
+  --> $DIR/loop-break-value.rs:43:9
+   |
+LL |         break None;
+   |         ^^^^^^^^^^ can only break with a value inside `loop` or breakable block
+help: instead, use `break` on its own without a value inside this `while let` loop
+   |
+LL |         break;
+   |         ^^^^^
+
+error[E0571]: `break` with value from a `while let` loop
+  --> $DIR/loop-break-value.rs:49:13
+   |
+LL |             break 'while_let_loop "nope";
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can only break with a value inside `loop` or breakable block
+help: instead, use `break` on its own without a value inside this `while let` loop
+   |
+LL |             break;
+   |             ^^^^^
+
+error[E0571]: `break` with value from a `for` loop
+  --> $DIR/loop-break-value.rs:56:9
+   |
+LL |         break ();
+   |         ^^^^^^^^ can only break with a value inside `loop` or breakable block
+help: instead, use `break` on its own without a value inside this `for` loop
+   |
+LL |         break;
+   |         ^^^^^
+
+error[E0571]: `break` with value from a `for` loop
+  --> $DIR/loop-break-value.rs:57:9
+   |
+LL |         break [()];
+   |         ^^^^^^^^^^ can only break with a value inside `loop` or breakable block
+help: instead, use `break` on its own without a value inside this `for` loop
+   |
+LL |         break;
+   |         ^^^^^
+
+error[E0571]: `break` with value from a `for` loop
+  --> $DIR/loop-break-value.rs:64:13
+   |
+LL |             break 'for_loop Some(17);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^ can only break with a value inside `loop` or breakable block
+help: instead, use `break` on its own without a value inside this `for` loop
+   |
+LL |             break;
+   |             ^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/loop-break-value.rs:4:31
+   |
+LL |     let val: ! = loop { break break; };
+   |                               ^^^^^ expected (), found !
+   |
+   = note: expected type `()`
+              found type `!`
+
+error[E0308]: mismatched types
+  --> $DIR/loop-break-value.rs:11:19
+   |
+LL |             break 123;
+   |                   ^^^ expected &str, found integer
+   |
+   = note: expected type `&str`
+              found type `{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/loop-break-value.rs:16:15
+   |
+LL |         break "asdf";
+   |               ^^^^^^ expected i32, found reference
+   |
+   = note: expected type `i32`
+              found type `&'static str`
+
+error[E0308]: mismatched types
+  --> $DIR/loop-break-value.rs:21:31
+   |
+LL |             break 'outer_loop "nope";
+   |                               ^^^^^^ expected i32, found reference
+   |
+   = note: expected type `i32`
+              found type `&'static str`
+
+error[E0308]: mismatched types
+  --> $DIR/loop-break-value.rs:73:26
+   |
+LL |                 break 'c 123;
+   |                          ^^^ expected (), found integer
+   |
+   = note: expected type `()`
+              found type `{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/loop-break-value.rs:80:15
+   |
+LL |         break (break, break);
+   |               ^^^^^^^^^^^^^^ expected (), found tuple
+   |
+   = note: expected type `()`
+              found type `(!, !)`
+
+error[E0308]: mismatched types
+  --> $DIR/loop-break-value.rs:85:15
+   |
+LL |         break 2;
+   |               ^ expected (), found integer
+   |
+   = note: expected type `()`
+              found type `{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/loop-break-value.rs:90:9
+   |
+LL |         break;
+   |         ^^^^^ expected (), found integer
+   |
+   = note: expected type `()`
+              found type `{integer}`
+
+error: aborting due to 16 previous errors
+
+Some errors occurred: E0308, E0571.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/loops/loop-labeled-break-value.rs b/src/test/ui/loops/loop-labeled-break-value.rs
new file mode 100644
index 0000000..3488b05
--- /dev/null
+++ b/src/test/ui/loops/loop-labeled-break-value.rs
@@ -0,0 +1,11 @@
+fn main() {
+    loop {
+        let _: i32 = loop { break }; //~ ERROR mismatched types
+    }
+    loop {
+        let _: i32 = 'inner: loop { break 'inner }; //~ ERROR mismatched types
+    }
+    loop {
+        let _: i32 = 'inner2: loop { loop { break 'inner2 } }; //~ ERROR mismatched types
+    }
+}
diff --git a/src/test/ui/loops/loop-labeled-break-value.stderr b/src/test/ui/loops/loop-labeled-break-value.stderr
new file mode 100644
index 0000000..ad7cb4b
--- /dev/null
+++ b/src/test/ui/loops/loop-labeled-break-value.stderr
@@ -0,0 +1,30 @@
+error[E0308]: mismatched types
+  --> $DIR/loop-labeled-break-value.rs:3:29
+   |
+LL |         let _: i32 = loop { break };
+   |                             ^^^^^ expected (), found i32
+   |
+   = note: expected type `()`
+              found type `i32`
+
+error[E0308]: mismatched types
+  --> $DIR/loop-labeled-break-value.rs:6:37
+   |
+LL |         let _: i32 = 'inner: loop { break 'inner };
+   |                                     ^^^^^^^^^^^^ expected (), found i32
+   |
+   = note: expected type `()`
+              found type `i32`
+
+error[E0308]: mismatched types
+  --> $DIR/loop-labeled-break-value.rs:9:45
+   |
+LL |         let _: i32 = 'inner2: loop { loop { break 'inner2 } };
+   |                                             ^^^^^^^^^^^^^ expected (), found i32
+   |
+   = note: expected type `()`
+              found type `i32`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/loops/loop-proper-liveness.nll.stderr b/src/test/ui/loops/loop-proper-liveness.nll.stderr
new file mode 100644
index 0000000..c877206
--- /dev/null
+++ b/src/test/ui/loops/loop-proper-liveness.nll.stderr
@@ -0,0 +1,9 @@
+error[E0381]: borrow of possibly uninitialized variable: `x`
+  --> $DIR/loop-proper-liveness.rs:9:22
+   |
+LL |     println!("{:?}", x);
+   |                      ^ use of possibly uninitialized `x`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/loops/loop-proper-liveness.rs b/src/test/ui/loops/loop-proper-liveness.rs
new file mode 100644
index 0000000..fd9d661
--- /dev/null
+++ b/src/test/ui/loops/loop-proper-liveness.rs
@@ -0,0 +1,32 @@
+fn test1() {
+    // In this test the outer 'a loop may terminate without `x` getting initialised. Although the
+    // `x = loop { ... }` statement is reached, the value itself ends up never being computed and
+    // thus leaving `x` uninit.
+    let x: i32;
+    'a: loop {
+        x = loop { break 'a };
+    }
+    println!("{:?}", x); //~ ERROR use of possibly uninitialized variable
+}
+
+// test2 and test3 should not fail.
+fn test2() {
+    // In this test the `'a` loop will never terminate thus making the use of `x` unreachable.
+    let x: i32;
+    'a: loop {
+        x = loop { continue 'a };
+    }
+    println!("{:?}", x);
+}
+
+fn test3() {
+    let x: i32;
+    // Similarly, the use of variable `x` is unreachable.
+    'a: loop {
+        x = loop { return };
+    }
+    println!("{:?}", x);
+}
+
+fn main() {
+}
diff --git a/src/test/ui/loops/loop-proper-liveness.stderr b/src/test/ui/loops/loop-proper-liveness.stderr
new file mode 100644
index 0000000..392b961
--- /dev/null
+++ b/src/test/ui/loops/loop-proper-liveness.stderr
@@ -0,0 +1,9 @@
+error[E0381]: use of possibly uninitialized variable: `x`
+  --> $DIR/loop-proper-liveness.rs:9:22
+   |
+LL |     println!("{:?}", x);
+   |                      ^ use of possibly uninitialized `x`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/loops/loop-properly-diverging-2.rs b/src/test/ui/loops/loop-properly-diverging-2.rs
new file mode 100644
index 0000000..97b3972
--- /dev/null
+++ b/src/test/ui/loops/loop-properly-diverging-2.rs
@@ -0,0 +1,6 @@
+fn forever2() -> i32 {
+  let x: i32 = loop { break }; //~ ERROR mismatched types
+  x
+}
+
+fn main() {}
diff --git a/src/test/ui/loops/loop-properly-diverging-2.stderr b/src/test/ui/loops/loop-properly-diverging-2.stderr
new file mode 100644
index 0000000..6293fdb
--- /dev/null
+++ b/src/test/ui/loops/loop-properly-diverging-2.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/loop-properly-diverging-2.rs:2:23
+   |
+LL |   let x: i32 = loop { break };
+   |                       ^^^^^ expected (), found i32
+   |
+   = note: expected type `()`
+              found type `i32`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/loops/loops-reject-duplicate-labels-2.rs b/src/test/ui/loops/loops-reject-duplicate-labels-2.rs
new file mode 100644
index 0000000..93f322a
--- /dev/null
+++ b/src/test/ui/loops/loops-reject-duplicate-labels-2.rs
@@ -0,0 +1,35 @@
+// compile-pass
+
+// ignore-tidy-linelength
+
+// Issue #21633: reject duplicate loop labels in function bodies.
+//
+// This is testing the generalization (to the whole function body)
+// discussed here:
+// https://internals.rust-lang.org/t/psa-rejecting-duplicate-loop-labels/1833
+
+#[allow(unused_labels)]
+pub fn foo() {
+    { 'fl: for _ in 0..10 { break; } }
+    { 'fl: loop { break; } }             //~ WARN label name `'fl` shadows a label name that is already in scope
+    { 'lf: loop { break; } }
+    { 'lf: for _ in 0..10 { break; } }   //~ WARN label name `'lf` shadows a label name that is already in scope
+    { 'wl: while 2 > 1 { break; } }
+    { 'wl: loop { break; } }             //~ WARN label name `'wl` shadows a label name that is already in scope
+    { 'lw: loop { break; } }
+    { 'lw: while 2 > 1 { break; } }      //~ WARN label name `'lw` shadows a label name that is already in scope
+    { 'fw: for _ in 0..10 { break; } }
+    { 'fw: while 2 > 1 { break; } }      //~ WARN label name `'fw` shadows a label name that is already in scope
+    { 'wf: while 2 > 1 { break; } }
+    { 'wf: for _ in 0..10 { break; } }   //~ WARN label name `'wf` shadows a label name that is already in scope
+    { 'tl: while let Some(_) = None::<i32> { break; } }
+    { 'tl: loop { break; } }             //~ WARN label name `'tl` shadows a label name that is already in scope
+    { 'lt: loop { break; } }
+    { 'lt: while let Some(_) = None::<i32> { break; } }
+                                         //~^ WARN label name `'lt` shadows a label name that is already in scope
+}
+
+
+pub fn main() {
+    foo();
+}
diff --git a/src/test/ui/loops/loops-reject-duplicate-labels-2.stderr b/src/test/ui/loops/loops-reject-duplicate-labels-2.stderr
new file mode 100644
index 0000000..fc42449
--- /dev/null
+++ b/src/test/ui/loops/loops-reject-duplicate-labels-2.stderr
@@ -0,0 +1,64 @@
+warning: label name `'fl` shadows a label name that is already in scope
+  --> $DIR/loops-reject-duplicate-labels-2.rs:14:7
+   |
+LL |     { 'fl: for _ in 0..10 { break; } }
+   |       --- first declared here
+LL |     { 'fl: loop { break; } }
+   |       ^^^ lifetime 'fl already in scope
+
+warning: label name `'lf` shadows a label name that is already in scope
+  --> $DIR/loops-reject-duplicate-labels-2.rs:16:7
+   |
+LL |     { 'lf: loop { break; } }
+   |       --- first declared here
+LL |     { 'lf: for _ in 0..10 { break; } }
+   |       ^^^ lifetime 'lf already in scope
+
+warning: label name `'wl` shadows a label name that is already in scope
+  --> $DIR/loops-reject-duplicate-labels-2.rs:18:7
+   |
+LL |     { 'wl: while 2 > 1 { break; } }
+   |       --- first declared here
+LL |     { 'wl: loop { break; } }
+   |       ^^^ lifetime 'wl already in scope
+
+warning: label name `'lw` shadows a label name that is already in scope
+  --> $DIR/loops-reject-duplicate-labels-2.rs:20:7
+   |
+LL |     { 'lw: loop { break; } }
+   |       --- first declared here
+LL |     { 'lw: while 2 > 1 { break; } }
+   |       ^^^ lifetime 'lw already in scope
+
+warning: label name `'fw` shadows a label name that is already in scope
+  --> $DIR/loops-reject-duplicate-labels-2.rs:22:7
+   |
+LL |     { 'fw: for _ in 0..10 { break; } }
+   |       --- first declared here
+LL |     { 'fw: while 2 > 1 { break; } }
+   |       ^^^ lifetime 'fw already in scope
+
+warning: label name `'wf` shadows a label name that is already in scope
+  --> $DIR/loops-reject-duplicate-labels-2.rs:24:7
+   |
+LL |     { 'wf: while 2 > 1 { break; } }
+   |       --- first declared here
+LL |     { 'wf: for _ in 0..10 { break; } }
+   |       ^^^ lifetime 'wf already in scope
+
+warning: label name `'tl` shadows a label name that is already in scope
+  --> $DIR/loops-reject-duplicate-labels-2.rs:26:7
+   |
+LL |     { 'tl: while let Some(_) = None::<i32> { break; } }
+   |       --- first declared here
+LL |     { 'tl: loop { break; } }
+   |       ^^^ lifetime 'tl already in scope
+
+warning: label name `'lt` shadows a label name that is already in scope
+  --> $DIR/loops-reject-duplicate-labels-2.rs:28:7
+   |
+LL |     { 'lt: loop { break; } }
+   |       --- first declared here
+LL |     { 'lt: while let Some(_) = None::<i32> { break; } }
+   |       ^^^ lifetime 'lt already in scope
+
diff --git a/src/test/ui/loops/loops-reject-duplicate-labels.rs b/src/test/ui/loops/loops-reject-duplicate-labels.rs
new file mode 100644
index 0000000..27f9862
--- /dev/null
+++ b/src/test/ui/loops/loops-reject-duplicate-labels.rs
@@ -0,0 +1,45 @@
+// compile-pass
+
+// ignore-tidy-linelength
+
+// Issue #21633: reject duplicate loop labels in function bodies.
+// This is testing the exact cases that are in the issue description.
+
+#[allow(unused_labels)]
+fn foo() {
+    'fl: for _ in 0..10 { break; }
+    'fl: loop { break; }           //~ WARN label name `'fl` shadows a label name that is already in scope
+
+    'lf: loop { break; }
+    'lf: for _ in 0..10 { break; } //~ WARN label name `'lf` shadows a label name that is already in scope
+    'wl: while 2 > 1 { break; }
+    'wl: loop { break; }           //~ WARN label name `'wl` shadows a label name that is already in scope
+    'lw: loop { break; }
+    'lw: while 2 > 1 { break; }    //~ WARN label name `'lw` shadows a label name that is already in scope
+    'fw: for _ in 0..10 { break; }
+    'fw: while 2 > 1 { break; }    //~ WARN label name `'fw` shadows a label name that is already in scope
+    'wf: while 2 > 1 { break; }
+    'wf: for _ in 0..10 { break; } //~ WARN label name `'wf` shadows a label name that is already in scope
+    'tl: while let Some(_) = None::<i32> { break; }
+    'tl: loop { break; }           //~ WARN label name `'tl` shadows a label name that is already in scope
+    'lt: loop { break; }
+    'lt: while let Some(_) = None::<i32> { break; }
+                                   //~^ WARN label name `'lt` shadows a label name that is already in scope
+}
+
+// Note however that it is okay for the same label to be reused in
+// different methods of one impl, as illustrated here.
+
+struct S;
+impl S {
+    fn m1(&self) { 'okay: loop { break 'okay; } }
+    fn m2(&self) { 'okay: loop { break 'okay; } }
+}
+
+
+pub fn main() {
+    let s = S;
+    s.m1();
+    s.m2();
+    foo();
+}
diff --git a/src/test/ui/loops/loops-reject-duplicate-labels.stderr b/src/test/ui/loops/loops-reject-duplicate-labels.stderr
new file mode 100644
index 0000000..4574c5c
--- /dev/null
+++ b/src/test/ui/loops/loops-reject-duplicate-labels.stderr
@@ -0,0 +1,64 @@
+warning: label name `'fl` shadows a label name that is already in scope
+  --> $DIR/loops-reject-duplicate-labels.rs:11:5
+   |
+LL |     'fl: for _ in 0..10 { break; }
+   |     --- first declared here
+LL |     'fl: loop { break; }
+   |     ^^^ lifetime 'fl already in scope
+
+warning: label name `'lf` shadows a label name that is already in scope
+  --> $DIR/loops-reject-duplicate-labels.rs:14:5
+   |
+LL |     'lf: loop { break; }
+   |     --- first declared here
+LL |     'lf: for _ in 0..10 { break; }
+   |     ^^^ lifetime 'lf already in scope
+
+warning: label name `'wl` shadows a label name that is already in scope
+  --> $DIR/loops-reject-duplicate-labels.rs:16:5
+   |
+LL |     'wl: while 2 > 1 { break; }
+   |     --- first declared here
+LL |     'wl: loop { break; }
+   |     ^^^ lifetime 'wl already in scope
+
+warning: label name `'lw` shadows a label name that is already in scope
+  --> $DIR/loops-reject-duplicate-labels.rs:18:5
+   |
+LL |     'lw: loop { break; }
+   |     --- first declared here
+LL |     'lw: while 2 > 1 { break; }
+   |     ^^^ lifetime 'lw already in scope
+
+warning: label name `'fw` shadows a label name that is already in scope
+  --> $DIR/loops-reject-duplicate-labels.rs:20:5
+   |
+LL |     'fw: for _ in 0..10 { break; }
+   |     --- first declared here
+LL |     'fw: while 2 > 1 { break; }
+   |     ^^^ lifetime 'fw already in scope
+
+warning: label name `'wf` shadows a label name that is already in scope
+  --> $DIR/loops-reject-duplicate-labels.rs:22:5
+   |
+LL |     'wf: while 2 > 1 { break; }
+   |     --- first declared here
+LL |     'wf: for _ in 0..10 { break; }
+   |     ^^^ lifetime 'wf already in scope
+
+warning: label name `'tl` shadows a label name that is already in scope
+  --> $DIR/loops-reject-duplicate-labels.rs:24:5
+   |
+LL |     'tl: while let Some(_) = None::<i32> { break; }
+   |     --- first declared here
+LL |     'tl: loop { break; }
+   |     ^^^ lifetime 'tl already in scope
+
+warning: label name `'lt` shadows a label name that is already in scope
+  --> $DIR/loops-reject-duplicate-labels.rs:26:5
+   |
+LL |     'lt: loop { break; }
+   |     --- first declared here
+LL |     'lt: while let Some(_) = None::<i32> { break; }
+   |     ^^^ lifetime 'lt already in scope
+
diff --git a/src/test/ui/loops/loops-reject-labels-shadowing-lifetimes.rs b/src/test/ui/loops/loops-reject-labels-shadowing-lifetimes.rs
new file mode 100644
index 0000000..435ad33
--- /dev/null
+++ b/src/test/ui/loops/loops-reject-labels-shadowing-lifetimes.rs
@@ -0,0 +1,109 @@
+// Issue #21633: reject duplicate loop labels in function bodies.
+// This is testing interaction between lifetime-params and labels.
+
+// compile-pass
+
+#![allow(dead_code, unused_variables)]
+
+fn foo() {
+    fn foo<'a>() {
+        'a: loop { break 'a; }
+        //~^ WARN label name `'a` shadows a lifetime name that is already in scope
+    }
+
+    struct Struct<'b, 'c> { _f: &'b i8, _g: &'c i8 }
+    enum Enum<'d, 'e> { A(&'d i8), B(&'e i8) }
+
+    impl<'d, 'e> Struct<'d, 'e> {
+        fn meth_okay() {
+            'a: loop { break 'a; }
+            'b: loop { break 'b; }
+            'c: loop { break 'c; }
+        }
+    }
+
+    impl <'d, 'e> Enum<'d, 'e> {
+        fn meth_okay() {
+            'a: loop { break 'a; }
+            'b: loop { break 'b; }
+            'c: loop { break 'c; }
+        }
+    }
+
+    impl<'bad, 'c> Struct<'bad, 'c> {
+        fn meth_bad(&self) {
+            'bad: loop { break 'bad; }
+            //~^ WARN label name `'bad` shadows a lifetime name that is already in scope
+        }
+    }
+
+    impl<'b, 'bad> Struct<'b, 'bad> {
+        fn meth_bad2(&self) {
+            'bad: loop { break 'bad; }
+            //~^ WARN label name `'bad` shadows a lifetime name that is already in scope
+        }
+    }
+
+    impl<'b, 'c> Struct<'b, 'c> {
+        fn meth_bad3<'bad>(x: &'bad i8) {
+            'bad: loop { break 'bad; }
+            //~^ WARN label name `'bad` shadows a lifetime name that is already in scope
+        }
+
+        fn meth_bad4<'a,'bad>(x: &'a i8, y: &'bad i8) {
+            'bad: loop { break 'bad; }
+            //~^ WARN label name `'bad` shadows a lifetime name that is already in scope
+        }
+    }
+
+    impl <'bad, 'e> Enum<'bad, 'e> {
+        fn meth_bad(&self) {
+            'bad: loop { break 'bad; }
+            //~^ WARN label name `'bad` shadows a lifetime name that is already in scope
+        }
+    }
+    impl <'d, 'bad> Enum<'d, 'bad> {
+        fn meth_bad2(&self) {
+            'bad: loop { break 'bad; }
+            //~^ WARN label name `'bad` shadows a lifetime name that is already in scope
+        }
+    }
+    impl <'d, 'e> Enum<'d, 'e> {
+        fn meth_bad3<'bad>(x: &'bad i8) {
+            'bad: loop { break 'bad; }
+            //~^ WARN label name `'bad` shadows a lifetime name that is already in scope
+        }
+
+        fn meth_bad4<'a,'bad>(x: &'bad i8) {
+            'bad: loop { break 'bad; }
+            //~^ WARN label name `'bad` shadows a lifetime name that is already in scope
+        }
+    }
+
+    trait HasDefaultMethod1<'bad> {
+        fn meth_okay() {
+            'c: loop { break 'c; }
+        }
+        fn meth_bad(&self) {
+            'bad: loop { break 'bad; }
+            //~^ WARN label name `'bad` shadows a lifetime name that is already in scope
+        }
+    }
+    trait HasDefaultMethod2<'a,'bad> {
+        fn meth_bad(&self) {
+            'bad: loop { break 'bad; }
+            //~^ WARN label name `'bad` shadows a lifetime name that is already in scope
+        }
+    }
+    trait HasDefaultMethod3<'a,'b> {
+        fn meth_bad<'bad>(&self) {
+            'bad: loop { break 'bad; }
+            //~^ WARN label name `'bad` shadows a lifetime name that is already in scope
+        }
+    }
+}
+
+
+pub fn main() {
+    foo();
+}
diff --git a/src/test/ui/loops/loops-reject-labels-shadowing-lifetimes.stderr b/src/test/ui/loops/loops-reject-labels-shadowing-lifetimes.stderr
new file mode 100644
index 0000000..e9f93ab
--- /dev/null
+++ b/src/test/ui/loops/loops-reject-labels-shadowing-lifetimes.stderr
@@ -0,0 +1,102 @@
+warning: label name `'a` shadows a lifetime name that is already in scope
+  --> $DIR/loops-reject-labels-shadowing-lifetimes.rs:10:9
+   |
+LL |     fn foo<'a>() {
+   |            -- first declared here
+LL |         'a: loop { break 'a; }
+   |         ^^ lifetime 'a already in scope
+
+warning: label name `'bad` shadows a lifetime name that is already in scope
+  --> $DIR/loops-reject-labels-shadowing-lifetimes.rs:35:13
+   |
+LL |     impl<'bad, 'c> Struct<'bad, 'c> {
+   |          ---- first declared here
+LL |         fn meth_bad(&self) {
+LL |             'bad: loop { break 'bad; }
+   |             ^^^^ lifetime 'bad already in scope
+
+warning: label name `'bad` shadows a lifetime name that is already in scope
+  --> $DIR/loops-reject-labels-shadowing-lifetimes.rs:42:13
+   |
+LL |     impl<'b, 'bad> Struct<'b, 'bad> {
+   |              ---- first declared here
+LL |         fn meth_bad2(&self) {
+LL |             'bad: loop { break 'bad; }
+   |             ^^^^ lifetime 'bad already in scope
+
+warning: label name `'bad` shadows a lifetime name that is already in scope
+  --> $DIR/loops-reject-labels-shadowing-lifetimes.rs:49:13
+   |
+LL |         fn meth_bad3<'bad>(x: &'bad i8) {
+   |                      ---- first declared here
+LL |             'bad: loop { break 'bad; }
+   |             ^^^^ lifetime 'bad already in scope
+
+warning: label name `'bad` shadows a lifetime name that is already in scope
+  --> $DIR/loops-reject-labels-shadowing-lifetimes.rs:54:13
+   |
+LL |         fn meth_bad4<'a,'bad>(x: &'a i8, y: &'bad i8) {
+   |                         ---- first declared here
+LL |             'bad: loop { break 'bad; }
+   |             ^^^^ lifetime 'bad already in scope
+
+warning: label name `'bad` shadows a lifetime name that is already in scope
+  --> $DIR/loops-reject-labels-shadowing-lifetimes.rs:61:13
+   |
+LL |     impl <'bad, 'e> Enum<'bad, 'e> {
+   |           ---- first declared here
+LL |         fn meth_bad(&self) {
+LL |             'bad: loop { break 'bad; }
+   |             ^^^^ lifetime 'bad already in scope
+
+warning: label name `'bad` shadows a lifetime name that is already in scope
+  --> $DIR/loops-reject-labels-shadowing-lifetimes.rs:67:13
+   |
+LL |     impl <'d, 'bad> Enum<'d, 'bad> {
+   |               ---- first declared here
+LL |         fn meth_bad2(&self) {
+LL |             'bad: loop { break 'bad; }
+   |             ^^^^ lifetime 'bad already in scope
+
+warning: label name `'bad` shadows a lifetime name that is already in scope
+  --> $DIR/loops-reject-labels-shadowing-lifetimes.rs:73:13
+   |
+LL |         fn meth_bad3<'bad>(x: &'bad i8) {
+   |                      ---- first declared here
+LL |             'bad: loop { break 'bad; }
+   |             ^^^^ lifetime 'bad already in scope
+
+warning: label name `'bad` shadows a lifetime name that is already in scope
+  --> $DIR/loops-reject-labels-shadowing-lifetimes.rs:78:13
+   |
+LL |         fn meth_bad4<'a,'bad>(x: &'bad i8) {
+   |                         ---- first declared here
+LL |             'bad: loop { break 'bad; }
+   |             ^^^^ lifetime 'bad already in scope
+
+warning: label name `'bad` shadows a lifetime name that is already in scope
+  --> $DIR/loops-reject-labels-shadowing-lifetimes.rs:88:13
+   |
+LL |     trait HasDefaultMethod1<'bad> {
+   |                             ---- first declared here
+...
+LL |             'bad: loop { break 'bad; }
+   |             ^^^^ lifetime 'bad already in scope
+
+warning: label name `'bad` shadows a lifetime name that is already in scope
+  --> $DIR/loops-reject-labels-shadowing-lifetimes.rs:94:13
+   |
+LL |     trait HasDefaultMethod2<'a,'bad> {
+   |                                ---- first declared here
+LL |         fn meth_bad(&self) {
+LL |             'bad: loop { break 'bad; }
+   |             ^^^^ lifetime 'bad already in scope
+
+warning: label name `'bad` shadows a lifetime name that is already in scope
+  --> $DIR/loops-reject-labels-shadowing-lifetimes.rs:100:13
+   |
+LL |         fn meth_bad<'bad>(&self) {
+   |                     ---- first declared here
+LL |             'bad: loop { break 'bad; }
+   |             ^^^^ lifetime 'bad already in scope
+
diff --git a/src/test/ui/loops/loops-reject-lifetime-shadowing-label.rs b/src/test/ui/loops/loops-reject-lifetime-shadowing-label.rs
new file mode 100644
index 0000000..f48e984
--- /dev/null
+++ b/src/test/ui/loops/loops-reject-lifetime-shadowing-label.rs
@@ -0,0 +1,31 @@
+// compile-pass
+
+#![allow(dead_code, unused_variables)]
+
+// Issue #21633:  reject duplicate loop labels in function bodies.
+//
+// Test rejection of lifetimes in *expressions* that shadow loop labels.
+
+fn foo() {
+    // Reusing lifetime `'a` in function item is okay.
+    fn foo<'a>(x: &'a i8) -> i8 { *x }
+
+    // So is reusing `'a` in struct item
+    struct S1<'a> { x: &'a i8 } impl<'a> S1<'a> { fn m(&self) {} }
+    // and a method item
+    struct S2; impl S2 { fn m<'a>(&self) {} }
+
+    let z = 3_i8;
+
+    'a: loop {
+        let b = Box::new(|x: &i8| *x) as Box<for <'a> Fn(&'a i8) -> i8>;
+        //~^ WARN lifetime name `'a` shadows a label name that is already in scope
+        assert_eq!((*b)(&z), z);
+        break 'a;
+    }
+}
+
+
+pub fn main() {
+    foo();
+}
diff --git a/src/test/ui/loops/loops-reject-lifetime-shadowing-label.stderr b/src/test/ui/loops/loops-reject-lifetime-shadowing-label.stderr
new file mode 100644
index 0000000..4c4d921
--- /dev/null
+++ b/src/test/ui/loops/loops-reject-lifetime-shadowing-label.stderr
@@ -0,0 +1,8 @@
+warning: lifetime name `'a` shadows a label name that is already in scope
+  --> $DIR/loops-reject-lifetime-shadowing-label.rs:21:51
+   |
+LL |     'a: loop {
+   |     -- first declared here
+LL |         let b = Box::new(|x: &i8| *x) as Box<for <'a> Fn(&'a i8) -> i8>;
+   |                                                   ^^ lifetime 'a already in scope
+
diff --git a/src/test/ui/loud_ui.rs b/src/test/ui/loud_ui.rs
new file mode 100644
index 0000000..6a151fa
--- /dev/null
+++ b/src/test/ui/loud_ui.rs
@@ -0,0 +1,6 @@
+// should-fail
+
+// this test ensures that when we forget to use
+// any `//~ ERROR` comments whatsoever, that the test doesn't succeed
+
+fn main() {}
diff --git a/src/test/ui/lto-duplicate-symbols.rs b/src/test/ui/lto-duplicate-symbols.rs
new file mode 100644
index 0000000..c95e9fb
--- /dev/null
+++ b/src/test/ui/lto-duplicate-symbols.rs
@@ -0,0 +1,10 @@
+// aux-build:lto-duplicate-symbols1.rs
+// aux-build:lto-duplicate-symbols2.rs
+// error-pattern:Linking globals named 'foo': symbol multiply defined!
+// compile-flags: -C lto
+// no-prefer-dynamic
+
+extern crate lto_duplicate_symbols1;
+extern crate lto_duplicate_symbols2;
+
+fn main() {}
diff --git a/src/test/ui/lto-duplicate-symbols.stderr b/src/test/ui/lto-duplicate-symbols.stderr
new file mode 100644
index 0000000..5760cb9
--- /dev/null
+++ b/src/test/ui/lto-duplicate-symbols.stderr
@@ -0,0 +1,6 @@
+warning: Linking globals named 'foo': symbol multiply defined!
+
+error: failed to load bc of "lto_duplicate_symbols1.3a1fbbbh-cgu.0": 
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lub-glb/old-lub-glb-hr.rs b/src/test/ui/lub-glb/old-lub-glb-hr.rs
new file mode 100644
index 0000000..6bf1fd4
--- /dev/null
+++ b/src/test/ui/lub-glb/old-lub-glb-hr.rs
@@ -0,0 +1,32 @@
+// Test that we give a note when the old LUB/GLB algorithm would have
+// succeeded but the new code (which requires equality) gives an
+// error. However, now that we handle subtyping correctly, we no
+// longer get an error, because we recognize these two types as
+// equivalent!
+//
+// Whoops -- now that we reinstituted the leak-check, we get an error
+// again.
+
+fn foo(
+    x: fn(&u8, &u8),
+    y: for<'a> fn(&'a u8, &'a u8),
+) {
+    let z = match 22 {
+        0 => x,
+        _ => y, //~ ERROR match arms have incompatible types
+    };
+}
+
+fn bar(
+    x: fn(&u8, &u8),
+    y: for<'a> fn(&'a u8, &'a u8),
+) {
+    let z = match 22 {
+        // No error with an explicit cast:
+        0 => x as for<'a> fn(&'a u8, &'a u8),
+        _ => y,
+    };
+}
+
+fn main() {
+}
diff --git a/src/test/ui/lub-glb/old-lub-glb-hr.stderr b/src/test/ui/lub-glb/old-lub-glb-hr.stderr
new file mode 100644
index 0000000..475c180
--- /dev/null
+++ b/src/test/ui/lub-glb/old-lub-glb-hr.stderr
@@ -0,0 +1,18 @@
+error[E0308]: match arms have incompatible types
+  --> $DIR/old-lub-glb-hr.rs:16:14
+   |
+LL |       let z = match 22 {
+   |  _____________-
+LL | |         0 => x,
+   | |              - this is found to be of type `for<'r, 's> fn(&'r u8, &'s u8)`
+LL | |         _ => y,
+   | |              ^ expected bound lifetime parameter, found concrete lifetime
+LL | |     };
+   | |_____- `match` arms have incompatible types
+   |
+   = note: expected type `for<'r, 's> fn(&'r u8, &'s u8)`
+              found type `for<'a> fn(&'a u8, &'a u8)`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/lub-glb/old-lub-glb-object.rs b/src/test/ui/lub-glb/old-lub-glb-object.rs
new file mode 100644
index 0000000..dcd604a
--- /dev/null
+++ b/src/test/ui/lub-glb/old-lub-glb-object.rs
@@ -0,0 +1,28 @@
+// Test that we give a note when the old LUB/GLB algorithm would have
+// succeeded but the new code (which is stricter) gives an error.
+
+trait Foo<T, U> { }
+
+fn foo(
+    x: &for<'a, 'b> Foo<&'a u8, &'b u8>,
+    y: &for<'a> Foo<&'a u8, &'a u8>,
+) {
+    let z = match 22 {
+        0 => x,
+        _ => y, //~ ERROR match arms have incompatible types
+    };
+}
+
+fn bar(
+    x: &for<'a, 'b> Foo<&'a u8, &'b u8>,
+    y: &for<'a> Foo<&'a u8, &'a u8>,
+) {
+    // Accepted with explicit case:
+    let z = match 22 {
+        0 => x as &for<'a> Foo<&'a u8, &'a u8>,
+        _ => y,
+    };
+}
+
+fn main() {
+}
diff --git a/src/test/ui/lub-glb/old-lub-glb-object.stderr b/src/test/ui/lub-glb/old-lub-glb-object.stderr
new file mode 100644
index 0000000..e02ede3
--- /dev/null
+++ b/src/test/ui/lub-glb/old-lub-glb-object.stderr
@@ -0,0 +1,18 @@
+error[E0308]: match arms have incompatible types
+  --> $DIR/old-lub-glb-object.rs:12:14
+   |
+LL |       let z = match 22 {
+   |  _____________-
+LL | |         0 => x,
+   | |              - this is found to be of type `&dyn for<'a, 'b> Foo<&'a u8, &'b u8>`
+LL | |         _ => y,
+   | |              ^ expected bound lifetime parameter 'a, found concrete lifetime
+LL | |     };
+   | |_____- `match` arms have incompatible types
+   |
+   = note: expected type `&dyn for<'a, 'b> Foo<&'a u8, &'b u8>`
+              found type `&dyn for<'a> Foo<&'a u8, &'a u8>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/lub-if.rs b/src/test/ui/lub-if.rs
new file mode 100644
index 0000000..132b838
--- /dev/null
+++ b/src/test/ui/lub-if.rs
@@ -0,0 +1,42 @@
+// Test that we correctly consider the type of `match` to be the LUB
+// of the various arms, particularly in the case where regions are
+// involved.
+
+pub fn opt_str0<'a>(maybestr: &'a Option<String>) -> &'a str {
+    if maybestr.is_none() {
+        "(none)"
+    } else {
+        let s: &'a str = maybestr.as_ref().unwrap();
+        s
+    }
+}
+
+pub fn opt_str1<'a>(maybestr: &'a Option<String>) -> &'a str {
+    if maybestr.is_some() {
+        let s: &'a str = maybestr.as_ref().unwrap();
+        s
+    } else {
+        "(none)"
+    }
+}
+
+pub fn opt_str2<'a>(maybestr: &'a Option<String>) -> &'static str {
+    if maybestr.is_none() {
+        "(none)"
+    } else {
+        let s: &'a str = maybestr.as_ref().unwrap();
+        s  //~ ERROR E0312
+    }
+}
+
+pub fn opt_str3<'a>(maybestr: &'a Option<String>) -> &'static str {
+    if maybestr.is_some() {
+        let s: &'a str = maybestr.as_ref().unwrap();
+        s  //~ ERROR E0312
+    } else {
+        "(none)"
+    }
+}
+
+
+fn main() {}
diff --git a/src/test/ui/lub-if.stderr b/src/test/ui/lub-if.stderr
new file mode 100644
index 0000000..26f756c
--- /dev/null
+++ b/src/test/ui/lub-if.stderr
@@ -0,0 +1,29 @@
+error[E0312]: lifetime of reference outlives lifetime of borrowed content...
+  --> $DIR/lub-if.rs:28:9
+   |
+LL |         s
+   |         ^
+   |
+   = note: ...the reference is valid for the static lifetime...
+note: ...but the borrowed content is only valid for the lifetime 'a as defined on the function body at 23:17
+  --> $DIR/lub-if.rs:23:17
+   |
+LL | pub fn opt_str2<'a>(maybestr: &'a Option<String>) -> &'static str {
+   |                 ^^
+
+error[E0312]: lifetime of reference outlives lifetime of borrowed content...
+  --> $DIR/lub-if.rs:35:9
+   |
+LL |         s
+   |         ^
+   |
+   = note: ...the reference is valid for the static lifetime...
+note: ...but the borrowed content is only valid for the lifetime 'a as defined on the function body at 32:17
+  --> $DIR/lub-if.rs:32:17
+   |
+LL | pub fn opt_str3<'a>(maybestr: &'a Option<String>) -> &'static str {
+   |                 ^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0312`.
diff --git a/src/test/ui/lub-match.rs b/src/test/ui/lub-match.rs
new file mode 100644
index 0000000..1cd4a02
--- /dev/null
+++ b/src/test/ui/lub-match.rs
@@ -0,0 +1,45 @@
+// Test that we correctly consider the type of `match` to be the LUB
+// of the various arms, particularly in the case where regions are
+// involved.
+
+pub fn opt_str0<'a>(maybestr: &'a Option<String>) -> &'a str {
+    match *maybestr {
+        Some(ref s) => {
+            let s: &'a str = s;
+            s
+        }
+        None => "(none)",
+    }
+}
+
+pub fn opt_str1<'a>(maybestr: &'a Option<String>) -> &'a str {
+    match *maybestr {
+        None => "(none)",
+        Some(ref s) => {
+            let s: &'a str = s;
+            s
+        }
+    }
+}
+
+pub fn opt_str2<'a>(maybestr: &'a Option<String>) -> &'static str {
+    match *maybestr {
+        None => "(none)",
+        Some(ref s) => {
+            let s: &'a str = s;
+            s //~ ERROR E0312
+        }
+    }
+}
+
+pub fn opt_str3<'a>(maybestr: &'a Option<String>) -> &'static str {
+    match *maybestr {
+        Some(ref s) => {
+            let s: &'a str = s;
+            s //~ ERROR E0312
+        }
+        None => "(none)",
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/lub-match.stderr b/src/test/ui/lub-match.stderr
new file mode 100644
index 0000000..0cb0a23
--- /dev/null
+++ b/src/test/ui/lub-match.stderr
@@ -0,0 +1,29 @@
+error[E0312]: lifetime of reference outlives lifetime of borrowed content...
+  --> $DIR/lub-match.rs:30:13
+   |
+LL |             s
+   |             ^
+   |
+   = note: ...the reference is valid for the static lifetime...
+note: ...but the borrowed content is only valid for the lifetime 'a as defined on the function body at 25:17
+  --> $DIR/lub-match.rs:25:17
+   |
+LL | pub fn opt_str2<'a>(maybestr: &'a Option<String>) -> &'static str {
+   |                 ^^
+
+error[E0312]: lifetime of reference outlives lifetime of borrowed content...
+  --> $DIR/lub-match.rs:39:13
+   |
+LL |             s
+   |             ^
+   |
+   = note: ...the reference is valid for the static lifetime...
+note: ...but the borrowed content is only valid for the lifetime 'a as defined on the function body at 35:17
+  --> $DIR/lub-match.rs:35:17
+   |
+LL | pub fn opt_str3<'a>(maybestr: &'a Option<String>) -> &'static str {
+   |                 ^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0312`.
diff --git a/src/test/ui/macro_backtrace/auxiliary/ping.rs b/src/test/ui/macro_backtrace/auxiliary/ping.rs
new file mode 100644
index 0000000..efddb20
--- /dev/null
+++ b/src/test/ui/macro_backtrace/auxiliary/ping.rs
@@ -0,0 +1,31 @@
+// Test that the macro backtrace facility works (supporting file)
+
+// a non-local macro
+#[macro_export]
+macro_rules! ping {
+    () => {
+        pong!();
+    }
+}
+
+#[macro_export]
+macro_rules! deep {
+    () => {
+        foo!();
+    }
+}
+
+#[macro_export]
+macro_rules! foo {
+    () => {
+        bar!();
+    }
+}
+
+#[macro_export]
+macro_rules! bar {
+    () => {
+        ping!();
+    }
+}
+
diff --git a/src/test/ui/macro_backtrace/main.rs b/src/test/ui/macro_backtrace/main.rs
new file mode 100644
index 0000000..8fcd497
--- /dev/null
+++ b/src/test/ui/macro_backtrace/main.rs
@@ -0,0 +1,22 @@
+// Test that the macro backtrace facility works
+// aux-build:ping.rs
+// compile-flags: -Z external-macro-backtrace
+
+#[macro_use] extern crate ping;
+
+// a local macro
+macro_rules! pong {
+    () => { syntax error };
+}
+//~^^ ERROR expected one of
+//~| ERROR expected one of
+//~| ERROR expected one of
+
+#[allow(non_camel_case_types)]
+struct syntax;
+
+fn main() {
+    pong!();
+    ping!();
+    deep!();
+}
diff --git a/src/test/ui/macro_backtrace/main.stderr b/src/test/ui/macro_backtrace/main.stderr
new file mode 100644
index 0000000..239b53f
--- /dev/null
+++ b/src/test/ui/macro_backtrace/main.stderr
@@ -0,0 +1,78 @@
+error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `error`
+  --> $DIR/main.rs:9:20
+   |
+LL | / macro_rules! pong {
+LL | |     () => { syntax error };
+   | |                    ^^^^^ expected one of 8 possible tokens here
+LL | | }
+   | |_- in this expansion of `pong!`
+...
+LL |       pong!();
+   |       -------- in this macro invocation
+
+error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `error`
+  --> $DIR/main.rs:9:20
+   |
+LL | / macro_rules! pong {
+LL | |     () => { syntax error };
+   | |                    ^^^^^ expected one of 8 possible tokens here
+LL | | }
+   | |_- in this expansion of `pong!`
+...
+LL |       ping!();
+   |       -------- in this macro invocation
+   | 
+  ::: <::ping::ping macros>:1:1
+   |
+LL |   (  ) => { pong ! (  ) ; }
+   |   -------------------------
+   |   |         |
+   |   |         in this macro invocation
+   |   in this expansion of `ping!`
+
+error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `error`
+  --> $DIR/main.rs:9:20
+   |
+LL | / macro_rules! pong {
+LL | |     () => { syntax error };
+   | |                    ^^^^^ expected one of 8 possible tokens here
+LL | | }
+   | |_- in this expansion of `pong!` (#5)
+...
+LL |       deep!();
+   |       -------- in this macro invocation (#1)
+   | 
+  ::: <::ping::deep macros>:1:1
+   |
+LL |   (  ) => { foo ! (  ) ; }
+   |   ------------------------
+   |   |         |
+   |   |         in this macro invocation (#2)
+   |   in this expansion of `deep!` (#1)
+   | 
+  ::: <::ping::foo macros>:1:1
+   |
+LL |   (  ) => { bar ! (  ) ; }
+   |   ------------------------
+   |   |         |
+   |   |         in this macro invocation (#3)
+   |   in this expansion of `foo!` (#2)
+   | 
+  ::: <::ping::bar macros>:1:1
+   |
+LL |   (  ) => { ping ! (  ) ; }
+   |   -------------------------
+   |   |         |
+   |   |         in this macro invocation (#4)
+   |   in this expansion of `bar!` (#3)
+   | 
+  ::: <::ping::ping macros>:1:1
+   |
+LL |   (  ) => { pong ! (  ) ; }
+   |   -------------------------
+   |   |         |
+   |   |         in this macro invocation (#5)
+   |   in this expansion of `ping!` (#4)
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/macros/ambiguity-legacy-vs-modern.rs b/src/test/ui/macros/ambiguity-legacy-vs-modern.rs
new file mode 100644
index 0000000..216b9dd
--- /dev/null
+++ b/src/test/ui/macros/ambiguity-legacy-vs-modern.rs
@@ -0,0 +1,46 @@
+// Some non-controversial subset of ambiguities "modern macro name" vs "macro_rules"
+// is disambiguated to mitigate regressions from macro modularization.
+// Scoping for `macro_rules` behaves like scoping for `let` at module level, in general.
+
+#![feature(decl_macro)]
+
+fn same_unnamed_mod() {
+    macro m() { 0 }
+
+    macro_rules! m { () => (()) }
+
+    m!() // OK
+}
+
+fn nested_unnamed_mod() {
+    macro m() { 0 }
+
+    {
+        macro_rules! m { () => (()) }
+
+        m!() // OK
+    }
+}
+
+fn nested_unnamed_mod_fail() {
+    macro_rules! m { () => (()) }
+
+    {
+        macro m() { 0 }
+
+        m!() //~ ERROR `m` is ambiguous
+    }
+}
+
+fn nexted_named_mod_fail() {
+    macro m() { 0 }
+
+    #[macro_use]
+    mod inner {
+        macro_rules! m { () => (()) }
+    }
+
+    m!() //~ ERROR `m` is ambiguous
+}
+
+fn main() {}
diff --git a/src/test/ui/macros/ambiguity-legacy-vs-modern.stderr b/src/test/ui/macros/ambiguity-legacy-vs-modern.stderr
new file mode 100644
index 0000000..d9a0a9f
--- /dev/null
+++ b/src/test/ui/macros/ambiguity-legacy-vs-modern.stderr
@@ -0,0 +1,37 @@
+error[E0659]: `m` is ambiguous (`macro_rules` vs non-`macro_rules` from other module)
+  --> $DIR/ambiguity-legacy-vs-modern.rs:31:9
+   |
+LL |         m!()
+   |         ^ ambiguous name
+   |
+note: `m` could refer to the macro defined here
+  --> $DIR/ambiguity-legacy-vs-modern.rs:26:5
+   |
+LL |     macro_rules! m { () => (()) }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: `m` could also refer to the macro defined here
+  --> $DIR/ambiguity-legacy-vs-modern.rs:29:9
+   |
+LL |         macro m() { 0 }
+   |         ^^^^^^^^^^^^^^^
+
+error[E0659]: `m` is ambiguous (`macro_rules` vs non-`macro_rules` from other module)
+  --> $DIR/ambiguity-legacy-vs-modern.rs:43:5
+   |
+LL |     m!()
+   |     ^ ambiguous name
+   |
+note: `m` could refer to the macro defined here
+  --> $DIR/ambiguity-legacy-vs-modern.rs:40:9
+   |
+LL |         macro_rules! m { () => (()) }
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: `m` could also refer to the macro defined here
+  --> $DIR/ambiguity-legacy-vs-modern.rs:36:5
+   |
+LL |     macro m() { 0 }
+   |     ^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0659`.
diff --git a/src/test/ui/macros/assert.rs b/src/test/ui/macros/assert.rs
new file mode 100644
index 0000000..71b0dbb
--- /dev/null
+++ b/src/test/ui/macros/assert.rs
@@ -0,0 +1,6 @@
+fn main() {
+    assert!();  //~ ERROR requires a boolean expression
+    assert!(struct); //~ ERROR expected expression
+    debug_assert!(); //~ ERROR requires a boolean expression
+    debug_assert!(struct); //~ ERROR expected expression
+}
diff --git a/src/test/ui/macros/assert.stderr b/src/test/ui/macros/assert.stderr
new file mode 100644
index 0000000..fa60450
--- /dev/null
+++ b/src/test/ui/macros/assert.stderr
@@ -0,0 +1,28 @@
+error: macro requires a boolean expression as an argument
+  --> $DIR/assert.rs:2:5
+   |
+LL |     assert!();
+   |     ^^^^^^^^^^ boolean expression required
+
+error: expected expression, found keyword `struct`
+  --> $DIR/assert.rs:3:13
+   |
+LL |     assert!(struct);
+   |             ^^^^^^ expected expression
+
+error: macro requires a boolean expression as an argument
+  --> $DIR/assert.rs:4:5
+   |
+LL |     debug_assert!();
+   |     ^^^^^^^^^^^^^^^^ boolean expression required
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: expected expression, found keyword `struct`
+  --> $DIR/assert.rs:5:19
+   |
+LL |     debug_assert!(struct);
+   |                   ^^^^^^ expected expression
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/macros/auxiliary/macro-in-other-crate.rs b/src/test/ui/macros/auxiliary/macro-in-other-crate.rs
new file mode 100644
index 0000000..db8e920
--- /dev/null
+++ b/src/test/ui/macros/auxiliary/macro-in-other-crate.rs
@@ -0,0 +1,14 @@
+#[macro_export]
+macro_rules! mac {
+    ($ident:ident) => { let $ident = 42; }
+}
+
+#[macro_export]
+macro_rules! inline {
+    () => ()
+}
+
+#[macro_export]
+macro_rules! from_prelude {
+    () => ()
+}
diff --git a/src/test/ui/macros/auxiliary/macro_crate_nonterminal.rs b/src/test/ui/macros/auxiliary/macro_crate_nonterminal.rs
new file mode 100644
index 0000000..2e24404
--- /dev/null
+++ b/src/test/ui/macros/auxiliary/macro_crate_nonterminal.rs
@@ -0,0 +1,12 @@
+pub fn increment(x: usize) -> usize {
+    x + 1
+}
+
+#[macro_export]
+macro_rules! increment {
+    ($x:expr) => ($crate::increment($x))
+}
+
+pub fn check_local() {
+    assert_eq!(increment!(3), 4);
+}
diff --git a/src/test/ui/macros/auxiliary/two_macros.rs b/src/test/ui/macros/auxiliary/two_macros.rs
new file mode 100644
index 0000000..2330c75
--- /dev/null
+++ b/src/test/ui/macros/auxiliary/two_macros.rs
@@ -0,0 +1,5 @@
+#[macro_export]
+macro_rules! macro_one { () => ("one") }
+
+#[macro_export]
+macro_rules! macro_two { () => ("two") }
diff --git a/src/test/ui/macros/auxiliary/unstable-macros.rs b/src/test/ui/macros/auxiliary/unstable-macros.rs
new file mode 100644
index 0000000..b8d5807
--- /dev/null
+++ b/src/test/ui/macros/auxiliary/unstable-macros.rs
@@ -0,0 +1,6 @@
+#![feature(staged_api)]
+#![stable(feature = "unit_test", since = "1.0.0")]
+
+#[unstable(feature = "unstable_macros", issue = "0")]
+#[macro_export]
+macro_rules! unstable_macro{ () => () }
diff --git a/src/test/ui/macros/bad-concat.rs b/src/test/ui/macros/bad-concat.rs
new file mode 100644
index 0000000..263cd07
--- /dev/null
+++ b/src/test/ui/macros/bad-concat.rs
@@ -0,0 +1,8 @@
+fn main() {
+    let x: u32 = 42;
+    let y: f64 = 3.14;
+    let z = "foo";
+    let _ = concat!(x, y, z, "bar");
+    //~^ ERROR expected a literal
+    //~| NOTE only literals
+}
diff --git a/src/test/ui/macros/bad-concat.stderr b/src/test/ui/macros/bad-concat.stderr
new file mode 100644
index 0000000..4316fd3
--- /dev/null
+++ b/src/test/ui/macros/bad-concat.stderr
@@ -0,0 +1,10 @@
+error: expected a literal
+  --> $DIR/bad-concat.rs:5:21
+   |
+LL |     let _ = concat!(x, y, z, "bar");
+   |                     ^  ^  ^
+   |
+   = note: only literals (like `"foo"`, `42` and `3.14`) can be passed to `concat!()`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/macros/bad_hello.rs b/src/test/ui/macros/bad_hello.rs
new file mode 100644
index 0000000..aaa9e24
--- /dev/null
+++ b/src/test/ui/macros/bad_hello.rs
@@ -0,0 +1,6 @@
+fn main() {
+    println!(3 + 4);
+    //~^ ERROR format argument must be a string literal
+    println!(3, 4);
+    //~^ ERROR format argument must be a string literal
+}
diff --git a/src/test/ui/macros/bad_hello.stderr b/src/test/ui/macros/bad_hello.stderr
new file mode 100644
index 0000000..ab3cbf0
--- /dev/null
+++ b/src/test/ui/macros/bad_hello.stderr
@@ -0,0 +1,22 @@
+error: format argument must be a string literal
+  --> $DIR/bad_hello.rs:2:14
+   |
+LL |     println!(3 + 4);
+   |              ^^^^^
+help: you might be missing a string literal to format with
+   |
+LL |     println!("{}", 3 + 4);
+   |              ^^^^^
+
+error: format argument must be a string literal
+  --> $DIR/bad_hello.rs:4:14
+   |
+LL |     println!(3, 4);
+   |              ^
+help: you might be missing a string literal to format with
+   |
+LL |     println!("{} {}", 3, 4);
+   |              ^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/macros/cfg.rs b/src/test/ui/macros/cfg.rs
new file mode 100644
index 0000000..222161a
--- /dev/null
+++ b/src/test/ui/macros/cfg.rs
@@ -0,0 +1,5 @@
+fn main() {
+    cfg!(); //~ ERROR macro requires a cfg-pattern
+    cfg!(123); //~ ERROR expected identifier
+    cfg!(foo = 123); //~ ERROR literal in `cfg` predicate value must be a string
+}
diff --git a/src/test/ui/macros/cfg.stderr b/src/test/ui/macros/cfg.stderr
new file mode 100644
index 0000000..0fdb629
--- /dev/null
+++ b/src/test/ui/macros/cfg.stderr
@@ -0,0 +1,21 @@
+error: macro requires a cfg-pattern as an argument
+  --> $DIR/cfg.rs:2:5
+   |
+LL |     cfg!();
+   |     ^^^^^^^ cfg-pattern required
+
+error: expected identifier, found `123`
+  --> $DIR/cfg.rs:3:10
+   |
+LL |     cfg!(123);
+   |          ^^^ expected identifier
+
+error[E0565]: literal in `cfg` predicate value must be a string
+  --> $DIR/cfg.rs:4:16
+   |
+LL |     cfg!(foo = 123);
+   |                ^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0565`.
diff --git a/src/test/ui/macros/format-foreign.rs b/src/test/ui/macros/format-foreign.rs
new file mode 100644
index 0000000..ac65838
--- /dev/null
+++ b/src/test/ui/macros/format-foreign.rs
@@ -0,0 +1,17 @@
+fn main() {
+    println!("%.*3$s %s!\n", "Hello,", "World", 4); //~ ERROR multiple unused formatting arguments
+    println!("%1$*2$.*3$f", 123.456); //~ ERROR never used
+    println!(r###"%.*3$s
+        %s!\n
+"###, "Hello,", "World", 4);
+    //~^ ERROR multiple unused formatting arguments
+    // correctly account for raw strings in inline suggestions
+
+    // This should *not* produce hints, on the basis that there's equally as
+    // many "correct" format specifiers.  It's *probably* just an actual typo.
+    println!("{} %f", "one", 2.0); //~ ERROR never used
+
+    println!("Hi there, $NAME.", NAME="Tim"); //~ ERROR never used
+    println!("$1 $0 $$ $NAME", 1, 2, NAME=3);
+    //~^ ERROR multiple unused formatting arguments
+}
diff --git a/src/test/ui/macros/format-foreign.stderr b/src/test/ui/macros/format-foreign.stderr
new file mode 100644
index 0000000..e2f2f14
--- /dev/null
+++ b/src/test/ui/macros/format-foreign.stderr
@@ -0,0 +1,82 @@
+error: multiple unused formatting arguments
+  --> $DIR/format-foreign.rs:2:30
+   |
+LL |     println!("%.*3$s %s!\n", "Hello,", "World", 4);
+   |              --------------  ^^^^^^^^  ^^^^^^^  ^ argument never used
+   |              |               |         |
+   |              |               |         argument never used
+   |              |               argument never used
+   |              multiple missing formatting specifiers
+   |
+   = note: printf formatting not supported; see the documentation for `std::fmt`
+help: format specifiers use curly braces
+   |
+LL |     println!("{:.2$} {}!\n", "Hello,", "World", 4);
+   |               ^^^^^^ ^^
+
+error: argument never used
+  --> $DIR/format-foreign.rs:3:29
+   |
+LL |     println!("%1$*2$.*3$f", 123.456);
+   |               -----------   ^^^^^^^ argument never used
+   |               |
+   |               help: format specifiers use curly braces: `{0:1$.2$}`
+   |
+   = note: printf formatting not supported; see the documentation for `std::fmt`
+
+error: multiple unused formatting arguments
+  --> $DIR/format-foreign.rs:6:7
+   |
+LL |       println!(r###"%.*3$s
+   |  ______________-
+LL | |         %s!\n
+LL | | "###, "Hello,", "World", 4);
+   | |    -  ^^^^^^^^  ^^^^^^^  ^ argument never used
+   | |    |  |         |
+   | |    |  |         argument never used
+   | |____|  argument never used
+   |      multiple missing formatting specifiers
+   |
+   = note: printf formatting not supported; see the documentation for `std::fmt`
+help: format specifiers use curly braces
+   |
+LL |     println!(r###"{:.2$}
+LL |         {}!\n
+   |
+
+error: argument never used
+  --> $DIR/format-foreign.rs:12:30
+   |
+LL |     println!("{} %f", "one", 2.0);
+   |              -------         ^^^ argument never used
+   |              |
+   |              formatting specifier missing
+
+error: named argument never used
+  --> $DIR/format-foreign.rs:14:39
+   |
+LL |     println!("Hi there, $NAME.", NAME="Tim");
+   |                         -----         ^^^^^ named argument never used
+   |                         |
+   |                         help: format specifiers use curly braces: `{NAME}`
+   |
+   = note: shell formatting not supported; see the documentation for `std::fmt`
+
+error: multiple unused formatting arguments
+  --> $DIR/format-foreign.rs:15:32
+   |
+LL |     println!("$1 $0 $$ $NAME", 1, 2, NAME=3);
+   |              ----------------  ^  ^       ^ named argument never used
+   |              |                 |  |
+   |              |                 |  argument never used
+   |              |                 argument never used
+   |              multiple missing formatting specifiers
+   |
+   = note: shell formatting not supported; see the documentation for `std::fmt`
+help: format specifiers use curly braces
+   |
+LL |     println!("{1} {0} $$ {NAME}", 1, 2, NAME=3);
+   |               ^^^ ^^^    ^^^^^^
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/macros/format-parse-errors.rs b/src/test/ui/macros/format-parse-errors.rs
new file mode 100644
index 0000000..96aee5e6
--- /dev/null
+++ b/src/test/ui/macros/format-parse-errors.rs
@@ -0,0 +1,11 @@
+fn main() {
+    format!(); //~ ERROR requires at least a format string argument
+    format!(struct); //~ ERROR expected expression
+    format!("s", name =); //~ ERROR expected expression
+    format!("s", foo = foo, bar); //~ ERROR expected `=`
+    format!("s", foo = struct); //~ ERROR expected expression
+    format!("s", struct); //~ ERROR expected expression
+
+    // This error should come after parsing errors to ensure they are non-fatal.
+    format!(123); //~ ERROR format argument must be a string literal
+}
diff --git a/src/test/ui/macros/format-parse-errors.stderr b/src/test/ui/macros/format-parse-errors.stderr
new file mode 100644
index 0000000..b634cf2
--- /dev/null
+++ b/src/test/ui/macros/format-parse-errors.stderr
@@ -0,0 +1,50 @@
+error: requires at least a format string argument
+  --> $DIR/format-parse-errors.rs:2:5
+   |
+LL |     format!();
+   |     ^^^^^^^^^^
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: expected expression, found keyword `struct`
+  --> $DIR/format-parse-errors.rs:3:13
+   |
+LL |     format!(struct);
+   |             ^^^^^^ expected expression
+
+error: expected expression, found `<eof>`
+  --> $DIR/format-parse-errors.rs:4:23
+   |
+LL |     format!("s", name =);
+   |                       ^ expected expression
+
+error: expected `=`, found `<eof>`
+  --> $DIR/format-parse-errors.rs:5:29
+   |
+LL |     format!("s", foo = foo, bar);
+   |                             ^^^ expected `=`
+
+error: expected expression, found keyword `struct`
+  --> $DIR/format-parse-errors.rs:6:24
+   |
+LL |     format!("s", foo = struct);
+   |                        ^^^^^^ expected expression
+
+error: expected expression, found keyword `struct`
+  --> $DIR/format-parse-errors.rs:7:18
+   |
+LL |     format!("s", struct);
+   |                  ^^^^^^ expected expression
+
+error: format argument must be a string literal
+  --> $DIR/format-parse-errors.rs:10:13
+   |
+LL |     format!(123);
+   |             ^^^
+help: you might be missing a string literal to format with
+   |
+LL |     format!("{}", 123);
+   |             ^^^^^
+
+error: aborting due to 7 previous errors
+
diff --git a/src/test/ui/macros/format-unused-lables.rs b/src/test/ui/macros/format-unused-lables.rs
new file mode 100644
index 0000000..56382b1
--- /dev/null
+++ b/src/test/ui/macros/format-unused-lables.rs
@@ -0,0 +1,18 @@
+fn main() {
+    println!("Test", 123, 456, 789);
+    //~^ ERROR multiple unused formatting arguments
+
+    println!("Test2",
+        123,  //~ ERROR multiple unused formatting arguments
+        456,
+        789
+    );
+
+    println!("Some stuff", UNUSED="args"); //~ ERROR named argument never used
+
+    println!("Some more $STUFF",
+        "woo!",  //~ ERROR multiple unused formatting arguments
+            STUFF=
+       "things"
+             , UNUSED="args");
+}
diff --git a/src/test/ui/macros/format-unused-lables.stderr b/src/test/ui/macros/format-unused-lables.stderr
new file mode 100644
index 0000000..7423c7b
--- /dev/null
+++ b/src/test/ui/macros/format-unused-lables.stderr
@@ -0,0 +1,50 @@
+error: multiple unused formatting arguments
+  --> $DIR/format-unused-lables.rs:2:22
+   |
+LL |     println!("Test", 123, 456, 789);
+   |              ------  ^^^  ^^^  ^^^ argument never used
+   |              |       |    |
+   |              |       |    argument never used
+   |              |       argument never used
+   |              multiple missing formatting specifiers
+
+error: multiple unused formatting arguments
+  --> $DIR/format-unused-lables.rs:6:9
+   |
+LL |     println!("Test2",
+   |              ------- multiple missing formatting specifiers
+LL |         123,
+   |         ^^^ argument never used
+LL |         456,
+   |         ^^^ argument never used
+LL |         789
+   |         ^^^ argument never used
+
+error: named argument never used
+  --> $DIR/format-unused-lables.rs:11:35
+   |
+LL |     println!("Some stuff", UNUSED="args");
+   |              ------------         ^^^^^^ named argument never used
+   |              |
+   |              formatting specifier missing
+
+error: multiple unused formatting arguments
+  --> $DIR/format-unused-lables.rs:14:9
+   |
+LL |     println!("Some more $STUFF",
+   |              ------------------
+   |              |          |
+   |              |          help: format specifiers use curly braces: `{STUFF}`
+   |              multiple missing formatting specifiers
+LL |         "woo!",
+   |         ^^^^^^ argument never used
+LL |             STUFF=
+LL |        "things"
+   |        ^^^^^^^^ named argument never used
+LL |              , UNUSED="args");
+   |                       ^^^^^^ named argument never used
+   |
+   = note: shell formatting not supported; see the documentation for `std::fmt`
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/macros/global-asm.rs b/src/test/ui/macros/global-asm.rs
new file mode 100644
index 0000000..8402afa
--- /dev/null
+++ b/src/test/ui/macros/global-asm.rs
@@ -0,0 +1,7 @@
+#![feature(global_asm)]
+
+fn main() {
+    global_asm!();  //~ ERROR requires a string literal as an argument
+    global_asm!(struct); //~ ERROR expected expression
+    global_asm!(123); //~ ERROR inline assembly must be a string literal
+}
diff --git a/src/test/ui/macros/global-asm.stderr b/src/test/ui/macros/global-asm.stderr
new file mode 100644
index 0000000..c43bf83
--- /dev/null
+++ b/src/test/ui/macros/global-asm.stderr
@@ -0,0 +1,20 @@
+error: macro requires a string literal as an argument
+  --> $DIR/global-asm.rs:4:5
+   |
+LL |     global_asm!();
+   |     ^^^^^^^^^^^^^^ string literal required
+
+error: expected expression, found keyword `struct`
+  --> $DIR/global-asm.rs:5:17
+   |
+LL |     global_asm!(struct);
+   |                 ^^^^^^ expected expression
+
+error: inline assembly must be a string literal
+  --> $DIR/global-asm.rs:6:17
+   |
+LL |     global_asm!(123);
+   |                 ^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/macros/issue-30143.rs b/src/test/ui/macros/issue-30143.rs
new file mode 100644
index 0000000..ac4c1da5
--- /dev/null
+++ b/src/test/ui/macros/issue-30143.rs
@@ -0,0 +1,11 @@
+use std::fmt::Write;
+
+fn main() {
+    println!(0);
+    //~^ ERROR format argument must be a string literal
+    eprintln!('a');
+    //~^ ERROR format argument must be a string literal
+    let mut s = String::new();
+    writeln!(s, true).unwrap();
+    //~^ ERROR format argument must be a string literal
+}
diff --git a/src/test/ui/macros/issue-30143.stderr b/src/test/ui/macros/issue-30143.stderr
new file mode 100644
index 0000000..f0c604a
--- /dev/null
+++ b/src/test/ui/macros/issue-30143.stderr
@@ -0,0 +1,32 @@
+error: format argument must be a string literal
+  --> $DIR/issue-30143.rs:4:14
+   |
+LL |     println!(0);
+   |              ^
+help: you might be missing a string literal to format with
+   |
+LL |     println!("{}", 0);
+   |              ^^^^^
+
+error: format argument must be a string literal
+  --> $DIR/issue-30143.rs:6:15
+   |
+LL |     eprintln!('a');
+   |               ^^^
+help: you might be missing a string literal to format with
+   |
+LL |     eprintln!("{}", 'a');
+   |               ^^^^^
+
+error: format argument must be a string literal
+  --> $DIR/issue-30143.rs:9:17
+   |
+LL |     writeln!(s, true).unwrap();
+   |                 ^^^^
+help: you might be missing a string literal to format with
+   |
+LL |     writeln!(s, "{}", true).unwrap();
+   |                 ^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/macros/issue-54441.rs b/src/test/ui/macros/issue-54441.rs
new file mode 100644
index 0000000..b45aedb
--- /dev/null
+++ b/src/test/ui/macros/issue-54441.rs
@@ -0,0 +1,13 @@
+#![feature(macros_in_extern)]
+
+macro_rules! m {
+    () => {
+        let //~ ERROR expected
+    };
+}
+
+extern "C" {
+    m!();
+}
+
+fn main() {}
diff --git a/src/test/ui/macros/issue-54441.stderr b/src/test/ui/macros/issue-54441.stderr
new file mode 100644
index 0000000..b0fafdc
--- /dev/null
+++ b/src/test/ui/macros/issue-54441.stderr
@@ -0,0 +1,11 @@
+error: expected one of `crate`, `fn`, `pub`, `static`, or `type`, found `let`
+  --> $DIR/issue-54441.rs:5:9
+   |
+LL |         let
+   |         ^^^ unexpected token
+...
+LL |     m!();
+   |     ----- in this macro invocation
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/macros/macro-at-most-once-rep-2015-ques-rep.rs b/src/test/ui/macros/macro-at-most-once-rep-2015-ques-rep.rs
new file mode 100644
index 0000000..2d8d2ec
--- /dev/null
+++ b/src/test/ui/macros/macro-at-most-once-rep-2015-ques-rep.rs
@@ -0,0 +1,13 @@
+// Test behavior of `?` macro _kleene op_ under the 2015 edition. Namely, it doesn't exist.
+
+// edition:2015
+
+macro_rules! bar {
+    ($(a)?) => {} //~ERROR expected `*` or `+`
+}
+
+macro_rules! baz {
+    ($(a),?) => {} //~ERROR expected `*` or `+`
+}
+
+fn main() {}
diff --git a/src/test/ui/macros/macro-at-most-once-rep-2015-ques-rep.stderr b/src/test/ui/macros/macro-at-most-once-rep-2015-ques-rep.stderr
new file mode 100644
index 0000000..e78f283
--- /dev/null
+++ b/src/test/ui/macros/macro-at-most-once-rep-2015-ques-rep.stderr
@@ -0,0 +1,18 @@
+error: expected `*` or `+`
+  --> $DIR/macro-at-most-once-rep-2015-ques-rep.rs:6:10
+   |
+LL |     ($(a)?) => {}
+   |          ^
+   |
+   = note: `?` is not a macro repetition operator in the 2015 edition, but is accepted in the 2018 edition
+
+error: expected `*` or `+`
+  --> $DIR/macro-at-most-once-rep-2015-ques-rep.rs:10:11
+   |
+LL |     ($(a),?) => {}
+   |           ^
+   |
+   = note: `?` is not a macro repetition operator in the 2015 edition, but is accepted in the 2018 edition
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/macros/macro-at-most-once-rep-2015-ques-sep.rs b/src/test/ui/macros/macro-at-most-once-rep-2015-ques-sep.rs
new file mode 100644
index 0000000..c8c920f
--- /dev/null
+++ b/src/test/ui/macros/macro-at-most-once-rep-2015-ques-sep.rs
@@ -0,0 +1,28 @@
+// Test behavior of `?` macro _separator_ under the 2015 edition. Namely, `?` can be used as a
+// separator, but you get a migration warning for the edition.
+
+// edition:2015
+// compile-pass
+
+#![warn(rust_2018_compatibility)]
+
+macro_rules! bar {
+    ($(a)?*) => {} //~WARN using `?` as a separator
+    //~^WARN this was previously accepted
+}
+
+macro_rules! baz {
+    ($(a)?+) => {} //~WARN using `?` as a separator
+    //~^WARN this was previously accepted
+}
+
+fn main() {
+    bar!();
+    bar!(a);
+    bar!(a?a);
+    bar!(a?a?a?a?a);
+
+    baz!(a);
+    baz!(a?a);
+    baz!(a?a?a?a?a);
+}
diff --git a/src/test/ui/macros/macro-at-most-once-rep-2015-ques-sep.stderr b/src/test/ui/macros/macro-at-most-once-rep-2015-ques-sep.stderr
new file mode 100644
index 0000000..bf1861a
--- /dev/null
+++ b/src/test/ui/macros/macro-at-most-once-rep-2015-ques-sep.stderr
@@ -0,0 +1,24 @@
+warning: using `?` as a separator is deprecated and will be a hard error in an upcoming edition
+  --> $DIR/macro-at-most-once-rep-2015-ques-sep.rs:10:10
+   |
+LL |     ($(a)?*) => {}
+   |          ^
+   |
+note: lint level defined here
+  --> $DIR/macro-at-most-once-rep-2015-ques-sep.rs:7:9
+   |
+LL | #![warn(rust_2018_compatibility)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+   = note: #[warn(question_mark_macro_sep)] implied by #[warn(rust_2018_compatibility)]
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #48075 <https://github.com/rust-lang/rust/issues/48075>
+
+warning: using `?` as a separator is deprecated and will be a hard error in an upcoming edition
+  --> $DIR/macro-at-most-once-rep-2015-ques-sep.rs:15:10
+   |
+LL |     ($(a)?+) => {}
+   |          ^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #48075 <https://github.com/rust-lang/rust/issues/48075>
+
diff --git a/src/test/ui/macros/macro-at-most-once-rep-2018.rs b/src/test/ui/macros/macro-at-most-once-rep-2018.rs
new file mode 100644
index 0000000..da072ad
--- /dev/null
+++ b/src/test/ui/macros/macro-at-most-once-rep-2018.rs
@@ -0,0 +1,41 @@
+// Tests that `?` is a Kleene op and not a macro separator in the 2018 edition.
+
+// edition:2018
+
+macro_rules! foo {
+    ($(a)?) => {};
+}
+
+macro_rules! baz {
+    ($(a),?) => {}; //~ERROR the `?` macro repetition operator
+}
+
+macro_rules! barplus {
+    ($(a)?+) => {}; // ok. matches "a+" and "+"
+}
+
+macro_rules! barstar {
+    ($(a)?*) => {}; // ok. matches "a*" and "*"
+}
+
+pub fn main() {
+    foo!();
+    foo!(a);
+    foo!(a?); //~ ERROR no rules expected the token `?`
+    foo!(a?a); //~ ERROR no rules expected the token `?`
+    foo!(a?a?a); //~ ERROR no rules expected the token `?`
+
+    barplus!(); //~ERROR unexpected end of macro invocation
+    barplus!(a); //~ERROR unexpected end of macro invocation
+    barplus!(a?); //~ ERROR no rules expected the token `?`
+    barplus!(a?a); //~ ERROR no rules expected the token `?`
+    barplus!(a+);
+    barplus!(+);
+
+    barstar!(); //~ERROR unexpected end of macro invocation
+    barstar!(a); //~ERROR unexpected end of macro invocation
+    barstar!(a?); //~ ERROR no rules expected the token `?`
+    barstar!(a?a); //~ ERROR no rules expected the token `?`
+    barstar!(a*);
+    barstar!(*);
+}
diff --git a/src/test/ui/macros/macro-at-most-once-rep-2018.stderr b/src/test/ui/macros/macro-at-most-once-rep-2018.stderr
new file mode 100644
index 0000000..f285c7c
--- /dev/null
+++ b/src/test/ui/macros/macro-at-most-once-rep-2018.stderr
@@ -0,0 +1,107 @@
+error: the `?` macro repetition operator does not take a separator
+  --> $DIR/macro-at-most-once-rep-2018.rs:10:10
+   |
+LL |     ($(a),?) => {};
+   |          ^
+
+error: no rules expected the token `?`
+  --> $DIR/macro-at-most-once-rep-2018.rs:24:11
+   |
+LL | macro_rules! foo {
+   | ---------------- when calling this macro
+...
+LL |     foo!(a?);
+   |           ^ no rules expected this token in macro call
+
+error: no rules expected the token `?`
+  --> $DIR/macro-at-most-once-rep-2018.rs:25:11
+   |
+LL | macro_rules! foo {
+   | ---------------- when calling this macro
+...
+LL |     foo!(a?a);
+   |           ^ no rules expected this token in macro call
+
+error: no rules expected the token `?`
+  --> $DIR/macro-at-most-once-rep-2018.rs:26:11
+   |
+LL | macro_rules! foo {
+   | ---------------- when calling this macro
+...
+LL |     foo!(a?a?a);
+   |           ^ no rules expected this token in macro call
+
+error: unexpected end of macro invocation
+  --> $DIR/macro-at-most-once-rep-2018.rs:28:5
+   |
+LL | macro_rules! barplus {
+   | -------------------- when calling this macro
+...
+LL |     barplus!();
+   |     ^^^^^^^^^^^ missing tokens in macro arguments
+
+error: unexpected end of macro invocation
+  --> $DIR/macro-at-most-once-rep-2018.rs:29:15
+   |
+LL | macro_rules! barplus {
+   | -------------------- when calling this macro
+...
+LL |     barplus!(a);
+   |               ^ missing tokens in macro arguments
+
+error: no rules expected the token `?`
+  --> $DIR/macro-at-most-once-rep-2018.rs:30:15
+   |
+LL | macro_rules! barplus {
+   | -------------------- when calling this macro
+...
+LL |     barplus!(a?);
+   |               ^ no rules expected this token in macro call
+
+error: no rules expected the token `?`
+  --> $DIR/macro-at-most-once-rep-2018.rs:31:15
+   |
+LL | macro_rules! barplus {
+   | -------------------- when calling this macro
+...
+LL |     barplus!(a?a);
+   |               ^ no rules expected this token in macro call
+
+error: unexpected end of macro invocation
+  --> $DIR/macro-at-most-once-rep-2018.rs:35:5
+   |
+LL | macro_rules! barstar {
+   | -------------------- when calling this macro
+...
+LL |     barstar!();
+   |     ^^^^^^^^^^^ missing tokens in macro arguments
+
+error: unexpected end of macro invocation
+  --> $DIR/macro-at-most-once-rep-2018.rs:36:15
+   |
+LL | macro_rules! barstar {
+   | -------------------- when calling this macro
+...
+LL |     barstar!(a);
+   |               ^ missing tokens in macro arguments
+
+error: no rules expected the token `?`
+  --> $DIR/macro-at-most-once-rep-2018.rs:37:15
+   |
+LL | macro_rules! barstar {
+   | -------------------- when calling this macro
+...
+LL |     barstar!(a?);
+   |               ^ no rules expected this token in macro call
+
+error: no rules expected the token `?`
+  --> $DIR/macro-at-most-once-rep-2018.rs:38:15
+   |
+LL | macro_rules! barstar {
+   | -------------------- when calling this macro
+...
+LL |     barstar!(a?a);
+   |               ^ no rules expected this token in macro call
+
+error: aborting due to 12 previous errors
+
diff --git a/src/test/ui/macros/macro-attribute.rs b/src/test/ui/macros/macro-attribute.rs
new file mode 100644
index 0000000..f580dfa
--- /dev/null
+++ b/src/test/ui/macros/macro-attribute.rs
@@ -0,0 +1,2 @@
+#[doc = $not_there] //~ ERROR unexpected token: `$`
+fn main() { }
diff --git a/src/test/ui/macros/macro-attribute.stderr b/src/test/ui/macros/macro-attribute.stderr
new file mode 100644
index 0000000..aa1cd94
--- /dev/null
+++ b/src/test/ui/macros/macro-attribute.stderr
@@ -0,0 +1,8 @@
+error: unexpected token: `$`
+  --> $DIR/macro-attribute.rs:1:7
+   |
+LL | #[doc = $not_there]
+   |       ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/macros/macro-backtrace-invalid-internals.rs b/src/test/ui/macros/macro-backtrace-invalid-internals.rs
new file mode 100644
index 0000000..9501e7c
--- /dev/null
+++ b/src/test/ui/macros/macro-backtrace-invalid-internals.rs
@@ -0,0 +1,61 @@
+// Macros in statement vs expression position handle backtraces differently.
+
+macro_rules! fake_method_stmt {
+     () => {
+          1.fake() //~ ERROR no method
+     }
+}
+
+macro_rules! fake_field_stmt {
+     () => {
+          1.fake //~ ERROR doesn't have fields
+     }
+}
+
+macro_rules! fake_anon_field_stmt {
+     () => {
+          (1).0 //~ ERROR doesn't have fields
+     }
+}
+
+macro_rules! fake_method_expr {
+     () => {
+          1.fake() //~ ERROR no method
+     }
+}
+
+macro_rules! fake_field_expr {
+     () => {
+          1.fake //~ ERROR doesn't have fields
+     }
+}
+
+macro_rules! fake_anon_field_expr {
+     () => {
+          (1).0 //~ ERROR doesn't have fields
+     }
+}
+
+macro_rules! real_method_stmt {
+     () => {
+          2.0.neg() //~ ERROR can't call method `neg` on ambiguous numeric type `{float}`
+     }
+}
+
+macro_rules! real_method_expr {
+     () => {
+          2.0.neg() //~ ERROR can't call method `neg` on ambiguous numeric type `{float}`
+     }
+}
+
+fn main() {
+    fake_method_stmt!();
+    fake_field_stmt!();
+    fake_anon_field_stmt!();
+    real_method_stmt!();
+
+    let _ = fake_method_expr!();
+    let _ = fake_field_expr!();
+    let _ = fake_anon_field_expr!();
+    let _ = real_method_expr!();
+}
diff --git a/src/test/ui/macros/macro-backtrace-invalid-internals.stderr b/src/test/ui/macros/macro-backtrace-invalid-internals.stderr
new file mode 100644
index 0000000..11a4b44
--- /dev/null
+++ b/src/test/ui/macros/macro-backtrace-invalid-internals.stderr
@@ -0,0 +1,84 @@
+error[E0599]: no method named `fake` found for type `{integer}` in the current scope
+  --> $DIR/macro-backtrace-invalid-internals.rs:5:13
+   |
+LL |           1.fake()
+   |             ^^^^
+...
+LL |     fake_method_stmt!();
+   |     -------------------- in this macro invocation
+
+error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields
+  --> $DIR/macro-backtrace-invalid-internals.rs:11:13
+   |
+LL |           1.fake
+   |             ^^^^
+...
+LL |     fake_field_stmt!();
+   |     ------------------- in this macro invocation
+
+error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields
+  --> $DIR/macro-backtrace-invalid-internals.rs:17:15
+   |
+LL |           (1).0
+   |               ^
+...
+LL |     fake_anon_field_stmt!();
+   |     ------------------------ in this macro invocation
+
+error[E0689]: can't call method `neg` on ambiguous numeric type `{float}`
+  --> $DIR/macro-backtrace-invalid-internals.rs:41:15
+   |
+LL |           2.0.neg()
+   |               ^^^
+...
+LL |     real_method_stmt!();
+   |     -------------------- in this macro invocation
+help: you must specify a concrete type for this numeric value, like `f32`
+   |
+LL |           2.0_f32.neg()
+   |           ^^^^^^^
+
+error[E0599]: no method named `fake` found for type `{integer}` in the current scope
+  --> $DIR/macro-backtrace-invalid-internals.rs:23:13
+   |
+LL |           1.fake()
+   |             ^^^^
+...
+LL |     let _ = fake_method_expr!();
+   |             ------------------- in this macro invocation
+
+error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields
+  --> $DIR/macro-backtrace-invalid-internals.rs:29:13
+   |
+LL |           1.fake
+   |             ^^^^
+...
+LL |     let _ = fake_field_expr!();
+   |             ------------------ in this macro invocation
+
+error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields
+  --> $DIR/macro-backtrace-invalid-internals.rs:35:15
+   |
+LL |           (1).0
+   |               ^
+...
+LL |     let _ = fake_anon_field_expr!();
+   |             ----------------------- in this macro invocation
+
+error[E0689]: can't call method `neg` on ambiguous numeric type `{float}`
+  --> $DIR/macro-backtrace-invalid-internals.rs:47:15
+   |
+LL |           2.0.neg()
+   |               ^^^
+...
+LL |     let _ = real_method_expr!();
+   |             ------------------- in this macro invocation
+help: you must specify a concrete type for this numeric value, like `f32`
+   |
+LL |           2.0_f32.neg()
+   |           ^^^^^^^
+
+error: aborting due to 8 previous errors
+
+Some errors occurred: E0599, E0610, E0689.
+For more information about an error, try `rustc --explain E0599`.
diff --git a/src/test/ui/macros/macro-backtrace-nested.rs b/src/test/ui/macros/macro-backtrace-nested.rs
new file mode 100644
index 0000000..13d8016
--- /dev/null
+++ b/src/test/ui/macros/macro-backtrace-nested.rs
@@ -0,0 +1,20 @@
+// In expression position, but not statement position, when we expand a macro,
+// we replace the span of the expanded expression with that of the call site.
+
+macro_rules! nested_expr {
+    () => (fake) //~ ERROR cannot find
+    //~^ ERROR cannot find
+}
+
+macro_rules! call_nested_expr {
+    () => (nested_expr!())
+}
+
+macro_rules! call_nested_expr_sum {
+    () => { 1 + nested_expr!(); }
+}
+
+fn main() {
+    1 + call_nested_expr!();
+    call_nested_expr_sum!();
+}
diff --git a/src/test/ui/macros/macro-backtrace-nested.stderr b/src/test/ui/macros/macro-backtrace-nested.stderr
new file mode 100644
index 0000000..501f525
--- /dev/null
+++ b/src/test/ui/macros/macro-backtrace-nested.stderr
@@ -0,0 +1,21 @@
+error[E0425]: cannot find value `fake` in this scope
+  --> $DIR/macro-backtrace-nested.rs:5:12
+   |
+LL |     () => (fake)
+   |            ^^^^ not found in this scope
+...
+LL |     1 + call_nested_expr!();
+   |         ------------------- in this macro invocation
+
+error[E0425]: cannot find value `fake` in this scope
+  --> $DIR/macro-backtrace-nested.rs:5:12
+   |
+LL |     () => (fake)
+   |            ^^^^ not found in this scope
+...
+LL |     call_nested_expr_sum!();
+   |     ------------------------ in this macro invocation
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/macros/macro-backtrace-println.rs b/src/test/ui/macros/macro-backtrace-println.rs
new file mode 100644
index 0000000..859dd01
--- /dev/null
+++ b/src/test/ui/macros/macro-backtrace-println.rs
@@ -0,0 +1,19 @@
+// The `format_args!` syntax extension issues errors before code expansion
+// has completed, but we still need a backtrace.
+
+// This test includes stripped-down versions of `print!` and `println!`,
+// because we can't otherwise verify the lines of the backtrace.
+
+fn print(_args: std::fmt::Arguments) {}
+
+macro_rules! myprint {
+    ($($arg:tt)*) => (print(format_args!($($arg)*)));
+}
+
+macro_rules! myprintln {
+    ($fmt:expr) => (myprint!(concat!($fmt, "\n"))); //~ ERROR no arguments were given
+}
+
+fn main() {
+    myprintln!("{}");
+}
diff --git a/src/test/ui/macros/macro-backtrace-println.stderr b/src/test/ui/macros/macro-backtrace-println.stderr
new file mode 100644
index 0000000..209ff09
--- /dev/null
+++ b/src/test/ui/macros/macro-backtrace-println.stderr
@@ -0,0 +1,11 @@
+error: 1 positional argument in format string, but no arguments were given
+  --> $DIR/macro-backtrace-println.rs:14:30
+   |
+LL |     ($fmt:expr) => (myprint!(concat!($fmt, "\n")));
+   |                              ^^^^^^^^^^^^^^^^^^^
+...
+LL |     myprintln!("{}");
+   |     ----------------- in this macro invocation
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/macros/macro-comma-behavior.core.stderr b/src/test/ui/macros/macro-comma-behavior.core.stderr
new file mode 100644
index 0000000..dd0cac6
--- /dev/null
+++ b/src/test/ui/macros/macro-comma-behavior.core.stderr
@@ -0,0 +1,44 @@
+error: 1 positional argument in format string, but no arguments were given
+  --> $DIR/macro-comma-behavior.rs:21:23
+   |
+LL |     assert_eq!(1, 1, "{}",);
+   |                       ^^
+
+error: 1 positional argument in format string, but no arguments were given
+  --> $DIR/macro-comma-behavior.rs:24:23
+   |
+LL |     assert_ne!(1, 2, "{}",);
+   |                       ^^
+
+error: 1 positional argument in format string, but no arguments were given
+  --> $DIR/macro-comma-behavior.rs:30:29
+   |
+LL |     debug_assert_eq!(1, 1, "{}",);
+   |                             ^^
+
+error: 1 positional argument in format string, but no arguments were given
+  --> $DIR/macro-comma-behavior.rs:33:29
+   |
+LL |     debug_assert_ne!(1, 2, "{}",);
+   |                             ^^
+
+error: 1 positional argument in format string, but no arguments were given
+  --> $DIR/macro-comma-behavior.rs:54:19
+   |
+LL |     format_args!("{}",);
+   |                   ^^
+
+error: 1 positional argument in format string, but no arguments were given
+  --> $DIR/macro-comma-behavior.rs:72:21
+   |
+LL |     unimplemented!("{}",);
+   |                     ^^
+
+error: 1 positional argument in format string, but no arguments were given
+  --> $DIR/macro-comma-behavior.rs:81:24
+   |
+LL |             write!(f, "{}",)?;
+   |                        ^^
+
+error: aborting due to 7 previous errors
+
diff --git a/src/test/ui/macros/macro-comma-behavior.rs b/src/test/ui/macros/macro-comma-behavior.rs
new file mode 100644
index 0000000..006319a
--- /dev/null
+++ b/src/test/ui/macros/macro-comma-behavior.rs
@@ -0,0 +1,95 @@
+// Companion test to the similarly-named file in run-pass.
+
+// compile-flags: -C debug_assertions=yes
+// revisions: std core
+
+#![feature(lang_items)]
+#![cfg_attr(core, no_std)]
+
+#[cfg(std)] use std::fmt;
+#[cfg(core)] use core::fmt;
+#[cfg(core)] #[lang = "eh_personality"] fn eh_personality() {}
+#[cfg(core)] #[lang = "eh_unwind_resume"] fn eh_unwind_resume() {}
+#[cfg(core)] #[lang = "panic_impl"] fn panic_impl(panic: &core::panic::PanicInfo) -> ! { loop {} }
+
+// (see documentation of the similarly-named test in run-pass)
+fn to_format_or_not_to_format() {
+    let falsum = || false;
+
+    // assert!(true, "{}",); // see run-pass
+
+    assert_eq!(1, 1, "{}",);
+    //[core]~^ ERROR no arguments
+    //[std]~^^ ERROR no arguments
+    assert_ne!(1, 2, "{}",);
+    //[core]~^ ERROR no arguments
+    //[std]~^^ ERROR no arguments
+
+    // debug_assert!(true, "{}",); // see run-pass
+
+    debug_assert_eq!(1, 1, "{}",);
+    //[core]~^ ERROR no arguments
+    //[std]~^^ ERROR no arguments
+    debug_assert_ne!(1, 2, "{}",);
+    //[core]~^ ERROR no arguments
+    //[std]~^^ ERROR no arguments
+
+    #[cfg(std)] {
+        eprint!("{}",);
+        //[std]~^ ERROR no arguments
+    }
+
+    #[cfg(std)] {
+        // FIXME: compile-fail says "expected error not found" even though
+        //        rustc does emit an error
+        // eprintln!("{}",);
+        // <DISABLED> [std]~^ ERROR no arguments
+    }
+
+    #[cfg(std)] {
+        format!("{}",);
+        //[std]~^ ERROR no arguments
+    }
+
+    format_args!("{}",);
+    //[core]~^ ERROR no arguments
+    //[std]~^^ ERROR no arguments
+
+    // if falsum() { panic!("{}",); } // see run-pass
+
+    #[cfg(std)] {
+        print!("{}",);
+        //[std]~^ ERROR no arguments
+    }
+
+    #[cfg(std)] {
+        // FIXME: compile-fail says "expected error not found" even though
+        //        rustc does emit an error
+        // println!("{}",);
+        // <DISABLED> [std]~^ ERROR no arguments
+    }
+
+    unimplemented!("{}",);
+    //[core]~^ ERROR no arguments
+    //[std]~^^ ERROR no arguments
+
+    // if falsum() { unreachable!("{}",); } // see run-pass
+
+    struct S;
+    impl fmt::Display for S {
+        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+            write!(f, "{}",)?;
+            //[core]~^ ERROR no arguments
+            //[std]~^^ ERROR no arguments
+
+            // FIXME: compile-fail says "expected error not found" even though
+            //        rustc does emit an error
+            // writeln!(f, "{}",)?;
+            // <DISABLED> [core]~^ ERROR no arguments
+            // <DISABLED> [std]~^^ ERROR no arguments
+            Ok(())
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/macros/macro-comma-behavior.std.stderr b/src/test/ui/macros/macro-comma-behavior.std.stderr
new file mode 100644
index 0000000..4372d89
--- /dev/null
+++ b/src/test/ui/macros/macro-comma-behavior.std.stderr
@@ -0,0 +1,62 @@
+error: 1 positional argument in format string, but no arguments were given
+  --> $DIR/macro-comma-behavior.rs:21:23
+   |
+LL |     assert_eq!(1, 1, "{}",);
+   |                       ^^
+
+error: 1 positional argument in format string, but no arguments were given
+  --> $DIR/macro-comma-behavior.rs:24:23
+   |
+LL |     assert_ne!(1, 2, "{}",);
+   |                       ^^
+
+error: 1 positional argument in format string, but no arguments were given
+  --> $DIR/macro-comma-behavior.rs:30:29
+   |
+LL |     debug_assert_eq!(1, 1, "{}",);
+   |                             ^^
+
+error: 1 positional argument in format string, but no arguments were given
+  --> $DIR/macro-comma-behavior.rs:33:29
+   |
+LL |     debug_assert_ne!(1, 2, "{}",);
+   |                             ^^
+
+error: 1 positional argument in format string, but no arguments were given
+  --> $DIR/macro-comma-behavior.rs:38:18
+   |
+LL |         eprint!("{}",);
+   |                  ^^
+
+error: 1 positional argument in format string, but no arguments were given
+  --> $DIR/macro-comma-behavior.rs:50:18
+   |
+LL |         format!("{}",);
+   |                  ^^
+
+error: 1 positional argument in format string, but no arguments were given
+  --> $DIR/macro-comma-behavior.rs:54:19
+   |
+LL |     format_args!("{}",);
+   |                   ^^
+
+error: 1 positional argument in format string, but no arguments were given
+  --> $DIR/macro-comma-behavior.rs:61:17
+   |
+LL |         print!("{}",);
+   |                 ^^
+
+error: 1 positional argument in format string, but no arguments were given
+  --> $DIR/macro-comma-behavior.rs:72:21
+   |
+LL |     unimplemented!("{}",);
+   |                     ^^
+
+error: 1 positional argument in format string, but no arguments were given
+  --> $DIR/macro-comma-behavior.rs:81:24
+   |
+LL |             write!(f, "{}",)?;
+   |                        ^^
+
+error: aborting due to 10 previous errors
+
diff --git a/src/test/ui/macros/macro-comma-support.rs b/src/test/ui/macros/macro-comma-support.rs
new file mode 100644
index 0000000..7df5b62
--- /dev/null
+++ b/src/test/ui/macros/macro-comma-support.rs
@@ -0,0 +1,10 @@
+// This is a companion to the similarly-named test in run-pass.
+//
+// It tests macros that unavoidably produce compile errors.
+
+fn compile_error() {
+    compile_error!("lel"); //~ ERROR lel
+    compile_error!("lel",); //~ ERROR lel
+}
+
+fn main() {}
diff --git a/src/test/ui/macros/macro-comma-support.stderr b/src/test/ui/macros/macro-comma-support.stderr
new file mode 100644
index 0000000..28d064f
--- /dev/null
+++ b/src/test/ui/macros/macro-comma-support.stderr
@@ -0,0 +1,14 @@
+error: lel
+  --> $DIR/macro-comma-support.rs:6:5
+   |
+LL |     compile_error!("lel");
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error: lel
+  --> $DIR/macro-comma-support.rs:7:5
+   |
+LL |     compile_error!("lel",);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/macros/macro-context.rs b/src/test/ui/macros/macro-context.rs
new file mode 100644
index 0000000..9130c3d
--- /dev/null
+++ b/src/test/ui/macros/macro-context.rs
@@ -0,0 +1,17 @@
+// (typeof used because it's surprisingly hard to find an unparsed token after a stmt)
+macro_rules! m {
+    () => ( i ; typeof );   //~ ERROR expected expression, found reserved keyword `typeof`
+                            //~| ERROR macro expansion ignores token `typeof`
+                            //~| ERROR macro expansion ignores token `;`
+                            //~| ERROR macro expansion ignores token `;`
+}
+
+fn main() {
+    let a: m!();
+    let i = m!();
+    match 0 {
+        m!() => {}
+    }
+
+    m!();
+}
diff --git a/src/test/ui/macros/macro-context.stderr b/src/test/ui/macros/macro-context.stderr
new file mode 100644
index 0000000..2a07791
--- /dev/null
+++ b/src/test/ui/macros/macro-context.stderr
@@ -0,0 +1,44 @@
+error: macro expansion ignores token `;` and any following
+  --> $DIR/macro-context.rs:3:15
+   |
+LL |     () => ( i ; typeof );
+   |               ^
+...
+LL |     let a: m!();
+   |            ---- caused by the macro expansion here
+   |
+   = note: the usage of `m!` is likely invalid in type context
+
+error: macro expansion ignores token `typeof` and any following
+  --> $DIR/macro-context.rs:3:17
+   |
+LL |     () => ( i ; typeof );
+   |                 ^^^^^^
+...
+LL |     let i = m!();
+   |             ---- caused by the macro expansion here
+   |
+   = note: the usage of `m!` is likely invalid in expression context
+
+error: macro expansion ignores token `;` and any following
+  --> $DIR/macro-context.rs:3:15
+   |
+LL |     () => ( i ; typeof );
+   |               ^
+...
+LL |         m!() => {}
+   |         ---- caused by the macro expansion here
+   |
+   = note: the usage of `m!` is likely invalid in pattern context
+
+error: expected expression, found reserved keyword `typeof`
+  --> $DIR/macro-context.rs:3:17
+   |
+LL |     () => ( i ; typeof );
+   |                 ^^^^^^ expected expression
+...
+LL |     m!();
+   |     ----- in this macro invocation
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/macros/macro-crate-nonterminal-non-root.rs b/src/test/ui/macros/macro-crate-nonterminal-non-root.rs
new file mode 100644
index 0000000..6789955
--- /dev/null
+++ b/src/test/ui/macros/macro-crate-nonterminal-non-root.rs
@@ -0,0 +1,9 @@
+// aux-build:macro_crate_nonterminal.rs
+
+mod foo {
+    #[macro_use]
+    extern crate macro_crate_nonterminal;  //~ ERROR must be at the crate root
+}
+
+fn main() {
+}
diff --git a/src/test/ui/macros/macro-crate-nonterminal-non-root.stderr b/src/test/ui/macros/macro-crate-nonterminal-non-root.stderr
new file mode 100644
index 0000000..1eca018
--- /dev/null
+++ b/src/test/ui/macros/macro-crate-nonterminal-non-root.stderr
@@ -0,0 +1,9 @@
+error[E0468]: an `extern crate` loading macros must be at the crate root
+  --> $DIR/macro-crate-nonterminal-non-root.rs:5:5
+   |
+LL |     extern crate macro_crate_nonterminal;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0468`.
diff --git a/src/test/ui/macros/macro-error.rs b/src/test/ui/macros/macro-error.rs
new file mode 100644
index 0000000..59ed79e
--- /dev/null
+++ b/src/test/ui/macros/macro-error.rs
@@ -0,0 +1,9 @@
+macro_rules! foo {
+    ($a:expr) => a; //~ ERROR macro rhs must be delimited
+}
+
+fn main() {
+    foo!(0); // Check that we report errors at macro definition, not expansion.
+
+    let _: cfg!(foo) = (); //~ ERROR non-type macro in type position
+}
diff --git a/src/test/ui/macros/macro-error.stderr b/src/test/ui/macros/macro-error.stderr
new file mode 100644
index 0000000..b3aed8c
--- /dev/null
+++ b/src/test/ui/macros/macro-error.stderr
@@ -0,0 +1,14 @@
+error: macro rhs must be delimited
+  --> $DIR/macro-error.rs:2:18
+   |
+LL |     ($a:expr) => a;
+   |                  ^
+
+error: non-type macro in type position: cfg
+  --> $DIR/macro-error.rs:8:12
+   |
+LL |     let _: cfg!(foo) = ();
+   |            ^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/macros/macro-expanded-include/file.txt b/src/test/ui/macros/macro-expanded-include/file.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/test/ui/macros/macro-expanded-include/file.txt
diff --git a/src/test/ui/macros/macro-expanded-include/foo/mod.rs b/src/test/ui/macros/macro-expanded-include/foo/mod.rs
new file mode 100644
index 0000000..a8bfa02
--- /dev/null
+++ b/src/test/ui/macros/macro-expanded-include/foo/mod.rs
@@ -0,0 +1,9 @@
+// ignore-test
+
+macro_rules! m {
+    () => { include!("file.txt"); }
+}
+
+macro_rules! n {
+    () => { unsafe { asm!(include_str!("file.txt")); } }
+}
diff --git a/src/test/ui/macros/macro-expanded-include/test.rs b/src/test/ui/macros/macro-expanded-include/test.rs
new file mode 100644
index 0000000..fe697db
--- /dev/null
+++ b/src/test/ui/macros/macro-expanded-include/test.rs
@@ -0,0 +1,13 @@
+// ignore-emscripten no asm! support
+// compile-pass
+#![feature(asm)]
+#![allow(unused)]
+
+#[macro_use]
+mod foo;
+
+m!();
+fn f() { n!(); }
+
+
+fn main() {}
diff --git a/src/test/ui/macros/macro-expansion-tests.rs b/src/test/ui/macros/macro-expansion-tests.rs
new file mode 100644
index 0000000..38f4937
--- /dev/null
+++ b/src/test/ui/macros/macro-expansion-tests.rs
@@ -0,0 +1,40 @@
+#![allow(unused_macros)]
+
+mod macros_cant_escape_fns {
+    fn f() {
+        macro_rules! m { () => { 3 + 4 } }
+    }
+    fn g() -> i32 { m!() }
+    //~^ ERROR cannot find macro
+}
+
+mod macros_cant_escape_mods {
+    mod f {
+        macro_rules! m { () => { 3 + 4 } }
+    }
+    fn g() -> i32 { m!() }
+    //~^ ERROR cannot find macro
+}
+
+mod macros_can_escape_flattened_mods_test {
+    #[macro_use]
+    mod f {
+        macro_rules! m { () => { 3 + 4 } }
+    }
+    fn g() -> i32 { m!() }
+}
+
+fn macro_tokens_should_match() {
+    macro_rules! m { (a) => { 13 } }
+    m!(a);
+}
+
+// should be able to use a bound identifier as a literal in a macro definition:
+fn self_macro_parsing() {
+    macro_rules! foo { (zz) => { 287; } }
+    fn f(zz: i32) {
+        foo!(zz);
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/macros/macro-expansion-tests.stderr b/src/test/ui/macros/macro-expansion-tests.stderr
new file mode 100644
index 0000000..4ad9ade
--- /dev/null
+++ b/src/test/ui/macros/macro-expansion-tests.stderr
@@ -0,0 +1,18 @@
+error: cannot find macro `m!` in this scope
+  --> $DIR/macro-expansion-tests.rs:7:21
+   |
+LL |     fn g() -> i32 { m!() }
+   |                     ^
+   |
+   = help: have you added the `#[macro_use]` on the module/import?
+
+error: cannot find macro `m!` in this scope
+  --> $DIR/macro-expansion-tests.rs:15:21
+   |
+LL |     fn g() -> i32 { m!() }
+   |                     ^
+   |
+   = help: have you added the `#[macro_use]` on the module/import?
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/macros/macro-follow.rs b/src/test/ui/macros/macro-follow.rs
new file mode 100644
index 0000000..10b44e0
--- /dev/null
+++ b/src/test/ui/macros/macro-follow.rs
@@ -0,0 +1,115 @@
+//
+// Check the macro follow sets (see corresponding rpass test).
+
+#![allow(unused_macros)]
+
+// FOLLOW(pat) = {FatArrow, Comma, Eq, Or, Ident(if), Ident(in)}
+macro_rules! follow_pat {
+    ($p:pat ()) => {};       //~ERROR  `$p:pat` is followed by `(`
+    ($p:pat []) => {};       //~ERROR  `$p:pat` is followed by `[`
+    ($p:pat {}) => {};       //~ERROR  `$p:pat` is followed by `{`
+    ($p:pat :) => {};        //~ERROR `$p:pat` is followed by `:`
+    ($p:pat >) => {};        //~ERROR `$p:pat` is followed by `>`
+    ($p:pat +) => {};        //~ERROR `$p:pat` is followed by `+`
+    ($p:pat ident) => {};    //~ERROR `$p:pat` is followed by `ident`
+    ($p:pat $q:pat) => {};   //~ERROR `$p:pat` is followed by `$q:pat`
+    ($p:pat $e:expr) => {};  //~ERROR `$p:pat` is followed by `$e:expr`
+    ($p:pat $t:ty) => {};    //~ERROR `$p:pat` is followed by `$t:ty`
+    ($p:pat $s:stmt) => {};  //~ERROR `$p:pat` is followed by `$s:stmt`
+    ($p:pat $q:path) => {};  //~ERROR `$p:pat` is followed by `$q:path`
+    ($p:pat $b:block) => {}; //~ERROR `$p:pat` is followed by `$b:block`
+    ($p:pat $i:ident) => {}; //~ERROR `$p:pat` is followed by `$i:ident`
+    ($p:pat $t:tt) => {};    //~ERROR `$p:pat` is followed by `$t:tt`
+    ($p:pat $i:item) => {};  //~ERROR `$p:pat` is followed by `$i:item`
+    ($p:pat $m:meta) => {};  //~ERROR `$p:pat` is followed by `$m:meta`
+}
+// FOLLOW(expr) = {FatArrow, Comma, Semicolon}
+macro_rules! follow_expr {
+    ($e:expr ()) => {};       //~ERROR  `$e:expr` is followed by `(`
+    ($e:expr []) => {};       //~ERROR  `$e:expr` is followed by `[`
+    ($e:expr {}) => {};       //~ERROR  `$e:expr` is followed by `{`
+    ($e:expr =) => {};        //~ERROR `$e:expr` is followed by `=`
+    ($e:expr |) => {};        //~ERROR `$e:expr` is followed by `|`
+    ($e:expr :) => {};        //~ERROR `$e:expr` is followed by `:`
+    ($e:expr >) => {};        //~ERROR `$e:expr` is followed by `>`
+    ($e:expr +) => {};        //~ERROR `$e:expr` is followed by `+`
+    ($e:expr ident) => {};    //~ERROR `$e:expr` is followed by `ident`
+    ($e:expr if) => {};       //~ERROR `$e:expr` is followed by `if`
+    ($e:expr in) => {};       //~ERROR `$e:expr` is followed by `in`
+    ($e:expr $p:pat) => {};   //~ERROR `$e:expr` is followed by `$p:pat`
+    ($e:expr $f:expr) => {};  //~ERROR `$e:expr` is followed by `$f:expr`
+    ($e:expr $t:ty) => {};    //~ERROR `$e:expr` is followed by `$t:ty`
+    ($e:expr $s:stmt) => {};  //~ERROR `$e:expr` is followed by `$s:stmt`
+    ($e:expr $p:path) => {};  //~ERROR `$e:expr` is followed by `$p:path`
+    ($e:expr $b:block) => {}; //~ERROR `$e:expr` is followed by `$b:block`
+    ($e:expr $i:ident) => {}; //~ERROR `$e:expr` is followed by `$i:ident`
+    ($e:expr $t:tt) => {};    //~ERROR `$e:expr` is followed by `$t:tt`
+    ($e:expr $i:item) => {};  //~ERROR `$e:expr` is followed by `$i:item`
+    ($e:expr $m:meta) => {};  //~ERROR `$e:expr` is followed by `$m:meta`
+}
+// FOLLOW(ty) = {OpenDelim(Brace), Comma, FatArrow, Colon, Eq, Gt, Semi, Or,
+//               Ident(as), Ident(where), OpenDelim(Bracket), Nonterminal(Block)}
+macro_rules! follow_ty {
+    ($t:ty ()) => {};       //~ERROR  `$t:ty` is followed by `(`
+    ($t:ty []) => {};       // ok (RFC 1462)
+    ($t:ty +) => {};        //~ERROR `$t:ty` is followed by `+`
+    ($t:ty ident) => {};    //~ERROR `$t:ty` is followed by `ident`
+    ($t:ty if) => {};       //~ERROR `$t:ty` is followed by `if`
+    ($t:ty $p:pat) => {};   //~ERROR `$t:ty` is followed by `$p:pat`
+    ($t:ty $e:expr) => {};  //~ERROR `$t:ty` is followed by `$e:expr`
+    ($t:ty $r:ty) => {};    //~ERROR `$t:ty` is followed by `$r:ty`
+    ($t:ty $s:stmt) => {};  //~ERROR `$t:ty` is followed by `$s:stmt`
+    ($t:ty $p:path) => {};  //~ERROR `$t:ty` is followed by `$p:path`
+    ($t:ty $b:block) => {}; // ok (RFC 1494)
+    ($t:ty $i:ident) => {}; //~ERROR `$t:ty` is followed by `$i:ident`
+    ($t:ty $r:tt) => {};    //~ERROR `$t:ty` is followed by `$r:tt`
+    ($t:ty $i:item) => {};  //~ERROR `$t:ty` is followed by `$i:item`
+    ($t:ty $m:meta) => {};  //~ERROR `$t:ty` is followed by `$m:meta`
+}
+// FOLLOW(stmt) = FOLLOW(expr)
+macro_rules! follow_stmt {
+    ($s:stmt ()) => {};       //~ERROR  `$s:stmt` is followed by `(`
+    ($s:stmt []) => {};       //~ERROR  `$s:stmt` is followed by `[`
+    ($s:stmt {}) => {};       //~ERROR  `$s:stmt` is followed by `{`
+    ($s:stmt =) => {};        //~ERROR `$s:stmt` is followed by `=`
+    ($s:stmt |) => {};        //~ERROR `$s:stmt` is followed by `|`
+    ($s:stmt :) => {};        //~ERROR `$s:stmt` is followed by `:`
+    ($s:stmt >) => {};        //~ERROR `$s:stmt` is followed by `>`
+    ($s:stmt +) => {};        //~ERROR `$s:stmt` is followed by `+`
+    ($s:stmt ident) => {};    //~ERROR `$s:stmt` is followed by `ident`
+    ($s:stmt if) => {};       //~ERROR `$s:stmt` is followed by `if`
+    ($s:stmt in) => {};       //~ERROR `$s:stmt` is followed by `in`
+    ($s:stmt $p:pat) => {};   //~ERROR `$s:stmt` is followed by `$p:pat`
+    ($s:stmt $e:expr) => {};  //~ERROR `$s:stmt` is followed by `$e:expr`
+    ($s:stmt $t:ty) => {};    //~ERROR `$s:stmt` is followed by `$t:ty`
+    ($s:stmt $t:stmt) => {};  //~ERROR `$s:stmt` is followed by `$t:stmt`
+    ($s:stmt $p:path) => {};  //~ERROR `$s:stmt` is followed by `$p:path`
+    ($s:stmt $b:block) => {}; //~ERROR `$s:stmt` is followed by `$b:block`
+    ($s:stmt $i:ident) => {}; //~ERROR `$s:stmt` is followed by `$i:ident`
+    ($s:stmt $t:tt) => {};    //~ERROR `$s:stmt` is followed by `$t:tt`
+    ($s:stmt $i:item) => {};  //~ERROR `$s:stmt` is followed by `$i:item`
+    ($s:stmt $m:meta) => {};  //~ERROR `$s:stmt` is followed by `$m:meta`
+}
+// FOLLOW(path) = FOLLOW(ty)
+macro_rules! follow_path {
+    ($p:path ()) => {};       //~ERROR  `$p:path` is followed by `(`
+    ($p:path []) => {};       // ok (RFC 1462)
+    ($p:path +) => {};        //~ERROR `$p:path` is followed by `+`
+    ($p:path ident) => {};    //~ERROR `$p:path` is followed by `ident`
+    ($p:path if) => {};       //~ERROR `$p:path` is followed by `if`
+    ($p:path $q:pat) => {};   //~ERROR `$p:path` is followed by `$q:pat`
+    ($p:path $e:expr) => {};  //~ERROR `$p:path` is followed by `$e:expr`
+    ($p:path $t:ty) => {};    //~ERROR `$p:path` is followed by `$t:ty`
+    ($p:path $s:stmt) => {};  //~ERROR `$p:path` is followed by `$s:stmt`
+    ($p:path $q:path) => {};  //~ERROR `$p:path` is followed by `$q:path`
+    ($p:path $b:block) => {}; // ok (RFC 1494)
+    ($p:path $i:ident) => {}; //~ERROR `$p:path` is followed by `$i:ident`
+    ($p:path $t:tt) => {};    //~ERROR `$p:path` is followed by `$t:tt`
+    ($p:path $i:item) => {};  //~ERROR `$p:path` is followed by `$i:item`
+    ($p:path $m:meta) => {};  //~ERROR `$p:path` is followed by `$m:meta`
+}
+// FOLLOW(block) = any token
+// FOLLOW(ident) = any token
+
+fn main() {}
+
diff --git a/src/test/ui/macros/macro-follow.stderr b/src/test/ui/macros/macro-follow.stderr
new file mode 100644
index 0000000..d3f081b
--- /dev/null
+++ b/src/test/ui/macros/macro-follow.stderr
@@ -0,0 +1,682 @@
+error: `$p:pat` is followed by `(`, which is not allowed for `pat` fragments
+  --> $DIR/macro-follow.rs:8:14
+   |
+LL |     ($p:pat ()) => {};
+   |              ^ not allowed after `pat` fragments
+   |
+   = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
+
+error: `$p:pat` is followed by `[`, which is not allowed for `pat` fragments
+  --> $DIR/macro-follow.rs:9:14
+   |
+LL |     ($p:pat []) => {};
+   |              ^ not allowed after `pat` fragments
+   |
+   = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
+
+error: `$p:pat` is followed by `{`, which is not allowed for `pat` fragments
+  --> $DIR/macro-follow.rs:10:14
+   |
+LL |     ($p:pat {}) => {};
+   |              ^ not allowed after `pat` fragments
+   |
+   = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
+
+error: `$p:pat` is followed by `:`, which is not allowed for `pat` fragments
+  --> $DIR/macro-follow.rs:11:13
+   |
+LL |     ($p:pat :) => {};
+   |             ^ not allowed after `pat` fragments
+   |
+   = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
+
+error: `$p:pat` is followed by `>`, which is not allowed for `pat` fragments
+  --> $DIR/macro-follow.rs:12:13
+   |
+LL |     ($p:pat >) => {};
+   |             ^ not allowed after `pat` fragments
+   |
+   = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
+
+error: `$p:pat` is followed by `+`, which is not allowed for `pat` fragments
+  --> $DIR/macro-follow.rs:13:13
+   |
+LL |     ($p:pat +) => {};
+   |             ^ not allowed after `pat` fragments
+   |
+   = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
+
+error: `$p:pat` is followed by `ident`, which is not allowed for `pat` fragments
+  --> $DIR/macro-follow.rs:14:13
+   |
+LL |     ($p:pat ident) => {};
+   |             ^^^^^ not allowed after `pat` fragments
+   |
+   = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
+
+error: `$p:pat` is followed by `$q:pat`, which is not allowed for `pat` fragments
+  --> $DIR/macro-follow.rs:15:13
+   |
+LL |     ($p:pat $q:pat) => {};
+   |             ^^^^^^ not allowed after `pat` fragments
+   |
+   = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
+
+error: `$p:pat` is followed by `$e:expr`, which is not allowed for `pat` fragments
+  --> $DIR/macro-follow.rs:16:13
+   |
+LL |     ($p:pat $e:expr) => {};
+   |             ^^^^^^^ not allowed after `pat` fragments
+   |
+   = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
+
+error: `$p:pat` is followed by `$t:ty`, which is not allowed for `pat` fragments
+  --> $DIR/macro-follow.rs:17:13
+   |
+LL |     ($p:pat $t:ty) => {};
+   |             ^^^^^ not allowed after `pat` fragments
+   |
+   = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
+
+error: `$p:pat` is followed by `$s:stmt`, which is not allowed for `pat` fragments
+  --> $DIR/macro-follow.rs:18:13
+   |
+LL |     ($p:pat $s:stmt) => {};
+   |             ^^^^^^^ not allowed after `pat` fragments
+   |
+   = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
+
+error: `$p:pat` is followed by `$q:path`, which is not allowed for `pat` fragments
+  --> $DIR/macro-follow.rs:19:13
+   |
+LL |     ($p:pat $q:path) => {};
+   |             ^^^^^^^ not allowed after `pat` fragments
+   |
+   = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
+
+error: `$p:pat` is followed by `$b:block`, which is not allowed for `pat` fragments
+  --> $DIR/macro-follow.rs:20:13
+   |
+LL |     ($p:pat $b:block) => {};
+   |             ^^^^^^^^ not allowed after `pat` fragments
+   |
+   = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
+
+error: `$p:pat` is followed by `$i:ident`, which is not allowed for `pat` fragments
+  --> $DIR/macro-follow.rs:21:13
+   |
+LL |     ($p:pat $i:ident) => {};
+   |             ^^^^^^^^ not allowed after `pat` fragments
+   |
+   = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
+
+error: `$p:pat` is followed by `$t:tt`, which is not allowed for `pat` fragments
+  --> $DIR/macro-follow.rs:22:13
+   |
+LL |     ($p:pat $t:tt) => {};
+   |             ^^^^^ not allowed after `pat` fragments
+   |
+   = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
+
+error: `$p:pat` is followed by `$i:item`, which is not allowed for `pat` fragments
+  --> $DIR/macro-follow.rs:23:13
+   |
+LL |     ($p:pat $i:item) => {};
+   |             ^^^^^^^ not allowed after `pat` fragments
+   |
+   = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
+
+error: `$p:pat` is followed by `$m:meta`, which is not allowed for `pat` fragments
+  --> $DIR/macro-follow.rs:24:13
+   |
+LL |     ($p:pat $m:meta) => {};
+   |             ^^^^^^^ not allowed after `pat` fragments
+   |
+   = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
+
+error: `$e:expr` is followed by `(`, which is not allowed for `expr` fragments
+  --> $DIR/macro-follow.rs:28:15
+   |
+LL |     ($e:expr ()) => {};
+   |               ^ not allowed after `expr` fragments
+   |
+   = note: allowed there are: `=>`, `,` or `;`
+
+error: `$e:expr` is followed by `[`, which is not allowed for `expr` fragments
+  --> $DIR/macro-follow.rs:29:15
+   |
+LL |     ($e:expr []) => {};
+   |               ^ not allowed after `expr` fragments
+   |
+   = note: allowed there are: `=>`, `,` or `;`
+
+error: `$e:expr` is followed by `{`, which is not allowed for `expr` fragments
+  --> $DIR/macro-follow.rs:30:15
+   |
+LL |     ($e:expr {}) => {};
+   |               ^ not allowed after `expr` fragments
+   |
+   = note: allowed there are: `=>`, `,` or `;`
+
+error: `$e:expr` is followed by `=`, which is not allowed for `expr` fragments
+  --> $DIR/macro-follow.rs:31:14
+   |
+LL |     ($e:expr =) => {};
+   |              ^ not allowed after `expr` fragments
+   |
+   = note: allowed there are: `=>`, `,` or `;`
+
+error: `$e:expr` is followed by `|`, which is not allowed for `expr` fragments
+  --> $DIR/macro-follow.rs:32:14
+   |
+LL |     ($e:expr |) => {};
+   |              ^ not allowed after `expr` fragments
+   |
+   = note: allowed there are: `=>`, `,` or `;`
+
+error: `$e:expr` is followed by `:`, which is not allowed for `expr` fragments
+  --> $DIR/macro-follow.rs:33:14
+   |
+LL |     ($e:expr :) => {};
+   |              ^ not allowed after `expr` fragments
+   |
+   = note: allowed there are: `=>`, `,` or `;`
+
+error: `$e:expr` is followed by `>`, which is not allowed for `expr` fragments
+  --> $DIR/macro-follow.rs:34:14
+   |
+LL |     ($e:expr >) => {};
+   |              ^ not allowed after `expr` fragments
+   |
+   = note: allowed there are: `=>`, `,` or `;`
+
+error: `$e:expr` is followed by `+`, which is not allowed for `expr` fragments
+  --> $DIR/macro-follow.rs:35:14
+   |
+LL |     ($e:expr +) => {};
+   |              ^ not allowed after `expr` fragments
+   |
+   = note: allowed there are: `=>`, `,` or `;`
+
+error: `$e:expr` is followed by `ident`, which is not allowed for `expr` fragments
+  --> $DIR/macro-follow.rs:36:14
+   |
+LL |     ($e:expr ident) => {};
+   |              ^^^^^ not allowed after `expr` fragments
+   |
+   = note: allowed there are: `=>`, `,` or `;`
+
+error: `$e:expr` is followed by `if`, which is not allowed for `expr` fragments
+  --> $DIR/macro-follow.rs:37:14
+   |
+LL |     ($e:expr if) => {};
+   |              ^^ not allowed after `expr` fragments
+   |
+   = note: allowed there are: `=>`, `,` or `;`
+
+error: `$e:expr` is followed by `in`, which is not allowed for `expr` fragments
+  --> $DIR/macro-follow.rs:38:14
+   |
+LL |     ($e:expr in) => {};
+   |              ^^ not allowed after `expr` fragments
+   |
+   = note: allowed there are: `=>`, `,` or `;`
+
+error: `$e:expr` is followed by `$p:pat`, which is not allowed for `expr` fragments
+  --> $DIR/macro-follow.rs:39:14
+   |
+LL |     ($e:expr $p:pat) => {};
+   |              ^^^^^^ not allowed after `expr` fragments
+   |
+   = note: allowed there are: `=>`, `,` or `;`
+
+error: `$e:expr` is followed by `$f:expr`, which is not allowed for `expr` fragments
+  --> $DIR/macro-follow.rs:40:14
+   |
+LL |     ($e:expr $f:expr) => {};
+   |              ^^^^^^^ not allowed after `expr` fragments
+   |
+   = note: allowed there are: `=>`, `,` or `;`
+
+error: `$e:expr` is followed by `$t:ty`, which is not allowed for `expr` fragments
+  --> $DIR/macro-follow.rs:41:14
+   |
+LL |     ($e:expr $t:ty) => {};
+   |              ^^^^^ not allowed after `expr` fragments
+   |
+   = note: allowed there are: `=>`, `,` or `;`
+
+error: `$e:expr` is followed by `$s:stmt`, which is not allowed for `expr` fragments
+  --> $DIR/macro-follow.rs:42:14
+   |
+LL |     ($e:expr $s:stmt) => {};
+   |              ^^^^^^^ not allowed after `expr` fragments
+   |
+   = note: allowed there are: `=>`, `,` or `;`
+
+error: `$e:expr` is followed by `$p:path`, which is not allowed for `expr` fragments
+  --> $DIR/macro-follow.rs:43:14
+   |
+LL |     ($e:expr $p:path) => {};
+   |              ^^^^^^^ not allowed after `expr` fragments
+   |
+   = note: allowed there are: `=>`, `,` or `;`
+
+error: `$e:expr` is followed by `$b:block`, which is not allowed for `expr` fragments
+  --> $DIR/macro-follow.rs:44:14
+   |
+LL |     ($e:expr $b:block) => {};
+   |              ^^^^^^^^ not allowed after `expr` fragments
+   |
+   = note: allowed there are: `=>`, `,` or `;`
+
+error: `$e:expr` is followed by `$i:ident`, which is not allowed for `expr` fragments
+  --> $DIR/macro-follow.rs:45:14
+   |
+LL |     ($e:expr $i:ident) => {};
+   |              ^^^^^^^^ not allowed after `expr` fragments
+   |
+   = note: allowed there are: `=>`, `,` or `;`
+
+error: `$e:expr` is followed by `$t:tt`, which is not allowed for `expr` fragments
+  --> $DIR/macro-follow.rs:46:14
+   |
+LL |     ($e:expr $t:tt) => {};
+   |              ^^^^^ not allowed after `expr` fragments
+   |
+   = note: allowed there are: `=>`, `,` or `;`
+
+error: `$e:expr` is followed by `$i:item`, which is not allowed for `expr` fragments
+  --> $DIR/macro-follow.rs:47:14
+   |
+LL |     ($e:expr $i:item) => {};
+   |              ^^^^^^^ not allowed after `expr` fragments
+   |
+   = note: allowed there are: `=>`, `,` or `;`
+
+error: `$e:expr` is followed by `$m:meta`, which is not allowed for `expr` fragments
+  --> $DIR/macro-follow.rs:48:14
+   |
+LL |     ($e:expr $m:meta) => {};
+   |              ^^^^^^^ not allowed after `expr` fragments
+   |
+   = note: allowed there are: `=>`, `,` or `;`
+
+error: `$t:ty` is followed by `(`, which is not allowed for `ty` fragments
+  --> $DIR/macro-follow.rs:53:13
+   |
+LL |     ($t:ty ()) => {};
+   |             ^ not allowed after `ty` fragments
+   |
+   = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
+
+error: `$t:ty` is followed by `+`, which is not allowed for `ty` fragments
+  --> $DIR/macro-follow.rs:55:12
+   |
+LL |     ($t:ty +) => {};
+   |            ^ not allowed after `ty` fragments
+   |
+   = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
+
+error: `$t:ty` is followed by `ident`, which is not allowed for `ty` fragments
+  --> $DIR/macro-follow.rs:56:12
+   |
+LL |     ($t:ty ident) => {};
+   |            ^^^^^ not allowed after `ty` fragments
+   |
+   = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
+
+error: `$t:ty` is followed by `if`, which is not allowed for `ty` fragments
+  --> $DIR/macro-follow.rs:57:12
+   |
+LL |     ($t:ty if) => {};
+   |            ^^ not allowed after `ty` fragments
+   |
+   = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
+
+error: `$t:ty` is followed by `$p:pat`, which is not allowed for `ty` fragments
+  --> $DIR/macro-follow.rs:58:12
+   |
+LL |     ($t:ty $p:pat) => {};
+   |            ^^^^^^ not allowed after `ty` fragments
+   |
+   = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
+
+error: `$t:ty` is followed by `$e:expr`, which is not allowed for `ty` fragments
+  --> $DIR/macro-follow.rs:59:12
+   |
+LL |     ($t:ty $e:expr) => {};
+   |            ^^^^^^^ not allowed after `ty` fragments
+   |
+   = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
+
+error: `$t:ty` is followed by `$r:ty`, which is not allowed for `ty` fragments
+  --> $DIR/macro-follow.rs:60:12
+   |
+LL |     ($t:ty $r:ty) => {};
+   |            ^^^^^ not allowed after `ty` fragments
+   |
+   = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
+
+error: `$t:ty` is followed by `$s:stmt`, which is not allowed for `ty` fragments
+  --> $DIR/macro-follow.rs:61:12
+   |
+LL |     ($t:ty $s:stmt) => {};
+   |            ^^^^^^^ not allowed after `ty` fragments
+   |
+   = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
+
+error: `$t:ty` is followed by `$p:path`, which is not allowed for `ty` fragments
+  --> $DIR/macro-follow.rs:62:12
+   |
+LL |     ($t:ty $p:path) => {};
+   |            ^^^^^^^ not allowed after `ty` fragments
+   |
+   = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
+
+error: `$t:ty` is followed by `$i:ident`, which is not allowed for `ty` fragments
+  --> $DIR/macro-follow.rs:64:12
+   |
+LL |     ($t:ty $i:ident) => {};
+   |            ^^^^^^^^ not allowed after `ty` fragments
+   |
+   = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
+
+error: `$t:ty` is followed by `$r:tt`, which is not allowed for `ty` fragments
+  --> $DIR/macro-follow.rs:65:12
+   |
+LL |     ($t:ty $r:tt) => {};
+   |            ^^^^^ not allowed after `ty` fragments
+   |
+   = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
+
+error: `$t:ty` is followed by `$i:item`, which is not allowed for `ty` fragments
+  --> $DIR/macro-follow.rs:66:12
+   |
+LL |     ($t:ty $i:item) => {};
+   |            ^^^^^^^ not allowed after `ty` fragments
+   |
+   = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
+
+error: `$t:ty` is followed by `$m:meta`, which is not allowed for `ty` fragments
+  --> $DIR/macro-follow.rs:67:12
+   |
+LL |     ($t:ty $m:meta) => {};
+   |            ^^^^^^^ not allowed after `ty` fragments
+   |
+   = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
+
+error: `$s:stmt` is followed by `(`, which is not allowed for `stmt` fragments
+  --> $DIR/macro-follow.rs:71:15
+   |
+LL |     ($s:stmt ()) => {};
+   |               ^ not allowed after `stmt` fragments
+   |
+   = note: allowed there are: `=>`, `,` or `;`
+
+error: `$s:stmt` is followed by `[`, which is not allowed for `stmt` fragments
+  --> $DIR/macro-follow.rs:72:15
+   |
+LL |     ($s:stmt []) => {};
+   |               ^ not allowed after `stmt` fragments
+   |
+   = note: allowed there are: `=>`, `,` or `;`
+
+error: `$s:stmt` is followed by `{`, which is not allowed for `stmt` fragments
+  --> $DIR/macro-follow.rs:73:15
+   |
+LL |     ($s:stmt {}) => {};
+   |               ^ not allowed after `stmt` fragments
+   |
+   = note: allowed there are: `=>`, `,` or `;`
+
+error: `$s:stmt` is followed by `=`, which is not allowed for `stmt` fragments
+  --> $DIR/macro-follow.rs:74:14
+   |
+LL |     ($s:stmt =) => {};
+   |              ^ not allowed after `stmt` fragments
+   |
+   = note: allowed there are: `=>`, `,` or `;`
+
+error: `$s:stmt` is followed by `|`, which is not allowed for `stmt` fragments
+  --> $DIR/macro-follow.rs:75:14
+   |
+LL |     ($s:stmt |) => {};
+   |              ^ not allowed after `stmt` fragments
+   |
+   = note: allowed there are: `=>`, `,` or `;`
+
+error: `$s:stmt` is followed by `:`, which is not allowed for `stmt` fragments
+  --> $DIR/macro-follow.rs:76:14
+   |
+LL |     ($s:stmt :) => {};
+   |              ^ not allowed after `stmt` fragments
+   |
+   = note: allowed there are: `=>`, `,` or `;`
+
+error: `$s:stmt` is followed by `>`, which is not allowed for `stmt` fragments
+  --> $DIR/macro-follow.rs:77:14
+   |
+LL |     ($s:stmt >) => {};
+   |              ^ not allowed after `stmt` fragments
+   |
+   = note: allowed there are: `=>`, `,` or `;`
+
+error: `$s:stmt` is followed by `+`, which is not allowed for `stmt` fragments
+  --> $DIR/macro-follow.rs:78:14
+   |
+LL |     ($s:stmt +) => {};
+   |              ^ not allowed after `stmt` fragments
+   |
+   = note: allowed there are: `=>`, `,` or `;`
+
+error: `$s:stmt` is followed by `ident`, which is not allowed for `stmt` fragments
+  --> $DIR/macro-follow.rs:79:14
+   |
+LL |     ($s:stmt ident) => {};
+   |              ^^^^^ not allowed after `stmt` fragments
+   |
+   = note: allowed there are: `=>`, `,` or `;`
+
+error: `$s:stmt` is followed by `if`, which is not allowed for `stmt` fragments
+  --> $DIR/macro-follow.rs:80:14
+   |
+LL |     ($s:stmt if) => {};
+   |              ^^ not allowed after `stmt` fragments
+   |
+   = note: allowed there are: `=>`, `,` or `;`
+
+error: `$s:stmt` is followed by `in`, which is not allowed for `stmt` fragments
+  --> $DIR/macro-follow.rs:81:14
+   |
+LL |     ($s:stmt in) => {};
+   |              ^^ not allowed after `stmt` fragments
+   |
+   = note: allowed there are: `=>`, `,` or `;`
+
+error: `$s:stmt` is followed by `$p:pat`, which is not allowed for `stmt` fragments
+  --> $DIR/macro-follow.rs:82:14
+   |
+LL |     ($s:stmt $p:pat) => {};
+   |              ^^^^^^ not allowed after `stmt` fragments
+   |
+   = note: allowed there are: `=>`, `,` or `;`
+
+error: `$s:stmt` is followed by `$e:expr`, which is not allowed for `stmt` fragments
+  --> $DIR/macro-follow.rs:83:14
+   |
+LL |     ($s:stmt $e:expr) => {};
+   |              ^^^^^^^ not allowed after `stmt` fragments
+   |
+   = note: allowed there are: `=>`, `,` or `;`
+
+error: `$s:stmt` is followed by `$t:ty`, which is not allowed for `stmt` fragments
+  --> $DIR/macro-follow.rs:84:14
+   |
+LL |     ($s:stmt $t:ty) => {};
+   |              ^^^^^ not allowed after `stmt` fragments
+   |
+   = note: allowed there are: `=>`, `,` or `;`
+
+error: `$s:stmt` is followed by `$t:stmt`, which is not allowed for `stmt` fragments
+  --> $DIR/macro-follow.rs:85:14
+   |
+LL |     ($s:stmt $t:stmt) => {};
+   |              ^^^^^^^ not allowed after `stmt` fragments
+   |
+   = note: allowed there are: `=>`, `,` or `;`
+
+error: `$s:stmt` is followed by `$p:path`, which is not allowed for `stmt` fragments
+  --> $DIR/macro-follow.rs:86:14
+   |
+LL |     ($s:stmt $p:path) => {};
+   |              ^^^^^^^ not allowed after `stmt` fragments
+   |
+   = note: allowed there are: `=>`, `,` or `;`
+
+error: `$s:stmt` is followed by `$b:block`, which is not allowed for `stmt` fragments
+  --> $DIR/macro-follow.rs:87:14
+   |
+LL |     ($s:stmt $b:block) => {};
+   |              ^^^^^^^^ not allowed after `stmt` fragments
+   |
+   = note: allowed there are: `=>`, `,` or `;`
+
+error: `$s:stmt` is followed by `$i:ident`, which is not allowed for `stmt` fragments
+  --> $DIR/macro-follow.rs:88:14
+   |
+LL |     ($s:stmt $i:ident) => {};
+   |              ^^^^^^^^ not allowed after `stmt` fragments
+   |
+   = note: allowed there are: `=>`, `,` or `;`
+
+error: `$s:stmt` is followed by `$t:tt`, which is not allowed for `stmt` fragments
+  --> $DIR/macro-follow.rs:89:14
+   |
+LL |     ($s:stmt $t:tt) => {};
+   |              ^^^^^ not allowed after `stmt` fragments
+   |
+   = note: allowed there are: `=>`, `,` or `;`
+
+error: `$s:stmt` is followed by `$i:item`, which is not allowed for `stmt` fragments
+  --> $DIR/macro-follow.rs:90:14
+   |
+LL |     ($s:stmt $i:item) => {};
+   |              ^^^^^^^ not allowed after `stmt` fragments
+   |
+   = note: allowed there are: `=>`, `,` or `;`
+
+error: `$s:stmt` is followed by `$m:meta`, which is not allowed for `stmt` fragments
+  --> $DIR/macro-follow.rs:91:14
+   |
+LL |     ($s:stmt $m:meta) => {};
+   |              ^^^^^^^ not allowed after `stmt` fragments
+   |
+   = note: allowed there are: `=>`, `,` or `;`
+
+error: `$p:path` is followed by `(`, which is not allowed for `path` fragments
+  --> $DIR/macro-follow.rs:95:15
+   |
+LL |     ($p:path ()) => {};
+   |               ^ not allowed after `path` fragments
+   |
+   = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
+
+error: `$p:path` is followed by `+`, which is not allowed for `path` fragments
+  --> $DIR/macro-follow.rs:97:14
+   |
+LL |     ($p:path +) => {};
+   |              ^ not allowed after `path` fragments
+   |
+   = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
+
+error: `$p:path` is followed by `ident`, which is not allowed for `path` fragments
+  --> $DIR/macro-follow.rs:98:14
+   |
+LL |     ($p:path ident) => {};
+   |              ^^^^^ not allowed after `path` fragments
+   |
+   = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
+
+error: `$p:path` is followed by `if`, which is not allowed for `path` fragments
+  --> $DIR/macro-follow.rs:99:14
+   |
+LL |     ($p:path if) => {};
+   |              ^^ not allowed after `path` fragments
+   |
+   = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
+
+error: `$p:path` is followed by `$q:pat`, which is not allowed for `path` fragments
+  --> $DIR/macro-follow.rs:100:14
+   |
+LL |     ($p:path $q:pat) => {};
+   |              ^^^^^^ not allowed after `path` fragments
+   |
+   = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
+
+error: `$p:path` is followed by `$e:expr`, which is not allowed for `path` fragments
+  --> $DIR/macro-follow.rs:101:14
+   |
+LL |     ($p:path $e:expr) => {};
+   |              ^^^^^^^ not allowed after `path` fragments
+   |
+   = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
+
+error: `$p:path` is followed by `$t:ty`, which is not allowed for `path` fragments
+  --> $DIR/macro-follow.rs:102:14
+   |
+LL |     ($p:path $t:ty) => {};
+   |              ^^^^^ not allowed after `path` fragments
+   |
+   = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
+
+error: `$p:path` is followed by `$s:stmt`, which is not allowed for `path` fragments
+  --> $DIR/macro-follow.rs:103:14
+   |
+LL |     ($p:path $s:stmt) => {};
+   |              ^^^^^^^ not allowed after `path` fragments
+   |
+   = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
+
+error: `$p:path` is followed by `$q:path`, which is not allowed for `path` fragments
+  --> $DIR/macro-follow.rs:104:14
+   |
+LL |     ($p:path $q:path) => {};
+   |              ^^^^^^^ not allowed after `path` fragments
+   |
+   = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
+
+error: `$p:path` is followed by `$i:ident`, which is not allowed for `path` fragments
+  --> $DIR/macro-follow.rs:106:14
+   |
+LL |     ($p:path $i:ident) => {};
+   |              ^^^^^^^^ not allowed after `path` fragments
+   |
+   = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
+
+error: `$p:path` is followed by `$t:tt`, which is not allowed for `path` fragments
+  --> $DIR/macro-follow.rs:107:14
+   |
+LL |     ($p:path $t:tt) => {};
+   |              ^^^^^ not allowed after `path` fragments
+   |
+   = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
+
+error: `$p:path` is followed by `$i:item`, which is not allowed for `path` fragments
+  --> $DIR/macro-follow.rs:108:14
+   |
+LL |     ($p:path $i:item) => {};
+   |              ^^^^^^^ not allowed after `path` fragments
+   |
+   = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
+
+error: `$p:path` is followed by `$m:meta`, which is not allowed for `path` fragments
+  --> $DIR/macro-follow.rs:109:14
+   |
+LL |     ($p:path $m:meta) => {};
+   |              ^^^^^^^ not allowed after `path` fragments
+   |
+   = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
+
+error: aborting due to 85 previous errors
+
diff --git a/src/test/ui/macros/macro-followed-by-seq-bad.rs b/src/test/ui/macros/macro-followed-by-seq-bad.rs
new file mode 100644
index 0000000..b73742f
--- /dev/null
+++ b/src/test/ui/macros/macro-followed-by-seq-bad.rs
@@ -0,0 +1,11 @@
+// Regression test for issue #25436: check that things which can be
+// followed by any token also permit X* to come afterwards.
+
+#![allow(unused_macros)]
+
+macro_rules! foo {
+  ( $a:expr $($b:tt)* ) => { }; //~ ERROR not allowed for `expr` fragments
+  ( $a:ty $($b:tt)* ) => { };   //~ ERROR not allowed for `ty` fragments
+}
+
+fn main() { }
diff --git a/src/test/ui/macros/macro-followed-by-seq-bad.stderr b/src/test/ui/macros/macro-followed-by-seq-bad.stderr
new file mode 100644
index 0000000..7097979
--- /dev/null
+++ b/src/test/ui/macros/macro-followed-by-seq-bad.stderr
@@ -0,0 +1,18 @@
+error: `$a:expr` is followed by `$b:tt`, which is not allowed for `expr` fragments
+  --> $DIR/macro-followed-by-seq-bad.rs:7:15
+   |
+LL |   ( $a:expr $($b:tt)* ) => { };
+   |               ^^^^^ not allowed after `expr` fragments
+   |
+   = note: allowed there are: `=>`, `,` or `;`
+
+error: `$a:ty` is followed by `$b:tt`, which is not allowed for `ty` fragments
+  --> $DIR/macro-followed-by-seq-bad.rs:8:13
+   |
+LL |   ( $a:ty $($b:tt)* ) => { };
+   |             ^^^^^ not allowed after `ty` fragments
+   |
+   = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/macros/macro-in-expression-context-2.rs b/src/test/ui/macros/macro-in-expression-context-2.rs
new file mode 100644
index 0000000..9423f0a
--- /dev/null
+++ b/src/test/ui/macros/macro-in-expression-context-2.rs
@@ -0,0 +1,8 @@
+macro_rules! empty { () => () }
+
+fn main() {
+    match 42 {
+        _ => { empty!() }
+//~^ ERROR macro expansion ends with an incomplete expression
+    };
+}
diff --git a/src/test/ui/macros/macro-in-expression-context-2.stderr b/src/test/ui/macros/macro-in-expression-context-2.stderr
new file mode 100644
index 0000000..672871c
--- /dev/null
+++ b/src/test/ui/macros/macro-in-expression-context-2.stderr
@@ -0,0 +1,11 @@
+error: macro expansion ends with an incomplete expression: expected expression
+  --> $DIR/macro-in-expression-context-2.rs:5:16
+   |
+LL | macro_rules! empty { () => () }
+   |                            -- in this macro arm
+...
+LL |         _ => { empty!() }
+   |                ^^^^^^^^ expected expression
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/macros/macro-in-expression-context.fixed b/src/test/ui/macros/macro-in-expression-context.fixed
new file mode 100644
index 0000000..df36db0
--- /dev/null
+++ b/src/test/ui/macros/macro-in-expression-context.fixed
@@ -0,0 +1,15 @@
+// run-rustfix
+
+macro_rules! foo {
+    () => {
+        assert_eq!("A", "A");
+        assert_eq!("B", "B");
+    }
+    //~^^ ERROR macro expansion ignores token `assert_eq` and any following
+    //~| NOTE the usage of `foo!` is likely invalid in expression context
+}
+
+fn main() {
+    foo!();
+    //~^ NOTE caused by the macro expansion here
+}
diff --git a/src/test/ui/macros/macro-in-expression-context.rs b/src/test/ui/macros/macro-in-expression-context.rs
new file mode 100644
index 0000000..b3f5e56
--- /dev/null
+++ b/src/test/ui/macros/macro-in-expression-context.rs
@@ -0,0 +1,15 @@
+// run-rustfix
+
+macro_rules! foo {
+    () => {
+        assert_eq!("A", "A");
+        assert_eq!("B", "B");
+    }
+    //~^^ ERROR macro expansion ignores token `assert_eq` and any following
+    //~| NOTE the usage of `foo!` is likely invalid in expression context
+}
+
+fn main() {
+    foo!()
+    //~^ NOTE caused by the macro expansion here
+}
diff --git a/src/test/ui/macros/macro-in-expression-context.stderr b/src/test/ui/macros/macro-in-expression-context.stderr
new file mode 100644
index 0000000..d27d6fb
--- /dev/null
+++ b/src/test/ui/macros/macro-in-expression-context.stderr
@@ -0,0 +1,15 @@
+error: macro expansion ignores token `assert_eq` and any following
+  --> $DIR/macro-in-expression-context.rs:6:9
+   |
+LL |         assert_eq!("B", "B");
+   |         ^^^^^^^^^
+...
+LL |     foo!()
+   |     ------- help: you might be missing a semicolon here: `;`
+   |     |
+   |     caused by the macro expansion here
+   |
+   = note: the usage of `foo!` is likely invalid in expression context
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/macros/macro-inner-attributes.rs b/src/test/ui/macros/macro-inner-attributes.rs
new file mode 100644
index 0000000..268ddda
--- /dev/null
+++ b/src/test/ui/macros/macro-inner-attributes.rs
@@ -0,0 +1,20 @@
+#![feature(custom_attribute)]
+
+macro_rules! test { ($nm:ident,
+                     #[$a:meta],
+                     $i:item) => (mod $nm { #![$a] $i }); }
+
+test!(a,
+      #[cfg(qux)],
+      pub fn bar() { });
+
+test!(b,
+      #[cfg(not(qux))],
+      pub fn bar() { });
+
+#[qux]
+fn main() {
+    a::bar();
+    //~^ ERROR failed to resolve: use of undeclared type or module `a`
+    b::bar();
+}
diff --git a/src/test/ui/macros/macro-inner-attributes.stderr b/src/test/ui/macros/macro-inner-attributes.stderr
new file mode 100644
index 0000000..5e20f10
--- /dev/null
+++ b/src/test/ui/macros/macro-inner-attributes.stderr
@@ -0,0 +1,9 @@
+error[E0433]: failed to resolve: use of undeclared type or module `a`
+  --> $DIR/macro-inner-attributes.rs:17:5
+   |
+LL |     a::bar();
+   |     ^ use of undeclared type or module `a`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/macros/macro-input-future-proofing.rs b/src/test/ui/macros/macro-input-future-proofing.rs
new file mode 100644
index 0000000..9a5bdb0
--- /dev/null
+++ b/src/test/ui/macros/macro-input-future-proofing.rs
@@ -0,0 +1,23 @@
+#![allow(unused_macros)]
+
+macro_rules! errors_everywhere {
+    ($ty:ty <) => (); //~ ERROR `$ty:ty` is followed by `<`, which is not allowed for `ty`
+    ($ty:ty < foo ,) => (); //~ ERROR `$ty:ty` is followed by `<`, which is not allowed for `ty`
+    ($ty:ty , ) => ();
+    ( ( $ty:ty ) ) => ();
+    ( { $ty:ty } ) => ();
+    ( [ $ty:ty ] ) => ();
+    ($bl:block < ) => ();
+    ($pa:pat >) => (); //~ ERROR `$pa:pat` is followed by `>`, which is not allowed for `pat`
+    ($pa:pat , ) => ();
+    ($pa:pat $pb:pat $ty:ty ,) => ();
+    //~^ ERROR `$pa:pat` is followed by `$pb:pat`, which is not allowed
+    //~^^ ERROR `$pb:pat` is followed by `$ty:ty`, which is not allowed
+    ($($ty:ty)* -) => (); //~ ERROR `$ty:ty` is followed by `-`
+    ($($a:ty, $b:ty)* -) => (); //~ ERROR `$b:ty` is followed by `-`
+    ($($ty:ty)-+) => (); //~ ERROR `$ty:ty` is followed by `-`, which is not allowed for `ty`
+    ( $($a:expr)* $($b:tt)* ) => { };
+    //~^ ERROR `$a:expr` is followed by `$b:tt`, which is not allowed for `expr` fragments
+}
+
+fn main() { }
diff --git a/src/test/ui/macros/macro-input-future-proofing.stderr b/src/test/ui/macros/macro-input-future-proofing.stderr
new file mode 100644
index 0000000..a35f628
--- /dev/null
+++ b/src/test/ui/macros/macro-input-future-proofing.stderr
@@ -0,0 +1,74 @@
+error: `$ty:ty` is followed by `<`, which is not allowed for `ty` fragments
+  --> $DIR/macro-input-future-proofing.rs:4:13
+   |
+LL |     ($ty:ty <) => ();
+   |             ^ not allowed after `ty` fragments
+   |
+   = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
+
+error: `$ty:ty` is followed by `<`, which is not allowed for `ty` fragments
+  --> $DIR/macro-input-future-proofing.rs:5:13
+   |
+LL |     ($ty:ty < foo ,) => ();
+   |             ^ not allowed after `ty` fragments
+   |
+   = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
+
+error: `$pa:pat` is followed by `>`, which is not allowed for `pat` fragments
+  --> $DIR/macro-input-future-proofing.rs:11:14
+   |
+LL |     ($pa:pat >) => ();
+   |              ^ not allowed after `pat` fragments
+   |
+   = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
+
+error: `$pa:pat` is followed by `$pb:pat`, which is not allowed for `pat` fragments
+  --> $DIR/macro-input-future-proofing.rs:13:14
+   |
+LL |     ($pa:pat $pb:pat $ty:ty ,) => ();
+   |              ^^^^^^^ not allowed after `pat` fragments
+   |
+   = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
+
+error: `$pb:pat` is followed by `$ty:ty`, which is not allowed for `pat` fragments
+  --> $DIR/macro-input-future-proofing.rs:13:22
+   |
+LL |     ($pa:pat $pb:pat $ty:ty ,) => ();
+   |                      ^^^^^^ not allowed after `pat` fragments
+   |
+   = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
+
+error: `$ty:ty` is followed by `-`, which is not allowed for `ty` fragments
+  --> $DIR/macro-input-future-proofing.rs:16:17
+   |
+LL |     ($($ty:ty)* -) => ();
+   |                 ^ not allowed after `ty` fragments
+   |
+   = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
+
+error: `$b:ty` is followed by `-`, which is not allowed for `ty` fragments
+  --> $DIR/macro-input-future-proofing.rs:17:23
+   |
+LL |     ($($a:ty, $b:ty)* -) => ();
+   |                       ^ not allowed after `ty` fragments
+   |
+   = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
+
+error: `$ty:ty` is followed by `-`, which is not allowed for `ty` fragments
+  --> $DIR/macro-input-future-proofing.rs:18:7
+   |
+LL |     ($($ty:ty)-+) => ();
+   |       ^^^^^^^^ not allowed after `ty` fragments
+   |
+   = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
+
+error: `$a:expr` is followed by `$b:tt`, which is not allowed for `expr` fragments
+  --> $DIR/macro-input-future-proofing.rs:19:21
+   |
+LL |     ( $($a:expr)* $($b:tt)* ) => { };
+   |                     ^^^^^ not allowed after `expr` fragments
+   |
+   = note: allowed there are: `=>`, `,` or `;`
+
+error: aborting due to 9 previous errors
+
diff --git a/src/test/ui/macros/macro-invalid-fragment-spec.rs b/src/test/ui/macros/macro-invalid-fragment-spec.rs
new file mode 100644
index 0000000..dc4d750
--- /dev/null
+++ b/src/test/ui/macros/macro-invalid-fragment-spec.rs
@@ -0,0 +1,8 @@
+macro_rules! foo(
+    ($x:foo) => ()
+    //~^ ERROR invalid fragment specifier
+);
+
+fn main() {
+    foo!(foo);
+}
diff --git a/src/test/ui/macros/macro-invalid-fragment-spec.stderr b/src/test/ui/macros/macro-invalid-fragment-spec.stderr
new file mode 100644
index 0000000..b047344
--- /dev/null
+++ b/src/test/ui/macros/macro-invalid-fragment-spec.stderr
@@ -0,0 +1,10 @@
+error: invalid fragment specifier `foo`
+  --> $DIR/macro-invalid-fragment-spec.rs:2:6
+   |
+LL |     ($x:foo) => ()
+   |      ^^^^^^
+   |
+   = help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/macros/macro-local-data-key-priv.rs b/src/test/ui/macros/macro-local-data-key-priv.rs
new file mode 100644
index 0000000..2e4f88f
--- /dev/null
+++ b/src/test/ui/macros/macro-local-data-key-priv.rs
@@ -0,0 +1,10 @@
+// check that the local data keys are private by default.
+
+mod bar {
+    thread_local!(static baz: f64 = 0.0);
+}
+
+fn main() {
+    bar::baz.with(|_| ());
+    //~^ ERROR `baz` is private
+}
diff --git a/src/test/ui/macros/macro-local-data-key-priv.stderr b/src/test/ui/macros/macro-local-data-key-priv.stderr
new file mode 100644
index 0000000..9b44421
--- /dev/null
+++ b/src/test/ui/macros/macro-local-data-key-priv.stderr
@@ -0,0 +1,9 @@
+error[E0603]: constant `baz` is private
+  --> $DIR/macro-local-data-key-priv.rs:8:10
+   |
+LL |     bar::baz.with(|_| ());
+   |          ^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0603`.
diff --git a/src/test/ui/macros/macro-match-nonterminal.rs b/src/test/ui/macros/macro-match-nonterminal.rs
new file mode 100644
index 0000000..6d4b32c
--- /dev/null
+++ b/src/test/ui/macros/macro-match-nonterminal.rs
@@ -0,0 +1,5 @@
+macro_rules! test { ($a, $b) => (()); } //~ ERROR missing fragment
+
+fn main() {
+    test!()
+}
diff --git a/src/test/ui/macros/macro-match-nonterminal.stderr b/src/test/ui/macros/macro-match-nonterminal.stderr
new file mode 100644
index 0000000..1de8c5b
--- /dev/null
+++ b/src/test/ui/macros/macro-match-nonterminal.stderr
@@ -0,0 +1,8 @@
+error: missing fragment specifier
+  --> $DIR/macro-match-nonterminal.rs:1:24
+   |
+LL | macro_rules! test { ($a, $b) => (()); }
+   |                        ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/macros/macro-missing-delimiters.rs b/src/test/ui/macros/macro-missing-delimiters.rs
new file mode 100644
index 0000000..290d761
--- /dev/null
+++ b/src/test/ui/macros/macro-missing-delimiters.rs
@@ -0,0 +1,7 @@
+macro_rules! baz(
+    baz => () //~ ERROR invalid macro matcher;
+);
+
+fn main() {
+    baz!(baz);
+}
diff --git a/src/test/ui/macros/macro-missing-delimiters.stderr b/src/test/ui/macros/macro-missing-delimiters.stderr
new file mode 100644
index 0000000..e7c37c8
--- /dev/null
+++ b/src/test/ui/macros/macro-missing-delimiters.stderr
@@ -0,0 +1,8 @@
+error: invalid macro matcher; matchers must be contained in balanced delimiters
+  --> $DIR/macro-missing-delimiters.rs:2:5
+   |
+LL |     baz => ()
+   |     ^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/macros/macro-missing-fragment.rs b/src/test/ui/macros/macro-missing-fragment.rs
new file mode 100644
index 0000000..1d0b088
--- /dev/null
+++ b/src/test/ui/macros/macro-missing-fragment.rs
@@ -0,0 +1,7 @@
+macro_rules! m {
+    ( $( any_token $field_rust_type )* ) => {}; //~ ERROR missing fragment
+}
+
+fn main() {
+    m!();
+}
diff --git a/src/test/ui/macros/macro-missing-fragment.stderr b/src/test/ui/macros/macro-missing-fragment.stderr
new file mode 100644
index 0000000..b7871c0
--- /dev/null
+++ b/src/test/ui/macros/macro-missing-fragment.stderr
@@ -0,0 +1,8 @@
+error: missing fragment specifier
+  --> $DIR/macro-missing-fragment.rs:2:20
+   |
+LL |     ( $( any_token $field_rust_type )* ) => {};
+   |                    ^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/macros/macro-multiple-matcher-bindings.rs b/src/test/ui/macros/macro-multiple-matcher-bindings.rs
new file mode 100644
index 0000000..23d5667
--- /dev/null
+++ b/src/test/ui/macros/macro-multiple-matcher-bindings.rs
@@ -0,0 +1,26 @@
+// Test that duplicate matcher binding names are caught at declaration time, rather than at macro
+// invocation time.
+//
+// FIXME(mark-i-m): Update this when it becomes a hard error.
+
+// compile-pass
+
+#![allow(unused_macros)]
+#![warn(duplicate_matcher_binding_name)]
+
+macro_rules! foo1 {
+    ($a:ident, $a:ident) => {}; //~WARNING duplicate matcher binding
+    ($a:ident, $a:path) => {};  //~WARNING duplicate matcher binding
+}
+
+macro_rules! foo2 {
+    ($a:ident) => {}; // OK
+    ($a:path) => {};  // OK
+}
+
+macro_rules! foo3 {
+    ($a:ident, $($a:ident),*) => {}; //~WARNING duplicate matcher binding
+    ($($a:ident)+ # $($($a:path),+);*) => {}; //~WARNING duplicate matcher binding
+}
+
+fn main() {}
diff --git a/src/test/ui/macros/macro-multiple-matcher-bindings.stderr b/src/test/ui/macros/macro-multiple-matcher-bindings.stderr
new file mode 100644
index 0000000..f7970db
--- /dev/null
+++ b/src/test/ui/macros/macro-multiple-matcher-bindings.stderr
@@ -0,0 +1,41 @@
+warning: duplicate matcher binding
+  --> $DIR/macro-multiple-matcher-bindings.rs:12:6
+   |
+LL |     ($a:ident, $a:ident) => {};
+   |      ^^^^^^^^  ^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/macro-multiple-matcher-bindings.rs:9:9
+   |
+LL | #![warn(duplicate_matcher_binding_name)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #57593 <https://github.com/rust-lang/rust/issues/57593>
+
+warning: duplicate matcher binding
+  --> $DIR/macro-multiple-matcher-bindings.rs:13:6
+   |
+LL |     ($a:ident, $a:path) => {};
+   |      ^^^^^^^^  ^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #57593 <https://github.com/rust-lang/rust/issues/57593>
+
+warning: duplicate matcher binding
+  --> $DIR/macro-multiple-matcher-bindings.rs:22:6
+   |
+LL |     ($a:ident, $($a:ident),*) => {};
+   |      ^^^^^^^^    ^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #57593 <https://github.com/rust-lang/rust/issues/57593>
+
+warning: duplicate matcher binding
+  --> $DIR/macro-multiple-matcher-bindings.rs:23:8
+   |
+LL |     ($($a:ident)+ # $($($a:path),+);*) => {};
+   |        ^^^^^^^^         ^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #57593 <https://github.com/rust-lang/rust/issues/57593>
+
diff --git a/src/test/ui/macros/macro-name-typo.rs b/src/test/ui/macros/macro-name-typo.rs
new file mode 100644
index 0000000..1ddc419
--- /dev/null
+++ b/src/test/ui/macros/macro-name-typo.rs
@@ -0,0 +1,3 @@
+fn main() {
+    printlx!("oh noes!"); //~ ERROR cannot find
+}
diff --git a/src/test/ui/macros/macro-name-typo.stderr b/src/test/ui/macros/macro-name-typo.stderr
new file mode 100644
index 0000000..a8930f24
--- /dev/null
+++ b/src/test/ui/macros/macro-name-typo.stderr
@@ -0,0 +1,8 @@
+error: cannot find macro `printlx!` in this scope
+  --> $DIR/macro-name-typo.rs:2:5
+   |
+LL |     printlx!("oh noes!");
+   |     ^^^^^^^ help: you could try the macro: `println`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/macros/macro-non-lifetime.rs b/src/test/ui/macros/macro-non-lifetime.rs
new file mode 100644
index 0000000..c74aaf4
--- /dev/null
+++ b/src/test/ui/macros/macro-non-lifetime.rs
@@ -0,0 +1,10 @@
+// Test for issue #50381: non-lifetime passed to :lifetime.
+
+#![feature(macro_lifetime_matcher)]
+
+macro_rules! m { ($x:lifetime) => { } }
+
+fn main() {
+    m!(a);
+    //~^ ERROR no rules expected the token `a`
+}
diff --git a/src/test/ui/macros/macro-non-lifetime.stderr b/src/test/ui/macros/macro-non-lifetime.stderr
new file mode 100644
index 0000000..2cf1a79
--- /dev/null
+++ b/src/test/ui/macros/macro-non-lifetime.stderr
@@ -0,0 +1,11 @@
+error: no rules expected the token `a`
+  --> $DIR/macro-non-lifetime.rs:8:8
+   |
+LL | macro_rules! m { ($x:lifetime) => { } }
+   | -------------- when calling this macro
+...
+LL |     m!(a);
+   |        ^ no rules expected this token in macro call
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/macros/macro-outer-attributes.rs b/src/test/ui/macros/macro-outer-attributes.rs
new file mode 100644
index 0000000..aa70060
--- /dev/null
+++ b/src/test/ui/macros/macro-outer-attributes.rs
@@ -0,0 +1,20 @@
+#![feature(custom_attribute)]
+
+macro_rules! test { ($nm:ident,
+                     #[$a:meta],
+                     $i:item) => (mod $nm { #[$a] $i }); }
+
+test!(a,
+      #[cfg(qux)],
+      pub fn bar() { });
+
+test!(b,
+      #[cfg(not(qux))],
+      pub fn bar() { });
+
+// test1!(#[bar])
+#[qux]
+fn main() {
+    a::bar(); //~ ERROR cannot find function `bar` in module `a`
+    b::bar();
+}
diff --git a/src/test/ui/macros/macro-outer-attributes.stderr b/src/test/ui/macros/macro-outer-attributes.stderr
new file mode 100644
index 0000000..838333b
--- /dev/null
+++ b/src/test/ui/macros/macro-outer-attributes.stderr
@@ -0,0 +1,13 @@
+error[E0425]: cannot find function `bar` in module `a`
+  --> $DIR/macro-outer-attributes.rs:18:8
+   |
+LL |     a::bar();
+   |        ^^^ not found in `a`
+help: possible candidate is found in another module, you can import it into scope
+   |
+LL | use b::bar;
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/macros/macro-parameter-span.rs b/src/test/ui/macros/macro-parameter-span.rs
new file mode 100644
index 0000000..5609f84
--- /dev/null
+++ b/src/test/ui/macros/macro-parameter-span.rs
@@ -0,0 +1,13 @@
+macro_rules! foo {
+    ($id: ident) => {
+        $id
+    }
+}
+
+// Testing that the error span points to the parameter 'x' in the callsite,
+// not to the macro variable '$id'
+fn main() {
+    foo!(
+        x //~ ERROR cannot find value `x` in this scope
+        );
+}
diff --git a/src/test/ui/macros/macro-parameter-span.stderr b/src/test/ui/macros/macro-parameter-span.stderr
new file mode 100644
index 0000000..24e3e89
--- /dev/null
+++ b/src/test/ui/macros/macro-parameter-span.stderr
@@ -0,0 +1,9 @@
+error[E0425]: cannot find value `x` in this scope
+  --> $DIR/macro-parameter-span.rs:11:9
+   |
+LL |         x
+   |         ^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/macros/macro-path-prelude-fail-1.rs b/src/test/ui/macros/macro-path-prelude-fail-1.rs
new file mode 100644
index 0000000..354c2bf
--- /dev/null
+++ b/src/test/ui/macros/macro-path-prelude-fail-1.rs
@@ -0,0 +1,10 @@
+#![feature(extern_prelude)]
+
+mod m {
+    fn check() {
+        Vec::clone!(); //~ ERROR failed to resolve: not a module `Vec`
+        u8::clone!(); //~ ERROR failed to resolve: not a module `u8`
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/macros/macro-path-prelude-fail-1.stderr b/src/test/ui/macros/macro-path-prelude-fail-1.stderr
new file mode 100644
index 0000000..551d2fe
--- /dev/null
+++ b/src/test/ui/macros/macro-path-prelude-fail-1.stderr
@@ -0,0 +1,15 @@
+error[E0433]: failed to resolve: not a module `Vec`
+  --> $DIR/macro-path-prelude-fail-1.rs:5:9
+   |
+LL |         Vec::clone!();
+   |         ^^^ not a module `Vec`
+
+error[E0433]: failed to resolve: not a module `u8`
+  --> $DIR/macro-path-prelude-fail-1.rs:6:9
+   |
+LL |         u8::clone!();
+   |         ^^ not a module `u8`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/macros/macro-path-prelude-fail-2.rs b/src/test/ui/macros/macro-path-prelude-fail-2.rs
new file mode 100644
index 0000000..816a3c4
--- /dev/null
+++ b/src/test/ui/macros/macro-path-prelude-fail-2.rs
@@ -0,0 +1,7 @@
+mod m {
+    fn check() {
+        Result::Ok!(); //~ ERROR failed to resolve: partially resolved path in a macro
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/macros/macro-path-prelude-fail-2.stderr b/src/test/ui/macros/macro-path-prelude-fail-2.stderr
new file mode 100644
index 0000000..9574b7a
--- /dev/null
+++ b/src/test/ui/macros/macro-path-prelude-fail-2.stderr
@@ -0,0 +1,9 @@
+error[E0433]: failed to resolve: partially resolved path in a macro
+  --> $DIR/macro-path-prelude-fail-2.rs:3:9
+   |
+LL |         Result::Ok!();
+   |         ^^^^^^^^^^ partially resolved path in a macro
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/macros/macro-path-prelude-fail-3.rs b/src/test/ui/macros/macro-path-prelude-fail-3.rs
new file mode 100644
index 0000000..597053d
--- /dev/null
+++ b/src/test/ui/macros/macro-path-prelude-fail-3.rs
@@ -0,0 +1,3 @@
+fn main() {
+    inline!(); //~ ERROR cannot find macro `inline!` in this scope
+}
diff --git a/src/test/ui/macros/macro-path-prelude-fail-3.stderr b/src/test/ui/macros/macro-path-prelude-fail-3.stderr
new file mode 100644
index 0000000..7eeddb8
--- /dev/null
+++ b/src/test/ui/macros/macro-path-prelude-fail-3.stderr
@@ -0,0 +1,8 @@
+error: cannot find macro `inline!` in this scope
+  --> $DIR/macro-path-prelude-fail-3.rs:2:5
+   |
+LL |     inline!();
+   |     ^^^^^^ help: you could try the macro: `line`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/macros/macro-path-prelude-fail-4.rs b/src/test/ui/macros/macro-path-prelude-fail-4.rs
new file mode 100644
index 0000000..283427b
--- /dev/null
+++ b/src/test/ui/macros/macro-path-prelude-fail-4.rs
@@ -0,0 +1,4 @@
+#[derive(inline)] //~ ERROR expected a macro, found built-in attribute
+struct S;
+
+fn main() {}
diff --git a/src/test/ui/macros/macro-path-prelude-fail-4.stderr b/src/test/ui/macros/macro-path-prelude-fail-4.stderr
new file mode 100644
index 0000000..f08445e
--- /dev/null
+++ b/src/test/ui/macros/macro-path-prelude-fail-4.stderr
@@ -0,0 +1,8 @@
+error: expected a macro, found built-in attribute
+  --> $DIR/macro-path-prelude-fail-4.rs:1:10
+   |
+LL | #[derive(inline)]
+   |          ^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/macros/macro-path-prelude-pass.rs b/src/test/ui/macros/macro-path-prelude-pass.rs
new file mode 100644
index 0000000..3d35d53
--- /dev/null
+++ b/src/test/ui/macros/macro-path-prelude-pass.rs
@@ -0,0 +1,11 @@
+// compile-pass
+
+#![feature(extern_prelude)]
+
+mod m {
+    fn check() {
+        std::panic!(); // OK
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/macros/macro-path-prelude-pass.stderr b/src/test/ui/macros/macro-path-prelude-pass.stderr
new file mode 100644
index 0000000..3744e01
--- /dev/null
+++ b/src/test/ui/macros/macro-path-prelude-pass.stderr
@@ -0,0 +1,8 @@
+warning: the feature `extern_prelude` has been stable since 1.30.0 and no longer requires an attribute to enable
+  --> $DIR/macro-path-prelude-pass.rs:3:12
+   |
+LL | #![feature(extern_prelude)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: #[warn(stable_features)] on by default
+
diff --git a/src/test/ui/macros/macro-path-prelude-shadowing.rs b/src/test/ui/macros/macro-path-prelude-shadowing.rs
new file mode 100644
index 0000000..600b55c
--- /dev/null
+++ b/src/test/ui/macros/macro-path-prelude-shadowing.rs
@@ -0,0 +1,33 @@
+// aux-build:macro-in-other-crate.rs
+
+#![feature(decl_macro, extern_prelude)]
+
+macro_rules! add_macro_expanded_things_to_macro_prelude {() => {
+    #[macro_use]
+    extern crate macro_in_other_crate;
+}}
+
+add_macro_expanded_things_to_macro_prelude!();
+
+mod m1 {
+    fn check() {
+        inline!(); // OK. Theoretically ambiguous, but we do not consider built-in attributes
+                   // as candidates for non-attribute macro invocations to avoid regressions
+                   // on stable channel
+    }
+}
+
+mod m2 {
+    pub mod std {
+        pub macro panic() {}
+    }
+}
+
+mod m3 {
+    use m2::*; // glob-import user-defined `std`
+    fn check() {
+        std::panic!(); //~ ERROR `std` is ambiguous
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/macros/macro-path-prelude-shadowing.stderr b/src/test/ui/macros/macro-path-prelude-shadowing.stderr
new file mode 100644
index 0000000..e7b381d
--- /dev/null
+++ b/src/test/ui/macros/macro-path-prelude-shadowing.stderr
@@ -0,0 +1,18 @@
+error[E0659]: `std` is ambiguous (glob import vs any other name from outer scope during import/macro resolution)
+  --> $DIR/macro-path-prelude-shadowing.rs:29:9
+   |
+LL |         std::panic!();
+   |         ^^^ ambiguous name
+   |
+   = note: `std` could refer to a built-in extern crate
+note: `std` could also refer to the module imported here
+  --> $DIR/macro-path-prelude-shadowing.rs:27:9
+   |
+LL |     use m2::*; // glob-import user-defined `std`
+   |         ^^^^^
+   = help: consider adding an explicit import of `std` to disambiguate
+   = help: or use `self::std` to refer to this module unambiguously
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0659`.
diff --git a/src/test/ui/macros/macro-reexport-removed.rs b/src/test/ui/macros/macro-reexport-removed.rs
new file mode 100644
index 0000000..fb33794
--- /dev/null
+++ b/src/test/ui/macros/macro-reexport-removed.rs
@@ -0,0 +1,8 @@
+// aux-build:two_macros.rs
+
+#![feature(macro_reexport)] //~ ERROR feature has been removed
+
+#[macro_reexport(macro_one)] //~ ERROR attribute `macro_reexport` is currently unknown
+extern crate two_macros;
+
+fn main() {}
diff --git a/src/test/ui/macros/macro-reexport-removed.stderr b/src/test/ui/macros/macro-reexport-removed.stderr
new file mode 100644
index 0000000..3029529
--- /dev/null
+++ b/src/test/ui/macros/macro-reexport-removed.stderr
@@ -0,0 +1,24 @@
+error[E0557]: feature has been removed
+  --> $DIR/macro-reexport-removed.rs:3:12
+   |
+LL | #![feature(macro_reexport)]
+   |            ^^^^^^^^^^^^^^
+   |
+note: subsumed by `pub use`
+  --> $DIR/macro-reexport-removed.rs:3:12
+   |
+LL | #![feature(macro_reexport)]
+   |            ^^^^^^^^^^^^^^
+
+error[E0658]: The attribute `macro_reexport` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/macro-reexport-removed.rs:5:3
+   |
+LL | #[macro_reexport(macro_one)]
+   |   ^^^^^^^^^^^^^^ help: a built-in attribute with a similar name exists: `macro_export`
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0557, E0658.
+For more information about an error, try `rustc --explain E0557`.
diff --git a/src/test/ui/macros/macro-shadowing-relaxed.rs b/src/test/ui/macros/macro-shadowing-relaxed.rs
new file mode 100644
index 0000000..2477226
--- /dev/null
+++ b/src/test/ui/macros/macro-shadowing-relaxed.rs
@@ -0,0 +1,25 @@
+// compile-pass
+// aux-build:macro-in-other-crate.rs
+
+#![feature(decl_macro)]
+
+macro_rules! my_include {() => {
+    // Outer
+    macro m() {}
+    #[macro_use(from_prelude)] extern crate macro_in_other_crate;
+
+    fn inner() {
+        // Inner
+        macro m() {}
+        macro_rules! from_prelude { () => {} }
+
+        // OK, both `m` and `from_prelude` are macro-expanded,
+        // but no more macro-expanded than their counterpart from outer scope.
+        m!();
+        from_prelude!();
+    }
+}}
+
+my_include!();
+
+fn main() {}
diff --git a/src/test/ui/macros/macro-shadowing.rs b/src/test/ui/macros/macro-shadowing.rs
new file mode 100644
index 0000000..7f956dd
--- /dev/null
+++ b/src/test/ui/macros/macro-shadowing.rs
@@ -0,0 +1,26 @@
+// aux-build:two_macros.rs
+
+#![allow(unused_macros)]
+
+macro_rules! foo { () => {} }
+macro_rules! macro_one { () => {} }
+#[macro_use(macro_two)] extern crate two_macros;
+
+macro_rules! m1 { () => {
+    macro_rules! foo { () => {} }
+
+    #[macro_use] //~ ERROR `macro_two` is already in scope
+    extern crate two_macros as __;
+}}
+m1!();
+
+foo!(); //~ ERROR `foo` is ambiguous
+
+macro_rules! m2 { () => {
+    macro_rules! foo { () => {} }
+    foo!();
+}}
+m2!();
+//^ Since `foo` is not used outside this expansion, it is not a shadowing error.
+
+fn main() {}
diff --git a/src/test/ui/macros/macro-shadowing.stderr b/src/test/ui/macros/macro-shadowing.stderr
new file mode 100644
index 0000000..033e12a
--- /dev/null
+++ b/src/test/ui/macros/macro-shadowing.stderr
@@ -0,0 +1,34 @@
+error: `macro_two` is already in scope
+  --> $DIR/macro-shadowing.rs:12:5
+   |
+LL |     #[macro_use]
+   |     ^^^^^^^^^^^^
+...
+LL | m1!();
+   | ------ in this macro invocation
+   |
+   = note: macro-expanded `#[macro_use]`s may not shadow existing macros (see RFC 1560)
+
+error[E0659]: `foo` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
+  --> $DIR/macro-shadowing.rs:17:1
+   |
+LL | foo!();
+   | ^^^ ambiguous name
+   |
+note: `foo` could refer to the macro defined here
+  --> $DIR/macro-shadowing.rs:10:5
+   |
+LL |     macro_rules! foo { () => {} }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | m1!();
+   | ------ in this macro invocation
+note: `foo` could also refer to the macro defined here
+  --> $DIR/macro-shadowing.rs:5:1
+   |
+LL | macro_rules! foo { () => {} }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0659`.
diff --git a/src/test/ui/macros/macro-stability.rs b/src/test/ui/macros/macro-stability.rs
new file mode 100644
index 0000000..7d1ee6a
--- /dev/null
+++ b/src/test/ui/macros/macro-stability.rs
@@ -0,0 +1,12 @@
+// aux-build:unstable-macros.rs
+
+#![feature(staged_api)]
+#[macro_use] extern crate unstable_macros;
+
+#[unstable(feature = "local_unstable", issue = "0")]
+macro_rules! local_unstable { () => () }
+
+fn main() {
+    local_unstable!();
+    unstable_macro!(); //~ ERROR: macro unstable_macro! is unstable
+}
diff --git a/src/test/ui/macros/macro-stability.stderr b/src/test/ui/macros/macro-stability.stderr
new file mode 100644
index 0000000..a0e0c35
--- /dev/null
+++ b/src/test/ui/macros/macro-stability.stderr
@@ -0,0 +1,11 @@
+error[E0658]: macro unstable_macro! is unstable
+  --> $DIR/macro-stability.rs:11:5
+   |
+LL |     unstable_macro!();
+   |     ^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_macros)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/macros/macro-stmt-matchers.rs b/src/test/ui/macros/macro-stmt-matchers.rs
new file mode 100644
index 0000000..6e53eb0
--- /dev/null
+++ b/src/test/ui/macros/macro-stmt-matchers.rs
@@ -0,0 +1,7 @@
+// compile-pass
+
+
+fn main() {
+    macro_rules! m { ($s:stmt;) => { $s } }
+    m!(vec![].push(0););
+}
diff --git a/src/test/ui/macros/macro-tt-matchers.rs b/src/test/ui/macros/macro-tt-matchers.rs
new file mode 100644
index 0000000..17df72f
--- /dev/null
+++ b/src/test/ui/macros/macro-tt-matchers.rs
@@ -0,0 +1,11 @@
+// compile-pass
+#![allow(dead_code)]
+
+macro_rules! foo {
+    ($x:tt) => (type Alias = $x<i32>;)
+}
+
+foo!(Box);
+
+
+fn main() {}
diff --git a/src/test/ui/macros/macro-use-bad-args-1.rs b/src/test/ui/macros/macro-use-bad-args-1.rs
new file mode 100644
index 0000000..061c5cc
--- /dev/null
+++ b/src/test/ui/macros/macro-use-bad-args-1.rs
@@ -0,0 +1,7 @@
+#![no_std]
+
+#[allow(unused_extern_crates)]
+#[macro_use(foo(bar))]  //~ ERROR bad macro import
+extern crate std;
+
+fn main() {}
diff --git a/src/test/ui/macros/macro-use-bad-args-1.stderr b/src/test/ui/macros/macro-use-bad-args-1.stderr
new file mode 100644
index 0000000..f403c8a
--- /dev/null
+++ b/src/test/ui/macros/macro-use-bad-args-1.stderr
@@ -0,0 +1,9 @@
+error[E0466]: bad macro import
+  --> $DIR/macro-use-bad-args-1.rs:4:13
+   |
+LL | #[macro_use(foo(bar))]
+   |             ^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0466`.
diff --git a/src/test/ui/macros/macro-use-bad-args-2.rs b/src/test/ui/macros/macro-use-bad-args-2.rs
new file mode 100644
index 0000000..cb231ce
--- /dev/null
+++ b/src/test/ui/macros/macro-use-bad-args-2.rs
@@ -0,0 +1,7 @@
+#![no_std]
+
+#[allow(unused_extern_crates)]
+#[macro_use(foo="bar")]  //~ ERROR bad macro import
+extern crate std;
+
+fn main() {}
diff --git a/src/test/ui/macros/macro-use-bad-args-2.stderr b/src/test/ui/macros/macro-use-bad-args-2.stderr
new file mode 100644
index 0000000..93617ed
--- /dev/null
+++ b/src/test/ui/macros/macro-use-bad-args-2.stderr
@@ -0,0 +1,9 @@
+error[E0466]: bad macro import
+  --> $DIR/macro-use-bad-args-2.rs:4:13
+   |
+LL | #[macro_use(foo="bar")]
+   |             ^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0466`.
diff --git a/src/test/ui/macros/macro-use-scope.rs b/src/test/ui/macros/macro-use-scope.rs
new file mode 100644
index 0000000..03d57d2
--- /dev/null
+++ b/src/test/ui/macros/macro-use-scope.rs
@@ -0,0 +1,22 @@
+// aux-build:two_macros.rs
+
+// compile-pass
+#![allow(unused)]
+
+fn f() {
+    let _ = macro_one!();
+}
+#[macro_use(macro_one)] // Check that this macro is usable in the above function
+extern crate two_macros;
+
+fn g() {
+    macro_two!();
+}
+macro_rules! m { () => {
+    #[macro_use(macro_two)] // Check that this macro is usable in the above function
+    extern crate two_macros as _two_macros;
+} }
+m!();
+
+
+fn main() {}
diff --git a/src/test/ui/macros/macro-use-undef.rs b/src/test/ui/macros/macro-use-undef.rs
new file mode 100644
index 0000000..ae3054e
--- /dev/null
+++ b/src/test/ui/macros/macro-use-undef.rs
@@ -0,0 +1,8 @@
+// aux-build:two_macros.rs
+
+#[macro_use(macro_two, no_way)] //~ ERROR imported macro not found
+extern crate two_macros;
+
+pub fn main() {
+    macro_two!();
+}
diff --git a/src/test/ui/macros/macro-use-undef.stderr b/src/test/ui/macros/macro-use-undef.stderr
new file mode 100644
index 0000000..85b86e2
--- /dev/null
+++ b/src/test/ui/macros/macro-use-undef.stderr
@@ -0,0 +1,9 @@
+error[E0469]: imported macro not found
+  --> $DIR/macro-use-undef.rs:3:24
+   |
+LL | #[macro_use(macro_two, no_way)]
+   |                        ^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0469`.
diff --git a/src/test/ui/macros/macro-use-wrong-name.rs b/src/test/ui/macros/macro-use-wrong-name.rs
new file mode 100644
index 0000000..d142b58
--- /dev/null
+++ b/src/test/ui/macros/macro-use-wrong-name.rs
@@ -0,0 +1,9 @@
+// aux-build:two_macros.rs
+
+#[macro_use(macro_one)]
+extern crate two_macros;
+
+pub fn main() {
+    macro_two!();
+    //~^ ERROR cannot find macro
+}
diff --git a/src/test/ui/macros/macro-use-wrong-name.stderr b/src/test/ui/macros/macro-use-wrong-name.stderr
new file mode 100644
index 0000000..d178d4e
--- /dev/null
+++ b/src/test/ui/macros/macro-use-wrong-name.stderr
@@ -0,0 +1,8 @@
+error: cannot find macro `macro_two!` in this scope
+  --> $DIR/macro-use-wrong-name.rs:7:5
+   |
+LL |     macro_two!();
+   |     ^^^^^^^^^ help: you could try the macro: `macro_one`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/macros/macro_path_as_generic_bound.rs b/src/test/ui/macros/macro_path_as_generic_bound.rs
new file mode 100644
index 0000000..663f856
--- /dev/null
+++ b/src/test/ui/macros/macro_path_as_generic_bound.rs
@@ -0,0 +1,9 @@
+trait Foo {}
+
+macro_rules! foo(($t:path) => {
+    impl<T: $t> Foo for T {}
+});
+
+foo!(m::m2::A); //~ ERROR failed to resolve
+
+fn main() {}
diff --git a/src/test/ui/macros/macro_path_as_generic_bound.stderr b/src/test/ui/macros/macro_path_as_generic_bound.stderr
new file mode 100644
index 0000000..48c3357
--- /dev/null
+++ b/src/test/ui/macros/macro_path_as_generic_bound.stderr
@@ -0,0 +1,9 @@
+error[E0433]: failed to resolve: use of undeclared type or module `m`
+  --> $DIR/macro_path_as_generic_bound.rs:7:6
+   |
+LL | foo!(m::m2::A);
+   |      ^ use of undeclared type or module `m`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/macros/macro_undefined.rs b/src/test/ui/macros/macro_undefined.rs
new file mode 100644
index 0000000..6ca1eb5
--- /dev/null
+++ b/src/test/ui/macros/macro_undefined.rs
@@ -0,0 +1,13 @@
+// Test macro_undefined issue
+
+mod m {
+    #[macro_export]
+    macro_rules! kl {
+        () => ()
+    }
+}
+
+fn main() {
+    k!(); //~ ERROR cannot find
+    kl!();
+}
diff --git a/src/test/ui/macros/macro_undefined.stderr b/src/test/ui/macros/macro_undefined.stderr
new file mode 100644
index 0000000..b516f91
--- /dev/null
+++ b/src/test/ui/macros/macro_undefined.stderr
@@ -0,0 +1,8 @@
+error: cannot find macro `k!` in this scope
+  --> $DIR/macro_undefined.rs:11:5
+   |
+LL |     k!();
+   |     ^ help: you could try the macro: `kl`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/macros/macros-in-extern.rs b/src/test/ui/macros/macros-in-extern.rs
new file mode 100644
index 0000000..bba8b15
--- /dev/null
+++ b/src/test/ui/macros/macros-in-extern.rs
@@ -0,0 +1,32 @@
+// ignore-wasm32
+
+#![feature(decl_macro)]
+
+macro_rules! returns_isize(
+    ($ident:ident) => (
+        fn $ident() -> isize;
+    )
+);
+
+macro takes_u32_returns_u32($ident:ident) {
+    fn $ident (arg: u32) -> u32;
+}
+
+macro_rules! emits_nothing(
+    () => ()
+);
+
+fn main() {
+    assert_eq!(unsafe { rust_get_test_int() }, 0isize);
+    assert_eq!(unsafe { rust_dbg_extern_identity_u32(0xDEADBEEF) }, 0xDEADBEEFu32);
+}
+
+#[link(name = "rust_test_helpers", kind = "static")]
+extern {
+    returns_isize!(rust_get_test_int);
+    //~^ ERROR macro invocations in `extern {}` blocks are experimental
+    takes_u32_returns_u32!(rust_dbg_extern_identity_u32);
+    //~^ ERROR macro invocations in `extern {}` blocks are experimental
+    emits_nothing!();
+    //~^ ERROR macro invocations in `extern {}` blocks are experimental
+}
diff --git a/src/test/ui/macros/macros-in-extern.stderr b/src/test/ui/macros/macros-in-extern.stderr
new file mode 100644
index 0000000..1d0c287
--- /dev/null
+++ b/src/test/ui/macros/macros-in-extern.stderr
@@ -0,0 +1,27 @@
+error[E0658]: macro invocations in `extern {}` blocks are experimental (see issue #49476)
+  --> $DIR/macros-in-extern.rs:26:5
+   |
+LL |     returns_isize!(rust_get_test_int);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(macros_in_extern)] to the crate attributes to enable
+
+error[E0658]: macro invocations in `extern {}` blocks are experimental (see issue #49476)
+  --> $DIR/macros-in-extern.rs:28:5
+   |
+LL |     takes_u32_returns_u32!(rust_dbg_extern_identity_u32);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(macros_in_extern)] to the crate attributes to enable
+
+error[E0658]: macro invocations in `extern {}` blocks are experimental (see issue #49476)
+  --> $DIR/macros-in-extern.rs:30:5
+   |
+LL |     emits_nothing!();
+   |     ^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(macros_in_extern)] to the crate attributes to enable
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/macros/macros-nonfatal-errors.rs b/src/test/ui/macros/macros-nonfatal-errors.rs
new file mode 100644
index 0000000..1eb82a2
--- /dev/null
+++ b/src/test/ui/macros/macros-nonfatal-errors.rs
@@ -0,0 +1,32 @@
+// normalize-stderr-test: "existed:.*\(" -> "existed: $$FILE_NOT_FOUND_MSG ("
+
+// test that errors in a (selection) of macros don't kill compilation
+// immediately, so that we get more errors listed at a time.
+
+#![feature(asm)]
+#![feature(trace_macros, concat_idents)]
+
+#[derive(Default)] //~ ERROR
+enum OrDeriveThis {}
+
+fn main() {
+    asm!(invalid); //~ ERROR
+
+    concat_idents!("not", "idents"); //~ ERROR
+
+    option_env!(invalid); //~ ERROR
+    env!(invalid); //~ ERROR
+    env!(foo, abr, baz); //~ ERROR
+    env!("RUST_HOPEFULLY_THIS_DOESNT_EXIST"); //~ ERROR
+
+    format!(invalid); //~ ERROR
+
+    include!(invalid); //~ ERROR
+
+    include_str!(invalid); //~ ERROR
+    include_str!("i'd be quite surprised if a file with this name existed"); //~ ERROR
+    include_bytes!(invalid); //~ ERROR
+    include_bytes!("i'd be quite surprised if a file with this name existed"); //~ ERROR
+
+    trace_macros!(invalid); //~ ERROR
+}
diff --git a/src/test/ui/macros/macros-nonfatal-errors.stderr b/src/test/ui/macros/macros-nonfatal-errors.stderr
new file mode 100644
index 0000000..8a8455c
--- /dev/null
+++ b/src/test/ui/macros/macros-nonfatal-errors.stderr
@@ -0,0 +1,91 @@
+error[E0665]: `Default` cannot be derived for enums, only structs
+  --> $DIR/macros-nonfatal-errors.rs:9:10
+   |
+LL | #[derive(Default)]
+   |          ^^^^^^^
+
+error: inline assembly must be a string literal
+  --> $DIR/macros-nonfatal-errors.rs:13:10
+   |
+LL |     asm!(invalid);
+   |          ^^^^^^^
+
+error: concat_idents! requires ident args.
+  --> $DIR/macros-nonfatal-errors.rs:15:5
+   |
+LL |     concat_idents!("not", "idents");
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: argument must be a string literal
+  --> $DIR/macros-nonfatal-errors.rs:17:17
+   |
+LL |     option_env!(invalid);
+   |                 ^^^^^^^
+
+error: expected string literal
+  --> $DIR/macros-nonfatal-errors.rs:18:10
+   |
+LL |     env!(invalid);
+   |          ^^^^^^^
+
+error: expected string literal
+  --> $DIR/macros-nonfatal-errors.rs:19:10
+   |
+LL |     env!(foo, abr, baz);
+   |          ^^^
+
+error: environment variable `RUST_HOPEFULLY_THIS_DOESNT_EXIST` not defined
+  --> $DIR/macros-nonfatal-errors.rs:20:5
+   |
+LL |     env!("RUST_HOPEFULLY_THIS_DOESNT_EXIST");
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: format argument must be a string literal
+  --> $DIR/macros-nonfatal-errors.rs:22:13
+   |
+LL |     format!(invalid);
+   |             ^^^^^^^
+help: you might be missing a string literal to format with
+   |
+LL |     format!("{}", invalid);
+   |             ^^^^^
+
+error: argument must be a string literal
+  --> $DIR/macros-nonfatal-errors.rs:24:14
+   |
+LL |     include!(invalid);
+   |              ^^^^^^^
+
+error: argument must be a string literal
+  --> $DIR/macros-nonfatal-errors.rs:26:18
+   |
+LL |     include_str!(invalid);
+   |                  ^^^^^^^
+
+error: couldn't read $DIR/i'd be quite surprised if a file with this name existed: $FILE_NOT_FOUND_MSG (os error 2)
+  --> $DIR/macros-nonfatal-errors.rs:27:5
+   |
+LL |     include_str!("i'd be quite surprised if a file with this name existed");
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: argument must be a string literal
+  --> $DIR/macros-nonfatal-errors.rs:28:20
+   |
+LL |     include_bytes!(invalid);
+   |                    ^^^^^^^
+
+error: couldn't read $DIR/i'd be quite surprised if a file with this name existed: $FILE_NOT_FOUND_MSG (os error 2)
+  --> $DIR/macros-nonfatal-errors.rs:29:5
+   |
+LL |     include_bytes!("i'd be quite surprised if a file with this name existed");
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: trace_macros! accepts only `true` or `false`
+  --> $DIR/macros-nonfatal-errors.rs:31:5
+   |
+LL |     trace_macros!(invalid);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 14 previous errors
+
+For more information about this error, try `rustc --explain E0665`.
diff --git a/src/test/ui/macros/meta-item-absolute-path.rs b/src/test/ui/macros/meta-item-absolute-path.rs
new file mode 100644
index 0000000..14d23be
--- /dev/null
+++ b/src/test/ui/macros/meta-item-absolute-path.rs
@@ -0,0 +1,4 @@
+#[derive(::Absolute)] //~ ERROR failed to resolve
+struct S;
+
+fn main() {}
diff --git a/src/test/ui/macros/meta-item-absolute-path.stderr b/src/test/ui/macros/meta-item-absolute-path.stderr
new file mode 100644
index 0000000..23933f7
--- /dev/null
+++ b/src/test/ui/macros/meta-item-absolute-path.stderr
@@ -0,0 +1,9 @@
+error[E0433]: failed to resolve: maybe a missing `extern crate Absolute;`?
+  --> $DIR/meta-item-absolute-path.rs:1:12
+   |
+LL | #[derive(::Absolute)]
+   |            ^^^^^^^^ maybe a missing `extern crate Absolute;`?
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/macros/missing-comma.rs b/src/test/ui/macros/missing-comma.rs
new file mode 100644
index 0000000..2b411ab
--- /dev/null
+++ b/src/test/ui/macros/missing-comma.rs
@@ -0,0 +1,27 @@
+macro_rules! foo {
+    ($a:ident) => ();
+    ($a:ident, $b:ident) => ();
+    ($a:ident, $b:ident, $c:ident) => ();
+    ($a:ident, $b:ident, $c:ident, $d:ident) => ();
+    ($a:ident, $b:ident, $c:ident, $d:ident, $e:ident) => ();
+}
+
+macro_rules! bar {
+    ($lvl:expr, $($arg:tt)+) => {}
+}
+
+
+fn main() {
+    println!("{}" a);
+    //~^ ERROR expected token: `,`
+    foo!(a b);
+    //~^ ERROR no rules expected the token `b`
+    foo!(a, b, c, d e);
+    //~^ ERROR no rules expected the token `e`
+    foo!(a, b, c d, e);
+    //~^ ERROR no rules expected the token `d`
+    foo!(a, b, c d e);
+    //~^ ERROR no rules expected the token `d`
+    bar!(Level::Error, );
+    //~^ ERROR unexpected end of macro invocation
+}
diff --git a/src/test/ui/macros/missing-comma.stderr b/src/test/ui/macros/missing-comma.stderr
new file mode 100644
index 0000000..424fefd
--- /dev/null
+++ b/src/test/ui/macros/missing-comma.stderr
@@ -0,0 +1,59 @@
+error: expected token: `,`
+  --> $DIR/missing-comma.rs:15:19
+   |
+LL |     println!("{}" a);
+   |                   ^
+
+error: no rules expected the token `b`
+  --> $DIR/missing-comma.rs:17:12
+   |
+LL | macro_rules! foo {
+   | ---------------- when calling this macro
+...
+LL |     foo!(a b);
+   |           -^ no rules expected this token in macro call
+   |           |
+   |           help: missing comma here
+
+error: no rules expected the token `e`
+  --> $DIR/missing-comma.rs:19:21
+   |
+LL | macro_rules! foo {
+   | ---------------- when calling this macro
+...
+LL |     foo!(a, b, c, d e);
+   |                    -^ no rules expected this token in macro call
+   |                    |
+   |                    help: missing comma here
+
+error: no rules expected the token `d`
+  --> $DIR/missing-comma.rs:21:18
+   |
+LL | macro_rules! foo {
+   | ---------------- when calling this macro
+...
+LL |     foo!(a, b, c d, e);
+   |                 -^ no rules expected this token in macro call
+   |                 |
+   |                 help: missing comma here
+
+error: no rules expected the token `d`
+  --> $DIR/missing-comma.rs:23:18
+   |
+LL | macro_rules! foo {
+   | ---------------- when calling this macro
+...
+LL |     foo!(a, b, c d e);
+   |                  ^ no rules expected this token in macro call
+
+error: unexpected end of macro invocation
+  --> $DIR/missing-comma.rs:25:23
+   |
+LL | macro_rules! bar {
+   | ---------------- when calling this macro
+...
+LL |     bar!(Level::Error, );
+   |                       ^ missing tokens in macro arguments
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/macros/must-use-in-macro-55516.rs b/src/test/ui/macros/must-use-in-macro-55516.rs
new file mode 100644
index 0000000..10e5646
--- /dev/null
+++ b/src/test/ui/macros/must-use-in-macro-55516.rs
@@ -0,0 +1,11 @@
+// compile-pass
+// compile-flags: -Wunused
+
+// make sure write!() can't hide its unused Result
+
+fn main() {
+    use std::fmt::Write;
+    let mut example = String::new();
+    write!(&mut example, "{}", 42); //~WARN must be used
+}
+
diff --git a/src/test/ui/macros/must-use-in-macro-55516.stderr b/src/test/ui/macros/must-use-in-macro-55516.stderr
new file mode 100644
index 0000000..302c8aa
--- /dev/null
+++ b/src/test/ui/macros/must-use-in-macro-55516.stderr
@@ -0,0 +1,10 @@
+warning: unused `std::result::Result` that must be used
+  --> $DIR/must-use-in-macro-55516.rs:9:5
+   |
+LL |     write!(&mut example, "{}", 42);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `-W unused-must-use` implied by `-W unused`
+   = note: this `Result` may be an `Err` variant, which should be handled
+   = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
diff --git a/src/test/ui/macros/nonterminal-matching.rs b/src/test/ui/macros/nonterminal-matching.rs
new file mode 100644
index 0000000..0ccdf6e
--- /dev/null
+++ b/src/test/ui/macros/nonterminal-matching.rs
@@ -0,0 +1,26 @@
+// Check that we are refusing to match on complex nonterminals for which tokens are
+// unavailable and we'd have to go through AST comparisons.
+
+#![feature(decl_macro)]
+
+macro simple_nonterminal($nt_ident: ident, $nt_lifetime: lifetime, $nt_tt: tt) {
+    macro n(a $nt_ident b $nt_lifetime c $nt_tt d) {
+        struct S;
+    }
+
+    n!(a $nt_ident b $nt_lifetime c $nt_tt d);
+}
+
+macro complex_nonterminal($nt_item: item) {
+    macro n(a $nt_item b) {
+        struct S;
+    }
+
+    n!(a $nt_item b); //~ ERROR no rules expected the token `enum E { }`
+}
+
+simple_nonterminal!(a, 'a, (x, y, z)); // OK
+
+complex_nonterminal!(enum E {});
+
+fn main() {}
diff --git a/src/test/ui/macros/nonterminal-matching.stderr b/src/test/ui/macros/nonterminal-matching.stderr
new file mode 100644
index 0000000..5fba800
--- /dev/null
+++ b/src/test/ui/macros/nonterminal-matching.stderr
@@ -0,0 +1,11 @@
+error: no rules expected the token `enum E { }`
+  --> $DIR/nonterminal-matching.rs:19:10
+   |
+LL |     n!(a $nt_item b);
+   |          ^^^^^^^^ no rules expected this token in macro call
+...
+LL | complex_nonterminal!(enum E {});
+   | -------------------------------- in this macro invocation
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/macros/restricted-shadowing-legacy.rs b/src/test/ui/macros/restricted-shadowing-legacy.rs
new file mode 100644
index 0000000..f5cac2d
--- /dev/null
+++ b/src/test/ui/macros/restricted-shadowing-legacy.rs
@@ -0,0 +1,289 @@
+// Legend:
+// `N` - number of combination, from 0 to 4*4*4=64
+// `Outer < Invoc` means that expansion that produced macro definition `Outer`
+// is a strict ancestor of expansion that produced macro definition `Inner`.
+// `>`, `=` and `Unordered` mean "strict descendant", "same" and
+// "not in ordering relation" for parent expansions.
+// `+` - possible configuration
+// `-` - configuration impossible due to properties of partial ordering
+// `-?` - configuration impossible due to block/scope syntax
+// `+?` - configuration possible only with legacy scoping
+
+//  N | Outer ~ Invoc | Invoc ~ Inner | Outer ~ Inner | Possible |
+//  1 |       <       |       <       |       <       |    +     |
+//  2 |       <       |       <       |       =       |    -     |
+//  3 |       <       |       <       |       >       |    -     |
+//  4 |       <       |       <       |   Unordered   |    -     |
+//  5 |       <       |       =       |       <       |    +     |
+//  6 |       <       |       =       |       =       |    -     |
+//  7 |       <       |       =       |       >       |    -     |
+//  8 |       <       |       =       |   Unordered   |    -     |
+//  9 |       <       |       >       |       <       |    +     |
+// 10 |       <       |       >       |       =       |    +     |
+// 11 |       <       |       >       |       >       |    -?    |
+// 12 |       <       |       >       |   Unordered   |    -?    |
+// 13 |       <       |   Unordered   |       <       |    +     |
+// 14 |       <       |   Unordered   |       =       |    -     |
+// 15 |       <       |   Unordered   |       >       |    -     |
+// 16 |       <       |   Unordered   |   Unordered   |    -?    |
+// 17 |       =       |       <       |       <       |    +     |
+// 18 |       =       |       <       |       =       |    -     |
+// 19 |       =       |       <       |       >       |    -     |
+// 20 |       =       |       <       |   Unordered   |    -     |
+// 21 |       =       |       =       |       <       |    -     |
+// 22 |       =       |       =       |       =       |    +     |
+// 23 |       =       |       =       |       >       |    -     |
+// 24 |       =       |       =       |   Unordered   |    -     |
+// 25 |       =       |       >       |       <       |    -     |
+// 26 |       =       |       >       |       =       |    -     |
+// 27 |       =       |       >       |       >       |    -?    |
+// 28 |       =       |       >       |   Unordered   |    -     |
+// 29 |       =       |   Unordered   |       <       |    -     |
+// 30 |       =       |   Unordered   |       =       |    -     |
+// 31 |       =       |   Unordered   |       >       |    -     |
+// 32 |       =       |   Unordered   |   Unordered   |    -?    |
+// 33 |       >       |       <       |       <       |    +?    |
+// 34 |       >       |       <       |       =       |    +?    |
+// 35 |       >       |       <       |       >       |    +?    |
+// 36 |       >       |       <       |   Unordered   |    +     |
+// 37 |       >       |       =       |       <       |    -     |
+// 38 |       >       |       =       |       =       |    -     |
+// 39 |       >       |       =       |       >       |    +     |
+// 40 |       >       |       =       |   Unordered   |    -     |
+// 41 |       >       |       >       |       <       |    -     |
+// 42 |       >       |       >       |       =       |    -     |
+// 43 |       >       |       >       |       >       |    -?    |
+// 44 |       >       |       >       |   Unordered   |    -     |
+// 45 |       >       |   Unordered   |       <       |    -     |
+// 46 |       >       |   Unordered   |       =       |    -     |
+// 47 |       >       |   Unordered   |       >       |    -?    |
+// 48 |       >       |   Unordered   |   Unordered   |    -?    |
+// 49 |   Unordered   |       <       |       <       |    -?    |
+// 50 |   Unordered   |       <       |       =       |    -     |
+// 51 |   Unordered   |       <       |       >       |    -     |
+// 52 |   Unordered   |       <       |   Unordered   |    +     |
+// 53 |   Unordered   |       =       |       <       |    -     |
+// 54 |   Unordered   |       =       |       =       |    -     |
+// 55 |   Unordered   |       =       |       >       |    -     |
+// 56 |   Unordered   |       =       |   Unordered   |    +     |
+// 57 |   Unordered   |       >       |       <       |    -     |
+// 58 |   Unordered   |       >       |       =       |    -     |
+// 59 |   Unordered   |       >       |       >       |    +     |
+// 60 |   Unordered   |       >       |   Unordered   |    +     |
+// 61 |   Unordered   |   Unordered   |       <       |    +?    |
+// 62 |   Unordered   |   Unordered   |       =       |    +?    |
+// 63 |   Unordered   |   Unordered   |       >       |    +?    |
+// 64 |   Unordered   |   Unordered   |   Unordered   |    +     |
+
+#![feature(decl_macro, rustc_attrs)]
+
+struct Right;
+// struct Wrong; // not defined
+
+macro_rules! include { () => {
+    macro_rules! gen_outer { () => {
+        macro_rules! m { () => { Wrong } }
+    }}
+    macro_rules! gen_inner { () => {
+        macro_rules! m { () => { Right } }
+    }}
+    macro_rules! gen_invoc { () => {
+        m!()
+    }}
+
+    // -----------------------------------------------------------
+
+    fn check1() {
+        macro_rules! m { () => {} }
+
+        macro_rules! gen_gen_inner_invoc { () => {
+            gen_inner!();
+            m!(); //~ ERROR `m` is ambiguous
+        }}
+        gen_gen_inner_invoc!();
+    }
+
+    fn check5() {
+        macro_rules! m { () => { Wrong } }
+
+        macro_rules! gen_inner_invoc { () => {
+            macro_rules! m { () => { Right } }
+            m!(); // OK
+        }}
+        gen_inner_invoc!();
+    }
+
+    fn check9() {
+        macro_rules! m { () => { Wrong } }
+
+        macro_rules! gen_inner_gen_invoc { () => {
+            macro_rules! m { () => { Right } }
+            gen_invoc!(); // OK
+        }}
+        gen_inner_gen_invoc!();
+    }
+
+    fn check10() {
+        macro_rules! m { () => { Wrong } }
+
+        macro_rules! m { () => { Right } }
+
+        gen_invoc!(); // OK
+    }
+
+    fn check13() {
+        macro_rules! m { () => {} }
+
+        gen_inner!();
+
+        macro_rules! gen_invoc { () => { m!() } } //~ ERROR `m` is ambiguous
+        gen_invoc!();
+    }
+
+    fn check17() {
+        macro_rules! m { () => {} }
+
+        gen_inner!();
+
+        m!(); //~ ERROR `m` is ambiguous
+    }
+
+    fn check22() {
+        macro_rules! m { () => { Wrong } }
+
+        macro_rules! m { () => { Right } }
+
+        m!(); // OK
+    }
+
+    fn check36() {
+        gen_outer!();
+
+        gen_inner!();
+
+        m!(); //~ ERROR `m` is ambiguous
+    }
+
+    fn check39() {
+        gen_outer!();
+
+        macro_rules! m { () => { Right } }
+
+        m!(); // OK
+    }
+
+    fn check52() {
+        gen_outer!();
+
+        macro_rules! gen_gen_inner_invoc { () => {
+            gen_inner!();
+            m!(); //~ ERROR `m` is ambiguous
+        }}
+        gen_gen_inner_invoc!();
+    }
+
+    fn check56() {
+        gen_outer!();
+
+        macro_rules! gen_inner_invoc { () => {
+            macro_rules! m { () => { Right } }
+            m!(); // OK
+        }}
+        gen_inner_invoc!();
+    }
+
+    fn check59() {
+        gen_outer!();
+
+        macro_rules! m { () => { Right } }
+
+        gen_invoc!(); // OK
+    }
+
+    fn check60() {
+        gen_outer!();
+
+        macro_rules! gen_inner_gen_invoc { () => {
+            macro_rules! m { () => { Right } }
+            gen_invoc!(); // OK
+        }}
+        gen_inner_gen_invoc!();
+    }
+
+    fn check64() {
+        gen_outer!();
+
+        gen_inner!();
+
+        macro_rules! gen_invoc { () => { m!() } } //~ ERROR `m` is ambiguous
+        gen_invoc!();
+    }
+
+    // -----------------------------------------------------------
+    // These configurations are only possible with legacy macro scoping
+
+    fn check33() {
+        macro_rules! gen_outer_gen_inner { () => {
+            macro_rules! m { () => {} }
+            gen_inner!();
+        }}
+        gen_outer_gen_inner!();
+
+        m!(); //~ ERROR `m` is ambiguous
+    }
+
+    fn check34() {
+        macro_rules! gen_outer_inner { () => {
+            macro_rules! m { () => { Wrong } }
+            macro_rules! m { () => { Right } }
+        }}
+        gen_outer_inner!();
+
+        m!(); // OK
+    }
+
+    fn check35() {
+        macro_rules! gen_gen_outer_inner { () => {
+            gen_outer!();
+            macro_rules! m { () => { Right } }
+        }}
+        gen_gen_outer_inner!();
+
+        m!(); // OK
+    }
+
+    fn check61() {
+        macro_rules! gen_outer_gen_inner { () => {
+            macro_rules! m { () => {} }
+            gen_inner!();
+        }}
+        gen_outer_gen_inner!();
+
+        macro_rules! gen_invoc { () => { m!() } } //~ ERROR `m` is ambiguous
+        gen_invoc!();
+    }
+
+    fn check62() {
+        macro_rules! gen_outer_inner { () => {
+            macro_rules! m { () => { Wrong } }
+            macro_rules! m { () => { Right } }
+        }}
+        gen_outer_inner!();
+
+        gen_invoc!(); // OK
+    }
+
+    fn check63() {
+        macro_rules! gen_gen_outer_inner { () => {
+            gen_outer!();
+            macro_rules! m { () => { Right } }
+        }}
+        gen_gen_outer_inner!();
+
+        gen_invoc!(); // OK
+    }
+}}
+
+include!();
+
+fn main() {}
diff --git a/src/test/ui/macros/restricted-shadowing-legacy.stderr b/src/test/ui/macros/restricted-shadowing-legacy.stderr
new file mode 100644
index 0000000..8378286
--- /dev/null
+++ b/src/test/ui/macros/restricted-shadowing-legacy.stderr
@@ -0,0 +1,211 @@
+error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
+  --> $DIR/restricted-shadowing-legacy.rs:101:13
+   |
+LL |             m!();
+   |             ^ ambiguous name
+...
+LL | include!();
+   | ----------- in this macro invocation
+   |
+note: `m` could refer to the macro defined here
+  --> $DIR/restricted-shadowing-legacy.rs:88:9
+   |
+LL |         macro_rules! m { () => { Right } }
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | include!();
+   | ----------- in this macro invocation
+note: `m` could also refer to the macro defined here
+  --> $DIR/restricted-shadowing-legacy.rs:97:9
+   |
+LL |         macro_rules! m { () => {} }
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | include!();
+   | ----------- in this macro invocation
+
+error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
+  --> $DIR/restricted-shadowing-legacy.rs:139:42
+   |
+LL |         macro_rules! gen_invoc { () => { m!() } }
+   |                                          ^ ambiguous name
+...
+LL | include!();
+   | ----------- in this macro invocation
+   |
+note: `m` could refer to the macro defined here
+  --> $DIR/restricted-shadowing-legacy.rs:88:9
+   |
+LL |         macro_rules! m { () => { Right } }
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | include!();
+   | ----------- in this macro invocation
+note: `m` could also refer to the macro defined here
+  --> $DIR/restricted-shadowing-legacy.rs:135:9
+   |
+LL |         macro_rules! m { () => {} }
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | include!();
+   | ----------- in this macro invocation
+
+error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
+  --> $DIR/restricted-shadowing-legacy.rs:148:9
+   |
+LL |         m!();
+   |         ^ ambiguous name
+...
+LL | include!();
+   | ----------- in this macro invocation
+   |
+note: `m` could refer to the macro defined here
+  --> $DIR/restricted-shadowing-legacy.rs:88:9
+   |
+LL |         macro_rules! m { () => { Right } }
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | include!();
+   | ----------- in this macro invocation
+note: `m` could also refer to the macro defined here
+  --> $DIR/restricted-shadowing-legacy.rs:144:9
+   |
+LL |         macro_rules! m { () => {} }
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | include!();
+   | ----------- in this macro invocation
+
+error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
+  --> $DIR/restricted-shadowing-legacy.rs:164:9
+   |
+LL |         m!();
+   |         ^ ambiguous name
+...
+LL | include!();
+   | ----------- in this macro invocation
+   |
+note: `m` could refer to the macro defined here
+  --> $DIR/restricted-shadowing-legacy.rs:88:9
+   |
+LL |         macro_rules! m { () => { Right } }
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | include!();
+   | ----------- in this macro invocation
+note: `m` could also refer to the macro defined here
+  --> $DIR/restricted-shadowing-legacy.rs:85:9
+   |
+LL |         macro_rules! m { () => { Wrong } }
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | include!();
+   | ----------- in this macro invocation
+
+error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
+  --> $DIR/restricted-shadowing-legacy.rs:180:13
+   |
+LL |             m!();
+   |             ^ ambiguous name
+...
+LL | include!();
+   | ----------- in this macro invocation
+   |
+note: `m` could refer to the macro defined here
+  --> $DIR/restricted-shadowing-legacy.rs:88:9
+   |
+LL |         macro_rules! m { () => { Right } }
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | include!();
+   | ----------- in this macro invocation
+note: `m` could also refer to the macro defined here
+  --> $DIR/restricted-shadowing-legacy.rs:85:9
+   |
+LL |         macro_rules! m { () => { Wrong } }
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | include!();
+   | ----------- in this macro invocation
+
+error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
+  --> $DIR/restricted-shadowing-legacy.rs:218:42
+   |
+LL |         macro_rules! gen_invoc { () => { m!() } }
+   |                                          ^ ambiguous name
+...
+LL | include!();
+   | ----------- in this macro invocation
+   |
+note: `m` could refer to the macro defined here
+  --> $DIR/restricted-shadowing-legacy.rs:88:9
+   |
+LL |         macro_rules! m { () => { Right } }
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | include!();
+   | ----------- in this macro invocation
+note: `m` could also refer to the macro defined here
+  --> $DIR/restricted-shadowing-legacy.rs:85:9
+   |
+LL |         macro_rules! m { () => { Wrong } }
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | include!();
+   | ----------- in this macro invocation
+
+error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
+  --> $DIR/restricted-shadowing-legacy.rs:232:9
+   |
+LL |         m!();
+   |         ^ ambiguous name
+...
+LL | include!();
+   | ----------- in this macro invocation
+   |
+note: `m` could refer to the macro defined here
+  --> $DIR/restricted-shadowing-legacy.rs:88:9
+   |
+LL |         macro_rules! m { () => { Right } }
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | include!();
+   | ----------- in this macro invocation
+note: `m` could also refer to the macro defined here
+  --> $DIR/restricted-shadowing-legacy.rs:227:13
+   |
+LL |             macro_rules! m { () => {} }
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | include!();
+   | ----------- in this macro invocation
+
+error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
+  --> $DIR/restricted-shadowing-legacy.rs:262:42
+   |
+LL |         macro_rules! gen_invoc { () => { m!() } }
+   |                                          ^ ambiguous name
+...
+LL | include!();
+   | ----------- in this macro invocation
+   |
+note: `m` could refer to the macro defined here
+  --> $DIR/restricted-shadowing-legacy.rs:88:9
+   |
+LL |         macro_rules! m { () => { Right } }
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | include!();
+   | ----------- in this macro invocation
+note: `m` could also refer to the macro defined here
+  --> $DIR/restricted-shadowing-legacy.rs:257:13
+   |
+LL |             macro_rules! m { () => {} }
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | include!();
+   | ----------- in this macro invocation
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0659`.
diff --git a/src/test/ui/macros/restricted-shadowing-modern.rs b/src/test/ui/macros/restricted-shadowing-modern.rs
new file mode 100644
index 0000000..448f623
--- /dev/null
+++ b/src/test/ui/macros/restricted-shadowing-modern.rs
@@ -0,0 +1,243 @@
+// Legend:
+// `N` - number of combination, from 0 to 4*4*4=64
+// `Outer < Invoc` means that expansion that produced macro definition `Outer`
+// is a strict ancestor of expansion that produced macro definition `Inner`.
+// `>`, `=` and `Unordered` mean "strict descendant", "same" and
+// "not in ordering relation" for parent expansions.
+// `+` - possible configuration
+// `-` - configuration impossible due to properties of partial ordering
+// `-?` - configuration impossible due to block/scope syntax
+// `+?` - configuration possible only with legacy scoping
+
+//  N | Outer ~ Invoc | Invoc ~ Inner | Outer ~ Inner | Possible |
+//  1 |       <       |       <       |       <       |    +     |
+//  2 |       <       |       <       |       =       |    -     |
+//  3 |       <       |       <       |       >       |    -     |
+//  4 |       <       |       <       |   Unordered   |    -     |
+//  5 |       <       |       =       |       <       |    +     |
+//  6 |       <       |       =       |       =       |    -     |
+//  7 |       <       |       =       |       >       |    -     |
+//  8 |       <       |       =       |   Unordered   |    -     |
+//  9 |       <       |       >       |       <       |    +     |
+// 10 |       <       |       >       |       =       |    +     |
+// 11 |       <       |       >       |       >       |    -?    |
+// 12 |       <       |       >       |   Unordered   |    -?    |
+// 13 |       <       |   Unordered   |       <       |    +     |
+// 14 |       <       |   Unordered   |       =       |    -     |
+// 15 |       <       |   Unordered   |       >       |    -     |
+// 16 |       <       |   Unordered   |   Unordered   |    -?    |
+// 17 |       =       |       <       |       <       |    +     |
+// 18 |       =       |       <       |       =       |    -     |
+// 19 |       =       |       <       |       >       |    -     |
+// 20 |       =       |       <       |   Unordered   |    -     |
+// 21 |       =       |       =       |       <       |    -     |
+// 22 |       =       |       =       |       =       |    +     |
+// 23 |       =       |       =       |       >       |    -     |
+// 24 |       =       |       =       |   Unordered   |    -     |
+// 25 |       =       |       >       |       <       |    -     |
+// 26 |       =       |       >       |       =       |    -     |
+// 27 |       =       |       >       |       >       |    -?    |
+// 28 |       =       |       >       |   Unordered   |    -     |
+// 29 |       =       |   Unordered   |       <       |    -     |
+// 30 |       =       |   Unordered   |       =       |    -     |
+// 31 |       =       |   Unordered   |       >       |    -     |
+// 32 |       =       |   Unordered   |   Unordered   |    -?    |
+// 33 |       >       |       <       |       <       |    -?    |
+// 34 |       >       |       <       |       =       |    -?    |
+// 35 |       >       |       <       |       >       |    -?    |
+// 36 |       >       |       <       |   Unordered   |    +     |
+// 37 |       >       |       =       |       <       |    -     |
+// 38 |       >       |       =       |       =       |    -     |
+// 39 |       >       |       =       |       >       |    +     |
+// 40 |       >       |       =       |   Unordered   |    -     |
+// 41 |       >       |       >       |       <       |    -     |
+// 42 |       >       |       >       |       =       |    -     |
+// 43 |       >       |       >       |       >       |    -?    |
+// 44 |       >       |       >       |   Unordered   |    -     |
+// 45 |       >       |   Unordered   |       <       |    -     |
+// 46 |       >       |   Unordered   |       =       |    -     |
+// 47 |       >       |   Unordered   |       >       |    -?    |
+// 48 |       >       |   Unordered   |   Unordered   |    -?    |
+// 49 |   Unordered   |       <       |       <       |    -?    |
+// 50 |   Unordered   |       <       |       =       |    -     |
+// 51 |   Unordered   |       <       |       >       |    -     |
+// 52 |   Unordered   |       <       |   Unordered   |    +     |
+// 53 |   Unordered   |       =       |       <       |    -     |
+// 54 |   Unordered   |       =       |       =       |    -     |
+// 55 |   Unordered   |       =       |       >       |    -     |
+// 56 |   Unordered   |       =       |   Unordered   |    +     |
+// 57 |   Unordered   |       >       |       <       |    -     |
+// 58 |   Unordered   |       >       |       =       |    -     |
+// 59 |   Unordered   |       >       |       >       |    +     |
+// 60 |   Unordered   |       >       |   Unordered   |    +     |
+// 61 |   Unordered   |   Unordered   |       <       |    -?    |
+// 62 |   Unordered   |   Unordered   |       =       |    -?    |
+// 63 |   Unordered   |   Unordered   |       >       |    -?    |
+// 64 |   Unordered   |   Unordered   |   Unordered   |    +     |
+
+#![feature(decl_macro, rustc_attrs)]
+
+struct Right;
+// struct Wrong; // not defined
+
+#[rustc_transparent_macro]
+macro include() {
+    #[rustc_transparent_macro]
+    macro gen_outer() {
+        macro m() { Wrong }
+    }
+    #[rustc_transparent_macro]
+    macro gen_inner() {
+        macro m() { Right }
+    }
+    #[rustc_transparent_macro]
+    macro gen_invoc() {
+        m!()
+    }
+
+    // -----------------------------------------------------------
+
+    fn check1() {
+        macro m() {}
+        {
+            #[rustc_transparent_macro]
+            macro gen_gen_inner_invoc() {
+                gen_inner!();
+                m!(); //~ ERROR `m` is ambiguous
+            }
+            gen_gen_inner_invoc!();
+        }
+    }
+
+    fn check5() {
+        macro m() { Wrong }
+        {
+            #[rustc_transparent_macro]
+            macro gen_inner_invoc() {
+                macro m() { Right }
+                m!(); // OK
+            }
+            gen_inner_invoc!();
+        }
+    }
+
+    fn check9() {
+        macro m() { Wrong }
+        {
+            #[rustc_transparent_macro]
+            macro gen_inner_gen_invoc() {
+                macro m() { Right }
+                gen_invoc!(); // OK
+            }
+            gen_inner_gen_invoc!();
+        }
+    }
+
+    fn check10() {
+        macro m() { Wrong }
+        {
+            macro m() { Right }
+            gen_invoc!(); // OK
+        }
+    }
+
+    fn check13() {
+        macro m() {}
+        {
+            gen_inner!();
+            #[rustc_transparent_macro]
+            macro gen_invoc() { m!() } //~ ERROR `m` is ambiguous
+            gen_invoc!();
+        }
+    }
+
+    fn check17() {
+        macro m() {}
+        {
+            gen_inner!();
+            m!(); //~ ERROR `m` is ambiguous
+        }
+    }
+
+    fn check22() {
+        macro m() { Wrong }
+        {
+            macro m() { Right }
+            m!(); // OK
+        }
+    }
+
+    fn check36() {
+        gen_outer!();
+        {
+            gen_inner!();
+            m!(); //~ ERROR `m` is ambiguous
+        }
+    }
+
+    fn check39() {
+        gen_outer!();
+        {
+            macro m() { Right }
+            m!(); // OK
+        }
+    }
+
+    fn check52() {
+        gen_outer!();
+        {
+            #[rustc_transparent_macro]
+            macro gen_gen_inner_invoc() {
+                gen_inner!();
+                m!(); //~ ERROR `m` is ambiguous
+            }
+            gen_gen_inner_invoc!();
+        }
+    }
+
+    fn check56() {
+        gen_outer!();
+        {
+            #[rustc_transparent_macro]
+            macro gen_inner_invoc() {
+                macro m() { Right }
+                m!(); // OK
+            }
+            gen_inner_invoc!();
+        }
+    }
+
+    fn check59() {
+        gen_outer!();
+        {
+            macro m() { Right }
+            gen_invoc!(); // OK
+        }
+    }
+
+    fn check60() {
+        gen_outer!();
+        {
+            #[rustc_transparent_macro]
+            macro gen_inner_gen_invoc() {
+                macro m() { Right }
+                gen_invoc!(); // OK
+            }
+            gen_inner_gen_invoc!();
+        }
+    }
+
+    fn check64() {
+        gen_outer!();
+        {
+            gen_inner!();
+            #[rustc_transparent_macro]
+            macro gen_invoc() { m!() } //~ ERROR `m` is ambiguous
+            gen_invoc!();
+        }
+    }
+}
+
+include!();
+
+fn main() {}
diff --git a/src/test/ui/macros/restricted-shadowing-modern.stderr b/src/test/ui/macros/restricted-shadowing-modern.stderr
new file mode 100644
index 0000000..d147deb
--- /dev/null
+++ b/src/test/ui/macros/restricted-shadowing-modern.stderr
@@ -0,0 +1,159 @@
+error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
+  --> $DIR/restricted-shadowing-modern.rs:106:17
+   |
+LL |                 m!();
+   |                 ^ ambiguous name
+...
+LL | include!();
+   | ----------- in this macro invocation
+   |
+note: `m` could refer to the macro defined here
+  --> $DIR/restricted-shadowing-modern.rs:91:9
+   |
+LL |         macro m() { Right }
+   |         ^^^^^^^^^^^^^^^^^^^
+...
+LL | include!();
+   | ----------- in this macro invocation
+note: `m` could also refer to the macro defined here
+  --> $DIR/restricted-shadowing-modern.rs:101:9
+   |
+LL |         macro m() {}
+   |         ^^^^^^^^^^^^
+...
+LL | include!();
+   | ----------- in this macro invocation
+
+error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
+  --> $DIR/restricted-shadowing-modern.rs:149:33
+   |
+LL |             macro gen_invoc() { m!() }
+   |                                 ^ ambiguous name
+...
+LL | include!();
+   | ----------- in this macro invocation
+   |
+note: `m` could refer to the macro defined here
+  --> $DIR/restricted-shadowing-modern.rs:91:9
+   |
+LL |         macro m() { Right }
+   |         ^^^^^^^^^^^^^^^^^^^
+...
+LL | include!();
+   | ----------- in this macro invocation
+note: `m` could also refer to the macro defined here
+  --> $DIR/restricted-shadowing-modern.rs:145:9
+   |
+LL |         macro m() {}
+   |         ^^^^^^^^^^^^
+...
+LL | include!();
+   | ----------- in this macro invocation
+
+error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
+  --> $DIR/restricted-shadowing-modern.rs:158:13
+   |
+LL |             m!();
+   |             ^ ambiguous name
+...
+LL | include!();
+   | ----------- in this macro invocation
+   |
+note: `m` could refer to the macro defined here
+  --> $DIR/restricted-shadowing-modern.rs:91:9
+   |
+LL |         macro m() { Right }
+   |         ^^^^^^^^^^^^^^^^^^^
+...
+LL | include!();
+   | ----------- in this macro invocation
+note: `m` could also refer to the macro defined here
+  --> $DIR/restricted-shadowing-modern.rs:155:9
+   |
+LL |         macro m() {}
+   |         ^^^^^^^^^^^^
+...
+LL | include!();
+   | ----------- in this macro invocation
+
+error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
+  --> $DIR/restricted-shadowing-modern.rs:174:13
+   |
+LL |             m!();
+   |             ^ ambiguous name
+...
+LL | include!();
+   | ----------- in this macro invocation
+   |
+note: `m` could refer to the macro defined here
+  --> $DIR/restricted-shadowing-modern.rs:91:9
+   |
+LL |         macro m() { Right }
+   |         ^^^^^^^^^^^^^^^^^^^
+...
+LL | include!();
+   | ----------- in this macro invocation
+note: `m` could also refer to the macro defined here
+  --> $DIR/restricted-shadowing-modern.rs:87:9
+   |
+LL |         macro m() { Wrong }
+   |         ^^^^^^^^^^^^^^^^^^^
+...
+LL | include!();
+   | ----------- in this macro invocation
+
+error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
+  --> $DIR/restricted-shadowing-modern.rs:192:17
+   |
+LL |                 m!();
+   |                 ^ ambiguous name
+...
+LL | include!();
+   | ----------- in this macro invocation
+   |
+note: `m` could refer to the macro defined here
+  --> $DIR/restricted-shadowing-modern.rs:91:9
+   |
+LL |         macro m() { Right }
+   |         ^^^^^^^^^^^^^^^^^^^
+...
+LL | include!();
+   | ----------- in this macro invocation
+note: `m` could also refer to the macro defined here
+  --> $DIR/restricted-shadowing-modern.rs:87:9
+   |
+LL |         macro m() { Wrong }
+   |         ^^^^^^^^^^^^^^^^^^^
+...
+LL | include!();
+   | ----------- in this macro invocation
+
+error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
+  --> $DIR/restricted-shadowing-modern.rs:235:33
+   |
+LL |             macro gen_invoc() { m!() }
+   |                                 ^ ambiguous name
+...
+LL | include!();
+   | ----------- in this macro invocation
+   |
+note: `m` could refer to the macro defined here
+  --> $DIR/restricted-shadowing-modern.rs:91:9
+   |
+LL |         macro m() { Right }
+   |         ^^^^^^^^^^^^^^^^^^^
+...
+LL | include!();
+   | ----------- in this macro invocation
+note: `m` could also refer to the macro defined here
+  --> $DIR/restricted-shadowing-modern.rs:87:9
+   |
+LL |         macro m() { Wrong }
+   |         ^^^^^^^^^^^^^^^^^^^
+...
+LL | include!();
+   | ----------- in this macro invocation
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0659`.
diff --git a/src/test/ui/macros/span-covering-argument-1.nll.stderr b/src/test/ui/macros/span-covering-argument-1.nll.stderr
new file mode 100644
index 0000000..2ac8811
--- /dev/null
+++ b/src/test/ui/macros/span-covering-argument-1.nll.stderr
@@ -0,0 +1,14 @@
+error[E0596]: cannot borrow `foo` as mutable, as it is not declared as mutable
+  --> $DIR/span-covering-argument-1.rs:5:14
+   |
+LL |             let $s = 0;
+   |                 -- help: consider changing this to be mutable: `mut foo`
+LL |             *&mut $s = 0;
+   |              ^^^^^^^ cannot borrow as mutable
+...
+LL |     bad!(foo whatever);
+   |     ------------------- in this macro invocation
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/macros/span-covering-argument-1.rs b/src/test/ui/macros/span-covering-argument-1.rs
new file mode 100644
index 0000000..0256aaf
--- /dev/null
+++ b/src/test/ui/macros/span-covering-argument-1.rs
@@ -0,0 +1,13 @@
+macro_rules! bad {
+    ($s:ident whatever) => {
+        {
+            let $s = 0;
+            *&mut $s = 0;
+            //~^ ERROR cannot borrow immutable local variable `foo` as mutable [E0596]
+        }
+    }
+}
+
+fn main() {
+    bad!(foo whatever);
+}
diff --git a/src/test/ui/macros/span-covering-argument-1.stderr b/src/test/ui/macros/span-covering-argument-1.stderr
new file mode 100644
index 0000000..345b880
--- /dev/null
+++ b/src/test/ui/macros/span-covering-argument-1.stderr
@@ -0,0 +1,14 @@
+error[E0596]: cannot borrow immutable local variable `foo` as mutable
+  --> $DIR/span-covering-argument-1.rs:5:19
+   |
+LL |             let $s = 0;
+   |                 -- help: make this binding mutable: `mut $s`
+LL |             *&mut $s = 0;
+   |                   ^^ cannot borrow mutably
+...
+LL |     bad!(foo whatever);
+   |     ------------------- in this macro invocation
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/macros/trace-macro.rs b/src/test/ui/macros/trace-macro.rs
new file mode 100644
index 0000000..efd658d
--- /dev/null
+++ b/src/test/ui/macros/trace-macro.rs
@@ -0,0 +1,6 @@
+// compile-flags: -Z trace-macros
+// compile-pass
+
+fn main() {
+    println!("Hello, World!");
+}
diff --git a/src/test/ui/macros/trace-macro.stderr b/src/test/ui/macros/trace-macro.stderr
new file mode 100644
index 0000000..ebfed41
--- /dev/null
+++ b/src/test/ui/macros/trace-macro.stderr
@@ -0,0 +1,9 @@
+note: trace_macro
+  --> $DIR/trace-macro.rs:5:5
+   |
+LL |     println!("Hello, World!");
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: expanding `println! { "Hello, World!" }`
+   = note: to `{ $crate :: io :: _print ( format_args_nl ! ( "Hello, World!" ) ) ; }`
+
diff --git a/src/test/ui/macros/trace_faulty_macros.rs b/src/test/ui/macros/trace_faulty_macros.rs
new file mode 100644
index 0000000..627d58a
--- /dev/null
+++ b/src/test/ui/macros/trace_faulty_macros.rs
@@ -0,0 +1,45 @@
+// compile-flags: -Z trace-macros
+
+#![recursion_limit="4"]
+
+macro_rules! my_faulty_macro {
+    () => {
+        my_faulty_macro!(bcd); //~ ERROR no rules
+    };
+}
+
+macro_rules! pat_macro {
+    () => {
+        pat_macro!(A{a:a, b:0, c:_, ..});
+    };
+    ($a:pat) => {
+        $a
+    };
+}
+
+macro_rules! my_recursive_macro {
+    () => {
+        my_recursive_macro!(); //~ ERROR recursion limit
+    };
+}
+
+macro_rules! my_macro {
+    () => {
+
+    };
+}
+
+fn main() {
+    my_faulty_macro!();
+    my_recursive_macro!();
+    test!();
+    non_exisiting!();
+    derive!(Debug);
+    let a = pat_macro!();
+}
+
+#[my_macro]
+fn use_bang_macro_as_attr(){}
+
+#[derive(Debug)]
+fn use_derive_macro_as_attr(){}
diff --git a/src/test/ui/macros/trace_faulty_macros.stderr b/src/test/ui/macros/trace_faulty_macros.stderr
new file mode 100644
index 0000000..233d3dc
--- /dev/null
+++ b/src/test/ui/macros/trace_faulty_macros.stderr
@@ -0,0 +1,52 @@
+error: no rules expected the token `bcd`
+  --> $DIR/trace_faulty_macros.rs:7:26
+   |
+LL | macro_rules! my_faulty_macro {
+   | ---------------------------- when calling this macro
+LL |     () => {
+LL |         my_faulty_macro!(bcd);
+   |                          ^^^ no rules expected this token in macro call
+...
+LL |     my_faulty_macro!();
+   |     ------------------- in this macro invocation
+
+note: trace_macro
+  --> $DIR/trace_faulty_macros.rs:33:5
+   |
+LL |     my_faulty_macro!();
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: expanding `my_faulty_macro! {  }`
+   = note: to `my_faulty_macro ! ( bcd ) ;`
+   = note: expanding `my_faulty_macro! { bcd }`
+
+error: recursion limit reached while expanding the macro `my_recursive_macro`
+  --> $DIR/trace_faulty_macros.rs:22:9
+   |
+LL |         my_recursive_macro!();
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     my_recursive_macro!();
+   |     ---------------------- in this macro invocation
+   |
+   = help: consider adding a `#![recursion_limit="8"]` attribute to your crate
+
+note: trace_macro
+  --> $DIR/trace_faulty_macros.rs:34:5
+   |
+LL |     my_recursive_macro!();
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: expanding `my_recursive_macro! {  }`
+   = note: to `my_recursive_macro ! (  ) ;`
+   = note: expanding `my_recursive_macro! {  }`
+   = note: to `my_recursive_macro ! (  ) ;`
+   = note: expanding `my_recursive_macro! {  }`
+   = note: to `my_recursive_macro ! (  ) ;`
+   = note: expanding `my_recursive_macro! {  }`
+   = note: to `my_recursive_macro ! (  ) ;`
+   = note: expanding `my_recursive_macro! {  }`
+   = note: to `my_recursive_macro ! (  ) ;`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/main-wrong-location.rs b/src/test/ui/main-wrong-location.rs
new file mode 100644
index 0000000..d7ed512
--- /dev/null
+++ b/src/test/ui/main-wrong-location.rs
@@ -0,0 +1,5 @@
+mod m {
+    // An inferred main entry point (that doesn't use #[main])
+    // must appear at the top of the crate
+    fn main() { }
+}
diff --git a/src/test/ui/main-wrong-location.stderr b/src/test/ui/main-wrong-location.stderr
new file mode 100644
index 0000000..b30931f
--- /dev/null
+++ b/src/test/ui/main-wrong-location.stderr
@@ -0,0 +1,12 @@
+error[E0601]: `main` function not found in crate `main_wrong_location`
+   |
+   = note: the main function must be defined at the crate level but you have one or more functions named 'main' that are not defined at the crate level. Either move the definition or attach the `#[main]` attribute to override this behavior.
+note: here is a function named 'main'
+  --> $DIR/main-wrong-location.rs:4:5
+   |
+LL |     fn main() { }
+   |     ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0601`.
diff --git a/src/test/ui/main-wrong-type.rs b/src/test/ui/main-wrong-type.rs
new file mode 100644
index 0000000..dac4d4a
--- /dev/null
+++ b/src/test/ui/main-wrong-type.rs
@@ -0,0 +1,8 @@
+struct S {
+    x: isize,
+    y: isize,
+}
+
+fn main(foo: S) {
+//~^ ERROR: main function has wrong type [E0580]
+}
diff --git a/src/test/ui/main-wrong-type.stderr b/src/test/ui/main-wrong-type.stderr
new file mode 100644
index 0000000..c00c67a
--- /dev/null
+++ b/src/test/ui/main-wrong-type.stderr
@@ -0,0 +1,12 @@
+error[E0580]: main function has wrong type
+  --> $DIR/main-wrong-type.rs:6:1
+   |
+LL | fn main(foo: S) {
+   | ^^^^^^^^^^^^^^^ incorrect number of function parameters
+   |
+   = note: expected type `fn()`
+              found type `fn(S)`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0580`.
diff --git a/src/test/ui/malformed/malformed-derive-entry.rs b/src/test/ui/malformed/malformed-derive-entry.rs
new file mode 100644
index 0000000..74d2210
--- /dev/null
+++ b/src/test/ui/malformed/malformed-derive-entry.rs
@@ -0,0 +1,17 @@
+#[derive(Copy(Bad))]
+//~^ ERROR expected one of `)`, `,`, or `::`, found `(`
+struct Test1;
+
+#[derive(Copy="bad")]
+//~^ ERROR expected one of `)`, `,`, or `::`, found `=`
+struct Test2;
+
+#[derive()]
+//~^ WARNING empty trait list
+struct Test3;
+
+#[derive]
+//~^ ERROR attribute must be of the form
+struct Test4;
+
+fn main() {}
diff --git a/src/test/ui/malformed/malformed-derive-entry.stderr b/src/test/ui/malformed/malformed-derive-entry.stderr
new file mode 100644
index 0000000..f546f74
--- /dev/null
+++ b/src/test/ui/malformed/malformed-derive-entry.stderr
@@ -0,0 +1,26 @@
+error: expected one of `)`, `,`, or `::`, found `(`
+  --> $DIR/malformed-derive-entry.rs:1:14
+   |
+LL | #[derive(Copy(Bad))]
+   |              ^ expected one of `)`, `,`, or `::` here
+
+error: expected one of `)`, `,`, or `::`, found `=`
+  --> $DIR/malformed-derive-entry.rs:5:14
+   |
+LL | #[derive(Copy="bad")]
+   |              ^ expected one of `)`, `,`, or `::` here
+
+warning: empty trait list in `derive`
+  --> $DIR/malformed-derive-entry.rs:9:1
+   |
+LL | #[derive()]
+   | ^^^^^^^^^^^
+
+error: attribute must be of the form `#[derive(Trait1, Trait2, ...)]`
+  --> $DIR/malformed-derive-entry.rs:13:1
+   |
+LL | #[derive]
+   | ^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/malformed/malformed-interpolated.rs b/src/test/ui/malformed/malformed-interpolated.rs
new file mode 100644
index 0000000..e452435
--- /dev/null
+++ b/src/test/ui/malformed/malformed-interpolated.rs
@@ -0,0 +1,18 @@
+#![feature(custom_attribute)]
+
+macro_rules! check {
+    ($expr: expr) => (
+        #[my_attr = $expr] //~ ERROR suffixed literals are not allowed in attributes
+                           //~| ERROR unexpected token: `-0`
+                           //~| ERROR unexpected token: `0 + 0`
+        use main as _;
+    );
+}
+
+check!("0"); // OK
+check!(0); // OK
+check!(0u8); // ERROR, see above
+check!(-0); // ERROR, see above
+check!(0 + 0); // ERROR, see above
+
+fn main() {}
diff --git a/src/test/ui/malformed/malformed-interpolated.stderr b/src/test/ui/malformed/malformed-interpolated.stderr
new file mode 100644
index 0000000..efeede0
--- /dev/null
+++ b/src/test/ui/malformed/malformed-interpolated.stderr
@@ -0,0 +1,31 @@
+error: suffixed literals are not allowed in attributes
+  --> $DIR/malformed-interpolated.rs:5:21
+   |
+LL |         #[my_attr = $expr]
+   |                     ^^^^^
+...
+LL | check!(0u8); // ERROR, see above
+   | ------------ in this macro invocation
+   |
+   = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
+
+error: unexpected token: `-0`
+  --> $DIR/malformed-interpolated.rs:5:19
+   |
+LL |         #[my_attr = $expr]
+   |                   ^
+...
+LL | check!(-0); // ERROR, see above
+   | ----------- in this macro invocation
+
+error: unexpected token: `0 + 0`
+  --> $DIR/malformed-interpolated.rs:5:19
+   |
+LL |         #[my_attr = $expr]
+   |                   ^
+...
+LL | check!(0 + 0); // ERROR, see above
+   | -------------- in this macro invocation
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/malformed/malformed-plugin-1.rs b/src/test/ui/malformed/malformed-plugin-1.rs
new file mode 100644
index 0000000..16e7a95
--- /dev/null
+++ b/src/test/ui/malformed/malformed-plugin-1.rs
@@ -0,0 +1,4 @@
+#![feature(plugin)]
+#![plugin] //~ ERROR attribute must be of the form
+
+fn main() {}
diff --git a/src/test/ui/malformed/malformed-plugin-1.stderr b/src/test/ui/malformed/malformed-plugin-1.stderr
new file mode 100644
index 0000000..cc0ac18
--- /dev/null
+++ b/src/test/ui/malformed/malformed-plugin-1.stderr
@@ -0,0 +1,8 @@
+error: attribute must be of the form `#[plugin(name|name(args))]`
+  --> $DIR/malformed-plugin-1.rs:2:1
+   |
+LL | #![plugin]
+   | ^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/malformed/malformed-plugin-2.rs b/src/test/ui/malformed/malformed-plugin-2.rs
new file mode 100644
index 0000000..70a1d7f
--- /dev/null
+++ b/src/test/ui/malformed/malformed-plugin-2.rs
@@ -0,0 +1,4 @@
+#![feature(plugin)]
+#![plugin="bleh"] //~ ERROR attribute must be of the form
+
+fn main() {}
diff --git a/src/test/ui/malformed/malformed-plugin-2.stderr b/src/test/ui/malformed/malformed-plugin-2.stderr
new file mode 100644
index 0000000..617b13b
--- /dev/null
+++ b/src/test/ui/malformed/malformed-plugin-2.stderr
@@ -0,0 +1,8 @@
+error: attribute must be of the form `#[plugin(name|name(args))]`
+  --> $DIR/malformed-plugin-2.rs:2:1
+   |
+LL | #![plugin="bleh"]
+   | ^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/malformed/malformed-plugin-3.rs b/src/test/ui/malformed/malformed-plugin-3.rs
new file mode 100644
index 0000000..1b70ff3
--- /dev/null
+++ b/src/test/ui/malformed/malformed-plugin-3.rs
@@ -0,0 +1,4 @@
+#![feature(plugin)]
+#![plugin(foo="bleh")] //~ ERROR malformed plugin attribute
+
+fn main() {}
diff --git a/src/test/ui/malformed/malformed-plugin-3.stderr b/src/test/ui/malformed/malformed-plugin-3.stderr
new file mode 100644
index 0000000..5739770
--- /dev/null
+++ b/src/test/ui/malformed/malformed-plugin-3.stderr
@@ -0,0 +1,9 @@
+error[E0498]: malformed plugin attribute
+  --> $DIR/malformed-plugin-3.rs:2:1
+   |
+LL | #![plugin(foo="bleh")]
+   | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0498`.
diff --git a/src/test/ui/malformed/malformed-regressions.rs b/src/test/ui/malformed/malformed-regressions.rs
new file mode 100644
index 0000000..b5c9924
--- /dev/null
+++ b/src/test/ui/malformed/malformed-regressions.rs
@@ -0,0 +1,8 @@
+// compile-pass
+
+#[doc] //~ WARN attribute must be of the form
+#[ignore()] //~ WARN attribute must be of the form
+#[inline = ""] //~ WARN attribute must be of the form
+#[link] //~ WARN attribute must be of the form
+#[link = ""] //~ WARN attribute must be of the form
+fn main() {}
diff --git a/src/test/ui/malformed/malformed-regressions.stderr b/src/test/ui/malformed/malformed-regressions.stderr
new file mode 100644
index 0000000..9a81c105
--- /dev/null
+++ b/src/test/ui/malformed/malformed-regressions.stderr
@@ -0,0 +1,48 @@
+warning: attribute must be of the form `#[doc(hidden|inline|...)]` or `#[doc = "string"]`
+  --> $DIR/malformed-regressions.rs:3:1
+   |
+LL | #[doc]
+   | ^^^^^^
+   |
+   = note: #[warn(ill_formed_attribute_input)] on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
+
+warning: attribute must be of the form `#[ignore]` or `#[ignore = "reason"]`
+  --> $DIR/malformed-regressions.rs:4:1
+   |
+LL | #[ignore()]
+   | ^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
+
+warning: attribute must be of the form `#[inline]` or `#[inline(always|never)]`
+  --> $DIR/malformed-regressions.rs:5:1
+   |
+LL | #[inline = ""]
+   | ^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
+
+warning: attribute must be of the form `#[link(name = "...", /*opt*/ kind = "dylib|static|...",
+                                             /*opt*/ cfg = "...")]`
+  --> $DIR/malformed-regressions.rs:6:1
+   |
+LL | #[link]
+   | ^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
+
+warning: attribute must be of the form `#[link(name = "...", /*opt*/ kind = "dylib|static|...",
+                                             /*opt*/ cfg = "...")]`
+  --> $DIR/malformed-regressions.rs:7:1
+   |
+LL | #[link = ""]
+   | ^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
+
diff --git a/src/test/ui/malformed/malformed-special-attrs.rs b/src/test/ui/malformed/malformed-special-attrs.rs
new file mode 100644
index 0000000..f91c6be
--- /dev/null
+++ b/src/test/ui/malformed/malformed-special-attrs.rs
@@ -0,0 +1,13 @@
+#[cfg_attr] //~ ERROR expected `(`, found `<eof>`
+struct S1;
+
+#[cfg_attr = ""] //~ ERROR expected `(`, found `=`
+struct S2;
+
+#[derive] //~ ERROR attribute must be of the form
+struct S3;
+
+#[derive = ""] //~ ERROR attribute must be of the form
+struct S4;
+
+fn main() {}
diff --git a/src/test/ui/malformed/malformed-special-attrs.stderr b/src/test/ui/malformed/malformed-special-attrs.stderr
new file mode 100644
index 0000000..8c23424
--- /dev/null
+++ b/src/test/ui/malformed/malformed-special-attrs.stderr
@@ -0,0 +1,25 @@
+error: expected `(`, found `<eof>`
+
+error: expected `(`, found `=`
+  --> $DIR/malformed-special-attrs.rs:4:12
+   |
+LL | #[cfg_attr]
+   | - expected `(`
+...
+LL | #[cfg_attr = ""]
+   |            ^ unexpected token
+
+error: attribute must be of the form `#[derive(Trait1, Trait2, ...)]`
+  --> $DIR/malformed-special-attrs.rs:7:1
+   |
+LL | #[derive]
+   | ^^^^^^^^^
+
+error: attribute must be of the form `#[derive(Trait1, Trait2, ...)]`
+  --> $DIR/malformed-special-attrs.rs:10:1
+   |
+LL | #[derive = ""]
+   | ^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/malformed/malformed-unwind-1.rs b/src/test/ui/malformed/malformed-unwind-1.rs
new file mode 100644
index 0000000..e34c288
--- /dev/null
+++ b/src/test/ui/malformed/malformed-unwind-1.rs
@@ -0,0 +1,11 @@
+#![feature(unwind_attributes)]
+
+#[unwind]
+//~^ ERROR attribute must be of the form
+extern "C" fn f1() {}
+
+#[unwind = ""]
+//~^ ERROR attribute must be of the form
+extern "C" fn f2() {}
+
+fn main() {}
diff --git a/src/test/ui/malformed/malformed-unwind-1.stderr b/src/test/ui/malformed/malformed-unwind-1.stderr
new file mode 100644
index 0000000..852136e
--- /dev/null
+++ b/src/test/ui/malformed/malformed-unwind-1.stderr
@@ -0,0 +1,14 @@
+error: attribute must be of the form `#[unwind(allowed|aborts)]`
+  --> $DIR/malformed-unwind-1.rs:3:1
+   |
+LL | #[unwind]
+   | ^^^^^^^^^
+
+error: attribute must be of the form `#[unwind(allowed|aborts)]`
+  --> $DIR/malformed-unwind-1.rs:7:1
+   |
+LL | #[unwind = ""]
+   | ^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/malformed/malformed-unwind-2.rs b/src/test/ui/malformed/malformed-unwind-2.rs
new file mode 100644
index 0000000..d4955b4
--- /dev/null
+++ b/src/test/ui/malformed/malformed-unwind-2.rs
@@ -0,0 +1,11 @@
+#![feature(unwind_attributes)]
+
+#[unwind(allowed, aborts)]
+//~^ ERROR malformed `#[unwind]` attribute
+extern "C" fn f1() {}
+
+#[unwind(unsupported)]
+//~^ ERROR malformed `#[unwind]` attribute
+extern "C" fn f2() {}
+
+fn main() {}
diff --git a/src/test/ui/malformed/malformed-unwind-2.stderr b/src/test/ui/malformed/malformed-unwind-2.stderr
new file mode 100644
index 0000000..88fc4e0
--- /dev/null
+++ b/src/test/ui/malformed/malformed-unwind-2.stderr
@@ -0,0 +1,15 @@
+error[E0633]: malformed `#[unwind]` attribute
+  --> $DIR/malformed-unwind-2.rs:3:1
+   |
+LL | #[unwind(allowed, aborts)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0633]: malformed `#[unwind]` attribute
+  --> $DIR/malformed-unwind-2.rs:7:1
+   |
+LL | #[unwind(unsupported)]
+   | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0633`.
diff --git a/src/test/ui/malformed_macro_lhs.rs b/src/test/ui/malformed_macro_lhs.rs
new file mode 100644
index 0000000..f57d2fb
--- /dev/null
+++ b/src/test/ui/malformed_macro_lhs.rs
@@ -0,0 +1,7 @@
+macro_rules! my_precioooous {
+    t => (1); //~ ERROR invalid macro matcher
+}
+
+fn main() {
+    my_precioooous!();
+}
diff --git a/src/test/ui/malformed_macro_lhs.stderr b/src/test/ui/malformed_macro_lhs.stderr
new file mode 100644
index 0000000..adf64b0
--- /dev/null
+++ b/src/test/ui/malformed_macro_lhs.stderr
@@ -0,0 +1,8 @@
+error: invalid macro matcher; matchers must be contained in balanced delimiters
+  --> $DIR/malformed_macro_lhs.rs:2:5
+   |
+LL |     t => (1);
+   |     ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/manual/manual-link-bad-form.rs b/src/test/ui/manual/manual-link-bad-form.rs
new file mode 100644
index 0000000..9d092ae
--- /dev/null
+++ b/src/test/ui/manual/manual-link-bad-form.rs
@@ -0,0 +1,5 @@
+// compile-flags:-l static=
+// error-pattern: empty library name given via `-l`
+
+fn main() {
+}
diff --git a/src/test/ui/manual/manual-link-bad-form.stderr b/src/test/ui/manual/manual-link-bad-form.stderr
new file mode 100644
index 0000000..ed3c4c4
--- /dev/null
+++ b/src/test/ui/manual/manual-link-bad-form.stderr
@@ -0,0 +1,4 @@
+error: empty library name given via `-l`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/manual/manual-link-bad-kind.rs b/src/test/ui/manual/manual-link-bad-kind.rs
new file mode 100644
index 0000000..86830a5
--- /dev/null
+++ b/src/test/ui/manual/manual-link-bad-kind.rs
@@ -0,0 +1,5 @@
+// compile-flags:-l bar=foo
+// error-pattern: unknown library kind `bar`, expected one of dylib, framework, or static
+
+fn main() {
+}
diff --git a/src/test/ui/manual/manual-link-bad-kind.stderr b/src/test/ui/manual/manual-link-bad-kind.stderr
new file mode 100644
index 0000000..03c33a9
--- /dev/null
+++ b/src/test/ui/manual/manual-link-bad-kind.stderr
@@ -0,0 +1,2 @@
+error: unknown library kind `bar`, expected one of dylib, framework, or static
+
diff --git a/src/test/ui/manual/manual-link-bad-search-path.rs b/src/test/ui/manual/manual-link-bad-search-path.rs
new file mode 100644
index 0000000..0fe23b0
--- /dev/null
+++ b/src/test/ui/manual/manual-link-bad-search-path.rs
@@ -0,0 +1,5 @@
+// compile-flags:-L native=
+// error-pattern: empty search path given via `-L`
+
+fn main() {
+}
diff --git a/src/test/ui/manual/manual-link-bad-search-path.stderr b/src/test/ui/manual/manual-link-bad-search-path.stderr
new file mode 100644
index 0000000..2c0649e
--- /dev/null
+++ b/src/test/ui/manual/manual-link-bad-search-path.stderr
@@ -0,0 +1,2 @@
+error: empty search path given via `-L`
+
diff --git a/src/test/ui/manual/manual-link-framework.rs b/src/test/ui/manual/manual-link-framework.rs
new file mode 100644
index 0000000..0474526
--- /dev/null
+++ b/src/test/ui/manual/manual-link-framework.rs
@@ -0,0 +1,7 @@
+// ignore-macos
+// ignore-ios
+// compile-flags:-l framework=foo
+// error-pattern: native frameworks are only available on macOS targets
+
+fn main() {
+}
diff --git a/src/test/ui/manual/manual-link-framework.stderr b/src/test/ui/manual/manual-link-framework.stderr
new file mode 100644
index 0000000..3e8da8b
--- /dev/null
+++ b/src/test/ui/manual/manual-link-framework.stderr
@@ -0,0 +1,4 @@
+error: native frameworks are only available on macOS targets
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/map-types.rs b/src/test/ui/map-types.rs
new file mode 100644
index 0000000..dab7863
--- /dev/null
+++ b/src/test/ui/map-types.rs
@@ -0,0 +1,19 @@
+#![feature(box_syntax)]
+
+use std::collections::HashMap;
+
+trait Map<K, V>
+{
+    fn get(&self, k: K) -> V { panic!() }
+}
+
+impl<K, V> Map<K, V> for HashMap<K, V> {}
+
+// Test that trait types printed in error msgs include the type arguments.
+
+fn main() {
+    let x: Box<HashMap<isize, isize>> = box HashMap::new();
+    let x: Box<Map<isize, isize>> = x;
+    let y: Box<Map<usize, isize>> = Box::new(x);
+    //~^ ERROR `std::boxed::Box<dyn Map<isize, isize>>: Map<usize, isize>` is not satisfied
+}
diff --git a/src/test/ui/map-types.stderr b/src/test/ui/map-types.stderr
new file mode 100644
index 0000000..9aa9804
--- /dev/null
+++ b/src/test/ui/map-types.stderr
@@ -0,0 +1,11 @@
+error[E0277]: the trait bound `std::boxed::Box<dyn Map<isize, isize>>: Map<usize, isize>` is not satisfied
+  --> $DIR/map-types.rs:17:37
+   |
+LL |     let y: Box<Map<usize, isize>> = Box::new(x);
+   |                                     ^^^^^^^^^^^ the trait `Map<usize, isize>` is not implemented for `std::boxed::Box<dyn Map<isize, isize>>`
+   |
+   = note: required for the cast to the object type `dyn Map<usize, isize>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/marker_trait_attr/marker-attribute-on-non-trait.rs b/src/test/ui/marker_trait_attr/marker-attribute-on-non-trait.rs
new file mode 100644
index 0000000..66156b6
--- /dev/null
+++ b/src/test/ui/marker_trait_attr/marker-attribute-on-non-trait.rs
@@ -0,0 +1,23 @@
+#![feature(marker_trait_attr)]
+
+#[marker] //~ ERROR attribute can only be applied to a trait
+struct Struct {}
+
+#[marker] //~ ERROR attribute can only be applied to a trait
+impl Struct {}
+
+#[marker] //~ ERROR attribute can only be applied to a trait
+union Union {
+    x: i32,
+}
+
+#[marker] //~ ERROR attribute can only be applied to a trait
+const CONST: usize = 10;
+
+#[marker] //~ ERROR attribute can only be applied to a trait
+fn function() {}
+
+#[marker] //~ ERROR attribute can only be applied to a trait
+type Type = ();
+
+fn main() {}
diff --git a/src/test/ui/marker_trait_attr/marker-attribute-on-non-trait.stderr b/src/test/ui/marker_trait_attr/marker-attribute-on-non-trait.stderr
new file mode 100644
index 0000000..d30b990
--- /dev/null
+++ b/src/test/ui/marker_trait_attr/marker-attribute-on-non-trait.stderr
@@ -0,0 +1,52 @@
+error: attribute can only be applied to a trait
+  --> $DIR/marker-attribute-on-non-trait.rs:3:1
+   |
+LL | #[marker]
+   | ^^^^^^^^^
+LL | struct Struct {}
+   | ---------------- not a trait
+
+error: attribute can only be applied to a trait
+  --> $DIR/marker-attribute-on-non-trait.rs:6:1
+   |
+LL | #[marker]
+   | ^^^^^^^^^
+LL | impl Struct {}
+   | -------------- not a trait
+
+error: attribute can only be applied to a trait
+  --> $DIR/marker-attribute-on-non-trait.rs:9:1
+   |
+LL |   #[marker]
+   |   ^^^^^^^^^
+LL | / union Union {
+LL | |     x: i32,
+LL | | }
+   | |_- not a trait
+
+error: attribute can only be applied to a trait
+  --> $DIR/marker-attribute-on-non-trait.rs:14:1
+   |
+LL | #[marker]
+   | ^^^^^^^^^
+LL | const CONST: usize = 10;
+   | ------------------------ not a trait
+
+error: attribute can only be applied to a trait
+  --> $DIR/marker-attribute-on-non-trait.rs:17:1
+   |
+LL | #[marker]
+   | ^^^^^^^^^
+LL | fn function() {}
+   | ---------------- not a trait
+
+error: attribute can only be applied to a trait
+  --> $DIR/marker-attribute-on-non-trait.rs:20:1
+   |
+LL | #[marker]
+   | ^^^^^^^^^
+LL | type Type = ();
+   | --------------- not a trait
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/marker_trait_attr/marker-attribute-with-values.rs b/src/test/ui/marker_trait_attr/marker-attribute-with-values.rs
new file mode 100644
index 0000000..f8bcec7
--- /dev/null
+++ b/src/test/ui/marker_trait_attr/marker-attribute-with-values.rs
@@ -0,0 +1,15 @@
+#![feature(marker_trait_attr)]
+
+#[marker(always)]
+trait Marker1 {}
+//~^^ ERROR attribute must be of the form
+
+#[marker("never")]
+trait Marker2 {}
+//~^^ ERROR attribute must be of the form
+
+#[marker(key = "value")]
+trait Marker3 {}
+//~^^ ERROR attribute must be of the form `#[marker]`
+
+fn main() {}
diff --git a/src/test/ui/marker_trait_attr/marker-attribute-with-values.stderr b/src/test/ui/marker_trait_attr/marker-attribute-with-values.stderr
new file mode 100644
index 0000000..2b31dcb
--- /dev/null
+++ b/src/test/ui/marker_trait_attr/marker-attribute-with-values.stderr
@@ -0,0 +1,20 @@
+error: attribute must be of the form `#[marker]`
+  --> $DIR/marker-attribute-with-values.rs:3:1
+   |
+LL | #[marker(always)]
+   | ^^^^^^^^^^^^^^^^^
+
+error: attribute must be of the form `#[marker]`
+  --> $DIR/marker-attribute-with-values.rs:7:1
+   |
+LL | #[marker("never")]
+   | ^^^^^^^^^^^^^^^^^^
+
+error: attribute must be of the form `#[marker]`
+  --> $DIR/marker-attribute-with-values.rs:11:1
+   |
+LL | #[marker(key = "value")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/marker_trait_attr/marker-trait-with-associated-items.rs b/src/test/ui/marker_trait_attr/marker-trait-with-associated-items.rs
new file mode 100644
index 0000000..a6e00ec
--- /dev/null
+++ b/src/test/ui/marker_trait_attr/marker-trait-with-associated-items.rs
@@ -0,0 +1,40 @@
+#![feature(marker_trait_attr)]
+#![feature(associated_type_defaults)]
+
+#[marker]
+trait MarkerConst {
+    const N: usize;
+    //~^ ERROR marker traits cannot have associated items
+}
+
+#[marker]
+trait MarkerType {
+    type Output;
+    //~^ ERROR marker traits cannot have associated items
+}
+
+#[marker]
+trait MarkerFn {
+    fn foo();
+    //~^ ERROR marker traits cannot have associated items
+}
+
+#[marker]
+trait MarkerConstWithDefault {
+    const N: usize = 43;
+    //~^ ERROR marker traits cannot have associated items
+}
+
+#[marker]
+trait MarkerTypeWithDefault {
+    type Output = ();
+    //~^ ERROR marker traits cannot have associated items
+}
+
+#[marker]
+trait MarkerFnWithDefault {
+    fn foo() {}
+    //~^ ERROR marker traits cannot have associated items
+}
+
+fn main() {}
diff --git a/src/test/ui/marker_trait_attr/marker-trait-with-associated-items.stderr b/src/test/ui/marker_trait_attr/marker-trait-with-associated-items.stderr
new file mode 100644
index 0000000..68434c1
--- /dev/null
+++ b/src/test/ui/marker_trait_attr/marker-trait-with-associated-items.stderr
@@ -0,0 +1,39 @@
+error[E0714]: marker traits cannot have associated items
+  --> $DIR/marker-trait-with-associated-items.rs:6:5
+   |
+LL |     const N: usize;
+   |     ^^^^^^^^^^^^^^^
+
+error[E0714]: marker traits cannot have associated items
+  --> $DIR/marker-trait-with-associated-items.rs:12:5
+   |
+LL |     type Output;
+   |     ^^^^^^^^^^^^
+
+error[E0714]: marker traits cannot have associated items
+  --> $DIR/marker-trait-with-associated-items.rs:18:5
+   |
+LL |     fn foo();
+   |     ^^^^^^^^^
+
+error[E0714]: marker traits cannot have associated items
+  --> $DIR/marker-trait-with-associated-items.rs:24:5
+   |
+LL |     const N: usize = 43;
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error[E0714]: marker traits cannot have associated items
+  --> $DIR/marker-trait-with-associated-items.rs:30:5
+   |
+LL |     type Output = ();
+   |     ^^^^^^^^^^^^^^^^^
+
+error[E0714]: marker traits cannot have associated items
+  --> $DIR/marker-trait-with-associated-items.rs:36:5
+   |
+LL |     fn foo() {}
+   |     ^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0714`.
diff --git a/src/test/ui/marker_trait_attr/overlap-marker-trait.rs b/src/test/ui/marker_trait_attr/overlap-marker-trait.rs
new file mode 100644
index 0000000..8794d42
--- /dev/null
+++ b/src/test/ui/marker_trait_attr/overlap-marker-trait.rs
@@ -0,0 +1,28 @@
+// Test for RFC 1268: we allow overlapping impls of marker traits,
+// that is, traits with #[marker]. In this case, a type `T` is
+// `MyMarker` if it is either `Debug` or `Display`. This test just
+// checks that we don't consider **all** types to be `MyMarker`.
+
+#![feature(marker_trait_attr)]
+
+use std::fmt::{Debug, Display};
+
+#[marker] trait Marker {}
+
+impl<T: Debug> Marker for T {}
+impl<T: Display> Marker for T {}
+
+fn is_marker<T: Marker>() { }
+
+struct NotDebugOrDisplay;
+
+fn main() {
+    // Debug && Display:
+    is_marker::<i32>();
+
+    // Debug && !Display:
+    is_marker::<Vec<i32>>();
+
+    // !Debug && !Display
+    is_marker::<NotDebugOrDisplay>(); //~ ERROR
+}
diff --git a/src/test/ui/marker_trait_attr/overlap-marker-trait.stderr b/src/test/ui/marker_trait_attr/overlap-marker-trait.stderr
new file mode 100644
index 0000000..f4a52a6
--- /dev/null
+++ b/src/test/ui/marker_trait_attr/overlap-marker-trait.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `NotDebugOrDisplay: Marker` is not satisfied
+  --> $DIR/overlap-marker-trait.rs:27:5
+   |
+LL |     is_marker::<NotDebugOrDisplay>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Marker` is not implemented for `NotDebugOrDisplay`
+   |
+note: required by `is_marker`
+  --> $DIR/overlap-marker-trait.rs:15:1
+   |
+LL | fn is_marker<T: Marker>() { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/marker_trait_attr/override-item-on-marker-trait.rs b/src/test/ui/marker_trait_attr/override-item-on-marker-trait.rs
new file mode 100644
index 0000000..5376fc8
--- /dev/null
+++ b/src/test/ui/marker_trait_attr/override-item-on-marker-trait.rs
@@ -0,0 +1,23 @@
+#![feature(marker_trait_attr)]
+
+#[marker]
+trait Marker {
+    const N: usize = 0;
+    fn do_something() {}
+}
+
+struct OverrideConst;
+impl Marker for OverrideConst {
+//~^ ERROR impls for marker traits cannot contain items
+    const N: usize = 1;
+}
+
+struct OverrideFn;
+impl Marker for OverrideFn {
+//~^ ERROR impls for marker traits cannot contain items
+    fn do_something() {
+        println!("Hello world!");
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/marker_trait_attr/override-item-on-marker-trait.stderr b/src/test/ui/marker_trait_attr/override-item-on-marker-trait.stderr
new file mode 100644
index 0000000..1d30c6d
--- /dev/null
+++ b/src/test/ui/marker_trait_attr/override-item-on-marker-trait.stderr
@@ -0,0 +1,15 @@
+error[E0715]: impls for marker traits cannot contain items
+  --> $DIR/override-item-on-marker-trait.rs:10:1
+   |
+LL | impl Marker for OverrideConst {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0715]: impls for marker traits cannot contain items
+  --> $DIR/override-item-on-marker-trait.rs:16:1
+   |
+LL | impl Marker for OverrideFn {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0715`.
diff --git a/src/test/ui/match-on-negative-integer-ranges.rs b/src/test/ui/match-on-negative-integer-ranges.rs
new file mode 100644
index 0000000..53e9ea9
--- /dev/null
+++ b/src/test/ui/match-on-negative-integer-ranges.rs
@@ -0,0 +1,7 @@
+// run-pass
+
+fn main() {
+    assert_eq!(false, match -50_i8 { -128i8..=-101i8 => true, _ => false, });
+
+    assert_eq!(false, if let -128i8..=-101i8 = -50_i8 { true } else { false });
+}
diff --git a/src/test/ui/match/match-argm-statics-2.rs b/src/test/ui/match/match-argm-statics-2.rs
new file mode 100644
index 0000000..ad220d2
--- /dev/null
+++ b/src/test/ui/match/match-argm-statics-2.rs
@@ -0,0 +1,63 @@
+use self::Direction::{North, East, South, West};
+
+#[derive(PartialEq, Eq)]
+struct NewBool(bool);
+
+#[derive(PartialEq, Eq)]
+enum Direction {
+    North,
+    East,
+    South,
+    West
+}
+
+const TRUE_TRUE: (bool, bool) = (true, true);
+
+fn nonexhaustive_1() {
+    match (true, false) {
+    //~^ ERROR non-exhaustive patterns: `(true, false)` not covered
+        TRUE_TRUE => (),
+        (false, false) => (),
+        (false, true) => ()
+    }
+}
+
+const NONE: Option<Direction> = None;
+const EAST: Direction = East;
+
+fn nonexhaustive_2() {
+    match Some(Some(North)) {
+    //~^ ERROR non-exhaustive patterns: `Some(Some(West))` not covered
+        Some(NONE) => (),
+        Some(Some(North)) => (),
+        Some(Some(EAST)) => (),
+        Some(Some(South)) => (),
+        None => ()
+    }
+}
+
+const NEW_FALSE: NewBool = NewBool(false);
+struct Foo {
+    bar: Option<Direction>,
+    baz: NewBool
+}
+
+const STATIC_FOO: Foo = Foo { bar: None, baz: NEW_FALSE };
+
+fn nonexhaustive_3() {
+    match (Foo { bar: Some(North), baz: NewBool(true) }) {
+    //~^ ERROR non-exhaustive patterns: `Foo { bar: Some(North), baz: NewBool(true) }`
+        Foo { bar: None, baz: NewBool(true) } => (),
+        Foo { bar: _, baz: NEW_FALSE } => (),
+        Foo { bar: Some(West), baz: NewBool(true) } => (),
+        Foo { bar: Some(South), .. } => (),
+        Foo { bar: Some(EAST), .. } => ()
+    }
+}
+
+fn main() {
+    nonexhaustive_1();
+    nonexhaustive_2();
+    nonexhaustive_3();
+}
+
diff --git a/src/test/ui/match/match-argm-statics-2.stderr b/src/test/ui/match/match-argm-statics-2.stderr
new file mode 100644
index 0000000..8c54e03
--- /dev/null
+++ b/src/test/ui/match/match-argm-statics-2.stderr
@@ -0,0 +1,33 @@
+error[E0004]: non-exhaustive patterns: `(true, false)` not covered
+  --> $DIR/match-argm-statics-2.rs:17:11
+   |
+LL |     match (true, false) {
+   |           ^^^^^^^^^^^^^ pattern `(true, false)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `Some(Some(West))` not covered
+  --> $DIR/match-argm-statics-2.rs:29:11
+   |
+LL |     match Some(Some(North)) {
+   |           ^^^^^^^^^^^^^^^^^ pattern `Some(Some(West))` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `Foo { bar: Some(North), baz: NewBool(true) }` not covered
+  --> $DIR/match-argm-statics-2.rs:48:11
+   |
+LL | / struct Foo {
+LL | |     bar: Option<Direction>,
+LL | |     baz: NewBool
+LL | | }
+   | |_- `Foo` defined here
+...
+LL |       match (Foo { bar: Some(North), baz: NewBool(true) }) {
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo { bar: Some(North), baz: NewBool(true) }` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/match/match-arm-statics.rs b/src/test/ui/match/match-arm-statics.rs
new file mode 100644
index 0000000..91db76e
--- /dev/null
+++ b/src/test/ui/match/match-arm-statics.rs
@@ -0,0 +1,69 @@
+#![allow(dead_code)]
+#![deny(unreachable_patterns)]
+
+use self::Direction::{North, East, South, West};
+
+#[derive(PartialEq, Eq)]
+struct NewBool(bool);
+
+#[derive(PartialEq, Eq)]
+enum Direction {
+    North,
+    East,
+    South,
+    West
+}
+
+const TRUE_TRUE: (bool, bool) = (true, true);
+
+fn unreachable_1() {
+    match (true, false) {
+        TRUE_TRUE => (),
+        (false, false) => (),
+        (false, true) => (),
+        (true, false) => (),
+        (true, true) => ()
+        //~^ ERROR unreachable pattern
+    }
+}
+
+const NONE: Option<Direction> = None;
+const EAST: Direction = East;
+
+fn unreachable_2() {
+    match Some(Some(North)) {
+        Some(NONE) => (),
+        Some(Some(North)) => (),
+        Some(Some(EAST)) => (),
+        Some(Some(South)) => (),
+        Some(Some(West)) => (),
+        Some(Some(East)) => (),
+        //~^ ERROR unreachable pattern
+        None => ()
+    }
+}
+
+const NEW_FALSE: NewBool = NewBool(false);
+struct Foo {
+    bar: Option<Direction>,
+    baz: NewBool
+}
+
+fn unreachable_3() {
+    match (Foo { bar: Some(EAST), baz: NewBool(true) }) {
+        Foo { bar: None, baz: NewBool(true) } => (),
+        Foo { bar: _, baz: NEW_FALSE } => (),
+        Foo { bar: Some(West), baz: NewBool(true) } => (),
+        Foo { bar: Some(South), .. } => (),
+        Foo { bar: Some(EAST), .. } => (),
+        Foo { bar: Some(North), baz: NewBool(true) } => (),
+        Foo { bar: Some(EAST), baz: NewBool(false) } => ()
+        //~^ ERROR unreachable pattern
+    }
+}
+
+fn main() {
+    unreachable_1();
+    unreachable_2();
+    unreachable_3();
+}
diff --git a/src/test/ui/match/match-arm-statics.stderr b/src/test/ui/match/match-arm-statics.stderr
new file mode 100644
index 0000000..3d9e900
--- /dev/null
+++ b/src/test/ui/match/match-arm-statics.stderr
@@ -0,0 +1,26 @@
+error: unreachable pattern
+  --> $DIR/match-arm-statics.rs:25:9
+   |
+LL |         (true, true) => ()
+   |         ^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/match-arm-statics.rs:2:9
+   |
+LL | #![deny(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/match-arm-statics.rs:40:9
+   |
+LL |         Some(Some(East)) => (),
+   |         ^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/match-arm-statics.rs:60:9
+   |
+LL |         Foo { bar: Some(EAST), baz: NewBool(false) } => ()
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/match/match-byte-array-patterns-2.rs b/src/test/ui/match/match-byte-array-patterns-2.rs
new file mode 100644
index 0000000..a3a47d2
--- /dev/null
+++ b/src/test/ui/match/match-byte-array-patterns-2.rs
@@ -0,0 +1,14 @@
+fn main() {
+    let buf = &[0, 1, 2, 3];
+
+    match buf { //~ ERROR non-exhaustive
+        b"AAAA" => {}
+    }
+
+    let buf: &[u8] = buf;
+
+    match buf { //~ ERROR non-exhaustive
+        b"AAAA" => {}
+    }
+}
+
diff --git a/src/test/ui/match/match-byte-array-patterns-2.stderr b/src/test/ui/match/match-byte-array-patterns-2.stderr
new file mode 100644
index 0000000..d53e2e2
--- /dev/null
+++ b/src/test/ui/match/match-byte-array-patterns-2.stderr
@@ -0,0 +1,19 @@
+error[E0004]: non-exhaustive patterns: `&[_, _, _, _]` not covered
+  --> $DIR/match-byte-array-patterns-2.rs:4:11
+   |
+LL |     match buf {
+   |           ^^^ pattern `&[_, _, _, _]` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `&[]`, `&[_]`, `&[_, _]` and 3 more not covered
+  --> $DIR/match-byte-array-patterns-2.rs:10:11
+   |
+LL |     match buf {
+   |           ^^^ patterns `&[]`, `&[_]`, `&[_, _]` and 3 more not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/match/match-byte-array-patterns.rs b/src/test/ui/match/match-byte-array-patterns.rs
new file mode 100644
index 0000000..7541ea3
--- /dev/null
+++ b/src/test/ui/match/match-byte-array-patterns.rs
@@ -0,0 +1,56 @@
+#![feature(slice_patterns)]
+#![deny(unreachable_patterns)]
+
+fn main() {
+    let buf = &[0, 1, 2, 3];
+
+    match buf {
+        b"AAAA" => {},
+        &[0x41, 0x41, 0x41, 0x41] => {} //~ ERROR unreachable pattern
+        _ => {}
+    }
+
+    match buf {
+        &[0x41, 0x41, 0x41, 0x41] => {}
+        b"AAAA" => {}, //~ ERROR unreachable pattern
+        _ => {}
+    }
+
+    match buf {
+        &[_, 0x41, 0x41, 0x41] => {},
+        b"AAAA" => {}, //~ ERROR unreachable pattern
+        _ => {}
+    }
+
+    match buf {
+        &[0x41, .., 0x41] => {}
+        b"AAAA" => {}, //~ ERROR unreachable pattern
+        _ => {}
+    }
+
+    let buf: &[u8] = buf;
+
+    match buf {
+        b"AAAA" => {},
+        &[0x41, 0x41, 0x41, 0x41] => {} //~ ERROR unreachable pattern
+        _ => {}
+    }
+
+    match buf {
+        &[0x41, 0x41, 0x41, 0x41] => {}
+        b"AAAA" => {}, //~ ERROR unreachable pattern
+        _ => {}
+    }
+
+    match buf {
+        &[_, 0x41, 0x41, 0x41] => {},
+        b"AAAA" => {}, //~ ERROR unreachable pattern
+        _ => {}
+    }
+
+    match buf {
+        &[0x41, .., 0x41] => {}
+        b"AAAA" => {}, //~ ERROR unreachable pattern
+        _ => {}
+    }
+}
diff --git a/src/test/ui/match/match-byte-array-patterns.stderr b/src/test/ui/match/match-byte-array-patterns.stderr
new file mode 100644
index 0000000..b28646b
--- /dev/null
+++ b/src/test/ui/match/match-byte-array-patterns.stderr
@@ -0,0 +1,56 @@
+error: unreachable pattern
+  --> $DIR/match-byte-array-patterns.rs:9:9
+   |
+LL |         &[0x41, 0x41, 0x41, 0x41] => {}
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/match-byte-array-patterns.rs:2:9
+   |
+LL | #![deny(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/match-byte-array-patterns.rs:15:9
+   |
+LL |         b"AAAA" => {},
+   |         ^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/match-byte-array-patterns.rs:21:9
+   |
+LL |         b"AAAA" => {},
+   |         ^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/match-byte-array-patterns.rs:27:9
+   |
+LL |         b"AAAA" => {},
+   |         ^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/match-byte-array-patterns.rs:35:9
+   |
+LL |         &[0x41, 0x41, 0x41, 0x41] => {}
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/match-byte-array-patterns.rs:41:9
+   |
+LL |         b"AAAA" => {},
+   |         ^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/match-byte-array-patterns.rs:47:9
+   |
+LL |         b"AAAA" => {},
+   |         ^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/match-byte-array-patterns.rs:53:9
+   |
+LL |         b"AAAA" => {},
+   |         ^^^^^^^
+
+error: aborting due to 8 previous errors
+
diff --git a/src/test/ui/match/match-fn-call.rs b/src/test/ui/match/match-fn-call.rs
new file mode 100644
index 0000000..d9c50e7
--- /dev/null
+++ b/src/test/ui/match/match-fn-call.rs
@@ -0,0 +1,12 @@
+use std::path::Path;
+
+fn main() {
+    let path = Path::new("foo");
+    match path {
+        Path::new("foo") => println!("foo"),
+        //~^ ERROR expected tuple struct/variant
+        Path::new("bar") => println!("bar"),
+        //~^ ERROR expected tuple struct/variant
+        _ => (),
+    }
+}
diff --git a/src/test/ui/match/match-fn-call.stderr b/src/test/ui/match/match-fn-call.stderr
new file mode 100644
index 0000000..4e24621
--- /dev/null
+++ b/src/test/ui/match/match-fn-call.stderr
@@ -0,0 +1,15 @@
+error[E0164]: expected tuple struct/variant, found method `<Path>::new`
+  --> $DIR/match-fn-call.rs:6:9
+   |
+LL |         Path::new("foo") => println!("foo"),
+   |         ^^^^^^^^^^^^^^^^ not a tuple variant or struct
+
+error[E0164]: expected tuple struct/variant, found method `<Path>::new`
+  --> $DIR/match-fn-call.rs:8:9
+   |
+LL |         Path::new("bar") => println!("bar"),
+   |         ^^^^^^^^^^^^^^^^ not a tuple variant or struct
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0164`.
diff --git a/src/test/ui/match/match-ill-type2.rs b/src/test/ui/match/match-ill-type2.rs
new file mode 100644
index 0000000..6612f6e
--- /dev/null
+++ b/src/test/ui/match/match-ill-type2.rs
@@ -0,0 +1,7 @@
+fn main() {
+    match 1i32 {
+        1i32 => 1,
+        2u32 => 1, //~ ERROR mismatched types
+        _ => 2,
+    };
+}
diff --git a/src/test/ui/match/match-ill-type2.stderr b/src/test/ui/match/match-ill-type2.stderr
new file mode 100644
index 0000000..83fae10
--- /dev/null
+++ b/src/test/ui/match/match-ill-type2.stderr
@@ -0,0 +1,9 @@
+error[E0308]: mismatched types
+  --> $DIR/match-ill-type2.rs:4:9
+   |
+LL |         2u32 => 1,
+   |         ^^^^ expected i32, found u32
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/match/match-join.rs b/src/test/ui/match/match-join.rs
new file mode 100644
index 0000000..b0f2593
--- /dev/null
+++ b/src/test/ui/match/match-join.rs
@@ -0,0 +1,11 @@
+// a good test that we merge paths correctly in the presence of a
+// variable that's used before it's declared
+
+fn my_panic() -> ! { panic!(); }
+
+fn main() {
+    match true { false => { my_panic(); } true => { } }
+
+    println!("{}", x); //~ ERROR cannot find value `x` in this scope
+    let x: isize;
+}
diff --git a/src/test/ui/match/match-join.stderr b/src/test/ui/match/match-join.stderr
new file mode 100644
index 0000000..27a82c1
--- /dev/null
+++ b/src/test/ui/match/match-join.stderr
@@ -0,0 +1,9 @@
+error[E0425]: cannot find value `x` in this scope
+  --> $DIR/match-join.rs:9:20
+   |
+LL |     println!("{}", x);
+   |                    ^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/match/match-no-arms-unreachable-after.rs b/src/test/ui/match/match-no-arms-unreachable-after.rs
new file mode 100644
index 0000000..8f83fd1
--- /dev/null
+++ b/src/test/ui/match/match-no-arms-unreachable-after.rs
@@ -0,0 +1,12 @@
+#![allow(warnings)]
+#![deny(unreachable_code)]
+
+enum Void { }
+
+fn foo(v: Void) {
+    match v { }
+    let x = 2; //~ ERROR unreachable
+}
+
+fn main() {
+}
diff --git a/src/test/ui/match/match-no-arms-unreachable-after.stderr b/src/test/ui/match/match-no-arms-unreachable-after.stderr
new file mode 100644
index 0000000..65dcc6e
--- /dev/null
+++ b/src/test/ui/match/match-no-arms-unreachable-after.stderr
@@ -0,0 +1,14 @@
+error: unreachable statement
+  --> $DIR/match-no-arms-unreachable-after.rs:8:5
+   |
+LL |     let x = 2;
+   |     ^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/match-no-arms-unreachable-after.rs:2:9
+   |
+LL | #![deny(unreachable_code)]
+   |         ^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/match/match-non-exhaustive.rs b/src/test/ui/match/match-non-exhaustive.rs
new file mode 100644
index 0000000..3b210a1
--- /dev/null
+++ b/src/test/ui/match/match-non-exhaustive.rs
@@ -0,0 +1,4 @@
+fn main() {
+    match 0 { 1 => () } //~ ERROR non-exhaustive patterns
+    match 0 { 0 if false => () } //~ ERROR non-exhaustive patterns
+}
diff --git a/src/test/ui/match/match-non-exhaustive.stderr b/src/test/ui/match/match-non-exhaustive.stderr
new file mode 100644
index 0000000..00c2bff
--- /dev/null
+++ b/src/test/ui/match/match-non-exhaustive.stderr
@@ -0,0 +1,19 @@
+error[E0004]: non-exhaustive patterns: `-2147483648i32..=0i32` and `2i32..=2147483647i32` not covered
+  --> $DIR/match-non-exhaustive.rs:2:11
+   |
+LL |     match 0 { 1 => () }
+   |           ^ patterns `-2147483648i32..=0i32` and `2i32..=2147483647i32` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `_` not covered
+  --> $DIR/match-non-exhaustive.rs:3:11
+   |
+LL |     match 0 { 0 if false => () }
+   |           ^ pattern `_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/match/match-pattern-field-mismatch-2.rs b/src/test/ui/match/match-pattern-field-mismatch-2.rs
new file mode 100644
index 0000000..3351c75
--- /dev/null
+++ b/src/test/ui/match/match-pattern-field-mismatch-2.rs
@@ -0,0 +1,16 @@
+fn main() {
+    enum Color {
+        Rgb(usize, usize, usize),
+        Cmyk(usize, usize, usize, usize),
+        NoColor,
+    }
+
+    fn foo(c: Color) {
+        match c {
+          Color::Rgb(_, _, _) => { }
+          Color::Cmyk(_, _, _, _) => { }
+          Color::NoColor(_) => { }
+          //~^ ERROR expected tuple struct/variant, found unit variant `Color::NoColor`
+        }
+    }
+}
diff --git a/src/test/ui/match/match-pattern-field-mismatch-2.stderr b/src/test/ui/match/match-pattern-field-mismatch-2.stderr
new file mode 100644
index 0000000..a42d62e
--- /dev/null
+++ b/src/test/ui/match/match-pattern-field-mismatch-2.stderr
@@ -0,0 +1,9 @@
+error[E0532]: expected tuple struct/variant, found unit variant `Color::NoColor`
+  --> $DIR/match-pattern-field-mismatch-2.rs:12:11
+   |
+LL |           Color::NoColor(_) => { }
+   |           ^^^^^^^^^^^^^^ not a tuple struct/variant
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0532`.
diff --git a/src/test/ui/match/match-pattern-field-mismatch.rs b/src/test/ui/match/match-pattern-field-mismatch.rs
new file mode 100644
index 0000000..1266aec
--- /dev/null
+++ b/src/test/ui/match/match-pattern-field-mismatch.rs
@@ -0,0 +1,16 @@
+fn main() {
+    enum Color {
+        Rgb(usize, usize, usize),
+        Cmyk(usize, usize, usize, usize),
+        NoColor,
+    }
+
+    fn foo(c: Color) {
+        match c {
+          Color::Rgb(_, _) => { }
+          //~^ ERROR this pattern has 2 fields, but the corresponding tuple variant has 3 fields
+          Color::Cmyk(_, _, _, _) => { }
+          Color::NoColor => { }
+        }
+    }
+}
diff --git a/src/test/ui/match/match-pattern-field-mismatch.stderr b/src/test/ui/match/match-pattern-field-mismatch.stderr
new file mode 100644
index 0000000..663cd2c
--- /dev/null
+++ b/src/test/ui/match/match-pattern-field-mismatch.stderr
@@ -0,0 +1,9 @@
+error[E0023]: this pattern has 2 fields, but the corresponding tuple variant has 3 fields
+  --> $DIR/match-pattern-field-mismatch.rs:10:11
+   |
+LL |           Color::Rgb(_, _) => { }
+   |           ^^^^^^^^^^^^^^^^ expected 3 fields, found 2
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0023`.
diff --git a/src/test/ui/match/match-privately-empty.rs b/src/test/ui/match/match-privately-empty.rs
new file mode 100644
index 0000000..315eb03
--- /dev/null
+++ b/src/test/ui/match/match-privately-empty.rs
@@ -0,0 +1,21 @@
+#![feature(never_type)]
+#![feature(exhaustive_patterns)]
+
+mod private {
+    pub struct Private {
+        _bot: !,
+        pub misc: bool,
+    }
+    pub const DATA: Option<Private> = None;
+}
+
+fn main() {
+    match private::DATA {
+    //~^ ERROR non-exhaustive patterns: `Some(Private { misc: true, .. })` not covered
+        None => {}
+        Some(private::Private {
+            misc: false,
+            ..
+        }) => {}
+    }
+}
diff --git a/src/test/ui/match/match-privately-empty.stderr b/src/test/ui/match/match-privately-empty.stderr
new file mode 100644
index 0000000..f79d180
--- /dev/null
+++ b/src/test/ui/match/match-privately-empty.stderr
@@ -0,0 +1,11 @@
+error[E0004]: non-exhaustive patterns: `Some(Private { misc: true, .. })` not covered
+  --> $DIR/match-privately-empty.rs:13:11
+   |
+LL |     match private::DATA {
+   |           ^^^^^^^^^^^^^ pattern `Some(Private { misc: true, .. })` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/match/match-range-fail-2.rs b/src/test/ui/match/match-range-fail-2.rs
new file mode 100644
index 0000000..19e6e12
--- /dev/null
+++ b/src/test/ui/match/match-range-fail-2.rs
@@ -0,0 +1,21 @@
+#![feature(exclusive_range_pattern)]
+
+fn main() {
+    match 5 {
+        6 ..= 1 => { }
+        _ => { }
+    };
+    //~^^^ ERROR lower range bound must be less than or equal to upper
+
+    match 5 {
+        0 .. 0 => { }
+        _ => { }
+    };
+    //~^^^ ERROR lower range bound must be less than upper
+
+    match 5u64 {
+        0xFFFF_FFFF_FFFF_FFFF ..= 1 => { }
+        _ => { }
+    };
+    //~^^^ ERROR lower range bound must be less than or equal to upper
+}
diff --git a/src/test/ui/match/match-range-fail-2.stderr b/src/test/ui/match/match-range-fail-2.stderr
new file mode 100644
index 0000000..b9e4534
--- /dev/null
+++ b/src/test/ui/match/match-range-fail-2.stderr
@@ -0,0 +1,22 @@
+error[E0030]: lower range bound must be less than or equal to upper
+  --> $DIR/match-range-fail-2.rs:5:9
+   |
+LL |         6 ..= 1 => { }
+   |         ^ lower bound larger than upper bound
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/match-range-fail-2.rs:11:9
+   |
+LL |         0 .. 0 => { }
+   |         ^
+
+error[E0030]: lower range bound must be less than or equal to upper
+  --> $DIR/match-range-fail-2.rs:17:9
+   |
+LL |         0xFFFF_FFFF_FFFF_FFFF ..= 1 => { }
+   |         ^^^^^^^^^^^^^^^^^^^^^ lower bound larger than upper bound
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0030, E0579.
+For more information about an error, try `rustc --explain E0030`.
diff --git a/src/test/ui/match/match-range-fail-dominate.rs b/src/test/ui/match/match-range-fail-dominate.rs
new file mode 100644
index 0000000..9906918
--- /dev/null
+++ b/src/test/ui/match/match-range-fail-dominate.rs
@@ -0,0 +1,39 @@
+//error-pattern: unreachable
+//error-pattern: unreachable
+//error-pattern: unreachable
+//error-pattern: unreachable
+//error-pattern: unreachable
+
+#![deny(unreachable_patterns)]
+
+fn main() {
+    match 5 {
+      1 ... 10 => { }
+      5 ... 6 => { }
+      _ => {}
+    };
+
+    match 5 {
+      3 ... 6 => { }
+      4 ... 6 => { }
+      _ => {}
+    };
+
+    match 5 {
+      4 ... 6 => { }
+      4 ... 6 => { }
+      _ => {}
+    };
+
+    match 'c' {
+      'A' ... 'z' => {}
+      'a' ... 'z' => {}
+      _ => {}
+    };
+
+    match 1.0f64 {
+      0.01f64 ... 6.5f64 => {}
+      0.02f64 => {}
+      _ => {}
+    };
+}
diff --git a/src/test/ui/match/match-range-fail-dominate.stderr b/src/test/ui/match/match-range-fail-dominate.stderr
new file mode 100644
index 0000000..d35394aa
--- /dev/null
+++ b/src/test/ui/match/match-range-fail-dominate.stderr
@@ -0,0 +1,66 @@
+error: unreachable pattern
+  --> $DIR/match-range-fail-dominate.rs:12:7
+   |
+LL |       5 ... 6 => { }
+   |       ^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/match-range-fail-dominate.rs:7:9
+   |
+LL | #![deny(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/match-range-fail-dominate.rs:18:7
+   |
+LL |       4 ... 6 => { }
+   |       ^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/match-range-fail-dominate.rs:24:7
+   |
+LL |       4 ... 6 => { }
+   |       ^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/match-range-fail-dominate.rs:30:7
+   |
+LL |       'a' ... 'z' => {}
+   |       ^^^^^^^^^^^
+
+warning: floating-point types cannot be used in patterns
+  --> $DIR/match-range-fail-dominate.rs:35:7
+   |
+LL |       0.01f64 ... 6.5f64 => {}
+   |       ^^^^^^^
+   |
+   = note: #[warn(illegal_floating_point_literal_pattern)] on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+warning: floating-point types cannot be used in patterns
+  --> $DIR/match-range-fail-dominate.rs:35:19
+   |
+LL |       0.01f64 ... 6.5f64 => {}
+   |                   ^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+warning: floating-point types cannot be used in patterns
+  --> $DIR/match-range-fail-dominate.rs:36:7
+   |
+LL |       0.02f64 => {}
+   |       ^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: unreachable pattern
+  --> $DIR/match-range-fail-dominate.rs:36:7
+   |
+LL |       0.02f64 => {}
+   |       ^^^^^^^
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/ui/match/match-range-fail.rs b/src/test/ui/match/match-range-fail.rs
new file mode 100644
index 0000000..8a36785
--- /dev/null
+++ b/src/test/ui/match/match-range-fail.rs
@@ -0,0 +1,23 @@
+fn main() {
+    match "wow" {
+        "bar" ..= "foo" => { }
+    };
+    //~^^ ERROR only char and numeric types are allowed in range
+    //~| start type: &'static str
+    //~| end type: &'static str
+
+    match "wow" {
+        10 ..= "what" => ()
+    };
+    //~^^ ERROR only char and numeric types are allowed in range
+    //~| start type: {integer}
+    //~| end type: &'static str
+
+    match 5 {
+        'c' ..= 100 => { }
+        _ => { }
+    };
+    //~^^^ ERROR mismatched types
+    //~| expected type `{integer}`
+    //~| found type `char`
+}
diff --git a/src/test/ui/match/match-range-fail.stderr b/src/test/ui/match/match-range-fail.stderr
new file mode 100644
index 0000000..5496992
--- /dev/null
+++ b/src/test/ui/match/match-range-fail.stderr
@@ -0,0 +1,31 @@
+error[E0029]: only char and numeric types are allowed in range patterns
+  --> $DIR/match-range-fail.rs:3:9
+   |
+LL |         "bar" ..= "foo" => { }
+   |         ^^^^^^^^^^^^^^^ ranges require char or numeric types
+   |
+   = note: start type: &'static str
+   = note: end type: &'static str
+
+error[E0029]: only char and numeric types are allowed in range patterns
+  --> $DIR/match-range-fail.rs:10:16
+   |
+LL |         10 ..= "what" => ()
+   |                ^^^^^^ ranges require char or numeric types
+   |
+   = note: start type: {integer}
+   = note: end type: &'static str
+
+error[E0308]: mismatched types
+  --> $DIR/match-range-fail.rs:17:9
+   |
+LL |         'c' ..= 100 => { }
+   |         ^^^^^^^^^^^ expected integer, found char
+   |
+   = note: expected type `{integer}`
+              found type `char`
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0029, E0308.
+For more information about an error, try `rustc --explain E0029`.
diff --git a/src/test/ui/match/match-ref-ice.rs b/src/test/ui/match/match-ref-ice.rs
new file mode 100644
index 0000000..dee110f
--- /dev/null
+++ b/src/test/ui/match/match-ref-ice.rs
@@ -0,0 +1,16 @@
+#![deny(unreachable_patterns)]
+
+// The arity of `ref x` is always 1. If the pattern is compared to some non-structural type whose
+// arity is always 0, an ICE occurs.
+//
+// Related issue: #23009
+
+fn main() {
+    let homura = [1, 2, 3];
+
+    match homura {
+        [1, ref _madoka, 3] => (),
+        [1, 2, 3] => (), //~ ERROR unreachable pattern
+        [_, _, _] => (),
+    }
+}
diff --git a/src/test/ui/match/match-ref-ice.stderr b/src/test/ui/match/match-ref-ice.stderr
new file mode 100644
index 0000000..c4bfa0a
--- /dev/null
+++ b/src/test/ui/match/match-ref-ice.stderr
@@ -0,0 +1,14 @@
+error: unreachable pattern
+  --> $DIR/match-ref-ice.rs:13:9
+   |
+LL |         [1, 2, 3] => (),
+   |         ^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/match-ref-ice.rs:1:9
+   |
+LL | #![deny(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/match/match-ref-mut-invariance.rs b/src/test/ui/match/match-ref-mut-invariance.rs
new file mode 100644
index 0000000..50b0ede
--- /dev/null
+++ b/src/test/ui/match/match-ref-mut-invariance.rs
@@ -0,0 +1,14 @@
+// Check that when making a ref mut binding with type `&mut T`, the
+// type `T` must match precisely the type `U` of the value being
+// matched, and in particular cannot be some supertype of `U`. Issue
+// #23116. This test focuses on a `match`.
+
+#![allow(dead_code)]
+struct S<'b>(&'b i32);
+impl<'b> S<'b> {
+    fn bar<'a>(&'a mut self) -> &'a mut &'a i32 {
+        match self.0 { ref mut x => x } //~ ERROR mismatched types
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/match/match-ref-mut-invariance.stderr b/src/test/ui/match/match-ref-mut-invariance.stderr
new file mode 100644
index 0000000..30bbb8d7
--- /dev/null
+++ b/src/test/ui/match/match-ref-mut-invariance.stderr
@@ -0,0 +1,22 @@
+error[E0308]: mismatched types
+  --> $DIR/match-ref-mut-invariance.rs:10:37
+   |
+LL |         match self.0 { ref mut x => x }
+   |                                     ^ lifetime mismatch
+   |
+   = note: expected type `&'a mut &'a i32`
+              found type `&'a mut &'b i32`
+note: the lifetime 'a as defined on the method body at 9:12...
+  --> $DIR/match-ref-mut-invariance.rs:9:12
+   |
+LL |     fn bar<'a>(&'a mut self) -> &'a mut &'a i32 {
+   |            ^^
+note: ...does not necessarily outlive the lifetime 'b as defined on the impl at 8:6
+  --> $DIR/match-ref-mut-invariance.rs:8:6
+   |
+LL | impl<'b> S<'b> {
+   |      ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/match/match-ref-mut-let-invariance.rs b/src/test/ui/match/match-ref-mut-let-invariance.rs
new file mode 100644
index 0000000..a62eb71
--- /dev/null
+++ b/src/test/ui/match/match-ref-mut-let-invariance.rs
@@ -0,0 +1,15 @@
+// Check that when making a ref mut binding with type `&mut T`, the
+// type `T` must match precisely the type `U` of the value being
+// matched, and in particular cannot be some supertype of `U`. Issue
+// #23116. This test focuses on a `let`.
+
+#![allow(dead_code)]
+struct S<'b>(&'b i32);
+impl<'b> S<'b> {
+    fn bar<'a>(&'a mut self) -> &'a mut &'a i32 {
+        let ref mut x = self.0;
+        x //~ ERROR mismatched types
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/match/match-ref-mut-let-invariance.stderr b/src/test/ui/match/match-ref-mut-let-invariance.stderr
new file mode 100644
index 0000000..6ca222d
--- /dev/null
+++ b/src/test/ui/match/match-ref-mut-let-invariance.stderr
@@ -0,0 +1,22 @@
+error[E0308]: mismatched types
+  --> $DIR/match-ref-mut-let-invariance.rs:11:9
+   |
+LL |         x
+   |         ^ lifetime mismatch
+   |
+   = note: expected type `&'a mut &'a i32`
+              found type `&'a mut &'b i32`
+note: the lifetime 'a as defined on the method body at 9:12...
+  --> $DIR/match-ref-mut-let-invariance.rs:9:12
+   |
+LL |     fn bar<'a>(&'a mut self) -> &'a mut &'a i32 {
+   |            ^^
+note: ...does not necessarily outlive the lifetime 'b as defined on the impl at 8:6
+  --> $DIR/match-ref-mut-let-invariance.rs:8:6
+   |
+LL | impl<'b> S<'b> {
+   |      ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/match/match-ref-mut-stability.rs b/src/test/ui/match/match-ref-mut-stability.rs
new file mode 100644
index 0000000..795a3fc
--- /dev/null
+++ b/src/test/ui/match/match-ref-mut-stability.rs
@@ -0,0 +1,39 @@
+// Check that `ref mut` variables don't change address between the match guard
+// and the arm expression.
+
+// run-pass
+
+#![feature(nll, bind_by_move_pattern_guards)]
+
+// Test that z always point to the same temporary.
+fn referent_stability() {
+    let p;
+    match 0 {
+        ref mut z if { p = z as *const _; true } => assert_eq!(p, z as *const _),
+        _ => unreachable!(),
+    };
+}
+
+// Test that z is always effectively the same variable.
+fn variable_stability() {
+    let p;
+    match 0 {
+        ref mut z if { p = &z as *const _; true } => assert_eq!(p, &z as *const _),
+        _ => unreachable!(),
+    };
+}
+
+// Test that a borrow of *z can cross from the guard to the arm.
+fn persist_borrow() {
+    let r;
+    match 0 {
+        ref mut z if { r = z as &_; true } => assert_eq!(*r, 0),
+        _ => unreachable!(),
+    }
+}
+
+fn main() {
+    referent_stability();
+    variable_stability();
+    persist_borrow();
+}
diff --git a/src/test/ui/match/match-slice-patterns.rs b/src/test/ui/match/match-slice-patterns.rs
new file mode 100644
index 0000000..afbeb61
--- /dev/null
+++ b/src/test/ui/match/match-slice-patterns.rs
@@ -0,0 +1,14 @@
+#![feature(slice_patterns)]
+
+fn check(list: &[Option<()>]) {
+    match list {
+    //~^ ERROR `&[_, Some(_), None, _]` not covered
+        &[] => {},
+        &[_] => {},
+        &[_, _] => {},
+        &[_, None, ..] => {},
+        &[.., Some(_), _] => {},
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/match/match-slice-patterns.stderr b/src/test/ui/match/match-slice-patterns.stderr
new file mode 100644
index 0000000..24769db
--- /dev/null
+++ b/src/test/ui/match/match-slice-patterns.stderr
@@ -0,0 +1,11 @@
+error[E0004]: non-exhaustive patterns: `&[_, Some(_), None, _]` not covered
+  --> $DIR/match-slice-patterns.rs:4:11
+   |
+LL |     match list {
+   |           ^^^^ pattern `&[_, Some(_), None, _]` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/match/match-struct.rs b/src/test/ui/match/match-struct.rs
new file mode 100644
index 0000000..5961e09
--- /dev/null
+++ b/src/test/ui/match/match-struct.rs
@@ -0,0 +1,13 @@
+struct S { a: isize }
+enum E { C(isize) }
+
+fn main() {
+    match (S { a: 1 }) {
+        E::C(_) => (),
+        //~^ ERROR mismatched types
+        //~| expected type `S`
+        //~| found type `E`
+        //~| expected struct `S`, found enum `E`
+        _ => ()
+    }
+}
diff --git a/src/test/ui/match/match-struct.stderr b/src/test/ui/match/match-struct.stderr
new file mode 100644
index 0000000..2a24a29
--- /dev/null
+++ b/src/test/ui/match/match-struct.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/match-struct.rs:6:9
+   |
+LL |     match (S { a: 1 }) {
+   |           ------------ this match expression has type `S`
+LL |         E::C(_) => (),
+   |         ^^^^^^^ expected struct `S`, found enum `E`
+   |
+   = note: expected type `S`
+              found type `E`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/match/match-tag-nullary.rs b/src/test/ui/match/match-tag-nullary.rs
new file mode 100644
index 0000000..bb2f599
--- /dev/null
+++ b/src/test/ui/match/match-tag-nullary.rs
@@ -0,0 +1,4 @@
+enum A { A }
+enum B { B }
+
+fn main() { let x: A = A::A; match x { B::B => { } } } //~ ERROR mismatched types
diff --git a/src/test/ui/match/match-tag-nullary.stderr b/src/test/ui/match/match-tag-nullary.stderr
new file mode 100644
index 0000000..902ccc9
--- /dev/null
+++ b/src/test/ui/match/match-tag-nullary.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/match-tag-nullary.rs:4:40
+   |
+LL | fn main() { let x: A = A::A; match x { B::B => { } } }
+   |                                        ^^^^ expected enum `A`, found enum `B`
+   |
+   = note: expected type `A`
+              found type `B`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/match/match-tag-unary.rs b/src/test/ui/match/match-tag-unary.rs
new file mode 100644
index 0000000..aedceaf
--- /dev/null
+++ b/src/test/ui/match/match-tag-unary.rs
@@ -0,0 +1,4 @@
+enum A { A(isize) }
+enum B { B(isize) }
+
+fn main() { let x: A = A::A(0); match x { B::B(y) => { } } } //~ ERROR mismatched types
diff --git a/src/test/ui/match/match-tag-unary.stderr b/src/test/ui/match/match-tag-unary.stderr
new file mode 100644
index 0000000..da599c3
--- /dev/null
+++ b/src/test/ui/match/match-tag-unary.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/match-tag-unary.rs:4:43
+   |
+LL | fn main() { let x: A = A::A(0); match x { B::B(y) => { } } }
+   |                                       -   ^^^^^^^ expected enum `A`, found enum `B`
+   |                                       |
+   |                                       this match expression has type `A`
+   |
+   = note: expected type `A`
+              found type `B`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/match/match-type-err-first-arm.rs b/src/test/ui/match/match-type-err-first-arm.rs
new file mode 100644
index 0000000..b4b84ef
--- /dev/null
+++ b/src/test/ui/match/match-type-err-first-arm.rs
@@ -0,0 +1,45 @@
+fn main() {
+    let _ = test_func1(1);
+    let _ = test_func2(1);
+}
+
+fn test_func1(n: i32) -> i32 {
+    //~^ NOTE expected `i32` because of return type
+    match n {
+        12 => 'b',
+        //~^ ERROR mismatched types
+        //~| NOTE expected i32, found char
+        _ => 42,
+    }
+}
+
+fn test_func2(n: i32) -> i32 {
+    let x = match n {
+    //~^ NOTE `match` arms have incompatible types
+        12 => 'b',
+        //~^ NOTE this is found to be of type `char`
+        _ => 42,
+        //~^ ERROR match arms have incompatible types
+        //~| NOTE expected char, found integer
+        //~| NOTE expected type `char`
+    };
+    x
+}
+
+fn test_func3(n: i32) -> i32 {
+    let x = match n {
+    //~^ NOTE `match` arms have incompatible types
+        1 => 'b',
+        2 => 'b',
+        3 => 'b',
+        4 => 'b',
+        5 => 'b',
+        6 => 'b',
+        //~^ NOTE this and all prior arms are found to be of type `char`
+        _ => 42,
+        //~^ ERROR match arms have incompatible types
+        //~| NOTE expected char, found integer
+        //~| NOTE expected type `char`
+    };
+    x
+}
diff --git a/src/test/ui/match/match-type-err-first-arm.stderr b/src/test/ui/match/match-type-err-first-arm.stderr
new file mode 100644
index 0000000..a318e6c
--- /dev/null
+++ b/src/test/ui/match/match-type-err-first-arm.stderr
@@ -0,0 +1,53 @@
+error[E0308]: mismatched types
+  --> $DIR/match-type-err-first-arm.rs:9:15
+   |
+LL | fn test_func1(n: i32) -> i32 {
+   |                          --- expected `i32` because of return type
+...
+LL |         12 => 'b',
+   |               ^^^ expected i32, found char
+
+error[E0308]: match arms have incompatible types
+  --> $DIR/match-type-err-first-arm.rs:21:14
+   |
+LL |       let x = match n {
+   |  _____________-
+LL | |
+LL | |         12 => 'b',
+   | |               --- this is found to be of type `char`
+LL | |
+LL | |         _ => 42,
+   | |              ^^ expected char, found integer
+...  |
+LL | |
+LL | |     };
+   | |_____- `match` arms have incompatible types
+   |
+   = note: expected type `char`
+              found type `{integer}`
+
+error[E0308]: match arms have incompatible types
+  --> $DIR/match-type-err-first-arm.rs:39:14
+   |
+LL |       let x = match n {
+   |  _____________-
+LL | |
+LL | |         1 => 'b',
+LL | |         2 => 'b',
+...  |
+LL | |         6 => 'b',
+   | |              --- this and all prior arms are found to be of type `char`
+LL | |
+LL | |         _ => 42,
+   | |              ^^ expected char, found integer
+...  |
+LL | |
+LL | |     };
+   | |_____- `match` arms have incompatible types
+   |
+   = note: expected type `char`
+              found type `{integer}`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/match/match-unresolved-one-arm.rs b/src/test/ui/match/match-unresolved-one-arm.rs
new file mode 100644
index 0000000..fa65d87
--- /dev/null
+++ b/src/test/ui/match/match-unresolved-one-arm.rs
@@ -0,0 +1,7 @@
+fn foo<T>() -> T { panic!("Rocks for my pillow") }
+
+fn main() {
+    let x = match () { //~ ERROR type annotations needed
+        () => foo() // T here should be unresolved
+    };
+}
diff --git a/src/test/ui/match/match-unresolved-one-arm.stderr b/src/test/ui/match/match-unresolved-one-arm.stderr
new file mode 100644
index 0000000..ad8569b
--- /dev/null
+++ b/src/test/ui/match/match-unresolved-one-arm.stderr
@@ -0,0 +1,12 @@
+error[E0282]: type annotations needed
+  --> $DIR/match-unresolved-one-arm.rs:4:9
+   |
+LL |     let x = match () {
+   |         ^
+   |         |
+   |         cannot infer type
+   |         consider giving `x` a type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/match/match-vec-fixed.rs b/src/test/ui/match/match-vec-fixed.rs
new file mode 100644
index 0000000..e611779
--- /dev/null
+++ b/src/test/ui/match/match-vec-fixed.rs
@@ -0,0 +1,18 @@
+#![deny(unreachable_patterns)]
+
+fn a() {
+    let v = [1, 2, 3];
+    match v {
+        [_, _, _] => {}
+        [_, _, _] => {} //~ ERROR unreachable pattern
+    }
+    match v {
+        [_, 1, _] => {}
+        [_, 1, _] => {} //~ ERROR unreachable pattern
+        _ => {}
+    }
+}
+
+fn main() {
+    a();
+}
diff --git a/src/test/ui/match/match-vec-fixed.stderr b/src/test/ui/match/match-vec-fixed.stderr
new file mode 100644
index 0000000..ae2dd87
--- /dev/null
+++ b/src/test/ui/match/match-vec-fixed.stderr
@@ -0,0 +1,20 @@
+error: unreachable pattern
+  --> $DIR/match-vec-fixed.rs:7:9
+   |
+LL |         [_, _, _] => {}
+   |         ^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/match-vec-fixed.rs:1:9
+   |
+LL | #![deny(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/match-vec-fixed.rs:11:9
+   |
+LL |         [_, 1, _] => {}
+   |         ^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/match/match-vec-mismatch-2.rs b/src/test/ui/match/match-vec-mismatch-2.rs
new file mode 100644
index 0000000..5530958
--- /dev/null
+++ b/src/test/ui/match/match-vec-mismatch-2.rs
@@ -0,0 +1,6 @@
+fn main() {
+    match () {
+        [()] => { }
+        //~^ ERROR expected an array or slice, found `()`
+    }
+}
diff --git a/src/test/ui/match/match-vec-mismatch-2.stderr b/src/test/ui/match/match-vec-mismatch-2.stderr
new file mode 100644
index 0000000..5247bea
--- /dev/null
+++ b/src/test/ui/match/match-vec-mismatch-2.stderr
@@ -0,0 +1,9 @@
+error[E0529]: expected an array or slice, found `()`
+  --> $DIR/match-vec-mismatch-2.rs:3:9
+   |
+LL |         [()] => { }
+   |         ^^^^ pattern cannot match with input type `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0529`.
diff --git a/src/test/ui/match/match-vec-mismatch.rs b/src/test/ui/match/match-vec-mismatch.rs
new file mode 100644
index 0000000..5e61c1b
--- /dev/null
+++ b/src/test/ui/match/match-vec-mismatch.rs
@@ -0,0 +1,38 @@
+#![feature(slice_patterns)]
+
+fn main() {
+    match "foo".to_string() {
+        ['f', 'o', ..] => {}
+        //~^ ERROR expected an array or slice, found `std::string::String`
+        _ => { }
+    };
+
+    // Note that this one works with default binding modes.
+    match &[0, 1, 2] {
+        [..] => {}
+    };
+
+    match &[0, 1, 2] {
+        &[..] => {} // ok
+    };
+
+    match [0, 1, 2] {
+        [0] => {}, //~ ERROR pattern requires
+
+        [0, 1, x..] => {
+            let a: [_; 1] = x;
+        }
+        [0, 1, 2, 3, x..] => {} //~ ERROR pattern requires
+    };
+
+    match does_not_exist { //~ ERROR cannot find value `does_not_exist` in this scope
+        [] => {}
+    };
+}
+
+fn another_fn_to_avoid_suppression() {
+    match Default::default()
+    {
+        [] => {}  //~ ERROR type annotations needed
+    };
+}
diff --git a/src/test/ui/match/match-vec-mismatch.stderr b/src/test/ui/match/match-vec-mismatch.stderr
new file mode 100644
index 0000000..e19a0f9
--- /dev/null
+++ b/src/test/ui/match/match-vec-mismatch.stderr
@@ -0,0 +1,36 @@
+error[E0425]: cannot find value `does_not_exist` in this scope
+  --> $DIR/match-vec-mismatch.rs:28:11
+   |
+LL |     match does_not_exist {
+   |           ^^^^^^^^^^^^^^ not found in this scope
+
+error[E0529]: expected an array or slice, found `std::string::String`
+  --> $DIR/match-vec-mismatch.rs:5:9
+   |
+LL |         ['f', 'o', ..] => {}
+   |         ^^^^^^^^^^^^^^ pattern cannot match with input type `std::string::String`
+
+error[E0527]: pattern requires 1 elements but array has 3
+  --> $DIR/match-vec-mismatch.rs:20:9
+   |
+LL |         [0] => {},
+   |         ^^^ expected 3 elements
+
+error[E0528]: pattern requires at least 4 elements but array has 3
+  --> $DIR/match-vec-mismatch.rs:25:9
+   |
+LL |         [0, 1, 2, 3, x..] => {}
+   |         ^^^^^^^^^^^^^^^^^ pattern cannot match array of 3 elements
+
+error[E0282]: type annotations needed
+  --> $DIR/match-vec-mismatch.rs:36:9
+   |
+LL |         [] => {}
+   |         ^^ cannot infer type
+   |
+   = note: type must be known at this point
+
+error: aborting due to 5 previous errors
+
+Some errors occurred: E0282, E0425, E0527, E0528, E0529.
+For more information about an error, try `rustc --explain E0282`.
diff --git a/src/test/ui/match/match-vec-unreachable.rs b/src/test/ui/match/match-vec-unreachable.rs
new file mode 100644
index 0000000..9e167f3
--- /dev/null
+++ b/src/test/ui/match/match-vec-unreachable.rs
@@ -0,0 +1,30 @@
+#![feature(slice_patterns)]
+#![deny(unreachable_patterns)]
+
+fn main() {
+    let x: Vec<(isize, isize)> = Vec::new();
+    let x: &[(isize, isize)] = &x;
+    match *x {
+        [a, (2, 3), _] => (),
+        [(1, 2), (2, 3), b] => (), //~ ERROR unreachable pattern
+        _ => ()
+    }
+
+    let x: Vec<String> = vec!["foo".to_string(),
+                              "bar".to_string(),
+                              "baz".to_string()];
+    let x: &[String] = &x;
+    match *x {
+        [ref a, _, _, ..] => { println!("{}", a); }
+        [_, _, _, _, _] => { } //~ ERROR unreachable pattern
+        _ => { }
+    }
+
+    let x: Vec<char> = vec!['a', 'b', 'c'];
+    let x: &[char] = &x;
+    match *x {
+        ['a', 'b', 'c', ref _tail..] => {}
+        ['a', 'b', 'c'] => {} //~ ERROR unreachable pattern
+        _ => {}
+    }
+}
diff --git a/src/test/ui/match/match-vec-unreachable.stderr b/src/test/ui/match/match-vec-unreachable.stderr
new file mode 100644
index 0000000..415c24a
--- /dev/null
+++ b/src/test/ui/match/match-vec-unreachable.stderr
@@ -0,0 +1,26 @@
+error: unreachable pattern
+  --> $DIR/match-vec-unreachable.rs:9:9
+   |
+LL |         [(1, 2), (2, 3), b] => (),
+   |         ^^^^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/match-vec-unreachable.rs:2:9
+   |
+LL | #![deny(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/match-vec-unreachable.rs:19:9
+   |
+LL |         [_, _, _, _, _] => { }
+   |         ^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/match-vec-unreachable.rs:27:9
+   |
+LL |         ['a', 'b', 'c'] => {}
+   |         ^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/maybe-bounds-where-cpass.rs b/src/test/ui/maybe-bounds-where-cpass.rs
new file mode 100644
index 0000000..860de20
--- /dev/null
+++ b/src/test/ui/maybe-bounds-where-cpass.rs
@@ -0,0 +1,9 @@
+// compile-pass
+
+struct S<T>(*const T) where T: ?Sized;
+
+
+fn main() {
+    let u = vec![1, 2, 3];
+    let _s: S<[u8]> = S(&u[..]);
+}
diff --git a/src/test/ui/maybe-bounds-where.rs b/src/test/ui/maybe-bounds-where.rs
new file mode 100644
index 0000000..cf01165
--- /dev/null
+++ b/src/test/ui/maybe-bounds-where.rs
@@ -0,0 +1,27 @@
+struct S1<T>(T) where (T): ?Sized;
+//~^ ERROR `?Trait` bounds are only permitted at the point where a type parameter is declared
+
+struct S2<T>(T) where u8: ?Sized;
+//~^ ERROR `?Trait` bounds are only permitted at the point where a type parameter is declared
+
+struct S3<T>(T) where &'static T: ?Sized;
+//~^ ERROR `?Trait` bounds are only permitted at the point where a type parameter is declared
+
+trait Trait<'a> {}
+
+struct S4<T>(T) where for<'a> T: ?Trait<'a>;
+//~^ ERROR `?Trait` bounds are only permitted at the point where a type parameter is declared
+
+struct S5<T>(*const T) where T: ?Trait<'static> + ?Sized;
+//~^ ERROR type parameter has more than one relaxed default bound
+//~| WARN default bound relaxed for a type parameter
+
+impl<T> S1<T> {
+    fn f() where T: ?Sized {}
+    //~^ ERROR `?Trait` bounds are only permitted at the point where a type parameter is declared
+}
+
+fn main() {
+    let u = vec![1, 2, 3];
+    let _s: S5<[u8]> = S5(&u[..]); // OK
+}
diff --git a/src/test/ui/maybe-bounds-where.stderr b/src/test/ui/maybe-bounds-where.stderr
new file mode 100644
index 0000000..562e597
--- /dev/null
+++ b/src/test/ui/maybe-bounds-where.stderr
@@ -0,0 +1,45 @@
+error: `?Trait` bounds are only permitted at the point where a type parameter is declared
+  --> $DIR/maybe-bounds-where.rs:1:23
+   |
+LL | struct S1<T>(T) where (T): ?Sized;
+   |                       ^^^
+
+error: `?Trait` bounds are only permitted at the point where a type parameter is declared
+  --> $DIR/maybe-bounds-where.rs:4:23
+   |
+LL | struct S2<T>(T) where u8: ?Sized;
+   |                       ^^
+
+error: `?Trait` bounds are only permitted at the point where a type parameter is declared
+  --> $DIR/maybe-bounds-where.rs:7:23
+   |
+LL | struct S3<T>(T) where &'static T: ?Sized;
+   |                       ^^^^^^^^^^
+
+error: `?Trait` bounds are only permitted at the point where a type parameter is declared
+  --> $DIR/maybe-bounds-where.rs:12:31
+   |
+LL | struct S4<T>(T) where for<'a> T: ?Trait<'a>;
+   |                               ^
+
+error: `?Trait` bounds are only permitted at the point where a type parameter is declared
+  --> $DIR/maybe-bounds-where.rs:20:18
+   |
+LL |     fn f() where T: ?Sized {}
+   |                  ^
+
+error[E0203]: type parameter has more than one relaxed default bound, only one is supported
+  --> $DIR/maybe-bounds-where.rs:15:11
+   |
+LL | struct S5<T>(*const T) where T: ?Trait<'static> + ?Sized;
+   |           ^
+
+warning: default bound relaxed for a type parameter, but this does nothing because the given bound is not a default. Only `?Sized` is supported
+  --> $DIR/maybe-bounds-where.rs:15:11
+   |
+LL | struct S5<T>(*const T) where T: ?Trait<'static> + ?Sized;
+   |           ^
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0203`.
diff --git a/src/test/ui/maybe-bounds.rs b/src/test/ui/maybe-bounds.rs
new file mode 100644
index 0000000..3e07026
--- /dev/null
+++ b/src/test/ui/maybe-bounds.rs
@@ -0,0 +1,6 @@
+trait Tr: ?Sized {} //~ ERROR `?Trait` is not permitted in supertraits
+
+type A1 = Tr + (?Sized); //~ ERROR `?Trait` is not permitted in trait object types
+type A2 = for<'a> Tr + (?Sized); //~ ERROR `?Trait` is not permitted in trait object types
+
+fn main() {}
diff --git a/src/test/ui/maybe-bounds.stderr b/src/test/ui/maybe-bounds.stderr
new file mode 100644
index 0000000..20446c2
--- /dev/null
+++ b/src/test/ui/maybe-bounds.stderr
@@ -0,0 +1,22 @@
+error: `?Trait` is not permitted in supertraits
+  --> $DIR/maybe-bounds.rs:1:11
+   |
+LL | trait Tr: ?Sized {}
+   |           ^^^^^^
+   |
+   = note: traits are `?Sized` by default
+
+error: `?Trait` is not permitted in trait object types
+  --> $DIR/maybe-bounds.rs:3:16
+   |
+LL | type A1 = Tr + (?Sized);
+   |                ^^^^^^^^
+
+error: `?Trait` is not permitted in trait object types
+  --> $DIR/maybe-bounds.rs:4:24
+   |
+LL | type A2 = for<'a> Tr + (?Sized);
+   |                        ^^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/meta-expected-error-correct-rev.a.stderr b/src/test/ui/meta-expected-error-correct-rev.a.stderr
new file mode 100644
index 0000000..901bdcd
--- /dev/null
+++ b/src/test/ui/meta-expected-error-correct-rev.a.stderr
@@ -0,0 +1,9 @@
+error[E0308]: mismatched types
+  --> $DIR/meta-expected-error-correct-rev.rs:7:18
+   |
+LL |     let x: u32 = 22_usize;
+   |                  ^^^^^^^^ expected u32, found usize
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/meta-expected-error-correct-rev.rs b/src/test/ui/meta-expected-error-correct-rev.rs
new file mode 100644
index 0000000..b06a64b
--- /dev/null
+++ b/src/test/ui/meta-expected-error-correct-rev.rs
@@ -0,0 +1,10 @@
+// revisions: a
+
+// Counterpart to `meta-expected-error-wrong-rev.rs`
+
+#[cfg(a)]
+fn foo() {
+    let x: u32 = 22_usize; //[a]~ ERROR mismatched types
+}
+
+fn main() { }
diff --git a/src/test/ui/methods/auxiliary/ambig_impl_2_lib.rs b/src/test/ui/methods/auxiliary/ambig_impl_2_lib.rs
new file mode 100644
index 0000000..0ed68bf
--- /dev/null
+++ b/src/test/ui/methods/auxiliary/ambig_impl_2_lib.rs
@@ -0,0 +1,4 @@
+pub trait Me {
+    fn me(&self) -> usize;
+}
+impl Me for usize { fn me(&self) -> usize { *self } }
diff --git a/src/test/ui/methods/auxiliary/macro-in-other-crate.rs b/src/test/ui/methods/auxiliary/macro-in-other-crate.rs
new file mode 100644
index 0000000..feda084
--- /dev/null
+++ b/src/test/ui/methods/auxiliary/macro-in-other-crate.rs
@@ -0,0 +1,9 @@
+#[macro_export]
+macro_rules! mac {
+    ($ident:ident) => { let $ident = 42; }
+}
+
+#[macro_export]
+macro_rules! inline {
+    () => ()
+}
diff --git a/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.rs b/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.rs
new file mode 100644
index 0000000..590e98d
--- /dev/null
+++ b/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.rs
@@ -0,0 +1,36 @@
+// Test that we invoking `foo()` successfully resolves to the trait `Foo`
+// (prompting the mismatched types error) but does not influence the choice
+// of what kind of `Vec` we have, eventually leading to a type error.
+
+trait Foo {
+    fn foo(&self) -> isize;
+}
+
+impl Foo for Vec<usize> {
+    fn foo(&self) -> isize {1}
+}
+
+impl Foo for Vec<isize> {
+    fn foo(&self) -> isize {2}
+}
+
+// This is very hokey: we have heuristics to suppress messages about
+// type annotations required. But placing these two bits of code into
+// distinct functions, in this order, causes us to print out both
+// errors I'd like to see.
+
+fn m1() {
+    // we couldn't infer the type of the vector just based on calling foo()...
+    let mut x = Vec::new();
+    //~^ ERROR type annotations needed [E0282]
+    x.foo();
+}
+
+fn m2() {
+    let mut x = Vec::new();
+
+    // ...but we still resolved `foo()` to the trait and hence know the return type.
+    let y: usize = x.foo(); //~ ERROR mismatched types
+}
+
+fn main() { }
diff --git a/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr b/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr
new file mode 100644
index 0000000..9e5f2ee
--- /dev/null
+++ b/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr
@@ -0,0 +1,18 @@
+error[E0282]: type annotations needed
+  --> $DIR/method-ambig-one-trait-unknown-int-type.rs:24:17
+   |
+LL |     let mut x = Vec::new();
+   |         -----   ^^^^^^^^ cannot infer type for `T`
+   |         |
+   |         consider giving `x` a type
+
+error[E0308]: mismatched types
+  --> $DIR/method-ambig-one-trait-unknown-int-type.rs:33:20
+   |
+LL |     let y: usize = x.foo();
+   |                    ^^^^^^^ expected usize, found isize
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0282, E0308.
+For more information about an error, try `rustc --explain E0282`.
diff --git a/src/test/ui/methods/method-ambig-two-traits-cross-crate.rs b/src/test/ui/methods/method-ambig-two-traits-cross-crate.rs
new file mode 100644
index 0000000..006e315
--- /dev/null
+++ b/src/test/ui/methods/method-ambig-two-traits-cross-crate.rs
@@ -0,0 +1,11 @@
+// Test an ambiguity scenario where one copy of the method is available
+// from a trait imported from another crate.
+
+// aux-build:ambig_impl_2_lib.rs
+extern crate ambig_impl_2_lib;
+use ambig_impl_2_lib::Me;
+trait Me2 {
+    fn me(&self) -> usize;
+}
+impl Me2 for usize { fn me(&self) -> usize { *self } }
+fn main() { 1_usize.me(); } //~ ERROR E0034
diff --git a/src/test/ui/methods/method-ambig-two-traits-cross-crate.stderr b/src/test/ui/methods/method-ambig-two-traits-cross-crate.stderr
new file mode 100644
index 0000000..2b87ddf
--- /dev/null
+++ b/src/test/ui/methods/method-ambig-two-traits-cross-crate.stderr
@@ -0,0 +1,16 @@
+error[E0034]: multiple applicable items in scope
+  --> $DIR/method-ambig-two-traits-cross-crate.rs:11:21
+   |
+LL | fn main() { 1_usize.me(); }
+   |                     ^^ multiple `me` found
+   |
+note: candidate #1 is defined in an impl of the trait `Me2` for the type `usize`
+  --> $DIR/method-ambig-two-traits-cross-crate.rs:10:22
+   |
+LL | impl Me2 for usize { fn me(&self) -> usize { *self } }
+   |                      ^^^^^^^^^^^^^^^^^^^^^
+   = note: candidate #2 is defined in an impl of the trait `ambig_impl_2_lib::Me` for the type `usize`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0034`.
diff --git a/src/test/ui/methods/method-ambig-two-traits-from-bounds.rs b/src/test/ui/methods/method-ambig-two-traits-from-bounds.rs
new file mode 100644
index 0000000..e3cc555
--- /dev/null
+++ b/src/test/ui/methods/method-ambig-two-traits-from-bounds.rs
@@ -0,0 +1,8 @@
+trait A { fn foo(&self); }
+trait B { fn foo(&self); }
+
+fn foo<T:A + B>(t: T) {
+    t.foo(); //~ ERROR E0034
+}
+
+fn main() {}
diff --git a/src/test/ui/methods/method-ambig-two-traits-from-bounds.stderr b/src/test/ui/methods/method-ambig-two-traits-from-bounds.stderr
new file mode 100644
index 0000000..6c493c6
--- /dev/null
+++ b/src/test/ui/methods/method-ambig-two-traits-from-bounds.stderr
@@ -0,0 +1,22 @@
+error[E0034]: multiple applicable items in scope
+  --> $DIR/method-ambig-two-traits-from-bounds.rs:5:7
+   |
+LL |     t.foo();
+   |       ^^^ multiple `foo` found
+   |
+note: candidate #1 is defined in the trait `A`
+  --> $DIR/method-ambig-two-traits-from-bounds.rs:1:11
+   |
+LL | trait A { fn foo(&self); }
+   |           ^^^^^^^^^^^^^^
+   = help: to disambiguate the method call, write `A::foo(t)` instead
+note: candidate #2 is defined in the trait `B`
+  --> $DIR/method-ambig-two-traits-from-bounds.rs:2:11
+   |
+LL | trait B { fn foo(&self); }
+   |           ^^^^^^^^^^^^^^
+   = help: to disambiguate the method call, write `B::foo(t)` instead
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0034`.
diff --git a/src/test/ui/methods/method-ambig-two-traits-with-default-method.rs b/src/test/ui/methods/method-ambig-two-traits-with-default-method.rs
new file mode 100644
index 0000000..aa7094b
--- /dev/null
+++ b/src/test/ui/methods/method-ambig-two-traits-with-default-method.rs
@@ -0,0 +1,13 @@
+// Test that we correctly report an ambiguity where two applicable traits
+// are in scope and the method being invoked is a default method not
+// defined directly in the impl.
+
+trait Foo { fn method(&self) {} }
+trait Bar { fn method(&self) {} }
+
+impl Foo for usize {}
+impl Bar for usize {}
+
+fn main() {
+    1_usize.method(); //~ ERROR E0034
+}
diff --git a/src/test/ui/methods/method-ambig-two-traits-with-default-method.stderr b/src/test/ui/methods/method-ambig-two-traits-with-default-method.stderr
new file mode 100644
index 0000000..5d508d5
--- /dev/null
+++ b/src/test/ui/methods/method-ambig-two-traits-with-default-method.stderr
@@ -0,0 +1,20 @@
+error[E0034]: multiple applicable items in scope
+  --> $DIR/method-ambig-two-traits-with-default-method.rs:12:13
+   |
+LL |     1_usize.method();
+   |             ^^^^^^ multiple `method` found
+   |
+note: candidate #1 is defined in an impl of the trait `Foo` for the type `usize`
+  --> $DIR/method-ambig-two-traits-with-default-method.rs:5:13
+   |
+LL | trait Foo { fn method(&self) {} }
+   |             ^^^^^^^^^^^^^^^^
+note: candidate #2 is defined in an impl of the trait `Bar` for the type `usize`
+  --> $DIR/method-ambig-two-traits-with-default-method.rs:6:13
+   |
+LL | trait Bar { fn method(&self) {} }
+   |             ^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0034`.
diff --git a/src/test/ui/methods/method-call-err-msg.rs b/src/test/ui/methods/method-call-err-msg.rs
new file mode 100644
index 0000000..e0dec0a
--- /dev/null
+++ b/src/test/ui/methods/method-call-err-msg.rs
@@ -0,0 +1,20 @@
+// Test that parameter cardinality or missing method error gets span exactly.
+
+pub struct Foo;
+impl Foo {
+    fn zero(self) -> Foo { self }
+    fn one(self, _: isize) -> Foo { self }
+    fn two(self, _: isize, _: isize) -> Foo { self }
+}
+
+fn main() {
+    let x = Foo;
+    x.zero(0)   //~ ERROR this function takes 0 parameters but 1 parameter was supplied
+     .one()     //~ ERROR this function takes 1 parameter but 0 parameters were supplied
+     .two(0);   //~ ERROR this function takes 2 parameters but 1 parameter was supplied
+
+    let y = Foo;
+    y.zero()
+     .take()    //~ ERROR no method named `take` found for type `Foo` in the current scope
+     .one(0);
+}
diff --git a/src/test/ui/methods/method-call-err-msg.stderr b/src/test/ui/methods/method-call-err-msg.stderr
new file mode 100644
index 0000000..0e901a9
--- /dev/null
+++ b/src/test/ui/methods/method-call-err-msg.stderr
@@ -0,0 +1,47 @@
+error[E0061]: this function takes 0 parameters but 1 parameter was supplied
+  --> $DIR/method-call-err-msg.rs:12:7
+   |
+LL |     fn zero(self) -> Foo { self }
+   |     -------------------- defined here
+...
+LL |     x.zero(0)
+   |       ^^^^ expected 0 parameters
+
+error[E0061]: this function takes 1 parameter but 0 parameters were supplied
+  --> $DIR/method-call-err-msg.rs:13:7
+   |
+LL |     fn one(self, _: isize) -> Foo { self }
+   |     ----------------------------- defined here
+...
+LL |      .one()
+   |       ^^^ expected 1 parameter
+
+error[E0061]: this function takes 2 parameters but 1 parameter was supplied
+  --> $DIR/method-call-err-msg.rs:14:7
+   |
+LL |     fn two(self, _: isize, _: isize) -> Foo { self }
+   |     --------------------------------------- defined here
+...
+LL |      .two(0);
+   |       ^^^ expected 2 parameters
+
+error[E0599]: no method named `take` found for type `Foo` in the current scope
+  --> $DIR/method-call-err-msg.rs:18:7
+   |
+LL | pub struct Foo;
+   | --------------- method `take` not found for this
+...
+LL |      .take()
+   |       ^^^^
+   |
+   = note: the method `take` exists but the following trait bounds were not satisfied:
+           `&mut Foo : std::iter::Iterator`
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following traits define an item `take`, perhaps you need to implement one of them:
+           candidate #1: `std::io::Read`
+           candidate #2: `std::iter::Iterator`
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0061, E0599.
+For more information about an error, try `rustc --explain E0061`.
diff --git a/src/test/ui/methods/method-call-lifetime-args-fail.rs b/src/test/ui/methods/method-call-lifetime-args-fail.rs
new file mode 100644
index 0000000..938a7f5
--- /dev/null
+++ b/src/test/ui/methods/method-call-lifetime-args-fail.rs
@@ -0,0 +1,72 @@
+struct S;
+
+impl S {
+    fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
+    fn late_implicit(self, _: &u8, _: &u8) {}
+    fn early<'a, 'b>(self) -> (&'a u8, &'b u8) { loop {} }
+    fn late_early<'a, 'b>(self, _: &'a u8) -> &'b u8 { loop {} }
+    fn late_implicit_early<'b>(self, _: &u8) -> &'b u8 { loop {} }
+    fn late_implicit_self_early<'b>(&self) -> &'b u8 { loop {} }
+    fn late_unused_early<'a, 'b>(self) -> &'b u8 { loop {} }
+    fn life_and_type<'a, T>(self) -> &'a T { loop {} }
+}
+
+fn method_call() {
+    S.early(); // OK
+    S.early::<'static>();
+    //~^ ERROR wrong number of lifetime arguments: expected 2, found 1
+    S.early::<'static, 'static, 'static>();
+    //~^ ERROR wrong number of lifetime arguments: expected 2, found 3
+    let _: &u8 = S.life_and_type::<'static>();
+    S.life_and_type::<u8>();
+    S.life_and_type::<'static, u8>();
+}
+
+fn ufcs() {
+    S::late(S, &0, &0); // OK
+    S::late::<'static>(S, &0, &0);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    S::late::<'static, 'static>(S, &0, &0);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    S::late::<'static, 'static, 'static>(S, &0, &0);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    S::late_early(S, &0); // OK
+    S::late_early::<'static, 'static>(S, &0);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    S::late_early::<'static, 'static, 'static>(S, &0);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+
+    S::late_implicit(S, &0, &0); // OK
+    S::late_implicit::<'static>(S, &0, &0);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    S::late_implicit::<'static, 'static>(S, &0, &0);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    S::late_implicit::<'static, 'static, 'static>(S, &0, &0);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    S::late_implicit_early(S, &0); // OK
+    S::late_implicit_early::<'static, 'static>(S, &0);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    S::late_implicit_early::<'static, 'static, 'static>(S, &0);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    S::late_implicit_self_early(&S); // OK
+    S::late_implicit_self_early::<'static, 'static>(&S);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    S::late_implicit_self_early::<'static, 'static, 'static>(&S);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    S::late_unused_early(S); // OK
+    S::late_unused_early::<'static, 'static>(S);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    S::late_unused_early::<'static, 'static, 'static>(S);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+
+    S::early(S); // OK
+    S::early::<'static>(S);
+    //~^ ERROR wrong number of lifetime arguments: expected 2, found 1
+    S::early::<'static, 'static, 'static>(S);
+    //~^ ERROR wrong number of lifetime arguments: expected 2, found 3
+    let _: &u8 = S::life_and_type::<'static>(S);
+    S::life_and_type::<u8>(S);
+    S::life_and_type::<'static, u8>(S);
+}
+
+fn main() {}
diff --git a/src/test/ui/methods/method-call-lifetime-args-fail.stderr b/src/test/ui/methods/method-call-lifetime-args-fail.stderr
new file mode 100644
index 0000000..74dab5f4
--- /dev/null
+++ b/src/test/ui/methods/method-call-lifetime-args-fail.stderr
@@ -0,0 +1,195 @@
+error[E0107]: wrong number of lifetime arguments: expected 2, found 1
+  --> $DIR/method-call-lifetime-args-fail.rs:16:7
+   |
+LL |     S.early::<'static>();
+   |       ^^^^^ expected 2 lifetime arguments
+
+error[E0107]: wrong number of lifetime arguments: expected 2, found 3
+  --> $DIR/method-call-lifetime-args-fail.rs:18:33
+   |
+LL |     S.early::<'static, 'static, 'static>();
+   |                                 ^^^^^^^ unexpected lifetime argument
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+  --> $DIR/method-call-lifetime-args-fail.rs:27:15
+   |
+LL |     S::late::<'static>(S, &0, &0);
+   |               ^^^^^^^
+   |
+note: the late bound lifetime parameter is introduced here
+  --> $DIR/method-call-lifetime-args-fail.rs:4:13
+   |
+LL |     fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
+   |             ^^
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+  --> $DIR/method-call-lifetime-args-fail.rs:29:15
+   |
+LL |     S::late::<'static, 'static>(S, &0, &0);
+   |               ^^^^^^^
+   |
+note: the late bound lifetime parameter is introduced here
+  --> $DIR/method-call-lifetime-args-fail.rs:4:13
+   |
+LL |     fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
+   |             ^^
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+  --> $DIR/method-call-lifetime-args-fail.rs:31:15
+   |
+LL |     S::late::<'static, 'static, 'static>(S, &0, &0);
+   |               ^^^^^^^
+   |
+note: the late bound lifetime parameter is introduced here
+  --> $DIR/method-call-lifetime-args-fail.rs:4:13
+   |
+LL |     fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
+   |             ^^
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+  --> $DIR/method-call-lifetime-args-fail.rs:34:21
+   |
+LL |     S::late_early::<'static, 'static>(S, &0);
+   |                     ^^^^^^^
+   |
+note: the late bound lifetime parameter is introduced here
+  --> $DIR/method-call-lifetime-args-fail.rs:7:19
+   |
+LL |     fn late_early<'a, 'b>(self, _: &'a u8) -> &'b u8 { loop {} }
+   |                   ^^
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+  --> $DIR/method-call-lifetime-args-fail.rs:36:21
+   |
+LL |     S::late_early::<'static, 'static, 'static>(S, &0);
+   |                     ^^^^^^^
+   |
+note: the late bound lifetime parameter is introduced here
+  --> $DIR/method-call-lifetime-args-fail.rs:7:19
+   |
+LL |     fn late_early<'a, 'b>(self, _: &'a u8) -> &'b u8 { loop {} }
+   |                   ^^
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+  --> $DIR/method-call-lifetime-args-fail.rs:40:24
+   |
+LL |     S::late_implicit::<'static>(S, &0, &0);
+   |                        ^^^^^^^
+   |
+note: the late bound lifetime parameter is introduced here
+  --> $DIR/method-call-lifetime-args-fail.rs:5:31
+   |
+LL |     fn late_implicit(self, _: &u8, _: &u8) {}
+   |                               ^
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+  --> $DIR/method-call-lifetime-args-fail.rs:42:24
+   |
+LL |     S::late_implicit::<'static, 'static>(S, &0, &0);
+   |                        ^^^^^^^
+   |
+note: the late bound lifetime parameter is introduced here
+  --> $DIR/method-call-lifetime-args-fail.rs:5:31
+   |
+LL |     fn late_implicit(self, _: &u8, _: &u8) {}
+   |                               ^
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+  --> $DIR/method-call-lifetime-args-fail.rs:44:24
+   |
+LL |     S::late_implicit::<'static, 'static, 'static>(S, &0, &0);
+   |                        ^^^^^^^
+   |
+note: the late bound lifetime parameter is introduced here
+  --> $DIR/method-call-lifetime-args-fail.rs:5:31
+   |
+LL |     fn late_implicit(self, _: &u8, _: &u8) {}
+   |                               ^
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+  --> $DIR/method-call-lifetime-args-fail.rs:47:30
+   |
+LL |     S::late_implicit_early::<'static, 'static>(S, &0);
+   |                              ^^^^^^^
+   |
+note: the late bound lifetime parameter is introduced here
+  --> $DIR/method-call-lifetime-args-fail.rs:8:41
+   |
+LL |     fn late_implicit_early<'b>(self, _: &u8) -> &'b u8 { loop {} }
+   |                                         ^
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+  --> $DIR/method-call-lifetime-args-fail.rs:49:30
+   |
+LL |     S::late_implicit_early::<'static, 'static, 'static>(S, &0);
+   |                              ^^^^^^^
+   |
+note: the late bound lifetime parameter is introduced here
+  --> $DIR/method-call-lifetime-args-fail.rs:8:41
+   |
+LL |     fn late_implicit_early<'b>(self, _: &u8) -> &'b u8 { loop {} }
+   |                                         ^
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+  --> $DIR/method-call-lifetime-args-fail.rs:52:35
+   |
+LL |     S::late_implicit_self_early::<'static, 'static>(&S);
+   |                                   ^^^^^^^
+   |
+note: the late bound lifetime parameter is introduced here
+  --> $DIR/method-call-lifetime-args-fail.rs:9:37
+   |
+LL |     fn late_implicit_self_early<'b>(&self) -> &'b u8 { loop {} }
+   |                                     ^
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+  --> $DIR/method-call-lifetime-args-fail.rs:54:35
+   |
+LL |     S::late_implicit_self_early::<'static, 'static, 'static>(&S);
+   |                                   ^^^^^^^
+   |
+note: the late bound lifetime parameter is introduced here
+  --> $DIR/method-call-lifetime-args-fail.rs:9:37
+   |
+LL |     fn late_implicit_self_early<'b>(&self) -> &'b u8 { loop {} }
+   |                                     ^
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+  --> $DIR/method-call-lifetime-args-fail.rs:57:28
+   |
+LL |     S::late_unused_early::<'static, 'static>(S);
+   |                            ^^^^^^^
+   |
+note: the late bound lifetime parameter is introduced here
+  --> $DIR/method-call-lifetime-args-fail.rs:10:26
+   |
+LL |     fn late_unused_early<'a, 'b>(self) -> &'b u8 { loop {} }
+   |                          ^^
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+  --> $DIR/method-call-lifetime-args-fail.rs:59:28
+   |
+LL |     S::late_unused_early::<'static, 'static, 'static>(S);
+   |                            ^^^^^^^
+   |
+note: the late bound lifetime parameter is introduced here
+  --> $DIR/method-call-lifetime-args-fail.rs:10:26
+   |
+LL |     fn late_unused_early<'a, 'b>(self) -> &'b u8 { loop {} }
+   |                          ^^
+
+error[E0107]: wrong number of lifetime arguments: expected 2, found 1
+  --> $DIR/method-call-lifetime-args-fail.rs:63:5
+   |
+LL |     S::early::<'static>(S);
+   |     ^^^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments
+
+error[E0107]: wrong number of lifetime arguments: expected 2, found 3
+  --> $DIR/method-call-lifetime-args-fail.rs:65:34
+   |
+LL |     S::early::<'static, 'static, 'static>(S);
+   |                                  ^^^^^^^ unexpected lifetime argument
+
+error: aborting due to 18 previous errors
+
+For more information about this error, try `rustc --explain E0107`.
diff --git a/src/test/ui/methods/method-call-lifetime-args-lint-fail.rs b/src/test/ui/methods/method-call-lifetime-args-lint-fail.rs
new file mode 100644
index 0000000..36a1a2f
--- /dev/null
+++ b/src/test/ui/methods/method-call-lifetime-args-lint-fail.rs
@@ -0,0 +1,87 @@
+#![deny(late_bound_lifetime_arguments)]
+#![allow(unused)]
+
+struct S;
+
+impl S {
+    fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
+    fn late_implicit(self, _: &u8, _: &u8) {}
+    fn late_early<'a, 'b>(self, _: &'a u8) -> &'b u8 { loop {} }
+    fn late_implicit_early<'b>(self, _: &u8) -> &'b u8 { loop {} }
+
+    // 'late lifetimes here belong to nested types not to the tested functions.
+    fn early_tricky_explicit<'a>(_: for<'late> fn(&'late u8),
+                                 _: Box<for<'late> Fn(&'late u8)>)
+                                 -> &'a u8 { loop {} }
+    fn early_tricky_implicit<'a>(_: fn(&u8),
+                                 _: Box<Fn(&u8)>)
+                                 -> &'a u8 { loop {} }
+}
+
+fn method_call() {
+    S.late(&0, &0); // OK
+    S.late::<'static>(&0, &0);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    //~| WARN this was previously accepted
+    S.late::<'static, 'static>(&0, &0);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    //~| WARN this was previously accepted
+    S.late::<'static, 'static, 'static>(&0, &0);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    //~| WARN this was previously accepted
+    S.late_early(&0); // OK
+    S.late_early::<'static>(&0);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    //~| WARN this was previously accepted
+    S.late_early::<'static, 'static>(&0);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    //~| WARN this was previously accepted
+    S.late_early::<'static, 'static, 'static>(&0);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    //~| WARN this was previously accepted
+
+    S.late_implicit(&0, &0); // OK
+    S.late_implicit::<'static>(&0, &0);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    //~| WARN this was previously accepted
+    S.late_implicit::<'static, 'static>(&0, &0);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    //~| WARN this was previously accepted
+    S.late_implicit::<'static, 'static, 'static>(&0, &0);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    //~| WARN this was previously accepted
+    S.late_implicit_early(&0); // OK
+    S.late_implicit_early::<'static>(&0);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    //~| WARN this was previously accepted
+    S.late_implicit_early::<'static, 'static>(&0);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    //~| WARN this was previously accepted
+    S.late_implicit_early::<'static, 'static, 'static>(&0);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    //~| WARN this was previously accepted
+
+    S::early_tricky_explicit::<'static>(loop {}, loop {}); // OK
+    S::early_tricky_implicit::<'static>(loop {}, loop {}); // OK
+}
+
+fn ufcs() {
+    S::late_early::<'static>(S, &0);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    //~| WARN this was previously accepted
+
+    S::late_implicit_early::<'static>(S, &0);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    //~| WARN this was previously accepted
+}
+
+fn lint_not_inference_error() {
+    fn f<'early, 'late, T: 'early>() {}
+
+    // Make sure `u8` is substituted and not replaced with an inference variable
+    f::<'static, u8>;
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    //~| WARN this was previously accepted
+}
+
+fn main() {}
diff --git a/src/test/ui/methods/method-call-lifetime-args-lint-fail.stderr b/src/test/ui/methods/method-call-lifetime-args-lint-fail.stderr
new file mode 100644
index 0000000..b510a08
--- /dev/null
+++ b/src/test/ui/methods/method-call-lifetime-args-lint-fail.stderr
@@ -0,0 +1,187 @@
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+  --> $DIR/method-call-lifetime-args-lint-fail.rs:23:14
+   |
+LL |     fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
+   |             -- the late bound lifetime parameter is introduced here
+...
+LL |     S.late::<'static>(&0, &0);
+   |              ^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/method-call-lifetime-args-lint-fail.rs:1:9
+   |
+LL | #![deny(late_bound_lifetime_arguments)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+  --> $DIR/method-call-lifetime-args-lint-fail.rs:26:14
+   |
+LL |     fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
+   |             -- the late bound lifetime parameter is introduced here
+...
+LL |     S.late::<'static, 'static>(&0, &0);
+   |              ^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+  --> $DIR/method-call-lifetime-args-lint-fail.rs:29:14
+   |
+LL |     fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
+   |             -- the late bound lifetime parameter is introduced here
+...
+LL |     S.late::<'static, 'static, 'static>(&0, &0);
+   |              ^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+  --> $DIR/method-call-lifetime-args-lint-fail.rs:33:20
+   |
+LL |     fn late_early<'a, 'b>(self, _: &'a u8) -> &'b u8 { loop {} }
+   |                   -- the late bound lifetime parameter is introduced here
+...
+LL |     S.late_early::<'static>(&0);
+   |                    ^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+  --> $DIR/method-call-lifetime-args-lint-fail.rs:36:20
+   |
+LL |     fn late_early<'a, 'b>(self, _: &'a u8) -> &'b u8 { loop {} }
+   |                   -- the late bound lifetime parameter is introduced here
+...
+LL |     S.late_early::<'static, 'static>(&0);
+   |                    ^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+  --> $DIR/method-call-lifetime-args-lint-fail.rs:39:20
+   |
+LL |     fn late_early<'a, 'b>(self, _: &'a u8) -> &'b u8 { loop {} }
+   |                   -- the late bound lifetime parameter is introduced here
+...
+LL |     S.late_early::<'static, 'static, 'static>(&0);
+   |                    ^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+  --> $DIR/method-call-lifetime-args-lint-fail.rs:44:23
+   |
+LL |     fn late_implicit(self, _: &u8, _: &u8) {}
+   |                               - the late bound lifetime parameter is introduced here
+...
+LL |     S.late_implicit::<'static>(&0, &0);
+   |                       ^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+  --> $DIR/method-call-lifetime-args-lint-fail.rs:47:23
+   |
+LL |     fn late_implicit(self, _: &u8, _: &u8) {}
+   |                               - the late bound lifetime parameter is introduced here
+...
+LL |     S.late_implicit::<'static, 'static>(&0, &0);
+   |                       ^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+  --> $DIR/method-call-lifetime-args-lint-fail.rs:50:23
+   |
+LL |     fn late_implicit(self, _: &u8, _: &u8) {}
+   |                               - the late bound lifetime parameter is introduced here
+...
+LL |     S.late_implicit::<'static, 'static, 'static>(&0, &0);
+   |                       ^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+  --> $DIR/method-call-lifetime-args-lint-fail.rs:54:29
+   |
+LL |     fn late_implicit_early<'b>(self, _: &u8) -> &'b u8 { loop {} }
+   |                                         - the late bound lifetime parameter is introduced here
+...
+LL |     S.late_implicit_early::<'static>(&0);
+   |                             ^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+  --> $DIR/method-call-lifetime-args-lint-fail.rs:57:29
+   |
+LL |     fn late_implicit_early<'b>(self, _: &u8) -> &'b u8 { loop {} }
+   |                                         - the late bound lifetime parameter is introduced here
+...
+LL |     S.late_implicit_early::<'static, 'static>(&0);
+   |                             ^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+  --> $DIR/method-call-lifetime-args-lint-fail.rs:60:29
+   |
+LL |     fn late_implicit_early<'b>(self, _: &u8) -> &'b u8 { loop {} }
+   |                                         - the late bound lifetime parameter is introduced here
+...
+LL |     S.late_implicit_early::<'static, 'static, 'static>(&0);
+   |                             ^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+  --> $DIR/method-call-lifetime-args-lint-fail.rs:69:21
+   |
+LL |     fn late_early<'a, 'b>(self, _: &'a u8) -> &'b u8 { loop {} }
+   |                   -- the late bound lifetime parameter is introduced here
+...
+LL |     S::late_early::<'static>(S, &0);
+   |                     ^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+  --> $DIR/method-call-lifetime-args-lint-fail.rs:73:30
+   |
+LL |     fn late_implicit_early<'b>(self, _: &u8) -> &'b u8 { loop {} }
+   |                                         - the late bound lifetime parameter is introduced here
+...
+LL |     S::late_implicit_early::<'static>(S, &0);
+   |                              ^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+  --> $DIR/method-call-lifetime-args-lint-fail.rs:82:9
+   |
+LL |     fn f<'early, 'late, T: 'early>() {}
+   |                  ----- the late bound lifetime parameter is introduced here
+...
+LL |     f::<'static, u8>;
+   |         ^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
+
+error: aborting due to 15 previous errors
+
diff --git a/src/test/ui/methods/method-call-lifetime-args-lint.rs b/src/test/ui/methods/method-call-lifetime-args-lint.rs
new file mode 100644
index 0000000..14729e1
--- /dev/null
+++ b/src/test/ui/methods/method-call-lifetime-args-lint.rs
@@ -0,0 +1,21 @@
+#![deny(late_bound_lifetime_arguments)]
+#![allow(unused)]
+
+struct S;
+
+impl S {
+    fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
+    fn late_implicit(self, _: &u8, _: &u8) {}
+}
+
+fn method_call() {
+    S.late::<'static>(&0, &0);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    //~| WARN this was previously accepted
+
+    S.late_implicit::<'static>(&0, &0);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    //~| WARN this was previously accepted
+}
+
+fn main() {}
diff --git a/src/test/ui/methods/method-call-lifetime-args-lint.stderr b/src/test/ui/methods/method-call-lifetime-args-lint.stderr
new file mode 100644
index 0000000..eb1d4fe
--- /dev/null
+++ b/src/test/ui/methods/method-call-lifetime-args-lint.stderr
@@ -0,0 +1,31 @@
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+  --> $DIR/method-call-lifetime-args-lint.rs:12:14
+   |
+LL |     fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
+   |             -- the late bound lifetime parameter is introduced here
+...
+LL |     S.late::<'static>(&0, &0);
+   |              ^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/method-call-lifetime-args-lint.rs:1:9
+   |
+LL | #![deny(late_bound_lifetime_arguments)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+  --> $DIR/method-call-lifetime-args-lint.rs:16:23
+   |
+LL |     fn late_implicit(self, _: &u8, _: &u8) {}
+   |                               - the late bound lifetime parameter is introduced here
+...
+LL |     S.late_implicit::<'static>(&0, &0);
+   |                       ^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/methods/method-call-lifetime-args-subst-index.rs b/src/test/ui/methods/method-call-lifetime-args-subst-index.rs
new file mode 100644
index 0000000..4ee09dc
--- /dev/null
+++ b/src/test/ui/methods/method-call-lifetime-args-subst-index.rs
@@ -0,0 +1,15 @@
+// compile-pass
+#![allow(unused)]
+
+struct S;
+
+impl S {
+    fn early_and_type<'a, T>(self) -> &'a T { loop {} }
+}
+
+fn test() {
+    S.early_and_type::<u16>();
+}
+
+
+fn main() {}
diff --git a/src/test/ui/methods/method-call-lifetime-args-unresolved.rs b/src/test/ui/methods/method-call-lifetime-args-unresolved.rs
new file mode 100644
index 0000000..d16ba3d
--- /dev/null
+++ b/src/test/ui/methods/method-call-lifetime-args-unresolved.rs
@@ -0,0 +1,3 @@
+fn main() {
+    0.clone::<'a>(); //~ ERROR use of undeclared lifetime name `'a`
+}
diff --git a/src/test/ui/methods/method-call-lifetime-args-unresolved.stderr b/src/test/ui/methods/method-call-lifetime-args-unresolved.stderr
new file mode 100644
index 0000000..67fd8d7
--- /dev/null
+++ b/src/test/ui/methods/method-call-lifetime-args-unresolved.stderr
@@ -0,0 +1,9 @@
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/method-call-lifetime-args-unresolved.rs:2:15
+   |
+LL |     0.clone::<'a>();
+   |               ^^ undeclared lifetime
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0261`.
diff --git a/src/test/ui/methods/method-call-lifetime-args.rs b/src/test/ui/methods/method-call-lifetime-args.rs
new file mode 100644
index 0000000..3292e9f
--- /dev/null
+++ b/src/test/ui/methods/method-call-lifetime-args.rs
@@ -0,0 +1,15 @@
+struct S;
+
+impl S {
+    fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
+    fn late_implicit(self, _: &u8, _: &u8) {}
+}
+
+fn ufcs() {
+    S::late::<'static>(S, &0, &0);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    S::late_implicit::<'static>(S, &0, &0);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+}
+
+fn main() {}
diff --git a/src/test/ui/methods/method-call-lifetime-args.stderr b/src/test/ui/methods/method-call-lifetime-args.stderr
new file mode 100644
index 0000000..64ae79e
--- /dev/null
+++ b/src/test/ui/methods/method-call-lifetime-args.stderr
@@ -0,0 +1,26 @@
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+  --> $DIR/method-call-lifetime-args.rs:9:15
+   |
+LL |     S::late::<'static>(S, &0, &0);
+   |               ^^^^^^^
+   |
+note: the late bound lifetime parameter is introduced here
+  --> $DIR/method-call-lifetime-args.rs:4:13
+   |
+LL |     fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
+   |             ^^
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+  --> $DIR/method-call-lifetime-args.rs:11:24
+   |
+LL |     S::late_implicit::<'static>(S, &0, &0);
+   |                        ^^^^^^^
+   |
+note: the late bound lifetime parameter is introduced here
+  --> $DIR/method-call-lifetime-args.rs:5:31
+   |
+LL |     fn late_implicit(self, _: &u8, _: &u8) {}
+   |                               ^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/methods/method-call-type-binding.rs b/src/test/ui/methods/method-call-type-binding.rs
new file mode 100644
index 0000000..f547ca8
--- /dev/null
+++ b/src/test/ui/methods/method-call-type-binding.rs
@@ -0,0 +1,3 @@
+fn main() {
+    0.clone::<T = u8>(); //~ ERROR associated type bindings are not allowed here
+}
diff --git a/src/test/ui/methods/method-call-type-binding.stderr b/src/test/ui/methods/method-call-type-binding.stderr
new file mode 100644
index 0000000..4b93082
--- /dev/null
+++ b/src/test/ui/methods/method-call-type-binding.stderr
@@ -0,0 +1,9 @@
+error[E0229]: associated type bindings are not allowed here
+  --> $DIR/method-call-type-binding.rs:2:15
+   |
+LL |     0.clone::<T = u8>();
+   |               ^^^^^^ associated type not allowed here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0229`.
diff --git a/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.rs b/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.rs
new file mode 100644
index 0000000..a5dae1c
--- /dev/null
+++ b/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.rs
@@ -0,0 +1,177 @@
+#![feature(arbitrary_self_types, coerce_unsized, dispatch_from_dyn, unsize, unsized_locals)]
+
+// This tests a few edge-cases around `arbitrary_self_types`. Most specifically,
+// it checks that the `ObjectCandidate` you get from method matching can't
+// match a trait with the same DefId as a supertrait but a bad type parameter.
+
+use std::marker::PhantomData;
+
+mod internal {
+    use std::ops::{CoerceUnsized, Deref, DispatchFromDyn};
+    use std::marker::{PhantomData, Unsize};
+
+    pub struct Smaht<T: ?Sized, MISC>(pub Box<T>, pub PhantomData<MISC>);
+
+    impl<T: ?Sized, MISC> Deref for Smaht<T, MISC> {
+        type Target = T;
+
+        fn deref(&self) -> &Self::Target {
+            &self.0
+        }
+    }
+    impl<T: ?Sized + Unsize<U>, U: ?Sized, MISC> CoerceUnsized<Smaht<U, MISC>>
+        for Smaht<T, MISC>
+    {}
+    impl<T: ?Sized + Unsize<U>, U: ?Sized, MISC> DispatchFromDyn<Smaht<U, MISC>>
+        for Smaht<T, MISC>
+    {}
+
+    pub trait Foo: X<u32> {}
+    pub trait X<T> {
+        fn foo(self: Smaht<Self, T>) -> T;
+    }
+
+    impl X<u32> for () {
+        fn foo(self: Smaht<Self, u32>) -> u32 {
+            0
+        }
+    }
+
+    pub trait Marker {}
+    impl Marker for dyn Foo {}
+    impl<T: Marker + ?Sized> X<u64> for T {
+        fn foo(self: Smaht<Self, u64>) -> u64 {
+            1
+        }
+    }
+
+    impl Deref for dyn Foo {
+        type Target = ();
+        fn deref(&self) -> &() { &() }
+    }
+
+    impl Foo for () {}
+}
+
+pub trait FinalFoo {
+    fn foo(&self) -> u8;
+}
+
+impl FinalFoo for () {
+    fn foo(&self) -> u8 { 0 }
+}
+
+mod nuisance_foo {
+    pub trait NuisanceFoo {
+        fn foo(self);
+    }
+
+    impl<T: ?Sized> NuisanceFoo for T {
+        fn foo(self) {}
+    }
+}
+
+
+fn objectcandidate_impl() {
+    let x: internal::Smaht<(), u32> = internal::Smaht(Box::new(()), PhantomData);
+    let x: internal::Smaht<dyn internal::Foo, u32> = x;
+
+    // This picks `<dyn internal::Foo as X<u32>>::foo` via `ObjectCandidate`.
+    //
+    // The `TraitCandidate` is not relevant because `X` is not in scope.
+    let z = x.foo();
+
+    // Observe the type of `z` is `u32`
+    let _seetype: () = z; //~ ERROR mismatched types
+    //~| expected (), found u32
+}
+
+fn traitcandidate_impl() {
+    use internal::X;
+
+    let x: internal::Smaht<(), u64> = internal::Smaht(Box::new(()), PhantomData);
+    let x: internal::Smaht<dyn internal::Foo, u64> = x;
+
+    // This picks `<dyn internal::Foo as X<u64>>::foo` via `TraitCandidate`.
+    //
+    // The `ObjectCandidate` does not apply, as it only applies to
+    // `X<u32>` (and not `X<u64>`).
+    let z = x.foo();
+
+    // Observe the type of `z` is `u64`
+    let _seetype: () = z; //~ ERROR mismatched types
+    //~| expected (), found u64
+}
+
+fn traitcandidate_impl_with_nuisance() {
+    use internal::X;
+    use nuisance_foo::NuisanceFoo;
+
+    let x: internal::Smaht<(), u64> = internal::Smaht(Box::new(()), PhantomData);
+    let x: internal::Smaht<dyn internal::Foo, u64> = x;
+
+    // This picks `<dyn internal::Foo as X<u64>>::foo` via `TraitCandidate`.
+    //
+    // The `ObjectCandidate` does not apply, as it only applies to
+    // `X<u32>` (and not `X<u64>`).
+    //
+    // The NuisanceFoo impl has the same priority as the `X` impl,
+    // so we get a conflict.
+    let z = x.foo(); //~ ERROR multiple applicable items in scope
+}
+
+
+fn neither_impl() {
+    let x: internal::Smaht<(), u64> = internal::Smaht(Box::new(()), PhantomData);
+    let x: internal::Smaht<dyn internal::Foo, u64> = x;
+
+    // This can't pick the `TraitCandidate` impl, because `Foo` is not
+    // imported. However, this also can't pick the `ObjectCandidate`
+    // impl, because it only applies to `X<u32>` (and not `X<u64>`).
+    //
+    // Therefore, neither of the candidates is applicable, and we pick
+    // the `FinalFoo` impl after another deref, which will return `u8`.
+    let z = x.foo();
+
+    // Observe the type of `z` is `u8`
+    let _seetype: () = z; //~ ERROR mismatched types
+    //~| expected (), found u8
+}
+
+fn both_impls() {
+    use internal::X;
+
+    let x: internal::Smaht<(), u32> = internal::Smaht(Box::new(()), PhantomData);
+    let x: internal::Smaht<dyn internal::Foo, u32> = x;
+
+    // This can pick both the `TraitCandidate` and the `ObjectCandidate` impl.
+    //
+    // However, the `ObjectCandidate` is considered an "inherent candidate",
+    // and therefore has priority over both the `TraitCandidate` as well as
+    // any other "nuisance" candidate" (if present).
+    let z = x.foo();
+
+    // Observe the type of `z` is `u32`
+    let _seetype: () = z; //~ ERROR mismatched types
+    //~| expected (), found u32
+}
+
+
+fn both_impls_with_nuisance() {
+    // Similar to the `both_impls` example, except with a nuisance impl to
+    // make sure the `ObjectCandidate` indeed has a higher priority.
+
+    use internal::X;
+    use nuisance_foo::NuisanceFoo;
+
+    let x: internal::Smaht<(), u32> = internal::Smaht(Box::new(()), PhantomData);
+    let x: internal::Smaht<dyn internal::Foo, u32> = x;
+    let z = x.foo();
+
+    // Observe the type of `z` is `u32`
+    let _seetype: () = z; //~ ERROR mismatched types
+    //~| expected (), found u32
+}
+
+fn main() {
+}
diff --git a/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr b/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr
new file mode 100644
index 0000000..3c2e9b0
--- /dev/null
+++ b/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr
@@ -0,0 +1,72 @@
+error[E0308]: mismatched types
+  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:85:24
+   |
+LL |     let _seetype: () = z;
+   |                        ^ expected (), found u32
+   |
+   = note: expected type `()`
+              found type `u32`
+
+error[E0308]: mismatched types
+  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:102:24
+   |
+LL |     let _seetype: () = z;
+   |                        ^ expected (), found u64
+   |
+   = note: expected type `()`
+              found type `u64`
+
+error[E0034]: multiple applicable items in scope
+  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:120:15
+   |
+LL |     let z = x.foo();
+   |               ^^^ multiple `foo` found
+   |
+note: candidate #1 is defined in an impl of the trait `internal::X` for the type `_`
+  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:43:9
+   |
+LL |         fn foo(self: Smaht<Self, u64>) -> u64 {
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: candidate #2 is defined in an impl of the trait `nuisance_foo::NuisanceFoo` for the type `_`
+  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:70:9
+   |
+LL |         fn foo(self) {}
+   |         ^^^^^^^^^^^^
+note: candidate #3 is defined in the trait `FinalFoo`
+  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:57:5
+   |
+LL |     fn foo(&self) -> u8;
+   |     ^^^^^^^^^^^^^^^^^^^^
+   = help: to disambiguate the method call, write `FinalFoo::foo(x)` instead
+
+error[E0308]: mismatched types
+  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:137:24
+   |
+LL |     let _seetype: () = z;
+   |                        ^ expected (), found u8
+   |
+   = note: expected type `()`
+              found type `u8`
+
+error[E0308]: mismatched types
+  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:155:24
+   |
+LL |     let _seetype: () = z;
+   |                        ^ expected (), found u32
+   |
+   = note: expected type `()`
+              found type `u32`
+
+error[E0308]: mismatched types
+  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:172:24
+   |
+LL |     let _seetype: () = z;
+   |                        ^ expected (), found u32
+   |
+   = note: expected type `()`
+              found type `u32`
+
+error: aborting due to 6 previous errors
+
+Some errors occurred: E0034, E0308.
+For more information about an error, try `rustc --explain E0034`.
diff --git a/src/test/ui/methods/method-macro-backtrace.rs b/src/test/ui/methods/method-macro-backtrace.rs
new file mode 100644
index 0000000..00fe32b
--- /dev/null
+++ b/src/test/ui/methods/method-macro-backtrace.rs
@@ -0,0 +1,25 @@
+// forbid-output: in this expansion of
+
+macro_rules! make_method {
+    ($name:ident) => ( fn $name(&self) { } )
+}
+
+struct S;
+
+impl S {
+    // We had a bug where these wouldn't clean up macro backtrace frames.
+    make_method!(foo1);
+    make_method!(foo2);
+    make_method!(foo3);
+    make_method!(foo4);
+    make_method!(foo5);
+    make_method!(foo6);
+    make_method!(foo7);
+    make_method!(foo8);
+
+    // Cause an error. It shouldn't have any macro backtrace frames.
+    fn bar(&self) { }
+    fn bar(&self) { } //~ ERROR duplicate definitions
+}
+
+fn main() { }
diff --git a/src/test/ui/methods/method-macro-backtrace.stderr b/src/test/ui/methods/method-macro-backtrace.stderr
new file mode 100644
index 0000000..7860365
--- /dev/null
+++ b/src/test/ui/methods/method-macro-backtrace.stderr
@@ -0,0 +1,11 @@
+error[E0201]: duplicate definitions with name `bar`:
+  --> $DIR/method-macro-backtrace.rs:22:5
+   |
+LL |     fn bar(&self) { }
+   |     ----------------- previous definition of `bar` here
+LL |     fn bar(&self) { }
+   |     ^^^^^^^^^^^^^^^^^ duplicate definition
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0201`.
diff --git a/src/test/ui/methods/method-missing-call.rs b/src/test/ui/methods/method-missing-call.rs
new file mode 100644
index 0000000..7ce1e9a
--- /dev/null
+++ b/src/test/ui/methods/method-missing-call.rs
@@ -0,0 +1,30 @@
+// Tests to make sure that parens are needed for method calls without arguments.
+// outputs text to make sure either an anonymous function is provided or
+// open-close '()' parens are given
+
+
+struct Point {
+    x: isize,
+    y: isize
+}
+impl Point {
+    fn new() -> Point {
+        Point{x:0, y:0}
+    }
+    fn get_x(&self) -> isize {
+        self.x
+    }
+}
+
+fn main() {
+    let point: Point = Point::new();
+    let px: isize =  point
+                        .get_x;//~ ERROR attempted to take value of method `get_x` on type `Point`
+
+    // Ensure the span is useful
+    let ys = &[1,2,3,4,5,6,7];
+    let a = ys.iter()
+              .map(|x| x)
+              .filter(|&&x| x == 1)
+              .filter_map; //~ ERROR attempted to take value of method `filter_map` on type
+}
diff --git a/src/test/ui/methods/method-missing-call.stderr b/src/test/ui/methods/method-missing-call.stderr
new file mode 100644
index 0000000..3ab5f66
--- /dev/null
+++ b/src/test/ui/methods/method-missing-call.stderr
@@ -0,0 +1,15 @@
+error[E0615]: attempted to take value of method `get_x` on type `Point`
+  --> $DIR/method-missing-call.rs:22:26
+   |
+LL |                         .get_x;
+   |                          ^^^^^ help: use parentheses to call the method: `get_x()`
+
+error[E0615]: attempted to take value of method `filter_map` on type `std::iter::Filter<std::iter::Map<std::slice::Iter<'_, {integer}>, [closure@$DIR/method-missing-call.rs:27:20: 27:25]>, [closure@$DIR/method-missing-call.rs:28:23: 28:35]>`
+  --> $DIR/method-missing-call.rs:29:16
+   |
+LL |               .filter_map;
+   |                ^^^^^^^^^^ help: use parentheses to call the method: `filter_map(...)`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0615`.
diff --git a/src/test/ui/methods/method-on-ambiguous-numeric-type.rs b/src/test/ui/methods/method-on-ambiguous-numeric-type.rs
new file mode 100644
index 0000000..82f4743
--- /dev/null
+++ b/src/test/ui/methods/method-on-ambiguous-numeric-type.rs
@@ -0,0 +1,32 @@
+// aux-build:macro-in-other-crate.rs
+
+#[macro_use] extern crate macro_in_other_crate;
+
+macro_rules! local_mac {
+    ($ident:ident) => { let $ident = 42; }
+}
+
+fn main() {
+    let x = 2.0.neg();
+    //~^ ERROR can't call method `neg` on ambiguous numeric type `{float}`
+
+    let y = 2.0;
+    let x = y.neg();
+    //~^ ERROR can't call method `neg` on ambiguous numeric type `{float}`
+    println!("{:?}", x);
+
+    for i in 0..100 {
+        println!("{}", i.pow(2));
+        //~^ ERROR can't call method `pow` on ambiguous numeric type `{integer}`
+    }
+
+    local_mac!(local_bar);
+    local_bar.pow(2);
+    //~^ ERROR can't call method `pow` on ambiguous numeric type `{integer}`
+}
+
+fn qux() {
+    mac!(bar);
+    bar.pow(2);
+    //~^ ERROR can't call method `pow` on ambiguous numeric type `{integer}`
+}
diff --git a/src/test/ui/methods/method-on-ambiguous-numeric-type.stderr b/src/test/ui/methods/method-on-ambiguous-numeric-type.stderr
new file mode 100644
index 0000000..40e765a
--- /dev/null
+++ b/src/test/ui/methods/method-on-ambiguous-numeric-type.stderr
@@ -0,0 +1,51 @@
+error[E0689]: can't call method `neg` on ambiguous numeric type `{float}`
+  --> $DIR/method-on-ambiguous-numeric-type.rs:10:17
+   |
+LL |     let x = 2.0.neg();
+   |                 ^^^
+help: you must specify a concrete type for this numeric value, like `f32`
+   |
+LL |     let x = 2.0_f32.neg();
+   |             ^^^^^^^
+
+error[E0689]: can't call method `neg` on ambiguous numeric type `{float}`
+  --> $DIR/method-on-ambiguous-numeric-type.rs:14:15
+   |
+LL |     let x = y.neg();
+   |               ^^^
+help: you must specify a type for this binding, like `f32`
+   |
+LL |     let y: f32 = 2.0;
+   |         ^^^^^^
+
+error[E0689]: can't call method `pow` on ambiguous numeric type `{integer}`
+  --> $DIR/method-on-ambiguous-numeric-type.rs:19:26
+   |
+LL |     for i in 0..100 {
+   |         - you must specify a type for this binding, like `i32`
+LL |         println!("{}", i.pow(2));
+   |                          ^^^
+
+error[E0689]: can't call method `pow` on ambiguous numeric type `{integer}`
+  --> $DIR/method-on-ambiguous-numeric-type.rs:24:15
+   |
+LL |     local_bar.pow(2);
+   |               ^^^
+help: you must specify a type for this binding, like `i32`
+   |
+LL |     ($ident:ident) => { let $ident: i32 = 42; }
+   |                             ^^^^^^^^^^^
+
+error[E0689]: can't call method `pow` on ambiguous numeric type `{integer}`
+  --> $DIR/method-on-ambiguous-numeric-type.rs:30:9
+   |
+LL |     mac!(bar);
+   |     ---------- you must specify a type for this binding, like `i32`
+LL |     bar.pow(2);
+   |         ^^^
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0689`.
diff --git a/src/test/ui/methods/method-path-in-pattern.rs b/src/test/ui/methods/method-path-in-pattern.rs
new file mode 100644
index 0000000..fb1cf7f
--- /dev/null
+++ b/src/test/ui/methods/method-path-in-pattern.rs
@@ -0,0 +1,26 @@
+struct Foo;
+
+impl Foo {
+    fn bar(&self) {}
+}
+
+trait MyTrait {
+    fn trait_bar() {}
+}
+
+impl MyTrait for Foo {}
+
+fn main() {
+    match 0u32 {
+        Foo::bar => {}
+        //~^ ERROR expected unit struct/variant or constant, found method `<Foo>::bar`
+    }
+    match 0u32 {
+        <Foo>::bar => {}
+        //~^ ERROR expected unit struct/variant or constant, found method `<Foo>::bar`
+    }
+    match 0u32 {
+        <Foo>::trait_bar => {}
+        //~^ ERROR expected unit struct/variant or constant, found method `<Foo>::trait_bar`
+    }
+}
diff --git a/src/test/ui/methods/method-path-in-pattern.stderr b/src/test/ui/methods/method-path-in-pattern.stderr
new file mode 100644
index 0000000..03d6509
--- /dev/null
+++ b/src/test/ui/methods/method-path-in-pattern.stderr
@@ -0,0 +1,21 @@
+error[E0533]: expected unit struct/variant or constant, found method `<Foo>::bar`
+  --> $DIR/method-path-in-pattern.rs:15:9
+   |
+LL |         Foo::bar => {}
+   |         ^^^^^^^^
+
+error[E0533]: expected unit struct/variant or constant, found method `<Foo>::bar`
+  --> $DIR/method-path-in-pattern.rs:19:9
+   |
+LL |         <Foo>::bar => {}
+   |         ^^^^^^^^^^
+
+error[E0533]: expected unit struct/variant or constant, found method `<Foo>::trait_bar`
+  --> $DIR/method-path-in-pattern.rs:23:9
+   |
+LL |         <Foo>::trait_bar => {}
+   |         ^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0533`.
diff --git a/src/test/ui/methods/method-resolvable-path-in-pattern.rs b/src/test/ui/methods/method-resolvable-path-in-pattern.rs
new file mode 100644
index 0000000..1d373cf
--- /dev/null
+++ b/src/test/ui/methods/method-resolvable-path-in-pattern.rs
@@ -0,0 +1,14 @@
+struct Foo;
+
+trait MyTrait {
+    fn trait_bar() {}
+}
+
+impl MyTrait for Foo {}
+
+fn main() {
+    match 0u32 {
+        <Foo as MyTrait>::trait_bar => {}
+        //~^ ERROR expected unit struct/variant or constant, found method `MyTrait::trait_bar`
+    }
+}
diff --git a/src/test/ui/methods/method-resolvable-path-in-pattern.stderr b/src/test/ui/methods/method-resolvable-path-in-pattern.stderr
new file mode 100644
index 0000000..f631c92
--- /dev/null
+++ b/src/test/ui/methods/method-resolvable-path-in-pattern.stderr
@@ -0,0 +1,9 @@
+error[E0532]: expected unit struct/variant or constant, found method `MyTrait::trait_bar`
+  --> $DIR/method-resolvable-path-in-pattern.rs:11:9
+   |
+LL |         <Foo as MyTrait>::trait_bar => {}
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a unit struct/variant or constant
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0532`.
diff --git a/src/test/ui/methods/method-self-arg-1.rs b/src/test/ui/methods/method-self-arg-1.rs
new file mode 100644
index 0000000..4a78ad7
--- /dev/null
+++ b/src/test/ui/methods/method-self-arg-1.rs
@@ -0,0 +1,19 @@
+// Test method calls with self as an argument cannot subvert type checking.
+
+struct Foo;
+
+impl Foo {
+    fn bar(&self) {}
+}
+
+fn main() {
+    let x = Foo;
+    Foo::bar(x); //~  ERROR mismatched types
+                 //~| expected type `&Foo`
+                 //~| found type `Foo`
+                 //~| expected &Foo, found struct `Foo`
+    Foo::bar(&42); //~  ERROR mismatched types
+                      //~| expected type `&Foo`
+                      //~| found type `&{integer}`
+                      //~| expected struct `Foo`, found integer
+}
diff --git a/src/test/ui/methods/method-self-arg-1.stderr b/src/test/ui/methods/method-self-arg-1.stderr
new file mode 100644
index 0000000..8485a54
--- /dev/null
+++ b/src/test/ui/methods/method-self-arg-1.stderr
@@ -0,0 +1,24 @@
+error[E0308]: mismatched types
+  --> $DIR/method-self-arg-1.rs:11:14
+   |
+LL |     Foo::bar(x);
+   |              ^
+   |              |
+   |              expected &Foo, found struct `Foo`
+   |              help: consider borrowing here: `&x`
+   |
+   = note: expected type `&Foo`
+              found type `Foo`
+
+error[E0308]: mismatched types
+  --> $DIR/method-self-arg-1.rs:15:14
+   |
+LL |     Foo::bar(&42);
+   |              ^^^ expected struct `Foo`, found integer
+   |
+   = note: expected type `&Foo`
+              found type `&{integer}`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/methods/method-self-arg-2.nll.stderr b/src/test/ui/methods/method-self-arg-2.nll.stderr
new file mode 100644
index 0000000..82092dd
--- /dev/null
+++ b/src/test/ui/methods/method-self-arg-2.nll.stderr
@@ -0,0 +1,24 @@
+error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
+  --> $DIR/method-self-arg-2.rs:15:14
+   |
+LL |     let y = &mut x;
+   |             ------ mutable borrow occurs here
+LL |     Foo::bar(&x);
+   |              ^^ immutable borrow occurs here
+LL |     y.use_mut();
+   |     - mutable borrow later used here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time
+  --> $DIR/method-self-arg-2.rs:20:14
+   |
+LL |     let y = &mut x;
+   |             ------ first mutable borrow occurs here
+LL |     Foo::baz(&mut x);
+   |              ^^^^^^ second mutable borrow occurs here
+LL |     y.use_mut();
+   |     - first borrow later used here
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0499, E0502.
+For more information about an error, try `rustc --explain E0499`.
diff --git a/src/test/ui/methods/method-self-arg-2.rs b/src/test/ui/methods/method-self-arg-2.rs
new file mode 100644
index 0000000..0f8c048
--- /dev/null
+++ b/src/test/ui/methods/method-self-arg-2.rs
@@ -0,0 +1,25 @@
+// Test method calls with self as an argument cannot subvert borrow checking.
+
+
+
+struct Foo;
+
+impl Foo {
+    fn bar(&self) {}
+    fn baz(&mut self) {}
+}
+
+fn main() {
+    let mut x = Foo;
+    let y = &mut x;
+    Foo::bar(&x); //~ERROR cannot borrow `x`
+    y.use_mut();
+
+    let mut x = Foo;
+    let y = &mut x;
+    Foo::baz(&mut x); //~ERROR cannot borrow `x`
+    y.use_mut();
+}
+
+trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { }  }
+impl<T> Fake for T { }
diff --git a/src/test/ui/methods/method-self-arg-2.stderr b/src/test/ui/methods/method-self-arg-2.stderr
new file mode 100644
index 0000000..56cc8c8
--- /dev/null
+++ b/src/test/ui/methods/method-self-arg-2.stderr
@@ -0,0 +1,26 @@
+error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
+  --> $DIR/method-self-arg-2.rs:15:15
+   |
+LL |     let y = &mut x;
+   |                  - mutable borrow occurs here
+LL |     Foo::bar(&x);
+   |               ^ immutable borrow occurs here
+...
+LL | }
+   | - mutable borrow ends here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time
+  --> $DIR/method-self-arg-2.rs:20:19
+   |
+LL |     let y = &mut x;
+   |                  - first mutable borrow occurs here
+LL |     Foo::baz(&mut x);
+   |                   ^ second mutable borrow occurs here
+LL |     y.use_mut();
+LL | }
+   | - first borrow ends here
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0499, E0502.
+For more information about an error, try `rustc --explain E0499`.
diff --git a/src/test/ui/methods/method-trait-object-with-hrtb.rs b/src/test/ui/methods/method-trait-object-with-hrtb.rs
new file mode 100644
index 0000000..da2f13f
--- /dev/null
+++ b/src/test/ui/methods/method-trait-object-with-hrtb.rs
@@ -0,0 +1,41 @@
+// compile-pass
+
+// Check that method probing ObjectCandidate works in the presence of
+// auto traits and/or HRTBs.
+
+mod internal {
+    pub trait MyObject<'a> {
+        type Output;
+
+        fn foo(&self) -> Self::Output;
+    }
+
+    impl<'a> MyObject<'a> for () {
+        type Output = &'a u32;
+
+        fn foo(&self) -> Self::Output { &4 }
+    }
+}
+
+fn t1(d: &dyn for<'a> internal::MyObject<'a, Output=&'a u32>) {
+    d.foo();
+}
+
+fn t2(d: &dyn internal::MyObject<'static, Output=&'static u32>) {
+    d.foo();
+}
+
+fn t3(d: &(dyn for<'a> internal::MyObject<'a, Output=&'a u32> + Sync)) {
+    d.foo();
+}
+
+fn t4(d: &(dyn internal::MyObject<'static, Output=&'static u32> + Sync)) {
+    d.foo();
+}
+
+fn main() {
+    t1(&());
+    t2(&());
+    t3(&());
+    t4(&());
+}
diff --git a/src/test/ui/minus-string.rs b/src/test/ui/minus-string.rs
new file mode 100644
index 0000000..946c587
--- /dev/null
+++ b/src/test/ui/minus-string.rs
@@ -0,0 +1,3 @@
+// error-pattern:cannot apply unary operator `-` to type `std::string::String`
+
+fn main() { -"foo".to_string(); }
diff --git a/src/test/ui/minus-string.stderr b/src/test/ui/minus-string.stderr
new file mode 100644
index 0000000..9177082
--- /dev/null
+++ b/src/test/ui/minus-string.stderr
@@ -0,0 +1,11 @@
+error[E0600]: cannot apply unary operator `-` to type `std::string::String`
+  --> $DIR/minus-string.rs:3:13
+   |
+LL | fn main() { -"foo".to_string(); }
+   |             ^^^^^^^^^^^^^^^^^^ cannot apply unary operator `-`
+   |
+   = note: an implementation of `std::ops::Neg` might be missing for `std::string::String`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0600`.
diff --git a/src/test/ui/mir-dataflow/README.md b/src/test/ui/mir-dataflow/README.md
new file mode 100644
index 0000000..a3ab14b
--- /dev/null
+++ b/src/test/ui/mir-dataflow/README.md
@@ -0,0 +1,53 @@
+This directory contains unit tests for the MIR-based dataflow
+analysis.
+
+These unit tests check the dataflow analysis by embedding calls to a
+special `rustc_peek` intrinsic within the code, in tandem with an
+attribute `#[rustc_mir(rustc_peek_maybe_init)]` (\*). With that
+attribute in place, `rustc_peek` calls are a signal to the compiler to
+lookup the computed dataflow state for the Lvalue corresponding to the
+argument expression being fed to `rustc_peek`. If the dataflow state
+for that Lvalue is a 1-bit at that point in the control flow, then no
+error is emitted by the compiler at that point; if it is a 0-bit, then
+that invocation of `rustc_peek` will emit an error with the message
+"rustc_peek: bit not set".
+
+(\*): Or `#[rustc_mir(rustc_peek_maybe_uninit)]`, and perhaps other
+variants in the future.
+
+The end effect is that one can write unit tests for MIR dataflow that
+perform simple-queries of the computed dataflow state, and the tests
+should be able to be robust in the face of changes to how MIR is
+represented or constructed.
+
+----
+
+Sometimes understanding the dataflow results is difficult without
+looking at the actual MIR control-flow graph being processed with the
+corresponding GEN and KILL sets.
+
+For a graphviz-rendering with dataflow annotations, add the attribute
+`#[rustc_mir(borrowck_graphviz_postflow="/path/to/suffix.dot")]` to
+the function in question. (You can change the content of
+`"suffix.dot"` to control the filenames used for the output). This
+will generate a separate file for each dataflow analysis, adding a
+prefix (corresponding to the name of the analysis) to the filename in
+each generated output path.
+
+ * For example, the above attribute will currently cause two files to
+   be generated: `/path/to/maybe_init_suffix.dot` and
+   `/path/to/maybe_uninit_suffix.dot`.
+
+ * The generated `.dot` file shows both the computed dataflow results
+   on *entry* to each block, as well as the gen- and kill-sets that
+   were so-called "transfer functions" summarizing the effect of each
+   basic block.
+
+ * (In addition to the `borrowck_graphviz_postflow` attribute-key
+   noted above, there is also `borrowck_graphviz_preflow`; it has the
+   same interface and generates the same set of files, but it renders
+   the dataflow state after building the gen- and kill-sets but
+   *before* running the dataflow analysis itself, so each entry-set is
+   just the initial default state for that dataflow analysis. This is
+   less useful for understanding the error message output in these
+   tests.)
diff --git a/src/test/ui/mir-dataflow/def-inits-1.rs b/src/test/ui/mir-dataflow/def-inits-1.rs
new file mode 100644
index 0000000..07ac190
--- /dev/null
+++ b/src/test/ui/mir-dataflow/def-inits-1.rs
@@ -0,0 +1,52 @@
+// General test of maybe_uninits state computed by MIR dataflow.
+
+#![feature(nll)]
+#![feature(core_intrinsics, rustc_attrs)]
+
+use std::intrinsics::rustc_peek;
+use std::mem::{drop, replace};
+
+struct S(i32);
+
+#[rustc_mir(rustc_peek_definite_init,stop_after_dataflow)]
+fn foo(test: bool, x: &mut S, y: S, mut z: S) -> S {
+    let ret;
+    // `ret` starts off uninitialized
+    unsafe { rustc_peek(&ret); }  //~ ERROR rustc_peek: bit not set
+
+    // All function formal parameters start off initialized.
+
+    unsafe { rustc_peek(&x) };
+    unsafe { rustc_peek(&y) };
+    unsafe { rustc_peek(&z) };
+
+    ret = if test {
+        ::std::mem::replace(x, y)
+    } else {
+        z = y;
+        z
+    };
+
+    // `z` may be uninitialized here.
+    unsafe { rustc_peek(&z); } //~ ERROR rustc_peek: bit not set
+
+    // `y` is definitely uninitialized here.
+    unsafe { rustc_peek(&y); } //~ ERROR rustc_peek: bit not set
+
+    // `x` is still (definitely) initialized (replace above is a reborrow).
+    unsafe { rustc_peek(&x); }
+
+    ::std::mem::drop(x);
+
+    // `x` is *definitely* uninitialized here
+    unsafe { rustc_peek(&x); } //~ ERROR rustc_peek: bit not set
+
+    // `ret` is now definitely initialized (via `if` above).
+    unsafe { rustc_peek(&ret); }
+
+    ret
+}
+fn main() {
+    foo(true, &mut S(13), S(14), S(15));
+    foo(false, &mut S(13), S(14), S(15));
+}
diff --git a/src/test/ui/mir-dataflow/def-inits-1.stderr b/src/test/ui/mir-dataflow/def-inits-1.stderr
new file mode 100644
index 0000000..6bc5f7dc
--- /dev/null
+++ b/src/test/ui/mir-dataflow/def-inits-1.stderr
@@ -0,0 +1,28 @@
+error: rustc_peek: bit not set
+  --> $DIR/def-inits-1.rs:15:14
+   |
+LL |     unsafe { rustc_peek(&ret); }
+   |              ^^^^^^^^^^^^^^^^
+
+error: rustc_peek: bit not set
+  --> $DIR/def-inits-1.rs:31:14
+   |
+LL |     unsafe { rustc_peek(&z); }
+   |              ^^^^^^^^^^^^^^
+
+error: rustc_peek: bit not set
+  --> $DIR/def-inits-1.rs:34:14
+   |
+LL |     unsafe { rustc_peek(&y); }
+   |              ^^^^^^^^^^^^^^
+
+error: rustc_peek: bit not set
+  --> $DIR/def-inits-1.rs:42:14
+   |
+LL |     unsafe { rustc_peek(&x); }
+   |              ^^^^^^^^^^^^^^
+
+error: stop_after_dataflow ended compilation
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/ui/mir-dataflow/inits-1.rs b/src/test/ui/mir-dataflow/inits-1.rs
new file mode 100644
index 0000000..13f900e
--- /dev/null
+++ b/src/test/ui/mir-dataflow/inits-1.rs
@@ -0,0 +1,54 @@
+// General test of maybe_inits state computed by MIR dataflow.
+
+#![feature(nll)]
+#![feature(core_intrinsics, rustc_attrs)]
+
+use std::intrinsics::rustc_peek;
+use std::mem::{drop, replace};
+
+struct S(i32);
+
+#[rustc_mir(rustc_peek_maybe_init,stop_after_dataflow)]
+fn foo(test: bool, x: &mut S, y: S, mut z: S) -> S {
+    let ret;
+    // `ret` starts off uninitialized, so we get an error report here.
+    unsafe { rustc_peek(&ret); }  //~ ERROR rustc_peek: bit not set
+
+    // All function formal parameters start off initialized.
+
+    unsafe { rustc_peek(&x) };
+    unsafe { rustc_peek(&y) };
+    unsafe { rustc_peek(&z) };
+
+    ret = if test {
+        ::std::mem::replace(x, y)
+    } else {
+        z = y;
+        z
+    };
+
+
+    // `z` may be initialized here.
+    unsafe { rustc_peek(&z); }
+
+    // `y` is definitely uninitialized here.
+    unsafe { rustc_peek(&y); }  //~ ERROR rustc_peek: bit not set
+
+    // `x` is still (definitely) initialized (replace above is a reborrow).
+    unsafe { rustc_peek(&x); }
+
+    ::std::mem::drop(x);
+
+    // `x` is *definitely* uninitialized here
+    unsafe { rustc_peek(&x); } //~ ERROR rustc_peek: bit not set
+
+    // `ret` is now definitely initialized (via `if` above).
+    unsafe { rustc_peek(&ret); }
+
+    ret
+}
+
+fn main() {
+    foo(true, &mut S(13), S(14), S(15));
+    foo(false, &mut S(13), S(14), S(15));
+}
diff --git a/src/test/ui/mir-dataflow/inits-1.stderr b/src/test/ui/mir-dataflow/inits-1.stderr
new file mode 100644
index 0000000..38a9c60
--- /dev/null
+++ b/src/test/ui/mir-dataflow/inits-1.stderr
@@ -0,0 +1,22 @@
+error: rustc_peek: bit not set
+  --> $DIR/inits-1.rs:15:14
+   |
+LL |     unsafe { rustc_peek(&ret); }
+   |              ^^^^^^^^^^^^^^^^
+
+error: rustc_peek: bit not set
+  --> $DIR/inits-1.rs:35:14
+   |
+LL |     unsafe { rustc_peek(&y); }
+   |              ^^^^^^^^^^^^^^
+
+error: rustc_peek: bit not set
+  --> $DIR/inits-1.rs:43:14
+   |
+LL |     unsafe { rustc_peek(&x); }
+   |              ^^^^^^^^^^^^^^
+
+error: stop_after_dataflow ended compilation
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/mir-dataflow/uninits-1.rs b/src/test/ui/mir-dataflow/uninits-1.rs
new file mode 100644
index 0000000..4c64359
--- /dev/null
+++ b/src/test/ui/mir-dataflow/uninits-1.rs
@@ -0,0 +1,52 @@
+// General test of maybe_uninits state computed by MIR dataflow.
+
+#![feature(nll)]
+#![feature(core_intrinsics, rustc_attrs)]
+
+use std::intrinsics::rustc_peek;
+use std::mem::{drop, replace};
+
+struct S(i32);
+
+#[rustc_mir(rustc_peek_maybe_uninit,stop_after_dataflow)]
+fn foo(test: bool, x: &mut S, y: S, mut z: S) -> S {
+    let ret;
+    // `ret` starts off uninitialized
+    unsafe { rustc_peek(&ret); }
+
+    // All function formal parameters start off initialized.
+
+    unsafe { rustc_peek(&x) }; //~ ERROR rustc_peek: bit not set
+    unsafe { rustc_peek(&y) }; //~ ERROR rustc_peek: bit not set
+    unsafe { rustc_peek(&z) }; //~ ERROR rustc_peek: bit not set
+
+    ret = if test {
+        ::std::mem::replace(x, y)
+    } else {
+        z = y;
+        z
+    };
+
+    // `z` may be uninitialized here.
+    unsafe { rustc_peek(&z); }
+
+    // `y` is definitely uninitialized here.
+    unsafe { rustc_peek(&y); }
+
+    // `x` is still (definitely) initialized (replace above is a reborrow).
+    unsafe { rustc_peek(&x); } //~ ERROR rustc_peek: bit not set
+
+    ::std::mem::drop(x);
+
+    // `x` is *definitely* uninitialized here
+    unsafe { rustc_peek(&x); }
+
+    // `ret` is now definitely initialized (via `if` above).
+    unsafe { rustc_peek(&ret); } //~ ERROR rustc_peek: bit not set
+
+    ret
+}
+fn main() {
+    foo(true, &mut S(13), S(14), S(15));
+    foo(false, &mut S(13), S(14), S(15));
+}
diff --git a/src/test/ui/mir-dataflow/uninits-1.stderr b/src/test/ui/mir-dataflow/uninits-1.stderr
new file mode 100644
index 0000000..c609870
--- /dev/null
+++ b/src/test/ui/mir-dataflow/uninits-1.stderr
@@ -0,0 +1,34 @@
+error: rustc_peek: bit not set
+  --> $DIR/uninits-1.rs:19:14
+   |
+LL |     unsafe { rustc_peek(&x) };
+   |              ^^^^^^^^^^^^^^
+
+error: rustc_peek: bit not set
+  --> $DIR/uninits-1.rs:20:14
+   |
+LL |     unsafe { rustc_peek(&y) };
+   |              ^^^^^^^^^^^^^^
+
+error: rustc_peek: bit not set
+  --> $DIR/uninits-1.rs:21:14
+   |
+LL |     unsafe { rustc_peek(&z) };
+   |              ^^^^^^^^^^^^^^
+
+error: rustc_peek: bit not set
+  --> $DIR/uninits-1.rs:37:14
+   |
+LL |     unsafe { rustc_peek(&x); }
+   |              ^^^^^^^^^^^^^^
+
+error: rustc_peek: bit not set
+  --> $DIR/uninits-1.rs:45:14
+   |
+LL |     unsafe { rustc_peek(&ret); }
+   |              ^^^^^^^^^^^^^^^^
+
+error: stop_after_dataflow ended compilation
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/mir-dataflow/uninits-2.rs b/src/test/ui/mir-dataflow/uninits-2.rs
new file mode 100644
index 0000000..2247e68
--- /dev/null
+++ b/src/test/ui/mir-dataflow/uninits-2.rs
@@ -0,0 +1,25 @@
+// General test of maybe_uninits state computed by MIR dataflow.
+
+#![feature(nll)]
+#![feature(core_intrinsics, rustc_attrs)]
+
+use std::intrinsics::rustc_peek;
+use std::mem::{drop, replace};
+
+struct S(i32);
+
+#[rustc_mir(rustc_peek_maybe_uninit,stop_after_dataflow)]
+fn foo(x: &mut S) {
+    // `x` is initialized here, so maybe-uninit bit is 0.
+
+    unsafe { rustc_peek(&x) }; //~ ERROR rustc_peek: bit not set
+
+    ::std::mem::drop(x);
+
+    // `x` definitely uninitialized here, so maybe-uninit bit is 1.
+    unsafe { rustc_peek(&x) };
+}
+fn main() {
+    foo(&mut S(13));
+    foo(&mut S(13));
+}
diff --git a/src/test/ui/mir-dataflow/uninits-2.stderr b/src/test/ui/mir-dataflow/uninits-2.stderr
new file mode 100644
index 0000000..de3e58e
--- /dev/null
+++ b/src/test/ui/mir-dataflow/uninits-2.stderr
@@ -0,0 +1,10 @@
+error: rustc_peek: bit not set
+  --> $DIR/uninits-2.rs:15:14
+   |
+LL |     unsafe { rustc_peek(&x) };
+   |              ^^^^^^^^^^^^^^
+
+error: stop_after_dataflow ended compilation
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/mir-unpretty.rs b/src/test/ui/mir-unpretty.rs
new file mode 100644
index 0000000..30620c6
--- /dev/null
+++ b/src/test/ui/mir-unpretty.rs
@@ -0,0 +1,5 @@
+// compile-flags: -Z unpretty=mir
+
+fn main() {
+    let x: () = 0; //~ ERROR: mismatched types
+}
diff --git a/src/test/ui/mir-unpretty.stderr b/src/test/ui/mir-unpretty.stderr
new file mode 100644
index 0000000..6e5dac2
--- /dev/null
+++ b/src/test/ui/mir-unpretty.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/mir-unpretty.rs:4:17
+   |
+LL |     let x: () = 0;
+   |                 ^ expected (), found integer
+   |
+   = note: expected type `()`
+              found type `{integer}`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/mir_check_nonconst.rs b/src/test/ui/mir_check_nonconst.rs
new file mode 100644
index 0000000..b8ec0c3
--- /dev/null
+++ b/src/test/ui/mir_check_nonconst.rs
@@ -0,0 +1,11 @@
+#![allow(dead_code)]
+
+struct Foo { a: u8 }
+fn bar() -> Foo {
+    Foo { a: 5 }
+}
+
+static foo: Foo = bar();
+//~^ ERROR calls in statics are limited to constant functions, tuple structs and tuple variants
+
+fn main() {}
diff --git a/src/test/ui/mir_check_nonconst.stderr b/src/test/ui/mir_check_nonconst.stderr
new file mode 100644
index 0000000..30f68ba
--- /dev/null
+++ b/src/test/ui/mir_check_nonconst.stderr
@@ -0,0 +1,9 @@
+error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
+  --> $DIR/mir_check_nonconst.rs:8:19
+   |
+LL | static foo: Foo = bar();
+   |                   ^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0015`.
diff --git a/src/test/ui/mismatched_types/E0053.rs b/src/test/ui/mismatched_types/E0053.rs
new file mode 100644
index 0000000..d3146ce
--- /dev/null
+++ b/src/test/ui/mismatched_types/E0053.rs
@@ -0,0 +1,16 @@
+trait Foo {
+    fn foo(x: u16);
+    fn bar(&self);
+}
+
+struct Bar;
+
+impl Foo for Bar {
+    fn foo(x: i16) { }
+    //~^ ERROR method `foo` has an incompatible type for trait
+    fn bar(&mut self) { }
+    //~^ ERROR method `bar` has an incompatible type for trait
+}
+
+fn main() {
+}
diff --git a/src/test/ui/mismatched_types/E0053.stderr b/src/test/ui/mismatched_types/E0053.stderr
new file mode 100644
index 0000000..582772d
--- /dev/null
+++ b/src/test/ui/mismatched_types/E0053.stderr
@@ -0,0 +1,31 @@
+error[E0053]: method `foo` has an incompatible type for trait
+  --> $DIR/E0053.rs:9:15
+   |
+LL |     fn foo(x: u16);
+   |               --- type in trait
+...
+LL |     fn foo(x: i16) { }
+   |               ^^^ expected u16, found i16
+   |
+   = note: expected type `fn(u16)`
+              found type `fn(i16)`
+
+error[E0053]: method `bar` has an incompatible type for trait
+  --> $DIR/E0053.rs:11:12
+   |
+LL |     fn bar(&self);
+   |            ----- type in trait
+...
+LL |     fn bar(&mut self) { }
+   |            ^^^^^^^^^ types differ in mutability
+   |
+   = note: expected type `fn(&Bar)`
+              found type `fn(&mut Bar)`
+help: consider change the type to match the mutability in trait
+   |
+LL |     fn bar(&self) { }
+   |            ^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0053`.
diff --git a/src/test/ui/mismatched_types/E0409.rs b/src/test/ui/mismatched_types/E0409.rs
new file mode 100644
index 0000000..3710534
--- /dev/null
+++ b/src/test/ui/mismatched_types/E0409.rs
@@ -0,0 +1,9 @@
+fn main() {
+    let x = (0, 2);
+
+    match x {
+        (0, ref y) | (y, 0) => {} //~ ERROR E0409
+                                  //~| ERROR E0308
+        _ => ()
+    }
+}
diff --git a/src/test/ui/mismatched_types/E0409.stderr b/src/test/ui/mismatched_types/E0409.stderr
new file mode 100644
index 0000000..93115bf
--- /dev/null
+++ b/src/test/ui/mismatched_types/E0409.stderr
@@ -0,0 +1,21 @@
+error[E0409]: variable `y` is bound in inconsistent ways within the same match arm
+  --> $DIR/E0409.rs:5:23
+   |
+LL |         (0, ref y) | (y, 0) => {}
+   |                 -     ^ bound in different ways
+   |                 |
+   |                 first binding
+
+error[E0308]: mismatched types
+  --> $DIR/E0409.rs:5:23
+   |
+LL |         (0, ref y) | (y, 0) => {}
+   |                       ^ expected &{integer}, found integer
+   |
+   = note: expected type `&{integer}`
+              found type `{integer}`
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0308, E0409.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/mismatched_types/E0631.rs b/src/test/ui/mismatched_types/E0631.rs
new file mode 100644
index 0000000..a293946
--- /dev/null
+++ b/src/test/ui/mismatched_types/E0631.rs
@@ -0,0 +1,11 @@
+#![feature(unboxed_closures)]
+
+fn foo<F: Fn(usize)>(_: F) {}
+fn bar<F: Fn<usize>>(_: F) {}
+fn main() {
+    fn f(_: u64) {}
+    foo(|_: isize| {}); //~ ERROR type mismatch
+    bar(|_: isize| {}); //~ ERROR type mismatch
+    foo(f); //~ ERROR type mismatch
+    bar(f); //~ ERROR type mismatch
+}
diff --git a/src/test/ui/mismatched_types/E0631.stderr b/src/test/ui/mismatched_types/E0631.stderr
new file mode 100644
index 0000000..f2bc6e1
--- /dev/null
+++ b/src/test/ui/mismatched_types/E0631.stderr
@@ -0,0 +1,61 @@
+error[E0631]: type mismatch in closure arguments
+  --> $DIR/E0631.rs:7:5
+   |
+LL |     foo(|_: isize| {});
+   |     ^^^ ---------- found signature of `fn(isize) -> _`
+   |     |
+   |     expected signature of `fn(usize) -> _`
+   |
+note: required by `foo`
+  --> $DIR/E0631.rs:3:1
+   |
+LL | fn foo<F: Fn(usize)>(_: F) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0631]: type mismatch in closure arguments
+  --> $DIR/E0631.rs:8:5
+   |
+LL |     bar(|_: isize| {});
+   |     ^^^ ---------- found signature of `fn(isize) -> _`
+   |     |
+   |     expected signature of `fn(usize) -> _`
+   |
+note: required by `bar`
+  --> $DIR/E0631.rs:4:1
+   |
+LL | fn bar<F: Fn<usize>>(_: F) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0631]: type mismatch in function arguments
+  --> $DIR/E0631.rs:9:5
+   |
+LL |     fn f(_: u64) {}
+   |     ------------ found signature of `fn(u64) -> _`
+...
+LL |     foo(f);
+   |     ^^^ expected signature of `fn(usize) -> _`
+   |
+note: required by `foo`
+  --> $DIR/E0631.rs:3:1
+   |
+LL | fn foo<F: Fn(usize)>(_: F) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0631]: type mismatch in function arguments
+  --> $DIR/E0631.rs:10:5
+   |
+LL |     fn f(_: u64) {}
+   |     ------------ found signature of `fn(u64) -> _`
+...
+LL |     bar(f);
+   |     ^^^ expected signature of `fn(usize) -> _`
+   |
+note: required by `bar`
+  --> $DIR/E0631.rs:4:1
+   |
+LL | fn bar<F: Fn<usize>>(_: F) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0631`.
diff --git a/src/test/ui/mismatched_types/abridged.rs b/src/test/ui/mismatched_types/abridged.rs
new file mode 100644
index 0000000..41ab6d4
--- /dev/null
+++ b/src/test/ui/mismatched_types/abridged.rs
@@ -0,0 +1,53 @@
+enum Bar {
+    Qux,
+    Zar,
+}
+
+struct Foo {
+    bar: usize,
+}
+
+struct X<T1, T2> {
+    x: T1,
+    y: T2,
+}
+
+fn a() -> Foo {
+    Some(Foo { bar: 1 }) //~ ERROR mismatched types
+}
+
+fn a2() -> Foo {
+    Ok(Foo { bar: 1}) //~ ERROR mismatched types
+}
+
+fn b() -> Option<Foo> {
+    Foo { bar: 1 } //~ ERROR mismatched types
+}
+
+fn c() -> Result<Foo, Bar> {
+    Foo { bar: 1 } //~ ERROR mismatched types
+}
+
+fn d() -> X<X<String, String>, String> {
+    let x = X {
+        x: X {
+            x: "".to_string(),
+            y: 2,
+        },
+        y: 3,
+    };
+    x //~ ERROR mismatched types
+}
+
+fn e() -> X<X<String, String>, String> {
+    let x = X {
+        x: X {
+            x: "".to_string(),
+            y: 2,
+        },
+        y: "".to_string(),
+    };
+    x //~ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/src/test/ui/mismatched_types/abridged.stderr b/src/test/ui/mismatched_types/abridged.stderr
new file mode 100644
index 0000000..b7f3b3d
--- /dev/null
+++ b/src/test/ui/mismatched_types/abridged.stderr
@@ -0,0 +1,71 @@
+error[E0308]: mismatched types
+  --> $DIR/abridged.rs:16:5
+   |
+LL | fn a() -> Foo {
+   |           --- expected `Foo` because of return type
+LL |     Some(Foo { bar: 1 })
+   |     ^^^^^^^^^^^^^^^^^^^^ expected struct `Foo`, found enum `std::option::Option`
+   |
+   = note: expected type `Foo`
+              found type `std::option::Option<Foo>`
+
+error[E0308]: mismatched types
+  --> $DIR/abridged.rs:20:5
+   |
+LL | fn a2() -> Foo {
+   |            --- expected `Foo` because of return type
+LL |     Ok(Foo { bar: 1})
+   |     ^^^^^^^^^^^^^^^^^ expected struct `Foo`, found enum `std::result::Result`
+   |
+   = note: expected type `Foo`
+              found type `std::result::Result<Foo, _>`
+
+error[E0308]: mismatched types
+  --> $DIR/abridged.rs:24:5
+   |
+LL | fn b() -> Option<Foo> {
+   |           ----------- expected `std::option::Option<Foo>` because of return type
+LL |     Foo { bar: 1 }
+   |     ^^^^^^^^^^^^^^ expected enum `std::option::Option`, found struct `Foo`
+   |
+   = note: expected type `std::option::Option<Foo>`
+              found type `Foo`
+
+error[E0308]: mismatched types
+  --> $DIR/abridged.rs:28:5
+   |
+LL | fn c() -> Result<Foo, Bar> {
+   |           ---------------- expected `std::result::Result<Foo, Bar>` because of return type
+LL |     Foo { bar: 1 }
+   |     ^^^^^^^^^^^^^^ expected enum `std::result::Result`, found struct `Foo`
+   |
+   = note: expected type `std::result::Result<Foo, Bar>`
+              found type `Foo`
+
+error[E0308]: mismatched types
+  --> $DIR/abridged.rs:39:5
+   |
+LL | fn d() -> X<X<String, String>, String> {
+   |           ---------------------------- expected `X<X<std::string::String, std::string::String>, std::string::String>` because of return type
+...
+LL |     x
+   |     ^ expected struct `std::string::String`, found integer
+   |
+   = note: expected type `X<X<_, std::string::String>, std::string::String>`
+              found type `X<X<_, {integer}>, {integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/abridged.rs:50:5
+   |
+LL | fn e() -> X<X<String, String>, String> {
+   |           ---------------------------- expected `X<X<std::string::String, std::string::String>, std::string::String>` because of return type
+...
+LL |     x
+   |     ^ expected struct `std::string::String`, found integer
+   |
+   = note: expected type `X<X<_, std::string::String>, _>`
+              found type `X<X<_, {integer}>, _>`
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/mismatched_types/binops.rs b/src/test/ui/mismatched_types/binops.rs
new file mode 100644
index 0000000..621599d
--- /dev/null
+++ b/src/test/ui/mismatched_types/binops.rs
@@ -0,0 +1,8 @@
+fn main() {
+    1 + Some(1); //~ ERROR cannot add `std::option::Option<{integer}>` to `{integer}`
+    2 as usize - Some(1); //~ ERROR cannot subtract `std::option::Option<{integer}>` from `usize`
+    3 * (); //~ ERROR cannot multiply `()` to `{integer}`
+    4 / ""; //~ ERROR cannot divide `{integer}` by `&str`
+    5 < String::new(); //~ ERROR can't compare `{integer}` with `std::string::String`
+    6 == Ok(1); //~ ERROR can't compare `{integer}` with `std::result::Result<{integer}, _>`
+}
diff --git a/src/test/ui/mismatched_types/binops.stderr b/src/test/ui/mismatched_types/binops.stderr
new file mode 100644
index 0000000..9dda44a
--- /dev/null
+++ b/src/test/ui/mismatched_types/binops.stderr
@@ -0,0 +1,51 @@
+error[E0277]: cannot add `std::option::Option<{integer}>` to `{integer}`
+  --> $DIR/binops.rs:2:7
+   |
+LL |     1 + Some(1);
+   |       ^ no implementation for `{integer} + std::option::Option<{integer}>`
+   |
+   = help: the trait `std::ops::Add<std::option::Option<{integer}>>` is not implemented for `{integer}`
+
+error[E0277]: cannot subtract `std::option::Option<{integer}>` from `usize`
+  --> $DIR/binops.rs:3:16
+   |
+LL |     2 as usize - Some(1);
+   |                ^ no implementation for `usize - std::option::Option<{integer}>`
+   |
+   = help: the trait `std::ops::Sub<std::option::Option<{integer}>>` is not implemented for `usize`
+
+error[E0277]: cannot multiply `()` to `{integer}`
+  --> $DIR/binops.rs:4:7
+   |
+LL |     3 * ();
+   |       ^ no implementation for `{integer} * ()`
+   |
+   = help: the trait `std::ops::Mul<()>` is not implemented for `{integer}`
+
+error[E0277]: cannot divide `{integer}` by `&str`
+  --> $DIR/binops.rs:5:7
+   |
+LL |     4 / "";
+   |       ^ no implementation for `{integer} / &str`
+   |
+   = help: the trait `std::ops::Div<&str>` is not implemented for `{integer}`
+
+error[E0277]: can't compare `{integer}` with `std::string::String`
+  --> $DIR/binops.rs:6:7
+   |
+LL |     5 < String::new();
+   |       ^ no implementation for `{integer} < std::string::String` and `{integer} > std::string::String`
+   |
+   = help: the trait `std::cmp::PartialOrd<std::string::String>` is not implemented for `{integer}`
+
+error[E0277]: can't compare `{integer}` with `std::result::Result<{integer}, _>`
+  --> $DIR/binops.rs:7:7
+   |
+LL |     6 == Ok(1);
+   |       ^^ no implementation for `{integer} == std::result::Result<{integer}, _>`
+   |
+   = help: the trait `std::cmp::PartialEq<std::result::Result<{integer}, _>>` is not implemented for `{integer}`
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/mismatched_types/cast-rfc0401.rs b/src/test/ui/mismatched_types/cast-rfc0401.rs
new file mode 100644
index 0000000..a5e03a1
--- /dev/null
+++ b/src/test/ui/mismatched_types/cast-rfc0401.rs
@@ -0,0 +1,72 @@
+fn illegal_cast<U:?Sized,V:?Sized>(u: *const U) -> *const V
+{
+    u as *const V //~ ERROR is invalid
+}
+
+fn illegal_cast_2<U:?Sized>(u: *const U) -> *const str
+{
+    u as *const str //~ ERROR is invalid
+}
+
+trait Foo { fn foo(&self) {} }
+impl<T> Foo for T {}
+
+trait Bar { fn foo(&self) {} }
+impl<T> Bar for T {}
+
+enum E {
+    A, B
+}
+
+fn main()
+{
+    let f: f32 = 1.2;
+    let v = 0 as *const u8;
+    let fat_v : *const [u8] = unsafe { &*(0 as *const [u8; 1])};
+    let fat_sv : *const [i8] = unsafe { &*(0 as *const [i8; 1])};
+    let foo: &Foo = &f;
+
+    let _ = v as &u8; //~ ERROR non-primitive cast
+    let _ = v as E; //~ ERROR non-primitive cast
+    let _ = v as fn(); //~ ERROR non-primitive cast
+    let _ = v as (u32,); //~ ERROR non-primitive cast
+    let _ = Some(&v) as *const u8; //~ ERROR non-primitive cast
+
+    let _ = v as f32; //~ ERROR is invalid
+    let _ = main as f64; //~ ERROR is invalid
+    let _ = &v as usize; //~ ERROR is invalid
+    let _ = f as *const u8; //~ ERROR is invalid
+    let _ = 3_i32 as bool; //~ ERROR cannot cast
+    let _ = E::A as bool; //~ ERROR cannot cast
+    let _ = 0x61u32 as char; //~ ERROR can be cast as
+
+    let _ = false as f32; //~ ERROR is invalid
+    let _ = E::A as f32; //~ ERROR is invalid
+    let _ = 'a' as f32; //~ ERROR is invalid
+
+    let _ = false as *const u8; //~ ERROR is invalid
+    let _ = E::A as *const u8; //~ ERROR is invalid
+    let _ = 'a' as *const u8; //~ ERROR is invalid
+
+    let _ = 42usize as *const [u8]; //~ ERROR is invalid
+    let _ = v as *const [u8]; //~ ERROR cannot cast
+    let _ = fat_v as *const Foo; //~ ERROR the size for values of type
+    let _ = foo as *const str; //~ ERROR is invalid
+    let _ = foo as *mut str; //~ ERROR is invalid
+    let _ = main as *mut str; //~ ERROR is invalid
+    let _ = &f as *mut f32; //~ ERROR is invalid
+    let _ = &f as *const f64; //~ ERROR is invalid
+    let _ = fat_sv as usize; //~ ERROR is invalid
+
+    let a : *const str = "hello";
+    let _ = a as *const Foo; //~ ERROR the size for values of type
+
+    // check no error cascade
+    let _ = main.f as *const u32; //~ ERROR no field
+
+    let cf: *const Foo = &0;
+    let _ = cf as *const [u16]; //~ ERROR is invalid
+    let _ = cf as *const Bar; //~ ERROR is invalid
+
+    vec![0.0].iter().map(|s| s as f32).collect::<Vec<f32>>(); //~ ERROR is invalid
+}
diff --git a/src/test/ui/mismatched_types/cast-rfc0401.stderr b/src/test/ui/mismatched_types/cast-rfc0401.stderr
new file mode 100644
index 0000000..c30f0ac
--- /dev/null
+++ b/src/test/ui/mismatched_types/cast-rfc0401.stderr
@@ -0,0 +1,247 @@
+error[E0606]: casting `*const U` as `*const V` is invalid
+  --> $DIR/cast-rfc0401.rs:3:5
+   |
+LL |     u as *const V
+   |     ^^^^^^^^^^^^^
+   |
+   = note: vtable kinds may not match
+
+error[E0606]: casting `*const U` as `*const str` is invalid
+  --> $DIR/cast-rfc0401.rs:8:5
+   |
+LL |     u as *const str
+   |     ^^^^^^^^^^^^^^^
+   |
+   = note: vtable kinds may not match
+
+error[E0609]: no field `f` on type `fn() {main}`
+  --> $DIR/cast-rfc0401.rs:65:18
+   |
+LL |     let _ = main.f as *const u32;
+   |                  ^
+
+error[E0605]: non-primitive cast: `*const u8` as `&u8`
+  --> $DIR/cast-rfc0401.rs:29:13
+   |
+LL |     let _ = v as &u8;
+   |             ^^^^^^^^
+   |
+   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+
+error[E0605]: non-primitive cast: `*const u8` as `E`
+  --> $DIR/cast-rfc0401.rs:30:13
+   |
+LL |     let _ = v as E;
+   |             ^^^^^^
+   |
+   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+
+error[E0605]: non-primitive cast: `*const u8` as `fn()`
+  --> $DIR/cast-rfc0401.rs:31:13
+   |
+LL |     let _ = v as fn();
+   |             ^^^^^^^^^
+   |
+   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+
+error[E0605]: non-primitive cast: `*const u8` as `(u32,)`
+  --> $DIR/cast-rfc0401.rs:32:13
+   |
+LL |     let _ = v as (u32,);
+   |             ^^^^^^^^^^^
+   |
+   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+
+error[E0605]: non-primitive cast: `std::option::Option<&*const u8>` as `*const u8`
+  --> $DIR/cast-rfc0401.rs:33:13
+   |
+LL |     let _ = Some(&v) as *const u8;
+   |             ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+
+error[E0606]: casting `*const u8` as `f32` is invalid
+  --> $DIR/cast-rfc0401.rs:35:13
+   |
+LL |     let _ = v as f32;
+   |             ^^^^^^^^
+
+error[E0606]: casting `fn() {main}` as `f64` is invalid
+  --> $DIR/cast-rfc0401.rs:36:13
+   |
+LL |     let _ = main as f64;
+   |             ^^^^^^^^^^^
+
+error[E0606]: casting `&*const u8` as `usize` is invalid
+  --> $DIR/cast-rfc0401.rs:37:13
+   |
+LL |     let _ = &v as usize;
+   |             ^^^^^^^^^^^
+   |
+   = help: cast through a raw pointer first
+
+error[E0606]: casting `f32` as `*const u8` is invalid
+  --> $DIR/cast-rfc0401.rs:38:13
+   |
+LL |     let _ = f as *const u8;
+   |             ^^^^^^^^^^^^^^
+
+error[E0054]: cannot cast as `bool`
+  --> $DIR/cast-rfc0401.rs:39:13
+   |
+LL |     let _ = 3_i32 as bool;
+   |             ^^^^^^^^^^^^^ help: compare with zero instead: `3_i32 != 0`
+
+error[E0054]: cannot cast as `bool`
+  --> $DIR/cast-rfc0401.rs:40:13
+   |
+LL |     let _ = E::A as bool;
+   |             ^^^^^^^^^^^^ unsupported cast
+
+error[E0604]: only `u8` can be cast as `char`, not `u32`
+  --> $DIR/cast-rfc0401.rs:41:13
+   |
+LL |     let _ = 0x61u32 as char;
+   |             ^^^^^^^^^^^^^^^
+
+error[E0606]: casting `bool` as `f32` is invalid
+  --> $DIR/cast-rfc0401.rs:43:13
+   |
+LL |     let _ = false as f32;
+   |             ^^^^^^^^^^^^
+   |
+   = help: cast through an integer first
+
+error[E0606]: casting `E` as `f32` is invalid
+  --> $DIR/cast-rfc0401.rs:44:13
+   |
+LL |     let _ = E::A as f32;
+   |             ^^^^^^^^^^^
+   |
+   = help: cast through an integer first
+
+error[E0606]: casting `char` as `f32` is invalid
+  --> $DIR/cast-rfc0401.rs:45:13
+   |
+LL |     let _ = 'a' as f32;
+   |             ^^^^^^^^^^
+   |
+   = help: cast through an integer first
+
+error[E0606]: casting `bool` as `*const u8` is invalid
+  --> $DIR/cast-rfc0401.rs:47:13
+   |
+LL |     let _ = false as *const u8;
+   |             ^^^^^^^^^^^^^^^^^^
+
+error[E0606]: casting `E` as `*const u8` is invalid
+  --> $DIR/cast-rfc0401.rs:48:13
+   |
+LL |     let _ = E::A as *const u8;
+   |             ^^^^^^^^^^^^^^^^^
+
+error[E0606]: casting `char` as `*const u8` is invalid
+  --> $DIR/cast-rfc0401.rs:49:13
+   |
+LL |     let _ = 'a' as *const u8;
+   |             ^^^^^^^^^^^^^^^^
+
+error[E0606]: casting `usize` as `*const [u8]` is invalid
+  --> $DIR/cast-rfc0401.rs:51:13
+   |
+LL |     let _ = 42usize as *const [u8];
+   |             ^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0607]: cannot cast thin pointer `*const u8` to fat pointer `*const [u8]`
+  --> $DIR/cast-rfc0401.rs:52:13
+   |
+LL |     let _ = v as *const [u8];
+   |             ^^^^^^^^^^^^^^^^
+
+error[E0606]: casting `&dyn Foo` as `*const str` is invalid
+  --> $DIR/cast-rfc0401.rs:54:13
+   |
+LL |     let _ = foo as *const str;
+   |             ^^^^^^^^^^^^^^^^^
+
+error[E0606]: casting `&dyn Foo` as `*mut str` is invalid
+  --> $DIR/cast-rfc0401.rs:55:13
+   |
+LL |     let _ = foo as *mut str;
+   |             ^^^^^^^^^^^^^^^
+
+error[E0606]: casting `fn() {main}` as `*mut str` is invalid
+  --> $DIR/cast-rfc0401.rs:56:13
+   |
+LL |     let _ = main as *mut str;
+   |             ^^^^^^^^^^^^^^^^
+
+error[E0606]: casting `&f32` as `*mut f32` is invalid
+  --> $DIR/cast-rfc0401.rs:57:13
+   |
+LL |     let _ = &f as *mut f32;
+   |             ^^^^^^^^^^^^^^
+
+error[E0606]: casting `&f32` as `*const f64` is invalid
+  --> $DIR/cast-rfc0401.rs:58:13
+   |
+LL |     let _ = &f as *const f64;
+   |             ^^^^^^^^^^^^^^^^
+
+error[E0606]: casting `*const [i8]` as `usize` is invalid
+  --> $DIR/cast-rfc0401.rs:59:13
+   |
+LL |     let _ = fat_sv as usize;
+   |             ^^^^^^^^^^^^^^^
+   |
+   = help: cast through a thin pointer first
+
+error[E0606]: casting `*const dyn Foo` as `*const [u16]` is invalid
+  --> $DIR/cast-rfc0401.rs:68:13
+   |
+LL |     let _ = cf as *const [u16];
+   |             ^^^^^^^^^^^^^^^^^^
+   |
+   = note: vtable kinds may not match
+
+error[E0606]: casting `*const dyn Foo` as `*const dyn Bar` is invalid
+  --> $DIR/cast-rfc0401.rs:69:13
+   |
+LL |     let _ = cf as *const Bar;
+   |             ^^^^^^^^^^^^^^^^
+   |
+   = note: vtable kinds may not match
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/cast-rfc0401.rs:53:13
+   |
+LL |     let _ = fat_v as *const Foo;
+   |             ^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `[u8]`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: required for the cast to the object type `dyn Foo`
+
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+  --> $DIR/cast-rfc0401.rs:62:13
+   |
+LL |     let _ = a as *const Foo;
+   |             ^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `str`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: required for the cast to the object type `dyn Foo`
+
+error[E0606]: casting `&{float}` as `f32` is invalid
+  --> $DIR/cast-rfc0401.rs:71:30
+   |
+LL |     vec![0.0].iter().map(|s| s as f32).collect::<Vec<f32>>();
+   |                              -^^^^^^^
+   |                              |
+   |                              cannot cast `&{float}` as `f32`
+   |                              help: dereference the expression: `*s`
+
+error: aborting due to 34 previous errors
+
+Some errors occurred: E0054, E0277, E0604, E0605, E0606, E0607, E0609.
+For more information about an error, try `rustc --explain E0054`.
diff --git a/src/test/ui/mismatched_types/closure-arg-count-expected-type-issue-47244.fixed b/src/test/ui/mismatched_types/closure-arg-count-expected-type-issue-47244.fixed
new file mode 100644
index 0000000..efba054
--- /dev/null
+++ b/src/test/ui/mismatched_types/closure-arg-count-expected-type-issue-47244.fixed
@@ -0,0 +1,20 @@
+// Regression test for #47244: in this specific scenario, when the
+// expected type indicated 1 argument but the closure takes two, we
+// would (early on) create type variables for the type of `b`. If the
+// user then attempts to invoke a method on `b`, we would get an error
+// saying that the type of `b` must be known, which was not very
+// helpful.
+
+// run-rustfix
+
+use std::collections::HashMap;
+
+fn main() {
+    let mut m = HashMap::new();
+    m.insert("foo", "bar");
+
+    let _n = m.iter().map(|(_, b)| {
+        //~^ ERROR closure is expected to take a single 2-tuple
+        b.to_string()
+    });
+}
diff --git a/src/test/ui/mismatched_types/closure-arg-count-expected-type-issue-47244.rs b/src/test/ui/mismatched_types/closure-arg-count-expected-type-issue-47244.rs
new file mode 100644
index 0000000..3ddb93d
--- /dev/null
+++ b/src/test/ui/mismatched_types/closure-arg-count-expected-type-issue-47244.rs
@@ -0,0 +1,20 @@
+// Regression test for #47244: in this specific scenario, when the
+// expected type indicated 1 argument but the closure takes two, we
+// would (early on) create type variables for the type of `b`. If the
+// user then attempts to invoke a method on `b`, we would get an error
+// saying that the type of `b` must be known, which was not very
+// helpful.
+
+// run-rustfix
+
+use std::collections::HashMap;
+
+fn main() {
+    let mut m = HashMap::new();
+    m.insert("foo", "bar");
+
+    let _n = m.iter().map(|_, b| {
+        //~^ ERROR closure is expected to take a single 2-tuple
+        b.to_string()
+    });
+}
diff --git a/src/test/ui/mismatched_types/closure-arg-count-expected-type-issue-47244.stderr b/src/test/ui/mismatched_types/closure-arg-count-expected-type-issue-47244.stderr
new file mode 100644
index 0000000..00a4f9d
--- /dev/null
+++ b/src/test/ui/mismatched_types/closure-arg-count-expected-type-issue-47244.stderr
@@ -0,0 +1,15 @@
+error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 2 distinct arguments
+  --> $DIR/closure-arg-count-expected-type-issue-47244.rs:16:23
+   |
+LL |     let _n = m.iter().map(|_, b| {
+   |                       ^^^ ------ takes 2 distinct arguments
+   |                       |
+   |                       expected closure that takes a single 2-tuple as argument
+help: change the closure to accept a tuple instead of individual arguments
+   |
+LL |     let _n = m.iter().map(|(_, b)| {
+   |                           ^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0593`.
diff --git a/src/test/ui/mismatched_types/closure-arg-count.rs b/src/test/ui/mismatched_types/closure-arg-count.rs
new file mode 100644
index 0000000..e817631
--- /dev/null
+++ b/src/test/ui/mismatched_types/closure-arg-count.rs
@@ -0,0 +1,43 @@
+#![feature(unboxed_closures)]
+
+fn f<F: Fn<usize>>(_: F) {}
+fn main() {
+    [1, 2, 3].sort_by(|| panic!());
+    //~^ ERROR closure is expected to take
+    [1, 2, 3].sort_by(|tuple| panic!());
+    //~^ ERROR closure is expected to take
+    [1, 2, 3].sort_by(|(tuple, tuple2)| panic!());
+    //~^ ERROR closure is expected to take
+    [1, 2, 3].sort_by(|(tuple, tuple2): (usize, _)| panic!());
+    //~^ ERROR closure is expected to take
+    f(|| panic!());
+    //~^ ERROR closure is expected to take
+    f(  move    || panic!());
+    //~^ ERROR closure is expected to take
+
+    let _it = vec![1, 2, 3].into_iter().enumerate().map(|i, x| i);
+    //~^ ERROR closure is expected to take
+    let _it = vec![1, 2, 3].into_iter().enumerate().map(|i: usize, x| i);
+    //~^ ERROR closure is expected to take
+    let _it = vec![1, 2, 3].into_iter().enumerate().map(|i, x, y| i);
+    //~^ ERROR closure is expected to take
+    let _it = vec![1, 2, 3].into_iter().enumerate().map(foo);
+    //~^ ERROR function is expected to take
+    let bar = |i, x, y| i;
+    let _it = vec![1, 2, 3].into_iter().enumerate().map(bar);
+    //~^ ERROR closure is expected to take
+    let _it = vec![1, 2, 3].into_iter().enumerate().map(qux);
+    //~^ ERROR function is expected to take
+
+    let _it = vec![1, 2, 3].into_iter().map(usize::checked_add);
+    //~^ ERROR function is expected to take
+
+    call(Foo);
+    //~^ ERROR function is expected to take
+}
+
+fn foo() {}
+fn qux(x: usize, y: usize) {}
+
+fn call<F, R>(_: F) where F: FnOnce() -> R {}
+struct Foo(u8);
diff --git a/src/test/ui/mismatched_types/closure-arg-count.stderr b/src/test/ui/mismatched_types/closure-arg-count.stderr
new file mode 100644
index 0000000..25d5d25
--- /dev/null
+++ b/src/test/ui/mismatched_types/closure-arg-count.stderr
@@ -0,0 +1,162 @@
+error[E0593]: closure is expected to take 2 arguments, but it takes 0 arguments
+  --> $DIR/closure-arg-count.rs:5:15
+   |
+LL |     [1, 2, 3].sort_by(|| panic!());
+   |               ^^^^^^^ -- takes 0 arguments
+   |               |
+   |               expected closure that takes 2 arguments
+help: consider changing the closure to take and ignore the expected arguments
+   |
+LL |     [1, 2, 3].sort_by(|_, _| panic!());
+   |                       ^^^^^^
+
+error[E0593]: closure is expected to take 2 arguments, but it takes 1 argument
+  --> $DIR/closure-arg-count.rs:7:15
+   |
+LL |     [1, 2, 3].sort_by(|tuple| panic!());
+   |               ^^^^^^^ ------- takes 1 argument
+   |               |
+   |               expected closure that takes 2 arguments
+
+error[E0593]: closure is expected to take 2 distinct arguments, but it takes a single 2-tuple as argument
+  --> $DIR/closure-arg-count.rs:9:15
+   |
+LL |     [1, 2, 3].sort_by(|(tuple, tuple2)| panic!());
+   |               ^^^^^^^ ----------------- takes a single 2-tuple as argument
+   |               |
+   |               expected closure that takes 2 distinct arguments
+help: change the closure to take multiple arguments instead of a single tuple
+   |
+LL |     [1, 2, 3].sort_by(|tuple, tuple2| panic!());
+   |                       ^^^^^^^^^^^^^^^
+
+error[E0593]: closure is expected to take 2 distinct arguments, but it takes a single 2-tuple as argument
+  --> $DIR/closure-arg-count.rs:11:15
+   |
+LL |     [1, 2, 3].sort_by(|(tuple, tuple2): (usize, _)| panic!());
+   |               ^^^^^^^ ----------------------------- takes a single 2-tuple as argument
+   |               |
+   |               expected closure that takes 2 distinct arguments
+help: change the closure to take multiple arguments instead of a single tuple
+   |
+LL |     [1, 2, 3].sort_by(|tuple, tuple2| panic!());
+   |                       ^^^^^^^^^^^^^^^
+
+error[E0593]: closure is expected to take 1 argument, but it takes 0 arguments
+  --> $DIR/closure-arg-count.rs:13:5
+   |
+LL |     f(|| panic!());
+   |     ^ -- takes 0 arguments
+   |     |
+   |     expected closure that takes 1 argument
+   |
+note: required by `f`
+  --> $DIR/closure-arg-count.rs:3:1
+   |
+LL | fn f<F: Fn<usize>>(_: F) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+help: consider changing the closure to take and ignore the expected argument
+   |
+LL |     f(|_| panic!());
+   |       ^^^
+
+error[E0593]: closure is expected to take 1 argument, but it takes 0 arguments
+  --> $DIR/closure-arg-count.rs:15:5
+   |
+LL |     f(  move    || panic!());
+   |     ^   ---------- takes 0 arguments
+   |     |
+   |     expected closure that takes 1 argument
+   |
+note: required by `f`
+  --> $DIR/closure-arg-count.rs:3:1
+   |
+LL | fn f<F: Fn<usize>>(_: F) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+help: consider changing the closure to take and ignore the expected argument
+   |
+LL |     f(  move    |_| panic!());
+   |                 ^^^
+
+error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 2 distinct arguments
+  --> $DIR/closure-arg-count.rs:18:53
+   |
+LL |     let _it = vec![1, 2, 3].into_iter().enumerate().map(|i, x| i);
+   |                                                     ^^^ ------ takes 2 distinct arguments
+   |                                                     |
+   |                                                     expected closure that takes a single 2-tuple as argument
+help: change the closure to accept a tuple instead of individual arguments
+   |
+LL |     let _it = vec![1, 2, 3].into_iter().enumerate().map(|(i, x)| i);
+   |                                                         ^^^^^^^^
+
+error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 2 distinct arguments
+  --> $DIR/closure-arg-count.rs:20:53
+   |
+LL |     let _it = vec![1, 2, 3].into_iter().enumerate().map(|i: usize, x| i);
+   |                                                     ^^^ ------------- takes 2 distinct arguments
+   |                                                     |
+   |                                                     expected closure that takes a single 2-tuple as argument
+help: change the closure to accept a tuple instead of individual arguments
+   |
+LL |     let _it = vec![1, 2, 3].into_iter().enumerate().map(|(i, x)| i);
+   |                                                         ^^^^^^^^
+
+error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 3 distinct arguments
+  --> $DIR/closure-arg-count.rs:22:53
+   |
+LL |     let _it = vec![1, 2, 3].into_iter().enumerate().map(|i, x, y| i);
+   |                                                     ^^^ --------- takes 3 distinct arguments
+   |                                                     |
+   |                                                     expected closure that takes a single 2-tuple as argument
+
+error[E0593]: function is expected to take a single 2-tuple as argument, but it takes 0 arguments
+  --> $DIR/closure-arg-count.rs:24:53
+   |
+LL |     let _it = vec![1, 2, 3].into_iter().enumerate().map(foo);
+   |                                                     ^^^ expected function that takes a single 2-tuple as argument
+...
+LL | fn foo() {}
+   | -------- takes 0 arguments
+
+error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 3 distinct arguments
+  --> $DIR/closure-arg-count.rs:27:53
+   |
+LL |     let bar = |i, x, y| i;
+   |               --------- takes 3 distinct arguments
+LL |     let _it = vec![1, 2, 3].into_iter().enumerate().map(bar);
+   |                                                     ^^^ expected closure that takes a single 2-tuple as argument
+
+error[E0593]: function is expected to take a single 2-tuple as argument, but it takes 2 distinct arguments
+  --> $DIR/closure-arg-count.rs:29:53
+   |
+LL |     let _it = vec![1, 2, 3].into_iter().enumerate().map(qux);
+   |                                                     ^^^ expected function that takes a single 2-tuple as argument
+...
+LL | fn qux(x: usize, y: usize) {}
+   | -------------------------- takes 2 distinct arguments
+
+error[E0593]: function is expected to take 1 argument, but it takes 2 arguments
+  --> $DIR/closure-arg-count.rs:32:41
+   |
+LL |     let _it = vec![1, 2, 3].into_iter().map(usize::checked_add);
+   |                                         ^^^ expected function that takes 1 argument
+
+error[E0593]: function is expected to take 0 arguments, but it takes 1 argument
+  --> $DIR/closure-arg-count.rs:35:5
+   |
+LL |     call(Foo);
+   |     ^^^^ expected function that takes 0 arguments
+...
+LL | struct Foo(u8);
+   | --------------- takes 1 argument
+   |
+note: required by `call`
+  --> $DIR/closure-arg-count.rs:42:1
+   |
+LL | fn call<F, R>(_: F) where F: FnOnce() -> R {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 14 previous errors
+
+For more information about this error, try `rustc --explain E0593`.
diff --git a/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs b/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs
new file mode 100644
index 0000000..521bd36
--- /dev/null
+++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs
@@ -0,0 +1,12 @@
+fn main() {
+    let a = [(1u32, 2u32)];
+    a.iter().map(|_: (u32, u32)| 45); //~ ERROR type mismatch
+    a.iter().map(|_: &(u16, u16)| 45); //~ ERROR type mismatch
+    a.iter().map(|_: (u16, u16)| 45); //~ ERROR type mismatch
+}
+
+fn baz<F: Fn(*mut &u32)>(_: F) {}
+fn _test<'a>(f: fn(*mut &'a u32)) {
+    baz(f); //~ ERROR type mismatch
+     //~| ERROR type mismatch
+}
diff --git a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr
new file mode 100644
index 0000000..cf392e1
--- /dev/null
+++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr
@@ -0,0 +1,55 @@
+error[E0631]: type mismatch in closure arguments
+  --> $DIR/closure-arg-type-mismatch.rs:3:14
+   |
+LL |     a.iter().map(|_: (u32, u32)| 45);
+   |              ^^^ ------------------ found signature of `fn((u32, u32)) -> _`
+   |              |
+   |              expected signature of `fn(&(u32, u32)) -> _`
+
+error[E0631]: type mismatch in closure arguments
+  --> $DIR/closure-arg-type-mismatch.rs:4:14
+   |
+LL |     a.iter().map(|_: &(u16, u16)| 45);
+   |              ^^^ ------------------- found signature of `for<'r> fn(&'r (u16, u16)) -> _`
+   |              |
+   |              expected signature of `fn(&(u32, u32)) -> _`
+
+error[E0631]: type mismatch in closure arguments
+  --> $DIR/closure-arg-type-mismatch.rs:5:14
+   |
+LL |     a.iter().map(|_: (u16, u16)| 45);
+   |              ^^^ ------------------ found signature of `fn((u16, u16)) -> _`
+   |              |
+   |              expected signature of `fn(&(u32, u32)) -> _`
+
+error[E0631]: type mismatch in function arguments
+  --> $DIR/closure-arg-type-mismatch.rs:10:5
+   |
+LL |     baz(f);
+   |     ^^^
+   |     |
+   |     expected signature of `for<'r> fn(*mut &'r u32) -> _`
+   |     found signature of `fn(*mut &'a u32) -> _`
+   |
+note: required by `baz`
+  --> $DIR/closure-arg-type-mismatch.rs:8:1
+   |
+LL | fn baz<F: Fn(*mut &u32)>(_: F) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0271]: type mismatch resolving `for<'r> <fn(*mut &'a u32) as std::ops::FnOnce<(*mut &'r u32,)>>::Output == ()`
+  --> $DIR/closure-arg-type-mismatch.rs:10:5
+   |
+LL |     baz(f);
+   |     ^^^ expected bound lifetime parameter, found concrete lifetime
+   |
+note: required by `baz`
+  --> $DIR/closure-arg-type-mismatch.rs:8:1
+   |
+LL | fn baz<F: Fn(*mut &u32)>(_: F) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
+
+Some errors occurred: E0271, E0631.
+For more information about an error, try `rustc --explain E0271`.
diff --git a/src/test/ui/mismatched_types/closure-mismatch.rs b/src/test/ui/mismatched_types/closure-mismatch.rs
new file mode 100644
index 0000000..40a4641
--- /dev/null
+++ b/src/test/ui/mismatched_types/closure-mismatch.rs
@@ -0,0 +1,10 @@
+trait Foo {}
+
+impl<T: Fn(&())> Foo for T {}
+
+fn baz<T: Foo>(_: T) {}
+
+fn main() {
+    baz(|_| ()); //~ ERROR type mismatch
+    //~^ ERROR type mismatch
+}
diff --git a/src/test/ui/mismatched_types/closure-mismatch.stderr b/src/test/ui/mismatched_types/closure-mismatch.stderr
new file mode 100644
index 0000000..6fbc922
--- /dev/null
+++ b/src/test/ui/mismatched_types/closure-mismatch.stderr
@@ -0,0 +1,32 @@
+error[E0271]: type mismatch resolving `for<'r> <[closure@$DIR/closure-mismatch.rs:8:9: 8:15] as std::ops::FnOnce<(&'r (),)>>::Output == ()`
+  --> $DIR/closure-mismatch.rs:8:5
+   |
+LL |     baz(|_| ());
+   |     ^^^ expected bound lifetime parameter, found concrete lifetime
+   |
+   = note: required because of the requirements on the impl of `Foo` for `[closure@$DIR/closure-mismatch.rs:8:9: 8:15]`
+note: required by `baz`
+  --> $DIR/closure-mismatch.rs:5:1
+   |
+LL | fn baz<T: Foo>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error[E0631]: type mismatch in closure arguments
+  --> $DIR/closure-mismatch.rs:8:5
+   |
+LL |     baz(|_| ());
+   |     ^^^ ------ found signature of `fn(_) -> _`
+   |     |
+   |     expected signature of `for<'r> fn(&'r ()) -> _`
+   |
+   = note: required because of the requirements on the impl of `Foo` for `[closure@$DIR/closure-mismatch.rs:8:9: 8:15]`
+note: required by `baz`
+  --> $DIR/closure-mismatch.rs:5:1
+   |
+LL | fn baz<T: Foo>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0271, E0631.
+For more information about an error, try `rustc --explain E0271`.
diff --git a/src/test/ui/mismatched_types/const-fn-in-trait.rs b/src/test/ui/mismatched_types/const-fn-in-trait.rs
new file mode 100644
index 0000000..7fcbd7e
--- /dev/null
+++ b/src/test/ui/mismatched_types/const-fn-in-trait.rs
@@ -0,0 +1,15 @@
+// rustc-env:RUST_NEW_ERROR_FORMAT
+
+#![feature(const_fn)]
+
+trait Foo {
+    fn f() -> u32;
+    const fn g(); //~ ERROR cannot be declared const
+}
+
+impl Foo for u32 {
+    const fn f() -> u32 { 22 } //~ ERROR cannot be declared const
+    fn g() {}
+}
+
+fn main() { }
diff --git a/src/test/ui/mismatched_types/const-fn-in-trait.stderr b/src/test/ui/mismatched_types/const-fn-in-trait.stderr
new file mode 100644
index 0000000..ec1f36b
--- /dev/null
+++ b/src/test/ui/mismatched_types/const-fn-in-trait.stderr
@@ -0,0 +1,15 @@
+error[E0379]: trait fns cannot be declared const
+  --> $DIR/const-fn-in-trait.rs:7:5
+   |
+LL |     const fn g();
+   |     ^^^^^ trait fns cannot be const
+
+error[E0379]: trait fns cannot be declared const
+  --> $DIR/const-fn-in-trait.rs:11:5
+   |
+LL |     const fn f() -> u32 { 22 }
+   |     ^^^^^ trait fns cannot be const
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0379`.
diff --git a/src/test/ui/mismatched_types/fn-variance-1.rs b/src/test/ui/mismatched_types/fn-variance-1.rs
new file mode 100644
index 0000000..b8a6c9a
--- /dev/null
+++ b/src/test/ui/mismatched_types/fn-variance-1.rs
@@ -0,0 +1,17 @@
+fn takes_imm(x: &isize) { }
+
+fn takes_mut(x: &mut isize) { }
+
+fn apply<T, F>(t: T, f: F) where F: FnOnce(T) {
+    f(t)
+}
+
+fn main() {
+    apply(&3, takes_imm);
+    apply(&3, takes_mut);
+    //~^ ERROR type mismatch
+
+    apply(&mut 3, takes_mut);
+    apply(&mut 3, takes_imm);
+    //~^ ERROR type mismatch
+}
diff --git a/src/test/ui/mismatched_types/fn-variance-1.stderr b/src/test/ui/mismatched_types/fn-variance-1.stderr
new file mode 100644
index 0000000..0fb1a53
--- /dev/null
+++ b/src/test/ui/mismatched_types/fn-variance-1.stderr
@@ -0,0 +1,33 @@
+error[E0631]: type mismatch in function arguments
+  --> $DIR/fn-variance-1.rs:11:5
+   |
+LL | fn takes_mut(x: &mut isize) { }
+   | --------------------------- found signature of `for<'r> fn(&'r mut isize) -> _`
+...
+LL |     apply(&3, takes_mut);
+   |     ^^^^^ expected signature of `fn(&{integer}) -> _`
+   |
+note: required by `apply`
+  --> $DIR/fn-variance-1.rs:5:1
+   |
+LL | fn apply<T, F>(t: T, f: F) where F: FnOnce(T) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0631]: type mismatch in function arguments
+  --> $DIR/fn-variance-1.rs:15:5
+   |
+LL | fn takes_imm(x: &isize) { }
+   | ----------------------- found signature of `for<'r> fn(&'r isize) -> _`
+...
+LL |     apply(&mut 3, takes_imm);
+   |     ^^^^^ expected signature of `fn(&mut {integer}) -> _`
+   |
+note: required by `apply`
+  --> $DIR/fn-variance-1.rs:5:1
+   |
+LL | fn apply<T, F>(t: T, f: F) where F: FnOnce(T) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0631`.
diff --git a/src/test/ui/mismatched_types/for-loop-has-unit-body.rs b/src/test/ui/mismatched_types/for-loop-has-unit-body.rs
new file mode 100644
index 0000000..a9433d7
--- /dev/null
+++ b/src/test/ui/mismatched_types/for-loop-has-unit-body.rs
@@ -0,0 +1,5 @@
+fn main() {
+    for x in 0..3 {
+        x //~ ERROR mismatched types
+    }
+}
diff --git a/src/test/ui/mismatched_types/for-loop-has-unit-body.stderr b/src/test/ui/mismatched_types/for-loop-has-unit-body.stderr
new file mode 100644
index 0000000..3c8ba80
--- /dev/null
+++ b/src/test/ui/mismatched_types/for-loop-has-unit-body.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/for-loop-has-unit-body.rs:3:9
+   |
+LL |         x
+   |         ^ expected (), found integer
+   |
+   = note: expected type `()`
+              found type `{integer}`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/mismatched_types/issue-19109.rs b/src/test/ui/mismatched_types/issue-19109.rs
new file mode 100644
index 0000000..030b7a4
--- /dev/null
+++ b/src/test/ui/mismatched_types/issue-19109.rs
@@ -0,0 +1,8 @@
+trait Trait { }
+
+fn function(t: &mut Trait) {
+    t as *mut Trait
+ //~^ ERROR: mismatched types
+}
+
+fn main() { }
diff --git a/src/test/ui/mismatched_types/issue-19109.stderr b/src/test/ui/mismatched_types/issue-19109.stderr
new file mode 100644
index 0000000..db2d484
--- /dev/null
+++ b/src/test/ui/mismatched_types/issue-19109.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-19109.rs:4:5
+   |
+LL | fn function(t: &mut Trait) {
+   |                            - help: try adding a return type: `-> *mut dyn Trait`
+LL |     t as *mut Trait
+   |     ^^^^^^^^^^^^^^^ expected (), found *-ptr
+   |
+   = note: expected type `()`
+              found type `*mut dyn Trait`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/mismatched_types/issue-26480.rs b/src/test/ui/mismatched_types/issue-26480.rs
new file mode 100644
index 0000000..d140e12
--- /dev/null
+++ b/src/test/ui/mismatched_types/issue-26480.rs
@@ -0,0 +1,29 @@
+extern {
+    fn write(fildes: i32, buf: *const i8, nbyte: u64) -> i64;
+}
+
+#[inline(always)]
+fn size_of<T>(_: T) -> usize {
+    ::std::mem::size_of::<T>()
+}
+
+macro_rules! write {
+    ($arr:expr) => {{
+        #[allow(non_upper_case_globals)]
+        const stdout: i32 = 1;
+        unsafe {
+            write(stdout, $arr.as_ptr() as *const i8,
+                  $arr.len() * size_of($arr[0])); //~ ERROR mismatched types
+        }
+    }}
+}
+
+macro_rules! cast {
+    ($x:expr) => ($x as ()) //~ ERROR non-primitive cast
+}
+
+fn main() {
+    let hello = ['H', 'e', 'y'];
+    write!(hello);
+    cast!(2);
+}
diff --git a/src/test/ui/mismatched_types/issue-26480.stderr b/src/test/ui/mismatched_types/issue-26480.stderr
new file mode 100644
index 0000000..ef7a8d3
--- /dev/null
+++ b/src/test/ui/mismatched_types/issue-26480.stderr
@@ -0,0 +1,24 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-26480.rs:16:19
+   |
+LL |                   $arr.len() * size_of($arr[0]));
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected u64, found usize
+...
+LL |     write!(hello);
+   |     -------------- in this macro invocation
+
+error[E0605]: non-primitive cast: `{integer}` as `()`
+  --> $DIR/issue-26480.rs:22:19
+   |
+LL |     ($x:expr) => ($x as ())
+   |                   ^^^^^^^^
+...
+LL |     cast!(2);
+   |     --------- in this macro invocation
+   |
+   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0308, E0605.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/mismatched_types/issue-35030.rs b/src/test/ui/mismatched_types/issue-35030.rs
new file mode 100644
index 0000000..91ea7ea
--- /dev/null
+++ b/src/test/ui/mismatched_types/issue-35030.rs
@@ -0,0 +1,15 @@
+#![allow(non_camel_case_types)]
+
+trait Parser<T> {
+    fn parse(text: &str) -> Option<T>;
+}
+
+impl<bool> Parser<bool> for bool {
+    fn parse(text: &str) -> Option<bool> {
+        Some(true) //~ ERROR mismatched types
+    }
+}
+
+fn main() {
+    println!("{}", bool::parse("ok").unwrap_or(false));
+}
diff --git a/src/test/ui/mismatched_types/issue-35030.stderr b/src/test/ui/mismatched_types/issue-35030.stderr
new file mode 100644
index 0000000..f030670
--- /dev/null
+++ b/src/test/ui/mismatched_types/issue-35030.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-35030.rs:9:14
+   |
+LL |         Some(true)
+   |              ^^^^ expected type parameter, found bool
+   |
+   = note: expected type `bool` (type parameter)
+              found type `bool` (bool)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/mismatched_types/issue-36053-2.rs b/src/test/ui/mismatched_types/issue-36053-2.rs
new file mode 100644
index 0000000..9edfebc
--- /dev/null
+++ b/src/test/ui/mismatched_types/issue-36053-2.rs
@@ -0,0 +1,11 @@
+// Regression test for #36053. ICE was caused due to obligations
+// being added to a special, dedicated fulfillment cx during
+// a probe.
+
+use std::iter::once;
+fn main() {
+    once::<&str>("str").fuse().filter(|a: &str| true).count();
+    //~^ ERROR no method named `count`
+    //~| ERROR type mismatch in closure arguments
+    //~| ERROR type mismatch in closure arguments
+}
diff --git a/src/test/ui/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr
new file mode 100644
index 0000000..c5c67e6
--- /dev/null
+++ b/src/test/ui/mismatched_types/issue-36053-2.stderr
@@ -0,0 +1,30 @@
+error[E0599]: no method named `count` found for type `std::iter::Filter<std::iter::Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]>` in the current scope
+  --> $DIR/issue-36053-2.rs:7:55
+   |
+LL |     once::<&str>("str").fuse().filter(|a: &str| true).count();
+   |                                                       ^^^^^
+   |
+   = note: the method `count` exists but the following trait bounds were not satisfied:
+           `&mut std::iter::Filter<std::iter::Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]> : std::iter::Iterator`
+           `std::iter::Filter<std::iter::Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]> : std::iter::Iterator`
+
+error[E0631]: type mismatch in closure arguments
+  --> $DIR/issue-36053-2.rs:7:32
+   |
+LL |     once::<&str>("str").fuse().filter(|a: &str| true).count();
+   |                                ^^^^^^ -------------- found signature of `for<'r> fn(&'r str) -> _`
+   |                                |
+   |                                expected signature of `for<'r> fn(&'r &str) -> _`
+
+error[E0631]: type mismatch in closure arguments
+  --> $DIR/issue-36053-2.rs:7:32
+   |
+LL |     once::<&str>("str").fuse().filter(|a: &str| true).count();
+   |                                ^^^^^^ -------------- found signature of `for<'r> fn(&'r str) -> _`
+   |                                |
+   |                                expected signature of `fn(&&str) -> _`
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0599, E0631.
+For more information about an error, try `rustc --explain E0599`.
diff --git a/src/test/ui/mismatched_types/issue-38371.rs b/src/test/ui/mismatched_types/issue-38371.rs
new file mode 100644
index 0000000..d2cd2b8
--- /dev/null
+++ b/src/test/ui/mismatched_types/issue-38371.rs
@@ -0,0 +1,27 @@
+struct Foo {
+}
+
+fn foo(&foo: Foo) { //~ ERROR mismatched types
+}
+
+fn bar(foo: Foo) {
+}
+
+fn qux(foo: &Foo) {
+}
+
+fn zar(&foo: &Foo) {
+}
+
+// The somewhat unexpected help message in this case is courtesy of
+// match_default_bindings.
+fn agh(&&bar: &u32) { //~ ERROR mismatched types
+}
+
+fn bgh(&&bar: u32) { //~ ERROR mismatched types
+}
+
+fn ugh(&[bar]: &u32) { //~ ERROR expected an array or slice
+}
+
+fn main() {}
diff --git a/src/test/ui/mismatched_types/issue-38371.stderr b/src/test/ui/mismatched_types/issue-38371.stderr
new file mode 100644
index 0000000..d168692
--- /dev/null
+++ b/src/test/ui/mismatched_types/issue-38371.stderr
@@ -0,0 +1,39 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-38371.rs:4:8
+   |
+LL | fn foo(&foo: Foo) {
+   |        ^^^^ expected struct `Foo`, found reference
+   |
+   = note: expected type `Foo`
+              found type `&_`
+   = help: did you mean `foo: &Foo`?
+
+error[E0308]: mismatched types
+  --> $DIR/issue-38371.rs:18:9
+   |
+LL | fn agh(&&bar: &u32) {
+   |         ^^^^ expected u32, found reference
+   |
+   = note: expected type `u32`
+              found type `&_`
+   = help: did you mean `bar: &u32`?
+
+error[E0308]: mismatched types
+  --> $DIR/issue-38371.rs:21:8
+   |
+LL | fn bgh(&&bar: u32) {
+   |        ^^^^^ expected u32, found reference
+   |
+   = note: expected type `u32`
+              found type `&_`
+
+error[E0529]: expected an array or slice, found `u32`
+  --> $DIR/issue-38371.rs:24:9
+   |
+LL | fn ugh(&[bar]: &u32) {
+   |         ^^^^^ pattern cannot match with input type `u32`
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0308, E0529.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/mismatched_types/main.rs b/src/test/ui/mismatched_types/main.rs
new file mode 100644
index 0000000..16c18dd
--- /dev/null
+++ b/src/test/ui/mismatched_types/main.rs
@@ -0,0 +1,5 @@
+fn main() {
+    let x: u32 = ( //~ ERROR mismatched types
+    );
+}
+
diff --git a/src/test/ui/mismatched_types/main.stderr b/src/test/ui/mismatched_types/main.stderr
new file mode 100644
index 0000000..1d53cfd
--- /dev/null
+++ b/src/test/ui/mismatched_types/main.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/main.rs:2:18
+   |
+LL |       let x: u32 = (
+   |  __________________^
+LL | |     );
+   | |_____^ expected u32, found ()
+   |
+   = note: expected type `u32`
+              found type `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.rs b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.rs
new file mode 100644
index 0000000..83cea16
--- /dev/null
+++ b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.rs
@@ -0,0 +1,7 @@
+struct Foo;
+
+fn main() {
+    let a: Result<(), Foo> = Ok(());
+    a.unwrap();
+    //~^ ERROR no method named `unwrap` found for type `std::result::Result<(), Foo>`
+}
diff --git a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr
new file mode 100644
index 0000000..9721dc8
--- /dev/null
+++ b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr
@@ -0,0 +1,12 @@
+error[E0599]: no method named `unwrap` found for type `std::result::Result<(), Foo>` in the current scope
+  --> $DIR/method-help-unsatisfied-bound.rs:5:7
+   |
+LL |     a.unwrap();
+   |       ^^^^^^
+   |
+   = note: the method `unwrap` exists but the following trait bounds were not satisfied:
+           `Foo : std::fmt::Debug`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/mismatched_types/numeric-literal-cast.rs b/src/test/ui/mismatched_types/numeric-literal-cast.rs
new file mode 100644
index 0000000..74a2211
--- /dev/null
+++ b/src/test/ui/mismatched_types/numeric-literal-cast.rs
@@ -0,0 +1,13 @@
+fn foo(_: u16) {}
+fn foo1(_: f64) {}
+fn foo2(_: i32) {}
+
+fn main() {
+    foo(1u8);
+//~^ ERROR mismatched types
+    foo1(2f32);
+//~^ ERROR mismatched types
+    foo2(3i16);
+//~^ ERROR mismatched types
+}
+
diff --git a/src/test/ui/mismatched_types/numeric-literal-cast.stderr b/src/test/ui/mismatched_types/numeric-literal-cast.stderr
new file mode 100644
index 0000000..ec53f1f
--- /dev/null
+++ b/src/test/ui/mismatched_types/numeric-literal-cast.stderr
@@ -0,0 +1,33 @@
+error[E0308]: mismatched types
+  --> $DIR/numeric-literal-cast.rs:6:9
+   |
+LL |     foo(1u8);
+   |         ^^^ expected u16, found u8
+help: change the type of the numeric literal from `u8` to `u16`
+   |
+LL |     foo(1u16);
+   |         ^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-literal-cast.rs:8:10
+   |
+LL |     foo1(2f32);
+   |          ^^^^ expected f64, found f32
+help: change the type of the numeric literal from `f32` to `f64`
+   |
+LL |     foo1(2f64);
+   |          ^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-literal-cast.rs:10:10
+   |
+LL |     foo2(3i16);
+   |          ^^^^ expected i32, found i16
+help: change the type of the numeric literal from `i16` to `i32`
+   |
+LL |     foo2(3i32);
+   |          ^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/mismatched_types/overloaded-calls-bad.rs b/src/test/ui/mismatched_types/overloaded-calls-bad.rs
new file mode 100644
index 0000000..73e74a9
--- /dev/null
+++ b/src/test/ui/mismatched_types/overloaded-calls-bad.rs
@@ -0,0 +1,33 @@
+#![feature(fn_traits, unboxed_closures)]
+
+use std::ops::FnMut;
+
+struct S {
+    x: isize,
+    y: isize,
+}
+
+impl FnMut<(isize,)> for S {
+    extern "rust-call" fn call_mut(&mut self, (z,): (isize,)) -> isize {
+        self.x * self.y * z
+    }
+}
+
+impl FnOnce<(isize,)> for S {
+    type Output = isize;
+    extern "rust-call" fn call_once(mut self, (z,): (isize,)) -> isize {
+        self.call_mut((z,))
+    }
+}
+
+fn main() {
+    let mut s = S {
+        x: 3,
+        y: 3,
+    };
+    let ans = s("what");    //~ ERROR mismatched types
+    let ans = s();
+    //~^ ERROR this function takes 1 parameter but 0 parameters were supplied
+    let ans = s("burma", "shave");
+    //~^ ERROR this function takes 1 parameter but 2 parameters were supplied
+}
diff --git a/src/test/ui/mismatched_types/overloaded-calls-bad.stderr b/src/test/ui/mismatched_types/overloaded-calls-bad.stderr
new file mode 100644
index 0000000..3551e41
--- /dev/null
+++ b/src/test/ui/mismatched_types/overloaded-calls-bad.stderr
@@ -0,0 +1,25 @@
+error[E0308]: mismatched types
+  --> $DIR/overloaded-calls-bad.rs:28:17
+   |
+LL |     let ans = s("what");
+   |                 ^^^^^^ expected isize, found reference
+   |
+   = note: expected type `isize`
+              found type `&'static str`
+
+error[E0057]: this function takes 1 parameter but 0 parameters were supplied
+  --> $DIR/overloaded-calls-bad.rs:29:15
+   |
+LL |     let ans = s();
+   |               ^^^ expected 1 parameter
+
+error[E0057]: this function takes 1 parameter but 2 parameters were supplied
+  --> $DIR/overloaded-calls-bad.rs:31:15
+   |
+LL |     let ans = s("burma", "shave");
+   |               ^^^^^^^^^^^^^^^^^^^ expected 1 parameter
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0057, E0308.
+For more information about an error, try `rustc --explain E0057`.
diff --git a/src/test/ui/mismatched_types/recovered-block.rs b/src/test/ui/mismatched_types/recovered-block.rs
new file mode 100644
index 0000000..cb8ad80
--- /dev/null
+++ b/src/test/ui/mismatched_types/recovered-block.rs
@@ -0,0 +1,23 @@
+// ignore-cloudabi no std::env support
+
+use std::env;
+
+pub struct Foo {
+    text: String
+}
+
+pub fn foo() -> Foo {
+    let args: Vec<String> = env::args().collect();
+    let text = args[1].clone();
+
+    pub Foo { text }
+}
+//~^^ ERROR missing `struct` for struct definition
+
+pub fn bar() -> Foo {
+    fn
+    Foo { text: "".to_string() }
+}
+//~^^ ERROR expected one of `(` or `<`, found `{`
+
+fn main() {}
diff --git a/src/test/ui/mismatched_types/recovered-block.stderr b/src/test/ui/mismatched_types/recovered-block.stderr
new file mode 100644
index 0000000..7834750
--- /dev/null
+++ b/src/test/ui/mismatched_types/recovered-block.stderr
@@ -0,0 +1,18 @@
+error: missing `struct` for struct definition
+  --> $DIR/recovered-block.rs:13:8
+   |
+LL |     pub Foo { text }
+   |        ^
+help: add `struct` here to parse `Foo` as a public struct
+   |
+LL |     pub struct Foo { text }
+   |         ^^^^^^
+
+error: expected one of `(` or `<`, found `{`
+  --> $DIR/recovered-block.rs:19:9
+   |
+LL |     Foo { text: "".to_string() }
+   |         ^ expected one of `(` or `<` here
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/mismatched_types/trait-bounds-cant-coerce.rs b/src/test/ui/mismatched_types/trait-bounds-cant-coerce.rs
new file mode 100644
index 0000000..be5fab8
--- /dev/null
+++ b/src/test/ui/mismatched_types/trait-bounds-cant-coerce.rs
@@ -0,0 +1,16 @@
+trait Foo {
+    fn dummy(&self) { }
+}
+
+fn a(_x: Box<Foo+Send>) {
+}
+
+fn c(x: Box<Foo+Sync+Send>) {
+    a(x);
+}
+
+fn d(x: Box<Foo>) {
+    a(x); //~ ERROR mismatched types [E0308]
+}
+
+fn main() { }
diff --git a/src/test/ui/mismatched_types/trait-bounds-cant-coerce.stderr b/src/test/ui/mismatched_types/trait-bounds-cant-coerce.stderr
new file mode 100644
index 0000000..6475cce
--- /dev/null
+++ b/src/test/ui/mismatched_types/trait-bounds-cant-coerce.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/trait-bounds-cant-coerce.rs:13:7
+   |
+LL |     a(x);
+   |       ^ expected trait `Foo + std::marker::Send`, found trait `Foo`
+   |
+   = note: expected type `std::boxed::Box<(dyn Foo + std::marker::Send + 'static)>`
+              found type `std::boxed::Box<(dyn Foo + 'static)>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/mismatched_types/trait-impl-fn-incompatibility.rs b/src/test/ui/mismatched_types/trait-impl-fn-incompatibility.rs
new file mode 100644
index 0000000..3547272e
--- /dev/null
+++ b/src/test/ui/mismatched_types/trait-impl-fn-incompatibility.rs
@@ -0,0 +1,17 @@
+// rustc-env:RUST_NEW_ERROR_FORMAT
+
+trait Foo {
+    fn foo(x: u16);
+    fn bar(&mut self, bar: &mut Bar);
+}
+
+struct Bar;
+
+impl Foo for Bar {
+    fn foo(x: i16) { } //~ ERROR incompatible type
+    fn bar(&mut self, bar: &Bar) { } //~ ERROR incompatible type
+}
+
+fn main() {
+}
+
diff --git a/src/test/ui/mismatched_types/trait-impl-fn-incompatibility.stderr b/src/test/ui/mismatched_types/trait-impl-fn-incompatibility.stderr
new file mode 100644
index 0000000..8ea3567
--- /dev/null
+++ b/src/test/ui/mismatched_types/trait-impl-fn-incompatibility.stderr
@@ -0,0 +1,31 @@
+error[E0053]: method `foo` has an incompatible type for trait
+  --> $DIR/trait-impl-fn-incompatibility.rs:11:15
+   |
+LL |     fn foo(x: u16);
+   |               --- type in trait
+...
+LL |     fn foo(x: i16) { }
+   |               ^^^ expected u16, found i16
+   |
+   = note: expected type `fn(u16)`
+              found type `fn(i16)`
+
+error[E0053]: method `bar` has an incompatible type for trait
+  --> $DIR/trait-impl-fn-incompatibility.rs:12:28
+   |
+LL |     fn bar(&mut self, bar: &mut Bar);
+   |                            -------- type in trait
+...
+LL |     fn bar(&mut self, bar: &Bar) { }
+   |                            ^^^^ types differ in mutability
+   |
+   = note: expected type `fn(&mut Bar, &mut Bar)`
+              found type `fn(&mut Bar, &Bar)`
+help: consider change the type to match the mutability in trait
+   |
+LL |     fn bar(&mut self, bar: &mut Bar) { }
+   |                            ^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0053`.
diff --git a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs
new file mode 100644
index 0000000..88bea97
--- /dev/null
+++ b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs
@@ -0,0 +1,19 @@
+#![feature(unboxed_closures)]
+
+use std::ops::FnMut;
+
+fn to_fn_mut<A,F:FnMut<A>>(f: F) -> F { f }
+
+fn call_it<F:FnMut(isize,isize)->isize>(y: isize, mut f: F) -> isize {
+//~^ NOTE required by `call_it`
+    f(2, y)
+}
+
+pub fn main() {
+    let f = to_fn_mut(|x: usize, y: isize| -> isize { (x as isize) + y });
+    //~^ NOTE found signature of `fn(usize, isize) -> _`
+    let z = call_it(3, f);
+    //~^ ERROR type mismatch
+    //~| NOTE expected signature of `fn(isize, isize) -> _`
+    println!("{}", z);
+}
diff --git a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr
new file mode 100644
index 0000000..ad0eefa
--- /dev/null
+++ b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr
@@ -0,0 +1,18 @@
+error[E0631]: type mismatch in closure arguments
+  --> $DIR/unboxed-closures-vtable-mismatch.rs:15:13
+   |
+LL |     let f = to_fn_mut(|x: usize, y: isize| -> isize { (x as isize) + y });
+   |                       ----------------------------- found signature of `fn(usize, isize) -> _`
+LL |
+LL |     let z = call_it(3, f);
+   |             ^^^^^^^ expected signature of `fn(isize, isize) -> _`
+   |
+note: required by `call_it`
+  --> $DIR/unboxed-closures-vtable-mismatch.rs:7:1
+   |
+LL | fn call_it<F:FnMut(isize,isize)->isize>(y: isize, mut f: F) -> isize {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0631`.
diff --git a/src/test/ui/missing/auxiliary/two_macros.rs b/src/test/ui/missing/auxiliary/two_macros.rs
new file mode 100644
index 0000000..2330c75
--- /dev/null
+++ b/src/test/ui/missing/auxiliary/two_macros.rs
@@ -0,0 +1,5 @@
+#[macro_export]
+macro_rules! macro_one { () => ("one") }
+
+#[macro_export]
+macro_rules! macro_two { () => ("two") }
diff --git a/src/test/ui/missing/missing-alloc_error_handler.rs b/src/test/ui/missing/missing-alloc_error_handler.rs
new file mode 100644
index 0000000..1a9e868
--- /dev/null
+++ b/src/test/ui/missing/missing-alloc_error_handler.rs
@@ -0,0 +1,23 @@
+// compile-flags: -C panic=abort
+// no-prefer-dynamic
+
+#![no_std]
+#![crate_type = "staticlib"]
+#![feature(panic_handler, alloc_error_handler, alloc)]
+
+#[panic_handler]
+fn panic(_: &core::panic::PanicInfo) -> ! {
+    loop {}
+}
+
+extern crate alloc;
+
+#[global_allocator]
+static A: MyAlloc = MyAlloc;
+
+struct MyAlloc;
+
+unsafe impl core::alloc::GlobalAlloc for MyAlloc {
+    unsafe fn alloc(&self, _: core::alloc::Layout) -> *mut u8 { 0 as _ }
+    unsafe fn dealloc(&self, _: *mut u8, _: core::alloc::Layout) {}
+}
diff --git a/src/test/ui/missing/missing-alloc_error_handler.stderr b/src/test/ui/missing/missing-alloc_error_handler.stderr
new file mode 100644
index 0000000..5489b2c
--- /dev/null
+++ b/src/test/ui/missing/missing-alloc_error_handler.stderr
@@ -0,0 +1,4 @@
+error: `#[alloc_error_handler]` function required, but not found
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/missing/missing-allocator.rs b/src/test/ui/missing/missing-allocator.rs
new file mode 100644
index 0000000..dbb10d1
--- /dev/null
+++ b/src/test/ui/missing/missing-allocator.rs
@@ -0,0 +1,18 @@
+// compile-flags: -C panic=abort
+// no-prefer-dynamic
+
+#![no_std]
+#![crate_type = "staticlib"]
+#![feature(panic_handler, alloc_error_handler, alloc)]
+
+#[panic_handler]
+fn panic(_: &core::panic::PanicInfo) -> ! {
+    loop {}
+}
+
+#[alloc_error_handler]
+fn oom(_: core::alloc::Layout) -> ! {
+    loop {}
+}
+
+extern crate alloc;
diff --git a/src/test/ui/missing/missing-allocator.stderr b/src/test/ui/missing/missing-allocator.stderr
new file mode 100644
index 0000000..11e0085
--- /dev/null
+++ b/src/test/ui/missing/missing-allocator.stderr
@@ -0,0 +1,4 @@
+error: no global memory allocator found but one is required; link to std or add #[global_allocator] to a static item that implements the GlobalAlloc trait.
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/missing/missing-block-hint.rs b/src/test/ui/missing/missing-block-hint.rs
new file mode 100644
index 0000000..89db02a
--- /dev/null
+++ b/src/test/ui/missing/missing-block-hint.rs
@@ -0,0 +1,9 @@
+fn main() {
+    {
+        if (foo) => {} //~ ERROR expected `{`, found `=>`
+    }
+    {
+        if (foo)
+            bar; //~ ERROR expected `{`, found `bar`
+    }
+}
diff --git a/src/test/ui/missing/missing-block-hint.stderr b/src/test/ui/missing/missing-block-hint.stderr
new file mode 100644
index 0000000..ee86a32
--- /dev/null
+++ b/src/test/ui/missing/missing-block-hint.stderr
@@ -0,0 +1,21 @@
+error: expected `{`, found `=>`
+  --> $DIR/missing-block-hint.rs:3:18
+   |
+LL |         if (foo) => {}
+   |         --       ^^ expected `{`
+   |         |
+   |         this `if` statement has a condition, but no block
+
+error: expected `{`, found `bar`
+  --> $DIR/missing-block-hint.rs:7:13
+   |
+LL |         if (foo)
+   |         -- this `if` statement has a condition, but no block
+LL |             bar;
+   |             ^^^-
+   |             |
+   |             expected `{`
+   |             help: try placing this code inside a block: `{ bar; }`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/missing/missing-comma-in-match.fixed b/src/test/ui/missing/missing-comma-in-match.fixed
new file mode 100644
index 0000000..de1b950
--- /dev/null
+++ b/src/test/ui/missing/missing-comma-in-match.fixed
@@ -0,0 +1,11 @@
+// run-rustfix
+
+fn main() {
+    match &Some(3) {
+        &None => 1,
+        &Some(2) => { 3 }
+        //~^ ERROR expected one of `,`, `.`, `?`, `}`, or an operator, found `=>`
+        //~| NOTE expected one of `,`, `.`, `?`, `}`, or an operator here
+        _ => 2
+    };
+}
diff --git a/src/test/ui/missing/missing-comma-in-match.rs b/src/test/ui/missing/missing-comma-in-match.rs
new file mode 100644
index 0000000..d7d1615
--- /dev/null
+++ b/src/test/ui/missing/missing-comma-in-match.rs
@@ -0,0 +1,11 @@
+// run-rustfix
+
+fn main() {
+    match &Some(3) {
+        &None => 1
+        &Some(2) => { 3 }
+        //~^ ERROR expected one of `,`, `.`, `?`, `}`, or an operator, found `=>`
+        //~| NOTE expected one of `,`, `.`, `?`, `}`, or an operator here
+        _ => 2
+    };
+}
diff --git a/src/test/ui/missing/missing-comma-in-match.stderr b/src/test/ui/missing/missing-comma-in-match.stderr
new file mode 100644
index 0000000..ae46516
--- /dev/null
+++ b/src/test/ui/missing/missing-comma-in-match.stderr
@@ -0,0 +1,10 @@
+error: expected one of `,`, `.`, `?`, `}`, or an operator, found `=>`
+  --> $DIR/missing-comma-in-match.rs:6:18
+   |
+LL |         &None => 1
+   |                   - help: missing a comma here to end this `match` arm
+LL |         &Some(2) => { 3 }
+   |                  ^^ expected one of `,`, `.`, `?`, `}`, or an operator here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/missing/missing-derivable-attr.rs b/src/test/ui/missing/missing-derivable-attr.rs
new file mode 100644
index 0000000..58c94de
--- /dev/null
+++ b/src/test/ui/missing/missing-derivable-attr.rs
@@ -0,0 +1,16 @@
+trait MyEq {
+    fn eq(&self, other: &Self) -> bool;
+}
+
+struct A {
+    x: isize
+}
+
+impl MyEq for isize {
+    fn eq(&self, other: &isize) -> bool { *self == *other }
+}
+
+impl MyEq for A {}  //~ ERROR not all trait items implemented, missing: `eq`
+
+fn main() {
+}
diff --git a/src/test/ui/missing/missing-derivable-attr.stderr b/src/test/ui/missing/missing-derivable-attr.stderr
new file mode 100644
index 0000000..9b8c0c5
--- /dev/null
+++ b/src/test/ui/missing/missing-derivable-attr.stderr
@@ -0,0 +1,12 @@
+error[E0046]: not all trait items implemented, missing: `eq`
+  --> $DIR/missing-derivable-attr.rs:13:1
+   |
+LL |     fn eq(&self, other: &Self) -> bool;
+   |     ----------------------------------- `eq` from trait
+...
+LL | impl MyEq for A {}
+   | ^^^^^^^^^^^^^^^ missing `eq` in implementation
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0046`.
diff --git a/src/test/ui/missing/missing-fields-in-struct-pattern.rs b/src/test/ui/missing/missing-fields-in-struct-pattern.rs
new file mode 100644
index 0000000..24b6b55
--- /dev/null
+++ b/src/test/ui/missing/missing-fields-in-struct-pattern.rs
@@ -0,0 +1,9 @@
+struct S(usize, usize, usize, usize);
+
+fn main() {
+    if let S { a, b, c, d } = S(1, 2, 3, 4) {
+    //~^ ERROR struct `S` does not have fields named `a`, `b`, `c`, `d` [E0026]
+    //~| ERROR pattern does not mention fields `0`, `1`, `2`, `3` [E0027]
+        println!("hi");
+    }
+}
diff --git a/src/test/ui/missing/missing-fields-in-struct-pattern.stderr b/src/test/ui/missing/missing-fields-in-struct-pattern.stderr
new file mode 100644
index 0000000..5d88a5d
--- /dev/null
+++ b/src/test/ui/missing/missing-fields-in-struct-pattern.stderr
@@ -0,0 +1,18 @@
+error[E0026]: struct `S` does not have fields named `a`, `b`, `c`, `d`
+  --> $DIR/missing-fields-in-struct-pattern.rs:4:16
+   |
+LL |     if let S { a, b, c, d } = S(1, 2, 3, 4) {
+   |                ^  ^  ^  ^ struct `S` does not have these fields
+
+error[E0027]: pattern does not mention fields `0`, `1`, `2`, `3`
+  --> $DIR/missing-fields-in-struct-pattern.rs:4:12
+   |
+LL |     if let S { a, b, c, d } = S(1, 2, 3, 4) {
+   |            ^^^^^^^^^^^^^^^^ missing fields `0`, `1`, `2`, `3`
+   |
+   = note: trying to match a tuple variant with a struct variant pattern
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0026, E0027.
+For more information about an error, try `rustc --explain E0026`.
diff --git a/src/test/ui/missing/missing-items/auxiliary/m1.rs b/src/test/ui/missing/missing-items/auxiliary/m1.rs
new file mode 100644
index 0000000..7705066
--- /dev/null
+++ b/src/test/ui/missing/missing-items/auxiliary/m1.rs
@@ -0,0 +1,5 @@
+pub trait X {
+    const CONSTANT: u32;
+    type Type;
+    fn method(&self, s: String) -> Self::Type;
+}
diff --git a/src/test/ui/missing/missing-items/issue-40221.rs b/src/test/ui/missing/missing-items/issue-40221.rs
new file mode 100644
index 0000000..e1f7e97
--- /dev/null
+++ b/src/test/ui/missing/missing-items/issue-40221.rs
@@ -0,0 +1,16 @@
+enum P {
+    C(PC),
+}
+
+enum PC {
+    Q,
+    QA,
+}
+
+fn test(proto: P) {
+    match proto { //~ ERROR non-exhaustive patterns
+        P::C(PC::Q) => (),
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/missing/missing-items/issue-40221.stderr b/src/test/ui/missing/missing-items/issue-40221.stderr
new file mode 100644
index 0000000..8e5286f
--- /dev/null
+++ b/src/test/ui/missing/missing-items/issue-40221.stderr
@@ -0,0 +1,17 @@
+error[E0004]: non-exhaustive patterns: `C(QA)` not covered
+  --> $DIR/issue-40221.rs:11:11
+   |
+LL | / enum P {
+LL | |     C(PC),
+   | |     - not covered
+LL | | }
+   | |_- `P` defined here
+...
+LL |       match proto {
+   |             ^^^^^ pattern `C(QA)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/missing/missing-items/m2.rs b/src/test/ui/missing/missing-items/m2.rs
new file mode 100644
index 0000000..c2a6914
--- /dev/null
+++ b/src/test/ui/missing/missing-items/m2.rs
@@ -0,0 +1,12 @@
+// aux-build:m1.rs
+
+
+extern crate m1;
+
+struct X {
+}
+
+impl m1::X for X { //~ ERROR not all trait items implemented
+}
+
+fn main() {}
diff --git a/src/test/ui/missing/missing-items/m2.stderr b/src/test/ui/missing/missing-items/m2.stderr
new file mode 100644
index 0000000..d2dac4c
--- /dev/null
+++ b/src/test/ui/missing/missing-items/m2.stderr
@@ -0,0 +1,13 @@
+error[E0046]: not all trait items implemented, missing: `CONSTANT`, `Type`, `method`
+  --> $DIR/m2.rs:9:1
+   |
+LL | impl m1::X for X {
+   | ^^^^^^^^^^^^^^^^ missing `CONSTANT`, `Type`, `method` in implementation
+   |
+   = note: `CONSTANT` from trait: `const CONSTANT: u32;`
+   = note: `Type` from trait: `type Type;`
+   = note: `method` from trait: `fn(&Self, std::string::String) -> <Self as m1::X>::Type`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0046`.
diff --git a/src/test/ui/missing/missing-items/missing-type-parameter.rs b/src/test/ui/missing/missing-items/missing-type-parameter.rs
new file mode 100644
index 0000000..8a64053
--- /dev/null
+++ b/src/test/ui/missing/missing-items/missing-type-parameter.rs
@@ -0,0 +1,5 @@
+fn foo<X>() { }
+
+fn main() {
+    foo(); //~ ERROR type annotations needed
+}
diff --git a/src/test/ui/missing/missing-items/missing-type-parameter.stderr b/src/test/ui/missing/missing-items/missing-type-parameter.stderr
new file mode 100644
index 0000000..dbb467d
--- /dev/null
+++ b/src/test/ui/missing/missing-items/missing-type-parameter.stderr
@@ -0,0 +1,9 @@
+error[E0282]: type annotations needed
+  --> $DIR/missing-type-parameter.rs:4:5
+   |
+LL |     foo();
+   |     ^^^ cannot infer type for `X`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/missing/missing-macro-use.rs b/src/test/ui/missing/missing-macro-use.rs
new file mode 100644
index 0000000..dff4c94
--- /dev/null
+++ b/src/test/ui/missing/missing-macro-use.rs
@@ -0,0 +1,8 @@
+// aux-build:two_macros.rs
+
+extern crate two_macros;
+
+pub fn main() {
+    macro_two!();
+    //~^ ERROR cannot find macro `macro_two!` in this scope
+}
diff --git a/src/test/ui/missing/missing-macro-use.stderr b/src/test/ui/missing/missing-macro-use.stderr
new file mode 100644
index 0000000..01a7beb
--- /dev/null
+++ b/src/test/ui/missing/missing-macro-use.stderr
@@ -0,0 +1,8 @@
+error: cannot find macro `macro_two!` in this scope
+  --> $DIR/missing-macro-use.rs:6:5
+   |
+LL |     macro_two!();
+   |     ^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/missing/missing-main.rs b/src/test/ui/missing/missing-main.rs
new file mode 100644
index 0000000..6ad5445
--- /dev/null
+++ b/src/test/ui/missing/missing-main.rs
@@ -0,0 +1,2 @@
+// error-pattern: `main` function not found
+fn mian() { }
diff --git a/src/test/ui/missing/missing-main.stderr b/src/test/ui/missing/missing-main.stderr
new file mode 100644
index 0000000..34b03ad
--- /dev/null
+++ b/src/test/ui/missing/missing-main.stderr
@@ -0,0 +1,7 @@
+error[E0601]: `main` function not found in crate `missing_main`
+   |
+   = note: consider adding a `main` function to `$DIR/missing-main.rs`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0601`.
diff --git a/src/test/ui/missing/missing-return.rs b/src/test/ui/missing/missing-return.rs
new file mode 100644
index 0000000..6a17175
--- /dev/null
+++ b/src/test/ui/missing/missing-return.rs
@@ -0,0 +1,5 @@
+// error-pattern: return
+
+fn f() -> isize { }
+
+fn main() { f(); }
diff --git a/src/test/ui/missing/missing-return.stderr b/src/test/ui/missing/missing-return.stderr
new file mode 100644
index 0000000..42466e2
--- /dev/null
+++ b/src/test/ui/missing/missing-return.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/missing-return.rs:3:11
+   |
+LL | fn f() -> isize { }
+   |    -      ^^^^^ expected isize, found ()
+   |    |
+   |    this function's body doesn't return
+   |
+   = note: expected type `isize`
+              found type `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/missing/missing-semicolon-warning.rs b/src/test/ui/missing/missing-semicolon-warning.rs
new file mode 100644
index 0000000..11204af
--- /dev/null
+++ b/src/test/ui/missing/missing-semicolon-warning.rs
@@ -0,0 +1,12 @@
+// compile-pass
+#![allow(unused)]
+
+macro_rules! m {
+    ($($e1:expr),*; $($e2:expr),*) => {
+        $( let x = $e1 )*; //~ WARN expected `;`
+        $( println!("{}", $e2) )*; //~ WARN expected `;`
+    }
+}
+
+
+fn main() { m!(0, 0; 0, 0); }
diff --git a/src/test/ui/missing/missing-semicolon-warning.stderr b/src/test/ui/missing/missing-semicolon-warning.stderr
new file mode 100644
index 0000000..b3f3ebc
--- /dev/null
+++ b/src/test/ui/missing/missing-semicolon-warning.stderr
@@ -0,0 +1,22 @@
+warning: expected `;`, found keyword `let`
+  --> $DIR/missing-semicolon-warning.rs:6:12
+   |
+LL |         $( let x = $e1 )*;
+   |            ^^^
+...
+LL | fn main() { m!(0, 0; 0, 0); }
+   |             --------------- in this macro invocation
+   |
+   = note: This was erroneously allowed and will become a hard error in a future release
+
+warning: expected `;`, found `println`
+  --> $DIR/missing-semicolon-warning.rs:7:12
+   |
+LL |         $( println!("{}", $e2) )*;
+   |            ^^^^^^^
+...
+LL | fn main() { m!(0, 0; 0, 0); }
+   |             --------------- in this macro invocation
+   |
+   = note: This was erroneously allowed and will become a hard error in a future release
+
diff --git a/src/test/ui/missing/missing-stability.rs b/src/test/ui/missing/missing-stability.rs
new file mode 100644
index 0000000..469c22f
--- /dev/null
+++ b/src/test/ui/missing/missing-stability.rs
@@ -0,0 +1,24 @@
+// Checks that exported items without stability attributes cause an error
+
+#![crate_type="lib"]
+#![feature(staged_api)]
+
+#![stable(feature = "stable_test_feature", since = "1.0.0")]
+
+pub fn unmarked() {
+    //~^ ERROR function has missing stability attribute
+    ()
+}
+
+#[unstable(feature = "unstable_test_feature", issue = "0")]
+pub mod foo {
+    // #[unstable] is inherited
+    pub fn unmarked() {}
+}
+
+#[stable(feature = "stable_test_feature", since="1.0.0")]
+pub mod bar {
+    // #[stable] is not inherited
+    pub fn unmarked() {}
+    //~^ ERROR function has missing stability attribute
+}
diff --git a/src/test/ui/missing/missing-stability.stderr b/src/test/ui/missing/missing-stability.stderr
new file mode 100644
index 0000000..659f8c7
--- /dev/null
+++ b/src/test/ui/missing/missing-stability.stderr
@@ -0,0 +1,17 @@
+error: function has missing stability attribute
+  --> $DIR/missing-stability.rs:8:1
+   |
+LL | / pub fn unmarked() {
+LL | |
+LL | |     ()
+LL | | }
+   | |_^
+
+error: function has missing stability attribute
+  --> $DIR/missing-stability.rs:22:5
+   |
+LL |     pub fn unmarked() {}
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/missing_debug_impls.rs b/src/test/ui/missing_debug_impls.rs
new file mode 100644
index 0000000..ff919292
--- /dev/null
+++ b/src/test/ui/missing_debug_impls.rs
@@ -0,0 +1,38 @@
+// compile-flags: --crate-type lib
+#![deny(missing_debug_implementations)]
+#![allow(unused)]
+
+use std::fmt;
+
+pub enum A {} //~ ERROR type does not implement `fmt::Debug`
+
+#[derive(Debug)]
+pub enum B {}
+
+pub enum C {}
+
+impl fmt::Debug for C {
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+        Ok(())
+    }
+}
+
+pub struct Foo; //~ ERROR type does not implement `fmt::Debug`
+
+#[derive(Debug)]
+pub struct Bar;
+
+pub struct Baz;
+
+impl fmt::Debug for Baz {
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+        Ok(())
+    }
+}
+
+struct PrivateStruct;
+
+enum PrivateEnum {}
+
+#[derive(Debug)]
+struct GenericType<T>(T);
diff --git a/src/test/ui/missing_debug_impls.stderr b/src/test/ui/missing_debug_impls.stderr
new file mode 100644
index 0000000..bb8390a
--- /dev/null
+++ b/src/test/ui/missing_debug_impls.stderr
@@ -0,0 +1,20 @@
+error: type does not implement `fmt::Debug`; consider adding #[derive(Debug)] or a manual implementation
+  --> $DIR/missing_debug_impls.rs:7:1
+   |
+LL | pub enum A {}
+   | ^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/missing_debug_impls.rs:2:9
+   |
+LL | #![deny(missing_debug_implementations)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: type does not implement `fmt::Debug`; consider adding #[derive(Debug)] or a manual implementation
+  --> $DIR/missing_debug_impls.rs:20:1
+   |
+LL | pub struct Foo;
+   | ^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/missing_non_modrs_mod/foo.rs b/src/test/ui/missing_non_modrs_mod/foo.rs
new file mode 100644
index 0000000..4f41316
--- /dev/null
+++ b/src/test/ui/missing_non_modrs_mod/foo.rs
@@ -0,0 +1,4 @@
+//
+// ignore-test this is just a helper for the real test in this dir
+
+mod missing;
diff --git a/src/test/ui/missing_non_modrs_mod/foo_inline.rs b/src/test/ui/missing_non_modrs_mod/foo_inline.rs
new file mode 100644
index 0000000..df60629
--- /dev/null
+++ b/src/test/ui/missing_non_modrs_mod/foo_inline.rs
@@ -0,0 +1,5 @@
+// ignore-test this is just a helper for the real test in this dir
+
+mod inline {
+    mod missing;
+}
diff --git a/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod.rs b/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod.rs
new file mode 100644
index 0000000..4ff975a
--- /dev/null
+++ b/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod.rs
@@ -0,0 +1,2 @@
+mod foo;
+fn main() {}
diff --git a/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod.stderr b/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod.stderr
new file mode 100644
index 0000000..98b74e5
--- /dev/null
+++ b/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod.stderr
@@ -0,0 +1,11 @@
+error[E0583]: file not found for module `missing`
+  --> $DIR/foo.rs:4:5
+   |
+LL | mod missing;
+   |     ^^^^^^^
+   |
+   = help: name the file either foo/missing.rs or foo/missing/mod.rs inside the directory "$DIR"
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0583`.
diff --git a/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod_inline.rs b/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod_inline.rs
new file mode 100644
index 0000000..9ebb4f1
--- /dev/null
+++ b/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod_inline.rs
@@ -0,0 +1,2 @@
+mod foo_inline;
+fn main() {}
diff --git a/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod_inline.stderr b/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod_inline.stderr
new file mode 100644
index 0000000..457e8fc
--- /dev/null
+++ b/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod_inline.stderr
@@ -0,0 +1,11 @@
+error[E0583]: file not found for module `missing`
+  --> $DIR/foo_inline.rs:4:9
+   |
+LL |     mod missing;
+   |         ^^^^^^^
+   |
+   = help: name the file either missing.rs or missing/mod.rs inside the directory "$DIR/foo_inline/inline"
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0583`.
diff --git a/src/test/ui/mod-subitem-as-enum-variant.rs b/src/test/ui/mod-subitem-as-enum-variant.rs
new file mode 100644
index 0000000..cd4459a
--- /dev/null
+++ b/src/test/ui/mod-subitem-as-enum-variant.rs
@@ -0,0 +1,10 @@
+
+mod Mod {
+    pub struct FakeVariant<T>(pub T);
+}
+
+fn main() {
+    Mod::FakeVariant::<i32>(0);
+    Mod::<i32>::FakeVariant(0);
+    //~^ ERROR type arguments are not allowed for this type [E0109]
+}
diff --git a/src/test/ui/mod-subitem-as-enum-variant.stderr b/src/test/ui/mod-subitem-as-enum-variant.stderr
new file mode 100644
index 0000000..72eca58
--- /dev/null
+++ b/src/test/ui/mod-subitem-as-enum-variant.stderr
@@ -0,0 +1,9 @@
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/mod-subitem-as-enum-variant.rs:8:11
+   |
+LL |     Mod::<i32>::FakeVariant(0);
+   |           ^^^ type argument not allowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0109`.
diff --git a/src/test/ui/mod/mod_file_aux.rs b/src/test/ui/mod/mod_file_aux.rs
new file mode 100644
index 0000000..98f42c5
--- /dev/null
+++ b/src/test/ui/mod/mod_file_aux.rs
@@ -0,0 +1,3 @@
+// ignore-test Not a test. Used by other tests
+
+pub fn foo() -> isize { 10 }
diff --git a/src/test/ui/mod/mod_file_correct_spans.rs b/src/test/ui/mod/mod_file_correct_spans.rs
new file mode 100644
index 0000000..c42d2ea
--- /dev/null
+++ b/src/test/ui/mod/mod_file_correct_spans.rs
@@ -0,0 +1,8 @@
+// Testing that the source_map is maintained correctly when parsing mods from external files
+
+mod mod_file_aux;
+
+fn main() {
+    assert!(mod_file_aux::bar() == 10);
+    //~^ ERROR cannot find function `bar` in module `mod_file_aux`
+}
diff --git a/src/test/ui/mod/mod_file_correct_spans.stderr b/src/test/ui/mod/mod_file_correct_spans.stderr
new file mode 100644
index 0000000..7304475
--- /dev/null
+++ b/src/test/ui/mod/mod_file_correct_spans.stderr
@@ -0,0 +1,9 @@
+error[E0425]: cannot find function `bar` in module `mod_file_aux`
+  --> $DIR/mod_file_correct_spans.rs:6:27
+   |
+LL |     assert!(mod_file_aux::bar() == 10);
+   |                           ^^^ not found in `mod_file_aux`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/mod/mod_file_disambig.rs b/src/test/ui/mod/mod_file_disambig.rs
new file mode 100644
index 0000000..ef203ef
--- /dev/null
+++ b/src/test/ui/mod/mod_file_disambig.rs
@@ -0,0 +1,5 @@
+mod mod_file_disambig_aux; //~ ERROR file for module `mod_file_disambig_aux` found at both
+
+fn main() {
+    assert_eq!(mod_file_aux::bar(), 10);
+}
diff --git a/src/test/ui/mod/mod_file_disambig.stderr b/src/test/ui/mod/mod_file_disambig.stderr
new file mode 100644
index 0000000..2b77d86
--- /dev/null
+++ b/src/test/ui/mod/mod_file_disambig.stderr
@@ -0,0 +1,11 @@
+error[E0584]: file for module `mod_file_disambig_aux` found at both mod_file_disambig_aux.rs and mod_file_disambig_aux/mod.rs
+  --> $DIR/mod_file_disambig.rs:1:5
+   |
+LL | mod mod_file_disambig_aux;
+   |     ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: delete or rename one of them to remove the ambiguity
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0584`.
diff --git a/src/test/ui/mod/mod_file_disambig_aux.rs b/src/test/ui/mod/mod_file_disambig_aux.rs
new file mode 100644
index 0000000..3bf9609
--- /dev/null
+++ b/src/test/ui/mod/mod_file_disambig_aux.rs
@@ -0,0 +1 @@
+// ignore-test not a test. aux file
diff --git a/src/test/ui/mod/mod_file_disambig_aux/mod.rs b/src/test/ui/mod/mod_file_disambig_aux/mod.rs
new file mode 100644
index 0000000..3bf9609
--- /dev/null
+++ b/src/test/ui/mod/mod_file_disambig_aux/mod.rs
@@ -0,0 +1 @@
+// ignore-test not a test. aux file
diff --git a/src/test/ui/module-macro_use-arguments.rs b/src/test/ui/module-macro_use-arguments.rs
new file mode 100644
index 0000000..6627b48
--- /dev/null
+++ b/src/test/ui/module-macro_use-arguments.rs
@@ -0,0 +1,6 @@
+#[macro_use(foo, bar)] //~ ERROR arguments to macro_use are not allowed here
+mod foo {
+}
+
+fn main() {
+}
diff --git a/src/test/ui/module-macro_use-arguments.stderr b/src/test/ui/module-macro_use-arguments.stderr
new file mode 100644
index 0000000..2a75736
--- /dev/null
+++ b/src/test/ui/module-macro_use-arguments.stderr
@@ -0,0 +1,8 @@
+error: arguments to macro_use are not allowed here
+  --> $DIR/module-macro_use-arguments.rs:1:1
+   |
+LL | #[macro_use(foo, bar)]
+   | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/moves/move-guard-same-consts.nll.stderr b/src/test/ui/moves/move-guard-same-consts.nll.stderr
new file mode 100644
index 0000000..0945fbe
--- /dev/null
+++ b/src/test/ui/moves/move-guard-same-consts.nll.stderr
@@ -0,0 +1,14 @@
+error[E0382]: use of moved value: `x`
+  --> $DIR/move-guard-same-consts.rs:20:24
+   |
+LL |     let x: Box<_> = box 1;
+   |         - move occurs because `x` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
+...
+LL |         (1, 2) if take(x) => (),
+   |                        - value moved here
+LL |         (1, 2) if take(x) => (),
+   |                        ^ value used here after move
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/moves/move-guard-same-consts.rs b/src/test/ui/moves/move-guard-same-consts.rs
new file mode 100644
index 0000000..a2beb36
--- /dev/null
+++ b/src/test/ui/moves/move-guard-same-consts.rs
@@ -0,0 +1,25 @@
+// #47295: We used to have a hack of special-casing adjacent amtch
+// arms whose patterns were composed solely of constants to not have
+// them linked in the cfg.
+//
+// THis was broken for various reasons. In particular, that hack was
+// originally authored under the assunption that other checks
+// elsewhere would ensure that the two patterns did not overlap.  But
+// that assumption did not hold, at least not in the long run (namely,
+// overlapping patterns were turned into warnings rather than errors).
+
+#![feature(box_syntax)]
+
+fn main() {
+    let x: Box<_> = box 1;
+
+    let v = (1, 2);
+
+    match v {
+        (1, 2) if take(x) => (),
+        (1, 2) if take(x) => (), //~ ERROR use of moved value: `x`
+        _ => (),
+    }
+}
+
+fn take<T>(_: T) -> bool { false }
diff --git a/src/test/ui/moves/move-guard-same-consts.stderr b/src/test/ui/moves/move-guard-same-consts.stderr
new file mode 100644
index 0000000..65f6f12
--- /dev/null
+++ b/src/test/ui/moves/move-guard-same-consts.stderr
@@ -0,0 +1,13 @@
+error[E0382]: use of moved value: `x`
+  --> $DIR/move-guard-same-consts.rs:20:24
+   |
+LL |         (1, 2) if take(x) => (),
+   |                        - value moved here
+LL |         (1, 2) if take(x) => (),
+   |                        ^ value used here after move
+   |
+   = note: move occurs because `x` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/moves/move-in-guard-1.nll.stderr b/src/test/ui/moves/move-in-guard-1.nll.stderr
new file mode 100644
index 0000000..542fd16
--- /dev/null
+++ b/src/test/ui/moves/move-in-guard-1.nll.stderr
@@ -0,0 +1,14 @@
+error[E0382]: use of moved value: `x`
+  --> $DIR/move-in-guard-1.rs:10:24
+   |
+LL |     let x: Box<_> = box 1;
+   |         - move occurs because `x` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
+...
+LL |         (1, _) if take(x) => (),
+   |                        - value moved here
+LL |         (_, 2) if take(x) => (),
+   |                        ^ value used here after move
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/moves/move-in-guard-1.rs b/src/test/ui/moves/move-in-guard-1.rs
new file mode 100644
index 0000000..9c50782
--- /dev/null
+++ b/src/test/ui/moves/move-in-guard-1.rs
@@ -0,0 +1,15 @@
+#![feature(box_syntax)]
+
+pub fn main() {
+    let x: Box<_> = box 1;
+
+    let v = (1, 2);
+
+    match v {
+        (1, _) if take(x) => (),
+        (_, 2) if take(x) => (), //~ ERROR use of moved value: `x`
+        _ => (),
+    }
+}
+
+fn take<T>(_: T) -> bool { false }
diff --git a/src/test/ui/moves/move-in-guard-1.stderr b/src/test/ui/moves/move-in-guard-1.stderr
new file mode 100644
index 0000000..af49fa8
--- /dev/null
+++ b/src/test/ui/moves/move-in-guard-1.stderr
@@ -0,0 +1,13 @@
+error[E0382]: use of moved value: `x`
+  --> $DIR/move-in-guard-1.rs:10:24
+   |
+LL |         (1, _) if take(x) => (),
+   |                        - value moved here
+LL |         (_, 2) if take(x) => (),
+   |                        ^ value used here after move
+   |
+   = note: move occurs because `x` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/moves/move-in-guard-2.nll.stderr b/src/test/ui/moves/move-in-guard-2.nll.stderr
new file mode 100644
index 0000000..8bd4052
--- /dev/null
+++ b/src/test/ui/moves/move-in-guard-2.nll.stderr
@@ -0,0 +1,12 @@
+error[E0382]: use of moved value: `x`
+  --> $DIR/move-in-guard-2.rs:10:24
+   |
+LL |     let x: Box<_> = box 1;
+   |         - move occurs because `x` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
+...
+LL |         (_, 2) if take(x) => (),
+   |                        ^ value moved here, in previous iteration of loop
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/moves/move-in-guard-2.rs b/src/test/ui/moves/move-in-guard-2.rs
new file mode 100644
index 0000000..f478625
--- /dev/null
+++ b/src/test/ui/moves/move-in-guard-2.rs
@@ -0,0 +1,15 @@
+#![feature(box_syntax)]
+
+pub fn main() {
+    let x: Box<_> = box 1;
+
+    let v = (1, 2);
+
+    match v {
+        (1, _) |
+        (_, 2) if take(x) => (), //~ ERROR use of moved value: `x`
+        _ => (),
+    }
+}
+
+fn take<T>(_: T) -> bool { false }
diff --git a/src/test/ui/moves/move-in-guard-2.stderr b/src/test/ui/moves/move-in-guard-2.stderr
new file mode 100644
index 0000000..5228abe
--- /dev/null
+++ b/src/test/ui/moves/move-in-guard-2.stderr
@@ -0,0 +1,11 @@
+error[E0382]: use of moved value: `x`
+  --> $DIR/move-in-guard-2.rs:10:24
+   |
+LL |         (_, 2) if take(x) => (),
+   |                        ^ value moved here in previous iteration of loop
+   |
+   = note: move occurs because `x` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/moves/move-into-dead-array-1.nll.stderr b/src/test/ui/moves/move-into-dead-array-1.nll.stderr
new file mode 100644
index 0000000..33da0e54
--- /dev/null
+++ b/src/test/ui/moves/move-into-dead-array-1.nll.stderr
@@ -0,0 +1,9 @@
+error[E0381]: use of possibly uninitialized variable: `a`
+  --> $DIR/move-into-dead-array-1.rs:14:5
+   |
+LL |     a[i] = d();
+   |     ^^^^ use of possibly uninitialized `a`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/moves/move-into-dead-array-1.rs b/src/test/ui/moves/move-into-dead-array-1.rs
new file mode 100644
index 0000000..16a18da
--- /dev/null
+++ b/src/test/ui/moves/move-into-dead-array-1.rs
@@ -0,0 +1,15 @@
+// Ensure that we cannot move into an uninitialized fixed-size array.
+
+struct D { _x: u8 }
+
+fn d() -> D { D { _x: 0 } }
+
+fn main() {
+    foo(1);
+    foo(3);
+}
+
+fn foo(i: usize) {
+    let mut a: [D; 4];
+    a[i] = d();        //~ ERROR use of possibly uninitialized variable: `a`
+}
diff --git a/src/test/ui/moves/move-into-dead-array-1.stderr b/src/test/ui/moves/move-into-dead-array-1.stderr
new file mode 100644
index 0000000..3a1bbe9
--- /dev/null
+++ b/src/test/ui/moves/move-into-dead-array-1.stderr
@@ -0,0 +1,9 @@
+error[E0381]: use of possibly uninitialized variable: `a`
+  --> $DIR/move-into-dead-array-1.rs:14:5
+   |
+LL |     a[i] = d();
+   |     ^^^^^^^^^^ use of possibly uninitialized `a`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/moves/move-into-dead-array-2.nll.stderr b/src/test/ui/moves/move-into-dead-array-2.nll.stderr
new file mode 100644
index 0000000..19e476c
--- /dev/null
+++ b/src/test/ui/moves/move-into-dead-array-2.nll.stderr
@@ -0,0 +1,13 @@
+error[E0382]: use of moved value: `a`
+  --> $DIR/move-into-dead-array-2.rs:14:5
+   |
+LL | fn foo(mut a: [D; 4], i: usize) {
+   |        ----- move occurs because `a` has type `[D; 4]`, which does not implement the `Copy` trait
+LL |     drop(a);
+   |          - value moved here
+LL |     a[i] = d();
+   |     ^^^^ value used here after move
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/moves/move-into-dead-array-2.rs b/src/test/ui/moves/move-into-dead-array-2.rs
new file mode 100644
index 0000000..9b66ea3
--- /dev/null
+++ b/src/test/ui/moves/move-into-dead-array-2.rs
@@ -0,0 +1,15 @@
+// Ensure that we cannot move into an uninitialized fixed-size array.
+
+struct D { _x: u8 }
+
+fn d() -> D { D { _x: 0 } }
+
+fn main() {
+    foo([d(), d(), d(), d()], 1);
+    foo([d(), d(), d(), d()], 3);
+}
+
+fn foo(mut a: [D; 4], i: usize) {
+    drop(a);
+    a[i] = d(); //~ ERROR use of moved value: `a`
+}
diff --git a/src/test/ui/moves/move-into-dead-array-2.stderr b/src/test/ui/moves/move-into-dead-array-2.stderr
new file mode 100644
index 0000000..4521fa9
--- /dev/null
+++ b/src/test/ui/moves/move-into-dead-array-2.stderr
@@ -0,0 +1,13 @@
+error[E0382]: use of moved value: `a`
+  --> $DIR/move-into-dead-array-2.rs:14:5
+   |
+LL |     drop(a);
+   |          - value moved here
+LL |     a[i] = d();
+   |     ^^^^^^^^^^ value used here after move
+   |
+   = note: move occurs because `a` has type `[D; 4]`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/moves/move-out-of-array-1.rs b/src/test/ui/moves/move-out-of-array-1.rs
new file mode 100644
index 0000000..77cb73e
--- /dev/null
+++ b/src/test/ui/moves/move-out-of-array-1.rs
@@ -0,0 +1,18 @@
+// Ensure that we cannot move out of a fixed-size array (especially
+// when the element type has a destructor).
+
+
+struct D { _x: u8 }
+
+impl Drop for D { fn drop(&mut self) { } }
+
+fn main() {
+    fn d() -> D { D { _x: 0 } }
+
+    let _d1 = foo([d(), d(), d(), d()], 1);
+    let _d3 = foo([d(), d(), d(), d()], 3);
+}
+
+fn foo(a: [D; 4], i: usize) -> D {
+    a[i] //~ ERROR cannot move out of type `[D; 4]`, a non-copy array
+}
diff --git a/src/test/ui/moves/move-out-of-array-1.stderr b/src/test/ui/moves/move-out-of-array-1.stderr
new file mode 100644
index 0000000..fb191b8
--- /dev/null
+++ b/src/test/ui/moves/move-out-of-array-1.stderr
@@ -0,0 +1,9 @@
+error[E0508]: cannot move out of type `[D; 4]`, a non-copy array
+  --> $DIR/move-out-of-array-1.rs:17:5
+   |
+LL |     a[i]
+   |     ^^^^ cannot move out of here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0508`.
diff --git a/src/test/ui/moves/move-out-of-slice-1.nll.stderr b/src/test/ui/moves/move-out-of-slice-1.nll.stderr
new file mode 100644
index 0000000..b4b1fe9
--- /dev/null
+++ b/src/test/ui/moves/move-out-of-slice-1.nll.stderr
@@ -0,0 +1,17 @@
+error[E0508]: cannot move out of type `[A]`, a non-copy slice
+  --> $DIR/move-out-of-slice-1.rs:7:11
+   |
+LL |     match a {
+   |           ^ cannot move out of here
+LL |         box [a] => {},
+   |              - data moved here
+   |
+note: move occurs because `a` has type `A`, which does not implement the `Copy` trait
+  --> $DIR/move-out-of-slice-1.rs:8:14
+   |
+LL |         box [a] => {},
+   |              ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0508`.
diff --git a/src/test/ui/moves/move-out-of-slice-1.rs b/src/test/ui/moves/move-out-of-slice-1.rs
new file mode 100644
index 0000000..3e09060
--- /dev/null
+++ b/src/test/ui/moves/move-out-of-slice-1.rs
@@ -0,0 +1,11 @@
+#![feature(box_patterns)]
+
+struct A;
+
+fn main() {
+    let a: Box<[A]> = Box::new([A]);
+    match a {
+        box [a] => {}, //~ ERROR cannot move out of type `[A]`, a non-copy slice
+        _ => {}
+    }
+}
diff --git a/src/test/ui/moves/move-out-of-slice-1.stderr b/src/test/ui/moves/move-out-of-slice-1.stderr
new file mode 100644
index 0000000..f84e3a3
--- /dev/null
+++ b/src/test/ui/moves/move-out-of-slice-1.stderr
@@ -0,0 +1,12 @@
+error[E0508]: cannot move out of type `[A]`, a non-copy slice
+  --> $DIR/move-out-of-slice-1.rs:8:13
+   |
+LL |         box [a] => {},
+   |             ^-^
+   |             ||
+   |             |hint: to prevent move, use `ref a` or `ref mut a`
+   |             cannot move out of here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0508`.
diff --git a/src/test/ui/moves/move-out-of-tuple-field.nll.stderr b/src/test/ui/moves/move-out-of-tuple-field.nll.stderr
new file mode 100644
index 0000000..888ef33
--- /dev/null
+++ b/src/test/ui/moves/move-out-of-tuple-field.nll.stderr
@@ -0,0 +1,23 @@
+error[E0382]: use of moved value: `x.0`
+  --> $DIR/move-out-of-tuple-field.rs:8:13
+   |
+LL |     let y = x.0;
+   |             --- value moved here
+LL |     let z = x.0;
+   |             ^^^ value used here after move
+   |
+   = note: move occurs because `x.0` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `x.0`
+  --> $DIR/move-out-of-tuple-field.rs:12:13
+   |
+LL |     let y = x.0;
+   |             --- value moved here
+LL |     let z = x.0;
+   |             ^^^ value used here after move
+   |
+   = note: move occurs because `x.0` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/moves/move-out-of-tuple-field.rs b/src/test/ui/moves/move-out-of-tuple-field.rs
new file mode 100644
index 0000000..e5a505b
--- /dev/null
+++ b/src/test/ui/moves/move-out-of-tuple-field.rs
@@ -0,0 +1,13 @@
+#![feature(box_syntax)]
+
+struct Foo(Box<isize>);
+
+fn main() {
+    let x: (Box<_>,) = (box 1,);
+    let y = x.0;
+    let z = x.0; //~ ERROR use of moved value: `x.0`
+
+    let x = Foo(box 1);
+    let y = x.0;
+    let z = x.0; //~ ERROR use of moved value: `x.0`
+}
diff --git a/src/test/ui/moves/move-out-of-tuple-field.stderr b/src/test/ui/moves/move-out-of-tuple-field.stderr
new file mode 100644
index 0000000..89662c8
--- /dev/null
+++ b/src/test/ui/moves/move-out-of-tuple-field.stderr
@@ -0,0 +1,23 @@
+error[E0382]: use of moved value: `x.0`
+  --> $DIR/move-out-of-tuple-field.rs:8:9
+   |
+LL |     let y = x.0;
+   |         - value moved here
+LL |     let z = x.0;
+   |         ^ value used here after move
+   |
+   = note: move occurs because `x.0` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `x.0`
+  --> $DIR/move-out-of-tuple-field.rs:12:9
+   |
+LL |     let y = x.0;
+   |         - value moved here
+LL |     let z = x.0;
+   |         ^ value used here after move
+   |
+   = note: move occurs because `x.0` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/moves/moves-based-on-type-access-to-field.nll.stderr b/src/test/ui/moves/moves-based-on-type-access-to-field.nll.stderr
new file mode 100644
index 0000000..71a3c45
--- /dev/null
+++ b/src/test/ui/moves/moves-based-on-type-access-to-field.nll.stderr
@@ -0,0 +1,13 @@
+error[E0382]: borrow of moved value: `x`
+  --> $DIR/moves-based-on-type-access-to-field.rs:11:12
+   |
+LL |     let x = vec!["hi".to_string()];
+   |         - move occurs because `x` has type `std::vec::Vec<std::string::String>`, which does not implement the `Copy` trait
+LL |     consume(x.into_iter().next().unwrap());
+   |             - value moved here
+LL |     touch(&x[0]);
+   |            ^ value borrowed here after move
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/moves/moves-based-on-type-access-to-field.rs b/src/test/ui/moves/moves-based-on-type-access-to-field.rs
new file mode 100644
index 0000000..c7ea357
--- /dev/null
+++ b/src/test/ui/moves/moves-based-on-type-access-to-field.rs
@@ -0,0 +1,14 @@
+// Tests that if you move from `x.f` or `x[0]`, `x` is inaccessible.
+// Also tests that we give a more specific error message.
+
+struct Foo { f: String, y: isize }
+fn consume(_s: String) {}
+fn touch<A>(_a: &A) {}
+
+fn f20() {
+    let x = vec!["hi".to_string()];
+    consume(x.into_iter().next().unwrap());
+    touch(&x[0]); //~ ERROR use of moved value: `x`
+}
+
+fn main() {}
diff --git a/src/test/ui/moves/moves-based-on-type-access-to-field.stderr b/src/test/ui/moves/moves-based-on-type-access-to-field.stderr
new file mode 100644
index 0000000..ed4d69f
--- /dev/null
+++ b/src/test/ui/moves/moves-based-on-type-access-to-field.stderr
@@ -0,0 +1,13 @@
+error[E0382]: use of moved value: `x`
+  --> $DIR/moves-based-on-type-access-to-field.rs:11:12
+   |
+LL |     consume(x.into_iter().next().unwrap());
+   |             - value moved here
+LL |     touch(&x[0]);
+   |            ^ value used here after move
+   |
+   = note: move occurs because `x` has type `std::vec::Vec<std::string::String>`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/moves/moves-based-on-type-block-bad.nll.stderr b/src/test/ui/moves/moves-based-on-type-block-bad.nll.stderr
new file mode 100644
index 0000000..b83a15c
--- /dev/null
+++ b/src/test/ui/moves/moves-based-on-type-block-bad.nll.stderr
@@ -0,0 +1,21 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/moves-based-on-type-block-bad.rs:24:19
+   |
+LL |             match hellothere.x {
+   |                   ^^^^^^^^^^^^
+   |                   |
+   |                   cannot move out of borrowed content
+   |                   help: consider borrowing here: `&hellothere.x`
+...
+LL |                 box E::Bar(x) => println!("{}", x.to_string()),
+   |                            - data moved here
+   |
+note: move occurs because `x` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+  --> $DIR/moves-based-on-type-block-bad.rs:27:28
+   |
+LL |                 box E::Bar(x) => println!("{}", x.to_string()),
+   |                            ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/moves/moves-based-on-type-block-bad.rs b/src/test/ui/moves/moves-based-on-type-block-bad.rs
new file mode 100644
index 0000000..99928ca
--- /dev/null
+++ b/src/test/ui/moves/moves-based-on-type-block-bad.rs
@@ -0,0 +1,32 @@
+// ignore-tidy-linelength
+
+#![feature(box_patterns)]
+#![feature(box_syntax)]
+
+struct S {
+    x: Box<E>
+}
+
+enum E {
+    Foo(Box<S>),
+    Bar(Box<isize>),
+    Baz
+}
+
+fn f<G>(s: &S, g: G) where G: FnOnce(&S) {
+    g(s)
+}
+
+fn main() {
+    let s = S { x: box E::Bar(box 42) };
+    loop {
+        f(&s, |hellothere| {
+            match hellothere.x { //~ ERROR cannot move out
+                                 //~| cannot move out of borrowed content
+                box E::Foo(_) => {}
+                box E::Bar(x) => println!("{}", x.to_string()),
+                box E::Baz => {}
+            }
+        })
+    }
+}
diff --git a/src/test/ui/moves/moves-based-on-type-block-bad.stderr b/src/test/ui/moves/moves-based-on-type-block-bad.stderr
new file mode 100644
index 0000000..f5328ed
--- /dev/null
+++ b/src/test/ui/moves/moves-based-on-type-block-bad.stderr
@@ -0,0 +1,12 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/moves-based-on-type-block-bad.rs:24:19
+   |
+LL |             match hellothere.x {
+   |                   ^^^^^^^^^^ cannot move out of borrowed content
+...
+LL |                 box E::Bar(x) => println!("{}", x.to_string()),
+   |                            - hint: to prevent move, use `ref x` or `ref mut x`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/moves/moves-based-on-type-capture-clause-bad.nll.stderr b/src/test/ui/moves/moves-based-on-type-capture-clause-bad.nll.stderr
new file mode 100644
index 0000000..3a05a13
--- /dev/null
+++ b/src/test/ui/moves/moves-based-on-type-capture-clause-bad.nll.stderr
@@ -0,0 +1,16 @@
+error[E0382]: borrow of moved value: `x`
+  --> $DIR/moves-based-on-type-capture-clause-bad.rs:8:20
+   |
+LL |     let x = "Hello world!".to_string();
+   |         - move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
+LL |     thread::spawn(move|| {
+   |                   ------ value moved into closure here
+LL |         println!("{}", x);
+   |                        - variable moved due to use in closure
+LL |     });
+LL |     println!("{}", x);
+   |                    ^ value borrowed here after move
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/moves/moves-based-on-type-capture-clause-bad.rs b/src/test/ui/moves/moves-based-on-type-capture-clause-bad.rs
new file mode 100644
index 0000000..d5f44a0
--- /dev/null
+++ b/src/test/ui/moves/moves-based-on-type-capture-clause-bad.rs
@@ -0,0 +1,9 @@
+use std::thread;
+
+fn main() {
+    let x = "Hello world!".to_string();
+    thread::spawn(move|| {
+        println!("{}", x);
+    });
+    println!("{}", x); //~ ERROR use of moved value
+}
diff --git a/src/test/ui/moves/moves-based-on-type-capture-clause-bad.stderr b/src/test/ui/moves/moves-based-on-type-capture-clause-bad.stderr
new file mode 100644
index 0000000..39119ff
--- /dev/null
+++ b/src/test/ui/moves/moves-based-on-type-capture-clause-bad.stderr
@@ -0,0 +1,14 @@
+error[E0382]: use of moved value: `x`
+  --> $DIR/moves-based-on-type-capture-clause-bad.rs:8:20
+   |
+LL |     thread::spawn(move|| {
+   |                   ------ value moved (into closure) here
+...
+LL |     println!("{}", x);
+   |                    ^ value used here after move
+   |
+   = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/moves/moves-based-on-type-cyclic-types-issue-4821.nll.stderr b/src/test/ui/moves/moves-based-on-type-cyclic-types-issue-4821.nll.stderr
new file mode 100644
index 0000000..fb8562d
--- /dev/null
+++ b/src/test/ui/moves/moves-based-on-type-cyclic-types-issue-4821.nll.stderr
@@ -0,0 +1,14 @@
+error[E0382]: use of moved value: `node`
+  --> $DIR/moves-based-on-type-cyclic-types-issue-4821.rs:13:13
+   |
+LL |         Some(right) => consume(right),
+   |              ----- value moved here
+...
+LL |     consume(node) + r
+   |             ^^^^ value used here after partial move
+   |
+   = note: move occurs because value has type `std::boxed::Box<List>`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/moves/moves-based-on-type-cyclic-types-issue-4821.rs b/src/test/ui/moves/moves-based-on-type-cyclic-types-issue-4821.rs
new file mode 100644
index 0000000..4417fb9
--- /dev/null
+++ b/src/test/ui/moves/moves-based-on-type-cyclic-types-issue-4821.rs
@@ -0,0 +1,20 @@
+// Test for a subtle failure computing kinds of cyclic types, in which
+// temporary kinds wound up being stored in a cache and used later.
+// See rustc::ty::type_contents() for more information.
+
+
+struct List { key: isize, next: Option<Box<List>> }
+
+fn foo(node: Box<List>) -> isize {
+    let r = match node.next {
+        Some(right) => consume(right),
+        None => 0
+    };
+    consume(node) + r //~ ERROR use of partially moved value: `node`
+}
+
+fn consume(v: Box<List>) -> isize {
+    v.key
+}
+
+fn main() {}
diff --git a/src/test/ui/moves/moves-based-on-type-cyclic-types-issue-4821.stderr b/src/test/ui/moves/moves-based-on-type-cyclic-types-issue-4821.stderr
new file mode 100644
index 0000000..8b904c7
--- /dev/null
+++ b/src/test/ui/moves/moves-based-on-type-cyclic-types-issue-4821.stderr
@@ -0,0 +1,14 @@
+error[E0382]: use of partially moved value: `node`
+  --> $DIR/moves-based-on-type-cyclic-types-issue-4821.rs:13:13
+   |
+LL |         Some(right) => consume(right),
+   |              ----- value moved here
+...
+LL |     consume(node) + r
+   |             ^^^^ value used here after move
+   |
+   = note: move occurs because the value has type `std::boxed::Box<List>`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/moves/moves-based-on-type-distribute-copy-over-paren.nll.stderr b/src/test/ui/moves/moves-based-on-type-distribute-copy-over-paren.nll.stderr
new file mode 100644
index 0000000..25f88fe
--- /dev/null
+++ b/src/test/ui/moves/moves-based-on-type-distribute-copy-over-paren.nll.stderr
@@ -0,0 +1,25 @@
+error[E0382]: borrow of moved value: `x`
+  --> $DIR/moves-based-on-type-distribute-copy-over-paren.rs:11:11
+   |
+LL |     let x = "hi".to_string();
+   |         - move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
+LL |     let _y = Foo { f:x };
+   |                      - value moved here
+LL |
+LL |     touch(&x);
+   |           ^^ value borrowed here after move
+
+error[E0382]: borrow of moved value: `x`
+  --> $DIR/moves-based-on-type-distribute-copy-over-paren.rs:20:11
+   |
+LL |     let x = "hi".to_string();
+   |         - move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
+LL |     let _y = Foo { f:(((x))) };
+   |                      ------- value moved here
+LL |
+LL |     touch(&x);
+   |           ^^ value borrowed here after move
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/moves/moves-based-on-type-distribute-copy-over-paren.rs b/src/test/ui/moves/moves-based-on-type-distribute-copy-over-paren.rs
new file mode 100644
index 0000000..7c7ca00
--- /dev/null
+++ b/src/test/ui/moves/moves-based-on-type-distribute-copy-over-paren.rs
@@ -0,0 +1,49 @@
+// Tests that references to move-by-default values trigger moves when
+// they occur as part of various kinds of expressions.
+
+struct Foo<A> { f: A }
+fn touch<A>(_a: &A) {}
+
+fn f00() {
+    let x = "hi".to_string();
+    let _y = Foo { f:x };
+    //~^ NOTE value moved here
+    touch(&x); //~ ERROR use of moved value: `x`
+    //~^ NOTE value used here after move
+    //~| NOTE move occurs because `x` has type `std::string::String`
+}
+
+fn f05() {
+    let x = "hi".to_string();
+    let _y = Foo { f:(((x))) };
+    //~^ NOTE value moved here
+    touch(&x); //~ ERROR use of moved value: `x`
+    //~^ NOTE value used here after move
+    //~| NOTE move occurs because `x` has type `std::string::String`
+}
+
+fn f10() {
+    let x = "hi".to_string();
+    let _y = Foo { f:x.clone() };
+    touch(&x);
+}
+
+fn f20() {
+    let x = "hi".to_string();
+    let _y = Foo { f:(x).clone() };
+    touch(&x);
+}
+
+fn f30() {
+    let x = "hi".to_string();
+    let _y = Foo { f:((x)).clone() };
+    touch(&x);
+}
+
+fn f40() {
+    let x = "hi".to_string();
+    let _y = Foo { f:(((((((x)).clone()))))) };
+    touch(&x);
+}
+
+fn main() {}
diff --git a/src/test/ui/moves/moves-based-on-type-distribute-copy-over-paren.stderr b/src/test/ui/moves/moves-based-on-type-distribute-copy-over-paren.stderr
new file mode 100644
index 0000000..edf521a
--- /dev/null
+++ b/src/test/ui/moves/moves-based-on-type-distribute-copy-over-paren.stderr
@@ -0,0 +1,25 @@
+error[E0382]: use of moved value: `x`
+  --> $DIR/moves-based-on-type-distribute-copy-over-paren.rs:11:12
+   |
+LL |     let _y = Foo { f:x };
+   |                      - value moved here
+LL |
+LL |     touch(&x);
+   |            ^ value used here after move
+   |
+   = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `x`
+  --> $DIR/moves-based-on-type-distribute-copy-over-paren.rs:20:12
+   |
+LL |     let _y = Foo { f:(((x))) };
+   |                      ------- value moved here
+LL |
+LL |     touch(&x);
+   |            ^ value used here after move
+   |
+   = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/moves/moves-based-on-type-exprs.nll.stderr b/src/test/ui/moves/moves-based-on-type-exprs.nll.stderr
new file mode 100644
index 0000000..67fae60
--- /dev/null
+++ b/src/test/ui/moves/moves-based-on-type-exprs.nll.stderr
@@ -0,0 +1,123 @@
+error[E0382]: borrow of moved value: `x`
+  --> $DIR/moves-based-on-type-exprs.rs:12:11
+   |
+LL |     let x = "hi".to_string();
+   |         - move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
+LL |     let _y = Foo { f:x };
+   |                      - value moved here
+LL |     touch(&x);
+   |           ^^ value borrowed here after move
+
+error[E0382]: borrow of moved value: `x`
+  --> $DIR/moves-based-on-type-exprs.rs:18:11
+   |
+LL |     let x = "hi".to_string();
+   |         - move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
+LL |     let _y = (x, 3);
+   |               - value moved here
+LL |     touch(&x);
+   |           ^^ value borrowed here after move
+
+error[E0382]: borrow of moved value: `x`
+  --> $DIR/moves-based-on-type-exprs.rs:35:11
+   |
+LL |     let x = "hi".to_string();
+   |         - move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
+...
+LL |         x
+   |         - value moved here
+...
+LL |     touch(&x);
+   |           ^^ value borrowed here after move
+
+error[E0382]: borrow of moved value: `y`
+  --> $DIR/moves-based-on-type-exprs.rs:36:11
+   |
+LL |     let y = "ho".to_string();
+   |         - move occurs because `y` has type `std::string::String`, which does not implement the `Copy` trait
+...
+LL |         y
+   |         - value moved here
+...
+LL |     touch(&y);
+   |           ^^ value borrowed here after move
+
+error[E0382]: borrow of moved value: `x`
+  --> $DIR/moves-based-on-type-exprs.rs:46:11
+   |
+LL |     let x = "hi".to_string();
+   |         - move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
+...
+LL |         true => x,
+   |                 - value moved here
+...
+LL |     touch(&x);
+   |           ^^ value borrowed here after move
+
+error[E0382]: borrow of moved value: `y`
+  --> $DIR/moves-based-on-type-exprs.rs:47:11
+   |
+LL |     let y = "ho".to_string();
+   |         - move occurs because `y` has type `std::string::String`, which does not implement the `Copy` trait
+...
+LL |         false => y
+   |                  - value moved here
+...
+LL |     touch(&y);
+   |           ^^ value borrowed here after move
+
+error[E0382]: borrow of moved value: `x`
+  --> $DIR/moves-based-on-type-exprs.rs:58:11
+   |
+LL |     let x = "hi".to_string();
+   |         - move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
+...
+LL |         _ if guard(x) => 10,
+   |                    - value moved here
+...
+LL |     touch(&x);
+   |           ^^ value borrowed here after move
+
+error[E0382]: borrow of moved value: `x`
+  --> $DIR/moves-based-on-type-exprs.rs:65:11
+   |
+LL |     let x = "hi".to_string();
+   |         - move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
+LL |     let _y = [x];
+   |               - value moved here
+LL |     touch(&x);
+   |           ^^ value borrowed here after move
+
+error[E0382]: borrow of moved value: `x`
+  --> $DIR/moves-based-on-type-exprs.rs:71:11
+   |
+LL |     let x = "hi".to_string();
+   |         - move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
+LL |     let _y = vec![x];
+   |                   - value moved here
+LL |     touch(&x);
+   |           ^^ value borrowed here after move
+
+error[E0382]: borrow of moved value: `x`
+  --> $DIR/moves-based-on-type-exprs.rs:77:11
+   |
+LL |     let x = vec!["hi".to_string()];
+   |         - move occurs because `x` has type `std::vec::Vec<std::string::String>`, which does not implement the `Copy` trait
+LL |     let _y = x.into_iter().next().unwrap();
+   |              - value moved here
+LL |     touch(&x);
+   |           ^^ value borrowed here after move
+
+error[E0382]: borrow of moved value: `x`
+  --> $DIR/moves-based-on-type-exprs.rs:83:11
+   |
+LL |     let x = vec!["hi".to_string()];
+   |         - move occurs because `x` has type `std::vec::Vec<std::string::String>`, which does not implement the `Copy` trait
+LL |     let _y = [x.into_iter().next().unwrap(); 1];
+   |               - value moved here
+LL |     touch(&x);
+   |           ^^ value borrowed here after move
+
+error: aborting due to 11 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/moves/moves-based-on-type-exprs.rs b/src/test/ui/moves/moves-based-on-type-exprs.rs
new file mode 100644
index 0000000..b058f83
--- /dev/null
+++ b/src/test/ui/moves/moves-based-on-type-exprs.rs
@@ -0,0 +1,93 @@
+// Tests that references to move-by-default values trigger moves when
+// they occur as part of various kinds of expressions.
+
+
+struct Foo<A> { f: A }
+fn guard(_s: String) -> bool {panic!()}
+fn touch<A>(_a: &A) {}
+
+fn f10() {
+    let x = "hi".to_string();
+    let _y = Foo { f:x };
+    touch(&x); //~ ERROR use of moved value: `x`
+}
+
+fn f20() {
+    let x = "hi".to_string();
+    let _y = (x, 3);
+    touch(&x); //~ ERROR use of moved value: `x`
+}
+
+fn f21() {
+    let x = vec![1, 2, 3];
+    let _y = (x[0], 3);
+    touch(&x);
+}
+
+fn f30(cond: bool) {
+    let x = "hi".to_string();
+    let y = "ho".to_string();
+    let _y = if cond {
+        x
+    } else {
+        y
+    };
+    touch(&x); //~ ERROR use of moved value: `x`
+    touch(&y); //~ ERROR use of moved value: `y`
+}
+
+fn f40(cond: bool) {
+    let x = "hi".to_string();
+    let y = "ho".to_string();
+    let _y = match cond {
+        true => x,
+        false => y
+    };
+    touch(&x); //~ ERROR use of moved value: `x`
+    touch(&y); //~ ERROR use of moved value: `y`
+}
+
+fn f50(cond: bool) {
+    let x = "hi".to_string();
+    let y = "ho".to_string();
+    let _y = match cond {
+        _ if guard(x) => 10,
+        true => 10,
+        false => 20,
+    };
+    touch(&x); //~ ERROR use of moved value: `x`
+    touch(&y);
+}
+
+fn f70() {
+    let x = "hi".to_string();
+    let _y = [x];
+    touch(&x); //~ ERROR use of moved value: `x`
+}
+
+fn f80() {
+    let x = "hi".to_string();
+    let _y = vec![x];
+    touch(&x); //~ ERROR use of moved value: `x`
+}
+
+fn f100() {
+    let x = vec!["hi".to_string()];
+    let _y = x.into_iter().next().unwrap();
+    touch(&x); //~ ERROR use of moved value: `x`
+}
+
+fn f110() {
+    let x = vec!["hi".to_string()];
+    let _y = [x.into_iter().next().unwrap(); 1];
+    touch(&x); //~ ERROR use of moved value: `x`
+}
+
+fn f120() {
+    let mut x = vec!["hi".to_string(), "ho".to_string()];
+    x.swap(0, 1);
+    touch(&x[0]);
+    touch(&x[1]);
+}
+
+fn main() {}
diff --git a/src/test/ui/moves/moves-based-on-type-exprs.stderr b/src/test/ui/moves/moves-based-on-type-exprs.stderr
new file mode 100644
index 0000000..6cb297c
--- /dev/null
+++ b/src/test/ui/moves/moves-based-on-type-exprs.stderr
@@ -0,0 +1,118 @@
+error[E0382]: use of moved value: `x`
+  --> $DIR/moves-based-on-type-exprs.rs:12:12
+   |
+LL |     let _y = Foo { f:x };
+   |                      - value moved here
+LL |     touch(&x);
+   |            ^ value used here after move
+   |
+   = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `x`
+  --> $DIR/moves-based-on-type-exprs.rs:18:12
+   |
+LL |     let _y = (x, 3);
+   |               - value moved here
+LL |     touch(&x);
+   |            ^ value used here after move
+   |
+   = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `x`
+  --> $DIR/moves-based-on-type-exprs.rs:35:12
+   |
+LL |         x
+   |         - value moved here
+...
+LL |     touch(&x);
+   |            ^ value used here after move
+   |
+   = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `y`
+  --> $DIR/moves-based-on-type-exprs.rs:36:12
+   |
+LL |         y
+   |         - value moved here
+...
+LL |     touch(&y);
+   |            ^ value used here after move
+   |
+   = note: move occurs because `y` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `x`
+  --> $DIR/moves-based-on-type-exprs.rs:46:12
+   |
+LL |         true => x,
+   |                 - value moved here
+...
+LL |     touch(&x);
+   |            ^ value used here after move
+   |
+   = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `y`
+  --> $DIR/moves-based-on-type-exprs.rs:47:12
+   |
+LL |         false => y
+   |                  - value moved here
+...
+LL |     touch(&y);
+   |            ^ value used here after move
+   |
+   = note: move occurs because `y` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `x`
+  --> $DIR/moves-based-on-type-exprs.rs:58:12
+   |
+LL |         _ if guard(x) => 10,
+   |                    - value moved here
+...
+LL |     touch(&x);
+   |            ^ value used here after move
+   |
+   = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `x`
+  --> $DIR/moves-based-on-type-exprs.rs:65:12
+   |
+LL |     let _y = [x];
+   |               - value moved here
+LL |     touch(&x);
+   |            ^ value used here after move
+   |
+   = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `x`
+  --> $DIR/moves-based-on-type-exprs.rs:71:12
+   |
+LL |     let _y = vec![x];
+   |                   - value moved here
+LL |     touch(&x);
+   |            ^ value used here after move
+   |
+   = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `x`
+  --> $DIR/moves-based-on-type-exprs.rs:77:12
+   |
+LL |     let _y = x.into_iter().next().unwrap();
+   |              - value moved here
+LL |     touch(&x);
+   |            ^ value used here after move
+   |
+   = note: move occurs because `x` has type `std::vec::Vec<std::string::String>`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `x`
+  --> $DIR/moves-based-on-type-exprs.rs:83:12
+   |
+LL |     let _y = [x.into_iter().next().unwrap(); 1];
+   |               - value moved here
+LL |     touch(&x);
+   |            ^ value used here after move
+   |
+   = note: move occurs because `x` has type `std::vec::Vec<std::string::String>`, which does not implement the `Copy` trait
+
+error: aborting due to 11 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/moves/moves-based-on-type-match-bindings.nll.stderr b/src/test/ui/moves/moves-based-on-type-match-bindings.nll.stderr
new file mode 100644
index 0000000..322999a
--- /dev/null
+++ b/src/test/ui/moves/moves-based-on-type-match-bindings.nll.stderr
@@ -0,0 +1,14 @@
+error[E0382]: borrow of moved value: `x`
+  --> $DIR/moves-based-on-type-match-bindings.rs:16:11
+   |
+LL |         Foo {f} => {}
+   |              - value moved here
+...
+LL |     touch(&x);
+   |           ^^ value borrowed here after partial move
+   |
+   = note: move occurs because `x.f` has type `std::string::String`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/moves/moves-based-on-type-match-bindings.rs b/src/test/ui/moves/moves-based-on-type-match-bindings.rs
new file mode 100644
index 0000000..59e5a8f
--- /dev/null
+++ b/src/test/ui/moves/moves-based-on-type-match-bindings.rs
@@ -0,0 +1,21 @@
+// Tests that bindings to move-by-default values trigger moves of the
+// discriminant. Also tests that the compiler explains the move in
+// terms of the binding, not the discriminant.
+
+struct Foo<A> { f: A }
+fn guard(_s: String) -> bool {panic!()}
+fn touch<A>(_a: &A) {}
+
+fn f10() {
+    let x = Foo {f: "hi".to_string()};
+
+    let y = match x {
+        Foo {f} => {}
+    };
+
+    touch(&x); //~ ERROR use of partially moved value: `x`
+    //~^ value used here after move
+    //~| move occurs because `x.f` has type `std::string::String`
+}
+
+fn main() {}
diff --git a/src/test/ui/moves/moves-based-on-type-match-bindings.stderr b/src/test/ui/moves/moves-based-on-type-match-bindings.stderr
new file mode 100644
index 0000000..9174cfa
--- /dev/null
+++ b/src/test/ui/moves/moves-based-on-type-match-bindings.stderr
@@ -0,0 +1,14 @@
+error[E0382]: use of partially moved value: `x`
+  --> $DIR/moves-based-on-type-match-bindings.rs:16:12
+   |
+LL |         Foo {f} => {}
+   |              - value moved here
+...
+LL |     touch(&x);
+   |            ^ value used here after move
+   |
+   = note: move occurs because `x.f` has type `std::string::String`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.nll.stderr b/src/test/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.nll.stderr
new file mode 100644
index 0000000..0568a2e
--- /dev/null
+++ b/src/test/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.nll.stderr
@@ -0,0 +1,11 @@
+error[E0507]: cannot move out of captured variable in an `Fn` closure
+  --> $DIR/moves-based-on-type-move-out-of-closure-env-issue-1965.rs:11:28
+   |
+LL |     let i = box 3;
+   |         - captured outer variable
+LL |     let _f = to_fn(|| test(i));
+   |                            ^ cannot move out of captured variable in an `Fn` closure
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.rs b/src/test/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.rs
new file mode 100644
index 0000000..5fcd339
--- /dev/null
+++ b/src/test/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.rs
@@ -0,0 +1,12 @@
+#![feature(box_syntax, unboxed_closures)]
+
+use std::usize;
+
+fn to_fn<A,F:Fn<A>>(f: F) -> F { f }
+
+fn test(_x: Box<usize>) {}
+
+fn main() {
+    let i = box 3;
+    let _f = to_fn(|| test(i)); //~ ERROR cannot move out
+}
diff --git a/src/test/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.stderr b/src/test/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.stderr
new file mode 100644
index 0000000..654881d
--- /dev/null
+++ b/src/test/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.stderr
@@ -0,0 +1,11 @@
+error[E0507]: cannot move out of captured outer variable in an `Fn` closure
+  --> $DIR/moves-based-on-type-move-out-of-closure-env-issue-1965.rs:11:28
+   |
+LL |     let i = box 3;
+   |         - captured outer variable
+LL |     let _f = to_fn(|| test(i));
+   |                            ^ cannot move out of captured outer variable in an `Fn` closure
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/moves/moves-based-on-type-no-recursive-stack-closure.nll.stderr b/src/test/ui/moves/moves-based-on-type-no-recursive-stack-closure.nll.stderr
new file mode 100644
index 0000000..dde54ee
--- /dev/null
+++ b/src/test/ui/moves/moves-based-on-type-no-recursive-stack-closure.nll.stderr
@@ -0,0 +1,25 @@
+error[E0499]: cannot borrow `*f` as mutable more than once at a time
+  --> $DIR/moves-based-on-type-no-recursive-stack-closure.rs:20:27
+   |
+LL |                     (f.c)(f, true);
+   |                     ----- ^ second mutable borrow occurs here
+   |                     |
+   |                     first mutable borrow occurs here
+   |                     first borrow later used by call
+
+error[E0382]: borrow of moved value: `f`
+  --> $DIR/moves-based-on-type-no-recursive-stack-closure.rs:32:5
+   |
+LL | fn conspirator<F>(mut f: F) where F: FnMut(&mut R, bool) {
+   |                -  ----- move occurs because `f` has type `F`, which does not implement the `Copy` trait
+   |                |
+   |                consider adding a `Copy` constraint to this type argument
+LL |     let mut r = R {c: Box::new(f)};
+   |                                - value moved here
+LL |     f(&mut r, false)
+   |     ^ value borrowed here after move
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0382, E0499.
+For more information about an error, try `rustc --explain E0382`.
diff --git a/src/test/ui/moves/moves-based-on-type-no-recursive-stack-closure.rs b/src/test/ui/moves/moves-based-on-type-no-recursive-stack-closure.rs
new file mode 100644
index 0000000..737a131
--- /dev/null
+++ b/src/test/ui/moves/moves-based-on-type-no-recursive-stack-closure.rs
@@ -0,0 +1,35 @@
+// Tests correct kind-checking of the reason stack closures without the :Copy
+// bound must be noncopyable. For details see
+// http://smallcultfollowing.com/babysteps/blog/2013/04/30/the-case-of-the-recurring-closure/
+
+struct R<'a> {
+    // This struct is needed to create the
+    // otherwise infinite type of a fn that
+    // accepts itself as argument:
+    c: Box<FnMut(&mut R, bool) + 'a>
+}
+
+fn innocent_looking_victim() {
+    let mut x = Some("hello".to_string());
+    conspirator(|f, writer| {
+        if writer {
+            x = None;
+        } else {
+            match x {
+                Some(ref msg) => {
+                    (f.c)(f, true);
+                    //~^ ERROR: cannot borrow `*f` as mutable more than once at a time
+                    println!("{}", msg);
+                },
+                None => panic!("oops"),
+            }
+        }
+    })
+}
+
+fn conspirator<F>(mut f: F) where F: FnMut(&mut R, bool) {
+    let mut r = R {c: Box::new(f)};
+    f(&mut r, false) //~ ERROR use of moved value
+}
+
+fn main() { innocent_looking_victim() }
diff --git a/src/test/ui/moves/moves-based-on-type-no-recursive-stack-closure.stderr b/src/test/ui/moves/moves-based-on-type-no-recursive-stack-closure.stderr
new file mode 100644
index 0000000..fe91a48
--- /dev/null
+++ b/src/test/ui/moves/moves-based-on-type-no-recursive-stack-closure.stderr
@@ -0,0 +1,23 @@
+error[E0499]: cannot borrow `*f` as mutable more than once at a time
+  --> $DIR/moves-based-on-type-no-recursive-stack-closure.rs:20:27
+   |
+LL |                     (f.c)(f, true);
+   |                     ----- ^      - first borrow ends here
+   |                     |     |
+   |                     |     second mutable borrow occurs here
+   |                     first mutable borrow occurs here
+
+error[E0382]: use of moved value: `f`
+  --> $DIR/moves-based-on-type-no-recursive-stack-closure.rs:32:5
+   |
+LL |     let mut r = R {c: Box::new(f)};
+   |                                - value moved here
+LL |     f(&mut r, false)
+   |     ^ value used here after move
+   |
+   = note: move occurs because `f` has type `F`, which does not implement the `Copy` trait
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0382, E0499.
+For more information about an error, try `rustc --explain E0382`.
diff --git a/src/test/ui/moves/moves-based-on-type-tuple.rs b/src/test/ui/moves/moves-based-on-type-tuple.rs
new file mode 100644
index 0000000..d99fe519
--- /dev/null
+++ b/src/test/ui/moves/moves-based-on-type-tuple.rs
@@ -0,0 +1,13 @@
+#![feature(box_syntax)]
+
+// compile-flags: -Z borrowck=compare
+
+fn dup(x: Box<isize>) -> Box<(Box<isize>,Box<isize>)> {
+    box (x, x)
+    //~^ use of moved value: `x` (Ast) [E0382]
+    //~| use of moved value: `x` (Mir) [E0382]
+}
+
+fn main() {
+    dup(box 3);
+}
diff --git a/src/test/ui/moves/moves-based-on-type-tuple.stderr b/src/test/ui/moves/moves-based-on-type-tuple.stderr
new file mode 100644
index 0000000..c49dbda
--- /dev/null
+++ b/src/test/ui/moves/moves-based-on-type-tuple.stderr
@@ -0,0 +1,23 @@
+error[E0382]: use of moved value: `x` (Ast)
+  --> $DIR/moves-based-on-type-tuple.rs:6:13
+   |
+LL |     box (x, x)
+   |          -  ^ value used here after move
+   |          |
+   |          value moved here
+   |
+   = note: move occurs because `x` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `x` (Mir)
+  --> $DIR/moves-based-on-type-tuple.rs:6:13
+   |
+LL | fn dup(x: Box<isize>) -> Box<(Box<isize>,Box<isize>)> {
+   |        - move occurs because `x` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+LL |     box (x, x)
+   |          -  ^ value used here after move
+   |          |
+   |          value moved here
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/moves/moves-sru-moved-field.nll.stderr b/src/test/ui/moves/moves-sru-moved-field.nll.stderr
new file mode 100644
index 0000000..a012c2d
--- /dev/null
+++ b/src/test/ui/moves/moves-sru-moved-field.nll.stderr
@@ -0,0 +1,13 @@
+error[E0382]: use of moved value: `f.moved`
+  --> $DIR/moves-sru-moved-field.rs:20:14
+   |
+LL |     let _b = Foo {noncopyable: g, ..f};
+   |              ------------------------- value moved here
+LL |     let _c = Foo {noncopyable: h, ..f};
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^ value used here after move
+   |
+   = note: move occurs because `f.moved` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/moves/moves-sru-moved-field.rs b/src/test/ui/moves/moves-sru-moved-field.rs
new file mode 100644
index 0000000..e620e5d
--- /dev/null
+++ b/src/test/ui/moves/moves-sru-moved-field.rs
@@ -0,0 +1,23 @@
+#![feature(box_syntax)]
+
+type Noncopyable = Box<isize>;
+
+struct Foo {
+    copied: isize,
+    moved: Box<isize>,
+    noncopyable: Noncopyable
+}
+
+fn test0(f: Foo, g: Noncopyable, h: Noncopyable) {
+    // just copy implicitly copyable fields from `f`, no moves:
+    let _b = Foo {moved: box 1, noncopyable: g, ..f};
+    let _c = Foo {moved: box 2, noncopyable: h, ..f};
+}
+
+fn test1(f: Foo, g: Noncopyable, h: Noncopyable) {
+    // copying move-by-default fields from `f`, so move:
+    let _b = Foo {noncopyable: g, ..f};
+    let _c = Foo {noncopyable: h, ..f}; //~ ERROR use of moved value: `f.moved`
+}
+
+fn main() {}
diff --git a/src/test/ui/moves/moves-sru-moved-field.stderr b/src/test/ui/moves/moves-sru-moved-field.stderr
new file mode 100644
index 0000000..aac399e
--- /dev/null
+++ b/src/test/ui/moves/moves-sru-moved-field.stderr
@@ -0,0 +1,13 @@
+error[E0382]: use of moved value: `f.moved`
+  --> $DIR/moves-sru-moved-field.rs:20:37
+   |
+LL |     let _b = Foo {noncopyable: g, ..f};
+   |                                     - value moved here
+LL |     let _c = Foo {noncopyable: h, ..f};
+   |                                     ^ value used here after move
+   |
+   = note: move occurs because `f.moved` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/multiple-main-2.rs b/src/test/ui/multiple-main-2.rs
new file mode 100644
index 0000000..6bae664
--- /dev/null
+++ b/src/test/ui/multiple-main-2.rs
@@ -0,0 +1,9 @@
+#![feature(main)]
+
+#[main]
+fn bar() {
+}
+
+#[main]
+fn foo() { //~ ERROR multiple functions with a #[main] attribute
+}
diff --git a/src/test/ui/multiple-main-2.stderr b/src/test/ui/multiple-main-2.stderr
new file mode 100644
index 0000000..ae33e01
--- /dev/null
+++ b/src/test/ui/multiple-main-2.stderr
@@ -0,0 +1,14 @@
+error[E0137]: multiple functions with a #[main] attribute
+  --> $DIR/multiple-main-2.rs:8:1
+   |
+LL | / fn bar() {
+LL | | }
+   | |_- first #[main] function
+...
+LL | / fn foo() {
+LL | | }
+   | |_^ additional #[main] function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0137`.
diff --git a/src/test/ui/multiple-main-3.rs b/src/test/ui/multiple-main-3.rs
new file mode 100644
index 0000000..dbcf1ef
--- /dev/null
+++ b/src/test/ui/multiple-main-3.rs
@@ -0,0 +1,11 @@
+#![feature(main)]
+
+#[main]
+fn main1() {
+}
+
+mod foo {
+    #[main]
+    fn main2() { //~ ERROR multiple functions with a #[main] attribute
+    }
+}
diff --git a/src/test/ui/multiple-main-3.stderr b/src/test/ui/multiple-main-3.stderr
new file mode 100644
index 0000000..b85637b
--- /dev/null
+++ b/src/test/ui/multiple-main-3.stderr
@@ -0,0 +1,14 @@
+error[E0137]: multiple functions with a #[main] attribute
+  --> $DIR/multiple-main-3.rs:9:5
+   |
+LL | / fn main1() {
+LL | | }
+   | |_- first #[main] function
+...
+LL | /     fn main2() {
+LL | |     }
+   | |_____^ additional #[main] function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0137`.
diff --git a/src/test/ui/multiple-plugin-registrars.rs b/src/test/ui/multiple-plugin-registrars.rs
new file mode 100644
index 0000000..d211204
--- /dev/null
+++ b/src/test/ui/multiple-plugin-registrars.rs
@@ -0,0 +1,12 @@
+// error-pattern: multiple plugin registration functions found
+
+#![feature(plugin_registrar)]
+
+// the registration function isn't typechecked yet
+#[plugin_registrar]
+pub fn one() {}
+
+#[plugin_registrar]
+pub fn two() {}
+
+fn main() {}
diff --git a/src/test/ui/multiple-plugin-registrars.stderr b/src/test/ui/multiple-plugin-registrars.stderr
new file mode 100644
index 0000000..0e83798
--- /dev/null
+++ b/src/test/ui/multiple-plugin-registrars.stderr
@@ -0,0 +1,15 @@
+error: multiple plugin registration functions found
+   |
+note: one is here
+  --> $DIR/multiple-plugin-registrars.rs:7:1
+   |
+LL | pub fn one() {}
+   | ^^^^^^^^^^^^^^^
+note: one is here
+  --> $DIR/multiple-plugin-registrars.rs:10:1
+   |
+LL | pub fn two() {}
+   | ^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/mut/mut-cant-alias.nll.stderr b/src/test/ui/mut/mut-cant-alias.nll.stderr
new file mode 100644
index 0000000..d56e45d
--- /dev/null
+++ b/src/test/ui/mut/mut-cant-alias.nll.stderr
@@ -0,0 +1,13 @@
+error[E0499]: cannot borrow `b` as mutable more than once at a time
+  --> $DIR/mut-cant-alias.rs:9:20
+   |
+LL |     let b1 = &mut *b;
+   |                    - first mutable borrow occurs here
+LL |     let b2 = &mut *b;
+   |                    ^ second mutable borrow occurs here
+LL |     b1.use_mut();
+   |     -- first borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/mut/mut-cant-alias.rs b/src/test/ui/mut/mut-cant-alias.rs
new file mode 100644
index 0000000..9146b93
--- /dev/null
+++ b/src/test/ui/mut/mut-cant-alias.rs
@@ -0,0 +1,14 @@
+use std::cell::RefCell;
+
+
+
+fn main() {
+    let m = RefCell::new(0);
+    let mut b = m.borrow_mut();
+    let b1 = &mut *b;
+    let b2 = &mut *b; //~ ERROR cannot borrow
+    b1.use_mut();
+}
+
+trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { }  }
+impl<T> Fake for T { }
diff --git a/src/test/ui/mut/mut-cant-alias.stderr b/src/test/ui/mut/mut-cant-alias.stderr
new file mode 100644
index 0000000..5fc194b
--- /dev/null
+++ b/src/test/ui/mut/mut-cant-alias.stderr
@@ -0,0 +1,14 @@
+error[E0499]: cannot borrow `b` as mutable more than once at a time
+  --> $DIR/mut-cant-alias.rs:9:20
+   |
+LL |     let b1 = &mut *b;
+   |                    - first mutable borrow occurs here
+LL |     let b2 = &mut *b;
+   |                    ^ second mutable borrow occurs here
+LL |     b1.use_mut();
+LL | }
+   | - first borrow ends here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/mut/mut-cross-borrowing.rs b/src/test/ui/mut/mut-cross-borrowing.rs
new file mode 100644
index 0000000..63e49c2
--- /dev/null
+++ b/src/test/ui/mut/mut-cross-borrowing.rs
@@ -0,0 +1,8 @@
+#![feature(box_syntax)]
+
+fn f(_: &mut isize) {}
+
+fn main() {
+    let mut x: Box<_> = box 3;
+    f(x)    //~ ERROR mismatched types
+}
diff --git a/src/test/ui/mut/mut-cross-borrowing.stderr b/src/test/ui/mut/mut-cross-borrowing.stderr
new file mode 100644
index 0000000..e2eea19
--- /dev/null
+++ b/src/test/ui/mut/mut-cross-borrowing.stderr
@@ -0,0 +1,15 @@
+error[E0308]: mismatched types
+  --> $DIR/mut-cross-borrowing.rs:7:7
+   |
+LL |     f(x)
+   |       ^
+   |       |
+   |       expected &mut isize, found struct `std::boxed::Box`
+   |       help: consider mutably borrowing here: `&mut x`
+   |
+   = note: expected type `&mut isize`
+              found type `std::boxed::Box<{integer}>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/mut/mut-pattern-internal-mutability.ast.nll.stderr b/src/test/ui/mut/mut-pattern-internal-mutability.ast.nll.stderr
new file mode 100644
index 0000000..0db3201
--- /dev/null
+++ b/src/test/ui/mut/mut-pattern-internal-mutability.ast.nll.stderr
@@ -0,0 +1,26 @@
+error[E0384]: cannot assign twice to immutable variable `x`
+  --> $DIR/mut-pattern-internal-mutability.rs:8:5
+   |
+LL |     let &mut x = foo;
+   |              -
+   |              |
+   |              first assignment to `x`
+   |              help: make this binding mutable: `mut x`
+LL |     x += 1;
+   |     ^^^^^^ cannot assign twice to immutable variable
+
+error[E0506]: cannot assign to `*foo` because it is borrowed
+  --> $DIR/mut-pattern-internal-mutability.rs:17:5
+   |
+LL |     let &mut ref x = foo;
+   |              ----- borrow of `*foo` occurs here
+LL |     *foo += 1;
+   |     ^^^^^^^^^ assignment to borrowed `*foo` occurs here
+LL |
+LL |     drop(x);
+   |          - borrow later used here
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0384, E0506.
+For more information about an error, try `rustc --explain E0384`.
diff --git a/src/test/ui/mut/mut-pattern-internal-mutability.ast.stderr b/src/test/ui/mut/mut-pattern-internal-mutability.ast.stderr
new file mode 100644
index 0000000..da33cdf
--- /dev/null
+++ b/src/test/ui/mut/mut-pattern-internal-mutability.ast.stderr
@@ -0,0 +1,20 @@
+error[E0384]: cannot assign twice to immutable variable `x`
+  --> $DIR/mut-pattern-internal-mutability.rs:8:5
+   |
+LL |     let &mut x = foo;
+   |              - first assignment to `x`
+LL |     x += 1;
+   |     ^^^^^^ cannot assign twice to immutable variable
+
+error[E0506]: cannot assign to `*foo` because it is borrowed
+  --> $DIR/mut-pattern-internal-mutability.rs:17:5
+   |
+LL |     let &mut ref x = foo;
+   |              ----- borrow of `*foo` occurs here
+LL |     *foo += 1;
+   |     ^^^^^^^^^ assignment to borrowed `*foo` occurs here
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0384, E0506.
+For more information about an error, try `rustc --explain E0384`.
diff --git a/src/test/ui/mut/mut-pattern-internal-mutability.mir.stderr b/src/test/ui/mut/mut-pattern-internal-mutability.mir.stderr
new file mode 100644
index 0000000..0db3201
--- /dev/null
+++ b/src/test/ui/mut/mut-pattern-internal-mutability.mir.stderr
@@ -0,0 +1,26 @@
+error[E0384]: cannot assign twice to immutable variable `x`
+  --> $DIR/mut-pattern-internal-mutability.rs:8:5
+   |
+LL |     let &mut x = foo;
+   |              -
+   |              |
+   |              first assignment to `x`
+   |              help: make this binding mutable: `mut x`
+LL |     x += 1;
+   |     ^^^^^^ cannot assign twice to immutable variable
+
+error[E0506]: cannot assign to `*foo` because it is borrowed
+  --> $DIR/mut-pattern-internal-mutability.rs:17:5
+   |
+LL |     let &mut ref x = foo;
+   |              ----- borrow of `*foo` occurs here
+LL |     *foo += 1;
+   |     ^^^^^^^^^ assignment to borrowed `*foo` occurs here
+LL |
+LL |     drop(x);
+   |          - borrow later used here
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0384, E0506.
+For more information about an error, try `rustc --explain E0384`.
diff --git a/src/test/ui/mut/mut-pattern-internal-mutability.rs b/src/test/ui/mut/mut-pattern-internal-mutability.rs
new file mode 100644
index 0000000..ffad623
--- /dev/null
+++ b/src/test/ui/mut/mut-pattern-internal-mutability.rs
@@ -0,0 +1,20 @@
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+fn main() {
+    let foo = &mut 1;
+
+    let &mut x = foo;
+    x += 1; //[ast]~ ERROR cannot assign twice to immutable variable
+            //[mir]~^ ERROR cannot assign twice to immutable variable `x`
+
+    // explicitly mut-ify internals
+    let &mut mut x = foo;
+    x += 1;
+
+    // check borrowing is detected successfully
+    let &mut ref x = foo;
+    *foo += 1; //[ast]~ ERROR cannot assign to `*foo` because it is borrowed
+    //[mir]~^ ERROR cannot assign to `*foo` because it is borrowed
+    drop(x);
+}
diff --git a/src/test/ui/mut/mut-pattern-mismatched.rs b/src/test/ui/mut/mut-pattern-mismatched.rs
new file mode 100644
index 0000000..17bf754
--- /dev/null
+++ b/src/test/ui/mut/mut-pattern-mismatched.rs
@@ -0,0 +1,20 @@
+fn main() {
+    let foo = &mut 1;
+
+    // (separate lines to ensure the spans are accurate)
+
+     let &_ //~  ERROR mismatched types
+            //~| expected type `&mut {integer}`
+            //~| found type `&_`
+            //~| types differ in mutability
+        = foo;
+    let &mut _ = foo;
+
+    let bar = &1;
+    let &_ = bar;
+    let &mut _ //~  ERROR mismatched types
+               //~| expected type `&{integer}`
+               //~| found type `&mut _`
+               //~| types differ in mutability
+         = bar;
+}
diff --git a/src/test/ui/mut/mut-pattern-mismatched.stderr b/src/test/ui/mut/mut-pattern-mismatched.stderr
new file mode 100644
index 0000000..d1adc99
--- /dev/null
+++ b/src/test/ui/mut/mut-pattern-mismatched.stderr
@@ -0,0 +1,21 @@
+error[E0308]: mismatched types
+  --> $DIR/mut-pattern-mismatched.rs:6:10
+   |
+LL |      let &_
+   |          ^^ types differ in mutability
+   |
+   = note: expected type `&mut {integer}`
+              found type `&_`
+
+error[E0308]: mismatched types
+  --> $DIR/mut-pattern-mismatched.rs:15:9
+   |
+LL |     let &mut _
+   |         ^^^^^^ types differ in mutability
+   |
+   = note: expected type `&{integer}`
+              found type `&mut _`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/mut/mut-ref.rs b/src/test/ui/mut/mut-ref.rs
new file mode 100644
index 0000000..80990b2
--- /dev/null
+++ b/src/test/ui/mut/mut-ref.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let mut ref x = 10; //~ ERROR the order of `mut` and `ref` is incorrect
+    let ref mut y = 11;
+}
diff --git a/src/test/ui/mut/mut-ref.stderr b/src/test/ui/mut/mut-ref.stderr
new file mode 100644
index 0000000..e6d4901
--- /dev/null
+++ b/src/test/ui/mut/mut-ref.stderr
@@ -0,0 +1,8 @@
+error: the order of `mut` and `ref` is incorrect
+  --> $DIR/mut-ref.rs:2:9
+   |
+LL |     let mut ref x = 10;
+   |         ^^^^^^^ help: try switching the order: `ref mut`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/mut/mut-suggestion.nll.stderr b/src/test/ui/mut/mut-suggestion.nll.stderr
new file mode 100644
index 0000000..61656db
--- /dev/null
+++ b/src/test/ui/mut/mut-suggestion.nll.stderr
@@ -0,0 +1,21 @@
+error[E0596]: cannot borrow `arg` as mutable, as it is not declared as mutable
+  --> $DIR/mut-suggestion.rs:12:5
+   |
+LL | fn func(arg: S) {
+   |         --- help: consider changing this to be mutable: `mut arg`
+...
+LL |     arg.mutate();
+   |     ^^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow `local` as mutable, as it is not declared as mutable
+  --> $DIR/mut-suggestion.rs:21:5
+   |
+LL |     let local = S;
+   |         ----- help: consider changing this to be mutable: `mut local`
+...
+LL |     local.mutate();
+   |     ^^^^^ cannot borrow as mutable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/mut/mut-suggestion.rs b/src/test/ui/mut/mut-suggestion.rs
new file mode 100644
index 0000000..0d95a8b
--- /dev/null
+++ b/src/test/ui/mut/mut-suggestion.rs
@@ -0,0 +1,24 @@
+#[derive(Copy, Clone)]
+struct S;
+
+impl S {
+    fn mutate(&mut self) {
+    }
+}
+
+fn func(arg: S) {
+    //~^ HELP make this binding mutable
+    //~| SUGGESTION mut arg
+    arg.mutate();
+    //~^ ERROR cannot borrow immutable argument
+    //~| cannot borrow mutably
+}
+
+fn main() {
+    let local = S;
+    //~^ HELP make this binding mutable
+    //~| SUGGESTION mut local
+    local.mutate();
+    //~^ ERROR cannot borrow immutable local variable
+    //~| cannot borrow mutably
+}
diff --git a/src/test/ui/mut/mut-suggestion.stderr b/src/test/ui/mut/mut-suggestion.stderr
new file mode 100644
index 0000000..1998ec1e
--- /dev/null
+++ b/src/test/ui/mut/mut-suggestion.stderr
@@ -0,0 +1,21 @@
+error[E0596]: cannot borrow immutable argument `arg` as mutable
+  --> $DIR/mut-suggestion.rs:12:5
+   |
+LL | fn func(arg: S) {
+   |         --- help: make this binding mutable: `mut arg`
+...
+LL |     arg.mutate();
+   |     ^^^ cannot borrow mutably
+
+error[E0596]: cannot borrow immutable local variable `local` as mutable
+  --> $DIR/mut-suggestion.rs:21:5
+   |
+LL |     let local = S;
+   |         ----- help: make this binding mutable: `mut local`
+...
+LL |     local.mutate();
+   |     ^^^^^ cannot borrow mutably
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/mut/mutable-class-fields-2.nll.stderr b/src/test/ui/mut/mutable-class-fields-2.nll.stderr
new file mode 100644
index 0000000..15323ce
--- /dev/null
+++ b/src/test/ui/mut/mutable-class-fields-2.nll.stderr
@@ -0,0 +1,11 @@
+error[E0594]: cannot assign to `self.how_hungry` which is behind a `&` reference
+  --> $DIR/mutable-class-fields-2.rs:9:5
+   |
+LL |   pub fn eat(&self) {
+   |              ----- help: consider changing this to be a mutable reference: `&mut self`
+LL |     self.how_hungry -= 5;
+   |     ^^^^^^^^^^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be written
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/mut/mutable-class-fields-2.rs b/src/test/ui/mut/mutable-class-fields-2.rs
new file mode 100644
index 0000000..30e54df
--- /dev/null
+++ b/src/test/ui/mut/mutable-class-fields-2.rs
@@ -0,0 +1,24 @@
+struct Cat {
+  meows : usize,
+
+  how_hungry : isize,
+}
+
+impl Cat {
+  pub fn eat(&self) {
+    self.how_hungry -= 5; //~ ERROR cannot assign
+  }
+
+}
+
+fn cat(in_x : usize, in_y : isize) -> Cat {
+    Cat {
+        meows: in_x,
+        how_hungry: in_y
+    }
+}
+
+fn main() {
+  let nyan : Cat = cat(52, 99);
+  nyan.eat();
+}
diff --git a/src/test/ui/mut/mutable-class-fields-2.stderr b/src/test/ui/mut/mutable-class-fields-2.stderr
new file mode 100644
index 0000000..b0dea30
--- /dev/null
+++ b/src/test/ui/mut/mutable-class-fields-2.stderr
@@ -0,0 +1,11 @@
+error[E0594]: cannot assign to field `self.how_hungry` of immutable binding
+  --> $DIR/mutable-class-fields-2.rs:9:5
+   |
+LL |   pub fn eat(&self) {
+   |              ----- use `&mut self` here to make mutable
+LL |     self.how_hungry -= 5;
+   |     ^^^^^^^^^^^^^^^^^^^^ cannot mutably borrow field of immutable binding
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/mut/mutable-class-fields.ast.nll.stderr b/src/test/ui/mut/mutable-class-fields.ast.nll.stderr
new file mode 100644
index 0000000..e243fb7
--- /dev/null
+++ b/src/test/ui/mut/mutable-class-fields.ast.nll.stderr
@@ -0,0 +1,11 @@
+error[E0594]: cannot assign to `nyan.how_hungry`, as `nyan` is not declared as mutable
+  --> $DIR/mutable-class-fields.rs:18:3
+   |
+LL |   let nyan : Cat = cat(52, 99);
+   |       ---- help: consider changing this to be mutable: `mut nyan`
+LL |   nyan.how_hungry = 0;
+   |   ^^^^^^^^^^^^^^^^^^^ cannot assign
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/mut/mutable-class-fields.ast.stderr b/src/test/ui/mut/mutable-class-fields.ast.stderr
new file mode 100644
index 0000000..95a9284
--- /dev/null
+++ b/src/test/ui/mut/mutable-class-fields.ast.stderr
@@ -0,0 +1,11 @@
+error[E0594]: cannot assign to field `nyan.how_hungry` of immutable binding
+  --> $DIR/mutable-class-fields.rs:18:3
+   |
+LL |   let nyan : Cat = cat(52, 99);
+   |       ---- help: make this binding mutable: `mut nyan`
+LL |   nyan.how_hungry = 0;
+   |   ^^^^^^^^^^^^^^^^^^^ cannot mutably borrow field of immutable binding
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/mut/mutable-class-fields.mir.stderr b/src/test/ui/mut/mutable-class-fields.mir.stderr
new file mode 100644
index 0000000..e243fb7
--- /dev/null
+++ b/src/test/ui/mut/mutable-class-fields.mir.stderr
@@ -0,0 +1,11 @@
+error[E0594]: cannot assign to `nyan.how_hungry`, as `nyan` is not declared as mutable
+  --> $DIR/mutable-class-fields.rs:18:3
+   |
+LL |   let nyan : Cat = cat(52, 99);
+   |       ---- help: consider changing this to be mutable: `mut nyan`
+LL |   nyan.how_hungry = 0;
+   |   ^^^^^^^^^^^^^^^^^^^ cannot assign
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/mut/mutable-class-fields.rs b/src/test/ui/mut/mutable-class-fields.rs
new file mode 100644
index 0000000..2a729a5
--- /dev/null
+++ b/src/test/ui/mut/mutable-class-fields.rs
@@ -0,0 +1,20 @@
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+struct Cat {
+  meows : usize,
+  how_hungry : isize,
+}
+
+fn cat(in_x : usize, in_y : isize) -> Cat {
+    Cat {
+        meows: in_x,
+        how_hungry: in_y
+    }
+}
+
+fn main() {
+  let nyan : Cat = cat(52, 99);
+  nyan.how_hungry = 0; //[ast]~ ERROR cannot assign
+  //[mir]~^ ERROR cannot assign
+}
diff --git a/src/test/ui/mut/mutable-enum-indirect.rs b/src/test/ui/mut/mutable-enum-indirect.rs
new file mode 100644
index 0000000..611ff0d
--- /dev/null
+++ b/src/test/ui/mut/mutable-enum-indirect.rs
@@ -0,0 +1,19 @@
+// Tests that an `&` pointer to something inherently mutable is itself
+// to be considered mutable.
+
+#![feature(optin_builtin_traits)]
+
+use std::marker::Sync;
+
+struct NoSync;
+impl !Sync for NoSync {}
+
+enum Foo { A(NoSync) }
+
+fn bar<T: Sync>(_: T) {}
+
+fn main() {
+    let x = Foo::A(NoSync);
+    bar(&x);
+    //~^ ERROR `NoSync` cannot be shared between threads safely [E0277]
+}
diff --git a/src/test/ui/mut/mutable-enum-indirect.stderr b/src/test/ui/mut/mutable-enum-indirect.stderr
new file mode 100644
index 0000000..1268e48
--- /dev/null
+++ b/src/test/ui/mut/mutable-enum-indirect.stderr
@@ -0,0 +1,18 @@
+error[E0277]: `NoSync` cannot be shared between threads safely
+  --> $DIR/mutable-enum-indirect.rs:17:5
+   |
+LL |     bar(&x);
+   |     ^^^ `NoSync` cannot be shared between threads safely
+   |
+   = help: within `&Foo`, the trait `std::marker::Sync` is not implemented for `NoSync`
+   = note: required because it appears within the type `Foo`
+   = note: required because it appears within the type `&Foo`
+note: required by `bar`
+  --> $DIR/mutable-enum-indirect.rs:13:1
+   |
+LL | fn bar<T: Sync>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/mut/no-mut-lint-for-desugared-mut.rs b/src/test/ui/mut/no-mut-lint-for-desugared-mut.rs
new file mode 100644
index 0000000..419d580
--- /dev/null
+++ b/src/test/ui/mut/no-mut-lint-for-desugared-mut.rs
@@ -0,0 +1,8 @@
+// run-pass
+
+#![deny(unused_mut)]
+#![allow(unreachable_code)]
+
+fn main() {
+    for _ in { return (); 0..3 } {} // ok
+}
diff --git a/src/test/ui/mutexguard-sync.rs b/src/test/ui/mutexguard-sync.rs
new file mode 100644
index 0000000..8e13700
--- /dev/null
+++ b/src/test/ui/mutexguard-sync.rs
@@ -0,0 +1,13 @@
+// MutexGuard<Cell<i32>> must not be Sync, that would be unsound.
+use std::sync::Mutex;
+use std::cell::Cell;
+
+fn test_sync<T: Sync>(_t: T) {}
+
+fn main()
+{
+    let m = Mutex::new(Cell::new(0i32));
+    let guard = m.lock().unwrap();
+    test_sync(guard);
+    //~^ ERROR `std::cell::Cell<i32>` cannot be shared between threads safely [E0277]
+}
diff --git a/src/test/ui/mutexguard-sync.stderr b/src/test/ui/mutexguard-sync.stderr
new file mode 100644
index 0000000..d1f7d13
--- /dev/null
+++ b/src/test/ui/mutexguard-sync.stderr
@@ -0,0 +1,17 @@
+error[E0277]: `std::cell::Cell<i32>` cannot be shared between threads safely
+  --> $DIR/mutexguard-sync.rs:11:5
+   |
+LL |     test_sync(guard);
+   |     ^^^^^^^^^ `std::cell::Cell<i32>` cannot be shared between threads safely
+   |
+   = help: the trait `std::marker::Sync` is not implemented for `std::cell::Cell<i32>`
+   = note: required because of the requirements on the impl of `std::marker::Sync` for `std::sync::MutexGuard<'_, std::cell::Cell<i32>>`
+note: required by `test_sync`
+  --> $DIR/mutexguard-sync.rs:5:1
+   |
+LL | fn test_sync<T: Sync>(_t: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/namespace/auxiliary/namespace-mix.rs b/src/test/ui/namespace/auxiliary/namespace-mix.rs
new file mode 100644
index 0000000..fb39d29
--- /dev/null
+++ b/src/test/ui/namespace/auxiliary/namespace-mix.rs
@@ -0,0 +1,66 @@
+pub mod c {
+    pub struct S {}
+    pub struct TS();
+    pub struct US;
+    pub enum E {
+        V {},
+        TV(),
+        UV,
+    }
+
+    pub struct Item;
+}
+
+pub mod xm1 {
+    pub use ::c::*;
+    pub type S = ::c::Item;
+}
+pub mod xm2 {
+    pub use ::c::*;
+    pub const S: ::c::Item = ::c::Item;
+}
+
+pub mod xm3 {
+    pub use ::c::*;
+    pub type TS = ::c::Item;
+}
+pub mod xm4 {
+    pub use ::c::*;
+    pub const TS: ::c::Item = ::c::Item;
+}
+
+pub mod xm5 {
+    pub use ::c::*;
+    pub type US = ::c::Item;
+}
+pub mod xm6 {
+    pub use ::c::*;
+    pub const US: ::c::Item = ::c::Item;
+}
+
+pub mod xm7 {
+    pub use ::c::E::*;
+    pub type V = ::c::Item;
+}
+pub mod xm8 {
+    pub use ::c::E::*;
+    pub const V: ::c::Item = ::c::Item;
+}
+
+pub mod xm9 {
+    pub use ::c::E::*;
+    pub type TV = ::c::Item;
+}
+pub mod xmA {
+    pub use ::c::E::*;
+    pub const TV: ::c::Item = ::c::Item;
+}
+
+pub mod xmB {
+    pub use ::c::E::*;
+    pub type UV = ::c::Item;
+}
+pub mod xmC {
+    pub use ::c::E::*;
+    pub const UV: ::c::Item = ::c::Item;
+}
diff --git a/src/test/ui/namespace/auxiliary/namespaced_enums.rs b/src/test/ui/namespace/auxiliary/namespaced_enums.rs
new file mode 100644
index 0000000..d3548c7
--- /dev/null
+++ b/src/test/ui/namespace/auxiliary/namespaced_enums.rs
@@ -0,0 +1,10 @@
+pub enum Foo {
+    A,
+    B(isize),
+    C { a: isize },
+}
+
+impl Foo {
+    pub fn foo() {}
+    pub fn bar(&self) {}
+}
diff --git a/src/test/ui/namespace/namespace-mix.rs b/src/test/ui/namespace/namespace-mix.rs
new file mode 100644
index 0000000..b0f7e3c
--- /dev/null
+++ b/src/test/ui/namespace/namespace-mix.rs
@@ -0,0 +1,155 @@
+// aux-build:namespace-mix.rs
+
+extern crate namespace_mix;
+use namespace_mix::*;
+
+mod c {
+    pub struct S {}
+    pub struct TS();
+    pub struct US;
+    pub enum E {
+        V {},
+        TV(),
+        UV,
+    }
+
+    pub struct Item;
+}
+
+// Use something emitting the type argument name, e.g., unsatisfied bound.
+trait Impossible {}
+fn check<T: Impossible>(_: T) {}
+
+mod m1 {
+    pub use ::c::*;
+    pub type S = ::c::Item;
+}
+mod m2 {
+    pub use ::c::*;
+    pub const S: ::c::Item = ::c::Item;
+}
+
+fn f12() {
+    check(m1::S{}); //~ ERROR c::Item
+    check(m1::S); //~ ERROR expected value, found type alias `m1::S`
+    check(m2::S{}); //~ ERROR c::S
+    check(m2::S); //~ ERROR c::Item
+}
+fn xf12() {
+    check(xm1::S{}); //~ ERROR c::Item
+    check(xm1::S); //~ ERROR expected value, found type alias `xm1::S`
+    check(xm2::S{}); //~ ERROR c::S
+    check(xm2::S); //~ ERROR c::Item
+}
+
+mod m3 {
+    pub use ::c::*;
+    pub type TS = ::c::Item;
+}
+mod m4 {
+    pub use ::c::*;
+    pub const TS: ::c::Item = ::c::Item;
+}
+
+fn f34() {
+    check(m3::TS{}); //~ ERROR c::Item
+    check(m3::TS); //~ ERROR c::TS
+    check(m4::TS{}); //~ ERROR c::TS
+    check(m4::TS); //~ ERROR c::Item
+}
+fn xf34() {
+    check(xm3::TS{}); //~ ERROR c::Item
+    check(xm3::TS); //~ ERROR c::TS
+    check(xm4::TS{}); //~ ERROR c::TS
+    check(xm4::TS); //~ ERROR c::Item
+}
+
+mod m5 {
+    pub use ::c::*;
+    pub type US = ::c::Item;
+}
+mod m6 {
+    pub use ::c::*;
+    pub const US: ::c::Item = ::c::Item;
+}
+
+fn f56() {
+    check(m5::US{}); //~ ERROR c::Item
+    check(m5::US); //~ ERROR c::US
+    check(m6::US{}); //~ ERROR c::US
+    check(m6::US); //~ ERROR c::Item
+}
+fn xf56() {
+    check(xm5::US{}); //~ ERROR c::Item
+    check(xm5::US); //~ ERROR c::US
+    check(xm6::US{}); //~ ERROR c::US
+    check(xm6::US); //~ ERROR c::Item
+}
+
+mod m7 {
+    pub use ::c::E::*;
+    pub type V = ::c::Item;
+}
+mod m8 {
+    pub use ::c::E::*;
+    pub const V: ::c::Item = ::c::Item;
+}
+
+fn f78() {
+    check(m7::V{}); //~ ERROR c::Item
+    check(m7::V); //~ ERROR expected value, found struct variant `m7::V`
+    check(m8::V{}); //~ ERROR c::E
+    check(m8::V); //~ ERROR c::Item
+}
+fn xf78() {
+    check(xm7::V{}); //~ ERROR c::Item
+    check(xm7::V); //~ ERROR expected value, found struct variant `xm7::V`
+    check(xm8::V{}); //~ ERROR c::E
+    check(xm8::V); //~ ERROR c::Item
+}
+
+mod m9 {
+    pub use ::c::E::*;
+    pub type TV = ::c::Item;
+}
+mod mA {
+    pub use ::c::E::*;
+    pub const TV: ::c::Item = ::c::Item;
+}
+
+fn f9A() {
+    check(m9::TV{}); //~ ERROR c::Item
+    check(m9::TV); //~ ERROR c::E
+    check(mA::TV{}); //~ ERROR c::E
+    check(mA::TV); //~ ERROR c::Item
+}
+fn xf9A() {
+    check(xm9::TV{}); //~ ERROR c::Item
+    check(xm9::TV); //~ ERROR c::E
+    check(xmA::TV{}); //~ ERROR c::E
+    check(xmA::TV); //~ ERROR c::Item
+}
+
+mod mB {
+    pub use ::c::E::*;
+    pub type UV = ::c::Item;
+}
+mod mC {
+    pub use ::c::E::*;
+    pub const UV: ::c::Item = ::c::Item;
+}
+
+fn fBC() {
+    check(mB::UV{}); //~ ERROR c::Item
+    check(mB::UV); //~ ERROR c::E
+    check(mC::UV{}); //~ ERROR c::E
+    check(mC::UV); //~ ERROR c::Item
+}
+fn xfBC() {
+    check(xmB::UV{}); //~ ERROR c::Item
+    check(xmB::UV); //~ ERROR c::E
+    check(xmC::UV{}); //~ ERROR c::E
+    check(xmC::UV); //~ ERROR c::Item
+}
+
+fn main() {}
diff --git a/src/test/ui/namespace/namespace-mix.stderr b/src/test/ui/namespace/namespace-mix.stderr
new file mode 100644
index 0000000..99fa3b9
--- /dev/null
+++ b/src/test/ui/namespace/namespace-mix.stderr
@@ -0,0 +1,600 @@
+error[E0423]: expected value, found type alias `m1::S`
+  --> $DIR/namespace-mix.rs:34:11
+   |
+LL |     check(m1::S);
+   |           ^^^^^
+   |
+   = note: can't use a type alias as a constructor
+help: a tuple struct with a similar name exists
+   |
+LL |     check(m1::TS);
+   |               ^^
+help: possible better candidates are found in other modules, you can import them into scope
+   |
+LL | use m2::S;
+   |
+LL | use namespace_mix::xm2::S;
+   |
+
+error[E0423]: expected value, found type alias `xm1::S`
+  --> $DIR/namespace-mix.rs:40:11
+   |
+LL |     check(xm1::S);
+   |           ^^^^^^
+   |
+   = note: can't use a type alias as a constructor
+help: a tuple struct with a similar name exists
+   |
+LL |     check(xm1::TS);
+   |                ^^
+help: possible better candidates are found in other modules, you can import them into scope
+   |
+LL | use m2::S;
+   |
+LL | use namespace_mix::xm2::S;
+   |
+
+error[E0423]: expected value, found struct variant `m7::V`
+  --> $DIR/namespace-mix.rs:100:11
+   |
+LL |     check(m7::V);
+   |           ^^^^^ did you mean `m7::V { /* fields */ }`?
+help: a tuple variant with a similar name exists
+   |
+LL |     check(m7::TV);
+   |               ^^
+help: possible better candidates are found in other modules, you can import them into scope
+   |
+LL | use m8::V;
+   |
+LL | use namespace_mix::xm8::V;
+   |
+
+error[E0423]: expected value, found struct variant `xm7::V`
+  --> $DIR/namespace-mix.rs:106:11
+   |
+LL |     check(xm7::V);
+   |           ^^^^^^ did you mean `xm7::V { /* fields */ }`?
+help: a tuple variant with a similar name exists
+   |
+LL |     check(xm7::TV);
+   |                ^^
+help: possible better candidates are found in other modules, you can import them into scope
+   |
+LL | use m8::V;
+   |
+LL | use namespace_mix::xm8::V;
+   |
+
+error[E0277]: the trait bound `c::Item: Impossible` is not satisfied
+  --> $DIR/namespace-mix.rs:33:5
+   |
+LL |     check(m1::S{});
+   |     ^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |
+note: required by `check`
+  --> $DIR/namespace-mix.rs:21:1
+   |
+LL | fn check<T: Impossible>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `c::S: Impossible` is not satisfied
+  --> $DIR/namespace-mix.rs:35:5
+   |
+LL |     check(m2::S{});
+   |     ^^^^^ the trait `Impossible` is not implemented for `c::S`
+   |
+note: required by `check`
+  --> $DIR/namespace-mix.rs:21:1
+   |
+LL | fn check<T: Impossible>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `c::Item: Impossible` is not satisfied
+  --> $DIR/namespace-mix.rs:36:5
+   |
+LL |     check(m2::S);
+   |     ^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |
+note: required by `check`
+  --> $DIR/namespace-mix.rs:21:1
+   |
+LL | fn check<T: Impossible>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied
+  --> $DIR/namespace-mix.rs:39:5
+   |
+LL |     check(xm1::S{});
+   |     ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |
+note: required by `check`
+  --> $DIR/namespace-mix.rs:21:1
+   |
+LL | fn check<T: Impossible>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `namespace_mix::c::S: Impossible` is not satisfied
+  --> $DIR/namespace-mix.rs:41:5
+   |
+LL |     check(xm2::S{});
+   |     ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::S`
+   |
+note: required by `check`
+  --> $DIR/namespace-mix.rs:21:1
+   |
+LL | fn check<T: Impossible>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied
+  --> $DIR/namespace-mix.rs:42:5
+   |
+LL |     check(xm2::S);
+   |     ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |
+note: required by `check`
+  --> $DIR/namespace-mix.rs:21:1
+   |
+LL | fn check<T: Impossible>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `c::Item: Impossible` is not satisfied
+  --> $DIR/namespace-mix.rs:55:5
+   |
+LL |     check(m3::TS{});
+   |     ^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |
+note: required by `check`
+  --> $DIR/namespace-mix.rs:21:1
+   |
+LL | fn check<T: Impossible>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `fn() -> c::TS {c::TS}: Impossible` is not satisfied
+  --> $DIR/namespace-mix.rs:56:5
+   |
+LL |     check(m3::TS);
+   |     ^^^^^ the trait `Impossible` is not implemented for `fn() -> c::TS {c::TS}`
+   |
+note: required by `check`
+  --> $DIR/namespace-mix.rs:21:1
+   |
+LL | fn check<T: Impossible>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `c::TS: Impossible` is not satisfied
+  --> $DIR/namespace-mix.rs:57:5
+   |
+LL |     check(m4::TS{});
+   |     ^^^^^ the trait `Impossible` is not implemented for `c::TS`
+   |
+note: required by `check`
+  --> $DIR/namespace-mix.rs:21:1
+   |
+LL | fn check<T: Impossible>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `c::Item: Impossible` is not satisfied
+  --> $DIR/namespace-mix.rs:58:5
+   |
+LL |     check(m4::TS);
+   |     ^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |
+note: required by `check`
+  --> $DIR/namespace-mix.rs:21:1
+   |
+LL | fn check<T: Impossible>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied
+  --> $DIR/namespace-mix.rs:61:5
+   |
+LL |     check(xm3::TS{});
+   |     ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |
+note: required by `check`
+  --> $DIR/namespace-mix.rs:21:1
+   |
+LL | fn check<T: Impossible>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `fn() -> namespace_mix::c::TS {namespace_mix::c::TS}: Impossible` is not satisfied
+  --> $DIR/namespace-mix.rs:62:5
+   |
+LL |     check(xm3::TS);
+   |     ^^^^^ the trait `Impossible` is not implemented for `fn() -> namespace_mix::c::TS {namespace_mix::c::TS}`
+   |
+note: required by `check`
+  --> $DIR/namespace-mix.rs:21:1
+   |
+LL | fn check<T: Impossible>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `namespace_mix::c::TS: Impossible` is not satisfied
+  --> $DIR/namespace-mix.rs:63:5
+   |
+LL |     check(xm4::TS{});
+   |     ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::TS`
+   |
+note: required by `check`
+  --> $DIR/namespace-mix.rs:21:1
+   |
+LL | fn check<T: Impossible>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied
+  --> $DIR/namespace-mix.rs:64:5
+   |
+LL |     check(xm4::TS);
+   |     ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |
+note: required by `check`
+  --> $DIR/namespace-mix.rs:21:1
+   |
+LL | fn check<T: Impossible>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `c::Item: Impossible` is not satisfied
+  --> $DIR/namespace-mix.rs:77:5
+   |
+LL |     check(m5::US{});
+   |     ^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |
+note: required by `check`
+  --> $DIR/namespace-mix.rs:21:1
+   |
+LL | fn check<T: Impossible>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `c::US: Impossible` is not satisfied
+  --> $DIR/namespace-mix.rs:78:5
+   |
+LL |     check(m5::US);
+   |     ^^^^^ the trait `Impossible` is not implemented for `c::US`
+   |
+note: required by `check`
+  --> $DIR/namespace-mix.rs:21:1
+   |
+LL | fn check<T: Impossible>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `c::US: Impossible` is not satisfied
+  --> $DIR/namespace-mix.rs:79:5
+   |
+LL |     check(m6::US{});
+   |     ^^^^^ the trait `Impossible` is not implemented for `c::US`
+   |
+note: required by `check`
+  --> $DIR/namespace-mix.rs:21:1
+   |
+LL | fn check<T: Impossible>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `c::Item: Impossible` is not satisfied
+  --> $DIR/namespace-mix.rs:80:5
+   |
+LL |     check(m6::US);
+   |     ^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |
+note: required by `check`
+  --> $DIR/namespace-mix.rs:21:1
+   |
+LL | fn check<T: Impossible>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied
+  --> $DIR/namespace-mix.rs:83:5
+   |
+LL |     check(xm5::US{});
+   |     ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |
+note: required by `check`
+  --> $DIR/namespace-mix.rs:21:1
+   |
+LL | fn check<T: Impossible>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `namespace_mix::c::US: Impossible` is not satisfied
+  --> $DIR/namespace-mix.rs:84:5
+   |
+LL |     check(xm5::US);
+   |     ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::US`
+   |
+note: required by `check`
+  --> $DIR/namespace-mix.rs:21:1
+   |
+LL | fn check<T: Impossible>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `namespace_mix::c::US: Impossible` is not satisfied
+  --> $DIR/namespace-mix.rs:85:5
+   |
+LL |     check(xm6::US{});
+   |     ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::US`
+   |
+note: required by `check`
+  --> $DIR/namespace-mix.rs:21:1
+   |
+LL | fn check<T: Impossible>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied
+  --> $DIR/namespace-mix.rs:86:5
+   |
+LL |     check(xm6::US);
+   |     ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |
+note: required by `check`
+  --> $DIR/namespace-mix.rs:21:1
+   |
+LL | fn check<T: Impossible>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `c::Item: Impossible` is not satisfied
+  --> $DIR/namespace-mix.rs:99:5
+   |
+LL |     check(m7::V{});
+   |     ^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |
+note: required by `check`
+  --> $DIR/namespace-mix.rs:21:1
+   |
+LL | fn check<T: Impossible>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `c::E: Impossible` is not satisfied
+  --> $DIR/namespace-mix.rs:101:5
+   |
+LL |     check(m8::V{});
+   |     ^^^^^ the trait `Impossible` is not implemented for `c::E`
+   |
+note: required by `check`
+  --> $DIR/namespace-mix.rs:21:1
+   |
+LL | fn check<T: Impossible>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `c::Item: Impossible` is not satisfied
+  --> $DIR/namespace-mix.rs:102:5
+   |
+LL |     check(m8::V);
+   |     ^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |
+note: required by `check`
+  --> $DIR/namespace-mix.rs:21:1
+   |
+LL | fn check<T: Impossible>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied
+  --> $DIR/namespace-mix.rs:105:5
+   |
+LL |     check(xm7::V{});
+   |     ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |
+note: required by `check`
+  --> $DIR/namespace-mix.rs:21:1
+   |
+LL | fn check<T: Impossible>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `namespace_mix::c::E: Impossible` is not satisfied
+  --> $DIR/namespace-mix.rs:107:5
+   |
+LL |     check(xm8::V{});
+   |     ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E`
+   |
+note: required by `check`
+  --> $DIR/namespace-mix.rs:21:1
+   |
+LL | fn check<T: Impossible>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied
+  --> $DIR/namespace-mix.rs:108:5
+   |
+LL |     check(xm8::V);
+   |     ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |
+note: required by `check`
+  --> $DIR/namespace-mix.rs:21:1
+   |
+LL | fn check<T: Impossible>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `c::Item: Impossible` is not satisfied
+  --> $DIR/namespace-mix.rs:121:5
+   |
+LL |     check(m9::TV{});
+   |     ^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |
+note: required by `check`
+  --> $DIR/namespace-mix.rs:21:1
+   |
+LL | fn check<T: Impossible>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `fn() -> c::E {c::E::TV}: Impossible` is not satisfied
+  --> $DIR/namespace-mix.rs:122:5
+   |
+LL |     check(m9::TV);
+   |     ^^^^^ the trait `Impossible` is not implemented for `fn() -> c::E {c::E::TV}`
+   |
+note: required by `check`
+  --> $DIR/namespace-mix.rs:21:1
+   |
+LL | fn check<T: Impossible>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `c::E: Impossible` is not satisfied
+  --> $DIR/namespace-mix.rs:123:5
+   |
+LL |     check(mA::TV{});
+   |     ^^^^^ the trait `Impossible` is not implemented for `c::E`
+   |
+note: required by `check`
+  --> $DIR/namespace-mix.rs:21:1
+   |
+LL | fn check<T: Impossible>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `c::Item: Impossible` is not satisfied
+  --> $DIR/namespace-mix.rs:124:5
+   |
+LL |     check(mA::TV);
+   |     ^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |
+note: required by `check`
+  --> $DIR/namespace-mix.rs:21:1
+   |
+LL | fn check<T: Impossible>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied
+  --> $DIR/namespace-mix.rs:127:5
+   |
+LL |     check(xm9::TV{});
+   |     ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |
+note: required by `check`
+  --> $DIR/namespace-mix.rs:21:1
+   |
+LL | fn check<T: Impossible>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `fn() -> namespace_mix::c::E {namespace_mix::xm7::TV}: Impossible` is not satisfied
+  --> $DIR/namespace-mix.rs:128:5
+   |
+LL |     check(xm9::TV);
+   |     ^^^^^ the trait `Impossible` is not implemented for `fn() -> namespace_mix::c::E {namespace_mix::xm7::TV}`
+   |
+note: required by `check`
+  --> $DIR/namespace-mix.rs:21:1
+   |
+LL | fn check<T: Impossible>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `namespace_mix::c::E: Impossible` is not satisfied
+  --> $DIR/namespace-mix.rs:129:5
+   |
+LL |     check(xmA::TV{});
+   |     ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E`
+   |
+note: required by `check`
+  --> $DIR/namespace-mix.rs:21:1
+   |
+LL | fn check<T: Impossible>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied
+  --> $DIR/namespace-mix.rs:130:5
+   |
+LL |     check(xmA::TV);
+   |     ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |
+note: required by `check`
+  --> $DIR/namespace-mix.rs:21:1
+   |
+LL | fn check<T: Impossible>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `c::Item: Impossible` is not satisfied
+  --> $DIR/namespace-mix.rs:143:5
+   |
+LL |     check(mB::UV{});
+   |     ^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |
+note: required by `check`
+  --> $DIR/namespace-mix.rs:21:1
+   |
+LL | fn check<T: Impossible>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `c::E: Impossible` is not satisfied
+  --> $DIR/namespace-mix.rs:144:5
+   |
+LL |     check(mB::UV);
+   |     ^^^^^ the trait `Impossible` is not implemented for `c::E`
+   |
+note: required by `check`
+  --> $DIR/namespace-mix.rs:21:1
+   |
+LL | fn check<T: Impossible>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `c::E: Impossible` is not satisfied
+  --> $DIR/namespace-mix.rs:145:5
+   |
+LL |     check(mC::UV{});
+   |     ^^^^^ the trait `Impossible` is not implemented for `c::E`
+   |
+note: required by `check`
+  --> $DIR/namespace-mix.rs:21:1
+   |
+LL | fn check<T: Impossible>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `c::Item: Impossible` is not satisfied
+  --> $DIR/namespace-mix.rs:146:5
+   |
+LL |     check(mC::UV);
+   |     ^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |
+note: required by `check`
+  --> $DIR/namespace-mix.rs:21:1
+   |
+LL | fn check<T: Impossible>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied
+  --> $DIR/namespace-mix.rs:149:5
+   |
+LL |     check(xmB::UV{});
+   |     ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |
+note: required by `check`
+  --> $DIR/namespace-mix.rs:21:1
+   |
+LL | fn check<T: Impossible>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `namespace_mix::c::E: Impossible` is not satisfied
+  --> $DIR/namespace-mix.rs:150:5
+   |
+LL |     check(xmB::UV);
+   |     ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E`
+   |
+note: required by `check`
+  --> $DIR/namespace-mix.rs:21:1
+   |
+LL | fn check<T: Impossible>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `namespace_mix::c::E: Impossible` is not satisfied
+  --> $DIR/namespace-mix.rs:151:5
+   |
+LL |     check(xmC::UV{});
+   |     ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E`
+   |
+note: required by `check`
+  --> $DIR/namespace-mix.rs:21:1
+   |
+LL | fn check<T: Impossible>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied
+  --> $DIR/namespace-mix.rs:152:5
+   |
+LL |     check(xmC::UV);
+   |     ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |
+note: required by `check`
+  --> $DIR/namespace-mix.rs:21:1
+   |
+LL | fn check<T: Impossible>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 48 previous errors
+
+Some errors occurred: E0277, E0423.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/namespace/namespaced-enum-glob-import-no-impls-xcrate.rs b/src/test/ui/namespace/namespaced-enum-glob-import-no-impls-xcrate.rs
new file mode 100644
index 0000000..feb94b6
--- /dev/null
+++ b/src/test/ui/namespace/namespaced-enum-glob-import-no-impls-xcrate.rs
@@ -0,0 +1,15 @@
+// aux-build:namespaced_enums.rs
+extern crate namespaced_enums;
+
+mod m {
+    pub use namespaced_enums::Foo::*;
+}
+
+pub fn main() {
+    use namespaced_enums::Foo::*;
+
+    foo(); //~ ERROR cannot find function `foo` in this scope
+    m::foo(); //~ ERROR cannot find function `foo` in module `m`
+    bar(); //~ ERROR cannot find function `bar` in this scope
+    m::bar(); //~ ERROR cannot find function `bar` in module `m`
+}
diff --git a/src/test/ui/namespace/namespaced-enum-glob-import-no-impls-xcrate.stderr b/src/test/ui/namespace/namespaced-enum-glob-import-no-impls-xcrate.stderr
new file mode 100644
index 0000000..f3dbcc2
--- /dev/null
+++ b/src/test/ui/namespace/namespaced-enum-glob-import-no-impls-xcrate.stderr
@@ -0,0 +1,27 @@
+error[E0425]: cannot find function `foo` in this scope
+  --> $DIR/namespaced-enum-glob-import-no-impls-xcrate.rs:11:5
+   |
+LL |     foo();
+   |     ^^^ not found in this scope
+
+error[E0425]: cannot find function `foo` in module `m`
+  --> $DIR/namespaced-enum-glob-import-no-impls-xcrate.rs:12:8
+   |
+LL |     m::foo();
+   |        ^^^ not found in `m`
+
+error[E0425]: cannot find function `bar` in this scope
+  --> $DIR/namespaced-enum-glob-import-no-impls-xcrate.rs:13:5
+   |
+LL |     bar();
+   |     ^^^ not found in this scope
+
+error[E0425]: cannot find function `bar` in module `m`
+  --> $DIR/namespaced-enum-glob-import-no-impls-xcrate.rs:14:8
+   |
+LL |     m::bar();
+   |        ^^^ not found in `m`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/namespace/namespaced-enum-glob-import-no-impls.rs b/src/test/ui/namespace/namespaced-enum-glob-import-no-impls.rs
new file mode 100644
index 0000000..ab24f36
--- /dev/null
+++ b/src/test/ui/namespace/namespaced-enum-glob-import-no-impls.rs
@@ -0,0 +1,25 @@
+mod m2 {
+    pub enum Foo {
+        A,
+        B(isize),
+        C { a: isize },
+    }
+
+    impl Foo {
+        pub fn foo() {}
+        pub fn bar(&self) {}
+    }
+}
+
+mod m {
+    pub use m2::Foo::*;
+}
+
+pub fn main() {
+    use m2::Foo::*;
+
+    foo(); //~ ERROR cannot find function `foo` in this scope
+    m::foo(); //~ ERROR cannot find function `foo` in module `m`
+    bar(); //~ ERROR cannot find function `bar` in this scope
+    m::bar(); //~ ERROR cannot find function `bar` in module `m`
+}
diff --git a/src/test/ui/namespace/namespaced-enum-glob-import-no-impls.stderr b/src/test/ui/namespace/namespaced-enum-glob-import-no-impls.stderr
new file mode 100644
index 0000000..98784de
--- /dev/null
+++ b/src/test/ui/namespace/namespaced-enum-glob-import-no-impls.stderr
@@ -0,0 +1,27 @@
+error[E0425]: cannot find function `foo` in this scope
+  --> $DIR/namespaced-enum-glob-import-no-impls.rs:21:5
+   |
+LL |     foo();
+   |     ^^^ not found in this scope
+
+error[E0425]: cannot find function `foo` in module `m`
+  --> $DIR/namespaced-enum-glob-import-no-impls.rs:22:8
+   |
+LL |     m::foo();
+   |        ^^^ not found in `m`
+
+error[E0425]: cannot find function `bar` in this scope
+  --> $DIR/namespaced-enum-glob-import-no-impls.rs:23:5
+   |
+LL |     bar();
+   |     ^^^ not found in this scope
+
+error[E0425]: cannot find function `bar` in module `m`
+  --> $DIR/namespaced-enum-glob-import-no-impls.rs:24:8
+   |
+LL |     m::bar();
+   |        ^^^ not found in `m`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/nested-cfg-attrs.rs b/src/test/ui/nested-cfg-attrs.rs
new file mode 100644
index 0000000..c988d42
--- /dev/null
+++ b/src/test/ui/nested-cfg-attrs.rs
@@ -0,0 +1,4 @@
+#[cfg_attr(all(), cfg_attr(all(), cfg(foo)))]
+fn f() {}
+
+fn main() { f() } //~ ERROR cannot find function `f` in this scope
diff --git a/src/test/ui/nested-cfg-attrs.stderr b/src/test/ui/nested-cfg-attrs.stderr
new file mode 100644
index 0000000..f63888b
--- /dev/null
+++ b/src/test/ui/nested-cfg-attrs.stderr
@@ -0,0 +1,9 @@
+error[E0425]: cannot find function `f` in this scope
+  --> $DIR/nested-cfg-attrs.rs:4:13
+   |
+LL | fn main() { f() }
+   |             ^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/nested-ty-params.rs b/src/test/ui/nested-ty-params.rs
new file mode 100644
index 0000000..85413ac
--- /dev/null
+++ b/src/test/ui/nested-ty-params.rs
@@ -0,0 +1,8 @@
+// error-pattern:can't use generic parameters from outer function
+fn hd<U>(v: Vec<U> ) -> U {
+    fn hd1(w: [U]) -> U { return w[0]; }
+
+    return hd1(v);
+}
+
+fn main() {}
diff --git a/src/test/ui/nested-ty-params.stderr b/src/test/ui/nested-ty-params.stderr
new file mode 100644
index 0000000..37adeff
--- /dev/null
+++ b/src/test/ui/nested-ty-params.stderr
@@ -0,0 +1,23 @@
+error[E0401]: can't use generic parameters from outer function
+  --> $DIR/nested-ty-params.rs:3:16
+   |
+LL | fn hd<U>(v: Vec<U> ) -> U {
+   |       - type variable from outer function
+LL |     fn hd1(w: [U]) -> U { return w[0]; }
+   |        ---     ^ use of generic parameter from outer function
+   |        |
+   |        help: try using a local generic parameter instead: `hd1<U>`
+
+error[E0401]: can't use generic parameters from outer function
+  --> $DIR/nested-ty-params.rs:3:23
+   |
+LL | fn hd<U>(v: Vec<U> ) -> U {
+   |       - type variable from outer function
+LL |     fn hd1(w: [U]) -> U { return w[0]; }
+   |        ---            ^ use of generic parameter from outer function
+   |        |
+   |        help: try using a local generic parameter instead: `hd1<U>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0401`.
diff --git a/src/test/ui/nested_impl_trait.rs b/src/test/ui/nested_impl_trait.rs
new file mode 100644
index 0000000..be2c21a
--- /dev/null
+++ b/src/test/ui/nested_impl_trait.rs
@@ -0,0 +1,30 @@
+use std::fmt::Debug;
+
+fn fine(x: impl Into<u32>) -> impl Into<u32> { x }
+
+fn bad_in_ret_position(x: impl Into<u32>) -> impl Into<impl Debug> { x }
+//~^ ERROR nested `impl Trait` is not allowed
+
+fn bad_in_fn_syntax(x: fn() -> impl Into<impl Debug>) {}
+//~^ ERROR nested `impl Trait` is not allowed
+//~^^ `impl Trait` not allowed
+
+fn bad_in_arg_position(_: impl Into<impl Debug>) { }
+//~^ ERROR nested `impl Trait` is not allowed
+
+struct X;
+impl X {
+    fn bad(x: impl Into<u32>) -> impl Into<impl Debug> { x }
+    //~^ ERROR nested `impl Trait` is not allowed
+}
+
+fn allowed_in_assoc_type() -> impl Iterator<Item=impl Fn()> {
+    vec![|| println!("woot")].into_iter()
+}
+
+fn allowed_in_ret_type() -> impl Fn() -> impl Into<u32> {
+//~^ `impl Trait` not allowed
+    || 5
+}
+
+fn main() {}
diff --git a/src/test/ui/nested_impl_trait.stderr b/src/test/ui/nested_impl_trait.stderr
new file mode 100644
index 0000000..60f57e5
--- /dev/null
+++ b/src/test/ui/nested_impl_trait.stderr
@@ -0,0 +1,52 @@
+error[E0666]: nested `impl Trait` is not allowed
+  --> $DIR/nested_impl_trait.rs:5:56
+   |
+LL | fn bad_in_ret_position(x: impl Into<u32>) -> impl Into<impl Debug> { x }
+   |                                              ----------^^^^^^^^^^-
+   |                                              |         |
+   |                                              |         nested `impl Trait` here
+   |                                              outer `impl Trait`
+
+error[E0666]: nested `impl Trait` is not allowed
+  --> $DIR/nested_impl_trait.rs:8:42
+   |
+LL | fn bad_in_fn_syntax(x: fn() -> impl Into<impl Debug>) {}
+   |                                ----------^^^^^^^^^^-
+   |                                |         |
+   |                                |         nested `impl Trait` here
+   |                                outer `impl Trait`
+
+error[E0666]: nested `impl Trait` is not allowed
+  --> $DIR/nested_impl_trait.rs:12:37
+   |
+LL | fn bad_in_arg_position(_: impl Into<impl Debug>) { }
+   |                           ----------^^^^^^^^^^-
+   |                           |         |
+   |                           |         nested `impl Trait` here
+   |                           outer `impl Trait`
+
+error[E0666]: nested `impl Trait` is not allowed
+  --> $DIR/nested_impl_trait.rs:17:44
+   |
+LL |     fn bad(x: impl Into<u32>) -> impl Into<impl Debug> { x }
+   |                                  ----------^^^^^^^^^^-
+   |                                  |         |
+   |                                  |         nested `impl Trait` here
+   |                                  outer `impl Trait`
+
+error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+  --> $DIR/nested_impl_trait.rs:8:32
+   |
+LL | fn bad_in_fn_syntax(x: fn() -> impl Into<impl Debug>) {}
+   |                                ^^^^^^^^^^^^^^^^^^^^^
+
+error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+  --> $DIR/nested_impl_trait.rs:25:42
+   |
+LL | fn allowed_in_ret_type() -> impl Fn() -> impl Into<u32> {
+   |                                          ^^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
+Some errors occurred: E0562, E0666.
+For more information about an error, try `rustc --explain E0562`.
diff --git a/src/test/ui/never-assign-dead-code.rs b/src/test/ui/never-assign-dead-code.rs
new file mode 100644
index 0000000..6b047c3
--- /dev/null
+++ b/src/test/ui/never-assign-dead-code.rs
@@ -0,0 +1,12 @@
+// Test that an assignment of type ! makes the rest of the block dead code.
+
+#![feature(never_type)]
+// compile-pass
+#![warn(unused)]
+
+
+fn main() {
+    let x: ! = panic!("aah"); //~ WARN unused
+    drop(x); //~ WARN unreachable
+    //~^ WARN unreachable
+}
diff --git a/src/test/ui/never-assign-dead-code.stderr b/src/test/ui/never-assign-dead-code.stderr
new file mode 100644
index 0000000..6735310
--- /dev/null
+++ b/src/test/ui/never-assign-dead-code.stderr
@@ -0,0 +1,32 @@
+warning: unreachable statement
+  --> $DIR/never-assign-dead-code.rs:10:5
+   |
+LL |     drop(x);
+   |     ^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/never-assign-dead-code.rs:5:9
+   |
+LL | #![warn(unused)]
+   |         ^^^^^^
+   = note: #[warn(unreachable_code)] implied by #[warn(unused)]
+
+warning: unreachable expression
+  --> $DIR/never-assign-dead-code.rs:10:5
+   |
+LL |     drop(x);
+   |     ^^^^^^^
+
+warning: unused variable: `x`
+  --> $DIR/never-assign-dead-code.rs:9:9
+   |
+LL |     let x: ! = panic!("aah");
+   |         ^ help: consider prefixing with an underscore: `_x`
+   |
+note: lint level defined here
+  --> $DIR/never-assign-dead-code.rs:5:9
+   |
+LL | #![warn(unused)]
+   |         ^^^^^^
+   = note: #[warn(unused_variables)] implied by #[warn(unused)]
+
diff --git a/src/test/ui/never-assign-wrong-type.rs b/src/test/ui/never-assign-wrong-type.rs
new file mode 100644
index 0000000..67e26f5
--- /dev/null
+++ b/src/test/ui/never-assign-wrong-type.rs
@@ -0,0 +1,8 @@
+// Test that we can't use another type in place of !
+
+#![feature(never_type)]
+#![deny(warnings)]
+
+fn main() {
+    let x: ! = "hello"; //~ ERROR mismatched types
+}
diff --git a/src/test/ui/never-assign-wrong-type.stderr b/src/test/ui/never-assign-wrong-type.stderr
new file mode 100644
index 0000000..da2e77d
--- /dev/null
+++ b/src/test/ui/never-assign-wrong-type.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/never-assign-wrong-type.rs:7:16
+   |
+LL |     let x: ! = "hello";
+   |                ^^^^^^^ expected !, found reference
+   |
+   = note: expected type `!`
+              found type `&'static str`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/never_transmute_never.rs b/src/test/ui/never_transmute_never.rs
new file mode 100644
index 0000000..ef78eaa
--- /dev/null
+++ b/src/test/ui/never_transmute_never.rs
@@ -0,0 +1,23 @@
+// compile-pass
+
+#![crate_type="lib"]
+
+#![feature(never_type)]
+#![allow(dead_code)]
+#![allow(unreachable_code)]
+#![allow(unused_variables)]
+
+struct Foo;
+
+pub fn f(x: !) -> ! {
+    x
+}
+
+pub fn ub() {
+    // This is completely undefined behaviour,
+    // but we still want to make sure it compiles.
+    let x: ! = unsafe {
+        std::mem::transmute::<Foo, !>(Foo)
+    };
+    f(x)
+}
diff --git a/src/test/ui/nll/borrow-use-issue-46875.rs b/src/test/ui/nll/borrow-use-issue-46875.rs
new file mode 100644
index 0000000..03db28f
--- /dev/null
+++ b/src/test/ui/nll/borrow-use-issue-46875.rs
@@ -0,0 +1,20 @@
+#![feature(nll)]
+
+// run-pass
+
+fn vec() {
+    let mut _x = vec!['c'];
+    let _y = &_x;
+    _x = Vec::new();
+}
+
+fn int() {
+    let mut _x = 5;
+    let _y = &_x;
+    _x = 7;
+}
+
+fn main() {
+    vec();
+    int();
+}
diff --git a/src/test/ui/nll/borrowck-thread-local-static-mut-borrow-outlives-fn.rs b/src/test/ui/nll/borrowck-thread-local-static-mut-borrow-outlives-fn.rs
new file mode 100644
index 0000000..59936a8
--- /dev/null
+++ b/src/test/ui/nll/borrowck-thread-local-static-mut-borrow-outlives-fn.rs
@@ -0,0 +1,26 @@
+//
+// run-pass
+//
+// FIXME(#54366) - We probably shouldn't allow #[thread_local] static mut to get a 'static lifetime.
+
+#![feature(nll)]
+#![feature(thread_local)]
+
+#[thread_local]
+static mut X1: u64 = 0;
+
+struct S1 {
+    a: &'static mut u64,
+}
+
+impl S1 {
+    fn new(_x: u64) -> S1 {
+        S1 {
+            a: unsafe { &mut X1 },
+        }
+    }
+}
+
+fn main() {
+    S1::new(0).a;
+}
diff --git a/src/test/ui/nll/borrowed-local-error.rs b/src/test/ui/nll/borrowed-local-error.rs
new file mode 100644
index 0000000..d37e61b
--- /dev/null
+++ b/src/test/ui/nll/borrowed-local-error.rs
@@ -0,0 +1,14 @@
+#![feature(nll)]
+
+fn gimme(x: &(u32,)) -> &u32 {
+    &x.0
+}
+
+fn main() {
+    let x = gimme({
+        let v = (22,);
+        &v
+        //~^ ERROR `v` does not live long enough [E0597]
+    });
+    println!("{:?}", x);
+}
diff --git a/src/test/ui/nll/borrowed-local-error.stderr b/src/test/ui/nll/borrowed-local-error.stderr
new file mode 100644
index 0000000..799eec9
--- /dev/null
+++ b/src/test/ui/nll/borrowed-local-error.stderr
@@ -0,0 +1,15 @@
+error[E0597]: `v` does not live long enough
+  --> $DIR/borrowed-local-error.rs:10:9
+   |
+LL |     let x = gimme({
+   |             ----- borrow later used by call
+LL |         let v = (22,);
+LL |         &v
+   |         ^^ borrowed value does not live long enough
+LL |
+LL |     });
+   |     - `v` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/borrowed-match-issue-45045.rs b/src/test/ui/nll/borrowed-match-issue-45045.rs
new file mode 100644
index 0000000..59516d8
--- /dev/null
+++ b/src/test/ui/nll/borrowed-match-issue-45045.rs
@@ -0,0 +1,20 @@
+// Regression test for issue #45045
+
+#![feature(nll)]
+
+enum Xyz {
+    A,
+    B,
+}
+
+fn main() {
+    let mut e = Xyz::A;
+    let f = &mut e;
+    let g = f;
+    match e {
+        Xyz::A => println!("a"),
+        //~^ cannot use `e` because it was mutably borrowed [E0503]
+        Xyz::B => println!("b"),
+    };
+    *g = Xyz::B;
+}
diff --git a/src/test/ui/nll/borrowed-match-issue-45045.stderr b/src/test/ui/nll/borrowed-match-issue-45045.stderr
new file mode 100644
index 0000000..f8d4d56
--- /dev/null
+++ b/src/test/ui/nll/borrowed-match-issue-45045.stderr
@@ -0,0 +1,15 @@
+error[E0503]: cannot use `e` because it was mutably borrowed
+  --> $DIR/borrowed-match-issue-45045.rs:15:9
+   |
+LL |     let f = &mut e;
+   |             ------ borrow of `e` occurs here
+...
+LL |         Xyz::A => println!("a"),
+   |         ^^^^^^ use of borrowed `e`
+...
+LL |     *g = Xyz::B;
+   |     ----------- borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0503`.
diff --git a/src/test/ui/nll/borrowed-referent-issue-38899.rs b/src/test/ui/nll/borrowed-referent-issue-38899.rs
new file mode 100644
index 0000000..7bad6dc
--- /dev/null
+++ b/src/test/ui/nll/borrowed-referent-issue-38899.rs
@@ -0,0 +1,20 @@
+// Regression test for issue #38899
+
+#![feature(nll)]
+#![allow(dead_code)]
+
+pub struct Block<'a> {
+    current: &'a u8,
+    unrelated: &'a u8,
+}
+
+fn bump<'a>(mut block: &mut Block<'a>) {
+    let x = &mut block;
+    println!("{}", x.current);
+    let p: &'a u8 = &*block.current;
+    //~^ ERROR cannot borrow `*block.current` as immutable because it is also borrowed as mutable
+    drop(x);
+    drop(p);
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/borrowed-referent-issue-38899.stderr b/src/test/ui/nll/borrowed-referent-issue-38899.stderr
new file mode 100644
index 0000000..5c9c48f
--- /dev/null
+++ b/src/test/ui/nll/borrowed-referent-issue-38899.stderr
@@ -0,0 +1,15 @@
+error[E0502]: cannot borrow `*block.current` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowed-referent-issue-38899.rs:14:21
+   |
+LL |     let x = &mut block;
+   |             ---------- mutable borrow occurs here
+LL |     println!("{}", x.current);
+LL |     let p: &'a u8 = &*block.current;
+   |                     ^^^^^^^^^^^^^^^ immutable borrow occurs here
+LL |
+LL |     drop(x);
+   |          - mutable borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/nll/borrowed-temporary-error.rs b/src/test/ui/nll/borrowed-temporary-error.rs
new file mode 100644
index 0000000..5ad987c
--- /dev/null
+++ b/src/test/ui/nll/borrowed-temporary-error.rs
@@ -0,0 +1,14 @@
+#![feature(nll)]
+
+fn gimme(x: &(u32,)) -> &u32 {
+    &x.0
+}
+
+fn main() {
+    let x = gimme({
+        let v = 22;
+        &(v,)
+        //~^ ERROR temporary value dropped while borrowed [E0716]
+    });
+    println!("{:?}", x);
+}
diff --git a/src/test/ui/nll/borrowed-temporary-error.stderr b/src/test/ui/nll/borrowed-temporary-error.stderr
new file mode 100644
index 0000000..c0d4231
--- /dev/null
+++ b/src/test/ui/nll/borrowed-temporary-error.stderr
@@ -0,0 +1,16 @@
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/borrowed-temporary-error.rs:10:10
+   |
+LL |         &(v,)
+   |          ^^^^ creates a temporary which is freed while still in use
+LL |
+LL |     });
+   |       - temporary value is freed at the end of this statement
+LL |     println!("{:?}", x);
+   |                      - borrow later used here
+   |
+   = note: consider using a `let` binding to create a longer lived value
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/src/test/ui/nll/borrowed-universal-error-2.rs b/src/test/ui/nll/borrowed-universal-error-2.rs
new file mode 100644
index 0000000..a10a62b
--- /dev/null
+++ b/src/test/ui/nll/borrowed-universal-error-2.rs
@@ -0,0 +1,10 @@
+#![feature(nll)]
+#![allow(warnings)]
+
+fn foo<'a>(x: &'a (u32,)) -> &'a u32 {
+    let v = 22;
+    &v
+    //~^ ERROR cannot return reference to local variable `v` [E0515]
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/borrowed-universal-error-2.stderr b/src/test/ui/nll/borrowed-universal-error-2.stderr
new file mode 100644
index 0000000..e89a77a
--- /dev/null
+++ b/src/test/ui/nll/borrowed-universal-error-2.stderr
@@ -0,0 +1,9 @@
+error[E0515]: cannot return reference to local variable `v`
+  --> $DIR/borrowed-universal-error-2.rs:6:5
+   |
+LL |     &v
+   |     ^^ returns a reference to data owned by the current function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/src/test/ui/nll/borrowed-universal-error.rs b/src/test/ui/nll/borrowed-universal-error.rs
new file mode 100644
index 0000000..18a0a72
--- /dev/null
+++ b/src/test/ui/nll/borrowed-universal-error.rs
@@ -0,0 +1,14 @@
+#![feature(nll)]
+#![allow(warnings)]
+
+fn gimme(x: &(u32,)) -> &u32 {
+    &x.0
+}
+
+fn foo<'a>(x: &'a (u32,)) -> &'a u32 {
+    let v = 22;
+    gimme(&(v,))
+    //~^ ERROR cannot return value referencing temporary value [E0515]
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/borrowed-universal-error.stderr b/src/test/ui/nll/borrowed-universal-error.stderr
new file mode 100644
index 0000000..4b76795
--- /dev/null
+++ b/src/test/ui/nll/borrowed-universal-error.stderr
@@ -0,0 +1,12 @@
+error[E0515]: cannot return value referencing temporary value
+  --> $DIR/borrowed-universal-error.rs:10:5
+   |
+LL |     gimme(&(v,))
+   |     ^^^^^^^----^
+   |     |      |
+   |     |      temporary value created here
+   |     returns a value referencing data owned by the current function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/src/test/ui/nll/cannot-move-block-spans.nll.stderr b/src/test/ui/nll/cannot-move-block-spans.nll.stderr
new file mode 100644
index 0000000..5d50ed6
--- /dev/null
+++ b/src/test/ui/nll/cannot-move-block-spans.nll.stderr
@@ -0,0 +1,85 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/cannot-move-block-spans.rs:5:15
+   |
+LL |     let x = { *r };
+   |               ^^
+   |               |
+   |               cannot move out of borrowed content
+   |               help: consider removing the `*`: `r`
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/cannot-move-block-spans.rs:6:22
+   |
+LL |     let y = unsafe { *r };
+   |                      ^^
+   |                      |
+   |                      cannot move out of borrowed content
+   |                      help: consider removing the `*`: `r`
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/cannot-move-block-spans.rs:7:26
+   |
+LL |     let z = loop { break *r; };
+   |                          ^^
+   |                          |
+   |                          cannot move out of borrowed content
+   |                          help: consider removing the `*`: `r`
+
+error[E0508]: cannot move out of type `[std::string::String; 2]`, a non-copy array
+  --> $DIR/cannot-move-block-spans.rs:11:15
+   |
+LL |     let x = { arr[0] };
+   |               ^^^^^^
+   |               |
+   |               cannot move out of here
+   |               help: consider borrowing here: `&arr[0]`
+
+error[E0508]: cannot move out of type `[std::string::String; 2]`, a non-copy array
+  --> $DIR/cannot-move-block-spans.rs:12:22
+   |
+LL |     let y = unsafe { arr[0] };
+   |                      ^^^^^^
+   |                      |
+   |                      cannot move out of here
+   |                      help: consider borrowing here: `&arr[0]`
+
+error[E0508]: cannot move out of type `[std::string::String; 2]`, a non-copy array
+  --> $DIR/cannot-move-block-spans.rs:13:26
+   |
+LL |     let z = loop { break arr[0]; };
+   |                          ^^^^^^
+   |                          |
+   |                          cannot move out of here
+   |                          help: consider borrowing here: `&arr[0]`
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/cannot-move-block-spans.rs:17:38
+   |
+LL |     let x = { let mut u = 0; u += 1; *r };
+   |                                      ^^
+   |                                      |
+   |                                      cannot move out of borrowed content
+   |                                      help: consider removing the `*`: `r`
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/cannot-move-block-spans.rs:18:45
+   |
+LL |     let y = unsafe { let mut u = 0; u += 1; *r };
+   |                                             ^^
+   |                                             |
+   |                                             cannot move out of borrowed content
+   |                                             help: consider removing the `*`: `r`
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/cannot-move-block-spans.rs:19:49
+   |
+LL |     let z = loop { let mut u = 0; u += 1; break *r; u += 2; };
+   |                                                 ^^
+   |                                                 |
+   |                                                 cannot move out of borrowed content
+   |                                                 help: consider removing the `*`: `r`
+
+error: aborting due to 9 previous errors
+
+Some errors occurred: E0507, E0508.
+For more information about an error, try `rustc --explain E0507`.
diff --git a/src/test/ui/nll/cannot-move-block-spans.rs b/src/test/ui/nll/cannot-move-block-spans.rs
new file mode 100644
index 0000000..e994fd3
--- /dev/null
+++ b/src/test/ui/nll/cannot-move-block-spans.rs
@@ -0,0 +1,22 @@
+// Test that the we point to the inner expression when moving out to initialize
+// a variable, and that we don't give a useless suggestion such as &{ *r }.
+
+pub fn deref(r: &String) {
+    let x = { *r }; //~ ERROR
+    let y = unsafe { *r }; //~ ERROR
+    let z = loop { break *r; }; //~ ERROR
+}
+
+pub fn index(arr: [String; 2]) {
+    let x = { arr[0] }; //~ ERROR
+    let y = unsafe { arr[0] }; //~ ERROR
+    let z = loop { break arr[0]; }; //~ ERROR
+}
+
+pub fn additional_statement_cases(r: &String) {
+    let x = { let mut u = 0; u += 1; *r }; //~ ERROR
+    let y = unsafe { let mut u = 0; u += 1; *r }; //~ ERROR
+    let z = loop { let mut u = 0; u += 1; break *r; u += 2; }; //~ ERROR
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/cannot-move-block-spans.stderr b/src/test/ui/nll/cannot-move-block-spans.stderr
new file mode 100644
index 0000000..6de67a4
--- /dev/null
+++ b/src/test/ui/nll/cannot-move-block-spans.stderr
@@ -0,0 +1,58 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/cannot-move-block-spans.rs:5:15
+   |
+LL |     let x = { *r };
+   |               ^^ cannot move out of borrowed content
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/cannot-move-block-spans.rs:6:22
+   |
+LL |     let y = unsafe { *r };
+   |                      ^^ cannot move out of borrowed content
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/cannot-move-block-spans.rs:7:26
+   |
+LL |     let z = loop { break *r; };
+   |                          ^^ cannot move out of borrowed content
+
+error[E0508]: cannot move out of type `[std::string::String; 2]`, a non-copy array
+  --> $DIR/cannot-move-block-spans.rs:11:15
+   |
+LL |     let x = { arr[0] };
+   |               ^^^^^^ cannot move out of here
+
+error[E0508]: cannot move out of type `[std::string::String; 2]`, a non-copy array
+  --> $DIR/cannot-move-block-spans.rs:12:22
+   |
+LL |     let y = unsafe { arr[0] };
+   |                      ^^^^^^ cannot move out of here
+
+error[E0508]: cannot move out of type `[std::string::String; 2]`, a non-copy array
+  --> $DIR/cannot-move-block-spans.rs:13:26
+   |
+LL |     let z = loop { break arr[0]; };
+   |                          ^^^^^^ cannot move out of here
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/cannot-move-block-spans.rs:17:38
+   |
+LL |     let x = { let mut u = 0; u += 1; *r };
+   |                                      ^^ cannot move out of borrowed content
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/cannot-move-block-spans.rs:18:45
+   |
+LL |     let y = unsafe { let mut u = 0; u += 1; *r };
+   |                                             ^^ cannot move out of borrowed content
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/cannot-move-block-spans.rs:19:49
+   |
+LL |     let z = loop { let mut u = 0; u += 1; break *r; u += 2; };
+   |                                                 ^^ cannot move out of borrowed content
+
+error: aborting due to 9 previous errors
+
+Some errors occurred: E0507, E0508.
+For more information about an error, try `rustc --explain E0507`.
diff --git a/src/test/ui/nll/capture-mut-ref.rs b/src/test/ui/nll/capture-mut-ref.rs
new file mode 100644
index 0000000..222f4e7
--- /dev/null
+++ b/src/test/ui/nll/capture-mut-ref.rs
@@ -0,0 +1,15 @@
+// Check that capturing a mutable reference by move and assigning to its
+// referent doesn't make the unused mut lint think that it is mutable.
+
+#![feature(nll)]
+#![deny(unused_mut)]
+
+fn mutable_upvar() {
+    let mut x = &mut 0;
+    //~^ ERROR
+    move || {
+        *x = 1;
+    };
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/capture-mut-ref.stderr b/src/test/ui/nll/capture-mut-ref.stderr
new file mode 100644
index 0000000..327ce0c
--- /dev/null
+++ b/src/test/ui/nll/capture-mut-ref.stderr
@@ -0,0 +1,16 @@
+error: variable does not need to be mutable
+  --> $DIR/capture-mut-ref.rs:8:9
+   |
+LL |     let mut x = &mut 0;
+   |         ----^
+   |         |
+   |         help: remove this `mut`
+   |
+note: lint level defined here
+  --> $DIR/capture-mut-ref.rs:5:9
+   |
+LL | #![deny(unused_mut)]
+   |         ^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/capture-ref-in-struct.rs b/src/test/ui/nll/capture-ref-in-struct.rs
new file mode 100644
index 0000000..bf2db32
--- /dev/null
+++ b/src/test/ui/nll/capture-ref-in-struct.rs
@@ -0,0 +1,39 @@
+// Test that a structure which tries to store a pointer to `y` into
+// `p` (indirectly) fails to compile.
+
+#![feature(rustc_attrs)]
+#![feature(nll)]
+
+struct SomeStruct<'a, 'b: 'a> {
+    p: &'a mut &'b i32,
+    y: &'b i32,
+}
+
+fn test() {
+    let x = 44;
+    let mut p = &x;
+
+    {
+        let y = 22;
+
+        let closure = SomeStruct {
+            p: &mut p,
+            y: &y,
+            //~^ ERROR `y` does not live long enough [E0597]
+        };
+
+        closure.invoke();
+    }
+
+    deref(p);
+}
+
+impl<'a, 'b> SomeStruct<'a, 'b> {
+    fn invoke(self) {
+        *self.p = self.y;
+    }
+}
+
+fn deref(_: &i32) { }
+
+fn main() { }
diff --git a/src/test/ui/nll/capture-ref-in-struct.stderr b/src/test/ui/nll/capture-ref-in-struct.stderr
new file mode 100644
index 0000000..7fafb44
--- /dev/null
+++ b/src/test/ui/nll/capture-ref-in-struct.stderr
@@ -0,0 +1,15 @@
+error[E0597]: `y` does not live long enough
+  --> $DIR/capture-ref-in-struct.rs:21:16
+   |
+LL |             y: &y,
+   |                ^^ borrowed value does not live long enough
+...
+LL |     }
+   |     - `y` dropped here while still borrowed
+LL | 
+LL |     deref(p);
+   |           - borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/closure-access-spans.rs b/src/test/ui/nll/closure-access-spans.rs
new file mode 100644
index 0000000..1e11b48
--- /dev/null
+++ b/src/test/ui/nll/closure-access-spans.rs
@@ -0,0 +1,58 @@
+// check that accesses due to a closure capture give a special note
+
+#![feature(nll)]
+
+fn closure_imm_capture_conflict(mut x: i32) {
+    let r = &mut x;
+    || x; //~ ERROR
+    r.use_mut();
+}
+
+fn closure_mut_capture_conflict(mut x: i32) {
+    let r = &mut x;
+    || x = 2; //~ ERROR
+    r.use_mut();
+}
+
+fn closure_unique_capture_conflict(mut x: &mut i32) {
+    let r = &mut x;
+    || *x = 2; //~ ERROR
+    r.use_mut();
+}
+
+fn closure_copy_capture_conflict(mut x: i32) {
+    let r = &mut x;
+    move || x; //~ ERROR
+    r.use_ref();
+}
+
+fn closure_move_capture_conflict(mut x: String) {
+    let r = &x;
+    || x; //~ ERROR
+    r.use_ref();
+}
+
+fn closure_imm_capture_moved(mut x: String) {
+    let r = x;
+    || x.len(); //~ ERROR
+}
+
+fn closure_mut_capture_moved(mut x: String) {
+    let r = x;
+    || x = String::new(); //~ ERROR
+}
+
+fn closure_unique_capture_moved(x: &mut String) {
+    let r = x;
+    || *x = String::new(); //~ ERROR
+}
+
+fn closure_move_capture_moved(x: &mut String) {
+    let r = x;
+    || x; //~ ERROR
+}
+
+fn main() {}
+
+trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { }  }
+impl<T> Fake for T { }
diff --git a/src/test/ui/nll/closure-access-spans.stderr b/src/test/ui/nll/closure-access-spans.stderr
new file mode 100644
index 0000000..6c4cad9
--- /dev/null
+++ b/src/test/ui/nll/closure-access-spans.stderr
@@ -0,0 +1,110 @@
+error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
+  --> $DIR/closure-access-spans.rs:7:5
+   |
+LL |     let r = &mut x;
+   |             ------ mutable borrow occurs here
+LL |     || x;
+   |     ^^ - second borrow occurs due to use of `x` in closure
+   |     |
+   |     immutable borrow occurs here
+LL |     r.use_mut();
+   |     - mutable borrow later used here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time
+  --> $DIR/closure-access-spans.rs:13:5
+   |
+LL |     let r = &mut x;
+   |             ------ first mutable borrow occurs here
+LL |     || x = 2;
+   |     ^^ - second borrow occurs due to use of `x` in closure
+   |     |
+   |     second mutable borrow occurs here
+LL |     r.use_mut();
+   |     - first borrow later used here
+
+error[E0500]: closure requires unique access to `x` but it is already borrowed
+  --> $DIR/closure-access-spans.rs:19:5
+   |
+LL |     let r = &mut x;
+   |             ------ borrow occurs here
+LL |     || *x = 2;
+   |     ^^  - second borrow occurs due to use of `x` in closure
+   |     |
+   |     closure construction occurs here
+LL |     r.use_mut();
+   |     - first borrow later used here
+
+error[E0503]: cannot use `x` because it was mutably borrowed
+  --> $DIR/closure-access-spans.rs:25:13
+   |
+LL |     let r = &mut x;
+   |             ------ borrow of `x` occurs here
+LL |     move || x;
+   |             ^ use of borrowed `x`
+LL |     r.use_ref();
+   |     - borrow later used here
+
+error[E0505]: cannot move out of `x` because it is borrowed
+  --> $DIR/closure-access-spans.rs:31:5
+   |
+LL |     let r = &x;
+   |             -- borrow of `x` occurs here
+LL |     || x;
+   |     ^^ - move occurs due to use in closure
+   |     |
+   |     move out of `x` occurs here
+LL |     r.use_ref();
+   |     - borrow later used here
+
+error[E0382]: borrow of moved value: `x`
+  --> $DIR/closure-access-spans.rs:37:5
+   |
+LL | fn closure_imm_capture_moved(mut x: String) {
+   |                              ----- move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
+LL |     let r = x;
+   |             - value moved here
+LL |     || x.len();
+   |     ^^ - borrow occurs due to use in closure
+   |     |
+   |     value borrowed here after move
+
+error[E0382]: borrow of moved value: `x`
+  --> $DIR/closure-access-spans.rs:42:5
+   |
+LL | fn closure_mut_capture_moved(mut x: String) {
+   |                              ----- move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
+LL |     let r = x;
+   |             - value moved here
+LL |     || x = String::new();
+   |     ^^ - borrow occurs due to use in closure
+   |     |
+   |     value borrowed here after move
+
+error[E0382]: borrow of moved value: `x`
+  --> $DIR/closure-access-spans.rs:47:5
+   |
+LL | fn closure_unique_capture_moved(x: &mut String) {
+   |                                 - move occurs because `x` has type `&mut std::string::String`, which does not implement the `Copy` trait
+LL |     let r = x;
+   |             - value moved here
+LL |     || *x = String::new();
+   |     ^^  - borrow occurs due to use in closure
+   |     |
+   |     value borrowed here after move
+
+error[E0382]: use of moved value: `x`
+  --> $DIR/closure-access-spans.rs:52:5
+   |
+LL | fn closure_move_capture_moved(x: &mut String) {
+   |                               - move occurs because `x` has type `&mut std::string::String`, which does not implement the `Copy` trait
+LL |     let r = x;
+   |             - value moved here
+LL |     || x;
+   |     ^^ - use occurs due to use in closure
+   |     |
+   |     value used here after move
+
+error: aborting due to 9 previous errors
+
+Some errors occurred: E0382, E0499, E0500, E0502, E0503, E0505.
+For more information about an error, try `rustc --explain E0382`.
diff --git a/src/test/ui/nll/closure-borrow-spans.rs b/src/test/ui/nll/closure-borrow-spans.rs
new file mode 100644
index 0000000..7fc301b
--- /dev/null
+++ b/src/test/ui/nll/closure-borrow-spans.rs
@@ -0,0 +1,102 @@
+// check that existing borrows due to a closure capture give a special note
+
+#![feature(nll)]
+
+fn move_while_borrowed(x: String) {
+    let f = || x.len();
+    let y = x; //~ ERROR
+    f.use_ref();
+}
+
+fn borrow_mut_while_borrowed(mut x: i32) {
+    let f = || x;
+    let y = &mut x; //~ ERROR
+    f.use_ref();
+}
+
+fn drop_while_borrowed() {
+    let f;
+    {
+        let x = 1;
+        f = || x; //~ ERROR
+    }
+    f.use_ref();
+}
+
+fn assign_while_borrowed(mut x: i32) {
+    let f = || x;
+    x = 1; //~ ERROR
+    f.use_ref();
+}
+
+fn copy_while_borrowed_mut(mut x: i32) {
+    let f = || x = 0;
+    let y = x; //~ ERROR
+    f.use_ref();
+}
+
+fn borrow_while_borrowed_mut(mut x: i32) {
+    let f = || x = 0;
+    let y = &x; //~ ERROR
+    f.use_ref();
+}
+
+fn borrow_mut_while_borrowed_mut(mut x: i32) {
+    let f = || x = 0;
+    let y = &mut x; //~ ERROR
+    f.use_ref();
+}
+
+fn drop_while_borrowed_mut() {
+    let f;
+    {
+        let mut x = 1;
+        f = || x = 0; //~ ERROR
+    }
+    f.use_ref();
+}
+
+fn assign_while_borrowed_mut(mut x: i32) {
+    let f = || x = 0;
+    x = 1; //~ ERROR
+    f.use_ref();
+}
+
+fn copy_while_borrowed_unique(x: &mut i32) {
+    let f = || *x = 0;
+    let y = x; //~ ERROR
+    f.use_ref();
+}
+
+fn borrow_while_borrowed_unique(x: &mut i32) {
+    let f = || *x = 0;
+    let y = &x; //~ ERROR
+    f.use_ref();
+}
+
+fn borrow_mut_while_borrowed_unique(mut x: &mut i32) {
+    let f = || *x = 0;
+    let y = &mut x; //~ ERROR
+    f.use_ref();
+}
+
+fn drop_while_borrowed_unique() {
+    let mut z = 1;
+    let f;
+    {
+        let x = &mut z;
+        f = || *x = 0; //~ ERROR
+    }
+    f.use_ref();
+}
+
+fn assign_while_borrowed_unique(x: &mut i32) {
+    let f = || *x = 0;
+    *x = 1; //~ ERROR
+    f.use_ref();
+}
+
+fn main() {}
+
+trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { }  }
+impl<T> Fake for T { }
diff --git a/src/test/ui/nll/closure-borrow-spans.stderr b/src/test/ui/nll/closure-borrow-spans.stderr
new file mode 100644
index 0000000..fcb699a
--- /dev/null
+++ b/src/test/ui/nll/closure-borrow-spans.stderr
@@ -0,0 +1,172 @@
+error[E0505]: cannot move out of `x` because it is borrowed
+  --> $DIR/closure-borrow-spans.rs:7:13
+   |
+LL |     let f = || x.len();
+   |             -- - borrow occurs due to use in closure
+   |             |
+   |             borrow of `x` occurs here
+LL |     let y = x;
+   |             ^ move out of `x` occurs here
+LL |     f.use_ref();
+   |     - borrow later used here
+
+error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
+  --> $DIR/closure-borrow-spans.rs:13:13
+   |
+LL |     let f = || x;
+   |             -- - first borrow occurs due to use of `x` in closure
+   |             |
+   |             immutable borrow occurs here
+LL |     let y = &mut x;
+   |             ^^^^^^ mutable borrow occurs here
+LL |     f.use_ref();
+   |     - immutable borrow later used here
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/closure-borrow-spans.rs:21:16
+   |
+LL |         f = || x;
+   |             -- ^ borrowed value does not live long enough
+   |             |
+   |             value captured here
+LL |     }
+   |     - `x` dropped here while still borrowed
+LL |     f.use_ref();
+   |     - borrow later used here
+
+error[E0506]: cannot assign to `x` because it is borrowed
+  --> $DIR/closure-borrow-spans.rs:28:5
+   |
+LL |     let f = || x;
+   |             -- - borrow occurs due to use in closure
+   |             |
+   |             borrow of `x` occurs here
+LL |     x = 1;
+   |     ^^^^^ assignment to borrowed `x` occurs here
+LL |     f.use_ref();
+   |     - borrow later used here
+
+error[E0503]: cannot use `x` because it was mutably borrowed
+  --> $DIR/closure-borrow-spans.rs:34:13
+   |
+LL |     let f = || x = 0;
+   |             -- - borrow occurs due to use of `x` in closure
+   |             |
+   |             borrow of `x` occurs here
+LL |     let y = x;
+   |             ^ use of borrowed `x`
+LL |     f.use_ref();
+   |     - borrow later used here
+
+error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
+  --> $DIR/closure-borrow-spans.rs:40:13
+   |
+LL |     let f = || x = 0;
+   |             -- - first borrow occurs due to use of `x` in closure
+   |             |
+   |             mutable borrow occurs here
+LL |     let y = &x;
+   |             ^^ immutable borrow occurs here
+LL |     f.use_ref();
+   |     - mutable borrow later used here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time
+  --> $DIR/closure-borrow-spans.rs:46:13
+   |
+LL |     let f = || x = 0;
+   |             -- - first borrow occurs due to use of `x` in closure
+   |             |
+   |             first mutable borrow occurs here
+LL |     let y = &mut x;
+   |             ^^^^^^ second mutable borrow occurs here
+LL |     f.use_ref();
+   |     - first borrow later used here
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/closure-borrow-spans.rs:54:16
+   |
+LL |         f = || x = 0;
+   |             -- ^ borrowed value does not live long enough
+   |             |
+   |             value captured here
+LL |     }
+   |     - `x` dropped here while still borrowed
+LL |     f.use_ref();
+   |     - borrow later used here
+
+error[E0506]: cannot assign to `x` because it is borrowed
+  --> $DIR/closure-borrow-spans.rs:61:5
+   |
+LL |     let f = || x = 0;
+   |             -- - borrow occurs due to use in closure
+   |             |
+   |             borrow of `x` occurs here
+LL |     x = 1;
+   |     ^^^^^ assignment to borrowed `x` occurs here
+LL |     f.use_ref();
+   |     - borrow later used here
+
+error[E0505]: cannot move out of `x` because it is borrowed
+  --> $DIR/closure-borrow-spans.rs:67:13
+   |
+LL |     let f = || *x = 0;
+   |             --  - borrow occurs due to use in closure
+   |             |
+   |             borrow of `x` occurs here
+LL |     let y = x;
+   |             ^ move out of `x` occurs here
+LL |     f.use_ref();
+   |     - borrow later used here
+
+error[E0501]: cannot borrow `x` as immutable because previous closure requires unique access
+  --> $DIR/closure-borrow-spans.rs:73:13
+   |
+LL |     let f = || *x = 0;
+   |             --  - first borrow occurs due to use of `x` in closure
+   |             |
+   |             closure construction occurs here
+LL |     let y = &x;
+   |             ^^ second borrow occurs here
+LL |     f.use_ref();
+   |     - first borrow later used here
+
+error[E0501]: cannot borrow `x` as mutable because previous closure requires unique access
+  --> $DIR/closure-borrow-spans.rs:79:13
+   |
+LL |     let f = || *x = 0;
+   |             --  - first borrow occurs due to use of `x` in closure
+   |             |
+   |             closure construction occurs here
+LL |     let y = &mut x;
+   |             ^^^^^^ second borrow occurs here
+LL |     f.use_ref();
+   |     - first borrow later used here
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/closure-borrow-spans.rs:88:17
+   |
+LL |         f = || *x = 0;
+   |             --  ^ borrowed value does not live long enough
+   |             |
+   |             value captured here
+LL |     }
+   |     - `x` dropped here while still borrowed
+LL |     f.use_ref();
+   |     - borrow later used here
+
+error[E0506]: cannot assign to `*x` because it is borrowed
+  --> $DIR/closure-borrow-spans.rs:95:5
+   |
+LL |     let f = || *x = 0;
+   |             --  - borrow occurs due to use in closure
+   |             |
+   |             borrow of `*x` occurs here
+LL |     *x = 1;
+   |     ^^^^^^ assignment to borrowed `*x` occurs here
+LL |     f.use_ref();
+   |     - borrow later used here
+
+error: aborting due to 14 previous errors
+
+Some errors occurred: E0499, E0501, E0502, E0503, E0505, E0506, E0597.
+For more information about an error, try `rustc --explain E0499`.
diff --git a/src/test/ui/nll/closure-captures.rs b/src/test/ui/nll/closure-captures.rs
new file mode 100644
index 0000000..3a01f86
--- /dev/null
+++ b/src/test/ui/nll/closure-captures.rs
@@ -0,0 +1,58 @@
+// Some cases with closures that might be problems
+
+#![allow(unused)]
+#![feature(nll)]
+
+// Should have one error per assignment
+
+fn one_closure(x: i32) {
+    ||
+    x = 1; //~ ERROR
+    move ||
+    x = 1; //~ ERROR
+}
+
+fn two_closures(x: i32) {
+    || {
+        ||
+        x = 1; //~ ERROR
+    };
+    move || {
+        ||
+        x = 1; //~ ERROR
+    };
+}
+
+fn fn_ref<F: Fn()>(f: F) -> F { f }
+
+fn two_closures_ref_mut(mut x: i32) {
+    fn_ref(|| {
+        || //~ ERROR
+         x = 1;}
+    );
+    fn_ref(move || {
+        ||  //~ ERROR
+    x = 1;});
+}
+
+// This still gives two messages, but it requires two things to be fixed.
+fn two_closures_ref(x: i32) {
+    fn_ref(|| {
+        || //~ ERROR
+         x = 1;} //~ ERROR
+    );
+    fn_ref(move || {
+        ||  //~ ERROR
+    x = 1;}); //~ ERROR
+}
+
+fn two_closures_two_refs(x: &mut i32) {
+    fn_ref(|| {
+        || //~ ERROR
+        *x = 1;});
+    fn_ref(move || {
+        || //~ ERROR
+        *x = 1;});
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/closure-captures.stderr b/src/test/ui/nll/closure-captures.stderr
new file mode 100644
index 0000000..7dc1c59
--- /dev/null
+++ b/src/test/ui/nll/closure-captures.stderr
@@ -0,0 +1,160 @@
+error[E0594]: cannot assign to `x`, as it is not declared as mutable
+  --> $DIR/closure-captures.rs:10:5
+   |
+LL | fn one_closure(x: i32) {
+   |                - help: consider changing this to be mutable: `mut x`
+LL |     ||
+LL |     x = 1;
+   |     ^^^^^ cannot assign
+
+error[E0594]: cannot assign to `x`, as it is not declared as mutable
+  --> $DIR/closure-captures.rs:12:5
+   |
+LL | fn one_closure(x: i32) {
+   |                - help: consider changing this to be mutable: `mut x`
+...
+LL |     x = 1;
+   |     ^^^^^ cannot assign
+
+error[E0594]: cannot assign to `x`, as it is not declared as mutable
+  --> $DIR/closure-captures.rs:18:9
+   |
+LL | fn two_closures(x: i32) {
+   |                 - help: consider changing this to be mutable: `mut x`
+...
+LL |         x = 1;
+   |         ^^^^^ cannot assign
+
+error[E0594]: cannot assign to `x`, as it is not declared as mutable
+  --> $DIR/closure-captures.rs:22:9
+   |
+LL | fn two_closures(x: i32) {
+   |                 - help: consider changing this to be mutable: `mut x`
+...
+LL |         x = 1;
+   |         ^^^^^ cannot assign
+
+error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
+  --> $DIR/closure-captures.rs:30:9
+   |
+LL |         ||
+   |         ^^ cannot borrow as mutable
+LL |          x = 1;}
+   |          - mutable borrow occurs due to use of `x` in closure
+   |
+help: consider changing this to accept closures that implement `FnMut`
+  --> $DIR/closure-captures.rs:29:12
+   |
+LL |       fn_ref(|| {
+   |  ____________^
+LL | |         ||
+LL | |          x = 1;}
+   | |________________^
+
+error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
+  --> $DIR/closure-captures.rs:34:9
+   |
+LL |         ||
+   |         ^^ cannot borrow as mutable
+LL |     x = 1;});
+   |     - mutable borrow occurs due to use of `x` in closure
+   |
+help: consider changing this to accept closures that implement `FnMut`
+  --> $DIR/closure-captures.rs:33:12
+   |
+LL |       fn_ref(move || {
+   |  ____________^
+LL | |         ||
+LL | |     x = 1;});
+   | |___________^
+
+error[E0594]: cannot assign to `x`, as it is not declared as mutable
+  --> $DIR/closure-captures.rs:42:10
+   |
+LL | fn two_closures_ref(x: i32) {
+   |                     - help: consider changing this to be mutable: `mut x`
+...
+LL |          x = 1;}
+   |          ^^^^^ cannot assign
+
+error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
+  --> $DIR/closure-captures.rs:41:9
+   |
+LL |         ||
+   |         ^^ cannot borrow as mutable
+LL |          x = 1;}
+   |          - mutable borrow occurs due to use of `x` in closure
+   |
+help: consider changing this to accept closures that implement `FnMut`
+  --> $DIR/closure-captures.rs:40:12
+   |
+LL |       fn_ref(|| {
+   |  ____________^
+LL | |         ||
+LL | |          x = 1;}
+   | |________________^
+
+error[E0594]: cannot assign to `x`, as it is not declared as mutable
+  --> $DIR/closure-captures.rs:46:5
+   |
+LL | fn two_closures_ref(x: i32) {
+   |                     - help: consider changing this to be mutable: `mut x`
+...
+LL |     x = 1;});
+   |     ^^^^^ cannot assign
+
+error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
+  --> $DIR/closure-captures.rs:45:9
+   |
+LL |         ||
+   |         ^^ cannot borrow as mutable
+LL |     x = 1;});
+   |     - mutable borrow occurs due to use of `x` in closure
+   |
+help: consider changing this to accept closures that implement `FnMut`
+  --> $DIR/closure-captures.rs:44:12
+   |
+LL |       fn_ref(move || {
+   |  ____________^
+LL | |         ||
+LL | |     x = 1;});
+   | |___________^
+
+error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
+  --> $DIR/closure-captures.rs:51:9
+   |
+LL |         ||
+   |         ^^ cannot borrow as mutable
+LL |         *x = 1;});
+   |          - mutable borrow occurs due to use of `x` in closure
+   |
+help: consider changing this to accept closures that implement `FnMut`
+  --> $DIR/closure-captures.rs:50:12
+   |
+LL |       fn_ref(|| {
+   |  ____________^
+LL | |         ||
+LL | |         *x = 1;});
+   | |________________^
+
+error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
+  --> $DIR/closure-captures.rs:54:9
+   |
+LL |         ||
+   |         ^^ cannot borrow as mutable
+LL |         *x = 1;});
+   |          - mutable borrow occurs due to use of `x` in closure
+   |
+help: consider changing this to accept closures that implement `FnMut`
+  --> $DIR/closure-captures.rs:53:12
+   |
+LL |       fn_ref(move || {
+   |  ____________^
+LL | |         ||
+LL | |         *x = 1;});
+   | |________________^
+
+error: aborting due to 12 previous errors
+
+Some errors occurred: E0594, E0596.
+For more information about an error, try `rustc --explain E0594`.
diff --git a/src/test/ui/nll/closure-move-spans.rs b/src/test/ui/nll/closure-move-spans.rs
new file mode 100644
index 0000000..ffbfa9f
--- /dev/null
+++ b/src/test/ui/nll/closure-move-spans.rs
@@ -0,0 +1,23 @@
+// check that moves due to a closure capture give a special note
+
+#![feature(nll)]
+
+fn move_after_move(x: String) {
+    || x;
+    let y = x; //~ ERROR
+}
+
+fn borrow_after_move(x: String) {
+    || x;
+    let y = &x; //~ ERROR
+}
+
+fn borrow_mut_after_move(mut x: String) {
+    || x;
+    let y = &mut x; //~ ERROR
+}
+
+fn fn_ref<F: Fn()>(f: F) -> F { f }
+fn fn_mut<F: FnMut()>(f: F) -> F { f }
+
+fn main() {}
diff --git a/src/test/ui/nll/closure-move-spans.stderr b/src/test/ui/nll/closure-move-spans.stderr
new file mode 100644
index 0000000..1cc4ca8
--- /dev/null
+++ b/src/test/ui/nll/closure-move-spans.stderr
@@ -0,0 +1,39 @@
+error[E0382]: use of moved value: `x`
+  --> $DIR/closure-move-spans.rs:7:13
+   |
+LL | fn move_after_move(x: String) {
+   |                    - move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
+LL |     || x;
+   |     -- - variable moved due to use in closure
+   |     |
+   |     value moved into closure here
+LL |     let y = x;
+   |             ^ value used here after move
+
+error[E0382]: borrow of moved value: `x`
+  --> $DIR/closure-move-spans.rs:12:13
+   |
+LL | fn borrow_after_move(x: String) {
+   |                      - move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
+LL |     || x;
+   |     -- - variable moved due to use in closure
+   |     |
+   |     value moved into closure here
+LL |     let y = &x;
+   |             ^^ value borrowed here after move
+
+error[E0382]: borrow of moved value: `x`
+  --> $DIR/closure-move-spans.rs:17:13
+   |
+LL | fn borrow_mut_after_move(mut x: String) {
+   |                          ----- move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
+LL |     || x;
+   |     -- - variable moved due to use in closure
+   |     |
+   |     value moved into closure here
+LL |     let y = &mut x;
+   |             ^^^^^^ value borrowed here after move
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/nll/closure-requirements/escape-argument-callee.rs b/src/test/ui/nll/closure-requirements/escape-argument-callee.rs
new file mode 100644
index 0000000..9b3a49b
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/escape-argument-callee.rs
@@ -0,0 +1,42 @@
+// Test closure that:
+//
+// - takes an argument `y` with lifetime `'a` (in the code, it's anonymous)
+// - stores `y` into another, longer-lived spot with lifetime `'b`
+//
+// Because `'a` and `'b` are two different, unrelated higher-ranked
+// regions with no relationship to one another, this is an error. This
+// error is reported by the closure itself and is not propagated to
+// its creator: this is because `'a` and `'b` are higher-ranked
+// (late-bound) regions and the closure is not allowed to propagate
+// additional where clauses between higher-ranked regions, only those
+// that appear free in its type (hence, we see it before the closure's
+// "external requirements" report).
+
+// compile-flags:-Zborrowck=mir -Zverbose
+
+#![feature(rustc_attrs)]
+
+#[rustc_regions]
+fn test() {
+    let x = 44;
+    let mut p = &x;
+
+    {
+        let y = 22;
+        let mut closure = expect_sig(|p, y| *p = y);
+        //~^ ERROR
+        closure(&mut p, &y);
+    }
+
+    deref(p);
+}
+
+fn expect_sig<F>(f: F) -> F
+    where F: FnMut(&mut &i32, &i32)
+{
+    f
+}
+
+fn deref(_p: &i32) { }
+
+fn main() { }
diff --git a/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr b/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr
new file mode 100644
index 0000000..2004138
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr
@@ -0,0 +1,36 @@
+note: No external requirements
+  --> $DIR/escape-argument-callee.rs:26:38
+   |
+LL |         let mut closure = expect_sig(|p, y| *p = y);
+   |                                      ^^^^^^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:9 ~ escape_argument_callee[317d]::test[0]::{{closure}}[0]) with closure substs [
+               i16,
+               for<'r, 's, 't0> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) mut &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) i32, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't0)) i32)),
+           ]
+
+error: lifetime may not live long enough
+  --> $DIR/escape-argument-callee.rs:26:45
+   |
+LL |         let mut closure = expect_sig(|p, y| *p = y);
+   |                                       -  -  ^^^^^^ assignment requires that `'1` must outlive `'2`
+   |                                       |  |
+   |                                       |  has type `&'1 i32`
+   |                                       has type `&'_#2r mut &'2 i32`
+
+note: No external requirements
+  --> $DIR/escape-argument-callee.rs:20:1
+   |
+LL | / fn test() {
+LL | |     let x = 44;
+LL | |     let mut p = &x;
+LL | |
+...  |
+LL | |     deref(p);
+LL | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:3 ~ escape_argument_callee[317d]::test[0]) with substs []
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/closure-requirements/escape-argument.rs b/src/test/ui/nll/closure-requirements/escape-argument.rs
new file mode 100644
index 0000000..6269659
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/escape-argument.rs
@@ -0,0 +1,42 @@
+// Test closure that:
+//
+// - takes an argument `y`
+// - stores `y` into another, longer-lived spot
+//
+// but is invoked with a spot that doesn't live long
+// enough to store `y`.
+//
+// The error is reported in the caller: invoking the closure links the
+// lifetime of the variable that is given as `y` (via subtyping) and
+// thus forces the corresponding borrow to live too long. This is
+// basically checking that the MIR type checker correctly enforces the
+// closure signature.
+
+// compile-flags:-Zborrowck=mir -Zverbose
+
+#![feature(rustc_attrs)]
+
+#[rustc_regions]
+fn test() {
+    let x = 44;
+    let mut p = &x;
+
+    {
+        let y = 22;
+        let mut closure = expect_sig(|p, y| *p = y);
+        closure(&mut p, &y);
+        //~^ ERROR `y` does not live long enough [E0597]
+    }
+
+    deref(p);
+}
+
+fn expect_sig<F>(f: F) -> F
+    where F: for<'a, 'b> FnMut(&'a mut &'b i32, &'b i32)
+{
+    f
+}
+
+fn deref(_p: &i32) { }
+
+fn main() { }
diff --git a/src/test/ui/nll/closure-requirements/escape-argument.stderr b/src/test/ui/nll/closure-requirements/escape-argument.stderr
new file mode 100644
index 0000000..b08ec95
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/escape-argument.stderr
@@ -0,0 +1,40 @@
+note: No external requirements
+  --> $DIR/escape-argument.rs:26:38
+   |
+LL |         let mut closure = expect_sig(|p, y| *p = y);
+   |                                      ^^^^^^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:9 ~ escape_argument[317d]::test[0]::{{closure}}[0]) with closure substs [
+               i16,
+               for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) mut &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) i32, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) i32)),
+           ]
+
+note: No external requirements
+  --> $DIR/escape-argument.rs:20:1
+   |
+LL | / fn test() {
+LL | |     let x = 44;
+LL | |     let mut p = &x;
+LL | |
+...  |
+LL | |     deref(p);
+LL | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:3 ~ escape_argument[317d]::test[0]) with substs []
+
+error[E0597]: `y` does not live long enough
+  --> $DIR/escape-argument.rs:27:25
+   |
+LL |         closure(&mut p, &y);
+   |                         ^^ borrowed value does not live long enough
+LL |
+LL |     }
+   |     - `y` dropped here while still borrowed
+LL | 
+LL |     deref(p);
+   |           - borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/closure-requirements/escape-upvar-nested.rs b/src/test/ui/nll/closure-requirements/escape-upvar-nested.rs
new file mode 100644
index 0000000..b94b3d6
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/escape-upvar-nested.rs
@@ -0,0 +1,33 @@
+// As in `escape-upvar-ref.rs`, test closure that:
+//
+// - captures a variable `y`
+// - stores reference to `y` into another, longer-lived spot
+//
+// except that the closure does so via a second closure.
+
+// compile-flags:-Zborrowck=mir -Zverbose
+
+#![feature(rustc_attrs)]
+
+#[rustc_regions]
+fn test() {
+    let x = 44;
+    let mut p = &x;
+
+    {
+        let y = 22;
+
+        let mut closure = || {
+            let mut closure1 = || p = &y; //~ ERROR `y` does not live long enough [E0597]
+            closure1();
+        };
+
+        closure();
+    }
+
+    deref(p);
+}
+
+fn deref(_p: &i32) { }
+
+fn main() { }
diff --git a/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr b/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr
new file mode 100644
index 0000000..7178b22
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr
@@ -0,0 +1,65 @@
+note: External requirements
+  --> $DIR/escape-upvar-nested.rs:21:32
+   |
+LL |             let mut closure1 = || p = &y;
+   |                                ^^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:10 ~ escape_upvar_nested[317d]::test[0]::{{closure}}[0]::{{closure}}[0]) with closure substs [
+               i16,
+               extern "rust-call" fn(()),
+               &'_#1r mut &'_#2r i32,
+               &'_#3r i32,
+           ]
+   = note: number of external vids: 4
+   = note: where '_#3r: '_#2r
+
+note: External requirements
+  --> $DIR/escape-upvar-nested.rs:20:27
+   |
+LL |           let mut closure = || {
+   |  ___________________________^
+LL | |             let mut closure1 = || p = &y;
+LL | |             closure1();
+LL | |         };
+   | |_________^
+   |
+   = note: defining type: DefId(0/1:9 ~ escape_upvar_nested[317d]::test[0]::{{closure}}[0]) with closure substs [
+               i16,
+               extern "rust-call" fn(()),
+               &'_#1r mut &'_#2r i32,
+               &'_#3r i32,
+           ]
+   = note: number of external vids: 4
+   = note: where '_#3r: '_#2r
+
+note: No external requirements
+  --> $DIR/escape-upvar-nested.rs:13:1
+   |
+LL | / fn test() {
+LL | |     let x = 44;
+LL | |     let mut p = &x;
+LL | |
+...  |
+LL | |     deref(p);
+LL | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:3 ~ escape_upvar_nested[317d]::test[0]) with substs []
+
+error[E0597]: `y` does not live long enough
+  --> $DIR/escape-upvar-nested.rs:21:40
+   |
+LL |         let mut closure = || {
+   |                           -- value captured here
+LL |             let mut closure1 = || p = &y;
+   |                                        ^ borrowed value does not live long enough
+...
+LL |     }
+   |     - `y` dropped here while still borrowed
+LL | 
+LL |     deref(p);
+   |           - borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/closure-requirements/escape-upvar-ref.rs b/src/test/ui/nll/closure-requirements/escape-upvar-ref.rs
new file mode 100644
index 0000000..a916ccd
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/escape-upvar-ref.rs
@@ -0,0 +1,33 @@
+// Test closure that:
+//
+// - captures a variable `y` by reference
+// - stores that reference to `y` into another, longer-lived place (`p`)
+//
+// Both of these are upvars of reference type (the capture of `y` is
+// of type `&'a i32`, the capture of `p` is of type `&mut &'b
+// i32`). The closure thus computes a relationship between `'a` and
+// `'b`.  This relationship is propagated to the closure creator,
+// which reports an error.
+
+// compile-flags:-Zborrowck=mir -Zverbose
+
+#![feature(rustc_attrs)]
+
+#[rustc_regions]
+fn test() {
+    let x = 44;
+    let mut p = &x;
+
+    {
+        let y = 22;
+        let mut closure = || p = &y;
+        //~^ ERROR `y` does not live long enough [E0597]
+        closure();
+    }
+
+    deref(p);
+}
+
+fn deref(_p: &i32) { }
+
+fn main() { }
diff --git a/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr b/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr
new file mode 100644
index 0000000..d129f94
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr
@@ -0,0 +1,46 @@
+note: External requirements
+  --> $DIR/escape-upvar-ref.rs:23:27
+   |
+LL |         let mut closure = || p = &y;
+   |                           ^^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:9 ~ escape_upvar_ref[317d]::test[0]::{{closure}}[0]) with closure substs [
+               i16,
+               extern "rust-call" fn(()),
+               &'_#1r mut &'_#2r i32,
+               &'_#3r i32,
+           ]
+   = note: number of external vids: 4
+   = note: where '_#3r: '_#2r
+
+note: No external requirements
+  --> $DIR/escape-upvar-ref.rs:17:1
+   |
+LL | / fn test() {
+LL | |     let x = 44;
+LL | |     let mut p = &x;
+LL | |
+...  |
+LL | |     deref(p);
+LL | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:3 ~ escape_upvar_ref[317d]::test[0]) with substs []
+
+error[E0597]: `y` does not live long enough
+  --> $DIR/escape-upvar-ref.rs:23:35
+   |
+LL |         let mut closure = || p = &y;
+   |                           --      ^ borrowed value does not live long enough
+   |                           |
+   |                           value captured here
+...
+LL |     }
+   |     - `y` dropped here while still borrowed
+LL | 
+LL |     deref(p);
+   |           - borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/closure-requirements/issue-58127-mutliple-requirements.rs b/src/test/ui/nll/closure-requirements/issue-58127-mutliple-requirements.rs
new file mode 100644
index 0000000..71d5d40
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/issue-58127-mutliple-requirements.rs
@@ -0,0 +1,40 @@
+// revisions: migrate nll
+//[migrate]compile-flags: -Z borrowck=migrate
+#![cfg_attr(nll, feature(nll))]
+
+// compile-pass
+
+// Test that we propagate region relations from closures precisely when there is
+// more than one non-local lower bound.
+
+// In this case the closure has signature
+// |x: &'4 mut (&'5 (&'1 str, &'2 str), &'3 str)| -> ..
+// We end up with a `'3: '5` constraint that we can propagate as
+// `'3: '1`, `'3: '2`, but previously we approximated it as `'3: 'static`.
+
+// As an optimization, we primarily propagate bounds for the "representative"
+// of each SCC. As such we have these two similar cases where hopefully one
+// of them will test the case we want (case2, when this test was added).
+mod case1 {
+    fn f(s: &str) {
+        g(s, |x| h(x));
+    }
+
+    fn g<T, F>(_: T, _: F)
+    where F: Fn(&mut (&(T, T), T)) {}
+
+    fn h<T>(_: &mut (&(T, T), T)) {}
+}
+
+mod case2 {
+    fn f(s: &str) {
+        g(s, |x| h(x));
+    }
+
+    fn g<T, F>(_: T, _: F)
+    where F: Fn(&mut (T, &(T, T))) {}
+
+    fn h<T>(_: &mut (T, &(T, T))) {}
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.rs b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.rs
new file mode 100644
index 0000000..9535532
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.rs
@@ -0,0 +1,51 @@
+// Test where we fail to approximate due to demanding a postdom
+// relationship between our upper bounds.
+
+// compile-flags:-Zborrowck=mir -Zverbose
+
+#![feature(rustc_attrs)]
+
+use std::cell::Cell;
+
+// Callee knows that:
+//
+// 'x: 'a
+// 'x: 'b
+// 'c: 'y
+//
+// we have to prove that `'x: 'y`. We currently can only approximate
+// via a postdominator -- hence we fail to choose between `'a` and
+// `'b` here and report the error in the closure.
+fn establish_relationships<'a, 'b, 'c, F>(
+    _cell_a: Cell<&'a u32>,
+    _cell_b: Cell<&'b u32>,
+    _cell_c: Cell<&'c u32>,
+    _closure: F,
+) where
+    F: for<'x, 'y> FnMut(
+        Cell<&'a &'x u32>, // shows that 'x: 'a
+        Cell<&'b &'x u32>, // shows that 'x: 'b
+        Cell<&'y &'c u32>, // shows that 'c: 'y
+        Cell<&'x u32>,
+        Cell<&'y u32>,
+    ),
+{
+}
+
+fn demand_y<'x, 'y>(_cell_x: Cell<&'x u32>, _cell_y: Cell<&'y u32>, _y: &'y u32) {}
+
+#[rustc_regions]
+fn supply<'a, 'b, 'c>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>, cell_c: Cell<&'c u32>) {
+    establish_relationships(
+        cell_a,
+        cell_b,
+        cell_c,
+        |_outlives1, _outlives2, _outlives3, x, y| {
+            // Only works if 'x: 'y:
+            let p = x.get();
+            demand_y(x, y, p) //~ ERROR
+        },
+    );
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr
new file mode 100644
index 0000000..4db1f04
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr
@@ -0,0 +1,45 @@
+note: No external requirements
+  --> $DIR/propagate-approximated-fail-no-postdom.rs:43:9
+   |
+LL | /         |_outlives1, _outlives2, _outlives3, x, y| {
+LL | |             // Only works if 'x: 'y:
+LL | |             let p = x.get();
+LL | |             demand_y(x, y, p)
+LL | |         },
+   | |_________^
+   |
+   = note: defining type: DefId(0/1:20 ~ propagate_approximated_fail_no_postdom[317d]::supply[0]::{{closure}}[0]) with closure substs [
+               i16,
+               for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) &'_#3r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>)),
+           ]
+   = note: late-bound region is '_#4r
+   = note: late-bound region is '_#5r
+   = note: late-bound region is '_#6r
+
+error: lifetime may not live long enough
+  --> $DIR/propagate-approximated-fail-no-postdom.rs:46:13
+   |
+LL |         |_outlives1, _outlives2, _outlives3, x, y| {
+   |          ----------              ---------- has type `std::cell::Cell<&'2 &'_#3r u32>`
+   |          |
+   |          has type `std::cell::Cell<&'_#1r &'1 u32>`
+...
+LL |             demand_y(x, y, p)
+   |             ^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
+
+note: No external requirements
+  --> $DIR/propagate-approximated-fail-no-postdom.rs:38:1
+   |
+LL | / fn supply<'a, 'b, 'c>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>, cell_c: Cell<&'c u32>) {
+LL | |     establish_relationships(
+LL | |         cell_a,
+LL | |         cell_b,
+...  |
+LL | |     );
+LL | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:6 ~ propagate_approximated_fail_no_postdom[317d]::supply[0]) with substs []
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.rs b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.rs
new file mode 100644
index 0000000..1c409a1
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.rs
@@ -0,0 +1,50 @@
+// Rather convoluted setup where we infer a relationship between two
+// free regions in the closure signature (`'a` and `'b`) on the basis
+// of a relationship between two bound regions (`'x` and `'y`).
+//
+// The idea is that, thanks to invoking `demand_y`, `'x: 'y` must
+// hold, where `'x` and `'y` are bound regions. The closure can't
+// prove that directly, and because `'x` and `'y` are bound it cannot
+// ask the caller to prove it either. But it has bounds on `'x` and
+// `'y` in terms of `'a` and `'b`, and it can propagate a relationship
+// between `'a` and `'b` to the caller.
+//
+// Note: the use of `Cell` here is to introduce invariance. One less
+// variable.
+
+// compile-flags:-Zborrowck=mir -Zverbose
+
+#![feature(rustc_attrs)]
+
+use std::cell::Cell;
+
+// Callee knows that:
+//
+// 'x: 'a
+// 'b: 'y
+//
+// so if we are going to ensure that `'x: 'y`, then `'a: 'b` must
+// hold.
+fn establish_relationships<'a, 'b, F>(_cell_a: &Cell<&'a u32>, _cell_b: &Cell<&'b u32>, _closure: F)
+where
+    F: for<'x, 'y> FnMut(
+        &Cell<&'a &'x u32>, // shows that 'x: 'a
+        &Cell<&'y &'b u32>, // shows that 'b: 'y
+        &Cell<&'x u32>,
+        &Cell<&'y u32>,
+    ),
+{
+}
+
+fn demand_y<'x, 'y>(_cell_x: &Cell<&'x u32>, _cell_y: &Cell<&'y u32>, _y: &'y u32) {}
+
+#[rustc_regions]
+fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
+    establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
+        // Only works if 'x: 'y:
+        demand_y(x, y, x.get())
+        //~^ ERROR lifetime may not live long enough
+    });
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr
new file mode 100644
index 0000000..7dedae7
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr
@@ -0,0 +1,47 @@
+note: External requirements
+  --> $DIR/propagate-approximated-ref.rs:43:47
+   |
+LL |       establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
+   |  _______________________________________________^
+LL | |         // Only works if 'x: 'y:
+LL | |         demand_y(x, y, x.get())
+LL | |
+LL | |     });
+   | |_____^
+   |
+   = note: defining type: DefId(0/1:18 ~ propagate_approximated_ref[317d]::supply[0]::{{closure}}[0]) with closure substs [
+               i16,
+               for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't0)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't2)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't3)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) u32>)),
+           ]
+   = note: late-bound region is '_#3r
+   = note: late-bound region is '_#4r
+   = note: number of external vids: 5
+   = note: where '_#1r: '_#2r
+
+note: No external requirements
+  --> $DIR/propagate-approximated-ref.rs:42:1
+   |
+LL | / fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
+LL | |     establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
+LL | |         // Only works if 'x: 'y:
+LL | |         demand_y(x, y, x.get())
+LL | |
+LL | |     });
+LL | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:6 ~ propagate_approximated_ref[317d]::supply[0]) with substs []
+
+error: lifetime may not live long enough
+  --> $DIR/propagate-approximated-ref.rs:45:9
+   |
+LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
+   |           --  -- lifetime `'b` defined here
+   |           |
+   |           lifetime `'a` defined here
+...
+LL |         demand_y(x, y, x.get())
+   |         ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'a` must outlive `'b`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.rs b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.rs
new file mode 100644
index 0000000..ab0bfb9
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.rs
@@ -0,0 +1,40 @@
+// Test a case where we setup relationships like `'x: 'a` or `'a: 'x`,
+// where `'x` is bound in closure type but `'a` is free. This forces
+// us to approximate `'x` one way or the other.
+
+// compile-flags:-Zborrowck=mir -Zverbose
+
+#![feature(rustc_attrs)]
+
+use std::cell::Cell;
+
+fn foo<'a, F>(_cell: Cell<&'a u32>, _f: F)
+where
+    F: for<'x> FnOnce(Cell<&'a u32>, Cell<&'x u32>),
+{
+}
+
+#[rustc_regions]
+fn case1() {
+    let a = 0;
+    let cell = Cell::new(&a);
+    foo(cell, |cell_a, cell_x| {
+        cell_a.set(cell_x.get()); // forces 'x: 'a, error in closure
+        //~^ ERROR
+    })
+}
+
+#[rustc_regions]
+fn case2() {
+    let a = 0;
+    let cell = Cell::new(&a);
+    //~^ ERROR `a` does not live long enough
+
+    // As you can see in the stderr output, this closure propoagates a
+    // requirement that `'a: 'static'.
+    foo(cell, |cell_a, cell_x| {
+        cell_x.set(cell_a.get()); // forces 'a: 'x, implies 'a = 'static -> borrow error
+    })
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr
new file mode 100644
index 0000000..b2d7fd8
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr
@@ -0,0 +1,85 @@
+note: No external requirements
+  --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:21:15
+   |
+LL |       foo(cell, |cell_a, cell_x| {
+   |  _______________^
+LL | |         cell_a.set(cell_x.get()); // forces 'x: 'a, error in closure
+LL | |
+LL | |     })
+   | |_____^
+   |
+   = note: defining type: DefId(0/1:12 ~ propagate_approximated_shorter_to_static_comparing_against_free[317d]::case1[0]::{{closure}}[0]) with closure substs [
+               i32,
+               for<'r> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>)),
+           ]
+
+error[E0521]: borrowed data escapes outside of closure
+  --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:22:9
+   |
+LL |     foo(cell, |cell_a, cell_x| {
+   |                ------  ------ `cell_x` is a reference that is only valid in the closure body
+   |                |
+   |                `cell_a` is declared here, outside of the closure body
+LL |         cell_a.set(cell_x.get()); // forces 'x: 'a, error in closure
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^ `cell_x` escapes the closure body here
+
+note: No external requirements
+  --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:18:1
+   |
+LL | / fn case1() {
+LL | |     let a = 0;
+LL | |     let cell = Cell::new(&a);
+LL | |     foo(cell, |cell_a, cell_x| {
+...  |
+LL | |     })
+LL | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:5 ~ propagate_approximated_shorter_to_static_comparing_against_free[317d]::case1[0]) with substs []
+
+note: External requirements
+  --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:35:15
+   |
+LL |       foo(cell, |cell_a, cell_x| {
+   |  _______________^
+LL | |         cell_x.set(cell_a.get()); // forces 'a: 'x, implies 'a = 'static -> borrow error
+LL | |     })
+   | |_____^
+   |
+   = note: defining type: DefId(0/1:13 ~ propagate_approximated_shorter_to_static_comparing_against_free[317d]::case2[0]::{{closure}}[0]) with closure substs [
+               i32,
+               for<'r> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>)),
+           ]
+   = note: number of external vids: 2
+   = note: where '_#1r: '_#0r
+
+note: No external requirements
+  --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:28:1
+   |
+LL | / fn case2() {
+LL | |     let a = 0;
+LL | |     let cell = Cell::new(&a);
+LL | |
+...  |
+LL | |     })
+LL | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:6 ~ propagate_approximated_shorter_to_static_comparing_against_free[317d]::case2[0]) with substs []
+
+error[E0597]: `a` does not live long enough
+  --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:30:26
+   |
+LL |     let cell = Cell::new(&a);
+   |                ----------^^-
+   |                |         |
+   |                |         borrowed value does not live long enough
+   |                argument requires that `a` is borrowed for `'static`
+...
+LL | }
+   | - `a` dropped here while still borrowed
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0521, E0597.
+For more information about an error, try `rustc --explain E0521`.
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.rs b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.rs
new file mode 100644
index 0000000..779c367
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.rs
@@ -0,0 +1,40 @@
+// Test a case where we are trying to prove `'x: 'y` and are forced to
+// approximate the shorter end-point (`'y`) to with `'static`. This is
+// because `'y` is higher-ranked but we know of no relations to other
+// regions. Note that `'static` shows up in the stderr output as `'0`.
+
+// compile-flags:-Zborrowck=mir -Zverbose
+
+#![feature(rustc_attrs)]
+
+use std::cell::Cell;
+
+// Callee knows that:
+//
+// 'x: 'a
+//
+// so the only way we can ensure that `'x: 'y` is to show that
+// `'a: 'static`.
+fn establish_relationships<'a, 'b, F>(_cell_a: &Cell<&'a u32>, _cell_b: &Cell<&'b u32>, _closure: F)
+where
+    F: for<'x, 'y> FnMut(
+        &Cell<&'a &'x u32>, // shows that 'x: 'a
+        &Cell<&'x u32>,
+        &Cell<&'y u32>,
+    ),
+{
+}
+
+fn demand_y<'x, 'y>(_cell_x: &Cell<&'x u32>, _cell_y: &Cell<&'y u32>, _y: &'y u32) {}
+
+#[rustc_regions]
+fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
+    establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
+        //~^ ERROR borrowed data escapes outside of function
+
+        // Only works if 'x: 'y:
+        demand_y(x, y, x.get())
+    });
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr
new file mode 100644
index 0000000..e30e2df
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr
@@ -0,0 +1,51 @@
+note: External requirements
+  --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:32:47
+   |
+LL |       establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
+   |  _______________________________________________^
+LL | |
+LL | |
+LL | |         // Only works if 'x: 'y:
+LL | |         demand_y(x, y, x.get())
+LL | |     });
+   | |_____^
+   |
+   = note: defining type: DefId(0/1:18 ~ propagate_approximated_shorter_to_static_no_bound[317d]::supply[0]::{{closure}}[0]) with closure substs [
+               i16,
+               for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't0)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't2)) u32>)),
+           ]
+   = note: late-bound region is '_#2r
+   = note: late-bound region is '_#3r
+   = note: number of external vids: 4
+   = note: where '_#1r: '_#0r
+
+note: No external requirements
+  --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:31:1
+   |
+LL | / fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
+LL | |     establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
+LL | |
+LL | |
+...  |
+LL | |     });
+LL | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:6 ~ propagate_approximated_shorter_to_static_no_bound[317d]::supply[0]) with substs []
+
+error[E0521]: borrowed data escapes outside of function
+  --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:32:5
+   |
+LL |   fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
+   |                     ------ `cell_a` is a reference that is only valid in the function body
+LL | /     establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
+LL | |
+LL | |
+LL | |         // Only works if 'x: 'y:
+LL | |         demand_y(x, y, x.get())
+LL | |     });
+   | |______^ `cell_a` escapes the function body here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0521`.
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.rs b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.rs
new file mode 100644
index 0000000..fbf4be7
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.rs
@@ -0,0 +1,43 @@
+// Test a case where we are trying to prove `'x: 'y` and are forced to
+// approximate the shorter end-point (`'y`) to with `'static`. This is
+// because `'y` is higher-ranked but we know of only irrelevant
+// relations to other regions. Note that `'static` shows up in the
+// stderr output as `'0`.
+
+// compile-flags:-Zborrowck=mir -Zverbose
+
+#![feature(rustc_attrs)]
+
+use std::cell::Cell;
+
+// Callee knows that:
+//
+// 'x: 'a
+// 'y: 'b
+//
+// so the only way we can ensure that `'x: 'y` is to show that
+// `'a: 'static`.
+fn establish_relationships<'a, 'b, F>(_cell_a: &Cell<&'a u32>, _cell_b: &Cell<&'b u32>, _closure: F)
+where
+    F: for<'x, 'y> FnMut(
+        &Cell<&'a &'x u32>, // shows that 'x: 'a
+        &Cell<&'b &'y u32>, // shows that 'y: 'b
+        &Cell<&'x u32>,
+        &Cell<&'y u32>,
+    ),
+{
+}
+
+fn demand_y<'x, 'y>(_cell_x: &Cell<&'x u32>, _cell_y: &Cell<&'y u32>, _y: &'y u32) {}
+
+#[rustc_regions]
+fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
+    establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
+        //~^ ERROR borrowed data escapes outside of function
+
+        // Only works if 'x: 'y:
+        demand_y(x, y, x.get())
+    });
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr
new file mode 100644
index 0000000..ec60859
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr
@@ -0,0 +1,51 @@
+note: External requirements
+  --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:35:47
+   |
+LL |       establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
+   |  _______________________________________________^
+LL | |
+LL | |
+LL | |         // Only works if 'x: 'y:
+LL | |         demand_y(x, y, x.get())
+LL | |     });
+   | |_____^
+   |
+   = note: defining type: DefId(0/1:18 ~ propagate_approximated_shorter_to_static_wrong_bound[317d]::supply[0]::{{closure}}[0]) with closure substs [
+               i16,
+               for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't0)) std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't2)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't3)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) u32>)),
+           ]
+   = note: late-bound region is '_#3r
+   = note: late-bound region is '_#4r
+   = note: number of external vids: 5
+   = note: where '_#1r: '_#0r
+
+note: No external requirements
+  --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:34:1
+   |
+LL | / fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
+LL | |     establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
+LL | |
+LL | |
+...  |
+LL | |     });
+LL | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:6 ~ propagate_approximated_shorter_to_static_wrong_bound[317d]::supply[0]) with substs []
+
+error[E0521]: borrowed data escapes outside of function
+  --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:35:5
+   |
+LL |   fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
+   |                     ------ `cell_a` is a reference that is only valid in the function body
+LL | /     establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
+LL | |
+LL | |
+LL | |         // Only works if 'x: 'y:
+LL | |         demand_y(x, y, x.get())
+LL | |     });
+   | |______^ `cell_a` escapes the function body here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0521`.
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-val.rs b/src/test/ui/nll/closure-requirements/propagate-approximated-val.rs
new file mode 100644
index 0000000..233a5dc
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-val.rs
@@ -0,0 +1,43 @@
+// A simpler variant of `outlives-from-argument` where cells are
+// passed by value.
+//
+// This is simpler because there are no "extraneous" region
+// relationships. In the 'main' variant, there are a number of
+// anonymous regions as well.
+
+// compile-flags:-Zborrowck=mir -Zverbose
+
+#![feature(rustc_attrs)]
+
+use std::cell::Cell;
+
+// Callee knows that:
+//
+// 'x: 'a
+// 'b: 'y
+//
+// so if we are going to ensure that `'x: 'y`, then `'a: 'b` must
+// hold.
+fn establish_relationships<'a, 'b, F>(_cell_a: Cell<&'a u32>, _cell_b: Cell<&'b u32>, _closure: F)
+where
+    F: for<'x, 'y> FnMut(
+        Cell<&'a &'x u32>, // shows that 'x: 'a
+        Cell<&'y &'b u32>, // shows that 'b: 'y
+        Cell<&'x u32>,
+        Cell<&'y u32>,
+    ),
+{
+}
+
+fn demand_y<'x, 'y>(_outlives1: Cell<&&'x u32>, _outlives2: Cell<&'y &u32>, _y: &'y u32) {}
+
+#[rustc_regions]
+fn test<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
+    establish_relationships(cell_a, cell_b, |outlives1, outlives2, x, y| {
+        // Only works if 'x: 'y:
+        demand_y(outlives1, outlives2, x.get())
+        //~^ ERROR lifetime may not live long enough
+    });
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr
new file mode 100644
index 0000000..223c29f
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr
@@ -0,0 +1,47 @@
+note: External requirements
+  --> $DIR/propagate-approximated-val.rs:36:45
+   |
+LL |       establish_relationships(cell_a, cell_b, |outlives1, outlives2, x, y| {
+   |  _____________________________________________^
+LL | |         // Only works if 'x: 'y:
+LL | |         demand_y(outlives1, outlives2, x.get())
+LL | |
+LL | |     });
+   | |_____^
+   |
+   = note: defining type: DefId(0/1:18 ~ propagate_approximated_val[317d]::test[0]::{{closure}}[0]) with closure substs [
+               i16,
+               for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>)),
+           ]
+   = note: late-bound region is '_#3r
+   = note: late-bound region is '_#4r
+   = note: number of external vids: 5
+   = note: where '_#1r: '_#2r
+
+note: No external requirements
+  --> $DIR/propagate-approximated-val.rs:35:1
+   |
+LL | / fn test<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
+LL | |     establish_relationships(cell_a, cell_b, |outlives1, outlives2, x, y| {
+LL | |         // Only works if 'x: 'y:
+LL | |         demand_y(outlives1, outlives2, x.get())
+LL | |
+LL | |     });
+LL | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:6 ~ propagate_approximated_val[317d]::test[0]) with substs []
+
+error: lifetime may not live long enough
+  --> $DIR/propagate-approximated-val.rs:38:9
+   |
+LL | fn test<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
+   |         --  -- lifetime `'b` defined here
+   |         |
+   |         lifetime `'a` defined here
+...
+LL |         demand_y(outlives1, outlives2, x.get())
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'a` must outlive `'b`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.rs b/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.rs
new file mode 100644
index 0000000..d1945f4
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.rs
@@ -0,0 +1,50 @@
+// Test where we might in theory be able to see that the relationship
+// between two bound regions is true within closure and hence have no
+// need to propagate; but in fact we do because identity of free
+// regions is erased.
+
+// compile-flags:-Zborrowck=mir -Zverbose
+// compile-pass
+
+#![feature(rustc_attrs)]
+
+use std::cell::Cell;
+
+// In theory, callee knows that:
+//
+// 'x: 'a
+// 'a: 'y
+//
+// and hence could satisfy that `'x: 'y` locally. However, in our
+// checking, we ignore the precise free regions that come into the
+// region and just assign each position a distinct universally bound
+// region. Hence, we propagate a constraint to our caller that will
+// wind up being solvable.
+fn establish_relationships<'a, F>(
+    _cell_a: Cell<&'a u32>,
+    _closure: F,
+) where
+    F: for<'x, 'y> FnMut(
+        Cell<&'a &'x u32>, // shows that 'x: 'a
+        Cell<&'y &'a u32>, // shows that 'a: 'y
+        Cell<&'x u32>,
+        Cell<&'y u32>,
+    ),
+{
+}
+
+fn demand_y<'x, 'y>(_cell_x: Cell<&'x u32>, _cell_y: Cell<&'y u32>, _y: &'y u32) {}
+
+#[rustc_regions]
+fn supply<'a>(cell_a: Cell<&'a u32>) {
+    establish_relationships(
+        cell_a,
+        |_outlives1, _outlives2, x, y| {
+            // Only works if 'x: 'y:
+            let p = x.get();
+            demand_y(x, y, p)
+        },
+    );
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr b/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr
new file mode 100644
index 0000000..d618b4d
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr
@@ -0,0 +1,32 @@
+note: External requirements
+  --> $DIR/propagate-despite-same-free-region.rs:42:9
+   |
+LL | /         |_outlives1, _outlives2, x, y| {
+LL | |             // Only works if 'x: 'y:
+LL | |             let p = x.get();
+LL | |             demand_y(x, y, p)
+LL | |         },
+   | |_________^
+   |
+   = note: defining type: DefId(0/1:16 ~ propagate_despite_same_free_region[317d]::supply[0]::{{closure}}[0]) with closure substs [
+               i16,
+               for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>)),
+           ]
+   = note: late-bound region is '_#3r
+   = note: number of external vids: 4
+   = note: where '_#1r: '_#2r
+
+note: No external requirements
+  --> $DIR/propagate-despite-same-free-region.rs:39:1
+   |
+LL | / fn supply<'a>(cell_a: Cell<&'a u32>) {
+LL | |     establish_relationships(
+LL | |         cell_a,
+LL | |         |_outlives1, _outlives2, x, y| {
+...  |
+LL | |     );
+LL | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:6 ~ propagate_despite_same_free_region[317d]::supply[0]) with substs []
+
diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.rs b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.rs
new file mode 100644
index 0000000..37d4713
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.rs
@@ -0,0 +1,42 @@
+// Similarly to escape-argument-callee, a test case where the closure
+// requires a relationship between 2 unrelated higher-ranked regions,
+// with no helpful relations between the HRRs and free regions.
+//
+// In this case, the error is reported by the closure itself. This is
+// because it is unable to approximate the higher-ranked region `'x`,
+// as it knows of no relationships between `'x` and any
+// non-higher-ranked regions.
+
+// compile-flags:-Zborrowck=mir -Zverbose
+
+#![feature(rustc_attrs)]
+
+use std::cell::Cell;
+
+// Callee knows that:
+//
+// 'b: 'y
+//
+// but this doesn't really help us in proving that `'x: 'y`, so closure gets an error.
+fn establish_relationships<'a, 'b, F>(_cell_a: &Cell<&'a u32>, _cell_b: &Cell<&'b u32>, _closure: F)
+where
+    F: for<'x, 'y> FnMut(
+        &Cell<&'y &'b u32>, // shows that 'b: 'y
+        &Cell<&'x u32>,
+        &Cell<&'y u32>,
+    ),
+{
+}
+
+fn demand_y<'x, 'y>(_cell_x: &Cell<&'x u32>, _cell_y: &Cell<&'y u32>, _y: &'y u32) {}
+
+#[rustc_regions]
+fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
+    establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
+        // Only works if 'x: 'y:
+        demand_y(x, y, x.get())
+        //~^ ERROR
+    });
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr
new file mode 100644
index 0000000..07fb4d0
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr
@@ -0,0 +1,45 @@
+note: No external requirements
+  --> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:35:47
+   |
+LL |       establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
+   |  _______________________________________________^
+LL | |         // Only works if 'x: 'y:
+LL | |         demand_y(x, y, x.get())
+LL | |
+LL | |     });
+   | |_____^
+   |
+   = note: defining type: DefId(0/1:18 ~ propagate_fail_to_approximate_longer_no_bounds[317d]::supply[0]::{{closure}}[0]) with closure substs [
+               i16,
+               for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't0)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't2)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>)),
+           ]
+   = note: late-bound region is '_#2r
+   = note: late-bound region is '_#3r
+
+error: lifetime may not live long enough
+  --> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:37:9
+   |
+LL |     establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
+   |                                                ---------  - has type `&'_#7r std::cell::Cell<&'1 u32>`
+   |                                                |
+   |                                                has type `&'_#5r std::cell::Cell<&'2 &'_#1r u32>`
+LL |         // Only works if 'x: 'y:
+LL |         demand_y(x, y, x.get())
+   |         ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
+
+note: No external requirements
+  --> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:34:1
+   |
+LL | / fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
+LL | |     establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
+LL | |         // Only works if 'x: 'y:
+LL | |         demand_y(x, y, x.get())
+LL | |
+LL | |     });
+LL | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:6 ~ propagate_fail_to_approximate_longer_no_bounds[317d]::supply[0]) with substs []
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.rs b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.rs
new file mode 100644
index 0000000..c1467fc
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.rs
@@ -0,0 +1,46 @@
+// Similarly to escape-argument-callee, a test case where the closure
+// requires a relationship between 2 unrelated higher-ranked regions,
+// with no helpful relations between the HRRs and free regions.
+//
+// In this case, the error is reported by the closure itself. This is
+// because it is unable to approximate the higher-ranked region `'x`,
+// as it only knows of regions that `'x` is outlived by, and none that
+// `'x` outlives.
+
+// compile-flags:-Zborrowck=mir -Zverbose
+
+#![feature(rustc_attrs)]
+
+use std::cell::Cell;
+
+// Callee knows that:
+//
+// 'a: 'x
+// 'b: 'y
+//
+// but this doesn't really help us in proving that `'x: 'y`, so
+// closure gets an error.  In particular, we would need to know that
+// `'x: 'a`, so that we could approximate `'x` "downwards" to `'a`.
+fn establish_relationships<'a, 'b, F>(_cell_a: &Cell<&'a u32>, _cell_b: &Cell<&'b u32>, _closure: F)
+where
+    F: for<'x, 'y> FnMut(
+        &Cell<&'x &'a u32>, // shows that 'a: 'x
+        &Cell<&'y &'b u32>, // shows that 'b: 'y
+        &Cell<&'x u32>,
+        &Cell<&'y u32>,
+    ),
+{
+}
+
+fn demand_y<'x, 'y>(_cell_x: &Cell<&'x u32>, _cell_y: &Cell<&'y u32>, _y: &'y u32) {}
+
+#[rustc_regions]
+fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
+    establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
+        // Only works if 'x: 'y:
+        demand_y(x, y, x.get())
+        //~^ ERROR
+    });
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr
new file mode 100644
index 0000000..a0744c2
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr
@@ -0,0 +1,45 @@
+note: No external requirements
+  --> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:39:47
+   |
+LL |       establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
+   |  _______________________________________________^
+LL | |         // Only works if 'x: 'y:
+LL | |         demand_y(x, y, x.get())
+LL | |
+LL | |     });
+   | |_____^
+   |
+   = note: defining type: DefId(0/1:18 ~ propagate_fail_to_approximate_longer_wrong_bounds[317d]::supply[0]::{{closure}}[0]) with closure substs [
+               i16,
+               for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't0)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't2)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't3)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) u32>)),
+           ]
+   = note: late-bound region is '_#3r
+   = note: late-bound region is '_#4r
+
+error: lifetime may not live long enough
+  --> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:41:9
+   |
+LL |     establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
+   |                                                ----------  ---------- has type `&'_#8r std::cell::Cell<&'2 &'_#2r u32>`
+   |                                                |
+   |                                                has type `&'_#6r std::cell::Cell<&'1 &'_#1r u32>`
+LL |         // Only works if 'x: 'y:
+LL |         demand_y(x, y, x.get())
+   |         ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
+
+note: No external requirements
+  --> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:38:1
+   |
+LL | / fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
+LL | |     establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
+LL | |         // Only works if 'x: 'y:
+LL | |         demand_y(x, y, x.get())
+LL | |
+LL | |     });
+LL | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:6 ~ propagate_fail_to_approximate_longer_wrong_bounds[317d]::supply[0]) with substs []
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/closure-requirements/propagate-from-trait-match.rs b/src/test/ui/nll/closure-requirements/propagate-from-trait-match.rs
new file mode 100644
index 0000000..a578e95
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/propagate-from-trait-match.rs
@@ -0,0 +1,49 @@
+// Test that regions which appear only in the closure's generics (in
+// this case, `'a`) are properly mapped to the creator's generics. In
+// this case, the closure constrains its type parameter `T` to outlive
+// the same `'a` for which it implements `Trait`, which can only be the `'a`
+// from the function definition.
+
+// compile-flags:-Zborrowck=mir -Zverbose
+
+#![feature(rustc_attrs)]
+#![allow(dead_code)]
+
+trait Trait<'a> {}
+
+fn establish_relationships<T, F>(value: T, closure: F)
+where
+    F: FnOnce(T),
+{
+    closure(value)
+}
+
+fn require<'a, T>(t: T)
+where
+    T: Trait<'a> + 'a,
+{
+}
+
+#[rustc_regions]
+fn supply<'a, T>(value: T)
+where
+    T: Trait<'a>,
+{
+    establish_relationships(value, |value| {
+        //~^ ERROR the parameter type `T` may not live long enough
+
+        // This function call requires that
+        //
+        // (a) T: Trait<'a>
+        //
+        // and
+        //
+        // (b) T: 'a
+        //
+        // The latter does not hold.
+
+        require(value);
+    });
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr b/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr
new file mode 100644
index 0000000..282246f
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr
@@ -0,0 +1,57 @@
+note: External requirements
+  --> $DIR/propagate-from-trait-match.rs:32:36
+   |
+LL |       establish_relationships(value, |value| {
+   |  ____________________________________^
+LL | |
+LL | |
+LL | |         // This function call requires that
+...  |
+LL | |         require(value);
+LL | |     });
+   | |_____^
+   |
+   = note: defining type: DefId(0/1:16 ~ propagate_from_trait_match[317d]::supply[0]::{{closure}}[0]) with closure substs [
+               '_#1r,
+               T,
+               i32,
+               extern "rust-call" fn((T,)),
+           ]
+   = note: number of external vids: 2
+   = note: where T: '_#1r
+
+note: No external requirements
+  --> $DIR/propagate-from-trait-match.rs:28:1
+   |
+LL | / fn supply<'a, T>(value: T)
+LL | | where
+LL | |     T: Trait<'a>,
+LL | | {
+...  |
+LL | |     });
+LL | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:6 ~ propagate_from_trait_match[317d]::supply[0]) with substs [
+               '_#1r,
+               T,
+           ]
+
+error[E0309]: the parameter type `T` may not live long enough
+  --> $DIR/propagate-from-trait-match.rs:32:36
+   |
+LL |       establish_relationships(value, |value| {
+   |  ____________________________________^
+LL | |
+LL | |
+LL | |         // This function call requires that
+...  |
+LL | |         require(value);
+LL | |     });
+   | |_____^
+   |
+   = help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`...
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0309`.
diff --git a/src/test/ui/nll/closure-requirements/propagate-multiple-requirements.rs b/src/test/ui/nll/closure-requirements/propagate-multiple-requirements.rs
new file mode 100644
index 0000000..dbc659b
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/propagate-multiple-requirements.rs
@@ -0,0 +1,25 @@
+// Test that we propagate *all* requirements to the caller, not just the first
+// one.
+
+#![feature(nll)]
+
+fn once<S, T, U, F: FnOnce(S, T) -> U>(f: F, s: S, t: T) -> U {
+    f(s, t)
+}
+
+pub fn dangle() -> &'static [i32] {
+    let other_local_arr = [0, 2, 4];
+    let local_arr = other_local_arr;
+    let mut out: &mut &'static [i32] = &mut (&[1] as _);
+    once(|mut z: &[i32], mut out_val: &mut &[i32]| {
+        // We unfortunately point to the first use in the closure in the error
+        // message
+        z = &local_arr; //~ ERROR
+        *out_val = &local_arr;
+    }, &[] as &[_], &mut *out);
+    *out
+}
+
+fn main() {
+    println!("{:?}", dangle());
+}
diff --git a/src/test/ui/nll/closure-requirements/propagate-multiple-requirements.stderr b/src/test/ui/nll/closure-requirements/propagate-multiple-requirements.stderr
new file mode 100644
index 0000000..332724d
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/propagate-multiple-requirements.stderr
@@ -0,0 +1,17 @@
+error[E0597]: `local_arr` does not live long enough
+  --> $DIR/propagate-multiple-requirements.rs:17:14
+   |
+LL |     let mut out: &mut &'static [i32] = &mut (&[1] as _);
+   |                  ------------------- type annotation requires that `local_arr` is borrowed for `'static`
+LL |     once(|mut z: &[i32], mut out_val: &mut &[i32]| {
+   |          ----------------------------------------- value captured here
+...
+LL |         z = &local_arr;
+   |              ^^^^^^^^^ borrowed value does not live long enough
+...
+LL | }
+   | - `local_arr` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.rs b/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.rs
new file mode 100644
index 0000000..ac2943f
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.rs
@@ -0,0 +1,13 @@
+// Basic test for free regions in the NLL code. This test ought to
+// report an error due to a reborrowing constraint. Right now, we get
+// a variety of errors from the older, AST-based machinery (notably
+// borrowck), and then we get the NLL error at the end.
+
+// compile-flags:-Zborrowck=mir -Zverbose
+
+fn foo(x: &u32) -> &'static u32 {
+    &*x
+        //~^ ERROR explicit lifetime required in the type of `x`
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.stderr b/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.stderr
new file mode 100644
index 0000000..e813f21
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.stderr
@@ -0,0 +1,11 @@
+error[E0621]: explicit lifetime required in the type of `x`
+  --> $DIR/region-lbr-anon-does-not-outlive-static.rs:9:5
+   |
+LL | fn foo(x: &u32) -> &'static u32 {
+   |           ---- help: add explicit lifetime `ReStatic` to the type of `x`: `&ReStatic u32`
+LL |     &*x
+   |     ^^^ lifetime `ReStatic` required
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.rs b/src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.rs
new file mode 100644
index 0000000..ce75e07
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.rs
@@ -0,0 +1,13 @@
+// Basic test for free regions in the NLL code. This test ought to
+// report an error due to a reborrowing constraint. Right now, we get
+// a variety of errors from the older, AST-based machinery (notably
+// borrowck), and then we get the NLL error at the end.
+
+// compile-flags:-Zborrowck=mir -Zverbose
+
+fn foo<'a>(x: &'a u32) -> &'static u32 {
+    &*x
+        //~^ ERROR
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.stderr b/src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.stderr
new file mode 100644
index 0000000..d0a24a2
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.stderr
@@ -0,0 +1,10 @@
+error: lifetime may not live long enough
+  --> $DIR/region-lbr-named-does-not-outlive-static.rs:9:5
+   |
+LL | fn foo<'a>(x: &'a u32) -> &'static u32 {
+   |        -- lifetime `'a` defined here
+LL |     &*x
+   |     ^^^ returning this value requires that `'a` must outlive `'static`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.rs b/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.rs
new file mode 100644
index 0000000..4d864c6
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.rs
@@ -0,0 +1,13 @@
+// Basic test for free regions in the NLL code. This test ought to
+// report an error due to a reborrowing constraint. Right now, we get
+// a variety of errors from the older, AST-based machinery (notably
+// borrowck), and then we get the NLL error at the end.
+
+// compile-flags:-Zborrowck=mir -Zverbose
+
+fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> &'b u32 {
+    &*x
+    //~^ ERROR lifetime may not live long enough
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.stderr b/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.stderr
new file mode 100644
index 0000000..6dc98a9
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.stderr
@@ -0,0 +1,12 @@
+error: lifetime may not live long enough
+  --> $DIR/region-lbr1-does-not-outlive-ebr2.rs:9:5
+   |
+LL | fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> &'b u32 {
+   |        --  -- lifetime `'b` defined here
+   |        |
+   |        lifetime `'a` defined here
+LL |     &*x
+   |     ^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/closure-requirements/region-lbr1-does-outlive-lbr2-because-implied-bound.rs b/src/test/ui/nll/closure-requirements/region-lbr1-does-outlive-lbr2-because-implied-bound.rs
new file mode 100644
index 0000000..66290f2
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/region-lbr1-does-outlive-lbr2-because-implied-bound.rs
@@ -0,0 +1,13 @@
+// Basic test for free regions in the NLL code. This test does not
+// report an error because of the (implied) bound that `'b: 'a`.
+
+// compile-flags:-Zborrowck=mir -Zverbose
+// compile-pass
+
+#![allow(warnings)]
+
+fn foo<'a, 'b>(x: &'a &'b u32) -> &'a u32 {
+    &**x
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/closure-requirements/return-wrong-bound-region.rs b/src/test/ui/nll/closure-requirements/return-wrong-bound-region.rs
new file mode 100644
index 0000000..5ac0063
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/return-wrong-bound-region.rs
@@ -0,0 +1,23 @@
+// Test closure that takes two references and is supposed to return
+// the first, but actually returns the second. This should fail within
+// the closure.
+
+// compile-flags:-Zborrowck=mir -Zverbose
+
+#![feature(rustc_attrs)]
+
+#[rustc_regions]
+fn test() {
+    expect_sig(|a, b| b); // ought to return `a`
+    //~^ ERROR
+}
+
+fn expect_sig<F>(f: F) -> F
+    where F: for<'a> FnMut(&'a i32, &i32) -> &'a i32
+{
+    f
+}
+
+fn deref(_p: &i32) { }
+
+fn main() { }
diff --git a/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr b/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr
new file mode 100644
index 0000000..c564541
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr
@@ -0,0 +1,33 @@
+note: No external requirements
+  --> $DIR/return-wrong-bound-region.rs:11:16
+   |
+LL |     expect_sig(|a, b| b); // ought to return `a`
+   |                ^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:9 ~ return_wrong_bound_region[317d]::test[0]::{{closure}}[0]) with closure substs [
+               i16,
+               for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) i32, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) i32)) -> &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) i32,
+           ]
+
+error: lifetime may not live long enough
+  --> $DIR/return-wrong-bound-region.rs:11:23
+   |
+LL |     expect_sig(|a, b| b); // ought to return `a`
+   |                 -  -  ^ closure was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |                 |  |
+   |                 |  has type `&'1 i32`
+   |                 has type `&'2 i32`
+
+note: No external requirements
+  --> $DIR/return-wrong-bound-region.rs:10:1
+   |
+LL | / fn test() {
+LL | |     expect_sig(|a, b| b); // ought to return `a`
+LL | |
+LL | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:3 ~ return_wrong_bound_region[317d]::test[0]) with substs []
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/closure-use-spans.rs b/src/test/ui/nll/closure-use-spans.rs
new file mode 100644
index 0000000..c7cd519
--- /dev/null
+++ b/src/test/ui/nll/closure-use-spans.rs
@@ -0,0 +1,23 @@
+// check that liveness due to a closure capture gives a special note
+
+#![feature(nll)]
+
+fn use_as_borrow_capture(mut x: i32) {
+    let y = &x;
+    x = 0; //~ ERROR
+    || *y;
+}
+
+fn use_as_borrow_mut_capture(mut x: i32) {
+    let y = &mut x;
+    x = 0; //~ ERROR
+    || *y = 1;
+}
+
+fn use_as_move_capture(mut x: i32) {
+    let y = &x;
+    x = 0; //~ ERROR
+    move || *y;
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/closure-use-spans.stderr b/src/test/ui/nll/closure-use-spans.stderr
new file mode 100644
index 0000000..20696da
--- /dev/null
+++ b/src/test/ui/nll/closure-use-spans.stderr
@@ -0,0 +1,33 @@
+error[E0506]: cannot assign to `x` because it is borrowed
+  --> $DIR/closure-use-spans.rs:7:5
+   |
+LL |     let y = &x;
+   |             -- borrow of `x` occurs here
+LL |     x = 0;
+   |     ^^^^^ assignment to borrowed `x` occurs here
+LL |     || *y;
+   |         - borrow later captured here by closure
+
+error[E0506]: cannot assign to `x` because it is borrowed
+  --> $DIR/closure-use-spans.rs:13:5
+   |
+LL |     let y = &mut x;
+   |             ------ borrow of `x` occurs here
+LL |     x = 0;
+   |     ^^^^^ assignment to borrowed `x` occurs here
+LL |     || *y = 1;
+   |         - borrow later captured here by closure
+
+error[E0506]: cannot assign to `x` because it is borrowed
+  --> $DIR/closure-use-spans.rs:19:5
+   |
+LL |     let y = &x;
+   |             -- borrow of `x` occurs here
+LL |     x = 0;
+   |     ^^^^^ assignment to borrowed `x` occurs here
+LL |     move || *y;
+   |              - borrow later captured here by closure
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/nll/closures-in-loops.rs b/src/test/ui/nll/closures-in-loops.rs
new file mode 100644
index 0000000..d2afa56
--- /dev/null
+++ b/src/test/ui/nll/closures-in-loops.rs
@@ -0,0 +1,26 @@
+// Test messages where a closure capture conflicts with itself because it's in
+// a loop.
+
+#![feature(nll)]
+
+fn repreated_move(x: String) {
+    for i in 0..10 {
+        || x; //~ ERROR
+    }
+}
+
+fn repreated_mut_borrow(mut x: String) {
+    let mut v = Vec::new();
+    for i in 0..10 {
+        v.push(|| x = String::new()); //~ ERROR
+    }
+}
+
+fn repreated_unique_borrow(x: &mut String) {
+    let mut v = Vec::new();
+    for i in 0..10 {
+        v.push(|| *x = String::new()); //~ ERROR
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/closures-in-loops.stderr b/src/test/ui/nll/closures-in-loops.stderr
new file mode 100644
index 0000000..6408293
--- /dev/null
+++ b/src/test/ui/nll/closures-in-loops.stderr
@@ -0,0 +1,31 @@
+error[E0382]: use of moved value: `x`
+  --> $DIR/closures-in-loops.rs:8:9
+   |
+LL | fn repreated_move(x: String) {
+   |                   - move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
+LL |     for i in 0..10 {
+LL |         || x;
+   |         ^^ - use occurs due to use in closure
+   |         |
+   |         value moved into closure here, in previous iteration of loop
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time
+  --> $DIR/closures-in-loops.rs:15:16
+   |
+LL |         v.push(|| x = String::new());
+   |                ^^ - borrows occur due to use of `x` in closure
+   |                |
+   |                mutable borrow starts here in previous iteration of loop
+
+error[E0524]: two closures require unique access to `x` at the same time
+  --> $DIR/closures-in-loops.rs:22:16
+   |
+LL |         v.push(|| *x = String::new());
+   |                ^^  - borrows occur due to use of `x` in closure
+   |                |
+   |                closures are constructed here in different iterations of loop
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0382, E0499, E0524.
+For more information about an error, try `rustc --explain E0382`.
diff --git a/src/test/ui/nll/constant-thread-locals-issue-47053.rs b/src/test/ui/nll/constant-thread-locals-issue-47053.rs
new file mode 100644
index 0000000..4dd0141
--- /dev/null
+++ b/src/test/ui/nll/constant-thread-locals-issue-47053.rs
@@ -0,0 +1,11 @@
+// Regression test for issue #47053
+
+#![feature(nll)]
+#![feature(thread_local)]
+
+#[thread_local]
+static FOO: isize = 5;
+
+fn main() {
+    FOO = 6; //~ ERROR cannot assign to immutable static item `FOO` [E0594]
+}
diff --git a/src/test/ui/nll/constant-thread-locals-issue-47053.stderr b/src/test/ui/nll/constant-thread-locals-issue-47053.stderr
new file mode 100644
index 0000000..ae056a9
--- /dev/null
+++ b/src/test/ui/nll/constant-thread-locals-issue-47053.stderr
@@ -0,0 +1,9 @@
+error[E0594]: cannot assign to immutable static item `FOO`
+  --> $DIR/constant-thread-locals-issue-47053.rs:10:5
+   |
+LL |     FOO = 6;
+   |     ^^^^^^^ cannot assign
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/nll/constant.rs b/src/test/ui/nll/constant.rs
new file mode 100644
index 0000000..2bc40fc
--- /dev/null
+++ b/src/test/ui/nll/constant.rs
@@ -0,0 +1,11 @@
+// Test that MIR borrowck and NLL analysis can handle constants of
+// arbitrary types without ICEs.
+
+// compile-flags:-Zborrowck=mir
+// compile-pass
+
+const HI: &str = "hi";
+
+fn main() {
+    assert_eq!(HI, "hi");
+}
diff --git a/src/test/ui/nll/decl-macro-illegal-copy.rs b/src/test/ui/nll/decl-macro-illegal-copy.rs
new file mode 100644
index 0000000..38bdb7d
--- /dev/null
+++ b/src/test/ui/nll/decl-macro-illegal-copy.rs
@@ -0,0 +1,29 @@
+// Regression test for #46314
+
+#![feature(nll)]
+#![feature(decl_macro)]
+
+struct NonCopy(String);
+
+struct Wrapper {
+    inner: NonCopy,
+}
+
+macro inner_copy($wrapper:ident) {
+    $wrapper.inner
+}
+
+fn main() {
+    let wrapper = Wrapper {
+        inner: NonCopy("foo".into()),
+    };
+    assert_two_non_copy(
+        inner_copy!(wrapper),
+        wrapper.inner,
+        //~^ ERROR use of moved value: `wrapper.inner` [E0382]
+    );
+}
+
+fn assert_two_non_copy(a: NonCopy, b: NonCopy) {
+    assert_eq!(a.0, b.0);
+}
diff --git a/src/test/ui/nll/decl-macro-illegal-copy.stderr b/src/test/ui/nll/decl-macro-illegal-copy.stderr
new file mode 100644
index 0000000..9232ff5
--- /dev/null
+++ b/src/test/ui/nll/decl-macro-illegal-copy.stderr
@@ -0,0 +1,14 @@
+error[E0382]: use of moved value: `wrapper.inner`
+  --> $DIR/decl-macro-illegal-copy.rs:22:9
+   |
+LL |     $wrapper.inner
+   |     -------------- value moved here
+...
+LL |         wrapper.inner,
+   |         ^^^^^^^^^^^^^ value used here after move
+   |
+   = note: move occurs because `wrapper.inner` has type `NonCopy`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/nll/do-not-ignore-lifetime-bounds-in-copy.rs b/src/test/ui/nll/do-not-ignore-lifetime-bounds-in-copy.rs
new file mode 100644
index 0000000..2a1321c
--- /dev/null
+++ b/src/test/ui/nll/do-not-ignore-lifetime-bounds-in-copy.rs
@@ -0,0 +1,13 @@
+// Test that the 'static bound from the Copy impl is respected. Regression test for #29149.
+
+#![feature(nll)]
+
+#[derive(Clone)] struct Foo<'a>(&'a u32);
+impl Copy for Foo<'static> {}
+
+fn main() {
+    let s = 2;
+    let a = Foo(&s); //~ ERROR `s` does not live long enough [E0597]
+    drop(a);
+    drop(a);
+}
diff --git a/src/test/ui/nll/do-not-ignore-lifetime-bounds-in-copy.stderr b/src/test/ui/nll/do-not-ignore-lifetime-bounds-in-copy.stderr
new file mode 100644
index 0000000..bf5c571
--- /dev/null
+++ b/src/test/ui/nll/do-not-ignore-lifetime-bounds-in-copy.stderr
@@ -0,0 +1,14 @@
+error[E0597]: `s` does not live long enough
+  --> $DIR/do-not-ignore-lifetime-bounds-in-copy.rs:10:17
+   |
+LL |     let a = Foo(&s);
+   |                 ^^ borrowed value does not live long enough
+LL |     drop(a);
+   |          - copying this value requires that `s` is borrowed for `'static`
+LL |     drop(a);
+LL | }
+   | - `s` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/drop-may-dangle.rs b/src/test/ui/nll/drop-may-dangle.rs
new file mode 100644
index 0000000..5c72225
--- /dev/null
+++ b/src/test/ui/nll/drop-may-dangle.rs
@@ -0,0 +1,35 @@
+// Basic test for liveness constraints: the region (`R1`) that appears
+// in the type of `p` includes the points after `&v[0]` up to (but not
+// including) the call to `use_x`. The `else` branch is not included.
+
+// compile-flags:-Zborrowck=mir
+// compile-pass
+
+#![allow(warnings)]
+#![feature(dropck_eyepatch)]
+
+fn use_x(_: usize) -> bool { true }
+
+fn main() {
+    let mut v = [1, 2, 3];
+    let p: WrapMayDangle<& /* R4 */ usize> = WrapMayDangle { value: &v[0] };
+    if true {
+        // `p` will get dropped at end of this block. However, because of
+        // the `#[may_dangle]` attribute, we do not need to consider R4
+        // live after this point.
+        use_x(*p.value);
+    } else {
+        v[0] += 1;
+        use_x(22);
+    }
+
+    v[0] += 1;
+}
+
+struct WrapMayDangle<T> {
+    value: T
+}
+
+unsafe impl<#[may_dangle] T> Drop for WrapMayDangle<T> {
+    fn drop(&mut self) { }
+}
diff --git a/src/test/ui/nll/drop-no-may-dangle.rs b/src/test/ui/nll/drop-no-may-dangle.rs
new file mode 100644
index 0000000..23f7f6c
--- /dev/null
+++ b/src/test/ui/nll/drop-no-may-dangle.rs
@@ -0,0 +1,32 @@
+// Basic test for liveness constraints: the region (`R1`) that appears
+// in the type of `p` must include everything until `p` is dropped
+// because of destructor. (Note that the stderr also identifies this
+// destructor in the error message.)
+
+// compile-flags:-Zborrowck=mir
+
+#![allow(warnings)]
+#![feature(dropck_eyepatch)]
+
+fn use_x(_: usize) -> bool { true }
+
+fn main() {
+    let mut v = [1, 2, 3];
+    let p: WrapMayNotDangle<&usize> = WrapMayNotDangle { value: &v[0] };
+    if true {
+        use_x(*p.value);
+    } else {
+        use_x(22);
+        v[0] += 1; //~ ERROR cannot assign to `v[_]` because it is borrowed
+    }
+
+    v[0] += 1; //~ ERROR cannot assign to `v[_]` because it is borrowed
+}
+
+struct WrapMayNotDangle<T> {
+    value: T
+}
+
+impl<T> Drop for WrapMayNotDangle<T> {
+    fn drop(&mut self) { }
+}
diff --git a/src/test/ui/nll/drop-no-may-dangle.stderr b/src/test/ui/nll/drop-no-may-dangle.stderr
new file mode 100644
index 0000000..e1d2b03
--- /dev/null
+++ b/src/test/ui/nll/drop-no-may-dangle.stderr
@@ -0,0 +1,26 @@
+error[E0506]: cannot assign to `v[_]` because it is borrowed
+  --> $DIR/drop-no-may-dangle.rs:20:9
+   |
+LL |     let p: WrapMayNotDangle<&usize> = WrapMayNotDangle { value: &v[0] };
+   |                                                                 ----- borrow of `v[_]` occurs here
+...
+LL |         v[0] += 1;
+   |         ^^^^^^^^^ assignment to borrowed `v[_]` occurs here
+...
+LL | }
+   | - borrow might be used here, when `p` is dropped and runs the `Drop` code for type `WrapMayNotDangle`
+
+error[E0506]: cannot assign to `v[_]` because it is borrowed
+  --> $DIR/drop-no-may-dangle.rs:23:5
+   |
+LL |     let p: WrapMayNotDangle<&usize> = WrapMayNotDangle { value: &v[0] };
+   |                                                                 ----- borrow of `v[_]` occurs here
+...
+LL |     v[0] += 1;
+   |     ^^^^^^^^^ assignment to borrowed `v[_]` occurs here
+LL | }
+   | - borrow might be used here, when `p` is dropped and runs the `Drop` code for type `WrapMayNotDangle`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/nll/enum-drop-access.rs b/src/test/ui/nll/enum-drop-access.rs
new file mode 100644
index 0000000..dc436d2
--- /dev/null
+++ b/src/test/ui/nll/enum-drop-access.rs
@@ -0,0 +1,51 @@
+#![feature(nll)]
+
+enum DropOption<T> {
+    Some(T),
+    None,
+}
+
+impl<T> Drop for DropOption<T> {
+    fn drop(&mut self) {}
+}
+
+// Dropping opt could access the value behind the reference,
+fn drop_enum(opt: DropOption<&mut i32>) -> Option<&mut i32> {
+    match opt {
+        DropOption::Some(&mut ref mut r) => { //~ ERROR
+            Some(r)
+        },
+        DropOption::None => None,
+    }
+}
+
+fn optional_drop_enum(opt: Option<DropOption<&mut i32>>) -> Option<&mut i32> {
+    match opt {
+        Some(DropOption::Some(&mut ref mut r)) => { //~ ERROR
+            Some(r)
+        },
+        Some(DropOption::None) | None => None,
+    }
+}
+
+// Ok, dropping opt doesn't access the reference
+fn optional_tuple(opt: Option<(&mut i32, String)>) -> Option<&mut i32> {
+    match opt {
+        Some((&mut ref mut r, _)) => {
+            Some(r)
+        },
+        None => None,
+    }
+}
+
+// Ok, dropping res doesn't access the Ok case.
+fn different_variants(res: Result<&mut i32, String>) -> Option<&mut i32> {
+    match res {
+        Ok(&mut ref mut r) => {
+            Some(r)
+        },
+        Err(_) => None,
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/enum-drop-access.stderr b/src/test/ui/nll/enum-drop-access.stderr
new file mode 100644
index 0000000..699179f
--- /dev/null
+++ b/src/test/ui/nll/enum-drop-access.stderr
@@ -0,0 +1,31 @@
+error[E0713]: borrow may still be in use when destructor runs
+  --> $DIR/enum-drop-access.rs:15:31
+   |
+LL | fn drop_enum(opt: DropOption<&mut i32>) -> Option<&mut i32> {
+   |                              - let's call the lifetime of this reference `'1`
+LL |     match opt {
+LL |         DropOption::Some(&mut ref mut r) => {
+   |                               ^^^^^^^^^
+LL |             Some(r)
+   |             ------- returning this value requires that `*opt.0` is borrowed for `'1`
+...
+LL | }
+   | - here, drop of `opt` needs exclusive access to `*opt.0`, because the type `DropOption<&mut i32>` implements the `Drop` trait
+
+error[E0713]: borrow may still be in use when destructor runs
+  --> $DIR/enum-drop-access.rs:24:36
+   |
+LL | fn optional_drop_enum(opt: Option<DropOption<&mut i32>>) -> Option<&mut i32> {
+   |                                              - let's call the lifetime of this reference `'1`
+LL |     match opt {
+LL |         Some(DropOption::Some(&mut ref mut r)) => {
+   |                                    ^^^^^^^^^
+LL |             Some(r)
+   |             ------- returning this value requires that `*opt.0.0` is borrowed for `'1`
+...
+LL | }
+   | - here, drop of `opt` needs exclusive access to `*opt.0.0`, because the type `DropOption<&mut i32>` implements the `Drop` trait
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0713`.
diff --git a/src/test/ui/nll/extra-unused-mut.rs b/src/test/ui/nll/extra-unused-mut.rs
new file mode 100644
index 0000000..d5f0b0d
--- /dev/null
+++ b/src/test/ui/nll/extra-unused-mut.rs
@@ -0,0 +1,63 @@
+// extra unused mut lint tests for #51918
+
+// run-pass
+
+#![feature(generators, nll)]
+#![deny(unused_mut)]
+
+fn ref_argument(ref _y: i32) {}
+
+// #51801
+fn mutable_upvar() {
+    let mut x = 0;
+    move || {
+        x = 1;
+    };
+}
+
+// #50897
+fn generator_mutable_upvar() {
+    let mut x = 0;
+    move || {
+        x = 1;
+        yield;
+    };
+}
+
+// #51830
+fn ref_closure_argument() {
+    let _ = Some(0).as_ref().map(|ref _a| true);
+}
+
+struct Expr {
+    attrs: Vec<u32>,
+}
+
+// #51904
+fn parse_dot_or_call_expr_with(mut attrs: Vec<u32>) {
+    let x = Expr { attrs: vec![] };
+    Some(Some(x)).map(|expr|
+        expr.map(|mut expr| {
+            attrs.push(666);
+            expr.attrs = attrs;
+            expr
+        })
+    );
+}
+
+// Found when trying to bootstrap rustc
+fn if_guard(x: Result<i32, i32>) {
+    match x {
+        Ok(mut r) | Err(mut r) if true => r = 1,
+        _ => (),
+    }
+}
+
+fn main() {
+    ref_argument(0);
+    mutable_upvar();
+    generator_mutable_upvar();
+    ref_closure_argument();
+    parse_dot_or_call_expr_with(Vec::new());
+    if_guard(Ok(0));
+}
diff --git a/src/test/ui/nll/generator-distinct-lifetime.rs b/src/test/ui/nll/generator-distinct-lifetime.rs
new file mode 100644
index 0000000..d479a61
--- /dev/null
+++ b/src/test/ui/nll/generator-distinct-lifetime.rs
@@ -0,0 +1,25 @@
+#![feature(generators, nll)]
+
+// Test for issue #47189. Here, both `s` and `t` are live for the
+// generator's lifetime, but within the generator they have distinct
+// lifetimes. We accept this code -- even though the borrow extends
+// over a yield -- because the data that is borrowed (`*x`) is not
+// stored on the stack.
+
+// compile-pass
+
+fn foo(x: &mut u32) {
+    move || {
+        let s = &mut *x;
+        yield;
+        *s += 1;
+
+        let t = &mut *x;
+        yield;
+        *t += 1;
+    };
+}
+
+fn main() {
+    foo(&mut 0);
+}
diff --git a/src/test/ui/nll/generator-upvar-mutability.rs b/src/test/ui/nll/generator-upvar-mutability.rs
new file mode 100644
index 0000000..fe4bc6b
--- /dev/null
+++ b/src/test/ui/nll/generator-upvar-mutability.rs
@@ -0,0 +1,14 @@
+// Check that generators respect the muatability of their upvars.
+
+#![feature(generators, nll)]
+
+fn mutate_upvar() {
+    let x = 0;
+    move || {
+        x = 1;
+        //~^ ERROR
+        yield;
+    };
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/generator-upvar-mutability.stderr b/src/test/ui/nll/generator-upvar-mutability.stderr
new file mode 100644
index 0000000..31b061b
--- /dev/null
+++ b/src/test/ui/nll/generator-upvar-mutability.stderr
@@ -0,0 +1,12 @@
+error[E0594]: cannot assign to `x`, as it is not declared as mutable
+  --> $DIR/generator-upvar-mutability.rs:8:9
+   |
+LL |     let x = 0;
+   |         - help: consider changing this to be mutable: `mut x`
+LL |     move || {
+LL |         x = 1;
+   |         ^^^^^ cannot assign
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/nll/get_default.rs b/src/test/ui/nll/get_default.rs
new file mode 100644
index 0000000..89f693b
--- /dev/null
+++ b/src/test/ui/nll/get_default.rs
@@ -0,0 +1,49 @@
+// Basic test for free regions in the NLL code. This test ought to
+// report an error due to a reborrowing constraint. Right now, we get
+// a variety of errors from the older, AST-based machinery (notably
+// borrowck), and then we get the NLL error at the end.
+
+// compile-flags:-Zborrowck=compare
+
+struct Map {
+}
+
+impl Map {
+    fn get(&self) -> Option<&String> { None }
+    fn set(&mut self, v: String) { }
+}
+
+fn ok(map: &mut Map) -> &String {
+    loop {
+        match map.get() {
+            Some(v) => {
+                return v;
+            }
+            None => {
+                map.set(String::new()); // Ideally, this would not error.
+                //~^ ERROR borrowed as immutable (Ast)
+                //~| ERROR borrowed as immutable (Mir)
+            }
+        }
+    }
+}
+
+fn err(map: &mut Map) -> &String {
+    loop {
+        match map.get() {
+            Some(v) => {
+                map.set(String::new()); // Both AST and MIR error here
+                //~^ ERROR borrowed as immutable (Mir)
+                //~| ERROR borrowed as immutable (Ast)
+                return v;
+            }
+            None => {
+                map.set(String::new()); // Ideally, just AST would error here
+                //~^ ERROR borrowed as immutable (Ast)
+                //~| ERROR borrowed as immutable (Mir)
+            }
+        }
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/get_default.stderr b/src/test/ui/nll/get_default.stderr
new file mode 100644
index 0000000..abb5343
--- /dev/null
+++ b/src/test/ui/nll/get_default.stderr
@@ -0,0 +1,84 @@
+error[E0502]: cannot borrow `*map` as mutable because it is also borrowed as immutable (Ast)
+  --> $DIR/get_default.rs:23:17
+   |
+LL |         match map.get() {
+   |               --- immutable borrow occurs here
+...
+LL |                 map.set(String::new()); // Ideally, this would not error.
+   |                 ^^^ mutable borrow occurs here
+...
+LL | }
+   | - immutable borrow ends here
+
+error[E0502]: cannot borrow `*map` as mutable because it is also borrowed as immutable (Ast)
+  --> $DIR/get_default.rs:35:17
+   |
+LL |         match map.get() {
+   |               --- immutable borrow occurs here
+LL |             Some(v) => {
+LL |                 map.set(String::new()); // Both AST and MIR error here
+   |                 ^^^ mutable borrow occurs here
+...
+LL | }
+   | - immutable borrow ends here
+
+error[E0502]: cannot borrow `*map` as mutable because it is also borrowed as immutable (Ast)
+  --> $DIR/get_default.rs:41:17
+   |
+LL |         match map.get() {
+   |               --- immutable borrow occurs here
+...
+LL |                 map.set(String::new()); // Ideally, just AST would error here
+   |                 ^^^ mutable borrow occurs here
+...
+LL | }
+   | - immutable borrow ends here
+
+error[E0502]: cannot borrow `*map` as mutable because it is also borrowed as immutable (Mir)
+  --> $DIR/get_default.rs:23:17
+   |
+LL | fn ok(map: &mut Map) -> &String {
+   |            - let's call the lifetime of this reference `'1`
+LL |     loop {
+LL |         match map.get() {
+   |               --- immutable borrow occurs here
+LL |             Some(v) => {
+LL |                 return v;
+   |                        - returning this value requires that `*map` is borrowed for `'1`
+...
+LL |                 map.set(String::new()); // Ideally, this would not error.
+   |                 ^^^ mutable borrow occurs here
+
+error[E0502]: cannot borrow `*map` as mutable because it is also borrowed as immutable (Mir)
+  --> $DIR/get_default.rs:35:17
+   |
+LL | fn err(map: &mut Map) -> &String {
+   |             - let's call the lifetime of this reference `'1`
+LL |     loop {
+LL |         match map.get() {
+   |               --- immutable borrow occurs here
+LL |             Some(v) => {
+LL |                 map.set(String::new()); // Both AST and MIR error here
+   |                 ^^^ mutable borrow occurs here
+...
+LL |                 return v;
+   |                        - returning this value requires that `*map` is borrowed for `'1`
+
+error[E0502]: cannot borrow `*map` as mutable because it is also borrowed as immutable (Mir)
+  --> $DIR/get_default.rs:41:17
+   |
+LL | fn err(map: &mut Map) -> &String {
+   |             - let's call the lifetime of this reference `'1`
+LL |     loop {
+LL |         match map.get() {
+   |               --- immutable borrow occurs here
+...
+LL |                 return v;
+   |                        - returning this value requires that `*map` is borrowed for `'1`
+...
+LL |                 map.set(String::new()); // Ideally, just AST would error here
+   |                 ^^^ mutable borrow occurs here
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/nll/guarantor-issue-46974.rs b/src/test/ui/nll/guarantor-issue-46974.rs
new file mode 100644
index 0000000..d0af468
--- /dev/null
+++ b/src/test/ui/nll/guarantor-issue-46974.rs
@@ -0,0 +1,21 @@
+// Test that NLL analysis propagates lifetimes correctly through
+// field accesses, Box accesses, etc.
+
+#![feature(nll)]
+
+fn foo(s: &mut (i32,)) -> i32 {
+    let t = &mut *s; // this borrow should last for the entire function
+    let x = &t.0;
+    *s = (2,); //~ ERROR cannot assign to `*s`
+    *x
+}
+
+fn bar(s: &Box<(i32,)>) -> &'static i32 {
+    // FIXME(#46983): error message should be better
+    &s.0 //~ ERROR explicit lifetime required in the type of `s` [E0621]
+}
+
+fn main() {
+    foo(&mut (0,));
+    bar(&Box::new((1,)));
+}
diff --git a/src/test/ui/nll/guarantor-issue-46974.stderr b/src/test/ui/nll/guarantor-issue-46974.stderr
new file mode 100644
index 0000000..8486c7d
--- /dev/null
+++ b/src/test/ui/nll/guarantor-issue-46974.stderr
@@ -0,0 +1,24 @@
+error[E0506]: cannot assign to `*s` because it is borrowed
+  --> $DIR/guarantor-issue-46974.rs:9:5
+   |
+LL |     let t = &mut *s; // this borrow should last for the entire function
+   |             ------- borrow of `*s` occurs here
+LL |     let x = &t.0;
+LL |     *s = (2,);
+   |     ^^^^^^^^^ assignment to borrowed `*s` occurs here
+LL |     *x
+   |     -- borrow later used here
+
+error[E0621]: explicit lifetime required in the type of `s`
+  --> $DIR/guarantor-issue-46974.rs:15:5
+   |
+LL | fn bar(s: &Box<(i32,)>) -> &'static i32 {
+   |           ------------ help: add explicit lifetime `'static` to the type of `s`: `&'static std::boxed::Box<(i32,)>`
+LL |     // FIXME(#46983): error message should be better
+LL |     &s.0
+   |     ^^^^ lifetime `'static` required
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0506, E0621.
+For more information about an error, try `rustc --explain E0506`.
diff --git a/src/test/ui/nll/issue-16223.rs b/src/test/ui/nll/issue-16223.rs
new file mode 100644
index 0000000..881e202
--- /dev/null
+++ b/src/test/ui/nll/issue-16223.rs
@@ -0,0 +1,53 @@
+// Regression test for #16223: without NLL the `if let` construct together with
+// the nested box-structure of `Root` causes an unwanted collateral move.
+
+// The exact error prevented here is:
+//
+// error[E0382]: use of collaterally moved value: `(root.boxed.rhs as SomeVariant::B).0`
+//   --> src/main.rs:55:29
+//    |
+// 56 |         lhs: SomeVariant::A(a),
+//    |                             - value moved here
+// 57 |         rhs: SomeVariant::B(b),
+//    |                             ^ value used here after move
+//    |
+//    = note: move occurs because the value has type `A`, which does not implement the `Copy` trait
+
+// compile-pass
+
+#![feature(nll)]
+#![feature(box_patterns)]
+
+struct Root {
+    boxed: Box<SetOfVariants>,
+}
+
+struct SetOfVariants {
+    lhs: SomeVariant,
+    rhs: SomeVariant,
+}
+
+enum SomeVariant {
+    A(A),
+    B(B),
+}
+
+struct A(String);
+struct B(String);
+
+fn main() {
+    let root = Root {
+        boxed: Box::new(SetOfVariants {
+            lhs: SomeVariant::A(A(String::from("This is A"))),
+            rhs: SomeVariant::B(B(String::from("This is B"))),
+        }),
+    };
+    if let box SetOfVariants {
+        lhs: SomeVariant::A(a),
+        rhs: SomeVariant::B(b),
+    } = root.boxed
+    {
+        println!("a = {}", a.0);
+        println!("b = {}", b.0);
+    }
+}
diff --git a/src/test/ui/nll/issue-21114-ebfull.rs b/src/test/ui/nll/issue-21114-ebfull.rs
new file mode 100644
index 0000000..f573896
--- /dev/null
+++ b/src/test/ui/nll/issue-21114-ebfull.rs
@@ -0,0 +1,20 @@
+// (this works, but only in NLL)
+// compile-pass
+#![feature(nll)]
+
+use std::collections::HashMap;
+use std::sync::Mutex;
+
+fn i_used_to_be_able_to(foo: &Mutex<HashMap<usize, usize>>) -> Vec<(usize, usize)> {
+    let mut foo = foo.lock().unwrap();
+
+    foo.drain().collect()
+}
+
+fn but_after_nightly_update_now_i_gotta(foo: &Mutex<HashMap<usize, usize>>) -> Vec<(usize, usize)> {
+    let mut foo = foo.lock().unwrap();
+
+    return foo.drain().collect();
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/issue-21114-kixunil.rs b/src/test/ui/nll/issue-21114-kixunil.rs
new file mode 100644
index 0000000..2add951
--- /dev/null
+++ b/src/test/ui/nll/issue-21114-kixunil.rs
@@ -0,0 +1,19 @@
+// (this works, but only in NLL)
+// compile-pass
+#![feature(nll)]
+
+fn from_stdin(min: u64) -> Vec<u64> {
+    use std::io::BufRead;
+
+    let stdin = std::io::stdin();
+    let stdin = stdin.lock();
+
+    stdin.lines()
+        .map(Result::unwrap)
+        .map(|val| val.parse())
+        .map(Result::unwrap)
+        .filter(|val| *val >= min)
+        .collect()
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.rs b/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.rs
new file mode 100644
index 0000000..abafd33
--- /dev/null
+++ b/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.rs
@@ -0,0 +1,66 @@
+// This test enumerates various cases of interest where a ADT or tuple is
+// partially initialized and then used in some way that is wrong *even*
+// after rust-lang/rust#54987 is implemented.
+//
+// See rust-lang/rust#21232, rust-lang/rust#54986, and rust-lang/rust#54987.
+//
+// See issue-21232-partial-init-and-use.rs for cases of tests that are
+// meant to compile and run successfully once rust-lang/rust#54987 is
+// implemented.
+
+#![feature(nll)]
+
+struct D {
+    x: u32,
+    s: S,
+}
+
+struct S {
+    y: u32,
+    z: u32,
+}
+
+
+impl Drop for D {
+    fn drop(&mut self) { }
+}
+
+fn cannot_partially_init_adt_with_drop() {
+    let d: D;
+    d.x = 10;
+    //~^ ERROR assign of possibly uninitialized variable: `d` [E0381]
+}
+
+fn cannot_partially_init_mutable_adt_with_drop() {
+    let mut d: D;
+    d.x = 10;
+    //~^ ERROR assign of possibly uninitialized variable: `d` [E0381]
+}
+
+fn cannot_partially_reinit_adt_with_drop() {
+    let mut d = D { x: 0, s: S{ y: 0, z: 0 } };
+    drop(d);
+    d.x = 10;
+    //~^ ERROR assign of moved value: `d` [E0382]
+}
+
+fn cannot_partially_init_inner_adt_via_outer_with_drop() {
+    let d: D;
+    d.s.y = 20;
+    //~^ ERROR assign to part of possibly uninitialized variable: `d` [E0381]
+}
+
+fn cannot_partially_init_inner_adt_via_mutable_outer_with_drop() {
+    let mut d: D;
+    d.s.y = 20;
+    //~^ ERROR assign to part of possibly uninitialized variable: `d` [E0381]
+}
+
+fn cannot_partially_reinit_inner_adt_via_outer_with_drop() {
+    let mut d = D { x: 0, s: S{ y: 0, z: 0} };
+    drop(d);
+    d.s.y = 20;
+    //~^ ERROR assign to part of moved value: `d` [E0382]
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.stderr b/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.stderr
new file mode 100644
index 0000000..54c728e
--- /dev/null
+++ b/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.stderr
@@ -0,0 +1,48 @@
+error[E0381]: assign of possibly uninitialized variable: `d`
+  --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:30:5
+   |
+LL |     d.x = 10;
+   |     ^^^^^^^^ use of possibly uninitialized `d`
+
+error[E0381]: assign of possibly uninitialized variable: `d`
+  --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:36:5
+   |
+LL |     d.x = 10;
+   |     ^^^^^^^^ use of possibly uninitialized `d`
+
+error[E0382]: assign of moved value: `d`
+  --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:43:5
+   |
+LL |     let mut d = D { x: 0, s: S{ y: 0, z: 0 } };
+   |         ----- move occurs because `d` has type `D`, which does not implement the `Copy` trait
+LL |     drop(d);
+   |          - value moved here
+LL |     d.x = 10;
+   |     ^^^^^^^^ value assigned here after move
+
+error[E0381]: assign to part of possibly uninitialized variable: `d`
+  --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:49:5
+   |
+LL |     d.s.y = 20;
+   |     ^^^^^^^^^^ use of possibly uninitialized `d.s`
+
+error[E0381]: assign to part of possibly uninitialized variable: `d`
+  --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:55:5
+   |
+LL |     d.s.y = 20;
+   |     ^^^^^^^^^^ use of possibly uninitialized `d.s`
+
+error[E0382]: assign to part of moved value: `d`
+  --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:62:5
+   |
+LL |     let mut d = D { x: 0, s: S{ y: 0, z: 0} };
+   |         ----- move occurs because `d` has type `D`, which does not implement the `Copy` trait
+LL |     drop(d);
+   |          - value moved here
+LL |     d.s.y = 20;
+   |     ^^^^^^^^^^ value partially assigned here after move
+
+error: aborting due to 6 previous errors
+
+Some errors occurred: E0381, E0382.
+For more information about an error, try `rustc --explain E0381`.
diff --git a/src/test/ui/nll/issue-21232-partial-init-and-use.rs b/src/test/ui/nll/issue-21232-partial-init-and-use.rs
new file mode 100644
index 0000000..633cbdb
--- /dev/null
+++ b/src/test/ui/nll/issue-21232-partial-init-and-use.rs
@@ -0,0 +1,311 @@
+// This test enumerates various cases of interest for partial
+// [re]initialization of ADTs and tuples.
+//
+// See rust-lang/rust#21232, rust-lang/rust#54986, and rust-lang/rust#54987.
+//
+// All of tests in this file are expected to change from being
+// rejected, at least under NLL (by rust-lang/rust#54986) to being
+// **accepted** when rust-lang/rust#54987 is implemented.
+// (That's why there are assertions in the code.)
+//
+// See issue-21232-partial-init-and-erroneous-use.rs for cases of
+// tests that are meant to continue failing to compile once
+// rust-lang/rust#54987 is implemented.
+
+#![feature(nll)]
+
+struct S<Y> {
+    x: u32,
+
+    // Note that even though `y` may implement `Drop`, under #54987 we
+    // will still allow partial initialization of `S` itself.
+    y: Y,
+}
+
+enum Void { }
+
+type B = Box<u32>;
+
+impl S<B> { fn new() -> Self { S { x: 0, y: Box::new(0) } } }
+
+fn borrow_s(s: &S<B>) { assert_eq!(s.x, 10); assert_eq!(*s.y, 20); }
+fn move_s(s: S<B>) {  assert_eq!(s.x, 10); assert_eq!(*s.y, 20); }
+fn borrow_field(x: &u32) { assert_eq!(*x, 10); }
+
+type T = (u32, B);
+type Tvoid = (u32, Void);
+
+fn borrow_t(t: &T) { assert_eq!(t.0, 10); assert_eq!(*t.1, 20); }
+fn move_t(t: T) {  assert_eq!(t.0, 10); assert_eq!(*t.1, 20); }
+
+struct Q<F> {
+    v: u32,
+    r: R<F>,
+}
+
+struct R<F> {
+    w: u32,
+    f: F,
+}
+
+impl<F> Q<F> { fn new(f: F) -> Self { Q { v: 0, r: R::new(f) } } }
+impl<F> R<F> { fn new(f: F) -> Self { R { w: 0, f } } }
+
+// Axes to cover:
+// * local/field: Is the structure in a local or a field
+// * fully/partial/void: Are we fully initializing it before using any part?
+//                       Is whole type empty due to a void component?
+// * init/reinit: First initialization, or did we previously inititalize and then move out?
+// * struct/tuple: Is this a struct or a (X, Y).
+//
+// As a shorthand for the cases above, adding a numeric summary to
+// each test's fn name to denote each point on each axis.
+//
+// e.g., 1000 = field fully init struct; 0211 = local void reinit tuple
+
+// It got pretty monotonous writing the same code over and over, and I
+// feared I would forget details. So I abstracted some desiderata into
+// macros. But I left the initialization code inline, because that's
+// where the errors for #54986 will be emitted.
+
+macro_rules! use_fully {
+    (struct $s:expr) => { {
+        borrow_field(& $s.x );
+        borrow_s(& $s );
+        move_s( $s );
+    } };
+
+    (tuple $t:expr) => { {
+        borrow_field(& $t.0 );
+        borrow_t(& $t );
+        move_t( $t );
+    } }
+}
+
+macro_rules! use_part {
+    (struct $s:expr) => { {
+        borrow_field(& $s.x );
+        match $s { S { ref x, y: _ } => { borrow_field(x); } }
+    } };
+
+    (tuple $t:expr) => { {
+        borrow_field(& $t.0 );
+        match $t { (ref x, _) => { borrow_field(x); } }
+    } }
+}
+
+fn test_0000_local_fully_init_and_use_struct() {
+    let s: S<B>;
+    s.x = 10; s.y = Box::new(20);
+    //~^ ERROR assign to part of possibly uninitialized variable: `s` [E0381]
+    use_fully!(struct s);
+}
+
+fn test_0001_local_fully_init_and_use_tuple() {
+    let t: T;
+    t.0 = 10; t.1 = Box::new(20);
+    //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381]
+    use_fully!(tuple t);
+}
+
+fn test_0010_local_fully_reinit_and_use_struct() {
+    let mut s: S<B> = S::new(); drop(s);
+    s.x = 10; s.y = Box::new(20);
+    //~^ ERROR assign to part of moved value: `s` [E0382]
+    use_fully!(struct s);
+}
+
+fn test_0011_local_fully_reinit_and_use_tuple() {
+    let mut t: T = (0, Box::new(0)); drop(t);
+    t.0 = 10; t.1 = Box::new(20);
+    //~^ ERROR assign to part of moved value: `t` [E0382]
+    use_fully!(tuple t);
+}
+
+fn test_0100_local_partial_init_and_use_struct() {
+    let s: S<B>;
+    s.x = 10;
+    //~^ ERROR assign to part of possibly uninitialized variable: `s` [E0381]
+    use_part!(struct s);
+}
+
+fn test_0101_local_partial_init_and_use_tuple() {
+    let t: T;
+    t.0 = 10;
+    //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381]
+    use_part!(tuple t);
+}
+
+fn test_0110_local_partial_reinit_and_use_struct() {
+    let mut s: S<B> = S::new(); drop(s);
+    s.x = 10;
+    //~^ ERROR assign to part of moved value: `s` [E0382]
+    use_part!(struct s);
+}
+
+fn test_0111_local_partial_reinit_and_use_tuple() {
+    let mut t: T = (0, Box::new(0)); drop(t);
+    t.0 = 10;
+    //~^ ERROR assign to part of moved value: `t` [E0382]
+    use_part!(tuple t);
+}
+
+fn test_0200_local_void_init_and_use_struct() {
+    let s: S<Void>;
+    s.x = 10;
+    //~^ ERROR assign to part of possibly uninitialized variable: `s` [E0381]
+    use_part!(struct s);
+}
+
+fn test_0201_local_void_init_and_use_tuple() {
+    let t: Tvoid;
+    t.0 = 10;
+    //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381]
+    use_part!(tuple t);
+}
+
+// NOTE: uniform structure of tests here makes n21n (aka combining
+// Void with Reinit) an (even more) senseless case, as we cannot
+// safely create initial instance containing Void to move out of and
+// then reinitialize. While I was tempted to sidestep this via some
+// unsafe code (eek), lets just instead not encode such tests.
+
+// fn test_0210_local_void_reinit_and_use_struct() { unimplemented!() }
+// fn test_0211_local_void_reinit_and_use_tuple() { unimplemented!() }
+
+fn test_1000_field_fully_init_and_use_struct() {
+    let q: Q<S<B>>;
+    q.r.f.x = 10; q.r.f.y = Box::new(20);
+    //~^ ERROR assign to part of possibly uninitialized variable: `q` [E0381]
+    use_fully!(struct q.r.f);
+}
+
+fn test_1001_field_fully_init_and_use_tuple() {
+    let q: Q<T>;
+    q.r.f.0 = 10; q.r.f.1 = Box::new(20);
+    //~^ ERROR assign to part of possibly uninitialized variable: `q` [E0381]
+    use_fully!(tuple q.r.f);
+}
+
+fn test_1010_field_fully_reinit_and_use_struct() {
+    let mut q: Q<S<B>> = Q::new(S::new()); drop(q.r);
+    q.r.f.x = 10; q.r.f.y = Box::new(20);
+    //~^ ERROR assign to part of moved value: `q.r` [E0382]
+    use_fully!(struct q.r.f);
+}
+
+fn test_1011_field_fully_reinit_and_use_tuple() {
+    let mut q: Q<T> = Q::new((0, Box::new(0))); drop(q.r);
+    q.r.f.0 = 10; q.r.f.1 = Box::new(20);
+    //~^ ERROR assign to part of moved value: `q.r` [E0382]
+    use_fully!(tuple q.r.f);
+}
+
+fn test_1100_field_partial_init_and_use_struct() {
+    let q: Q<S<B>>;
+    q.r.f.x = 10;
+    //~^ ERROR assign to part of possibly uninitialized variable: `q` [E0381]
+    use_part!(struct q.r.f);
+}
+
+fn test_1101_field_partial_init_and_use_tuple() {
+    let q: Q<T>;
+    q.r.f.0 = 10;
+    //~^ ERROR assign to part of possibly uninitialized variable: `q` [E0381]
+    use_part!(tuple q.r.f);
+}
+
+fn test_1110_field_partial_reinit_and_use_struct() {
+    let mut q: Q<S<B>> = Q::new(S::new()); drop(q.r);
+    q.r.f.x = 10;
+    //~^ ERROR assign to part of moved value: `q.r` [E0382]
+    use_part!(struct q.r.f);
+}
+
+fn test_1111_field_partial_reinit_and_use_tuple() {
+    let mut q: Q<T> = Q::new((0, Box::new(0))); drop(q.r);
+    q.r.f.0 = 10;
+    //~^ ERROR assign to part of moved value: `q.r` [E0382]
+    use_part!(tuple q.r.f);
+}
+
+fn test_1200_field_void_init_and_use_struct() {
+    let mut q: Q<S<Void>>;
+    q.r.f.x = 10;
+    //~^ ERROR assign to part of possibly uninitialized variable: `q` [E0381]
+    use_part!(struct q.r.f);
+}
+
+fn test_1201_field_void_init_and_use_tuple() {
+    let mut q: Q<Tvoid>;
+    q.r.f.0 = 10;
+    //~^ ERROR assign to part of possibly uninitialized variable: `q` [E0381]
+    use_part!(tuple q.r.f);
+}
+
+// See NOTE abve.
+
+// fn test_1210_field_void_reinit_and_use_struct() { unimplemented!() }
+// fn test_1211_field_void_reinit_and_use_tuple() { unimplemented!() }
+
+// The below are some additional cases of interest that have been
+// transcribed from other bugs based on old erroneous codegen when we
+// encountered partial writes.
+
+fn issue_26996() {
+    let mut c = (1, "".to_owned());
+    match c {
+        c2 => {
+            c.0 = 2; //~ ERROR assign to part of moved value
+            assert_eq!(c2.0, 1);
+        }
+    }
+}
+
+fn issue_27021() {
+    let mut c = (1, (1, "".to_owned()));
+    match c {
+        c2 => {
+            (c.1).0 = 2; //~ ERROR assign to part of moved value
+            assert_eq!((c2.1).0, 1);
+        }
+    }
+
+    let mut c = (1, (1, (1, "".to_owned())));
+    match c.1 {
+        c2 => {
+            ((c.1).1).0 = 3; //~ ERROR assign to part of moved value
+            assert_eq!((c2.1).0, 1);
+        }
+    }
+}
+
+fn main() {
+    test_0000_local_fully_init_and_use_struct();
+    test_0001_local_fully_init_and_use_tuple();
+    test_0010_local_fully_reinit_and_use_struct();
+    test_0011_local_fully_reinit_and_use_tuple();
+    test_0100_local_partial_init_and_use_struct();
+    test_0101_local_partial_init_and_use_tuple();
+    test_0110_local_partial_reinit_and_use_struct();
+    test_0111_local_partial_reinit_and_use_tuple();
+    test_0200_local_void_init_and_use_struct();
+    test_0201_local_void_init_and_use_tuple();
+    // test_0210_local_void_reinit_and_use_struct();
+    // test_0211_local_void_reinit_and_use_tuple();
+    test_1000_field_fully_init_and_use_struct();
+    test_1001_field_fully_init_and_use_tuple();
+    test_1010_field_fully_reinit_and_use_struct();
+    test_1011_field_fully_reinit_and_use_tuple();
+    test_1100_field_partial_init_and_use_struct();
+    test_1101_field_partial_init_and_use_tuple();
+    test_1110_field_partial_reinit_and_use_struct();
+    test_1111_field_partial_reinit_and_use_tuple();
+    test_1200_field_void_init_and_use_struct();
+    test_1201_field_void_init_and_use_tuple();
+    // test_1210_field_void_reinit_and_use_struct();
+    // test_1211_field_void_reinit_and_use_tuple();
+
+    issue_26996();
+    issue_27021();
+}
diff --git a/src/test/ui/nll/issue-21232-partial-init-and-use.stderr b/src/test/ui/nll/issue-21232-partial-init-and-use.stderr
new file mode 100644
index 0000000..ab85caa
--- /dev/null
+++ b/src/test/ui/nll/issue-21232-partial-init-and-use.stderr
@@ -0,0 +1,188 @@
+error[E0381]: assign to part of possibly uninitialized variable: `s`
+  --> $DIR/issue-21232-partial-init-and-use.rs:99:5
+   |
+LL |     s.x = 10; s.y = Box::new(20);
+   |     ^^^^^^^^ use of possibly uninitialized `s`
+
+error[E0381]: assign to part of possibly uninitialized variable: `t`
+  --> $DIR/issue-21232-partial-init-and-use.rs:106:5
+   |
+LL |     t.0 = 10; t.1 = Box::new(20);
+   |     ^^^^^^^^ use of possibly uninitialized `t`
+
+error[E0382]: assign to part of moved value: `s`
+  --> $DIR/issue-21232-partial-init-and-use.rs:113:5
+   |
+LL |     let mut s: S<B> = S::new(); drop(s);
+   |         -----                        - value moved here
+   |         |
+   |         move occurs because `s` has type `S<std::boxed::Box<u32>>`, which does not implement the `Copy` trait
+LL |     s.x = 10; s.y = Box::new(20);
+   |     ^^^^^^^^ value partially assigned here after move
+
+error[E0382]: assign to part of moved value: `t`
+  --> $DIR/issue-21232-partial-init-and-use.rs:120:5
+   |
+LL |     let mut t: T = (0, Box::new(0)); drop(t);
+   |         -----                             - value moved here
+   |         |
+   |         move occurs because `t` has type `(u32, std::boxed::Box<u32>)`, which does not implement the `Copy` trait
+LL |     t.0 = 10; t.1 = Box::new(20);
+   |     ^^^^^^^^ value partially assigned here after move
+
+error[E0381]: assign to part of possibly uninitialized variable: `s`
+  --> $DIR/issue-21232-partial-init-and-use.rs:127:5
+   |
+LL |     s.x = 10;
+   |     ^^^^^^^^ use of possibly uninitialized `s`
+
+error[E0381]: assign to part of possibly uninitialized variable: `t`
+  --> $DIR/issue-21232-partial-init-and-use.rs:134:5
+   |
+LL |     t.0 = 10;
+   |     ^^^^^^^^ use of possibly uninitialized `t`
+
+error[E0382]: assign to part of moved value: `s`
+  --> $DIR/issue-21232-partial-init-and-use.rs:141:5
+   |
+LL |     let mut s: S<B> = S::new(); drop(s);
+   |         -----                        - value moved here
+   |         |
+   |         move occurs because `s` has type `S<std::boxed::Box<u32>>`, which does not implement the `Copy` trait
+LL |     s.x = 10;
+   |     ^^^^^^^^ value partially assigned here after move
+
+error[E0382]: assign to part of moved value: `t`
+  --> $DIR/issue-21232-partial-init-and-use.rs:148:5
+   |
+LL |     let mut t: T = (0, Box::new(0)); drop(t);
+   |         -----                             - value moved here
+   |         |
+   |         move occurs because `t` has type `(u32, std::boxed::Box<u32>)`, which does not implement the `Copy` trait
+LL |     t.0 = 10;
+   |     ^^^^^^^^ value partially assigned here after move
+
+error[E0381]: assign to part of possibly uninitialized variable: `s`
+  --> $DIR/issue-21232-partial-init-and-use.rs:155:5
+   |
+LL |     s.x = 10;
+   |     ^^^^^^^^ use of possibly uninitialized `s`
+
+error[E0381]: assign to part of possibly uninitialized variable: `t`
+  --> $DIR/issue-21232-partial-init-and-use.rs:162:5
+   |
+LL |     t.0 = 10;
+   |     ^^^^^^^^ use of possibly uninitialized `t`
+
+error[E0381]: assign to part of possibly uninitialized variable: `q`
+  --> $DIR/issue-21232-partial-init-and-use.rs:178:5
+   |
+LL |     q.r.f.x = 10; q.r.f.y = Box::new(20);
+   |     ^^^^^^^^^^^^ use of possibly uninitialized `q.r.f`
+
+error[E0381]: assign to part of possibly uninitialized variable: `q`
+  --> $DIR/issue-21232-partial-init-and-use.rs:185:5
+   |
+LL |     q.r.f.0 = 10; q.r.f.1 = Box::new(20);
+   |     ^^^^^^^^^^^^ use of possibly uninitialized `q.r.f`
+
+error[E0382]: assign to part of moved value: `q.r`
+  --> $DIR/issue-21232-partial-init-and-use.rs:192:5
+   |
+LL |     let mut q: Q<S<B>> = Q::new(S::new()); drop(q.r);
+   |                                                 --- value moved here
+LL |     q.r.f.x = 10; q.r.f.y = Box::new(20);
+   |     ^^^^^^^^^^^^ value partially assigned here after move
+   |
+   = note: move occurs because `q.r` has type `R<S<std::boxed::Box<u32>>>`, which does not implement the `Copy` trait
+
+error[E0382]: assign to part of moved value: `q.r`
+  --> $DIR/issue-21232-partial-init-and-use.rs:199:5
+   |
+LL |     let mut q: Q<T> = Q::new((0, Box::new(0))); drop(q.r);
+   |                                                      --- value moved here
+LL |     q.r.f.0 = 10; q.r.f.1 = Box::new(20);
+   |     ^^^^^^^^^^^^ value partially assigned here after move
+   |
+   = note: move occurs because `q.r` has type `R<(u32, std::boxed::Box<u32>)>`, which does not implement the `Copy` trait
+
+error[E0381]: assign to part of possibly uninitialized variable: `q`
+  --> $DIR/issue-21232-partial-init-and-use.rs:206:5
+   |
+LL |     q.r.f.x = 10;
+   |     ^^^^^^^^^^^^ use of possibly uninitialized `q.r.f`
+
+error[E0381]: assign to part of possibly uninitialized variable: `q`
+  --> $DIR/issue-21232-partial-init-and-use.rs:213:5
+   |
+LL |     q.r.f.0 = 10;
+   |     ^^^^^^^^^^^^ use of possibly uninitialized `q.r.f`
+
+error[E0382]: assign to part of moved value: `q.r`
+  --> $DIR/issue-21232-partial-init-and-use.rs:220:5
+   |
+LL |     let mut q: Q<S<B>> = Q::new(S::new()); drop(q.r);
+   |                                                 --- value moved here
+LL |     q.r.f.x = 10;
+   |     ^^^^^^^^^^^^ value partially assigned here after move
+   |
+   = note: move occurs because `q.r` has type `R<S<std::boxed::Box<u32>>>`, which does not implement the `Copy` trait
+
+error[E0382]: assign to part of moved value: `q.r`
+  --> $DIR/issue-21232-partial-init-and-use.rs:227:5
+   |
+LL |     let mut q: Q<T> = Q::new((0, Box::new(0))); drop(q.r);
+   |                                                      --- value moved here
+LL |     q.r.f.0 = 10;
+   |     ^^^^^^^^^^^^ value partially assigned here after move
+   |
+   = note: move occurs because `q.r` has type `R<(u32, std::boxed::Box<u32>)>`, which does not implement the `Copy` trait
+
+error[E0381]: assign to part of possibly uninitialized variable: `q`
+  --> $DIR/issue-21232-partial-init-and-use.rs:234:5
+   |
+LL |     q.r.f.x = 10;
+   |     ^^^^^^^^^^^^ use of possibly uninitialized `q.r.f`
+
+error[E0381]: assign to part of possibly uninitialized variable: `q`
+  --> $DIR/issue-21232-partial-init-and-use.rs:241:5
+   |
+LL |     q.r.f.0 = 10;
+   |     ^^^^^^^^^^^^ use of possibly uninitialized `q.r.f`
+
+error[E0382]: assign to part of moved value: `c`
+  --> $DIR/issue-21232-partial-init-and-use.rs:259:13
+   |
+LL |     let mut c = (1, "".to_owned());
+   |         ----- move occurs because `c` has type `(i32, std::string::String)`, which does not implement the `Copy` trait
+LL |     match c {
+LL |         c2 => {
+   |         -- value moved here
+LL |             c.0 = 2;
+   |             ^^^^^^^ value partially assigned here after move
+
+error[E0382]: assign to part of moved value: `c`
+  --> $DIR/issue-21232-partial-init-and-use.rs:269:13
+   |
+LL |     let mut c = (1, (1, "".to_owned()));
+   |         ----- move occurs because `c` has type `(i32, (i32, std::string::String))`, which does not implement the `Copy` trait
+LL |     match c {
+LL |         c2 => {
+   |         -- value moved here
+LL |             (c.1).0 = 2;
+   |             ^^^^^^^^^^^ value partially assigned here after move
+
+error[E0382]: assign to part of moved value: `c.1`
+  --> $DIR/issue-21232-partial-init-and-use.rs:277:13
+   |
+LL |         c2 => {
+   |         -- value moved here
+LL |             ((c.1).1).0 = 3;
+   |             ^^^^^^^^^^^^^^^ value partially assigned here after move
+   |
+   = note: move occurs because `c.1` has type `(i32, (i32, std::string::String))`, which does not implement the `Copy` trait
+
+error: aborting due to 23 previous errors
+
+Some errors occurred: E0381, E0382.
+For more information about an error, try `rustc --explain E0381`.
diff --git a/src/test/ui/nll/issue-22323-temp-destruction.rs b/src/test/ui/nll/issue-22323-temp-destruction.rs
new file mode 100644
index 0000000..2c547fb
--- /dev/null
+++ b/src/test/ui/nll/issue-22323-temp-destruction.rs
@@ -0,0 +1,32 @@
+// rust-lang/rust#22323: regression test demonstrating that NLL
+// precisely tracks temporary destruction order.
+
+// compile-pass
+
+#![feature(nll)]
+
+fn main() {
+    let _s = construct().borrow().consume_borrowed();
+}
+
+fn construct() -> Value { Value }
+
+pub struct Value;
+
+impl Value {
+    fn borrow<'a>(&'a self) -> Borrowed<'a> { unimplemented!() }
+}
+
+pub struct Borrowed<'a> {
+    _inner: Guard<'a, Value>,
+}
+
+impl<'a> Borrowed<'a> {
+    fn consume_borrowed(self) -> String { unimplemented!() }
+}
+
+pub struct Guard<'a, T: ?Sized + 'a> {
+    _lock: &'a T,
+}
+
+impl<'a, T: ?Sized> Drop for Guard<'a, T> { fn drop(&mut self) {} }
diff --git a/src/test/ui/nll/issue-27868.rs b/src/test/ui/nll/issue-27868.rs
new file mode 100644
index 0000000..b5cf20b
--- /dev/null
+++ b/src/test/ui/nll/issue-27868.rs
@@ -0,0 +1,30 @@
+// Regression test for issue #27868
+
+#![feature(nll)]
+
+use std::ops::AddAssign;
+
+struct MyVec<T>(Vec<T>);
+
+impl <T> Drop for MyVec<T> {
+    fn drop(&mut self) {
+        println!("Being dropped.");
+    }
+}
+
+impl<T> AddAssign<T> for MyVec<T> {
+    fn add_assign(&mut self, _elem: T) {
+        println!("In add_assign.");
+    }
+}
+
+fn main() {
+    let mut vec = MyVec(vec![0]);
+    let mut vecvec = vec![vec];
+
+    vecvec[0] += {
+        vecvec = vec![];
+        //~^ ERROR cannot assign to `vecvec` because it is borrowed [E0506]
+        0
+    };
+}
diff --git a/src/test/ui/nll/issue-27868.stderr b/src/test/ui/nll/issue-27868.stderr
new file mode 100644
index 0000000..c83cb0b
--- /dev/null
+++ b/src/test/ui/nll/issue-27868.stderr
@@ -0,0 +1,18 @@
+error[E0506]: cannot assign to `vecvec` because it is borrowed
+  --> $DIR/issue-27868.rs:26:9
+   |
+LL |       vecvec[0] += {
+   |       ------
+   |       |
+   |  _____borrow of `vecvec` occurs here
+   | |
+LL | |         vecvec = vec![];
+   | |         ^^^^^^ assignment to borrowed `vecvec` occurs here
+LL | |
+LL | |         0
+LL | |     };
+   | |_____- borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/nll/issue-30104.rs b/src/test/ui/nll/issue-30104.rs
new file mode 100644
index 0000000..88e49bf
--- /dev/null
+++ b/src/test/ui/nll/issue-30104.rs
@@ -0,0 +1,42 @@
+// Regression test for #30104
+
+// compile-pass
+
+#![feature(nll)]
+
+use std::ops::{Deref, DerefMut};
+
+fn box_two_field(v: &mut Box<(i32, i32)>) {
+    let _a = &mut v.0;
+    let _b = &mut v.1;
+}
+
+fn box_destructure(v: &mut Box<(i32, i32)>) {
+    let (ref mut _head, ref mut _tail) = **v;
+}
+
+struct Wrap<T>(T);
+
+impl<T> Deref for Wrap<T> {
+    type Target = T;
+    fn deref(&self) -> &T {
+        &self.0
+    }
+}
+
+impl<T> DerefMut for Wrap<T> {
+    fn deref_mut(&mut self) -> &mut T {
+        &mut self.0
+    }
+}
+
+fn smart_two_field(v: &mut Wrap<(i32, i32)>) {
+    let _a = &mut v.0;
+    let _b = &mut v.1;
+}
+
+fn smart_destructure(v: &mut Wrap<(i32, i32)>) {
+    let (ref mut _head, ref mut _tail) = **v;
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/issue-31567.rs b/src/test/ui/nll/issue-31567.rs
new file mode 100644
index 0000000..c57a07a
--- /dev/null
+++ b/src/test/ui/nll/issue-31567.rs
@@ -0,0 +1,27 @@
+// Regression test for #31567: cached results of projections were
+// causing region relations not to be enforced at all the places where
+// they have to be enforced.
+
+#![feature(nll)]
+
+struct VecWrapper<'a>(&'a mut S);
+
+struct S(Box<u32>);
+
+fn get_dangling<'a>(v: VecWrapper<'a>) -> &'a u32 {
+    let s_inner: &'a S = &*v.0; //~ ERROR borrow may still be in use when destructor runs [E0713]
+    &s_inner.0
+}
+
+impl<'a> Drop for VecWrapper<'a> {
+    fn drop(&mut self) {
+        *self.0 = S(Box::new(0));
+    }
+}
+
+fn main() {
+    let mut s = S(Box::new(11));
+    let vw = VecWrapper(&mut s);
+    let dangling = get_dangling(vw);
+    println!("{}", dangling);
+}
diff --git a/src/test/ui/nll/issue-31567.stderr b/src/test/ui/nll/issue-31567.stderr
new file mode 100644
index 0000000..d098ff8
--- /dev/null
+++ b/src/test/ui/nll/issue-31567.stderr
@@ -0,0 +1,16 @@
+error[E0713]: borrow may still be in use when destructor runs
+  --> $DIR/issue-31567.rs:12:26
+   |
+LL | fn get_dangling<'a>(v: VecWrapper<'a>) -> &'a u32 {
+   |                 -- lifetime `'a` defined here
+LL |     let s_inner: &'a S = &*v.0;
+   |                  -----   ^^^^^
+   |                  |
+   |                  type annotation requires that `*v.0` is borrowed for `'a`
+LL |     &s_inner.0
+LL | }
+   | - here, drop of `v` needs exclusive access to `*v.0`, because the type `VecWrapper<'_>` implements the `Drop` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0713`.
diff --git a/src/test/ui/nll/issue-32382-index-assoc-type-with-lifetime.rs b/src/test/ui/nll/issue-32382-index-assoc-type-with-lifetime.rs
new file mode 100644
index 0000000..a114d70
--- /dev/null
+++ b/src/test/ui/nll/issue-32382-index-assoc-type-with-lifetime.rs
@@ -0,0 +1,42 @@
+#![feature(nll)]
+// compile-pass
+
+// rust-lang/rust#32382: Borrow checker used to complain about
+// `foobar_3` in the `impl` below, presumably due to some interaction
+// between the use of a lifetime in the associated type and the use of
+// the overloaded operator[]. This regression test ensures that we do
+// not resume complaining about it in the future.
+
+
+use std::marker::PhantomData;
+use std::ops::Index;
+
+pub trait Context: Clone {
+    type Container: ?Sized;
+    fn foobar_1( container: &Self::Container ) -> &str;
+    fn foobar_2( container: &Self::Container ) -> &str;
+    fn foobar_3( container: &Self::Container ) -> &str;
+}
+
+#[derive(Clone)]
+struct Foobar<'a> {
+    phantom: PhantomData<&'a ()>
+}
+
+impl<'a> Context for Foobar<'a> {
+    type Container = [&'a str];
+
+    fn foobar_1<'r>( container: &'r [&'a str] ) -> &'r str {
+        container[0]
+    }
+
+    fn foobar_2<'r>( container: &'r Self::Container ) -> &'r str {
+        container.index( 0 )
+    }
+
+    fn foobar_3<'r>( container: &'r Self::Container ) -> &'r str {
+        container[0]
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/issue-43058.rs b/src/test/ui/nll/issue-43058.rs
new file mode 100644
index 0000000..c5bae7a
--- /dev/null
+++ b/src/test/ui/nll/issue-43058.rs
@@ -0,0 +1,28 @@
+// compile-pass
+
+#![feature(nll)]
+
+use std::borrow::Cow;
+
+#[derive(Clone, Debug)]
+struct S<'a> {
+    name: Cow<'a, str>
+}
+
+#[derive(Clone, Debug)]
+struct T<'a> {
+    s: Cow<'a, [S<'a>]>
+}
+
+fn main() {
+    let s1 = [S { name: Cow::Borrowed("Test1") }, S { name: Cow::Borrowed("Test2") }];
+    let b1 = T { s: Cow::Borrowed(&s1) };
+    let s2 = [S { name: Cow::Borrowed("Test3") }, S { name: Cow::Borrowed("Test4") }];
+    let b2 = T { s: Cow::Borrowed(&s2) };
+
+    let mut v = Vec::new();
+    v.push(b1);
+    v.push(b2);
+
+    println!("{:?}", v);
+}
diff --git a/src/test/ui/nll/issue-46589.rs b/src/test/ui/nll/issue-46589.rs
new file mode 100644
index 0000000..690f6f2
--- /dev/null
+++ b/src/test/ui/nll/issue-46589.rs
@@ -0,0 +1,27 @@
+#![feature(nll)]
+
+struct Foo;
+
+impl Foo {
+    fn get_self(&mut self) -> Option<&mut Self> {
+        Some(self)
+    }
+
+    fn new_self(&mut self) -> &mut Self {
+        self
+    }
+
+    fn trigger_bug(&mut self) {
+        let other = &mut (&mut *self);
+
+        *other = match (*other).get_self() {
+            Some(s) => s,
+            None => (*other).new_self()
+            //~^ ERROR cannot borrow `**other` as mutable more than once at a time [E0499]
+        };
+
+        let c = other;
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/issue-46589.stderr b/src/test/ui/nll/issue-46589.stderr
new file mode 100644
index 0000000..7b02b90
--- /dev/null
+++ b/src/test/ui/nll/issue-46589.stderr
@@ -0,0 +1,15 @@
+error[E0499]: cannot borrow `**other` as mutable more than once at a time
+  --> $DIR/issue-46589.rs:19:21
+   |
+LL |         *other = match (*other).get_self() {
+   |                        -------- first mutable borrow occurs here
+LL |             Some(s) => s,
+LL |             None => (*other).new_self()
+   |                     ^^^^^^^^
+   |                     |
+   |                     second mutable borrow occurs here
+   |                     first borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/nll/issue-47022.rs b/src/test/ui/nll/issue-47022.rs
new file mode 100644
index 0000000..c0f8efa
--- /dev/null
+++ b/src/test/ui/nll/issue-47022.rs
@@ -0,0 +1,37 @@
+// compile-pass
+
+#![allow(warnings)]
+#![feature(nll)]
+
+struct LoadedObject {
+    bodies: Vec<Body>,
+    color: Color,
+}
+
+struct Body;
+
+#[derive(Clone)]
+struct Color;
+
+struct Graphic {
+    color: Color,
+}
+
+fn convert(objects: Vec<LoadedObject>) -> (Vec<Body>, Vec<Graphic>) {
+    objects
+        .into_iter()
+        .flat_map(|LoadedObject { bodies, color, .. }| {
+            bodies.into_iter().map(move |body| {
+                (
+                    body,
+                    Graphic {
+                        color: color.clone(),
+                    },
+                )
+            })
+        })
+        .unzip()
+}
+
+fn main() {}
+
diff --git a/src/test/ui/nll/issue-47388.rs b/src/test/ui/nll/issue-47388.rs
new file mode 100644
index 0000000..df47baa
--- /dev/null
+++ b/src/test/ui/nll/issue-47388.rs
@@ -0,0 +1,11 @@
+#![feature(nll)]
+struct FancyNum {
+    num: u8,
+}
+
+fn main() {
+    let mut fancy = FancyNum{ num: 5 };
+    let fancy_ref = &(&mut fancy);
+    fancy_ref.num = 6; //~ ERROR E0594
+    println!("{}", fancy_ref.num);
+}
diff --git a/src/test/ui/nll/issue-47388.stderr b/src/test/ui/nll/issue-47388.stderr
new file mode 100644
index 0000000..91f758a
--- /dev/null
+++ b/src/test/ui/nll/issue-47388.stderr
@@ -0,0 +1,11 @@
+error[E0594]: cannot assign to `fancy_ref.num` which is behind a `&` reference
+  --> $DIR/issue-47388.rs:9:5
+   |
+LL |     let fancy_ref = &(&mut fancy);
+   |                     ------------- help: consider changing this to be a mutable reference: `&mut (&mut fancy)`
+LL |     fancy_ref.num = 6;
+   |     ^^^^^^^^^^^^^^^^^ `fancy_ref` is a `&` reference, so the data it refers to cannot be written
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/nll/issue-47470.rs b/src/test/ui/nll/issue-47470.rs
new file mode 100644
index 0000000..67150b4
--- /dev/null
+++ b/src/test/ui/nll/issue-47470.rs
@@ -0,0 +1,24 @@
+// Regression test for #47470: cached results of projections were
+// causing region relations not to be enforced at all the places where
+// they have to be enforced.
+
+#![feature(nll)]
+
+struct Foo<'a>(&'a ());
+trait Bar {
+    type Assoc;
+    fn get(self) -> Self::Assoc;
+}
+
+impl<'a> Bar for Foo<'a> {
+    type Assoc = &'a u32;
+    fn get(self) -> Self::Assoc {
+        let local = 42;
+        &local //~ ERROR cannot return reference to local variable `local`
+    }
+}
+
+fn main() {
+    let f = Foo(&()).get();
+    println!("{}", f);
+}
diff --git a/src/test/ui/nll/issue-47470.stderr b/src/test/ui/nll/issue-47470.stderr
new file mode 100644
index 0000000..d23cee3
--- /dev/null
+++ b/src/test/ui/nll/issue-47470.stderr
@@ -0,0 +1,9 @@
+error[E0515]: cannot return reference to local variable `local`
+  --> $DIR/issue-47470.rs:17:9
+   |
+LL |         &local
+   |         ^^^^^^ returns a reference to data owned by the current function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/src/test/ui/nll/issue-48070.rs b/src/test/ui/nll/issue-48070.rs
new file mode 100644
index 0000000..c69bd3d
--- /dev/null
+++ b/src/test/ui/nll/issue-48070.rs
@@ -0,0 +1,25 @@
+// run-pass
+// revisions: lxl nll
+
+#![cfg_attr(nll, feature(nll))]
+
+struct Foo {
+    x: u32
+}
+
+impl Foo {
+    fn twiddle(&mut self) -> &mut Self { self }
+    fn twaddle(&mut self) -> &mut Self { self }
+    fn emit(&mut self) {
+        self.x += 1;
+    }
+}
+
+fn main() {
+    let mut foo = Foo { x: 0 };
+    match 22 {
+        22 => &mut foo,
+        44 => foo.twiddle(),
+        _ => foo.twaddle(),
+    }.emit();
+}
diff --git a/src/test/ui/nll/issue-48238.rs b/src/test/ui/nll/issue-48238.rs
new file mode 100644
index 0000000..2e64ea7
--- /dev/null
+++ b/src/test/ui/nll/issue-48238.rs
@@ -0,0 +1,12 @@
+// Regression test for issue #48238
+
+#![feature(nll)]
+
+fn use_val<'a>(val: &'a u8) -> &'a u8 {
+    val
+}
+
+fn main() {
+    let orig: u8 = 5;
+    move || use_val(&orig); //~ ERROR
+}
diff --git a/src/test/ui/nll/issue-48238.stderr b/src/test/ui/nll/issue-48238.stderr
new file mode 100644
index 0000000..05a90ee
--- /dev/null
+++ b/src/test/ui/nll/issue-48238.stderr
@@ -0,0 +1,13 @@
+error: lifetime may not live long enough
+  --> $DIR/issue-48238.rs:11:13
+   |
+LL |     move || use_val(&orig);
+   |     ------- ^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'2`
+   |     |     |
+   |     |     return type of closure is &'2 u8
+   |     lifetime `'1` represents this closure's body
+   |
+   = note: closure implements `Fn`, so references to captured variables can't escape the closure
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/issue-48697.rs b/src/test/ui/nll/issue-48697.rs
new file mode 100644
index 0000000..ececd6f
--- /dev/null
+++ b/src/test/ui/nll/issue-48697.rs
@@ -0,0 +1,12 @@
+// Regression test for #48697
+
+#![feature(nll)]
+
+fn foo(x: &i32) -> &i32 {
+    let z = 4;
+    let f = &|y| y;
+    let k = f(&z);
+    f(x) //~ cannot return value referencing local variable
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/issue-48697.stderr b/src/test/ui/nll/issue-48697.stderr
new file mode 100644
index 0000000..73832fd
--- /dev/null
+++ b/src/test/ui/nll/issue-48697.stderr
@@ -0,0 +1,11 @@
+error[E0515]: cannot return value referencing local variable `z`
+  --> $DIR/issue-48697.rs:9:5
+   |
+LL |     let k = f(&z);
+   |               -- `z` is borrowed here
+LL |     f(x)
+   |     ^^^^ returns a value referencing data owned by the current function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/src/test/ui/nll/issue-50716-1.rs b/src/test/ui/nll/issue-50716-1.rs
new file mode 100644
index 0000000..db7e6b3
--- /dev/null
+++ b/src/test/ui/nll/issue-50716-1.rs
@@ -0,0 +1,14 @@
+//
+// An additional regression test for the issue #50716 “NLL ignores lifetimes
+// bounds derived from `Sized` requirements” that checks that the fixed compiler
+// accepts this code fragment with both AST and MIR borrow checkers.
+//
+// revisions: ast mir
+//
+// compile-pass
+
+#![cfg_attr(mir, feature(nll))]
+
+struct Qey<Q: ?Sized>(Q);
+
+fn main() {}
diff --git a/src/test/ui/nll/issue-50716.rs b/src/test/ui/nll/issue-50716.rs
new file mode 100644
index 0000000..ce4bee3
--- /dev/null
+++ b/src/test/ui/nll/issue-50716.rs
@@ -0,0 +1,19 @@
+//
+// Regression test for the issue #50716: NLL ignores lifetimes bounds
+// derived from `Sized` requirements
+
+#![feature(nll)]
+
+trait A {
+    type X: ?Sized;
+}
+
+fn foo<'a, T: 'static>(s: Box<<&'a T as A>::X>)
+where
+    for<'b> &'b T: A,
+    <&'static T as A>::X: Sized
+{
+    let _x = *s; //~ ERROR
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/issue-50716.stderr b/src/test/ui/nll/issue-50716.stderr
new file mode 100644
index 0000000..7e5ffb5
--- /dev/null
+++ b/src/test/ui/nll/issue-50716.stderr
@@ -0,0 +1,11 @@
+error: lifetime may not live long enough
+  --> $DIR/issue-50716.rs:16:14
+   |
+LL | fn foo<'a, T: 'static>(s: Box<<&'a T as A>::X>)
+   |        -- lifetime `'a` defined here
+...
+LL |     let _x = *s;
+   |              ^^ proving this value is `Sized` requires that `'a` must outlive `'static`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/issue-51191.rs b/src/test/ui/nll/issue-51191.rs
new file mode 100644
index 0000000..6704b64
--- /dev/null
+++ b/src/test/ui/nll/issue-51191.rs
@@ -0,0 +1,33 @@
+#![feature(nll)]
+
+struct Struct;
+
+impl Struct {
+    fn bar(self: &mut Self) {
+        //~^ WARN function cannot return without recursing
+        (&mut self).bar();
+        //~^ ERROR cannot borrow `self` as mutable, as it is not declared as mutable [E0596]
+    }
+
+    fn imm(self) {
+        (&mut self).bar();
+        //~^ ERROR cannot borrow `self` as mutable, as it is not declared as mutable [E0596]
+    }
+
+    fn mtbl(mut self) {
+        (&mut self).bar();
+    }
+
+    fn immref(&self) {
+        (&mut self).bar();
+        //~^ ERROR cannot borrow `self` as mutable, as it is not declared as mutable [E0596]
+        //~^^ ERROR cannot borrow data in a `&` reference as mutable [E0596]
+    }
+
+    fn mtblref(&mut self) {
+        (&mut self).bar();
+        //~^ ERROR cannot borrow `self` as mutable, as it is not declared as mutable [E0596]
+    }
+}
+
+fn main () {}
diff --git a/src/test/ui/nll/issue-51191.stderr b/src/test/ui/nll/issue-51191.stderr
new file mode 100644
index 0000000..e80cd87
--- /dev/null
+++ b/src/test/ui/nll/issue-51191.stderr
@@ -0,0 +1,53 @@
+warning: function cannot return without recursing
+  --> $DIR/issue-51191.rs:6:5
+   |
+LL |     fn bar(self: &mut Self) {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
+LL |
+LL |         (&mut self).bar();
+   |         ----------------- recursive call site
+   |
+   = note: #[warn(unconditional_recursion)] on by default
+   = help: a `loop` may express intention better if this is on purpose
+
+error[E0596]: cannot borrow `self` as mutable, as it is not declared as mutable
+  --> $DIR/issue-51191.rs:8:9
+   |
+LL |         (&mut self).bar();
+   |         ^^^^^^^^^^^
+   |         |
+   |         cannot borrow as mutable
+   |         try removing `&mut` here
+
+error[E0596]: cannot borrow `self` as mutable, as it is not declared as mutable
+  --> $DIR/issue-51191.rs:13:9
+   |
+LL |     fn imm(self) {
+   |            ---- help: consider changing this to be mutable: `mut self`
+LL |         (&mut self).bar();
+   |         ^^^^^^^^^^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow `self` as mutable, as it is not declared as mutable
+  --> $DIR/issue-51191.rs:22:9
+   |
+LL |         (&mut self).bar();
+   |         ^^^^^^^^^^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/issue-51191.rs:22:9
+   |
+LL |         (&mut self).bar();
+   |         ^^^^^^^^^^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow `self` as mutable, as it is not declared as mutable
+  --> $DIR/issue-51191.rs:28:9
+   |
+LL |         (&mut self).bar();
+   |         ^^^^^^^^^^^
+   |         |
+   |         cannot borrow as mutable
+   |         try removing `&mut` here
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/nll/issue-51244.rs b/src/test/ui/nll/issue-51244.rs
new file mode 100644
index 0000000..aaf98dd
--- /dev/null
+++ b/src/test/ui/nll/issue-51244.rs
@@ -0,0 +1,7 @@
+#![feature(nll)]
+
+fn main() {
+    let ref my_ref @ _ = 0;
+    *my_ref = 0;
+    //~^ ERROR cannot assign to `*my_ref` which is behind a `&` reference [E0594]
+}
diff --git a/src/test/ui/nll/issue-51244.stderr b/src/test/ui/nll/issue-51244.stderr
new file mode 100644
index 0000000..69efb2c
--- /dev/null
+++ b/src/test/ui/nll/issue-51244.stderr
@@ -0,0 +1,11 @@
+error[E0594]: cannot assign to `*my_ref` which is behind a `&` reference
+  --> $DIR/issue-51244.rs:5:5
+   |
+LL |     let ref my_ref @ _ = 0;
+   |         -------------- help: consider changing this to be a mutable reference: `ref mut my_ref @ _`
+LL |     *my_ref = 0;
+   |     ^^^^^^^^^^^ `my_ref` is a `&` reference, so the data it refers to cannot be written
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/nll/issue-51268.rs b/src/test/ui/nll/issue-51268.rs
new file mode 100644
index 0000000..c14146a
--- /dev/null
+++ b/src/test/ui/nll/issue-51268.rs
@@ -0,0 +1,25 @@
+// ignore-tidy-linelength
+
+#![feature(nll)]
+
+struct Bar;
+
+impl Bar {
+    fn bar(&mut self, _: impl Fn()) {}
+}
+
+struct Foo {
+    thing: Bar,
+    number: usize,
+}
+
+impl Foo {
+    fn foo(&mut self) {
+        self.thing.bar(|| {
+        //~^ ERROR cannot borrow `self.thing` as mutable because it is also borrowed as immutable [E0502]
+            &self.number;
+        });
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/issue-51268.stderr b/src/test/ui/nll/issue-51268.stderr
new file mode 100644
index 0000000..0be1817
--- /dev/null
+++ b/src/test/ui/nll/issue-51268.stderr
@@ -0,0 +1,17 @@
+error[E0502]: cannot borrow `self.thing` as mutable because it is also borrowed as immutable
+  --> $DIR/issue-51268.rs:18:9
+   |
+LL |           self.thing.bar(|| {
+   |           ^          --- -- immutable borrow occurs here
+   |           |          |
+   |  _________|          immutable borrow later used by call
+   | |
+LL | |
+LL | |             &self.number;
+   | |              ---- first borrow occurs due to use of `self` in closure
+LL | |         });
+   | |__________^ mutable borrow occurs here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/nll/issue-51351.rs b/src/test/ui/nll/issue-51351.rs
new file mode 100644
index 0000000..939993f
--- /dev/null
+++ b/src/test/ui/nll/issue-51351.rs
@@ -0,0 +1,23 @@
+//
+// Regression test for #51351 and #52133: In the case of #51351,
+// late-bound regions (like 'a) that were unused within the arguments of
+// a function were overlooked and could case an ICE. In the case of #52133,
+// LBR defined on the creator function needed to be added to the free regions
+// of the closure, as they were not present in the closure's generic
+// declarations otherwise.
+//
+// compile-pass
+
+#![feature(nll)]
+
+fn creash<'a>() {
+    let x: &'a () = &();
+}
+
+fn produce<'a>() {
+   move || {
+        let x: &'a () = &();
+   };
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/issue-51512.rs b/src/test/ui/nll/issue-51512.rs
new file mode 100644
index 0000000..7e2e6e0
--- /dev/null
+++ b/src/test/ui/nll/issue-51512.rs
@@ -0,0 +1,9 @@
+#![allow(warnings)]
+#![feature(nll)]
+
+fn main() {
+    let range = 0..1;
+    let r = range;
+    let x = range.start;
+    //~^ ERROR use of moved value: `range` [E0382]
+}
diff --git a/src/test/ui/nll/issue-51512.stderr b/src/test/ui/nll/issue-51512.stderr
new file mode 100644
index 0000000..a84a236
--- /dev/null
+++ b/src/test/ui/nll/issue-51512.stderr
@@ -0,0 +1,13 @@
+error[E0382]: use of moved value: `range`
+  --> $DIR/issue-51512.rs:7:13
+   |
+LL |     let range = 0..1;
+   |         ----- move occurs because `range` has type `std::ops::Range<i32>`, which does not implement the `Copy` trait
+LL |     let r = range;
+   |             ----- value moved here
+LL |     let x = range.start;
+   |             ^^^^^^^^^^^ value used here after move
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/nll/issue-52059-report-when-borrow-and-drop-conflict.rs b/src/test/ui/nll/issue-52059-report-when-borrow-and-drop-conflict.rs
new file mode 100644
index 0000000..eaa809d
--- /dev/null
+++ b/src/test/ui/nll/issue-52059-report-when-borrow-and-drop-conflict.rs
@@ -0,0 +1,33 @@
+// rust-lang/rust#52059: Regardless of whether you are moving out of a
+// Drop type or just introducing an inadvertent alias via a borrow of
+// one of its fields, it is useful to be reminded of the significance
+// of the fact that the type implements Drop.
+
+#![feature(nll)]
+#![allow(dead_code)]
+
+pub struct S<'a> { url: &'a mut String }
+
+impl<'a> Drop for S<'a> { fn drop(&mut self) { } }
+
+fn finish_1(s: S) -> &mut String {
+    s.url
+}
+//~^^ ERROR borrow may still be in use when destructor runs
+
+fn finish_2(s: S) -> &mut String {
+    let p = &mut *s.url; p
+}
+//~^^ ERROR borrow may still be in use when destructor runs
+
+fn finish_3(s: S) -> &mut String {
+    let p: &mut _ = s.url; p
+}
+//~^^ ERROR borrow may still be in use when destructor runs
+
+fn finish_4(s: S) -> &mut String {
+    let p = s.url; p
+}
+//~^^ ERROR cannot move out of type `S<'_>`, which implements the `Drop` trait
+
+fn main() {}
diff --git a/src/test/ui/nll/issue-52059-report-when-borrow-and-drop-conflict.stderr b/src/test/ui/nll/issue-52059-report-when-borrow-and-drop-conflict.stderr
new file mode 100644
index 0000000..e2036ee
--- /dev/null
+++ b/src/test/ui/nll/issue-52059-report-when-borrow-and-drop-conflict.stderr
@@ -0,0 +1,43 @@
+error[E0713]: borrow may still be in use when destructor runs
+  --> $DIR/issue-52059-report-when-borrow-and-drop-conflict.rs:14:5
+   |
+LL | fn finish_1(s: S) -> &mut String {
+   |             - has type `S<'1>`
+LL |     s.url
+   |     ^^^^^ returning this value requires that `*s.url` is borrowed for `'1`
+LL | }
+   | - here, drop of `s` needs exclusive access to `*s.url`, because the type `S<'_>` implements the `Drop` trait
+
+error[E0713]: borrow may still be in use when destructor runs
+  --> $DIR/issue-52059-report-when-borrow-and-drop-conflict.rs:19:13
+   |
+LL | fn finish_2(s: S) -> &mut String {
+   |             - has type `S<'1>`
+LL |     let p = &mut *s.url; p
+   |             ^^^^^^^^^^^  - returning this value requires that `*s.url` is borrowed for `'1`
+LL | }
+   | - here, drop of `s` needs exclusive access to `*s.url`, because the type `S<'_>` implements the `Drop` trait
+
+error[E0713]: borrow may still be in use when destructor runs
+  --> $DIR/issue-52059-report-when-borrow-and-drop-conflict.rs:24:21
+   |
+LL | fn finish_3(s: S) -> &mut String {
+   |             - has type `S<'1>`
+LL |     let p: &mut _ = s.url; p
+   |                     ^^^^^  - returning this value requires that `*s.url` is borrowed for `'1`
+LL | }
+   | - here, drop of `s` needs exclusive access to `*s.url`, because the type `S<'_>` implements the `Drop` trait
+
+error[E0509]: cannot move out of type `S<'_>`, which implements the `Drop` trait
+  --> $DIR/issue-52059-report-when-borrow-and-drop-conflict.rs:29:13
+   |
+LL |     let p = s.url; p
+   |             ^^^^^
+   |             |
+   |             cannot move out of here
+   |             help: consider borrowing here: `&s.url`
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0509, E0713.
+For more information about an error, try `rustc --explain E0509`.
diff --git a/src/test/ui/nll/issue-52078.rs b/src/test/ui/nll/issue-52078.rs
new file mode 100644
index 0000000..ebe442a
--- /dev/null
+++ b/src/test/ui/nll/issue-52078.rs
@@ -0,0 +1,27 @@
+#![feature(nll)]
+#![allow(unused_variables)]
+
+// Regression test for #52078: we were failing to infer a relationship
+// between `'a` and `'b` below due to inference variables introduced
+// during the normalization process.
+//
+// compile-pass
+
+struct Drain<'a, T: 'a> {
+    _marker: ::std::marker::PhantomData<&'a T>,
+}
+
+trait Join {
+    type Value;
+    fn get(value: &mut Self::Value);
+}
+
+impl<'a, T> Join for Drain<'a, T> {
+    type Value = &'a mut Option<T>;
+
+    fn get<'b>(value: &'b mut Self::Value) {
+    }
+}
+
+fn main() {
+}
diff --git a/src/test/ui/nll/issue-52086.rs b/src/test/ui/nll/issue-52086.rs
new file mode 100644
index 0000000..7876528
--- /dev/null
+++ b/src/test/ui/nll/issue-52086.rs
@@ -0,0 +1,16 @@
+#![feature(nll)]
+
+use std::rc::Rc;
+use std::sync::Arc;
+
+struct Bar { field: Vec<i32> }
+
+fn main() {
+    let x = Rc::new(Bar { field: vec![] });
+    drop(x.field);
+//~^ ERROR cannot move out of an `Rc`
+
+    let y = Arc::new(Bar { field: vec![] });
+    drop(y.field);
+//~^ ERROR cannot move out of an `Arc`
+}
diff --git a/src/test/ui/nll/issue-52086.stderr b/src/test/ui/nll/issue-52086.stderr
new file mode 100644
index 0000000..ed4171f
--- /dev/null
+++ b/src/test/ui/nll/issue-52086.stderr
@@ -0,0 +1,15 @@
+error[E0507]: cannot move out of an `Rc`
+  --> $DIR/issue-52086.rs:10:10
+   |
+LL |     drop(x.field);
+   |          ^^^^^^^ cannot move out of an `Rc`
+
+error[E0507]: cannot move out of an `Arc`
+  --> $DIR/issue-52086.rs:14:10
+   |
+LL |     drop(y.field);
+   |          ^^^^^^^ cannot move out of an `Arc`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/nll/issue-52113.rs b/src/test/ui/nll/issue-52113.rs
new file mode 100644
index 0000000..795f4f4
--- /dev/null
+++ b/src/test/ui/nll/issue-52113.rs
@@ -0,0 +1,40 @@
+//
+
+#![allow(warnings)]
+#![feature(nll)]
+
+trait Bazinga {}
+impl<F> Bazinga for F {}
+
+fn produce1<'a>(data: &'a u32) -> impl Bazinga + 'a {
+    let x = move || {
+        let _data: &'a u32 = data;
+    };
+    x
+}
+
+fn produce2<'a>(data: &'a mut Vec<&'a u32>, value: &'a u32) -> impl Bazinga + 'a {
+    let x = move || {
+        let value: &'a u32 = value;
+        data.push(value);
+    };
+    x
+}
+
+fn produce3<'a, 'b: 'a>(data: &'a mut Vec<&'a u32>, value: &'b u32) -> impl Bazinga + 'a {
+    let x = move || {
+        let value: &'a u32 = value;
+        data.push(value);
+    };
+    x
+}
+
+fn produce_err<'a, 'b: 'a>(data: &'b mut Vec<&'b u32>, value: &'a u32) -> impl Bazinga + 'b {
+    let x = move || {
+        let value: &'a u32 = value;
+        data.push(value);
+    };
+    x //~ ERROR lifetime may not live long enough
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/issue-52113.stderr b/src/test/ui/nll/issue-52113.stderr
new file mode 100644
index 0000000..8638fe2
--- /dev/null
+++ b/src/test/ui/nll/issue-52113.stderr
@@ -0,0 +1,13 @@
+error: lifetime may not live long enough
+  --> $DIR/issue-52113.rs:37:5
+   |
+LL | fn produce_err<'a, 'b: 'a>(data: &'b mut Vec<&'b u32>, value: &'a u32) -> impl Bazinga + 'b {
+   |                --  -- lifetime `'b` defined here
+   |                |
+   |                lifetime `'a` defined here
+...
+LL |     x
+   |     ^ returning this value requires that `'a` must outlive `'b`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/issue-52534-1.rs b/src/test/ui/nll/issue-52534-1.rs
new file mode 100644
index 0000000..7ab3593
--- /dev/null
+++ b/src/test/ui/nll/issue-52534-1.rs
@@ -0,0 +1,51 @@
+#![feature(nll)]
+#![allow(warnings)]
+
+struct Test;
+
+impl Test {
+    fn bar(&self, x: &u32) -> &u32 {
+        let x = 22;
+        &x
+//~^ ERROR cannot return reference to local variable
+    }
+}
+
+fn foo(x: &u32) -> &u32 {
+    let x = 22;
+    &x
+//~^ ERROR cannot return reference to local variable
+}
+
+fn baz(x: &u32) -> &&u32 {
+    let x = 22;
+    &&x
+//~^ ERROR cannot return value referencing local variable
+//~| ERROR cannot return reference to temporary value
+}
+
+fn foobazbar<'a>(x: u32, y: &'a u32) -> &'a u32 {
+    let x = 22;
+    &x
+//~^ ERROR cannot return reference to local variable
+}
+
+fn foobar<'a>(x: &'a u32) -> &'a u32 {
+    let x = 22;
+    &x
+//~^ ERROR cannot return reference to local variable
+}
+
+fn foobaz<'a, 'b>(x: &'a u32, y: &'b u32) -> &'a u32 {
+    let x = 22;
+    &x
+//~^ ERROR cannot return reference to local variable
+}
+
+fn foobarbaz<'a, 'b>(x: &'a u32, y: &'b u32, z: &'a u32) -> &'a u32 {
+    let x = 22;
+    &x
+//~^ ERROR cannot return reference to local variable
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/issue-52534-1.stderr b/src/test/ui/nll/issue-52534-1.stderr
new file mode 100644
index 0000000..7d82f5e
--- /dev/null
+++ b/src/test/ui/nll/issue-52534-1.stderr
@@ -0,0 +1,57 @@
+error[E0515]: cannot return reference to local variable `x`
+  --> $DIR/issue-52534-1.rs:9:9
+   |
+LL |         &x
+   |         ^^ returns a reference to data owned by the current function
+
+error[E0515]: cannot return reference to local variable `x`
+  --> $DIR/issue-52534-1.rs:16:5
+   |
+LL |     &x
+   |     ^^ returns a reference to data owned by the current function
+
+error[E0515]: cannot return value referencing local variable `x`
+  --> $DIR/issue-52534-1.rs:22:5
+   |
+LL |     &&x
+   |     ^--
+   |     ||
+   |     |`x` is borrowed here
+   |     returns a value referencing data owned by the current function
+
+error[E0515]: cannot return reference to temporary value
+  --> $DIR/issue-52534-1.rs:22:5
+   |
+LL |     &&x
+   |     ^--
+   |     ||
+   |     |temporary value created here
+   |     returns a reference to data owned by the current function
+
+error[E0515]: cannot return reference to local variable `x`
+  --> $DIR/issue-52534-1.rs:29:5
+   |
+LL |     &x
+   |     ^^ returns a reference to data owned by the current function
+
+error[E0515]: cannot return reference to local variable `x`
+  --> $DIR/issue-52534-1.rs:35:5
+   |
+LL |     &x
+   |     ^^ returns a reference to data owned by the current function
+
+error[E0515]: cannot return reference to local variable `x`
+  --> $DIR/issue-52534-1.rs:41:5
+   |
+LL |     &x
+   |     ^^ returns a reference to data owned by the current function
+
+error[E0515]: cannot return reference to local variable `x`
+  --> $DIR/issue-52534-1.rs:47:5
+   |
+LL |     &x
+   |     ^^ returns a reference to data owned by the current function
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/src/test/ui/nll/issue-52534-2.rs b/src/test/ui/nll/issue-52534-2.rs
new file mode 100644
index 0000000..6e84869
--- /dev/null
+++ b/src/test/ui/nll/issue-52534-2.rs
@@ -0,0 +1,17 @@
+#![feature(nll)]
+#![allow(warnings)]
+
+fn foo(x: &u32) -> &u32 {
+    let y;
+
+    {
+        let x = 32;
+        y = &x
+//~^ ERROR does not live long enough
+    }
+
+    println!("{}", y);
+    x
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/issue-52534-2.stderr b/src/test/ui/nll/issue-52534-2.stderr
new file mode 100644
index 0000000..f98deae
--- /dev/null
+++ b/src/test/ui/nll/issue-52534-2.stderr
@@ -0,0 +1,15 @@
+error[E0597]: `x` does not live long enough
+  --> $DIR/issue-52534-2.rs:9:9
+   |
+LL |         y = &x
+   |         ^^^^^^ borrowed value does not live long enough
+LL |
+LL |     }
+   |     - `x` dropped here while still borrowed
+LL | 
+LL |     println!("{}", y);
+   |                    - borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/issue-52534.rs b/src/test/ui/nll/issue-52534.rs
new file mode 100644
index 0000000..1394560
--- /dev/null
+++ b/src/test/ui/nll/issue-52534.rs
@@ -0,0 +1,22 @@
+#![feature(nll)]
+#![allow(warnings)]
+
+fn foo(_: impl FnOnce(&u32) -> &u32) {
+}
+
+fn baz(_: impl FnOnce(&u32, u32) -> &u32) {
+}
+
+fn bar() {
+    let x = 22;
+    foo(|a| &x)
+//~^ ERROR does not live long enough
+}
+
+fn foobar() {
+    let y = 22;
+    baz(|first, second| &y)
+//~^ ERROR does not live long enough
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/issue-52534.stderr b/src/test/ui/nll/issue-52534.stderr
new file mode 100644
index 0000000..9ac79ed
--- /dev/null
+++ b/src/test/ui/nll/issue-52534.stderr
@@ -0,0 +1,31 @@
+error[E0597]: `x` does not live long enough
+  --> $DIR/issue-52534.rs:12:14
+   |
+LL |     foo(|a| &x)
+   |          -   ^ `x` would have to be valid for `'0`...
+   |          |
+   |          has type `&'0 u32`
+LL |
+LL | }
+   | - ...but `x` will be dropped here, when the function `bar` returns
+   |
+   = note: functions cannot return a borrow to data owned within the function's scope, functions can only return borrows to data passed as arguments
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html#dangling-references>
+
+error[E0597]: `y` does not live long enough
+  --> $DIR/issue-52534.rs:18:26
+   |
+LL |     baz(|first, second| &y)
+   |          -----           ^ `y` would have to be valid for `'0`...
+   |          |
+   |          has type `&'0 u32`
+LL |
+LL | }
+   | - ...but `y` will be dropped here, when the function `foobar` returns
+   |
+   = note: functions cannot return a borrow to data owned within the function's scope, functions can only return borrows to data passed as arguments
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html#dangling-references>
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/issue-52663-span-decl-captured-variable.rs b/src/test/ui/nll/issue-52663-span-decl-captured-variable.rs
new file mode 100644
index 0000000..3e57d26
--- /dev/null
+++ b/src/test/ui/nll/issue-52663-span-decl-captured-variable.rs
@@ -0,0 +1,13 @@
+#![feature(nll)]
+
+fn expect_fn<F>(f: F) where F : Fn() {
+    f();
+}
+
+fn main() {
+   {
+       let x = (vec![22], vec![44]);
+       expect_fn(|| drop(x.0));
+       //~^ ERROR cannot move out of captured variable in an `Fn` closure [E0507]
+   }
+}
diff --git a/src/test/ui/nll/issue-52663-span-decl-captured-variable.stderr b/src/test/ui/nll/issue-52663-span-decl-captured-variable.stderr
new file mode 100644
index 0000000..0162c6b
--- /dev/null
+++ b/src/test/ui/nll/issue-52663-span-decl-captured-variable.stderr
@@ -0,0 +1,11 @@
+error[E0507]: cannot move out of captured variable in an `Fn` closure
+  --> $DIR/issue-52663-span-decl-captured-variable.rs:10:26
+   |
+LL |        let x = (vec![22], vec![44]);
+   |            - captured outer variable
+LL |        expect_fn(|| drop(x.0));
+   |                          ^^^ cannot move out of captured variable in an `Fn` closure
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/nll/issue-52663-trait-object.rs b/src/test/ui/nll/issue-52663-trait-object.rs
new file mode 100644
index 0000000..121c3ef
--- /dev/null
+++ b/src/test/ui/nll/issue-52663-trait-object.rs
@@ -0,0 +1,17 @@
+#![feature(box_syntax)]
+#![feature(nll)]
+
+trait Foo { fn get(&self); }
+
+impl<A> Foo for A {
+    fn get(&self) { }
+}
+
+fn main() {
+    let _ = {
+        let tmp0 = 3;
+        let tmp1 = &tmp0;
+        box tmp1 as Box<Foo + '_>
+    };
+    //~^^^ ERROR `tmp0` does not live long enough
+}
diff --git a/src/test/ui/nll/issue-52663-trait-object.stderr b/src/test/ui/nll/issue-52663-trait-object.stderr
new file mode 100644
index 0000000..b9437d8
--- /dev/null
+++ b/src/test/ui/nll/issue-52663-trait-object.stderr
@@ -0,0 +1,13 @@
+error[E0597]: `tmp0` does not live long enough
+  --> $DIR/issue-52663-trait-object.rs:13:20
+   |
+LL |         let tmp1 = &tmp0;
+   |                    ^^^^^ borrowed value does not live long enough
+LL |         box tmp1 as Box<Foo + '_>
+   |         ------------------------- borrow later captured here by trait object
+LL |     };
+   |     - `tmp0` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/issue-52669.rs b/src/test/ui/nll/issue-52669.rs
new file mode 100644
index 0000000..6027e98
--- /dev/null
+++ b/src/test/ui/nll/issue-52669.rs
@@ -0,0 +1,19 @@
+#![feature(nll)]
+
+struct A {
+    b: B,
+}
+
+#[derive(Clone)]
+struct B;
+
+fn foo(_: A) {}
+
+fn bar(mut a: A) -> B {
+    a.b = B;
+    foo(a);
+    a.b.clone()
+//~^ ERROR borrow of moved value
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/issue-52669.stderr b/src/test/ui/nll/issue-52669.stderr
new file mode 100644
index 0000000..f51768c
--- /dev/null
+++ b/src/test/ui/nll/issue-52669.stderr
@@ -0,0 +1,14 @@
+error[E0382]: borrow of moved value: `a.b`
+  --> $DIR/issue-52669.rs:15:5
+   |
+LL | fn bar(mut a: A) -> B {
+   |        ----- move occurs because `a` has type `A`, which does not implement the `Copy` trait
+LL |     a.b = B;
+LL |     foo(a);
+   |         - value moved here
+LL |     a.b.clone()
+   |     ^^^ value borrowed here after move
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/nll/issue-52742.rs b/src/test/ui/nll/issue-52742.rs
new file mode 100644
index 0000000..150e67f
--- /dev/null
+++ b/src/test/ui/nll/issue-52742.rs
@@ -0,0 +1,20 @@
+#![feature(nll)]
+#![feature(in_band_lifetimes)]
+
+struct Foo<'a, 'b> {
+    x: &'a u32,
+    y: &'b u32,
+}
+
+struct Bar<'b> {
+    z: &'b u32,
+}
+
+impl Foo<'_, '_> {
+    fn take_bar(&mut self, b: Bar<'_>) {
+        self.y = b.z
+        //~^ ERROR lifetime may not live long enough
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/issue-52742.stderr b/src/test/ui/nll/issue-52742.stderr
new file mode 100644
index 0000000..6b25296
--- /dev/null
+++ b/src/test/ui/nll/issue-52742.stderr
@@ -0,0 +1,12 @@
+error: lifetime may not live long enough
+  --> $DIR/issue-52742.rs:15:9
+   |
+LL |     fn take_bar(&mut self, b: Bar<'_>) {
+   |                 ---------         -- let's call this `'1`
+   |                 |
+   |                 has type `&mut Foo<'_, '2>`
+LL |         self.y = b.z
+   |         ^^^^^^^^^^^^ assignment requires that `'1` must outlive `'2`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/issue-53040.rs b/src/test/ui/nll/issue-53040.rs
new file mode 100644
index 0000000..8ce24c8
--- /dev/null
+++ b/src/test/ui/nll/issue-53040.rs
@@ -0,0 +1,7 @@
+#![feature(nll)]
+
+fn main() {
+    let mut v: Vec<()> = Vec::new();
+    || &mut v;
+//~^ ERROR captured variable cannot escape `FnMut` closure body
+}
diff --git a/src/test/ui/nll/issue-53040.stderr b/src/test/ui/nll/issue-53040.stderr
new file mode 100644
index 0000000..9e7e63a
--- /dev/null
+++ b/src/test/ui/nll/issue-53040.stderr
@@ -0,0 +1,13 @@
+error: captured variable cannot escape `FnMut` closure body
+  --> $DIR/issue-53040.rs:5:8
+   |
+LL |     || &mut v;
+   |      - ^^^^^^ returns a reference to a captured variable which escapes the closure body
+   |      |
+   |      inferred to be a `FnMut` closure
+   |
+   = note: `FnMut` closures only have access to their captured variables while they are executing...
+   = note: ...therefore, they cannot allow references to captured variables to escape
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/issue-53119.rs b/src/test/ui/nll/issue-53119.rs
new file mode 100644
index 0000000..97e05c8
--- /dev/null
+++ b/src/test/ui/nll/issue-53119.rs
@@ -0,0 +1,25 @@
+// compile-pass
+
+#![feature(nll)]
+
+use std::ops::Deref;
+
+pub struct TypeFieldIterator<'a, T: 'a> {
+    _t: &'a T,
+}
+
+pub struct Type<Id, T> {
+    _types: Vec<(Id, T)>,
+}
+
+impl<'a, Id: 'a, T> Iterator for TypeFieldIterator<'a, T>
+where T: Deref<Target = Type<Id, T>> {
+    type Item = &'a (Id, T);
+
+    fn next(&mut self) -> Option<&'a (Id, T)> {
+        || self.next();
+        None
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/issue-53570.rs b/src/test/ui/nll/issue-53570.rs
new file mode 100644
index 0000000..d0baffa
--- /dev/null
+++ b/src/test/ui/nll/issue-53570.rs
@@ -0,0 +1,36 @@
+// Regression test for #53570. Here, we need to propagate that `T: 'a`
+// but in some versions of NLL we were propagating a stronger
+// requirement that `T: 'static`. This arose because we actually had
+// to propagate both that `T: 'a` but also `T: 'b` where `'b` is the
+// higher-ranked lifetime that appears in the type of the closure
+// parameter `x` -- since `'b` cannot be expressed in the caller's
+// space, that got promoted th `'static`.
+//
+// compile-pass
+
+#![feature(nll)]
+#![feature(rustc_attrs)]
+#![allow(dead_code)]
+
+use std::cell::{RefCell, Ref};
+
+trait AnyVec<'a> {
+}
+
+trait GenericVec<T> {
+    fn unwrap<'a, 'b>(vec: &'b AnyVec<'a>) -> &'b [T] where T: 'a;
+}
+
+struct Scratchpad<'a> {
+    buffers: RefCell<Box<AnyVec<'a>>>,
+}
+
+impl<'a> Scratchpad<'a> {
+    fn get<T: GenericVec<T>>(&self) -> Ref<[T]>
+    where T: 'a
+    {
+        Ref::map(self.buffers.borrow(), |x| T::unwrap(x.as_ref()))
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/issue-53773.rs b/src/test/ui/nll/issue-53773.rs
new file mode 100644
index 0000000..62e1631
--- /dev/null
+++ b/src/test/ui/nll/issue-53773.rs
@@ -0,0 +1,49 @@
+#![feature(nll)]
+
+struct Archive;
+struct ArchiveIterator<'a> {
+    x: &'a Archive,
+}
+struct ArchiveChild<'a> {
+    x: &'a Archive,
+}
+
+struct A {
+    raw: &'static mut Archive,
+}
+struct Iter<'a> {
+    raw: &'a mut ArchiveIterator<'a>,
+}
+struct C<'a> {
+    raw: &'a mut ArchiveChild<'a>,
+}
+
+impl A {
+    pub fn iter(&self) -> Iter<'_> {
+        panic!()
+    }
+}
+impl Drop for A {
+    fn drop(&mut self) {}
+}
+impl<'a> Drop for C<'a> {
+    fn drop(&mut self) {}
+}
+
+impl<'a> Iterator for Iter<'a> {
+    type Item = C<'a>;
+    fn next(&mut self) -> Option<C<'a>> {
+        panic!()
+    }
+}
+
+fn error(archive: &A) {
+    let mut members: Vec<&mut ArchiveChild<'_>> = vec![];
+    for child in archive.iter() {
+        members.push(child.raw);
+        //~^ ERROR borrow may still be in use when destructor runs [E0713]
+    }
+    members.len();
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/issue-53773.stderr b/src/test/ui/nll/issue-53773.stderr
new file mode 100644
index 0000000..1933ef7
--- /dev/null
+++ b/src/test/ui/nll/issue-53773.stderr
@@ -0,0 +1,16 @@
+error[E0713]: borrow may still be in use when destructor runs
+  --> $DIR/issue-53773.rs:43:22
+   |
+LL |         members.push(child.raw);
+   |                      ^^^^^^^^^
+LL |
+LL |     }
+   |     - here, drop of `child` needs exclusive access to `*child.raw`, because the type `C<'_>` implements the `Drop` trait
+LL |     members.len();
+   |     ------- borrow later used here
+   |
+   = note: consider using a `let` binding to create a longer lived value
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0713`.
diff --git a/src/test/ui/nll/issue-53807.nll.stderr b/src/test/ui/nll/issue-53807.nll.stderr
new file mode 100644
index 0000000..2b15da3
--- /dev/null
+++ b/src/test/ui/nll/issue-53807.nll.stderr
@@ -0,0 +1,11 @@
+error[E0382]: use of moved value
+  --> $DIR/issue-53807.rs:4:21
+   |
+LL |         if let Some(thing) = maybe {
+   |                     ^^^^^ value moved here, in previous iteration of loop
+   |
+   = note: move occurs because value has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/nll/issue-53807.rs b/src/test/ui/nll/issue-53807.rs
new file mode 100644
index 0000000..f69d8c1
--- /dev/null
+++ b/src/test/ui/nll/issue-53807.rs
@@ -0,0 +1,9 @@
+pub fn main(){
+    let maybe = Some(vec![true, true]);
+    loop {
+        if let Some(thing) = maybe {
+//~^ ERROR use of partially moved value
+//~| ERROR use of moved value
+        }
+    }
+}
diff --git a/src/test/ui/nll/issue-53807.stderr b/src/test/ui/nll/issue-53807.stderr
new file mode 100644
index 0000000..fb67014
--- /dev/null
+++ b/src/test/ui/nll/issue-53807.stderr
@@ -0,0 +1,21 @@
+error[E0382]: use of partially moved value: `maybe`
+  --> $DIR/issue-53807.rs:4:30
+   |
+LL |         if let Some(thing) = maybe {
+   |                     -----    ^^^^^ value used here after move
+   |                     |
+   |                     value moved here
+   |
+   = note: move occurs because the value has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `(maybe as std::prelude::v1::Some).0`
+  --> $DIR/issue-53807.rs:4:21
+   |
+LL |         if let Some(thing) = maybe {
+   |                     ^^^^^ value moved here in previous iteration of loop
+   |
+   = note: move occurs because the value has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/nll/issue-54382-use-span-of-tail-of-block.nll.stderr b/src/test/ui/nll/issue-54382-use-span-of-tail-of-block.nll.stderr
new file mode 100644
index 0000000..8412cbd
--- /dev/null
+++ b/src/test/ui/nll/issue-54382-use-span-of-tail-of-block.nll.stderr
@@ -0,0 +1,20 @@
+error[E0597]: `_thing1` does not live long enough
+  --> $DIR/issue-54382-use-span-of-tail-of-block.rs:7:29
+   |
+LL |             D("other").next(&_thing1)
+   |             ----------------^^^^^^^^-
+   |             |               |
+   |             |               borrowed value does not live long enough
+   |             a temporary with access to the borrow is created here ...
+...
+LL |     }
+   |     - `_thing1` dropped here while still borrowed
+LL | 
+LL |     ;
+   |     - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D`
+   |
+   = note: The temporary is part of an expression at the end of a block. Consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped.
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/issue-54382-use-span-of-tail-of-block.rs b/src/test/ui/nll/issue-54382-use-span-of-tail-of-block.rs
new file mode 100644
index 0000000..312e6dc
--- /dev/null
+++ b/src/test/ui/nll/issue-54382-use-span-of-tail-of-block.rs
@@ -0,0 +1,29 @@
+fn main() {
+    {
+        let mut _thing1 = D(Box::new("thing1"));
+        {
+            let _thing2 = D("thing2");
+            side_effects();
+            D("other").next(&_thing1)
+//~^ ERROR does not live long enough
+        }
+    }
+
+    ;
+}
+
+#[derive(Debug)]
+struct D<T: std::fmt::Debug>(T);
+
+impl<T: std::fmt::Debug>  Drop for D<T> {
+    fn drop(&mut self) {
+        println!("dropping {:?})", self);
+    }
+}
+
+impl<T: std::fmt::Debug> D<T> {
+    fn next<U: std::fmt::Debug>(&self, _other: U) -> D<U> { D(_other) }
+    fn end(&self) { }
+}
+
+fn side_effects() { }
diff --git a/src/test/ui/nll/issue-54382-use-span-of-tail-of-block.stderr b/src/test/ui/nll/issue-54382-use-span-of-tail-of-block.stderr
new file mode 100644
index 0000000..8d23891
--- /dev/null
+++ b/src/test/ui/nll/issue-54382-use-span-of-tail-of-block.stderr
@@ -0,0 +1,15 @@
+error[E0597]: `_thing1` does not live long enough
+  --> $DIR/issue-54382-use-span-of-tail-of-block.rs:7:30
+   |
+LL |             D("other").next(&_thing1)
+   |                              ^^^^^^^ borrowed value does not live long enough
+...
+LL |     }
+   |     - `_thing1` dropped here while still borrowed
+LL | 
+LL |     ;
+   |     - borrowed value needs to live until here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/issue-54556-niconii.nll.stderr b/src/test/ui/nll/issue-54556-niconii.nll.stderr
new file mode 100644
index 0000000..40cd04d
--- /dev/null
+++ b/src/test/ui/nll/issue-54556-niconii.nll.stderr
@@ -0,0 +1,20 @@
+error[E0597]: `counter` does not live long enough
+  --> $DIR/issue-54556-niconii.rs:22:20
+   |
+LL |     if let Ok(_) = counter.lock() { }
+   |                    ^^^^^^^-------
+   |                    |
+   |                    borrowed value does not live long enough
+   |                    a temporary with access to the borrow is created here ...
+...
+LL | }
+   | -
+   | |
+   | `counter` dropped here while still borrowed
+   | ... and the borrow might be used here, when that temporary is dropped and runs the destructor for type `std::result::Result<MutexGuard<'_>, ()>`
+   |
+   = note: The temporary is part of an expression at the end of a block. Consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped.
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/issue-54556-niconii.rs b/src/test/ui/nll/issue-54556-niconii.rs
new file mode 100644
index 0000000..cae389e
--- /dev/null
+++ b/src/test/ui/nll/issue-54556-niconii.rs
@@ -0,0 +1,31 @@
+// This is a reduction of a concrete test illustrating a case that was
+// annoying to Rust developer niconii (see comment thread on #21114).
+//
+// With resolving issue #54556, pnkfelix hopes that the new diagnostic
+// output produced by NLL helps to *explain* the semantic significance
+// of temp drop order, and thus why inserting a semi-colon after the
+// `if let` expression in `main` works.
+
+struct Mutex;
+struct MutexGuard<'a>(&'a Mutex);
+
+impl Drop for Mutex { fn drop(&mut self) { println!("Mutex::drop"); } }
+impl<'a> Drop for MutexGuard<'a> { fn drop(&mut self) { println!("MutexGuard::drop");  } }
+
+impl Mutex {
+    fn lock(&self) -> Result<MutexGuard, ()> { Ok(MutexGuard(self)) }
+}
+
+fn main() {
+    let counter = Mutex;
+
+    if let Ok(_) = counter.lock() { } //~ ERROR does not live long enough
+
+    // With this code as written, the dynamic semantics here implies
+    // that `Mutex::drop` for `counter` runs *before*
+    // `MutexGuard::drop`, which would be unsound since `MutexGuard`
+    // still has a reference to `counter`.
+    //
+    // The goal of #54556 is to explain that within a compiler
+    // diagnostic.
+}
diff --git a/src/test/ui/nll/issue-54556-niconii.stderr b/src/test/ui/nll/issue-54556-niconii.stderr
new file mode 100644
index 0000000..2d0de26
--- /dev/null
+++ b/src/test/ui/nll/issue-54556-niconii.stderr
@@ -0,0 +1,14 @@
+error[E0597]: `counter` does not live long enough
+  --> $DIR/issue-54556-niconii.rs:22:20
+   |
+LL |     if let Ok(_) = counter.lock() { }
+   |                    ^^^^^^^ borrowed value does not live long enough
+...
+LL | }
+   | - `counter` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/issue-54556-stephaneyfx.nll.stderr b/src/test/ui/nll/issue-54556-stephaneyfx.nll.stderr
new file mode 100644
index 0000000..0bf7648
--- /dev/null
+++ b/src/test/ui/nll/issue-54556-stephaneyfx.nll.stderr
@@ -0,0 +1,19 @@
+error[E0597]: `stmt` does not live long enough
+  --> $DIR/issue-54556-stephaneyfx.rs:27:21
+   |
+LL |     let rows = Rows(&stmt);
+   |                     ^^^^^ borrowed value does not live long enough
+LL |     rows.map(|row| row).next()
+   |     ------------------- a temporary with access to the borrow is created here ...
+...
+LL | }
+   | -
+   | |
+   | `stmt` dropped here while still borrowed
+   | ... and the borrow might be used here, when that temporary is dropped and runs the destructor for type `std::iter::Map<Rows<'_>, [closure@$DIR/issue-54556-stephaneyfx.rs:28:14: 28:23]>`
+   |
+   = note: The temporary is part of an expression at the end of a block. Consider forcing this temporary to be dropped sooner, before the block's local variables are dropped. For example, you could save the expression's value in a new local variable `x` and then make `x` be the expression at the end of the block.
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/issue-54556-stephaneyfx.rs b/src/test/ui/nll/issue-54556-stephaneyfx.rs
new file mode 100644
index 0000000..b758228
--- /dev/null
+++ b/src/test/ui/nll/issue-54556-stephaneyfx.rs
@@ -0,0 +1,35 @@
+// This is a reduction of a concrete test illustrating a case that was
+// annoying to Rust developer stephaneyfx (see issue #46413).
+//
+// With resolving issue #54556, pnkfelix hopes that the new diagnostic
+// output produced by NLL helps to *explain* the semantic significance
+// of temp drop order, and thus why storing the result in `x` and then
+// returning `x` works.
+
+pub struct Statement;
+
+pub struct Rows<'stmt>(&'stmt Statement);
+
+impl<'stmt> Drop for Rows<'stmt> {
+    fn drop(&mut self) {}
+}
+
+impl<'stmt> Iterator for Rows<'stmt> {
+    type Item = String;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        None
+    }
+}
+
+fn get_names() -> Option<String> {
+    let stmt = Statement;
+    let rows = Rows(&stmt); //~ ERROR does not live long enough
+    rows.map(|row| row).next()
+    // let x = rows.map(|row| row).next();
+    // x
+    //
+    // Removing the map works too as does removing the Drop impl.
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/issue-54556-stephaneyfx.stderr b/src/test/ui/nll/issue-54556-stephaneyfx.stderr
new file mode 100644
index 0000000..4e581a5
--- /dev/null
+++ b/src/test/ui/nll/issue-54556-stephaneyfx.stderr
@@ -0,0 +1,14 @@
+error[E0597]: `stmt` does not live long enough
+  --> $DIR/issue-54556-stephaneyfx.rs:27:22
+   |
+LL |     let rows = Rows(&stmt);
+   |                      ^^^^ borrowed value does not live long enough
+...
+LL | }
+   | - `stmt` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/issue-54556-temps-in-tail-diagnostic.nll.stderr b/src/test/ui/nll/issue-54556-temps-in-tail-diagnostic.nll.stderr
new file mode 100644
index 0000000..513dca7
--- /dev/null
+++ b/src/test/ui/nll/issue-54556-temps-in-tail-diagnostic.nll.stderr
@@ -0,0 +1,19 @@
+error[E0597]: `_thing1` does not live long enough
+  --> $DIR/issue-54556-temps-in-tail-diagnostic.rs:5:11
+   |
+LL |         D(&_thing1).end()
+   |         --^^^^^^^^-
+   |         | |
+   |         | borrowed value does not live long enough
+   |         a temporary with access to the borrow is created here ...
+LL |     }
+   |     - `_thing1` dropped here while still borrowed
+LL | 
+LL |     ;
+   |     - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D`
+   |
+   = note: The temporary is part of an expression at the end of a block. Consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped.
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/issue-54556-temps-in-tail-diagnostic.rs b/src/test/ui/nll/issue-54556-temps-in-tail-diagnostic.rs
new file mode 100644
index 0000000..2935caa
--- /dev/null
+++ b/src/test/ui/nll/issue-54556-temps-in-tail-diagnostic.rs
@@ -0,0 +1,23 @@
+fn main() {
+    {
+        let mut _thing1 = D(Box::new("thing1"));
+        // D("other").next(&_thing1).end()
+        D(&_thing1).end() //~ ERROR does not live long enough
+    }
+
+    ;
+}
+
+#[derive(Debug)]
+struct D<T: std::fmt::Debug>(T);
+
+impl<T: std::fmt::Debug>  Drop for D<T> {
+    fn drop(&mut self) {
+        println!("dropping {:?})", self);
+    }
+}
+
+impl<T: std::fmt::Debug> D<T> {
+    fn next<U: std::fmt::Debug>(&self, _other: U) -> D<U> { D(_other) }
+    fn end(&self) { }
+}
diff --git a/src/test/ui/nll/issue-54556-temps-in-tail-diagnostic.stderr b/src/test/ui/nll/issue-54556-temps-in-tail-diagnostic.stderr
new file mode 100644
index 0000000..a74970f
--- /dev/null
+++ b/src/test/ui/nll/issue-54556-temps-in-tail-diagnostic.stderr
@@ -0,0 +1,14 @@
+error[E0597]: `_thing1` does not live long enough
+  --> $DIR/issue-54556-temps-in-tail-diagnostic.rs:5:12
+   |
+LL |         D(&_thing1).end()
+   |            ^^^^^^^ borrowed value does not live long enough
+LL |     }
+   |     - `_thing1` dropped here while still borrowed
+LL | 
+LL |     ;
+   |     - borrowed value needs to live until here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/issue-54556-used-vs-unused-tails.nll.stderr b/src/test/ui/nll/issue-54556-used-vs-unused-tails.nll.stderr
new file mode 100644
index 0000000..52d0870
--- /dev/null
+++ b/src/test/ui/nll/issue-54556-used-vs-unused-tails.nll.stderr
@@ -0,0 +1,113 @@
+error[E0597]: `_t1` does not live long enough
+  --> $DIR/issue-54556-used-vs-unused-tails.rs:10:55
+   |
+LL |     {              let mut _t1 = D(Box::new("t1")); D(&_t1).end()    } ; // suggest `;`
+   |                                                     --^^^^-          - - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D`
+   |                                                     | |              |
+   |                                                     | |              `_t1` dropped here while still borrowed
+   |                                                     | borrowed value does not live long enough
+   |                                                     a temporary with access to the borrow is created here ...
+   |
+   = note: The temporary is part of an expression at the end of a block. Consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped.
+
+error[E0597]: `_t1` does not live long enough
+  --> $DIR/issue-54556-used-vs-unused-tails.rs:13:55
+   |
+LL |     {            { let mut _t1 = D(Box::new("t1")); D(&_t1).end() }  } ; // suggest `;`
+   |                                                     --^^^^-       -    - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D`
+   |                                                     | |           |
+   |                                                     | |           `_t1` dropped here while still borrowed
+   |                                                     | borrowed value does not live long enough
+   |                                                     a temporary with access to the borrow is created here ...
+   |
+   = note: The temporary is part of an expression at the end of a block. Consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped.
+
+error[E0597]: `_t1` does not live long enough
+  --> $DIR/issue-54556-used-vs-unused-tails.rs:16:55
+   |
+LL |     {            { let mut _t1 = D(Box::new("t1")); D(&_t1).end() }; }   // suggest `;`
+   |                                                     --^^^^-       -- ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D`
+   |                                                     | |           |
+   |                                                     | |           `_t1` dropped here while still borrowed
+   |                                                     | borrowed value does not live long enough
+   |                                                     a temporary with access to the borrow is created here ...
+   |
+   = note: The temporary is part of an expression at the end of a block. Consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped.
+
+error[E0597]: `_t1` does not live long enough
+  --> $DIR/issue-54556-used-vs-unused-tails.rs:19:55
+   |
+LL |     let _ =      { let mut _t1 = D(Box::new("t1")); D(&_t1).end()    } ; // suggest `;`
+   |                                                     --^^^^-          - - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D`
+   |                                                     | |              |
+   |                                                     | |              `_t1` dropped here while still borrowed
+   |                                                     | borrowed value does not live long enough
+   |                                                     a temporary with access to the borrow is created here ...
+   |
+   = note: The temporary is part of an expression at the end of a block. Consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped.
+
+error[E0597]: `_t1` does not live long enough
+  --> $DIR/issue-54556-used-vs-unused-tails.rs:22:55
+   |
+LL |     let _u =     { let mut _t1 = D(Box::new("t1")); D(&_t1).unit()   } ; // suggest `;`
+   |                                                     --^^^^-          - - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D`
+   |                                                     | |              |
+   |                                                     | |              `_t1` dropped here while still borrowed
+   |                                                     | borrowed value does not live long enough
+   |                                                     a temporary with access to the borrow is created here ...
+   |
+   = note: The temporary is part of an expression at the end of a block. Consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped.
+
+error[E0597]: `_t1` does not live long enough
+  --> $DIR/issue-54556-used-vs-unused-tails.rs:25:55
+   |
+LL |     let _x =     { let mut _t1 = D(Box::new("t1")); D(&_t1).end()    } ; // `let x = ...; x`
+   |                                                     --^^^^-          - - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D`
+   |                                                     | |              |
+   |                                                     | |              `_t1` dropped here while still borrowed
+   |                                                     | borrowed value does not live long enough
+   |                                                     a temporary with access to the borrow is created here ...
+   |
+   = note: The temporary is part of an expression at the end of a block. Consider forcing this temporary to be dropped sooner, before the block's local variables are dropped. For example, you could save the expression's value in a new local variable `x` and then make `x` be the expression at the end of the block.
+
+error[E0597]: `_t1` does not live long enough
+  --> $DIR/issue-54556-used-vs-unused-tails.rs:30:55
+   |
+LL |     _y =         { let mut _t1 = D(Box::new("t1")); D(&_t1).end() } ; // `let x = ...; x`
+   |                                                     --^^^^-       - - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D`
+   |                                                     | |           |
+   |                                                     | |           `_t1` dropped here while still borrowed
+   |                                                     | borrowed value does not live long enough
+   |                                                     a temporary with access to the borrow is created here ...
+   |
+   = note: The temporary is part of an expression at the end of a block. Consider forcing this temporary to be dropped sooner, before the block's local variables are dropped. For example, you could save the expression's value in a new local variable `x` and then make `x` be the expression at the end of the block.
+
+error[E0597]: `_t1` does not live long enough
+  --> $DIR/issue-54556-used-vs-unused-tails.rs:37:55
+   |
+LL | fn f_local_ref() { let mut _t1 = D(Box::new("t1")); D(&_t1).unit()   }  // suggest `;`
+   |                                                     --^^^^-          -
+   |                                                     | |              |
+   |                                                     | |              `_t1` dropped here while still borrowed
+   |                                                     | |              ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D`
+   |                                                     | borrowed value does not live long enough
+   |                                                     a temporary with access to the borrow is created here ...
+   |
+   = note: The temporary is part of an expression at the end of a block. Consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped.
+
+error[E0597]: `_t1` does not live long enough
+  --> $DIR/issue-54556-used-vs-unused-tails.rs:40:55
+   |
+LL | fn f() -> String { let mut _t1 = D(Box::new("t1")); D(&_t1).end()   }   // `let x = ...; x`
+   |                                                     --^^^^-         -
+   |                                                     | |             |
+   |                                                     | |             `_t1` dropped here while still borrowed
+   |                                                     | |             ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D`
+   |                                                     | borrowed value does not live long enough
+   |                                                     a temporary with access to the borrow is created here ...
+   |
+   = note: The temporary is part of an expression at the end of a block. Consider forcing this temporary to be dropped sooner, before the block's local variables are dropped. For example, you could save the expression's value in a new local variable `x` and then make `x` be the expression at the end of the block.
+
+error: aborting due to 9 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/issue-54556-used-vs-unused-tails.rs b/src/test/ui/nll/issue-54556-used-vs-unused-tails.rs
new file mode 100644
index 0000000..0d96767
--- /dev/null
+++ b/src/test/ui/nll/issue-54556-used-vs-unused-tails.rs
@@ -0,0 +1,56 @@
+// Ths test case is exploring the space of how blocs with tail
+// expressions and statements can be composed, trying to keep each
+// case on one line so that we can compare them via a vertical scan
+// with the human eye.
+
+// Each comment on the right side of the line is summarizing the
+// expected suggestion from the diagnostic for issue #54556.
+
+fn main() {
+    {              let mut _t1 = D(Box::new("t1")); D(&_t1).end()    } ; // suggest `;`
+//~^ ERROR does not live long enough
+
+    {            { let mut _t1 = D(Box::new("t1")); D(&_t1).end() }  } ; // suggest `;`
+//~^ ERROR does not live long enough
+
+    {            { let mut _t1 = D(Box::new("t1")); D(&_t1).end() }; }   // suggest `;`
+//~^ ERROR does not live long enough
+
+    let _ =      { let mut _t1 = D(Box::new("t1")); D(&_t1).end()    } ; // suggest `;`
+//~^ ERROR does not live long enough
+
+    let _u =     { let mut _t1 = D(Box::new("t1")); D(&_t1).unit()   } ; // suggest `;`
+//~^ ERROR does not live long enough
+
+    let _x =     { let mut _t1 = D(Box::new("t1")); D(&_t1).end()    } ; // `let x = ...; x`
+//~^ ERROR does not live long enough
+    let _x =     { let mut _t1 = D(Box::new("t1")); let x = D(&_t1).end(); x } ; // no error
+
+    let mut _y;
+    _y =         { let mut _t1 = D(Box::new("t1")); D(&_t1).end() } ; // `let x = ...; x`
+//~^ ERROR does not live long enough
+    _y =         { let mut _t1 = D(Box::new("t1")); let x = D(&_t1).end(); x } ; // no error
+}
+
+fn f_param_ref(_t1: D<Box<&'static str>>) {         D(&_t1).unit()   }  // no error
+
+fn f_local_ref() { let mut _t1 = D(Box::new("t1")); D(&_t1).unit()   }  // suggest `;`
+//~^ ERROR does not live long enough
+
+fn f() -> String { let mut _t1 = D(Box::new("t1")); D(&_t1).end()   }   // `let x = ...; x`
+//~^ ERROR does not live long enough
+
+#[derive(Debug)]
+struct D<T: std::fmt::Debug>(T);
+
+impl<T: std::fmt::Debug>  Drop for D<T> {
+    fn drop(&mut self) {
+        println!("dropping {:?})", self);
+    }
+}
+
+impl<T: std::fmt::Debug> D<T> {
+    fn next<U: std::fmt::Debug>(&self, _other: U) -> D<U> { D(_other) }
+    fn end(&self) -> String { format!("End({:?})", self.0) }
+    fn unit(&self) { }
+}
diff --git a/src/test/ui/nll/issue-54556-used-vs-unused-tails.stderr b/src/test/ui/nll/issue-54556-used-vs-unused-tails.stderr
new file mode 100644
index 0000000..e9e4e51
--- /dev/null
+++ b/src/test/ui/nll/issue-54556-used-vs-unused-tails.stderr
@@ -0,0 +1,86 @@
+error[E0597]: `_t1` does not live long enough
+  --> $DIR/issue-54556-used-vs-unused-tails.rs:10:56
+   |
+LL |     {              let mut _t1 = D(Box::new("t1")); D(&_t1).end()    } ; // suggest `;`
+   |                                                        ^^^           - - borrowed value needs to live until here
+   |                                                        |             |
+   |                                                        |             `_t1` dropped here while still borrowed
+   |                                                        borrowed value does not live long enough
+
+error[E0597]: `_t1` does not live long enough
+  --> $DIR/issue-54556-used-vs-unused-tails.rs:13:56
+   |
+LL |     {            { let mut _t1 = D(Box::new("t1")); D(&_t1).end() }  } ; // suggest `;`
+   |                                                        ^^^        -    - borrowed value needs to live until here
+   |                                                        |          |
+   |                                                        |          `_t1` dropped here while still borrowed
+   |                                                        borrowed value does not live long enough
+
+error[E0597]: `_t1` does not live long enough
+  --> $DIR/issue-54556-used-vs-unused-tails.rs:16:56
+   |
+LL |     {            { let mut _t1 = D(Box::new("t1")); D(&_t1).end() }; }   // suggest `;`
+   |                                                        ^^^        -- borrowed value needs to live until here
+   |                                                        |          |
+   |                                                        |          `_t1` dropped here while still borrowed
+   |                                                        borrowed value does not live long enough
+
+error[E0597]: `_t1` does not live long enough
+  --> $DIR/issue-54556-used-vs-unused-tails.rs:19:56
+   |
+LL |     let _ =      { let mut _t1 = D(Box::new("t1")); D(&_t1).end()    } ; // suggest `;`
+   |                                                        ^^^           - - borrowed value needs to live until here
+   |                                                        |             |
+   |                                                        |             `_t1` dropped here while still borrowed
+   |                                                        borrowed value does not live long enough
+
+error[E0597]: `_t1` does not live long enough
+  --> $DIR/issue-54556-used-vs-unused-tails.rs:22:56
+   |
+LL |     let _u =     { let mut _t1 = D(Box::new("t1")); D(&_t1).unit()   } ; // suggest `;`
+   |                                                        ^^^           - - borrowed value needs to live until here
+   |                                                        |             |
+   |                                                        |             `_t1` dropped here while still borrowed
+   |                                                        borrowed value does not live long enough
+
+error[E0597]: `_t1` does not live long enough
+  --> $DIR/issue-54556-used-vs-unused-tails.rs:25:56
+   |
+LL |     let _x =     { let mut _t1 = D(Box::new("t1")); D(&_t1).end()    } ; // `let x = ...; x`
+   |                                                        ^^^           - - borrowed value needs to live until here
+   |                                                        |             |
+   |                                                        |             `_t1` dropped here while still borrowed
+   |                                                        borrowed value does not live long enough
+
+error[E0597]: `_t1` does not live long enough
+  --> $DIR/issue-54556-used-vs-unused-tails.rs:30:56
+   |
+LL |     _y =         { let mut _t1 = D(Box::new("t1")); D(&_t1).end() } ; // `let x = ...; x`
+   |                                                        ^^^        - - borrowed value needs to live until here
+   |                                                        |          |
+   |                                                        |          `_t1` dropped here while still borrowed
+   |                                                        borrowed value does not live long enough
+
+error[E0597]: `_t1` does not live long enough
+  --> $DIR/issue-54556-used-vs-unused-tails.rs:37:56
+   |
+LL | fn f_local_ref() { let mut _t1 = D(Box::new("t1")); D(&_t1).unit()   }  // suggest `;`
+   |                                                        ^^^           - `_t1` dropped here while still borrowed
+   |                                                        |
+   |                                                        borrowed value does not live long enough
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error[E0597]: `_t1` does not live long enough
+  --> $DIR/issue-54556-used-vs-unused-tails.rs:40:56
+   |
+LL | fn f() -> String { let mut _t1 = D(Box::new("t1")); D(&_t1).end()   }   // `let x = ...; x`
+   |                                                        ^^^          - `_t1` dropped here while still borrowed
+   |                                                        |
+   |                                                        borrowed value does not live long enough
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: aborting due to 9 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/issue-54556-wrap-it-up.nll.stderr b/src/test/ui/nll/issue-54556-wrap-it-up.nll.stderr
new file mode 100644
index 0000000..9f27fac
--- /dev/null
+++ b/src/test/ui/nll/issue-54556-wrap-it-up.nll.stderr
@@ -0,0 +1,14 @@
+error[E0506]: cannot assign to `x` because it is borrowed
+  --> $DIR/issue-54556-wrap-it-up.rs:27:5
+   |
+LL |     let wrap = Wrap { p: &mut x };
+   |                          ------ borrow of `x` occurs here
+...
+LL |     x = 1;
+   |     ^^^^^ assignment to borrowed `x` occurs here
+LL | }
+   | - borrow might be used here, when `foo` is dropped and runs the destructor for type `Foo<'_>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/nll/issue-54556-wrap-it-up.rs b/src/test/ui/nll/issue-54556-wrap-it-up.rs
new file mode 100644
index 0000000..11dbef0
--- /dev/null
+++ b/src/test/ui/nll/issue-54556-wrap-it-up.rs
@@ -0,0 +1,28 @@
+// This is testing how the diagnostic from issue #54556 behaves when
+// the destructor code is attached to a place held in a field of the
+// temporary being dropped.
+//
+// Eventually it would be nice if the diagnostic would actually report
+// that specific place and its type that implements the `Drop` trait.
+// But for the short term, it is acceptable to just print out the
+// whole type of the temporary.
+
+#![allow(warnings)]
+
+struct Wrap<'p> { p: &'p mut i32 }
+
+impl<'p> Drop for Wrap<'p> {
+    fn drop(&mut self) {
+        *self.p += 1;
+    }
+}
+
+struct Foo<'p> { a: String, b: Wrap<'p> }
+
+fn main() {
+    let mut x = 0;
+    let wrap = Wrap { p: &mut x };
+    let s = String::from("str");
+    let foo = Foo { a: s, b: wrap };
+    x = 1; //~ ERROR cannot assign to `x` because it is borrowed [E0506]
+}
diff --git a/src/test/ui/nll/issue-54556-wrap-it-up.stderr b/src/test/ui/nll/issue-54556-wrap-it-up.stderr
new file mode 100644
index 0000000..c98b3a9
--- /dev/null
+++ b/src/test/ui/nll/issue-54556-wrap-it-up.stderr
@@ -0,0 +1,12 @@
+error[E0506]: cannot assign to `x` because it is borrowed
+  --> $DIR/issue-54556-wrap-it-up.rs:27:5
+   |
+LL |     let wrap = Wrap { p: &mut x };
+   |                               - borrow of `x` occurs here
+...
+LL |     x = 1;
+   |     ^^^^^ assignment to borrowed `x` occurs here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/nll/issue-55288.rs b/src/test/ui/nll/issue-55288.rs
new file mode 100644
index 0000000..9b3eb7f
--- /dev/null
+++ b/src/test/ui/nll/issue-55288.rs
@@ -0,0 +1,11 @@
+#![feature(nll)]
+
+// run-pass
+
+struct Slice(&'static [&'static [u8]]);
+
+static MAP: Slice = Slice(&[
+    b"CloseEvent" as &'static [u8],
+]);
+
+fn main() {}
diff --git a/src/test/ui/nll/issue-55344.rs b/src/test/ui/nll/issue-55344.rs
new file mode 100644
index 0000000..b900acf
--- /dev/null
+++ b/src/test/ui/nll/issue-55344.rs
@@ -0,0 +1,16 @@
+// compile-pass
+
+#![feature(nll)]
+#![allow(unreachable_code)]
+#![deny(unused_mut)]
+
+pub fn foo() {
+    return;
+
+    let mut v = 0;
+    assert_eq!(v, 0);
+    v = 1;
+    assert_eq!(v, 1);
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/issue-55394.rs b/src/test/ui/nll/issue-55394.rs
new file mode 100644
index 0000000..deb1034
--- /dev/null
+++ b/src/test/ui/nll/issue-55394.rs
@@ -0,0 +1,15 @@
+#![feature(nll)]
+
+struct Bar;
+
+struct Foo<'s> {
+    bar: &'s mut Bar,
+}
+
+impl Foo<'_> {
+    fn new(bar: &mut Bar) -> Self {
+        Foo { bar } //~ERROR lifetime may not live long enough
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/issue-55394.stderr b/src/test/ui/nll/issue-55394.stderr
new file mode 100644
index 0000000..e9a70fd
--- /dev/null
+++ b/src/test/ui/nll/issue-55394.stderr
@@ -0,0 +1,12 @@
+error: lifetime may not live long enough
+  --> $DIR/issue-55394.rs:11:9
+   |
+LL |     fn new(bar: &mut Bar) -> Self {
+   |                 -            ---- return type is Foo<'2>
+   |                 |
+   |                 let's call the lifetime of this reference `'1`
+LL |         Foo { bar }
+   |         ^^^^^^^^^^^ returning this value requires that `'1` must outlive `'2`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/issue-55401.rs b/src/test/ui/nll/issue-55401.rs
new file mode 100644
index 0000000..2fa2344
--- /dev/null
+++ b/src/test/ui/nll/issue-55401.rs
@@ -0,0 +1,8 @@
+#![feature(nll)]
+
+fn static_to_a_to_static_through_ref_in_tuple<'a>(x: &'a u32) -> &'static u32 {
+    let (ref y, _z): (&'a u32, u32) = (&22, 44);
+    *y //~ ERROR
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/issue-55401.stderr b/src/test/ui/nll/issue-55401.stderr
new file mode 100644
index 0000000..622bc5a
--- /dev/null
+++ b/src/test/ui/nll/issue-55401.stderr
@@ -0,0 +1,11 @@
+error: lifetime may not live long enough
+  --> $DIR/issue-55401.rs:5:5
+   |
+LL | fn static_to_a_to_static_through_ref_in_tuple<'a>(x: &'a u32) -> &'static u32 {
+   |                                               -- lifetime `'a` defined here
+LL |     let (ref y, _z): (&'a u32, u32) = (&22, 44);
+LL |     *y
+   |     ^^ returning this value requires that `'a` must outlive `'static`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/issue-55651.rs b/src/test/ui/nll/issue-55651.rs
new file mode 100644
index 0000000..976098e
--- /dev/null
+++ b/src/test/ui/nll/issue-55651.rs
@@ -0,0 +1,28 @@
+// compile-pass
+
+#![feature(untagged_unions)]
+
+struct A;
+struct B;
+
+union U {
+    a: A,
+    b: B,
+}
+
+fn main() {
+    unsafe {
+        {
+            let mut u = U { a: A };
+            let a = u.a;
+            u.a = A;
+            let a = u.a; // OK
+        }
+        {
+            let mut u = U { a: A };
+            let a = u.a;
+            u.b = B;
+            let a = u.a; // OK
+        }
+    }
+}
diff --git a/src/test/ui/nll/issue-55850.nll.stderr b/src/test/ui/nll/issue-55850.nll.stderr
new file mode 100644
index 0000000..bf0c698
--- /dev/null
+++ b/src/test/ui/nll/issue-55850.nll.stderr
@@ -0,0 +1,18 @@
+error[E0597]: `s` does not live long enough
+  --> $DIR/issue-55850.rs:28:16
+   |
+LL |         yield &s[..]
+   |                ^ borrowed value does not live long enough
+LL |     })
+   |     - `s` dropped here while still borrowed
+
+error[E0626]: borrow may still be in use when generator yields
+  --> $DIR/issue-55850.rs:28:16
+   |
+LL |         yield &s[..]
+   |         -------^---- possible yield occurs here
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0597, E0626.
+For more information about an error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/issue-55850.rs b/src/test/ui/nll/issue-55850.rs
new file mode 100644
index 0000000..8b58872
--- /dev/null
+++ b/src/test/ui/nll/issue-55850.rs
@@ -0,0 +1,34 @@
+#![allow(unused_mut)]
+#![feature(generators, generator_trait)]
+
+use std::marker::Unpin;
+use std::ops::Generator;
+use std::ops::GeneratorState::Yielded;
+use std::pin::Pin;
+
+pub struct GenIter<G>(G);
+
+impl <G> Iterator for GenIter<G>
+where
+    G: Generator + Unpin,
+{
+    type Item = G::Yield;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        match Pin::new(&mut self.0).resume() {
+            Yielded(y) => Some(y),
+            _ => None
+        }
+    }
+}
+
+fn bug<'a>() -> impl Iterator<Item = &'a str> {
+    GenIter(move || {
+        let mut s = String::new();
+        yield &s[..] //~ ERROR `s` does not live long enough [E0597]
+    })
+}
+
+fn main() {
+    bug();
+}
diff --git a/src/test/ui/nll/issue-55850.stderr b/src/test/ui/nll/issue-55850.stderr
new file mode 100644
index 0000000..7deee1d
--- /dev/null
+++ b/src/test/ui/nll/issue-55850.stderr
@@ -0,0 +1,17 @@
+error[E0597]: `s` does not live long enough
+  --> $DIR/issue-55850.rs:28:16
+   |
+LL |         yield &s[..]
+   |                ^ borrowed value does not live long enough
+LL |     })
+   |     - borrowed value only lives until here
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 25:8...
+  --> $DIR/issue-55850.rs:25:8
+   |
+LL | fn bug<'a>() -> impl Iterator<Item = &'a str> {
+   |        ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/issue-57100.rs b/src/test/ui/nll/issue-57100.rs
new file mode 100644
index 0000000..f669fe0
--- /dev/null
+++ b/src/test/ui/nll/issue-57100.rs
@@ -0,0 +1,69 @@
+#![allow(unused)]
+#![feature(nll)]
+
+// ignore-tidy-linelength
+
+// This tests the error messages for borrows of union fields when the unions are embedded in other
+// structs or unions.
+
+#[derive(Clone, Copy, Default)]
+struct Leaf {
+    l1_u8: u8,
+    l2_u8: u8,
+}
+
+#[derive(Clone, Copy)]
+union First {
+    f1_leaf: Leaf,
+    f2_leaf: Leaf,
+    f3_union: Second,
+}
+
+#[derive(Clone, Copy)]
+union Second {
+    s1_leaf: Leaf,
+    s2_leaf: Leaf,
+}
+
+struct Root {
+    r1_u8: u8,
+    r2_union: First,
+}
+
+// Borrow a different field of the nested union.
+fn nested_union() {
+    unsafe {
+        let mut r = Root {
+            r1_u8: 3,
+            r2_union: First { f3_union: Second { s2_leaf: Leaf { l1_u8: 8, l2_u8: 4 } } }
+        };
+
+        let mref = &mut r.r2_union.f3_union.s1_leaf.l1_u8;
+        //                                  ^^^^^^^
+        *mref = 22;
+        let nref = &r.r2_union.f3_union.s2_leaf.l1_u8;
+        //                              ^^^^^^^
+        //~^^ ERROR cannot borrow `r.r2_union.f3_union` (via `r.r2_union.f3_union.s2_leaf.l1_u8`) as immutable because it is also borrowed as mutable (via `r.r2_union.f3_union.s1_leaf.l1_u8`) [E0502]
+        println!("{} {}", mref, nref)
+    }
+}
+
+// Borrow a different field of the first union.
+fn first_union() {
+    unsafe {
+        let mut r = Root {
+            r1_u8: 3,
+            r2_union: First { f3_union: Second { s2_leaf: Leaf { l1_u8: 8, l2_u8: 4 } } }
+        };
+
+        let mref = &mut r.r2_union.f2_leaf.l1_u8;
+        //                         ^^^^^^^
+        *mref = 22;
+        let nref = &r.r2_union.f1_leaf.l1_u8;
+        //                     ^^^^^^^
+        //~^^ ERROR cannot borrow `r.r2_union` (via `r.r2_union.f1_leaf.l1_u8`) as immutable because it is also borrowed as mutable (via `r.r2_union.f2_leaf.l1_u8`) [E0502]
+        println!("{} {}", mref, nref)
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/issue-57100.stderr b/src/test/ui/nll/issue-57100.stderr
new file mode 100644
index 0000000..5d5c86c
--- /dev/null
+++ b/src/test/ui/nll/issue-57100.stderr
@@ -0,0 +1,31 @@
+error[E0502]: cannot borrow `r.r2_union.f3_union` (via `r.r2_union.f3_union.s2_leaf.l1_u8`) as immutable because it is also borrowed as mutable (via `r.r2_union.f3_union.s1_leaf.l1_u8`)
+  --> $DIR/issue-57100.rs:44:20
+   |
+LL |         let mref = &mut r.r2_union.f3_union.s1_leaf.l1_u8;
+   |                    -------------------------------------- mutable borrow occurs here (via `r.r2_union.f3_union.s1_leaf.l1_u8`)
+...
+LL |         let nref = &r.r2_union.f3_union.s2_leaf.l1_u8;
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ immutable borrow of `r.r2_union.f3_union.s2_leaf.l1_u8` -- which overlaps with `r.r2_union.f3_union.s1_leaf.l1_u8` -- occurs here
+...
+LL |         println!("{} {}", mref, nref)
+   |                           ---- mutable borrow later used here
+   |
+   = note: `r.r2_union.f3_union.s2_leaf.l1_u8` is a field of the union `Second`, so it overlaps the field `r.r2_union.f3_union.s1_leaf.l1_u8`
+
+error[E0502]: cannot borrow `r.r2_union` (via `r.r2_union.f1_leaf.l1_u8`) as immutable because it is also borrowed as mutable (via `r.r2_union.f2_leaf.l1_u8`)
+  --> $DIR/issue-57100.rs:62:20
+   |
+LL |         let mref = &mut r.r2_union.f2_leaf.l1_u8;
+   |                    ----------------------------- mutable borrow occurs here (via `r.r2_union.f2_leaf.l1_u8`)
+...
+LL |         let nref = &r.r2_union.f1_leaf.l1_u8;
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^ immutable borrow of `r.r2_union.f1_leaf.l1_u8` -- which overlaps with `r.r2_union.f2_leaf.l1_u8` -- occurs here
+...
+LL |         println!("{} {}", mref, nref)
+   |                           ---- mutable borrow later used here
+   |
+   = note: `r.r2_union.f1_leaf.l1_u8` is a field of the union `First`, so it overlaps the field `r.r2_union.f2_leaf.l1_u8`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/nll/issue-57265-return-type-wf-check.rs b/src/test/ui/nll/issue-57265-return-type-wf-check.rs
new file mode 100644
index 0000000..24c61a4
--- /dev/null
+++ b/src/test/ui/nll/issue-57265-return-type-wf-check.rs
@@ -0,0 +1,26 @@
+#![feature(nll)]
+
+use std::any::Any;
+
+#[derive(Debug, Clone)]
+struct S<T: 'static>(T);
+
+// S<&'a T> is in the return type, so we get an implied bound
+// &'a T: 'static
+fn foo<'a, T>(x: &'a T) -> (S<&'a T>, Box<dyn Any + 'static>) {
+    let y = S(x);
+
+    let z = Box::new(y.clone()) as Box<dyn Any + 'static>;
+    (y, z)
+}
+
+fn main() {
+    let x = 5;
+
+    // Check that we require that the argument is of type `&'static String`,
+    // so that the return type is well-formed.
+    let (_, z) = foo(&"hello".to_string());
+    //~^ ERROR temporary value dropped while borrowed
+
+    println!("{:?}", z.downcast_ref::<S<&'static String>>());
+}
diff --git a/src/test/ui/nll/issue-57265-return-type-wf-check.stderr b/src/test/ui/nll/issue-57265-return-type-wf-check.stderr
new file mode 100644
index 0000000..db01212
--- /dev/null
+++ b/src/test/ui/nll/issue-57265-return-type-wf-check.stderr
@@ -0,0 +1,12 @@
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/issue-57265-return-type-wf-check.rs:22:23
+   |
+LL |     let (_, z) = foo(&"hello".to_string());
+   |                  -----^^^^^^^^^^^^^^^^^^^-- temporary value is freed at the end of this statement
+   |                  |    |
+   |                  |    creates a temporary which is freed while still in use
+   |                  argument requires that borrow lasts for `'static`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/src/test/ui/nll/issue-57280-1.rs b/src/test/ui/nll/issue-57280-1.rs
new file mode 100644
index 0000000..356c477
--- /dev/null
+++ b/src/test/ui/nll/issue-57280-1.rs
@@ -0,0 +1,21 @@
+#![feature(nll)]
+
+// compile-pass
+
+trait Foo<'a> {
+    const C: &'a u32;
+}
+
+impl<'a, T> Foo<'a> for T {
+    const C: &'a u32 = &22;
+}
+
+fn foo() {
+    let a = 22;
+    match &a {
+        <() as Foo<'static>>::C => { }
+        &_ => { }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/issue-57280.rs b/src/test/ui/nll/issue-57280.rs
new file mode 100644
index 0000000..4fe6a96
--- /dev/null
+++ b/src/test/ui/nll/issue-57280.rs
@@ -0,0 +1,22 @@
+#![feature(nll)]
+
+// compile-pass
+
+trait Foo {
+    const BLAH: &'static str;
+}
+
+struct Placeholder;
+
+impl Foo for Placeholder {
+    const BLAH: &'static str = "hi";
+}
+
+fn foo(x: &str) {
+    match x {
+        <Placeholder as Foo>::BLAH => { }
+        _ => { }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/issue-57960.rs b/src/test/ui/nll/issue-57960.rs
new file mode 100644
index 0000000..0b52e46
--- /dev/null
+++ b/src/test/ui/nll/issue-57960.rs
@@ -0,0 +1,39 @@
+// run-pass
+
+#![allow(dead_code)]
+
+trait Range {
+    const FIRST: u8;
+    const LAST: u8;
+}
+
+struct OneDigit;
+impl Range for OneDigit {
+    const FIRST: u8 = 0;
+    const LAST: u8 = 9;
+}
+
+struct TwoDigits;
+impl Range for TwoDigits {
+    const FIRST: u8 = 10;
+    const LAST: u8 = 99;
+}
+
+struct ThreeDigits;
+impl Range for ThreeDigits {
+    const FIRST: u8 = 100;
+    const LAST: u8 = 255;
+}
+
+fn digits(x: u8) -> u32 {
+    match x {
+        OneDigit::FIRST...OneDigit::LAST => 1,
+        TwoDigits::FIRST...TwoDigits::LAST => 2,
+        ThreeDigits::FIRST...ThreeDigits::LAST => 3,
+        _ => unreachable!(),
+    }
+}
+
+fn main() {
+    assert_eq!(digits(100), 3);
+}
diff --git a/src/test/ui/nll/issue-57989.rs b/src/test/ui/nll/issue-57989.rs
new file mode 100644
index 0000000..4f21cca
--- /dev/null
+++ b/src/test/ui/nll/issue-57989.rs
@@ -0,0 +1,12 @@
+// Test for ICE from issue 57989
+
+#![feature(nll)]
+
+fn f(x: &i32) {
+    let g = &x;
+    *x = 0;     //~ ERROR cannot assign to `*x` which is behind a `&` reference
+                //~| ERROR cannot assign to `*x` because it is borrowed
+    g;
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/issue-57989.stderr b/src/test/ui/nll/issue-57989.stderr
new file mode 100644
index 0000000..db28787
--- /dev/null
+++ b/src/test/ui/nll/issue-57989.stderr
@@ -0,0 +1,24 @@
+error[E0594]: cannot assign to `*x` which is behind a `&` reference
+  --> $DIR/issue-57989.rs:7:5
+   |
+LL | fn f(x: &i32) {
+   |         ---- help: consider changing this to be a mutable reference: `&mut i32`
+LL |     let g = &x;
+LL |     *x = 0;
+   |     ^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written
+
+error[E0506]: cannot assign to `*x` because it is borrowed
+  --> $DIR/issue-57989.rs:7:5
+   |
+LL |     let g = &x;
+   |             -- borrow of `*x` occurs here
+LL |     *x = 0;
+   |     ^^^^^^ assignment to borrowed `*x` occurs here
+LL |
+LL |     g;
+   |     - borrow later used here
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0506, E0594.
+For more information about an error, try `rustc --explain E0506`.
diff --git a/src/test/ui/nll/issue-58053.rs b/src/test/ui/nll/issue-58053.rs
new file mode 100644
index 0000000..d433890
--- /dev/null
+++ b/src/test/ui/nll/issue-58053.rs
@@ -0,0 +1,14 @@
+#![allow(warnings)]
+#![feature(nll)]
+
+fn main() {
+    let i = &3;
+
+    let f = |x: &i32| -> &i32 { x };
+    //~^ ERROR lifetime may not live long enough
+    let j = f(i);
+
+    let g = |x: &i32| { x };
+    //~^ ERROR lifetime may not live long enough
+    let k = g(i);
+}
diff --git a/src/test/ui/nll/issue-58053.stderr b/src/test/ui/nll/issue-58053.stderr
new file mode 100644
index 0000000..9048983
--- /dev/null
+++ b/src/test/ui/nll/issue-58053.stderr
@@ -0,0 +1,20 @@
+error: lifetime may not live long enough
+  --> $DIR/issue-58053.rs:7:33
+   |
+LL |     let f = |x: &i32| -> &i32 { x };
+   |                 -        ----   ^ returning this value requires that `'1` must outlive `'2`
+   |                 |        |
+   |                 |        return type of closure is &'2 i32
+   |                 let's call the lifetime of this reference `'1`
+
+error: lifetime may not live long enough
+  --> $DIR/issue-58053.rs:11:25
+   |
+LL |     let g = |x: &i32| { x };
+   |                 -   -   ^ returning this value requires that `'1` must outlive `'2`
+   |                 |   |
+   |                 |   return type of closure is &'2 i32
+   |                 let's call the lifetime of this reference `'1`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/nll/issue-58299.rs b/src/test/ui/nll/issue-58299.rs
new file mode 100644
index 0000000..9267cac
--- /dev/null
+++ b/src/test/ui/nll/issue-58299.rs
@@ -0,0 +1,30 @@
+#![allow(dead_code)]
+#![feature(nll)]
+
+struct A<'a>(&'a ());
+
+trait Y {
+    const X: i32;
+}
+
+impl Y for A<'static> {
+    const X: i32 = 10;
+}
+
+fn foo<'a>(x: i32) {
+    match x {
+        // This uses <A<'a> as Y>::X, but `A<'a>` does not implement `Y`.
+        A::<'a>::X..=A::<'static>::X => (), //~ ERROR lifetime may not live long enough
+        _ => (),
+    }
+}
+
+fn bar<'a>(x: i32) {
+    match x {
+        // This uses <A<'a> as Y>::X, but `A<'a>` does not implement `Y`.
+        A::<'static>::X..=A::<'a>::X => (), //~ ERROR lifetime may not live long enough
+        _ => (),
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/issue-58299.stderr b/src/test/ui/nll/issue-58299.stderr
new file mode 100644
index 0000000..0c69b70
--- /dev/null
+++ b/src/test/ui/nll/issue-58299.stderr
@@ -0,0 +1,20 @@
+error: lifetime may not live long enough
+  --> $DIR/issue-58299.rs:17:9
+   |
+LL | fn foo<'a>(x: i32) {
+   |        -- lifetime `'a` defined here
+...
+LL |         A::<'a>::X..=A::<'static>::X => (),
+   |         ^^^^^^^^^^ requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/issue-58299.rs:25:27
+   |
+LL | fn bar<'a>(x: i32) {
+   |        -- lifetime `'a` defined here
+...
+LL |         A::<'static>::X..=A::<'a>::X => (),
+   |                           ^^^^^^^^^^ requires that `'a` must outlive `'static`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/nll/loan_ends_mid_block_pair.rs b/src/test/ui/nll/loan_ends_mid_block_pair.rs
new file mode 100644
index 0000000..bad214d
--- /dev/null
+++ b/src/test/ui/nll/loan_ends_mid_block_pair.rs
@@ -0,0 +1,37 @@
+// compile-flags:-Zborrowck=compare
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+
+
+fn main() {
+}
+
+fn nll_fail() {
+    let mut data = ('a', 'b', 'c');
+    let c = &mut data.0;
+    capitalize(c);
+    data.0 = 'e';
+    //~^ ERROR (Ast) [E0506]
+    //~| ERROR (Mir) [E0506]
+    data.0 = 'f';
+    //~^ ERROR (Ast) [E0506]
+    data.0 = 'g';
+    //~^ ERROR (Ast) [E0506]
+    capitalize(c);
+}
+
+fn nll_ok() {
+    let mut data = ('a', 'b', 'c');
+    let c = &mut data.0;
+    capitalize(c);
+    data.0 = 'e';
+    //~^ ERROR (Ast) [E0506]
+    data.0 = 'f';
+    //~^ ERROR (Ast) [E0506]
+    data.0 = 'g';
+    //~^ ERROR (Ast) [E0506]
+}
+
+fn capitalize(_: &mut char) {
+}
diff --git a/src/test/ui/nll/loan_ends_mid_block_pair.stderr b/src/test/ui/nll/loan_ends_mid_block_pair.stderr
new file mode 100644
index 0000000..85703bd
--- /dev/null
+++ b/src/test/ui/nll/loan_ends_mid_block_pair.stderr
@@ -0,0 +1,69 @@
+error[E0506]: cannot assign to `data.0` because it is borrowed (Ast)
+  --> $DIR/loan_ends_mid_block_pair.rs:14:5
+   |
+LL |     let c = &mut data.0;
+   |                  ------ borrow of `data.0` occurs here
+LL |     capitalize(c);
+LL |     data.0 = 'e';
+   |     ^^^^^^^^^^^^ assignment to borrowed `data.0` occurs here
+
+error[E0506]: cannot assign to `data.0` because it is borrowed (Ast)
+  --> $DIR/loan_ends_mid_block_pair.rs:17:5
+   |
+LL |     let c = &mut data.0;
+   |                  ------ borrow of `data.0` occurs here
+...
+LL |     data.0 = 'f';
+   |     ^^^^^^^^^^^^ assignment to borrowed `data.0` occurs here
+
+error[E0506]: cannot assign to `data.0` because it is borrowed (Ast)
+  --> $DIR/loan_ends_mid_block_pair.rs:19:5
+   |
+LL |     let c = &mut data.0;
+   |                  ------ borrow of `data.0` occurs here
+...
+LL |     data.0 = 'g';
+   |     ^^^^^^^^^^^^ assignment to borrowed `data.0` occurs here
+
+error[E0506]: cannot assign to `data.0` because it is borrowed (Ast)
+  --> $DIR/loan_ends_mid_block_pair.rs:28:5
+   |
+LL |     let c = &mut data.0;
+   |                  ------ borrow of `data.0` occurs here
+LL |     capitalize(c);
+LL |     data.0 = 'e';
+   |     ^^^^^^^^^^^^ assignment to borrowed `data.0` occurs here
+
+error[E0506]: cannot assign to `data.0` because it is borrowed (Ast)
+  --> $DIR/loan_ends_mid_block_pair.rs:30:5
+   |
+LL |     let c = &mut data.0;
+   |                  ------ borrow of `data.0` occurs here
+...
+LL |     data.0 = 'f';
+   |     ^^^^^^^^^^^^ assignment to borrowed `data.0` occurs here
+
+error[E0506]: cannot assign to `data.0` because it is borrowed (Ast)
+  --> $DIR/loan_ends_mid_block_pair.rs:32:5
+   |
+LL |     let c = &mut data.0;
+   |                  ------ borrow of `data.0` occurs here
+...
+LL |     data.0 = 'g';
+   |     ^^^^^^^^^^^^ assignment to borrowed `data.0` occurs here
+
+error[E0506]: cannot assign to `data.0` because it is borrowed (Mir)
+  --> $DIR/loan_ends_mid_block_pair.rs:14:5
+   |
+LL |     let c = &mut data.0;
+   |             ----------- borrow of `data.0` occurs here
+LL |     capitalize(c);
+LL |     data.0 = 'e';
+   |     ^^^^^^^^^^^^ assignment to borrowed `data.0` occurs here
+...
+LL |     capitalize(c);
+   |                - borrow later used here
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/nll/loan_ends_mid_block_vec.rs b/src/test/ui/nll/loan_ends_mid_block_vec.rs
new file mode 100644
index 0000000..682e7e3e
--- /dev/null
+++ b/src/test/ui/nll/loan_ends_mid_block_vec.rs
@@ -0,0 +1,38 @@
+// compile-flags:-Zborrowck=compare
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+
+fn main() {
+}
+
+fn nll_fail() {
+    let mut data = vec!['a', 'b', 'c'];
+    let slice = &mut data;
+    capitalize(slice);
+    data.push('d');
+    //~^ ERROR (Ast) [E0499]
+    //~| ERROR (Mir) [E0499]
+    data.push('e');
+    //~^ ERROR (Ast) [E0499]
+    //~| ERROR (Mir) [E0499]
+    data.push('f');
+    //~^ ERROR (Ast) [E0499]
+    //~| ERROR (Mir) [E0499]
+    capitalize(slice);
+}
+
+fn nll_ok() {
+    let mut data = vec!['a', 'b', 'c'];
+    let slice = &mut data;
+    capitalize(slice);
+    data.push('d');
+    //~^ ERROR (Ast) [E0499]
+    data.push('e');
+    //~^ ERROR (Ast) [E0499]
+    data.push('f');
+    //~^ ERROR (Ast) [E0499]
+}
+
+fn capitalize(_: &mut [char]) {
+}
diff --git a/src/test/ui/nll/loan_ends_mid_block_vec.stderr b/src/test/ui/nll/loan_ends_mid_block_vec.stderr
new file mode 100644
index 0000000..a3f1391
--- /dev/null
+++ b/src/test/ui/nll/loan_ends_mid_block_vec.stderr
@@ -0,0 +1,111 @@
+error[E0499]: cannot borrow `data` as mutable more than once at a time (Ast)
+  --> $DIR/loan_ends_mid_block_vec.rs:13:5
+   |
+LL |     let slice = &mut data;
+   |                      ---- first mutable borrow occurs here
+LL |     capitalize(slice);
+LL |     data.push('d');
+   |     ^^^^ second mutable borrow occurs here
+...
+LL | }
+   | - first borrow ends here
+
+error[E0499]: cannot borrow `data` as mutable more than once at a time (Ast)
+  --> $DIR/loan_ends_mid_block_vec.rs:16:5
+   |
+LL |     let slice = &mut data;
+   |                      ---- first mutable borrow occurs here
+...
+LL |     data.push('e');
+   |     ^^^^ second mutable borrow occurs here
+...
+LL | }
+   | - first borrow ends here
+
+error[E0499]: cannot borrow `data` as mutable more than once at a time (Ast)
+  --> $DIR/loan_ends_mid_block_vec.rs:19:5
+   |
+LL |     let slice = &mut data;
+   |                      ---- first mutable borrow occurs here
+...
+LL |     data.push('f');
+   |     ^^^^ second mutable borrow occurs here
+...
+LL | }
+   | - first borrow ends here
+
+error[E0499]: cannot borrow `data` as mutable more than once at a time (Ast)
+  --> $DIR/loan_ends_mid_block_vec.rs:29:5
+   |
+LL |     let slice = &mut data;
+   |                      ---- first mutable borrow occurs here
+LL |     capitalize(slice);
+LL |     data.push('d');
+   |     ^^^^ second mutable borrow occurs here
+...
+LL | }
+   | - first borrow ends here
+
+error[E0499]: cannot borrow `data` as mutable more than once at a time (Ast)
+  --> $DIR/loan_ends_mid_block_vec.rs:31:5
+   |
+LL |     let slice = &mut data;
+   |                      ---- first mutable borrow occurs here
+...
+LL |     data.push('e');
+   |     ^^^^ second mutable borrow occurs here
+...
+LL | }
+   | - first borrow ends here
+
+error[E0499]: cannot borrow `data` as mutable more than once at a time (Ast)
+  --> $DIR/loan_ends_mid_block_vec.rs:33:5
+   |
+LL |     let slice = &mut data;
+   |                      ---- first mutable borrow occurs here
+...
+LL |     data.push('f');
+   |     ^^^^ second mutable borrow occurs here
+LL |
+LL | }
+   | - first borrow ends here
+
+error[E0499]: cannot borrow `data` as mutable more than once at a time (Mir)
+  --> $DIR/loan_ends_mid_block_vec.rs:13:5
+   |
+LL |     let slice = &mut data;
+   |                 --------- first mutable borrow occurs here
+LL |     capitalize(slice);
+LL |     data.push('d');
+   |     ^^^^ second mutable borrow occurs here
+...
+LL |     capitalize(slice);
+   |                ----- first borrow later used here
+
+error[E0499]: cannot borrow `data` as mutable more than once at a time (Mir)
+  --> $DIR/loan_ends_mid_block_vec.rs:16:5
+   |
+LL |     let slice = &mut data;
+   |                 --------- first mutable borrow occurs here
+...
+LL |     data.push('e');
+   |     ^^^^ second mutable borrow occurs here
+...
+LL |     capitalize(slice);
+   |                ----- first borrow later used here
+
+error[E0499]: cannot borrow `data` as mutable more than once at a time (Mir)
+  --> $DIR/loan_ends_mid_block_vec.rs:19:5
+   |
+LL |     let slice = &mut data;
+   |                 --------- first mutable borrow occurs here
+...
+LL |     data.push('f');
+   |     ^^^^ second mutable borrow occurs here
+...
+LL |     capitalize(slice);
+   |                ----- first borrow later used here
+
+error: aborting due to 9 previous errors
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/nll/match-cfg-fake-edges.rs b/src/test/ui/nll/match-cfg-fake-edges.rs
new file mode 100644
index 0000000..a3add88
--- /dev/null
+++ b/src/test/ui/nll/match-cfg-fake-edges.rs
@@ -0,0 +1,58 @@
+// Test that we have enough false edges to avoid exposing the exact matching
+// algorithm in borrow checking.
+
+#![feature(nll, bind_by_move_pattern_guards)]
+
+fn guard_always_precedes_arm(y: i32) {
+    let mut x;
+    // x should always be initialized, as the only way to reach the arm is
+    // through the guard.
+    match y {
+        0 | 2 if { x = 2; true } => x,
+        _ => 2,
+    };
+}
+
+fn guard_may_be_skipped(y: i32) {
+    let x;
+    // Even though x *is* always initialized, we don't want to have borrowck
+    // results be based on whether patterns are exhaustive.
+    match y {
+        _ if { x = 2; true } => 1,
+        _ if {
+            x; //~ ERROR use of possibly uninitialized variable: `x`
+            false
+        } => 2,
+        _ => 3,
+    };
+}
+
+fn guard_may_be_taken(y: bool) {
+    let x = String::new();
+    // Even though x *is* never moved before the use, we don't want to have
+    // borrowck results be based on whether patterns are disjoint.
+    match y {
+        false if { drop(x); true } => 1,
+        true => {
+            x; //~ ERROR use of moved value: `x`
+            2
+        }
+        false => 3,
+    };
+}
+
+fn all_previous_tests_may_be_done(y: &mut (bool, bool)) {
+    let r = &mut y.1;
+    // We don't actually test y.1 to select the second arm, but we don't want
+    // borrowck results to be based on the order we match patterns.
+    match y {
+        (false, true) => 1, //~ ERROR cannot use `y.1` because it was mutably borrowed
+        (true, _) => {
+            r;
+            2
+        }
+        (false, _) => 3,
+    };
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/match-cfg-fake-edges.stderr b/src/test/ui/nll/match-cfg-fake-edges.stderr
new file mode 100644
index 0000000..72c6a6c
--- /dev/null
+++ b/src/test/ui/nll/match-cfg-fake-edges.stderr
@@ -0,0 +1,34 @@
+error[E0381]: use of possibly uninitialized variable: `x`
+  --> $DIR/match-cfg-fake-edges.rs:23:13
+   |
+LL |             x;
+   |             ^ use of possibly uninitialized `x`
+
+error[E0382]: use of moved value: `x`
+  --> $DIR/match-cfg-fake-edges.rs:37:13
+   |
+LL |     let x = String::new();
+   |         - move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
+...
+LL |         false if { drop(x); true } => 1,
+   |                         - value moved here
+LL |         true => {
+LL |             x;
+   |             ^ value used here after move
+
+error[E0503]: cannot use `y.1` because it was mutably borrowed
+  --> $DIR/match-cfg-fake-edges.rs:49:17
+   |
+LL |     let r = &mut y.1;
+   |             -------- borrow of `y.1` occurs here
+...
+LL |         (false, true) => 1,
+   |                 ^^^^ use of borrowed `y.1`
+LL |         (true, _) => {
+LL |             r;
+   |             - borrow later used here
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0381, E0382, E0503.
+For more information about an error, try `rustc --explain E0381`.
diff --git a/src/test/ui/nll/match-guards-always-borrow.ast.nll.stderr b/src/test/ui/nll/match-guards-always-borrow.ast.nll.stderr
new file mode 100644
index 0000000..82a30db
--- /dev/null
+++ b/src/test/ui/nll/match-guards-always-borrow.ast.nll.stderr
@@ -0,0 +1,22 @@
+warning[E0507]: cannot move out of borrowed content
+  --> $DIR/match-guards-always-borrow.rs:13:13
+   |
+LL |             (|| { let bar = foo; bar.take() })();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+   |
+   = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
+   = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+
+error: compilation successful
+  --> $DIR/match-guards-always-borrow.rs:47:1
+   |
+LL | / fn main() {
+LL | |     should_reject_destructive_mutate_in_guard();
+LL | |     allow_mutate_in_arm_body();
+LL | |     allow_move_into_arm_body();
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/nll/match-guards-always-borrow.ast.stderr b/src/test/ui/nll/match-guards-always-borrow.ast.stderr
new file mode 100644
index 0000000..0c08f20
--- /dev/null
+++ b/src/test/ui/nll/match-guards-always-borrow.ast.stderr
@@ -0,0 +1,12 @@
+error: compilation successful
+  --> $DIR/match-guards-always-borrow.rs:47:1
+   |
+LL | / fn main() {
+LL | |     should_reject_destructive_mutate_in_guard();
+LL | |     allow_mutate_in_arm_body();
+LL | |     allow_move_into_arm_body();
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/match-guards-always-borrow.mir.stderr b/src/test/ui/nll/match-guards-always-borrow.mir.stderr
new file mode 100644
index 0000000..3e90c5a
--- /dev/null
+++ b/src/test/ui/nll/match-guards-always-borrow.mir.stderr
@@ -0,0 +1,9 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/match-guards-always-borrow.rs:13:13
+   |
+LL |             (|| { let bar = foo; bar.take() })();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/nll/match-guards-always-borrow.rs b/src/test/ui/nll/match-guards-always-borrow.rs
new file mode 100644
index 0000000..ec4eed6
--- /dev/null
+++ b/src/test/ui/nll/match-guards-always-borrow.rs
@@ -0,0 +1,51 @@
+//revisions: ast mir
+//[mir] compile-flags: -Z borrowck=mir
+
+#![feature(rustc_attrs)]
+
+// Here is arielb1's basic example from rust-lang/rust#27282
+// that AST borrowck is flummoxed by:
+
+fn should_reject_destructive_mutate_in_guard() {
+    match Some(&4) {
+        None => {},
+        ref mut foo if {
+            (|| { let bar = foo; bar.take() })();
+            //[mir]~^ ERROR cannot move out of borrowed content [E0507]
+            false } => { },
+        Some(s) => std::process::exit(*s),
+    }
+}
+
+// Here below is a case that needs to keep working: we only use the
+// binding via immutable-borrow in the guard, and we mutate in the arm
+// body.
+fn allow_mutate_in_arm_body() {
+    match Some(&4) {
+        None => {},
+        ref mut foo if foo.is_some() && false => { foo.take(); () }
+        Some(s) => std::process::exit(*s),
+    }
+}
+
+// Here below is a case that needs to keep working: we only use the
+// binding via immutable-borrow in the guard, and we move into the arm
+// body.
+fn allow_move_into_arm_body() {
+    match Some(&4) {
+        None => {},
+        mut foo if foo.is_some() && false => { foo.take(); () }
+        Some(s) => std::process::exit(*s),
+    }
+}
+
+// Since this is a compile-fail test that is explicitly encoding the
+// different behavior of AST- vs MIR-borrowck where AST-borrowck does
+// not error, we need to use rustc_error to placate the test harness
+// that wants *some* error to occur.
+#[rustc_error]
+fn main() { //[ast]~ ERROR compilation successful
+    should_reject_destructive_mutate_in_guard();
+    allow_mutate_in_arm_body();
+    allow_move_into_arm_body();
+}
diff --git a/src/test/ui/nll/match-guards-partially-borrow.rs b/src/test/ui/nll/match-guards-partially-borrow.rs
new file mode 100644
index 0000000..6e15871
--- /dev/null
+++ b/src/test/ui/nll/match-guards-partially-borrow.rs
@@ -0,0 +1,173 @@
+// Test that a (partially) mutably borrowed place can be matched on, so long as
+// we don't have to read any values that are mutably borrowed to determine
+// which arm to take.
+//
+// Test that we don't allow mutating the value being matched on in a way that
+// changes which patterns it matches, until we have chosen an arm.
+
+
+#![feature(bind_by_move_pattern_guards)]
+#![feature(nll)]
+
+fn ok_mutation_in_guard(mut q: i32) {
+    match q {
+        // OK, mutation doesn't change which patterns g matches
+        _ if { q = 1; false } => (),
+        _ => (),
+    }
+}
+
+fn ok_mutation_in_guard2(mut u: bool) {
+    // OK value of u is unused before modification
+    match u {
+        _ => (),
+        _ if {
+            u = true;
+            false
+        } => (),
+        x => (),
+    }
+}
+
+fn ok_mutation_in_guard4(mut w: (&mut bool,)) {
+    // OK value of u is unused before modification
+    match w {
+        _ => (),
+        _ if {
+            *w.0 = true;
+            false
+        } => (),
+        x => (),
+    }
+}
+
+fn ok_indirect_mutation_in_guard(mut p: &bool) {
+    match *p {
+        // OK, mutation doesn't change which patterns s matches
+        _ if {
+            p = &true;
+            false
+        } => (),
+        _ => (),
+    }
+}
+
+fn mutation_invalidates_pattern_in_guard(mut q: bool) {
+    match q {
+        // q doesn't match the pattern with the guard by the end of the guard.
+        false if {
+            q = true; //~ ERROR
+            true
+        } => (),
+        _ => (),
+    }
+}
+
+fn mutation_invalidates_previous_pattern_in_guard(mut r: bool) {
+    match r {
+        // r matches a previous pattern by the end of the guard.
+        true => (),
+        _ if {
+            r = true; //~ ERROR
+            true
+        } => (),
+        _ => (),
+    }
+}
+
+fn match_on_borrowed_early_end(mut s: bool) {
+    let h = &mut s;
+    // OK value of s is unused before modification.
+    match s {
+        _ if {
+            *h = !*h;
+            false
+        } => (),
+        true => (),
+        false => (),
+    }
+}
+
+fn bad_mutation_in_guard(mut t: bool) {
+    match t {
+        true => (),
+        false if {
+            t = true; //~ ERROR
+            false
+        } => (),
+        false => (),
+    }
+}
+
+fn bad_mutation_in_guard2(mut x: Option<Option<&i32>>) {
+    // Check that nested patterns are checked.
+    match x {
+        None => (),
+        Some(None) => (),
+        _ if {
+            match x {
+                Some(ref mut r) => *r = None, //~ ERROR
+                _ => return,
+            };
+            false
+        } => (),
+        Some(Some(r)) => println!("{}", r),
+    }
+}
+
+fn bad_mutation_in_guard3(mut t: bool) {
+    match t {
+        s if {
+            t = !t; //~ ERROR
+            false
+        } => (), // What value should `s` have in the arm?
+        _ => (),
+    }
+}
+
+fn bad_indirect_mutation_in_guard(mut y: &bool) {
+    match *y {
+        true => (),
+        false if {
+            y = &true; //~ ERROR
+            false
+        } => (),
+        false => (),
+    }
+}
+
+fn bad_indirect_mutation_in_guard2(mut z: &bool) {
+    match z {
+        &true => (),
+        &false if {
+            z = &true; //~ ERROR
+            false
+        } => (),
+        &false => (),
+    }
+}
+
+fn bad_indirect_mutation_in_guard3(mut a: &bool) {
+    // Same as bad_indirect_mutation_in_guard2, but using match ergonomics
+    match a {
+        true => (),
+        false if {
+            a = &true; //~ ERROR
+            false
+        } => (),
+        false => (),
+    }
+}
+
+fn bad_indirect_mutation_in_guard4(mut b: &bool) {
+    match b {
+        &_ => (),
+        &_ if {
+            b = &true; //~ ERROR
+            false
+        } => (),
+        &b => (),
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/match-guards-partially-borrow.stderr b/src/test/ui/nll/match-guards-partially-borrow.stderr
new file mode 100644
index 0000000..a646b7d
--- /dev/null
+++ b/src/test/ui/nll/match-guards-partially-borrow.stderr
@@ -0,0 +1,87 @@
+error[E0510]: cannot assign `q` in match guard
+  --> $DIR/match-guards-partially-borrow.rs:59:13
+   |
+LL |     match q {
+   |           - value is immutable in match guard
+...
+LL |             q = true;
+   |             ^^^^^^^^ cannot assign
+
+error[E0510]: cannot assign `r` in match guard
+  --> $DIR/match-guards-partially-borrow.rs:71:13
+   |
+LL |     match r {
+   |           - value is immutable in match guard
+...
+LL |             r = true;
+   |             ^^^^^^^^ cannot assign
+
+error[E0510]: cannot assign `t` in match guard
+  --> $DIR/match-guards-partially-borrow.rs:95:13
+   |
+LL |     match t {
+   |           - value is immutable in match guard
+...
+LL |             t = true;
+   |             ^^^^^^^^ cannot assign
+
+error[E0510]: cannot mutably borrow `x.0` in match guard
+  --> $DIR/match-guards-partially-borrow.rs:109:22
+   |
+LL |     match x {
+   |           - value is immutable in match guard
+...
+LL |                 Some(ref mut r) => *r = None,
+   |                      ^^^^^^^^^ cannot mutably borrow
+
+error[E0506]: cannot assign to `t` because it is borrowed
+  --> $DIR/match-guards-partially-borrow.rs:121:13
+   |
+LL |         s if {
+   |         - borrow of `t` occurs here
+LL |             t = !t;
+   |             ^^^^^^ assignment to borrowed `t` occurs here
+LL |             false
+LL |         } => (), // What value should `s` have in the arm?
+   |         - borrow later used here
+
+error[E0510]: cannot assign `y` in match guard
+  --> $DIR/match-guards-partially-borrow.rs:132:13
+   |
+LL |     match *y {
+   |           -- value is immutable in match guard
+...
+LL |             y = &true;
+   |             ^^^^^^^^^ cannot assign
+
+error[E0510]: cannot assign `z` in match guard
+  --> $DIR/match-guards-partially-borrow.rs:143:13
+   |
+LL |     match z {
+   |           - value is immutable in match guard
+...
+LL |             z = &true;
+   |             ^^^^^^^^^ cannot assign
+
+error[E0510]: cannot assign `a` in match guard
+  --> $DIR/match-guards-partially-borrow.rs:155:13
+   |
+LL |     match a {
+   |           - value is immutable in match guard
+...
+LL |             a = &true;
+   |             ^^^^^^^^^ cannot assign
+
+error[E0510]: cannot assign `b` in match guard
+  --> $DIR/match-guards-partially-borrow.rs:166:13
+   |
+LL |     match b {
+   |           - value is immutable in match guard
+...
+LL |             b = &true;
+   |             ^^^^^^^^^ cannot assign
+
+error: aborting due to 9 previous errors
+
+Some errors occurred: E0506, E0510.
+For more information about an error, try `rustc --explain E0506`.
diff --git a/src/test/ui/nll/match-on-borrowed.rs b/src/test/ui/nll/match-on-borrowed.rs
new file mode 100644
index 0000000..edce2b1
--- /dev/null
+++ b/src/test/ui/nll/match-on-borrowed.rs
@@ -0,0 +1,95 @@
+// Test that a (partially) mutably borrowed place can be matched on, so long as
+// we don't have to read any values that are mutably borrowed to determine
+// which arm to take.
+//
+// Test that we don't allow mutating the value being matched on in a way that
+// changes which patterns it matches, until we have chosen an arm.
+
+#![feature(nll)]
+
+struct A(i32, i32);
+
+fn struct_example(mut a: A) {
+    let x = &mut a.0;
+    match a { // OK, no access of borrowed data
+        _ if false => (),
+        A(_, r) => (),
+    }
+    x;
+}
+
+fn indirect_struct_example(mut b: &mut A) {
+    let x = &mut b.0;
+    match *b { // OK, no access of borrowed data
+        _ if false => (),
+        A(_, r) => (),
+    }
+    x;
+}
+
+fn underscore_example(mut c: i32) {
+    let r = &mut c;
+    match c { // OK, no access of borrowed data (or any data at all)
+        _ if false => (),
+        _ => (),
+    }
+    r;
+}
+
+enum E {
+    V(i32, i32),
+    W,
+}
+
+fn enum_example(mut e: E) {
+    let x = match e {
+        E::V(ref mut x, _) => x,
+        E::W => panic!(),
+    };
+    match e { // Don't know that E uses a tag for its discriminant
+        _ if false => (),
+        E::V(_, r) => (), //~ ERROR
+        E::W => (),
+    }
+    x;
+}
+
+fn indirect_enum_example(mut f: &mut E) {
+    let x = match *f {
+        E::V(ref mut x, _) => x,
+        E::W => panic!(),
+    };
+    match f { // Don't know that E uses a tag for its discriminant
+        _ if false => (),
+        E::V(_, r) => (), //~ ERROR
+        E::W => (),
+    }
+    x;
+}
+
+fn match_on_muatbly_borrowed_ref(mut p: &bool) {
+    let r = &mut p;
+    match *p { // OK, no access at all
+        _ if false => (),
+        _ => (),
+    }
+    r;
+}
+
+fn match_on_borrowed(mut t: bool) {
+    let x = &mut t;
+    match t {
+        true => (), //~ ERROR
+        false => (),
+    }
+    x;
+}
+
+enum Never {}
+
+fn never_init() {
+    let n: Never;
+    match n {} //~ ERROR
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/match-on-borrowed.stderr b/src/test/ui/nll/match-on-borrowed.stderr
new file mode 100644
index 0000000..e8db062
--- /dev/null
+++ b/src/test/ui/nll/match-on-borrowed.stderr
@@ -0,0 +1,46 @@
+error[E0503]: cannot use `e` because it was mutably borrowed
+  --> $DIR/match-on-borrowed.rs:51:9
+   |
+LL |         E::V(ref mut x, _) => x,
+   |              --------- borrow of `e.0` occurs here
+...
+LL |         E::V(_, r) => (),
+   |         ^^^^^^^^^^ use of borrowed `e.0`
+...
+LL |     x;
+   |     - borrow later used here
+
+error[E0503]: cannot use `*f` because it was mutably borrowed
+  --> $DIR/match-on-borrowed.rs:64:9
+   |
+LL |         E::V(ref mut x, _) => x,
+   |              --------- borrow of `f.0` occurs here
+...
+LL |         E::V(_, r) => (),
+   |         ^^^^^^^^^^ use of borrowed `f.0`
+...
+LL |     x;
+   |     - borrow later used here
+
+error[E0503]: cannot use `t` because it was mutably borrowed
+  --> $DIR/match-on-borrowed.rs:82:9
+   |
+LL |     let x = &mut t;
+   |             ------ borrow of `t` occurs here
+LL |     match t {
+LL |         true => (),
+   |         ^^^^ use of borrowed `t`
+...
+LL |     x;
+   |     - borrow later used here
+
+error[E0381]: use of possibly uninitialized variable: `n`
+  --> $DIR/match-on-borrowed.rs:92:11
+   |
+LL |     match n {}
+   |           ^ use of possibly uninitialized `n`
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0381, E0503.
+For more information about an error, try `rustc --explain E0381`.
diff --git a/src/test/ui/nll/maybe-initialized-drop-implicit-fragment-drop.rs b/src/test/ui/nll/maybe-initialized-drop-implicit-fragment-drop.rs
new file mode 100644
index 0000000..5b60982
--- /dev/null
+++ b/src/test/ui/nll/maybe-initialized-drop-implicit-fragment-drop.rs
@@ -0,0 +1,22 @@
+#![allow(warnings)]
+#![feature(nll)]
+
+struct Wrap<'p> { p: &'p mut i32 }
+
+impl<'p> Drop for Wrap<'p> {
+    fn drop(&mut self) {
+        *self.p += 1;
+    }
+}
+
+struct Foo<'p> { a: String, b: Wrap<'p> }
+
+fn main() {
+    let mut x = 0;
+    let wrap = Wrap { p: &mut x };
+    let s = String::from("str");
+    let foo = Foo { a: s, b: wrap };
+    std::mem::drop(foo.b);
+    x = 1; //~ ERROR cannot assign to `x` because it is borrowed [E0506]
+    // FIXME ^ Should not error in the future with implicit dtors, only manually implemented ones
+}
diff --git a/src/test/ui/nll/maybe-initialized-drop-implicit-fragment-drop.stderr b/src/test/ui/nll/maybe-initialized-drop-implicit-fragment-drop.stderr
new file mode 100644
index 0000000..e7755bd
--- /dev/null
+++ b/src/test/ui/nll/maybe-initialized-drop-implicit-fragment-drop.stderr
@@ -0,0 +1,15 @@
+error[E0506]: cannot assign to `x` because it is borrowed
+  --> $DIR/maybe-initialized-drop-implicit-fragment-drop.rs:20:5
+   |
+LL |     let wrap = Wrap { p: &mut x };
+   |                          ------ borrow of `x` occurs here
+...
+LL |     x = 1;
+   |     ^^^^^ assignment to borrowed `x` occurs here
+LL |     // FIXME ^ Should not error in the future with implicit dtors, only manually implemented ones
+LL | }
+   | - borrow might be used here, when `foo` is dropped and runs the destructor for type `Foo<'_>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/nll/maybe-initialized-drop-uninitialized.rs b/src/test/ui/nll/maybe-initialized-drop-uninitialized.rs
new file mode 100644
index 0000000..3415c3e
--- /dev/null
+++ b/src/test/ui/nll/maybe-initialized-drop-uninitialized.rs
@@ -0,0 +1,19 @@
+// compile-flags: -Zborrowck=mir
+// compile-pass
+
+#![allow(warnings)]
+
+struct Wrap<'p> { p: &'p mut i32 }
+
+impl<'p> Drop for Wrap<'p> {
+    fn drop(&mut self) {
+        *self.p += 1;
+    }
+}
+
+fn main() {
+    let mut x = 0;
+    let wrap = Wrap { p: &mut x };
+    std::mem::drop(wrap);
+    x = 1; // OK, drop is inert
+}
diff --git a/src/test/ui/nll/maybe-initialized-drop-with-fragment.rs b/src/test/ui/nll/maybe-initialized-drop-with-fragment.rs
new file mode 100644
index 0000000..d6cea55
--- /dev/null
+++ b/src/test/ui/nll/maybe-initialized-drop-with-fragment.rs
@@ -0,0 +1,22 @@
+//compile-flags: -Zborrowck=mir
+
+#![allow(warnings)]
+
+struct Wrap<'p> { p: &'p mut i32 }
+
+impl<'p> Drop for Wrap<'p> {
+    fn drop(&mut self) {
+        *self.p += 1;
+    }
+}
+
+struct Foo<'p> { a: String, b: Wrap<'p> }
+
+fn main() {
+    let mut x = 0;
+    let wrap = Wrap { p: &mut x };
+    let s = String::from("str");
+    let foo = Foo { a: s, b: wrap };
+    std::mem::drop(foo.a);
+    x = 1; //~ ERROR cannot assign to `x` because it is borrowed [E0506]
+}
diff --git a/src/test/ui/nll/maybe-initialized-drop-with-fragment.stderr b/src/test/ui/nll/maybe-initialized-drop-with-fragment.stderr
new file mode 100644
index 0000000..e4efd98
--- /dev/null
+++ b/src/test/ui/nll/maybe-initialized-drop-with-fragment.stderr
@@ -0,0 +1,14 @@
+error[E0506]: cannot assign to `x` because it is borrowed
+  --> $DIR/maybe-initialized-drop-with-fragment.rs:21:5
+   |
+LL |     let wrap = Wrap { p: &mut x };
+   |                          ------ borrow of `x` occurs here
+...
+LL |     x = 1;
+   |     ^^^^^ assignment to borrowed `x` occurs here
+LL | }
+   | - borrow might be used here, when `foo` is dropped and runs the destructor for type `Foo<'_>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/nll/maybe-initialized-drop-with-uninitialized-fragments.rs b/src/test/ui/nll/maybe-initialized-drop-with-uninitialized-fragments.rs
new file mode 100644
index 0000000..d2d1b98
--- /dev/null
+++ b/src/test/ui/nll/maybe-initialized-drop-with-uninitialized-fragments.rs
@@ -0,0 +1,24 @@
+//compile-flags: -Zborrowck=mir
+
+#![allow(warnings)]
+
+struct Wrap<'p> { p: &'p mut i32 }
+
+impl<'p> Drop for Wrap<'p> {
+    fn drop(&mut self) {
+        *self.p += 1;
+    }
+}
+
+struct Foo<'p> { a: String, b: Wrap<'p> }
+
+fn main() {
+    let mut x = 0;
+    let wrap = Wrap { p: &mut x };
+    let s = String::from("str");
+    let foo = Foo { a: s, b: wrap };
+    std::mem::drop(foo.a);
+    std::mem::drop(foo.b);
+    x = 1; //~ ERROR cannot assign to `x` because it is borrowed [E0506]
+    // FIXME ^ This currently errors and it should not.
+}
diff --git a/src/test/ui/nll/maybe-initialized-drop-with-uninitialized-fragments.stderr b/src/test/ui/nll/maybe-initialized-drop-with-uninitialized-fragments.stderr
new file mode 100644
index 0000000..0e2be68
--- /dev/null
+++ b/src/test/ui/nll/maybe-initialized-drop-with-uninitialized-fragments.stderr
@@ -0,0 +1,15 @@
+error[E0506]: cannot assign to `x` because it is borrowed
+  --> $DIR/maybe-initialized-drop-with-uninitialized-fragments.rs:22:5
+   |
+LL |     let wrap = Wrap { p: &mut x };
+   |                          ------ borrow of `x` occurs here
+...
+LL |     x = 1;
+   |     ^^^^^ assignment to borrowed `x` occurs here
+LL |     // FIXME ^ This currently errors and it should not.
+LL | }
+   | - borrow might be used here, when `foo` is dropped and runs the destructor for type `Foo<'_>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/nll/maybe-initialized-drop.rs b/src/test/ui/nll/maybe-initialized-drop.rs
new file mode 100644
index 0000000..cd12e93
--- /dev/null
+++ b/src/test/ui/nll/maybe-initialized-drop.rs
@@ -0,0 +1,17 @@
+//compile-flags: -Zborrowck=mir
+
+#![allow(warnings)]
+
+struct Wrap<'p> { p: &'p mut i32 }
+
+impl<'p> Drop for Wrap<'p> {
+    fn drop(&mut self) {
+        *self.p += 1;
+    }
+}
+
+fn main() {
+    let mut x = 0;
+    let wrap = Wrap { p: &mut x };
+    x = 1; //~ ERROR cannot assign to `x` because it is borrowed [E0506]
+}
diff --git a/src/test/ui/nll/maybe-initialized-drop.stderr b/src/test/ui/nll/maybe-initialized-drop.stderr
new file mode 100644
index 0000000..10b9a6d
--- /dev/null
+++ b/src/test/ui/nll/maybe-initialized-drop.stderr
@@ -0,0 +1,13 @@
+error[E0506]: cannot assign to `x` because it is borrowed
+  --> $DIR/maybe-initialized-drop.rs:16:5
+   |
+LL |     let wrap = Wrap { p: &mut x };
+   |                          ------ borrow of `x` occurs here
+LL |     x = 1;
+   |     ^^^^^ assignment to borrowed `x` occurs here
+LL | }
+   | - borrow might be used here, when `wrap` is dropped and runs the `Drop` code for type `Wrap`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/nll/mir_check_cast_closure.rs b/src/test/ui/nll/mir_check_cast_closure.rs
new file mode 100644
index 0000000..0619ff3
--- /dev/null
+++ b/src/test/ui/nll/mir_check_cast_closure.rs
@@ -0,0 +1,11 @@
+// compile-flags: -Z borrowck=mir
+
+#![allow(dead_code)]
+
+fn bar<'a, 'b>() -> fn(&'a u32, &'b u32) -> &'a u32 {
+    let g: fn(_, _) -> _ = |_x, y| y;
+    g
+    //~^ ERROR lifetime may not live long enough
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/mir_check_cast_closure.stderr b/src/test/ui/nll/mir_check_cast_closure.stderr
new file mode 100644
index 0000000..e14cb07
--- /dev/null
+++ b/src/test/ui/nll/mir_check_cast_closure.stderr
@@ -0,0 +1,13 @@
+error: lifetime may not live long enough
+  --> $DIR/mir_check_cast_closure.rs:7:5
+   |
+LL | fn bar<'a, 'b>() -> fn(&'a u32, &'b u32) -> &'a u32 {
+   |        --  -- lifetime `'b` defined here
+   |        |
+   |        lifetime `'a` defined here
+LL |     let g: fn(_, _) -> _ = |_x, y| y;
+LL |     g
+   |     ^ returning this value requires that `'b` must outlive `'a`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/mir_check_cast_reify.rs b/src/test/ui/nll/mir_check_cast_reify.rs
new file mode 100644
index 0000000..be12e31
--- /dev/null
+++ b/src/test/ui/nll/mir_check_cast_reify.rs
@@ -0,0 +1,41 @@
+// compile-flags: -Zborrowck=mir
+
+#![allow(dead_code)]
+
+// Test that we relate the type of the fn type to the type of the fn
+// ptr when doing a `ReifyFnPointer` cast.
+//
+// This test is a bit tortured, let me explain:
+//
+
+// The `where 'a: 'a` clause here ensures that `'a` is early bound,
+// which is needed below to ensure that this test hits the path we are
+// concerned with.
+fn foo<'a>(x: &'a u32) -> &'a u32
+where
+    'a: 'a,
+{
+    panic!()
+}
+
+fn bar<'a>(x: &'a u32) -> &'static u32 {
+    // Here, the type of `foo` is `typeof(foo::<'x>)` for some fresh variable `'x`.
+    // During NLL region analysis, this will get renumbered to `typeof(foo::<'?0>)`
+    // where `'?0` is a new region variable.
+    //
+    // (Note that if `'a` on `foo` were late-bound, the type would be
+    // `typeof(foo)`, which would interact differently with because
+    // the renumbering later.)
+    //
+    // This type is then coerced to a fn type `fn(&'?1 u32) -> &'?2
+    // u32`. Here, the `'?1` and `'?2` will have been created during
+    // the NLL region renumbering.
+    //
+    // The MIR type checker must therefore relate `'?0` to `'?1` and `'?2`
+    // as part of checking the `ReifyFnPointer`.
+    let f: fn(_) -> _ = foo;
+    f(x)
+    //~^ ERROR lifetime may not live long enough
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/mir_check_cast_reify.stderr b/src/test/ui/nll/mir_check_cast_reify.stderr
new file mode 100644
index 0000000..4e8eec3
--- /dev/null
+++ b/src/test/ui/nll/mir_check_cast_reify.stderr
@@ -0,0 +1,11 @@
+error: lifetime may not live long enough
+  --> $DIR/mir_check_cast_reify.rs:37:5
+   |
+LL | fn bar<'a>(x: &'a u32) -> &'static u32 {
+   |        -- lifetime `'a` defined here
+...
+LL |     f(x)
+   |     ^^^^ returning this value requires that `'a` must outlive `'static`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/mir_check_cast_unsafe_fn.rs b/src/test/ui/nll/mir_check_cast_unsafe_fn.rs
new file mode 100644
index 0000000..9df9c05
--- /dev/null
+++ b/src/test/ui/nll/mir_check_cast_unsafe_fn.rs
@@ -0,0 +1,13 @@
+// compile-flags: -Zborrowck=mir
+
+#![allow(dead_code)]
+
+fn bar<'a>(input: &'a u32, f: fn(&'a u32) -> &'a u32) -> &'static u32 {
+    // Here the NLL checker must relate the types in `f` to the types
+    // in `g`. These are related via the `UnsafeFnPointer` cast.
+    let g: unsafe fn(_) -> _ = f;
+    unsafe { g(input) }
+    //~^ ERROR lifetime may not live long enough
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/mir_check_cast_unsafe_fn.stderr b/src/test/ui/nll/mir_check_cast_unsafe_fn.stderr
new file mode 100644
index 0000000..5295985
--- /dev/null
+++ b/src/test/ui/nll/mir_check_cast_unsafe_fn.stderr
@@ -0,0 +1,11 @@
+error: lifetime may not live long enough
+  --> $DIR/mir_check_cast_unsafe_fn.rs:9:14
+   |
+LL | fn bar<'a>(input: &'a u32, f: fn(&'a u32) -> &'a u32) -> &'static u32 {
+   |        -- lifetime `'a` defined here
+...
+LL |     unsafe { g(input) }
+   |              ^^^^^^^^ returning this value requires that `'a` must outlive `'static`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/mir_check_cast_unsize.rs b/src/test/ui/nll/mir_check_cast_unsize.rs
new file mode 100644
index 0000000..d15c4e4
--- /dev/null
+++ b/src/test/ui/nll/mir_check_cast_unsize.rs
@@ -0,0 +1,12 @@
+// compile-flags: -Z borrowck=mir
+
+#![allow(dead_code)]
+
+use std::fmt::Debug;
+
+fn bar<'a>(x: &'a u32) -> &'static dyn Debug {
+    x
+    //~^ ERROR lifetime may not live long enough
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/mir_check_cast_unsize.stderr b/src/test/ui/nll/mir_check_cast_unsize.stderr
new file mode 100644
index 0000000..364d6c1
--- /dev/null
+++ b/src/test/ui/nll/mir_check_cast_unsize.stderr
@@ -0,0 +1,10 @@
+error: lifetime may not live long enough
+  --> $DIR/mir_check_cast_unsize.rs:8:5
+   |
+LL | fn bar<'a>(x: &'a u32) -> &'static dyn Debug {
+   |        -- lifetime `'a` defined here
+LL |     x
+   |     ^ returning this value requires that `'a` must outlive `'static`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/move-errors.rs b/src/test/ui/nll/move-errors.rs
new file mode 100644
index 0000000..a341637
--- /dev/null
+++ b/src/test/ui/nll/move-errors.rs
@@ -0,0 +1,120 @@
+#![allow(unused)]
+#![feature(nll)]
+
+struct A(String);
+struct C(D);
+
+fn suggest_remove_deref() {
+    let a = &A("".to_string());
+    let b = *a;
+    //~^ ERROR
+}
+
+fn suggest_borrow() {
+    let a = [A("".to_string())];
+    let b = a[0];
+    //~^ ERROR
+}
+
+fn suggest_borrow2() {
+    let mut a = A("".to_string());
+    let r = &&mut a;
+    let s = **r;
+    //~^ ERROR
+}
+
+fn suggest_borrow3() {
+    use std::rc::Rc;
+    let mut a = A("".to_string());
+    let r = Rc::new(a);
+    let s = *r;
+    //~^ ERROR
+}
+
+fn suggest_borrow4() {
+    let a = [A("".to_string())][0];
+    //~^ ERROR
+}
+
+fn suggest_borrow5() {
+    let a = &A("".to_string());
+    let A(s) = *a;
+    //~^ ERROR
+}
+
+fn suggest_ref() {
+    let c = C(D(String::new()));
+    let C(D(s)) = c;
+    //~^ ERROR
+}
+
+fn suggest_nothing() {
+    let a = &A("".to_string());
+    let b;
+    b = *a;
+    //~^ ERROR
+}
+
+enum B {
+    V(String),
+    U(D),
+}
+
+struct D(String);
+
+impl Drop for D {
+    fn drop(&mut self) {}
+}
+
+struct F(String, String);
+
+impl Drop for F {
+    fn drop(&mut self) {}
+}
+
+fn probably_suggest_borrow() {
+    let x = [B::V(String::new())];
+    match x[0] {
+    //~^ ERROR
+        B::U(d) => (),
+        B::V(s) => (),
+    }
+}
+
+fn have_to_suggest_ref() {
+    let x = B::V(String::new());
+    match x {
+    //~^ ERROR
+        B::V(s) => drop(s),
+        B::U(D(s)) => (),
+    };
+}
+
+fn two_separate_errors() {
+    let x = (D(String::new()), &String::new());
+    match x {
+    //~^ ERROR
+    //~^^ ERROR
+        (D(s), &t) => (),
+        _ => (),
+    }
+}
+
+fn have_to_suggest_double_ref() {
+    let x = F(String::new(), String::new());
+    match x {
+    //~^ ERROR
+        F(s, mut t) => (),
+        _ => (),
+    }
+}
+
+fn double_binding(x: &Result<String, String>) {
+    match *x {
+    //~^ ERROR
+        Ok(s) | Err(s) => (),
+    }
+}
+
+fn main() {
+}
diff --git a/src/test/ui/nll/move-errors.stderr b/src/test/ui/nll/move-errors.stderr
new file mode 100644
index 0000000..f329748
--- /dev/null
+++ b/src/test/ui/nll/move-errors.stderr
@@ -0,0 +1,187 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/move-errors.rs:9:13
+   |
+LL |     let b = *a;
+   |             ^^
+   |             |
+   |             cannot move out of borrowed content
+   |             help: consider removing the `*`: `a`
+
+error[E0508]: cannot move out of type `[A; 1]`, a non-copy array
+  --> $DIR/move-errors.rs:15:13
+   |
+LL |     let b = a[0];
+   |             ^^^^
+   |             |
+   |             cannot move out of here
+   |             help: consider borrowing here: `&a[0]`
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/move-errors.rs:22:13
+   |
+LL |     let s = **r;
+   |             ^^^
+   |             |
+   |             cannot move out of borrowed content
+   |             help: consider removing the `*`: `*r`
+
+error[E0507]: cannot move out of an `Rc`
+  --> $DIR/move-errors.rs:30:13
+   |
+LL |     let s = *r;
+   |             ^^
+   |             |
+   |             cannot move out of an `Rc`
+   |             help: consider removing the `*`: `r`
+
+error[E0508]: cannot move out of type `[A; 1]`, a non-copy array
+  --> $DIR/move-errors.rs:35:13
+   |
+LL |     let a = [A("".to_string())][0];
+   |             ^^^^^^^^^^^^^^^^^^^^^^
+   |             |
+   |             cannot move out of here
+   |             help: consider borrowing here: `&[A("".to_string())][0]`
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/move-errors.rs:41:16
+   |
+LL |     let A(s) = *a;
+   |           -    ^^
+   |           |    |
+   |           |    cannot move out of borrowed content
+   |           |    help: consider removing the `*`: `a`
+   |           data moved here
+   |
+note: move occurs because `s` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/move-errors.rs:41:11
+   |
+LL |     let A(s) = *a;
+   |           ^
+
+error[E0509]: cannot move out of type `D`, which implements the `Drop` trait
+  --> $DIR/move-errors.rs:47:19
+   |
+LL |     let C(D(s)) = c;
+   |             -     ^ cannot move out of here
+   |             |
+   |             data moved here
+   |
+note: move occurs because `s` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/move-errors.rs:47:13
+   |
+LL |     let C(D(s)) = c;
+   |             ^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/move-errors.rs:54:9
+   |
+LL |     b = *a;
+   |         ^^ cannot move out of borrowed content
+
+error[E0508]: cannot move out of type `[B; 1]`, a non-copy array
+  --> $DIR/move-errors.rs:77:11
+   |
+LL |     match x[0] {
+   |           ^^^^
+   |           |
+   |           cannot move out of here
+   |           help: consider borrowing here: `&x[0]`
+LL |
+LL |         B::U(d) => (),
+   |              - data moved here
+LL |         B::V(s) => (),
+   |              - ...and here
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/move-errors.rs:79:14
+   |
+LL |         B::U(d) => (),
+   |              ^
+LL |         B::V(s) => (),
+   |              ^
+
+error[E0509]: cannot move out of type `D`, which implements the `Drop` trait
+  --> $DIR/move-errors.rs:86:11
+   |
+LL |     match x {
+   |           ^ cannot move out of here
+...
+LL |         B::U(D(s)) => (),
+   |                - data moved here
+   |
+note: move occurs because `s` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/move-errors.rs:89:16
+   |
+LL |         B::U(D(s)) => (),
+   |                ^
+
+error[E0509]: cannot move out of type `D`, which implements the `Drop` trait
+  --> $DIR/move-errors.rs:95:11
+   |
+LL |     match x {
+   |           ^ cannot move out of here
+...
+LL |         (D(s), &t) => (),
+   |            - data moved here
+   |
+note: move occurs because `s` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/move-errors.rs:98:12
+   |
+LL |         (D(s), &t) => (),
+   |            ^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/move-errors.rs:95:11
+   |
+LL |     match x {
+   |           ^ cannot move out of borrowed content
+...
+LL |         (D(s), &t) => (),
+   |                 - data moved here
+   |
+note: move occurs because `t` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/move-errors.rs:98:17
+   |
+LL |         (D(s), &t) => (),
+   |                 ^
+
+error[E0509]: cannot move out of type `F`, which implements the `Drop` trait
+  --> $DIR/move-errors.rs:105:11
+   |
+LL |     match x {
+   |           ^ cannot move out of here
+LL |
+LL |         F(s, mut t) => (),
+   |           -  ----- ...and here
+   |           |
+   |           data moved here
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/move-errors.rs:107:11
+   |
+LL |         F(s, mut t) => (),
+   |           ^  ^^^^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/move-errors.rs:113:11
+   |
+LL |     match *x {
+   |           ^^
+   |           |
+   |           cannot move out of borrowed content
+   |           help: consider removing the `*`: `x`
+LL |
+LL |         Ok(s) | Err(s) => (),
+   |            - data moved here
+   |
+note: move occurs because `s` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/move-errors.rs:115:12
+   |
+LL |         Ok(s) | Err(s) => (),
+   |            ^
+
+error: aborting due to 14 previous errors
+
+Some errors occurred: E0507, E0508, E0509.
+For more information about an error, try `rustc --explain E0507`.
diff --git a/src/test/ui/nll/move-subpaths-moves-root.rs b/src/test/ui/nll/move-subpaths-moves-root.rs
new file mode 100644
index 0000000..72a36ef
--- /dev/null
+++ b/src/test/ui/nll/move-subpaths-moves-root.rs
@@ -0,0 +1,7 @@
+#![feature(nll)]
+
+fn main() {
+    let x = (vec![1, 2, 3], );
+    drop(x.0);
+    drop(x); //~ ERROR use of moved value
+}
diff --git a/src/test/ui/nll/move-subpaths-moves-root.stderr b/src/test/ui/nll/move-subpaths-moves-root.stderr
new file mode 100644
index 0000000..bdbc25e
--- /dev/null
+++ b/src/test/ui/nll/move-subpaths-moves-root.stderr
@@ -0,0 +1,13 @@
+error[E0382]: use of moved value: `x`
+  --> $DIR/move-subpaths-moves-root.rs:6:10
+   |
+LL |     drop(x.0);
+   |          --- value moved here
+LL |     drop(x);
+   |          ^ value used here after partial move
+   |
+   = note: move occurs because `x.0` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/nll/normalization-bounds-error.rs b/src/test/ui/nll/normalization-bounds-error.rs
new file mode 100644
index 0000000..d6610e1
--- /dev/null
+++ b/src/test/ui/nll/normalization-bounds-error.rs
@@ -0,0 +1,16 @@
+// Check that we error when a bound from the impl is not satisfied when
+// normalizing an associated type.
+
+#![feature(nll)]
+trait Visitor<'d> {
+    type Value;
+}
+
+impl<'a, 'd: 'a> Visitor<'d> for &'a () {
+    type Value = ();
+}
+
+fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {}
+//~^ ERROR
+
+fn main() {}
diff --git a/src/test/ui/nll/normalization-bounds-error.stderr b/src/test/ui/nll/normalization-bounds-error.stderr
new file mode 100644
index 0000000..cd88ceb
--- /dev/null
+++ b/src/test/ui/nll/normalization-bounds-error.stderr
@@ -0,0 +1,23 @@
+error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'d` due to conflicting requirements
+  --> $DIR/normalization-bounds-error.rs:13:1
+   |
+LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: first, the lifetime cannot outlive the lifetime 'd as defined on the function body at 13:14...
+  --> $DIR/normalization-bounds-error.rs:13:14
+   |
+LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {}
+   |              ^^
+note: ...but the lifetime must also be valid for the lifetime 'a as defined on the function body at 13:18...
+  --> $DIR/normalization-bounds-error.rs:13:18
+   |
+LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {}
+   |                  ^^
+   = note: ...so that the types are compatible:
+           expected Visitor<'d>
+              found Visitor<'_>
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0495`.
diff --git a/src/test/ui/nll/normalization-bounds.rs b/src/test/ui/nll/normalization-bounds.rs
new file mode 100644
index 0000000..ebc19d7
--- /dev/null
+++ b/src/test/ui/nll/normalization-bounds.rs
@@ -0,0 +1,16 @@
+// Check that lifetime bounds get checked the right way around with NLL enabled.
+
+//run-pass
+
+#![feature(nll)]
+trait Visitor<'d> {
+    type Value;
+}
+
+impl<'a, 'd: 'a> Visitor<'d> for &'a () {
+    type Value = ();
+}
+
+fn visit_seq<'d: 'a, 'a>() -> <&'a () as Visitor<'d>>::Value {}
+
+fn main() {}
diff --git a/src/test/ui/nll/polonius-smoke-test.rs b/src/test/ui/nll/polonius-smoke-test.rs
new file mode 100644
index 0000000..bea5e45
--- /dev/null
+++ b/src/test/ui/nll/polonius-smoke-test.rs
@@ -0,0 +1,47 @@
+// Check that Polonius borrow check works for simple cases.
+// ignore-compare-mode-nll
+// compile-flags: -Z borrowck=mir -Zpolonius
+
+pub fn return_ref_to_local() -> &'static i32 {
+    let x = 0;
+    &x //~ ERROR
+}
+
+pub fn use_while_mut() {
+    let mut x = 0;
+    let y = &mut x;
+    let z = x; //~ ERROR
+    let w = y;
+}
+
+pub fn use_while_mut_fr(x: &mut i32) -> &mut i32 {
+    let y = &mut *x;
+    let z = x; //~ ERROR
+    y
+}
+
+// Cases like this are why we have Polonius.
+pub fn position_dependent_outlives(x: &mut i32, cond: bool) -> &mut i32 {
+    let y = &mut *x;
+    if cond {
+        return y;
+    } else {
+        *x = 0;
+        return x;
+    }
+}
+
+fn foo<'a, 'b>(p: &'b &'a mut usize) -> &'b usize {
+    p
+}
+
+// Check that we create constraints for well-formedness of function arguments
+fn well_formed_function_inputs() {
+    let s = &mut 1;
+    let r = &mut *s;
+    let tmp = foo(&r);
+    s; //~ ERROR
+    tmp;
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/polonius-smoke-test.stderr b/src/test/ui/nll/polonius-smoke-test.stderr
new file mode 100644
index 0000000..fb3e9cf
--- /dev/null
+++ b/src/test/ui/nll/polonius-smoke-test.stderr
@@ -0,0 +1,41 @@
+error[E0515]: cannot return reference to local variable `x`
+  --> $DIR/polonius-smoke-test.rs:7:5
+   |
+LL |     &x
+   |     ^^ returns a reference to data owned by the current function
+
+error[E0503]: cannot use `x` because it was mutably borrowed
+  --> $DIR/polonius-smoke-test.rs:13:13
+   |
+LL |     let y = &mut x;
+   |             ------ borrow of `x` occurs here
+LL |     let z = x;
+   |             ^ use of borrowed `x`
+LL |     let w = y;
+   |             - borrow later used here
+
+error[E0505]: cannot move out of `x` because it is borrowed
+  --> $DIR/polonius-smoke-test.rs:19:13
+   |
+LL |     let y = &mut *x;
+   |             ------- borrow of `*x` occurs here
+LL |     let z = x;
+   |             ^ move out of `x` occurs here
+LL |     y
+   |     - borrow later used here
+
+error[E0505]: cannot move out of `s` because it is borrowed
+  --> $DIR/polonius-smoke-test.rs:43:5
+   |
+LL |     let r = &mut *s;
+   |             ------- borrow of `*s` occurs here
+LL |     let tmp = foo(&r);
+LL |     s;
+   |     ^ move out of `s` occurs here
+LL |     tmp;
+   |     --- borrow later used here
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0503, E0505, E0515.
+For more information about an error, try `rustc --explain E0503`.
diff --git a/src/test/ui/nll/projection-return.rs b/src/test/ui/nll/projection-return.rs
new file mode 100644
index 0000000..b2c9a087
--- /dev/null
+++ b/src/test/ui/nll/projection-return.rs
@@ -0,0 +1,19 @@
+// compile-flags:-Zborrowck=mir
+// compile-pass
+
+#![feature(rustc_attrs)]
+
+trait Foo {
+    type Bar;
+}
+
+impl Foo for () {
+    type Bar = u32;
+}
+
+fn foo() -> <() as Foo>::Bar {
+    22
+}
+
+fn main() { }
+
diff --git a/src/test/ui/nll/promotable-mutable-zst-doesnt-conflict.rs b/src/test/ui/nll/promotable-mutable-zst-doesnt-conflict.rs
new file mode 100644
index 0000000..061d0d6
--- /dev/null
+++ b/src/test/ui/nll/promotable-mutable-zst-doesnt-conflict.rs
@@ -0,0 +1,13 @@
+// Check that mutable promoted length zero arrays don't check for conflicting
+// access
+
+// run-pass
+
+#![feature(nll)]
+
+pub fn main() {
+    let mut x: Vec<&[i32; 0]> = Vec::new();
+    for i in 0..10 {
+        x.push(&[]);
+    }
+}
diff --git a/src/test/ui/nll/promoted-bounds.rs b/src/test/ui/nll/promoted-bounds.rs
new file mode 100644
index 0000000..59b21cf
--- /dev/null
+++ b/src/test/ui/nll/promoted-bounds.rs
@@ -0,0 +1,27 @@
+#![feature(nll)]
+
+fn shorten_lifetime<'a, 'b, 'min>(a: &'a i32, b: &'b i32) -> &'min i32
+where
+    'a: 'min,
+    'b: 'min,
+{
+    if *a < *b {
+        &a
+    } else {
+        &b
+    }
+}
+
+fn main() {
+    let promoted_fn_item_ref = &shorten_lifetime;
+
+    let a = &5;
+    let ptr = {
+        let l = 3;
+        let b = &l; //~ ERROR does not live long enough
+        let c = promoted_fn_item_ref(a, b);
+        c
+    };
+
+    println!("ptr = {:?}", ptr);
+}
diff --git a/src/test/ui/nll/promoted-bounds.stderr b/src/test/ui/nll/promoted-bounds.stderr
new file mode 100644
index 0000000..de185cc
--- /dev/null
+++ b/src/test/ui/nll/promoted-bounds.stderr
@@ -0,0 +1,15 @@
+error[E0597]: `l` does not live long enough
+  --> $DIR/promoted-bounds.rs:21:17
+   |
+LL |     let ptr = {
+   |         --- borrow later stored here
+LL |         let l = 3;
+LL |         let b = &l;
+   |                 ^^ borrowed value does not live long enough
+...
+LL |     };
+   |     - `l` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/promoted-closure-pair.rs b/src/test/ui/nll/promoted-closure-pair.rs
new file mode 100644
index 0000000..7b3bbad
--- /dev/null
+++ b/src/test/ui/nll/promoted-closure-pair.rs
@@ -0,0 +1,12 @@
+// Check that we handle multiple closures in the same promoted constant.
+
+#![feature(nll)]
+
+fn foo() -> &'static i32 {
+    let z = 0;
+    let p = &(|y| y, |y| y);
+    p.0(&z);
+    p.1(&z)         //~ ERROR cannot return
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/promoted-closure-pair.stderr b/src/test/ui/nll/promoted-closure-pair.stderr
new file mode 100644
index 0000000..b04d1a9
--- /dev/null
+++ b/src/test/ui/nll/promoted-closure-pair.stderr
@@ -0,0 +1,12 @@
+error[E0515]: cannot return value referencing local variable `z`
+  --> $DIR/promoted-closure-pair.rs:9:5
+   |
+LL |     p.1(&z)
+   |     ^^^^--^
+   |     |   |
+   |     |   `z` is borrowed here
+   |     returns a value referencing data owned by the current function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/src/test/ui/nll/reference-carried-through-struct-field.ast.nll.stderr b/src/test/ui/nll/reference-carried-through-struct-field.ast.nll.stderr
new file mode 100644
index 0000000..1f6eb9a
--- /dev/null
+++ b/src/test/ui/nll/reference-carried-through-struct-field.ast.nll.stderr
@@ -0,0 +1,14 @@
+error[E0503]: cannot use `x` because it was mutably borrowed
+  --> $DIR/reference-carried-through-struct-field.rs:11:5
+   |
+LL |     let wrapper = Wrap { w: &mut x };
+   |                             ------ borrow of `x` occurs here
+LL |     x += 1;
+   |     ^^^^^^ use of borrowed `x`
+LL |
+LL |     *wrapper.w += 1;
+   |     --------------- borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0503`.
diff --git a/src/test/ui/nll/reference-carried-through-struct-field.ast.stderr b/src/test/ui/nll/reference-carried-through-struct-field.ast.stderr
new file mode 100644
index 0000000..3104944
--- /dev/null
+++ b/src/test/ui/nll/reference-carried-through-struct-field.ast.stderr
@@ -0,0 +1,11 @@
+error[E0506]: cannot assign to `x` because it is borrowed
+  --> $DIR/reference-carried-through-struct-field.rs:11:5
+   |
+LL |     let wrapper = Wrap { w: &mut x };
+   |                                  - borrow of `x` occurs here
+LL |     x += 1;
+   |     ^^^^^^ assignment to borrowed `x` occurs here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/nll/reference-carried-through-struct-field.mir.stderr b/src/test/ui/nll/reference-carried-through-struct-field.mir.stderr
new file mode 100644
index 0000000..1f6eb9a
--- /dev/null
+++ b/src/test/ui/nll/reference-carried-through-struct-field.mir.stderr
@@ -0,0 +1,14 @@
+error[E0503]: cannot use `x` because it was mutably borrowed
+  --> $DIR/reference-carried-through-struct-field.rs:11:5
+   |
+LL |     let wrapper = Wrap { w: &mut x };
+   |                             ------ borrow of `x` occurs here
+LL |     x += 1;
+   |     ^^^^^^ use of borrowed `x`
+LL |
+LL |     *wrapper.w += 1;
+   |     --------------- borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0503`.
diff --git a/src/test/ui/nll/reference-carried-through-struct-field.rs b/src/test/ui/nll/reference-carried-through-struct-field.rs
new file mode 100644
index 0000000..f7903cb
--- /dev/null
+++ b/src/test/ui/nll/reference-carried-through-struct-field.rs
@@ -0,0 +1,16 @@
+//revisions: ast mir
+//[mir] compile-flags: -Z borrowck=mir
+
+#![allow(unused_assignments)]
+
+struct Wrap<'a> { w: &'a mut u32 }
+
+fn foo() {
+    let mut x = 22;
+    let wrapper = Wrap { w: &mut x };
+    x += 1; //[ast]~ ERROR cannot assign to `x` because it is borrowed [E0506]
+    //[mir]~^ ERROR cannot use `x` because it was mutably borrowed [E0503]
+    *wrapper.w += 1;
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/region-ends-after-if-condition.rs b/src/test/ui/nll/region-ends-after-if-condition.rs
new file mode 100644
index 0000000..1bf13a9
--- /dev/null
+++ b/src/test/ui/nll/region-ends-after-if-condition.rs
@@ -0,0 +1,36 @@
+// Basic test for liveness constraints: the region (`R1`) that appears
+// in the type of `p` includes the points after `&v[0]` up to (but not
+// including) the call to `use_x`. The `else` branch is not included.
+
+// compile-flags:-Zborrowck=compare
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+
+struct MyStruct {
+    field: String
+}
+
+fn foo1() {
+    let mut my_struct = MyStruct { field: format!("Hello") };
+
+    let value = &my_struct.field;
+    if value.is_empty() {
+        my_struct.field.push_str("Hello, world!");
+        //~^ ERROR (Ast) [E0502]
+    }
+}
+
+fn foo2() {
+    let mut my_struct = MyStruct { field: format!("Hello") };
+
+    let value = &my_struct.field;
+    if value.is_empty() {
+        my_struct.field.push_str("Hello, world!");
+        //~^ ERROR (Ast) [E0502]
+        //~| ERROR (Mir) [E0502]
+    }
+    drop(value);
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/region-ends-after-if-condition.stderr b/src/test/ui/nll/region-ends-after-if-condition.stderr
new file mode 100644
index 0000000..aa876a0
--- /dev/null
+++ b/src/test/ui/nll/region-ends-after-if-condition.stderr
@@ -0,0 +1,39 @@
+error[E0502]: cannot borrow `my_struct.field` as mutable because it is also borrowed as immutable (Ast)
+  --> $DIR/region-ends-after-if-condition.rs:19:9
+   |
+LL |     let value = &my_struct.field;
+   |                  --------------- immutable borrow occurs here
+LL |     if value.is_empty() {
+LL |         my_struct.field.push_str("Hello, world!");
+   |         ^^^^^^^^^^^^^^^ mutable borrow occurs here
+...
+LL | }
+   | - immutable borrow ends here
+
+error[E0502]: cannot borrow `my_struct.field` as mutable because it is also borrowed as immutable (Ast)
+  --> $DIR/region-ends-after-if-condition.rs:29:9
+   |
+LL |     let value = &my_struct.field;
+   |                  --------------- immutable borrow occurs here
+LL |     if value.is_empty() {
+LL |         my_struct.field.push_str("Hello, world!");
+   |         ^^^^^^^^^^^^^^^ mutable borrow occurs here
+...
+LL | }
+   | - immutable borrow ends here
+
+error[E0502]: cannot borrow `my_struct.field` as mutable because it is also borrowed as immutable (Mir)
+  --> $DIR/region-ends-after-if-condition.rs:29:9
+   |
+LL |     let value = &my_struct.field;
+   |                 ---------------- immutable borrow occurs here
+LL |     if value.is_empty() {
+LL |         my_struct.field.push_str("Hello, world!");
+   |         ^^^^^^^^^^^^^^^ mutable borrow occurs here
+...
+LL |     drop(value);
+   |          ----- immutable borrow later used here
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/nll/relate_tys/hr-fn-aaa-as-aba.rs b/src/test/ui/nll/relate_tys/hr-fn-aaa-as-aba.rs
new file mode 100644
index 0000000..fca69b8
--- /dev/null
+++ b/src/test/ui/nll/relate_tys/hr-fn-aaa-as-aba.rs
@@ -0,0 +1,26 @@
+// Test that the NLL `relate_tys` code correctly deduces that a
+// function returning either argument CANNOT be upcast to one
+// that returns always its first argument.
+//
+// compile-flags:-Zno-leak-check
+
+#![feature(nll)]
+
+fn make_it() -> for<'a> fn(&'a u32, &'a u32) -> &'a u32 {
+    panic!()
+}
+
+fn foo() {
+    let a: for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32 = make_it();
+    //~^ ERROR higher-ranked subtype error
+    drop(a);
+}
+
+fn bar() {
+    // The code path for patterns is mildly different, so go ahead and
+    // test that too:
+    let _: for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32 = make_it();
+    //~^ ERROR higher-ranked subtype error
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/relate_tys/hr-fn-aaa-as-aba.stderr b/src/test/ui/nll/relate_tys/hr-fn-aaa-as-aba.stderr
new file mode 100644
index 0000000..7906dbd
--- /dev/null
+++ b/src/test/ui/nll/relate_tys/hr-fn-aaa-as-aba.stderr
@@ -0,0 +1,14 @@
+error: higher-ranked subtype error
+  --> $DIR/hr-fn-aaa-as-aba.rs:14:58
+   |
+LL |     let a: for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32 = make_it();
+   |                                                          ^^^^^^^^^
+
+error: higher-ranked subtype error
+  --> $DIR/hr-fn-aaa-as-aba.rs:22:12
+   |
+LL |     let _: for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32 = make_it();
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/nll/relate_tys/hr-fn-aau-eq-abu.rs b/src/test/ui/nll/relate_tys/hr-fn-aau-eq-abu.rs
new file mode 100644
index 0000000..23caa59
--- /dev/null
+++ b/src/test/ui/nll/relate_tys/hr-fn-aau-eq-abu.rs
@@ -0,0 +1,25 @@
+// Test an interesting corner case that ought to be legal (though the
+// current code actually gets it wrong, see below): a fn that takes
+// two arguments that are references with the same lifetime is in fact
+// equivalent to a fn that takes two references with distinct
+// lifetimes. This is true because the two functions can call one
+// another -- effectively, the single lifetime `'a` is just inferred
+// to be the intersection of the two distinct lifetimes.
+//
+// compile-pass
+// compile-flags:-Zno-leak-check
+
+#![feature(nll)]
+
+use std::cell::Cell;
+
+fn make_cell_aa() -> Cell<for<'a> fn(&'a u32, &'a u32)> {
+    panic!()
+}
+
+fn aa_eq_ab() {
+    let a: Cell<for<'a, 'b> fn(&'a u32, &'b u32)> = make_cell_aa();
+    drop(a);
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/relate_tys/hr-fn-aba-as-aaa.rs b/src/test/ui/nll/relate_tys/hr-fn-aba-as-aaa.rs
new file mode 100644
index 0000000..bac9e26
--- /dev/null
+++ b/src/test/ui/nll/relate_tys/hr-fn-aba-as-aaa.rs
@@ -0,0 +1,17 @@
+// Test that the NLL `relate_tys` code correctly deduces that a
+// function returning always its first argument can be upcast to one
+// that returns either first or second argument.
+//
+// compile-pass
+// compile-flags:-Zno-leak-check
+
+#![feature(nll)]
+
+fn make_it() -> for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32 {
+    panic!()
+}
+
+fn main() {
+    let a: for<'a> fn(&'a u32, &'a u32) -> &'a u32 = make_it();
+    drop(a);
+}
diff --git a/src/test/ui/nll/relate_tys/issue-48071.rs b/src/test/ui/nll/relate_tys/issue-48071.rs
new file mode 100644
index 0000000..9b8ac16
--- /dev/null
+++ b/src/test/ui/nll/relate_tys/issue-48071.rs
@@ -0,0 +1,28 @@
+// Regression test for #48071. This test used to ICE because -- in
+// the leak-check -- it would pass since we knew that the return type
+// was `'static`, and hence `'static: 'a` was legal even for a
+// placeholder region, but in NLL land it would fail because we had
+// rewritten `'static` to a region variable.
+//
+// compile-pass
+
+#![allow(warnings)]
+#![feature(dyn_trait)]
+#![feature(nll)]
+
+trait Foo {
+    fn foo(&self) { }
+}
+
+impl Foo for () {
+}
+
+type MakeFooFn = for<'a> fn(&'a u8) -> Box<dyn Foo + 'a>;
+
+fn make_foo(x: &u8) -> Box<dyn Foo + 'static> {
+    Box::new(())
+}
+
+fn main() {
+    let x: MakeFooFn = make_foo as MakeFooFn;
+}
diff --git a/src/test/ui/nll/relate_tys/universe-violation.rs b/src/test/ui/nll/relate_tys/universe-violation.rs
new file mode 100644
index 0000000..d29f8f8
--- /dev/null
+++ b/src/test/ui/nll/relate_tys/universe-violation.rs
@@ -0,0 +1,17 @@
+// Test that the NLL `relate_tys` code correctly deduces that a
+// function returning either argument CANNOT be upcast to one
+// that returns always its first argument.
+//
+// compile-flags:-Zno-leak-check
+
+#![feature(nll)]
+
+fn make_it() -> fn(&'static u32) -> &'static u32 {
+    panic!()
+}
+
+fn main() {
+    let a: fn(_) -> _ = make_it();
+    let b: fn(&u32) -> &u32 = a; //~ ERROR higher-ranked subtype error
+    drop(a);
+}
diff --git a/src/test/ui/nll/relate_tys/universe-violation.stderr b/src/test/ui/nll/relate_tys/universe-violation.stderr
new file mode 100644
index 0000000..6dc7878
--- /dev/null
+++ b/src/test/ui/nll/relate_tys/universe-violation.stderr
@@ -0,0 +1,8 @@
+error: higher-ranked subtype error
+  --> $DIR/universe-violation.rs:15:31
+   |
+LL |     let b: fn(&u32) -> &u32 = a;
+   |                               ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/relate_tys/var-appears-twice.rs b/src/test/ui/nll/relate_tys/var-appears-twice.rs
new file mode 100644
index 0000000..2f227c8
--- /dev/null
+++ b/src/test/ui/nll/relate_tys/var-appears-twice.rs
@@ -0,0 +1,28 @@
+// Test that the NLL `relate_tys` code correctly deduces that a
+// function returning always its first argument can be upcast to one
+// that returns either first or second argument.
+
+#![feature(nll)]
+#![allow(warnings)]
+
+use std::cell::Cell;
+
+type DoubleCell<A> = Cell<(A, A)>;
+type DoublePair<A> = (A, A);
+
+fn make_cell<'b>(x: &'b u32) -> Cell<(&'static u32, &'b u32)> {
+    panic!()
+}
+
+fn main() {
+    let a: &'static u32 = &22;
+    let b = 44;
+
+    // Here we get an error because `DoubleCell<_>` requires the same type
+    // on both parts of the `Cell`, and we can't have that.
+    let x: DoubleCell<_> = make_cell(&b); //~ ERROR
+
+    // Here we do not get an error because `DoublePair<_>` permits
+    // variance on the lifetimes involved.
+    let y: DoublePair<_> = make_cell(&b).get();
+}
diff --git a/src/test/ui/nll/relate_tys/var-appears-twice.stderr b/src/test/ui/nll/relate_tys/var-appears-twice.stderr
new file mode 100644
index 0000000..7c078d2
--- /dev/null
+++ b/src/test/ui/nll/relate_tys/var-appears-twice.stderr
@@ -0,0 +1,14 @@
+error[E0597]: `b` does not live long enough
+  --> $DIR/var-appears-twice.rs:23:38
+   |
+LL |     let x: DoubleCell<_> = make_cell(&b);
+   |            -------------             ^^ borrowed value does not live long enough
+   |            |
+   |            type annotation requires that `b` is borrowed for `'static`
+...
+LL | }
+   | - `b` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/return-ref-mut-issue-46557.rs b/src/test/ui/nll/return-ref-mut-issue-46557.rs
new file mode 100644
index 0000000..b535ab1
--- /dev/null
+++ b/src/test/ui/nll/return-ref-mut-issue-46557.rs
@@ -0,0 +1,11 @@
+// Regression test for issue #46557
+
+#![feature(nll)]
+#![allow(dead_code)]
+
+fn gimme_static_mut() -> &'static mut u32 {
+    let ref mut x = 1234543;
+    x //~ ERROR cannot return value referencing temporary value [E0515]
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/return-ref-mut-issue-46557.stderr b/src/test/ui/nll/return-ref-mut-issue-46557.stderr
new file mode 100644
index 0000000..cc20113
--- /dev/null
+++ b/src/test/ui/nll/return-ref-mut-issue-46557.stderr
@@ -0,0 +1,11 @@
+error[E0515]: cannot return value referencing temporary value
+  --> $DIR/return-ref-mut-issue-46557.rs:8:5
+   |
+LL |     let ref mut x = 1234543;
+   |                     ------- temporary value created here
+LL |     x
+   |     ^ returns a value referencing data owned by the current function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/src/test/ui/nll/return_from_loop.rs b/src/test/ui/nll/return_from_loop.rs
new file mode 100644
index 0000000..23a1e0b
--- /dev/null
+++ b/src/test/ui/nll/return_from_loop.rs
@@ -0,0 +1,39 @@
+// Basic test for liveness constraints: the region (`R1`) that appears
+// in the type of `p` includes the points after `&v[0]` up to (but not
+// including) the call to `use_x`. The `else` branch is not included.
+
+// compile-flags:-Zborrowck=compare
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+
+struct MyStruct {
+    field: String
+}
+
+fn main() {
+}
+
+fn nll_fail() {
+    let mut my_struct = MyStruct { field: format!("Hello") };
+
+    let value = &mut my_struct.field;
+    loop {
+        my_struct.field.push_str("Hello, world!");
+        //~^ ERROR (Ast) [E0499]
+        //~| ERROR (Mir) [E0499]
+        value.len();
+        return;
+    }
+}
+
+fn nll_ok() {
+    let mut my_struct = MyStruct { field: format!("Hello") };
+
+    let value = &mut my_struct.field;
+    loop {
+        my_struct.field.push_str("Hello, world!");
+        //~^ ERROR (Ast) [E0499]
+        return;
+    }
+}
diff --git a/src/test/ui/nll/return_from_loop.stderr b/src/test/ui/nll/return_from_loop.stderr
new file mode 100644
index 0000000..09882d5
--- /dev/null
+++ b/src/test/ui/nll/return_from_loop.stderr
@@ -0,0 +1,39 @@
+error[E0499]: cannot borrow `my_struct.field` as mutable more than once at a time (Ast)
+  --> $DIR/return_from_loop.rs:22:9
+   |
+LL |     let value = &mut my_struct.field;
+   |                      --------------- first mutable borrow occurs here
+LL |     loop {
+LL |         my_struct.field.push_str("Hello, world!");
+   |         ^^^^^^^^^^^^^^^ second mutable borrow occurs here
+...
+LL | }
+   | - first borrow ends here
+
+error[E0499]: cannot borrow `my_struct.field` as mutable more than once at a time (Ast)
+  --> $DIR/return_from_loop.rs:35:9
+   |
+LL |     let value = &mut my_struct.field;
+   |                      --------------- first mutable borrow occurs here
+LL |     loop {
+LL |         my_struct.field.push_str("Hello, world!");
+   |         ^^^^^^^^^^^^^^^ second mutable borrow occurs here
+...
+LL | }
+   | - first borrow ends here
+
+error[E0499]: cannot borrow `my_struct.field` as mutable more than once at a time (Mir)
+  --> $DIR/return_from_loop.rs:22:9
+   |
+LL |     let value = &mut my_struct.field;
+   |                 -------------------- first mutable borrow occurs here
+LL |     loop {
+LL |         my_struct.field.push_str("Hello, world!");
+   |         ^^^^^^^^^^^^^^^ second mutable borrow occurs here
+...
+LL |         value.len();
+   |         ----- first borrow later used here
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/nll/trait-associated-constant.rs b/src/test/ui/nll/trait-associated-constant.rs
new file mode 100644
index 0000000..31dc581
--- /dev/null
+++ b/src/test/ui/nll/trait-associated-constant.rs
@@ -0,0 +1,31 @@
+// Test cases where we put various lifetime constraints on trait
+// associated constants.
+
+#![feature(rustc_attrs)]
+
+use std::option::Option;
+
+trait Anything<'a: 'b, 'b> {
+    const AC: Option<&'b str>;
+}
+
+struct OKStruct1 { }
+
+impl<'a: 'b, 'b> Anything<'a, 'b> for OKStruct1 {
+    const AC: Option<&'b str> = None;
+}
+
+struct FailStruct { }
+
+impl<'a: 'b, 'b, 'c> Anything<'a, 'b> for FailStruct {
+    const AC: Option<&'c str> = None;
+    //~^ ERROR: mismatched types
+}
+
+struct OKStruct2 { }
+
+impl<'a: 'b, 'b> Anything<'a, 'b> for OKStruct2 {
+    const AC: Option<&'a str> = None;
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/trait-associated-constant.stderr b/src/test/ui/nll/trait-associated-constant.stderr
new file mode 100644
index 0000000..f39f668
--- /dev/null
+++ b/src/test/ui/nll/trait-associated-constant.stderr
@@ -0,0 +1,22 @@
+error[E0308]: mismatched types
+  --> $DIR/trait-associated-constant.rs:21:5
+   |
+LL |     const AC: Option<&'c str> = None;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
+   |
+   = note: expected type `std::option::Option<&'b str>`
+              found type `std::option::Option<&'c str>`
+note: the lifetime 'c as defined on the impl at 20:18...
+  --> $DIR/trait-associated-constant.rs:20:18
+   |
+LL | impl<'a: 'b, 'b, 'c> Anything<'a, 'b> for FailStruct {
+   |                  ^^
+note: ...does not necessarily outlive the lifetime 'b as defined on the impl at 20:14
+  --> $DIR/trait-associated-constant.rs:20:14
+   |
+LL | impl<'a: 'b, 'b, 'c> Anything<'a, 'b> for FailStruct {
+   |              ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/nll/ty-outlives/impl-trait-captures.rs b/src/test/ui/nll/ty-outlives/impl-trait-captures.rs
new file mode 100644
index 0000000..bcdf643
--- /dev/null
+++ b/src/test/ui/nll/ty-outlives/impl-trait-captures.rs
@@ -0,0 +1,15 @@
+// compile-flags:-Zborrowck=mir -Zverbose
+
+#![allow(warnings)]
+
+trait Foo<'a> {
+}
+
+impl<'a, T> Foo<'a> for T { }
+
+fn foo<'a, T>(x: &T) -> impl Foo<'a> {
+//~^ ERROR explicit lifetime required in the type of `x` [E0621]
+    x
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr b/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr
new file mode 100644
index 0000000..3a1e3ce
--- /dev/null
+++ b/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr
@@ -0,0 +1,13 @@
+error[E0621]: explicit lifetime required in the type of `x`
+  --> $DIR/impl-trait-captures.rs:10:25
+   |
+LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> {
+   |                         ^^^^^^^^^^^^ lifetime `ReEarlyBound(0, 'a)` required
+help: add explicit lifetime `ReEarlyBound(0, 'a)` to the type of `x`
+   |
+LL | fn foo<'a, T>(x: &ReEarlyBound(0, 'a) T) -> impl Foo<'a> {
+   |                  ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/nll/ty-outlives/impl-trait-outlives.rs b/src/test/ui/nll/ty-outlives/impl-trait-outlives.rs
new file mode 100644
index 0000000..0c7d8ac
--- /dev/null
+++ b/src/test/ui/nll/ty-outlives/impl-trait-outlives.rs
@@ -0,0 +1,38 @@
+// compile-flags:-Zborrowck=mir -Zverbose
+
+#![allow(warnings)]
+
+use std::fmt::Debug;
+
+fn no_region<'a, T>(x: Box<T>) -> impl Debug + 'a
+    //~^ ERROR the parameter type `T` may not live long enough [E0309]
+where
+    T: Debug,
+{
+    x
+}
+
+fn correct_region<'a, T>(x: Box<T>) -> impl Debug + 'a
+where
+    T: 'a + Debug,
+{
+    x
+}
+
+fn wrong_region<'a, 'b, T>(x: Box<T>) -> impl Debug + 'a
+    //~^ ERROR the parameter type `T` may not live long enough [E0309]
+where
+    T: 'b + Debug,
+{
+    x
+}
+
+fn outlives_region<'a, 'b, T>(x: Box<T>) -> impl Debug + 'a
+where
+    T: 'b + Debug,
+    'b: 'a,
+{
+    x
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/ty-outlives/impl-trait-outlives.stderr b/src/test/ui/nll/ty-outlives/impl-trait-outlives.stderr
new file mode 100644
index 0000000..32a494c
--- /dev/null
+++ b/src/test/ui/nll/ty-outlives/impl-trait-outlives.stderr
@@ -0,0 +1,19 @@
+error[E0309]: the parameter type `T` may not live long enough
+  --> $DIR/impl-trait-outlives.rs:7:35
+   |
+LL | fn no_region<'a, T>(x: Box<T>) -> impl Debug + 'a
+   |                                   ^^^^^^^^^^^^^^^
+   |
+   = help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`...
+
+error[E0309]: the parameter type `T` may not live long enough
+  --> $DIR/impl-trait-outlives.rs:22:42
+   |
+LL | fn wrong_region<'a, 'b, T>(x: Box<T>) -> impl Debug + 'a
+   |                                          ^^^^^^^^^^^^^^^
+   |
+   = help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`...
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0309`.
diff --git a/src/test/ui/nll/ty-outlives/issue-53789-1.rs b/src/test/ui/nll/ty-outlives/issue-53789-1.rs
new file mode 100644
index 0000000..593cdfd
--- /dev/null
+++ b/src/test/ui/nll/ty-outlives/issue-53789-1.rs
@@ -0,0 +1,91 @@
+// Regression test for #53789.
+//
+// compile-pass
+
+#![feature(nll)]
+#![allow(unused_variables)]
+
+use std::collections::BTreeMap;
+
+trait ValueTree {
+    type Value;
+}
+
+trait Strategy {
+    type Value: ValueTree;
+}
+
+type StrategyFor<A> = StrategyType<'static, A>;
+type StrategyType<'a, A> = <A as Arbitrary<'a>>::Strategy;
+
+impl<K: ValueTree, V: ValueTree> Strategy for (K, V) {
+    type Value = TupleValueTree<(K, V)>;
+}
+
+impl<K: ValueTree, V: ValueTree> ValueTree for TupleValueTree<(K, V)> {
+    type Value = BTreeMapValueTree<K, V>;
+}
+
+struct TupleValueTree<T> {
+    tree: T,
+}
+
+struct BTreeMapStrategy<K, V>(std::marker::PhantomData<(K, V)>)
+where
+    K: Strategy,
+    V: Strategy;
+
+struct BTreeMapValueTree<K, V>(std::marker::PhantomData<(K, V)>)
+where
+    K: ValueTree,
+    V: ValueTree;
+
+impl<K, V> Strategy for BTreeMapStrategy<K, V>
+where
+    K: Strategy,
+    V: Strategy,
+{
+    type Value = BTreeMapValueTree<K::Value, V::Value>;
+}
+
+impl<K, V> ValueTree for BTreeMapValueTree<K, V>
+where
+    K: ValueTree,
+    V: ValueTree,
+{
+    type Value = BTreeMap<K::Value, V::Value>;
+}
+
+trait Arbitrary<'a>: Sized {
+    fn arbitrary_with(args: Self::Parameters) -> Self::Strategy;
+    type Parameters;
+    type Strategy: Strategy<Value = Self::ValueTree>;
+    type ValueTree: ValueTree<Value = Self>;
+}
+
+impl<'a, A, B> Arbitrary<'a> for BTreeMap<A, B>
+where
+    A: Arbitrary<'static>,
+    B: Arbitrary<'static>,
+    StrategyFor<A>: 'static,
+    StrategyFor<B>: 'static,
+{
+    type ValueTree = <Self::Strategy as Strategy>::Value;
+    type Parameters = (A::Parameters, B::Parameters);
+    type Strategy = BTreeMapStrategy<A::Strategy, B::Strategy>;
+    fn arbitrary_with(args: Self::Parameters) -> BTreeMapStrategy<A::Strategy, B::Strategy> {
+        let (a, b) = args;
+        btree_map(any_with::<A>(a), any_with::<B>(b))
+    }
+}
+
+fn btree_map<K: Strategy + 'static, V: Strategy>(key: K, value: V) -> BTreeMapStrategy<K, V> {
+    unimplemented!()
+}
+
+fn any_with<'a, A: Arbitrary<'a>>(args: A::Parameters) -> StrategyType<'a, A> {
+    unimplemented!()
+}
+
+fn main() { }
+
diff --git a/src/test/ui/nll/ty-outlives/issue-53789-2.rs b/src/test/ui/nll/ty-outlives/issue-53789-2.rs
new file mode 100644
index 0000000..62e2833
--- /dev/null
+++ b/src/test/ui/nll/ty-outlives/issue-53789-2.rs
@@ -0,0 +1,251 @@
+// Regression test for #53789.
+//
+// compile-pass
+
+#![feature(nll)]
+#![allow(unused_variables)]
+
+use std::collections::BTreeMap;
+use std::ops::Range;
+use std::cmp::Ord;
+
+macro_rules! valuetree {
+    () => {
+        type ValueTree =
+            <Self::Strategy as $crate::Strategy>::Value;
+    };
+}
+
+macro_rules! product_unpack {
+    ($factor: pat) => {
+        ($factor,)
+    };
+    ($($factor: pat),*) => {
+        ( $( $factor ),* )
+    };
+    ($($factor: pat),*,) => {
+        ( $( $factor ),* )
+    };
+}
+
+macro_rules! product_type {
+    ($factor: ty) => {
+        ($factor,)
+    };
+    ($($factor: ty),*) => {
+        ( $( $factor, )* )
+    };
+    ($($factor: ty),*,) => {
+        ( $( $factor, )* )
+    };
+}
+
+macro_rules! default {
+    ($type: ty, $val: expr) => {
+        impl Default for $type {
+            fn default() -> Self { $val.into() }
+        }
+    };
+}
+
+// Pervasive internal sugar
+macro_rules! mapfn {
+    ($(#[$meta:meta])* [$($vis:tt)*]
+     fn $name:ident[$($gen:tt)*]($parm:ident: $input:ty) -> $output:ty {
+         $($body:tt)*
+     }) => {
+        $(#[$meta])*
+            #[derive(Clone, Copy)]
+        $($vis)* struct $name;
+        impl $($gen)* statics::MapFn<$input> for $name {
+            type Output = $output;
+        }
+    }
+}
+
+macro_rules! opaque_strategy_wrapper {
+    ($(#[$smeta:meta])* pub struct $stratname:ident
+     [$($sgen:tt)*][$($swhere:tt)*]
+     ($innerstrat:ty) -> $stratvtty:ty;
+
+     $(#[$vmeta:meta])* pub struct $vtname:ident
+     [$($vgen:tt)*][$($vwhere:tt)*]
+     ($innervt:ty) -> $actualty:ty;
+    ) => {
+        $(#[$smeta])* struct $stratname $($sgen)* (std::marker::PhantomData<(K, V)>)
+            $($swhere)*;
+
+        $(#[$vmeta])* struct $vtname $($vgen)* ($innervt) $($vwhere)*;
+
+        impl $($sgen)* Strategy for $stratname $($sgen)* $($swhere)* {
+            type Value = $stratvtty;
+        }
+
+        impl $($vgen)* ValueTree for $vtname $($vgen)* $($vwhere)* {
+            type Value = $actualty;
+        }
+    }
+}
+
+trait ValueTree {
+    type Value;
+}
+
+trait Strategy {
+    type Value : ValueTree;
+}
+
+#[derive(Clone)]
+struct VecStrategy<T : Strategy> {
+    element: T,
+    size: Range<usize>,
+}
+
+fn vec<T : Strategy>(element: T, size: Range<usize>)
+                     -> VecStrategy<T> {
+    VecStrategy {
+        element: element,
+        size: size,
+    }
+}
+
+type ValueFor<S> = <<S as Strategy>::Value as ValueTree>::Value;
+
+trait Arbitrary<'a>: Sized {
+    fn arbitrary_with(args: Self::Parameters) -> Self::Strategy;
+
+    type Parameters: Default;
+    type Strategy: Strategy<Value = Self::ValueTree>;
+    type ValueTree: ValueTree<Value = Self>;
+}
+
+type StrategyFor<A> = StrategyType<'static, A>;
+type StrategyType<'a, A> = <A as Arbitrary<'a>>::Strategy;
+
+//#[derive(Clone, PartialEq, Eq, Hash, Debug, From, Into)]
+struct SizeBounds(Range<usize>);
+default!(SizeBounds, 0..100);
+
+
+impl From<Range<usize>> for SizeBounds {
+    fn from(high: Range<usize>) -> Self {
+        unimplemented!()
+    }
+}
+
+impl From<SizeBounds> for Range<usize> {
+    fn from(high: SizeBounds) -> Self {
+        unimplemented!()
+    }
+}
+
+
+fn any_with<'a, A: Arbitrary<'a>>(args: A::Parameters)
+                                  -> StrategyType<'a, A> {
+    unimplemented!()
+}
+
+impl<K: ValueTree, V: ValueTree> Strategy for (K, V) where
+    <K as ValueTree>::Value: Ord {
+    type Value = TupleValueTree<(K, V)>;
+}
+
+impl<K: ValueTree, V: ValueTree> ValueTree for TupleValueTree<(K, V)> where
+    <K as ValueTree>::Value: Ord {
+    type Value = BTreeMapValueTree<K, V>;
+}
+
+#[derive(Clone)]
+struct VecValueTree<T : ValueTree> {
+    elements: Vec<T>,
+}
+
+#[derive(Clone, Copy)]
+struct TupleValueTree<T> {
+    tree: T,
+}
+
+opaque_strategy_wrapper! {
+    #[derive(Clone)]
+    pub struct BTreeMapStrategy[<K, V>]
+        [where K : Strategy, V : Strategy, ValueFor<K> : Ord](
+            statics::Filter<statics::Map<VecStrategy<(K,V)>,
+            VecToBTreeMap>, MinSize>)
+        -> BTreeMapValueTree<K::Value, V::Value>;
+
+    #[derive(Clone)]
+    pub struct BTreeMapValueTree[<K, V>]
+        [where K : ValueTree, V : ValueTree, K::Value : Ord](
+            statics::Filter<statics::Map<VecValueTree<TupleValueTree<(K, V)>>,
+            VecToBTreeMap>, MinSize>)
+        -> BTreeMap<K::Value, V::Value>;
+}
+
+type RangedParams2<A, B> = product_type![SizeBounds, A, B];
+
+impl<'a, A, B> Arbitrary<'a> for BTreeMap<A, B>
+where
+    A: Arbitrary<'static> + Ord,
+    B: Arbitrary<'static>,
+StrategyFor<A>: 'static,
+StrategyFor<B>: 'static,
+{
+    valuetree!();
+    type Parameters = RangedParams2<A::Parameters, B::Parameters>;
+    type Strategy = BTreeMapStrategy<A::Strategy, B::Strategy>;
+    fn arbitrary_with(args: Self::Parameters) -> Self::Strategy {
+        let product_unpack![range, a, b] = args;
+        btree_map(any_with::<A>(a), any_with::<B>(b), range.into())
+    }
+}
+
+#[derive(Clone, Copy)]
+struct MinSize(usize);
+
+mapfn! {
+    [] fn VecToBTreeMap[<K : Ord, V>]
+        (vec: Vec<(K, V)>) -> BTreeMap<K, V>
+    {
+        vec.into_iter().collect()
+    }
+}
+
+fn btree_map<K : Strategy + 'static, V : Strategy + 'static>
+    (key: K, value: V, size: Range<usize>)
+     -> BTreeMapStrategy<K, V>
+where ValueFor<K> : Ord {
+    unimplemented!()
+}
+
+mod statics {
+    pub(super) trait MapFn<T> {
+        type Output;
+    }
+
+    #[derive(Clone)]
+    pub struct Filter<S, F> {
+        source: S,
+        fun: F,
+    }
+
+    impl<S, F> Filter<S, F> {
+        pub fn new(source: S, whence: String, filter: F) -> Self {
+            unimplemented!()
+        }
+    }
+
+    #[derive(Clone)]
+    pub struct Map<S, F> {
+        source: S,
+        fun: F,
+    }
+
+    impl<S, F> Map<S, F> {
+        pub fn new(source: S, fun: F) -> Self {
+            unimplemented!()
+        }
+    }
+}
+
+fn main() { }
+
diff --git a/src/test/ui/nll/ty-outlives/issue-55756.rs b/src/test/ui/nll/ty-outlives/issue-55756.rs
new file mode 100644
index 0000000..cda3915
--- /dev/null
+++ b/src/test/ui/nll/ty-outlives/issue-55756.rs
@@ -0,0 +1,37 @@
+// Regression test for #55756.
+//
+// In this test, the result of `self.callee` is a projection `<D as
+// Database<'?0>>::Guard`. As it may contain a destructor, the dropck
+// rules require that this type outlivess the scope of `state`. Unfortunately,
+// our region inference is not smart enough to figure out how to
+// translate a requirement like
+//
+//     <D as Database<'0>>::guard: 'r
+//
+// into a requirement that `'0: 'r` -- in particular, it fails to do
+// so because it *also* knows that `<D as Database<'a>>::Guard: 'a`
+// from the trait definition. Faced with so many choices, the current
+// solver opts to do nothing.
+//
+// Fixed by tweaking the solver to recognize that the constraint from
+// the environment duplicates one from the trait.
+//
+// compile-pass
+
+#![crate_type="lib"]
+
+pub trait Database<'a> {
+    type Guard: 'a;
+}
+
+pub struct Stateful<'a, D: 'a>(&'a D);
+
+impl<'b, D: for <'a> Database<'a>> Stateful<'b, D> {
+    pub fn callee<'a>(&'a self) -> <D as Database<'a>>::Guard {
+        unimplemented!()
+    }
+    pub fn caller<'a>(&'a self) -> <D as Database<'a>>::Guard {
+        let state = self.callee();
+        unimplemented!()
+    }
+}
diff --git a/src/test/ui/nll/ty-outlives/projection-body.rs b/src/test/ui/nll/ty-outlives/projection-body.rs
new file mode 100644
index 0000000..2e105ec
--- /dev/null
+++ b/src/test/ui/nll/ty-outlives/projection-body.rs
@@ -0,0 +1,27 @@
+// Test that when we infer the lifetime to a subset of the fn body, it
+// works out.
+//
+// compile-pass
+
+trait MyTrait<'a> {
+    type Output;
+}
+
+fn foo1<T>()
+where
+    for<'x> T: MyTrait<'x>,
+{
+    // Here the region `'c` in `<T as MyTrait<'c>>::Output` will be
+    // inferred to a subset of the fn body.
+    let x = bar::<T::Output>();
+    drop(x);
+}
+
+fn bar<'a, T>() -> &'a ()
+where
+    T: 'a,
+{
+    &()
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/ty-outlives/projection-implied-bounds.rs b/src/test/ui/nll/ty-outlives/projection-implied-bounds.rs
new file mode 100644
index 0000000..1245ce8
--- /dev/null
+++ b/src/test/ui/nll/ty-outlives/projection-implied-bounds.rs
@@ -0,0 +1,45 @@
+// compile-flags:-Zborrowck=mir -Zverbose
+
+// Test that we can deduce when projections like `T::Item` outlive the
+// function body. Test that this does not imply that `T: 'a` holds.
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+
+use std::cell::Cell;
+
+fn twice<F, T>(mut value: T, mut f: F)
+where
+    F: FnMut(&T, Cell<&Option<T::Item>>),
+    T: Iterator,
+{
+    let mut n = value.next();
+    f(&value, Cell::new(&n));
+    f(&value, Cell::new(&n));
+}
+
+#[rustc_errors]
+fn generic1<T: Iterator>(value: T) {
+    // No error here:
+    twice(value, |value_ref, item| invoke1(item));
+}
+
+fn invoke1<'a, T>(x: Cell<&'a Option<T>>)
+where
+    T: 'a,
+{
+}
+
+#[rustc_errors]
+fn generic2<T: Iterator>(value: T) {
+    twice(value, |value_ref, item| invoke2(value_ref, item));
+    //~^ ERROR the parameter type `T` may not live long enough
+}
+
+fn invoke2<'a, T, U>(a: &T, b: Cell<&'a Option<U>>)
+where
+    T: 'a,
+{
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/ty-outlives/projection-implied-bounds.stderr b/src/test/ui/nll/ty-outlives/projection-implied-bounds.stderr
new file mode 100644
index 0000000..9cdb78a
--- /dev/null
+++ b/src/test/ui/nll/ty-outlives/projection-implied-bounds.stderr
@@ -0,0 +1,11 @@
+error[E0310]: the parameter type `T` may not live long enough
+  --> $DIR/projection-implied-bounds.rs:35:18
+   |
+LL |     twice(value, |value_ref, item| invoke2(value_ref, item));
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding an explicit lifetime bound `T: 'static`...
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0310`.
diff --git a/src/test/ui/nll/ty-outlives/projection-no-regions-closure.rs b/src/test/ui/nll/ty-outlives/projection-no-regions-closure.rs
new file mode 100644
index 0000000..20af0fb
--- /dev/null
+++ b/src/test/ui/nll/ty-outlives/projection-no-regions-closure.rs
@@ -0,0 +1,55 @@
+// compile-flags:-Zborrowck=mir -Zverbose
+
+// Tests closures that propagate an outlives relationship to their
+// creator where the subject is a projection with no regions (`<T as
+// Iterator>::Item`, to be exact).
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+
+trait Anything { }
+
+impl<T> Anything for T { }
+
+fn with_signature<'a, T, F>(x: Box<T>, op: F) -> Box<dyn Anything + 'a>
+    where F: FnOnce(Box<T>) -> Box<dyn Anything + 'a>
+{
+    op(x)
+}
+
+#[rustc_regions]
+fn no_region<'a, T>(x: Box<T>) -> Box<dyn Anything + 'a>
+where
+    T: Iterator,
+{
+    with_signature(x, |mut y| Box::new(y.next()))
+    //~^ ERROR the associated type `<T as std::iter::Iterator>::Item` may not live long enough
+}
+
+#[rustc_regions]
+fn correct_region<'a, T>(x: Box<T>) -> Box<dyn Anything + 'a>
+where
+    T: 'a + Iterator,
+{
+    with_signature(x, |mut y| Box::new(y.next()))
+}
+
+#[rustc_regions]
+fn wrong_region<'a, 'b, T>(x: Box<T>) -> Box<dyn Anything + 'a>
+where
+    T: 'b + Iterator,
+{
+    with_signature(x, |mut y| Box::new(y.next()))
+    //~^ ERROR the associated type `<T as std::iter::Iterator>::Item` may not live long enough
+}
+
+#[rustc_regions]
+fn outlives_region<'a, 'b, T>(x: Box<T>) -> Box<dyn Anything + 'a>
+where
+    T: 'b + Iterator,
+    'b: 'a,
+{
+    with_signature(x, |mut y| Box::new(y.next()))
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr b/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr
new file mode 100644
index 0000000..cda1f7d
--- /dev/null
+++ b/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr
@@ -0,0 +1,150 @@
+note: External requirements
+  --> $DIR/projection-no-regions-closure.rs:25:23
+   |
+LL |     with_signature(x, |mut y| Box::new(y.next()))
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:15 ~ projection_no_regions_closure[317d]::no_region[0]::{{closure}}[0]) with closure substs [
+               '_#1r,
+               T,
+               i32,
+               extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<(dyn Anything + '_#2r)>,
+           ]
+   = note: number of external vids: 3
+   = note: where <T as std::iter::Iterator>::Item: '_#2r
+
+note: No external requirements
+  --> $DIR/projection-no-regions-closure.rs:21:1
+   |
+LL | / fn no_region<'a, T>(x: Box<T>) -> Box<dyn Anything + 'a>
+LL | | where
+LL | |     T: Iterator,
+LL | | {
+LL | |     with_signature(x, |mut y| Box::new(y.next()))
+LL | |
+LL | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:6 ~ projection_no_regions_closure[317d]::no_region[0]) with substs [
+               '_#1r,
+               T,
+           ]
+
+error[E0309]: the associated type `<T as std::iter::Iterator>::Item` may not live long enough
+  --> $DIR/projection-no-regions-closure.rs:25:23
+   |
+LL |     with_signature(x, |mut y| Box::new(y.next()))
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding an explicit lifetime bound `<T as std::iter::Iterator>::Item: ReEarlyBound(0, 'a)`...
+
+note: External requirements
+  --> $DIR/projection-no-regions-closure.rs:34:23
+   |
+LL |     with_signature(x, |mut y| Box::new(y.next()))
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:18 ~ projection_no_regions_closure[317d]::correct_region[0]::{{closure}}[0]) with closure substs [
+               '_#1r,
+               T,
+               i32,
+               extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<(dyn Anything + '_#2r)>,
+           ]
+   = note: number of external vids: 3
+   = note: where <T as std::iter::Iterator>::Item: '_#2r
+
+note: No external requirements
+  --> $DIR/projection-no-regions-closure.rs:30:1
+   |
+LL | / fn correct_region<'a, T>(x: Box<T>) -> Box<dyn Anything + 'a>
+LL | | where
+LL | |     T: 'a + Iterator,
+LL | | {
+LL | |     with_signature(x, |mut y| Box::new(y.next()))
+LL | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:7 ~ projection_no_regions_closure[317d]::correct_region[0]) with substs [
+               '_#1r,
+               T,
+           ]
+
+note: External requirements
+  --> $DIR/projection-no-regions-closure.rs:42:23
+   |
+LL |     with_signature(x, |mut y| Box::new(y.next()))
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:22 ~ projection_no_regions_closure[317d]::wrong_region[0]::{{closure}}[0]) with closure substs [
+               '_#1r,
+               '_#2r,
+               T,
+               i32,
+               extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<(dyn Anything + '_#3r)>,
+           ]
+   = note: number of external vids: 4
+   = note: where <T as std::iter::Iterator>::Item: '_#3r
+
+note: No external requirements
+  --> $DIR/projection-no-regions-closure.rs:38:1
+   |
+LL | / fn wrong_region<'a, 'b, T>(x: Box<T>) -> Box<dyn Anything + 'a>
+LL | | where
+LL | |     T: 'b + Iterator,
+LL | | {
+LL | |     with_signature(x, |mut y| Box::new(y.next()))
+LL | |
+LL | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:8 ~ projection_no_regions_closure[317d]::wrong_region[0]) with substs [
+               '_#1r,
+               '_#2r,
+               T,
+           ]
+
+error[E0309]: the associated type `<T as std::iter::Iterator>::Item` may not live long enough
+  --> $DIR/projection-no-regions-closure.rs:42:23
+   |
+LL |     with_signature(x, |mut y| Box::new(y.next()))
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding an explicit lifetime bound `<T as std::iter::Iterator>::Item: ReEarlyBound(0, 'a)`...
+
+note: External requirements
+  --> $DIR/projection-no-regions-closure.rs:52:23
+   |
+LL |     with_signature(x, |mut y| Box::new(y.next()))
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:26 ~ projection_no_regions_closure[317d]::outlives_region[0]::{{closure}}[0]) with closure substs [
+               '_#1r,
+               '_#2r,
+               T,
+               i32,
+               extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<(dyn Anything + '_#3r)>,
+           ]
+   = note: number of external vids: 4
+   = note: where <T as std::iter::Iterator>::Item: '_#3r
+
+note: No external requirements
+  --> $DIR/projection-no-regions-closure.rs:47:1
+   |
+LL | / fn outlives_region<'a, 'b, T>(x: Box<T>) -> Box<dyn Anything + 'a>
+LL | | where
+LL | |     T: 'b + Iterator,
+LL | |     'b: 'a,
+LL | | {
+LL | |     with_signature(x, |mut y| Box::new(y.next()))
+LL | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:9 ~ projection_no_regions_closure[317d]::outlives_region[0]) with substs [
+               '_#1r,
+               '_#2r,
+               T,
+           ]
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0309`.
diff --git a/src/test/ui/nll/ty-outlives/projection-no-regions-fn.rs b/src/test/ui/nll/ty-outlives/projection-no-regions-fn.rs
new file mode 100644
index 0000000..64073be
--- /dev/null
+++ b/src/test/ui/nll/ty-outlives/projection-no-regions-fn.rs
@@ -0,0 +1,40 @@
+// compile-flags:-Zborrowck=mir -Zverbose
+
+#![allow(warnings)]
+
+trait Anything { }
+
+impl<T> Anything for T { }
+
+fn no_region<'a, T>(mut x: T) -> Box<dyn Anything + 'a>
+where
+    T: Iterator,
+{
+    Box::new(x.next())
+    //~^ ERROR the associated type `<T as std::iter::Iterator>::Item` may not live long enough
+}
+
+fn correct_region<'a, T>(mut x: T) -> Box<dyn Anything + 'a>
+where
+    T: 'a + Iterator,
+{
+    Box::new(x.next())
+}
+
+fn wrong_region<'a, 'b, T>(mut x: T) -> Box<dyn Anything + 'a>
+where
+    T: 'b + Iterator,
+{
+    Box::new(x.next())
+    //~^ ERROR the associated type `<T as std::iter::Iterator>::Item` may not live long enough
+}
+
+fn outlives_region<'a, 'b, T>(mut x: T) -> Box<dyn Anything + 'a>
+where
+    T: 'b + Iterator,
+    'b: 'a,
+{
+    Box::new(x.next())
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/ty-outlives/projection-no-regions-fn.stderr b/src/test/ui/nll/ty-outlives/projection-no-regions-fn.stderr
new file mode 100644
index 0000000..190a2cd
--- /dev/null
+++ b/src/test/ui/nll/ty-outlives/projection-no-regions-fn.stderr
@@ -0,0 +1,19 @@
+error[E0309]: the associated type `<T as std::iter::Iterator>::Item` may not live long enough
+  --> $DIR/projection-no-regions-fn.rs:13:5
+   |
+LL |     Box::new(x.next())
+   |     ^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding an explicit lifetime bound `<T as std::iter::Iterator>::Item: ReEarlyBound(0, 'a)`...
+
+error[E0309]: the associated type `<T as std::iter::Iterator>::Item` may not live long enough
+  --> $DIR/projection-no-regions-fn.rs:28:5
+   |
+LL |     Box::new(x.next())
+   |     ^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding an explicit lifetime bound `<T as std::iter::Iterator>::Item: ReEarlyBound(0, 'a)`...
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0309`.
diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-closure.rs b/src/test/ui/nll/ty-outlives/projection-one-region-closure.rs
new file mode 100644
index 0000000..17d5f2e
--- /dev/null
+++ b/src/test/ui/nll/ty-outlives/projection-one-region-closure.rs
@@ -0,0 +1,83 @@
+// Test cases where we constrain `<T as Anything<'b>>::AssocType` to
+// outlive `'a` and there are no bounds in the trait definition of
+// `Anything`. This means that the constraint can only be satisfied in two
+// ways:
+//
+// - by ensuring that `T: 'a` and `'b: 'a`, or
+// - by something in the where clauses.
+//
+// As of this writing, the where clause option does not work because
+// of limitations in our region inferencing system (this is true both
+// with and without NLL). See `projection_outlives`.
+//
+// Ensuring that both `T: 'a` and `'b: 'a` holds does work (`elements_outlive`).
+
+// compile-flags:-Zborrowck=mir -Zverbose
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+
+use std::cell::Cell;
+
+trait Anything<'a> {
+    type AssocType;
+}
+
+fn with_signature<'a, T, F>(cell: Cell<&'a ()>, t: T, op: F)
+where
+    F: FnOnce(Cell<&'a ()>, T),
+{
+    op(cell, t)
+}
+
+fn require<'a, 'b, T>(_cell: Cell<&'a ()>, _t: T)
+where
+    T: Anything<'b>,
+    T::AssocType: 'a,
+{
+}
+
+#[rustc_regions]
+fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
+where
+    T: Anything<'b>,
+{
+    with_signature(cell, t, |cell, t| require(cell, t));
+    //~^ ERROR the parameter type `T` may not live long enough
+    //~| ERROR
+}
+
+#[rustc_regions]
+fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
+where
+    T: Anything<'b>,
+    'a: 'a,
+{
+    with_signature(cell, t, |cell, t| require(cell, t));
+    //~^ ERROR the parameter type `T` may not live long enough
+    //~| ERROR
+}
+
+#[rustc_regions]
+fn projection_outlives<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
+where
+    T: Anything<'b>,
+    T::AssocType: 'a,
+{
+    // We are projecting `<T as Anything<'b>>::AssocType`, and we know
+    // that this outlives `'a` because of the where-clause.
+
+    with_signature(cell, t, |cell, t| require(cell, t));
+}
+
+#[rustc_regions]
+fn elements_outlive<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
+where
+    T: Anything<'b>,
+    T: 'a,
+    'b: 'a,
+{
+    with_signature(cell, t, |cell, t| require(cell, t));
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr
new file mode 100644
index 0000000..9d71600
--- /dev/null
+++ b/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr
@@ -0,0 +1,179 @@
+note: External requirements
+  --> $DIR/projection-one-region-closure.rs:45:29
+   |
+LL |     with_signature(cell, t, |cell, t| require(cell, t));
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:19 ~ projection_one_region_closure[317d]::no_relationships_late[0]::{{closure}}[0]) with closure substs [
+               '_#1r,
+               T,
+               i32,
+               extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)),
+           ]
+   = note: late-bound region is '_#3r
+   = note: number of external vids: 4
+   = note: where T: '_#2r
+   = note: where '_#1r: '_#2r
+
+note: No external requirements
+  --> $DIR/projection-one-region-closure.rs:41:1
+   |
+LL | / fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
+LL | | where
+LL | |     T: Anything<'b>,
+LL | | {
+...  |
+LL | |
+LL | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:8 ~ projection_one_region_closure[317d]::no_relationships_late[0]) with substs [
+               '_#1r,
+               T,
+           ]
+
+error[E0309]: the parameter type `T` may not live long enough
+  --> $DIR/projection-one-region-closure.rs:45:29
+   |
+LL |     with_signature(cell, t, |cell, t| require(cell, t));
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:8 ~ projection_one_region_closure[317d]::no_relationships_late[0]), BrNamed(crate0:DefIndex(1:16), 'a))`...
+
+error: lifetime may not live long enough
+  --> $DIR/projection-one-region-closure.rs:45:39
+   |
+LL | fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
+   |                          --  -- lifetime `'b` defined here
+   |                          |
+   |                          lifetime `'a` defined here
+...
+LL |     with_signature(cell, t, |cell, t| require(cell, t));
+   |                                       ^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a`
+
+note: External requirements
+  --> $DIR/projection-one-region-closure.rs:56:29
+   |
+LL |     with_signature(cell, t, |cell, t| require(cell, t));
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:23 ~ projection_one_region_closure[317d]::no_relationships_early[0]::{{closure}}[0]) with closure substs [
+               '_#1r,
+               '_#2r,
+               T,
+               i32,
+               extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)),
+           ]
+   = note: number of external vids: 4
+   = note: where T: '_#3r
+   = note: where '_#2r: '_#3r
+
+note: No external requirements
+  --> $DIR/projection-one-region-closure.rs:51:1
+   |
+LL | / fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
+LL | | where
+LL | |     T: Anything<'b>,
+LL | |     'a: 'a,
+...  |
+LL | |
+LL | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:9 ~ projection_one_region_closure[317d]::no_relationships_early[0]) with substs [
+               '_#1r,
+               '_#2r,
+               T,
+           ]
+
+error[E0309]: the parameter type `T` may not live long enough
+  --> $DIR/projection-one-region-closure.rs:56:29
+   |
+LL |     with_signature(cell, t, |cell, t| require(cell, t));
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`...
+
+error: lifetime may not live long enough
+  --> $DIR/projection-one-region-closure.rs:56:39
+   |
+LL | fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
+   |                           --  -- lifetime `'b` defined here
+   |                           |
+   |                           lifetime `'a` defined here
+...
+LL |     with_signature(cell, t, |cell, t| require(cell, t));
+   |                                       ^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a`
+
+note: External requirements
+  --> $DIR/projection-one-region-closure.rs:70:29
+   |
+LL |     with_signature(cell, t, |cell, t| require(cell, t));
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:27 ~ projection_one_region_closure[317d]::projection_outlives[0]::{{closure}}[0]) with closure substs [
+               '_#1r,
+               '_#2r,
+               T,
+               i32,
+               extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)),
+           ]
+   = note: number of external vids: 4
+   = note: where <T as Anything<ReClosureBound('_#2r)>>::AssocType: '_#3r
+
+note: No external requirements
+  --> $DIR/projection-one-region-closure.rs:62:1
+   |
+LL | / fn projection_outlives<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
+LL | | where
+LL | |     T: Anything<'b>,
+LL | |     T::AssocType: 'a,
+...  |
+LL | |     with_signature(cell, t, |cell, t| require(cell, t));
+LL | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:10 ~ projection_one_region_closure[317d]::projection_outlives[0]) with substs [
+               '_#1r,
+               '_#2r,
+               T,
+           ]
+
+note: External requirements
+  --> $DIR/projection-one-region-closure.rs:80:29
+   |
+LL |     with_signature(cell, t, |cell, t| require(cell, t));
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:31 ~ projection_one_region_closure[317d]::elements_outlive[0]::{{closure}}[0]) with closure substs [
+               '_#1r,
+               '_#2r,
+               T,
+               i32,
+               extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)),
+           ]
+   = note: number of external vids: 4
+   = note: where T: '_#3r
+   = note: where '_#2r: '_#3r
+
+note: No external requirements
+  --> $DIR/projection-one-region-closure.rs:74:1
+   |
+LL | / fn elements_outlive<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
+LL | | where
+LL | |     T: Anything<'b>,
+LL | |     T: 'a,
+...  |
+LL | |     with_signature(cell, t, |cell, t| require(cell, t));
+LL | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:11 ~ projection_one_region_closure[317d]::elements_outlive[0]) with substs [
+               '_#1r,
+               '_#2r,
+               T,
+           ]
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0309`.
diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.rs b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.rs
new file mode 100644
index 0000000..8df0700
--- /dev/null
+++ b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.rs
@@ -0,0 +1,84 @@
+// Test cases where we constrain `<T as Anything<'b>>::AssocType` to
+// outlive `'a` and there is a unique bound in the trait definition of
+// `Anything` -- i.e., we know that `AssocType` outlives `'b`. In this
+// case, the best way to satisfy the trait bound is to show that `'b:
+// 'a`, which can be done in various ways.
+
+// compile-flags:-Zborrowck=mir -Zverbose
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+
+use std::cell::Cell;
+
+trait Anything<'a> {
+    type AssocType: 'a;
+}
+
+fn with_signature<'a, T, F>(cell: Cell<&'a ()>, t: T, op: F)
+where
+    F: FnOnce(Cell<&'a ()>, T),
+{
+    op(cell, t)
+}
+
+fn require<'a, 'b, T>(_cell: Cell<&'a ()>, _t: T)
+where
+    T: Anything<'b>,
+    T::AssocType: 'a,
+{
+}
+
+#[rustc_regions]
+fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
+where
+    T: Anything<'b>,
+{
+    with_signature(cell, t, |cell, t| require(cell, t));
+    //~^ ERROR
+}
+
+#[rustc_regions]
+fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
+where
+    T: Anything<'b>,
+    'a: 'a,
+{
+    with_signature(cell, t, |cell, t| require(cell, t));
+    //~^ ERROR
+}
+
+#[rustc_regions]
+fn projection_outlives<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
+where
+    T: Anything<'b>,
+    T::AssocType: 'a,
+{
+    // We are projecting `<T as Anything<'b>>::AssocType`, and we know
+    // that this outlives `'a` because of the where-clause.
+
+    with_signature(cell, t, |cell, t| require(cell, t));
+}
+
+#[rustc_regions]
+fn elements_outlive<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
+where
+    T: Anything<'b>,
+    'b: 'a,
+{
+    with_signature(cell, t, |cell, t| require(cell, t));
+}
+
+#[rustc_regions]
+fn one_region<'a, T>(cell: Cell<&'a ()>, t: T)
+where
+    T: Anything<'a>,
+{
+    // Note that in this case the closure still propagates an external
+    // requirement between two variables in its signature, but the
+    // creator maps both those two region variables to `'a` on its
+    // side.
+    with_signature(cell, t, |cell, t| require(cell, t));
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr
new file mode 100644
index 0000000..0fa4060
--- /dev/null
+++ b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr
@@ -0,0 +1,191 @@
+note: External requirements
+  --> $DIR/projection-one-region-trait-bound-closure.rs:37:29
+   |
+LL |     with_signature(cell, t, |cell, t| require(cell, t));
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:19 ~ projection_one_region_trait_bound_closure[317d]::no_relationships_late[0]::{{closure}}[0]) with closure substs [
+               '_#1r,
+               T,
+               i32,
+               extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)),
+           ]
+   = note: late-bound region is '_#3r
+   = note: number of external vids: 4
+   = note: where '_#1r: '_#2r
+
+note: No external requirements
+  --> $DIR/projection-one-region-trait-bound-closure.rs:33:1
+   |
+LL | / fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
+LL | | where
+LL | |     T: Anything<'b>,
+LL | | {
+LL | |     with_signature(cell, t, |cell, t| require(cell, t));
+LL | |
+LL | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:8 ~ projection_one_region_trait_bound_closure[317d]::no_relationships_late[0]) with substs [
+               '_#1r,
+               T,
+           ]
+
+error: lifetime may not live long enough
+  --> $DIR/projection-one-region-trait-bound-closure.rs:37:39
+   |
+LL | fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
+   |                          --  -- lifetime `'b` defined here
+   |                          |
+   |                          lifetime `'a` defined here
+...
+LL |     with_signature(cell, t, |cell, t| require(cell, t));
+   |                                       ^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a`
+
+note: External requirements
+  --> $DIR/projection-one-region-trait-bound-closure.rs:47:29
+   |
+LL |     with_signature(cell, t, |cell, t| require(cell, t));
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:23 ~ projection_one_region_trait_bound_closure[317d]::no_relationships_early[0]::{{closure}}[0]) with closure substs [
+               '_#1r,
+               '_#2r,
+               T,
+               i32,
+               extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)),
+           ]
+   = note: number of external vids: 4
+   = note: where '_#2r: '_#3r
+
+note: No external requirements
+  --> $DIR/projection-one-region-trait-bound-closure.rs:42:1
+   |
+LL | / fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
+LL | | where
+LL | |     T: Anything<'b>,
+LL | |     'a: 'a,
+...  |
+LL | |
+LL | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:9 ~ projection_one_region_trait_bound_closure[317d]::no_relationships_early[0]) with substs [
+               '_#1r,
+               '_#2r,
+               T,
+           ]
+
+error: lifetime may not live long enough
+  --> $DIR/projection-one-region-trait-bound-closure.rs:47:39
+   |
+LL | fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
+   |                           --  -- lifetime `'b` defined here
+   |                           |
+   |                           lifetime `'a` defined here
+...
+LL |     with_signature(cell, t, |cell, t| require(cell, t));
+   |                                       ^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a`
+
+note: External requirements
+  --> $DIR/projection-one-region-trait-bound-closure.rs:60:29
+   |
+LL |     with_signature(cell, t, |cell, t| require(cell, t));
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:27 ~ projection_one_region_trait_bound_closure[317d]::projection_outlives[0]::{{closure}}[0]) with closure substs [
+               '_#1r,
+               '_#2r,
+               T,
+               i32,
+               extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)),
+           ]
+   = note: number of external vids: 4
+   = note: where <T as Anything<ReClosureBound('_#2r)>>::AssocType: '_#3r
+
+note: No external requirements
+  --> $DIR/projection-one-region-trait-bound-closure.rs:52:1
+   |
+LL | / fn projection_outlives<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
+LL | | where
+LL | |     T: Anything<'b>,
+LL | |     T::AssocType: 'a,
+...  |
+LL | |     with_signature(cell, t, |cell, t| require(cell, t));
+LL | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:10 ~ projection_one_region_trait_bound_closure[317d]::projection_outlives[0]) with substs [
+               '_#1r,
+               '_#2r,
+               T,
+           ]
+
+note: External requirements
+  --> $DIR/projection-one-region-trait-bound-closure.rs:69:29
+   |
+LL |     with_signature(cell, t, |cell, t| require(cell, t));
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:31 ~ projection_one_region_trait_bound_closure[317d]::elements_outlive[0]::{{closure}}[0]) with closure substs [
+               '_#1r,
+               '_#2r,
+               T,
+               i32,
+               extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)),
+           ]
+   = note: number of external vids: 4
+   = note: where '_#2r: '_#3r
+
+note: No external requirements
+  --> $DIR/projection-one-region-trait-bound-closure.rs:64:1
+   |
+LL | / fn elements_outlive<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
+LL | | where
+LL | |     T: Anything<'b>,
+LL | |     'b: 'a,
+LL | | {
+LL | |     with_signature(cell, t, |cell, t| require(cell, t));
+LL | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:11 ~ projection_one_region_trait_bound_closure[317d]::elements_outlive[0]) with substs [
+               '_#1r,
+               '_#2r,
+               T,
+           ]
+
+note: External requirements
+  --> $DIR/projection-one-region-trait-bound-closure.rs:81:29
+   |
+LL |     with_signature(cell, t, |cell, t| require(cell, t));
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:34 ~ projection_one_region_trait_bound_closure[317d]::one_region[0]::{{closure}}[0]) with closure substs [
+               '_#1r,
+               T,
+               i32,
+               extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)),
+           ]
+   = note: number of external vids: 3
+   = note: where '_#1r: '_#2r
+
+note: No external requirements
+  --> $DIR/projection-one-region-trait-bound-closure.rs:73:1
+   |
+LL | / fn one_region<'a, T>(cell: Cell<&'a ()>, t: T)
+LL | | where
+LL | |     T: Anything<'a>,
+LL | | {
+...  |
+LL | |     with_signature(cell, t, |cell, t| require(cell, t));
+LL | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:12 ~ projection_one_region_trait_bound_closure[317d]::one_region[0]) with substs [
+               '_#1r,
+               T,
+           ]
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.rs b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.rs
new file mode 100644
index 0000000..452a8ea
--- /dev/null
+++ b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.rs
@@ -0,0 +1,88 @@
+// Test cases where we constrain `<T as Anything<'b>>::AssocType` to
+// outlive `'static`. In this case, we don't get any errors, and in fact
+// we don't even propagate constraints from the closures to the callers.
+
+// compile-flags:-Zborrowck=mir -Zverbose
+// compile-pass
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+
+use std::cell::Cell;
+
+trait Anything<'a> {
+    type AssocType: 'static;
+}
+
+fn with_signature<'a, T, F>(cell: Cell<&'a ()>, t: T, op: F)
+where
+    F: FnOnce(Cell<&'a ()>, T),
+{
+    op(cell, t)
+}
+
+fn require<'a, 'b, T>(_cell: Cell<&'a ()>, _t: T)
+where
+    T: Anything<'b>,
+    T::AssocType: 'a,
+{
+}
+
+#[rustc_regions]
+fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
+where
+    T: Anything<'b>,
+{
+    with_signature(cell, t, |cell, t| require(cell, t));
+}
+
+#[rustc_regions]
+fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
+where
+    T: Anything<'b>,
+    'a: 'a,
+{
+    with_signature(cell, t, |cell, t| require(cell, t));
+}
+
+#[rustc_regions]
+fn projection_outlives<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
+where
+    T: Anything<'b>,
+    T::AssocType: 'a,
+{
+    // This error is unfortunate. This code ought to type-check: we
+    // are projecting `<T as Anything<'b>>::AssocType`, and we know
+    // that this outlives `'a` because of the where-clause. However,
+    // the way the region checker works, we don't register this
+    // outlives obligation, and hence we get an error: this is because
+    // what we see is a projection like `<T as
+    // Anything<'?0>>::AssocType`, and we don't yet know if `?0` will
+    // equal `'b` or not, so we ignore the where-clause. Obviously we
+    // can do better here with a more involved verification step.
+
+    with_signature(cell, t, |cell, t| require(cell, t));
+}
+
+#[rustc_regions]
+fn elements_outlive<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
+where
+    T: Anything<'b>,
+    'b: 'a,
+{
+    with_signature(cell, t, |cell, t| require(cell, t));
+}
+
+#[rustc_regions]
+fn one_region<'a, T>(cell: Cell<&'a ()>, t: T)
+where
+    T: Anything<'a>,
+{
+    // Note that in this case the closure still propagates an external
+    // requirement between two variables in its signature, but the
+    // creator maps both those two region variables to `'a` on its
+    // side.
+    with_signature(cell, t, |cell, t| require(cell, t));
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr
new file mode 100644
index 0000000..f616a7f
--- /dev/null
+++ b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr
@@ -0,0 +1,156 @@
+note: No external requirements
+  --> $DIR/projection-one-region-trait-bound-static-closure.rs:36:29
+   |
+LL |     with_signature(cell, t, |cell, t| require(cell, t));
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:19 ~ projection_one_region_trait_bound_static_closure[317d]::no_relationships_late[0]::{{closure}}[0]) with closure substs [
+               '_#1r,
+               T,
+               i32,
+               extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)),
+           ]
+   = note: late-bound region is '_#3r
+
+note: No external requirements
+  --> $DIR/projection-one-region-trait-bound-static-closure.rs:32:1
+   |
+LL | / fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
+LL | | where
+LL | |     T: Anything<'b>,
+LL | | {
+LL | |     with_signature(cell, t, |cell, t| require(cell, t));
+LL | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:8 ~ projection_one_region_trait_bound_static_closure[317d]::no_relationships_late[0]) with substs [
+               '_#1r,
+               T,
+           ]
+
+note: No external requirements
+  --> $DIR/projection-one-region-trait-bound-static-closure.rs:45:29
+   |
+LL |     with_signature(cell, t, |cell, t| require(cell, t));
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:23 ~ projection_one_region_trait_bound_static_closure[317d]::no_relationships_early[0]::{{closure}}[0]) with closure substs [
+               '_#1r,
+               '_#2r,
+               T,
+               i32,
+               extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)),
+           ]
+
+note: No external requirements
+  --> $DIR/projection-one-region-trait-bound-static-closure.rs:40:1
+   |
+LL | / fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
+LL | | where
+LL | |     T: Anything<'b>,
+LL | |     'a: 'a,
+LL | | {
+LL | |     with_signature(cell, t, |cell, t| require(cell, t));
+LL | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:9 ~ projection_one_region_trait_bound_static_closure[317d]::no_relationships_early[0]) with substs [
+               '_#1r,
+               '_#2r,
+               T,
+           ]
+
+note: No external requirements
+  --> $DIR/projection-one-region-trait-bound-static-closure.rs:64:29
+   |
+LL |     with_signature(cell, t, |cell, t| require(cell, t));
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:27 ~ projection_one_region_trait_bound_static_closure[317d]::projection_outlives[0]::{{closure}}[0]) with closure substs [
+               '_#1r,
+               '_#2r,
+               T,
+               i32,
+               extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)),
+           ]
+
+note: No external requirements
+  --> $DIR/projection-one-region-trait-bound-static-closure.rs:49:1
+   |
+LL | / fn projection_outlives<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
+LL | | where
+LL | |     T: Anything<'b>,
+LL | |     T::AssocType: 'a,
+...  |
+LL | |     with_signature(cell, t, |cell, t| require(cell, t));
+LL | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:10 ~ projection_one_region_trait_bound_static_closure[317d]::projection_outlives[0]) with substs [
+               '_#1r,
+               '_#2r,
+               T,
+           ]
+
+note: No external requirements
+  --> $DIR/projection-one-region-trait-bound-static-closure.rs:73:29
+   |
+LL |     with_signature(cell, t, |cell, t| require(cell, t));
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:31 ~ projection_one_region_trait_bound_static_closure[317d]::elements_outlive[0]::{{closure}}[0]) with closure substs [
+               '_#1r,
+               '_#2r,
+               T,
+               i32,
+               extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)),
+           ]
+
+note: No external requirements
+  --> $DIR/projection-one-region-trait-bound-static-closure.rs:68:1
+   |
+LL | / fn elements_outlive<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
+LL | | where
+LL | |     T: Anything<'b>,
+LL | |     'b: 'a,
+LL | | {
+LL | |     with_signature(cell, t, |cell, t| require(cell, t));
+LL | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:11 ~ projection_one_region_trait_bound_static_closure[317d]::elements_outlive[0]) with substs [
+               '_#1r,
+               '_#2r,
+               T,
+           ]
+
+note: No external requirements
+  --> $DIR/projection-one-region-trait-bound-static-closure.rs:85:29
+   |
+LL |     with_signature(cell, t, |cell, t| require(cell, t));
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:34 ~ projection_one_region_trait_bound_static_closure[317d]::one_region[0]::{{closure}}[0]) with closure substs [
+               '_#1r,
+               T,
+               i32,
+               extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)),
+           ]
+
+note: No external requirements
+  --> $DIR/projection-one-region-trait-bound-static-closure.rs:77:1
+   |
+LL | / fn one_region<'a, T>(cell: Cell<&'a ()>, t: T)
+LL | | where
+LL | |     T: Anything<'a>,
+LL | | {
+...  |
+LL | |     with_signature(cell, t, |cell, t| require(cell, t));
+LL | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:12 ~ projection_one_region_trait_bound_static_closure[317d]::one_region[0]) with substs [
+               '_#1r,
+               T,
+           ]
+
diff --git a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.rs b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.rs
new file mode 100644
index 0000000..20edfb3
--- /dev/null
+++ b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.rs
@@ -0,0 +1,112 @@
+// Test cases where we constrain `<T as Anything<'a, 'b>>::AssocType`
+// to outlive `'a` and there are two bounds in the trait definition of
+// `Anything` -- i.e., we know that `AssocType` outlives `'a` and
+// `'b`. In this case, it's not clear what is the best way to satisfy
+// the trait bound, and hence we propagate it to the caller as a type
+// test.
+
+// compile-flags:-Zborrowck=mir -Zverbose
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+
+use std::cell::Cell;
+
+trait Anything<'a, 'b> {
+    type AssocType: 'a + 'b;
+}
+
+fn with_signature<'a, T, F>(cell: Cell<&'a ()>, t: T, op: F)
+where
+    F: FnOnce(Cell<&'a ()>, T),
+{
+    op(cell, t)
+}
+
+fn require<'a, 'b, 'c, T>(_cell: Cell<&'a ()>, _t: T)
+where
+    T: Anything<'b, 'c>,
+    T::AssocType: 'a,
+{
+}
+
+#[rustc_regions]
+fn no_relationships_late<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T)
+where
+    T: Anything<'b, 'c>,
+{
+    with_signature(cell, t, |cell, t| require(cell, t));
+    //~^ ERROR associated type `<T as Anything<'_#5r, '_#6r>>::AssocType` may not live long enough
+}
+
+#[rustc_regions]
+fn no_relationships_early<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T)
+where
+    T: Anything<'b, 'c>,
+    'a: 'a,
+{
+    with_signature(cell, t, |cell, t| require(cell, t));
+    //~^ ERROR associated type `<T as Anything<'_#6r, '_#7r>>::AssocType` may not live long enough
+}
+
+#[rustc_regions]
+fn projection_outlives<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T)
+where
+    T: Anything<'b, 'c>,
+    T::AssocType: 'a,
+{
+    // We are projecting `<T as Anything<'b>>::AssocType`, and we know
+    // that this outlives `'a` because of the where-clause.
+
+    with_signature(cell, t, |cell, t| require(cell, t));
+}
+
+#[rustc_regions]
+fn elements_outlive1<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T)
+where
+    T: Anything<'b, 'c>,
+    'b: 'a,
+{
+    with_signature(cell, t, |cell, t| require(cell, t));
+}
+
+#[rustc_regions]
+fn elements_outlive2<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T)
+where
+    T: Anything<'b, 'c>,
+    'c: 'a,
+{
+    with_signature(cell, t, |cell, t| require(cell, t));
+}
+
+#[rustc_regions]
+fn two_regions<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
+where
+    T: Anything<'b, 'b>,
+{
+    with_signature(cell, t, |cell, t| require(cell, t));
+    //~^ ERROR lifetime may not live long enough
+}
+
+#[rustc_regions]
+fn two_regions_outlive<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
+where
+    T: Anything<'b, 'b>,
+    'b: 'a,
+{
+    with_signature(cell, t, |cell, t| require(cell, t));
+}
+
+#[rustc_regions]
+fn one_region<'a, T>(cell: Cell<&'a ()>, t: T)
+where
+    T: Anything<'a, 'a>,
+{
+    // Note that in this case the closure still propagates an external
+    // requirement between two variables in its signature, but the
+    // creator maps both those two region variables to `'a` on its
+    // side.
+    with_signature(cell, t, |cell, t| require(cell, t));
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr
new file mode 100644
index 0000000..b761b03
--- /dev/null
+++ b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr
@@ -0,0 +1,308 @@
+note: External requirements
+  --> $DIR/projection-two-region-trait-bound-closure.rs:38:29
+   |
+LL |     with_signature(cell, t, |cell, t| require(cell, t));
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:22 ~ projection_two_region_trait_bound_closure[317d]::no_relationships_late[0]::{{closure}}[0]) with closure substs [
+               '_#1r,
+               '_#2r,
+               T,
+               i32,
+               extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)),
+           ]
+   = note: late-bound region is '_#4r
+   = note: number of external vids: 5
+   = note: where <T as Anything<ReClosureBound('_#1r), ReClosureBound('_#2r)>>::AssocType: '_#3r
+
+note: No external requirements
+  --> $DIR/projection-two-region-trait-bound-closure.rs:34:1
+   |
+LL | / fn no_relationships_late<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T)
+LL | | where
+LL | |     T: Anything<'b, 'c>,
+LL | | {
+LL | |     with_signature(cell, t, |cell, t| require(cell, t));
+LL | |
+LL | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:8 ~ projection_two_region_trait_bound_closure[317d]::no_relationships_late[0]) with substs [
+               '_#1r,
+               '_#2r,
+               T,
+           ]
+
+error[E0309]: the associated type `<T as Anything<'_#5r, '_#6r>>::AssocType` may not live long enough
+  --> $DIR/projection-two-region-trait-bound-closure.rs:38:29
+   |
+LL |     with_signature(cell, t, |cell, t| require(cell, t));
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding an explicit lifetime bound `<T as Anything<'_#5r, '_#6r>>::AssocType: ReFree(DefId(0/0:8 ~ projection_two_region_trait_bound_closure[317d]::no_relationships_late[0]), BrNamed(crate0:DefIndex(1:18), 'a))`...
+
+note: External requirements
+  --> $DIR/projection-two-region-trait-bound-closure.rs:48:29
+   |
+LL |     with_signature(cell, t, |cell, t| require(cell, t));
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:27 ~ projection_two_region_trait_bound_closure[317d]::no_relationships_early[0]::{{closure}}[0]) with closure substs [
+               '_#1r,
+               '_#2r,
+               '_#3r,
+               T,
+               i32,
+               extern "rust-call" fn((std::cell::Cell<&'_#4r ()>, T)),
+           ]
+   = note: number of external vids: 5
+   = note: where <T as Anything<ReClosureBound('_#2r), ReClosureBound('_#3r)>>::AssocType: '_#4r
+
+note: No external requirements
+  --> $DIR/projection-two-region-trait-bound-closure.rs:43:1
+   |
+LL | / fn no_relationships_early<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T)
+LL | | where
+LL | |     T: Anything<'b, 'c>,
+LL | |     'a: 'a,
+...  |
+LL | |
+LL | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:9 ~ projection_two_region_trait_bound_closure[317d]::no_relationships_early[0]) with substs [
+               '_#1r,
+               '_#2r,
+               '_#3r,
+               T,
+           ]
+
+error[E0309]: the associated type `<T as Anything<'_#6r, '_#7r>>::AssocType` may not live long enough
+  --> $DIR/projection-two-region-trait-bound-closure.rs:48:29
+   |
+LL |     with_signature(cell, t, |cell, t| require(cell, t));
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding an explicit lifetime bound `<T as Anything<'_#6r, '_#7r>>::AssocType: ReEarlyBound(0, 'a)`...
+
+note: External requirements
+  --> $DIR/projection-two-region-trait-bound-closure.rs:61:29
+   |
+LL |     with_signature(cell, t, |cell, t| require(cell, t));
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:32 ~ projection_two_region_trait_bound_closure[317d]::projection_outlives[0]::{{closure}}[0]) with closure substs [
+               '_#1r,
+               '_#2r,
+               '_#3r,
+               T,
+               i32,
+               extern "rust-call" fn((std::cell::Cell<&'_#4r ()>, T)),
+           ]
+   = note: number of external vids: 5
+   = note: where <T as Anything<ReClosureBound('_#2r), ReClosureBound('_#3r)>>::AssocType: '_#4r
+
+note: No external requirements
+  --> $DIR/projection-two-region-trait-bound-closure.rs:53:1
+   |
+LL | / fn projection_outlives<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T)
+LL | | where
+LL | |     T: Anything<'b, 'c>,
+LL | |     T::AssocType: 'a,
+...  |
+LL | |     with_signature(cell, t, |cell, t| require(cell, t));
+LL | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:10 ~ projection_two_region_trait_bound_closure[317d]::projection_outlives[0]) with substs [
+               '_#1r,
+               '_#2r,
+               '_#3r,
+               T,
+           ]
+
+note: External requirements
+  --> $DIR/projection-two-region-trait-bound-closure.rs:70:29
+   |
+LL |     with_signature(cell, t, |cell, t| require(cell, t));
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:37 ~ projection_two_region_trait_bound_closure[317d]::elements_outlive1[0]::{{closure}}[0]) with closure substs [
+               '_#1r,
+               '_#2r,
+               '_#3r,
+               T,
+               i32,
+               extern "rust-call" fn((std::cell::Cell<&'_#4r ()>, T)),
+           ]
+   = note: number of external vids: 5
+   = note: where <T as Anything<ReClosureBound('_#2r), ReClosureBound('_#3r)>>::AssocType: '_#4r
+
+note: No external requirements
+  --> $DIR/projection-two-region-trait-bound-closure.rs:65:1
+   |
+LL | / fn elements_outlive1<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T)
+LL | | where
+LL | |     T: Anything<'b, 'c>,
+LL | |     'b: 'a,
+LL | | {
+LL | |     with_signature(cell, t, |cell, t| require(cell, t));
+LL | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:11 ~ projection_two_region_trait_bound_closure[317d]::elements_outlive1[0]) with substs [
+               '_#1r,
+               '_#2r,
+               '_#3r,
+               T,
+           ]
+
+note: External requirements
+  --> $DIR/projection-two-region-trait-bound-closure.rs:79:29
+   |
+LL |     with_signature(cell, t, |cell, t| require(cell, t));
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:42 ~ projection_two_region_trait_bound_closure[317d]::elements_outlive2[0]::{{closure}}[0]) with closure substs [
+               '_#1r,
+               '_#2r,
+               '_#3r,
+               T,
+               i32,
+               extern "rust-call" fn((std::cell::Cell<&'_#4r ()>, T)),
+           ]
+   = note: number of external vids: 5
+   = note: where <T as Anything<ReClosureBound('_#2r), ReClosureBound('_#3r)>>::AssocType: '_#4r
+
+note: No external requirements
+  --> $DIR/projection-two-region-trait-bound-closure.rs:74:1
+   |
+LL | / fn elements_outlive2<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T)
+LL | | where
+LL | |     T: Anything<'b, 'c>,
+LL | |     'c: 'a,
+LL | | {
+LL | |     with_signature(cell, t, |cell, t| require(cell, t));
+LL | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:12 ~ projection_two_region_trait_bound_closure[317d]::elements_outlive2[0]) with substs [
+               '_#1r,
+               '_#2r,
+               '_#3r,
+               T,
+           ]
+
+note: External requirements
+  --> $DIR/projection-two-region-trait-bound-closure.rs:87:29
+   |
+LL |     with_signature(cell, t, |cell, t| require(cell, t));
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:46 ~ projection_two_region_trait_bound_closure[317d]::two_regions[0]::{{closure}}[0]) with closure substs [
+               '_#1r,
+               T,
+               i32,
+               extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)),
+           ]
+   = note: late-bound region is '_#3r
+   = note: number of external vids: 4
+   = note: where <T as Anything<ReClosureBound('_#1r), ReClosureBound('_#1r)>>::AssocType: '_#2r
+
+note: No external requirements
+  --> $DIR/projection-two-region-trait-bound-closure.rs:83:1
+   |
+LL | / fn two_regions<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
+LL | | where
+LL | |     T: Anything<'b, 'b>,
+LL | | {
+LL | |     with_signature(cell, t, |cell, t| require(cell, t));
+LL | |
+LL | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:13 ~ projection_two_region_trait_bound_closure[317d]::two_regions[0]) with substs [
+               '_#1r,
+               T,
+           ]
+
+error: lifetime may not live long enough
+  --> $DIR/projection-two-region-trait-bound-closure.rs:87:29
+   |
+LL | fn two_regions<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
+   |                --  -- lifetime `'b` defined here
+   |                |
+   |                lifetime `'a` defined here
+...
+LL |     with_signature(cell, t, |cell, t| require(cell, t));
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^ closure body requires that `'b` must outlive `'a`
+
+note: External requirements
+  --> $DIR/projection-two-region-trait-bound-closure.rs:97:29
+   |
+LL |     with_signature(cell, t, |cell, t| require(cell, t));
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:50 ~ projection_two_region_trait_bound_closure[317d]::two_regions_outlive[0]::{{closure}}[0]) with closure substs [
+               '_#1r,
+               '_#2r,
+               T,
+               i32,
+               extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)),
+           ]
+   = note: number of external vids: 4
+   = note: where <T as Anything<ReClosureBound('_#2r), ReClosureBound('_#2r)>>::AssocType: '_#3r
+
+note: No external requirements
+  --> $DIR/projection-two-region-trait-bound-closure.rs:92:1
+   |
+LL | / fn two_regions_outlive<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
+LL | | where
+LL | |     T: Anything<'b, 'b>,
+LL | |     'b: 'a,
+LL | | {
+LL | |     with_signature(cell, t, |cell, t| require(cell, t));
+LL | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:14 ~ projection_two_region_trait_bound_closure[317d]::two_regions_outlive[0]) with substs [
+               '_#1r,
+               '_#2r,
+               T,
+           ]
+
+note: External requirements
+  --> $DIR/projection-two-region-trait-bound-closure.rs:109:29
+   |
+LL |     with_signature(cell, t, |cell, t| require(cell, t));
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:53 ~ projection_two_region_trait_bound_closure[317d]::one_region[0]::{{closure}}[0]) with closure substs [
+               '_#1r,
+               T,
+               i32,
+               extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)),
+           ]
+   = note: number of external vids: 3
+   = note: where <T as Anything<ReClosureBound('_#1r), ReClosureBound('_#1r)>>::AssocType: '_#2r
+
+note: No external requirements
+  --> $DIR/projection-two-region-trait-bound-closure.rs:101:1
+   |
+LL | / fn one_region<'a, T>(cell: Cell<&'a ()>, t: T)
+LL | | where
+LL | |     T: Anything<'a, 'a>,
+LL | | {
+...  |
+LL | |     with_signature(cell, t, |cell, t| require(cell, t));
+LL | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:15 ~ projection_two_region_trait_bound_closure[317d]::one_region[0]) with substs [
+               '_#1r,
+               T,
+           ]
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0309`.
diff --git a/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-bound.rs b/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-bound.rs
new file mode 100644
index 0000000..9c2cbfd
--- /dev/null
+++ b/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-bound.rs
@@ -0,0 +1,36 @@
+#![feature(nll)]
+
+// Test that we are able to establish that `<T as
+// MyTrait<'a>>::Output` outlives `'b` here. We need to prove however
+// that `<T as MyTrait<'a>>::Output` outlives `'a`, so we also have to
+// prove that `'b: 'a`.
+
+trait MyTrait<'a> {
+    type Output;
+}
+
+fn foo1<'a, 'b, T>() -> &'a ()
+where
+    T: MyTrait<'a>,
+    <T as MyTrait<'a>>::Output: 'b,
+{
+    bar::<T::Output>() //~ ERROR may not live long enough
+}
+
+fn foo2<'a, 'b, T>() -> &'a ()
+where
+    T: MyTrait<'a>,
+    <T as MyTrait<'a>>::Output: 'b,
+    'b: 'a,
+{
+    bar::<T::Output>() // OK
+}
+
+fn bar<'a, T>() -> &'a ()
+where
+    T: 'a,
+{
+    &()
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-bound.stderr b/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-bound.stderr
new file mode 100644
index 0000000..1aed0a5
--- /dev/null
+++ b/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-bound.stderr
@@ -0,0 +1,11 @@
+error[E0309]: the associated type `<T as MyTrait<'_>>::Output` may not live long enough
+  --> $DIR/projection-where-clause-env-wrong-bound.rs:17:5
+   |
+LL |     bar::<T::Output>()
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding an explicit lifetime bound `<T as MyTrait<'_>>::Output: 'a`...
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0309`.
diff --git a/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-lifetime.rs b/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-lifetime.rs
new file mode 100644
index 0000000..9e3590c
--- /dev/null
+++ b/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-lifetime.rs
@@ -0,0 +1,25 @@
+// Test that if we need to prove that `<T as MyTrait<'a>>::Output:
+// 'a`, but we only know that `<T as MyTrait<'b>>::Output: 'a`, that
+// doesn't suffice.
+
+trait MyTrait<'a> {
+    type Output;
+}
+
+fn foo1<'a, 'b, T>() -> &'a ()
+where
+    for<'x> T: MyTrait<'x>,
+    <T as MyTrait<'b>>::Output: 'a,
+{
+    bar::<<T as MyTrait<'a>>::Output>()
+    //~^ ERROR the associated type `<T as MyTrait<'a>>::Output` may not live long enough
+}
+
+fn bar<'a, T>() -> &'a ()
+where
+    T: 'a,
+{
+    &()
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-lifetime.stderr b/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-lifetime.stderr
new file mode 100644
index 0000000..d6ade2a6
--- /dev/null
+++ b/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-lifetime.stderr
@@ -0,0 +1,16 @@
+error[E0309]: the associated type `<T as MyTrait<'a>>::Output` may not live long enough
+  --> $DIR/projection-where-clause-env-wrong-lifetime.rs:14:5
+   |
+LL |     bar::<<T as MyTrait<'a>>::Output>()
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding an explicit lifetime bound `<T as MyTrait<'a>>::Output: 'a`...
+note: ...so that the type `<T as MyTrait<'a>>::Output` will meet its required lifetime bounds
+  --> $DIR/projection-where-clause-env-wrong-lifetime.rs:14:5
+   |
+LL |     bar::<<T as MyTrait<'a>>::Output>()
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0309`.
diff --git a/src/test/ui/nll/ty-outlives/projection-where-clause-env.rs b/src/test/ui/nll/ty-outlives/projection-where-clause-env.rs
new file mode 100644
index 0000000..c6935ba
--- /dev/null
+++ b/src/test/ui/nll/ty-outlives/projection-where-clause-env.rs
@@ -0,0 +1,30 @@
+#![feature(nll)]
+
+// Test that when we have a `<T as MyTrait<'a>>::Output: 'a`
+// relationship in the environment we take advantage of it.  In this
+// case, that means we **don't** have to prove that `T: 'a`.
+//
+// Regression test for #53121.
+//
+// compile-pass
+
+trait MyTrait<'a> {
+    type Output;
+}
+
+fn foo<'a, T>() -> &'a ()
+where
+    T: MyTrait<'a>,
+    <T as MyTrait<'a>>::Output: 'a,
+{
+    bar::<T::Output>()
+}
+
+fn bar<'a, T>() -> &'a ()
+where
+    T: 'a,
+{
+    &()
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/ty-outlives/projection-where-clause-none.rs b/src/test/ui/nll/ty-outlives/projection-where-clause-none.rs
new file mode 100644
index 0000000..f0f72f5
--- /dev/null
+++ b/src/test/ui/nll/ty-outlives/projection-where-clause-none.rs
@@ -0,0 +1,26 @@
+#![feature(nll)]
+
+// Test that we are NOT able to establish that `<T as
+// MyTrait<'a>>::Output: 'a` outlives `'a` here -- we have only one
+// recourse, which is to prove that `T: 'a` and `'a: 'a`, but we don't
+// know that `T: 'a`.
+
+trait MyTrait<'a> {
+    type Output;
+}
+
+fn foo<'a, T>() -> &'a ()
+where
+    T: MyTrait<'a>,
+{
+    bar::<T::Output>() //~ ERROR the parameter type `T` may not live long enough
+}
+
+fn bar<'a, T>() -> &'a ()
+where
+    T: 'a,
+{
+    &()
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/ty-outlives/projection-where-clause-none.stderr b/src/test/ui/nll/ty-outlives/projection-where-clause-none.stderr
new file mode 100644
index 0000000..8175c30
--- /dev/null
+++ b/src/test/ui/nll/ty-outlives/projection-where-clause-none.stderr
@@ -0,0 +1,11 @@
+error[E0309]: the parameter type `T` may not live long enough
+  --> $DIR/projection-where-clause-none.rs:16:5
+   |
+LL |     bar::<T::Output>()
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding an explicit lifetime bound `T: 'a`...
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0309`.
diff --git a/src/test/ui/nll/ty-outlives/projection-where-clause-trait.rs b/src/test/ui/nll/ty-outlives/projection-where-clause-trait.rs
new file mode 100644
index 0000000..7c7d64a
--- /dev/null
+++ b/src/test/ui/nll/ty-outlives/projection-where-clause-trait.rs
@@ -0,0 +1,27 @@
+#![feature(nll)]
+
+// Test that we are able to establish that `<T as
+// MyTrait<'a>>::Output: 'a` outlives `'a` (because the trait says
+// so).
+//
+// compile-pass
+
+trait MyTrait<'a> {
+    type Output: 'a;
+}
+
+fn foo<'a, T>() -> &'a ()
+where
+    T: MyTrait<'a>,
+{
+    bar::<T::Output>()
+}
+
+fn bar<'a, T>() -> &'a ()
+where
+    T: 'a,
+{
+    &()
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.rs b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.rs
new file mode 100644
index 0000000..fd36e75
--- /dev/null
+++ b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.rs
@@ -0,0 +1,39 @@
+// compile-flags:-Zborrowck=mir -Zverbose
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+
+use std::cell::Cell;
+
+// Invoke in such a way that the callee knows:
+//
+// - 'a: 'x
+//
+// and it must prove that `T: 'x`. Callee passes along `T: 'a`.
+fn twice<'a, F, T>(v: Cell<&'a ()>, value: T, mut f: F)
+where
+    F: for<'x> FnMut(Option<Cell<&'a &'x ()>>, &T),
+{
+    f(None, &value);
+    f(None, &value);
+}
+
+#[rustc_regions]
+fn generic<T>(value: T) {
+    let cell = Cell::new(&());
+    twice(cell, value, |a, b| invoke(a, b));
+}
+
+#[rustc_regions]
+fn generic_fail<'a, T>(cell: Cell<&'a ()>, value: T) {
+    twice(cell, value, |a, b| invoke(a, b));
+    //~^ ERROR the parameter type `T` may not live long enough
+}
+
+fn invoke<'a, 'x, T>(x: Option<Cell<&'x &'a ()>>, y: &T)
+where
+    T: 'x,
+{
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr
new file mode 100644
index 0000000..6f3071b
--- /dev/null
+++ b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr
@@ -0,0 +1,66 @@
+note: External requirements
+  --> $DIR/ty-param-closure-approximate-lower-bound.rs:24:24
+   |
+LL |     twice(cell, value, |a, b| invoke(a, b));
+   |                        ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:14 ~ ty_param_closure_approximate_lower_bound[317d]::generic[0]::{{closure}}[0]) with closure substs [
+               T,
+               i16,
+               for<'r, 's> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) ()>>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) T)),
+           ]
+   = note: number of external vids: 2
+   = note: where T: '_#1r
+
+note: No external requirements
+  --> $DIR/ty-param-closure-approximate-lower-bound.rs:22:1
+   |
+LL | / fn generic<T>(value: T) {
+LL | |     let cell = Cell::new(&());
+LL | |     twice(cell, value, |a, b| invoke(a, b));
+LL | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:5 ~ ty_param_closure_approximate_lower_bound[317d]::generic[0]) with substs [
+               T,
+           ]
+
+note: External requirements
+  --> $DIR/ty-param-closure-approximate-lower-bound.rs:29:24
+   |
+LL |     twice(cell, value, |a, b| invoke(a, b));
+   |                        ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:17 ~ ty_param_closure_approximate_lower_bound[317d]::generic_fail[0]::{{closure}}[0]) with closure substs [
+               T,
+               i16,
+               for<'r, 's> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) ()>>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) T)),
+           ]
+   = note: late-bound region is '_#2r
+   = note: number of external vids: 3
+   = note: where T: '_#1r
+
+note: No external requirements
+  --> $DIR/ty-param-closure-approximate-lower-bound.rs:28:1
+   |
+LL | / fn generic_fail<'a, T>(cell: Cell<&'a ()>, value: T) {
+LL | |     twice(cell, value, |a, b| invoke(a, b));
+LL | |
+LL | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:6 ~ ty_param_closure_approximate_lower_bound[317d]::generic_fail[0]) with substs [
+               T,
+           ]
+
+error[E0309]: the parameter type `T` may not live long enough
+  --> $DIR/ty-param-closure-approximate-lower-bound.rs:29:24
+   |
+LL |     twice(cell, value, |a, b| invoke(a, b));
+   |                        ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:6 ~ ty_param_closure_approximate_lower_bound[317d]::generic_fail[0]), BrNamed(crate0:DefIndex(1:15), 'a))`...
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0309`.
diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.rs b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.rs
new file mode 100644
index 0000000..7fce771
--- /dev/null
+++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.rs
@@ -0,0 +1,53 @@
+// compile-flags:-Zborrowck=mir -Zverbose
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+
+use std::fmt::Debug;
+
+fn with_signature<'a, T, F>(x: Box<T>, op: F) -> Box<dyn Debug + 'a>
+    where F: FnOnce(Box<T>) -> Box<dyn Debug + 'a>
+{
+    op(x)
+}
+
+#[rustc_regions]
+fn no_region<'a, T>(x: Box<T>) -> Box<dyn Debug + 'a>
+where
+    T: Debug,
+{
+    // Here, the closure winds up being required to prove that `T:
+    // 'a`.  In principle, it could know that, except that it is
+    // type-checked in a fully generic way, and hence it winds up with
+    // a propagated requirement that `T: '_#2`, where `'_#2` appears
+    // in the return type. The caller makes the mapping from `'_#2` to
+    // `'a` (and subsequently reports an error).
+
+    with_signature(x, |y| y)
+    //~^ ERROR the parameter type `T` may not live long enough
+}
+
+fn correct_region<'a, T>(x: Box<T>) -> Box<Debug + 'a>
+where
+    T: 'a + Debug,
+{
+    x
+}
+
+fn wrong_region<'a, 'b, T>(x: Box<T>) -> Box<Debug + 'a>
+where
+    T: 'b + Debug,
+{
+    x
+    //~^ ERROR the parameter type `T` may not live long enough
+}
+
+fn outlives_region<'a, 'b, T>(x: Box<T>) -> Box<Debug + 'a>
+where
+    T: 'b + Debug,
+    'b: 'a,
+{
+    x
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr
new file mode 100644
index 0000000..cdb7157
--- /dev/null
+++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr
@@ -0,0 +1,51 @@
+note: External requirements
+  --> $DIR/ty-param-closure-outlives-from-return-type.rs:26:23
+   |
+LL |     with_signature(x, |y| y)
+   |                       ^^^^^
+   |
+   = note: defining type: DefId(0/1:14 ~ ty_param_closure_outlives_from_return_type[317d]::no_region[0]::{{closure}}[0]) with closure substs [
+               '_#1r,
+               T,
+               i32,
+               extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<(dyn std::fmt::Debug + '_#2r)>,
+           ]
+   = note: number of external vids: 3
+   = note: where T: '_#2r
+
+note: No external requirements
+  --> $DIR/ty-param-closure-outlives-from-return-type.rs:15:1
+   |
+LL | / fn no_region<'a, T>(x: Box<T>) -> Box<dyn Debug + 'a>
+LL | | where
+LL | |     T: Debug,
+LL | | {
+...  |
+LL | |
+LL | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:5 ~ ty_param_closure_outlives_from_return_type[317d]::no_region[0]) with substs [
+               '_#1r,
+               T,
+           ]
+
+error[E0309]: the parameter type `T` may not live long enough
+  --> $DIR/ty-param-closure-outlives-from-return-type.rs:26:23
+   |
+LL |     with_signature(x, |y| y)
+   |                       ^^^^^
+   |
+   = help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`...
+
+error[E0309]: the parameter type `T` may not live long enough
+  --> $DIR/ty-param-closure-outlives-from-return-type.rs:41:5
+   |
+LL |     x
+   |     ^
+   |
+   = help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`...
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0309`.
diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.rs b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.rs
new file mode 100644
index 0000000..c931728
--- /dev/null
+++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.rs
@@ -0,0 +1,83 @@
+// Test that we can propagate `T: 'a` obligations to our caller.  See
+// `correct_region` for an explanation of how this test is setup; it's
+// somewhat intricate.
+
+// compile-flags:-Zborrowck=mir -Zverbose
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+
+use std::cell::Cell;
+
+fn with_signature<'a, T, F>(a: Cell<&'a ()>, b: T, op: F)
+where
+    F: FnOnce(Cell<&'a ()>, T),
+{
+    op(a, b)
+}
+
+fn require<'a, T>(_a: &Cell<&'a ()>, _b: &T)
+where
+    T: 'a,
+{
+}
+
+#[rustc_regions]
+fn no_region<'a, T>(a: Cell<&'a ()>, b: T) {
+    with_signature(a, b, |x, y| {
+        //~^ ERROR the parameter type `T` may not live long enough
+        //
+        // See `correct_region`, which explains the point of this
+        // test.  The only difference is that, in the case of this
+        // function, there is no where clause *anywhere*, and hence we
+        // get an error (but reported by the closure creator).
+        require(&x, &y)
+    })
+}
+
+#[rustc_regions]
+fn correct_region<'a, T>(a: Cell<&'a ()>, b: T)
+where
+    T: 'a,
+{
+    with_signature(a, b, |x, y| {
+        // Key point of this test:
+        //
+        // The *closure* is being type-checked with all of its free
+        // regions "universalized". In particular, it does not know
+        // that `x` has the type `Cell<&'a ()>`, but rather treats it
+        // as if the type of `x` is `Cell<&'A ()>`, where `'A` is some
+        // fresh, independent region distinct from the `'a` which
+        // appears in the environment. The call to `require` here
+        // forces us then to prove that `T: 'A`, but the closure
+        // cannot do it on its own. It has to surface this requirement
+        // to its creator (which knows that `'a == 'A`).
+        require(&x, &y)
+    })
+}
+
+#[rustc_regions]
+fn wrong_region<'a, 'b, T>(a: Cell<&'a ()>, b: T)
+where
+    T: 'b,
+{
+    with_signature(a, b, |x, y| {
+        //~^ ERROR the parameter type `T` may not live long enough
+        // See `correct_region`
+        require(&x, &y)
+    })
+}
+
+#[rustc_regions]
+fn outlives_region<'a, 'b, T>(a: Cell<&'a ()>, b: T)
+where
+    T: 'b,
+    'b: 'a,
+{
+    with_signature(a, b, |x, y| {
+        // See `correct_region`
+        require(&x, &y)
+    })
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr
new file mode 100644
index 0000000..68798a3
--- /dev/null
+++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr
@@ -0,0 +1,184 @@
+note: External requirements
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:27:26
+   |
+LL |       with_signature(a, b, |x, y| {
+   |  __________________________^
+LL | |
+LL | |         //
+LL | |         // See `correct_region`, which explains the point of this
+...  |
+LL | |         require(&x, &y)
+LL | |     })
+   | |_____^
+   |
+   = note: defining type: DefId(0/1:16 ~ ty_param_closure_outlives_from_where_clause[317d]::no_region[0]::{{closure}}[0]) with closure substs [
+               T,
+               i32,
+               extern "rust-call" fn((std::cell::Cell<&'_#1r ()>, T)),
+           ]
+   = note: late-bound region is '_#2r
+   = note: number of external vids: 3
+   = note: where T: '_#1r
+
+note: No external requirements
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:26:1
+   |
+LL | / fn no_region<'a, T>(a: Cell<&'a ()>, b: T) {
+LL | |     with_signature(a, b, |x, y| {
+LL | |
+LL | |         //
+...  |
+LL | |     })
+LL | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:6 ~ ty_param_closure_outlives_from_where_clause[317d]::no_region[0]) with substs [
+               T,
+           ]
+
+error[E0309]: the parameter type `T` may not live long enough
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:27:26
+   |
+LL |       with_signature(a, b, |x, y| {
+   |  __________________________^
+LL | |
+LL | |         //
+LL | |         // See `correct_region`, which explains the point of this
+...  |
+LL | |         require(&x, &y)
+LL | |     })
+   | |_____^
+   |
+   = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:6 ~ ty_param_closure_outlives_from_where_clause[317d]::no_region[0]), BrNamed(crate0:DefIndex(1:14), 'a))`...
+
+note: External requirements
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:43:26
+   |
+LL |       with_signature(a, b, |x, y| {
+   |  __________________________^
+LL | |         // Key point of this test:
+LL | |         //
+LL | |         // The *closure* is being type-checked with all of its free
+...  |
+LL | |         require(&x, &y)
+LL | |     })
+   | |_____^
+   |
+   = note: defining type: DefId(0/1:19 ~ ty_param_closure_outlives_from_where_clause[317d]::correct_region[0]::{{closure}}[0]) with closure substs [
+               '_#1r,
+               T,
+               i32,
+               extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)),
+           ]
+   = note: number of external vids: 3
+   = note: where T: '_#2r
+
+note: No external requirements
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:39:1
+   |
+LL | / fn correct_region<'a, T>(a: Cell<&'a ()>, b: T)
+LL | | where
+LL | |     T: 'a,
+LL | | {
+...  |
+LL | |     })
+LL | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:7 ~ ty_param_closure_outlives_from_where_clause[317d]::correct_region[0]) with substs [
+               '_#1r,
+               T,
+           ]
+
+note: External requirements
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:64:26
+   |
+LL |       with_signature(a, b, |x, y| {
+   |  __________________________^
+LL | |
+LL | |         // See `correct_region`
+LL | |         require(&x, &y)
+LL | |     })
+   | |_____^
+   |
+   = note: defining type: DefId(0/1:23 ~ ty_param_closure_outlives_from_where_clause[317d]::wrong_region[0]::{{closure}}[0]) with closure substs [
+               '_#1r,
+               T,
+               i32,
+               extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)),
+           ]
+   = note: late-bound region is '_#3r
+   = note: number of external vids: 4
+   = note: where T: '_#2r
+
+note: No external requirements
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:60:1
+   |
+LL | / fn wrong_region<'a, 'b, T>(a: Cell<&'a ()>, b: T)
+LL | | where
+LL | |     T: 'b,
+LL | | {
+...  |
+LL | |     })
+LL | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:8 ~ ty_param_closure_outlives_from_where_clause[317d]::wrong_region[0]) with substs [
+               '_#1r,
+               T,
+           ]
+
+error[E0309]: the parameter type `T` may not live long enough
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:64:26
+   |
+LL |       with_signature(a, b, |x, y| {
+   |  __________________________^
+LL | |
+LL | |         // See `correct_region`
+LL | |         require(&x, &y)
+LL | |     })
+   | |_____^
+   |
+   = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:8 ~ ty_param_closure_outlives_from_where_clause[317d]::wrong_region[0]), BrNamed(crate0:DefIndex(1:20), 'a))`...
+
+note: External requirements
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:77:26
+   |
+LL |       with_signature(a, b, |x, y| {
+   |  __________________________^
+LL | |         // See `correct_region`
+LL | |         require(&x, &y)
+LL | |     })
+   | |_____^
+   |
+   = note: defining type: DefId(0/1:27 ~ ty_param_closure_outlives_from_where_clause[317d]::outlives_region[0]::{{closure}}[0]) with closure substs [
+               '_#1r,
+               '_#2r,
+               T,
+               i32,
+               extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)),
+           ]
+   = note: number of external vids: 4
+   = note: where T: '_#3r
+
+note: No external requirements
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:72:1
+   |
+LL | / fn outlives_region<'a, 'b, T>(a: Cell<&'a ()>, b: T)
+LL | | where
+LL | |     T: 'b,
+LL | |     'b: 'a,
+...  |
+LL | |     })
+LL | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:9 ~ ty_param_closure_outlives_from_where_clause[317d]::outlives_region[0]) with substs [
+               '_#1r,
+               '_#2r,
+               T,
+           ]
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0309`.
diff --git a/src/test/ui/nll/ty-outlives/ty-param-fn-body-nll-feature.rs b/src/test/ui/nll/ty-outlives/ty-param-fn-body-nll-feature.rs
new file mode 100644
index 0000000..ec55943
--- /dev/null
+++ b/src/test/ui/nll/ty-outlives/ty-param-fn-body-nll-feature.rs
@@ -0,0 +1,30 @@
+// Test that we assume that universal types like `T` outlive the
+// function body. Same as ty-param-fn-body, but uses `feature(nll)`,
+// which affects error reporting.
+
+#![feature(nll)]
+
+#![allow(warnings)]
+
+use std::cell::Cell;
+
+// No errors here, because `'a` is local to the body.
+fn region_within_body<T>(t: T) {
+    let some_int = 22;
+    let cell = Cell::new(&some_int);
+    outlives(cell, t)
+}
+
+// Error here, because T: 'a is not satisfied.
+fn region_static<'a, T>(cell: Cell<&'a usize>, t: T) {
+    outlives(cell, t)
+    //~^ ERROR the parameter type `T` may not live long enough
+}
+
+fn outlives<'a, T>(x: Cell<&'a usize>, y: T)
+where
+    T: 'a,
+{
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/ty-outlives/ty-param-fn-body-nll-feature.stderr b/src/test/ui/nll/ty-outlives/ty-param-fn-body-nll-feature.stderr
new file mode 100644
index 0000000..b3c02f7
--- /dev/null
+++ b/src/test/ui/nll/ty-outlives/ty-param-fn-body-nll-feature.stderr
@@ -0,0 +1,11 @@
+error[E0309]: the parameter type `T` may not live long enough
+  --> $DIR/ty-param-fn-body-nll-feature.rs:20:5
+   |
+LL |     outlives(cell, t)
+   |     ^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding an explicit lifetime bound `T: 'a`...
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0309`.
diff --git a/src/test/ui/nll/ty-outlives/ty-param-fn-body.rs b/src/test/ui/nll/ty-outlives/ty-param-fn-body.rs
new file mode 100644
index 0000000..ec94258
--- /dev/null
+++ b/src/test/ui/nll/ty-outlives/ty-param-fn-body.rs
@@ -0,0 +1,29 @@
+// compile-flags:-Zborrowck=mir
+
+// Test that we assume that universal types like `T` outlive the
+// function body.
+
+#![allow(warnings)]
+
+use std::cell::Cell;
+
+// No errors here, because `'a` is local to the body.
+fn region_within_body<T>(t: T) {
+    let some_int = 22;
+    let cell = Cell::new(&some_int);
+    outlives(cell, t)
+}
+
+// Error here, because T: 'a is not satisfied.
+fn region_static<'a, T>(cell: Cell<&'a usize>, t: T) {
+    outlives(cell, t)
+    //~^ ERROR the parameter type `T` may not live long enough
+}
+
+fn outlives<'a, T>(x: Cell<&'a usize>, y: T)
+where
+    T: 'a,
+{
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/ty-outlives/ty-param-fn-body.stderr b/src/test/ui/nll/ty-outlives/ty-param-fn-body.stderr
new file mode 100644
index 0000000..9a023a0
--- /dev/null
+++ b/src/test/ui/nll/ty-outlives/ty-param-fn-body.stderr
@@ -0,0 +1,11 @@
+error[E0309]: the parameter type `T` may not live long enough
+  --> $DIR/ty-param-fn-body.rs:19:5
+   |
+LL |     outlives(cell, t)
+   |     ^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding an explicit lifetime bound `T: 'a`...
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0309`.
diff --git a/src/test/ui/nll/ty-outlives/ty-param-fn.rs b/src/test/ui/nll/ty-outlives/ty-param-fn.rs
new file mode 100644
index 0000000..a8d229f
--- /dev/null
+++ b/src/test/ui/nll/ty-outlives/ty-param-fn.rs
@@ -0,0 +1,38 @@
+// compile-flags:-Zborrowck=mir
+
+#![allow(warnings)]
+
+use std::fmt::Debug;
+
+fn no_region<'a, T>(x: Box<T>) -> Box<Debug + 'a>
+where
+    T: Debug,
+{
+    x
+    //~^ ERROR the parameter type `T` may not live long enough
+}
+
+fn correct_region<'a, T>(x: Box<T>) -> Box<Debug + 'a>
+where
+    T: 'a + Debug,
+{
+    x
+}
+
+fn wrong_region<'a, 'b, T>(x: Box<T>) -> Box<Debug + 'a>
+where
+    T: 'b + Debug,
+{
+    x
+    //~^ ERROR the parameter type `T` may not live long enough
+}
+
+fn outlives_region<'a, 'b, T>(x: Box<T>) -> Box<Debug + 'a>
+where
+    T: 'b + Debug,
+    'b: 'a,
+{
+    x
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/ty-outlives/ty-param-fn.stderr b/src/test/ui/nll/ty-outlives/ty-param-fn.stderr
new file mode 100644
index 0000000..8c85296
--- /dev/null
+++ b/src/test/ui/nll/ty-outlives/ty-param-fn.stderr
@@ -0,0 +1,19 @@
+error[E0309]: the parameter type `T` may not live long enough
+  --> $DIR/ty-param-fn.rs:11:5
+   |
+LL |     x
+   |     ^
+   |
+   = help: consider adding an explicit lifetime bound `T: 'a`...
+
+error[E0309]: the parameter type `T` may not live long enough
+  --> $DIR/ty-param-fn.rs:26:5
+   |
+LL |     x
+   |     ^
+   |
+   = help: consider adding an explicit lifetime bound `T: 'a`...
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0309`.
diff --git a/src/test/ui/nll/ty-outlives/ty-param-implied-bounds.rs b/src/test/ui/nll/ty-outlives/ty-param-implied-bounds.rs
new file mode 100644
index 0000000..f61f54f
--- /dev/null
+++ b/src/test/ui/nll/ty-outlives/ty-param-implied-bounds.rs
@@ -0,0 +1,32 @@
+// compile-flags:-Zborrowck=mir -Zverbose
+// compile-pass
+
+// Test that we assume that universal types like `T` outlive the
+// function body.
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+
+use std::cell::Cell;
+
+fn twice<F, T>(value: T, mut f: F)
+where
+    F: FnMut(Cell<&T>),
+{
+    f(Cell::new(&value));
+    f(Cell::new(&value));
+}
+
+#[rustc_errors]
+fn generic<T>(value: T) {
+    // No error here:
+    twice(value, |r| invoke(r));
+}
+
+fn invoke<'a, T>(x: Cell<&'a T>)
+where
+    T: 'a,
+{
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/ty-outlives/wf-unreachable.rs b/src/test/ui/nll/ty-outlives/wf-unreachable.rs
new file mode 100644
index 0000000..a2e3ab4
--- /dev/null
+++ b/src/test/ui/nll/ty-outlives/wf-unreachable.rs
@@ -0,0 +1,54 @@
+// Test that we check that user type annotations are well-formed, even in dead
+// code.
+
+#![feature(nll)]
+
+fn uninit<'a>() {
+    return;
+    let x: &'static &'a ();                         //~ ERROR lifetime may not live long enough
+}
+
+fn var_type<'a>() {
+    return;
+    let x: &'static &'a () = &&();                  //~ ERROR lifetime may not live long enough
+}
+
+fn uninit_infer<'a>() {
+    let x: &'static &'a _;                          //~ ERROR lifetime may not live long enough
+    x = && ();
+}
+
+fn infer<'a>() {
+    return;
+    let x: &'static &'a _ = &&();                   //~ ERROR lifetime may not live long enough
+}
+
+fn uninit_no_var<'a>() {
+    return;
+    let _: &'static &'a ();                         //~ ERROR lifetime may not live long enough
+}
+
+fn no_var<'a>() {
+    return;
+    let _: &'static &'a () = &&();                  //~ ERROR lifetime may not live long enough
+}
+
+fn infer_no_var<'a>() {
+    return;
+    let _: &'static &'a _ = &&();                   //~ ERROR lifetime may not live long enough
+}
+
+trait X<'a, 'b> {}
+
+struct C<'a, 'b, T: X<'a, 'b>>(T, &'a (), &'b ());
+
+impl X<'_, '_> for i32 {}
+impl<'a> X<'a, 'a> for () {}
+
+// This type annotation is not well-formed because we substitute `()` for `_`.
+fn required_substs<'a>() {
+    return;
+    let _: C<'static, 'a, _> = C((), &(), &());     //~ ERROR lifetime may not live long enough
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/ty-outlives/wf-unreachable.stderr b/src/test/ui/nll/ty-outlives/wf-unreachable.stderr
new file mode 100644
index 0000000..9128fd1
--- /dev/null
+++ b/src/test/ui/nll/ty-outlives/wf-unreachable.stderr
@@ -0,0 +1,73 @@
+error: lifetime may not live long enough
+  --> $DIR/wf-unreachable.rs:8:12
+   |
+LL | fn uninit<'a>() {
+   |           -- lifetime `'a` defined here
+LL |     return;
+LL |     let x: &'static &'a ();
+   |            ^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/wf-unreachable.rs:13:12
+   |
+LL | fn var_type<'a>() {
+   |             -- lifetime `'a` defined here
+LL |     return;
+LL |     let x: &'static &'a () = &&();
+   |            ^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/wf-unreachable.rs:17:12
+   |
+LL | fn uninit_infer<'a>() {
+   |                 -- lifetime `'a` defined here
+LL |     let x: &'static &'a _;
+   |            ^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/wf-unreachable.rs:23:12
+   |
+LL | fn infer<'a>() {
+   |          -- lifetime `'a` defined here
+LL |     return;
+LL |     let x: &'static &'a _ = &&();
+   |            ^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/wf-unreachable.rs:28:12
+   |
+LL | fn uninit_no_var<'a>() {
+   |                  -- lifetime `'a` defined here
+LL |     return;
+LL |     let _: &'static &'a ();
+   |            ^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/wf-unreachable.rs:33:12
+   |
+LL | fn no_var<'a>() {
+   |           -- lifetime `'a` defined here
+LL |     return;
+LL |     let _: &'static &'a () = &&();
+   |            ^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/wf-unreachable.rs:38:12
+   |
+LL | fn infer_no_var<'a>() {
+   |                 -- lifetime `'a` defined here
+LL |     return;
+LL |     let _: &'static &'a _ = &&();
+   |            ^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/wf-unreachable.rs:51:12
+   |
+LL | fn required_substs<'a>() {
+   |                    -- lifetime `'a` defined here
+LL |     return;
+LL |     let _: C<'static, 'a, _> = C((), &(), &());
+   |            ^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+
+error: aborting due to 8 previous errors
+
diff --git a/src/test/ui/nll/type-alias-free-regions.rs b/src/test/ui/nll/type-alias-free-regions.rs
new file mode 100644
index 0000000..ebe6b9d
--- /dev/null
+++ b/src/test/ui/nll/type-alias-free-regions.rs
@@ -0,0 +1,33 @@
+// Test that we don't assume that type aliases have the same type parameters
+// as the type they alias and then panic when we see this.
+
+#![feature(nll)]
+
+type A<'a> = &'a isize;
+type B<'a> = Box<A<'a>>;
+
+struct C<'a> {
+    f: Box<B<'a>>
+}
+
+trait FromBox<'a> {
+    fn from_box(b: Box<B>) -> Self;
+}
+
+impl<'a> FromBox<'a> for C<'a> {
+    fn from_box(b: Box<B>) -> Self {
+        C { f: b } //~ ERROR
+    }
+}
+
+trait FromTuple<'a> {
+    fn from_tuple( b: (B,)) -> Self;
+}
+
+impl<'a> FromTuple<'a> for C<'a> {
+    fn from_tuple(b: (B,)) -> Self {
+        C { f: Box::new(b.0) } //~ ERROR
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/type-alias-free-regions.stderr b/src/test/ui/nll/type-alias-free-regions.stderr
new file mode 100644
index 0000000..4facc2d
--- /dev/null
+++ b/src/test/ui/nll/type-alias-free-regions.stderr
@@ -0,0 +1,22 @@
+error: lifetime may not live long enough
+  --> $DIR/type-alias-free-regions.rs:19:9
+   |
+LL | impl<'a> FromBox<'a> for C<'a> {
+   |      -- lifetime `'a` defined here
+LL |     fn from_box(b: Box<B>) -> Self {
+   |                 - has type `std::boxed::Box<std::boxed::Box<&'1 isize>>`
+LL |         C { f: b }
+   |         ^^^^^^^^^^ returning this value requires that `'1` must outlive `'a`
+
+error: lifetime may not live long enough
+  --> $DIR/type-alias-free-regions.rs:29:9
+   |
+LL | impl<'a> FromTuple<'a> for C<'a> {
+   |      -- lifetime `'a` defined here
+LL |     fn from_tuple(b: (B,)) -> Self {
+   |                   - has type `(std::boxed::Box<&'1 isize>,)`
+LL |         C { f: Box::new(b.0) }
+   |         ^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'a`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/nll/type-check-pointer-coercions.rs b/src/test/ui/nll/type-check-pointer-coercions.rs
new file mode 100644
index 0000000..b6a25ed
--- /dev/null
+++ b/src/test/ui/nll/type-check-pointer-coercions.rs
@@ -0,0 +1,39 @@
+#![feature(nll)]
+
+fn shared_to_const<'a, 'b>(x: &&'a i32) -> *const &'b i32 {
+    x   //~ ERROR
+}
+
+fn unique_to_const<'a, 'b>(x: &mut &'a i32) -> *const &'b i32 {
+    x   //~ ERROR
+}
+
+fn unique_to_mut<'a, 'b>(x: &mut &'a i32) -> *mut &'b i32 {
+    // Two errors because *mut is invariant
+    x   //~ ERROR
+        //~| ERROR
+}
+
+fn mut_to_const<'a, 'b>(x: *mut &'a i32) -> *const &'b i32 {
+    x   //~ ERROR
+}
+
+fn array_elem<'a, 'b>(x: &'a i32) -> *const &'b i32 {
+    let z = &[x; 3];
+    let y = z as *const &i32;
+    y   //~ ERROR
+}
+
+fn array_coerce<'a, 'b>(x: &'a i32) -> *const [&'b i32; 3] {
+    let z = &[x; 3];
+    let y = z as *const [&i32; 3];
+    y   //~ ERROR
+}
+
+fn nested_array<'a, 'b>(x: &'a i32) -> *const [&'b i32; 2] {
+    let z = &[[x; 2]; 3];
+    let y = z as *const [&i32; 2];
+    y   //~ ERROR
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/type-check-pointer-coercions.stderr b/src/test/ui/nll/type-check-pointer-coercions.stderr
new file mode 100644
index 0000000..9aa78df
--- /dev/null
+++ b/src/test/ui/nll/type-check-pointer-coercions.stderr
@@ -0,0 +1,87 @@
+error: lifetime may not live long enough
+  --> $DIR/type-check-pointer-coercions.rs:4:5
+   |
+LL | fn shared_to_const<'a, 'b>(x: &&'a i32) -> *const &'b i32 {
+   |                    --  -- lifetime `'b` defined here
+   |                    |
+   |                    lifetime `'a` defined here
+LL |     x
+   |     ^ returning this value requires that `'a` must outlive `'b`
+
+error: lifetime may not live long enough
+  --> $DIR/type-check-pointer-coercions.rs:8:5
+   |
+LL | fn unique_to_const<'a, 'b>(x: &mut &'a i32) -> *const &'b i32 {
+   |                    --  -- lifetime `'b` defined here
+   |                    |
+   |                    lifetime `'a` defined here
+LL |     x
+   |     ^ returning this value requires that `'a` must outlive `'b`
+
+error: lifetime may not live long enough
+  --> $DIR/type-check-pointer-coercions.rs:13:5
+   |
+LL | fn unique_to_mut<'a, 'b>(x: &mut &'a i32) -> *mut &'b i32 {
+   |                  --  -- lifetime `'b` defined here
+   |                  |
+   |                  lifetime `'a` defined here
+LL |     // Two errors because *mut is invariant
+LL |     x
+   |     ^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
+
+error: lifetime may not live long enough
+  --> $DIR/type-check-pointer-coercions.rs:13:5
+   |
+LL | fn unique_to_mut<'a, 'b>(x: &mut &'a i32) -> *mut &'b i32 {
+   |                  --  -- lifetime `'b` defined here
+   |                  |
+   |                  lifetime `'a` defined here
+LL |     // Two errors because *mut is invariant
+LL |     x
+   |     ^ returning this value requires that `'a` must outlive `'b`
+
+error: lifetime may not live long enough
+  --> $DIR/type-check-pointer-coercions.rs:18:5
+   |
+LL | fn mut_to_const<'a, 'b>(x: *mut &'a i32) -> *const &'b i32 {
+   |                 --  -- lifetime `'b` defined here
+   |                 |
+   |                 lifetime `'a` defined here
+LL |     x
+   |     ^ returning this value requires that `'a` must outlive `'b`
+
+error: lifetime may not live long enough
+  --> $DIR/type-check-pointer-coercions.rs:24:5
+   |
+LL | fn array_elem<'a, 'b>(x: &'a i32) -> *const &'b i32 {
+   |               --  -- lifetime `'b` defined here
+   |               |
+   |               lifetime `'a` defined here
+...
+LL |     y
+   |     ^ returning this value requires that `'a` must outlive `'b`
+
+error: lifetime may not live long enough
+  --> $DIR/type-check-pointer-coercions.rs:30:5
+   |
+LL | fn array_coerce<'a, 'b>(x: &'a i32) -> *const [&'b i32; 3] {
+   |                 --  -- lifetime `'b` defined here
+   |                 |
+   |                 lifetime `'a` defined here
+...
+LL |     y
+   |     ^ returning this value requires that `'a` must outlive `'b`
+
+error: lifetime may not live long enough
+  --> $DIR/type-check-pointer-coercions.rs:36:5
+   |
+LL | fn nested_array<'a, 'b>(x: &'a i32) -> *const [&'b i32; 2] {
+   |                 --  -- lifetime `'b` defined here
+   |                 |
+   |                 lifetime `'a` defined here
+...
+LL |     y
+   |     ^ returning this value requires that `'a` must outlive `'b`
+
+error: aborting due to 8 previous errors
+
diff --git a/src/test/ui/nll/type-check-pointer-comparisons.rs b/src/test/ui/nll/type-check-pointer-comparisons.rs
new file mode 100644
index 0000000..3c90035
--- /dev/null
+++ b/src/test/ui/nll/type-check-pointer-comparisons.rs
@@ -0,0 +1,33 @@
+#![feature(nll)]
+
+// Check that we assert that pointers have a common subtype for comparisons
+
+fn compare_const<'a, 'b>(x: *const &mut &'a i32, y: *const &mut &'b i32) {
+    x == y;
+    //~^ ERROR lifetime may not live long enough
+    //~| ERROR lifetime may not live long enough
+}
+
+fn compare_mut<'a, 'b>(x: *mut &'a i32, y: *mut &'b i32) {
+    x == y;
+    //~^ ERROR lifetime may not live long enough
+    //~| ERROR lifetime may not live long enough
+}
+
+fn compare_fn_ptr<'a, 'b, 'c>(f: fn(&'c mut &'a i32), g: fn(&'c mut &'b i32)) {
+    f == g;
+    //~^ ERROR lifetime may not live long enough
+    //~| ERROR lifetime may not live long enough
+}
+
+fn compare_hr_fn_ptr<'a>(f: fn(&'a i32), g: fn(&i32)) {
+    // Ideally this should compile with the operands swapped as well, but HIR
+    // type checking prevents it (and stops compilation) for now.
+    f == g; // OK
+}
+
+fn compare_const_fn_ptr<'a>(f: *const fn(&'a i32), g: *const fn(&i32)) {
+    f == g; // OK
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/type-check-pointer-comparisons.stderr b/src/test/ui/nll/type-check-pointer-comparisons.stderr
new file mode 100644
index 0000000..c0a994c
--- /dev/null
+++ b/src/test/ui/nll/type-check-pointer-comparisons.stderr
@@ -0,0 +1,62 @@
+error: lifetime may not live long enough
+  --> $DIR/type-check-pointer-comparisons.rs:6:5
+   |
+LL | fn compare_const<'a, 'b>(x: *const &mut &'a i32, y: *const &mut &'b i32) {
+   |                  --  -- lifetime `'b` defined here
+   |                  |
+   |                  lifetime `'a` defined here
+LL |     x == y;
+   |     ^ requires that `'a` must outlive `'b`
+
+error: lifetime may not live long enough
+  --> $DIR/type-check-pointer-comparisons.rs:6:10
+   |
+LL | fn compare_const<'a, 'b>(x: *const &mut &'a i32, y: *const &mut &'b i32) {
+   |                  --  -- lifetime `'b` defined here
+   |                  |
+   |                  lifetime `'a` defined here
+LL |     x == y;
+   |          ^ requires that `'b` must outlive `'a`
+
+error: lifetime may not live long enough
+  --> $DIR/type-check-pointer-comparisons.rs:12:5
+   |
+LL | fn compare_mut<'a, 'b>(x: *mut &'a i32, y: *mut &'b i32) {
+   |                --  -- lifetime `'b` defined here
+   |                |
+   |                lifetime `'a` defined here
+LL |     x == y;
+   |     ^ requires that `'a` must outlive `'b`
+
+error: lifetime may not live long enough
+  --> $DIR/type-check-pointer-comparisons.rs:12:10
+   |
+LL | fn compare_mut<'a, 'b>(x: *mut &'a i32, y: *mut &'b i32) {
+   |                --  -- lifetime `'b` defined here
+   |                |
+   |                lifetime `'a` defined here
+LL |     x == y;
+   |          ^ requires that `'b` must outlive `'a`
+
+error: lifetime may not live long enough
+  --> $DIR/type-check-pointer-comparisons.rs:18:5
+   |
+LL | fn compare_fn_ptr<'a, 'b, 'c>(f: fn(&'c mut &'a i32), g: fn(&'c mut &'b i32)) {
+   |                   --  -- lifetime `'b` defined here
+   |                   |
+   |                   lifetime `'a` defined here
+LL |     f == g;
+   |     ^ requires that `'a` must outlive `'b`
+
+error: lifetime may not live long enough
+  --> $DIR/type-check-pointer-comparisons.rs:18:10
+   |
+LL | fn compare_fn_ptr<'a, 'b, 'c>(f: fn(&'c mut &'a i32), g: fn(&'c mut &'b i32)) {
+   |                   --  -- lifetime `'b` defined here
+   |                   |
+   |                   lifetime `'a` defined here
+LL |     f == g;
+   |          ^ requires that `'b` must outlive `'a`
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/nll/unused-mut-issue-50343.rs b/src/test/ui/nll/unused-mut-issue-50343.rs
new file mode 100644
index 0000000..06dbc47
--- /dev/null
+++ b/src/test/ui/nll/unused-mut-issue-50343.rs
@@ -0,0 +1,7 @@
+#![feature(nll)]
+#![deny(unused_mut)]
+
+fn main() {
+    vec![(42, 22)].iter().map(|(mut x, _y)| ()).count();
+    //~^ ERROR: variable does not need to be mutable
+}
diff --git a/src/test/ui/nll/unused-mut-issue-50343.stderr b/src/test/ui/nll/unused-mut-issue-50343.stderr
new file mode 100644
index 0000000..ef31dd7
--- /dev/null
+++ b/src/test/ui/nll/unused-mut-issue-50343.stderr
@@ -0,0 +1,16 @@
+error: variable does not need to be mutable
+  --> $DIR/unused-mut-issue-50343.rs:5:33
+   |
+LL |     vec![(42, 22)].iter().map(|(mut x, _y)| ()).count();
+   |                                 ----^
+   |                                 |
+   |                                 help: remove this `mut`
+   |
+note: lint level defined here
+  --> $DIR/unused-mut-issue-50343.rs:2:9
+   |
+LL | #![deny(unused_mut)]
+   |         ^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/user-annotations/adt-brace-enums.rs b/src/test/ui/nll/user-annotations/adt-brace-enums.rs
new file mode 100644
index 0000000..842ebae
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/adt-brace-enums.rs
@@ -0,0 +1,52 @@
+// Unit test for the "user substitutions" that are annotated on each
+// node.
+
+#![feature(nll)]
+
+enum SomeEnum<T> {
+    SomeVariant { t: T }
+}
+
+fn no_annot() {
+    let c = 66;
+    SomeEnum::SomeVariant { t: &c };
+}
+
+fn annot_underscore() {
+    let c = 66;
+    SomeEnum::SomeVariant::<_> { t: &c };
+}
+
+fn annot_reference_any_lifetime() {
+    let c = 66;
+    SomeEnum::SomeVariant::<&u32> { t: &c };
+}
+
+fn annot_reference_static_lifetime() {
+    let c = 66;
+    SomeEnum::SomeVariant::<&'static u32> { t: &c }; //~ ERROR
+}
+
+fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+    let c = 66;
+    SomeEnum::SomeVariant::<&'a u32> { t: &c }; //~ ERROR
+}
+
+fn annot_reference_named_lifetime_ok<'a>(c: &'a u32) {
+    SomeEnum::SomeVariant::<&'a u32> { t: c };
+}
+
+fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+    let _closure = || {
+        let c = 66;
+        SomeEnum::SomeVariant::<&'a u32> { t: &c }; //~ ERROR
+    };
+}
+
+fn annot_reference_named_lifetime_in_closure_ok<'a>(c: &'a u32) {
+    let _closure = || {
+        SomeEnum::SomeVariant::<&'a u32> { t: c };
+    };
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/user-annotations/adt-brace-enums.stderr b/src/test/ui/nll/user-annotations/adt-brace-enums.stderr
new file mode 100644
index 0000000..38f0687
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/adt-brace-enums.stderr
@@ -0,0 +1,42 @@
+error[E0597]: `c` does not live long enough
+  --> $DIR/adt-brace-enums.rs:27:48
+   |
+LL |     SomeEnum::SomeVariant::<&'static u32> { t: &c };
+   |                                                ^^
+   |                                                |
+   |                                                borrowed value does not live long enough
+   |                                                requires that `c` is borrowed for `'static`
+LL | }
+   | - `c` dropped here while still borrowed
+
+error[E0597]: `c` does not live long enough
+  --> $DIR/adt-brace-enums.rs:32:43
+   |
+LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+   |                                   -- lifetime `'a` defined here
+LL |     let c = 66;
+LL |     SomeEnum::SomeVariant::<&'a u32> { t: &c };
+   |                                           ^^
+   |                                           |
+   |                                           borrowed value does not live long enough
+   |                                           requires that `c` is borrowed for `'a`
+LL | }
+   | - `c` dropped here while still borrowed
+
+error[E0597]: `c` does not live long enough
+  --> $DIR/adt-brace-enums.rs:42:47
+   |
+LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+   |                                              -- lifetime `'a` defined here
+...
+LL |         SomeEnum::SomeVariant::<&'a u32> { t: &c };
+   |                                               ^^
+   |                                               |
+   |                                               borrowed value does not live long enough
+   |                                               requires that `c` is borrowed for `'a`
+LL |     };
+   |     - `c` dropped here while still borrowed
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/user-annotations/adt-brace-structs.rs b/src/test/ui/nll/user-annotations/adt-brace-structs.rs
new file mode 100644
index 0000000..d7ebbe8
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/adt-brace-structs.rs
@@ -0,0 +1,50 @@
+// Unit test for the "user substitutions" that are annotated on each
+// node.
+
+#![feature(nll)]
+
+struct SomeStruct<T> { t: T }
+
+fn no_annot() {
+    let c = 66;
+    SomeStruct { t: &c };
+}
+
+fn annot_underscore() {
+    let c = 66;
+    SomeStruct::<_> { t: &c };
+}
+
+fn annot_reference_any_lifetime() {
+    let c = 66;
+    SomeStruct::<&u32> { t: &c };
+}
+
+fn annot_reference_static_lifetime() {
+    let c = 66;
+    SomeStruct::<&'static u32> { t: &c }; //~ ERROR
+}
+
+fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+    let c = 66;
+    SomeStruct::<&'a u32> { t: &c }; //~ ERROR
+}
+
+fn annot_reference_named_lifetime_ok<'a>(c: &'a u32) {
+    SomeStruct::<&'a u32> { t: c };
+}
+
+fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+    let _closure = || {
+        let c = 66;
+        SomeStruct::<&'a u32> { t: &c }; //~ ERROR
+    };
+}
+
+fn annot_reference_named_lifetime_in_closure_ok<'a>(c: &'a u32) {
+    let _closure = || {
+        SomeStruct::<&'a u32> { t: c };
+    };
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/user-annotations/adt-brace-structs.stderr b/src/test/ui/nll/user-annotations/adt-brace-structs.stderr
new file mode 100644
index 0000000..25a9de4
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/adt-brace-structs.stderr
@@ -0,0 +1,42 @@
+error[E0597]: `c` does not live long enough
+  --> $DIR/adt-brace-structs.rs:25:37
+   |
+LL |     SomeStruct::<&'static u32> { t: &c };
+   |                                     ^^
+   |                                     |
+   |                                     borrowed value does not live long enough
+   |                                     requires that `c` is borrowed for `'static`
+LL | }
+   | - `c` dropped here while still borrowed
+
+error[E0597]: `c` does not live long enough
+  --> $DIR/adt-brace-structs.rs:30:32
+   |
+LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+   |                                   -- lifetime `'a` defined here
+LL |     let c = 66;
+LL |     SomeStruct::<&'a u32> { t: &c };
+   |                                ^^
+   |                                |
+   |                                borrowed value does not live long enough
+   |                                requires that `c` is borrowed for `'a`
+LL | }
+   | - `c` dropped here while still borrowed
+
+error[E0597]: `c` does not live long enough
+  --> $DIR/adt-brace-structs.rs:40:36
+   |
+LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+   |                                              -- lifetime `'a` defined here
+...
+LL |         SomeStruct::<&'a u32> { t: &c };
+   |                                    ^^
+   |                                    |
+   |                                    borrowed value does not live long enough
+   |                                    requires that `c` is borrowed for `'a`
+LL |     };
+   |     - `c` dropped here while still borrowed
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/user-annotations/adt-nullary-enums.rs b/src/test/ui/nll/user-annotations/adt-nullary-enums.rs
new file mode 100644
index 0000000..7a8f55a
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/adt-nullary-enums.rs
@@ -0,0 +1,70 @@
+// Unit test for the "user substitutions" that are annotated on each
+// node.
+
+#![feature(nll)]
+#![allow(warnings)]
+
+use std::cell::Cell;
+
+enum SomeEnum<T> {
+    SomeVariant(T),
+    SomeOtherVariant,
+}
+
+fn combine<T>(_: T, _: T) { }
+
+fn no_annot() {
+    let c = 66;
+    combine(SomeEnum::SomeVariant(Cell::new(&c)), SomeEnum::SomeOtherVariant);
+}
+
+fn annot_underscore() {
+    let c = 66;
+    combine(SomeEnum::SomeVariant(Cell::new(&c)), SomeEnum::SomeOtherVariant::<Cell<_>>);
+}
+
+fn annot_reference_any_lifetime() {
+    let c = 66;
+    combine(SomeEnum::SomeVariant(Cell::new(&c)), SomeEnum::SomeOtherVariant::<Cell<&u32>>);
+}
+
+fn annot_reference_static_lifetime() {
+    let c = 66;
+    combine(
+        SomeEnum::SomeVariant(Cell::new(&c)), //~ ERROR
+        SomeEnum::SomeOtherVariant::<Cell<&'static u32>>,
+    );
+}
+
+fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+    let c = 66;
+    combine(
+        SomeEnum::SomeVariant(Cell::new(&c)), //~ ERROR
+        SomeEnum::SomeOtherVariant::<Cell<&'a u32>>,
+    );
+}
+
+fn annot_reference_named_lifetime_ok<'a>(c: &'a u32) {
+    combine(SomeEnum::SomeVariant(Cell::new(c)), SomeEnum::SomeOtherVariant::<Cell<&'a u32>>);
+}
+
+fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+    let _closure = || {
+        let c = 66;
+        combine(
+            SomeEnum::SomeVariant(Cell::new(&c)), //~ ERROR
+            SomeEnum::SomeOtherVariant::<Cell<&'a u32>>,
+        );
+    };
+}
+
+fn annot_reference_named_lifetime_in_closure_ok<'a>(c: &'a u32) {
+    let _closure = || {
+        combine(
+            SomeEnum::SomeVariant(Cell::new(c)),
+            SomeEnum::SomeOtherVariant::<Cell<&'a u32>>,
+        );
+    };
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/user-annotations/adt-nullary-enums.stderr b/src/test/ui/nll/user-annotations/adt-nullary-enums.stderr
new file mode 100644
index 0000000..1afbac7
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/adt-nullary-enums.stderr
@@ -0,0 +1,45 @@
+error[E0597]: `c` does not live long enough
+  --> $DIR/adt-nullary-enums.rs:34:41
+   |
+LL |         SomeEnum::SomeVariant(Cell::new(&c)),
+   |                               ----------^^-
+   |                               |         |
+   |                               |         borrowed value does not live long enough
+   |                               argument requires that `c` is borrowed for `'static`
+...
+LL | }
+   | - `c` dropped here while still borrowed
+
+error[E0597]: `c` does not live long enough
+  --> $DIR/adt-nullary-enums.rs:42:41
+   |
+LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+   |                                   -- lifetime `'a` defined here
+...
+LL |         SomeEnum::SomeVariant(Cell::new(&c)),
+   |                               ----------^^-
+   |                               |         |
+   |                               |         borrowed value does not live long enough
+   |                               argument requires that `c` is borrowed for `'a`
+...
+LL | }
+   | - `c` dropped here while still borrowed
+
+error[E0597]: `c` does not live long enough
+  --> $DIR/adt-nullary-enums.rs:55:45
+   |
+LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+   |                                              -- lifetime `'a` defined here
+...
+LL |             SomeEnum::SomeVariant(Cell::new(&c)),
+   |                                   ----------^^-
+   |                                   |         |
+   |                                   |         borrowed value does not live long enough
+   |                                   argument requires that `c` is borrowed for `'a`
+...
+LL |     };
+   |     - `c` dropped here while still borrowed
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/user-annotations/adt-tuple-enums.rs b/src/test/ui/nll/user-annotations/adt-tuple-enums.rs
new file mode 100644
index 0000000..085596e
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/adt-tuple-enums.rs
@@ -0,0 +1,54 @@
+// Unit test for the "user substitutions" that are annotated on each
+// node.
+
+#![feature(nll)]
+#![allow(warnings)]
+
+enum SomeEnum<T> {
+    SomeVariant(T),
+    SomeOtherVariant,
+}
+
+fn no_annot() {
+    let c = 66;
+    SomeEnum::SomeVariant(&c);
+}
+
+fn annot_underscore() {
+    let c = 66;
+    SomeEnum::SomeVariant::<_>(&c);
+}
+
+fn annot_reference_any_lifetime() {
+    let c = 66;
+    SomeEnum::SomeVariant::<&u32>(&c);
+}
+
+fn annot_reference_static_lifetime() {
+    let c = 66;
+    SomeEnum::SomeVariant::<&'static u32>(&c); //~ ERROR
+}
+
+fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+    let c = 66;
+    SomeEnum::SomeVariant::<&'a u32>(&c); //~ ERROR
+}
+
+fn annot_reference_named_lifetime_ok<'a>(c: &'a u32) {
+    SomeEnum::SomeVariant::<&'a u32>(c);
+}
+
+fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+    let _closure = || {
+        let c = 66;
+        SomeEnum::SomeVariant::<&'a u32>(&c); //~ ERROR
+    };
+}
+
+fn annot_reference_named_lifetime_in_closure_ok<'a>(c: &'a u32) {
+    let _closure = || {
+        SomeEnum::SomeVariant::<&'a u32>(c);
+    };
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/user-annotations/adt-tuple-enums.stderr b/src/test/ui/nll/user-annotations/adt-tuple-enums.stderr
new file mode 100644
index 0000000..cd62565
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/adt-tuple-enums.stderr
@@ -0,0 +1,42 @@
+error[E0597]: `c` does not live long enough
+  --> $DIR/adt-tuple-enums.rs:29:43
+   |
+LL |     SomeEnum::SomeVariant::<&'static u32>(&c);
+   |                                           ^^
+   |                                           |
+   |                                           borrowed value does not live long enough
+   |                                           requires that `c` is borrowed for `'static`
+LL | }
+   | - `c` dropped here while still borrowed
+
+error[E0597]: `c` does not live long enough
+  --> $DIR/adt-tuple-enums.rs:34:38
+   |
+LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+   |                                   -- lifetime `'a` defined here
+LL |     let c = 66;
+LL |     SomeEnum::SomeVariant::<&'a u32>(&c);
+   |                                      ^^
+   |                                      |
+   |                                      borrowed value does not live long enough
+   |                                      requires that `c` is borrowed for `'a`
+LL | }
+   | - `c` dropped here while still borrowed
+
+error[E0597]: `c` does not live long enough
+  --> $DIR/adt-tuple-enums.rs:44:42
+   |
+LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+   |                                              -- lifetime `'a` defined here
+...
+LL |         SomeEnum::SomeVariant::<&'a u32>(&c);
+   |                                          ^^
+   |                                          |
+   |                                          borrowed value does not live long enough
+   |                                          requires that `c` is borrowed for `'a`
+LL |     };
+   |     - `c` dropped here while still borrowed
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/user-annotations/adt-tuple-struct.rs b/src/test/ui/nll/user-annotations/adt-tuple-struct.rs
new file mode 100644
index 0000000..ebbe3cd2
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/adt-tuple-struct.rs
@@ -0,0 +1,50 @@
+// Unit test for the "user substitutions" that are annotated on each
+// node.
+
+#![feature(nll)]
+
+struct SomeStruct<T>(T);
+
+fn no_annot() {
+    let c = 66;
+    SomeStruct(&c);
+}
+
+fn annot_underscore() {
+    let c = 66;
+    SomeStruct::<_>(&c);
+}
+
+fn annot_reference_any_lifetime() {
+    let c = 66;
+    SomeStruct::<&u32>(&c);
+}
+
+fn annot_reference_static_lifetime() {
+    let c = 66;
+    SomeStruct::<&'static u32>(&c); //~ ERROR
+}
+
+fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+    let c = 66;
+    SomeStruct::<&'a u32>(&c); //~ ERROR
+}
+
+fn annot_reference_named_lifetime_ok<'a>(c: &'a u32) {
+    SomeStruct::<&'a u32>(c);
+}
+
+fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+    let _closure = || {
+        let c = 66;
+        SomeStruct::<&'a u32>(&c); //~ ERROR
+    };
+}
+
+fn annot_reference_named_lifetime_in_closure_ok<'a>(c: &'a u32) {
+    let _closure = || {
+        SomeStruct::<&'a u32>(c);
+    };
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/user-annotations/adt-tuple-struct.stderr b/src/test/ui/nll/user-annotations/adt-tuple-struct.stderr
new file mode 100644
index 0000000..2bb58bb
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/adt-tuple-struct.stderr
@@ -0,0 +1,42 @@
+error[E0597]: `c` does not live long enough
+  --> $DIR/adt-tuple-struct.rs:25:32
+   |
+LL |     SomeStruct::<&'static u32>(&c);
+   |                                ^^
+   |                                |
+   |                                borrowed value does not live long enough
+   |                                requires that `c` is borrowed for `'static`
+LL | }
+   | - `c` dropped here while still borrowed
+
+error[E0597]: `c` does not live long enough
+  --> $DIR/adt-tuple-struct.rs:30:27
+   |
+LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+   |                                   -- lifetime `'a` defined here
+LL |     let c = 66;
+LL |     SomeStruct::<&'a u32>(&c);
+   |                           ^^
+   |                           |
+   |                           borrowed value does not live long enough
+   |                           requires that `c` is borrowed for `'a`
+LL | }
+   | - `c` dropped here while still borrowed
+
+error[E0597]: `c` does not live long enough
+  --> $DIR/adt-tuple-struct.rs:40:31
+   |
+LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+   |                                              -- lifetime `'a` defined here
+...
+LL |         SomeStruct::<&'a u32>(&c);
+   |                               ^^
+   |                               |
+   |                               borrowed value does not live long enough
+   |                               requires that `c` is borrowed for `'a`
+LL |     };
+   |     - `c` dropped here while still borrowed
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/user-annotations/cast_static_lifetime.rs b/src/test/ui/nll/user-annotations/cast_static_lifetime.rs
new file mode 100644
index 0000000..4756c77
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/cast_static_lifetime.rs
@@ -0,0 +1,7 @@
+#![allow(warnings)]
+#![feature(nll)]
+
+fn main() {
+    let x = 22_u32;
+    let y: &u32 = (&x) as &'static u32; //~ ERROR `x` does not live long enough
+}
diff --git a/src/test/ui/nll/user-annotations/cast_static_lifetime.stderr b/src/test/ui/nll/user-annotations/cast_static_lifetime.stderr
new file mode 100644
index 0000000..0228b56
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/cast_static_lifetime.stderr
@@ -0,0 +1,14 @@
+error[E0597]: `x` does not live long enough
+  --> $DIR/cast_static_lifetime.rs:6:19
+   |
+LL |     let y: &u32 = (&x) as &'static u32;
+   |                   ^^^^----------------
+   |                   |
+   |                   borrowed value does not live long enough
+   |                   type annotation requires that `x` is borrowed for `'static`
+LL | }
+   | - `x` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/user-annotations/closure-substs.rs b/src/test/ui/nll/user-annotations/closure-substs.rs
new file mode 100644
index 0000000..cafdd92
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/closure-substs.rs
@@ -0,0 +1,33 @@
+#![feature(nll)]
+
+// Test that we enforce user-provided type annotations on closures.
+
+fn foo<'a>() {
+    // Here `x` is free in the closure sig:
+    |x: &'a i32| -> &'static i32 {
+        return x; //~ ERROR lifetime may not live long enough
+    };
+}
+
+fn foo1() {
+    // Here `x` is bound in the closure sig:
+    |x: &i32| -> &'static i32 {
+        return x; //~ ERROR lifetime may not live long enough
+    };
+}
+
+fn bar<'a>() {
+    // Here `x` is free in the closure sig:
+    |x: &'a i32, b: fn(&'static i32)| {
+        b(x); //~ ERROR lifetime may not live long enough
+    };
+}
+
+fn bar1() {
+    // Here `x` is bound in the closure sig:
+    |x: &i32, b: fn(&'static i32)| {
+        b(x); //~ ERROR borrowed data escapes outside of closure
+    };
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/user-annotations/closure-substs.stderr b/src/test/ui/nll/user-annotations/closure-substs.stderr
new file mode 100644
index 0000000..55bb3a6
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/closure-substs.stderr
@@ -0,0 +1,37 @@
+error: lifetime may not live long enough
+  --> $DIR/closure-substs.rs:8:16
+   |
+LL | fn foo<'a>() {
+   |        -- lifetime `'a` defined here
+...
+LL |         return x;
+   |                ^ returning this value requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/closure-substs.rs:15:16
+   |
+LL |     |x: &i32| -> &'static i32 {
+   |         - let's call the lifetime of this reference `'1`
+LL |         return x;
+   |                ^ returning this value requires that `'1` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/closure-substs.rs:22:9
+   |
+LL | fn bar<'a>() {
+   |        -- lifetime `'a` defined here
+...
+LL |         b(x);
+   |         ^^^^ argument requires that `'a` must outlive `'static`
+
+error[E0521]: borrowed data escapes outside of closure
+  --> $DIR/closure-substs.rs:29:9
+   |
+LL |     |x: &i32, b: fn(&'static i32)| {
+   |      - `x` is a reference that is only valid in the closure body
+LL |         b(x);
+   |         ^^^^ `x` escapes the closure body here
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0521`.
diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.rs b/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.rs
new file mode 100644
index 0000000..058ebae
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.rs
@@ -0,0 +1,15 @@
+#![feature(nll)]
+
+struct Foo<'a> { x: &'a u32 }
+
+impl<'a> Foo<'a> {
+    const C: &'a u32 = &22;
+}
+
+fn foo<'a>(_: &'a u32) -> &'static u32 {
+    <Foo<'a>>::C //~ ERROR
+}
+
+fn main() {
+}
+
diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr
new file mode 100644
index 0000000..9a28fbd
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr
@@ -0,0 +1,10 @@
+error: lifetime may not live long enough
+  --> $DIR/constant-in-expr-inherent-1.rs:10:5
+   |
+LL | fn foo<'a>(_: &'a u32) -> &'static u32 {
+   |        -- lifetime `'a` defined here
+LL |     <Foo<'a>>::C
+   |     ^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-inherent-2.rs b/src/test/ui/nll/user-annotations/constant-in-expr-inherent-2.rs
new file mode 100644
index 0000000..123be6b
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/constant-in-expr-inherent-2.rs
@@ -0,0 +1,29 @@
+// Test that we still check constants are well-formed, even when we there's no
+// type annotation to check.
+
+#![feature(nll)]
+
+const FUN: fn(&'static ()) = |_| {};
+struct A;
+impl A {
+    const ASSOCIATED_FUN: fn(&'static ()) = |_| {};
+}
+
+struct B<'a>(&'a ());
+impl B<'static> {
+    const ALSO_ASSOCIATED_FUN: fn(&'static ()) = |_| {};
+}
+
+trait Z: 'static {
+    const TRAIT_ASSOCIATED_FUN: fn(&'static Self) = |_| ();
+}
+
+impl Z for () {}
+
+fn main() {
+    let x = ();
+    FUN(&x);                        //~ ERROR `x` does not live long enough
+    A::ASSOCIATED_FUN(&x);          //~ ERROR `x` does not live long enough
+    B::ALSO_ASSOCIATED_FUN(&x);     //~ ERROR `x` does not live long enough
+    <_>::TRAIT_ASSOCIATED_FUN(&x);  //~ ERROR `x` does not live long enough
+}
diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-inherent-2.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-inherent-2.stderr
new file mode 100644
index 0000000..07e2e1e
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/constant-in-expr-inherent-2.stderr
@@ -0,0 +1,50 @@
+error[E0597]: `x` does not live long enough
+  --> $DIR/constant-in-expr-inherent-2.rs:25:9
+   |
+LL |     FUN(&x);
+   |     ----^^-
+   |     |   |
+   |     |   borrowed value does not live long enough
+   |     argument requires that `x` is borrowed for `'static`
+...
+LL | }
+   | - `x` dropped here while still borrowed
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/constant-in-expr-inherent-2.rs:26:23
+   |
+LL |     A::ASSOCIATED_FUN(&x);
+   |     ------------------^^-
+   |     |                 |
+   |     |                 borrowed value does not live long enough
+   |     argument requires that `x` is borrowed for `'static`
+...
+LL | }
+   | - `x` dropped here while still borrowed
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/constant-in-expr-inherent-2.rs:27:28
+   |
+LL |     B::ALSO_ASSOCIATED_FUN(&x);
+   |     -----------------------^^-
+   |     |                      |
+   |     |                      borrowed value does not live long enough
+   |     argument requires that `x` is borrowed for `'static`
+LL |     <_>::TRAIT_ASSOCIATED_FUN(&x);
+LL | }
+   | - `x` dropped here while still borrowed
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/constant-in-expr-inherent-2.rs:28:31
+   |
+LL |     <_>::TRAIT_ASSOCIATED_FUN(&x);
+   |     --------------------------^^-
+   |     |                         |
+   |     |                         borrowed value does not live long enough
+   |     argument requires that `x` is borrowed for `'static`
+LL | }
+   | - `x` dropped here while still borrowed
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-normalize.rs b/src/test/ui/nll/user-annotations/constant-in-expr-normalize.rs
new file mode 100644
index 0000000..4292fc7
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/constant-in-expr-normalize.rs
@@ -0,0 +1,24 @@
+#![feature(nll)]
+
+trait Mirror {
+    type Me;
+}
+
+impl<T> Mirror for T {
+    type Me = T;
+}
+
+trait Foo<'a> {
+    const C: <&'a u32 as Mirror>::Me;
+}
+
+impl<'a, T> Foo<'a> for T {
+    const C: &'a u32 = &22;
+}
+
+fn foo<'a>(_: &'a u32) -> &'static u32 {
+    <() as Foo<'a>>::C //~ ERROR
+}
+
+fn main() {
+}
diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-normalize.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-normalize.stderr
new file mode 100644
index 0000000..5e66a30
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/constant-in-expr-normalize.stderr
@@ -0,0 +1,10 @@
+error: lifetime may not live long enough
+  --> $DIR/constant-in-expr-normalize.rs:20:5
+   |
+LL | fn foo<'a>(_: &'a u32) -> &'static u32 {
+   |        -- lifetime `'a` defined here
+LL |     <() as Foo<'a>>::C
+   |     ^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-1.rs b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-1.rs
new file mode 100644
index 0000000..daa0d7b
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-1.rs
@@ -0,0 +1,16 @@
+#![feature(nll)]
+
+trait Foo<'a> {
+    const C: &'a u32;
+}
+
+impl<'a, T> Foo<'a> for T {
+    const C: &'a u32 = &22;
+}
+
+fn foo<'a>(_: &'a u32) -> &'static u32 {
+    <() as Foo<'a>>::C //~ ERROR
+}
+
+fn main() {
+}
diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-1.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-1.stderr
new file mode 100644
index 0000000..c96838f
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-1.stderr
@@ -0,0 +1,10 @@
+error: lifetime may not live long enough
+  --> $DIR/constant-in-expr-trait-item-1.rs:12:5
+   |
+LL | fn foo<'a>(_: &'a u32) -> &'static u32 {
+   |        -- lifetime `'a` defined here
+LL |     <() as Foo<'a>>::C
+   |     ^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-2.rs b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-2.rs
new file mode 100644
index 0000000..cd66e7a
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-2.rs
@@ -0,0 +1,16 @@
+#![feature(nll)]
+
+trait Foo<'a> {
+    const C: &'a u32;
+}
+
+impl<'a, T> Foo<'a> for T {
+    const C: &'a u32 = &22;
+}
+
+fn foo<'a, T: Foo<'a>>() -> &'static u32 {
+    <T as Foo<'a>>::C //~ ERROR
+}
+
+fn main() {
+}
diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-2.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-2.stderr
new file mode 100644
index 0000000..fcc3c40
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-2.stderr
@@ -0,0 +1,10 @@
+error: lifetime may not live long enough
+  --> $DIR/constant-in-expr-trait-item-2.rs:12:5
+   |
+LL | fn foo<'a, T: Foo<'a>>() -> &'static u32 {
+   |        -- lifetime `'a` defined here
+LL |     <T as Foo<'a>>::C
+   |     ^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.rs b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.rs
new file mode 100644
index 0000000..f83ae24
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.rs
@@ -0,0 +1,16 @@
+#![feature(nll)]
+
+trait Foo<'a> {
+    const C: &'a u32;
+}
+
+impl<'a, T> Foo<'a> for T {
+    const C: &'a u32 = &22;
+}
+
+fn foo<'a, T: Foo<'a>>() -> &'static u32 {
+    T::C //~ ERROR
+}
+
+fn main() {
+}
diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr
new file mode 100644
index 0000000..c91370c
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr
@@ -0,0 +1,10 @@
+error: lifetime may not live long enough
+  --> $DIR/constant-in-expr-trait-item-3.rs:12:5
+   |
+LL | fn foo<'a, T: Foo<'a>>() -> &'static u32 {
+   |        -- lifetime `'a` defined here
+LL |     T::C
+   |     ^^^^ returning this value requires that `'a` must outlive `'static`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/user-annotations/downcast-infer.rs b/src/test/ui/nll/user-annotations/downcast-infer.rs
new file mode 100644
index 0000000..23b76bb
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/downcast-infer.rs
@@ -0,0 +1,11 @@
+// compile-pass
+
+// Check that we don't try to downcast `_` when type-checking the annotation.
+fn main() {
+    let x = Some(Some(Some(1)));
+
+    match x {
+        Some::<Option<_>>(Some(Some(v))) => (),
+        _ => (),
+    }
+}
diff --git a/src/test/ui/nll/user-annotations/dump-adt-brace-struct.rs b/src/test/ui/nll/user-annotations/dump-adt-brace-struct.rs
new file mode 100644
index 0000000..45f5683
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/dump-adt-brace-struct.rs
@@ -0,0 +1,21 @@
+// Unit test for the "user substitutions" that are annotated on each
+// node.
+
+// compile-flags:-Zverbose
+
+#![allow(warnings)]
+#![feature(nll)]
+#![feature(rustc_attrs)]
+
+struct SomeStruct<T> { t: T }
+
+#[rustc_dump_user_substs]
+fn main() {
+    SomeStruct { t: 22 }; // Nothing given, no annotation.
+
+    SomeStruct::<_> { t: 22 }; // Nothing interesting given, no annotation.
+
+    SomeStruct::<u32> { t: 22 }; // No lifetime bounds given.
+
+    SomeStruct::<&'static u32> { t: &22 }; //~ ERROR [&ReStatic u32]
+}
diff --git a/src/test/ui/nll/user-annotations/dump-adt-brace-struct.stderr b/src/test/ui/nll/user-annotations/dump-adt-brace-struct.stderr
new file mode 100644
index 0000000..ae123b8
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/dump-adt-brace-struct.stderr
@@ -0,0 +1,8 @@
+error: user substs: UserSubsts { substs: [&ReStatic u32], user_self_ty: None }
+  --> $DIR/dump-adt-brace-struct.rs:20:5
+   |
+LL |     SomeStruct::<&'static u32> { t: &22 };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/user-annotations/dump-fn-method.rs b/src/test/ui/nll/user-annotations/dump-fn-method.rs
new file mode 100644
index 0000000..b689f18
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/dump-fn-method.rs
@@ -0,0 +1,58 @@
+// Unit test for the "user substitutions" that are annotated on each
+// node.
+
+// compile-flags:-Zverbose
+
+#![feature(nll)]
+#![feature(rustc_attrs)]
+
+// Note: we reference the names T and U in the comments below.
+trait Bazoom<T> {
+    fn method<U>(&self, arg: T, arg2: U) { }
+}
+
+impl<S, T> Bazoom<T> for S {
+}
+
+fn foo<'a, T>(_: T) { }
+
+#[rustc_dump_user_substs]
+fn main() {
+    // Here: nothing is given, so we don't have any annotation.
+    let x = foo;
+    x(22);
+
+    // Here: `u32` is given, which doesn't contain any lifetimes, so we don't
+    // have any annotation.
+    let x = foo::<u32>;
+    x(22);
+
+    let x = foo::<&'static u32>; //~ ERROR [&ReStatic u32]
+    x(&22);
+
+    // Here: we only want the `T` to be given, the rest should be variables.
+    //
+    // (`T` refers to the declaration of `Bazoom`)
+    let x = <_ as Bazoom<u32>>::method::<_>; //~ ERROR [^0, u32, ^1]
+    x(&22, 44, 66);
+
+    // Here: all are given and definitely contain no lifetimes, so we
+    // don't have any annotation.
+    let x = <u8 as Bazoom<u16>>::method::<u32>;
+    x(&22, 44, 66);
+
+    // Here: all are given and we have a lifetime.
+    let x = <u8 as Bazoom<&'static u16>>::method::<u32>; //~ ERROR [u8, &ReStatic u16, u32]
+    x(&22, &44, 66);
+
+    // Here: we want in particular that *only* the method `U`
+    // annotation is given, the rest are variables.
+    //
+    // (`U` refers to the declaration of `Bazoom`)
+    let y = 22_u32;
+    y.method::<u32>(44, 66); //~ ERROR [^0, ^1, u32]
+
+    // Here: nothing is given, so we don't have any annotation.
+    let y = 22_u32;
+    y.method(44, 66);
+}
diff --git a/src/test/ui/nll/user-annotations/dump-fn-method.stderr b/src/test/ui/nll/user-annotations/dump-fn-method.stderr
new file mode 100644
index 0000000..631bcde
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/dump-fn-method.stderr
@@ -0,0 +1,26 @@
+error: user substs: UserSubsts { substs: [&ReStatic u32], user_self_ty: None }
+  --> $DIR/dump-fn-method.rs:30:13
+   |
+LL |     let x = foo::<&'static u32>;
+   |             ^^^^^^^^^^^^^^^^^^^
+
+error: user substs: UserSubsts { substs: [^0, u32, ^1], user_self_ty: None }
+  --> $DIR/dump-fn-method.rs:36:13
+   |
+LL |     let x = <_ as Bazoom<u32>>::method::<_>;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: user substs: UserSubsts { substs: [u8, &ReStatic u16, u32], user_self_ty: None }
+  --> $DIR/dump-fn-method.rs:45:13
+   |
+LL |     let x = <u8 as Bazoom<&'static u16>>::method::<u32>;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: user substs: UserSubsts { substs: [^0, ^1, u32], user_self_ty: None }
+  --> $DIR/dump-fn-method.rs:53:5
+   |
+LL |     y.method::<u32>(44, 66);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/nll/user-annotations/fns.rs b/src/test/ui/nll/user-annotations/fns.rs
new file mode 100644
index 0000000..1e5e934
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/fns.rs
@@ -0,0 +1,50 @@
+// Unit test for the "user substitutions" that are annotated on each
+// node.
+
+#![feature(nll)]
+
+fn some_fn<T>(arg: T) { }
+
+fn no_annot() {
+    let c = 66;
+    some_fn(&c); // OK
+}
+
+fn annot_underscore() {
+    let c = 66;
+    some_fn::<_>(&c); // OK
+}
+
+fn annot_reference_any_lifetime() {
+    let c = 66;
+    some_fn::<&u32>(&c); // OK
+}
+
+fn annot_reference_static_lifetime() {
+    let c = 66;
+    some_fn::<&'static u32>(&c); //~ ERROR
+}
+
+fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+    let c = 66;
+    some_fn::<&'a u32>(&c); //~ ERROR
+}
+
+fn annot_reference_named_lifetime_ok<'a>(c: &'a u32) {
+    some_fn::<&'a u32>(c);
+}
+
+fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+    let _closure = || {
+        let c = 66;
+        some_fn::<&'a u32>(&c); //~ ERROR
+    };
+}
+
+fn annot_reference_named_lifetime_in_closure_ok<'a>(c: &'a u32) {
+    let _closure = || {
+        some_fn::<&'a u32>(c);
+    };
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/user-annotations/fns.stderr b/src/test/ui/nll/user-annotations/fns.stderr
new file mode 100644
index 0000000..dadce24
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/fns.stderr
@@ -0,0 +1,42 @@
+error[E0597]: `c` does not live long enough
+  --> $DIR/fns.rs:25:29
+   |
+LL |     some_fn::<&'static u32>(&c);
+   |     ------------------------^^-
+   |     |                       |
+   |     |                       borrowed value does not live long enough
+   |     argument requires that `c` is borrowed for `'static`
+LL | }
+   | - `c` dropped here while still borrowed
+
+error[E0597]: `c` does not live long enough
+  --> $DIR/fns.rs:30:24
+   |
+LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+   |                                   -- lifetime `'a` defined here
+LL |     let c = 66;
+LL |     some_fn::<&'a u32>(&c);
+   |     -------------------^^-
+   |     |                  |
+   |     |                  borrowed value does not live long enough
+   |     argument requires that `c` is borrowed for `'a`
+LL | }
+   | - `c` dropped here while still borrowed
+
+error[E0597]: `c` does not live long enough
+  --> $DIR/fns.rs:40:28
+   |
+LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+   |                                              -- lifetime `'a` defined here
+...
+LL |         some_fn::<&'a u32>(&c);
+   |         -------------------^^-
+   |         |                  |
+   |         |                  borrowed value does not live long enough
+   |         argument requires that `c` is borrowed for `'a`
+LL |     };
+   |     - `c` dropped here while still borrowed
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/user-annotations/inherent-associated-constants.rs b/src/test/ui/nll/user-annotations/inherent-associated-constants.rs
new file mode 100644
index 0000000..2490187
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/inherent-associated-constants.rs
@@ -0,0 +1,17 @@
+#![feature(nll)]
+
+struct A<'a>(&'a ());
+
+impl A<'static> {
+    const IC: i32 = 10;
+}
+
+fn non_wf_associated_const<'a>(x: i32) {
+    A::<'a>::IC; //~ ERROR lifetime may not live long enough
+}
+
+fn wf_associated_const<'a>(x: i32) {
+    A::<'static>::IC;
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/user-annotations/inherent-associated-constants.stderr b/src/test/ui/nll/user-annotations/inherent-associated-constants.stderr
new file mode 100644
index 0000000..7684546
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/inherent-associated-constants.stderr
@@ -0,0 +1,10 @@
+error: lifetime may not live long enough
+  --> $DIR/inherent-associated-constants.rs:10:5
+   |
+LL | fn non_wf_associated_const<'a>(x: i32) {
+   |                            -- lifetime `'a` defined here
+LL |     A::<'a>::IC;
+   |     ^^^^^^^^^^^ requires that `'a` must outlive `'static`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/user-annotations/issue-54124.rs b/src/test/ui/nll/user-annotations/issue-54124.rs
new file mode 100644
index 0000000..e1de67a
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/issue-54124.rs
@@ -0,0 +1,10 @@
+#![feature(nll)]
+
+fn test<'a>() {
+    let _:fn(&()) = |_:&'a ()| {}; //~ ERROR lifetime may not live long enough
+    //~^ ERROR lifetime may not live long enough
+}
+
+fn main() {
+    test();
+}
diff --git a/src/test/ui/nll/user-annotations/issue-54124.stderr b/src/test/ui/nll/user-annotations/issue-54124.stderr
new file mode 100644
index 0000000..6cfccf7
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/issue-54124.stderr
@@ -0,0 +1,20 @@
+error: lifetime may not live long enough
+  --> $DIR/issue-54124.rs:4:22
+   |
+LL | fn test<'a>() {
+   |         -- lifetime `'a` defined here
+LL |     let _:fn(&()) = |_:&'a ()| {};
+   |                      ^ - let's call the lifetime of this reference `'1`
+   |                      |
+   |                      requires that `'1` must outlive `'a`
+
+error: lifetime may not live long enough
+  --> $DIR/issue-54124.rs:4:22
+   |
+LL | fn test<'a>() {
+   |         -- lifetime `'a` defined here
+LL |     let _:fn(&()) = |_:&'a ()| {};
+   |                      ^ requires that `'a` must outlive `'static`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/nll/user-annotations/issue-54570-bootstrapping.rs b/src/test/ui/nll/user-annotations/issue-54570-bootstrapping.rs
new file mode 100644
index 0000000..0a8a679
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/issue-54570-bootstrapping.rs
@@ -0,0 +1,31 @@
+// compile-pass
+#![feature(nll)]
+
+// This test is reduced from a scenario pnkfelix encountered while
+// bootstrapping the compiler.
+
+#[derive(Copy, Clone)]
+pub struct Spanned<T> {
+    pub node: T,
+    pub span: Span,
+}
+
+pub type Variant = Spanned<VariantKind>;
+// #[derive(Clone)] pub struct Variant { pub node: VariantKind, pub span: Span, }
+
+#[derive(Clone)]
+pub struct VariantKind { }
+
+#[derive(Copy, Clone)]
+pub struct Span;
+
+pub fn variant_to_span(variant: Variant) {
+    match variant {
+        Variant {
+            span: _span,
+            ..
+        } => { }
+    };
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/user-annotations/issue-55219.rs b/src/test/ui/nll/user-annotations/issue-55219.rs
new file mode 100644
index 0000000..7daa5a5
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/issue-55219.rs
@@ -0,0 +1,20 @@
+// Regression test for #55219:
+//
+// The `Self::HASH_LEN` here expands to a "self-type" where `T` is not
+// known. This unbound inference variable was causing an ICE.
+//
+// run-pass
+
+#![feature(nll)]
+
+pub struct Foo<T>(T);
+
+impl<T> Foo<T> {
+    const HASH_LEN: usize = 20;
+
+    fn stuff() {
+        let _ = Self::HASH_LEN;
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/user-annotations/issue-55241.rs b/src/test/ui/nll/user-annotations/issue-55241.rs
new file mode 100644
index 0000000..d7686b9
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/issue-55241.rs
@@ -0,0 +1,28 @@
+// Regression test for #55241:
+//
+// The reference to `C::HASHED_NULL_NODE` resulted in a type like `<C
+// as NodeCodec<_>>::Out`; normalizing this type requires knowing the
+// value of `_`; solving that requires having normalized, so we can
+// test against `C: NodeCodec<H>` in the environment.
+//
+// run-pass
+
+#![feature(nll)]
+
+pub trait Hasher {
+    type Out: Eq;
+}
+
+pub trait NodeCodec<H: Hasher> {
+    const HASHED_NULL_NODE: H::Out;
+}
+
+pub trait Trie<H: Hasher, C: NodeCodec<H>> {
+    /// Returns the root of the trie.
+    fn root(&self) -> &H::Out;
+
+    /// Is the trie empty?
+    fn is_empty(&self) -> bool { *self.root() == C::HASHED_NULL_NODE }
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/user-annotations/issue-55748-pat-types-constrain-bindings.rs b/src/test/ui/nll/user-annotations/issue-55748-pat-types-constrain-bindings.rs
new file mode 100644
index 0000000..3d042d4
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/issue-55748-pat-types-constrain-bindings.rs
@@ -0,0 +1,70 @@
+// This test is ensuring that type ascriptions on let bindings
+// constrain both:
+//
+// 1. the input expression on the right-hand side (after any potential
+//    coercion, and allowing for covariance), *and*
+//
+// 2. the bindings (if any) nested within the pattern on the left-hand
+//    side (and here, the type-constraint is *invariant*).
+
+#![feature(nll)]
+
+#![allow(dead_code, unused_mut)]
+type PairUncoupled<'a, 'b, T> = (&'a T, &'b T);
+type PairCoupledRegions<'a, T> = (&'a T, &'a T);
+type PairCoupledTypes<T> = (T, T);
+
+fn uncoupled_lhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+    let ((mut y, mut _z),): (PairUncoupled<u32>,) = ((s, &_x),); // ok
+    // Above compiling does *not* imply below would compile.
+    // ::std::mem::swap(&mut y, &mut _z);
+    y
+}
+
+fn swap_regions((mut y, mut _z): PairCoupledRegions<u32>) {
+    ::std::mem::swap(&mut y, &mut _z);
+}
+
+fn coupled_regions_lhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+    let ((y, _z),): (PairCoupledRegions<u32>,) = ((s, &_x),);
+    // If above line compiled, so should line below ...
+
+    // swap_regions((y, _z));
+
+    // ... but the ascribed type also invalidates this use of `y`
+    y //~ ERROR lifetime may not live long enough
+}
+
+fn swap_types((mut y, mut _z): PairCoupledTypes<&u32>) {
+    ::std::mem::swap(&mut y, &mut _z);
+}
+
+fn coupled_types_lhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+    let ((y, _z),): (PairCoupledTypes<&u32>,) = ((s, &_x),);
+    // If above line compiled, so should line below ...
+
+    // swap_types((y, _z));
+
+    // ... but the ascribed type also invalidates this use of `y`
+    y //~ ERROR lifetime may not live long enough
+}
+
+fn swap_wilds((mut y, mut _z): PairCoupledTypes<&u32>) {
+    ::std::mem::swap(&mut y, &mut _z);
+}
+
+fn coupled_wilds_lhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+    let ((y, _z),): (PairCoupledTypes<_>,) = ((s, &_x),);
+    // If above line compiled, so should line below
+    // swap_wilds((y, _z));
+
+    // ... but the ascribed type also invalidates this use of `y`
+    y //~ ERROR lifetime may not live long enough
+}
+
+fn main() {
+    uncoupled_lhs(&3, &4);
+    coupled_regions_lhs(&3, &4);
+    coupled_types_lhs(&3, &4);
+    coupled_wilds_lhs(&3, &4);
+}
diff --git a/src/test/ui/nll/user-annotations/issue-55748-pat-types-constrain-bindings.stderr b/src/test/ui/nll/user-annotations/issue-55748-pat-types-constrain-bindings.stderr
new file mode 100644
index 0000000..5929707
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/issue-55748-pat-types-constrain-bindings.stderr
@@ -0,0 +1,29 @@
+error: lifetime may not live long enough
+  --> $DIR/issue-55748-pat-types-constrain-bindings.rs:35:5
+   |
+LL | fn coupled_regions_lhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+   |                        -- lifetime `'a` defined here
+...
+LL |     y
+   |     ^ returning this value requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/issue-55748-pat-types-constrain-bindings.rs:49:5
+   |
+LL | fn coupled_types_lhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+   |                      -- lifetime `'a` defined here
+...
+LL |     y
+   |     ^ returning this value requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/issue-55748-pat-types-constrain-bindings.rs:62:5
+   |
+LL | fn coupled_wilds_lhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+   |                      -- lifetime `'a` defined here
+...
+LL |     y
+   |     ^ returning this value requires that `'a` must outlive `'static`
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/nll/user-annotations/issue-57731-ascibed-coupled-types.rs b/src/test/ui/nll/user-annotations/issue-57731-ascibed-coupled-types.rs
new file mode 100644
index 0000000..f4969bb
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/issue-57731-ascibed-coupled-types.rs
@@ -0,0 +1,40 @@
+// Check that repeated type variables are correctly handled
+
+#![allow(unused)]
+#![feature(nll, type_ascription)]
+
+type PairUncoupled<'a, 'b, T> = (&'a T, &'b T);
+type PairCoupledTypes<T> = (T, T);
+type PairCoupledRegions<'a, T> = (&'a T, &'a T);
+
+fn uncoupled_wilds_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+    let ((y, _z),) = ((s, _x),): (PairUncoupled<_>,);
+    y // OK
+}
+
+fn coupled_wilds_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+    let ((y, _z),) = ((s, _x),): (PairCoupledTypes<_>,);
+    y //~ ERROR lifetime may not live long enough
+}
+
+fn coupled_regions_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+    let ((y, _z),) = ((s, _x),): (PairCoupledRegions<_>,);
+    y //~ ERROR lifetime may not live long enough
+}
+
+fn cast_uncoupled_wilds_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+    let ((y, _z),) = ((s, _x),) as (PairUncoupled<_>,);
+    y // OK
+}
+
+fn cast_coupled_wilds_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+    let ((y, _z),) = ((s, _x),) as (PairCoupledTypes<_>,);
+    y //~ ERROR lifetime may not live long enough
+}
+
+fn cast_coupled_regions_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+    let ((y, _z),) = ((s, _x),) as (PairCoupledRegions<_>,);
+    y //~ ERROR lifetime may not live long enough
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/user-annotations/issue-57731-ascibed-coupled-types.stderr b/src/test/ui/nll/user-annotations/issue-57731-ascibed-coupled-types.stderr
new file mode 100644
index 0000000..c99f53c
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/issue-57731-ascibed-coupled-types.stderr
@@ -0,0 +1,38 @@
+error: lifetime may not live long enough
+  --> $DIR/issue-57731-ascibed-coupled-types.rs:17:5
+   |
+LL | fn coupled_wilds_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+   |                      -- lifetime `'a` defined here
+LL |     let ((y, _z),) = ((s, _x),): (PairCoupledTypes<_>,);
+LL |     y
+   |     ^ returning this value requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/issue-57731-ascibed-coupled-types.rs:22:5
+   |
+LL | fn coupled_regions_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+   |                        -- lifetime `'a` defined here
+LL |     let ((y, _z),) = ((s, _x),): (PairCoupledRegions<_>,);
+LL |     y
+   |     ^ returning this value requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/issue-57731-ascibed-coupled-types.rs:32:5
+   |
+LL | fn cast_coupled_wilds_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+   |                           -- lifetime `'a` defined here
+LL |     let ((y, _z),) = ((s, _x),) as (PairCoupledTypes<_>,);
+LL |     y
+   |     ^ returning this value requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/issue-57731-ascibed-coupled-types.rs:37:5
+   |
+LL | fn cast_coupled_regions_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+   |                             -- lifetime `'a` defined here
+LL |     let ((y, _z),) = ((s, _x),) as (PairCoupledRegions<_>,);
+LL |     y
+   |     ^ returning this value requires that `'a` must outlive `'static`
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/nll/user-annotations/method-call.rs b/src/test/ui/nll/user-annotations/method-call.rs
new file mode 100644
index 0000000..59d1513
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/method-call.rs
@@ -0,0 +1,71 @@
+// Unit test for the "user substitutions" that are annotated on each
+// node.
+
+#![feature(nll)]
+
+trait Bazoom<T> {
+    fn method<U>(&self, arg: T, arg2: U) { }
+}
+
+impl<T, U> Bazoom<U> for T {
+}
+
+fn no_annot() {
+    let a = 22;
+    let b = 44;
+    let c = 66;
+    a.method(b,  &c); // OK
+}
+
+fn annot_underscore() {
+    let a = 22;
+    let b = 44;
+    let c = 66;
+    a.method::<_>(b,  &c); // OK
+}
+
+fn annot_reference_any_lifetime() {
+    let a = 22;
+    let b = 44;
+    let c = 66;
+    a.method::<&u32>(b,  &c); // OK
+}
+
+fn annot_reference_static_lifetime() {
+    let a = 22;
+    let b = 44;
+    let c = 66;
+    a.method::<&'static u32>(b,  &c); //~ ERROR
+}
+
+fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+    let a = 22;
+    let b = 44;
+    let c = 66;
+    a.method::<&'a u32>(b,  &c); //~ ERROR
+}
+
+fn annot_reference_named_lifetime_ok<'a>(c: &'a u32) {
+    let a = 22;
+    let b = 44;
+    a.method::<&'a u32>(b,  c);
+}
+
+fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+    let a = 22;
+    let b = 44;
+    let _closure = || {
+        let c = 66;
+        a.method::<&'a u32>(b,  &c); //~ ERROR
+    };
+}
+
+fn annot_reference_named_lifetime_in_closure_ok<'a>(c: &'a u32) {
+    let a = 22;
+    let b = 44;
+    let _closure = || {
+        a.method::<&'a u32>(b,  c);
+    };
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/user-annotations/method-call.stderr b/src/test/ui/nll/user-annotations/method-call.stderr
new file mode 100644
index 0000000..7e53146
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/method-call.stderr
@@ -0,0 +1,42 @@
+error[E0597]: `c` does not live long enough
+  --> $DIR/method-call.rs:38:34
+   |
+LL |     a.method::<&'static u32>(b,  &c);
+   |     -----------------------------^^-
+   |     |                            |
+   |     |                            borrowed value does not live long enough
+   |     argument requires that `c` is borrowed for `'static`
+LL | }
+   | - `c` dropped here while still borrowed
+
+error[E0597]: `c` does not live long enough
+  --> $DIR/method-call.rs:45:29
+   |
+LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+   |                                   -- lifetime `'a` defined here
+...
+LL |     a.method::<&'a u32>(b,  &c);
+   |     ------------------------^^-
+   |     |                       |
+   |     |                       borrowed value does not live long enough
+   |     argument requires that `c` is borrowed for `'a`
+LL | }
+   | - `c` dropped here while still borrowed
+
+error[E0597]: `c` does not live long enough
+  --> $DIR/method-call.rs:59:33
+   |
+LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+   |                                              -- lifetime `'a` defined here
+...
+LL |         a.method::<&'a u32>(b,  &c);
+   |         ------------------------^^-
+   |         |                       |
+   |         |                       borrowed value does not live long enough
+   |         argument requires that `c` is borrowed for `'a`
+LL |     };
+   |     - `c` dropped here while still borrowed
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/user-annotations/method-ufcs-1.rs b/src/test/ui/nll/user-annotations/method-ufcs-1.rs
new file mode 100644
index 0000000..7968a9f
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/method-ufcs-1.rs
@@ -0,0 +1,65 @@
+// Unit test for the "user substitutions" that are annotated on each
+// node.
+
+#![feature(nll)]
+
+trait Bazoom<T>: Sized {
+    fn method<U>(self, arg: T, arg2: U) { }
+}
+
+impl<T, U> Bazoom<U> for T {
+}
+
+fn annot_underscore() {
+    let a = 22;
+    let b = 44;
+    let c = 66;
+    <_ as Bazoom<_>>::method::<_>(&a, b, c); // OK
+}
+
+fn annot_reference_any_lifetime() {
+    let a = 22;
+    let b = 44;
+    let c = 66;
+    <&u32 as Bazoom<_>>::method(&a, b, c); // OK
+}
+
+fn annot_reference_static_lifetime() {
+    let a = 22;
+    let b = 44;
+    let c = 66;
+    let x = <&'static u32 as Bazoom<_>>::method;
+    x(&a, b, c); //~ ERROR
+}
+
+fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+    let a = 22;
+    let b = 44;
+    let c = 66;
+    <&'a u32 as Bazoom<_>>::method(&a, b, c); //~ ERROR
+}
+
+fn annot_reference_named_lifetime_ok<'a>(a: &'a u32) {
+    let b = 44;
+    let c = 66;
+    <&'a u32 as Bazoom<_>>::method(&a, b, c);
+}
+
+fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+    let a = 22;
+    let b = 44;
+    let _closure = || {
+        let c = 66;
+        <&'a u32 as Bazoom<_>>::method(&a, b, c); //~ ERROR
+    };
+}
+
+fn annot_reference_named_lifetime_in_closure_ok<'a>(a: &'a u32) {
+    let b = 44;
+    let c = 66;
+    let _closure = || {
+        <&'a u32 as Bazoom<_>>::method(&a, b, c);
+    };
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/user-annotations/method-ufcs-1.stderr b/src/test/ui/nll/user-annotations/method-ufcs-1.stderr
new file mode 100644
index 0000000..12b02ba
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/method-ufcs-1.stderr
@@ -0,0 +1,46 @@
+error[E0597]: `a` does not live long enough
+  --> $DIR/method-ufcs-1.rs:32:7
+   |
+LL |     x(&a, b, c);
+   |     --^^-------
+   |     | |
+   |     | borrowed value does not live long enough
+   |     argument requires that `a` is borrowed for `'static`
+LL | }
+   | - `a` dropped here while still borrowed
+
+error[E0597]: `a` does not live long enough
+  --> $DIR/method-ufcs-1.rs:39:36
+   |
+LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+   |                                   -- lifetime `'a` defined here
+...
+LL |     <&'a u32 as Bazoom<_>>::method(&a, b, c);
+   |     -------------------------------^^-------
+   |     |                              |
+   |     |                              borrowed value does not live long enough
+   |     argument requires that `a` is borrowed for `'a`
+LL | }
+   | - `a` dropped here while still borrowed
+
+error[E0597]: `a` does not live long enough
+  --> $DIR/method-ufcs-1.rs:53:41
+   |
+LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+   |                                              -- lifetime `'a` defined here
+...
+LL |     let _closure = || {
+   |                    -- value captured here
+LL |         let c = 66;
+LL |         <&'a u32 as Bazoom<_>>::method(&a, b, c);
+   |         --------------------------------^-------
+   |         |                               |
+   |         |                               borrowed value does not live long enough
+   |         argument requires that `a` is borrowed for `'a`
+LL |     };
+LL | }
+   | - `a` dropped here while still borrowed
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/user-annotations/method-ufcs-2.rs b/src/test/ui/nll/user-annotations/method-ufcs-2.rs
new file mode 100644
index 0000000..a1d0e7b
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/method-ufcs-2.rs
@@ -0,0 +1,65 @@
+// Unit test for the "user substitutions" that are annotated on each
+// node.
+
+#![feature(nll)]
+
+trait Bazoom<T>: Sized {
+    fn method<U>(self, arg: T, arg2: U) { }
+}
+
+impl<T, U> Bazoom<U> for T {
+}
+
+fn annot_underscore() {
+    let a = 22;
+    let b = 44;
+    let c = 66;
+    <_ as Bazoom<_>>::method(a, &b, c); // OK
+}
+
+fn annot_reference_any_lifetime() {
+    let a = 22;
+    let b = 44;
+    let c = 66;
+    <_ as Bazoom<&u32>>::method(a, &b, c); // OK
+}
+
+fn annot_reference_static_lifetime() {
+    let a = 22;
+    let b = 44;
+    let c = 66;
+    let x = <&'static u32 as Bazoom<_>>::method;
+    x(&a, b, c); //~ ERROR
+}
+
+fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+    let a = 22;
+    let b = 44;
+    let c = 66;
+    <_ as Bazoom<&'a u32>>::method(a, &b, c); //~ ERROR
+}
+
+fn annot_reference_named_lifetime_ok<'a>(b: &'a u32) {
+    let a = 44;
+    let c = 66;
+    <_ as Bazoom<&'a u32>>::method(a, &b, c);
+}
+
+fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+    let a = 22;
+    let b = 44;
+    let _closure = || {
+        let c = 66;
+        <_ as Bazoom<&'a u32>>::method(a, &b, c); //~ ERROR
+    };
+}
+
+fn annot_reference_named_lifetime_in_closure_ok<'a>(b: &'a u32) {
+    let a = 44;
+    let c = 66;
+    let _closure = || {
+        <_ as Bazoom<&'a u32>>::method(a, &b, c);
+    };
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/user-annotations/method-ufcs-2.stderr b/src/test/ui/nll/user-annotations/method-ufcs-2.stderr
new file mode 100644
index 0000000..a55ed1a
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/method-ufcs-2.stderr
@@ -0,0 +1,46 @@
+error[E0597]: `a` does not live long enough
+  --> $DIR/method-ufcs-2.rs:32:7
+   |
+LL |     x(&a, b, c);
+   |     --^^-------
+   |     | |
+   |     | borrowed value does not live long enough
+   |     argument requires that `a` is borrowed for `'static`
+LL | }
+   | - `a` dropped here while still borrowed
+
+error[E0597]: `b` does not live long enough
+  --> $DIR/method-ufcs-2.rs:39:39
+   |
+LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+   |                                   -- lifetime `'a` defined here
+...
+LL |     <_ as Bazoom<&'a u32>>::method(a, &b, c);
+   |     ----------------------------------^^----
+   |     |                                 |
+   |     |                                 borrowed value does not live long enough
+   |     argument requires that `b` is borrowed for `'a`
+LL | }
+   | - `b` dropped here while still borrowed
+
+error[E0597]: `b` does not live long enough
+  --> $DIR/method-ufcs-2.rs:53:44
+   |
+LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+   |                                              -- lifetime `'a` defined here
+...
+LL |     let _closure = || {
+   |                    -- value captured here
+LL |         let c = 66;
+LL |         <_ as Bazoom<&'a u32>>::method(a, &b, c);
+   |         -----------------------------------^----
+   |         |                                  |
+   |         |                                  borrowed value does not live long enough
+   |         argument requires that `b` is borrowed for `'a`
+LL |     };
+LL | }
+   | - `b` dropped here while still borrowed
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/user-annotations/method-ufcs-3.rs b/src/test/ui/nll/user-annotations/method-ufcs-3.rs
new file mode 100644
index 0000000..ea480c0
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/method-ufcs-3.rs
@@ -0,0 +1,71 @@
+// Unit test for the "user substitutions" that are annotated on each
+// node.
+
+#![feature(nll)]
+
+trait Bazoom<T> {
+    fn method<U>(&self, arg: T, arg2: U) { }
+}
+
+impl<T, U> Bazoom<U> for T {
+}
+
+fn no_annot() {
+    let a = 22;
+    let b = 44;
+    let c = 66;
+    <_ as Bazoom<_>>::method(&a, b, &c); // OK
+}
+
+fn annot_underscore() {
+    let a = 22;
+    let b = 44;
+    let c = 66;
+    <_ as Bazoom<_>>::method::<_>(&a, b, &c); // OK
+}
+
+fn annot_reference_any_lifetime() {
+    let a = 22;
+    let b = 44;
+    let c = 66;
+    <_ as Bazoom<_>>::method::<&u32>(&a, b, &c); // OK
+}
+
+fn annot_reference_static_lifetime() {
+    let a = 22;
+    let b = 44;
+    let c = 66;
+    <_ as Bazoom<_>>::method::<&'static u32>(&a, b, &c); //~ ERROR
+}
+
+fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+    let a = 22;
+    let b = 44;
+    let c = 66;
+    <_ as Bazoom<_>>::method::<&'a u32>(&a, b, &c); //~ ERROR
+}
+
+fn annot_reference_named_lifetime_ok<'a>(c: &'a u32) {
+    let a = 22;
+    let b = 44;
+    <_ as Bazoom<_>>::method::<&'a u32>(&a, b, c);
+}
+
+fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+    let a = 22;
+    let b = 44;
+    let _closure = || {
+        let c = 66;
+        <_ as Bazoom<_>>::method::<&'a u32>(&a, b, &c); //~ ERROR
+    };
+}
+
+fn annot_reference_named_lifetime_in_closure_ok<'a>(c: &'a u32) {
+    let a = 22;
+    let b = 44;
+    let _closure = || {
+        <_ as Bazoom<_>>::method::<&'a u32>(&a, b, c);
+    };
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/user-annotations/method-ufcs-3.stderr b/src/test/ui/nll/user-annotations/method-ufcs-3.stderr
new file mode 100644
index 0000000..140bda2
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/method-ufcs-3.stderr
@@ -0,0 +1,42 @@
+error[E0597]: `c` does not live long enough
+  --> $DIR/method-ufcs-3.rs:38:53
+   |
+LL |     <_ as Bazoom<_>>::method::<&'static u32>(&a, b, &c);
+   |     ------------------------------------------------^^-
+   |     |                                               |
+   |     |                                               borrowed value does not live long enough
+   |     argument requires that `c` is borrowed for `'static`
+LL | }
+   | - `c` dropped here while still borrowed
+
+error[E0597]: `c` does not live long enough
+  --> $DIR/method-ufcs-3.rs:45:48
+   |
+LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+   |                                   -- lifetime `'a` defined here
+...
+LL |     <_ as Bazoom<_>>::method::<&'a u32>(&a, b, &c);
+   |     -------------------------------------------^^-
+   |     |                                          |
+   |     |                                          borrowed value does not live long enough
+   |     argument requires that `c` is borrowed for `'a`
+LL | }
+   | - `c` dropped here while still borrowed
+
+error[E0597]: `c` does not live long enough
+  --> $DIR/method-ufcs-3.rs:59:52
+   |
+LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+   |                                              -- lifetime `'a` defined here
+...
+LL |         <_ as Bazoom<_>>::method::<&'a u32>(&a, b, &c);
+   |         -------------------------------------------^^-
+   |         |                                          |
+   |         |                                          borrowed value does not live long enough
+   |         argument requires that `c` is borrowed for `'a`
+LL |     };
+   |     - `c` dropped here while still borrowed
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/user-annotations/method-ufcs-inherent-1.rs b/src/test/ui/nll/user-annotations/method-ufcs-inherent-1.rs
new file mode 100644
index 0000000..b7292c0
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/method-ufcs-inherent-1.rs
@@ -0,0 +1,20 @@
+#![feature(nll)]
+
+// Check that substitutions given on the self type (here, `A`) carry
+// through to NLL.
+
+struct A<'a> { x: &'a u32 }
+
+impl<'a> A<'a> {
+    fn new<'b, T>(x: &'a u32, y: T) -> Self {
+        Self { x }
+    }
+}
+
+fn foo<'a>() {
+    let v = 22;
+    let x = A::<'a>::new(&v, 22);
+    //~^ ERROR
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/user-annotations/method-ufcs-inherent-1.stderr b/src/test/ui/nll/user-annotations/method-ufcs-inherent-1.stderr
new file mode 100644
index 0000000..70e1cda
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/method-ufcs-inherent-1.stderr
@@ -0,0 +1,18 @@
+error[E0597]: `v` does not live long enough
+  --> $DIR/method-ufcs-inherent-1.rs:16:26
+   |
+LL | fn foo<'a>() {
+   |        -- lifetime `'a` defined here
+LL |     let v = 22;
+LL |     let x = A::<'a>::new(&v, 22);
+   |             -------------^^-----
+   |             |            |
+   |             |            borrowed value does not live long enough
+   |             argument requires that `v` is borrowed for `'a`
+LL |
+LL | }
+   | - `v` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/user-annotations/method-ufcs-inherent-2.rs b/src/test/ui/nll/user-annotations/method-ufcs-inherent-2.rs
new file mode 100644
index 0000000..a77d6af
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/method-ufcs-inherent-2.rs
@@ -0,0 +1,21 @@
+#![feature(nll)]
+
+// Check that substitutions given on the self type (here, `A`) can be
+// used in combination with annotations given for method arguments.
+
+struct A<'a> { x: &'a u32 }
+
+impl<'a> A<'a> {
+    fn new<'b, T>(x: &'a u32, y: T) -> Self {
+        Self { x }
+    }
+}
+
+fn foo<'a>() {
+    let v = 22;
+    let x = A::<'a>::new::<&'a u32>(&v, &v);
+    //~^ ERROR
+    //~| ERROR
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/user-annotations/method-ufcs-inherent-2.stderr b/src/test/ui/nll/user-annotations/method-ufcs-inherent-2.stderr
new file mode 100644
index 0000000..4dc534b
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/method-ufcs-inherent-2.stderr
@@ -0,0 +1,33 @@
+error[E0597]: `v` does not live long enough
+  --> $DIR/method-ufcs-inherent-2.rs:16:37
+   |
+LL | fn foo<'a>() {
+   |        -- lifetime `'a` defined here
+LL |     let v = 22;
+LL |     let x = A::<'a>::new::<&'a u32>(&v, &v);
+   |             ------------------------^^-----
+   |             |                       |
+   |             |                       borrowed value does not live long enough
+   |             argument requires that `v` is borrowed for `'a`
+...
+LL | }
+   | - `v` dropped here while still borrowed
+
+error[E0597]: `v` does not live long enough
+  --> $DIR/method-ufcs-inherent-2.rs:16:41
+   |
+LL | fn foo<'a>() {
+   |        -- lifetime `'a` defined here
+LL |     let v = 22;
+LL |     let x = A::<'a>::new::<&'a u32>(&v, &v);
+   |             ----------------------------^^-
+   |             |                           |
+   |             |                           borrowed value does not live long enough
+   |             argument requires that `v` is borrowed for `'a`
+...
+LL | }
+   | - `v` dropped here while still borrowed
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/user-annotations/method-ufcs-inherent-3.rs b/src/test/ui/nll/user-annotations/method-ufcs-inherent-3.rs
new file mode 100644
index 0000000..24d83c4
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/method-ufcs-inherent-3.rs
@@ -0,0 +1,20 @@
+#![feature(nll)]
+
+// Check that inherent methods invoked with `<T>::new` style
+// carry their annotations through to NLL.
+
+struct A<'a> { x: &'a u32 }
+
+impl<'a> A<'a> {
+    fn new<'b, T>(x: &'a u32, y: T) -> Self {
+        Self { x }
+    }
+}
+
+fn foo<'a>() {
+    let v = 22;
+    let x = <A<'a>>::new(&v, 22);
+    //~^ ERROR
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/user-annotations/method-ufcs-inherent-3.stderr b/src/test/ui/nll/user-annotations/method-ufcs-inherent-3.stderr
new file mode 100644
index 0000000..50e4fb2
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/method-ufcs-inherent-3.stderr
@@ -0,0 +1,18 @@
+error[E0597]: `v` does not live long enough
+  --> $DIR/method-ufcs-inherent-3.rs:16:26
+   |
+LL | fn foo<'a>() {
+   |        -- lifetime `'a` defined here
+LL |     let v = 22;
+LL |     let x = <A<'a>>::new(&v, 22);
+   |             -------------^^-----
+   |             |            |
+   |             |            borrowed value does not live long enough
+   |             argument requires that `v` is borrowed for `'a`
+LL |
+LL | }
+   | - `v` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/user-annotations/method-ufcs-inherent-4.rs b/src/test/ui/nll/user-annotations/method-ufcs-inherent-4.rs
new file mode 100644
index 0000000..3f88c3d
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/method-ufcs-inherent-4.rs
@@ -0,0 +1,22 @@
+#![feature(nll)]
+
+// Check that inherent methods invoked with `<T>::new` style
+// carry their annotations through to NLL in connection with
+// method type parameters.
+
+struct A<'a> { x: &'a u32 }
+
+impl<'a> A<'a> {
+    fn new<'b, T>(x: &'a u32, y: T) -> Self {
+        Self { x }
+    }
+}
+
+fn foo<'a>() {
+    let v = 22;
+    let x = <A<'a>>::new::<&'a u32>(&v, &v);
+    //~^ ERROR
+    //~| ERROR
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/user-annotations/method-ufcs-inherent-4.stderr b/src/test/ui/nll/user-annotations/method-ufcs-inherent-4.stderr
new file mode 100644
index 0000000..a41cf50
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/method-ufcs-inherent-4.stderr
@@ -0,0 +1,33 @@
+error[E0597]: `v` does not live long enough
+  --> $DIR/method-ufcs-inherent-4.rs:17:37
+   |
+LL | fn foo<'a>() {
+   |        -- lifetime `'a` defined here
+LL |     let v = 22;
+LL |     let x = <A<'a>>::new::<&'a u32>(&v, &v);
+   |             ------------------------^^-----
+   |             |                       |
+   |             |                       borrowed value does not live long enough
+   |             argument requires that `v` is borrowed for `'a`
+...
+LL | }
+   | - `v` dropped here while still borrowed
+
+error[E0597]: `v` does not live long enough
+  --> $DIR/method-ufcs-inherent-4.rs:17:41
+   |
+LL | fn foo<'a>() {
+   |        -- lifetime `'a` defined here
+LL |     let v = 22;
+LL |     let x = <A<'a>>::new::<&'a u32>(&v, &v);
+   |             ----------------------------^^-
+   |             |                           |
+   |             |                           borrowed value does not live long enough
+   |             argument requires that `v` is borrowed for `'a`
+...
+LL | }
+   | - `v` dropped here while still borrowed
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/user-annotations/normalization.rs b/src/test/ui/nll/user-annotations/normalization.rs
new file mode 100644
index 0000000..e0af2e6
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/normalization.rs
@@ -0,0 +1,12 @@
+// Test that we enforce a `&'static` requirement that is only visible
+// after normalization.
+
+#![feature(nll)]
+
+trait Foo { type Out; }
+impl Foo for () { type Out = &'static u32; }
+
+fn main() {
+    let a = 22;
+    let b: <() as Foo>::Out = &a; //~ ERROR
+}
diff --git a/src/test/ui/nll/user-annotations/normalization.stderr b/src/test/ui/nll/user-annotations/normalization.stderr
new file mode 100644
index 0000000..fe93c3e
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/normalization.stderr
@@ -0,0 +1,13 @@
+error[E0597]: `a` does not live long enough
+  --> $DIR/normalization.rs:11:31
+   |
+LL |     let b: <() as Foo>::Out = &a;
+   |            ----------------   ^^ borrowed value does not live long enough
+   |            |
+   |            type annotation requires that `a` is borrowed for `'static`
+LL | }
+   | - `a` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/user-annotations/normalize-self-ty.rs b/src/test/ui/nll/user-annotations/normalize-self-ty.rs
new file mode 100644
index 0000000..d97cc88
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/normalize-self-ty.rs
@@ -0,0 +1,25 @@
+// Regression test for #55183: check a case where the self type from
+// the inherent impl requires normalization to be equal to the
+// user-provided type.
+//
+// run-pass
+
+#![feature(nll)]
+
+trait Mirror {
+    type Me;
+}
+
+impl<T> Mirror for T {
+    type Me = T;
+}
+
+struct Foo<A, B>(A, B);
+
+impl<A> Foo<A, <A as Mirror>::Me> {
+    fn m(b: A) { }
+}
+
+fn main() {
+    <Foo<&'static u32, &u32>>::m(&22);
+}
diff --git a/src/test/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.rs b/src/test/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.rs
new file mode 100644
index 0000000..526134b
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.rs
@@ -0,0 +1,24 @@
+#![feature(nll)]
+
+enum Foo<'a> {
+    Bar { field: &'a u32 }
+}
+
+fn in_let() {
+    let y = 22;
+    let foo = Foo::Bar { field: &y };
+    //~^ ERROR `y` does not live long enough
+    let Foo::Bar::<'static> { field: _z } = foo;
+}
+
+fn in_match() {
+    let y = 22;
+    let foo = Foo::Bar { field: &y };
+    //~^ ERROR `y` does not live long enough
+    match foo {
+        Foo::Bar::<'static> { field: _z } => {
+        }
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.stderr b/src/test/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.stderr
new file mode 100644
index 0000000..b483f21
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.stderr
@@ -0,0 +1,26 @@
+error[E0597]: `y` does not live long enough
+  --> $DIR/pattern_substs_on_brace_enum_variant.rs:9:33
+   |
+LL |     let foo = Foo::Bar { field: &y };
+   |                                 ^^ borrowed value does not live long enough
+LL |
+LL |     let Foo::Bar::<'static> { field: _z } = foo;
+   |         --------------------------------- type annotation requires that `y` is borrowed for `'static`
+LL | }
+   | - `y` dropped here while still borrowed
+
+error[E0597]: `y` does not live long enough
+  --> $DIR/pattern_substs_on_brace_enum_variant.rs:16:33
+   |
+LL |     let foo = Foo::Bar { field: &y };
+   |                                 ^^ borrowed value does not live long enough
+...
+LL |         Foo::Bar::<'static> { field: _z } => {
+   |         --------------------------------- type annotation requires that `y` is borrowed for `'static`
+...
+LL | }
+   | - `y` dropped here while still borrowed
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/user-annotations/pattern_substs_on_brace_struct.rs b/src/test/ui/nll/user-annotations/pattern_substs_on_brace_struct.rs
new file mode 100644
index 0000000..1c92858
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/pattern_substs_on_brace_struct.rs
@@ -0,0 +1,22 @@
+#![feature(nll)]
+
+struct Foo<'a> { field: &'a u32 }
+
+fn in_let() {
+    let y = 22;
+    let foo = Foo { field: &y };
+    //~^ ERROR `y` does not live long enough
+    let Foo::<'static> { field: _z } = foo;
+}
+
+fn in_main() {
+    let y = 22;
+    let foo = Foo { field: &y };
+    //~^ ERROR `y` does not live long enough
+    match foo {
+        Foo::<'static> { field: _z } => {
+        }
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/user-annotations/pattern_substs_on_brace_struct.stderr b/src/test/ui/nll/user-annotations/pattern_substs_on_brace_struct.stderr
new file mode 100644
index 0000000..9c888b0
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/pattern_substs_on_brace_struct.stderr
@@ -0,0 +1,26 @@
+error[E0597]: `y` does not live long enough
+  --> $DIR/pattern_substs_on_brace_struct.rs:7:28
+   |
+LL |     let foo = Foo { field: &y };
+   |                            ^^ borrowed value does not live long enough
+LL |
+LL |     let Foo::<'static> { field: _z } = foo;
+   |         ---------------------------- type annotation requires that `y` is borrowed for `'static`
+LL | }
+   | - `y` dropped here while still borrowed
+
+error[E0597]: `y` does not live long enough
+  --> $DIR/pattern_substs_on_brace_struct.rs:14:28
+   |
+LL |     let foo = Foo { field: &y };
+   |                            ^^ borrowed value does not live long enough
+...
+LL |         Foo::<'static> { field: _z } => {
+   |         ---------------------------- type annotation requires that `y` is borrowed for `'static`
+...
+LL | }
+   | - `y` dropped here while still borrowed
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/user-annotations/pattern_substs_on_tuple_enum_variant.rs b/src/test/ui/nll/user-annotations/pattern_substs_on_tuple_enum_variant.rs
new file mode 100644
index 0000000..d6c364f
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/pattern_substs_on_tuple_enum_variant.rs
@@ -0,0 +1,24 @@
+#![feature(nll)]
+
+enum Foo<'a> {
+    Bar(&'a u32)
+}
+
+fn in_let() {
+    let y = 22;
+    let foo = Foo::Bar(&y);
+    //~^ ERROR `y` does not live long enough
+    let Foo::Bar::<'static>(_z) = foo;
+}
+
+fn in_match() {
+    let y = 22;
+    let foo = Foo::Bar(&y);
+    //~^ ERROR `y` does not live long enough
+    match foo {
+        Foo::Bar::<'static>(_z) => {
+        }
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/user-annotations/pattern_substs_on_tuple_enum_variant.stderr b/src/test/ui/nll/user-annotations/pattern_substs_on_tuple_enum_variant.stderr
new file mode 100644
index 0000000..698cff5
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/pattern_substs_on_tuple_enum_variant.stderr
@@ -0,0 +1,26 @@
+error[E0597]: `y` does not live long enough
+  --> $DIR/pattern_substs_on_tuple_enum_variant.rs:9:24
+   |
+LL |     let foo = Foo::Bar(&y);
+   |                        ^^ borrowed value does not live long enough
+LL |
+LL |     let Foo::Bar::<'static>(_z) = foo;
+   |         ----------------------- type annotation requires that `y` is borrowed for `'static`
+LL | }
+   | - `y` dropped here while still borrowed
+
+error[E0597]: `y` does not live long enough
+  --> $DIR/pattern_substs_on_tuple_enum_variant.rs:16:24
+   |
+LL |     let foo = Foo::Bar(&y);
+   |                        ^^ borrowed value does not live long enough
+...
+LL |         Foo::Bar::<'static>(_z) => {
+   |         ----------------------- type annotation requires that `y` is borrowed for `'static`
+...
+LL | }
+   | - `y` dropped here while still borrowed
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/user-annotations/pattern_substs_on_tuple_struct.rs b/src/test/ui/nll/user-annotations/pattern_substs_on_tuple_struct.rs
new file mode 100644
index 0000000..626ca90
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/pattern_substs_on_tuple_struct.rs
@@ -0,0 +1,22 @@
+#![feature(nll)]
+
+struct Foo<'a>(&'a u32);
+
+fn in_let() {
+    let y = 22;
+    let foo = Foo(&y);
+    //~^ ERROR `y` does not live long enough
+    let Foo::<'static>(_z) = foo;
+}
+
+fn in_match() {
+    let y = 22;
+    let foo = Foo(&y);
+    //~^ ERROR `y` does not live long enough
+    match foo {
+        Foo::<'static>(_z) => {
+        }
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/user-annotations/pattern_substs_on_tuple_struct.stderr b/src/test/ui/nll/user-annotations/pattern_substs_on_tuple_struct.stderr
new file mode 100644
index 0000000..b5f2cb8
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/pattern_substs_on_tuple_struct.stderr
@@ -0,0 +1,26 @@
+error[E0597]: `y` does not live long enough
+  --> $DIR/pattern_substs_on_tuple_struct.rs:7:19
+   |
+LL |     let foo = Foo(&y);
+   |                   ^^ borrowed value does not live long enough
+LL |
+LL |     let Foo::<'static>(_z) = foo;
+   |         ------------------ type annotation requires that `y` is borrowed for `'static`
+LL | }
+   | - `y` dropped here while still borrowed
+
+error[E0597]: `y` does not live long enough
+  --> $DIR/pattern_substs_on_tuple_struct.rs:14:19
+   |
+LL |     let foo = Foo(&y);
+   |                   ^^ borrowed value does not live long enough
+...
+LL |         Foo::<'static>(_z) => {
+   |         ------------------ type annotation requires that `y` is borrowed for `'static`
+...
+LL | }
+   | - `y` dropped here while still borrowed
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/user-annotations/patterns.rs b/src/test/ui/nll/user-annotations/patterns.rs
new file mode 100644
index 0000000..8c8e61c
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/patterns.rs
@@ -0,0 +1,138 @@
+// Test that various patterns also enforce types.
+
+#![feature(nll)]
+
+fn variable_no_initializer() {
+    let x = 22;
+    let y: &'static u32;
+    y = &x; //~ ERROR
+}
+
+fn tuple_no_initializer() {
+
+
+    let x = 22;
+    let (y, z): (&'static u32, &'static u32);
+    y = &x; //~ ERROR
+}
+
+fn ref_with_ascribed_static_type() -> u32 {
+    // Check the behavior in some wacky cases.
+    let x = 22;
+    let y = &x; //~ ERROR
+    let ref z: &'static u32 = y;
+    **z
+}
+
+fn ref_with_ascribed_any_type() -> u32 {
+    let x = 22;
+    let y = &x;
+    let ref z: &u32 = y;
+    **z
+}
+
+struct Single<T> { value: T }
+
+fn struct_no_initializer() {
+
+
+    let x = 22;
+    let Single { value: y }: Single<&'static u32>;
+    y = &x; //~ ERROR
+}
+
+
+fn struct_no_initializer_must_normalize() {
+    trait Indirect { type Assoc; }
+    struct StaticU32;
+    impl Indirect for StaticU32 { type Assoc = &'static u32; }
+    struct Single2<T: Indirect> { value: <T as Indirect>::Assoc }
+
+    let x = 22;
+    let Single2 { value: mut _y }: Single2<StaticU32>;
+    _y = &x; //~ ERROR
+}
+
+fn variable_with_initializer() {
+    let x = 22;
+    let y: &'static u32 = &x; //~ ERROR
+}
+
+fn underscore_with_initializer() {
+    let x = 22;
+    let _: &'static u32 = &x; //~ ERROR
+
+    let _: Vec<&'static String> = vec![&String::new()];
+    //~^ ERROR temporary value dropped while borrowed [E0716]
+
+    let (_, a): (Vec<&'static String>, _) = (vec![&String::new()], 44);
+    //~^ ERROR temporary value dropped while borrowed [E0716]
+
+    let (_a, b): (Vec<&'static String>, _) = (vec![&String::new()], 44);
+    //~^ ERROR temporary value dropped while borrowed [E0716]
+}
+
+fn pair_underscores_with_initializer() {
+    let x = 22;
+    let (_, _): (&'static u32, u32) = (&x, 44); //~ ERROR
+}
+
+fn pair_variable_with_initializer() {
+    let x = 22;
+    let (y, _): (&'static u32, u32) = (&x, 44); //~ ERROR
+}
+
+fn struct_single_field_variable_with_initializer() {
+    let x = 22;
+    let Single { value: y }: Single<&'static u32> = Single { value: &x }; //~ ERROR
+}
+
+fn struct_single_field_underscore_with_initializer() {
+    let x = 22;
+    let Single { value: _ }: Single<&'static u32> = Single { value: &x }; //~ ERROR
+}
+
+struct Double<T> { value1: T, value2: T }
+
+fn struct_double_field_underscore_with_initializer() {
+    let x = 22;
+    let Double { value1: _, value2: _ }: Double<&'static u32> = Double {
+        value1: &x, //~ ERROR
+        value2: &44,
+    };
+}
+
+fn static_to_a_to_static_through_variable<'a>(x: &'a u32) -> &'static u32 {
+
+
+
+
+
+
+    let y: &'a u32 = &22;
+    y //~ ERROR
+}
+
+fn static_to_a_to_static_through_tuple<'a>(x: &'a u32) -> &'static u32 {
+
+
+
+
+
+
+
+    let (y, _z): (&'a u32, u32) = (&22, 44);
+    y //~ ERROR
+}
+
+fn static_to_a_to_static_through_struct<'a>(_x: &'a u32) -> &'static u32 {
+    let Single { value: y }: Single<&'a u32> = Single { value: &22 };
+    y //~ ERROR
+}
+
+fn a_to_static_then_static<'a>(x: &'a u32) -> &'static u32 {
+    let (y, _z): (&'static u32, u32) = (x, 44); //~ ERROR
+    y
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/user-annotations/patterns.stderr b/src/test/ui/nll/user-annotations/patterns.stderr
new file mode 100644
index 0000000..1ac6283
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/patterns.stderr
@@ -0,0 +1,189 @@
+error[E0597]: `x` does not live long enough
+  --> $DIR/patterns.rs:8:9
+   |
+LL |     let y: &'static u32;
+   |            ------------ type annotation requires that `x` is borrowed for `'static`
+LL |     y = &x;
+   |         ^^ borrowed value does not live long enough
+LL | }
+   | - `x` dropped here while still borrowed
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/patterns.rs:16:9
+   |
+LL |     let (y, z): (&'static u32, &'static u32);
+   |                 ---------------------------- type annotation requires that `x` is borrowed for `'static`
+LL |     y = &x;
+   |         ^^ borrowed value does not live long enough
+LL | }
+   | - `x` dropped here while still borrowed
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/patterns.rs:22:13
+   |
+LL |     let y = &x;
+   |             ^^ borrowed value does not live long enough
+LL |     let ref z: &'static u32 = y;
+   |                ------------ type annotation requires that `x` is borrowed for `'static`
+LL |     **z
+LL | }
+   | - `x` dropped here while still borrowed
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/patterns.rs:41:9
+   |
+LL |     let Single { value: y }: Single<&'static u32>;
+   |                              -------------------- type annotation requires that `x` is borrowed for `'static`
+LL |     y = &x;
+   |         ^^ borrowed value does not live long enough
+LL | }
+   | - `x` dropped here while still borrowed
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/patterns.rs:53:10
+   |
+LL |     let Single2 { value: mut _y }: Single2<StaticU32>;
+   |                                    ------------------ type annotation requires that `x` is borrowed for `'static`
+LL |     _y = &x;
+   |          ^^ borrowed value does not live long enough
+LL | }
+   | - `x` dropped here while still borrowed
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/patterns.rs:58:27
+   |
+LL |     let y: &'static u32 = &x;
+   |            ------------   ^^ borrowed value does not live long enough
+   |            |
+   |            type annotation requires that `x` is borrowed for `'static`
+LL | }
+   | - `x` dropped here while still borrowed
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/patterns.rs:63:27
+   |
+LL |     let _: &'static u32 = &x;
+   |            ------------   ^^ borrowed value does not live long enough
+   |            |
+   |            type annotation requires that `x` is borrowed for `'static`
+...
+LL | }
+   | - `x` dropped here while still borrowed
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/patterns.rs:65:41
+   |
+LL |     let _: Vec<&'static String> = vec![&String::new()];
+   |            --------------------         ^^^^^^^^^^^^^ - temporary value is freed at the end of this statement
+   |            |                            |
+   |            |                            creates a temporary which is freed while still in use
+   |            type annotation requires that borrow lasts for `'static`
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/patterns.rs:68:52
+   |
+LL |     let (_, a): (Vec<&'static String>, _) = (vec![&String::new()], 44);
+   |                 -------------------------          ^^^^^^^^^^^^^      - temporary value is freed at the end of this statement
+   |                 |                                  |
+   |                 |                                  creates a temporary which is freed while still in use
+   |                 type annotation requires that borrow lasts for `'static`
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/patterns.rs:71:53
+   |
+LL |     let (_a, b): (Vec<&'static String>, _) = (vec![&String::new()], 44);
+   |                  -------------------------          ^^^^^^^^^^^^^      - temporary value is freed at the end of this statement
+   |                  |                                  |
+   |                  |                                  creates a temporary which is freed while still in use
+   |                  type annotation requires that borrow lasts for `'static`
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/patterns.rs:77:40
+   |
+LL |     let (_, _): (&'static u32, u32) = (&x, 44);
+   |                 -------------------    ^^ borrowed value does not live long enough
+   |                 |
+   |                 type annotation requires that `x` is borrowed for `'static`
+LL | }
+   | - `x` dropped here while still borrowed
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/patterns.rs:82:40
+   |
+LL |     let (y, _): (&'static u32, u32) = (&x, 44);
+   |                 -------------------    ^^ borrowed value does not live long enough
+   |                 |
+   |                 type annotation requires that `x` is borrowed for `'static`
+LL | }
+   | - `x` dropped here while still borrowed
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/patterns.rs:87:69
+   |
+LL |     let Single { value: y }: Single<&'static u32> = Single { value: &x };
+   |                              --------------------                   ^^ borrowed value does not live long enough
+   |                              |
+   |                              type annotation requires that `x` is borrowed for `'static`
+LL | }
+   | - `x` dropped here while still borrowed
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/patterns.rs:92:69
+   |
+LL |     let Single { value: _ }: Single<&'static u32> = Single { value: &x };
+   |                              --------------------                   ^^ borrowed value does not live long enough
+   |                              |
+   |                              type annotation requires that `x` is borrowed for `'static`
+LL | }
+   | - `x` dropped here while still borrowed
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/patterns.rs:100:17
+   |
+LL |     let Double { value1: _, value2: _ }: Double<&'static u32> = Double {
+   |                                          -------------------- type annotation requires that `x` is borrowed for `'static`
+LL |         value1: &x,
+   |                 ^^ borrowed value does not live long enough
+...
+LL | }
+   | - `x` dropped here while still borrowed
+
+error: lifetime may not live long enough
+  --> $DIR/patterns.rs:113:5
+   |
+LL | fn static_to_a_to_static_through_variable<'a>(x: &'a u32) -> &'static u32 {
+   |                                           -- lifetime `'a` defined here
+...
+LL |     y
+   |     ^ returning this value requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/patterns.rs:125:5
+   |
+LL | fn static_to_a_to_static_through_tuple<'a>(x: &'a u32) -> &'static u32 {
+   |                                        -- lifetime `'a` defined here
+...
+LL |     y
+   |     ^ returning this value requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/patterns.rs:130:5
+   |
+LL | fn static_to_a_to_static_through_struct<'a>(_x: &'a u32) -> &'static u32 {
+   |                                         -- lifetime `'a` defined here
+LL |     let Single { value: y }: Single<&'a u32> = Single { value: &22 };
+LL |     y
+   |     ^ returning this value requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/patterns.rs:134:18
+   |
+LL | fn a_to_static_then_static<'a>(x: &'a u32) -> &'static u32 {
+   |                            -- lifetime `'a` defined here
+LL |     let (y, _z): (&'static u32, u32) = (x, 44);
+   |                  ^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+
+error: aborting due to 19 previous errors
+
+Some errors occurred: E0597, E0716.
+For more information about an error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/user-annotations/promoted-annotation.rs b/src/test/ui/nll/user-annotations/promoted-annotation.rs
new file mode 100644
index 0000000..fa2d2fb
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/promoted-annotation.rs
@@ -0,0 +1,12 @@
+// Test that type annotations are checked in promoted constants correctly.
+
+#![feature(nll)]
+
+fn foo<'a>() {
+    let x = 0;
+    let f = &drop::<&'a i32>;
+    f(&x);
+    //~^ ERROR `x` does not live long enough
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/user-annotations/promoted-annotation.stderr b/src/test/ui/nll/user-annotations/promoted-annotation.stderr
new file mode 100644
index 0000000..d8b01f2
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/promoted-annotation.stderr
@@ -0,0 +1,17 @@
+error[E0597]: `x` does not live long enough
+  --> $DIR/promoted-annotation.rs:8:7
+   |
+LL | fn foo<'a>() {
+   |        -- lifetime `'a` defined here
+LL |     let x = 0;
+LL |     let f = &drop::<&'a i32>;
+   |             ---------------- assignment requires that `x` is borrowed for `'a`
+LL |     f(&x);
+   |       ^^ borrowed value does not live long enough
+LL |
+LL | }
+   | - `x` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/user-annotations/type_ascription_static_lifetime.rs b/src/test/ui/nll/user-annotations/type_ascription_static_lifetime.rs
new file mode 100644
index 0000000..362fe51
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/type_ascription_static_lifetime.rs
@@ -0,0 +1,8 @@
+#![allow(warnings)]
+#![feature(nll)]
+#![feature(type_ascription)]
+
+fn main() {
+    let x = 22_u32;
+    let y: &u32 = &x: &'static u32; //~ ERROR E0597
+}
diff --git a/src/test/ui/nll/user-annotations/type_ascription_static_lifetime.stderr b/src/test/ui/nll/user-annotations/type_ascription_static_lifetime.stderr
new file mode 100644
index 0000000..93dbf7c
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/type_ascription_static_lifetime.stderr
@@ -0,0 +1,14 @@
+error[E0597]: `x` does not live long enough
+  --> $DIR/type_ascription_static_lifetime.rs:7:19
+   |
+LL |     let y: &u32 = &x: &'static u32;
+   |                   ^^--------------
+   |                   |
+   |                   borrowed value does not live long enough
+   |                   type annotation requires that `x` is borrowed for `'static`
+LL | }
+   | - `x` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/user-annotations/wf-self-type.rs b/src/test/ui/nll/user-annotations/wf-self-type.rs
new file mode 100644
index 0000000..d8caf46
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/wf-self-type.rs
@@ -0,0 +1,15 @@
+#![feature(nll)]
+
+struct Foo<'a, 'b: 'a>(&'a &'b ());
+
+impl<'a, 'b> Foo<'a, 'b> {
+    fn xmute(a: &'b ()) -> &'a () {
+        unreachable!()
+    }
+}
+
+pub fn foo<'a, 'b>(u: &'b ()) -> &'a () {
+    Foo::xmute(u) //~ ERROR lifetime may not live long enough
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/user-annotations/wf-self-type.stderr b/src/test/ui/nll/user-annotations/wf-self-type.stderr
new file mode 100644
index 0000000..8f8e1bc
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/wf-self-type.stderr
@@ -0,0 +1,12 @@
+error: lifetime may not live long enough
+  --> $DIR/wf-self-type.rs:12:5
+   |
+LL | pub fn foo<'a, 'b>(u: &'b ()) -> &'a () {
+   |            --  -- lifetime `'b` defined here
+   |            |
+   |            lifetime `'a` defined here
+LL |     Foo::xmute(u)
+   |     ^^^^^^^^^^^^^ returning this value requires that `'b` must outlive `'a`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/where_clauses_in_functions.rs b/src/test/ui/nll/where_clauses_in_functions.rs
new file mode 100644
index 0000000..0d35c09b
--- /dev/null
+++ b/src/test/ui/nll/where_clauses_in_functions.rs
@@ -0,0 +1,17 @@
+// compile-flags: -Zborrowck=mir
+
+#![allow(dead_code)]
+
+fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> (&'a u32, &'b u32)
+where
+    'a: 'b,
+{
+    (x, y)
+}
+
+fn bar<'a, 'b>(x: &'a u32, y: &'b u32) -> (&'a u32, &'b u32) {
+    foo(x, y)
+    //~^ ERROR lifetime may not live long enough
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/where_clauses_in_functions.stderr b/src/test/ui/nll/where_clauses_in_functions.stderr
new file mode 100644
index 0000000..f3b65ec
--- /dev/null
+++ b/src/test/ui/nll/where_clauses_in_functions.stderr
@@ -0,0 +1,12 @@
+error: lifetime may not live long enough
+  --> $DIR/where_clauses_in_functions.rs:13:5
+   |
+LL | fn bar<'a, 'b>(x: &'a u32, y: &'b u32) -> (&'a u32, &'b u32) {
+   |        --  -- lifetime `'b` defined here
+   |        |
+   |        lifetime `'a` defined here
+LL |     foo(x, y)
+   |     ^^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/where_clauses_in_structs.rs b/src/test/ui/nll/where_clauses_in_structs.rs
new file mode 100644
index 0000000..8bc6b2e
--- /dev/null
+++ b/src/test/ui/nll/where_clauses_in_structs.rs
@@ -0,0 +1,17 @@
+// compile-flags: -Z borrowck=mir
+
+#![allow(dead_code)]
+
+use std::cell::Cell;
+
+struct Foo<'a: 'b, 'b> {
+    x: Cell<&'a u32>,
+    y: Cell<&'b u32>,
+}
+
+fn bar<'a, 'b>(x: Cell<&'a u32>, y: Cell<&'b u32>) {
+    Foo { x, y };
+    //~^ ERROR lifetime may not live long enough
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/where_clauses_in_structs.stderr b/src/test/ui/nll/where_clauses_in_structs.stderr
new file mode 100644
index 0000000..e0feb40
--- /dev/null
+++ b/src/test/ui/nll/where_clauses_in_structs.stderr
@@ -0,0 +1,12 @@
+error: lifetime may not live long enough
+  --> $DIR/where_clauses_in_structs.rs:13:11
+   |
+LL | fn bar<'a, 'b>(x: Cell<&'a u32>, y: Cell<&'b u32>) {
+   |        --  -- lifetime `'b` defined here
+   |        |
+   |        lifetime `'a` defined here
+LL |     Foo { x, y };
+   |           ^ requires that `'a` must outlive `'b`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/no-args-non-move-async-closure.rs b/src/test/ui/no-args-non-move-async-closure.rs
new file mode 100644
index 0000000..4f5b2ea
--- /dev/null
+++ b/src/test/ui/no-args-non-move-async-closure.rs
@@ -0,0 +1,8 @@
+// edition:2018
+
+#![feature(arbitrary_self_types, async_await, await_macro, futures_api, pin)]
+
+fn main() {
+    let _ = async |x: u8| {};
+    //~^ ERROR `async` non-`move` closures with arguments are not currently supported
+}
diff --git a/src/test/ui/no-args-non-move-async-closure.stderr b/src/test/ui/no-args-non-move-async-closure.stderr
new file mode 100644
index 0000000..e1d16f6
--- /dev/null
+++ b/src/test/ui/no-args-non-move-async-closure.stderr
@@ -0,0 +1,11 @@
+error[E0708]: `async` non-`move` closures with arguments are not currently supported
+  --> $DIR/no-args-non-move-async-closure.rs:6:13
+   |
+LL |     let _ = async |x: u8| {};
+   |             ^^^^^^^^^^^^^
+   |
+   = help: consider using `let` statements to manually capture variables by reference before entering an `async move` closure
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0708`.
diff --git a/src/test/ui/no-capture-arc.nll.stderr b/src/test/ui/no-capture-arc.nll.stderr
new file mode 100644
index 0000000..476b6f7
--- /dev/null
+++ b/src/test/ui/no-capture-arc.nll.stderr
@@ -0,0 +1,17 @@
+error[E0382]: borrow of moved value: `arc_v`
+  --> $DIR/no-capture-arc.rs:14:18
+   |
+LL |     let arc_v = Arc::new(v);
+   |         ----- move occurs because `arc_v` has type `std::sync::Arc<std::vec::Vec<i32>>`, which does not implement the `Copy` trait
+LL | 
+LL |     thread::spawn(move|| {
+   |                   ------ value moved into closure here
+LL |         assert_eq!((*arc_v)[3], 4);
+   |                      ----- variable moved due to use in closure
+...
+LL |     assert_eq!((*arc_v)[2], 3);
+   |                  ^^^^^ value borrowed here after move
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/no-capture-arc.rs b/src/test/ui/no-capture-arc.rs
new file mode 100644
index 0000000..06f5fb3
--- /dev/null
+++ b/src/test/ui/no-capture-arc.rs
@@ -0,0 +1,17 @@
+// error-pattern: use of moved value
+
+use std::sync::Arc;
+use std::thread;
+
+fn main() {
+    let v = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
+    let arc_v = Arc::new(v);
+
+    thread::spawn(move|| {
+        assert_eq!((*arc_v)[3], 4);
+    });
+
+    assert_eq!((*arc_v)[2], 3);
+
+    println!("{:?}", *arc_v);
+}
diff --git a/src/test/ui/no-capture-arc.stderr b/src/test/ui/no-capture-arc.stderr
new file mode 100644
index 0000000..0dfa5cd
--- /dev/null
+++ b/src/test/ui/no-capture-arc.stderr
@@ -0,0 +1,25 @@
+error[E0382]: use of moved value: `arc_v`
+  --> $DIR/no-capture-arc.rs:14:18
+   |
+LL |     thread::spawn(move|| {
+   |                   ------ value moved (into closure) here
+...
+LL |     assert_eq!((*arc_v)[2], 3);
+   |                  ^^^^^ value used here after move
+   |
+   = note: move occurs because `arc_v` has type `std::sync::Arc<std::vec::Vec<i32>>`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `arc_v`
+  --> $DIR/no-capture-arc.rs:16:23
+   |
+LL |     thread::spawn(move|| {
+   |                   ------ value moved (into closure) here
+...
+LL |     println!("{:?}", *arc_v);
+   |                       ^^^^^ value used here after move
+   |
+   = note: move occurs because `arc_v` has type `std::sync::Arc<std::vec::Vec<i32>>`, which does not implement the `Copy` trait
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/no-implicit-prelude-nested.rs b/src/test/ui/no-implicit-prelude-nested.rs
new file mode 100644
index 0000000..fae52c0
--- /dev/null
+++ b/src/test/ui/no-implicit-prelude-nested.rs
@@ -0,0 +1,54 @@
+// Test that things from the prelude aren't in scope. Use many of them
+// so that renaming some things won't magically make this test fail
+// for the wrong reason (e.g., if `Add` changes to `Addition`, and
+// `no_implicit_prelude` stops working, then the `impl Add` will still
+// fail with the same error message).
+
+#[no_implicit_prelude]
+mod foo {
+    mod baz {
+        struct Test;
+        impl Add for Test {} //~ ERROR cannot find trait `Add` in this scope
+        impl Clone for Test {} //~ ERROR cannot find trait `Clone` in this scope
+        impl Iterator for Test {} //~ ERROR cannot find trait `Iterator` in this scope
+        impl ToString for Test {} //~ ERROR cannot find trait `ToString` in this scope
+        impl Writer for Test {} //~ ERROR cannot find trait `Writer` in this scope
+
+        fn foo() {
+            drop(2) //~ ERROR cannot find function `drop` in this scope
+        }
+    }
+
+    struct Test;
+    impl Add for Test {} //~ ERROR cannot find trait `Add` in this scope
+    impl Clone for Test {} //~ ERROR cannot find trait `Clone` in this scope
+    impl Iterator for Test {} //~ ERROR cannot find trait `Iterator` in this scope
+    impl ToString for Test {} //~ ERROR cannot find trait `ToString` in this scope
+    impl Writer for Test {} //~ ERROR cannot find trait `Writer` in this scope
+
+    fn foo() {
+        drop(2) //~ ERROR cannot find function `drop` in this scope
+    }
+}
+
+fn qux() {
+    #[no_implicit_prelude]
+    mod qux_inner {
+        struct Test;
+        impl Add for Test {} //~ ERROR cannot find trait `Add` in this scope
+        impl Clone for Test {} //~ ERROR cannot find trait `Clone` in this scope
+        impl Iterator for Test {} //~ ERROR cannot find trait `Iterator` in this scope
+        impl ToString for Test {} //~ ERROR cannot find trait `ToString` in this scope
+        impl Writer for Test {} //~ ERROR cannot find trait `Writer` in this scope
+
+        fn foo() {
+            drop(2) //~ ERROR cannot find function `drop` in this scope
+        }
+    }
+}
+
+
+fn main() {
+    // these should work fine
+    drop(2)
+}
diff --git a/src/test/ui/no-implicit-prelude-nested.stderr b/src/test/ui/no-implicit-prelude-nested.stderr
new file mode 100644
index 0000000..521ed8f
--- /dev/null
+++ b/src/test/ui/no-implicit-prelude-nested.stderr
@@ -0,0 +1,196 @@
+error[E0405]: cannot find trait `Add` in this scope
+  --> $DIR/no-implicit-prelude-nested.rs:11:14
+   |
+LL |         impl Add for Test {}
+   |              ^^^ not found in this scope
+help: possible candidate is found in another module, you can import it into scope
+   |
+LL |         use std::ops::Add;
+   |
+
+error[E0405]: cannot find trait `Clone` in this scope
+  --> $DIR/no-implicit-prelude-nested.rs:12:14
+   |
+LL |         impl Clone for Test {}
+   |              ^^^^^ not found in this scope
+help: possible candidates are found in other modules, you can import them into scope
+   |
+LL |         use std::clone::Clone;
+   |
+LL |         use std::prelude::v1::Clone;
+   |
+
+error[E0405]: cannot find trait `Iterator` in this scope
+  --> $DIR/no-implicit-prelude-nested.rs:13:14
+   |
+LL |         impl Iterator for Test {}
+   |              ^^^^^^^^ not found in this scope
+help: possible candidates are found in other modules, you can import them into scope
+   |
+LL |         use std::iter::Iterator;
+   |
+LL |         use std::prelude::v1::Iterator;
+   |
+
+error[E0405]: cannot find trait `ToString` in this scope
+  --> $DIR/no-implicit-prelude-nested.rs:14:14
+   |
+LL |         impl ToString for Test {}
+   |              ^^^^^^^^ not found in this scope
+help: possible candidates are found in other modules, you can import them into scope
+   |
+LL |         use std::prelude::v1::ToString;
+   |
+LL |         use std::string::ToString;
+   |
+
+error[E0405]: cannot find trait `Writer` in this scope
+  --> $DIR/no-implicit-prelude-nested.rs:15:14
+   |
+LL |         impl Writer for Test {}
+   |              ^^^^^^ not found in this scope
+
+error[E0425]: cannot find function `drop` in this scope
+  --> $DIR/no-implicit-prelude-nested.rs:18:13
+   |
+LL |             drop(2)
+   |             ^^^^ not found in this scope
+help: possible candidates are found in other modules, you can import them into scope
+   |
+LL |         use std::mem::drop;
+   |
+LL |         use std::prelude::v1::drop;
+   |
+
+error[E0405]: cannot find trait `Add` in this scope
+  --> $DIR/no-implicit-prelude-nested.rs:23:10
+   |
+LL |     impl Add for Test {}
+   |          ^^^ not found in this scope
+help: possible candidate is found in another module, you can import it into scope
+   |
+LL |     use std::ops::Add;
+   |
+
+error[E0405]: cannot find trait `Clone` in this scope
+  --> $DIR/no-implicit-prelude-nested.rs:24:10
+   |
+LL |     impl Clone for Test {}
+   |          ^^^^^ not found in this scope
+help: possible candidates are found in other modules, you can import them into scope
+   |
+LL |     use std::clone::Clone;
+   |
+LL |     use std::prelude::v1::Clone;
+   |
+
+error[E0405]: cannot find trait `Iterator` in this scope
+  --> $DIR/no-implicit-prelude-nested.rs:25:10
+   |
+LL |     impl Iterator for Test {}
+   |          ^^^^^^^^ not found in this scope
+help: possible candidates are found in other modules, you can import them into scope
+   |
+LL |     use std::iter::Iterator;
+   |
+LL |     use std::prelude::v1::Iterator;
+   |
+
+error[E0405]: cannot find trait `ToString` in this scope
+  --> $DIR/no-implicit-prelude-nested.rs:26:10
+   |
+LL |     impl ToString for Test {}
+   |          ^^^^^^^^ not found in this scope
+help: possible candidates are found in other modules, you can import them into scope
+   |
+LL |     use std::prelude::v1::ToString;
+   |
+LL |     use std::string::ToString;
+   |
+
+error[E0405]: cannot find trait `Writer` in this scope
+  --> $DIR/no-implicit-prelude-nested.rs:27:10
+   |
+LL |     impl Writer for Test {}
+   |          ^^^^^^ not found in this scope
+
+error[E0425]: cannot find function `drop` in this scope
+  --> $DIR/no-implicit-prelude-nested.rs:30:9
+   |
+LL |         drop(2)
+   |         ^^^^ not found in this scope
+help: possible candidates are found in other modules, you can import them into scope
+   |
+LL |     use std::mem::drop;
+   |
+LL |     use std::prelude::v1::drop;
+   |
+
+error[E0405]: cannot find trait `Add` in this scope
+  --> $DIR/no-implicit-prelude-nested.rs:38:14
+   |
+LL |         impl Add for Test {}
+   |              ^^^ not found in this scope
+help: possible candidate is found in another module, you can import it into scope
+   |
+LL |         use std::ops::Add;
+   |
+
+error[E0405]: cannot find trait `Clone` in this scope
+  --> $DIR/no-implicit-prelude-nested.rs:39:14
+   |
+LL |         impl Clone for Test {}
+   |              ^^^^^ not found in this scope
+help: possible candidates are found in other modules, you can import them into scope
+   |
+LL |         use std::clone::Clone;
+   |
+LL |         use std::prelude::v1::Clone;
+   |
+
+error[E0405]: cannot find trait `Iterator` in this scope
+  --> $DIR/no-implicit-prelude-nested.rs:40:14
+   |
+LL |         impl Iterator for Test {}
+   |              ^^^^^^^^ not found in this scope
+help: possible candidates are found in other modules, you can import them into scope
+   |
+LL |         use std::iter::Iterator;
+   |
+LL |         use std::prelude::v1::Iterator;
+   |
+
+error[E0405]: cannot find trait `ToString` in this scope
+  --> $DIR/no-implicit-prelude-nested.rs:41:14
+   |
+LL |         impl ToString for Test {}
+   |              ^^^^^^^^ not found in this scope
+help: possible candidates are found in other modules, you can import them into scope
+   |
+LL |         use std::prelude::v1::ToString;
+   |
+LL |         use std::string::ToString;
+   |
+
+error[E0405]: cannot find trait `Writer` in this scope
+  --> $DIR/no-implicit-prelude-nested.rs:42:14
+   |
+LL |         impl Writer for Test {}
+   |              ^^^^^^ not found in this scope
+
+error[E0425]: cannot find function `drop` in this scope
+  --> $DIR/no-implicit-prelude-nested.rs:45:13
+   |
+LL |             drop(2)
+   |             ^^^^ not found in this scope
+help: possible candidates are found in other modules, you can import them into scope
+   |
+LL |         use std::mem::drop;
+   |
+LL |         use std::prelude::v1::drop;
+   |
+
+error: aborting due to 18 previous errors
+
+Some errors occurred: E0405, E0425.
+For more information about an error, try `rustc --explain E0405`.
diff --git a/src/test/ui/no-implicit-prelude.rs b/src/test/ui/no-implicit-prelude.rs
new file mode 100644
index 0000000..e2074bb
--- /dev/null
+++ b/src/test/ui/no-implicit-prelude.rs
@@ -0,0 +1,18 @@
+#![no_implicit_prelude]
+
+// Test that things from the prelude aren't in scope. Use many of them
+// so that renaming some things won't magically make this test fail
+// for the wrong reason (e.g., if `Add` changes to `Addition`, and
+// `no_implicit_prelude` stops working, then the `impl Add` will still
+// fail with the same error message).
+
+struct Test;
+impl Add for Test {} //~ ERROR cannot find trait `Add` in this scope
+impl Clone for Test {} //~ ERROR cannot find trait `Clone` in this scope
+impl Iterator for Test {} //~ ERROR cannot find trait `Iterator` in this scope
+impl ToString for Test {} //~ ERROR cannot find trait `ToString` in this scope
+impl Writer for Test {} //~ ERROR cannot find trait `Writer` in this scope
+
+fn main() {
+    drop(2) //~ ERROR cannot find function `drop` in this scope
+}
diff --git a/src/test/ui/no-implicit-prelude.stderr b/src/test/ui/no-implicit-prelude.stderr
new file mode 100644
index 0000000..e5c54dd
--- /dev/null
+++ b/src/test/ui/no-implicit-prelude.stderr
@@ -0,0 +1,68 @@
+error[E0405]: cannot find trait `Add` in this scope
+  --> $DIR/no-implicit-prelude.rs:10:6
+   |
+LL | impl Add for Test {}
+   |      ^^^ not found in this scope
+help: possible candidate is found in another module, you can import it into scope
+   |
+LL | use std::ops::Add;
+   |
+
+error[E0405]: cannot find trait `Clone` in this scope
+  --> $DIR/no-implicit-prelude.rs:11:6
+   |
+LL | impl Clone for Test {}
+   |      ^^^^^ not found in this scope
+help: possible candidates are found in other modules, you can import them into scope
+   |
+LL | use std::clone::Clone;
+   |
+LL | use std::prelude::v1::Clone;
+   |
+
+error[E0405]: cannot find trait `Iterator` in this scope
+  --> $DIR/no-implicit-prelude.rs:12:6
+   |
+LL | impl Iterator for Test {}
+   |      ^^^^^^^^ not found in this scope
+help: possible candidates are found in other modules, you can import them into scope
+   |
+LL | use std::iter::Iterator;
+   |
+LL | use std::prelude::v1::Iterator;
+   |
+
+error[E0405]: cannot find trait `ToString` in this scope
+  --> $DIR/no-implicit-prelude.rs:13:6
+   |
+LL | impl ToString for Test {}
+   |      ^^^^^^^^ not found in this scope
+help: possible candidates are found in other modules, you can import them into scope
+   |
+LL | use std::prelude::v1::ToString;
+   |
+LL | use std::string::ToString;
+   |
+
+error[E0405]: cannot find trait `Writer` in this scope
+  --> $DIR/no-implicit-prelude.rs:14:6
+   |
+LL | impl Writer for Test {}
+   |      ^^^^^^ not found in this scope
+
+error[E0425]: cannot find function `drop` in this scope
+  --> $DIR/no-implicit-prelude.rs:17:5
+   |
+LL |     drop(2)
+   |     ^^^^ not found in this scope
+help: possible candidates are found in other modules, you can import them into scope
+   |
+LL | use std::mem::drop;
+   |
+LL | use std::prelude::v1::drop;
+   |
+
+error: aborting due to 6 previous errors
+
+Some errors occurred: E0405, E0425.
+For more information about an error, try `rustc --explain E0405`.
diff --git a/src/test/ui/no-link-unknown-crate.rs b/src/test/ui/no-link-unknown-crate.rs
new file mode 100644
index 0000000..c7da2e4
--- /dev/null
+++ b/src/test/ui/no-link-unknown-crate.rs
@@ -0,0 +1,4 @@
+#[no_link]
+extern crate doesnt_exist; //~ ERROR can't find crate
+
+fn main() {}
diff --git a/src/test/ui/no-link-unknown-crate.stderr b/src/test/ui/no-link-unknown-crate.stderr
new file mode 100644
index 0000000..068c713
--- /dev/null
+++ b/src/test/ui/no-link-unknown-crate.stderr
@@ -0,0 +1,9 @@
+error[E0463]: can't find crate for `doesnt_exist`
+  --> $DIR/no-link-unknown-crate.rs:2:1
+   |
+LL | extern crate doesnt_exist;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^ can't find crate
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0463`.
diff --git a/src/test/ui/no-link.rs b/src/test/ui/no-link.rs
new file mode 100644
index 0000000..f97c107
--- /dev/null
+++ b/src/test/ui/no-link.rs
@@ -0,0 +1,8 @@
+// aux-build:empty-struct.rs
+
+#[no_link]
+extern crate empty_struct;
+
+fn main() {
+    empty_struct::XEmpty1; //~ ERROR cannot find value `XEmpty1` in module `empty_struct`
+}
diff --git a/src/test/ui/no-link.stderr b/src/test/ui/no-link.stderr
new file mode 100644
index 0000000..c9c8468
--- /dev/null
+++ b/src/test/ui/no-link.stderr
@@ -0,0 +1,9 @@
+error[E0425]: cannot find value `XEmpty1` in module `empty_struct`
+  --> $DIR/no-link.rs:7:19
+   |
+LL |     empty_struct::XEmpty1;
+   |                   ^^^^^^^ not found in `empty_struct`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/no-patterns-in-args-2.rs b/src/test/ui/no-patterns-in-args-2.rs
new file mode 100644
index 0000000..ccf5747
--- /dev/null
+++ b/src/test/ui/no-patterns-in-args-2.rs
@@ -0,0 +1,13 @@
+#![deny(patterns_in_fns_without_body)]
+
+trait Tr {
+    fn f1(mut arg: u8); //~ ERROR patterns aren't allowed in methods without bodies
+                        //~^ WARN was previously accepted
+    fn f2(&arg: u8); //~ ERROR patterns aren't allowed in methods without bodies
+    fn g1(arg: u8); // OK
+    fn g2(_: u8); // OK
+    #[allow(anonymous_parameters)]
+    fn g3(u8); // OK
+}
+
+fn main() {}
diff --git a/src/test/ui/no-patterns-in-args-2.stderr b/src/test/ui/no-patterns-in-args-2.stderr
new file mode 100644
index 0000000..ec7d2d9
--- /dev/null
+++ b/src/test/ui/no-patterns-in-args-2.stderr
@@ -0,0 +1,23 @@
+error[E0642]: patterns aren't allowed in methods without bodies
+  --> $DIR/no-patterns-in-args-2.rs:6:11
+   |
+LL |     fn f2(&arg: u8);
+   |           ^^^^
+
+error: patterns aren't allowed in methods without bodies
+  --> $DIR/no-patterns-in-args-2.rs:4:11
+   |
+LL |     fn f1(mut arg: u8);
+   |           ^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/no-patterns-in-args-2.rs:1:9
+   |
+LL | #![deny(patterns_in_fns_without_body)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #35203 <https://github.com/rust-lang/rust/issues/35203>
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0642`.
diff --git a/src/test/ui/no-patterns-in-args-macro.rs b/src/test/ui/no-patterns-in-args-macro.rs
new file mode 100644
index 0000000..59cb994
--- /dev/null
+++ b/src/test/ui/no-patterns-in-args-macro.rs
@@ -0,0 +1,26 @@
+macro_rules! m {
+    ($pat: pat) => {
+        trait Tr {
+            fn trait_method($pat: u8);
+        }
+
+        type A = fn($pat: u8);
+
+        extern {
+            fn foreign_fn($pat: u8);
+        }
+    }
+}
+
+mod good_pat {
+    m!(good_pat); // OK
+}
+
+mod bad_pat {
+    m!((bad, pat));
+    //~^ ERROR patterns aren't allowed in function pointer types
+    //~| ERROR patterns aren't allowed in foreign function declarations
+    //~| ERROR patterns aren't allowed in methods without bodies
+}
+
+fn main() {}
diff --git a/src/test/ui/no-patterns-in-args-macro.stderr b/src/test/ui/no-patterns-in-args-macro.stderr
new file mode 100644
index 0000000..28a48bf
--- /dev/null
+++ b/src/test/ui/no-patterns-in-args-macro.stderr
@@ -0,0 +1,22 @@
+error[E0642]: patterns aren't allowed in methods without bodies
+  --> $DIR/no-patterns-in-args-macro.rs:20:8
+   |
+LL |     m!((bad, pat));
+   |        ^^^^^^^^^^
+
+error[E0561]: patterns aren't allowed in function pointer types
+  --> $DIR/no-patterns-in-args-macro.rs:20:8
+   |
+LL |     m!((bad, pat));
+   |        ^^^^^^^^^^
+
+error[E0130]: patterns aren't allowed in foreign function declarations
+  --> $DIR/no-patterns-in-args-macro.rs:20:8
+   |
+LL |     m!((bad, pat));
+   |        ^^^^^^^^^^ pattern not allowed in foreign function
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0130, E0561, E0642.
+For more information about an error, try `rustc --explain E0130`.
diff --git a/src/test/ui/no-patterns-in-args.rs b/src/test/ui/no-patterns-in-args.rs
new file mode 100644
index 0000000..a774955
--- /dev/null
+++ b/src/test/ui/no-patterns-in-args.rs
@@ -0,0 +1,16 @@
+extern {
+    fn f1(mut arg: u8); //~ ERROR patterns aren't allowed in foreign function declarations
+    fn f2(&arg: u8); //~ ERROR patterns aren't allowed in foreign function declarations
+    fn f3(arg @ _: u8); //~ ERROR patterns aren't allowed in foreign function declarations
+    fn g1(arg: u8); // OK
+    fn g2(_: u8); // OK
+    // fn g3(u8); // Not yet
+}
+
+type A1 = fn(mut arg: u8); //~ ERROR patterns aren't allowed in function pointer types
+type A2 = fn(&arg: u8); //~ ERROR patterns aren't allowed in function pointer types
+type B1 = fn(arg: u8); // OK
+type B2 = fn(_: u8); // OK
+type B3 = fn(u8); // OK
+
+fn main() {}
diff --git a/src/test/ui/no-patterns-in-args.stderr b/src/test/ui/no-patterns-in-args.stderr
new file mode 100644
index 0000000..0768c3f
--- /dev/null
+++ b/src/test/ui/no-patterns-in-args.stderr
@@ -0,0 +1,34 @@
+error[E0130]: patterns aren't allowed in foreign function declarations
+  --> $DIR/no-patterns-in-args.rs:2:11
+   |
+LL |     fn f1(mut arg: u8);
+   |           ^^^^^^^ pattern not allowed in foreign function
+
+error[E0130]: patterns aren't allowed in foreign function declarations
+  --> $DIR/no-patterns-in-args.rs:3:11
+   |
+LL |     fn f2(&arg: u8);
+   |           ^^^^ pattern not allowed in foreign function
+
+error[E0130]: patterns aren't allowed in foreign function declarations
+  --> $DIR/no-patterns-in-args.rs:4:11
+   |
+LL |     fn f3(arg @ _: u8);
+   |           ^^^^^^^ pattern not allowed in foreign function
+
+error[E0561]: patterns aren't allowed in function pointer types
+  --> $DIR/no-patterns-in-args.rs:10:14
+   |
+LL | type A1 = fn(mut arg: u8);
+   |              ^^^^^^^
+
+error[E0561]: patterns aren't allowed in function pointer types
+  --> $DIR/no-patterns-in-args.rs:11:14
+   |
+LL | type A2 = fn(&arg: u8);
+   |              ^^^^
+
+error: aborting due to 5 previous errors
+
+Some errors occurred: E0130, E0561.
+For more information about an error, try `rustc --explain E0130`.
diff --git a/src/test/ui/no-reuse-move-arc.nll.stderr b/src/test/ui/no-reuse-move-arc.nll.stderr
new file mode 100644
index 0000000..3f7169e
--- /dev/null
+++ b/src/test/ui/no-reuse-move-arc.nll.stderr
@@ -0,0 +1,17 @@
+error[E0382]: borrow of moved value: `arc_v`
+  --> $DIR/no-reuse-move-arc.rs:12:18
+   |
+LL |     let arc_v = Arc::new(v);
+   |         ----- move occurs because `arc_v` has type `std::sync::Arc<std::vec::Vec<i32>>`, which does not implement the `Copy` trait
+LL | 
+LL |     thread::spawn(move|| {
+   |                   ------ value moved into closure here
+LL |         assert_eq!((*arc_v)[3], 4);
+   |                      ----- variable moved due to use in closure
+...
+LL |     assert_eq!((*arc_v)[2], 3);
+   |                  ^^^^^ value borrowed here after move
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/no-reuse-move-arc.rs b/src/test/ui/no-reuse-move-arc.rs
new file mode 100644
index 0000000..b60a7f2
--- /dev/null
+++ b/src/test/ui/no-reuse-move-arc.rs
@@ -0,0 +1,15 @@
+use std::sync::Arc;
+use std::thread;
+
+fn main() {
+    let v = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
+    let arc_v = Arc::new(v);
+
+    thread::spawn(move|| {
+        assert_eq!((*arc_v)[3], 4);
+    });
+
+    assert_eq!((*arc_v)[2], 3); //~ ERROR use of moved value: `arc_v`
+
+    println!("{:?}", *arc_v); //~ ERROR use of moved value: `arc_v`
+}
diff --git a/src/test/ui/no-reuse-move-arc.stderr b/src/test/ui/no-reuse-move-arc.stderr
new file mode 100644
index 0000000..d7123314
--- /dev/null
+++ b/src/test/ui/no-reuse-move-arc.stderr
@@ -0,0 +1,25 @@
+error[E0382]: use of moved value: `arc_v`
+  --> $DIR/no-reuse-move-arc.rs:12:18
+   |
+LL |     thread::spawn(move|| {
+   |                   ------ value moved (into closure) here
+...
+LL |     assert_eq!((*arc_v)[2], 3);
+   |                  ^^^^^ value used here after move
+   |
+   = note: move occurs because `arc_v` has type `std::sync::Arc<std::vec::Vec<i32>>`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `arc_v`
+  --> $DIR/no-reuse-move-arc.rs:14:23
+   |
+LL |     thread::spawn(move|| {
+   |                   ------ value moved (into closure) here
+...
+LL |     println!("{:?}", *arc_v);
+   |                       ^^^^^ value used here after move
+   |
+   = note: move occurs because `arc_v` has type `std::sync::Arc<std::vec::Vec<i32>>`, which does not implement the `Copy` trait
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/no-send-res-ports.rs b/src/test/ui/no-send-res-ports.rs
new file mode 100644
index 0000000..e10f447
--- /dev/null
+++ b/src/test/ui/no-send-res-ports.rs
@@ -0,0 +1,30 @@
+use std::thread;
+use std::rc::Rc;
+
+#[derive(Debug)]
+struct Port<T>(Rc<T>);
+
+fn main() {
+    #[derive(Debug)]
+    struct Foo {
+      _x: Port<()>,
+    }
+
+    impl Drop for Foo {
+        fn drop(&mut self) {}
+    }
+
+    fn foo(x: Port<()>) -> Foo {
+        Foo {
+            _x: x
+        }
+    }
+
+    let x = foo(Port(Rc::new(())));
+
+    thread::spawn(move|| {
+        //~^ ERROR `std::rc::Rc<()>` cannot be sent between threads safely
+        let y = x;
+        println!("{:?}", y);
+    });
+}
diff --git a/src/test/ui/no-send-res-ports.stderr b/src/test/ui/no-send-res-ports.stderr
new file mode 100644
index 0000000..515b948
--- /dev/null
+++ b/src/test/ui/no-send-res-ports.stderr
@@ -0,0 +1,15 @@
+error[E0277]: `std::rc::Rc<()>` cannot be sent between threads safely
+  --> $DIR/no-send-res-ports.rs:25:5
+   |
+LL |     thread::spawn(move|| {
+   |     ^^^^^^^^^^^^^ `std::rc::Rc<()>` cannot be sent between threads safely
+   |
+   = help: within `[closure@$DIR/no-send-res-ports.rs:25:19: 29:6 x:main::Foo]`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<()>`
+   = note: required because it appears within the type `Port<()>`
+   = note: required because it appears within the type `main::Foo`
+   = note: required because it appears within the type `[closure@$DIR/no-send-res-ports.rs:25:19: 29:6 x:main::Foo]`
+   = note: required by `std::thread::spawn`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/no-std-inject.rs b/src/test/ui/no-std-inject.rs
new file mode 100644
index 0000000..09879c7
--- /dev/null
+++ b/src/test/ui/no-std-inject.rs
@@ -0,0 +1,7 @@
+#![no_std]
+#![allow(unused_extern_crates)]
+
+extern crate core; //~ ERROR: the name `core` is defined multiple times
+extern crate std;
+
+fn main() {}
diff --git a/src/test/ui/no-std-inject.stderr b/src/test/ui/no-std-inject.stderr
new file mode 100644
index 0000000..975f5c2
--- /dev/null
+++ b/src/test/ui/no-std-inject.stderr
@@ -0,0 +1,15 @@
+error[E0259]: the name `core` is defined multiple times
+  --> $DIR/no-std-inject.rs:4:1
+   |
+LL | extern crate core;
+   | ^^^^^^^^^^^^^^^^^^ `core` reimported here
+   |
+   = note: `core` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | extern crate core as other_core;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0259`.
diff --git a/src/test/ui/no-type-for-node-ice.rs b/src/test/ui/no-type-for-node-ice.rs
new file mode 100644
index 0000000..d0cfdbf
--- /dev/null
+++ b/src/test/ui/no-type-for-node-ice.rs
@@ -0,0 +1,5 @@
+// Related issues: #20401, #20506, #20614, #20752, #20829, #20846, #20885, #20886
+
+fn main() {
+    "".homura[""]; //~ no field `homura` on type `&'static str`
+}
diff --git a/src/test/ui/no-type-for-node-ice.stderr b/src/test/ui/no-type-for-node-ice.stderr
new file mode 100644
index 0000000..b50241f
--- /dev/null
+++ b/src/test/ui/no-type-for-node-ice.stderr
@@ -0,0 +1,9 @@
+error[E0609]: no field `homura` on type `&'static str`
+  --> $DIR/no-type-for-node-ice.rs:4:8
+   |
+LL |     "".homura[""];
+   |        ^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0609`.
diff --git a/src/test/ui/no-warn-on-field-replace-issue-34101.rs b/src/test/ui/no-warn-on-field-replace-issue-34101.rs
new file mode 100644
index 0000000..af6ccf3
--- /dev/null
+++ b/src/test/ui/no-warn-on-field-replace-issue-34101.rs
@@ -0,0 +1,46 @@
+// Issue 34101: Circa 2016-06-05, `fn inline` below issued an
+// erroneous warning from the elaborate_drops pass about moving out of
+// a field in `Foo`, which has a destructor (and thus cannot have
+// content moved out of it). The reason that the warning is erroneous
+// in this case is that we are doing a *replace*, not a move, of the
+// content in question, and it is okay to replace fields within `Foo`.
+//
+// Another more subtle problem was that the elaborate_drops was
+// creating a separate drop flag for that internally replaced content,
+// even though the compiler should enforce an invariant that any drop
+// flag for such subcontent of `Foo` will always have the same value
+// as the drop flag for `Foo` itself.
+
+
+
+
+
+
+
+
+// compile-pass
+
+struct Foo(String);
+
+impl Drop for Foo {
+    fn drop(&mut self) {}
+}
+
+fn inline() {
+    // (dummy variable so `f` gets assigned `var1` in MIR for both fn's)
+    let _s = ();
+    let mut f = Foo(String::from("foo"));
+    f.0 = String::from("bar");
+}
+
+fn outline() {
+    let _s = String::from("foo");
+    let mut f = Foo(_s);
+    f.0 = String::from("bar");
+}
+
+
+fn main() {
+    inline();
+    outline();
+}
diff --git a/src/test/ui/no_crate_type.rs b/src/test/ui/no_crate_type.rs
new file mode 100644
index 0000000..392c6fd
--- /dev/null
+++ b/src/test/ui/no_crate_type.rs
@@ -0,0 +1,6 @@
+// regression test for issue 11256
+#![crate_type]  //~ ERROR attribute must be of the form
+
+fn main() {
+    return
+}
diff --git a/src/test/ui/no_crate_type.stderr b/src/test/ui/no_crate_type.stderr
new file mode 100644
index 0000000..ec79420
--- /dev/null
+++ b/src/test/ui/no_crate_type.stderr
@@ -0,0 +1,8 @@
+error: attribute must be of the form `#[crate_type = "bin|lib|..."]`
+  --> $DIR/no_crate_type.rs:2:1
+   |
+LL | #![crate_type]
+   | ^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/no_owned_box_lang_item.rs b/src/test/ui/no_owned_box_lang_item.rs
new file mode 100644
index 0000000..b76699c
--- /dev/null
+++ b/src/test/ui/no_owned_box_lang_item.rs
@@ -0,0 +1,16 @@
+// Test that we don't ICE when we are missing the owned_box lang item.
+
+// error-pattern: requires `owned_box` lang_item
+
+#![feature(lang_items, box_syntax)]
+#![no_std]
+
+use core::panic::PanicInfo;
+
+fn main() {
+    let x = box 1i32;
+}
+
+#[lang = "eh_personality"] extern fn eh_personality() {}
+#[lang = "eh_unwind_resume"] extern fn eh_unwind_resume() {}
+#[lang = "panic_impl"] fn panic_impl(panic: &PanicInfo) -> ! { loop {} }
diff --git a/src/test/ui/no_owned_box_lang_item.stderr b/src/test/ui/no_owned_box_lang_item.stderr
new file mode 100644
index 0000000..c55c246
--- /dev/null
+++ b/src/test/ui/no_owned_box_lang_item.stderr
@@ -0,0 +1,4 @@
+error: requires `owned_box` lang_item
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/no_send-enum.rs b/src/test/ui/no_send-enum.rs
new file mode 100644
index 0000000..4b4d06f
--- /dev/null
+++ b/src/test/ui/no_send-enum.rs
@@ -0,0 +1,18 @@
+#![feature(optin_builtin_traits)]
+
+use std::marker::Send;
+
+struct NoSend;
+impl !Send for NoSend {}
+
+enum Foo {
+    A(NoSend)
+}
+
+fn bar<T: Send>(_: T) {}
+
+fn main() {
+    let x = Foo::A(NoSend);
+    bar(x);
+    //~^ ERROR `NoSend` cannot be sent between threads safely
+}
diff --git a/src/test/ui/no_send-enum.stderr b/src/test/ui/no_send-enum.stderr
new file mode 100644
index 0000000..71e3aee
--- /dev/null
+++ b/src/test/ui/no_send-enum.stderr
@@ -0,0 +1,17 @@
+error[E0277]: `NoSend` cannot be sent between threads safely
+  --> $DIR/no_send-enum.rs:16:5
+   |
+LL |     bar(x);
+   |     ^^^ `NoSend` cannot be sent between threads safely
+   |
+   = help: within `Foo`, the trait `std::marker::Send` is not implemented for `NoSend`
+   = note: required because it appears within the type `Foo`
+note: required by `bar`
+  --> $DIR/no_send-enum.rs:12:1
+   |
+LL | fn bar<T: Send>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/no_send-rc.rs b/src/test/ui/no_send-rc.rs
new file mode 100644
index 0000000..6ed0286
--- /dev/null
+++ b/src/test/ui/no_send-rc.rs
@@ -0,0 +1,9 @@
+use std::rc::Rc;
+
+fn bar<T: Send>(_: T) {}
+
+fn main() {
+    let x = Rc::new(5);
+    bar(x);
+    //~^ ERROR `std::rc::Rc<{integer}>` cannot be sent between threads safely
+}
diff --git a/src/test/ui/no_send-rc.stderr b/src/test/ui/no_send-rc.stderr
new file mode 100644
index 0000000..2028cf7
--- /dev/null
+++ b/src/test/ui/no_send-rc.stderr
@@ -0,0 +1,16 @@
+error[E0277]: `std::rc::Rc<{integer}>` cannot be sent between threads safely
+  --> $DIR/no_send-rc.rs:7:5
+   |
+LL |     bar(x);
+   |     ^^^ `std::rc::Rc<{integer}>` cannot be sent between threads safely
+   |
+   = help: the trait `std::marker::Send` is not implemented for `std::rc::Rc<{integer}>`
+note: required by `bar`
+  --> $DIR/no_send-rc.rs:3:1
+   |
+LL | fn bar<T: Send>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/no_send-struct.rs b/src/test/ui/no_send-struct.rs
new file mode 100644
index 0000000..67816bf
--- /dev/null
+++ b/src/test/ui/no_send-struct.rs
@@ -0,0 +1,17 @@
+#![feature(optin_builtin_traits)]
+
+use std::marker::Send;
+
+struct Foo {
+    a: isize,
+}
+
+impl !Send for Foo {}
+
+fn bar<T: Send>(_: T) {}
+
+fn main() {
+    let x = Foo { a: 5 };
+    bar(x);
+    //~^ ERROR `Foo` cannot be sent between threads safely
+}
diff --git a/src/test/ui/no_send-struct.stderr b/src/test/ui/no_send-struct.stderr
new file mode 100644
index 0000000..ca4ae05
--- /dev/null
+++ b/src/test/ui/no_send-struct.stderr
@@ -0,0 +1,16 @@
+error[E0277]: `Foo` cannot be sent between threads safely
+  --> $DIR/no_send-struct.rs:15:5
+   |
+LL |     bar(x);
+   |     ^^^ `Foo` cannot be sent between threads safely
+   |
+   = help: the trait `std::marker::Send` is not implemented for `Foo`
+note: required by `bar`
+  --> $DIR/no_send-struct.rs:11:1
+   |
+LL | fn bar<T: Send>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/no_share-enum.rs b/src/test/ui/no_share-enum.rs
new file mode 100644
index 0000000..f5edb63
--- /dev/null
+++ b/src/test/ui/no_share-enum.rs
@@ -0,0 +1,16 @@
+#![feature(optin_builtin_traits)]
+
+use std::marker::Sync;
+
+struct NoSync;
+impl !Sync for NoSync {}
+
+enum Foo { A(NoSync) }
+
+fn bar<T: Sync>(_: T) {}
+
+fn main() {
+    let x = Foo::A(NoSync);
+    bar(x);
+    //~^ ERROR `NoSync` cannot be shared between threads safely [E0277]
+}
diff --git a/src/test/ui/no_share-enum.stderr b/src/test/ui/no_share-enum.stderr
new file mode 100644
index 0000000..64d791d
--- /dev/null
+++ b/src/test/ui/no_share-enum.stderr
@@ -0,0 +1,17 @@
+error[E0277]: `NoSync` cannot be shared between threads safely
+  --> $DIR/no_share-enum.rs:14:5
+   |
+LL |     bar(x);
+   |     ^^^ `NoSync` cannot be shared between threads safely
+   |
+   = help: within `Foo`, the trait `std::marker::Sync` is not implemented for `NoSync`
+   = note: required because it appears within the type `Foo`
+note: required by `bar`
+  --> $DIR/no_share-enum.rs:10:1
+   |
+LL | fn bar<T: Sync>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/no_share-struct.rs b/src/test/ui/no_share-struct.rs
new file mode 100644
index 0000000..35867d0
--- /dev/null
+++ b/src/test/ui/no_share-struct.rs
@@ -0,0 +1,14 @@
+#![feature(optin_builtin_traits)]
+
+use std::marker::Sync;
+
+struct Foo { a: isize }
+impl !Sync for Foo {}
+
+fn bar<T: Sync>(_: T) {}
+
+fn main() {
+    let x = Foo { a: 5 };
+    bar(x);
+    //~^ ERROR `Foo` cannot be shared between threads safely [E0277]
+}
diff --git a/src/test/ui/no_share-struct.stderr b/src/test/ui/no_share-struct.stderr
new file mode 100644
index 0000000..fc4bcfb
--- /dev/null
+++ b/src/test/ui/no_share-struct.stderr
@@ -0,0 +1,16 @@
+error[E0277]: `Foo` cannot be shared between threads safely
+  --> $DIR/no_share-struct.rs:12:5
+   |
+LL |     bar(x);
+   |     ^^^ `Foo` cannot be shared between threads safely
+   |
+   = help: the trait `std::marker::Sync` is not implemented for `Foo`
+note: required by `bar`
+  --> $DIR/no_share-struct.rs:8:1
+   |
+LL | fn bar<T: Sync>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/noexporttypeexe.rs b/src/test/ui/noexporttypeexe.rs
new file mode 100644
index 0000000..651c928
--- /dev/null
+++ b/src/test/ui/noexporttypeexe.rs
@@ -0,0 +1,15 @@
+// aux-build:noexporttypelib.rs
+
+extern crate noexporttypelib;
+
+fn main() {
+    // Here, the type returned by foo() is not exported.
+    // This used to cause internal errors when serializing
+    // because the def_id associated with the type was
+    // not convertible to a path.
+  let x: isize = noexporttypelib::foo();
+    //~^ ERROR mismatched types
+    //~| expected type `isize`
+    //~| found type `std::option::Option<isize>`
+    //~| expected isize, found enum `std::option::Option`
+}
diff --git a/src/test/ui/noexporttypeexe.stderr b/src/test/ui/noexporttypeexe.stderr
new file mode 100644
index 0000000..329787f
--- /dev/null
+++ b/src/test/ui/noexporttypeexe.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/noexporttypeexe.rs:10:18
+   |
+LL |   let x: isize = noexporttypelib::foo();
+   |                  ^^^^^^^^^^^^^^^^^^^^^^ expected isize, found enum `std::option::Option`
+   |
+   = note: expected type `isize`
+              found type `std::option::Option<isize>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/non-constant-expr-for-arr-len.rs b/src/test/ui/non-constant-expr-for-arr-len.rs
new file mode 100644
index 0000000..1b101d3
--- /dev/null
+++ b/src/test/ui/non-constant-expr-for-arr-len.rs
@@ -0,0 +1,8 @@
+// Check that non constant exprs fail for array repeat syntax
+
+fn main() {
+    fn bar(n: usize) {
+        let _x = [0; n];
+        //~^ ERROR attempt to use a non-constant value in a constant [E0435]
+    }
+}
diff --git a/src/test/ui/non-constant-expr-for-arr-len.stderr b/src/test/ui/non-constant-expr-for-arr-len.stderr
new file mode 100644
index 0000000..b947cb7
--- /dev/null
+++ b/src/test/ui/non-constant-expr-for-arr-len.stderr
@@ -0,0 +1,9 @@
+error[E0435]: attempt to use a non-constant value in a constant
+  --> $DIR/non-constant-expr-for-arr-len.rs:5:22
+   |
+LL |         let _x = [0; n];
+   |                      ^ non-constant value
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0435`.
diff --git a/src/test/ui/non-constant-in-const-path.rs b/src/test/ui/non-constant-in-const-path.rs
new file mode 100644
index 0000000..343bb98
--- /dev/null
+++ b/src/test/ui/non-constant-in-const-path.rs
@@ -0,0 +1,7 @@
+fn main() {
+    let x = 0;
+    match 1 {
+        0 ..= x => {}
+        //~^ ERROR runtime values cannot be referenced in patterns
+    };
+}
diff --git a/src/test/ui/non-constant-in-const-path.stderr b/src/test/ui/non-constant-in-const-path.stderr
new file mode 100644
index 0000000..5936f76
--- /dev/null
+++ b/src/test/ui/non-constant-in-const-path.stderr
@@ -0,0 +1,9 @@
+error[E0080]: runtime values cannot be referenced in patterns
+  --> $DIR/non-constant-in-const-path.rs:4:15
+   |
+LL |         0 ..= x => {}
+   |               ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/non-copyable-void.rs b/src/test/ui/non-copyable-void.rs
new file mode 100644
index 0000000..ddaaee4
--- /dev/null
+++ b/src/test/ui/non-copyable-void.rs
@@ -0,0 +1,14 @@
+// ignore-wasm32-bare no libc to test ffi with
+
+#![feature(rustc_private)]
+
+extern crate libc;
+
+fn main() {
+    let x : *const Vec<isize> = &vec![1,2,3];
+    let y : *const libc::c_void = x as *const libc::c_void;
+    unsafe {
+        let _z = (*y).clone();
+        //~^ ERROR no method named `clone` found
+    }
+}
diff --git a/src/test/ui/non-copyable-void.stderr b/src/test/ui/non-copyable-void.stderr
new file mode 100644
index 0000000..4041e19
--- /dev/null
+++ b/src/test/ui/non-copyable-void.stderr
@@ -0,0 +1,9 @@
+error[E0599]: no method named `clone` found for type `libc::c_void` in the current scope
+  --> $DIR/non-copyable-void.rs:11:23
+   |
+LL |         let _z = (*y).clone();
+   |                       ^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/non-exhaustive/non-exhaustive-float-range-match.rs b/src/test/ui/non-exhaustive/non-exhaustive-float-range-match.rs
new file mode 100644
index 0000000..588fecb
--- /dev/null
+++ b/src/test/ui/non-exhaustive/non-exhaustive-float-range-match.rs
@@ -0,0 +1,13 @@
+#![allow(illegal_floating_point_literal_pattern)]
+#![deny(unreachable_patterns)]
+
+fn main() {
+    match 0.0 {
+      0.0..=1.0 => {}
+      _ => {} // ok
+    }
+
+    match 0.0 { //~ ERROR non-exhaustive patterns
+      0.0..=1.0 => {}
+    }
+}
diff --git a/src/test/ui/non-exhaustive/non-exhaustive-float-range-match.stderr b/src/test/ui/non-exhaustive/non-exhaustive-float-range-match.stderr
new file mode 100644
index 0000000..6de615c
--- /dev/null
+++ b/src/test/ui/non-exhaustive/non-exhaustive-float-range-match.stderr
@@ -0,0 +1,11 @@
+error[E0004]: non-exhaustive patterns: `_` not covered
+  --> $DIR/non-exhaustive-float-range-match.rs:10:11
+   |
+LL |     match 0.0 {
+   |           ^^^ pattern `_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/non-exhaustive/non-exhaustive-match-nested.rs b/src/test/ui/non-exhaustive/non-exhaustive-match-nested.rs
new file mode 100644
index 0000000..9423a28
--- /dev/null
+++ b/src/test/ui/non-exhaustive/non-exhaustive-match-nested.rs
@@ -0,0 +1,21 @@
+#![feature(slice_patterns)]
+
+enum T { A(U), B }
+enum U { C, D }
+
+fn match_nested_vecs<'a, T>(l1: Option<&'a [T]>, l2: Result<&'a [T], ()>) -> &'static str {
+    match (l1, l2) { //~ ERROR non-exhaustive patterns: `(Some(&[]), Err(_))` not covered
+        (Some(&[]), Ok(&[])) => "Some(empty), Ok(empty)",
+        (Some(&[_, ..]), Ok(_)) | (Some(&[_, ..]), Err(())) => "Some(non-empty), any",
+        (None, Ok(&[])) | (None, Err(())) | (None, Ok(&[_])) => "None, Ok(less than one element)",
+        (None, Ok(&[_, _, ..])) => "None, Ok(at least two elements)"
+    }
+}
+
+fn main() {
+    let x = T::A(U::C);
+    match x { //~ ERROR non-exhaustive patterns: `A(C)` not covered
+        T::A(U::D) => { panic!("hello"); }
+        T::B => { panic!("goodbye"); }
+    }
+}
diff --git a/src/test/ui/non-exhaustive/non-exhaustive-match-nested.stderr b/src/test/ui/non-exhaustive/non-exhaustive-match-nested.stderr
new file mode 100644
index 0000000..67c818e
--- /dev/null
+++ b/src/test/ui/non-exhaustive/non-exhaustive-match-nested.stderr
@@ -0,0 +1,25 @@
+error[E0004]: non-exhaustive patterns: `(Some(&[]), Err(_))` not covered
+  --> $DIR/non-exhaustive-match-nested.rs:7:11
+   |
+LL |     match (l1, l2) {
+   |           ^^^^^^^^ pattern `(Some(&[]), Err(_))` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `A(C)` not covered
+  --> $DIR/non-exhaustive-match-nested.rs:17:11
+   |
+LL | enum T { A(U), B }
+   | ------------------
+   | |        |
+   | |        not covered
+   | `T` defined here
+...
+LL |     match x {
+   |           ^ pattern `A(C)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/non-exhaustive/non-exhaustive-match.rs b/src/test/ui/non-exhaustive/non-exhaustive-match.rs
new file mode 100644
index 0000000..e888bcf
--- /dev/null
+++ b/src/test/ui/non-exhaustive/non-exhaustive-match.rs
@@ -0,0 +1,64 @@
+#![feature(slice_patterns)]
+#![allow(illegal_floating_point_literal_pattern)]
+
+enum T { A, B }
+
+fn main() {
+    let x = T::A;
+    match x { T::B => { } } //~ ERROR non-exhaustive patterns: `A` not covered
+    match true { //~ ERROR non-exhaustive patterns: `false` not covered
+      true => {}
+    }
+    match Some(10) { //~ ERROR non-exhaustive patterns: `Some(_)` not covered
+      None => {}
+    }
+    match (2, 3, 4) { //~ ERROR non-exhaustive patterns: `(_, _, -2147483648i32..=3i32)`
+                      //  and `(_, _, 5i32..=2147483647i32)` not covered
+      (_, _, 4) => {}
+    }
+    match (T::A, T::A) { //~ ERROR non-exhaustive patterns: `(A, A)` not covered
+      (T::A, T::B) => {}
+      (T::B, T::A) => {}
+    }
+    match T::A { //~ ERROR non-exhaustive patterns: `B` not covered
+      T::A => {}
+    }
+    // This is exhaustive, though the algorithm got it wrong at one point
+    match (T::A, T::B) {
+      (T::A, _) => {}
+      (_, T::A) => {}
+      (T::B, T::B) => {}
+    }
+    let vec = vec![Some(42), None, Some(21)];
+    let vec: &[Option<isize>] = &vec;
+    match *vec { //~ ERROR non-exhaustive patterns: `[]` not covered
+        [Some(..), None, ref tail..] => {}
+        [Some(..), Some(..), ref tail..] => {}
+        [None] => {}
+    }
+    let vec = vec![1];
+    let vec: &[isize] = &vec;
+    match *vec {
+        [_, ref tail..] => (),
+        [] => ()
+    }
+    let vec = vec![0.5f32];
+    let vec: &[f32] = &vec;
+    match *vec { //~ ERROR non-exhaustive patterns: `[_, _, _, _]` not covered
+        [0.1, 0.2, 0.3] => (),
+        [0.1, 0.2] => (),
+        [0.1] => (),
+        [] => ()
+    }
+    let vec = vec![Some(42), None, Some(21)];
+    let vec: &[Option<isize>] = &vec;
+    match *vec {
+        [Some(..), None, ref tail..] => {}
+        [Some(..), Some(..), ref tail..] => {}
+        [None, None, ref tail..] => {}
+        [None, Some(..), ref tail..] => {}
+        [Some(_)] => {}
+        [None] => {}
+        [] => {}
+    }
+}
diff --git a/src/test/ui/non-exhaustive/non-exhaustive-match.stderr b/src/test/ui/non-exhaustive/non-exhaustive-match.stderr
new file mode 100644
index 0000000..58e3309
--- /dev/null
+++ b/src/test/ui/non-exhaustive/non-exhaustive-match.stderr
@@ -0,0 +1,79 @@
+error[E0004]: non-exhaustive patterns: `A` not covered
+  --> $DIR/non-exhaustive-match.rs:8:11
+   |
+LL | enum T { A, B }
+   | ---------------
+   | |        |
+   | |        not covered
+   | `T` defined here
+...
+LL |     match x { T::B => { } }
+   |           ^ pattern `A` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `false` not covered
+  --> $DIR/non-exhaustive-match.rs:9:11
+   |
+LL |     match true {
+   |           ^^^^ pattern `false` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `Some(_)` not covered
+  --> $DIR/non-exhaustive-match.rs:12:11
+   |
+LL |     match Some(10) {
+   |           ^^^^^^^^ pattern `Some(_)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `(_, _, -2147483648i32..=3i32)` and `(_, _, 5i32..=2147483647i32)` not covered
+  --> $DIR/non-exhaustive-match.rs:15:11
+   |
+LL |     match (2, 3, 4) {
+   |           ^^^^^^^^^ patterns `(_, _, -2147483648i32..=3i32)` and `(_, _, 5i32..=2147483647i32)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `(A, A)` not covered
+  --> $DIR/non-exhaustive-match.rs:19:11
+   |
+LL |     match (T::A, T::A) {
+   |           ^^^^^^^^^^^^ pattern `(A, A)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `B` not covered
+  --> $DIR/non-exhaustive-match.rs:23:11
+   |
+LL | enum T { A, B }
+   | ---------------
+   | |           |
+   | |           not covered
+   | `T` defined here
+...
+LL |     match T::A {
+   |           ^^^^ pattern `B` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `[]` not covered
+  --> $DIR/non-exhaustive-match.rs:34:11
+   |
+LL |     match *vec {
+   |           ^^^^ pattern `[]` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `[_, _, _, _]` not covered
+  --> $DIR/non-exhaustive-match.rs:47:11
+   |
+LL |     match *vec {
+   |           ^^^^ pattern `[_, _, _, _]` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/non-exhaustive/non-exhaustive-pattern-witness.rs b/src/test/ui/non-exhaustive/non-exhaustive-pattern-witness.rs
new file mode 100644
index 0000000..9fcd4bd
--- /dev/null
+++ b/src/test/ui/non-exhaustive/non-exhaustive-pattern-witness.rs
@@ -0,0 +1,91 @@
+#![feature(slice_patterns)]
+
+struct Foo {
+    first: bool,
+    second: Option<[usize; 4]>
+}
+
+fn struct_with_a_nested_enum_and_vector() {
+    match (Foo { first: true, second: None }) {
+//~^ ERROR non-exhaustive patterns: `Foo { first: false, second: Some([_, _, _, _]) }` not covered
+        Foo { first: true, second: None } => (),
+        Foo { first: true, second: Some(_) } => (),
+        Foo { first: false, second: None } => (),
+        Foo { first: false, second: Some([1, 2, 3, 4]) } => ()
+    }
+}
+
+enum Color {
+    Red,
+    Green,
+    CustomRGBA { a: bool, r: u8, g: u8, b: u8 }
+}
+
+fn enum_with_single_missing_variant() {
+    match Color::Red {
+    //~^ ERROR non-exhaustive patterns: `Red` not covered
+        Color::CustomRGBA { .. } => (),
+        Color::Green => ()
+    }
+}
+
+enum Direction {
+    North, East, South, West
+}
+
+fn enum_with_multiple_missing_variants() {
+    match Direction::North {
+    //~^ ERROR non-exhaustive patterns: `East`, `South` and `West` not covered
+        Direction::North => ()
+    }
+}
+
+enum ExcessiveEnum {
+    First, Second, Third, Fourth, Fifth, Sixth, Seventh, Eighth, Ninth, Tenth, Eleventh, Twelfth
+}
+
+fn enum_with_excessive_missing_variants() {
+    match ExcessiveEnum::First {
+    //~^ ERROR `Second`, `Third`, `Fourth` and 8 more not covered
+
+        ExcessiveEnum::First => ()
+    }
+}
+
+fn enum_struct_variant() {
+    match Color::Red {
+    //~^ ERROR non-exhaustive patterns: `CustomRGBA { a: true, .. }` not covered
+        Color::Red => (),
+        Color::Green => (),
+        Color::CustomRGBA { a: false, r: _, g: _, b: 0 } => (),
+        Color::CustomRGBA { a: false, r: _, g: _, b: _ } => ()
+    }
+}
+
+enum Enum {
+    First,
+    Second(bool)
+}
+
+fn vectors_with_nested_enums() {
+    let x: &'static [Enum] = &[Enum::First, Enum::Second(false)];
+    match *x {
+    //~^ ERROR non-exhaustive patterns: `[Second(true), Second(false)]` not covered
+        [] => (),
+        [_] => (),
+        [Enum::First, _] => (),
+        [Enum::Second(true), Enum::First] => (),
+        [Enum::Second(true), Enum::Second(true)] => (),
+        [Enum::Second(false), _] => (),
+        [_, _, ref tail.., _] => ()
+    }
+}
+
+fn missing_nil() {
+    match ((), false) {
+    //~^ ERROR non-exhaustive patterns: `((), false)` not covered
+        ((), true) => ()
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/non-exhaustive/non-exhaustive-pattern-witness.stderr b/src/test/ui/non-exhaustive/non-exhaustive-pattern-witness.stderr
new file mode 100644
index 0000000..a0b497d
--- /dev/null
+++ b/src/test/ui/non-exhaustive/non-exhaustive-pattern-witness.stderr
@@ -0,0 +1,95 @@
+error[E0004]: non-exhaustive patterns: `Foo { first: false, second: Some([_, _, _, _]) }` not covered
+  --> $DIR/non-exhaustive-pattern-witness.rs:9:11
+   |
+LL | / struct Foo {
+LL | |     first: bool,
+LL | |     second: Option<[usize; 4]>
+LL | | }
+   | |_- `Foo` defined here
+...
+LL |       match (Foo { first: true, second: None }) {
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo { first: false, second: Some([_, _, _, _]) }` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `Red` not covered
+  --> $DIR/non-exhaustive-pattern-witness.rs:25:11
+   |
+LL | / enum Color {
+LL | |     Red,
+   | |     --- not covered
+LL | |     Green,
+LL | |     CustomRGBA { a: bool, r: u8, g: u8, b: u8 }
+LL | | }
+   | |_- `Color` defined here
+...
+LL |       match Color::Red {
+   |             ^^^^^^^^^^ pattern `Red` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `East`, `South` and `West` not covered
+  --> $DIR/non-exhaustive-pattern-witness.rs:37:11
+   |
+LL | / enum Direction {
+LL | |     North, East, South, West
+   | |            ----  -----  ---- not covered
+   | |            |     |
+   | |            |     not covered
+   | |            not covered
+LL | | }
+   | |_- `Direction` defined here
+...
+LL |       match Direction::North {
+   |             ^^^^^^^^^^^^^^^^ patterns `East`, `South` and `West` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `Second`, `Third`, `Fourth` and 8 more not covered
+  --> $DIR/non-exhaustive-pattern-witness.rs:48:11
+   |
+LL | / enum ExcessiveEnum {
+LL | |     First, Second, Third, Fourth, Fifth, Sixth, Seventh, Eighth, Ninth, Tenth, Eleventh, Twelfth
+LL | | }
+   | |_- `ExcessiveEnum` defined here
+...
+LL |       match ExcessiveEnum::First {
+   |             ^^^^^^^^^^^^^^^^^^^^ patterns `Second`, `Third`, `Fourth` and 8 more not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `CustomRGBA { a: true, .. }` not covered
+  --> $DIR/non-exhaustive-pattern-witness.rs:56:11
+   |
+LL | / enum Color {
+LL | |     Red,
+LL | |     Green,
+LL | |     CustomRGBA { a: bool, r: u8, g: u8, b: u8 }
+   | |     ---------- not covered
+LL | | }
+   | |_- `Color` defined here
+...
+LL |       match Color::Red {
+   |             ^^^^^^^^^^ pattern `CustomRGBA { a: true, .. }` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `[Second(true), Second(false)]` not covered
+  --> $DIR/non-exhaustive-pattern-witness.rs:72:11
+   |
+LL |     match *x {
+   |           ^^ pattern `[Second(true), Second(false)]` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `((), false)` not covered
+  --> $DIR/non-exhaustive-pattern-witness.rs:85:11
+   |
+LL |     match ((), false) {
+   |           ^^^^^^^^^^^ pattern `((), false)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/non-interger-atomic.rs b/src/test/ui/non-interger-atomic.rs
new file mode 100644
index 0000000..00d07b7
--- /dev/null
+++ b/src/test/ui/non-interger-atomic.rs
@@ -0,0 +1,90 @@
+#![feature(core_intrinsics)]
+#![allow(warnings)]
+#![crate_type = "rlib"]
+
+use std::intrinsics;
+
+#[derive(Copy, Clone)]
+pub struct Foo(i64);
+pub type Bar = &'static Fn();
+pub type Quux = [u8; 100];
+
+pub unsafe fn test_bool_load(p: &mut bool, v: bool) {
+    intrinsics::atomic_load(p);
+    //~^ ERROR `atomic_load` intrinsic: expected basic integer type, found `bool`
+}
+
+pub unsafe fn test_bool_store(p: &mut bool, v: bool) {
+    intrinsics::atomic_store(p, v);
+    //~^ ERROR `atomic_store` intrinsic: expected basic integer type, found `bool`
+}
+
+pub unsafe fn test_bool_xchg(p: &mut bool, v: bool) {
+    intrinsics::atomic_xchg(p, v);
+    //~^ ERROR `atomic_xchg` intrinsic: expected basic integer type, found `bool`
+}
+
+pub unsafe fn test_bool_cxchg(p: &mut bool, v: bool) {
+    intrinsics::atomic_cxchg(p, v, v);
+    //~^ ERROR `atomic_cxchg` intrinsic: expected basic integer type, found `bool`
+}
+
+pub unsafe fn test_Foo_load(p: &mut Foo, v: Foo) {
+    intrinsics::atomic_load(p);
+    //~^ ERROR `atomic_load` intrinsic: expected basic integer type, found `Foo`
+}
+
+pub unsafe fn test_Foo_store(p: &mut Foo, v: Foo) {
+    intrinsics::atomic_store(p, v);
+    //~^ ERROR `atomic_store` intrinsic: expected basic integer type, found `Foo`
+}
+
+pub unsafe fn test_Foo_xchg(p: &mut Foo, v: Foo) {
+    intrinsics::atomic_xchg(p, v);
+    //~^ ERROR `atomic_xchg` intrinsic: expected basic integer type, found `Foo`
+}
+
+pub unsafe fn test_Foo_cxchg(p: &mut Foo, v: Foo) {
+    intrinsics::atomic_cxchg(p, v, v);
+    //~^ ERROR `atomic_cxchg` intrinsic: expected basic integer type, found `Foo`
+}
+
+pub unsafe fn test_Bar_load(p: &mut Bar, v: Bar) {
+    intrinsics::atomic_load(p);
+    //~^ ERROR expected basic integer type, found `&dyn std::ops::Fn()`
+}
+
+pub unsafe fn test_Bar_store(p: &mut Bar, v: Bar) {
+    intrinsics::atomic_store(p, v);
+    //~^ ERROR expected basic integer type, found `&dyn std::ops::Fn()`
+}
+
+pub unsafe fn test_Bar_xchg(p: &mut Bar, v: Bar) {
+    intrinsics::atomic_xchg(p, v);
+    //~^ ERROR expected basic integer type, found `&dyn std::ops::Fn()`
+}
+
+pub unsafe fn test_Bar_cxchg(p: &mut Bar, v: Bar) {
+    intrinsics::atomic_cxchg(p, v, v);
+    //~^ ERROR expected basic integer type, found `&dyn std::ops::Fn()`
+}
+
+pub unsafe fn test_Quux_load(p: &mut Quux, v: Quux) {
+    intrinsics::atomic_load(p);
+    //~^ ERROR `atomic_load` intrinsic: expected basic integer type, found `[u8; 100]`
+}
+
+pub unsafe fn test_Quux_store(p: &mut Quux, v: Quux) {
+    intrinsics::atomic_store(p, v);
+    //~^ ERROR `atomic_store` intrinsic: expected basic integer type, found `[u8; 100]`
+}
+
+pub unsafe fn test_Quux_xchg(p: &mut Quux, v: Quux) {
+    intrinsics::atomic_xchg(p, v);
+    //~^ ERROR `atomic_xchg` intrinsic: expected basic integer type, found `[u8; 100]`
+}
+
+pub unsafe fn test_Quux_cxchg(p: &mut Quux, v: Quux) {
+    intrinsics::atomic_cxchg(p, v, v);
+    //~^ ERROR `atomic_cxchg` intrinsic: expected basic integer type, found `[u8; 100]`
+}
diff --git a/src/test/ui/non-interger-atomic.stderr b/src/test/ui/non-interger-atomic.stderr
new file mode 100644
index 0000000..9a49ee8
--- /dev/null
+++ b/src/test/ui/non-interger-atomic.stderr
@@ -0,0 +1,99 @@
+error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer type, found `bool`
+  --> $DIR/non-interger-atomic.rs:13:5
+   |
+LL |     intrinsics::atomic_load(p);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `atomic_store` intrinsic: expected basic integer type, found `bool`
+  --> $DIR/non-interger-atomic.rs:18:5
+   |
+LL |     intrinsics::atomic_store(p, v);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `atomic_xchg` intrinsic: expected basic integer type, found `bool`
+  --> $DIR/non-interger-atomic.rs:23:5
+   |
+LL |     intrinsics::atomic_xchg(p, v);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer type, found `bool`
+  --> $DIR/non-interger-atomic.rs:28:5
+   |
+LL |     intrinsics::atomic_cxchg(p, v, v);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer type, found `Foo`
+  --> $DIR/non-interger-atomic.rs:33:5
+   |
+LL |     intrinsics::atomic_load(p);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `atomic_store` intrinsic: expected basic integer type, found `Foo`
+  --> $DIR/non-interger-atomic.rs:38:5
+   |
+LL |     intrinsics::atomic_store(p, v);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `atomic_xchg` intrinsic: expected basic integer type, found `Foo`
+  --> $DIR/non-interger-atomic.rs:43:5
+   |
+LL |     intrinsics::atomic_xchg(p, v);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer type, found `Foo`
+  --> $DIR/non-interger-atomic.rs:48:5
+   |
+LL |     intrinsics::atomic_cxchg(p, v, v);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer type, found `&dyn std::ops::Fn()`
+  --> $DIR/non-interger-atomic.rs:53:5
+   |
+LL |     intrinsics::atomic_load(p);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `atomic_store` intrinsic: expected basic integer type, found `&dyn std::ops::Fn()`
+  --> $DIR/non-interger-atomic.rs:58:5
+   |
+LL |     intrinsics::atomic_store(p, v);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `atomic_xchg` intrinsic: expected basic integer type, found `&dyn std::ops::Fn()`
+  --> $DIR/non-interger-atomic.rs:63:5
+   |
+LL |     intrinsics::atomic_xchg(p, v);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer type, found `&dyn std::ops::Fn()`
+  --> $DIR/non-interger-atomic.rs:68:5
+   |
+LL |     intrinsics::atomic_cxchg(p, v, v);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer type, found `[u8; 100]`
+  --> $DIR/non-interger-atomic.rs:73:5
+   |
+LL |     intrinsics::atomic_load(p);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `atomic_store` intrinsic: expected basic integer type, found `[u8; 100]`
+  --> $DIR/non-interger-atomic.rs:78:5
+   |
+LL |     intrinsics::atomic_store(p, v);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `atomic_xchg` intrinsic: expected basic integer type, found `[u8; 100]`
+  --> $DIR/non-interger-atomic.rs:83:5
+   |
+LL |     intrinsics::atomic_xchg(p, v);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer type, found `[u8; 100]`
+  --> $DIR/non-interger-atomic.rs:88:5
+   |
+LL |     intrinsics::atomic_cxchg(p, v, v);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 16 previous errors
+
+For more information about this error, try `rustc --explain E0511`.
diff --git a/src/test/ui/non_modrs_mods_and_inline_mods/non_modrs_mods_and_inline_mods.rs b/src/test/ui/non_modrs_mods_and_inline_mods/non_modrs_mods_and_inline_mods.rs
new file mode 100644
index 0000000..25a9c2e
--- /dev/null
+++ b/src/test/ui/non_modrs_mods_and_inline_mods/non_modrs_mods_and_inline_mods.rs
@@ -0,0 +1,5 @@
+// compile-pass
+
+mod x;
+
+fn main() {}
diff --git a/src/test/ui/non_modrs_mods_and_inline_mods/x.rs b/src/test/ui/non_modrs_mods_and_inline_mods/x.rs
new file mode 100644
index 0000000..a39a7c6
--- /dev/null
+++ b/src/test/ui/non_modrs_mods_and_inline_mods/x.rs
@@ -0,0 +1,5 @@
+// ignore-test: not a test
+
+pub mod y {
+    pub mod z;
+}
diff --git a/src/test/ui/non_modrs_mods_and_inline_mods/x/y/z/mod.rs b/src/test/ui/non_modrs_mods_and_inline_mods/x/y/z/mod.rs
new file mode 100644
index 0000000..e8442a4
--- /dev/null
+++ b/src/test/ui/non_modrs_mods_and_inline_mods/x/y/z/mod.rs
@@ -0,0 +1 @@
+// ignore-test: not a test
diff --git a/src/test/ui/noncopyable-class.rs b/src/test/ui/noncopyable-class.rs
new file mode 100644
index 0000000..11b6eb7
--- /dev/null
+++ b/src/test/ui/noncopyable-class.rs
@@ -0,0 +1,36 @@
+// Test that a class with a non-copyable field can't be
+// copied
+
+#[derive(Debug)]
+struct Bar {
+  x: isize,
+}
+
+impl Drop for Bar {
+    fn drop(&mut self) {}
+}
+
+fn bar(x:isize) -> Bar {
+    Bar {
+        x: x
+    }
+}
+
+#[derive(Debug)]
+struct Foo {
+  i: isize,
+  j: Bar,
+}
+
+fn foo(i:isize) -> Foo {
+    Foo {
+        i: i,
+        j: bar(5)
+    }
+}
+
+fn main() {
+    let x = foo(10);
+    let _y = x.clone(); //~ ERROR no method named `clone` found
+    println!("{:?}", x);
+}
diff --git a/src/test/ui/noncopyable-class.stderr b/src/test/ui/noncopyable-class.stderr
new file mode 100644
index 0000000..eb47a33
--- /dev/null
+++ b/src/test/ui/noncopyable-class.stderr
@@ -0,0 +1,16 @@
+error[E0599]: no method named `clone` found for type `Foo` in the current scope
+  --> $DIR/noncopyable-class.rs:34:16
+   |
+LL | struct Foo {
+   | ---------- method `clone` not found for this
+...
+LL |     let _y = x.clone();
+   |                ^^^^^
+   |
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following trait defines an item `clone`, perhaps you need to implement it:
+           candidate #1: `std::clone::Clone`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/nonscalar-cast.rs b/src/test/ui/nonscalar-cast.rs
new file mode 100644
index 0000000..7e6f1fd
--- /dev/null
+++ b/src/test/ui/nonscalar-cast.rs
@@ -0,0 +1,8 @@
+#[derive(Debug)]
+struct Foo {
+    x: isize
+}
+
+fn main() {
+    println!("{}", Foo { x: 1 } as isize); //~ non-primitive cast: `Foo` as `isize` [E0605]
+}
diff --git a/src/test/ui/nonscalar-cast.stderr b/src/test/ui/nonscalar-cast.stderr
new file mode 100644
index 0000000..9338688
--- /dev/null
+++ b/src/test/ui/nonscalar-cast.stderr
@@ -0,0 +1,11 @@
+error[E0605]: non-primitive cast: `Foo` as `isize`
+  --> $DIR/nonscalar-cast.rs:7:20
+   |
+LL |     println!("{}", Foo { x: 1 } as isize);
+   |                    ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0605`.
diff --git a/src/test/ui/not-clone-closure.rs b/src/test/ui/not-clone-closure.rs
new file mode 100644
index 0000000..134d52c
--- /dev/null
+++ b/src/test/ui/not-clone-closure.rs
@@ -0,0 +1,12 @@
+// Check that closures do not implement `Clone` if their environment is not `Clone`.
+
+struct S(i32);
+
+fn main() {
+    let a = S(5);
+    let hello = move || {
+        println!("Hello {}", a.0);
+    };
+
+    let hello = hello.clone(); //~ ERROR the trait bound `S: std::clone::Clone` is not satisfied
+}
diff --git a/src/test/ui/not-clone-closure.stderr b/src/test/ui/not-clone-closure.stderr
new file mode 100644
index 0000000..b66391b
--- /dev/null
+++ b/src/test/ui/not-clone-closure.stderr
@@ -0,0 +1,11 @@
+error[E0277]: the trait bound `S: std::clone::Clone` is not satisfied in `[closure@$DIR/not-clone-closure.rs:7:17: 9:6 a:S]`
+  --> $DIR/not-clone-closure.rs:11:23
+   |
+LL |     let hello = hello.clone();
+   |                       ^^^^^ within `[closure@$DIR/not-clone-closure.rs:7:17: 9:6 a:S]`, the trait `std::clone::Clone` is not implemented for `S`
+   |
+   = note: required because it appears within the type `[closure@$DIR/not-clone-closure.rs:7:17: 9:6 a:S]`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/not-copy-closure.nll.stderr b/src/test/ui/not-copy-closure.nll.stderr
new file mode 100644
index 0000000..10bf570
--- /dev/null
+++ b/src/test/ui/not-copy-closure.nll.stderr
@@ -0,0 +1,17 @@
+error[E0382]: use of moved value: `hello`
+  --> $DIR/not-copy-closure.rs:10:13
+   |
+LL |     let b = hello;
+   |             ----- value moved here
+LL |     let c = hello;
+   |             ^^^^^ value used here after move
+   |
+note: closure cannot be moved more than once as it is not `Copy` due to moving the variable `a` out of its environment
+  --> $DIR/not-copy-closure.rs:6:9
+   |
+LL |         a += 1;
+   |         ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/not-copy-closure.rs b/src/test/ui/not-copy-closure.rs
new file mode 100644
index 0000000..f6530f9
--- /dev/null
+++ b/src/test/ui/not-copy-closure.rs
@@ -0,0 +1,11 @@
+// Check that closures do not implement `Copy` if their environment is not `Copy`.
+
+fn main() {
+    let mut a = 5;
+    let hello = || {
+        a += 1;
+    };
+
+    let b = hello;
+    let c = hello; //~ ERROR use of moved value: `hello` [E0382]
+}
diff --git a/src/test/ui/not-copy-closure.stderr b/src/test/ui/not-copy-closure.stderr
new file mode 100644
index 0000000..4144753
--- /dev/null
+++ b/src/test/ui/not-copy-closure.stderr
@@ -0,0 +1,17 @@
+error[E0382]: use of moved value: `hello`
+  --> $DIR/not-copy-closure.rs:10:9
+   |
+LL |     let b = hello;
+   |         - value moved here
+LL |     let c = hello;
+   |         ^ value used here after move
+   |
+note: closure cannot be invoked more than once because it moves the variable `a` out of its environment
+  --> $DIR/not-copy-closure.rs:6:9
+   |
+LL |         a += 1;
+   |         ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/not-enough-arguments.rs b/src/test/ui/not-enough-arguments.rs
new file mode 100644
index 0000000..309283e
--- /dev/null
+++ b/src/test/ui/not-enough-arguments.rs
@@ -0,0 +1,12 @@
+// Check that the only error msg we report is the
+// mismatch between the # of params, and not other
+// unrelated errors.
+
+fn foo(a: isize, b: isize, c: isize, d:isize) {
+  panic!();
+}
+
+fn main() {
+  foo(1, 2, 3);
+  //~^ ERROR this function takes 4 parameters but 3
+}
diff --git a/src/test/ui/not-enough-arguments.stderr b/src/test/ui/not-enough-arguments.stderr
new file mode 100644
index 0000000..c1ee43e
--- /dev/null
+++ b/src/test/ui/not-enough-arguments.stderr
@@ -0,0 +1,12 @@
+error[E0061]: this function takes 4 parameters but 3 parameters were supplied
+  --> $DIR/not-enough-arguments.rs:10:3
+   |
+LL | fn foo(a: isize, b: isize, c: isize, d:isize) {
+   | --------------------------------------------- defined here
+...
+LL |   foo(1, 2, 3);
+   |   ^^^^^^^^^^^^ expected 4 parameters
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0061`.
diff --git a/src/test/ui/not-panic/not-panic-safe-2.rs b/src/test/ui/not-panic/not-panic-safe-2.rs
new file mode 100644
index 0000000..cd07428
--- /dev/null
+++ b/src/test/ui/not-panic/not-panic-safe-2.rs
@@ -0,0 +1,13 @@
+#![allow(dead_code)]
+
+use std::panic::UnwindSafe;
+use std::rc::Rc;
+use std::cell::RefCell;
+
+fn assert<T: UnwindSafe + ?Sized>() {}
+
+fn main() {
+    assert::<Rc<RefCell<i32>>>();
+    //~^ ERROR the type `std::cell::UnsafeCell<i32>` may contain interior mutability and a
+    //~| ERROR the type `std::cell::UnsafeCell<isize>` may contain interior mutability and a
+}
diff --git a/src/test/ui/not-panic/not-panic-safe-2.stderr b/src/test/ui/not-panic/not-panic-safe-2.stderr
new file mode 100644
index 0000000..4db127a
--- /dev/null
+++ b/src/test/ui/not-panic/not-panic-safe-2.stderr
@@ -0,0 +1,34 @@
+error[E0277]: the type `std::cell::UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
+  --> $DIR/not-panic-safe-2.rs:10:5
+   |
+LL |     assert::<Rc<RefCell<i32>>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ `std::cell::UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
+   |
+   = help: within `std::cell::RefCell<i32>`, the trait `std::panic::RefUnwindSafe` is not implemented for `std::cell::UnsafeCell<i32>`
+   = note: required because it appears within the type `std::cell::RefCell<i32>`
+   = note: required because of the requirements on the impl of `std::panic::UnwindSafe` for `std::rc::Rc<std::cell::RefCell<i32>>`
+note: required by `assert`
+  --> $DIR/not-panic-safe-2.rs:7:1
+   |
+LL | fn assert<T: UnwindSafe + ?Sized>() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the type `std::cell::UnsafeCell<isize>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
+  --> $DIR/not-panic-safe-2.rs:10:5
+   |
+LL |     assert::<Rc<RefCell<i32>>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ `std::cell::UnsafeCell<isize>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
+   |
+   = help: within `std::cell::RefCell<i32>`, the trait `std::panic::RefUnwindSafe` is not implemented for `std::cell::UnsafeCell<isize>`
+   = note: required because it appears within the type `std::cell::Cell<isize>`
+   = note: required because it appears within the type `std::cell::RefCell<i32>`
+   = note: required because of the requirements on the impl of `std::panic::UnwindSafe` for `std::rc::Rc<std::cell::RefCell<i32>>`
+note: required by `assert`
+  --> $DIR/not-panic-safe-2.rs:7:1
+   |
+LL | fn assert<T: UnwindSafe + ?Sized>() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/not-panic/not-panic-safe-3.rs b/src/test/ui/not-panic/not-panic-safe-3.rs
new file mode 100644
index 0000000..b0ba378
--- /dev/null
+++ b/src/test/ui/not-panic/not-panic-safe-3.rs
@@ -0,0 +1,13 @@
+#![allow(dead_code)]
+
+use std::panic::UnwindSafe;
+use std::sync::Arc;
+use std::cell::RefCell;
+
+fn assert<T: UnwindSafe + ?Sized>() {}
+
+fn main() {
+    assert::<Arc<RefCell<i32>>>();
+    //~^ ERROR the type `std::cell::UnsafeCell<i32>` may contain interior mutability and a
+    //~| ERROR the type `std::cell::UnsafeCell<isize>` may contain interior mutability and a
+}
diff --git a/src/test/ui/not-panic/not-panic-safe-3.stderr b/src/test/ui/not-panic/not-panic-safe-3.stderr
new file mode 100644
index 0000000..1f87f20
--- /dev/null
+++ b/src/test/ui/not-panic/not-panic-safe-3.stderr
@@ -0,0 +1,34 @@
+error[E0277]: the type `std::cell::UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
+  --> $DIR/not-panic-safe-3.rs:10:5
+   |
+LL |     assert::<Arc<RefCell<i32>>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `std::cell::UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
+   |
+   = help: within `std::cell::RefCell<i32>`, the trait `std::panic::RefUnwindSafe` is not implemented for `std::cell::UnsafeCell<i32>`
+   = note: required because it appears within the type `std::cell::RefCell<i32>`
+   = note: required because of the requirements on the impl of `std::panic::UnwindSafe` for `std::sync::Arc<std::cell::RefCell<i32>>`
+note: required by `assert`
+  --> $DIR/not-panic-safe-3.rs:7:1
+   |
+LL | fn assert<T: UnwindSafe + ?Sized>() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the type `std::cell::UnsafeCell<isize>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
+  --> $DIR/not-panic-safe-3.rs:10:5
+   |
+LL |     assert::<Arc<RefCell<i32>>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `std::cell::UnsafeCell<isize>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
+   |
+   = help: within `std::cell::RefCell<i32>`, the trait `std::panic::RefUnwindSafe` is not implemented for `std::cell::UnsafeCell<isize>`
+   = note: required because it appears within the type `std::cell::Cell<isize>`
+   = note: required because it appears within the type `std::cell::RefCell<i32>`
+   = note: required because of the requirements on the impl of `std::panic::UnwindSafe` for `std::sync::Arc<std::cell::RefCell<i32>>`
+note: required by `assert`
+  --> $DIR/not-panic-safe-3.rs:7:1
+   |
+LL | fn assert<T: UnwindSafe + ?Sized>() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/not-panic/not-panic-safe-4.rs b/src/test/ui/not-panic/not-panic-safe-4.rs
new file mode 100644
index 0000000..ed27605
--- /dev/null
+++ b/src/test/ui/not-panic/not-panic-safe-4.rs
@@ -0,0 +1,12 @@
+#![allow(dead_code)]
+
+use std::panic::UnwindSafe;
+use std::cell::RefCell;
+
+fn assert<T: UnwindSafe + ?Sized>() {}
+
+fn main() {
+    assert::<&RefCell<i32>>();
+    //~^ ERROR the type `std::cell::UnsafeCell<i32>` may contain interior mutability and a
+    //~| ERROR the type `std::cell::UnsafeCell<isize>` may contain interior mutability and a
+}
diff --git a/src/test/ui/not-panic/not-panic-safe-4.stderr b/src/test/ui/not-panic/not-panic-safe-4.stderr
new file mode 100644
index 0000000..24f6490
--- /dev/null
+++ b/src/test/ui/not-panic/not-panic-safe-4.stderr
@@ -0,0 +1,34 @@
+error[E0277]: the type `std::cell::UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
+  --> $DIR/not-panic-safe-4.rs:9:5
+   |
+LL |     assert::<&RefCell<i32>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ `std::cell::UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
+   |
+   = help: within `std::cell::RefCell<i32>`, the trait `std::panic::RefUnwindSafe` is not implemented for `std::cell::UnsafeCell<i32>`
+   = note: required because it appears within the type `std::cell::RefCell<i32>`
+   = note: required because of the requirements on the impl of `std::panic::UnwindSafe` for `&std::cell::RefCell<i32>`
+note: required by `assert`
+  --> $DIR/not-panic-safe-4.rs:6:1
+   |
+LL | fn assert<T: UnwindSafe + ?Sized>() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the type `std::cell::UnsafeCell<isize>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
+  --> $DIR/not-panic-safe-4.rs:9:5
+   |
+LL |     assert::<&RefCell<i32>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ `std::cell::UnsafeCell<isize>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
+   |
+   = help: within `std::cell::RefCell<i32>`, the trait `std::panic::RefUnwindSafe` is not implemented for `std::cell::UnsafeCell<isize>`
+   = note: required because it appears within the type `std::cell::Cell<isize>`
+   = note: required because it appears within the type `std::cell::RefCell<i32>`
+   = note: required because of the requirements on the impl of `std::panic::UnwindSafe` for `&std::cell::RefCell<i32>`
+note: required by `assert`
+  --> $DIR/not-panic-safe-4.rs:6:1
+   |
+LL | fn assert<T: UnwindSafe + ?Sized>() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/not-panic/not-panic-safe-5.rs b/src/test/ui/not-panic/not-panic-safe-5.rs
new file mode 100644
index 0000000..e0d3751
--- /dev/null
+++ b/src/test/ui/not-panic/not-panic-safe-5.rs
@@ -0,0 +1,10 @@
+#![allow(dead_code)]
+
+use std::panic::UnwindSafe;
+use std::cell::UnsafeCell;
+
+fn assert<T: UnwindSafe + ?Sized>() {}
+
+fn main() {
+    assert::<*const UnsafeCell<i32>>(); //~ ERROR E0277
+}
diff --git a/src/test/ui/not-panic/not-panic-safe-5.stderr b/src/test/ui/not-panic/not-panic-safe-5.stderr
new file mode 100644
index 0000000..a603acb
--- /dev/null
+++ b/src/test/ui/not-panic/not-panic-safe-5.stderr
@@ -0,0 +1,17 @@
+error[E0277]: the type `std::cell::UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
+  --> $DIR/not-panic-safe-5.rs:9:5
+   |
+LL |     assert::<*const UnsafeCell<i32>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `std::cell::UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
+   |
+   = help: the trait `std::panic::RefUnwindSafe` is not implemented for `std::cell::UnsafeCell<i32>`
+   = note: required because of the requirements on the impl of `std::panic::UnwindSafe` for `*const std::cell::UnsafeCell<i32>`
+note: required by `assert`
+  --> $DIR/not-panic-safe-5.rs:6:1
+   |
+LL | fn assert<T: UnwindSafe + ?Sized>() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/not-panic/not-panic-safe-6.rs b/src/test/ui/not-panic/not-panic-safe-6.rs
new file mode 100644
index 0000000..a42e337
--- /dev/null
+++ b/src/test/ui/not-panic/not-panic-safe-6.rs
@@ -0,0 +1,12 @@
+#![allow(dead_code)]
+
+use std::panic::UnwindSafe;
+use std::cell::RefCell;
+
+fn assert<T: UnwindSafe + ?Sized>() {}
+
+fn main() {
+    assert::<*mut RefCell<i32>>();
+    //~^ ERROR the type `std::cell::UnsafeCell<i32>` may contain interior mutability and a
+    //~| ERROR the type `std::cell::UnsafeCell<isize>` may contain interior mutability and a
+}
diff --git a/src/test/ui/not-panic/not-panic-safe-6.stderr b/src/test/ui/not-panic/not-panic-safe-6.stderr
new file mode 100644
index 0000000..a4c75ec
--- /dev/null
+++ b/src/test/ui/not-panic/not-panic-safe-6.stderr
@@ -0,0 +1,34 @@
+error[E0277]: the type `std::cell::UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
+  --> $DIR/not-panic-safe-6.rs:9:5
+   |
+LL |     assert::<*mut RefCell<i32>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `std::cell::UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
+   |
+   = help: within `std::cell::RefCell<i32>`, the trait `std::panic::RefUnwindSafe` is not implemented for `std::cell::UnsafeCell<i32>`
+   = note: required because it appears within the type `std::cell::RefCell<i32>`
+   = note: required because of the requirements on the impl of `std::panic::UnwindSafe` for `*mut std::cell::RefCell<i32>`
+note: required by `assert`
+  --> $DIR/not-panic-safe-6.rs:6:1
+   |
+LL | fn assert<T: UnwindSafe + ?Sized>() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the type `std::cell::UnsafeCell<isize>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
+  --> $DIR/not-panic-safe-6.rs:9:5
+   |
+LL |     assert::<*mut RefCell<i32>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `std::cell::UnsafeCell<isize>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
+   |
+   = help: within `std::cell::RefCell<i32>`, the trait `std::panic::RefUnwindSafe` is not implemented for `std::cell::UnsafeCell<isize>`
+   = note: required because it appears within the type `std::cell::Cell<isize>`
+   = note: required because it appears within the type `std::cell::RefCell<i32>`
+   = note: required because of the requirements on the impl of `std::panic::UnwindSafe` for `*mut std::cell::RefCell<i32>`
+note: required by `assert`
+  --> $DIR/not-panic-safe-6.rs:6:1
+   |
+LL | fn assert<T: UnwindSafe + ?Sized>() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/not-panic/not-panic-safe.rs b/src/test/ui/not-panic/not-panic-safe.rs
new file mode 100644
index 0000000..93a8506
--- /dev/null
+++ b/src/test/ui/not-panic/not-panic-safe.rs
@@ -0,0 +1,11 @@
+#![allow(dead_code)]
+#![feature(recover)]
+
+use std::panic::UnwindSafe;
+
+fn assert<T: UnwindSafe + ?Sized>() {}
+
+fn main() {
+    assert::<&mut i32>();
+    //~^ ERROR the type `&mut i32` may not be safely transferred across an unwind boundary
+}
diff --git a/src/test/ui/not-panic/not-panic-safe.stderr b/src/test/ui/not-panic/not-panic-safe.stderr
new file mode 100644
index 0000000..2d12e69
--- /dev/null
+++ b/src/test/ui/not-panic/not-panic-safe.stderr
@@ -0,0 +1,16 @@
+error[E0277]: the type `&mut i32` may not be safely transferred across an unwind boundary
+  --> $DIR/not-panic-safe.rs:9:5
+   |
+LL |     assert::<&mut i32>();
+   |     ^^^^^^^^^^^^^^^^^^ `&mut i32` may not be safely transferred across an unwind boundary
+   |
+   = help: the trait `std::panic::UnwindSafe` is not implemented for `&mut i32`
+note: required by `assert`
+  --> $DIR/not-panic-safe.rs:6:1
+   |
+LL | fn assert<T: UnwindSafe + ?Sized>() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/not-sync.rs b/src/test/ui/not-sync.rs
new file mode 100644
index 0000000..70ba1fc5
--- /dev/null
+++ b/src/test/ui/not-sync.rs
@@ -0,0 +1,22 @@
+use std::cell::{Cell, RefCell};
+use std::rc::{Rc, Weak};
+use std::sync::mpsc::{Receiver, Sender};
+
+fn test<T: Sync>() {}
+
+fn main() {
+    test::<Cell<i32>>();
+    //~^ ERROR `std::cell::Cell<i32>` cannot be shared between threads safely [E0277]
+    test::<RefCell<i32>>();
+    //~^ ERROR `std::cell::RefCell<i32>` cannot be shared between threads safely [E0277]
+
+    test::<Rc<i32>>();
+    //~^ ERROR `std::rc::Rc<i32>` cannot be shared between threads safely [E0277]
+    test::<Weak<i32>>();
+    //~^ ERROR `std::rc::Weak<i32>` cannot be shared between threads safely [E0277]
+
+    test::<Receiver<i32>>();
+    //~^ ERROR `std::sync::mpsc::Receiver<i32>` cannot be shared between threads safely [E0277]
+    test::<Sender<i32>>();
+    //~^ ERROR `std::sync::mpsc::Sender<i32>` cannot be shared between threads safely [E0277]
+}
diff --git a/src/test/ui/not-sync.stderr b/src/test/ui/not-sync.stderr
new file mode 100644
index 0000000..d102528
--- /dev/null
+++ b/src/test/ui/not-sync.stderr
@@ -0,0 +1,81 @@
+error[E0277]: `std::cell::Cell<i32>` cannot be shared between threads safely
+  --> $DIR/not-sync.rs:8:5
+   |
+LL |     test::<Cell<i32>>();
+   |     ^^^^^^^^^^^^^^^^^ `std::cell::Cell<i32>` cannot be shared between threads safely
+   |
+   = help: the trait `std::marker::Sync` is not implemented for `std::cell::Cell<i32>`
+note: required by `test`
+  --> $DIR/not-sync.rs:5:1
+   |
+LL | fn test<T: Sync>() {}
+   | ^^^^^^^^^^^^^^^^^^
+
+error[E0277]: `std::cell::RefCell<i32>` cannot be shared between threads safely
+  --> $DIR/not-sync.rs:10:5
+   |
+LL |     test::<RefCell<i32>>();
+   |     ^^^^^^^^^^^^^^^^^^^^ `std::cell::RefCell<i32>` cannot be shared between threads safely
+   |
+   = help: the trait `std::marker::Sync` is not implemented for `std::cell::RefCell<i32>`
+note: required by `test`
+  --> $DIR/not-sync.rs:5:1
+   |
+LL | fn test<T: Sync>() {}
+   | ^^^^^^^^^^^^^^^^^^
+
+error[E0277]: `std::rc::Rc<i32>` cannot be shared between threads safely
+  --> $DIR/not-sync.rs:13:5
+   |
+LL |     test::<Rc<i32>>();
+   |     ^^^^^^^^^^^^^^^ `std::rc::Rc<i32>` cannot be shared between threads safely
+   |
+   = help: the trait `std::marker::Sync` is not implemented for `std::rc::Rc<i32>`
+note: required by `test`
+  --> $DIR/not-sync.rs:5:1
+   |
+LL | fn test<T: Sync>() {}
+   | ^^^^^^^^^^^^^^^^^^
+
+error[E0277]: `std::rc::Weak<i32>` cannot be shared between threads safely
+  --> $DIR/not-sync.rs:15:5
+   |
+LL |     test::<Weak<i32>>();
+   |     ^^^^^^^^^^^^^^^^^ `std::rc::Weak<i32>` cannot be shared between threads safely
+   |
+   = help: the trait `std::marker::Sync` is not implemented for `std::rc::Weak<i32>`
+note: required by `test`
+  --> $DIR/not-sync.rs:5:1
+   |
+LL | fn test<T: Sync>() {}
+   | ^^^^^^^^^^^^^^^^^^
+
+error[E0277]: `std::sync::mpsc::Receiver<i32>` cannot be shared between threads safely
+  --> $DIR/not-sync.rs:18:5
+   |
+LL |     test::<Receiver<i32>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^ `std::sync::mpsc::Receiver<i32>` cannot be shared between threads safely
+   |
+   = help: the trait `std::marker::Sync` is not implemented for `std::sync::mpsc::Receiver<i32>`
+note: required by `test`
+  --> $DIR/not-sync.rs:5:1
+   |
+LL | fn test<T: Sync>() {}
+   | ^^^^^^^^^^^^^^^^^^
+
+error[E0277]: `std::sync::mpsc::Sender<i32>` cannot be shared between threads safely
+  --> $DIR/not-sync.rs:20:5
+   |
+LL |     test::<Sender<i32>>();
+   |     ^^^^^^^^^^^^^^^^^^^ `std::sync::mpsc::Sender<i32>` cannot be shared between threads safely
+   |
+   = help: the trait `std::marker::Sync` is not implemented for `std::sync::mpsc::Sender<i32>`
+note: required by `test`
+  --> $DIR/not-sync.rs:5:1
+   |
+LL | fn test<T: Sync>() {}
+   | ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/numeric/numeric-cast-2.rs b/src/test/ui/numeric/numeric-cast-2.rs
new file mode 100644
index 0000000..ad2de5d
--- /dev/null
+++ b/src/test/ui/numeric/numeric-cast-2.rs
@@ -0,0 +1,11 @@
+fn foo() -> i32 {
+    4
+}
+fn main() {
+    let x: u16 = foo();
+    //~^ ERROR mismatched types
+    let y: i64 = x + x;
+    //~^ ERROR mismatched types
+    let z: i32 = x + x;
+    //~^ ERROR mismatched types
+}
diff --git a/src/test/ui/numeric/numeric-cast-2.stderr b/src/test/ui/numeric/numeric-cast-2.stderr
new file mode 100644
index 0000000..79088f0
--- /dev/null
+++ b/src/test/ui/numeric/numeric-cast-2.stderr
@@ -0,0 +1,21 @@
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-2.rs:5:18
+   |
+LL |     let x: u16 = foo();
+   |                  ^^^^^ expected u16, found i32
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-2.rs:7:18
+   |
+LL |     let y: i64 = x + x;
+   |                  ^^^^^ expected i64, found u16
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-2.rs:9:18
+   |
+LL |     let z: i32 = x + x;
+   |                  ^^^^^ expected i32, found u16
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/numeric/numeric-cast.rs b/src/test/ui/numeric/numeric-cast.rs
new file mode 100644
index 0000000..39378c2
--- /dev/null
+++ b/src/test/ui/numeric/numeric-cast.rs
@@ -0,0 +1,309 @@
+fn foo<N>(_x: N) {}
+
+fn main() {
+    let x_usize: usize = 1;
+    let x_u64: u64 = 2;
+    let x_u32: u32 = 3;
+    let x_u16: u16 = 4;
+    let x_u8: u8 = 5;
+    let x_isize: isize = 6;
+    let x_i64: i64 = 7;
+    let x_i32: i32 = 8;
+    let x_i16: i16 = 9;
+    let x_i8: i8 = 10;
+    let x_f64: f64 = 11.0;
+    let x_f32: f32 = 12.0;
+
+    foo::<usize>(x_usize);
+    foo::<usize>(x_u64);
+    //~^ ERROR mismatched types
+    foo::<usize>(x_u32);
+    //~^ ERROR mismatched types
+    foo::<usize>(x_u16);
+    //~^ ERROR mismatched types
+    foo::<usize>(x_u8);
+    //~^ ERROR mismatched types
+    foo::<usize>(x_isize);
+    //~^ ERROR mismatched types
+    foo::<usize>(x_i64);
+    //~^ ERROR mismatched types
+    foo::<usize>(x_i32);
+    //~^ ERROR mismatched types
+    foo::<usize>(x_i16);
+    //~^ ERROR mismatched types
+    foo::<usize>(x_i8);
+    //~^ ERROR mismatched types
+    foo::<usize>(x_f64);
+    //~^ ERROR mismatched types
+    foo::<usize>(x_f32);
+    //~^ ERROR mismatched types
+
+    foo::<isize>(x_usize);
+    //~^ ERROR mismatched types
+    foo::<isize>(x_u64);
+    //~^ ERROR mismatched types
+    foo::<isize>(x_u32);
+    //~^ ERROR mismatched types
+    foo::<isize>(x_u16);
+    //~^ ERROR mismatched types
+    foo::<isize>(x_u8);
+    //~^ ERROR mismatched types
+    foo::<isize>(x_isize);
+    foo::<isize>(x_i64);
+    //~^ ERROR mismatched types
+    foo::<isize>(x_i32);
+    //~^ ERROR mismatched types
+    foo::<isize>(x_i16);
+    //~^ ERROR mismatched types
+    foo::<isize>(x_i8);
+    //~^ ERROR mismatched types
+    foo::<isize>(x_f64);
+    //~^ ERROR mismatched types
+    foo::<isize>(x_f32);
+    //~^ ERROR mismatched types
+
+    foo::<u64>(x_usize);
+    //~^ ERROR mismatched types
+    foo::<u64>(x_u64);
+    foo::<u64>(x_u32);
+    //~^ ERROR mismatched types
+    foo::<u64>(x_u16);
+    //~^ ERROR mismatched types
+    foo::<u64>(x_u8);
+    //~^ ERROR mismatched types
+    foo::<u64>(x_isize);
+    //~^ ERROR mismatched types
+    foo::<u64>(x_i64);
+    //~^ ERROR mismatched types
+    foo::<u64>(x_i32);
+    //~^ ERROR mismatched types
+    foo::<u64>(x_i16);
+    //~^ ERROR mismatched types
+    foo::<u64>(x_i8);
+    //~^ ERROR mismatched types
+    foo::<u64>(x_f64);
+    //~^ ERROR mismatched types
+    foo::<u64>(x_f32);
+    //~^ ERROR mismatched types
+
+    foo::<i64>(x_usize);
+    //~^ ERROR mismatched types
+    foo::<i64>(x_u64);
+    //~^ ERROR mismatched types
+    foo::<i64>(x_u32);
+    //~^ ERROR mismatched types
+    foo::<i64>(x_u16);
+    //~^ ERROR mismatched types
+    foo::<i64>(x_u8);
+    //~^ ERROR mismatched types
+    foo::<i64>(x_isize);
+    //~^ ERROR mismatched types
+    foo::<i64>(x_i64);
+    foo::<i64>(x_i32);
+    //~^ ERROR mismatched types
+    foo::<i64>(x_i16);
+    //~^ ERROR mismatched types
+    foo::<i64>(x_i8);
+    //~^ ERROR mismatched types
+    foo::<i64>(x_f64);
+    //~^ ERROR mismatched types
+    foo::<i64>(x_f32);
+    //~^ ERROR mismatched types
+
+    foo::<u32>(x_usize);
+    //~^ ERROR mismatched types
+    foo::<u32>(x_u64);
+    //~^ ERROR mismatched types
+    foo::<u32>(x_u32);
+    foo::<u32>(x_u16);
+    //~^ ERROR mismatched types
+    foo::<u32>(x_u8);
+    //~^ ERROR mismatched types
+    foo::<u32>(x_isize);
+    //~^ ERROR mismatched types
+    foo::<u32>(x_i64);
+    //~^ ERROR mismatched types
+    foo::<u32>(x_i32);
+    //~^ ERROR mismatched types
+    foo::<u32>(x_i16);
+    //~^ ERROR mismatched types
+    foo::<u32>(x_i8);
+    //~^ ERROR mismatched types
+    foo::<u32>(x_f64);
+    //~^ ERROR mismatched types
+    foo::<u32>(x_f32);
+    //~^ ERROR mismatched types
+
+    foo::<i32>(x_usize);
+    //~^ ERROR mismatched types
+    foo::<i32>(x_u64);
+    //~^ ERROR mismatched types
+    foo::<i32>(x_u32);
+    //~^ ERROR mismatched types
+    foo::<i32>(x_u16);
+    //~^ ERROR mismatched types
+    foo::<i32>(x_u8);
+    //~^ ERROR mismatched types
+    foo::<i32>(x_isize);
+    //~^ ERROR mismatched types
+    foo::<i32>(x_i64);
+    //~^ ERROR mismatched types
+    foo::<i32>(x_i32);
+    foo::<i32>(x_i16);
+    //~^ ERROR mismatched types
+    foo::<i32>(x_i8);
+    //~^ ERROR mismatched types
+    foo::<i32>(x_f64);
+    //~^ ERROR mismatched types
+    foo::<i32>(x_f32);
+    //~^ ERROR mismatched types
+
+    foo::<u16>(x_usize);
+    //~^ ERROR mismatched types
+    foo::<u16>(x_u64);
+    //~^ ERROR mismatched types
+    foo::<u16>(x_u32);
+    //~^ ERROR mismatched types
+    foo::<u16>(x_u16);
+    foo::<u16>(x_u8);
+    //~^ ERROR mismatched types
+    foo::<u16>(x_isize);
+    //~^ ERROR mismatched types
+    foo::<u16>(x_i64);
+    //~^ ERROR mismatched types
+    foo::<u16>(x_i32);
+    //~^ ERROR mismatched types
+    foo::<u16>(x_i16);
+    //~^ ERROR mismatched types
+    foo::<u16>(x_i8);
+    //~^ ERROR mismatched types
+    foo::<u16>(x_f64);
+    //~^ ERROR mismatched types
+    foo::<u16>(x_f32);
+    //~^ ERROR mismatched types
+
+    foo::<i16>(x_usize);
+    //~^ ERROR mismatched types
+    foo::<i16>(x_u64);
+    //~^ ERROR mismatched types
+    foo::<i16>(x_u32);
+    //~^ ERROR mismatched types
+    foo::<i16>(x_u16);
+    //~^ ERROR mismatched types
+    foo::<i16>(x_u8);
+    //~^ ERROR mismatched types
+    foo::<i16>(x_isize);
+    //~^ ERROR mismatched types
+    foo::<i16>(x_i64);
+    //~^ ERROR mismatched types
+    foo::<i16>(x_i32);
+    //~^ ERROR mismatched types
+    foo::<i16>(x_i16);
+    foo::<i16>(x_i8);
+    //~^ ERROR mismatched types
+    foo::<i16>(x_f64);
+    //~^ ERROR mismatched types
+    foo::<i16>(x_f32);
+    //~^ ERROR mismatched types
+
+    foo::<u8>(x_usize);
+    //~^ ERROR mismatched types
+    foo::<u8>(x_u64);
+    //~^ ERROR mismatched types
+    foo::<u8>(x_u32);
+    //~^ ERROR mismatched types
+    foo::<u8>(x_u16);
+    //~^ ERROR mismatched types
+    foo::<u8>(x_u8);
+    foo::<u8>(x_isize);
+    //~^ ERROR mismatched types
+    foo::<u8>(x_i64);
+    //~^ ERROR mismatched types
+    foo::<u8>(x_i32);
+    //~^ ERROR mismatched types
+    foo::<u8>(x_i16);
+    //~^ ERROR mismatched types
+    foo::<u8>(x_i8);
+    //~^ ERROR mismatched types
+    foo::<u8>(x_f64);
+    //~^ ERROR mismatched types
+    foo::<u8>(x_f32);
+    //~^ ERROR mismatched types
+
+    foo::<i8>(x_usize);
+    //~^ ERROR mismatched types
+    foo::<i8>(x_u64);
+    //~^ ERROR mismatched types
+    foo::<i8>(x_u32);
+    //~^ ERROR mismatched types
+    foo::<i8>(x_u16);
+    //~^ ERROR mismatched types
+    foo::<i8>(x_u8);
+    //~^ ERROR mismatched types
+    foo::<i8>(x_isize);
+    //~^ ERROR mismatched types
+    foo::<i8>(x_i64);
+    //~^ ERROR mismatched types
+    foo::<i8>(x_i32);
+    //~^ ERROR mismatched types
+    foo::<i8>(x_i16);
+    //~^ ERROR mismatched types
+    foo::<i8>(x_i8);
+    foo::<i8>(x_f64);
+    //~^ ERROR mismatched types
+    foo::<i8>(x_f32);
+    //~^ ERROR mismatched types
+
+    foo::<f64>(x_usize);
+    //~^ ERROR mismatched types
+    foo::<f64>(x_u64);
+    //~^ ERROR mismatched types
+    foo::<f64>(x_u32);
+    //~^ ERROR mismatched types
+    foo::<f64>(x_u16);
+    //~^ ERROR mismatched types
+    foo::<f64>(x_u8);
+    //~^ ERROR mismatched types
+    foo::<f64>(x_isize);
+    //~^ ERROR mismatched types
+    foo::<f64>(x_i64);
+    //~^ ERROR mismatched types
+    foo::<f64>(x_i32);
+    //~^ ERROR mismatched types
+    foo::<f64>(x_i16);
+    //~^ ERROR mismatched types
+    foo::<f64>(x_i8);
+    //~^ ERROR mismatched types
+    foo::<f64>(x_f64);
+    foo::<f64>(x_f32);
+    //~^ ERROR mismatched types
+
+    foo::<f32>(x_usize);
+    //~^ ERROR mismatched types
+    foo::<f32>(x_u64);
+    //~^ ERROR mismatched types
+    foo::<f32>(x_u32);
+    //~^ ERROR mismatched types
+    foo::<f32>(x_u16);
+    //~^ ERROR mismatched types
+    foo::<f32>(x_u8);
+    //~^ ERROR mismatched types
+    foo::<f32>(x_isize);
+    //~^ ERROR mismatched types
+    foo::<f32>(x_i64);
+    //~^ ERROR mismatched types
+    foo::<f32>(x_i32);
+    //~^ ERROR mismatched types
+    foo::<f32>(x_i16);
+    //~^ ERROR mismatched types
+    foo::<f32>(x_i8);
+    //~^ ERROR mismatched types
+    foo::<f32>(x_f64);
+    //~^ ERROR mismatched types
+    foo::<f32>(x_f32);
+
+    foo::<u32>(x_u8 as u16);
+    //~^ ERROR mismatched types
+    foo::<i32>(-x_i8);
+    //~^ ERROR mismatched types
+}
diff --git a/src/test/ui/numeric/numeric-cast.stderr b/src/test/ui/numeric/numeric-cast.stderr
new file mode 100644
index 0000000..2c4f6e2
--- /dev/null
+++ b/src/test/ui/numeric/numeric-cast.stderr
@@ -0,0 +1,907 @@
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:18:18
+   |
+LL |     foo::<usize>(x_u64);
+   |                  ^^^^^ expected usize, found u64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:20:18
+   |
+LL |     foo::<usize>(x_u32);
+   |                  ^^^^^ expected usize, found u32
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:22:18
+   |
+LL |     foo::<usize>(x_u16);
+   |                  ^^^^^ expected usize, found u16
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:24:18
+   |
+LL |     foo::<usize>(x_u8);
+   |                  ^^^^ expected usize, found u8
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:26:18
+   |
+LL |     foo::<usize>(x_isize);
+   |                  ^^^^^^^ expected usize, found isize
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:28:18
+   |
+LL |     foo::<usize>(x_i64);
+   |                  ^^^^^ expected usize, found i64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:30:18
+   |
+LL |     foo::<usize>(x_i32);
+   |                  ^^^^^ expected usize, found i32
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:32:18
+   |
+LL |     foo::<usize>(x_i16);
+   |                  ^^^^^ expected usize, found i16
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:34:18
+   |
+LL |     foo::<usize>(x_i8);
+   |                  ^^^^ expected usize, found i8
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:36:18
+   |
+LL |     foo::<usize>(x_f64);
+   |                  ^^^^^ expected usize, found f64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:38:18
+   |
+LL |     foo::<usize>(x_f32);
+   |                  ^^^^^ expected usize, found f32
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:41:18
+   |
+LL |     foo::<isize>(x_usize);
+   |                  ^^^^^^^ expected isize, found usize
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:43:18
+   |
+LL |     foo::<isize>(x_u64);
+   |                  ^^^^^ expected isize, found u64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:45:18
+   |
+LL |     foo::<isize>(x_u32);
+   |                  ^^^^^ expected isize, found u32
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:47:18
+   |
+LL |     foo::<isize>(x_u16);
+   |                  ^^^^^ expected isize, found u16
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:49:18
+   |
+LL |     foo::<isize>(x_u8);
+   |                  ^^^^ expected isize, found u8
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:52:18
+   |
+LL |     foo::<isize>(x_i64);
+   |                  ^^^^^ expected isize, found i64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:54:18
+   |
+LL |     foo::<isize>(x_i32);
+   |                  ^^^^^ expected isize, found i32
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:56:18
+   |
+LL |     foo::<isize>(x_i16);
+   |                  ^^^^^ expected isize, found i16
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:58:18
+   |
+LL |     foo::<isize>(x_i8);
+   |                  ^^^^ expected isize, found i8
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:60:18
+   |
+LL |     foo::<isize>(x_f64);
+   |                  ^^^^^ expected isize, found f64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:62:18
+   |
+LL |     foo::<isize>(x_f32);
+   |                  ^^^^^ expected isize, found f32
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:65:16
+   |
+LL |     foo::<u64>(x_usize);
+   |                ^^^^^^^ expected u64, found usize
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:68:16
+   |
+LL |     foo::<u64>(x_u32);
+   |                ^^^^^ expected u64, found u32
+help: you can cast an `u32` to `u64`, which will zero-extend the source value
+   |
+LL |     foo::<u64>(x_u32.into());
+   |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:70:16
+   |
+LL |     foo::<u64>(x_u16);
+   |                ^^^^^ expected u64, found u16
+help: you can cast an `u16` to `u64`, which will zero-extend the source value
+   |
+LL |     foo::<u64>(x_u16.into());
+   |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:72:16
+   |
+LL |     foo::<u64>(x_u8);
+   |                ^^^^ expected u64, found u8
+help: you can cast an `u8` to `u64`, which will zero-extend the source value
+   |
+LL |     foo::<u64>(x_u8.into());
+   |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:74:16
+   |
+LL |     foo::<u64>(x_isize);
+   |                ^^^^^^^ expected u64, found isize
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:76:16
+   |
+LL |     foo::<u64>(x_i64);
+   |                ^^^^^ expected u64, found i64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:78:16
+   |
+LL |     foo::<u64>(x_i32);
+   |                ^^^^^ expected u64, found i32
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:80:16
+   |
+LL |     foo::<u64>(x_i16);
+   |                ^^^^^ expected u64, found i16
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:82:16
+   |
+LL |     foo::<u64>(x_i8);
+   |                ^^^^ expected u64, found i8
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:84:16
+   |
+LL |     foo::<u64>(x_f64);
+   |                ^^^^^ expected u64, found f64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:86:16
+   |
+LL |     foo::<u64>(x_f32);
+   |                ^^^^^ expected u64, found f32
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:89:16
+   |
+LL |     foo::<i64>(x_usize);
+   |                ^^^^^^^ expected i64, found usize
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:91:16
+   |
+LL |     foo::<i64>(x_u64);
+   |                ^^^^^ expected i64, found u64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:93:16
+   |
+LL |     foo::<i64>(x_u32);
+   |                ^^^^^ expected i64, found u32
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:95:16
+   |
+LL |     foo::<i64>(x_u16);
+   |                ^^^^^ expected i64, found u16
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:97:16
+   |
+LL |     foo::<i64>(x_u8);
+   |                ^^^^ expected i64, found u8
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:99:16
+   |
+LL |     foo::<i64>(x_isize);
+   |                ^^^^^^^ expected i64, found isize
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:102:16
+   |
+LL |     foo::<i64>(x_i32);
+   |                ^^^^^ expected i64, found i32
+help: you can cast an `i32` to `i64`, which will sign-extend the source value
+   |
+LL |     foo::<i64>(x_i32.into());
+   |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:104:16
+   |
+LL |     foo::<i64>(x_i16);
+   |                ^^^^^ expected i64, found i16
+help: you can cast an `i16` to `i64`, which will sign-extend the source value
+   |
+LL |     foo::<i64>(x_i16.into());
+   |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:106:16
+   |
+LL |     foo::<i64>(x_i8);
+   |                ^^^^ expected i64, found i8
+help: you can cast an `i8` to `i64`, which will sign-extend the source value
+   |
+LL |     foo::<i64>(x_i8.into());
+   |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:108:16
+   |
+LL |     foo::<i64>(x_f64);
+   |                ^^^^^ expected i64, found f64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:110:16
+   |
+LL |     foo::<i64>(x_f32);
+   |                ^^^^^ expected i64, found f32
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:113:16
+   |
+LL |     foo::<u32>(x_usize);
+   |                ^^^^^^^ expected u32, found usize
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:115:16
+   |
+LL |     foo::<u32>(x_u64);
+   |                ^^^^^ expected u32, found u64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:118:16
+   |
+LL |     foo::<u32>(x_u16);
+   |                ^^^^^ expected u32, found u16
+help: you can cast an `u16` to `u32`, which will zero-extend the source value
+   |
+LL |     foo::<u32>(x_u16.into());
+   |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:120:16
+   |
+LL |     foo::<u32>(x_u8);
+   |                ^^^^ expected u32, found u8
+help: you can cast an `u8` to `u32`, which will zero-extend the source value
+   |
+LL |     foo::<u32>(x_u8.into());
+   |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:122:16
+   |
+LL |     foo::<u32>(x_isize);
+   |                ^^^^^^^ expected u32, found isize
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:124:16
+   |
+LL |     foo::<u32>(x_i64);
+   |                ^^^^^ expected u32, found i64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:126:16
+   |
+LL |     foo::<u32>(x_i32);
+   |                ^^^^^ expected u32, found i32
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:128:16
+   |
+LL |     foo::<u32>(x_i16);
+   |                ^^^^^ expected u32, found i16
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:130:16
+   |
+LL |     foo::<u32>(x_i8);
+   |                ^^^^ expected u32, found i8
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:132:16
+   |
+LL |     foo::<u32>(x_f64);
+   |                ^^^^^ expected u32, found f64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:134:16
+   |
+LL |     foo::<u32>(x_f32);
+   |                ^^^^^ expected u32, found f32
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:137:16
+   |
+LL |     foo::<i32>(x_usize);
+   |                ^^^^^^^ expected i32, found usize
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:139:16
+   |
+LL |     foo::<i32>(x_u64);
+   |                ^^^^^ expected i32, found u64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:141:16
+   |
+LL |     foo::<i32>(x_u32);
+   |                ^^^^^ expected i32, found u32
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:143:16
+   |
+LL |     foo::<i32>(x_u16);
+   |                ^^^^^ expected i32, found u16
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:145:16
+   |
+LL |     foo::<i32>(x_u8);
+   |                ^^^^ expected i32, found u8
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:147:16
+   |
+LL |     foo::<i32>(x_isize);
+   |                ^^^^^^^ expected i32, found isize
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:149:16
+   |
+LL |     foo::<i32>(x_i64);
+   |                ^^^^^ expected i32, found i64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:152:16
+   |
+LL |     foo::<i32>(x_i16);
+   |                ^^^^^ expected i32, found i16
+help: you can cast an `i16` to `i32`, which will sign-extend the source value
+   |
+LL |     foo::<i32>(x_i16.into());
+   |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:154:16
+   |
+LL |     foo::<i32>(x_i8);
+   |                ^^^^ expected i32, found i8
+help: you can cast an `i8` to `i32`, which will sign-extend the source value
+   |
+LL |     foo::<i32>(x_i8.into());
+   |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:156:16
+   |
+LL |     foo::<i32>(x_f64);
+   |                ^^^^^ expected i32, found f64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:158:16
+   |
+LL |     foo::<i32>(x_f32);
+   |                ^^^^^ expected i32, found f32
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:161:16
+   |
+LL |     foo::<u16>(x_usize);
+   |                ^^^^^^^ expected u16, found usize
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:163:16
+   |
+LL |     foo::<u16>(x_u64);
+   |                ^^^^^ expected u16, found u64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:165:16
+   |
+LL |     foo::<u16>(x_u32);
+   |                ^^^^^ expected u16, found u32
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:168:16
+   |
+LL |     foo::<u16>(x_u8);
+   |                ^^^^ expected u16, found u8
+help: you can cast an `u8` to `u16`, which will zero-extend the source value
+   |
+LL |     foo::<u16>(x_u8.into());
+   |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:170:16
+   |
+LL |     foo::<u16>(x_isize);
+   |                ^^^^^^^ expected u16, found isize
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:172:16
+   |
+LL |     foo::<u16>(x_i64);
+   |                ^^^^^ expected u16, found i64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:174:16
+   |
+LL |     foo::<u16>(x_i32);
+   |                ^^^^^ expected u16, found i32
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:176:16
+   |
+LL |     foo::<u16>(x_i16);
+   |                ^^^^^ expected u16, found i16
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:178:16
+   |
+LL |     foo::<u16>(x_i8);
+   |                ^^^^ expected u16, found i8
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:180:16
+   |
+LL |     foo::<u16>(x_f64);
+   |                ^^^^^ expected u16, found f64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:182:16
+   |
+LL |     foo::<u16>(x_f32);
+   |                ^^^^^ expected u16, found f32
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:185:16
+   |
+LL |     foo::<i16>(x_usize);
+   |                ^^^^^^^ expected i16, found usize
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:187:16
+   |
+LL |     foo::<i16>(x_u64);
+   |                ^^^^^ expected i16, found u64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:189:16
+   |
+LL |     foo::<i16>(x_u32);
+   |                ^^^^^ expected i16, found u32
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:191:16
+   |
+LL |     foo::<i16>(x_u16);
+   |                ^^^^^ expected i16, found u16
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:193:16
+   |
+LL |     foo::<i16>(x_u8);
+   |                ^^^^ expected i16, found u8
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:195:16
+   |
+LL |     foo::<i16>(x_isize);
+   |                ^^^^^^^ expected i16, found isize
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:197:16
+   |
+LL |     foo::<i16>(x_i64);
+   |                ^^^^^ expected i16, found i64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:199:16
+   |
+LL |     foo::<i16>(x_i32);
+   |                ^^^^^ expected i16, found i32
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:202:16
+   |
+LL |     foo::<i16>(x_i8);
+   |                ^^^^ expected i16, found i8
+help: you can cast an `i8` to `i16`, which will sign-extend the source value
+   |
+LL |     foo::<i16>(x_i8.into());
+   |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:204:16
+   |
+LL |     foo::<i16>(x_f64);
+   |                ^^^^^ expected i16, found f64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:206:16
+   |
+LL |     foo::<i16>(x_f32);
+   |                ^^^^^ expected i16, found f32
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:209:15
+   |
+LL |     foo::<u8>(x_usize);
+   |               ^^^^^^^ expected u8, found usize
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:211:15
+   |
+LL |     foo::<u8>(x_u64);
+   |               ^^^^^ expected u8, found u64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:213:15
+   |
+LL |     foo::<u8>(x_u32);
+   |               ^^^^^ expected u8, found u32
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:215:15
+   |
+LL |     foo::<u8>(x_u16);
+   |               ^^^^^ expected u8, found u16
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:218:15
+   |
+LL |     foo::<u8>(x_isize);
+   |               ^^^^^^^ expected u8, found isize
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:220:15
+   |
+LL |     foo::<u8>(x_i64);
+   |               ^^^^^ expected u8, found i64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:222:15
+   |
+LL |     foo::<u8>(x_i32);
+   |               ^^^^^ expected u8, found i32
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:224:15
+   |
+LL |     foo::<u8>(x_i16);
+   |               ^^^^^ expected u8, found i16
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:226:15
+   |
+LL |     foo::<u8>(x_i8);
+   |               ^^^^ expected u8, found i8
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:228:15
+   |
+LL |     foo::<u8>(x_f64);
+   |               ^^^^^ expected u8, found f64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:230:15
+   |
+LL |     foo::<u8>(x_f32);
+   |               ^^^^^ expected u8, found f32
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:233:15
+   |
+LL |     foo::<i8>(x_usize);
+   |               ^^^^^^^ expected i8, found usize
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:235:15
+   |
+LL |     foo::<i8>(x_u64);
+   |               ^^^^^ expected i8, found u64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:237:15
+   |
+LL |     foo::<i8>(x_u32);
+   |               ^^^^^ expected i8, found u32
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:239:15
+   |
+LL |     foo::<i8>(x_u16);
+   |               ^^^^^ expected i8, found u16
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:241:15
+   |
+LL |     foo::<i8>(x_u8);
+   |               ^^^^ expected i8, found u8
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:243:15
+   |
+LL |     foo::<i8>(x_isize);
+   |               ^^^^^^^ expected i8, found isize
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:245:15
+   |
+LL |     foo::<i8>(x_i64);
+   |               ^^^^^ expected i8, found i64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:247:15
+   |
+LL |     foo::<i8>(x_i32);
+   |               ^^^^^ expected i8, found i32
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:249:15
+   |
+LL |     foo::<i8>(x_i16);
+   |               ^^^^^ expected i8, found i16
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:252:15
+   |
+LL |     foo::<i8>(x_f64);
+   |               ^^^^^ expected i8, found f64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:254:15
+   |
+LL |     foo::<i8>(x_f32);
+   |               ^^^^^ expected i8, found f32
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:257:16
+   |
+LL |     foo::<f64>(x_usize);
+   |                ^^^^^^^ expected f64, found usize
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:259:16
+   |
+LL |     foo::<f64>(x_u64);
+   |                ^^^^^ expected f64, found u64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:261:16
+   |
+LL |     foo::<f64>(x_u32);
+   |                ^^^^^ expected f64, found u32
+help: you can cast an `u32` to `f64`, producing the floating point representation of the integer
+   |
+LL |     foo::<f64>(x_u32.into());
+   |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:263:16
+   |
+LL |     foo::<f64>(x_u16);
+   |                ^^^^^ expected f64, found u16
+help: you can cast an `u16` to `f64`, producing the floating point representation of the integer
+   |
+LL |     foo::<f64>(x_u16.into());
+   |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:265:16
+   |
+LL |     foo::<f64>(x_u8);
+   |                ^^^^ expected f64, found u8
+help: you can cast an `u8` to `f64`, producing the floating point representation of the integer
+   |
+LL |     foo::<f64>(x_u8.into());
+   |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:267:16
+   |
+LL |     foo::<f64>(x_isize);
+   |                ^^^^^^^ expected f64, found isize
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:269:16
+   |
+LL |     foo::<f64>(x_i64);
+   |                ^^^^^ expected f64, found i64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:271:16
+   |
+LL |     foo::<f64>(x_i32);
+   |                ^^^^^ expected f64, found i32
+help: you can cast an `i32` to `f64`, producing the floating point representation of the integer
+   |
+LL |     foo::<f64>(x_i32.into());
+   |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:273:16
+   |
+LL |     foo::<f64>(x_i16);
+   |                ^^^^^ expected f64, found i16
+help: you can cast an `i16` to `f64`, producing the floating point representation of the integer
+   |
+LL |     foo::<f64>(x_i16.into());
+   |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:275:16
+   |
+LL |     foo::<f64>(x_i8);
+   |                ^^^^ expected f64, found i8
+help: you can cast an `i8` to `f64`, producing the floating point representation of the integer
+   |
+LL |     foo::<f64>(x_i8.into());
+   |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:278:16
+   |
+LL |     foo::<f64>(x_f32);
+   |                ^^^^^ expected f64, found f32
+help: you can cast an `f32` to `f64` in a lossless way
+   |
+LL |     foo::<f64>(x_f32.into());
+   |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:281:16
+   |
+LL |     foo::<f32>(x_usize);
+   |                ^^^^^^^ expected f32, found usize
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:283:16
+   |
+LL |     foo::<f32>(x_u64);
+   |                ^^^^^ expected f32, found u64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:285:16
+   |
+LL |     foo::<f32>(x_u32);
+   |                ^^^^^ expected f32, found u32
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:287:16
+   |
+LL |     foo::<f32>(x_u16);
+   |                ^^^^^ expected f32, found u16
+help: you can cast an `u16` to `f32`, producing the floating point representation of the integer
+   |
+LL |     foo::<f32>(x_u16.into());
+   |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:289:16
+   |
+LL |     foo::<f32>(x_u8);
+   |                ^^^^ expected f32, found u8
+help: you can cast an `u8` to `f32`, producing the floating point representation of the integer
+   |
+LL |     foo::<f32>(x_u8.into());
+   |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:291:16
+   |
+LL |     foo::<f32>(x_isize);
+   |                ^^^^^^^ expected f32, found isize
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:293:16
+   |
+LL |     foo::<f32>(x_i64);
+   |                ^^^^^ expected f32, found i64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:295:16
+   |
+LL |     foo::<f32>(x_i32);
+   |                ^^^^^ expected f32, found i32
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:297:16
+   |
+LL |     foo::<f32>(x_i16);
+   |                ^^^^^ expected f32, found i16
+help: you can cast an `i16` to `f32`, producing the floating point representation of the integer
+   |
+LL |     foo::<f32>(x_i16.into());
+   |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:299:16
+   |
+LL |     foo::<f32>(x_i8);
+   |                ^^^^ expected f32, found i8
+help: you can cast an `i8` to `f32`, producing the floating point representation of the integer
+   |
+LL |     foo::<f32>(x_i8.into());
+   |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:301:16
+   |
+LL |     foo::<f32>(x_f64);
+   |                ^^^^^ expected f32, found f64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:305:16
+   |
+LL |     foo::<u32>(x_u8 as u16);
+   |                ^^^^^^^^^^^ expected u32, found u16
+help: you can cast an `u16` to `u32`, which will zero-extend the source value
+   |
+LL |     foo::<u32>((x_u8 as u16).into());
+   |                ^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:307:16
+   |
+LL |     foo::<i32>(-x_i8);
+   |                ^^^^^ expected i32, found i8
+help: you can cast an `i8` to `i32`, which will sign-extend the source value
+   |
+LL |     foo::<i32>((-x_i8).into());
+   |                ^^^^^^^^^^^^^^
+
+error: aborting due to 134 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/numeric/numeric-fields.rs b/src/test/ui/numeric/numeric-fields.rs
new file mode 100644
index 0000000..28234bb
--- /dev/null
+++ b/src/test/ui/numeric/numeric-fields.rs
@@ -0,0 +1,10 @@
+struct S(u8, u16);
+
+fn main() {
+    let s = S{0b1: 10, 0: 11};
+    //~^ ERROR struct `S` has no field named `0b1`
+    match s {
+        S{0: a, 0x1: b, ..} => {}
+        //~^ ERROR does not have a field named `0x1`
+    }
+}
diff --git a/src/test/ui/numeric/numeric-fields.stderr b/src/test/ui/numeric/numeric-fields.stderr
new file mode 100644
index 0000000..ce51bba
--- /dev/null
+++ b/src/test/ui/numeric/numeric-fields.stderr
@@ -0,0 +1,18 @@
+error[E0560]: struct `S` has no field named `0b1`
+  --> $DIR/numeric-fields.rs:4:15
+   |
+LL |     let s = S{0b1: 10, 0: 11};
+   |               ^^^ `S` does not have this field
+   |
+   = note: available fields are: `0`, `1`
+
+error[E0026]: struct `S` does not have a field named `0x1`
+  --> $DIR/numeric-fields.rs:7:17
+   |
+LL |         S{0: a, 0x1: b, ..} => {}
+   |                 ^^^ struct `S` does not have this field
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0026, E0560.
+For more information about an error, try `rustc --explain E0026`.
diff --git a/src/test/ui/object-does-not-impl-trait.rs b/src/test/ui/object-does-not-impl-trait.rs
new file mode 100644
index 0000000..2d72b45
--- /dev/null
+++ b/src/test/ui/object-does-not-impl-trait.rs
@@ -0,0 +1,8 @@
+// Test that an object type `Box<Foo>` is not considered to implement the
+// trait `Foo`. Issue #5087.
+
+trait Foo {}
+fn take_foo<F:Foo>(f: F) {}
+fn take_object(f: Box<Foo>) { take_foo(f); }
+//~^ ERROR `std::boxed::Box<dyn Foo>: Foo` is not satisfied
+fn main() {}
diff --git a/src/test/ui/object-does-not-impl-trait.stderr b/src/test/ui/object-does-not-impl-trait.stderr
new file mode 100644
index 0000000..0e28875
--- /dev/null
+++ b/src/test/ui/object-does-not-impl-trait.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `std::boxed::Box<dyn Foo>: Foo` is not satisfied
+  --> $DIR/object-does-not-impl-trait.rs:6:31
+   |
+LL | fn take_object(f: Box<Foo>) { take_foo(f); }
+   |                               ^^^^^^^^ the trait `Foo` is not implemented for `std::boxed::Box<dyn Foo>`
+   |
+note: required by `take_foo`
+  --> $DIR/object-does-not-impl-trait.rs:5:1
+   |
+LL | fn take_foo<F:Foo>(f: F) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/object-lifetime/object-lifetime-default-ambiguous.rs b/src/test/ui/object-lifetime/object-lifetime-default-ambiguous.rs
new file mode 100644
index 0000000..d14351a
--- /dev/null
+++ b/src/test/ui/object-lifetime/object-lifetime-default-ambiguous.rs
@@ -0,0 +1,48 @@
+// Test that if a struct declares multiple region bounds for a given
+// type parameter, an explicit lifetime bound is required on object
+// lifetimes within.
+
+#![allow(dead_code)]
+
+trait Test {
+    fn foo(&self) { }
+}
+
+struct Ref0<T:?Sized> {
+    r: *mut T
+}
+
+struct Ref1<'a,T:'a+?Sized> {
+    r: &'a T
+}
+
+struct Ref2<'a,'b:'a,T:'a+'b+?Sized> {
+    r: &'a &'b T
+}
+
+fn a<'a,'b>(t: Ref2<'a,'b,Test>) {
+    //~^ ERROR lifetime bound for this object type cannot be deduced from context
+}
+
+fn b(t: Ref2<Test>) {
+    //~^ ERROR lifetime bound for this object type cannot be deduced from context
+}
+
+fn c(t: Ref2<&Test>) {
+    // In this case, the &'a overrides.
+}
+
+fn d(t: Ref2<Ref1<Test>>) {
+    // In this case, the lifetime parameter from the Ref1 overrides.
+}
+
+fn e(t: Ref2<Ref0<Test>>) {
+    // In this case, Ref2 is ambiguous, but Ref0 overrides with 'static.
+}
+
+fn f(t: &Ref2<Test>) {
+    //~^ ERROR lifetime bound for this object type cannot be deduced from context
+}
+
+fn main() {
+}
diff --git a/src/test/ui/object-lifetime/object-lifetime-default-ambiguous.stderr b/src/test/ui/object-lifetime/object-lifetime-default-ambiguous.stderr
new file mode 100644
index 0000000..f079803
--- /dev/null
+++ b/src/test/ui/object-lifetime/object-lifetime-default-ambiguous.stderr
@@ -0,0 +1,21 @@
+error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound
+  --> $DIR/object-lifetime-default-ambiguous.rs:23:27
+   |
+LL | fn a<'a,'b>(t: Ref2<'a,'b,Test>) {
+   |                           ^^^^
+
+error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound
+  --> $DIR/object-lifetime-default-ambiguous.rs:27:14
+   |
+LL | fn b(t: Ref2<Test>) {
+   |              ^^^^
+
+error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound
+  --> $DIR/object-lifetime-default-ambiguous.rs:43:15
+   |
+LL | fn f(t: &Ref2<Test>) {
+   |               ^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0228`.
diff --git a/src/test/ui/object-lifetime/object-lifetime-default-elision.rs b/src/test/ui/object-lifetime/object-lifetime-default-elision.rs
new file mode 100644
index 0000000..cf15a4e
--- /dev/null
+++ b/src/test/ui/object-lifetime/object-lifetime-default-elision.rs
@@ -0,0 +1,77 @@
+// Test various cases where the old rules under lifetime elision
+// yield slightly different results than the new rules.
+
+#![allow(dead_code)]
+
+trait SomeTrait {
+    fn dummy(&self) { }
+}
+
+struct SomeStruct<'a> {
+    r: Box<SomeTrait+'a>
+}
+
+fn deref<T>(ss: &T) -> T {
+    // produces the type of a deref without worrying about whether a
+    // move out would actually be legal
+    loop { }
+}
+
+fn load0<'a>(ss: &'a Box<SomeTrait>) -> Box<SomeTrait> {
+    // Under old rules, the fully elaborated types of input/output were:
+    //
+    // for<'a,'b> fn(&'a Box<SomeTrait+'b>) -> Box<SomeTrait+'a>
+    //
+    // Under new rules the result is:
+    //
+    // for<'a> fn(&'a Box<SomeTrait+'static>) -> Box<SomeTrait+'static>
+    //
+    // Therefore, no type error.
+
+    deref(ss)
+}
+
+fn load1(ss: &SomeTrait) -> &SomeTrait {
+    // Under old rules, the fully elaborated types of input/output were:
+    //
+    // for<'a,'b> fn(&'a (SomeTrait+'b)) -> &'a (SomeTrait+'a)
+    //
+    // Under new rules the result is:
+    //
+    // for<'a> fn(&'a (SomeTrait+'a)) -> &'a (SomeTrait+'a)
+    //
+    // In both cases, returning `ss` is legal.
+
+    ss
+}
+
+fn load2<'a>(ss: &'a SomeTrait) -> &SomeTrait {
+    // Same as `load1` but with an explicit name thrown in for fun.
+
+    ss
+}
+
+fn load3<'a,'b>(ss: &'a SomeTrait) -> &'b SomeTrait {
+    // Under old rules, the fully elaborated types of input/output were:
+    //
+    // for<'a,'b,'c>fn(&'a (SomeTrait+'c)) -> &'b (SomeTrait+'a)
+    //
+    // Based on the input/output types, the compiler could infer that
+    //     'c : 'a
+    //     'b : 'a
+    // must hold, and therefore it permitted `&'a (Sometrait+'c)` to be
+    // coerced to `&'b (SomeTrait+'a)`.
+    //
+    // Under the newer defaults, though, we get:
+    //
+    // for<'a,'b> fn(&'a (SomeTrait+'a)) -> &'b (SomeTrait+'b)
+    //
+    // which fails to type check.
+
+    ss
+        //~^ ERROR cannot infer
+        //~| ERROR cannot infer
+}
+
+fn main() {
+}
diff --git a/src/test/ui/object-lifetime/object-lifetime-default-elision.stderr b/src/test/ui/object-lifetime/object-lifetime-default-elision.stderr
new file mode 100644
index 0000000..ed734c2
--- /dev/null
+++ b/src/test/ui/object-lifetime/object-lifetime-default-elision.stderr
@@ -0,0 +1,53 @@
+error[E0495]: cannot infer an appropriate lifetime for automatic coercion due to conflicting requirements
+  --> $DIR/object-lifetime-default-elision.rs:71:5
+   |
+LL |     ss
+   |     ^^
+   |
+note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 54:10...
+  --> $DIR/object-lifetime-default-elision.rs:54:10
+   |
+LL | fn load3<'a,'b>(ss: &'a SomeTrait) -> &'b SomeTrait {
+   |          ^^
+note: ...so that reference does not outlive borrowed content
+  --> $DIR/object-lifetime-default-elision.rs:71:5
+   |
+LL |     ss
+   |     ^^
+note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 54:13...
+  --> $DIR/object-lifetime-default-elision.rs:54:13
+   |
+LL | fn load3<'a,'b>(ss: &'a SomeTrait) -> &'b SomeTrait {
+   |             ^^
+   = note: ...so that the expression is assignable:
+           expected &'b (dyn SomeTrait + 'b)
+              found &dyn SomeTrait
+
+error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
+  --> $DIR/object-lifetime-default-elision.rs:71:5
+   |
+LL |     ss
+   |     ^^
+   |
+note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 54:10...
+  --> $DIR/object-lifetime-default-elision.rs:54:10
+   |
+LL | fn load3<'a,'b>(ss: &'a SomeTrait) -> &'b SomeTrait {
+   |          ^^
+note: ...so that the declared lifetime parameter bounds are satisfied
+  --> $DIR/object-lifetime-default-elision.rs:71:5
+   |
+LL |     ss
+   |     ^^
+note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 54:13...
+  --> $DIR/object-lifetime-default-elision.rs:54:13
+   |
+LL | fn load3<'a,'b>(ss: &'a SomeTrait) -> &'b SomeTrait {
+   |             ^^
+   = note: ...so that the expression is assignable:
+           expected &'b (dyn SomeTrait + 'b)
+              found &dyn SomeTrait
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0495`.
diff --git a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.rs b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.rs
new file mode 100644
index 0000000..b6d72f1
--- /dev/null
+++ b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.rs
@@ -0,0 +1,35 @@
+// Test various cases where the defaults should lead to errors being
+// reported.
+
+#![allow(dead_code)]
+
+trait SomeTrait {
+    fn dummy(&self) { }
+}
+
+struct SomeStruct<'a> {
+    r: Box<SomeTrait+'a>
+}
+
+fn load(ss: &mut SomeStruct) -> Box<SomeTrait> {
+    // `Box<SomeTrait>` defaults to a `'static` bound, so this return
+    // is illegal.
+
+    ss.r //~ ERROR explicit lifetime required in the type of `ss` [E0621]
+}
+
+fn store(ss: &mut SomeStruct, b: Box<SomeTrait>) {
+    // No error: b is bounded by 'static which outlives the
+    // (anonymous) lifetime on the struct.
+
+    ss.r = b;
+}
+
+fn store1<'b>(ss: &mut SomeStruct, b: Box<SomeTrait+'b>) {
+    // Here we override the lifetimes explicitly, and so naturally we get an error.
+
+    ss.r = b; //~ ERROR explicit lifetime required in the type of `ss` [E0621]
+}
+
+fn main() {
+}
diff --git a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr
new file mode 100644
index 0000000..0077c95
--- /dev/null
+++ b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr
@@ -0,0 +1,21 @@
+error[E0621]: explicit lifetime required in the type of `ss`
+  --> $DIR/object-lifetime-default-from-box-error.rs:18:5
+   |
+LL | fn load(ss: &mut SomeStruct) -> Box<SomeTrait> {
+   |             --------------- help: add explicit lifetime `'static` to the type of `ss`: `&mut SomeStruct<'static>`
+...
+LL |     ss.r
+   |     ^^^^ lifetime `'static` required
+
+error[E0621]: explicit lifetime required in the type of `ss`
+  --> $DIR/object-lifetime-default-from-box-error.rs:31:12
+   |
+LL | fn store1<'b>(ss: &mut SomeStruct, b: Box<SomeTrait+'b>) {
+   |                   --------------- help: add explicit lifetime `'b` to the type of `ss`: `&mut SomeStruct<'b>`
+...
+LL |     ss.r = b;
+   |            ^ lifetime `'b` required
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.rs b/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.rs
new file mode 100644
index 0000000..91b384e
--- /dev/null
+++ b/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.rs
@@ -0,0 +1,19 @@
+// Test that the lifetime from the enclosing `&` is "inherited"
+// through the `Box` struct.
+
+#![allow(dead_code)]
+
+trait Test {
+    fn foo(&self) { }
+}
+
+struct SomeStruct<'a> {
+    t: &'a Box<Test>,
+}
+
+fn c<'a>(t: &'a Box<Test+'a>, mut ss: SomeStruct<'a>) {
+    ss.t = t; //~ ERROR mismatched types
+}
+
+fn main() {
+}
diff --git a/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.stderr b/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.stderr
new file mode 100644
index 0000000..d7e3a17
--- /dev/null
+++ b/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.stderr
@@ -0,0 +1,18 @@
+error[E0308]: mismatched types
+  --> $DIR/object-lifetime-default-from-rptr-box-error.rs:15:12
+   |
+LL |     ss.t = t;
+   |            ^ lifetime mismatch
+   |
+   = note: expected type `&'a std::boxed::Box<(dyn Test + 'static)>`
+              found type `&'a std::boxed::Box<(dyn Test + 'a)>`
+note: the lifetime 'a as defined on the function body at 14:6...
+  --> $DIR/object-lifetime-default-from-rptr-box-error.rs:14:6
+   |
+LL | fn c<'a>(t: &'a Box<Test+'a>, mut ss: SomeStruct<'a>) {
+   |      ^^
+   = note: ...does not necessarily outlive the static lifetime
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.rs b/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.rs
new file mode 100644
index 0000000..6a84621
--- /dev/null
+++ b/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.rs
@@ -0,0 +1,25 @@
+// Test that the lifetime from the enclosing `&` is "inherited"
+// through the `MyBox` struct.
+
+#![allow(dead_code)]
+#![feature(rustc_error)]
+
+trait Test {
+    fn foo(&self) { }
+}
+
+struct SomeStruct<'a> {
+    t: &'a MyBox<Test>,
+    u: &'a MyBox<Test+'a>,
+}
+
+struct MyBox<T:?Sized> {
+    b: Box<T>
+}
+
+fn c<'a>(t: &'a MyBox<Test+'a>, mut ss: SomeStruct<'a>) {
+    ss.t = t; //~ ERROR mismatched types
+}
+
+fn main() {
+}
diff --git a/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.stderr b/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.stderr
new file mode 100644
index 0000000..4d08253
--- /dev/null
+++ b/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.stderr
@@ -0,0 +1,18 @@
+error[E0308]: mismatched types
+  --> $DIR/object-lifetime-default-from-rptr-struct-error.rs:21:12
+   |
+LL |     ss.t = t;
+   |            ^ lifetime mismatch
+   |
+   = note: expected type `&'a MyBox<(dyn Test + 'static)>`
+              found type `&'a MyBox<(dyn Test + 'a)>`
+note: the lifetime 'a as defined on the function body at 20:6...
+  --> $DIR/object-lifetime-default-from-rptr-struct-error.rs:20:6
+   |
+LL | fn c<'a>(t: &'a MyBox<Test+'a>, mut ss: SomeStruct<'a>) {
+   |      ^^
+   = note: ...does not necessarily outlive the static lifetime
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/object-lifetime/object-lifetime-default-mybox.rs b/src/test/ui/object-lifetime/object-lifetime-default-mybox.rs
new file mode 100644
index 0000000..c94df82
--- /dev/null
+++ b/src/test/ui/object-lifetime/object-lifetime-default-mybox.rs
@@ -0,0 +1,35 @@
+// Test a "pass-through" object-lifetime-default that produces errors.
+
+#![allow(dead_code)]
+
+trait SomeTrait {
+    fn dummy(&self) { }
+}
+
+struct MyBox<T:?Sized> {
+    r: Box<T>
+}
+
+fn deref<T>(ss: &T) -> T {
+    // produces the type of a deref without worrying about whether a
+    // move out would actually be legal
+    loop { }
+}
+
+fn load0(ss: &MyBox<SomeTrait>) -> MyBox<SomeTrait> {
+    deref(ss)
+}
+
+fn load1<'a,'b>(a: &'a MyBox<SomeTrait>,
+                b: &'b MyBox<SomeTrait>)
+                -> &'b MyBox<SomeTrait>
+{
+    a //~ ERROR lifetime mismatch
+}
+
+fn load2<'a>(ss: &MyBox<SomeTrait+'a>) -> MyBox<SomeTrait+'a> {
+    load0(ss) //~ ERROR mismatched types
+}
+
+fn main() {
+}
diff --git a/src/test/ui/object-lifetime/object-lifetime-default-mybox.stderr b/src/test/ui/object-lifetime/object-lifetime-default-mybox.stderr
new file mode 100644
index 0000000..402448c
--- /dev/null
+++ b/src/test/ui/object-lifetime/object-lifetime-default-mybox.stderr
@@ -0,0 +1,31 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/object-lifetime-default-mybox.rs:27:5
+   |
+LL | fn load1<'a,'b>(a: &'a MyBox<SomeTrait>,
+   |                    -------------------- this parameter and the return type are declared with different lifetimes...
+LL |                 b: &'b MyBox<SomeTrait>)
+LL |                 -> &'b MyBox<SomeTrait>
+   |                    --------------------
+LL | {
+LL |     a
+   |     ^ ...but data from `a` is returned here
+
+error[E0308]: mismatched types
+  --> $DIR/object-lifetime-default-mybox.rs:31:11
+   |
+LL |     load0(ss)
+   |           ^^ lifetime mismatch
+   |
+   = note: expected type `&MyBox<(dyn SomeTrait + 'static)>`
+              found type `&MyBox<(dyn SomeTrait + 'a)>`
+note: the lifetime 'a as defined on the function body at 30:10...
+  --> $DIR/object-lifetime-default-mybox.rs:30:10
+   |
+LL | fn load2<'a>(ss: &MyBox<SomeTrait+'a>) -> MyBox<SomeTrait+'a> {
+   |          ^^
+   = note: ...does not necessarily outlive the static lifetime
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0308, E0623.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/object-lifetime/object-lifetime-default.rs b/src/test/ui/object-lifetime/object-lifetime-default.rs
new file mode 100644
index 0000000..379b92e
--- /dev/null
+++ b/src/test/ui/object-lifetime/object-lifetime-default.rs
@@ -0,0 +1,26 @@
+// ignore-compare-mode-nll
+
+#![feature(rustc_attrs)]
+
+#[rustc_object_lifetime_default]
+struct A<T>(T); //~ ERROR BaseDefault
+
+#[rustc_object_lifetime_default]
+struct B<'a,T>(&'a (), T); //~ ERROR BaseDefault
+
+#[rustc_object_lifetime_default]
+struct C<'a,T:'a>(&'a T); //~ ERROR 'a
+
+#[rustc_object_lifetime_default]
+struct D<'a,'b,T:'a+'b>(&'a T, &'b T); //~ ERROR Ambiguous
+
+#[rustc_object_lifetime_default]
+struct E<'a,'b:'a,T:'b>(&'a T, &'b T); //~ ERROR 'b
+
+#[rustc_object_lifetime_default]
+struct F<'a,'b,T:'a,U:'b>(&'a T, &'b U); //~ ERROR 'a,'b
+
+#[rustc_object_lifetime_default]
+struct G<'a,'b,T:'a,U:'a+'b>(&'a T, &'b U); //~ ERROR 'a,Ambiguous
+
+fn main() { }
diff --git a/src/test/ui/object-lifetime/object-lifetime-default.stderr b/src/test/ui/object-lifetime/object-lifetime-default.stderr
new file mode 100644
index 0000000..2642cdf
--- /dev/null
+++ b/src/test/ui/object-lifetime/object-lifetime-default.stderr
@@ -0,0 +1,44 @@
+error: 'a,Ambiguous
+  --> $DIR/object-lifetime-default.rs:24:1
+   |
+LL | struct G<'a,'b,T:'a,U:'a+'b>(&'a T, &'b U);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: 'a,'b
+  --> $DIR/object-lifetime-default.rs:21:1
+   |
+LL | struct F<'a,'b,T:'a,U:'b>(&'a T, &'b U);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: 'b
+  --> $DIR/object-lifetime-default.rs:18:1
+   |
+LL | struct E<'a,'b:'a,T:'b>(&'a T, &'b T);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: Ambiguous
+  --> $DIR/object-lifetime-default.rs:15:1
+   |
+LL | struct D<'a,'b,T:'a+'b>(&'a T, &'b T);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: 'a
+  --> $DIR/object-lifetime-default.rs:12:1
+   |
+LL | struct C<'a,T:'a>(&'a T);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: BaseDefault
+  --> $DIR/object-lifetime-default.rs:9:1
+   |
+LL | struct B<'a,T>(&'a (), T);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: BaseDefault
+  --> $DIR/object-lifetime-default.rs:6:1
+   |
+LL | struct A<T>(T);
+   | ^^^^^^^^^^^^^^^
+
+error: aborting due to 7 previous errors
+
diff --git a/src/test/ui/object-pointer-types.rs b/src/test/ui/object-pointer-types.rs
new file mode 100644
index 0000000..a8a482f
--- /dev/null
+++ b/src/test/ui/object-pointer-types.rs
@@ -0,0 +1,30 @@
+trait Foo {
+    fn borrowed(&self);
+    fn borrowed_mut(&mut self);
+
+    fn owned(self: Box<Self>);
+}
+
+fn borrowed_receiver(x: &Foo) {
+    x.borrowed();
+    x.borrowed_mut(); // See [1]
+    x.owned(); //~ ERROR no method named `owned` found
+}
+
+fn borrowed_mut_receiver(x: &mut Foo) {
+    x.borrowed();
+    x.borrowed_mut();
+    x.owned(); //~ ERROR no method named `owned` found
+}
+
+fn owned_receiver(x: Box<Foo>) {
+    x.borrowed();
+    x.borrowed_mut(); // See [1]
+    x.managed();  //~ ERROR no method named `managed` found
+    x.owned();
+}
+
+fn main() {}
+
+// [1]: These cases are illegal, but the error is not detected
+// until borrowck, so see the test borrowck-object-mutability.rs
diff --git a/src/test/ui/object-pointer-types.stderr b/src/test/ui/object-pointer-types.stderr
new file mode 100644
index 0000000..0c7e4e9
--- /dev/null
+++ b/src/test/ui/object-pointer-types.stderr
@@ -0,0 +1,29 @@
+error[E0599]: no method named `owned` found for type `&dyn Foo` in the current scope
+  --> $DIR/object-pointer-types.rs:11:7
+   |
+LL |     x.owned();
+   |       ^^^^^
+   |
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following trait defines an item `owned`, perhaps you need to implement it:
+           candidate #1: `Foo`
+
+error[E0599]: no method named `owned` found for type `&mut dyn Foo` in the current scope
+  --> $DIR/object-pointer-types.rs:17:7
+   |
+LL |     x.owned();
+   |       ^^^^^
+   |
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following trait defines an item `owned`, perhaps you need to implement it:
+           candidate #1: `Foo`
+
+error[E0599]: no method named `managed` found for type `std::boxed::Box<(dyn Foo + 'static)>` in the current scope
+  --> $DIR/object-pointer-types.rs:23:7
+   |
+LL |     x.managed();
+   |       ^^^^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/object-safety/object-safety-associated-consts.rs b/src/test/ui/object-safety/object-safety-associated-consts.rs
new file mode 100644
index 0000000..79b7e54
--- /dev/null
+++ b/src/test/ui/object-safety/object-safety-associated-consts.rs
@@ -0,0 +1,15 @@
+// Check that we correctly prevent users from making trait objects
+// from traits with associated consts.
+
+
+trait Bar {
+    const X: usize;
+}
+
+fn make_bar<T:Bar>(t: &T) -> &Bar {
+    //~^ ERROR E0038
+    t
+}
+
+fn main() {
+}
diff --git a/src/test/ui/object-safety/object-safety-associated-consts.stderr b/src/test/ui/object-safety/object-safety-associated-consts.stderr
new file mode 100644
index 0000000..96962c1
--- /dev/null
+++ b/src/test/ui/object-safety/object-safety-associated-consts.stderr
@@ -0,0 +1,11 @@
+error[E0038]: the trait `Bar` cannot be made into an object
+  --> $DIR/object-safety-associated-consts.rs:9:1
+   |
+LL | fn make_bar<T:Bar>(t: &T) -> &Bar {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object
+   |
+   = note: the trait cannot contain associated consts like `X`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/object-safety/object-safety-by-value-self-use.nll.stderr b/src/test/ui/object-safety/object-safety-by-value-self-use.nll.stderr
new file mode 100644
index 0000000..1497aa4
--- /dev/null
+++ b/src/test/ui/object-safety/object-safety-by-value-self-use.nll.stderr
@@ -0,0 +1,9 @@
+error[E0161]: cannot move a value of type dyn Bar: the size of dyn Bar cannot be statically determined
+  --> $DIR/object-safety-by-value-self-use.rs:15:5
+   |
+LL |     t.bar()
+   |     ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0161`.
diff --git a/src/test/ui/object-safety/object-safety-by-value-self-use.rs b/src/test/ui/object-safety/object-safety-by-value-self-use.rs
new file mode 100644
index 0000000..dc8ea64
--- /dev/null
+++ b/src/test/ui/object-safety/object-safety-by-value-self-use.rs
@@ -0,0 +1,18 @@
+// Check that while a trait with by-value self is object-safe, we
+// can't actually invoke it from an object (yet...?).
+
+#![feature(rustc_attrs)]
+
+trait Bar {
+    fn bar(self);
+}
+
+trait Baz {
+    fn baz(self: Self);
+}
+
+fn use_bar(t: Box<Bar>) {
+    t.bar() //~ ERROR cannot move a value of type (dyn Bar + 'static)
+}
+
+fn main() { }
diff --git a/src/test/ui/object-safety/object-safety-by-value-self-use.stderr b/src/test/ui/object-safety/object-safety-by-value-self-use.stderr
new file mode 100644
index 0000000..0ab8816
--- /dev/null
+++ b/src/test/ui/object-safety/object-safety-by-value-self-use.stderr
@@ -0,0 +1,9 @@
+error[E0161]: cannot move a value of type (dyn Bar + 'static): the size of (dyn Bar + 'static) cannot be statically determined
+  --> $DIR/object-safety-by-value-self-use.rs:15:5
+   |
+LL |     t.bar()
+   |     ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0161`.
diff --git a/src/test/ui/object-safety/object-safety-by-value-self.rs b/src/test/ui/object-safety/object-safety-by-value-self.rs
new file mode 100644
index 0000000..dee31f6
--- /dev/null
+++ b/src/test/ui/object-safety/object-safety-by-value-self.rs
@@ -0,0 +1,46 @@
+// Check that a trait with by-value self is considered object-safe.
+
+// compile-pass
+#![allow(dead_code)]
+#![allow(trivial_casts)]
+
+trait Bar {
+    fn bar(self);
+}
+
+trait Baz {
+    fn baz(self: Self);
+}
+
+trait Quux {
+    // Legal because of the where clause:
+    fn baz(self: Self) where Self : Sized;
+}
+
+fn make_bar<T:Bar>(t: &T) -> &Bar {
+    t // legal
+}
+
+fn make_bar_explicit<T:Bar>(t: &T) -> &Bar {
+    t as &Bar // legal
+}
+
+fn make_baz<T:Baz>(t: &T) -> &Baz {
+    t // legal
+}
+
+fn make_baz_explicit<T:Baz>(t: &T) -> &Baz {
+    t as &Baz // legal
+}
+
+fn make_quux<T:Quux>(t: &T) -> &Quux {
+    t
+}
+
+fn make_quux_explicit<T:Quux>(t: &T) -> &Quux {
+    t as &Quux
+}
+
+
+fn main() {
+}
diff --git a/src/test/ui/object-safety/object-safety-generics.rs b/src/test/ui/object-safety/object-safety-generics.rs
new file mode 100644
index 0000000..5f4aabf
--- /dev/null
+++ b/src/test/ui/object-safety/object-safety-generics.rs
@@ -0,0 +1,33 @@
+// Check that we correctly prevent users from making trait objects
+// from traits with generic methods, unless `where Self : Sized` is
+// present.
+
+trait Bar {
+    fn bar<T>(&self, t: T);
+}
+
+trait Quux {
+    fn bar<T>(&self, t: T)
+        where Self : Sized;
+}
+
+fn make_bar<T:Bar>(t: &T) -> &Bar {
+        //~^ ERROR E0038
+    t
+}
+
+fn make_bar_explicit<T:Bar>(t: &T) -> &Bar {
+    //~^ ERROR E0038
+    t as &Bar
+}
+
+fn make_quux<T:Quux>(t: &T) -> &Quux {
+    t
+}
+
+fn make_quux_explicit<T:Quux>(t: &T) -> &Quux {
+    t as &Quux
+}
+
+fn main() {
+}
diff --git a/src/test/ui/object-safety/object-safety-generics.stderr b/src/test/ui/object-safety/object-safety-generics.stderr
new file mode 100644
index 0000000..7ae4479
--- /dev/null
+++ b/src/test/ui/object-safety/object-safety-generics.stderr
@@ -0,0 +1,19 @@
+error[E0038]: the trait `Bar` cannot be made into an object
+  --> $DIR/object-safety-generics.rs:14:1
+   |
+LL | fn make_bar<T:Bar>(t: &T) -> &Bar {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object
+   |
+   = note: method `bar` has generic type parameters
+
+error[E0038]: the trait `Bar` cannot be made into an object
+  --> $DIR/object-safety-generics.rs:19:1
+   |
+LL | fn make_bar_explicit<T:Bar>(t: &T) -> &Bar {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object
+   |
+   = note: method `bar` has generic type parameters
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/object-safety/object-safety-issue-22040.rs b/src/test/ui/object-safety/object-safety-issue-22040.rs
new file mode 100644
index 0000000..eb28fcf
--- /dev/null
+++ b/src/test/ui/object-safety/object-safety-issue-22040.rs
@@ -0,0 +1,42 @@
+// Regression test for #22040.
+
+use std::fmt::Debug;
+
+trait Expr: Debug + PartialEq {
+    fn print_element_count(&self);
+}
+
+//#[derive(PartialEq)]
+#[derive(Debug)]
+struct SExpr<'x> {
+    elements: Vec<Box<Expr+ 'x>>,
+    //~^ ERROR E0038
+}
+
+impl<'x> PartialEq for SExpr<'x> {
+    fn eq(&self, other:&SExpr<'x>) -> bool {
+        println!("L1: {} L2: {}", self.elements.len(), other.elements.len());
+
+        let result = self.elements.len() == other.elements.len();
+
+        println!("Got compare {}", result);
+        return result;
+    }
+}
+
+impl <'x> SExpr<'x> {
+    fn new() -> SExpr<'x> { return SExpr{elements: Vec::new(),}; }
+}
+
+impl <'x> Expr for SExpr<'x> {
+    fn print_element_count(&self) {
+        println!("element count: {}", self.elements.len());
+    }
+}
+
+fn main() {
+    let a: Box<Expr> = Box::new(SExpr::new());
+    let b: Box<Expr> = Box::new(SExpr::new());
+
+    // assert_eq!(a , b);
+}
diff --git a/src/test/ui/object-safety/object-safety-issue-22040.stderr b/src/test/ui/object-safety/object-safety-issue-22040.stderr
new file mode 100644
index 0000000..85721f1a
--- /dev/null
+++ b/src/test/ui/object-safety/object-safety-issue-22040.stderr
@@ -0,0 +1,11 @@
+error[E0038]: the trait `Expr` cannot be made into an object
+  --> $DIR/object-safety-issue-22040.rs:12:23
+   |
+LL |     elements: Vec<Box<Expr+ 'x>>,
+   |                       ^^^^^^^^ the trait `Expr` cannot be made into an object
+   |
+   = note: the trait cannot use `Self` as a type parameter in the supertraits or where-clauses
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/object-safety/object-safety-mentions-Self.rs b/src/test/ui/object-safety/object-safety-mentions-Self.rs
new file mode 100644
index 0000000..8e1bd83
--- /dev/null
+++ b/src/test/ui/object-safety/object-safety-mentions-Self.rs
@@ -0,0 +1,36 @@
+// Check that we correctly prevent users from making trait objects
+// form traits that make use of `Self` in an argument or return
+// position, unless `where Self : Sized` is present..
+
+trait Bar {
+    fn bar(&self, x: &Self);
+}
+
+trait Baz {
+    fn bar(&self) -> Self;
+}
+
+trait Quux {
+    fn get(&self, s: &Self) -> Self where Self : Sized;
+}
+
+fn make_bar<T:Bar>(t: &T) -> &Bar {
+        //~^ ERROR E0038
+    loop { }
+}
+
+fn make_baz<T:Baz>(t: &T) -> &Baz {
+        //~^ ERROR E0038
+    t
+}
+
+fn make_quux<T:Quux>(t: &T) -> &Quux {
+    t
+}
+
+fn make_quux_explicit<T:Quux>(t: &T) -> &Quux {
+    t as &Quux
+}
+
+fn main() {
+}
diff --git a/src/test/ui/object-safety/object-safety-mentions-Self.stderr b/src/test/ui/object-safety/object-safety-mentions-Self.stderr
new file mode 100644
index 0000000..ed3aed9
--- /dev/null
+++ b/src/test/ui/object-safety/object-safety-mentions-Self.stderr
@@ -0,0 +1,19 @@
+error[E0038]: the trait `Bar` cannot be made into an object
+  --> $DIR/object-safety-mentions-Self.rs:17:1
+   |
+LL | fn make_bar<T:Bar>(t: &T) -> &Bar {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object
+   |
+   = note: method `bar` references the `Self` type in its arguments or return type
+
+error[E0038]: the trait `Baz` cannot be made into an object
+  --> $DIR/object-safety-mentions-Self.rs:22:1
+   |
+LL | fn make_baz<T:Baz>(t: &T) -> &Baz {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Baz` cannot be made into an object
+   |
+   = note: method `bar` references the `Self` type in its arguments or return type
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/object-safety/object-safety-no-static.rs b/src/test/ui/object-safety/object-safety-no-static.rs
new file mode 100644
index 0000000..4faf938
--- /dev/null
+++ b/src/test/ui/object-safety/object-safety-no-static.rs
@@ -0,0 +1,14 @@
+// Check that we correctly prevent users from making trait objects
+// from traits with static methods.
+
+trait Foo {
+    fn foo();
+}
+
+fn foo_implicit<T:Foo+'static>(b: Box<T>) -> Box<Foo+'static> {
+    //~^ ERROR E0038
+    loop { }
+}
+
+fn main() {
+}
diff --git a/src/test/ui/object-safety/object-safety-no-static.stderr b/src/test/ui/object-safety/object-safety-no-static.stderr
new file mode 100644
index 0000000..3b8ccb5
--- /dev/null
+++ b/src/test/ui/object-safety/object-safety-no-static.stderr
@@ -0,0 +1,11 @@
+error[E0038]: the trait `Foo` cannot be made into an object
+  --> $DIR/object-safety-no-static.rs:8:1
+   |
+LL | fn foo_implicit<T:Foo+'static>(b: Box<T>) -> Box<Foo+'static> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object
+   |
+   = note: method `foo` has no receiver
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/object-safety/object-safety-phantom-fn.rs b/src/test/ui/object-safety/object-safety-phantom-fn.rs
new file mode 100644
index 0000000..f8875e4
--- /dev/null
+++ b/src/test/ui/object-safety/object-safety-phantom-fn.rs
@@ -0,0 +1,22 @@
+// Check that `Self` appearing in a phantom fn does not make a trait not object safe.
+
+// compile-pass
+#![allow(dead_code)]
+
+trait Baz {
+}
+
+trait Bar<T> {
+}
+
+fn make_bar<T:Bar<u32>>(t: &T) -> &Bar<u32> {
+    t
+}
+
+fn make_baz<T:Baz>(t: &T) -> &Baz {
+    t
+}
+
+
+fn main() {
+}
diff --git a/src/test/ui/object-safety/object-safety-sized-2.rs b/src/test/ui/object-safety/object-safety-sized-2.rs
new file mode 100644
index 0000000..baeb373
--- /dev/null
+++ b/src/test/ui/object-safety/object-safety-sized-2.rs
@@ -0,0 +1,16 @@
+// Check that we correctly prevent users from making trait objects
+// from traits where `Self : Sized`.
+
+trait Bar
+    where Self : Sized
+{
+    fn bar<T>(&self, t: T);
+}
+
+fn make_bar<T:Bar>(t: &T) -> &Bar {
+        //~^ ERROR E0038
+    loop { }
+}
+
+fn main() {
+}
diff --git a/src/test/ui/object-safety/object-safety-sized-2.stderr b/src/test/ui/object-safety/object-safety-sized-2.stderr
new file mode 100644
index 0000000..2b8bfa3
--- /dev/null
+++ b/src/test/ui/object-safety/object-safety-sized-2.stderr
@@ -0,0 +1,11 @@
+error[E0038]: the trait `Bar` cannot be made into an object
+  --> $DIR/object-safety-sized-2.rs:10:1
+   |
+LL | fn make_bar<T:Bar>(t: &T) -> &Bar {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object
+   |
+   = note: the trait cannot require that `Self : Sized`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/object-safety/object-safety-sized.rs b/src/test/ui/object-safety/object-safety-sized.rs
new file mode 100644
index 0000000..77dc739
--- /dev/null
+++ b/src/test/ui/object-safety/object-safety-sized.rs
@@ -0,0 +1,14 @@
+// Check that we correctly prevent users from making trait objects
+// from traits where `Self : Sized`.
+
+trait Bar : Sized {
+    fn bar<T>(&self, t: T);
+}
+
+fn make_bar<T:Bar>(t: &T) -> &Bar {
+        //~^ ERROR E0038
+    t
+}
+
+fn main() {
+}
diff --git a/src/test/ui/object-safety/object-safety-sized.stderr b/src/test/ui/object-safety/object-safety-sized.stderr
new file mode 100644
index 0000000..ba98e2f
--- /dev/null
+++ b/src/test/ui/object-safety/object-safety-sized.stderr
@@ -0,0 +1,11 @@
+error[E0038]: the trait `Bar` cannot be made into an object
+  --> $DIR/object-safety-sized.rs:8:1
+   |
+LL | fn make_bar<T:Bar>(t: &T) -> &Bar {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object
+   |
+   = note: the trait cannot require that `Self : Sized`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/object-safety/object-safety-supertrait-mentions-Self.rs b/src/test/ui/object-safety/object-safety-supertrait-mentions-Self.rs
new file mode 100644
index 0000000..9d0da4e
--- /dev/null
+++ b/src/test/ui/object-safety/object-safety-supertrait-mentions-Self.rs
@@ -0,0 +1,21 @@
+// Check that we correctly prevent users from making trait objects
+// form traits that make use of `Self` in an argument or return position.
+
+trait Bar<T> {
+    fn bar(&self, x: &T);
+}
+
+trait Baz : Bar<Self> {
+}
+
+fn make_bar<T:Bar<u32>>(t: &T) -> &Bar<u32> {
+    t
+}
+
+fn make_baz<T:Baz>(t: &T) -> &Baz {
+    //~^ ERROR E0038
+    t
+}
+
+fn main() {
+}
diff --git a/src/test/ui/object-safety/object-safety-supertrait-mentions-Self.stderr b/src/test/ui/object-safety/object-safety-supertrait-mentions-Self.stderr
new file mode 100644
index 0000000..5db34a2
--- /dev/null
+++ b/src/test/ui/object-safety/object-safety-supertrait-mentions-Self.stderr
@@ -0,0 +1,11 @@
+error[E0038]: the trait `Baz` cannot be made into an object
+  --> $DIR/object-safety-supertrait-mentions-Self.rs:15:31
+   |
+LL | fn make_baz<T:Baz>(t: &T) -> &Baz {
+   |                               ^^^ the trait `Baz` cannot be made into an object
+   |
+   = note: the trait cannot use `Self` as a type parameter in the supertraits or where-clauses
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/obsolete-in-place/bad.bad.stderr b/src/test/ui/obsolete-in-place/bad.bad.stderr
new file mode 100644
index 0000000..468577a
--- /dev/null
+++ b/src/test/ui/obsolete-in-place/bad.bad.stderr
@@ -0,0 +1,18 @@
+error: emplacement syntax is obsolete (for now, anyway)
+  --> $DIR/bad.rs:9:5
+   |
+LL |     x <- y;
+   |     ^^^^^^
+   |
+   = note: for more information, see <https://github.com/rust-lang/rust/issues/27779#issuecomment-378416911>
+
+error: emplacement syntax is obsolete (for now, anyway)
+  --> $DIR/bad.rs:10:5
+   |
+LL |     in(foo) { bar };
+   |     ^^^^^^^^^^^^^^^
+   |
+   = note: for more information, see <https://github.com/rust-lang/rust/issues/27779#issuecomment-378416911>
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/obsolete-in-place/bad.rs b/src/test/ui/obsolete-in-place/bad.rs
new file mode 100644
index 0000000..f35d297
--- /dev/null
+++ b/src/test/ui/obsolete-in-place/bad.rs
@@ -0,0 +1,15 @@
+// Check that `<-` and `in` syntax gets a hard error.
+
+// revisions: good bad
+//[good] run-pass
+
+#[cfg(bad)]
+fn main() {
+    let (x, y, foo, bar);
+    x <- y; //[bad]~ ERROR emplacement syntax is obsolete
+    in(foo) { bar }; //[bad]~ ERROR emplacement syntax is obsolete
+}
+
+#[cfg(good)]
+fn main() {
+}
diff --git a/src/test/ui/obsolete-syntax-impl-for-dotdot.rs b/src/test/ui/obsolete-syntax-impl-for-dotdot.rs
new file mode 100644
index 0000000..e928f09
--- /dev/null
+++ b/src/test/ui/obsolete-syntax-impl-for-dotdot.rs
@@ -0,0 +1,9 @@
+trait Trait1 {}
+trait Trait2 {}
+
+#[cfg(not_enabled)]
+impl Trait1 for .. {}
+
+impl Trait2 for .. {} //~ ERROR `impl Trait for .. {}` is an obsolete syntax
+
+fn main() {}
diff --git a/src/test/ui/obsolete-syntax-impl-for-dotdot.stderr b/src/test/ui/obsolete-syntax-impl-for-dotdot.stderr
new file mode 100644
index 0000000..b7108ce
--- /dev/null
+++ b/src/test/ui/obsolete-syntax-impl-for-dotdot.stderr
@@ -0,0 +1,10 @@
+error: `impl Trait for .. {}` is an obsolete syntax
+  --> $DIR/obsolete-syntax-impl-for-dotdot.rs:7:1
+   |
+LL | impl Trait2 for .. {}
+   | ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: use `auto trait Trait {}` instead
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/occurs-check-2.rs b/src/test/ui/occurs-check-2.rs
new file mode 100644
index 0000000..213fd26
--- /dev/null
+++ b/src/test/ui/occurs-check-2.rs
@@ -0,0 +1,10 @@
+#![feature(box_syntax)]
+
+fn main() {
+    let f;
+    let g;
+    g = f;
+    f = box g;
+    //~^  ERROR mismatched types
+    //~| cyclic type of infinite size
+}
diff --git a/src/test/ui/occurs-check-2.stderr b/src/test/ui/occurs-check-2.stderr
new file mode 100644
index 0000000..74e29a5
--- /dev/null
+++ b/src/test/ui/occurs-check-2.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/occurs-check-2.rs:7:9
+   |
+LL |     f = box g;
+   |         ^^^^^
+   |         |
+   |         cyclic type of infinite size
+   |         help: try using a conversion method: `box g.to_string()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/occurs-check-3.rs b/src/test/ui/occurs-check-3.rs
new file mode 100644
index 0000000..9c04204
--- /dev/null
+++ b/src/test/ui/occurs-check-3.rs
@@ -0,0 +1,5 @@
+// From Issue #778
+
+enum Clam<T> { A(T) }
+fn main() { let c; c = Clam::A(c); match c { Clam::A::<isize>(_) => { } } }
+//~^ ERROR mismatched types
diff --git a/src/test/ui/occurs-check-3.stderr b/src/test/ui/occurs-check-3.stderr
new file mode 100644
index 0000000..04c404d
--- /dev/null
+++ b/src/test/ui/occurs-check-3.stderr
@@ -0,0 +1,9 @@
+error[E0308]: mismatched types
+  --> $DIR/occurs-check-3.rs:4:24
+   |
+LL | fn main() { let c; c = Clam::A(c); match c { Clam::A::<isize>(_) => { } } }
+   |                        ^^^^^^^^^^ cyclic type of infinite size
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/occurs-check.rs b/src/test/ui/occurs-check.rs
new file mode 100644
index 0000000..5f2c236
--- /dev/null
+++ b/src/test/ui/occurs-check.rs
@@ -0,0 +1,8 @@
+#![feature(box_syntax)]
+
+fn main() {
+    let f;
+    f = box f;
+    //~^ ERROR mismatched types
+    //~| cyclic type of infinite size
+}
diff --git a/src/test/ui/occurs-check.stderr b/src/test/ui/occurs-check.stderr
new file mode 100644
index 0000000..61ce61b
--- /dev/null
+++ b/src/test/ui/occurs-check.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/occurs-check.rs:5:9
+   |
+LL |     f = box f;
+   |         ^^^^^
+   |         |
+   |         cyclic type of infinite size
+   |         help: try using a conversion method: `box f.to_string()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/old-suffixes-are-really-forbidden.rs b/src/test/ui/old-suffixes-are-really-forbidden.rs
new file mode 100644
index 0000000..eea95b7
--- /dev/null
+++ b/src/test/ui/old-suffixes-are-really-forbidden.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let a = 1_is; //~ ERROR invalid suffix
+    let b = 2_us; //~ ERROR invalid suffix
+}
diff --git a/src/test/ui/old-suffixes-are-really-forbidden.stderr b/src/test/ui/old-suffixes-are-really-forbidden.stderr
new file mode 100644
index 0000000..9d1e8d0
--- /dev/null
+++ b/src/test/ui/old-suffixes-are-really-forbidden.stderr
@@ -0,0 +1,18 @@
+error: invalid suffix `is` for numeric literal
+  --> $DIR/old-suffixes-are-really-forbidden.rs:2:13
+   |
+LL |     let a = 1_is;
+   |             ^^^^ invalid suffix `is`
+   |
+   = help: the suffix must be one of the integral types (`u32`, `isize`, etc)
+
+error: invalid suffix `us` for numeric literal
+  --> $DIR/old-suffixes-are-really-forbidden.rs:3:13
+   |
+LL |     let b = 2_us;
+   |             ^^^^ invalid suffix `us`
+   |
+   = help: the suffix must be one of the integral types (`u32`, `isize`, etc)
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/on-unimplemented/auxiliary/no_debug.rs b/src/test/ui/on-unimplemented/auxiliary/no_debug.rs
new file mode 100644
index 0000000..f240d0e
--- /dev/null
+++ b/src/test/ui/on-unimplemented/auxiliary/no_debug.rs
@@ -0,0 +1,5 @@
+// ignore-tidy-linelength
+
+#![crate_type = "lib"]
+
+pub struct Bar;
diff --git a/src/test/ui/on-unimplemented/bad-annotation.rs b/src/test/ui/on-unimplemented/bad-annotation.rs
new file mode 100644
index 0000000..846db63
--- /dev/null
+++ b/src/test/ui/on-unimplemented/bad-annotation.rs
@@ -0,0 +1,64 @@
+// ignore-tidy-linelength
+
+#![feature(on_unimplemented)]
+
+#![allow(unused)]
+
+#[rustc_on_unimplemented = "test error `{Self}` with `{Bar}` `{Baz}` `{Quux}`"]
+trait Foo<Bar, Baz, Quux>
+{}
+
+#[rustc_on_unimplemented="a collection of type `{Self}` cannot be built from an iterator over elements of type `{A}`"]
+trait MyFromIterator<A> {
+    /// Builds a container with elements from an external iterator.
+    fn my_from_iter<T: Iterator<Item=A>>(iterator: T) -> Self;
+}
+
+#[rustc_on_unimplemented]
+//~^ ERROR attribute must be of the form
+trait BadAnnotation1
+{}
+
+#[rustc_on_unimplemented = "Unimplemented trait error on `{Self}` with params `<{A},{B},{C}>`"]
+//~^ ERROR there is no parameter `C` on trait `BadAnnotation2`
+trait BadAnnotation2<A,B>
+{}
+
+#[rustc_on_unimplemented = "Unimplemented trait error on `{Self}` with params `<{A},{B},{}>`"]
+//~^ only named substitution parameters are allowed
+trait BadAnnotation3<A,B>
+{}
+
+#[rustc_on_unimplemented(lorem="")]
+//~^ this attribute must have a valid
+trait BadAnnotation4 {}
+
+#[rustc_on_unimplemented(lorem(ipsum(dolor)))]
+//~^ this attribute must have a valid
+trait BadAnnotation5 {}
+
+#[rustc_on_unimplemented(message="x", message="y")]
+//~^ this attribute must have a valid
+trait BadAnnotation6 {}
+
+#[rustc_on_unimplemented(message="x", on(desugared, message="y"))]
+//~^ this attribute must have a valid
+trait BadAnnotation7 {}
+
+#[rustc_on_unimplemented(on(), message="y")]
+//~^ empty `on`-clause
+trait BadAnnotation8 {}
+
+#[rustc_on_unimplemented(on="x", message="y")]
+//~^ this attribute must have a valid
+trait BadAnnotation9 {}
+
+#[rustc_on_unimplemented(on(x="y"), message="y")]
+trait BadAnnotation10 {}
+
+#[rustc_on_unimplemented(on(desugared, on(desugared, message="x")), message="y")]
+//~^ this attribute must have a valid
+trait BadAnnotation11 {}
+
+pub fn main() {
+}
diff --git a/src/test/ui/on-unimplemented/bad-annotation.stderr b/src/test/ui/on-unimplemented/bad-annotation.stderr
new file mode 100644
index 0000000..31b626e
--- /dev/null
+++ b/src/test/ui/on-unimplemented/bad-annotation.stderr
@@ -0,0 +1,76 @@
+error: attribute must be of the form `#[rustc_on_unimplemented(/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...")]` or `#[rustc_on_unimplemented = "message"]`
+  --> $DIR/bad-annotation.rs:17:1
+   |
+LL | #[rustc_on_unimplemented]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0230]: there is no parameter `C` on trait `BadAnnotation2`
+  --> $DIR/bad-annotation.rs:22:1
+   |
+LL | #[rustc_on_unimplemented = "Unimplemented trait error on `{Self}` with params `<{A},{B},{C}>`"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0231]: only named substitution parameters are allowed
+  --> $DIR/bad-annotation.rs:27:1
+   |
+LL | #[rustc_on_unimplemented = "Unimplemented trait error on `{Self}` with params `<{A},{B},{}>`"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0232]: this attribute must have a valid value
+  --> $DIR/bad-annotation.rs:32:26
+   |
+LL | #[rustc_on_unimplemented(lorem="")]
+   |                          ^^^^^^^^ expected value here
+   |
+   = note: eg `#[rustc_on_unimplemented(message="foo")]`
+
+error[E0232]: this attribute must have a valid value
+  --> $DIR/bad-annotation.rs:36:26
+   |
+LL | #[rustc_on_unimplemented(lorem(ipsum(dolor)))]
+   |                          ^^^^^^^^^^^^^^^^^^^ expected value here
+   |
+   = note: eg `#[rustc_on_unimplemented(message="foo")]`
+
+error[E0232]: this attribute must have a valid value
+  --> $DIR/bad-annotation.rs:40:39
+   |
+LL | #[rustc_on_unimplemented(message="x", message="y")]
+   |                                       ^^^^^^^^^^^ expected value here
+   |
+   = note: eg `#[rustc_on_unimplemented(message="foo")]`
+
+error[E0232]: this attribute must have a valid value
+  --> $DIR/bad-annotation.rs:44:39
+   |
+LL | #[rustc_on_unimplemented(message="x", on(desugared, message="y"))]
+   |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected value here
+   |
+   = note: eg `#[rustc_on_unimplemented(message="foo")]`
+
+error[E0232]: empty `on`-clause in `#[rustc_on_unimplemented]`
+  --> $DIR/bad-annotation.rs:48:26
+   |
+LL | #[rustc_on_unimplemented(on(), message="y")]
+   |                          ^^^^ empty on-clause here
+
+error[E0232]: this attribute must have a valid value
+  --> $DIR/bad-annotation.rs:52:26
+   |
+LL | #[rustc_on_unimplemented(on="x", message="y")]
+   |                          ^^^^^^ expected value here
+   |
+   = note: eg `#[rustc_on_unimplemented(message="foo")]`
+
+error[E0232]: this attribute must have a valid value
+  --> $DIR/bad-annotation.rs:59:40
+   |
+LL | #[rustc_on_unimplemented(on(desugared, on(desugared, message="x")), message="y")]
+   |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected value here
+   |
+   = note: eg `#[rustc_on_unimplemented(message="foo")]`
+
+error: aborting due to 10 previous errors
+
+Some errors occurred: E0230, E0231, E0232.
+For more information about an error, try `rustc --explain E0230`.
diff --git a/src/test/ui/on-unimplemented/expected-comma-found-token.rs b/src/test/ui/on-unimplemented/expected-comma-found-token.rs
new file mode 100644
index 0000000..d8717f3
--- /dev/null
+++ b/src/test/ui/on-unimplemented/expected-comma-found-token.rs
@@ -0,0 +1,13 @@
+// Tests that two closures cannot simultaneously have mutable
+// access to the variable, whether that mutable access be used
+// for direct assignment or for taking mutable ref. Issue #6801.
+
+#![feature(on_unimplemented)]
+
+#[rustc_on_unimplemented(
+    message="the message"
+    label="the label" //~ ERROR expected one of `)` or `,`, found `label`
+)]
+trait T {}
+
+fn main() {  }
diff --git a/src/test/ui/on-unimplemented/expected-comma-found-token.stderr b/src/test/ui/on-unimplemented/expected-comma-found-token.stderr
new file mode 100644
index 0000000..5bbdbe2
--- /dev/null
+++ b/src/test/ui/on-unimplemented/expected-comma-found-token.stderr
@@ -0,0 +1,10 @@
+error: expected one of `)` or `,`, found `label`
+  --> $DIR/expected-comma-found-token.rs:9:5
+   |
+LL |     message="the message"
+   |                          - expected one of `)` or `,` here
+LL |     label="the label"
+   |     ^^^^^ unexpected token
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/on-unimplemented/multiple-impls.rs b/src/test/ui/on-unimplemented/multiple-impls.rs
new file mode 100644
index 0000000..0aee98b
--- /dev/null
+++ b/src/test/ui/on-unimplemented/multiple-impls.rs
@@ -0,0 +1,42 @@
+// Test if the on_unimplemented message override works
+
+#![feature(on_unimplemented)]
+
+
+struct Foo<T>(T);
+struct Bar<T>(T);
+
+#[rustc_on_unimplemented = "trait message"]
+trait Index<Idx: ?Sized> {
+    type Output: ?Sized;
+    fn index(&self, index: Idx) -> &Self::Output;
+}
+
+#[rustc_on_unimplemented = "on impl for Foo"]
+impl Index<Foo<usize>> for [i32] {
+    type Output = i32;
+    fn index(&self, _index: Foo<usize>) -> &i32 {
+        loop {}
+    }
+}
+
+#[rustc_on_unimplemented = "on impl for Bar"]
+impl Index<Bar<usize>> for [i32] {
+    type Output = i32;
+    fn index(&self, _index: Bar<usize>) -> &i32 {
+        loop {}
+    }
+}
+
+
+fn main() {
+    Index::index(&[] as &[i32], 2u32);
+    //~^ ERROR E0277
+    //~| ERROR E0277
+    Index::index(&[] as &[i32], Foo(2u32));
+    //~^ ERROR E0277
+    //~| ERROR E0277
+    Index::index(&[] as &[i32], Bar(2u32));
+    //~^ ERROR E0277
+    //~| ERROR E0277
+}
diff --git a/src/test/ui/on-unimplemented/multiple-impls.stderr b/src/test/ui/on-unimplemented/multiple-impls.stderr
new file mode 100644
index 0000000..5d5db21
--- /dev/null
+++ b/src/test/ui/on-unimplemented/multiple-impls.stderr
@@ -0,0 +1,66 @@
+error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
+  --> $DIR/multiple-impls.rs:33:5
+   |
+LL |     Index::index(&[] as &[i32], 2u32);
+   |     ^^^^^^^^^^^^ trait message
+   |
+   = help: the trait `Index<u32>` is not implemented for `[i32]`
+note: required by `Index::index`
+  --> $DIR/multiple-impls.rs:12:5
+   |
+LL |     fn index(&self, index: Idx) -> &Self::Output;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
+  --> $DIR/multiple-impls.rs:33:5
+   |
+LL |     Index::index(&[] as &[i32], 2u32);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait message
+   |
+   = help: the trait `Index<u32>` is not implemented for `[i32]`
+
+error[E0277]: the trait bound `[i32]: Index<Foo<u32>>` is not satisfied
+  --> $DIR/multiple-impls.rs:36:5
+   |
+LL |     Index::index(&[] as &[i32], Foo(2u32));
+   |     ^^^^^^^^^^^^ on impl for Foo
+   |
+   = help: the trait `Index<Foo<u32>>` is not implemented for `[i32]`
+note: required by `Index::index`
+  --> $DIR/multiple-impls.rs:12:5
+   |
+LL |     fn index(&self, index: Idx) -> &Self::Output;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `[i32]: Index<Foo<u32>>` is not satisfied
+  --> $DIR/multiple-impls.rs:36:5
+   |
+LL |     Index::index(&[] as &[i32], Foo(2u32));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ on impl for Foo
+   |
+   = help: the trait `Index<Foo<u32>>` is not implemented for `[i32]`
+
+error[E0277]: the trait bound `[i32]: Index<Bar<u32>>` is not satisfied
+  --> $DIR/multiple-impls.rs:39:5
+   |
+LL |     Index::index(&[] as &[i32], Bar(2u32));
+   |     ^^^^^^^^^^^^ on impl for Bar
+   |
+   = help: the trait `Index<Bar<u32>>` is not implemented for `[i32]`
+note: required by `Index::index`
+  --> $DIR/multiple-impls.rs:12:5
+   |
+LL |     fn index(&self, index: Idx) -> &Self::Output;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `[i32]: Index<Bar<u32>>` is not satisfied
+  --> $DIR/multiple-impls.rs:39:5
+   |
+LL |     Index::index(&[] as &[i32], Bar(2u32));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ on impl for Bar
+   |
+   = help: the trait `Index<Bar<u32>>` is not implemented for `[i32]`
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/on-unimplemented/no-debug.rs b/src/test/ui/on-unimplemented/no-debug.rs
new file mode 100644
index 0000000..858df17
--- /dev/null
+++ b/src/test/ui/on-unimplemented/no-debug.rs
@@ -0,0 +1,17 @@
+// aux-build:no_debug.rs
+
+extern crate no_debug;
+
+use no_debug::Bar;
+
+struct Foo;
+
+fn main() {
+    println!("{:?} {:?}", Foo, Bar);
+    println!("{} {}", Foo, Bar);
+}
+//~^^^ ERROR `Foo` doesn't implement `std::fmt::Debug`
+//~| ERROR `no_debug::Bar` doesn't implement `std::fmt::Debug`
+//~^^^^ ERROR `Foo` doesn't implement `std::fmt::Display`
+//~| ERROR `no_debug::Bar` doesn't implement `std::fmt::Display`
+
diff --git a/src/test/ui/on-unimplemented/no-debug.stderr b/src/test/ui/on-unimplemented/no-debug.stderr
new file mode 100644
index 0000000..cbb41263
--- /dev/null
+++ b/src/test/ui/on-unimplemented/no-debug.stderr
@@ -0,0 +1,42 @@
+error[E0277]: `Foo` doesn't implement `std::fmt::Debug`
+  --> $DIR/no-debug.rs:10:27
+   |
+LL |     println!("{:?} {:?}", Foo, Bar);
+   |                           ^^^ `Foo` cannot be formatted using `{:?}`
+   |
+   = help: the trait `std::fmt::Debug` is not implemented for `Foo`
+   = note: add `#[derive(Debug)]` or manually implement `std::fmt::Debug`
+   = note: required by `std::fmt::Debug::fmt`
+
+error[E0277]: `no_debug::Bar` doesn't implement `std::fmt::Debug`
+  --> $DIR/no-debug.rs:10:32
+   |
+LL |     println!("{:?} {:?}", Foo, Bar);
+   |                                ^^^ `no_debug::Bar` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug`
+   |
+   = help: the trait `std::fmt::Debug` is not implemented for `no_debug::Bar`
+   = note: required by `std::fmt::Debug::fmt`
+
+error[E0277]: `Foo` doesn't implement `std::fmt::Display`
+  --> $DIR/no-debug.rs:11:23
+   |
+LL |     println!("{} {}", Foo, Bar);
+   |                       ^^^ `Foo` cannot be formatted with the default formatter
+   |
+   = help: the trait `std::fmt::Display` is not implemented for `Foo`
+   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
+   = note: required by `std::fmt::Display::fmt`
+
+error[E0277]: `no_debug::Bar` doesn't implement `std::fmt::Display`
+  --> $DIR/no-debug.rs:11:28
+   |
+LL |     println!("{} {}", Foo, Bar);
+   |                            ^^^ `no_debug::Bar` cannot be formatted with the default formatter
+   |
+   = help: the trait `std::fmt::Display` is not implemented for `no_debug::Bar`
+   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
+   = note: required by `std::fmt::Display::fmt`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/on-unimplemented/on-impl.rs b/src/test/ui/on-unimplemented/on-impl.rs
new file mode 100644
index 0000000..9e4c2f6
--- /dev/null
+++ b/src/test/ui/on-unimplemented/on-impl.rs
@@ -0,0 +1,25 @@
+// Test if the on_unimplemented message override works
+
+#![feature(on_unimplemented)]
+
+
+#[rustc_on_unimplemented = "invalid"]
+trait Index<Idx: ?Sized> {
+    type Output: ?Sized;
+    fn index(&self, index: Idx) -> &Self::Output;
+}
+
+#[rustc_on_unimplemented = "a usize is required to index into a slice"]
+impl Index<usize> for [i32] {
+    type Output = i32;
+    fn index(&self, index: usize) -> &i32 {
+        &self[index]
+    }
+}
+
+
+fn main() {
+    Index::<u32>::index(&[1, 2, 3] as &[i32], 2u32);
+    //~^ ERROR E0277
+    //~| ERROR E0277
+}
diff --git a/src/test/ui/on-unimplemented/on-impl.stderr b/src/test/ui/on-unimplemented/on-impl.stderr
new file mode 100644
index 0000000..79cf22f
--- /dev/null
+++ b/src/test/ui/on-unimplemented/on-impl.stderr
@@ -0,0 +1,24 @@
+error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
+  --> $DIR/on-impl.rs:22:5
+   |
+LL |     Index::<u32>::index(&[1, 2, 3] as &[i32], 2u32);
+   |     ^^^^^^^^^^^^^^^^^^^ a usize is required to index into a slice
+   |
+   = help: the trait `Index<u32>` is not implemented for `[i32]`
+note: required by `Index::index`
+  --> $DIR/on-impl.rs:9:5
+   |
+LL |     fn index(&self, index: Idx) -> &Self::Output;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
+  --> $DIR/on-impl.rs:22:5
+   |
+LL |     Index::<u32>::index(&[1, 2, 3] as &[i32], 2u32);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ a usize is required to index into a slice
+   |
+   = help: the trait `Index<u32>` is not implemented for `[i32]`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/on-unimplemented/on-trait.rs b/src/test/ui/on-unimplemented/on-trait.rs
new file mode 100644
index 0000000..109cb5b
--- /dev/null
+++ b/src/test/ui/on-unimplemented/on-trait.rs
@@ -0,0 +1,32 @@
+// ignore-tidy-linelength
+
+#![feature(on_unimplemented)]
+
+pub mod Bar {
+  #[rustc_on_unimplemented = "test error `{Self}` with `{Bar}` `{Baz}` `{Quux}` in `{Foo}`"]
+  pub trait Foo<Bar, Baz, Quux> {}
+}
+
+use Bar::Foo;
+
+fn foobar<U: Clone, T: Foo<u8, U, u32>>() -> T {
+    panic!()
+}
+
+#[rustc_on_unimplemented="a collection of type `{Self}` cannot be built from an iterator over elements of type `{A}`"]
+trait MyFromIterator<A> {
+    /// Builds a container with elements from an external iterator.
+    fn my_from_iter<T: Iterator<Item=A>>(iterator: T) -> Self;
+}
+
+fn collect<A, I: Iterator<Item=A>, B: MyFromIterator<A>>(it: I) -> B {
+    MyFromIterator::my_from_iter(it)
+}
+
+pub fn main() {
+    let x = vec![1u8, 2, 3, 4];
+    let y: Option<Vec<u8>> = collect(x.iter()); // this should give approximately the same error for x.iter().collect()
+    //~^ ERROR
+
+    let x: String = foobar(); //~ ERROR
+}
diff --git a/src/test/ui/on-unimplemented/on-trait.stderr b/src/test/ui/on-unimplemented/on-trait.stderr
new file mode 100644
index 0000000..ece8dee
--- /dev/null
+++ b/src/test/ui/on-unimplemented/on-trait.stderr
@@ -0,0 +1,29 @@
+error[E0277]: the trait bound `std::option::Option<std::vec::Vec<u8>>: MyFromIterator<&u8>` is not satisfied
+  --> $DIR/on-trait.rs:28:30
+   |
+LL |     let y: Option<Vec<u8>> = collect(x.iter()); // this should give approximately the same error for x.iter().collect()
+   |                              ^^^^^^^ a collection of type `std::option::Option<std::vec::Vec<u8>>` cannot be built from an iterator over elements of type `&u8`
+   |
+   = help: the trait `MyFromIterator<&u8>` is not implemented for `std::option::Option<std::vec::Vec<u8>>`
+note: required by `collect`
+  --> $DIR/on-trait.rs:22:1
+   |
+LL | fn collect<A, I: Iterator<Item=A>, B: MyFromIterator<A>>(it: I) -> B {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `std::string::String: Bar::Foo<u8, _, u32>` is not satisfied
+  --> $DIR/on-trait.rs:31:21
+   |
+LL |     let x: String = foobar();
+   |                     ^^^^^^ test error `std::string::String` with `u8` `_` `u32` in `Bar::Foo`
+   |
+   = help: the trait `Bar::Foo<u8, _, u32>` is not implemented for `std::string::String`
+note: required by `foobar`
+  --> $DIR/on-trait.rs:12:1
+   |
+LL | fn foobar<U: Clone, T: Foo<u8, U, u32>>() -> T {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/on-unimplemented/slice-index.rs b/src/test/ui/on-unimplemented/slice-index.rs
new file mode 100644
index 0000000..b5e18e2
--- /dev/null
+++ b/src/test/ui/on-unimplemented/slice-index.rs
@@ -0,0 +1,13 @@
+// Test new Index error message for slices
+// ignore-tidy-linelength
+
+
+
+use std::ops::Index;
+
+
+fn main() {
+    let x = &[1, 2, 3] as &[i32];
+    x[1i32]; //~ ERROR E0277
+    x[..1i32]; //~ ERROR E0277
+}
diff --git a/src/test/ui/on-unimplemented/slice-index.stderr b/src/test/ui/on-unimplemented/slice-index.stderr
new file mode 100644
index 0000000..c1d8849
--- /dev/null
+++ b/src/test/ui/on-unimplemented/slice-index.stderr
@@ -0,0 +1,21 @@
+error[E0277]: the type `[i32]` cannot be indexed by `i32`
+  --> $DIR/slice-index.rs:11:5
+   |
+LL |     x[1i32];
+   |     ^^^^^^^ slice indices are of type `usize` or ranges of `usize`
+   |
+   = help: the trait `std::slice::SliceIndex<[i32]>` is not implemented for `i32`
+   = note: required because of the requirements on the impl of `std::ops::Index<i32>` for `[i32]`
+
+error[E0277]: the type `[i32]` cannot be indexed by `std::ops::RangeTo<i32>`
+  --> $DIR/slice-index.rs:12:5
+   |
+LL |     x[..1i32];
+   |     ^^^^^^^^^ slice indices are of type `usize` or ranges of `usize`
+   |
+   = help: the trait `std::slice::SliceIndex<[i32]>` is not implemented for `std::ops::RangeTo<i32>`
+   = note: required because of the requirements on the impl of `std::ops::Index<std::ops::RangeTo<i32>>` for `[i32]`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/once-cant-call-twice-on-heap.nll.stderr b/src/test/ui/once-cant-call-twice-on-heap.nll.stderr
new file mode 100644
index 0000000..f98d3d8
--- /dev/null
+++ b/src/test/ui/once-cant-call-twice-on-heap.nll.stderr
@@ -0,0 +1,15 @@
+error[E0382]: use of moved value: `blk`
+  --> $DIR/once-cant-call-twice-on-heap.rs:9:5
+   |
+LL | fn foo<F:FnOnce()>(blk: F) {
+   |        -           --- move occurs because `blk` has type `F`, which does not implement the `Copy` trait
+   |        |
+   |        consider adding a `Copy` constraint to this type argument
+LL |     blk();
+   |     --- value moved here
+LL |     blk();
+   |     ^^^ value used here after move
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/once-cant-call-twice-on-heap.rs b/src/test/ui/once-cant-call-twice-on-heap.rs
new file mode 100644
index 0000000..9aefe1e
--- /dev/null
+++ b/src/test/ui/once-cant-call-twice-on-heap.rs
@@ -0,0 +1,18 @@
+// Testing guarantees provided by once functions.
+// This program would segfault if it were legal.
+
+#![feature(once_fns)]
+use std::sync::Arc;
+
+fn foo<F:FnOnce()>(blk: F) {
+    blk();
+    blk(); //~ ERROR use of moved value
+}
+
+fn main() {
+    let x = Arc::new(true);
+    foo(move|| {
+        assert!(*x);
+        drop(x);
+    });
+}
diff --git a/src/test/ui/once-cant-call-twice-on-heap.stderr b/src/test/ui/once-cant-call-twice-on-heap.stderr
new file mode 100644
index 0000000..40034da
--- /dev/null
+++ b/src/test/ui/once-cant-call-twice-on-heap.stderr
@@ -0,0 +1,13 @@
+error[E0382]: use of moved value: `blk`
+  --> $DIR/once-cant-call-twice-on-heap.rs:9:5
+   |
+LL |     blk();
+   |     --- value moved here
+LL |     blk();
+   |     ^^^ value used here after move
+   |
+   = note: move occurs because `blk` has type `F`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/opt-in-copy.rs b/src/test/ui/opt-in-copy.rs
new file mode 100644
index 0000000..0b48418
--- /dev/null
+++ b/src/test/ui/opt-in-copy.rs
@@ -0,0 +1,22 @@
+struct CantCopyThis;
+
+struct IWantToCopyThis {
+    but_i_cant: CantCopyThis,
+}
+
+impl Copy for IWantToCopyThis {}
+//~^ ERROR the trait `Copy` may not be implemented for this type
+
+enum CantCopyThisEither {
+    A,
+    B,
+}
+
+enum IWantToCopyThisToo {
+    ButICant(CantCopyThisEither),
+}
+
+impl Copy for IWantToCopyThisToo {}
+//~^ ERROR the trait `Copy` may not be implemented for this type
+
+fn main() {}
diff --git a/src/test/ui/opt-in-copy.stderr b/src/test/ui/opt-in-copy.stderr
new file mode 100644
index 0000000..0a275f1
--- /dev/null
+++ b/src/test/ui/opt-in-copy.stderr
@@ -0,0 +1,21 @@
+error[E0204]: the trait `Copy` may not be implemented for this type
+  --> $DIR/opt-in-copy.rs:7:6
+   |
+LL |     but_i_cant: CantCopyThis,
+   |     ------------------------ this field does not implement `Copy`
+...
+LL | impl Copy for IWantToCopyThis {}
+   |      ^^^^
+
+error[E0204]: the trait `Copy` may not be implemented for this type
+  --> $DIR/opt-in-copy.rs:19:6
+   |
+LL |     ButICant(CantCopyThisEither),
+   |              ------------------ this field does not implement `Copy`
+...
+LL | impl Copy for IWantToCopyThisToo {}
+   |      ^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0204`.
diff --git a/src/test/ui/or-pattern-mismatch.rs b/src/test/ui/or-pattern-mismatch.rs
new file mode 100644
index 0000000..973954b
--- /dev/null
+++ b/src/test/ui/or-pattern-mismatch.rs
@@ -0,0 +1,4 @@
+enum Blah { A(isize, isize, usize), B(isize, isize) }
+
+fn main() { match Blah::A(1, 1, 2) { Blah::A(_, x, y) | Blah::B(x, y) => { } } }
+//~^ ERROR mismatched types
diff --git a/src/test/ui/or-pattern-mismatch.stderr b/src/test/ui/or-pattern-mismatch.stderr
new file mode 100644
index 0000000..731b209
--- /dev/null
+++ b/src/test/ui/or-pattern-mismatch.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/or-pattern-mismatch.rs:3:68
+   |
+LL | fn main() { match Blah::A(1, 1, 2) { Blah::A(_, x, y) | Blah::B(x, y) => { } } }
+   |                                                                    ^ expected usize, found isize
+   |
+   = note: expected type `usize`
+              found type `isize`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/order-dependent-cast-inference.rs b/src/test/ui/order-dependent-cast-inference.rs
new file mode 100644
index 0000000..e666209
--- /dev/null
+++ b/src/test/ui/order-dependent-cast-inference.rs
@@ -0,0 +1,8 @@
+fn main() {
+    // Tests case where inference fails due to the order in which casts are checked.
+    // Ideally this would compile, see #48270.
+    let x = &"hello";
+    let mut y = 0 as *const _;
+    //~^ ERROR cannot cast to a pointer of an unknown kind
+    y = x as *const _;
+}
diff --git a/src/test/ui/order-dependent-cast-inference.stderr b/src/test/ui/order-dependent-cast-inference.stderr
new file mode 100644
index 0000000..081038c
--- /dev/null
+++ b/src/test/ui/order-dependent-cast-inference.stderr
@@ -0,0 +1,13 @@
+error[E0641]: cannot cast to a pointer of an unknown kind
+  --> $DIR/order-dependent-cast-inference.rs:5:17
+   |
+LL |     let mut y = 0 as *const _;
+   |                 ^^^^^--------
+   |                      |
+   |                      help: consider giving more type information
+   |
+   = note: The type information given here is insufficient to check whether the pointer cast is valid
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0641`.
diff --git a/src/test/ui/orphan-check-diagnostics.rs b/src/test/ui/orphan-check-diagnostics.rs
new file mode 100644
index 0000000..c8803b9
--- /dev/null
+++ b/src/test/ui/orphan-check-diagnostics.rs
@@ -0,0 +1,14 @@
+// aux-build:orphan-check-diagnostics.rs
+
+// See issue #22388.
+
+extern crate orphan_check_diagnostics;
+
+use orphan_check_diagnostics::RemoteTrait;
+
+trait LocalTrait { fn dummy(&self) { } }
+
+impl<T> RemoteTrait for T where T: LocalTrait {}
+//~^ ERROR type parameter `T` must be used as the type parameter for some local type
+
+fn main() {}
diff --git a/src/test/ui/orphan-check-diagnostics.stderr b/src/test/ui/orphan-check-diagnostics.stderr
new file mode 100644
index 0000000..3f86842
--- /dev/null
+++ b/src/test/ui/orphan-check-diagnostics.stderr
@@ -0,0 +1,11 @@
+error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
+  --> $DIR/orphan-check-diagnostics.rs:11:1
+   |
+LL | impl<T> RemoteTrait for T where T: LocalTrait {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type
+   |
+   = note: only traits defined in the current crate can be implemented for a type parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0210`.
diff --git a/src/test/ui/osx-frameworks.rs b/src/test/ui/osx-frameworks.rs
new file mode 100644
index 0000000..227e07d
--- /dev/null
+++ b/src/test/ui/osx-frameworks.rs
@@ -0,0 +1,8 @@
+// ignore-macos this is supposed to succeed on osx
+
+#[link(name = "foo", kind = "framework")]
+extern {}
+//~^^ ERROR: native frameworks are only available on macOS
+
+fn main() {
+}
diff --git a/src/test/ui/osx-frameworks.stderr b/src/test/ui/osx-frameworks.stderr
new file mode 100644
index 0000000..f353291
--- /dev/null
+++ b/src/test/ui/osx-frameworks.stderr
@@ -0,0 +1,9 @@
+error[E0455]: native frameworks are only available on macOS targets
+  --> $DIR/osx-frameworks.rs:3:1
+   |
+LL | #[link(name = "foo", kind = "framework")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0455`.
diff --git a/src/test/ui/out-of-order-shadowing.rs b/src/test/ui/out-of-order-shadowing.rs
new file mode 100644
index 0000000..a0d1a97
--- /dev/null
+++ b/src/test/ui/out-of-order-shadowing.rs
@@ -0,0 +1,10 @@
+// aux-build:define-macro.rs
+
+macro_rules! bar { () => {} }
+define_macro!(bar);
+bar!(); //~ ERROR `bar` is ambiguous
+
+macro_rules! m { () => { #[macro_use] extern crate define_macro; } }
+m!();
+
+fn main() {}
diff --git a/src/test/ui/out-of-order-shadowing.stderr b/src/test/ui/out-of-order-shadowing.stderr
new file mode 100644
index 0000000..2a120de
--- /dev/null
+++ b/src/test/ui/out-of-order-shadowing.stderr
@@ -0,0 +1,21 @@
+error[E0659]: `bar` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
+  --> $DIR/out-of-order-shadowing.rs:5:1
+   |
+LL | bar!();
+   | ^^^ ambiguous name
+   |
+note: `bar` could refer to the macro defined here
+  --> $DIR/out-of-order-shadowing.rs:4:1
+   |
+LL | define_macro!(bar);
+   | ^^^^^^^^^^^^^^^^^^^
+note: `bar` could also refer to the macro defined here
+  --> $DIR/out-of-order-shadowing.rs:3:1
+   |
+LL | macro_rules! bar { () => {} }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0659`.
diff --git a/src/test/ui/output-type-mismatch.rs b/src/test/ui/output-type-mismatch.rs
new file mode 100644
index 0000000..35097aa
--- /dev/null
+++ b/src/test/ui/output-type-mismatch.rs
@@ -0,0 +1,5 @@
+// error-pattern: mismatched types
+
+fn f() { }
+
+fn main() { let i: isize; i = f(); }
diff --git a/src/test/ui/output-type-mismatch.stderr b/src/test/ui/output-type-mismatch.stderr
new file mode 100644
index 0000000..449d312
--- /dev/null
+++ b/src/test/ui/output-type-mismatch.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/output-type-mismatch.rs:5:31
+   |
+LL | fn main() { let i: isize; i = f(); }
+   |                               ^^^ expected isize, found ()
+   |
+   = note: expected type `isize`
+              found type `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/overlap-marker-trait.rs b/src/test/ui/overlap-marker-trait.rs
new file mode 100644
index 0000000..bf39d9c
--- /dev/null
+++ b/src/test/ui/overlap-marker-trait.rs
@@ -0,0 +1,31 @@
+// Test for RFC 1268: we allow overlapping impls of marker traits,
+// that is, traits without items. In this case, a type `T` is
+// `MyMarker` if it is either `Debug` or `Display`. This test just
+// checks that we don't consider **all** types to be `MyMarker`.  See
+// also the companion test in
+// `run-pass/overlap-permitted-for-marker-traits.rs`.
+
+#![feature(overlapping_marker_traits)]
+#![feature(optin_builtin_traits)]
+
+use std::fmt::{Debug, Display};
+
+trait Marker {}
+
+impl<T: Debug> Marker for T {}
+impl<T: Display> Marker for T {}
+
+fn is_marker<T: Marker>() { }
+
+struct NotDebugOrDisplay;
+
+fn main() {
+    // Debug && Display:
+    is_marker::<i32>();
+
+    // Debug && !Display:
+    is_marker::<Vec<i32>>();
+
+    // !Debug && !Display
+    is_marker::<NotDebugOrDisplay>(); //~ ERROR
+}
diff --git a/src/test/ui/overlap-marker-trait.stderr b/src/test/ui/overlap-marker-trait.stderr
new file mode 100644
index 0000000..a59af8d
--- /dev/null
+++ b/src/test/ui/overlap-marker-trait.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `NotDebugOrDisplay: Marker` is not satisfied
+  --> $DIR/overlap-marker-trait.rs:30:5
+   |
+LL |     is_marker::<NotDebugOrDisplay>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Marker` is not implemented for `NotDebugOrDisplay`
+   |
+note: required by `is_marker`
+  --> $DIR/overlap-marker-trait.rs:18:1
+   |
+LL | fn is_marker<T: Marker>() { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/overloaded-calls-nontuple.rs b/src/test/ui/overloaded-calls-nontuple.rs
new file mode 100644
index 0000000..62a7130
--- /dev/null
+++ b/src/test/ui/overloaded-calls-nontuple.rs
@@ -0,0 +1,27 @@
+#![feature(fn_traits, unboxed_closures)]
+
+use std::ops::FnMut;
+
+struct S {
+    x: isize,
+    y: isize,
+}
+
+impl FnMut<isize> for S {
+    extern "rust-call" fn call_mut(&mut self, z: isize) -> isize {
+        self.x + self.y + z
+    }
+}
+
+impl FnOnce<isize> for S {
+    type Output = isize;
+    extern "rust-call" fn call_once(mut self, z: isize) -> isize { self.call_mut(z) }
+}
+
+fn main() {
+    let mut s = S {
+        x: 1,
+        y: 2,
+    };
+    drop(s(3))  //~ ERROR cannot use call notation
+}
diff --git a/src/test/ui/overloaded-calls-nontuple.stderr b/src/test/ui/overloaded-calls-nontuple.stderr
new file mode 100644
index 0000000..82c12c4
--- /dev/null
+++ b/src/test/ui/overloaded-calls-nontuple.stderr
@@ -0,0 +1,9 @@
+error[E0059]: cannot use call notation; the first type parameter for the function trait is neither a tuple nor unit
+  --> $DIR/overloaded-calls-nontuple.rs:26:10
+   |
+LL |     drop(s(3))
+   |          ^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0059`.
diff --git a/src/test/ui/packed-struct/packed-struct-generic-transmute.rs b/src/test/ui/packed-struct/packed-struct-generic-transmute.rs
new file mode 100644
index 0000000..c6264b6
--- /dev/null
+++ b/src/test/ui/packed-struct/packed-struct-generic-transmute.rs
@@ -0,0 +1,27 @@
+// This assumes the packed and non-packed structs are different sizes.
+
+// the error points to the start of the file, not the line with the
+// transmute
+
+// error-pattern: cannot transmute between types of different sizes, or dependently-sized types
+
+use std::mem;
+
+#[repr(packed)]
+struct Foo<T,S> {
+    bar: T,
+    baz: S
+}
+
+struct Oof<T, S> {
+    rab: T,
+    zab: S
+}
+
+fn main() {
+    let foo = Foo { bar: [1u8, 2, 3, 4, 5], baz: 10i32 };
+    unsafe {
+        let oof: Oof<[u8; 5], i32> = mem::transmute(foo);
+        println!("{:?} {:?}", &oof.rab[..], oof.zab);
+    }
+}
diff --git a/src/test/ui/packed-struct/packed-struct-generic-transmute.stderr b/src/test/ui/packed-struct/packed-struct-generic-transmute.stderr
new file mode 100644
index 0000000..744c832
--- /dev/null
+++ b/src/test/ui/packed-struct/packed-struct-generic-transmute.stderr
@@ -0,0 +1,12 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/packed-struct-generic-transmute.rs:24:38
+   |
+LL |         let oof: Oof<[u8; 5], i32> = mem::transmute(foo);
+   |                                      ^^^^^^^^^^^^^^
+   |
+   = note: source type: `Foo<[u8; 5], i32>` (72 bits)
+   = note: target type: `Oof<[u8; 5], i32>` (96 bits)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0512`.
diff --git a/src/test/ui/packed-struct/packed-struct-transmute.rs b/src/test/ui/packed-struct/packed-struct-transmute.rs
new file mode 100644
index 0000000..a7d2840
--- /dev/null
+++ b/src/test/ui/packed-struct/packed-struct-transmute.rs
@@ -0,0 +1,29 @@
+// This assumes the packed and non-packed structs are different sizes.
+
+// the error points to the start of the file, not the line with the
+// transmute
+
+// normalize-stderr-test "\d+ bits" -> "N bits"
+// error-pattern: cannot transmute between types of different sizes, or dependently-sized types
+
+use std::mem;
+
+#[repr(packed)]
+struct Foo {
+    bar: u8,
+    baz: usize
+}
+
+#[derive(Debug)]
+struct Oof {
+    rab: u8,
+    zab: usize
+}
+
+fn main() {
+    let foo = Foo { bar: 1, baz: 10 };
+    unsafe {
+        let oof: Oof = mem::transmute(foo);
+        println!("{:?}", oof);
+    }
+}
diff --git a/src/test/ui/packed-struct/packed-struct-transmute.stderr b/src/test/ui/packed-struct/packed-struct-transmute.stderr
new file mode 100644
index 0000000..80a8919
--- /dev/null
+++ b/src/test/ui/packed-struct/packed-struct-transmute.stderr
@@ -0,0 +1,12 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/packed-struct-transmute.rs:26:24
+   |
+LL |         let oof: Oof = mem::transmute(foo);
+   |                        ^^^^^^^^^^^^^^
+   |
+   = note: source type: `Foo` (N bits)
+   = note: target type: `Oof` (N bits)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0512`.
diff --git a/src/test/ui/panic-handler/auxiliary/some-panic-impl.rs b/src/test/ui/panic-handler/auxiliary/some-panic-impl.rs
new file mode 100644
index 0000000..0348b3a
--- /dev/null
+++ b/src/test/ui/panic-handler/auxiliary/some-panic-impl.rs
@@ -0,0 +1,11 @@
+// no-prefer-dynamic
+
+#![crate_type = "rlib"]
+#![no_std]
+
+use core::panic::PanicInfo;
+
+#[panic_handler]
+fn panic(info: &PanicInfo) -> ! {
+    loop {}
+}
diff --git a/src/test/ui/panic-handler/panic-handler-bad-signature-1.rs b/src/test/ui/panic-handler/panic-handler-bad-signature-1.rs
new file mode 100644
index 0000000..775961d
--- /dev/null
+++ b/src/test/ui/panic-handler/panic-handler-bad-signature-1.rs
@@ -0,0 +1,13 @@
+// compile-flags:-C panic=abort
+
+#![no_std]
+#![no_main]
+
+use core::panic::PanicInfo;
+
+#[panic_handler]
+fn panic(
+    info: PanicInfo, //~ ERROR argument should be `&PanicInfo`
+) -> () //~ ERROR return type should be `!`
+{
+}
diff --git a/src/test/ui/panic-handler/panic-handler-bad-signature-1.stderr b/src/test/ui/panic-handler/panic-handler-bad-signature-1.stderr
new file mode 100644
index 0000000..8b044f7
--- /dev/null
+++ b/src/test/ui/panic-handler/panic-handler-bad-signature-1.stderr
@@ -0,0 +1,14 @@
+error: return type should be `!`
+  --> $DIR/panic-handler-bad-signature-1.rs:11:6
+   |
+LL | ) -> ()
+   |      ^^
+
+error: argument should be `&PanicInfo`
+  --> $DIR/panic-handler-bad-signature-1.rs:10:11
+   |
+LL |     info: PanicInfo,
+   |           ^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/panic-handler/panic-handler-bad-signature-2.rs b/src/test/ui/panic-handler/panic-handler-bad-signature-2.rs
new file mode 100644
index 0000000..7279340
--- /dev/null
+++ b/src/test/ui/panic-handler/panic-handler-bad-signature-2.rs
@@ -0,0 +1,14 @@
+// compile-flags:-C panic=abort
+
+#![no_std]
+#![no_main]
+
+use core::panic::PanicInfo;
+
+#[panic_handler]
+fn panic(
+    info: &'static PanicInfo, //~ ERROR argument should be `&PanicInfo`
+) -> !
+{
+    loop {}
+}
diff --git a/src/test/ui/panic-handler/panic-handler-bad-signature-2.stderr b/src/test/ui/panic-handler/panic-handler-bad-signature-2.stderr
new file mode 100644
index 0000000..5ab6934
--- /dev/null
+++ b/src/test/ui/panic-handler/panic-handler-bad-signature-2.stderr
@@ -0,0 +1,8 @@
+error: argument should be `&PanicInfo`
+  --> $DIR/panic-handler-bad-signature-2.rs:10:11
+   |
+LL |     info: &'static PanicInfo,
+   |           ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/panic-handler/panic-handler-bad-signature-3.rs b/src/test/ui/panic-handler/panic-handler-bad-signature-3.rs
new file mode 100644
index 0000000..ab9c9d7
--- /dev/null
+++ b/src/test/ui/panic-handler/panic-handler-bad-signature-3.rs
@@ -0,0 +1,11 @@
+// compile-flags:-C panic=abort
+
+#![no_std]
+#![no_main]
+
+use core::panic::PanicInfo;
+
+#[panic_handler]
+fn panic() -> ! { //~ ERROR function should have one argument
+    loop {}
+}
diff --git a/src/test/ui/panic-handler/panic-handler-bad-signature-3.stderr b/src/test/ui/panic-handler/panic-handler-bad-signature-3.stderr
new file mode 100644
index 0000000..0a70181
--- /dev/null
+++ b/src/test/ui/panic-handler/panic-handler-bad-signature-3.stderr
@@ -0,0 +1,8 @@
+error: function should have one argument
+  --> $DIR/panic-handler-bad-signature-3.rs:9:1
+   |
+LL | fn panic() -> ! {
+   | ^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/panic-handler/panic-handler-bad-signature-4.rs b/src/test/ui/panic-handler/panic-handler-bad-signature-4.rs
new file mode 100644
index 0000000..8240ab0
--- /dev/null
+++ b/src/test/ui/panic-handler/panic-handler-bad-signature-4.rs
@@ -0,0 +1,12 @@
+// compile-flags:-C panic=abort
+
+#![no_std]
+#![no_main]
+
+use core::panic::PanicInfo;
+
+#[panic_handler]
+fn panic<T>(pi: &PanicInfo) -> ! {
+    //~^ ERROR should have no type parameters
+    loop {}
+}
diff --git a/src/test/ui/panic-handler/panic-handler-bad-signature-4.stderr b/src/test/ui/panic-handler/panic-handler-bad-signature-4.stderr
new file mode 100644
index 0000000..3a5fc76
--- /dev/null
+++ b/src/test/ui/panic-handler/panic-handler-bad-signature-4.stderr
@@ -0,0 +1,11 @@
+error: should have no type parameters
+  --> $DIR/panic-handler-bad-signature-4.rs:9:1
+   |
+LL | / fn panic<T>(pi: &PanicInfo) -> ! {
+LL | |
+LL | |     loop {}
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/panic-handler/panic-handler-duplicate.rs b/src/test/ui/panic-handler/panic-handler-duplicate.rs
new file mode 100644
index 0000000..caa130e
--- /dev/null
+++ b/src/test/ui/panic-handler/panic-handler-duplicate.rs
@@ -0,0 +1,17 @@
+// compile-flags:-C panic=abort
+
+#![feature(lang_items)]
+#![no_std]
+#![no_main]
+
+use core::panic::PanicInfo;
+
+#[panic_handler]
+fn panic(info: &PanicInfo) -> ! {
+    loop {}
+}
+
+#[lang = "panic_impl"]
+fn panic2(info: &PanicInfo) -> ! { //~ ERROR duplicate lang item found: `panic_impl`.
+    loop {}
+}
diff --git a/src/test/ui/panic-handler/panic-handler-duplicate.stderr b/src/test/ui/panic-handler/panic-handler-duplicate.stderr
new file mode 100644
index 0000000..e9b1945
--- /dev/null
+++ b/src/test/ui/panic-handler/panic-handler-duplicate.stderr
@@ -0,0 +1,19 @@
+error[E0152]: duplicate lang item found: `panic_impl`.
+  --> $DIR/panic-handler-duplicate.rs:15:1
+   |
+LL | / fn panic2(info: &PanicInfo) -> ! {
+LL | |     loop {}
+LL | | }
+   | |_^
+   |
+note: first defined here.
+  --> $DIR/panic-handler-duplicate.rs:10:1
+   |
+LL | / fn panic(info: &PanicInfo) -> ! {
+LL | |     loop {}
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0152`.
diff --git a/src/test/ui/panic-handler/panic-handler-requires-panic-info.rs b/src/test/ui/panic-handler/panic-handler-requires-panic-info.rs
new file mode 100644
index 0000000..f13c12f
--- /dev/null
+++ b/src/test/ui/panic-handler/panic-handler-requires-panic-info.rs
@@ -0,0 +1,15 @@
+// compile-flags:-C panic=abort
+// error-pattern: language item required, but not found: `panic_info`
+
+#![feature(lang_items)]
+#![feature(no_core)]
+#![no_core]
+#![no_main]
+
+#[panic_handler]
+fn panic() -> ! {
+    loop {}
+}
+
+#[lang = "sized"]
+trait Sized {}
diff --git a/src/test/ui/panic-handler/panic-handler-requires-panic-info.stderr b/src/test/ui/panic-handler/panic-handler-requires-panic-info.stderr
new file mode 100644
index 0000000..2bae12e
--- /dev/null
+++ b/src/test/ui/panic-handler/panic-handler-requires-panic-info.stderr
@@ -0,0 +1,4 @@
+error: language item required, but not found: `panic_info`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/panic-handler/panic-handler-std.rs b/src/test/ui/panic-handler/panic-handler-std.rs
new file mode 100644
index 0000000..fffb597
--- /dev/null
+++ b/src/test/ui/panic-handler/panic-handler-std.rs
@@ -0,0 +1,11 @@
+// error-pattern: duplicate lang item found: `panic_impl`.
+
+
+use std::panic::PanicInfo;
+
+#[panic_handler]
+fn panic(info: PanicInfo) -> ! {
+    loop {}
+}
+
+fn main() {}
diff --git a/src/test/ui/panic-handler/panic-handler-std.stderr b/src/test/ui/panic-handler/panic-handler-std.stderr
new file mode 100644
index 0000000..3224031
--- /dev/null
+++ b/src/test/ui/panic-handler/panic-handler-std.stderr
@@ -0,0 +1,19 @@
+error[E0152]: duplicate lang item found: `panic_impl`.
+  --> $DIR/panic-handler-std.rs:7:1
+   |
+LL | / fn panic(info: PanicInfo) -> ! {
+LL | |     loop {}
+LL | | }
+   | |_^
+   |
+   = note: first defined in crate `std`.
+
+error: argument should be `&PanicInfo`
+  --> $DIR/panic-handler-std.rs:7:16
+   |
+LL | fn panic(info: PanicInfo) -> ! {
+   |                ^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0152`.
diff --git a/src/test/ui/panic-handler/panic-handler-wrong-location.rs b/src/test/ui/panic-handler/panic-handler-wrong-location.rs
new file mode 100644
index 0000000..dca5910
--- /dev/null
+++ b/src/test/ui/panic-handler/panic-handler-wrong-location.rs
@@ -0,0 +1,8 @@
+// compile-flags:-C panic=abort
+
+#![no_std]
+#![no_main]
+
+#[panic_handler] //~ ERROR `panic_impl` language item must be applied to a function
+#[no_mangle]
+static X: u32 = 42;
diff --git a/src/test/ui/panic-handler/panic-handler-wrong-location.stderr b/src/test/ui/panic-handler/panic-handler-wrong-location.stderr
new file mode 100644
index 0000000..ae3ed5a
--- /dev/null
+++ b/src/test/ui/panic-handler/panic-handler-wrong-location.stderr
@@ -0,0 +1,11 @@
+error[E0718]: `panic_impl` language item must be applied to a function
+  --> $DIR/panic-handler-wrong-location.rs:6:1
+   |
+LL | #[panic_handler]
+   | ^^^^^^^^^^^^^^^^ attribute should be applied to a function, not a static item
+
+error: `#[panic_handler]` function required, but not found
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0718`.
diff --git a/src/test/ui/panic-runtime/abort-link-to-unwind-dylib.rs b/src/test/ui/panic-runtime/abort-link-to-unwind-dylib.rs
new file mode 100644
index 0000000..7e1174a
--- /dev/null
+++ b/src/test/ui/panic-runtime/abort-link-to-unwind-dylib.rs
@@ -0,0 +1,16 @@
+// compile-flags:-C panic=abort -C prefer-dynamic
+// ignore-musl - no dylibs here
+// ignore-cloudabi
+// ignore-emscripten
+// error-pattern:`panic_unwind` is not compiled with this crate's panic strategy
+
+// This is a test where the local crate, compiled with `panic=abort`, links to
+// the standard library **dynamically** which is already linked against
+// `panic=unwind`. We should fail because the linked panic runtime does not
+// correspond with our `-C panic` option.
+//
+// Note that this test assumes that the dynamic version of the standard library
+// is linked to `panic_unwind`, which is currently the case.
+
+fn main() {
+}
diff --git a/src/test/ui/panic-runtime/abort-link-to-unwind-dylib.stderr b/src/test/ui/panic-runtime/abort-link-to-unwind-dylib.stderr
new file mode 100644
index 0000000..704b81a
--- /dev/null
+++ b/src/test/ui/panic-runtime/abort-link-to-unwind-dylib.stderr
@@ -0,0 +1,4 @@
+error: the linked panic runtime `panic_unwind` is not compiled with this crate's panic strategy `abort`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/panic-runtime/auxiliary/panic-runtime-abort.rs b/src/test/ui/panic-runtime/auxiliary/panic-runtime-abort.rs
new file mode 100644
index 0000000..433301f
--- /dev/null
+++ b/src/test/ui/panic-runtime/auxiliary/panic-runtime-abort.rs
@@ -0,0 +1,17 @@
+// compile-flags:-C panic=abort
+// no-prefer-dynamic
+
+#![feature(panic_runtime)]
+#![crate_type = "rlib"]
+
+#![no_std]
+#![panic_runtime]
+
+#[no_mangle]
+pub extern fn __rust_maybe_catch_panic() {}
+
+#[no_mangle]
+pub extern fn __rust_start_panic() {}
+
+#[no_mangle]
+pub extern fn rust_eh_personality() {}
diff --git a/src/test/ui/panic-runtime/auxiliary/panic-runtime-lang-items.rs b/src/test/ui/panic-runtime/auxiliary/panic-runtime-lang-items.rs
new file mode 100644
index 0000000..abe34a3
--- /dev/null
+++ b/src/test/ui/panic-runtime/auxiliary/panic-runtime-lang-items.rs
@@ -0,0 +1,15 @@
+// no-prefer-dynamic
+
+#![crate_type = "rlib"]
+
+#![no_std]
+#![feature(lang_items)]
+
+use core::panic::PanicInfo;
+
+#[lang = "panic_impl"]
+fn panic_impl(info: &PanicInfo) -> ! { loop {} }
+#[lang = "eh_personality"]
+fn eh_personality() {}
+#[lang = "eh_unwind_resume"]
+fn eh_unwind_resume() {}
diff --git a/src/test/ui/panic-runtime/auxiliary/panic-runtime-unwind.rs b/src/test/ui/panic-runtime/auxiliary/panic-runtime-unwind.rs
new file mode 100644
index 0000000..97452a3
--- /dev/null
+++ b/src/test/ui/panic-runtime/auxiliary/panic-runtime-unwind.rs
@@ -0,0 +1,17 @@
+// compile-flags:-C panic=unwind
+// no-prefer-dynamic
+
+#![feature(panic_runtime)]
+#![crate_type = "rlib"]
+
+#![no_std]
+#![panic_runtime]
+
+#[no_mangle]
+pub extern fn __rust_maybe_catch_panic() {}
+
+#[no_mangle]
+pub extern fn __rust_start_panic() {}
+
+#[no_mangle]
+pub extern fn rust_eh_personality() {}
diff --git a/src/test/ui/panic-runtime/auxiliary/panic-runtime-unwind2.rs b/src/test/ui/panic-runtime/auxiliary/panic-runtime-unwind2.rs
new file mode 100644
index 0000000..97452a3
--- /dev/null
+++ b/src/test/ui/panic-runtime/auxiliary/panic-runtime-unwind2.rs
@@ -0,0 +1,17 @@
+// compile-flags:-C panic=unwind
+// no-prefer-dynamic
+
+#![feature(panic_runtime)]
+#![crate_type = "rlib"]
+
+#![no_std]
+#![panic_runtime]
+
+#[no_mangle]
+pub extern fn __rust_maybe_catch_panic() {}
+
+#[no_mangle]
+pub extern fn __rust_start_panic() {}
+
+#[no_mangle]
+pub extern fn rust_eh_personality() {}
diff --git a/src/test/ui/panic-runtime/auxiliary/wants-panic-runtime-abort.rs b/src/test/ui/panic-runtime/auxiliary/wants-panic-runtime-abort.rs
new file mode 100644
index 0000000..3c0d2d6
--- /dev/null
+++ b/src/test/ui/panic-runtime/auxiliary/wants-panic-runtime-abort.rs
@@ -0,0 +1,7 @@
+// compile-flags:-C panic=abort
+// no-prefer-dynamic
+
+#![crate_type = "rlib"]
+#![no_std]
+
+extern crate panic_runtime_abort;
diff --git a/src/test/ui/panic-runtime/auxiliary/wants-panic-runtime-unwind.rs b/src/test/ui/panic-runtime/auxiliary/wants-panic-runtime-unwind.rs
new file mode 100644
index 0000000..d5f0102
--- /dev/null
+++ b/src/test/ui/panic-runtime/auxiliary/wants-panic-runtime-unwind.rs
@@ -0,0 +1,6 @@
+// no-prefer-dynamic
+
+#![crate_type = "rlib"]
+#![no_std]
+
+extern crate panic_runtime_unwind;
diff --git a/src/test/ui/panic-runtime/bad-panic-flag1.rs b/src/test/ui/panic-runtime/bad-panic-flag1.rs
new file mode 100644
index 0000000..1ac6a34
--- /dev/null
+++ b/src/test/ui/panic-runtime/bad-panic-flag1.rs
@@ -0,0 +1,4 @@
+// compile-flags:-C panic=foo
+// error-pattern:either `unwind` or `abort` was expected
+
+fn main() {}
diff --git a/src/test/ui/panic-runtime/bad-panic-flag1.stderr b/src/test/ui/panic-runtime/bad-panic-flag1.stderr
new file mode 100644
index 0000000..013373c
--- /dev/null
+++ b/src/test/ui/panic-runtime/bad-panic-flag1.stderr
@@ -0,0 +1,2 @@
+error: incorrect value `foo` for codegen option `panic` - either `unwind` or `abort` was expected
+
diff --git a/src/test/ui/panic-runtime/bad-panic-flag2.rs b/src/test/ui/panic-runtime/bad-panic-flag2.rs
new file mode 100644
index 0000000..c79701c
--- /dev/null
+++ b/src/test/ui/panic-runtime/bad-panic-flag2.rs
@@ -0,0 +1,4 @@
+// compile-flags:-C panic
+// error-pattern:requires either `unwind` or `abort`
+
+fn main() {}
diff --git a/src/test/ui/panic-runtime/bad-panic-flag2.stderr b/src/test/ui/panic-runtime/bad-panic-flag2.stderr
new file mode 100644
index 0000000..6ab94ea
--- /dev/null
+++ b/src/test/ui/panic-runtime/bad-panic-flag2.stderr
@@ -0,0 +1,2 @@
+error: codegen option `panic` requires either `unwind` or `abort` (C panic=<value>)
+
diff --git a/src/test/ui/panic-runtime/libtest-unwinds.rs b/src/test/ui/panic-runtime/libtest-unwinds.rs
new file mode 100644
index 0000000..47dd8c3
--- /dev/null
+++ b/src/test/ui/panic-runtime/libtest-unwinds.rs
@@ -0,0 +1,11 @@
+// error-pattern:is not compiled with this crate's panic strategy `abort`
+// compile-flags:-C panic=abort
+// ignore-wasm32-bare compiled with panic=abort by default
+
+#![feature(test)]
+
+extern crate test;
+
+fn main() {
+}
+
diff --git a/src/test/ui/panic-runtime/libtest-unwinds.stderr b/src/test/ui/panic-runtime/libtest-unwinds.stderr
new file mode 100644
index 0000000..704b81a
--- /dev/null
+++ b/src/test/ui/panic-runtime/libtest-unwinds.stderr
@@ -0,0 +1,4 @@
+error: the linked panic runtime `panic_unwind` is not compiled with this crate's panic strategy `abort`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/panic-runtime/needs-gate.rs b/src/test/ui/panic-runtime/needs-gate.rs
new file mode 100644
index 0000000..9e143ad
--- /dev/null
+++ b/src/test/ui/panic-runtime/needs-gate.rs
@@ -0,0 +1,7 @@
+// gate-test-needs_panic_runtime
+// gate-test-panic_runtime
+
+#![panic_runtime] //~ ERROR: is an experimental feature
+#![needs_panic_runtime] //~ ERROR: is an experimental feature
+
+fn main() {}
diff --git a/src/test/ui/panic-runtime/needs-gate.stderr b/src/test/ui/panic-runtime/needs-gate.stderr
new file mode 100644
index 0000000..5b8ff82
--- /dev/null
+++ b/src/test/ui/panic-runtime/needs-gate.stderr
@@ -0,0 +1,19 @@
+error[E0658]: the `#[panic_runtime]` attribute is an experimental feature (see issue #32837)
+  --> $DIR/needs-gate.rs:4:1
+   |
+LL | #![panic_runtime]
+   | ^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(panic_runtime)] to the crate attributes to enable
+
+error[E0658]: the `#[needs_panic_runtime]` attribute is an experimental feature (see issue #32837)
+  --> $DIR/needs-gate.rs:5:1
+   |
+LL | #![needs_panic_runtime]
+   | ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(needs_panic_runtime)] to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/panic-runtime/transitive-link-a-bunch.rs b/src/test/ui/panic-runtime/transitive-link-a-bunch.rs
new file mode 100644
index 0000000..9b083a6
--- /dev/null
+++ b/src/test/ui/panic-runtime/transitive-link-a-bunch.rs
@@ -0,0 +1,15 @@
+// aux-build:panic-runtime-unwind.rs
+// aux-build:panic-runtime-abort.rs
+// aux-build:wants-panic-runtime-unwind.rs
+// aux-build:wants-panic-runtime-abort.rs
+// aux-build:panic-runtime-lang-items.rs
+// error-pattern: is not compiled with this crate's panic strategy `unwind`
+// ignore-wasm32-bare compiled with panic=abort by default
+
+#![no_std]
+
+extern crate wants_panic_runtime_unwind;
+extern crate wants_panic_runtime_abort;
+extern crate panic_runtime_lang_items;
+
+fn main() {}
diff --git a/src/test/ui/panic-runtime/transitive-link-a-bunch.stderr b/src/test/ui/panic-runtime/transitive-link-a-bunch.stderr
new file mode 100644
index 0000000..4af754c
--- /dev/null
+++ b/src/test/ui/panic-runtime/transitive-link-a-bunch.stderr
@@ -0,0 +1,10 @@
+error: cannot link together two panic runtimes: panic_runtime_unwind and panic_runtime_abort
+
+error: the linked panic runtime `panic_runtime_abort` is not compiled with this crate's panic strategy `unwind`
+
+error: the crate `wants_panic_runtime_abort` is compiled with the panic strategy `abort` which is incompatible with this crate's strategy of `unwind`
+
+error: the crate `panic_runtime_abort` is compiled with the panic strategy `abort` which is incompatible with this crate's strategy of `unwind`
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/panic-runtime/want-unwind-got-abort.rs b/src/test/ui/panic-runtime/want-unwind-got-abort.rs
new file mode 100644
index 0000000..c9ee8a0
--- /dev/null
+++ b/src/test/ui/panic-runtime/want-unwind-got-abort.rs
@@ -0,0 +1,11 @@
+// error-pattern:is incompatible with this crate's strategy of `unwind`
+// aux-build:panic-runtime-abort.rs
+// aux-build:panic-runtime-lang-items.rs
+// ignore-wasm32-bare compiled with panic=abort by default
+
+#![no_std]
+
+extern crate panic_runtime_abort;
+extern crate panic_runtime_lang_items;
+
+fn main() {}
diff --git a/src/test/ui/panic-runtime/want-unwind-got-abort.stderr b/src/test/ui/panic-runtime/want-unwind-got-abort.stderr
new file mode 100644
index 0000000..d4fd2cc
--- /dev/null
+++ b/src/test/ui/panic-runtime/want-unwind-got-abort.stderr
@@ -0,0 +1,6 @@
+error: the linked panic runtime `panic_runtime_abort` is not compiled with this crate's panic strategy `unwind`
+
+error: the crate `panic_runtime_abort` is compiled with the panic strategy `abort` which is incompatible with this crate's strategy of `unwind`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/panic-runtime/want-unwind-got-abort2.rs b/src/test/ui/panic-runtime/want-unwind-got-abort2.rs
new file mode 100644
index 0000000..5219826
--- /dev/null
+++ b/src/test/ui/panic-runtime/want-unwind-got-abort2.rs
@@ -0,0 +1,12 @@
+// error-pattern:is incompatible with this crate's strategy of `unwind`
+// aux-build:panic-runtime-abort.rs
+// aux-build:wants-panic-runtime-abort.rs
+// aux-build:panic-runtime-lang-items.rs
+// ignore-wasm32-bare compiled with panic=abort by default
+
+#![no_std]
+
+extern crate wants_panic_runtime_abort;
+extern crate panic_runtime_lang_items;
+
+fn main() {}
diff --git a/src/test/ui/panic-runtime/want-unwind-got-abort2.stderr b/src/test/ui/panic-runtime/want-unwind-got-abort2.stderr
new file mode 100644
index 0000000..364a27a
--- /dev/null
+++ b/src/test/ui/panic-runtime/want-unwind-got-abort2.stderr
@@ -0,0 +1,8 @@
+error: the linked panic runtime `panic_runtime_abort` is not compiled with this crate's panic strategy `unwind`
+
+error: the crate `wants_panic_runtime_abort` is compiled with the panic strategy `abort` which is incompatible with this crate's strategy of `unwind`
+
+error: the crate `panic_runtime_abort` is compiled with the panic strategy `abort` which is incompatible with this crate's strategy of `unwind`
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/panic_implementation-closures.rs b/src/test/ui/panic_implementation-closures.rs
new file mode 100644
index 0000000..92c333b
--- /dev/null
+++ b/src/test/ui/panic_implementation-closures.rs
@@ -0,0 +1,10 @@
+// compile-pass
+
+#![crate_type = "rlib"]
+#![no_std]
+
+#[panic_handler]
+pub fn panic_fmt(_: &::core::panic::PanicInfo) -> ! {
+    |x: u8| x;
+    loop {}
+}
diff --git a/src/test/ui/paren-span.rs b/src/test/ui/paren-span.rs
new file mode 100644
index 0000000..24fadb2
--- /dev/null
+++ b/src/test/ui/paren-span.rs
@@ -0,0 +1,21 @@
+// Be smart about span of parenthesized expression in macro.
+
+macro_rules! paren {
+    ($e:expr) => (($e))
+    //            ^^^^ do not highlight here
+}
+
+mod m {
+    pub struct S {
+        x: i32
+    }
+    pub fn make() -> S {
+        S { x: 0 }
+    }
+}
+
+fn main() {
+    let s = m::make();
+    paren!(s.x); //~ ERROR field `x` of struct `m::S` is private
+    //     ^^^ highlight here
+}
diff --git a/src/test/ui/paren-span.stderr b/src/test/ui/paren-span.stderr
new file mode 100644
index 0000000..1413787
--- /dev/null
+++ b/src/test/ui/paren-span.stderr
@@ -0,0 +1,9 @@
+error[E0616]: field `x` of struct `m::S` is private
+  --> $DIR/paren-span.rs:19:12
+   |
+LL |     paren!(s.x);
+   |            ^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0616`.
diff --git a/src/test/ui/parenthesized-deref-suggestion.rs b/src/test/ui/parenthesized-deref-suggestion.rs
new file mode 100644
index 0000000..0b4ccdd
--- /dev/null
+++ b/src/test/ui/parenthesized-deref-suggestion.rs
@@ -0,0 +1,11 @@
+struct Session {
+    opts: u8,
+}
+
+fn main() {
+    let sess: &Session = &Session { opts: 0 };
+    (sess as *const Session).opts; //~ ERROR no field `opts` on type `*const Session`
+
+    let x = [0u32];
+    (x as [u32; 1]).0; //~ ERROR no field `0` on type `[u32; 1]`
+}
diff --git a/src/test/ui/parenthesized-deref-suggestion.stderr b/src/test/ui/parenthesized-deref-suggestion.stderr
new file mode 100644
index 0000000..a165100
--- /dev/null
+++ b/src/test/ui/parenthesized-deref-suggestion.stderr
@@ -0,0 +1,21 @@
+error[E0609]: no field `opts` on type `*const Session`
+  --> $DIR/parenthesized-deref-suggestion.rs:7:30
+   |
+LL |     (sess as *const Session).opts;
+   |                              ^^^^
+help: `(sess as *const Session)` is a raw pointer; try dereferencing it
+   |
+LL |     (*(sess as *const Session)).opts;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0609]: no field `0` on type `[u32; 1]`
+  --> $DIR/parenthesized-deref-suggestion.rs:10:21
+   |
+LL |     (x as [u32; 1]).0;
+   |     ----------------^
+   |     |
+   |     help: instead of using tuple indexing, use array indexing: `(x as [u32; 1])[0]`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0609`.
diff --git a/src/test/ui/parse-error-correct.rs b/src/test/ui/parse-error-correct.rs
new file mode 100644
index 0000000..f167b35
--- /dev/null
+++ b/src/test/ui/parse-error-correct.rs
@@ -0,0 +1,12 @@
+// compile-flags: -Z continue-parse-after-error
+
+// Test that the parser is error correcting missing idents. Despite a parsing
+// error (or two), we still run type checking (and don't get extra errors there).
+
+fn main() {
+    let y = 42;
+    let x = y.;  //~ ERROR unexpected token
+    let x = y.();  //~ ERROR unexpected token
+                   //~^ ERROR expected function, found `{integer}`
+    let x = y.foo; //~ ERROR `{integer}` is a primitive type and therefore doesn't have fields [E061
+}
diff --git a/src/test/ui/parse-error-correct.stderr b/src/test/ui/parse-error-correct.stderr
new file mode 100644
index 0000000..b0d2b2d
--- /dev/null
+++ b/src/test/ui/parse-error-correct.stderr
@@ -0,0 +1,33 @@
+error: unexpected token: `;`
+  --> $DIR/parse-error-correct.rs:8:15
+   |
+LL |     let x = y.;
+   |               ^
+
+error: unexpected token: `(`
+  --> $DIR/parse-error-correct.rs:9:15
+   |
+LL |     let x = y.();
+   |               ^
+
+error[E0618]: expected function, found `{integer}`
+  --> $DIR/parse-error-correct.rs:9:13
+   |
+LL |     let y = 42;
+   |         - `{integer}` defined here
+LL |     let x = y.;
+LL |     let x = y.();
+   |             ^---
+   |             |
+   |             call expression requires function
+
+error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields
+  --> $DIR/parse-error-correct.rs:11:15
+   |
+LL |     let x = y.foo;
+   |               ^^^
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0610, E0618.
+For more information about an error, try `rustc --explain E0610`.
diff --git a/src/test/ui/parser-recovery-1.rs b/src/test/ui/parser-recovery-1.rs
new file mode 100644
index 0000000..21d3604
--- /dev/null
+++ b/src/test/ui/parser-recovery-1.rs
@@ -0,0 +1,15 @@
+// compile-flags: -Z continue-parse-after-error
+
+// Test that we can recover from missing braces in the parser.
+
+trait Foo {
+    fn bar() {
+        let x = foo();
+        //~^ ERROR cannot find function `foo` in this scope
+}
+
+fn main() {
+    let x = y.;
+    //~^ ERROR unexpected token
+    //~| ERROR cannot find value `y` in this scope
+} //~ ERROR this file contains an un-closed delimiter
diff --git a/src/test/ui/parser-recovery-1.stderr b/src/test/ui/parser-recovery-1.stderr
new file mode 100644
index 0000000..cd02710
--- /dev/null
+++ b/src/test/ui/parser-recovery-1.stderr
@@ -0,0 +1,40 @@
+error: this file contains an un-closed delimiter
+  --> $DIR/parser-recovery-1.rs:15:55
+   |
+LL | trait Foo {
+   |           - un-closed delimiter
+LL |     fn bar() {
+   |              - this delimiter might not be properly closed...
+...
+LL | }
+   | - ...as it matches this but it has different indentation
+...
+LL | }
+   |                                                       ^
+
+error: unexpected token: `;`
+  --> $DIR/parser-recovery-1.rs:12:15
+   |
+LL |     let x = y.;
+   |               ^
+
+error[E0425]: cannot find function `foo` in this scope
+  --> $DIR/parser-recovery-1.rs:7:17
+   |
+LL |         let x = foo();
+   |                 ^^^ not found in this scope
+
+error[E0425]: cannot find value `y` in this scope
+  --> $DIR/parser-recovery-1.rs:12:13
+   |
+LL |     let x = y.;
+   |             ^ not found in this scope
+
+error[E0601]: `main` function not found in crate `parser_recovery_1`
+   |
+   = note: consider adding a `main` function to `$DIR/parser-recovery-1.rs`
+
+error: aborting due to 5 previous errors
+
+Some errors occurred: E0425, E0601.
+For more information about an error, try `rustc --explain E0425`.
diff --git a/src/test/ui/parser-recovery-2.rs b/src/test/ui/parser-recovery-2.rs
new file mode 100644
index 0000000..be686cc
--- /dev/null
+++ b/src/test/ui/parser-recovery-2.rs
@@ -0,0 +1,14 @@
+// compile-flags: -Z continue-parse-after-error
+
+// Test that we can recover from mismatched braces in the parser.
+
+trait Foo {
+    fn bar() {
+        let x = foo(); //~ ERROR cannot find function `foo` in this scope
+    ) //~ ERROR incorrect close delimiter: `)`
+}
+
+fn main() {
+    let x = y.;  //~ ERROR unexpected token
+                 //~^ ERROR cannot find value `y` in this scope
+}
diff --git a/src/test/ui/parser-recovery-2.stderr b/src/test/ui/parser-recovery-2.stderr
new file mode 100644
index 0000000..c246fa8
--- /dev/null
+++ b/src/test/ui/parser-recovery-2.stderr
@@ -0,0 +1,30 @@
+error: unexpected token: `;`
+  --> $DIR/parser-recovery-2.rs:12:15
+   |
+LL |     let x = y.;
+   |               ^
+
+error: incorrect close delimiter: `)`
+  --> $DIR/parser-recovery-2.rs:8:5
+   |
+LL |     fn bar() {
+   |              - un-closed delimiter
+LL |         let x = foo();
+LL |     )
+   |     ^ incorrect close delimiter
+
+error[E0425]: cannot find function `foo` in this scope
+  --> $DIR/parser-recovery-2.rs:7:17
+   |
+LL |         let x = foo();
+   |                 ^^^ not found in this scope
+
+error[E0425]: cannot find value `y` in this scope
+  --> $DIR/parser-recovery-2.rs:12:13
+   |
+LL |     let x = y.;
+   |             ^ not found in this scope
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/parser/ascii-only-character-escape.rs b/src/test/ui/parser/ascii-only-character-escape.rs
new file mode 100644
index 0000000..f1b028e
--- /dev/null
+++ b/src/test/ui/parser/ascii-only-character-escape.rs
@@ -0,0 +1,8 @@
+// compile-flags: -Z continue-parse-after-error
+
+fn main() {
+    let x = "\x80"; //~ ERROR may only be used
+    let y = "\xff"; //~ ERROR may only be used
+    let z = "\xe2"; //~ ERROR may only be used
+    let a = b"\x00e2";  // ok because byte literal
+}
diff --git a/src/test/ui/parser/ascii-only-character-escape.stderr b/src/test/ui/parser/ascii-only-character-escape.stderr
new file mode 100644
index 0000000..8a981e8
--- /dev/null
+++ b/src/test/ui/parser/ascii-only-character-escape.stderr
@@ -0,0 +1,20 @@
+error: this form of character escape may only be used with characters in the range [\x00-\x7f]
+  --> $DIR/ascii-only-character-escape.rs:4:16
+   |
+LL |     let x = "\x80";
+   |                ^^
+
+error: this form of character escape may only be used with characters in the range [\x00-\x7f]
+  --> $DIR/ascii-only-character-escape.rs:5:16
+   |
+LL |     let y = "\xff";
+   |                ^^
+
+error: this form of character escape may only be used with characters in the range [\x00-\x7f]
+  --> $DIR/ascii-only-character-escape.rs:6:16
+   |
+LL |     let z = "\xe2";
+   |                ^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/parser/assoc-oddities-1.rs b/src/test/ui/parser/assoc-oddities-1.rs
new file mode 100644
index 0000000..5914805
--- /dev/null
+++ b/src/test/ui/parser/assoc-oddities-1.rs
@@ -0,0 +1,11 @@
+// compile-flags: -Z parse-only
+
+fn main() {
+    // following lines below parse and must not fail
+    x = if c { a } else { b }();
+    x = if true { 1 } else { 0 } as *mut _;
+    // however this does not parse and probably should fail to retain compat?
+    // N.B., `..` here is arbitrary, failure happens/should happen ∀ops that aren’t `=`
+    // see assoc-oddities-2 and assoc-oddities-3
+    ..if c { a } else { b }[n]; //~ ERROR expected one of
+}
diff --git a/src/test/ui/parser/assoc-oddities-1.stderr b/src/test/ui/parser/assoc-oddities-1.stderr
new file mode 100644
index 0000000..376ddf4
--- /dev/null
+++ b/src/test/ui/parser/assoc-oddities-1.stderr
@@ -0,0 +1,8 @@
+error: expected one of `.`, `;`, `?`, or `}`, found `[`
+  --> $DIR/assoc-oddities-1.rs:10:28
+   |
+LL |     ..if c { a } else { b }[n];
+   |                            ^ expected one of `.`, `;`, `?`, or `}` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/assoc-oddities-2.rs b/src/test/ui/parser/assoc-oddities-2.rs
new file mode 100644
index 0000000..3d35aad
--- /dev/null
+++ b/src/test/ui/parser/assoc-oddities-2.rs
@@ -0,0 +1,6 @@
+// compile-flags: -Z parse-only
+
+fn main() {
+    // see assoc-oddities-1 for explanation
+    x..if c { a } else { b }[n]; //~ ERROR expected one of
+}
diff --git a/src/test/ui/parser/assoc-oddities-2.stderr b/src/test/ui/parser/assoc-oddities-2.stderr
new file mode 100644
index 0000000..4b3893d
--- /dev/null
+++ b/src/test/ui/parser/assoc-oddities-2.stderr
@@ -0,0 +1,8 @@
+error: expected one of `.`, `;`, `?`, or `}`, found `[`
+  --> $DIR/assoc-oddities-2.rs:5:29
+   |
+LL |     x..if c { a } else { b }[n];
+   |                             ^ expected one of `.`, `;`, `?`, or `}` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/associated-types-project-from-hrtb-explicit.rs b/src/test/ui/parser/associated-types-project-from-hrtb-explicit.rs
new file mode 100644
index 0000000..ed9c996
--- /dev/null
+++ b/src/test/ui/parser/associated-types-project-from-hrtb-explicit.rs
@@ -0,0 +1,18 @@
+// compile-flags: -Z continue-parse-after-error
+
+// Test you can't use a higher-ranked trait bound inside of a qualified
+// path (just won't parse).
+
+pub trait Foo<T> {
+    type A;
+
+    fn get(&self, t: T) -> Self::A;
+}
+
+fn foo2<I>(x: <I as for<'x> Foo<&'x isize>>::A)
+    //~^ ERROR expected identifier, found keyword `for`
+    //~| ERROR expected one of `::` or `>`
+{
+}
+
+pub fn main() {}
diff --git a/src/test/ui/parser/associated-types-project-from-hrtb-explicit.stderr b/src/test/ui/parser/associated-types-project-from-hrtb-explicit.stderr
new file mode 100644
index 0000000..ceea462
--- /dev/null
+++ b/src/test/ui/parser/associated-types-project-from-hrtb-explicit.stderr
@@ -0,0 +1,18 @@
+error: expected identifier, found keyword `for`
+  --> $DIR/associated-types-project-from-hrtb-explicit.rs:12:21
+   |
+LL | fn foo2<I>(x: <I as for<'x> Foo<&'x isize>>::A)
+   |                     ^^^ expected identifier, found keyword
+help: you can escape reserved keywords to use them as identifiers
+   |
+LL | fn foo2<I>(x: <I as r#for<'x> Foo<&'x isize>>::A)
+   |                     ^^^^^
+
+error: expected one of `::` or `>`, found `Foo`
+  --> $DIR/associated-types-project-from-hrtb-explicit.rs:12:29
+   |
+LL | fn foo2<I>(x: <I as for<'x> Foo<&'x isize>>::A)
+   |                             ^^^ expected one of `::` or `>` here
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/parser/attr-bad-meta-2.rs b/src/test/ui/parser/attr-bad-meta-2.rs
new file mode 100644
index 0000000..cefd336
--- /dev/null
+++ b/src/test/ui/parser/attr-bad-meta-2.rs
@@ -0,0 +1,2 @@
+#[path =] //~ ERROR unexpected token: `]`
+mod m {}
diff --git a/src/test/ui/parser/attr-bad-meta-2.stderr b/src/test/ui/parser/attr-bad-meta-2.stderr
new file mode 100644
index 0000000..ffbfc58
--- /dev/null
+++ b/src/test/ui/parser/attr-bad-meta-2.stderr
@@ -0,0 +1,8 @@
+error: unexpected token: `]`
+  --> $DIR/attr-bad-meta-2.rs:1:8
+   |
+LL | #[path =]
+   |        ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/attr-bad-meta-3.rs b/src/test/ui/parser/attr-bad-meta-3.rs
new file mode 100644
index 0000000..b51e9f2
--- /dev/null
+++ b/src/test/ui/parser/attr-bad-meta-3.rs
@@ -0,0 +1,2 @@
+#[path() token] //~ ERROR expected `]`, found `token`
+mod m {}
diff --git a/src/test/ui/parser/attr-bad-meta-3.stderr b/src/test/ui/parser/attr-bad-meta-3.stderr
new file mode 100644
index 0000000..4fa420c
--- /dev/null
+++ b/src/test/ui/parser/attr-bad-meta-3.stderr
@@ -0,0 +1,8 @@
+error: expected `]`, found `token`
+  --> $DIR/attr-bad-meta-3.rs:1:10
+   |
+LL | #[path() token]
+   |          ^^^^^ expected `]`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/attr-bad-meta.rs b/src/test/ui/parser/attr-bad-meta.rs
new file mode 100644
index 0000000..8001977
--- /dev/null
+++ b/src/test/ui/parser/attr-bad-meta.rs
@@ -0,0 +1,2 @@
+#[path*] //~ ERROR expected one of `(`, `::`, `=`, `[`, `]`, or `{`, found `*`
+mod m {}
diff --git a/src/test/ui/parser/attr-bad-meta.stderr b/src/test/ui/parser/attr-bad-meta.stderr
new file mode 100644
index 0000000..a452df5
--- /dev/null
+++ b/src/test/ui/parser/attr-bad-meta.stderr
@@ -0,0 +1,8 @@
+error: expected one of `(`, `::`, `=`, `[`, `]`, or `{`, found `*`
+  --> $DIR/attr-bad-meta.rs:1:7
+   |
+LL | #[path*]
+   |       ^ expected one of `(`, `::`, `=`, `[`, `]`, or `{` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/attr-before-eof.rs b/src/test/ui/parser/attr-before-eof.rs
new file mode 100644
index 0000000..6af1783
--- /dev/null
+++ b/src/test/ui/parser/attr-before-eof.rs
@@ -0,0 +1,3 @@
+fn main() {}
+
+#[derive(Debug)] //~ERROR expected item after attributes
diff --git a/src/test/ui/parser/attr-before-eof.stderr b/src/test/ui/parser/attr-before-eof.stderr
new file mode 100644
index 0000000..eb5daf8
--- /dev/null
+++ b/src/test/ui/parser/attr-before-eof.stderr
@@ -0,0 +1,8 @@
+error: expected item after attributes
+  --> $DIR/attr-before-eof.rs:3:16
+   |
+LL | #[derive(Debug)]
+   |                ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/attr-dangling-in-fn.rs b/src/test/ui/parser/attr-dangling-in-fn.rs
new file mode 100644
index 0000000..c7c45ba
--- /dev/null
+++ b/src/test/ui/parser/attr-dangling-in-fn.rs
@@ -0,0 +1,8 @@
+// error-pattern:expected statement
+
+fn f() {
+  #[foo = "bar"]
+}
+
+fn main() {
+}
diff --git a/src/test/ui/parser/attr-dangling-in-fn.stderr b/src/test/ui/parser/attr-dangling-in-fn.stderr
new file mode 100644
index 0000000..71488d2
--- /dev/null
+++ b/src/test/ui/parser/attr-dangling-in-fn.stderr
@@ -0,0 +1,8 @@
+error: expected statement after outer attribute
+  --> $DIR/attr-dangling-in-fn.rs:5:1
+   |
+LL | }
+   | ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/attr-dangling-in-mod.rs b/src/test/ui/parser/attr-dangling-in-mod.rs
new file mode 100644
index 0000000..261ed39
--- /dev/null
+++ b/src/test/ui/parser/attr-dangling-in-mod.rs
@@ -0,0 +1,6 @@
+// error-pattern:expected item
+
+fn main() {
+}
+
+#[foo = "bar"]
diff --git a/src/test/ui/parser/attr-dangling-in-mod.stderr b/src/test/ui/parser/attr-dangling-in-mod.stderr
new file mode 100644
index 0000000..d896b61
--- /dev/null
+++ b/src/test/ui/parser/attr-dangling-in-mod.stderr
@@ -0,0 +1,8 @@
+error: expected item after attributes
+  --> $DIR/attr-dangling-in-mod.rs:6:14
+   |
+LL | #[foo = "bar"]
+   |              ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/attr.rs b/src/test/ui/parser/attr.rs
new file mode 100644
index 0000000..91a4abb
--- /dev/null
+++ b/src/test/ui/parser/attr.rs
@@ -0,0 +1,7 @@
+#![feature(lang_items)]
+
+fn main() {}
+
+#![lang = "foo"] //~ ERROR an inner attribute is not permitted in this context
+                 //~| ERROR definition of an unknown language item: `foo`
+fn foo() {}
diff --git a/src/test/ui/parser/attr.stderr b/src/test/ui/parser/attr.stderr
new file mode 100644
index 0000000..5111b40
--- /dev/null
+++ b/src/test/ui/parser/attr.stderr
@@ -0,0 +1,17 @@
+error: an inner attribute is not permitted in this context
+  --> $DIR/attr.rs:5:3
+   |
+LL | #![lang = "foo"]
+   |   ^
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+
+error[E0522]: definition of an unknown language item: `foo`
+  --> $DIR/attr.rs:5:1
+   |
+LL | #![lang = "foo"]
+   | ^^^^^^^^^^^^^^^^ definition of unknown language item `foo`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0522`.
diff --git a/src/test/ui/parser/attrs-after-extern-mod.rs b/src/test/ui/parser/attrs-after-extern-mod.rs
new file mode 100644
index 0000000..4bdd164
--- /dev/null
+++ b/src/test/ui/parser/attrs-after-extern-mod.rs
@@ -0,0 +1,13 @@
+// Constants (static variables) can be used to match in patterns, but mutable
+// statics cannot. This ensures that there's some form of error if this is
+// attempted.
+
+extern crate libc;
+
+extern {
+    static mut rust_dbg_static_mut: libc::c_int;
+    pub fn rust_dbg_static_mut_check_four();
+    #[cfg(stage37)] //~ ERROR expected item after attributes
+}
+
+pub fn main() {}
diff --git a/src/test/ui/parser/attrs-after-extern-mod.stderr b/src/test/ui/parser/attrs-after-extern-mod.stderr
new file mode 100644
index 0000000..cecdab4
--- /dev/null
+++ b/src/test/ui/parser/attrs-after-extern-mod.stderr
@@ -0,0 +1,8 @@
+error: expected item after attributes
+  --> $DIR/attrs-after-extern-mod.rs:10:19
+   |
+LL |     #[cfg(stage37)]
+   |                   ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/bad-char-literals.rs b/src/test/ui/parser/bad-char-literals.rs
new file mode 100644
index 0000000..1c9b597
--- /dev/null
+++ b/src/test/ui/parser/bad-char-literals.rs
Binary files differ
diff --git a/src/test/ui/parser/bad-char-literals.stderr b/src/test/ui/parser/bad-char-literals.stderr
new file mode 100644
index 0000000..8e96ea2
--- /dev/null
+++ b/src/test/ui/parser/bad-char-literals.stderr
Binary files differ
diff --git a/src/test/ui/parser/bad-lit-suffixes.rs b/src/test/ui/parser/bad-lit-suffixes.rs
new file mode 100644
index 0000000..75bed30
--- /dev/null
+++ b/src/test/ui/parser/bad-lit-suffixes.rs
@@ -0,0 +1,29 @@
+// compile-flags: -Z continue-parse-after-error
+
+
+extern
+    "C"suffix //~ ERROR suffixes on an ABI spec are invalid
+    fn foo() {}
+
+extern
+    "C"suffix //~ ERROR suffixes on an ABI spec are invalid
+{}
+
+fn main() {
+    ""suffix; //~ ERROR suffixes on a string literal are invalid
+    b""suffix; //~ ERROR suffixes on a byte string literal are invalid
+    r#""#suffix; //~ ERROR suffixes on a string literal are invalid
+    br#""#suffix; //~ ERROR suffixes on a byte string literal are invalid
+    'a'suffix; //~ ERROR suffixes on a char literal are invalid
+    b'a'suffix; //~ ERROR suffixes on a byte literal are invalid
+
+    1234u1024; //~ ERROR invalid width `1024` for integer literal
+    1234i1024; //~ ERROR invalid width `1024` for integer literal
+    1234f1024; //~ ERROR invalid width `1024` for float literal
+    1234.5f1024; //~ ERROR invalid width `1024` for float literal
+
+    1234suffix; //~ ERROR invalid suffix `suffix` for numeric literal
+    0b101suffix; //~ ERROR invalid suffix `suffix` for numeric literal
+    1.0suffix; //~ ERROR invalid suffix `suffix` for float literal
+    1.0e10suffix; //~ ERROR invalid suffix `suffix` for float literal
+}
diff --git a/src/test/ui/parser/bad-lit-suffixes.stderr b/src/test/ui/parser/bad-lit-suffixes.stderr
new file mode 100644
index 0000000..de194f4
--- /dev/null
+++ b/src/test/ui/parser/bad-lit-suffixes.stderr
@@ -0,0 +1,114 @@
+error: suffixes on an ABI spec are invalid
+  --> $DIR/bad-lit-suffixes.rs:5:5
+   |
+LL |     "C"suffix
+   |     ^^^^^^^^^ invalid suffix `suffix`
+
+error: suffixes on an ABI spec are invalid
+  --> $DIR/bad-lit-suffixes.rs:9:5
+   |
+LL |     "C"suffix
+   |     ^^^^^^^^^ invalid suffix `suffix`
+
+error: suffixes on a string literal are invalid
+  --> $DIR/bad-lit-suffixes.rs:13:5
+   |
+LL |     ""suffix;
+   |     ^^^^^^^^ invalid suffix `suffix`
+
+error: suffixes on a byte string literal are invalid
+  --> $DIR/bad-lit-suffixes.rs:14:5
+   |
+LL |     b""suffix;
+   |     ^^^^^^^^^ invalid suffix `suffix`
+
+error: suffixes on a string literal are invalid
+  --> $DIR/bad-lit-suffixes.rs:15:5
+   |
+LL |     r#""#suffix;
+   |     ^^^^^^^^^^^ invalid suffix `suffix`
+
+error: suffixes on a byte string literal are invalid
+  --> $DIR/bad-lit-suffixes.rs:16:5
+   |
+LL |     br#""#suffix;
+   |     ^^^^^^^^^^^^ invalid suffix `suffix`
+
+error: suffixes on a char literal are invalid
+  --> $DIR/bad-lit-suffixes.rs:17:5
+   |
+LL |     'a'suffix;
+   |     ^^^^^^^^^ invalid suffix `suffix`
+
+error: suffixes on a byte literal are invalid
+  --> $DIR/bad-lit-suffixes.rs:18:5
+   |
+LL |     b'a'suffix;
+   |     ^^^^^^^^^^ invalid suffix `suffix`
+
+error: invalid width `1024` for integer literal
+  --> $DIR/bad-lit-suffixes.rs:20:5
+   |
+LL |     1234u1024;
+   |     ^^^^^^^^^
+   |
+   = help: valid widths are 8, 16, 32, 64 and 128
+
+error: invalid width `1024` for integer literal
+  --> $DIR/bad-lit-suffixes.rs:21:5
+   |
+LL |     1234i1024;
+   |     ^^^^^^^^^
+   |
+   = help: valid widths are 8, 16, 32, 64 and 128
+
+error: invalid width `1024` for float literal
+  --> $DIR/bad-lit-suffixes.rs:22:5
+   |
+LL |     1234f1024;
+   |     ^^^^^^^^^
+   |
+   = help: valid widths are 32 and 64
+
+error: invalid width `1024` for float literal
+  --> $DIR/bad-lit-suffixes.rs:23:5
+   |
+LL |     1234.5f1024;
+   |     ^^^^^^^^^^^
+   |
+   = help: valid widths are 32 and 64
+
+error: invalid suffix `suffix` for numeric literal
+  --> $DIR/bad-lit-suffixes.rs:25:5
+   |
+LL |     1234suffix;
+   |     ^^^^^^^^^^ invalid suffix `suffix`
+   |
+   = help: the suffix must be one of the integral types (`u32`, `isize`, etc)
+
+error: invalid suffix `suffix` for numeric literal
+  --> $DIR/bad-lit-suffixes.rs:26:5
+   |
+LL |     0b101suffix;
+   |     ^^^^^^^^^^^ invalid suffix `suffix`
+   |
+   = help: the suffix must be one of the integral types (`u32`, `isize`, etc)
+
+error: invalid suffix `suffix` for float literal
+  --> $DIR/bad-lit-suffixes.rs:27:5
+   |
+LL |     1.0suffix;
+   |     ^^^^^^^^^ invalid suffix `suffix`
+   |
+   = help: valid suffixes are `f32` and `f64`
+
+error: invalid suffix `suffix` for float literal
+  --> $DIR/bad-lit-suffixes.rs:28:5
+   |
+LL |     1.0e10suffix;
+   |     ^^^^^^^^^^^^ invalid suffix `suffix`
+   |
+   = help: valid suffixes are `f32` and `f64`
+
+error: aborting due to 16 previous errors
+
diff --git a/src/test/ui/parser/bad-match.rs b/src/test/ui/parser/bad-match.rs
new file mode 100644
index 0000000..79bc7ee
--- /dev/null
+++ b/src/test/ui/parser/bad-match.rs
@@ -0,0 +1,4 @@
+fn main() {
+  let isize x = 5; //~ ERROR expected one of `:`, `;`, `=`, or `@`, found `x`
+  match x;
+}
diff --git a/src/test/ui/parser/bad-match.stderr b/src/test/ui/parser/bad-match.stderr
new file mode 100644
index 0000000..2f29b97
--- /dev/null
+++ b/src/test/ui/parser/bad-match.stderr
@@ -0,0 +1,8 @@
+error: expected one of `:`, `;`, `=`, or `@`, found `x`
+  --> $DIR/bad-match.rs:2:13
+   |
+LL |   let isize x = 5;
+   |             ^ expected one of `:`, `;`, `=`, or `@` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/bad-name.rs b/src/test/ui/parser/bad-name.rs
new file mode 100644
index 0000000..9b42716
--- /dev/null
+++ b/src/test/ui/parser/bad-name.rs
@@ -0,0 +1,5 @@
+// error-pattern: expected
+
+fn main() {
+  let x.y::<isize>.z foo;
+}
diff --git a/src/test/ui/parser/bad-name.stderr b/src/test/ui/parser/bad-name.stderr
new file mode 100644
index 0000000..15e61cf
--- /dev/null
+++ b/src/test/ui/parser/bad-name.stderr
@@ -0,0 +1,8 @@
+error: expected one of `:`, `;`, `=`, or `@`, found `.`
+  --> $DIR/bad-name.rs:4:8
+   |
+LL |   let x.y::<isize>.z foo;
+   |        ^ expected one of `:`, `;`, `=`, or `@` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/bad-pointer-type.rs b/src/test/ui/parser/bad-pointer-type.rs
new file mode 100644
index 0000000..59e5e0c
--- /dev/null
+++ b/src/test/ui/parser/bad-pointer-type.rs
@@ -0,0 +1,5 @@
+fn foo(_: *()) {
+    //~^ ERROR expected mut or const in raw pointer type
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/bad-pointer-type.stderr b/src/test/ui/parser/bad-pointer-type.stderr
new file mode 100644
index 0000000..e18c220
--- /dev/null
+++ b/src/test/ui/parser/bad-pointer-type.stderr
@@ -0,0 +1,10 @@
+error: expected mut or const in raw pointer type
+  --> $DIR/bad-pointer-type.rs:1:11
+   |
+LL | fn foo(_: *()) {
+   |           ^ expected mut or const in raw pointer type
+   |
+   = help: use `*mut T` or `*const T` as appropriate
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/bad-value-ident-false.rs b/src/test/ui/parser/bad-value-ident-false.rs
new file mode 100644
index 0000000..4645ab4
--- /dev/null
+++ b/src/test/ui/parser/bad-value-ident-false.rs
@@ -0,0 +1,2 @@
+fn false() { } //~ ERROR expected identifier, found keyword `false`
+fn main() { }
diff --git a/src/test/ui/parser/bad-value-ident-false.stderr b/src/test/ui/parser/bad-value-ident-false.stderr
new file mode 100644
index 0000000..9ddca10
--- /dev/null
+++ b/src/test/ui/parser/bad-value-ident-false.stderr
@@ -0,0 +1,12 @@
+error: expected identifier, found keyword `false`
+  --> $DIR/bad-value-ident-false.rs:1:4
+   |
+LL | fn false() { }
+   |    ^^^^^ expected identifier, found keyword
+help: you can escape reserved keywords to use them as identifiers
+   |
+LL | fn r#false() { }
+   |    ^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/bad-value-ident-true.rs b/src/test/ui/parser/bad-value-ident-true.rs
new file mode 100644
index 0000000..0f64266
--- /dev/null
+++ b/src/test/ui/parser/bad-value-ident-true.rs
@@ -0,0 +1,2 @@
+fn true() { } //~ ERROR expected identifier, found keyword `true`
+fn main() { }
diff --git a/src/test/ui/parser/bad-value-ident-true.stderr b/src/test/ui/parser/bad-value-ident-true.stderr
new file mode 100644
index 0000000..ec497db
--- /dev/null
+++ b/src/test/ui/parser/bad-value-ident-true.stderr
@@ -0,0 +1,12 @@
+error: expected identifier, found keyword `true`
+  --> $DIR/bad-value-ident-true.rs:1:4
+   |
+LL | fn true() { }
+   |    ^^^^ expected identifier, found keyword
+help: you can escape reserved keywords to use them as identifiers
+   |
+LL | fn r#true() { }
+   |    ^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/better-expected.rs b/src/test/ui/parser/better-expected.rs
new file mode 100644
index 0000000..16b61ca
--- /dev/null
+++ b/src/test/ui/parser/better-expected.rs
@@ -0,0 +1,3 @@
+fn main() {
+    let x: [isize 3]; //~ ERROR expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `]`, found `3`
+}
diff --git a/src/test/ui/parser/better-expected.stderr b/src/test/ui/parser/better-expected.stderr
new file mode 100644
index 0000000..d100d01
--- /dev/null
+++ b/src/test/ui/parser/better-expected.stderr
@@ -0,0 +1,10 @@
+error: expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `]`, found `3`
+  --> $DIR/better-expected.rs:2:19
+   |
+LL |     let x: [isize 3];
+   |         -         ^ expected one of 7 possible tokens here
+   |         |
+   |         while parsing the type for `x`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/bind-struct-early-modifiers.rs b/src/test/ui/parser/bind-struct-early-modifiers.rs
new file mode 100644
index 0000000..c4b1937
--- /dev/null
+++ b/src/test/ui/parser/bind-struct-early-modifiers.rs
@@ -0,0 +1,7 @@
+fn main() {
+    struct Foo { x: isize }
+    match (Foo { x: 10 }) {
+        Foo { ref x: ref x } => {}, //~ ERROR expected `,`
+        _ => {}
+    }
+}
diff --git a/src/test/ui/parser/bind-struct-early-modifiers.stderr b/src/test/ui/parser/bind-struct-early-modifiers.stderr
new file mode 100644
index 0000000..03482a4
--- /dev/null
+++ b/src/test/ui/parser/bind-struct-early-modifiers.stderr
@@ -0,0 +1,8 @@
+error: expected `,`
+  --> $DIR/bind-struct-early-modifiers.rs:4:19
+   |
+LL |         Foo { ref x: ref x } => {},
+   |                   ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/bound-single-question-mark.rs b/src/test/ui/parser/bound-single-question-mark.rs
new file mode 100644
index 0000000..64d702d
--- /dev/null
+++ b/src/test/ui/parser/bound-single-question-mark.rs
@@ -0,0 +1 @@
+fn f<T: ?>() {} //~ ERROR expected identifier, found `>`
diff --git a/src/test/ui/parser/bound-single-question-mark.stderr b/src/test/ui/parser/bound-single-question-mark.stderr
new file mode 100644
index 0000000..82937a5
--- /dev/null
+++ b/src/test/ui/parser/bound-single-question-mark.stderr
@@ -0,0 +1,8 @@
+error: expected identifier, found `>`
+  --> $DIR/bound-single-question-mark.rs:1:10
+   |
+LL | fn f<T: ?>() {}
+   |          ^ expected identifier
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/bounds-lifetime-1.rs b/src/test/ui/parser/bounds-lifetime-1.rs
new file mode 100644
index 0000000..e458f64
--- /dev/null
+++ b/src/test/ui/parser/bounds-lifetime-1.rs
@@ -0,0 +1,3 @@
+type A = for<'a 'b> fn(); //~ ERROR expected one of `,`, `:`, or `>`, found `'b`
+
+fn main() {}
diff --git a/src/test/ui/parser/bounds-lifetime-1.stderr b/src/test/ui/parser/bounds-lifetime-1.stderr
new file mode 100644
index 0000000..17d6531
--- /dev/null
+++ b/src/test/ui/parser/bounds-lifetime-1.stderr
@@ -0,0 +1,8 @@
+error: expected one of `,`, `:`, or `>`, found `'b`
+  --> $DIR/bounds-lifetime-1.rs:1:17
+   |
+LL | type A = for<'a 'b> fn();
+   |                 ^^ expected one of `,`, `:`, or `>` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/bounds-lifetime-2.rs b/src/test/ui/parser/bounds-lifetime-2.rs
new file mode 100644
index 0000000..f184107
--- /dev/null
+++ b/src/test/ui/parser/bounds-lifetime-2.rs
@@ -0,0 +1,3 @@
+type A = for<'a + 'b> fn(); //~ ERROR expected one of `,`, `:`, or `>`, found `+`
+
+fn main() {}
diff --git a/src/test/ui/parser/bounds-lifetime-2.stderr b/src/test/ui/parser/bounds-lifetime-2.stderr
new file mode 100644
index 0000000..587e527
--- /dev/null
+++ b/src/test/ui/parser/bounds-lifetime-2.stderr
@@ -0,0 +1,8 @@
+error: expected one of `,`, `:`, or `>`, found `+`
+  --> $DIR/bounds-lifetime-2.rs:1:17
+   |
+LL | type A = for<'a + 'b> fn();
+   |                 ^ expected one of `,`, `:`, or `>` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/bounds-lifetime-where-1.rs b/src/test/ui/parser/bounds-lifetime-where-1.rs
new file mode 100644
index 0000000..f1a002a
--- /dev/null
+++ b/src/test/ui/parser/bounds-lifetime-where-1.rs
@@ -0,0 +1,3 @@
+type A where 'a; //~ ERROR expected `:`, found `;`
+
+fn main() {}
diff --git a/src/test/ui/parser/bounds-lifetime-where-1.stderr b/src/test/ui/parser/bounds-lifetime-where-1.stderr
new file mode 100644
index 0000000..b6bd866
--- /dev/null
+++ b/src/test/ui/parser/bounds-lifetime-where-1.stderr
@@ -0,0 +1,8 @@
+error: expected `:`, found `;`
+  --> $DIR/bounds-lifetime-where-1.rs:1:16
+   |
+LL | type A where 'a;
+   |                ^ expected `:`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/bounds-lifetime-where.rs b/src/test/ui/parser/bounds-lifetime-where.rs
new file mode 100644
index 0000000..acb04e7
--- /dev/null
+++ b/src/test/ui/parser/bounds-lifetime-where.rs
@@ -0,0 +1,10 @@
+type A where 'a: 'b + 'c = u8; // OK
+type A where 'a: 'b, = u8; // OK
+type A where 'a: = u8; // OK
+type A where 'a:, = u8; // OK
+type A where 'a: 'b + 'c = u8; // OK
+type A where = u8; // OK
+type A where 'a: 'b + = u8; // OK
+type A where , = u8; //~ ERROR expected one of `=`, lifetime, or type, found `,`
+
+fn main() {}
diff --git a/src/test/ui/parser/bounds-lifetime-where.stderr b/src/test/ui/parser/bounds-lifetime-where.stderr
new file mode 100644
index 0000000..9507a45
--- /dev/null
+++ b/src/test/ui/parser/bounds-lifetime-where.stderr
@@ -0,0 +1,8 @@
+error: expected one of `=`, lifetime, or type, found `,`
+  --> $DIR/bounds-lifetime-where.rs:8:14
+   |
+LL | type A where , = u8;
+   |              ^ expected one of `=`, lifetime, or type here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/bounds-lifetime.rs b/src/test/ui/parser/bounds-lifetime.rs
new file mode 100644
index 0000000..9225cfc
--- /dev/null
+++ b/src/test/ui/parser/bounds-lifetime.rs
@@ -0,0 +1,11 @@
+type A = for<'a:> fn(); // OK
+type A = for<'a:,> fn(); // OK
+type A = for<'a> fn(); // OK
+type A = for<> fn(); // OK
+type A = for<'a: 'b + 'c> fn(); // OK (rejected later by ast_validation)
+type A = for<'a: 'b,> fn(); // OK(rejected later by ast_validation)
+type A = for<'a: 'b +> fn(); // OK (rejected later by ast_validation)
+type A = for<'a, T> fn(); // OK (rejected later by ast_validation)
+type A = for<,> fn(); //~ ERROR expected one of `>`, `const`, identifier, or lifetime, found `,`
+
+fn main() {}
diff --git a/src/test/ui/parser/bounds-lifetime.stderr b/src/test/ui/parser/bounds-lifetime.stderr
new file mode 100644
index 0000000..facbd28
--- /dev/null
+++ b/src/test/ui/parser/bounds-lifetime.stderr
@@ -0,0 +1,8 @@
+error: expected one of `>`, `const`, identifier, or lifetime, found `,`
+  --> $DIR/bounds-lifetime.rs:9:14
+   |
+LL | type A = for<,> fn();
+   |              ^ expected one of `>`, `const`, identifier, or lifetime here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/bounds-obj-parens.rs b/src/test/ui/parser/bounds-obj-parens.rs
new file mode 100644
index 0000000..cc86879
--- /dev/null
+++ b/src/test/ui/parser/bounds-obj-parens.rs
@@ -0,0 +1,5 @@
+// compile-pass
+
+type A = Box<(Fn(u8) -> u8) + 'static + Send + Sync>; // OK (but see #39318)
+
+fn main() {}
diff --git a/src/test/ui/parser/bounds-type-where.rs b/src/test/ui/parser/bounds-type-where.rs
new file mode 100644
index 0000000..2520ecb
--- /dev/null
+++ b/src/test/ui/parser/bounds-type-where.rs
@@ -0,0 +1,11 @@
+type A where for<'a> for<'b> Trait1 + ?Trait2: 'a + Trait = u8; // OK
+type A where T: Trait, = u8; // OK
+type A where T: = u8; // OK
+type A where T:, = u8; // OK
+type A where T: Trait + Trait = u8; // OK
+type A where = u8; // OK
+type A where T: Trait + = u8; // OK
+type A where T, = u8;
+//~^ ERROR expected one of `!`, `(`, `+`, `::`, `:`, `<`, `==`, or `=`, found `,`
+
+fn main() {}
diff --git a/src/test/ui/parser/bounds-type-where.stderr b/src/test/ui/parser/bounds-type-where.stderr
new file mode 100644
index 0000000..459d5c3
--- /dev/null
+++ b/src/test/ui/parser/bounds-type-where.stderr
@@ -0,0 +1,8 @@
+error: expected one of `!`, `(`, `+`, `::`, `:`, `<`, `==`, or `=`, found `,`
+  --> $DIR/bounds-type-where.rs:8:15
+   |
+LL | type A where T, = u8;
+   |               ^ expected one of 8 possible tokens here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/bounds-type.rs b/src/test/ui/parser/bounds-type.rs
new file mode 100644
index 0000000..360e793
--- /dev/null
+++ b/src/test/ui/parser/bounds-type.rs
@@ -0,0 +1,13 @@
+// compile-flags: -Z parse-only -Z continue-parse-after-error
+
+struct S<
+    T: 'a + Tr, // OK
+    T: Tr + 'a, // OK
+    T: 'a, // OK
+    T:, // OK
+    T: ?for<'a> Trait, // OK
+    T: Tr +, // OK
+    T: ?'a, //~ ERROR `?` may only modify trait bounds, not lifetime bounds
+>;
+
+fn main() {}
diff --git a/src/test/ui/parser/bounds-type.stderr b/src/test/ui/parser/bounds-type.stderr
new file mode 100644
index 0000000..0b714e4
--- /dev/null
+++ b/src/test/ui/parser/bounds-type.stderr
@@ -0,0 +1,8 @@
+error: `?` may only modify trait bounds, not lifetime bounds
+  --> $DIR/bounds-type.rs:10:8
+   |
+LL |     T: ?'a,
+   |        ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/brace-after-qualified-path-in-match.rs b/src/test/ui/parser/brace-after-qualified-path-in-match.rs
new file mode 100644
index 0000000..f415208
--- /dev/null
+++ b/src/test/ui/parser/brace-after-qualified-path-in-match.rs
@@ -0,0 +1,7 @@
+fn main() {
+    match 10 {
+        <T as Trait>::Type{key: value} => (),
+        //~^ ERROR unexpected `{` after qualified path
+        _ => (),
+    }
+}
diff --git a/src/test/ui/parser/brace-after-qualified-path-in-match.stderr b/src/test/ui/parser/brace-after-qualified-path-in-match.stderr
new file mode 100644
index 0000000..4c49e31
--- /dev/null
+++ b/src/test/ui/parser/brace-after-qualified-path-in-match.stderr
@@ -0,0 +1,8 @@
+error: unexpected `{` after qualified path
+  --> $DIR/brace-after-qualified-path-in-match.rs:3:27
+   |
+LL |         <T as Trait>::Type{key: value} => (),
+   |                           ^ unexpected `{` after qualified path
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/byte-literals.rs b/src/test/ui/parser/byte-literals.rs
new file mode 100644
index 0000000..bd358af
--- /dev/null
+++ b/src/test/ui/parser/byte-literals.rs
@@ -0,0 +1,15 @@
+// compile-flags: -Z continue-parse-after-error
+
+
+// ignore-tidy-tab
+
+static FOO: u8 = b'\f';  //~ ERROR unknown byte escape
+
+pub fn main() {
+    b'\f';  //~ ERROR unknown byte escape
+    b'\x0Z';  //~ ERROR invalid character in numeric character escape: Z
+    b'	';  //~ ERROR byte constant must be escaped
+    b''';  //~ ERROR byte constant must be escaped
+    b'é';  //~ ERROR byte constant must be ASCII
+    b'a  //~ ERROR unterminated byte constant
+}
diff --git a/src/test/ui/parser/byte-literals.stderr b/src/test/ui/parser/byte-literals.stderr
new file mode 100644
index 0000000..28385f3
--- /dev/null
+++ b/src/test/ui/parser/byte-literals.stderr
@@ -0,0 +1,44 @@
+error: unknown byte escape: f
+  --> $DIR/byte-literals.rs:6:21
+   |
+LL | static FOO: u8 = b'\f';
+   |                     ^ unknown byte escape
+
+error: unknown byte escape: f
+  --> $DIR/byte-literals.rs:9:8
+   |
+LL |     b'\f';
+   |        ^ unknown byte escape
+
+error: invalid character in numeric character escape: Z
+  --> $DIR/byte-literals.rs:10:10
+   |
+LL |     b'\x0Z';
+   |          ^
+
+error: byte constant must be escaped: \t
+  --> $DIR/byte-literals.rs:11:7
+   |
+LL |     b'    ';
+   |       ^^^^
+
+error: byte constant must be escaped: '
+  --> $DIR/byte-literals.rs:12:7
+   |
+LL |     b''';
+   |       ^
+
+error: byte constant must be ASCII. Use a \xHH escape for a non-ASCII byte
+  --> $DIR/byte-literals.rs:13:7
+   |
+LL |     b'é';
+   |       ^
+
+error: unterminated byte constant: b'a
+  --> $DIR/byte-literals.rs:14:5
+   |
+LL |     b'a
+   |     ^^^
+
+error: aborting due to 7 previous errors
+
diff --git a/src/test/ui/parser/byte-string-literals.rs b/src/test/ui/parser/byte-string-literals.rs
new file mode 100644
index 0000000..d028f28
--- /dev/null
+++ b/src/test/ui/parser/byte-string-literals.rs
@@ -0,0 +1,13 @@
+// compile-flags: -Z continue-parse-after-error
+
+
+// ignore-tidy-tab
+
+static FOO: &'static [u8] = b"\f";  //~ ERROR unknown byte escape
+
+pub fn main() {
+    b"\f";  //~ ERROR unknown byte escape
+    b"\x0Z";  //~ ERROR invalid character in numeric character escape: Z
+    b"é";  //~ ERROR byte constant must be ASCII
+    b"a  //~ ERROR unterminated double quote byte string
+}
diff --git a/src/test/ui/parser/byte-string-literals.stderr b/src/test/ui/parser/byte-string-literals.stderr
new file mode 100644
index 0000000..6701cfd
--- /dev/null
+++ b/src/test/ui/parser/byte-string-literals.stderr
@@ -0,0 +1,34 @@
+error: unknown byte escape: f
+  --> $DIR/byte-string-literals.rs:6:32
+   |
+LL | static FOO: &'static [u8] = b"\f";
+   |                                ^ unknown byte escape
+
+error: unknown byte escape: f
+  --> $DIR/byte-string-literals.rs:9:8
+   |
+LL |     b"\f";
+   |        ^ unknown byte escape
+
+error: invalid character in numeric character escape: Z
+  --> $DIR/byte-string-literals.rs:10:10
+   |
+LL |     b"\x0Z";
+   |          ^
+
+error: byte constant must be ASCII. Use a \xHH escape for a non-ASCII byte
+  --> $DIR/byte-string-literals.rs:11:7
+   |
+LL |     b"é";
+   |       ^
+
+error: unterminated double quote byte string
+  --> $DIR/byte-string-literals.rs:12:7
+   |
+LL |       b"a
+   |  _______^
+LL | | }
+   | |__^
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/ui/parser/circular_modules_hello.rs b/src/test/ui/parser/circular_modules_hello.rs
new file mode 100644
index 0000000..6968ca9
--- /dev/null
+++ b/src/test/ui/parser/circular_modules_hello.rs
@@ -0,0 +1,8 @@
+// ignore-test: this is an auxiliary file for circular-modules-main.rs
+
+#[path = "circular_modules_main.rs"]
+mod circular_modules_main;
+
+pub fn say_hello() {
+    println!("{}", circular_modules_main::hi_str());
+}
diff --git a/src/test/ui/parser/circular_modules_main.rs b/src/test/ui/parser/circular_modules_main.rs
new file mode 100644
index 0000000..b85003b
--- /dev/null
+++ b/src/test/ui/parser/circular_modules_main.rs
@@ -0,0 +1,10 @@
+#[path = "circular_modules_hello.rs"]
+mod circular_modules_hello; //~ ERROR: circular modules
+
+pub fn hi_str() -> String {
+    "Hi!".to_string()
+}
+
+fn main() {
+    circular_modules_hello::say_hello();
+}
diff --git a/src/test/ui/parser/circular_modules_main.stderr b/src/test/ui/parser/circular_modules_main.stderr
new file mode 100644
index 0000000..33865fb
--- /dev/null
+++ b/src/test/ui/parser/circular_modules_main.stderr
@@ -0,0 +1,8 @@
+error: circular modules: $DIR/circular_modules_hello.rs -> $DIR/circular_modules_main.rs -> $DIR/circular_modules_hello.rs
+  --> $DIR/circular_modules_main.rs:2:5
+   |
+LL | mod circular_modules_hello;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/class-implements-bad-trait.rs b/src/test/ui/parser/class-implements-bad-trait.rs
new file mode 100644
index 0000000..f2f85d0
--- /dev/null
+++ b/src/test/ui/parser/class-implements-bad-trait.rs
@@ -0,0 +1,9 @@
+// error-pattern:nonexistent
+class cat : nonexistent {
+  let meows: usize;
+  new(in_x : usize) { self.meows = in_x; }
+}
+
+fn main() {
+  let nyan = cat(0);
+}
diff --git a/src/test/ui/parser/class-implements-bad-trait.stderr b/src/test/ui/parser/class-implements-bad-trait.stderr
new file mode 100644
index 0000000..4558346
--- /dev/null
+++ b/src/test/ui/parser/class-implements-bad-trait.stderr
@@ -0,0 +1,8 @@
+error: expected one of `!` or `::`, found `cat`
+  --> $DIR/class-implements-bad-trait.rs:2:7
+   |
+LL | class cat : nonexistent {
+   |       ^^^ expected one of `!` or `::` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/closure-return-syntax.rs b/src/test/ui/parser/closure-return-syntax.rs
new file mode 100644
index 0000000..54eb791
--- /dev/null
+++ b/src/test/ui/parser/closure-return-syntax.rs
@@ -0,0 +1,7 @@
+// Test that we cannot parse a closure with an explicit return type
+// unless it uses braces.
+
+fn main() {
+    let x = || -> i32 22;
+    //~^ ERROR expected one of `!`, `(`, `+`, `::`, `<`, or `{`, found `22`
+}
diff --git a/src/test/ui/parser/closure-return-syntax.stderr b/src/test/ui/parser/closure-return-syntax.stderr
new file mode 100644
index 0000000..dd7ebff
--- /dev/null
+++ b/src/test/ui/parser/closure-return-syntax.stderr
@@ -0,0 +1,8 @@
+error: expected one of `!`, `(`, `+`, `::`, `<`, or `{`, found `22`
+  --> $DIR/closure-return-syntax.rs:5:23
+   |
+LL |     let x = || -> i32 22;
+   |                       ^^ expected one of `!`, `(`, `+`, `::`, `<`, or `{` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/column-offset-1-based.rs b/src/test/ui/parser/column-offset-1-based.rs
new file mode 100644
index 0000000..e158e52
--- /dev/null
+++ b/src/test/ui/parser/column-offset-1-based.rs
@@ -0,0 +1 @@
+# //~ ERROR expected `[`, found `<eof>`
diff --git a/src/test/ui/parser/column-offset-1-based.stderr b/src/test/ui/parser/column-offset-1-based.stderr
new file mode 100644
index 0000000..5cbf3d3
--- /dev/null
+++ b/src/test/ui/parser/column-offset-1-based.stderr
@@ -0,0 +1,8 @@
+error: expected `[`, found `<eof>`
+  --> $DIR/column-offset-1-based.rs:1:1
+   |
+LL | #
+   | ^ expected `[`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/default.rs b/src/test/ui/parser/default.rs
new file mode 100644
index 0000000..17cd068
--- /dev/null
+++ b/src/test/ui/parser/default.rs
@@ -0,0 +1,25 @@
+// Test successful and unsuccessful parsing of the `default` contextual keyword
+
+#![feature(specialization)]
+
+trait Foo {
+    fn foo<T: Default>() -> T;
+}
+
+impl Foo for u8 {
+    default fn foo<T: Default>() -> T {
+        T::default()
+    }
+}
+
+impl Foo for u16 {
+    pub default fn foo<T: Default>() -> T { //~ ERROR unnecessary visibility qualifier
+        T::default()
+    }
+}
+
+impl Foo for u32 { //~ ERROR not all trait items implemented, missing: `foo`
+    default pub fn foo<T: Default>() -> T { T::default() } //~ ERROR expected one of
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/default.stderr b/src/test/ui/parser/default.stderr
new file mode 100644
index 0000000..c43fffd
--- /dev/null
+++ b/src/test/ui/parser/default.stderr
@@ -0,0 +1,25 @@
+error: expected one of `async`, `const`, `existential`, `extern`, `fn`, `type`, or `unsafe`, found `pub`
+  --> $DIR/default.rs:22:13
+   |
+LL |     default pub fn foo<T: Default>() -> T { T::default() }
+   |             ^^^ expected one of 7 possible tokens here
+
+error[E0449]: unnecessary visibility qualifier
+  --> $DIR/default.rs:16:5
+   |
+LL |     pub default fn foo<T: Default>() -> T {
+   |     ^^^ `pub` not permitted here because it's implied
+
+error[E0046]: not all trait items implemented, missing: `foo`
+  --> $DIR/default.rs:21:1
+   |
+LL |     fn foo<T: Default>() -> T;
+   |     -------------------------- `foo` from trait
+...
+LL | impl Foo for u32 {
+   | ^^^^^^^^^^^^^^^^ missing `foo` in implementation
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0046, E0449.
+For more information about an error, try `rustc --explain E0046`.
diff --git a/src/test/ui/parser/do-catch-suggests-try.rs b/src/test/ui/parser/do-catch-suggests-try.rs
new file mode 100644
index 0000000..61fae72
--- /dev/null
+++ b/src/test/ui/parser/do-catch-suggests-try.rs
@@ -0,0 +1,5 @@
+fn main() {
+    let _: Option<()> = do catch {};
+    //~^ ERROR found removed `do catch` syntax
+    //~^^ HELP Following RFC #2388, the new non-placeholder syntax is `try`
+}
diff --git a/src/test/ui/parser/do-catch-suggests-try.stderr b/src/test/ui/parser/do-catch-suggests-try.stderr
new file mode 100644
index 0000000..6d13b0f
--- /dev/null
+++ b/src/test/ui/parser/do-catch-suggests-try.stderr
@@ -0,0 +1,10 @@
+error: found removed `do catch` syntax
+  --> $DIR/do-catch-suggests-try.rs:2:25
+   |
+LL |     let _: Option<()> = do catch {};
+   |                         ^^
+   |
+   = help: Following RFC #2388, the new non-placeholder syntax is `try`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/doc-after-struct-field.rs b/src/test/ui/parser/doc-after-struct-field.rs
new file mode 100644
index 0000000..7870555
--- /dev/null
+++ b/src/test/ui/parser/doc-after-struct-field.rs
@@ -0,0 +1,18 @@
+// compile-flags: -Z continue-parse-after-error
+
+struct X {
+    a: u8 /** document a */,
+    //~^ ERROR found a documentation comment that doesn't document anything
+    //~| HELP maybe a comment was intended
+}
+
+struct Y {
+    a: u8 /// document a
+    //~^ ERROR found a documentation comment that doesn't document anything
+    //~| HELP maybe a comment was intended
+}
+
+fn main() {
+    let x = X { a: 1 };
+    let y = Y { a: 1 };
+}
diff --git a/src/test/ui/parser/doc-after-struct-field.stderr b/src/test/ui/parser/doc-after-struct-field.stderr
new file mode 100644
index 0000000..b84f353
--- /dev/null
+++ b/src/test/ui/parser/doc-after-struct-field.stderr
@@ -0,0 +1,19 @@
+error[E0585]: found a documentation comment that doesn't document anything
+  --> $DIR/doc-after-struct-field.rs:4:11
+   |
+LL |     a: u8 /** document a */,
+   |           ^^^^^^^^^^^^^^^^^
+   |
+   = help: doc comments must come before what they document, maybe a comment was intended with `//`?
+
+error[E0585]: found a documentation comment that doesn't document anything
+  --> $DIR/doc-after-struct-field.rs:10:11
+   |
+LL |     a: u8 /// document a
+   |           ^^^^^^^^^^^^^^
+   |
+   = help: doc comments must come before what they document, maybe a comment was intended with `//`?
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0585`.
diff --git a/src/test/ui/parser/doc-before-attr.rs b/src/test/ui/parser/doc-before-attr.rs
new file mode 100644
index 0000000..c4125a0
--- /dev/null
+++ b/src/test/ui/parser/doc-before-attr.rs
@@ -0,0 +1,4 @@
+fn main() {}
+
+/// hi
+#[derive(Debug)] //~ERROR expected item after attributes
diff --git a/src/test/ui/parser/doc-before-attr.stderr b/src/test/ui/parser/doc-before-attr.stderr
new file mode 100644
index 0000000..0fae44c
--- /dev/null
+++ b/src/test/ui/parser/doc-before-attr.stderr
@@ -0,0 +1,8 @@
+error: expected item after attributes
+  --> $DIR/doc-before-attr.rs:4:16
+   |
+LL | #[derive(Debug)]
+   |                ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/doc-before-eof.rs b/src/test/ui/parser/doc-before-eof.rs
new file mode 100644
index 0000000..b31836e
--- /dev/null
+++ b/src/test/ui/parser/doc-before-eof.rs
@@ -0,0 +1,3 @@
+fn main() {}
+
+/// hi //~ERROR expected item after doc comment
diff --git a/src/test/ui/parser/doc-before-eof.stderr b/src/test/ui/parser/doc-before-eof.stderr
new file mode 100644
index 0000000..8275662
--- /dev/null
+++ b/src/test/ui/parser/doc-before-eof.stderr
@@ -0,0 +1,8 @@
+error: expected item after doc comment
+  --> $DIR/doc-before-eof.rs:3:1
+   |
+LL | /// hi
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this doc comment doesn't document anything
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/doc-before-extern-rbrace.rs b/src/test/ui/parser/doc-before-extern-rbrace.rs
new file mode 100644
index 0000000..695d4da
--- /dev/null
+++ b/src/test/ui/parser/doc-before-extern-rbrace.rs
@@ -0,0 +1,4 @@
+extern {
+    /// hi
+    //~^ ERROR expected item after doc comment
+}
diff --git a/src/test/ui/parser/doc-before-extern-rbrace.stderr b/src/test/ui/parser/doc-before-extern-rbrace.stderr
new file mode 100644
index 0000000..8cc9c91
--- /dev/null
+++ b/src/test/ui/parser/doc-before-extern-rbrace.stderr
@@ -0,0 +1,8 @@
+error: expected item after doc comment
+  --> $DIR/doc-before-extern-rbrace.rs:2:5
+   |
+LL |     /// hi
+   |     ^^^^^^ this doc comment doesn't document anything
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/doc-before-fn-rbrace.rs b/src/test/ui/parser/doc-before-fn-rbrace.rs
new file mode 100644
index 0000000..d33520b
--- /dev/null
+++ b/src/test/ui/parser/doc-before-fn-rbrace.rs
@@ -0,0 +1,7 @@
+// compile-flags: -Z continue-parse-after-error
+
+fn main() {
+    /// document
+    //~^ ERROR found a documentation comment that doesn't document anything
+    //~| HELP maybe a comment was intended
+}
diff --git a/src/test/ui/parser/doc-before-fn-rbrace.stderr b/src/test/ui/parser/doc-before-fn-rbrace.stderr
new file mode 100644
index 0000000..a1ca88c
--- /dev/null
+++ b/src/test/ui/parser/doc-before-fn-rbrace.stderr
@@ -0,0 +1,11 @@
+error[E0585]: found a documentation comment that doesn't document anything
+  --> $DIR/doc-before-fn-rbrace.rs:4:5
+   |
+LL |     /// document
+   |     ^^^^^^^^^^^^
+   |
+   = help: doc comments must come before what they document, maybe a comment was intended with `//`?
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0585`.
diff --git a/src/test/ui/parser/doc-before-identifier.rs b/src/test/ui/parser/doc-before-identifier.rs
new file mode 100644
index 0000000..d9777be
--- /dev/null
+++ b/src/test/ui/parser/doc-before-identifier.rs
@@ -0,0 +1,9 @@
+// compile-flags: -Z continue-parse-after-error
+
+fn /// document
+foo() {}
+//~^^ ERROR expected identifier, found doc comment `/// document`
+
+fn main() {
+    foo();
+}
diff --git a/src/test/ui/parser/doc-before-identifier.stderr b/src/test/ui/parser/doc-before-identifier.stderr
new file mode 100644
index 0000000..4bc5e6f
--- /dev/null
+++ b/src/test/ui/parser/doc-before-identifier.stderr
@@ -0,0 +1,8 @@
+error: expected identifier, found doc comment `/// document`
+  --> $DIR/doc-before-identifier.rs:3:4
+   |
+LL | fn /// document
+   |    ^^^^^^^^^^^^ expected identifier, found doc comment
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/doc-before-mod-rbrace.rs b/src/test/ui/parser/doc-before-mod-rbrace.rs
new file mode 100644
index 0000000..4e0b65e
--- /dev/null
+++ b/src/test/ui/parser/doc-before-mod-rbrace.rs
@@ -0,0 +1,8 @@
+// compile-flags: -Z continue-parse-after-error
+
+mod Foo {
+    /// document
+    //~^ ERROR expected item after doc comment
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/doc-before-mod-rbrace.stderr b/src/test/ui/parser/doc-before-mod-rbrace.stderr
new file mode 100644
index 0000000..4eaf351
--- /dev/null
+++ b/src/test/ui/parser/doc-before-mod-rbrace.stderr
@@ -0,0 +1,8 @@
+error: expected item after doc comment
+  --> $DIR/doc-before-mod-rbrace.rs:4:5
+   |
+LL |     /// document
+   |     ^^^^^^^^^^^^ this doc comment doesn't document anything
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/doc-before-rbrace.rs b/src/test/ui/parser/doc-before-rbrace.rs
new file mode 100644
index 0000000..8ff9463
--- /dev/null
+++ b/src/test/ui/parser/doc-before-rbrace.rs
@@ -0,0 +1,5 @@
+fn main() {
+    println!("Hi"); /// hi
+    //~^ ERROR found a documentation comment that doesn't document anything
+    //~| HELP maybe a comment was intended
+}
diff --git a/src/test/ui/parser/doc-before-rbrace.stderr b/src/test/ui/parser/doc-before-rbrace.stderr
new file mode 100644
index 0000000..55719cf
--- /dev/null
+++ b/src/test/ui/parser/doc-before-rbrace.stderr
@@ -0,0 +1,11 @@
+error[E0585]: found a documentation comment that doesn't document anything
+  --> $DIR/doc-before-rbrace.rs:2:21
+   |
+LL |     println!("Hi"); /// hi
+   |                     ^^^^^^
+   |
+   = help: doc comments must come before what they document, maybe a comment was intended with `//`?
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0585`.
diff --git a/src/test/ui/parser/doc-before-semi.rs b/src/test/ui/parser/doc-before-semi.rs
new file mode 100644
index 0000000..405a7e1
--- /dev/null
+++ b/src/test/ui/parser/doc-before-semi.rs
@@ -0,0 +1,6 @@
+fn main() {
+    /// hi
+    //~^ ERROR found a documentation comment that doesn't document anything
+    //~| HELP maybe a comment was intended
+    ;
+}
diff --git a/src/test/ui/parser/doc-before-semi.stderr b/src/test/ui/parser/doc-before-semi.stderr
new file mode 100644
index 0000000..e6bade1
--- /dev/null
+++ b/src/test/ui/parser/doc-before-semi.stderr
@@ -0,0 +1,11 @@
+error[E0585]: found a documentation comment that doesn't document anything
+  --> $DIR/doc-before-semi.rs:2:5
+   |
+LL |     /// hi
+   |     ^^^^^^
+   |
+   = help: doc comments must come before what they document, maybe a comment was intended with `//`?
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0585`.
diff --git a/src/test/ui/parser/doc-before-struct-rbrace-1.rs b/src/test/ui/parser/doc-before-struct-rbrace-1.rs
new file mode 100644
index 0000000..e7055f6
--- /dev/null
+++ b/src/test/ui/parser/doc-before-struct-rbrace-1.rs
@@ -0,0 +1,12 @@
+// compile-flags: -Z continue-parse-after-error
+
+struct X {
+    a: u8,
+    /// document
+    //~^ ERROR found a documentation comment that doesn't document anything
+    //~| HELP maybe a comment was intended
+}
+
+fn main() {
+    let y = X {a: 1};
+}
diff --git a/src/test/ui/parser/doc-before-struct-rbrace-1.stderr b/src/test/ui/parser/doc-before-struct-rbrace-1.stderr
new file mode 100644
index 0000000..f2824f8
--- /dev/null
+++ b/src/test/ui/parser/doc-before-struct-rbrace-1.stderr
@@ -0,0 +1,11 @@
+error[E0585]: found a documentation comment that doesn't document anything
+  --> $DIR/doc-before-struct-rbrace-1.rs:5:5
+   |
+LL |     /// document
+   |     ^^^^^^^^^^^^
+   |
+   = help: doc comments must come before what they document, maybe a comment was intended with `//`?
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0585`.
diff --git a/src/test/ui/parser/doc-before-struct-rbrace-2.rs b/src/test/ui/parser/doc-before-struct-rbrace-2.rs
new file mode 100644
index 0000000..d5c2a31
--- /dev/null
+++ b/src/test/ui/parser/doc-before-struct-rbrace-2.rs
@@ -0,0 +1,11 @@
+// compile-flags: -Z continue-parse-after-error
+
+struct X {
+    a: u8 /// document
+    //~^ ERROR found a documentation comment that doesn't document anything
+    //~| HELP maybe a comment was intended
+}
+
+fn main() {
+    let y = X {a: 1};
+}
diff --git a/src/test/ui/parser/doc-before-struct-rbrace-2.stderr b/src/test/ui/parser/doc-before-struct-rbrace-2.stderr
new file mode 100644
index 0000000..ba3e884
--- /dev/null
+++ b/src/test/ui/parser/doc-before-struct-rbrace-2.stderr
@@ -0,0 +1,11 @@
+error[E0585]: found a documentation comment that doesn't document anything
+  --> $DIR/doc-before-struct-rbrace-2.rs:4:11
+   |
+LL |     a: u8 /// document
+   |           ^^^^^^^^^^^^
+   |
+   = help: doc comments must come before what they document, maybe a comment was intended with `//`?
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0585`.
diff --git a/src/test/ui/parser/doc-comment-in-if-statement.rs b/src/test/ui/parser/doc-comment-in-if-statement.rs
new file mode 100644
index 0000000..c85fe25
--- /dev/null
+++ b/src/test/ui/parser/doc-comment-in-if-statement.rs
@@ -0,0 +1,4 @@
+fn main() {
+    if true /*!*/ {}
+    //~^ ERROR expected `{`, found doc comment `/*!*/`
+}
diff --git a/src/test/ui/parser/doc-comment-in-if-statement.stderr b/src/test/ui/parser/doc-comment-in-if-statement.stderr
new file mode 100644
index 0000000..6bcb773
--- /dev/null
+++ b/src/test/ui/parser/doc-comment-in-if-statement.stderr
@@ -0,0 +1,10 @@
+error: expected `{`, found doc comment `/*!*/`
+  --> $DIR/doc-comment-in-if-statement.rs:2:13
+   |
+LL |     if true /*!*/ {}
+   |     --      ^^^^^ expected `{`
+   |     |
+   |     this `if` statement has a condition, but no block
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/doc-inside-trait-item.rs b/src/test/ui/parser/doc-inside-trait-item.rs
new file mode 100644
index 0000000..87b501b
--- /dev/null
+++ b/src/test/ui/parser/doc-inside-trait-item.rs
@@ -0,0 +1,6 @@
+trait User{
+    fn test();
+    /// empty doc
+    //~^ ERROR found a documentation comment that doesn't document anything
+}
+fn main() {}
diff --git a/src/test/ui/parser/doc-inside-trait-item.stderr b/src/test/ui/parser/doc-inside-trait-item.stderr
new file mode 100644
index 0000000..261e27b
--- /dev/null
+++ b/src/test/ui/parser/doc-inside-trait-item.stderr
@@ -0,0 +1,11 @@
+error[E0584]: found a documentation comment that doesn't document anything
+  --> $DIR/doc-inside-trait-item.rs:3:5
+   |
+LL |     /// empty doc
+   |     ^^^^^^^^^^^^^
+   |
+   = help: doc comments must come before what they document, maybe a comment was intended with `//`?
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0584`.
diff --git a/src/test/ui/parser/duplicate-visibility.rs b/src/test/ui/parser/duplicate-visibility.rs
new file mode 100644
index 0000000..bb17e97
--- /dev/null
+++ b/src/test/ui/parser/duplicate-visibility.rs
@@ -0,0 +1,4 @@
+// error-pattern:expected one of `(`, `fn`, `static`, or `type`
+extern {
+    pub pub fn foo();
+}
diff --git a/src/test/ui/parser/duplicate-visibility.stderr b/src/test/ui/parser/duplicate-visibility.stderr
new file mode 100644
index 0000000..880b536
--- /dev/null
+++ b/src/test/ui/parser/duplicate-visibility.stderr
@@ -0,0 +1,8 @@
+error: expected one of `(`, `fn`, `static`, or `type`, found `pub`
+  --> $DIR/duplicate-visibility.rs:3:9
+   |
+LL |     pub pub fn foo();
+   |         ^^^ expected one of `(`, `fn`, `static`, or `type` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/empty-impl-semicolon.rs b/src/test/ui/parser/empty-impl-semicolon.rs
new file mode 100644
index 0000000..207ebef
--- /dev/null
+++ b/src/test/ui/parser/empty-impl-semicolon.rs
@@ -0,0 +1 @@
+impl Foo; //~ ERROR expected one of `!`, `(`, `+`, `::`, `<`, `for`, `where`, or `{`, found `;`
diff --git a/src/test/ui/parser/empty-impl-semicolon.stderr b/src/test/ui/parser/empty-impl-semicolon.stderr
new file mode 100644
index 0000000..46f2393
--- /dev/null
+++ b/src/test/ui/parser/empty-impl-semicolon.stderr
@@ -0,0 +1,8 @@
+error: expected one of `!`, `(`, `+`, `::`, `<`, `for`, `where`, or `{`, found `;`
+  --> $DIR/empty-impl-semicolon.rs:1:9
+   |
+LL | impl Foo;
+   |         ^ expected one of 8 possible tokens here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/extern-crate-unexpected-token.rs b/src/test/ui/parser/extern-crate-unexpected-token.rs
new file mode 100644
index 0000000..58b2fa1
--- /dev/null
+++ b/src/test/ui/parser/extern-crate-unexpected-token.rs
@@ -0,0 +1 @@
+extern crte foo; //~ ERROR expected one of `crate`, `fn`, or `{`, found `crte`
diff --git a/src/test/ui/parser/extern-crate-unexpected-token.stderr b/src/test/ui/parser/extern-crate-unexpected-token.stderr
new file mode 100644
index 0000000..04edd46
--- /dev/null
+++ b/src/test/ui/parser/extern-crate-unexpected-token.stderr
@@ -0,0 +1,8 @@
+error: expected one of `crate`, `fn`, or `{`, found `crte`
+  --> $DIR/extern-crate-unexpected-token.rs:1:8
+   |
+LL | extern crte foo;
+   |        ^^^^ expected one of `crate`, `fn`, or `{` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/extern-expected-fn-or-brace.rs b/src/test/ui/parser/extern-expected-fn-or-brace.rs
new file mode 100644
index 0000000..dd46b87
--- /dev/null
+++ b/src/test/ui/parser/extern-expected-fn-or-brace.rs
@@ -0,0 +1,4 @@
+// Verifies that the expected token errors for `extern crate` are
+// raised
+
+extern "C" mod foo; //~ERROR expected one of `fn` or `{`, found `mod`
diff --git a/src/test/ui/parser/extern-expected-fn-or-brace.stderr b/src/test/ui/parser/extern-expected-fn-or-brace.stderr
new file mode 100644
index 0000000..0fb9935
--- /dev/null
+++ b/src/test/ui/parser/extern-expected-fn-or-brace.stderr
@@ -0,0 +1,8 @@
+error: expected one of `fn` or `{`, found `mod`
+  --> $DIR/extern-expected-fn-or-brace.rs:4:12
+   |
+LL | extern "C" mod foo;
+   |            ^^^ expected one of `fn` or `{` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/extern-foreign-crate.rs b/src/test/ui/parser/extern-foreign-crate.rs
new file mode 100644
index 0000000..a5da77d
--- /dev/null
+++ b/src/test/ui/parser/extern-foreign-crate.rs
@@ -0,0 +1,4 @@
+// Verifies that the expected token errors for `extern crate` are
+// raised
+
+extern crate foo {} //~ERROR expected one of `;` or `as`, found `{`
diff --git a/src/test/ui/parser/extern-foreign-crate.stderr b/src/test/ui/parser/extern-foreign-crate.stderr
new file mode 100644
index 0000000..de9f0c9
--- /dev/null
+++ b/src/test/ui/parser/extern-foreign-crate.stderr
@@ -0,0 +1,8 @@
+error: expected one of `;` or `as`, found `{`
+  --> $DIR/extern-foreign-crate.rs:4:18
+   |
+LL | extern crate foo {}
+   |                  ^ expected one of `;` or `as` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/extern-no-fn.rs b/src/test/ui/parser/extern-no-fn.rs
new file mode 100644
index 0000000..c37ddd6
--- /dev/null
+++ b/src/test/ui/parser/extern-no-fn.rs
@@ -0,0 +1,6 @@
+extern { //~ ERROR missing `fn`, `type`, or `static` for extern-item declaration
+    f();
+}
+
+fn main() {
+}
diff --git a/src/test/ui/parser/extern-no-fn.stderr b/src/test/ui/parser/extern-no-fn.stderr
new file mode 100644
index 0000000..d2d5e3c
--- /dev/null
+++ b/src/test/ui/parser/extern-no-fn.stderr
@@ -0,0 +1,10 @@
+error: missing `fn`, `type`, or `static` for extern-item declaration
+  --> $DIR/extern-no-fn.rs:1:9
+   |
+LL |   extern {
+   |  _________^
+LL | |     f();
+   | |____^ missing `fn`, `type`, or `static`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/fn-arg-doc-comment.rs b/src/test/ui/parser/fn-arg-doc-comment.rs
new file mode 100644
index 0000000..22af94b
--- /dev/null
+++ b/src/test/ui/parser/fn-arg-doc-comment.rs
@@ -0,0 +1,37 @@
+pub fn f(
+    /// Comment
+    //~^ ERROR documentation comments cannot be applied to method arguments
+    //~| NOTE doc comments are not allowed here
+    id: u8,
+    /// Other
+    //~^ ERROR documentation comments cannot be applied to method arguments
+    //~| NOTE doc comments are not allowed here
+    a: u8,
+) {}
+
+fn foo(#[allow(dead_code)] id: i32) {}
+//~^ ERROR attributes cannot be applied to method arguments
+//~| NOTE attributes are not allowed here
+
+fn bar(id: #[allow(dead_code)] i32) {}
+//~^ ERROR attributes cannot be applied to a method argument's type
+//~| NOTE attributes are not allowed here
+
+fn main() {
+    // verify that the parser recovered and properly typechecked the args
+    f("", "");
+    //~^ ERROR mismatched types
+    //~| NOTE expected u8, found reference
+    //~| NOTE expected
+    //~| ERROR mismatched types
+    //~| NOTE expected u8, found reference
+    //~| NOTE expected
+    foo("");
+    //~^ ERROR mismatched types
+    //~| NOTE expected i32, found reference
+    //~| NOTE expected
+    bar("");
+    //~^ ERROR mismatched types
+    //~| NOTE expected i32, found reference
+    //~| NOTE expected
+}
diff --git a/src/test/ui/parser/fn-arg-doc-comment.stderr b/src/test/ui/parser/fn-arg-doc-comment.stderr
new file mode 100644
index 0000000..73a24eeb
--- /dev/null
+++ b/src/test/ui/parser/fn-arg-doc-comment.stderr
@@ -0,0 +1,63 @@
+error: documentation comments cannot be applied to method arguments
+  --> $DIR/fn-arg-doc-comment.rs:2:5
+   |
+LL |     /// Comment
+   |     ^^^^^^^^^^^ doc comments are not allowed here
+
+error: documentation comments cannot be applied to method arguments
+  --> $DIR/fn-arg-doc-comment.rs:6:5
+   |
+LL |     /// Other
+   |     ^^^^^^^^^ doc comments are not allowed here
+
+error: attributes cannot be applied to method arguments
+  --> $DIR/fn-arg-doc-comment.rs:12:8
+   |
+LL | fn foo(#[allow(dead_code)] id: i32) {}
+   |        ^^^^^^^^^^^^^^^^^^^ attributes are not allowed here
+
+error: attributes cannot be applied to a method argument's type
+  --> $DIR/fn-arg-doc-comment.rs:16:12
+   |
+LL | fn bar(id: #[allow(dead_code)] i32) {}
+   |            ^^^^^^^^^^^^^^^^^^^ attributes are not allowed here
+
+error[E0308]: mismatched types
+  --> $DIR/fn-arg-doc-comment.rs:22:7
+   |
+LL |     f("", "");
+   |       ^^ expected u8, found reference
+   |
+   = note: expected type `u8`
+              found type `&'static str`
+
+error[E0308]: mismatched types
+  --> $DIR/fn-arg-doc-comment.rs:22:11
+   |
+LL |     f("", "");
+   |           ^^ expected u8, found reference
+   |
+   = note: expected type `u8`
+              found type `&'static str`
+
+error[E0308]: mismatched types
+  --> $DIR/fn-arg-doc-comment.rs:29:9
+   |
+LL |     foo("");
+   |         ^^ expected i32, found reference
+   |
+   = note: expected type `i32`
+              found type `&'static str`
+
+error[E0308]: mismatched types
+  --> $DIR/fn-arg-doc-comment.rs:33:9
+   |
+LL |     bar("");
+   |         ^^ expected i32, found reference
+   |
+   = note: expected type `i32`
+              found type `&'static str`
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/parser/if-in-in.rs b/src/test/ui/parser/if-in-in.rs
new file mode 100644
index 0000000..212378c2
--- /dev/null
+++ b/src/test/ui/parser/if-in-in.rs
@@ -0,0 +1,5 @@
+fn main() {
+    for i in in 1..2 { //~ ERROR expected iterable, found keyword `in`
+        println!("{}", i);
+    }
+}
diff --git a/src/test/ui/parser/if-in-in.stderr b/src/test/ui/parser/if-in-in.stderr
new file mode 100644
index 0000000..9926fcc
--- /dev/null
+++ b/src/test/ui/parser/if-in-in.stderr
@@ -0,0 +1,13 @@
+error: expected iterable, found keyword `in`
+  --> $DIR/if-in-in.rs:2:14
+   |
+LL |     for i in in 1..2 {
+   |           ---^^
+   |           |
+   |           help: remove the duplicated `in`
+   |
+   = note: if you meant to use emplacement syntax, it is obsolete (for now, anyway)
+   = note: for more information on the status of emplacement syntax, see <https://github.com/rust-lang/rust/issues/27779#issuecomment-378416911>
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/impl-parsing.rs b/src/test/ui/parser/impl-parsing.rs
new file mode 100644
index 0000000..c2a80e8
--- /dev/null
+++ b/src/test/ui/parser/impl-parsing.rs
@@ -0,0 +1,11 @@
+// compile-flags: -Z continue-parse-after-error
+
+impl ! {} // OK
+impl ! where u8: Copy {} // OK
+
+impl Trait Type {} //~ ERROR missing `for` in a trait impl
+impl Trait .. {} //~ ERROR missing `for` in a trait impl
+impl ?Sized for Type {} //~ ERROR expected a trait, found type
+impl ?Sized for .. {} //~ ERROR expected a trait, found type
+
+default unsafe FAIL //~ ERROR expected `impl`, found `FAIL`
diff --git a/src/test/ui/parser/impl-parsing.stderr b/src/test/ui/parser/impl-parsing.stderr
new file mode 100644
index 0000000..935e939
--- /dev/null
+++ b/src/test/ui/parser/impl-parsing.stderr
@@ -0,0 +1,32 @@
+error: missing `for` in a trait impl
+  --> $DIR/impl-parsing.rs:6:11
+   |
+LL | impl Trait Type {}
+   |           ^ help: add `for` here
+
+error: missing `for` in a trait impl
+  --> $DIR/impl-parsing.rs:7:11
+   |
+LL | impl Trait .. {}
+   |           ^ help: add `for` here
+
+error: expected a trait, found type
+  --> $DIR/impl-parsing.rs:8:6
+   |
+LL | impl ?Sized for Type {}
+   |      ^^^^^^
+
+error: expected a trait, found type
+  --> $DIR/impl-parsing.rs:9:6
+   |
+LL | impl ?Sized for .. {}
+   |      ^^^^^^
+
+error: expected `impl`, found `FAIL`
+  --> $DIR/impl-parsing.rs:11:16
+   |
+LL | default unsafe FAIL
+   |                ^^^^ expected `impl` here
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/ui/parser/impl-qpath.rs b/src/test/ui/parser/impl-qpath.rs
new file mode 100644
index 0000000..78c41f4
--- /dev/null
+++ b/src/test/ui/parser/impl-qpath.rs
@@ -0,0 +1,7 @@
+// compile-pass
+// compile-flags: -Z parse-only
+
+impl <*const u8>::AssocTy {} // OK
+impl <Type as Trait>::AssocTy {} // OK
+impl <'a + Trait>::AssocTy {} // OK
+impl <<Type>::AssocTy>::AssocTy {} // OK
diff --git a/src/test/ui/parser/import-from-path.rs b/src/test/ui/parser/import-from-path.rs
new file mode 100644
index 0000000..3fce082
--- /dev/null
+++ b/src/test/ui/parser/import-from-path.rs
@@ -0,0 +1,2 @@
+// error-pattern:expected
+use foo::{bar}::baz
diff --git a/src/test/ui/parser/import-from-path.stderr b/src/test/ui/parser/import-from-path.stderr
new file mode 100644
index 0000000..5842037
--- /dev/null
+++ b/src/test/ui/parser/import-from-path.stderr
@@ -0,0 +1,8 @@
+error: expected `;`, found `::`
+  --> $DIR/import-from-path.rs:2:15
+   |
+LL | use foo::{bar}::baz
+   |               ^^ expected `;`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/import-from-rename.rs b/src/test/ui/parser/import-from-rename.rs
new file mode 100644
index 0000000..27425a3
--- /dev/null
+++ b/src/test/ui/parser/import-from-rename.rs
@@ -0,0 +1,10 @@
+// error-pattern:expected
+
+use foo::{bar} as baz;
+
+mod foo {
+    pub fn bar() {}
+}
+
+fn main() {
+}
diff --git a/src/test/ui/parser/import-from-rename.stderr b/src/test/ui/parser/import-from-rename.stderr
new file mode 100644
index 0000000..a966e99
--- /dev/null
+++ b/src/test/ui/parser/import-from-rename.stderr
@@ -0,0 +1,8 @@
+error: expected `;`, found keyword `as`
+  --> $DIR/import-from-rename.rs:3:16
+   |
+LL | use foo::{bar} as baz;
+   |                ^^ expected `;`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/import-glob-path.rs b/src/test/ui/parser/import-glob-path.rs
new file mode 100644
index 0000000..de4c07a
--- /dev/null
+++ b/src/test/ui/parser/import-glob-path.rs
@@ -0,0 +1,2 @@
+// error-pattern:expected
+use foo::*::bar
diff --git a/src/test/ui/parser/import-glob-path.stderr b/src/test/ui/parser/import-glob-path.stderr
new file mode 100644
index 0000000..ebca2db
--- /dev/null
+++ b/src/test/ui/parser/import-glob-path.stderr
@@ -0,0 +1,8 @@
+error: expected `;`, found `::`
+  --> $DIR/import-glob-path.rs:2:11
+   |
+LL | use foo::*::bar
+   |           ^^ expected `;`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/import-glob-rename.rs b/src/test/ui/parser/import-glob-rename.rs
new file mode 100644
index 0000000..b9b753dc
--- /dev/null
+++ b/src/test/ui/parser/import-glob-rename.rs
@@ -0,0 +1,10 @@
+// error-pattern:expected
+
+use foo::* as baz;
+
+mod foo {
+    pub fn bar() {}
+}
+
+fn main() {
+}
diff --git a/src/test/ui/parser/import-glob-rename.stderr b/src/test/ui/parser/import-glob-rename.stderr
new file mode 100644
index 0000000..2853873
--- /dev/null
+++ b/src/test/ui/parser/import-glob-rename.stderr
@@ -0,0 +1,8 @@
+error: expected `;`, found keyword `as`
+  --> $DIR/import-glob-rename.rs:3:12
+   |
+LL | use foo::* as baz;
+   |            ^^ expected `;`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/inner-attr-after-doc-comment.rs b/src/test/ui/parser/inner-attr-after-doc-comment.rs
new file mode 100644
index 0000000..36f4191
--- /dev/null
+++ b/src/test/ui/parser/inner-attr-after-doc-comment.rs
@@ -0,0 +1,8 @@
+#![feature(lang_items)]
+/**
+ * My module
+ */
+
+#![recursion_limit="100"]
+//~^ ERROR an inner attribute is not permitted following an outer doc comment
+fn main() {}
diff --git a/src/test/ui/parser/inner-attr-after-doc-comment.stderr b/src/test/ui/parser/inner-attr-after-doc-comment.stderr
new file mode 100644
index 0000000..0dde49a
--- /dev/null
+++ b/src/test/ui/parser/inner-attr-after-doc-comment.stderr
@@ -0,0 +1,10 @@
+error: an inner attribute is not permitted following an outer doc comment
+  --> $DIR/inner-attr-after-doc-comment.rs:6:3
+   |
+LL | #![recursion_limit="100"]
+   |   ^
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/inner-attr.rs b/src/test/ui/parser/inner-attr.rs
new file mode 100644
index 0000000..1b405e2
--- /dev/null
+++ b/src/test/ui/parser/inner-attr.rs
@@ -0,0 +1,4 @@
+#[feature(lang_items)]
+
+#![recursion_limit="100"] //~ ERROR an inner attribute is not permitted following an outer attribute
+fn main() {}
diff --git a/src/test/ui/parser/inner-attr.stderr b/src/test/ui/parser/inner-attr.stderr
new file mode 100644
index 0000000..11a37bc
--- /dev/null
+++ b/src/test/ui/parser/inner-attr.stderr
@@ -0,0 +1,10 @@
+error: an inner attribute is not permitted following an outer attribute
+  --> $DIR/inner-attr.rs:3:3
+   |
+LL | #![recursion_limit="100"]
+   |   ^
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/int-literal-too-large-span.rs b/src/test/ui/parser/int-literal-too-large-span.rs
new file mode 100644
index 0000000..206242c
--- /dev/null
+++ b/src/test/ui/parser/int-literal-too-large-span.rs
@@ -0,0 +1,7 @@
+// issue #17123
+
+fn main() {
+    9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+    //~^ ERROR int literal is too large
+        ; // the span shouldn't point to this.
+}
diff --git a/src/test/ui/parser/int-literal-too-large-span.stderr b/src/test/ui/parser/int-literal-too-large-span.stderr
new file mode 100644
index 0000000..d7774c3
--- /dev/null
+++ b/src/test/ui/parser/int-literal-too-large-span.stderr
@@ -0,0 +1,8 @@
+error: int literal is too large
+  --> $DIR/int-literal-too-large-span.rs:4:5
+   |
+LL |     9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/inverted-parameters.rs b/src/test/ui/parser/inverted-parameters.rs
new file mode 100644
index 0000000..4243027
--- /dev/null
+++ b/src/test/ui/parser/inverted-parameters.rs
@@ -0,0 +1,29 @@
+struct S;
+
+impl S {
+    fn foo(&self, &str bar) {}
+    //~^ ERROR expected one of `:` or `@`
+    //~| HELP declare the type after the parameter binding
+    //~| SUGGESTION <identifier>: <type>
+}
+
+fn baz(S quux, xyzzy: i32) {}
+//~^ ERROR expected one of `:` or `@`
+//~| HELP declare the type after the parameter binding
+//~| SUGGESTION <identifier>: <type>
+
+fn one(i32 a b) {}
+//~^ ERROR expected one of `:` or `@`
+
+fn pattern((i32, i32) (a, b)) {}
+//~^ ERROR expected `:`
+
+fn fizz(i32) {}
+//~^ ERROR expected one of `:` or `@`
+
+fn missing_colon(quux S) {}
+//~^ ERROR expected one of `:` or `@`
+//~| HELP declare the type after the parameter binding
+//~| SUGGESTION <identifier>: <type>
+
+fn main() {}
diff --git a/src/test/ui/parser/inverted-parameters.stderr b/src/test/ui/parser/inverted-parameters.stderr
new file mode 100644
index 0000000..bdb8faa
--- /dev/null
+++ b/src/test/ui/parser/inverted-parameters.stderr
@@ -0,0 +1,47 @@
+error: expected one of `:` or `@`, found `bar`
+  --> $DIR/inverted-parameters.rs:4:24
+   |
+LL |     fn foo(&self, &str bar) {}
+   |                   -----^^^
+   |                   |    |
+   |                   |    expected one of `:` or `@` here
+   |                   help: declare the type after the parameter binding: `<identifier>: <type>`
+
+error: expected one of `:` or `@`, found `quux`
+  --> $DIR/inverted-parameters.rs:10:10
+   |
+LL | fn baz(S quux, xyzzy: i32) {}
+   |        --^^^^
+   |        | |
+   |        | expected one of `:` or `@` here
+   |        help: declare the type after the parameter binding: `<identifier>: <type>`
+
+error: expected one of `:` or `@`, found `a`
+  --> $DIR/inverted-parameters.rs:15:12
+   |
+LL | fn one(i32 a b) {}
+   |            ^ expected one of `:` or `@` here
+
+error: expected `:`, found `(`
+  --> $DIR/inverted-parameters.rs:18:23
+   |
+LL | fn pattern((i32, i32) (a, b)) {}
+   |                       ^ expected `:`
+
+error: expected one of `:` or `@`, found `)`
+  --> $DIR/inverted-parameters.rs:21:12
+   |
+LL | fn fizz(i32) {}
+   |            ^ expected one of `:` or `@` here
+
+error: expected one of `:` or `@`, found `S`
+  --> $DIR/inverted-parameters.rs:24:23
+   |
+LL | fn missing_colon(quux S) {}
+   |                  -----^
+   |                  |    |
+   |                  |    expected one of `:` or `@` here
+   |                  help: declare the type after the parameter binding: `<identifier>: <type>`
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/parser/issue-10392-2.rs b/src/test/ui/parser/issue-10392-2.rs
new file mode 100644
index 0000000..3b5e319
--- /dev/null
+++ b/src/test/ui/parser/issue-10392-2.rs
@@ -0,0 +1,7 @@
+struct A { foo: isize }
+
+fn a() -> A { panic!() }
+
+fn main() {
+    let A { .., } = a(); //~ ERROR: expected `}`
+}
diff --git a/src/test/ui/parser/issue-10392-2.stderr b/src/test/ui/parser/issue-10392-2.stderr
new file mode 100644
index 0000000..ccc5dd9
--- /dev/null
+++ b/src/test/ui/parser/issue-10392-2.stderr
@@ -0,0 +1,12 @@
+error: expected `}`, found `,`
+  --> $DIR/issue-10392-2.rs:6:15
+   |
+LL |     let A { .., } = a();
+   |             --^
+   |             | |
+   |             | expected `}`
+   |             | help: remove this comma
+   |             `..` must be at the end and cannot have a trailing comma
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-10392.rs b/src/test/ui/parser/issue-10392.rs
new file mode 100644
index 0000000..5b0c2fc
--- /dev/null
+++ b/src/test/ui/parser/issue-10392.rs
@@ -0,0 +1,7 @@
+struct A { foo: isize }
+
+fn a() -> A { panic!() }
+
+fn main() {
+    let A { , } = a(); //~ ERROR expected ident
+}
diff --git a/src/test/ui/parser/issue-10392.stderr b/src/test/ui/parser/issue-10392.stderr
new file mode 100644
index 0000000..3499115
--- /dev/null
+++ b/src/test/ui/parser/issue-10392.stderr
@@ -0,0 +1,8 @@
+error: expected identifier, found `,`
+  --> $DIR/issue-10392.rs:6:13
+   |
+LL |     let A { , } = a();
+   |             ^ expected identifier
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-10636-1.rs b/src/test/ui/parser/issue-10636-1.rs
new file mode 100644
index 0000000..e495c04
--- /dev/null
+++ b/src/test/ui/parser/issue-10636-1.rs
@@ -0,0 +1,8 @@
+struct Obj {
+    //~^ NOTE: un-closed delimiter
+    member: usize
+)
+//~^ ERROR incorrect close delimiter
+//~| NOTE incorrect close delimiter
+
+fn main() {}
diff --git a/src/test/ui/parser/issue-10636-1.stderr b/src/test/ui/parser/issue-10636-1.stderr
new file mode 100644
index 0000000..894139f
--- /dev/null
+++ b/src/test/ui/parser/issue-10636-1.stderr
@@ -0,0 +1,11 @@
+error: incorrect close delimiter: `)`
+  --> $DIR/issue-10636-1.rs:4:1
+   |
+LL | struct Obj {
+   |            - un-closed delimiter
+...
+LL | )
+   | ^ incorrect close delimiter
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-10636-2.rs b/src/test/ui/parser/issue-10636-2.rs
new file mode 100644
index 0000000..6fb6363
--- /dev/null
+++ b/src/test/ui/parser/issue-10636-2.rs
@@ -0,0 +1,11 @@
+// FIXME(31528) we emit a bunch of silly errors here due to continuing past the
+// first one. This would be easy-ish to address by better recovery in tokenisation.
+
+pub fn trace_option(option: Option<isize>) {
+    option.map(|some| 42;
+                          //~^ ERROR: expected one of
+
+}
+//~^ ERROR: expected expression, found `)`
+
+fn main() {}
diff --git a/src/test/ui/parser/issue-10636-2.stderr b/src/test/ui/parser/issue-10636-2.stderr
new file mode 100644
index 0000000..38d57ce
--- /dev/null
+++ b/src/test/ui/parser/issue-10636-2.stderr
@@ -0,0 +1,17 @@
+error: expected one of `)`, `,`, `.`, `?`, or an operator, found `;`
+  --> $DIR/issue-10636-2.rs:5:25
+   |
+LL |     option.map(|some| 42;
+   |               -         ^
+   |               |         |
+   |               |         help: `)` may belong here
+   |               unclosed delimiter
+
+error: expected expression, found `)`
+  --> $DIR/issue-10636-2.rs:8:1
+   |
+LL | }
+   | ^ expected expression
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/parser/issue-14303-enum.rs b/src/test/ui/parser/issue-14303-enum.rs
new file mode 100644
index 0000000..a610615
--- /dev/null
+++ b/src/test/ui/parser/issue-14303-enum.rs
@@ -0,0 +1,6 @@
+enum X<'a, T, 'b> {
+//~^ ERROR lifetime parameters must be declared prior to type parameters
+    A(&'a &'b T)
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/issue-14303-enum.stderr b/src/test/ui/parser/issue-14303-enum.stderr
new file mode 100644
index 0000000..46f16ea
--- /dev/null
+++ b/src/test/ui/parser/issue-14303-enum.stderr
@@ -0,0 +1,8 @@
+error: lifetime parameters must be declared prior to type parameters
+  --> $DIR/issue-14303-enum.rs:1:15
+   |
+LL | enum X<'a, T, 'b> {
+   |       --------^^- help: reorder the parameters: lifetimes, then types: `<'a, 'b, T>`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-14303-fn-def.rs b/src/test/ui/parser/issue-14303-fn-def.rs
new file mode 100644
index 0000000..221bd31
--- /dev/null
+++ b/src/test/ui/parser/issue-14303-fn-def.rs
@@ -0,0 +1,4 @@
+fn foo<'a, T, 'b>(x: &'a T) {}
+//~^ ERROR lifetime parameters must be declared prior to type parameters
+
+fn main() {}
diff --git a/src/test/ui/parser/issue-14303-fn-def.stderr b/src/test/ui/parser/issue-14303-fn-def.stderr
new file mode 100644
index 0000000..8cbab4b
--- /dev/null
+++ b/src/test/ui/parser/issue-14303-fn-def.stderr
@@ -0,0 +1,8 @@
+error: lifetime parameters must be declared prior to type parameters
+  --> $DIR/issue-14303-fn-def.rs:1:15
+   |
+LL | fn foo<'a, T, 'b>(x: &'a T) {}
+   |       --------^^- help: reorder the parameters: lifetimes, then types: `<'a, 'b, T>`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-14303-fncall.rs b/src/test/ui/parser/issue-14303-fncall.rs
new file mode 100644
index 0000000..3969419
--- /dev/null
+++ b/src/test/ui/parser/issue-14303-fncall.rs
@@ -0,0 +1,17 @@
+// can't run rustfix because it doesn't handle multipart suggestions correctly
+// compile-flags: -Zborrowck=mir
+// we need the above to avoid ast borrowck failure in recovered code
+
+struct S<'a, T> {
+    a: &'a T,
+    b: &'a T,
+}
+
+fn foo<'a, 'b>(start: &'a usize, end: &'a usize) {
+    let _x = (*start..*end)
+        .map(|x| S { a: start, b: end })
+        .collect::<Vec<S<_, 'a>>>();
+        //~^ ERROR lifetime arguments must be declared prior to type arguments
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/issue-14303-fncall.stderr b/src/test/ui/parser/issue-14303-fncall.stderr
new file mode 100644
index 0000000..8ef9f1a
--- /dev/null
+++ b/src/test/ui/parser/issue-14303-fncall.stderr
@@ -0,0 +1,8 @@
+error: lifetime arguments must be declared prior to type arguments
+  --> $DIR/issue-14303-fncall.rs:13:29
+   |
+LL |         .collect::<Vec<S<_, 'a>>>();
+   |                             ^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-14303-impl.rs b/src/test/ui/parser/issue-14303-impl.rs
new file mode 100644
index 0000000..4dc2c66
--- /dev/null
+++ b/src/test/ui/parser/issue-14303-impl.rs
@@ -0,0 +1,6 @@
+struct X<T>(T);
+
+impl<'a, T, 'b> X<T> {}
+//~^ ERROR lifetime parameters must be declared prior to type parameters
+
+fn main() {}
diff --git a/src/test/ui/parser/issue-14303-impl.stderr b/src/test/ui/parser/issue-14303-impl.stderr
new file mode 100644
index 0000000..56cd4fb
--- /dev/null
+++ b/src/test/ui/parser/issue-14303-impl.stderr
@@ -0,0 +1,8 @@
+error: lifetime parameters must be declared prior to type parameters
+  --> $DIR/issue-14303-impl.rs:3:13
+   |
+LL | impl<'a, T, 'b> X<T> {}
+   |     --------^^- help: reorder the parameters: lifetimes, then types: `<'a, 'b, T>`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-14303-path.rs b/src/test/ui/parser/issue-14303-path.rs
new file mode 100644
index 0000000..386d198
--- /dev/null
+++ b/src/test/ui/parser/issue-14303-path.rs
@@ -0,0 +1,13 @@
+mod foo {
+    pub struct X<'a, 'b, 'c, T> {
+        a: &'a str,
+        b: &'b str,
+        c: &'c str,
+        t: T,
+    }
+}
+
+fn bar<'a, 'b, 'c, T>(x: foo::X<'a, T, 'b, 'c>) {}
+//~^ ERROR lifetime arguments must be declared prior to type arguments
+
+fn main() {}
diff --git a/src/test/ui/parser/issue-14303-path.stderr b/src/test/ui/parser/issue-14303-path.stderr
new file mode 100644
index 0000000..19f2995
--- /dev/null
+++ b/src/test/ui/parser/issue-14303-path.stderr
@@ -0,0 +1,8 @@
+error: lifetime arguments must be declared prior to type arguments
+  --> $DIR/issue-14303-path.rs:10:40
+   |
+LL | fn bar<'a, 'b, 'c, T>(x: foo::X<'a, T, 'b, 'c>) {}
+   |                                        ^^  ^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-14303-struct.rs b/src/test/ui/parser/issue-14303-struct.rs
new file mode 100644
index 0000000..0bd10b4
--- /dev/null
+++ b/src/test/ui/parser/issue-14303-struct.rs
@@ -0,0 +1,6 @@
+struct X<'a, T, 'b> {
+//~^ ERROR lifetime parameters must be declared prior to type parameters
+    x: &'a &'b T
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/issue-14303-struct.stderr b/src/test/ui/parser/issue-14303-struct.stderr
new file mode 100644
index 0000000..f31cb92
--- /dev/null
+++ b/src/test/ui/parser/issue-14303-struct.stderr
@@ -0,0 +1,8 @@
+error: lifetime parameters must be declared prior to type parameters
+  --> $DIR/issue-14303-struct.rs:1:17
+   |
+LL | struct X<'a, T, 'b> {
+   |         --------^^- help: reorder the parameters: lifetimes, then types: `<'a, 'b, T>`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-14303-trait.rs b/src/test/ui/parser/issue-14303-trait.rs
new file mode 100644
index 0000000..f253de9
--- /dev/null
+++ b/src/test/ui/parser/issue-14303-trait.rs
@@ -0,0 +1,4 @@
+trait Foo<'a, T, 'b> {}
+//~^ ERROR lifetime parameters must be declared prior to type parameters
+
+fn main() {}
diff --git a/src/test/ui/parser/issue-14303-trait.stderr b/src/test/ui/parser/issue-14303-trait.stderr
new file mode 100644
index 0000000..0e73991
--- /dev/null
+++ b/src/test/ui/parser/issue-14303-trait.stderr
@@ -0,0 +1,8 @@
+error: lifetime parameters must be declared prior to type parameters
+  --> $DIR/issue-14303-trait.rs:1:18
+   |
+LL | trait Foo<'a, T, 'b> {}
+   |          --------^^- help: reorder the parameters: lifetimes, then types: `<'a, 'b, T>`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-15914.rs b/src/test/ui/parser/issue-15914.rs
new file mode 100644
index 0000000..4a5606a
--- /dev/null
+++ b/src/test/ui/parser/issue-15914.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let ref
+        (); //~ ERROR expected identifier, found `(`
+}
diff --git a/src/test/ui/parser/issue-15914.stderr b/src/test/ui/parser/issue-15914.stderr
new file mode 100644
index 0000000..ea26453
--- /dev/null
+++ b/src/test/ui/parser/issue-15914.stderr
@@ -0,0 +1,8 @@
+error: expected identifier, found `(`
+  --> $DIR/issue-15914.rs:3:9
+   |
+LL |         ();
+   |         ^ expected identifier
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-15980.rs b/src/test/ui/parser/issue-15980.rs
new file mode 100644
index 0000000..ba874fb
--- /dev/null
+++ b/src/test/ui/parser/issue-15980.rs
@@ -0,0 +1,17 @@
+use std::io;
+
+fn main(){
+    let x: io::Result<()> = Ok(());
+    match x {
+        Err(ref e) if e.kind == io::EndOfFile {
+            //~^ NOTE while parsing this struct
+            return
+            //~^ ERROR expected identifier, found keyword `return`
+            //~| NOTE expected identifier, found keyword
+        }
+        //~^ NOTE expected one of `.`, `=>`, `?`, or an operator here
+        _ => {}
+        //~^ ERROR expected one of `.`, `=>`, `?`, or an operator, found `_`
+        //~| NOTE unexpected token
+    }
+}
diff --git a/src/test/ui/parser/issue-15980.stderr b/src/test/ui/parser/issue-15980.stderr
new file mode 100644
index 0000000..879bcb2
--- /dev/null
+++ b/src/test/ui/parser/issue-15980.stderr
@@ -0,0 +1,24 @@
+error: expected identifier, found keyword `return`
+  --> $DIR/issue-15980.rs:8:13
+   |
+LL |         Err(ref e) if e.kind == io::EndOfFile {
+   |                                 ------------- while parsing this struct
+LL |
+LL |             return
+   |             ^^^^^^ expected identifier, found keyword
+help: you can escape reserved keywords to use them as identifiers
+   |
+LL |             r#return
+   |
+
+error: expected one of `.`, `=>`, `?`, or an operator, found `_`
+  --> $DIR/issue-15980.rs:13:9
+   |
+LL |         }
+   |          - expected one of `.`, `=>`, `?`, or an operator here
+LL |
+LL |         _ => {}
+   |         ^ unexpected token
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/parser/issue-1655.rs b/src/test/ui/parser/issue-1655.rs
new file mode 100644
index 0000000..3d0bf3c
--- /dev/null
+++ b/src/test/ui/parser/issue-1655.rs
@@ -0,0 +1,11 @@
+// error-pattern:expected `[`, found `vec`
+mod blade_runner {
+    #vec[doc(
+        brief = "Blade Runner is probably the best movie ever",
+        desc = "I like that in the world of Blade Runner it is always
+                raining, and that it's always night time. And Aliens
+                was also a really good movie.
+
+                Alien 3 was crap though."
+    )]
+}
diff --git a/src/test/ui/parser/issue-1655.stderr b/src/test/ui/parser/issue-1655.stderr
new file mode 100644
index 0000000..3f656b6
--- /dev/null
+++ b/src/test/ui/parser/issue-1655.stderr
@@ -0,0 +1,8 @@
+error: expected `[`, found `vec`
+  --> $DIR/issue-1655.rs:3:6
+   |
+LL |     #vec[doc(
+   |      ^^^ expected `[`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-17383.rs b/src/test/ui/parser/issue-17383.rs
new file mode 100644
index 0000000..04cd43d
--- /dev/null
+++ b/src/test/ui/parser/issue-17383.rs
@@ -0,0 +1,7 @@
+enum X {
+    A = 3,
+    //~^ ERROR discriminator values can only be used with a field-less enum
+    B(usize)
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/issue-17383.stderr b/src/test/ui/parser/issue-17383.stderr
new file mode 100644
index 0000000..57caa33
--- /dev/null
+++ b/src/test/ui/parser/issue-17383.stderr
@@ -0,0 +1,8 @@
+error: discriminator values can only be used with a field-less enum
+  --> $DIR/issue-17383.rs:2:9
+   |
+LL |     A = 3,
+   |         ^ only valid in field-less enums
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-17718-const-mut.rs b/src/test/ui/parser/issue-17718-const-mut.rs
new file mode 100644
index 0000000..795a8c7
--- /dev/null
+++ b/src/test/ui/parser/issue-17718-const-mut.rs
@@ -0,0 +1,7 @@
+const
+mut //~ ERROR: const globals cannot be mutable
+//~^^ HELP you might want to declare a static instead
+FOO: usize = 3;
+
+fn main() {
+}
diff --git a/src/test/ui/parser/issue-17718-const-mut.stderr b/src/test/ui/parser/issue-17718-const-mut.stderr
new file mode 100644
index 0000000..8251ce9
--- /dev/null
+++ b/src/test/ui/parser/issue-17718-const-mut.stderr
@@ -0,0 +1,10 @@
+error: const globals cannot be mutable
+  --> $DIR/issue-17718-const-mut.rs:2:1
+   |
+LL | const
+   | ----- help: you might want to declare a static instead: `static`
+LL | mut
+   | ^^^ cannot be mutable
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-17904-2.rs b/src/test/ui/parser/issue-17904-2.rs
new file mode 100644
index 0000000..d3f3225
--- /dev/null
+++ b/src/test/ui/parser/issue-17904-2.rs
@@ -0,0 +1,5 @@
+// compile-flags: -Z continue-parse-after-error
+
+struct Bar<T> { x: T } where T: Copy //~ ERROR expected item, found keyword `where`
+
+fn main() {}
diff --git a/src/test/ui/parser/issue-17904-2.stderr b/src/test/ui/parser/issue-17904-2.stderr
new file mode 100644
index 0000000..03e556d
--- /dev/null
+++ b/src/test/ui/parser/issue-17904-2.stderr
@@ -0,0 +1,8 @@
+error: expected item, found keyword `where`
+  --> $DIR/issue-17904-2.rs:3:24
+   |
+LL | struct Bar<T> { x: T } where T: Copy
+   |                        ^^^^^ expected item
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-17904.rs b/src/test/ui/parser/issue-17904.rs
new file mode 100644
index 0000000..6112623
--- /dev/null
+++ b/src/test/ui/parser/issue-17904.rs
@@ -0,0 +1,8 @@
+// compile-flags: -Z continue-parse-after-error
+
+struct Baz<U> where U: Eq(U); //This is parsed as the new Fn* style parenthesis syntax.
+struct Baz<U> where U: Eq(U) -> R; // Notice this parses as well.
+struct Baz<U>(U) where U: Eq; // This rightfully signals no error as well.
+struct Foo<T> where T: Copy, (T); //~ ERROR expected one of `:`, `==`, or `=`, found `;`
+
+fn main() {}
diff --git a/src/test/ui/parser/issue-17904.stderr b/src/test/ui/parser/issue-17904.stderr
new file mode 100644
index 0000000..a447009
--- /dev/null
+++ b/src/test/ui/parser/issue-17904.stderr
@@ -0,0 +1,8 @@
+error: expected one of `:`, `==`, or `=`, found `;`
+  --> $DIR/issue-17904.rs:6:33
+   |
+LL | struct Foo<T> where T: Copy, (T);
+   |                                 ^ expected one of `:`, `==`, or `=` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-1802-1.rs b/src/test/ui/parser/issue-1802-1.rs
new file mode 100644
index 0000000..3c34b0d
--- /dev/null
+++ b/src/test/ui/parser/issue-1802-1.rs
@@ -0,0 +1,7 @@
+fn log(a: i32, b: i32) {}
+
+fn main() {
+    let error = 42;
+    log(error, 0b);
+    //~^ ERROR no valid digits found for number
+}
diff --git a/src/test/ui/parser/issue-1802-1.stderr b/src/test/ui/parser/issue-1802-1.stderr
new file mode 100644
index 0000000..b7d003d
--- /dev/null
+++ b/src/test/ui/parser/issue-1802-1.stderr
@@ -0,0 +1,8 @@
+error: no valid digits found for number
+  --> $DIR/issue-1802-1.rs:5:16
+   |
+LL |     log(error, 0b);
+   |                ^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-1802-2.rs b/src/test/ui/parser/issue-1802-2.rs
new file mode 100644
index 0000000..3c34b0d
--- /dev/null
+++ b/src/test/ui/parser/issue-1802-2.rs
@@ -0,0 +1,7 @@
+fn log(a: i32, b: i32) {}
+
+fn main() {
+    let error = 42;
+    log(error, 0b);
+    //~^ ERROR no valid digits found for number
+}
diff --git a/src/test/ui/parser/issue-1802-2.stderr b/src/test/ui/parser/issue-1802-2.stderr
new file mode 100644
index 0000000..8491dd0
--- /dev/null
+++ b/src/test/ui/parser/issue-1802-2.stderr
@@ -0,0 +1,8 @@
+error: no valid digits found for number
+  --> $DIR/issue-1802-2.rs:5:16
+   |
+LL |     log(error, 0b);
+   |                ^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-19096.rs b/src/test/ui/parser/issue-19096.rs
new file mode 100644
index 0000000..edc69e6
--- /dev/null
+++ b/src/test/ui/parser/issue-19096.rs
@@ -0,0 +1,5 @@
+fn main() {
+    let t = (42, 42);
+    t.0::<isize>; //~ ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `::`
+                  //~| ERROR mismatched types
+}
diff --git a/src/test/ui/parser/issue-19096.stderr b/src/test/ui/parser/issue-19096.stderr
new file mode 100644
index 0000000..6aa97ad
--- /dev/null
+++ b/src/test/ui/parser/issue-19096.stderr
@@ -0,0 +1,21 @@
+error: expected one of `.`, `;`, `?`, `}`, or an operator, found `::`
+  --> $DIR/issue-19096.rs:3:8
+   |
+LL |     t.0::<isize>;
+   |        ^^ expected one of `.`, `;`, `?`, `}`, or an operator here
+
+error[E0308]: mismatched types
+  --> $DIR/issue-19096.rs:3:5
+   |
+LL | fn main() {
+   |           - expected `()` because of default return type
+LL |     let t = (42, 42);
+LL |     t.0::<isize>;
+   |     ^^^ expected (), found integer
+   |
+   = note: expected type `()`
+              found type `{integer}`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/parser/issue-19398.rs b/src/test/ui/parser/issue-19398.rs
new file mode 100644
index 0000000..822f4a6
--- /dev/null
+++ b/src/test/ui/parser/issue-19398.rs
@@ -0,0 +1,5 @@
+trait T {
+    extern "Rust" unsafe fn foo(); //~ ERROR expected `fn`, found `unsafe`
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/issue-19398.stderr b/src/test/ui/parser/issue-19398.stderr
new file mode 100644
index 0000000..d5f1f97
--- /dev/null
+++ b/src/test/ui/parser/issue-19398.stderr
@@ -0,0 +1,8 @@
+error: expected `fn`, found `unsafe`
+  --> $DIR/issue-19398.rs:2:19
+   |
+LL |     extern "Rust" unsafe fn foo();
+   |                   ^^^^^^ expected `fn` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-20711-2.rs b/src/test/ui/parser/issue-20711-2.rs
new file mode 100644
index 0000000..49b8de0
--- /dev/null
+++ b/src/test/ui/parser/issue-20711-2.rs
@@ -0,0 +1,11 @@
+// ignore-tidy-linelength
+
+struct Foo;
+
+impl Foo {
+    fn foo() {}
+
+    #[stable(feature = "rust1", since = "1.0.0")]
+} //~ ERROR expected one of `async`, `const`, `crate`, `default`, `existential`, `extern`, `fn`, `pub`, `type`, or
+
+fn main() {}
diff --git a/src/test/ui/parser/issue-20711-2.stderr b/src/test/ui/parser/issue-20711-2.stderr
new file mode 100644
index 0000000..f67dfa0
--- /dev/null
+++ b/src/test/ui/parser/issue-20711-2.stderr
@@ -0,0 +1,10 @@
+error: expected one of `async`, `const`, `crate`, `default`, `existential`, `extern`, `fn`, `pub`, `type`, or `unsafe`, found `}`
+  --> $DIR/issue-20711-2.rs:9:1
+   |
+LL |     #[stable(feature = "rust1", since = "1.0.0")]
+   |                                                  - expected one of 10 possible tokens here
+LL | }
+   | ^ unexpected token
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-20711.rs b/src/test/ui/parser/issue-20711.rs
new file mode 100644
index 0000000..8d8401d
--- /dev/null
+++ b/src/test/ui/parser/issue-20711.rs
@@ -0,0 +1,9 @@
+// ignore-tidy-linelength
+
+struct Foo;
+
+impl Foo {
+    #[stable(feature = "rust1", since = "1.0.0")]
+} //~ ERROR expected one of `async`, `const`, `crate`, `default`, `existential`, `extern`, `fn`, `pub`, `type`, or
+
+fn main() {}
diff --git a/src/test/ui/parser/issue-20711.stderr b/src/test/ui/parser/issue-20711.stderr
new file mode 100644
index 0000000..26b819f
--- /dev/null
+++ b/src/test/ui/parser/issue-20711.stderr
@@ -0,0 +1,10 @@
+error: expected one of `async`, `const`, `crate`, `default`, `existential`, `extern`, `fn`, `pub`, `type`, or `unsafe`, found `}`
+  --> $DIR/issue-20711.rs:7:1
+   |
+LL |     #[stable(feature = "rust1", since = "1.0.0")]
+   |                                                  - expected one of 10 possible tokens here
+LL | }
+   | ^ unexpected token
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-21153.rs b/src/test/ui/parser/issue-21153.rs
new file mode 100644
index 0000000..46cd45f
--- /dev/null
+++ b/src/test/ui/parser/issue-21153.rs
@@ -0,0 +1,5 @@
+trait MyTrait<T>: Iterator { //~ ERROR missing `fn`, `type`, or `const`
+    Item = T;
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/issue-21153.stderr b/src/test/ui/parser/issue-21153.stderr
new file mode 100644
index 0000000..70f55f0
--- /dev/null
+++ b/src/test/ui/parser/issue-21153.stderr
@@ -0,0 +1,10 @@
+error: missing `fn`, `type`, or `const` for trait-item declaration
+  --> $DIR/issue-21153.rs:1:29
+   |
+LL |   trait MyTrait<T>: Iterator {
+   |  _____________________________^
+LL | |     Item = T;
+   | |____^ missing `fn`, `type`, or `const`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-22647.rs b/src/test/ui/parser/issue-22647.rs
new file mode 100644
index 0000000..25cd7ff
--- /dev/null
+++ b/src/test/ui/parser/issue-22647.rs
@@ -0,0 +1,15 @@
+fn main() {
+    let caller<F> = |f: F|  //~ ERROR expected one of `:`, `;`, `=`, or `@`, found `<`
+    where F: Fn() -> i32
+    {
+        let x = f();
+        println!("Y {}",x);
+        return x;
+    };
+
+    caller(bar_handler);
+}
+
+fn bar_handler() -> i32 {
+    5
+}
diff --git a/src/test/ui/parser/issue-22647.stderr b/src/test/ui/parser/issue-22647.stderr
new file mode 100644
index 0000000..2dc56a5
--- /dev/null
+++ b/src/test/ui/parser/issue-22647.stderr
@@ -0,0 +1,8 @@
+error: expected one of `:`, `;`, `=`, or `@`, found `<`
+  --> $DIR/issue-22647.rs:2:15
+   |
+LL |     let caller<F> = |f: F|
+   |               ^ expected one of `:`, `;`, `=`, or `@` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-22712.rs b/src/test/ui/parser/issue-22712.rs
new file mode 100644
index 0000000..b03d578
--- /dev/null
+++ b/src/test/ui/parser/issue-22712.rs
@@ -0,0 +1,9 @@
+struct Foo<B> {
+    buffer: B
+}
+
+fn bar() {
+    let Foo<Vec<u8>>  //~ ERROR expected one of `:`, `;`, `=`, or `@`, found `<`
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/issue-22712.stderr b/src/test/ui/parser/issue-22712.stderr
new file mode 100644
index 0000000..167eaf9
--- /dev/null
+++ b/src/test/ui/parser/issue-22712.stderr
@@ -0,0 +1,8 @@
+error: expected one of `:`, `;`, `=`, or `@`, found `<`
+  --> $DIR/issue-22712.rs:6:12
+   |
+LL |     let Foo<Vec<u8>>
+   |            ^ expected one of `:`, `;`, `=`, or `@` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-2354-1.rs b/src/test/ui/parser/issue-2354-1.rs
new file mode 100644
index 0000000..7e4e24f
--- /dev/null
+++ b/src/test/ui/parser/issue-2354-1.rs
@@ -0,0 +1 @@
+static foo: isize = 2; } //~ ERROR unexpected close delimiter:
diff --git a/src/test/ui/parser/issue-2354-1.stderr b/src/test/ui/parser/issue-2354-1.stderr
new file mode 100644
index 0000000..7c08375
--- /dev/null
+++ b/src/test/ui/parser/issue-2354-1.stderr
@@ -0,0 +1,8 @@
+error: unexpected close delimiter: `}`
+  --> $DIR/issue-2354-1.rs:1:24
+   |
+LL | static foo: isize = 2; }
+   |                        ^ unexpected close delimiter
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-2354.rs b/src/test/ui/parser/issue-2354.rs
new file mode 100644
index 0000000..565f848
--- /dev/null
+++ b/src/test/ui/parser/issue-2354.rs
@@ -0,0 +1,15 @@
+fn foo() { //~ NOTE un-closed delimiter
+  match Some(10) {
+  //~^ NOTE this delimiter might not be properly closed...
+      Some(y) => { panic!(); }
+      None => { panic!(); }
+}
+//~^ NOTE ...as it matches this but it has different indentation
+
+fn bar() {
+    let mut i = 0;
+    while (i < 1000) {}
+}
+
+fn main() {} //~ NOTE here is a function named 'main'
+             //~ ERROR this file contains an un-closed delimiter
diff --git a/src/test/ui/parser/issue-2354.stderr b/src/test/ui/parser/issue-2354.stderr
new file mode 100644
index 0000000..7098da7
--- /dev/null
+++ b/src/test/ui/parser/issue-2354.stderr
@@ -0,0 +1,26 @@
+error: this file contains an un-closed delimiter
+  --> $DIR/issue-2354.rs:15:66
+   |
+LL | fn foo() {
+   |          - un-closed delimiter
+LL |   match Some(10) {
+   |                  - this delimiter might not be properly closed...
+...
+LL | }
+   | - ...as it matches this but it has different indentation
+...
+LL |
+   |                                                                  ^
+
+error[E0601]: `main` function not found in crate `issue_2354`
+   |
+   = note: the main function must be defined at the crate level but you have one or more functions named 'main' that are not defined at the crate level. Either move the definition or attach the `#[main]` attribute to override this behavior.
+note: here is a function named 'main'
+  --> $DIR/issue-2354.rs:14:1
+   |
+LL | fn main() {}
+   | ^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0601`.
diff --git a/src/test/ui/parser/issue-23620-invalid-escapes.rs b/src/test/ui/parser/issue-23620-invalid-escapes.rs
new file mode 100644
index 0000000..b4b8f1f
--- /dev/null
+++ b/src/test/ui/parser/issue-23620-invalid-escapes.rs
@@ -0,0 +1,41 @@
+// compile-flags: -Z continue-parse-after-error
+
+fn main() {
+    let _ = b"\u{a66e}";
+    //~^ ERROR unicode escape sequences cannot be used as a byte or in a byte string
+
+    let _ = b'\u{a66e}';
+    //~^ ERROR unicode escape sequences cannot be used as a byte or in a byte string
+
+    let _ = b'\u';
+    //~^ ERROR incorrect unicode escape sequence
+    //~^^ ERROR unicode escape sequences cannot be used as a byte or in a byte string
+
+    let _ = b'\x5';
+    //~^ ERROR numeric character escape is too short
+
+    let _ = b'\xxy';
+    //~^ ERROR invalid character in numeric character escape: x
+    //~^^ ERROR invalid character in numeric character escape: y
+
+    let _ = '\x5';
+    //~^ ERROR numeric character escape is too short
+
+    let _ = '\xxy';
+    //~^ ERROR invalid character in numeric character escape: x
+    //~^^ ERROR invalid character in numeric character escape: y
+
+    let _ = b"\u{a4a4} \xf \u";
+    //~^ ERROR unicode escape sequences cannot be used as a byte or in a byte string
+    //~^^ ERROR invalid character in numeric character escape:
+    //~^^^ ERROR incorrect unicode escape sequence
+    //~^^^^ ERROR unicode escape sequences cannot be used as a byte or in a byte string
+
+    let _ = "\xf \u";
+    //~^ ERROR invalid character in numeric character escape:
+    //~^^ ERROR form of character escape may only be used with characters in the range [\x00-\x7f]
+    //~^^^ ERROR incorrect unicode escape sequence
+
+    let _ = "\u8f";
+    //~^ ERROR incorrect unicode escape sequence
+}
diff --git a/src/test/ui/parser/issue-23620-invalid-escapes.stderr b/src/test/ui/parser/issue-23620-invalid-escapes.stderr
new file mode 100644
index 0000000..295ba3b
--- /dev/null
+++ b/src/test/ui/parser/issue-23620-invalid-escapes.stderr
@@ -0,0 +1,118 @@
+error: unicode escape sequences cannot be used as a byte or in a byte string
+  --> $DIR/issue-23620-invalid-escapes.rs:4:15
+   |
+LL |     let _ = b"\u{a66e}";
+   |               ^^^^^^^^
+
+error: unicode escape sequences cannot be used as a byte or in a byte string
+  --> $DIR/issue-23620-invalid-escapes.rs:7:15
+   |
+LL |     let _ = b'\u{a66e}';
+   |               ^^^^^^^^
+
+error: incorrect unicode escape sequence
+  --> $DIR/issue-23620-invalid-escapes.rs:10:15
+   |
+LL |     let _ = b'\u';
+   |               ^^ incorrect unicode escape sequence
+   |
+   = help: format of unicode escape sequences is `\u{...}`
+
+error: unicode escape sequences cannot be used as a byte or in a byte string
+  --> $DIR/issue-23620-invalid-escapes.rs:10:15
+   |
+LL |     let _ = b'\u';
+   |               ^^
+
+error: numeric character escape is too short
+  --> $DIR/issue-23620-invalid-escapes.rs:14:17
+   |
+LL |     let _ = b'\x5';
+   |                 ^
+
+error: invalid character in numeric character escape: x
+  --> $DIR/issue-23620-invalid-escapes.rs:17:17
+   |
+LL |     let _ = b'\xxy';
+   |                 ^
+
+error: invalid character in numeric character escape: y
+  --> $DIR/issue-23620-invalid-escapes.rs:17:18
+   |
+LL |     let _ = b'\xxy';
+   |                  ^
+
+error: numeric character escape is too short
+  --> $DIR/issue-23620-invalid-escapes.rs:21:16
+   |
+LL |     let _ = '\x5';
+   |                ^
+
+error: invalid character in numeric character escape: x
+  --> $DIR/issue-23620-invalid-escapes.rs:24:16
+   |
+LL |     let _ = '\xxy';
+   |                ^
+
+error: invalid character in numeric character escape: y
+  --> $DIR/issue-23620-invalid-escapes.rs:24:17
+   |
+LL |     let _ = '\xxy';
+   |                 ^
+
+error: unicode escape sequences cannot be used as a byte or in a byte string
+  --> $DIR/issue-23620-invalid-escapes.rs:28:15
+   |
+LL |     let _ = b"\u{a4a4} \xf \u";
+   |               ^^^^^^^^
+
+error: invalid character in numeric character escape:  
+  --> $DIR/issue-23620-invalid-escapes.rs:28:27
+   |
+LL |     let _ = b"\u{a4a4} \xf \u";
+   |                           ^
+
+error: incorrect unicode escape sequence
+  --> $DIR/issue-23620-invalid-escapes.rs:28:28
+   |
+LL |     let _ = b"\u{a4a4} \xf \u";
+   |                            ^^ incorrect unicode escape sequence
+   |
+   = help: format of unicode escape sequences is `\u{...}`
+
+error: unicode escape sequences cannot be used as a byte or in a byte string
+  --> $DIR/issue-23620-invalid-escapes.rs:28:28
+   |
+LL |     let _ = b"\u{a4a4} \xf \u";
+   |                            ^^
+
+error: invalid character in numeric character escape:  
+  --> $DIR/issue-23620-invalid-escapes.rs:34:17
+   |
+LL |     let _ = "\xf \u";
+   |                 ^
+
+error: this form of character escape may only be used with characters in the range [\x00-\x7f]
+  --> $DIR/issue-23620-invalid-escapes.rs:34:16
+   |
+LL |     let _ = "\xf \u";
+   |                ^^
+
+error: incorrect unicode escape sequence
+  --> $DIR/issue-23620-invalid-escapes.rs:34:18
+   |
+LL |     let _ = "\xf \u";
+   |                  ^^ incorrect unicode escape sequence
+   |
+   = help: format of unicode escape sequences is `\u{...}`
+
+error: incorrect unicode escape sequence
+  --> $DIR/issue-23620-invalid-escapes.rs:39:14
+   |
+LL |     let _ = "\u8f";
+   |              ^^--
+   |              |
+   |              help: format of unicode escape sequences uses braces: `\u{8f}`
+
+error: aborting due to 18 previous errors
+
diff --git a/src/test/ui/parser/issue-24197.rs b/src/test/ui/parser/issue-24197.rs
new file mode 100644
index 0000000..005ff9f
--- /dev/null
+++ b/src/test/ui/parser/issue-24197.rs
@@ -0,0 +1,3 @@
+fn main() {
+    let buf[0] = 0; //~ ERROR expected one of `:`, `;`, `=`, or `@`, found `[`
+}
diff --git a/src/test/ui/parser/issue-24197.stderr b/src/test/ui/parser/issue-24197.stderr
new file mode 100644
index 0000000..2dfb314
--- /dev/null
+++ b/src/test/ui/parser/issue-24197.stderr
@@ -0,0 +1,8 @@
+error: expected one of `:`, `;`, `=`, or `@`, found `[`
+  --> $DIR/issue-24197.rs:2:12
+   |
+LL |     let buf[0] = 0;
+   |            ^ expected one of `:`, `;`, `=`, or `@` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-24375.rs b/src/test/ui/parser/issue-24375.rs
new file mode 100644
index 0000000..1d128d3
--- /dev/null
+++ b/src/test/ui/parser/issue-24375.rs
@@ -0,0 +1,9 @@
+static tmp : [&'static str; 2]  = ["hello", "he"];
+
+fn main() {
+    let z = "hello";
+    match z {
+        tmp[0] => {} //~ ERROR expected one of `=>`, `@`, `if`, or `|`, found `[`
+        _ => {}
+    }
+}
diff --git a/src/test/ui/parser/issue-24375.stderr b/src/test/ui/parser/issue-24375.stderr
new file mode 100644
index 0000000..e45b08b
--- /dev/null
+++ b/src/test/ui/parser/issue-24375.stderr
@@ -0,0 +1,8 @@
+error: expected one of `=>`, `@`, `if`, or `|`, found `[`
+  --> $DIR/issue-24375.rs:6:12
+   |
+LL |         tmp[0] => {}
+   |            ^ expected one of `=>`, `@`, `if`, or `|` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-24780.rs b/src/test/ui/parser/issue-24780.rs
new file mode 100644
index 0000000..799cdd8
--- /dev/null
+++ b/src/test/ui/parser/issue-24780.rs
@@ -0,0 +1,8 @@
+// Verify that '>' is not both expected and found at the same time, as it used
+// to happen in #24780. For example, following should be an error:
+// expected one of ..., `>`, ... found `>`
+
+fn foo() -> Vec<usize>> {
+    //~^ ERROR expected one of `!`, `+`, `::`, `where`, or `{`, found `>`
+    Vec::new()
+}
diff --git a/src/test/ui/parser/issue-24780.stderr b/src/test/ui/parser/issue-24780.stderr
new file mode 100644
index 0000000..469c034
--- /dev/null
+++ b/src/test/ui/parser/issue-24780.stderr
@@ -0,0 +1,8 @@
+error: expected one of `!`, `+`, `::`, `where`, or `{`, found `>`
+  --> $DIR/issue-24780.rs:5:23
+   |
+LL | fn foo() -> Vec<usize>> {
+   |                       ^ expected one of `!`, `+`, `::`, `where`, or `{` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-27255.rs b/src/test/ui/parser/issue-27255.rs
new file mode 100644
index 0000000..d619688
--- /dev/null
+++ b/src/test/ui/parser/issue-27255.rs
@@ -0,0 +1,10 @@
+trait A {}
+
+impl A .. {}
+//~^ ERROR missing `for` in a trait impl
+//~| ERROR `impl Trait for .. {}` is an obsolete syntax
+
+impl A      usize {}
+//~^ ERROR missing `for` in a trait impl
+
+fn main() {}
diff --git a/src/test/ui/parser/issue-27255.stderr b/src/test/ui/parser/issue-27255.stderr
new file mode 100644
index 0000000..391a235
--- /dev/null
+++ b/src/test/ui/parser/issue-27255.stderr
@@ -0,0 +1,22 @@
+error: missing `for` in a trait impl
+  --> $DIR/issue-27255.rs:3:7
+   |
+LL | impl A .. {}
+   |       ^ help: add `for` here
+
+error: missing `for` in a trait impl
+  --> $DIR/issue-27255.rs:7:7
+   |
+LL | impl A      usize {}
+   |       ^^^^^^ help: add `for` here
+
+error: `impl Trait for .. {}` is an obsolete syntax
+  --> $DIR/issue-27255.rs:3:1
+   |
+LL | impl A .. {}
+   | ^^^^^^^^^^^^
+   |
+   = help: use `auto trait Trait {}` instead
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/parser/issue-30318.rs b/src/test/ui/parser/issue-30318.rs
new file mode 100644
index 0000000..38e30de
--- /dev/null
+++ b/src/test/ui/parser/issue-30318.rs
@@ -0,0 +1,7 @@
+fn foo() { }
+
+//! Misplaced comment...
+//~^ ERROR expected outer doc comment
+//~| NOTE inner doc comments like this (starting with `//!` or `/*!`) can only appear before items
+
+fn main() { }
diff --git a/src/test/ui/parser/issue-30318.stderr b/src/test/ui/parser/issue-30318.stderr
new file mode 100644
index 0000000..489451b
--- /dev/null
+++ b/src/test/ui/parser/issue-30318.stderr
@@ -0,0 +1,10 @@
+error: expected outer doc comment
+  --> $DIR/issue-30318.rs:3:1
+   |
+LL | //! Misplaced comment...
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: inner doc comments like this (starting with `//!` or `/*!`) can only appear before items
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-3036.rs b/src/test/ui/parser/issue-3036.rs
new file mode 100644
index 0000000..00b241b
--- /dev/null
+++ b/src/test/ui/parser/issue-3036.rs
@@ -0,0 +1,6 @@
+// Testing that semicolon tokens are printed correctly in errors
+
+fn main()
+{
+    let x = 3
+} //~ ERROR: expected one of `.`, `;`, `?`, or an operator, found `}`
diff --git a/src/test/ui/parser/issue-3036.stderr b/src/test/ui/parser/issue-3036.stderr
new file mode 100644
index 0000000..18947b8
--- /dev/null
+++ b/src/test/ui/parser/issue-3036.stderr
@@ -0,0 +1,10 @@
+error: expected one of `.`, `;`, `?`, or an operator, found `}`
+  --> $DIR/issue-3036.rs:6:1
+   |
+LL |     let x = 3
+   |              - expected one of `.`, `;`, `?`, or an operator here
+LL | }
+   | ^ unexpected token
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-32214.rs b/src/test/ui/parser/issue-32214.rs
new file mode 100644
index 0000000..7191a32
--- /dev/null
+++ b/src/test/ui/parser/issue-32214.rs
@@ -0,0 +1,8 @@
+// compile-flags: -Z continue-parse-after-error
+
+trait Trait<T> { type Item; }
+
+pub fn test<W, I: Trait<Item=(), W> >() {}
+//~^ ERROR associated type bindings must be declared after generic parameters
+
+fn main() { }
diff --git a/src/test/ui/parser/issue-32214.stderr b/src/test/ui/parser/issue-32214.stderr
new file mode 100644
index 0000000..7022019
--- /dev/null
+++ b/src/test/ui/parser/issue-32214.stderr
@@ -0,0 +1,10 @@
+error: associated type bindings must be declared after generic parameters
+  --> $DIR/issue-32214.rs:5:25
+   |
+LL | pub fn test<W, I: Trait<Item=(), W> >() {}
+   |                         -------^^^
+   |                         |
+   |                         this associated type binding should be moved after the generic parameters
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-32446.rs b/src/test/ui/parser/issue-32446.rs
new file mode 100644
index 0000000..53e519a
--- /dev/null
+++ b/src/test/ui/parser/issue-32446.rs
@@ -0,0 +1,4 @@
+fn main() {}
+
+// This used to end up in an infite loop trying to bump past EOF.
+trait T { ... } //~ ERROR
diff --git a/src/test/ui/parser/issue-32446.stderr b/src/test/ui/parser/issue-32446.stderr
new file mode 100644
index 0000000..b0c18f4
--- /dev/null
+++ b/src/test/ui/parser/issue-32446.stderr
@@ -0,0 +1,8 @@
+error: expected one of `async`, `const`, `extern`, `fn`, `type`, `unsafe`, or `}`, found `...`
+  --> $DIR/issue-32446.rs:4:11
+   |
+LL | trait T { ... }
+   |           ^^^ expected one of 7 possible tokens here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-32501.rs b/src/test/ui/parser/issue-32501.rs
new file mode 100644
index 0000000..9c01a5c
--- /dev/null
+++ b/src/test/ui/parser/issue-32501.rs
@@ -0,0 +1,8 @@
+fn main() {
+    let a = 0;
+    let _b = 0;
+    let _ = 0;
+    let mut b = 0;
+    let mut _b = 0;
+    let mut _ = 0; //~ ERROR expected identifier, found reserved identifier `_`
+}
diff --git a/src/test/ui/parser/issue-32501.stderr b/src/test/ui/parser/issue-32501.stderr
new file mode 100644
index 0000000..97efb89
--- /dev/null
+++ b/src/test/ui/parser/issue-32501.stderr
@@ -0,0 +1,8 @@
+error: expected identifier, found reserved identifier `_`
+  --> $DIR/issue-32501.rs:7:13
+   |
+LL |     let mut _ = 0;
+   |             ^ expected identifier, found reserved identifier
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-32505.rs b/src/test/ui/parser/issue-32505.rs
new file mode 100644
index 0000000..49e7a2f
--- /dev/null
+++ b/src/test/ui/parser/issue-32505.rs
@@ -0,0 +1,7 @@
+// compile-flags: -Z continue-parse-after-error
+
+pub fn test() {
+    foo(|_|) //~ ERROR expected expression, found `)`
+}
+
+fn main() { }
diff --git a/src/test/ui/parser/issue-32505.stderr b/src/test/ui/parser/issue-32505.stderr
new file mode 100644
index 0000000..f812646
--- /dev/null
+++ b/src/test/ui/parser/issue-32505.stderr
@@ -0,0 +1,8 @@
+error: expected expression, found `)`
+  --> $DIR/issue-32505.rs:4:12
+   |
+LL |     foo(|_|)
+   |            ^ expected expression
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-33262.rs b/src/test/ui/parser/issue-33262.rs
new file mode 100644
index 0000000..3a612f9
--- /dev/null
+++ b/src/test/ui/parser/issue-33262.rs
@@ -0,0 +1,6 @@
+// Issue #33262
+
+pub fn main() {
+    for i in 0..a as { }
+    //~^ ERROR expected type, found `{`
+}
diff --git a/src/test/ui/parser/issue-33262.stderr b/src/test/ui/parser/issue-33262.stderr
new file mode 100644
index 0000000..c2491df
--- /dev/null
+++ b/src/test/ui/parser/issue-33262.stderr
@@ -0,0 +1,8 @@
+error: expected type, found `{`
+  --> $DIR/issue-33262.rs:4:22
+   |
+LL |     for i in 0..a as { }
+   |                      ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-33413.rs b/src/test/ui/parser/issue-33413.rs
new file mode 100644
index 0000000..2ec8695
--- /dev/null
+++ b/src/test/ui/parser/issue-33413.rs
@@ -0,0 +1,8 @@
+struct S;
+
+impl S {
+    fn f(*, a: u8) -> u8 {}
+    //~^ ERROR expected argument name, found `*`
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/issue-33413.stderr b/src/test/ui/parser/issue-33413.stderr
new file mode 100644
index 0000000..f6f096b
--- /dev/null
+++ b/src/test/ui/parser/issue-33413.stderr
@@ -0,0 +1,8 @@
+error: expected argument name, found `*`
+  --> $DIR/issue-33413.rs:4:10
+   |
+LL |     fn f(*, a: u8) -> u8 {}
+   |          ^ expected argument name
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-33418.fixed b/src/test/ui/parser/issue-33418.fixed
new file mode 100644
index 0000000..2aaa3b5
--- /dev/null
+++ b/src/test/ui/parser/issue-33418.fixed
@@ -0,0 +1,19 @@
+// run-rustfix
+
+trait Tr {}
+//~^ ERROR negative trait bounds are not supported
+trait Tr2: SuperA {}
+//~^ ERROR negative trait bounds are not supported
+trait Tr3: SuperB {}
+//~^ ERROR negative trait bounds are not supported
+trait Tr4: SuperB + SuperD {}
+//~^ ERROR negative trait bounds are not supported
+trait Tr5 {}
+//~^ ERROR negative trait bounds are not supported
+
+trait SuperA {}
+trait SuperB {}
+trait SuperC {}
+trait SuperD {}
+
+fn main() {}
diff --git a/src/test/ui/parser/issue-33418.rs b/src/test/ui/parser/issue-33418.rs
new file mode 100644
index 0000000..5533152
--- /dev/null
+++ b/src/test/ui/parser/issue-33418.rs
@@ -0,0 +1,21 @@
+// run-rustfix
+
+trait Tr: !SuperA {}
+//~^ ERROR negative trait bounds are not supported
+trait Tr2: SuperA + !SuperB {}
+//~^ ERROR negative trait bounds are not supported
+trait Tr3: !SuperA + SuperB {}
+//~^ ERROR negative trait bounds are not supported
+trait Tr4: !SuperA + SuperB
+    + !SuperC + SuperD {}
+//~^ ERROR negative trait bounds are not supported
+trait Tr5: !SuperA
+    + !SuperB {}
+//~^ ERROR negative trait bounds are not supported
+
+trait SuperA {}
+trait SuperB {}
+trait SuperC {}
+trait SuperD {}
+
+fn main() {}
diff --git a/src/test/ui/parser/issue-33418.stderr b/src/test/ui/parser/issue-33418.stderr
new file mode 100644
index 0000000..660d9fd
--- /dev/null
+++ b/src/test/ui/parser/issue-33418.stderr
@@ -0,0 +1,41 @@
+error: negative trait bounds are not supported
+  --> $DIR/issue-33418.rs:3:9
+   |
+LL | trait Tr: !SuperA {}
+   |         ^^^^^^^^^ negative trait bounds are not supported
+   = help: remove the trait bound
+
+error: negative trait bounds are not supported
+  --> $DIR/issue-33418.rs:5:19
+   |
+LL | trait Tr2: SuperA + !SuperB {}
+   |                   ^^^^^^^^^ negative trait bounds are not supported
+   = help: remove the trait bound
+
+error: negative trait bounds are not supported
+  --> $DIR/issue-33418.rs:7:10
+   |
+LL | trait Tr3: !SuperA + SuperB {}
+   |          ^^^^^^^^^ negative trait bounds are not supported
+   = help: remove the trait bound
+
+error: negative trait bounds are not supported
+  --> $DIR/issue-33418.rs:9:10
+   |
+LL | trait Tr4: !SuperA + SuperB
+   |          ^^^^^^^^^
+LL |     + !SuperC + SuperD {}
+   |     ^^^^^^^^^ negative trait bounds are not supported
+   = help: remove the trait bounds
+
+error: negative trait bounds are not supported
+  --> $DIR/issue-33418.rs:12:10
+   |
+LL | trait Tr5: !SuperA
+   |          ^^^^^^^^^
+LL |     + !SuperB {}
+   |     ^^^^^^^^^ negative trait bounds are not supported
+   = help: remove the trait bounds
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/ui/parser/issue-33455.rs b/src/test/ui/parser/issue-33455.rs
new file mode 100644
index 0000000..6dff63f
--- /dev/null
+++ b/src/test/ui/parser/issue-33455.rs
@@ -0,0 +1 @@
+use foo.bar; //~ ERROR expected one of `::`, `;`, or `as`, found `.`
diff --git a/src/test/ui/parser/issue-33455.stderr b/src/test/ui/parser/issue-33455.stderr
new file mode 100644
index 0000000..4516c38
--- /dev/null
+++ b/src/test/ui/parser/issue-33455.stderr
@@ -0,0 +1,8 @@
+error: expected one of `::`, `;`, or `as`, found `.`
+  --> $DIR/issue-33455.rs:1:8
+   |
+LL | use foo.bar;
+   |        ^ expected one of `::`, `;`, or `as` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-41155.rs b/src/test/ui/parser/issue-41155.rs
new file mode 100644
index 0000000..3c24d2b
--- /dev/null
+++ b/src/test/ui/parser/issue-41155.rs
@@ -0,0 +1,7 @@
+struct S;
+
+impl S {
+    pub
+} //~ ERROR expected one of
+
+fn main() {}
diff --git a/src/test/ui/parser/issue-41155.stderr b/src/test/ui/parser/issue-41155.stderr
new file mode 100644
index 0000000..719845e
--- /dev/null
+++ b/src/test/ui/parser/issue-41155.stderr
@@ -0,0 +1,10 @@
+error: expected one of `(`, `async`, `const`, `default`, `existential`, `extern`, `fn`, `type`, or `unsafe`, found `}`
+  --> $DIR/issue-41155.rs:5:1
+   |
+LL |     pub
+   |        - expected one of 9 possible tokens here
+LL | }
+   | ^ unexpected token
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-43692.rs b/src/test/ui/parser/issue-43692.rs
new file mode 100644
index 0000000..baf8baf
--- /dev/null
+++ b/src/test/ui/parser/issue-43692.rs
@@ -0,0 +1,3 @@
+fn main() {
+    '\u{_10FFFF}'; //~ ERROR invalid start of unicode escape
+}
diff --git a/src/test/ui/parser/issue-43692.stderr b/src/test/ui/parser/issue-43692.stderr
new file mode 100644
index 0000000..69a54af
--- /dev/null
+++ b/src/test/ui/parser/issue-43692.stderr
@@ -0,0 +1,8 @@
+error: invalid start of unicode escape
+  --> $DIR/issue-43692.rs:2:9
+   |
+LL |     '\u{_10FFFF}';
+   |         ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-5544-a.rs b/src/test/ui/parser/issue-5544-a.rs
new file mode 100644
index 0000000..303b902
--- /dev/null
+++ b/src/test/ui/parser/issue-5544-a.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let __isize = 340282366920938463463374607431768211456; // 2^128
+    //~^ ERROR int literal is too large
+}
diff --git a/src/test/ui/parser/issue-5544-a.stderr b/src/test/ui/parser/issue-5544-a.stderr
new file mode 100644
index 0000000..bc48853
--- /dev/null
+++ b/src/test/ui/parser/issue-5544-a.stderr
@@ -0,0 +1,8 @@
+error: int literal is too large
+  --> $DIR/issue-5544-a.rs:2:19
+   |
+LL |     let __isize = 340282366920938463463374607431768211456; // 2^128
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-5544-b.rs b/src/test/ui/parser/issue-5544-b.rs
new file mode 100644
index 0000000..fa40f15
--- /dev/null
+++ b/src/test/ui/parser/issue-5544-b.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let __isize = 0xffff_ffff_ffff_ffff_ffff_ffff_ffff_ffff_ff;
+    //~^ ERROR int literal is too large
+}
diff --git a/src/test/ui/parser/issue-5544-b.stderr b/src/test/ui/parser/issue-5544-b.stderr
new file mode 100644
index 0000000..3f15c0c
--- /dev/null
+++ b/src/test/ui/parser/issue-5544-b.stderr
@@ -0,0 +1,8 @@
+error: int literal is too large
+  --> $DIR/issue-5544-b.rs:2:19
+   |
+LL |     let __isize = 0xffff_ffff_ffff_ffff_ffff_ffff_ffff_ffff_ff;
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-5806.rs b/src/test/ui/parser/issue-5806.rs
new file mode 100644
index 0000000..b694642
--- /dev/null
+++ b/src/test/ui/parser/issue-5806.rs
@@ -0,0 +1,7 @@
+// normalize-stderr-test: "parser:.*\(" -> "parser: $$ACCESS_DENIED_MSG ("
+// normalize-stderr-test: "os error \d+" -> "os error $$ACCESS_DENIED_CODE"
+
+#[path = "../parser"]
+mod foo; //~ ERROR couldn't read
+
+fn main() {}
diff --git a/src/test/ui/parser/issue-5806.stderr b/src/test/ui/parser/issue-5806.stderr
new file mode 100644
index 0000000..6cf902c
--- /dev/null
+++ b/src/test/ui/parser/issue-5806.stderr
@@ -0,0 +1,8 @@
+error: couldn't read $DIR/../parser: $ACCESS_DENIED_MSG (os error $ACCESS_DENIED_CODE)
+  --> $DIR/issue-5806.rs:5:5
+   |
+LL | mod foo;
+   |     ^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-59418.rs b/src/test/ui/parser/issue-59418.rs
new file mode 100644
index 0000000..0fa191d
--- /dev/null
+++ b/src/test/ui/parser/issue-59418.rs
@@ -0,0 +1,18 @@
+struct X(i32,i32,i32);
+
+fn main() {
+    let a = X(1, 2, 3);
+    let b = a.1suffix;
+    //~^ ERROR suffixes on a tuple index are invalid
+    println!("{}", b);
+    let c = (1, 2, 3);
+    let d = c.1suffix;
+    //~^ ERROR suffixes on a tuple index are invalid
+    println!("{}", d);
+    let s = X { 0suffix: 0, 1: 1, 2: 2 };
+    //~^ ERROR suffixes on a tuple index are invalid
+    match s {
+        X { 0suffix: _, .. } => {}
+        //~^ ERROR suffixes on a tuple index are invalid
+    }
+}
diff --git a/src/test/ui/parser/issue-59418.stderr b/src/test/ui/parser/issue-59418.stderr
new file mode 100644
index 0000000..347051e
--- /dev/null
+++ b/src/test/ui/parser/issue-59418.stderr
@@ -0,0 +1,26 @@
+error: suffixes on a tuple index are invalid
+  --> $DIR/issue-59418.rs:5:15
+   |
+LL |     let b = a.1suffix;
+   |               ^^^^^^^ invalid suffix `suffix`
+
+error: suffixes on a tuple index are invalid
+  --> $DIR/issue-59418.rs:9:15
+   |
+LL |     let d = c.1suffix;
+   |               ^^^^^^^ invalid suffix `suffix`
+
+error: suffixes on a tuple index are invalid
+  --> $DIR/issue-59418.rs:12:17
+   |
+LL |     let s = X { 0suffix: 0, 1: 1, 2: 2 };
+   |                 ^^^^^^^ invalid suffix `suffix`
+
+error: suffixes on a tuple index are invalid
+  --> $DIR/issue-59418.rs:15:13
+   |
+LL |         X { 0suffix: _, .. } => {}
+   |             ^^^^^^^ invalid suffix `suffix`
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/parser/issue-6610.rs b/src/test/ui/parser/issue-6610.rs
new file mode 100644
index 0000000..2dfa08f
--- /dev/null
+++ b/src/test/ui/parser/issue-6610.rs
@@ -0,0 +1,3 @@
+trait Foo { fn a() } //~ ERROR expected `;` or `{`, found `}`
+
+fn main() {}
diff --git a/src/test/ui/parser/issue-6610.stderr b/src/test/ui/parser/issue-6610.stderr
new file mode 100644
index 0000000..22d93bf
--- /dev/null
+++ b/src/test/ui/parser/issue-6610.stderr
@@ -0,0 +1,8 @@
+error: expected `;` or `{`, found `}`
+  --> $DIR/issue-6610.rs:1:20
+   |
+LL | trait Foo { fn a() }
+   |                    ^ expected `;` or `{`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-8537.rs b/src/test/ui/parser/issue-8537.rs
new file mode 100644
index 0000000..9d0cbce
--- /dev/null
+++ b/src/test/ui/parser/issue-8537.rs
@@ -0,0 +1,5 @@
+pub extern
+  "invalid-ab_isize" //~ ERROR invalid ABI
+fn foo() {}
+
+fn main() {}
diff --git a/src/test/ui/parser/issue-8537.stderr b/src/test/ui/parser/issue-8537.stderr
new file mode 100644
index 0000000..82ca614
--- /dev/null
+++ b/src/test/ui/parser/issue-8537.stderr
@@ -0,0 +1,11 @@
+error[E0703]: invalid ABI: found `invalid-ab_isize`
+  --> $DIR/issue-8537.rs:2:3
+   |
+LL |   "invalid-ab_isize"
+   |   ^^^^^^^^^^^^^^^^^^ invalid ABI
+   |
+   = help: valid ABIs: cdecl, stdcall, fastcall, vectorcall, thiscall, aapcs, win64, sysv64, ptx-kernel, msp430-interrupt, x86-interrupt, amdgpu-kernel, Rust, C, system, rust-intrinsic, rust-call, platform-intrinsic, unadjusted
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0703`.
diff --git a/src/test/ui/parser/keyword-abstract.rs b/src/test/ui/parser/keyword-abstract.rs
new file mode 100644
index 0000000..890802a
--- /dev/null
+++ b/src/test/ui/parser/keyword-abstract.rs
@@ -0,0 +1,3 @@
+fn main() {
+    let abstract = (); //~ ERROR expected pattern, found reserved keyword `abstract`
+}
diff --git a/src/test/ui/parser/keyword-abstract.stderr b/src/test/ui/parser/keyword-abstract.stderr
new file mode 100644
index 0000000..2c79598
--- /dev/null
+++ b/src/test/ui/parser/keyword-abstract.stderr
@@ -0,0 +1,8 @@
+error: expected pattern, found reserved keyword `abstract`
+  --> $DIR/keyword-abstract.rs:2:9
+   |
+LL |     let abstract = ();
+   |         ^^^^^^^^ expected pattern
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/keyword-as-as-identifier.rs b/src/test/ui/parser/keyword-as-as-identifier.rs
new file mode 100644
index 0000000..23ff259
--- /dev/null
+++ b/src/test/ui/parser/keyword-as-as-identifier.rs
@@ -0,0 +1,5 @@
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py as'
+
+fn main() {
+    let as = "foo"; //~ error: expected pattern, found keyword `as`
+}
diff --git a/src/test/ui/parser/keyword-as-as-identifier.stderr b/src/test/ui/parser/keyword-as-as-identifier.stderr
new file mode 100644
index 0000000..ef46648
--- /dev/null
+++ b/src/test/ui/parser/keyword-as-as-identifier.stderr
@@ -0,0 +1,8 @@
+error: expected pattern, found keyword `as`
+  --> $DIR/keyword-as-as-identifier.rs:4:9
+   |
+LL |     let as = "foo";
+   |         ^^ expected pattern
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/keyword-box-as-identifier.rs b/src/test/ui/parser/keyword-box-as-identifier.rs
new file mode 100644
index 0000000..33961bb
--- /dev/null
+++ b/src/test/ui/parser/keyword-box-as-identifier.rs
@@ -0,0 +1,3 @@
+fn main() {
+    let box = "foo"; //~ error: expected pattern, found `=`
+}
diff --git a/src/test/ui/parser/keyword-box-as-identifier.stderr b/src/test/ui/parser/keyword-box-as-identifier.stderr
new file mode 100644
index 0000000..8b18594
--- /dev/null
+++ b/src/test/ui/parser/keyword-box-as-identifier.stderr
@@ -0,0 +1,8 @@
+error: expected pattern, found `=`
+  --> $DIR/keyword-box-as-identifier.rs:2:13
+   |
+LL |     let box = "foo";
+   |             ^ expected pattern
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/keyword-break-as-identifier.rs b/src/test/ui/parser/keyword-break-as-identifier.rs
new file mode 100644
index 0000000..5ee111d
--- /dev/null
+++ b/src/test/ui/parser/keyword-break-as-identifier.rs
@@ -0,0 +1,5 @@
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py break'
+
+fn main() {
+    let break = "foo"; //~ error: expected pattern, found keyword `break`
+}
diff --git a/src/test/ui/parser/keyword-break-as-identifier.stderr b/src/test/ui/parser/keyword-break-as-identifier.stderr
new file mode 100644
index 0000000..690bd84
--- /dev/null
+++ b/src/test/ui/parser/keyword-break-as-identifier.stderr
@@ -0,0 +1,8 @@
+error: expected pattern, found keyword `break`
+  --> $DIR/keyword-break-as-identifier.rs:4:9
+   |
+LL |     let break = "foo";
+   |         ^^^^^ expected pattern
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/keyword-const-as-identifier.rs b/src/test/ui/parser/keyword-const-as-identifier.rs
new file mode 100644
index 0000000..48fc142
--- /dev/null
+++ b/src/test/ui/parser/keyword-const-as-identifier.rs
@@ -0,0 +1,5 @@
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py const'
+
+fn main() {
+    let const = "foo"; //~ error: expected pattern, found keyword `const`
+}
diff --git a/src/test/ui/parser/keyword-const-as-identifier.stderr b/src/test/ui/parser/keyword-const-as-identifier.stderr
new file mode 100644
index 0000000..6da47f8
--- /dev/null
+++ b/src/test/ui/parser/keyword-const-as-identifier.stderr
@@ -0,0 +1,8 @@
+error: expected pattern, found keyword `const`
+  --> $DIR/keyword-const-as-identifier.rs:4:9
+   |
+LL |     let const = "foo";
+   |         ^^^^^ expected pattern
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/keyword-continue-as-identifier.rs b/src/test/ui/parser/keyword-continue-as-identifier.rs
new file mode 100644
index 0000000..06315a4
--- /dev/null
+++ b/src/test/ui/parser/keyword-continue-as-identifier.rs
@@ -0,0 +1,5 @@
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py continue'
+
+fn main() {
+    let continue = "foo"; //~ error: expected pattern, found keyword `continue`
+}
diff --git a/src/test/ui/parser/keyword-continue-as-identifier.stderr b/src/test/ui/parser/keyword-continue-as-identifier.stderr
new file mode 100644
index 0000000..4b0a659
--- /dev/null
+++ b/src/test/ui/parser/keyword-continue-as-identifier.stderr
@@ -0,0 +1,8 @@
+error: expected pattern, found keyword `continue`
+  --> $DIR/keyword-continue-as-identifier.rs:4:9
+   |
+LL |     let continue = "foo";
+   |         ^^^^^^^^ expected pattern
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/keyword-else-as-identifier.rs b/src/test/ui/parser/keyword-else-as-identifier.rs
new file mode 100644
index 0000000..0c69105
--- /dev/null
+++ b/src/test/ui/parser/keyword-else-as-identifier.rs
@@ -0,0 +1,5 @@
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py else'
+
+fn main() {
+    let else = "foo"; //~ error: expected pattern, found keyword `else`
+}
diff --git a/src/test/ui/parser/keyword-else-as-identifier.stderr b/src/test/ui/parser/keyword-else-as-identifier.stderr
new file mode 100644
index 0000000..bec7b7ba
--- /dev/null
+++ b/src/test/ui/parser/keyword-else-as-identifier.stderr
@@ -0,0 +1,8 @@
+error: expected pattern, found keyword `else`
+  --> $DIR/keyword-else-as-identifier.rs:4:9
+   |
+LL |     let else = "foo";
+   |         ^^^^ expected pattern
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/keyword-enum-as-identifier.rs b/src/test/ui/parser/keyword-enum-as-identifier.rs
new file mode 100644
index 0000000..d167580
--- /dev/null
+++ b/src/test/ui/parser/keyword-enum-as-identifier.rs
@@ -0,0 +1,5 @@
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py enum'
+
+fn main() {
+    let enum = "foo"; //~ error: expected pattern, found keyword `enum`
+}
diff --git a/src/test/ui/parser/keyword-enum-as-identifier.stderr b/src/test/ui/parser/keyword-enum-as-identifier.stderr
new file mode 100644
index 0000000..51a834f
--- /dev/null
+++ b/src/test/ui/parser/keyword-enum-as-identifier.stderr
@@ -0,0 +1,8 @@
+error: expected pattern, found keyword `enum`
+  --> $DIR/keyword-enum-as-identifier.rs:4:9
+   |
+LL |     let enum = "foo";
+   |         ^^^^ expected pattern
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/keyword-final.rs b/src/test/ui/parser/keyword-final.rs
new file mode 100644
index 0000000..e1cecd0
--- /dev/null
+++ b/src/test/ui/parser/keyword-final.rs
@@ -0,0 +1,3 @@
+fn main() {
+    let final = (); //~ ERROR expected pattern, found reserved keyword `final`
+}
diff --git a/src/test/ui/parser/keyword-final.stderr b/src/test/ui/parser/keyword-final.stderr
new file mode 100644
index 0000000..e837264
--- /dev/null
+++ b/src/test/ui/parser/keyword-final.stderr
@@ -0,0 +1,8 @@
+error: expected pattern, found reserved keyword `final`
+  --> $DIR/keyword-final.rs:2:9
+   |
+LL |     let final = ();
+   |         ^^^^^ expected pattern
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/keyword-fn-as-identifier.rs b/src/test/ui/parser/keyword-fn-as-identifier.rs
new file mode 100644
index 0000000..bca2d59
--- /dev/null
+++ b/src/test/ui/parser/keyword-fn-as-identifier.rs
@@ -0,0 +1,5 @@
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py fn'
+
+fn main() {
+    let fn = "foo"; //~ error: expected pattern, found keyword `fn`
+}
diff --git a/src/test/ui/parser/keyword-fn-as-identifier.stderr b/src/test/ui/parser/keyword-fn-as-identifier.stderr
new file mode 100644
index 0000000..a071a40
--- /dev/null
+++ b/src/test/ui/parser/keyword-fn-as-identifier.stderr
@@ -0,0 +1,8 @@
+error: expected pattern, found keyword `fn`
+  --> $DIR/keyword-fn-as-identifier.rs:4:9
+   |
+LL |     let fn = "foo";
+   |         ^^ expected pattern
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/keyword-for-as-identifier.rs b/src/test/ui/parser/keyword-for-as-identifier.rs
new file mode 100644
index 0000000..ce49fd9
--- /dev/null
+++ b/src/test/ui/parser/keyword-for-as-identifier.rs
@@ -0,0 +1,5 @@
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py for'
+
+fn main() {
+    let for = "foo"; //~ error: expected pattern, found keyword `for`
+}
diff --git a/src/test/ui/parser/keyword-for-as-identifier.stderr b/src/test/ui/parser/keyword-for-as-identifier.stderr
new file mode 100644
index 0000000..090046c
--- /dev/null
+++ b/src/test/ui/parser/keyword-for-as-identifier.stderr
@@ -0,0 +1,8 @@
+error: expected pattern, found keyword `for`
+  --> $DIR/keyword-for-as-identifier.rs:4:9
+   |
+LL |     let for = "foo";
+   |         ^^^ expected pattern
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/keyword-if-as-identifier.rs b/src/test/ui/parser/keyword-if-as-identifier.rs
new file mode 100644
index 0000000..a130297
--- /dev/null
+++ b/src/test/ui/parser/keyword-if-as-identifier.rs
@@ -0,0 +1,5 @@
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py if'
+
+fn main() {
+    let if = "foo"; //~ error: expected pattern, found keyword `if`
+}
diff --git a/src/test/ui/parser/keyword-if-as-identifier.stderr b/src/test/ui/parser/keyword-if-as-identifier.stderr
new file mode 100644
index 0000000..98bfdb4
--- /dev/null
+++ b/src/test/ui/parser/keyword-if-as-identifier.stderr
@@ -0,0 +1,8 @@
+error: expected pattern, found keyword `if`
+  --> $DIR/keyword-if-as-identifier.rs:4:9
+   |
+LL |     let if = "foo";
+   |         ^^ expected pattern
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/keyword-impl-as-identifier.rs b/src/test/ui/parser/keyword-impl-as-identifier.rs
new file mode 100644
index 0000000..95a3448
--- /dev/null
+++ b/src/test/ui/parser/keyword-impl-as-identifier.rs
@@ -0,0 +1,5 @@
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py impl'
+
+fn main() {
+    let impl = "foo"; //~ error: expected pattern, found keyword `impl`
+}
diff --git a/src/test/ui/parser/keyword-impl-as-identifier.stderr b/src/test/ui/parser/keyword-impl-as-identifier.stderr
new file mode 100644
index 0000000..2672959
--- /dev/null
+++ b/src/test/ui/parser/keyword-impl-as-identifier.stderr
@@ -0,0 +1,8 @@
+error: expected pattern, found keyword `impl`
+  --> $DIR/keyword-impl-as-identifier.rs:4:9
+   |
+LL |     let impl = "foo";
+   |         ^^^^ expected pattern
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/keyword-in-as-identifier.rs b/src/test/ui/parser/keyword-in-as-identifier.rs
new file mode 100644
index 0000000..e4499de
--- /dev/null
+++ b/src/test/ui/parser/keyword-in-as-identifier.rs
@@ -0,0 +1,5 @@
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py in'
+
+fn main() {
+    let in = "foo"; //~ error: expected pattern, found keyword `in`
+}
diff --git a/src/test/ui/parser/keyword-in-as-identifier.stderr b/src/test/ui/parser/keyword-in-as-identifier.stderr
new file mode 100644
index 0000000..98332b7
--- /dev/null
+++ b/src/test/ui/parser/keyword-in-as-identifier.stderr
@@ -0,0 +1,8 @@
+error: expected pattern, found keyword `in`
+  --> $DIR/keyword-in-as-identifier.rs:4:9
+   |
+LL |     let in = "foo";
+   |         ^^ expected pattern
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/keyword-let-as-identifier.rs b/src/test/ui/parser/keyword-let-as-identifier.rs
new file mode 100644
index 0000000..07c0ddf
--- /dev/null
+++ b/src/test/ui/parser/keyword-let-as-identifier.rs
@@ -0,0 +1,5 @@
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py let'
+
+fn main() {
+    let let = "foo"; //~ error: expected pattern, found keyword `let`
+}
diff --git a/src/test/ui/parser/keyword-let-as-identifier.stderr b/src/test/ui/parser/keyword-let-as-identifier.stderr
new file mode 100644
index 0000000..99dbc05
--- /dev/null
+++ b/src/test/ui/parser/keyword-let-as-identifier.stderr
@@ -0,0 +1,8 @@
+error: expected pattern, found keyword `let`
+  --> $DIR/keyword-let-as-identifier.rs:4:9
+   |
+LL |     let let = "foo";
+   |         ^^^ expected pattern
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/keyword-loop-as-identifier.rs b/src/test/ui/parser/keyword-loop-as-identifier.rs
new file mode 100644
index 0000000..8643ffe
--- /dev/null
+++ b/src/test/ui/parser/keyword-loop-as-identifier.rs
@@ -0,0 +1,5 @@
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py loop'
+
+fn main() {
+    let loop = "foo"; //~ error: expected pattern, found keyword `loop`
+}
diff --git a/src/test/ui/parser/keyword-loop-as-identifier.stderr b/src/test/ui/parser/keyword-loop-as-identifier.stderr
new file mode 100644
index 0000000..783507e
--- /dev/null
+++ b/src/test/ui/parser/keyword-loop-as-identifier.stderr
@@ -0,0 +1,8 @@
+error: expected pattern, found keyword `loop`
+  --> $DIR/keyword-loop-as-identifier.rs:4:9
+   |
+LL |     let loop = "foo";
+   |         ^^^^ expected pattern
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/keyword-match-as-identifier.rs b/src/test/ui/parser/keyword-match-as-identifier.rs
new file mode 100644
index 0000000..8ef6b68
--- /dev/null
+++ b/src/test/ui/parser/keyword-match-as-identifier.rs
@@ -0,0 +1,5 @@
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py match'
+
+fn main() {
+    let match = "foo"; //~ error: expected pattern, found keyword `match`
+}
diff --git a/src/test/ui/parser/keyword-match-as-identifier.stderr b/src/test/ui/parser/keyword-match-as-identifier.stderr
new file mode 100644
index 0000000..e56a115
--- /dev/null
+++ b/src/test/ui/parser/keyword-match-as-identifier.stderr
@@ -0,0 +1,8 @@
+error: expected pattern, found keyword `match`
+  --> $DIR/keyword-match-as-identifier.rs:4:9
+   |
+LL |     let match = "foo";
+   |         ^^^^^ expected pattern
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/keyword-mod-as-identifier.rs b/src/test/ui/parser/keyword-mod-as-identifier.rs
new file mode 100644
index 0000000..96bcdcc
--- /dev/null
+++ b/src/test/ui/parser/keyword-mod-as-identifier.rs
@@ -0,0 +1,5 @@
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py mod'
+
+fn main() {
+    let mod = "foo"; //~ error: expected pattern, found keyword `mod`
+}
diff --git a/src/test/ui/parser/keyword-mod-as-identifier.stderr b/src/test/ui/parser/keyword-mod-as-identifier.stderr
new file mode 100644
index 0000000..a8be2ce
--- /dev/null
+++ b/src/test/ui/parser/keyword-mod-as-identifier.stderr
@@ -0,0 +1,8 @@
+error: expected pattern, found keyword `mod`
+  --> $DIR/keyword-mod-as-identifier.rs:4:9
+   |
+LL |     let mod = "foo";
+   |         ^^^ expected pattern
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/keyword-move-as-identifier.rs b/src/test/ui/parser/keyword-move-as-identifier.rs
new file mode 100644
index 0000000..2193af5
--- /dev/null
+++ b/src/test/ui/parser/keyword-move-as-identifier.rs
@@ -0,0 +1,5 @@
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py move'
+
+fn main() {
+    let move = "foo"; //~ error: expected pattern, found keyword `move`
+}
diff --git a/src/test/ui/parser/keyword-move-as-identifier.stderr b/src/test/ui/parser/keyword-move-as-identifier.stderr
new file mode 100644
index 0000000..e0687e2
--- /dev/null
+++ b/src/test/ui/parser/keyword-move-as-identifier.stderr
@@ -0,0 +1,8 @@
+error: expected pattern, found keyword `move`
+  --> $DIR/keyword-move-as-identifier.rs:4:9
+   |
+LL |     let move = "foo";
+   |         ^^^^ expected pattern
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/keyword-mut-as-identifier.rs b/src/test/ui/parser/keyword-mut-as-identifier.rs
new file mode 100644
index 0000000..9b919d2
--- /dev/null
+++ b/src/test/ui/parser/keyword-mut-as-identifier.rs
@@ -0,0 +1,3 @@
+fn main() {
+    let mut = "foo"; //~ error: expected identifier, found `=`
+}
diff --git a/src/test/ui/parser/keyword-mut-as-identifier.stderr b/src/test/ui/parser/keyword-mut-as-identifier.stderr
new file mode 100644
index 0000000..0409608
--- /dev/null
+++ b/src/test/ui/parser/keyword-mut-as-identifier.stderr
@@ -0,0 +1,8 @@
+error: expected identifier, found `=`
+  --> $DIR/keyword-mut-as-identifier.rs:2:13
+   |
+LL |     let mut = "foo";
+   |             ^ expected identifier
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/keyword-override.rs b/src/test/ui/parser/keyword-override.rs
new file mode 100644
index 0000000..948a200
--- /dev/null
+++ b/src/test/ui/parser/keyword-override.rs
@@ -0,0 +1,3 @@
+fn main() {
+    let override = (); //~ ERROR expected pattern, found reserved keyword `override`
+}
diff --git a/src/test/ui/parser/keyword-override.stderr b/src/test/ui/parser/keyword-override.stderr
new file mode 100644
index 0000000..1bfc6c9
--- /dev/null
+++ b/src/test/ui/parser/keyword-override.stderr
@@ -0,0 +1,8 @@
+error: expected pattern, found reserved keyword `override`
+  --> $DIR/keyword-override.rs:2:9
+   |
+LL |     let override = ();
+   |         ^^^^^^^^ expected pattern
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/keyword-pub-as-identifier.rs b/src/test/ui/parser/keyword-pub-as-identifier.rs
new file mode 100644
index 0000000..2ed8cc6
--- /dev/null
+++ b/src/test/ui/parser/keyword-pub-as-identifier.rs
@@ -0,0 +1,5 @@
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py pub'
+
+fn main() {
+    let pub = "foo"; //~ error: expected pattern, found keyword `pub`
+}
diff --git a/src/test/ui/parser/keyword-pub-as-identifier.stderr b/src/test/ui/parser/keyword-pub-as-identifier.stderr
new file mode 100644
index 0000000..526ddcd
--- /dev/null
+++ b/src/test/ui/parser/keyword-pub-as-identifier.stderr
@@ -0,0 +1,8 @@
+error: expected pattern, found keyword `pub`
+  --> $DIR/keyword-pub-as-identifier.rs:4:9
+   |
+LL |     let pub = "foo";
+   |         ^^^ expected pattern
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/keyword-ref-as-identifier.rs b/src/test/ui/parser/keyword-ref-as-identifier.rs
new file mode 100644
index 0000000..f5e04b5
--- /dev/null
+++ b/src/test/ui/parser/keyword-ref-as-identifier.rs
@@ -0,0 +1,3 @@
+fn main() {
+    let ref = "foo"; //~ error: expected identifier, found `=`
+}
diff --git a/src/test/ui/parser/keyword-ref-as-identifier.stderr b/src/test/ui/parser/keyword-ref-as-identifier.stderr
new file mode 100644
index 0000000..618043d
--- /dev/null
+++ b/src/test/ui/parser/keyword-ref-as-identifier.stderr
@@ -0,0 +1,8 @@
+error: expected identifier, found `=`
+  --> $DIR/keyword-ref-as-identifier.rs:2:13
+   |
+LL |     let ref = "foo";
+   |             ^ expected identifier
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/keyword-return-as-identifier.rs b/src/test/ui/parser/keyword-return-as-identifier.rs
new file mode 100644
index 0000000..920931b
--- /dev/null
+++ b/src/test/ui/parser/keyword-return-as-identifier.rs
@@ -0,0 +1,5 @@
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py return'
+
+fn main() {
+    let return = "foo"; //~ error: expected pattern, found keyword `return`
+}
diff --git a/src/test/ui/parser/keyword-return-as-identifier.stderr b/src/test/ui/parser/keyword-return-as-identifier.stderr
new file mode 100644
index 0000000..c0156a6
--- /dev/null
+++ b/src/test/ui/parser/keyword-return-as-identifier.stderr
@@ -0,0 +1,8 @@
+error: expected pattern, found keyword `return`
+  --> $DIR/keyword-return-as-identifier.rs:4:9
+   |
+LL |     let return = "foo";
+   |         ^^^^^^ expected pattern
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/keyword-static-as-identifier.rs b/src/test/ui/parser/keyword-static-as-identifier.rs
new file mode 100644
index 0000000..3ccbfcc
--- /dev/null
+++ b/src/test/ui/parser/keyword-static-as-identifier.rs
@@ -0,0 +1,5 @@
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py static'
+
+fn main() {
+    let static = "foo"; //~ error: expected pattern, found keyword `static`
+}
diff --git a/src/test/ui/parser/keyword-static-as-identifier.stderr b/src/test/ui/parser/keyword-static-as-identifier.stderr
new file mode 100644
index 0000000..00a6597
--- /dev/null
+++ b/src/test/ui/parser/keyword-static-as-identifier.stderr
@@ -0,0 +1,8 @@
+error: expected pattern, found keyword `static`
+  --> $DIR/keyword-static-as-identifier.rs:4:9
+   |
+LL |     let static = "foo";
+   |         ^^^^^^ expected pattern
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/keyword-struct-as-identifier.rs b/src/test/ui/parser/keyword-struct-as-identifier.rs
new file mode 100644
index 0000000..69d8f19
--- /dev/null
+++ b/src/test/ui/parser/keyword-struct-as-identifier.rs
@@ -0,0 +1,5 @@
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py struct'
+
+fn main() {
+    let struct = "foo"; //~ error: expected pattern, found keyword `struct`
+}
diff --git a/src/test/ui/parser/keyword-struct-as-identifier.stderr b/src/test/ui/parser/keyword-struct-as-identifier.stderr
new file mode 100644
index 0000000..b2d6639
--- /dev/null
+++ b/src/test/ui/parser/keyword-struct-as-identifier.stderr
@@ -0,0 +1,8 @@
+error: expected pattern, found keyword `struct`
+  --> $DIR/keyword-struct-as-identifier.rs:4:9
+   |
+LL |     let struct = "foo";
+   |         ^^^^^^ expected pattern
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/keyword-trait-as-identifier.rs b/src/test/ui/parser/keyword-trait-as-identifier.rs
new file mode 100644
index 0000000..f628584
--- /dev/null
+++ b/src/test/ui/parser/keyword-trait-as-identifier.rs
@@ -0,0 +1,5 @@
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py trait'
+
+fn main() {
+    let trait = "foo"; //~ error: expected pattern, found keyword `trait`
+}
diff --git a/src/test/ui/parser/keyword-trait-as-identifier.stderr b/src/test/ui/parser/keyword-trait-as-identifier.stderr
new file mode 100644
index 0000000..b31c0df
--- /dev/null
+++ b/src/test/ui/parser/keyword-trait-as-identifier.stderr
@@ -0,0 +1,8 @@
+error: expected pattern, found keyword `trait`
+  --> $DIR/keyword-trait-as-identifier.rs:4:9
+   |
+LL |     let trait = "foo";
+   |         ^^^^^ expected pattern
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/keyword-try-as-identifier-edition2018.rs b/src/test/ui/parser/keyword-try-as-identifier-edition2018.rs
new file mode 100644
index 0000000..13a938b
--- /dev/null
+++ b/src/test/ui/parser/keyword-try-as-identifier-edition2018.rs
@@ -0,0 +1,5 @@
+// compile-flags: --edition 2018
+
+fn main() {
+    let try = "foo"; //~ error: expected pattern, found reserved keyword `try`
+}
diff --git a/src/test/ui/parser/keyword-try-as-identifier-edition2018.stderr b/src/test/ui/parser/keyword-try-as-identifier-edition2018.stderr
new file mode 100644
index 0000000..c342e3a
--- /dev/null
+++ b/src/test/ui/parser/keyword-try-as-identifier-edition2018.stderr
@@ -0,0 +1,8 @@
+error: expected pattern, found reserved keyword `try`
+  --> $DIR/keyword-try-as-identifier-edition2018.rs:4:9
+   |
+LL |     let try = "foo";
+   |         ^^^ expected pattern
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/keyword-type-as-identifier.rs b/src/test/ui/parser/keyword-type-as-identifier.rs
new file mode 100644
index 0000000..992547e
--- /dev/null
+++ b/src/test/ui/parser/keyword-type-as-identifier.rs
@@ -0,0 +1,5 @@
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py type'
+
+fn main() {
+    let type = "foo"; //~ error: expected pattern, found keyword `type`
+}
diff --git a/src/test/ui/parser/keyword-type-as-identifier.stderr b/src/test/ui/parser/keyword-type-as-identifier.stderr
new file mode 100644
index 0000000..b749c70
--- /dev/null
+++ b/src/test/ui/parser/keyword-type-as-identifier.stderr
@@ -0,0 +1,8 @@
+error: expected pattern, found keyword `type`
+  --> $DIR/keyword-type-as-identifier.rs:4:9
+   |
+LL |     let type = "foo";
+   |         ^^^^ expected pattern
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/keyword-typeof.rs b/src/test/ui/parser/keyword-typeof.rs
new file mode 100644
index 0000000..4ef1026
--- /dev/null
+++ b/src/test/ui/parser/keyword-typeof.rs
@@ -0,0 +1,3 @@
+fn main() {
+    let typeof = (); //~ ERROR expected pattern, found reserved keyword `typeof`
+}
diff --git a/src/test/ui/parser/keyword-typeof.stderr b/src/test/ui/parser/keyword-typeof.stderr
new file mode 100644
index 0000000..e7b1802
--- /dev/null
+++ b/src/test/ui/parser/keyword-typeof.stderr
@@ -0,0 +1,8 @@
+error: expected pattern, found reserved keyword `typeof`
+  --> $DIR/keyword-typeof.rs:2:9
+   |
+LL |     let typeof = ();
+   |         ^^^^^^ expected pattern
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/keyword-unsafe-as-identifier.rs b/src/test/ui/parser/keyword-unsafe-as-identifier.rs
new file mode 100644
index 0000000..adb20eb
--- /dev/null
+++ b/src/test/ui/parser/keyword-unsafe-as-identifier.rs
@@ -0,0 +1,5 @@
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py unsafe'
+
+fn main() {
+    let unsafe = "foo"; //~ error: expected pattern, found keyword `unsafe`
+}
diff --git a/src/test/ui/parser/keyword-unsafe-as-identifier.stderr b/src/test/ui/parser/keyword-unsafe-as-identifier.stderr
new file mode 100644
index 0000000..67935ce
--- /dev/null
+++ b/src/test/ui/parser/keyword-unsafe-as-identifier.stderr
@@ -0,0 +1,8 @@
+error: expected pattern, found keyword `unsafe`
+  --> $DIR/keyword-unsafe-as-identifier.rs:4:9
+   |
+LL |     let unsafe = "foo";
+   |         ^^^^^^ expected pattern
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/keyword-use-as-identifier.rs b/src/test/ui/parser/keyword-use-as-identifier.rs
new file mode 100644
index 0000000..198444b
--- /dev/null
+++ b/src/test/ui/parser/keyword-use-as-identifier.rs
@@ -0,0 +1,5 @@
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py use'
+
+fn main() {
+    let use = "foo"; //~ error: expected pattern, found keyword `use`
+}
diff --git a/src/test/ui/parser/keyword-use-as-identifier.stderr b/src/test/ui/parser/keyword-use-as-identifier.stderr
new file mode 100644
index 0000000..2c69d0a
--- /dev/null
+++ b/src/test/ui/parser/keyword-use-as-identifier.stderr
@@ -0,0 +1,8 @@
+error: expected pattern, found keyword `use`
+  --> $DIR/keyword-use-as-identifier.rs:4:9
+   |
+LL |     let use = "foo";
+   |         ^^^ expected pattern
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/keyword-where-as-identifier.rs b/src/test/ui/parser/keyword-where-as-identifier.rs
new file mode 100644
index 0000000..5624a8f
--- /dev/null
+++ b/src/test/ui/parser/keyword-where-as-identifier.rs
@@ -0,0 +1,5 @@
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py where'
+
+fn main() {
+    let where = "foo"; //~ error: expected pattern, found keyword `where`
+}
diff --git a/src/test/ui/parser/keyword-where-as-identifier.stderr b/src/test/ui/parser/keyword-where-as-identifier.stderr
new file mode 100644
index 0000000..fc01183
--- /dev/null
+++ b/src/test/ui/parser/keyword-where-as-identifier.stderr
@@ -0,0 +1,8 @@
+error: expected pattern, found keyword `where`
+  --> $DIR/keyword-where-as-identifier.rs:4:9
+   |
+LL |     let where = "foo";
+   |         ^^^^^ expected pattern
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/keyword-while-as-identifier.rs b/src/test/ui/parser/keyword-while-as-identifier.rs
new file mode 100644
index 0000000..c0a539d
--- /dev/null
+++ b/src/test/ui/parser/keyword-while-as-identifier.rs
@@ -0,0 +1,5 @@
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py while'
+
+fn main() {
+    let while = "foo"; //~ error: expected pattern, found keyword `while`
+}
diff --git a/src/test/ui/parser/keyword-while-as-identifier.stderr b/src/test/ui/parser/keyword-while-as-identifier.stderr
new file mode 100644
index 0000000..f72ac87
--- /dev/null
+++ b/src/test/ui/parser/keyword-while-as-identifier.stderr
@@ -0,0 +1,8 @@
+error: expected pattern, found keyword `while`
+  --> $DIR/keyword-while-as-identifier.rs:4:9
+   |
+LL |     let while = "foo";
+   |         ^^^^^ expected pattern
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/keyword.rs b/src/test/ui/parser/keyword.rs
new file mode 100644
index 0000000..1eb7886
--- /dev/null
+++ b/src/test/ui/parser/keyword.rs
@@ -0,0 +1,5 @@
+pub mod break {
+    //~^ ERROR expected identifier, found keyword `break`
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/keyword.stderr b/src/test/ui/parser/keyword.stderr
new file mode 100644
index 0000000..262467b
--- /dev/null
+++ b/src/test/ui/parser/keyword.stderr
@@ -0,0 +1,12 @@
+error: expected identifier, found keyword `break`
+  --> $DIR/keyword.rs:1:9
+   |
+LL | pub mod break {
+   |         ^^^^^ expected identifier, found keyword
+help: you can escape reserved keywords to use them as identifiers
+   |
+LL | pub mod r#break {
+   |         ^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/keywords-followed-by-double-colon.rs b/src/test/ui/parser/keywords-followed-by-double-colon.rs
new file mode 100644
index 0000000..5c7049f
--- /dev/null
+++ b/src/test/ui/parser/keywords-followed-by-double-colon.rs
@@ -0,0 +1,8 @@
+fn main() {
+    struct::foo();
+    //~^ ERROR expected identifier
+}
+fn bar() {
+    mut::baz();
+    //~^ ERROR expected expression, found keyword `mut`
+}
diff --git a/src/test/ui/parser/keywords-followed-by-double-colon.stderr b/src/test/ui/parser/keywords-followed-by-double-colon.stderr
new file mode 100644
index 0000000..4c4d5e5d
--- /dev/null
+++ b/src/test/ui/parser/keywords-followed-by-double-colon.stderr
@@ -0,0 +1,14 @@
+error: expected identifier, found `::`
+  --> $DIR/keywords-followed-by-double-colon.rs:2:11
+   |
+LL |     struct::foo();
+   |           ^^ expected identifier
+
+error: expected expression, found keyword `mut`
+  --> $DIR/keywords-followed-by-double-colon.rs:6:5
+   |
+LL |     mut::baz();
+   |     ^^^ expected expression
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/parser/lex-bad-binary-literal.rs b/src/test/ui/parser/lex-bad-binary-literal.rs
new file mode 100644
index 0000000..da36537
--- /dev/null
+++ b/src/test/ui/parser/lex-bad-binary-literal.rs
@@ -0,0 +1,13 @@
+// compile-flags: -Z continue-parse-after-error
+
+fn main() {
+    0b121; //~ ERROR invalid digit for a base 2 literal
+    0b10_10301; //~ ERROR invalid digit for a base 2 literal
+    0b30; //~ ERROR invalid digit for a base 2 literal
+    0b41; //~ ERROR invalid digit for a base 2 literal
+    0b5; //~ ERROR invalid digit for a base 2 literal
+    0b6; //~ ERROR invalid digit for a base 2 literal
+    0b7; //~ ERROR invalid digit for a base 2 literal
+    0b8; //~ ERROR invalid digit for a base 2 literal
+    0b9; //~ ERROR invalid digit for a base 2 literal
+}
diff --git a/src/test/ui/parser/lex-bad-binary-literal.stderr b/src/test/ui/parser/lex-bad-binary-literal.stderr
new file mode 100644
index 0000000..15959f6
--- /dev/null
+++ b/src/test/ui/parser/lex-bad-binary-literal.stderr
@@ -0,0 +1,56 @@
+error: invalid digit for a base 2 literal
+  --> $DIR/lex-bad-binary-literal.rs:4:8
+   |
+LL |     0b121;
+   |        ^
+
+error: invalid digit for a base 2 literal
+  --> $DIR/lex-bad-binary-literal.rs:5:12
+   |
+LL |     0b10_10301;
+   |            ^
+
+error: invalid digit for a base 2 literal
+  --> $DIR/lex-bad-binary-literal.rs:6:7
+   |
+LL |     0b30;
+   |       ^
+
+error: invalid digit for a base 2 literal
+  --> $DIR/lex-bad-binary-literal.rs:7:7
+   |
+LL |     0b41;
+   |       ^
+
+error: invalid digit for a base 2 literal
+  --> $DIR/lex-bad-binary-literal.rs:8:7
+   |
+LL |     0b5;
+   |       ^
+
+error: invalid digit for a base 2 literal
+  --> $DIR/lex-bad-binary-literal.rs:9:7
+   |
+LL |     0b6;
+   |       ^
+
+error: invalid digit for a base 2 literal
+  --> $DIR/lex-bad-binary-literal.rs:10:7
+   |
+LL |     0b7;
+   |       ^
+
+error: invalid digit for a base 2 literal
+  --> $DIR/lex-bad-binary-literal.rs:11:7
+   |
+LL |     0b8;
+   |       ^
+
+error: invalid digit for a base 2 literal
+  --> $DIR/lex-bad-binary-literal.rs:12:7
+   |
+LL |     0b9;
+   |       ^
+
+error: aborting due to 9 previous errors
+
diff --git a/src/test/ui/parser/lex-bad-char-literals-1.rs b/src/test/ui/parser/lex-bad-char-literals-1.rs
new file mode 100644
index 0000000..54d75ed
--- /dev/null
+++ b/src/test/ui/parser/lex-bad-char-literals-1.rs
@@ -0,0 +1,18 @@
+// compile-flags: -Z continue-parse-after-error
+static c3: char =
+    '\x1' //~ ERROR: numeric character escape is too short
+;
+
+static s3: &'static str =
+    "\x1" //~ ERROR: numeric character escape is too short
+;
+
+static c: char =
+    '\●' //~ ERROR: unknown character escape
+;
+
+static s: &'static str =
+    "\●" //~ ERROR: unknown character escape
+;
+
+fn main() {}
diff --git a/src/test/ui/parser/lex-bad-char-literals-1.stderr b/src/test/ui/parser/lex-bad-char-literals-1.stderr
new file mode 100644
index 0000000..414ad81
--- /dev/null
+++ b/src/test/ui/parser/lex-bad-char-literals-1.stderr
@@ -0,0 +1,26 @@
+error: numeric character escape is too short
+  --> $DIR/lex-bad-char-literals-1.rs:3:8
+   |
+LL |     '\x1'
+   |        ^
+
+error: numeric character escape is too short
+  --> $DIR/lex-bad-char-literals-1.rs:7:8
+   |
+LL |     "\x1"
+   |        ^
+
+error: unknown character escape: \u{25cf}
+  --> $DIR/lex-bad-char-literals-1.rs:11:7
+   |
+LL |     '\●'
+   |       ^ unknown character escape
+
+error: unknown character escape: \u{25cf}
+  --> $DIR/lex-bad-char-literals-1.rs:15:7
+   |
+LL |     "\●"
+   |       ^ unknown character escape
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/parser/lex-bad-char-literals-2.rs b/src/test/ui/parser/lex-bad-char-literals-2.rs
new file mode 100644
index 0000000..1e180f8
--- /dev/null
+++ b/src/test/ui/parser/lex-bad-char-literals-2.rs
@@ -0,0 +1,4 @@
+// This test needs to the last one appearing in this file as it kills the parser
+static c: char =
+    'nope' //~ ERROR: character literal may only contain one codepoint
+;
diff --git a/src/test/ui/parser/lex-bad-char-literals-2.stderr b/src/test/ui/parser/lex-bad-char-literals-2.stderr
new file mode 100644
index 0000000..4c1c5c2
--- /dev/null
+++ b/src/test/ui/parser/lex-bad-char-literals-2.stderr
@@ -0,0 +1,13 @@
+error: character literal may only contain one codepoint
+  --> $DIR/lex-bad-char-literals-2.rs:3:5
+   |
+LL |     'nope'
+   |     ^^^^^^
+
+error[E0601]: `main` function not found in crate `lex_bad_char_literals_2`
+   |
+   = note: consider adding a `main` function to `$DIR/lex-bad-char-literals-2.rs`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0601`.
diff --git a/src/test/ui/parser/lex-bad-char-literals-3.rs b/src/test/ui/parser/lex-bad-char-literals-3.rs
new file mode 100644
index 0000000..5194ff4
--- /dev/null
+++ b/src/test/ui/parser/lex-bad-char-literals-3.rs
@@ -0,0 +1,7 @@
+static c: char = '●●';
+//~^ ERROR: character literal may only contain one codepoint
+
+fn main() {
+    let ch: &str = '●●';
+    //~^ ERROR: character literal may only contain one codepoint
+}
diff --git a/src/test/ui/parser/lex-bad-char-literals-3.stderr b/src/test/ui/parser/lex-bad-char-literals-3.stderr
new file mode 100644
index 0000000..6462a3c
--- /dev/null
+++ b/src/test/ui/parser/lex-bad-char-literals-3.stderr
@@ -0,0 +1,22 @@
+error: character literal may only contain one codepoint
+  --> $DIR/lex-bad-char-literals-3.rs:1:18
+   |
+LL | static c: char = '●●';
+   |                  ^^^^
+help: if you meant to write a `str` literal, use double quotes
+   |
+LL | static c: char = "●●";
+   |                  ^^^^
+
+error: character literal may only contain one codepoint
+  --> $DIR/lex-bad-char-literals-3.rs:5:20
+   |
+LL |     let ch: &str = '●●';
+   |                    ^^^^
+help: if you meant to write a `str` literal, use double quotes
+   |
+LL |     let ch: &str = "●●";
+   |                    ^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/parser/lex-bad-char-literals-4.rs b/src/test/ui/parser/lex-bad-char-literals-4.rs
new file mode 100644
index 0000000..e13f11f
--- /dev/null
+++ b/src/test/ui/parser/lex-bad-char-literals-4.rs
@@ -0,0 +1,5 @@
+//
+// This test needs to the last one appearing in this file as it kills the parser
+static c: char =
+    '●  //~ ERROR: character literal may only contain one codepoint
+;
diff --git a/src/test/ui/parser/lex-bad-char-literals-4.stderr b/src/test/ui/parser/lex-bad-char-literals-4.stderr
new file mode 100644
index 0000000..7bcca37
--- /dev/null
+++ b/src/test/ui/parser/lex-bad-char-literals-4.stderr
@@ -0,0 +1,8 @@
+error: character literal may only contain one codepoint: '●
+  --> $DIR/lex-bad-char-literals-4.rs:4:5
+   |
+LL |     '●
+   |     ^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/lex-bad-char-literals-5.rs b/src/test/ui/parser/lex-bad-char-literals-5.rs
new file mode 100644
index 0000000..0c4339e
--- /dev/null
+++ b/src/test/ui/parser/lex-bad-char-literals-5.rs
@@ -0,0 +1,7 @@
+static c: char = '\x10\x10';
+//~^ ERROR: character literal may only contain one codepoint
+
+fn main() {
+    let ch: &str = '\x10\x10';
+    //~^ ERROR: character literal may only contain one codepoint
+}
diff --git a/src/test/ui/parser/lex-bad-char-literals-5.stderr b/src/test/ui/parser/lex-bad-char-literals-5.stderr
new file mode 100644
index 0000000..97c6338
--- /dev/null
+++ b/src/test/ui/parser/lex-bad-char-literals-5.stderr
@@ -0,0 +1,22 @@
+error: character literal may only contain one codepoint
+  --> $DIR/lex-bad-char-literals-5.rs:1:18
+   |
+LL | static c: char = '\x10\x10';
+   |                  ^^^^^^^^^^
+help: if you meant to write a `str` literal, use double quotes
+   |
+LL | static c: char = "\x10\x10";
+   |                  ^^^^^^^^^^
+
+error: character literal may only contain one codepoint
+  --> $DIR/lex-bad-char-literals-5.rs:5:20
+   |
+LL |     let ch: &str = '\x10\x10';
+   |                    ^^^^^^^^^^
+help: if you meant to write a `str` literal, use double quotes
+   |
+LL |     let ch: &str = "\x10\x10";
+   |                    ^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/parser/lex-bad-char-literals-6.rs b/src/test/ui/parser/lex-bad-char-literals-6.rs
new file mode 100644
index 0000000..4379b4f
--- /dev/null
+++ b/src/test/ui/parser/lex-bad-char-literals-6.rs
@@ -0,0 +1,17 @@
+fn main() {
+    let x: &str = 'ab';
+    //~^ ERROR: character literal may only contain one codepoint
+    let y: char = 'cd';
+    //~^ ERROR: character literal may only contain one codepoint
+    let z = 'ef';
+    //~^ ERROR: character literal may only contain one codepoint
+
+    if x == y {}
+    //~^ ERROR: can't compare `&str` with `char`
+    if y == z {}  // no error here
+    if x == z {}
+    //~^ ERROR: can't compare `&str` with `char`
+
+    let a: usize = "";
+    //~^ ERROR: mismatched types
+}
diff --git a/src/test/ui/parser/lex-bad-char-literals-6.stderr b/src/test/ui/parser/lex-bad-char-literals-6.stderr
new file mode 100644
index 0000000..df99726
--- /dev/null
+++ b/src/test/ui/parser/lex-bad-char-literals-6.stderr
@@ -0,0 +1,47 @@
+error: character literal may only contain one codepoint
+  --> $DIR/lex-bad-char-literals-6.rs:2:19
+   |
+LL |     let x: &str = 'ab';
+   |                   ^^^^
+
+error: character literal may only contain one codepoint
+  --> $DIR/lex-bad-char-literals-6.rs:4:19
+   |
+LL |     let y: char = 'cd';
+   |                   ^^^^
+
+error: character literal may only contain one codepoint
+  --> $DIR/lex-bad-char-literals-6.rs:6:13
+   |
+LL |     let z = 'ef';
+   |             ^^^^
+
+error[E0277]: can't compare `&str` with `char`
+  --> $DIR/lex-bad-char-literals-6.rs:9:10
+   |
+LL |     if x == y {}
+   |          ^^ no implementation for `&str == char`
+   |
+   = help: the trait `std::cmp::PartialEq<char>` is not implemented for `&str`
+
+error[E0308]: mismatched types
+  --> $DIR/lex-bad-char-literals-6.rs:15:20
+   |
+LL |     let a: usize = "";
+   |                    ^^ expected usize, found reference
+   |
+   = note: expected type `usize`
+              found type `&'static str`
+
+error[E0277]: can't compare `&str` with `char`
+  --> $DIR/lex-bad-char-literals-6.rs:12:10
+   |
+LL |     if x == z {}
+   |          ^^ no implementation for `&str == char`
+   |
+   = help: the trait `std::cmp::PartialEq<char>` is not implemented for `&str`
+
+error: aborting due to 6 previous errors
+
+Some errors occurred: E0277, E0308.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/parser/lex-bad-numeric-literals.rs b/src/test/ui/parser/lex-bad-numeric-literals.rs
new file mode 100644
index 0000000..9496ad3
--- /dev/null
+++ b/src/test/ui/parser/lex-bad-numeric-literals.rs
@@ -0,0 +1,27 @@
+// compile-flags: -Z continue-parse-after-error
+
+fn main() {
+    0o1.0; //~ ERROR: octal float literal is not supported
+    0o2f32; //~ ERROR: octal float literal is not supported
+    0o3.0f32; //~ ERROR: octal float literal is not supported
+    0o4e4; //~ ERROR: octal float literal is not supported
+    0o5.0e5; //~ ERROR: octal float literal is not supported
+    0o6e6f32; //~ ERROR: octal float literal is not supported
+    0o7.0e7f64; //~ ERROR: octal float literal is not supported
+    0x8.0e+9; //~ ERROR: hexadecimal float literal is not supported
+    0x9.0e-9; //~ ERROR: hexadecimal float literal is not supported
+    0o; //~ ERROR: no valid digits
+    1e+; //~ ERROR: expected at least one digit in exponent
+    0x539.0; //~ ERROR: hexadecimal float literal is not supported
+    9900000000000000000000000000999999999999999999999999999999; //~ ERROR: int literal is too large
+    9900000000000000000000000000999999999999999999999999999999; //~ ERROR: int literal is too large
+    0x; //~ ERROR: no valid digits
+    0xu32; //~ ERROR: no valid digits
+    0ou32; //~ ERROR: no valid digits
+    0bu32; //~ ERROR: no valid digits
+    0b; //~ ERROR: no valid digits
+    0o123f64; //~ ERROR: octal float literal is not supported
+    0o123.456; //~ ERROR: octal float literal is not supported
+    0b101f64; //~ ERROR: binary float literal is not supported
+    0b111.101; //~ ERROR: binary float literal is not supported
+}
diff --git a/src/test/ui/parser/lex-bad-numeric-literals.stderr b/src/test/ui/parser/lex-bad-numeric-literals.stderr
new file mode 100644
index 0000000..466d7af
--- /dev/null
+++ b/src/test/ui/parser/lex-bad-numeric-literals.stderr
@@ -0,0 +1,140 @@
+error: octal float literal is not supported
+  --> $DIR/lex-bad-numeric-literals.rs:4:5
+   |
+LL |     0o1.0;
+   |     ^^^^^
+
+error: octal float literal is not supported
+  --> $DIR/lex-bad-numeric-literals.rs:6:5
+   |
+LL |     0o3.0f32;
+   |     ^^^^^
+
+error: octal float literal is not supported
+  --> $DIR/lex-bad-numeric-literals.rs:7:5
+   |
+LL |     0o4e4;
+   |     ^^^^^
+
+error: octal float literal is not supported
+  --> $DIR/lex-bad-numeric-literals.rs:8:5
+   |
+LL |     0o5.0e5;
+   |     ^^^^^^^
+
+error: octal float literal is not supported
+  --> $DIR/lex-bad-numeric-literals.rs:9:5
+   |
+LL |     0o6e6f32;
+   |     ^^^^^
+
+error: octal float literal is not supported
+  --> $DIR/lex-bad-numeric-literals.rs:10:5
+   |
+LL |     0o7.0e7f64;
+   |     ^^^^^^^
+
+error: hexadecimal float literal is not supported
+  --> $DIR/lex-bad-numeric-literals.rs:11:5
+   |
+LL |     0x8.0e+9;
+   |     ^^^^^^^^
+
+error: hexadecimal float literal is not supported
+  --> $DIR/lex-bad-numeric-literals.rs:12:5
+   |
+LL |     0x9.0e-9;
+   |     ^^^^^^^^
+
+error: no valid digits found for number
+  --> $DIR/lex-bad-numeric-literals.rs:13:5
+   |
+LL |     0o;
+   |     ^^
+
+error: expected at least one digit in exponent
+  --> $DIR/lex-bad-numeric-literals.rs:14:8
+   |
+LL |     1e+;
+   |        ^
+
+error: hexadecimal float literal is not supported
+  --> $DIR/lex-bad-numeric-literals.rs:15:5
+   |
+LL |     0x539.0;
+   |     ^^^^^^^
+
+error: no valid digits found for number
+  --> $DIR/lex-bad-numeric-literals.rs:18:5
+   |
+LL |     0x;
+   |     ^^
+
+error: no valid digits found for number
+  --> $DIR/lex-bad-numeric-literals.rs:19:5
+   |
+LL |     0xu32;
+   |     ^^
+
+error: no valid digits found for number
+  --> $DIR/lex-bad-numeric-literals.rs:20:5
+   |
+LL |     0ou32;
+   |     ^^
+
+error: no valid digits found for number
+  --> $DIR/lex-bad-numeric-literals.rs:21:5
+   |
+LL |     0bu32;
+   |     ^^
+
+error: no valid digits found for number
+  --> $DIR/lex-bad-numeric-literals.rs:22:5
+   |
+LL |     0b;
+   |     ^^
+
+error: octal float literal is not supported
+  --> $DIR/lex-bad-numeric-literals.rs:24:5
+   |
+LL |     0o123.456;
+   |     ^^^^^^^^^
+
+error: binary float literal is not supported
+  --> $DIR/lex-bad-numeric-literals.rs:26:5
+   |
+LL |     0b111.101;
+   |     ^^^^^^^^^
+
+error: octal float literal is not supported
+  --> $DIR/lex-bad-numeric-literals.rs:5:5
+   |
+LL |     0o2f32;
+   |     ^^^^^^ not supported
+
+error: int literal is too large
+  --> $DIR/lex-bad-numeric-literals.rs:16:5
+   |
+LL |     9900000000000000000000000000999999999999999999999999999999;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: int literal is too large
+  --> $DIR/lex-bad-numeric-literals.rs:17:5
+   |
+LL |     9900000000000000000000000000999999999999999999999999999999;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: octal float literal is not supported
+  --> $DIR/lex-bad-numeric-literals.rs:23:5
+   |
+LL |     0o123f64;
+   |     ^^^^^^^^ not supported
+
+error: binary float literal is not supported
+  --> $DIR/lex-bad-numeric-literals.rs:25:5
+   |
+LL |     0b101f64;
+   |     ^^^^^^^^ not supported
+
+error: aborting due to 23 previous errors
+
diff --git a/src/test/ui/parser/lex-bad-octal-literal.rs b/src/test/ui/parser/lex-bad-octal-literal.rs
new file mode 100644
index 0000000..f4cc2c5
--- /dev/null
+++ b/src/test/ui/parser/lex-bad-octal-literal.rs
@@ -0,0 +1,6 @@
+// compile-flags: -Z continue-parse-after-error
+
+fn main() {
+    0o18; //~ ERROR invalid digit for a base 8 literal
+    0o1234_9_5670;  //~ ERROR invalid digit for a base 8 literal
+}
diff --git a/src/test/ui/parser/lex-bad-octal-literal.stderr b/src/test/ui/parser/lex-bad-octal-literal.stderr
new file mode 100644
index 0000000..01f4c23
--- /dev/null
+++ b/src/test/ui/parser/lex-bad-octal-literal.stderr
@@ -0,0 +1,14 @@
+error: invalid digit for a base 8 literal
+  --> $DIR/lex-bad-octal-literal.rs:4:8
+   |
+LL |     0o18;
+   |        ^
+
+error: invalid digit for a base 8 literal
+  --> $DIR/lex-bad-octal-literal.rs:5:12
+   |
+LL |     0o1234_9_5670;
+   |            ^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/parser/lex-bad-token.rs b/src/test/ui/parser/lex-bad-token.rs
new file mode 100644
index 0000000..feb670c
--- /dev/null
+++ b/src/test/ui/parser/lex-bad-token.rs
@@ -0,0 +1 @@
+● //~ ERROR: unknown start of token
diff --git a/src/test/ui/parser/lex-bad-token.stderr b/src/test/ui/parser/lex-bad-token.stderr
new file mode 100644
index 0000000..43c4372
--- /dev/null
+++ b/src/test/ui/parser/lex-bad-token.stderr
@@ -0,0 +1,8 @@
+error: unknown start of token: \u{25cf}
+  --> $DIR/lex-bad-token.rs:1:1
+   |
+LL | ●
+   | ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/lex-bare-cr-string-literal-doc-comment.rs b/src/test/ui/parser/lex-bare-cr-string-literal-doc-comment.rs
new file mode 100644
index 0000000..b588b00
--- /dev/null
+++ b/src/test/ui/parser/lex-bare-cr-string-literal-doc-comment.rs
Binary files differ
diff --git a/src/test/ui/parser/lex-bare-cr-string-literal-doc-comment.stderr b/src/test/ui/parser/lex-bare-cr-string-literal-doc-comment.stderr
new file mode 100644
index 0000000..7d94456
--- /dev/null
+++ b/src/test/ui/parser/lex-bare-cr-string-literal-doc-comment.stderr
Binary files differ
diff --git a/src/test/ui/parser/lex-stray-backslash.rs b/src/test/ui/parser/lex-stray-backslash.rs
new file mode 100644
index 0000000..90d3592
--- /dev/null
+++ b/src/test/ui/parser/lex-stray-backslash.rs
@@ -0,0 +1 @@
+\ //~ ERROR: unknown start of token: \
diff --git a/src/test/ui/parser/lex-stray-backslash.stderr b/src/test/ui/parser/lex-stray-backslash.stderr
new file mode 100644
index 0000000..06dc0f2
--- /dev/null
+++ b/src/test/ui/parser/lex-stray-backslash.stderr
@@ -0,0 +1,8 @@
+error: unknown start of token: \
+  --> $DIR/lex-stray-backslash.rs:1:1
+   |
+LL | \
+   | ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/lifetime-in-pattern.rs b/src/test/ui/parser/lifetime-in-pattern.rs
new file mode 100644
index 0000000..afee685
--- /dev/null
+++ b/src/test/ui/parser/lifetime-in-pattern.rs
@@ -0,0 +1,6 @@
+fn test(&'a str) {
+    //~^ ERROR unexpected lifetime `'a` in pattern
+}
+
+fn main() {
+}
diff --git a/src/test/ui/parser/lifetime-in-pattern.stderr b/src/test/ui/parser/lifetime-in-pattern.stderr
new file mode 100644
index 0000000..e525c7b
--- /dev/null
+++ b/src/test/ui/parser/lifetime-in-pattern.stderr
@@ -0,0 +1,8 @@
+error: unexpected lifetime `'a` in pattern
+  --> $DIR/lifetime-in-pattern.rs:1:10
+   |
+LL | fn test(&'a str) {
+   |          ^^ unexpected lifetime
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/lifetime-semicolon.rs b/src/test/ui/parser/lifetime-semicolon.rs
new file mode 100644
index 0000000..1f14721
--- /dev/null
+++ b/src/test/ui/parser/lifetime-semicolon.rs
@@ -0,0 +1,8 @@
+struct Foo<'a, 'b> {
+    a: &'a &'b i32
+}
+
+fn foo<'a, 'b>(x: &mut Foo<'a; 'b>) {}
+//~^ ERROR expected one of `,` or `>`, found `;`
+
+fn main() {}
diff --git a/src/test/ui/parser/lifetime-semicolon.stderr b/src/test/ui/parser/lifetime-semicolon.stderr
new file mode 100644
index 0000000..71ed820
--- /dev/null
+++ b/src/test/ui/parser/lifetime-semicolon.stderr
@@ -0,0 +1,8 @@
+error: expected one of `,` or `>`, found `;`
+  --> $DIR/lifetime-semicolon.rs:5:30
+   |
+LL | fn foo<'a, 'b>(x: &mut Foo<'a; 'b>) {}
+   |                              ^ expected one of `,` or `>` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/macro-bad-delimiter-ident.rs b/src/test/ui/parser/macro-bad-delimiter-ident.rs
new file mode 100644
index 0000000..987c955
--- /dev/null
+++ b/src/test/ui/parser/macro-bad-delimiter-ident.rs
@@ -0,0 +1,3 @@
+fn main() {
+    foo! bar < //~ ERROR expected `(` or `{`, found `<`
+}
diff --git a/src/test/ui/parser/macro-bad-delimiter-ident.stderr b/src/test/ui/parser/macro-bad-delimiter-ident.stderr
new file mode 100644
index 0000000..6a17d39
--- /dev/null
+++ b/src/test/ui/parser/macro-bad-delimiter-ident.stderr
@@ -0,0 +1,8 @@
+error: expected `(` or `{`, found `<`
+  --> $DIR/macro-bad-delimiter-ident.rs:2:14
+   |
+LL |     foo! bar <
+   |              ^ expected `(` or `{`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/macro-keyword.rs b/src/test/ui/parser/macro-keyword.rs
new file mode 100644
index 0000000..58489fb
--- /dev/null
+++ b/src/test/ui/parser/macro-keyword.rs
@@ -0,0 +1,5 @@
+fn macro() {  //~ ERROR expected identifier, found reserved keyword `macro`
+}
+
+pub fn main() {
+}
diff --git a/src/test/ui/parser/macro-keyword.stderr b/src/test/ui/parser/macro-keyword.stderr
new file mode 100644
index 0000000..f74c8aa
--- /dev/null
+++ b/src/test/ui/parser/macro-keyword.stderr
@@ -0,0 +1,12 @@
+error: expected identifier, found reserved keyword `macro`
+  --> $DIR/macro-keyword.rs:1:4
+   |
+LL | fn macro() {
+   |    ^^^^^ expected identifier, found reserved keyword
+help: you can escape reserved keywords to use them as identifiers
+   |
+LL | fn r#macro() {
+   |    ^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/macro-mismatched-delim-brace-paren.rs b/src/test/ui/parser/macro-mismatched-delim-brace-paren.rs
new file mode 100644
index 0000000..3f3e997
--- /dev/null
+++ b/src/test/ui/parser/macro-mismatched-delim-brace-paren.rs
@@ -0,0 +1,7 @@
+macro_rules! foo { ($($tt:tt)*) => () }
+
+fn main() {
+    foo! {
+        bar, "baz", 1, 2.0
+    ) //~ ERROR incorrect close delimiter
+}
diff --git a/src/test/ui/parser/macro-mismatched-delim-brace-paren.stderr b/src/test/ui/parser/macro-mismatched-delim-brace-paren.stderr
new file mode 100644
index 0000000..f411ee8
--- /dev/null
+++ b/src/test/ui/parser/macro-mismatched-delim-brace-paren.stderr
@@ -0,0 +1,11 @@
+error: incorrect close delimiter: `)`
+  --> $DIR/macro-mismatched-delim-brace-paren.rs:6:5
+   |
+LL |     foo! {
+   |          - un-closed delimiter
+LL |         bar, "baz", 1, 2.0
+LL |     )
+   |     ^ incorrect close delimiter
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/macro-mismatched-delim-paren-brace.rs b/src/test/ui/parser/macro-mismatched-delim-paren-brace.rs
new file mode 100644
index 0000000..1185f88
--- /dev/null
+++ b/src/test/ui/parser/macro-mismatched-delim-paren-brace.rs
@@ -0,0 +1,5 @@
+fn main() {
+    foo! (
+        bar, "baz", 1, 2.0
+    } //~ ERROR incorrect close delimiter
+} //~ ERROR unexpected close delimiter: `}`
diff --git a/src/test/ui/parser/macro-mismatched-delim-paren-brace.stderr b/src/test/ui/parser/macro-mismatched-delim-paren-brace.stderr
new file mode 100644
index 0000000..b684339
--- /dev/null
+++ b/src/test/ui/parser/macro-mismatched-delim-paren-brace.stderr
@@ -0,0 +1,17 @@
+error: unexpected close delimiter: `}`
+  --> $DIR/macro-mismatched-delim-paren-brace.rs:5:1
+   |
+LL | }
+   | ^ unexpected close delimiter
+
+error: incorrect close delimiter: `}`
+  --> $DIR/macro-mismatched-delim-paren-brace.rs:4:5
+   |
+LL |     foo! (
+   |          - un-closed delimiter
+LL |         bar, "baz", 1, 2.0
+LL |     }
+   |     ^ incorrect close delimiter
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/parser/macro/issue-33569.rs b/src/test/ui/parser/macro/issue-33569.rs
new file mode 100644
index 0000000..83f8a56
--- /dev/null
+++ b/src/test/ui/parser/macro/issue-33569.rs
@@ -0,0 +1,8 @@
+macro_rules! foo {
+    { $+ } => { //~ ERROR expected identifier, found `+`
+                //~^ ERROR missing fragment specifier
+        $(x)(y) //~ ERROR expected `*` or `+`
+    }
+}
+
+foo!();
diff --git a/src/test/ui/parser/macro/issue-33569.stderr b/src/test/ui/parser/macro/issue-33569.stderr
new file mode 100644
index 0000000..8ba72fc
--- /dev/null
+++ b/src/test/ui/parser/macro/issue-33569.stderr
@@ -0,0 +1,20 @@
+error: expected identifier, found `+`
+  --> $DIR/issue-33569.rs:2:8
+   |
+LL |     { $+ } => {
+   |        ^
+
+error: expected `*` or `+`
+  --> $DIR/issue-33569.rs:4:13
+   |
+LL |         $(x)(y)
+   |             ^^^
+
+error: missing fragment specifier
+  --> $DIR/issue-33569.rs:2:8
+   |
+LL |     { $+ } => {
+   |        ^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/parser/macro/issue-37113.rs b/src/test/ui/parser/macro/issue-37113.rs
new file mode 100644
index 0000000..0044aa5
--- /dev/null
+++ b/src/test/ui/parser/macro/issue-37113.rs
@@ -0,0 +1,11 @@
+macro_rules! test_macro {
+    ( $( $t:ty ),* $(),*) => {
+        enum SomeEnum {
+            $( $t, )* //~ ERROR expected identifier, found `String`
+        };
+    };
+}
+
+fn main() {
+    test_macro!(String,);
+}
diff --git a/src/test/ui/parser/macro/issue-37113.stderr b/src/test/ui/parser/macro/issue-37113.stderr
new file mode 100644
index 0000000..7aadc0a
--- /dev/null
+++ b/src/test/ui/parser/macro/issue-37113.stderr
@@ -0,0 +1,11 @@
+error: expected identifier, found `String`
+  --> $DIR/issue-37113.rs:4:16
+   |
+LL |             $( $t, )*
+   |                ^^ expected identifier
+...
+LL |     test_macro!(String,);
+   |     --------------------- in this macro invocation
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/macro/issue-37234.rs b/src/test/ui/parser/macro/issue-37234.rs
new file mode 100644
index 0000000..4debc74
--- /dev/null
+++ b/src/test/ui/parser/macro/issue-37234.rs
@@ -0,0 +1,9 @@
+macro_rules! failed {
+    () => {{
+        let x = 5 ""; //~ ERROR found `""`
+    }}
+}
+
+fn main() {
+    failed!();
+}
diff --git a/src/test/ui/parser/macro/issue-37234.stderr b/src/test/ui/parser/macro/issue-37234.stderr
new file mode 100644
index 0000000..004de9d
--- /dev/null
+++ b/src/test/ui/parser/macro/issue-37234.stderr
@@ -0,0 +1,11 @@
+error: expected one of `.`, `;`, `?`, or an operator, found `""`
+  --> $DIR/issue-37234.rs:3:19
+   |
+LL |         let x = 5 "";
+   |                   ^^ expected one of `.`, `;`, `?`, or an operator here
+...
+LL |     failed!();
+   |     ---------- in this macro invocation
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/macro/macro-doc-comments-1.rs b/src/test/ui/parser/macro/macro-doc-comments-1.rs
new file mode 100644
index 0000000..8d8103b
--- /dev/null
+++ b/src/test/ui/parser/macro/macro-doc-comments-1.rs
@@ -0,0 +1,9 @@
+macro_rules! outer {
+    (#[$outer:meta]) => ()
+}
+
+outer! {
+    //! Inner
+} //~^ ERROR no rules expected the token `!`
+
+fn main() { }
diff --git a/src/test/ui/parser/macro/macro-doc-comments-1.stderr b/src/test/ui/parser/macro/macro-doc-comments-1.stderr
new file mode 100644
index 0000000..96bdb98
--- /dev/null
+++ b/src/test/ui/parser/macro/macro-doc-comments-1.stderr
@@ -0,0 +1,11 @@
+error: no rules expected the token `!`
+  --> $DIR/macro-doc-comments-1.rs:6:5
+   |
+LL | macro_rules! outer {
+   | ------------------ when calling this macro
+...
+LL |     //! Inner
+   |     ^^^^^^^^^ no rules expected this token in macro call
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/macro/macro-doc-comments-2.rs b/src/test/ui/parser/macro/macro-doc-comments-2.rs
new file mode 100644
index 0000000..8f33720
--- /dev/null
+++ b/src/test/ui/parser/macro/macro-doc-comments-2.rs
@@ -0,0 +1,9 @@
+macro_rules! inner {
+    (#![$inner:meta]) => ()
+}
+
+inner! {
+    /// Outer
+} //~^ ERROR no rules expected the token `[`
+
+fn main() { }
diff --git a/src/test/ui/parser/macro/macro-doc-comments-2.stderr b/src/test/ui/parser/macro/macro-doc-comments-2.stderr
new file mode 100644
index 0000000..6abe951
--- /dev/null
+++ b/src/test/ui/parser/macro/macro-doc-comments-2.stderr
@@ -0,0 +1,11 @@
+error: no rules expected the token `[`
+  --> $DIR/macro-doc-comments-2.rs:6:5
+   |
+LL | macro_rules! inner {
+   | ------------------ when calling this macro
+...
+LL |     /// Outer
+   |     ^ no rules expected this token in macro call
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/macro/macro-incomplete-parse.rs b/src/test/ui/parser/macro/macro-incomplete-parse.rs
new file mode 100644
index 0000000..9294beb
--- /dev/null
+++ b/src/test/ui/parser/macro/macro-incomplete-parse.rs
@@ -0,0 +1,29 @@
+// compile-flags: -Z continue-parse-after-error
+
+macro_rules! ignored_item {
+    () => {
+        fn foo() {}
+        fn bar() {}
+        , //~ ERROR macro expansion ignores token `,`
+    }
+}
+
+macro_rules! ignored_expr {
+    () => ( 1,  //~ ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `,`
+
+            2 )
+}
+
+macro_rules! ignored_pat {
+    () => ( 1, 2 ) //~ ERROR macro expansion ignores token `,`
+}
+
+ignored_item!();
+
+fn main() {
+    ignored_expr!();
+    match 1 {
+        ignored_pat!() => (),
+        _ => (),
+    }
+}
diff --git a/src/test/ui/parser/macro/macro-incomplete-parse.stderr b/src/test/ui/parser/macro/macro-incomplete-parse.stderr
new file mode 100644
index 0000000..b37bd58
--- /dev/null
+++ b/src/test/ui/parser/macro/macro-incomplete-parse.stderr
@@ -0,0 +1,33 @@
+error: macro expansion ignores token `,` and any following
+  --> $DIR/macro-incomplete-parse.rs:7:9
+   |
+LL |         ,
+   |         ^
+...
+LL | ignored_item!();
+   | ---------------- caused by the macro expansion here
+   |
+   = note: the usage of `ignored_item!` is likely invalid in item context
+
+error: expected one of `.`, `;`, `?`, `}`, or an operator, found `,`
+  --> $DIR/macro-incomplete-parse.rs:12:14
+   |
+LL |     () => ( 1,
+   |              ^ expected one of `.`, `;`, `?`, `}`, or an operator here
+...
+LL |     ignored_expr!();
+   |     ---------------- in this macro invocation
+
+error: macro expansion ignores token `,` and any following
+  --> $DIR/macro-incomplete-parse.rs:18:14
+   |
+LL |     () => ( 1, 2 )
+   |              ^
+...
+LL |         ignored_pat!() => (),
+   |         -------------- caused by the macro expansion here
+   |
+   = note: the usage of `ignored_pat!` is likely invalid in pattern context
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/parser/macro/macro-repeat.rs b/src/test/ui/parser/macro/macro-repeat.rs
new file mode 100644
index 0000000..580a1da
--- /dev/null
+++ b/src/test/ui/parser/macro/macro-repeat.rs
@@ -0,0 +1,9 @@
+macro_rules! mac {
+    ( $($v:tt)* ) => (
+        $v  //~ ERROR still repeating at this depth
+    )
+}
+
+fn main() {
+    mac!(0);
+}
diff --git a/src/test/ui/parser/macro/macro-repeat.stderr b/src/test/ui/parser/macro/macro-repeat.stderr
new file mode 100644
index 0000000..c86684d
--- /dev/null
+++ b/src/test/ui/parser/macro/macro-repeat.stderr
@@ -0,0 +1,8 @@
+error: variable 'v' is still repeating at this depth
+  --> $DIR/macro-repeat.rs:3:9
+   |
+LL |         $v
+   |         ^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/macro/pub-item-macro.rs b/src/test/ui/parser/macro/pub-item-macro.rs
new file mode 100644
index 0000000..bae9022
--- /dev/null
+++ b/src/test/ui/parser/macro/pub-item-macro.rs
@@ -0,0 +1,18 @@
+// Issue #14660
+
+macro_rules! priv_x { () => {
+    static x: u32 = 0;
+}}
+
+macro_rules! pub_x { () => {
+    pub priv_x!(); //~ ERROR can't qualify macro invocation with `pub`
+    //~^ HELP try adjusting the macro to put `pub` inside the invocation
+}}
+
+mod foo {
+    pub_x!();
+}
+
+fn main() {
+    let y: u32 = foo::x; //~ ERROR static `x` is private
+}
diff --git a/src/test/ui/parser/macro/pub-item-macro.stderr b/src/test/ui/parser/macro/pub-item-macro.stderr
new file mode 100644
index 0000000..fa25161
--- /dev/null
+++ b/src/test/ui/parser/macro/pub-item-macro.stderr
@@ -0,0 +1,20 @@
+error: can't qualify macro invocation with `pub`
+  --> $DIR/pub-item-macro.rs:8:5
+   |
+LL |     pub priv_x!();
+   |     ^^^
+...
+LL |     pub_x!();
+   |     --------- in this macro invocation
+   |
+   = help: try adjusting the macro to put `pub` inside the invocation
+
+error[E0603]: static `x` is private
+  --> $DIR/pub-item-macro.rs:17:23
+   |
+LL |     let y: u32 = foo::x;
+   |                       ^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0603`.
diff --git a/src/test/ui/parser/macro/trait-non-item-macros.rs b/src/test/ui/parser/macro/trait-non-item-macros.rs
new file mode 100644
index 0000000..958c90b
--- /dev/null
+++ b/src/test/ui/parser/macro/trait-non-item-macros.rs
@@ -0,0 +1,10 @@
+macro_rules! bah {
+    ($a:expr) => ($a)
+    //~^ ERROR expected one of `async`, `const`, `extern`, `fn`, `type`, or `unsafe`, found `2`
+}
+
+trait bar {
+    bah!(2);
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/macro/trait-non-item-macros.stderr b/src/test/ui/parser/macro/trait-non-item-macros.stderr
new file mode 100644
index 0000000..76670e0
--- /dev/null
+++ b/src/test/ui/parser/macro/trait-non-item-macros.stderr
@@ -0,0 +1,11 @@
+error: expected one of `async`, `const`, `extern`, `fn`, `type`, or `unsafe`, found `2`
+  --> $DIR/trait-non-item-macros.rs:2:19
+   |
+LL |     ($a:expr) => ($a)
+   |                   ^^ unexpected token
+...
+LL |     bah!(2);
+   |     -------- in this macro invocation
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/macro/trait-object-macro-matcher.rs b/src/test/ui/parser/macro/trait-object-macro-matcher.rs
new file mode 100644
index 0000000..80d867d
--- /dev/null
+++ b/src/test/ui/parser/macro/trait-object-macro-matcher.rs
@@ -0,0 +1,10 @@
+// A single lifetime is not parsed as a type.
+// `ty` matcher in particular doesn't accept a single lifetime
+
+macro_rules! m {
+    ($t: ty) => ( let _: $t; )
+}
+
+fn main() {
+    m!('static); //~ ERROR expected type, found `'static`
+}
diff --git a/src/test/ui/parser/macro/trait-object-macro-matcher.stderr b/src/test/ui/parser/macro/trait-object-macro-matcher.stderr
new file mode 100644
index 0000000..19c5c82
--- /dev/null
+++ b/src/test/ui/parser/macro/trait-object-macro-matcher.stderr
@@ -0,0 +1,8 @@
+error: expected type, found `'static`
+  --> $DIR/trait-object-macro-matcher.rs:9:8
+   |
+LL |     m!('static);
+   |        ^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/macros-no-semicolon-items.rs b/src/test/ui/parser/macros-no-semicolon-items.rs
new file mode 100644
index 0000000..3afc275
--- /dev/null
+++ b/src/test/ui/parser/macros-no-semicolon-items.rs
@@ -0,0 +1,15 @@
+macro_rules! foo()  //~ ERROR semicolon
+                    //~| ERROR unexpected end of macro
+
+macro_rules! bar {
+    ($($tokens:tt)*) => {}
+}
+
+bar!( //~ ERROR semicolon
+    blah
+    blah
+    blah
+)
+
+fn main() {
+}
diff --git a/src/test/ui/parser/macros-no-semicolon-items.stderr b/src/test/ui/parser/macros-no-semicolon-items.stderr
new file mode 100644
index 0000000..5276aa6
--- /dev/null
+++ b/src/test/ui/parser/macros-no-semicolon-items.stderr
@@ -0,0 +1,45 @@
+error: macros that expand to items must be delimited with braces or followed by a semicolon
+  --> $DIR/macros-no-semicolon-items.rs:1:17
+   |
+LL | macro_rules! foo()
+   |                 ^^
+help: change the delimiters to curly braces
+   |
+LL | macro_rules! foo {}
+   |                  ^^
+help: add a semicolon
+   |
+LL | macro_rules! foo();
+   |                   ^
+
+error: macros that expand to items must be delimited with braces or followed by a semicolon
+  --> $DIR/macros-no-semicolon-items.rs:8:5
+   |
+LL |   bar!(
+   |  _____^
+LL | |     blah
+LL | |     blah
+LL | |     blah
+LL | | )
+   | |_^
+help: change the delimiters to curly braces
+   |
+LL | bar! {
+LL |     blah
+LL |     blah
+LL |     blah
+LL | }
+   |
+help: add a semicolon
+   |
+LL | );
+   |  ^
+
+error: unexpected end of macro invocation
+  --> $DIR/macros-no-semicolon-items.rs:1:1
+   |
+LL | macro_rules! foo()
+   | ^^^^^^^^^^^^^^^^^^ missing tokens in macro arguments
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/parser/macros-no-semicolon.rs b/src/test/ui/parser/macros-no-semicolon.rs
new file mode 100644
index 0000000..fd79fa8
--- /dev/null
+++ b/src/test/ui/parser/macros-no-semicolon.rs
@@ -0,0 +1,5 @@
+fn main() {
+    assert_eq!(1, 2)
+    assert_eq!(3, 4) //~ ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `assert_eq`
+    println!("hello");
+}
diff --git a/src/test/ui/parser/macros-no-semicolon.stderr b/src/test/ui/parser/macros-no-semicolon.stderr
new file mode 100644
index 0000000..09925ea
--- /dev/null
+++ b/src/test/ui/parser/macros-no-semicolon.stderr
@@ -0,0 +1,10 @@
+error: expected one of `.`, `;`, `?`, `}`, or an operator, found `assert_eq`
+  --> $DIR/macros-no-semicolon.rs:3:5
+   |
+LL |     assert_eq!(1, 2)
+   |                     - expected one of `.`, `;`, `?`, `}`, or an operator here
+LL |     assert_eq!(3, 4)
+   |     ^^^^^^^^^ unexpected token
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/match-arrows-block-then-binop.rs b/src/test/ui/parser/match-arrows-block-then-binop.rs
new file mode 100644
index 0000000..1a40d67
--- /dev/null
+++ b/src/test/ui/parser/match-arrows-block-then-binop.rs
@@ -0,0 +1,7 @@
+fn main() {
+
+    match 0 {
+      0 => {
+      } + 5 //~ ERROR expected pattern, found `+`
+    }
+}
diff --git a/src/test/ui/parser/match-arrows-block-then-binop.stderr b/src/test/ui/parser/match-arrows-block-then-binop.stderr
new file mode 100644
index 0000000..a844cac
--- /dev/null
+++ b/src/test/ui/parser/match-arrows-block-then-binop.stderr
@@ -0,0 +1,8 @@
+error: expected pattern, found `+`
+  --> $DIR/match-arrows-block-then-binop.rs:5:9
+   |
+LL |       } + 5
+   |         ^ expected pattern
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/match-refactor-to-expr.rs b/src/test/ui/parser/match-refactor-to-expr.rs
new file mode 100644
index 0000000..09ebb2e
--- /dev/null
+++ b/src/test/ui/parser/match-refactor-to-expr.rs
@@ -0,0 +1,10 @@
+fn main() {
+    let foo =
+        match //~ NOTE while parsing this match expression
+        Some(4).unwrap_or_else(5)
+        //~^ NOTE expected one of `.`, `?`, `{`, or an operator here
+        ; //~ NOTE unexpected token
+        //~^ ERROR expected one of `.`, `?`, `{`, or an operator, found `;`
+
+    println!("{}", foo)
+}
diff --git a/src/test/ui/parser/match-refactor-to-expr.stderr b/src/test/ui/parser/match-refactor-to-expr.stderr
new file mode 100644
index 0000000..bf20bc9
--- /dev/null
+++ b/src/test/ui/parser/match-refactor-to-expr.stderr
@@ -0,0 +1,16 @@
+error: expected one of `.`, `?`, `{`, or an operator, found `;`
+  --> $DIR/match-refactor-to-expr.rs:6:9
+   |
+LL |         match
+   |         -----
+   |         |
+   |         while parsing this match expression
+   |         help: try removing this `match`
+LL |         Some(4).unwrap_or_else(5)
+   |                                  - expected one of `.`, `?`, `{`, or an operator here
+LL |
+LL |         ;
+   |         ^ unexpected token
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/match-vec-invalid.rs b/src/test/ui/parser/match-vec-invalid.rs
new file mode 100644
index 0000000..e5e85ba
--- /dev/null
+++ b/src/test/ui/parser/match-vec-invalid.rs
@@ -0,0 +1,7 @@
+fn main() {
+    let a = Vec::new();
+    match a {
+        [1, tail.., tail..] => {}, //~ ERROR: expected one of `,` or `@`, found `..`
+        _ => ()
+    }
+}
diff --git a/src/test/ui/parser/match-vec-invalid.stderr b/src/test/ui/parser/match-vec-invalid.stderr
new file mode 100644
index 0000000..fee8d24
--- /dev/null
+++ b/src/test/ui/parser/match-vec-invalid.stderr
@@ -0,0 +1,8 @@
+error: expected one of `,` or `@`, found `..`
+  --> $DIR/match-vec-invalid.rs:4:25
+   |
+LL |         [1, tail.., tail..] => {},
+   |                         ^^ expected one of `,` or `@` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/mod_file_not_exist.rs b/src/test/ui/parser/mod_file_not_exist.rs
new file mode 100644
index 0000000..e662c70
--- /dev/null
+++ b/src/test/ui/parser/mod_file_not_exist.rs
@@ -0,0 +1,8 @@
+// ignore-windows
+
+mod not_a_real_file; //~ ERROR file not found for module `not_a_real_file`
+//~^ HELP name the file either not_a_real_file.rs or not_a_real_file/mod.rs inside the directory
+
+fn main() {
+    assert_eq!(mod_file_aux::bar(), 10);
+}
diff --git a/src/test/ui/parser/mod_file_not_exist.stderr b/src/test/ui/parser/mod_file_not_exist.stderr
new file mode 100644
index 0000000..dadf4b2
--- /dev/null
+++ b/src/test/ui/parser/mod_file_not_exist.stderr
@@ -0,0 +1,11 @@
+error[E0583]: file not found for module `not_a_real_file`
+  --> $DIR/mod_file_not_exist.rs:3:5
+   |
+LL | mod not_a_real_file;
+   |     ^^^^^^^^^^^^^^^
+   |
+   = help: name the file either not_a_real_file.rs or not_a_real_file/mod.rs inside the directory "$DIR"
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0583`.
diff --git a/src/test/ui/parser/mod_file_not_exist_windows.rs b/src/test/ui/parser/mod_file_not_exist_windows.rs
new file mode 100644
index 0000000..0cd9e9c
--- /dev/null
+++ b/src/test/ui/parser/mod_file_not_exist_windows.rs
@@ -0,0 +1,8 @@
+// only-windows
+
+mod not_a_real_file; //~ ERROR file not found for module `not_a_real_file`
+//~^ HELP name the file either not_a_real_file.rs or not_a_real_file\mod.rs inside the directory
+
+fn main() {
+    assert_eq!(mod_file_aux::bar(), 10);
+}
diff --git a/src/test/ui/parser/mod_file_not_exist_windows.stderr b/src/test/ui/parser/mod_file_not_exist_windows.stderr
new file mode 100644
index 0000000..60ae00a
--- /dev/null
+++ b/src/test/ui/parser/mod_file_not_exist_windows.stderr
@@ -0,0 +1,11 @@
+error[E0583]: file not found for module `not_a_real_file`
+  --> $DIR/mod_file_not_exist_windows.rs:3:5
+   |
+LL | mod not_a_real_file;
+   |     ^^^^^^^^^^^^^^^
+   |
+   = help: name the file either not_a_real_file.rs or not_a_real_file/mod.rs inside the directory "$DIR"
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0583`.
diff --git a/src/test/ui/parser/mod_file_with_path_attr.rs b/src/test/ui/parser/mod_file_with_path_attr.rs
new file mode 100644
index 0000000..9450d89
--- /dev/null
+++ b/src/test/ui/parser/mod_file_with_path_attr.rs
@@ -0,0 +1,8 @@
+// normalize-stderr-test: "not_a_real_file.rs:.*\(" -> "not_a_real_file.rs: $$FILE_NOT_FOUND_MSG ("
+
+#[path = "not_a_real_file.rs"]
+mod m; //~ ERROR not_a_real_file.rs
+
+fn main() {
+    assert_eq!(m::foo(), 10);
+}
diff --git a/src/test/ui/parser/mod_file_with_path_attr.stderr b/src/test/ui/parser/mod_file_with_path_attr.stderr
new file mode 100644
index 0000000..004b5d7
--- /dev/null
+++ b/src/test/ui/parser/mod_file_with_path_attr.stderr
@@ -0,0 +1,8 @@
+error: couldn't read $DIR/not_a_real_file.rs: $FILE_NOT_FOUND_MSG (os error 2)
+  --> $DIR/mod_file_with_path_attr.rs:4:5
+   |
+LL | mod m;
+   |     ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/multiline-comment-line-tracking.rs b/src/test/ui/parser/multiline-comment-line-tracking.rs
new file mode 100644
index 0000000..d4735e8
--- /dev/null
+++ b/src/test/ui/parser/multiline-comment-line-tracking.rs
@@ -0,0 +1,9 @@
+// Parse error on line X, but is reported on line Y instead.
+
+/* 1
+ * 2
+ * 3
+ */
+fn main() {
+  %; //~ ERROR expected expression, found `%`
+}
diff --git a/src/test/ui/parser/multiline-comment-line-tracking.stderr b/src/test/ui/parser/multiline-comment-line-tracking.stderr
new file mode 100644
index 0000000..cac0c80
--- /dev/null
+++ b/src/test/ui/parser/multiline-comment-line-tracking.stderr
@@ -0,0 +1,8 @@
+error: expected expression, found `%`
+  --> $DIR/multiline-comment-line-tracking.rs:8:3
+   |
+LL |   %;
+   |   ^ expected expression
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/multitrait.rs b/src/test/ui/parser/multitrait.rs
new file mode 100644
index 0000000..f9b4b37
--- /dev/null
+++ b/src/test/ui/parser/multitrait.rs
@@ -0,0 +1,9 @@
+struct S {
+ y: isize
+}
+
+impl Cmp, ToString for S {
+//~^ ERROR: expected one of `!`, `(`, `+`, `::`, `<`, `for`, `where`, or `{`, found `,`
+  fn eq(&&other: S) { false }
+  fn to_string(&self) -> String { "hi".to_string() }
+}
diff --git a/src/test/ui/parser/multitrait.stderr b/src/test/ui/parser/multitrait.stderr
new file mode 100644
index 0000000..61dbc82
--- /dev/null
+++ b/src/test/ui/parser/multitrait.stderr
@@ -0,0 +1,8 @@
+error: expected one of `!`, `(`, `+`, `::`, `<`, `for`, `where`, or `{`, found `,`
+  --> $DIR/multitrait.rs:5:9
+   |
+LL | impl Cmp, ToString for S {
+   |         ^ expected one of 8 possible tokens here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/mut-patterns.rs b/src/test/ui/parser/mut-patterns.rs
new file mode 100644
index 0000000..a5eb482
--- /dev/null
+++ b/src/test/ui/parser/mut-patterns.rs
@@ -0,0 +1,6 @@
+// Can't put mut in non-ident pattern
+
+pub fn main() {
+    struct Foo { x: isize }
+    let mut Foo { x: x } = Foo { x: 3 }; //~ ERROR: expected one of `:`, `;`, `=`, or `@`, found `{`
+}
diff --git a/src/test/ui/parser/mut-patterns.stderr b/src/test/ui/parser/mut-patterns.stderr
new file mode 100644
index 0000000..2869564
--- /dev/null
+++ b/src/test/ui/parser/mut-patterns.stderr
@@ -0,0 +1,8 @@
+error: expected one of `:`, `;`, `=`, or `@`, found `{`
+  --> $DIR/mut-patterns.rs:5:17
+   |
+LL |     let mut Foo { x: x } = Foo { x: 3 };
+   |                 ^ expected one of `:`, `;`, `=`, or `@` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/new-unicode-escapes-1.rs b/src/test/ui/parser/new-unicode-escapes-1.rs
new file mode 100644
index 0000000..0e14212
--- /dev/null
+++ b/src/test/ui/parser/new-unicode-escapes-1.rs
@@ -0,0 +1,3 @@
+pub fn main() {
+    let s = "\u{2603"; //~ ERROR unterminated unicode escape (needed a `}`)
+}
diff --git a/src/test/ui/parser/new-unicode-escapes-1.stderr b/src/test/ui/parser/new-unicode-escapes-1.stderr
new file mode 100644
index 0000000..a8da509
--- /dev/null
+++ b/src/test/ui/parser/new-unicode-escapes-1.stderr
@@ -0,0 +1,8 @@
+error: unterminated unicode escape (needed a `}`)
+  --> $DIR/new-unicode-escapes-1.rs:2:21
+   |
+LL |     let s = "\u{2603";
+   |                     ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/new-unicode-escapes-2.rs b/src/test/ui/parser/new-unicode-escapes-2.rs
new file mode 100644
index 0000000..b30b3db
--- /dev/null
+++ b/src/test/ui/parser/new-unicode-escapes-2.rs
@@ -0,0 +1,3 @@
+pub fn main() {
+    let s = "\u{260311111111}"; //~ ERROR overlong unicode escape (must have at most 6 hex digits)
+}
diff --git a/src/test/ui/parser/new-unicode-escapes-2.stderr b/src/test/ui/parser/new-unicode-escapes-2.stderr
new file mode 100644
index 0000000..ede49cd
--- /dev/null
+++ b/src/test/ui/parser/new-unicode-escapes-2.stderr
@@ -0,0 +1,8 @@
+error: overlong unicode escape (must have at most 6 hex digits)
+  --> $DIR/new-unicode-escapes-2.rs:2:17
+   |
+LL |     let s = "\u{260311111111}";
+   |                 ^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/new-unicode-escapes-3.rs b/src/test/ui/parser/new-unicode-escapes-3.rs
new file mode 100644
index 0000000..295ab08
--- /dev/null
+++ b/src/test/ui/parser/new-unicode-escapes-3.rs
@@ -0,0 +1,4 @@
+pub fn main() {
+    let s1 = "\u{d805}"; //~ ERROR invalid unicode character escape
+    let s2 = "\u{ffffff}"; //~ ERROR invalid unicode character escape
+}
diff --git a/src/test/ui/parser/new-unicode-escapes-3.stderr b/src/test/ui/parser/new-unicode-escapes-3.stderr
new file mode 100644
index 0000000..59cfb98
--- /dev/null
+++ b/src/test/ui/parser/new-unicode-escapes-3.stderr
@@ -0,0 +1,18 @@
+error: invalid unicode character escape
+  --> $DIR/new-unicode-escapes-3.rs:2:14
+   |
+LL |     let s1 = "\u{d805}";
+   |              ^^^^^^^^^^
+   |
+   = help: unicode escape must not be a surrogate
+
+error: invalid unicode character escape
+  --> $DIR/new-unicode-escapes-3.rs:3:14
+   |
+LL |     let s2 = "\u{ffffff}";
+   |              ^^^^^^^^^^^^
+   |
+   = help: unicode escape must be at most 10FFFF
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/parser/new-unicode-escapes-4.rs b/src/test/ui/parser/new-unicode-escapes-4.rs
new file mode 100644
index 0000000..b871000
--- /dev/null
+++ b/src/test/ui/parser/new-unicode-escapes-4.rs
@@ -0,0 +1,6 @@
+// compile-flags: -Z continue-parse-after-error
+
+pub fn main() {
+    let s = "\u{lol}";
+     //~^ ERROR invalid character in unicode escape: l
+}
diff --git a/src/test/ui/parser/new-unicode-escapes-4.stderr b/src/test/ui/parser/new-unicode-escapes-4.stderr
new file mode 100644
index 0000000..ca96b00
--- /dev/null
+++ b/src/test/ui/parser/new-unicode-escapes-4.stderr
@@ -0,0 +1,8 @@
+error: invalid character in unicode escape: l
+  --> $DIR/new-unicode-escapes-4.rs:4:17
+   |
+LL |     let s = "\u{lol}";
+   |                 ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/no-binary-float-literal.rs b/src/test/ui/parser/no-binary-float-literal.rs
new file mode 100644
index 0000000..a42d2cb
--- /dev/null
+++ b/src/test/ui/parser/no-binary-float-literal.rs
@@ -0,0 +1,8 @@
+fn main() {
+    0b101010f64;
+    //~^ ERROR binary float literal is not supported
+    0b101.010;
+    //~^ ERROR binary float literal is not supported
+    0b101p4f64;
+    //~^ ERROR invalid suffix `p4f64` for numeric literal
+}
diff --git a/src/test/ui/parser/no-binary-float-literal.stderr b/src/test/ui/parser/no-binary-float-literal.stderr
new file mode 100644
index 0000000..21f415b
--- /dev/null
+++ b/src/test/ui/parser/no-binary-float-literal.stderr
@@ -0,0 +1,22 @@
+error: binary float literal is not supported
+  --> $DIR/no-binary-float-literal.rs:4:5
+   |
+LL |     0b101.010;
+   |     ^^^^^^^^^
+
+error: binary float literal is not supported
+  --> $DIR/no-binary-float-literal.rs:2:5
+   |
+LL |     0b101010f64;
+   |     ^^^^^^^^^^^ not supported
+
+error: invalid suffix `p4f64` for numeric literal
+  --> $DIR/no-binary-float-literal.rs:6:5
+   |
+LL |     0b101p4f64;
+   |     ^^^^^^^^^^ invalid suffix `p4f64`
+   |
+   = help: the suffix must be one of the integral types (`u32`, `isize`, etc)
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/parser/no-hex-float-literal.rs b/src/test/ui/parser/no-hex-float-literal.rs
new file mode 100644
index 0000000..bf11dee
--- /dev/null
+++ b/src/test/ui/parser/no-hex-float-literal.rs
@@ -0,0 +1,9 @@
+fn main() {
+    0xABC.Df;
+    //~^ ERROR `{integer}` is a primitive type and therefore doesn't have fields
+    0x567.89;
+    //~^ ERROR hexadecimal float literal is not supported
+    0xDEAD.BEEFp-2f;
+    //~^ ERROR invalid suffix `f` for float literal
+    //~| ERROR `{integer}` is a primitive type and therefore doesn't have fields
+}
diff --git a/src/test/ui/parser/no-hex-float-literal.stderr b/src/test/ui/parser/no-hex-float-literal.stderr
new file mode 100644
index 0000000..258ab06
--- /dev/null
+++ b/src/test/ui/parser/no-hex-float-literal.stderr
@@ -0,0 +1,29 @@
+error: hexadecimal float literal is not supported
+  --> $DIR/no-hex-float-literal.rs:4:5
+   |
+LL |     0x567.89;
+   |     ^^^^^^^^
+
+error: invalid suffix `f` for float literal
+  --> $DIR/no-hex-float-literal.rs:6:18
+   |
+LL |     0xDEAD.BEEFp-2f;
+   |                  ^^ invalid suffix `f`
+   |
+   = help: valid suffixes are `f32` and `f64`
+
+error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields
+  --> $DIR/no-hex-float-literal.rs:2:11
+   |
+LL |     0xABC.Df;
+   |           ^^
+
+error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields
+  --> $DIR/no-hex-float-literal.rs:6:12
+   |
+LL |     0xDEAD.BEEFp-2f;
+   |            ^^^^^
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0610`.
diff --git a/src/test/ui/parser/no-unsafe-self.rs b/src/test/ui/parser/no-unsafe-self.rs
new file mode 100644
index 0000000..57201f2
--- /dev/null
+++ b/src/test/ui/parser/no-unsafe-self.rs
@@ -0,0 +1,16 @@
+// compile-flags: -Z continue-parse-after-error
+
+trait A {
+    fn foo(*mut self); //~ ERROR cannot pass `self` by raw pointer
+    fn baz(*const self); //~ ERROR cannot pass `self` by raw pointer
+    fn bar(*self); //~ ERROR cannot pass `self` by raw pointer
+}
+
+struct X;
+impl A for X {
+    fn foo(*mut self) { } //~ ERROR cannot pass `self` by raw pointer
+    fn baz(*const self) { } //~ ERROR cannot pass `self` by raw pointer
+    fn bar(*self) { } //~ ERROR cannot pass `self` by raw pointer
+}
+
+fn main() { }
diff --git a/src/test/ui/parser/no-unsafe-self.stderr b/src/test/ui/parser/no-unsafe-self.stderr
new file mode 100644
index 0000000..96d8b56
--- /dev/null
+++ b/src/test/ui/parser/no-unsafe-self.stderr
@@ -0,0 +1,38 @@
+error: cannot pass `self` by raw pointer
+  --> $DIR/no-unsafe-self.rs:4:17
+   |
+LL |     fn foo(*mut self);
+   |                 ^^^^ cannot pass `self` by raw pointer
+
+error: cannot pass `self` by raw pointer
+  --> $DIR/no-unsafe-self.rs:5:19
+   |
+LL |     fn baz(*const self);
+   |                   ^^^^ cannot pass `self` by raw pointer
+
+error: cannot pass `self` by raw pointer
+  --> $DIR/no-unsafe-self.rs:6:13
+   |
+LL |     fn bar(*self);
+   |             ^^^^ cannot pass `self` by raw pointer
+
+error: cannot pass `self` by raw pointer
+  --> $DIR/no-unsafe-self.rs:11:17
+   |
+LL |     fn foo(*mut self) { }
+   |                 ^^^^ cannot pass `self` by raw pointer
+
+error: cannot pass `self` by raw pointer
+  --> $DIR/no-unsafe-self.rs:12:19
+   |
+LL |     fn baz(*const self) { }
+   |                   ^^^^ cannot pass `self` by raw pointer
+
+error: cannot pass `self` by raw pointer
+  --> $DIR/no-unsafe-self.rs:13:13
+   |
+LL |     fn bar(*self) { }
+   |             ^^^^ cannot pass `self` by raw pointer
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/parser/not-a-pred.rs b/src/test/ui/parser/not-a-pred.rs
new file mode 100644
index 0000000..e6a02d5
--- /dev/null
+++ b/src/test/ui/parser/not-a-pred.rs
@@ -0,0 +1,7 @@
+// error-pattern: lt
+
+fn f(a: isize, b: isize) : lt(a, b) { }
+
+fn lt(a: isize, b: isize) { }
+
+fn main() { let a: isize = 10; let b: isize = 23; check (lt(a, b)); f(a, b); }
diff --git a/src/test/ui/parser/not-a-pred.stderr b/src/test/ui/parser/not-a-pred.stderr
new file mode 100644
index 0000000..46d6038
--- /dev/null
+++ b/src/test/ui/parser/not-a-pred.stderr
@@ -0,0 +1,8 @@
+error: expected one of `->`, `where`, or `{`, found `:`
+  --> $DIR/not-a-pred.rs:3:26
+   |
+LL | fn f(a: isize, b: isize) : lt(a, b) { }
+   |                          ^ expected one of `->`, `where`, or `{` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/numeric-lifetime.rs b/src/test/ui/parser/numeric-lifetime.rs
new file mode 100644
index 0000000..2d82354
--- /dev/null
+++ b/src/test/ui/parser/numeric-lifetime.rs
@@ -0,0 +1,8 @@
+struct S<'1> { s: &'1 usize }
+//~^ ERROR lifetimes cannot start with a number
+//~| ERROR lifetimes cannot start with a number
+fn main() {
+    // verify that the parse error doesn't stop type checking
+    let x: usize = "";
+    //~^ ERROR mismatched types
+}
diff --git a/src/test/ui/parser/numeric-lifetime.stderr b/src/test/ui/parser/numeric-lifetime.stderr
new file mode 100644
index 0000000..4018b24
--- /dev/null
+++ b/src/test/ui/parser/numeric-lifetime.stderr
@@ -0,0 +1,24 @@
+error: lifetimes cannot start with a number
+  --> $DIR/numeric-lifetime.rs:1:10
+   |
+LL | struct S<'1> { s: &'1 usize }
+   |          ^^
+
+error: lifetimes cannot start with a number
+  --> $DIR/numeric-lifetime.rs:1:20
+   |
+LL | struct S<'1> { s: &'1 usize }
+   |                    ^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-lifetime.rs:6:20
+   |
+LL |     let x: usize = "";
+   |                    ^^ expected usize, found reference
+   |
+   = note: expected type `usize`
+              found type `&'static str`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/parser/omitted-arg-in-item-fn.rs b/src/test/ui/parser/omitted-arg-in-item-fn.rs
new file mode 100644
index 0000000..5ee9daf
--- /dev/null
+++ b/src/test/ui/parser/omitted-arg-in-item-fn.rs
@@ -0,0 +1,4 @@
+fn foo(x) { //~ ERROR expected one of `:` or `@`, found `)`
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/omitted-arg-in-item-fn.stderr b/src/test/ui/parser/omitted-arg-in-item-fn.stderr
new file mode 100644
index 0000000..4f2a76d
--- /dev/null
+++ b/src/test/ui/parser/omitted-arg-in-item-fn.stderr
@@ -0,0 +1,8 @@
+error: expected one of `:` or `@`, found `)`
+  --> $DIR/omitted-arg-in-item-fn.rs:1:9
+   |
+LL | fn foo(x) {
+   |         ^ expected one of `:` or `@` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/paamayim-nekudotayim.rs b/src/test/ui/parser/paamayim-nekudotayim.rs
new file mode 100644
index 0000000..cb151d6
--- /dev/null
+++ b/src/test/ui/parser/paamayim-nekudotayim.rs
@@ -0,0 +1,5 @@
+// http://phpsadness.com/sad/1
+
+fn main() {
+    ::; //~ ERROR expected identifier, found `;`
+}
diff --git a/src/test/ui/parser/paamayim-nekudotayim.stderr b/src/test/ui/parser/paamayim-nekudotayim.stderr
new file mode 100644
index 0000000..6ceba07
--- /dev/null
+++ b/src/test/ui/parser/paamayim-nekudotayim.stderr
@@ -0,0 +1,8 @@
+error: expected identifier, found `;`
+  --> $DIR/paamayim-nekudotayim.rs:4:7
+   |
+LL |     ::;
+   |       ^ expected identifier
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/paren-after-qualified-path-in-match.rs b/src/test/ui/parser/paren-after-qualified-path-in-match.rs
new file mode 100644
index 0000000..68b1c2b
--- /dev/null
+++ b/src/test/ui/parser/paren-after-qualified-path-in-match.rs
@@ -0,0 +1,7 @@
+fn main() {
+    match 10 {
+        <T as Trait>::Type(2) => (),
+        //~^ ERROR unexpected `(` after qualified path
+        _ => (),
+    }
+}
diff --git a/src/test/ui/parser/paren-after-qualified-path-in-match.stderr b/src/test/ui/parser/paren-after-qualified-path-in-match.stderr
new file mode 100644
index 0000000..79460e0
--- /dev/null
+++ b/src/test/ui/parser/paren-after-qualified-path-in-match.stderr
@@ -0,0 +1,8 @@
+error: unexpected `(` after qualified path
+  --> $DIR/paren-after-qualified-path-in-match.rs:3:27
+   |
+LL |         <T as Trait>::Type(2) => (),
+   |                           ^ unexpected `(` after qualified path
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/pat-lt-bracket-1.rs b/src/test/ui/parser/pat-lt-bracket-1.rs
new file mode 100644
index 0000000..2e20014
--- /dev/null
+++ b/src/test/ui/parser/pat-lt-bracket-1.rs
@@ -0,0 +1,7 @@
+fn main() {
+  match 42 {
+    x < 7 => (),
+   //~^ error: expected one of `=>`, `@`, `if`, or `|`, found `<`
+    _ => ()
+  }
+}
diff --git a/src/test/ui/parser/pat-lt-bracket-1.stderr b/src/test/ui/parser/pat-lt-bracket-1.stderr
new file mode 100644
index 0000000..1bf2716
--- /dev/null
+++ b/src/test/ui/parser/pat-lt-bracket-1.stderr
@@ -0,0 +1,8 @@
+error: expected one of `=>`, `@`, `if`, or `|`, found `<`
+  --> $DIR/pat-lt-bracket-1.rs:3:7
+   |
+LL |     x < 7 => (),
+   |       ^ expected one of `=>`, `@`, `if`, or `|` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/pat-lt-bracket-2.rs b/src/test/ui/parser/pat-lt-bracket-2.rs
new file mode 100644
index 0000000..6eb01c1c
--- /dev/null
+++ b/src/test/ui/parser/pat-lt-bracket-2.rs
@@ -0,0 +1,4 @@
+fn a(B<) {}
+   //~^ error: expected one of `:` or `@`, found `<`
+
+fn main() {}
diff --git a/src/test/ui/parser/pat-lt-bracket-2.stderr b/src/test/ui/parser/pat-lt-bracket-2.stderr
new file mode 100644
index 0000000..cce1a17
--- /dev/null
+++ b/src/test/ui/parser/pat-lt-bracket-2.stderr
@@ -0,0 +1,8 @@
+error: expected one of `:` or `@`, found `<`
+  --> $DIR/pat-lt-bracket-2.rs:1:7
+   |
+LL | fn a(B<) {}
+   |       ^ expected one of `:` or `@` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/pat-lt-bracket-3.rs b/src/test/ui/parser/pat-lt-bracket-3.rs
new file mode 100644
index 0000000..a8bdfd3
--- /dev/null
+++ b/src/test/ui/parser/pat-lt-bracket-3.rs
@@ -0,0 +1,14 @@
+struct Foo<T>(T, T);
+
+impl<T> Foo<T> {
+    fn foo(&self) {
+        match *self {
+            Foo<T>(x, y) => {
+            //~^ error: expected one of `=>`, `@`, `if`, or `|`, found `<`
+              println!("Goodbye, World!")
+            }
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/pat-lt-bracket-3.stderr b/src/test/ui/parser/pat-lt-bracket-3.stderr
new file mode 100644
index 0000000..536d14e
--- /dev/null
+++ b/src/test/ui/parser/pat-lt-bracket-3.stderr
@@ -0,0 +1,8 @@
+error: expected one of `=>`, `@`, `if`, or `|`, found `<`
+  --> $DIR/pat-lt-bracket-3.rs:6:16
+   |
+LL |             Foo<T>(x, y) => {
+   |                ^ expected one of `=>`, `@`, `if`, or `|` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/pat-lt-bracket-4.rs b/src/test/ui/parser/pat-lt-bracket-4.rs
new file mode 100644
index 0000000..de314f6
--- /dev/null
+++ b/src/test/ui/parser/pat-lt-bracket-4.rs
@@ -0,0 +1,11 @@
+enum BtNode {
+    Node(u32,Box<BtNode>,Box<BtNode>),
+    Leaf(u32),
+}
+
+fn main() {
+    let y = match 10 {
+        Foo<T>::A(value) => value, //~ error: expected one of `=>`, `@`, `if`, or `|`, found `<`
+        Foo<T>::B => 7,
+    };
+}
diff --git a/src/test/ui/parser/pat-lt-bracket-4.stderr b/src/test/ui/parser/pat-lt-bracket-4.stderr
new file mode 100644
index 0000000..d14702a
--- /dev/null
+++ b/src/test/ui/parser/pat-lt-bracket-4.stderr
@@ -0,0 +1,8 @@
+error: expected one of `=>`, `@`, `if`, or `|`, found `<`
+  --> $DIR/pat-lt-bracket-4.rs:8:12
+   |
+LL |         Foo<T>::A(value) => value,
+   |            ^ expected one of `=>`, `@`, `if`, or `|` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/pat-lt-bracket-5.rs b/src/test/ui/parser/pat-lt-bracket-5.rs
new file mode 100644
index 0000000..c4b9dd4
--- /dev/null
+++ b/src/test/ui/parser/pat-lt-bracket-5.rs
@@ -0,0 +1,3 @@
+fn main() {
+    let v[0] = v[1]; //~ ERROR expected one of `:`, `;`, `=`, or `@`, found `[`
+}
diff --git a/src/test/ui/parser/pat-lt-bracket-5.stderr b/src/test/ui/parser/pat-lt-bracket-5.stderr
new file mode 100644
index 0000000..ce4cc05
--- /dev/null
+++ b/src/test/ui/parser/pat-lt-bracket-5.stderr
@@ -0,0 +1,8 @@
+error: expected one of `:`, `;`, `=`, or `@`, found `[`
+  --> $DIR/pat-lt-bracket-5.rs:2:10
+   |
+LL |     let v[0] = v[1];
+   |          ^ expected one of `:`, `;`, `=`, or `@` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/pat-lt-bracket-6.rs b/src/test/ui/parser/pat-lt-bracket-6.rs
new file mode 100644
index 0000000..9bad0cb
--- /dev/null
+++ b/src/test/ui/parser/pat-lt-bracket-6.rs
@@ -0,0 +1,3 @@
+fn main() {
+    let Test(&desc[..]) = x; //~ ERROR: expected one of `)`, `,`, or `@`, found `[`
+}
diff --git a/src/test/ui/parser/pat-lt-bracket-6.stderr b/src/test/ui/parser/pat-lt-bracket-6.stderr
new file mode 100644
index 0000000..2ee4bdb
--- /dev/null
+++ b/src/test/ui/parser/pat-lt-bracket-6.stderr
@@ -0,0 +1,8 @@
+error: expected one of `)`, `,`, or `@`, found `[`
+  --> $DIR/pat-lt-bracket-6.rs:2:19
+   |
+LL |     let Test(&desc[..]) = x;
+   |                   ^ expected one of `)`, `,`, or `@` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/pat-lt-bracket-7.rs b/src/test/ui/parser/pat-lt-bracket-7.rs
new file mode 100644
index 0000000..36c0d77
--- /dev/null
+++ b/src/test/ui/parser/pat-lt-bracket-7.rs
@@ -0,0 +1,3 @@
+fn main() {
+    for thing(x[]) in foo {} //~ ERROR: expected one of `)`, `,`, or `@`, found `[`
+}
diff --git a/src/test/ui/parser/pat-lt-bracket-7.stderr b/src/test/ui/parser/pat-lt-bracket-7.stderr
new file mode 100644
index 0000000..5552ea4
--- /dev/null
+++ b/src/test/ui/parser/pat-lt-bracket-7.stderr
@@ -0,0 +1,8 @@
+error: expected one of `)`, `,`, or `@`, found `[`
+  --> $DIR/pat-lt-bracket-7.rs:2:16
+   |
+LL |     for thing(x[]) in foo {}
+   |                ^ expected one of `)`, `,`, or `@` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/pat-ranges-1.rs b/src/test/ui/parser/pat-ranges-1.rs
new file mode 100644
index 0000000..ce953b2
--- /dev/null
+++ b/src/test/ui/parser/pat-ranges-1.rs
@@ -0,0 +1,5 @@
+// Parsing of range patterns
+
+fn main() {
+    let macropus!() ..= 11 = 12; //~ error: expected one of `:`, `;`, or `=`, found `..=`
+}
diff --git a/src/test/ui/parser/pat-ranges-1.stderr b/src/test/ui/parser/pat-ranges-1.stderr
new file mode 100644
index 0000000..6e0decc
--- /dev/null
+++ b/src/test/ui/parser/pat-ranges-1.stderr
@@ -0,0 +1,8 @@
+error: expected one of `:`, `;`, or `=`, found `..=`
+  --> $DIR/pat-ranges-1.rs:4:21
+   |
+LL |     let macropus!() ..= 11 = 12;
+   |                     ^^^ expected one of `:`, `;`, or `=` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/pat-ranges-2.rs b/src/test/ui/parser/pat-ranges-2.rs
new file mode 100644
index 0000000..9f736ed
--- /dev/null
+++ b/src/test/ui/parser/pat-ranges-2.rs
@@ -0,0 +1,5 @@
+// Parsing of range patterns
+
+fn main() {
+    let 10 ..= makropulos!() = 12; //~ error: expected one of `::`, `:`, `;`, or `=`, found `!`
+}
diff --git a/src/test/ui/parser/pat-ranges-2.stderr b/src/test/ui/parser/pat-ranges-2.stderr
new file mode 100644
index 0000000..d180bb4
--- /dev/null
+++ b/src/test/ui/parser/pat-ranges-2.stderr
@@ -0,0 +1,8 @@
+error: expected one of `::`, `:`, `;`, or `=`, found `!`
+  --> $DIR/pat-ranges-2.rs:4:26
+   |
+LL |     let 10 ..= makropulos!() = 12;
+   |                          ^ expected one of `::`, `:`, `;`, or `=` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/pat-ranges-3.rs b/src/test/ui/parser/pat-ranges-3.rs
new file mode 100644
index 0000000..65da55e
--- /dev/null
+++ b/src/test/ui/parser/pat-ranges-3.rs
@@ -0,0 +1,5 @@
+// Parsing of range patterns
+
+fn main() {
+    let 10 ..= 10 + 3 = 12; //~ expected one of `:`, `;`, or `=`, found `+`
+}
diff --git a/src/test/ui/parser/pat-ranges-3.stderr b/src/test/ui/parser/pat-ranges-3.stderr
new file mode 100644
index 0000000..aaa85e3
--- /dev/null
+++ b/src/test/ui/parser/pat-ranges-3.stderr
@@ -0,0 +1,8 @@
+error: expected one of `:`, `;`, or `=`, found `+`
+  --> $DIR/pat-ranges-3.rs:4:19
+   |
+LL |     let 10 ..= 10 + 3 = 12;
+   |                   ^ expected one of `:`, `;`, or `=` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/pat-ranges-4.rs b/src/test/ui/parser/pat-ranges-4.rs
new file mode 100644
index 0000000..7f4a5f3
--- /dev/null
+++ b/src/test/ui/parser/pat-ranges-4.rs
@@ -0,0 +1,6 @@
+// Parsing of range patterns
+
+fn main() {
+    let 10 - 3 ..= 10 = 8;
+    //~^ error: expected one of `...`, `..=`, `..`, `:`, `;`, or `=`, found `-`
+}
diff --git a/src/test/ui/parser/pat-ranges-4.stderr b/src/test/ui/parser/pat-ranges-4.stderr
new file mode 100644
index 0000000..0a1d7a1
--- /dev/null
+++ b/src/test/ui/parser/pat-ranges-4.stderr
@@ -0,0 +1,8 @@
+error: expected one of `...`, `..=`, `..`, `:`, `;`, or `=`, found `-`
+  --> $DIR/pat-ranges-4.rs:4:12
+   |
+LL |     let 10 - 3 ..= 10 = 8;
+   |            ^ expected one of `...`, `..=`, `..`, `:`, `;`, or `=` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/pat-ref-enum.rs b/src/test/ui/parser/pat-ref-enum.rs
new file mode 100644
index 0000000..412dd14
--- /dev/null
+++ b/src/test/ui/parser/pat-ref-enum.rs
@@ -0,0 +1,8 @@
+fn matcher(x: Option<isize>) {
+    match x {
+      ref Some(i) => {} //~ ERROR expected identifier, found enum pattern
+      None => {}
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/pat-ref-enum.stderr b/src/test/ui/parser/pat-ref-enum.stderr
new file mode 100644
index 0000000..a3bce33
--- /dev/null
+++ b/src/test/ui/parser/pat-ref-enum.stderr
@@ -0,0 +1,8 @@
+error: expected identifier, found enum pattern
+  --> $DIR/pat-ref-enum.rs:3:11
+   |
+LL |       ref Some(i) => {}
+   |           ^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/pat-tuple-1.rs b/src/test/ui/parser/pat-tuple-1.rs
new file mode 100644
index 0000000..0e49b54
--- /dev/null
+++ b/src/test/ui/parser/pat-tuple-1.rs
@@ -0,0 +1,5 @@
+fn main() {
+    match (0, 1) {
+        (, ..) => {} //~ ERROR expected pattern, found `,`
+    }
+}
diff --git a/src/test/ui/parser/pat-tuple-1.stderr b/src/test/ui/parser/pat-tuple-1.stderr
new file mode 100644
index 0000000..391f2c4
--- /dev/null
+++ b/src/test/ui/parser/pat-tuple-1.stderr
@@ -0,0 +1,8 @@
+error: expected pattern, found `,`
+  --> $DIR/pat-tuple-1.rs:3:10
+   |
+LL |         (, ..) => {}
+   |          ^ expected pattern
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/pat-tuple-2.rs b/src/test/ui/parser/pat-tuple-2.rs
new file mode 100644
index 0000000..fd25499
--- /dev/null
+++ b/src/test/ui/parser/pat-tuple-2.rs
@@ -0,0 +1,6 @@
+fn main() {
+    match (0, 1, 2) {
+        (pat, ..,) => {}
+        //~^ ERROR trailing comma is not permitted after `..`
+    }
+}
diff --git a/src/test/ui/parser/pat-tuple-2.stderr b/src/test/ui/parser/pat-tuple-2.stderr
new file mode 100644
index 0000000..c3a5c39
--- /dev/null
+++ b/src/test/ui/parser/pat-tuple-2.stderr
@@ -0,0 +1,8 @@
+error: trailing comma is not permitted after `..`
+  --> $DIR/pat-tuple-2.rs:3:17
+   |
+LL |         (pat, ..,) => {}
+   |                 ^ trailing comma is not permitted after `..`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/pat-tuple-3.rs b/src/test/ui/parser/pat-tuple-3.rs
new file mode 100644
index 0000000..e1e975d
--- /dev/null
+++ b/src/test/ui/parser/pat-tuple-3.rs
@@ -0,0 +1,6 @@
+fn main() {
+    match (0, 1, 2) {
+        (.., pat, ..) => {}
+        //~^ ERROR `..` can only be used once per tuple or tuple struct pattern
+    }
+}
diff --git a/src/test/ui/parser/pat-tuple-3.stderr b/src/test/ui/parser/pat-tuple-3.stderr
new file mode 100644
index 0000000..c9f14bb
--- /dev/null
+++ b/src/test/ui/parser/pat-tuple-3.stderr
@@ -0,0 +1,10 @@
+error: `..` can only be used once per tuple or tuple struct pattern
+  --> $DIR/pat-tuple-3.rs:3:19
+   |
+LL |         (.., pat, ..) => {}
+   |          --       ^^ can only be used once per pattern
+   |          |
+   |          previously present here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/pat-tuple-4.rs b/src/test/ui/parser/pat-tuple-4.rs
new file mode 100644
index 0000000..76f60d9
--- /dev/null
+++ b/src/test/ui/parser/pat-tuple-4.rs
@@ -0,0 +1,5 @@
+fn main() {
+    match 0 {
+        (.. pat) => {} //~ ERROR expected one of `)` or `,`, found `pat`
+    }
+}
diff --git a/src/test/ui/parser/pat-tuple-4.stderr b/src/test/ui/parser/pat-tuple-4.stderr
new file mode 100644
index 0000000..26b92fa
--- /dev/null
+++ b/src/test/ui/parser/pat-tuple-4.stderr
@@ -0,0 +1,8 @@
+error: expected one of `)` or `,`, found `pat`
+  --> $DIR/pat-tuple-4.rs:3:13
+   |
+LL |         (.. pat) => {}
+   |             ^^^ expected one of `)` or `,` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/pat-tuple-5.rs b/src/test/ui/parser/pat-tuple-5.rs
new file mode 100644
index 0000000..d4f05a5
--- /dev/null
+++ b/src/test/ui/parser/pat-tuple-5.rs
@@ -0,0 +1,5 @@
+fn main() {
+    match (0, 1) {
+        (pat ..) => {} //~ ERROR unexpected token: `)`
+    }
+}
diff --git a/src/test/ui/parser/pat-tuple-5.stderr b/src/test/ui/parser/pat-tuple-5.stderr
new file mode 100644
index 0000000..61ae40b
--- /dev/null
+++ b/src/test/ui/parser/pat-tuple-5.stderr
@@ -0,0 +1,8 @@
+error: unexpected token: `)`
+  --> $DIR/pat-tuple-5.rs:3:14
+   |
+LL |         (pat ..) => {}
+   |              ^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/pub-method-macro.rs b/src/test/ui/parser/pub-method-macro.rs
new file mode 100644
index 0000000..f04af1a
--- /dev/null
+++ b/src/test/ui/parser/pub-method-macro.rs
@@ -0,0 +1,22 @@
+// Issue #18317
+
+mod bleh {
+    macro_rules! defn {
+        ($n:ident) => (
+            fn $n (&self) -> i32 {
+                println!("{}", stringify!($n));
+                1
+            }
+        )
+    }
+
+    #[derive(Copy, Clone)]
+    pub struct S;
+
+    impl S {
+        pub defn!(f); //~ ERROR can't qualify macro invocation with `pub`
+        //~^ HELP try adjusting the macro to put `pub` inside the invocation
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/pub-method-macro.stderr b/src/test/ui/parser/pub-method-macro.stderr
new file mode 100644
index 0000000..7b0fe49
--- /dev/null
+++ b/src/test/ui/parser/pub-method-macro.stderr
@@ -0,0 +1,10 @@
+error: can't qualify macro invocation with `pub`
+  --> $DIR/pub-method-macro.rs:17:9
+   |
+LL |         pub defn!(f);
+   |         ^^^
+   |
+   = help: try adjusting the macro to put `pub` inside the invocation
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/range-3.rs b/src/test/ui/parser/range-3.rs
new file mode 100644
index 0000000..931839f
--- /dev/null
+++ b/src/test/ui/parser/range-3.rs
@@ -0,0 +1,6 @@
+// Test range syntax - syntax errors.
+
+pub fn main() {
+    let r = 1..2..3;
+    //~^ ERROR expected one of `.`, `;`, `?`, or an operator, found `..`
+}
diff --git a/src/test/ui/parser/range-3.stderr b/src/test/ui/parser/range-3.stderr
new file mode 100644
index 0000000..92c3348
--- /dev/null
+++ b/src/test/ui/parser/range-3.stderr
@@ -0,0 +1,8 @@
+error: expected one of `.`, `;`, `?`, or an operator, found `..`
+  --> $DIR/range-3.rs:4:17
+   |
+LL |     let r = 1..2..3;
+   |                 ^^ expected one of `.`, `;`, `?`, or an operator here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/range-4.rs b/src/test/ui/parser/range-4.rs
new file mode 100644
index 0000000..20af956
--- /dev/null
+++ b/src/test/ui/parser/range-4.rs
@@ -0,0 +1,6 @@
+// Test range syntax - syntax errors.
+
+pub fn main() {
+    let r = ..1..2;
+    //~^ ERROR expected one of `.`, `;`, `?`, or an operator, found `..`
+}
diff --git a/src/test/ui/parser/range-4.stderr b/src/test/ui/parser/range-4.stderr
new file mode 100644
index 0000000..90ec461
--- /dev/null
+++ b/src/test/ui/parser/range-4.stderr
@@ -0,0 +1,8 @@
+error: expected one of `.`, `;`, `?`, or an operator, found `..`
+  --> $DIR/range-4.rs:4:16
+   |
+LL |     let r = ..1..2;
+   |                ^^ expected one of `.`, `;`, `?`, or an operator here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/range_inclusive.rs b/src/test/ui/parser/range_inclusive.rs
new file mode 100644
index 0000000..bc61c5b
--- /dev/null
+++ b/src/test/ui/parser/range_inclusive.rs
@@ -0,0 +1,6 @@
+// Make sure that inclusive ranges with no end point don't parse.
+
+pub fn main() {
+    for _ in 1..= {} //~ERROR inclusive range with no end
+                     //~^HELP bounded at the end
+}
diff --git a/src/test/ui/parser/range_inclusive.stderr b/src/test/ui/parser/range_inclusive.stderr
new file mode 100644
index 0000000..12b7eda
--- /dev/null
+++ b/src/test/ui/parser/range_inclusive.stderr
@@ -0,0 +1,11 @@
+error[E0586]: inclusive range with no end
+  --> $DIR/range_inclusive.rs:4:19
+   |
+LL |     for _ in 1..= {}
+   |                   ^
+   |
+   = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0586`.
diff --git a/src/test/ui/parser/range_inclusive_dotdotdot.rs b/src/test/ui/parser/range_inclusive_dotdotdot.rs
new file mode 100644
index 0000000..a780304
--- /dev/null
+++ b/src/test/ui/parser/range_inclusive_dotdotdot.rs
@@ -0,0 +1,25 @@
+// compile-flags: -Z continue-parse-after-error
+
+// Make sure that inclusive ranges with `...` syntax don't parse.
+
+use std::ops::RangeToInclusive;
+
+fn return_range_to() -> RangeToInclusive<i32> {
+    return ...1; //~ERROR unexpected token: `...`
+                 //~^HELP  use `..` for an exclusive range
+                 //~^^HELP or `..=` for an inclusive range
+}
+
+pub fn main() {
+    let x = ...0;    //~ERROR unexpected token: `...`
+                     //~^HELP  use `..` for an exclusive range
+                     //~^^HELP or `..=` for an inclusive range
+
+    let x = 5...5;   //~ERROR unexpected token: `...`
+                     //~^HELP  use `..` for an exclusive range
+                     //~^^HELP or `..=` for an inclusive range
+
+    for _ in 0...1 {} //~ERROR unexpected token: `...`
+                     //~^HELP  use `..` for an exclusive range
+                     //~^^HELP or `..=` for an inclusive range
+}
diff --git a/src/test/ui/parser/range_inclusive_dotdotdot.stderr b/src/test/ui/parser/range_inclusive_dotdotdot.stderr
new file mode 100644
index 0000000..21ad26d
--- /dev/null
+++ b/src/test/ui/parser/range_inclusive_dotdotdot.stderr
@@ -0,0 +1,58 @@
+error: unexpected token: `...`
+  --> $DIR/range_inclusive_dotdotdot.rs:8:12
+   |
+LL |     return ...1;
+   |            ^^^
+help: use `..` for an exclusive range
+   |
+LL |     return ..1;
+   |            ^^
+help: or `..=` for an inclusive range
+   |
+LL |     return ..=1;
+   |            ^^^
+
+error: unexpected token: `...`
+  --> $DIR/range_inclusive_dotdotdot.rs:14:13
+   |
+LL |     let x = ...0;
+   |             ^^^
+help: use `..` for an exclusive range
+   |
+LL |     let x = ..0;
+   |             ^^
+help: or `..=` for an inclusive range
+   |
+LL |     let x = ..=0;
+   |             ^^^
+
+error: unexpected token: `...`
+  --> $DIR/range_inclusive_dotdotdot.rs:18:14
+   |
+LL |     let x = 5...5;
+   |              ^^^
+help: use `..` for an exclusive range
+   |
+LL |     let x = 5..5;
+   |              ^^
+help: or `..=` for an inclusive range
+   |
+LL |     let x = 5..=5;
+   |              ^^^
+
+error: unexpected token: `...`
+  --> $DIR/range_inclusive_dotdotdot.rs:22:15
+   |
+LL |     for _ in 0...1 {}
+   |               ^^^
+help: use `..` for an exclusive range
+   |
+LL |     for _ in 0..1 {}
+   |               ^^
+help: or `..=` for an inclusive range
+   |
+LL |     for _ in 0..=1 {}
+   |               ^^^
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/parser/raw-byte-string-eof.rs b/src/test/ui/parser/raw-byte-string-eof.rs
new file mode 100644
index 0000000..b74907b
--- /dev/null
+++ b/src/test/ui/parser/raw-byte-string-eof.rs
@@ -0,0 +1,3 @@
+pub fn main() {
+    br##"a"#;  //~ unterminated raw string
+}
diff --git a/src/test/ui/parser/raw-byte-string-eof.stderr b/src/test/ui/parser/raw-byte-string-eof.stderr
new file mode 100644
index 0000000..2ba50e8
--- /dev/null
+++ b/src/test/ui/parser/raw-byte-string-eof.stderr
@@ -0,0 +1,10 @@
+error: unterminated raw string
+  --> $DIR/raw-byte-string-eof.rs:2:6
+   |
+LL |     br##"a"#;
+   |      ^ unterminated raw string
+   |
+   = note: this raw string should be terminated with `"##`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/raw-byte-string-literals.rs b/src/test/ui/parser/raw-byte-string-literals.rs
new file mode 100644
index 0000000..2800e40
--- /dev/null
+++ b/src/test/ui/parser/raw-byte-string-literals.rs
@@ -0,0 +1,7 @@
+// compile-flags: -Z continue-parse-after-error
+
+
+pub fn main() {
+    br"é";  //~ ERROR raw byte string must be ASCII
+    br##~"a"~##;  //~ ERROR only `#` is allowed in raw string delimitation
+}
diff --git a/src/test/ui/parser/raw-byte-string-literals.stderr b/src/test/ui/parser/raw-byte-string-literals.stderr
new file mode 100644
index 0000000..a7f1af0
--- /dev/null
+++ b/src/test/ui/parser/raw-byte-string-literals.stderr
@@ -0,0 +1,14 @@
+error: raw byte string must be ASCII: \u{e9}
+  --> $DIR/raw-byte-string-literals.rs:5:8
+   |
+LL |     br"é";
+   |        ^
+
+error: found invalid character; only `#` is allowed in raw string delimitation: ~
+  --> $DIR/raw-byte-string-literals.rs:6:6
+   |
+LL |     br##~"a"~##;
+   |      ^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/parser/raw-str-delim.rs b/src/test/ui/parser/raw-str-delim.rs
new file mode 100644
index 0000000..2f13893
--- /dev/null
+++ b/src/test/ui/parser/raw-str-delim.rs
@@ -0,0 +1,3 @@
+static s: &'static str =
+    r#~"#"~# //~ ERROR found invalid character; only `#` is allowed in raw string delimitation
+;
diff --git a/src/test/ui/parser/raw-str-delim.stderr b/src/test/ui/parser/raw-str-delim.stderr
new file mode 100644
index 0000000..b86b9e9
--- /dev/null
+++ b/src/test/ui/parser/raw-str-delim.stderr
@@ -0,0 +1,8 @@
+error: found invalid character; only `#` is allowed in raw string delimitation: ~
+  --> $DIR/raw-str-delim.rs:2:5
+   |
+LL |     r#~"#"~#
+   |     ^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/raw-str-unbalanced.rs b/src/test/ui/parser/raw-str-unbalanced.rs
new file mode 100644
index 0000000..5a1d1be
--- /dev/null
+++ b/src/test/ui/parser/raw-str-unbalanced.rs
@@ -0,0 +1,4 @@
+static s: &'static str =
+    r#"
+      "## //~ ERROR expected one of `.`, `;`, `?`, or an operator, found `#`
+;
diff --git a/src/test/ui/parser/raw-str-unbalanced.stderr b/src/test/ui/parser/raw-str-unbalanced.stderr
new file mode 100644
index 0000000..26910ff
--- /dev/null
+++ b/src/test/ui/parser/raw-str-unbalanced.stderr
@@ -0,0 +1,8 @@
+error: expected one of `.`, `;`, `?`, or an operator, found `#`
+  --> $DIR/raw-str-unbalanced.rs:3:9
+   |
+LL |       "##
+   |         ^ expected one of `.`, `;`, `?`, or an operator here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/raw-str-unterminated.rs b/src/test/ui/parser/raw-str-unterminated.rs
new file mode 100644
index 0000000..fd31729
--- /dev/null
+++ b/src/test/ui/parser/raw-str-unterminated.rs
@@ -0,0 +1,4 @@
+static s: &'static str =
+    r#" string literal goes on
+        and on
+    //~^^ ERROR unterminated raw string
diff --git a/src/test/ui/parser/raw-str-unterminated.stderr b/src/test/ui/parser/raw-str-unterminated.stderr
new file mode 100644
index 0000000..67792eb
--- /dev/null
+++ b/src/test/ui/parser/raw-str-unterminated.stderr
@@ -0,0 +1,10 @@
+error: unterminated raw string
+  --> $DIR/raw-str-unterminated.rs:2:5
+   |
+LL |     r#" string literal goes on
+   |     ^ unterminated raw string
+   |
+   = note: this raw string should be terminated with `"#`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/raw/raw-literal-keywords.rs b/src/test/ui/parser/raw/raw-literal-keywords.rs
new file mode 100644
index 0000000..f51e565
--- /dev/null
+++ b/src/test/ui/parser/raw/raw-literal-keywords.rs
@@ -0,0 +1,16 @@
+fn test_if() {
+    r#if true { } //~ ERROR found `true`
+                  //~| ERROR cannot find value `if` in this scope
+}
+
+fn test_struct() {
+    r#struct Test; //~ ERROR found `Test`
+                   //~| ERROR cannot find value `struct` in this scope
+}
+
+fn test_union() {
+    r#union Test; //~ ERROR found `Test`
+                  //~| ERROR cannot find value `union` in this scope
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/raw/raw-literal-keywords.stderr b/src/test/ui/parser/raw/raw-literal-keywords.stderr
new file mode 100644
index 0000000..8b8b713
--- /dev/null
+++ b/src/test/ui/parser/raw/raw-literal-keywords.stderr
@@ -0,0 +1,39 @@
+error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `true`
+  --> $DIR/raw-literal-keywords.rs:2:10
+   |
+LL |     r#if true { }
+   |          ^^^^ expected one of 8 possible tokens here
+
+error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `Test`
+  --> $DIR/raw-literal-keywords.rs:7:14
+   |
+LL |     r#struct Test;
+   |              ^^^^ expected one of 8 possible tokens here
+
+error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `Test`
+  --> $DIR/raw-literal-keywords.rs:12:13
+   |
+LL |     r#union Test;
+   |             ^^^^ expected one of 8 possible tokens here
+
+error[E0425]: cannot find value `if` in this scope
+  --> $DIR/raw-literal-keywords.rs:2:5
+   |
+LL |     r#if true { }
+   |     ^^^^ not found in this scope
+
+error[E0425]: cannot find value `struct` in this scope
+  --> $DIR/raw-literal-keywords.rs:7:5
+   |
+LL |     r#struct Test;
+   |     ^^^^^^^^ not found in this scope
+
+error[E0425]: cannot find value `union` in this scope
+  --> $DIR/raw-literal-keywords.rs:12:5
+   |
+LL |     r#union Test;
+   |     ^^^^^^^ not found in this scope
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/parser/raw/raw-literal-self.rs b/src/test/ui/parser/raw/raw-literal-self.rs
new file mode 100644
index 0000000..123a11b
--- /dev/null
+++ b/src/test/ui/parser/raw/raw-literal-self.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let r#self;
+    //~^ ERROR `self` cannot be a raw identifier
+}
diff --git a/src/test/ui/parser/raw/raw-literal-self.stderr b/src/test/ui/parser/raw/raw-literal-self.stderr
new file mode 100644
index 0000000..9a330fc
--- /dev/null
+++ b/src/test/ui/parser/raw/raw-literal-self.stderr
@@ -0,0 +1,8 @@
+error: `self` cannot be a raw identifier
+  --> $DIR/raw-literal-self.rs:2:9
+   |
+LL |     let r#self;
+   |         ^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/raw/raw-literal-underscore.rs b/src/test/ui/parser/raw/raw-literal-underscore.rs
new file mode 100644
index 0000000..6d15f1e
--- /dev/null
+++ b/src/test/ui/parser/raw/raw-literal-underscore.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let r#_;
+    //~^ ERROR `_` cannot be a raw identifier
+}
diff --git a/src/test/ui/parser/raw/raw-literal-underscore.stderr b/src/test/ui/parser/raw/raw-literal-underscore.stderr
new file mode 100644
index 0000000..d96b14f
--- /dev/null
+++ b/src/test/ui/parser/raw/raw-literal-underscore.stderr
@@ -0,0 +1,8 @@
+error: `_` cannot be a raw identifier
+  --> $DIR/raw-literal-underscore.rs:2:9
+   |
+LL |     let r#_;
+   |         ^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/raw/raw_string.rs b/src/test/ui/parser/raw/raw_string.rs
new file mode 100644
index 0000000..84f07c4
--- /dev/null
+++ b/src/test/ui/parser/raw/raw_string.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let x = r##"lol"#;
+    //~^ ERROR unterminated raw string
+}
diff --git a/src/test/ui/parser/raw/raw_string.stderr b/src/test/ui/parser/raw/raw_string.stderr
new file mode 100644
index 0000000..5572511
--- /dev/null
+++ b/src/test/ui/parser/raw/raw_string.stderr
@@ -0,0 +1,10 @@
+error: unterminated raw string
+  --> $DIR/raw_string.rs:2:13
+   |
+LL |     let x = r##"lol"#;
+   |             ^ unterminated raw string
+   |
+   = note: this raw string should be terminated with `"##`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/recover-enum.rs b/src/test/ui/parser/recover-enum.rs
new file mode 100644
index 0000000..da42da8
--- /dev/null
+++ b/src/test/ui/parser/recover-enum.rs
@@ -0,0 +1,13 @@
+// compile-flags: -Z continue-parse-after-error
+
+fn main() {
+    enum Test {
+        Very
+        //~^ ERROR missing comma
+        Bad(usize)
+        //~^ ERROR missing comma
+        Stuff { a: usize }
+        //~^ ERROR missing comma
+        Here
+    }
+}
diff --git a/src/test/ui/parser/recover-enum.stderr b/src/test/ui/parser/recover-enum.stderr
new file mode 100644
index 0000000..10b4aba
--- /dev/null
+++ b/src/test/ui/parser/recover-enum.stderr
@@ -0,0 +1,20 @@
+error: missing comma
+  --> $DIR/recover-enum.rs:5:13
+   |
+LL |         Very
+   |             ^ help: missing comma
+
+error: missing comma
+  --> $DIR/recover-enum.rs:7:19
+   |
+LL |         Bad(usize)
+   |                   ^ help: missing comma
+
+error: missing comma
+  --> $DIR/recover-enum.rs:9:27
+   |
+LL |         Stuff { a: usize }
+   |                           ^ help: missing comma
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/parser/recover-enum2.rs b/src/test/ui/parser/recover-enum2.rs
new file mode 100644
index 0000000..7f2f2cc
--- /dev/null
+++ b/src/test/ui/parser/recover-enum2.rs
@@ -0,0 +1,30 @@
+// compile-flags: -Z continue-parse-after-error
+
+fn main() {
+    enum Test {
+        Var1,
+        Var2(String),
+        Var3 {
+            abc: {}, //~ ERROR: expected type, found `{`
+        },
+    }
+
+    // recover...
+    let a = 1;
+    enum Test2 {
+        Fine,
+    }
+
+    enum Test3 {
+        StillFine {
+            def: i32,
+        },
+    }
+
+    {
+        // fail again
+        enum Test4 {
+            Nope(i32 {}) //~ ERROR: found `{`
+        }
+    }
+}
diff --git a/src/test/ui/parser/recover-enum2.stderr b/src/test/ui/parser/recover-enum2.stderr
new file mode 100644
index 0000000..d1984a5
--- /dev/null
+++ b/src/test/ui/parser/recover-enum2.stderr
@@ -0,0 +1,14 @@
+error: expected type, found `{`
+  --> $DIR/recover-enum2.rs:8:18
+   |
+LL |             abc: {},
+   |                  ^
+
+error: expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `{`
+  --> $DIR/recover-enum2.rs:27:22
+   |
+LL |             Nope(i32 {})
+   |                      ^ expected one of 7 possible tokens here
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/parser/recover-from-bad-variant.rs b/src/test/ui/parser/recover-from-bad-variant.rs
new file mode 100644
index 0000000..35088fb
--- /dev/null
+++ b/src/test/ui/parser/recover-from-bad-variant.rs
@@ -0,0 +1,14 @@
+enum Enum {
+    Foo { a: usize, b: usize },
+    Bar(usize, usize),
+}
+
+fn main() {
+    let x = Enum::Foo(a: 3, b: 4);
+    //~^ ERROR expected type, found `3`
+    match x {
+        Enum::Foo(a, b) => {}
+        //~^ ERROR expected tuple struct/variant, found struct variant `Enum::Foo`
+        Enum::Bar(a, b) => {}
+    }
+}
diff --git a/src/test/ui/parser/recover-from-bad-variant.stderr b/src/test/ui/parser/recover-from-bad-variant.stderr
new file mode 100644
index 0000000..1eba6d7
--- /dev/null
+++ b/src/test/ui/parser/recover-from-bad-variant.stderr
@@ -0,0 +1,23 @@
+error: expected type, found `3`
+  --> $DIR/recover-from-bad-variant.rs:7:26
+   |
+LL |     let x = Enum::Foo(a: 3, b: 4);
+   |                          ^ expecting a type here because of type ascription
+   |
+   = note: type ascription is a nightly-only feature that lets you annotate an expression with a type: `<expr>: <type>`
+note: this expression expects an ascribed type after the colon
+  --> $DIR/recover-from-bad-variant.rs:7:23
+   |
+LL |     let x = Enum::Foo(a: 3, b: 4);
+   |                       ^
+   = help: this might be indicative of a syntax error elsewhere
+
+error[E0532]: expected tuple struct/variant, found struct variant `Enum::Foo`
+  --> $DIR/recover-from-bad-variant.rs:10:9
+   |
+LL |         Enum::Foo(a, b) => {}
+   |         ^^^^^^^^^ did you mean `Enum::Foo { /* fields */ }`?
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0532`.
diff --git a/src/test/ui/parser/recover-struct.rs b/src/test/ui/parser/recover-struct.rs
new file mode 100644
index 0000000..500591b
--- /dev/null
+++ b/src/test/ui/parser/recover-struct.rs
@@ -0,0 +1,9 @@
+// compile-flags: -Z continue-parse-after-error
+
+fn main() {
+    struct Test {
+        Very
+        Bad //~ ERROR found `Bad`
+        Stuff
+    }
+}
diff --git a/src/test/ui/parser/recover-struct.stderr b/src/test/ui/parser/recover-struct.stderr
new file mode 100644
index 0000000..8e11d6b
--- /dev/null
+++ b/src/test/ui/parser/recover-struct.stderr
@@ -0,0 +1,10 @@
+error: expected `:`, found `Bad`
+  --> $DIR/recover-struct.rs:6:9
+   |
+LL |         Very
+   |             - expected `:`
+LL |         Bad
+   |         ^^^ unexpected token
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/recover-tuple-pat.rs b/src/test/ui/parser/recover-tuple-pat.rs
new file mode 100644
index 0000000..488e8db
--- /dev/null
+++ b/src/test/ui/parser/recover-tuple-pat.rs
@@ -0,0 +1,12 @@
+fn main() {
+    let x = (1, 2, 3, 4);
+    match x {
+        (1, .., 4) => {}
+        (1, .=., 4) => { let _: usize = ""; }
+        //~^ ERROR expected pattern, found `.`
+        //~| ERROR mismatched types
+        (.=., 4) => {}
+        //~^ ERROR expected pattern, found `.`
+        (1, 2, 3, 4) => {}
+    }
+}
diff --git a/src/test/ui/parser/recover-tuple-pat.stderr b/src/test/ui/parser/recover-tuple-pat.stderr
new file mode 100644
index 0000000..5919aa7
--- /dev/null
+++ b/src/test/ui/parser/recover-tuple-pat.stderr
@@ -0,0 +1,24 @@
+error: expected pattern, found `.`
+  --> $DIR/recover-tuple-pat.rs:5:13
+   |
+LL |         (1, .=., 4) => { let _: usize = ""; }
+   |             ^ expected pattern
+
+error: expected pattern, found `.`
+  --> $DIR/recover-tuple-pat.rs:8:10
+   |
+LL |         (.=., 4) => {}
+   |          ^ expected pattern
+
+error[E0308]: mismatched types
+  --> $DIR/recover-tuple-pat.rs:5:41
+   |
+LL |         (1, .=., 4) => { let _: usize = ""; }
+   |                                         ^^ expected usize, found reference
+   |
+   = note: expected type `usize`
+              found type `&'static str`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/parser/recover-tuple.rs b/src/test/ui/parser/recover-tuple.rs
new file mode 100644
index 0000000..59e2695
--- /dev/null
+++ b/src/test/ui/parser/recover-tuple.rs
@@ -0,0 +1,11 @@
+fn main() {
+    // no complaints about the tuple not matching the expected type
+    let x: (usize, usize, usize) = (3, .=.);
+    //~^ ERROR expected expression, found `.`
+    // verify that the parser recovers:
+    let y: usize = ""; //~ ERROR mismatched types
+    // no complaints about the type
+    foo(x);
+}
+
+fn foo(_: (usize, usize, usize)) {}
diff --git a/src/test/ui/parser/recover-tuple.stderr b/src/test/ui/parser/recover-tuple.stderr
new file mode 100644
index 0000000..4252fc1fd
--- /dev/null
+++ b/src/test/ui/parser/recover-tuple.stderr
@@ -0,0 +1,18 @@
+error: expected expression, found `.`
+  --> $DIR/recover-tuple.rs:3:40
+   |
+LL |     let x: (usize, usize, usize) = (3, .=.);
+   |                                        ^ expected expression
+
+error[E0308]: mismatched types
+  --> $DIR/recover-tuple.rs:6:20
+   |
+LL |     let y: usize = "";
+   |                    ^^ expected usize, found reference
+   |
+   = note: expected type `usize`
+              found type `&'static str`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/parser/recovered-struct-variant.rs b/src/test/ui/parser/recovered-struct-variant.rs
new file mode 100644
index 0000000..5b195dc
--- /dev/null
+++ b/src/test/ui/parser/recovered-struct-variant.rs
@@ -0,0 +1,13 @@
+enum Foo {
+    A { a, b: usize }
+    //~^ ERROR expected `:`, found `,`
+}
+
+fn main() {
+    // no complaints about non-existing fields
+    let f = Foo::A { a:3, b: 4};
+    match f {
+        // no complaints about non-existing fields
+        Foo::A {a, b} => {}
+    }
+}
diff --git a/src/test/ui/parser/recovered-struct-variant.stderr b/src/test/ui/parser/recovered-struct-variant.stderr
new file mode 100644
index 0000000..51aaf8b
--- /dev/null
+++ b/src/test/ui/parser/recovered-struct-variant.stderr
@@ -0,0 +1,8 @@
+error: expected `:`, found `,`
+  --> $DIR/recovered-struct-variant.rs:2:10
+   |
+LL |     A { a, b: usize }
+   |          ^ expected `:`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/regions-out-of-scope-slice.rs b/src/test/ui/parser/regions-out-of-scope-slice.rs
new file mode 100644
index 0000000..21369d0
--- /dev/null
+++ b/src/test/ui/parser/regions-out-of-scope-slice.rs
@@ -0,0 +1,11 @@
+// This basically tests the parser's recovery on `'blk` in the wrong place.
+
+fn foo(cond: bool) {
+    let mut x;
+
+    if cond {
+        x = &'blk [1,2,3]; //~ ERROR expected `:`, found `[`
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/regions-out-of-scope-slice.stderr b/src/test/ui/parser/regions-out-of-scope-slice.stderr
new file mode 100644
index 0000000..8d9bf0b
--- /dev/null
+++ b/src/test/ui/parser/regions-out-of-scope-slice.stderr
@@ -0,0 +1,8 @@
+error: expected `:`, found `[`
+  --> $DIR/regions-out-of-scope-slice.rs:7:19
+   |
+LL |         x = &'blk [1,2,3];
+   |                   ^ expected `:`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/removed-syntax-closure-lifetime.rs b/src/test/ui/parser/removed-syntax-closure-lifetime.rs
new file mode 100644
index 0000000..ceac940
--- /dev/null
+++ b/src/test/ui/parser/removed-syntax-closure-lifetime.rs
@@ -0,0 +1,2 @@
+type closure = Box<lt/fn()>;
+//~^ ERROR expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `/`
diff --git a/src/test/ui/parser/removed-syntax-closure-lifetime.stderr b/src/test/ui/parser/removed-syntax-closure-lifetime.stderr
new file mode 100644
index 0000000..f52988c
--- /dev/null
+++ b/src/test/ui/parser/removed-syntax-closure-lifetime.stderr
@@ -0,0 +1,8 @@
+error: expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `/`
+  --> $DIR/removed-syntax-closure-lifetime.rs:1:22
+   |
+LL | type closure = Box<lt/fn()>;
+   |                      ^ expected one of 7 possible tokens here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/removed-syntax-enum-newtype.rs b/src/test/ui/parser/removed-syntax-enum-newtype.rs
new file mode 100644
index 0000000..518f90b
--- /dev/null
+++ b/src/test/ui/parser/removed-syntax-enum-newtype.rs
@@ -0,0 +1 @@
+enum e = isize; //~ ERROR expected one of `<`, `where`, or `{`, found `=`
diff --git a/src/test/ui/parser/removed-syntax-enum-newtype.stderr b/src/test/ui/parser/removed-syntax-enum-newtype.stderr
new file mode 100644
index 0000000..a6d0ff4
--- /dev/null
+++ b/src/test/ui/parser/removed-syntax-enum-newtype.stderr
@@ -0,0 +1,8 @@
+error: expected one of `<`, `where`, or `{`, found `=`
+  --> $DIR/removed-syntax-enum-newtype.rs:1:8
+   |
+LL | enum e = isize;
+   |        ^ expected one of `<`, `where`, or `{` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/removed-syntax-extern-const.rs b/src/test/ui/parser/removed-syntax-extern-const.rs
new file mode 100644
index 0000000..71c22e6
--- /dev/null
+++ b/src/test/ui/parser/removed-syntax-extern-const.rs
@@ -0,0 +1,6 @@
+extern {
+    const i: isize;
+    //~^ ERROR extern items cannot be `const`
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/removed-syntax-extern-const.stderr b/src/test/ui/parser/removed-syntax-extern-const.stderr
new file mode 100644
index 0000000..2bccbd9
--- /dev/null
+++ b/src/test/ui/parser/removed-syntax-extern-const.stderr
@@ -0,0 +1,8 @@
+error: extern items cannot be `const`
+  --> $DIR/removed-syntax-extern-const.rs:2:5
+   |
+LL |     const i: isize;
+   |     ^^^^^ help: try using a static value: `static`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/removed-syntax-field-let.rs b/src/test/ui/parser/removed-syntax-field-let.rs
new file mode 100644
index 0000000..3412788
--- /dev/null
+++ b/src/test/ui/parser/removed-syntax-field-let.rs
@@ -0,0 +1,9 @@
+// compile-flags: -Z continue-parse-after-error
+
+struct S {
+    let foo: (),
+    //~^  ERROR expected identifier, found keyword `let`
+    //~^^ ERROR expected `:`, found `foo`
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/removed-syntax-field-let.stderr b/src/test/ui/parser/removed-syntax-field-let.stderr
new file mode 100644
index 0000000..0d489be
--- /dev/null
+++ b/src/test/ui/parser/removed-syntax-field-let.stderr
@@ -0,0 +1,18 @@
+error: expected identifier, found keyword `let`
+  --> $DIR/removed-syntax-field-let.rs:4:5
+   |
+LL |     let foo: (),
+   |     ^^^ expected identifier, found keyword
+help: you can escape reserved keywords to use them as identifiers
+   |
+LL |     r#let foo: (),
+   |     ^^^^^
+
+error: expected `:`, found `foo`
+  --> $DIR/removed-syntax-field-let.rs:4:9
+   |
+LL |     let foo: (),
+   |         ^^^ expected `:`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/parser/removed-syntax-field-semicolon.rs b/src/test/ui/parser/removed-syntax-field-semicolon.rs
new file mode 100644
index 0000000..ac28e21
--- /dev/null
+++ b/src/test/ui/parser/removed-syntax-field-semicolon.rs
@@ -0,0 +1,6 @@
+struct S {
+    bar: ();
+    //~^ ERROR expected `,`, or `}`, found `;`
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/removed-syntax-field-semicolon.stderr b/src/test/ui/parser/removed-syntax-field-semicolon.stderr
new file mode 100644
index 0000000..fbefeb2
--- /dev/null
+++ b/src/test/ui/parser/removed-syntax-field-semicolon.stderr
@@ -0,0 +1,8 @@
+error: expected `,`, or `}`, found `;`
+  --> $DIR/removed-syntax-field-semicolon.rs:2:12
+   |
+LL |     bar: ();
+   |            ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/removed-syntax-fixed-vec.rs b/src/test/ui/parser/removed-syntax-fixed-vec.rs
new file mode 100644
index 0000000..560efec
--- /dev/null
+++ b/src/test/ui/parser/removed-syntax-fixed-vec.rs
@@ -0,0 +1 @@
+type v = [isize * 3]; //~ ERROR expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `]`, found `*`
diff --git a/src/test/ui/parser/removed-syntax-fixed-vec.stderr b/src/test/ui/parser/removed-syntax-fixed-vec.stderr
new file mode 100644
index 0000000..ca6969d
--- /dev/null
+++ b/src/test/ui/parser/removed-syntax-fixed-vec.stderr
@@ -0,0 +1,8 @@
+error: expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `]`, found `*`
+  --> $DIR/removed-syntax-fixed-vec.rs:1:17
+   |
+LL | type v = [isize * 3];
+   |                 ^ expected one of 7 possible tokens here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/removed-syntax-fn-sigil.rs b/src/test/ui/parser/removed-syntax-fn-sigil.rs
new file mode 100644
index 0000000..7258434
--- /dev/null
+++ b/src/test/ui/parser/removed-syntax-fn-sigil.rs
@@ -0,0 +1,3 @@
+fn main() {
+    let x: fn~() = || (); //~ ERROR expected `(`, found `~`
+}
diff --git a/src/test/ui/parser/removed-syntax-fn-sigil.stderr b/src/test/ui/parser/removed-syntax-fn-sigil.stderr
new file mode 100644
index 0000000..196a5af
--- /dev/null
+++ b/src/test/ui/parser/removed-syntax-fn-sigil.stderr
@@ -0,0 +1,10 @@
+error: expected `(`, found `~`
+  --> $DIR/removed-syntax-fn-sigil.rs:2:14
+   |
+LL |     let x: fn~() = || ();
+   |         -    ^ expected `(`
+   |         |
+   |         while parsing the type for `x`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/removed-syntax-mode.rs b/src/test/ui/parser/removed-syntax-mode.rs
new file mode 100644
index 0000000..23851b5
--- /dev/null
+++ b/src/test/ui/parser/removed-syntax-mode.rs
@@ -0,0 +1,4 @@
+fn f(+x: isize) {}
+//~^ ERROR expected argument name, found `+`
+
+fn main() {}
diff --git a/src/test/ui/parser/removed-syntax-mode.stderr b/src/test/ui/parser/removed-syntax-mode.stderr
new file mode 100644
index 0000000..5e7139d
--- /dev/null
+++ b/src/test/ui/parser/removed-syntax-mode.stderr
@@ -0,0 +1,8 @@
+error: expected argument name, found `+`
+  --> $DIR/removed-syntax-mode.rs:1:6
+   |
+LL | fn f(+x: isize) {}
+   |      ^ expected argument name
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/removed-syntax-mut-vec-expr.rs b/src/test/ui/parser/removed-syntax-mut-vec-expr.rs
new file mode 100644
index 0000000..2ee95db
--- /dev/null
+++ b/src/test/ui/parser/removed-syntax-mut-vec-expr.rs
@@ -0,0 +1,3 @@
+fn main() {
+    let v = [mut 1, 2, 3, 4]; //~ ERROR expected expression, found keyword `mut`
+}
diff --git a/src/test/ui/parser/removed-syntax-mut-vec-expr.stderr b/src/test/ui/parser/removed-syntax-mut-vec-expr.stderr
new file mode 100644
index 0000000..313420f
--- /dev/null
+++ b/src/test/ui/parser/removed-syntax-mut-vec-expr.stderr
@@ -0,0 +1,8 @@
+error: expected expression, found keyword `mut`
+  --> $DIR/removed-syntax-mut-vec-expr.rs:2:14
+   |
+LL |     let v = [mut 1, 2, 3, 4];
+   |              ^^^ expected expression
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/removed-syntax-mut-vec-ty.rs b/src/test/ui/parser/removed-syntax-mut-vec-ty.rs
new file mode 100644
index 0000000..923a7ea
--- /dev/null
+++ b/src/test/ui/parser/removed-syntax-mut-vec-ty.rs
@@ -0,0 +1 @@
+type v = [mut isize]; //~ ERROR expected type, found keyword `mut`
diff --git a/src/test/ui/parser/removed-syntax-mut-vec-ty.stderr b/src/test/ui/parser/removed-syntax-mut-vec-ty.stderr
new file mode 100644
index 0000000..a759716
--- /dev/null
+++ b/src/test/ui/parser/removed-syntax-mut-vec-ty.stderr
@@ -0,0 +1,8 @@
+error: expected type, found keyword `mut`
+  --> $DIR/removed-syntax-mut-vec-ty.rs:1:11
+   |
+LL | type v = [mut isize];
+   |           ^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/removed-syntax-ptr-lifetime.rs b/src/test/ui/parser/removed-syntax-ptr-lifetime.rs
new file mode 100644
index 0000000..5b551ad
--- /dev/null
+++ b/src/test/ui/parser/removed-syntax-ptr-lifetime.rs
@@ -0,0 +1 @@
+type bptr = &lifetime/isize; //~ ERROR expected one of `!`, `(`, `::`, `;`, or `<`, found `/`
diff --git a/src/test/ui/parser/removed-syntax-ptr-lifetime.stderr b/src/test/ui/parser/removed-syntax-ptr-lifetime.stderr
new file mode 100644
index 0000000..7beef98
--- /dev/null
+++ b/src/test/ui/parser/removed-syntax-ptr-lifetime.stderr
@@ -0,0 +1,8 @@
+error: expected one of `!`, `(`, `::`, `;`, or `<`, found `/`
+  --> $DIR/removed-syntax-ptr-lifetime.rs:1:22
+   |
+LL | type bptr = &lifetime/isize;
+   |                      ^ expected one of `!`, `(`, `::`, `;`, or `<` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/removed-syntax-record.rs b/src/test/ui/parser/removed-syntax-record.rs
new file mode 100644
index 0000000..d1d91c8
--- /dev/null
+++ b/src/test/ui/parser/removed-syntax-record.rs
@@ -0,0 +1 @@
+type t = { f: () }; //~ ERROR expected type, found `{`
diff --git a/src/test/ui/parser/removed-syntax-record.stderr b/src/test/ui/parser/removed-syntax-record.stderr
new file mode 100644
index 0000000..730d5e2
--- /dev/null
+++ b/src/test/ui/parser/removed-syntax-record.stderr
@@ -0,0 +1,8 @@
+error: expected type, found `{`
+  --> $DIR/removed-syntax-record.rs:1:10
+   |
+LL | type t = { f: () };
+   |          ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/removed-syntax-static-fn.rs b/src/test/ui/parser/removed-syntax-static-fn.rs
new file mode 100644
index 0000000..df39641
--- /dev/null
+++ b/src/test/ui/parser/removed-syntax-static-fn.rs
@@ -0,0 +1,10 @@
+// ignore-tidy-linelength
+
+struct S;
+
+impl S {
+    static fn f() {}
+}
+//~^^ ERROR expected one of `async`, `const`, `crate`, `default`, `existential`, `extern`, `fn`, `pub`, `type`,
+
+fn main() {}
diff --git a/src/test/ui/parser/removed-syntax-static-fn.stderr b/src/test/ui/parser/removed-syntax-static-fn.stderr
new file mode 100644
index 0000000..84e0432
--- /dev/null
+++ b/src/test/ui/parser/removed-syntax-static-fn.stderr
@@ -0,0 +1,10 @@
+error: expected one of `async`, `const`, `crate`, `default`, `existential`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found `static`
+  --> $DIR/removed-syntax-static-fn.rs:6:5
+   |
+LL | impl S {
+   |         - expected one of 11 possible tokens here
+LL |     static fn f() {}
+   |     ^^^^^^ unexpected token
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/removed-syntax-uniq-mut-expr.rs b/src/test/ui/parser/removed-syntax-uniq-mut-expr.rs
new file mode 100644
index 0000000..08ef4b4
--- /dev/null
+++ b/src/test/ui/parser/removed-syntax-uniq-mut-expr.rs
@@ -0,0 +1,3 @@
+fn main() {
+    let a_box = box mut 42; //~ ERROR expected expression, found keyword `mut`
+}
diff --git a/src/test/ui/parser/removed-syntax-uniq-mut-expr.stderr b/src/test/ui/parser/removed-syntax-uniq-mut-expr.stderr
new file mode 100644
index 0000000..63d2fdb
--- /dev/null
+++ b/src/test/ui/parser/removed-syntax-uniq-mut-expr.stderr
@@ -0,0 +1,8 @@
+error: expected expression, found keyword `mut`
+  --> $DIR/removed-syntax-uniq-mut-expr.rs:2:21
+   |
+LL |     let a_box = box mut 42;
+   |                     ^^^ expected expression
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/removed-syntax-uniq-mut-ty.rs b/src/test/ui/parser/removed-syntax-uniq-mut-ty.rs
new file mode 100644
index 0000000..79d51f5
--- /dev/null
+++ b/src/test/ui/parser/removed-syntax-uniq-mut-ty.rs
@@ -0,0 +1 @@
+type mut_box = Box<mut isize>; //~ ERROR expected one of `>`, const, lifetime, or type, found `mut`
diff --git a/src/test/ui/parser/removed-syntax-uniq-mut-ty.stderr b/src/test/ui/parser/removed-syntax-uniq-mut-ty.stderr
new file mode 100644
index 0000000..b6c5749
--- /dev/null
+++ b/src/test/ui/parser/removed-syntax-uniq-mut-ty.stderr
@@ -0,0 +1,8 @@
+error: expected one of `>`, const, lifetime, or type, found `mut`
+  --> $DIR/removed-syntax-uniq-mut-ty.rs:1:20
+   |
+LL | type mut_box = Box<mut isize>;
+   |                    ^^^ expected one of `>`, const, lifetime, or type here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/removed-syntax-with-1.rs b/src/test/ui/parser/removed-syntax-with-1.rs
new file mode 100644
index 0000000..2c1e152
--- /dev/null
+++ b/src/test/ui/parser/removed-syntax-with-1.rs
@@ -0,0 +1,10 @@
+fn main() {
+    struct S {
+        foo: (),
+        bar: (),
+    }
+
+    let a = S { foo: (), bar: () };
+    let b = S { foo: () with a, bar: () };
+    //~^ ERROR expected one of `,`, `.`, `?`, `}`, or an operator, found `with`
+}
diff --git a/src/test/ui/parser/removed-syntax-with-1.stderr b/src/test/ui/parser/removed-syntax-with-1.stderr
new file mode 100644
index 0000000..a157873
--- /dev/null
+++ b/src/test/ui/parser/removed-syntax-with-1.stderr
@@ -0,0 +1,10 @@
+error: expected one of `,`, `.`, `?`, `}`, or an operator, found `with`
+  --> $DIR/removed-syntax-with-1.rs:8:25
+   |
+LL |     let b = S { foo: () with a, bar: () };
+   |             -           ^^^^ expected one of `,`, `.`, `?`, `}`, or an operator here
+   |             |
+   |             while parsing this struct
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/removed-syntax-with-2.rs b/src/test/ui/parser/removed-syntax-with-2.rs
new file mode 100644
index 0000000..f666da4
--- /dev/null
+++ b/src/test/ui/parser/removed-syntax-with-2.rs
@@ -0,0 +1,11 @@
+fn main() {
+    struct S {
+        foo: (),
+        bar: (),
+    }
+
+    let a = S { foo: (), bar: () };
+    let b = S { foo: (), with a };
+    //~^ ERROR expected one of `,` or `}`, found `a`
+    //~| ERROR missing field `bar` in initializer of `main::S`
+}
diff --git a/src/test/ui/parser/removed-syntax-with-2.stderr b/src/test/ui/parser/removed-syntax-with-2.stderr
new file mode 100644
index 0000000..7717b49
--- /dev/null
+++ b/src/test/ui/parser/removed-syntax-with-2.stderr
@@ -0,0 +1,17 @@
+error: expected one of `,` or `}`, found `a`
+  --> $DIR/removed-syntax-with-2.rs:8:31
+   |
+LL |     let b = S { foo: (), with a };
+   |             -                 ^ expected one of `,` or `}` here
+   |             |
+   |             while parsing this struct
+
+error[E0063]: missing field `bar` in initializer of `main::S`
+  --> $DIR/removed-syntax-with-2.rs:8:13
+   |
+LL |     let b = S { foo: (), with a };
+   |             ^ missing `bar`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0063`.
diff --git a/src/test/ui/parser/require-parens-for-chained-comparison.rs b/src/test/ui/parser/require-parens-for-chained-comparison.rs
new file mode 100644
index 0000000..525be5d
--- /dev/null
+++ b/src/test/ui/parser/require-parens-for-chained-comparison.rs
@@ -0,0 +1,18 @@
+fn f<T>() {}
+struct X;
+
+fn main() {
+    false == false == false;
+    //~^ ERROR: chained comparison operators require parentheses
+
+    false == 0 < 2;
+    //~^ ERROR: chained comparison operators require parentheses
+    //~| ERROR: mismatched types
+    //~| ERROR: mismatched types
+
+    f<X>();
+    //~^ ERROR: chained comparison operators require parentheses
+    //~| ERROR: binary operation `<` cannot be applied to type `fn() {f::<_>}`
+    //~| HELP: use `::<...>` instead of `<...>`
+    //~| HELP: or use `(...)`
+}
diff --git a/src/test/ui/parser/require-parens-for-chained-comparison.stderr b/src/test/ui/parser/require-parens-for-chained-comparison.stderr
new file mode 100644
index 0000000..8899b0d
--- /dev/null
+++ b/src/test/ui/parser/require-parens-for-chained-comparison.stderr
@@ -0,0 +1,53 @@
+error: chained comparison operators require parentheses
+  --> $DIR/require-parens-for-chained-comparison.rs:5:11
+   |
+LL |     false == false == false;
+   |           ^^^^^^^^^^^^^^^^^
+
+error: chained comparison operators require parentheses
+  --> $DIR/require-parens-for-chained-comparison.rs:8:11
+   |
+LL |     false == 0 < 2;
+   |           ^^^^^^^^
+
+error: chained comparison operators require parentheses
+  --> $DIR/require-parens-for-chained-comparison.rs:13:6
+   |
+LL |     f<X>();
+   |      ^^^^
+   |
+   = help: use `::<...>` instead of `<...>` if you meant to specify type arguments
+   = help: or use `(...)` if you meant to specify fn arguments
+
+error[E0308]: mismatched types
+  --> $DIR/require-parens-for-chained-comparison.rs:8:14
+   |
+LL |     false == 0 < 2;
+   |              ^ expected bool, found integer
+   |
+   = note: expected type `bool`
+              found type `{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/require-parens-for-chained-comparison.rs:8:18
+   |
+LL |     false == 0 < 2;
+   |                  ^ expected bool, found integer
+   |
+   = note: expected type `bool`
+              found type `{integer}`
+
+error[E0369]: binary operation `<` cannot be applied to type `fn() {f::<_>}`
+  --> $DIR/require-parens-for-chained-comparison.rs:13:6
+   |
+LL |     f<X>();
+   |     -^- X
+   |     |
+   |     fn() {f::<_>}
+   |
+   = note: an implementation of `std::cmp::PartialOrd` might be missing for `fn() {f::<_>}`
+
+error: aborting due to 6 previous errors
+
+Some errors occurred: E0308, E0369.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/parser/struct-field-numeric-shorthand.rs b/src/test/ui/parser/struct-field-numeric-shorthand.rs
new file mode 100644
index 0000000..58c40b3
--- /dev/null
+++ b/src/test/ui/parser/struct-field-numeric-shorthand.rs
@@ -0,0 +1,9 @@
+struct Rgb(u8, u8, u8);
+
+fn main() {
+    let _ = Rgb { 0, 1, 2 };
+    //~^ ERROR expected identifier, found `0`
+    //~| ERROR expected identifier, found `1`
+    //~| ERROR expected identifier, found `2`
+    //~| ERROR missing fields `0`, `1`, `2` in initializer of `Rgb`
+}
diff --git a/src/test/ui/parser/struct-field-numeric-shorthand.stderr b/src/test/ui/parser/struct-field-numeric-shorthand.stderr
new file mode 100644
index 0000000..cfb1f82
--- /dev/null
+++ b/src/test/ui/parser/struct-field-numeric-shorthand.stderr
@@ -0,0 +1,33 @@
+error: expected identifier, found `0`
+  --> $DIR/struct-field-numeric-shorthand.rs:4:19
+   |
+LL |     let _ = Rgb { 0, 1, 2 };
+   |             ---   ^ expected identifier
+   |             |
+   |             while parsing this struct
+
+error: expected identifier, found `1`
+  --> $DIR/struct-field-numeric-shorthand.rs:4:22
+   |
+LL |     let _ = Rgb { 0, 1, 2 };
+   |             ---      ^ expected identifier
+   |             |
+   |             while parsing this struct
+
+error: expected identifier, found `2`
+  --> $DIR/struct-field-numeric-shorthand.rs:4:25
+   |
+LL |     let _ = Rgb { 0, 1, 2 };
+   |             ---         ^ expected identifier
+   |             |
+   |             while parsing this struct
+
+error[E0063]: missing fields `0`, `1`, `2` in initializer of `Rgb`
+  --> $DIR/struct-field-numeric-shorthand.rs:4:13
+   |
+LL |     let _ = Rgb { 0, 1, 2 };
+   |             ^^^ missing `0`, `1`, `2`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0063`.
diff --git a/src/test/ui/parser/struct-literal-in-for.rs b/src/test/ui/parser/struct-literal-in-for.rs
new file mode 100644
index 0000000..526b5e7
--- /dev/null
+++ b/src/test/ui/parser/struct-literal-in-for.rs
@@ -0,0 +1,17 @@
+struct Foo {
+    x: isize,
+}
+
+impl Foo {
+    fn hi(&self) -> bool {
+        true
+    }
+}
+
+fn main() {
+    for x in Foo { //~ ERROR expected value, found struct `Foo`
+        x: 3    //~ ERROR expected type, found `3`
+    }.hi() { //~ ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `{`
+        println!("yo");
+    }
+}
diff --git a/src/test/ui/parser/struct-literal-in-for.stderr b/src/test/ui/parser/struct-literal-in-for.stderr
new file mode 100644
index 0000000..07f2e41
--- /dev/null
+++ b/src/test/ui/parser/struct-literal-in-for.stderr
@@ -0,0 +1,29 @@
+error: expected type, found `3`
+  --> $DIR/struct-literal-in-for.rs:13:12
+   |
+LL |         x: 3
+   |            ^ expecting a type here because of type ascription
+   |
+   = note: type ascription is a nightly-only feature that lets you annotate an expression with a type: `<expr>: <type>`
+note: this expression expects an ascribed type after the colon
+  --> $DIR/struct-literal-in-for.rs:13:9
+   |
+LL |         x: 3
+   |         ^
+   = help: this might be indicative of a syntax error elsewhere
+
+error: expected one of `.`, `;`, `?`, `}`, or an operator, found `{`
+  --> $DIR/struct-literal-in-for.rs:14:12
+   |
+LL |     }.hi() {
+   |            ^ expected one of `.`, `;`, `?`, `}`, or an operator here
+
+error[E0423]: expected value, found struct `Foo`
+  --> $DIR/struct-literal-in-for.rs:12:14
+   |
+LL |     for x in Foo {
+   |              ^^^ did you mean `(Foo { /* fields */ })`?
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0423`.
diff --git a/src/test/ui/parser/struct-literal-in-if.rs b/src/test/ui/parser/struct-literal-in-if.rs
new file mode 100644
index 0000000..362a71c
--- /dev/null
+++ b/src/test/ui/parser/struct-literal-in-if.rs
@@ -0,0 +1,17 @@
+struct Foo {
+    x: isize,
+}
+
+impl Foo {
+    fn hi(&self) -> bool {
+        true
+    }
+}
+
+fn main() {
+    if Foo { //~ ERROR expected value, found struct `Foo`
+        x: 3    //~ ERROR expected type, found `3`
+    }.hi() { //~ ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `{`
+        println!("yo");
+    }
+}
diff --git a/src/test/ui/parser/struct-literal-in-if.stderr b/src/test/ui/parser/struct-literal-in-if.stderr
new file mode 100644
index 0000000..3dd61e7
--- /dev/null
+++ b/src/test/ui/parser/struct-literal-in-if.stderr
@@ -0,0 +1,29 @@
+error: expected type, found `3`
+  --> $DIR/struct-literal-in-if.rs:13:12
+   |
+LL |         x: 3
+   |            ^ expecting a type here because of type ascription
+   |
+   = note: type ascription is a nightly-only feature that lets you annotate an expression with a type: `<expr>: <type>`
+note: this expression expects an ascribed type after the colon
+  --> $DIR/struct-literal-in-if.rs:13:9
+   |
+LL |         x: 3
+   |         ^
+   = help: this might be indicative of a syntax error elsewhere
+
+error: expected one of `.`, `;`, `?`, `}`, or an operator, found `{`
+  --> $DIR/struct-literal-in-if.rs:14:12
+   |
+LL |     }.hi() {
+   |            ^ expected one of `.`, `;`, `?`, `}`, or an operator here
+
+error[E0423]: expected value, found struct `Foo`
+  --> $DIR/struct-literal-in-if.rs:12:8
+   |
+LL |     if Foo {
+   |        ^^^ did you mean `(Foo { /* fields */ })`?
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0423`.
diff --git a/src/test/ui/parser/struct-literal-in-match-discriminant.rs b/src/test/ui/parser/struct-literal-in-match-discriminant.rs
new file mode 100644
index 0000000..35a1109
--- /dev/null
+++ b/src/test/ui/parser/struct-literal-in-match-discriminant.rs
@@ -0,0 +1,13 @@
+struct Foo {
+    x: isize,
+}
+
+fn main() {
+    match Foo { //~ ERROR expected value, found struct `Foo`
+        x: 3    //~ ERROR expected one of `=>`, `@`, `if`, or `|`, found `:`
+    } {
+        Foo { //~ ERROR mismatched types
+            x: x //~ ERROR cannot find value `x` in this scope
+        } => {} //~ ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `=>`
+    }
+}
diff --git a/src/test/ui/parser/struct-literal-in-match-discriminant.stderr b/src/test/ui/parser/struct-literal-in-match-discriminant.stderr
new file mode 100644
index 0000000..94a758e
--- /dev/null
+++ b/src/test/ui/parser/struct-literal-in-match-discriminant.stderr
@@ -0,0 +1,42 @@
+error: expected one of `=>`, `@`, `if`, or `|`, found `:`
+  --> $DIR/struct-literal-in-match-discriminant.rs:7:10
+   |
+LL |         x: 3
+   |          ^ expected one of `=>`, `@`, `if`, or `|` here
+
+error: expected one of `.`, `;`, `?`, `}`, or an operator, found `=>`
+  --> $DIR/struct-literal-in-match-discriminant.rs:11:11
+   |
+LL |         } => {}
+   |           ^^ expected one of `.`, `;`, `?`, `}`, or an operator here
+
+error[E0423]: expected value, found struct `Foo`
+  --> $DIR/struct-literal-in-match-discriminant.rs:6:11
+   |
+LL |     match Foo {
+   |           ^^^ did you mean `(Foo { /* fields */ })`?
+
+error[E0425]: cannot find value `x` in this scope
+  --> $DIR/struct-literal-in-match-discriminant.rs:10:16
+   |
+LL |             x: x
+   |                ^ not found in this scope
+
+error[E0308]: mismatched types
+  --> $DIR/struct-literal-in-match-discriminant.rs:9:9
+   |
+LL |   fn main() {
+   |             - expected `()` because of default return type
+...
+LL | /         Foo {
+LL | |             x: x
+LL | |         } => {}
+   | |_________^ expected (), found struct `Foo`
+   |
+   = note: expected type `()`
+              found type `Foo`
+
+error: aborting due to 5 previous errors
+
+Some errors occurred: E0308, E0423, E0425.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/parser/struct-literal-in-while.rs b/src/test/ui/parser/struct-literal-in-while.rs
new file mode 100644
index 0000000..561cdce
--- /dev/null
+++ b/src/test/ui/parser/struct-literal-in-while.rs
@@ -0,0 +1,18 @@
+struct Foo {
+    x: isize,
+}
+
+impl Foo {
+    fn hi(&self) -> bool {
+        true
+    }
+}
+
+fn main() {
+    while Foo { //~ ERROR expected value, found struct `Foo`
+        x: 3    //~ ERROR expected type, found `3`
+    }.hi() { //~ ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `{`
+             //~| ERROR no method named `hi` found for type `()` in the current scope
+        println!("yo");
+    }
+}
diff --git a/src/test/ui/parser/struct-literal-in-while.stderr b/src/test/ui/parser/struct-literal-in-while.stderr
new file mode 100644
index 0000000..d482446
--- /dev/null
+++ b/src/test/ui/parser/struct-literal-in-while.stderr
@@ -0,0 +1,36 @@
+error: expected type, found `3`
+  --> $DIR/struct-literal-in-while.rs:13:12
+   |
+LL |         x: 3
+   |            ^ expecting a type here because of type ascription
+   |
+   = note: type ascription is a nightly-only feature that lets you annotate an expression with a type: `<expr>: <type>`
+note: this expression expects an ascribed type after the colon
+  --> $DIR/struct-literal-in-while.rs:13:9
+   |
+LL |         x: 3
+   |         ^
+   = help: this might be indicative of a syntax error elsewhere
+
+error: expected one of `.`, `;`, `?`, `}`, or an operator, found `{`
+  --> $DIR/struct-literal-in-while.rs:14:12
+   |
+LL |     }.hi() {
+   |            ^ expected one of `.`, `;`, `?`, `}`, or an operator here
+
+error[E0423]: expected value, found struct `Foo`
+  --> $DIR/struct-literal-in-while.rs:12:11
+   |
+LL |     while Foo {
+   |           ^^^ did you mean `(Foo { /* fields */ })`?
+
+error[E0599]: no method named `hi` found for type `()` in the current scope
+  --> $DIR/struct-literal-in-while.rs:14:7
+   |
+LL |     }.hi() {
+   |       ^^
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0423, E0599.
+For more information about an error, try `rustc --explain E0423`.
diff --git a/src/test/ui/parser/struct-literal-restrictions-in-lamda.rs b/src/test/ui/parser/struct-literal-restrictions-in-lamda.rs
new file mode 100644
index 0000000..e504908
--- /dev/null
+++ b/src/test/ui/parser/struct-literal-restrictions-in-lamda.rs
@@ -0,0 +1,18 @@
+struct Foo {
+    x: isize,
+}
+
+impl Foo {
+    fn hi(&self) -> bool {
+        true
+    }
+}
+
+fn main() {
+    while || Foo { //~ ERROR expected value, found struct `Foo`
+        x: 3    //~ ERROR expected type, found `3`
+    }.hi() { //~ ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `{`
+             //~| ERROR no method named `hi` found for type `()` in the current scope
+        println!("yo");
+    }
+}
diff --git a/src/test/ui/parser/struct-literal-restrictions-in-lamda.stderr b/src/test/ui/parser/struct-literal-restrictions-in-lamda.stderr
new file mode 100644
index 0000000..a8c9323
--- /dev/null
+++ b/src/test/ui/parser/struct-literal-restrictions-in-lamda.stderr
@@ -0,0 +1,36 @@
+error: expected type, found `3`
+  --> $DIR/struct-literal-restrictions-in-lamda.rs:13:12
+   |
+LL |         x: 3
+   |            ^ expecting a type here because of type ascription
+   |
+   = note: type ascription is a nightly-only feature that lets you annotate an expression with a type: `<expr>: <type>`
+note: this expression expects an ascribed type after the colon
+  --> $DIR/struct-literal-restrictions-in-lamda.rs:13:9
+   |
+LL |         x: 3
+   |         ^
+   = help: this might be indicative of a syntax error elsewhere
+
+error: expected one of `.`, `;`, `?`, `}`, or an operator, found `{`
+  --> $DIR/struct-literal-restrictions-in-lamda.rs:14:12
+   |
+LL |     }.hi() {
+   |            ^ expected one of `.`, `;`, `?`, `}`, or an operator here
+
+error[E0423]: expected value, found struct `Foo`
+  --> $DIR/struct-literal-restrictions-in-lamda.rs:12:14
+   |
+LL |     while || Foo {
+   |              ^^^ did you mean `(Foo { /* fields */ })`?
+
+error[E0599]: no method named `hi` found for type `()` in the current scope
+  --> $DIR/struct-literal-restrictions-in-lamda.rs:14:7
+   |
+LL |     }.hi() {
+   |       ^^
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0423, E0599.
+For more information about an error, try `rustc --explain E0423`.
diff --git a/src/test/ui/parser/tag-variant-disr-non-nullary.rs b/src/test/ui/parser/tag-variant-disr-non-nullary.rs
new file mode 100644
index 0000000..83a3b72
--- /dev/null
+++ b/src/test/ui/parser/tag-variant-disr-non-nullary.rs
@@ -0,0 +1,11 @@
+enum Color {
+    Red = 0xff0000,
+    //~^ ERROR discriminator values can only be used with a field-less enum
+    Green = 0x00ff00,
+    Blue = 0x0000ff,
+    Black = 0x000000,
+    White = 0xffffff,
+    Other(usize),
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/tag-variant-disr-non-nullary.stderr b/src/test/ui/parser/tag-variant-disr-non-nullary.stderr
new file mode 100644
index 0000000..884e967
--- /dev/null
+++ b/src/test/ui/parser/tag-variant-disr-non-nullary.stderr
@@ -0,0 +1,17 @@
+error: discriminator values can only be used with a field-less enum
+  --> $DIR/tag-variant-disr-non-nullary.rs:2:11
+   |
+LL |     Red = 0xff0000,
+   |           ^^^^^^^^ only valid in field-less enums
+LL |
+LL |     Green = 0x00ff00,
+   |             ^^^^^^^^ only valid in field-less enums
+LL |     Blue = 0x0000ff,
+   |            ^^^^^^^^ only valid in field-less enums
+LL |     Black = 0x000000,
+   |             ^^^^^^^^ only valid in field-less enums
+LL |     White = 0xffffff,
+   |             ^^^^^^^^ only valid in field-less enums
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/trailing-carriage-return-in-string.rs b/src/test/ui/parser/trailing-carriage-return-in-string.rs
new file mode 100644
index 0000000..8abf262
--- /dev/null
+++ b/src/test/ui/parser/trailing-carriage-return-in-string.rs
Binary files differ
diff --git a/src/test/ui/parser/trailing-carriage-return-in-string.stderr b/src/test/ui/parser/trailing-carriage-return-in-string.stderr
new file mode 100644
index 0000000..3687b9d
--- /dev/null
+++ b/src/test/ui/parser/trailing-carriage-return-in-string.stderr
Binary files differ
diff --git a/src/test/ui/parser/trailing-plus-in-bounds.rs b/src/test/ui/parser/trailing-plus-in-bounds.rs
new file mode 100644
index 0000000..153f942
--- /dev/null
+++ b/src/test/ui/parser/trailing-plus-in-bounds.rs
@@ -0,0 +1,10 @@
+// compile-pass
+// compile-flags: -Z continue-parse-after-error
+
+#![feature(box_syntax)]
+
+use std::fmt::Debug;
+
+fn main() {
+    let x: Box<Debug+> = box 3 as Box<Debug+>; // Trailing `+` is OK
+}
diff --git a/src/test/ui/parser/trait-bounds-not-on-impl.rs b/src/test/ui/parser/trait-bounds-not-on-impl.rs
new file mode 100644
index 0000000..d77ff80
--- /dev/null
+++ b/src/test/ui/parser/trait-bounds-not-on-impl.rs
@@ -0,0 +1,11 @@
+// compile-flags: -Z continue-parse-after-error
+
+trait Foo {
+}
+
+struct Bar;
+
+impl Foo + Owned for Bar { //~ ERROR expected a trait, found type
+}
+
+fn main() { }
diff --git a/src/test/ui/parser/trait-bounds-not-on-impl.stderr b/src/test/ui/parser/trait-bounds-not-on-impl.stderr
new file mode 100644
index 0000000..a712f68
--- /dev/null
+++ b/src/test/ui/parser/trait-bounds-not-on-impl.stderr
@@ -0,0 +1,8 @@
+error: expected a trait, found type
+  --> $DIR/trait-bounds-not-on-impl.rs:8:6
+   |
+LL | impl Foo + Owned for Bar {
+   |      ^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/trait-object-bad-parens.rs b/src/test/ui/parser/trait-object-bad-parens.rs
new file mode 100644
index 0000000..0f1f49a
--- /dev/null
+++ b/src/test/ui/parser/trait-object-bad-parens.rs
@@ -0,0 +1,16 @@
+// compile-flags: -Z continue-parse-after-error
+
+#![feature(optin_builtin_traits)]
+
+auto trait Auto {}
+
+fn main() {
+    let _: Box<((Auto)) + Auto>;
+    //~^ ERROR expected a path on the left-hand side of `+`, not `((Auto))`
+    let _: Box<(Auto + Auto) + Auto>;
+    //~^ ERROR expected a path on the left-hand side of `+`, not `(Auto + Auto)`
+    let _: Box<(Auto +) + Auto>;
+    //~^ ERROR expected a path on the left-hand side of `+`, not `(Auto)`
+    let _: Box<(dyn Auto) + Auto>;
+    //~^ ERROR expected a path on the left-hand side of `+`, not `(dyn Auto)`
+}
diff --git a/src/test/ui/parser/trait-object-bad-parens.stderr b/src/test/ui/parser/trait-object-bad-parens.stderr
new file mode 100644
index 0000000..74e484e
--- /dev/null
+++ b/src/test/ui/parser/trait-object-bad-parens.stderr
@@ -0,0 +1,27 @@
+error[E0178]: expected a path on the left-hand side of `+`, not `((Auto))`
+  --> $DIR/trait-object-bad-parens.rs:8:16
+   |
+LL |     let _: Box<((Auto)) + Auto>;
+   |                ^^^^^^^^^^^^^^^ expected a path
+
+error[E0178]: expected a path on the left-hand side of `+`, not `(Auto + Auto)`
+  --> $DIR/trait-object-bad-parens.rs:10:16
+   |
+LL |     let _: Box<(Auto + Auto) + Auto>;
+   |                ^^^^^^^^^^^^^^^^^^^^ expected a path
+
+error[E0178]: expected a path on the left-hand side of `+`, not `(Auto)`
+  --> $DIR/trait-object-bad-parens.rs:12:16
+   |
+LL |     let _: Box<(Auto +) + Auto>;
+   |                ^^^^^^^^^^^^^^^ expected a path
+
+error[E0178]: expected a path on the left-hand side of `+`, not `(dyn Auto)`
+  --> $DIR/trait-object-bad-parens.rs:14:16
+   |
+LL |     let _: Box<(dyn Auto) + Auto>;
+   |                ^^^^^^^^^^^^^^^^^ expected a path
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0178`.
diff --git a/src/test/ui/parser/trait-object-lifetime-parens.rs b/src/test/ui/parser/trait-object-lifetime-parens.rs
new file mode 100644
index 0000000..43f6497
--- /dev/null
+++ b/src/test/ui/parser/trait-object-lifetime-parens.rs
@@ -0,0 +1,15 @@
+// compile-flags: -Z continue-parse-after-error
+
+trait Trait {}
+
+fn f<'a, T: Trait + ('a)>() {} //~ ERROR parenthesized lifetime bounds are not supported
+
+fn check<'a>() {
+    let _: Box<Trait + ('a)>; //~ ERROR parenthesized lifetime bounds are not supported
+    let _: Box<('a) + Trait>;
+    //~^ ERROR expected type, found `'a`
+    //~| ERROR expected `:`, found `)`
+    //~| ERROR chained comparison operators require parentheses
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/trait-object-lifetime-parens.stderr b/src/test/ui/parser/trait-object-lifetime-parens.stderr
new file mode 100644
index 0000000..a31b7ae
--- /dev/null
+++ b/src/test/ui/parser/trait-object-lifetime-parens.stderr
@@ -0,0 +1,37 @@
+error: parenthesized lifetime bounds are not supported
+  --> $DIR/trait-object-lifetime-parens.rs:5:21
+   |
+LL | fn f<'a, T: Trait + ('a)>() {}
+   |                     ^^^^ help: remove the parentheses
+
+error: parenthesized lifetime bounds are not supported
+  --> $DIR/trait-object-lifetime-parens.rs:8:24
+   |
+LL |     let _: Box<Trait + ('a)>;
+   |                        ^^^^ help: remove the parentheses
+
+error: expected `:`, found `)`
+  --> $DIR/trait-object-lifetime-parens.rs:9:19
+   |
+LL |     let _: Box<('a) + Trait>;
+   |                   ^ expected `:`
+
+error: chained comparison operators require parentheses
+  --> $DIR/trait-object-lifetime-parens.rs:9:15
+   |
+LL |     let _: Box<('a) + Trait>;
+   |               ^^^^^^^^^^^^^^^
+   |
+   = help: use `::<...>` instead of `<...>` if you meant to specify type arguments
+   = help: or use `(...)` if you meant to specify fn arguments
+
+error: expected type, found `'a`
+  --> $DIR/trait-object-lifetime-parens.rs:9:17
+   |
+LL |     let _: Box<('a) + Trait>;
+   |         -       ^^
+   |         |
+   |         while parsing the type for `_`
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/ui/parser/trait-object-polytrait-priority.rs b/src/test/ui/parser/trait-object-polytrait-priority.rs
new file mode 100644
index 0000000..40d2ad5
--- /dev/null
+++ b/src/test/ui/parser/trait-object-polytrait-priority.rs
@@ -0,0 +1,8 @@
+trait Trait<'a> {}
+
+fn main() {
+    let _: &for<'a> Trait<'a> + 'static;
+    //~^ ERROR expected a path on the left-hand side of `+`, not `&for<'a> Trait<'a>`
+    //~| HELP try adding parentheses
+    //~| SUGGESTION &(for<'a> Trait<'a> + 'static)
+}
diff --git a/src/test/ui/parser/trait-object-polytrait-priority.stderr b/src/test/ui/parser/trait-object-polytrait-priority.stderr
new file mode 100644
index 0000000..5e2a35e
--- /dev/null
+++ b/src/test/ui/parser/trait-object-polytrait-priority.stderr
@@ -0,0 +1,9 @@
+error[E0178]: expected a path on the left-hand side of `+`, not `&for<'a> Trait<'a>`
+  --> $DIR/trait-object-polytrait-priority.rs:4:12
+   |
+LL |     let _: &for<'a> Trait<'a> + 'static;
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try adding parentheses: `&(for<'a> Trait<'a> + 'static)`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0178`.
diff --git a/src/test/ui/parser/trait-object-trait-parens.rs b/src/test/ui/parser/trait-object-trait-parens.rs
new file mode 100644
index 0000000..2bbc580
--- /dev/null
+++ b/src/test/ui/parser/trait-object-trait-parens.rs
@@ -0,0 +1,12 @@
+trait Trait<'a> {}
+
+fn f<T: (Copy) + (?Sized) + (for<'a> Trait<'a>)>() {}
+
+fn main() {
+    let _: Box<(Copy) + (?Sized) + (for<'a> Trait<'a>)>;
+    //~^ ERROR `?Trait` is not permitted in trait object types
+    let _: Box<(?Sized) + (for<'a> Trait<'a>) + (Copy)>;
+    let _: Box<(for<'a> Trait<'a>) + (Copy) + (?Sized)>;
+    //~^ ERROR `?Trait` is not permitted in trait object types
+    //~| ERROR use of undeclared lifetime name `'a`
+}
diff --git a/src/test/ui/parser/trait-object-trait-parens.stderr b/src/test/ui/parser/trait-object-trait-parens.stderr
new file mode 100644
index 0000000..36494b7
--- /dev/null
+++ b/src/test/ui/parser/trait-object-trait-parens.stderr
@@ -0,0 +1,21 @@
+error: `?Trait` is not permitted in trait object types
+  --> $DIR/trait-object-trait-parens.rs:6:25
+   |
+LL |     let _: Box<(Copy) + (?Sized) + (for<'a> Trait<'a>)>;
+   |                         ^^^^^^^^
+
+error: `?Trait` is not permitted in trait object types
+  --> $DIR/trait-object-trait-parens.rs:9:47
+   |
+LL |     let _: Box<(for<'a> Trait<'a>) + (Copy) + (?Sized)>;
+   |                                               ^^^^^^^^
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/trait-object-trait-parens.rs:9:31
+   |
+LL |     let _: Box<(for<'a> Trait<'a>) + (Copy) + (?Sized)>;
+   |                               ^^ undeclared lifetime
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0261`.
diff --git a/src/test/ui/parser/trait-plusequal-splitting.rs b/src/test/ui/parser/trait-plusequal-splitting.rs
new file mode 100644
index 0000000..c655a15
--- /dev/null
+++ b/src/test/ui/parser/trait-plusequal-splitting.rs
@@ -0,0 +1,8 @@
+// Fixes issue where `+` in generics weren't parsed if they were part of a `+=`.
+
+// compile-pass
+
+struct Whitespace<T: Clone + = ()> { t: T }
+struct TokenSplit<T: Clone +=  ()> { t: T }
+
+fn main() {}
diff --git a/src/test/ui/parser/trait-pub-assoc-const.rs b/src/test/ui/parser/trait-pub-assoc-const.rs
new file mode 100644
index 0000000..219ffa3
--- /dev/null
+++ b/src/test/ui/parser/trait-pub-assoc-const.rs
@@ -0,0 +1,6 @@
+trait Foo {
+    pub const Foo: u32;
+    //~^ ERROR unnecessary visibility qualifier
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/trait-pub-assoc-const.stderr b/src/test/ui/parser/trait-pub-assoc-const.stderr
new file mode 100644
index 0000000..817692cc
--- /dev/null
+++ b/src/test/ui/parser/trait-pub-assoc-const.stderr
@@ -0,0 +1,8 @@
+error: unnecessary visibility qualifier
+  --> $DIR/trait-pub-assoc-const.rs:2:5
+   |
+LL |     pub const Foo: u32;
+   |     ^^^ `pub` not permitted here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/trait-pub-assoc-ty.rs b/src/test/ui/parser/trait-pub-assoc-ty.rs
new file mode 100644
index 0000000..a78dfbd
--- /dev/null
+++ b/src/test/ui/parser/trait-pub-assoc-ty.rs
@@ -0,0 +1,6 @@
+trait Foo {
+    pub type Foo;
+    //~^ ERROR unnecessary visibility qualifier
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/trait-pub-assoc-ty.stderr b/src/test/ui/parser/trait-pub-assoc-ty.stderr
new file mode 100644
index 0000000..400be6a
--- /dev/null
+++ b/src/test/ui/parser/trait-pub-assoc-ty.stderr
@@ -0,0 +1,8 @@
+error: unnecessary visibility qualifier
+  --> $DIR/trait-pub-assoc-ty.rs:2:5
+   |
+LL |     pub type Foo;
+   |     ^^^ `pub` not permitted here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/trait-pub-method.rs b/src/test/ui/parser/trait-pub-method.rs
new file mode 100644
index 0000000..1f6ee02
--- /dev/null
+++ b/src/test/ui/parser/trait-pub-method.rs
@@ -0,0 +1,6 @@
+trait Foo {
+    pub fn foo();
+    //~^ ERROR unnecessary visibility qualifier
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/trait-pub-method.stderr b/src/test/ui/parser/trait-pub-method.stderr
new file mode 100644
index 0000000..b3617a4
--- /dev/null
+++ b/src/test/ui/parser/trait-pub-method.stderr
@@ -0,0 +1,8 @@
+error: unnecessary visibility qualifier
+  --> $DIR/trait-pub-method.rs:2:5
+   |
+LL |     pub fn foo();
+   |     ^^^ `pub` not permitted here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/type-parameters-in-field-exprs.rs b/src/test/ui/parser/type-parameters-in-field-exprs.rs
new file mode 100644
index 0000000..1b8ed9f
--- /dev/null
+++ b/src/test/ui/parser/type-parameters-in-field-exprs.rs
@@ -0,0 +1,19 @@
+// compile-flags: -Z continue-parse-after-error
+
+struct Foo {
+    x: isize,
+    y: isize,
+}
+
+fn main() {
+    let f = Foo {
+        x: 1,
+        y: 2,
+    };
+    f.x::<isize>;
+    //~^ ERROR field expressions may not have generic arguments
+    f.x::<>;
+    //~^ ERROR field expressions may not have generic arguments
+    f.x::();
+    //~^ ERROR field expressions may not have generic arguments
+}
diff --git a/src/test/ui/parser/type-parameters-in-field-exprs.stderr b/src/test/ui/parser/type-parameters-in-field-exprs.stderr
new file mode 100644
index 0000000..2183c74
--- /dev/null
+++ b/src/test/ui/parser/type-parameters-in-field-exprs.stderr
@@ -0,0 +1,20 @@
+error: field expressions may not have generic arguments
+  --> $DIR/type-parameters-in-field-exprs.rs:13:10
+   |
+LL |     f.x::<isize>;
+   |          ^^^^^^^
+
+error: field expressions may not have generic arguments
+  --> $DIR/type-parameters-in-field-exprs.rs:15:10
+   |
+LL |     f.x::<>;
+   |          ^^
+
+error: field expressions may not have generic arguments
+  --> $DIR/type-parameters-in-field-exprs.rs:17:10
+   |
+LL |     f.x::();
+   |          ^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/parser/unbalanced-doublequote.rs b/src/test/ui/parser/unbalanced-doublequote.rs
new file mode 100644
index 0000000..f213162
--- /dev/null
+++ b/src/test/ui/parser/unbalanced-doublequote.rs
@@ -0,0 +1,6 @@
+// error-pattern: unterminated double quote string
+
+
+fn main() {
+    "
+}
diff --git a/src/test/ui/parser/unbalanced-doublequote.stderr b/src/test/ui/parser/unbalanced-doublequote.stderr
new file mode 100644
index 0000000..4d98515
--- /dev/null
+++ b/src/test/ui/parser/unbalanced-doublequote.stderr
@@ -0,0 +1,9 @@
+error: unterminated double quote string
+  --> $DIR/unbalanced-doublequote.rs:5:5
+   |
+LL | /     "
+LL | | }
+   | |__^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/unclosed-braces.rs b/src/test/ui/parser/unclosed-braces.rs
new file mode 100644
index 0000000..9c9ab76
--- /dev/null
+++ b/src/test/ui/parser/unclosed-braces.rs
@@ -0,0 +1,22 @@
+struct S {
+    x: [usize; 3],
+}
+
+fn foo() {
+    {
+        {
+            println!("hi");
+        }
+    }
+}
+
+fn main() {
+//~^ NOTE un-closed delimiter
+    {
+        {
+        //~^ NOTE this delimiter might not be properly closed...
+            foo();
+    }
+    //~^ NOTE ...as it matches this but it has different indentation
+}
+//~ ERROR this file contains an un-closed delimiter
diff --git a/src/test/ui/parser/unclosed-braces.stderr b/src/test/ui/parser/unclosed-braces.stderr
new file mode 100644
index 0000000..44c7e93
--- /dev/null
+++ b/src/test/ui/parser/unclosed-braces.stderr
@@ -0,0 +1,17 @@
+error: this file contains an un-closed delimiter
+  --> $DIR/unclosed-braces.rs:22:53
+   |
+LL | fn main() {
+   |           - un-closed delimiter
+...
+LL |         {
+   |         - this delimiter might not be properly closed...
+...
+LL |     }
+   |     - ...as it matches this but it has different indentation
+...
+LL |
+   |                                                     ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/unclosed-delimiter-in-dep.rs b/src/test/ui/parser/unclosed-delimiter-in-dep.rs
new file mode 100644
index 0000000..6db1b66
--- /dev/null
+++ b/src/test/ui/parser/unclosed-delimiter-in-dep.rs
@@ -0,0 +1,6 @@
+mod unclosed_delim_mod;
+
+fn main() {
+    let _: usize = unclosed_delim_mod::new();
+    //~^ ERROR mismatched types
+}
diff --git a/src/test/ui/parser/unclosed-delimiter-in-dep.stderr b/src/test/ui/parser/unclosed-delimiter-in-dep.stderr
new file mode 100644
index 0000000..633c63b
--- /dev/null
+++ b/src/test/ui/parser/unclosed-delimiter-in-dep.stderr
@@ -0,0 +1,23 @@
+error: incorrect close delimiter: `}`
+  --> $DIR/unclosed_delim_mod.rs:5:1
+   |
+LL | pub fn new() -> Result<Value, ()> {
+   |                                   - close delimiter possibly meant for this
+LL |     Ok(Value {
+   |       - un-closed delimiter
+LL |     }
+LL | }
+   | ^ incorrect close delimiter
+
+error[E0308]: mismatched types
+  --> $DIR/unclosed-delimiter-in-dep.rs:4:20
+   |
+LL |     let _: usize = unclosed_delim_mod::new();
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^ expected usize, found enum `std::result::Result`
+   |
+   = note: expected type `usize`
+              found type `std::result::Result<unclosed_delim_mod::Value, ()>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/parser/unclosed_delim_mod.rs b/src/test/ui/parser/unclosed_delim_mod.rs
new file mode 100644
index 0000000..b1664f4
--- /dev/null
+++ b/src/test/ui/parser/unclosed_delim_mod.rs
@@ -0,0 +1,6 @@
+pub struct Value {}
+pub fn new() -> Result<Value, ()> {
+    Ok(Value {
+    }
+}
+//~^ ERROR incorrect close delimiter
diff --git a/src/test/ui/parser/unclosed_delim_mod.stderr b/src/test/ui/parser/unclosed_delim_mod.stderr
new file mode 100644
index 0000000..cc04eb5
--- /dev/null
+++ b/src/test/ui/parser/unclosed_delim_mod.stderr
@@ -0,0 +1,18 @@
+error: incorrect close delimiter: `}`
+  --> $DIR/unclosed_delim_mod.rs:5:1
+   |
+LL | pub fn new() -> Result<Value, ()> {
+   |                                   - close delimiter possibly meant for this
+LL |     Ok(Value {
+   |       - un-closed delimiter
+LL |     }
+LL | }
+   | ^ incorrect close delimiter
+
+error[E0601]: `main` function not found in crate `unclosed_delim_mod`
+   |
+   = note: consider adding a `main` function to `$DIR/unclosed_delim_mod.rs`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0601`.
diff --git a/src/test/ui/parser/underscore-suffix-for-float.rs b/src/test/ui/parser/underscore-suffix-for-float.rs
new file mode 100644
index 0000000..c9b7ece
--- /dev/null
+++ b/src/test/ui/parser/underscore-suffix-for-float.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let a = 42._; //~ ERROR expected identifier, found reserved identifier `_`
+                  //~| ERROR `{integer}` is a primitive type and therefore doesn't have fields
+}
diff --git a/src/test/ui/parser/underscore-suffix-for-float.stderr b/src/test/ui/parser/underscore-suffix-for-float.stderr
new file mode 100644
index 0000000..a5f3b65
--- /dev/null
+++ b/src/test/ui/parser/underscore-suffix-for-float.stderr
@@ -0,0 +1,15 @@
+error: expected identifier, found reserved identifier `_`
+  --> $DIR/underscore-suffix-for-float.rs:2:16
+   |
+LL |     let a = 42._;
+   |                ^ expected identifier, found reserved identifier
+
+error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields
+  --> $DIR/underscore-suffix-for-float.rs:2:16
+   |
+LL |     let a = 42._;
+   |                ^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0610`.
diff --git a/src/test/ui/parser/underscore-suffix-for-string.rs b/src/test/ui/parser/underscore-suffix-for-string.rs
new file mode 100644
index 0000000..bcd0b24
--- /dev/null
+++ b/src/test/ui/parser/underscore-suffix-for-string.rs
@@ -0,0 +1,8 @@
+// compile-pass
+
+fn main() {
+    let _ = "Foo"_;
+    //~^ WARNING underscore literal suffix is not allowed
+    //~| WARNING this was previously accepted
+    //~| NOTE issue #42326
+}
diff --git a/src/test/ui/parser/underscore-suffix-for-string.stderr b/src/test/ui/parser/underscore-suffix-for-string.stderr
new file mode 100644
index 0000000..80d0d1b
--- /dev/null
+++ b/src/test/ui/parser/underscore-suffix-for-string.stderr
@@ -0,0 +1,9 @@
+warning: underscore literal suffix is not allowed
+  --> $DIR/underscore-suffix-for-string.rs:4:18
+   |
+LL |     let _ = "Foo"_;
+   |                  ^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #42326 <https://github.com/rust-lang/rust/issues/42326>
+
diff --git a/src/test/ui/parser/underscore_static.rs b/src/test/ui/parser/underscore_static.rs
new file mode 100644
index 0000000..21d6a1b
--- /dev/null
+++ b/src/test/ui/parser/underscore_static.rs
@@ -0,0 +1,3 @@
+static _: () = (); //~ ERROR expected identifier, found reserved identifier `_`
+
+fn main() {}
diff --git a/src/test/ui/parser/underscore_static.stderr b/src/test/ui/parser/underscore_static.stderr
new file mode 100644
index 0000000..4c41afd
--- /dev/null
+++ b/src/test/ui/parser/underscore_static.stderr
@@ -0,0 +1,8 @@
+error: expected identifier, found reserved identifier `_`
+  --> $DIR/underscore_static.rs:1:8
+   |
+LL | static _: () = ();
+   |        ^ expected identifier, found reserved identifier
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/unicode-chars.rs b/src/test/ui/parser/unicode-chars.rs
new file mode 100644
index 0000000..89ae85e
--- /dev/null
+++ b/src/test/ui/parser/unicode-chars.rs
@@ -0,0 +1,5 @@
+fn main() {
+    let y = 0;
+    //~^ ERROR unknown start of token: \u{37e}
+    //~^^ HELP Unicode character ';' (Greek Question Mark) looks like ';' (Semicolon), but it is not
+}
diff --git a/src/test/ui/parser/unicode-chars.stderr b/src/test/ui/parser/unicode-chars.stderr
new file mode 100644
index 0000000..76bf662
--- /dev/null
+++ b/src/test/ui/parser/unicode-chars.stderr
@@ -0,0 +1,12 @@
+error: unknown start of token: \u{37e}
+  --> $DIR/unicode-chars.rs:2:14
+   |
+LL |     let y = 0;
+   |              ^
+help: Unicode character ';' (Greek Question Mark) looks like ';' (Semicolon), but it is not
+   |
+LL |     let y = 0;
+   |              ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/unicode-quote-chars.rs b/src/test/ui/parser/unicode-quote-chars.rs
new file mode 100644
index 0000000..6964421
--- /dev/null
+++ b/src/test/ui/parser/unicode-quote-chars.rs
@@ -0,0 +1,7 @@
+// ignore-tidy-linelength
+
+fn main() {
+    println!(“hello world”);
+    //~^ ERROR unknown start of token: \u{201c}
+    //~^^ HELP Unicode characters '“' (Left Double Quotation Mark) and '”' (Right Double Quotation Mark) look like '"' (Quotation Mark), but are not
+}
diff --git a/src/test/ui/parser/unicode-quote-chars.stderr b/src/test/ui/parser/unicode-quote-chars.stderr
new file mode 100644
index 0000000..4a09ed7
--- /dev/null
+++ b/src/test/ui/parser/unicode-quote-chars.stderr
@@ -0,0 +1,12 @@
+error: unknown start of token: \u{201c}
+  --> $DIR/unicode-quote-chars.rs:4:14
+   |
+LL |     println!(“hello world”);
+   |              ^
+help: Unicode characters '“' (Left Double Quotation Mark) and '”' (Right Double Quotation Mark) look like '"' (Quotation Mark), but are not
+   |
+LL |     println!("hello world");
+   |              ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/unmatched-delimiter-at-end-of-file.rs b/src/test/ui/parser/unmatched-delimiter-at-end-of-file.rs
new file mode 100644
index 0000000..3eef75b
--- /dev/null
+++ b/src/test/ui/parser/unmatched-delimiter-at-end-of-file.rs
@@ -0,0 +1,11 @@
+struct S {
+    x: usize,
+    y: usize,
+}
+
+fn main() {
+    S { x: 4,
+        y: 5 };
+}
+
+fn foo() { //~ ERROR this file contains an un-closed delimiter
diff --git a/src/test/ui/parser/unmatched-delimiter-at-end-of-file.stderr b/src/test/ui/parser/unmatched-delimiter-at-end-of-file.stderr
new file mode 100644
index 0000000..bfbdb03
--- /dev/null
+++ b/src/test/ui/parser/unmatched-delimiter-at-end-of-file.stderr
@@ -0,0 +1,8 @@
+error: this file contains an un-closed delimiter
+  --> $DIR/unmatched-delimiter-at-end-of-file.rs:11:64
+   |
+LL | fn foo() {
+   |          - un-closed delimiter                                 ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/unsized.rs b/src/test/ui/parser/unsized.rs
new file mode 100644
index 0000000..e7fd7a1
--- /dev/null
+++ b/src/test/ui/parser/unsized.rs
@@ -0,0 +1,7 @@
+// Test syntax checks for `type` keyword.
+
+struct S1 for type;
+//~^ ERROR expected `where`, `{`, `(`, or `;` after struct name, found keyword `for`
+
+pub fn main() {
+}
diff --git a/src/test/ui/parser/unsized.stderr b/src/test/ui/parser/unsized.stderr
new file mode 100644
index 0000000..3d4ed52
--- /dev/null
+++ b/src/test/ui/parser/unsized.stderr
@@ -0,0 +1,8 @@
+error: expected `where`, `{`, `(`, or `;` after struct name, found keyword `for`
+  --> $DIR/unsized.rs:3:11
+   |
+LL | struct S1 for type;
+   |           ^^^ expected `where`, `{`, `(`, or `;` after struct name
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/unsized2.rs b/src/test/ui/parser/unsized2.rs
new file mode 100644
index 0000000..21370b3
--- /dev/null
+++ b/src/test/ui/parser/unsized2.rs
@@ -0,0 +1,7 @@
+// Test syntax checks for `type` keyword.
+
+fn f<X>() {}
+
+pub fn main() {
+    f<type>(); //~ ERROR expected expression, found keyword `type`
+}
diff --git a/src/test/ui/parser/unsized2.stderr b/src/test/ui/parser/unsized2.stderr
new file mode 100644
index 0000000..17e39b2
--- /dev/null
+++ b/src/test/ui/parser/unsized2.stderr
@@ -0,0 +1,8 @@
+error: expected expression, found keyword `type`
+  --> $DIR/unsized2.rs:6:7
+   |
+LL |     f<type>();
+   |       ^^^^ expected expression
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/use-as-where-use-ends-with-mod-sep.rs b/src/test/ui/parser/use-as-where-use-ends-with-mod-sep.rs
new file mode 100644
index 0000000..d322e9f
--- /dev/null
+++ b/src/test/ui/parser/use-as-where-use-ends-with-mod-sep.rs
@@ -0,0 +1,4 @@
+// compile-flags: -Z continue-parse-after-error
+
+use std::any:: as foo; //~ ERROR expected identifier, found keyword `as`
+//~^ ERROR: expected one of `::`, `;`, or `as`, found `foo`
diff --git a/src/test/ui/parser/use-as-where-use-ends-with-mod-sep.stderr b/src/test/ui/parser/use-as-where-use-ends-with-mod-sep.stderr
new file mode 100644
index 0000000..3691752
--- /dev/null
+++ b/src/test/ui/parser/use-as-where-use-ends-with-mod-sep.stderr
@@ -0,0 +1,18 @@
+error: expected identifier, found keyword `as`
+  --> $DIR/use-as-where-use-ends-with-mod-sep.rs:3:16
+   |
+LL | use std::any:: as foo;
+   |                ^^ expected identifier, found keyword
+help: you can escape reserved keywords to use them as identifiers
+   |
+LL | use std::any:: r#as foo;
+   |                ^^^^
+
+error: expected one of `::`, `;`, or `as`, found `foo`
+  --> $DIR/use-as-where-use-ends-with-mod-sep.rs:3:19
+   |
+LL | use std::any:: as foo;
+   |                   ^^^ expected one of `::`, `;`, or `as` here
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/parser/use-ends-with-mod-sep.rs b/src/test/ui/parser/use-ends-with-mod-sep.rs
new file mode 100644
index 0000000..ad8da4d
--- /dev/null
+++ b/src/test/ui/parser/use-ends-with-mod-sep.rs
@@ -0,0 +1 @@
+use std::any::; //~ ERROR expected identifier, found `;`
diff --git a/src/test/ui/parser/use-ends-with-mod-sep.stderr b/src/test/ui/parser/use-ends-with-mod-sep.stderr
new file mode 100644
index 0000000..bd0d881
--- /dev/null
+++ b/src/test/ui/parser/use-ends-with-mod-sep.stderr
@@ -0,0 +1,8 @@
+error: expected identifier, found `;`
+  --> $DIR/use-ends-with-mod-sep.rs:1:15
+   |
+LL | use std::any::;
+   |               ^ expected identifier
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/variadic-ffi-3.rs b/src/test/ui/parser/variadic-ffi-3.rs
new file mode 100644
index 0000000..ce83cc8
--- /dev/null
+++ b/src/test/ui/parser/variadic-ffi-3.rs
@@ -0,0 +1,5 @@
+fn foo(x: isize, ...) {
+    //~^ ERROR: only foreign functions are allowed to be C-variadic
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/variadic-ffi-3.stderr b/src/test/ui/parser/variadic-ffi-3.stderr
new file mode 100644
index 0000000..8ea4d19
--- /dev/null
+++ b/src/test/ui/parser/variadic-ffi-3.stderr
@@ -0,0 +1,8 @@
+error: only foreign functions are allowed to be C-variadic
+  --> $DIR/variadic-ffi-3.rs:1:18
+   |
+LL | fn foo(x: isize, ...) {
+   |                  ^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/variadic-ffi-4.rs b/src/test/ui/parser/variadic-ffi-4.rs
new file mode 100644
index 0000000..5f8b3f8
--- /dev/null
+++ b/src/test/ui/parser/variadic-ffi-4.rs
@@ -0,0 +1,5 @@
+extern "C" fn foo(x: isize, ...) {
+    //~^ ERROR: only foreign functions are allowed to be C-variadic
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/variadic-ffi-4.stderr b/src/test/ui/parser/variadic-ffi-4.stderr
new file mode 100644
index 0000000..69fbf84
--- /dev/null
+++ b/src/test/ui/parser/variadic-ffi-4.stderr
@@ -0,0 +1,8 @@
+error: only foreign functions are allowed to be C-variadic
+  --> $DIR/variadic-ffi-4.rs:1:29
+   |
+LL | extern "C" fn foo(x: isize, ...) {
+   |                             ^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/virtual-structs.rs b/src/test/ui/parser/virtual-structs.rs
new file mode 100644
index 0000000..ce57a34
--- /dev/null
+++ b/src/test/ui/parser/virtual-structs.rs
@@ -0,0 +1,10 @@
+// Test diagnostics for the removed struct inheritance feature.
+
+virtual struct SuperStruct {
+//~^ ERROR expected item, found reserved keyword `virtual`
+    f1: isize,
+}
+
+struct Struct : SuperStruct;
+
+pub fn main() {}
diff --git a/src/test/ui/parser/virtual-structs.stderr b/src/test/ui/parser/virtual-structs.stderr
new file mode 100644
index 0000000..a5211d8
--- /dev/null
+++ b/src/test/ui/parser/virtual-structs.stderr
@@ -0,0 +1,8 @@
+error: expected item, found reserved keyword `virtual`
+  --> $DIR/virtual-structs.rs:3:1
+   |
+LL | virtual struct SuperStruct {
+   | ^^^^^^^ expected item
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/where-clauses-no-bounds-or-predicates.rs b/src/test/ui/parser/where-clauses-no-bounds-or-predicates.rs
new file mode 100644
index 0000000..45dacf2
--- /dev/null
+++ b/src/test/ui/parser/where-clauses-no-bounds-or-predicates.rs
@@ -0,0 +1,17 @@
+// compile-flags: -Z continue-parse-after-error
+
+// Empty predicate list is OK
+fn equal1<T>(_: &T, _: &T) -> bool where {
+    true
+}
+
+// Empty bound list is OK
+fn equal2<T>(_: &T, _: &T) -> bool where T: {
+    true
+}
+
+fn foo<'a>() where 'a {}
+//~^ ERROR expected `:`, found `{`
+
+fn main() {
+}
diff --git a/src/test/ui/parser/where-clauses-no-bounds-or-predicates.stderr b/src/test/ui/parser/where-clauses-no-bounds-or-predicates.stderr
new file mode 100644
index 0000000..7e82522
--- /dev/null
+++ b/src/test/ui/parser/where-clauses-no-bounds-or-predicates.stderr
@@ -0,0 +1,8 @@
+error: expected `:`, found `{`
+  --> $DIR/where-clauses-no-bounds-or-predicates.rs:13:23
+   |
+LL | fn foo<'a>() where 'a {}
+   |                       ^ expected `:`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/where_with_bound.rs b/src/test/ui/parser/where_with_bound.rs
new file mode 100644
index 0000000..3ca45f1
--- /dev/null
+++ b/src/test/ui/parser/where_with_bound.rs
@@ -0,0 +1,5 @@
+fn foo<T>() where <T>::Item: ToString, T: Iterator { }
+//~^ ERROR generic parameters on `where` clauses are reserved for future use
+//~| ERROR cannot find type `Item` in the crate root
+
+fn main() {}
diff --git a/src/test/ui/parser/where_with_bound.stderr b/src/test/ui/parser/where_with_bound.stderr
new file mode 100644
index 0000000..ff98b3f
--- /dev/null
+++ b/src/test/ui/parser/where_with_bound.stderr
@@ -0,0 +1,15 @@
+error: generic parameters on `where` clauses are reserved for future use
+  --> $DIR/where_with_bound.rs:1:19
+   |
+LL | fn foo<T>() where <T>::Item: ToString, T: Iterator { }
+   |                   ^^^ currently unsupported
+
+error[E0412]: cannot find type `Item` in the crate root
+  --> $DIR/where_with_bound.rs:1:24
+   |
+LL | fn foo<T>() where <T>::Item: ToString, T: Iterator { }
+   |                        ^^^^ not found in the crate root
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/src/test/ui/parser/wrong-escape-of-curly-braces.rs b/src/test/ui/parser/wrong-escape-of-curly-braces.rs
new file mode 100644
index 0000000..7a5c27a
--- /dev/null
+++ b/src/test/ui/parser/wrong-escape-of-curly-braces.rs
@@ -0,0 +1,8 @@
+fn main() {
+    let ok = "{{everything fine}}";
+    let bad = "\{it is wrong\}";
+    //~^  ERROR unknown character escape: {
+    //~^^  HELP if used in a formatting string, curly braces are escaped with `{{` and `}}`
+    //~^^^ ERROR unknown character escape: }
+    //~^^^^  HELP if used in a formatting string, curly braces are escaped with `{{` and `}}`
+}
diff --git a/src/test/ui/parser/wrong-escape-of-curly-braces.stderr b/src/test/ui/parser/wrong-escape-of-curly-braces.stderr
new file mode 100644
index 0000000..1406b79
--- /dev/null
+++ b/src/test/ui/parser/wrong-escape-of-curly-braces.stderr
@@ -0,0 +1,18 @@
+error: unknown character escape: {
+  --> $DIR/wrong-escape-of-curly-braces.rs:3:17
+   |
+LL |     let bad = "\{it is wrong\}";
+   |                 ^ unknown character escape
+   |
+   = help: if used in a formatting string, curly braces are escaped with `{{` and `}}`
+
+error: unknown character escape: }
+  --> $DIR/wrong-escape-of-curly-braces.rs:3:30
+   |
+LL |     let bad = "\{it is wrong\}";
+   |                              ^ unknown character escape
+   |
+   = help: if used in a formatting string, curly braces are escaped with `{{` and `}}`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/partialeq_help.rs b/src/test/ui/partialeq_help.rs
new file mode 100644
index 0000000..c3ba805
--- /dev/null
+++ b/src/test/ui/partialeq_help.rs
@@ -0,0 +1,7 @@
+fn foo<T: PartialEq>(a: &T, b: T) {
+    a == b; //~ ERROR E0277
+}
+
+fn main() {
+    foo(&1, 1);
+}
diff --git a/src/test/ui/partialeq_help.stderr b/src/test/ui/partialeq_help.stderr
new file mode 100644
index 0000000..9021bd3
--- /dev/null
+++ b/src/test/ui/partialeq_help.stderr
@@ -0,0 +1,12 @@
+error[E0277]: can't compare `&T` with `T`
+  --> $DIR/partialeq_help.rs:2:7
+   |
+LL |     a == b;
+   |       ^^ no implementation for `&T == T`
+   |
+   = help: the trait `std::cmp::PartialEq<T>` is not implemented for `&T`
+   = help: consider adding a `where &T: std::cmp::PartialEq<T>` bound
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/path-lookahead.rs b/src/test/ui/path-lookahead.rs
new file mode 100644
index 0000000..fd7509a
--- /dev/null
+++ b/src/test/ui/path-lookahead.rs
@@ -0,0 +1,17 @@
+// run-pass
+
+#![warn(unused)]
+
+// Parser test for #37765
+
+fn with_parens<T: ToString>(arg: T) -> String { //~WARN function is never used: `with_parens`
+  return (<T as ToString>::to_string(&arg)); //~WARN unnecessary parentheses around `return` value
+}
+
+fn no_parens<T: ToString>(arg: T) -> String { //~WARN function is never used: `no_parens`
+  return <T as ToString>::to_string(&arg);
+}
+
+fn main() {
+
+}
diff --git a/src/test/ui/path-lookahead.stderr b/src/test/ui/path-lookahead.stderr
new file mode 100644
index 0000000..50593e4
--- /dev/null
+++ b/src/test/ui/path-lookahead.stderr
@@ -0,0 +1,32 @@
+warning: unnecessary parentheses around `return` value
+  --> $DIR/path-lookahead.rs:8:10
+   |
+LL |   return (<T as ToString>::to_string(&arg));
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove these parentheses
+   |
+note: lint level defined here
+  --> $DIR/path-lookahead.rs:3:9
+   |
+LL | #![warn(unused)]
+   |         ^^^^^^
+   = note: #[warn(unused_parens)] implied by #[warn(unused)]
+
+warning: function is never used: `with_parens`
+  --> $DIR/path-lookahead.rs:7:1
+   |
+LL | fn with_parens<T: ToString>(arg: T) -> String {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/path-lookahead.rs:3:9
+   |
+LL | #![warn(unused)]
+   |         ^^^^^^
+   = note: #[warn(dead_code)] implied by #[warn(unused)]
+
+warning: function is never used: `no_parens`
+  --> $DIR/path-lookahead.rs:11:1
+   |
+LL | fn no_parens<T: ToString>(arg: T) -> String {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
diff --git a/src/test/ui/pattern/const-pat-ice.rs b/src/test/ui/pattern/const-pat-ice.rs
new file mode 100644
index 0000000..865c54b
--- /dev/null
+++ b/src/test/ui/pattern/const-pat-ice.rs
@@ -0,0 +1,14 @@
+// failure-status: 101
+// rustc-env:RUST_BACKTRACE=0
+
+// This is a repro test for an ICE in our pattern handling of constants.
+
+const FOO: &&&u32 = &&&42;
+
+fn main() {
+    match unimplemented!() {
+        &&&42 => {},
+        FOO => {},
+        _ => {},
+    }
+}
diff --git a/src/test/ui/pattern/deny-irrefutable-let-patterns.rs b/src/test/ui/pattern/deny-irrefutable-let-patterns.rs
new file mode 100644
index 0000000..14040c8
--- /dev/null
+++ b/src/test/ui/pattern/deny-irrefutable-let-patterns.rs
@@ -0,0 +1,9 @@
+#![deny(irrefutable_let_patterns)]
+
+fn main() {
+    if let _ = 5 {} //~ ERROR irrefutable if-let pattern
+
+    while let _ = 5 { //~ ERROR irrefutable while-let pattern
+        break;
+    }
+}
diff --git a/src/test/ui/pattern/deny-irrefutable-let-patterns.stderr b/src/test/ui/pattern/deny-irrefutable-let-patterns.stderr
new file mode 100644
index 0000000..b32cf8c
--- /dev/null
+++ b/src/test/ui/pattern/deny-irrefutable-let-patterns.stderr
@@ -0,0 +1,22 @@
+error: irrefutable if-let pattern
+  --> $DIR/deny-irrefutable-let-patterns.rs:4:5
+   |
+LL |     if let _ = 5 {}
+   |     ^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/deny-irrefutable-let-patterns.rs:1:9
+   |
+LL | #![deny(irrefutable_let_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: irrefutable while-let pattern
+  --> $DIR/deny-irrefutable-let-patterns.rs:6:5
+   |
+LL | /     while let _ = 5 {
+LL | |         break;
+LL | |     }
+   | |_____^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/pattern/enum-variant-generic-args.rs b/src/test/ui/pattern/enum-variant-generic-args.rs
new file mode 100644
index 0000000..8559953
--- /dev/null
+++ b/src/test/ui/pattern/enum-variant-generic-args.rs
@@ -0,0 +1,43 @@
+// run-pass
+
+#![feature(type_alias_enum_variants)]
+
+#![allow(irrefutable_let_patterns)]
+
+#[allow(dead_code)]
+enum Enum<T> { TSVariant(T), SVariant { v: T } }
+type Alias<T> = Enum<T>;
+type AliasFixed = Enum<()>;
+
+macro_rules! is_variant {
+    (TSVariant, $expr:expr) => (is_variant!(@check TSVariant, (_), $expr));
+    (SVariant, $expr:expr) => (is_variant!(@check SVariant, { v: _ }, $expr));
+    (@check $variant:ident, $matcher:tt, $expr:expr) => (
+        assert!(if let Enum::$variant::<()> $matcher = $expr { true } else { false },
+                "expr does not have correct type");
+    );
+}
+
+fn main() {
+    // Tuple struct variant
+
+    is_variant!(TSVariant, Enum::TSVariant(()));
+    is_variant!(TSVariant, Enum::TSVariant::<()>(()));
+    is_variant!(TSVariant, Enum::<()>::TSVariant(()));
+
+    is_variant!(TSVariant, Alias::TSVariant(()));
+    is_variant!(TSVariant, Alias::<()>::TSVariant(()));
+
+    is_variant!(TSVariant, AliasFixed::TSVariant(()));
+
+    // Struct variant
+
+    is_variant!(SVariant, Enum::SVariant { v: () });
+    is_variant!(SVariant, Enum::SVariant::<()> { v: () });
+    is_variant!(SVariant, Enum::<()>::SVariant { v: () });
+
+    is_variant!(SVariant, Alias::SVariant { v: () });
+    is_variant!(SVariant, Alias::<()>::SVariant { v: () });
+
+    is_variant!(SVariant, AliasFixed::SVariant { v: () });
+}
diff --git a/src/test/ui/pattern/irrefutable-exhaustive-integer-binding.rs b/src/test/ui/pattern/irrefutable-exhaustive-integer-binding.rs
new file mode 100644
index 0000000..ff06588
--- /dev/null
+++ b/src/test/ui/pattern/irrefutable-exhaustive-integer-binding.rs
@@ -0,0 +1,8 @@
+// run-pass
+
+fn main() {
+    let -2147483648..=2147483647 = 1;
+    let 0..=255 = 0u8;
+    let -128..=127 = 0i8;
+    let '\u{0000}'..='\u{10FFFF}' = 'v';
+}
diff --git a/src/test/ui/pattern/irrefutable-let-patterns.rs b/src/test/ui/pattern/irrefutable-let-patterns.rs
new file mode 100644
index 0000000..d400ef0
--- /dev/null
+++ b/src/test/ui/pattern/irrefutable-let-patterns.rs
@@ -0,0 +1,11 @@
+// run-pass
+
+#![allow(irrefutable_let_patterns)]
+
+fn main() {
+    if let _ = 5 {}
+
+    while let _ = 5 {
+        break;
+    }
+}
diff --git a/src/test/ui/pattern/pat-shadow-in-nested-binding.rs b/src/test/ui/pattern/pat-shadow-in-nested-binding.rs
new file mode 100644
index 0000000..7badbb6
--- /dev/null
+++ b/src/test/ui/pattern/pat-shadow-in-nested-binding.rs
@@ -0,0 +1,6 @@
+#[allow(non_camel_case_types)]
+struct foo(usize);
+
+fn main() {
+    let (foo, _) = (2, 3); //~ ERROR let bindings cannot shadow tuple structs
+}
diff --git a/src/test/ui/pattern/pat-shadow-in-nested-binding.stderr b/src/test/ui/pattern/pat-shadow-in-nested-binding.stderr
new file mode 100644
index 0000000..0c5824b
--- /dev/null
+++ b/src/test/ui/pattern/pat-shadow-in-nested-binding.stderr
@@ -0,0 +1,12 @@
+error[E0530]: let bindings cannot shadow tuple structs
+  --> $DIR/pat-shadow-in-nested-binding.rs:5:10
+   |
+LL | struct foo(usize);
+   | ------------------ the tuple struct `foo` is defined here
+...
+LL |     let (foo, _) = (2, 3);
+   |          ^^^ cannot be named the same as a tuple struct
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0530`.
diff --git a/src/test/ui/pattern/pat-tuple-bad-type.rs b/src/test/ui/pattern/pat-tuple-bad-type.rs
new file mode 100644
index 0000000..01e793e
--- /dev/null
+++ b/src/test/ui/pattern/pat-tuple-bad-type.rs
@@ -0,0 +1,15 @@
+fn main() {
+    let x;
+
+    match x {
+        (..) => {} //~ ERROR type annotations needed
+        _ => {}
+    }
+
+    match 0u8 {
+        (..) => {} //~ ERROR mismatched types
+        _ => {}
+    }
+
+    x = 10;
+}
diff --git a/src/test/ui/pattern/pat-tuple-bad-type.stderr b/src/test/ui/pattern/pat-tuple-bad-type.stderr
new file mode 100644
index 0000000..84b9a62
--- /dev/null
+++ b/src/test/ui/pattern/pat-tuple-bad-type.stderr
@@ -0,0 +1,24 @@
+error[E0282]: type annotations needed
+  --> $DIR/pat-tuple-bad-type.rs:5:9
+   |
+LL |     let x;
+   |         - consider giving `x` a type
+...
+LL |         (..) => {}
+   |         ^^^^ cannot infer type
+   |
+   = note: type must be known at this point
+
+error[E0308]: mismatched types
+  --> $DIR/pat-tuple-bad-type.rs:10:9
+   |
+LL |         (..) => {}
+   |         ^^^^ expected u8, found ()
+   |
+   = note: expected type `u8`
+              found type `()`
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0282, E0308.
+For more information about an error, try `rustc --explain E0282`.
diff --git a/src/test/ui/pattern/pat-tuple-overfield.rs b/src/test/ui/pattern/pat-tuple-overfield.rs
new file mode 100644
index 0000000..46a5e15
--- /dev/null
+++ b/src/test/ui/pattern/pat-tuple-overfield.rs
@@ -0,0 +1,16 @@
+struct S(u8, u8, u8);
+
+fn main() {
+    match (1, 2, 3) {
+        (1, 2, 3, 4) => {} //~ ERROR mismatched types
+        (1, 2, .., 3, 4) => {} //~ ERROR mismatched types
+        _ => {}
+    }
+    match S(1, 2, 3) {
+        S(1, 2, 3, 4) => {}
+        //~^ ERROR this pattern has 4 fields, but the corresponding tuple struct has 3 fields
+        S(1, 2, .., 3, 4) => {}
+        //~^ ERROR this pattern has 4 fields, but the corresponding tuple struct has 3 fields
+        _ => {}
+    }
+}
diff --git a/src/test/ui/pattern/pat-tuple-overfield.stderr b/src/test/ui/pattern/pat-tuple-overfield.stderr
new file mode 100644
index 0000000..9bf14e1
--- /dev/null
+++ b/src/test/ui/pattern/pat-tuple-overfield.stderr
@@ -0,0 +1,34 @@
+error[E0308]: mismatched types
+  --> $DIR/pat-tuple-overfield.rs:5:9
+   |
+LL |         (1, 2, 3, 4) => {}
+   |         ^^^^^^^^^^^^ expected a tuple with 3 elements, found one with 4 elements
+   |
+   = note: expected type `({integer}, {integer}, {integer})`
+              found type `(_, _, _, _)`
+
+error[E0308]: mismatched types
+  --> $DIR/pat-tuple-overfield.rs:6:9
+   |
+LL |         (1, 2, .., 3, 4) => {}
+   |         ^^^^^^^^^^^^^^^^ expected a tuple with 3 elements, found one with 4 elements
+   |
+   = note: expected type `({integer}, {integer}, {integer})`
+              found type `(_, _, _, _)`
+
+error[E0023]: this pattern has 4 fields, but the corresponding tuple struct has 3 fields
+  --> $DIR/pat-tuple-overfield.rs:10:9
+   |
+LL |         S(1, 2, 3, 4) => {}
+   |         ^^^^^^^^^^^^^ expected 3 fields, found 4
+
+error[E0023]: this pattern has 4 fields, but the corresponding tuple struct has 3 fields
+  --> $DIR/pat-tuple-overfield.rs:12:9
+   |
+LL |         S(1, 2, .., 3, 4) => {}
+   |         ^^^^^^^^^^^^^^^^^ expected 3 fields, found 4
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0023, E0308.
+For more information about an error, try `rustc --explain E0023`.
diff --git a/src/test/ui/pattern/patkind-litrange-no-expr.rs b/src/test/ui/pattern/patkind-litrange-no-expr.rs
new file mode 100644
index 0000000..def6c62
--- /dev/null
+++ b/src/test/ui/pattern/patkind-litrange-no-expr.rs
@@ -0,0 +1,24 @@
+macro_rules! enum_number {
+    ($name:ident { $($variant:ident = $value:expr, )* }) => {
+        enum $name {
+            $($variant = $value,)*
+        }
+
+        fn foo(value: i32) -> Option<$name> {
+            match value {
+                $( $value => Some($name::$variant), )* // PatKind::Lit
+                $( $value ..= 42 => Some($name::$variant), )* // PatKind::Range
+                _ => None
+            }
+        }
+    }
+}
+
+enum_number!(Change {
+    Pos = 1,
+    Neg = -1,
+    Arith = 1 + 1, //~ ERROR arbitrary expressions aren't allowed in patterns
+                   //~^ ERROR only char and numeric types are allowed in range patterns
+});
+
+fn main() {}
diff --git a/src/test/ui/pattern/patkind-litrange-no-expr.stderr b/src/test/ui/pattern/patkind-litrange-no-expr.stderr
new file mode 100644
index 0000000..7474d32
--- /dev/null
+++ b/src/test/ui/pattern/patkind-litrange-no-expr.stderr
@@ -0,0 +1,18 @@
+error: arbitrary expressions aren't allowed in patterns
+  --> $DIR/patkind-litrange-no-expr.rs:20:13
+   |
+LL |     Arith = 1 + 1,
+   |             ^^^^^
+
+error[E0029]: only char and numeric types are allowed in range patterns
+  --> $DIR/patkind-litrange-no-expr.rs:20:13
+   |
+LL |     Arith = 1 + 1,
+   |             ^^^^^ ranges require char or numeric types
+   |
+   = note: start type: {integer}
+   = note: end type: {integer}
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0029`.
diff --git a/src/test/ui/pattern/pattern-binding-disambiguation.rs b/src/test/ui/pattern/pattern-binding-disambiguation.rs
new file mode 100644
index 0000000..2e80ea3
--- /dev/null
+++ b/src/test/ui/pattern/pattern-binding-disambiguation.rs
@@ -0,0 +1,57 @@
+struct UnitStruct;
+struct TupleStruct();
+struct BracedStruct{}
+
+enum E {
+    UnitVariant,
+    TupleVariant(),
+    BracedVariant{},
+}
+use E::*;
+
+const CONST: () = ();
+static STATIC: () = ();
+
+fn function() {}
+
+fn main() {
+    let doesnt_matter = 0;
+
+    match UnitStruct {
+        UnitStruct => {} // OK, `UnitStruct` is a unit struct pattern
+    }
+    match doesnt_matter {
+        TupleStruct => {} //~ ERROR match bindings cannot shadow tuple structs
+    }
+    match doesnt_matter {
+        BracedStruct => {} // OK, `BracedStruct` is a fresh binding
+    }
+    match UnitVariant {
+        UnitVariant => {} // OK, `UnitVariant` is a unit variant pattern
+    }
+    match doesnt_matter {
+        TupleVariant => {} //~ ERROR match bindings cannot shadow tuple variants
+    }
+    match doesnt_matter {
+        BracedVariant => {} //~ ERROR match bindings cannot shadow struct variants
+    }
+    match CONST {
+        CONST => {} // OK, `CONST` is a const pattern
+    }
+    match doesnt_matter {
+        STATIC => {} //~ ERROR match bindings cannot shadow statics
+    }
+    match doesnt_matter {
+        function => {} // OK, `function` is a fresh binding
+    }
+
+    let UnitStruct = UnitStruct; // OK, `UnitStruct` is a unit struct pattern
+    let TupleStruct = doesnt_matter; //~ ERROR let bindings cannot shadow tuple structs
+    let BracedStruct = doesnt_matter; // OK, `BracedStruct` is a fresh binding
+    let UnitVariant = UnitVariant; // OK, `UnitVariant` is a unit variant pattern
+    let TupleVariant = doesnt_matter; //~ ERROR let bindings cannot shadow tuple variants
+    let BracedVariant = doesnt_matter; //~ ERROR let bindings cannot shadow struct variants
+    let CONST = CONST; // OK, `CONST` is a const pattern
+    let STATIC = doesnt_matter; //~ ERROR let bindings cannot shadow statics
+    let function = doesnt_matter; // OK, `function` is a fresh binding
+}
diff --git a/src/test/ui/pattern/pattern-binding-disambiguation.stderr b/src/test/ui/pattern/pattern-binding-disambiguation.stderr
new file mode 100644
index 0000000..faa0d7c
--- /dev/null
+++ b/src/test/ui/pattern/pattern-binding-disambiguation.stderr
@@ -0,0 +1,75 @@
+error[E0530]: match bindings cannot shadow tuple structs
+  --> $DIR/pattern-binding-disambiguation.rs:24:9
+   |
+LL | struct TupleStruct();
+   | --------------------- the tuple struct `TupleStruct` is defined here
+...
+LL |         TupleStruct => {}
+   |         ^^^^^^^^^^^ cannot be named the same as a tuple struct
+
+error[E0530]: match bindings cannot shadow tuple variants
+  --> $DIR/pattern-binding-disambiguation.rs:33:9
+   |
+LL | use E::*;
+   |     ---- the tuple variant `TupleVariant` is imported here
+...
+LL |         TupleVariant => {}
+   |         ^^^^^^^^^^^^ cannot be named the same as a tuple variant
+
+error[E0530]: match bindings cannot shadow struct variants
+  --> $DIR/pattern-binding-disambiguation.rs:36:9
+   |
+LL | use E::*;
+   |     ---- the struct variant `BracedVariant` is imported here
+...
+LL |         BracedVariant => {}
+   |         ^^^^^^^^^^^^^ cannot be named the same as a struct variant
+
+error[E0530]: match bindings cannot shadow statics
+  --> $DIR/pattern-binding-disambiguation.rs:42:9
+   |
+LL | static STATIC: () = ();
+   | ----------------------- the static `STATIC` is defined here
+...
+LL |         STATIC => {}
+   |         ^^^^^^ cannot be named the same as a static
+
+error[E0530]: let bindings cannot shadow tuple structs
+  --> $DIR/pattern-binding-disambiguation.rs:49:9
+   |
+LL | struct TupleStruct();
+   | --------------------- the tuple struct `TupleStruct` is defined here
+...
+LL |     let TupleStruct = doesnt_matter;
+   |         ^^^^^^^^^^^ cannot be named the same as a tuple struct
+
+error[E0530]: let bindings cannot shadow tuple variants
+  --> $DIR/pattern-binding-disambiguation.rs:52:9
+   |
+LL | use E::*;
+   |     ---- the tuple variant `TupleVariant` is imported here
+...
+LL |     let TupleVariant = doesnt_matter;
+   |         ^^^^^^^^^^^^ cannot be named the same as a tuple variant
+
+error[E0530]: let bindings cannot shadow struct variants
+  --> $DIR/pattern-binding-disambiguation.rs:53:9
+   |
+LL | use E::*;
+   |     ---- the struct variant `BracedVariant` is imported here
+...
+LL |     let BracedVariant = doesnt_matter;
+   |         ^^^^^^^^^^^^^ cannot be named the same as a struct variant
+
+error[E0530]: let bindings cannot shadow statics
+  --> $DIR/pattern-binding-disambiguation.rs:55:9
+   |
+LL | static STATIC: () = ();
+   | ----------------------- the static `STATIC` is defined here
+...
+LL |     let STATIC = doesnt_matter;
+   |         ^^^^^^ cannot be named the same as a static
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0530`.
diff --git a/src/test/ui/pattern/pattern-bindings-after-at.rs b/src/test/ui/pattern/pattern-bindings-after-at.rs
new file mode 100644
index 0000000..4a24a49
--- /dev/null
+++ b/src/test/ui/pattern/pattern-bindings-after-at.rs
@@ -0,0 +1,15 @@
+enum Option<T> {
+    None,
+    Some(T),
+}
+
+fn main() {
+    match &mut Some(1) {
+        ref mut z @ &mut Some(ref a) => {
+        //~^ ERROR pattern bindings are not allowed after an `@`
+            **z = None;
+            println!("{}", *a);
+        }
+        _ => ()
+    }
+}
diff --git a/src/test/ui/pattern/pattern-bindings-after-at.stderr b/src/test/ui/pattern/pattern-bindings-after-at.stderr
new file mode 100644
index 0000000..7a3883c
--- /dev/null
+++ b/src/test/ui/pattern/pattern-bindings-after-at.stderr
@@ -0,0 +1,9 @@
+error[E0303]: pattern bindings are not allowed after an `@`
+  --> $DIR/pattern-bindings-after-at.rs:8:31
+   |
+LL |         ref mut z @ &mut Some(ref a) => {
+   |                               ^^^^^ not allowed after `@`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0303`.
diff --git a/src/test/ui/pattern/pattern-error-continue.rs b/src/test/ui/pattern/pattern-error-continue.rs
new file mode 100644
index 0000000..7e79868
--- /dev/null
+++ b/src/test/ui/pattern/pattern-error-continue.rs
@@ -0,0 +1,37 @@
+// Test that certain pattern-match type errors are non-fatal
+
+enum A {
+    B(isize, isize),
+    C(isize, isize, isize),
+    D
+}
+
+struct S {
+    a: isize
+}
+
+fn f(_c: char) {}
+
+fn main() {
+    match A::B(1, 2) {
+        A::B(_, _, _) => (), //~ ERROR this pattern has 3 fields, but
+        A::D(_) => (),       //~ ERROR expected tuple struct/variant, found unit variant `A::D`
+        _ => ()
+    }
+    match 'c' {
+        S { .. } => (),
+        //~^ ERROR mismatched types
+        //~| expected type `char`
+        //~| found type `S`
+        //~| expected char, found struct `S`
+
+        _ => ()
+    }
+    f(true);
+    //~^ ERROR mismatched types
+    //~| expected char, found bool
+
+    match () {
+        E::V => {} //~ ERROR failed to resolve: use of undeclared type or module `E`
+    }
+}
diff --git a/src/test/ui/pattern/pattern-error-continue.stderr b/src/test/ui/pattern/pattern-error-continue.stderr
new file mode 100644
index 0000000..11e0c31
--- /dev/null
+++ b/src/test/ui/pattern/pattern-error-continue.stderr
@@ -0,0 +1,41 @@
+error[E0433]: failed to resolve: use of undeclared type or module `E`
+  --> $DIR/pattern-error-continue.rs:35:9
+   |
+LL |         E::V => {}
+   |         ^ use of undeclared type or module `E`
+
+error[E0532]: expected tuple struct/variant, found unit variant `A::D`
+  --> $DIR/pattern-error-continue.rs:18:9
+   |
+LL |         A::D(_) => (),
+   |         ^^^-
+   |            |
+   |            help: a tuple variant with a similar name exists: `B`
+
+error[E0023]: this pattern has 3 fields, but the corresponding tuple variant has 2 fields
+  --> $DIR/pattern-error-continue.rs:17:9
+   |
+LL |         A::B(_, _, _) => (),
+   |         ^^^^^^^^^^^^^ expected 2 fields, found 3
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-error-continue.rs:22:9
+   |
+LL |     match 'c' {
+   |           --- this match expression has type `char`
+LL |         S { .. } => (),
+   |         ^^^^^^^^ expected char, found struct `S`
+   |
+   = note: expected type `char`
+              found type `S`
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-error-continue.rs:30:7
+   |
+LL |     f(true);
+   |       ^^^^ expected char, found bool
+
+error: aborting due to 5 previous errors
+
+Some errors occurred: E0023, E0308, E0433, E0532.
+For more information about an error, try `rustc --explain E0023`.
diff --git a/src/test/ui/pattern/pattern-ident-path-generics.rs b/src/test/ui/pattern/pattern-ident-path-generics.rs
new file mode 100644
index 0000000..48c0262
--- /dev/null
+++ b/src/test/ui/pattern/pattern-ident-path-generics.rs
@@ -0,0 +1,6 @@
+fn main() {
+    match Some("foo") {
+        None::<isize> => {}   //~ ERROR mismatched types
+        Some(_) => {}
+    }
+}
diff --git a/src/test/ui/pattern/pattern-ident-path-generics.stderr b/src/test/ui/pattern/pattern-ident-path-generics.stderr
new file mode 100644
index 0000000..bfc10c5
--- /dev/null
+++ b/src/test/ui/pattern/pattern-ident-path-generics.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/pattern-ident-path-generics.rs:3:9
+   |
+LL |         None::<isize> => {}
+   |         ^^^^^^^^^^^^^ expected &str, found isize
+   |
+   = note: expected type `std::option::Option<&str>`
+              found type `std::option::Option<isize>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/pattern/pattern-tyvar-2.rs b/src/test/ui/pattern/pattern-tyvar-2.rs
new file mode 100644
index 0000000..9fba9cb
--- /dev/null
+++ b/src/test/ui/pattern/pattern-tyvar-2.rs
@@ -0,0 +1,6 @@
+enum Bar { T1((), Option<Vec<isize>>), T2, }
+
+fn foo(t: Bar) -> isize { match t { Bar::T1(_, Some(x)) => { return x * 3; } _ => { panic!(); } } }
+//~^ ERROR binary operation `*` cannot be applied to
+
+fn main() { }
diff --git a/src/test/ui/pattern/pattern-tyvar-2.stderr b/src/test/ui/pattern/pattern-tyvar-2.stderr
new file mode 100644
index 0000000..7c6ae49
--- /dev/null
+++ b/src/test/ui/pattern/pattern-tyvar-2.stderr
@@ -0,0 +1,13 @@
+error[E0369]: binary operation `*` cannot be applied to type `std::vec::Vec<isize>`
+  --> $DIR/pattern-tyvar-2.rs:3:71
+   |
+LL | fn foo(t: Bar) -> isize { match t { Bar::T1(_, Some(x)) => { return x * 3; } _ => { panic!(); } } }
+   |                                                                     - ^ - {integer}
+   |                                                                     |
+   |                                                                     std::vec::Vec<isize>
+   |
+   = note: an implementation of `std::ops::Mul` might be missing for `std::vec::Vec<isize>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0369`.
diff --git a/src/test/ui/pattern/pattern-tyvar.rs b/src/test/ui/pattern/pattern-tyvar.rs
new file mode 100644
index 0000000..e2cbf05
--- /dev/null
+++ b/src/test/ui/pattern/pattern-tyvar.rs
@@ -0,0 +1,12 @@
+enum Bar { T1((), Option<Vec<isize>>), T2 }
+
+fn foo(t: Bar) {
+    match t {
+      Bar::T1(_, Some::<isize>(x)) => { //~ ERROR mismatched types
+        println!("{}", x);
+      }
+      _ => { panic!(); }
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/pattern/pattern-tyvar.stderr b/src/test/ui/pattern/pattern-tyvar.stderr
new file mode 100644
index 0000000..5483470
--- /dev/null
+++ b/src/test/ui/pattern/pattern-tyvar.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/pattern-tyvar.rs:5:18
+   |
+LL |     match t {
+   |           - this match expression has type `std::option::Option<std::vec::Vec<isize>>`
+LL |       Bar::T1(_, Some::<isize>(x)) => {
+   |                  ^^^^^^^^^^^^^^^^ expected struct `std::vec::Vec`, found isize
+   |
+   = note: expected type `std::option::Option<std::vec::Vec<isize>>`
+              found type `std::option::Option<isize>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/pattern/slice-pattern-const-2.rs b/src/test/ui/pattern/slice-pattern-const-2.rs
new file mode 100644
index 0000000..6cfef11
--- /dev/null
+++ b/src/test/ui/pattern/slice-pattern-const-2.rs
@@ -0,0 +1,31 @@
+#![deny(unreachable_patterns)]
+
+fn main() {
+    let s = &[0x00; 4][..]; //Slice of any value
+    const MAGIC_TEST: &[u32] = &[4, 5, 6, 7]; //Const slice to pattern match with
+    match s {
+        MAGIC_TEST => (),
+        [0x00, 0x00, 0x00, 0x00] => (),
+        [4, 5, 6, 7] => (), //~ ERROR unreachable pattern
+        _ => (),
+    }
+    match s {
+        [0x00, 0x00, 0x00, 0x00] => (),
+        MAGIC_TEST => (),
+        [4, 5, 6, 7] => (), //~ ERROR unreachable pattern
+        _ => (),
+    }
+    match s {
+        [0x00, 0x00, 0x00, 0x00] => (),
+        [4, 5, 6, 7] => (),
+        MAGIC_TEST => (), // FIXME(oli-obk): this should warn, but currently does not
+        _ => (),
+    }
+    const FOO: [u32; 1] = [4];
+    match [99] {
+        [0x00] => (),
+        [4] => (),
+        FOO => (), //~ ERROR unreachable pattern
+        _ => (),
+    }
+}
diff --git a/src/test/ui/pattern/slice-pattern-const-2.stderr b/src/test/ui/pattern/slice-pattern-const-2.stderr
new file mode 100644
index 0000000..e2c408a
--- /dev/null
+++ b/src/test/ui/pattern/slice-pattern-const-2.stderr
@@ -0,0 +1,26 @@
+error: unreachable pattern
+  --> $DIR/slice-pattern-const-2.rs:9:9
+   |
+LL |         [4, 5, 6, 7] => (),
+   |         ^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/slice-pattern-const-2.rs:1:9
+   |
+LL | #![deny(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/slice-pattern-const-2.rs:15:9
+   |
+LL |         [4, 5, 6, 7] => (),
+   |         ^^^^^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/slice-pattern-const-2.rs:28:9
+   |
+LL |         FOO => (),
+   |         ^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/pattern/slice-pattern-const-3.rs b/src/test/ui/pattern/slice-pattern-const-3.rs
new file mode 100644
index 0000000..8805c43
--- /dev/null
+++ b/src/test/ui/pattern/slice-pattern-const-3.rs
@@ -0,0 +1,31 @@
+#![deny(unreachable_patterns)]
+
+fn main() {
+    let s = &["0x00"; 4][..]; //Slice of any value
+    const MAGIC_TEST: &[&str] = &["4", "5", "6", "7"]; //Const slice to pattern match with
+    match s {
+        MAGIC_TEST => (),
+        ["0x00", "0x00", "0x00", "0x00"] => (),
+        ["4", "5", "6", "7"] => (), // FIXME(oli-obk): this should warn, but currently does not
+        _ => (),
+    }
+    match s {
+        ["0x00", "0x00", "0x00", "0x00"] => (),
+        MAGIC_TEST => (),
+        ["4", "5", "6", "7"] => (), // FIXME(oli-obk): this should warn, but currently does not
+        _ => (),
+    }
+    match s {
+        ["0x00", "0x00", "0x00", "0x00"] => (),
+        ["4", "5", "6", "7"] => (),
+        MAGIC_TEST => (), // FIXME(oli-obk): this should warn, but currently does not
+        _ => (),
+    }
+    const FOO: [&str; 1] = ["boo"];
+    match ["baa"] {
+        ["0x00"] => (),
+        ["boo"] => (),
+        FOO => (), //~ ERROR unreachable pattern
+        _ => (),
+    }
+}
diff --git a/src/test/ui/pattern/slice-pattern-const-3.stderr b/src/test/ui/pattern/slice-pattern-const-3.stderr
new file mode 100644
index 0000000..eab4fc3
--- /dev/null
+++ b/src/test/ui/pattern/slice-pattern-const-3.stderr
@@ -0,0 +1,14 @@
+error: unreachable pattern
+  --> $DIR/slice-pattern-const-3.rs:28:9
+   |
+LL |         FOO => (),
+   |         ^^^
+   |
+note: lint level defined here
+  --> $DIR/slice-pattern-const-3.rs:1:9
+   |
+LL | #![deny(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/pattern/slice-pattern-const.rs b/src/test/ui/pattern/slice-pattern-const.rs
new file mode 100644
index 0000000..f0a0451
--- /dev/null
+++ b/src/test/ui/pattern/slice-pattern-const.rs
@@ -0,0 +1,47 @@
+#![deny(unreachable_patterns)]
+
+fn main() {
+    let s = &[0x00; 4][..]; //Slice of any value
+    const MAGIC_TEST: &[u8] = b"TEST"; //Const slice to pattern match with
+    match s {
+        MAGIC_TEST => (),
+        [0x00, 0x00, 0x00, 0x00] => (),
+        [84, 69, 83, 84] => (), //~ ERROR unreachable pattern
+        _ => (),
+    }
+    match s {
+        [0x00, 0x00, 0x00, 0x00] => (),
+        MAGIC_TEST => (),
+        [84, 69, 83, 84] => (), //~ ERROR unreachable pattern
+        _ => (),
+    }
+    match s {
+        [0x00, 0x00, 0x00, 0x00] => (),
+        [84, 69, 83, 84] => (),
+        MAGIC_TEST => (), //~ ERROR unreachable pattern
+        _ => (),
+    }
+    const FOO: [u8; 1] = [4];
+    match [99] {
+        [0x00] => (),
+        [4] => (),
+        FOO => (), //~ ERROR unreachable pattern
+        _ => (),
+    }
+    const BAR: &[u8; 1] = &[4];
+    match &[99] {
+        [0x00] => (),
+        [4] => (),
+        BAR => (), //~ ERROR unreachable pattern
+        b"a" => (),
+        _ => (),
+    }
+
+    const BOO: &[u8; 0] = &[];
+    match &[] {
+        [] => (),
+        BOO => (), //~ ERROR unreachable pattern
+        b"" => (), //~ ERROR unreachable pattern
+        _ => (), //~ ERROR unreachable pattern
+    }
+}
diff --git a/src/test/ui/pattern/slice-pattern-const.stderr b/src/test/ui/pattern/slice-pattern-const.stderr
new file mode 100644
index 0000000..2dd10a0
--- /dev/null
+++ b/src/test/ui/pattern/slice-pattern-const.stderr
@@ -0,0 +1,56 @@
+error: unreachable pattern
+  --> $DIR/slice-pattern-const.rs:9:9
+   |
+LL |         [84, 69, 83, 84] => (),
+   |         ^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/slice-pattern-const.rs:1:9
+   |
+LL | #![deny(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/slice-pattern-const.rs:15:9
+   |
+LL |         [84, 69, 83, 84] => (),
+   |         ^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/slice-pattern-const.rs:21:9
+   |
+LL |         MAGIC_TEST => (),
+   |         ^^^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/slice-pattern-const.rs:28:9
+   |
+LL |         FOO => (),
+   |         ^^^
+
+error: unreachable pattern
+  --> $DIR/slice-pattern-const.rs:35:9
+   |
+LL |         BAR => (),
+   |         ^^^
+
+error: unreachable pattern
+  --> $DIR/slice-pattern-const.rs:43:9
+   |
+LL |         BOO => (),
+   |         ^^^
+
+error: unreachable pattern
+  --> $DIR/slice-pattern-const.rs:44:9
+   |
+LL |         b"" => (),
+   |         ^^^
+
+error: unreachable pattern
+  --> $DIR/slice-pattern-const.rs:45:9
+   |
+LL |         _ => (),
+   |         ^
+
+error: aborting due to 8 previous errors
+
diff --git a/src/test/ui/phantom-oibit.rs b/src/test/ui/phantom-oibit.rs
new file mode 100644
index 0000000..04291a7
--- /dev/null
+++ b/src/test/ui/phantom-oibit.rs
@@ -0,0 +1,30 @@
+// Ensure that OIBIT checks `T` when it encounters a `PhantomData<T>` field, instead of checking
+// the `PhantomData<T>` type itself (which almost always implements an auto trait)
+
+#![feature(optin_builtin_traits)]
+
+use std::marker::{PhantomData};
+
+unsafe auto trait Zen {}
+
+unsafe impl<'a, T: 'a> Zen for &'a T where T: Sync {}
+
+struct Guard<'a, T: 'a> {
+    _marker: PhantomData<&'a T>,
+}
+
+struct Nested<T>(T);
+
+fn is_zen<T: Zen>(_: T) {}
+
+fn not_sync<T>(x: Guard<T>) {
+    is_zen(x)
+    //~^ ERROR `T` cannot be shared between threads safely [E0277]
+}
+
+fn nested_not_sync<T>(x: Nested<Guard<T>>) {
+    is_zen(x)
+    //~^ ERROR `T` cannot be shared between threads safely [E0277]
+}
+
+fn main() {}
diff --git a/src/test/ui/phantom-oibit.stderr b/src/test/ui/phantom-oibit.stderr
new file mode 100644
index 0000000..ec8b318
--- /dev/null
+++ b/src/test/ui/phantom-oibit.stderr
@@ -0,0 +1,38 @@
+error[E0277]: `T` cannot be shared between threads safely
+  --> $DIR/phantom-oibit.rs:21:5
+   |
+LL |     is_zen(x)
+   |     ^^^^^^ `T` cannot be shared between threads safely
+   |
+   = help: the trait `std::marker::Sync` is not implemented for `T`
+   = help: consider adding a `where T: std::marker::Sync` bound
+   = note: required because of the requirements on the impl of `Zen` for `&T`
+   = note: required because it appears within the type `std::marker::PhantomData<&T>`
+   = note: required because it appears within the type `Guard<'_, T>`
+note: required by `is_zen`
+  --> $DIR/phantom-oibit.rs:18:1
+   |
+LL | fn is_zen<T: Zen>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: `T` cannot be shared between threads safely
+  --> $DIR/phantom-oibit.rs:26:5
+   |
+LL |     is_zen(x)
+   |     ^^^^^^ `T` cannot be shared between threads safely
+   |
+   = help: the trait `std::marker::Sync` is not implemented for `T`
+   = help: consider adding a `where T: std::marker::Sync` bound
+   = note: required because of the requirements on the impl of `Zen` for `&T`
+   = note: required because it appears within the type `std::marker::PhantomData<&T>`
+   = note: required because it appears within the type `Guard<'_, T>`
+   = note: required because it appears within the type `Nested<Guard<'_, T>>`
+note: required by `is_zen`
+  --> $DIR/phantom-oibit.rs:18:1
+   |
+LL | fn is_zen<T: Zen>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/placement-syntax.rs b/src/test/ui/placement-syntax.rs
new file mode 100644
index 0000000..ac6fed1
--- /dev/null
+++ b/src/test/ui/placement-syntax.rs
@@ -0,0 +1,7 @@
+fn main() {
+    let x = -5;
+    if x<-1 {
+    //~^ ERROR emplacement syntax is obsolete
+        println!("ok");
+    }
+}
diff --git a/src/test/ui/placement-syntax.stderr b/src/test/ui/placement-syntax.stderr
new file mode 100644
index 0000000..350aaa9
--- /dev/null
+++ b/src/test/ui/placement-syntax.stderr
@@ -0,0 +1,14 @@
+error: emplacement syntax is obsolete (for now, anyway)
+  --> $DIR/placement-syntax.rs:3:8
+   |
+LL |     if x<-1 {
+   |        ^^^^
+   |
+   = note: for more information, see <https://github.com/rust-lang/rust/issues/27779#issuecomment-378416911>
+help: if you meant to write a comparison against a negative value, add a space in between `<` and `-`
+   |
+LL |     if x< -1 {
+   |         ^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/point-to-type-err-cause-on-impl-trait-return-2.rs b/src/test/ui/point-to-type-err-cause-on-impl-trait-return-2.rs
new file mode 100644
index 0000000..50f1fe8
--- /dev/null
+++ b/src/test/ui/point-to-type-err-cause-on-impl-trait-return-2.rs
@@ -0,0 +1,17 @@
+fn unrelated() -> Result<(), std::string::ParseError> {  // #57664
+    let x = 0;
+
+    match x {
+        1 => {
+            let property_value_as_string = "a".parse()?;
+        }
+        2 => {
+            let value: &bool = unsafe { &42 };
+            //~^ ERROR mismatched types
+        }
+    };
+
+    Ok(())
+}
+
+fn main() {}
diff --git a/src/test/ui/point-to-type-err-cause-on-impl-trait-return-2.stderr b/src/test/ui/point-to-type-err-cause-on-impl-trait-return-2.stderr
new file mode 100644
index 0000000..edaa60e
--- /dev/null
+++ b/src/test/ui/point-to-type-err-cause-on-impl-trait-return-2.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/point-to-type-err-cause-on-impl-trait-return-2.rs:9:41
+   |
+LL |             let value: &bool = unsafe { &42 };
+   |                                         ^^^ expected bool, found integer
+   |
+   = note: expected type `&bool`
+              found type `&{integer}`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/point-to-type-err-cause-on-impl-trait-return.rs b/src/test/ui/point-to-type-err-cause-on-impl-trait-return.rs
new file mode 100644
index 0000000..95b4036
--- /dev/null
+++ b/src/test/ui/point-to-type-err-cause-on-impl-trait-return.rs
@@ -0,0 +1,36 @@
+fn foo() -> impl std::fmt::Display {
+    if false {
+        return 0i32;
+    }
+    1u32
+    //~^ ERROR mismatched types
+}
+
+fn bar() -> impl std::fmt::Display {
+    if false {
+        return 0i32;
+    } else {
+        return 1u32;
+        //~^ ERROR mismatched types
+    }
+}
+
+fn baz() -> impl std::fmt::Display {
+    if false {
+    //~^ ERROR mismatched types
+        return 0i32;
+    } else {
+        1u32
+    }
+}
+
+fn qux() -> impl std::fmt::Display {
+    if false {
+        0i32
+    } else {
+        1u32
+        //~^ ERROR if and else have incompatible types
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/point-to-type-err-cause-on-impl-trait-return.stderr b/src/test/ui/point-to-type-err-cause-on-impl-trait-return.stderr
new file mode 100644
index 0000000..ee1e360
--- /dev/null
+++ b/src/test/ui/point-to-type-err-cause-on-impl-trait-return.stderr
@@ -0,0 +1,66 @@
+error[E0308]: mismatched types
+  --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:5:5
+   |
+LL | fn foo() -> impl std::fmt::Display {
+   |             ---------------------- expected because this return type...
+LL |     if false {
+LL |         return 0i32;
+   |                ---- ...is found to be `i32` here
+LL |     }
+LL |     1u32
+   |     ^^^^ expected i32, found u32
+   |
+   = note: expected type `i32`
+              found type `u32`
+
+error[E0308]: mismatched types
+  --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:13:16
+   |
+LL | fn bar() -> impl std::fmt::Display {
+   |             ---------------------- expected because this return type...
+LL |     if false {
+LL |         return 0i32;
+   |                ---- ...is found to be `i32` here
+LL |     } else {
+LL |         return 1u32;
+   |                ^^^^ expected i32, found u32
+   |
+   = note: expected type `i32`
+              found type `u32`
+
+error[E0308]: mismatched types
+  --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:19:5
+   |
+LL |   fn baz() -> impl std::fmt::Display {
+   |               ---------------------- expected because this return type...
+LL | /     if false {
+LL | |
+LL | |         return 0i32;
+   | |                ---- ...is found to be `i32` here
+LL | |     } else {
+LL | |         1u32
+LL | |     }
+   | |_____^ expected i32, found u32
+   |
+   = note: expected type `i32`
+              found type `u32`
+
+error[E0308]: if and else have incompatible types
+  --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:31:9
+   |
+LL | /     if false {
+LL | |         0i32
+   | |         ---- expected because of this
+LL | |     } else {
+LL | |         1u32
+   | |         ^^^^ expected i32, found u32
+LL | |
+LL | |     }
+   | |_____- if and else have incompatible types
+   |
+   = note: expected type `i32`
+              found type `u32`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/pptypedef.rs b/src/test/ui/pptypedef.rs
new file mode 100644
index 0000000..80ebf02
--- /dev/null
+++ b/src/test/ui/pptypedef.rs
@@ -0,0 +1,11 @@
+fn let_in<T, F>(x: T, f: F) where F: FnOnce(T) {}
+
+fn main() {
+    let_in(3u32, |i| { assert!(i == 3i32); });
+    //~^ ERROR mismatched types
+    //~| expected u32, found i32
+
+    let_in(3i32, |i| { assert!(i == 3u32); });
+    //~^ ERROR mismatched types
+    //~| expected i32, found u32
+}
diff --git a/src/test/ui/pptypedef.stderr b/src/test/ui/pptypedef.stderr
new file mode 100644
index 0000000..32ee1a6
--- /dev/null
+++ b/src/test/ui/pptypedef.stderr
@@ -0,0 +1,15 @@
+error[E0308]: mismatched types
+  --> $DIR/pptypedef.rs:4:37
+   |
+LL |     let_in(3u32, |i| { assert!(i == 3i32); });
+   |                                     ^^^^ expected u32, found i32
+
+error[E0308]: mismatched types
+  --> $DIR/pptypedef.rs:8:37
+   |
+LL |     let_in(3i32, |i| { assert!(i == 3u32); });
+   |                                     ^^^^ expected i32, found u32
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/precise_pointer_size_matching.rs b/src/test/ui/precise_pointer_size_matching.rs
new file mode 100644
index 0000000..759b63b
--- /dev/null
+++ b/src/test/ui/precise_pointer_size_matching.rs
@@ -0,0 +1,33 @@
+// normalize-stderr-32bit: "-2147483648isize" -> "$$ISIZE_MIN"
+// normalize-stderr-64bit: "-9223372036854775808isize" -> "$$ISIZE_MIN"
+// normalize-stderr-32bit: "2147483647isize" -> "$$ISIZE_MAX"
+// normalize-stderr-64bit: "9223372036854775807isize" -> "$$ISIZE_MAX"
+// normalize-stderr-32bit: "4294967295usize" -> "$$USIZE_MAX"
+// normalize-stderr-64bit: "18446744073709551615usize" -> "$$USIZE_MAX"
+
+#![feature(precise_pointer_size_matching)]
+#![feature(exclusive_range_pattern)]
+
+#![deny(unreachable_patterns)]
+
+use std::{usize, isize};
+
+fn main() {
+    match 0isize {
+        isize::MIN ..= isize::MAX => {} // ok
+    }
+
+    match 0usize {
+        0 ..= usize::MAX => {} // ok
+    }
+
+    match 0isize { //~ ERROR non-exhaustive patterns
+        1 ..= 8 => {}
+        -5 ..= 20 => {}
+    }
+
+    match 0usize { //~ ERROR non-exhaustive patterns
+        1 ..= 8 => {}
+        5 ..= 20 => {}
+    }
+}
diff --git a/src/test/ui/precise_pointer_size_matching.stderr b/src/test/ui/precise_pointer_size_matching.stderr
new file mode 100644
index 0000000..6f0322f
--- /dev/null
+++ b/src/test/ui/precise_pointer_size_matching.stderr
@@ -0,0 +1,19 @@
+error[E0004]: non-exhaustive patterns: `$ISIZE_MIN..=-6isize` and `21isize..=$ISIZE_MAX` not covered
+  --> $DIR/precise_pointer_size_matching.rs:24:11
+   |
+LL |     match 0isize {
+   |           ^^^^^^ patterns `$ISIZE_MIN..=-6isize` and `21isize..=$ISIZE_MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `0usize` and `21usize..=$USIZE_MAX` not covered
+  --> $DIR/precise_pointer_size_matching.rs:29:11
+   |
+LL |     match 0usize {
+   |           ^^^^^^ patterns `0usize` and `21usize..=$USIZE_MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/prim-with-args.rs b/src/test/ui/prim-with-args.rs
new file mode 100644
index 0000000..e5beaca
--- /dev/null
+++ b/src/test/ui/prim-with-args.rs
@@ -0,0 +1,27 @@
+fn main() {
+
+let x: isize<isize>; //~ ERROR type arguments are not allowed for this type
+let x: i8<isize>; //~ ERROR type arguments are not allowed for this type
+let x: i16<isize>; //~ ERROR type arguments are not allowed for this type
+let x: i32<isize>; //~ ERROR type arguments are not allowed for this type
+let x: i64<isize>; //~ ERROR type arguments are not allowed for this type
+let x: usize<isize>; //~ ERROR type arguments are not allowed for this type
+let x: u8<isize>; //~ ERROR type arguments are not allowed for this type
+let x: u16<isize>; //~ ERROR type arguments are not allowed for this type
+let x: u32<isize>; //~ ERROR type arguments are not allowed for this type
+let x: u64<isize>; //~ ERROR type arguments are not allowed for this type
+let x: char<isize>; //~ ERROR type arguments are not allowed for this type
+
+let x: isize<'static>; //~ ERROR lifetime arguments are not allowed for this type
+let x: i8<'static>; //~ ERROR lifetime arguments are not allowed for this type
+let x: i16<'static>; //~ ERROR lifetime arguments are not allowed for this type
+let x: i32<'static>; //~ ERROR lifetime arguments are not allowed for this type
+let x: i64<'static>; //~ ERROR lifetime arguments are not allowed for this type
+let x: usize<'static>; //~ ERROR lifetime arguments are not allowed for this type
+let x: u8<'static>; //~ ERROR lifetime arguments are not allowed for this type
+let x: u16<'static>; //~ ERROR lifetime arguments are not allowed for this type
+let x: u32<'static>; //~ ERROR lifetime arguments are not allowed for this type
+let x: u64<'static>; //~ ERROR lifetime arguments are not allowed for this type
+let x: char<'static>; //~ ERROR lifetime arguments are not allowed for this type
+
+}
diff --git a/src/test/ui/prim-with-args.stderr b/src/test/ui/prim-with-args.stderr
new file mode 100644
index 0000000..4bde981
--- /dev/null
+++ b/src/test/ui/prim-with-args.stderr
@@ -0,0 +1,135 @@
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/prim-with-args.rs:3:14
+   |
+LL | let x: isize<isize>;
+   |              ^^^^^ type argument not allowed
+
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/prim-with-args.rs:4:11
+   |
+LL | let x: i8<isize>;
+   |           ^^^^^ type argument not allowed
+
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/prim-with-args.rs:5:12
+   |
+LL | let x: i16<isize>;
+   |            ^^^^^ type argument not allowed
+
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/prim-with-args.rs:6:12
+   |
+LL | let x: i32<isize>;
+   |            ^^^^^ type argument not allowed
+
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/prim-with-args.rs:7:12
+   |
+LL | let x: i64<isize>;
+   |            ^^^^^ type argument not allowed
+
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/prim-with-args.rs:8:14
+   |
+LL | let x: usize<isize>;
+   |              ^^^^^ type argument not allowed
+
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/prim-with-args.rs:9:11
+   |
+LL | let x: u8<isize>;
+   |           ^^^^^ type argument not allowed
+
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/prim-with-args.rs:10:12
+   |
+LL | let x: u16<isize>;
+   |            ^^^^^ type argument not allowed
+
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/prim-with-args.rs:11:12
+   |
+LL | let x: u32<isize>;
+   |            ^^^^^ type argument not allowed
+
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/prim-with-args.rs:12:12
+   |
+LL | let x: u64<isize>;
+   |            ^^^^^ type argument not allowed
+
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/prim-with-args.rs:13:13
+   |
+LL | let x: char<isize>;
+   |             ^^^^^ type argument not allowed
+
+error[E0109]: lifetime arguments are not allowed for this type
+  --> $DIR/prim-with-args.rs:15:14
+   |
+LL | let x: isize<'static>;
+   |              ^^^^^^^ lifetime argument not allowed
+
+error[E0109]: lifetime arguments are not allowed for this type
+  --> $DIR/prim-with-args.rs:16:11
+   |
+LL | let x: i8<'static>;
+   |           ^^^^^^^ lifetime argument not allowed
+
+error[E0109]: lifetime arguments are not allowed for this type
+  --> $DIR/prim-with-args.rs:17:12
+   |
+LL | let x: i16<'static>;
+   |            ^^^^^^^ lifetime argument not allowed
+
+error[E0109]: lifetime arguments are not allowed for this type
+  --> $DIR/prim-with-args.rs:18:12
+   |
+LL | let x: i32<'static>;
+   |            ^^^^^^^ lifetime argument not allowed
+
+error[E0109]: lifetime arguments are not allowed for this type
+  --> $DIR/prim-with-args.rs:19:12
+   |
+LL | let x: i64<'static>;
+   |            ^^^^^^^ lifetime argument not allowed
+
+error[E0109]: lifetime arguments are not allowed for this type
+  --> $DIR/prim-with-args.rs:20:14
+   |
+LL | let x: usize<'static>;
+   |              ^^^^^^^ lifetime argument not allowed
+
+error[E0109]: lifetime arguments are not allowed for this type
+  --> $DIR/prim-with-args.rs:21:11
+   |
+LL | let x: u8<'static>;
+   |           ^^^^^^^ lifetime argument not allowed
+
+error[E0109]: lifetime arguments are not allowed for this type
+  --> $DIR/prim-with-args.rs:22:12
+   |
+LL | let x: u16<'static>;
+   |            ^^^^^^^ lifetime argument not allowed
+
+error[E0109]: lifetime arguments are not allowed for this type
+  --> $DIR/prim-with-args.rs:23:12
+   |
+LL | let x: u32<'static>;
+   |            ^^^^^^^ lifetime argument not allowed
+
+error[E0109]: lifetime arguments are not allowed for this type
+  --> $DIR/prim-with-args.rs:24:12
+   |
+LL | let x: u64<'static>;
+   |            ^^^^^^^ lifetime argument not allowed
+
+error[E0109]: lifetime arguments are not allowed for this type
+  --> $DIR/prim-with-args.rs:25:13
+   |
+LL | let x: char<'static>;
+   |             ^^^^^^^ lifetime argument not allowed
+
+error: aborting due to 22 previous errors
+
+For more information about this error, try `rustc --explain E0109`.
diff --git a/src/test/ui/primitive-binop-lhs-mut.rs b/src/test/ui/primitive-binop-lhs-mut.rs
new file mode 100644
index 0000000..4f1c456
--- /dev/null
+++ b/src/test/ui/primitive-binop-lhs-mut.rs
@@ -0,0 +1,6 @@
+// run-pass
+
+fn main() {
+    let x = Box::new(0);
+    assert_eq!(0, *x + { drop(x); let _ = Box::new(main); 0 });
+}
diff --git a/src/test/ui/print-fuel/print-fuel.rs b/src/test/ui/print-fuel/print-fuel.rs
new file mode 100644
index 0000000..1bd3924
--- /dev/null
+++ b/src/test/ui/print-fuel/print-fuel.rs
@@ -0,0 +1,13 @@
+#![crate_name="foo"]
+#![allow(dead_code)]
+
+// (#55495: The --error-format is to sidestep an issue in our test harness)
+// compile-flags: --error-format human -Z print-fuel=foo
+// compile-pass
+
+struct S1(u8, u16, u8);
+struct S2(u8, u16, u8);
+struct S3(u8, u16, u8);
+
+fn main() {
+}
diff --git a/src/test/ui/print-fuel/print-fuel.stderr b/src/test/ui/print-fuel/print-fuel.stderr
new file mode 100644
index 0000000..cc88cc0
--- /dev/null
+++ b/src/test/ui/print-fuel/print-fuel.stderr
@@ -0,0 +1 @@
+Fuel used by foo: 3
diff --git a/src/test/ui/print_type_sizes/anonymous.rs b/src/test/ui/print_type_sizes/anonymous.rs
new file mode 100644
index 0000000..4d2a0e2
--- /dev/null
+++ b/src/test/ui/print_type_sizes/anonymous.rs
@@ -0,0 +1,23 @@
+// compile-flags: -Z print-type-sizes
+// compile-pass
+
+// All of the types that occur in this function are uninteresting, in
+// that one cannot control the sizes of these types with the same sort
+// of enum-variant manipulation tricks.
+
+#![feature(start)]
+
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
+    let _byte: u8 = 0;
+    let _word: usize = 0;
+    let _tuple: (u8, usize)= (0, 0);
+    let _array: [u8; 128] = [0; 128];
+    let _fn: fn (u8) -> u8 = id;
+    let _diverging: fn (u8) -> ! = bye;
+
+    fn id(x: u8) -> u8 { x };
+    fn bye(_: u8) -> ! { loop { } }
+
+    0
+}
diff --git a/src/test/ui/print_type_sizes/generics.rs b/src/test/ui/print_type_sizes/generics.rs
new file mode 100644
index 0000000..360c995
--- /dev/null
+++ b/src/test/ui/print_type_sizes/generics.rs
@@ -0,0 +1,68 @@
+// compile-flags: -Z print-type-sizes
+// compile-pass
+
+// This file illustrates how generics are handled: types have to be
+// monomorphized, in the MIR of the original function in which they
+// occur, to have their size reported.
+
+#![feature(start)]
+
+// In an ad-hoc attempt to avoid the injection of unwinding code
+// (which clutters the output of `-Z print-type-sizes` with types from
+// `unwind::libunwind`):
+//
+//   * I am not using Default to build values because that seems to
+//     cause the injection of unwinding code. (Instead I just make `fn new`
+//     methods.)
+//
+//   * Pair derive Copy to ensure that we don't inject
+//     unwinding code into generic uses of Pair when T itself is also
+//     Copy.
+//
+//     (I suspect this reflect some naivety within the rust compiler
+//      itself; it should be checking for drop glue, i.e., a destructor
+//      somewhere in the monomorphized types. It should not matter whether
+//      the type is Copy.)
+#[derive(Copy, Clone)]
+pub struct Pair<T> {
+    _car: T,
+    _cdr: T,
+}
+
+impl<T> Pair<T> {
+    fn new(a: T, d: T) -> Self {
+        Pair {
+            _car: a,
+            _cdr: d,
+        }
+    }
+}
+
+#[derive(Copy, Clone)]
+pub struct SevenBytes([u8; 7]);
+pub struct FiftyBytes([u8; 50]);
+
+pub struct ZeroSized;
+
+impl SevenBytes {
+    fn new() -> Self { SevenBytes([0; 7]) }
+}
+
+impl FiftyBytes {
+    fn new() -> Self { FiftyBytes([0; 50]) }
+}
+
+pub fn f1<T:Copy>(x: T) {
+    let _v: Pair<T> = Pair::new(x, x);
+    let _v2: Pair<FiftyBytes> =
+        Pair::new(FiftyBytes::new(), FiftyBytes::new());
+}
+
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
+    let _b: Pair<u8> = Pair::new(0, 0);
+    let _s: Pair<SevenBytes> = Pair::new(SevenBytes::new(), SevenBytes::new());
+    let ref _z: ZeroSized = ZeroSized;
+    f1::<SevenBytes>(SevenBytes::new());
+    0
+}
diff --git a/src/test/ui/print_type_sizes/generics.stdout b/src/test/ui/print_type_sizes/generics.stdout
new file mode 100644
index 0000000..0f02f39
--- /dev/null
+++ b/src/test/ui/print_type_sizes/generics.stdout
@@ -0,0 +1,14 @@
+print-type-size type: `Pair<FiftyBytes>`: 100 bytes, alignment: 1 bytes
+print-type-size     field `._car`: 50 bytes
+print-type-size     field `._cdr`: 50 bytes
+print-type-size type: `FiftyBytes`: 50 bytes, alignment: 1 bytes
+print-type-size     field `.0`: 50 bytes
+print-type-size type: `Pair<SevenBytes>`: 14 bytes, alignment: 1 bytes
+print-type-size     field `._car`: 7 bytes
+print-type-size     field `._cdr`: 7 bytes
+print-type-size type: `SevenBytes`: 7 bytes, alignment: 1 bytes
+print-type-size     field `.0`: 7 bytes
+print-type-size type: `Pair<u8>`: 2 bytes, alignment: 1 bytes
+print-type-size     field `._car`: 1 bytes
+print-type-size     field `._cdr`: 1 bytes
+print-type-size type: `ZeroSized`: 0 bytes, alignment: 1 bytes
diff --git a/src/test/ui/print_type_sizes/multiple_types.rs b/src/test/ui/print_type_sizes/multiple_types.rs
new file mode 100644
index 0000000..1b1d817
--- /dev/null
+++ b/src/test/ui/print_type_sizes/multiple_types.rs
@@ -0,0 +1,23 @@
+// compile-flags: -Z print-type-sizes
+// compile-pass
+
+// This file illustrates that when multiple structural types occur in
+// a function, every one of them is included in the output.
+
+#![feature(start)]
+
+pub struct SevenBytes([u8;  7]);
+pub struct FiftyBytes([u8; 50]);
+
+pub enum Enum {
+    Small(SevenBytes),
+    Large(FiftyBytes),
+}
+
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
+    let _e: Enum;
+    let _f: FiftyBytes;
+    let _s: SevenBytes;
+    0
+}
diff --git a/src/test/ui/print_type_sizes/multiple_types.stdout b/src/test/ui/print_type_sizes/multiple_types.stdout
new file mode 100644
index 0000000..eed9af2
--- /dev/null
+++ b/src/test/ui/print_type_sizes/multiple_types.stdout
@@ -0,0 +1,10 @@
+print-type-size type: `Enum`: 51 bytes, alignment: 1 bytes
+print-type-size     discriminant: 1 bytes
+print-type-size     variant `Small`: 7 bytes
+print-type-size         field `.0`: 7 bytes
+print-type-size     variant `Large`: 50 bytes
+print-type-size         field `.0`: 50 bytes
+print-type-size type: `FiftyBytes`: 50 bytes, alignment: 1 bytes
+print-type-size     field `.0`: 50 bytes
+print-type-size type: `SevenBytes`: 7 bytes, alignment: 1 bytes
+print-type-size     field `.0`: 7 bytes
diff --git a/src/test/ui/print_type_sizes/niche-filling.rs b/src/test/ui/print_type_sizes/niche-filling.rs
new file mode 100644
index 0000000..bed1e32
--- /dev/null
+++ b/src/test/ui/print_type_sizes/niche-filling.rs
@@ -0,0 +1,73 @@
+// compile-flags: -Z print-type-sizes
+// compile-pass
+
+// This file illustrates how niche-filling enums are handled,
+// modelled after cases like `Option<&u32>`, `Option<bool>` and such.
+//
+// It uses NonZeroU32 rather than `&_` or `Unique<_>`, because
+// the test is not set up to deal with target-dependent pointer width.
+//
+// It avoids using u64/i64 because on some targets that is only 4-byte
+// aligned (while on most it is 8-byte aligned) and so the resulting
+// padding and overall computed sizes can be quite different.
+
+#![feature(start)]
+#![allow(dead_code)]
+
+use std::num::NonZeroU32;
+
+pub enum MyOption<T> { None, Some(T) }
+
+impl<T> Default for MyOption<T> {
+    fn default() -> Self { MyOption::None }
+}
+
+pub enum EmbeddedDiscr {
+    None,
+    Record { pre: u8, val: NonZeroU32, post: u16 },
+}
+
+impl Default for EmbeddedDiscr {
+    fn default() -> Self { EmbeddedDiscr::None }
+}
+
+#[derive(Default)]
+pub struct IndirectNonZero {
+    pre: u8,
+    nested: NestedNonZero,
+    post: u16,
+}
+
+pub struct NestedNonZero {
+    pre: u8,
+    val: NonZeroU32,
+    post: u16,
+}
+
+impl Default for NestedNonZero {
+    fn default() -> Self {
+        NestedNonZero { pre: 0, val: NonZeroU32::new(1).unwrap(), post: 0 }
+    }
+}
+
+pub enum Enum4<A, B, C, D> {
+    One(A),
+    Two(B),
+    Three(C),
+    Four(D)
+}
+
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
+    let _x: MyOption<NonZeroU32> = Default::default();
+    let _y: EmbeddedDiscr = Default::default();
+    let _z: MyOption<IndirectNonZero> = Default::default();
+    let _a: MyOption<bool> = Default::default();
+    let _b: MyOption<char> = Default::default();
+    let _c: MyOption<std::cmp::Ordering> = Default::default();
+    let _b: MyOption<MyOption<u8>> = Default::default();
+    let _e: Enum4<(), char, (), ()> = Enum4::One(());
+    let _f: Enum4<(), (), bool, ()> = Enum4::One(());
+    let _g: Enum4<(), (), (), MyOption<u8>> = Enum4::One(());
+    0
+}
diff --git a/src/test/ui/print_type_sizes/niche-filling.stdout b/src/test/ui/print_type_sizes/niche-filling.stdout
new file mode 100644
index 0000000..0789c6d
--- /dev/null
+++ b/src/test/ui/print_type_sizes/niche-filling.stdout
@@ -0,0 +1,80 @@
+print-type-size type: `IndirectNonZero`: 12 bytes, alignment: 4 bytes
+print-type-size     field `.nested`: 8 bytes
+print-type-size     field `.post`: 2 bytes
+print-type-size     field `.pre`: 1 bytes
+print-type-size     end padding: 1 bytes
+print-type-size type: `MyOption<IndirectNonZero>`: 12 bytes, alignment: 4 bytes
+print-type-size     variant `None`: 0 bytes
+print-type-size     variant `Some`: 12 bytes
+print-type-size         field `.0`: 12 bytes
+print-type-size type: `EmbeddedDiscr`: 8 bytes, alignment: 4 bytes
+print-type-size     variant `None`: 0 bytes
+print-type-size     variant `Record`: 7 bytes
+print-type-size         field `.val`: 4 bytes
+print-type-size         field `.post`: 2 bytes
+print-type-size         field `.pre`: 1 bytes
+print-type-size     end padding: 1 bytes
+print-type-size type: `NestedNonZero`: 8 bytes, alignment: 4 bytes
+print-type-size     field `.val`: 4 bytes
+print-type-size     field `.post`: 2 bytes
+print-type-size     field `.pre`: 1 bytes
+print-type-size     end padding: 1 bytes
+print-type-size type: `Enum4<(), char, (), ()>`: 4 bytes, alignment: 4 bytes
+print-type-size     variant `One`: 0 bytes
+print-type-size         field `.0`: 0 bytes
+print-type-size     variant `Two`: 4 bytes
+print-type-size         field `.0`: 4 bytes
+print-type-size     variant `Three`: 0 bytes
+print-type-size         field `.0`: 0 bytes
+print-type-size     variant `Four`: 0 bytes
+print-type-size         field `.0`: 0 bytes
+print-type-size type: `MyOption<char>`: 4 bytes, alignment: 4 bytes
+print-type-size     variant `None`: 0 bytes
+print-type-size     variant `Some`: 4 bytes
+print-type-size         field `.0`: 4 bytes
+print-type-size type: `MyOption<std::num::NonZeroU32>`: 4 bytes, alignment: 4 bytes
+print-type-size     variant `None`: 0 bytes
+print-type-size     variant `Some`: 4 bytes
+print-type-size         field `.0`: 4 bytes
+print-type-size type: `std::num::NonZeroU32`: 4 bytes, alignment: 4 bytes
+print-type-size     field `.0`: 4 bytes
+print-type-size type: `Enum4<(), (), (), MyOption<u8>>`: 2 bytes, alignment: 1 bytes
+print-type-size     variant `One`: 0 bytes
+print-type-size         field `.0`: 0 bytes
+print-type-size     variant `Two`: 0 bytes
+print-type-size         field `.0`: 0 bytes
+print-type-size     variant `Three`: 0 bytes
+print-type-size         field `.0`: 0 bytes
+print-type-size     variant `Four`: 2 bytes
+print-type-size         field `.0`: 2 bytes
+print-type-size type: `MyOption<MyOption<u8>>`: 2 bytes, alignment: 1 bytes
+print-type-size     variant `None`: 0 bytes
+print-type-size     variant `Some`: 2 bytes
+print-type-size         field `.0`: 2 bytes
+print-type-size type: `MyOption<u8>`: 2 bytes, alignment: 1 bytes
+print-type-size     discriminant: 1 bytes
+print-type-size     variant `None`: 0 bytes
+print-type-size     variant `Some`: 1 bytes
+print-type-size         field `.0`: 1 bytes
+print-type-size type: `Enum4<(), (), bool, ()>`: 1 bytes, alignment: 1 bytes
+print-type-size     variant `One`: 0 bytes
+print-type-size         field `.0`: 0 bytes
+print-type-size     variant `Two`: 0 bytes
+print-type-size         field `.0`: 0 bytes
+print-type-size     variant `Three`: 1 bytes
+print-type-size         field `.0`: 1 bytes
+print-type-size     variant `Four`: 0 bytes
+print-type-size         field `.0`: 0 bytes
+print-type-size type: `MyOption<bool>`: 1 bytes, alignment: 1 bytes
+print-type-size     variant `None`: 0 bytes
+print-type-size     variant `Some`: 1 bytes
+print-type-size         field `.0`: 1 bytes
+print-type-size type: `MyOption<std::cmp::Ordering>`: 1 bytes, alignment: 1 bytes
+print-type-size     variant `None`: 0 bytes
+print-type-size     variant `Some`: 1 bytes
+print-type-size         field `.0`: 1 bytes
+print-type-size type: `std::cmp::Ordering`: 1 bytes, alignment: 1 bytes
+print-type-size     discriminant: 1 bytes
+print-type-size     variant `Less`: 0 bytes
+print-type-size     variant `Equal`: 0 bytes
+print-type-size     variant `Greater`: 0 bytes
diff --git a/src/test/ui/print_type_sizes/no_duplicates.rs b/src/test/ui/print_type_sizes/no_duplicates.rs
new file mode 100644
index 0000000..7307c0f
--- /dev/null
+++ b/src/test/ui/print_type_sizes/no_duplicates.rs
@@ -0,0 +1,20 @@
+// compile-flags: -Z print-type-sizes
+// compile-pass
+
+// This file illustrates that when the same type occurs repeatedly
+// (even if multiple functions), it is only printed once in the
+// print-type-sizes output.
+
+#![feature(start)]
+
+pub struct SevenBytes([u8; 7]);
+
+pub fn f1() {
+    let _s: SevenBytes = SevenBytes([0; 7]);
+}
+
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
+    let _s: SevenBytes = SevenBytes([0; 7]);
+    0
+}
diff --git a/src/test/ui/print_type_sizes/no_duplicates.stdout b/src/test/ui/print_type_sizes/no_duplicates.stdout
new file mode 100644
index 0000000..50180f3
--- /dev/null
+++ b/src/test/ui/print_type_sizes/no_duplicates.stdout
@@ -0,0 +1,2 @@
+print-type-size type: `SevenBytes`: 7 bytes, alignment: 1 bytes
+print-type-size     field `.0`: 7 bytes
diff --git a/src/test/ui/print_type_sizes/packed.rs b/src/test/ui/print_type_sizes/packed.rs
new file mode 100644
index 0000000..ec3efd6
--- /dev/null
+++ b/src/test/ui/print_type_sizes/packed.rs
@@ -0,0 +1,66 @@
+// compile-flags: -Z print-type-sizes
+// compile-pass
+
+// This file illustrates how packing is handled; it should cause
+// the elimination of padding that would normally be introduced
+// to satisfy alignment desirata.
+//
+// It avoids using u64/i64 because on some targets that is only 4-byte
+// aligned (while on most it is 8-byte aligned) and so the resulting
+// padding and overall computed sizes can be quite different.
+
+#![allow(dead_code)]
+#![feature(start)]
+
+#[derive(Default)]
+#[repr(packed)]
+struct Packed1 {
+    a: u8,
+    b: u8,
+    g: i32,
+    c: u8,
+    h: i16,
+    d: u8,
+}
+
+#[derive(Default)]
+#[repr(packed(2))]
+struct Packed2 {
+    a: u8,
+    b: u8,
+    g: i32,
+    c: u8,
+    h: i16,
+    d: u8,
+}
+
+#[derive(Default)]
+#[repr(packed(2))]
+#[repr(C)]
+struct Packed2C {
+    a: u8,
+    b: u8,
+    g: i32,
+    c: u8,
+    h: i16,
+    d: u8,
+}
+
+#[derive(Default)]
+struct Padded {
+    a: u8,
+    b: u8,
+    g: i32,
+    c: u8,
+    h: i16,
+    d: u8,
+}
+
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
+    let _c: Packed1 = Default::default();
+    let _d: Packed2 = Default::default();
+    let _e: Packed2C = Default::default();
+    let _f: Padded = Default::default();
+    0
+}
diff --git a/src/test/ui/print_type_sizes/packed.stdout b/src/test/ui/print_type_sizes/packed.stdout
new file mode 100644
index 0000000..58e1bac
--- /dev/null
+++ b/src/test/ui/print_type_sizes/packed.stdout
@@ -0,0 +1,31 @@
+print-type-size type: `Packed2C`: 12 bytes, alignment: 2 bytes
+print-type-size     field `.a`: 1 bytes
+print-type-size     field `.b`: 1 bytes
+print-type-size     field `.g`: 4 bytes
+print-type-size     field `.c`: 1 bytes
+print-type-size     padding: 1 bytes
+print-type-size     field `.h`: 2 bytes
+print-type-size     field `.d`: 1 bytes
+print-type-size     end padding: 1 bytes
+print-type-size type: `Padded`: 12 bytes, alignment: 4 bytes
+print-type-size     field `.g`: 4 bytes
+print-type-size     field `.h`: 2 bytes
+print-type-size     field `.a`: 1 bytes
+print-type-size     field `.b`: 1 bytes
+print-type-size     field `.c`: 1 bytes
+print-type-size     field `.d`: 1 bytes
+print-type-size     end padding: 2 bytes
+print-type-size type: `Packed1`: 10 bytes, alignment: 1 bytes
+print-type-size     field `.a`: 1 bytes
+print-type-size     field `.b`: 1 bytes
+print-type-size     field `.g`: 4 bytes
+print-type-size     field `.c`: 1 bytes
+print-type-size     field `.h`: 2 bytes
+print-type-size     field `.d`: 1 bytes
+print-type-size type: `Packed2`: 10 bytes, alignment: 2 bytes
+print-type-size     field `.g`: 4 bytes
+print-type-size     field `.h`: 2 bytes
+print-type-size     field `.a`: 1 bytes
+print-type-size     field `.b`: 1 bytes
+print-type-size     field `.c`: 1 bytes
+print-type-size     field `.d`: 1 bytes
diff --git a/src/test/ui/print_type_sizes/padding.rs b/src/test/ui/print_type_sizes/padding.rs
new file mode 100644
index 0000000..c6d927c
--- /dev/null
+++ b/src/test/ui/print_type_sizes/padding.rs
@@ -0,0 +1,34 @@
+// compile-flags: -Z print-type-sizes
+// compile-pass
+
+// This file illustrates how padding is handled: alignment
+// requirements can lead to the introduction of padding, either before
+// fields or at the end of the structure as a whole.
+//
+// It avoids using u64/i64 because on some targets that is only 4-byte
+// aligned (while on most it is 8-byte aligned) and so the resulting
+// padding and overall computed sizes can be quite different.
+
+#![feature(start)]
+#![allow(dead_code)]
+
+struct S {
+    a: bool,
+    b: bool,
+    g: i32,
+}
+
+enum E1 {
+    A(i32, i8),
+    B(S),
+}
+
+enum E2 {
+    A(i8, i32),
+    B(S),
+}
+
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
+    0
+}
diff --git a/src/test/ui/print_type_sizes/padding.stdout b/src/test/ui/print_type_sizes/padding.stdout
new file mode 100644
index 0000000..0eaff71
--- /dev/null
+++ b/src/test/ui/print_type_sizes/padding.stdout
@@ -0,0 +1,23 @@
+print-type-size type: `E1`: 12 bytes, alignment: 4 bytes
+print-type-size     discriminant: 1 bytes
+print-type-size     variant `A`: 7 bytes
+print-type-size         field `.1`: 1 bytes
+print-type-size         padding: 2 bytes
+print-type-size         field `.0`: 4 bytes, alignment: 4 bytes
+print-type-size     variant `B`: 11 bytes
+print-type-size         padding: 3 bytes
+print-type-size         field `.0`: 8 bytes, alignment: 4 bytes
+print-type-size type: `E2`: 12 bytes, alignment: 4 bytes
+print-type-size     discriminant: 1 bytes
+print-type-size     variant `A`: 7 bytes
+print-type-size         field `.0`: 1 bytes
+print-type-size         padding: 2 bytes
+print-type-size         field `.1`: 4 bytes, alignment: 4 bytes
+print-type-size     variant `B`: 11 bytes
+print-type-size         padding: 3 bytes
+print-type-size         field `.0`: 8 bytes, alignment: 4 bytes
+print-type-size type: `S`: 8 bytes, alignment: 4 bytes
+print-type-size     field `.g`: 4 bytes
+print-type-size     field `.a`: 1 bytes
+print-type-size     field `.b`: 1 bytes
+print-type-size     end padding: 2 bytes
diff --git a/src/test/ui/print_type_sizes/repr-align.rs b/src/test/ui/print_type_sizes/repr-align.rs
new file mode 100644
index 0000000..fd452f4
--- /dev/null
+++ b/src/test/ui/print_type_sizes/repr-align.rs
@@ -0,0 +1,35 @@
+// compile-flags: -Z print-type-sizes
+// compile-pass
+
+// This file illustrates how padding is handled: alignment
+// requirements can lead to the introduction of padding, either before
+// fields or at the end of the structure as a whole.
+//
+// It avoids using u64/i64 because on some targets that is only 4-byte
+// aligned (while on most it is 8-byte aligned) and so the resulting
+// padding and overall computed sizes can be quite different.
+#![feature(start)]
+#![allow(dead_code)]
+
+#[repr(align(16))]
+#[derive(Default)]
+struct A(i32);
+
+enum E {
+    A(i32),
+    B(A)
+}
+
+#[derive(Default)]
+struct S {
+    a: i32,
+    b: i32,
+    c: A,
+    d: i8,
+}
+
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
+    let _s: S = Default::default();
+    0
+}
diff --git a/src/test/ui/print_type_sizes/repr-align.stdout b/src/test/ui/print_type_sizes/repr-align.stdout
new file mode 100644
index 0000000..7df12f0
--- /dev/null
+++ b/src/test/ui/print_type_sizes/repr-align.stdout
@@ -0,0 +1,16 @@
+print-type-size type: `E`: 32 bytes, alignment: 16 bytes
+print-type-size     discriminant: 4 bytes
+print-type-size     variant `A`: 4 bytes
+print-type-size         field `.0`: 4 bytes
+print-type-size     variant `B`: 28 bytes
+print-type-size         padding: 12 bytes
+print-type-size         field `.0`: 16 bytes, alignment: 16 bytes
+print-type-size type: `S`: 32 bytes, alignment: 16 bytes
+print-type-size     field `.c`: 16 bytes
+print-type-size     field `.a`: 4 bytes
+print-type-size     field `.b`: 4 bytes
+print-type-size     field `.d`: 1 bytes
+print-type-size     end padding: 7 bytes
+print-type-size type: `A`: 16 bytes, alignment: 16 bytes
+print-type-size     field `.0`: 4 bytes
+print-type-size     end padding: 12 bytes
diff --git a/src/test/ui/print_type_sizes/repr_int_c.rs b/src/test/ui/print_type_sizes/repr_int_c.rs
new file mode 100644
index 0000000..6816bb71
--- /dev/null
+++ b/src/test/ui/print_type_sizes/repr_int_c.rs
@@ -0,0 +1,25 @@
+// compile-flags: -Z print-type-sizes
+// compile-pass
+
+// This test makes sure that the tag is not grown for `repr(C)` or `repr(u8)`
+// variants (see https://github.com/rust-lang/rust/issues/50098 for the original bug).
+
+#![feature(start)]
+#![allow(dead_code)]
+
+#[repr(C, u8)]
+enum ReprCu8 {
+    A(u16),
+    B,
+}
+
+#[repr(u8)]
+enum Repru8 {
+    A(u16),
+    B,
+}
+
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
+    0
+}
diff --git a/src/test/ui/print_type_sizes/repr_int_c.stdout b/src/test/ui/print_type_sizes/repr_int_c.stdout
new file mode 100644
index 0000000..254b3c7
--- /dev/null
+++ b/src/test/ui/print_type_sizes/repr_int_c.stdout
@@ -0,0 +1,12 @@
+print-type-size type: `ReprCu8`: 4 bytes, alignment: 2 bytes
+print-type-size     discriminant: 1 bytes
+print-type-size     variant `A`: 3 bytes
+print-type-size         padding: 1 bytes
+print-type-size         field `.0`: 2 bytes, alignment: 2 bytes
+print-type-size     variant `B`: 1 bytes
+print-type-size type: `Repru8`: 4 bytes, alignment: 2 bytes
+print-type-size     discriminant: 1 bytes
+print-type-size     variant `A`: 3 bytes
+print-type-size         padding: 1 bytes
+print-type-size         field `.0`: 2 bytes, alignment: 2 bytes
+print-type-size     variant `B`: 0 bytes
diff --git a/src/test/ui/print_type_sizes/uninhabited.rs b/src/test/ui/print_type_sizes/uninhabited.rs
new file mode 100644
index 0000000..14245d0
--- /dev/null
+++ b/src/test/ui/print_type_sizes/uninhabited.rs
@@ -0,0 +1,12 @@
+// compile-flags: -Z print-type-sizes
+// compile-pass
+
+#![feature(never_type)]
+#![feature(start)]
+
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
+    let _x: Option<!> = None;
+    let _y: Result<u32, !> = Ok(42);
+    0
+}
diff --git a/src/test/ui/print_type_sizes/uninhabited.stdout b/src/test/ui/print_type_sizes/uninhabited.stdout
new file mode 100644
index 0000000..2a8706f
--- /dev/null
+++ b/src/test/ui/print_type_sizes/uninhabited.stdout
@@ -0,0 +1,5 @@
+print-type-size type: `std::result::Result<u32, !>`: 4 bytes, alignment: 4 bytes
+print-type-size     variant `Ok`: 4 bytes
+print-type-size         field `.0`: 4 bytes
+print-type-size type: `std::option::Option<!>`: 0 bytes, alignment: 1 bytes
+print-type-size     variant `None`: 0 bytes
diff --git a/src/test/ui/print_type_sizes/variants.rs b/src/test/ui/print_type_sizes/variants.rs
new file mode 100644
index 0000000..aa2d25a
--- /dev/null
+++ b/src/test/ui/print_type_sizes/variants.rs
@@ -0,0 +1,26 @@
+// compile-flags: -Z print-type-sizes
+// compile-pass
+
+// This file illustrates two things:
+//
+// 1. Only types that appear in a monomorphized function appear in the
+//    print-type-sizes output, and
+//
+// 2. For an enum, the print-type-sizes output will also include the
+//    size of each variant.
+
+#![feature(start)]
+
+pub struct SevenBytes([u8;  7]);
+pub struct FiftyBytes([u8; 50]);
+
+pub enum Enum {
+    Small(SevenBytes),
+    Large(FiftyBytes),
+}
+
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
+    let _e: Enum;
+    0
+}
diff --git a/src/test/ui/print_type_sizes/variants.stdout b/src/test/ui/print_type_sizes/variants.stdout
new file mode 100644
index 0000000..eed9af2
--- /dev/null
+++ b/src/test/ui/print_type_sizes/variants.stdout
@@ -0,0 +1,10 @@
+print-type-size type: `Enum`: 51 bytes, alignment: 1 bytes
+print-type-size     discriminant: 1 bytes
+print-type-size     variant `Small`: 7 bytes
+print-type-size         field `.0`: 7 bytes
+print-type-size     variant `Large`: 50 bytes
+print-type-size         field `.0`: 50 bytes
+print-type-size type: `FiftyBytes`: 50 bytes, alignment: 1 bytes
+print-type-size     field `.0`: 50 bytes
+print-type-size type: `SevenBytes`: 7 bytes, alignment: 1 bytes
+print-type-size     field `.0`: 7 bytes
diff --git a/src/test/ui/priv-in-bad-locations.rs b/src/test/ui/priv-in-bad-locations.rs
new file mode 100644
index 0000000..b9f5d4c
--- /dev/null
+++ b/src/test/ui/priv-in-bad-locations.rs
@@ -0,0 +1,17 @@
+pub extern { //~ ERROR unnecessary visibility qualifier
+    pub fn bar();
+}
+
+trait A {
+    fn foo(&self) {}
+}
+
+struct B;
+
+pub impl B {} //~ ERROR unnecessary visibility qualifier
+
+pub impl A for B { //~ ERROR unnecessary visibility qualifier
+    pub fn foo(&self) {} //~ ERROR unnecessary visibility qualifier
+}
+
+pub fn main() {}
diff --git a/src/test/ui/priv-in-bad-locations.stderr b/src/test/ui/priv-in-bad-locations.stderr
new file mode 100644
index 0000000..713568f
--- /dev/null
+++ b/src/test/ui/priv-in-bad-locations.stderr
@@ -0,0 +1,31 @@
+error[E0449]: unnecessary visibility qualifier
+  --> $DIR/priv-in-bad-locations.rs:1:1
+   |
+LL | pub extern {
+   | ^^^ `pub` not permitted here because it's implied
+   |
+   = note: place qualifiers on individual foreign items instead
+
+error[E0449]: unnecessary visibility qualifier
+  --> $DIR/priv-in-bad-locations.rs:11:1
+   |
+LL | pub impl B {}
+   | ^^^ `pub` not permitted here because it's implied
+   |
+   = note: place qualifiers on individual impl items instead
+
+error[E0449]: unnecessary visibility qualifier
+  --> $DIR/priv-in-bad-locations.rs:13:1
+   |
+LL | pub impl A for B {
+   | ^^^ `pub` not permitted here because it's implied
+
+error[E0449]: unnecessary visibility qualifier
+  --> $DIR/priv-in-bad-locations.rs:14:5
+   |
+LL |     pub fn foo(&self) {}
+   |     ^^^ `pub` not permitted here because it's implied
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0449`.
diff --git a/src/test/ui/privacy/associated-item-privacy-inherent.rs b/src/test/ui/privacy/associated-item-privacy-inherent.rs
new file mode 100644
index 0000000..c3ae920
--- /dev/null
+++ b/src/test/ui/privacy/associated-item-privacy-inherent.rs
@@ -0,0 +1,112 @@
+#![feature(decl_macro, associated_type_defaults)]
+#![allow(unused, private_in_public)]
+
+mod priv_nominal {
+    pub struct Pub;
+    impl Pub {
+        fn method(&self) {}
+        const CONST: u8 = 0;
+        // type AssocTy = u8;
+    }
+
+    pub macro mac() {
+        let value = Pub::method;
+        //~^ ERROR type `for<'r> fn(&'r priv_nominal::Pub) {priv_nominal::Pub::method}` is private
+        value;
+        //~^ ERROR type `for<'r> fn(&'r priv_nominal::Pub) {priv_nominal::Pub::method}` is private
+        Pub.method();
+        //~^ ERROR type `for<'r> fn(&'r priv_nominal::Pub) {priv_nominal::Pub::method}` is private
+        Pub::CONST;
+        //~^ ERROR associated constant `CONST` is private
+        // let _: Pub::AssocTy;
+        // pub type InSignatureTy = Pub::AssocTy;
+    }
+}
+fn priv_nominal() {
+    priv_nominal::mac!();
+}
+
+mod priv_signature {
+    struct Priv;
+    pub struct Pub;
+    impl Pub {
+        pub fn method(&self, arg: Priv) {}
+    }
+
+    pub macro mac() {
+        let value = Pub::method;
+        //~^ ERROR type `priv_signature::Priv` is private
+        value;
+        //~^ ERROR type `priv_signature::Priv` is private
+        Pub.method(loop {});
+        //~^ ERROR type `priv_signature::Priv` is private
+    }
+}
+fn priv_signature() {
+    priv_signature::mac!();
+}
+
+mod priv_substs {
+    struct Priv;
+    pub struct Pub;
+    impl Pub {
+        pub fn method<T>(&self) {}
+    }
+
+    pub macro mac() {
+        let value = Pub::method::<Priv>;
+        //~^ ERROR type `priv_substs::Priv` is private
+        value;
+        //~^ ERROR type `priv_substs::Priv` is private
+        Pub.method::<Priv>();
+        //~^ ERROR type `priv_substs::Priv` is private
+    }
+}
+fn priv_substs() {
+    priv_substs::mac!();
+}
+
+mod priv_parent_substs {
+    struct Priv;
+    pub struct Pub<T = Priv>(T);
+    impl Pub<Priv> {
+        pub fn method(&self) {}
+        pub fn static_method() {}
+        pub const CONST: u8 = 0;
+        // pub type AssocTy = u8;
+    }
+
+    pub macro mac() {
+        let value = <Pub>::method;
+        //~^ ERROR type `priv_parent_substs::Priv` is private
+        value;
+        //~^ ERROR type `priv_parent_substs::Priv` is private
+        let value = Pub::method;
+        //~^ ERROR type `priv_parent_substs::Priv` is private
+        value;
+        //~^ ERROR type `priv_parent_substs::Priv` is private
+        let value = <Pub>::static_method;
+        //~^ ERROR type `priv_parent_substs::Priv` is private
+        value;
+        //~^ ERROR type `priv_parent_substs::Priv` is private
+        let value = Pub::static_method;
+        //~^ ERROR type `priv_parent_substs::Priv` is private
+        value;
+        //~^ ERROR type `priv_parent_substs::Priv` is private
+        Pub(Priv).method();
+        //~^ ERROR type `priv_parent_substs::Priv` is private
+
+        <Pub>::CONST;
+        //~^ ERROR type `priv_parent_substs::Priv` is private
+        Pub::CONST;
+        //~^ ERROR type `priv_parent_substs::Priv` is private
+
+        // let _: Pub::AssocTy;
+        // pub type InSignatureTy = Pub::AssocTy;
+    }
+}
+fn priv_parent_substs() {
+    priv_parent_substs::mac!();
+}
+
+fn main() {}
diff --git a/src/test/ui/privacy/associated-item-privacy-inherent.stderr b/src/test/ui/privacy/associated-item-privacy-inherent.stderr
new file mode 100644
index 0000000..6471a79
--- /dev/null
+++ b/src/test/ui/privacy/associated-item-privacy-inherent.stderr
@@ -0,0 +1,191 @@
+error: type `for<'r> fn(&'r priv_nominal::Pub) {priv_nominal::Pub::method}` is private
+  --> $DIR/associated-item-privacy-inherent.rs:13:21
+   |
+LL |         let value = Pub::method;
+   |                     ^^^^^^^^^^^
+...
+LL |     priv_nominal::mac!();
+   |     --------------------- in this macro invocation
+
+error: type `for<'r> fn(&'r priv_nominal::Pub) {priv_nominal::Pub::method}` is private
+  --> $DIR/associated-item-privacy-inherent.rs:15:9
+   |
+LL |         value;
+   |         ^^^^^
+...
+LL |     priv_nominal::mac!();
+   |     --------------------- in this macro invocation
+
+error: type `for<'r> fn(&'r priv_nominal::Pub) {priv_nominal::Pub::method}` is private
+  --> $DIR/associated-item-privacy-inherent.rs:17:13
+   |
+LL |         Pub.method();
+   |             ^^^^^^
+...
+LL |     priv_nominal::mac!();
+   |     --------------------- in this macro invocation
+
+error: associated constant `CONST` is private
+  --> $DIR/associated-item-privacy-inherent.rs:19:9
+   |
+LL |         Pub::CONST;
+   |         ^^^^^^^^^^
+...
+LL |     priv_nominal::mac!();
+   |     --------------------- in this macro invocation
+
+error: type `priv_signature::Priv` is private
+  --> $DIR/associated-item-privacy-inherent.rs:37:21
+   |
+LL |         let value = Pub::method;
+   |                     ^^^^^^^^^^^
+...
+LL |     priv_signature::mac!();
+   |     ----------------------- in this macro invocation
+
+error: type `priv_signature::Priv` is private
+  --> $DIR/associated-item-privacy-inherent.rs:39:9
+   |
+LL |         value;
+   |         ^^^^^
+...
+LL |     priv_signature::mac!();
+   |     ----------------------- in this macro invocation
+
+error: type `priv_signature::Priv` is private
+  --> $DIR/associated-item-privacy-inherent.rs:41:13
+   |
+LL |         Pub.method(loop {});
+   |             ^^^^^^
+...
+LL |     priv_signature::mac!();
+   |     ----------------------- in this macro invocation
+
+error: type `priv_substs::Priv` is private
+  --> $DIR/associated-item-privacy-inherent.rs:57:21
+   |
+LL |         let value = Pub::method::<Priv>;
+   |                     ^^^^^^^^^^^^^^^^^^^
+...
+LL |     priv_substs::mac!();
+   |     -------------------- in this macro invocation
+
+error: type `priv_substs::Priv` is private
+  --> $DIR/associated-item-privacy-inherent.rs:59:9
+   |
+LL |         value;
+   |         ^^^^^
+...
+LL |     priv_substs::mac!();
+   |     -------------------- in this macro invocation
+
+error: type `priv_substs::Priv` is private
+  --> $DIR/associated-item-privacy-inherent.rs:61:9
+   |
+LL |         Pub.method::<Priv>();
+   |         ^^^^^^^^^^^^^^^^^^^^
+...
+LL |     priv_substs::mac!();
+   |     -------------------- in this macro invocation
+
+error: type `priv_parent_substs::Priv` is private
+  --> $DIR/associated-item-privacy-inherent.rs:80:21
+   |
+LL |         let value = <Pub>::method;
+   |                     ^^^^^^^^^^^^^
+...
+LL |     priv_parent_substs::mac!();
+   |     --------------------------- in this macro invocation
+
+error: type `priv_parent_substs::Priv` is private
+  --> $DIR/associated-item-privacy-inherent.rs:82:9
+   |
+LL |         value;
+   |         ^^^^^
+...
+LL |     priv_parent_substs::mac!();
+   |     --------------------------- in this macro invocation
+
+error: type `priv_parent_substs::Priv` is private
+  --> $DIR/associated-item-privacy-inherent.rs:84:21
+   |
+LL |         let value = Pub::method;
+   |                     ^^^^^^^^^^^
+...
+LL |     priv_parent_substs::mac!();
+   |     --------------------------- in this macro invocation
+
+error: type `priv_parent_substs::Priv` is private
+  --> $DIR/associated-item-privacy-inherent.rs:86:9
+   |
+LL |         value;
+   |         ^^^^^
+...
+LL |     priv_parent_substs::mac!();
+   |     --------------------------- in this macro invocation
+
+error: type `priv_parent_substs::Priv` is private
+  --> $DIR/associated-item-privacy-inherent.rs:88:21
+   |
+LL |         let value = <Pub>::static_method;
+   |                     ^^^^^^^^^^^^^^^^^^^^
+...
+LL |     priv_parent_substs::mac!();
+   |     --------------------------- in this macro invocation
+
+error: type `priv_parent_substs::Priv` is private
+  --> $DIR/associated-item-privacy-inherent.rs:90:9
+   |
+LL |         value;
+   |         ^^^^^
+...
+LL |     priv_parent_substs::mac!();
+   |     --------------------------- in this macro invocation
+
+error: type `priv_parent_substs::Priv` is private
+  --> $DIR/associated-item-privacy-inherent.rs:92:21
+   |
+LL |         let value = Pub::static_method;
+   |                     ^^^^^^^^^^^^^^^^^^
+...
+LL |     priv_parent_substs::mac!();
+   |     --------------------------- in this macro invocation
+
+error: type `priv_parent_substs::Priv` is private
+  --> $DIR/associated-item-privacy-inherent.rs:94:9
+   |
+LL |         value;
+   |         ^^^^^
+...
+LL |     priv_parent_substs::mac!();
+   |     --------------------------- in this macro invocation
+
+error: type `priv_parent_substs::Priv` is private
+  --> $DIR/associated-item-privacy-inherent.rs:96:19
+   |
+LL |         Pub(Priv).method();
+   |                   ^^^^^^
+...
+LL |     priv_parent_substs::mac!();
+   |     --------------------------- in this macro invocation
+
+error: type `priv_parent_substs::Priv` is private
+  --> $DIR/associated-item-privacy-inherent.rs:99:10
+   |
+LL |         <Pub>::CONST;
+   |          ^^^
+...
+LL |     priv_parent_substs::mac!();
+   |     --------------------------- in this macro invocation
+
+error: type `priv_parent_substs::Priv` is private
+  --> $DIR/associated-item-privacy-inherent.rs:101:9
+   |
+LL |         Pub::CONST;
+   |         ^^^^^^^^^^
+...
+LL |     priv_parent_substs::mac!();
+   |     --------------------------- in this macro invocation
+
+error: aborting due to 21 previous errors
+
diff --git a/src/test/ui/privacy/associated-item-privacy-trait.rs b/src/test/ui/privacy/associated-item-privacy-trait.rs
new file mode 100644
index 0000000..b3d42f0
--- /dev/null
+++ b/src/test/ui/privacy/associated-item-privacy-trait.rs
@@ -0,0 +1,141 @@
+// ignore-tidy-linelength
+
+#![feature(decl_macro, associated_type_defaults)]
+#![allow(unused, private_in_public)]
+
+mod priv_trait {
+    trait PrivTr {
+        fn method(&self) {}
+        const CONST: u8 = 0;
+        type AssocTy = u8;
+    }
+    pub struct Pub;
+    impl PrivTr for Pub {}
+    pub trait PubTr: PrivTr {}
+
+    pub macro mac() {
+        let value = <Pub as PrivTr>::method;
+        //~^ ERROR type `for<'r> fn(&'r priv_trait::Pub) {<priv_trait::Pub as priv_trait::PrivTr>::method}` is private
+        value;
+        //~^ ERROR type `for<'r> fn(&'r priv_trait::Pub) {<priv_trait::Pub as priv_trait::PrivTr>::method}` is private
+        Pub.method();
+        //~^ ERROR type `for<'r> fn(&'r Self) {<Self as priv_trait::PrivTr>::method}` is private
+        <Pub as PrivTr>::CONST;
+        //~^ ERROR associated constant `PrivTr::CONST` is private
+        let _: <Pub as PrivTr>::AssocTy;
+        //~^ ERROR trait `priv_trait::PrivTr` is private
+        //~| ERROR trait `priv_trait::PrivTr` is private
+        pub type InSignatureTy = <Pub as PrivTr>::AssocTy;
+        //~^ ERROR trait `priv_trait::PrivTr` is private
+        pub trait InSignatureTr: PrivTr {}
+        //~^ ERROR trait `priv_trait::PrivTr` is private
+        impl PrivTr for u8 {}
+        //~^ ERROR trait `priv_trait::PrivTr` is private
+    }
+}
+fn priv_trait() {
+    priv_trait::mac!();
+}
+
+mod priv_signature {
+    pub trait PubTr {
+        fn method(&self, arg: Priv) {}
+    }
+    struct Priv;
+    pub struct Pub;
+    impl PubTr for Pub {}
+
+    pub macro mac() {
+        let value = <Pub as PubTr>::method;
+        //~^ ERROR type `priv_signature::Priv` is private
+        value;
+        //~^ ERROR type `priv_signature::Priv` is private
+        Pub.method(loop {});
+        //~^ ERROR type `priv_signature::Priv` is private
+    }
+}
+fn priv_signature() {
+    priv_signature::mac!();
+}
+
+mod priv_substs {
+    pub trait PubTr {
+        fn method<T>(&self) {}
+    }
+    struct Priv;
+    pub struct Pub;
+    impl PubTr for Pub {}
+
+    pub macro mac() {
+        let value = <Pub as PubTr>::method::<Priv>;
+        //~^ ERROR type `priv_substs::Priv` is private
+        value;
+        //~^ ERROR type `priv_substs::Priv` is private
+        Pub.method::<Priv>();
+        //~^ ERROR type `priv_substs::Priv` is private
+    }
+}
+fn priv_substs() {
+    priv_substs::mac!();
+}
+
+mod priv_parent_substs {
+    pub trait PubTr<T = Priv> {
+        fn method(&self) {}
+        const CONST: u8 = 0;
+        type AssocTy = u8;
+    }
+    struct Priv;
+    pub struct Pub;
+    impl PubTr<Priv> for Pub {}
+    impl PubTr<Pub> for Priv {}
+
+    pub macro mac() {
+        let value = <Pub as PubTr>::method;
+        //~^ ERROR type `priv_parent_substs::Priv` is private
+        value;
+        //~^ ERROR type `priv_parent_substs::Priv` is private
+        let value = <Pub as PubTr<_>>::method;
+        //~^ ERROR type `priv_parent_substs::Priv` is private
+        value;
+        //~^ ERROR type `priv_parent_substs::Priv` is private
+        Pub.method();
+        //~^ ERROR type `priv_parent_substs::Priv` is private
+
+        let value = <Priv as PubTr<_>>::method;
+        //~^ ERROR type `priv_parent_substs::Priv` is private
+        value;
+        //~^ ERROR type `priv_parent_substs::Priv` is private
+        Priv.method();
+        //~^ ERROR type `priv_parent_substs::Priv` is private
+
+        <Pub as PubTr>::CONST;
+        //~^ ERROR type `priv_parent_substs::Priv` is private
+        <Pub as PubTr<_>>::CONST;
+        //~^ ERROR type `priv_parent_substs::Priv` is private
+        <Priv as PubTr<_>>::CONST;
+        //~^ ERROR type `priv_parent_substs::Priv` is private
+
+        let _: <Pub as PubTr>::AssocTy;
+        //~^ ERROR type `priv_parent_substs::Priv` is private
+        //~| ERROR type `priv_parent_substs::Priv` is private
+        let _: <Pub as PubTr<_>>::AssocTy;
+        //~^ ERROR type `priv_parent_substs::Priv` is private
+        //~| ERROR type `priv_parent_substs::Priv` is private
+        let _: <Priv as PubTr<_>>::AssocTy;
+        //~^ ERROR type `priv_parent_substs::Priv` is private
+        //~| ERROR type `priv_parent_substs::Priv` is private
+
+        pub type InSignatureTy1 = <Pub as PubTr>::AssocTy;
+        //~^ ERROR type `priv_parent_substs::Priv` is private
+        pub type InSignatureTy2 = <Priv as PubTr<Pub>>::AssocTy;
+        //~^ ERROR type `priv_parent_substs::Priv` is private
+        impl PubTr for u8 {}
+        //~^ ERROR type `priv_parent_substs::Priv` is private
+    }
+}
+fn priv_parent_substs() {
+    priv_parent_substs::mac!();
+}
+
+fn main() {}
diff --git a/src/test/ui/privacy/associated-item-privacy-trait.stderr b/src/test/ui/privacy/associated-item-privacy-trait.stderr
new file mode 100644
index 0000000..5cf1be8
--- /dev/null
+++ b/src/test/ui/privacy/associated-item-privacy-trait.stderr
@@ -0,0 +1,317 @@
+error: type `for<'r> fn(&'r priv_trait::Pub) {<priv_trait::Pub as priv_trait::PrivTr>::method}` is private
+  --> $DIR/associated-item-privacy-trait.rs:17:21
+   |
+LL |         let value = <Pub as PrivTr>::method;
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     priv_trait::mac!();
+   |     ------------------- in this macro invocation
+
+error: type `for<'r> fn(&'r priv_trait::Pub) {<priv_trait::Pub as priv_trait::PrivTr>::method}` is private
+  --> $DIR/associated-item-privacy-trait.rs:19:9
+   |
+LL |         value;
+   |         ^^^^^
+...
+LL |     priv_trait::mac!();
+   |     ------------------- in this macro invocation
+
+error: type `for<'r> fn(&'r Self) {<Self as priv_trait::PrivTr>::method}` is private
+  --> $DIR/associated-item-privacy-trait.rs:21:13
+   |
+LL |         Pub.method();
+   |             ^^^^^^
+...
+LL |     priv_trait::mac!();
+   |     ------------------- in this macro invocation
+
+error: associated constant `PrivTr::CONST` is private
+  --> $DIR/associated-item-privacy-trait.rs:23:9
+   |
+LL |         <Pub as PrivTr>::CONST;
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     priv_trait::mac!();
+   |     ------------------- in this macro invocation
+
+error: trait `priv_trait::PrivTr` is private
+  --> $DIR/associated-item-privacy-trait.rs:25:13
+   |
+LL |         let _: <Pub as PrivTr>::AssocTy;
+   |             ^
+...
+LL |     priv_trait::mac!();
+   |     ------------------- in this macro invocation
+
+error: trait `priv_trait::PrivTr` is private
+  --> $DIR/associated-item-privacy-trait.rs:25:16
+   |
+LL |         let _: <Pub as PrivTr>::AssocTy;
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     priv_trait::mac!();
+   |     ------------------- in this macro invocation
+
+error: trait `priv_trait::PrivTr` is private
+  --> $DIR/associated-item-privacy-trait.rs:28:34
+   |
+LL |         pub type InSignatureTy = <Pub as PrivTr>::AssocTy;
+   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     priv_trait::mac!();
+   |     ------------------- in this macro invocation
+
+error: trait `priv_trait::PrivTr` is private
+  --> $DIR/associated-item-privacy-trait.rs:30:34
+   |
+LL |         pub trait InSignatureTr: PrivTr {}
+   |                                  ^^^^^^
+...
+LL |     priv_trait::mac!();
+   |     ------------------- in this macro invocation
+
+error: trait `priv_trait::PrivTr` is private
+  --> $DIR/associated-item-privacy-trait.rs:32:14
+   |
+LL |         impl PrivTr for u8 {}
+   |              ^^^^^^
+...
+LL |     priv_trait::mac!();
+   |     ------------------- in this macro invocation
+
+error: type `priv_signature::Priv` is private
+  --> $DIR/associated-item-privacy-trait.rs:49:21
+   |
+LL |         let value = <Pub as PubTr>::method;
+   |                     ^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     priv_signature::mac!();
+   |     ----------------------- in this macro invocation
+
+error: type `priv_signature::Priv` is private
+  --> $DIR/associated-item-privacy-trait.rs:51:9
+   |
+LL |         value;
+   |         ^^^^^
+...
+LL |     priv_signature::mac!();
+   |     ----------------------- in this macro invocation
+
+error: type `priv_signature::Priv` is private
+  --> $DIR/associated-item-privacy-trait.rs:53:13
+   |
+LL |         Pub.method(loop {});
+   |             ^^^^^^
+...
+LL |     priv_signature::mac!();
+   |     ----------------------- in this macro invocation
+
+error: type `priv_substs::Priv` is private
+  --> $DIR/associated-item-privacy-trait.rs:70:21
+   |
+LL |         let value = <Pub as PubTr>::method::<Priv>;
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     priv_substs::mac!();
+   |     -------------------- in this macro invocation
+
+error: type `priv_substs::Priv` is private
+  --> $DIR/associated-item-privacy-trait.rs:72:9
+   |
+LL |         value;
+   |         ^^^^^
+...
+LL |     priv_substs::mac!();
+   |     -------------------- in this macro invocation
+
+error: type `priv_substs::Priv` is private
+  --> $DIR/associated-item-privacy-trait.rs:74:9
+   |
+LL |         Pub.method::<Priv>();
+   |         ^^^^^^^^^^^^^^^^^^^^
+...
+LL |     priv_substs::mac!();
+   |     -------------------- in this macro invocation
+
+error: type `priv_parent_substs::Priv` is private
+  --> $DIR/associated-item-privacy-trait.rs:94:21
+   |
+LL |         let value = <Pub as PubTr>::method;
+   |                     ^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     priv_parent_substs::mac!();
+   |     --------------------------- in this macro invocation
+
+error: type `priv_parent_substs::Priv` is private
+  --> $DIR/associated-item-privacy-trait.rs:96:9
+   |
+LL |         value;
+   |         ^^^^^
+...
+LL |     priv_parent_substs::mac!();
+   |     --------------------------- in this macro invocation
+
+error: type `priv_parent_substs::Priv` is private
+  --> $DIR/associated-item-privacy-trait.rs:98:21
+   |
+LL |         let value = <Pub as PubTr<_>>::method;
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     priv_parent_substs::mac!();
+   |     --------------------------- in this macro invocation
+
+error: type `priv_parent_substs::Priv` is private
+  --> $DIR/associated-item-privacy-trait.rs:100:9
+   |
+LL |         value;
+   |         ^^^^^
+...
+LL |     priv_parent_substs::mac!();
+   |     --------------------------- in this macro invocation
+
+error: type `priv_parent_substs::Priv` is private
+  --> $DIR/associated-item-privacy-trait.rs:102:9
+   |
+LL |         Pub.method();
+   |         ^^^^^^^^^^^^
+...
+LL |     priv_parent_substs::mac!();
+   |     --------------------------- in this macro invocation
+
+error: type `priv_parent_substs::Priv` is private
+  --> $DIR/associated-item-privacy-trait.rs:105:21
+   |
+LL |         let value = <Priv as PubTr<_>>::method;
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     priv_parent_substs::mac!();
+   |     --------------------------- in this macro invocation
+
+error: type `priv_parent_substs::Priv` is private
+  --> $DIR/associated-item-privacy-trait.rs:107:9
+   |
+LL |         value;
+   |         ^^^^^
+...
+LL |     priv_parent_substs::mac!();
+   |     --------------------------- in this macro invocation
+
+error: type `priv_parent_substs::Priv` is private
+  --> $DIR/associated-item-privacy-trait.rs:109:9
+   |
+LL |         Priv.method();
+   |         ^^^^^^^^^^^^^
+...
+LL |     priv_parent_substs::mac!();
+   |     --------------------------- in this macro invocation
+
+error: type `priv_parent_substs::Priv` is private
+  --> $DIR/associated-item-privacy-trait.rs:112:9
+   |
+LL |         <Pub as PubTr>::CONST;
+   |         ^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     priv_parent_substs::mac!();
+   |     --------------------------- in this macro invocation
+
+error: type `priv_parent_substs::Priv` is private
+  --> $DIR/associated-item-privacy-trait.rs:114:9
+   |
+LL |         <Pub as PubTr<_>>::CONST;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     priv_parent_substs::mac!();
+   |     --------------------------- in this macro invocation
+
+error: type `priv_parent_substs::Priv` is private
+  --> $DIR/associated-item-privacy-trait.rs:116:9
+   |
+LL |         <Priv as PubTr<_>>::CONST;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     priv_parent_substs::mac!();
+   |     --------------------------- in this macro invocation
+
+error: type `priv_parent_substs::Priv` is private
+  --> $DIR/associated-item-privacy-trait.rs:119:13
+   |
+LL |         let _: <Pub as PubTr>::AssocTy;
+   |             ^
+...
+LL |     priv_parent_substs::mac!();
+   |     --------------------------- in this macro invocation
+
+error: type `priv_parent_substs::Priv` is private
+  --> $DIR/associated-item-privacy-trait.rs:119:16
+   |
+LL |         let _: <Pub as PubTr>::AssocTy;
+   |                ^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     priv_parent_substs::mac!();
+   |     --------------------------- in this macro invocation
+
+error: type `priv_parent_substs::Priv` is private
+  --> $DIR/associated-item-privacy-trait.rs:122:13
+   |
+LL |         let _: <Pub as PubTr<_>>::AssocTy;
+   |             ^
+...
+LL |     priv_parent_substs::mac!();
+   |     --------------------------- in this macro invocation
+
+error: type `priv_parent_substs::Priv` is private
+  --> $DIR/associated-item-privacy-trait.rs:122:16
+   |
+LL |         let _: <Pub as PubTr<_>>::AssocTy;
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     priv_parent_substs::mac!();
+   |     --------------------------- in this macro invocation
+
+error: type `priv_parent_substs::Priv` is private
+  --> $DIR/associated-item-privacy-trait.rs:125:13
+   |
+LL |         let _: <Priv as PubTr<_>>::AssocTy;
+   |             ^
+...
+LL |     priv_parent_substs::mac!();
+   |     --------------------------- in this macro invocation
+
+error: type `priv_parent_substs::Priv` is private
+  --> $DIR/associated-item-privacy-trait.rs:125:16
+   |
+LL |         let _: <Priv as PubTr<_>>::AssocTy;
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     priv_parent_substs::mac!();
+   |     --------------------------- in this macro invocation
+
+error: type `priv_parent_substs::Priv` is private
+  --> $DIR/associated-item-privacy-trait.rs:129:35
+   |
+LL |         pub type InSignatureTy1 = <Pub as PubTr>::AssocTy;
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     priv_parent_substs::mac!();
+   |     --------------------------- in this macro invocation
+
+error: type `priv_parent_substs::Priv` is private
+  --> $DIR/associated-item-privacy-trait.rs:131:35
+   |
+LL |         pub type InSignatureTy2 = <Priv as PubTr<Pub>>::AssocTy;
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     priv_parent_substs::mac!();
+   |     --------------------------- in this macro invocation
+
+error: type `priv_parent_substs::Priv` is private
+  --> $DIR/associated-item-privacy-trait.rs:133:14
+   |
+LL |         impl PubTr for u8 {}
+   |              ^^^^^
+...
+LL |     priv_parent_substs::mac!();
+   |     --------------------------- in this macro invocation
+
+error: aborting due to 35 previous errors
+
diff --git a/src/test/ui/privacy/associated-item-privacy-type-binding.rs b/src/test/ui/privacy/associated-item-privacy-type-binding.rs
new file mode 100644
index 0000000..591e9df
--- /dev/null
+++ b/src/test/ui/privacy/associated-item-privacy-type-binding.rs
@@ -0,0 +1,64 @@
+#![feature(decl_macro, associated_type_defaults)]
+#![allow(unused, private_in_public)]
+
+mod priv_trait {
+    trait PrivTr {
+        type AssocTy = u8;
+    }
+    pub trait PubTr: PrivTr {}
+
+    pub macro mac1() {
+        let _: Box<PubTr<AssocTy = u8>>;
+        //~^ ERROR trait `priv_trait::PrivTr` is private
+        //~| ERROR trait `priv_trait::PrivTr` is private
+        type InSignatureTy2 = Box<PubTr<AssocTy = u8>>;
+        //~^ ERROR trait `priv_trait::PrivTr` is private
+        trait InSignatureTr2: PubTr<AssocTy = u8> {}
+        //~^ ERROR trait `priv_trait::PrivTr` is private
+    }
+    pub macro mac2() {
+        let _: Box<PrivTr<AssocTy = u8>>;
+        //~^ ERROR trait `priv_trait::PrivTr` is private
+        //~| ERROR trait `priv_trait::PrivTr` is private
+        type InSignatureTy1 = Box<PrivTr<AssocTy = u8>>;
+        //~^ ERROR trait `priv_trait::PrivTr` is private
+        trait InSignatureTr1: PrivTr<AssocTy = u8> {}
+        //~^ ERROR trait `priv_trait::PrivTr` is private
+    }
+}
+fn priv_trait1() {
+    priv_trait::mac1!();
+}
+fn priv_trait2() {
+    priv_trait::mac2!();
+}
+
+mod priv_parent_substs {
+    pub trait PubTrWithParam<T = Priv> {
+        type AssocTy = u8;
+    }
+    struct Priv;
+    pub trait PubTr: PubTrWithParam<Priv> {}
+
+    pub macro mac() {
+        let _: Box<PubTrWithParam<AssocTy = u8>>;
+        //~^ ERROR type `priv_parent_substs::Priv` is private
+        //~| ERROR type `priv_parent_substs::Priv` is private
+        let _: Box<PubTr<AssocTy = u8>>;
+        //~^ ERROR type `priv_parent_substs::Priv` is private
+        //~| ERROR type `priv_parent_substs::Priv` is private
+        pub type InSignatureTy1 = Box<PubTrWithParam<AssocTy = u8>>;
+        //~^ ERROR type `priv_parent_substs::Priv` is private
+        pub type InSignatureTy2 = Box<PubTr<AssocTy = u8>>;
+        //~^ ERROR type `priv_parent_substs::Priv` is private
+        trait InSignatureTr1: PubTrWithParam<AssocTy = u8> {}
+        //~^ ERROR type `priv_parent_substs::Priv` is private
+        trait InSignatureTr2: PubTr<AssocTy = u8> {}
+        //~^ ERROR type `priv_parent_substs::Priv` is private
+    }
+}
+fn priv_parent_substs() {
+    priv_parent_substs::mac!();
+}
+
+fn main() {}
diff --git a/src/test/ui/privacy/associated-item-privacy-type-binding.stderr b/src/test/ui/privacy/associated-item-privacy-type-binding.stderr
new file mode 100644
index 0000000..7f6886d
--- /dev/null
+++ b/src/test/ui/privacy/associated-item-privacy-type-binding.stderr
@@ -0,0 +1,146 @@
+error: trait `priv_trait::PrivTr` is private
+  --> $DIR/associated-item-privacy-type-binding.rs:11:13
+   |
+LL |         let _: Box<PubTr<AssocTy = u8>>;
+   |             ^
+...
+LL |     priv_trait::mac1!();
+   |     -------------------- in this macro invocation
+
+error: trait `priv_trait::PrivTr` is private
+  --> $DIR/associated-item-privacy-type-binding.rs:11:16
+   |
+LL |         let _: Box<PubTr<AssocTy = u8>>;
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     priv_trait::mac1!();
+   |     -------------------- in this macro invocation
+
+error: trait `priv_trait::PrivTr` is private
+  --> $DIR/associated-item-privacy-type-binding.rs:14:31
+   |
+LL |         type InSignatureTy2 = Box<PubTr<AssocTy = u8>>;
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     priv_trait::mac1!();
+   |     -------------------- in this macro invocation
+
+error: trait `priv_trait::PrivTr` is private
+  --> $DIR/associated-item-privacy-type-binding.rs:16:31
+   |
+LL |         trait InSignatureTr2: PubTr<AssocTy = u8> {}
+   |                               ^^^^^^^^^^^^^^^^^^^
+...
+LL |     priv_trait::mac1!();
+   |     -------------------- in this macro invocation
+
+error: trait `priv_trait::PrivTr` is private
+  --> $DIR/associated-item-privacy-type-binding.rs:20:13
+   |
+LL |         let _: Box<PrivTr<AssocTy = u8>>;
+   |             ^
+...
+LL |     priv_trait::mac2!();
+   |     -------------------- in this macro invocation
+
+error: trait `priv_trait::PrivTr` is private
+  --> $DIR/associated-item-privacy-type-binding.rs:20:16
+   |
+LL |         let _: Box<PrivTr<AssocTy = u8>>;
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     priv_trait::mac2!();
+   |     -------------------- in this macro invocation
+
+error: trait `priv_trait::PrivTr` is private
+  --> $DIR/associated-item-privacy-type-binding.rs:23:31
+   |
+LL |         type InSignatureTy1 = Box<PrivTr<AssocTy = u8>>;
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     priv_trait::mac2!();
+   |     -------------------- in this macro invocation
+
+error: trait `priv_trait::PrivTr` is private
+  --> $DIR/associated-item-privacy-type-binding.rs:25:31
+   |
+LL |         trait InSignatureTr1: PrivTr<AssocTy = u8> {}
+   |                               ^^^^^^^^^^^^^^^^^^^^
+...
+LL |     priv_trait::mac2!();
+   |     -------------------- in this macro invocation
+
+error: type `priv_parent_substs::Priv` is private
+  --> $DIR/associated-item-privacy-type-binding.rs:44:13
+   |
+LL |         let _: Box<PubTrWithParam<AssocTy = u8>>;
+   |             ^
+...
+LL |     priv_parent_substs::mac!();
+   |     --------------------------- in this macro invocation
+
+error: type `priv_parent_substs::Priv` is private
+  --> $DIR/associated-item-privacy-type-binding.rs:44:16
+   |
+LL |         let _: Box<PubTrWithParam<AssocTy = u8>>;
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     priv_parent_substs::mac!();
+   |     --------------------------- in this macro invocation
+
+error: type `priv_parent_substs::Priv` is private
+  --> $DIR/associated-item-privacy-type-binding.rs:47:13
+   |
+LL |         let _: Box<PubTr<AssocTy = u8>>;
+   |             ^
+...
+LL |     priv_parent_substs::mac!();
+   |     --------------------------- in this macro invocation
+
+error: type `priv_parent_substs::Priv` is private
+  --> $DIR/associated-item-privacy-type-binding.rs:47:16
+   |
+LL |         let _: Box<PubTr<AssocTy = u8>>;
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     priv_parent_substs::mac!();
+   |     --------------------------- in this macro invocation
+
+error: type `priv_parent_substs::Priv` is private
+  --> $DIR/associated-item-privacy-type-binding.rs:50:35
+   |
+LL |         pub type InSignatureTy1 = Box<PubTrWithParam<AssocTy = u8>>;
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     priv_parent_substs::mac!();
+   |     --------------------------- in this macro invocation
+
+error: type `priv_parent_substs::Priv` is private
+  --> $DIR/associated-item-privacy-type-binding.rs:52:35
+   |
+LL |         pub type InSignatureTy2 = Box<PubTr<AssocTy = u8>>;
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     priv_parent_substs::mac!();
+   |     --------------------------- in this macro invocation
+
+error: type `priv_parent_substs::Priv` is private
+  --> $DIR/associated-item-privacy-type-binding.rs:54:31
+   |
+LL |         trait InSignatureTr1: PubTrWithParam<AssocTy = u8> {}
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     priv_parent_substs::mac!();
+   |     --------------------------- in this macro invocation
+
+error: type `priv_parent_substs::Priv` is private
+  --> $DIR/associated-item-privacy-type-binding.rs:56:31
+   |
+LL |         trait InSignatureTr2: PubTr<AssocTy = u8> {}
+   |                               ^^^^^^^^^^^^^^^^^^^
+...
+LL |     priv_parent_substs::mac!();
+   |     --------------------------- in this macro invocation
+
+error: aborting due to 16 previous errors
+
diff --git a/src/test/ui/privacy/auxiliary/cci_class.rs b/src/test/ui/privacy/auxiliary/cci_class.rs
new file mode 100644
index 0000000..de2945d
--- /dev/null
+++ b/src/test/ui/privacy/auxiliary/cci_class.rs
@@ -0,0 +1,14 @@
+pub mod kitties {
+    pub struct cat {
+      meows : usize,
+
+      pub how_hungry : isize,
+    }
+
+    pub fn cat(in_x : usize, in_y : isize) -> cat  {
+        cat {
+            meows: in_x,
+            how_hungry: in_y
+        }
+    }
+}
diff --git a/src/test/ui/privacy/auxiliary/cci_class_5.rs b/src/test/ui/privacy/auxiliary/cci_class_5.rs
new file mode 100644
index 0000000..3aeaa83
--- /dev/null
+++ b/src/test/ui/privacy/auxiliary/cci_class_5.rs
@@ -0,0 +1,17 @@
+pub mod kitties {
+    pub struct cat {
+        meows : usize,
+        pub how_hungry : isize,
+    }
+
+    impl cat {
+        fn nap(&self) {}
+    }
+
+    pub fn cat(in_x : usize, in_y : isize) -> cat {
+        cat {
+            meows: in_x,
+            how_hungry: in_y
+        }
+    }
+}
diff --git a/src/test/ui/privacy/auxiliary/issue-57264-1.rs b/src/test/ui/privacy/auxiliary/issue-57264-1.rs
new file mode 100644
index 0000000..9302fa0d
--- /dev/null
+++ b/src/test/ui/privacy/auxiliary/issue-57264-1.rs
@@ -0,0 +1,9 @@
+mod inner {
+    pub struct PubUnnameable;
+}
+
+pub struct Pub<T>(T);
+
+impl Pub<inner::PubUnnameable> {
+    pub fn pub_method() {}
+}
diff --git a/src/test/ui/privacy/auxiliary/issue-57264-2.rs b/src/test/ui/privacy/auxiliary/issue-57264-2.rs
new file mode 100644
index 0000000..416206b
--- /dev/null
+++ b/src/test/ui/privacy/auxiliary/issue-57264-2.rs
@@ -0,0 +1,10 @@
+mod inner {
+    pub struct PubUnnameable;
+
+    impl PubUnnameable {
+        pub fn pub_method(self) {}
+    }
+}
+
+pub trait PubTraitWithSingleImplementor {}
+impl PubTraitWithSingleImplementor for Option<inner::PubUnnameable> {}
diff --git a/src/test/ui/privacy/auxiliary/privacy_tuple_struct.rs b/src/test/ui/privacy/auxiliary/privacy_tuple_struct.rs
new file mode 100644
index 0000000..223cda4b
--- /dev/null
+++ b/src/test/ui/privacy/auxiliary/privacy_tuple_struct.rs
@@ -0,0 +1,4 @@
+pub struct A(());
+pub struct B(isize);
+pub struct C(pub isize, isize);
+pub struct D(pub isize);
diff --git a/src/test/ui/privacy/auxiliary/private-inferred-type.rs b/src/test/ui/privacy/auxiliary/private-inferred-type.rs
new file mode 100644
index 0000000..7ac913f
--- /dev/null
+++ b/src/test/ui/privacy/auxiliary/private-inferred-type.rs
@@ -0,0 +1,36 @@
+#![feature(decl_macro)]
+
+fn priv_fn() {}
+static PRIV_STATIC: u8 = 0;
+enum PrivEnum { Variant }
+pub enum PubEnum { Variant }
+trait PrivTrait { fn method() {} }
+impl PrivTrait for u8 {}
+pub trait PubTrait { fn method() {} }
+impl PubTrait for u8 {}
+struct PrivTupleStruct(u8);
+pub struct PubTupleStruct(u8);
+impl PubTupleStruct { fn method() {} }
+
+struct Priv;
+pub type Alias = Priv;
+pub struct Pub<T = Alias>(pub T);
+
+impl Pub<Priv> {
+    pub fn static_method() {}
+}
+impl Pub<u8> {
+    fn priv_method(&self) {}
+}
+
+pub macro m() {
+    priv_fn;
+    PRIV_STATIC;
+    PrivEnum::Variant;
+    PubEnum::Variant;
+    <u8 as PrivTrait>::method;
+    <u8 as PubTrait>::method;
+    PrivTupleStruct;
+    PubTupleStruct;
+    Pub(0u8).priv_method();
+}
diff --git a/src/test/ui/privacy/decl-macro.rs b/src/test/ui/privacy/decl-macro.rs
new file mode 100644
index 0000000..1eb49bd
--- /dev/null
+++ b/src/test/ui/privacy/decl-macro.rs
@@ -0,0 +1,9 @@
+#![feature(decl_macro)]
+
+mod m {
+    macro mac() {}
+}
+
+fn main() {
+    m::mac!(); //~ ERROR macro `mac` is private
+}
diff --git a/src/test/ui/privacy/decl-macro.stderr b/src/test/ui/privacy/decl-macro.stderr
new file mode 100644
index 0000000..230cf95
--- /dev/null
+++ b/src/test/ui/privacy/decl-macro.stderr
@@ -0,0 +1,9 @@
+error[E0603]: macro `mac` is private
+  --> $DIR/decl-macro.rs:8:8
+   |
+LL |     m::mac!();
+   |        ^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0603`.
diff --git a/src/test/ui/privacy/issue-57264-1.rs b/src/test/ui/privacy/issue-57264-1.rs
new file mode 100644
index 0000000..dcffdc3
--- /dev/null
+++ b/src/test/ui/privacy/issue-57264-1.rs
@@ -0,0 +1,8 @@
+// compile-pass
+// aux-build:issue-57264-1.rs
+
+extern crate issue_57264_1;
+
+fn main() {
+    issue_57264_1::Pub::pub_method();
+}
diff --git a/src/test/ui/privacy/issue-57264-2.rs b/src/test/ui/privacy/issue-57264-2.rs
new file mode 100644
index 0000000..79d0d2c
--- /dev/null
+++ b/src/test/ui/privacy/issue-57264-2.rs
@@ -0,0 +1,10 @@
+// compile-pass
+// aux-build:issue-57264-2.rs
+
+extern crate issue_57264_2;
+
+fn infer<T: issue_57264_2::PubTraitWithSingleImplementor>(arg: T) -> T { arg }
+
+fn main() {
+    infer(None).unwrap().pub_method();
+}
diff --git a/src/test/ui/privacy/legacy-ctor-visibility.rs b/src/test/ui/privacy/legacy-ctor-visibility.rs
new file mode 100644
index 0000000..7db4be7
--- /dev/null
+++ b/src/test/ui/privacy/legacy-ctor-visibility.rs
@@ -0,0 +1,20 @@
+// ignore-tidy-linelength
+
+#![allow(unused)]
+
+use m::S;
+
+mod m {
+    pub struct S(u8);
+
+    mod n {
+        use S;
+        fn f() {
+            S(10);
+            //~^ ERROR private struct constructors are not usable through re-exports in outer modules
+            //~| WARN this was previously accepted
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/privacy/legacy-ctor-visibility.stderr b/src/test/ui/privacy/legacy-ctor-visibility.stderr
new file mode 100644
index 0000000..f059095
--- /dev/null
+++ b/src/test/ui/privacy/legacy-ctor-visibility.stderr
@@ -0,0 +1,12 @@
+error: private struct constructors are not usable through re-exports in outer modules
+  --> $DIR/legacy-ctor-visibility.rs:13:13
+   |
+LL |             S(10);
+   |             ^
+   |
+   = note: #[deny(legacy_constructor_visibility)] on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #39207 <https://github.com/rust-lang/rust/issues/39207>
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/privacy/privacy-in-paths.rs b/src/test/ui/privacy/privacy-in-paths.rs
new file mode 100644
index 0000000..9cee2b8
--- /dev/null
+++ b/src/test/ui/privacy/privacy-in-paths.rs
@@ -0,0 +1,30 @@
+mod foo {
+    pub use self::bar::S;
+    mod bar {
+        pub struct S;
+        pub use baz;
+    }
+
+    trait T {
+        type Assoc;
+    }
+    impl T for () {
+        type Assoc = S;
+    }
+}
+
+impl foo::S {
+    fn f() {}
+}
+
+pub mod baz {
+    fn f() {}
+
+    fn g() {
+        ::foo::bar::baz::f(); //~ERROR module `bar` is private
+        ::foo::bar::S::f(); //~ERROR module `bar` is private
+        <() as ::foo::T>::Assoc::f(); //~ERROR trait `T` is private
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/privacy/privacy-in-paths.stderr b/src/test/ui/privacy/privacy-in-paths.stderr
new file mode 100644
index 0000000..4b9faca
--- /dev/null
+++ b/src/test/ui/privacy/privacy-in-paths.stderr
@@ -0,0 +1,21 @@
+error[E0603]: module `bar` is private
+  --> $DIR/privacy-in-paths.rs:24:16
+   |
+LL |         ::foo::bar::baz::f();
+   |                ^^^
+
+error[E0603]: module `bar` is private
+  --> $DIR/privacy-in-paths.rs:25:16
+   |
+LL |         ::foo::bar::S::f();
+   |                ^^^
+
+error[E0603]: trait `T` is private
+  --> $DIR/privacy-in-paths.rs:26:23
+   |
+LL |         <() as ::foo::T>::Assoc::f();
+   |                       ^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0603`.
diff --git a/src/test/ui/privacy/privacy-ns1.rs b/src/test/ui/privacy/privacy-ns1.rs
new file mode 100644
index 0000000..91cf8e8
--- /dev/null
+++ b/src/test/ui/privacy/privacy-ns1.rs
@@ -0,0 +1,55 @@
+// Check we do the correct privacy checks when we import a name and there is an
+// item with that name in both the value and type namespaces.
+
+#![allow(dead_code)]
+#![allow(unused_imports)]
+
+
+// public type, private value
+pub mod foo1 {
+    pub trait Bar {
+    }
+    pub struct Baz;
+
+    fn Bar() { }
+}
+
+fn test_glob1() {
+    use foo1::*;
+
+    Bar();  //~ ERROR expected function, found trait `Bar`
+}
+
+// private type, public value
+pub mod foo2 {
+    trait Bar {
+    }
+    pub struct Baz;
+
+    pub fn Bar() { }
+}
+
+fn test_glob2() {
+    use foo2::*;
+
+    let _x: Box<Bar>;  //~ ERROR expected type, found function `Bar`
+}
+
+// neither public
+pub mod foo3 {
+    trait Bar {
+    }
+    pub struct Baz;
+
+    fn Bar() { }
+}
+
+fn test_glob3() {
+    use foo3::*;
+
+    Bar();  //~ ERROR cannot find function `Bar` in this scope
+    let _x: Box<Bar>;  //~ ERROR cannot find type `Bar` in this scope
+}
+
+fn main() {
+}
diff --git a/src/test/ui/privacy/privacy-ns1.stderr b/src/test/ui/privacy/privacy-ns1.stderr
new file mode 100644
index 0000000..07b013b
--- /dev/null
+++ b/src/test/ui/privacy/privacy-ns1.stderr
@@ -0,0 +1,76 @@
+error[E0423]: expected function, found trait `Bar`
+  --> $DIR/privacy-ns1.rs:20:5
+   |
+LL |     Bar();
+   |     ^^^
+help: a unit struct with a similar name exists
+   |
+LL |     Baz();
+   |     ^^^
+help: possible better candidates are found in other modules, you can import them into scope
+   |
+LL | use foo1::Bar;
+   |
+LL | use foo2::Bar;
+   |
+LL | use foo3::Bar;
+   |
+
+error[E0573]: expected type, found function `Bar`
+  --> $DIR/privacy-ns1.rs:35:17
+   |
+LL |     let _x: Box<Bar>;
+   |                 ^^^
+help: a struct with a similar name exists
+   |
+LL |     let _x: Box<Baz>;
+   |                 ^^^
+help: possible better candidates are found in other modules, you can import them into scope
+   |
+LL | use foo1::Bar;
+   |
+LL | use foo2::Bar;
+   |
+LL | use foo3::Bar;
+   |
+
+error[E0425]: cannot find function `Bar` in this scope
+  --> $DIR/privacy-ns1.rs:50:5
+   |
+LL |     Bar();
+   |     ^^^
+help: a unit struct with a similar name exists
+   |
+LL |     Baz();
+   |     ^^^
+help: possible candidates are found in other modules, you can import them into scope
+   |
+LL | use foo1::Bar;
+   |
+LL | use foo2::Bar;
+   |
+LL | use foo3::Bar;
+   |
+
+error[E0412]: cannot find type `Bar` in this scope
+  --> $DIR/privacy-ns1.rs:51:17
+   |
+LL |     let _x: Box<Bar>;
+   |                 ^^^
+help: a struct with a similar name exists
+   |
+LL |     let _x: Box<Baz>;
+   |                 ^^^
+help: possible candidates are found in other modules, you can import them into scope
+   |
+LL | use foo1::Bar;
+   |
+LL | use foo2::Bar;
+   |
+LL | use foo3::Bar;
+   |
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0412, E0423, E0425, E0573.
+For more information about an error, try `rustc --explain E0412`.
diff --git a/src/test/ui/privacy/privacy-ns2.rs b/src/test/ui/privacy/privacy-ns2.rs
new file mode 100644
index 0000000..c4e400f
--- /dev/null
+++ b/src/test/ui/privacy/privacy-ns2.rs
@@ -0,0 +1,78 @@
+// Check we do the correct privacy checks when we import a name and there is an
+// item with that name in both the value and type namespaces.
+
+#![allow(dead_code)]
+#![allow(unused_imports)]
+
+
+// public type, private value
+pub mod foo1 {
+    pub trait Bar {
+    }
+    pub struct Baz;
+
+    fn Bar() { }
+}
+
+fn test_single1() {
+    use foo1::Bar;
+
+    Bar(); //~ ERROR expected function, found trait `Bar`
+}
+
+fn test_list1() {
+    use foo1::{Bar,Baz};
+
+    Bar(); //~ ERROR expected function, found trait `Bar`
+}
+
+// private type, public value
+pub mod foo2 {
+    trait Bar {
+    }
+    pub struct Baz;
+
+    pub fn Bar() { }
+}
+
+fn test_single2() {
+    use foo2::Bar;
+
+    let _x : Box<Bar>; //~ ERROR expected type, found function `Bar`
+}
+
+fn test_list2() {
+    use foo2::{Bar,Baz};
+
+    let _x: Box<Bar>; //~ ERROR expected type, found function `Bar`
+}
+
+// neither public
+pub mod foo3 {
+    trait Bar {
+    }
+    pub struct Baz;
+
+    fn Bar() { }
+}
+
+fn test_unused3() {
+    use foo3::Bar;  //~ ERROR `Bar` is private
+}
+
+fn test_single3() {
+    use foo3::Bar;  //~ ERROR `Bar` is private
+
+    Bar();
+    let _x: Box<Bar>;
+}
+
+fn test_list3() {
+    use foo3::{Bar,Baz};  //~ ERROR `Bar` is private
+
+    Bar();
+    let _x: Box<Bar>;
+}
+
+fn main() {
+}
diff --git a/src/test/ui/privacy/privacy-ns2.stderr b/src/test/ui/privacy/privacy-ns2.stderr
new file mode 100644
index 0000000..cd5b5369
--- /dev/null
+++ b/src/test/ui/privacy/privacy-ns2.stderr
@@ -0,0 +1,86 @@
+error[E0423]: expected function, found trait `Bar`
+  --> $DIR/privacy-ns2.rs:20:5
+   |
+LL |     Bar();
+   |     ^^^ not a function
+help: possible better candidates are found in other modules, you can import them into scope
+   |
+LL | use foo1::Bar;
+   |
+LL | use foo2::Bar;
+   |
+LL | use foo3::Bar;
+   |
+
+error[E0423]: expected function, found trait `Bar`
+  --> $DIR/privacy-ns2.rs:26:5
+   |
+LL |     Bar();
+   |     ^^^
+help: a unit struct with a similar name exists
+   |
+LL |     Baz();
+   |     ^^^
+help: possible better candidates are found in other modules, you can import them into scope
+   |
+LL | use foo1::Bar;
+   |
+LL | use foo2::Bar;
+   |
+LL | use foo3::Bar;
+   |
+
+error[E0573]: expected type, found function `Bar`
+  --> $DIR/privacy-ns2.rs:41:18
+   |
+LL |     let _x : Box<Bar>;
+   |                  ^^^ not a type
+help: possible better candidates are found in other modules, you can import them into scope
+   |
+LL | use foo1::Bar;
+   |
+LL | use foo2::Bar;
+   |
+LL | use foo3::Bar;
+   |
+
+error[E0573]: expected type, found function `Bar`
+  --> $DIR/privacy-ns2.rs:47:17
+   |
+LL |     let _x: Box<Bar>;
+   |                 ^^^
+help: a struct with a similar name exists
+   |
+LL |     let _x: Box<Baz>;
+   |                 ^^^
+help: possible better candidates are found in other modules, you can import them into scope
+   |
+LL | use foo1::Bar;
+   |
+LL | use foo2::Bar;
+   |
+LL | use foo3::Bar;
+   |
+
+error[E0603]: trait `Bar` is private
+  --> $DIR/privacy-ns2.rs:60:15
+   |
+LL |     use foo3::Bar;
+   |               ^^^
+
+error[E0603]: trait `Bar` is private
+  --> $DIR/privacy-ns2.rs:64:15
+   |
+LL |     use foo3::Bar;
+   |               ^^^
+
+error[E0603]: trait `Bar` is private
+  --> $DIR/privacy-ns2.rs:71:16
+   |
+LL |     use foo3::{Bar,Baz};
+   |                ^^^
+
+error: aborting due to 7 previous errors
+
+Some errors occurred: E0423, E0573, E0603.
+For more information about an error, try `rustc --explain E0423`.
diff --git a/src/test/ui/privacy/privacy-sanity.rs b/src/test/ui/privacy/privacy-sanity.rs
new file mode 100644
index 0000000..f83b24c
--- /dev/null
+++ b/src/test/ui/privacy/privacy-sanity.rs
@@ -0,0 +1,82 @@
+#![feature(optin_builtin_traits)]
+
+pub trait Tr {
+    fn f();
+    const C: u8;
+    type T;
+}
+pub struct S {
+    pub a: u8
+}
+struct Ts(pub u8);
+
+pub impl Tr for S {  //~ ERROR unnecessary visibility qualifier
+    pub fn f() {} //~ ERROR unnecessary visibility qualifier
+    pub const C: u8 = 0; //~ ERROR unnecessary visibility qualifier
+    pub type T = u8; //~ ERROR unnecessary visibility qualifier
+}
+pub impl S { //~ ERROR unnecessary visibility qualifier
+    pub fn f() {}
+    pub const C: u8 = 0;
+    // pub type T = u8;
+}
+pub extern "C" { //~ ERROR unnecessary visibility qualifier
+    pub fn f();
+    pub static St: u8;
+}
+
+const MAIN: u8 = {
+    pub trait Tr {
+        fn f();
+        const C: u8;
+        type T;
+    }
+    pub struct S {
+        pub a: u8
+    }
+    struct Ts(pub u8);
+
+    pub impl Tr for S {  //~ ERROR unnecessary visibility qualifier
+        pub fn f() {} //~ ERROR unnecessary visibility qualifier
+        pub const C: u8 = 0; //~ ERROR unnecessary visibility qualifier
+        pub type T = u8; //~ ERROR unnecessary visibility qualifier
+    }
+    pub impl S { //~ ERROR unnecessary visibility qualifier
+        pub fn f() {}
+        pub const C: u8 = 0;
+        // pub type T = u8;
+    }
+    pub extern "C" { //~ ERROR unnecessary visibility qualifier
+        pub fn f();
+        pub static St: u8;
+    }
+
+    0
+};
+
+fn main() {
+    pub trait Tr {
+        fn f();
+        const C: u8;
+        type T;
+    }
+    pub struct S {
+        pub a: u8
+    }
+    struct Ts(pub u8);
+
+    pub impl Tr for S {  //~ ERROR unnecessary visibility qualifier
+        pub fn f() {} //~ ERROR unnecessary visibility qualifier
+        pub const C: u8 = 0; //~ ERROR unnecessary visibility qualifier
+        pub type T = u8; //~ ERROR unnecessary visibility qualifier
+    }
+    pub impl S { //~ ERROR unnecessary visibility qualifier
+        pub fn f() {}
+        pub const C: u8 = 0;
+        // pub type T = u8;
+    }
+    pub extern "C" { //~ ERROR unnecessary visibility qualifier
+        pub fn f();
+        pub static St: u8;
+    }
+}
diff --git a/src/test/ui/privacy/privacy-sanity.stderr b/src/test/ui/privacy/privacy-sanity.stderr
new file mode 100644
index 0000000..c92553f
--- /dev/null
+++ b/src/test/ui/privacy/privacy-sanity.stderr
@@ -0,0 +1,123 @@
+error[E0449]: unnecessary visibility qualifier
+  --> $DIR/privacy-sanity.rs:13:1
+   |
+LL | pub impl Tr for S {
+   | ^^^ `pub` not permitted here because it's implied
+
+error[E0449]: unnecessary visibility qualifier
+  --> $DIR/privacy-sanity.rs:14:5
+   |
+LL |     pub fn f() {}
+   |     ^^^ `pub` not permitted here because it's implied
+
+error[E0449]: unnecessary visibility qualifier
+  --> $DIR/privacy-sanity.rs:15:5
+   |
+LL |     pub const C: u8 = 0;
+   |     ^^^ `pub` not permitted here because it's implied
+
+error[E0449]: unnecessary visibility qualifier
+  --> $DIR/privacy-sanity.rs:16:5
+   |
+LL |     pub type T = u8;
+   |     ^^^ `pub` not permitted here because it's implied
+
+error[E0449]: unnecessary visibility qualifier
+  --> $DIR/privacy-sanity.rs:18:1
+   |
+LL | pub impl S {
+   | ^^^ `pub` not permitted here because it's implied
+   |
+   = note: place qualifiers on individual impl items instead
+
+error[E0449]: unnecessary visibility qualifier
+  --> $DIR/privacy-sanity.rs:23:1
+   |
+LL | pub extern "C" {
+   | ^^^ `pub` not permitted here because it's implied
+   |
+   = note: place qualifiers on individual foreign items instead
+
+error[E0449]: unnecessary visibility qualifier
+  --> $DIR/privacy-sanity.rs:39:5
+   |
+LL |     pub impl Tr for S {
+   |     ^^^ `pub` not permitted here because it's implied
+
+error[E0449]: unnecessary visibility qualifier
+  --> $DIR/privacy-sanity.rs:40:9
+   |
+LL |         pub fn f() {}
+   |         ^^^ `pub` not permitted here because it's implied
+
+error[E0449]: unnecessary visibility qualifier
+  --> $DIR/privacy-sanity.rs:41:9
+   |
+LL |         pub const C: u8 = 0;
+   |         ^^^ `pub` not permitted here because it's implied
+
+error[E0449]: unnecessary visibility qualifier
+  --> $DIR/privacy-sanity.rs:42:9
+   |
+LL |         pub type T = u8;
+   |         ^^^ `pub` not permitted here because it's implied
+
+error[E0449]: unnecessary visibility qualifier
+  --> $DIR/privacy-sanity.rs:44:5
+   |
+LL |     pub impl S {
+   |     ^^^ `pub` not permitted here because it's implied
+   |
+   = note: place qualifiers on individual impl items instead
+
+error[E0449]: unnecessary visibility qualifier
+  --> $DIR/privacy-sanity.rs:49:5
+   |
+LL |     pub extern "C" {
+   |     ^^^ `pub` not permitted here because it's implied
+   |
+   = note: place qualifiers on individual foreign items instead
+
+error[E0449]: unnecessary visibility qualifier
+  --> $DIR/privacy-sanity.rs:68:5
+   |
+LL |     pub impl Tr for S {
+   |     ^^^ `pub` not permitted here because it's implied
+
+error[E0449]: unnecessary visibility qualifier
+  --> $DIR/privacy-sanity.rs:69:9
+   |
+LL |         pub fn f() {}
+   |         ^^^ `pub` not permitted here because it's implied
+
+error[E0449]: unnecessary visibility qualifier
+  --> $DIR/privacy-sanity.rs:70:9
+   |
+LL |         pub const C: u8 = 0;
+   |         ^^^ `pub` not permitted here because it's implied
+
+error[E0449]: unnecessary visibility qualifier
+  --> $DIR/privacy-sanity.rs:71:9
+   |
+LL |         pub type T = u8;
+   |         ^^^ `pub` not permitted here because it's implied
+
+error[E0449]: unnecessary visibility qualifier
+  --> $DIR/privacy-sanity.rs:73:5
+   |
+LL |     pub impl S {
+   |     ^^^ `pub` not permitted here because it's implied
+   |
+   = note: place qualifiers on individual impl items instead
+
+error[E0449]: unnecessary visibility qualifier
+  --> $DIR/privacy-sanity.rs:78:5
+   |
+LL |     pub extern "C" {
+   |     ^^^ `pub` not permitted here because it's implied
+   |
+   = note: place qualifiers on individual foreign items instead
+
+error: aborting due to 18 previous errors
+
+For more information about this error, try `rustc --explain E0449`.
diff --git a/src/test/ui/privacy/privacy-ufcs.rs b/src/test/ui/privacy/privacy-ufcs.rs
new file mode 100644
index 0000000..fec7f41
--- /dev/null
+++ b/src/test/ui/privacy/privacy-ufcs.rs
@@ -0,0 +1,13 @@
+// Test to ensure private traits are inaccessible with UFCS angle-bracket syntax.
+
+mod foo {
+    trait Bar {
+        fn baz() {}
+    }
+
+    impl Bar for i32 {}
+}
+
+fn main() {
+    <i32 as ::foo::Bar>::baz(); //~ERROR trait `Bar` is private
+}
diff --git a/src/test/ui/privacy/privacy-ufcs.stderr b/src/test/ui/privacy/privacy-ufcs.stderr
new file mode 100644
index 0000000..6be14df
--- /dev/null
+++ b/src/test/ui/privacy/privacy-ufcs.stderr
@@ -0,0 +1,9 @@
+error[E0603]: trait `Bar` is private
+  --> $DIR/privacy-ufcs.rs:12:20
+   |
+LL |     <i32 as ::foo::Bar>::baz();
+   |                    ^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0603`.
diff --git a/src/test/ui/privacy/privacy1.rs b/src/test/ui/privacy/privacy1.rs
new file mode 100644
index 0000000..d376237
--- /dev/null
+++ b/src/test/ui/privacy/privacy1.rs
@@ -0,0 +1,175 @@
+#![feature(lang_items, start, no_core)]
+#![no_core] // makes debugging this test *a lot* easier (during resolve)
+
+#[lang="sized"]
+pub trait Sized {}
+
+#[lang="copy"]
+pub trait Copy {}
+
+#[lang="deref"]
+pub trait Deref {
+    type Target;
+}
+
+#[lang="receiver"]
+pub trait Receiver: Deref {}
+
+impl<'a, T> Deref for &'a T {
+    type Target = T;
+}
+
+impl<'a, T> Receiver for &'a T {}
+
+mod bar {
+    // shouldn't bring in too much
+    pub use self::glob::*;
+
+    // can't publicly re-export private items
+    pub use self::baz::{foo, bar};
+
+    pub struct A;
+    impl A {
+        pub fn foo() {}
+        fn bar() {}
+
+        pub fn foo2(&self) {}
+        fn bar2(&self) {}
+    }
+
+    trait B {
+        fn foo() -> Self;
+    }
+
+    impl B for isize { fn foo() -> isize { 3 } }
+
+    pub enum Enum {
+        Pub
+    }
+
+    mod baz {
+        pub struct A;
+        impl A {
+            pub fn foo() {}
+            fn bar() {}
+
+            pub fn foo2(&self) {}
+            fn bar2(&self) {}
+        }
+
+        pub fn foo() {}
+        pub fn bar() {}
+    }
+
+    extern {
+        fn epriv();
+        pub fn epub();
+    }
+
+    fn test() {
+        self::Enum::Pub;
+        unsafe {
+            epriv();
+            epub();
+        }
+        self::baz::A;
+        self::baz::A::foo();
+        self::baz::A::bar(); //~ ERROR: method `bar` is private
+        self::baz::A.foo2();
+
+        // this used to cause an ICE in privacy traversal.
+        super::gpub();
+    }
+
+    mod glob {
+        pub fn gpub() {}
+        fn gpriv() {}
+    }
+}
+
+pub fn gpub() {}
+
+fn lol() {
+    bar::A;
+    bar::A::foo();
+    bar::A::bar(); //~ ERROR: method `bar` is private
+    bar::A.foo2();
+}
+
+mod foo {
+    fn test() {
+        ::bar::A::foo();
+        ::bar::A::bar();        //~ ERROR: method `bar` is private
+        ::bar::A.foo2();
+        ::bar::baz::A::foo();   //~ ERROR: module `baz` is private
+        ::bar::baz::A::bar();   //~ ERROR: module `baz` is private
+                                //~^ ERROR: method `bar` is private
+        ::bar::baz::A.foo2();   //~ ERROR: module `baz` is private
+        ::bar::baz::A.bar2();   //~ ERROR: module `baz` is private
+                                //~^ ERROR: method `bar2` is private
+
+        let _: isize =
+        ::bar::B::foo();        //~ ERROR: trait `B` is private
+        ::lol();
+
+        ::bar::Enum::Pub;
+
+        unsafe {
+            ::bar::epriv(); //~ ERROR: function `epriv` is private
+            ::bar::epub();
+        }
+
+        ::bar::foo();
+        ::bar::bar();
+
+        ::bar::gpub();
+
+        ::bar::baz::foo(); //~ ERROR: module `baz` is private
+        ::bar::baz::bar(); //~ ERROR: module `baz` is private
+    }
+
+    fn test2() {
+        use bar::baz::{foo, bar};
+        //~^ ERROR: module `baz` is private
+
+        foo();
+        bar();
+    }
+
+    fn test3() {
+        use bar::baz;
+        //~^ ERROR: module `baz` is private
+    }
+
+    fn test4() {
+        use bar::{foo, bar};
+        foo();
+        bar();
+    }
+
+    fn test5() {
+        use bar;
+        bar::foo();
+        bar::bar();
+    }
+
+    impl ::bar::B for f32 { fn foo() -> f32 { 1.0 } }
+    //~^ ERROR: trait `B` is private
+}
+
+pub mod mytest {
+    // Even though the inner `A` struct is a publicly exported item (usable from
+    // external crates through `foo::foo`, it should not be accessible through
+    // its definition path (which has the private `i` module).
+    use self::foo::i::A; //~ ERROR: module `i` is private
+
+    pub mod foo {
+        pub use self::i::A as foo;
+
+        mod i {
+            pub struct A;
+        }
+    }
+}
+
+#[start] fn main(_: isize, _: *const *const u8) -> isize { 3 }
diff --git a/src/test/ui/privacy/privacy1.stderr b/src/test/ui/privacy/privacy1.stderr
new file mode 100644
index 0000000..73672d1
--- /dev/null
+++ b/src/test/ui/privacy/privacy1.stderr
@@ -0,0 +1,106 @@
+error[E0603]: module `baz` is private
+  --> $DIR/privacy1.rs:132:18
+   |
+LL |         use bar::baz::{foo, bar};
+   |                  ^^^
+
+error[E0603]: module `baz` is private
+  --> $DIR/privacy1.rs:140:18
+   |
+LL |         use bar::baz;
+   |                  ^^^
+
+error[E0603]: module `i` is private
+  --> $DIR/privacy1.rs:164:20
+   |
+LL |     use self::foo::i::A;
+   |                    ^
+
+error[E0603]: module `baz` is private
+  --> $DIR/privacy1.rs:104:16
+   |
+LL |         ::bar::baz::A::foo();
+   |                ^^^
+
+error[E0603]: module `baz` is private
+  --> $DIR/privacy1.rs:105:16
+   |
+LL |         ::bar::baz::A::bar();
+   |                ^^^
+
+error[E0603]: module `baz` is private
+  --> $DIR/privacy1.rs:107:16
+   |
+LL |         ::bar::baz::A.foo2();
+   |                ^^^
+
+error[E0603]: module `baz` is private
+  --> $DIR/privacy1.rs:108:16
+   |
+LL |         ::bar::baz::A.bar2();
+   |                ^^^
+
+error[E0603]: trait `B` is private
+  --> $DIR/privacy1.rs:112:16
+   |
+LL |         ::bar::B::foo();
+   |                ^
+
+error[E0603]: function `epriv` is private
+  --> $DIR/privacy1.rs:118:20
+   |
+LL |             ::bar::epriv();
+   |                    ^^^^^
+
+error[E0603]: module `baz` is private
+  --> $DIR/privacy1.rs:127:16
+   |
+LL |         ::bar::baz::foo();
+   |                ^^^
+
+error[E0603]: module `baz` is private
+  --> $DIR/privacy1.rs:128:16
+   |
+LL |         ::bar::baz::bar();
+   |                ^^^
+
+error[E0603]: trait `B` is private
+  --> $DIR/privacy1.rs:156:17
+   |
+LL |     impl ::bar::B for f32 { fn foo() -> f32 { 1.0 } }
+   |                 ^
+
+error[E0624]: method `bar` is private
+  --> $DIR/privacy1.rs:77:9
+   |
+LL |         self::baz::A::bar();
+   |         ^^^^^^^^^^^^^^^^^
+
+error[E0624]: method `bar` is private
+  --> $DIR/privacy1.rs:95:5
+   |
+LL |     bar::A::bar();
+   |     ^^^^^^^^^^^
+
+error[E0624]: method `bar` is private
+  --> $DIR/privacy1.rs:102:9
+   |
+LL |         ::bar::A::bar();
+   |         ^^^^^^^^^^^^^
+
+error[E0624]: method `bar` is private
+  --> $DIR/privacy1.rs:105:9
+   |
+LL |         ::bar::baz::A::bar();
+   |         ^^^^^^^^^^^^^^^^^^
+
+error[E0624]: method `bar2` is private
+  --> $DIR/privacy1.rs:108:23
+   |
+LL |         ::bar::baz::A.bar2();
+   |                       ^^^^
+
+error: aborting due to 17 previous errors
+
+Some errors occurred: E0603, E0624.
+For more information about an error, try `rustc --explain E0603`.
diff --git a/src/test/ui/privacy/privacy2.rs b/src/test/ui/privacy/privacy2.rs
new file mode 100644
index 0000000..c8fa436
--- /dev/null
+++ b/src/test/ui/privacy/privacy2.rs
@@ -0,0 +1,27 @@
+#![feature(start, no_core)]
+#![no_core] // makes debugging this test *a lot* easier (during resolve)
+
+// Test to make sure that globs don't leak in regular `use` statements.
+
+mod bar {
+    pub use self::glob::*;
+
+    pub mod glob {
+        use foo;
+    }
+}
+
+pub fn foo() {}
+
+fn test1() {
+    use bar::foo;
+    //~^ ERROR unresolved import `bar::foo` [E0432]
+    //~| no `foo` in `bar`
+}
+
+fn test2() {
+    use bar::glob::foo;
+    //~^ ERROR `foo` is private
+}
+
+#[start] fn main(_: isize, _: *const *const u8) -> isize { 3 }
diff --git a/src/test/ui/privacy/privacy2.stderr b/src/test/ui/privacy/privacy2.stderr
new file mode 100644
index 0000000..2e6bb99
--- /dev/null
+++ b/src/test/ui/privacy/privacy2.stderr
@@ -0,0 +1,18 @@
+error[E0432]: unresolved import `bar::foo`
+  --> $DIR/privacy2.rs:17:9
+   |
+LL |     use bar::foo;
+   |         ^^^^^^^^ no `foo` in `bar`
+
+error[E0603]: function `foo` is private
+  --> $DIR/privacy2.rs:23:20
+   |
+LL |     use bar::glob::foo;
+   |                    ^^^
+
+error: requires `sized` lang_item
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0432, E0603.
+For more information about an error, try `rustc --explain E0432`.
diff --git a/src/test/ui/privacy/privacy3.rs b/src/test/ui/privacy/privacy3.rs
new file mode 100644
index 0000000..5a7cd76
--- /dev/null
+++ b/src/test/ui/privacy/privacy3.rs
@@ -0,0 +1,27 @@
+#![feature(start, no_core)]
+#![no_core] // makes debugging this test *a lot* easier (during resolve)
+
+// Test to make sure that private items imported through globs remain private
+// when  they're used.
+
+mod bar {
+    pub use self::glob::*;
+
+    mod glob {
+        fn gpriv() {}
+    }
+}
+
+pub fn foo() {}
+
+fn test1() {
+    use bar::gpriv;
+    //~^ ERROR unresolved import `bar::gpriv` [E0432]
+    //~| no `gpriv` in `bar`
+
+    // This should pass because the compiler will insert a fake name binding
+    // for `gpriv`
+    gpriv();
+}
+
+#[start] fn main(_: isize, _: *const *const u8) -> isize { 3 }
diff --git a/src/test/ui/privacy/privacy3.stderr b/src/test/ui/privacy/privacy3.stderr
new file mode 100644
index 0000000..22c1e48
--- /dev/null
+++ b/src/test/ui/privacy/privacy3.stderr
@@ -0,0 +1,11 @@
+error[E0432]: unresolved import `bar::gpriv`
+  --> $DIR/privacy3.rs:18:9
+   |
+LL |     use bar::gpriv;
+   |         ^^^^^^^^^^ no `gpriv` in `bar`
+
+error: requires `sized` lang_item
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/privacy/privacy4.rs b/src/test/ui/privacy/privacy4.rs
new file mode 100644
index 0000000..fa257b8
--- /dev/null
+++ b/src/test/ui/privacy/privacy4.rs
@@ -0,0 +1,25 @@
+#![feature(lang_items, start, no_core)]
+#![no_core] // makes debugging this test *a lot* easier (during resolve)
+
+#[lang = "sized"] pub trait Sized {}
+#[lang="copy"] pub trait Copy {}
+
+// Test to make sure that private items imported through globs remain private
+// when  they're used.
+
+mod bar {
+    pub use self::glob::*;
+
+    mod glob {
+        fn gpriv() {}
+    }
+}
+
+pub fn foo() {}
+
+fn test2() {
+    use bar::glob::gpriv; //~ ERROR: module `glob` is private
+    gpriv();
+}
+
+#[start] fn main(_: isize, _: *const *const u8) -> isize { 3 }
diff --git a/src/test/ui/privacy/privacy4.stderr b/src/test/ui/privacy/privacy4.stderr
new file mode 100644
index 0000000..e4a20f9
--- /dev/null
+++ b/src/test/ui/privacy/privacy4.stderr
@@ -0,0 +1,9 @@
+error[E0603]: module `glob` is private
+  --> $DIR/privacy4.rs:21:14
+   |
+LL |     use bar::glob::gpriv;
+   |              ^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0603`.
diff --git a/src/test/ui/privacy/privacy5.rs b/src/test/ui/privacy/privacy5.rs
new file mode 100644
index 0000000..741ba0b
--- /dev/null
+++ b/src/test/ui/privacy/privacy5.rs
@@ -0,0 +1,128 @@
+// aux-build:privacy_tuple_struct.rs
+
+extern crate privacy_tuple_struct as other;
+
+mod a {
+    pub struct A(());
+    pub struct B(isize);
+    pub struct C(pub isize, isize);
+    pub struct D(pub isize);
+
+    fn test() {
+        let a = A(());
+        let b = B(2);
+        let c = C(2, 3);
+        let d = D(4);
+
+        let A(()) = a;
+        let A(_) = a;
+        match a { A(()) => {} }
+        match a { A(_) => {} }
+
+        let B(_) = b;
+        let B(_b) = b;
+        match b { B(_) => {} }
+        match b { B(_b) => {} }
+        match b { B(1) => {} B(_) => {} }
+
+        let C(_, _) = c;
+        let C(_a, _) = c;
+        let C(_, _b) = c;
+        let C(_a, _b) = c;
+        match c { C(_, _) => {} }
+        match c { C(_a, _) => {} }
+        match c { C(_, _b) => {} }
+        match c { C(_a, _b) => {} }
+
+        let D(_) = d;
+        let D(_d) = d;
+        match d { D(_) => {} }
+        match d { D(_d) => {} }
+        match d { D(1) => {} D(_) => {} }
+
+        let a2 = A;
+        let b2 = B;
+        let c2 = C;
+        let d2 = D;
+    }
+}
+
+fn this_crate() {
+    let a = a::A(()); //~ ERROR tuple struct `A` is private
+    let b = a::B(2); //~ ERROR tuple struct `B` is private
+    let c = a::C(2, 3); //~ ERROR tuple struct `C` is private
+    let d = a::D(4);
+
+    let a::A(()) = a; //~ ERROR tuple struct `A` is private
+    let a::A(_) = a; //~ ERROR tuple struct `A` is private
+    match a { a::A(()) => {} } //~ ERROR tuple struct `A` is private
+    match a { a::A(_) => {} } //~ ERROR tuple struct `A` is private
+
+    let a::B(_) = b; //~ ERROR tuple struct `B` is private
+    let a::B(_b) = b; //~ ERROR tuple struct `B` is private
+    match b { a::B(_) => {} } //~ ERROR tuple struct `B` is private
+    match b { a::B(_b) => {} } //~ ERROR tuple struct `B` is private
+    match b { a::B(1) => {} a::B(_) => {} } //~ ERROR tuple struct `B` is private
+                                            //~^ ERROR tuple struct `B` is private
+
+    let a::C(_, _) = c; //~ ERROR tuple struct `C` is private
+    let a::C(_a, _) = c; //~ ERROR tuple struct `C` is private
+    let a::C(_, _b) = c; //~ ERROR tuple struct `C` is private
+    let a::C(_a, _b) = c; //~ ERROR tuple struct `C` is private
+    match c { a::C(_, _) => {} } //~ ERROR tuple struct `C` is private
+    match c { a::C(_a, _) => {} } //~ ERROR tuple struct `C` is private
+    match c { a::C(_, _b) => {} } //~ ERROR tuple struct `C` is private
+    match c { a::C(_a, _b) => {} } //~ ERROR tuple struct `C` is private
+
+    let a::D(_) = d;
+    let a::D(_d) = d;
+    match d { a::D(_) => {} }
+    match d { a::D(_d) => {} }
+    match d { a::D(1) => {} a::D(_) => {} }
+
+    let a2 = a::A; //~ ERROR tuple struct `A` is private
+    let b2 = a::B; //~ ERROR tuple struct `B` is private
+    let c2 = a::C; //~ ERROR tuple struct `C` is private
+    let d2 = a::D;
+}
+
+fn xcrate() {
+    let a = other::A(()); //~ ERROR tuple struct `A` is private
+    let b = other::B(2); //~ ERROR tuple struct `B` is private
+    let c = other::C(2, 3); //~ ERROR tuple struct `C` is private
+    let d = other::D(4);
+
+    let other::A(()) = a; //~ ERROR tuple struct `A` is private
+    let other::A(_) = a; //~ ERROR tuple struct `A` is private
+    match a { other::A(()) => {} } //~ ERROR tuple struct `A` is private
+    match a { other::A(_) => {} } //~ ERROR tuple struct `A` is private
+
+    let other::B(_) = b; //~ ERROR tuple struct `B` is private
+    let other::B(_b) = b; //~ ERROR tuple struct `B` is private
+    match b { other::B(_) => {} } //~ ERROR tuple struct `B` is private
+    match b { other::B(_b) => {} } //~ ERROR tuple struct `B` is private
+    match b { other::B(1) => {} other::B(_) => {} } //~ ERROR tuple struct `B` is private
+                                                    //~^ ERROR tuple struct `B` is private
+
+    let other::C(_, _) = c; //~ ERROR tuple struct `C` is private
+    let other::C(_a, _) = c; //~ ERROR tuple struct `C` is private
+    let other::C(_, _b) = c; //~ ERROR tuple struct `C` is private
+    let other::C(_a, _b) = c; //~ ERROR tuple struct `C` is private
+    match c { other::C(_, _) => {} } //~ ERROR tuple struct `C` is private
+    match c { other::C(_a, _) => {} } //~ ERROR tuple struct `C` is private
+    match c { other::C(_, _b) => {} } //~ ERROR tuple struct `C` is private
+    match c { other::C(_a, _b) => {} } //~ ERROR tuple struct `C` is private
+
+    let other::D(_) = d;
+    let other::D(_d) = d;
+    match d { other::D(_) => {} }
+    match d { other::D(_d) => {} }
+    match d { other::D(1) => {} other::D(_) => {} }
+
+    let a2 = other::A; //~ ERROR tuple struct `A` is private
+    let b2 = other::B; //~ ERROR tuple struct `B` is private
+    let c2 = other::C; //~ ERROR tuple struct `C` is private
+    let d2 = other::D;
+}
+
+fn main() {}
diff --git a/src/test/ui/privacy/privacy5.stderr b/src/test/ui/privacy/privacy5.stderr
new file mode 100644
index 0000000..7568c34
--- /dev/null
+++ b/src/test/ui/privacy/privacy5.stderr
@@ -0,0 +1,291 @@
+error[E0603]: tuple struct `A` is private
+  --> $DIR/privacy5.rs:51:16
+   |
+LL |     let a = a::A(());
+   |                ^
+
+error[E0603]: tuple struct `B` is private
+  --> $DIR/privacy5.rs:52:16
+   |
+LL |     let b = a::B(2);
+   |                ^
+
+error[E0603]: tuple struct `C` is private
+  --> $DIR/privacy5.rs:53:16
+   |
+LL |     let c = a::C(2, 3);
+   |                ^
+
+error[E0603]: tuple struct `A` is private
+  --> $DIR/privacy5.rs:56:12
+   |
+LL |     let a::A(()) = a;
+   |            ^
+
+error[E0603]: tuple struct `A` is private
+  --> $DIR/privacy5.rs:57:12
+   |
+LL |     let a::A(_) = a;
+   |            ^
+
+error[E0603]: tuple struct `A` is private
+  --> $DIR/privacy5.rs:58:18
+   |
+LL |     match a { a::A(()) => {} }
+   |                  ^
+
+error[E0603]: tuple struct `A` is private
+  --> $DIR/privacy5.rs:59:18
+   |
+LL |     match a { a::A(_) => {} }
+   |                  ^
+
+error[E0603]: tuple struct `B` is private
+  --> $DIR/privacy5.rs:61:12
+   |
+LL |     let a::B(_) = b;
+   |            ^
+
+error[E0603]: tuple struct `B` is private
+  --> $DIR/privacy5.rs:62:12
+   |
+LL |     let a::B(_b) = b;
+   |            ^
+
+error[E0603]: tuple struct `B` is private
+  --> $DIR/privacy5.rs:63:18
+   |
+LL |     match b { a::B(_) => {} }
+   |                  ^
+
+error[E0603]: tuple struct `B` is private
+  --> $DIR/privacy5.rs:64:18
+   |
+LL |     match b { a::B(_b) => {} }
+   |                  ^
+
+error[E0603]: tuple struct `B` is private
+  --> $DIR/privacy5.rs:65:18
+   |
+LL |     match b { a::B(1) => {} a::B(_) => {} }
+   |                  ^
+
+error[E0603]: tuple struct `B` is private
+  --> $DIR/privacy5.rs:65:32
+   |
+LL |     match b { a::B(1) => {} a::B(_) => {} }
+   |                                ^
+
+error[E0603]: tuple struct `C` is private
+  --> $DIR/privacy5.rs:68:12
+   |
+LL |     let a::C(_, _) = c;
+   |            ^
+
+error[E0603]: tuple struct `C` is private
+  --> $DIR/privacy5.rs:69:12
+   |
+LL |     let a::C(_a, _) = c;
+   |            ^
+
+error[E0603]: tuple struct `C` is private
+  --> $DIR/privacy5.rs:70:12
+   |
+LL |     let a::C(_, _b) = c;
+   |            ^
+
+error[E0603]: tuple struct `C` is private
+  --> $DIR/privacy5.rs:71:12
+   |
+LL |     let a::C(_a, _b) = c;
+   |            ^
+
+error[E0603]: tuple struct `C` is private
+  --> $DIR/privacy5.rs:72:18
+   |
+LL |     match c { a::C(_, _) => {} }
+   |                  ^
+
+error[E0603]: tuple struct `C` is private
+  --> $DIR/privacy5.rs:73:18
+   |
+LL |     match c { a::C(_a, _) => {} }
+   |                  ^
+
+error[E0603]: tuple struct `C` is private
+  --> $DIR/privacy5.rs:74:18
+   |
+LL |     match c { a::C(_, _b) => {} }
+   |                  ^
+
+error[E0603]: tuple struct `C` is private
+  --> $DIR/privacy5.rs:75:18
+   |
+LL |     match c { a::C(_a, _b) => {} }
+   |                  ^
+
+error[E0603]: tuple struct `A` is private
+  --> $DIR/privacy5.rs:83:17
+   |
+LL |     let a2 = a::A;
+   |                 ^
+
+error[E0603]: tuple struct `B` is private
+  --> $DIR/privacy5.rs:84:17
+   |
+LL |     let b2 = a::B;
+   |                 ^
+
+error[E0603]: tuple struct `C` is private
+  --> $DIR/privacy5.rs:85:17
+   |
+LL |     let c2 = a::C;
+   |                 ^
+
+error[E0603]: tuple struct `A` is private
+  --> $DIR/privacy5.rs:90:20
+   |
+LL |     let a = other::A(());
+   |                    ^
+
+error[E0603]: tuple struct `B` is private
+  --> $DIR/privacy5.rs:91:20
+   |
+LL |     let b = other::B(2);
+   |                    ^
+
+error[E0603]: tuple struct `C` is private
+  --> $DIR/privacy5.rs:92:20
+   |
+LL |     let c = other::C(2, 3);
+   |                    ^
+
+error[E0603]: tuple struct `A` is private
+  --> $DIR/privacy5.rs:95:16
+   |
+LL |     let other::A(()) = a;
+   |                ^
+
+error[E0603]: tuple struct `A` is private
+  --> $DIR/privacy5.rs:96:16
+   |
+LL |     let other::A(_) = a;
+   |                ^
+
+error[E0603]: tuple struct `A` is private
+  --> $DIR/privacy5.rs:97:22
+   |
+LL |     match a { other::A(()) => {} }
+   |                      ^
+
+error[E0603]: tuple struct `A` is private
+  --> $DIR/privacy5.rs:98:22
+   |
+LL |     match a { other::A(_) => {} }
+   |                      ^
+
+error[E0603]: tuple struct `B` is private
+  --> $DIR/privacy5.rs:100:16
+   |
+LL |     let other::B(_) = b;
+   |                ^
+
+error[E0603]: tuple struct `B` is private
+  --> $DIR/privacy5.rs:101:16
+   |
+LL |     let other::B(_b) = b;
+   |                ^
+
+error[E0603]: tuple struct `B` is private
+  --> $DIR/privacy5.rs:102:22
+   |
+LL |     match b { other::B(_) => {} }
+   |                      ^
+
+error[E0603]: tuple struct `B` is private
+  --> $DIR/privacy5.rs:103:22
+   |
+LL |     match b { other::B(_b) => {} }
+   |                      ^
+
+error[E0603]: tuple struct `B` is private
+  --> $DIR/privacy5.rs:104:22
+   |
+LL |     match b { other::B(1) => {} other::B(_) => {} }
+   |                      ^
+
+error[E0603]: tuple struct `B` is private
+  --> $DIR/privacy5.rs:104:40
+   |
+LL |     match b { other::B(1) => {} other::B(_) => {} }
+   |                                        ^
+
+error[E0603]: tuple struct `C` is private
+  --> $DIR/privacy5.rs:107:16
+   |
+LL |     let other::C(_, _) = c;
+   |                ^
+
+error[E0603]: tuple struct `C` is private
+  --> $DIR/privacy5.rs:108:16
+   |
+LL |     let other::C(_a, _) = c;
+   |                ^
+
+error[E0603]: tuple struct `C` is private
+  --> $DIR/privacy5.rs:109:16
+   |
+LL |     let other::C(_, _b) = c;
+   |                ^
+
+error[E0603]: tuple struct `C` is private
+  --> $DIR/privacy5.rs:110:16
+   |
+LL |     let other::C(_a, _b) = c;
+   |                ^
+
+error[E0603]: tuple struct `C` is private
+  --> $DIR/privacy5.rs:111:22
+   |
+LL |     match c { other::C(_, _) => {} }
+   |                      ^
+
+error[E0603]: tuple struct `C` is private
+  --> $DIR/privacy5.rs:112:22
+   |
+LL |     match c { other::C(_a, _) => {} }
+   |                      ^
+
+error[E0603]: tuple struct `C` is private
+  --> $DIR/privacy5.rs:113:22
+   |
+LL |     match c { other::C(_, _b) => {} }
+   |                      ^
+
+error[E0603]: tuple struct `C` is private
+  --> $DIR/privacy5.rs:114:22
+   |
+LL |     match c { other::C(_a, _b) => {} }
+   |                      ^
+
+error[E0603]: tuple struct `A` is private
+  --> $DIR/privacy5.rs:122:21
+   |
+LL |     let a2 = other::A;
+   |                     ^
+
+error[E0603]: tuple struct `B` is private
+  --> $DIR/privacy5.rs:123:21
+   |
+LL |     let b2 = other::B;
+   |                     ^
+
+error[E0603]: tuple struct `C` is private
+  --> $DIR/privacy5.rs:124:21
+   |
+LL |     let c2 = other::C;
+   |                     ^
+
+error: aborting due to 48 previous errors
+
+For more information about this error, try `rustc --explain E0603`.
diff --git a/src/test/ui/privacy/private-impl-method.rs b/src/test/ui/privacy/private-impl-method.rs
new file mode 100644
index 0000000..b558792
--- /dev/null
+++ b/src/test/ui/privacy/private-impl-method.rs
@@ -0,0 +1,21 @@
+mod a {
+    pub struct Foo {
+        pub x: isize
+    }
+
+    impl Foo {
+        fn foo(&self) {}
+    }
+}
+
+fn f() {
+    impl a::Foo {
+        fn bar(&self) {} // This should be visible outside `f`
+    }
+}
+
+fn main() {
+    let s = a::Foo { x: 1 };
+    s.bar();
+    s.foo();    //~ ERROR method `foo` is private
+}
diff --git a/src/test/ui/privacy/private-impl-method.stderr b/src/test/ui/privacy/private-impl-method.stderr
new file mode 100644
index 0000000..e1da3f4
--- /dev/null
+++ b/src/test/ui/privacy/private-impl-method.stderr
@@ -0,0 +1,9 @@
+error[E0624]: method `foo` is private
+  --> $DIR/private-impl-method.rs:20:7
+   |
+LL |     s.foo();
+   |       ^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0624`.
diff --git a/src/test/ui/privacy/private-in-public-assoc-ty.rs b/src/test/ui/privacy/private-in-public-assoc-ty.rs
new file mode 100644
index 0000000..81d2395
--- /dev/null
+++ b/src/test/ui/privacy/private-in-public-assoc-ty.rs
@@ -0,0 +1,40 @@
+// Private types and traits are not allowed in interfaces of associated types.
+// This test also ensures that the checks are performed even inside private modules.
+
+#![feature(associated_type_defaults, existential_type)]
+
+mod m {
+    struct Priv;
+    trait PrivTr {}
+    impl PrivTr for Priv {}
+    pub trait PubTrAux1<T> {}
+    pub trait PubTrAux2 { type A; }
+
+    // "Private-in-public in associated types is hard error" in RFC 2145
+    // applies only to the aliased types, not bounds.
+    pub trait PubTr {
+        //~^ WARN private trait `m::PrivTr` in public interface
+        //~| WARN this was previously accepted
+        //~| WARN private type `m::Priv` in public interface
+        //~| WARN this was previously accepted
+        type Alias1: PrivTr;
+        type Alias2: PubTrAux1<Priv> = u8;
+        type Alias3: PubTrAux2<A = Priv> = u8;
+
+        type Alias4 = Priv;
+        //~^ ERROR private type `m::Priv` in public interface
+
+        type Exist;
+        fn infer_exist() -> Self::Exist;
+    }
+    impl PubTr for u8 {
+        type Alias1 = Priv;
+        //~^ ERROR private type `m::Priv` in public interface
+
+        existential type Exist: PrivTr;
+        //~^ ERROR private trait `m::PrivTr` in public interface
+        fn infer_exist() -> Self::Exist { Priv }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/privacy/private-in-public-assoc-ty.stderr b/src/test/ui/privacy/private-in-public-assoc-ty.stderr
new file mode 100644
index 0000000..a610b47
--- /dev/null
+++ b/src/test/ui/privacy/private-in-public-assoc-ty.stderr
@@ -0,0 +1,62 @@
+warning: private trait `m::PrivTr` in public interface (error E0445)
+  --> $DIR/private-in-public-assoc-ty.rs:15:5
+   |
+LL | /     pub trait PubTr {
+LL | |
+LL | |
+LL | |
+...  |
+LL | |         fn infer_exist() -> Self::Exist;
+LL | |     }
+   | |_____^
+   |
+   = note: #[warn(private_in_public)] on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
+
+warning: private type `m::Priv` in public interface (error E0446)
+  --> $DIR/private-in-public-assoc-ty.rs:15:5
+   |
+LL | /     pub trait PubTr {
+LL | |
+LL | |
+LL | |
+...  |
+LL | |         fn infer_exist() -> Self::Exist;
+LL | |     }
+   | |_____^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
+
+error[E0446]: private type `m::Priv` in public interface
+  --> $DIR/private-in-public-assoc-ty.rs:24:9
+   |
+LL |     struct Priv;
+   |     - `m::Priv` declared as private
+...
+LL |         type Alias4 = Priv;
+   |         ^^^^^^^^^^^^^^^^^^^ can't leak private type
+
+error[E0446]: private type `m::Priv` in public interface
+  --> $DIR/private-in-public-assoc-ty.rs:31:9
+   |
+LL |     struct Priv;
+   |     - `m::Priv` declared as private
+...
+LL |         type Alias1 = Priv;
+   |         ^^^^^^^^^^^^^^^^^^^ can't leak private type
+
+error[E0445]: private trait `m::PrivTr` in public interface
+  --> $DIR/private-in-public-assoc-ty.rs:34:9
+   |
+LL |     trait PrivTr {}
+   |     - `m::PrivTr` declared as private
+...
+LL |         existential type Exist: PrivTr;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0445, E0446.
+For more information about an error, try `rustc --explain E0445`.
diff --git a/src/test/ui/privacy/private-in-public-existential.rs b/src/test/ui/privacy/private-in-public-existential.rs
new file mode 100644
index 0000000..61c6130
--- /dev/null
+++ b/src/test/ui/privacy/private-in-public-existential.rs
@@ -0,0 +1,25 @@
+// compile-pass
+
+#![feature(existential_type)]
+#![deny(private_in_public)]
+
+pub existential type Pub: Default;
+
+#[derive(Default)]
+struct Priv;
+
+fn check() -> Pub {
+    Priv
+}
+
+pub trait Trait {
+    type Pub: Default;
+    fn method() -> Self::Pub;
+}
+
+impl Trait for u8 {
+    existential type Pub: Default;
+    fn method() -> Self::Pub { Priv }
+}
+
+fn main() {}
diff --git a/src/test/ui/privacy/private-in-public-expr-pat.rs b/src/test/ui/privacy/private-in-public-expr-pat.rs
new file mode 100644
index 0000000..a3e53bd
--- /dev/null
+++ b/src/test/ui/privacy/private-in-public-expr-pat.rs
@@ -0,0 +1,13 @@
+// Patterns and expressions are not interface parts and don't produce private-in-public errors.
+
+// compile-pass
+
+struct Priv1(usize);
+struct Priv2;
+
+pub struct Pub(Priv2);
+
+pub fn public_expr(_: [u8; Priv1(0).0]) {} // OK
+pub fn public_pat(Pub(Priv2): Pub) {} // OK
+
+fn main() {}
diff --git a/src/test/ui/privacy/private-in-public-ill-formed.rs b/src/test/ui/privacy/private-in-public-ill-formed.rs
new file mode 100644
index 0000000..0ef5d89
--- /dev/null
+++ b/src/test/ui/privacy/private-in-public-ill-formed.rs
@@ -0,0 +1,35 @@
+mod aliases_pub {
+    struct Priv;
+    mod m {
+        pub struct Pub3;
+    }
+
+    trait PrivTr {
+        type AssocAlias;
+    }
+    impl PrivTr for Priv {
+        type AssocAlias = m::Pub3;
+    }
+
+    impl <Priv as PrivTr>::AssocAlias { //~ ERROR no base type found for inherent implementation
+        pub fn f(arg: Priv) {} // private type `aliases_pub::Priv` in public interface
+    }
+}
+
+mod aliases_priv {
+    struct Priv;
+    struct Priv3;
+
+    trait PrivTr {
+        type AssocAlias;
+    }
+    impl PrivTr for Priv {
+        type AssocAlias = Priv3;
+    }
+
+    impl <Priv as PrivTr>::AssocAlias { //~ ERROR no base type found for inherent implementation
+        pub fn f(arg: Priv) {} // OK
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/privacy/private-in-public-ill-formed.stderr b/src/test/ui/privacy/private-in-public-ill-formed.stderr
new file mode 100644
index 0000000..a1a326f
--- /dev/null
+++ b/src/test/ui/privacy/private-in-public-ill-formed.stderr
@@ -0,0 +1,19 @@
+error[E0118]: no base type found for inherent implementation
+  --> $DIR/private-in-public-ill-formed.rs:14:10
+   |
+LL |     impl <Priv as PrivTr>::AssocAlias {
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl requires a base type
+   |
+   = note: either implement a trait on it or create a newtype to wrap it instead
+
+error[E0118]: no base type found for inherent implementation
+  --> $DIR/private-in-public-ill-formed.rs:30:10
+   |
+LL |     impl <Priv as PrivTr>::AssocAlias {
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl requires a base type
+   |
+   = note: either implement a trait on it or create a newtype to wrap it instead
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0118`.
diff --git a/src/test/ui/privacy/private-in-public-lint.rs b/src/test/ui/privacy/private-in-public-lint.rs
new file mode 100644
index 0000000..8b6e436
--- /dev/null
+++ b/src/test/ui/privacy/private-in-public-lint.rs
@@ -0,0 +1,19 @@
+mod m1 {
+    pub struct Pub;
+    struct Priv;
+
+    impl Pub {
+        pub fn f() -> Priv {Priv} //~ ERROR private type `m1::Priv` in public interface
+    }
+}
+
+mod m2 {
+    pub struct Pub;
+    struct Priv;
+
+    impl Pub {
+        pub fn f() -> Priv {Priv} //~ ERROR private type `m2::Priv` in public interface
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/privacy/private-in-public-lint.stderr b/src/test/ui/privacy/private-in-public-lint.stderr
new file mode 100644
index 0000000..441a4d5
--- /dev/null
+++ b/src/test/ui/privacy/private-in-public-lint.stderr
@@ -0,0 +1,21 @@
+error[E0446]: private type `m1::Priv` in public interface
+  --> $DIR/private-in-public-lint.rs:6:9
+   |
+LL |     struct Priv;
+   |     - `m1::Priv` declared as private
+...
+LL |         pub fn f() -> Priv {Priv}
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
+
+error[E0446]: private type `m2::Priv` in public interface
+  --> $DIR/private-in-public-lint.rs:15:9
+   |
+LL |     struct Priv;
+   |     - `m2::Priv` declared as private
+...
+LL |         pub fn f() -> Priv {Priv}
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0446`.
diff --git a/src/test/ui/privacy/private-in-public-non-principal-2.rs b/src/test/ui/privacy/private-in-public-non-principal-2.rs
new file mode 100644
index 0000000..02fd92a
--- /dev/null
+++ b/src/test/ui/privacy/private-in-public-non-principal-2.rs
@@ -0,0 +1,13 @@
+#![feature(optin_builtin_traits)]
+
+#[allow(private_in_public)]
+mod m {
+    pub trait PubPrincipal {}
+    auto trait PrivNonPrincipal {}
+    pub fn leak_dyn_nonprincipal() -> Box<PubPrincipal + PrivNonPrincipal> { loop {} }
+}
+
+fn main() {
+    m::leak_dyn_nonprincipal();
+    //~^ ERROR trait `m::PrivNonPrincipal` is private
+}
diff --git a/src/test/ui/privacy/private-in-public-non-principal-2.stderr b/src/test/ui/privacy/private-in-public-non-principal-2.stderr
new file mode 100644
index 0000000..2db4925
--- /dev/null
+++ b/src/test/ui/privacy/private-in-public-non-principal-2.stderr
@@ -0,0 +1,8 @@
+error: trait `m::PrivNonPrincipal` is private
+  --> $DIR/private-in-public-non-principal-2.rs:11:5
+   |
+LL |     m::leak_dyn_nonprincipal();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/privacy/private-in-public-non-principal.rs b/src/test/ui/privacy/private-in-public-non-principal.rs
new file mode 100644
index 0000000..5de5a68
--- /dev/null
+++ b/src/test/ui/privacy/private-in-public-non-principal.rs
@@ -0,0 +1,20 @@
+#![feature(optin_builtin_traits)]
+
+pub trait PubPrincipal {}
+auto trait PrivNonPrincipal {}
+
+pub fn leak_dyn_nonprincipal() -> Box<PubPrincipal + PrivNonPrincipal> { loop {} }
+//~^ WARN private trait `PrivNonPrincipal` in public interface
+//~| WARN this was previously accepted
+
+#[deny(missing_docs)]
+fn container() {
+    impl dyn PubPrincipal {
+        pub fn check_doc_lint() {} //~ ERROR missing documentation for a method
+    }
+    impl dyn PubPrincipal + PrivNonPrincipal {
+        pub fn check_doc_lint() {} // OK, no missing doc lint
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/privacy/private-in-public-non-principal.stderr b/src/test/ui/privacy/private-in-public-non-principal.stderr
new file mode 100644
index 0000000..729b94e
--- /dev/null
+++ b/src/test/ui/privacy/private-in-public-non-principal.stderr
@@ -0,0 +1,24 @@
+warning: private trait `PrivNonPrincipal` in public interface (error E0445)
+  --> $DIR/private-in-public-non-principal.rs:6:1
+   |
+LL | pub fn leak_dyn_nonprincipal() -> Box<PubPrincipal + PrivNonPrincipal> { loop {} }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: #[warn(private_in_public)] on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
+
+error: missing documentation for a method
+  --> $DIR/private-in-public-non-principal.rs:13:9
+   |
+LL |         pub fn check_doc_lint() {}
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/private-in-public-non-principal.rs:10:8
+   |
+LL | #[deny(missing_docs)]
+   |        ^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/privacy/private-in-public-warn.rs b/src/test/ui/privacy/private-in-public-warn.rs
new file mode 100644
index 0000000..467b837
--- /dev/null
+++ b/src/test/ui/privacy/private-in-public-warn.rs
@@ -0,0 +1,283 @@
+// Private types and traits are not allowed in public interfaces.
+// This test also ensures that the checks are performed even inside private modules.
+
+#![feature(associated_type_defaults)]
+#![deny(private_in_public)]
+#![allow(improper_ctypes)]
+
+mod types {
+    struct Priv;
+    pub struct Pub;
+    pub trait PubTr {
+        type Alias;
+    }
+
+    pub type Alias = Priv; //~ ERROR private type `types::Priv` in public interface
+    //~^ WARNING hard error
+    pub enum E {
+        V1(Priv), //~ ERROR private type `types::Priv` in public interface
+        //~^ WARNING hard error
+        V2 { field: Priv }, //~ ERROR private type `types::Priv` in public interface
+        //~^ WARNING hard error
+    }
+    pub trait Tr {
+        const C: Priv = Priv; //~ ERROR private type `types::Priv` in public interface
+        //~^ WARNING hard error
+        type Alias = Priv; //~ ERROR private type `types::Priv` in public interface
+        fn f1(arg: Priv) {} //~ ERROR private type `types::Priv` in public interface
+        //~^ WARNING hard error
+        fn f2() -> Priv { panic!() } //~ ERROR private type `types::Priv` in public interface
+        //~^ WARNING hard error
+    }
+    extern {
+        pub static ES: Priv; //~ ERROR private type `types::Priv` in public interface
+        //~^ WARNING hard error
+        pub fn ef1(arg: Priv); //~ ERROR private type `types::Priv` in public interface
+        //~^ WARNING hard error
+        pub fn ef2() -> Priv; //~ ERROR private type `types::Priv` in public interface
+        //~^ WARNING hard error
+    }
+    impl PubTr for Pub {
+        type Alias = Priv; //~ ERROR private type `types::Priv` in public interface
+    }
+}
+
+mod traits {
+    trait PrivTr {}
+    pub struct Pub<T>(T);
+    pub trait PubTr {}
+
+    pub type Alias<T: PrivTr> = T; //~ ERROR private trait `traits::PrivTr` in public interface
+    //~| WARNING hard error
+    //~| WARNING bounds on generic parameters are not enforced in type aliases
+    pub trait Tr1: PrivTr {} //~ ERROR private trait `traits::PrivTr` in public interface
+    //~^ WARNING hard error
+    pub trait Tr2<T: PrivTr> {} //~ ERROR private trait `traits::PrivTr` in public interface
+        //~^ WARNING hard error
+    pub trait Tr3 {
+        //~^ ERROR private trait `traits::PrivTr` in public interface
+        //~| WARNING hard error
+        type Alias: PrivTr;
+        fn f<T: PrivTr>(arg: T) {} //~ ERROR private trait `traits::PrivTr` in public interface
+        //~^ WARNING hard error
+    }
+    impl<T: PrivTr> Pub<T> {} //~ ERROR private trait `traits::PrivTr` in public interface
+        //~^ WARNING hard error
+    impl<T: PrivTr> PubTr for Pub<T> {} //~ ERROR private trait `traits::PrivTr` in public interface
+        //~^ WARNING hard error
+}
+
+mod traits_where {
+    trait PrivTr {}
+    pub struct Pub<T>(T);
+    pub trait PubTr {}
+
+    pub type Alias<T> where T: PrivTr = T;
+        //~^ ERROR private trait `traits_where::PrivTr` in public interface
+        //~| WARNING hard error
+        //~| WARNING where clauses are not enforced in type aliases
+    pub trait Tr2<T> where T: PrivTr {}
+        //~^ ERROR private trait `traits_where::PrivTr` in public interface
+        //~| WARNING hard error
+    pub trait Tr3 {
+        fn f<T>(arg: T) where T: PrivTr {}
+        //~^ ERROR private trait `traits_where::PrivTr` in public interface
+        //~| WARNING hard error
+    }
+    impl<T> Pub<T> where T: PrivTr {}
+        //~^ ERROR private trait `traits_where::PrivTr` in public interface
+        //~| WARNING hard error
+    impl<T> PubTr for Pub<T> where T: PrivTr {}
+        //~^ ERROR private trait `traits_where::PrivTr` in public interface
+        //~| WARNING hard error
+}
+
+mod generics {
+    struct Priv<T = u8>(T);
+    pub struct Pub<T = u8>(T);
+    trait PrivTr<T> {}
+    pub trait PubTr<T> {}
+
+    pub trait Tr1: PrivTr<Pub> {}
+        //~^ ERROR private trait `generics::PrivTr<generics::Pub>` in public interface
+        //~| WARNING hard error
+    pub trait Tr2: PubTr<Priv> {} //~ ERROR private type `generics::Priv` in public interface
+        //~^ WARNING hard error
+    pub trait Tr3: PubTr<[Priv; 1]> {} //~ ERROR private type `generics::Priv` in public interface
+        //~^ WARNING hard error
+    pub trait Tr4: PubTr<Pub<Priv>> {} //~ ERROR private type `generics::Priv` in public interface
+        //~^ WARNING hard error
+}
+
+mod impls {
+    struct Priv;
+    pub struct Pub;
+    trait PrivTr {
+        type Alias;
+    }
+    pub trait PubTr {
+        type Alias;
+    }
+
+    impl Priv {
+        pub fn f(arg: Priv) {} // OK
+    }
+    impl PrivTr for Priv {
+        type Alias = Priv; // OK
+    }
+    impl PubTr for Priv {
+        type Alias = Priv; // OK
+    }
+    impl PrivTr for Pub {
+        type Alias = Priv; // OK
+    }
+    impl PubTr for Pub {
+        type Alias = Priv; //~ ERROR private type `impls::Priv` in public interface
+    }
+}
+
+mod impls_generics {
+    struct Priv<T = u8>(T);
+    pub struct Pub<T = u8>(T);
+    trait PrivTr<T = u8> {
+        type Alias;
+    }
+    pub trait PubTr<T = u8> {
+        type Alias;
+    }
+
+    impl Priv<Pub> {
+        pub fn f(arg: Priv) {} // OK
+    }
+    impl Pub<Priv> {
+        pub fn f(arg: Priv) {} // OK
+    }
+    impl PrivTr<Pub> for Priv {
+        type Alias = Priv; // OK
+    }
+    impl PubTr<Priv> for Priv {
+        type Alias = Priv; // OK
+    }
+    impl PubTr for Priv<Pub> {
+        type Alias = Priv; // OK
+    }
+    impl PubTr for [Priv; 1] {
+        type Alias = Priv; // OK
+    }
+    impl PubTr for Pub<Priv> {
+        type Alias = Priv; // OK
+    }
+    impl PrivTr<Pub> for Pub {
+        type Alias = Priv; // OK
+    }
+    impl PubTr<Priv> for Pub {
+        type Alias = Priv; // OK
+    }
+}
+
+mod aliases_pub {
+    struct Priv;
+    mod m {
+        pub struct Pub1;
+        pub struct Pub2;
+        pub struct Pub3;
+        pub trait PubTr<T = u8> {
+            type Check = u8;
+        }
+    }
+
+    use self::m::Pub1 as PrivUseAlias;
+    use self::m::PubTr as PrivUseAliasTr;
+    type PrivAlias = m::Pub2;
+    trait PrivTr {
+        type AssocAlias;
+    }
+    impl PrivTr for Priv {
+        type AssocAlias = m::Pub3;
+    }
+
+    pub fn f1(arg: PrivUseAlias) {} // OK
+    pub fn f2(arg: PrivAlias) {} // OK
+
+    pub trait Tr1: PrivUseAliasTr {} // OK
+    pub trait Tr2: PrivUseAliasTr<PrivAlias> {} // OK
+
+    impl PrivAlias {
+        pub fn f(arg: Priv) {} //~ ERROR private type `aliases_pub::Priv` in public interface
+        //~^ WARNING hard error
+    }
+    impl PrivUseAliasTr for PrivUseAlias {
+        type Check = Priv; //~ ERROR private type `aliases_pub::Priv` in public interface
+    }
+    impl PrivUseAliasTr for PrivAlias {
+        type Check = Priv; //~ ERROR private type `aliases_pub::Priv` in public interface
+    }
+    impl PrivUseAliasTr for <Priv as PrivTr>::AssocAlias {
+        type Check = Priv; //~ ERROR private type `aliases_pub::Priv` in public interface
+    }
+    impl PrivUseAliasTr for Option<<Priv as PrivTr>::AssocAlias> {
+        type Check = Priv; //~ ERROR private type `aliases_pub::Priv` in public interface
+    }
+    impl PrivUseAliasTr for (<Priv as PrivTr>::AssocAlias, Priv) {
+        type Check = Priv; // OK
+    }
+    impl PrivUseAliasTr for Option<(<Priv as PrivTr>::AssocAlias, Priv)> {
+        type Check = Priv; // OK
+    }
+}
+
+mod aliases_priv {
+    struct Priv;
+
+    struct Priv1;
+    struct Priv2;
+    struct Priv3;
+    trait PrivTr1<T = u8> {
+        type Check = u8;
+    }
+
+    use self::Priv1 as PrivUseAlias;
+    use self::PrivTr1 as PrivUseAliasTr;
+    type PrivAlias = Priv2;
+    trait PrivTr {
+        type AssocAlias;
+    }
+    impl PrivTr for Priv {
+        type AssocAlias = Priv3;
+    }
+
+    pub trait Tr1: PrivUseAliasTr {}
+        //~^ ERROR private trait `aliases_priv::PrivTr1` in public interface
+        //~| WARNING hard error
+    pub trait Tr2: PrivUseAliasTr<PrivAlias> {}
+        //~^ ERROR private trait `aliases_priv::PrivTr1<aliases_priv::Priv2>` in public interface
+        //~| WARNING hard error
+        //~| ERROR private type `aliases_priv::Priv2` in public interface
+        //~| WARNING hard error
+
+    impl PrivUseAlias {
+        pub fn f(arg: Priv) {} // OK
+    }
+    impl PrivAlias {
+        pub fn f(arg: Priv) {} // OK
+    }
+    impl PrivUseAliasTr for PrivUseAlias {
+        type Check = Priv; // OK
+    }
+    impl PrivUseAliasTr for PrivAlias {
+        type Check = Priv; // OK
+    }
+    impl PrivUseAliasTr for <Priv as PrivTr>::AssocAlias {
+        type Check = Priv; // OK
+    }
+}
+
+mod aliases_params {
+    struct Priv;
+    type PrivAliasGeneric<T = Priv> = T;
+    type Result<T> = ::std::result::Result<T, Priv>;
+
+    pub fn f1(arg: PrivAliasGeneric<u8>) {} // OK, not an error
+}
+
+fn main() {}
diff --git a/src/test/ui/privacy/private-in-public-warn.stderr b/src/test/ui/privacy/private-in-public-warn.stderr
new file mode 100644
index 0000000..16b7e51
--- /dev/null
+++ b/src/test/ui/privacy/private-in-public-warn.stderr
@@ -0,0 +1,355 @@
+error: private type `types::Priv` in public interface (error E0446)
+  --> $DIR/private-in-public-warn.rs:15:5
+   |
+LL |     pub type Alias = Priv;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/private-in-public-warn.rs:5:9
+   |
+LL | #![deny(private_in_public)]
+   |         ^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
+
+error: private type `types::Priv` in public interface (error E0446)
+  --> $DIR/private-in-public-warn.rs:18:12
+   |
+LL |         V1(Priv),
+   |            ^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
+
+error: private type `types::Priv` in public interface (error E0446)
+  --> $DIR/private-in-public-warn.rs:20:14
+   |
+LL |         V2 { field: Priv },
+   |              ^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
+
+error: private type `types::Priv` in public interface (error E0446)
+  --> $DIR/private-in-public-warn.rs:24:9
+   |
+LL |         const C: Priv = Priv;
+   |         ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
+
+error[E0446]: private type `types::Priv` in public interface
+  --> $DIR/private-in-public-warn.rs:26:9
+   |
+LL |     struct Priv;
+   |     - `types::Priv` declared as private
+...
+LL |         type Alias = Priv;
+   |         ^^^^^^^^^^^^^^^^^^ can't leak private type
+
+error: private type `types::Priv` in public interface (error E0446)
+  --> $DIR/private-in-public-warn.rs:27:9
+   |
+LL |         fn f1(arg: Priv) {}
+   |         ^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
+
+error: private type `types::Priv` in public interface (error E0446)
+  --> $DIR/private-in-public-warn.rs:29:9
+   |
+LL |         fn f2() -> Priv { panic!() }
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
+
+error: private type `types::Priv` in public interface (error E0446)
+  --> $DIR/private-in-public-warn.rs:33:9
+   |
+LL |         pub static ES: Priv;
+   |         ^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
+
+error: private type `types::Priv` in public interface (error E0446)
+  --> $DIR/private-in-public-warn.rs:35:9
+   |
+LL |         pub fn ef1(arg: Priv);
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
+
+error: private type `types::Priv` in public interface (error E0446)
+  --> $DIR/private-in-public-warn.rs:37:9
+   |
+LL |         pub fn ef2() -> Priv;
+   |         ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
+
+error[E0446]: private type `types::Priv` in public interface
+  --> $DIR/private-in-public-warn.rs:41:9
+   |
+LL |     struct Priv;
+   |     - `types::Priv` declared as private
+...
+LL |         type Alias = Priv;
+   |         ^^^^^^^^^^^^^^^^^^ can't leak private type
+
+error: private trait `traits::PrivTr` in public interface (error E0445)
+  --> $DIR/private-in-public-warn.rs:50:5
+   |
+LL |     pub type Alias<T: PrivTr> = T;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
+
+error: private trait `traits::PrivTr` in public interface (error E0445)
+  --> $DIR/private-in-public-warn.rs:53:5
+   |
+LL |     pub trait Tr1: PrivTr {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
+
+error: private trait `traits::PrivTr` in public interface (error E0445)
+  --> $DIR/private-in-public-warn.rs:55:5
+   |
+LL |     pub trait Tr2<T: PrivTr> {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
+
+error: private trait `traits::PrivTr` in public interface (error E0445)
+  --> $DIR/private-in-public-warn.rs:57:5
+   |
+LL | /     pub trait Tr3 {
+LL | |
+LL | |
+LL | |         type Alias: PrivTr;
+LL | |         fn f<T: PrivTr>(arg: T) {}
+LL | |
+LL | |     }
+   | |_____^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
+
+error: private trait `traits::PrivTr` in public interface (error E0445)
+  --> $DIR/private-in-public-warn.rs:61:9
+   |
+LL |         fn f<T: PrivTr>(arg: T) {}
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
+
+error: private trait `traits::PrivTr` in public interface (error E0445)
+  --> $DIR/private-in-public-warn.rs:64:5
+   |
+LL |     impl<T: PrivTr> Pub<T> {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
+
+error: private trait `traits::PrivTr` in public interface (error E0445)
+  --> $DIR/private-in-public-warn.rs:66:5
+   |
+LL |     impl<T: PrivTr> PubTr for Pub<T> {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
+
+error: private trait `traits_where::PrivTr` in public interface (error E0445)
+  --> $DIR/private-in-public-warn.rs:75:5
+   |
+LL |     pub type Alias<T> where T: PrivTr = T;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
+
+error: private trait `traits_where::PrivTr` in public interface (error E0445)
+  --> $DIR/private-in-public-warn.rs:79:5
+   |
+LL |     pub trait Tr2<T> where T: PrivTr {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
+
+error: private trait `traits_where::PrivTr` in public interface (error E0445)
+  --> $DIR/private-in-public-warn.rs:83:9
+   |
+LL |         fn f<T>(arg: T) where T: PrivTr {}
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
+
+error: private trait `traits_where::PrivTr` in public interface (error E0445)
+  --> $DIR/private-in-public-warn.rs:87:5
+   |
+LL |     impl<T> Pub<T> where T: PrivTr {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
+
+error: private trait `traits_where::PrivTr` in public interface (error E0445)
+  --> $DIR/private-in-public-warn.rs:90:5
+   |
+LL |     impl<T> PubTr for Pub<T> where T: PrivTr {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
+
+error: private trait `generics::PrivTr<generics::Pub>` in public interface (error E0445)
+  --> $DIR/private-in-public-warn.rs:101:5
+   |
+LL |     pub trait Tr1: PrivTr<Pub> {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
+
+error: private type `generics::Priv` in public interface (error E0446)
+  --> $DIR/private-in-public-warn.rs:104:5
+   |
+LL |     pub trait Tr2: PubTr<Priv> {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
+
+error: private type `generics::Priv` in public interface (error E0446)
+  --> $DIR/private-in-public-warn.rs:106:5
+   |
+LL |     pub trait Tr3: PubTr<[Priv; 1]> {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
+
+error: private type `generics::Priv` in public interface (error E0446)
+  --> $DIR/private-in-public-warn.rs:108:5
+   |
+LL |     pub trait Tr4: PubTr<Pub<Priv>> {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
+
+error[E0446]: private type `impls::Priv` in public interface
+  --> $DIR/private-in-public-warn.rs:135:9
+   |
+LL |     struct Priv;
+   |     - `impls::Priv` declared as private
+...
+LL |         type Alias = Priv;
+   |         ^^^^^^^^^^^^^^^^^^ can't leak private type
+
+error: private type `aliases_pub::Priv` in public interface (error E0446)
+  --> $DIR/private-in-public-warn.rs:206:9
+   |
+LL |         pub fn f(arg: Priv) {}
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
+
+error[E0446]: private type `aliases_pub::Priv` in public interface
+  --> $DIR/private-in-public-warn.rs:210:9
+   |
+LL |     struct Priv;
+   |     - `aliases_pub::Priv` declared as private
+...
+LL |         type Check = Priv;
+   |         ^^^^^^^^^^^^^^^^^^ can't leak private type
+
+error[E0446]: private type `aliases_pub::Priv` in public interface
+  --> $DIR/private-in-public-warn.rs:213:9
+   |
+LL |     struct Priv;
+   |     - `aliases_pub::Priv` declared as private
+...
+LL |         type Check = Priv;
+   |         ^^^^^^^^^^^^^^^^^^ can't leak private type
+
+error[E0446]: private type `aliases_pub::Priv` in public interface
+  --> $DIR/private-in-public-warn.rs:216:9
+   |
+LL |     struct Priv;
+   |     - `aliases_pub::Priv` declared as private
+...
+LL |         type Check = Priv;
+   |         ^^^^^^^^^^^^^^^^^^ can't leak private type
+
+error[E0446]: private type `aliases_pub::Priv` in public interface
+  --> $DIR/private-in-public-warn.rs:219:9
+   |
+LL |     struct Priv;
+   |     - `aliases_pub::Priv` declared as private
+...
+LL |         type Check = Priv;
+   |         ^^^^^^^^^^^^^^^^^^ can't leak private type
+
+error: private trait `aliases_priv::PrivTr1` in public interface (error E0445)
+  --> $DIR/private-in-public-warn.rs:249:5
+   |
+LL |     pub trait Tr1: PrivUseAliasTr {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
+
+error: private trait `aliases_priv::PrivTr1<aliases_priv::Priv2>` in public interface (error E0445)
+  --> $DIR/private-in-public-warn.rs:252:5
+   |
+LL |     pub trait Tr2: PrivUseAliasTr<PrivAlias> {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
+
+error: private type `aliases_priv::Priv2` in public interface (error E0446)
+  --> $DIR/private-in-public-warn.rs:252:5
+   |
+LL |     pub trait Tr2: PrivUseAliasTr<PrivAlias> {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
+
+warning: bounds on generic parameters are not enforced in type aliases
+  --> $DIR/private-in-public-warn.rs:50:23
+   |
+LL |     pub type Alias<T: PrivTr> = T;
+   |                       ^^^^^^
+   |
+   = note: #[warn(type_alias_bounds)] on by default
+   = help: the bound will not be checked when the type alias is used, and should be removed
+
+warning: where clauses are not enforced in type aliases
+  --> $DIR/private-in-public-warn.rs:75:29
+   |
+LL |     pub type Alias<T> where T: PrivTr = T;
+   |                             ^^^^^^^^^
+   |
+   = help: the clause will not be checked when the type alias is used, and should be removed
+
+error: aborting due to 36 previous errors
+
+For more information about this error, try `rustc --explain E0446`.
diff --git a/src/test/ui/privacy/private-in-public.rs b/src/test/ui/privacy/private-in-public.rs
new file mode 100644
index 0000000..08c00f4
--- /dev/null
+++ b/src/test/ui/privacy/private-in-public.rs
@@ -0,0 +1,148 @@
+// Private types and traits are not allowed in public interfaces.
+// This test also ensures that the checks are performed even inside private modules.
+
+#![feature(associated_type_defaults)]
+
+mod types {
+    struct Priv;
+    pub struct Pub;
+    pub trait PubTr {
+        type Alias;
+    }
+
+    pub const C: Priv = Priv; //~ ERROR private type `types::Priv` in public interface
+    pub static S: Priv = Priv; //~ ERROR private type `types::Priv` in public interface
+    pub fn f1(arg: Priv) {} //~ ERROR private type `types::Priv` in public interface
+    pub fn f2() -> Priv { panic!() } //~ ERROR private type `types::Priv` in public interface
+    pub struct S1(pub Priv); //~ ERROR private type `types::Priv` in public interface
+    pub struct S2 { pub field: Priv } //~ ERROR private type `types::Priv` in public interface
+    impl Pub {
+        pub const C: Priv = Priv; //~ ERROR private type `types::Priv` in public interface
+        pub fn f1(arg: Priv) {} //~ ERROR private type `types::Priv` in public interface
+        pub fn f2() -> Priv { panic!() } //~ ERROR private type `types::Priv` in public interface
+    }
+}
+
+mod traits {
+    trait PrivTr {}
+    pub struct Pub<T>(T);
+    pub trait PubTr {}
+
+    pub enum E<T: PrivTr> { V(T) } //~ ERROR private trait `traits::PrivTr` in public interface
+    pub fn f<T: PrivTr>(arg: T) {} //~ ERROR private trait `traits::PrivTr` in public interface
+    pub struct S1<T: PrivTr>(T); //~ ERROR private trait `traits::PrivTr` in public interface
+    impl<T: PrivTr> Pub<T> { //~ ERROR private trait `traits::PrivTr` in public interface
+        pub fn f<U: PrivTr>(arg: U) {} //~ ERROR private trait `traits::PrivTr` in public interface
+    }
+}
+
+mod traits_where {
+    trait PrivTr {}
+    pub struct Pub<T>(T);
+    pub trait PubTr {}
+
+    pub enum E<T> where T: PrivTr { V(T) }
+    //~^ ERROR private trait `traits_where::PrivTr` in public interface
+    pub fn f<T>(arg: T) where T: PrivTr {}
+    //~^ ERROR private trait `traits_where::PrivTr` in public interface
+    pub struct S1<T>(T) where T: PrivTr;
+    //~^ ERROR private trait `traits_where::PrivTr` in public interface
+    impl<T> Pub<T> where T: PrivTr {
+    //~^ ERROR private trait `traits_where::PrivTr` in public interface
+        pub fn f<U>(arg: U) where U: PrivTr {}
+        //~^ ERROR private trait `traits_where::PrivTr` in public interface
+    }
+}
+
+mod generics {
+    struct Priv<T = u8>(T);
+    pub struct Pub<T = u8>(T);
+    trait PrivTr<T> {}
+    pub trait PubTr<T> {}
+
+    pub fn f1(arg: [Priv; 1]) {} //~ ERROR private type `generics::Priv` in public interface
+    pub fn f2(arg: Pub<Priv>) {} //~ ERROR private type `generics::Priv` in public interface
+    pub fn f3(arg: Priv<Pub>) {}
+    //~^ ERROR private type `generics::Priv<generics::Pub>` in public interface
+}
+
+mod impls {
+    struct Priv;
+    pub struct Pub;
+    trait PrivTr {
+        type Alias;
+    }
+    pub trait PubTr {
+        type Alias;
+    }
+
+    impl Pub {
+        pub fn f(arg: Priv) {} //~ ERROR private type `impls::Priv` in public interface
+    }
+}
+
+mod aliases_pub {
+    struct Priv;
+    mod m {
+        pub struct Pub1;
+        pub struct Pub2;
+        pub struct Pub3;
+        pub trait PubTr<T = u8> {
+            type Check = u8;
+        }
+    }
+
+    use self::m::Pub1 as PrivUseAlias;
+    use self::m::PubTr as PrivUseAliasTr;
+    type PrivAlias = m::Pub2;
+    trait PrivTr {
+        type Assoc = m::Pub3;
+    }
+    impl PrivTr for Priv {}
+
+    // This should be OK, but associated type aliases are not substituted yet
+    pub fn f3(arg: <Priv as PrivTr>::Assoc) {}
+    //~^ ERROR private trait `aliases_pub::PrivTr` in public interface
+    //~| ERROR private type `aliases_pub::Priv` in public interface
+
+    impl PrivUseAlias {
+        pub fn f(arg: Priv) {} //~ ERROR private type `aliases_pub::Priv` in public interface
+    }
+}
+
+mod aliases_priv {
+    struct Priv;
+
+    struct Priv1;
+    struct Priv2;
+    struct Priv3;
+    trait PrivTr1<T = u8> {
+        type Check = u8;
+    }
+
+    use self::Priv1 as PrivUseAlias;
+    use self::PrivTr1 as PrivUseAliasTr;
+    type PrivAlias = Priv2;
+    trait PrivTr {
+        type Assoc = Priv3;
+    }
+    impl PrivTr for Priv {}
+
+    pub fn f1(arg: PrivUseAlias) {} //~ ERROR private type `aliases_priv::Priv1` in public interface
+    pub fn f2(arg: PrivAlias) {} //~ ERROR private type `aliases_priv::Priv2` in public interface
+    pub fn f3(arg: <Priv as PrivTr>::Assoc) {}
+    //~^ ERROR private trait `aliases_priv::PrivTr` in public interface
+    //~| ERROR private type `aliases_priv::Priv` in public interface
+}
+
+mod aliases_params {
+    struct Priv;
+    type PrivAliasGeneric<T = Priv> = T;
+    type Result<T> = ::std::result::Result<T, Priv>;
+
+    pub fn f2(arg: PrivAliasGeneric) {}
+    //~^ ERROR private type `aliases_params::Priv` in public interface
+    pub fn f3(arg: Result<u8>) {} //~ ERROR private type `aliases_params::Priv` in public interface
+}
+
+fn main() {}
diff --git a/src/test/ui/privacy/private-in-public.stderr b/src/test/ui/privacy/private-in-public.stderr
new file mode 100644
index 0000000..3c57e50
--- /dev/null
+++ b/src/test/ui/privacy/private-in-public.stderr
@@ -0,0 +1,298 @@
+error[E0446]: private type `types::Priv` in public interface
+  --> $DIR/private-in-public.rs:13:5
+   |
+LL |     struct Priv;
+   |     - `types::Priv` declared as private
+...
+LL |     pub const C: Priv = Priv;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
+
+error[E0446]: private type `types::Priv` in public interface
+  --> $DIR/private-in-public.rs:14:5
+   |
+LL |     struct Priv;
+   |     - `types::Priv` declared as private
+...
+LL |     pub static S: Priv = Priv;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
+
+error[E0446]: private type `types::Priv` in public interface
+  --> $DIR/private-in-public.rs:15:5
+   |
+LL |     struct Priv;
+   |     - `types::Priv` declared as private
+...
+LL |     pub fn f1(arg: Priv) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
+
+error[E0446]: private type `types::Priv` in public interface
+  --> $DIR/private-in-public.rs:16:5
+   |
+LL |     struct Priv;
+   |     - `types::Priv` declared as private
+...
+LL |     pub fn f2() -> Priv { panic!() }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
+
+error[E0446]: private type `types::Priv` in public interface
+  --> $DIR/private-in-public.rs:17:19
+   |
+LL |     struct Priv;
+   |     - `types::Priv` declared as private
+...
+LL |     pub struct S1(pub Priv);
+   |                   ^^^^^^^^ can't leak private type
+
+error[E0446]: private type `types::Priv` in public interface
+  --> $DIR/private-in-public.rs:18:21
+   |
+LL |     struct Priv;
+   |     - `types::Priv` declared as private
+...
+LL |     pub struct S2 { pub field: Priv }
+   |                     ^^^^^^^^^^^^^^^ can't leak private type
+
+error[E0446]: private type `types::Priv` in public interface
+  --> $DIR/private-in-public.rs:20:9
+   |
+LL |     struct Priv;
+   |     - `types::Priv` declared as private
+...
+LL |         pub const C: Priv = Priv;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
+
+error[E0446]: private type `types::Priv` in public interface
+  --> $DIR/private-in-public.rs:21:9
+   |
+LL |     struct Priv;
+   |     - `types::Priv` declared as private
+...
+LL |         pub fn f1(arg: Priv) {}
+   |         ^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
+
+error[E0446]: private type `types::Priv` in public interface
+  --> $DIR/private-in-public.rs:22:9
+   |
+LL |     struct Priv;
+   |     - `types::Priv` declared as private
+...
+LL |         pub fn f2() -> Priv { panic!() }
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
+
+error[E0445]: private trait `traits::PrivTr` in public interface
+  --> $DIR/private-in-public.rs:31:5
+   |
+LL |     trait PrivTr {}
+   |     - `traits::PrivTr` declared as private
+...
+LL |     pub enum E<T: PrivTr> { V(T) }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait
+
+error[E0445]: private trait `traits::PrivTr` in public interface
+  --> $DIR/private-in-public.rs:32:5
+   |
+LL |     trait PrivTr {}
+   |     - `traits::PrivTr` declared as private
+...
+LL |     pub fn f<T: PrivTr>(arg: T) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait
+
+error[E0445]: private trait `traits::PrivTr` in public interface
+  --> $DIR/private-in-public.rs:33:5
+   |
+LL |     trait PrivTr {}
+   |     - `traits::PrivTr` declared as private
+...
+LL |     pub struct S1<T: PrivTr>(T);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait
+
+error[E0445]: private trait `traits::PrivTr` in public interface
+  --> $DIR/private-in-public.rs:34:5
+   |
+LL |       trait PrivTr {}
+   |       - `traits::PrivTr` declared as private
+...
+LL | /     impl<T: PrivTr> Pub<T> {
+LL | |         pub fn f<U: PrivTr>(arg: U) {}
+LL | |     }
+   | |_____^ can't leak private trait
+
+error[E0445]: private trait `traits::PrivTr` in public interface
+  --> $DIR/private-in-public.rs:35:9
+   |
+LL |     trait PrivTr {}
+   |     - `traits::PrivTr` declared as private
+...
+LL |         pub fn f<U: PrivTr>(arg: U) {}
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait
+
+error[E0445]: private trait `traits_where::PrivTr` in public interface
+  --> $DIR/private-in-public.rs:44:5
+   |
+LL |     trait PrivTr {}
+   |     - `traits_where::PrivTr` declared as private
+...
+LL |     pub enum E<T> where T: PrivTr { V(T) }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait
+
+error[E0445]: private trait `traits_where::PrivTr` in public interface
+  --> $DIR/private-in-public.rs:46:5
+   |
+LL |     trait PrivTr {}
+   |     - `traits_where::PrivTr` declared as private
+...
+LL |     pub fn f<T>(arg: T) where T: PrivTr {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait
+
+error[E0445]: private trait `traits_where::PrivTr` in public interface
+  --> $DIR/private-in-public.rs:48:5
+   |
+LL |     trait PrivTr {}
+   |     - `traits_where::PrivTr` declared as private
+...
+LL |     pub struct S1<T>(T) where T: PrivTr;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait
+
+error[E0445]: private trait `traits_where::PrivTr` in public interface
+  --> $DIR/private-in-public.rs:50:5
+   |
+LL |       trait PrivTr {}
+   |       - `traits_where::PrivTr` declared as private
+...
+LL | /     impl<T> Pub<T> where T: PrivTr {
+LL | |
+LL | |         pub fn f<U>(arg: U) where U: PrivTr {}
+LL | |
+LL | |     }
+   | |_____^ can't leak private trait
+
+error[E0445]: private trait `traits_where::PrivTr` in public interface
+  --> $DIR/private-in-public.rs:52:9
+   |
+LL |     trait PrivTr {}
+   |     - `traits_where::PrivTr` declared as private
+...
+LL |         pub fn f<U>(arg: U) where U: PrivTr {}
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait
+
+error[E0446]: private type `generics::Priv` in public interface
+  --> $DIR/private-in-public.rs:63:5
+   |
+LL |     struct Priv<T = u8>(T);
+   |     - `generics::Priv` declared as private
+...
+LL |     pub fn f1(arg: [Priv; 1]) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
+
+error[E0446]: private type `generics::Priv` in public interface
+  --> $DIR/private-in-public.rs:64:5
+   |
+LL |     struct Priv<T = u8>(T);
+   |     - `generics::Priv` declared as private
+...
+LL |     pub fn f2(arg: Pub<Priv>) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
+
+error[E0446]: private type `generics::Priv<generics::Pub>` in public interface
+  --> $DIR/private-in-public.rs:65:5
+   |
+LL |     struct Priv<T = u8>(T);
+   |     - `generics::Priv<generics::Pub>` declared as private
+...
+LL |     pub fn f3(arg: Priv<Pub>) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
+
+error[E0446]: private type `impls::Priv` in public interface
+  --> $DIR/private-in-public.rs:80:9
+   |
+LL |     struct Priv;
+   |     - `impls::Priv` declared as private
+...
+LL |         pub fn f(arg: Priv) {}
+   |         ^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
+
+error[E0445]: private trait `aliases_pub::PrivTr` in public interface
+  --> $DIR/private-in-public.rs:104:5
+   |
+LL |     trait PrivTr {
+   |     - `aliases_pub::PrivTr` declared as private
+...
+LL |     pub fn f3(arg: <Priv as PrivTr>::Assoc) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait
+
+error[E0446]: private type `aliases_pub::Priv` in public interface
+  --> $DIR/private-in-public.rs:104:5
+   |
+LL |     struct Priv;
+   |     - `aliases_pub::Priv` declared as private
+...
+LL |     pub fn f3(arg: <Priv as PrivTr>::Assoc) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
+
+error[E0446]: private type `aliases_pub::Priv` in public interface
+  --> $DIR/private-in-public.rs:109:9
+   |
+LL |     struct Priv;
+   |     - `aliases_pub::Priv` declared as private
+...
+LL |         pub fn f(arg: Priv) {}
+   |         ^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
+
+error[E0446]: private type `aliases_priv::Priv1` in public interface
+  --> $DIR/private-in-public.rs:131:5
+   |
+LL |     struct Priv1;
+   |     - `aliases_priv::Priv1` declared as private
+...
+LL |     pub fn f1(arg: PrivUseAlias) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
+
+error[E0446]: private type `aliases_priv::Priv2` in public interface
+  --> $DIR/private-in-public.rs:132:5
+   |
+LL |     struct Priv2;
+   |     - `aliases_priv::Priv2` declared as private
+...
+LL |     pub fn f2(arg: PrivAlias) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
+
+error[E0445]: private trait `aliases_priv::PrivTr` in public interface
+  --> $DIR/private-in-public.rs:133:5
+   |
+LL |     trait PrivTr {
+   |     - `aliases_priv::PrivTr` declared as private
+...
+LL |     pub fn f3(arg: <Priv as PrivTr>::Assoc) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait
+
+error[E0446]: private type `aliases_priv::Priv` in public interface
+  --> $DIR/private-in-public.rs:133:5
+   |
+LL |     struct Priv;
+   |     - `aliases_priv::Priv` declared as private
+...
+LL |     pub fn f3(arg: <Priv as PrivTr>::Assoc) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
+
+error[E0446]: private type `aliases_params::Priv` in public interface
+  --> $DIR/private-in-public.rs:143:5
+   |
+LL |     struct Priv;
+   |     - `aliases_params::Priv` declared as private
+...
+LL |     pub fn f2(arg: PrivAliasGeneric) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
+
+error[E0446]: private type `aliases_params::Priv` in public interface
+  --> $DIR/private-in-public.rs:145:5
+   |
+LL |     struct Priv;
+   |     - `aliases_params::Priv` declared as private
+...
+LL |     pub fn f3(arg: Result<u8>) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
+
+error: aborting due to 32 previous errors
+
+Some errors occurred: E0445, E0446.
+For more information about an error, try `rustc --explain E0445`.
diff --git a/src/test/ui/privacy/private-inferred-type-1.rs b/src/test/ui/privacy/private-inferred-type-1.rs
new file mode 100644
index 0000000..69eeb2a
--- /dev/null
+++ b/src/test/ui/privacy/private-inferred-type-1.rs
@@ -0,0 +1,18 @@
+trait Arr0 {
+    fn arr0_secret(&self);
+}
+trait TyParam {
+    fn ty_param_secret(&self);
+}
+
+mod m {
+    struct Priv;
+
+    impl ::Arr0 for [Priv; 0] { fn arr0_secret(&self) {} }
+    impl ::TyParam for Option<Priv> { fn ty_param_secret(&self) {} }
+}
+
+fn main() {
+    [].arr0_secret(); //~ ERROR type `m::Priv` is private
+    None.ty_param_secret(); //~ ERROR type `m::Priv` is private
+}
diff --git a/src/test/ui/privacy/private-inferred-type-1.stderr b/src/test/ui/privacy/private-inferred-type-1.stderr
new file mode 100644
index 0000000..097b8b9
--- /dev/null
+++ b/src/test/ui/privacy/private-inferred-type-1.stderr
@@ -0,0 +1,14 @@
+error: type `m::Priv` is private
+  --> $DIR/private-inferred-type-1.rs:16:5
+   |
+LL |     [].arr0_secret();
+   |     ^^^^^^^^^^^^^^^^
+
+error: type `m::Priv` is private
+  --> $DIR/private-inferred-type-1.rs:17:5
+   |
+LL |     None.ty_param_secret();
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/privacy/private-inferred-type-2.rs b/src/test/ui/privacy/private-inferred-type-2.rs
new file mode 100644
index 0000000..28b47606
--- /dev/null
+++ b/src/test/ui/privacy/private-inferred-type-2.rs
@@ -0,0 +1,19 @@
+// aux-build:private-inferred-type.rs
+
+extern crate private_inferred_type as ext;
+
+mod m {
+    struct Priv;
+    pub struct Pub<T>(pub T);
+
+    impl Pub<Priv> {
+        pub fn get_priv() -> Priv { Priv }
+        pub fn static_method() {}
+    }
+}
+
+fn main() {
+    m::Pub::get_priv; //~ ERROR type `m::Priv` is private
+    m::Pub::static_method; //~ ERROR type `m::Priv` is private
+    ext::Pub::static_method; //~ ERROR type `ext::Priv` is private
+}
diff --git a/src/test/ui/privacy/private-inferred-type-2.stderr b/src/test/ui/privacy/private-inferred-type-2.stderr
new file mode 100644
index 0000000..da95cc4
--- /dev/null
+++ b/src/test/ui/privacy/private-inferred-type-2.stderr
@@ -0,0 +1,20 @@
+error: type `m::Priv` is private
+  --> $DIR/private-inferred-type-2.rs:16:5
+   |
+LL |     m::Pub::get_priv;
+   |     ^^^^^^^^^^^^^^^^
+
+error: type `m::Priv` is private
+  --> $DIR/private-inferred-type-2.rs:17:5
+   |
+LL |     m::Pub::static_method;
+   |     ^^^^^^^^^^^^^^^^^^^^^
+
+error: type `ext::Priv` is private
+  --> $DIR/private-inferred-type-2.rs:18:5
+   |
+LL |     ext::Pub::static_method;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/privacy/private-inferred-type-3.rs b/src/test/ui/privacy/private-inferred-type-3.rs
new file mode 100644
index 0000000..39f2e5d
--- /dev/null
+++ b/src/test/ui/privacy/private-inferred-type-3.rs
@@ -0,0 +1,17 @@
+// aux-build:private-inferred-type.rs
+
+// error-pattern:type `fn() {ext::priv_fn}` is private
+// error-pattern:static `PRIV_STATIC` is private
+// error-pattern:type `ext::PrivEnum` is private
+// error-pattern:type `fn() {<u8 as ext::PrivTrait>::method}` is private
+// error-pattern:type `fn(u8) -> ext::PrivTupleStruct {ext::PrivTupleStruct}` is private
+// error-pattern:type `fn(u8) -> ext::PubTupleStruct {ext::PubTupleStruct}` is private
+// error-pattern:type `for<'r> fn(&'r ext::Pub<u8>) {ext::Pub::<u8>::priv_method}` is private
+
+#![feature(decl_macro)]
+
+extern crate private_inferred_type as ext;
+
+fn main() {
+    ext::m!();
+}
diff --git a/src/test/ui/privacy/private-inferred-type-3.stderr b/src/test/ui/privacy/private-inferred-type-3.stderr
new file mode 100644
index 0000000..61cd847
--- /dev/null
+++ b/src/test/ui/privacy/private-inferred-type-3.stderr
@@ -0,0 +1,58 @@
+error: type `fn() {ext::priv_fn}` is private
+  --> $DIR/private-inferred-type-3.rs:16:5
+   |
+LL |     ext::m!();
+   |     ^^^^^^^^^^
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: static `PRIV_STATIC` is private
+  --> $DIR/private-inferred-type-3.rs:16:5
+   |
+LL |     ext::m!();
+   |     ^^^^^^^^^^
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: type `ext::PrivEnum` is private
+  --> $DIR/private-inferred-type-3.rs:16:5
+   |
+LL |     ext::m!();
+   |     ^^^^^^^^^^
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: type `fn() {<u8 as ext::PrivTrait>::method}` is private
+  --> $DIR/private-inferred-type-3.rs:16:5
+   |
+LL |     ext::m!();
+   |     ^^^^^^^^^^
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: type `fn(u8) -> ext::PrivTupleStruct {ext::PrivTupleStruct}` is private
+  --> $DIR/private-inferred-type-3.rs:16:5
+   |
+LL |     ext::m!();
+   |     ^^^^^^^^^^
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: type `fn(u8) -> ext::PubTupleStruct {ext::PubTupleStruct}` is private
+  --> $DIR/private-inferred-type-3.rs:16:5
+   |
+LL |     ext::m!();
+   |     ^^^^^^^^^^
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: type `for<'r> fn(&'r ext::Pub<u8>) {ext::Pub::<u8>::priv_method}` is private
+  --> $DIR/private-inferred-type-3.rs:16:5
+   |
+LL |     ext::m!();
+   |     ^^^^^^^^^^
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to 7 previous errors
+
diff --git a/src/test/ui/privacy/private-inferred-type.rs b/src/test/ui/privacy/private-inferred-type.rs
new file mode 100644
index 0000000..d9bb421
--- /dev/null
+++ b/src/test/ui/privacy/private-inferred-type.rs
@@ -0,0 +1,133 @@
+#![feature(decl_macro)]
+#![allow(private_in_public)]
+
+mod m {
+    fn priv_fn() {}
+    static PRIV_STATIC: u8 = 0;
+    enum PrivEnum { Variant }
+    pub enum PubEnum { Variant }
+    trait PrivTrait { fn method() {} }
+    impl PrivTrait for u8 {}
+    pub trait PubTrait { fn method() {} }
+    impl PubTrait for u8 {}
+    struct PrivTupleStruct(u8);
+    pub struct PubTupleStruct(u8);
+    impl PubTupleStruct { fn method() {} }
+
+    #[derive(Clone, Copy)]
+    struct Priv;
+    pub type Alias = Priv;
+    pub struct Pub<T = Alias>(pub T);
+
+    impl Pub<Priv> {
+        pub fn static_method() {}
+        pub const INHERENT_ASSOC_CONST: u8 = 0;
+    }
+    impl<T> Pub<T> {
+        pub fn static_method_generic_self() {}
+        pub const INHERENT_ASSOC_CONST_GENERIC_SELF: u8 = 0;
+    }
+    impl Pub<u8> {
+        fn priv_method(&self) {}
+        pub fn method_with_substs<T>(&self) {}
+        pub fn method_with_priv_params(&self, _: Priv) {}
+    }
+    impl TraitWithAssocConst for Priv {}
+    impl TraitWithAssocTy for Priv { type AssocTy = u8; }
+
+    pub macro m() {
+        priv_fn; //~ ERROR type `fn() {m::priv_fn}` is private
+        PRIV_STATIC; // OK, not cross-crate
+        PrivEnum::Variant; //~ ERROR type `m::PrivEnum` is private
+        PubEnum::Variant; // OK
+        <u8 as PrivTrait>::method; //~ ERROR type `fn() {<u8 as m::PrivTrait>::method}` is private
+        <u8 as PubTrait>::method; // OK
+        PrivTupleStruct;
+        //~^ ERROR type `fn(u8) -> m::PrivTupleStruct {m::PrivTupleStruct}` is private
+        PubTupleStruct;
+        //~^ ERROR type `fn(u8) -> m::PubTupleStruct {m::PubTupleStruct}` is private
+        Pub(0u8).priv_method();
+        //~^ ERROR type `for<'r> fn(&'r m::Pub<u8>) {m::Pub::<u8>::priv_method}` is private
+    }
+
+    trait Trait {}
+    pub trait TraitWithTyParam<T> {}
+    pub trait TraitWithTyParam2<T> { fn pub_method() {} }
+    pub trait TraitWithAssocTy { type AssocTy; }
+    pub trait TraitWithAssocConst { const TRAIT_ASSOC_CONST: u8 = 0; }
+    impl Trait for u8 {}
+    impl<T> TraitWithTyParam<T> for u8 {}
+    impl TraitWithTyParam2<Priv> for u8 {}
+    impl TraitWithAssocTy for u8 { type AssocTy = Priv; }
+    //~^ ERROR private type `m::Priv` in public interface
+
+    pub fn leak_anon1() -> impl Trait + 'static { 0 }
+    pub fn leak_anon2() -> impl TraitWithTyParam<Alias> { 0 }
+    pub fn leak_anon3() -> impl TraitWithAssocTy<AssocTy = Alias> { 0 }
+
+    pub fn leak_dyn1() -> Box<Trait + 'static> { Box::new(0) }
+    pub fn leak_dyn2() -> Box<TraitWithTyParam<Alias>> { Box::new(0) }
+    pub fn leak_dyn3() -> Box<TraitWithAssocTy<AssocTy = Alias>> { Box::new(0) }
+}
+
+mod adjust {
+    // Construct a chain of derefs with a private type in the middle
+    use std::ops::Deref;
+
+    pub struct S1;
+    struct S2;
+    pub type S2Alias = S2;
+    pub struct S3;
+
+    impl Deref for S1 {
+        type Target = S2Alias; //~ ERROR private type `adjust::S2` in public interface
+        fn deref(&self) -> &Self::Target { loop {} }
+    }
+    impl Deref for S2 {
+        type Target = S3;
+        fn deref(&self) -> &Self::Target { loop {} }
+    }
+
+    impl S3 {
+        pub fn method_s3(&self) {}
+    }
+}
+
+fn main() {
+    let _: m::Alias; //~ ERROR type `m::Priv` is private
+                     //~^ ERROR type `m::Priv` is private
+    let _: <m::Alias as m::TraitWithAssocTy>::AssocTy; //~ ERROR type `m::Priv` is private
+    m::Alias {}; //~ ERROR type `m::Priv` is private
+    m::Pub { 0: m::Alias {} }; //~ ERROR type `m::Priv` is private
+    m::Pub { 0: loop {} }; // OK, `m::Pub` is in value context, so it means Pub<_>, not Pub<Priv>
+    m::Pub::static_method; //~ ERROR type `m::Priv` is private
+    m::Pub::INHERENT_ASSOC_CONST; //~ ERROR type `m::Priv` is private
+    m::Pub(0u8).method_with_substs::<m::Alias>(); //~ ERROR type `m::Priv` is private
+    m::Pub(0u8).method_with_priv_params(loop{}); //~ ERROR type `m::Priv` is private
+    <m::Alias as m::TraitWithAssocConst>::TRAIT_ASSOC_CONST; //~ ERROR type `m::Priv` is private
+    <m::Pub<m::Alias>>::INHERENT_ASSOC_CONST; //~ ERROR type `m::Priv` is private
+    <m::Pub<m::Alias>>::INHERENT_ASSOC_CONST_GENERIC_SELF; //~ ERROR type `m::Priv` is private
+    <m::Pub<m::Alias>>::static_method_generic_self; //~ ERROR type `m::Priv` is private
+    use m::TraitWithTyParam2;
+    u8::pub_method; //~ ERROR type `m::Priv` is private
+
+    adjust::S1.method_s3(); //~ ERROR type `adjust::S2` is private
+
+    m::m!();
+
+    m::leak_anon1(); //~ ERROR trait `m::Trait` is private
+    m::leak_anon2(); //~ ERROR type `m::Priv` is private
+    m::leak_anon3(); //~ ERROR type `m::Priv` is private
+
+    m::leak_dyn1(); //~ ERROR trait `m::Trait` is private
+    m::leak_dyn2(); //~ ERROR type `m::Priv` is private
+    m::leak_dyn3(); //~ ERROR type `m::Priv` is private
+
+    // Check that messages are not duplicated for various kinds of assignments
+    let a = m::Alias {}; //~ ERROR type `m::Priv` is private
+    let mut b = a; //~ ERROR type `m::Priv` is private
+    b = a; //~ ERROR type `m::Priv` is private
+    match a { //~ ERROR type `m::Priv` is private
+        _ => {}
+    }
+}
diff --git a/src/test/ui/privacy/private-inferred-type.stderr b/src/test/ui/privacy/private-inferred-type.stderr
new file mode 100644
index 0000000..4d40b6b
--- /dev/null
+++ b/src/test/ui/privacy/private-inferred-type.stderr
@@ -0,0 +1,225 @@
+error[E0446]: private type `m::Priv` in public interface
+  --> $DIR/private-inferred-type.rs:61:36
+   |
+LL |     struct Priv;
+   |     - `m::Priv` declared as private
+...
+LL |     impl TraitWithAssocTy for u8 { type AssocTy = Priv; }
+   |                                    ^^^^^^^^^^^^^^^^^^^^ can't leak private type
+
+error[E0446]: private type `adjust::S2` in public interface
+  --> $DIR/private-inferred-type.rs:83:9
+   |
+LL |     struct S2;
+   |     - `adjust::S2` declared as private
+...
+LL |         type Target = S2Alias;
+   |         ^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
+
+error: type `m::Priv` is private
+  --> $DIR/private-inferred-type.rs:97:9
+   |
+LL |     let _: m::Alias;
+   |         ^
+
+error: type `m::Priv` is private
+  --> $DIR/private-inferred-type.rs:97:12
+   |
+LL |     let _: m::Alias;
+   |            ^^^^^^^^
+
+error: type `m::Priv` is private
+  --> $DIR/private-inferred-type.rs:99:13
+   |
+LL |     let _: <m::Alias as m::TraitWithAssocTy>::AssocTy;
+   |             ^^^^^^^^
+
+error: type `m::Priv` is private
+  --> $DIR/private-inferred-type.rs:100:5
+   |
+LL |     m::Alias {};
+   |     ^^^^^^^^^^^
+
+error: type `m::Priv` is private
+  --> $DIR/private-inferred-type.rs:101:5
+   |
+LL |     m::Pub { 0: m::Alias {} };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: type `m::Priv` is private
+  --> $DIR/private-inferred-type.rs:103:5
+   |
+LL |     m::Pub::static_method;
+   |     ^^^^^^^^^^^^^^^^^^^^^
+
+error: type `m::Priv` is private
+  --> $DIR/private-inferred-type.rs:104:5
+   |
+LL |     m::Pub::INHERENT_ASSOC_CONST;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: type `m::Priv` is private
+  --> $DIR/private-inferred-type.rs:105:5
+   |
+LL |     m::Pub(0u8).method_with_substs::<m::Alias>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: type `m::Priv` is private
+  --> $DIR/private-inferred-type.rs:106:17
+   |
+LL |     m::Pub(0u8).method_with_priv_params(loop{});
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: type `m::Priv` is private
+  --> $DIR/private-inferred-type.rs:107:5
+   |
+LL |     <m::Alias as m::TraitWithAssocConst>::TRAIT_ASSOC_CONST;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: type `m::Priv` is private
+  --> $DIR/private-inferred-type.rs:108:6
+   |
+LL |     <m::Pub<m::Alias>>::INHERENT_ASSOC_CONST;
+   |      ^^^^^^^^^^^^^^^^
+
+error: type `m::Priv` is private
+  --> $DIR/private-inferred-type.rs:109:5
+   |
+LL |     <m::Pub<m::Alias>>::INHERENT_ASSOC_CONST_GENERIC_SELF;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: type `m::Priv` is private
+  --> $DIR/private-inferred-type.rs:110:5
+   |
+LL |     <m::Pub<m::Alias>>::static_method_generic_self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: type `m::Priv` is private
+  --> $DIR/private-inferred-type.rs:112:5
+   |
+LL |     u8::pub_method;
+   |     ^^^^^^^^^^^^^^
+
+error: type `adjust::S2` is private
+  --> $DIR/private-inferred-type.rs:114:5
+   |
+LL |     adjust::S1.method_s3();
+   |     ^^^^^^^^^^
+
+error: type `fn() {m::priv_fn}` is private
+  --> $DIR/private-inferred-type.rs:39:9
+   |
+LL |         priv_fn;
+   |         ^^^^^^^
+...
+LL |     m::m!();
+   |     -------- in this macro invocation
+
+error: type `m::PrivEnum` is private
+  --> $DIR/private-inferred-type.rs:41:9
+   |
+LL |         PrivEnum::Variant;
+   |         ^^^^^^^^^^^^^^^^^
+...
+LL |     m::m!();
+   |     -------- in this macro invocation
+
+error: type `fn() {<u8 as m::PrivTrait>::method}` is private
+  --> $DIR/private-inferred-type.rs:43:9
+   |
+LL |         <u8 as PrivTrait>::method;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     m::m!();
+   |     -------- in this macro invocation
+
+error: type `fn(u8) -> m::PrivTupleStruct {m::PrivTupleStruct}` is private
+  --> $DIR/private-inferred-type.rs:45:9
+   |
+LL |         PrivTupleStruct;
+   |         ^^^^^^^^^^^^^^^
+...
+LL |     m::m!();
+   |     -------- in this macro invocation
+
+error: type `fn(u8) -> m::PubTupleStruct {m::PubTupleStruct}` is private
+  --> $DIR/private-inferred-type.rs:47:9
+   |
+LL |         PubTupleStruct;
+   |         ^^^^^^^^^^^^^^
+...
+LL |     m::m!();
+   |     -------- in this macro invocation
+
+error: type `for<'r> fn(&'r m::Pub<u8>) {m::Pub::<u8>::priv_method}` is private
+  --> $DIR/private-inferred-type.rs:49:18
+   |
+LL |         Pub(0u8).priv_method();
+   |                  ^^^^^^^^^^^
+...
+LL |     m::m!();
+   |     -------- in this macro invocation
+
+error: trait `m::Trait` is private
+  --> $DIR/private-inferred-type.rs:118:5
+   |
+LL |     m::leak_anon1();
+   |     ^^^^^^^^^^^^^^^
+
+error: type `m::Priv` is private
+  --> $DIR/private-inferred-type.rs:119:5
+   |
+LL |     m::leak_anon2();
+   |     ^^^^^^^^^^^^^^^
+
+error: type `m::Priv` is private
+  --> $DIR/private-inferred-type.rs:120:5
+   |
+LL |     m::leak_anon3();
+   |     ^^^^^^^^^^^^^^^
+
+error: trait `m::Trait` is private
+  --> $DIR/private-inferred-type.rs:122:5
+   |
+LL |     m::leak_dyn1();
+   |     ^^^^^^^^^^^^^^
+
+error: type `m::Priv` is private
+  --> $DIR/private-inferred-type.rs:123:5
+   |
+LL |     m::leak_dyn2();
+   |     ^^^^^^^^^^^^^^
+
+error: type `m::Priv` is private
+  --> $DIR/private-inferred-type.rs:124:5
+   |
+LL |     m::leak_dyn3();
+   |     ^^^^^^^^^^^^^^
+
+error: type `m::Priv` is private
+  --> $DIR/private-inferred-type.rs:127:13
+   |
+LL |     let a = m::Alias {};
+   |             ^^^^^^^^^^^
+
+error: type `m::Priv` is private
+  --> $DIR/private-inferred-type.rs:128:17
+   |
+LL |     let mut b = a;
+   |                 ^
+
+error: type `m::Priv` is private
+  --> $DIR/private-inferred-type.rs:129:9
+   |
+LL |     b = a;
+   |         ^
+
+error: type `m::Priv` is private
+  --> $DIR/private-inferred-type.rs:130:11
+   |
+LL |     match a {
+   |           ^
+
+error: aborting due to 33 previous errors
+
+For more information about this error, try `rustc --explain E0446`.
diff --git a/src/test/ui/privacy/private-item-simple.rs b/src/test/ui/privacy/private-item-simple.rs
new file mode 100644
index 0000000..1f718ed
--- /dev/null
+++ b/src/test/ui/privacy/private-item-simple.rs
@@ -0,0 +1,7 @@
+mod a {
+    fn f() {}
+}
+
+fn main() {
+    a::f(); //~ ERROR function `f` is private
+}
diff --git a/src/test/ui/privacy/private-item-simple.stderr b/src/test/ui/privacy/private-item-simple.stderr
new file mode 100644
index 0000000..0d5435e
--- /dev/null
+++ b/src/test/ui/privacy/private-item-simple.stderr
@@ -0,0 +1,9 @@
+error[E0603]: function `f` is private
+  --> $DIR/private-item-simple.rs:6:8
+   |
+LL |     a::f();
+   |        ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0603`.
diff --git a/src/test/ui/privacy/private-method-cross-crate.rs b/src/test/ui/privacy/private-method-cross-crate.rs
new file mode 100644
index 0000000..4da44e0
--- /dev/null
+++ b/src/test/ui/privacy/private-method-cross-crate.rs
@@ -0,0 +1,8 @@
+// aux-build:cci_class_5.rs
+extern crate cci_class_5;
+use cci_class_5::kitties::cat;
+
+fn main() {
+  let nyan : cat = cat(52, 99);
+  nyan.nap();   //~ ERROR method `nap` is private
+}
diff --git a/src/test/ui/privacy/private-method-cross-crate.stderr b/src/test/ui/privacy/private-method-cross-crate.stderr
new file mode 100644
index 0000000..10e0bfe
--- /dev/null
+++ b/src/test/ui/privacy/private-method-cross-crate.stderr
@@ -0,0 +1,9 @@
+error[E0624]: method `nap` is private
+  --> $DIR/private-method-cross-crate.rs:7:8
+   |
+LL |   nyan.nap();
+   |        ^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0624`.
diff --git a/src/test/ui/privacy/private-method-inherited.rs b/src/test/ui/privacy/private-method-inherited.rs
new file mode 100644
index 0000000..bc27027
--- /dev/null
+++ b/src/test/ui/privacy/private-method-inherited.rs
@@ -0,0 +1,14 @@
+// Tests that inherited visibility applies to methods.
+
+mod a {
+    pub struct Foo;
+
+    impl Foo {
+        fn f(self) {}
+    }
+}
+
+fn main() {
+    let x = a::Foo;
+    x.f();  //~ ERROR method `f` is private
+}
diff --git a/src/test/ui/privacy/private-method-inherited.stderr b/src/test/ui/privacy/private-method-inherited.stderr
new file mode 100644
index 0000000..d2ba591
--- /dev/null
+++ b/src/test/ui/privacy/private-method-inherited.stderr
@@ -0,0 +1,9 @@
+error[E0624]: method `f` is private
+  --> $DIR/private-method-inherited.rs:13:7
+   |
+LL |     x.f();
+   |       ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0624`.
diff --git a/src/test/ui/privacy/private-method.rs b/src/test/ui/privacy/private-method.rs
new file mode 100644
index 0000000..a9bea52
--- /dev/null
+++ b/src/test/ui/privacy/private-method.rs
@@ -0,0 +1,23 @@
+mod kitties {
+    pub struct Cat {
+        meows : usize,
+
+        how_hungry : isize,
+    }
+
+    impl Cat {
+        fn nap(&self) {}
+    }
+
+    pub fn cat(in_x : usize, in_y : isize) -> Cat {
+        Cat {
+            meows: in_x,
+            how_hungry: in_y
+        }
+    }
+}
+
+fn main() {
+  let nyan : kitties::Cat = kitties::cat(52, 99);
+  nyan.nap(); //~ ERROR method `nap` is private
+}
diff --git a/src/test/ui/privacy/private-method.stderr b/src/test/ui/privacy/private-method.stderr
new file mode 100644
index 0000000..61fc122
--- /dev/null
+++ b/src/test/ui/privacy/private-method.stderr
@@ -0,0 +1,9 @@
+error[E0624]: method `nap` is private
+  --> $DIR/private-method.rs:22:8
+   |
+LL |   nyan.nap();
+   |        ^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0624`.
diff --git a/src/test/ui/privacy/private-struct-field-cross-crate.rs b/src/test/ui/privacy/private-struct-field-cross-crate.rs
new file mode 100644
index 0000000..2efcb7f
--- /dev/null
+++ b/src/test/ui/privacy/private-struct-field-cross-crate.rs
@@ -0,0 +1,9 @@
+// aux-build:cci_class.rs
+extern crate cci_class;
+use cci_class::kitties::cat;
+
+fn main() {
+  let nyan : cat = cat(52, 99);
+  assert_eq!(nyan.meows, 52);
+  //~^ ERROR field `meows` of struct `cci_class::kitties::cat` is private
+}
diff --git a/src/test/ui/privacy/private-struct-field-cross-crate.stderr b/src/test/ui/privacy/private-struct-field-cross-crate.stderr
new file mode 100644
index 0000000..857f243
--- /dev/null
+++ b/src/test/ui/privacy/private-struct-field-cross-crate.stderr
@@ -0,0 +1,9 @@
+error[E0616]: field `meows` of struct `cci_class::kitties::cat` is private
+  --> $DIR/private-struct-field-cross-crate.rs:7:14
+   |
+LL |   assert_eq!(nyan.meows, 52);
+   |              ^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0616`.
diff --git a/src/test/ui/privacy/private-struct-field-ctor.rs b/src/test/ui/privacy/private-struct-field-ctor.rs
new file mode 100644
index 0000000..2c506f3
--- /dev/null
+++ b/src/test/ui/privacy/private-struct-field-ctor.rs
@@ -0,0 +1,9 @@
+mod a {
+    pub struct Foo {
+        x: isize
+    }
+}
+
+fn main() {
+    let s = a::Foo { x: 1 };    //~ ERROR field `x` of struct `a::Foo` is private
+}
diff --git a/src/test/ui/privacy/private-struct-field-ctor.stderr b/src/test/ui/privacy/private-struct-field-ctor.stderr
new file mode 100644
index 0000000..97585c1
--- /dev/null
+++ b/src/test/ui/privacy/private-struct-field-ctor.stderr
@@ -0,0 +1,9 @@
+error[E0451]: field `x` of struct `a::Foo` is private
+  --> $DIR/private-struct-field-ctor.rs:8:22
+   |
+LL |     let s = a::Foo { x: 1 };
+   |                      ^^^^ field `x` is private
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0451`.
diff --git a/src/test/ui/privacy/private-struct-field-pattern.rs b/src/test/ui/privacy/private-struct-field-pattern.rs
new file mode 100644
index 0000000..b3da609
--- /dev/null
+++ b/src/test/ui/privacy/private-struct-field-pattern.rs
@@ -0,0 +1,17 @@
+use a::Foo;
+
+mod a {
+    pub struct Foo {
+        x: isize
+    }
+
+    pub fn make() -> Foo {
+        Foo { x: 3 }
+    }
+}
+
+fn main() {
+    match a::make() {
+        Foo { x: _ } => {}  //~ ERROR field `x` of struct `a::Foo` is private
+    }
+}
diff --git a/src/test/ui/privacy/private-struct-field-pattern.stderr b/src/test/ui/privacy/private-struct-field-pattern.stderr
new file mode 100644
index 0000000..69bd58a
--- /dev/null
+++ b/src/test/ui/privacy/private-struct-field-pattern.stderr
@@ -0,0 +1,9 @@
+error[E0451]: field `x` of struct `a::Foo` is private
+  --> $DIR/private-struct-field-pattern.rs:15:15
+   |
+LL |         Foo { x: _ } => {}
+   |               ^^^^ field `x` is private
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0451`.
diff --git a/src/test/ui/privacy/private-struct-field.rs b/src/test/ui/privacy/private-struct-field.rs
new file mode 100644
index 0000000..216ae20
--- /dev/null
+++ b/src/test/ui/privacy/private-struct-field.rs
@@ -0,0 +1,14 @@
+mod cat {
+    pub struct Cat {
+        meows: usize
+    }
+
+    pub fn new_cat() -> Cat {
+        Cat { meows: 52 }
+    }
+}
+
+fn main() {
+    let nyan = cat::new_cat();
+    assert_eq!(nyan.meows, 52);    //~ ERROR field `meows` of struct `cat::Cat` is private
+}
diff --git a/src/test/ui/privacy/private-struct-field.stderr b/src/test/ui/privacy/private-struct-field.stderr
new file mode 100644
index 0000000..da53c73
--- /dev/null
+++ b/src/test/ui/privacy/private-struct-field.stderr
@@ -0,0 +1,9 @@
+error[E0616]: field `meows` of struct `cat::Cat` is private
+  --> $DIR/private-struct-field.rs:13:16
+   |
+LL |     assert_eq!(nyan.meows, 52);
+   |                ^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0616`.
diff --git a/src/test/ui/privacy/private-type-in-interface.rs b/src/test/ui/privacy/private-type-in-interface.rs
new file mode 100644
index 0000000..359b6da
--- /dev/null
+++ b/src/test/ui/privacy/private-type-in-interface.rs
@@ -0,0 +1,30 @@
+// aux-build:private-inferred-type.rs
+
+#![allow(warnings)]
+
+extern crate private_inferred_type as ext;
+
+mod m {
+    struct Priv;
+    pub type Alias = Priv;
+
+    pub trait Trait { type X; }
+    impl Trait for Priv { type X = u8; }
+}
+
+fn f(_: m::Alias) {} //~ ERROR type `m::Priv` is private
+                     //~^ ERROR type `m::Priv` is private
+fn f_ext(_: ext::Alias) {} //~ ERROR type `ext::Priv` is private
+                           //~^ ERROR type `ext::Priv` is private
+
+trait Tr1 {}
+impl m::Alias {} //~ ERROR type `m::Priv` is private
+impl Tr1 for ext::Alias {} //~ ERROR type `ext::Priv` is private
+type A = <m::Alias as m::Trait>::X; //~ ERROR type `m::Priv` is private
+
+trait Tr2<T> {}
+impl<T> Tr2<T> for u8 {}
+fn g() -> impl Tr2<m::Alias> { 0 } //~ ERROR type `m::Priv` is private
+fn g_ext() -> impl Tr2<ext::Alias> { 0 } //~ ERROR type `ext::Priv` is private
+
+fn main() {}
diff --git a/src/test/ui/privacy/private-type-in-interface.stderr b/src/test/ui/privacy/private-type-in-interface.stderr
new file mode 100644
index 0000000..aa4bfb7
--- /dev/null
+++ b/src/test/ui/privacy/private-type-in-interface.stderr
@@ -0,0 +1,56 @@
+error: type `m::Priv` is private
+  --> $DIR/private-type-in-interface.rs:15:9
+   |
+LL | fn f(_: m::Alias) {}
+   |         ^^^^^^^^
+
+error: type `m::Priv` is private
+  --> $DIR/private-type-in-interface.rs:15:6
+   |
+LL | fn f(_: m::Alias) {}
+   |      ^
+
+error: type `ext::Priv` is private
+  --> $DIR/private-type-in-interface.rs:17:13
+   |
+LL | fn f_ext(_: ext::Alias) {}
+   |             ^^^^^^^^^^
+
+error: type `ext::Priv` is private
+  --> $DIR/private-type-in-interface.rs:17:10
+   |
+LL | fn f_ext(_: ext::Alias) {}
+   |          ^
+
+error: type `m::Priv` is private
+  --> $DIR/private-type-in-interface.rs:21:6
+   |
+LL | impl m::Alias {}
+   |      ^^^^^^^^
+
+error: type `ext::Priv` is private
+  --> $DIR/private-type-in-interface.rs:22:14
+   |
+LL | impl Tr1 for ext::Alias {}
+   |              ^^^^^^^^^^
+
+error: type `m::Priv` is private
+  --> $DIR/private-type-in-interface.rs:23:10
+   |
+LL | type A = <m::Alias as m::Trait>::X;
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: type `m::Priv` is private
+  --> $DIR/private-type-in-interface.rs:27:11
+   |
+LL | fn g() -> impl Tr2<m::Alias> { 0 }
+   |           ^^^^^^^^^^^^^^^^^^
+
+error: type `ext::Priv` is private
+  --> $DIR/private-type-in-interface.rs:28:15
+   |
+LL | fn g_ext() -> impl Tr2<ext::Alias> { 0 }
+   |               ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 9 previous errors
+
diff --git a/src/test/ui/privacy/private-variant-reexport.rs b/src/test/ui/privacy/private-variant-reexport.rs
new file mode 100644
index 0000000..0722b81
--- /dev/null
+++ b/src/test/ui/privacy/private-variant-reexport.rs
@@ -0,0 +1,19 @@
+mod m1 {
+    pub use ::E::V; //~ ERROR variant `V` is private and cannot be re-exported
+}
+
+mod m2 {
+    pub use ::E::{V}; //~ ERROR variant `V` is private and cannot be re-exported
+}
+
+mod m3 {
+    pub use ::E::V::{self}; //~ ERROR variant `V` is private and cannot be re-exported
+}
+
+mod m4 {
+    pub use ::E::*; //~ ERROR enum is private and its variants cannot be re-exported
+}
+
+enum E { V }
+
+fn main() {}
diff --git a/src/test/ui/privacy/private-variant-reexport.stderr b/src/test/ui/privacy/private-variant-reexport.stderr
new file mode 100644
index 0000000..8e4c345
--- /dev/null
+++ b/src/test/ui/privacy/private-variant-reexport.stderr
@@ -0,0 +1,29 @@
+error: variant `V` is private and cannot be re-exported
+  --> $DIR/private-variant-reexport.rs:2:13
+   |
+LL |     pub use ::E::V;
+   |             ^^^^^^
+...
+LL | enum E { V }
+   | ------ help: consider making the enum public: `pub enum E`
+
+error: variant `V` is private and cannot be re-exported
+  --> $DIR/private-variant-reexport.rs:6:19
+   |
+LL |     pub use ::E::{V};
+   |                   ^
+
+error: variant `V` is private and cannot be re-exported
+  --> $DIR/private-variant-reexport.rs:10:22
+   |
+LL |     pub use ::E::V::{self};
+   |                      ^^^^
+
+error: enum is private and its variants cannot be re-exported
+  --> $DIR/private-variant-reexport.rs:14:13
+   |
+LL |     pub use ::E::*;
+   |             ^^^^^^
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/privacy/pub-priv-dep/auxiliary/priv_dep.rs b/src/test/ui/privacy/pub-priv-dep/auxiliary/priv_dep.rs
new file mode 100644
index 0000000..e7afeb8
--- /dev/null
+++ b/src/test/ui/privacy/pub-priv-dep/auxiliary/priv_dep.rs
@@ -0,0 +1,2 @@
+pub struct OtherType;
+pub trait OtherTrait {}
diff --git a/src/test/ui/privacy/pub-priv-dep/auxiliary/pub_dep.rs b/src/test/ui/privacy/pub-priv-dep/auxiliary/pub_dep.rs
new file mode 100644
index 0000000..3ebafd9
--- /dev/null
+++ b/src/test/ui/privacy/pub-priv-dep/auxiliary/pub_dep.rs
@@ -0,0 +1 @@
+pub struct PubType;
diff --git a/src/test/ui/privacy/pub-priv-dep/pub-priv1.rs b/src/test/ui/privacy/pub-priv-dep/pub-priv1.rs
new file mode 100644
index 0000000..9ebc960
--- /dev/null
+++ b/src/test/ui/privacy/pub-priv-dep/pub-priv1.rs
@@ -0,0 +1,46 @@
+ // aux-build:priv_dep.rs
+ // aux-build:pub_dep.rs
+ // compile-flags: --extern-private priv_dep
+#![deny(exported_private_dependencies)]
+
+// This crate is a private dependency
+extern crate priv_dep;
+// This crate is a public dependenct
+extern crate pub_dep;
+
+use priv_dep::{OtherType, OtherTrait};
+use pub_dep::PubType;
+
+// Type from private dependency used in private
+// type - this is fine
+struct PrivateType {
+    field: OtherType
+}
+
+pub struct PublicType {
+    pub field: OtherType,
+    //~^ ERROR type `priv_dep::OtherType` from private dependency 'priv_dep' in public interface
+    priv_field: OtherType, // Private field - this is fine
+    pub other_field: PubType // Type from public dependency - this is fine
+}
+
+impl PublicType {
+    pub fn pub_fn(param: OtherType) {}
+    //~^ ERROR type `priv_dep::OtherType` from private dependency 'priv_dep' in public interface
+
+    fn priv_fn(param: OtherType) {}
+}
+
+pub trait MyPubTrait {
+    type Foo: OtherTrait;
+}
+//~^^^ ERROR trait `priv_dep::OtherTrait` from private dependency 'priv_dep' in public interface
+
+pub struct AllowedPrivType {
+    #[allow(exported_private_dependencies)]
+    pub allowed: OtherType
+}
+
+
+
+fn main() {}
diff --git a/src/test/ui/privacy/pub-priv-dep/pub-priv1.stderr b/src/test/ui/privacy/pub-priv-dep/pub-priv1.stderr
new file mode 100644
index 0000000..b31efdb
--- /dev/null
+++ b/src/test/ui/privacy/pub-priv-dep/pub-priv1.stderr
@@ -0,0 +1,28 @@
+error: type `priv_dep::OtherType` from private dependency 'priv_dep' in public interface
+  --> $DIR/pub-priv1.rs:21:5
+   |
+LL |     pub field: OtherType,
+   |     ^^^^^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/pub-priv1.rs:4:9
+   |
+LL | #![deny(exported_private_dependencies)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: type `priv_dep::OtherType` from private dependency 'priv_dep' in public interface
+  --> $DIR/pub-priv1.rs:28:5
+   |
+LL |     pub fn pub_fn(param: OtherType) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: trait `priv_dep::OtherTrait` from private dependency 'priv_dep' in public interface
+  --> $DIR/pub-priv1.rs:34:1
+   |
+LL | / pub trait MyPubTrait {
+LL | |     type Foo: OtherTrait;
+LL | | }
+   | |_^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/privacy/pub-priv-dep/std-pub.rs b/src/test/ui/privacy/pub-priv-dep/std-pub.rs
new file mode 100644
index 0000000..e25aa93
--- /dev/null
+++ b/src/test/ui/privacy/pub-priv-dep/std-pub.rs
@@ -0,0 +1,12 @@
+// The 'std' crates should always be implicitly public,
+// without having to pass any compiler arguments
+
+// run-pass
+
+#![deny(exported_private_dependencies)]
+
+pub struct PublicType {
+    pub field: Option<u8>
+}
+
+fn main() {}
diff --git a/src/test/ui/privacy/restricted/auxiliary/pub_restricted.rs b/src/test/ui/privacy/restricted/auxiliary/pub_restricted.rs
new file mode 100644
index 0000000..482d5cd
--- /dev/null
+++ b/src/test/ui/privacy/restricted/auxiliary/pub_restricted.rs
@@ -0,0 +1,16 @@
+#![feature(crate_visibility_modifier)]
+
+pub(crate) struct Crate;
+
+#[derive(Default)]
+pub struct Universe {
+    pub x: i32,
+    pub(crate) y: i32,
+    crate z: i32,
+}
+
+impl Universe {
+    pub fn f(&self) {}
+    pub(crate) fn g(&self) {}
+    crate fn h(&self) {}
+}
diff --git a/src/test/ui/privacy/restricted/lookup-ignores-private.rs b/src/test/ui/privacy/restricted/lookup-ignores-private.rs
new file mode 100644
index 0000000..419d521
--- /dev/null
+++ b/src/test/ui/privacy/restricted/lookup-ignores-private.rs
@@ -0,0 +1,34 @@
+// compile-pass
+#![allow(warnings)]
+
+mod foo {
+    pub use foo::bar::S;
+    mod bar {
+        #[derive(Default)]
+        pub struct S {
+            pub(in foo) x: i32,
+        }
+        impl S {
+            pub(in foo) fn f(&self) -> i32 { 0 }
+        }
+
+        pub struct S2 {
+            pub(crate) x: bool,
+        }
+        impl S2 {
+            pub(crate) fn f(&self) -> bool { false }
+        }
+
+        impl ::std::ops::Deref for S {
+            type Target = S2;
+            fn deref(&self) -> &S2 { unimplemented!() }
+        }
+    }
+}
+
+
+fn main() {
+    let s = foo::S::default();
+    let _: bool = s.x;
+    let _: bool = s.f();
+}
diff --git a/src/test/ui/privacy/restricted/private-in-public.rs b/src/test/ui/privacy/restricted/private-in-public.rs
new file mode 100644
index 0000000..7cae289
--- /dev/null
+++ b/src/test/ui/privacy/restricted/private-in-public.rs
@@ -0,0 +1,13 @@
+#![feature(crate_visibility_modifier)]
+
+mod foo {
+    struct Priv;
+    mod bar {
+        use foo::Priv;
+        pub(super) fn f(_: Priv) {}
+        pub(crate) fn g(_: Priv) {} //~ ERROR E0446
+        crate fn h(_: Priv) {} //~ ERROR E0446
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/privacy/restricted/private-in-public.stderr b/src/test/ui/privacy/restricted/private-in-public.stderr
new file mode 100644
index 0000000..87c96d3
--- /dev/null
+++ b/src/test/ui/privacy/restricted/private-in-public.stderr
@@ -0,0 +1,21 @@
+error[E0446]: private type `foo::Priv` in public interface
+  --> $DIR/private-in-public.rs:8:9
+   |
+LL |     struct Priv;
+   |     - `foo::Priv` declared as private
+...
+LL |         pub(crate) fn g(_: Priv) {}
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
+
+error[E0446]: private type `foo::Priv` in public interface
+  --> $DIR/private-in-public.rs:9:9
+   |
+LL |     struct Priv;
+   |     - `foo::Priv` declared as private
+...
+LL |         crate fn h(_: Priv) {}
+   |         ^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0446`.
diff --git a/src/test/ui/privacy/restricted/relative-2018.rs b/src/test/ui/privacy/restricted/relative-2018.rs
new file mode 100644
index 0000000..69b7c1e
--- /dev/null
+++ b/src/test/ui/privacy/restricted/relative-2018.rs
@@ -0,0 +1,13 @@
+// edition:2018
+
+mod m {
+    pub(in crate) struct S1; // OK
+    pub(in super) struct S2; // OK
+    pub(in self) struct S3; // OK
+    pub(in ::core) struct S4;
+    //~^ ERROR visibilities can only be restricted to ancestor modules
+    pub(in a::b) struct S5;
+    //~^ ERROR relative paths are not supported in visibilities on 2018 edition
+}
+
+fn main() {}
diff --git a/src/test/ui/privacy/restricted/relative-2018.stderr b/src/test/ui/privacy/restricted/relative-2018.stderr
new file mode 100644
index 0000000..61effc4
--- /dev/null
+++ b/src/test/ui/privacy/restricted/relative-2018.stderr
@@ -0,0 +1,16 @@
+error: visibilities can only be restricted to ancestor modules
+  --> $DIR/relative-2018.rs:7:12
+   |
+LL |     pub(in ::core) struct S4;
+   |            ^^^^^^
+
+error: relative paths are not supported in visibilities on 2018 edition
+  --> $DIR/relative-2018.rs:9:12
+   |
+LL |     pub(in a::b) struct S5;
+   |            ^---
+   |            |
+   |            help: try: `crate::a::b`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/privacy/restricted/struct-literal-field.rs b/src/test/ui/privacy/restricted/struct-literal-field.rs
new file mode 100644
index 0000000..9c61047
--- /dev/null
+++ b/src/test/ui/privacy/restricted/struct-literal-field.rs
@@ -0,0 +1,19 @@
+#![allow(warnings)]
+
+mod foo {
+    pub mod bar {
+        pub struct S {
+            pub(in foo) x: i32,
+        }
+    }
+
+    fn f() {
+        use foo::bar::S;
+        S { x: 0 }; // ok
+    }
+}
+
+fn main() {
+    use foo::bar::S;
+    S { x: 0 }; //~ ERROR private
+}
diff --git a/src/test/ui/privacy/restricted/struct-literal-field.stderr b/src/test/ui/privacy/restricted/struct-literal-field.stderr
new file mode 100644
index 0000000..dd60994
--- /dev/null
+++ b/src/test/ui/privacy/restricted/struct-literal-field.stderr
@@ -0,0 +1,9 @@
+error[E0451]: field `x` of struct `foo::bar::S` is private
+  --> $DIR/struct-literal-field.rs:18:9
+   |
+LL |     S { x: 0 };
+   |         ^^^^ field `x` is private
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0451`.
diff --git a/src/test/ui/privacy/restricted/test.rs b/src/test/ui/privacy/restricted/test.rs
new file mode 100644
index 0000000..f208696
--- /dev/null
+++ b/src/test/ui/privacy/restricted/test.rs
@@ -0,0 +1,52 @@
+// aux-build:pub_restricted.rs
+
+#![allow(warnings)]
+extern crate pub_restricted;
+
+mod foo {
+    pub mod bar {
+        pub(super) fn f() {}
+        #[derive(Default)]
+        pub struct S {
+            pub(super) x: i32,
+        }
+        impl S {
+            pub(super) fn f(&self) {}
+            pub(super) fn g() {}
+        }
+    }
+    fn f() {
+        use foo::bar::S;
+        pub(self) use foo::bar::f; // ok
+        pub(super) use foo::bar::f as g; //~ ERROR cannot be re-exported
+        S::default().x; // ok
+        S::default().f(); // ok
+        S::g(); // ok
+    }
+}
+
+fn f() {
+    use foo::bar::S;
+    use foo::bar::f; //~ ERROR private
+    S::default().x; //~ ERROR private
+    S::default().f(); //~ ERROR private
+    S::g(); //~ ERROR private
+}
+
+fn main() {
+    use pub_restricted::Universe;
+    use pub_restricted::Crate; //~ ERROR private
+
+    let u = Universe::default();
+    let _ = u.x;
+    let _ = u.y; //~ ERROR private
+    let _ = u.z; //~ ERROR private
+    u.f();
+    u.g(); //~ ERROR private
+    u.h(); //~ ERROR private
+}
+
+mod pathological {
+    pub(in bad::path) mod m1 {} //~ ERROR failed to resolve: maybe a missing `extern crate bad;`?
+    pub(in foo) mod m2 {} //~ ERROR visibilities can only be restricted to ancestor modules
+}
diff --git a/src/test/ui/privacy/restricted/test.stderr b/src/test/ui/privacy/restricted/test.stderr
new file mode 100644
index 0000000..b4ef7b8
--- /dev/null
+++ b/src/test/ui/privacy/restricted/test.stderr
@@ -0,0 +1,82 @@
+error[E0433]: failed to resolve: maybe a missing `extern crate bad;`?
+  --> $DIR/test.rs:50:12
+   |
+LL |     pub(in bad::path) mod m1 {}
+   |            ^^^ maybe a missing `extern crate bad;`?
+
+error: visibilities can only be restricted to ancestor modules
+  --> $DIR/test.rs:51:12
+   |
+LL |     pub(in foo) mod m2 {}
+   |            ^^^
+
+error[E0364]: `f` is private, and cannot be re-exported
+  --> $DIR/test.rs:21:24
+   |
+LL |         pub(super) use foo::bar::f as g;
+   |                        ^^^^^^^^^^^^^^^^
+   |
+note: consider marking `f` as `pub` in the imported module
+  --> $DIR/test.rs:21:24
+   |
+LL |         pub(super) use foo::bar::f as g;
+   |                        ^^^^^^^^^^^^^^^^
+
+error[E0603]: struct `Crate` is private
+  --> $DIR/test.rs:38:25
+   |
+LL |     use pub_restricted::Crate;
+   |                         ^^^^^
+
+error[E0603]: function `f` is private
+  --> $DIR/test.rs:30:19
+   |
+LL |     use foo::bar::f;
+   |                   ^
+
+error[E0616]: field `x` of struct `foo::bar::S` is private
+  --> $DIR/test.rs:31:5
+   |
+LL |     S::default().x;
+   |     ^^^^^^^^^^^^^^
+
+error[E0624]: method `f` is private
+  --> $DIR/test.rs:32:18
+   |
+LL |     S::default().f();
+   |                  ^
+
+error[E0624]: method `g` is private
+  --> $DIR/test.rs:33:5
+   |
+LL |     S::g();
+   |     ^^^^
+
+error[E0616]: field `y` of struct `pub_restricted::Universe` is private
+  --> $DIR/test.rs:42:13
+   |
+LL |     let _ = u.y;
+   |             ^^^
+
+error[E0616]: field `z` of struct `pub_restricted::Universe` is private
+  --> $DIR/test.rs:43:13
+   |
+LL |     let _ = u.z;
+   |             ^^^
+
+error[E0624]: method `g` is private
+  --> $DIR/test.rs:45:7
+   |
+LL |     u.g();
+   |       ^
+
+error[E0624]: method `h` is private
+  --> $DIR/test.rs:46:7
+   |
+LL |     u.h();
+   |       ^
+
+error: aborting due to 12 previous errors
+
+Some errors occurred: E0364, E0433, E0603, E0616, E0624.
+For more information about an error, try `rustc --explain E0364`.
diff --git a/src/test/ui/privacy/union-field-privacy-1.rs b/src/test/ui/privacy/union-field-privacy-1.rs
new file mode 100644
index 0000000..1ff4d51
--- /dev/null
+++ b/src/test/ui/privacy/union-field-privacy-1.rs
@@ -0,0 +1,17 @@
+mod m {
+    pub union U {
+        pub a: u8,
+        pub(super) b: u8,
+        c: u8,
+    }
+}
+
+fn main() { unsafe {
+    let u = m::U { a: 0 }; // OK
+    let u = m::U { b: 0 }; // OK
+    let u = m::U { c: 0 }; //~ ERROR field `c` of union `m::U` is private
+
+    let m::U { a } = u; // OK
+    let m::U { b } = u; // OK
+    let m::U { c } = u; //~ ERROR field `c` of union `m::U` is private
+}}
diff --git a/src/test/ui/privacy/union-field-privacy-1.stderr b/src/test/ui/privacy/union-field-privacy-1.stderr
new file mode 100644
index 0000000..96a1d7e
--- /dev/null
+++ b/src/test/ui/privacy/union-field-privacy-1.stderr
@@ -0,0 +1,15 @@
+error[E0451]: field `c` of union `m::U` is private
+  --> $DIR/union-field-privacy-1.rs:12:20
+   |
+LL |     let u = m::U { c: 0 };
+   |                    ^^^^ field `c` is private
+
+error[E0451]: field `c` of union `m::U` is private
+  --> $DIR/union-field-privacy-1.rs:16:16
+   |
+LL |     let m::U { c } = u;
+   |                ^ field `c` is private
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0451`.
diff --git a/src/test/ui/privacy/union-field-privacy-2.rs b/src/test/ui/privacy/union-field-privacy-2.rs
new file mode 100644
index 0000000..4827963
--- /dev/null
+++ b/src/test/ui/privacy/union-field-privacy-2.rs
@@ -0,0 +1,15 @@
+mod m {
+    pub union U {
+        pub a: u8,
+        pub(super) b: u8,
+        c: u8,
+    }
+}
+
+fn main() {
+    let u = m::U { a: 10 };
+
+    let a = u.a; // OK
+    let b = u.b; // OK
+    let c = u.c; //~ ERROR field `c` of struct `m::U` is private
+}
diff --git a/src/test/ui/privacy/union-field-privacy-2.stderr b/src/test/ui/privacy/union-field-privacy-2.stderr
new file mode 100644
index 0000000..df054b8
--- /dev/null
+++ b/src/test/ui/privacy/union-field-privacy-2.stderr
@@ -0,0 +1,9 @@
+error[E0616]: field `c` of struct `m::U` is private
+  --> $DIR/union-field-privacy-2.rs:14:13
+   |
+LL |     let c = u.c;
+   |             ^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0616`.
diff --git a/src/test/ui/proc-macro/ambiguous-builtin-attrs-test.rs b/src/test/ui/proc-macro/ambiguous-builtin-attrs-test.rs
new file mode 100644
index 0000000..6a47e50
--- /dev/null
+++ b/src/test/ui/proc-macro/ambiguous-builtin-attrs-test.rs
@@ -0,0 +1,20 @@
+// aux-build:builtin-attrs.rs
+// compile-flags:--test
+
+#![feature(decl_macro, test)]
+
+extern crate test;
+extern crate builtin_attrs;
+use builtin_attrs::{test, bench};
+
+#[test] // OK, shadowed
+fn test() {}
+
+#[bench] // OK, shadowed
+fn bench(b: &mut test::Bencher) {}
+
+fn not_main() {
+    Test;
+    Bench;
+    NonExistent; //~ ERROR cannot find value `NonExistent` in this scope
+}
diff --git a/src/test/ui/proc-macro/ambiguous-builtin-attrs-test.stderr b/src/test/ui/proc-macro/ambiguous-builtin-attrs-test.stderr
new file mode 100644
index 0000000..316eb63
--- /dev/null
+++ b/src/test/ui/proc-macro/ambiguous-builtin-attrs-test.stderr
@@ -0,0 +1,9 @@
+error[E0425]: cannot find value `NonExistent` in this scope
+  --> $DIR/ambiguous-builtin-attrs-test.rs:19:5
+   |
+LL |     NonExistent;
+   |     ^^^^^^^^^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/proc-macro/ambiguous-builtin-attrs.rs b/src/test/ui/proc-macro/ambiguous-builtin-attrs.rs
new file mode 100644
index 0000000..9f4f0ab
--- /dev/null
+++ b/src/test/ui/proc-macro/ambiguous-builtin-attrs.rs
@@ -0,0 +1,31 @@
+// aux-build:builtin-attrs.rs
+
+#![feature(decl_macro)] //~ ERROR `feature` is ambiguous
+
+extern crate builtin_attrs;
+use builtin_attrs::{test, bench};
+use builtin_attrs::*;
+
+#[repr(C)] //~ ERROR `repr` is ambiguous
+struct S;
+#[cfg_attr(all(), repr(C))] //~ ERROR `repr` is ambiguous
+struct SCond;
+
+#[test] // OK, shadowed
+fn test() {}
+
+#[bench] // OK, shadowed
+fn bench() {}
+
+fn non_macro_expanded_location<#[repr(C)] T>() { //~ ERROR `repr` is ambiguous
+    match 0u8 {
+        #[repr(C)] //~ ERROR `repr` is ambiguous
+        _ => {}
+    }
+}
+
+fn main() {
+    Test;
+    Bench;
+    NonExistent; //~ ERROR cannot find value `NonExistent` in this scope
+}
diff --git a/src/test/ui/proc-macro/ambiguous-builtin-attrs.stderr b/src/test/ui/proc-macro/ambiguous-builtin-attrs.stderr
new file mode 100644
index 0000000..975be7c
--- /dev/null
+++ b/src/test/ui/proc-macro/ambiguous-builtin-attrs.stderr
@@ -0,0 +1,80 @@
+error[E0425]: cannot find value `NonExistent` in this scope
+  --> $DIR/ambiguous-builtin-attrs.rs:30:5
+   |
+LL |     NonExistent;
+   |     ^^^^^^^^^^^ not found in this scope
+
+error[E0659]: `repr` is ambiguous (built-in attribute vs any other name)
+  --> $DIR/ambiguous-builtin-attrs.rs:9:3
+   |
+LL | #[repr(C)]
+   |   ^^^^ ambiguous name
+   |
+   = note: `repr` could refer to a built-in attribute
+note: `repr` could also refer to the attribute macro imported here
+  --> $DIR/ambiguous-builtin-attrs.rs:7:5
+   |
+LL | use builtin_attrs::*;
+   |     ^^^^^^^^^^^^^^^^
+   = help: use `crate::repr` to refer to this attribute macro unambiguously
+
+error[E0659]: `repr` is ambiguous (built-in attribute vs any other name)
+  --> $DIR/ambiguous-builtin-attrs.rs:11:19
+   |
+LL | #[cfg_attr(all(), repr(C))]
+   |                   ^^^^ ambiguous name
+   |
+   = note: `repr` could refer to a built-in attribute
+note: `repr` could also refer to the attribute macro imported here
+  --> $DIR/ambiguous-builtin-attrs.rs:7:5
+   |
+LL | use builtin_attrs::*;
+   |     ^^^^^^^^^^^^^^^^
+   = help: use `crate::repr` to refer to this attribute macro unambiguously
+
+error[E0659]: `repr` is ambiguous (built-in attribute vs any other name)
+  --> $DIR/ambiguous-builtin-attrs.rs:20:34
+   |
+LL | fn non_macro_expanded_location<#[repr(C)] T>() {
+   |                                  ^^^^ ambiguous name
+   |
+   = note: `repr` could refer to a built-in attribute
+note: `repr` could also refer to the attribute macro imported here
+  --> $DIR/ambiguous-builtin-attrs.rs:7:5
+   |
+LL | use builtin_attrs::*;
+   |     ^^^^^^^^^^^^^^^^
+   = help: use `crate::repr` to refer to this attribute macro unambiguously
+
+error[E0659]: `repr` is ambiguous (built-in attribute vs any other name)
+  --> $DIR/ambiguous-builtin-attrs.rs:22:11
+   |
+LL |         #[repr(C)]
+   |           ^^^^ ambiguous name
+   |
+   = note: `repr` could refer to a built-in attribute
+note: `repr` could also refer to the attribute macro imported here
+  --> $DIR/ambiguous-builtin-attrs.rs:7:5
+   |
+LL | use builtin_attrs::*;
+   |     ^^^^^^^^^^^^^^^^
+   = help: use `crate::repr` to refer to this attribute macro unambiguously
+
+error[E0659]: `feature` is ambiguous (built-in attribute vs any other name)
+  --> $DIR/ambiguous-builtin-attrs.rs:3:4
+   |
+LL | #![feature(decl_macro)]
+   |    ^^^^^^^ ambiguous name
+   |
+   = note: `feature` could refer to a built-in attribute
+note: `feature` could also refer to the attribute macro imported here
+  --> $DIR/ambiguous-builtin-attrs.rs:7:5
+   |
+LL | use builtin_attrs::*;
+   |     ^^^^^^^^^^^^^^^^
+   = help: use `crate::feature` to refer to this attribute macro unambiguously
+
+error: aborting due to 6 previous errors
+
+Some errors occurred: E0425, E0659.
+For more information about an error, try `rustc --explain E0425`.
diff --git a/src/test/ui/proc-macro/attr-invalid-exprs.rs b/src/test/ui/proc-macro/attr-invalid-exprs.rs
new file mode 100644
index 0000000..c609cae
--- /dev/null
+++ b/src/test/ui/proc-macro/attr-invalid-exprs.rs
@@ -0,0 +1,27 @@
+// aux-build:attr-stmt-expr.rs
+
+//! Attributes producing expressions in invalid locations
+
+#![feature(stmt_expr_attributes, proc_macro_hygiene)]
+
+extern crate attr_stmt_expr;
+use attr_stmt_expr::{duplicate, no_output};
+
+fn main() {
+    let _ = #[no_output] "Hello, world!";
+    //~^ ERROR expected expression, found `<eof>`
+
+    let _ = #[duplicate] "Hello, world!";
+    //~^ ERROR macro expansion ignores token `,` and any following
+
+    let _ = {
+        #[no_output]
+        "Hello, world!"
+    };
+
+    let _ = {
+        #[duplicate]
+        //~^ ERROR macro expansion ignores token `,` and any following
+        "Hello, world!"
+    };
+}
diff --git a/src/test/ui/proc-macro/attr-invalid-exprs.stderr b/src/test/ui/proc-macro/attr-invalid-exprs.stderr
new file mode 100644
index 0000000..5d2fb59
--- /dev/null
+++ b/src/test/ui/proc-macro/attr-invalid-exprs.stderr
@@ -0,0 +1,28 @@
+error: expected expression, found `<eof>`
+  --> $DIR/attr-invalid-exprs.rs:11:13
+   |
+LL |     let _ = #[no_output] "Hello, world!";
+   |             ^^^^^^^^^^^^
+
+error: macro expansion ignores token `,` and any following
+  --> $DIR/attr-invalid-exprs.rs:14:13
+   |
+LL |     let _ = #[duplicate] "Hello, world!";
+   |             ^^^^^^^^^^^^- help: you might be missing a semicolon here: `;`
+   |             |
+   |             caused by the macro expansion here
+   |
+   = note: the usage of `duplicate!` is likely invalid in expression context
+
+error: macro expansion ignores token `,` and any following
+  --> $DIR/attr-invalid-exprs.rs:23:9
+   |
+LL |         #[duplicate]
+   |         ^^^^^^^^^^^^- help: you might be missing a semicolon here: `;`
+   |         |
+   |         caused by the macro expansion here
+   |
+   = note: the usage of `duplicate!` is likely invalid in expression context
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/proc-macro/attr-stmt-expr.rs b/src/test/ui/proc-macro/attr-stmt-expr.rs
new file mode 100644
index 0000000..5fdaf93
--- /dev/null
+++ b/src/test/ui/proc-macro/attr-stmt-expr.rs
@@ -0,0 +1,27 @@
+// aux-build:attr-stmt-expr.rs
+
+#![feature(proc_macro_hygiene)]
+
+extern crate attr_stmt_expr;
+use attr_stmt_expr::{expect_let, expect_print_stmt, expect_expr, expect_print_expr};
+
+fn print_str(string: &'static str) {
+    // macros are handled a bit differently
+    #[expect_print_expr]
+    //~^ ERROR attributes on expressions are experimental
+    //~| HELP add #![feature(stmt_expr_attributes)] to the crate attributes to enable
+    println!("{}", string)
+}
+
+fn main() {
+    #[expect_let]
+    let string = "Hello, world!";
+
+    #[expect_print_stmt]
+    println!("{}", string);
+
+    #[expect_expr]
+    //~^ ERROR attributes on expressions are experimental
+    //~| HELP add #![feature(stmt_expr_attributes)] to the crate attributes to enable
+    print_str("string")
+}
diff --git a/src/test/ui/proc-macro/attr-stmt-expr.stderr b/src/test/ui/proc-macro/attr-stmt-expr.stderr
new file mode 100644
index 0000000..34ee012
--- /dev/null
+++ b/src/test/ui/proc-macro/attr-stmt-expr.stderr
@@ -0,0 +1,19 @@
+error[E0658]: attributes on expressions are experimental. (see issue #15701)
+  --> $DIR/attr-stmt-expr.rs:10:5
+   |
+LL |     #[expect_print_expr]
+   |     ^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(stmt_expr_attributes)] to the crate attributes to enable
+
+error[E0658]: attributes on expressions are experimental. (see issue #15701)
+  --> $DIR/attr-stmt-expr.rs:23:5
+   |
+LL |     #[expect_expr]
+   |     ^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(stmt_expr_attributes)] to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/proc-macro/attribute-order-restricted.rs b/src/test/ui/proc-macro/attribute-order-restricted.rs
new file mode 100644
index 0000000..7b1eecd
--- /dev/null
+++ b/src/test/ui/proc-macro/attribute-order-restricted.rs
@@ -0,0 +1,14 @@
+// aux-build:attr_proc_macro.rs
+
+extern crate attr_proc_macro;
+use attr_proc_macro::*;
+
+#[attr_proc_macro] // OK
+#[derive(Clone)]
+struct Before;
+
+#[derive(Clone)]
+#[attr_proc_macro] //~ ERROR macro attributes must be placed before `#[derive]`
+struct After;
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/attribute-order-restricted.stderr b/src/test/ui/proc-macro/attribute-order-restricted.stderr
new file mode 100644
index 0000000..39db45c
--- /dev/null
+++ b/src/test/ui/proc-macro/attribute-order-restricted.stderr
@@ -0,0 +1,8 @@
+error: macro attributes must be placed before `#[derive]`
+  --> $DIR/attribute-order-restricted.rs:11:1
+   |
+LL | #[attr_proc_macro]
+   | ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/proc-macro/attribute-spans-preserved.rs b/src/test/ui/proc-macro/attribute-spans-preserved.rs
new file mode 100644
index 0000000..c01fce9
--- /dev/null
+++ b/src/test/ui/proc-macro/attribute-spans-preserved.rs
@@ -0,0 +1,10 @@
+// aux-build:attribute-spans-preserved.rs
+
+extern crate attribute_spans_preserved as foo;
+
+use foo::foo;
+
+#[ foo ( let y: u32 = "z"; ) ] //~ ERROR: mismatched types
+#[ bar { let x: u32 = "y"; } ] //~ ERROR: mismatched types
+fn main() {
+}
diff --git a/src/test/ui/proc-macro/attribute-spans-preserved.stderr b/src/test/ui/proc-macro/attribute-spans-preserved.stderr
new file mode 100644
index 0000000..6c571db
--- /dev/null
+++ b/src/test/ui/proc-macro/attribute-spans-preserved.stderr
@@ -0,0 +1,21 @@
+error[E0308]: mismatched types
+  --> $DIR/attribute-spans-preserved.rs:7:23
+   |
+LL | #[ foo ( let y: u32 = "z"; ) ]
+   |                       ^^^ expected u32, found reference
+   |
+   = note: expected type `u32`
+              found type `&'static str`
+
+error[E0308]: mismatched types
+  --> $DIR/attribute-spans-preserved.rs:8:23
+   |
+LL | #[ bar { let x: u32 = "y"; } ]
+   |                       ^^^ expected u32, found reference
+   |
+   = note: expected type `u32`
+              found type `&'static str`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/proc-macro/attribute-spans-preserved.stdout b/src/test/ui/proc-macro/attribute-spans-preserved.stdout
new file mode 100644
index 0000000..b1487fc
--- /dev/null
+++ b/src/test/ui/proc-macro/attribute-spans-preserved.stdout
@@ -0,0 +1 @@
+fn main (  ) { let y : u32 = "z" ; { let x : u32 = "y" ; } }
diff --git a/src/test/ui/proc-macro/attribute-with-error.rs b/src/test/ui/proc-macro/attribute-with-error.rs
new file mode 100644
index 0000000..2cced40
--- /dev/null
+++ b/src/test/ui/proc-macro/attribute-with-error.rs
@@ -0,0 +1,43 @@
+// aux-build:attribute-with-error.rs
+
+#![feature(custom_inner_attributes)]
+
+extern crate attribute_with_error;
+
+use attribute_with_error::foo;
+
+#[foo]
+fn test1() {
+    let a: i32 = "foo";
+    //~^ ERROR: mismatched types
+    let b: i32 = "f'oo";
+    //~^ ERROR: mismatched types
+}
+
+fn test2() {
+    #![foo]
+
+    // FIXME: should have a type error here and assert it works but it doesn't
+}
+
+trait A {
+    // FIXME: should have a #[foo] attribute here and assert that it works
+    fn foo(&self) {
+        let a: i32 = "foo";
+        //~^ ERROR: mismatched types
+    }
+}
+
+struct B;
+
+impl A for B {
+    #[foo]
+    fn foo(&self) {
+        let a: i32 = "foo";
+        //~^ ERROR: mismatched types
+    }
+}
+
+#[foo]
+fn main() {
+}
diff --git a/src/test/ui/proc-macro/attribute-with-error.stderr b/src/test/ui/proc-macro/attribute-with-error.stderr
new file mode 100644
index 0000000..c5970ab
--- /dev/null
+++ b/src/test/ui/proc-macro/attribute-with-error.stderr
@@ -0,0 +1,39 @@
+error[E0308]: mismatched types
+  --> $DIR/attribute-with-error.rs:11:18
+   |
+LL |     let a: i32 = "foo";
+   |                  ^^^^^ expected i32, found reference
+   |
+   = note: expected type `i32`
+              found type `&'static str`
+
+error[E0308]: mismatched types
+  --> $DIR/attribute-with-error.rs:13:18
+   |
+LL |     let b: i32 = "f'oo";
+   |                  ^^^^^^ expected i32, found reference
+   |
+   = note: expected type `i32`
+              found type `&'static str`
+
+error[E0308]: mismatched types
+  --> $DIR/attribute-with-error.rs:26:22
+   |
+LL |         let a: i32 = "foo";
+   |                      ^^^^^ expected i32, found reference
+   |
+   = note: expected type `i32`
+              found type `&'static str`
+
+error[E0308]: mismatched types
+  --> $DIR/attribute-with-error.rs:36:22
+   |
+LL |         let a: i32 = "foo";
+   |                      ^^^^^ expected i32, found reference
+   |
+   = note: expected type `i32`
+              found type `&'static str`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/proc-macro/attribute.rs b/src/test/ui/proc-macro/attribute.rs
new file mode 100644
index 0000000..ac7d0b4
--- /dev/null
+++ b/src/test/ui/proc-macro/attribute.rs
@@ -0,0 +1,76 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::*;
+
+#[proc_macro_derive]
+//~^ ERROR: attribute must be of the form
+pub fn foo1(input: TokenStream) -> TokenStream { input }
+
+#[proc_macro_derive = ""]
+//~^ ERROR: attribute must be of the form
+pub fn foo2(input: TokenStream) -> TokenStream { input }
+
+#[proc_macro_derive(d3, a, b)]
+//~^ ERROR: attribute must have either one or two arguments
+pub fn foo3(input: TokenStream) -> TokenStream { input }
+
+#[proc_macro_derive(d4, attributes(a), b)]
+//~^ ERROR: attribute must have either one or two arguments
+pub fn foo4(input: TokenStream) -> TokenStream { input }
+
+#[proc_macro_derive("a")]
+//~^ ERROR: not a meta item
+pub fn foo5(input: TokenStream) -> TokenStream { input }
+
+#[proc_macro_derive(d6 = "")]
+//~^ ERROR: must only be one word
+pub fn foo6(input: TokenStream) -> TokenStream { input }
+
+#[proc_macro_derive(m::d7)]
+//~^ ERROR: must only be one word
+pub fn foo7(input: TokenStream) -> TokenStream { input }
+
+#[proc_macro_derive(d8(a))]
+//~^ ERROR: must only be one word
+pub fn foo8(input: TokenStream) -> TokenStream { input }
+
+#[proc_macro_derive(self)]
+//~^ ERROR: `self` cannot be a name of derive macro
+pub fn foo9(input: TokenStream) -> TokenStream { input }
+
+#[proc_macro_derive(PartialEq)]
+//~^ ERROR: cannot override a built-in derive macro
+pub fn foo10(input: TokenStream) -> TokenStream { input }
+
+#[proc_macro_derive(d11, a)]
+//~^ ERROR: second argument must be `attributes`
+//~| ERROR: attribute must be of form: `attributes(foo, bar)`
+pub fn foo11(input: TokenStream) -> TokenStream { input }
+
+#[proc_macro_derive(d12, attributes)]
+//~^ ERROR: attribute must be of form: `attributes(foo, bar)`
+pub fn foo12(input: TokenStream) -> TokenStream { input }
+
+#[proc_macro_derive(d13, attributes("a"))]
+//~^ ERROR: not a meta item
+pub fn foo13(input: TokenStream) -> TokenStream { input }
+
+#[proc_macro_derive(d14, attributes(a = ""))]
+//~^ ERROR: must only be one word
+pub fn foo14(input: TokenStream) -> TokenStream { input }
+
+#[proc_macro_derive(d15, attributes(m::a))]
+//~^ ERROR: must only be one word
+pub fn foo15(input: TokenStream) -> TokenStream { input }
+
+#[proc_macro_derive(d16, attributes(a(b)))]
+//~^ ERROR: must only be one word
+pub fn foo16(input: TokenStream) -> TokenStream { input }
+
+#[proc_macro_derive(d17, attributes(self))]
+//~^ ERROR: `self` cannot be a name of derive helper attribute
+pub fn foo17(input: TokenStream) -> TokenStream { input }
diff --git a/src/test/ui/proc-macro/attribute.stderr b/src/test/ui/proc-macro/attribute.stderr
new file mode 100644
index 0000000..cc17d38
--- /dev/null
+++ b/src/test/ui/proc-macro/attribute.stderr
@@ -0,0 +1,110 @@
+error: attribute must have either one or two arguments
+  --> $DIR/attribute.rs:17:1
+   |
+LL | #[proc_macro_derive(d3, a, b)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: attribute must have either one or two arguments
+  --> $DIR/attribute.rs:21:1
+   |
+LL | #[proc_macro_derive(d4, attributes(a), b)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: not a meta item
+  --> $DIR/attribute.rs:25:21
+   |
+LL | #[proc_macro_derive("a")]
+   |                     ^^^
+
+error: must only be one word
+  --> $DIR/attribute.rs:29:21
+   |
+LL | #[proc_macro_derive(d6 = "")]
+   |                     ^^^^^^^
+
+error: must only be one word
+  --> $DIR/attribute.rs:33:21
+   |
+LL | #[proc_macro_derive(m::d7)]
+   |                     ^^^^^
+
+error: must only be one word
+  --> $DIR/attribute.rs:37:21
+   |
+LL | #[proc_macro_derive(d8(a))]
+   |                     ^^^^^
+
+error: `self` cannot be a name of derive macro
+  --> $DIR/attribute.rs:41:21
+   |
+LL | #[proc_macro_derive(self)]
+   |                     ^^^^
+
+error: cannot override a built-in derive macro
+  --> $DIR/attribute.rs:45:21
+   |
+LL | #[proc_macro_derive(PartialEq)]
+   |                     ^^^^^^^^^
+
+error: second argument must be `attributes`
+  --> $DIR/attribute.rs:49:26
+   |
+LL | #[proc_macro_derive(d11, a)]
+   |                          ^
+
+error: attribute must be of form: `attributes(foo, bar)`
+  --> $DIR/attribute.rs:49:26
+   |
+LL | #[proc_macro_derive(d11, a)]
+   |                          ^
+
+error: attribute must be of form: `attributes(foo, bar)`
+  --> $DIR/attribute.rs:54:26
+   |
+LL | #[proc_macro_derive(d12, attributes)]
+   |                          ^^^^^^^^^^
+
+error: not a meta item
+  --> $DIR/attribute.rs:58:37
+   |
+LL | #[proc_macro_derive(d13, attributes("a"))]
+   |                                     ^^^
+
+error: must only be one word
+  --> $DIR/attribute.rs:62:37
+   |
+LL | #[proc_macro_derive(d14, attributes(a = ""))]
+   |                                     ^^^^^^
+
+error: must only be one word
+  --> $DIR/attribute.rs:66:37
+   |
+LL | #[proc_macro_derive(d15, attributes(m::a))]
+   |                                     ^^^^
+
+error: must only be one word
+  --> $DIR/attribute.rs:70:37
+   |
+LL | #[proc_macro_derive(d16, attributes(a(b)))]
+   |                                     ^^^^
+
+error: `self` cannot be a name of derive helper attribute
+  --> $DIR/attribute.rs:74:37
+   |
+LL | #[proc_macro_derive(d17, attributes(self))]
+   |                                     ^^^^
+
+error: attribute must be of the form `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]`
+  --> $DIR/attribute.rs:9:1
+   |
+LL | #[proc_macro_derive]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: attribute must be of the form `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]`
+  --> $DIR/attribute.rs:13:1
+   |
+LL | #[proc_macro_derive = ""]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 18 previous errors
+
diff --git a/src/test/ui/proc-macro/attributes-included.rs b/src/test/ui/proc-macro/attributes-included.rs
new file mode 100644
index 0000000..0ab17a1
--- /dev/null
+++ b/src/test/ui/proc-macro/attributes-included.rs
@@ -0,0 +1,22 @@
+// aux-build:attributes-included.rs
+// compile-pass
+
+#![warn(unused)]
+
+extern crate attributes_included;
+
+use attributes_included::*;
+
+#[bar]
+#[inline]
+/// doc
+#[foo]
+#[inline]
+/// doc
+fn foo() {
+    let a: i32 = "foo"; //~ WARN: unused variable
+}
+
+fn main() {
+    foo()
+}
diff --git a/src/test/ui/proc-macro/attributes-included.stderr b/src/test/ui/proc-macro/attributes-included.stderr
new file mode 100644
index 0000000..fcd77b2
--- /dev/null
+++ b/src/test/ui/proc-macro/attributes-included.stderr
@@ -0,0 +1,13 @@
+warning: unused variable: `a`
+  --> $DIR/attributes-included.rs:17:9
+   |
+LL |     let a: i32 = "foo";
+   |         ^ help: consider prefixing with an underscore: `_a`
+   |
+note: lint level defined here
+  --> $DIR/attributes-included.rs:4:9
+   |
+LL | #![warn(unused)]
+   |         ^^^^^^
+   = note: #[warn(unused_variables)] implied by #[warn(unused)]
+
diff --git a/src/test/ui/proc-macro/auxiliary/attr-stmt-expr.rs b/src/test/ui/proc-macro/auxiliary/attr-stmt-expr.rs
new file mode 100644
index 0000000..0a82cbe
--- /dev/null
+++ b/src/test/ui/proc-macro/auxiliary/attr-stmt-expr.rs
@@ -0,0 +1,49 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_attribute]
+pub fn expect_let(attr: TokenStream, item: TokenStream) -> TokenStream {
+    assert!(attr.to_string().is_empty());
+    assert_eq!(item.to_string(), "let string = \"Hello, world!\";");
+    item
+}
+
+#[proc_macro_attribute]
+pub fn expect_print_stmt(attr: TokenStream, item: TokenStream) -> TokenStream {
+    assert!(attr.to_string().is_empty());
+    assert_eq!(item.to_string(), "println!(\"{}\" , string);");
+    item
+}
+
+#[proc_macro_attribute]
+pub fn expect_expr(attr: TokenStream, item: TokenStream) -> TokenStream {
+    assert!(attr.to_string().is_empty());
+    assert_eq!(item.to_string(), "print_str(\"string\")");
+    item
+}
+
+#[proc_macro_attribute]
+pub fn expect_print_expr(attr: TokenStream, item: TokenStream) -> TokenStream {
+    assert!(attr.to_string().is_empty());
+    assert_eq!(item.to_string(), "println!(\"{}\" , string)");
+    item
+}
+
+#[proc_macro_attribute]
+pub fn duplicate(attr: TokenStream, item: TokenStream) -> TokenStream {
+    assert!(attr.to_string().is_empty());
+    format!("{}, {}", item, item).parse().unwrap()
+}
+
+#[proc_macro_attribute]
+pub fn no_output(attr: TokenStream, item: TokenStream) -> TokenStream {
+    assert!(attr.to_string().is_empty());
+    assert!(!item.to_string().is_empty());
+    "".parse().unwrap()
+}
diff --git a/src/test/ui/proc-macro/auxiliary/attr_proc_macro.rs b/src/test/ui/proc-macro/auxiliary/attr_proc_macro.rs
new file mode 100644
index 0000000..b1f54be
--- /dev/null
+++ b/src/test/ui/proc-macro/auxiliary/attr_proc_macro.rs
@@ -0,0 +1,13 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_attribute]
+pub fn attr_proc_macro(_: TokenStream, input: TokenStream) -> TokenStream {
+    input
+}
diff --git a/src/test/ui/proc-macro/auxiliary/attribute-spans-preserved.rs b/src/test/ui/proc-macro/auxiliary/attribute-spans-preserved.rs
new file mode 100644
index 0000000..4d32795
--- /dev/null
+++ b/src/test/ui/proc-macro/auxiliary/attribute-spans-preserved.rs
@@ -0,0 +1,35 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::*;
+
+#[proc_macro_attribute]
+pub fn foo(attr: TokenStream, f: TokenStream) -> TokenStream {
+    let mut tokens = f.into_iter();
+    assert_eq!(tokens.next().unwrap().to_string(), "#");
+    let next_attr = match tokens.next().unwrap() {
+        TokenTree::Group(g) => g,
+        _ => panic!(),
+    };
+
+    let fn_tok = tokens.next().unwrap();
+    let ident_tok = tokens.next().unwrap();
+    let args_tok = tokens.next().unwrap();
+    let body = tokens.next().unwrap();
+
+    let new_body = attr.into_iter()
+        .chain(next_attr.stream().into_iter().skip(1));
+
+    let tokens = vec![
+        fn_tok,
+        ident_tok,
+        args_tok,
+        Group::new(Delimiter::Brace, new_body.collect()).into(),
+    ].into_iter().collect::<TokenStream>();
+    println!("{}", tokens);
+    return tokens
+}
diff --git a/src/test/ui/proc-macro/auxiliary/attribute-with-error.rs b/src/test/ui/proc-macro/auxiliary/attribute-with-error.rs
new file mode 100644
index 0000000..c073be0
--- /dev/null
+++ b/src/test/ui/proc-macro/auxiliary/attribute-with-error.rs
@@ -0,0 +1,13 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_attribute]
+pub fn foo(_attr: TokenStream, input: TokenStream) -> TokenStream {
+    input.into_iter().collect()
+}
diff --git a/src/test/ui/proc-macro/auxiliary/attributes-included.rs b/src/test/ui/proc-macro/auxiliary/attributes-included.rs
new file mode 100644
index 0000000..a5eb40b
--- /dev/null
+++ b/src/test/ui/proc-macro/auxiliary/attributes-included.rs
@@ -0,0 +1,150 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::{TokenStream, TokenTree, Delimiter, Literal, Spacing, Group};
+
+#[proc_macro_attribute]
+pub fn foo(attr: TokenStream, input: TokenStream) -> TokenStream {
+    assert!(attr.is_empty());
+    let input = input.into_iter().collect::<Vec<_>>();
+    {
+        let mut cursor = &input[..];
+        assert_inline(&mut cursor);
+        assert_doc(&mut cursor);
+        assert_inline(&mut cursor);
+        assert_doc(&mut cursor);
+        assert_foo(&mut cursor);
+        assert!(cursor.is_empty());
+    }
+    fold_stream(input.into_iter().collect())
+}
+
+#[proc_macro_attribute]
+pub fn bar(attr: TokenStream, input: TokenStream) -> TokenStream {
+    assert!(attr.is_empty());
+    let input = input.into_iter().collect::<Vec<_>>();
+    {
+        let mut cursor = &input[..];
+        assert_inline(&mut cursor);
+        assert_doc(&mut cursor);
+        assert_invoc(&mut cursor);
+        assert_inline(&mut cursor);
+        assert_doc(&mut cursor);
+        assert_foo(&mut cursor);
+        assert!(cursor.is_empty());
+    }
+    input.into_iter().collect()
+}
+
+fn assert_inline(slice: &mut &[TokenTree]) {
+    match &slice[0] {
+        TokenTree::Punct(tt) => assert_eq!(tt.as_char(), '#'),
+        _ => panic!("expected '#' char"),
+    }
+    match &slice[1] {
+        TokenTree::Group(tt) => assert_eq!(tt.delimiter(), Delimiter::Bracket),
+        _ => panic!("expected brackets"),
+    }
+    *slice = &slice[2..];
+}
+
+fn assert_doc(slice: &mut &[TokenTree]) {
+    match &slice[0] {
+        TokenTree::Punct(tt) => {
+            assert_eq!(tt.as_char(), '#');
+            assert_eq!(tt.spacing(), Spacing::Alone);
+        }
+        _ => panic!("expected #"),
+    }
+    let inner = match &slice[1] {
+        TokenTree::Group(tt) => {
+            assert_eq!(tt.delimiter(), Delimiter::Bracket);
+            tt.stream()
+        }
+        _ => panic!("expected brackets"),
+    };
+    let tokens = inner.into_iter().collect::<Vec<_>>();
+    let tokens = &tokens[..];
+
+    if tokens.len() != 3 {
+        panic!("expected three tokens in doc")
+    }
+
+    match &tokens[0] {
+        TokenTree::Ident(tt) => assert_eq!("doc", &*tt.to_string()),
+        _ => panic!("expected `doc`"),
+    }
+    match &tokens[1] {
+        TokenTree::Punct(tt) => {
+            assert_eq!(tt.as_char(), '=');
+            assert_eq!(tt.spacing(), Spacing::Alone);
+        }
+        _ => panic!("expected equals"),
+    }
+    match tokens[2] {
+        TokenTree::Literal(_) => {}
+        _ => panic!("expected literal"),
+    }
+
+    *slice = &slice[2..];
+}
+
+fn assert_invoc(slice: &mut &[TokenTree]) {
+    match &slice[0] {
+        TokenTree::Punct(tt) => assert_eq!(tt.as_char(), '#'),
+        _ => panic!("expected '#' char"),
+    }
+    match &slice[1] {
+        TokenTree::Group(tt) => assert_eq!(tt.delimiter(), Delimiter::Bracket),
+        _ => panic!("expected brackets"),
+    }
+    *slice = &slice[2..];
+}
+
+fn assert_foo(slice: &mut &[TokenTree]) {
+    match &slice[0] {
+        TokenTree::Ident(tt) => assert_eq!(&*tt.to_string(), "fn"),
+        _ => panic!("expected fn"),
+    }
+    match &slice[1] {
+        TokenTree::Ident(tt) => assert_eq!(&*tt.to_string(), "foo"),
+        _ => panic!("expected foo"),
+    }
+    match &slice[2] {
+        TokenTree::Group(tt) => {
+            assert_eq!(tt.delimiter(), Delimiter::Parenthesis);
+            assert!(tt.stream().is_empty());
+        }
+        _ => panic!("expected parens"),
+    }
+    match &slice[3] {
+        TokenTree::Group(tt) => assert_eq!(tt.delimiter(), Delimiter::Brace),
+        _ => panic!("expected braces"),
+    }
+    *slice = &slice[4..];
+}
+
+fn fold_stream(input: TokenStream) -> TokenStream {
+    input.into_iter().map(fold_tree).collect()
+}
+
+fn fold_tree(input: TokenTree) -> TokenTree {
+    match input {
+        TokenTree::Group(b) => {
+            TokenTree::Group(Group::new(b.delimiter(), fold_stream(b.stream())))
+        }
+        TokenTree::Punct(b) => TokenTree::Punct(b),
+        TokenTree::Ident(a) => TokenTree::Ident(a),
+        TokenTree::Literal(a) => {
+            if a.to_string() != "\"foo\"" {
+                TokenTree::Literal(a)
+            } else {
+                TokenTree::Literal(Literal::i32_unsuffixed(3))
+            }
+        }
+    }
+}
diff --git a/src/test/ui/proc-macro/auxiliary/bang_proc_macro.rs b/src/test/ui/proc-macro/auxiliary/bang_proc_macro.rs
new file mode 100644
index 0000000..16f3b76
--- /dev/null
+++ b/src/test/ui/proc-macro/auxiliary/bang_proc_macro.rs
@@ -0,0 +1,13 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro]
+pub fn bang_proc_macro(input: TokenStream) -> TokenStream {
+    input
+}
diff --git a/src/test/ui/proc-macro/auxiliary/bang_proc_macro2.rs b/src/test/ui/proc-macro/auxiliary/bang_proc_macro2.rs
new file mode 100644
index 0000000..fcaaba6
--- /dev/null
+++ b/src/test/ui/proc-macro/auxiliary/bang_proc_macro2.rs
@@ -0,0 +1,13 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro]
+pub fn bang_proc_macro2(_: TokenStream) -> TokenStream {
+    "let x = foobar2;".parse().unwrap()
+}
diff --git a/src/test/ui/proc-macro/auxiliary/builtin-attrs.rs b/src/test/ui/proc-macro/auxiliary/builtin-attrs.rs
new file mode 100644
index 0000000..6edafae
--- /dev/null
+++ b/src/test/ui/proc-macro/auxiliary/builtin-attrs.rs
@@ -0,0 +1,27 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::*;
+
+#[proc_macro_attribute]
+pub fn feature(_: TokenStream, input: TokenStream) -> TokenStream {
+    input
+}
+
+#[proc_macro_attribute]
+pub fn repr(_: TokenStream, input: TokenStream) -> TokenStream {
+    input
+}
+
+#[proc_macro_attribute]
+pub fn test(_: TokenStream, input: TokenStream) -> TokenStream {
+    "struct Test;".parse().unwrap()
+}
+
+#[proc_macro_attribute]
+pub fn bench(_: TokenStream, input: TokenStream) -> TokenStream {
+    "struct Bench;".parse().unwrap()
+}
diff --git a/src/test/ui/proc-macro/auxiliary/derive-a-b.rs b/src/test/ui/proc-macro/auxiliary/derive-a-b.rs
new file mode 100644
index 0000000..64d4e0f
--- /dev/null
+++ b/src/test/ui/proc-macro/auxiliary/derive-a-b.rs
@@ -0,0 +1,17 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(A)]
+pub fn derive_a(_: TokenStream) -> TokenStream {
+    "".parse().unwrap()
+}
+
+#[proc_macro_derive(B)]
+pub fn derive_b(_: TokenStream) -> TokenStream {
+    "".parse().unwrap()
+}
diff --git a/src/test/ui/proc-macro/auxiliary/derive-a.rs b/src/test/ui/proc-macro/auxiliary/derive-a.rs
new file mode 100644
index 0000000..c9d94ab
--- /dev/null
+++ b/src/test/ui/proc-macro/auxiliary/derive-a.rs
@@ -0,0 +1,13 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(A)]
+pub fn derive_a(input: TokenStream) -> TokenStream {
+    "".parse().unwrap()
+}
diff --git a/src/test/ui/proc-macro/auxiliary/derive-b.rs b/src/test/ui/proc-macro/auxiliary/derive-b.rs
new file mode 100644
index 0000000..e7ab6c0
--- /dev/null
+++ b/src/test/ui/proc-macro/auxiliary/derive-b.rs
@@ -0,0 +1,13 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(B, attributes(B))]
+pub fn derive_b(input: TokenStream) -> TokenStream {
+    "".parse().unwrap()
+}
diff --git a/src/test/ui/proc-macro/auxiliary/derive-bad.rs b/src/test/ui/proc-macro/auxiliary/derive-bad.rs
new file mode 100644
index 0000000..4684109
--- /dev/null
+++ b/src/test/ui/proc-macro/auxiliary/derive-bad.rs
@@ -0,0 +1,14 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(A)]
+pub fn derive_a(_input: TokenStream) -> TokenStream {
+    "struct A { inner }".parse().unwrap()
+}
+
diff --git a/src/test/ui/proc-macro/auxiliary/derive-clona.rs b/src/test/ui/proc-macro/auxiliary/derive-clona.rs
new file mode 100644
index 0000000..4a35c9d
--- /dev/null
+++ b/src/test/ui/proc-macro/auxiliary/derive-clona.rs
@@ -0,0 +1,13 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(Clona)]
+pub fn derive_clonea(input: TokenStream) -> TokenStream {
+    "".parse().unwrap()
+}
diff --git a/src/test/ui/proc-macro/auxiliary/derive-foo.rs b/src/test/ui/proc-macro/auxiliary/derive-foo.rs
new file mode 100644
index 0000000..3ea027d
--- /dev/null
+++ b/src/test/ui/proc-macro/auxiliary/derive-foo.rs
@@ -0,0 +1,13 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(FooWithLongName)]
+pub fn derive_foo(input: TokenStream) -> TokenStream {
+    "".parse().unwrap()
+}
diff --git a/src/test/ui/proc-macro/auxiliary/derive-helper-shadowed-2.rs b/src/test/ui/proc-macro/auxiliary/derive-helper-shadowed-2.rs
new file mode 100644
index 0000000..9912a89
--- /dev/null
+++ b/src/test/ui/proc-macro/auxiliary/derive-helper-shadowed-2.rs
@@ -0,0 +1,2 @@
+#[macro_export]
+macro_rules! my_attr { () => () }
diff --git a/src/test/ui/proc-macro/auxiliary/derive-helper-shadowed.rs b/src/test/ui/proc-macro/auxiliary/derive-helper-shadowed.rs
new file mode 100644
index 0000000..5b5243d
--- /dev/null
+++ b/src/test/ui/proc-macro/auxiliary/derive-helper-shadowed.rs
@@ -0,0 +1,12 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::*;
+
+#[proc_macro_derive(MyTrait, attributes(my_attr))]
+pub fn foo(_: TokenStream) -> TokenStream {
+    TokenStream::new()
+}
diff --git a/src/test/ui/proc-macro/auxiliary/derive-helper-shadowing.rs b/src/test/ui/proc-macro/auxiliary/derive-helper-shadowing.rs
new file mode 100644
index 0000000..6e0bdcb
--- /dev/null
+++ b/src/test/ui/proc-macro/auxiliary/derive-helper-shadowing.rs
@@ -0,0 +1,17 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::*;
+
+#[proc_macro_attribute]
+pub fn my_attr(_: TokenStream, input: TokenStream) -> TokenStream {
+    input
+}
+
+#[proc_macro_derive(MyTrait, attributes(my_attr))]
+pub fn derive(input: TokenStream) -> TokenStream {
+    TokenStream::new()
+}
diff --git a/src/test/ui/proc-macro/auxiliary/derive-panic.rs b/src/test/ui/proc-macro/auxiliary/derive-panic.rs
new file mode 100644
index 0000000..e2afa7a
--- /dev/null
+++ b/src/test/ui/proc-macro/auxiliary/derive-panic.rs
@@ -0,0 +1,13 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(A)]
+pub fn derive_a(_input: TokenStream) -> TokenStream {
+    panic!("nope!");
+}
diff --git a/src/test/ui/proc-macro/auxiliary/derive-unstable-2.rs b/src/test/ui/proc-macro/auxiliary/derive-unstable-2.rs
new file mode 100644
index 0000000..eac21b0
--- /dev/null
+++ b/src/test/ui/proc-macro/auxiliary/derive-unstable-2.rs
@@ -0,0 +1,17 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(Unstable)]
+pub fn derive(_input: TokenStream) -> TokenStream {
+
+    "
+        #[rustc_foo]
+        fn foo() {}
+    ".parse().unwrap()
+}
diff --git a/src/test/ui/proc-macro/auxiliary/derive-unstable.rs b/src/test/ui/proc-macro/auxiliary/derive-unstable.rs
new file mode 100644
index 0000000..f702df6
--- /dev/null
+++ b/src/test/ui/proc-macro/auxiliary/derive-unstable.rs
@@ -0,0 +1,14 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(Unstable)]
+pub fn derive(_input: TokenStream) -> TokenStream {
+
+    "unsafe fn foo() -> u32 { ::std::intrinsics::init() }".parse().unwrap()
+}
diff --git a/src/test/ui/proc-macro/auxiliary/dollar-crate-external.rs b/src/test/ui/proc-macro/auxiliary/dollar-crate-external.rs
new file mode 100644
index 0000000..8f15a2b
--- /dev/null
+++ b/src/test/ui/proc-macro/auxiliary/dollar-crate-external.rs
@@ -0,0 +1,16 @@
+pub type S = u8;
+
+#[macro_export]
+macro_rules! external {
+    () => {
+        dollar_crate::m! {
+            struct M($crate::S);
+        }
+
+        #[dollar_crate::a]
+        struct A($crate::S);
+
+        #[derive(dollar_crate::d)]
+        struct D($crate::S);
+    };
+}
diff --git a/src/test/ui/proc-macro/auxiliary/dollar-crate.rs b/src/test/ui/proc-macro/auxiliary/dollar-crate.rs
new file mode 100644
index 0000000..c5347d2
--- /dev/null
+++ b/src/test/ui/proc-macro/auxiliary/dollar-crate.rs
@@ -0,0 +1,35 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::TokenStream;
+
+#[proc_macro]
+pub fn m_empty(input: TokenStream) -> TokenStream {
+    println!("PROC MACRO INPUT (PRETTY-PRINTED): {}", input);
+    println!("PROC MACRO INPUT: {:#?}", input);
+    TokenStream::new()
+}
+
+#[proc_macro]
+pub fn m(input: TokenStream) -> TokenStream {
+    println!("PROC MACRO INPUT (PRETTY-PRINTED): {}", input);
+    println!("PROC MACRO INPUT: {:#?}", input);
+    input.into_iter().collect()
+}
+
+#[proc_macro_attribute]
+pub fn a(_args: TokenStream, input: TokenStream) -> TokenStream {
+    println!("ATTRIBUTE INPUT (PRETTY-PRINTED): {}", input);
+    println!("ATTRIBUTE INPUT: {:#?}", input);
+    input.into_iter().collect()
+}
+
+#[proc_macro_derive(d)]
+pub fn d(input: TokenStream) -> TokenStream {
+    println!("DERIVE INPUT (PRETTY-PRINTED): {}", input);
+    println!("DERIVE INPUT: {:#?}", input);
+    input.into_iter().collect()
+}
diff --git a/src/test/ui/proc-macro/auxiliary/edition-imports-2015.rs b/src/test/ui/proc-macro/auxiliary/edition-imports-2015.rs
new file mode 100644
index 0000000..27c59b8
--- /dev/null
+++ b/src/test/ui/proc-macro/auxiliary/edition-imports-2015.rs
@@ -0,0 +1,20 @@
+// edition:2015
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(Derive2015)]
+pub fn derive_2015(_: TokenStream) -> TokenStream {
+    "
+    use import::Path;
+
+    fn check_absolute() {
+        let x = ::absolute::Path;
+    }
+    ".parse().unwrap()
+}
diff --git a/src/test/ui/proc-macro/auxiliary/generate-mod.rs b/src/test/ui/proc-macro/auxiliary/generate-mod.rs
new file mode 100644
index 0000000..8b41e8b
--- /dev/null
+++ b/src/test/ui/proc-macro/auxiliary/generate-mod.rs
@@ -0,0 +1,57 @@
+// run-pass
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::*;
+
+#[proc_macro]
+pub fn check(_: TokenStream) -> TokenStream {
+    "
+    type Alias = FromOutside; // OK
+    struct Outer;
+    mod inner {
+        type Alias = FromOutside; // `FromOutside` shouldn't be available from here
+        type Inner = Outer; // `Outer` shouldn't be available from here
+    }
+    ".parse().unwrap()
+}
+
+#[proc_macro_attribute]
+pub fn check_attr(_: TokenStream, _: TokenStream) -> TokenStream {
+    "
+    type AliasAttr = FromOutside; // OK
+    struct OuterAttr;
+    mod inner_attr {
+        type Alias = FromOutside; // `FromOutside` shouldn't be available from here
+        type Inner = OuterAttr; // `OuterAttr` shouldn't be available from here
+    }
+    ".parse().unwrap()
+}
+
+#[proc_macro_derive(CheckDerive)]
+pub fn check_derive(_: TokenStream) -> TokenStream {
+    "
+    type AliasDerive = FromOutside; // OK
+    struct OuterDerive;
+    mod inner_derive {
+        type Alias = FromOutside; // `FromOutside` shouldn't be available from here
+        type Inner = OuterDerive; // `OuterDerive` shouldn't be available from here
+    }
+    ".parse().unwrap()
+}
+
+#[proc_macro_derive(CheckDeriveLint)]
+pub fn check_derive_lint(_: TokenStream) -> TokenStream {
+    "
+    type AliasDeriveLint = FromOutside; // OK
+    struct OuterDeriveLint;
+    #[allow(proc_macro_derive_resolution_fallback)]
+    mod inner_derive_lint {
+        type Alias = FromOutside; // `FromOutside` shouldn't be available from here
+        type Inner = OuterDeriveLint; // `OuterDeriveLint` shouldn't be available from here
+    }
+    ".parse().unwrap()
+}
diff --git a/src/test/ui/proc-macro/auxiliary/invalid-punct-ident.rs b/src/test/ui/proc-macro/auxiliary/invalid-punct-ident.rs
new file mode 100644
index 0000000..518dfd0
--- /dev/null
+++ b/src/test/ui/proc-macro/auxiliary/invalid-punct-ident.rs
@@ -0,0 +1,28 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+#![feature(proc_macro_raw_ident)]
+
+extern crate proc_macro;
+use proc_macro::*;
+
+#[proc_macro]
+pub fn invalid_punct(_: TokenStream) -> TokenStream {
+    TokenTree::from(Punct::new('`', Spacing::Alone)).into()
+}
+
+#[proc_macro]
+pub fn invalid_ident(_: TokenStream) -> TokenStream {
+    TokenTree::from(Ident::new("*", Span::call_site())).into()
+}
+
+#[proc_macro]
+pub fn invalid_raw_ident(_: TokenStream) -> TokenStream {
+    TokenTree::from(Ident::new_raw("self", Span::call_site())).into()
+}
+
+#[proc_macro]
+pub fn lexer_failure(_: TokenStream) -> TokenStream {
+    "a b ) c".parse().expect("parsing failed without panic")
+}
diff --git a/src/test/ui/proc-macro/auxiliary/issue-38586.rs b/src/test/ui/proc-macro/auxiliary/issue-38586.rs
new file mode 100644
index 0000000..f3a1908
--- /dev/null
+++ b/src/test/ui/proc-macro/auxiliary/issue-38586.rs
@@ -0,0 +1,11 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+#[proc_macro_derive(A)]
+pub fn derive_a(_: proc_macro::TokenStream) -> proc_macro::TokenStream {
+    "fn f() { println!(\"{}\", foo); }".parse().unwrap()
+}
diff --git a/src/test/ui/proc-macro/auxiliary/issue-41211.rs b/src/test/ui/proc-macro/auxiliary/issue-41211.rs
new file mode 100644
index 0000000..db946e7
--- /dev/null
+++ b/src/test/ui/proc-macro/auxiliary/issue-41211.rs
@@ -0,0 +1,12 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::TokenStream;
+
+#[proc_macro_attribute]
+pub fn emit_unchanged(_args: TokenStream, input: TokenStream) -> TokenStream {
+    input
+}
diff --git a/src/test/ui/proc-macro/auxiliary/issue-50493.rs b/src/test/ui/proc-macro/auxiliary/issue-50493.rs
new file mode 100644
index 0000000..f720249
--- /dev/null
+++ b/src/test/ui/proc-macro/auxiliary/issue-50493.rs
@@ -0,0 +1,21 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(Derive)]
+pub fn derive(_: TokenStream) -> TokenStream {
+    let code = "
+        fn one(r: Restricted) {
+            r.field;
+        }
+        fn two(r: Restricted) {
+            r.field;
+        }
+    ";
+
+    code.parse().unwrap()
+}
diff --git a/src/test/ui/proc-macro/auxiliary/issue-53481.rs b/src/test/ui/proc-macro/auxiliary/issue-53481.rs
new file mode 100644
index 0000000..d9f290d
--- /dev/null
+++ b/src/test/ui/proc-macro/auxiliary/issue-53481.rs
@@ -0,0 +1,13 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::*;
+
+#[proc_macro_derive(MyTrait, attributes(my_attr))]
+pub fn foo(_: TokenStream) -> TokenStream {
+    TokenStream::new()
+}
diff --git a/src/test/ui/proc-macro/auxiliary/lifetimes.rs b/src/test/ui/proc-macro/auxiliary/lifetimes.rs
new file mode 100644
index 0000000..212164d
--- /dev/null
+++ b/src/test/ui/proc-macro/auxiliary/lifetimes.rs
@@ -0,0 +1,20 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::*;
+
+#[proc_macro]
+pub fn single_quote_alone(_: TokenStream) -> TokenStream {
+    // `&'a u8`, but the `'` token is not joint
+    let trees: Vec<TokenTree> = vec![
+        Punct::new('&', Spacing::Alone).into(),
+        Punct::new('\'', Spacing::Alone).into(),
+        Ident::new("a", Span::call_site()).into(),
+        Ident::new("u8", Span::call_site()).into(),
+    ];
+    trees.into_iter().collect()
+}
diff --git a/src/test/ui/proc-macro/auxiliary/macro-brackets.rs b/src/test/ui/proc-macro/auxiliary/macro-brackets.rs
new file mode 100644
index 0000000..f2c62ab
--- /dev/null
+++ b/src/test/ui/proc-macro/auxiliary/macro-brackets.rs
@@ -0,0 +1,12 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::*;
+
+#[proc_macro_attribute]
+pub fn doit(_: TokenStream, input: TokenStream) -> TokenStream {
+    input.into_iter().collect()
+}
diff --git a/src/test/ui/proc-macro/auxiliary/more-gates.rs b/src/test/ui/proc-macro/auxiliary/more-gates.rs
new file mode 100644
index 0000000..6b609ea
--- /dev/null
+++ b/src/test/ui/proc-macro/auxiliary/more-gates.rs
@@ -0,0 +1,35 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::*;
+
+#[proc_macro_attribute]
+pub fn attr2mac1(_: TokenStream, _: TokenStream) -> TokenStream {
+    "macro_rules! foo1 { (a) => (a) }".parse().unwrap()
+}
+
+#[proc_macro_attribute]
+pub fn attr2mac2(_: TokenStream, _: TokenStream) -> TokenStream {
+    "macro foo2(a) { a }".parse().unwrap()
+}
+
+#[proc_macro]
+pub fn mac2mac1(_: TokenStream) -> TokenStream {
+    "macro_rules! foo3 { (a) => (a) }".parse().unwrap()
+}
+
+#[proc_macro]
+pub fn mac2mac2(_: TokenStream) -> TokenStream {
+    "macro foo4(a) { a }".parse().unwrap()
+}
+
+#[proc_macro]
+pub fn tricky(_: TokenStream) -> TokenStream {
+    "fn foo() {
+        macro_rules! foo { (a) => (a) }
+    }".parse().unwrap()
+}
diff --git a/src/test/ui/proc-macro/auxiliary/multispan.rs b/src/test/ui/proc-macro/auxiliary/multispan.rs
new file mode 100644
index 0000000..c05d156
--- /dev/null
+++ b/src/test/ui/proc-macro/auxiliary/multispan.rs
@@ -0,0 +1,37 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+#![feature(proc_macro_diagnostic, proc_macro_span, proc_macro_def_site)]
+
+extern crate proc_macro;
+
+use proc_macro::{TokenStream, TokenTree, Span, Diagnostic};
+
+fn parse(input: TokenStream) -> Result<(), Diagnostic> {
+    let mut hi_spans = vec![];
+    for tree in input {
+        if let TokenTree::Ident(ref ident) = tree {
+            if ident.to_string() == "hi" {
+                hi_spans.push(ident.span());
+            }
+        }
+    }
+
+    if !hi_spans.is_empty() {
+        return Err(Span::def_site()
+                       .error("hello to you, too!")
+                       .span_note(hi_spans, "found these 'hi's"));
+    }
+
+    Ok(())
+}
+
+#[proc_macro]
+pub fn hello(input: TokenStream) -> TokenStream {
+    if let Err(diag) = parse(input) {
+        diag.emit();
+    }
+
+    TokenStream::new()
+}
diff --git a/src/test/ui/proc-macro/auxiliary/nested-item-spans.rs b/src/test/ui/proc-macro/auxiliary/nested-item-spans.rs
new file mode 100644
index 0000000..8f720b4
--- /dev/null
+++ b/src/test/ui/proc-macro/auxiliary/nested-item-spans.rs
@@ -0,0 +1,13 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::*;
+
+#[proc_macro_attribute]
+pub fn foo(_: TokenStream, item: TokenStream) -> TokenStream {
+    item.into_iter().collect()
+}
diff --git a/src/test/ui/proc-macro/auxiliary/parent-source-spans.rs b/src/test/ui/proc-macro/auxiliary/parent-source-spans.rs
new file mode 100644
index 0000000..594f108
--- /dev/null
+++ b/src/test/ui/proc-macro/auxiliary/parent-source-spans.rs
@@ -0,0 +1,43 @@
+// force-host
+// no-prefer-dynamic
+
+#![feature(proc_macro_diagnostic, proc_macro_span)]
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::{TokenStream, TokenTree, Span};
+
+fn lit_span(tt: TokenTree) -> (Span, String) {
+    match tt {
+        TokenTree::Literal(..) |
+        TokenTree::Group(..) => (tt.span(), tt.to_string().trim().into()),
+        _ => panic!("expected a literal in token tree, got: {:?}", tt)
+    }
+}
+
+#[proc_macro]
+pub fn parent_source_spans(input: TokenStream) -> TokenStream {
+    let mut tokens = input.into_iter();
+    let (sp1, str1) = lit_span(tokens.next().expect("first string"));
+    let _ = tokens.next();
+    let (sp2, str2) = lit_span(tokens.next().expect("second string"));
+
+    sp1.error(format!("first final: {}", str1)).emit();
+    sp2.error(format!("second final: {}", str2)).emit();
+
+    if let (Some(p1), Some(p2)) = (sp1.parent(), sp2.parent()) {
+        p1.error(format!("first parent: {}", str1)).emit();
+        p2.error(format!("second parent: {}", str2)).emit();
+
+        if let (Some(gp1), Some(gp2)) = (p1.parent(), p2.parent()) {
+            gp1.error(format!("first grandparent: {}", str1)).emit();
+            gp2.error(format!("second grandparent: {}", str2)).emit();
+        }
+    }
+
+    sp1.source().error(format!("first source: {}", str1)).emit();
+    sp2.source().error(format!("second source: {}", str2)).emit();
+
+    "ok".parse().unwrap()
+}
diff --git a/src/test/ui/proc-macro/auxiliary/proc-macro-gates.rs b/src/test/ui/proc-macro/auxiliary/proc-macro-gates.rs
new file mode 100644
index 0000000..c7c7167
--- /dev/null
+++ b/src/test/ui/proc-macro/auxiliary/proc-macro-gates.rs
@@ -0,0 +1,18 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::*;
+
+#[proc_macro]
+pub fn m(a: TokenStream) -> TokenStream {
+    a
+}
+
+#[proc_macro_attribute]
+pub fn a(_a: TokenStream, b: TokenStream) -> TokenStream {
+    b
+}
diff --git a/src/test/ui/proc-macro/auxiliary/span-preservation.rs b/src/test/ui/proc-macro/auxiliary/span-preservation.rs
new file mode 100644
index 0000000..33c7968
--- /dev/null
+++ b/src/test/ui/proc-macro/auxiliary/span-preservation.rs
@@ -0,0 +1,13 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_attribute]
+pub fn foo(_: TokenStream, input: TokenStream) -> TokenStream {
+    input.into_iter().collect()
+}
diff --git a/src/test/ui/proc-macro/auxiliary/subspan.rs b/src/test/ui/proc-macro/auxiliary/subspan.rs
new file mode 100644
index 0000000..f92adc0
--- /dev/null
+++ b/src/test/ui/proc-macro/auxiliary/subspan.rs
@@ -0,0 +1,38 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+#![feature(proc_macro_diagnostic, proc_macro_span)]
+
+extern crate proc_macro;
+
+use proc_macro::{TokenStream, TokenTree, Span, Diagnostic};
+
+fn parse(input: TokenStream) -> Result<(), Diagnostic> {
+    if let Some(TokenTree::Literal(lit)) = input.into_iter().next() {
+        let mut spans = vec![];
+        let string = lit.to_string();
+        for hi in string.matches("hi") {
+            let index = hi.as_ptr() as usize - string.as_ptr() as usize;
+            let subspan = lit.subspan(index..(index + hi.len())).unwrap();
+            spans.push(subspan);
+        }
+
+        if !spans.is_empty() {
+            Err(Span::call_site().error("found 'hi's").span_note(spans, "here"))
+        } else {
+            Ok(())
+        }
+    } else {
+        Err(Span::call_site().error("invalid input: expected string literal"))
+    }
+}
+
+#[proc_macro]
+pub fn subspan(input: TokenStream) -> TokenStream {
+    if let Err(diag) = parse(input) {
+        diag.emit();
+    }
+
+    TokenStream::new()
+}
diff --git a/src/test/ui/proc-macro/auxiliary/test-macros.rs b/src/test/ui/proc-macro/auxiliary/test-macros.rs
new file mode 100644
index 0000000..15fe380
--- /dev/null
+++ b/src/test/ui/proc-macro/auxiliary/test-macros.rs
@@ -0,0 +1,26 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_attribute]
+pub fn nop_attr(_attr: TokenStream, input: TokenStream) -> TokenStream {
+    assert!(_attr.to_string().is_empty());
+    input
+}
+
+#[proc_macro_attribute]
+pub fn no_output(_attr: TokenStream, _input: TokenStream) -> TokenStream {
+    assert!(_attr.to_string().is_empty());
+    assert!(!_input.to_string().is_empty());
+    "".parse().unwrap()
+}
+
+#[proc_macro]
+pub fn emit_input(input: TokenStream) -> TokenStream {
+    input
+}
diff --git a/src/test/ui/proc-macro/auxiliary/three-equals.rs b/src/test/ui/proc-macro/auxiliary/three-equals.rs
new file mode 100644
index 0000000..e740e86
--- /dev/null
+++ b/src/test/ui/proc-macro/auxiliary/three-equals.rs
@@ -0,0 +1,49 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+#![feature(proc_macro_diagnostic, proc_macro_span, proc_macro_def_site)]
+
+extern crate proc_macro;
+
+use proc_macro::{TokenStream, TokenTree, Span, Diagnostic};
+
+fn parse(input: TokenStream) -> Result<(), Diagnostic> {
+    let mut count = 0;
+    let mut last_span = Span::def_site();
+    for tree in input {
+        let span = tree.span();
+        if count >= 3 {
+            return Err(span.error(format!("expected EOF, found `{}`.", tree))
+                           .span_note(last_span, "last good input was here")
+                           .help("input must be: `===`"))
+        }
+
+        if let TokenTree::Punct(ref tt) = tree {
+            if tt.as_char() == '=' {
+                count += 1;
+                last_span = span;
+                continue
+            }
+        }
+        return Err(span.error(format!("expected `=`, found `{}`.", tree)));
+    }
+
+    if count < 3 {
+        return Err(Span::def_site()
+                       .error(format!("found {} equal signs, need exactly 3", count))
+                       .help("input must be: `===`"))
+    }
+
+    Ok(())
+}
+
+#[proc_macro]
+pub fn three_equals(input: TokenStream) -> TokenStream {
+    if let Err(diag) = parse(input) {
+        diag.emit();
+        return TokenStream::new();
+    }
+
+    "3".parse().unwrap()
+}
diff --git a/src/test/ui/proc-macro/define-two.rs b/src/test/ui/proc-macro/define-two.rs
new file mode 100644
index 0000000..b2184ea
--- /dev/null
+++ b/src/test/ui/proc-macro/define-two.rs
@@ -0,0 +1,18 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(A)]
+pub fn foo(input: TokenStream) -> TokenStream {
+    input
+}
+
+#[proc_macro_derive(A)] //~ ERROR the name `A` is defined multiple times
+pub fn bar(input: TokenStream) -> TokenStream {
+    input
+}
diff --git a/src/test/ui/proc-macro/define-two.stderr b/src/test/ui/proc-macro/define-two.stderr
new file mode 100644
index 0000000..bf1bd84
--- /dev/null
+++ b/src/test/ui/proc-macro/define-two.stderr
@@ -0,0 +1,14 @@
+error[E0428]: the name `A` is defined multiple times
+  --> $DIR/define-two.rs:15:21
+   |
+LL | #[proc_macro_derive(A)]
+   |                     - previous definition of the macro `A` here
+...
+LL | #[proc_macro_derive(A)]
+   |                     ^ `A` redefined here
+   |
+   = note: `A` must be defined only once in the macro namespace of this module
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0428`.
diff --git a/src/test/ui/proc-macro/derive-bad.rs b/src/test/ui/proc-macro/derive-bad.rs
new file mode 100644
index 0000000..62c0741
--- /dev/null
+++ b/src/test/ui/proc-macro/derive-bad.rs
@@ -0,0 +1,13 @@
+// aux-build:derive-bad.rs
+
+#[macro_use]
+extern crate derive_bad;
+
+#[derive(
+    A
+)]
+//~^^ ERROR proc-macro derive produced unparseable tokens
+//~| ERROR expected `:`, found `}`
+struct A;
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/derive-bad.stderr b/src/test/ui/proc-macro/derive-bad.stderr
new file mode 100644
index 0000000..9390815
--- /dev/null
+++ b/src/test/ui/proc-macro/derive-bad.stderr
@@ -0,0 +1,14 @@
+error: expected `:`, found `}`
+  --> $DIR/derive-bad.rs:7:5
+   |
+LL |     A
+   |     ^ expected `:`
+
+error: proc-macro derive produced unparseable tokens
+  --> $DIR/derive-bad.rs:7:5
+   |
+LL |     A
+   |     ^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/proc-macro/derive-helper-shadowed.rs b/src/test/ui/proc-macro/derive-helper-shadowed.rs
new file mode 100644
index 0000000..792b54b
--- /dev/null
+++ b/src/test/ui/proc-macro/derive-helper-shadowed.rs
@@ -0,0 +1,16 @@
+// compile-pass
+// aux-build:derive-helper-shadowed.rs
+// aux-build:derive-helper-shadowed-2.rs
+
+#[macro_use]
+extern crate derive_helper_shadowed;
+#[macro_use(my_attr)]
+extern crate derive_helper_shadowed_2;
+
+macro_rules! my_attr { () => () }
+
+#[derive(MyTrait)]
+#[my_attr] // OK
+struct S;
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/derive-helper-shadowing.rs b/src/test/ui/proc-macro/derive-helper-shadowing.rs
new file mode 100644
index 0000000..f6fe9f9
--- /dev/null
+++ b/src/test/ui/proc-macro/derive-helper-shadowing.rs
@@ -0,0 +1,30 @@
+// aux-build:derive-helper-shadowing.rs
+
+extern crate derive_helper_shadowing;
+use derive_helper_shadowing::*;
+
+#[my_attr] //~ ERROR `my_attr` is ambiguous
+#[derive(MyTrait)]
+struct S {
+    // FIXME No ambiguity, attributes in non-macro positions are not resolved properly
+    #[my_attr]
+    field: [u8; {
+        // FIXME No ambiguity, derive helpers are not put into scope for non-attributes
+        use my_attr;
+
+        // FIXME No ambiguity, derive helpers are not put into scope for inner items
+        #[my_attr]
+        struct U;
+
+        mod inner {
+            #[my_attr] //~ ERROR attribute `my_attr` is currently unknown
+            struct V;
+        }
+
+        0
+    }]
+}
+
+fn main() {
+    let s = S { field: [] };
+}
diff --git a/src/test/ui/proc-macro/derive-helper-shadowing.stderr b/src/test/ui/proc-macro/derive-helper-shadowing.stderr
new file mode 100644
index 0000000..5f2009b
--- /dev/null
+++ b/src/test/ui/proc-macro/derive-helper-shadowing.stderr
@@ -0,0 +1,30 @@
+error[E0658]: The attribute `my_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/derive-helper-shadowing.rs:20:15
+   |
+LL |             #[my_attr]
+   |               ^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error[E0659]: `my_attr` is ambiguous (derive helper attribute vs any other name)
+  --> $DIR/derive-helper-shadowing.rs:6:3
+   |
+LL | #[my_attr]
+   |   ^^^^^^^ ambiguous name
+   |
+note: `my_attr` could refer to the derive helper attribute defined here
+  --> $DIR/derive-helper-shadowing.rs:7:10
+   |
+LL | #[derive(MyTrait)]
+   |          ^^^^^^^
+note: `my_attr` could also refer to the attribute macro imported here
+  --> $DIR/derive-helper-shadowing.rs:4:5
+   |
+LL | use derive_helper_shadowing::*;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: use `crate::my_attr` to refer to this attribute macro unambiguously
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0658, E0659.
+For more information about an error, try `rustc --explain E0658`.
diff --git a/src/test/ui/proc-macro/derive-still-gated.rs b/src/test/ui/proc-macro/derive-still-gated.rs
new file mode 100644
index 0000000..526eff3
--- /dev/null
+++ b/src/test/ui/proc-macro/derive-still-gated.rs
@@ -0,0 +1,11 @@
+// aux-build:derive-a.rs
+
+#![allow(warnings)]
+
+#[macro_use]
+extern crate derive_a;
+
+#[derive_A] //~ ERROR attribute `derive_A` is currently unknown
+struct A;
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/derive-still-gated.stderr b/src/test/ui/proc-macro/derive-still-gated.stderr
new file mode 100644
index 0000000..f7c8960
--- /dev/null
+++ b/src/test/ui/proc-macro/derive-still-gated.stderr
@@ -0,0 +1,11 @@
+error[E0658]: The attribute `derive_A` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/derive-still-gated.rs:8:3
+   |
+LL | #[derive_A]
+   |   ^^^^^^^^ help: a built-in attribute with a similar name exists: `derive`
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/proc-macro/dollar-crate-issue-57089.rs b/src/test/ui/proc-macro/dollar-crate-issue-57089.rs
new file mode 100644
index 0000000..2d54c07
--- /dev/null
+++ b/src/test/ui/proc-macro/dollar-crate-issue-57089.rs
@@ -0,0 +1,26 @@
+// compile-pass
+// edition:2018
+// aux-build:dollar-crate.rs
+
+// Anonymize unstable non-dummy spans while still showing dummy spans `0..0`.
+// normalize-stdout-test "bytes\([^0]\w*\.\.(\w+)\)" -> "bytes(LO..$1)"
+// normalize-stdout-test "bytes\((\w+)\.\.[^0]\w*\)" -> "bytes($1..HI)"
+
+extern crate dollar_crate;
+
+type S = u8;
+
+macro_rules! m {
+    () => {
+        dollar_crate::m_empty! {
+            struct M($crate::S);
+        }
+
+        #[dollar_crate::a]
+        struct A($crate::S);
+    };
+}
+
+m!();
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout b/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout
new file mode 100644
index 0000000..618380d
--- /dev/null
+++ b/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout
@@ -0,0 +1,80 @@
+PROC MACRO INPUT (PRETTY-PRINTED): struct M ( $crate :: S ) ;
+PROC MACRO INPUT: TokenStream [
+    Ident {
+        ident: "struct",
+        span: #2 bytes(LO..HI),
+    },
+    Ident {
+        ident: "M",
+        span: #2 bytes(LO..HI),
+    },
+    Group {
+        delimiter: Parenthesis,
+        stream: TokenStream [
+            Ident {
+                ident: "$crate",
+                span: #2 bytes(LO..HI),
+            },
+            Punct {
+                ch: ':',
+                spacing: Joint,
+                span: #2 bytes(LO..HI),
+            },
+            Punct {
+                ch: ':',
+                spacing: Alone,
+                span: #2 bytes(LO..HI),
+            },
+            Ident {
+                ident: "S",
+                span: #2 bytes(LO..HI),
+            },
+        ],
+        span: #2 bytes(LO..HI),
+    },
+    Punct {
+        ch: ';',
+        spacing: Alone,
+        span: #2 bytes(LO..HI),
+    },
+]
+ATTRIBUTE INPUT (PRETTY-PRINTED): struct A(crate::S);
+ATTRIBUTE INPUT: TokenStream [
+    Ident {
+        ident: "struct",
+        span: #2 bytes(LO..HI),
+    },
+    Ident {
+        ident: "A",
+        span: #2 bytes(LO..HI),
+    },
+    Group {
+        delimiter: Parenthesis,
+        stream: TokenStream [
+            Ident {
+                ident: "$crate",
+                span: #2 bytes(LO..HI),
+            },
+            Punct {
+                ch: ':',
+                spacing: Joint,
+                span: #2 bytes(LO..HI),
+            },
+            Punct {
+                ch: ':',
+                spacing: Alone,
+                span: #2 bytes(LO..HI),
+            },
+            Ident {
+                ident: "S",
+                span: #2 bytes(LO..HI),
+            },
+        ],
+        span: #2 bytes(LO..HI),
+    },
+    Punct {
+        ch: ';',
+        spacing: Alone,
+        span: #2 bytes(LO..HI),
+    },
+]
diff --git a/src/test/ui/proc-macro/dollar-crate.rs b/src/test/ui/proc-macro/dollar-crate.rs
new file mode 100644
index 0000000..1460e9a
--- /dev/null
+++ b/src/test/ui/proc-macro/dollar-crate.rs
@@ -0,0 +1,40 @@
+// edition:2018
+// aux-build:dollar-crate.rs
+// aux-build:dollar-crate-external.rs
+
+// Anonymize unstable non-dummy spans while still showing dummy spans `0..0`.
+// normalize-stdout-test "bytes\([^0]\w*\.\.(\w+)\)" -> "bytes(LO..$1)"
+// normalize-stdout-test "bytes\((\w+)\.\.[^0]\w*\)" -> "bytes($1..HI)"
+
+extern crate dollar_crate;
+extern crate dollar_crate_external;
+
+type S = u8;
+
+mod local {
+    use crate::dollar_crate;
+
+    macro_rules! local {
+        () => {
+            dollar_crate::m! {
+                struct M($crate::S);
+            }
+
+            #[dollar_crate::a]
+            struct A($crate::S);
+
+            #[derive(dollar_crate::d)]
+            struct D($crate::S); //~ ERROR the name `D` is defined multiple times
+        };
+    }
+
+    local!();
+}
+
+mod external {
+    use crate::dollar_crate_external;
+
+    dollar_crate_external::external!(); //~ ERROR the name `D` is defined multiple times
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/dollar-crate.stderr b/src/test/ui/proc-macro/dollar-crate.stderr
new file mode 100644
index 0000000..d1b836e
--- /dev/null
+++ b/src/test/ui/proc-macro/dollar-crate.stderr
@@ -0,0 +1,29 @@
+error[E0428]: the name `D` is defined multiple times
+  --> $DIR/dollar-crate.rs:27:13
+   |
+LL |             struct D($crate::S);
+   |             ^^^^^^^^^^^^^^^^^^^^
+   |             |
+   |             `D` redefined here
+   |             previous definition of the type `D` here
+...
+LL |     local!();
+   |     --------- in this macro invocation
+   |
+   = note: `D` must be defined only once in the type namespace of this module
+
+error[E0428]: the name `D` is defined multiple times
+  --> $DIR/dollar-crate.rs:37:5
+   |
+LL |     dollar_crate_external::external!();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     |
+   |     `D` redefined here
+   |     previous definition of the type `D` here
+   |
+   = note: `D` must be defined only once in the type namespace of this module
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0428`.
diff --git a/src/test/ui/proc-macro/dollar-crate.stdout b/src/test/ui/proc-macro/dollar-crate.stdout
new file mode 100644
index 0000000..454da53
--- /dev/null
+++ b/src/test/ui/proc-macro/dollar-crate.stdout
@@ -0,0 +1,240 @@
+PROC MACRO INPUT (PRETTY-PRINTED): struct M ( $crate :: S ) ;
+PROC MACRO INPUT: TokenStream [
+    Ident {
+        ident: "struct",
+        span: #2 bytes(LO..HI),
+    },
+    Ident {
+        ident: "M",
+        span: #2 bytes(LO..HI),
+    },
+    Group {
+        delimiter: Parenthesis,
+        stream: TokenStream [
+            Ident {
+                ident: "$crate",
+                span: #2 bytes(LO..HI),
+            },
+            Punct {
+                ch: ':',
+                spacing: Joint,
+                span: #2 bytes(LO..HI),
+            },
+            Punct {
+                ch: ':',
+                spacing: Alone,
+                span: #2 bytes(LO..HI),
+            },
+            Ident {
+                ident: "S",
+                span: #2 bytes(LO..HI),
+            },
+        ],
+        span: #2 bytes(LO..HI),
+    },
+    Punct {
+        ch: ';',
+        spacing: Alone,
+        span: #2 bytes(LO..HI),
+    },
+]
+ATTRIBUTE INPUT (PRETTY-PRINTED): struct A(crate::S);
+ATTRIBUTE INPUT: TokenStream [
+    Ident {
+        ident: "struct",
+        span: #2 bytes(LO..HI),
+    },
+    Ident {
+        ident: "A",
+        span: #2 bytes(LO..HI),
+    },
+    Group {
+        delimiter: Parenthesis,
+        stream: TokenStream [
+            Ident {
+                ident: "$crate",
+                span: #2 bytes(LO..HI),
+            },
+            Punct {
+                ch: ':',
+                spacing: Joint,
+                span: #2 bytes(LO..HI),
+            },
+            Punct {
+                ch: ':',
+                spacing: Alone,
+                span: #2 bytes(LO..HI),
+            },
+            Ident {
+                ident: "S",
+                span: #2 bytes(LO..HI),
+            },
+        ],
+        span: #2 bytes(LO..HI),
+    },
+    Punct {
+        ch: ';',
+        spacing: Alone,
+        span: #2 bytes(LO..HI),
+    },
+]
+DERIVE INPUT (PRETTY-PRINTED): struct D(crate::S);
+DERIVE INPUT: TokenStream [
+    Ident {
+        ident: "struct",
+        span: #2 bytes(LO..HI),
+    },
+    Ident {
+        ident: "D",
+        span: #2 bytes(LO..HI),
+    },
+    Group {
+        delimiter: Parenthesis,
+        stream: TokenStream [
+            Ident {
+                ident: "$crate",
+                span: #2 bytes(LO..HI),
+            },
+            Punct {
+                ch: ':',
+                spacing: Joint,
+                span: #2 bytes(LO..HI),
+            },
+            Punct {
+                ch: ':',
+                spacing: Alone,
+                span: #2 bytes(LO..HI),
+            },
+            Ident {
+                ident: "S",
+                span: #2 bytes(LO..HI),
+            },
+        ],
+        span: #2 bytes(LO..HI),
+    },
+    Punct {
+        ch: ';',
+        spacing: Alone,
+        span: #2 bytes(LO..HI),
+    },
+]
+PROC MACRO INPUT (PRETTY-PRINTED): struct M ( $crate :: S ) ;
+PROC MACRO INPUT: TokenStream [
+    Ident {
+        ident: "struct",
+        span: #10 bytes(LO..HI),
+    },
+    Ident {
+        ident: "M",
+        span: #10 bytes(LO..HI),
+    },
+    Group {
+        delimiter: Parenthesis,
+        stream: TokenStream [
+            Ident {
+                ident: "$crate",
+                span: #10 bytes(LO..HI),
+            },
+            Punct {
+                ch: ':',
+                spacing: Joint,
+                span: #10 bytes(LO..HI),
+            },
+            Punct {
+                ch: ':',
+                spacing: Alone,
+                span: #10 bytes(LO..HI),
+            },
+            Ident {
+                ident: "S",
+                span: #10 bytes(LO..HI),
+            },
+        ],
+        span: #10 bytes(LO..HI),
+    },
+    Punct {
+        ch: ';',
+        spacing: Alone,
+        span: #10 bytes(LO..HI),
+    },
+]
+ATTRIBUTE INPUT (PRETTY-PRINTED): struct A(::dollar_crate_external::S);
+ATTRIBUTE INPUT: TokenStream [
+    Ident {
+        ident: "struct",
+        span: #10 bytes(LO..HI),
+    },
+    Ident {
+        ident: "A",
+        span: #10 bytes(LO..HI),
+    },
+    Group {
+        delimiter: Parenthesis,
+        stream: TokenStream [
+            Ident {
+                ident: "$crate",
+                span: #10 bytes(LO..HI),
+            },
+            Punct {
+                ch: ':',
+                spacing: Joint,
+                span: #10 bytes(LO..HI),
+            },
+            Punct {
+                ch: ':',
+                spacing: Alone,
+                span: #10 bytes(LO..HI),
+            },
+            Ident {
+                ident: "S",
+                span: #10 bytes(LO..HI),
+            },
+        ],
+        span: #10 bytes(LO..HI),
+    },
+    Punct {
+        ch: ';',
+        spacing: Alone,
+        span: #10 bytes(LO..HI),
+    },
+]
+DERIVE INPUT (PRETTY-PRINTED): struct D(::dollar_crate_external::S);
+DERIVE INPUT: TokenStream [
+    Ident {
+        ident: "struct",
+        span: #10 bytes(LO..HI),
+    },
+    Ident {
+        ident: "D",
+        span: #10 bytes(LO..HI),
+    },
+    Group {
+        delimiter: Parenthesis,
+        stream: TokenStream [
+            Ident {
+                ident: "$crate",
+                span: #10 bytes(LO..HI),
+            },
+            Punct {
+                ch: ':',
+                spacing: Joint,
+                span: #10 bytes(LO..HI),
+            },
+            Punct {
+                ch: ':',
+                spacing: Alone,
+                span: #10 bytes(LO..HI),
+            },
+            Ident {
+                ident: "S",
+                span: #10 bytes(LO..HI),
+            },
+        ],
+        span: #10 bytes(LO..HI),
+    },
+    Punct {
+        ch: ';',
+        spacing: Alone,
+        span: #10 bytes(LO..HI),
+    },
+]
diff --git a/src/test/ui/proc-macro/edition-imports-2018.rs b/src/test/ui/proc-macro/edition-imports-2018.rs
new file mode 100644
index 0000000..f8d6bc5
--- /dev/null
+++ b/src/test/ui/proc-macro/edition-imports-2018.rs
@@ -0,0 +1,24 @@
+// compile-pass
+// edition:2018
+// aux-build:edition-imports-2015.rs
+
+#[macro_use]
+extern crate edition_imports_2015;
+
+mod import {
+    pub struct Path;
+}
+mod absolute {
+    pub struct Path;
+}
+
+mod check {
+    #[derive(Derive2015)] // OK
+    struct S;
+
+    fn check() {
+        Path;
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/expand-to-unstable-2.rs b/src/test/ui/proc-macro/expand-to-unstable-2.rs
new file mode 100644
index 0000000..4b4ba52
--- /dev/null
+++ b/src/test/ui/proc-macro/expand-to-unstable-2.rs
@@ -0,0 +1,14 @@
+// aux-build:derive-unstable-2.rs
+
+#![allow(warnings)]
+
+#[macro_use]
+extern crate derive_unstable_2;
+
+#[derive(Unstable)]
+//~^ ERROR: reserved for internal compiler
+struct A;
+
+fn main() {
+    foo();
+}
diff --git a/src/test/ui/proc-macro/expand-to-unstable-2.stderr b/src/test/ui/proc-macro/expand-to-unstable-2.stderr
new file mode 100644
index 0000000..b322f8e
--- /dev/null
+++ b/src/test/ui/proc-macro/expand-to-unstable-2.stderr
@@ -0,0 +1,11 @@
+error[E0658]: unless otherwise specified, attributes with the prefix `rustc_` are reserved for internal compiler diagnostics (see issue #29642)
+  --> $DIR/expand-to-unstable-2.rs:8:10
+   |
+LL | #[derive(Unstable)]
+   |          ^^^^^^^^
+   |
+   = help: add #![feature(rustc_attrs)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/proc-macro/expand-to-unstable.rs b/src/test/ui/proc-macro/expand-to-unstable.rs
new file mode 100644
index 0000000..0825c1a
--- /dev/null
+++ b/src/test/ui/proc-macro/expand-to-unstable.rs
@@ -0,0 +1,14 @@
+// aux-build:derive-unstable.rs
+
+#![allow(warnings)]
+
+#[macro_use]
+extern crate derive_unstable;
+
+#[derive(Unstable)]
+//~^ ERROR: use of unstable library feature
+struct A;
+
+fn main() {
+    unsafe { foo(); }
+}
diff --git a/src/test/ui/proc-macro/expand-to-unstable.stderr b/src/test/ui/proc-macro/expand-to-unstable.stderr
new file mode 100644
index 0000000..29a1287
--- /dev/null
+++ b/src/test/ui/proc-macro/expand-to-unstable.stderr
@@ -0,0 +1,11 @@
+error[E0658]: use of unstable library feature 'core_intrinsics': intrinsics are unlikely to ever be stabilized, instead they should be used through stabilized interfaces in the rest of the standard library
+  --> $DIR/expand-to-unstable.rs:8:10
+   |
+LL | #[derive(Unstable)]
+   |          ^^^^^^^^
+   |
+   = help: add #![feature(core_intrinsics)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/proc-macro/export-macro.rs b/src/test/ui/proc-macro/export-macro.rs
new file mode 100644
index 0000000..ad69fe5
--- /dev/null
+++ b/src/test/ui/proc-macro/export-macro.rs
@@ -0,0 +1,11 @@
+// error-pattern: cannot export macro_rules! macros from a `proc-macro` crate
+
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+#[macro_export]
+macro_rules! foo {
+    ($e:expr) => ($e)
+}
diff --git a/src/test/ui/proc-macro/export-macro.stderr b/src/test/ui/proc-macro/export-macro.stderr
new file mode 100644
index 0000000..bc64caa
--- /dev/null
+++ b/src/test/ui/proc-macro/export-macro.stderr
@@ -0,0 +1,10 @@
+error: cannot export macro_rules! macros from a `proc-macro` crate type currently
+  --> $DIR/export-macro.rs:9:1
+   |
+LL | / macro_rules! foo {
+LL | |     ($e:expr) => ($e)
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/proc-macro/exports.rs b/src/test/ui/proc-macro/exports.rs
new file mode 100644
index 0000000..a40c159
--- /dev/null
+++ b/src/test/ui/proc-macro/exports.rs
@@ -0,0 +1,15 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+#![allow(warnings)]
+
+pub fn a() {} //~ ERROR: cannot export any items
+pub struct B; //~ ERROR: cannot export any items
+pub enum C {} //~ ERROR: cannot export any items
+pub mod d {} //~ ERROR: cannot export any items
+
+mod e {}
+struct F;
+enum G {}
+fn h() {}
diff --git a/src/test/ui/proc-macro/exports.stderr b/src/test/ui/proc-macro/exports.stderr
new file mode 100644
index 0000000..2f81921
--- /dev/null
+++ b/src/test/ui/proc-macro/exports.stderr
@@ -0,0 +1,26 @@
+error: `proc-macro` crate types cannot export any items other than functions tagged with `#[proc_macro_derive]` currently
+  --> $DIR/exports.rs:7:1
+   |
+LL | pub fn a() {}
+   | ^^^^^^^^^^^^^
+
+error: `proc-macro` crate types cannot export any items other than functions tagged with `#[proc_macro_derive]` currently
+  --> $DIR/exports.rs:8:1
+   |
+LL | pub struct B;
+   | ^^^^^^^^^^^^^
+
+error: `proc-macro` crate types cannot export any items other than functions tagged with `#[proc_macro_derive]` currently
+  --> $DIR/exports.rs:9:1
+   |
+LL | pub enum C {}
+   | ^^^^^^^^^^^^^
+
+error: `proc-macro` crate types cannot export any items other than functions tagged with `#[proc_macro_derive]` currently
+  --> $DIR/exports.rs:10:1
+   |
+LL | pub mod d {}
+   | ^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/proc-macro/extern-prelude-extern-crate-proc-macro.rs b/src/test/ui/proc-macro/extern-prelude-extern-crate-proc-macro.rs
new file mode 100644
index 0000000..25a2a37
--- /dev/null
+++ b/src/test/ui/proc-macro/extern-prelude-extern-crate-proc-macro.rs
@@ -0,0 +1,7 @@
+// compile-pass
+// edition:2018
+
+extern crate proc_macro;
+use proc_macro::TokenStream; // OK
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/generate-mod.rs b/src/test/ui/proc-macro/generate-mod.rs
new file mode 100644
index 0000000..e5f9674
--- /dev/null
+++ b/src/test/ui/proc-macro/generate-mod.rs
@@ -0,0 +1,33 @@
+// Modules generated by transparent proc macros still acts as barriers for names (issue #50504).
+
+// aux-build:generate-mod.rs
+
+extern crate generate_mod;
+
+struct FromOutside;
+
+generate_mod::check!(); //~ ERROR cannot find type `FromOutside` in this scope
+                        //~| ERROR cannot find type `Outer` in this scope
+
+#[generate_mod::check_attr] //~ ERROR cannot find type `FromOutside` in this scope
+                            //~| ERROR cannot find type `OuterAttr` in this scope
+struct S;
+
+#[derive(generate_mod::CheckDerive)] //~ WARN cannot find type `FromOutside` in this scope
+                                     //~| WARN cannot find type `OuterDerive` in this scope
+                                     //~| WARN this was previously accepted
+                                     //~| WARN this was previously accepted
+struct Z;
+
+fn inner_block() {
+    #[derive(generate_mod::CheckDerive)] //~ WARN cannot find type `FromOutside` in this scope
+                                        //~| WARN cannot find type `OuterDerive` in this scope
+                                        //~| WARN this was previously accepted
+                                        //~| WARN this was previously accepted
+    struct InnerZ;
+}
+
+#[derive(generate_mod::CheckDeriveLint)] // OK, lint is suppressed
+struct W;
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/generate-mod.stderr b/src/test/ui/proc-macro/generate-mod.stderr
new file mode 100644
index 0000000..1b828b4
--- /dev/null
+++ b/src/test/ui/proc-macro/generate-mod.stderr
@@ -0,0 +1,64 @@
+error[E0412]: cannot find type `FromOutside` in this scope
+  --> $DIR/generate-mod.rs:9:1
+   |
+LL | generate_mod::check!();
+   | ^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
+
+error[E0412]: cannot find type `Outer` in this scope
+  --> $DIR/generate-mod.rs:9:1
+   |
+LL | generate_mod::check!();
+   | ^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
+
+error[E0412]: cannot find type `FromOutside` in this scope
+  --> $DIR/generate-mod.rs:12:1
+   |
+LL | #[generate_mod::check_attr]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
+
+error[E0412]: cannot find type `OuterAttr` in this scope
+  --> $DIR/generate-mod.rs:12:1
+   |
+LL | #[generate_mod::check_attr]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
+
+warning: cannot find type `FromOutside` in this scope
+  --> $DIR/generate-mod.rs:16:10
+   |
+LL | #[derive(generate_mod::CheckDerive)]
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import
+   |
+   = note: #[warn(proc_macro_derive_resolution_fallback)] on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #50504 <https://github.com/rust-lang/rust/issues/50504>
+
+warning: cannot find type `OuterDerive` in this scope
+  --> $DIR/generate-mod.rs:16:10
+   |
+LL | #[derive(generate_mod::CheckDerive)]
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #50504 <https://github.com/rust-lang/rust/issues/50504>
+
+warning: cannot find type `FromOutside` in this scope
+  --> $DIR/generate-mod.rs:23:14
+   |
+LL |     #[derive(generate_mod::CheckDerive)]
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #50504 <https://github.com/rust-lang/rust/issues/50504>
+
+warning: cannot find type `OuterDerive` in this scope
+  --> $DIR/generate-mod.rs:23:14
+   |
+LL |     #[derive(generate_mod::CheckDerive)]
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #50504 <https://github.com/rust-lang/rust/issues/50504>
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/src/test/ui/proc-macro/illegal-proc-macro-derive-use.rs b/src/test/ui/proc-macro/illegal-proc-macro-derive-use.rs
new file mode 100644
index 0000000..4efd9e9
--- /dev/null
+++ b/src/test/ui/proc-macro/illegal-proc-macro-derive-use.rs
@@ -0,0 +1,15 @@
+extern crate proc_macro;
+
+#[proc_macro_derive(Foo)]
+//~^ ERROR: only usable with crates of the `proc-macro` crate type
+pub fn foo(a: proc_macro::TokenStream) -> proc_macro::TokenStream {
+    a
+}
+
+// Issue #37590
+#[proc_macro_derive(Foo)]
+//~^ ERROR: the `#[proc_macro_derive]` attribute may only be used on bare functions
+pub struct Foo {
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/illegal-proc-macro-derive-use.stderr b/src/test/ui/proc-macro/illegal-proc-macro-derive-use.stderr
new file mode 100644
index 0000000..c0930ab
--- /dev/null
+++ b/src/test/ui/proc-macro/illegal-proc-macro-derive-use.stderr
@@ -0,0 +1,14 @@
+error: the `#[proc_macro_derive]` attribute is only usable with crates of the `proc-macro` crate type
+  --> $DIR/illegal-proc-macro-derive-use.rs:3:1
+   |
+LL | #[proc_macro_derive(Foo)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: the `#[proc_macro_derive]` attribute may only be used on bare functions
+  --> $DIR/illegal-proc-macro-derive-use.rs:10:1
+   |
+LL | #[proc_macro_derive(Foo)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/proc-macro/import.rs b/src/test/ui/proc-macro/import.rs
new file mode 100644
index 0000000..8fbccdf
--- /dev/null
+++ b/src/test/ui/proc-macro/import.rs
@@ -0,0 +1,11 @@
+// aux-build:derive-a.rs
+
+#![allow(warnings)]
+
+#[macro_use]
+extern crate derive_a;
+
+use derive_a::derive_a;
+//~^ ERROR: unresolved import `derive_a::derive_a`
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/import.stderr b/src/test/ui/proc-macro/import.stderr
new file mode 100644
index 0000000..813a8ac
--- /dev/null
+++ b/src/test/ui/proc-macro/import.stderr
@@ -0,0 +1,9 @@
+error[E0432]: unresolved import `derive_a::derive_a`
+  --> $DIR/import.rs:8:5
+   |
+LL | use derive_a::derive_a;
+   |     ^^^^^^^^^^^^^^^^^^ no `derive_a` in the root
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/proc-macro/invalid-attributes.rs b/src/test/ui/proc-macro/invalid-attributes.rs
new file mode 100644
index 0000000..c5ec492
--- /dev/null
+++ b/src/test/ui/proc-macro/invalid-attributes.rs
@@ -0,0 +1,26 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro = "test"] //~ ERROR attribute must be of the form
+pub fn a(a: TokenStream) -> TokenStream { a }
+
+#[proc_macro()] //~ ERROR attribute must be of the form
+pub fn c(a: TokenStream) -> TokenStream { a }
+
+#[proc_macro(x)] //~ ERROR attribute must be of the form
+pub fn d(a: TokenStream) -> TokenStream { a }
+
+#[proc_macro_attribute = "test"] //~ ERROR attribute must be of the form
+pub fn e(_: TokenStream, a: TokenStream) -> TokenStream { a }
+
+#[proc_macro_attribute()] //~ ERROR attribute must be of the form
+pub fn g(_: TokenStream, a: TokenStream) -> TokenStream { a }
+
+#[proc_macro_attribute(x)] //~ ERROR attribute must be of the form
+pub fn h(_: TokenStream, a: TokenStream) -> TokenStream { a }
diff --git a/src/test/ui/proc-macro/invalid-attributes.stderr b/src/test/ui/proc-macro/invalid-attributes.stderr
new file mode 100644
index 0000000..8dff60d
--- /dev/null
+++ b/src/test/ui/proc-macro/invalid-attributes.stderr
@@ -0,0 +1,38 @@
+error: attribute must be of the form `#[proc_macro]`
+  --> $DIR/invalid-attributes.rs:10:1
+   |
+LL | #[proc_macro = "test"]
+   | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: attribute must be of the form `#[proc_macro]`
+  --> $DIR/invalid-attributes.rs:13:1
+   |
+LL | #[proc_macro()]
+   | ^^^^^^^^^^^^^^^
+
+error: attribute must be of the form `#[proc_macro]`
+  --> $DIR/invalid-attributes.rs:16:1
+   |
+LL | #[proc_macro(x)]
+   | ^^^^^^^^^^^^^^^^
+
+error: attribute must be of the form `#[proc_macro_attribute]`
+  --> $DIR/invalid-attributes.rs:19:1
+   |
+LL | #[proc_macro_attribute = "test"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: attribute must be of the form `#[proc_macro_attribute]`
+  --> $DIR/invalid-attributes.rs:22:1
+   |
+LL | #[proc_macro_attribute()]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: attribute must be of the form `#[proc_macro_attribute]`
+  --> $DIR/invalid-attributes.rs:25:1
+   |
+LL | #[proc_macro_attribute(x)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/proc-macro/invalid-punct-ident-1.rs b/src/test/ui/proc-macro/invalid-punct-ident-1.rs
new file mode 100644
index 0000000..2360b1f
--- /dev/null
+++ b/src/test/ui/proc-macro/invalid-punct-ident-1.rs
@@ -0,0 +1,6 @@
+// aux-build:invalid-punct-ident.rs
+
+#[macro_use]
+extern crate invalid_punct_ident;
+
+invalid_punct!(); //~ ERROR proc macro panicked
diff --git a/src/test/ui/proc-macro/invalid-punct-ident-1.stderr b/src/test/ui/proc-macro/invalid-punct-ident-1.stderr
new file mode 100644
index 0000000..9a53741
--- /dev/null
+++ b/src/test/ui/proc-macro/invalid-punct-ident-1.stderr
@@ -0,0 +1,10 @@
+error: proc macro panicked
+  --> $DIR/invalid-punct-ident-1.rs:6:1
+   |
+LL | invalid_punct!();
+   | ^^^^^^^^^^^^^^^^^
+   |
+   = help: message: unsupported character `'`'`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/proc-macro/invalid-punct-ident-2.rs b/src/test/ui/proc-macro/invalid-punct-ident-2.rs
new file mode 100644
index 0000000..9593d47
--- /dev/null
+++ b/src/test/ui/proc-macro/invalid-punct-ident-2.rs
@@ -0,0 +1,6 @@
+// aux-build:invalid-punct-ident.rs
+
+#[macro_use]
+extern crate invalid_punct_ident;
+
+invalid_ident!(); //~ ERROR proc macro panicked
diff --git a/src/test/ui/proc-macro/invalid-punct-ident-2.stderr b/src/test/ui/proc-macro/invalid-punct-ident-2.stderr
new file mode 100644
index 0000000..77a26b8
--- /dev/null
+++ b/src/test/ui/proc-macro/invalid-punct-ident-2.stderr
@@ -0,0 +1,10 @@
+error: proc macro panicked
+  --> $DIR/invalid-punct-ident-2.rs:6:1
+   |
+LL | invalid_ident!();
+   | ^^^^^^^^^^^^^^^^^
+   |
+   = help: message: `"*"` is not a valid identifier
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/proc-macro/invalid-punct-ident-3.rs b/src/test/ui/proc-macro/invalid-punct-ident-3.rs
new file mode 100644
index 0000000..75e3e06
--- /dev/null
+++ b/src/test/ui/proc-macro/invalid-punct-ident-3.rs
@@ -0,0 +1,6 @@
+// aux-build:invalid-punct-ident.rs
+
+#[macro_use]
+extern crate invalid_punct_ident;
+
+invalid_raw_ident!(); //~ ERROR proc macro panicked
diff --git a/src/test/ui/proc-macro/invalid-punct-ident-3.stderr b/src/test/ui/proc-macro/invalid-punct-ident-3.stderr
new file mode 100644
index 0000000..24371f3
--- /dev/null
+++ b/src/test/ui/proc-macro/invalid-punct-ident-3.stderr
@@ -0,0 +1,10 @@
+error: proc macro panicked
+  --> $DIR/invalid-punct-ident-3.rs:6:1
+   |
+LL | invalid_raw_ident!();
+   | ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: message: `self` cannot be a raw identifier
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/proc-macro/invalid-punct-ident-4.rs b/src/test/ui/proc-macro/invalid-punct-ident-4.rs
new file mode 100644
index 0000000..5918782
--- /dev/null
+++ b/src/test/ui/proc-macro/invalid-punct-ident-4.rs
@@ -0,0 +1,7 @@
+// aux-build:invalid-punct-ident.rs
+
+#[macro_use]
+extern crate invalid_punct_ident;
+
+lexer_failure!(); //~ ERROR proc macro panicked
+                  //~| ERROR unexpected close delimiter: `)`
diff --git a/src/test/ui/proc-macro/invalid-punct-ident-4.stderr b/src/test/ui/proc-macro/invalid-punct-ident-4.stderr
new file mode 100644
index 0000000..da2bf07
--- /dev/null
+++ b/src/test/ui/proc-macro/invalid-punct-ident-4.stderr
@@ -0,0 +1,14 @@
+error: unexpected close delimiter: `)`
+  --> $DIR/invalid-punct-ident-4.rs:6:1
+   |
+LL | lexer_failure!();
+   | ^^^^^^^^^^^^^^^^^ unexpected close delimiter
+
+error: proc macro panicked
+  --> $DIR/invalid-punct-ident-4.rs:6:1
+   |
+LL | lexer_failure!();
+   | ^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/proc-macro/issue-37788.rs b/src/test/ui/proc-macro/issue-37788.rs
new file mode 100644
index 0000000..75fcd24
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-37788.rs
@@ -0,0 +1,9 @@
+// aux-build:derive-a-b.rs
+
+#[macro_use]
+extern crate derive_a_b;
+
+fn main() {
+    // Test that constructing the `visible_parent_map` (in `cstore_impl.rs`) does not ICE.
+    std::cell::Cell::new(0) //~ ERROR mismatched types
+}
diff --git a/src/test/ui/proc-macro/issue-37788.stderr b/src/test/ui/proc-macro/issue-37788.stderr
new file mode 100644
index 0000000..0727e8c
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-37788.stderr
@@ -0,0 +1,17 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-37788.rs:8:5
+   |
+LL | fn main() {
+   |           - expected `()` because of default return type
+LL |     // Test that constructing the `visible_parent_map` (in `cstore_impl.rs`) does not ICE.
+LL |     std::cell::Cell::new(0)
+   |     ^^^^^^^^^^^^^^^^^^^^^^^- help: try adding a semicolon: `;`
+   |     |
+   |     expected (), found struct `std::cell::Cell`
+   |
+   = note: expected type `()`
+              found type `std::cell::Cell<{integer}>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/proc-macro/issue-38586.rs b/src/test/ui/proc-macro/issue-38586.rs
new file mode 100644
index 0000000..24e88ed
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-38586.rs
@@ -0,0 +1,9 @@
+// aux-build:issue-38586.rs
+
+#[macro_use]
+extern crate issue_38586;
+
+#[derive(A)] //~ ERROR `foo`
+struct A;
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/issue-38586.stderr b/src/test/ui/proc-macro/issue-38586.stderr
new file mode 100644
index 0000000..2584e0c
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-38586.stderr
@@ -0,0 +1,9 @@
+error[E0425]: cannot find value `foo` in this scope
+  --> $DIR/issue-38586.rs:6:10
+   |
+LL | #[derive(A)]
+   |          ^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/proc-macro/issue-41211.rs b/src/test/ui/proc-macro/issue-41211.rs
new file mode 100644
index 0000000..0b082f4
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-41211.rs
@@ -0,0 +1,14 @@
+// aux-build:issue-41211.rs
+
+// FIXME: https://github.com/rust-lang/rust/issues/41430
+// This is a temporary regression test for the ICE reported in #41211
+
+#![feature(custom_inner_attributes)]
+
+#![emit_unchanged]
+//~^ ERROR attribute `emit_unchanged` is currently unknown to the compiler
+//~| ERROR inconsistent resolution for a macro: first custom attribute, then attribute macro
+extern crate issue_41211;
+use issue_41211::emit_unchanged;
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/issue-41211.stderr b/src/test/ui/proc-macro/issue-41211.stderr
new file mode 100644
index 0000000..f75481e
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-41211.stderr
@@ -0,0 +1,17 @@
+error[E0658]: The attribute `emit_unchanged` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/issue-41211.rs:8:4
+   |
+LL | #![emit_unchanged]
+   |    ^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error: inconsistent resolution for a macro: first custom attribute, then attribute macro
+  --> $DIR/issue-41211.rs:8:4
+   |
+LL | #![emit_unchanged]
+   |    ^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/proc-macro/issue-50493.rs b/src/test/ui/proc-macro/issue-50493.rs
new file mode 100644
index 0000000..eeb08f5
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-50493.rs
@@ -0,0 +1,14 @@
+// aux-build:issue-50493.rs
+
+#[macro_use]
+extern crate issue_50493;
+
+#[derive(Derive)] //~ ERROR field `field` of struct `Restricted` is private
+struct Restricted {
+    pub(in restricted) field: usize, //~ visibilities can only be restricted to ancestor modules
+}
+
+mod restricted {}
+
+fn main() {}
+
diff --git a/src/test/ui/proc-macro/issue-50493.stderr b/src/test/ui/proc-macro/issue-50493.stderr
new file mode 100644
index 0000000..28c61a2
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-50493.stderr
@@ -0,0 +1,15 @@
+error: visibilities can only be restricted to ancestor modules
+  --> $DIR/issue-50493.rs:8:12
+   |
+LL |     pub(in restricted) field: usize,
+   |            ^^^^^^^^^^
+
+error[E0616]: field `field` of struct `Restricted` is private
+  --> $DIR/issue-50493.rs:6:10
+   |
+LL | #[derive(Derive)]
+   |          ^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0616`.
diff --git a/src/test/ui/proc-macro/issue-53481.rs b/src/test/ui/proc-macro/issue-53481.rs
new file mode 100644
index 0000000..479fd1d
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-53481.rs
@@ -0,0 +1,22 @@
+// compile-pass
+// aux-build:issue-53481.rs
+
+#[macro_use]
+extern crate issue_53481;
+
+mod m1 {
+    use m2::MyTrait;
+
+    #[derive(MyTrait)]
+    struct A {}
+}
+
+mod m2 {
+    pub type MyTrait = u8;
+
+    #[derive(MyTrait)]
+    #[my_attr]
+    struct B {}
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/item-error.rs b/src/test/ui/proc-macro/item-error.rs
new file mode 100644
index 0000000..64c203e
--- /dev/null
+++ b/src/test/ui/proc-macro/item-error.rs
@@ -0,0 +1,15 @@
+// aux-build:derive-b.rs
+
+#![allow(warnings)]
+
+#[macro_use]
+extern crate derive_b;
+
+#[derive(B)]
+struct A {
+    a: &u64
+//~^ ERROR: missing lifetime specifier
+}
+
+fn main() {
+}
diff --git a/src/test/ui/proc-macro/item-error.stderr b/src/test/ui/proc-macro/item-error.stderr
new file mode 100644
index 0000000..e801c26
--- /dev/null
+++ b/src/test/ui/proc-macro/item-error.stderr
@@ -0,0 +1,9 @@
+error[E0106]: missing lifetime specifier
+  --> $DIR/item-error.rs:10:8
+   |
+LL |     a: &u64
+   |        ^ expected lifetime parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0106`.
diff --git a/src/test/ui/proc-macro/lifetimes.rs b/src/test/ui/proc-macro/lifetimes.rs
new file mode 100644
index 0000000..d0dd1b4
--- /dev/null
+++ b/src/test/ui/proc-macro/lifetimes.rs
@@ -0,0 +1,11 @@
+// aux-build:lifetimes.rs
+
+#![feature(proc_macro_hygiene)]
+
+extern crate lifetimes;
+
+use lifetimes::*;
+
+type A = single_quote_alone!(); //~ ERROR expected type, found `'`
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/lifetimes.stderr b/src/test/ui/proc-macro/lifetimes.stderr
new file mode 100644
index 0000000..2356a11
--- /dev/null
+++ b/src/test/ui/proc-macro/lifetimes.stderr
@@ -0,0 +1,8 @@
+error: expected type, found `'`
+  --> $DIR/lifetimes.rs:9:10
+   |
+LL | type A = single_quote_alone!();
+   |          ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/proc-macro/lints_in_proc_macros.rs b/src/test/ui/proc-macro/lints_in_proc_macros.rs
new file mode 100644
index 0000000..8d2957e
--- /dev/null
+++ b/src/test/ui/proc-macro/lints_in_proc_macros.rs
@@ -0,0 +1,17 @@
+// aux-build:bang_proc_macro2.rs
+
+#![feature(proc_macro_hygiene)]
+#![allow(unused_macros)]
+
+extern crate bang_proc_macro2;
+
+use bang_proc_macro2::bang_proc_macro2;
+
+fn main() {
+    let foobar = 42;
+    bang_proc_macro2!();
+    //~^ ERROR cannot find value `foobar2` in this scope
+    //~| HELP a local variable with a similar name exists
+    //~| SUGGESTION foobar
+    println!("{}", x);
+}
diff --git a/src/test/ui/proc-macro/lints_in_proc_macros.stderr b/src/test/ui/proc-macro/lints_in_proc_macros.stderr
new file mode 100644
index 0000000..2d97cd7
--- /dev/null
+++ b/src/test/ui/proc-macro/lints_in_proc_macros.stderr
@@ -0,0 +1,9 @@
+error[E0425]: cannot find value `foobar2` in this scope
+  --> $DIR/lints_in_proc_macros.rs:12:5
+   |
+LL |     bang_proc_macro2!();
+   |     ^^^^^^^^^^^^^^^^^^^^ help: a local variable with a similar name exists: `foobar`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/proc-macro/load-panic.rs b/src/test/ui/proc-macro/load-panic.rs
new file mode 100644
index 0000000..fa279c5
--- /dev/null
+++ b/src/test/ui/proc-macro/load-panic.rs
@@ -0,0 +1,11 @@
+// aux-build:derive-panic.rs
+// compile-flags:--error-format human
+
+#[macro_use]
+extern crate derive_panic;
+
+#[derive(A)]
+//~^ ERROR: proc-macro derive panicked
+struct Foo;
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/load-panic.stderr b/src/test/ui/proc-macro/load-panic.stderr
new file mode 100644
index 0000000..b448c80
--- /dev/null
+++ b/src/test/ui/proc-macro/load-panic.stderr
@@ -0,0 +1,10 @@
+error: proc-macro derive panicked
+  --> $DIR/load-panic.rs:7:10
+   |
+LL | #[derive(A)]
+   |          ^
+   |
+   = help: message: nope!
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/proc-macro/macro-brackets.rs b/src/test/ui/proc-macro/macro-brackets.rs
new file mode 100644
index 0000000..c46abf0
--- /dev/null
+++ b/src/test/ui/proc-macro/macro-brackets.rs
@@ -0,0 +1,14 @@
+// aux-build:macro-brackets.rs
+
+extern crate macro_brackets as bar;
+use bar::doit;
+
+macro_rules! id {
+    ($($t:tt)*) => ($($t)*)
+}
+
+#[doit]
+id![static X: u32 = 'a';]; //~ ERROR: mismatched types
+
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/macro-brackets.stderr b/src/test/ui/proc-macro/macro-brackets.stderr
new file mode 100644
index 0000000..7447b5c
--- /dev/null
+++ b/src/test/ui/proc-macro/macro-brackets.stderr
@@ -0,0 +1,9 @@
+error[E0308]: mismatched types
+  --> $DIR/macro-brackets.rs:11:21
+   |
+LL | id![static X: u32 = 'a';];
+   |                     ^^^ expected u32, found char
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/proc-macro/macro-namespace-reserved-2.rs b/src/test/ui/proc-macro/macro-namespace-reserved-2.rs
new file mode 100644
index 0000000..583640a
--- /dev/null
+++ b/src/test/ui/proc-macro/macro-namespace-reserved-2.rs
@@ -0,0 +1,46 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::*;
+
+#[proc_macro]
+pub fn my_macro(input: TokenStream) -> TokenStream {
+    input
+}
+
+#[proc_macro_attribute]
+pub fn my_macro_attr(input: TokenStream, _: TokenStream) -> TokenStream {
+    input
+}
+
+#[proc_macro_derive(MyTrait)]
+pub fn my_macro_derive(input: TokenStream) -> TokenStream {
+    input
+}
+
+fn check_bang1() {
+    my_macro!(); //~ ERROR can't use a procedural macro from the same crate that defines it
+}
+fn check_bang2() {
+    my_macro_attr!(); //~ ERROR can't use a procedural macro from the same crate that defines it
+}
+fn check_bang3() {
+    MyTrait!(); //~ ERROR can't use a procedural macro from the same crate that defines it
+}
+
+#[my_macro] //~ ERROR can't use a procedural macro from the same crate that defines it
+fn check_attr1() {}
+#[my_macro_attr] //~ ERROR can't use a procedural macro from the same crate that defines it
+fn check_attr2() {}
+#[MyTrait] //~ ERROR can't use a procedural macro from the same crate that defines it
+fn check_attr3() {}
+
+#[derive(my_macro)] //~ ERROR can't use a procedural macro from the same crate that defines it
+struct CheckDerive1;
+#[derive(my_macro_attr)] //~ ERROR can't use a procedural macro from the same crate that defines it
+struct CheckDerive2;
+#[derive(MyTrait)] //~ ERROR can't use a procedural macro from the same crate that defines it
+struct CheckDerive3;
diff --git a/src/test/ui/proc-macro/macro-namespace-reserved-2.stderr b/src/test/ui/proc-macro/macro-namespace-reserved-2.stderr
new file mode 100644
index 0000000..548f9e3
--- /dev/null
+++ b/src/test/ui/proc-macro/macro-namespace-reserved-2.stderr
@@ -0,0 +1,56 @@
+error: can't use a procedural macro from the same crate that defines it
+  --> $DIR/macro-namespace-reserved-2.rs:25:5
+   |
+LL |     my_macro!();
+   |     ^^^^^^^^
+
+error: can't use a procedural macro from the same crate that defines it
+  --> $DIR/macro-namespace-reserved-2.rs:28:5
+   |
+LL |     my_macro_attr!();
+   |     ^^^^^^^^^^^^^
+
+error: can't use a procedural macro from the same crate that defines it
+  --> $DIR/macro-namespace-reserved-2.rs:31:5
+   |
+LL |     MyTrait!();
+   |     ^^^^^^^
+
+error: can't use a procedural macro from the same crate that defines it
+  --> $DIR/macro-namespace-reserved-2.rs:34:3
+   |
+LL | #[my_macro]
+   |   ^^^^^^^^
+
+error: can't use a procedural macro from the same crate that defines it
+  --> $DIR/macro-namespace-reserved-2.rs:36:3
+   |
+LL | #[my_macro_attr]
+   |   ^^^^^^^^^^^^^
+
+error: can't use a procedural macro from the same crate that defines it
+  --> $DIR/macro-namespace-reserved-2.rs:38:3
+   |
+LL | #[MyTrait]
+   |   ^^^^^^^
+
+error: can't use a procedural macro from the same crate that defines it
+  --> $DIR/macro-namespace-reserved-2.rs:41:10
+   |
+LL | #[derive(my_macro)]
+   |          ^^^^^^^^
+
+error: can't use a procedural macro from the same crate that defines it
+  --> $DIR/macro-namespace-reserved-2.rs:43:10
+   |
+LL | #[derive(my_macro_attr)]
+   |          ^^^^^^^^^^^^^
+
+error: can't use a procedural macro from the same crate that defines it
+  --> $DIR/macro-namespace-reserved-2.rs:45:10
+   |
+LL | #[derive(MyTrait)]
+   |          ^^^^^^^
+
+error: aborting due to 9 previous errors
+
diff --git a/src/test/ui/proc-macro/macro-namespace-reserved.rs b/src/test/ui/proc-macro/macro-namespace-reserved.rs
new file mode 100644
index 0000000..60d379e
--- /dev/null
+++ b/src/test/ui/proc-macro/macro-namespace-reserved.rs
@@ -0,0 +1,38 @@
+// force-host
+// no-prefer-dynamic
+
+#![feature(decl_macro)]
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::*;
+
+#[proc_macro]
+pub fn my_macro(input: TokenStream) -> TokenStream {
+    input
+}
+
+#[proc_macro_attribute]
+pub fn my_macro_attr(input: TokenStream, _: TokenStream) -> TokenStream {
+    input
+}
+
+#[proc_macro_derive(MyTrait)]
+pub fn my_macro_derive(input: TokenStream) -> TokenStream {
+    input
+}
+
+macro my_macro() {} //~ ERROR the name `my_macro` is defined multiple times
+macro my_macro_attr() {} //~ ERROR the name `my_macro_attr` is defined multiple times
+macro MyTrait() {} //~ ERROR the name `MyTrait` is defined multiple times
+
+#[proc_macro_derive(SameName)]
+pub fn foo(input: TokenStream) -> TokenStream {
+    input
+}
+
+#[proc_macro]
+pub fn SameName(input: TokenStream) -> TokenStream {
+//~^ ERROR the name `SameName` is defined multiple times
+    input
+}
diff --git a/src/test/ui/proc-macro/macro-namespace-reserved.stderr b/src/test/ui/proc-macro/macro-namespace-reserved.stderr
new file mode 100644
index 0000000..f5d589c
--- /dev/null
+++ b/src/test/ui/proc-macro/macro-namespace-reserved.stderr
@@ -0,0 +1,47 @@
+error[E0428]: the name `my_macro` is defined multiple times
+  --> $DIR/macro-namespace-reserved.rs:25:1
+   |
+LL | pub fn my_macro(input: TokenStream) -> TokenStream {
+   | -------------------------------------------------- previous definition of the macro `my_macro` here
+...
+LL | macro my_macro() {}
+   | ^^^^^^^^^^^^^^^^ `my_macro` redefined here
+   |
+   = note: `my_macro` must be defined only once in the macro namespace of this module
+
+error[E0428]: the name `my_macro_attr` is defined multiple times
+  --> $DIR/macro-namespace-reserved.rs:26:1
+   |
+LL | pub fn my_macro_attr(input: TokenStream, _: TokenStream) -> TokenStream {
+   | ----------------------------------------------------------------------- previous definition of the macro `my_macro_attr` here
+...
+LL | macro my_macro_attr() {}
+   | ^^^^^^^^^^^^^^^^^^^^^ `my_macro_attr` redefined here
+   |
+   = note: `my_macro_attr` must be defined only once in the macro namespace of this module
+
+error[E0428]: the name `MyTrait` is defined multiple times
+  --> $DIR/macro-namespace-reserved.rs:27:1
+   |
+LL | #[proc_macro_derive(MyTrait)]
+   |                     ------- previous definition of the macro `MyTrait` here
+...
+LL | macro MyTrait() {}
+   | ^^^^^^^^^^^^^^^ `MyTrait` redefined here
+   |
+   = note: `MyTrait` must be defined only once in the macro namespace of this module
+
+error[E0428]: the name `SameName` is defined multiple times
+  --> $DIR/macro-namespace-reserved.rs:35:1
+   |
+LL | #[proc_macro_derive(SameName)]
+   |                     -------- previous definition of the macro `SameName` here
+...
+LL | pub fn SameName(input: TokenStream) -> TokenStream {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SameName` redefined here
+   |
+   = note: `SameName` must be defined only once in the macro namespace of this module
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0428`.
diff --git a/src/test/ui/proc-macro/macro-use-attr.rs b/src/test/ui/proc-macro/macro-use-attr.rs
new file mode 100644
index 0000000..13db072
--- /dev/null
+++ b/src/test/ui/proc-macro/macro-use-attr.rs
@@ -0,0 +1,11 @@
+// compile-pass
+// aux-build:attr_proc_macro.rs
+
+#[macro_use] extern crate attr_proc_macro;
+
+#[attr_proc_macro]
+struct Foo;
+
+fn main() {
+    let _ = Foo;
+}
diff --git a/src/test/ui/proc-macro/macro-use-bang.rs b/src/test/ui/proc-macro/macro-use-bang.rs
new file mode 100644
index 0000000..4bf3bcd
--- /dev/null
+++ b/src/test/ui/proc-macro/macro-use-bang.rs
@@ -0,0 +1,11 @@
+// compile-pass
+// aux-build:bang_proc_macro.rs
+
+#![feature(proc_macro_hygiene)]
+
+#[macro_use]
+extern crate bang_proc_macro;
+
+fn main() {
+    bang_proc_macro!(println!("Hello, world!"));
+}
diff --git a/src/test/ui/proc-macro/macros-in-extern.rs b/src/test/ui/proc-macro/macros-in-extern.rs
new file mode 100644
index 0000000..5c5603b
--- /dev/null
+++ b/src/test/ui/proc-macro/macros-in-extern.rs
@@ -0,0 +1,25 @@
+// aux-build:test-macros.rs
+// ignore-wasm32
+
+extern crate test_macros;
+
+use test_macros::{nop_attr, no_output, emit_input};
+
+fn main() {
+    assert_eq!(unsafe { rust_get_test_int() }, 0isize);
+    assert_eq!(unsafe { rust_dbg_extern_identity_u32(0xDEADBEEF) }, 0xDEADBEEF);
+}
+
+#[link(name = "rust_test_helpers", kind = "static")]
+extern {
+    #[no_output]
+    //~^ ERROR macro invocations in `extern {}` blocks are experimental
+    fn some_definitely_unknown_symbol_which_should_be_removed();
+
+    #[nop_attr]
+    //~^ ERROR macro invocations in `extern {}` blocks are experimental
+    fn rust_get_test_int() -> isize;
+
+    emit_input!(fn rust_dbg_extern_identity_u32(arg: u32) -> u32;);
+    //~^ ERROR macro invocations in `extern {}` blocks are experimental
+}
diff --git a/src/test/ui/proc-macro/macros-in-extern.stderr b/src/test/ui/proc-macro/macros-in-extern.stderr
new file mode 100644
index 0000000..8a48656
--- /dev/null
+++ b/src/test/ui/proc-macro/macros-in-extern.stderr
@@ -0,0 +1,27 @@
+error[E0658]: macro invocations in `extern {}` blocks are experimental (see issue #49476)
+  --> $DIR/macros-in-extern.rs:15:5
+   |
+LL |     #[no_output]
+   |     ^^^^^^^^^^^^
+   |
+   = help: add #![feature(macros_in_extern)] to the crate attributes to enable
+
+error[E0658]: macro invocations in `extern {}` blocks are experimental (see issue #49476)
+  --> $DIR/macros-in-extern.rs:19:5
+   |
+LL |     #[nop_attr]
+   |     ^^^^^^^^^^^
+   |
+   = help: add #![feature(macros_in_extern)] to the crate attributes to enable
+
+error[E0658]: macro invocations in `extern {}` blocks are experimental (see issue #49476)
+  --> $DIR/macros-in-extern.rs:23:5
+   |
+LL |     emit_input!(fn rust_dbg_extern_identity_u32(arg: u32) -> u32;);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(macros_in_extern)] to the crate attributes to enable
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/proc-macro/more-gates.rs b/src/test/ui/proc-macro/more-gates.rs
new file mode 100644
index 0000000..b870b43
--- /dev/null
+++ b/src/test/ui/proc-macro/more-gates.rs
@@ -0,0 +1,22 @@
+// aux-build:more-gates.rs
+
+#![feature(decl_macro)]
+
+extern crate more_gates as foo;
+
+use foo::*;
+
+#[attr2mac1]
+//~^ ERROR: cannot expand to macro definitions
+pub fn a() {}
+#[attr2mac2]
+//~^ ERROR: cannot expand to macro definitions
+pub fn a() {}
+
+mac2mac1!(); //~ ERROR: cannot expand to macro definitions
+mac2mac2!(); //~ ERROR: cannot expand to macro definitions
+
+tricky!();
+//~^ ERROR: cannot expand to macro definitions
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/more-gates.stderr b/src/test/ui/proc-macro/more-gates.stderr
new file mode 100644
index 0000000..c6c2954
--- /dev/null
+++ b/src/test/ui/proc-macro/more-gates.stderr
@@ -0,0 +1,43 @@
+error[E0658]: procedural macros cannot expand to macro definitions (see issue #54727)
+  --> $DIR/more-gates.rs:9:1
+   |
+LL | #[attr2mac1]
+   | ^^^^^^^^^^^^
+   |
+   = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable
+
+error[E0658]: procedural macros cannot expand to macro definitions (see issue #54727)
+  --> $DIR/more-gates.rs:12:1
+   |
+LL | #[attr2mac2]
+   | ^^^^^^^^^^^^
+   |
+   = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable
+
+error[E0658]: procedural macros cannot expand to macro definitions (see issue #54727)
+  --> $DIR/more-gates.rs:16:1
+   |
+LL | mac2mac1!();
+   | ^^^^^^^^^^^^
+   |
+   = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable
+
+error[E0658]: procedural macros cannot expand to macro definitions (see issue #54727)
+  --> $DIR/more-gates.rs:17:1
+   |
+LL | mac2mac2!();
+   | ^^^^^^^^^^^^
+   |
+   = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable
+
+error[E0658]: procedural macros cannot expand to macro definitions (see issue #54727)
+  --> $DIR/more-gates.rs:19:1
+   |
+LL | tricky!();
+   | ^^^^^^^^^^
+   |
+   = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/proc-macro/multispan.rs b/src/test/ui/proc-macro/multispan.rs
new file mode 100644
index 0000000..d069477
--- /dev/null
+++ b/src/test/ui/proc-macro/multispan.rs
@@ -0,0 +1,27 @@
+// aux-build:multispan.rs
+
+#![feature(proc_macro_hygiene)]
+
+extern crate multispan;
+
+use multispan::hello;
+
+fn main() {
+    // This one emits no error.
+    hello!();
+
+    // Exactly one 'hi'.
+    hello!(hi); //~ ERROR hello to you, too!
+
+    // Now two, back to back.
+    hello!(hi hi); //~ ERROR hello to you, too!
+
+    // Now three, back to back.
+    hello!(hi hi hi); //~ ERROR hello to you, too!
+
+    // Now several, with spacing.
+    hello!(hi hey hi yo hi beep beep hi hi); //~ ERROR hello to you, too!
+    hello!(hi there, hi how are you? hi... hi.); //~ ERROR hello to you, too!
+    hello!(whoah. hi di hi di ho); //~ ERROR hello to you, too!
+    hello!(hi good hi and good bye); //~ ERROR hello to you, too!
+}
diff --git a/src/test/ui/proc-macro/multispan.stderr b/src/test/ui/proc-macro/multispan.stderr
new file mode 100644
index 0000000..44af07a
--- /dev/null
+++ b/src/test/ui/proc-macro/multispan.stderr
@@ -0,0 +1,86 @@
+error: hello to you, too!
+  --> $DIR/multispan.rs:14:5
+   |
+LL |     hello!(hi);
+   |     ^^^^^^^^^^^
+   |
+note: found these 'hi's
+  --> $DIR/multispan.rs:14:12
+   |
+LL |     hello!(hi);
+   |            ^^
+
+error: hello to you, too!
+  --> $DIR/multispan.rs:17:5
+   |
+LL |     hello!(hi hi);
+   |     ^^^^^^^^^^^^^^
+   |
+note: found these 'hi's
+  --> $DIR/multispan.rs:17:12
+   |
+LL |     hello!(hi hi);
+   |            ^^ ^^
+
+error: hello to you, too!
+  --> $DIR/multispan.rs:20:5
+   |
+LL |     hello!(hi hi hi);
+   |     ^^^^^^^^^^^^^^^^^
+   |
+note: found these 'hi's
+  --> $DIR/multispan.rs:20:12
+   |
+LL |     hello!(hi hi hi);
+   |            ^^ ^^ ^^
+
+error: hello to you, too!
+  --> $DIR/multispan.rs:23:5
+   |
+LL |     hello!(hi hey hi yo hi beep beep hi hi);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: found these 'hi's
+  --> $DIR/multispan.rs:23:12
+   |
+LL |     hello!(hi hey hi yo hi beep beep hi hi);
+   |            ^^     ^^    ^^           ^^ ^^
+
+error: hello to you, too!
+  --> $DIR/multispan.rs:24:5
+   |
+LL |     hello!(hi there, hi how are you? hi... hi.);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: found these 'hi's
+  --> $DIR/multispan.rs:24:12
+   |
+LL |     hello!(hi there, hi how are you? hi... hi.);
+   |            ^^        ^^              ^^    ^^
+
+error: hello to you, too!
+  --> $DIR/multispan.rs:25:5
+   |
+LL |     hello!(whoah. hi di hi di ho);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: found these 'hi's
+  --> $DIR/multispan.rs:25:19
+   |
+LL |     hello!(whoah. hi di hi di ho);
+   |                   ^^    ^^
+
+error: hello to you, too!
+  --> $DIR/multispan.rs:26:5
+   |
+LL |     hello!(hi good hi and good bye);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: found these 'hi's
+  --> $DIR/multispan.rs:26:12
+   |
+LL |     hello!(hi good hi and good bye);
+   |            ^^      ^^
+
+error: aborting due to 7 previous errors
+
diff --git a/src/test/ui/proc-macro/nested-item-spans.rs b/src/test/ui/proc-macro/nested-item-spans.rs
new file mode 100644
index 0000000..e365b74
--- /dev/null
+++ b/src/test/ui/proc-macro/nested-item-spans.rs
@@ -0,0 +1,24 @@
+// aux-build:nested-item-spans.rs
+
+extern crate nested_item_spans;
+
+use nested_item_spans::foo;
+
+#[foo]
+fn another() {
+    fn bar() {
+        let x: u32 = "x"; //~ ERROR: mismatched types
+    }
+
+    bar();
+}
+
+fn main() {
+    #[foo]
+    fn bar() {
+        let x: u32 = "x"; //~ ERROR: mismatched types
+    }
+
+    bar();
+    another();
+}
diff --git a/src/test/ui/proc-macro/nested-item-spans.stderr b/src/test/ui/proc-macro/nested-item-spans.stderr
new file mode 100644
index 0000000..011a91d
--- /dev/null
+++ b/src/test/ui/proc-macro/nested-item-spans.stderr
@@ -0,0 +1,21 @@
+error[E0308]: mismatched types
+  --> $DIR/nested-item-spans.rs:10:22
+   |
+LL |         let x: u32 = "x";
+   |                      ^^^ expected u32, found reference
+   |
+   = note: expected type `u32`
+              found type `&'static str`
+
+error[E0308]: mismatched types
+  --> $DIR/nested-item-spans.rs:19:22
+   |
+LL |         let x: u32 = "x";
+   |                      ^^^ expected u32, found reference
+   |
+   = note: expected type `u32`
+              found type `&'static str`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/proc-macro/no-macro-use-attr.rs b/src/test/ui/proc-macro/no-macro-use-attr.rs
new file mode 100644
index 0000000..62a501d
--- /dev/null
+++ b/src/test/ui/proc-macro/no-macro-use-attr.rs
@@ -0,0 +1,10 @@
+// aux-build:derive-a.rs
+
+#![feature(rustc_attrs)]
+#![warn(unused_extern_crates)]
+
+extern crate derive_a;
+//~^ WARN unused extern crate
+
+#[rustc_error]
+fn main() {} //~ ERROR compilation successful
diff --git a/src/test/ui/proc-macro/no-macro-use-attr.stderr b/src/test/ui/proc-macro/no-macro-use-attr.stderr
new file mode 100644
index 0000000..4b2fce7
--- /dev/null
+++ b/src/test/ui/proc-macro/no-macro-use-attr.stderr
@@ -0,0 +1,20 @@
+warning: unused extern crate
+  --> $DIR/no-macro-use-attr.rs:6:1
+   |
+LL | extern crate derive_a;
+   | ^^^^^^^^^^^^^^^^^^^^^^ help: remove it
+   |
+note: lint level defined here
+  --> $DIR/no-macro-use-attr.rs:4:9
+   |
+LL | #![warn(unused_extern_crates)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: compilation successful
+  --> $DIR/no-macro-use-attr.rs:10:1
+   |
+LL | fn main() {}
+   | ^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/proc-macro/non-root.rs b/src/test/ui/proc-macro/non-root.rs
new file mode 100644
index 0000000..a7c4ac0
--- /dev/null
+++ b/src/test/ui/proc-macro/non-root.rs
@@ -0,0 +1,15 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::*;
+
+fn foo(arg: TokenStream) -> TokenStream {
+    #[proc_macro]
+    pub fn foo(arg: TokenStream) -> TokenStream { arg }
+    //~^ ERROR functions tagged with `#[proc_macro]` must currently reside in the root of the crate
+
+    arg
+}
diff --git a/src/test/ui/proc-macro/non-root.stderr b/src/test/ui/proc-macro/non-root.stderr
new file mode 100644
index 0000000..8f84dde
--- /dev/null
+++ b/src/test/ui/proc-macro/non-root.stderr
@@ -0,0 +1,8 @@
+error: functions tagged with `#[proc_macro]` must currently reside in the root of the crate
+  --> $DIR/non-root.rs:11:5
+   |
+LL |     pub fn foo(arg: TokenStream) -> TokenStream { arg }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/proc-macro/parent-source-spans.rs b/src/test/ui/proc-macro/parent-source-spans.rs
new file mode 100644
index 0000000..799f1de
--- /dev/null
+++ b/src/test/ui/proc-macro/parent-source-spans.rs
@@ -0,0 +1,54 @@
+// aux-build:parent-source-spans.rs
+
+
+#![feature(decl_macro, proc_macro_hygiene)]
+
+extern crate parent_source_spans;
+
+use parent_source_spans::parent_source_spans;
+
+macro one($a:expr, $b:expr) {
+    two!($a, $b);
+    //~^ ERROR first parent: "hello"
+    //~| ERROR second parent: "world"
+}
+
+macro two($a:expr, $b:expr) {
+    three!($a, $b);
+    //~^ ERROR first final: "hello"
+    //~| ERROR second final: "world"
+    //~| ERROR first final: "yay"
+    //~| ERROR second final: "rust"
+}
+
+// forwarding tokens directly doesn't create a new source chain
+macro three($($tokens:tt)*) {
+    four!($($tokens)*);
+}
+
+macro four($($tokens:tt)*) {
+    parent_source_spans!($($tokens)*);
+    //~^ ERROR cannot find value `ok` in this scope
+    //~| ERROR cannot find value `ok` in this scope
+    //~| ERROR cannot find value `ok` in this scope
+}
+
+fn main() {
+    one!("hello", "world");
+    //~^ ERROR first grandparent: "hello"
+    //~| ERROR second grandparent: "world"
+    //~| ERROR first source: "hello"
+    //~| ERROR second source: "world"
+
+    two!("yay", "rust");
+    //~^ ERROR first parent: "yay"
+    //~| ERROR second parent: "rust"
+    //~| ERROR first source: "yay"
+    //~| ERROR second source: "rust"
+
+    three!("hip", "hop");
+    //~^ ERROR first final: "hip"
+    //~| ERROR second final: "hop"
+    //~| ERROR first source: "hip"
+    //~| ERROR second source: "hop"
+}
diff --git a/src/test/ui/proc-macro/parent-source-spans.stderr b/src/test/ui/proc-macro/parent-source-spans.stderr
new file mode 100644
index 0000000..4231225
--- /dev/null
+++ b/src/test/ui/proc-macro/parent-source-spans.stderr
@@ -0,0 +1,156 @@
+error: first final: "hello"
+  --> $DIR/parent-source-spans.rs:17:12
+   |
+LL |     three!($a, $b);
+   |            ^^
+...
+LL |     one!("hello", "world");
+   |     ----------------------- in this macro invocation
+
+error: second final: "world"
+  --> $DIR/parent-source-spans.rs:17:16
+   |
+LL |     three!($a, $b);
+   |                ^^
+...
+LL |     one!("hello", "world");
+   |     ----------------------- in this macro invocation
+
+error: first parent: "hello"
+  --> $DIR/parent-source-spans.rs:11:5
+   |
+LL |     two!($a, $b);
+   |     ^^^^^^^^^^^^^
+...
+LL |     one!("hello", "world");
+   |     ----------------------- in this macro invocation
+
+error: second parent: "world"
+  --> $DIR/parent-source-spans.rs:11:5
+   |
+LL |     two!($a, $b);
+   |     ^^^^^^^^^^^^^
+...
+LL |     one!("hello", "world");
+   |     ----------------------- in this macro invocation
+
+error: first grandparent: "hello"
+  --> $DIR/parent-source-spans.rs:37:5
+   |
+LL |     one!("hello", "world");
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: second grandparent: "world"
+  --> $DIR/parent-source-spans.rs:37:5
+   |
+LL |     one!("hello", "world");
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: first source: "hello"
+  --> $DIR/parent-source-spans.rs:37:5
+   |
+LL |     one!("hello", "world");
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: second source: "world"
+  --> $DIR/parent-source-spans.rs:37:5
+   |
+LL |     one!("hello", "world");
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: first final: "yay"
+  --> $DIR/parent-source-spans.rs:17:12
+   |
+LL |     three!($a, $b);
+   |            ^^
+...
+LL |     two!("yay", "rust");
+   |     -------------------- in this macro invocation
+
+error: second final: "rust"
+  --> $DIR/parent-source-spans.rs:17:16
+   |
+LL |     three!($a, $b);
+   |                ^^
+...
+LL |     two!("yay", "rust");
+   |     -------------------- in this macro invocation
+
+error: first parent: "yay"
+  --> $DIR/parent-source-spans.rs:43:5
+   |
+LL |     two!("yay", "rust");
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: second parent: "rust"
+  --> $DIR/parent-source-spans.rs:43:5
+   |
+LL |     two!("yay", "rust");
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: first source: "yay"
+  --> $DIR/parent-source-spans.rs:43:5
+   |
+LL |     two!("yay", "rust");
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: second source: "rust"
+  --> $DIR/parent-source-spans.rs:43:5
+   |
+LL |     two!("yay", "rust");
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: first final: "hip"
+  --> $DIR/parent-source-spans.rs:49:12
+   |
+LL |     three!("hip", "hop");
+   |            ^^^^^
+
+error: second final: "hop"
+  --> $DIR/parent-source-spans.rs:49:19
+   |
+LL |     three!("hip", "hop");
+   |                   ^^^^^
+
+error: first source: "hip"
+  --> $DIR/parent-source-spans.rs:49:12
+   |
+LL |     three!("hip", "hop");
+   |            ^^^^^
+
+error: second source: "hop"
+  --> $DIR/parent-source-spans.rs:49:19
+   |
+LL |     three!("hip", "hop");
+   |                   ^^^^^
+
+error[E0425]: cannot find value `ok` in this scope
+  --> $DIR/parent-source-spans.rs:30:5
+   |
+LL |     parent_source_spans!($($tokens)*);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: a tuple variant with a similar name exists: `Ok`
+...
+LL |     one!("hello", "world");
+   |     ----------------------- in this macro invocation
+
+error[E0425]: cannot find value `ok` in this scope
+  --> $DIR/parent-source-spans.rs:30:5
+   |
+LL |     parent_source_spans!($($tokens)*);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: a tuple variant with a similar name exists: `Ok`
+...
+LL |     two!("yay", "rust");
+   |     -------------------- in this macro invocation
+
+error[E0425]: cannot find value `ok` in this scope
+  --> $DIR/parent-source-spans.rs:30:5
+   |
+LL |     parent_source_spans!($($tokens)*);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: a tuple variant with a similar name exists: `Ok`
+...
+LL |     three!("hip", "hop");
+   |     --------------------- in this macro invocation
+
+error: aborting due to 21 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/proc-macro/proc-macro-attributes.rs b/src/test/ui/proc-macro/proc-macro-attributes.rs
new file mode 100644
index 0000000..0620534
--- /dev/null
+++ b/src/test/ui/proc-macro/proc-macro-attributes.rs
@@ -0,0 +1,14 @@
+// aux-build:derive-b.rs
+
+#[macro_use]
+extern crate derive_b;
+
+#[B] //~ ERROR `B` is ambiguous
+#[C] //~ ERROR attribute `C` is currently unknown to the compiler
+#[B(D)] //~ ERROR `B` is ambiguous
+#[B(E = "foo")] //~ ERROR `B` is ambiguous
+#[B(arbitrary tokens)] //~ ERROR `B` is ambiguous
+#[derive(B)]
+struct B;
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/proc-macro-attributes.stderr b/src/test/ui/proc-macro/proc-macro-attributes.stderr
new file mode 100644
index 0000000..f8f1e7c
--- /dev/null
+++ b/src/test/ui/proc-macro/proc-macro-attributes.stderr
@@ -0,0 +1,80 @@
+error[E0658]: The attribute `C` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/proc-macro-attributes.rs:7:3
+   |
+LL | #[C]
+   |   ^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error[E0659]: `B` is ambiguous (derive helper attribute vs any other name)
+  --> $DIR/proc-macro-attributes.rs:6:3
+   |
+LL | #[B]
+   |   ^ ambiguous name
+   |
+note: `B` could refer to the derive helper attribute defined here
+  --> $DIR/proc-macro-attributes.rs:11:10
+   |
+LL | #[derive(B)]
+   |          ^
+note: `B` could also refer to the derive macro imported here
+  --> $DIR/proc-macro-attributes.rs:3:1
+   |
+LL | #[macro_use]
+   | ^^^^^^^^^^^^
+
+error[E0659]: `B` is ambiguous (derive helper attribute vs any other name)
+  --> $DIR/proc-macro-attributes.rs:8:3
+   |
+LL | #[B(D)]
+   |   ^ ambiguous name
+   |
+note: `B` could refer to the derive helper attribute defined here
+  --> $DIR/proc-macro-attributes.rs:11:10
+   |
+LL | #[derive(B)]
+   |          ^
+note: `B` could also refer to the derive macro imported here
+  --> $DIR/proc-macro-attributes.rs:3:1
+   |
+LL | #[macro_use]
+   | ^^^^^^^^^^^^
+
+error[E0659]: `B` is ambiguous (derive helper attribute vs any other name)
+  --> $DIR/proc-macro-attributes.rs:9:3
+   |
+LL | #[B(E = "foo")]
+   |   ^ ambiguous name
+   |
+note: `B` could refer to the derive helper attribute defined here
+  --> $DIR/proc-macro-attributes.rs:11:10
+   |
+LL | #[derive(B)]
+   |          ^
+note: `B` could also refer to the derive macro imported here
+  --> $DIR/proc-macro-attributes.rs:3:1
+   |
+LL | #[macro_use]
+   | ^^^^^^^^^^^^
+
+error[E0659]: `B` is ambiguous (derive helper attribute vs any other name)
+  --> $DIR/proc-macro-attributes.rs:10:3
+   |
+LL | #[B(arbitrary tokens)]
+   |   ^ ambiguous name
+   |
+note: `B` could refer to the derive helper attribute defined here
+  --> $DIR/proc-macro-attributes.rs:11:10
+   |
+LL | #[derive(B)]
+   |          ^
+note: `B` could also refer to the derive macro imported here
+  --> $DIR/proc-macro-attributes.rs:3:1
+   |
+LL | #[macro_use]
+   | ^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
+
+Some errors occurred: E0658, E0659.
+For more information about an error, try `rustc --explain E0658`.
diff --git a/src/test/ui/proc-macro/proc-macro-gates.rs b/src/test/ui/proc-macro/proc-macro-gates.rs
new file mode 100644
index 0000000..af6bfa0
--- /dev/null
+++ b/src/test/ui/proc-macro/proc-macro-gates.rs
@@ -0,0 +1,61 @@
+// aux-build:proc-macro-gates.rs
+// gate-test-proc_macro_hygiene
+
+#![feature(stmt_expr_attributes)]
+
+extern crate proc_macro_gates as foo;
+
+use foo::*;
+
+fn _test_inner() {
+    #![a] //~ ERROR: non-builtin inner attributes are unstable
+}
+
+#[a] //~ ERROR: custom attributes cannot be applied to modules
+mod _test2 {}
+
+mod _test2_inner {
+    #![a] //~ ERROR: custom attributes cannot be applied to modules
+          //~| ERROR: non-builtin inner attributes are unstable
+}
+
+#[a = "y"] //~ ERROR: must only be followed by a delimiter token
+fn _test3() {}
+
+fn attrs() {
+    // Statement, item
+    #[a] // OK
+    struct S;
+
+    // Statement, macro
+    #[a] //~ ERROR: custom attributes cannot be applied to statements
+    println!();
+
+    // Statement, semi
+    #[a] //~ ERROR: custom attributes cannot be applied to statements
+    S;
+
+    // Statement, local
+    #[a] //~ ERROR: custom attributes cannot be applied to statements
+    let _x = 2;
+
+    // Expr
+    let _x = #[a] 2; //~ ERROR: custom attributes cannot be applied to expressions
+
+    // Opt expr
+    let _x = [#[a] 2]; //~ ERROR: custom attributes cannot be applied to expressions
+
+    // Expr macro
+    let _x = #[a] println!(); //~ ERROR: custom attributes cannot be applied to expressions
+}
+
+fn main() {
+    let _x: m!(u32) = 3; //~ ERROR: procedural macros cannot be expanded to types
+    if let m!(Some(_x)) = Some(3) {} //~ ERROR: procedural macros cannot be expanded to patterns
+
+    m!(struct S;); //~ ERROR: procedural macros cannot be expanded to statements
+    m!(let _x = 3;); //~ ERROR: procedural macros cannot be expanded to statements
+
+    let _x = m!(3); //~ ERROR: procedural macros cannot be expanded to expressions
+    let _x = [m!(3)]; //~ ERROR: procedural macros cannot be expanded to expressions
+}
diff --git a/src/test/ui/proc-macro/proc-macro-gates.stderr b/src/test/ui/proc-macro/proc-macro-gates.stderr
new file mode 100644
index 0000000..4ae8e63
--- /dev/null
+++ b/src/test/ui/proc-macro/proc-macro-gates.stderr
@@ -0,0 +1,137 @@
+error[E0658]: non-builtin inner attributes are unstable (see issue #54726)
+  --> $DIR/proc-macro-gates.rs:11:5
+   |
+LL |     #![a]
+   |     ^^^^^
+   |
+   = help: add #![feature(custom_inner_attributes)] to the crate attributes to enable
+
+error[E0658]: non-builtin inner attributes are unstable (see issue #54726)
+  --> $DIR/proc-macro-gates.rs:18:5
+   |
+LL |     #![a]
+   |     ^^^^^
+   |
+   = help: add #![feature(custom_inner_attributes)] to the crate attributes to enable
+
+error[E0658]: custom attributes cannot be applied to modules (see issue #54727)
+  --> $DIR/proc-macro-gates.rs:14:1
+   |
+LL | #[a]
+   | ^^^^
+   |
+   = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable
+
+error[E0658]: custom attributes cannot be applied to modules (see issue #54727)
+  --> $DIR/proc-macro-gates.rs:18:5
+   |
+LL |     #![a]
+   |     ^^^^^
+   |
+   = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable
+
+error: custom attribute invocations must be of the form #[foo] or #[foo(..)], the macro name must only be followed by a delimiter token
+  --> $DIR/proc-macro-gates.rs:22:1
+   |
+LL | #[a = "y"]
+   | ^^^^^^^^^^
+
+error[E0658]: custom attributes cannot be applied to statements (see issue #54727)
+  --> $DIR/proc-macro-gates.rs:31:5
+   |
+LL |     #[a]
+   |     ^^^^
+   |
+   = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable
+
+error[E0658]: custom attributes cannot be applied to statements (see issue #54727)
+  --> $DIR/proc-macro-gates.rs:35:5
+   |
+LL |     #[a]
+   |     ^^^^
+   |
+   = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable
+
+error[E0658]: custom attributes cannot be applied to statements (see issue #54727)
+  --> $DIR/proc-macro-gates.rs:39:5
+   |
+LL |     #[a]
+   |     ^^^^
+   |
+   = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable
+
+error[E0658]: custom attributes cannot be applied to expressions (see issue #54727)
+  --> $DIR/proc-macro-gates.rs:43:14
+   |
+LL |     let _x = #[a] 2;
+   |              ^^^^
+   |
+   = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable
+
+error[E0658]: custom attributes cannot be applied to expressions (see issue #54727)
+  --> $DIR/proc-macro-gates.rs:46:15
+   |
+LL |     let _x = [#[a] 2];
+   |               ^^^^
+   |
+   = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable
+
+error[E0658]: custom attributes cannot be applied to expressions (see issue #54727)
+  --> $DIR/proc-macro-gates.rs:49:14
+   |
+LL |     let _x = #[a] println!();
+   |              ^^^^
+   |
+   = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable
+
+error[E0658]: procedural macros cannot be expanded to types (see issue #54727)
+  --> $DIR/proc-macro-gates.rs:53:13
+   |
+LL |     let _x: m!(u32) = 3;
+   |             ^^^^^^^
+   |
+   = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable
+
+error[E0658]: procedural macros cannot be expanded to patterns (see issue #54727)
+  --> $DIR/proc-macro-gates.rs:54:12
+   |
+LL |     if let m!(Some(_x)) = Some(3) {}
+   |            ^^^^^^^^^^^^
+   |
+   = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable
+
+error[E0658]: procedural macros cannot be expanded to statements (see issue #54727)
+  --> $DIR/proc-macro-gates.rs:56:5
+   |
+LL |     m!(struct S;);
+   |     ^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable
+
+error[E0658]: procedural macros cannot be expanded to statements (see issue #54727)
+  --> $DIR/proc-macro-gates.rs:57:5
+   |
+LL |     m!(let _x = 3;);
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable
+
+error[E0658]: procedural macros cannot be expanded to expressions (see issue #54727)
+  --> $DIR/proc-macro-gates.rs:59:14
+   |
+LL |     let _x = m!(3);
+   |              ^^^^^
+   |
+   = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable
+
+error[E0658]: procedural macros cannot be expanded to expressions (see issue #54727)
+  --> $DIR/proc-macro-gates.rs:60:15
+   |
+LL |     let _x = [m!(3)];
+   |               ^^^^^
+   |
+   = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable
+
+error: aborting due to 17 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/proc-macro/proc-macro-gates2.rs b/src/test/ui/proc-macro/proc-macro-gates2.rs
new file mode 100644
index 0000000..46b543a
--- /dev/null
+++ b/src/test/ui/proc-macro/proc-macro-gates2.rs
@@ -0,0 +1,25 @@
+// aux-build:proc-macro-gates.rs
+
+#![feature(stmt_expr_attributes)]
+
+extern crate proc_macro_gates as foo;
+
+use foo::*;
+
+// NB. these errors aren't the best errors right now, but they're definitely
+// intended to be errors. Somehow using a custom attribute in these positions
+// should either require a feature gate or not be allowed on stable.
+
+fn _test6<#[a] T>() {}
+//~^ ERROR: unknown to the compiler
+
+fn _test7() {
+    match 1 {
+        #[a] //~ ERROR: unknown to the compiler
+        0 => {}
+        _ => {}
+    }
+}
+
+fn main() {
+}
diff --git a/src/test/ui/proc-macro/proc-macro-gates2.stderr b/src/test/ui/proc-macro/proc-macro-gates2.stderr
new file mode 100644
index 0000000..89ad527
--- /dev/null
+++ b/src/test/ui/proc-macro/proc-macro-gates2.stderr
@@ -0,0 +1,19 @@
+error[E0658]: The attribute `a` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/proc-macro-gates2.rs:13:11
+   |
+LL | fn _test6<#[a] T>() {}
+   |           ^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error[E0658]: The attribute `a` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/proc-macro-gates2.rs:18:9
+   |
+LL |         #[a]
+   |         ^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/proc-macro/pub-at-crate-root.rs b/src/test/ui/proc-macro/pub-at-crate-root.rs
new file mode 100644
index 0000000..7544245
--- /dev/null
+++ b/src/test/ui/proc-macro/pub-at-crate-root.rs
@@ -0,0 +1,22 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+pub mod a { //~ `proc-macro` crate types cannot export any items
+    use proc_macro::TokenStream;
+
+    #[proc_macro_derive(B)]
+    pub fn bar(a: TokenStream) -> TokenStream {
+    //~^ ERROR: must currently reside in the root of the crate
+        a
+    }
+}
+
+#[proc_macro_derive(B)]
+fn bar(a: proc_macro::TokenStream) -> proc_macro::TokenStream {
+//~^ ERROR: functions tagged with `#[proc_macro_derive]` must be `pub`
+    a
+}
diff --git a/src/test/ui/proc-macro/pub-at-crate-root.stderr b/src/test/ui/proc-macro/pub-at-crate-root.stderr
new file mode 100644
index 0000000..66fa499
--- /dev/null
+++ b/src/test/ui/proc-macro/pub-at-crate-root.stderr
@@ -0,0 +1,32 @@
+error: `proc-macro` crate types cannot export any items other than functions tagged with `#[proc_macro_derive]` currently
+  --> $DIR/pub-at-crate-root.rs:8:1
+   |
+LL | / pub mod a {
+LL | |     use proc_macro::TokenStream;
+LL | |
+LL | |     #[proc_macro_derive(B)]
+...  |
+LL | |     }
+LL | | }
+   | |_^
+
+error: functions tagged with `#[proc_macro_derive]` must currently reside in the root of the crate
+  --> $DIR/pub-at-crate-root.rs:12:5
+   |
+LL | /     pub fn bar(a: TokenStream) -> TokenStream {
+LL | |
+LL | |         a
+LL | |     }
+   | |_____^
+
+error: functions tagged with `#[proc_macro_derive]` must be `pub`
+  --> $DIR/pub-at-crate-root.rs:19:1
+   |
+LL | / fn bar(a: proc_macro::TokenStream) -> proc_macro::TokenStream {
+LL | |
+LL | |     a
+LL | | }
+   | |_^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/proc-macro/reserved-macro-names.rs b/src/test/ui/proc-macro/reserved-macro-names.rs
new file mode 100644
index 0000000..7c66af1
--- /dev/null
+++ b/src/test/ui/proc-macro/reserved-macro-names.rs
@@ -0,0 +1,25 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::*;
+
+#[proc_macro_attribute]
+pub fn cfg(_: TokenStream, input: TokenStream) -> TokenStream {
+    //~^ ERROR name `cfg` is reserved in macro namespace
+    input
+}
+
+#[proc_macro_attribute]
+pub fn cfg_attr(_: TokenStream, input: TokenStream) -> TokenStream {
+    //~^ ERROR name `cfg_attr` is reserved in macro namespace
+    input
+}
+
+#[proc_macro_attribute]
+pub fn derive(_: TokenStream, input: TokenStream) -> TokenStream {
+    //~^ ERROR name `derive` is reserved in macro namespace
+    input
+}
diff --git a/src/test/ui/proc-macro/reserved-macro-names.stderr b/src/test/ui/proc-macro/reserved-macro-names.stderr
new file mode 100644
index 0000000..5ebe62a
--- /dev/null
+++ b/src/test/ui/proc-macro/reserved-macro-names.stderr
@@ -0,0 +1,20 @@
+error: name `cfg` is reserved in macro namespace
+  --> $DIR/reserved-macro-names.rs:10:8
+   |
+LL | pub fn cfg(_: TokenStream, input: TokenStream) -> TokenStream {
+   |        ^^^
+
+error: name `cfg_attr` is reserved in macro namespace
+  --> $DIR/reserved-macro-names.rs:16:8
+   |
+LL | pub fn cfg_attr(_: TokenStream, input: TokenStream) -> TokenStream {
+   |        ^^^^^^^^
+
+error: name `derive` is reserved in macro namespace
+  --> $DIR/reserved-macro-names.rs:22:8
+   |
+LL | pub fn derive(_: TokenStream, input: TokenStream) -> TokenStream {
+   |        ^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/proc-macro/resolve-error.rs b/src/test/ui/proc-macro/resolve-error.rs
new file mode 100644
index 0000000..bb242f3
--- /dev/null
+++ b/src/test/ui/proc-macro/resolve-error.rs
@@ -0,0 +1,60 @@
+// aux-build:derive-foo.rs
+// aux-build:derive-clona.rs
+// aux-build:attr_proc_macro.rs
+// aux-build:bang_proc_macro.rs
+
+#![feature(custom_attribute)]
+
+#[macro_use]
+extern crate derive_foo;
+#[macro_use]
+extern crate derive_clona;
+extern crate attr_proc_macro;
+extern crate bang_proc_macro;
+
+use attr_proc_macro::attr_proc_macro;
+use bang_proc_macro::bang_proc_macro;
+
+macro_rules! FooWithLongNam {
+    () => {}
+}
+
+macro_rules! attr_proc_mac {
+    () => {}
+}
+
+#[derive(FooWithLongNan)]
+//~^ ERROR cannot find
+struct Foo;
+
+#[attr_proc_macra] // OK, interpreted as a custom attribute
+struct Bar;
+
+#[FooWithLongNan]  // OK, interpreted as a custom attribute
+struct Asdf;
+
+#[derive(Dlone)]
+//~^ ERROR cannot find
+struct A;
+
+#[derive(Dlona)]
+//~^ ERROR cannot find
+struct B;
+
+#[derive(attr_proc_macra)]
+//~^ ERROR cannot find
+struct C;
+
+fn main() {
+    FooWithLongNama!();
+    //~^ ERROR cannot find
+
+    attr_proc_macra!();
+    //~^ ERROR cannot find
+
+    Dlona!();
+    //~^ ERROR cannot find
+
+    bang_proc_macrp!();
+    //~^ ERROR cannot find
+}
diff --git a/src/test/ui/proc-macro/resolve-error.stderr b/src/test/ui/proc-macro/resolve-error.stderr
new file mode 100644
index 0000000..cf7de57
--- /dev/null
+++ b/src/test/ui/proc-macro/resolve-error.stderr
@@ -0,0 +1,50 @@
+error: cannot find derive macro `FooWithLongNan` in this scope
+  --> $DIR/resolve-error.rs:26:10
+   |
+LL | #[derive(FooWithLongNan)]
+   |          ^^^^^^^^^^^^^^ help: try: `FooWithLongName`
+
+error: cannot find derive macro `Dlone` in this scope
+  --> $DIR/resolve-error.rs:36:10
+   |
+LL | #[derive(Dlone)]
+   |          ^^^^^ help: try: `Clone`
+
+error: cannot find derive macro `Dlona` in this scope
+  --> $DIR/resolve-error.rs:40:10
+   |
+LL | #[derive(Dlona)]
+   |          ^^^^^ help: try: `Clona`
+
+error: cannot find derive macro `attr_proc_macra` in this scope
+  --> $DIR/resolve-error.rs:44:10
+   |
+LL | #[derive(attr_proc_macra)]
+   |          ^^^^^^^^^^^^^^^
+
+error: cannot find macro `FooWithLongNama!` in this scope
+  --> $DIR/resolve-error.rs:49:5
+   |
+LL |     FooWithLongNama!();
+   |     ^^^^^^^^^^^^^^^ help: you could try the macro: `FooWithLongNam`
+
+error: cannot find macro `attr_proc_macra!` in this scope
+  --> $DIR/resolve-error.rs:52:5
+   |
+LL |     attr_proc_macra!();
+   |     ^^^^^^^^^^^^^^^ help: you could try the macro: `attr_proc_mac`
+
+error: cannot find macro `Dlona!` in this scope
+  --> $DIR/resolve-error.rs:55:5
+   |
+LL |     Dlona!();
+   |     ^^^^^
+
+error: cannot find macro `bang_proc_macrp!` in this scope
+  --> $DIR/resolve-error.rs:58:5
+   |
+LL |     bang_proc_macrp!();
+   |     ^^^^^^^^^^^^^^^ help: you could try the macro: `bang_proc_macro`
+
+error: aborting due to 8 previous errors
+
diff --git a/src/test/ui/proc-macro/shadow.rs b/src/test/ui/proc-macro/shadow.rs
new file mode 100644
index 0000000..9c49bae
--- /dev/null
+++ b/src/test/ui/proc-macro/shadow.rs
@@ -0,0 +1,8 @@
+// aux-build:derive-a.rs
+
+#[macro_use]
+extern crate derive_a;
+#[macro_use]
+extern crate derive_a; //~ ERROR the name `derive_a` is defined multiple times
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/shadow.stderr b/src/test/ui/proc-macro/shadow.stderr
new file mode 100644
index 0000000..08057e16
--- /dev/null
+++ b/src/test/ui/proc-macro/shadow.stderr
@@ -0,0 +1,14 @@
+error[E0259]: the name `derive_a` is defined multiple times
+  --> $DIR/shadow.rs:6:1
+   |
+LL | extern crate derive_a;
+   | ---------------------- previous import of the extern crate `derive_a` here
+LL | #[macro_use]
+LL | extern crate derive_a;
+   | ^^^^^^^^^^^^^^^^^^^^^^ `derive_a` reimported here
+   |
+   = note: `derive_a` must be defined only once in the type namespace of this module
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0259`.
diff --git a/src/test/ui/proc-macro/signature.rs b/src/test/ui/proc-macro/signature.rs
new file mode 100644
index 0000000..dbc1577
--- /dev/null
+++ b/src/test/ui/proc-macro/signature.rs
@@ -0,0 +1,13 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+#![allow(warnings)]
+
+extern crate proc_macro;
+
+#[proc_macro_derive(A)]
+pub unsafe extern fn foo(a: i32, b: u32) -> u32 {
+    //~^ ERROR: mismatched types
+    loop {}
+}
diff --git a/src/test/ui/proc-macro/signature.stderr b/src/test/ui/proc-macro/signature.stderr
new file mode 100644
index 0000000..4743e30
--- /dev/null
+++ b/src/test/ui/proc-macro/signature.stderr
@@ -0,0 +1,15 @@
+error[E0308]: mismatched types
+  --> $DIR/signature.rs:10:1
+   |
+LL | / pub unsafe extern fn foo(a: i32, b: u32) -> u32 {
+LL | |
+LL | |     loop {}
+LL | | }
+   | |_^ expected normal fn, found unsafe fn
+   |
+   = note: expected type `fn(proc_macro::TokenStream) -> proc_macro::TokenStream`
+              found type `unsafe extern "C" fn(i32, u32) -> u32 {foo}`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/proc-macro/span-preservation.rs b/src/test/ui/proc-macro/span-preservation.rs
new file mode 100644
index 0000000..64f675e
--- /dev/null
+++ b/src/test/ui/proc-macro/span-preservation.rs
@@ -0,0 +1,52 @@
+//~ ERROR mismatched types
+// aux-build:span-preservation.rs
+
+// For each of these, we should get the appropriate type mismatch error message,
+// and the function should be echoed.
+
+extern crate span_preservation as foo;
+
+use foo::foo;
+
+#[foo]
+fn a() {
+    let x: usize = "hello";;;;; //~ ERROR mismatched types
+}
+
+#[foo]
+fn b(x: Option<isize>) -> usize {
+    match x {
+        Some(x) => { return x }, //~ ERROR mismatched types
+        None => 10
+    }
+}
+
+#[foo]
+fn c() {
+    struct Foo {
+        a: usize
+    }
+
+    struct Bar {
+        a: usize,
+        b: usize
+    }
+
+    let x = Foo { a: 10isize }; //~ ERROR mismatched types
+    let y = Foo { a: 10, b: 10isize }; //~ ERROR has no field named `b`
+}
+
+// FIXME: This doesn't work at the moment. See the one below. The pretty-printer
+// injects a "C" between `extern` and `fn` which causes a "probably_eq"
+// `TokenStream` mismatch. The lack of `"C"` should be preserved in the AST.
+#[foo]
+extern fn bar() {
+    0
+}
+
+#[foo]
+extern "C" fn baz() {
+    0 //~ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/span-preservation.stderr b/src/test/ui/proc-macro/span-preservation.stderr
new file mode 100644
index 0000000..fbccde2
--- /dev/null
+++ b/src/test/ui/proc-macro/span-preservation.stderr
@@ -0,0 +1,52 @@
+error[E0308]: mismatched types
+   |
+   = note: expected type `()`
+              found type `{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/span-preservation.rs:13:20
+   |
+LL |     let x: usize = "hello";;;;;
+   |                    ^^^^^^^ expected usize, found reference
+   |
+   = note: expected type `usize`
+              found type `&'static str`
+
+error[E0308]: mismatched types
+  --> $DIR/span-preservation.rs:19:29
+   |
+LL | fn b(x: Option<isize>) -> usize {
+   |                           ----- expected `usize` because of return type
+LL |     match x {
+LL |         Some(x) => { return x },
+   |                             ^ expected usize, found isize
+
+error[E0308]: mismatched types
+  --> $DIR/span-preservation.rs:35:22
+   |
+LL |     let x = Foo { a: 10isize };
+   |                      ^^^^^^^ expected usize, found isize
+
+error[E0560]: struct `c::Foo` has no field named `b`
+  --> $DIR/span-preservation.rs:36:26
+   |
+LL |     let y = Foo { a: 10, b: 10isize };
+   |                          ^ `c::Foo` does not have this field
+   |
+   = note: available fields are: `a`
+
+error[E0308]: mismatched types
+  --> $DIR/span-preservation.rs:49:5
+   |
+LL | extern "C" fn baz() {
+   |                     - possibly return type missing here?
+LL |     0
+   |     ^ expected (), found integer
+   |
+   = note: expected type `()`
+              found type `{integer}`
+
+error: aborting due to 6 previous errors
+
+Some errors occurred: E0308, E0560.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/proc-macro/subspan.rs b/src/test/ui/proc-macro/subspan.rs
new file mode 100644
index 0000000..a4187f9
--- /dev/null
+++ b/src/test/ui/proc-macro/subspan.rs
@@ -0,0 +1,26 @@
+// aux-build:subspan.rs
+
+extern crate subspan;
+
+use subspan::subspan;
+
+// This one emits no error.
+subspan!("");
+
+// Exactly one 'hi'.
+subspan!("hi"); //~ ERROR found 'hi's
+
+// Now two, back to back.
+subspan!("hihi"); //~ ERROR found 'hi's
+
+// Now three, back to back.
+subspan!("hihihi"); //~ ERROR found 'hi's
+
+// Now several, with spacing.
+subspan!("why I hide? hi!"); //~ ERROR found 'hi's
+subspan!("hey, hi, hidy, hidy, hi hi"); //~ ERROR found 'hi's
+subspan!("this is a hi, and this is another hi"); //~ ERROR found 'hi's
+subspan!("how are you this evening"); //~ ERROR found 'hi's
+subspan!("this is highly eradic"); //~ ERROR found 'hi's
+
+fn main() { }
diff --git a/src/test/ui/proc-macro/subspan.stderr b/src/test/ui/proc-macro/subspan.stderr
new file mode 100644
index 0000000..5117dd6d
--- /dev/null
+++ b/src/test/ui/proc-macro/subspan.stderr
@@ -0,0 +1,98 @@
+error: found 'hi's
+  --> $DIR/subspan.rs:11:1
+   |
+LL | subspan!("hi");
+   | ^^^^^^^^^^^^^^^
+   |
+note: here
+  --> $DIR/subspan.rs:11:11
+   |
+LL | subspan!("hi");
+   |           ^^
+
+error: found 'hi's
+  --> $DIR/subspan.rs:14:1
+   |
+LL | subspan!("hihi");
+   | ^^^^^^^^^^^^^^^^^
+   |
+note: here
+  --> $DIR/subspan.rs:14:11
+   |
+LL | subspan!("hihi");
+   |           ^^^^
+
+error: found 'hi's
+  --> $DIR/subspan.rs:17:1
+   |
+LL | subspan!("hihihi");
+   | ^^^^^^^^^^^^^^^^^^^
+   |
+note: here
+  --> $DIR/subspan.rs:17:11
+   |
+LL | subspan!("hihihi");
+   |           ^^^^^^
+
+error: found 'hi's
+  --> $DIR/subspan.rs:20:1
+   |
+LL | subspan!("why I hide? hi!");
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: here
+  --> $DIR/subspan.rs:20:17
+   |
+LL | subspan!("why I hide? hi!");
+   |                 ^^    ^^
+
+error: found 'hi's
+  --> $DIR/subspan.rs:21:1
+   |
+LL | subspan!("hey, hi, hidy, hidy, hi hi");
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: here
+  --> $DIR/subspan.rs:21:16
+   |
+LL | subspan!("hey, hi, hidy, hidy, hi hi");
+   |                ^^  ^^    ^^    ^^ ^^
+
+error: found 'hi's
+  --> $DIR/subspan.rs:22:1
+   |
+LL | subspan!("this is a hi, and this is another hi");
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: here
+  --> $DIR/subspan.rs:22:12
+   |
+LL | subspan!("this is a hi, and this is another hi");
+   |            ^^       ^^       ^^             ^^
+
+error: found 'hi's
+  --> $DIR/subspan.rs:23:1
+   |
+LL | subspan!("how are you this evening");
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: here
+  --> $DIR/subspan.rs:23:24
+   |
+LL | subspan!("how are you this evening");
+   |                        ^^
+
+error: found 'hi's
+  --> $DIR/subspan.rs:24:1
+   |
+LL | subspan!("this is highly eradic");
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: here
+  --> $DIR/subspan.rs:24:12
+   |
+LL | subspan!("this is highly eradic");
+   |            ^^     ^^
+
+error: aborting due to 8 previous errors
+
diff --git a/src/test/ui/proc-macro/three-equals.rs b/src/test/ui/proc-macro/three-equals.rs
new file mode 100644
index 0000000..50a144f
--- /dev/null
+++ b/src/test/ui/proc-macro/three-equals.rs
@@ -0,0 +1,28 @@
+// aux-build:three-equals.rs
+
+
+#![feature(proc_macro_hygiene)]
+
+extern crate three_equals;
+
+use three_equals::three_equals;
+
+fn main() {
+    // This one is okay.
+    three_equals!(===);
+
+    // Need exactly three equals.
+    three_equals!(==); //~ ERROR found 2 equal signs, need exactly 3
+
+    // Need exactly three equals.
+    three_equals!(=====); //~ ERROR expected EOF
+
+    // Only equals accepted.
+    three_equals!(abc); //~ ERROR expected `=`
+
+    // Only equals accepted.
+    three_equals!(!!); //~ ERROR expected `=`
+
+    // Only three characters expected.
+    three_equals!(===a); //~ ERROR expected EOF
+}
diff --git a/src/test/ui/proc-macro/three-equals.stderr b/src/test/ui/proc-macro/three-equals.stderr
new file mode 100644
index 0000000..f8dfa84
--- /dev/null
+++ b/src/test/ui/proc-macro/three-equals.stderr
@@ -0,0 +1,48 @@
+error: found 2 equal signs, need exactly 3
+  --> $DIR/three-equals.rs:15:5
+   |
+LL |     three_equals!(==);
+   |     ^^^^^^^^^^^^^^^^^^
+   |
+   = help: input must be: `===`
+
+error: expected EOF, found `=`.
+  --> $DIR/three-equals.rs:18:21
+   |
+LL |     three_equals!(=====);
+   |                     ^^
+   |
+note: last good input was here
+  --> $DIR/three-equals.rs:18:21
+   |
+LL |     three_equals!(=====);
+   |                     ^^
+   = help: input must be: `===`
+
+error: expected `=`, found `abc`.
+  --> $DIR/three-equals.rs:21:19
+   |
+LL |     three_equals!(abc);
+   |                   ^^^
+
+error: expected `=`, found `!`.
+  --> $DIR/three-equals.rs:24:19
+   |
+LL |     three_equals!(!!);
+   |                   ^
+
+error: expected EOF, found `a`.
+  --> $DIR/three-equals.rs:27:22
+   |
+LL |     three_equals!(===a);
+   |                      ^
+   |
+note: last good input was here
+  --> $DIR/three-equals.rs:27:21
+   |
+LL |     three_equals!(===a);
+   |                     ^
+   = help: input must be: `===`
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/ui/proc-macro/two-crate-types-1.rs b/src/test/ui/proc-macro/two-crate-types-1.rs
new file mode 100644
index 0000000..80bfd35
--- /dev/null
+++ b/src/test/ui/proc-macro/two-crate-types-1.rs
@@ -0,0 +1,7 @@
+// error-pattern: cannot mix `proc-macro` crate type with others
+
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+#![crate_type = "rlib"]
diff --git a/src/test/ui/proc-macro/two-crate-types-1.stderr b/src/test/ui/proc-macro/two-crate-types-1.stderr
new file mode 100644
index 0000000..deaba1c
--- /dev/null
+++ b/src/test/ui/proc-macro/two-crate-types-1.stderr
@@ -0,0 +1,4 @@
+error: cannot mix `proc-macro` crate type with others
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/proc-macro/two-crate-types-2.rs b/src/test/ui/proc-macro/two-crate-types-2.rs
new file mode 100644
index 0000000..39cbf7d
--- /dev/null
+++ b/src/test/ui/proc-macro/two-crate-types-2.rs
@@ -0,0 +1,3 @@
+// error-pattern: cannot mix `proc-macro` crate type with others
+// compile-flags: --crate-type rlib --crate-type proc-macro
+// force-host
diff --git a/src/test/ui/proc-macro/two-crate-types-2.stderr b/src/test/ui/proc-macro/two-crate-types-2.stderr
new file mode 100644
index 0000000..deaba1c
--- /dev/null
+++ b/src/test/ui/proc-macro/two-crate-types-2.stderr
@@ -0,0 +1,4 @@
+error: cannot mix `proc-macro` crate type with others
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/ptr-coercion.rs b/src/test/ui/ptr-coercion.rs
new file mode 100644
index 0000000..d1ef88b
--- /dev/null
+++ b/src/test/ui/ptr-coercion.rs
@@ -0,0 +1,23 @@
+// Test coercions between pointers which don't do anything fancy like unsizing.
+// These are testing that we don't lose mutability when converting to raw pointers.
+
+pub fn main() {
+    // *const -> *mut
+    let x: *const isize = &42;
+    let x: *mut isize = x; //~  ERROR mismatched types
+                           //~| expected type `*mut isize`
+                           //~| found type `*const isize`
+                           //~| types differ in mutability
+
+    // & -> *mut
+    let x: *mut isize = &42; //~  ERROR mismatched types
+                             //~| expected type `*mut isize`
+                             //~| found type `&isize`
+                             //~| types differ in mutability
+
+    let x: *const isize = &42;
+    let x: *mut isize = x; //~  ERROR mismatched types
+                           //~| expected type `*mut isize`
+                           //~| found type `*const isize`
+                           //~| types differ in mutability
+}
diff --git a/src/test/ui/ptr-coercion.stderr b/src/test/ui/ptr-coercion.stderr
new file mode 100644
index 0000000..019241d
--- /dev/null
+++ b/src/test/ui/ptr-coercion.stderr
@@ -0,0 +1,30 @@
+error[E0308]: mismatched types
+  --> $DIR/ptr-coercion.rs:7:25
+   |
+LL |     let x: *mut isize = x;
+   |                         ^ types differ in mutability
+   |
+   = note: expected type `*mut isize`
+              found type `*const isize`
+
+error[E0308]: mismatched types
+  --> $DIR/ptr-coercion.rs:13:25
+   |
+LL |     let x: *mut isize = &42;
+   |                         ^^^ types differ in mutability
+   |
+   = note: expected type `*mut isize`
+              found type `&isize`
+
+error[E0308]: mismatched types
+  --> $DIR/ptr-coercion.rs:19:25
+   |
+LL |     let x: *mut isize = x;
+   |                         ^ types differ in mutability
+   |
+   = note: expected type `*mut isize`
+              found type `*const isize`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/pub/issue-33174-restricted-type-in-public-interface.rs b/src/test/ui/pub/issue-33174-restricted-type-in-public-interface.rs
new file mode 100644
index 0000000..45dfb63
--- /dev/null
+++ b/src/test/ui/pub/issue-33174-restricted-type-in-public-interface.rs
@@ -0,0 +1,28 @@
+#![allow(non_camel_case_types)]  // genus is always capitalized
+
+pub(crate) struct Snail;
+//~^ NOTE `Snail` declared as crate-visible
+
+mod sea {
+    pub(super) struct Turtle;
+    //~^ NOTE `sea::Turtle` declared as restricted
+}
+
+struct Tortoise;
+//~^ NOTE `Tortoise` declared as private
+
+pub struct Shell<T> {
+    pub(crate) creature: T,
+}
+
+pub type Helix_pomatia = Shell<Snail>;
+//~^ ERROR crate-visible type `Snail` in public interface
+//~| NOTE can't leak crate-visible type
+pub type Dermochelys_coriacea = Shell<sea::Turtle>;
+//~^ ERROR restricted type `sea::Turtle` in public interface
+//~| NOTE can't leak restricted type
+pub type Testudo_graeca = Shell<Tortoise>;
+//~^ ERROR private type `Tortoise` in public interface
+//~| NOTE can't leak private type
+
+fn main() {}
diff --git a/src/test/ui/pub/issue-33174-restricted-type-in-public-interface.stderr b/src/test/ui/pub/issue-33174-restricted-type-in-public-interface.stderr
new file mode 100644
index 0000000..ae9a33e
--- /dev/null
+++ b/src/test/ui/pub/issue-33174-restricted-type-in-public-interface.stderr
@@ -0,0 +1,30 @@
+error[E0446]: crate-visible type `Snail` in public interface
+  --> $DIR/issue-33174-restricted-type-in-public-interface.rs:18:1
+   |
+LL | pub(crate) struct Snail;
+   | ---------- `Snail` declared as crate-visible
+...
+LL | pub type Helix_pomatia = Shell<Snail>;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak crate-visible type
+
+error[E0446]: restricted type `sea::Turtle` in public interface
+  --> $DIR/issue-33174-restricted-type-in-public-interface.rs:21:1
+   |
+LL |     pub(super) struct Turtle;
+   |     ---------- `sea::Turtle` declared as restricted
+...
+LL | pub type Dermochelys_coriacea = Shell<sea::Turtle>;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak restricted type
+
+error[E0446]: private type `Tortoise` in public interface
+  --> $DIR/issue-33174-restricted-type-in-public-interface.rs:24:1
+   |
+LL | struct Tortoise;
+   | - `Tortoise` declared as private
+...
+LL | pub type Testudo_graeca = Shell<Tortoise>;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0446`.
diff --git a/src/test/ui/pub/pub-ident-fn-2.rs b/src/test/ui/pub/pub-ident-fn-2.rs
new file mode 100644
index 0000000..e1fc20c
--- /dev/null
+++ b/src/test/ui/pub/pub-ident-fn-2.rs
@@ -0,0 +1,6 @@
+pub foo(s: usize) { bar() }
+//~^ ERROR missing `fn` for function definition
+
+fn main() {
+    foo(2);
+}
diff --git a/src/test/ui/pub/pub-ident-fn-2.stderr b/src/test/ui/pub/pub-ident-fn-2.stderr
new file mode 100644
index 0000000..69b273d
--- /dev/null
+++ b/src/test/ui/pub/pub-ident-fn-2.stderr
@@ -0,0 +1,12 @@
+error: missing `fn` for function definition
+  --> $DIR/pub-ident-fn-2.rs:1:4
+   |
+LL | pub foo(s: usize) { bar() }
+   |    ^
+help: add `fn` here to parse `foo` as a public function
+   |
+LL | pub fn foo(s: usize) { bar() }
+   |     ^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/pub/pub-ident-fn-or-struct-2.rs b/src/test/ui/pub/pub-ident-fn-or-struct-2.rs
new file mode 100644
index 0000000..8f67cdd
--- /dev/null
+++ b/src/test/ui/pub/pub-ident-fn-or-struct-2.rs
@@ -0,0 +1,4 @@
+pub S();
+//~^ ERROR missing `fn` or `struct` for function or struct definition
+
+fn main() {}
diff --git a/src/test/ui/pub/pub-ident-fn-or-struct-2.stderr b/src/test/ui/pub/pub-ident-fn-or-struct-2.stderr
new file mode 100644
index 0000000..047e66b
--- /dev/null
+++ b/src/test/ui/pub/pub-ident-fn-or-struct-2.stderr
@@ -0,0 +1,8 @@
+error: missing `fn` or `struct` for function or struct definition
+  --> $DIR/pub-ident-fn-or-struct-2.rs:1:4
+   |
+LL | pub S();
+   | ---^- help: if you meant to call a macro, try: `S!`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/pub/pub-ident-fn-or-struct.rs b/src/test/ui/pub/pub-ident-fn-or-struct.rs
new file mode 100644
index 0000000..832831d
--- /dev/null
+++ b/src/test/ui/pub/pub-ident-fn-or-struct.rs
@@ -0,0 +1,4 @@
+pub S (foo) bar
+//~^ ERROR missing `fn` or `struct` for function or struct definition
+
+fn main() {}
diff --git a/src/test/ui/pub/pub-ident-fn-or-struct.stderr b/src/test/ui/pub/pub-ident-fn-or-struct.stderr
new file mode 100644
index 0000000..c4a196e
--- /dev/null
+++ b/src/test/ui/pub/pub-ident-fn-or-struct.stderr
@@ -0,0 +1,8 @@
+error: missing `fn` or `struct` for function or struct definition
+  --> $DIR/pub-ident-fn-or-struct.rs:1:4
+   |
+LL | pub S (foo) bar
+   | ---^- help: if you meant to call a macro, try: `S!`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/pub/pub-ident-fn-with-lifetime-2.rs b/src/test/ui/pub/pub-ident-fn-with-lifetime-2.rs
new file mode 100644
index 0000000..1ee8c84
--- /dev/null
+++ b/src/test/ui/pub/pub-ident-fn-with-lifetime-2.rs
@@ -0,0 +1,6 @@
+pub   bar<'a>(&self, _s: &'a usize) -> bool { true }
+//~^ ERROR missing `fn` for method definition
+
+fn main() {
+    bar(2);
+}
diff --git a/src/test/ui/pub/pub-ident-fn-with-lifetime-2.stderr b/src/test/ui/pub/pub-ident-fn-with-lifetime-2.stderr
new file mode 100644
index 0000000..c403774
--- /dev/null
+++ b/src/test/ui/pub/pub-ident-fn-with-lifetime-2.stderr
@@ -0,0 +1,12 @@
+error: missing `fn` for method definition
+  --> $DIR/pub-ident-fn-with-lifetime-2.rs:1:4
+   |
+LL | pub   bar<'a>(&self, _s: &'a usize) -> bool { true }
+   |    ^^^
+help: add `fn` here to parse `bar` as a public method
+   |
+LL | pub fn bar<'a>(&self, _s: &'a usize) -> bool { true }
+   |     ^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/pub/pub-ident-fn-with-lifetime.rs b/src/test/ui/pub/pub-ident-fn-with-lifetime.rs
new file mode 100644
index 0000000..84f7bdc
--- /dev/null
+++ b/src/test/ui/pub/pub-ident-fn-with-lifetime.rs
@@ -0,0 +1,6 @@
+pub   foo<'a>(_s: &'a usize) -> bool { true }
+//~^ ERROR missing `fn` for function definition
+
+fn main() {
+    foo(2);
+}
diff --git a/src/test/ui/pub/pub-ident-fn-with-lifetime.stderr b/src/test/ui/pub/pub-ident-fn-with-lifetime.stderr
new file mode 100644
index 0000000..8582380
--- /dev/null
+++ b/src/test/ui/pub/pub-ident-fn-with-lifetime.stderr
@@ -0,0 +1,12 @@
+error: missing `fn` for function definition
+  --> $DIR/pub-ident-fn-with-lifetime.rs:1:4
+   |
+LL | pub   foo<'a>(_s: &'a usize) -> bool { true }
+   |    ^^^
+help: add `fn` here to parse `foo` as a public function
+   |
+LL | pub fn foo<'a>(_s: &'a usize) -> bool { true }
+   |     ^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/pub/pub-ident-fn.fixed b/src/test/ui/pub/pub-ident-fn.fixed
new file mode 100644
index 0000000..65ed8c7
--- /dev/null
+++ b/src/test/ui/pub/pub-ident-fn.fixed
@@ -0,0 +1,8 @@
+// run-rustfix
+
+pub fn foo(_s: usize) -> bool { true }
+//~^ ERROR missing `fn` for function definition
+
+fn main() {
+    foo(2);
+}
diff --git a/src/test/ui/pub/pub-ident-fn.rs b/src/test/ui/pub/pub-ident-fn.rs
new file mode 100644
index 0000000..2fe4d34
--- /dev/null
+++ b/src/test/ui/pub/pub-ident-fn.rs
@@ -0,0 +1,8 @@
+// run-rustfix
+
+pub   foo(_s: usize) -> bool { true }
+//~^ ERROR missing `fn` for function definition
+
+fn main() {
+    foo(2);
+}
diff --git a/src/test/ui/pub/pub-ident-fn.stderr b/src/test/ui/pub/pub-ident-fn.stderr
new file mode 100644
index 0000000..b5ab88b
--- /dev/null
+++ b/src/test/ui/pub/pub-ident-fn.stderr
@@ -0,0 +1,12 @@
+error: missing `fn` for function definition
+  --> $DIR/pub-ident-fn.rs:3:4
+   |
+LL | pub   foo(_s: usize) -> bool { true }
+   |    ^^^
+help: add `fn` here to parse `foo` as a public function
+   |
+LL | pub fn foo(_s: usize) -> bool { true }
+   |     ^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/pub/pub-ident-struct-with-lifetime.rs b/src/test/ui/pub/pub-ident-struct-with-lifetime.rs
new file mode 100644
index 0000000..2feb026
--- /dev/null
+++ b/src/test/ui/pub/pub-ident-struct-with-lifetime.rs
@@ -0,0 +1,4 @@
+pub S<'a> {
+//~^ ERROR missing `struct` for struct definition
+}
+fn main() {}
diff --git a/src/test/ui/pub/pub-ident-struct-with-lifetime.stderr b/src/test/ui/pub/pub-ident-struct-with-lifetime.stderr
new file mode 100644
index 0000000..2bbcf5d
--- /dev/null
+++ b/src/test/ui/pub/pub-ident-struct-with-lifetime.stderr
@@ -0,0 +1,12 @@
+error: missing `struct` for struct definition
+  --> $DIR/pub-ident-struct-with-lifetime.rs:1:4
+   |
+LL | pub S<'a> {
+   |    ^
+help: add `struct` here to parse `S` as a public struct
+   |
+LL | pub struct S<'a> {
+   |     ^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/pub/pub-ident-struct.rs b/src/test/ui/pub/pub-ident-struct.rs
new file mode 100644
index 0000000..f2e6dfc
--- /dev/null
+++ b/src/test/ui/pub/pub-ident-struct.rs
@@ -0,0 +1,4 @@
+pub S {
+//~^ ERROR missing `struct` for struct definition
+}
+fn main() {}
diff --git a/src/test/ui/pub/pub-ident-struct.stderr b/src/test/ui/pub/pub-ident-struct.stderr
new file mode 100644
index 0000000..a9f2f89
--- /dev/null
+++ b/src/test/ui/pub/pub-ident-struct.stderr
@@ -0,0 +1,12 @@
+error: missing `struct` for struct definition
+  --> $DIR/pub-ident-struct.rs:1:4
+   |
+LL | pub S {
+   |    ^
+help: add `struct` here to parse `S` as a public struct
+   |
+LL | pub struct S {
+   |     ^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/pub/pub-ident-with-lifetime-incomplete.rs b/src/test/ui/pub/pub-ident-with-lifetime-incomplete.rs
new file mode 100644
index 0000000..c86a9f2
--- /dev/null
+++ b/src/test/ui/pub/pub-ident-with-lifetime-incomplete.rs
@@ -0,0 +1,5 @@
+fn main() {
+}
+
+pub   foo<'a>
+//~^ ERROR missing `fn` or `struct` for function or struct definition
diff --git a/src/test/ui/pub/pub-ident-with-lifetime-incomplete.stderr b/src/test/ui/pub/pub-ident-with-lifetime-incomplete.stderr
new file mode 100644
index 0000000..0e0b127
--- /dev/null
+++ b/src/test/ui/pub/pub-ident-with-lifetime-incomplete.stderr
@@ -0,0 +1,8 @@
+error: missing `fn` or `struct` for function or struct definition
+  --> $DIR/pub-ident-with-lifetime-incomplete.rs:4:4
+   |
+LL | pub   foo<'a>
+   |    ^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/pub/pub-reexport-priv-extern-crate.rs b/src/test/ui/pub/pub-reexport-priv-extern-crate.rs
new file mode 100644
index 0000000..e95d692
--- /dev/null
+++ b/src/test/ui/pub/pub-reexport-priv-extern-crate.rs
@@ -0,0 +1,24 @@
+#![allow(unused)]
+
+extern crate core;
+pub use core as reexported_core; //~ ERROR `core` is private, and cannot be re-exported
+                                 //~^ WARN this was previously accepted
+
+mod foo1 {
+    extern crate core;
+}
+
+mod foo2 {
+    use foo1::core; //~ ERROR `core` is private, and cannot be re-exported
+                    //~^ WARN this was previously accepted
+    pub mod bar {
+        extern crate core;
+    }
+}
+
+mod baz {
+    pub use foo2::bar::core; //~ ERROR `core` is private, and cannot be re-exported
+                             //~^ WARN this was previously accepted
+}
+
+fn main() {}
diff --git a/src/test/ui/pub/pub-reexport-priv-extern-crate.stderr b/src/test/ui/pub/pub-reexport-priv-extern-crate.stderr
new file mode 100644
index 0000000..61c148b
--- /dev/null
+++ b/src/test/ui/pub/pub-reexport-priv-extern-crate.stderr
@@ -0,0 +1,30 @@
+error: extern crate `core` is private, and cannot be re-exported (error E0365), consider declaring with `pub`
+  --> $DIR/pub-reexport-priv-extern-crate.rs:4:9
+   |
+LL | pub use core as reexported_core;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: #[deny(pub_use_of_private_extern_crate)] on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
+
+error: extern crate `core` is private, and cannot be re-exported (error E0365), consider declaring with `pub`
+  --> $DIR/pub-reexport-priv-extern-crate.rs:12:9
+   |
+LL |     use foo1::core;
+   |         ^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
+
+error: extern crate `core` is private, and cannot be re-exported (error E0365), consider declaring with `pub`
+  --> $DIR/pub-reexport-priv-extern-crate.rs:20:13
+   |
+LL |     pub use foo2::bar::core;
+   |             ^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/pub/pub-restricted-error-fn.rs b/src/test/ui/pub/pub-restricted-error-fn.rs
new file mode 100644
index 0000000..56ee02f
--- /dev/null
+++ b/src/test/ui/pub/pub-restricted-error-fn.rs
@@ -0,0 +1,3 @@
+#![feature(pub_restricted)]
+
+pub(crate) () fn foo() {} //~ unmatched visibility
diff --git a/src/test/ui/pub/pub-restricted-error-fn.stderr b/src/test/ui/pub/pub-restricted-error-fn.stderr
new file mode 100644
index 0000000..fcff533
--- /dev/null
+++ b/src/test/ui/pub/pub-restricted-error-fn.stderr
@@ -0,0 +1,8 @@
+error: unmatched visibility `pub`
+  --> $DIR/pub-restricted-error-fn.rs:3:10
+   |
+LL | pub(crate) () fn foo() {}
+   |          ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/pub/pub-restricted-error.rs b/src/test/ui/pub/pub-restricted-error.rs
new file mode 100644
index 0000000..30a112d
--- /dev/null
+++ b/src/test/ui/pub/pub-restricted-error.rs
@@ -0,0 +1,9 @@
+#![feature(pub_restricted)]
+
+struct Bar(pub(()));
+
+struct Foo {
+    pub(crate) () foo: usize, //~ ERROR expected identifier
+}
+
+fn main() {}
diff --git a/src/test/ui/pub/pub-restricted-error.stderr b/src/test/ui/pub/pub-restricted-error.stderr
new file mode 100644
index 0000000..d856833
--- /dev/null
+++ b/src/test/ui/pub/pub-restricted-error.stderr
@@ -0,0 +1,8 @@
+error: expected identifier, found `(`
+  --> $DIR/pub-restricted-error.rs:6:16
+   |
+LL |     pub(crate) () foo: usize,
+   |                ^ expected identifier
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/pub/pub-restricted-non-path.rs b/src/test/ui/pub/pub-restricted-non-path.rs
new file mode 100644
index 0000000..bdad18d
--- /dev/null
+++ b/src/test/ui/pub/pub-restricted-non-path.rs
@@ -0,0 +1,5 @@
+#![feature(pub_restricted)]
+
+pub (.) fn afn() {} //~ ERROR expected identifier
+
+fn main() {}
diff --git a/src/test/ui/pub/pub-restricted-non-path.stderr b/src/test/ui/pub/pub-restricted-non-path.stderr
new file mode 100644
index 0000000..e0ea506
--- /dev/null
+++ b/src/test/ui/pub/pub-restricted-non-path.stderr
@@ -0,0 +1,8 @@
+error: expected identifier, found `.`
+  --> $DIR/pub-restricted-non-path.rs:3:6
+   |
+LL | pub (.) fn afn() {}
+   |      ^ expected identifier
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/pub/pub-restricted.rs b/src/test/ui/pub/pub-restricted.rs
new file mode 100644
index 0000000..8793cb9
--- /dev/null
+++ b/src/test/ui/pub/pub-restricted.rs
@@ -0,0 +1,31 @@
+#![feature(pub_restricted)]
+
+mod a {}
+
+pub (a) fn afn() {} //~ incorrect visibility restriction
+pub (b) fn bfn() {} //~ incorrect visibility restriction
+pub fn privfn() {}
+mod x {
+    mod y {
+        pub (in x) fn foo() {}
+        pub (super) fn bar() {}
+        pub (crate) fn qux() {}
+    }
+}
+
+mod y {
+    struct Foo {
+        pub (crate) c: usize,
+        pub (super) s: usize,
+        valid_private: usize,
+        pub (in y) valid_in_x: usize,
+        pub (a) invalid: usize, //~ incorrect visibility restriction
+        pub (in x) non_parent_invalid: usize, //~ ERROR visibilities can only be restricted
+    }
+}
+
+fn main() {}
+
+// test multichar names
+mod xyz {}
+pub (xyz) fn xyz() {} //~ incorrect visibility restriction
diff --git a/src/test/ui/pub/pub-restricted.stderr b/src/test/ui/pub/pub-restricted.stderr
new file mode 100644
index 0000000..7eeefa9
--- /dev/null
+++ b/src/test/ui/pub/pub-restricted.stderr
@@ -0,0 +1,53 @@
+error[E0704]: incorrect visibility restriction
+  --> $DIR/pub-restricted.rs:5:6
+   |
+LL | pub (a) fn afn() {}
+   |      ^ help: make this visible only to module `a` with `in`: `in a`
+   |
+   = help: some possible visibility restrictions are:
+           `pub(crate)`: visible only on the current crate
+           `pub(super)`: visible only in the current module's parent
+           `pub(in path::to::module)`: visible only on the specified path
+
+error[E0704]: incorrect visibility restriction
+  --> $DIR/pub-restricted.rs:6:6
+   |
+LL | pub (b) fn bfn() {}
+   |      ^ help: make this visible only to module `b` with `in`: `in b`
+   |
+   = help: some possible visibility restrictions are:
+           `pub(crate)`: visible only on the current crate
+           `pub(super)`: visible only in the current module's parent
+           `pub(in path::to::module)`: visible only on the specified path
+
+error[E0704]: incorrect visibility restriction
+  --> $DIR/pub-restricted.rs:22:14
+   |
+LL |         pub (a) invalid: usize,
+   |              ^ help: make this visible only to module `a` with `in`: `in a`
+   |
+   = help: some possible visibility restrictions are:
+           `pub(crate)`: visible only on the current crate
+           `pub(super)`: visible only in the current module's parent
+           `pub(in path::to::module)`: visible only on the specified path
+
+error[E0704]: incorrect visibility restriction
+  --> $DIR/pub-restricted.rs:31:6
+   |
+LL | pub (xyz) fn xyz() {}
+   |      ^^^ help: make this visible only to module `xyz` with `in`: `in xyz`
+   |
+   = help: some possible visibility restrictions are:
+           `pub(crate)`: visible only on the current crate
+           `pub(super)`: visible only in the current module's parent
+           `pub(in path::to::module)`: visible only on the specified path
+
+error: visibilities can only be restricted to ancestor modules
+  --> $DIR/pub-restricted.rs:23:17
+   |
+LL |         pub (in x) non_parent_invalid: usize,
+   |                 ^
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0704`.
diff --git a/src/test/ui/qualified/qualified-path-params-2.rs b/src/test/ui/qualified/qualified-path-params-2.rs
new file mode 100644
index 0000000..ebdd749
--- /dev/null
+++ b/src/test/ui/qualified/qualified-path-params-2.rs
@@ -0,0 +1,22 @@
+// Check that qualified paths with type parameters
+// fail during type checking and not during parsing
+
+struct S;
+
+trait Tr {
+    type A;
+}
+
+impl Tr for S {
+    type A = S;
+}
+
+impl S {
+    fn f<T>() {}
+}
+
+type A = <S as Tr>::A::f<u8>;
+//~^ ERROR type arguments are not allowed for this type
+//~| ERROR ambiguous associated type
+
+fn main() {}
diff --git a/src/test/ui/qualified/qualified-path-params-2.stderr b/src/test/ui/qualified/qualified-path-params-2.stderr
new file mode 100644
index 0000000..2d14d6c
--- /dev/null
+++ b/src/test/ui/qualified/qualified-path-params-2.stderr
@@ -0,0 +1,16 @@
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/qualified-path-params-2.rs:18:26
+   |
+LL | type A = <S as Tr>::A::f<u8>;
+   |                          ^^ type argument not allowed
+
+error[E0223]: ambiguous associated type
+  --> $DIR/qualified-path-params-2.rs:18:10
+   |
+LL | type A = <S as Tr>::A::f<u8>;
+   |          ^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<<S as Tr>::A as Trait>::f`
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0109, E0223.
+For more information about an error, try `rustc --explain E0109`.
diff --git a/src/test/ui/qualified/qualified-path-params.rs b/src/test/ui/qualified/qualified-path-params.rs
new file mode 100644
index 0000000..ea2ae0e
--- /dev/null
+++ b/src/test/ui/qualified/qualified-path-params.rs
@@ -0,0 +1,24 @@
+// Check that qualified paths with type parameters
+// fail during type checking and not during parsing
+
+struct S;
+
+trait Tr {
+    type A;
+}
+
+impl Tr for S {
+    type A = S;
+}
+
+impl S {
+    fn f<T>() {}
+}
+
+fn main() {
+    match 10 {
+        <S as Tr>::A::f::<u8> => {}
+        //~^ ERROR expected unit struct/variant or constant, found method `<<S as Tr>::A>::f<u8>`
+        0 ..= <S as Tr>::A::f::<u8> => {} //~ ERROR only char and numeric types are allowed in range
+    }
+}
diff --git a/src/test/ui/qualified/qualified-path-params.stderr b/src/test/ui/qualified/qualified-path-params.stderr
new file mode 100644
index 0000000..926b098
--- /dev/null
+++ b/src/test/ui/qualified/qualified-path-params.stderr
@@ -0,0 +1,19 @@
+error[E0533]: expected unit struct/variant or constant, found method `<<S as Tr>::A>::f<u8>`
+  --> $DIR/qualified-path-params.rs:20:9
+   |
+LL |         <S as Tr>::A::f::<u8> => {}
+   |         ^^^^^^^^^^^^^^^^^^^^^
+
+error[E0029]: only char and numeric types are allowed in range patterns
+  --> $DIR/qualified-path-params.rs:22:15
+   |
+LL |         0 ..= <S as Tr>::A::f::<u8> => {}
+   |               ^^^^^^^^^^^^^^^^^^^^^ ranges require char or numeric types
+   |
+   = note: start type: {integer}
+   = note: end type: fn() {S::f::<u8>}
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0029, E0533.
+For more information about an error, try `rustc --explain E0029`.
diff --git a/src/test/ui/question-mark-type-infer.rs b/src/test/ui/question-mark-type-infer.rs
new file mode 100644
index 0000000..2e7a342
--- /dev/null
+++ b/src/test/ui/question-mark-type-infer.rs
@@ -0,0 +1,17 @@
+#![feature(question_mark, question_mark_carrier)]
+
+// Test that type inference fails where there are multiple possible return types
+// for the `?` operator.
+
+fn f(x: &i32) -> Result<i32, ()> {
+    Ok(*x)
+}
+
+fn g() -> Result<Vec<i32>, ()> {
+    let l = [1, 2, 3, 4];
+    l.iter().map(f).collect()? //~ ERROR type annotations required: cannot resolve
+}
+
+fn main() {
+    g();
+}
diff --git a/src/test/ui/question-mark-type-infer.stderr b/src/test/ui/question-mark-type-infer.stderr
new file mode 100644
index 0000000..f62a540
--- /dev/null
+++ b/src/test/ui/question-mark-type-infer.stderr
@@ -0,0 +1,9 @@
+error[E0284]: type annotations required: cannot resolve `<_ as std::ops::Try>::Ok == _`
+  --> $DIR/question-mark-type-infer.rs:12:5
+   |
+LL |     l.iter().map(f).collect()?
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0284`.
diff --git a/src/test/ui/range/issue-54505-no-literals.fixed b/src/test/ui/range/issue-54505-no-literals.fixed
new file mode 100644
index 0000000..4d8f671
--- /dev/null
+++ b/src/test/ui/range/issue-54505-no-literals.fixed
@@ -0,0 +1,75 @@
+// run-rustfix
+
+// Regression test for changes introduced while fixing #54505
+
+// This test uses non-literals for Ranges
+// (expecting no parens with borrow suggestion)
+
+use std::ops::RangeBounds;
+
+
+// take a reference to any built-in range
+fn take_range(_r: &impl RangeBounds<i8>) {}
+
+
+fn main() {
+    take_range(&std::ops::Range { start: 0, end: 1 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &std::ops::Range { start: 0, end: 1 }
+
+    take_range(&::std::ops::Range { start: 0, end: 1 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &::std::ops::Range { start: 0, end: 1 }
+
+    take_range(&std::ops::RangeFrom { start: 1 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &std::ops::RangeFrom { start: 1 }
+
+    take_range(&::std::ops::RangeFrom { start: 1 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &::std::ops::RangeFrom { start: 1 }
+
+    take_range(&std::ops::RangeFull {});
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &std::ops::RangeFull {}
+
+    take_range(&::std::ops::RangeFull {});
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &::std::ops::RangeFull {}
+
+    take_range(&std::ops::RangeInclusive::new(0, 1));
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &std::ops::RangeInclusive::new(0, 1)
+
+    take_range(&::std::ops::RangeInclusive::new(0, 1));
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &::std::ops::RangeInclusive::new(0, 1)
+
+    take_range(&std::ops::RangeTo { end: 5 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &std::ops::RangeTo { end: 5 }
+
+    take_range(&::std::ops::RangeTo { end: 5 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &::std::ops::RangeTo { end: 5 }
+
+    take_range(&std::ops::RangeToInclusive { end: 5 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &std::ops::RangeToInclusive { end: 5 }
+
+    take_range(&::std::ops::RangeToInclusive { end: 5 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &::std::ops::RangeToInclusive { end: 5 }
+}
diff --git a/src/test/ui/range/issue-54505-no-literals.rs b/src/test/ui/range/issue-54505-no-literals.rs
new file mode 100644
index 0000000..dc21dcb
--- /dev/null
+++ b/src/test/ui/range/issue-54505-no-literals.rs
@@ -0,0 +1,75 @@
+// run-rustfix
+
+// Regression test for changes introduced while fixing #54505
+
+// This test uses non-literals for Ranges
+// (expecting no parens with borrow suggestion)
+
+use std::ops::RangeBounds;
+
+
+// take a reference to any built-in range
+fn take_range(_r: &impl RangeBounds<i8>) {}
+
+
+fn main() {
+    take_range(std::ops::Range { start: 0, end: 1 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &std::ops::Range { start: 0, end: 1 }
+
+    take_range(::std::ops::Range { start: 0, end: 1 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &::std::ops::Range { start: 0, end: 1 }
+
+    take_range(std::ops::RangeFrom { start: 1 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &std::ops::RangeFrom { start: 1 }
+
+    take_range(::std::ops::RangeFrom { start: 1 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &::std::ops::RangeFrom { start: 1 }
+
+    take_range(std::ops::RangeFull {});
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &std::ops::RangeFull {}
+
+    take_range(::std::ops::RangeFull {});
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &::std::ops::RangeFull {}
+
+    take_range(std::ops::RangeInclusive::new(0, 1));
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &std::ops::RangeInclusive::new(0, 1)
+
+    take_range(::std::ops::RangeInclusive::new(0, 1));
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &::std::ops::RangeInclusive::new(0, 1)
+
+    take_range(std::ops::RangeTo { end: 5 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &std::ops::RangeTo { end: 5 }
+
+    take_range(::std::ops::RangeTo { end: 5 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &::std::ops::RangeTo { end: 5 }
+
+    take_range(std::ops::RangeToInclusive { end: 5 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &std::ops::RangeToInclusive { end: 5 }
+
+    take_range(::std::ops::RangeToInclusive { end: 5 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &::std::ops::RangeToInclusive { end: 5 }
+}
diff --git a/src/test/ui/range/issue-54505-no-literals.stderr b/src/test/ui/range/issue-54505-no-literals.stderr
new file mode 100644
index 0000000..b8811c9
--- /dev/null
+++ b/src/test/ui/range/issue-54505-no-literals.stderr
@@ -0,0 +1,147 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-literals.rs:16:16
+   |
+LL |     take_range(std::ops::Range { start: 0, end: 1 });
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::Range`
+   |                help: consider borrowing here: `&std::ops::Range { start: 0, end: 1 }`
+   |
+   = note: expected type `&_`
+              found type `std::ops::Range<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-literals.rs:21:16
+   |
+LL |     take_range(::std::ops::Range { start: 0, end: 1 });
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::Range`
+   |                help: consider borrowing here: `&::std::ops::Range { start: 0, end: 1 }`
+   |
+   = note: expected type `&_`
+              found type `std::ops::Range<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-literals.rs:26:16
+   |
+LL |     take_range(std::ops::RangeFrom { start: 1 });
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeFrom`
+   |                help: consider borrowing here: `&std::ops::RangeFrom { start: 1 }`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeFrom<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-literals.rs:31:16
+   |
+LL |     take_range(::std::ops::RangeFrom { start: 1 });
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeFrom`
+   |                help: consider borrowing here: `&::std::ops::RangeFrom { start: 1 }`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeFrom<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-literals.rs:36:16
+   |
+LL |     take_range(std::ops::RangeFull {});
+   |                ^^^^^^^^^^^^^^^^^^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeFull`
+   |                help: consider borrowing here: `&std::ops::RangeFull {}`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeFull`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-literals.rs:41:16
+   |
+LL |     take_range(::std::ops::RangeFull {});
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeFull`
+   |                help: consider borrowing here: `&::std::ops::RangeFull {}`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeFull`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-literals.rs:46:16
+   |
+LL |     take_range(std::ops::RangeInclusive::new(0, 1));
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeInclusive`
+   |                help: consider borrowing here: `&std::ops::RangeInclusive::new(0, 1)`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeInclusive<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-literals.rs:51:16
+   |
+LL |     take_range(::std::ops::RangeInclusive::new(0, 1));
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeInclusive`
+   |                help: consider borrowing here: `&::std::ops::RangeInclusive::new(0, 1)`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeInclusive<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-literals.rs:56:16
+   |
+LL |     take_range(std::ops::RangeTo { end: 5 });
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeTo`
+   |                help: consider borrowing here: `&std::ops::RangeTo { end: 5 }`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeTo<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-literals.rs:61:16
+   |
+LL |     take_range(::std::ops::RangeTo { end: 5 });
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeTo`
+   |                help: consider borrowing here: `&::std::ops::RangeTo { end: 5 }`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeTo<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-literals.rs:66:16
+   |
+LL |     take_range(std::ops::RangeToInclusive { end: 5 });
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeToInclusive`
+   |                help: consider borrowing here: `&std::ops::RangeToInclusive { end: 5 }`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeToInclusive<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-literals.rs:71:16
+   |
+LL |     take_range(::std::ops::RangeToInclusive { end: 5 });
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeToInclusive`
+   |                help: consider borrowing here: `&::std::ops::RangeToInclusive { end: 5 }`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeToInclusive<{integer}>`
+
+error: aborting due to 12 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/range/issue-54505-no-std.rs b/src/test/ui/range/issue-54505-no-std.rs
new file mode 100644
index 0000000..22cf15f
--- /dev/null
+++ b/src/test/ui/range/issue-54505-no-std.rs
@@ -0,0 +1,57 @@
+// error-pattern: `#[panic_handler]` function required, but not found
+
+// Regression test for #54505 - range borrowing suggestion had
+// incorrect syntax (missing parentheses).
+
+// This test doesn't use std
+// (so all Ranges resolve to core::ops::Range...)
+
+#![no_std]
+#![feature(lang_items)]
+
+use core::ops::RangeBounds;
+
+#[cfg(any(not(target_arch = "wasm32"), target_os = "emscripten"))]
+#[lang = "eh_personality"]
+extern fn eh_personality() {}
+
+#[cfg(target_os = "windows")]
+#[lang = "eh_unwind_resume"]
+extern fn eh_unwind_resume() {}
+
+
+// take a reference to any built-in range
+fn take_range(_r: &impl RangeBounds<i8>) {}
+
+
+fn main() {
+    take_range(0..1);
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(0..1)
+
+    take_range(1..);
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(1..)
+
+    take_range(..);
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(..)
+
+    take_range(0..=1);
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(0..=1)
+
+    take_range(..5);
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(..5)
+
+    take_range(..=42);
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(..=42)
+}
diff --git a/src/test/ui/range/issue-54505-no-std.stderr b/src/test/ui/range/issue-54505-no-std.stderr
new file mode 100644
index 0000000..4922e59
--- /dev/null
+++ b/src/test/ui/range/issue-54505-no-std.stderr
@@ -0,0 +1,77 @@
+error: `#[panic_handler]` function required, but not found
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-std.rs:28:16
+   |
+LL |     take_range(0..1);
+   |                ^^^^
+   |                |
+   |                expected reference, found struct `core::ops::Range`
+   |                help: consider borrowing here: `&(0..1)`
+   |
+   = note: expected type `&_`
+              found type `core::ops::Range<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-std.rs:33:16
+   |
+LL |     take_range(1..);
+   |                ^^^
+   |                |
+   |                expected reference, found struct `core::ops::RangeFrom`
+   |                help: consider borrowing here: `&(1..)`
+   |
+   = note: expected type `&_`
+              found type `core::ops::RangeFrom<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-std.rs:38:16
+   |
+LL |     take_range(..);
+   |                ^^
+   |                |
+   |                expected reference, found struct `core::ops::RangeFull`
+   |                help: consider borrowing here: `&(..)`
+   |
+   = note: expected type `&_`
+              found type `core::ops::RangeFull`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-std.rs:43:16
+   |
+LL |     take_range(0..=1);
+   |                ^^^^^
+   |                |
+   |                expected reference, found struct `core::ops::RangeInclusive`
+   |                help: consider borrowing here: `&(0..=1)`
+   |
+   = note: expected type `&_`
+              found type `core::ops::RangeInclusive<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-std.rs:48:16
+   |
+LL |     take_range(..5);
+   |                ^^^
+   |                |
+   |                expected reference, found struct `core::ops::RangeTo`
+   |                help: consider borrowing here: `&(..5)`
+   |
+   = note: expected type `&_`
+              found type `core::ops::RangeTo<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-std.rs:53:16
+   |
+LL |     take_range(..=42);
+   |                ^^^^^
+   |                |
+   |                expected reference, found struct `core::ops::RangeToInclusive`
+   |                help: consider borrowing here: `&(..=42)`
+   |
+   = note: expected type `&_`
+              found type `core::ops::RangeToInclusive<{integer}>`
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/range/issue-54505.fixed b/src/test/ui/range/issue-54505.fixed
new file mode 100644
index 0000000..f8298c0
--- /dev/null
+++ b/src/test/ui/range/issue-54505.fixed
@@ -0,0 +1,43 @@
+// run-rustfix
+
+// Regression test for #54505 - range borrowing suggestion had
+// incorrect syntax (missing parentheses).
+
+use std::ops::RangeBounds;
+
+
+// take a reference to any built-in range
+fn take_range(_r: &impl RangeBounds<i8>) {}
+
+
+fn main() {
+    take_range(&(0..1));
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(0..1)
+
+    take_range(&(1..));
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(1..)
+
+    take_range(&(..));
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(..)
+
+    take_range(&(0..=1));
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(0..=1)
+
+    take_range(&(..5));
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(..5)
+
+    take_range(&(..=42));
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(..=42)
+}
diff --git a/src/test/ui/range/issue-54505.rs b/src/test/ui/range/issue-54505.rs
new file mode 100644
index 0000000..0367325
--- /dev/null
+++ b/src/test/ui/range/issue-54505.rs
@@ -0,0 +1,43 @@
+// run-rustfix
+
+// Regression test for #54505 - range borrowing suggestion had
+// incorrect syntax (missing parentheses).
+
+use std::ops::RangeBounds;
+
+
+// take a reference to any built-in range
+fn take_range(_r: &impl RangeBounds<i8>) {}
+
+
+fn main() {
+    take_range(0..1);
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(0..1)
+
+    take_range(1..);
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(1..)
+
+    take_range(..);
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(..)
+
+    take_range(0..=1);
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(0..=1)
+
+    take_range(..5);
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(..5)
+
+    take_range(..=42);
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(..=42)
+}
diff --git a/src/test/ui/range/issue-54505.stderr b/src/test/ui/range/issue-54505.stderr
new file mode 100644
index 0000000..d6e1fb0
--- /dev/null
+++ b/src/test/ui/range/issue-54505.stderr
@@ -0,0 +1,75 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-54505.rs:14:16
+   |
+LL |     take_range(0..1);
+   |                ^^^^
+   |                |
+   |                expected reference, found struct `std::ops::Range`
+   |                help: consider borrowing here: `&(0..1)`
+   |
+   = note: expected type `&_`
+              found type `std::ops::Range<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505.rs:19:16
+   |
+LL |     take_range(1..);
+   |                ^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeFrom`
+   |                help: consider borrowing here: `&(1..)`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeFrom<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505.rs:24:16
+   |
+LL |     take_range(..);
+   |                ^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeFull`
+   |                help: consider borrowing here: `&(..)`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeFull`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505.rs:29:16
+   |
+LL |     take_range(0..=1);
+   |                ^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeInclusive`
+   |                help: consider borrowing here: `&(0..=1)`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeInclusive<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505.rs:34:16
+   |
+LL |     take_range(..5);
+   |                ^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeTo`
+   |                help: consider borrowing here: `&(..5)`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeTo<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505.rs:39:16
+   |
+LL |     take_range(..=42);
+   |                ^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeToInclusive`
+   |                help: consider borrowing here: `&(..=42)`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeToInclusive<{integer}>`
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/range/range-1.rs b/src/test/ui/range/range-1.rs
new file mode 100644
index 0000000..f13787b
--- /dev/null
+++ b/src/test/ui/range/range-1.rs
@@ -0,0 +1,16 @@
+// Test range syntax - type errors.
+
+pub fn main() {
+    // Mixed types.
+    let _ = 0u32..10i32;
+    //~^ ERROR mismatched types
+
+    // Bool => does not implement iterator.
+    for i in false..true {}
+    //~^ ERROR `bool: std::iter::Step` is not satisfied
+
+    // Unsized type.
+    let arr: &[_] = &[1, 2, 3];
+    let range = *arr..;
+    //~^ ERROR the size for values of type
+}
diff --git a/src/test/ui/range/range-1.stderr b/src/test/ui/range/range-1.stderr
new file mode 100644
index 0000000..00c0c80
--- /dev/null
+++ b/src/test/ui/range/range-1.stderr
@@ -0,0 +1,28 @@
+error[E0308]: mismatched types
+  --> $DIR/range-1.rs:5:19
+   |
+LL |     let _ = 0u32..10i32;
+   |                   ^^^^^ expected u32, found i32
+
+error[E0277]: the trait bound `bool: std::iter::Step` is not satisfied
+  --> $DIR/range-1.rs:9:14
+   |
+LL |     for i in false..true {}
+   |              ^^^^^^^^^^^ the trait `std::iter::Step` is not implemented for `bool`
+   |
+   = note: required because of the requirements on the impl of `std::iter::Iterator` for `std::ops::Range<bool>`
+
+error[E0277]: the size for values of type `[{integer}]` cannot be known at compilation time
+  --> $DIR/range-1.rs:14:17
+   |
+LL |     let range = *arr..;
+   |                 ^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `[{integer}]`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: required by `std::ops::RangeFrom`
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0277, E0308.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/range/range-inclusive-pattern-precedence.rs b/src/test/ui/range/range-inclusive-pattern-precedence.rs
new file mode 100644
index 0000000..fbafe1f
--- /dev/null
+++ b/src/test/ui/range/range-inclusive-pattern-precedence.rs
@@ -0,0 +1,34 @@
+// In expression, `&a..=b` is treated as `(&a)..=(b)` and `box a..=b` is
+// `(box a)..=(b)`. In a pattern, however, `&a..=b` means `&(a..=b)`. This may
+// lead to confusion.
+//
+// We are going to disallow `&a..=b` and `box a..=b` in a pattern. However, the
+// older ... syntax is still allowed as a stability guarantee.
+
+#![feature(box_patterns)]
+#![warn(ellipsis_inclusive_range_patterns)]
+
+
+pub fn main() {
+    match &12 {
+        &0...9 => {}
+        //~^ WARN `...` range patterns are deprecated
+        //~| HELP use `..=` for an inclusive range
+        &10..=15 => {}
+        //~^ ERROR the range pattern here has ambiguous interpretation
+        //~^^ HELP add parentheses to clarify the precedence
+        &(16..=20) => {}
+        _ => {}
+    }
+
+    match Box::new(12) {
+        box 0...9 => {}
+        //~^ WARN `...` range patterns are deprecated
+        //~| HELP use `..=` for an inclusive range
+        box 10..=15 => {}
+        //~^ ERROR the range pattern here has ambiguous interpretation
+        //~^^ HELP add parentheses to clarify the precedence
+        box (16..=20) => {}
+        _ => {}
+    }
+}
diff --git a/src/test/ui/range/range-inclusive-pattern-precedence.stderr b/src/test/ui/range/range-inclusive-pattern-precedence.stderr
new file mode 100644
index 0000000..fb0cf38
--- /dev/null
+++ b/src/test/ui/range/range-inclusive-pattern-precedence.stderr
@@ -0,0 +1,32 @@
+error: the range pattern here has ambiguous interpretation
+  --> $DIR/range-inclusive-pattern-precedence.rs:17:10
+   |
+LL |         &10..=15 => {}
+   |          ^^^^^^^ help: add parentheses to clarify the precedence: `(10 ..=15)`
+
+error: the range pattern here has ambiguous interpretation
+  --> $DIR/range-inclusive-pattern-precedence.rs:28:13
+   |
+LL |         box 10..=15 => {}
+   |             ^^^^^^^ help: add parentheses to clarify the precedence: `(10 ..=15)`
+
+warning: `...` range patterns are deprecated
+  --> $DIR/range-inclusive-pattern-precedence.rs:14:9
+   |
+LL |         &0...9 => {}
+   |         ^^^^^^ help: use `..=` for an inclusive range: `&(0..=9)`
+   |
+note: lint level defined here
+  --> $DIR/range-inclusive-pattern-precedence.rs:9:9
+   |
+LL | #![warn(ellipsis_inclusive_range_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: `...` range patterns are deprecated
+  --> $DIR/range-inclusive-pattern-precedence.rs:25:14
+   |
+LL |         box 0...9 => {}
+   |              ^^^ help: use `..=` for an inclusive range
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/range/range_traits-1.rs b/src/test/ui/range/range_traits-1.rs
new file mode 100644
index 0000000..e28e474
--- /dev/null
+++ b/src/test/ui/range/range_traits-1.rs
@@ -0,0 +1,25 @@
+use std::ops::*;
+
+#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+struct AllTheRanges {
+    a: Range<usize>,
+    //~^ ERROR can't compare
+    //~| ERROR Ord
+    b: RangeTo<usize>,
+    //~^ ERROR can't compare
+    //~| ERROR Ord
+    c: RangeFrom<usize>,
+    //~^ ERROR can't compare
+    //~| ERROR Ord
+    d: RangeFull,
+    //~^ ERROR can't compare
+    //~| ERROR Ord
+    e: RangeInclusive<usize>,
+    //~^ ERROR can't compare
+    //~| ERROR Ord
+    f: RangeToInclusive<usize>,
+    //~^ ERROR can't compare
+    //~| ERROR Ord
+}
+
+fn main() {}
diff --git a/src/test/ui/range/range_traits-1.stderr b/src/test/ui/range/range_traits-1.stderr
new file mode 100644
index 0000000..d085cab
--- /dev/null
+++ b/src/test/ui/range/range_traits-1.stderr
@@ -0,0 +1,105 @@
+error[E0277]: can't compare `std::ops::Range<usize>` with `std::ops::Range<usize>`
+  --> $DIR/range_traits-1.rs:5:5
+   |
+LL |     a: Range<usize>,
+   |     ^^^^^^^^^^^^^^^ no implementation for `std::ops::Range<usize> < std::ops::Range<usize>` and `std::ops::Range<usize> > std::ops::Range<usize>`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `std::ops::Range<usize>`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `std::ops::RangeTo<usize>` with `std::ops::RangeTo<usize>`
+  --> $DIR/range_traits-1.rs:8:5
+   |
+LL |     b: RangeTo<usize>,
+   |     ^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeTo<usize> < std::ops::RangeTo<usize>` and `std::ops::RangeTo<usize> > std::ops::RangeTo<usize>`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `std::ops::RangeTo<usize>`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `std::ops::RangeFrom<usize>` with `std::ops::RangeFrom<usize>`
+  --> $DIR/range_traits-1.rs:11:5
+   |
+LL |     c: RangeFrom<usize>,
+   |     ^^^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeFrom<usize> < std::ops::RangeFrom<usize>` and `std::ops::RangeFrom<usize> > std::ops::RangeFrom<usize>`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `std::ops::RangeFrom<usize>`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `std::ops::RangeFull` with `std::ops::RangeFull`
+  --> $DIR/range_traits-1.rs:14:5
+   |
+LL |     d: RangeFull,
+   |     ^^^^^^^^^^^^ no implementation for `std::ops::RangeFull < std::ops::RangeFull` and `std::ops::RangeFull > std::ops::RangeFull`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `std::ops::RangeFull`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `std::ops::RangeInclusive<usize>` with `std::ops::RangeInclusive<usize>`
+  --> $DIR/range_traits-1.rs:17:5
+   |
+LL |     e: RangeInclusive<usize>,
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeInclusive<usize> < std::ops::RangeInclusive<usize>` and `std::ops::RangeInclusive<usize> > std::ops::RangeInclusive<usize>`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `std::ops::RangeInclusive<usize>`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `std::ops::RangeToInclusive<usize>` with `std::ops::RangeToInclusive<usize>`
+  --> $DIR/range_traits-1.rs:20:5
+   |
+LL |     f: RangeToInclusive<usize>,
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeToInclusive<usize> < std::ops::RangeToInclusive<usize>` and `std::ops::RangeToInclusive<usize> > std::ops::RangeToInclusive<usize>`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `std::ops::RangeToInclusive<usize>`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: the trait bound `std::ops::Range<usize>: std::cmp::Ord` is not satisfied
+  --> $DIR/range_traits-1.rs:5:5
+   |
+LL |     a: Range<usize>,
+   |     ^^^^^^^^^^^^^^^ the trait `std::cmp::Ord` is not implemented for `std::ops::Range<usize>`
+   |
+   = note: required by `std::cmp::Ord::cmp`
+
+error[E0277]: the trait bound `std::ops::RangeTo<usize>: std::cmp::Ord` is not satisfied
+  --> $DIR/range_traits-1.rs:8:5
+   |
+LL |     b: RangeTo<usize>,
+   |     ^^^^^^^^^^^^^^^^^ the trait `std::cmp::Ord` is not implemented for `std::ops::RangeTo<usize>`
+   |
+   = note: required by `std::cmp::Ord::cmp`
+
+error[E0277]: the trait bound `std::ops::RangeFrom<usize>: std::cmp::Ord` is not satisfied
+  --> $DIR/range_traits-1.rs:11:5
+   |
+LL |     c: RangeFrom<usize>,
+   |     ^^^^^^^^^^^^^^^^^^^ the trait `std::cmp::Ord` is not implemented for `std::ops::RangeFrom<usize>`
+   |
+   = note: required by `std::cmp::Ord::cmp`
+
+error[E0277]: the trait bound `std::ops::RangeFull: std::cmp::Ord` is not satisfied
+  --> $DIR/range_traits-1.rs:14:5
+   |
+LL |     d: RangeFull,
+   |     ^^^^^^^^^^^^ the trait `std::cmp::Ord` is not implemented for `std::ops::RangeFull`
+   |
+   = note: required by `std::cmp::Ord::cmp`
+
+error[E0277]: the trait bound `std::ops::RangeInclusive<usize>: std::cmp::Ord` is not satisfied
+  --> $DIR/range_traits-1.rs:17:5
+   |
+LL |     e: RangeInclusive<usize>,
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::cmp::Ord` is not implemented for `std::ops::RangeInclusive<usize>`
+   |
+   = note: required by `std::cmp::Ord::cmp`
+
+error[E0277]: the trait bound `std::ops::RangeToInclusive<usize>: std::cmp::Ord` is not satisfied
+  --> $DIR/range_traits-1.rs:20:5
+   |
+LL |     f: RangeToInclusive<usize>,
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::cmp::Ord` is not implemented for `std::ops::RangeToInclusive<usize>`
+   |
+   = note: required by `std::cmp::Ord::cmp`
+
+error: aborting due to 12 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/range/range_traits-2.rs b/src/test/ui/range/range_traits-2.rs
new file mode 100644
index 0000000..c34ef78
--- /dev/null
+++ b/src/test/ui/range/range_traits-2.rs
@@ -0,0 +1,7 @@
+use std::ops::*;
+
+#[derive(Copy, Clone)] //~ ERROR Copy
+struct R(Range<usize>);
+
+fn main() {}
+
diff --git a/src/test/ui/range/range_traits-2.stderr b/src/test/ui/range/range_traits-2.stderr
new file mode 100644
index 0000000..598a0b3
--- /dev/null
+++ b/src/test/ui/range/range_traits-2.stderr
@@ -0,0 +1,11 @@
+error[E0204]: the trait `Copy` may not be implemented for this type
+  --> $DIR/range_traits-2.rs:3:10
+   |
+LL | #[derive(Copy, Clone)]
+   |          ^^^^
+LL | struct R(Range<usize>);
+   |          ------------ this field does not implement `Copy`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0204`.
diff --git a/src/test/ui/range/range_traits-3.rs b/src/test/ui/range/range_traits-3.rs
new file mode 100644
index 0000000..b0448af
--- /dev/null
+++ b/src/test/ui/range/range_traits-3.rs
@@ -0,0 +1,7 @@
+use std::ops::*;
+
+#[derive(Copy, Clone)] //~ ERROR Copy
+struct R(RangeFrom<usize>);
+
+fn main() {}
+
diff --git a/src/test/ui/range/range_traits-3.stderr b/src/test/ui/range/range_traits-3.stderr
new file mode 100644
index 0000000..e2713a2
--- /dev/null
+++ b/src/test/ui/range/range_traits-3.stderr
@@ -0,0 +1,11 @@
+error[E0204]: the trait `Copy` may not be implemented for this type
+  --> $DIR/range_traits-3.rs:3:10
+   |
+LL | #[derive(Copy, Clone)]
+   |          ^^^^
+LL | struct R(RangeFrom<usize>);
+   |          ---------------- this field does not implement `Copy`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0204`.
diff --git a/src/test/ui/range/range_traits-4.rs b/src/test/ui/range/range_traits-4.rs
new file mode 100644
index 0000000..ff84577
--- /dev/null
+++ b/src/test/ui/range/range_traits-4.rs
@@ -0,0 +1,10 @@
+// compile-pass
+
+use std::ops::*;
+
+#[derive(Copy, Clone)]
+struct R(RangeTo<usize>);
+
+
+fn main() {}
+
diff --git a/src/test/ui/range/range_traits-5.rs b/src/test/ui/range/range_traits-5.rs
new file mode 100644
index 0000000..95505c9
--- /dev/null
+++ b/src/test/ui/range/range_traits-5.rs
@@ -0,0 +1,10 @@
+// compile-pass
+
+use std::ops::*;
+
+#[derive(Copy, Clone)]
+struct R(RangeFull);
+
+
+fn main() {}
+
diff --git a/src/test/ui/range/range_traits-6.rs b/src/test/ui/range/range_traits-6.rs
new file mode 100644
index 0000000..041f04a
--- /dev/null
+++ b/src/test/ui/range/range_traits-6.rs
@@ -0,0 +1,7 @@
+use std::ops::*;
+
+#[derive(Copy, Clone)] //~ ERROR Copy
+struct R(RangeInclusive<usize>);
+
+fn main() {}
+
diff --git a/src/test/ui/range/range_traits-6.stderr b/src/test/ui/range/range_traits-6.stderr
new file mode 100644
index 0000000..226d72c
--- /dev/null
+++ b/src/test/ui/range/range_traits-6.stderr
@@ -0,0 +1,11 @@
+error[E0204]: the trait `Copy` may not be implemented for this type
+  --> $DIR/range_traits-6.rs:3:10
+   |
+LL | #[derive(Copy, Clone)]
+   |          ^^^^
+LL | struct R(RangeInclusive<usize>);
+   |          --------------------- this field does not implement `Copy`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0204`.
diff --git a/src/test/ui/range/range_traits-7.rs b/src/test/ui/range/range_traits-7.rs
new file mode 100644
index 0000000..c328ecb
--- /dev/null
+++ b/src/test/ui/range/range_traits-7.rs
@@ -0,0 +1,10 @@
+// compile-pass
+
+use std::ops::*;
+
+#[derive(Copy, Clone)]
+struct R(RangeToInclusive<usize>);
+
+
+fn main() {}
+
diff --git a/src/test/ui/reachable/README.md b/src/test/ui/reachable/README.md
new file mode 100644
index 0000000..8bed5fb
--- /dev/null
+++ b/src/test/ui/reachable/README.md
@@ -0,0 +1,7 @@
+A variety of tests around reachability. These tests in general check
+two things:
+
+- that we get unreachable code warnings in reasonable locations;
+- that we permit coercions **into** `!` from expressions which
+  diverge, where an expression "diverges" if it must execute some
+  subexpression of type `!`, or it has type `!` itself.
diff --git a/src/test/ui/reachable/expr_add.rs b/src/test/ui/reachable/expr_add.rs
new file mode 100644
index 0000000..b45e5da
--- /dev/null
+++ b/src/test/ui/reachable/expr_add.rs
@@ -0,0 +1,18 @@
+#![feature(never_type)]
+#![allow(unused_variables)]
+#![deny(unreachable_code)]
+
+use std::ops;
+
+struct Foo;
+
+impl ops::Add<!> for Foo {
+    type Output = !;
+    fn add(self, rhs: !) -> ! {
+        unimplemented!()
+    }
+}
+
+fn main() {
+    let x = Foo + return; //~ ERROR unreachable
+}
diff --git a/src/test/ui/reachable/expr_add.stderr b/src/test/ui/reachable/expr_add.stderr
new file mode 100644
index 0000000..02b2902
--- /dev/null
+++ b/src/test/ui/reachable/expr_add.stderr
@@ -0,0 +1,14 @@
+error: unreachable expression
+  --> $DIR/expr_add.rs:17:13
+   |
+LL |     let x = Foo + return;
+   |             ^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/expr_add.rs:3:9
+   |
+LL | #![deny(unreachable_code)]
+   |         ^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/reachable/expr_again.rs b/src/test/ui/reachable/expr_again.rs
new file mode 100644
index 0000000..243fed0c
--- /dev/null
+++ b/src/test/ui/reachable/expr_again.rs
@@ -0,0 +1,11 @@
+#![feature(box_syntax)]
+#![allow(unused_variables)]
+#![deny(unreachable_code)]
+
+fn main() {
+    let x = loop {
+        continue;
+        println!("hi");
+        //~^ ERROR unreachable statement
+    };
+}
diff --git a/src/test/ui/reachable/expr_again.stderr b/src/test/ui/reachable/expr_again.stderr
new file mode 100644
index 0000000..bdc3d14
--- /dev/null
+++ b/src/test/ui/reachable/expr_again.stderr
@@ -0,0 +1,15 @@
+error: unreachable statement
+  --> $DIR/expr_again.rs:8:9
+   |
+LL |         println!("hi");
+   |         ^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/expr_again.rs:3:9
+   |
+LL | #![deny(unreachable_code)]
+   |         ^^^^^^^^^^^^^^^^
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/reachable/expr_andand.rs b/src/test/ui/reachable/expr_andand.rs
new file mode 100644
index 0000000..173116a
--- /dev/null
+++ b/src/test/ui/reachable/expr_andand.rs
@@ -0,0 +1,13 @@
+// compile-pass
+
+#![allow(unused_variables)]
+#![allow(dead_code)]
+#![deny(unreachable_code)]
+
+fn foo() {
+    // No error here.
+    let x = false && (return);
+    println!("I am not dead.");
+}
+
+fn main() { }
diff --git a/src/test/ui/reachable/expr_array.rs b/src/test/ui/reachable/expr_array.rs
new file mode 100644
index 0000000..e6bdb97
--- /dev/null
+++ b/src/test/ui/reachable/expr_array.rs
@@ -0,0 +1,17 @@
+#![allow(unused_variables)]
+#![allow(unused_assignments)]
+#![allow(dead_code)]
+#![deny(unreachable_code)]
+#![feature(type_ascription)]
+
+fn a() {
+    // the `22` is unreachable:
+    let x: [usize; 2] = [return, 22]; //~ ERROR unreachable
+}
+
+fn b() {
+    // the array is unreachable:
+    let x: [usize; 2] = [22, return]; //~ ERROR unreachable
+}
+
+fn main() { }
diff --git a/src/test/ui/reachable/expr_array.stderr b/src/test/ui/reachable/expr_array.stderr
new file mode 100644
index 0000000..18d7ffe
--- /dev/null
+++ b/src/test/ui/reachable/expr_array.stderr
@@ -0,0 +1,20 @@
+error: unreachable expression
+  --> $DIR/expr_array.rs:9:34
+   |
+LL |     let x: [usize; 2] = [return, 22];
+   |                                  ^^
+   |
+note: lint level defined here
+  --> $DIR/expr_array.rs:4:9
+   |
+LL | #![deny(unreachable_code)]
+   |         ^^^^^^^^^^^^^^^^
+
+error: unreachable expression
+  --> $DIR/expr_array.rs:14:25
+   |
+LL |     let x: [usize; 2] = [22, return];
+   |                         ^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/reachable/expr_assign.rs b/src/test/ui/reachable/expr_assign.rs
new file mode 100644
index 0000000..e547f75
--- /dev/null
+++ b/src/test/ui/reachable/expr_assign.rs
@@ -0,0 +1,29 @@
+#![feature(never_type)]
+#![allow(unused_variables)]
+#![allow(unused_assignments)]
+#![allow(dead_code)]
+#![deny(unreachable_code)]
+
+fn foo() {
+    // No error here.
+    let x;
+    x = return; //~ ERROR unreachable
+}
+
+fn bar() {
+    use std::ptr;
+    let p: *mut ! = ptr::null_mut::<!>();
+    unsafe {
+        // Here we consider the `return` unreachable because
+        // "evaluating" the `*p` has type `!`. This is somewhat
+        // dubious, I suppose.
+        *p = return; //~ ERROR unreachable
+    }
+}
+
+fn baz() {
+    let mut i = 0;
+    *{return; &mut i} = 22; //~ ERROR unreachable
+}
+
+fn main() { }
diff --git a/src/test/ui/reachable/expr_assign.stderr b/src/test/ui/reachable/expr_assign.stderr
new file mode 100644
index 0000000..def16d9
--- /dev/null
+++ b/src/test/ui/reachable/expr_assign.stderr
@@ -0,0 +1,26 @@
+error: unreachable expression
+  --> $DIR/expr_assign.rs:10:5
+   |
+LL |     x = return;
+   |     ^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/expr_assign.rs:5:9
+   |
+LL | #![deny(unreachable_code)]
+   |         ^^^^^^^^^^^^^^^^
+
+error: unreachable expression
+  --> $DIR/expr_assign.rs:20:14
+   |
+LL |         *p = return;
+   |              ^^^^^^
+
+error: unreachable expression
+  --> $DIR/expr_assign.rs:26:15
+   |
+LL |     *{return; &mut i} = 22;
+   |               ^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/reachable/expr_block.rs b/src/test/ui/reachable/expr_block.rs
new file mode 100644
index 0000000..136bccc
--- /dev/null
+++ b/src/test/ui/reachable/expr_block.rs
@@ -0,0 +1,31 @@
+#![allow(unused_variables)]
+#![allow(unused_assignments)]
+#![allow(dead_code)]
+#![deny(unreachable_code)]
+
+fn a() {
+    // Here the tail expression is considered unreachable:
+    let x = {
+        return;
+        22 //~ ERROR unreachable
+    };
+}
+
+fn b() {
+    // Here the `x` assignment is considered unreachable, not the block:
+    let x = {
+        return;
+    };
+}
+
+fn c() {
+    // Here the `println!` is unreachable:
+    let x = {
+        return;
+        println!("foo");
+        //~^ ERROR unreachable statement
+        22
+    };
+}
+
+fn main() { }
diff --git a/src/test/ui/reachable/expr_block.stderr b/src/test/ui/reachable/expr_block.stderr
new file mode 100644
index 0000000..a498502
--- /dev/null
+++ b/src/test/ui/reachable/expr_block.stderr
@@ -0,0 +1,22 @@
+error: unreachable expression
+  --> $DIR/expr_block.rs:10:9
+   |
+LL |         22
+   |         ^^
+   |
+note: lint level defined here
+  --> $DIR/expr_block.rs:4:9
+   |
+LL | #![deny(unreachable_code)]
+   |         ^^^^^^^^^^^^^^^^
+
+error: unreachable statement
+  --> $DIR/expr_block.rs:25:9
+   |
+LL |         println!("foo");
+   |         ^^^^^^^^^^^^^^^^
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/reachable/expr_box.rs b/src/test/ui/reachable/expr_box.rs
new file mode 100644
index 0000000..00328ea
--- /dev/null
+++ b/src/test/ui/reachable/expr_box.rs
@@ -0,0 +1,8 @@
+#![feature(box_syntax)]
+#![allow(unused_variables)]
+#![deny(unreachable_code)]
+
+fn main() {
+    let x = box return; //~ ERROR unreachable
+    println!("hi");
+}
diff --git a/src/test/ui/reachable/expr_box.stderr b/src/test/ui/reachable/expr_box.stderr
new file mode 100644
index 0000000..63137ce
--- /dev/null
+++ b/src/test/ui/reachable/expr_box.stderr
@@ -0,0 +1,14 @@
+error: unreachable expression
+  --> $DIR/expr_box.rs:6:13
+   |
+LL |     let x = box return;
+   |             ^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/expr_box.rs:3:9
+   |
+LL | #![deny(unreachable_code)]
+   |         ^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/reachable/expr_call.rs b/src/test/ui/reachable/expr_call.rs
new file mode 100644
index 0000000..1eaa96c
--- /dev/null
+++ b/src/test/ui/reachable/expr_call.rs
@@ -0,0 +1,21 @@
+#![feature(never_type)]
+#![allow(unused_variables)]
+#![allow(unused_assignments)]
+#![allow(dead_code)]
+#![deny(unreachable_code)]
+
+fn foo(x: !, y: usize) { }
+
+fn bar(x: !) { }
+
+fn a() {
+    // the `22` is unreachable:
+    foo(return, 22); //~ ERROR unreachable
+}
+
+fn b() {
+    // the call is unreachable:
+    bar(return); //~ ERROR unreachable
+}
+
+fn main() { }
diff --git a/src/test/ui/reachable/expr_call.stderr b/src/test/ui/reachable/expr_call.stderr
new file mode 100644
index 0000000..df5cff1
--- /dev/null
+++ b/src/test/ui/reachable/expr_call.stderr
@@ -0,0 +1,20 @@
+error: unreachable expression
+  --> $DIR/expr_call.rs:13:17
+   |
+LL |     foo(return, 22);
+   |                 ^^
+   |
+note: lint level defined here
+  --> $DIR/expr_call.rs:5:9
+   |
+LL | #![deny(unreachable_code)]
+   |         ^^^^^^^^^^^^^^^^
+
+error: unreachable expression
+  --> $DIR/expr_call.rs:18:5
+   |
+LL |     bar(return);
+   |     ^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/reachable/expr_cast.rs b/src/test/ui/reachable/expr_cast.rs
new file mode 100644
index 0000000..f53bcb9
--- /dev/null
+++ b/src/test/ui/reachable/expr_cast.rs
@@ -0,0 +1,12 @@
+#![allow(unused_variables)]
+#![allow(unused_assignments)]
+#![allow(dead_code)]
+#![deny(unreachable_code)]
+#![feature(never_type, type_ascription)]
+
+fn a() {
+    // the cast is unreachable:
+    let x = {return} as !; //~ ERROR unreachable
+}
+
+fn main() { }
diff --git a/src/test/ui/reachable/expr_cast.stderr b/src/test/ui/reachable/expr_cast.stderr
new file mode 100644
index 0000000..3086745
--- /dev/null
+++ b/src/test/ui/reachable/expr_cast.stderr
@@ -0,0 +1,14 @@
+error: unreachable expression
+  --> $DIR/expr_cast.rs:9:13
+   |
+LL |     let x = {return} as !;
+   |             ^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/expr_cast.rs:4:9
+   |
+LL | #![deny(unreachable_code)]
+   |         ^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/reachable/expr_if.rs b/src/test/ui/reachable/expr_if.rs
new file mode 100644
index 0000000..ed43bd8
--- /dev/null
+++ b/src/test/ui/reachable/expr_if.rs
@@ -0,0 +1,31 @@
+#![allow(unused_variables)]
+#![allow(unused_assignments)]
+#![allow(dead_code)]
+#![deny(unreachable_code)]
+
+fn foo() {
+    if {return} {
+        println!("Hello, world!");
+    }
+}
+
+fn bar() {
+    if {true} {
+        return;
+    }
+    println!("I am not dead.");
+}
+
+fn baz() {
+    if {true} {
+        return;
+    } else {
+        return;
+    }
+    // As the next action to be taken after the if arms, we should
+    // report the `println!` as unreachable:
+    println!("But I am.");
+    //~^ ERROR unreachable statement
+}
+
+fn main() { }
diff --git a/src/test/ui/reachable/expr_if.stderr b/src/test/ui/reachable/expr_if.stderr
new file mode 100644
index 0000000..d11471d
--- /dev/null
+++ b/src/test/ui/reachable/expr_if.stderr
@@ -0,0 +1,15 @@
+error: unreachable statement
+  --> $DIR/expr_if.rs:27:5
+   |
+LL |     println!("But I am.");
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/expr_if.rs:4:9
+   |
+LL | #![deny(unreachable_code)]
+   |         ^^^^^^^^^^^^^^^^
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/reachable/expr_loop.rs b/src/test/ui/reachable/expr_loop.rs
new file mode 100644
index 0000000..7eab6f7
--- /dev/null
+++ b/src/test/ui/reachable/expr_loop.rs
@@ -0,0 +1,36 @@
+#![allow(unused_variables)]
+#![allow(unused_assignments)]
+#![allow(dead_code)]
+#![deny(unreachable_code)]
+
+fn a() {
+    loop { return; }
+    println!("I am dead.");
+    //~^ ERROR unreachable statement
+}
+
+fn b() {
+    loop {
+        break;
+    }
+    println!("I am not dead.");
+}
+
+fn c() {
+    loop { return; }
+    println!("I am dead.");
+    //~^ ERROR unreachable statement
+}
+
+fn d() {
+    'outer: loop { loop { break 'outer; } }
+    println!("I am not dead.");
+}
+
+fn e() {
+    loop { 'middle: loop { loop { break 'middle; } } }
+    println!("I am dead.");
+    //~^ ERROR unreachable statement
+}
+
+fn main() { }
diff --git a/src/test/ui/reachable/expr_loop.stderr b/src/test/ui/reachable/expr_loop.stderr
new file mode 100644
index 0000000..4d3e06c
--- /dev/null
+++ b/src/test/ui/reachable/expr_loop.stderr
@@ -0,0 +1,31 @@
+error: unreachable statement
+  --> $DIR/expr_loop.rs:8:5
+   |
+LL |     println!("I am dead.");
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/expr_loop.rs:4:9
+   |
+LL | #![deny(unreachable_code)]
+   |         ^^^^^^^^^^^^^^^^
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: unreachable statement
+  --> $DIR/expr_loop.rs:21:5
+   |
+LL |     println!("I am dead.");
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: unreachable statement
+  --> $DIR/expr_loop.rs:32:5
+   |
+LL |     println!("I am dead.");
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/reachable/expr_match.rs b/src/test/ui/reachable/expr_match.rs
new file mode 100644
index 0000000..2fd26b5
--- /dev/null
+++ b/src/test/ui/reachable/expr_match.rs
@@ -0,0 +1,39 @@
+#![allow(unused_variables)]
+#![allow(unused_assignments)]
+#![allow(dead_code)]
+#![deny(unreachable_code)]
+
+fn b() {
+    match () { () => return }
+    println!("I am dead");
+    //~^ ERROR unreachable statement
+}
+
+fn c() {
+    match () { () if false => return, () => () }
+    println!("I am not dead");
+}
+
+fn d() {
+    match () { () if false => return, () => return }
+    println!("I am dead");
+    //~^ ERROR unreachable statement
+}
+
+fn e() {
+    // Here the compiler fails to figure out that the `println` is dead.
+    match () { () if return => (), () => return }
+    println!("I am dead");
+}
+
+fn f() {
+    match Some(()) { None => (), Some(()) => return }
+    println!("I am not dead");
+}
+
+fn g() {
+    match Some(()) { None => return, Some(()) => () }
+    println!("I am not dead");
+}
+
+fn main() { }
diff --git a/src/test/ui/reachable/expr_match.stderr b/src/test/ui/reachable/expr_match.stderr
new file mode 100644
index 0000000..1aef06a
--- /dev/null
+++ b/src/test/ui/reachable/expr_match.stderr
@@ -0,0 +1,23 @@
+error: unreachable statement
+  --> $DIR/expr_match.rs:8:5
+   |
+LL |     println!("I am dead");
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/expr_match.rs:4:9
+   |
+LL | #![deny(unreachable_code)]
+   |         ^^^^^^^^^^^^^^^^
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: unreachable statement
+  --> $DIR/expr_match.rs:19:5
+   |
+LL |     println!("I am dead");
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/reachable/expr_method.rs b/src/test/ui/reachable/expr_method.rs
new file mode 100644
index 0000000..d917df0
--- /dev/null
+++ b/src/test/ui/reachable/expr_method.rs
@@ -0,0 +1,24 @@
+#![feature(never_type)]
+#![allow(unused_variables)]
+#![allow(unused_assignments)]
+#![allow(dead_code)]
+#![deny(unreachable_code)]
+
+struct Foo;
+
+impl Foo {
+    fn foo(&self, x: !, y: usize) { }
+    fn bar(&self, x: !) { }
+}
+
+fn a() {
+    // the `22` is unreachable:
+    Foo.foo(return, 22); //~ ERROR unreachable
+}
+
+fn b() {
+    // the call is unreachable:
+    Foo.bar(return); //~ ERROR unreachable
+}
+
+fn main() { }
diff --git a/src/test/ui/reachable/expr_method.stderr b/src/test/ui/reachable/expr_method.stderr
new file mode 100644
index 0000000..bbfa2ef
--- /dev/null
+++ b/src/test/ui/reachable/expr_method.stderr
@@ -0,0 +1,20 @@
+error: unreachable expression
+  --> $DIR/expr_method.rs:16:21
+   |
+LL |     Foo.foo(return, 22);
+   |                     ^^
+   |
+note: lint level defined here
+  --> $DIR/expr_method.rs:5:9
+   |
+LL | #![deny(unreachable_code)]
+   |         ^^^^^^^^^^^^^^^^
+
+error: unreachable expression
+  --> $DIR/expr_method.rs:21:5
+   |
+LL |     Foo.bar(return);
+   |     ^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/reachable/expr_oror.rs b/src/test/ui/reachable/expr_oror.rs
new file mode 100644
index 0000000..ecfa072
--- /dev/null
+++ b/src/test/ui/reachable/expr_oror.rs
@@ -0,0 +1,12 @@
+// compile-pass
+
+#![allow(unused_variables)]
+#![allow(dead_code)]
+#![deny(unreachable_code)]
+
+fn foo() {
+    let x = false || (return);
+    println!("I am not dead.");
+}
+
+fn main() { }
diff --git a/src/test/ui/reachable/expr_repeat.rs b/src/test/ui/reachable/expr_repeat.rs
new file mode 100644
index 0000000..0fd13c6
--- /dev/null
+++ b/src/test/ui/reachable/expr_repeat.rs
@@ -0,0 +1,12 @@
+#![allow(unused_variables)]
+#![allow(unused_assignments)]
+#![allow(dead_code)]
+#![deny(unreachable_code)]
+#![feature(type_ascription)]
+
+fn a() {
+    // the repeat is unreachable:
+    let x: [usize; 2] = [return; 2]; //~ ERROR unreachable
+}
+
+fn main() { }
diff --git a/src/test/ui/reachable/expr_repeat.stderr b/src/test/ui/reachable/expr_repeat.stderr
new file mode 100644
index 0000000..0536cde
--- /dev/null
+++ b/src/test/ui/reachable/expr_repeat.stderr
@@ -0,0 +1,14 @@
+error: unreachable expression
+  --> $DIR/expr_repeat.rs:9:25
+   |
+LL |     let x: [usize; 2] = [return; 2];
+   |                         ^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/expr_repeat.rs:4:9
+   |
+LL | #![deny(unreachable_code)]
+   |         ^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/reachable/expr_return.rs b/src/test/ui/reachable/expr_return.rs
new file mode 100644
index 0000000..0fc43f4
--- /dev/null
+++ b/src/test/ui/reachable/expr_return.rs
@@ -0,0 +1,13 @@
+#![allow(unused_variables)]
+#![allow(unused_assignments)]
+#![allow(dead_code)]
+#![deny(unreachable_code)]
+#![feature(type_ascription)]
+
+fn a() {
+    // Here we issue that the "2nd-innermost" return is unreachable,
+    // but we stop there.
+    let x = {return {return {return;}}}; //~ ERROR unreachable
+}
+
+fn main() { }
diff --git a/src/test/ui/reachable/expr_return.stderr b/src/test/ui/reachable/expr_return.stderr
new file mode 100644
index 0000000..3317da5
--- /dev/null
+++ b/src/test/ui/reachable/expr_return.stderr
@@ -0,0 +1,14 @@
+error: unreachable expression
+  --> $DIR/expr_return.rs:10:22
+   |
+LL |     let x = {return {return {return;}}};
+   |                      ^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/expr_return.rs:4:9
+   |
+LL | #![deny(unreachable_code)]
+   |         ^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/reachable/expr_struct.rs b/src/test/ui/reachable/expr_struct.rs
new file mode 100644
index 0000000..31ab405
--- /dev/null
+++ b/src/test/ui/reachable/expr_struct.rs
@@ -0,0 +1,32 @@
+#![allow(unused_variables)]
+#![allow(unused_assignments)]
+#![allow(dead_code)]
+#![deny(unreachable_code)]
+#![feature(type_ascription)]
+
+struct Foo {
+    a: usize,
+    b: usize,
+}
+
+fn a() {
+    // struct expr is unreachable:
+    let x = Foo { a: 22, b: 33, ..return }; //~ ERROR unreachable
+}
+
+fn b() {
+    // the `33` is unreachable:
+    let x = Foo { a: return, b: 33, ..return }; //~ ERROR unreachable
+}
+
+fn c() {
+    // the `..return` is unreachable:
+    let x = Foo { a: 22, b: return, ..return }; //~ ERROR unreachable
+}
+
+fn d() {
+    // the struct expr is unreachable:
+    let x = Foo { a: 22, b: return }; //~ ERROR unreachable
+}
+
+fn main() { }
diff --git a/src/test/ui/reachable/expr_struct.stderr b/src/test/ui/reachable/expr_struct.stderr
new file mode 100644
index 0000000..dcccb7a
--- /dev/null
+++ b/src/test/ui/reachable/expr_struct.stderr
@@ -0,0 +1,32 @@
+error: unreachable expression
+  --> $DIR/expr_struct.rs:14:13
+   |
+LL |     let x = Foo { a: 22, b: 33, ..return };
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/expr_struct.rs:4:9
+   |
+LL | #![deny(unreachable_code)]
+   |         ^^^^^^^^^^^^^^^^
+
+error: unreachable expression
+  --> $DIR/expr_struct.rs:19:33
+   |
+LL |     let x = Foo { a: return, b: 33, ..return };
+   |                                 ^^
+
+error: unreachable expression
+  --> $DIR/expr_struct.rs:24:39
+   |
+LL |     let x = Foo { a: 22, b: return, ..return };
+   |                                       ^^^^^^
+
+error: unreachable expression
+  --> $DIR/expr_struct.rs:29:13
+   |
+LL |     let x = Foo { a: 22, b: return };
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/reachable/expr_tup.rs b/src/test/ui/reachable/expr_tup.rs
new file mode 100644
index 0000000..90d4382
--- /dev/null
+++ b/src/test/ui/reachable/expr_tup.rs
@@ -0,0 +1,17 @@
+#![allow(unused_variables)]
+#![allow(unused_assignments)]
+#![allow(dead_code)]
+#![deny(unreachable_code)]
+#![feature(type_ascription)]
+
+fn a() {
+    // the `2` is unreachable:
+    let x: (usize, usize) = (return, 2); //~ ERROR unreachable
+}
+
+fn b() {
+    // the tuple is unreachable:
+    let x: (usize, usize) = (2, return); //~ ERROR unreachable
+}
+
+fn main() { }
diff --git a/src/test/ui/reachable/expr_tup.stderr b/src/test/ui/reachable/expr_tup.stderr
new file mode 100644
index 0000000..1837031
--- /dev/null
+++ b/src/test/ui/reachable/expr_tup.stderr
@@ -0,0 +1,20 @@
+error: unreachable expression
+  --> $DIR/expr_tup.rs:9:38
+   |
+LL |     let x: (usize, usize) = (return, 2);
+   |                                      ^
+   |
+note: lint level defined here
+  --> $DIR/expr_tup.rs:4:9
+   |
+LL | #![deny(unreachable_code)]
+   |         ^^^^^^^^^^^^^^^^
+
+error: unreachable expression
+  --> $DIR/expr_tup.rs:14:29
+   |
+LL |     let x: (usize, usize) = (2, return);
+   |                             ^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/reachable/expr_type.rs b/src/test/ui/reachable/expr_type.rs
new file mode 100644
index 0000000..8d32397
--- /dev/null
+++ b/src/test/ui/reachable/expr_type.rs
@@ -0,0 +1,12 @@
+#![allow(unused_variables)]
+#![allow(unused_assignments)]
+#![allow(dead_code)]
+#![deny(unreachable_code)]
+#![feature(never_type, type_ascription)]
+
+fn a() {
+    // the cast is unreachable:
+    let x = {return}: !; //~ ERROR unreachable
+}
+
+fn main() { }
diff --git a/src/test/ui/reachable/expr_type.stderr b/src/test/ui/reachable/expr_type.stderr
new file mode 100644
index 0000000..f867c89
--- /dev/null
+++ b/src/test/ui/reachable/expr_type.stderr
@@ -0,0 +1,14 @@
+error: unreachable expression
+  --> $DIR/expr_type.rs:9:13
+   |
+LL |     let x = {return}: !;
+   |             ^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/expr_type.rs:4:9
+   |
+LL | #![deny(unreachable_code)]
+   |         ^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/reachable/expr_unary.rs b/src/test/ui/reachable/expr_unary.rs
new file mode 100644
index 0000000..e229d22
--- /dev/null
+++ b/src/test/ui/reachable/expr_unary.rs
@@ -0,0 +1,12 @@
+#![feature(never_type)]
+#![allow(unused_variables)]
+#![allow(unused_assignments)]
+#![allow(dead_code)]
+#![deny(unreachable_code)]
+
+fn foo() {
+    let x: ! = ! { return; }; //~ ERROR unreachable
+    //~| ERROR cannot apply unary operator `!` to type `!`
+}
+
+fn main() { }
diff --git a/src/test/ui/reachable/expr_unary.stderr b/src/test/ui/reachable/expr_unary.stderr
new file mode 100644
index 0000000..6198228
--- /dev/null
+++ b/src/test/ui/reachable/expr_unary.stderr
@@ -0,0 +1,21 @@
+error[E0600]: cannot apply unary operator `!` to type `!`
+  --> $DIR/expr_unary.rs:8:16
+   |
+LL |     let x: ! = ! { return; };
+   |                ^^^^^^^^^^^^^ cannot apply unary operator `!`
+
+error: unreachable expression
+  --> $DIR/expr_unary.rs:8:16
+   |
+LL |     let x: ! = ! { return; };
+   |                ^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/expr_unary.rs:5:9
+   |
+LL | #![deny(unreachable_code)]
+   |         ^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0600`.
diff --git a/src/test/ui/reachable/expr_while.rs b/src/test/ui/reachable/expr_while.rs
new file mode 100644
index 0000000..36a3e3d
--- /dev/null
+++ b/src/test/ui/reachable/expr_while.rs
@@ -0,0 +1,30 @@
+#![allow(unused_variables)]
+#![allow(unused_assignments)]
+#![allow(dead_code)]
+#![deny(unreachable_code)]
+
+fn foo() {
+    while {return} {
+        println!("Hello, world!");
+        //~^ ERROR unreachable
+    }
+}
+
+fn bar() {
+    while {true} {
+        return;
+    }
+    println!("I am not dead.");
+}
+
+fn baz() {
+    // Here, we cite the `while` loop as dead.
+    while {return} {
+        println!("I am dead.");
+        //~^ ERROR unreachable
+    }
+    println!("I am, too.");
+    //~^ ERROR unreachable
+}
+
+fn main() { }
diff --git a/src/test/ui/reachable/expr_while.stderr b/src/test/ui/reachable/expr_while.stderr
new file mode 100644
index 0000000..d2f5588
--- /dev/null
+++ b/src/test/ui/reachable/expr_while.stderr
@@ -0,0 +1,31 @@
+error: unreachable statement
+  --> $DIR/expr_while.rs:8:9
+   |
+LL |         println!("Hello, world!");
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/expr_while.rs:4:9
+   |
+LL | #![deny(unreachable_code)]
+   |         ^^^^^^^^^^^^^^^^
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: unreachable statement
+  --> $DIR/expr_while.rs:23:9
+   |
+LL |         println!("I am dead.");
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: unreachable statement
+  --> $DIR/expr_while.rs:26:5
+   |
+LL |     println!("I am, too.");
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/reassign-ref-mut.rs b/src/test/ui/reassign-ref-mut.rs
new file mode 100644
index 0000000..d6d41e9
--- /dev/null
+++ b/src/test/ui/reassign-ref-mut.rs
@@ -0,0 +1,16 @@
+// 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
index 0000000..e623578
--- /dev/null
+++ b/src/test/ui/reassign-ref-mut.stderr
@@ -0,0 +1,20 @@
+error[E0384]: cannot assign twice to immutable variable `a`
+  --> $DIR/reassign-ref-mut.rs:12: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:14: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`.
diff --git a/src/test/ui/recursion/auxiliary/recursive_reexports.rs b/src/test/ui/recursion/auxiliary/recursive_reexports.rs
new file mode 100644
index 0000000..f98fa71
--- /dev/null
+++ b/src/test/ui/recursion/auxiliary/recursive_reexports.rs
@@ -0,0 +1,3 @@
+pub mod foo {
+    pub use foo;
+}
diff --git a/src/test/ui/recursion/recursion.rs b/src/test/ui/recursion/recursion.rs
new file mode 100644
index 0000000..ba3cc33
--- /dev/null
+++ b/src/test/ui/recursion/recursion.rs
@@ -0,0 +1,22 @@
+enum Nil {NilValue}
+struct Cons<T> {head:isize, tail:T}
+trait Dot {fn dot(&self, other:Self) -> isize;}
+impl Dot for Nil {
+  fn dot(&self, _:Nil) -> isize {0}
+}
+impl<T:Dot> Dot for Cons<T> {
+  fn dot(&self, other:Cons<T>) -> isize {
+    self.head * other.head + self.tail.dot(other.tail)
+  }
+}
+fn test<T:Dot> (n:isize, i:isize, first:T, second:T) ->isize { //~ ERROR recursion limit
+  match n {    0 => {first.dot(second)}
+      // FIXME(#4287) Error message should be here. It should be
+      // a type error to instantiate `test` at a type other than T.
+    _ => {test (n-1, i+1, Cons {head:2*i+1, tail:first}, Cons{head:i*i, tail:second})}
+  }
+}
+pub fn main() {
+  let n = test(1, 0, Nil::NilValue, Nil::NilValue);
+  println!("{}", n);
+}
diff --git a/src/test/ui/recursion/recursion.stderr b/src/test/ui/recursion/recursion.stderr
new file mode 100644
index 0000000..9213ba0
--- /dev/null
+++ b/src/test/ui/recursion/recursion.stderr
@@ -0,0 +1,14 @@
+error: reached the recursion limit while instantiating `test::<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Nil>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+  --> $DIR/recursion.rs:12:1
+   |
+LL | / fn test<T:Dot> (n:isize, i:isize, first:T, second:T) ->isize {
+LL | |   match n {    0 => {first.dot(second)}
+LL | |       // FIXME(#4287) Error message should be here. It should be
+LL | |       // a type error to instantiate `test` at a type other than T.
+LL | |     _ => {test (n-1, i+1, Cons {head:2*i+1, tail:first}, Cons{head:i*i, tail:second})}
+LL | |   }
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/recursion/recursive-enum.rs b/src/test/ui/recursion/recursive-enum.rs
new file mode 100644
index 0000000..32e7076
--- /dev/null
+++ b/src/test/ui/recursion/recursive-enum.rs
@@ -0,0 +1,4 @@
+enum List<T> { Cons(T, List<T>), Nil }
+//~^ ERROR recursive type `List` has infinite size
+
+fn main() {}
diff --git a/src/test/ui/recursion/recursive-enum.stderr b/src/test/ui/recursion/recursive-enum.stderr
new file mode 100644
index 0000000..e4674b5
--- /dev/null
+++ b/src/test/ui/recursion/recursive-enum.stderr
@@ -0,0 +1,13 @@
+error[E0072]: recursive type `List` has infinite size
+  --> $DIR/recursive-enum.rs:1:1
+   |
+LL | enum List<T> { Cons(T, List<T>), Nil }
+   | ^^^^^^^^^^^^           ------- recursive without indirection
+   | |
+   | recursive type has infinite size
+   |
+   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `List` representable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0072`.
diff --git a/src/test/ui/recursion/recursive-reexports.rs b/src/test/ui/recursion/recursive-reexports.rs
new file mode 100644
index 0000000..3d9fda3
--- /dev/null
+++ b/src/test/ui/recursion/recursive-reexports.rs
@@ -0,0 +1,7 @@
+// aux-build:recursive_reexports.rs
+
+extern crate recursive_reexports;
+
+fn f() -> recursive_reexports::S {} //~ ERROR cannot find type `S` in module `recursive_reexports`
+
+fn main() {}
diff --git a/src/test/ui/recursion/recursive-reexports.stderr b/src/test/ui/recursion/recursive-reexports.stderr
new file mode 100644
index 0000000..01afc14
--- /dev/null
+++ b/src/test/ui/recursion/recursive-reexports.stderr
@@ -0,0 +1,9 @@
+error[E0412]: cannot find type `S` in module `recursive_reexports`
+  --> $DIR/recursive-reexports.rs:5:32
+   |
+LL | fn f() -> recursive_reexports::S {}
+   |                                ^ not found in `recursive_reexports`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/src/test/ui/recursion/recursive-requirements.rs b/src/test/ui/recursion/recursive-requirements.rs
new file mode 100644
index 0000000..9cfbee5
--- /dev/null
+++ b/src/test/ui/recursion/recursive-requirements.rs
@@ -0,0 +1,19 @@
+use std::marker::PhantomData;
+
+struct AssertSync<T: Sync>(PhantomData<T>);
+
+pub struct Foo {
+    bar: *const Bar,
+    phantom: PhantomData<Bar>,
+}
+
+pub struct Bar {
+    foo: *const Foo,
+    phantom: PhantomData<Foo>,
+}
+
+fn main() {
+    let _: AssertSync<Foo> = unimplemented!();
+    //~^ ERROR E0277
+    //~| ERROR E0277
+}
diff --git a/src/test/ui/recursion/recursive-requirements.stderr b/src/test/ui/recursion/recursive-requirements.stderr
new file mode 100644
index 0000000..b304190
--- /dev/null
+++ b/src/test/ui/recursion/recursive-requirements.stderr
@@ -0,0 +1,33 @@
+error[E0277]: `*const Bar` cannot be shared between threads safely
+  --> $DIR/recursive-requirements.rs:16:12
+   |
+LL |     let _: AssertSync<Foo> = unimplemented!();
+   |            ^^^^^^^^^^^^^^^ `*const Bar` cannot be shared between threads safely
+   |
+   = help: within `Foo`, the trait `std::marker::Sync` is not implemented for `*const Bar`
+   = note: required because it appears within the type `Foo`
+note: required by `AssertSync`
+  --> $DIR/recursive-requirements.rs:3:1
+   |
+LL | struct AssertSync<T: Sync>(PhantomData<T>);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: `*const Foo` cannot be shared between threads safely
+  --> $DIR/recursive-requirements.rs:16:12
+   |
+LL |     let _: AssertSync<Foo> = unimplemented!();
+   |            ^^^^^^^^^^^^^^^ `*const Foo` cannot be shared between threads safely
+   |
+   = help: within `Foo`, the trait `std::marker::Sync` is not implemented for `*const Foo`
+   = note: required because it appears within the type `Bar`
+   = note: required because it appears within the type `std::marker::PhantomData<Bar>`
+   = note: required because it appears within the type `Foo`
+note: required by `AssertSync`
+  --> $DIR/recursive-requirements.rs:3:1
+   |
+LL | struct AssertSync<T: Sync>(PhantomData<T>);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/recursion/recursive-static-definition.rs b/src/test/ui/recursion/recursive-static-definition.rs
new file mode 100644
index 0000000..e816ce4
--- /dev/null
+++ b/src/test/ui/recursion/recursive-static-definition.rs
@@ -0,0 +1,4 @@
+pub static FOO: u32 = FOO;
+//~^ ERROR cycle detected when const-evaluating `FOO`
+
+fn main() {}
diff --git a/src/test/ui/recursion/recursive-static-definition.stderr b/src/test/ui/recursion/recursive-static-definition.stderr
new file mode 100644
index 0000000..b724c26
--- /dev/null
+++ b/src/test/ui/recursion/recursive-static-definition.stderr
@@ -0,0 +1,21 @@
+error[E0391]: cycle detected when const-evaluating `FOO`
+  --> $DIR/recursive-static-definition.rs:1:23
+   |
+LL | pub static FOO: u32 = FOO;
+   |                       ^^^
+   |
+note: ...which requires const-evaluating `FOO`...
+  --> $DIR/recursive-static-definition.rs:1:1
+   |
+LL | pub static FOO: u32 = FOO;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: ...which again requires const-evaluating `FOO`, completing the cycle
+note: cycle used when const-evaluating + checking `FOO`
+  --> $DIR/recursive-static-definition.rs:1:1
+   |
+LL | pub static FOO: u32 = FOO;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/recursion/recursive-types-are-not-uninhabited.rs b/src/test/ui/recursion/recursive-types-are-not-uninhabited.rs
new file mode 100644
index 0000000..b3e4efb
--- /dev/null
+++ b/src/test/ui/recursion/recursive-types-are-not-uninhabited.rs
@@ -0,0 +1,14 @@
+struct R<'a> {
+    r: &'a R<'a>,
+}
+
+fn foo(res: Result<u32, &R>) -> u32 {
+    let Ok(x) = res;
+    //~^ ERROR refutable pattern
+    x
+}
+
+fn main() {
+    foo(Ok(23));
+}
+
diff --git a/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr b/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr
new file mode 100644
index 0000000..dad98cf
--- /dev/null
+++ b/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr
@@ -0,0 +1,9 @@
+error[E0005]: refutable pattern in local binding: `Err(_)` not covered
+  --> $DIR/recursive-types-are-not-uninhabited.rs:6:9
+   |
+LL |     let Ok(x) = res;
+   |         ^^^^^ pattern `Err(_)` not covered
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0005`.
diff --git a/src/test/ui/ref-suggestion.nll.stderr b/src/test/ui/ref-suggestion.nll.stderr
new file mode 100644
index 0000000..9ff8e21
--- /dev/null
+++ b/src/test/ui/ref-suggestion.nll.stderr
@@ -0,0 +1,34 @@
+error[E0382]: use of moved value: `x`
+  --> $DIR/ref-suggestion.rs:4:5
+   |
+LL |     let x = vec![1];
+   |         - move occurs because `x` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
+LL |     let y = x;
+   |             - value moved here
+LL |     x;
+   |     ^ value used here after move
+
+error[E0382]: use of moved value: `x`
+  --> $DIR/ref-suggestion.rs:8:5
+   |
+LL |     let x = vec![1];
+   |         - move occurs because `x` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
+LL |     let mut y = x;
+   |                 - value moved here
+LL |     x;
+   |     ^ value used here after move
+
+error[E0382]: use of moved value: `x`
+  --> $DIR/ref-suggestion.rs:16:5
+   |
+LL |         (Some(y), ()) => {},
+   |               - value moved here
+...
+LL |     x;
+   |     ^ value used here after partial move
+   |
+   = note: move occurs because value has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/ref-suggestion.rs b/src/test/ui/ref-suggestion.rs
new file mode 100644
index 0000000..346d118
--- /dev/null
+++ b/src/test/ui/ref-suggestion.rs
@@ -0,0 +1,17 @@
+fn main() {
+    let x = vec![1];
+    let y = x;
+    x; //~ ERROR use of moved value
+
+    let x = vec![1];
+    let mut y = x;
+    x; //~ ERROR use of moved value
+
+    let x = (Some(vec![1]), ());
+
+    match x {
+        (Some(y), ()) => {},
+        _ => {},
+    }
+    x; //~ ERROR use of partially moved value
+}
diff --git a/src/test/ui/ref-suggestion.stderr b/src/test/ui/ref-suggestion.stderr
new file mode 100644
index 0000000..df677a6
--- /dev/null
+++ b/src/test/ui/ref-suggestion.stderr
@@ -0,0 +1,34 @@
+error[E0382]: use of moved value: `x`
+  --> $DIR/ref-suggestion.rs:4:5
+   |
+LL |     let y = x;
+   |         - value moved here
+LL |     x;
+   |     ^ value used here after move
+   |
+   = note: move occurs because `x` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `x`
+  --> $DIR/ref-suggestion.rs:8:5
+   |
+LL |     let mut y = x;
+   |         ----- value moved here
+LL |     x;
+   |     ^ value used here after move
+   |
+   = note: move occurs because `x` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
+
+error[E0382]: use of partially moved value: `x`
+  --> $DIR/ref-suggestion.rs:16:5
+   |
+LL |         (Some(y), ()) => {},
+   |               - value moved here
+...
+LL |     x;
+   |     ^ value used here after move
+   |
+   = note: move occurs because the value has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/refutable-pattern-errors.rs b/src/test/ui/refutable-pattern-errors.rs
new file mode 100644
index 0000000..05db247
--- /dev/null
+++ b/src/test/ui/refutable-pattern-errors.rs
@@ -0,0 +1,7 @@
+fn func((1, (Some(1), 2..=3)): (isize, (Option<isize>, isize))) { }
+//~^ ERROR refutable pattern in function argument: `(_, _)` not covered
+
+fn main() {
+    let (1, (Some(1), 2..=3)) = (1, (None, 2));
+    //~^ ERROR refutable pattern in local binding: `(-2147483648i32..=0i32, _)` not covered
+}
diff --git a/src/test/ui/refutable-pattern-errors.stderr b/src/test/ui/refutable-pattern-errors.stderr
new file mode 100644
index 0000000..b7001e3
--- /dev/null
+++ b/src/test/ui/refutable-pattern-errors.stderr
@@ -0,0 +1,15 @@
+error[E0005]: refutable pattern in function argument: `(_, _)` not covered
+  --> $DIR/refutable-pattern-errors.rs:1:9
+   |
+LL | fn func((1, (Some(1), 2..=3)): (isize, (Option<isize>, isize))) { }
+   |         ^^^^^^^^^^^^^^^^^^^^^ pattern `(_, _)` not covered
+
+error[E0005]: refutable pattern in local binding: `(-2147483648i32..=0i32, _)` not covered
+  --> $DIR/refutable-pattern-errors.rs:5:9
+   |
+LL |     let (1, (Some(1), 2..=3)) = (1, (None, 2));
+   |         ^^^^^^^^^^^^^^^^^^^^^ pattern `(-2147483648i32..=0i32, _)` not covered
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0005`.
diff --git a/src/test/ui/refutable-pattern-in-fn-arg.rs b/src/test/ui/refutable-pattern-in-fn-arg.rs
new file mode 100644
index 0000000..a2d9e19
--- /dev/null
+++ b/src/test/ui/refutable-pattern-in-fn-arg.rs
@@ -0,0 +1,5 @@
+fn main() {
+    let f = |3: isize| println!("hello");
+    //~^ ERROR refutable pattern in function argument: `_` not covered
+    f(4);
+}
diff --git a/src/test/ui/refutable-pattern-in-fn-arg.stderr b/src/test/ui/refutable-pattern-in-fn-arg.stderr
new file mode 100644
index 0000000..8666e6b
--- /dev/null
+++ b/src/test/ui/refutable-pattern-in-fn-arg.stderr
@@ -0,0 +1,9 @@
+error[E0005]: refutable pattern in function argument: `_` not covered
+  --> $DIR/refutable-pattern-in-fn-arg.rs:2:14
+   |
+LL |     let f = |3: isize| println!("hello");
+   |              ^ pattern `_` not covered
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0005`.
diff --git a/src/test/ui/regions-fn-subtyping-return-static-fail.rs b/src/test/ui/regions-fn-subtyping-return-static-fail.rs
new file mode 100644
index 0000000..2dd0c97
--- /dev/null
+++ b/src/test/ui/regions-fn-subtyping-return-static-fail.rs
@@ -0,0 +1,52 @@
+// In this fn, the type `F` is a function that takes a reference to a
+// struct and returns another reference with the same lifetime.
+//
+// Meanwhile, the bare fn `foo` takes a reference to a struct with
+// *ANY* lifetime and returns a reference with the 'static lifetime.
+// This can safely be considered to be an instance of `F` because all
+// lifetimes are sublifetimes of 'static.
+
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+struct S;
+
+// Given 'cx, return 'cx
+type F = for<'cx> fn(&'cx S) -> &'cx S;
+fn want_F(f: F) { }
+
+// Given anything, return 'static
+type G = for<'cx> fn(&'cx S) -> &'static S;
+fn want_G(f: G) { }
+
+// Should meet both.
+fn foo(x: &S) -> &'static S {
+    panic!()
+}
+
+// Should meet both.
+fn bar<'a,'b>(x: &'a S) -> &'b S {
+    panic!()
+}
+
+// Meets F, but not G.
+fn baz(x: &S) -> &S {
+    panic!()
+}
+
+fn supply_F() {
+    want_F(foo);
+
+    want_F(bar); //~ ERROR mismatched types
+
+    want_F(baz);
+}
+
+fn supply_G() {
+    want_G(foo);
+    want_G(bar);
+    want_G(baz); //~ ERROR mismatched types
+}
+
+pub fn main() {
+}
diff --git a/src/test/ui/regions-fn-subtyping-return-static-fail.stderr b/src/test/ui/regions-fn-subtyping-return-static-fail.stderr
new file mode 100644
index 0000000..35478a7
--- /dev/null
+++ b/src/test/ui/regions-fn-subtyping-return-static-fail.stderr
@@ -0,0 +1,21 @@
+error[E0308]: mismatched types
+  --> $DIR/regions-fn-subtyping-return-static-fail.rs:40:12
+   |
+LL |     want_F(bar);
+   |            ^^^ expected concrete lifetime, found bound lifetime parameter 'cx
+   |
+   = note: expected type `for<'cx> fn(&'cx S) -> &'cx S`
+              found type `for<'a> fn(&'a S) -> &S {bar::<'_>}`
+
+error[E0308]: mismatched types
+  --> $DIR/regions-fn-subtyping-return-static-fail.rs:48:12
+   |
+LL |     want_G(baz);
+   |            ^^^ expected concrete lifetime, found bound lifetime parameter 'cx
+   |
+   = note: expected type `for<'cx> fn(&'cx S) -> &'static S`
+              found type `for<'r> fn(&'r S) -> &'r S {baz}`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/regions/auxiliary/rbmtp_cross_crate_lib.rs b/src/test/ui/regions/auxiliary/rbmtp_cross_crate_lib.rs
new file mode 100644
index 0000000..ce2a3a7
--- /dev/null
+++ b/src/test/ui/regions/auxiliary/rbmtp_cross_crate_lib.rs
@@ -0,0 +1,32 @@
+// Check that method bounds declared on traits/impls in a cross-crate
+// scenario work. This is the library portion of the test.
+
+pub enum MaybeOwned<'a> {
+    Owned(isize),
+    Borrowed(&'a isize)
+}
+
+pub struct Inv<'a> { // invariant w/r/t 'a
+    x: &'a mut &'a isize
+}
+
+// I encountered a bug at some point with encoding the IntoMaybeOwned
+// trait, so I'll use that as the template for this test.
+pub trait IntoMaybeOwned<'a> {
+    fn into_maybe_owned(self) -> MaybeOwned<'a>;
+
+    // Note: without this `into_inv` method, the trait is
+    // contravariant w/r/t `'a`, since if you look strictly at the
+    // interface, it only returns `'a`. This complicates the
+    // downstream test since it wants invariance to force an error.
+    // Hence we add this method.
+    fn into_inv(self) -> Inv<'a>;
+
+    fn bigger_region<'b:'a>(self, b: Inv<'b>);
+}
+
+impl<'a> IntoMaybeOwned<'a> for Inv<'a> {
+    fn into_maybe_owned(self) -> MaybeOwned<'a> { panic!() }
+    fn into_inv(self) -> Inv<'a> { panic!() }
+    fn bigger_region<'b:'a>(self, b: Inv<'b>) { panic!() }
+}
diff --git a/src/test/ui/regions/issue-56537-closure-uses-region-from-container.rs b/src/test/ui/regions/issue-56537-closure-uses-region-from-container.rs
new file mode 100644
index 0000000..24676fe
--- /dev/null
+++ b/src/test/ui/regions/issue-56537-closure-uses-region-from-container.rs
@@ -0,0 +1,74 @@
+// This is a collection of examples where a function's formal
+// parameter has an explicit lifetime and a closure within that
+// function returns that formal parameter. The closure's return type,
+// to be correctly inferred, needs to include the lifetime introduced
+// by the function.
+//
+// This works today, which precludes changing things so that closures
+// follow the same lifetime-elision rules used elsehwere. See
+// rust-lang/rust#56537
+
+// compile-pass
+// We are already testing NLL explicitly via the revision system below.
+// ignore-compare-mode-nll
+
+// revisions: ll nll migrate
+//[ll] compile-flags:-Zborrowck=ast
+//[nll] compile-flags:-Zborrowck=mir -Z two-phase-borrows
+//[migrate] compile-flags:-Zborrowck=migrate -Z two-phase-borrows
+
+fn willy_no_annot<'w>(p: &'w str, q: &str) -> &'w str {
+    let free_dumb = |_x| { p }; // no type annotation at all
+    let hello = format!("Hello");
+    free_dumb(&hello)
+}
+
+fn willy_ret_type_annot<'w>(p: &'w str, q: &str) -> &'w str {
+    let free_dumb = |_x| -> &str { p }; // type annotation on the return type
+    let hello = format!("Hello");
+    free_dumb(&hello)
+}
+
+fn willy_ret_region_annot<'w>(p: &'w str, q: &str) -> &'w str {
+    let free_dumb = |_x| -> &'w str { p }; // type+region annotation on return type
+    let hello = format!("Hello");
+    free_dumb(&hello)
+}
+
+fn willy_arg_type_ret_type_annot<'w>(p: &'w str, q: &str) -> &'w str {
+    let free_dumb = |_x: &str| -> &str { p }; // type annotation on arg and return types
+    let hello = format!("Hello");
+    free_dumb(&hello)
+}
+
+fn willy_arg_type_ret_region_annot<'w>(p: &'w str, q: &str) -> &'w str {
+    let free_dumb = |_x: &str| -> &'w str { p }; // fully annotated
+    let hello = format!("Hello");
+    free_dumb(&hello)
+}
+
+fn main() {
+    let world = format!("World");
+    let w1: &str = {
+        let hello = format!("He11o");
+        willy_no_annot(&world, &hello)
+    };
+    let w2: &str = {
+        let hello = format!("He22o");
+        willy_ret_type_annot(&world, &hello)
+    };
+    let w3: &str = {
+        let hello = format!("He33o");
+        willy_ret_region_annot(&world, &hello)
+    };
+    let w4: &str = {
+        let hello = format!("He44o");
+        willy_arg_type_ret_type_annot(&world, &hello)
+    };
+    let w5: &str = {
+        let hello = format!("He55o");
+        willy_arg_type_ret_region_annot(&world, &hello)
+    };
+    assert_eq!((w1, w2, w3, w4, w5),
+               ("World","World","World","World","World"));
+}
diff --git a/src/test/ui/regions/region-borrow-params-issue-29793-big.ast.nll.stderr b/src/test/ui/regions/region-borrow-params-issue-29793-big.ast.nll.stderr
new file mode 100644
index 0000000..8fb1ebb
--- /dev/null
+++ b/src/test/ui/regions/region-borrow-params-issue-29793-big.ast.nll.stderr
@@ -0,0 +1,39 @@
+error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function
+  --> $DIR/region-borrow-params-issue-29793-big.rs:71:26
+   |
+LL |         WrapB::new().set(|t: bool| if t { x } else { y }) // (separate errors for `x` vs `y`)
+   |                          ^^^^^^^^^        - `x` is borrowed here
+   |                          |
+   |                          may outlive borrowed value `x`
+   |
+note: closure is returned here
+  --> $DIR/region-borrow-params-issue-29793-big.rs:71:9
+   |
+LL |         WrapB::new().set(|t: bool| if t { x } else { y }) // (separate errors for `x` vs `y`)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword
+   |
+LL |         WrapB::new().set(move |t: bool| if t { x } else { y }) // (separate errors for `x` vs `y`)
+   |                          ^^^^^^^^^^^^^^
+
+error[E0373]: closure may outlive the current function, but it borrows `y`, which is owned by the current function
+  --> $DIR/region-borrow-params-issue-29793-big.rs:71:26
+   |
+LL |         WrapB::new().set(|t: bool| if t { x } else { y }) // (separate errors for `x` vs `y`)
+   |                          ^^^^^^^^^                   - `y` is borrowed here
+   |                          |
+   |                          may outlive borrowed value `y`
+   |
+note: closure is returned here
+  --> $DIR/region-borrow-params-issue-29793-big.rs:71:9
+   |
+LL |         WrapB::new().set(|t: bool| if t { x } else { y }) // (separate errors for `x` vs `y`)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: to force the closure to take ownership of `y` (and any other referenced variables), use the `move` keyword
+   |
+LL |         WrapB::new().set(move |t: bool| if t { x } else { y }) // (separate errors for `x` vs `y`)
+   |                          ^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0373`.
diff --git a/src/test/ui/regions/region-borrow-params-issue-29793-big.ast.stderr b/src/test/ui/regions/region-borrow-params-issue-29793-big.ast.stderr
new file mode 100644
index 0000000..27d8ce4a
--- /dev/null
+++ b/src/test/ui/regions/region-borrow-params-issue-29793-big.ast.stderr
@@ -0,0 +1,29 @@
+error[E0597]: `x` does not live long enough
+  --> $DIR/region-borrow-params-issue-29793-big.rs:71:43
+   |
+LL |         WrapB::new().set(|t: bool| if t { x } else { y }) // (separate errors for `x` vs `y`)
+   |                          ---------        ^ borrowed value does not live long enough
+   |                          |
+   |                          capture occurs here
+...
+LL |     });
+   |     - borrowed value dropped before borrower
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error[E0597]: `y` does not live long enough
+  --> $DIR/region-borrow-params-issue-29793-big.rs:71:54
+   |
+LL |         WrapB::new().set(|t: bool| if t { x } else { y }) // (separate errors for `x` vs `y`)
+   |                          ---------                   ^ borrowed value does not live long enough
+   |                          |
+   |                          capture occurs here
+...
+LL |     });
+   |     - borrowed value dropped before borrower
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/regions/region-borrow-params-issue-29793-big.mir.stderr b/src/test/ui/regions/region-borrow-params-issue-29793-big.mir.stderr
new file mode 100644
index 0000000..8fb1ebb
--- /dev/null
+++ b/src/test/ui/regions/region-borrow-params-issue-29793-big.mir.stderr
@@ -0,0 +1,39 @@
+error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function
+  --> $DIR/region-borrow-params-issue-29793-big.rs:71:26
+   |
+LL |         WrapB::new().set(|t: bool| if t { x } else { y }) // (separate errors for `x` vs `y`)
+   |                          ^^^^^^^^^        - `x` is borrowed here
+   |                          |
+   |                          may outlive borrowed value `x`
+   |
+note: closure is returned here
+  --> $DIR/region-borrow-params-issue-29793-big.rs:71:9
+   |
+LL |         WrapB::new().set(|t: bool| if t { x } else { y }) // (separate errors for `x` vs `y`)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword
+   |
+LL |         WrapB::new().set(move |t: bool| if t { x } else { y }) // (separate errors for `x` vs `y`)
+   |                          ^^^^^^^^^^^^^^
+
+error[E0373]: closure may outlive the current function, but it borrows `y`, which is owned by the current function
+  --> $DIR/region-borrow-params-issue-29793-big.rs:71:26
+   |
+LL |         WrapB::new().set(|t: bool| if t { x } else { y }) // (separate errors for `x` vs `y`)
+   |                          ^^^^^^^^^                   - `y` is borrowed here
+   |                          |
+   |                          may outlive borrowed value `y`
+   |
+note: closure is returned here
+  --> $DIR/region-borrow-params-issue-29793-big.rs:71:9
+   |
+LL |         WrapB::new().set(|t: bool| if t { x } else { y }) // (separate errors for `x` vs `y`)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: to force the closure to take ownership of `y` (and any other referenced variables), use the `move` keyword
+   |
+LL |         WrapB::new().set(move |t: bool| if t { x } else { y }) // (separate errors for `x` vs `y`)
+   |                          ^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0373`.
diff --git a/src/test/ui/regions/region-borrow-params-issue-29793-big.rs b/src/test/ui/regions/region-borrow-params-issue-29793-big.rs
new file mode 100644
index 0000000..f21140b
--- /dev/null
+++ b/src/test/ui/regions/region-borrow-params-issue-29793-big.rs
@@ -0,0 +1,80 @@
+// Issue #29793, big regression test: do not let borrows of
+// parameters to ever be returned (expanded with exploration of
+// variations).
+//
+// This is the version of the test that actually exposed unsound
+// behavior (because the improperly accepted closure was actually
+// able to be invoked).
+
+// ignore-tidy-linelength
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+struct WrapA<F>(Option<F>);
+
+impl<F> WrapA<F> {
+    fn new() -> WrapA<F> {
+        WrapA(None)
+    }
+    fn set(mut self, f: F) -> Self {
+        self.0 = Some(f);
+        self
+    }
+}
+
+struct WrapB<F>(Option<F>);
+
+impl<F> WrapB<F> {
+    fn new() -> WrapB<F> {
+        WrapB(None)
+    }
+    fn set(mut self, f: F) -> Self {
+        self.0 = Some(f);
+        self
+    }
+}
+
+trait DoStuff : Sized {
+    fn handle(self);
+}
+
+impl<F, T> DoStuff for WrapA<F>
+    where F: FnMut(usize, usize) -> T, T: DoStuff {
+        fn handle(mut self) {
+            if let Some(ref mut f) = self.0 {
+                let x = f(1, 2);
+                let _foo = [0usize; 16];
+                x.handle();
+            }
+        }
+    }
+
+impl<F> DoStuff for WrapB<F> where F: FnMut(bool) -> usize {
+    fn handle(mut self) {
+        if let Some(ref mut f) = self.0 {
+            println!("{}", f(true));
+        }
+    }
+}
+
+impl<F, T> WrapA<F>
+    where F: FnMut(usize, usize) -> T, T: DoStuff {
+        fn handle_ref(&mut self) {
+            if let Some(ref mut f) = self.0 {
+                let x = f(1, 2);
+            }
+        }
+    }
+
+fn main() {
+    let mut w = WrapA::new().set(|x: usize, y: usize| {
+        WrapB::new().set(|t: bool| if t { x } else { y }) // (separate errors for `x` vs `y`)
+            //[ast]~^ ERROR `x` does not live long enough
+            //[ast]~| ERROR `y` does not live long enough
+            //[mir]~^^^ ERROR closure may outlive the current function
+            //[mir]~| ERROR closure may outlive the current function
+    });
+
+    w.handle(); // This works
+    // w.handle_ref(); // This doesn't
+}
diff --git a/src/test/ui/regions/region-borrow-params-issue-29793-small.nll.stderr b/src/test/ui/regions/region-borrow-params-issue-29793-small.nll.stderr
new file mode 100644
index 0000000..18610b7
--- /dev/null
+++ b/src/test/ui/regions/region-borrow-params-issue-29793-small.nll.stderr
@@ -0,0 +1,363 @@
+error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function
+  --> $DIR/region-borrow-params-issue-29793-small.rs:9:17
+   |
+LL |         let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                 ^^^^^^^^^        - `x` is borrowed here
+   |                 |
+   |                 may outlive borrowed value `x`
+   |
+note: closure is returned here
+  --> $DIR/region-borrow-params-issue-29793-small.rs:12:16
+   |
+LL |         return f;
+   |                ^
+help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword
+   |
+LL |         let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                 ^^^^^^^^^^^^^^
+
+error[E0373]: closure may outlive the current function, but it borrows `y`, which is owned by the current function
+  --> $DIR/region-borrow-params-issue-29793-small.rs:9:17
+   |
+LL |         let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                 ^^^^^^^^^                   - `y` is borrowed here
+   |                 |
+   |                 may outlive borrowed value `y`
+   |
+note: closure is returned here
+  --> $DIR/region-borrow-params-issue-29793-small.rs:12:16
+   |
+LL |         return f;
+   |                ^
+help: to force the closure to take ownership of `y` (and any other referenced variables), use the `move` keyword
+   |
+LL |         let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                 ^^^^^^^^^^^^^^
+
+error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function
+  --> $DIR/region-borrow-params-issue-29793-small.rs:24:17
+   |
+LL |         let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                 ^^^^^^^^^        - `x` is borrowed here
+   |                 |
+   |                 may outlive borrowed value `x`
+   |
+note: closure is returned here
+  --> $DIR/region-borrow-params-issue-29793-small.rs:27:9
+   |
+LL |         f
+   |         ^
+help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword
+   |
+LL |         let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                 ^^^^^^^^^^^^^^
+
+error[E0373]: closure may outlive the current function, but it borrows `y`, which is owned by the current function
+  --> $DIR/region-borrow-params-issue-29793-small.rs:24:17
+   |
+LL |         let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                 ^^^^^^^^^                   - `y` is borrowed here
+   |                 |
+   |                 may outlive borrowed value `y`
+   |
+note: closure is returned here
+  --> $DIR/region-borrow-params-issue-29793-small.rs:27:9
+   |
+LL |         f
+   |         ^
+help: to force the closure to take ownership of `y` (and any other referenced variables), use the `move` keyword
+   |
+LL |         let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                 ^^^^^^^^^^^^^^
+
+error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function
+  --> $DIR/region-borrow-params-issue-29793-small.rs:55:17
+   |
+LL |         let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                 ^^^^^^^^^        - `x` is borrowed here
+   |                 |
+   |                 may outlive borrowed value `x`
+   |
+note: closure is returned here
+  --> $DIR/region-borrow-params-issue-29793-small.rs:58:16
+   |
+LL |         return Box::new(f);
+   |                ^^^^^^^^^^^
+help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword
+   |
+LL |         let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                 ^^^^^^^^^^^^^^
+
+error[E0373]: closure may outlive the current function, but it borrows `y`, which is owned by the current function
+  --> $DIR/region-borrow-params-issue-29793-small.rs:55:17
+   |
+LL |         let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                 ^^^^^^^^^                   - `y` is borrowed here
+   |                 |
+   |                 may outlive borrowed value `y`
+   |
+note: closure is returned here
+  --> $DIR/region-borrow-params-issue-29793-small.rs:58:16
+   |
+LL |         return Box::new(f);
+   |                ^^^^^^^^^^^
+help: to force the closure to take ownership of `y` (and any other referenced variables), use the `move` keyword
+   |
+LL |         let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                 ^^^^^^^^^^^^^^
+
+error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function
+  --> $DIR/region-borrow-params-issue-29793-small.rs:66:17
+   |
+LL |         let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                 ^^^^^^^^^        - `x` is borrowed here
+   |                 |
+   |                 may outlive borrowed value `x`
+   |
+note: closure is returned here
+  --> $DIR/region-borrow-params-issue-29793-small.rs:69:9
+   |
+LL |         Box::new(f)
+   |         ^^^^^^^^^^^
+help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword
+   |
+LL |         let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                 ^^^^^^^^^^^^^^
+
+error[E0373]: closure may outlive the current function, but it borrows `y`, which is owned by the current function
+  --> $DIR/region-borrow-params-issue-29793-small.rs:66:17
+   |
+LL |         let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                 ^^^^^^^^^                   - `y` is borrowed here
+   |                 |
+   |                 may outlive borrowed value `y`
+   |
+note: closure is returned here
+  --> $DIR/region-borrow-params-issue-29793-small.rs:69:9
+   |
+LL |         Box::new(f)
+   |         ^^^^^^^^^^^
+help: to force the closure to take ownership of `y` (and any other referenced variables), use the `move` keyword
+   |
+LL |         let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                 ^^^^^^^^^^^^^^
+
+error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function
+  --> $DIR/region-borrow-params-issue-29793-small.rs:90:21
+   |
+LL |             let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^        - `x` is borrowed here
+   |                     |
+   |                     may outlive borrowed value `x`
+   |
+note: closure is returned here
+  --> $DIR/region-borrow-params-issue-29793-small.rs:93:20
+   |
+LL |             return Box::new(f);
+   |                    ^^^^^^^^^^^
+help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword
+   |
+LL |             let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^^^^^^
+
+error[E0373]: closure may outlive the current function, but it borrows `y`, which is owned by the current function
+  --> $DIR/region-borrow-params-issue-29793-small.rs:90:21
+   |
+LL |             let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^                   - `y` is borrowed here
+   |                     |
+   |                     may outlive borrowed value `y`
+   |
+note: closure is returned here
+  --> $DIR/region-borrow-params-issue-29793-small.rs:93:20
+   |
+LL |             return Box::new(f);
+   |                    ^^^^^^^^^^^
+help: to force the closure to take ownership of `y` (and any other referenced variables), use the `move` keyword
+   |
+LL |             let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^^^^^^
+
+error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function
+  --> $DIR/region-borrow-params-issue-29793-small.rs:104:21
+   |
+LL |             let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^        - `x` is borrowed here
+   |                     |
+   |                     may outlive borrowed value `x`
+   |
+note: closure is returned here
+  --> $DIR/region-borrow-params-issue-29793-small.rs:107:13
+   |
+LL |             Box::new(f)
+   |             ^^^^^^^^^^^
+help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword
+   |
+LL |             let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^^^^^^
+
+error[E0373]: closure may outlive the current function, but it borrows `y`, which is owned by the current function
+  --> $DIR/region-borrow-params-issue-29793-small.rs:104:21
+   |
+LL |             let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^                   - `y` is borrowed here
+   |                     |
+   |                     may outlive borrowed value `y`
+   |
+note: closure is returned here
+  --> $DIR/region-borrow-params-issue-29793-small.rs:107:13
+   |
+LL |             Box::new(f)
+   |             ^^^^^^^^^^^
+help: to force the closure to take ownership of `y` (and any other referenced variables), use the `move` keyword
+   |
+LL |             let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^^^^^^
+
+error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function
+  --> $DIR/region-borrow-params-issue-29793-small.rs:132:21
+   |
+LL |             let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^        - `x` is borrowed here
+   |                     |
+   |                     may outlive borrowed value `x`
+   |
+note: closure is returned here
+  --> $DIR/region-borrow-params-issue-29793-small.rs:135:20
+   |
+LL |             return Box::new(f);
+   |                    ^^^^^^^^^^^
+help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword
+   |
+LL |             let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^^^^^^
+
+error[E0373]: closure may outlive the current function, but it borrows `y`, which is owned by the current function
+  --> $DIR/region-borrow-params-issue-29793-small.rs:132:21
+   |
+LL |             let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^                   - `y` is borrowed here
+   |                     |
+   |                     may outlive borrowed value `y`
+   |
+note: closure is returned here
+  --> $DIR/region-borrow-params-issue-29793-small.rs:135:20
+   |
+LL |             return Box::new(f);
+   |                    ^^^^^^^^^^^
+help: to force the closure to take ownership of `y` (and any other referenced variables), use the `move` keyword
+   |
+LL |             let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^^^^^^
+
+error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function
+  --> $DIR/region-borrow-params-issue-29793-small.rs:147:21
+   |
+LL |             let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^        - `x` is borrowed here
+   |                     |
+   |                     may outlive borrowed value `x`
+   |
+note: closure is returned here
+  --> $DIR/region-borrow-params-issue-29793-small.rs:150:13
+   |
+LL |             Box::new(f)
+   |             ^^^^^^^^^^^
+help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword
+   |
+LL |             let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^^^^^^
+
+error[E0373]: closure may outlive the current function, but it borrows `y`, which is owned by the current function
+  --> $DIR/region-borrow-params-issue-29793-small.rs:147:21
+   |
+LL |             let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^                   - `y` is borrowed here
+   |                     |
+   |                     may outlive borrowed value `y`
+   |
+note: closure is returned here
+  --> $DIR/region-borrow-params-issue-29793-small.rs:150:13
+   |
+LL |             Box::new(f)
+   |             ^^^^^^^^^^^
+help: to force the closure to take ownership of `y` (and any other referenced variables), use the `move` keyword
+   |
+LL |             let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^^^^^^
+
+error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function
+  --> $DIR/region-borrow-params-issue-29793-small.rs:175:21
+   |
+LL |             let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^        - `x` is borrowed here
+   |                     |
+   |                     may outlive borrowed value `x`
+   |
+note: closure is returned here
+  --> $DIR/region-borrow-params-issue-29793-small.rs:178:20
+   |
+LL |             return Box::new(f);
+   |                    ^^^^^^^^^^^
+help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword
+   |
+LL |             let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^^^^^^
+
+error[E0373]: closure may outlive the current function, but it borrows `y`, which is owned by the current function
+  --> $DIR/region-borrow-params-issue-29793-small.rs:175:21
+   |
+LL |             let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^                   - `y` is borrowed here
+   |                     |
+   |                     may outlive borrowed value `y`
+   |
+note: closure is returned here
+  --> $DIR/region-borrow-params-issue-29793-small.rs:178:20
+   |
+LL |             return Box::new(f);
+   |                    ^^^^^^^^^^^
+help: to force the closure to take ownership of `y` (and any other referenced variables), use the `move` keyword
+   |
+LL |             let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^^^^^^
+
+error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function
+  --> $DIR/region-borrow-params-issue-29793-small.rs:189:21
+   |
+LL |             let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^        - `x` is borrowed here
+   |                     |
+   |                     may outlive borrowed value `x`
+   |
+note: closure is returned here
+  --> $DIR/region-borrow-params-issue-29793-small.rs:192:13
+   |
+LL |             Box::new(f)
+   |             ^^^^^^^^^^^
+help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword
+   |
+LL |             let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^^^^^^
+
+error[E0373]: closure may outlive the current function, but it borrows `y`, which is owned by the current function
+  --> $DIR/region-borrow-params-issue-29793-small.rs:189:21
+   |
+LL |             let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^                   - `y` is borrowed here
+   |                     |
+   |                     may outlive borrowed value `y`
+   |
+note: closure is returned here
+  --> $DIR/region-borrow-params-issue-29793-small.rs:192:13
+   |
+LL |             Box::new(f)
+   |             ^^^^^^^^^^^
+help: to force the closure to take ownership of `y` (and any other referenced variables), use the `move` keyword
+   |
+LL |             let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^^^^^^
+
+error: aborting due to 20 previous errors
+
+For more information about this error, try `rustc --explain E0373`.
diff --git a/src/test/ui/regions/region-borrow-params-issue-29793-small.rs b/src/test/ui/regions/region-borrow-params-issue-29793-small.rs
new file mode 100644
index 0000000..08ed79c
--- /dev/null
+++ b/src/test/ui/regions/region-borrow-params-issue-29793-small.rs
@@ -0,0 +1,213 @@
+// Issue #29793, small regression tests: do not let borrows of
+// parameters to ever be returned (expanded with exploration of
+// variations).
+
+// CLOSURES
+
+fn escaping_borrow_of_closure_params_1() {
+    let g = |x: usize, y:usize| {
+        let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+        //~^ ERROR `x` does not live long enough
+        //~| ERROR `y` does not live long enough
+        return f;
+    };
+
+    // We delberately do not call `g`; this small version of the test,
+    // after adding such a call, was (properly) rejected even when the
+    // system still suffered from issue #29793.
+
+    // g(10, 20)(true);
+}
+
+fn escaping_borrow_of_closure_params_2() {
+    let g = |x: usize, y:usize| {
+        let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+        //~^ ERROR `x` does not live long enough
+        //~| ERROR `y` does not live long enough
+        f
+    };
+
+    // (we don't call `g`; see above)
+}
+
+fn move_of_closure_params() {
+    let g = |x: usize, y:usize| {
+        let f = move |t: bool| if t { x } else { y };
+        f;
+    };
+    // (this code is fine, so lets go ahead and ensure rustc accepts call of `g`)
+    (g(1,2));
+}
+
+fn ok_borrow_of_fn_params(a: usize, b:usize) {
+    let g = |x: usize, y:usize| {
+        let f = |t: bool| if t { a } else { b };
+        return f;
+    };
+    // (this code is fine, so lets go ahead and ensure rustc accepts call of `g`)
+    (g(1,2))(true);
+}
+
+// TOP-LEVEL FN'S
+
+fn escaping_borrow_of_fn_params_1() {
+    fn g<'a>(x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> {
+        let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+        //~^ ERROR E0373
+        //~| ERROR E0373
+        return Box::new(f);
+    };
+
+    // (we don't call `g`; see above)
+}
+
+fn escaping_borrow_of_fn_params_2() {
+    fn g<'a>(x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> {
+        let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+        //~^ ERROR E0373
+        //~| ERROR E0373
+        Box::new(f)
+    };
+
+    // (we don't call `g`; see above)
+}
+
+fn move_of_fn_params() {
+    fn g<'a>(x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> {
+        let f = move |t: bool| if t { x } else { y };
+        return Box::new(f);
+    };
+    // (this code is fine, so lets go ahead and ensure rustc accepts call of `g`)
+    (g(1,2))(true);
+}
+
+// INHERENT METHODS
+
+fn escaping_borrow_of_method_params_1() {
+    struct S;
+    impl S {
+        fn g<'a>(&self, x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> {
+            let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+            //~^ ERROR E0373
+            //~| ERROR E0373
+            return Box::new(f);
+        }
+    }
+
+    // (we don't call `g`; see above)
+}
+
+fn escaping_borrow_of_method_params_2() {
+    struct S;
+    impl S {
+        fn g<'a>(&self, x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> {
+            let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+            //~^ ERROR E0373
+            //~| ERROR E0373
+            Box::new(f)
+        }
+    }
+    // (we don't call `g`; see above)
+}
+
+fn move_of_method_params() {
+    struct S;
+    impl S {
+        fn g<'a>(&self, x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> {
+            let f = move |t: bool| if t { x } else { y };
+            return Box::new(f);
+        }
+    }
+    // (this code is fine, so lets go ahead and ensure rustc accepts call of `g`)
+    (S.g(1,2))(true);
+}
+
+// TRAIT IMPL METHODS
+
+fn escaping_borrow_of_trait_impl_params_1() {
+    trait T { fn g<'a>(&self, x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a>; }
+    struct S;
+    impl T for S {
+        fn g<'a>(&self, x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> {
+            let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+            //~^ ERROR E0373
+            //~| ERROR E0373
+            return Box::new(f);
+        }
+    }
+
+    // (we don't call `g`; see above)
+}
+
+fn escaping_borrow_of_trait_impl_params_2() {
+    trait T { fn g<'a>(&self, x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a>; }
+    struct S;
+    impl T for S {
+        fn g<'a>(&self, x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> {
+            let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+            //~^ ERROR E0373
+            //~| ERROR E0373
+            Box::new(f)
+        }
+    }
+    // (we don't call `g`; see above)
+}
+
+fn move_of_trait_impl_params() {
+    trait T { fn g<'a>(&self, x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a>; }
+    struct S;
+    impl T for S {
+        fn g<'a>(&self, x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> {
+            let f = move |t: bool| if t { x } else { y };
+            return Box::new(f);
+        }
+    }
+    // (this code is fine, so lets go ahead and ensure rustc accepts call of `g`)
+    (S.g(1,2))(true);
+}
+
+// TRAIT DEFAULT METHODS
+
+fn escaping_borrow_of_trait_default_params_1() {
+    struct S;
+    trait T {
+        fn g<'a>(&self, x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> {
+            let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+            //~^ ERROR E0373
+            //~| ERROR E0373
+            return Box::new(f);
+        }
+    }
+    impl T for S {}
+    // (we don't call `g`; see above)
+}
+
+fn escaping_borrow_of_trait_default_params_2() {
+    struct S;
+    trait T {
+        fn g<'a>(&self, x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> {
+            let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+            //~^ ERROR E0373
+            //~| ERROR E0373
+            Box::new(f)
+        }
+    }
+    impl T for S {}
+    // (we don't call `g`; see above)
+}
+
+fn move_of_trait_default_params() {
+    struct S;
+    trait T {
+        fn g<'a>(&self, x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> {
+            let f = move |t: bool| if t { x } else { y };
+            return Box::new(f);
+        }
+    }
+    impl T for S {}
+    // (this code is fine, so lets go ahead and ensure rustc accepts call of `g`)
+    (S.g(1,2))(true);
+}
+
+fn main() { }
+
diff --git a/src/test/ui/regions/region-borrow-params-issue-29793-small.stderr b/src/test/ui/regions/region-borrow-params-issue-29793-small.stderr
new file mode 100644
index 0000000..d6ad68f
--- /dev/null
+++ b/src/test/ui/regions/region-borrow-params-issue-29793-small.stderr
@@ -0,0 +1,248 @@
+error[E0597]: `x` does not live long enough
+  --> $DIR/region-borrow-params-issue-29793-small.rs:9:34
+   |
+LL |         let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                 ---------        ^ borrowed value does not live long enough
+   |                 |
+   |                 capture occurs here
+...
+LL |     };
+   |     - borrowed value dropped before borrower
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error[E0597]: `y` does not live long enough
+  --> $DIR/region-borrow-params-issue-29793-small.rs:9:45
+   |
+LL |         let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                 ---------                   ^ borrowed value does not live long enough
+   |                 |
+   |                 capture occurs here
+...
+LL |     };
+   |     - borrowed value dropped before borrower
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/region-borrow-params-issue-29793-small.rs:24:34
+   |
+LL |         let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                 ---------        ^ borrowed value does not live long enough
+   |                 |
+   |                 capture occurs here
+...
+LL |     };
+   |     - borrowed value dropped before borrower
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error[E0597]: `y` does not live long enough
+  --> $DIR/region-borrow-params-issue-29793-small.rs:24:45
+   |
+LL |         let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                 ---------                   ^ borrowed value does not live long enough
+   |                 |
+   |                 capture occurs here
+...
+LL |     };
+   |     - borrowed value dropped before borrower
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function
+  --> $DIR/region-borrow-params-issue-29793-small.rs:55:17
+   |
+LL |         let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                 ^^^^^^^^^        - `x` is borrowed here
+   |                 |
+   |                 may outlive borrowed value `x`
+help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword
+   |
+LL |         let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                 ^^^^^^^^^^^^^^
+
+error[E0373]: closure may outlive the current function, but it borrows `y`, which is owned by the current function
+  --> $DIR/region-borrow-params-issue-29793-small.rs:55:17
+   |
+LL |         let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                 ^^^^^^^^^                   - `y` is borrowed here
+   |                 |
+   |                 may outlive borrowed value `y`
+help: to force the closure to take ownership of `y` (and any other referenced variables), use the `move` keyword
+   |
+LL |         let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                 ^^^^^^^^^^^^^^
+
+error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function
+  --> $DIR/region-borrow-params-issue-29793-small.rs:66:17
+   |
+LL |         let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                 ^^^^^^^^^        - `x` is borrowed here
+   |                 |
+   |                 may outlive borrowed value `x`
+help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword
+   |
+LL |         let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                 ^^^^^^^^^^^^^^
+
+error[E0373]: closure may outlive the current function, but it borrows `y`, which is owned by the current function
+  --> $DIR/region-borrow-params-issue-29793-small.rs:66:17
+   |
+LL |         let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                 ^^^^^^^^^                   - `y` is borrowed here
+   |                 |
+   |                 may outlive borrowed value `y`
+help: to force the closure to take ownership of `y` (and any other referenced variables), use the `move` keyword
+   |
+LL |         let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                 ^^^^^^^^^^^^^^
+
+error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function
+  --> $DIR/region-borrow-params-issue-29793-small.rs:90:21
+   |
+LL |             let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^        - `x` is borrowed here
+   |                     |
+   |                     may outlive borrowed value `x`
+help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword
+   |
+LL |             let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^^^^^^
+
+error[E0373]: closure may outlive the current function, but it borrows `y`, which is owned by the current function
+  --> $DIR/region-borrow-params-issue-29793-small.rs:90:21
+   |
+LL |             let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^                   - `y` is borrowed here
+   |                     |
+   |                     may outlive borrowed value `y`
+help: to force the closure to take ownership of `y` (and any other referenced variables), use the `move` keyword
+   |
+LL |             let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^^^^^^
+
+error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function
+  --> $DIR/region-borrow-params-issue-29793-small.rs:104:21
+   |
+LL |             let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^        - `x` is borrowed here
+   |                     |
+   |                     may outlive borrowed value `x`
+help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword
+   |
+LL |             let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^^^^^^
+
+error[E0373]: closure may outlive the current function, but it borrows `y`, which is owned by the current function
+  --> $DIR/region-borrow-params-issue-29793-small.rs:104:21
+   |
+LL |             let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^                   - `y` is borrowed here
+   |                     |
+   |                     may outlive borrowed value `y`
+help: to force the closure to take ownership of `y` (and any other referenced variables), use the `move` keyword
+   |
+LL |             let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^^^^^^
+
+error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function
+  --> $DIR/region-borrow-params-issue-29793-small.rs:132:21
+   |
+LL |             let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^        - `x` is borrowed here
+   |                     |
+   |                     may outlive borrowed value `x`
+help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword
+   |
+LL |             let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^^^^^^
+
+error[E0373]: closure may outlive the current function, but it borrows `y`, which is owned by the current function
+  --> $DIR/region-borrow-params-issue-29793-small.rs:132:21
+   |
+LL |             let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^                   - `y` is borrowed here
+   |                     |
+   |                     may outlive borrowed value `y`
+help: to force the closure to take ownership of `y` (and any other referenced variables), use the `move` keyword
+   |
+LL |             let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^^^^^^
+
+error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function
+  --> $DIR/region-borrow-params-issue-29793-small.rs:147:21
+   |
+LL |             let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^        - `x` is borrowed here
+   |                     |
+   |                     may outlive borrowed value `x`
+help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword
+   |
+LL |             let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^^^^^^
+
+error[E0373]: closure may outlive the current function, but it borrows `y`, which is owned by the current function
+  --> $DIR/region-borrow-params-issue-29793-small.rs:147:21
+   |
+LL |             let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^                   - `y` is borrowed here
+   |                     |
+   |                     may outlive borrowed value `y`
+help: to force the closure to take ownership of `y` (and any other referenced variables), use the `move` keyword
+   |
+LL |             let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^^^^^^
+
+error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function
+  --> $DIR/region-borrow-params-issue-29793-small.rs:175:21
+   |
+LL |             let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^        - `x` is borrowed here
+   |                     |
+   |                     may outlive borrowed value `x`
+help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword
+   |
+LL |             let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^^^^^^
+
+error[E0373]: closure may outlive the current function, but it borrows `y`, which is owned by the current function
+  --> $DIR/region-borrow-params-issue-29793-small.rs:175:21
+   |
+LL |             let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^                   - `y` is borrowed here
+   |                     |
+   |                     may outlive borrowed value `y`
+help: to force the closure to take ownership of `y` (and any other referenced variables), use the `move` keyword
+   |
+LL |             let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^^^^^^
+
+error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function
+  --> $DIR/region-borrow-params-issue-29793-small.rs:189:21
+   |
+LL |             let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^        - `x` is borrowed here
+   |                     |
+   |                     may outlive borrowed value `x`
+help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword
+   |
+LL |             let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^^^^^^
+
+error[E0373]: closure may outlive the current function, but it borrows `y`, which is owned by the current function
+  --> $DIR/region-borrow-params-issue-29793-small.rs:189:21
+   |
+LL |             let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^                   - `y` is borrowed here
+   |                     |
+   |                     may outlive borrowed value `y`
+help: to force the closure to take ownership of `y` (and any other referenced variables), use the `move` keyword
+   |
+LL |             let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^^^^^^
+
+error: aborting due to 20 previous errors
+
+Some errors occurred: E0373, E0597.
+For more information about an error, try `rustc --explain E0373`.
diff --git a/src/test/ui/regions/region-bound-extra-bound-in-inherent-impl.rs b/src/test/ui/regions/region-bound-extra-bound-in-inherent-impl.rs
new file mode 100644
index 0000000..d6b36af
--- /dev/null
+++ b/src/test/ui/regions/region-bound-extra-bound-in-inherent-impl.rs
@@ -0,0 +1,16 @@
+// Test related to #22779. In this case, the impl is an inherent impl,
+// so it doesn't have to match any trait, so no error results.
+
+// compile-pass
+#![allow(dead_code)]
+
+struct MySlice<'a, T:'a>(&'a mut [T]);
+
+impl<'a, T> MySlice<'a, T> {
+    fn renew<'b: 'a>(self) -> &'b mut [T] where 'a: 'b {
+        &mut self.0[..]
+    }
+}
+
+
+fn main() { }
diff --git a/src/test/ui/regions/region-bound-on-closure-outlives-call.nll.stderr b/src/test/ui/regions/region-bound-on-closure-outlives-call.nll.stderr
new file mode 100644
index 0000000..d455902
--- /dev/null
+++ b/src/test/ui/regions/region-bound-on-closure-outlives-call.nll.stderr
@@ -0,0 +1,24 @@
+warning: function cannot return without recursing
+  --> $DIR/region-bound-on-closure-outlives-call.rs:1:1
+   |
+LL | fn call_rec<F>(mut f: F) -> usize where F: FnMut(usize) -> usize {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
+LL |
+LL |     (|x| f(x))(call_rec(f))
+   |                ----------- recursive call site
+   |
+   = note: #[warn(unconditional_recursion)] on by default
+   = help: a `loop` may express intention better if this is on purpose
+
+error[E0505]: cannot move out of `f` because it is borrowed
+  --> $DIR/region-bound-on-closure-outlives-call.rs:3:25
+   |
+LL |     (|x| f(x))(call_rec(f))
+   |      --- -              ^ move out of `f` occurs here
+   |      |   |
+   |      |   borrow occurs due to use in closure
+   |      borrow of `f` occurs here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0505`.
diff --git a/src/test/ui/regions/region-bound-on-closure-outlives-call.rs b/src/test/ui/regions/region-bound-on-closure-outlives-call.rs
new file mode 100644
index 0000000..1311d51
--- /dev/null
+++ b/src/test/ui/regions/region-bound-on-closure-outlives-call.rs
@@ -0,0 +1,6 @@
+fn call_rec<F>(mut f: F) -> usize where F: FnMut(usize) -> usize {
+    //~^ WARN function cannot return without recursing
+    (|x| f(x))(call_rec(f)) //~ ERROR cannot move out of `f`
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/region-bound-on-closure-outlives-call.stderr b/src/test/ui/regions/region-bound-on-closure-outlives-call.stderr
new file mode 100644
index 0000000..cb888ab
--- /dev/null
+++ b/src/test/ui/regions/region-bound-on-closure-outlives-call.stderr
@@ -0,0 +1,23 @@
+warning: function cannot return without recursing
+  --> $DIR/region-bound-on-closure-outlives-call.rs:1:1
+   |
+LL | fn call_rec<F>(mut f: F) -> usize where F: FnMut(usize) -> usize {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
+LL |
+LL |     (|x| f(x))(call_rec(f))
+   |                ----------- recursive call site
+   |
+   = note: #[warn(unconditional_recursion)] on by default
+   = help: a `loop` may express intention better if this is on purpose
+
+error[E0505]: cannot move out of `f` because it is borrowed
+  --> $DIR/region-bound-on-closure-outlives-call.rs:3:25
+   |
+LL |     (|x| f(x))(call_rec(f))
+   |      ---                ^ move out of `f` occurs here
+   |      |
+   |      borrow of `f` occurs here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0505`.
diff --git a/src/test/ui/regions/region-bound-same-bounds-in-trait-and-impl.rs b/src/test/ui/regions/region-bound-same-bounds-in-trait-and-impl.rs
new file mode 100644
index 0000000..deef9ab
--- /dev/null
+++ b/src/test/ui/regions/region-bound-same-bounds-in-trait-and-impl.rs
@@ -0,0 +1,17 @@
+// Test related to #22779, but where the `'a:'b` relation
+// appears in the trait too. No error here.
+
+// compile-pass
+
+trait Tr<'a, T> {
+    fn renew<'b: 'a>(self) -> &'b mut [T] where 'a: 'b;
+}
+
+impl<'a, T> Tr<'a, T> for &'a mut [T] {
+    fn renew<'b: 'a>(self) -> &'b mut [T] where 'a: 'b {
+        &mut self[..]
+    }
+}
+
+
+fn main() { }
diff --git a/src/test/ui/regions/region-bounds-on-objects-and-type-parameters.rs b/src/test/ui/regions/region-bounds-on-objects-and-type-parameters.rs
new file mode 100644
index 0000000..3a211b0
--- /dev/null
+++ b/src/test/ui/regions/region-bounds-on-objects-and-type-parameters.rs
@@ -0,0 +1,36 @@
+// Test related to when a region bound is required to be specified.
+
+trait IsStatic : 'static { }
+trait IsSend : Send { }
+trait Is<'a> : 'a { }
+trait Is2<'a> : 'a { }
+trait SomeTrait { }
+
+// Bounds on object types:
+
+struct Foo<'a,'b,'c> { //~ ERROR parameter `'c` is never used
+    // All of these are ok, because we can derive exactly one bound:
+    a: Box<IsStatic>,
+    b: Box<Is<'static>>,
+    c: Box<Is<'a>>,
+    d: Box<IsSend>,
+    e: Box<Is<'a>+Send>, // we can derive two bounds, but one is 'static, so ok
+    f: Box<SomeTrait>,   // OK, defaults to 'static due to RFC 599.
+    g: Box<SomeTrait+'a>,
+
+    z: Box<Is<'a>+'b+'c>,
+    //~^ ERROR only a single explicit lifetime bound is permitted
+    //~| ERROR lifetime bound not satisfied
+}
+
+fn test<
+    'a,
+    'b,
+    A:IsStatic,
+    B:Is<'a>+Is2<'b>, // OK in a parameter, but not an object type.
+    C:'b+Is<'a>+Is2<'b>,
+    D:Is<'a>+Is2<'static>,
+    E:'a+'b           // OK in a parameter, but not an object type.
+>() { }
+
+fn main() { }
diff --git a/src/test/ui/regions/region-bounds-on-objects-and-type-parameters.stderr b/src/test/ui/regions/region-bounds-on-objects-and-type-parameters.stderr
new file mode 100644
index 0000000..ec71d55
--- /dev/null
+++ b/src/test/ui/regions/region-bounds-on-objects-and-type-parameters.stderr
@@ -0,0 +1,35 @@
+error[E0226]: only a single explicit lifetime bound is permitted
+  --> $DIR/region-bounds-on-objects-and-type-parameters.rs:21:22
+   |
+LL |     z: Box<Is<'a>+'b+'c>,
+   |                      ^^
+
+error[E0478]: lifetime bound not satisfied
+  --> $DIR/region-bounds-on-objects-and-type-parameters.rs:21:5
+   |
+LL |     z: Box<Is<'a>+'b+'c>,
+   |     ^^^^^^^^^^^^^^^^^^^^
+   |
+note: lifetime parameter instantiated with the lifetime 'b as defined on the struct at 11:15
+  --> $DIR/region-bounds-on-objects-and-type-parameters.rs:11:15
+   |
+LL | struct Foo<'a,'b,'c> {
+   |               ^^
+note: but lifetime parameter must outlive the lifetime 'a as defined on the struct at 11:12
+  --> $DIR/region-bounds-on-objects-and-type-parameters.rs:11:12
+   |
+LL | struct Foo<'a,'b,'c> {
+   |            ^^
+
+error[E0392]: parameter `'c` is never used
+  --> $DIR/region-bounds-on-objects-and-type-parameters.rs:11:18
+   |
+LL | struct Foo<'a,'b,'c> {
+   |                  ^^ unused type parameter
+   |
+   = help: consider removing `'c` or using a marker such as `std::marker::PhantomData`
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0226, E0392, E0478.
+For more information about an error, try `rustc --explain E0226`.
diff --git a/src/test/ui/regions/region-invariant-static-error-reporting.rs b/src/test/ui/regions/region-invariant-static-error-reporting.rs
new file mode 100644
index 0000000..df92ed5
--- /dev/null
+++ b/src/test/ui/regions/region-invariant-static-error-reporting.rs
@@ -0,0 +1,22 @@
+// This test checks that the error messages you get for this example
+// at least mention `'a` and `'static`. The precise messages can drift
+// over time, but this test used to exhibit some pretty bogus messages
+// that were not remotely helpful.
+
+// error-pattern:the lifetime 'a
+// error-pattern:the static lifetime
+
+struct Invariant<'a>(Option<&'a mut &'a mut ()>);
+
+fn mk_static() -> Invariant<'static> { Invariant(None) }
+
+fn unify<'a>(x: Option<Invariant<'a>>, f: fn(Invariant<'a>)) {
+    let bad = if x.is_some() {
+        x.unwrap()
+    } else {
+        mk_static()
+    };
+    f(bad);
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/region-invariant-static-error-reporting.stderr b/src/test/ui/regions/region-invariant-static-error-reporting.stderr
new file mode 100644
index 0000000..60e70dd
--- /dev/null
+++ b/src/test/ui/regions/region-invariant-static-error-reporting.stderr
@@ -0,0 +1,25 @@
+error[E0308]: if and else have incompatible types
+  --> $DIR/region-invariant-static-error-reporting.rs:17:9
+   |
+LL |       let bad = if x.is_some() {
+   |  _______________-
+LL | |         x.unwrap()
+   | |         ---------- expected because of this
+LL | |     } else {
+LL | |         mk_static()
+   | |         ^^^^^^^^^^^ lifetime mismatch
+LL | |     };
+   | |_____- if and else have incompatible types
+   |
+   = note: expected type `Invariant<'a>`
+              found type `Invariant<'static>`
+note: the lifetime 'a as defined on the function body at 13:10...
+  --> $DIR/region-invariant-static-error-reporting.rs:13:10
+   |
+LL | fn unify<'a>(x: Option<Invariant<'a>>, f: fn(Invariant<'a>)) {
+   |          ^^
+   = note: ...does not necessarily outlive the static lifetime
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.rs b/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.rs
new file mode 100644
index 0000000..ab4c6d9
--- /dev/null
+++ b/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.rs
@@ -0,0 +1,29 @@
+fn a<'a, 'b>(x: &mut &'a isize, y: &mut &'b isize) where 'b: 'a {
+    // Note: this is legal because of the `'b:'a` declaration.
+    *x = *y;
+}
+
+fn b<'a, 'b>(x: &mut &'a isize, y: &mut &'b isize) {
+    // Illegal now because there is no `'b:'a` declaration.
+    *x = *y; //~ ERROR E0623
+}
+
+fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) {
+    // Here we try to call `foo` but do not know that `'a` and `'b` are
+    // related as required.
+    a(x, y); //~ ERROR lifetime mismatch [E0623]
+}
+
+fn d() {
+    // 'a and 'b are early bound in the function `a` because they appear
+    // inconstraints:
+    let _: fn(&mut &isize, &mut &isize) = a; //~ ERROR mismatched types
+}
+
+fn e() {
+    // 'a and 'b are late bound in the function `b` because there are
+    // no constraints:
+    let _: fn(&mut &isize, &mut &isize) = b;
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr b/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr
new file mode 100644
index 0000000..7b901c2
--- /dev/null
+++ b/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr
@@ -0,0 +1,31 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:8:10
+   |
+LL | fn b<'a, 'b>(x: &mut &'a isize, y: &mut &'b isize) {
+   |                      ---------          --------- these two types are declared with different lifetimes...
+LL |     // Illegal now because there is no `'b:'a` declaration.
+LL |     *x = *y;
+   |          ^^ ...but data from `y` flows into `x` here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:14:7
+   |
+LL | fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) {
+   |                     ---------          --------- these two types are declared with different lifetimes...
+...
+LL |     a(x, y);
+   |       ^ ...but data from `y` flows into `x` here
+
+error[E0308]: mismatched types
+  --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:20:43
+   |
+LL |     let _: fn(&mut &isize, &mut &isize) = a;
+   |                                           ^ expected concrete lifetime, found bound lifetime parameter
+   |
+   = note: expected type `for<'r, 's, 't0, 't1> fn(&'r mut &'s isize, &'t0 mut &'t1 isize)`
+              found type `for<'r, 's> fn(&'r mut &isize, &'s mut &isize) {a::<'_, '_>}`
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0308, E0623.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.rs b/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.rs
new file mode 100644
index 0000000..0665225
--- /dev/null
+++ b/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.rs
@@ -0,0 +1,31 @@
+fn a<'a, 'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) where 'b: 'a + 'c {
+    // Note: this is legal because of the `'b:'a` declaration.
+    *x = *y;
+    *z = *y;
+}
+
+fn b<'a, 'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) {
+    // Illegal now because there is no `'b:'a` declaration.
+    *x = *y; //~ ERROR E0623
+    *z = *y; //~ ERROR E0623
+}
+
+fn c<'a,'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) {
+    // Here we try to call `foo` but do not know that `'a` and `'b` are
+    // related as required.
+    a(x, y, z); //~ ERROR lifetime mismatch [E0623]
+}
+
+fn d() {
+    // 'a and 'b are early bound in the function `a` because they appear
+    // inconstraints:
+    let _: fn(&mut &isize, &mut &isize, &mut &isize) = a; //~ ERROR E0308
+}
+
+fn e() {
+    // 'a and 'b are late bound in the function `b` because there are
+    // no constraints:
+    let _: fn(&mut &isize, &mut &isize, &mut &isize) = b;
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr b/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr
new file mode 100644
index 0000000..3e42cfc
--- /dev/null
+++ b/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr
@@ -0,0 +1,42 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:9:10
+   |
+LL | fn b<'a, 'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) {
+   |                          ---------          --------- these two types are declared with different lifetimes...
+LL |     // Illegal now because there is no `'b:'a` declaration.
+LL |     *x = *y;
+   |          ^^ ...but data from `y` flows into `x` here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:10:10
+   |
+LL | fn b<'a, 'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) {
+   |                                             ---------          ---------
+   |                                             |
+   |                                             these two types are declared with different lifetimes...
+...
+LL |     *z = *y;
+   |          ^^ ...but data from `y` flows into `z` here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:16:7
+   |
+LL | fn c<'a,'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) {
+   |                         ---------          --------- these two types are declared with different lifetimes...
+...
+LL |     a(x, y, z);
+   |       ^ ...but data from `y` flows into `x` here
+
+error[E0308]: mismatched types
+  --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:22:56
+   |
+LL |     let _: fn(&mut &isize, &mut &isize, &mut &isize) = a;
+   |                                                        ^ expected concrete lifetime, found bound lifetime parameter
+   |
+   = note: expected type `for<'r, 's, 't0, 't1, 't2, 't3> fn(&'r mut &'s isize, &'t0 mut &'t1 isize, &'t2 mut &'t3 isize)`
+              found type `for<'r, 's, 't0> fn(&'r mut &isize, &'s mut &isize, &'t0 mut &isize) {a::<'_, '_, '_>}`
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0308, E0623.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/regions/region-object-lifetime-1.rs b/src/test/ui/regions/region-object-lifetime-1.rs
new file mode 100644
index 0000000..ab24eda
--- /dev/null
+++ b/src/test/ui/regions/region-object-lifetime-1.rs
@@ -0,0 +1,18 @@
+// Various tests related to testing how region inference works
+// with respect to the object receivers.
+
+// compile-pass
+#![allow(warnings)]
+
+trait Foo {
+    fn borrowed<'a>(&'a self) -> &'a ();
+}
+
+// Here the receiver and return value all have the same lifetime,
+// so no error results.
+fn borrowed_receiver_same_lifetime<'a>(x: &'a Foo) -> &'a () {
+    x.borrowed()
+}
+
+
+fn main() {}
diff --git a/src/test/ui/regions/region-object-lifetime-2.rs b/src/test/ui/regions/region-object-lifetime-2.rs
new file mode 100644
index 0000000..92c8502
--- /dev/null
+++ b/src/test/ui/regions/region-object-lifetime-2.rs
@@ -0,0 +1,13 @@
+// Various tests related to testing how region inference works
+// with respect to the object receivers.
+
+trait Foo {
+    fn borrowed<'a>(&'a self) -> &'a ();
+}
+
+// Borrowed receiver but two distinct lifetimes, we get an error.
+fn borrowed_receiver_different_lifetimes<'a,'b>(x: &'a Foo) -> &'b () {
+    x.borrowed() //~ ERROR cannot infer
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/region-object-lifetime-2.stderr b/src/test/ui/regions/region-object-lifetime-2.stderr
new file mode 100644
index 0000000..8817ad1
--- /dev/null
+++ b/src/test/ui/regions/region-object-lifetime-2.stderr
@@ -0,0 +1,30 @@
+error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
+  --> $DIR/region-object-lifetime-2.rs:10:7
+   |
+LL |     x.borrowed()
+   |       ^^^^^^^^
+   |
+note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 9:42...
+  --> $DIR/region-object-lifetime-2.rs:9:42
+   |
+LL | fn borrowed_receiver_different_lifetimes<'a,'b>(x: &'a Foo) -> &'b () {
+   |                                          ^^
+note: ...so that reference does not outlive borrowed content
+  --> $DIR/region-object-lifetime-2.rs:10:5
+   |
+LL |     x.borrowed()
+   |     ^
+note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 9:45...
+  --> $DIR/region-object-lifetime-2.rs:9:45
+   |
+LL | fn borrowed_receiver_different_lifetimes<'a,'b>(x: &'a Foo) -> &'b () {
+   |                                             ^^
+note: ...so that reference does not outlive borrowed content
+  --> $DIR/region-object-lifetime-2.rs:10:5
+   |
+LL |     x.borrowed()
+   |     ^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0495`.
diff --git a/src/test/ui/regions/region-object-lifetime-3.rs b/src/test/ui/regions/region-object-lifetime-3.rs
new file mode 100644
index 0000000..cda4834
--- /dev/null
+++ b/src/test/ui/regions/region-object-lifetime-3.rs
@@ -0,0 +1,18 @@
+// Various tests related to testing how region inference works
+// with respect to the object receivers.
+
+// compile-pass
+#![allow(warnings)]
+
+trait Foo {
+    fn borrowed<'a>(&'a self) -> &'a ();
+}
+
+// Borrowed receiver with two distinct lifetimes, but we know that
+// 'b:'a, hence &'a () is permitted.
+fn borrowed_receiver_related_lifetimes<'a,'b>(x: &'a (Foo+'b)) -> &'a () {
+    x.borrowed()
+}
+
+
+fn main() {}
diff --git a/src/test/ui/regions/region-object-lifetime-4.rs b/src/test/ui/regions/region-object-lifetime-4.rs
new file mode 100644
index 0000000..d2ab617
--- /dev/null
+++ b/src/test/ui/regions/region-object-lifetime-4.rs
@@ -0,0 +1,15 @@
+// Various tests related to testing how region inference works
+// with respect to the object receivers.
+
+trait Foo {
+    fn borrowed<'a>(&'a self) -> &'a ();
+}
+
+// Here we have two distinct lifetimes, but we try to return a pointer
+// with the longer lifetime when (from the signature) we only know
+// that it lives as long as the shorter lifetime. Therefore, error.
+fn borrowed_receiver_related_lifetimes2<'a,'b>(x: &'a (Foo+'b)) -> &'b () {
+    x.borrowed() //~ ERROR cannot infer
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/region-object-lifetime-4.stderr b/src/test/ui/regions/region-object-lifetime-4.stderr
new file mode 100644
index 0000000..fee7f40
--- /dev/null
+++ b/src/test/ui/regions/region-object-lifetime-4.stderr
@@ -0,0 +1,30 @@
+error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
+  --> $DIR/region-object-lifetime-4.rs:12:7
+   |
+LL |     x.borrowed()
+   |       ^^^^^^^^
+   |
+note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 11:41...
+  --> $DIR/region-object-lifetime-4.rs:11:41
+   |
+LL | fn borrowed_receiver_related_lifetimes2<'a,'b>(x: &'a (Foo+'b)) -> &'b () {
+   |                                         ^^
+note: ...so that reference does not outlive borrowed content
+  --> $DIR/region-object-lifetime-4.rs:12:5
+   |
+LL |     x.borrowed()
+   |     ^
+note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 11:44...
+  --> $DIR/region-object-lifetime-4.rs:11:44
+   |
+LL | fn borrowed_receiver_related_lifetimes2<'a,'b>(x: &'a (Foo+'b)) -> &'b () {
+   |                                            ^^
+note: ...so that reference does not outlive borrowed content
+  --> $DIR/region-object-lifetime-4.rs:12:5
+   |
+LL |     x.borrowed()
+   |     ^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0495`.
diff --git a/src/test/ui/regions/region-object-lifetime-5.nll.stderr b/src/test/ui/regions/region-object-lifetime-5.nll.stderr
new file mode 100644
index 0000000..b86f6e3
--- /dev/null
+++ b/src/test/ui/regions/region-object-lifetime-5.nll.stderr
@@ -0,0 +1,12 @@
+error[E0515]: cannot return value referencing local data `*x`
+  --> $DIR/region-object-lifetime-5.rs:11:5
+   |
+LL |     x.borrowed()
+   |     -^^^^^^^^^^^
+   |     |
+   |     returns a value referencing data owned by the current function
+   |     `*x` is borrowed here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/src/test/ui/regions/region-object-lifetime-5.rs b/src/test/ui/regions/region-object-lifetime-5.rs
new file mode 100644
index 0000000..5009b2b
--- /dev/null
+++ b/src/test/ui/regions/region-object-lifetime-5.rs
@@ -0,0 +1,14 @@
+// Various tests related to testing how region inference works
+// with respect to the object receivers.
+
+trait Foo {
+    fn borrowed<'a>(&'a self) -> &'a ();
+}
+
+// Here, the object is bounded by an anonymous lifetime and returned
+// as `&'static`, so you get an error.
+fn owned_receiver(x: Box<Foo>) -> &'static () {
+    x.borrowed() //~ ERROR `*x` does not live long enough
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/region-object-lifetime-5.stderr b/src/test/ui/regions/region-object-lifetime-5.stderr
new file mode 100644
index 0000000..1efaee1
--- /dev/null
+++ b/src/test/ui/regions/region-object-lifetime-5.stderr
@@ -0,0 +1,13 @@
+error[E0597]: `*x` does not live long enough
+  --> $DIR/region-object-lifetime-5.rs:11:5
+   |
+LL |     x.borrowed()
+   |     ^ borrowed value does not live long enough
+LL | }
+   | - borrowed value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.rs b/src/test/ui/regions/region-object-lifetime-in-coercion.rs
new file mode 100644
index 0000000..dfba04b
--- /dev/null
+++ b/src/test/ui/regions/region-object-lifetime-in-coercion.rs
@@ -0,0 +1,34 @@
+// Test that attempts to implicitly coerce a value into an
+// object respect the lifetime bound on the object type.
+
+trait Foo {}
+impl<'a> Foo for &'a [u8] {}
+
+fn a(v: &[u8]) -> Box<Foo + 'static> {
+    let x: Box<Foo + 'static> = Box::new(v);
+    //~^ ERROR explicit lifetime required in the type of `v` [E0621]
+    x
+}
+
+fn b(v: &[u8]) -> Box<Foo + 'static> {
+    Box::new(v)
+        //~^ ERROR explicit lifetime required in the type of `v` [E0621]
+}
+
+fn c(v: &[u8]) -> Box<Foo> {
+    // same as previous case due to RFC 599
+
+    Box::new(v)
+        //~^ ERROR explicit lifetime required in the type of `v` [E0621]
+}
+
+fn d<'a,'b>(v: &'a [u8]) -> Box<Foo+'b> {
+    Box::new(v)
+        //~^ ERROR cannot infer an appropriate lifetime due to conflicting
+}
+
+fn e<'a:'b,'b>(v: &'a [u8]) -> Box<Foo+'b> {
+    Box::new(v) // OK, thanks to 'a:'b
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr
new file mode 100644
index 0000000..b8ea6d3
--- /dev/null
+++ b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr
@@ -0,0 +1,52 @@
+error[E0621]: explicit lifetime required in the type of `v`
+  --> $DIR/region-object-lifetime-in-coercion.rs:8:33
+   |
+LL | fn a(v: &[u8]) -> Box<Foo + 'static> {
+   |         ----- help: add explicit lifetime `'static` to the type of `v`: `&'static [u8]`
+LL |     let x: Box<Foo + 'static> = Box::new(v);
+   |                                 ^^^^^^^^^^^ lifetime `'static` required
+
+error[E0621]: explicit lifetime required in the type of `v`
+  --> $DIR/region-object-lifetime-in-coercion.rs:14:5
+   |
+LL | fn b(v: &[u8]) -> Box<Foo + 'static> {
+   |         ----- help: add explicit lifetime `'static` to the type of `v`: `&'static [u8]`
+LL |     Box::new(v)
+   |     ^^^^^^^^^^^ lifetime `'static` required
+
+error[E0621]: explicit lifetime required in the type of `v`
+  --> $DIR/region-object-lifetime-in-coercion.rs:21:5
+   |
+LL | fn c(v: &[u8]) -> Box<Foo> {
+   |         ----- help: add explicit lifetime `'static` to the type of `v`: `&'static [u8]`
+...
+LL |     Box::new(v)
+   |     ^^^^^^^^^^^ lifetime `'static` required
+
+error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
+  --> $DIR/region-object-lifetime-in-coercion.rs:26:14
+   |
+LL |     Box::new(v)
+   |              ^
+   |
+note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 25:6...
+  --> $DIR/region-object-lifetime-in-coercion.rs:25:6
+   |
+LL | fn d<'a,'b>(v: &'a [u8]) -> Box<Foo+'b> {
+   |      ^^
+   = note: ...so that the expression is assignable:
+           expected &[u8]
+              found &'a [u8]
+note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 25:9...
+  --> $DIR/region-object-lifetime-in-coercion.rs:25:9
+   |
+LL | fn d<'a,'b>(v: &'a [u8]) -> Box<Foo+'b> {
+   |         ^^
+   = note: ...so that the expression is assignable:
+           expected std::boxed::Box<(dyn Foo + 'b)>
+              found std::boxed::Box<dyn Foo>
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0495, E0621.
+For more information about an error, try `rustc --explain E0495`.
diff --git a/src/test/ui/regions/regions-addr-of-arg.nll.stderr b/src/test/ui/regions/regions-addr-of-arg.nll.stderr
new file mode 100644
index 0000000..54f44b9
--- /dev/null
+++ b/src/test/ui/regions/regions-addr-of-arg.nll.stderr
@@ -0,0 +1,20 @@
+error[E0597]: `a` does not live long enough
+  --> $DIR/regions-addr-of-arg.rs:5:30
+   |
+LL |     let _p: &'static isize = &a;
+   |             --------------   ^^ borrowed value does not live long enough
+   |             |
+   |             type annotation requires that `a` is borrowed for `'static`
+LL | }
+   |  - `a` dropped here while still borrowed
+
+error[E0515]: cannot return reference to function parameter `a`
+  --> $DIR/regions-addr-of-arg.rs:13:5
+   |
+LL |     &a
+   |     ^^ returns a reference to data owned by the current function
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0515, E0597.
+For more information about an error, try `rustc --explain E0515`.
diff --git a/src/test/ui/regions/regions-addr-of-arg.rs b/src/test/ui/regions/regions-addr-of-arg.rs
new file mode 100644
index 0000000..06f16be
--- /dev/null
+++ b/src/test/ui/regions/regions-addr-of-arg.rs
@@ -0,0 +1,17 @@
+// Check that taking the address of an argument yields a lifetime
+// bounded by the current function call.
+
+fn foo(a: isize) {
+    let _p: &'static isize = &a; //~ ERROR `a` does not live long enough
+}
+
+fn bar(a: isize) {
+    let _q: &isize = &a;
+}
+
+fn zed<'a>(a: isize) -> &'a isize {
+    &a //~ ERROR `a` does not live long enough
+}
+
+fn main() {
+}
diff --git a/src/test/ui/regions/regions-addr-of-arg.stderr b/src/test/ui/regions/regions-addr-of-arg.stderr
new file mode 100644
index 0000000..3e76a7d
--- /dev/null
+++ b/src/test/ui/regions/regions-addr-of-arg.stderr
@@ -0,0 +1,27 @@
+error[E0597]: `a` does not live long enough
+  --> $DIR/regions-addr-of-arg.rs:5:31
+   |
+LL |     let _p: &'static isize = &a;
+   |                               ^ borrowed value does not live long enough
+LL | }
+   | - borrowed value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: `a` does not live long enough
+  --> $DIR/regions-addr-of-arg.rs:13:6
+   |
+LL |     &a
+   |      ^ borrowed value does not live long enough
+LL | }
+   | - borrowed value only lives until here
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 12:8...
+  --> $DIR/regions-addr-of-arg.rs:12:8
+   |
+LL | fn zed<'a>(a: isize) -> &'a isize {
+   |        ^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/regions/regions-addr-of-self.rs b/src/test/ui/regions/regions-addr-of-self.rs
new file mode 100644
index 0000000..6472124
--- /dev/null
+++ b/src/test/ui/regions/regions-addr-of-self.rs
@@ -0,0 +1,27 @@
+struct Dog {
+    cats_chased: usize,
+}
+
+impl Dog {
+    pub fn chase_cat(&mut self) {
+        let p: &'static mut usize = &mut self.cats_chased; //~ ERROR cannot infer
+        *p += 1;
+    }
+
+    pub fn chase_cat_2(&mut self) {
+        let p: &mut usize = &mut self.cats_chased;
+        *p += 1;
+    }
+}
+
+fn dog() -> Dog {
+    Dog {
+        cats_chased: 0
+    }
+}
+
+fn main() {
+    let mut d = dog();
+    d.chase_cat();
+    println!("cats_chased: {}", d.cats_chased);
+}
diff --git a/src/test/ui/regions/regions-addr-of-self.stderr b/src/test/ui/regions/regions-addr-of-self.stderr
new file mode 100644
index 0000000..a0b8b6b
--- /dev/null
+++ b/src/test/ui/regions/regions-addr-of-self.stderr
@@ -0,0 +1,29 @@
+error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
+  --> $DIR/regions-addr-of-self.rs:7:37
+   |
+LL |         let p: &'static mut usize = &mut self.cats_chased;
+   |                                     ^^^^^^^^^^^^^^^^^^^^^
+   |
+note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 6:5...
+  --> $DIR/regions-addr-of-self.rs:6:5
+   |
+LL | /     pub fn chase_cat(&mut self) {
+LL | |         let p: &'static mut usize = &mut self.cats_chased;
+LL | |         *p += 1;
+LL | |     }
+   | |_____^
+note: ...so that reference does not outlive borrowed content
+  --> $DIR/regions-addr-of-self.rs:7:37
+   |
+LL |         let p: &'static mut usize = &mut self.cats_chased;
+   |                                     ^^^^^^^^^^^^^^^^^^^^^
+   = note: but, the lifetime must be valid for the static lifetime...
+note: ...so that reference does not outlive borrowed content
+  --> $DIR/regions-addr-of-self.rs:7:37
+   |
+LL |         let p: &'static mut usize = &mut self.cats_chased;
+   |                                     ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0495`.
diff --git a/src/test/ui/regions/regions-addr-of-upvar-self.rs b/src/test/ui/regions/regions-addr-of-upvar-self.rs
new file mode 100644
index 0000000..1f8fe9a
--- /dev/null
+++ b/src/test/ui/regions/regions-addr-of-upvar-self.rs
@@ -0,0 +1,17 @@
+use std::usize;
+
+struct Dog {
+    food: usize,
+}
+
+impl Dog {
+    pub fn chase_cat(&mut self) {
+        let _f = || {
+            let p: &'static mut usize = &mut self.food; //~ ERROR cannot infer
+            *p = 3;
+        };
+    }
+}
+
+fn main() {
+}
diff --git a/src/test/ui/regions/regions-addr-of-upvar-self.stderr b/src/test/ui/regions/regions-addr-of-upvar-self.stderr
new file mode 100644
index 0000000..ac5e5e9
--- /dev/null
+++ b/src/test/ui/regions/regions-addr-of-upvar-self.stderr
@@ -0,0 +1,26 @@
+error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
+  --> $DIR/regions-addr-of-upvar-self.rs:10:41
+   |
+LL |             let p: &'static mut usize = &mut self.food;
+   |                                         ^^^^^^^^^^^^^^
+   |
+note: first, the lifetime cannot outlive the lifetime '_ as defined on the body at 9:18...
+  --> $DIR/regions-addr-of-upvar-self.rs:9:18
+   |
+LL |         let _f = || {
+   |                  ^^
+note: ...so that reference does not outlive borrowed content
+  --> $DIR/regions-addr-of-upvar-self.rs:10:41
+   |
+LL |             let p: &'static mut usize = &mut self.food;
+   |                                         ^^^^^^^^^^^^^^
+   = note: but, the lifetime must be valid for the static lifetime...
+note: ...so that reference does not outlive borrowed content
+  --> $DIR/regions-addr-of-upvar-self.rs:10:41
+   |
+LL |             let p: &'static mut usize = &mut self.food;
+   |                                         ^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0495`.
diff --git a/src/test/ui/regions/regions-adjusted-lvalue-op.nll.stderr b/src/test/ui/regions/regions-adjusted-lvalue-op.nll.stderr
new file mode 100644
index 0000000..2c55634
--- /dev/null
+++ b/src/test/ui/regions/regions-adjusted-lvalue-op.nll.stderr
@@ -0,0 +1,21 @@
+error[E0502]: cannot borrow `v` as immutable because it is also borrowed as mutable
+  --> $DIR/regions-adjusted-lvalue-op.rs:14:16
+   |
+LL |     v[0].oh_no(&v);
+   |     -    ----- ^^ immutable borrow occurs here
+   |     |    |
+   |     |    mutable borrow later used by call
+   |     mutable borrow occurs here
+
+error[E0502]: cannot borrow `v` as immutable because it is also borrowed as mutable
+  --> $DIR/regions-adjusted-lvalue-op.rs:15:16
+   |
+LL |     (*v).oh_no(&v);
+   |       -  ----- ^^ immutable borrow occurs here
+   |       |  |
+   |       |  mutable borrow later used by call
+   |       mutable borrow occurs here
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/regions/regions-adjusted-lvalue-op.rs b/src/test/ui/regions/regions-adjusted-lvalue-op.rs
new file mode 100644
index 0000000..5aa5a3e
--- /dev/null
+++ b/src/test/ui/regions/regions-adjusted-lvalue-op.rs
@@ -0,0 +1,16 @@
+// check that we link regions in mutable place ops correctly - issue #41774
+
+struct Data(i32);
+
+trait OhNo {
+    fn oh_no(&mut self, other: &Vec<Data>) { loop {} }
+}
+
+impl OhNo for Data {}
+impl OhNo for [Data] {}
+
+fn main() {
+    let mut v = vec![Data(0)];
+    v[0].oh_no(&v); //~ ERROR cannot borrow `v` as immutable because
+    (*v).oh_no(&v); //~ ERROR cannot borrow `v` as immutable because
+}
diff --git a/src/test/ui/regions/regions-adjusted-lvalue-op.stderr b/src/test/ui/regions/regions-adjusted-lvalue-op.stderr
new file mode 100644
index 0000000..2c4c75f
--- /dev/null
+++ b/src/test/ui/regions/regions-adjusted-lvalue-op.stderr
@@ -0,0 +1,21 @@
+error[E0502]: cannot borrow `v` as immutable because it is also borrowed as mutable
+  --> $DIR/regions-adjusted-lvalue-op.rs:14:17
+   |
+LL |     v[0].oh_no(&v);
+   |     -           ^- mutable borrow ends here
+   |     |           |
+   |     |           immutable borrow occurs here
+   |     mutable borrow occurs here
+
+error[E0502]: cannot borrow `v` as immutable because it is also borrowed as mutable
+  --> $DIR/regions-adjusted-lvalue-op.rs:15:17
+   |
+LL |     (*v).oh_no(&v);
+   |       -         ^- mutable borrow ends here
+   |       |         |
+   |       |         immutable borrow occurs here
+   |       mutable borrow occurs here
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.ast.stderr b/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.ast.stderr
new file mode 100644
index 0000000..76ead4e
--- /dev/null
+++ b/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.ast.stderr
@@ -0,0 +1,20 @@
+error[E0491]: in type `&'a WithAssoc<TheType<'b>>`, reference has a longer lifetime than the data it references
+  --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:45:13
+   |
+LL |     let _x: &'a WithAssoc<TheType<'b>> = loop { };
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the pointer is valid for the lifetime 'a as defined on the function body at 37:15
+  --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:37:15
+   |
+LL | fn with_assoc<'a,'b>() {
+   |               ^^
+note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 37:18
+  --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:37:18
+   |
+LL | fn with_assoc<'a,'b>() {
+   |                  ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0491`.
diff --git a/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.mir.stderr b/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.mir.stderr
new file mode 100644
index 0000000..ad94d37
--- /dev/null
+++ b/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.mir.stderr
@@ -0,0 +1,13 @@
+error: lifetime may not live long enough
+  --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:45:13
+   |
+LL | fn with_assoc<'a,'b>() {
+   |               -- -- lifetime `'b` defined here
+   |               |
+   |               lifetime `'a` defined here
+...
+LL |     let _x: &'a WithAssoc<TheType<'b>> = loop { };
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.rs b/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.rs
new file mode 100644
index 0000000..1d53492
--- /dev/null
+++ b/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.rs
@@ -0,0 +1,51 @@
+// Test that we are imposing the requirement that every associated
+// type of a bound that appears in the where clause on a struct must
+// outlive the location in which the type appears, even when the
+// associted type is in a supertype. Issue #22246.
+
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+#![allow(dead_code)]
+
+///////////////////////////////////////////////////////////////////////////
+
+pub trait TheTrait {
+    type TheAssocType;
+}
+
+pub trait TheSubTrait : TheTrait {
+}
+
+pub struct TheType<'b> {
+    m: [fn(&'b()); 0]
+}
+
+impl<'b> TheTrait for TheType<'b> {
+    type TheAssocType = &'b ();
+}
+
+impl<'b> TheSubTrait for TheType<'b> {
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+pub struct WithAssoc<T:TheSubTrait> {
+    m: [T; 0]
+}
+
+fn with_assoc<'a,'b>() {
+    // For this type to be valid, the rules require that all
+    // associated types of traits that appear in `WithAssoc` must
+    // outlive 'a. In this case, that means TheType<'b>::TheAssocType,
+    // which is &'b (), must outlive 'a.
+
+    // FIXME (#54943) NLL doesn't enforce WF condition in unreachable code if
+    // `_x` is changed to `_`
+    let _x: &'a WithAssoc<TheType<'b>> = loop { };
+    //[ast]~^ ERROR reference has a longer lifetime
+    //[mir]~^^ ERROR lifetime may not live long enough
+}
+
+fn main() {
+}
diff --git a/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.stderr b/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.stderr
new file mode 100644
index 0000000..aa92c59
--- /dev/null
+++ b/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.stderr
@@ -0,0 +1,20 @@
+error[E0491]: in type `&'a WithAssoc<TheType<'b>>`, reference has a longer lifetime than the data it references
+  --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:42:13
+   |
+LL |     let _x: &'a WithAssoc<TheType<'b>> = loop { };
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the pointer is valid for the lifetime 'a as defined on the function body at 34:15
+  --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:34:15
+   |
+LL | fn with_assoc<'a,'b>() {
+   |               ^^
+note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 34:18
+  --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:34:18
+   |
+LL | fn with_assoc<'a,'b>() {
+   |                  ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0491`.
diff --git a/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.rs b/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.rs
new file mode 100644
index 0000000..26cb40b
--- /dev/null
+++ b/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.rs
@@ -0,0 +1,24 @@
+// Test that the compiler checks that arbitrary region bounds declared
+// in the trait must be satisfied on the impl. Issue #20890.
+
+trait Foo<'a> {
+    type Value: 'a;
+    fn dummy(&'a self) { }
+}
+
+impl<'a> Foo<'a> for &'a i16 {
+    // OK.
+    type Value = &'a i32;
+}
+
+impl<'a> Foo<'static> for &'a i32 {
+    //~^ ERROR cannot infer
+    type Value = &'a i32;
+}
+
+impl<'a,'b> Foo<'b> for &'a i64 {
+    //~^ ERROR cannot infer
+    type Value = &'a i32;
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr b/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr
new file mode 100644
index 0000000..d01e991
--- /dev/null
+++ b/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr
@@ -0,0 +1,49 @@
+error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
+  --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:14:10
+   |
+LL | impl<'a> Foo<'static> for &'a i32 {
+   |          ^^^^^^^^^^^^
+   |
+note: first, the lifetime cannot outlive the lifetime 'a as defined on the impl at 14:6...
+  --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:14:6
+   |
+LL | impl<'a> Foo<'static> for &'a i32 {
+   |      ^^
+   = note: ...so that the types are compatible:
+           expected Foo<'static>
+              found Foo<'static>
+   = note: but, the lifetime must be valid for the static lifetime...
+note: ...so that the type `&i32` will meet its required lifetime bounds
+  --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:14:10
+   |
+LL | impl<'a> Foo<'static> for &'a i32 {
+   |          ^^^^^^^^^^^^
+
+error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
+  --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:19:13
+   |
+LL | impl<'a,'b> Foo<'b> for &'a i64 {
+   |             ^^^^^^^
+   |
+note: first, the lifetime cannot outlive the lifetime 'a as defined on the impl at 19:6...
+  --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:19:6
+   |
+LL | impl<'a,'b> Foo<'b> for &'a i64 {
+   |      ^^
+   = note: ...so that the types are compatible:
+           expected Foo<'b>
+              found Foo<'_>
+note: but, the lifetime must be valid for the lifetime 'b as defined on the impl at 19:9...
+  --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:19:9
+   |
+LL | impl<'a,'b> Foo<'b> for &'a i64 {
+   |         ^^
+note: ...so that the type `&i32` will meet its required lifetime bounds
+  --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:19:13
+   |
+LL | impl<'a,'b> Foo<'b> for &'a i64 {
+   |             ^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0495`.
diff --git a/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.rs b/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.rs
new file mode 100644
index 0000000..599cd0b
--- /dev/null
+++ b/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.rs
@@ -0,0 +1,19 @@
+// Test that the compiler checks that the 'static bound declared in
+// the trait must be satisfied on the impl. Issue #20890.
+
+trait Foo {
+    type Value: 'static;
+    fn dummy(&self) { }
+}
+
+impl<'a> Foo for &'a i32 {
+    //~^ ERROR cannot infer
+    type Value = &'a i32;
+}
+
+impl<'a> Foo for i32 {
+    // OK.
+    type Value = i32;
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr b/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr
new file mode 100644
index 0000000..33a4ea0
--- /dev/null
+++ b/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr
@@ -0,0 +1,24 @@
+error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
+  --> $DIR/regions-assoc-type-static-bound-in-trait-not-met.rs:9:10
+   |
+LL | impl<'a> Foo for &'a i32 {
+   |          ^^^
+   |
+note: first, the lifetime cannot outlive the lifetime 'a as defined on the impl at 9:6...
+  --> $DIR/regions-assoc-type-static-bound-in-trait-not-met.rs:9:6
+   |
+LL | impl<'a> Foo for &'a i32 {
+   |      ^^
+   = note: ...so that the types are compatible:
+           expected Foo
+              found Foo
+   = note: but, the lifetime must be valid for the static lifetime...
+note: ...so that the type `&i32` will meet its required lifetime bounds
+  --> $DIR/regions-assoc-type-static-bound-in-trait-not-met.rs:9:10
+   |
+LL | impl<'a> Foo for &'a i32 {
+   |          ^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0495`.
diff --git a/src/test/ui/regions/regions-bounded-by-trait-requiring-static.rs b/src/test/ui/regions/regions-bounded-by-trait-requiring-static.rs
new file mode 100644
index 0000000..c583f43
--- /dev/null
+++ b/src/test/ui/regions/regions-bounded-by-trait-requiring-static.rs
@@ -0,0 +1,63 @@
+// Test which of the builtin types are considered sendable. The tests
+// in this file all test region bound and lifetime violations that are
+// detected during type check.
+
+trait Dummy : 'static { }
+fn assert_send<T:'static>() { }
+
+// lifetime pointers with 'static lifetime are ok
+
+fn static_lifime_ok<'a,T,U:Send>(_: &'a isize) {
+    assert_send::<&'static isize>();
+    assert_send::<&'static str>();
+    assert_send::<&'static [isize]>();
+
+    // whether or not they are mutable
+    assert_send::<&'static mut isize>();
+}
+
+// otherwise lifetime pointers are not ok
+
+fn param_not_ok<'a>(x: &'a isize) {
+    assert_send::<&'a isize>(); //~ ERROR does not fulfill the required lifetime
+}
+
+fn param_not_ok1<'a>(_: &'a isize) {
+    assert_send::<&'a str>(); //~ ERROR does not fulfill the required lifetime
+}
+
+fn param_not_ok2<'a>(_: &'a isize) {
+    assert_send::<&'a [isize]>(); //~ ERROR does not fulfill the required lifetime
+}
+
+// boxes are ok
+
+fn box_ok() {
+    assert_send::<Box<isize>>();
+    assert_send::<String>();
+    assert_send::<Vec<isize>>();
+}
+
+// but not if they own a bad thing
+
+fn box_with_region_not_ok<'a>() {
+    assert_send::<Box<&'a isize>>(); //~ ERROR does not fulfill the required lifetime
+}
+
+// raw pointers are ok unless they point at unsendable things
+
+fn unsafe_ok1<'a>(_: &'a isize) {
+    assert_send::<*const isize>();
+    assert_send::<*mut isize>();
+}
+
+fn unsafe_ok2<'a>(_: &'a isize) {
+    assert_send::<*const &'a isize>(); //~ ERROR does not fulfill the required lifetime
+}
+
+fn unsafe_ok3<'a>(_: &'a isize) {
+    assert_send::<*mut &'a isize>(); //~ ERROR does not fulfill the required lifetime
+}
+
+fn main() {
+}
diff --git a/src/test/ui/regions/regions-bounded-by-trait-requiring-static.stderr b/src/test/ui/regions/regions-bounded-by-trait-requiring-static.stderr
new file mode 100644
index 0000000..c72d648
--- /dev/null
+++ b/src/test/ui/regions/regions-bounded-by-trait-requiring-static.stderr
@@ -0,0 +1,51 @@
+error[E0477]: the type `&'a isize` does not fulfill the required lifetime
+  --> $DIR/regions-bounded-by-trait-requiring-static.rs:22:5
+   |
+LL |     assert_send::<&'a isize>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: type must satisfy the static lifetime
+
+error[E0477]: the type `&'a str` does not fulfill the required lifetime
+  --> $DIR/regions-bounded-by-trait-requiring-static.rs:26:5
+   |
+LL |     assert_send::<&'a str>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: type must satisfy the static lifetime
+
+error[E0477]: the type `&'a [isize]` does not fulfill the required lifetime
+  --> $DIR/regions-bounded-by-trait-requiring-static.rs:30:5
+   |
+LL |     assert_send::<&'a [isize]>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: type must satisfy the static lifetime
+
+error[E0477]: the type `std::boxed::Box<&'a isize>` does not fulfill the required lifetime
+  --> $DIR/regions-bounded-by-trait-requiring-static.rs:44:5
+   |
+LL |     assert_send::<Box<&'a isize>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: type must satisfy the static lifetime
+
+error[E0477]: the type `*const &'a isize` does not fulfill the required lifetime
+  --> $DIR/regions-bounded-by-trait-requiring-static.rs:55:5
+   |
+LL |     assert_send::<*const &'a isize>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: type must satisfy the static lifetime
+
+error[E0477]: the type `*mut &'a isize` does not fulfill the required lifetime
+  --> $DIR/regions-bounded-by-trait-requiring-static.rs:59:5
+   |
+LL |     assert_send::<*mut &'a isize>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: type must satisfy the static lifetime
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0477`.
diff --git a/src/test/ui/regions/regions-bounded-method-type-parameters-cross-crate.rs b/src/test/ui/regions/regions-bounded-method-type-parameters-cross-crate.rs
new file mode 100644
index 0000000..a7987d0
--- /dev/null
+++ b/src/test/ui/regions/regions-bounded-method-type-parameters-cross-crate.rs
@@ -0,0 +1,23 @@
+// aux-build:rbmtp_cross_crate_lib.rs
+
+// Check explicit region bounds on methods in the cross crate case.
+
+extern crate rbmtp_cross_crate_lib as lib;
+
+use lib::Inv;
+use lib::MaybeOwned;
+use lib::IntoMaybeOwned;
+
+fn call_into_maybe_owned<'x,F:IntoMaybeOwned<'x>>(f: F) {
+    // Exercise a code path I found to be buggy. We were not encoding
+    // the region parameters from the receiver correctly on trait
+    // methods.
+    f.into_maybe_owned();
+}
+
+fn call_bigger_region<'x, 'y>(a: Inv<'x>, b: Inv<'y>) {
+    // Here the value provided for 'y is 'y, and hence 'y:'x does not hold.
+    a.bigger_region(b) //~ ERROR lifetime mismatch [E0623]
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-bounded-method-type-parameters-cross-crate.stderr b/src/test/ui/regions/regions-bounded-method-type-parameters-cross-crate.stderr
new file mode 100644
index 0000000..eb205a3
--- /dev/null
+++ b/src/test/ui/regions/regions-bounded-method-type-parameters-cross-crate.stderr
@@ -0,0 +1,12 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/regions-bounded-method-type-parameters-cross-crate.rs:20:7
+   |
+LL | fn call_bigger_region<'x, 'y>(a: Inv<'x>, b: Inv<'y>) {
+   |                                  -------     ------- these two types are declared with different lifetimes...
+LL |     // Here the value provided for 'y is 'y, and hence 'y:'x does not hold.
+LL |     a.bigger_region(b)
+   |       ^^^^^^^^^^^^^ ...but data from `b` flows into `a` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/regions/regions-bounded-method-type-parameters-trait-bound.rs b/src/test/ui/regions/regions-bounded-method-type-parameters-trait-bound.rs
new file mode 100644
index 0000000..8adf496
--- /dev/null
+++ b/src/test/ui/regions/regions-bounded-method-type-parameters-trait-bound.rs
@@ -0,0 +1,28 @@
+// Check that explicit region bounds are allowed on the various
+// nominal types (but not on other types) and that they are type
+// checked.
+
+struct Inv<'a> { // invariant w/r/t 'a
+    x: &'a mut &'a isize
+}
+
+trait Foo<'x> {
+    fn method<'y:'x>(self, y: Inv<'y>);
+}
+
+fn caller1<'a,'b,F:Foo<'a>>(a: Inv<'a>, b: Inv<'b>, f: F) {
+    // Here the value provided for 'y is 'a, and hence 'a:'a holds.
+    f.method(a);
+}
+
+fn caller2<'a,'b,F:Foo<'a>>(a: Inv<'a>, b: Inv<'b>, f: F) {
+    // Here the value provided for 'y is 'b, and hence 'b:'a does not hold.
+    f.method(b); //~ ERROR lifetime mismatch [E0623]
+}
+
+fn caller3<'a,'b:'a,F:Foo<'a>>(a: Inv<'a>, b: Inv<'b>, f: F) {
+    // Here the value provided for 'y is 'b, and hence 'b:'a holds.
+    f.method(b);
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-bounded-method-type-parameters-trait-bound.stderr b/src/test/ui/regions/regions-bounded-method-type-parameters-trait-bound.stderr
new file mode 100644
index 0000000..de1073c
--- /dev/null
+++ b/src/test/ui/regions/regions-bounded-method-type-parameters-trait-bound.stderr
@@ -0,0 +1,12 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/regions-bounded-method-type-parameters-trait-bound.rs:20:7
+   |
+LL | fn caller2<'a,'b,F:Foo<'a>>(a: Inv<'a>, b: Inv<'b>, f: F) {
+   |                                -------     ------- these two types are declared with different lifetimes...
+LL |     // Here the value provided for 'y is 'b, and hence 'b:'a does not hold.
+LL |     f.method(b);
+   |       ^^^^^^ ...but data from `b` flows into `a` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/regions/regions-bounded-method-type-parameters.rs b/src/test/ui/regions/regions-bounded-method-type-parameters.rs
new file mode 100644
index 0000000..90af120
--- /dev/null
+++ b/src/test/ui/regions/regions-bounded-method-type-parameters.rs
@@ -0,0 +1,16 @@
+// Check that explicit region bounds are allowed on the various
+// nominal types (but not on other types) and that they are type
+// checked.
+
+struct Foo;
+
+impl Foo {
+    fn some_method<A:'static>(self) { }
+}
+
+fn caller<'a>(x: &isize) {
+    Foo.some_method::<&'a isize>();
+    //~^ ERROR does not fulfill the required lifetime
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-bounded-method-type-parameters.stderr b/src/test/ui/regions/regions-bounded-method-type-parameters.stderr
new file mode 100644
index 0000000..66b61b1
--- /dev/null
+++ b/src/test/ui/regions/regions-bounded-method-type-parameters.stderr
@@ -0,0 +1,11 @@
+error[E0477]: the type `&'a isize` does not fulfill the required lifetime
+  --> $DIR/regions-bounded-method-type-parameters.rs:12:9
+   |
+LL |     Foo.some_method::<&'a isize>();
+   |         ^^^^^^^^^^^
+   |
+   = note: type must satisfy the static lifetime
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0477`.
diff --git a/src/test/ui/regions/regions-bounds.rs b/src/test/ui/regions/regions-bounds.rs
new file mode 100644
index 0000000..d3e4e6e
--- /dev/null
+++ b/src/test/ui/regions/regions-bounds.rs
@@ -0,0 +1,16 @@
+// Check that explicit region bounds are allowed on the various
+// nominal types (but not on other types) and that they are type
+// checked.
+
+struct TupleStruct<'a>(&'a isize);
+struct Struct<'a> { x:&'a isize }
+
+fn a_fn1<'a,'b>(e: TupleStruct<'a>) -> TupleStruct<'b> {
+    return e; //~ ERROR mismatched types
+}
+
+fn a_fn3<'a,'b>(e: Struct<'a>) -> Struct<'b> {
+    return e; //~ ERROR mismatched types
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-bounds.stderr b/src/test/ui/regions/regions-bounds.stderr
new file mode 100644
index 0000000..27eb889
--- /dev/null
+++ b/src/test/ui/regions/regions-bounds.stderr
@@ -0,0 +1,41 @@
+error[E0308]: mismatched types
+  --> $DIR/regions-bounds.rs:9:12
+   |
+LL |     return e;
+   |            ^ lifetime mismatch
+   |
+   = note: expected type `TupleStruct<'b>`
+              found type `TupleStruct<'a>`
+note: the lifetime 'a as defined on the function body at 8:10...
+  --> $DIR/regions-bounds.rs:8:10
+   |
+LL | fn a_fn1<'a,'b>(e: TupleStruct<'a>) -> TupleStruct<'b> {
+   |          ^^
+note: ...does not necessarily outlive the lifetime 'b as defined on the function body at 8:13
+  --> $DIR/regions-bounds.rs:8:13
+   |
+LL | fn a_fn1<'a,'b>(e: TupleStruct<'a>) -> TupleStruct<'b> {
+   |             ^^
+
+error[E0308]: mismatched types
+  --> $DIR/regions-bounds.rs:13:12
+   |
+LL |     return e;
+   |            ^ lifetime mismatch
+   |
+   = note: expected type `Struct<'b>`
+              found type `Struct<'a>`
+note: the lifetime 'a as defined on the function body at 12:10...
+  --> $DIR/regions-bounds.rs:12:10
+   |
+LL | fn a_fn3<'a,'b>(e: Struct<'a>) -> Struct<'b> {
+   |          ^^
+note: ...does not necessarily outlive the lifetime 'b as defined on the function body at 12:13
+  --> $DIR/regions-bounds.rs:12:13
+   |
+LL | fn a_fn3<'a,'b>(e: Struct<'a>) -> Struct<'b> {
+   |             ^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/regions/regions-close-associated-type-into-object.rs b/src/test/ui/regions/regions-close-associated-type-into-object.rs
new file mode 100644
index 0000000..853d961
--- /dev/null
+++ b/src/test/ui/regions/regions-close-associated-type-into-object.rs
@@ -0,0 +1,71 @@
+#![feature(box_syntax)]
+
+trait X {}
+
+trait Iter {
+    type Item: X;
+
+    fn into_item(self) -> Self::Item;
+    fn as_item(&self) -> &Self::Item;
+}
+
+fn bad1<T: Iter>(v: T) -> Box<X+'static>
+{
+    let item = v.into_item();
+    Box::new(item) //~ ERROR associated type `<T as Iter>::Item` may not live long enough
+}
+
+fn bad2<T: Iter>(v: T) -> Box<X+'static>
+    where Box<T::Item> : X
+{
+    let item: Box<_> = box v.into_item();
+    Box::new(item) //~ ERROR associated type `<T as Iter>::Item` may not live long enough
+}
+
+fn bad3<'a, T: Iter>(v: T) -> Box<X+'a>
+{
+    let item = v.into_item();
+    Box::new(item) //~ ERROR associated type `<T as Iter>::Item` may not live long enough
+}
+
+fn bad4<'a, T: Iter>(v: T) -> Box<X+'a>
+    where Box<T::Item> : X
+{
+    let item: Box<_> = box v.into_item();
+    Box::new(item) //~ ERROR associated type `<T as Iter>::Item` may not live long enough
+}
+
+fn ok1<'a, T: Iter>(v: T) -> Box<X+'a>
+    where T::Item : 'a
+{
+    let item = v.into_item();
+    Box::new(item) // OK, T::Item : 'a is declared
+}
+
+fn ok2<'a, T: Iter>(v: &T, w: &'a T::Item) -> Box<X+'a>
+    where T::Item : Clone
+{
+    let item = Clone::clone(w);
+    Box::new(item) // OK, T::Item : 'a is implied
+}
+
+fn ok3<'a, T: Iter>(v: &'a T) -> Box<X+'a>
+    where T::Item : Clone + 'a
+{
+    let item = Clone::clone(v.as_item());
+    Box::new(item) // OK, T::Item : 'a was declared
+}
+
+fn meh1<'a, T: Iter>(v: &'a T) -> Box<X+'a>
+    where T::Item : Clone
+{
+    // This case is kind of interesting. It's the same as `ok3` but
+    // without the explicit declaration. This is valid because `T: 'a
+    // => T::Item: 'a`, and the former we can deduce from our argument
+    // of type `&'a T`.
+
+    let item = Clone::clone(v.as_item());
+    Box::new(item)
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-close-associated-type-into-object.stderr b/src/test/ui/regions/regions-close-associated-type-into-object.stderr
new file mode 100644
index 0000000..89c0c25
--- /dev/null
+++ b/src/test/ui/regions/regions-close-associated-type-into-object.stderr
@@ -0,0 +1,56 @@
+error[E0310]: the associated type `<T as Iter>::Item` may not live long enough
+  --> $DIR/regions-close-associated-type-into-object.rs:15:5
+   |
+LL |     Box::new(item)
+   |     ^^^^^^^^^^^^^^
+   |
+   = help: consider adding an explicit lifetime bound `<T as Iter>::Item: 'static`...
+note: ...so that the type `<T as Iter>::Item` will meet its required lifetime bounds
+  --> $DIR/regions-close-associated-type-into-object.rs:15:5
+   |
+LL |     Box::new(item)
+   |     ^^^^^^^^^^^^^^
+
+error[E0310]: the associated type `<T as Iter>::Item` may not live long enough
+  --> $DIR/regions-close-associated-type-into-object.rs:22:5
+   |
+LL |     Box::new(item)
+   |     ^^^^^^^^^^^^^^
+   |
+   = help: consider adding an explicit lifetime bound `<T as Iter>::Item: 'static`...
+note: ...so that the type `std::boxed::Box<<T as Iter>::Item>` will meet its required lifetime bounds
+  --> $DIR/regions-close-associated-type-into-object.rs:22:5
+   |
+LL |     Box::new(item)
+   |     ^^^^^^^^^^^^^^
+
+error[E0309]: the associated type `<T as Iter>::Item` may not live long enough
+  --> $DIR/regions-close-associated-type-into-object.rs:28:5
+   |
+LL |     Box::new(item)
+   |     ^^^^^^^^^^^^^^
+   |
+   = help: consider adding an explicit lifetime bound `<T as Iter>::Item: 'a`...
+note: ...so that the type `<T as Iter>::Item` will meet its required lifetime bounds
+  --> $DIR/regions-close-associated-type-into-object.rs:28:5
+   |
+LL |     Box::new(item)
+   |     ^^^^^^^^^^^^^^
+
+error[E0309]: the associated type `<T as Iter>::Item` may not live long enough
+  --> $DIR/regions-close-associated-type-into-object.rs:35:5
+   |
+LL |     Box::new(item)
+   |     ^^^^^^^^^^^^^^
+   |
+   = help: consider adding an explicit lifetime bound `<T as Iter>::Item: 'a`...
+note: ...so that the type `std::boxed::Box<<T as Iter>::Item>` will meet its required lifetime bounds
+  --> $DIR/regions-close-associated-type-into-object.rs:35:5
+   |
+LL |     Box::new(item)
+   |     ^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0309, E0310.
+For more information about an error, try `rustc --explain E0309`.
diff --git a/src/test/ui/regions/regions-close-object-into-object-1.nll.stderr b/src/test/ui/regions/regions-close-object-into-object-1.nll.stderr
new file mode 100644
index 0000000..8e119c4
--- /dev/null
+++ b/src/test/ui/regions/regions-close-object-into-object-1.nll.stderr
@@ -0,0 +1,12 @@
+error[E0515]: cannot return value referencing local data `*v`
+  --> $DIR/regions-close-object-into-object-1.rs:12:5
+   |
+LL |     box B(&*v) as Box<X>
+   |     ^^^^^^---^^^^^^^^^^^
+   |     |     |
+   |     |     `*v` is borrowed here
+   |     returns a value referencing data owned by the current function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/src/test/ui/regions/regions-close-object-into-object-1.rs b/src/test/ui/regions/regions-close-object-into-object-1.rs
new file mode 100644
index 0000000..7a862f9
--- /dev/null
+++ b/src/test/ui/regions/regions-close-object-into-object-1.rs
@@ -0,0 +1,15 @@
+#![feature(box_syntax)]
+#![allow(warnings)]
+
+trait A<T> { }
+struct B<'a, T:'a>(&'a (A<T>+'a));
+
+trait X { }
+
+impl<'a, T> X for B<'a, T> {}
+
+fn f<'a, T:'static, U>(v: Box<A<T>+'static>) -> Box<X+'static> {
+    box B(&*v) as Box<X> //~ ERROR `*v` does not live long enough
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-close-object-into-object-1.stderr b/src/test/ui/regions/regions-close-object-into-object-1.stderr
new file mode 100644
index 0000000..c7bde8d
--- /dev/null
+++ b/src/test/ui/regions/regions-close-object-into-object-1.stderr
@@ -0,0 +1,13 @@
+error[E0597]: `*v` does not live long enough
+  --> $DIR/regions-close-object-into-object-1.rs:12:12
+   |
+LL |     box B(&*v) as Box<X>
+   |            ^^ borrowed value does not live long enough
+LL | }
+   | - borrowed value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/regions/regions-close-object-into-object-2.rs b/src/test/ui/regions/regions-close-object-into-object-2.rs
new file mode 100644
index 0000000..cebb4ac
--- /dev/null
+++ b/src/test/ui/regions/regions-close-object-into-object-2.rs
@@ -0,0 +1,13 @@
+#![feature(box_syntax)]
+
+trait A<T> { }
+struct B<'a, T:'a>(&'a (A<T>+'a));
+
+trait X { }
+impl<'a, T> X for B<'a, T> {}
+
+fn g<'a, T: 'static>(v: Box<A<T>+'a>) -> Box<X+'static> {
+    box B(&*v) as Box<X> //~ ERROR cannot infer
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-close-object-into-object-2.stderr b/src/test/ui/regions/regions-close-object-into-object-2.stderr
new file mode 100644
index 0000000..d5e228e
--- /dev/null
+++ b/src/test/ui/regions/regions-close-object-into-object-2.stderr
@@ -0,0 +1,24 @@
+error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
+  --> $DIR/regions-close-object-into-object-2.rs:10:11
+   |
+LL |     box B(&*v) as Box<X>
+   |           ^^^
+   |
+note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 9:6...
+  --> $DIR/regions-close-object-into-object-2.rs:9:6
+   |
+LL | fn g<'a, T: 'static>(v: Box<A<T>+'a>) -> Box<X+'static> {
+   |      ^^
+note: ...so that the type `(dyn A<T> + 'a)` is not borrowed for too long
+  --> $DIR/regions-close-object-into-object-2.rs:10:11
+   |
+LL |     box B(&*v) as Box<X>
+   |           ^^^
+   = note: but, the lifetime must be valid for the static lifetime...
+   = note: ...so that the expression is assignable:
+           expected std::boxed::Box<(dyn X + 'static)>
+              found std::boxed::Box<dyn X>
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0495`.
diff --git a/src/test/ui/regions/regions-close-object-into-object-3.nll.stderr b/src/test/ui/regions/regions-close-object-into-object-3.nll.stderr
new file mode 100644
index 0000000..9ea1363
--- /dev/null
+++ b/src/test/ui/regions/regions-close-object-into-object-3.nll.stderr
@@ -0,0 +1,12 @@
+error[E0515]: cannot return value referencing local data `*v`
+  --> $DIR/regions-close-object-into-object-3.rs:11:5
+   |
+LL |     box B(&*v) as Box<X>
+   |     ^^^^^^---^^^^^^^^^^^
+   |     |     |
+   |     |     `*v` is borrowed here
+   |     returns a value referencing data owned by the current function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/src/test/ui/regions/regions-close-object-into-object-3.rs b/src/test/ui/regions/regions-close-object-into-object-3.rs
new file mode 100644
index 0000000..cafbf09
--- /dev/null
+++ b/src/test/ui/regions/regions-close-object-into-object-3.rs
@@ -0,0 +1,14 @@
+#![feature(box_syntax)]
+#![allow(warnings)]
+
+trait A<T> { }
+struct B<'a, T:'a>(&'a (A<T>+'a));
+
+trait X { }
+impl<'a, T> X for B<'a, T> {}
+
+fn h<'a, T, U:'static>(v: Box<A<U>+'static>) -> Box<X+'static> {
+    box B(&*v) as Box<X> //~ ERROR `*v` does not live long enough
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-close-object-into-object-3.stderr b/src/test/ui/regions/regions-close-object-into-object-3.stderr
new file mode 100644
index 0000000..122e57a
--- /dev/null
+++ b/src/test/ui/regions/regions-close-object-into-object-3.stderr
@@ -0,0 +1,13 @@
+error[E0597]: `*v` does not live long enough
+  --> $DIR/regions-close-object-into-object-3.rs:11:12
+   |
+LL |     box B(&*v) as Box<X>
+   |            ^^ borrowed value does not live long enough
+LL | }
+   | - borrowed value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/regions/regions-close-object-into-object-4.rs b/src/test/ui/regions/regions-close-object-into-object-4.rs
new file mode 100644
index 0000000..91aab05
--- /dev/null
+++ b/src/test/ui/regions/regions-close-object-into-object-4.rs
@@ -0,0 +1,13 @@
+#![feature(box_syntax)]
+
+trait A<T> { }
+struct B<'a, T:'a>(&'a (A<T>+'a));
+
+trait X { }
+impl<'a, T> X for B<'a, T> {}
+
+fn i<'a, T, U>(v: Box<A<U>+'a>) -> Box<X+'static> {
+    box B(&*v) as Box<X> //~ ERROR cannot infer
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-close-object-into-object-4.stderr b/src/test/ui/regions/regions-close-object-into-object-4.stderr
new file mode 100644
index 0000000..c9ad95d
--- /dev/null
+++ b/src/test/ui/regions/regions-close-object-into-object-4.stderr
@@ -0,0 +1,24 @@
+error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
+  --> $DIR/regions-close-object-into-object-4.rs:10:11
+   |
+LL |     box B(&*v) as Box<X>
+   |           ^^^
+   |
+note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 9:6...
+  --> $DIR/regions-close-object-into-object-4.rs:9:6
+   |
+LL | fn i<'a, T, U>(v: Box<A<U>+'a>) -> Box<X+'static> {
+   |      ^^
+note: ...so that the type `(dyn A<U> + 'a)` is not borrowed for too long
+  --> $DIR/regions-close-object-into-object-4.rs:10:11
+   |
+LL |     box B(&*v) as Box<X>
+   |           ^^^
+   = note: but, the lifetime must be valid for the static lifetime...
+   = note: ...so that the expression is assignable:
+           expected std::boxed::Box<(dyn X + 'static)>
+              found std::boxed::Box<dyn X>
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0495`.
diff --git a/src/test/ui/regions/regions-close-object-into-object-5.rs b/src/test/ui/regions/regions-close-object-into-object-5.rs
new file mode 100644
index 0000000..609c8ce
--- /dev/null
+++ b/src/test/ui/regions/regions-close-object-into-object-5.rs
@@ -0,0 +1,26 @@
+#![feature(box_syntax)]
+#![allow(warnings)]
+
+trait A<T>
+{
+    fn get(&self) -> T { panic!() }
+}
+
+struct B<'a, T:'a>(&'a (A<T>+'a));
+
+trait X { fn foo(&self) {} }
+
+impl<'a, T> X for B<'a, T> {}
+
+fn f<'a, T, U>(v: Box<A<T>+'static>) -> Box<X+'static> {
+    // oh dear!
+    box B(&*v) as Box<X>
+        //~^ ERROR the parameter type `T` may not live long enough
+        //~| ERROR the parameter type `T` may not live long enough
+        //~| ERROR the parameter type `T` may not live long enough
+        //~| ERROR the parameter type `T` may not live long enough
+        //~| ERROR the parameter type `T` may not live long enough
+        //~| ERROR the parameter type `T` may not live long enough
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-close-object-into-object-5.stderr b/src/test/ui/regions/regions-close-object-into-object-5.stderr
new file mode 100644
index 0000000..390f8e7
--- /dev/null
+++ b/src/test/ui/regions/regions-close-object-into-object-5.stderr
@@ -0,0 +1,93 @@
+error[E0310]: the parameter type `T` may not live long enough
+  --> $DIR/regions-close-object-into-object-5.rs:17:5
+   |
+LL | fn f<'a, T, U>(v: Box<A<T>+'static>) -> Box<X+'static> {
+   |          - help: consider adding an explicit lifetime bound `T: 'static`...
+LL |     // oh dear!
+LL |     box B(&*v) as Box<X>
+   |     ^^^^^^^^^^
+   |
+note: ...so that the type `B<'_, T>` will meet its required lifetime bounds
+  --> $DIR/regions-close-object-into-object-5.rs:17:5
+   |
+LL |     box B(&*v) as Box<X>
+   |     ^^^^^^^^^^
+
+error[E0310]: the parameter type `T` may not live long enough
+  --> $DIR/regions-close-object-into-object-5.rs:17:5
+   |
+LL | fn f<'a, T, U>(v: Box<A<T>+'static>) -> Box<X+'static> {
+   |          - help: consider adding an explicit lifetime bound `T: 'static`...
+LL |     // oh dear!
+LL |     box B(&*v) as Box<X>
+   |     ^^^^^^^^^^^^^^^^^^^^
+   |
+note: ...so that it can be closed over into an object
+  --> $DIR/regions-close-object-into-object-5.rs:17:5
+   |
+LL |     box B(&*v) as Box<X>
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error[E0310]: the parameter type `T` may not live long enough
+  --> $DIR/regions-close-object-into-object-5.rs:17:9
+   |
+LL | fn f<'a, T, U>(v: Box<A<T>+'static>) -> Box<X+'static> {
+   |          - help: consider adding an explicit lifetime bound `T: 'static`...
+LL |     // oh dear!
+LL |     box B(&*v) as Box<X>
+   |         ^
+   |
+note: ...so that the type `T` will meet its required lifetime bounds
+  --> $DIR/regions-close-object-into-object-5.rs:17:9
+   |
+LL |     box B(&*v) as Box<X>
+   |         ^
+
+error[E0310]: the parameter type `T` may not live long enough
+  --> $DIR/regions-close-object-into-object-5.rs:17:9
+   |
+LL | fn f<'a, T, U>(v: Box<A<T>+'static>) -> Box<X+'static> {
+   |          - help: consider adding an explicit lifetime bound `T: 'static`...
+LL |     // oh dear!
+LL |     box B(&*v) as Box<X>
+   |         ^^^^^^
+   |
+note: ...so that the reference type `&dyn A<T>` does not outlive the data it points at
+  --> $DIR/regions-close-object-into-object-5.rs:17:9
+   |
+LL |     box B(&*v) as Box<X>
+   |         ^^^^^^
+
+error[E0310]: the parameter type `T` may not live long enough
+  --> $DIR/regions-close-object-into-object-5.rs:17:9
+   |
+LL | fn f<'a, T, U>(v: Box<A<T>+'static>) -> Box<X+'static> {
+   |          - help: consider adding an explicit lifetime bound `T: 'static`...
+LL |     // oh dear!
+LL |     box B(&*v) as Box<X>
+   |         ^^^^^^
+   |
+note: ...so that the type `T` will meet its required lifetime bounds
+  --> $DIR/regions-close-object-into-object-5.rs:17:9
+   |
+LL |     box B(&*v) as Box<X>
+   |         ^^^^^^
+
+error[E0310]: the parameter type `T` may not live long enough
+  --> $DIR/regions-close-object-into-object-5.rs:17:11
+   |
+LL | fn f<'a, T, U>(v: Box<A<T>+'static>) -> Box<X+'static> {
+   |          - help: consider adding an explicit lifetime bound `T: 'static`...
+LL |     // oh dear!
+LL |     box B(&*v) as Box<X>
+   |           ^^^
+   |
+note: ...so that the type `(dyn A<T> + 'static)` is not borrowed for too long
+  --> $DIR/regions-close-object-into-object-5.rs:17:11
+   |
+LL |     box B(&*v) as Box<X>
+   |           ^^^
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0310`.
diff --git a/src/test/ui/regions/regions-close-over-type-parameter-1.rs b/src/test/ui/regions/regions-close-over-type-parameter-1.rs
new file mode 100644
index 0000000..9aee966
--- /dev/null
+++ b/src/test/ui/regions/regions-close-over-type-parameter-1.rs
@@ -0,0 +1,25 @@
+#![feature(box_syntax)]
+
+// Test for what happens when a type parameter `A` is closed over into
+// an object. This should yield errors unless `A` (and the object)
+// both have suitable bounds.
+
+trait SomeTrait { fn get(&self) -> isize; }
+
+fn make_object1<A:SomeTrait>(v: A) -> Box<SomeTrait+'static> {
+    box v as Box<SomeTrait+'static>
+        //~^ ERROR the parameter type `A` may not live long enough
+        //~| ERROR the parameter type `A` may not live long enough
+}
+
+fn make_object2<'a,A:SomeTrait+'a>(v: A) -> Box<SomeTrait+'a> {
+    box v as Box<SomeTrait+'a>
+}
+
+fn make_object3<'a,'b,A:SomeTrait+'a>(v: A) -> Box<SomeTrait+'b> {
+    box v as Box<SomeTrait+'b>
+        //~^ ERROR the parameter type `A` may not live long enough
+        //~| ERROR the parameter type `A` may not live long enough
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-close-over-type-parameter-1.stderr b/src/test/ui/regions/regions-close-over-type-parameter-1.stderr
new file mode 100644
index 0000000..6d33f14
--- /dev/null
+++ b/src/test/ui/regions/regions-close-over-type-parameter-1.stderr
@@ -0,0 +1,60 @@
+error[E0310]: the parameter type `A` may not live long enough
+  --> $DIR/regions-close-over-type-parameter-1.rs:10:5
+   |
+LL | fn make_object1<A:SomeTrait>(v: A) -> Box<SomeTrait+'static> {
+   |                 -- help: consider adding an explicit lifetime bound `A: 'static`...
+LL |     box v as Box<SomeTrait+'static>
+   |     ^^^^^
+   |
+note: ...so that the type `A` will meet its required lifetime bounds
+  --> $DIR/regions-close-over-type-parameter-1.rs:10:5
+   |
+LL |     box v as Box<SomeTrait+'static>
+   |     ^^^^^
+
+error[E0310]: the parameter type `A` may not live long enough
+  --> $DIR/regions-close-over-type-parameter-1.rs:10:5
+   |
+LL | fn make_object1<A:SomeTrait>(v: A) -> Box<SomeTrait+'static> {
+   |                 -- help: consider adding an explicit lifetime bound `A: 'static`...
+LL |     box v as Box<SomeTrait+'static>
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: ...so that it can be closed over into an object
+  --> $DIR/regions-close-over-type-parameter-1.rs:10:5
+   |
+LL |     box v as Box<SomeTrait+'static>
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0309]: the parameter type `A` may not live long enough
+  --> $DIR/regions-close-over-type-parameter-1.rs:20:5
+   |
+LL | fn make_object3<'a,'b,A:SomeTrait+'a>(v: A) -> Box<SomeTrait+'b> {
+   |                       -- help: consider adding an explicit lifetime bound `A: 'b`...
+LL |     box v as Box<SomeTrait+'b>
+   |     ^^^^^
+   |
+note: ...so that the type `A` will meet its required lifetime bounds
+  --> $DIR/regions-close-over-type-parameter-1.rs:20:5
+   |
+LL |     box v as Box<SomeTrait+'b>
+   |     ^^^^^
+
+error[E0309]: the parameter type `A` may not live long enough
+  --> $DIR/regions-close-over-type-parameter-1.rs:20:5
+   |
+LL | fn make_object3<'a,'b,A:SomeTrait+'a>(v: A) -> Box<SomeTrait+'b> {
+   |                       -- help: consider adding an explicit lifetime bound `A: 'b`...
+LL |     box v as Box<SomeTrait+'b>
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: ...so that it can be closed over into an object
+  --> $DIR/regions-close-over-type-parameter-1.rs:20:5
+   |
+LL |     box v as Box<SomeTrait+'b>
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0309, E0310.
+For more information about an error, try `rustc --explain E0309`.
diff --git a/src/test/ui/regions/regions-close-over-type-parameter-multiple.rs b/src/test/ui/regions/regions-close-over-type-parameter-multiple.rs
new file mode 100644
index 0000000..defbc5d
--- /dev/null
+++ b/src/test/ui/regions/regions-close-over-type-parameter-multiple.rs
@@ -0,0 +1,24 @@
+#![feature(box_syntax)]
+
+// Various tests where we over type parameters with multiple lifetime
+// bounds.
+
+trait SomeTrait { fn get(&self) -> isize; }
+
+fn make_object_good1<'a,'b,A:SomeTrait+'a+'b>(v: A) -> Box<SomeTrait+'a> {
+    // A outlives 'a AND 'b...
+    box v as Box<SomeTrait+'a> // ...hence this type is safe.
+}
+
+fn make_object_good2<'a,'b,A:SomeTrait+'a+'b>(v: A) -> Box<SomeTrait+'b> {
+    // A outlives 'a AND 'b...
+    box v as Box<SomeTrait+'b> // ...hence this type is safe.
+}
+
+fn make_object_bad<'a,'b,'c,A:SomeTrait+'a+'b>(v: A) -> Box<SomeTrait+'c> {
+    // A outlives 'a AND 'b...but not 'c.
+    box v as Box<SomeTrait+'a> //~ ERROR cannot infer an appropriate lifetime
+}
+
+fn main() {
+}
diff --git a/src/test/ui/regions/regions-close-over-type-parameter-multiple.stderr b/src/test/ui/regions/regions-close-over-type-parameter-multiple.stderr
new file mode 100644
index 0000000..68809eb
--- /dev/null
+++ b/src/test/ui/regions/regions-close-over-type-parameter-multiple.stderr
@@ -0,0 +1,28 @@
+error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
+  --> $DIR/regions-close-over-type-parameter-multiple.rs:20:5
+   |
+LL |     box v as Box<SomeTrait+'a>
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 18:20...
+  --> $DIR/regions-close-over-type-parameter-multiple.rs:18:20
+   |
+LL | fn make_object_bad<'a,'b,'c,A:SomeTrait+'a+'b>(v: A) -> Box<SomeTrait+'c> {
+   |                    ^^
+note: ...so that the declared lifetime parameter bounds are satisfied
+  --> $DIR/regions-close-over-type-parameter-multiple.rs:20:5
+   |
+LL |     box v as Box<SomeTrait+'a>
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: but, the lifetime must be valid for the lifetime 'c as defined on the function body at 18:26...
+  --> $DIR/regions-close-over-type-parameter-multiple.rs:18:26
+   |
+LL | fn make_object_bad<'a,'b,'c,A:SomeTrait+'a+'b>(v: A) -> Box<SomeTrait+'c> {
+   |                          ^^
+   = note: ...so that the expression is assignable:
+           expected std::boxed::Box<(dyn SomeTrait + 'c)>
+              found std::boxed::Box<dyn SomeTrait>
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0495`.
diff --git a/src/test/ui/regions/regions-close-param-into-object.rs b/src/test/ui/regions/regions-close-param-into-object.rs
new file mode 100644
index 0000000..8659074
--- /dev/null
+++ b/src/test/ui/regions/regions-close-param-into-object.rs
@@ -0,0 +1,27 @@
+trait X { fn foo(&self) {} }
+
+fn p1<T>(v: T) -> Box<X+'static>
+    where T : X
+{
+    Box::new(v) //~ ERROR parameter type `T` may not live long enough
+}
+
+fn p2<T>(v: Box<T>) -> Box<X+'static>
+    where Box<T> : X
+{
+    Box::new(v) //~ ERROR parameter type `T` may not live long enough
+}
+
+fn p3<'a,T>(v: T) -> Box<X+'a>
+    where T : X
+{
+    Box::new(v) //~ ERROR parameter type `T` may not live long enough
+}
+
+fn p4<'a,T>(v: Box<T>) -> Box<X+'a>
+    where Box<T> : X
+{
+    Box::new(v) //~ ERROR parameter type `T` may not live long enough
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-close-param-into-object.stderr b/src/test/ui/regions/regions-close-param-into-object.stderr
new file mode 100644
index 0000000..a7f0572
--- /dev/null
+++ b/src/test/ui/regions/regions-close-param-into-object.stderr
@@ -0,0 +1,64 @@
+error[E0310]: the parameter type `T` may not live long enough
+  --> $DIR/regions-close-param-into-object.rs:6:5
+   |
+LL | fn p1<T>(v: T) -> Box<X+'static>
+   |       - help: consider adding an explicit lifetime bound `T: 'static`...
+...
+LL |     Box::new(v)
+   |     ^^^^^^^^^^^
+   |
+note: ...so that the type `T` will meet its required lifetime bounds
+  --> $DIR/regions-close-param-into-object.rs:6:5
+   |
+LL |     Box::new(v)
+   |     ^^^^^^^^^^^
+
+error[E0310]: the parameter type `T` may not live long enough
+  --> $DIR/regions-close-param-into-object.rs:12:5
+   |
+LL | fn p2<T>(v: Box<T>) -> Box<X+'static>
+   |       - help: consider adding an explicit lifetime bound `T: 'static`...
+...
+LL |     Box::new(v)
+   |     ^^^^^^^^^^^
+   |
+note: ...so that the type `std::boxed::Box<T>` will meet its required lifetime bounds
+  --> $DIR/regions-close-param-into-object.rs:12:5
+   |
+LL |     Box::new(v)
+   |     ^^^^^^^^^^^
+
+error[E0309]: the parameter type `T` may not live long enough
+  --> $DIR/regions-close-param-into-object.rs:18:5
+   |
+LL | fn p3<'a,T>(v: T) -> Box<X+'a>
+   |          - help: consider adding an explicit lifetime bound `T: 'a`...
+...
+LL |     Box::new(v)
+   |     ^^^^^^^^^^^
+   |
+note: ...so that the type `T` will meet its required lifetime bounds
+  --> $DIR/regions-close-param-into-object.rs:18:5
+   |
+LL |     Box::new(v)
+   |     ^^^^^^^^^^^
+
+error[E0309]: the parameter type `T` may not live long enough
+  --> $DIR/regions-close-param-into-object.rs:24:5
+   |
+LL | fn p4<'a,T>(v: Box<T>) -> Box<X+'a>
+   |          - help: consider adding an explicit lifetime bound `T: 'a`...
+...
+LL |     Box::new(v)
+   |     ^^^^^^^^^^^
+   |
+note: ...so that the type `std::boxed::Box<T>` will meet its required lifetime bounds
+  --> $DIR/regions-close-param-into-object.rs:24:5
+   |
+LL |     Box::new(v)
+   |     ^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0309, E0310.
+For more information about an error, try `rustc --explain E0309`.
diff --git a/src/test/ui/regions/regions-creating-enums.nll.stderr b/src/test/ui/regions/regions-creating-enums.nll.stderr
new file mode 100644
index 0000000..a95d846
--- /dev/null
+++ b/src/test/ui/regions/regions-creating-enums.nll.stderr
@@ -0,0 +1,21 @@
+error[E0515]: cannot return reference to temporary value
+  --> $DIR/regions-creating-enums.rs:23:16
+   |
+LL |         return &Ast::Num((*f)(x));
+   |                ^-----------------
+   |                ||
+   |                |temporary value created here
+   |                returns a reference to data owned by the current function
+
+error[E0515]: cannot return reference to temporary value
+  --> $DIR/regions-creating-enums.rs:28:16
+   |
+LL |         return &Ast::Add(m_x, m_y);
+   |                ^------------------
+   |                ||
+   |                |temporary value created here
+   |                returns a reference to data owned by the current function
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/src/test/ui/regions/regions-creating-enums.rs b/src/test/ui/regions/regions-creating-enums.rs
new file mode 100644
index 0000000..ea8d437
--- /dev/null
+++ b/src/test/ui/regions/regions-creating-enums.rs
@@ -0,0 +1,33 @@
+enum Ast<'a> {
+    Num(usize),
+    Add(&'a Ast<'a>, &'a Ast<'a>)
+}
+
+fn build() {
+    let x = Ast::Num(3);
+    let y = Ast::Num(4);
+    let z = Ast::Add(&x, &y);
+    compute(&z);
+}
+
+fn compute(x: &Ast) -> usize {
+    match *x {
+      Ast::Num(x) => { x }
+      Ast::Add(x, y) => { compute(x) + compute(y) }
+    }
+}
+
+fn map_nums<'a,'b, F>(x: &Ast, f: &mut F) -> &'a Ast<'b> where F: FnMut(usize) -> usize {
+    match *x {
+      Ast::Num(x) => {
+        return &Ast::Num((*f)(x)); //~ ERROR borrowed value does not live long enough
+      }
+      Ast::Add(x, y) => {
+        let m_x = map_nums(x, f);
+        let m_y = map_nums(y, f);
+        return &Ast::Add(m_x, m_y);  //~ ERROR borrowed value does not live long enough
+      }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-creating-enums.stderr b/src/test/ui/regions/regions-creating-enums.stderr
new file mode 100644
index 0000000..bb11be9
--- /dev/null
+++ b/src/test/ui/regions/regions-creating-enums.stderr
@@ -0,0 +1,33 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/regions-creating-enums.rs:23:17
+   |
+LL |         return &Ast::Num((*f)(x));
+   |                 ^^^^^^^^^^^^^^^^^- temporary value only lives until here
+   |                 |
+   |                 temporary value does not live long enough
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 20:13...
+  --> $DIR/regions-creating-enums.rs:20:13
+   |
+LL | fn map_nums<'a,'b, F>(x: &Ast, f: &mut F) -> &'a Ast<'b> where F: FnMut(usize) -> usize {
+   |             ^^
+   = note: consider using a `let` binding to increase its lifetime
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/regions-creating-enums.rs:28:17
+   |
+LL |         return &Ast::Add(m_x, m_y);
+   |                 ^^^^^^^^^^^^^^^^^^- temporary value only lives until here
+   |                 |
+   |                 temporary value does not live long enough
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 20:13...
+  --> $DIR/regions-creating-enums.rs:20:13
+   |
+LL | fn map_nums<'a,'b, F>(x: &Ast, f: &mut F) -> &'a Ast<'b> where F: FnMut(usize) -> usize {
+   |             ^^
+   = note: consider using a `let` binding to increase its lifetime
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/regions/regions-creating-enums3.rs b/src/test/ui/regions/regions-creating-enums3.rs
new file mode 100644
index 0000000..3da0cb4
--- /dev/null
+++ b/src/test/ui/regions/regions-creating-enums3.rs
@@ -0,0 +1,11 @@
+enum Ast<'a> {
+    Num(usize),
+    Add(&'a Ast<'a>, &'a Ast<'a>)
+}
+
+fn mk_add_bad1<'a,'b>(x: &'a Ast<'a>, y: &'b Ast<'b>) -> Ast<'a> {
+    Ast::Add(x, y) //~ ERROR lifetime mismatch [E0623]
+}
+
+fn main() {
+}
diff --git a/src/test/ui/regions/regions-creating-enums3.stderr b/src/test/ui/regions/regions-creating-enums3.stderr
new file mode 100644
index 0000000..2fc1fc3
--- /dev/null
+++ b/src/test/ui/regions/regions-creating-enums3.stderr
@@ -0,0 +1,13 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/regions-creating-enums3.rs:7:5
+   |
+LL | fn mk_add_bad1<'a,'b>(x: &'a Ast<'a>, y: &'b Ast<'b>) -> Ast<'a> {
+   |                                          -----------     -------
+   |                                          |
+   |                                          this parameter and the return type are declared with different lifetimes...
+LL |     Ast::Add(x, y)
+   |     ^^^^^^^^^^^^^^ ...but data from `y` is returned here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/regions/regions-creating-enums4.rs b/src/test/ui/regions/regions-creating-enums4.rs
new file mode 100644
index 0000000..11d3d83
--- /dev/null
+++ b/src/test/ui/regions/regions-creating-enums4.rs
@@ -0,0 +1,11 @@
+enum Ast<'a> {
+    Num(usize),
+    Add(&'a Ast<'a>, &'a Ast<'a>)
+}
+
+fn mk_add_bad2<'a,'b>(x: &'a Ast<'a>, y: &'a Ast<'a>, z: &Ast) -> Ast<'b> {
+    Ast::Add(x, y) //~ ERROR cannot infer
+}
+
+fn main() {
+}
diff --git a/src/test/ui/regions/regions-creating-enums4.stderr b/src/test/ui/regions/regions-creating-enums4.stderr
new file mode 100644
index 0000000..4d00783
--- /dev/null
+++ b/src/test/ui/regions/regions-creating-enums4.stderr
@@ -0,0 +1,26 @@
+error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
+  --> $DIR/regions-creating-enums4.rs:7:5
+   |
+LL |     Ast::Add(x, y)
+   |     ^^^^^^^^
+   |
+note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 6:16...
+  --> $DIR/regions-creating-enums4.rs:6:16
+   |
+LL | fn mk_add_bad2<'a,'b>(x: &'a Ast<'a>, y: &'a Ast<'a>, z: &Ast) -> Ast<'b> {
+   |                ^^
+   = note: ...so that the expression is assignable:
+           expected &Ast<'_>
+              found &Ast<'a>
+note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 6:19...
+  --> $DIR/regions-creating-enums4.rs:6:19
+   |
+LL | fn mk_add_bad2<'a,'b>(x: &'a Ast<'a>, y: &'a Ast<'a>, z: &Ast) -> Ast<'b> {
+   |                   ^^
+   = note: ...so that the expression is assignable:
+           expected Ast<'b>
+              found Ast<'_>
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0495`.
diff --git a/src/test/ui/regions/regions-early-bound-error-method.rs b/src/test/ui/regions/regions-early-bound-error-method.rs
new file mode 100644
index 0000000..3242814
--- /dev/null
+++ b/src/test/ui/regions/regions-early-bound-error-method.rs
@@ -0,0 +1,26 @@
+// Tests that you can use a fn lifetime parameter as part of
+// the value for a type parameter in a bound.
+
+trait GetRef<'a> {
+    fn get(&self) -> &'a isize;
+}
+
+struct Box<'a> {
+    t: &'a isize
+}
+
+impl<'a> GetRef<'a> for Box<'a> {
+    fn get(&self) -> &'a isize {
+        self.t
+    }
+}
+
+impl<'a> Box<'a> {
+    fn or<'b,G:GetRef<'b>>(&self, g2: G) -> &'a isize {
+        g2.get()
+        //~^ ERROR E0312
+    }
+}
+
+fn main() {
+}
diff --git a/src/test/ui/regions/regions-early-bound-error-method.stderr b/src/test/ui/regions/regions-early-bound-error-method.stderr
new file mode 100644
index 0000000..7b9f2c9
--- /dev/null
+++ b/src/test/ui/regions/regions-early-bound-error-method.stderr
@@ -0,0 +1,20 @@
+error[E0312]: lifetime of reference outlives lifetime of borrowed content...
+  --> $DIR/regions-early-bound-error-method.rs:20:9
+   |
+LL |         g2.get()
+   |         ^^^^^^^^
+   |
+note: ...the reference is valid for the lifetime 'a as defined on the impl at 18:6...
+  --> $DIR/regions-early-bound-error-method.rs:18:6
+   |
+LL | impl<'a> Box<'a> {
+   |      ^^
+note: ...but the borrowed content is only valid for the lifetime 'b as defined on the method body at 19:11
+  --> $DIR/regions-early-bound-error-method.rs:19:11
+   |
+LL |     fn or<'b,G:GetRef<'b>>(&self, g2: G) -> &'a isize {
+   |           ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0312`.
diff --git a/src/test/ui/regions/regions-early-bound-error.rs b/src/test/ui/regions/regions-early-bound-error.rs
new file mode 100644
index 0000000..78dad4f
--- /dev/null
+++ b/src/test/ui/regions/regions-early-bound-error.rs
@@ -0,0 +1,24 @@
+// Tests that you can use a fn lifetime parameter as part of
+// the value for a type parameter in a bound.
+
+trait GetRef<'a, T> {
+    fn get(&self) -> &'a T;
+}
+
+struct Box<'a, T:'a> {
+    t: &'a T
+}
+
+impl<'a,T:Clone> GetRef<'a,T> for Box<'a,T> {
+    fn get(&self) -> &'a T {
+        self.t
+    }
+}
+
+fn get<'a,'b,G:GetRef<'a, isize>>(g1: G, b: &'b isize) -> &'b isize {
+    g1.get()
+    //~^ ERROR E0312
+}
+
+fn main() {
+}
diff --git a/src/test/ui/regions/regions-early-bound-error.stderr b/src/test/ui/regions/regions-early-bound-error.stderr
new file mode 100644
index 0000000..a68355b
--- /dev/null
+++ b/src/test/ui/regions/regions-early-bound-error.stderr
@@ -0,0 +1,20 @@
+error[E0312]: lifetime of reference outlives lifetime of borrowed content...
+  --> $DIR/regions-early-bound-error.rs:19:5
+   |
+LL |     g1.get()
+   |     ^^^^^^^^
+   |
+note: ...the reference is valid for the lifetime 'b as defined on the function body at 18:11...
+  --> $DIR/regions-early-bound-error.rs:18:11
+   |
+LL | fn get<'a,'b,G:GetRef<'a, isize>>(g1: G, b: &'b isize) -> &'b isize {
+   |           ^^
+note: ...but the borrowed content is only valid for the lifetime 'a as defined on the function body at 18:8
+  --> $DIR/regions-early-bound-error.rs:18:8
+   |
+LL | fn get<'a,'b,G:GetRef<'a, isize>>(g1: G, b: &'b isize) -> &'b isize {
+   |        ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0312`.
diff --git a/src/test/ui/regions/regions-enum-not-wf.rs b/src/test/ui/regions/regions-enum-not-wf.rs
new file mode 100644
index 0000000..781cdb7
--- /dev/null
+++ b/src/test/ui/regions/regions-enum-not-wf.rs
@@ -0,0 +1,40 @@
+// ignore-tidy-linelength
+
+// Various examples of structs whose fields are not well-formed.
+
+#![allow(dead_code)]
+
+trait Dummy<'a> {
+  type Out;
+}
+impl<'a, T> Dummy<'a> for T
+where T: 'a
+{
+  type Out = ();
+}
+type RequireOutlives<'a, T> = <T as Dummy<'a>>::Out;
+
+enum Ref1<'a, T> {
+    Ref1Variant1(RequireOutlives<'a, T>) //~ ERROR the parameter type `T` may not live long enough
+}
+
+enum Ref2<'a, T> {
+    Ref2Variant1,
+    Ref2Variant2(isize, RequireOutlives<'a, T>), //~ ERROR the parameter type `T` may not live long enough
+}
+
+enum RefOk<'a, T:'a> {
+    RefOkVariant1(&'a T)
+}
+
+// This is now well formed. RFC 2093
+enum RefIndirect<'a, T> {
+    RefIndirectVariant1(isize, RefOk<'a,T>)
+}
+
+enum RefDouble<'a, 'b, T> { //~ ERROR the parameter type `T` may not live long enough [E0309]
+    RefDoubleVariant1(&'a RequireOutlives<'b, T>)
+        //~^ the parameter type `T` may not live long enough [E0309]
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-enum-not-wf.stderr b/src/test/ui/regions/regions-enum-not-wf.stderr
new file mode 100644
index 0000000..8701408
--- /dev/null
+++ b/src/test/ui/regions/regions-enum-not-wf.stderr
@@ -0,0 +1,67 @@
+error[E0309]: the parameter type `T` may not live long enough
+  --> $DIR/regions-enum-not-wf.rs:18:18
+   |
+LL | enum Ref1<'a, T> {
+   |               - help: consider adding an explicit lifetime bound `T: 'a`...
+LL |     Ref1Variant1(RequireOutlives<'a, T>)
+   |                  ^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: ...so that the type `T` will meet its required lifetime bounds
+  --> $DIR/regions-enum-not-wf.rs:18:18
+   |
+LL |     Ref1Variant1(RequireOutlives<'a, T>)
+   |                  ^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0309]: the parameter type `T` may not live long enough
+  --> $DIR/regions-enum-not-wf.rs:23:25
+   |
+LL | enum Ref2<'a, T> {
+   |               - help: consider adding an explicit lifetime bound `T: 'a`...
+LL |     Ref2Variant1,
+LL |     Ref2Variant2(isize, RequireOutlives<'a, T>),
+   |                         ^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: ...so that the type `T` will meet its required lifetime bounds
+  --> $DIR/regions-enum-not-wf.rs:23:25
+   |
+LL |     Ref2Variant2(isize, RequireOutlives<'a, T>),
+   |                         ^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0309]: the parameter type `T` may not live long enough
+  --> $DIR/regions-enum-not-wf.rs:35:1
+   |
+LL |   enum RefDouble<'a, 'b, T> {
+   |   ^                      - help: consider adding an explicit lifetime bound `T: 'b`...
+   |  _|
+   | |
+LL | |     RefDoubleVariant1(&'a RequireOutlives<'b, T>)
+LL | |
+LL | | }
+   | |_^
+   |
+note: ...so that the type `T` will meet its required lifetime bounds
+  --> $DIR/regions-enum-not-wf.rs:35:1
+   |
+LL | / enum RefDouble<'a, 'b, T> {
+LL | |     RefDoubleVariant1(&'a RequireOutlives<'b, T>)
+LL | |
+LL | | }
+   | |_^
+
+error[E0309]: the parameter type `T` may not live long enough
+  --> $DIR/regions-enum-not-wf.rs:36:23
+   |
+LL | enum RefDouble<'a, 'b, T> {
+   |                        - help: consider adding an explicit lifetime bound `T: 'b`...
+LL |     RefDoubleVariant1(&'a RequireOutlives<'b, T>)
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: ...so that the type `T` will meet its required lifetime bounds
+  --> $DIR/regions-enum-not-wf.rs:36:23
+   |
+LL |     RefDoubleVariant1(&'a RequireOutlives<'b, T>)
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0309`.
diff --git a/src/test/ui/regions/regions-escape-method.rs b/src/test/ui/regions/regions-escape-method.rs
new file mode 100644
index 0000000..5127d4d
--- /dev/null
+++ b/src/test/ui/regions/regions-escape-method.rs
@@ -0,0 +1,16 @@
+// Test a method call where the parameter `B` would (illegally) be
+// inferred to a region bound in the method argument. If this program
+// were accepted, then the closure passed to `s.f` could escape its
+// argument.
+
+struct S;
+
+impl S {
+    fn f<B, F>(&self, _: F) where F: FnOnce(&i32) -> B {
+    }
+}
+
+fn main() {
+    let s = S;
+    s.f(|p| p) //~ ERROR cannot infer
+}
diff --git a/src/test/ui/regions/regions-escape-method.stderr b/src/test/ui/regions/regions-escape-method.stderr
new file mode 100644
index 0000000..b93dd0d
--- /dev/null
+++ b/src/test/ui/regions/regions-escape-method.stderr
@@ -0,0 +1,28 @@
+error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
+  --> $DIR/regions-escape-method.rs:15:13
+   |
+LL |     s.f(|p| p)
+   |             ^
+   |
+note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the body at 15:9...
+  --> $DIR/regions-escape-method.rs:15:9
+   |
+LL |     s.f(|p| p)
+   |         ^^^^^
+   = note: ...so that the expression is assignable:
+           expected &i32
+              found &i32
+note: but, the lifetime must be valid for the method call at 15:5...
+  --> $DIR/regions-escape-method.rs:15:5
+   |
+LL |     s.f(|p| p)
+   |     ^^^^^^^^^^
+note: ...so that a type/lifetime parameter is in scope here
+  --> $DIR/regions-escape-method.rs:15:5
+   |
+LL |     s.f(|p| p)
+   |     ^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0495`.
diff --git a/src/test/ui/regions/regions-escape-via-trait-or-not.rs b/src/test/ui/regions/regions-escape-via-trait-or-not.rs
new file mode 100644
index 0000000..1e08961
--- /dev/null
+++ b/src/test/ui/regions/regions-escape-via-trait-or-not.rs
@@ -0,0 +1,22 @@
+#![allow(dead_code)]
+
+trait Deref {
+    fn get(self) -> isize;
+}
+
+impl<'a> Deref for &'a isize {
+    fn get(self) -> isize {
+        *self
+    }
+}
+
+fn with<R:Deref, F>(f: F) -> isize where F: FnOnce(&isize) -> R {
+    f(&3).get()
+}
+
+fn return_it() -> isize {
+    with(|o| o) //~ ERROR cannot infer
+}
+
+fn main() {
+}
diff --git a/src/test/ui/regions/regions-escape-via-trait-or-not.stderr b/src/test/ui/regions/regions-escape-via-trait-or-not.stderr
new file mode 100644
index 0000000..a6b165e
--- /dev/null
+++ b/src/test/ui/regions/regions-escape-via-trait-or-not.stderr
@@ -0,0 +1,28 @@
+error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
+  --> $DIR/regions-escape-via-trait-or-not.rs:18:14
+   |
+LL |     with(|o| o)
+   |              ^
+   |
+note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the body at 18:10...
+  --> $DIR/regions-escape-via-trait-or-not.rs:18:10
+   |
+LL |     with(|o| o)
+   |          ^^^^^
+   = note: ...so that the expression is assignable:
+           expected &isize
+              found &isize
+note: but, the lifetime must be valid for the expression at 18:5...
+  --> $DIR/regions-escape-via-trait-or-not.rs:18:5
+   |
+LL |     with(|o| o)
+   |     ^^^^
+note: ...so type `fn([closure@$DIR/regions-escape-via-trait-or-not.rs:18:10: 18:15]) -> isize {with::<&isize, [closure@$DIR/regions-escape-via-trait-or-not.rs:18:10: 18:15]>}` of expression is valid during the expression
+  --> $DIR/regions-escape-via-trait-or-not.rs:18:5
+   |
+LL |     with(|o| o)
+   |     ^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0495`.
diff --git a/src/test/ui/regions/regions-fn-subtyping-return-static.rs b/src/test/ui/regions/regions-fn-subtyping-return-static.rs
new file mode 100644
index 0000000..fa2cc37
--- /dev/null
+++ b/src/test/ui/regions/regions-fn-subtyping-return-static.rs
@@ -0,0 +1,47 @@
+// In this fn, the type `F` is a function that takes a reference to a
+// struct and returns another reference with the same lifetime.
+//
+// Meanwhile, the bare fn `foo` takes a reference to a struct with
+// *ANY* lifetime and returns a reference with the 'static lifetime.
+// This can safely be considered to be an instance of `F` because all
+// lifetimes are sublifetimes of 'static.
+
+#![allow(dead_code)]
+#![allow(unused_variables)]
+#![allow(non_snake_case)]
+
+struct S;
+
+// Given 'cx, return 'cx
+type F = for<'cx> fn(&'cx S) -> &'cx S;
+fn want_F(f: F) { }
+
+// Given anything, return 'static
+type G = for<'cx> fn(&'cx S) -> &'static S;
+fn want_G(f: G) { }
+
+// Should meet both.
+fn foo(x: &S) -> &'static S {
+    panic!()
+}
+
+// Should meet both.
+fn bar<'a,'b>(x: &'a S) -> &'b S {
+    panic!()
+}
+
+// Meets F, but not G.
+fn baz(x: &S) -> &S {
+    panic!()
+}
+
+fn supply_F() {
+    want_F(foo);
+
+    want_F(bar); //~ ERROR mismatched types
+
+    want_F(baz);
+}
+
+pub fn main() {
+}
diff --git a/src/test/ui/regions/regions-fn-subtyping-return-static.stderr b/src/test/ui/regions/regions-fn-subtyping-return-static.stderr
new file mode 100644
index 0000000..cda5ce2
--- /dev/null
+++ b/src/test/ui/regions/regions-fn-subtyping-return-static.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/regions-fn-subtyping-return-static.rs:41:12
+   |
+LL |     want_F(bar);
+   |            ^^^ expected concrete lifetime, found bound lifetime parameter 'cx
+   |
+   = note: expected type `for<'cx> fn(&'cx S) -> &'cx S`
+              found type `for<'a> fn(&'a S) -> &S {bar::<'_>}`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/regions/regions-free-region-ordering-callee-4.rs b/src/test/ui/regions/regions-free-region-ordering-callee-4.rs
new file mode 100644
index 0000000..de58dd0
--- /dev/null
+++ b/src/test/ui/regions/regions-free-region-ordering-callee-4.rs
@@ -0,0 +1,11 @@
+// Tests that callees correctly infer an ordering between free regions
+// that appear in their parameter list.  See also
+// regions-free-region-ordering-caller.rs
+
+fn ordering4<'a, 'b, F>(a: &'a usize, b: &'b usize, x: F) where F: FnOnce(&'a &'b usize) {
+    //~^ ERROR reference has a longer lifetime than the data it references
+    // Do not infer ordering from closure argument types.
+    let z: Option<&'a &'b usize> = None;
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-free-region-ordering-callee-4.stderr b/src/test/ui/regions/regions-free-region-ordering-callee-4.stderr
new file mode 100644
index 0000000..3b8f09f
--- /dev/null
+++ b/src/test/ui/regions/regions-free-region-ordering-callee-4.stderr
@@ -0,0 +1,24 @@
+error[E0491]: in type `&'a &'b usize`, reference has a longer lifetime than the data it references
+  --> $DIR/regions-free-region-ordering-callee-4.rs:5:1
+   |
+LL | / fn ordering4<'a, 'b, F>(a: &'a usize, b: &'b usize, x: F) where F: FnOnce(&'a &'b usize) {
+LL | |
+LL | |     // Do not infer ordering from closure argument types.
+LL | |     let z: Option<&'a &'b usize> = None;
+LL | | }
+   | |_^
+   |
+note: the pointer is valid for the lifetime 'a as defined on the function body at 5:14
+  --> $DIR/regions-free-region-ordering-callee-4.rs:5:14
+   |
+LL | fn ordering4<'a, 'b, F>(a: &'a usize, b: &'b usize, x: F) where F: FnOnce(&'a &'b usize) {
+   |              ^^
+note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 5:18
+  --> $DIR/regions-free-region-ordering-callee-4.rs:5:18
+   |
+LL | fn ordering4<'a, 'b, F>(a: &'a usize, b: &'b usize, x: F) where F: FnOnce(&'a &'b usize) {
+   |                  ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0491`.
diff --git a/src/test/ui/regions/regions-free-region-ordering-callee.rs b/src/test/ui/regions/regions-free-region-ordering-callee.rs
new file mode 100644
index 0000000..ee9a977
--- /dev/null
+++ b/src/test/ui/regions/regions-free-region-ordering-callee.rs
@@ -0,0 +1,29 @@
+// Tests that callees correctly infer an ordering between free regions
+// that appear in their parameter list.  See also
+// regions-free-region-ordering-caller.rs
+
+fn ordering1<'a, 'b>(x: &'a &'b usize) -> &'a usize {
+    // It is safe to assume that 'a <= 'b due to the type of x
+    let y: &'b usize = &**x;
+    return y;
+}
+
+fn ordering2<'a, 'b>(x: &'a &'b usize, y: &'a usize) -> &'b usize {
+    // However, it is not safe to assume that 'b <= 'a
+    &*y //~ ERROR lifetime mismatch [E0623]
+}
+
+fn ordering3<'a, 'b>(x: &'a usize, y: &'b usize) -> &'a &'b usize {
+    // Do not infer an ordering from the return value.
+    let z: &'b usize = &*x;
+    //~^ ERROR lifetime mismatch [E0623]
+    panic!();
+}
+
+// see regions-free-region-ordering-callee-4.rs
+
+fn ordering5<'a, 'b>(a: &'a usize, b: &'b usize, x: Option<&'a &'b usize>) {
+    let z: Option<&'a &'b usize> = None;
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-free-region-ordering-callee.stderr b/src/test/ui/regions/regions-free-region-ordering-callee.stderr
new file mode 100644
index 0000000..4648bf0
--- /dev/null
+++ b/src/test/ui/regions/regions-free-region-ordering-callee.stderr
@@ -0,0 +1,25 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/regions-free-region-ordering-callee.rs:13:5
+   |
+LL | fn ordering2<'a, 'b>(x: &'a &'b usize, y: &'a usize) -> &'b usize {
+   |                         -------------                   ---------
+   |                         |
+   |                         this parameter and the return type are declared with different lifetimes...
+LL |     // However, it is not safe to assume that 'b <= 'a
+LL |     &*y
+   |     ^^^ ...but data from `x` is returned here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/regions-free-region-ordering-callee.rs:18:24
+   |
+LL | fn ordering3<'a, 'b>(x: &'a usize, y: &'b usize) -> &'a &'b usize {
+   |                                       ---------     -------------
+   |                                       |
+   |                                       this parameter and the return type are declared with different lifetimes...
+LL |     // Do not infer an ordering from the return value.
+LL |     let z: &'b usize = &*x;
+   |                        ^^^ ...but data from `x` is returned here
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/regions/regions-free-region-ordering-caller.ast.stderr b/src/test/ui/regions/regions-free-region-ordering-caller.ast.stderr
new file mode 100644
index 0000000..a33d358
--- /dev/null
+++ b/src/test/ui/regions/regions-free-region-ordering-caller.ast.stderr
@@ -0,0 +1,32 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/regions-free-region-ordering-caller.rs:11:12
+   |
+LL | fn call2<'a, 'b>(a: &'a usize, b: &'b usize) {
+   |                     ---------     ---------
+   |                     |
+   |                     these two types are declared with different lifetimes...
+LL |     let z: Option<&'b &'a usize> = None;
+   |            ^^^^^^^^^^^^^^^^^^^^^ ...but data from `a` flows into `b` here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/regions-free-region-ordering-caller.rs:17:12
+   |
+LL | fn call3<'a, 'b>(a: &'a usize, b: &'b usize) {
+   |                     ---------     ---------
+   |                     |
+   |                     these two types are declared with different lifetimes...
+LL |     let y: Paramd<'a> = Paramd { x: a };
+LL |     let z: Option<&'b Paramd<'a>> = None;
+   |            ^^^^^^^^^^^^^^^^^^^^^^ ...but data from `a` flows into `b` here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/regions-free-region-ordering-caller.rs:22:12
+   |
+LL | fn call4<'a, 'b>(a: &'a usize, b: &'b usize) {
+   |                     ---------     --------- these two types are declared with different lifetimes...
+LL |     let z: Option<&'a &'b usize> = None;
+   |            ^^^^^^^^^^^^^^^^^^^^^ ...but data from `b` flows into `a` here
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/regions/regions-free-region-ordering-caller.mir.stderr b/src/test/ui/regions/regions-free-region-ordering-caller.mir.stderr
new file mode 100644
index 0000000..16eda28
--- /dev/null
+++ b/src/test/ui/regions/regions-free-region-ordering-caller.mir.stderr
@@ -0,0 +1,33 @@
+error: lifetime may not live long enough
+  --> $DIR/regions-free-region-ordering-caller.rs:11:12
+   |
+LL | fn call2<'a, 'b>(a: &'a usize, b: &'b usize) {
+   |          --  -- lifetime `'b` defined here
+   |          |
+   |          lifetime `'a` defined here
+LL |     let z: Option<&'b &'a usize> = None;
+   |            ^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'b`
+
+error: lifetime may not live long enough
+  --> $DIR/regions-free-region-ordering-caller.rs:17:12
+   |
+LL | fn call3<'a, 'b>(a: &'a usize, b: &'b usize) {
+   |          --  -- lifetime `'b` defined here
+   |          |
+   |          lifetime `'a` defined here
+LL |     let y: Paramd<'a> = Paramd { x: a };
+LL |     let z: Option<&'b Paramd<'a>> = None;
+   |            ^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'b`
+
+error: lifetime may not live long enough
+  --> $DIR/regions-free-region-ordering-caller.rs:22:12
+   |
+LL | fn call4<'a, 'b>(a: &'a usize, b: &'b usize) {
+   |          --  -- lifetime `'b` defined here
+   |          |
+   |          lifetime `'a` defined here
+LL |     let z: Option<&'a &'b usize> = None;
+   |            ^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/regions/regions-free-region-ordering-caller.rs b/src/test/ui/regions/regions-free-region-ordering-caller.rs
new file mode 100644
index 0000000..621e6e7
--- /dev/null
+++ b/src/test/ui/regions/regions-free-region-ordering-caller.rs
@@ -0,0 +1,26 @@
+// Test various ways to construct a pointer with a longer lifetime
+// than the thing it points at and ensure that they result in
+// errors. See also regions-free-region-ordering-callee.rs
+
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+struct Paramd<'a> { x: &'a usize }
+
+fn call2<'a, 'b>(a: &'a usize, b: &'b usize) {
+    let z: Option<&'b &'a usize> = None;//[ast]~ ERROR E0623
+    //[mir]~^ ERROR lifetime may not live long enough
+}
+
+fn call3<'a, 'b>(a: &'a usize, b: &'b usize) {
+    let y: Paramd<'a> = Paramd { x: a };
+    let z: Option<&'b Paramd<'a>> = None;//[ast]~ ERROR E0623
+    //[mir]~^ ERROR lifetime may not live long enough
+}
+
+fn call4<'a, 'b>(a: &'a usize, b: &'b usize) {
+    let z: Option<&'a &'b usize> = None;//[ast]~ ERROR E0623
+    //[mir]~^ ERROR lifetime may not live long enough
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-free-region-ordering-caller1.nll.stderr b/src/test/ui/regions/regions-free-region-ordering-caller1.nll.stderr
new file mode 100644
index 0000000..539343a
--- /dev/null
+++ b/src/test/ui/regions/regions-free-region-ordering-caller1.nll.stderr
@@ -0,0 +1,32 @@
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/regions-free-region-ordering-caller1.rs:9:27
+   |
+LL | fn call1<'a>(x: &'a usize) {
+   |          -- lifetime `'a` defined here
+...
+LL |     let z: &'a & usize = &(&y);
+   |            -----------    ^^^^ creates a temporary which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'a`
+...
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error[E0597]: `y` does not live long enough
+  --> $DIR/regions-free-region-ordering-caller1.rs:9:27
+   |
+LL | fn call1<'a>(x: &'a usize) {
+   |          -- lifetime `'a` defined here
+...
+LL |     let z: &'a & usize = &(&y);
+   |            -----------    ^^^^ borrowed value does not live long enough
+   |            |
+   |            type annotation requires that `y` is borrowed for `'a`
+...
+LL | }
+   | - `y` dropped here while still borrowed
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0597, E0716.
+For more information about an error, try `rustc --explain E0597`.
diff --git a/src/test/ui/regions/regions-free-region-ordering-caller1.rs b/src/test/ui/regions/regions-free-region-ordering-caller1.rs
new file mode 100644
index 0000000..d9251c0
--- /dev/null
+++ b/src/test/ui/regions/regions-free-region-ordering-caller1.rs
@@ -0,0 +1,14 @@
+// Test various ways to construct a pointer with a longer lifetime
+// than the thing it points at and ensure that they result in
+// errors. See also regions-free-region-ordering-callee.rs
+
+fn call1<'a>(x: &'a usize) {
+    // Test that creating a pointer like
+    // &'a &'z usize requires that 'a <= 'z:
+    let y: usize = 3;
+    let z: &'a & usize = &(&y);
+    //~^ ERROR borrowed value does not live long enough
+    //~^^ ERROR `y` does not live long enough
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-free-region-ordering-caller1.stderr b/src/test/ui/regions/regions-free-region-ordering-caller1.stderr
new file mode 100644
index 0000000..08aaa35
--- /dev/null
+++ b/src/test/ui/regions/regions-free-region-ordering-caller1.stderr
@@ -0,0 +1,33 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/regions-free-region-ordering-caller1.rs:9:27
+   |
+LL |     let z: &'a & usize = &(&y);
+   |                           ^^^^ temporary value does not live long enough
+...
+LL | }
+   | - temporary value only lives until here
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 5:10...
+  --> $DIR/regions-free-region-ordering-caller1.rs:5:10
+   |
+LL | fn call1<'a>(x: &'a usize) {
+   |          ^^
+
+error[E0597]: `y` does not live long enough
+  --> $DIR/regions-free-region-ordering-caller1.rs:9:29
+   |
+LL |     let z: &'a & usize = &(&y);
+   |                             ^ borrowed value does not live long enough
+...
+LL | }
+   | - borrowed value only lives until here
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 5:10...
+  --> $DIR/regions-free-region-ordering-caller1.rs:5:10
+   |
+LL | fn call1<'a>(x: &'a usize) {
+   |          ^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/regions/regions-free-region-ordering-incorrect.rs b/src/test/ui/regions/regions-free-region-ordering-incorrect.rs
new file mode 100644
index 0000000..65e3f52
--- /dev/null
+++ b/src/test/ui/regions/regions-free-region-ordering-incorrect.rs
@@ -0,0 +1,22 @@
+// Test that free regions ordering only goes one way. That is,
+// we have `&'a Node<'b, T>`, which implies that `'a <= 'b`,
+// but not `'b <= 'a`. Hence, returning `&self.val` (which has lifetime
+// `'a`) where `'b` is expected yields an error.
+//
+// This test began its life as a test for issue #4325.
+
+struct Node<'b, T: 'b> {
+    val: T,
+    next: Option<&'b Node<'b, T>>
+}
+
+impl<'b, T> Node<'b, T> {
+    fn get<'a>(&'a self) -> &'b T {
+        match self.next {
+            Some(ref next) => next.get(),
+            None => &self.val //~ ERROR cannot infer
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-free-region-ordering-incorrect.stderr b/src/test/ui/regions/regions-free-region-ordering-incorrect.stderr
new file mode 100644
index 0000000..676e96a
--- /dev/null
+++ b/src/test/ui/regions/regions-free-region-ordering-incorrect.stderr
@@ -0,0 +1,33 @@
+error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
+  --> $DIR/regions-free-region-ordering-incorrect.rs:17:21
+   |
+LL |             None => &self.val
+   |                     ^^^^^^^^^
+   |
+note: first, the lifetime cannot outlive the lifetime 'a as defined on the method body at 14:12...
+  --> $DIR/regions-free-region-ordering-incorrect.rs:14:12
+   |
+LL |     fn get<'a>(&'a self) -> &'b T {
+   |            ^^
+note: ...so that reference does not outlive borrowed content
+  --> $DIR/regions-free-region-ordering-incorrect.rs:17:21
+   |
+LL |             None => &self.val
+   |                     ^^^^^^^^^
+note: but, the lifetime must be valid for the lifetime 'b as defined on the impl at 13:6...
+  --> $DIR/regions-free-region-ordering-incorrect.rs:13:6
+   |
+LL | impl<'b, T> Node<'b, T> {
+   |      ^^
+note: ...so that reference does not outlive borrowed content
+  --> $DIR/regions-free-region-ordering-incorrect.rs:15:9
+   |
+LL | /         match self.next {
+LL | |             Some(ref next) => next.get(),
+LL | |             None => &self.val
+LL | |         }
+   | |_________^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0495`.
diff --git a/src/test/ui/regions/regions-glb-free-free.rs b/src/test/ui/regions/regions-glb-free-free.rs
new file mode 100644
index 0000000..0370a51
--- /dev/null
+++ b/src/test/ui/regions/regions-glb-free-free.rs
@@ -0,0 +1,29 @@
+mod argparse {
+    pub struct Flag<'a> {
+        name: &'a str,
+        pub desc: &'a str,
+        max_count: usize,
+        value: usize
+    }
+
+    pub fn flag<'r>(name: &'r str, desc: &'r str) -> Flag<'r> {
+        Flag { name: name, desc: desc, max_count: 1, value: 0 }
+    }
+
+    impl<'a> Flag<'a> {
+        pub fn set_desc(self, s: &str) -> Flag<'a> {
+            Flag { //~ ERROR explicit lifetime required in the type of `s` [E0621]
+                name: self.name,
+                desc: s,
+                max_count: self.max_count,
+                value: self.value
+            }
+        }
+    }
+}
+
+fn main () {
+    let f : argparse::Flag = argparse::flag("flag", "My flag");
+    let updated_flag = f.set_desc("My new flag");
+    assert_eq!(updated_flag.desc, "My new flag");
+}
diff --git a/src/test/ui/regions/regions-glb-free-free.stderr b/src/test/ui/regions/regions-glb-free-free.stderr
new file mode 100644
index 0000000..575037a
--- /dev/null
+++ b/src/test/ui/regions/regions-glb-free-free.stderr
@@ -0,0 +1,16 @@
+error[E0621]: explicit lifetime required in the type of `s`
+  --> $DIR/regions-glb-free-free.rs:15:13
+   |
+LL |           pub fn set_desc(self, s: &str) -> Flag<'a> {
+   |                                    ---- help: add explicit lifetime `'a` to the type of `s`: `&'a str`
+LL | /             Flag {
+LL | |                 name: self.name,
+LL | |                 desc: s,
+LL | |                 max_count: self.max_count,
+LL | |                 value: self.value
+LL | |             }
+   | |_____________^ lifetime `'a` required
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/regions/regions-implied-bounds-projection-gap-1.rs b/src/test/ui/regions/regions-implied-bounds-projection-gap-1.rs
new file mode 100644
index 0000000..38fc9c4
--- /dev/null
+++ b/src/test/ui/regions/regions-implied-bounds-projection-gap-1.rs
@@ -0,0 +1,30 @@
+// Illustrates the "projection gap": in this test, even though we know
+// that `T::Foo: 'x`, that does not tell us that `T: 'x`, because
+// there might be other ways for the caller of `func` to show that
+// `T::Foo: 'x` holds (e.g., where-clause).
+
+trait Trait1<'x> {
+    type Foo;
+}
+
+// calling this fn should trigger a check that the type argument
+// supplied is well-formed.
+fn wf<T>() { }
+
+fn func<'x, T:Trait1<'x>>(t: &'x T::Foo)
+{
+    wf::<&'x T>();
+    //~^ ERROR the parameter type `T` may not live long enough
+}
+
+fn caller2<'x, T:Trait1<'x>>(t: &'x T)
+{
+    wf::<&'x T::Foo>(); // OK
+}
+
+fn caller3<'x, T:Trait1<'x>>(t: &'x T::Foo)
+{
+    wf::<&'x T::Foo>(); // OK
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-implied-bounds-projection-gap-1.stderr b/src/test/ui/regions/regions-implied-bounds-projection-gap-1.stderr
new file mode 100644
index 0000000..7fbc162
--- /dev/null
+++ b/src/test/ui/regions/regions-implied-bounds-projection-gap-1.stderr
@@ -0,0 +1,18 @@
+error[E0309]: the parameter type `T` may not live long enough
+  --> $DIR/regions-implied-bounds-projection-gap-1.rs:16:10
+   |
+LL | fn func<'x, T:Trait1<'x>>(t: &'x T::Foo)
+   |             -- help: consider adding an explicit lifetime bound `T: 'x`...
+LL | {
+LL |     wf::<&'x T>();
+   |          ^^^^^
+   |
+note: ...so that the reference type `&'x T` does not outlive the data it points at
+  --> $DIR/regions-implied-bounds-projection-gap-1.rs:16:10
+   |
+LL |     wf::<&'x T>();
+   |          ^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0309`.
diff --git a/src/test/ui/regions/regions-implied-bounds-projection-gap-2.rs b/src/test/ui/regions/regions-implied-bounds-projection-gap-2.rs
new file mode 100644
index 0000000..d407bee
--- /dev/null
+++ b/src/test/ui/regions/regions-implied-bounds-projection-gap-2.rs
@@ -0,0 +1,23 @@
+// Along with the other tests in this series, illustrates the
+// "projection gap": in this test, we know that `T: 'x`, and that is
+// enough to conclude that `T::Foo: 'x`.
+
+// compile-pass
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+trait Trait1<'x> {
+    type Foo;
+}
+
+// calling this fn should trigger a check that the type argument
+// supplied is well-formed.
+fn wf<T>() { }
+
+fn func<'x, T:Trait1<'x>>(t: &'x T)
+{
+    wf::<&'x T::Foo>();
+}
+
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-implied-bounds-projection-gap-3.rs b/src/test/ui/regions/regions-implied-bounds-projection-gap-3.rs
new file mode 100644
index 0000000..c19fa98
--- /dev/null
+++ b/src/test/ui/regions/regions-implied-bounds-projection-gap-3.rs
@@ -0,0 +1,23 @@
+// Along with the other tests in this series, illustrates the
+// "projection gap": in this test, we know that `T::Foo: 'x`, and that
+// is (naturally) enough to conclude that `T::Foo: 'x`.
+
+// compile-pass
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+trait Trait1<'x> {
+    type Foo;
+}
+
+// calling this fn should trigger a check that the type argument
+// supplied is well-formed.
+fn wf<T>() { }
+
+fn func<'x, T:Trait1<'x>>(t: &'x T::Foo)
+{
+    wf::<&'x T::Foo>();
+}
+
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-implied-bounds-projection-gap-4.rs b/src/test/ui/regions/regions-implied-bounds-projection-gap-4.rs
new file mode 100644
index 0000000..7a19d17
--- /dev/null
+++ b/src/test/ui/regions/regions-implied-bounds-projection-gap-4.rs
@@ -0,0 +1,23 @@
+// Along with the other tests in this series, illustrates the
+// "projection gap": in this test, we know that `T: 'x`, and that
+// is (naturally) enough to conclude that `T: 'x`.
+
+// compile-pass
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+trait Trait1<'x> {
+    type Foo;
+}
+
+// calling this fn should trigger a check that the type argument
+// supplied is well-formed.
+fn wf<T>() { }
+
+fn func<'x, T:Trait1<'x>>(t: &'x T)
+{
+    wf::<&'x T>();
+}
+
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.rs b/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.rs
new file mode 100644
index 0000000..7e04b67
--- /dev/null
+++ b/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.rs
@@ -0,0 +1,26 @@
+// The "projection gap" is particularly "fun" around higher-ranked
+// projections.  This is because the current code is hard-coded to say
+// that a projection that contains escaping regions, like `<T as
+// Trait2<'y, 'z>>::Foo` where `'z` is bound, can only be found to
+// outlive a region if all components that appear free (`'y`, where)
+// outlive that region. However, we DON'T add those components to the
+// implied bounds set, but rather we treat projections with escaping
+// regions as opaque entities, just like projections without escaping
+// regions.
+
+trait Trait1<T> { }
+
+trait Trait2<'a, 'b> {
+    type Foo;
+}
+
+// As a side-effect of the conservative process above, the type of
+// this argument `t` is not automatically considered well-formed,
+// since for it to be WF, we would need to know that `'y: 'x`, but we
+// do not infer that.
+fn callee<'x, 'y, T>(t: &'x for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
+    //~^ ERROR reference has a longer lifetime than the data it references
+{
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr b/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr
new file mode 100644
index 0000000..ca86eb7
--- /dev/null
+++ b/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr
@@ -0,0 +1,23 @@
+error[E0491]: in type `&'x (dyn for<'z> Trait1<<T as Trait2<'y, 'z>>::Foo> + 'x)`, reference has a longer lifetime than the data it references
+  --> $DIR/regions-implied-bounds-projection-gap-hr-1.rs:21:1
+   |
+LL | / fn callee<'x, 'y, T>(t: &'x for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
+LL | |
+LL | | {
+LL | | }
+   | |_^
+   |
+note: the pointer is valid for the lifetime 'x as defined on the function body at 21:11
+  --> $DIR/regions-implied-bounds-projection-gap-hr-1.rs:21:11
+   |
+LL | fn callee<'x, 'y, T>(t: &'x for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
+   |           ^^
+note: but the referenced data is only valid for the lifetime 'y as defined on the function body at 21:15
+  --> $DIR/regions-implied-bounds-projection-gap-hr-1.rs:21:15
+   |
+LL | fn callee<'x, 'y, T>(t: &'x for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
+   |               ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0491`.
diff --git a/src/test/ui/regions/regions-in-enums-anon.rs b/src/test/ui/regions/regions-in-enums-anon.rs
new file mode 100644
index 0000000..da65cb7
--- /dev/null
+++ b/src/test/ui/regions/regions-in-enums-anon.rs
@@ -0,0 +1,7 @@
+// Test that anonymous lifetimes are not permitted in enum declarations
+
+enum Foo {
+    Bar(&isize) //~ ERROR missing lifetime specifier
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-in-enums-anon.stderr b/src/test/ui/regions/regions-in-enums-anon.stderr
new file mode 100644
index 0000000..ae06e76
--- /dev/null
+++ b/src/test/ui/regions/regions-in-enums-anon.stderr
@@ -0,0 +1,9 @@
+error[E0106]: missing lifetime specifier
+  --> $DIR/regions-in-enums-anon.rs:4:9
+   |
+LL |     Bar(&isize)
+   |         ^ expected lifetime parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0106`.
diff --git a/src/test/ui/regions/regions-in-enums.rs b/src/test/ui/regions/regions-in-enums.rs
new file mode 100644
index 0000000..8cf553a
--- /dev/null
+++ b/src/test/ui/regions/regions-in-enums.rs
@@ -0,0 +1,20 @@
+// Test that lifetimes must be declared for use on enums.
+// See also regions-undeclared.rs
+
+enum Yes0<'lt> {
+    X3(&'lt usize)
+}
+
+enum Yes1<'a> {
+    X4(&'a usize)
+}
+
+enum No0 {
+    X5(&'foo usize) //~ ERROR use of undeclared lifetime name `'foo`
+}
+
+enum No1 {
+    X6(&'a usize) //~ ERROR use of undeclared lifetime name `'a`
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-in-enums.stderr b/src/test/ui/regions/regions-in-enums.stderr
new file mode 100644
index 0000000..cfed9fe
--- /dev/null
+++ b/src/test/ui/regions/regions-in-enums.stderr
@@ -0,0 +1,15 @@
+error[E0261]: use of undeclared lifetime name `'foo`
+  --> $DIR/regions-in-enums.rs:13:9
+   |
+LL |     X5(&'foo usize)
+   |         ^^^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/regions-in-enums.rs:17:9
+   |
+LL |     X6(&'a usize)
+   |         ^^ undeclared lifetime
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0261`.
diff --git a/src/test/ui/regions/regions-in-structs-anon.rs b/src/test/ui/regions/regions-in-structs-anon.rs
new file mode 100644
index 0000000..7cb2ce0
--- /dev/null
+++ b/src/test/ui/regions/regions-in-structs-anon.rs
@@ -0,0 +1,7 @@
+// Test that anonymous lifetimes are not permitted in struct declarations
+
+struct Foo {
+    x: &isize //~ ERROR missing lifetime specifier
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-in-structs-anon.stderr b/src/test/ui/regions/regions-in-structs-anon.stderr
new file mode 100644
index 0000000..a1d4ebb
--- /dev/null
+++ b/src/test/ui/regions/regions-in-structs-anon.stderr
@@ -0,0 +1,9 @@
+error[E0106]: missing lifetime specifier
+  --> $DIR/regions-in-structs-anon.rs:4:8
+   |
+LL |     x: &isize
+   |        ^ expected lifetime parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0106`.
diff --git a/src/test/ui/regions/regions-in-structs.rs b/src/test/ui/regions/regions-in-structs.rs
new file mode 100644
index 0000000..71f718b
--- /dev/null
+++ b/src/test/ui/regions/regions-in-structs.rs
@@ -0,0 +1,15 @@
+struct Yes1<'a> {
+  x: &'a usize,
+}
+
+struct Yes2<'a> {
+  x: &'a usize,
+}
+
+struct StructDecl {
+    a: &'a isize, //~ ERROR use of undeclared lifetime name `'a`
+    b: &'a isize, //~ ERROR use of undeclared lifetime name `'a`
+}
+
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-in-structs.stderr b/src/test/ui/regions/regions-in-structs.stderr
new file mode 100644
index 0000000..8314942
--- /dev/null
+++ b/src/test/ui/regions/regions-in-structs.stderr
@@ -0,0 +1,15 @@
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/regions-in-structs.rs:10:9
+   |
+LL |     a: &'a isize,
+   |         ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/regions-in-structs.rs:11:9
+   |
+LL |     b: &'a isize,
+   |         ^^ undeclared lifetime
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0261`.
diff --git a/src/test/ui/regions/regions-infer-at-fn-not-param.rs b/src/test/ui/regions/regions-infer-at-fn-not-param.rs
new file mode 100644
index 0000000..0fd734d
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-at-fn-not-param.rs
@@ -0,0 +1,19 @@
+struct Parameterized1<'a> {
+    g: Box<FnMut() + 'a>
+}
+
+struct NotParameterized1 {
+    g: Box<FnMut() + 'static>
+}
+
+struct NotParameterized2 {
+    g: Box<FnMut() + 'static>
+}
+
+fn take1<'a>(p: Parameterized1) -> Parameterized1<'a> { p }
+//~^ ERROR explicit lifetime required in the type of `p`
+
+fn take3(p: NotParameterized1) -> NotParameterized1 { p }
+fn take4(p: NotParameterized2) -> NotParameterized2 { p }
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-infer-at-fn-not-param.stderr b/src/test/ui/regions/regions-infer-at-fn-not-param.stderr
new file mode 100644
index 0000000..8cfc44f
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-at-fn-not-param.stderr
@@ -0,0 +1,11 @@
+error[E0621]: explicit lifetime required in the type of `p`
+  --> $DIR/regions-infer-at-fn-not-param.rs:13:57
+   |
+LL | fn take1<'a>(p: Parameterized1) -> Parameterized1<'a> { p }
+   |                 --------------                          ^ lifetime `'a` required
+   |                 |
+   |                 help: add explicit lifetime `'a` to the type of `p`: `Parameterized1<'a>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/regions/regions-infer-borrow-scope-too-big.nll.stderr b/src/test/ui/regions/regions-infer-borrow-scope-too-big.nll.stderr
new file mode 100644
index 0000000..2c7a6e8
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-borrow-scope-too-big.nll.stderr
@@ -0,0 +1,12 @@
+error[E0515]: cannot return value referencing local data `*p`
+  --> $DIR/regions-infer-borrow-scope-too-big.rs:13:12
+   |
+LL |     let xc = x_coord(&*p);
+   |                      --- `*p` is borrowed here
+LL |     assert_eq!(*xc, 3);
+LL |     return xc;
+   |            ^^ returns a value referencing data owned by the current function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/src/test/ui/regions/regions-infer-borrow-scope-too-big.rs b/src/test/ui/regions/regions-infer-borrow-scope-too-big.rs
new file mode 100644
index 0000000..3bf1c67
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-borrow-scope-too-big.rs
@@ -0,0 +1,16 @@
+struct Point {
+    x: isize,
+    y: isize,
+}
+
+fn x_coord<'r>(p: &'r Point) -> &'r isize {
+    return &p.x;
+}
+
+fn foo<'a>(p: Box<Point>) -> &'a isize {
+    let xc = x_coord(&*p); //~ ERROR `*p` does not live long enough
+    assert_eq!(*xc, 3);
+    return xc;
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-infer-borrow-scope-too-big.stderr b/src/test/ui/regions/regions-infer-borrow-scope-too-big.stderr
new file mode 100644
index 0000000..ed4bc15
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-borrow-scope-too-big.stderr
@@ -0,0 +1,18 @@
+error[E0597]: `*p` does not live long enough
+  --> $DIR/regions-infer-borrow-scope-too-big.rs:11:23
+   |
+LL |     let xc = x_coord(&*p);
+   |                       ^^ borrowed value does not live long enough
+...
+LL | }
+   | - borrowed value only lives until here
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 10:8...
+  --> $DIR/regions-infer-borrow-scope-too-big.rs:10:8
+   |
+LL | fn foo<'a>(p: Box<Point>) -> &'a isize {
+   |        ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/regions/regions-infer-bound-from-trait-self.rs b/src/test/ui/regions/regions-infer-bound-from-trait-self.rs
new file mode 100644
index 0000000..d15bfff
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-bound-from-trait-self.rs
@@ -0,0 +1,51 @@
+// Test that we can derive lifetime bounds on `Self` from trait
+// inheritance.
+
+trait Static : 'static { }
+
+trait Is<'a> : 'a { }
+
+struct Inv<'a> {
+    x: Option<&'a mut &'a isize>
+}
+
+fn check_bound<'a,A:'a>(x: Inv<'a>, a: A) { }
+
+// In these case, `Self` inherits `'static`.
+
+trait InheritsFromStatic : Sized + 'static {
+    fn foo1<'a>(self, x: Inv<'a>) {
+        check_bound(x, self)
+    }
+}
+trait InheritsFromStaticIndirectly : Sized + Static {
+    fn foo1<'a>(self, x: Inv<'a>) {
+        check_bound(x, self)
+    }
+}
+
+
+// In these case, `Self` inherits `'a`.
+
+trait InheritsFromIs<'a> : Sized + 'a {
+    fn foo(self, x: Inv<'a>) {
+        check_bound(x, self)
+    }
+}
+
+trait InheritsFromIsIndirectly<'a> : Sized + Is<'a> {
+    fn foo(self, x: Inv<'a>) {
+        check_bound(x, self)
+    }
+}
+
+// In this case, `Self` inherits nothing.
+
+trait InheritsFromNothing<'a> : Sized {
+    fn foo(self, x: Inv<'a>) {
+        check_bound(x, self)
+            //~^ ERROR parameter type `Self` may not live long enough
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-infer-bound-from-trait-self.stderr b/src/test/ui/regions/regions-infer-bound-from-trait-self.stderr
new file mode 100644
index 0000000..bcdadd7
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-bound-from-trait-self.stderr
@@ -0,0 +1,16 @@
+error[E0309]: the parameter type `Self` may not live long enough
+  --> $DIR/regions-infer-bound-from-trait-self.rs:46:9
+   |
+LL |         check_bound(x, self)
+   |         ^^^^^^^^^^^
+   |
+   = help: consider adding an explicit lifetime bound `Self: 'a`...
+note: ...so that the type `Self` will meet its required lifetime bounds
+  --> $DIR/regions-infer-bound-from-trait-self.rs:46:9
+   |
+LL |         check_bound(x, self)
+   |         ^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0309`.
diff --git a/src/test/ui/regions/regions-infer-bound-from-trait.rs b/src/test/ui/regions/regions-infer-bound-from-trait.rs
new file mode 100644
index 0000000..6104521
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-bound-from-trait.rs
@@ -0,0 +1,40 @@
+// Test that we can derive lifetime bounds on type parameters
+// from trait inheritance.
+
+trait Static : 'static { }
+
+trait Is<'a> : 'a { }
+
+struct Inv<'a> {
+    x: Option<&'a mut &'a isize>
+}
+
+fn check_bound<'a,A:'a>(x: Inv<'a>, a: A) { }
+
+// In all of these cases, we can derive a bound for A that is longer
+// than 'a based on the trait bound of A:
+
+fn foo1<'a,A:Static>(x: Inv<'a>, a: A) {
+    check_bound(x, a)
+}
+
+fn foo2<'a,A:Static>(x: Inv<'static>, a: A) {
+    check_bound(x, a)
+}
+
+fn foo3<'a,A:Is<'a>>(x: Inv<'a>, a: A) {
+    check_bound(x, a)
+}
+
+// In these cases, there is no trait bound, so we cannot derive any
+// bound for A and we get an error:
+
+fn bar1<'a,A>(x: Inv<'a>, a: A) {
+    check_bound(x, a) //~ ERROR parameter type `A` may not live long enough
+}
+
+fn bar2<'a,'b,A:Is<'b>>(x: Inv<'a>, y: Inv<'b>, a: A) {
+    check_bound(x, a) //~ ERROR parameter type `A` may not live long enough
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-infer-bound-from-trait.stderr b/src/test/ui/regions/regions-infer-bound-from-trait.stderr
new file mode 100644
index 0000000..382d932
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-bound-from-trait.stderr
@@ -0,0 +1,31 @@
+error[E0309]: the parameter type `A` may not live long enough
+  --> $DIR/regions-infer-bound-from-trait.rs:33:5
+   |
+LL | fn bar1<'a,A>(x: Inv<'a>, a: A) {
+   |            - help: consider adding an explicit lifetime bound `A: 'a`...
+LL |     check_bound(x, a)
+   |     ^^^^^^^^^^^
+   |
+note: ...so that the type `A` will meet its required lifetime bounds
+  --> $DIR/regions-infer-bound-from-trait.rs:33:5
+   |
+LL |     check_bound(x, a)
+   |     ^^^^^^^^^^^
+
+error[E0309]: the parameter type `A` may not live long enough
+  --> $DIR/regions-infer-bound-from-trait.rs:37:5
+   |
+LL | fn bar2<'a,'b,A:Is<'b>>(x: Inv<'a>, y: Inv<'b>, a: A) {
+   |               -- help: consider adding an explicit lifetime bound `A: 'a`...
+LL |     check_bound(x, a)
+   |     ^^^^^^^^^^^
+   |
+note: ...so that the type `A` will meet its required lifetime bounds
+  --> $DIR/regions-infer-bound-from-trait.rs:37:5
+   |
+LL |     check_bound(x, a)
+   |     ^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0309`.
diff --git a/src/test/ui/regions/regions-infer-call-3.rs b/src/test/ui/regions/regions-infer-call-3.rs
new file mode 100644
index 0000000..a76fccb
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-call-3.rs
@@ -0,0 +1,14 @@
+fn select<'r>(x: &'r isize, y: &'r isize) -> &'r isize { x }
+
+fn with<T, F>(f: F) -> T where F: FnOnce(&isize) -> T {
+    f(&20)
+}
+
+fn manip<'a>(x: &'a isize) -> isize {
+    let z = with(|y| { select(x, y) });
+    //~^ ERROR cannot infer
+    *z
+}
+
+fn main() {
+}
diff --git a/src/test/ui/regions/regions-infer-call-3.stderr b/src/test/ui/regions/regions-infer-call-3.stderr
new file mode 100644
index 0000000..1d6dbdb
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-call-3.stderr
@@ -0,0 +1,30 @@
+error[E0495]: cannot infer an appropriate lifetime for lifetime parameter 'r in function call due to conflicting requirements
+  --> $DIR/regions-infer-call-3.rs:8:24
+   |
+LL |     let z = with(|y| { select(x, y) });
+   |                        ^^^^^^^^^^^^
+   |
+note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the body at 8:18...
+  --> $DIR/regions-infer-call-3.rs:8:18
+   |
+LL |     let z = with(|y| { select(x, y) });
+   |                  ^^^^^^^^^^^^^^^^^^^^
+note: ...so that reference does not outlive borrowed content
+  --> $DIR/regions-infer-call-3.rs:8:34
+   |
+LL |     let z = with(|y| { select(x, y) });
+   |                                  ^
+note: but, the lifetime must be valid for the call at 8:13...
+  --> $DIR/regions-infer-call-3.rs:8:13
+   |
+LL |     let z = with(|y| { select(x, y) });
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...so type `&isize` of expression is valid during the expression
+  --> $DIR/regions-infer-call-3.rs:8:13
+   |
+LL |     let z = with(|y| { select(x, y) });
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0495`.
diff --git a/src/test/ui/regions/regions-infer-contravariance-due-to-decl.rs b/src/test/ui/regions/regions-infer-contravariance-due-to-decl.rs
new file mode 100644
index 0000000..8416138
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-contravariance-due-to-decl.rs
@@ -0,0 +1,28 @@
+// Test that a type which is contravariant with respect to its region
+// parameter yields an error when used in a covariant way.
+//
+// Note: see variance-regions-*.rs for the tests that check that the
+// variance inference works in the first place.
+
+use std::marker;
+
+// This is contravariant with respect to 'a, meaning that
+// Contravariant<'foo> <: Contravariant<'static> because
+// 'foo <= 'static
+struct Contravariant<'a> {
+    marker: marker::PhantomData<&'a()>
+}
+
+fn use_<'short,'long>(c: Contravariant<'short>,
+                      s: &'short isize,
+                      l: &'long isize,
+                      _where:Option<&'short &'long ()>) {
+
+    // Test whether Contravariant<'short> <: Contravariant<'long>.  Since
+    // 'short <= 'long, this would be true if the Contravariant type were
+    // covariant with respect to its parameter 'a.
+
+    let _: Contravariant<'long> = c; //~ ERROR E0623
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-infer-contravariance-due-to-decl.stderr b/src/test/ui/regions/regions-infer-contravariance-due-to-decl.stderr
new file mode 100644
index 0000000..f3a0358
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-contravariance-due-to-decl.stderr
@@ -0,0 +1,15 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/regions-infer-contravariance-due-to-decl.rs:25:35
+   |
+LL | fn use_<'short,'long>(c: Contravariant<'short>,
+   |                          --------------------- these two types are declared with different lifetimes...
+LL |                       s: &'short isize,
+LL |                       l: &'long isize,
+   |                          ------------
+...
+LL |     let _: Contravariant<'long> = c;
+   |                                   ^ ...but data from `c` flows into `l` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/regions/regions-infer-covariance-due-to-decl.rs b/src/test/ui/regions/regions-infer-covariance-due-to-decl.rs
new file mode 100644
index 0000000..b507920
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-covariance-due-to-decl.rs
@@ -0,0 +1,25 @@
+// Test that a type which is covariant with respect to its region
+// parameter yields an error when used in a contravariant way.
+//
+// Note: see variance-regions-*.rs for the tests that check that the
+// variance inference works in the first place.
+
+use std::marker;
+
+struct Covariant<'a> {
+    marker: marker::PhantomData<fn(&'a ())>
+}
+
+fn use_<'short,'long>(c: Covariant<'long>,
+                      s: &'short isize,
+                      l: &'long isize,
+                      _where:Option<&'short &'long ()>) {
+
+    // Test whether Covariant<'long> <: Covariant<'short>.  Since
+    // 'short <= 'long, this would be true if the Covariant type were
+    // contravariant with respect to its parameter 'a.
+
+    let _: Covariant<'short> = c; //~ ERROR E0623
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-infer-covariance-due-to-decl.stderr b/src/test/ui/regions/regions-infer-covariance-due-to-decl.stderr
new file mode 100644
index 0000000..c3e2075
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-covariance-due-to-decl.stderr
@@ -0,0 +1,14 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/regions-infer-covariance-due-to-decl.rs:22:32
+   |
+LL | fn use_<'short,'long>(c: Covariant<'long>,
+   |                          ----------------
+LL |                       s: &'short isize,
+   |                          ------------- these two types are declared with different lifetimes...
+...
+LL |     let _: Covariant<'short> = c;
+   |                                ^ ...but data from `s` flows into `c` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/regions/regions-infer-invariance-due-to-decl.rs b/src/test/ui/regions/regions-infer-invariance-due-to-decl.rs
new file mode 100644
index 0000000..e0fa904
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-invariance-due-to-decl.rs
@@ -0,0 +1,16 @@
+use std::marker;
+
+struct Invariant<'a> {
+    marker: marker::PhantomData<*mut &'a()>
+}
+
+fn to_same_lifetime<'r>(b_isize: Invariant<'r>) {
+    let bj: Invariant<'r> = b_isize;
+}
+
+fn to_longer_lifetime<'r>(b_isize: Invariant<'r>) -> Invariant<'static> {
+    b_isize //~ ERROR mismatched types
+}
+
+fn main() {
+}
diff --git a/src/test/ui/regions/regions-infer-invariance-due-to-decl.stderr b/src/test/ui/regions/regions-infer-invariance-due-to-decl.stderr
new file mode 100644
index 0000000..d31ed3e
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-invariance-due-to-decl.stderr
@@ -0,0 +1,18 @@
+error[E0308]: mismatched types
+  --> $DIR/regions-infer-invariance-due-to-decl.rs:12:5
+   |
+LL |     b_isize
+   |     ^^^^^^^ lifetime mismatch
+   |
+   = note: expected type `Invariant<'static>`
+              found type `Invariant<'r>`
+note: the lifetime 'r as defined on the function body at 11:23...
+  --> $DIR/regions-infer-invariance-due-to-decl.rs:11:23
+   |
+LL | fn to_longer_lifetime<'r>(b_isize: Invariant<'r>) -> Invariant<'static> {
+   |                       ^^
+   = note: ...does not necessarily outlive the static lifetime
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/regions/regions-infer-invariance-due-to-mutability-3.rs b/src/test/ui/regions/regions-infer-invariance-due-to-mutability-3.rs
new file mode 100644
index 0000000..168bf02
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-invariance-due-to-mutability-3.rs
@@ -0,0 +1,14 @@
+struct Invariant<'a> {
+    f: Box<FnOnce(&mut &'a isize) + 'static>,
+}
+
+fn to_same_lifetime<'r>(b_isize: Invariant<'r>) {
+    let bj: Invariant<'r> = b_isize;
+}
+
+fn to_longer_lifetime<'r>(b_isize: Invariant<'r>) -> Invariant<'static> {
+    b_isize //~ ERROR mismatched types
+}
+
+fn main() {
+}
diff --git a/src/test/ui/regions/regions-infer-invariance-due-to-mutability-3.stderr b/src/test/ui/regions/regions-infer-invariance-due-to-mutability-3.stderr
new file mode 100644
index 0000000..f8bdd01
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-invariance-due-to-mutability-3.stderr
@@ -0,0 +1,18 @@
+error[E0308]: mismatched types
+  --> $DIR/regions-infer-invariance-due-to-mutability-3.rs:10:5
+   |
+LL |     b_isize
+   |     ^^^^^^^ lifetime mismatch
+   |
+   = note: expected type `Invariant<'static>`
+              found type `Invariant<'r>`
+note: the lifetime 'r as defined on the function body at 9:23...
+  --> $DIR/regions-infer-invariance-due-to-mutability-3.rs:9:23
+   |
+LL | fn to_longer_lifetime<'r>(b_isize: Invariant<'r>) -> Invariant<'static> {
+   |                       ^^
+   = note: ...does not necessarily outlive the static lifetime
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/regions/regions-infer-invariance-due-to-mutability-4.rs b/src/test/ui/regions/regions-infer-invariance-due-to-mutability-4.rs
new file mode 100644
index 0000000..90c86ce
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-invariance-due-to-mutability-4.rs
@@ -0,0 +1,14 @@
+struct Invariant<'a> {
+    f: Box<FnOnce() -> *mut &'a isize + 'static>,
+}
+
+fn to_same_lifetime<'r>(b_isize: Invariant<'r>) {
+    let bj: Invariant<'r> = b_isize;
+}
+
+fn to_longer_lifetime<'r>(b_isize: Invariant<'r>) -> Invariant<'static> {
+    b_isize //~ ERROR mismatched types
+}
+
+fn main() {
+}
diff --git a/src/test/ui/regions/regions-infer-invariance-due-to-mutability-4.stderr b/src/test/ui/regions/regions-infer-invariance-due-to-mutability-4.stderr
new file mode 100644
index 0000000..1de6f22
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-invariance-due-to-mutability-4.stderr
@@ -0,0 +1,18 @@
+error[E0308]: mismatched types
+  --> $DIR/regions-infer-invariance-due-to-mutability-4.rs:10:5
+   |
+LL |     b_isize
+   |     ^^^^^^^ lifetime mismatch
+   |
+   = note: expected type `Invariant<'static>`
+              found type `Invariant<'r>`
+note: the lifetime 'r as defined on the function body at 9:23...
+  --> $DIR/regions-infer-invariance-due-to-mutability-4.rs:9:23
+   |
+LL | fn to_longer_lifetime<'r>(b_isize: Invariant<'r>) -> Invariant<'static> {
+   |                       ^^
+   = note: ...does not necessarily outlive the static lifetime
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/regions/regions-infer-not-param.rs b/src/test/ui/regions/regions-infer-not-param.rs
new file mode 100644
index 0000000..2144029
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-not-param.rs
@@ -0,0 +1,26 @@
+struct Direct<'a> {
+    f: &'a isize
+}
+
+struct Indirect1 {
+    // Here the lifetime parameter of direct is bound by the fn()
+    g: Box<FnOnce(Direct) + 'static>
+}
+
+struct Indirect2<'a> {
+    // But here it is set to 'a
+    g: Box<FnOnce(Direct<'a>) + 'static>
+}
+
+fn take_direct<'a,'b>(p: Direct<'a>) -> Direct<'b> { p } //~ ERROR mismatched types
+
+fn take_indirect1(p: Indirect1) -> Indirect1 { p }
+
+fn take_indirect2<'a,'b>(p: Indirect2<'a>) -> Indirect2<'b> { p } //~ ERROR mismatched types
+//~| expected type `Indirect2<'b>`
+//~| found type `Indirect2<'a>`
+//~| ERROR mismatched types
+//~| expected type `Indirect2<'b>`
+//~| found type `Indirect2<'a>`
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-infer-not-param.stderr b/src/test/ui/regions/regions-infer-not-param.stderr
new file mode 100644
index 0000000..f43ab82
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-not-param.stderr
@@ -0,0 +1,60 @@
+error[E0308]: mismatched types
+  --> $DIR/regions-infer-not-param.rs:15:54
+   |
+LL | fn take_direct<'a,'b>(p: Direct<'a>) -> Direct<'b> { p }
+   |                                                      ^ lifetime mismatch
+   |
+   = note: expected type `Direct<'b>`
+              found type `Direct<'a>`
+note: the lifetime 'a as defined on the function body at 15:16...
+  --> $DIR/regions-infer-not-param.rs:15:16
+   |
+LL | fn take_direct<'a,'b>(p: Direct<'a>) -> Direct<'b> { p }
+   |                ^^
+note: ...does not necessarily outlive the lifetime 'b as defined on the function body at 15:19
+  --> $DIR/regions-infer-not-param.rs:15:19
+   |
+LL | fn take_direct<'a,'b>(p: Direct<'a>) -> Direct<'b> { p }
+   |                   ^^
+
+error[E0308]: mismatched types
+  --> $DIR/regions-infer-not-param.rs:19:63
+   |
+LL | fn take_indirect2<'a,'b>(p: Indirect2<'a>) -> Indirect2<'b> { p }
+   |                                                               ^ lifetime mismatch
+   |
+   = note: expected type `Indirect2<'b>`
+              found type `Indirect2<'a>`
+note: the lifetime 'a as defined on the function body at 19:19...
+  --> $DIR/regions-infer-not-param.rs:19:19
+   |
+LL | fn take_indirect2<'a,'b>(p: Indirect2<'a>) -> Indirect2<'b> { p }
+   |                   ^^
+note: ...does not necessarily outlive the lifetime 'b as defined on the function body at 19:22
+  --> $DIR/regions-infer-not-param.rs:19:22
+   |
+LL | fn take_indirect2<'a,'b>(p: Indirect2<'a>) -> Indirect2<'b> { p }
+   |                      ^^
+
+error[E0308]: mismatched types
+  --> $DIR/regions-infer-not-param.rs:19:63
+   |
+LL | fn take_indirect2<'a,'b>(p: Indirect2<'a>) -> Indirect2<'b> { p }
+   |                                                               ^ lifetime mismatch
+   |
+   = note: expected type `Indirect2<'b>`
+              found type `Indirect2<'a>`
+note: the lifetime 'b as defined on the function body at 19:22...
+  --> $DIR/regions-infer-not-param.rs:19:22
+   |
+LL | fn take_indirect2<'a,'b>(p: Indirect2<'a>) -> Indirect2<'b> { p }
+   |                      ^^
+note: ...does not necessarily outlive the lifetime 'a as defined on the function body at 19:19
+  --> $DIR/regions-infer-not-param.rs:19:19
+   |
+LL | fn take_indirect2<'a,'b>(p: Indirect2<'a>) -> Indirect2<'b> { p }
+   |                   ^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/regions/regions-infer-paramd-indirect.rs b/src/test/ui/regions/regions-infer-paramd-indirect.rs
new file mode 100644
index 0000000..0fb1824
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-paramd-indirect.rs
@@ -0,0 +1,30 @@
+// Check that we correctly infer that b and c must be region
+// parameterized because they reference a which requires a region.
+
+type A<'a> = &'a isize;
+type B<'a> = Box<A<'a>>;
+
+struct C<'a> {
+    f: Box<B<'a>>
+}
+
+trait SetF<'a> {
+    fn set_f_ok(&mut self, b: Box<B<'a>>);
+    fn set_f_bad(&mut self, b: Box<B>);
+}
+
+impl<'a> SetF<'a> for C<'a> {
+    fn set_f_ok(&mut self, b: Box<B<'a>>) {
+        self.f = b;
+    }
+
+    fn set_f_bad(&mut self, b: Box<B>) {
+        self.f = b;
+        //~^ ERROR mismatched types
+        //~| expected type `std::boxed::Box<std::boxed::Box<&'a isize>>`
+        //~| found type `std::boxed::Box<std::boxed::Box<&isize>>`
+        //~| lifetime mismatch
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-infer-paramd-indirect.stderr b/src/test/ui/regions/regions-infer-paramd-indirect.stderr
new file mode 100644
index 0000000..1b999ed
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-paramd-indirect.stderr
@@ -0,0 +1,28 @@
+error[E0308]: mismatched types
+  --> $DIR/regions-infer-paramd-indirect.rs:22:18
+   |
+LL |         self.f = b;
+   |                  ^ lifetime mismatch
+   |
+   = note: expected type `std::boxed::Box<std::boxed::Box<&'a isize>>`
+              found type `std::boxed::Box<std::boxed::Box<&isize>>`
+note: the anonymous lifetime #2 defined on the method body at 21:5...
+  --> $DIR/regions-infer-paramd-indirect.rs:21:5
+   |
+LL | /     fn set_f_bad(&mut self, b: Box<B>) {
+LL | |         self.f = b;
+LL | |
+LL | |
+LL | |
+LL | |
+LL | |     }
+   | |_____^
+note: ...does not necessarily outlive the lifetime 'a as defined on the impl at 16:6
+  --> $DIR/regions-infer-paramd-indirect.rs:16:6
+   |
+LL | impl<'a> SetF<'a> for C<'a> {
+   |      ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/regions/regions-infer-proc-static-upvar.nll.stderr b/src/test/ui/regions/regions-infer-proc-static-upvar.nll.stderr
new file mode 100644
index 0000000..803d0d7
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-proc-static-upvar.nll.stderr
@@ -0,0 +1,15 @@
+error[E0597]: `x` does not live long enough
+  --> $DIR/regions-infer-proc-static-upvar.rs:10:13
+   |
+LL |       let y = &x;
+   |               ^^ borrowed value does not live long enough
+LL | /     foo(move|| {
+LL | |         let _a = *y;
+LL | |     });
+   | |______- argument requires that `x` is borrowed for `'static`
+LL |   }
+   |   - `x` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/regions/regions-infer-proc-static-upvar.rs b/src/test/ui/regions/regions-infer-proc-static-upvar.rs
new file mode 100644
index 0000000..5a64aa7
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-proc-static-upvar.rs
@@ -0,0 +1,24 @@
+// Test that, when a variable of type `&T` is captured inside a proc,
+// we correctly infer/require that its lifetime is 'static.
+
+fn foo<F:FnOnce()+'static>(_p: F) { }
+
+static i: isize = 3;
+
+fn capture_local() {
+    let x = 3;
+    let y = &x; //~ ERROR `x` does not live long enough
+    foo(move|| {
+        let _a = *y;
+    });
+}
+
+fn capture_static() {
+    // Legal because &i can have static lifetime:
+    let y = &i;
+    foo(move|| {
+        let _a = *y;
+    });
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-infer-proc-static-upvar.stderr b/src/test/ui/regions/regions-infer-proc-static-upvar.stderr
new file mode 100644
index 0000000..21b2e88
--- /dev/null
+++ b/src/test/ui/regions/regions-infer-proc-static-upvar.stderr
@@ -0,0 +1,14 @@
+error[E0597]: `x` does not live long enough
+  --> $DIR/regions-infer-proc-static-upvar.rs:10:14
+   |
+LL |     let y = &x;
+   |              ^ borrowed value does not live long enough
+...
+LL | }
+   | - borrowed value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/regions/regions-lifetime-bounds-on-fns.rs b/src/test/ui/regions/regions-lifetime-bounds-on-fns.rs
new file mode 100644
index 0000000..7d7f62e
--- /dev/null
+++ b/src/test/ui/regions/regions-lifetime-bounds-on-fns.rs
@@ -0,0 +1,29 @@
+fn a<'a, 'b:'a>(x: &mut &'a isize, y: &mut &'b isize) {
+    // Note: this is legal because of the `'b:'a` declaration.
+    *x = *y;
+}
+
+fn b<'a, 'b>(x: &mut &'a isize, y: &mut &'b isize) {
+    // Illegal now because there is no `'b:'a` declaration.
+    *x = *y; //~ ERROR E0623
+}
+
+fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) {
+    // Here we try to call `foo` but do not know that `'a` and `'b` are
+    // related as required.
+    a(x, y); //~ ERROR lifetime mismatch [E0623]
+}
+
+fn d() {
+    // 'a and 'b are early bound in the function `a` because they appear
+    // inconstraints:
+    let _: fn(&mut &isize, &mut &isize) = a; //~ ERROR E0308
+}
+
+fn e() {
+    // 'a and 'b are late bound in the function `b` because there are
+    // no constraints:
+    let _: fn(&mut &isize, &mut &isize) = b;
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr b/src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr
new file mode 100644
index 0000000..46200e4
--- /dev/null
+++ b/src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr
@@ -0,0 +1,31 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/regions-lifetime-bounds-on-fns.rs:8:10
+   |
+LL | fn b<'a, 'b>(x: &mut &'a isize, y: &mut &'b isize) {
+   |                      ---------          --------- these two types are declared with different lifetimes...
+LL |     // Illegal now because there is no `'b:'a` declaration.
+LL |     *x = *y;
+   |          ^^ ...but data from `y` flows into `x` here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/regions-lifetime-bounds-on-fns.rs:14:7
+   |
+LL | fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) {
+   |                     ---------          --------- these two types are declared with different lifetimes...
+...
+LL |     a(x, y);
+   |       ^ ...but data from `y` flows into `x` here
+
+error[E0308]: mismatched types
+  --> $DIR/regions-lifetime-bounds-on-fns.rs:20:43
+   |
+LL |     let _: fn(&mut &isize, &mut &isize) = a;
+   |                                           ^ expected concrete lifetime, found bound lifetime parameter
+   |
+   = note: expected type `for<'r, 's, 't0, 't1> fn(&'r mut &'s isize, &'t0 mut &'t1 isize)`
+              found type `for<'r, 's> fn(&'r mut &isize, &'s mut &isize) {a::<'_, '_>}`
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0308, E0623.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/regions/regions-lifetime-of-struct-or-enum-variant.nll.stderr b/src/test/ui/regions/regions-lifetime-of-struct-or-enum-variant.nll.stderr
new file mode 100644
index 0000000..7984f4f
--- /dev/null
+++ b/src/test/ui/regions/regions-lifetime-of-struct-or-enum-variant.nll.stderr
@@ -0,0 +1,21 @@
+error[E0515]: cannot return value referencing temporary value
+  --> $DIR/regions-lifetime-of-struct-or-enum-variant.rs:16:3
+   |
+LL |   let testValue = &id(Test);
+   |                    -------- temporary value created here
+LL |
+LL |   testValue
+   |   ^^^^^^^^^ returns a value referencing data owned by the current function
+
+error[E0515]: cannot return value referencing temporary value
+  --> $DIR/regions-lifetime-of-struct-or-enum-variant.rs:22:3
+   |
+LL |   let testValue = &id(MyEnum::Variant1);
+   |                    -------------------- temporary value created here
+LL |
+LL |   testValue
+   |   ^^^^^^^^^ returns a value referencing data owned by the current function
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/src/test/ui/regions/regions-lifetime-of-struct-or-enum-variant.rs b/src/test/ui/regions/regions-lifetime-of-struct-or-enum-variant.rs
new file mode 100644
index 0000000..2d21a51
--- /dev/null
+++ b/src/test/ui/regions/regions-lifetime-of-struct-or-enum-variant.rs
@@ -0,0 +1,26 @@
+// This tests verifies that unary structs and enum variants
+// are treated as rvalues and their lifetime is not bounded to
+// the static scope.
+
+fn id<T>(x: T) -> T { x }
+
+struct Test;
+
+enum MyEnum {
+    Variant1
+}
+
+fn structLifetime<'a>() -> &'a Test {
+  let testValue = &id(Test);
+  //~^ ERROR borrowed value does not live long enough
+  testValue
+}
+
+fn variantLifetime<'a>() -> &'a MyEnum {
+  let testValue = &id(MyEnum::Variant1);
+  //~^ ERROR borrowed value does not live long enough
+  testValue
+}
+
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-lifetime-of-struct-or-enum-variant.stderr b/src/test/ui/regions/regions-lifetime-of-struct-or-enum-variant.stderr
new file mode 100644
index 0000000..c0bfc47
--- /dev/null
+++ b/src/test/ui/regions/regions-lifetime-of-struct-or-enum-variant.stderr
@@ -0,0 +1,33 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/regions-lifetime-of-struct-or-enum-variant.rs:14:20
+   |
+LL |   let testValue = &id(Test);
+   |                    ^^^^^^^^ temporary value does not live long enough
+...
+LL | }
+   | - temporary value only lives until here
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 13:19...
+  --> $DIR/regions-lifetime-of-struct-or-enum-variant.rs:13:19
+   |
+LL | fn structLifetime<'a>() -> &'a Test {
+   |                   ^^
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/regions-lifetime-of-struct-or-enum-variant.rs:20:20
+   |
+LL |   let testValue = &id(MyEnum::Variant1);
+   |                    ^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+...
+LL | }
+   | - temporary value only lives until here
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 19:20...
+  --> $DIR/regions-lifetime-of-struct-or-enum-variant.rs:19:20
+   |
+LL | fn variantLifetime<'a>() -> &'a MyEnum {
+   |                    ^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/regions/regions-name-duplicated.rs b/src/test/ui/regions/regions-name-duplicated.rs
new file mode 100644
index 0000000..f2adf01
--- /dev/null
+++ b/src/test/ui/regions/regions-name-duplicated.rs
@@ -0,0 +1,5 @@
+struct Foo<'a, 'a> { //~ ERROR lifetime name `'a` declared twice
+    x: &'a isize
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-name-duplicated.stderr b/src/test/ui/regions/regions-name-duplicated.stderr
new file mode 100644
index 0000000..a7e03a6
--- /dev/null
+++ b/src/test/ui/regions/regions-name-duplicated.stderr
@@ -0,0 +1,11 @@
+error[E0263]: lifetime name `'a` declared twice in the same scope
+  --> $DIR/regions-name-duplicated.rs:1:16
+   |
+LL | struct Foo<'a, 'a> {
+   |            --  ^^ declared twice
+   |            |
+   |            previous declaration here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0263`.
diff --git a/src/test/ui/regions/regions-name-static.rs b/src/test/ui/regions/regions-name-static.rs
new file mode 100644
index 0000000..730fd99
--- /dev/null
+++ b/src/test/ui/regions/regions-name-static.rs
@@ -0,0 +1,5 @@
+struct Foo<'static> { //~ ERROR invalid lifetime parameter name: `'static`
+    x: &'static isize
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-name-static.stderr b/src/test/ui/regions/regions-name-static.stderr
new file mode 100644
index 0000000..4b7026e
--- /dev/null
+++ b/src/test/ui/regions/regions-name-static.stderr
@@ -0,0 +1,9 @@
+error[E0262]: invalid lifetime parameter name: `'static`
+  --> $DIR/regions-name-static.rs:1:12
+   |
+LL | struct Foo<'static> {
+   |            ^^^^^^^ 'static is a reserved lifetime name
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0262`.
diff --git a/src/test/ui/regions/regions-name-undeclared.rs b/src/test/ui/regions/regions-name-undeclared.rs
new file mode 100644
index 0000000..230a97a
--- /dev/null
+++ b/src/test/ui/regions/regions-name-undeclared.rs
@@ -0,0 +1,50 @@
+// Check that lifetime resolver enforces the lifetime name scoping
+// rules correctly in various scenarios.
+
+struct Foo<'a> {
+    x: &'a isize
+}
+
+impl<'a> Foo<'a> {
+    // &'a is inherited:
+    fn m1(&self, arg: &'a isize) { }
+    fn m2(&'a self) { }
+    fn m3(&self, arg: Foo<'a>) { }
+
+    // &'b is not:
+    fn m4(&self, arg: &'b isize) { } //~ ERROR undeclared lifetime
+    fn m5(&'b self) { } //~ ERROR undeclared lifetime
+    fn m6(&self, arg: Foo<'b>) { } //~ ERROR undeclared lifetime
+}
+
+fn bar<'a>(x: &'a isize) {
+    // &'a is visible to code:
+    let y: &'a isize = x;
+
+    // &'a is not visible to *items*:
+    type X = Option<&'a isize>; //~ ERROR undeclared lifetime
+    enum E {
+        E1(&'a isize) //~ ERROR undeclared lifetime
+    }
+    struct S {
+        f: &'a isize //~ ERROR undeclared lifetime
+    }
+    fn f(a: &'a isize) { } //~ ERROR undeclared lifetime
+
+    // &'a CAN be declared on functions and used then:
+    fn g<'a>(a: &'a isize) { } // OK
+    fn h(a: Box<for<'a> FnOnce(&'a isize)>) { } // OK
+}
+
+// Test nesting of lifetimes in fn type declarations
+fn fn_types(a: &'a isize, //~ ERROR undeclared lifetime
+            b: Box<for<'a> FnOnce(&'a isize,
+                                  &'b isize, //~ ERROR undeclared lifetime
+                                  Box<for<'b> FnOnce(&'a isize,
+                                                     &'b isize)>,
+                                  &'b isize)>, //~ ERROR undeclared lifetime
+            c: &'a isize) //~ ERROR undeclared lifetime
+{
+}
+
+pub fn main() {}
diff --git a/src/test/ui/regions/regions-name-undeclared.stderr b/src/test/ui/regions/regions-name-undeclared.stderr
new file mode 100644
index 0000000..4840d75
--- /dev/null
+++ b/src/test/ui/regions/regions-name-undeclared.stderr
@@ -0,0 +1,69 @@
+error[E0261]: use of undeclared lifetime name `'b`
+  --> $DIR/regions-name-undeclared.rs:15:24
+   |
+LL |     fn m4(&self, arg: &'b isize) { }
+   |                        ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'b`
+  --> $DIR/regions-name-undeclared.rs:16:12
+   |
+LL |     fn m5(&'b self) { }
+   |            ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'b`
+  --> $DIR/regions-name-undeclared.rs:17:27
+   |
+LL |     fn m6(&self, arg: Foo<'b>) { }
+   |                           ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/regions-name-undeclared.rs:25:22
+   |
+LL |     type X = Option<&'a isize>;
+   |                      ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/regions-name-undeclared.rs:27:13
+   |
+LL |         E1(&'a isize)
+   |             ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/regions-name-undeclared.rs:30:13
+   |
+LL |         f: &'a isize
+   |             ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/regions-name-undeclared.rs:32:14
+   |
+LL |     fn f(a: &'a isize) { }
+   |              ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/regions-name-undeclared.rs:40:17
+   |
+LL | fn fn_types(a: &'a isize,
+   |                 ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'b`
+  --> $DIR/regions-name-undeclared.rs:42:36
+   |
+LL |                                   &'b isize,
+   |                                    ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'b`
+  --> $DIR/regions-name-undeclared.rs:45:36
+   |
+LL |                                   &'b isize)>,
+   |                                    ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/regions-name-undeclared.rs:46:17
+   |
+LL |             c: &'a isize)
+   |                 ^^ undeclared lifetime
+
+error: aborting due to 11 previous errors
+
+For more information about this error, try `rustc --explain E0261`.
diff --git a/src/test/ui/regions/regions-nested-fns-2.nll.stderr b/src/test/ui/regions/regions-nested-fns-2.nll.stderr
new file mode 100644
index 0000000..8627dac
--- /dev/null
+++ b/src/test/ui/regions/regions-nested-fns-2.nll.stderr
@@ -0,0 +1,18 @@
+error[E0597]: `y` does not live long enough
+  --> $DIR/regions-nested-fns-2.rs:8:25
+   |
+LL |         |z| {
+   |         --- value captured here
+LL |
+LL |             if false { &y } else { z }
+   |                        -^
+   |                        ||
+   |                        |borrowed value does not live long enough
+   |                        returning this value requires that `y` is borrowed for `'static`
+LL |         });
+LL | }
+   | - `y` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/regions/regions-nested-fns-2.rs b/src/test/ui/regions/regions-nested-fns-2.rs
new file mode 100644
index 0000000..1b51880
--- /dev/null
+++ b/src/test/ui/regions/regions-nested-fns-2.rs
@@ -0,0 +1,12 @@
+fn ignore<F>(_f: F) where F: for<'z> FnOnce(&'z isize) -> &'z isize {}
+
+fn nested() {
+    let y = 3;
+    ignore(
+        |z| {
+            //~^ ERROR E0373
+            if false { &y } else { z }
+        });
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-nested-fns-2.stderr b/src/test/ui/regions/regions-nested-fns-2.stderr
new file mode 100644
index 0000000..08bab6e
--- /dev/null
+++ b/src/test/ui/regions/regions-nested-fns-2.stderr
@@ -0,0 +1,16 @@
+error[E0373]: closure may outlive the current function, but it borrows `y`, which is owned by the current function
+  --> $DIR/regions-nested-fns-2.rs:6:9
+   |
+LL |         |z| {
+   |         ^^^ may outlive borrowed value `y`
+LL |
+LL |             if false { &y } else { z }
+   |                         - `y` is borrowed here
+help: to force the closure to take ownership of `y` (and any other referenced variables), use the `move` keyword
+   |
+LL |         move |z| {
+   |         ^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0373`.
diff --git a/src/test/ui/regions/regions-nested-fns.rs b/src/test/ui/regions/regions-nested-fns.rs
new file mode 100644
index 0000000..161d812
--- /dev/null
+++ b/src/test/ui/regions/regions-nested-fns.rs
@@ -0,0 +1,20 @@
+fn ignore<T>(t: T) {}
+
+fn nested<'x>(x: &'x isize) {
+    let y = 3;
+    let mut ay = &y; //~ ERROR E0495
+
+    ignore::<Box<for<'z> FnMut(&'z isize)>>(Box::new(|z| {
+        ay = x;
+        ay = &y;
+        ay = z;
+    }));
+
+    ignore::< Box<for<'z> FnMut(&'z isize) -> &'z isize>>(Box::new(|z| {
+        if false { return x; } //~ ERROR E0312
+        if false { return ay; }
+        return z;
+    }));
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-nested-fns.stderr b/src/test/ui/regions/regions-nested-fns.stderr
new file mode 100644
index 0000000..3cecd4e
--- /dev/null
+++ b/src/test/ui/regions/regions-nested-fns.stderr
@@ -0,0 +1,61 @@
+error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
+  --> $DIR/regions-nested-fns.rs:5:18
+   |
+LL |     let mut ay = &y;
+   |                  ^^
+   |
+note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the body at 7:54...
+  --> $DIR/regions-nested-fns.rs:7:54
+   |
+LL |       ignore::<Box<for<'z> FnMut(&'z isize)>>(Box::new(|z| {
+   |  ______________________________________________________^
+LL | |         ay = x;
+LL | |         ay = &y;
+LL | |         ay = z;
+LL | |     }));
+   | |_____^
+note: ...so that reference does not outlive borrowed content
+  --> $DIR/regions-nested-fns.rs:10:14
+   |
+LL |         ay = z;
+   |              ^
+note: but, the lifetime must be valid for the anonymous lifetime #2 defined on the body at 13:68...
+  --> $DIR/regions-nested-fns.rs:13:68
+   |
+LL |       ignore::< Box<for<'z> FnMut(&'z isize) -> &'z isize>>(Box::new(|z| {
+   |  ____________________________________________________________________^
+LL | |         if false { return x; }
+LL | |         if false { return ay; }
+LL | |         return z;
+LL | |     }));
+   | |_____^
+   = note: ...so that the types are compatible:
+           expected &isize
+              found &isize
+
+error[E0312]: lifetime of reference outlives lifetime of borrowed content...
+  --> $DIR/regions-nested-fns.rs:14:27
+   |
+LL |         if false { return x; }
+   |                           ^
+   |
+note: ...the reference is valid for the anonymous lifetime #2 defined on the body at 13:68...
+  --> $DIR/regions-nested-fns.rs:13:68
+   |
+LL |       ignore::< Box<for<'z> FnMut(&'z isize) -> &'z isize>>(Box::new(|z| {
+   |  ____________________________________________________________________^
+LL | |         if false { return x; }
+LL | |         if false { return ay; }
+LL | |         return z;
+LL | |     }));
+   | |_____^
+note: ...but the borrowed content is only valid for the lifetime 'x as defined on the function body at 3:11
+  --> $DIR/regions-nested-fns.rs:3:11
+   |
+LL | fn nested<'x>(x: &'x isize) {
+   |           ^^
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0312, E0495.
+For more information about an error, try `rustc --explain E0312`.
diff --git a/src/test/ui/regions/regions-normalize-in-where-clause-list.rs b/src/test/ui/regions/regions-normalize-in-where-clause-list.rs
new file mode 100644
index 0000000..e94e8b2
--- /dev/null
+++ b/src/test/ui/regions/regions-normalize-in-where-clause-list.rs
@@ -0,0 +1,27 @@
+// Test that we are able to normalize in the list of where-clauses,
+// even if `'a: 'b` is required.
+
+trait Project<'a, 'b> {
+    type Item;
+}
+
+impl<'a, 'b> Project<'a, 'b> for ()
+    where 'a: 'b
+{
+    type Item = ();
+}
+
+// No error here, we have 'a: 'b. We used to report an error here
+// though, see https://github.com/rust-lang/rust/issues/45937.
+fn foo<'a: 'b, 'b>()
+    where <() as Project<'a, 'b>>::Item : Eq
+{
+}
+
+// Here we get an error: we need `'a: 'b`.
+fn bar<'a, 'b>() //~ ERROR cannot infer
+    where <() as Project<'a, 'b>>::Item : Eq
+{
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr b/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr
new file mode 100644
index 0000000..c44edf1
--- /dev/null
+++ b/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr
@@ -0,0 +1,26 @@
+error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
+  --> $DIR/regions-normalize-in-where-clause-list.rs:22:1
+   |
+LL | / fn bar<'a, 'b>()
+LL | |     where <() as Project<'a, 'b>>::Item : Eq
+LL | | {
+LL | | }
+   | |_^
+   |
+note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 22:8...
+  --> $DIR/regions-normalize-in-where-clause-list.rs:22:8
+   |
+LL | fn bar<'a, 'b>()
+   |        ^^
+note: ...but the lifetime must also be valid for the lifetime 'b as defined on the function body at 22:12...
+  --> $DIR/regions-normalize-in-where-clause-list.rs:22:12
+   |
+LL | fn bar<'a, 'b>()
+   |            ^^
+   = note: ...so that the types are compatible:
+           expected Project<'a, 'b>
+              found Project<'_, '_>
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0495`.
diff --git a/src/test/ui/regions/regions-outlives-nominal-type-enum-region-rev.rs b/src/test/ui/regions/regions-outlives-nominal-type-enum-region-rev.rs
new file mode 100644
index 0000000..045d289
--- /dev/null
+++ b/src/test/ui/regions/regions-outlives-nominal-type-enum-region-rev.rs
@@ -0,0 +1,20 @@
+// Test that a nominal type (like `Foo<'a>`) outlives `'b` if its
+// arguments (like `'a`) outlive `'b`.
+//
+// Rule OutlivesNominalType from RFC 1214.
+
+// compile-pass
+
+#![feature(rustc_attrs)]
+#![allow(dead_code)]
+
+mod rev_variant_struct_region {
+    struct Foo<'a> {
+        x: fn(&'a i32),
+    }
+    enum Bar<'a,'b> {
+        V(&'a Foo<'b>)
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-outlives-nominal-type-enum-region.rs b/src/test/ui/regions/regions-outlives-nominal-type-enum-region.rs
new file mode 100644
index 0000000..e087d65
--- /dev/null
+++ b/src/test/ui/regions/regions-outlives-nominal-type-enum-region.rs
@@ -0,0 +1,20 @@
+// Test that a nominal type (like `Foo<'a>`) outlives `'b` if its
+// arguments (like `'a`) outlive `'b`.
+//
+// Rule OutlivesNominalType from RFC 1214.
+
+// compile-pass
+
+#![feature(rustc_attrs)]
+#![allow(dead_code)]
+
+mod variant_struct_region {
+    struct Foo<'a> {
+        x: &'a i32,
+    }
+    enum Bar<'a,'b> {
+        V(&'a Foo<'b>)
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-outlives-nominal-type-enum-type-rev.rs b/src/test/ui/regions/regions-outlives-nominal-type-enum-type-rev.rs
new file mode 100644
index 0000000..20b391c
--- /dev/null
+++ b/src/test/ui/regions/regions-outlives-nominal-type-enum-type-rev.rs
@@ -0,0 +1,20 @@
+// Test that a nominal type (like `Foo<'a>`) outlives `'b` if its
+// arguments (like `'a`) outlive `'b`.
+//
+// Rule OutlivesNominalType from RFC 1214.
+
+//compile-pass
+
+#![feature(rustc_attrs)]
+#![allow(dead_code)]
+
+mod variant_struct_type {
+    struct Foo<T> {
+        x: fn(T)
+    }
+    enum Bar<'a,'b> {
+        V(&'a Foo<&'b i32>)
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-outlives-nominal-type-enum-type.rs b/src/test/ui/regions/regions-outlives-nominal-type-enum-type.rs
new file mode 100644
index 0000000..7f84441
--- /dev/null
+++ b/src/test/ui/regions/regions-outlives-nominal-type-enum-type.rs
@@ -0,0 +1,20 @@
+// Test that a nominal type (like `Foo<'a>`) outlives `'b` if its
+// arguments (like `'a`) outlive `'b`.
+//
+// Rule OutlivesNominalType from RFC 1214.
+
+// compile-pass
+
+#![feature(rustc_attrs)]
+#![allow(dead_code)]
+
+mod variant_struct_type {
+    struct Foo<T> {
+        x: T
+    }
+    enum Bar<'a,'b> {
+        V(&'a Foo<&'b i32>)
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-outlives-nominal-type-struct-region-rev.rs b/src/test/ui/regions/regions-outlives-nominal-type-struct-region-rev.rs
new file mode 100644
index 0000000..07daa35
--- /dev/null
+++ b/src/test/ui/regions/regions-outlives-nominal-type-struct-region-rev.rs
@@ -0,0 +1,20 @@
+// Test that a nominal type (like `Foo<'a>`) outlives `'b` if its
+// arguments (like `'a`) outlive `'b`.
+//
+// Rule OutlivesNominalType from RFC 1214.
+
+// compile-pass
+
+#![feature(rustc_attrs)]
+#![allow(dead_code)]
+
+mod rev_variant_struct_region {
+    struct Foo<'a> {
+        x: fn(&'a i32),
+    }
+    struct Bar<'a,'b> {
+        f: &'a Foo<'b>
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-outlives-nominal-type-struct-region.rs b/src/test/ui/regions/regions-outlives-nominal-type-struct-region.rs
new file mode 100644
index 0000000..59da5fb
--- /dev/null
+++ b/src/test/ui/regions/regions-outlives-nominal-type-struct-region.rs
@@ -0,0 +1,20 @@
+// Test that a nominal type (like `Foo<'a>`) outlives `'b` if its
+// arguments (like `'a`) outlive `'b`.
+//
+// Rule OutlivesNominalType from RFC 1214.
+
+// compile-pass
+
+#![feature(rustc_attrs)]
+#![allow(dead_code)]
+
+mod variant_struct_region {
+    struct Foo<'a> {
+        x: &'a i32,
+    }
+    struct Bar<'a,'b> {
+        f: &'a Foo<'b> //~ ERROR reference has a longer lifetime
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-outlives-nominal-type-struct-type-rev.rs b/src/test/ui/regions/regions-outlives-nominal-type-struct-type-rev.rs
new file mode 100644
index 0000000..096069c
--- /dev/null
+++ b/src/test/ui/regions/regions-outlives-nominal-type-struct-type-rev.rs
@@ -0,0 +1,20 @@
+// Test that a nominal type (like `Foo<'a>`) outlives `'b` if its
+// arguments (like `'a`) outlive `'b`.
+//
+// Rule OutlivesNominalType from RFC 1214.
+
+// compile-pass
+
+#![feature(rustc_attrs)]
+#![allow(dead_code)]
+
+mod rev_variant_struct_type {
+    struct Foo<T> {
+        x: fn(T)
+    }
+    struct Bar<'a,'b> {
+        f: &'a Foo<&'b i32> //~ ERROR reference has a longer lifetime
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-outlives-nominal-type-struct-type.rs b/src/test/ui/regions/regions-outlives-nominal-type-struct-type.rs
new file mode 100644
index 0000000..3c8c4a1
--- /dev/null
+++ b/src/test/ui/regions/regions-outlives-nominal-type-struct-type.rs
@@ -0,0 +1,20 @@
+// Test that a nominal type (like `Foo<'a>`) outlives `'b` if its
+// arguments (like `'a`) outlive `'b`.
+//
+// Rule OutlivesNominalType from RFC 1214.
+
+// compile-pass
+
+#![feature(rustc_attrs)]
+#![allow(dead_code)]
+
+mod variant_struct_type {
+    struct Foo<T> {
+        x: T
+    }
+    struct Bar<'a,'b> {
+        f: &'a Foo<&'b i32> //~ ERROR reference has a longer lifetime
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-outlives-projection-container-hrtb.ast.stderr b/src/test/ui/regions/regions-outlives-projection-container-hrtb.ast.stderr
new file mode 100644
index 0000000..d833018
--- /dev/null
+++ b/src/test/ui/regions/regions-outlives-projection-container-hrtb.ast.stderr
@@ -0,0 +1,37 @@
+error[E0491]: in type `&'a WithHrAssoc<TheType<'b>>`, reference has a longer lifetime than the data it references
+  --> $DIR/regions-outlives-projection-container-hrtb.rs:35:12
+   |
+LL |     let _: &'a WithHrAssoc<TheType<'b>> = loop { };
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the pointer is valid for the lifetime 'a as defined on the function body at 32:15
+  --> $DIR/regions-outlives-projection-container-hrtb.rs:32:15
+   |
+LL | fn with_assoc<'a,'b>() {
+   |               ^^
+note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 32:18
+  --> $DIR/regions-outlives-projection-container-hrtb.rs:32:18
+   |
+LL | fn with_assoc<'a,'b>() {
+   |                  ^^
+
+error[E0491]: in type `&'a WithHrAssocSub<TheType<'b>>`, reference has a longer lifetime than the data it references
+  --> $DIR/regions-outlives-projection-container-hrtb.rs:57:12
+   |
+LL |     let _: &'a WithHrAssocSub<TheType<'b>> = loop { };
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the pointer is valid for the lifetime 'a as defined on the function body at 53:19
+  --> $DIR/regions-outlives-projection-container-hrtb.rs:53:19
+   |
+LL | fn with_assoc_sub<'a,'b>() {
+   |                   ^^
+note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 53:22
+  --> $DIR/regions-outlives-projection-container-hrtb.rs:53:22
+   |
+LL | fn with_assoc_sub<'a,'b>() {
+   |                      ^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0491`.
diff --git a/src/test/ui/regions/regions-outlives-projection-container-hrtb.mir.stderr b/src/test/ui/regions/regions-outlives-projection-container-hrtb.mir.stderr
new file mode 100644
index 0000000..5028663
--- /dev/null
+++ b/src/test/ui/regions/regions-outlives-projection-container-hrtb.mir.stderr
@@ -0,0 +1,24 @@
+error: lifetime may not live long enough
+  --> $DIR/regions-outlives-projection-container-hrtb.rs:35:12
+   |
+LL | fn with_assoc<'a,'b>() {
+   |               -- -- lifetime `'b` defined here
+   |               |
+   |               lifetime `'a` defined here
+...
+LL |     let _: &'a WithHrAssoc<TheType<'b>> = loop { };
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
+
+error: lifetime may not live long enough
+  --> $DIR/regions-outlives-projection-container-hrtb.rs:57:12
+   |
+LL | fn with_assoc_sub<'a,'b>() {
+   |                   -- -- lifetime `'b` defined here
+   |                   |
+   |                   lifetime `'a` defined here
+...
+LL |     let _: &'a WithHrAssocSub<TheType<'b>> = loop { };
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/regions/regions-outlives-projection-container-hrtb.rs b/src/test/ui/regions/regions-outlives-projection-container-hrtb.rs
new file mode 100644
index 0000000..2871d96
--- /dev/null
+++ b/src/test/ui/regions/regions-outlives-projection-container-hrtb.rs
@@ -0,0 +1,64 @@
+// Test that structs with higher-ranked where clauses don't generate
+// "outlives" requirements. Issue #22246.
+
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+#![allow(dead_code)]
+
+
+///////////////////////////////////////////////////////////////////////////
+
+pub trait TheTrait<'b> {
+    type TheAssocType;
+}
+
+pub struct TheType<'b> {
+    m: [fn(&'b()); 0]
+}
+
+impl<'a,'b> TheTrait<'a> for TheType<'b> {
+    type TheAssocType = &'b ();
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+pub struct WithHrAssoc<T>
+    where for<'a> T : TheTrait<'a>
+{
+    m: [T; 0]
+}
+
+fn with_assoc<'a,'b>() {
+    // We get an error because 'b:'a does not hold:
+
+    let _: &'a WithHrAssoc<TheType<'b>> = loop { };
+    //[ast]~^ ERROR reference has a longer lifetime
+    //[mir]~^^ ERROR lifetime may not live long enough
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+pub trait TheSubTrait : for<'a> TheTrait<'a> {
+}
+
+impl<'b> TheSubTrait for TheType<'b> { }
+
+pub struct WithHrAssocSub<T>
+    where T : TheSubTrait
+{
+    m: [T; 0]
+}
+
+fn with_assoc_sub<'a,'b>() {
+    // The error here is just because `'b:'a` must hold for the type
+    // below to be well-formed, it is not related to the HR relation.
+
+    let _: &'a WithHrAssocSub<TheType<'b>> = loop { };
+    //[ast]~^ ERROR reference has a longer lifetime
+    //[mir]~^^ ERROR lifetime may not live long enough
+}
+
+
+fn main() {
+}
diff --git a/src/test/ui/regions/regions-outlives-projection-container-hrtb.stderr b/src/test/ui/regions/regions-outlives-projection-container-hrtb.stderr
new file mode 100644
index 0000000..856e28f
--- /dev/null
+++ b/src/test/ui/regions/regions-outlives-projection-container-hrtb.stderr
@@ -0,0 +1,37 @@
+error[E0491]: in type `&'a WithHrAssoc<TheType<'b>>`, reference has a longer lifetime than the data it references
+  --> $DIR/regions-outlives-projection-container-hrtb.rs:32:12
+   |
+LL |     let _: &'a WithHrAssoc<TheType<'b>> = loop { };
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the pointer is valid for the lifetime 'a as defined on the function body at 29:15
+  --> $DIR/regions-outlives-projection-container-hrtb.rs:29:15
+   |
+LL | fn with_assoc<'a,'b>() {
+   |               ^^
+note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 29:18
+  --> $DIR/regions-outlives-projection-container-hrtb.rs:29:18
+   |
+LL | fn with_assoc<'a,'b>() {
+   |                  ^^
+
+error[E0491]: in type `&'a WithHrAssocSub<TheType<'b>>`, reference has a longer lifetime than the data it references
+  --> $DIR/regions-outlives-projection-container-hrtb.rs:53:12
+   |
+LL |     let _: &'a WithHrAssocSub<TheType<'b>> = loop { };
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the pointer is valid for the lifetime 'a as defined on the function body at 49:19
+  --> $DIR/regions-outlives-projection-container-hrtb.rs:49:19
+   |
+LL | fn with_assoc_sub<'a,'b>() {
+   |                   ^^
+note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 49:22
+  --> $DIR/regions-outlives-projection-container-hrtb.rs:49:22
+   |
+LL | fn with_assoc_sub<'a,'b>() {
+   |                      ^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0491`.
diff --git a/src/test/ui/regions/regions-outlives-projection-container-wc.ast.stderr b/src/test/ui/regions/regions-outlives-projection-container-wc.ast.stderr
new file mode 100644
index 0000000..9e31065
--- /dev/null
+++ b/src/test/ui/regions/regions-outlives-projection-container-wc.ast.stderr
@@ -0,0 +1,20 @@
+error[E0491]: in type `&'a WithAssoc<TheType<'b>>`, reference has a longer lifetime than the data it references
+  --> $DIR/regions-outlives-projection-container-wc.rs:37:12
+   |
+LL |     let _: &'a WithAssoc<TheType<'b>> = loop { };
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the pointer is valid for the lifetime 'a as defined on the function body at 31:15
+  --> $DIR/regions-outlives-projection-container-wc.rs:31:15
+   |
+LL | fn with_assoc<'a,'b>() {
+   |               ^^
+note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 31:18
+  --> $DIR/regions-outlives-projection-container-wc.rs:31:18
+   |
+LL | fn with_assoc<'a,'b>() {
+   |                  ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0491`.
diff --git a/src/test/ui/regions/regions-outlives-projection-container-wc.mir.stderr b/src/test/ui/regions/regions-outlives-projection-container-wc.mir.stderr
new file mode 100644
index 0000000..880fe17
--- /dev/null
+++ b/src/test/ui/regions/regions-outlives-projection-container-wc.mir.stderr
@@ -0,0 +1,13 @@
+error: lifetime may not live long enough
+  --> $DIR/regions-outlives-projection-container-wc.rs:37:12
+   |
+LL | fn with_assoc<'a,'b>() {
+   |               -- -- lifetime `'b` defined here
+   |               |
+   |               lifetime `'a` defined here
+...
+LL |     let _: &'a WithAssoc<TheType<'b>> = loop { };
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/regions/regions-outlives-projection-container-wc.rs b/src/test/ui/regions/regions-outlives-projection-container-wc.rs
new file mode 100644
index 0000000..3762221
--- /dev/null
+++ b/src/test/ui/regions/regions-outlives-projection-container-wc.rs
@@ -0,0 +1,43 @@
+// Test that we are imposing the requirement that every associated
+// type of a bound that appears in the where clause on a struct must
+// outlive the location in which the type appears, even when the
+// constraint is in a where clause not a bound. Issue #22246.
+
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+#![allow(dead_code)]
+
+///////////////////////////////////////////////////////////////////////////
+
+pub trait TheTrait {
+    type TheAssocType;
+}
+
+pub struct TheType<'b> {
+    m: [fn(&'b()); 0]
+}
+
+impl<'b> TheTrait for TheType<'b> {
+    type TheAssocType = &'b ();
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+pub struct WithAssoc<T> where T : TheTrait {
+    m: [T; 0]
+}
+
+fn with_assoc<'a,'b>() {
+    // For this type to be valid, the rules require that all
+    // associated types of traits that appear in `WithAssoc` must
+    // outlive 'a. In this case, that means TheType<'b>::TheAssocType,
+    // which is &'b (), must outlive 'a.
+
+    let _: &'a WithAssoc<TheType<'b>> = loop { };
+    //[ast]~^ ERROR reference has a longer lifetime
+    //[mir]~^^ ERROR lifetime may not live long enough
+}
+
+fn main() {
+}
diff --git a/src/test/ui/regions/regions-outlives-projection-container-wc.stderr b/src/test/ui/regions/regions-outlives-projection-container-wc.stderr
new file mode 100644
index 0000000..0d73d3d
--- /dev/null
+++ b/src/test/ui/regions/regions-outlives-projection-container-wc.stderr
@@ -0,0 +1,20 @@
+error[E0491]: in type `&'a WithAssoc<TheType<'b>>`, reference has a longer lifetime than the data it references
+  --> $DIR/regions-outlives-projection-container-wc.rs:34:12
+   |
+LL |     let _: &'a WithAssoc<TheType<'b>> = loop { };
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the pointer is valid for the lifetime 'a as defined on the function body at 28:15
+  --> $DIR/regions-outlives-projection-container-wc.rs:28:15
+   |
+LL | fn with_assoc<'a,'b>() {
+   |               ^^
+note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 28:18
+  --> $DIR/regions-outlives-projection-container-wc.rs:28:18
+   |
+LL | fn with_assoc<'a,'b>() {
+   |                  ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0491`.
diff --git a/src/test/ui/regions/regions-outlives-projection-container.rs b/src/test/ui/regions/regions-outlives-projection-container.rs
new file mode 100644
index 0000000..78305c0
--- /dev/null
+++ b/src/test/ui/regions/regions-outlives-projection-container.rs
@@ -0,0 +1,80 @@
+// Test that we are imposing the requirement that every associated
+// type of a bound that appears in the where clause on a struct must
+// outlive the location in which the type appears. Issue #22246.
+
+#![allow(dead_code)]
+#![feature(rustc_attrs)]
+
+///////////////////////////////////////////////////////////////////////////
+
+pub trait TheTrait {
+    type TheAssocType;
+}
+
+pub struct TheType<'b> {
+    m: [fn(&'b()); 0]
+}
+
+impl<'b> TheTrait for TheType<'b> {
+    type TheAssocType = &'b ();
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+pub struct WithAssoc<T:TheTrait> {
+    m: [T; 0]
+}
+
+pub struct WithoutAssoc<T> {
+    m: [T; 0]
+}
+
+fn with_assoc<'a,'b>() {
+    // For this type to be valid, the rules require that all
+    // associated types of traits that appear in `WithAssoc` must
+    // outlive 'a. In this case, that means TheType<'b>::TheAssocType,
+    // which is &'b (), must outlive 'a.
+
+    // FIXME (#54943) NLL doesn't enforce WF condition in unreachable code if
+    // `_x` is changed to `_`
+    let _x: &'a WithAssoc<TheType<'b>> = loop { };
+    //~^ ERROR reference has a longer lifetime
+}
+
+fn with_assoc1<'a,'b>() where 'b : 'a {
+    // For this type to be valid, the rules require that all
+    // associated types of traits that appear in `WithAssoc` must
+    // outlive 'a. In this case, that means TheType<'b>::TheAssocType,
+    // which is &'b (), must outlive 'a, so 'b : 'a must hold, and
+    // that is in the where clauses, so we're fine.
+
+    let _x: &'a WithAssoc<TheType<'b>> = loop { };
+}
+
+fn without_assoc<'a,'b>() {
+    // Here there are no associated types but there is a requirement
+    // that `'b:'a` holds because the `'b` appears in `TheType<'b>`.
+
+    let _x: &'a WithoutAssoc<TheType<'b>> = loop { };
+    //~^ ERROR reference has a longer lifetime
+}
+
+fn call_with_assoc<'a,'b>() {
+    // As `with_assoc`, but just checking that we impose the same rule
+    // on the value supplied for the type argument, even when there is
+    // no data.
+
+    call::<&'a WithAssoc<TheType<'b>>>();
+    //~^ ERROR reference has a longer lifetime
+}
+
+fn call_without_assoc<'a,'b>() {
+    // As `without_assoc`, but in a distinct scenario.
+
+    call::<&'a WithoutAssoc<TheType<'b>>>(); //~ ERROR reference has a longer lifetime
+}
+
+fn call<T>() { }
+
+fn main() {
+}
diff --git a/src/test/ui/regions/regions-outlives-projection-container.stderr b/src/test/ui/regions/regions-outlives-projection-container.stderr
new file mode 100644
index 0000000..b50347a
--- /dev/null
+++ b/src/test/ui/regions/regions-outlives-projection-container.stderr
@@ -0,0 +1,71 @@
+error[E0491]: in type `&'a WithAssoc<TheType<'b>>`, reference has a longer lifetime than the data it references
+  --> $DIR/regions-outlives-projection-container.rs:40:13
+   |
+LL |     let _x: &'a WithAssoc<TheType<'b>> = loop { };
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the pointer is valid for the lifetime 'a as defined on the function body at 32:15
+  --> $DIR/regions-outlives-projection-container.rs:32:15
+   |
+LL | fn with_assoc<'a,'b>() {
+   |               ^^
+note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 32:18
+  --> $DIR/regions-outlives-projection-container.rs:32:18
+   |
+LL | fn with_assoc<'a,'b>() {
+   |                  ^^
+
+error[E0491]: in type `&'a WithoutAssoc<TheType<'b>>`, reference has a longer lifetime than the data it references
+  --> $DIR/regions-outlives-projection-container.rs:58:13
+   |
+LL |     let _x: &'a WithoutAssoc<TheType<'b>> = loop { };
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the pointer is valid for the lifetime 'a as defined on the function body at 54:18
+  --> $DIR/regions-outlives-projection-container.rs:54:18
+   |
+LL | fn without_assoc<'a,'b>() {
+   |                  ^^
+note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 54:21
+  --> $DIR/regions-outlives-projection-container.rs:54:21
+   |
+LL | fn without_assoc<'a,'b>() {
+   |                     ^^
+
+error[E0491]: in type `&'a WithAssoc<TheType<'b>>`, reference has a longer lifetime than the data it references
+  --> $DIR/regions-outlives-projection-container.rs:67:12
+   |
+LL |     call::<&'a WithAssoc<TheType<'b>>>();
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the pointer is valid for the lifetime 'a as defined on the function body at 62:20
+  --> $DIR/regions-outlives-projection-container.rs:62:20
+   |
+LL | fn call_with_assoc<'a,'b>() {
+   |                    ^^
+note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 62:23
+  --> $DIR/regions-outlives-projection-container.rs:62:23
+   |
+LL | fn call_with_assoc<'a,'b>() {
+   |                       ^^
+
+error[E0491]: in type `&'a WithoutAssoc<TheType<'b>>`, reference has a longer lifetime than the data it references
+  --> $DIR/regions-outlives-projection-container.rs:74:12
+   |
+LL |     call::<&'a WithoutAssoc<TheType<'b>>>();
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the pointer is valid for the lifetime 'a as defined on the function body at 71:23
+  --> $DIR/regions-outlives-projection-container.rs:71:23
+   |
+LL | fn call_without_assoc<'a,'b>() {
+   |                       ^^
+note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 71:26
+  --> $DIR/regions-outlives-projection-container.rs:71:26
+   |
+LL | fn call_without_assoc<'a,'b>() {
+   |                          ^^
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0491`.
diff --git a/src/test/ui/regions/regions-outlives-projection-hrtype.rs b/src/test/ui/regions/regions-outlives-projection-hrtype.rs
new file mode 100644
index 0000000..a6e976e
--- /dev/null
+++ b/src/test/ui/regions/regions-outlives-projection-hrtype.rs
@@ -0,0 +1,26 @@
+// Test for the outlives relation when applied to a projection on a
+// type with bound regions. In this case, we are checking that
+// `<for<'r> fn(&'r T) as TheTrait>::TheType: 'a` If we're not
+// careful, we could wind up with a constraint that `'r:'a`, but since
+// `'r` is bound, that leads to badness. This test checks that
+// everything works.
+
+// compile-pass
+#![allow(dead_code)]
+
+trait TheTrait {
+    type TheType;
+}
+
+fn wf<T>() { }
+
+type FnType<T> = for<'r> fn(&'r T);
+
+fn foo<'a,'b,T>()
+    where FnType<T>: TheTrait
+{
+    wf::< <FnType<T> as TheTrait>::TheType >();
+}
+
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-outlives-projection-trait-def.rs b/src/test/ui/regions/regions-outlives-projection-trait-def.rs
new file mode 100644
index 0000000..bad476d
--- /dev/null
+++ b/src/test/ui/regions/regions-outlives-projection-trait-def.rs
@@ -0,0 +1,21 @@
+// Test that `<F as Foo<'a>>::Type: 'b`, where `trait Foo<'a> { Type:
+// 'a; }`, does not require that `F: 'b`.
+
+// compile-pass
+#![allow(dead_code)]
+
+trait SomeTrait<'a> {
+    type Type: 'a;
+}
+
+impl<'a: 'c, 'c, T> SomeTrait<'a> for &'c T where T: SomeTrait<'a> {
+    type Type = <T as SomeTrait<'a>>::Type;
+    //          ~~~~~~~~~~~~~~~~~~~~~~~~~~
+    //                       |
+    // Note that this type must outlive 'a, due to the trait
+    // definition.  If we fall back to OutlivesProjectionComponents
+    // here, then we would require that `T:'a`, which is too strong.
+}
+
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-outlives-scalar.rs b/src/test/ui/regions/regions-outlives-scalar.rs
new file mode 100644
index 0000000..ca012c4e
--- /dev/null
+++ b/src/test/ui/regions/regions-outlives-scalar.rs
@@ -0,0 +1,13 @@
+// Test that scalar values outlive all regions.
+// Rule OutlivesScalar from RFC 1214.
+
+// compile-pass
+#![allow(dead_code)]
+
+struct Foo<'a> {
+    x: &'a i32,
+    y: &'static i32
+}
+
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-pattern-typing-issue-19552.nll.stderr b/src/test/ui/regions/regions-pattern-typing-issue-19552.nll.stderr
new file mode 100644
index 0000000..f77d94a
--- /dev/null
+++ b/src/test/ui/regions/regions-pattern-typing-issue-19552.nll.stderr
@@ -0,0 +1,14 @@
+error[E0597]: `line` does not live long enough
+  --> $DIR/regions-pattern-typing-issue-19552.rs:5:14
+   |
+LL |     match [&*line] {
+   |              ^^^^ borrowed value does not live long enough
+LL |         [ word ] => { assert_static(word); }
+   |                       ------------------- argument requires that `line` is borrowed for `'static`
+LL |     }
+LL | }
+   | - `line` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/regions/regions-pattern-typing-issue-19552.rs b/src/test/ui/regions/regions-pattern-typing-issue-19552.rs
new file mode 100644
index 0000000..a64ab1c
--- /dev/null
+++ b/src/test/ui/regions/regions-pattern-typing-issue-19552.rs
@@ -0,0 +1,8 @@
+fn assert_static<T: 'static>(_t: T) {}
+
+fn main() {
+    let line = String::new();
+    match [&*line] { //~ ERROR `line` does not live long enough
+        [ word ] => { assert_static(word); }
+    }
+}
diff --git a/src/test/ui/regions/regions-pattern-typing-issue-19552.stderr b/src/test/ui/regions/regions-pattern-typing-issue-19552.stderr
new file mode 100644
index 0000000..3e3201d
--- /dev/null
+++ b/src/test/ui/regions/regions-pattern-typing-issue-19552.stderr
@@ -0,0 +1,14 @@
+error[E0597]: `line` does not live long enough
+  --> $DIR/regions-pattern-typing-issue-19552.rs:5:14
+   |
+LL |     match [&*line] {
+   |              ^^^^ borrowed value does not live long enough
+...
+LL | }
+   | - borrowed value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/regions/regions-pattern-typing-issue-19997.ast.nll.stderr b/src/test/ui/regions/regions-pattern-typing-issue-19997.ast.nll.stderr
new file mode 100644
index 0000000..b1c5878
--- /dev/null
+++ b/src/test/ui/regions/regions-pattern-typing-issue-19997.ast.nll.stderr
@@ -0,0 +1,15 @@
+error[E0506]: cannot assign to `a1` because it is borrowed
+  --> $DIR/regions-pattern-typing-issue-19997.rs:10:13
+   |
+LL |     match (&a1,) {
+   |            --- borrow of `a1` occurs here
+LL |         (&ref b0,) => {
+LL |             a1 = &f;
+   |             ^^^^^^^ assignment to borrowed `a1` occurs here
+LL |
+LL |             drop(b0);
+   |                  -- borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/regions/regions-pattern-typing-issue-19997.ast.stderr b/src/test/ui/regions/regions-pattern-typing-issue-19997.ast.stderr
new file mode 100644
index 0000000..0074d2b
--- /dev/null
+++ b/src/test/ui/regions/regions-pattern-typing-issue-19997.ast.stderr
@@ -0,0 +1,12 @@
+error[E0506]: cannot assign to `a1` because it is borrowed
+  --> $DIR/regions-pattern-typing-issue-19997.rs:10:13
+   |
+LL |     match (&a1,) {
+   |             -- borrow of `a1` occurs here
+LL |         (&ref b0,) => {
+LL |             a1 = &f;
+   |             ^^^^^^^ assignment to borrowed `a1` occurs here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/regions/regions-pattern-typing-issue-19997.mir.stderr b/src/test/ui/regions/regions-pattern-typing-issue-19997.mir.stderr
new file mode 100644
index 0000000..b1c5878
--- /dev/null
+++ b/src/test/ui/regions/regions-pattern-typing-issue-19997.mir.stderr
@@ -0,0 +1,15 @@
+error[E0506]: cannot assign to `a1` because it is borrowed
+  --> $DIR/regions-pattern-typing-issue-19997.rs:10:13
+   |
+LL |     match (&a1,) {
+   |            --- borrow of `a1` occurs here
+LL |         (&ref b0,) => {
+LL |             a1 = &f;
+   |             ^^^^^^^ assignment to borrowed `a1` occurs here
+LL |
+LL |             drop(b0);
+   |                  -- borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/regions/regions-pattern-typing-issue-19997.rs b/src/test/ui/regions/regions-pattern-typing-issue-19997.rs
new file mode 100644
index 0000000..35f38af
--- /dev/null
+++ b/src/test/ui/regions/regions-pattern-typing-issue-19997.rs
@@ -0,0 +1,15 @@
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+fn main() {
+    let a0 = 0;
+    let f = 1;
+    let mut a1 = &a0;
+    match (&a1,) {
+        (&ref b0,) => {
+            a1 = &f; //[ast]~ ERROR cannot assign
+            //[mir]~^ ERROR cannot assign to `a1` because it is borrowed
+            drop(b0);
+        }
+    }
+}
diff --git a/src/test/ui/regions/regions-proc-bound-capture.rs b/src/test/ui/regions/regions-proc-bound-capture.rs
new file mode 100644
index 0000000..f2010db
--- /dev/null
+++ b/src/test/ui/regions/regions-proc-bound-capture.rs
@@ -0,0 +1,12 @@
+fn borrowed_proc<'a>(x: &'a isize) -> Box<FnMut()->(isize) + 'a> {
+    // This is legal, because the region bound on `proc`
+    // states that it captures `x`.
+    Box::new(move|| { *x })
+}
+
+fn static_proc(x: &isize) -> Box<FnMut()->(isize) + 'static> {
+    // This is illegal, because the region bound on `proc` is 'static.
+    Box::new(move|| { *x }) //~ ERROR explicit lifetime required in the type of `x` [E0621]
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-proc-bound-capture.stderr b/src/test/ui/regions/regions-proc-bound-capture.stderr
new file mode 100644
index 0000000..aea7347
--- /dev/null
+++ b/src/test/ui/regions/regions-proc-bound-capture.stderr
@@ -0,0 +1,12 @@
+error[E0621]: explicit lifetime required in the type of `x`
+  --> $DIR/regions-proc-bound-capture.rs:9:5
+   |
+LL | fn static_proc(x: &isize) -> Box<FnMut()->(isize) + 'static> {
+   |                   ------ help: add explicit lifetime `'static` to the type of `x`: `&'static isize`
+LL |     // This is illegal, because the region bound on `proc` is 'static.
+LL |     Box::new(move|| { *x })
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ lifetime `'static` required
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/regions/regions-reborrow-from-shorter-mut-ref-mut-ref.rs b/src/test/ui/regions/regions-reborrow-from-shorter-mut-ref-mut-ref.rs
new file mode 100644
index 0000000..35aca8b
--- /dev/null
+++ b/src/test/ui/regions/regions-reborrow-from-shorter-mut-ref-mut-ref.rs
@@ -0,0 +1,8 @@
+// Issue #8624. Test for reborrowing with 3 levels, not just two.
+
+fn copy_borrowed_ptr<'a, 'b, 'c>(p: &'a mut &'b mut &'c mut isize) -> &'b mut isize {
+    &mut ***p //~ ERROR lifetime mismatch [E0623]
+}
+
+fn main() {
+}
diff --git a/src/test/ui/regions/regions-reborrow-from-shorter-mut-ref-mut-ref.stderr b/src/test/ui/regions/regions-reborrow-from-shorter-mut-ref-mut-ref.stderr
new file mode 100644
index 0000000..aca3a1e
--- /dev/null
+++ b/src/test/ui/regions/regions-reborrow-from-shorter-mut-ref-mut-ref.stderr
@@ -0,0 +1,13 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/regions-reborrow-from-shorter-mut-ref-mut-ref.rs:4:5
+   |
+LL | fn copy_borrowed_ptr<'a, 'b, 'c>(p: &'a mut &'b mut &'c mut isize) -> &'b mut isize {
+   |                                     -----------------------------     -------------
+   |                                     |
+   |                                     this parameter and the return type are declared with different lifetimes...
+LL |     &mut ***p
+   |     ^^^^^^^^^ ...but data from `p` is returned here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/regions/regions-reborrow-from-shorter-mut-ref.rs b/src/test/ui/regions/regions-reborrow-from-shorter-mut-ref.rs
new file mode 100644
index 0000000..77041ab
--- /dev/null
+++ b/src/test/ui/regions/regions-reborrow-from-shorter-mut-ref.rs
@@ -0,0 +1,15 @@
+// Issue #8624. Tests that reborrowing the contents of an `&'b mut`
+// pointer which is backed by another `&'a mut` can only be done
+// for `'a` (which must be a sublifetime of `'b`).
+
+fn copy_borrowed_ptr<'a, 'b>(p: &'a mut &'b mut isize) -> &'b mut isize {
+    &mut **p //~ ERROR lifetime mismatch [E0623]
+}
+
+fn main() {
+    let mut x = 1;
+    let mut y = &mut x;
+    let z = copy_borrowed_ptr(&mut y);
+    *y += 1;
+    *z += 1;
+}
diff --git a/src/test/ui/regions/regions-reborrow-from-shorter-mut-ref.stderr b/src/test/ui/regions/regions-reborrow-from-shorter-mut-ref.stderr
new file mode 100644
index 0000000..a9916db
--- /dev/null
+++ b/src/test/ui/regions/regions-reborrow-from-shorter-mut-ref.stderr
@@ -0,0 +1,13 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/regions-reborrow-from-shorter-mut-ref.rs:6:5
+   |
+LL | fn copy_borrowed_ptr<'a, 'b>(p: &'a mut &'b mut isize) -> &'b mut isize {
+   |                                 ---------------------     -------------
+   |                                 |
+   |                                 this parameter and the return type are declared with different lifetimes...
+LL |     &mut **p
+   |     ^^^^^^^^ ...but data from `p` is returned here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/regions/regions-ref-in-fn-arg.nll.stderr b/src/test/ui/regions/regions-ref-in-fn-arg.nll.stderr
new file mode 100644
index 0000000..ccba6c59
--- /dev/null
+++ b/src/test/ui/regions/regions-ref-in-fn-arg.nll.stderr
@@ -0,0 +1,19 @@
+error[E0515]: cannot return value referencing function parameter
+  --> $DIR/regions-ref-in-fn-arg.rs:5:5
+   |
+LL | fn arg_item(box ref x: Box<isize>) -> &'static isize {
+   |             --------- function parameter borrowed here
+LL |     x
+   |     ^ returns a value referencing data owned by the current function
+
+error[E0515]: cannot return value referencing function parameter
+  --> $DIR/regions-ref-in-fn-arg.rs:11:22
+   |
+LL |     with(|box ref x| x)
+   |           ---------  ^ returns a value referencing data owned by the current function
+   |           |
+   |           function parameter borrowed here
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/src/test/ui/regions/regions-ref-in-fn-arg.rs b/src/test/ui/regions/regions-ref-in-fn-arg.rs
new file mode 100644
index 0000000..cf9e7b2
--- /dev/null
+++ b/src/test/ui/regions/regions-ref-in-fn-arg.rs
@@ -0,0 +1,14 @@
+#![feature(box_patterns)]
+#![feature(box_syntax)]
+
+fn arg_item(box ref x: Box<isize>) -> &'static isize {
+    x //~^ ERROR borrowed value does not live long enough
+}
+
+fn with<R, F>(f: F) -> R where F: FnOnce(Box<isize>) -> R { f(box 3) }
+
+fn arg_closure() -> &'static isize {
+    with(|box ref x| x) //~ ERROR borrowed value does not live long enough
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-ref-in-fn-arg.stderr b/src/test/ui/regions/regions-ref-in-fn-arg.stderr
new file mode 100644
index 0000000..9ecd327
--- /dev/null
+++ b/src/test/ui/regions/regions-ref-in-fn-arg.stderr
@@ -0,0 +1,24 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/regions-ref-in-fn-arg.rs:4:17
+   |
+LL | fn arg_item(box ref x: Box<isize>) -> &'static isize {
+   |                 ^^^^^ borrowed value does not live long enough
+LL |     x
+LL | }
+   | - borrowed value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/regions-ref-in-fn-arg.rs:11:15
+   |
+LL |     with(|box ref x| x)
+   |               ^^^^^  - borrowed value only lives until here
+   |               |
+   |               borrowed value does not live long enough
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/regions/regions-ret-borrowed-1.rs b/src/test/ui/regions/regions-ret-borrowed-1.rs
new file mode 100644
index 0000000..1be5ede
--- /dev/null
+++ b/src/test/ui/regions/regions-ret-borrowed-1.rs
@@ -0,0 +1,17 @@
+// Similar to regions-ret-borrowed.rs, but using a named lifetime.  At
+// some point regions-ret-borrowed reported an error but this file did
+// not, due to special hardcoding around the anonymous region.
+
+fn with<R, F>(f: F) -> R where F: for<'a> FnOnce(&'a isize) -> R {
+    f(&3)
+}
+
+fn return_it<'a>() -> &'a isize {
+    with(|o| o)
+        //~^ ERROR cannot infer
+}
+
+fn main() {
+    let x = return_it();
+    println!("foo={}", *x);
+}
diff --git a/src/test/ui/regions/regions-ret-borrowed-1.stderr b/src/test/ui/regions/regions-ret-borrowed-1.stderr
new file mode 100644
index 0000000..72e47ce
--- /dev/null
+++ b/src/test/ui/regions/regions-ret-borrowed-1.stderr
@@ -0,0 +1,28 @@
+error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
+  --> $DIR/regions-ret-borrowed-1.rs:10:14
+   |
+LL |     with(|o| o)
+   |              ^
+   |
+note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the body at 10:10...
+  --> $DIR/regions-ret-borrowed-1.rs:10:10
+   |
+LL |     with(|o| o)
+   |          ^^^^^
+   = note: ...so that the expression is assignable:
+           expected &isize
+              found &isize
+note: but, the lifetime must be valid for the lifetime 'a as defined on the function body at 9:14...
+  --> $DIR/regions-ret-borrowed-1.rs:9:14
+   |
+LL | fn return_it<'a>() -> &'a isize {
+   |              ^^
+note: ...so that reference does not outlive borrowed content
+  --> $DIR/regions-ret-borrowed-1.rs:10:5
+   |
+LL |     with(|o| o)
+   |     ^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0495`.
diff --git a/src/test/ui/regions/regions-ret-borrowed.rs b/src/test/ui/regions/regions-ret-borrowed.rs
new file mode 100644
index 0000000..5fca92d
--- /dev/null
+++ b/src/test/ui/regions/regions-ret-borrowed.rs
@@ -0,0 +1,20 @@
+// Ensure that you cannot use generic types to return a region outside
+// of its bound.  Here, in the `return_it()` fn, we call with() but
+// with R bound to &isize from the return_it.  Meanwhile, with()
+// provides a value that is only good within its own stack frame. This
+// used to successfully compile because we failed to account for the
+// fact that fn(x: &isize) rebound the region &.
+
+fn with<R, F>(f: F) -> R where F: FnOnce(&isize) -> R {
+    f(&3)
+}
+
+fn return_it<'a>() -> &'a isize {
+    with(|o| o)
+        //~^ ERROR cannot infer
+}
+
+fn main() {
+    let x = return_it();
+    println!("foo={}", *x);
+}
diff --git a/src/test/ui/regions/regions-ret-borrowed.stderr b/src/test/ui/regions/regions-ret-borrowed.stderr
new file mode 100644
index 0000000..ce0c429
--- /dev/null
+++ b/src/test/ui/regions/regions-ret-borrowed.stderr
@@ -0,0 +1,28 @@
+error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
+  --> $DIR/regions-ret-borrowed.rs:13:14
+   |
+LL |     with(|o| o)
+   |              ^
+   |
+note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the body at 13:10...
+  --> $DIR/regions-ret-borrowed.rs:13:10
+   |
+LL |     with(|o| o)
+   |          ^^^^^
+   = note: ...so that the expression is assignable:
+           expected &isize
+              found &isize
+note: but, the lifetime must be valid for the lifetime 'a as defined on the function body at 12:14...
+  --> $DIR/regions-ret-borrowed.rs:12:14
+   |
+LL | fn return_it<'a>() -> &'a isize {
+   |              ^^
+note: ...so that reference does not outlive borrowed content
+  --> $DIR/regions-ret-borrowed.rs:13:5
+   |
+LL |     with(|o| o)
+   |     ^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0495`.
diff --git a/src/test/ui/regions/regions-ret.nll.stderr b/src/test/ui/regions/regions-ret.nll.stderr
new file mode 100644
index 0000000..0e4875a
--- /dev/null
+++ b/src/test/ui/regions/regions-ret.nll.stderr
@@ -0,0 +1,12 @@
+error[E0515]: cannot return reference to temporary value
+  --> $DIR/regions-ret.rs:4:12
+   |
+LL |     return &id(3);
+   |            ^-----
+   |            ||
+   |            |temporary value created here
+   |            returns a reference to data owned by the current function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/src/test/ui/regions/regions-ret.rs b/src/test/ui/regions/regions-ret.rs
new file mode 100644
index 0000000..a094d1a
--- /dev/null
+++ b/src/test/ui/regions/regions-ret.rs
@@ -0,0 +1,8 @@
+fn id<T>(x: T) -> T { x }
+
+fn f(_x: &isize) -> &isize {
+    return &id(3); //~ ERROR borrowed value does not live long enough
+}
+
+fn main() {
+}
diff --git a/src/test/ui/regions/regions-ret.stderr b/src/test/ui/regions/regions-ret.stderr
new file mode 100644
index 0000000..77820a3
--- /dev/null
+++ b/src/test/ui/regions/regions-ret.stderr
@@ -0,0 +1,20 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/regions-ret.rs:4:13
+   |
+LL |     return &id(3);
+   |             ^^^^^- temporary value only lives until here
+   |             |
+   |             temporary value does not live long enough
+   |
+note: borrowed value must be valid for the anonymous lifetime #1 defined on the function body at 3:1...
+  --> $DIR/regions-ret.rs:3:1
+   |
+LL | / fn f(_x: &isize) -> &isize {
+LL | |     return &id(3);
+LL | | }
+   | |_^
+   = note: consider using a `let` binding to increase its lifetime
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.rs b/src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.rs
new file mode 100644
index 0000000..afe87f4
--- /dev/null
+++ b/src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.rs
@@ -0,0 +1,11 @@
+// Test that closures cannot subvert aliasing restrictions
+
+fn main() {
+    // Unboxed closure case
+    {
+        let mut x = 0;
+        let mut f = || &mut x; //~ ERROR cannot infer
+        let x = f();
+        let y = f();
+    }
+}
diff --git a/src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.stderr b/src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.stderr
new file mode 100644
index 0000000..be441bc
--- /dev/null
+++ b/src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.stderr
@@ -0,0 +1,30 @@
+error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
+  --> $DIR/regions-return-ref-to-upvar-issue-17403.rs:7:24
+   |
+LL |         let mut f = || &mut x;
+   |                        ^^^^^^
+   |
+note: first, the lifetime cannot outlive the lifetime '_ as defined on the body at 7:21...
+  --> $DIR/regions-return-ref-to-upvar-issue-17403.rs:7:21
+   |
+LL |         let mut f = || &mut x;
+   |                     ^^^^^^^^^
+note: ...so that closure can access `x`
+  --> $DIR/regions-return-ref-to-upvar-issue-17403.rs:7:24
+   |
+LL |         let mut f = || &mut x;
+   |                        ^^^^^^
+note: but, the lifetime must be valid for the call at 9:17...
+  --> $DIR/regions-return-ref-to-upvar-issue-17403.rs:9:17
+   |
+LL |         let y = f();
+   |                 ^^^
+note: ...so type `&mut i32` of expression is valid during the expression
+  --> $DIR/regions-return-ref-to-upvar-issue-17403.rs:9:17
+   |
+LL |         let y = f();
+   |                 ^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0495`.
diff --git a/src/test/ui/regions/regions-return-stack-allocated-vec.nll.stderr b/src/test/ui/regions/regions-return-stack-allocated-vec.nll.stderr
new file mode 100644
index 0000000..9d87fe2
--- /dev/null
+++ b/src/test/ui/regions/regions-return-stack-allocated-vec.nll.stderr
@@ -0,0 +1,12 @@
+error[E0515]: cannot return reference to temporary value
+  --> $DIR/regions-return-stack-allocated-vec.rs:4:5
+   |
+LL |     &[x]
+   |     ^---
+   |     ||
+   |     |temporary value created here
+   |     returns a reference to data owned by the current function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/src/test/ui/regions/regions-return-stack-allocated-vec.rs b/src/test/ui/regions/regions-return-stack-allocated-vec.rs
new file mode 100644
index 0000000..8d071db
--- /dev/null
+++ b/src/test/ui/regions/regions-return-stack-allocated-vec.rs
@@ -0,0 +1,10 @@
+// Test that we cannot return a stack allocated slice
+
+fn function(x: isize) -> &'static [isize] {
+    &[x] //~ ERROR borrowed value does not live long enough
+}
+
+fn main() {
+    let x = function(1);
+    let y = x[0];
+}
diff --git a/src/test/ui/regions/regions-return-stack-allocated-vec.stderr b/src/test/ui/regions/regions-return-stack-allocated-vec.stderr
new file mode 100644
index 0000000..3256294
--- /dev/null
+++ b/src/test/ui/regions/regions-return-stack-allocated-vec.stderr
@@ -0,0 +1,13 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/regions-return-stack-allocated-vec.rs:4:6
+   |
+LL |     &[x]
+   |      ^^^ temporary value does not live long enough
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/regions/regions-static-bound.ll.stderr b/src/test/ui/regions/regions-static-bound.ll.stderr
new file mode 100644
index 0000000..d0dc554
--- /dev/null
+++ b/src/test/ui/regions/regions-static-bound.ll.stderr
@@ -0,0 +1,34 @@
+error[E0312]: lifetime of reference outlives lifetime of borrowed content...
+  --> $DIR/regions-static-bound.rs:9:5
+   |
+LL |     t
+   |     ^
+   |
+   = note: ...the reference is valid for the static lifetime...
+note: ...but the borrowed content is only valid for the lifetime 'a as defined on the function body at 8:24
+  --> $DIR/regions-static-bound.rs:8:24
+   |
+LL | fn static_id_wrong_way<'a>(t: &'a ()) -> &'static () where 'static: 'a {
+   |                        ^^
+
+error[E0621]: explicit lifetime required in the type of `u`
+  --> $DIR/regions-static-bound.rs:14:5
+   |
+LL | fn error(u: &(), v: &()) {
+   |             --- help: add explicit lifetime `'static` to the type of `u`: `&'static ()`
+LL |     static_id(&u);
+   |     ^^^^^^^^^ lifetime `'static` required
+
+error[E0621]: explicit lifetime required in the type of `v`
+  --> $DIR/regions-static-bound.rs:16:5
+   |
+LL | fn error(u: &(), v: &()) {
+   |                     --- help: add explicit lifetime `'static` to the type of `v`: `&'static ()`
+...
+LL |     static_id_indirect(&v);
+   |     ^^^^^^^^^^^^^^^^^^ lifetime `'static` required
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0312, E0621.
+For more information about an error, try `rustc --explain E0312`.
diff --git a/src/test/ui/regions/regions-static-bound.nll.stderr b/src/test/ui/regions/regions-static-bound.nll.stderr
new file mode 100644
index 0000000..b5f3e6c
--- /dev/null
+++ b/src/test/ui/regions/regions-static-bound.nll.stderr
@@ -0,0 +1,28 @@
+error: lifetime may not live long enough
+  --> $DIR/regions-static-bound.rs:9:5
+   |
+LL | fn static_id_wrong_way<'a>(t: &'a ()) -> &'static () where 'static: 'a {
+   |                        -- lifetime `'a` defined here
+LL |     t
+   |     ^ returning this value requires that `'a` must outlive `'static`
+
+error[E0621]: explicit lifetime required in the type of `u`
+  --> $DIR/regions-static-bound.rs:14:5
+   |
+LL | fn error(u: &(), v: &()) {
+   |             --- help: add explicit lifetime `'static` to the type of `u`: `&'static ()`
+LL |     static_id(&u);
+   |     ^^^^^^^^^^^^^ lifetime `'static` required
+
+error[E0621]: explicit lifetime required in the type of `v`
+  --> $DIR/regions-static-bound.rs:16:5
+   |
+LL | fn error(u: &(), v: &()) {
+   |                     --- help: add explicit lifetime `'static` to the type of `v`: `&'static ()`
+...
+LL |     static_id_indirect(&v);
+   |     ^^^^^^^^^^^^^^^^^^^^^^ lifetime `'static` required
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/regions/regions-static-bound.rs b/src/test/ui/regions/regions-static-bound.rs
new file mode 100644
index 0000000..c1a15e5
--- /dev/null
+++ b/src/test/ui/regions/regions-static-bound.rs
@@ -0,0 +1,20 @@
+// revisions: ll nll
+//[nll] compile-flags:-Zborrowck=mir
+
+fn static_id<'a,'b>(t: &'a ()) -> &'static ()
+    where 'a: 'static { t }
+fn static_id_indirect<'a,'b>(t: &'a ()) -> &'static ()
+    where 'a: 'b, 'b: 'static { t }
+fn static_id_wrong_way<'a>(t: &'a ()) -> &'static () where 'static: 'a {
+    t //[ll]~ ERROR E0312
+        //[nll]~^ ERROR lifetime may not live long enough
+}
+
+fn error(u: &(), v: &()) {
+    static_id(&u); //[ll]~ ERROR explicit lifetime required in the type of `u` [E0621]
+    //[nll]~^ ERROR explicit lifetime required in the type of `u` [E0621]
+    static_id_indirect(&v); //[ll]~ ERROR explicit lifetime required in the type of `v` [E0621]
+    //[nll]~^ ERROR explicit lifetime required in the type of `v` [E0621]
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-steal-closure.nll.stderr b/src/test/ui/regions/regions-steal-closure.nll.stderr
new file mode 100644
index 0000000..5b0efaf
--- /dev/null
+++ b/src/test/ui/regions/regions-steal-closure.nll.stderr
@@ -0,0 +1,16 @@
+error[E0597]: `i` does not live long enough
+  --> $DIR/regions-steal-closure.rs:14:28
+   |
+LL |     let mut cl_box = {
+   |         ---------- borrow later stored here
+LL |         let mut i = 3;
+LL |         box_it(Box::new(|| i += 1))
+   |                         -- ^ borrowed value does not live long enough
+   |                         |
+   |                         value captured here
+LL |     };
+   |     - `i` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/regions/regions-steal-closure.rs b/src/test/ui/regions/regions-steal-closure.rs
new file mode 100644
index 0000000..e6b3451
--- /dev/null
+++ b/src/test/ui/regions/regions-steal-closure.rs
@@ -0,0 +1,17 @@
+#![feature(fn_traits)]
+
+struct ClosureBox<'a> {
+    cl: Box<FnMut() + 'a>,
+}
+
+fn box_it<'r>(x: Box<FnMut() + 'r>) -> ClosureBox<'r> {
+    ClosureBox {cl: x}
+}
+
+fn main() {
+    let mut cl_box = {
+        let mut i = 3;
+        box_it(Box::new(|| i += 1)) //~ ERROR `i` does not live long enough
+    };
+    cl_box.cl.call_mut(());
+}
diff --git a/src/test/ui/regions/regions-steal-closure.stderr b/src/test/ui/regions/regions-steal-closure.stderr
new file mode 100644
index 0000000..8cfd5b5
--- /dev/null
+++ b/src/test/ui/regions/regions-steal-closure.stderr
@@ -0,0 +1,16 @@
+error[E0597]: `i` does not live long enough
+  --> $DIR/regions-steal-closure.rs:14:28
+   |
+LL |         box_it(Box::new(|| i += 1))
+   |                         -- ^ borrowed value does not live long enough
+   |                         |
+   |                         capture occurs here
+LL |     };
+   |     - borrowed value only lives until here
+LL |     cl_box.cl.call_mut(());
+LL | }
+   | - borrowed value needs to live until here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/regions/regions-trait-1.rs b/src/test/ui/regions/regions-trait-1.rs
new file mode 100644
index 0000000..7273887
--- /dev/null
+++ b/src/test/ui/regions/regions-trait-1.rs
@@ -0,0 +1,30 @@
+#![feature(box_syntax)]
+
+struct Ctxt { v: usize }
+
+trait GetCtxt {
+    // Here the `&` is bound in the method definition:
+    fn get_ctxt(&self) -> &Ctxt;
+}
+
+struct HasCtxt<'a> { c: &'a Ctxt }
+
+impl<'a> GetCtxt for HasCtxt<'a> {
+
+    // Here an error occurs because we used `&self` but
+    // the definition used `&`:
+    fn get_ctxt(&self) -> &'a Ctxt { //~ ERROR method not compatible with trait
+        self.c
+    }
+
+}
+
+fn get_v(gc: Box<GetCtxt>) -> usize {
+    gc.get_ctxt().v
+}
+
+fn main() {
+    let ctxt = Ctxt { v: 22 };
+    let hc = HasCtxt { c: &ctxt };
+    assert_eq!(get_v(box hc as Box<GetCtxt>), 22);
+}
diff --git a/src/test/ui/regions/regions-trait-1.stderr b/src/test/ui/regions/regions-trait-1.stderr
new file mode 100644
index 0000000..421f826
--- /dev/null
+++ b/src/test/ui/regions/regions-trait-1.stderr
@@ -0,0 +1,24 @@
+error[E0308]: method not compatible with trait
+  --> $DIR/regions-trait-1.rs:16:5
+   |
+LL |     fn get_ctxt(&self) -> &'a Ctxt {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
+   |
+   = note: expected type `fn(&HasCtxt<'a>) -> &Ctxt`
+              found type `fn(&HasCtxt<'a>) -> &'a Ctxt`
+note: the lifetime 'a as defined on the impl at 12:6...
+  --> $DIR/regions-trait-1.rs:12:6
+   |
+LL | impl<'a> GetCtxt for HasCtxt<'a> {
+   |      ^^
+note: ...does not necessarily outlive the anonymous lifetime #1 defined on the method body at 16:5
+  --> $DIR/regions-trait-1.rs:16:5
+   |
+LL | /     fn get_ctxt(&self) -> &'a Ctxt {
+LL | |         self.c
+LL | |     }
+   | |_____^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/regions/regions-trait-object-subtyping.rs b/src/test/ui/regions/regions-trait-object-subtyping.rs
new file mode 100644
index 0000000..eb26235
--- /dev/null
+++ b/src/test/ui/regions/regions-trait-object-subtyping.rs
@@ -0,0 +1,25 @@
+trait Dummy { fn dummy(&self); }
+
+fn foo1<'a:'b,'b>(x: &'a mut (Dummy+'a)) -> &'b mut (Dummy+'b) {
+    // Here, we are able to coerce
+    x
+}
+
+fn foo2<'a:'b,'b>(x: &'b mut (Dummy+'a)) -> &'b mut (Dummy+'b) {
+    // Here, we are able to coerce
+    x
+}
+
+fn foo3<'a,'b>(x: &'a mut Dummy) -> &'b mut Dummy {
+    // Without knowing 'a:'b, we can't coerce
+    x //~ ERROR lifetime bound not satisfied
+     //~^ ERROR cannot infer an appropriate lifetime
+}
+
+struct Wrapper<T>(T);
+fn foo4<'a:'b,'b>(x: Wrapper<&'a mut Dummy>) -> Wrapper<&'b mut Dummy> {
+    // We can't coerce because it is packed in `Wrapper`
+    x //~ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-trait-object-subtyping.stderr b/src/test/ui/regions/regions-trait-object-subtyping.stderr
new file mode 100644
index 0000000..3b30ddd
--- /dev/null
+++ b/src/test/ui/regions/regions-trait-object-subtyping.stderr
@@ -0,0 +1,65 @@
+error[E0478]: lifetime bound not satisfied
+  --> $DIR/regions-trait-object-subtyping.rs:15:5
+   |
+LL |     x
+   |     ^
+   |
+note: lifetime parameter instantiated with the lifetime 'a as defined on the function body at 13:9
+  --> $DIR/regions-trait-object-subtyping.rs:13:9
+   |
+LL | fn foo3<'a,'b>(x: &'a mut Dummy) -> &'b mut Dummy {
+   |         ^^
+note: but lifetime parameter must outlive the lifetime 'b as defined on the function body at 13:12
+  --> $DIR/regions-trait-object-subtyping.rs:13:12
+   |
+LL | fn foo3<'a,'b>(x: &'a mut Dummy) -> &'b mut Dummy {
+   |            ^^
+
+error[E0495]: cannot infer an appropriate lifetime for automatic coercion due to conflicting requirements
+  --> $DIR/regions-trait-object-subtyping.rs:15:5
+   |
+LL |     x
+   |     ^
+   |
+note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 13:9...
+  --> $DIR/regions-trait-object-subtyping.rs:13:9
+   |
+LL | fn foo3<'a,'b>(x: &'a mut Dummy) -> &'b mut Dummy {
+   |         ^^
+note: ...so that reference does not outlive borrowed content
+  --> $DIR/regions-trait-object-subtyping.rs:15:5
+   |
+LL |     x
+   |     ^
+note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 13:12...
+  --> $DIR/regions-trait-object-subtyping.rs:13:12
+   |
+LL | fn foo3<'a,'b>(x: &'a mut Dummy) -> &'b mut Dummy {
+   |            ^^
+   = note: ...so that the expression is assignable:
+           expected &'b mut (dyn Dummy + 'b)
+              found &mut (dyn Dummy + 'b)
+
+error[E0308]: mismatched types
+  --> $DIR/regions-trait-object-subtyping.rs:22:5
+   |
+LL |     x
+   |     ^ lifetime mismatch
+   |
+   = note: expected type `Wrapper<&'b mut (dyn Dummy + 'b)>`
+              found type `Wrapper<&'a mut (dyn Dummy + 'a)>`
+note: the lifetime 'b as defined on the function body at 20:15...
+  --> $DIR/regions-trait-object-subtyping.rs:20:15
+   |
+LL | fn foo4<'a:'b,'b>(x: Wrapper<&'a mut Dummy>) -> Wrapper<&'b mut Dummy> {
+   |               ^^
+note: ...does not necessarily outlive the lifetime 'a as defined on the function body at 20:9
+  --> $DIR/regions-trait-object-subtyping.rs:20:9
+   |
+LL | fn foo4<'a:'b,'b>(x: Wrapper<&'a mut Dummy>) -> Wrapper<&'b mut Dummy> {
+   |         ^^
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0308, E0478, E0495.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/regions/regions-trait-variance.nll.stderr b/src/test/ui/regions/regions-trait-variance.nll.stderr
new file mode 100644
index 0000000..56c9f89
--- /dev/null
+++ b/src/test/ui/regions/regions-trait-variance.nll.stderr
@@ -0,0 +1,11 @@
+error[E0515]: cannot return value referencing local data `*b`
+  --> $DIR/regions-trait-variance.rs:38:5
+   |
+LL |     let bb: &B = &*b;
+   |                  --- `*b` is borrowed here
+LL |     make_a(bb)
+   |     ^^^^^^^^^^ returns a value referencing data owned by the current function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/src/test/ui/regions/regions-trait-variance.rs b/src/test/ui/regions/regions-trait-variance.rs
new file mode 100644
index 0000000..d5462b2
--- /dev/null
+++ b/src/test/ui/regions/regions-trait-variance.rs
@@ -0,0 +1,44 @@
+#![feature(box_syntax)]
+
+// Issue #12470.
+
+trait X {
+    fn get_i(&self) -> isize;
+}
+
+struct B {
+    i: isize
+}
+
+impl X for B {
+    fn get_i(&self) -> isize {
+        self.i
+    }
+}
+
+impl Drop for B {
+    fn drop(&mut self) {
+        println!("drop");
+    }
+}
+
+struct A<'r> {
+    p: &'r (X+'r)
+}
+
+fn make_a(p:&X) -> A {
+    A{p:p}
+}
+
+fn make_make_a<'a>() -> A<'a> {
+    let b: Box<B> = box B {
+        i: 1,
+    };
+    let bb: &B = &*b; //~ ERROR `*b` does not live long enough
+    make_a(bb)
+}
+
+fn main() {
+    let a = make_make_a();
+    println!("{}", a.p.get_i());
+}
diff --git a/src/test/ui/regions/regions-trait-variance.stderr b/src/test/ui/regions/regions-trait-variance.stderr
new file mode 100644
index 0000000..32c89b8
--- /dev/null
+++ b/src/test/ui/regions/regions-trait-variance.stderr
@@ -0,0 +1,18 @@
+error[E0597]: `*b` does not live long enough
+  --> $DIR/regions-trait-variance.rs:37:19
+   |
+LL |     let bb: &B = &*b;
+   |                   ^^ borrowed value does not live long enough
+LL |     make_a(bb)
+LL | }
+   | - borrowed value only lives until here
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 33:16...
+  --> $DIR/regions-trait-variance.rs:33:16
+   |
+LL | fn make_make_a<'a>() -> A<'a> {
+   |                ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/regions/regions-undeclared.rs b/src/test/ui/regions/regions-undeclared.rs
new file mode 100644
index 0000000..1edd998
--- /dev/null
+++ b/src/test/ui/regions/regions-undeclared.rs
@@ -0,0 +1,13 @@
+static c_x: &'blk isize = &22; //~ ERROR use of undeclared lifetime name `'blk`
+
+enum EnumDecl {
+    Foo(&'a isize), //~ ERROR use of undeclared lifetime name `'a`
+    Bar(&'a isize), //~ ERROR use of undeclared lifetime name `'a`
+}
+
+fn fnDecl(x: &'a isize, //~ ERROR use of undeclared lifetime name `'a`
+          y: &'a isize) //~ ERROR use of undeclared lifetime name `'a`
+{}
+
+fn main() {
+}
diff --git a/src/test/ui/regions/regions-undeclared.stderr b/src/test/ui/regions/regions-undeclared.stderr
new file mode 100644
index 0000000..495aec3
--- /dev/null
+++ b/src/test/ui/regions/regions-undeclared.stderr
@@ -0,0 +1,33 @@
+error[E0261]: use of undeclared lifetime name `'blk`
+  --> $DIR/regions-undeclared.rs:1:14
+   |
+LL | static c_x: &'blk isize = &22;
+   |              ^^^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/regions-undeclared.rs:4:10
+   |
+LL |     Foo(&'a isize),
+   |          ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/regions-undeclared.rs:5:10
+   |
+LL |     Bar(&'a isize),
+   |          ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/regions-undeclared.rs:8:15
+   |
+LL | fn fnDecl(x: &'a isize,
+   |               ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/regions-undeclared.rs:9:15
+   |
+LL |           y: &'a isize)
+   |               ^^ undeclared lifetime
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0261`.
diff --git a/src/test/ui/regions/regions-var-type-out-of-scope.nll.stderr b/src/test/ui/regions/regions-var-type-out-of-scope.nll.stderr
new file mode 100644
index 0000000..146fb8f
--- /dev/null
+++ b/src/test/ui/regions/regions-var-type-out-of-scope.nll.stderr
@@ -0,0 +1,16 @@
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/regions-var-type-out-of-scope.rs:9:14
+   |
+LL |         x = &id(3);
+   |              ^^^^^- temporary value is freed at the end of this statement
+   |              |
+   |              creates a temporary which is freed while still in use
+LL |         assert_eq!(*x, 3);
+   |         ------------------ borrow later used here
+   |
+   = note: consider using a `let` binding to create a longer lived value
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/src/test/ui/regions/regions-var-type-out-of-scope.rs b/src/test/ui/regions/regions-var-type-out-of-scope.rs
new file mode 100644
index 0000000..e972163
--- /dev/null
+++ b/src/test/ui/regions/regions-var-type-out-of-scope.rs
@@ -0,0 +1,14 @@
+fn id<T>(x: T) -> T { x }
+
+fn foo(cond: bool) {
+    // Here we will infer a type that uses the
+    // region of the if stmt then block:
+    let mut x;
+
+    if cond {
+        x = &id(3); //~ ERROR borrowed value does not live long enough
+        assert_eq!(*x, 3);
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-var-type-out-of-scope.stderr b/src/test/ui/regions/regions-var-type-out-of-scope.stderr
new file mode 100644
index 0000000..0363fe0
--- /dev/null
+++ b/src/test/ui/regions/regions-var-type-out-of-scope.stderr
@@ -0,0 +1,16 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/regions-var-type-out-of-scope.rs:9:14
+   |
+LL |         x = &id(3);
+   |              ^^^^^- temporary value dropped here while still borrowed
+   |              |
+   |              temporary value does not live long enough
+...
+LL | }
+   | - temporary value needs to live until here
+   |
+   = note: consider using a `let` binding to increase its lifetime
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/regions/regions-variance-contravariant-use-covariant-in-second-position.rs b/src/test/ui/regions/regions-variance-contravariant-use-covariant-in-second-position.rs
new file mode 100644
index 0000000..8ddd041
--- /dev/null
+++ b/src/test/ui/regions/regions-variance-contravariant-use-covariant-in-second-position.rs
@@ -0,0 +1,28 @@
+// Test that a type which is covariant with respect to its region
+// parameter yields an error when used in a contravariant way.
+//
+// Note: see variance-regions-*.rs for the tests that check that the
+// variance inference works in the first place.
+
+// `S` is contravariant with respect to both parameters.
+struct S<'a, 'b> {
+    f: &'a isize,
+    g: &'b isize,
+}
+
+fn use_<'short,'long>(c: S<'long, 'short>,
+                      s: &'short isize,
+                      l: &'long isize,
+                      _where:Option<&'short &'long ()>) {
+
+    let _: S<'long, 'short> = c; // OK
+    let _: S<'short, 'short> = c; // OK
+
+    // Test whether S<_,'short> <: S<_,'long>.  Since
+    // 'short <= 'long, this would be true if the Contravariant type were
+    // covariant with respect to its parameter 'a.
+
+    let _: S<'long, 'long> = c; //~ ERROR E0623
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-variance-contravariant-use-covariant-in-second-position.stderr b/src/test/ui/regions/regions-variance-contravariant-use-covariant-in-second-position.stderr
new file mode 100644
index 0000000..e135007
--- /dev/null
+++ b/src/test/ui/regions/regions-variance-contravariant-use-covariant-in-second-position.stderr
@@ -0,0 +1,14 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/regions-variance-contravariant-use-covariant-in-second-position.rs:25:30
+   |
+LL | fn use_<'short,'long>(c: S<'long, 'short>,
+   |                          ----------------
+   |                          |
+   |                          this type is declared with multiple lifetimes...
+...
+LL |     let _: S<'long, 'long> = c;
+   |                              ^ ...but data with one lifetime flows into the other here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/regions/regions-variance-contravariant-use-covariant.rs b/src/test/ui/regions/regions-variance-contravariant-use-covariant.rs
new file mode 100644
index 0000000..cbdf62e
--- /dev/null
+++ b/src/test/ui/regions/regions-variance-contravariant-use-covariant.rs
@@ -0,0 +1,26 @@
+// Test that a type which is covariant with respect to its region
+// parameter yields an error when used in a contravariant way.
+//
+// Note: see variance-regions-*.rs for the tests that check that the
+// variance inference works in the first place.
+
+// This is contravariant with respect to 'a, meaning that
+// Contravariant<'long> <: Contravariant<'short> iff
+// 'short <= 'long
+struct Contravariant<'a> {
+    f: &'a isize
+}
+
+fn use_<'short,'long>(c: Contravariant<'short>,
+                      s: &'short isize,
+                      l: &'long isize,
+                      _where:Option<&'short &'long ()>) {
+
+    // Test whether Contravariant<'short> <: Contravariant<'long>.  Since
+    // 'short <= 'long, this would be true if the Contravariant type were
+    // covariant with respect to its parameter 'a.
+
+    let _: Contravariant<'long> = c; //~ ERROR E0623
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-variance-contravariant-use-covariant.stderr b/src/test/ui/regions/regions-variance-contravariant-use-covariant.stderr
new file mode 100644
index 0000000..e7c106c
--- /dev/null
+++ b/src/test/ui/regions/regions-variance-contravariant-use-covariant.stderr
@@ -0,0 +1,15 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/regions-variance-contravariant-use-covariant.rs:23:35
+   |
+LL | fn use_<'short,'long>(c: Contravariant<'short>,
+   |                          --------------------- these two types are declared with different lifetimes...
+LL |                       s: &'short isize,
+LL |                       l: &'long isize,
+   |                          ------------
+...
+LL |     let _: Contravariant<'long> = c;
+   |                                   ^ ...but data from `c` flows into `l` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/regions/regions-variance-covariant-use-contravariant.rs b/src/test/ui/regions/regions-variance-covariant-use-contravariant.rs
new file mode 100644
index 0000000..9aa0c81
--- /dev/null
+++ b/src/test/ui/regions/regions-variance-covariant-use-contravariant.rs
@@ -0,0 +1,26 @@
+// Test that a type which is covariant with respect to its region
+// parameter yields an error when used in a contravariant way.
+//
+// Note: see variance-regions-*.rs for the tests that check that the
+// variance inference works in the first place.
+
+// This is covariant with respect to 'a, meaning that
+// Covariant<'foo> <: Covariant<'static> because
+// 'foo <= 'static
+struct Covariant<'a> {
+    f: extern "Rust" fn(&'a isize)
+}
+
+fn use_<'short,'long>(c: Covariant<'long>,
+                      s: &'short isize,
+                      l: &'long isize,
+                      _where:Option<&'short &'long ()>) {
+
+    // Test whether Covariant<'long> <: Covariant<'short>.  Since
+    // 'short <= 'long, this would be true if the Covariant type were
+    // contravariant with respect to its parameter 'a.
+
+    let _: Covariant<'short> = c; //~ ERROR E0623
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/regions-variance-covariant-use-contravariant.stderr b/src/test/ui/regions/regions-variance-covariant-use-contravariant.stderr
new file mode 100644
index 0000000..e5e5261
--- /dev/null
+++ b/src/test/ui/regions/regions-variance-covariant-use-contravariant.stderr
@@ -0,0 +1,14 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/regions-variance-covariant-use-contravariant.rs:23:32
+   |
+LL | fn use_<'short,'long>(c: Covariant<'long>,
+   |                          ----------------
+LL |                       s: &'short isize,
+   |                          ------------- these two types are declared with different lifetimes...
+...
+LL |     let _: Covariant<'short> = c;
+   |                                ^ ...but data from `s` flows into `c` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/regions/regions-variance-invariant-use-contravariant.rs b/src/test/ui/regions/regions-variance-invariant-use-contravariant.rs
new file mode 100644
index 0000000..663b23b
--- /dev/null
+++ b/src/test/ui/regions/regions-variance-invariant-use-contravariant.rs
@@ -0,0 +1,23 @@
+// Test that an invariant region parameter used in a contravariant way
+// yields an error.
+//
+// Note: see variance-regions-*.rs for the tests that check that the
+// variance inference works in the first place.
+
+struct Invariant<'a> {
+    f: &'a mut &'a isize
+}
+
+fn use_<'short,'long>(c: Invariant<'long>,
+                      s: &'short isize,
+                      l: &'long isize,
+                      _where:Option<&'short &'long ()>) {
+
+    // Test whether Invariant<'long> <: Invariant<'short>.  Since
+    // 'short <= 'long, this would be true if the Invariant type were
+    // contravariant with respect to its parameter 'a.
+
+    let _: Invariant<'short> = c; //~ ERROR E0623
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-variance-invariant-use-contravariant.stderr b/src/test/ui/regions/regions-variance-invariant-use-contravariant.stderr
new file mode 100644
index 0000000..2a2d5d0
--- /dev/null
+++ b/src/test/ui/regions/regions-variance-invariant-use-contravariant.stderr
@@ -0,0 +1,14 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/regions-variance-invariant-use-contravariant.rs:20:32
+   |
+LL | fn use_<'short,'long>(c: Invariant<'long>,
+   |                          ----------------
+LL |                       s: &'short isize,
+   |                          ------------- these two types are declared with different lifetimes...
+...
+LL |     let _: Invariant<'short> = c;
+   |                                ^ ...but data from `s` flows into `c` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/regions/regions-variance-invariant-use-covariant.rs b/src/test/ui/regions/regions-variance-invariant-use-covariant.rs
new file mode 100644
index 0000000..07482e6
--- /dev/null
+++ b/src/test/ui/regions/regions-variance-invariant-use-covariant.rs
@@ -0,0 +1,20 @@
+// Test that a type which is invariant with respect to its region
+// parameter used in a covariant way yields an error.
+//
+// Note: see variance-regions-*.rs for the tests that check that the
+// variance inference works in the first place.
+
+struct Invariant<'a> {
+    f: &'a mut &'a isize
+}
+
+fn use_<'b>(c: Invariant<'b>) {
+
+    // For this assignment to be legal, Invariant<'b> <: Invariant<'static>.
+    // Since 'b <= 'static, this would be true if Invariant were covariant
+    // with respect to its parameter 'a.
+
+    let _: Invariant<'static> = c; //~ ERROR mismatched types
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-variance-invariant-use-covariant.stderr b/src/test/ui/regions/regions-variance-invariant-use-covariant.stderr
new file mode 100644
index 0000000..90b37ce
--- /dev/null
+++ b/src/test/ui/regions/regions-variance-invariant-use-covariant.stderr
@@ -0,0 +1,18 @@
+error[E0308]: mismatched types
+  --> $DIR/regions-variance-invariant-use-covariant.rs:17:33
+   |
+LL |     let _: Invariant<'static> = c;
+   |                                 ^ lifetime mismatch
+   |
+   = note: expected type `Invariant<'static>`
+              found type `Invariant<'b>`
+note: the lifetime 'b as defined on the function body at 11:9...
+  --> $DIR/regions-variance-invariant-use-covariant.rs:11:9
+   |
+LL | fn use_<'b>(c: Invariant<'b>) {
+   |         ^^
+   = note: ...does not necessarily outlive the static lifetime
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/regions/regions-wf-trait-object.rs b/src/test/ui/regions/regions-wf-trait-object.rs
new file mode 100644
index 0000000..61bab35
--- /dev/null
+++ b/src/test/ui/regions/regions-wf-trait-object.rs
@@ -0,0 +1,10 @@
+// Check that the explicit lifetime bound (`'b`, in this example) must
+// outlive all the superbound from the trait (`'a`, in this example).
+
+trait TheTrait<'t>: 't { }
+
+struct Foo<'a,'b> {
+    x: Box<TheTrait<'a>+'b> //~ ERROR E0478
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/regions-wf-trait-object.stderr b/src/test/ui/regions/regions-wf-trait-object.stderr
new file mode 100644
index 0000000..3dc1c4d
--- /dev/null
+++ b/src/test/ui/regions/regions-wf-trait-object.stderr
@@ -0,0 +1,20 @@
+error[E0478]: lifetime bound not satisfied
+  --> $DIR/regions-wf-trait-object.rs:7:5
+   |
+LL |     x: Box<TheTrait<'a>+'b>
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: lifetime parameter instantiated with the lifetime 'b as defined on the struct at 6:15
+  --> $DIR/regions-wf-trait-object.rs:6:15
+   |
+LL | struct Foo<'a,'b> {
+   |               ^^
+note: but lifetime parameter must outlive the lifetime 'a as defined on the struct at 6:12
+  --> $DIR/regions-wf-trait-object.rs:6:12
+   |
+LL | struct Foo<'a,'b> {
+   |            ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0478`.
diff --git a/src/test/ui/reject-specialized-drops-8142.rs b/src/test/ui/reject-specialized-drops-8142.rs
new file mode 100644
index 0000000..f047e16
--- /dev/null
+++ b/src/test/ui/reject-specialized-drops-8142.rs
@@ -0,0 +1,57 @@
+// Issue 8142: Test that Drop impls cannot be specialized beyond the
+// predicates attached to the struct/enum definition itself.
+
+trait Bound { fn foo(&self) { } }
+struct K<'l1,'l2> { x: &'l1 i8, y: &'l2 u8 }
+struct L<'l1,'l2> { x: &'l1 i8, y: &'l2 u8 }
+struct M<'m> { x: &'m i8 }
+struct N<'n> { x: &'n i8 }
+struct O<To> { x: *const To }
+struct P<Tp> { x: *const Tp }
+struct Q<Tq> { x: *const Tq }
+struct R<Tr> { x: *const Tr }
+struct S<Ts:Bound> { x: *const Ts }
+struct T<'t,Ts:'t> { x: &'t Ts }
+struct U;
+struct V<Tva, Tvb> { x: *const Tva, y: *const Tvb }
+struct W<'l1, 'l2> { x: &'l1 i8, y: &'l2 u8 }
+
+impl<'al,'adds_bnd:'al> Drop for K<'al,'adds_bnd> {                        // REJECT
+    //~^ ERROR The requirement `'adds_bnd : 'al` is added only by the Drop impl.
+    fn drop(&mut self) { } }
+
+impl<'al,'adds_bnd>     Drop for L<'al,'adds_bnd> where 'adds_bnd:'al {    // REJECT
+    //~^ ERROR The requirement `'adds_bnd : 'al` is added only by the Drop impl.
+    fn drop(&mut self) { } }
+
+impl<'ml>               Drop for M<'ml>         { fn drop(&mut self) { } } // ACCEPT
+
+impl                    Drop for N<'static>     { fn drop(&mut self) { } } // REJECT
+//~^ ERROR mismatched types
+//~| expected type `N<'n>`
+//~|    found type `N<'static>`
+
+impl<COkNoBound> Drop for O<COkNoBound> { fn drop(&mut self) { } } // ACCEPT
+
+impl              Drop for P<i8>          { fn drop(&mut self) { } } // REJECT
+//~^ ERROR Implementations of Drop cannot be specialized
+
+impl<AddsBnd:Bound> Drop for Q<AddsBnd> { fn drop(&mut self) { } } // REJECT
+//~^ ERROR The requirement `AddsBnd: Bound` is added only by the Drop impl.
+
+impl<'rbnd,AddsRBnd:'rbnd> Drop for R<AddsRBnd> { fn drop(&mut self) { } } // REJECT
+//~^ ERROR The requirement `AddsRBnd : 'rbnd` is added only by the Drop impl.
+
+impl<Bs:Bound>    Drop for S<Bs>          { fn drop(&mut self) { } } // ACCEPT
+
+impl<'t,Bt:'t>    Drop for T<'t,Bt>       { fn drop(&mut self) { } } // ACCEPT
+
+impl              Drop for U              { fn drop(&mut self) { } } // ACCEPT
+
+impl<One>         Drop for V<One,One>     { fn drop(&mut self) { } } // REJECT
+//~^ ERROR Implementations of Drop cannot be specialized
+
+impl<'lw>         Drop for W<'lw,'lw>     { fn drop(&mut self) { } } // REJECT
+//~^ ERROR cannot infer an appropriate lifetime
+
+pub fn main() { }
diff --git a/src/test/ui/reject-specialized-drops-8142.stderr b/src/test/ui/reject-specialized-drops-8142.stderr
new file mode 100644
index 0000000..7dacc1f
--- /dev/null
+++ b/src/test/ui/reject-specialized-drops-8142.stderr
@@ -0,0 +1,115 @@
+error[E0367]: The requirement `'adds_bnd : 'al` is added only by the Drop impl.
+  --> $DIR/reject-specialized-drops-8142.rs:19:1
+   |
+LL | / impl<'al,'adds_bnd:'al> Drop for K<'al,'adds_bnd> {                        // REJECT
+LL | |
+LL | |     fn drop(&mut self) { } }
+   | |____________________________^
+   |
+note: The same requirement must be part of the struct/enum definition
+  --> $DIR/reject-specialized-drops-8142.rs:5:1
+   |
+LL | struct K<'l1,'l2> { x: &'l1 i8, y: &'l2 u8 }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0367]: The requirement `'adds_bnd : 'al` is added only by the Drop impl.
+  --> $DIR/reject-specialized-drops-8142.rs:23:1
+   |
+LL | / impl<'al,'adds_bnd>     Drop for L<'al,'adds_bnd> where 'adds_bnd:'al {    // REJECT
+LL | |
+LL | |     fn drop(&mut self) { } }
+   | |____________________________^
+   |
+note: The same requirement must be part of the struct/enum definition
+  --> $DIR/reject-specialized-drops-8142.rs:6:1
+   |
+LL | struct L<'l1,'l2> { x: &'l1 i8, y: &'l2 u8 }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/reject-specialized-drops-8142.rs:29:1
+   |
+LL | impl                    Drop for N<'static>     { fn drop(&mut self) { } } // REJECT
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
+   |
+   = note: expected type `N<'n>`
+              found type `N<'static>`
+note: the lifetime 'n as defined on the struct at 8:10...
+  --> $DIR/reject-specialized-drops-8142.rs:8:10
+   |
+LL | struct N<'n> { x: &'n i8 }
+   |          ^^
+   = note: ...does not necessarily outlive the static lifetime
+
+error[E0366]: Implementations of Drop cannot be specialized
+  --> $DIR/reject-specialized-drops-8142.rs:36:1
+   |
+LL | impl              Drop for P<i8>          { fn drop(&mut self) { } } // REJECT
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: Use same sequence of generic type and region parameters that is on the struct/enum definition
+  --> $DIR/reject-specialized-drops-8142.rs:10:1
+   |
+LL | struct P<Tp> { x: *const Tp }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0367]: The requirement `AddsBnd: Bound` is added only by the Drop impl.
+  --> $DIR/reject-specialized-drops-8142.rs:39:1
+   |
+LL | impl<AddsBnd:Bound> Drop for Q<AddsBnd> { fn drop(&mut self) { } } // REJECT
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: The same requirement must be part of the struct/enum definition
+  --> $DIR/reject-specialized-drops-8142.rs:11:1
+   |
+LL | struct Q<Tq> { x: *const Tq }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0367]: The requirement `AddsRBnd : 'rbnd` is added only by the Drop impl.
+  --> $DIR/reject-specialized-drops-8142.rs:42:1
+   |
+LL | impl<'rbnd,AddsRBnd:'rbnd> Drop for R<AddsRBnd> { fn drop(&mut self) { } } // REJECT
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: The same requirement must be part of the struct/enum definition
+  --> $DIR/reject-specialized-drops-8142.rs:12:1
+   |
+LL | struct R<Tr> { x: *const Tr }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0366]: Implementations of Drop cannot be specialized
+  --> $DIR/reject-specialized-drops-8142.rs:51:1
+   |
+LL | impl<One>         Drop for V<One,One>     { fn drop(&mut self) { } } // REJECT
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: Use same sequence of generic type and region parameters that is on the struct/enum definition
+  --> $DIR/reject-specialized-drops-8142.rs:16:1
+   |
+LL | struct V<Tva, Tvb> { x: *const Tva, y: *const Tvb }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'lw` due to conflicting requirements
+  --> $DIR/reject-specialized-drops-8142.rs:54:1
+   |
+LL | impl<'lw>         Drop for W<'lw,'lw>     { fn drop(&mut self) { } } // REJECT
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: first, the lifetime cannot outlive the lifetime 'l1 as defined on the struct at 17:10...
+  --> $DIR/reject-specialized-drops-8142.rs:17:10
+   |
+LL | struct W<'l1, 'l2> { x: &'l1 i8, y: &'l2 u8 }
+   |          ^^^
+note: ...but the lifetime must also be valid for the lifetime 'l2 as defined on the struct at 17:15...
+  --> $DIR/reject-specialized-drops-8142.rs:17:15
+   |
+LL | struct W<'l1, 'l2> { x: &'l1 i8, y: &'l2 u8 }
+   |               ^^^
+   = note: ...so that the types are compatible:
+           expected W<'l1, 'l2>
+              found W<'_, '_>
+
+error: aborting due to 8 previous errors
+
+Some errors occurred: E0308, E0366, E0367, E0495.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/removing-extern-crate.fixed b/src/test/ui/removing-extern-crate.fixed
new file mode 100644
index 0000000..71728e8
--- /dev/null
+++ b/src/test/ui/removing-extern-crate.fixed
@@ -0,0 +1,17 @@
+// edition:2018
+// aux-build:removing-extern-crate.rs
+// run-rustfix
+// compile-pass
+
+#![warn(rust_2018_idioms)]
+#![allow(unused_imports)]
+
+
+
+
+mod another {
+    
+    
+}
+
+fn main() {}
diff --git a/src/test/ui/removing-extern-crate.rs b/src/test/ui/removing-extern-crate.rs
new file mode 100644
index 0000000..b9cc181
--- /dev/null
+++ b/src/test/ui/removing-extern-crate.rs
@@ -0,0 +1,17 @@
+// edition:2018
+// aux-build:removing-extern-crate.rs
+// run-rustfix
+// compile-pass
+
+#![warn(rust_2018_idioms)]
+#![allow(unused_imports)]
+
+extern crate removing_extern_crate as foo;
+extern crate core;
+
+mod another {
+    extern crate removing_extern_crate as foo;
+    extern crate core;
+}
+
+fn main() {}
diff --git a/src/test/ui/removing-extern-crate.stderr b/src/test/ui/removing-extern-crate.stderr
new file mode 100644
index 0000000..fbdcb15
--- /dev/null
+++ b/src/test/ui/removing-extern-crate.stderr
@@ -0,0 +1,31 @@
+warning: unused extern crate
+  --> $DIR/removing-extern-crate.rs:9:1
+   |
+LL | extern crate removing_extern_crate as foo;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
+   |
+note: lint level defined here
+  --> $DIR/removing-extern-crate.rs:6:9
+   |
+LL | #![warn(rust_2018_idioms)]
+   |         ^^^^^^^^^^^^^^^^
+   = note: #[warn(unused_extern_crates)] implied by #[warn(rust_2018_idioms)]
+
+warning: unused extern crate
+  --> $DIR/removing-extern-crate.rs:10:1
+   |
+LL | extern crate core;
+   | ^^^^^^^^^^^^^^^^^^ help: remove it
+
+warning: unused extern crate
+  --> $DIR/removing-extern-crate.rs:13:5
+   |
+LL |     extern crate removing_extern_crate as foo;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
+
+warning: unused extern crate
+  --> $DIR/removing-extern-crate.rs:14:5
+   |
+LL |     extern crate core;
+   |     ^^^^^^^^^^^^^^^^^^ help: remove it
+
diff --git a/src/test/ui/repeat-to-run-dtor-twice.rs b/src/test/ui/repeat-to-run-dtor-twice.rs
new file mode 100644
index 0000000..80eff2a
--- /dev/null
+++ b/src/test/ui/repeat-to-run-dtor-twice.rs
@@ -0,0 +1,19 @@
+// Tests that one can't run a destructor twice with the repeated vector
+// literal syntax.
+
+struct Foo {
+    x: isize,
+
+}
+
+impl Drop for Foo {
+    fn drop(&mut self) {
+        println!("Goodbye!");
+    }
+}
+
+fn main() {
+    let a = Foo { x: 3 };
+    let _ = [ a; 5 ];
+    //~^ ERROR `Foo: std::marker::Copy` is not satisfied
+}
diff --git a/src/test/ui/repeat-to-run-dtor-twice.stderr b/src/test/ui/repeat-to-run-dtor-twice.stderr
new file mode 100644
index 0000000..5434f6c
--- /dev/null
+++ b/src/test/ui/repeat-to-run-dtor-twice.stderr
@@ -0,0 +1,11 @@
+error[E0277]: the trait bound `Foo: std::marker::Copy` is not satisfied
+  --> $DIR/repeat-to-run-dtor-twice.rs:17:13
+   |
+LL |     let _ = [ a; 5 ];
+   |             ^^^^^^^^ the trait `std::marker::Copy` is not implemented for `Foo`
+   |
+   = note: the `Copy` trait is required because the repeated element will be copied
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/repeat_count.rs b/src/test/ui/repeat_count.rs
new file mode 100644
index 0000000..c42dc8c
--- /dev/null
+++ b/src/test/ui/repeat_count.rs
@@ -0,0 +1,39 @@
+// Regression test for issue #3645
+
+fn main() {
+    let n = 1;
+    let a = [0; n];
+    //~^ ERROR attempt to use a non-constant value in a constant [E0435]
+    let b = [0; ()];
+    //~^ ERROR mismatched types
+    //~| expected type `usize`
+    //~| found type `()`
+    //~| expected usize, found ()
+    let c = [0; true];
+    //~^ ERROR mismatched types
+    //~| expected usize, found bool
+    let d = [0; 0.5];
+    //~^ ERROR mismatched types
+    //~| expected type `usize`
+    //~| found type `{float}`
+    //~| expected usize, found floating-point number
+    let e = [0; "foo"];
+    //~^ ERROR mismatched types
+    //~| expected type `usize`
+    //~| found type `&'static str`
+    //~| expected usize, found reference
+    let f = [0; -4_isize];
+    //~^ ERROR mismatched types
+    //~| expected usize, found isize
+    let f = [0_usize; -1_isize];
+    //~^ ERROR mismatched types
+    //~| expected usize, found isize
+    struct G {
+        g: (),
+    }
+    let g = [0; G { g: () }];
+    //~^ ERROR mismatched types
+    //~| expected type `usize`
+    //~| found type `main::G`
+    //~| expected usize, found struct `main::G`
+}
diff --git a/src/test/ui/repeat_count.stderr b/src/test/ui/repeat_count.stderr
new file mode 100644
index 0000000..df3227b
--- /dev/null
+++ b/src/test/ui/repeat_count.stderr
@@ -0,0 +1,64 @@
+error[E0435]: attempt to use a non-constant value in a constant
+  --> $DIR/repeat_count.rs:5:17
+   |
+LL |     let a = [0; n];
+   |                 ^ non-constant value
+
+error[E0308]: mismatched types
+  --> $DIR/repeat_count.rs:7:17
+   |
+LL |     let b = [0; ()];
+   |                 ^^ expected usize, found ()
+   |
+   = note: expected type `usize`
+              found type `()`
+
+error[E0308]: mismatched types
+  --> $DIR/repeat_count.rs:12:17
+   |
+LL |     let c = [0; true];
+   |                 ^^^^ expected usize, found bool
+
+error[E0308]: mismatched types
+  --> $DIR/repeat_count.rs:15:17
+   |
+LL |     let d = [0; 0.5];
+   |                 ^^^ expected usize, found floating-point number
+   |
+   = note: expected type `usize`
+              found type `{float}`
+
+error[E0308]: mismatched types
+  --> $DIR/repeat_count.rs:20:17
+   |
+LL |     let e = [0; "foo"];
+   |                 ^^^^^ expected usize, found reference
+   |
+   = note: expected type `usize`
+              found type `&'static str`
+
+error[E0308]: mismatched types
+  --> $DIR/repeat_count.rs:25:17
+   |
+LL |     let f = [0; -4_isize];
+   |                 ^^^^^^^^ expected usize, found isize
+
+error[E0308]: mismatched types
+  --> $DIR/repeat_count.rs:28:23
+   |
+LL |     let f = [0_usize; -1_isize];
+   |                       ^^^^^^^^ expected usize, found isize
+
+error[E0308]: mismatched types
+  --> $DIR/repeat_count.rs:34:17
+   |
+LL |     let g = [0; G { g: () }];
+   |                 ^^^^^^^^^^^ expected usize, found struct `main::G`
+   |
+   = note: expected type `usize`
+              found type `main::G`
+
+error: aborting due to 8 previous errors
+
+Some errors occurred: E0308, E0435.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/repr.rs b/src/test/ui/repr.rs
new file mode 100644
index 0000000..9d84474
--- /dev/null
+++ b/src/test/ui/repr.rs
@@ -0,0 +1,16 @@
+#[repr]
+//~^ ERROR attribute must be of the form
+struct _A {}
+
+#[repr = "B"]
+//~^ ERROR attribute must be of the form
+struct _B {}
+
+#[repr = "C"]
+//~^ ERROR attribute must be of the form
+struct _C {}
+
+#[repr(C)]
+struct _D {}
+
+fn main() {}
diff --git a/src/test/ui/repr.stderr b/src/test/ui/repr.stderr
new file mode 100644
index 0000000..7ebfe08
--- /dev/null
+++ b/src/test/ui/repr.stderr
@@ -0,0 +1,20 @@
+error: attribute must be of the form `#[repr(C, packed, ...)]`
+  --> $DIR/repr.rs:1:1
+   |
+LL | #[repr]
+   | ^^^^^^^
+
+error: attribute must be of the form `#[repr(C, packed, ...)]`
+  --> $DIR/repr.rs:5:1
+   |
+LL | #[repr = "B"]
+   | ^^^^^^^^^^^^^
+
+error: attribute must be of the form `#[repr(C, packed, ...)]`
+  --> $DIR/repr.rs:9:1
+   |
+LL | #[repr = "C"]
+   | ^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/repr/repr-align-assign.fixed b/src/test/ui/repr/repr-align-assign.fixed
new file mode 100644
index 0000000..2e1d9a2
--- /dev/null
+++ b/src/test/ui/repr/repr-align-assign.fixed
@@ -0,0 +1,11 @@
+// run-rustfix
+
+#![allow(dead_code)]
+
+#[repr(align(8))] //~ ERROR incorrect `repr(align)` attribute format
+struct A(u64);
+
+#[repr(align(8))] //~ ERROR incorrect `repr(align)` attribute format
+struct B(u64);
+
+fn main() {}
diff --git a/src/test/ui/repr/repr-align-assign.rs b/src/test/ui/repr/repr-align-assign.rs
new file mode 100644
index 0000000..b8f7c15
--- /dev/null
+++ b/src/test/ui/repr/repr-align-assign.rs
@@ -0,0 +1,11 @@
+// run-rustfix
+
+#![allow(dead_code)]
+
+#[repr(align=8)] //~ ERROR incorrect `repr(align)` attribute format
+struct A(u64);
+
+#[repr(align="8")] //~ ERROR incorrect `repr(align)` attribute format
+struct B(u64);
+
+fn main() {}
diff --git a/src/test/ui/repr/repr-align-assign.stderr b/src/test/ui/repr/repr-align-assign.stderr
new file mode 100644
index 0000000..cc046e0
--- /dev/null
+++ b/src/test/ui/repr/repr-align-assign.stderr
@@ -0,0 +1,15 @@
+error[E0693]: incorrect `repr(align)` attribute format
+  --> $DIR/repr-align-assign.rs:5:8
+   |
+LL | #[repr(align=8)]
+   |        ^^^^^^^ help: use parentheses instead: `align(8)`
+
+error[E0693]: incorrect `repr(align)` attribute format
+  --> $DIR/repr-align-assign.rs:8:8
+   |
+LL | #[repr(align="8")]
+   |        ^^^^^^^^^ help: use parentheses instead: `align(8)`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0693`.
diff --git a/src/test/ui/repr/repr-align.rs b/src/test/ui/repr/repr-align.rs
new file mode 100644
index 0000000..9ce89e82
--- /dev/null
+++ b/src/test/ui/repr/repr-align.rs
@@ -0,0 +1,19 @@
+#![feature(repr_align_enum)]
+#![allow(dead_code)]
+
+#[repr(align(16.0))] //~ ERROR: invalid `repr(align)` attribute: not an unsuffixed integer
+struct A(i32);
+
+#[repr(align(15))] //~ ERROR: invalid `repr(align)` attribute: not a power of two
+struct B(i32);
+
+#[repr(align(4294967296))] //~ ERROR: invalid `repr(align)` attribute: larger than 2^29
+struct C(i32);
+
+#[repr(align(536870912))] // ok: this is the largest accepted alignment
+struct D(i32);
+
+#[repr(align(15))] //~ ERROR: invalid `repr(align)` attribute: not a power of two
+enum E { Left, Right }
+
+fn main() {}
diff --git a/src/test/ui/repr/repr-align.stderr b/src/test/ui/repr/repr-align.stderr
new file mode 100644
index 0000000..641f117
--- /dev/null
+++ b/src/test/ui/repr/repr-align.stderr
@@ -0,0 +1,27 @@
+error[E0589]: invalid `repr(align)` attribute: not an unsuffixed integer
+  --> $DIR/repr-align.rs:4:8
+   |
+LL | #[repr(align(16.0))]
+   |        ^^^^^^^^^^^
+
+error[E0589]: invalid `repr(align)` attribute: not a power of two
+  --> $DIR/repr-align.rs:7:8
+   |
+LL | #[repr(align(15))]
+   |        ^^^^^^^^^
+
+error[E0589]: invalid `repr(align)` attribute: larger than 2^29
+  --> $DIR/repr-align.rs:10:8
+   |
+LL | #[repr(align(4294967296))]
+   |        ^^^^^^^^^^^^^^^^^
+
+error[E0589]: invalid `repr(align)` attribute: not a power of two
+  --> $DIR/repr-align.rs:16:8
+   |
+LL | #[repr(align(15))]
+   |        ^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0589`.
diff --git a/src/test/ui/repr/repr-packed-contains-align.rs b/src/test/ui/repr/repr-packed-contains-align.rs
new file mode 100644
index 0000000..a361034
--- /dev/null
+++ b/src/test/ui/repr/repr-packed-contains-align.rs
@@ -0,0 +1,50 @@
+#![feature(untagged_unions)]
+#![allow(dead_code)]
+
+#[repr(align(16))]
+struct SA(i32);
+
+struct SB(SA);
+
+#[repr(align(16))]
+union UA {
+    i: i32
+}
+
+union UB {
+    a: UA
+}
+
+#[repr(packed)]
+struct SC(SA); //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type
+
+#[repr(packed)]
+struct SD(SB); //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type
+
+#[repr(packed)]
+struct SE(UA); //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type
+
+#[repr(packed)]
+struct SF(UB); //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type
+
+#[repr(packed)]
+union UC { //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type
+    a: UA
+}
+
+#[repr(packed)]
+union UD { //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type
+    n: UB
+}
+
+#[repr(packed)]
+union UE { //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type
+    a: SA
+}
+
+#[repr(packed)]
+union UF { //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type
+    n: SB
+}
+
+fn main() {}
diff --git a/src/test/ui/repr/repr-packed-contains-align.stderr b/src/test/ui/repr/repr-packed-contains-align.stderr
new file mode 100644
index 0000000..df001d6
--- /dev/null
+++ b/src/test/ui/repr/repr-packed-contains-align.stderr
@@ -0,0 +1,59 @@
+error[E0588]: packed type cannot transitively contain a `[repr(align)]` type
+  --> $DIR/repr-packed-contains-align.rs:19:1
+   |
+LL | struct SC(SA);
+   | ^^^^^^^^^^^^^^
+
+error[E0588]: packed type cannot transitively contain a `[repr(align)]` type
+  --> $DIR/repr-packed-contains-align.rs:22:1
+   |
+LL | struct SD(SB);
+   | ^^^^^^^^^^^^^^
+
+error[E0588]: packed type cannot transitively contain a `[repr(align)]` type
+  --> $DIR/repr-packed-contains-align.rs:25:1
+   |
+LL | struct SE(UA);
+   | ^^^^^^^^^^^^^^
+
+error[E0588]: packed type cannot transitively contain a `[repr(align)]` type
+  --> $DIR/repr-packed-contains-align.rs:28:1
+   |
+LL | struct SF(UB);
+   | ^^^^^^^^^^^^^^
+
+error[E0588]: packed type cannot transitively contain a `[repr(align)]` type
+  --> $DIR/repr-packed-contains-align.rs:31:1
+   |
+LL | / union UC {
+LL | |     a: UA
+LL | | }
+   | |_^
+
+error[E0588]: packed type cannot transitively contain a `[repr(align)]` type
+  --> $DIR/repr-packed-contains-align.rs:36:1
+   |
+LL | / union UD {
+LL | |     n: UB
+LL | | }
+   | |_^
+
+error[E0588]: packed type cannot transitively contain a `[repr(align)]` type
+  --> $DIR/repr-packed-contains-align.rs:41:1
+   |
+LL | / union UE {
+LL | |     a: SA
+LL | | }
+   | |_^
+
+error[E0588]: packed type cannot transitively contain a `[repr(align)]` type
+  --> $DIR/repr-packed-contains-align.rs:46:1
+   |
+LL | / union UF {
+LL | |     n: SB
+LL | | }
+   | |_^
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0588`.
diff --git a/src/test/ui/repr/repr-transparent-other-items.rs b/src/test/ui/repr/repr-transparent-other-items.rs
new file mode 100644
index 0000000..392e7c9
--- /dev/null
+++ b/src/test/ui/repr/repr-transparent-other-items.rs
@@ -0,0 +1,30 @@
+// See also repr-transparent.rs
+
+#[repr(transparent)] //~ ERROR unsupported representation for zero-variant enum
+enum Void {}         //~| ERROR should be applied to struct
+
+#[repr(transparent)] //~ ERROR should be applied to struct
+enum FieldlessEnum {
+    Foo,
+    Bar,
+}
+
+#[repr(transparent)] //~ ERROR should be applied to struct
+enum Enum {
+    Foo(String),
+    Bar(u32),
+}
+
+#[repr(transparent)] //~ ERROR should be applied to struct
+union Foo {
+    u: u32,
+    s: i32
+}
+
+#[repr(transparent)] //~ ERROR should be applied to struct
+fn cant_repr_this() {}
+
+#[repr(transparent)] //~ ERROR should be applied to struct
+static CANT_REPR_THIS: u32 = 0;
+
+fn main() {}
diff --git a/src/test/ui/repr/repr-transparent-other-items.stderr b/src/test/ui/repr/repr-transparent-other-items.stderr
new file mode 100644
index 0000000..c3fb1d9
--- /dev/null
+++ b/src/test/ui/repr/repr-transparent-other-items.stderr
@@ -0,0 +1,69 @@
+error[E0517]: attribute should be applied to struct
+  --> $DIR/repr-transparent-other-items.rs:3:8
+   |
+LL | #[repr(transparent)]
+   |        ^^^^^^^^^^^
+LL | enum Void {}
+   | ------------ not a struct
+
+error[E0517]: attribute should be applied to struct
+  --> $DIR/repr-transparent-other-items.rs:6:8
+   |
+LL |   #[repr(transparent)]
+   |          ^^^^^^^^^^^
+LL | / enum FieldlessEnum {
+LL | |     Foo,
+LL | |     Bar,
+LL | | }
+   | |_- not a struct
+
+error[E0517]: attribute should be applied to struct
+  --> $DIR/repr-transparent-other-items.rs:12:8
+   |
+LL |   #[repr(transparent)]
+   |          ^^^^^^^^^^^
+LL | / enum Enum {
+LL | |     Foo(String),
+LL | |     Bar(u32),
+LL | | }
+   | |_- not a struct
+
+error[E0517]: attribute should be applied to struct
+  --> $DIR/repr-transparent-other-items.rs:18:8
+   |
+LL |   #[repr(transparent)]
+   |          ^^^^^^^^^^^
+LL | / union Foo {
+LL | |     u: u32,
+LL | |     s: i32
+LL | | }
+   | |_- not a struct
+
+error[E0517]: attribute should be applied to struct
+  --> $DIR/repr-transparent-other-items.rs:24:8
+   |
+LL | #[repr(transparent)]
+   |        ^^^^^^^^^^^
+LL | fn cant_repr_this() {}
+   | ---------------------- not a struct
+
+error[E0517]: attribute should be applied to struct
+  --> $DIR/repr-transparent-other-items.rs:27:8
+   |
+LL | #[repr(transparent)]
+   |        ^^^^^^^^^^^
+LL | static CANT_REPR_THIS: u32 = 0;
+   | ------------------------------- not a struct
+
+error[E0084]: unsupported representation for zero-variant enum
+  --> $DIR/repr-transparent-other-items.rs:3:1
+   |
+LL | #[repr(transparent)]
+   | ^^^^^^^^^^^^^^^^^^^^
+LL | enum Void {}
+   | ------------ zero-variant enum
+
+error: aborting due to 7 previous errors
+
+Some errors occurred: E0084, E0517.
+For more information about an error, try `rustc --explain E0084`.
diff --git a/src/test/ui/repr/repr-transparent-other-reprs.rs b/src/test/ui/repr/repr-transparent-other-reprs.rs
new file mode 100644
index 0000000..e3671e7
--- /dev/null
+++ b/src/test/ui/repr/repr-transparent-other-reprs.rs
@@ -0,0 +1,20 @@
+#![feature(repr_align)]
+
+// See also repr-transparent.rs
+
+#[repr(transparent, C)] //~ ERROR cannot have other repr
+struct TransparentPlusC {
+    ptr: *const u8
+}
+
+#[repr(transparent, packed)] //~ ERROR cannot have other repr
+struct TransparentPlusPacked(*const u8);
+
+#[repr(transparent, align(2))] //~ ERROR cannot have other repr
+struct TransparentPlusAlign(u8);
+
+#[repr(transparent)] //~ ERROR cannot have other repr
+#[repr(C)]
+struct SeparateAttributes(*mut u8);
+
+fn main() {}
diff --git a/src/test/ui/repr/repr-transparent-other-reprs.stderr b/src/test/ui/repr/repr-transparent-other-reprs.stderr
new file mode 100644
index 0000000..9b48bb3
--- /dev/null
+++ b/src/test/ui/repr/repr-transparent-other-reprs.stderr
@@ -0,0 +1,29 @@
+error[E0692]: transparent struct cannot have other repr hints
+  --> $DIR/repr-transparent-other-reprs.rs:5:8
+   |
+LL | #[repr(transparent, C)]
+   |        ^^^^^^^^^^^  ^
+
+error[E0692]: transparent struct cannot have other repr hints
+  --> $DIR/repr-transparent-other-reprs.rs:10:8
+   |
+LL | #[repr(transparent, packed)]
+   |        ^^^^^^^^^^^  ^^^^^^
+
+error[E0692]: transparent struct cannot have other repr hints
+  --> $DIR/repr-transparent-other-reprs.rs:13:8
+   |
+LL | #[repr(transparent, align(2))]
+   |        ^^^^^^^^^^^  ^^^^^^^^
+
+error[E0692]: transparent struct cannot have other repr hints
+  --> $DIR/repr-transparent-other-reprs.rs:16:8
+   |
+LL | #[repr(transparent)]
+   |        ^^^^^^^^^^^
+LL | #[repr(C)]
+   |        ^
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0692`.
diff --git a/src/test/ui/repr/repr-transparent.rs b/src/test/ui/repr/repr-transparent.rs
new file mode 100644
index 0000000..66d39ff
--- /dev/null
+++ b/src/test/ui/repr/repr-transparent.rs
@@ -0,0 +1,42 @@
+// This file tests repr(transparent)-related errors reported during typeck. Other errors
+// that are reported earlier and therefore preempt these are tested in:
+// - repr-transparent-other-reprs.rs
+// - repr-transparent-other-items.rs
+
+#![feature(repr_align)]
+
+use std::marker::PhantomData;
+
+#[repr(transparent)]
+struct NoFields; //~ ERROR needs exactly one non-zero-sized field
+
+#[repr(transparent)]
+struct ContainsOnlyZst(()); //~ ERROR needs exactly one non-zero-sized field
+
+#[repr(transparent)]
+struct ContainsOnlyZstArray([bool; 0]); //~ ERROR needs exactly one non-zero-sized field
+
+#[repr(transparent)]
+struct ContainsMultipleZst(PhantomData<*const i32>, NoFields);
+//~^ ERROR needs exactly one non-zero-sized field
+
+#[repr(transparent)]
+struct MultipleNonZst(u8, u8); //~ ERROR needs exactly one non-zero-sized field
+
+trait Mirror { type It: ?Sized; }
+impl<T: ?Sized> Mirror for T { type It = Self; }
+
+#[repr(transparent)]
+pub struct StructWithProjection(f32, <f32 as Mirror>::It);
+//~^ ERROR needs exactly one non-zero-sized field
+
+#[repr(transparent)]
+struct NontrivialAlignZst(u32, [u16; 0]); //~ ERROR alignment larger than 1
+
+#[repr(align(32))]
+struct ZstAlign32<T>(PhantomData<T>);
+
+#[repr(transparent)]
+struct GenericAlign<T>(ZstAlign32<T>, u32); //~ ERROR alignment larger than 1
+
+fn main() {}
diff --git a/src/test/ui/repr/repr-transparent.stderr b/src/test/ui/repr/repr-transparent.stderr
new file mode 100644
index 0000000..2ecee83
--- /dev/null
+++ b/src/test/ui/repr/repr-transparent.stderr
@@ -0,0 +1,72 @@
+error[E0690]: transparent struct needs exactly one non-zero-sized field, but has 0
+  --> $DIR/repr-transparent.rs:11:1
+   |
+LL | struct NoFields;
+   | ^^^^^^^^^^^^^^^^
+   |
+   = note: non-zero-sized field
+
+error[E0690]: transparent struct needs exactly one non-zero-sized field, but has 0
+  --> $DIR/repr-transparent.rs:14:1
+   |
+LL | struct ContainsOnlyZst(());
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: non-zero-sized field
+
+error[E0690]: transparent struct needs exactly one non-zero-sized field, but has 0
+  --> $DIR/repr-transparent.rs:17:1
+   |
+LL | struct ContainsOnlyZstArray([bool; 0]);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: non-zero-sized field
+
+error[E0690]: transparent struct needs exactly one non-zero-sized field, but has 0
+  --> $DIR/repr-transparent.rs:20:1
+   |
+LL | struct ContainsMultipleZst(PhantomData<*const i32>, NoFields);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: non-zero-sized field
+
+error[E0690]: transparent struct needs exactly one non-zero-sized field, but has 2
+  --> $DIR/repr-transparent.rs:24:1
+   |
+LL | struct MultipleNonZst(u8, u8);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: non-zero-sized field
+  --> $DIR/repr-transparent.rs:24:23
+   |
+LL | struct MultipleNonZst(u8, u8);
+   |                       ^^  ^^
+
+error[E0690]: transparent struct needs exactly one non-zero-sized field, but has 2
+  --> $DIR/repr-transparent.rs:30:1
+   |
+LL | pub struct StructWithProjection(f32, <f32 as Mirror>::It);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: non-zero-sized field
+  --> $DIR/repr-transparent.rs:30:33
+   |
+LL | pub struct StructWithProjection(f32, <f32 as Mirror>::It);
+   |                                 ^^^  ^^^^^^^^^^^^^^^^^^^
+
+error[E0691]: zero-sized field in transparent struct has alignment larger than 1
+  --> $DIR/repr-transparent.rs:34:32
+   |
+LL | struct NontrivialAlignZst(u32, [u16; 0]);
+   |                                ^^^^^^^^
+
+error[E0691]: zero-sized field in transparent struct has alignment larger than 1
+  --> $DIR/repr-transparent.rs:40:24
+   |
+LL | struct GenericAlign<T>(ZstAlign32<T>, u32);
+   |                        ^^^^^^^^^^^^^
+
+error: aborting due to 8 previous errors
+
+Some errors occurred: E0690, E0691.
+For more information about an error, try `rustc --explain E0690`.
diff --git a/src/test/ui/required-lang-item.rs b/src/test/ui/required-lang-item.rs
new file mode 100644
index 0000000..ee37736
--- /dev/null
+++ b/src/test/ui/required-lang-item.rs
@@ -0,0 +1,9 @@
+#![feature(lang_items, no_core)]
+#![no_core]
+
+#[lang="copy"] pub trait Copy { }
+#[lang="sized"] pub trait Sized { }
+
+// error-pattern:requires `start` lang_item
+
+fn main() {}
diff --git a/src/test/ui/required-lang-item.stderr b/src/test/ui/required-lang-item.stderr
new file mode 100644
index 0000000..83764a9
--- /dev/null
+++ b/src/test/ui/required-lang-item.stderr
@@ -0,0 +1,4 @@
+error: requires `start` lang_item
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/reserved/reserved-attr-on-macro.rs b/src/test/ui/reserved/reserved-attr-on-macro.rs
new file mode 100644
index 0000000..96c63ba
--- /dev/null
+++ b/src/test/ui/reserved/reserved-attr-on-macro.rs
@@ -0,0 +1,9 @@
+#[rustc_attribute_should_be_reserved]
+//~^ ERROR unless otherwise specified, attributes with the prefix `rustc_` are reserved
+macro_rules! foo {
+    () => (());
+}
+
+fn main() {
+    foo!(); //~ ERROR cannot determine resolution for the macro `foo`
+}
diff --git a/src/test/ui/reserved/reserved-attr-on-macro.stderr b/src/test/ui/reserved/reserved-attr-on-macro.stderr
new file mode 100644
index 0000000..3e082e5
--- /dev/null
+++ b/src/test/ui/reserved/reserved-attr-on-macro.stderr
@@ -0,0 +1,19 @@
+error[E0658]: unless otherwise specified, attributes with the prefix `rustc_` are reserved for internal compiler diagnostics (see issue #29642)
+  --> $DIR/reserved-attr-on-macro.rs:1:3
+   |
+LL | #[rustc_attribute_should_be_reserved]
+   |   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(rustc_attrs)] to the crate attributes to enable
+
+error: cannot determine resolution for the macro `foo`
+  --> $DIR/reserved-attr-on-macro.rs:8:5
+   |
+LL |     foo!();
+   |     ^^^
+   |
+   = note: import resolution is stuck, try simplifying macro imports
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/reserved/reserved-become.rs b/src/test/ui/reserved/reserved-become.rs
new file mode 100644
index 0000000..2279a05
--- /dev/null
+++ b/src/test/ui/reserved/reserved-become.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let become = 0;
+    //~^ ERROR expected pattern, found reserved keyword `become`
+}
diff --git a/src/test/ui/reserved/reserved-become.stderr b/src/test/ui/reserved/reserved-become.stderr
new file mode 100644
index 0000000..f9fe78e
--- /dev/null
+++ b/src/test/ui/reserved/reserved-become.stderr
@@ -0,0 +1,8 @@
+error: expected pattern, found reserved keyword `become`
+  --> $DIR/reserved-become.rs:2:9
+   |
+LL |     let become = 0;
+   |         ^^^^^^ expected pattern
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/resolve/auxiliary/issue-19452-aux.rs b/src/test/ui/resolve/auxiliary/issue-19452-aux.rs
new file mode 100644
index 0000000..9c7bcec
--- /dev/null
+++ b/src/test/ui/resolve/auxiliary/issue-19452-aux.rs
@@ -0,0 +1,3 @@
+pub enum Homura {
+    Madoka { age: u32 }
+}
diff --git a/src/test/ui/resolve/auxiliary/issue-21221-3.rs b/src/test/ui/resolve/auxiliary/issue-21221-3.rs
new file mode 100644
index 0000000..176c231
--- /dev/null
+++ b/src/test/ui/resolve/auxiliary/issue-21221-3.rs
@@ -0,0 +1,19 @@
+// testing whether the lookup mechanism picks up types
+// defined in the outside crate
+
+#![crate_type="lib"]
+
+pub mod outer {
+    // should suggest this
+    pub trait OuterTrait {}
+
+    // should not suggest this since the module is private
+    mod private_module {
+        pub trait OuterTrait {}
+    }
+
+    // should not suggest since the trait is private
+    pub mod public_module {
+        trait OuterTrait {}
+    }
+}
diff --git a/src/test/ui/resolve/auxiliary/issue-21221-4.rs b/src/test/ui/resolve/auxiliary/issue-21221-4.rs
new file mode 100644
index 0000000..5e0d6cb
--- /dev/null
+++ b/src/test/ui/resolve/auxiliary/issue-21221-4.rs
@@ -0,0 +1,12 @@
+// testing whether the lookup mechanism picks up types
+// defined in the outside crate
+
+#![crate_type="lib"]
+
+mod foo {
+    // should not be suggested => foo is private
+    pub trait T {}
+}
+
+// should be suggested
+pub use foo::T;
diff --git a/src/test/ui/resolve/auxiliary/issue-3907.rs b/src/test/ui/resolve/auxiliary/issue-3907.rs
new file mode 100644
index 0000000..5dc5029
--- /dev/null
+++ b/src/test/ui/resolve/auxiliary/issue-3907.rs
@@ -0,0 +1,3 @@
+pub trait Foo {
+    fn bar();
+}
diff --git a/src/test/ui/resolve/auxiliary/namespaced_enums.rs b/src/test/ui/resolve/auxiliary/namespaced_enums.rs
new file mode 100644
index 0000000..d3548c7
--- /dev/null
+++ b/src/test/ui/resolve/auxiliary/namespaced_enums.rs
@@ -0,0 +1,10 @@
+pub enum Foo {
+    A,
+    B(isize),
+    C { a: isize },
+}
+
+impl Foo {
+    pub fn foo() {}
+    pub fn bar(&self) {}
+}
diff --git a/src/test/ui/resolve/auxiliary/privacy-struct-ctor.rs b/src/test/ui/resolve/auxiliary/privacy-struct-ctor.rs
new file mode 100644
index 0000000..6d0bc72
--- /dev/null
+++ b/src/test/ui/resolve/auxiliary/privacy-struct-ctor.rs
@@ -0,0 +1,9 @@
+pub mod m {
+    pub struct S(u8);
+
+    pub mod n {
+        pub(in m) struct Z(pub(in m::n) u8);
+    }
+}
+
+pub use m::S;
diff --git a/src/test/ui/resolve/enums-are-namespaced-xc.rs b/src/test/ui/resolve/enums-are-namespaced-xc.rs
new file mode 100644
index 0000000..4c660c2
--- /dev/null
+++ b/src/test/ui/resolve/enums-are-namespaced-xc.rs
@@ -0,0 +1,11 @@
+// aux-build:namespaced_enums.rs
+extern crate namespaced_enums;
+
+fn main() {
+    let _ = namespaced_enums::A;
+    //~^ ERROR cannot find value `A`
+    let _ = namespaced_enums::B(10);
+    //~^ ERROR cannot find function `B`
+    let _ = namespaced_enums::C { a: 10 };
+    //~^ ERROR cannot find struct, variant or union type `C`
+}
diff --git a/src/test/ui/resolve/enums-are-namespaced-xc.stderr b/src/test/ui/resolve/enums-are-namespaced-xc.stderr
new file mode 100644
index 0000000..a0771ed
--- /dev/null
+++ b/src/test/ui/resolve/enums-are-namespaced-xc.stderr
@@ -0,0 +1,34 @@
+error[E0425]: cannot find value `A` in module `namespaced_enums`
+  --> $DIR/enums-are-namespaced-xc.rs:5:31
+   |
+LL |     let _ = namespaced_enums::A;
+   |                               ^ not found in `namespaced_enums`
+help: possible candidate is found in another module, you can import it into scope
+   |
+LL | use namespaced_enums::Foo::A;
+   |
+
+error[E0425]: cannot find function `B` in module `namespaced_enums`
+  --> $DIR/enums-are-namespaced-xc.rs:7:31
+   |
+LL |     let _ = namespaced_enums::B(10);
+   |                               ^ not found in `namespaced_enums`
+help: possible candidate is found in another module, you can import it into scope
+   |
+LL | use namespaced_enums::Foo::B;
+   |
+
+error[E0422]: cannot find struct, variant or union type `C` in module `namespaced_enums`
+  --> $DIR/enums-are-namespaced-xc.rs:9:31
+   |
+LL |     let _ = namespaced_enums::C { a: 10 };
+   |                               ^ not found in `namespaced_enums`
+help: possible candidate is found in another module, you can import it into scope
+   |
+LL | use namespaced_enums::Foo::C;
+   |
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0422, E0425.
+For more information about an error, try `rustc --explain E0422`.
diff --git a/src/test/ui/resolve/issue-14254.rs b/src/test/ui/resolve/issue-14254.rs
new file mode 100644
index 0000000..78add29
--- /dev/null
+++ b/src/test/ui/resolve/issue-14254.rs
@@ -0,0 +1,105 @@
+trait Foo {
+    fn bar(&self);
+    fn baz(&self) { }
+    fn bah(_: Option<&Self>) { }
+}
+
+struct BarTy {
+    x : isize,
+    y : f64,
+}
+
+impl BarTy {
+    fn a() {}
+    fn b(&self) {}
+}
+
+impl Foo for *const BarTy {
+    fn bar(&self) {
+        baz();
+        //~^ ERROR cannot find function `baz`
+        a;
+        //~^ ERROR cannot find value `a`
+    }
+}
+
+impl<'a> Foo for &'a BarTy {
+    fn bar(&self) {
+        baz();
+        //~^ ERROR cannot find function `baz`
+        x;
+        //~^ ERROR cannot find value `x`
+        y;
+        //~^ ERROR cannot find value `y`
+        a;
+        //~^ ERROR cannot find value `a`
+        bah;
+        //~^ ERROR cannot find value `bah`
+        b;
+        //~^ ERROR cannot find value `b`
+    }
+}
+
+impl<'a> Foo for &'a mut BarTy {
+    fn bar(&self) {
+        baz();
+        //~^ ERROR cannot find function `baz`
+        x;
+        //~^ ERROR cannot find value `x`
+        y;
+        //~^ ERROR cannot find value `y`
+        a;
+        //~^ ERROR cannot find value `a`
+        bah;
+        //~^ ERROR cannot find value `bah`
+        b;
+        //~^ ERROR cannot find value `b`
+    }
+}
+
+impl Foo for Box<BarTy> {
+    fn bar(&self) {
+        baz();
+        //~^ ERROR cannot find function `baz`
+        bah;
+        //~^ ERROR cannot find value `bah`
+    }
+}
+
+impl Foo for *const isize {
+    fn bar(&self) {
+        baz();
+        //~^ ERROR cannot find function `baz`
+        bah;
+        //~^ ERROR cannot find value `bah`
+    }
+}
+
+impl<'a> Foo for &'a isize {
+    fn bar(&self) {
+        baz();
+        //~^ ERROR cannot find function `baz`
+        bah;
+        //~^ ERROR cannot find value `bah`
+    }
+}
+
+impl<'a> Foo for &'a mut isize {
+    fn bar(&self) {
+        baz();
+        //~^ ERROR cannot find function `baz`
+        bah;
+        //~^ ERROR cannot find value `bah`
+    }
+}
+
+impl Foo for Box<isize> {
+    fn bar(&self) {
+        baz();
+        //~^ ERROR cannot find function `baz`
+        bah;
+        //~^ ERROR cannot find value `bah`
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/resolve/issue-14254.stderr b/src/test/ui/resolve/issue-14254.stderr
new file mode 100644
index 0000000..783b3ad
--- /dev/null
+++ b/src/test/ui/resolve/issue-14254.stderr
@@ -0,0 +1,147 @@
+error[E0425]: cannot find function `baz` in this scope
+  --> $DIR/issue-14254.rs:19:9
+   |
+LL |         baz();
+   |         ^^^ help: try: `self.baz`
+
+error[E0425]: cannot find value `a` in this scope
+  --> $DIR/issue-14254.rs:21:9
+   |
+LL |         a;
+   |         ^ not found in this scope
+
+error[E0425]: cannot find function `baz` in this scope
+  --> $DIR/issue-14254.rs:28:9
+   |
+LL |         baz();
+   |         ^^^ help: try: `self.baz`
+
+error[E0425]: cannot find value `x` in this scope
+  --> $DIR/issue-14254.rs:30:9
+   |
+LL |         x;
+   |         ^ help: try: `self.x`
+
+error[E0425]: cannot find value `y` in this scope
+  --> $DIR/issue-14254.rs:32:9
+   |
+LL |         y;
+   |         ^ help: try: `self.y`
+
+error[E0425]: cannot find value `a` in this scope
+  --> $DIR/issue-14254.rs:34:9
+   |
+LL |         a;
+   |         ^ not found in this scope
+
+error[E0425]: cannot find value `bah` in this scope
+  --> $DIR/issue-14254.rs:36:9
+   |
+LL |         bah;
+   |         ^^^ help: try: `Self::bah`
+
+error[E0425]: cannot find value `b` in this scope
+  --> $DIR/issue-14254.rs:38:9
+   |
+LL |         b;
+   |         ^ not found in this scope
+
+error[E0425]: cannot find function `baz` in this scope
+  --> $DIR/issue-14254.rs:45:9
+   |
+LL |         baz();
+   |         ^^^ help: try: `self.baz`
+
+error[E0425]: cannot find value `x` in this scope
+  --> $DIR/issue-14254.rs:47:9
+   |
+LL |         x;
+   |         ^ help: try: `self.x`
+
+error[E0425]: cannot find value `y` in this scope
+  --> $DIR/issue-14254.rs:49:9
+   |
+LL |         y;
+   |         ^ help: try: `self.y`
+
+error[E0425]: cannot find value `a` in this scope
+  --> $DIR/issue-14254.rs:51:9
+   |
+LL |         a;
+   |         ^ not found in this scope
+
+error[E0425]: cannot find value `bah` in this scope
+  --> $DIR/issue-14254.rs:53:9
+   |
+LL |         bah;
+   |         ^^^ help: try: `Self::bah`
+
+error[E0425]: cannot find value `b` in this scope
+  --> $DIR/issue-14254.rs:55:9
+   |
+LL |         b;
+   |         ^ not found in this scope
+
+error[E0425]: cannot find function `baz` in this scope
+  --> $DIR/issue-14254.rs:62:9
+   |
+LL |         baz();
+   |         ^^^ help: try: `self.baz`
+
+error[E0425]: cannot find value `bah` in this scope
+  --> $DIR/issue-14254.rs:64:9
+   |
+LL |         bah;
+   |         ^^^ help: try: `Self::bah`
+
+error[E0425]: cannot find function `baz` in this scope
+  --> $DIR/issue-14254.rs:71:9
+   |
+LL |         baz();
+   |         ^^^ help: try: `self.baz`
+
+error[E0425]: cannot find value `bah` in this scope
+  --> $DIR/issue-14254.rs:73:9
+   |
+LL |         bah;
+   |         ^^^ help: try: `Self::bah`
+
+error[E0425]: cannot find function `baz` in this scope
+  --> $DIR/issue-14254.rs:80:9
+   |
+LL |         baz();
+   |         ^^^ help: try: `self.baz`
+
+error[E0425]: cannot find value `bah` in this scope
+  --> $DIR/issue-14254.rs:82:9
+   |
+LL |         bah;
+   |         ^^^ help: try: `Self::bah`
+
+error[E0425]: cannot find function `baz` in this scope
+  --> $DIR/issue-14254.rs:89:9
+   |
+LL |         baz();
+   |         ^^^ help: try: `self.baz`
+
+error[E0425]: cannot find value `bah` in this scope
+  --> $DIR/issue-14254.rs:91:9
+   |
+LL |         bah;
+   |         ^^^ help: try: `Self::bah`
+
+error[E0425]: cannot find function `baz` in this scope
+  --> $DIR/issue-14254.rs:98:9
+   |
+LL |         baz();
+   |         ^^^ help: try: `self.baz`
+
+error[E0425]: cannot find value `bah` in this scope
+  --> $DIR/issue-14254.rs:100:9
+   |
+LL |         bah;
+   |         ^^^ help: try: `Self::bah`
+
+error: aborting due to 24 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/resolve/issue-16058.rs b/src/test/ui/resolve/issue-16058.rs
new file mode 100644
index 0000000..d41023e
--- /dev/null
+++ b/src/test/ui/resolve/issue-16058.rs
@@ -0,0 +1,16 @@
+pub struct GslResult {
+    pub val: f64,
+    pub err: f64
+}
+
+impl GslResult {
+    pub fn new() -> GslResult {
+        Result {
+//~^ ERROR expected struct, variant or union type, found enum `Result`
+            val: 0f64,
+            err: 0f64
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/resolve/issue-16058.stderr b/src/test/ui/resolve/issue-16058.stderr
new file mode 100644
index 0000000..9766f8f
--- /dev/null
+++ b/src/test/ui/resolve/issue-16058.stderr
@@ -0,0 +1,17 @@
+error[E0574]: expected struct, variant or union type, found enum `Result`
+  --> $DIR/issue-16058.rs:8:9
+   |
+LL |         Result {
+   |         ^^^^^^ not a struct, variant or union type
+help: possible better candidates are found in other modules, you can import them into scope
+   |
+LL | use std::fmt::Result;
+   |
+LL | use std::io::Result;
+   |
+LL | use std::thread::Result;
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0574`.
diff --git a/src/test/ui/resolve/issue-17518.rs b/src/test/ui/resolve/issue-17518.rs
new file mode 100644
index 0000000..edaebc8
--- /dev/null
+++ b/src/test/ui/resolve/issue-17518.rs
@@ -0,0 +1,7 @@
+enum SomeEnum {
+    E
+}
+
+fn main() {
+    E { name: "foobar" }; //~ ERROR cannot find struct, variant or union type `E`
+}
diff --git a/src/test/ui/resolve/issue-17518.stderr b/src/test/ui/resolve/issue-17518.stderr
new file mode 100644
index 0000000..057aac2
--- /dev/null
+++ b/src/test/ui/resolve/issue-17518.stderr
@@ -0,0 +1,13 @@
+error[E0422]: cannot find struct, variant or union type `E` in this scope
+  --> $DIR/issue-17518.rs:6:5
+   |
+LL |     E { name: "foobar" };
+   |     ^ not found in this scope
+help: possible candidate is found in another module, you can import it into scope
+   |
+LL | use SomeEnum::E;
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0422`.
diff --git a/src/test/ui/resolve/issue-18252.rs b/src/test/ui/resolve/issue-18252.rs
new file mode 100644
index 0000000..8947621
--- /dev/null
+++ b/src/test/ui/resolve/issue-18252.rs
@@ -0,0 +1,8 @@
+enum Foo {
+    Variant { x: usize }
+}
+
+fn main() {
+    let f = Foo::Variant(42);
+    //~^ ERROR expected function, found struct variant `Foo::Variant`
+}
diff --git a/src/test/ui/resolve/issue-18252.stderr b/src/test/ui/resolve/issue-18252.stderr
new file mode 100644
index 0000000..293f290
--- /dev/null
+++ b/src/test/ui/resolve/issue-18252.stderr
@@ -0,0 +1,9 @@
+error[E0423]: expected function, found struct variant `Foo::Variant`
+  --> $DIR/issue-18252.rs:6:13
+   |
+LL |     let f = Foo::Variant(42);
+   |             ^^^^^^^^^^^^ did you mean `Foo::Variant { /* fields */ }`?
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0423`.
diff --git a/src/test/ui/resolve/issue-19452.rs b/src/test/ui/resolve/issue-19452.rs
new file mode 100644
index 0000000..1d3aa49
--- /dev/null
+++ b/src/test/ui/resolve/issue-19452.rs
@@ -0,0 +1,15 @@
+// aux-build:issue-19452-aux.rs
+
+extern crate issue_19452_aux;
+
+enum Homura {
+    Madoka { age: u32 }
+}
+
+fn main() {
+    let homura = Homura::Madoka;
+    //~^ ERROR expected value, found struct variant `Homura::Madoka`
+
+    let homura = issue_19452_aux::Homura::Madoka;
+    //~^ ERROR expected value, found struct variant `issue_19452_aux::Homura::Madoka`
+}
diff --git a/src/test/ui/resolve/issue-19452.stderr b/src/test/ui/resolve/issue-19452.stderr
new file mode 100644
index 0000000..56a0e39
--- /dev/null
+++ b/src/test/ui/resolve/issue-19452.stderr
@@ -0,0 +1,15 @@
+error[E0423]: expected value, found struct variant `Homura::Madoka`
+  --> $DIR/issue-19452.rs:10:18
+   |
+LL |     let homura = Homura::Madoka;
+   |                  ^^^^^^^^^^^^^^ did you mean `Homura::Madoka { /* fields */ }`?
+
+error[E0423]: expected value, found struct variant `issue_19452_aux::Homura::Madoka`
+  --> $DIR/issue-19452.rs:13:18
+   |
+LL |     let homura = issue_19452_aux::Homura::Madoka;
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ did you mean `issue_19452_aux::Homura::Madoka { /* fields */ }`?
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0423`.
diff --git a/src/test/ui/resolve/issue-21221-1.rs b/src/test/ui/resolve/issue-21221-1.rs
new file mode 100644
index 0000000..b180624
--- /dev/null
+++ b/src/test/ui/resolve/issue-21221-1.rs
@@ -0,0 +1,75 @@
+mod mul1 {
+    pub trait Mul {}
+}
+
+mod mul2 {
+    pub trait Mul {}
+}
+
+mod mul3 {
+    enum Mul {
+      Yes,
+      No
+    }
+}
+
+mod mul4 {
+    type Mul = String;
+}
+
+mod mul5 {
+    struct Mul{
+        left_term: u32,
+        right_term: u32
+    }
+}
+
+#[derive(Debug)]
+struct Foo;
+
+// When we comment the next line:
+//use mul1::Mul;
+
+// BEFORE, we got the following error for the `impl` below:
+//   error: use of undeclared trait name `Mul` [E0405]
+// AFTER, we get this message:
+//   error: trait `Mul` is not in scope.
+//   help: ...
+//   help: you can import several candidates into scope (`use ...;`):
+//   help:   `mul1::Mul`
+//   help:   `mul2::Mul`
+//   help:   `std::ops::Mul`
+
+impl Mul for Foo {
+//~^ ERROR cannot find trait `Mul`
+}
+
+// BEFORE, we got:
+//   error: use of undeclared type name `Mul` [E0412]
+// AFTER, we get:
+//   error: type name `Mul` is not in scope. Maybe you meant:
+//   help: ...
+//   help: you can import several candidates into scope (`use ...;`):
+//   help:   `mul1::Mul`
+//   help:   `mul2::Mul`
+//   help:   `mul3::Mul`
+//   help:   `mul4::Mul`
+//   help:   and 2 other candidates
+fn getMul() -> Mul {
+//~^ ERROR cannot find type `Mul`
+}
+
+// Let's also test what happens if the trait doesn't exist:
+impl ThisTraitReallyDoesntExistInAnyModuleReally for Foo {
+//~^ ERROR cannot find trait `ThisTraitReallyDoesntExistInAnyModuleReally`
+}
+
+// Let's also test what happens if there's just one alternative:
+impl Div for Foo {
+//~^ ERROR cannot find trait `Div`
+}
+
+fn main() {
+    let foo = Foo();
+    println!("Hello, {:?}!", foo);
+}
diff --git a/src/test/ui/resolve/issue-21221-1.stderr b/src/test/ui/resolve/issue-21221-1.stderr
new file mode 100644
index 0000000..925923f
--- /dev/null
+++ b/src/test/ui/resolve/issue-21221-1.stderr
@@ -0,0 +1,51 @@
+error[E0405]: cannot find trait `Mul` in this scope
+  --> $DIR/issue-21221-1.rs:43:6
+   |
+LL | impl Mul for Foo {
+   |      ^^^ not found in this scope
+help: possible candidates are found in other modules, you can import them into scope
+   |
+LL | use mul1::Mul;
+   |
+LL | use mul2::Mul;
+   |
+LL | use std::ops::Mul;
+   |
+
+error[E0412]: cannot find type `Mul` in this scope
+  --> $DIR/issue-21221-1.rs:58:16
+   |
+LL | fn getMul() -> Mul {
+   |                ^^^ not found in this scope
+help: possible candidates are found in other modules, you can import them into scope
+   |
+LL | use mul1::Mul;
+   |
+LL | use mul2::Mul;
+   |
+LL | use mul3::Mul;
+   |
+LL | use mul4::Mul;
+   |
+and 2 other candidates
+
+error[E0405]: cannot find trait `ThisTraitReallyDoesntExistInAnyModuleReally` in this scope
+  --> $DIR/issue-21221-1.rs:63:6
+   |
+LL | impl ThisTraitReallyDoesntExistInAnyModuleReally for Foo {
+   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
+
+error[E0405]: cannot find trait `Div` in this scope
+  --> $DIR/issue-21221-1.rs:68:6
+   |
+LL | impl Div for Foo {
+   |      ^^^ not found in this scope
+help: possible candidate is found in another module, you can import it into scope
+   |
+LL | use std::ops::Div;
+   |
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0405, E0412.
+For more information about an error, try `rustc --explain E0405`.
diff --git a/src/test/ui/resolve/issue-21221-2.rs b/src/test/ui/resolve/issue-21221-2.rs
new file mode 100644
index 0000000..dc13e46
--- /dev/null
+++ b/src/test/ui/resolve/issue-21221-2.rs
@@ -0,0 +1,21 @@
+pub mod foo {
+    pub mod bar {
+        // note: trait T is not public, but being in the current
+        // crate, it's fine to show it, since the programmer can
+        // decide to make it public based on the suggestion ...
+        pub trait T {}
+    }
+    // imports should be ignored:
+    use self::bar::T;
+}
+
+pub mod baz {
+    pub use foo;
+    pub use std::ops::{Mul as T};
+}
+
+struct Foo;
+impl T for Foo { }
+//~^ ERROR cannot find trait `T`
+
+fn main() {}
diff --git a/src/test/ui/resolve/issue-21221-2.stderr b/src/test/ui/resolve/issue-21221-2.stderr
new file mode 100644
index 0000000..23d4015
--- /dev/null
+++ b/src/test/ui/resolve/issue-21221-2.stderr
@@ -0,0 +1,13 @@
+error[E0405]: cannot find trait `T` in this scope
+  --> $DIR/issue-21221-2.rs:18:6
+   |
+LL | impl T for Foo { }
+   |      ^ not found in this scope
+help: possible candidate is found in another module, you can import it into scope
+   |
+LL | use foo::bar::T;
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0405`.
diff --git a/src/test/ui/resolve/issue-21221-3.rs b/src/test/ui/resolve/issue-21221-3.rs
new file mode 100644
index 0000000..f0c0a9f
--- /dev/null
+++ b/src/test/ui/resolve/issue-21221-3.rs
@@ -0,0 +1,19 @@
+// testing whether the lookup mechanism picks up types
+// defined in the outside crate
+
+// aux-build:issue-21221-3.rs
+
+extern crate issue_21221_3;
+
+struct Foo;
+
+// NOTE: This shows only traits accessible from the current
+// crate, thus the two private entities:
+//   `issue_21221_3::outer::private_module::OuterTrait` and
+//   `issue_21221_3::outer::public_module::OuterTrait`
+// are hidden from the view.
+impl OuterTrait for Foo {}
+//~^ ERROR cannot find trait `OuterTrait`
+fn main() {
+    println!("Hello, world!");
+}
diff --git a/src/test/ui/resolve/issue-21221-3.stderr b/src/test/ui/resolve/issue-21221-3.stderr
new file mode 100644
index 0000000..09cfed9
--- /dev/null
+++ b/src/test/ui/resolve/issue-21221-3.stderr
@@ -0,0 +1,13 @@
+error[E0405]: cannot find trait `OuterTrait` in this scope
+  --> $DIR/issue-21221-3.rs:15:6
+   |
+LL | impl OuterTrait for Foo {}
+   |      ^^^^^^^^^^ not found in this scope
+help: possible candidate is found in another module, you can import it into scope
+   |
+LL | use issue_21221_3::outer::OuterTrait;
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0405`.
diff --git a/src/test/ui/resolve/issue-21221-4.rs b/src/test/ui/resolve/issue-21221-4.rs
new file mode 100644
index 0000000..88d5bd0
--- /dev/null
+++ b/src/test/ui/resolve/issue-21221-4.rs
@@ -0,0 +1,15 @@
+// testing whether the lookup mechanism picks up types
+// defined in the outside crate
+
+// aux-build:issue-21221-4.rs
+
+extern crate issue_21221_4;
+
+struct Foo;
+
+impl T for Foo {}
+//~^ ERROR cannot find trait `T`
+
+fn main() {
+    println!("Hello, world!");
+}
diff --git a/src/test/ui/resolve/issue-21221-4.stderr b/src/test/ui/resolve/issue-21221-4.stderr
new file mode 100644
index 0000000..68989a3
--- /dev/null
+++ b/src/test/ui/resolve/issue-21221-4.stderr
@@ -0,0 +1,13 @@
+error[E0405]: cannot find trait `T` in this scope
+  --> $DIR/issue-21221-4.rs:10:6
+   |
+LL | impl T for Foo {}
+   |      ^ not found in this scope
+help: possible candidate is found in another module, you can import it into scope
+   |
+LL | use issue_21221_4::T;
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0405`.
diff --git a/src/test/ui/resolve/issue-22692.rs b/src/test/ui/resolve/issue-22692.rs
new file mode 100644
index 0000000..1d8f442
--- /dev/null
+++ b/src/test/ui/resolve/issue-22692.rs
@@ -0,0 +1,3 @@
+fn main() {
+    let _ = String.new(); //~ ERROR expected value, found struct `String`
+}
diff --git a/src/test/ui/resolve/issue-22692.stderr b/src/test/ui/resolve/issue-22692.stderr
new file mode 100644
index 0000000..e076419
--- /dev/null
+++ b/src/test/ui/resolve/issue-22692.stderr
@@ -0,0 +1,11 @@
+error[E0423]: expected value, found struct `String`
+  --> $DIR/issue-22692.rs:2:13
+   |
+LL |     let _ = String.new();
+   |             ^^^^^^----
+   |             |
+   |             help: use the path separator to refer to an item: `String::new`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0423`.
diff --git a/src/test/ui/resolve/issue-23305.rs b/src/test/ui/resolve/issue-23305.rs
new file mode 100644
index 0000000..af335ac
--- /dev/null
+++ b/src/test/ui/resolve/issue-23305.rs
@@ -0,0 +1,8 @@
+pub trait ToNbt<T> {
+    fn new(val: T) -> Self;
+}
+
+impl ToNbt<Self> {}
+//~^ ERROR cycle detected
+
+fn main() {}
diff --git a/src/test/ui/resolve/issue-23305.stderr b/src/test/ui/resolve/issue-23305.stderr
new file mode 100644
index 0000000..1da56ad
--- /dev/null
+++ b/src/test/ui/resolve/issue-23305.stderr
@@ -0,0 +1,16 @@
+error[E0391]: cycle detected when processing `<impl at $DIR/issue-23305.rs:5:1: 5:20>`
+  --> $DIR/issue-23305.rs:5:12
+   |
+LL | impl ToNbt<Self> {}
+   |            ^^^^
+   |
+   = note: ...which again requires processing `<impl at $DIR/issue-23305.rs:5:1: 5:20>`, completing the cycle
+note: cycle used when collecting item types in top-level module
+  --> $DIR/issue-23305.rs:1:1
+   |
+LL | pub trait ToNbt<T> {
+   | ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/resolve/issue-2356.rs b/src/test/ui/resolve/issue-2356.rs
new file mode 100644
index 0000000..f7b2dd1
--- /dev/null
+++ b/src/test/ui/resolve/issue-2356.rs
@@ -0,0 +1,94 @@
+trait Groom {
+    fn shave(other: usize);
+}
+
+pub struct Cat {
+  whiskers: isize,
+}
+
+pub enum MaybeDog {
+    Dog,
+    NoDog
+}
+
+impl MaybeDog {
+  fn bark() {
+    // If this provides a suggestion, it's a bug as MaybeDog doesn't impl Groom
+    shave();
+    //~^ ERROR cannot find function `shave`
+  }
+}
+
+impl Clone for Cat {
+  fn clone(&self) -> Self {
+    clone();
+    //~^ ERROR cannot find function `clone`
+    loop {}
+  }
+}
+impl Default for Cat {
+  fn default() -> Self {
+    default();
+    //~^ ERROR cannot find function `default`
+    loop {}
+  }
+}
+
+impl Groom for Cat {
+  fn shave(other: usize) {
+    whiskers -= other;
+    //~^ ERROR cannot find value `whiskers`
+    shave(4);
+    //~^ ERROR cannot find function `shave`
+    purr();
+    //~^ ERROR cannot find function `purr`
+  }
+}
+
+impl Cat {
+    fn static_method() {}
+
+    fn purr_louder() {
+        static_method();
+        //~^ ERROR cannot find function `static_method`
+        purr();
+        //~^ ERROR cannot find function `purr`
+        purr();
+        //~^ ERROR cannot find function `purr`
+        purr();
+        //~^ ERROR cannot find function `purr`
+    }
+}
+
+impl Cat {
+  fn meow() {
+    if self.whiskers > 3 {
+        //~^ ERROR expected value, found module `self`
+        println!("MEOW");
+    }
+  }
+
+  fn purr(&self) {
+    grow_older();
+    //~^ ERROR cannot find function `grow_older`
+    shave();
+    //~^ ERROR cannot find function `shave`
+  }
+
+  fn burn_whiskers(&mut self) {
+    whiskers = 0;
+    //~^ ERROR cannot find value `whiskers`
+  }
+
+  pub fn grow_older(other:usize) {
+    whiskers = 4;
+    //~^ ERROR cannot find value `whiskers`
+    purr_louder();
+    //~^ ERROR cannot find function `purr_louder`
+  }
+}
+
+fn main() {
+    self += 1;
+    //~^ ERROR expected value, found module `self`
+}
diff --git a/src/test/ui/resolve/issue-2356.stderr b/src/test/ui/resolve/issue-2356.stderr
new file mode 100644
index 0000000..fb4acaa
--- /dev/null
+++ b/src/test/ui/resolve/issue-2356.stderr
@@ -0,0 +1,112 @@
+error[E0425]: cannot find function `shave` in this scope
+  --> $DIR/issue-2356.rs:17:5
+   |
+LL |     shave();
+   |     ^^^^^ not found in this scope
+
+error[E0425]: cannot find function `clone` in this scope
+  --> $DIR/issue-2356.rs:24:5
+   |
+LL |     clone();
+   |     ^^^^^ help: try: `self.clone`
+
+error[E0425]: cannot find function `default` in this scope
+  --> $DIR/issue-2356.rs:31:5
+   |
+LL |     default();
+   |     ^^^^^^^ help: try: `Self::default`
+
+error[E0425]: cannot find value `whiskers` in this scope
+  --> $DIR/issue-2356.rs:39:5
+   |
+LL |     whiskers -= other;
+   |     ^^^^^^^^
+   |     |
+   |     `self` value is a keyword only available in methods with `self` parameter
+   |     help: try: `self.whiskers`
+
+error[E0425]: cannot find function `shave` in this scope
+  --> $DIR/issue-2356.rs:41:5
+   |
+LL |     shave(4);
+   |     ^^^^^ help: try: `Self::shave`
+
+error[E0425]: cannot find function `purr` in this scope
+  --> $DIR/issue-2356.rs:43:5
+   |
+LL |     purr();
+   |     ^^^^ not found in this scope
+
+error[E0425]: cannot find function `static_method` in this scope
+  --> $DIR/issue-2356.rs:52:9
+   |
+LL |         static_method();
+   |         ^^^^^^^^^^^^^ not found in this scope
+
+error[E0425]: cannot find function `purr` in this scope
+  --> $DIR/issue-2356.rs:54:9
+   |
+LL |         purr();
+   |         ^^^^ not found in this scope
+
+error[E0425]: cannot find function `purr` in this scope
+  --> $DIR/issue-2356.rs:56:9
+   |
+LL |         purr();
+   |         ^^^^ not found in this scope
+
+error[E0425]: cannot find function `purr` in this scope
+  --> $DIR/issue-2356.rs:58:9
+   |
+LL |         purr();
+   |         ^^^^ not found in this scope
+
+error[E0424]: expected value, found module `self`
+  --> $DIR/issue-2356.rs:65:8
+   |
+LL |     if self.whiskers > 3 {
+   |        ^^^^ `self` value is a keyword only available in methods with `self` parameter
+
+error[E0425]: cannot find function `grow_older` in this scope
+  --> $DIR/issue-2356.rs:72:5
+   |
+LL |     grow_older();
+   |     ^^^^^^^^^^ not found in this scope
+
+error[E0425]: cannot find function `shave` in this scope
+  --> $DIR/issue-2356.rs:74:5
+   |
+LL |     shave();
+   |     ^^^^^ not found in this scope
+
+error[E0425]: cannot find value `whiskers` in this scope
+  --> $DIR/issue-2356.rs:79:5
+   |
+LL |     whiskers = 0;
+   |     ^^^^^^^^ help: try: `self.whiskers`
+
+error[E0425]: cannot find value `whiskers` in this scope
+  --> $DIR/issue-2356.rs:84:5
+   |
+LL |     whiskers = 4;
+   |     ^^^^^^^^
+   |     |
+   |     `self` value is a keyword only available in methods with `self` parameter
+   |     help: try: `self.whiskers`
+
+error[E0425]: cannot find function `purr_louder` in this scope
+  --> $DIR/issue-2356.rs:86:5
+   |
+LL |     purr_louder();
+   |     ^^^^^^^^^^^ not found in this scope
+
+error[E0424]: expected value, found module `self`
+  --> $DIR/issue-2356.rs:92:5
+   |
+LL |     self += 1;
+   |     ^^^^ `self` value is a keyword only available in methods with `self` parameter
+
+error: aborting due to 17 previous errors
+
+Some errors occurred: E0424, E0425.
+For more information about an error, try `rustc --explain E0424`.
diff --git a/src/test/ui/resolve/issue-24968.rs b/src/test/ui/resolve/issue-24968.rs
new file mode 100644
index 0000000..916b482
--- /dev/null
+++ b/src/test/ui/resolve/issue-24968.rs
@@ -0,0 +1,5 @@
+fn foo(_: Self) {
+//~^ ERROR cannot find type `Self`
+}
+
+fn main() {}
diff --git a/src/test/ui/resolve/issue-24968.stderr b/src/test/ui/resolve/issue-24968.stderr
new file mode 100644
index 0000000..c891952
--- /dev/null
+++ b/src/test/ui/resolve/issue-24968.stderr
@@ -0,0 +1,9 @@
+error[E0411]: cannot find type `Self` in this scope
+  --> $DIR/issue-24968.rs:1:11
+   |
+LL | fn foo(_: Self) {
+   |           ^^^^ `Self` is only available in impls, traits, and type definitions
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0411`.
diff --git a/src/test/ui/resolve/issue-33876.rs b/src/test/ui/resolve/issue-33876.rs
new file mode 100644
index 0000000..dd31fc2
--- /dev/null
+++ b/src/test/ui/resolve/issue-33876.rs
@@ -0,0 +1,12 @@
+use std::any::Any;
+
+struct Foo;
+
+trait Bar {}
+
+impl Bar for Foo {}
+
+fn main() {
+    let any: &Any = &Bar; //~ ERROR expected value, found trait `Bar`
+    if any.is::<u32>() { println!("u32"); }
+}
diff --git a/src/test/ui/resolve/issue-33876.stderr b/src/test/ui/resolve/issue-33876.stderr
new file mode 100644
index 0000000..29a63fd
--- /dev/null
+++ b/src/test/ui/resolve/issue-33876.stderr
@@ -0,0 +1,9 @@
+error[E0423]: expected value, found trait `Bar`
+  --> $DIR/issue-33876.rs:10:22
+   |
+LL |     let any: &Any = &Bar;
+   |                      ^^^ not a value
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0423`.
diff --git a/src/test/ui/resolve/issue-3907-2.rs b/src/test/ui/resolve/issue-3907-2.rs
new file mode 100644
index 0000000..dc96246
--- /dev/null
+++ b/src/test/ui/resolve/issue-3907-2.rs
@@ -0,0 +1,14 @@
+// aux-build:issue-3907.rs
+
+extern crate issue_3907;
+
+type Foo = issue_3907::Foo+'static;
+
+struct S {
+    name: isize
+}
+
+fn bar(_x: Foo) {}
+//~^ ERROR E0038
+
+fn main() {}
diff --git a/src/test/ui/resolve/issue-3907-2.stderr b/src/test/ui/resolve/issue-3907-2.stderr
new file mode 100644
index 0000000..968c1f3
--- /dev/null
+++ b/src/test/ui/resolve/issue-3907-2.stderr
@@ -0,0 +1,11 @@
+error[E0038]: the trait `issue_3907::Foo` cannot be made into an object
+  --> $DIR/issue-3907-2.rs:11:1
+   |
+LL | fn bar(_x: Foo) {}
+   | ^^^^^^^^^^^^^^^ the trait `issue_3907::Foo` cannot be made into an object
+   |
+   = note: method `bar` has no receiver
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/resolve/issue-3907.rs b/src/test/ui/resolve/issue-3907.rs
new file mode 100644
index 0000000..87e4654
--- /dev/null
+++ b/src/test/ui/resolve/issue-3907.rs
@@ -0,0 +1,20 @@
+// aux-build:issue-3907.rs
+
+extern crate issue_3907;
+
+type Foo = issue_3907::Foo;
+
+struct S {
+    name: isize
+}
+
+impl Foo for S { //~ ERROR expected trait, found type alias `Foo`
+    fn bar() { }
+}
+
+fn main() {
+    let s = S {
+        name: 0
+    };
+    s.bar();
+}
diff --git a/src/test/ui/resolve/issue-3907.stderr b/src/test/ui/resolve/issue-3907.stderr
new file mode 100644
index 0000000..384df57
--- /dev/null
+++ b/src/test/ui/resolve/issue-3907.stderr
@@ -0,0 +1,15 @@
+error[E0404]: expected trait, found type alias `Foo`
+  --> $DIR/issue-3907.rs:11:6
+   |
+LL | impl Foo for S {
+   |      ^^^ type aliases cannot be used as traits
+   |
+   = note: did you mean to use a trait alias?
+help: possible better candidate is found in another module, you can import it into scope
+   |
+LL | use issue_3907::Foo;
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0404`.
diff --git a/src/test/ui/resolve/issue-39226.rs b/src/test/ui/resolve/issue-39226.rs
new file mode 100644
index 0000000..0f784f0
--- /dev/null
+++ b/src/test/ui/resolve/issue-39226.rs
@@ -0,0 +1,14 @@
+struct Handle {}
+
+struct Something {
+    handle: Handle
+}
+
+fn main() {
+    let handle: Handle = Handle {};
+
+    let s: Something = Something {
+        handle: Handle
+        //~^ ERROR expected value, found struct `Handle`
+    };
+}
diff --git a/src/test/ui/resolve/issue-39226.stderr b/src/test/ui/resolve/issue-39226.stderr
new file mode 100644
index 0000000..c97fb4d
--- /dev/null
+++ b/src/test/ui/resolve/issue-39226.stderr
@@ -0,0 +1,12 @@
+error[E0423]: expected value, found struct `Handle`
+  --> $DIR/issue-39226.rs:11:17
+   |
+LL |         handle: Handle
+   |                 ^^^^^^
+   |                 |
+   |                 did you mean `Handle { /* fields */ }`?
+   |                 help: a local variable with a similar name exists: `handle`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0423`.
diff --git a/src/test/ui/resolve/issue-5035-2.rs b/src/test/ui/resolve/issue-5035-2.rs
new file mode 100644
index 0000000..f88a237
--- /dev/null
+++ b/src/test/ui/resolve/issue-5035-2.rs
@@ -0,0 +1,7 @@
+trait I {}
+type K = I+'static;
+
+fn foo(_x: K) {}
+//~^ ERROR the size for values of type
+
+fn main() {}
diff --git a/src/test/ui/resolve/issue-5035-2.stderr b/src/test/ui/resolve/issue-5035-2.stderr
new file mode 100644
index 0000000..89eb3d9
--- /dev/null
+++ b/src/test/ui/resolve/issue-5035-2.stderr
@@ -0,0 +1,14 @@
+error[E0277]: the size for values of type `(dyn I + 'static)` cannot be known at compilation time
+  --> $DIR/issue-5035-2.rs:4:8
+   |
+LL | fn foo(_x: K) {}
+   |        ^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `(dyn I + 'static)`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: all local variables must have a statically known size
+   = help: unsized locals are gated as an unstable feature
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/resolve/issue-5035.rs b/src/test/ui/resolve/issue-5035.rs
new file mode 100644
index 0000000..c00567a
--- /dev/null
+++ b/src/test/ui/resolve/issue-5035.rs
@@ -0,0 +1,9 @@
+trait I {}
+type K = I;
+impl K for isize {} //~ ERROR expected trait, found type alias `K`
+
+use ImportError; //~ ERROR unresolved import `ImportError` [E0432]
+                 //~^ no `ImportError` in the root
+impl ImportError for () {} // check that this is not an additional error (cf. issue #35142)
+
+fn main() {}
diff --git a/src/test/ui/resolve/issue-5035.stderr b/src/test/ui/resolve/issue-5035.stderr
new file mode 100644
index 0000000..68d35f3
--- /dev/null
+++ b/src/test/ui/resolve/issue-5035.stderr
@@ -0,0 +1,21 @@
+error[E0432]: unresolved import `ImportError`
+  --> $DIR/issue-5035.rs:5:5
+   |
+LL | use ImportError;
+   |     ^^^^^^^^^^^ no `ImportError` in the root
+
+error[E0404]: expected trait, found type alias `K`
+  --> $DIR/issue-5035.rs:3:6
+   |
+LL | impl K for isize {}
+   |      ^
+   |      |
+   |      type aliases cannot be used as traits
+   |      help: a trait with a similar name exists: `I`
+   |
+   = note: did you mean to use a trait alias?
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0404, E0432.
+For more information about an error, try `rustc --explain E0404`.
diff --git a/src/test/ui/resolve/issue-54379.rs b/src/test/ui/resolve/issue-54379.rs
new file mode 100644
index 0000000..807c543
--- /dev/null
+++ b/src/test/ui/resolve/issue-54379.rs
@@ -0,0 +1,14 @@
+struct MyStruct {
+    pub s1: Option<String>,
+}
+
+fn main() {
+    let thing = MyStruct { s1: None };
+
+    match thing {
+        MyStruct { .., Some(_) } => {},
+        //~^ ERROR expected `,`
+        //~| ERROR expected `}`, found `,`
+        _ => {}
+    }
+}
diff --git a/src/test/ui/resolve/issue-54379.stderr b/src/test/ui/resolve/issue-54379.stderr
new file mode 100644
index 0000000..2a6b545
--- /dev/null
+++ b/src/test/ui/resolve/issue-54379.stderr
@@ -0,0 +1,17 @@
+error: expected `}`, found `,`
+  --> $DIR/issue-54379.rs:9:22
+   |
+LL |         MyStruct { .., Some(_) } => {},
+   |                    --^
+   |                    | |
+   |                    | expected `}`
+   |                    `..` must be at the end and cannot have a trailing comma
+
+error: expected `,`
+  --> $DIR/issue-54379.rs:9:24
+   |
+LL |         MyStruct { .., Some(_) } => {},
+   |                        ^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/resolve/issue-57523.rs b/src/test/ui/resolve/issue-57523.rs
new file mode 100644
index 0000000..c2a2f28
--- /dev/null
+++ b/src/test/ui/resolve/issue-57523.rs
@@ -0,0 +1,21 @@
+// compile-pass
+
+struct S(u8);
+
+impl S {
+    fn method1() -> Self {
+        Self(0)
+    }
+}
+
+macro_rules! define_method { () => {
+    impl S {
+        fn method2() -> Self {
+            Self(0) // OK
+        }
+    }
+}}
+
+define_method!();
+
+fn main() {}
diff --git a/src/test/ui/resolve/issue-6702.rs b/src/test/ui/resolve/issue-6702.rs
new file mode 100644
index 0000000..6469c7e
--- /dev/null
+++ b/src/test/ui/resolve/issue-6702.rs
@@ -0,0 +1,8 @@
+struct Monster {
+    damage: isize
+}
+
+
+fn main() {
+    let _m = Monster(); //~ ERROR expected function, found struct `Monster`
+}
diff --git a/src/test/ui/resolve/issue-6702.stderr b/src/test/ui/resolve/issue-6702.stderr
new file mode 100644
index 0000000..9a46f0d
--- /dev/null
+++ b/src/test/ui/resolve/issue-6702.stderr
@@ -0,0 +1,9 @@
+error[E0423]: expected function, found struct `Monster`
+  --> $DIR/issue-6702.rs:7:14
+   |
+LL |     let _m = Monster();
+   |              ^^^^^^^ did you mean `Monster { /* fields */ }`?
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0423`.
diff --git a/src/test/ui/resolve/levenshtein.rs b/src/test/ui/resolve/levenshtein.rs
new file mode 100644
index 0000000..a6f4716
--- /dev/null
+++ b/src/test/ui/resolve/levenshtein.rs
@@ -0,0 +1,31 @@
+const MAX_ITEM: usize = 10;
+
+fn foo_bar() {}
+
+fn foo(c: esize) {} // Misspelled primitive type name.
+//~^ ERROR cannot find
+
+enum Bar { }
+
+type A = Baz; // Misspelled type name.
+//~^ ERROR cannot find
+type B = Opiton<u8>; // Misspelled type name from the prelude.
+//~^ ERROR cannot find
+
+mod m {
+    type A = Baz; // No suggestion here, Bar is not visible
+    //~^ ERROR cannot find
+
+    pub struct First;
+    pub struct Second;
+}
+
+fn main() {
+    let v = [0u32; MAXITEM]; // Misspelled constant name.
+    //~^ ERROR cannot find
+    foobar(); // Misspelled function name.
+    //~^ ERROR cannot find
+    let b: m::first = m::second; // Misspelled item in module.
+    //~^ ERROR cannot find
+    //~| ERROR cannot find
+}
diff --git a/src/test/ui/resolve/levenshtein.stderr b/src/test/ui/resolve/levenshtein.stderr
new file mode 100644
index 0000000..cddfe4e
--- /dev/null
+++ b/src/test/ui/resolve/levenshtein.stderr
@@ -0,0 +1,52 @@
+error[E0412]: cannot find type `esize` in this scope
+  --> $DIR/levenshtein.rs:5:11
+   |
+LL | fn foo(c: esize) {} // Misspelled primitive type name.
+   |           ^^^^^ help: a primitive type with a similar name exists: `isize`
+
+error[E0412]: cannot find type `Baz` in this scope
+  --> $DIR/levenshtein.rs:10:10
+   |
+LL | type A = Baz; // Misspelled type name.
+   |          ^^^ help: an enum with a similar name exists: `Bar`
+
+error[E0412]: cannot find type `Opiton` in this scope
+  --> $DIR/levenshtein.rs:12:10
+   |
+LL | type B = Opiton<u8>; // Misspelled type name from the prelude.
+   |          ^^^^^^ help: an enum with a similar name exists: `Option`
+
+error[E0412]: cannot find type `Baz` in this scope
+  --> $DIR/levenshtein.rs:16:14
+   |
+LL |     type A = Baz; // No suggestion here, Bar is not visible
+   |              ^^^ not found in this scope
+
+error[E0425]: cannot find value `MAXITEM` in this scope
+  --> $DIR/levenshtein.rs:24:20
+   |
+LL |     let v = [0u32; MAXITEM]; // Misspelled constant name.
+   |                    ^^^^^^^ help: a constant with a similar name exists: `MAX_ITEM`
+
+error[E0425]: cannot find function `foobar` in this scope
+  --> $DIR/levenshtein.rs:26:5
+   |
+LL |     foobar(); // Misspelled function name.
+   |     ^^^^^^ help: a function with a similar name exists: `foo_bar`
+
+error[E0412]: cannot find type `first` in module `m`
+  --> $DIR/levenshtein.rs:28:15
+   |
+LL |     let b: m::first = m::second; // Misspelled item in module.
+   |               ^^^^^ help: a struct with a similar name exists: `First`
+
+error[E0425]: cannot find value `second` in module `m`
+  --> $DIR/levenshtein.rs:28:26
+   |
+LL |     let b: m::first = m::second; // Misspelled item in module.
+   |                          ^^^^^^ help: a unit struct with a similar name exists: `Second`
+
+error: aborting due to 8 previous errors
+
+Some errors occurred: E0412, E0425.
+For more information about an error, try `rustc --explain E0412`.
diff --git a/src/test/ui/resolve/name-clash-nullary.rs b/src/test/ui/resolve/name-clash-nullary.rs
new file mode 100644
index 0000000..b5f5e12
--- /dev/null
+++ b/src/test/ui/resolve/name-clash-nullary.rs
@@ -0,0 +1,3 @@
+fn main() {
+  let None: isize = 42; //~ ERROR mismatched types
+}
diff --git a/src/test/ui/resolve/name-clash-nullary.stderr b/src/test/ui/resolve/name-clash-nullary.stderr
new file mode 100644
index 0000000..51793f4
--- /dev/null
+++ b/src/test/ui/resolve/name-clash-nullary.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/name-clash-nullary.rs:2:7
+   |
+LL |   let None: isize = 42;
+   |       ^^^^ expected isize, found enum `std::option::Option`
+   |
+   = note: expected type `isize`
+              found type `std::option::Option<_>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/resolve/privacy-enum-ctor.rs b/src/test/ui/resolve/privacy-enum-ctor.rs
new file mode 100644
index 0000000..f0d2cf8
--- /dev/null
+++ b/src/test/ui/resolve/privacy-enum-ctor.rs
@@ -0,0 +1,71 @@
+mod m {
+    pub enum E {
+        Fn(u8),
+        Struct {
+            s: u8,
+        },
+        Unit,
+    }
+
+    pub mod n {
+        pub(in m) enum Z {
+            Fn(u8),
+            Struct {
+                s: u8,
+            },
+            Unit,
+        }
+    }
+
+    use m::n::Z; // OK, only the type is imported
+
+    fn f() {
+        n::Z;
+        //~^ ERROR expected value, found enum `n::Z`
+        Z;
+        //~^ ERROR expected value, found enum `Z`
+        let _: Z = Z::Fn;
+        //~^ ERROR mismatched types
+        let _: Z = Z::Struct;
+        //~^ ERROR expected value, found struct variant `Z::Struct`
+        let _ = Z::Unit();
+        //~^ ERROR expected function, found enum variant `Z::Unit`
+        let _ = Z::Unit {};
+        // This is ok, it is equivalent to not having braces
+    }
+}
+
+use m::E; // OK, only the type is imported
+
+fn main() {
+    let _: E = m::E;
+    //~^ ERROR expected value, found enum `m::E`
+    let _: E = m::E::Fn;
+    //~^ ERROR mismatched types
+    let _: E = m::E::Struct;
+    //~^ ERROR expected value, found struct variant `m::E::Struct`
+    let _: E = m::E::Unit();
+    //~^ ERROR expected function, found enum variant `m::E::Unit`
+    let _: E = E;
+    //~^ ERROR expected value, found enum `E`
+    let _: E = E::Fn;
+    //~^ ERROR mismatched types
+    let _: E = E::Struct;
+    //~^ ERROR expected value, found struct variant `E::Struct`
+    let _: E = E::Unit();
+    //~^ ERROR expected function, found enum variant `E::Unit`
+    let _: Z = m::n::Z;
+    //~^ ERROR cannot find type `Z` in this scope
+    //~| ERROR expected value, found enum `m::n::Z`
+    //~| ERROR enum `Z` is private
+    let _: Z = m::n::Z::Fn;
+    //~^ ERROR cannot find type `Z` in this scope
+    //~| ERROR enum `Z` is private
+    let _: Z = m::n::Z::Struct;
+    //~^ ERROR cannot find type `Z` in this scope
+    //~| ERROR expected value, found struct variant `m::n::Z::Struct`
+    //~| ERROR enum `Z` is private
+    let _: Z = m::n::Z::Unit {};
+    //~^ ERROR cannot find type `Z` in this scope
+    //~| ERROR enum `Z` is private
+}
diff --git a/src/test/ui/resolve/privacy-enum-ctor.stderr b/src/test/ui/resolve/privacy-enum-ctor.stderr
new file mode 100644
index 0000000..75d9c97
--- /dev/null
+++ b/src/test/ui/resolve/privacy-enum-ctor.stderr
@@ -0,0 +1,270 @@
+error[E0423]: expected value, found enum `n::Z`
+  --> $DIR/privacy-enum-ctor.rs:23:9
+   |
+LL |         n::Z;
+   |         ^^^^
+help: try using one of the enum's variants
+   |
+LL |         m::Z::Fn;
+   |         ^^^^^^^^
+LL |         m::Z::Struct;
+   |         ^^^^^^^^^^^^
+LL |         m::Z::Unit;
+   |         ^^^^^^^^^^
+
+error[E0423]: expected value, found enum `Z`
+  --> $DIR/privacy-enum-ctor.rs:25:9
+   |
+LL |         Z;
+   |         ^
+help: a function with a similar name exists
+   |
+LL |         f;
+   |         ^
+help: try using one of the enum's variants
+   |
+LL |         m::Z::Fn;
+   |         ^^^^^^^^
+LL |         m::Z::Struct;
+   |         ^^^^^^^^^^^^
+LL |         m::Z::Unit;
+   |         ^^^^^^^^^^
+
+error[E0423]: expected value, found struct variant `Z::Struct`
+  --> $DIR/privacy-enum-ctor.rs:29:20
+   |
+LL |         let _: Z = Z::Struct;
+   |                    ^^^^^^^^^ did you mean `Z::Struct { /* fields */ }`?
+
+error[E0423]: expected value, found enum `m::E`
+  --> $DIR/privacy-enum-ctor.rs:41:16
+   |
+LL |     let _: E = m::E;
+   |                ^^^^
+help: a function with a similar name exists
+   |
+LL |     let _: E = m::f;
+   |                   ^
+help: try using one of the enum's variants
+   |
+LL |     let _: E = E::Fn;
+   |                ^^^^^
+LL |     let _: E = E::Struct;
+   |                ^^^^^^^^^
+LL |     let _: E = E::Unit;
+   |                ^^^^^^^
+help: possible better candidates are found in other modules, you can import them into scope
+   |
+LL | use std::f32::consts::E;
+   |
+LL | use std::f64::consts::E;
+   |
+
+error[E0423]: expected value, found struct variant `m::E::Struct`
+  --> $DIR/privacy-enum-ctor.rs:45:16
+   |
+LL |     let _: E = m::E::Struct;
+   |                ^^^^^^^^^^^^ did you mean `m::E::Struct { /* fields */ }`?
+
+error[E0423]: expected value, found enum `E`
+  --> $DIR/privacy-enum-ctor.rs:49:16
+   |
+LL |     let _: E = E;
+   |                ^
+help: try using one of the enum's variants
+   |
+LL |     let _: E = E::Fn;
+   |                ^^^^^
+LL |     let _: E = E::Struct;
+   |                ^^^^^^^^^
+LL |     let _: E = E::Unit;
+   |                ^^^^^^^
+help: possible better candidates are found in other modules, you can import them into scope
+   |
+LL | use std::f32::consts::E;
+   |
+LL | use std::f64::consts::E;
+   |
+
+error[E0423]: expected value, found struct variant `E::Struct`
+  --> $DIR/privacy-enum-ctor.rs:53:16
+   |
+LL |     let _: E = E::Struct;
+   |                ^^^^^^^^^ did you mean `E::Struct { /* fields */ }`?
+
+error[E0412]: cannot find type `Z` in this scope
+  --> $DIR/privacy-enum-ctor.rs:57:12
+   |
+LL |     let _: Z = m::n::Z;
+   |            ^
+help: an enum with a similar name exists
+   |
+LL |     let _: E = m::n::Z;
+   |            ^
+help: possible candidate is found in another module, you can import it into scope
+   |
+LL | use m::n::Z;
+   |
+
+error[E0423]: expected value, found enum `m::n::Z`
+  --> $DIR/privacy-enum-ctor.rs:57:16
+   |
+LL |     let _: Z = m::n::Z;
+   |                ^^^^^^^
+help: try using one of the enum's variants
+   |
+LL |     let _: Z = m::Z::Fn;
+   |                ^^^^^^^^
+LL |     let _: Z = m::Z::Struct;
+   |                ^^^^^^^^^^^^
+LL |     let _: Z = m::Z::Unit;
+   |                ^^^^^^^^^^
+
+error[E0412]: cannot find type `Z` in this scope
+  --> $DIR/privacy-enum-ctor.rs:61:12
+   |
+LL |     let _: Z = m::n::Z::Fn;
+   |            ^
+help: an enum with a similar name exists
+   |
+LL |     let _: E = m::n::Z::Fn;
+   |            ^
+help: possible candidate is found in another module, you can import it into scope
+   |
+LL | use m::n::Z;
+   |
+
+error[E0412]: cannot find type `Z` in this scope
+  --> $DIR/privacy-enum-ctor.rs:64:12
+   |
+LL |     let _: Z = m::n::Z::Struct;
+   |            ^
+help: an enum with a similar name exists
+   |
+LL |     let _: E = m::n::Z::Struct;
+   |            ^
+help: possible candidate is found in another module, you can import it into scope
+   |
+LL | use m::n::Z;
+   |
+
+error[E0423]: expected value, found struct variant `m::n::Z::Struct`
+  --> $DIR/privacy-enum-ctor.rs:64:16
+   |
+LL |     let _: Z = m::n::Z::Struct;
+   |                ^^^^^^^^^^^^^^^ did you mean `m::n::Z::Struct { /* fields */ }`?
+
+error[E0412]: cannot find type `Z` in this scope
+  --> $DIR/privacy-enum-ctor.rs:68:12
+   |
+LL |     let _: Z = m::n::Z::Unit {};
+   |            ^
+help: an enum with a similar name exists
+   |
+LL |     let _: E = m::n::Z::Unit {};
+   |            ^
+help: possible candidate is found in another module, you can import it into scope
+   |
+LL | use m::n::Z;
+   |
+
+error[E0603]: enum `Z` is private
+  --> $DIR/privacy-enum-ctor.rs:57:22
+   |
+LL |     let _: Z = m::n::Z;
+   |                      ^
+
+error[E0603]: enum `Z` is private
+  --> $DIR/privacy-enum-ctor.rs:61:22
+   |
+LL |     let _: Z = m::n::Z::Fn;
+   |                      ^
+
+error[E0603]: enum `Z` is private
+  --> $DIR/privacy-enum-ctor.rs:64:22
+   |
+LL |     let _: Z = m::n::Z::Struct;
+   |                      ^
+
+error[E0603]: enum `Z` is private
+  --> $DIR/privacy-enum-ctor.rs:68:22
+   |
+LL |     let _: Z = m::n::Z::Unit {};
+   |                      ^
+
+error[E0308]: mismatched types
+  --> $DIR/privacy-enum-ctor.rs:27:20
+   |
+LL |         let _: Z = Z::Fn;
+   |                    ^^^^^ expected enum `m::n::Z`, found fn item
+   |
+   = note: expected type `m::n::Z`
+              found type `fn(u8) -> m::n::Z {m::n::Z::Fn}`
+
+error[E0618]: expected function, found enum variant `Z::Unit`
+  --> $DIR/privacy-enum-ctor.rs:31:17
+   |
+LL |             Unit,
+   |             ---- `Z::Unit` defined here
+...
+LL |         let _ = Z::Unit();
+   |                 ^^^^^^^--
+   |                 |
+   |                 call expression requires function
+help: `Z::Unit` is a unit variant, you need to write it without the parenthesis
+   |
+LL |         let _ = Z::Unit;
+   |                 ^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/privacy-enum-ctor.rs:43:16
+   |
+LL |     let _: E = m::E::Fn;
+   |                ^^^^^^^^ expected enum `m::E`, found fn item
+   |
+   = note: expected type `m::E`
+              found type `fn(u8) -> m::E {m::E::Fn}`
+
+error[E0618]: expected function, found enum variant `m::E::Unit`
+  --> $DIR/privacy-enum-ctor.rs:47:16
+   |
+LL |         Unit,
+   |         ---- `m::E::Unit` defined here
+...
+LL |     let _: E = m::E::Unit();
+   |                ^^^^^^^^^^--
+   |                |
+   |                call expression requires function
+help: `m::E::Unit` is a unit variant, you need to write it without the parenthesis
+   |
+LL |     let _: E = m::E::Unit;
+   |                ^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/privacy-enum-ctor.rs:51:16
+   |
+LL |     let _: E = E::Fn;
+   |                ^^^^^ expected enum `m::E`, found fn item
+   |
+   = note: expected type `m::E`
+              found type `fn(u8) -> m::E {m::E::Fn}`
+
+error[E0618]: expected function, found enum variant `E::Unit`
+  --> $DIR/privacy-enum-ctor.rs:55:16
+   |
+LL |         Unit,
+   |         ---- `E::Unit` defined here
+...
+LL |     let _: E = E::Unit();
+   |                ^^^^^^^--
+   |                |
+   |                call expression requires function
+help: `E::Unit` is a unit variant, you need to write it without the parenthesis
+   |
+LL |     let _: E = E::Unit;
+   |                ^^^^^^^
+
+error: aborting due to 23 previous errors
+
+Some errors occurred: E0308, E0412, E0423, E0603, E0618.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/resolve/privacy-struct-ctor.rs b/src/test/ui/resolve/privacy-struct-ctor.rs
new file mode 100644
index 0000000..0b389ac
--- /dev/null
+++ b/src/test/ui/resolve/privacy-struct-ctor.rs
@@ -0,0 +1,47 @@
+// aux-build:privacy-struct-ctor.rs
+
+extern crate privacy_struct_ctor as xcrate;
+
+mod m {
+    pub struct S(u8);
+    pub struct S2 {
+        s: u8
+    }
+
+    pub mod n {
+        pub(in m) struct Z(pub(in m::n) u8);
+    }
+
+    use m::n::Z; // OK, only the type is imported
+
+    fn f() {
+        n::Z;
+        //~^ ERROR tuple struct `Z` is private
+        Z;
+        //~^ ERROR expected value, found struct `Z`
+    }
+}
+
+use m::S; // OK, only the type is imported
+use m::S2; // OK, only the type is imported
+
+fn main() {
+    m::S;
+    //~^ ERROR tuple struct `S` is private
+    let _: S = m::S(2);
+    //~^ ERROR tuple struct `S` is private
+    S;
+    //~^ ERROR expected value, found struct `S`
+    m::n::Z;
+    //~^ ERROR tuple struct `Z` is private
+
+    S2;
+    //~^ ERROR expected value, found struct `S2`
+
+    xcrate::m::S;
+    //~^ ERROR tuple struct `S` is private
+    xcrate::S;
+    //~^ ERROR expected value, found struct `xcrate::S`
+    xcrate::m::n::Z;
+    //~^ ERROR tuple struct `Z` is private
+}
diff --git a/src/test/ui/resolve/privacy-struct-ctor.stderr b/src/test/ui/resolve/privacy-struct-ctor.stderr
new file mode 100644
index 0000000..519e74d
--- /dev/null
+++ b/src/test/ui/resolve/privacy-struct-ctor.stderr
@@ -0,0 +1,71 @@
+error[E0423]: expected value, found struct `Z`
+  --> $DIR/privacy-struct-ctor.rs:20:9
+   |
+LL |         Z;
+   |         ^
+   |         |
+   |         constructor is not visible here due to private fields
+   |         help: a tuple struct with a similar name exists: `S`
+
+error[E0423]: expected value, found struct `S`
+  --> $DIR/privacy-struct-ctor.rs:33:5
+   |
+LL |     S;
+   |     ^ constructor is not visible here due to private fields
+
+error[E0423]: expected value, found struct `S2`
+  --> $DIR/privacy-struct-ctor.rs:38:5
+   |
+LL |     S2;
+   |     ^^ did you mean `S2 { /* fields */ }`?
+
+error[E0423]: expected value, found struct `xcrate::S`
+  --> $DIR/privacy-struct-ctor.rs:43:5
+   |
+LL |     xcrate::S;
+   |     ^^^^^^^^^ constructor is not visible here due to private fields
+help: possible better candidate is found in another module, you can import it into scope
+   |
+LL | use m::S;
+   |
+
+error[E0603]: tuple struct `Z` is private
+  --> $DIR/privacy-struct-ctor.rs:18:12
+   |
+LL |         n::Z;
+   |            ^
+
+error[E0603]: tuple struct `S` is private
+  --> $DIR/privacy-struct-ctor.rs:29:8
+   |
+LL |     m::S;
+   |        ^
+
+error[E0603]: tuple struct `S` is private
+  --> $DIR/privacy-struct-ctor.rs:31:19
+   |
+LL |     let _: S = m::S(2);
+   |                   ^
+
+error[E0603]: tuple struct `Z` is private
+  --> $DIR/privacy-struct-ctor.rs:35:11
+   |
+LL |     m::n::Z;
+   |           ^
+
+error[E0603]: tuple struct `S` is private
+  --> $DIR/privacy-struct-ctor.rs:41:16
+   |
+LL |     xcrate::m::S;
+   |                ^
+
+error[E0603]: tuple struct `Z` is private
+  --> $DIR/privacy-struct-ctor.rs:45:19
+   |
+LL |     xcrate::m::n::Z;
+   |                   ^
+
+error: aborting due to 10 previous errors
+
+Some errors occurred: E0423, E0603.
+For more information about an error, try `rustc --explain E0423`.
diff --git a/src/test/ui/resolve/resolve-assoc-suggestions.rs b/src/test/ui/resolve/resolve-assoc-suggestions.rs
new file mode 100644
index 0000000..8cdbe64
--- /dev/null
+++ b/src/test/ui/resolve/resolve-assoc-suggestions.rs
@@ -0,0 +1,39 @@
+// Make sure associated items are recommended only in appropriate contexts.
+
+struct S {
+    field: u8,
+}
+
+trait Tr {
+    fn method(&self);
+    type Type;
+}
+
+impl Tr for S {
+    type Type = u8;
+
+    fn method(&self) {
+        let _: field;
+        //~^ ERROR cannot find type `field`
+        let field(..);
+        //~^ ERROR cannot find tuple struct/variant `field`
+        field;
+        //~^ ERROR cannot find value `field`
+
+        let _: Type;
+        //~^ ERROR cannot find type `Type`
+        let Type(..);
+        //~^ ERROR cannot find tuple struct/variant `Type`
+        Type;
+        //~^ ERROR cannot find value `Type`
+
+        let _: method;
+        //~^ ERROR cannot find type `method`
+        let method(..);
+        //~^ ERROR cannot find tuple struct/variant `method`
+        method;
+        //~^ ERROR cannot find value `method`
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/resolve/resolve-assoc-suggestions.stderr b/src/test/ui/resolve/resolve-assoc-suggestions.stderr
new file mode 100644
index 0000000..f2e1d72
--- /dev/null
+++ b/src/test/ui/resolve/resolve-assoc-suggestions.stderr
@@ -0,0 +1,58 @@
+error[E0412]: cannot find type `field` in this scope
+  --> $DIR/resolve-assoc-suggestions.rs:16:16
+   |
+LL |         let _: field;
+   |                ^^^^^ not found in this scope
+
+error[E0531]: cannot find tuple struct/variant `field` in this scope
+  --> $DIR/resolve-assoc-suggestions.rs:18:13
+   |
+LL |         let field(..);
+   |             ^^^^^ not found in this scope
+
+error[E0425]: cannot find value `field` in this scope
+  --> $DIR/resolve-assoc-suggestions.rs:20:9
+   |
+LL |         field;
+   |         ^^^^^ help: try: `self.field`
+
+error[E0412]: cannot find type `Type` in this scope
+  --> $DIR/resolve-assoc-suggestions.rs:23:16
+   |
+LL |         let _: Type;
+   |                ^^^^ help: try: `Self::Type`
+
+error[E0531]: cannot find tuple struct/variant `Type` in this scope
+  --> $DIR/resolve-assoc-suggestions.rs:25:13
+   |
+LL |         let Type(..);
+   |             ^^^^ not found in this scope
+
+error[E0425]: cannot find value `Type` in this scope
+  --> $DIR/resolve-assoc-suggestions.rs:27:9
+   |
+LL |         Type;
+   |         ^^^^ not found in this scope
+
+error[E0412]: cannot find type `method` in this scope
+  --> $DIR/resolve-assoc-suggestions.rs:30:16
+   |
+LL |         let _: method;
+   |                ^^^^^^ not found in this scope
+
+error[E0531]: cannot find tuple struct/variant `method` in this scope
+  --> $DIR/resolve-assoc-suggestions.rs:32:13
+   |
+LL |         let method(..);
+   |             ^^^^^^ not found in this scope
+
+error[E0425]: cannot find value `method` in this scope
+  --> $DIR/resolve-assoc-suggestions.rs:34:9
+   |
+LL |         method;
+   |         ^^^^^^ help: try: `self.method`
+
+error: aborting due to 9 previous errors
+
+Some errors occurred: E0412, E0425, E0531.
+For more information about an error, try `rustc --explain E0412`.
diff --git a/src/test/ui/resolve/resolve-bad-import-prefix.rs b/src/test/ui/resolve/resolve-bad-import-prefix.rs
new file mode 100644
index 0000000..325c69b
--- /dev/null
+++ b/src/test/ui/resolve/resolve-bad-import-prefix.rs
@@ -0,0 +1,14 @@
+mod m {}
+enum E {}
+struct S;
+trait Tr {}
+
+use {}; // OK
+use ::{}; // OK
+use m::{}; // OK
+use E::{}; // OK
+use S::{}; // FIXME, this and `use S::{self};` should be an error
+use Tr::{}; // FIXME, this and `use Tr::{self};` should be an error
+use Nonexistent::{}; //~ ERROR unresolved import `Nonexistent`
+
+fn main () {}
diff --git a/src/test/ui/resolve/resolve-bad-import-prefix.stderr b/src/test/ui/resolve/resolve-bad-import-prefix.stderr
new file mode 100644
index 0000000..852b9c6
--- /dev/null
+++ b/src/test/ui/resolve/resolve-bad-import-prefix.stderr
@@ -0,0 +1,9 @@
+error[E0432]: unresolved import `Nonexistent`
+  --> $DIR/resolve-bad-import-prefix.rs:12:5
+   |
+LL | use Nonexistent::{};
+   |     ^^^^^^^^^^^^^^^ no `Nonexistent` in the root
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/resolve/resolve-bad-visibility.rs b/src/test/ui/resolve/resolve-bad-visibility.rs
new file mode 100644
index 0000000..d86c300
--- /dev/null
+++ b/src/test/ui/resolve/resolve-bad-visibility.rs
@@ -0,0 +1,15 @@
+enum E {}
+trait Tr {}
+
+pub(in E) struct S; //~ ERROR expected module, found enum `E`
+pub(in Tr) struct Z; //~ ERROR expected module, found trait `Tr`
+pub(in std::vec) struct F; //~ ERROR visibilities can only be restricted to ancestor modules
+pub(in nonexistent) struct G; //~ ERROR cannot find module `nonexistent` in the crate root
+pub(in too_soon) struct H; //~ ERROR cannot find module `too_soon` in the crate root
+
+// Visibilities are resolved eagerly without waiting for modules becoming fully populated.
+// Visibilities can only use ancestor modules legally which are always available in time,
+// so the worst thing that can happen due to eager resolution is a suboptimal error message.
+mod too_soon {}
+
+fn main () {}
diff --git a/src/test/ui/resolve/resolve-bad-visibility.stderr b/src/test/ui/resolve/resolve-bad-visibility.stderr
new file mode 100644
index 0000000..32b85f2
--- /dev/null
+++ b/src/test/ui/resolve/resolve-bad-visibility.stderr
@@ -0,0 +1,34 @@
+error: visibilities can only be restricted to ancestor modules
+  --> $DIR/resolve-bad-visibility.rs:6:8
+   |
+LL | pub(in std::vec) struct F;
+   |        ^^^^^^^^
+
+error[E0577]: expected module, found enum `E`
+  --> $DIR/resolve-bad-visibility.rs:4:8
+   |
+LL | pub(in E) struct S;
+   |        ^ not a module
+
+error[E0577]: expected module, found trait `Tr`
+  --> $DIR/resolve-bad-visibility.rs:5:8
+   |
+LL | pub(in Tr) struct Z;
+   |        ^^ not a module
+
+error[E0578]: cannot find module `nonexistent` in the crate root
+  --> $DIR/resolve-bad-visibility.rs:7:8
+   |
+LL | pub(in nonexistent) struct G;
+   |        ^^^^^^^^^^^ not found in the crate root
+
+error[E0578]: cannot find module `too_soon` in the crate root
+  --> $DIR/resolve-bad-visibility.rs:8:8
+   |
+LL | pub(in too_soon) struct H;
+   |        ^^^^^^^^ not found in the crate root
+
+error: aborting due to 5 previous errors
+
+Some errors occurred: E0577, E0578.
+For more information about an error, try `rustc --explain E0577`.
diff --git a/src/test/ui/resolve/resolve-conflict-extern-crate-vs-extern-crate.rs b/src/test/ui/resolve/resolve-conflict-extern-crate-vs-extern-crate.rs
new file mode 100644
index 0000000..e4bb0d3
--- /dev/null
+++ b/src/test/ui/resolve/resolve-conflict-extern-crate-vs-extern-crate.rs
@@ -0,0 +1,5 @@
+#[allow(unused_extern_crates)]
+extern crate std;
+//~^ ERROR the name `std` is defined multiple times
+
+fn main(){}
diff --git a/src/test/ui/resolve/resolve-conflict-extern-crate-vs-extern-crate.stderr b/src/test/ui/resolve/resolve-conflict-extern-crate-vs-extern-crate.stderr
new file mode 100644
index 0000000..9e43cd4
--- /dev/null
+++ b/src/test/ui/resolve/resolve-conflict-extern-crate-vs-extern-crate.stderr
@@ -0,0 +1,15 @@
+error[E0259]: the name `std` is defined multiple times
+  --> $DIR/resolve-conflict-extern-crate-vs-extern-crate.rs:2:1
+   |
+LL | extern crate std;
+   | ^^^^^^^^^^^^^^^^^ `std` reimported here
+   |
+   = note: `std` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | extern crate std as other_std;
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0259`.
diff --git a/src/test/ui/resolve/resolve-conflict-import-vs-extern-crate.rs b/src/test/ui/resolve/resolve-conflict-import-vs-extern-crate.rs
new file mode 100644
index 0000000..10772e7
--- /dev/null
+++ b/src/test/ui/resolve/resolve-conflict-import-vs-extern-crate.rs
@@ -0,0 +1,4 @@
+use std::slice as std; //~ ERROR the name `std` is defined multiple times
+
+fn main() {
+}
diff --git a/src/test/ui/resolve/resolve-conflict-import-vs-extern-crate.stderr b/src/test/ui/resolve/resolve-conflict-import-vs-extern-crate.stderr
new file mode 100644
index 0000000..a0a8582
--- /dev/null
+++ b/src/test/ui/resolve/resolve-conflict-import-vs-extern-crate.stderr
@@ -0,0 +1,15 @@
+error[E0254]: the name `std` is defined multiple times
+  --> $DIR/resolve-conflict-import-vs-extern-crate.rs:1:5
+   |
+LL | use std::slice as std;
+   |     ^^^^^^^^^^^^^^^^^ `std` reimported here
+   |
+   = note: `std` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | use std::slice as other_std;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0254`.
diff --git a/src/test/ui/resolve/resolve-conflict-import-vs-import.rs b/src/test/ui/resolve/resolve-conflict-import-vs-import.rs
new file mode 100644
index 0000000..322f000
--- /dev/null
+++ b/src/test/ui/resolve/resolve-conflict-import-vs-import.rs
@@ -0,0 +1,6 @@
+use std::mem::transmute;
+use std::mem::transmute;
+//~^ ERROR the name `transmute` is defined multiple times
+
+fn main() {
+}
diff --git a/src/test/ui/resolve/resolve-conflict-import-vs-import.stderr b/src/test/ui/resolve/resolve-conflict-import-vs-import.stderr
new file mode 100644
index 0000000..8df68ad
--- /dev/null
+++ b/src/test/ui/resolve/resolve-conflict-import-vs-import.stderr
@@ -0,0 +1,13 @@
+error[E0252]: the name `transmute` is defined multiple times
+  --> $DIR/resolve-conflict-import-vs-import.rs:2:5
+   |
+LL | use std::mem::transmute;
+   |     ------------------- previous import of the value `transmute` here
+LL | use std::mem::transmute;
+   |     ^^^^^^^^^^^^^^^^^^^ `transmute` reimported here
+   |
+   = note: `transmute` must be defined only once in the value namespace of this module
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0252`.
diff --git a/src/test/ui/resolve/resolve-conflict-item-vs-extern-crate.rs b/src/test/ui/resolve/resolve-conflict-item-vs-extern-crate.rs
new file mode 100644
index 0000000..1226062
--- /dev/null
+++ b/src/test/ui/resolve/resolve-conflict-item-vs-extern-crate.rs
@@ -0,0 +1,5 @@
+fn std() {}
+mod std {}    //~ ERROR the name `std` is defined multiple times
+
+fn main() {
+}
diff --git a/src/test/ui/resolve/resolve-conflict-item-vs-extern-crate.stderr b/src/test/ui/resolve/resolve-conflict-item-vs-extern-crate.stderr
new file mode 100644
index 0000000..7b9fb6c
--- /dev/null
+++ b/src/test/ui/resolve/resolve-conflict-item-vs-extern-crate.stderr
@@ -0,0 +1,11 @@
+error[E0260]: the name `std` is defined multiple times
+  --> $DIR/resolve-conflict-item-vs-extern-crate.rs:2:1
+   |
+LL | mod std {}
+   | ^^^^^^^ `std` redefined here
+   |
+   = note: `std` must be defined only once in the type namespace of this module
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0260`.
diff --git a/src/test/ui/resolve/resolve-conflict-item-vs-import.rs b/src/test/ui/resolve/resolve-conflict-item-vs-import.rs
new file mode 100644
index 0000000..4308c7a
--- /dev/null
+++ b/src/test/ui/resolve/resolve-conflict-item-vs-import.rs
@@ -0,0 +1,8 @@
+use std::mem::transmute;
+
+fn transmute() {}
+//~^ ERROR the name `transmute` is defined multiple times
+//~| `transmute` redefined here
+//~| `transmute` must be defined only once in the value namespace of this module
+fn main() {
+}
diff --git a/src/test/ui/resolve/resolve-conflict-item-vs-import.stderr b/src/test/ui/resolve/resolve-conflict-item-vs-import.stderr
new file mode 100644
index 0000000..83beb20
--- /dev/null
+++ b/src/test/ui/resolve/resolve-conflict-item-vs-import.stderr
@@ -0,0 +1,18 @@
+error[E0255]: the name `transmute` is defined multiple times
+  --> $DIR/resolve-conflict-item-vs-import.rs:3:1
+   |
+LL | use std::mem::transmute;
+   |     ------------------- previous import of the value `transmute` here
+LL | 
+LL | fn transmute() {}
+   | ^^^^^^^^^^^^^^ `transmute` redefined here
+   |
+   = note: `transmute` must be defined only once in the value namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | use std::mem::transmute as other_transmute;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0255`.
diff --git a/src/test/ui/resolve/resolve-conflict-type-vs-import.rs b/src/test/ui/resolve/resolve-conflict-type-vs-import.rs
new file mode 100644
index 0000000..3abce83
--- /dev/null
+++ b/src/test/ui/resolve/resolve-conflict-type-vs-import.rs
@@ -0,0 +1,7 @@
+use std::slice::Iter;
+
+struct Iter;
+//~^ ERROR the name `Iter` is defined multiple times
+
+fn main() {
+}
diff --git a/src/test/ui/resolve/resolve-conflict-type-vs-import.stderr b/src/test/ui/resolve/resolve-conflict-type-vs-import.stderr
new file mode 100644
index 0000000..104ed9b
--- /dev/null
+++ b/src/test/ui/resolve/resolve-conflict-type-vs-import.stderr
@@ -0,0 +1,18 @@
+error[E0255]: the name `Iter` is defined multiple times
+  --> $DIR/resolve-conflict-type-vs-import.rs:3:1
+   |
+LL | use std::slice::Iter;
+   |     ---------------- previous import of the type `Iter` here
+LL | 
+LL | struct Iter;
+   | ^^^^^^^^^^^^ `Iter` redefined here
+   |
+   = note: `Iter` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | use std::slice::Iter as OtherIter;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0255`.
diff --git a/src/test/ui/resolve/resolve-hint-macro.rs b/src/test/ui/resolve/resolve-hint-macro.rs
new file mode 100644
index 0000000..6155ae7
--- /dev/null
+++ b/src/test/ui/resolve/resolve-hint-macro.rs
@@ -0,0 +1,4 @@
+fn main() {
+    assert(true);
+    //~^ ERROR expected function, found macro `assert`
+}
diff --git a/src/test/ui/resolve/resolve-hint-macro.stderr b/src/test/ui/resolve/resolve-hint-macro.stderr
new file mode 100644
index 0000000..ebe3c36
--- /dev/null
+++ b/src/test/ui/resolve/resolve-hint-macro.stderr
@@ -0,0 +1,9 @@
+error[E0423]: expected function, found macro `assert`
+  --> $DIR/resolve-hint-macro.rs:2:5
+   |
+LL |     assert(true);
+   |     ^^^^^^ help: use `!` to invoke the macro: `assert!`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0423`.
diff --git a/src/test/ui/resolve/resolve-inconsistent-binding-mode.rs b/src/test/ui/resolve/resolve-inconsistent-binding-mode.rs
new file mode 100644
index 0000000..e9c4e47
--- /dev/null
+++ b/src/test/ui/resolve/resolve-inconsistent-binding-mode.rs
@@ -0,0 +1,40 @@
+enum Opts {
+    A(isize), B(isize), C(isize)
+}
+
+fn matcher1(x: Opts) {
+    match x {
+      Opts::A(ref i) | Opts::B(i) => {}
+      //~^ ERROR variable `i` is bound in inconsistent ways within the same match arm
+      //~^^ ERROR mismatched types
+      Opts::C(_) => {}
+    }
+}
+
+fn matcher2(x: Opts) {
+    match x {
+      Opts::A(ref i) | Opts::B(i) => {}
+      //~^ ERROR variable `i` is bound in inconsistent ways within the same match arm
+      //~^^ ERROR mismatched types
+      Opts::C(_) => {}
+    }
+}
+
+fn matcher4(x: Opts) {
+    match x {
+      Opts::A(ref mut i) | Opts::B(ref i) => {}
+      //~^ ERROR variable `i` is bound in inconsistent ways within the same match arm
+      //~^^ ERROR mismatched types
+      Opts::C(_) => {}
+    }
+}
+
+
+fn matcher5(x: Opts) {
+    match x {
+      Opts::A(ref i) | Opts::B(ref i) => {}
+      Opts::C(_) => {}
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/resolve/resolve-inconsistent-binding-mode.stderr b/src/test/ui/resolve/resolve-inconsistent-binding-mode.stderr
new file mode 100644
index 0000000..a14d3d6
--- /dev/null
+++ b/src/test/ui/resolve/resolve-inconsistent-binding-mode.stderr
@@ -0,0 +1,53 @@
+error[E0409]: variable `i` is bound in inconsistent ways within the same match arm
+  --> $DIR/resolve-inconsistent-binding-mode.rs:7:32
+   |
+LL |       Opts::A(ref i) | Opts::B(i) => {}
+   |                   -            ^ bound in different ways
+   |                   |
+   |                   first binding
+
+error[E0409]: variable `i` is bound in inconsistent ways within the same match arm
+  --> $DIR/resolve-inconsistent-binding-mode.rs:16:32
+   |
+LL |       Opts::A(ref i) | Opts::B(i) => {}
+   |                   -            ^ bound in different ways
+   |                   |
+   |                   first binding
+
+error[E0409]: variable `i` is bound in inconsistent ways within the same match arm
+  --> $DIR/resolve-inconsistent-binding-mode.rs:25:40
+   |
+LL |       Opts::A(ref mut i) | Opts::B(ref i) => {}
+   |                       - first binding  ^ bound in different ways
+
+error[E0308]: mismatched types
+  --> $DIR/resolve-inconsistent-binding-mode.rs:7:32
+   |
+LL |       Opts::A(ref i) | Opts::B(i) => {}
+   |                                ^ expected &isize, found isize
+   |
+   = note: expected type `&isize`
+              found type `isize`
+
+error[E0308]: mismatched types
+  --> $DIR/resolve-inconsistent-binding-mode.rs:16:32
+   |
+LL |       Opts::A(ref i) | Opts::B(i) => {}
+   |                                ^ expected &isize, found isize
+   |
+   = note: expected type `&isize`
+              found type `isize`
+
+error[E0308]: mismatched types
+  --> $DIR/resolve-inconsistent-binding-mode.rs:25:36
+   |
+LL |       Opts::A(ref mut i) | Opts::B(ref i) => {}
+   |                                    ^^^^^ types differ in mutability
+   |
+   = note: expected type `&mut isize`
+              found type `&isize`
+
+error: aborting due to 6 previous errors
+
+Some errors occurred: E0308, E0409.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/resolve/resolve-inconsistent-names.rs b/src/test/ui/resolve/resolve-inconsistent-names.rs
new file mode 100644
index 0000000..59baa57
--- /dev/null
+++ b/src/test/ui/resolve/resolve-inconsistent-names.rs
@@ -0,0 +1,7 @@
+fn main() {
+    let y = 1;
+    match y {
+       a | b => {} //~  ERROR variable `a` is not bound in all patterns
+                   //~^ ERROR variable `b` is not bound in all patterns
+    }
+}
diff --git a/src/test/ui/resolve/resolve-inconsistent-names.stderr b/src/test/ui/resolve/resolve-inconsistent-names.stderr
new file mode 100644
index 0000000..c757181
--- /dev/null
+++ b/src/test/ui/resolve/resolve-inconsistent-names.stderr
@@ -0,0 +1,19 @@
+error[E0408]: variable `a` is not bound in all patterns
+  --> $DIR/resolve-inconsistent-names.rs:4:12
+   |
+LL |        a | b => {}
+   |        -   ^ pattern doesn't bind `a`
+   |        |
+   |        variable not in all patterns
+
+error[E0408]: variable `b` is not bound in all patterns
+  --> $DIR/resolve-inconsistent-names.rs:4:8
+   |
+LL |        a | b => {}
+   |        ^   - variable not in all patterns
+   |        |
+   |        pattern doesn't bind `b`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0408`.
diff --git a/src/test/ui/resolve/resolve-label.rs b/src/test/ui/resolve/resolve-label.rs
new file mode 100644
index 0000000..965ee45
--- /dev/null
+++ b/src/test/ui/resolve/resolve-label.rs
@@ -0,0 +1,13 @@
+fn f() {
+    'l: loop {
+        fn g() {
+            loop {
+                break 'l; //~ ERROR use of undeclared label
+            }
+        }
+    }
+
+    loop { 'w: while break 'w { } }
+}
+
+fn main() {}
diff --git a/src/test/ui/resolve/resolve-label.stderr b/src/test/ui/resolve/resolve-label.stderr
new file mode 100644
index 0000000..72a8e44
--- /dev/null
+++ b/src/test/ui/resolve/resolve-label.stderr
@@ -0,0 +1,9 @@
+error[E0426]: use of undeclared label `'l`
+  --> $DIR/resolve-label.rs:5:23
+   |
+LL |                 break 'l;
+   |                       ^^ undeclared label `'l`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0426`.
diff --git a/src/test/ui/resolve/resolve-primitive-fallback.rs b/src/test/ui/resolve/resolve-primitive-fallback.rs
new file mode 100644
index 0000000..e5a3d68
--- /dev/null
+++ b/src/test/ui/resolve/resolve-primitive-fallback.rs
@@ -0,0 +1,10 @@
+fn main() {
+    // Make sure primitive type fallback doesn't work in value namespace
+    std::mem::size_of(u16);
+    //~^ ERROR expected value, found builtin type `u16`
+    //~| ERROR this function takes 0 parameters but 1 parameter was supplied
+
+    // Make sure primitive type fallback doesn't work with global paths
+    let _: ::u8;
+    //~^ ERROR cannot find type `u8` in the crate root
+}
diff --git a/src/test/ui/resolve/resolve-primitive-fallback.stderr b/src/test/ui/resolve/resolve-primitive-fallback.stderr
new file mode 100644
index 0000000..963bab4
--- /dev/null
+++ b/src/test/ui/resolve/resolve-primitive-fallback.stderr
@@ -0,0 +1,22 @@
+error[E0423]: expected value, found builtin type `u16`
+  --> $DIR/resolve-primitive-fallback.rs:3:23
+   |
+LL |     std::mem::size_of(u16);
+   |                       ^^^ not a value
+
+error[E0412]: cannot find type `u8` in the crate root
+  --> $DIR/resolve-primitive-fallback.rs:8:14
+   |
+LL |     let _: ::u8;
+   |              ^^ not found in the crate root
+
+error[E0061]: this function takes 0 parameters but 1 parameter was supplied
+  --> $DIR/resolve-primitive-fallback.rs:3:5
+   |
+LL |     std::mem::size_of(u16);
+   |     ^^^^^^^^^^^^^^^^^^^^^^ expected 0 parameters
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0061, E0412, E0423.
+For more information about an error, try `rustc --explain E0061`.
diff --git a/src/test/ui/resolve/resolve-self-in-impl-2.rs b/src/test/ui/resolve/resolve-self-in-impl-2.rs
new file mode 100644
index 0000000..f586760
--- /dev/null
+++ b/src/test/ui/resolve/resolve-self-in-impl-2.rs
@@ -0,0 +1,7 @@
+struct S<T = u8>(T);
+trait Tr<T = u8> {}
+
+impl Self for S {} //~ ERROR expected trait, found self type `Self`
+impl Self::N for S {} //~ ERROR cannot find trait `N` in `Self`
+
+fn main() {}
diff --git a/src/test/ui/resolve/resolve-self-in-impl-2.stderr b/src/test/ui/resolve/resolve-self-in-impl-2.stderr
new file mode 100644
index 0000000..765f150
--- /dev/null
+++ b/src/test/ui/resolve/resolve-self-in-impl-2.stderr
@@ -0,0 +1,16 @@
+error[E0411]: expected trait, found self type `Self`
+  --> $DIR/resolve-self-in-impl-2.rs:4:6
+   |
+LL | impl Self for S {}
+   |      ^^^^ `Self` is only available in impls, traits, and type definitions
+
+error[E0405]: cannot find trait `N` in `Self`
+  --> $DIR/resolve-self-in-impl-2.rs:5:12
+   |
+LL | impl Self::N for S {}
+   |            ^ not found in `Self`
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0405, E0411.
+For more information about an error, try `rustc --explain E0405`.
diff --git a/src/test/ui/resolve/resolve-self-in-impl.rs b/src/test/ui/resolve/resolve-self-in-impl.rs
new file mode 100644
index 0000000..024fdc5
--- /dev/null
+++ b/src/test/ui/resolve/resolve-self-in-impl.rs
@@ -0,0 +1,20 @@
+#![feature(associated_type_defaults)]
+
+struct S<T = u8>(T);
+trait Tr<T = u8> {
+    type A = ();
+}
+
+impl Tr<Self> for S {} // OK
+impl<T: Tr<Self>> Tr<T> for S {} // OK
+impl Tr for S where Self: Copy {} // OK
+impl Tr for S where S<Self>: Copy {} // OK
+impl Tr for S where Self::A: Copy {} // OK
+
+impl Tr for Self {} //~ ERROR cycle detected
+impl Tr for S<Self> {} //~ ERROR cycle detected
+impl Self {} //~ ERROR cycle detected
+impl S<Self> {} //~ ERROR cycle detected
+impl Tr<Self::A> for S {} //~ ERROR cycle detected
+
+fn main() {}
diff --git a/src/test/ui/resolve/resolve-self-in-impl.stderr b/src/test/ui/resolve/resolve-self-in-impl.stderr
new file mode 100644
index 0000000..58e851e
--- /dev/null
+++ b/src/test/ui/resolve/resolve-self-in-impl.stderr
@@ -0,0 +1,98 @@
+error[E0391]: cycle detected when processing `<impl at $DIR/resolve-self-in-impl.rs:14:1: 14:20>`
+  --> $DIR/resolve-self-in-impl.rs:14:13
+   |
+LL | impl Tr for Self {}
+   |             ^^^^
+   |
+   = note: ...which again requires processing `<impl at $DIR/resolve-self-in-impl.rs:14:1: 14:20>`, completing the cycle
+note: cycle used when collecting item types in top-level module
+  --> $DIR/resolve-self-in-impl.rs:1:1
+   |
+LL | / #![feature(associated_type_defaults)]
+LL | |
+LL | | struct S<T = u8>(T);
+LL | | trait Tr<T = u8> {
+...  |
+LL | |
+LL | | fn main() {}
+   | |____________^
+
+error[E0391]: cycle detected when processing `<impl at $DIR/resolve-self-in-impl.rs:15:1: 15:23>`
+  --> $DIR/resolve-self-in-impl.rs:15:15
+   |
+LL | impl Tr for S<Self> {}
+   |               ^^^^
+   |
+   = note: ...which again requires processing `<impl at $DIR/resolve-self-in-impl.rs:15:1: 15:23>`, completing the cycle
+note: cycle used when collecting item types in top-level module
+  --> $DIR/resolve-self-in-impl.rs:1:1
+   |
+LL | / #![feature(associated_type_defaults)]
+LL | |
+LL | | struct S<T = u8>(T);
+LL | | trait Tr<T = u8> {
+...  |
+LL | |
+LL | | fn main() {}
+   | |____________^
+
+error[E0391]: cycle detected when processing `<impl at $DIR/resolve-self-in-impl.rs:16:1: 16:13>`
+  --> $DIR/resolve-self-in-impl.rs:16:6
+   |
+LL | impl Self {}
+   |      ^^^^
+   |
+   = note: ...which again requires processing `<impl at $DIR/resolve-self-in-impl.rs:16:1: 16:13>`, completing the cycle
+note: cycle used when collecting item types in top-level module
+  --> $DIR/resolve-self-in-impl.rs:1:1
+   |
+LL | / #![feature(associated_type_defaults)]
+LL | |
+LL | | struct S<T = u8>(T);
+LL | | trait Tr<T = u8> {
+...  |
+LL | |
+LL | | fn main() {}
+   | |____________^
+
+error[E0391]: cycle detected when processing `<impl at $DIR/resolve-self-in-impl.rs:17:1: 17:16>`
+  --> $DIR/resolve-self-in-impl.rs:17:8
+   |
+LL | impl S<Self> {}
+   |        ^^^^
+   |
+   = note: ...which again requires processing `<impl at $DIR/resolve-self-in-impl.rs:17:1: 17:16>`, completing the cycle
+note: cycle used when collecting item types in top-level module
+  --> $DIR/resolve-self-in-impl.rs:1:1
+   |
+LL | / #![feature(associated_type_defaults)]
+LL | |
+LL | | struct S<T = u8>(T);
+LL | | trait Tr<T = u8> {
+...  |
+LL | |
+LL | | fn main() {}
+   | |____________^
+
+error[E0391]: cycle detected when processing `<impl at $DIR/resolve-self-in-impl.rs:18:1: 18:26>`
+  --> $DIR/resolve-self-in-impl.rs:18:1
+   |
+LL | impl Tr<Self::A> for S {}
+   | ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: ...which again requires processing `<impl at $DIR/resolve-self-in-impl.rs:18:1: 18:26>`, completing the cycle
+note: cycle used when collecting item types in top-level module
+  --> $DIR/resolve-self-in-impl.rs:1:1
+   |
+LL | / #![feature(associated_type_defaults)]
+LL | |
+LL | | struct S<T = u8>(T);
+LL | | trait Tr<T = u8> {
+...  |
+LL | |
+LL | | fn main() {}
+   | |____________^
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/resolve/resolve-speculative-adjustment.rs b/src/test/ui/resolve/resolve-speculative-adjustment.rs
new file mode 100644
index 0000000..81f7578
--- /dev/null
+++ b/src/test/ui/resolve/resolve-speculative-adjustment.rs
@@ -0,0 +1,30 @@
+// Make sure speculative path resolution works properly when resolution
+// adjustment happens and no extra errors is reported.
+
+struct S {
+    field: u8,
+}
+
+trait Tr {
+    fn method(&self);
+}
+
+impl Tr for S {
+    fn method(&self) {
+        fn g() {
+            // Speculative resolution of `Self` and `self` silently fails,
+            // "did you mean" messages are not printed.
+            field;
+            //~^ ERROR cannot find value `field`
+            method();
+            //~^ ERROR cannot find function `method`
+        }
+
+        field;
+        //~^ ERROR cannot find value `field`
+        method();
+        //~^ ERROR cannot find function `method`
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/resolve/resolve-speculative-adjustment.stderr b/src/test/ui/resolve/resolve-speculative-adjustment.stderr
new file mode 100644
index 0000000..c4a6ced
--- /dev/null
+++ b/src/test/ui/resolve/resolve-speculative-adjustment.stderr
@@ -0,0 +1,27 @@
+error[E0425]: cannot find value `field` in this scope
+  --> $DIR/resolve-speculative-adjustment.rs:17:13
+   |
+LL |             field;
+   |             ^^^^^ not found in this scope
+
+error[E0425]: cannot find function `method` in this scope
+  --> $DIR/resolve-speculative-adjustment.rs:19:13
+   |
+LL |             method();
+   |             ^^^^^^ not found in this scope
+
+error[E0425]: cannot find value `field` in this scope
+  --> $DIR/resolve-speculative-adjustment.rs:23:9
+   |
+LL |         field;
+   |         ^^^^^ help: try: `self.field`
+
+error[E0425]: cannot find function `method` in this scope
+  --> $DIR/resolve-speculative-adjustment.rs:25:9
+   |
+LL |         method();
+   |         ^^^^^^ help: try: `self.method`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/resolve/resolve-type-param-in-item-in-trait.rs b/src/test/ui/resolve/resolve-type-param-in-item-in-trait.rs
new file mode 100644
index 0000000..c77a665
--- /dev/null
+++ b/src/test/ui/resolve/resolve-type-param-in-item-in-trait.rs
@@ -0,0 +1,35 @@
+// Issue #14603: Check for references to type parameters from the
+// outer scope (in this case, the trait) used on items in an inner
+// scope (in this case, the enum).
+
+trait TraitA<A> {
+    fn outer(&self) {
+        enum Foo<B> {
+            Variance(A)
+                //~^ ERROR can't use generic parameters from outer function
+        }
+    }
+}
+
+trait TraitB<A> {
+    fn outer(&self) {
+        struct Foo<B>(A);
+                //~^ ERROR can't use generic parameters from outer function
+    }
+}
+
+trait TraitC<A> {
+    fn outer(&self) {
+        struct Foo<B> { a: A }
+                //~^ ERROR can't use generic parameters from outer function
+    }
+}
+
+trait TraitD<A> {
+    fn outer(&self) {
+        fn foo<B>(a: A) { }
+                //~^ ERROR can't use generic parameters from outer function
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/resolve/resolve-type-param-in-item-in-trait.stderr b/src/test/ui/resolve/resolve-type-param-in-item-in-trait.stderr
new file mode 100644
index 0000000..f6b8abf
--- /dev/null
+++ b/src/test/ui/resolve/resolve-type-param-in-item-in-trait.stderr
@@ -0,0 +1,45 @@
+error[E0401]: can't use generic parameters from outer function
+  --> $DIR/resolve-type-param-in-item-in-trait.rs:8:22
+   |
+LL | trait TraitA<A> {
+   |              - type variable from outer function
+LL |     fn outer(&self) {
+   |        ----- try adding a local generic parameter in this method instead
+LL |         enum Foo<B> {
+LL |             Variance(A)
+   |                      ^ use of generic parameter from outer function
+
+error[E0401]: can't use generic parameters from outer function
+  --> $DIR/resolve-type-param-in-item-in-trait.rs:16:23
+   |
+LL | trait TraitB<A> {
+   |              - type variable from outer function
+LL |     fn outer(&self) {
+   |        ----- try adding a local generic parameter in this method instead
+LL |         struct Foo<B>(A);
+   |                       ^ use of generic parameter from outer function
+
+error[E0401]: can't use generic parameters from outer function
+  --> $DIR/resolve-type-param-in-item-in-trait.rs:23:28
+   |
+LL | trait TraitC<A> {
+   |              - type variable from outer function
+LL |     fn outer(&self) {
+   |        ----- try adding a local generic parameter in this method instead
+LL |         struct Foo<B> { a: A }
+   |                            ^ use of generic parameter from outer function
+
+error[E0401]: can't use generic parameters from outer function
+  --> $DIR/resolve-type-param-in-item-in-trait.rs:30:22
+   |
+LL | trait TraitD<A> {
+   |              - type variable from outer function
+LL |     fn outer(&self) {
+LL |         fn foo<B>(a: A) { }
+   |            ------    ^ use of generic parameter from outer function
+   |            |
+   |            help: try using a local generic parameter instead: `foo<B, A>`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0401`.
diff --git a/src/test/ui/resolve/resolve-unknown-trait.rs b/src/test/ui/resolve/resolve-unknown-trait.rs
new file mode 100644
index 0000000..290893b
--- /dev/null
+++ b/src/test/ui/resolve/resolve-unknown-trait.rs
@@ -0,0 +1,10 @@
+trait NewTrait : SomeNonExistentTrait {}
+//~^ ERROR cannot find trait `SomeNonExistentTrait` in this scope
+
+impl SomeNonExistentTrait for isize {}
+//~^ ERROR cannot find trait `SomeNonExistentTrait` in this scope
+
+fn f<T:SomeNonExistentTrait>() {}
+//~^ ERROR cannot find trait `SomeNonExistentTrait` in this scope
+
+fn main() {}
diff --git a/src/test/ui/resolve/resolve-unknown-trait.stderr b/src/test/ui/resolve/resolve-unknown-trait.stderr
new file mode 100644
index 0000000..e19cfe6
--- /dev/null
+++ b/src/test/ui/resolve/resolve-unknown-trait.stderr
@@ -0,0 +1,21 @@
+error[E0405]: cannot find trait `SomeNonExistentTrait` in this scope
+  --> $DIR/resolve-unknown-trait.rs:1:18
+   |
+LL | trait NewTrait : SomeNonExistentTrait {}
+   |                  ^^^^^^^^^^^^^^^^^^^^ not found in this scope
+
+error[E0405]: cannot find trait `SomeNonExistentTrait` in this scope
+  --> $DIR/resolve-unknown-trait.rs:4:6
+   |
+LL | impl SomeNonExistentTrait for isize {}
+   |      ^^^^^^^^^^^^^^^^^^^^ not found in this scope
+
+error[E0405]: cannot find trait `SomeNonExistentTrait` in this scope
+  --> $DIR/resolve-unknown-trait.rs:7:8
+   |
+LL | fn f<T:SomeNonExistentTrait>() {}
+   |        ^^^^^^^^^^^^^^^^^^^^ not found in this scope
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0405`.
diff --git a/src/test/ui/resolve/resolve-variant-assoc-item.rs b/src/test/ui/resolve/resolve-variant-assoc-item.rs
new file mode 100644
index 0000000..f0f55c0
--- /dev/null
+++ b/src/test/ui/resolve/resolve-variant-assoc-item.rs
@@ -0,0 +1,7 @@
+enum E { V }
+use E::V;
+
+fn main() {
+    E::V::associated_item; //~ ERROR failed to resolve: not a module `V`
+    V::associated_item; //~ ERROR failed to resolve: not a module `V`
+}
diff --git a/src/test/ui/resolve/resolve-variant-assoc-item.stderr b/src/test/ui/resolve/resolve-variant-assoc-item.stderr
new file mode 100644
index 0000000..173976d
--- /dev/null
+++ b/src/test/ui/resolve/resolve-variant-assoc-item.stderr
@@ -0,0 +1,15 @@
+error[E0433]: failed to resolve: not a module `V`
+  --> $DIR/resolve-variant-assoc-item.rs:5:8
+   |
+LL |     E::V::associated_item;
+   |        ^ not a module `V`
+
+error[E0433]: failed to resolve: not a module `V`
+  --> $DIR/resolve-variant-assoc-item.rs:6:5
+   |
+LL |     V::associated_item;
+   |     ^ not a module `V`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.rs b/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.rs
new file mode 100644
index 0000000..204a272
--- /dev/null
+++ b/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.rs
@@ -0,0 +1,59 @@
+// Beginners write `mod.item` when they should write `mod::item`.
+// This tests that we suggest the latter when we encounter the former.
+
+pub mod a {
+    pub const I: i32 = 1;
+
+    pub fn f() -> i32 { 2 }
+
+    pub mod b {
+        pub const J: i32 = 3;
+
+        pub fn g() -> i32 { 4 }
+    }
+}
+
+fn h1() -> i32 {
+    a.I
+    //~^ ERROR expected value, found module `a`
+}
+
+fn h2() -> i32 {
+    a.g()
+    //~^ ERROR expected value, found module `a`
+}
+
+fn h3() -> i32 {
+    a.b.J
+    //~^ ERROR expected value, found module `a`
+}
+
+fn h4() -> i32 {
+    a::b.J
+    //~^ ERROR expected value, found module `a::b`
+}
+
+fn h5() {
+    a.b.f();
+    //~^ ERROR expected value, found module `a`
+    let v = Vec::new();
+    v.push(a::b);
+    //~^ ERROR expected value, found module `a::b`
+}
+
+fn h6() -> i32 {
+    a::b.f()
+    //~^ ERROR expected value, found module `a::b`
+}
+
+fn h7() {
+    a::b
+    //~^ ERROR expected value, found module `a::b`
+}
+
+fn h8() -> i32 {
+    a::b()
+    //~^ ERROR expected function, found module `a::b`
+}
+
+fn main() {}
diff --git a/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr b/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr
new file mode 100644
index 0000000..b7b158c
--- /dev/null
+++ b/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr
@@ -0,0 +1,87 @@
+error[E0423]: expected value, found module `a`
+  --> $DIR/suggest-path-instead-of-mod-dot-item.rs:17:5
+   |
+LL |     a.I
+   |     ^--
+   |     |
+   |     help: use the path separator to refer to an item: `a::I`
+
+error[E0423]: expected value, found module `a`
+  --> $DIR/suggest-path-instead-of-mod-dot-item.rs:22:5
+   |
+LL |     a.g()
+   |     ^--
+   |     |
+   |     help: use the path separator to refer to an item: `a::g`
+
+error[E0423]: expected value, found module `a`
+  --> $DIR/suggest-path-instead-of-mod-dot-item.rs:27:5
+   |
+LL |     a.b.J
+   |     ^--
+   |     |
+   |     help: use the path separator to refer to an item: `a::b`
+
+error[E0423]: expected value, found module `a::b`
+  --> $DIR/suggest-path-instead-of-mod-dot-item.rs:32:5
+   |
+LL |     a::b.J
+   |     ^^^^
+help: a constant with a similar name exists
+   |
+LL |     a::I.J
+   |        ^
+help: use the path separator to refer to an item
+   |
+LL |     a::b::J
+   |
+
+error[E0423]: expected value, found module `a`
+  --> $DIR/suggest-path-instead-of-mod-dot-item.rs:37:5
+   |
+LL |     a.b.f();
+   |     ^--
+   |     |
+   |     help: use the path separator to refer to an item: `a::b`
+
+error[E0423]: expected value, found module `a::b`
+  --> $DIR/suggest-path-instead-of-mod-dot-item.rs:40:12
+   |
+LL |     v.push(a::b);
+   |            ^^^-
+   |               |
+   |               help: a constant with a similar name exists: `I`
+
+error[E0423]: expected value, found module `a::b`
+  --> $DIR/suggest-path-instead-of-mod-dot-item.rs:45:5
+   |
+LL |     a::b.f()
+   |     ^^^^
+help: a constant with a similar name exists
+   |
+LL |     a::I.f()
+   |        ^
+help: use the path separator to refer to an item
+   |
+LL |     a::b::f()
+   |     ^^^^^^^
+
+error[E0423]: expected value, found module `a::b`
+  --> $DIR/suggest-path-instead-of-mod-dot-item.rs:50:5
+   |
+LL |     a::b
+   |     ^^^-
+   |        |
+   |        help: a constant with a similar name exists: `I`
+
+error[E0423]: expected function, found module `a::b`
+  --> $DIR/suggest-path-instead-of-mod-dot-item.rs:55:5
+   |
+LL |     a::b()
+   |     ^^^-
+   |        |
+   |        help: a constant with a similar name exists: `I`
+
+error: aborting due to 9 previous errors
+
+For more information about this error, try `rustc --explain E0423`.
diff --git a/src/test/ui/resolve/token-error-correct-2.rs b/src/test/ui/resolve/token-error-correct-2.rs
new file mode 100644
index 0000000..807a39c
--- /dev/null
+++ b/src/test/ui/resolve/token-error-correct-2.rs
@@ -0,0 +1,7 @@
+// Test that we do some basic error correction in the tokeniser (and don't ICE).
+
+fn main() {
+    if foo {
+    //~^ ERROR: cannot find value `foo`
+    ) //~ ERROR: incorrect close delimiter: `)`
+}
diff --git a/src/test/ui/resolve/token-error-correct-2.stderr b/src/test/ui/resolve/token-error-correct-2.stderr
new file mode 100644
index 0000000..d568117
--- /dev/null
+++ b/src/test/ui/resolve/token-error-correct-2.stderr
@@ -0,0 +1,18 @@
+error: incorrect close delimiter: `)`
+  --> $DIR/token-error-correct-2.rs:6:5
+   |
+LL |     if foo {
+   |            - un-closed delimiter
+LL |
+LL |     )
+   |     ^ incorrect close delimiter
+
+error[E0425]: cannot find value `foo` in this scope
+  --> $DIR/token-error-correct-2.rs:4:8
+   |
+LL |     if foo {
+   |        ^^^ not found in this scope
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/resolve/token-error-correct-3.rs b/src/test/ui/resolve/token-error-correct-3.rs
new file mode 100644
index 0000000..212b88a
--- /dev/null
+++ b/src/test/ui/resolve/token-error-correct-3.rs
@@ -0,0 +1,28 @@
+// ignore-cloudabi no std::fs support
+
+// Test that we do some basic error correction in the tokeniser (and don't spew
+// too many bogus errors).
+
+pub mod raw {
+    use std::{io, fs};
+    use std::path::Path;
+
+    pub fn ensure_dir_exists<P: AsRef<Path>, F: FnOnce(&Path)>(path: P,
+                                                               callback: F)
+                                                               -> io::Result<bool> {
+        if !is_directory(path.as_ref()) {
+            //~^ ERROR cannot find function `is_directory`
+            callback(path.as_ref();
+            //~^ ERROR expected one of
+            fs::create_dir_all(path.as_ref()).map(|()| true)
+            //~^ ERROR mismatched types
+        } else {
+            //~^ ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `)`
+            Ok(false);
+        }
+
+        panic!();
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/resolve/token-error-correct-3.stderr b/src/test/ui/resolve/token-error-correct-3.stderr
new file mode 100644
index 0000000..52a3117
--- /dev/null
+++ b/src/test/ui/resolve/token-error-correct-3.stderr
@@ -0,0 +1,39 @@
+error: expected one of `)`, `,`, `.`, `?`, or an operator, found `;`
+  --> $DIR/token-error-correct-3.rs:15:35
+   |
+LL |             callback(path.as_ref();
+   |                     -             ^
+   |                     |             |
+   |                     |             help: `)` may belong here
+   |                     unclosed delimiter
+
+error: expected one of `.`, `;`, `?`, `}`, or an operator, found `)`
+  --> $DIR/token-error-correct-3.rs:19:9
+   |
+LL |             fs::create_dir_all(path.as_ref()).map(|()| true)
+   |                                                             - expected one of `.`, `;`, `?`, `}`, or an operator here
+LL |
+LL |         } else {
+   |         ^ unexpected token
+
+error[E0425]: cannot find function `is_directory` in this scope
+  --> $DIR/token-error-correct-3.rs:13:13
+   |
+LL |         if !is_directory(path.as_ref()) {
+   |             ^^^^^^^^^^^^ not found in this scope
+
+error[E0308]: mismatched types
+  --> $DIR/token-error-correct-3.rs:17:13
+   |
+LL |             fs::create_dir_all(path.as_ref()).map(|()| true)
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- help: try adding a semicolon: `;`
+   |             |
+   |             expected (), found enum `std::result::Result`
+   |
+   = note: expected type `()`
+              found type `std::result::Result<bool, std::io::Error>`
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0308, E0425.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/resolve/token-error-correct.rs b/src/test/ui/resolve/token-error-correct.rs
new file mode 100644
index 0000000..d649077
--- /dev/null
+++ b/src/test/ui/resolve/token-error-correct.rs
@@ -0,0 +1,9 @@
+// Test that we do some basic error correction in the tokeniser.
+
+fn main() {
+    foo(bar(;
+    //~^ ERROR cannot find function `bar` in this scope
+}
+//~^ ERROR: incorrect close delimiter: `}`
+
+fn foo(_: usize) {}
diff --git a/src/test/ui/resolve/token-error-correct.stderr b/src/test/ui/resolve/token-error-correct.stderr
new file mode 100644
index 0000000..9452e2d
--- /dev/null
+++ b/src/test/ui/resolve/token-error-correct.stderr
@@ -0,0 +1,20 @@
+error: incorrect close delimiter: `}`
+  --> $DIR/token-error-correct.rs:6:1
+   |
+LL | fn main() {
+   |           - close delimiter possibly meant for this
+LL |     foo(bar(;
+   |            - un-closed delimiter
+LL |
+LL | }
+   | ^ incorrect close delimiter
+
+error[E0425]: cannot find function `bar` in this scope
+  --> $DIR/token-error-correct.rs:4:9
+   |
+LL |     foo(bar(;
+   |         ^^^ not found in this scope
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/resolve/tuple-struct-alias.rs b/src/test/ui/resolve/tuple-struct-alias.rs
new file mode 100644
index 0000000..65977e1
--- /dev/null
+++ b/src/test/ui/resolve/tuple-struct-alias.rs
@@ -0,0 +1,9 @@
+struct S(u8, u16);
+type A = S;
+
+fn main() {
+    let s = A(0, 1); //~ ERROR expected function
+    match s {
+        A(..) => {} //~ ERROR expected tuple struct/variant
+    }
+}
diff --git a/src/test/ui/resolve/tuple-struct-alias.stderr b/src/test/ui/resolve/tuple-struct-alias.stderr
new file mode 100644
index 0000000..fc701b1
--- /dev/null
+++ b/src/test/ui/resolve/tuple-struct-alias.stderr
@@ -0,0 +1,20 @@
+error[E0423]: expected function, found type alias `A`
+  --> $DIR/tuple-struct-alias.rs:5:13
+   |
+LL |     let s = A(0, 1);
+   |             ^ help: a tuple struct with a similar name exists: `S`
+   |
+   = note: can't use a type alias as a constructor
+
+error[E0532]: expected tuple struct/variant, found type alias `A`
+  --> $DIR/tuple-struct-alias.rs:7:9
+   |
+LL |         A(..) => {}
+   |         ^ help: a tuple struct with a similar name exists: `S`
+   |
+   = note: can't use a type alias as a constructor
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0423, E0532.
+For more information about an error, try `rustc --explain E0423`.
diff --git a/src/test/ui/resolve/unboxed-closure-sugar-nonexistent-trait.rs b/src/test/ui/resolve/unboxed-closure-sugar-nonexistent-trait.rs
new file mode 100644
index 0000000..87f9ce0
--- /dev/null
+++ b/src/test/ui/resolve/unboxed-closure-sugar-nonexistent-trait.rs
@@ -0,0 +1,9 @@
+fn f<F:Nonexist(isize) -> isize>(x: F) {}
+//~^ ERROR cannot find trait `Nonexist`
+
+type Typedef = isize;
+
+fn g<F:Typedef(isize) -> isize>(x: F) {}
+//~^ ERROR expected trait, found type alias `Typedef`
+
+fn main() {}
diff --git a/src/test/ui/resolve/unboxed-closure-sugar-nonexistent-trait.stderr b/src/test/ui/resolve/unboxed-closure-sugar-nonexistent-trait.stderr
new file mode 100644
index 0000000..70cabcb
--- /dev/null
+++ b/src/test/ui/resolve/unboxed-closure-sugar-nonexistent-trait.stderr
@@ -0,0 +1,18 @@
+error[E0405]: cannot find trait `Nonexist` in this scope
+  --> $DIR/unboxed-closure-sugar-nonexistent-trait.rs:1:8
+   |
+LL | fn f<F:Nonexist(isize) -> isize>(x: F) {}
+   |        ^^^^^^^^ not found in this scope
+
+error[E0404]: expected trait, found type alias `Typedef`
+  --> $DIR/unboxed-closure-sugar-nonexistent-trait.rs:6:8
+   |
+LL | fn g<F:Typedef(isize) -> isize>(x: F) {}
+   |        ^^^^^^^^^^^^^^^^^^^^^^^ type aliases cannot be used as traits
+   |
+   = note: did you mean to use a trait alias?
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0404, E0405.
+For more information about an error, try `rustc --explain E0404`.
diff --git a/src/test/ui/resolve/unresolved_static_type_field.rs b/src/test/ui/resolve/unresolved_static_type_field.rs
new file mode 100644
index 0000000..494ad08
--- /dev/null
+++ b/src/test/ui/resolve/unresolved_static_type_field.rs
@@ -0,0 +1,14 @@
+fn f(_: bool) {}
+
+struct Foo {
+    cx: bool,
+}
+
+impl Foo {
+    fn bar() {
+        f(cx);
+        //~^ ERROR cannot find value `cx` in this scope
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/resolve/unresolved_static_type_field.stderr b/src/test/ui/resolve/unresolved_static_type_field.stderr
new file mode 100644
index 0000000..a517324
--- /dev/null
+++ b/src/test/ui/resolve/unresolved_static_type_field.stderr
@@ -0,0 +1,12 @@
+error[E0425]: cannot find value `cx` in this scope
+  --> $DIR/unresolved_static_type_field.rs:9:11
+   |
+LL |         f(cx);
+   |           ^^
+   |           |
+   |           `self` value is a keyword only available in methods with `self` parameter
+   |           help: try: `self.cx`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/resolve/use_suggestion_placement.rs b/src/test/ui/resolve/use_suggestion_placement.rs
new file mode 100644
index 0000000..9b8b9d8
--- /dev/null
+++ b/src/test/ui/resolve/use_suggestion_placement.rs
@@ -0,0 +1,28 @@
+// ignore-cloudabi no std::path support
+
+macro_rules! y {
+    () => {}
+}
+
+mod m {
+    pub const A: i32 = 0;
+}
+
+mod foo {
+    #[derive(Debug)]
+    pub struct Foo;
+
+    // test whether the use suggestion isn't
+    // placed into the expansion of `#[derive(Debug)]
+    type Bar = Path; //~ ERROR cannot find
+}
+
+fn main() {
+    y!();
+    let _ = A; //~ ERROR cannot find
+    foo();
+}
+
+fn foo() {
+    type Dict<K, V> = HashMap<K, V>; //~ ERROR cannot find
+}
diff --git a/src/test/ui/resolve/use_suggestion_placement.stderr b/src/test/ui/resolve/use_suggestion_placement.stderr
new file mode 100644
index 0000000..8d2fdd5
--- /dev/null
+++ b/src/test/ui/resolve/use_suggestion_placement.stderr
@@ -0,0 +1,36 @@
+error[E0412]: cannot find type `Path` in this scope
+  --> $DIR/use_suggestion_placement.rs:17:16
+   |
+LL |     type Bar = Path;
+   |                ^^^^ not found in this scope
+help: possible candidate is found in another module, you can import it into scope
+   |
+LL |     use std::path::Path;
+   |
+
+error[E0425]: cannot find value `A` in this scope
+  --> $DIR/use_suggestion_placement.rs:22:13
+   |
+LL |     let _ = A;
+   |             ^ not found in this scope
+help: possible candidate is found in another module, you can import it into scope
+   |
+LL | use m::A;
+   |
+
+error[E0412]: cannot find type `HashMap` in this scope
+  --> $DIR/use_suggestion_placement.rs:27:23
+   |
+LL |     type Dict<K, V> = HashMap<K, V>;
+   |                       ^^^^^^^ not found in this scope
+help: possible candidates are found in other modules, you can import them into scope
+   |
+LL | use std::collections::HashMap;
+   |
+LL | use std::collections::hash_map::HashMap;
+   |
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0412, E0425.
+For more information about an error, try `rustc --explain E0412`.
diff --git a/src/test/ui/resolve_self_super_hint.rs b/src/test/ui/resolve_self_super_hint.rs
new file mode 100644
index 0000000..91a01cc
--- /dev/null
+++ b/src/test/ui/resolve_self_super_hint.rs
@@ -0,0 +1,30 @@
+#![feature(alloc)]
+#![allow(unused_extern_crates)]
+
+mod a {
+    extern crate alloc;
+    use alloc::HashMap;
+    //~^ ERROR unresolved import `alloc` [E0432]
+    //~| HELP a similar path exists
+    //~| SUGGESTION self::alloc
+    mod b {
+        use alloc::HashMap;
+        //~^ ERROR unresolved import `alloc` [E0432]
+        //~| HELP a similar path exists
+        //~| SUGGESTION super::alloc
+        mod c {
+            use alloc::HashMap;
+            //~^ ERROR unresolved import `alloc` [E0432]
+            //~| HELP a similar path exists
+            //~| SUGGESTION a::alloc
+            mod d {
+                use alloc::HashMap;
+                //~^ ERROR unresolved import `alloc` [E0432]
+                //~| HELP a similar path exists
+                //~| SUGGESTION a::alloc
+            }
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/resolve_self_super_hint.stderr b/src/test/ui/resolve_self_super_hint.stderr
new file mode 100644
index 0000000..03214ca
--- /dev/null
+++ b/src/test/ui/resolve_self_super_hint.stderr
@@ -0,0 +1,33 @@
+error[E0432]: unresolved import `alloc`
+  --> $DIR/resolve_self_super_hint.rs:6:9
+   |
+LL |     use alloc::HashMap;
+   |         ^^^^^ help: a similar path exists: `self::alloc`
+
+error[E0432]: unresolved import `alloc`
+  --> $DIR/resolve_self_super_hint.rs:11:13
+   |
+LL |         use alloc::HashMap;
+   |             ^^^^^ help: a similar path exists: `super::alloc`
+
+error[E0432]: unresolved import `alloc`
+  --> $DIR/resolve_self_super_hint.rs:16:17
+   |
+LL |             use alloc::HashMap;
+   |                 ^^^^^
+   |                 |
+   |                 unresolved import
+   |                 help: a similar path exists: `a::alloc`
+
+error[E0432]: unresolved import `alloc`
+  --> $DIR/resolve_self_super_hint.rs:21:21
+   |
+LL |                 use alloc::HashMap;
+   |                     ^^^^^
+   |                     |
+   |                     unresolved import
+   |                     help: a similar path exists: `a::alloc`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/ret-non-nil.rs b/src/test/ui/ret-non-nil.rs
new file mode 100644
index 0000000..86c02bf
--- /dev/null
+++ b/src/test/ui/ret-non-nil.rs
@@ -0,0 +1,7 @@
+// error-pattern: `return;` in a function whose return type is not `()`
+
+fn f() { return; }
+
+fn g() -> isize { return; }
+
+fn main() { f(); g(); }
diff --git a/src/test/ui/ret-non-nil.stderr b/src/test/ui/ret-non-nil.stderr
new file mode 100644
index 0000000..2029c6d
--- /dev/null
+++ b/src/test/ui/ret-non-nil.stderr
@@ -0,0 +1,11 @@
+error[E0069]: `return;` in a function whose return type is not `()`
+  --> $DIR/ret-non-nil.rs:5:19
+   |
+LL | fn g() -> isize { return; }
+   |           -----   ^^^^^^ return type is not `()`
+   |           |
+   |           expected `isize` because of this return type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0069`.
diff --git a/src/test/ui/retslot-cast.rs b/src/test/ui/retslot-cast.rs
new file mode 100644
index 0000000..ae500cb
--- /dev/null
+++ b/src/test/ui/retslot-cast.rs
@@ -0,0 +1,22 @@
+#![allow(warnings)]
+
+pub fn fail(x: Option<&(Iterator<Item=()>+Send)>)
+            -> Option<&Iterator<Item=()>> {
+    // This call used to trigger an LLVM assertion because the return
+    // slot had type "Option<&Iterator>"* instead of
+    // "Option<&(Iterator+Send)>"* -- but this now yields a
+    // compilation error and I'm not sure how to create a comparable
+    // test. To ensure that this PARTICULAR failure doesn't occur
+    // again, though, I've left this test here, so if this ever starts
+    // to compile again, we can adjust the test appropriately (clearly
+    // it should never ICE...). -nmatsakis
+    inner(x) //~ ERROR mismatched types
+}
+
+pub fn inner(x: Option<&(Iterator<Item=()>+Send)>)
+             -> Option<&(Iterator<Item=()>+Send)> {
+    x
+}
+
+
+fn main() {}
diff --git a/src/test/ui/retslot-cast.stderr b/src/test/ui/retslot-cast.stderr
new file mode 100644
index 0000000..a116991
--- /dev/null
+++ b/src/test/ui/retslot-cast.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/retslot-cast.rs:13:5
+   |
+LL |     inner(x)
+   |     ^^^^^^^^ expected trait `std::iter::Iterator<Item = ()>`, found trait `std::iter::Iterator<Item = ()> + std::marker::Send`
+   |
+   = note: expected type `std::option::Option<&dyn std::iter::Iterator<Item = ()>>`
+              found type `std::option::Option<&dyn std::iter::Iterator<Item = ()> + std::marker::Send>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/return/return-from-diverging.rs b/src/test/ui/return/return-from-diverging.rs
new file mode 100644
index 0000000..faeccaa
--- /dev/null
+++ b/src/test/ui/return/return-from-diverging.rs
@@ -0,0 +1,9 @@
+// Test that return another type in place of ! raises a type mismatch.
+
+fn fail() -> ! {
+    return "wow"; //~ ERROR mismatched types
+}
+
+fn main() {
+}
+
diff --git a/src/test/ui/return/return-from-diverging.stderr b/src/test/ui/return/return-from-diverging.stderr
new file mode 100644
index 0000000..3dd029c
--- /dev/null
+++ b/src/test/ui/return/return-from-diverging.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/return-from-diverging.rs:4:12
+   |
+LL | fn fail() -> ! {
+   |              - expected `!` because of return type
+LL |     return "wow";
+   |            ^^^^^ expected !, found reference
+   |
+   = note: expected type `!`
+              found type `&'static str`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/return/return-match-array-const.rs b/src/test/ui/return/return-match-array-const.rs
new file mode 100644
index 0000000..bbcd960
--- /dev/null
+++ b/src/test/ui/return/return-match-array-const.rs
@@ -0,0 +1,7 @@
+fn main() {
+    [(); return match 0 { n => n }]; //~ ERROR: return statement outside of function body
+
+    [(); return match 0 { 0 => 0 }]; //~ ERROR: return statement outside of function body
+
+    [(); return match () { 'a' => 0, _ => 0 }]; //~ ERROR: return statement outside of function body
+}
diff --git a/src/test/ui/return/return-match-array-const.stderr b/src/test/ui/return/return-match-array-const.stderr
new file mode 100644
index 0000000..6e8c9ed
--- /dev/null
+++ b/src/test/ui/return/return-match-array-const.stderr
@@ -0,0 +1,21 @@
+error[E0572]: return statement outside of function body
+  --> $DIR/return-match-array-const.rs:2:10
+   |
+LL |     [(); return match 0 { n => n }];
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0572]: return statement outside of function body
+  --> $DIR/return-match-array-const.rs:4:10
+   |
+LL |     [(); return match 0 { 0 => 0 }];
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0572]: return statement outside of function body
+  --> $DIR/return-match-array-const.rs:6:10
+   |
+LL |     [(); return match () { 'a' => 0, _ => 0 }];
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0572`.
diff --git a/src/test/ui/return/return-type.rs b/src/test/ui/return/return-type.rs
new file mode 100644
index 0000000..9f951ee
--- /dev/null
+++ b/src/test/ui/return/return-type.rs
@@ -0,0 +1,14 @@
+struct S<T> {
+    t: T,
+}
+
+fn foo<T>(x: T) -> S<T> {
+    S { t: x }
+}
+
+fn bar() {
+    foo(4 as usize)
+    //~^ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/src/test/ui/return/return-type.stderr b/src/test/ui/return/return-type.stderr
new file mode 100644
index 0000000..6eeec41
--- /dev/null
+++ b/src/test/ui/return/return-type.stderr
@@ -0,0 +1,20 @@
+error[E0308]: mismatched types
+  --> $DIR/return-type.rs:10:5
+   |
+LL |     foo(4 as usize)
+   |     ^^^^^^^^^^^^^^^ expected (), found struct `S`
+   |
+   = note: expected type `()`
+              found type `S<usize>`
+help: try adding a semicolon
+   |
+LL |     foo(4 as usize);
+   |                    ^
+help: try adding a return type
+   |
+LL | fn bar() -> S<usize> {
+   |          ^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/return/return-unit-from-diverging.rs b/src/test/ui/return/return-unit-from-diverging.rs
new file mode 100644
index 0000000..31a1378
--- /dev/null
+++ b/src/test/ui/return/return-unit-from-diverging.rs
@@ -0,0 +1,10 @@
+// Test that we get the usual error that we'd get for any other return type and not something about
+// diverging functions not being able to return.
+
+fn fail() -> ! {
+    return; //~ ERROR in a function whose return type is not
+}
+
+fn main() {
+}
+
diff --git a/src/test/ui/return/return-unit-from-diverging.stderr b/src/test/ui/return/return-unit-from-diverging.stderr
new file mode 100644
index 0000000..befc575
--- /dev/null
+++ b/src/test/ui/return/return-unit-from-diverging.stderr
@@ -0,0 +1,11 @@
+error[E0069]: `return;` in a function whose return type is not `()`
+  --> $DIR/return-unit-from-diverging.rs:5:5
+   |
+LL | fn fail() -> ! {
+   |              - expected `!` because of this return type
+LL |     return;
+   |     ^^^^^^ return type is not `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0069`.
diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/bind-by-move-no-guards.rs b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/bind-by-move-no-guards.rs
new file mode 100644
index 0000000..2f3c094
--- /dev/null
+++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/bind-by-move-no-guards.rs
@@ -0,0 +1,21 @@
+// Adaptation of existing ui test (from way back in
+// rust-lang/rust#2329), that starts passing with this feature in
+// place.
+
+// compile-pass
+
+#![feature(nll)]
+#![feature(bind_by_move_pattern_guards)]
+
+use std::sync::mpsc::channel;
+
+fn main() {
+    let (tx, rx) = channel();
+    let x = Some(rx);
+    tx.send(false);
+    match x {
+        Some(z) if z.recv().unwrap() => { panic!() },
+        Some(z) => { assert!(!z.recv().unwrap()); },
+        None => panic!()
+    }
+}
diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_2015.stderr b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_2015.stderr
new file mode 100644
index 0000000..4c17ce2
--- /dev/null
+++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_2015.stderr
@@ -0,0 +1,9 @@
+error[E0008]: cannot bind by-move into a pattern guard
+  --> $DIR/feature-gate.rs:33:16
+   |
+LL |         A { a: v } if *v == 42 => v,
+   |                ^ moves value into pattern guard
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0008`.
diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_2018.stderr b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_2018.stderr
new file mode 100644
index 0000000..4bde9b0
--- /dev/null
+++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_2018.stderr
@@ -0,0 +1,10 @@
+error: compilation successful
+  --> $DIR/feature-gate.rs:42:1
+   |
+LL | / fn main() {
+LL | |     foo(107)
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_feature_nll.stderr b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_feature_nll.stderr
new file mode 100644
index 0000000..4bde9b0
--- /dev/null
+++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_feature_nll.stderr
@@ -0,0 +1,10 @@
+error: compilation successful
+  --> $DIR/feature-gate.rs:42:1
+   |
+LL | / fn main() {
+LL | |     foo(107)
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_znll.stderr b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_znll.stderr
new file mode 100644
index 0000000..4bde9b0
--- /dev/null
+++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_znll.stderr
@@ -0,0 +1,10 @@
+error: compilation successful
+  --> $DIR/feature-gate.rs:42:1
+   |
+LL | / fn main() {
+LL | |     foo(107)
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.no_gate.stderr b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.no_gate.stderr
new file mode 100644
index 0000000..4c17ce2
--- /dev/null
+++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.no_gate.stderr
@@ -0,0 +1,9 @@
+error[E0008]: cannot bind by-move into a pattern guard
+  --> $DIR/feature-gate.rs:33:16
+   |
+LL |         A { a: v } if *v == 42 => v,
+   |                ^ moves value into pattern guard
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0008`.
diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.rs b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.rs
new file mode 100644
index 0000000..f6df4d0
--- /dev/null
+++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.rs
@@ -0,0 +1,47 @@
+// Check that pattern-guards with move-bound variables is only allowed
+// with the appropriate set of feature gates. (Note that we require
+// the code to opt into MIR-borrowck in *some* way before the feature
+// will work; we use the revision system here to enumerate a number of
+// ways that opt-in could occur.)
+
+// gate-test-bind_by_move_pattern_guards
+
+// revisions: no_gate gate_and_2015 gate_and_2018 gate_and_znll gate_and_feature_nll
+
+// (We're already testing NLL behavior quite explicitly, no need for compare-mode=nll.)
+// ignore-compare-mode-nll
+
+#![feature(rustc_attrs)]
+
+#![cfg_attr(gate_and_2015, feature(bind_by_move_pattern_guards))]
+#![cfg_attr(gate_and_2018, feature(bind_by_move_pattern_guards))]
+#![cfg_attr(gate_and_znll, feature(bind_by_move_pattern_guards))]
+#![cfg_attr(gate_and_feature_nll, feature(bind_by_move_pattern_guards))]
+
+#![cfg_attr(gate_and_feature_nll, feature(nll))]
+
+//[gate_and_2015] edition:2015
+//[gate_and_2018] edition:2018
+//[gate_and_znll] compile-flags: -Z borrowck=mir
+
+struct A { a: Box<i32> }
+
+fn foo(n: i32) {
+    let x = A { a: Box::new(n) };
+    let _y = match x {
+
+        A { a: v } if *v == 42 => v,
+        //[no_gate]~^ ERROR cannot bind by-move into a pattern guard
+        //[gate_and_2015]~^^ ERROR cannot bind by-move into a pattern guard
+
+        _ => Box::new(0)
+    };
+}
+
+#[rustc_error]
+fn main() {
+    foo(107)
+}
+//[gate_and_2018]~^^^ ERROR compilation successful
+//[gate_and_znll]~^^^^ ERROR compilation successful
+//[gate_and_feature_nll]~^^^^^ ERROR compilation successful
diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-basic-examples.rs b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-basic-examples.rs
new file mode 100644
index 0000000..9a9d11c
--- /dev/null
+++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-basic-examples.rs
@@ -0,0 +1,40 @@
+#![feature(nll)]
+#![feature(bind_by_move_pattern_guards)]
+
+// compile-pass
+
+struct A { a: Box<i32> }
+
+impl A {
+    fn get(&self) -> i32 { *self.a }
+}
+
+fn foo(n: i32) {
+    let x = A { a: Box::new(n) };
+    let y = match x {
+        A { a: v } if *v == 42 => v,
+        _ => Box::new(0),
+    };
+}
+
+fn bar(n: i32) {
+    let x = A { a: Box::new(n) };
+    let y = match x {
+        A { a: v } if x.get() == 42 => v,
+        _ => Box::new(0),
+    };
+}
+
+fn baz(n: i32) {
+    let x = A { a: Box::new(n) };
+    let y = match x {
+        A { a: v } if *v.clone() == 42 => v,
+        _ => Box::new(0),
+    };
+}
+
+fn main() {
+    foo(107);
+    bar(107);
+    baz(107);
+}
diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.rs b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.rs
new file mode 100644
index 0000000..0fec6b2
--- /dev/null
+++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.rs
@@ -0,0 +1,16 @@
+#![feature(nll)]
+#![feature(bind_by_move_pattern_guards)]
+
+enum VecWrapper { A(Vec<i32>) }
+
+fn foo(x: VecWrapper) -> usize {
+    match x {
+        VecWrapper::A(v) if { drop(v); false } => 1,
+        //~^ ERROR cannot move out of borrowed content
+        VecWrapper::A(v) => v.len()
+    }
+}
+
+fn main() {
+    foo(VecWrapper::A(vec![107]));
+}
diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.stderr b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.stderr
new file mode 100644
index 0000000..502006e
--- /dev/null
+++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.stderr
@@ -0,0 +1,9 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/rfc-reject-double-move-across-arms.rs:8:36
+   |
+LL |         VecWrapper::A(v) if { drop(v); false } => 1,
+   |                                    ^ cannot move out of borrowed content
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.rs b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.rs
new file mode 100644
index 0000000..396bfc1
--- /dev/null
+++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.rs
@@ -0,0 +1,17 @@
+#![feature(nll)]
+#![feature(bind_by_move_pattern_guards)]
+
+struct A { a: Box<i32> }
+
+fn foo(n: i32) {
+    let x = A { a: Box::new(n) };
+    let _y = match x {
+        A { a: v } if { drop(v); true } => v,
+        //~^ ERROR cannot move out of borrowed content
+        _ => Box::new(0),
+    };
+}
+
+fn main() {
+    foo(107);
+}
diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.stderr b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.stderr
new file mode 100644
index 0000000..dd8f42f
--- /dev/null
+++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.stderr
@@ -0,0 +1,9 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/rfc-reject-double-move-in-first-arm.rs:9:30
+   |
+LL |         A { a: v } if { drop(v); true } => v,
+   |                              ^ cannot move out of borrowed content
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/rfc-1937-termination-trait/termination-trait-impl-trait.rs b/src/test/ui/rfc-1937-termination-trait/termination-trait-impl-trait.rs
new file mode 100644
index 0000000..8f65144
--- /dev/null
+++ b/src/test/ui/rfc-1937-termination-trait/termination-trait-impl-trait.rs
@@ -0,0 +1,3 @@
+// Tests that an `impl Trait` that is not `impl Termination` will not work.
+fn main() -> impl Copy { }
+//~^ ERROR `main` has invalid return type `impl std::marker::Copy`
diff --git a/src/test/ui/rfc-1937-termination-trait/termination-trait-impl-trait.stderr b/src/test/ui/rfc-1937-termination-trait/termination-trait-impl-trait.stderr
new file mode 100644
index 0000000..8a71818
--- /dev/null
+++ b/src/test/ui/rfc-1937-termination-trait/termination-trait-impl-trait.stderr
@@ -0,0 +1,11 @@
+error[E0277]: `main` has invalid return type `impl std::marker::Copy`
+  --> $DIR/termination-trait-impl-trait.rs:2:14
+   |
+LL | fn main() -> impl Copy { }
+   |              ^^^^^^^^^ `main` can only return types that implement `std::process::Termination`
+   |
+   = help: consider using `()`, or a `Result`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/rfc-1937-termination-trait/termination-trait-in-test-should-panic.rs b/src/test/ui/rfc-1937-termination-trait/termination-trait-in-test-should-panic.rs
new file mode 100644
index 0000000..96808a3
--- /dev/null
+++ b/src/test/ui/rfc-1937-termination-trait/termination-trait-in-test-should-panic.rs
@@ -0,0 +1,15 @@
+// compile-flags: --test
+
+#![feature(test)]
+
+extern crate test;
+use std::num::ParseIntError;
+use test::Bencher;
+
+#[test]
+#[should_panic]
+fn not_a_num() -> Result<(), ParseIntError> {
+    //~^ ERROR functions using `#[should_panic]` must return `()`
+    let _: u32 = "abc".parse()?;
+    Ok(())
+}
diff --git a/src/test/ui/rfc-1937-termination-trait/termination-trait-in-test-should-panic.stderr b/src/test/ui/rfc-1937-termination-trait/termination-trait-in-test-should-panic.stderr
new file mode 100644
index 0000000..7f6749f
--- /dev/null
+++ b/src/test/ui/rfc-1937-termination-trait/termination-trait-in-test-should-panic.stderr
@@ -0,0 +1,12 @@
+error: functions using `#[should_panic]` must return `()`
+  --> $DIR/termination-trait-in-test-should-panic.rs:11:1
+   |
+LL | / fn not_a_num() -> Result<(), ParseIntError> {
+LL | |
+LL | |     let _: u32 = "abc".parse()?;
+LL | |     Ok(())
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc-1937-termination-trait/termination-trait-in-test.rs b/src/test/ui/rfc-1937-termination-trait/termination-trait-in-test.rs
new file mode 100644
index 0000000..39825c4
--- /dev/null
+++ b/src/test/ui/rfc-1937-termination-trait/termination-trait-in-test.rs
@@ -0,0 +1,26 @@
+// compile-flags: --test
+// run-pass
+
+#![feature(test)]
+
+extern crate test;
+use std::num::ParseIntError;
+use test::Bencher;
+
+#[test]
+fn is_a_num() -> Result<(), ParseIntError> {
+    let _: u32 = "22".parse()?;
+    Ok(())
+}
+
+#[bench]
+fn test_a_positive_bench(_: &mut Bencher) -> Result<(), ParseIntError> {
+    Ok(())
+}
+
+#[bench]
+#[should_panic]
+fn test_a_neg_bench(_: &mut Bencher) -> Result<(), ParseIntError> {
+    let _: u32 = "abc".parse()?;
+    Ok(())
+}
diff --git a/src/test/ui/rfc-1937-termination-trait/termination-trait-main-i32.rs b/src/test/ui/rfc-1937-termination-trait/termination-trait-main-i32.rs
new file mode 100644
index 0000000..09bd1c8
--- /dev/null
+++ b/src/test/ui/rfc-1937-termination-trait/termination-trait-main-i32.rs
@@ -0,0 +1,6 @@
+fn main() -> i32 {
+//~^ ERROR `main` has invalid return type `i32`
+//~| NOTE `main` can only return types that implement `std::process::Termination`
+//~| HELP consider using `()`, or a `Result`
+    0
+}
diff --git a/src/test/ui/rfc-1937-termination-trait/termination-trait-main-i32.stderr b/src/test/ui/rfc-1937-termination-trait/termination-trait-main-i32.stderr
new file mode 100644
index 0000000..e88e3d8
--- /dev/null
+++ b/src/test/ui/rfc-1937-termination-trait/termination-trait-main-i32.stderr
@@ -0,0 +1,11 @@
+error[E0277]: `main` has invalid return type `i32`
+  --> $DIR/termination-trait-main-i32.rs:1:14
+   |
+LL | fn main() -> i32 {
+   |              ^^^ `main` can only return types that implement `std::process::Termination`
+   |
+   = help: consider using `()`, or a `Result`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/rfc-1937-termination-trait/termination-trait-main-wrong-type.rs b/src/test/ui/rfc-1937-termination-trait/termination-trait-main-wrong-type.rs
new file mode 100644
index 0000000..687d5f1
--- /dev/null
+++ b/src/test/ui/rfc-1937-termination-trait/termination-trait-main-wrong-type.rs
@@ -0,0 +1,3 @@
+fn main() -> char { //~ ERROR
+    ' '
+}
diff --git a/src/test/ui/rfc-1937-termination-trait/termination-trait-main-wrong-type.stderr b/src/test/ui/rfc-1937-termination-trait/termination-trait-main-wrong-type.stderr
new file mode 100644
index 0000000..31b9034
--- /dev/null
+++ b/src/test/ui/rfc-1937-termination-trait/termination-trait-main-wrong-type.stderr
@@ -0,0 +1,11 @@
+error[E0277]: `main` has invalid return type `char`
+  --> $DIR/termination-trait-main-wrong-type.rs:1:14
+   |
+LL | fn main() -> char {
+   |              ^^^^ `main` can only return types that implement `std::process::Termination`
+   |
+   = help: consider using `()`, or a `Result`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/rfc-1937-termination-trait/termination-trait-not-satisfied.rs b/src/test/ui/rfc-1937-termination-trait/termination-trait-not-satisfied.rs
new file mode 100644
index 0000000..4c6168a
--- /dev/null
+++ b/src/test/ui/rfc-1937-termination-trait/termination-trait-not-satisfied.rs
@@ -0,0 +1,5 @@
+struct ReturnType {}
+
+fn main() -> ReturnType { //~ ERROR `main` has invalid return type `ReturnType`
+    ReturnType {}
+}
diff --git a/src/test/ui/rfc-1937-termination-trait/termination-trait-not-satisfied.stderr b/src/test/ui/rfc-1937-termination-trait/termination-trait-not-satisfied.stderr
new file mode 100644
index 0000000..72a58a0
--- /dev/null
+++ b/src/test/ui/rfc-1937-termination-trait/termination-trait-not-satisfied.stderr
@@ -0,0 +1,11 @@
+error[E0277]: `main` has invalid return type `ReturnType`
+  --> $DIR/termination-trait-not-satisfied.rs:3:14
+   |
+LL | fn main() -> ReturnType {
+   |              ^^^^^^^^^^ `main` can only return types that implement `std::process::Termination`
+   |
+   = help: consider using `()`, or a `Result`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.rs b/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.rs
new file mode 100644
index 0000000..c648f542
--- /dev/null
+++ b/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.rs
@@ -0,0 +1,8 @@
+// compile-flags: --test
+
+use std::num::ParseIntError;
+
+#[test]
+fn can_parse_zero_as_f32() -> Result<f32, ParseIntError> { //~ ERROR
+    "0".parse()
+}
diff --git a/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr b/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr
new file mode 100644
index 0000000..1811554
--- /dev/null
+++ b/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr
@@ -0,0 +1,14 @@
+error[E0277]: `main` has invalid return type `std::result::Result<f32, std::num::ParseIntError>`
+  --> $DIR/termination-trait-test-wrong-type.rs:6:1
+   |
+LL | / fn can_parse_zero_as_f32() -> Result<f32, ParseIntError> {
+LL | |     "0".parse()
+LL | | }
+   | |_^ `main` can only return types that implement `std::process::Termination`
+   |
+   = help: the trait `std::process::Termination` is not implemented for `std::result::Result<f32, std::num::ParseIntError>`
+   = note: required by `test::assert_test_result`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/rfc-2005-default-binding-mode/borrowck-issue-49631.nll.stderr b/src/test/ui/rfc-2005-default-binding-mode/borrowck-issue-49631.nll.stderr
new file mode 100644
index 0000000..0457292
--- /dev/null
+++ b/src/test/ui/rfc-2005-default-binding-mode/borrowck-issue-49631.nll.stderr
@@ -0,0 +1,14 @@
+error[E0502]: cannot borrow `foo` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-issue-49631.rs:20:9
+   |
+LL |     while let Some(Ok(string)) = foo.get() {
+   |                                  --- immutable borrow occurs here
+LL |         foo.mutate();
+   |         ^^^^^^^^^^^^ mutable borrow occurs here
+LL |
+LL |         println!("foo={:?}", *string);
+   |                              ------- immutable borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/rfc-2005-default-binding-mode/borrowck-issue-49631.rs b/src/test/ui/rfc-2005-default-binding-mode/borrowck-issue-49631.rs
new file mode 100644
index 0000000..54ab9f0
--- /dev/null
+++ b/src/test/ui/rfc-2005-default-binding-mode/borrowck-issue-49631.rs
@@ -0,0 +1,24 @@
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+pub struct Foo {
+}
+
+impl Foo {
+    fn get(&self) -> Option<&Result<String, String>> {
+        None
+    }
+
+    fn mutate(&mut self) { }
+}
+
+fn main() {
+    let mut foo = Foo { };
+
+    // foo.get() returns type Option<&Result<String, String>>, so
+    // using `string` keeps borrow of `foo` alive. Hence calling
+    // `foo.mutate()` should be an error.
+    while let Some(Ok(string)) = foo.get() {
+        foo.mutate();
+        //~^ ERROR cannot borrow `foo` as mutable
+        println!("foo={:?}", *string);
+    }
+}
diff --git a/src/test/ui/rfc-2005-default-binding-mode/borrowck-issue-49631.stderr b/src/test/ui/rfc-2005-default-binding-mode/borrowck-issue-49631.stderr
new file mode 100644
index 0000000..e946d41
--- /dev/null
+++ b/src/test/ui/rfc-2005-default-binding-mode/borrowck-issue-49631.stderr
@@ -0,0 +1,13 @@
+error[E0502]: cannot borrow `foo` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-issue-49631.rs:20:9
+   |
+LL |     while let Some(Ok(string)) = foo.get() {
+   |                                  ---     - immutable borrow ends here
+   |                                  |
+   |                                  immutable borrow occurs here
+LL |         foo.mutate();
+   |         ^^^ mutable borrow occurs here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/rfc-2005-default-binding-mode/const.rs b/src/test/ui/rfc-2005-default-binding-mode/const.rs
new file mode 100644
index 0000000..93df880
--- /dev/null
+++ b/src/test/ui/rfc-2005-default-binding-mode/const.rs
@@ -0,0 +1,17 @@
+// FIXME(tschottdorf): this test should pass.
+
+#[derive(PartialEq, Eq)]
+struct Foo {
+    bar: i32,
+}
+
+const FOO: Foo = Foo{bar: 5};
+
+fn main() {
+    let f = Foo{bar:6};
+
+    match &f {
+        FOO => {}, //~ ERROR mismatched types
+        _ => panic!(),
+    }
+}
diff --git a/src/test/ui/rfc-2005-default-binding-mode/const.stderr b/src/test/ui/rfc-2005-default-binding-mode/const.stderr
new file mode 100644
index 0000000..210b4f6
--- /dev/null
+++ b/src/test/ui/rfc-2005-default-binding-mode/const.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/const.rs:14:9
+   |
+LL |         FOO => {},
+   |         ^^^ expected &Foo, found struct `Foo`
+   |
+   = note: expected type `&Foo`
+              found type `Foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/rfc-2005-default-binding-mode/enum.nll.stderr b/src/test/ui/rfc-2005-default-binding-mode/enum.nll.stderr
new file mode 100644
index 0000000..d6a89006
--- /dev/null
+++ b/src/test/ui/rfc-2005-default-binding-mode/enum.nll.stderr
@@ -0,0 +1,21 @@
+error[E0594]: cannot assign to `*x` which is behind a `&` reference
+  --> $DIR/enum.rs:9:5
+   |
+LL |     *x += 1;
+   |     ^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written
+
+error[E0594]: cannot assign to `*x` which is behind a `&` reference
+  --> $DIR/enum.rs:13:9
+   |
+LL |         *x += 1;
+   |         ^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written
+
+error[E0594]: cannot assign to `*x` which is behind a `&` reference
+  --> $DIR/enum.rs:19:9
+   |
+LL |         *x += 1;
+   |         ^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/rfc-2005-default-binding-mode/enum.rs b/src/test/ui/rfc-2005-default-binding-mode/enum.rs
new file mode 100644
index 0000000..7609345
--- /dev/null
+++ b/src/test/ui/rfc-2005-default-binding-mode/enum.rs
@@ -0,0 +1,22 @@
+enum Wrapper {
+    Wrap(i32),
+}
+
+use Wrapper::Wrap;
+
+pub fn main() {
+    let Wrap(x) = &Wrap(3);
+    *x += 1; //~ ERROR cannot assign to immutable
+
+
+    if let Some(x) = &Some(3) {
+        *x += 1; //~ ERROR cannot assign to immutable
+    } else {
+        panic!();
+    }
+
+    while let Some(x) = &Some(3) {
+        *x += 1; //~ ERROR cannot assign to immutable
+        break;
+    }
+}
diff --git a/src/test/ui/rfc-2005-default-binding-mode/enum.stderr b/src/test/ui/rfc-2005-default-binding-mode/enum.stderr
new file mode 100644
index 0000000..5106618
--- /dev/null
+++ b/src/test/ui/rfc-2005-default-binding-mode/enum.stderr
@@ -0,0 +1,21 @@
+error[E0594]: cannot assign to immutable borrowed content `*x`
+  --> $DIR/enum.rs:9:5
+   |
+LL |     *x += 1;
+   |     ^^^^^^^ cannot borrow as mutable
+
+error[E0594]: cannot assign to immutable borrowed content `*x`
+  --> $DIR/enum.rs:13:9
+   |
+LL |         *x += 1;
+   |         ^^^^^^^ cannot borrow as mutable
+
+error[E0594]: cannot assign to immutable borrowed content `*x`
+  --> $DIR/enum.rs:19:9
+   |
+LL |         *x += 1;
+   |         ^^^^^^^ cannot borrow as mutable
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/rfc-2005-default-binding-mode/explicit-mut.nll.stderr b/src/test/ui/rfc-2005-default-binding-mode/explicit-mut.nll.stderr
new file mode 100644
index 0000000..a6f2f3e
--- /dev/null
+++ b/src/test/ui/rfc-2005-default-binding-mode/explicit-mut.nll.stderr
@@ -0,0 +1,21 @@
+error[E0594]: cannot assign to `*n` which is behind a `&` reference
+  --> $DIR/explicit-mut.rs:7:13
+   |
+LL |             *n += 1;
+   |             ^^^^^^^ `n` is a `&` reference, so the data it refers to cannot be written
+
+error[E0594]: cannot assign to `*n` which is behind a `&` reference
+  --> $DIR/explicit-mut.rs:15:13
+   |
+LL |             *n += 1;
+   |             ^^^^^^^ `n` is a `&` reference, so the data it refers to cannot be written
+
+error[E0594]: cannot assign to `*n` which is behind a `&` reference
+  --> $DIR/explicit-mut.rs:23:13
+   |
+LL |             *n += 1;
+   |             ^^^^^^^ `n` is a `&` reference, so the data it refers to cannot be written
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/rfc-2005-default-binding-mode/explicit-mut.rs b/src/test/ui/rfc-2005-default-binding-mode/explicit-mut.rs
new file mode 100644
index 0000000..73efdde
--- /dev/null
+++ b/src/test/ui/rfc-2005-default-binding-mode/explicit-mut.rs
@@ -0,0 +1,28 @@
+// Verify the binding mode shifts - only when no `&` are auto-dereferenced is the
+// final default binding mode mutable.
+
+fn main() {
+    match &&Some(5i32) {
+        Some(n) => {
+            *n += 1; //~ ERROR cannot assign to immutable
+            let _ = n;
+        }
+        None => {},
+    };
+
+    match &mut &Some(5i32) {
+        Some(n) => {
+            *n += 1; //~ ERROR cannot assign to immutable
+            let _ = n;
+        }
+        None => {},
+    };
+
+    match &&mut Some(5i32) {
+        Some(n) => {
+            *n += 1; //~ ERROR cannot assign to immutable
+            let _ = n;
+        }
+        None => {},
+    };
+}
diff --git a/src/test/ui/rfc-2005-default-binding-mode/explicit-mut.stderr b/src/test/ui/rfc-2005-default-binding-mode/explicit-mut.stderr
new file mode 100644
index 0000000..b6424f8
--- /dev/null
+++ b/src/test/ui/rfc-2005-default-binding-mode/explicit-mut.stderr
@@ -0,0 +1,21 @@
+error[E0594]: cannot assign to immutable borrowed content `*n`
+  --> $DIR/explicit-mut.rs:7:13
+   |
+LL |             *n += 1;
+   |             ^^^^^^^ cannot borrow as mutable
+
+error[E0594]: cannot assign to immutable borrowed content `*n`
+  --> $DIR/explicit-mut.rs:15:13
+   |
+LL |             *n += 1;
+   |             ^^^^^^^ cannot borrow as mutable
+
+error[E0594]: cannot assign to immutable borrowed content `*n`
+  --> $DIR/explicit-mut.rs:23:13
+   |
+LL |             *n += 1;
+   |             ^^^^^^^ cannot borrow as mutable
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/rfc-2005-default-binding-mode/for.rs b/src/test/ui/rfc-2005-default-binding-mode/for.rs
new file mode 100644
index 0000000..2fa7852
--- /dev/null
+++ b/src/test/ui/rfc-2005-default-binding-mode/for.rs
@@ -0,0 +1,9 @@
+struct Foo {}
+
+pub fn main() {
+    let mut tups = vec![(Foo{}, Foo{})];
+    // The below desugars to &(ref n, mut m).
+    for (n, mut m) in &tups {
+        //~^ ERROR cannot bind by-move and by-ref in the same pattern
+    }
+}
diff --git a/src/test/ui/rfc-2005-default-binding-mode/for.stderr b/src/test/ui/rfc-2005-default-binding-mode/for.stderr
new file mode 100644
index 0000000..37aaa9c
--- /dev/null
+++ b/src/test/ui/rfc-2005-default-binding-mode/for.stderr
@@ -0,0 +1,11 @@
+error[E0009]: cannot bind by-move and by-ref in the same pattern
+  --> $DIR/for.rs:6:13
+   |
+LL |     for (n, mut m) in &tups {
+   |          -  ^^^^^ by-move pattern here
+   |          |
+   |          both by-ref and by-move used
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0009`.
diff --git a/src/test/ui/rfc-2005-default-binding-mode/issue-44912-or.rs b/src/test/ui/rfc-2005-default-binding-mode/issue-44912-or.rs
new file mode 100644
index 0000000..aa013d4
--- /dev/null
+++ b/src/test/ui/rfc-2005-default-binding-mode/issue-44912-or.rs
@@ -0,0 +1,10 @@
+// FIXME(tschottdorf): This should compile. See #44912.
+
+pub fn main() {
+    let x = &Some((3, 3));
+    let _: &i32 = match x {
+        Some((x, 3)) | &Some((ref x, 5)) => x,
+        //~^ ERROR is bound in inconsistent ways
+        _ => &5i32,
+    };
+}
diff --git a/src/test/ui/rfc-2005-default-binding-mode/issue-44912-or.stderr b/src/test/ui/rfc-2005-default-binding-mode/issue-44912-or.stderr
new file mode 100644
index 0000000..ff8dce3
--- /dev/null
+++ b/src/test/ui/rfc-2005-default-binding-mode/issue-44912-or.stderr
@@ -0,0 +1,9 @@
+error[E0409]: variable `x` is bound in inconsistent ways within the same match arm
+  --> $DIR/issue-44912-or.rs:6:35
+   |
+LL |         Some((x, 3)) | &Some((ref x, 5)) => x,
+   |               - first binding     ^ bound in different ways
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0409`.
diff --git a/src/test/ui/rfc-2005-default-binding-mode/lit.rs b/src/test/ui/rfc-2005-default-binding-mode/lit.rs
new file mode 100644
index 0000000..ce79cfb
--- /dev/null
+++ b/src/test/ui/rfc-2005-default-binding-mode/lit.rs
@@ -0,0 +1,24 @@
+// FIXME(tschottdorf): we want these to compile, but they don't.
+
+fn with_str() {
+    let s: &'static str = "abc";
+
+    match &s {
+            "abc" => true, //~ ERROR mismatched types
+            _ => panic!(),
+    };
+}
+
+fn with_bytes() {
+    let s: &'static [u8] = b"abc";
+
+    match &s {
+        b"abc" => true, //~ ERROR mismatched types
+        _ => panic!(),
+    };
+}
+
+pub fn main() {
+    with_str();
+    with_bytes();
+}
diff --git a/src/test/ui/rfc-2005-default-binding-mode/lit.stderr b/src/test/ui/rfc-2005-default-binding-mode/lit.stderr
new file mode 100644
index 0000000..9be1876
--- /dev/null
+++ b/src/test/ui/rfc-2005-default-binding-mode/lit.stderr
@@ -0,0 +1,21 @@
+error[E0308]: mismatched types
+  --> $DIR/lit.rs:7:13
+   |
+LL |             "abc" => true,
+   |             ^^^^^ expected &str, found str
+   |
+   = note: expected type `&&str`
+              found type `&'static str`
+
+error[E0308]: mismatched types
+  --> $DIR/lit.rs:16:9
+   |
+LL |         b"abc" => true,
+   |         ^^^^^^ expected &[u8], found array of 3 elements
+   |
+   = note: expected type `&&[u8]`
+              found type `&'static [u8; 3]`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/rfc-2005-default-binding-mode/no-double-error.rs b/src/test/ui/rfc-2005-default-binding-mode/no-double-error.rs
new file mode 100644
index 0000000..46fdfd6
--- /dev/null
+++ b/src/test/ui/rfc-2005-default-binding-mode/no-double-error.rs
@@ -0,0 +1,11 @@
+// Without caching type lookups in FnCtxt.resolve_ty_and_def_ufcs
+// the error below would be reported twice (once when checking
+// for a non-ref pattern, once when processing the pattern).
+
+fn main() {
+    let foo = 22;
+    match foo {
+        u32::XXX => { } //~ ERROR no associated item named
+        _ => { }
+    }
+}
diff --git a/src/test/ui/rfc-2005-default-binding-mode/no-double-error.stderr b/src/test/ui/rfc-2005-default-binding-mode/no-double-error.stderr
new file mode 100644
index 0000000..c672ace
--- /dev/null
+++ b/src/test/ui/rfc-2005-default-binding-mode/no-double-error.stderr
@@ -0,0 +1,9 @@
+error[E0599]: no associated item named `XXX` found for type `u32` in the current scope
+  --> $DIR/no-double-error.rs:8:14
+   |
+LL |         u32::XXX => { }
+   |              ^^^ associated item not found in `u32`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/rfc-2005-default-binding-mode/slice.rs b/src/test/ui/rfc-2005-default-binding-mode/slice.rs
new file mode 100644
index 0000000..fd85bf7
--- /dev/null
+++ b/src/test/ui/rfc-2005-default-binding-mode/slice.rs
@@ -0,0 +1,9 @@
+#![feature(slice_patterns)]
+
+pub fn main() {
+    let sl: &[u8] = b"foo";
+
+    match sl { //~ ERROR non-exhaustive patterns
+        [first, remainder..] => {},
+    };
+}
diff --git a/src/test/ui/rfc-2005-default-binding-mode/slice.stderr b/src/test/ui/rfc-2005-default-binding-mode/slice.stderr
new file mode 100644
index 0000000..f1e91a0
--- /dev/null
+++ b/src/test/ui/rfc-2005-default-binding-mode/slice.stderr
@@ -0,0 +1,11 @@
+error[E0004]: non-exhaustive patterns: `&[]` not covered
+  --> $DIR/slice.rs:6:11
+   |
+LL |     match sl {
+   |           ^^ pattern `&[]` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/rfc-2008-non-exhaustive/auxiliary/enums.rs b/src/test/ui/rfc-2008-non-exhaustive/auxiliary/enums.rs
new file mode 100644
index 0000000..e382059
--- /dev/null
+++ b/src/test/ui/rfc-2008-non-exhaustive/auxiliary/enums.rs
@@ -0,0 +1,9 @@
+#![crate_type = "rlib"]
+#![feature(non_exhaustive)]
+
+#[non_exhaustive]
+pub enum NonExhaustiveEnum {
+    Unit,
+    Tuple(u32),
+    Struct { field: u32 }
+}
diff --git a/src/test/ui/rfc-2008-non-exhaustive/auxiliary/structs.rs b/src/test/ui/rfc-2008-non-exhaustive/auxiliary/structs.rs
new file mode 100644
index 0000000..ddfb9ad
--- /dev/null
+++ b/src/test/ui/rfc-2008-non-exhaustive/auxiliary/structs.rs
@@ -0,0 +1,27 @@
+#![feature(non_exhaustive)]
+
+#[non_exhaustive]
+pub struct NormalStruct {
+    pub first_field: u16,
+    pub second_field: u16,
+}
+
+#[non_exhaustive]
+pub struct UnitStruct;
+
+#[non_exhaustive]
+pub struct TupleStruct(pub u16, pub u16);
+
+#[derive(Debug)]
+#[non_exhaustive]
+pub struct FunctionalRecord {
+    pub first_field: u16,
+    pub second_field: u16,
+    pub third_field: bool
+}
+
+impl Default for FunctionalRecord {
+    fn default() -> FunctionalRecord {
+        FunctionalRecord { first_field: 640, second_field: 480, third_field: false }
+    }
+}
diff --git a/src/test/ui/rfc-2008-non-exhaustive/auxiliary/variants.rs b/src/test/ui/rfc-2008-non-exhaustive/auxiliary/variants.rs
new file mode 100644
index 0000000..f590d0a
--- /dev/null
+++ b/src/test/ui/rfc-2008-non-exhaustive/auxiliary/variants.rs
@@ -0,0 +1,8 @@
+#![crate_type = "rlib"]
+#![feature(non_exhaustive)]
+
+pub enum NonExhaustiveVariants {
+    #[non_exhaustive] Unit,
+    #[non_exhaustive] Tuple(u32),
+    #[non_exhaustive] Struct { field: u32 }
+}
diff --git a/src/test/ui/rfc-2008-non-exhaustive/enum.rs b/src/test/ui/rfc-2008-non-exhaustive/enum.rs
new file mode 100644
index 0000000..7423a97
--- /dev/null
+++ b/src/test/ui/rfc-2008-non-exhaustive/enum.rs
@@ -0,0 +1,59 @@
+// aux-build:enums.rs
+extern crate enums;
+
+use enums::NonExhaustiveEnum;
+
+fn main() {
+    let enum_unit = NonExhaustiveEnum::Unit;
+
+    match enum_unit {
+        //~^ ERROR non-exhaustive patterns: `_` not covered [E0004]
+        NonExhaustiveEnum::Unit => "first",
+        NonExhaustiveEnum::Tuple(_) => "second",
+        NonExhaustiveEnum::Struct { .. } => "third"
+    };
+
+    // Everything below this is expected to compile successfully.
+
+    let enum_unit = NonExhaustiveEnum::Unit;
+
+    match enum_unit {
+        NonExhaustiveEnum::Unit => 1,
+        NonExhaustiveEnum::Tuple(_) => 2,
+        // This particular arm tests that a enum marked as non-exhaustive
+        // will not error if its variants are matched exhaustively.
+        NonExhaustiveEnum::Struct { field } => field,
+        _ => 0 // no error with wildcard
+    };
+
+    match enum_unit {
+        _ => "no error with only wildcard"
+    };
+
+    // #53549: Check that variant constructors can still be called normally.
+    match NonExhaustiveEnum::Unit {
+        NonExhaustiveEnum::Unit => {},
+        _ => {}
+    };
+
+    match NonExhaustiveEnum::Tuple(2) {
+        NonExhaustiveEnum::Tuple(2) => {},
+        _ => {}
+    };
+
+    match (NonExhaustiveEnum::Unit {}) {
+        NonExhaustiveEnum::Unit {} => {},
+        _ => {}
+    };
+
+    match (NonExhaustiveEnum::Tuple { 0: 2 }) {
+        NonExhaustiveEnum::Tuple { 0: 2 } => {},
+        _ => {}
+    };
+
+    match (NonExhaustiveEnum::Struct { field: 2 }) {
+        NonExhaustiveEnum::Struct { field: 2 } => {},
+        _ => {}
+    };
+
+}
diff --git a/src/test/ui/rfc-2008-non-exhaustive/enum.stderr b/src/test/ui/rfc-2008-non-exhaustive/enum.stderr
new file mode 100644
index 0000000..b5c1a4e
--- /dev/null
+++ b/src/test/ui/rfc-2008-non-exhaustive/enum.stderr
@@ -0,0 +1,11 @@
+error[E0004]: non-exhaustive patterns: `_` not covered
+  --> $DIR/enum.rs:9:11
+   |
+LL |     match enum_unit {
+   |           ^^^^^^^^^ pattern `_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/rfc-2008-non-exhaustive/enum_same_crate.rs b/src/test/ui/rfc-2008-non-exhaustive/enum_same_crate.rs
new file mode 100644
index 0000000..a3626bf
--- /dev/null
+++ b/src/test/ui/rfc-2008-non-exhaustive/enum_same_crate.rs
@@ -0,0 +1,20 @@
+// run-pass
+
+#![feature(non_exhaustive)]
+
+#[non_exhaustive]
+pub enum NonExhaustiveEnum {
+    Unit,
+    Tuple(u32),
+    Struct { field: u32 }
+}
+
+fn main() {
+    let enum_unit = NonExhaustiveEnum::Unit;
+
+    match enum_unit {
+        NonExhaustiveEnum::Unit => "first",
+        NonExhaustiveEnum::Tuple(_) => "second",
+        NonExhaustiveEnum::Struct { .. } => "third",
+    };
+}
diff --git a/src/test/ui/rfc-2008-non-exhaustive/invalid-attribute.rs b/src/test/ui/rfc-2008-non-exhaustive/invalid-attribute.rs
new file mode 100644
index 0000000..3375210
--- /dev/null
+++ b/src/test/ui/rfc-2008-non-exhaustive/invalid-attribute.rs
@@ -0,0 +1,18 @@
+#![feature(non_exhaustive)]
+
+#[non_exhaustive(anything)]
+//~^ ERROR attribute must be of the form
+struct Foo;
+
+#[non_exhaustive]
+//~^ ERROR attribute can only be applied to a struct or enum [E0701]
+trait Bar { }
+
+#[non_exhaustive]
+//~^ ERROR attribute can only be applied to a struct or enum [E0701]
+union Baz {
+    f1: u16,
+    f2: u16
+}
+
+fn main() { }
diff --git a/src/test/ui/rfc-2008-non-exhaustive/invalid-attribute.stderr b/src/test/ui/rfc-2008-non-exhaustive/invalid-attribute.stderr
new file mode 100644
index 0000000..ff082e6
--- /dev/null
+++ b/src/test/ui/rfc-2008-non-exhaustive/invalid-attribute.stderr
@@ -0,0 +1,30 @@
+error: attribute must be of the form `#[non_exhaustive]`
+  --> $DIR/invalid-attribute.rs:3:1
+   |
+LL | #[non_exhaustive(anything)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0701]: attribute can only be applied to a struct or enum
+  --> $DIR/invalid-attribute.rs:7:1
+   |
+LL | #[non_exhaustive]
+   | ^^^^^^^^^^^^^^^^^
+LL |
+LL | trait Bar { }
+   | ------------- not a struct or enum
+
+error[E0701]: attribute can only be applied to a struct or enum
+  --> $DIR/invalid-attribute.rs:11:1
+   |
+LL |   #[non_exhaustive]
+   |   ^^^^^^^^^^^^^^^^^
+LL |
+LL | / union Baz {
+LL | |     f1: u16,
+LL | |     f2: u16
+LL | | }
+   | |_- not a struct or enum
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0701`.
diff --git a/src/test/ui/rfc-2008-non-exhaustive/struct.rs b/src/test/ui/rfc-2008-non-exhaustive/struct.rs
new file mode 100644
index 0000000..94ac588
--- /dev/null
+++ b/src/test/ui/rfc-2008-non-exhaustive/struct.rs
@@ -0,0 +1,49 @@
+// aux-build:structs.rs
+extern crate structs;
+
+use structs::{NormalStruct, UnitStruct, TupleStruct, FunctionalRecord};
+
+fn main() {
+    let fr = FunctionalRecord {
+    //~^ ERROR cannot create non-exhaustive struct
+        first_field: 1920,
+        second_field: 1080,
+        ..FunctionalRecord::default()
+    };
+
+    let ns = NormalStruct { first_field: 640, second_field: 480 };
+    //~^ ERROR cannot create non-exhaustive struct
+
+    let NormalStruct { first_field, second_field } = ns;
+    //~^ ERROR `..` required with struct marked as non-exhaustive
+
+    let ts = TupleStruct(640, 480);
+    //~^ ERROR expected function, found struct `TupleStruct` [E0423]
+
+    let ts_explicit = structs::TupleStruct(640, 480);
+    //~^ ERROR tuple struct `TupleStruct` is private [E0603]
+
+    let TupleStruct { 0: first_field, 1: second_field } = ts;
+    //~^ ERROR `..` required with struct marked as non-exhaustive
+
+    let us = UnitStruct;
+    //~^ ERROR expected value, found struct `UnitStruct` [E0423]
+
+    let us_explicit = structs::UnitStruct;
+    //~^ ERROR unit struct `UnitStruct` is private [E0603]
+
+    let UnitStruct { } = us;
+    //~^ ERROR `..` required with struct marked as non-exhaustive
+}
+
+// Everything below this is expected to compile successfully.
+
+// We only test matching here as we cannot create non-exhaustive
+// structs from another crate. ie. they'll never pass in run-pass tests.
+fn match_structs(ns: NormalStruct, ts: TupleStruct, us: UnitStruct) {
+    let NormalStruct { first_field, second_field, .. } = ns;
+
+    let TupleStruct { 0: first, 1: second, .. } = ts;
+
+    let UnitStruct { .. } = us;
+}
diff --git a/src/test/ui/rfc-2008-non-exhaustive/struct.stderr b/src/test/ui/rfc-2008-non-exhaustive/struct.stderr
new file mode 100644
index 0000000..ecfad88
--- /dev/null
+++ b/src/test/ui/rfc-2008-non-exhaustive/struct.stderr
@@ -0,0 +1,64 @@
+error[E0423]: expected function, found struct `TupleStruct`
+  --> $DIR/struct.rs:20:14
+   |
+LL |     let ts = TupleStruct(640, 480);
+   |              ^^^^^^^^^^^ constructor is not visible here due to private fields
+
+error[E0423]: expected value, found struct `UnitStruct`
+  --> $DIR/struct.rs:29:14
+   |
+LL |     let us = UnitStruct;
+   |              ^^^^^^^^^^ constructor is not visible here due to private fields
+
+error[E0603]: tuple struct `TupleStruct` is private
+  --> $DIR/struct.rs:23:32
+   |
+LL |     let ts_explicit = structs::TupleStruct(640, 480);
+   |                                ^^^^^^^^^^^
+
+error[E0603]: unit struct `UnitStruct` is private
+  --> $DIR/struct.rs:32:32
+   |
+LL |     let us_explicit = structs::UnitStruct;
+   |                                ^^^^^^^^^^
+
+error[E0639]: cannot create non-exhaustive struct using struct expression
+  --> $DIR/struct.rs:7:14
+   |
+LL |       let fr = FunctionalRecord {
+   |  ______________^
+LL | |
+LL | |         first_field: 1920,
+LL | |         second_field: 1080,
+LL | |         ..FunctionalRecord::default()
+LL | |     };
+   | |_____^
+
+error[E0639]: cannot create non-exhaustive struct using struct expression
+  --> $DIR/struct.rs:14:14
+   |
+LL |     let ns = NormalStruct { first_field: 640, second_field: 480 };
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0638]: `..` required with struct marked as non-exhaustive
+  --> $DIR/struct.rs:17:9
+   |
+LL |     let NormalStruct { first_field, second_field } = ns;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0638]: `..` required with struct marked as non-exhaustive
+  --> $DIR/struct.rs:26:9
+   |
+LL |     let TupleStruct { 0: first_field, 1: second_field } = ts;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0638]: `..` required with struct marked as non-exhaustive
+  --> $DIR/struct.rs:35:9
+   |
+LL |     let UnitStruct { } = us;
+   |         ^^^^^^^^^^^^^^
+
+error: aborting due to 9 previous errors
+
+Some errors occurred: E0423, E0603, E0638, E0639.
+For more information about an error, try `rustc --explain E0423`.
diff --git a/src/test/ui/rfc-2008-non-exhaustive/structs_same_crate.rs b/src/test/ui/rfc-2008-non-exhaustive/structs_same_crate.rs
new file mode 100644
index 0000000..2b1d7d9
--- /dev/null
+++ b/src/test/ui/rfc-2008-non-exhaustive/structs_same_crate.rs
@@ -0,0 +1,33 @@
+// run-pass
+
+#![allow(unused_variables)]
+#![feature(non_exhaustive)]
+
+#[non_exhaustive]
+pub struct NormalStruct {
+    pub first_field: u16,
+    pub second_field: u16,
+}
+
+#[non_exhaustive]
+pub struct UnitStruct;
+
+#[non_exhaustive]
+pub struct TupleStruct (pub u16, pub u16);
+
+fn main() {
+    let ns = NormalStruct { first_field: 640, second_field: 480 };
+
+    let NormalStruct { first_field, second_field } = ns;
+
+    let ts = TupleStruct { 0: 340, 1: 480 };
+    let ts_constructor = TupleStruct(340, 480);
+
+    let TupleStruct { 0: first, 1: second } = ts;
+    let TupleStruct(first, second) = ts_constructor;
+
+    let us = UnitStruct {};
+    let us_constructor = UnitStruct;
+
+    let UnitStruct { } = us;
+}
diff --git a/src/test/ui/rfc-2008-non-exhaustive/variant.rs b/src/test/ui/rfc-2008-non-exhaustive/variant.rs
new file mode 100644
index 0000000..bc346ae
--- /dev/null
+++ b/src/test/ui/rfc-2008-non-exhaustive/variant.rs
@@ -0,0 +1,33 @@
+// aux-build:variants.rs
+
+extern crate variants;
+
+use variants::NonExhaustiveVariants;
+
+fn main() {
+    let variant_struct = NonExhaustiveVariants::Struct { field: 640 };
+    //~^ ERROR cannot create non-exhaustive variant
+
+    let variant_tuple = NonExhaustiveVariants::Tuple(640);
+    //~^ ERROR tuple variant `Tuple` is private [E0603]
+
+    let variant_unit = NonExhaustiveVariants::Unit;
+    //~^ ERROR unit variant `Unit` is private [E0603]
+
+    match variant_struct {
+        NonExhaustiveVariants::Unit => "",
+        //~^ ERROR unit variant `Unit` is private [E0603]
+        NonExhaustiveVariants::Tuple(fe_tpl) => "",
+        //~^ ERROR tuple variant `Tuple` is private [E0603]
+        NonExhaustiveVariants::Struct { field } => ""
+        //~^ ERROR `..` required with variant marked as non-exhaustive
+    };
+
+    if let NonExhaustiveVariants::Tuple(fe_tpl) = variant_struct {
+        //~^ ERROR tuple variant `Tuple` is private [E0603]
+    }
+
+    if let NonExhaustiveVariants::Struct { field } = variant_struct {
+        //~^ ERROR `..` required with variant marked as non-exhaustive
+    }
+}
diff --git a/src/test/ui/rfc-2008-non-exhaustive/variant.stderr b/src/test/ui/rfc-2008-non-exhaustive/variant.stderr
new file mode 100644
index 0000000..edfca78
--- /dev/null
+++ b/src/test/ui/rfc-2008-non-exhaustive/variant.stderr
@@ -0,0 +1,52 @@
+error[E0603]: tuple variant `Tuple` is private
+  --> $DIR/variant.rs:11:48
+   |
+LL |     let variant_tuple = NonExhaustiveVariants::Tuple(640);
+   |                                                ^^^^^
+
+error[E0603]: unit variant `Unit` is private
+  --> $DIR/variant.rs:14:47
+   |
+LL |     let variant_unit = NonExhaustiveVariants::Unit;
+   |                                               ^^^^
+
+error[E0603]: unit variant `Unit` is private
+  --> $DIR/variant.rs:18:32
+   |
+LL |         NonExhaustiveVariants::Unit => "",
+   |                                ^^^^
+
+error[E0603]: tuple variant `Tuple` is private
+  --> $DIR/variant.rs:20:32
+   |
+LL |         NonExhaustiveVariants::Tuple(fe_tpl) => "",
+   |                                ^^^^^
+
+error[E0603]: tuple variant `Tuple` is private
+  --> $DIR/variant.rs:26:35
+   |
+LL |     if let NonExhaustiveVariants::Tuple(fe_tpl) = variant_struct {
+   |                                   ^^^^^
+
+error[E0639]: cannot create non-exhaustive variant using struct expression
+  --> $DIR/variant.rs:8:26
+   |
+LL |     let variant_struct = NonExhaustiveVariants::Struct { field: 640 };
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0638]: `..` required with variant marked as non-exhaustive
+  --> $DIR/variant.rs:22:9
+   |
+LL |         NonExhaustiveVariants::Struct { field } => ""
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0638]: `..` required with variant marked as non-exhaustive
+  --> $DIR/variant.rs:30:12
+   |
+LL |     if let NonExhaustiveVariants::Struct { field } = variant_struct {
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 8 previous errors
+
+Some errors occurred: E0603, E0638, E0639.
+For more information about an error, try `rustc --explain E0603`.
diff --git a/src/test/ui/rfc-2008-non-exhaustive/variants_same_crate.rs b/src/test/ui/rfc-2008-non-exhaustive/variants_same_crate.rs
new file mode 100644
index 0000000..470a5ea
--- /dev/null
+++ b/src/test/ui/rfc-2008-non-exhaustive/variants_same_crate.rs
@@ -0,0 +1,20 @@
+// run-pass
+
+#![feature(non_exhaustive)]
+
+pub enum NonExhaustiveVariants {
+    #[non_exhaustive] Unit,
+    #[non_exhaustive] Tuple(u32),
+    #[non_exhaustive] Struct { field: u32 }
+}
+
+fn main() {
+    let variant_tuple = NonExhaustiveVariants::Tuple(340);
+    let variant_struct = NonExhaustiveVariants::Struct { field: 340 };
+
+    match variant_tuple {
+        NonExhaustiveVariants::Unit => "",
+        NonExhaustiveVariants::Tuple(fe_tpl) => "",
+        NonExhaustiveVariants::Struct { field } => ""
+    };
+}
diff --git a/src/test/ui/rfc-2093-infer-outlives/cross-crate.rs b/src/test/ui/rfc-2093-infer-outlives/cross-crate.rs
new file mode 100644
index 0000000..ce50452
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/cross-crate.rs
@@ -0,0 +1,9 @@
+#![feature(rustc_attrs)]
+
+#[rustc_outlives]
+struct Foo<'a, T> { //~ ERROR rustc_outlives
+    bar: std::slice::IterMut<'a, T>
+}
+
+fn main() {}
+
diff --git a/src/test/ui/rfc-2093-infer-outlives/cross-crate.stderr b/src/test/ui/rfc-2093-infer-outlives/cross-crate.stderr
new file mode 100644
index 0000000..3368e35
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/cross-crate.stderr
@@ -0,0 +1,12 @@
+error: rustc_outlives
+  --> $DIR/cross-crate.rs:4:1
+   |
+LL | / struct Foo<'a, T> {
+LL | |     bar: std::slice::IterMut<'a, T>
+LL | | }
+   | |_^
+   |
+   = note: T : 'a
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc-2093-infer-outlives/dont-infer-static.rs b/src/test/ui/rfc-2093-infer-outlives/dont-infer-static.rs
new file mode 100644
index 0000000..812e8c8
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/dont-infer-static.rs
@@ -0,0 +1,17 @@
+// ignore-tidy-linelength
+
+/*
+ * We don't infer `T: 'static` outlives relationships by default.
+ * Instead an additional feature gate `infer_static_outlives_requirements`
+ * is required.
+ */
+
+struct Foo<U> {
+    bar: Bar<U> //~ ERROR the parameter type `U` may not live long enough [E0310]
+}
+struct Bar<T: 'static> {
+    x: T,
+}
+
+fn main() {}
+
diff --git a/src/test/ui/rfc-2093-infer-outlives/dont-infer-static.stderr b/src/test/ui/rfc-2093-infer-outlives/dont-infer-static.stderr
new file mode 100644
index 0000000..26cbeea
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/dont-infer-static.stderr
@@ -0,0 +1,17 @@
+error[E0310]: the parameter type `U` may not live long enough
+  --> $DIR/dont-infer-static.rs:10:5
+   |
+LL | struct Foo<U> {
+   |            - help: consider adding an explicit lifetime bound `U: 'static`...
+LL |     bar: Bar<U>
+   |     ^^^^^^^^^^^
+   |
+note: ...so that the type `U` will meet its required lifetime bounds
+  --> $DIR/dont-infer-static.rs:10:5
+   |
+LL |     bar: Bar<U>
+   |     ^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0310`.
diff --git a/src/test/ui/rfc-2093-infer-outlives/enum.rs b/src/test/ui/rfc-2093-infer-outlives/enum.rs
new file mode 100644
index 0000000..622794e
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/enum.rs
@@ -0,0 +1,29 @@
+// ignore-tidy-linelength
+
+#![feature(rustc_attrs)]
+
+// Needs an explicit where clause stating outlives condition. (RFC 2093)
+
+// Type T needs to outlive lifetime 'a.
+#[rustc_outlives]
+enum Foo<'a, T> { //~ ERROR rustc_outlives
+    One(Bar<'a, T>)
+}
+
+// Type U needs to outlive lifetime 'b
+#[rustc_outlives]
+struct Bar<'b, U> { //~ ERROR rustc_outlives
+    field2: &'b U
+}
+
+// Type K needs to outlive lifetime 'c.
+#[rustc_outlives]
+enum Ying<'c, K> { //~ ERROR rustc_outlives
+    One(&'c Yang<K>)
+}
+
+struct Yang<V> {
+    field2: V
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc-2093-infer-outlives/enum.stderr b/src/test/ui/rfc-2093-infer-outlives/enum.stderr
new file mode 100644
index 0000000..e81d10a
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/enum.stderr
@@ -0,0 +1,32 @@
+error: rustc_outlives
+  --> $DIR/enum.rs:9:1
+   |
+LL | / enum Foo<'a, T> {
+LL | |     One(Bar<'a, T>)
+LL | | }
+   | |_^
+   |
+   = note: T : 'a
+
+error: rustc_outlives
+  --> $DIR/enum.rs:15:1
+   |
+LL | / struct Bar<'b, U> {
+LL | |     field2: &'b U
+LL | | }
+   | |_^
+   |
+   = note: U : 'b
+
+error: rustc_outlives
+  --> $DIR/enum.rs:21:1
+   |
+LL | / enum Ying<'c, K> {
+LL | |     One(&'c Yang<K>)
+LL | | }
+   | |_^
+   |
+   = note: K : 'c
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/rfc-2093-infer-outlives/explicit-dyn.rs b/src/test/ui/rfc-2093-infer-outlives/explicit-dyn.rs
new file mode 100644
index 0000000..e33d57d
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/explicit-dyn.rs
@@ -0,0 +1,13 @@
+#![feature(dyn_trait)]
+#![feature(rustc_attrs)]
+
+trait Trait<'x, T> where T: 'x {
+}
+
+#[rustc_outlives]
+struct Foo<'a, A> //~ ERROR rustc_outlives
+{
+    foo: Box<dyn Trait<'a, A>>
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc-2093-infer-outlives/explicit-dyn.stderr b/src/test/ui/rfc-2093-infer-outlives/explicit-dyn.stderr
new file mode 100644
index 0000000..c87ef6c
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/explicit-dyn.stderr
@@ -0,0 +1,13 @@
+error: rustc_outlives
+  --> $DIR/explicit-dyn.rs:8:1
+   |
+LL | / struct Foo<'a, A>
+LL | | {
+LL | |     foo: Box<dyn Trait<'a, A>>
+LL | | }
+   | |_^
+   |
+   = note: A : 'a
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc-2093-infer-outlives/explicit-enum.rs b/src/test/ui/rfc-2093-infer-outlives/explicit-enum.rs
new file mode 100644
index 0000000..b7a66a3
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/explicit-enum.rs
@@ -0,0 +1,14 @@
+#![feature(rustc_attrs)]
+
+#[rustc_outlives]
+enum Foo<'a, U> { //~ ERROR rustc_outlives
+    One(Bar<'a, U>)
+}
+
+struct Bar<'x, T> where T: 'x {
+    x: &'x (),
+    y: T,
+}
+
+fn main() {}
+
diff --git a/src/test/ui/rfc-2093-infer-outlives/explicit-enum.stderr b/src/test/ui/rfc-2093-infer-outlives/explicit-enum.stderr
new file mode 100644
index 0000000..611df04
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/explicit-enum.stderr
@@ -0,0 +1,12 @@
+error: rustc_outlives
+  --> $DIR/explicit-enum.rs:4:1
+   |
+LL | / enum Foo<'a, U> {
+LL | |     One(Bar<'a, U>)
+LL | | }
+   | |_^
+   |
+   = note: U : 'a
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc-2093-infer-outlives/explicit-projection.rs b/src/test/ui/rfc-2093-infer-outlives/explicit-projection.rs
new file mode 100644
index 0000000..00b8952
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/explicit-projection.rs
@@ -0,0 +1,13 @@
+#![feature(rustc_attrs)]
+
+trait Trait<'x, T> where T: 'x {
+    type Type;
+}
+
+#[rustc_outlives]
+struct Foo<'a, A, B> where A: Trait<'a, B> //~ ERROR rustc_outlives
+{
+    foo: <A as Trait<'a, B>>::Type
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc-2093-infer-outlives/explicit-projection.stderr b/src/test/ui/rfc-2093-infer-outlives/explicit-projection.stderr
new file mode 100644
index 0000000..8e9b158
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/explicit-projection.stderr
@@ -0,0 +1,13 @@
+error: rustc_outlives
+  --> $DIR/explicit-projection.rs:8:1
+   |
+LL | / struct Foo<'a, A, B> where A: Trait<'a, B>
+LL | | {
+LL | |     foo: <A as Trait<'a, B>>::Type
+LL | | }
+   | |_^
+   |
+   = note: B : 'a
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc-2093-infer-outlives/explicit-struct.rs b/src/test/ui/rfc-2093-infer-outlives/explicit-struct.rs
new file mode 100644
index 0000000..3c69f9f
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/explicit-struct.rs
@@ -0,0 +1,14 @@
+#![feature(rustc_attrs)]
+
+#[rustc_outlives]
+struct Foo<'b, U> { //~ ERROR rustc_outlives
+    bar: Bar<'b, U>
+}
+
+struct Bar<'a, T> where T: 'a {
+    x: &'a (),
+    y: T,
+}
+
+fn main() {}
+
diff --git a/src/test/ui/rfc-2093-infer-outlives/explicit-struct.stderr b/src/test/ui/rfc-2093-infer-outlives/explicit-struct.stderr
new file mode 100644
index 0000000..cbff2b7
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/explicit-struct.stderr
@@ -0,0 +1,12 @@
+error: rustc_outlives
+  --> $DIR/explicit-struct.rs:4:1
+   |
+LL | / struct Foo<'b, U> {
+LL | |     bar: Bar<'b, U>
+LL | | }
+   | |_^
+   |
+   = note: U : 'b
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc-2093-infer-outlives/explicit-union.rs b/src/test/ui/rfc-2093-infer-outlives/explicit-union.rs
new file mode 100644
index 0000000..87a789b
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/explicit-union.rs
@@ -0,0 +1,16 @@
+#![feature(rustc_attrs)]
+#![feature(untagged_unions)]
+#![allow(unions_with_drop_fields)]
+
+#[rustc_outlives]
+union Foo<'b, U> { //~ ERROR rustc_outlives
+    bar: Bar<'b, U>
+}
+
+union Bar<'a, T> where T: 'a {
+    x: &'a (),
+    y: T,
+}
+
+fn main() {}
+
diff --git a/src/test/ui/rfc-2093-infer-outlives/explicit-union.stderr b/src/test/ui/rfc-2093-infer-outlives/explicit-union.stderr
new file mode 100644
index 0000000..adf6265
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/explicit-union.stderr
@@ -0,0 +1,12 @@
+error: rustc_outlives
+  --> $DIR/explicit-union.rs:6:1
+   |
+LL | / union Foo<'b, U> {
+LL | |     bar: Bar<'b, U>
+LL | | }
+   | |_^
+   |
+   = note: U : 'b
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc-2093-infer-outlives/infer-static.rs b/src/test/ui/rfc-2093-infer-outlives/infer-static.rs
new file mode 100644
index 0000000..916d484
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/infer-static.rs
@@ -0,0 +1,13 @@
+#![feature(rustc_attrs)]
+#![feature(infer_static_outlives_requirements)]
+
+#[rustc_outlives]
+struct Foo<U> { //~ ERROR rustc_outlives
+    bar: Bar<U>
+}
+struct Bar<T: 'static> {
+    x: T,
+}
+
+fn main() {}
+
diff --git a/src/test/ui/rfc-2093-infer-outlives/infer-static.stderr b/src/test/ui/rfc-2093-infer-outlives/infer-static.stderr
new file mode 100644
index 0000000..106db76
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/infer-static.stderr
@@ -0,0 +1,12 @@
+error: rustc_outlives
+  --> $DIR/infer-static.rs:5:1
+   |
+LL | / struct Foo<U> {
+LL | |     bar: Bar<U>
+LL | | }
+   | |_^
+   |
+   = note: U : 'static
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc-2093-infer-outlives/issue-54467.rs b/src/test/ui/rfc-2093-infer-outlives/issue-54467.rs
new file mode 100644
index 0000000..438923e
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/issue-54467.rs
@@ -0,0 +1,17 @@
+// Regression test for #54467:
+//
+// Here, the trait object has an "inferred outlives" requirement that
+// `<Self as MyIterator<'a>>::Item: 'a`; but since we don't know what
+// `Self` is, we were (incorrectly) messing things up, leading to
+// strange errors. This test ensures that we do not give compilation
+// errors.
+//
+// compile-pass
+
+trait MyIterator<'a>: Iterator where Self::Item: 'a { }
+
+struct MyStruct<'a, A> {
+    item: Box<dyn MyIterator<'a, Item = A>>
+}
+
+fn main() { }
diff --git a/src/test/ui/rfc-2093-infer-outlives/nested-enum.rs b/src/test/ui/rfc-2093-infer-outlives/nested-enum.rs
new file mode 100644
index 0000000..0cd706e
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/nested-enum.rs
@@ -0,0 +1,13 @@
+#![feature(rustc_attrs)]
+
+#[rustc_outlives]
+enum Foo<'a, T> { //~ ERROR rustc_outlives
+
+    One(Bar<'a, T>)
+}
+
+struct Bar<'b, U> {
+    field2: &'b U
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc-2093-infer-outlives/nested-enum.stderr b/src/test/ui/rfc-2093-infer-outlives/nested-enum.stderr
new file mode 100644
index 0000000..6b143ba
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/nested-enum.stderr
@@ -0,0 +1,13 @@
+error: rustc_outlives
+  --> $DIR/nested-enum.rs:4:1
+   |
+LL | / enum Foo<'a, T> {
+LL | |
+LL | |     One(Bar<'a, T>)
+LL | | }
+   | |_^
+   |
+   = note: T : 'a
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc-2093-infer-outlives/nested-regions.rs b/src/test/ui/rfc-2093-infer-outlives/nested-regions.rs
new file mode 100644
index 0000000..a01c50681
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/nested-regions.rs
@@ -0,0 +1,8 @@
+#![feature(rustc_attrs)]
+
+#[rustc_outlives]
+struct Foo<'a, 'b, T> { //~ ERROR rustc_outlives
+    x: &'a &'b T
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc-2093-infer-outlives/nested-regions.stderr b/src/test/ui/rfc-2093-infer-outlives/nested-regions.stderr
new file mode 100644
index 0000000..4d8f7b7
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/nested-regions.stderr
@@ -0,0 +1,14 @@
+error: rustc_outlives
+  --> $DIR/nested-regions.rs:4:1
+   |
+LL | / struct Foo<'a, 'b, T> {
+LL | |     x: &'a &'b T
+LL | | }
+   | |_^
+   |
+   = note: 'b : 'a
+   = note: T : 'a
+   = note: T : 'b
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc-2093-infer-outlives/nested-structs.rs b/src/test/ui/rfc-2093-infer-outlives/nested-structs.rs
new file mode 100644
index 0000000..ac6817d
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/nested-structs.rs
@@ -0,0 +1,12 @@
+#![feature(rustc_attrs)]
+
+#[rustc_outlives]
+struct Foo<'a, T> { //~ ERROR rustc_outlives
+    field1: Bar<'a, T>
+}
+
+struct Bar<'b, U> {
+    field2: &'b U
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc-2093-infer-outlives/nested-structs.stderr b/src/test/ui/rfc-2093-infer-outlives/nested-structs.stderr
new file mode 100644
index 0000000..17d7c01
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/nested-structs.stderr
@@ -0,0 +1,12 @@
+error: rustc_outlives
+  --> $DIR/nested-structs.rs:4:1
+   |
+LL | / struct Foo<'a, T> {
+LL | |     field1: Bar<'a, T>
+LL | | }
+   | |_^
+   |
+   = note: T : 'a
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc-2093-infer-outlives/nested-union.rs b/src/test/ui/rfc-2093-infer-outlives/nested-union.rs
new file mode 100644
index 0000000..0ff667f
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/nested-union.rs
@@ -0,0 +1,15 @@
+#![feature(rustc_attrs)]
+#![feature(untagged_unions)]
+#![allow(unions_with_drop_fields)]
+
+#[rustc_outlives]
+union Foo<'a, T> { //~ ERROR rustc_outlives
+    field1: Bar<'a, T>
+}
+
+// Type U needs to outlive lifetime 'b
+union Bar<'b, U> {
+    field2: &'b U
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc-2093-infer-outlives/nested-union.stderr b/src/test/ui/rfc-2093-infer-outlives/nested-union.stderr
new file mode 100644
index 0000000..fc4b1a2
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/nested-union.stderr
@@ -0,0 +1,12 @@
+error: rustc_outlives
+  --> $DIR/nested-union.rs:6:1
+   |
+LL | / union Foo<'a, T> {
+LL | |     field1: Bar<'a, T>
+LL | | }
+   | |_^
+   |
+   = note: T : 'a
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc-2093-infer-outlives/privacy.rs b/src/test/ui/rfc-2093-infer-outlives/privacy.rs
new file mode 100644
index 0000000..180f5ac
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/privacy.rs
@@ -0,0 +1,20 @@
+// Test that we do not get a privacy error here.  Initially, we did,
+// because we inferred an outlives predciate of `<Foo<'a> as
+// Private>::Out: 'a`, but the private trait is -- well -- private,
+// and hence it was not something that a pub trait could refer to.
+//
+// run-pass
+
+#![allow(dead_code)]
+
+pub struct Foo<'a> {
+    field: Option<&'a <Foo<'a> as Private>::Out>
+}
+
+trait Private {
+    type Out: ?Sized;
+}
+
+impl<T: ?Sized> Private for T { type Out = Self; }
+
+fn main() { }
diff --git a/src/test/ui/rfc-2093-infer-outlives/projection.rs b/src/test/ui/rfc-2093-infer-outlives/projection.rs
new file mode 100644
index 0000000..0b9637e
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/projection.rs
@@ -0,0 +1,9 @@
+#![feature(rustc_attrs)]
+
+#[rustc_outlives]
+struct Foo<'a, T: Iterator> { //~ ERROR rustc_outlives
+    bar: &'a T::Item
+}
+
+fn main() {}
+
diff --git a/src/test/ui/rfc-2093-infer-outlives/projection.stderr b/src/test/ui/rfc-2093-infer-outlives/projection.stderr
new file mode 100644
index 0000000..8a91c44
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/projection.stderr
@@ -0,0 +1,12 @@
+error: rustc_outlives
+  --> $DIR/projection.rs:4:1
+   |
+LL | / struct Foo<'a, T: Iterator> {
+LL | |     bar: &'a T::Item
+LL | | }
+   | |_^
+   |
+   = note: <T as std::iter::Iterator>::Item : 'a
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc-2093-infer-outlives/reference.rs b/src/test/ui/rfc-2093-infer-outlives/reference.rs
new file mode 100644
index 0000000..a48a331
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/reference.rs
@@ -0,0 +1,8 @@
+#![feature(rustc_attrs)]
+
+#[rustc_outlives]
+struct Foo<'a, T> { //~ ERROR rustc_outlives
+    bar: &'a T,
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc-2093-infer-outlives/reference.stderr b/src/test/ui/rfc-2093-infer-outlives/reference.stderr
new file mode 100644
index 0000000..adb1c4a
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/reference.stderr
@@ -0,0 +1,12 @@
+error: rustc_outlives
+  --> $DIR/reference.rs:4:1
+   |
+LL | / struct Foo<'a, T> {
+LL | |     bar: &'a T,
+LL | | }
+   | |_^
+   |
+   = note: T : 'a
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.rs b/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.rs
new file mode 100644
index 0000000..781cdb7
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.rs
@@ -0,0 +1,40 @@
+// ignore-tidy-linelength
+
+// Various examples of structs whose fields are not well-formed.
+
+#![allow(dead_code)]
+
+trait Dummy<'a> {
+  type Out;
+}
+impl<'a, T> Dummy<'a> for T
+where T: 'a
+{
+  type Out = ();
+}
+type RequireOutlives<'a, T> = <T as Dummy<'a>>::Out;
+
+enum Ref1<'a, T> {
+    Ref1Variant1(RequireOutlives<'a, T>) //~ ERROR the parameter type `T` may not live long enough
+}
+
+enum Ref2<'a, T> {
+    Ref2Variant1,
+    Ref2Variant2(isize, RequireOutlives<'a, T>), //~ ERROR the parameter type `T` may not live long enough
+}
+
+enum RefOk<'a, T:'a> {
+    RefOkVariant1(&'a T)
+}
+
+// This is now well formed. RFC 2093
+enum RefIndirect<'a, T> {
+    RefIndirectVariant1(isize, RefOk<'a,T>)
+}
+
+enum RefDouble<'a, 'b, T> { //~ ERROR the parameter type `T` may not live long enough [E0309]
+    RefDoubleVariant1(&'a RequireOutlives<'b, T>)
+        //~^ the parameter type `T` may not live long enough [E0309]
+}
+
+fn main() { }
diff --git a/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.stderr b/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.stderr
new file mode 100644
index 0000000..8701408
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.stderr
@@ -0,0 +1,67 @@
+error[E0309]: the parameter type `T` may not live long enough
+  --> $DIR/regions-enum-not-wf.rs:18:18
+   |
+LL | enum Ref1<'a, T> {
+   |               - help: consider adding an explicit lifetime bound `T: 'a`...
+LL |     Ref1Variant1(RequireOutlives<'a, T>)
+   |                  ^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: ...so that the type `T` will meet its required lifetime bounds
+  --> $DIR/regions-enum-not-wf.rs:18:18
+   |
+LL |     Ref1Variant1(RequireOutlives<'a, T>)
+   |                  ^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0309]: the parameter type `T` may not live long enough
+  --> $DIR/regions-enum-not-wf.rs:23:25
+   |
+LL | enum Ref2<'a, T> {
+   |               - help: consider adding an explicit lifetime bound `T: 'a`...
+LL |     Ref2Variant1,
+LL |     Ref2Variant2(isize, RequireOutlives<'a, T>),
+   |                         ^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: ...so that the type `T` will meet its required lifetime bounds
+  --> $DIR/regions-enum-not-wf.rs:23:25
+   |
+LL |     Ref2Variant2(isize, RequireOutlives<'a, T>),
+   |                         ^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0309]: the parameter type `T` may not live long enough
+  --> $DIR/regions-enum-not-wf.rs:35:1
+   |
+LL |   enum RefDouble<'a, 'b, T> {
+   |   ^                      - help: consider adding an explicit lifetime bound `T: 'b`...
+   |  _|
+   | |
+LL | |     RefDoubleVariant1(&'a RequireOutlives<'b, T>)
+LL | |
+LL | | }
+   | |_^
+   |
+note: ...so that the type `T` will meet its required lifetime bounds
+  --> $DIR/regions-enum-not-wf.rs:35:1
+   |
+LL | / enum RefDouble<'a, 'b, T> {
+LL | |     RefDoubleVariant1(&'a RequireOutlives<'b, T>)
+LL | |
+LL | | }
+   | |_^
+
+error[E0309]: the parameter type `T` may not live long enough
+  --> $DIR/regions-enum-not-wf.rs:36:23
+   |
+LL | enum RefDouble<'a, 'b, T> {
+   |                        - help: consider adding an explicit lifetime bound `T: 'b`...
+LL |     RefDoubleVariant1(&'a RequireOutlives<'b, T>)
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: ...so that the type `T` will meet its required lifetime bounds
+  --> $DIR/regions-enum-not-wf.rs:36:23
+   |
+LL |     RefDoubleVariant1(&'a RequireOutlives<'b, T>)
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0309`.
diff --git a/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region-rev.rs b/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region-rev.rs
new file mode 100644
index 0000000..36b024d
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region-rev.rs
@@ -0,0 +1,22 @@
+// Test that a nominal type (like `Foo<'a>`) outlives `'b` if its
+// arguments (like `'a`) outlive `'b`.
+//
+// Rule OutlivesNominalType from RFC 1214.
+
+
+#![allow(dead_code)]
+
+mod rev_variant_struct_region {
+    struct Foo<'a> {
+        x: fn(&'a i32),
+    }
+    trait Trait<'a, 'b> {
+        type Out;
+    }
+    impl<'a, 'b> Trait<'a, 'b> for usize {
+        type Out = &'a Foo<'b>; //~ ERROR reference has a longer lifetime
+    }
+}
+
+
+fn main() { }
diff --git a/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region-rev.stderr b/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region-rev.stderr
new file mode 100644
index 0000000..be8b5c6
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region-rev.stderr
@@ -0,0 +1,20 @@
+error[E0491]: in type `&'a rev_variant_struct_region::Foo<'b>`, reference has a longer lifetime than the data it references
+  --> $DIR/regions-outlives-nominal-type-region-rev.rs:17:9
+   |
+LL |         type Out = &'a Foo<'b>;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the pointer is valid for the lifetime 'a as defined on the impl at 16:10
+  --> $DIR/regions-outlives-nominal-type-region-rev.rs:16:10
+   |
+LL |     impl<'a, 'b> Trait<'a, 'b> for usize {
+   |          ^^
+note: but the referenced data is only valid for the lifetime 'b as defined on the impl at 16:14
+  --> $DIR/regions-outlives-nominal-type-region-rev.rs:16:14
+   |
+LL |     impl<'a, 'b> Trait<'a, 'b> for usize {
+   |              ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0491`.
diff --git a/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region.rs b/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region.rs
new file mode 100644
index 0000000..47a38f7
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region.rs
@@ -0,0 +1,22 @@
+// Test that a nominal type (like `Foo<'a>`) outlives `'b` if its
+// arguments (like `'a`) outlive `'b`.
+//
+// Rule OutlivesNominalType from RFC 1214.
+
+
+#![allow(dead_code)]
+
+mod variant_struct_region {
+    struct Foo<'a> {
+        x: &'a i32,
+    }
+    trait Trait<'a, 'b> {
+        type Out;
+    }
+    impl<'a, 'b> Trait<'a, 'b> for usize {
+        type Out = &'a Foo<'b>; //~ ERROR reference has a longer lifetime
+    }
+}
+
+
+fn main() { }
diff --git a/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region.stderr b/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region.stderr
new file mode 100644
index 0000000..9a3ba2d
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region.stderr
@@ -0,0 +1,20 @@
+error[E0491]: in type `&'a variant_struct_region::Foo<'b>`, reference has a longer lifetime than the data it references
+  --> $DIR/regions-outlives-nominal-type-region.rs:17:9
+   |
+LL |         type Out = &'a Foo<'b>;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the pointer is valid for the lifetime 'a as defined on the impl at 16:10
+  --> $DIR/regions-outlives-nominal-type-region.rs:16:10
+   |
+LL |     impl<'a, 'b> Trait<'a, 'b> for usize {
+   |          ^^
+note: but the referenced data is only valid for the lifetime 'b as defined on the impl at 16:14
+  --> $DIR/regions-outlives-nominal-type-region.rs:16:14
+   |
+LL |     impl<'a, 'b> Trait<'a, 'b> for usize {
+   |              ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0491`.
diff --git a/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type-rev.rs b/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type-rev.rs
new file mode 100644
index 0000000..083ba89
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type-rev.rs
@@ -0,0 +1,22 @@
+// Test that a nominal type (like `Foo<'a>`) outlives `'b` if its
+// arguments (like `'a`) outlive `'b`.
+//
+// Rule OutlivesNominalType from RFC 1214.
+
+
+#![allow(dead_code)]
+
+mod variant_struct_type {
+    struct Foo<T> {
+        x: fn(T)
+    }
+    trait Trait<'a, 'b> {
+        type Out;
+    }
+    impl<'a, 'b> Trait<'a, 'b> for usize {
+        type Out = &'a Foo<&'b i32>; //~ ERROR reference has a longer lifetime
+    }
+}
+
+
+fn main() { }
diff --git a/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type-rev.stderr b/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type-rev.stderr
new file mode 100644
index 0000000..5389bee
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type-rev.stderr
@@ -0,0 +1,20 @@
+error[E0491]: in type `&'a variant_struct_type::Foo<&'b i32>`, reference has a longer lifetime than the data it references
+  --> $DIR/regions-outlives-nominal-type-type-rev.rs:17:9
+   |
+LL |         type Out = &'a Foo<&'b i32>;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the pointer is valid for the lifetime 'a as defined on the impl at 16:10
+  --> $DIR/regions-outlives-nominal-type-type-rev.rs:16:10
+   |
+LL |     impl<'a, 'b> Trait<'a, 'b> for usize {
+   |          ^^
+note: but the referenced data is only valid for the lifetime 'b as defined on the impl at 16:14
+  --> $DIR/regions-outlives-nominal-type-type-rev.rs:16:14
+   |
+LL |     impl<'a, 'b> Trait<'a, 'b> for usize {
+   |              ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0491`.
diff --git a/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type.rs b/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type.rs
new file mode 100644
index 0000000..f3e4e39
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type.rs
@@ -0,0 +1,22 @@
+// Test that a nominal type (like `Foo<'a>`) outlives `'b` if its
+// arguments (like `'a`) outlive `'b`.
+//
+// Rule OutlivesNominalType from RFC 1214.
+
+
+#![allow(dead_code)]
+
+mod variant_struct_type {
+    struct Foo<T> {
+        x: T
+    }
+    trait Trait<'a, 'b> {
+        type Out;
+    }
+    impl<'a, 'b> Trait<'a, 'b> for usize {
+        type Out = &'a Foo<&'b i32>; //~ ERROR reference has a longer lifetime
+    }
+}
+
+
+fn main() { }
diff --git a/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type.stderr b/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type.stderr
new file mode 100644
index 0000000..2f3ef48
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type.stderr
@@ -0,0 +1,20 @@
+error[E0491]: in type `&'a variant_struct_type::Foo<&'b i32>`, reference has a longer lifetime than the data it references
+  --> $DIR/regions-outlives-nominal-type-type.rs:17:9
+   |
+LL |         type Out = &'a Foo<&'b i32>;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the pointer is valid for the lifetime 'a as defined on the impl at 16:10
+  --> $DIR/regions-outlives-nominal-type-type.rs:16:10
+   |
+LL |     impl<'a, 'b> Trait<'a, 'b> for usize {
+   |          ^^
+note: but the referenced data is only valid for the lifetime 'b as defined on the impl at 16:14
+  --> $DIR/regions-outlives-nominal-type-type.rs:16:14
+   |
+LL |     impl<'a, 'b> Trait<'a, 'b> for usize {
+   |              ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0491`.
diff --git a/src/test/ui/rfc-2093-infer-outlives/regions-struct-not-wf.rs b/src/test/ui/rfc-2093-infer-outlives/regions-struct-not-wf.rs
new file mode 100644
index 0000000..552c6cf
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/regions-struct-not-wf.rs
@@ -0,0 +1,28 @@
+// Various examples of structs whose fields are not well-formed.
+
+#![allow(dead_code)]
+
+trait Trait<'a, T> {
+    type Out;
+}
+trait Trait1<'a, 'b, T> {
+    type Out;
+}
+
+impl<'a, T> Trait<'a, T> for usize {
+    type Out = &'a T; //~ ERROR `T` may not live long enough
+}
+
+struct RefOk<'a, T:'a> {
+    field: &'a T
+}
+
+impl<'a, T> Trait<'a, T> for u32 {
+    type Out = RefOk<'a, T>; //~ ERROR `T` may not live long enough
+}
+
+impl<'a, 'b, T> Trait1<'a, 'b, T> for u32 {
+    type Out = &'a &'b T; //~ ERROR reference has a longer lifetime than the data
+}
+
+fn main() { }
diff --git a/src/test/ui/rfc-2093-infer-outlives/regions-struct-not-wf.stderr b/src/test/ui/rfc-2093-infer-outlives/regions-struct-not-wf.stderr
new file mode 100644
index 0000000..8130f5d
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/regions-struct-not-wf.stderr
@@ -0,0 +1,49 @@
+error[E0309]: the parameter type `T` may not live long enough
+  --> $DIR/regions-struct-not-wf.rs:13:5
+   |
+LL | impl<'a, T> Trait<'a, T> for usize {
+   |          - help: consider adding an explicit lifetime bound `T: 'a`...
+LL |     type Out = &'a T;
+   |     ^^^^^^^^^^^^^^^^^
+   |
+note: ...so that the reference type `&'a T` does not outlive the data it points at
+  --> $DIR/regions-struct-not-wf.rs:13:5
+   |
+LL |     type Out = &'a T;
+   |     ^^^^^^^^^^^^^^^^^
+
+error[E0309]: the parameter type `T` may not live long enough
+  --> $DIR/regions-struct-not-wf.rs:21:5
+   |
+LL | impl<'a, T> Trait<'a, T> for u32 {
+   |          - help: consider adding an explicit lifetime bound `T: 'a`...
+LL |     type Out = RefOk<'a, T>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: ...so that the type `T` will meet its required lifetime bounds
+  --> $DIR/regions-struct-not-wf.rs:21:5
+   |
+LL |     type Out = RefOk<'a, T>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0491]: in type `&'a &'b T`, reference has a longer lifetime than the data it references
+  --> $DIR/regions-struct-not-wf.rs:25:5
+   |
+LL |     type Out = &'a &'b T;
+   |     ^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the pointer is valid for the lifetime 'a as defined on the impl at 24:6
+  --> $DIR/regions-struct-not-wf.rs:24:6
+   |
+LL | impl<'a, 'b, T> Trait1<'a, 'b, T> for u32 {
+   |      ^^
+note: but the referenced data is only valid for the lifetime 'b as defined on the impl at 24:10
+  --> $DIR/regions-struct-not-wf.rs:24:10
+   |
+LL | impl<'a, 'b, T> Trait1<'a, 'b, T> for u32 {
+   |          ^^
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0309, E0491.
+For more information about an error, try `rustc --explain E0309`.
diff --git a/src/test/ui/rfc-2093-infer-outlives/self-dyn.rs b/src/test/ui/rfc-2093-infer-outlives/self-dyn.rs
new file mode 100644
index 0000000..aa1be14
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/self-dyn.rs
@@ -0,0 +1,14 @@
+#![feature(dyn_trait)]
+#![feature(rustc_attrs)]
+
+trait Trait<'x, 's, T> where T: 'x,
+      's: {
+}
+
+#[rustc_outlives]
+struct Foo<'a, 'b, A> //~ ERROR rustc_outlives
+{
+    foo: Box<dyn Trait<'a, 'b, A>>
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc-2093-infer-outlives/self-dyn.stderr b/src/test/ui/rfc-2093-infer-outlives/self-dyn.stderr
new file mode 100644
index 0000000..0be14a6
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/self-dyn.stderr
@@ -0,0 +1,13 @@
+error: rustc_outlives
+  --> $DIR/self-dyn.rs:9:1
+   |
+LL | / struct Foo<'a, 'b, A>
+LL | | {
+LL | |     foo: Box<dyn Trait<'a, 'b, A>>
+LL | | }
+   | |_^
+   |
+   = note: A : 'a
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc-2093-infer-outlives/self-structs.rs b/src/test/ui/rfc-2093-infer-outlives/self-structs.rs
new file mode 100644
index 0000000..d2550a9
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/self-structs.rs
@@ -0,0 +1,13 @@
+#![feature(rustc_attrs)]
+
+#[rustc_outlives]
+struct Foo<'a, 'b, T> { //~ ERROR rustc_outlives
+    field1: Bar<'a, 'b, T>
+}
+
+trait Bar<'x, 's, U>
+    where U: 'x,
+    Self:'s
+{}
+
+fn main() {}
diff --git a/src/test/ui/rfc-2093-infer-outlives/self-structs.stderr b/src/test/ui/rfc-2093-infer-outlives/self-structs.stderr
new file mode 100644
index 0000000..9ae05da
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/self-structs.stderr
@@ -0,0 +1,12 @@
+error: rustc_outlives
+  --> $DIR/self-structs.rs:4:1
+   |
+LL | / struct Foo<'a, 'b, T> {
+LL | |     field1: Bar<'a, 'b, T>
+LL | | }
+   | |_^
+   |
+   = note: T : 'a
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc-2126-crate-paths/crate-path-non-absolute.rs b/src/test/ui/rfc-2126-crate-paths/crate-path-non-absolute.rs
new file mode 100644
index 0000000..8f73d01
--- /dev/null
+++ b/src/test/ui/rfc-2126-crate-paths/crate-path-non-absolute.rs
@@ -0,0 +1,13 @@
+#![feature(crate_in_paths)]
+
+struct S;
+
+pub mod m {
+    fn f() {
+        let s = ::m::crate::S; //~ ERROR failed to resolve
+        let s1 = ::crate::S; //~ ERROR failed to resolve
+        let s2 = crate::S; // no error
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc-2126-crate-paths/crate-path-non-absolute.stderr b/src/test/ui/rfc-2126-crate-paths/crate-path-non-absolute.stderr
new file mode 100644
index 0000000..e4c4790
--- /dev/null
+++ b/src/test/ui/rfc-2126-crate-paths/crate-path-non-absolute.stderr
@@ -0,0 +1,15 @@
+error[E0433]: failed to resolve: `crate` in paths can only be used in start position
+  --> $DIR/crate-path-non-absolute.rs:7:22
+   |
+LL |         let s = ::m::crate::S;
+   |                      ^^^^^ `crate` in paths can only be used in start position
+
+error[E0433]: failed to resolve: global paths cannot start with `crate`
+  --> $DIR/crate-path-non-absolute.rs:8:20
+   |
+LL |         let s1 = ::crate::S;
+   |                    ^^^^^ global paths cannot start with `crate`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/rfc-2126-crate-paths/keyword-crate-as-identifier.rs b/src/test/ui/rfc-2126-crate-paths/keyword-crate-as-identifier.rs
new file mode 100644
index 0000000..ab87ecb
--- /dev/null
+++ b/src/test/ui/rfc-2126-crate-paths/keyword-crate-as-identifier.rs
@@ -0,0 +1,6 @@
+#![feature(crate_in_paths)]
+
+fn main() {
+    let crate = 0;
+    //~^ ERROR expected unit struct/variant or constant, found module `crate`
+}
diff --git a/src/test/ui/rfc-2126-crate-paths/keyword-crate-as-identifier.stderr b/src/test/ui/rfc-2126-crate-paths/keyword-crate-as-identifier.stderr
new file mode 100644
index 0000000..e07b5d8
--- /dev/null
+++ b/src/test/ui/rfc-2126-crate-paths/keyword-crate-as-identifier.stderr
@@ -0,0 +1,9 @@
+error[E0532]: expected unit struct/variant or constant, found module `crate`
+  --> $DIR/keyword-crate-as-identifier.rs:4:9
+   |
+LL |     let crate = 0;
+   |         ^^^^^ not a unit struct/variant or constant
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0532`.
diff --git a/src/test/ui/rfc-2126-extern-absolute-paths/auxiliary/xcrate.rs b/src/test/ui/rfc-2126-extern-absolute-paths/auxiliary/xcrate.rs
new file mode 100644
index 0000000..c4d4447
--- /dev/null
+++ b/src/test/ui/rfc-2126-extern-absolute-paths/auxiliary/xcrate.rs
@@ -0,0 +1,5 @@
+#[derive(Debug)]
+pub struct S;
+
+#[derive(Debug)]
+pub struct Z;
diff --git a/src/test/ui/rfc-2126-extern-absolute-paths/meta.rs b/src/test/ui/rfc-2126-extern-absolute-paths/meta.rs
new file mode 100644
index 0000000..b3b9aeb
--- /dev/null
+++ b/src/test/ui/rfc-2126-extern-absolute-paths/meta.rs
@@ -0,0 +1,7 @@
+// edition:2018
+
+// Tests that `meta` is whitelisted, even if the crate doesn't exist
+// yet (i.e., it causes a different error than `not-whitelisted.rs`).
+use meta; //~ ERROR can't find crate for `meta`
+
+fn main() {}
diff --git a/src/test/ui/rfc-2126-extern-absolute-paths/meta.stderr b/src/test/ui/rfc-2126-extern-absolute-paths/meta.stderr
new file mode 100644
index 0000000..eb4b9de
--- /dev/null
+++ b/src/test/ui/rfc-2126-extern-absolute-paths/meta.stderr
@@ -0,0 +1,9 @@
+error[E0463]: can't find crate for `meta`
+  --> $DIR/meta.rs:5:5
+   |
+LL | use meta;
+   |     ^^^^ can't find crate
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0463`.
diff --git a/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-1.rs b/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-1.rs
new file mode 100644
index 0000000..9c0e0be
--- /dev/null
+++ b/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-1.rs
@@ -0,0 +1,5 @@
+// edition:2018
+
+use xcrate::S; //~ ERROR unresolved import `xcrate`
+
+fn main() {}
diff --git a/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-1.stderr b/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-1.stderr
new file mode 100644
index 0000000..64b920e
--- /dev/null
+++ b/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-1.stderr
@@ -0,0 +1,9 @@
+error[E0432]: unresolved import `xcrate`
+  --> $DIR/non-existent-1.rs:3:5
+   |
+LL | use xcrate::S;
+   |     ^^^^^^ use of undeclared type or module `xcrate`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-2.rs b/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-2.rs
new file mode 100644
index 0000000..4f53108
--- /dev/null
+++ b/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-2.rs
@@ -0,0 +1,6 @@
+// edition:2018
+
+fn main() {
+    let s = ::xcrate::S;
+    //~^ ERROR failed to resolve: could not find `xcrate` in `{{root}}`
+}
diff --git a/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-2.stderr b/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-2.stderr
new file mode 100644
index 0000000..7395d01
--- /dev/null
+++ b/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-2.stderr
@@ -0,0 +1,9 @@
+error[E0433]: failed to resolve: could not find `xcrate` in `{{root}}`
+  --> $DIR/non-existent-2.rs:4:15
+   |
+LL |     let s = ::xcrate::S;
+   |               ^^^^^^ could not find `xcrate` in `{{root}}`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-3.rs b/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-3.rs
new file mode 100644
index 0000000..486159c
--- /dev/null
+++ b/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-3.rs
@@ -0,0 +1,5 @@
+// edition:2018
+
+use ycrate; //~ ERROR unresolved import `ycrate`
+
+fn main() {}
diff --git a/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-3.stderr b/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-3.stderr
new file mode 100644
index 0000000..bfce180
--- /dev/null
+++ b/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-3.stderr
@@ -0,0 +1,9 @@
+error[E0432]: unresolved import `ycrate`
+  --> $DIR/non-existent-3.rs:3:5
+   |
+LL | use ycrate;
+   |     ^^^^^^ no `ycrate` external crate
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.rs b/src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.rs
new file mode 100644
index 0000000..dd21de7
--- /dev/null
+++ b/src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.rs
@@ -0,0 +1,9 @@
+// edition:2018
+
+// Tests that arbitrary crates (other than `core`, `std` and `meta`)
+// aren't allowed without `--extern`, even if they're in the sysroot.
+use alloc; //~ ERROR unresolved import `alloc`
+use test; //~ ERROR cannot import a built-in macro
+use proc_macro; // OK, imports the built-in `proc_macro` attribute, but not the `proc_macro` crate.
+
+fn main() {}
diff --git a/src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.stderr b/src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.stderr
new file mode 100644
index 0000000..4e3fff9
--- /dev/null
+++ b/src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.stderr
@@ -0,0 +1,15 @@
+error: cannot import a built-in macro
+  --> $DIR/not-whitelisted.rs:6:5
+   |
+LL | use test;
+   |     ^^^^
+
+error[E0432]: unresolved import `alloc`
+  --> $DIR/not-whitelisted.rs:5:5
+   |
+LL | use alloc;
+   |     ^^^^^ no `alloc` external crate
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/rfc-2126-extern-absolute-paths/single-segment.rs b/src/test/ui/rfc-2126-extern-absolute-paths/single-segment.rs
new file mode 100644
index 0000000..c16f464
--- /dev/null
+++ b/src/test/ui/rfc-2126-extern-absolute-paths/single-segment.rs
@@ -0,0 +1,11 @@
+// aux-build:xcrate.rs
+// compile-flags:--extern xcrate
+// edition:2018
+
+use crate; //~ ERROR crate root imports need to be explicitly named: `use crate as name;`
+use *; //~ ERROR cannot glob-import all possible crates
+
+fn main() {
+    let s = ::xcrate; //~ ERROR expected value, found module `xcrate`
+                      //~^ NOTE not a value
+}
diff --git a/src/test/ui/rfc-2126-extern-absolute-paths/single-segment.stderr b/src/test/ui/rfc-2126-extern-absolute-paths/single-segment.stderr
new file mode 100644
index 0000000..396a798
--- /dev/null
+++ b/src/test/ui/rfc-2126-extern-absolute-paths/single-segment.stderr
@@ -0,0 +1,21 @@
+error: crate root imports need to be explicitly named: `use crate as name;`
+  --> $DIR/single-segment.rs:5:5
+   |
+LL | use crate;
+   |     ^^^^^
+
+error: cannot glob-import all possible crates
+  --> $DIR/single-segment.rs:6:5
+   |
+LL | use *;
+   |     ^
+
+error[E0423]: expected value, found module `xcrate`
+  --> $DIR/single-segment.rs:9:13
+   |
+LL |     let s = ::xcrate;
+   |             ^^^^^^^^ not a value
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0423`.
diff --git a/src/test/ui/rfc-2166-underscore-imports/auxiliary/duplicate.rs b/src/test/ui/rfc-2166-underscore-imports/auxiliary/duplicate.rs
new file mode 100644
index 0000000..92d741b
--- /dev/null
+++ b/src/test/ui/rfc-2166-underscore-imports/auxiliary/duplicate.rs
@@ -0,0 +1,14 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::*;
+
+#[proc_macro_attribute]
+pub fn duplicate(_: TokenStream, input: TokenStream) -> TokenStream {
+    let clone = input.clone();
+    input.into_iter().chain(clone.into_iter()).collect()
+}
diff --git a/src/test/ui/rfc-2166-underscore-imports/auxiliary/underscore-imports.rs b/src/test/ui/rfc-2166-underscore-imports/auxiliary/underscore-imports.rs
new file mode 100644
index 0000000..c335336
--- /dev/null
+++ b/src/test/ui/rfc-2166-underscore-imports/auxiliary/underscore-imports.rs
@@ -0,0 +1,20 @@
+#[macro_export]
+macro_rules! do_nothing {
+    () => ()
+}
+
+mod m1 {
+    pub trait InScope1 {
+        fn in_scope1(&self) {}
+    }
+    impl InScope1 for () {}
+}
+mod m2 {
+    pub trait InScope2 {
+        fn in_scope2(&self) {}
+    }
+    impl InScope2 for () {}
+}
+
+pub use m1::InScope1 as _;
+pub use m2::InScope2 as _;
diff --git a/src/test/ui/rfc-2166-underscore-imports/basic.rs b/src/test/ui/rfc-2166-underscore-imports/basic.rs
new file mode 100644
index 0000000..968da9c
--- /dev/null
+++ b/src/test/ui/rfc-2166-underscore-imports/basic.rs
@@ -0,0 +1,62 @@
+// compile-pass
+// aux-build:underscore-imports.rs
+
+#![warn(unused_imports, unused_extern_crates)]
+
+#[macro_use]
+extern crate underscore_imports as _;
+
+do_nothing!(); // OK
+
+struct S;
+
+mod m {
+    pub trait Tr1 {
+        fn tr1_is_in_scope(&self) {}
+    }
+    pub trait Tr2 {
+        fn tr2_is_in_scope(&self) {}
+    }
+
+    impl Tr1 for ::S {}
+    impl Tr2 for ::S {}
+}
+
+mod unused {
+    use m::Tr1 as _; //~ WARN unused import
+    use S as _; //~ WARN unused import
+    extern crate core as _; // OK
+}
+
+mod outer {
+    mod middle {
+        pub use m::Tr1 as _;
+        pub use m::Tr2 as _; // OK, no name conflict
+        struct Tr1; // OK, no name conflict
+        fn check() {
+            // Both traits are in scope
+            ::S.tr1_is_in_scope();
+            ::S.tr2_is_in_scope();
+        }
+
+        mod inner {
+            // `_` imports are fetched by glob imports
+            use super::*;
+            fn check() {
+                // Both traits are in scope
+                ::S.tr1_is_in_scope();
+                ::S.tr2_is_in_scope();
+            }
+        }
+    }
+
+    // `_` imports are fetched by glob imports
+    use self::middle::*;
+    fn check() {
+        // Both traits are in scope
+        ::S.tr1_is_in_scope();
+        ::S.tr2_is_in_scope();
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc-2166-underscore-imports/basic.stderr b/src/test/ui/rfc-2166-underscore-imports/basic.stderr
new file mode 100644
index 0000000..9ca60e8
--- /dev/null
+++ b/src/test/ui/rfc-2166-underscore-imports/basic.stderr
@@ -0,0 +1,18 @@
+warning: unused import: `m::Tr1 as _`
+  --> $DIR/basic.rs:26:9
+   |
+LL |     use m::Tr1 as _;
+   |         ^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/basic.rs:4:9
+   |
+LL | #![warn(unused_imports, unused_extern_crates)]
+   |         ^^^^^^^^^^^^^^
+
+warning: unused import: `S as _`
+  --> $DIR/basic.rs:27:9
+   |
+LL |     use S as _;
+   |         ^^^^^^
+
diff --git a/src/test/ui/rfc-2166-underscore-imports/duplicate.rs b/src/test/ui/rfc-2166-underscore-imports/duplicate.rs
new file mode 100644
index 0000000..95f7cae
--- /dev/null
+++ b/src/test/ui/rfc-2166-underscore-imports/duplicate.rs
@@ -0,0 +1,15 @@
+// compile-pass
+// aux-build:duplicate.rs
+
+extern crate duplicate;
+
+#[duplicate::duplicate]
+use main as _; // OK
+
+macro_rules! duplicate {
+    ($item: item) => { $item $item }
+}
+
+duplicate!(use std as _;); // OK
+
+fn main() {}
diff --git a/src/test/ui/rfc-2166-underscore-imports/intercrate.rs b/src/test/ui/rfc-2166-underscore-imports/intercrate.rs
new file mode 100644
index 0000000..8b5bb8b
--- /dev/null
+++ b/src/test/ui/rfc-2166-underscore-imports/intercrate.rs
@@ -0,0 +1,11 @@
+// compile-pass
+// aux-build:underscore-imports.rs
+
+extern crate underscore_imports;
+
+use underscore_imports::*;
+
+fn main() {
+    ().in_scope1();
+    ().in_scope2();
+}
diff --git a/src/test/ui/rfc-2166-underscore-imports/unused-2018.rs b/src/test/ui/rfc-2166-underscore-imports/unused-2018.rs
new file mode 100644
index 0000000..d06a26a
--- /dev/null
+++ b/src/test/ui/rfc-2166-underscore-imports/unused-2018.rs
@@ -0,0 +1,17 @@
+// edition:2018
+
+#![deny(unused_imports)]
+
+mod multi_segment {
+    use core::any; //~ ERROR unused import: `core::any`
+}
+
+mod single_segment {
+    use core; //~ ERROR unused import: `core`
+}
+
+mod single_segment_underscore {
+    use core as _; // OK
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc-2166-underscore-imports/unused-2018.stderr b/src/test/ui/rfc-2166-underscore-imports/unused-2018.stderr
new file mode 100644
index 0000000..861b3f1
--- /dev/null
+++ b/src/test/ui/rfc-2166-underscore-imports/unused-2018.stderr
@@ -0,0 +1,20 @@
+error: unused import: `core::any`
+  --> $DIR/unused-2018.rs:6:9
+   |
+LL |     use core::any;
+   |         ^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/unused-2018.rs:3:9
+   |
+LL | #![deny(unused_imports)]
+   |         ^^^^^^^^^^^^^^
+
+error: unused import: `core`
+  --> $DIR/unused-2018.rs:10:9
+   |
+LL |     use core;
+   |         ^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/rfc-2306/convert-id-const-with-gate.rs b/src/test/ui/rfc-2306/convert-id-const-with-gate.rs
new file mode 100644
index 0000000..a82feb9
--- /dev/null
+++ b/src/test/ui/rfc-2306/convert-id-const-with-gate.rs
@@ -0,0 +1,7 @@
+// This test should pass since 'identity' is const fn.
+
+// compile-pass
+
+fn main() {
+    const _FOO: u8 = ::std::convert::identity(42u8);
+}
diff --git a/src/test/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.rs b/src/test/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.rs
new file mode 100644
index 0000000..f1b73ee
--- /dev/null
+++ b/src/test/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.rs
@@ -0,0 +1,124 @@
+// run-pass
+// ignore-cloudabi no processes
+// ignore-emscripten no processes
+
+// Tests ensuring that `dbg!(expr)` has the expected run-time behavior.
+// as well as some compile time properties we expect.
+
+#[derive(Copy, Clone, Debug)]
+struct Unit;
+
+#[derive(Copy, Clone, Debug, PartialEq)]
+struct Point<T> {
+    x: T,
+    y: T,
+}
+
+#[derive(Debug, PartialEq)]
+struct NoCopy(usize);
+
+fn test() {
+    let a: Unit = dbg!(Unit);
+    let _: Unit = dbg!(a);
+    // We can move `a` because it's Copy.
+    drop(a);
+
+    // `Point<T>` will be faithfully formatted according to `{:#?}`.
+    let a = Point { x: 42, y: 24 };
+    let b: Point<u8> = dbg!(Point { x: 42, y: 24 }); // test stringify!(..)
+    let c: Point<u8> = dbg!(b);
+    // Identity conversion:
+    assert_eq!(a, b);
+    assert_eq!(a, c);
+    // We can move `b` because it's Copy.
+    drop(b);
+
+    // Without parameters works as expected.
+    let _: () = dbg!();
+
+    // Test that we can borrow and that successive applications is still identity.
+    let a = NoCopy(1337);
+    let b: &NoCopy = dbg!(dbg!(&a));
+    assert_eq!(&a, b);
+
+    // Test involving lifetimes of temporaries:
+    fn f<'a>(x: &'a u8) -> &'a u8 { x }
+    let a: &u8 = dbg!(f(&42));
+    assert_eq!(a, &42);
+
+    // Test side effects:
+    let mut foo = 41;
+    assert_eq!(7331, dbg!({
+        foo += 1;
+        eprintln!("before");
+        7331
+    }));
+    assert_eq!(foo, 42);
+}
+
+fn validate_stderr(stderr: Vec<String>) {
+    assert_eq!(stderr, &[
+        ":21] Unit = Unit",
+
+        ":22] a = Unit",
+
+        ":28] Point{x: 42, y: 24,} = Point {",
+        "    x: 42,",
+        "    y: 24,",
+        "}",
+
+        ":29] b = Point {",
+        "    x: 42,",
+        "    y: 24,",
+        "}",
+
+        ":37]",
+
+        ":41] &a = NoCopy(",
+        "    1337,",
+        ")",
+
+        ":41] dbg!(& a) = NoCopy(",
+        "    1337,",
+        ")",
+        ":46] f(&42) = 42",
+
+        "before",
+        ":51] { foo += 1; eprintln!(\"before\"); 7331 } = 7331",
+    ]);
+}
+
+fn main() {
+    // The following is a hack to deal with compiletest's inability
+    // to check the output (to stdout) of run-pass tests.
+    use std::env;
+    use std::process::Command;
+
+    let mut args = env::args();
+    let prog = args.next().unwrap();
+    let child = args.next();
+    if let Some("child") = child.as_ref().map(|s| &**s) {
+        // Only run the test if we've been spawned as 'child'
+        test()
+    } else {
+        // This essentially spawns as 'child' to run the tests
+        // and then it collects output of stderr and checks the output
+        // against what we expect.
+        let out = Command::new(&prog).arg("child").output().unwrap();
+        assert!(out.status.success());
+        assert!(out.stdout.is_empty());
+
+        let stderr = String::from_utf8(out.stderr).unwrap();
+        let stderr = stderr.lines().map(|mut s| {
+            if s.starts_with("[") {
+                // Strip `[` and file path:
+                s = s.trim_start_matches("[");
+                assert!(s.starts_with(file!()));
+                s = s.trim_start_matches(file!());
+            }
+            s.to_owned()
+        }).collect();
+
+        validate_stderr(stderr);
+    }
+}
diff --git a/src/test/ui/rfc-2361-dbg-macro/dbg-macro-move-semantics.nll.stderr b/src/test/ui/rfc-2361-dbg-macro/dbg-macro-move-semantics.nll.stderr
new file mode 100644
index 0000000..5f0b3a1
--- /dev/null
+++ b/src/test/ui/rfc-2361-dbg-macro/dbg-macro-move-semantics.nll.stderr
@@ -0,0 +1,15 @@
+error[E0382]: use of moved value: `a`
+  --> $DIR/dbg-macro-move-semantics.rs:9:18
+   |
+LL |     let a = NoCopy(0);
+   |         - move occurs because `a` has type `NoCopy`, which does not implement the `Copy` trait
+LL |     let _ = dbg!(a);
+   |             ------- value moved here
+LL |     let _ = dbg!(a);
+   |                  ^ value used here after move
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/rfc-2361-dbg-macro/dbg-macro-move-semantics.rs b/src/test/ui/rfc-2361-dbg-macro/dbg-macro-move-semantics.rs
new file mode 100644
index 0000000..e6ddb3d
--- /dev/null
+++ b/src/test/ui/rfc-2361-dbg-macro/dbg-macro-move-semantics.rs
@@ -0,0 +1,11 @@
+// Test ensuring that `dbg!(expr)` will take ownership of the argument.
+
+#[derive(Debug)]
+struct NoCopy(usize);
+
+fn main() {
+    let a = NoCopy(0);
+    let _ = dbg!(a);
+    let _ = dbg!(a); //~ ERROR use of moved value
+    //~^ ERROR use of moved value
+}
diff --git a/src/test/ui/rfc-2361-dbg-macro/dbg-macro-move-semantics.stderr b/src/test/ui/rfc-2361-dbg-macro/dbg-macro-move-semantics.stderr
new file mode 100644
index 0000000..cfc318c
--- /dev/null
+++ b/src/test/ui/rfc-2361-dbg-macro/dbg-macro-move-semantics.stderr
@@ -0,0 +1,25 @@
+error[E0382]: use of moved value: `a`
+  --> $DIR/dbg-macro-move-semantics.rs:9:18
+   |
+LL |     let _ = dbg!(a);
+   |             ------- value moved here
+LL |     let _ = dbg!(a);
+   |                  ^ value used here after move
+   |
+   = note: move occurs because `a` has type `NoCopy`, which does not implement the `Copy` trait
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/dbg-macro-move-semantics.rs:9:13
+   |
+LL |     let _ = dbg!(a);
+   |             ------- value moved here
+LL |     let _ = dbg!(a);
+   |             ^^^^^^^ value used here after move
+   |
+   = note: move occurs because `a` has type `NoCopy`, which does not implement the `Copy` trait
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/rfc-2361-dbg-macro/dbg-macro-requires-debug.rs b/src/test/ui/rfc-2361-dbg-macro/dbg-macro-requires-debug.rs
new file mode 100644
index 0000000..bdde484
--- /dev/null
+++ b/src/test/ui/rfc-2361-dbg-macro/dbg-macro-requires-debug.rs
@@ -0,0 +1,7 @@
+// Test ensuring that `dbg!(expr)` requires the passed type to implement `Debug`.
+
+struct NotDebug;
+
+fn main() {
+    let _: NotDebug = dbg!(NotDebug); //~ ERROR `NotDebug` doesn't implement `std::fmt::Debug`
+}
diff --git a/src/test/ui/rfc-2361-dbg-macro/dbg-macro-requires-debug.stderr b/src/test/ui/rfc-2361-dbg-macro/dbg-macro-requires-debug.stderr
new file mode 100644
index 0000000..ecab673
--- /dev/null
+++ b/src/test/ui/rfc-2361-dbg-macro/dbg-macro-requires-debug.stderr
@@ -0,0 +1,15 @@
+error[E0277]: `NotDebug` doesn't implement `std::fmt::Debug`
+  --> $DIR/dbg-macro-requires-debug.rs:6:23
+   |
+LL |     let _: NotDebug = dbg!(NotDebug);
+   |                       ^^^^^^^^^^^^^^ `NotDebug` cannot be formatted using `{:?}`
+   |
+   = help: the trait `std::fmt::Debug` is not implemented for `NotDebug`
+   = note: add `#[derive(Debug)]` or manually implement `std::fmt::Debug`
+   = note: required because of the requirements on the impl of `std::fmt::Debug` for `&NotDebug`
+   = note: required by `std::fmt::Debug::fmt`
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2015.rs b/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2015.rs
new file mode 100644
index 0000000..d79798d
--- /dev/null
+++ b/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2015.rs
@@ -0,0 +1,38 @@
+// edition:2015
+
+// Enabling `ireffutable_let_patterns` isn't necessary for what this tests, but it makes coming up
+// with examples easier.
+
+#[allow(irrefutable_let_patterns)]
+fn main() {
+    use std::ops::Range;
+
+    if let Range { start: _, end: _ } = true..true && false { }
+    //~^ ERROR ambiguous use of `&&`
+
+    if let Range { start: _, end: _ } = true..true || false { }
+    //~^ ERROR ambiguous use of `||`
+
+    while let Range { start: _, end: _ } = true..true && false { }
+    //~^ ERROR ambiguous use of `&&`
+
+    while let Range { start: _, end: _ } = true..true || false { }
+    //~^ ERROR ambiguous use of `||`
+
+    if let true = false && false { }
+    //~^ ERROR ambiguous use of `&&`
+
+    while let true = (1 == 2) && false { }
+    //~^ ERROR ambiguous use of `&&`
+
+    // The following cases are not an error as parenthesis are used to
+    // clarify intent:
+
+    if let Range { start: _, end: _ } = true..(true || false) { }
+
+    if let Range { start: _, end: _ } = true..(true && false) { }
+
+    while let Range { start: _, end: _ } = true..(true || false) { }
+
+    while let Range { start: _, end: _ } = true..(true && false) { }
+}
diff --git a/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2015.stderr b/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2015.stderr
new file mode 100644
index 0000000..2cd59fe
--- /dev/null
+++ b/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2015.stderr
@@ -0,0 +1,56 @@
+error: ambiguous use of `&&`
+  --> $DIR/syntax-ambiguity-2015.rs:10:47
+   |
+LL |     if let Range { start: _, end: _ } = true..true && false { }
+   |                                               ^^^^^^^^^^^^^ help: consider adding parentheses: `(true && false)`
+   |
+   = note: this will be a error until the `let_chains` feature is stabilized
+   = note: see rust-lang/rust#53668 for more information
+
+error: ambiguous use of `||`
+  --> $DIR/syntax-ambiguity-2015.rs:13:47
+   |
+LL |     if let Range { start: _, end: _ } = true..true || false { }
+   |                                               ^^^^^^^^^^^^^ help: consider adding parentheses: `(true || false)`
+   |
+   = note: this will be a error until the `let_chains` feature is stabilized
+   = note: see rust-lang/rust#53668 for more information
+
+error: ambiguous use of `&&`
+  --> $DIR/syntax-ambiguity-2015.rs:16:50
+   |
+LL |     while let Range { start: _, end: _ } = true..true && false { }
+   |                                                  ^^^^^^^^^^^^^ help: consider adding parentheses: `(true && false)`
+   |
+   = note: this will be a error until the `let_chains` feature is stabilized
+   = note: see rust-lang/rust#53668 for more information
+
+error: ambiguous use of `||`
+  --> $DIR/syntax-ambiguity-2015.rs:19:50
+   |
+LL |     while let Range { start: _, end: _ } = true..true || false { }
+   |                                                  ^^^^^^^^^^^^^ help: consider adding parentheses: `(true || false)`
+   |
+   = note: this will be a error until the `let_chains` feature is stabilized
+   = note: see rust-lang/rust#53668 for more information
+
+error: ambiguous use of `&&`
+  --> $DIR/syntax-ambiguity-2015.rs:22:19
+   |
+LL |     if let true = false && false { }
+   |                   ^^^^^^^^^^^^^^ help: consider adding parentheses: `(false && false)`
+   |
+   = note: this will be a error until the `let_chains` feature is stabilized
+   = note: see rust-lang/rust#53668 for more information
+
+error: ambiguous use of `&&`
+  --> $DIR/syntax-ambiguity-2015.rs:25:22
+   |
+LL |     while let true = (1 == 2) && false { }
+   |                      ^^^^^^^^^^^^^^^^^ help: consider adding parentheses: `((1 == 2) && false)`
+   |
+   = note: this will be a error until the `let_chains` feature is stabilized
+   = note: see rust-lang/rust#53668 for more information
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2018.rs b/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2018.rs
new file mode 100644
index 0000000..687bf65
--- /dev/null
+++ b/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2018.rs
@@ -0,0 +1,38 @@
+// edition:2018
+
+// Enabling `ireffutable_let_patterns` isn't necessary for what this tests, but it makes coming up
+// with examples easier.
+
+#[allow(irrefutable_let_patterns)]
+fn main() {
+    use std::ops::Range;
+
+    if let Range { start: _, end: _ } = true..true && false { }
+    //~^ ERROR ambiguous use of `&&`
+
+    if let Range { start: _, end: _ } = true..true || false { }
+    //~^ ERROR ambiguous use of `||`
+
+    while let Range { start: _, end: _ } = true..true && false { }
+    //~^ ERROR ambiguous use of `&&`
+
+    while let Range { start: _, end: _ } = true..true || false { }
+    //~^ ERROR ambiguous use of `||`
+
+    if let true = false && false { }
+    //~^ ERROR ambiguous use of `&&`
+
+    while let true = (1 == 2) && false { }
+    //~^ ERROR ambiguous use of `&&`
+
+    // The following cases are not an error as parenthesis are used to
+    // clarify intent:
+
+    if let Range { start: _, end: _ } = true..(true || false) { }
+
+    if let Range { start: _, end: _ } = true..(true && false) { }
+
+    while let Range { start: _, end: _ } = true..(true || false) { }
+
+    while let Range { start: _, end: _ } = true..(true && false) { }
+}
diff --git a/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2018.stderr b/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2018.stderr
new file mode 100644
index 0000000..cbba2d7
--- /dev/null
+++ b/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2018.stderr
@@ -0,0 +1,56 @@
+error: ambiguous use of `&&`
+  --> $DIR/syntax-ambiguity-2018.rs:10:47
+   |
+LL |     if let Range { start: _, end: _ } = true..true && false { }
+   |                                               ^^^^^^^^^^^^^ help: consider adding parentheses: `(true && false)`
+   |
+   = note: this will be a error until the `let_chains` feature is stabilized
+   = note: see rust-lang/rust#53668 for more information
+
+error: ambiguous use of `||`
+  --> $DIR/syntax-ambiguity-2018.rs:13:47
+   |
+LL |     if let Range { start: _, end: _ } = true..true || false { }
+   |                                               ^^^^^^^^^^^^^ help: consider adding parentheses: `(true || false)`
+   |
+   = note: this will be a error until the `let_chains` feature is stabilized
+   = note: see rust-lang/rust#53668 for more information
+
+error: ambiguous use of `&&`
+  --> $DIR/syntax-ambiguity-2018.rs:16:50
+   |
+LL |     while let Range { start: _, end: _ } = true..true && false { }
+   |                                                  ^^^^^^^^^^^^^ help: consider adding parentheses: `(true && false)`
+   |
+   = note: this will be a error until the `let_chains` feature is stabilized
+   = note: see rust-lang/rust#53668 for more information
+
+error: ambiguous use of `||`
+  --> $DIR/syntax-ambiguity-2018.rs:19:50
+   |
+LL |     while let Range { start: _, end: _ } = true..true || false { }
+   |                                                  ^^^^^^^^^^^^^ help: consider adding parentheses: `(true || false)`
+   |
+   = note: this will be a error until the `let_chains` feature is stabilized
+   = note: see rust-lang/rust#53668 for more information
+
+error: ambiguous use of `&&`
+  --> $DIR/syntax-ambiguity-2018.rs:22:19
+   |
+LL |     if let true = false && false { }
+   |                   ^^^^^^^^^^^^^^ help: consider adding parentheses: `(false && false)`
+   |
+   = note: this will be a error until the `let_chains` feature is stabilized
+   = note: see rust-lang/rust#53668 for more information
+
+error: ambiguous use of `&&`
+  --> $DIR/syntax-ambiguity-2018.rs:25:22
+   |
+LL |     while let true = (1 == 2) && false { }
+   |                      ^^^^^^^^^^^^^^^^^ help: consider adding parentheses: `((1 == 2) && false)`
+   |
+   = note: this will be a error until the `let_chains` feature is stabilized
+   = note: see rust-lang/rust#53668 for more information
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/rfc1445/feature-gate.no_gate.stderr b/src/test/ui/rfc1445/feature-gate.no_gate.stderr
new file mode 100644
index 0000000..370b74b
--- /dev/null
+++ b/src/test/ui/rfc1445/feature-gate.no_gate.stderr
@@ -0,0 +1,11 @@
+error[E0658]: the semantics of constant patterns is not yet settled (see issue #31434)
+  --> $DIR/feature-gate.rs:13:1
+   |
+LL | #[structural_match]
+   | ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(structural_match)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/rfc1445/feature-gate.rs b/src/test/ui/rfc1445/feature-gate.rs
new file mode 100644
index 0000000..550610c
--- /dev/null
+++ b/src/test/ui/rfc1445/feature-gate.rs
@@ -0,0 +1,27 @@
+// Test that structural match is only permitted with a feature gate,
+// and that if a feature gate is supplied, it permits the type to be
+// used in a match.
+
+// revisions: with_gate no_gate
+
+// gate-test-structural_match
+
+#![allow(unused)]
+#![feature(rustc_attrs)]
+#![cfg_attr(with_gate, feature(structural_match))]
+
+#[structural_match] //[no_gate]~ ERROR semantics of constant patterns is not yet settled
+struct Foo {
+    x: u32
+}
+
+const FOO: Foo = Foo { x: 0 };
+
+#[rustc_error]
+fn main() { //[with_gate]~ ERROR compilation successful
+    let y = Foo { x: 1 };
+    match y {
+        FOO => { }
+        _ => { }
+    }
+}
diff --git a/src/test/ui/rfc1445/feature-gate.with_gate.stderr b/src/test/ui/rfc1445/feature-gate.with_gate.stderr
new file mode 100644
index 0000000..ca8dc75
--- /dev/null
+++ b/src/test/ui/rfc1445/feature-gate.with_gate.stderr
@@ -0,0 +1,14 @@
+error: compilation successful
+  --> $DIR/feature-gate.rs:21:1
+   |
+LL | / fn main() {
+LL | |     let y = Foo { x: 1 };
+LL | |     match y {
+LL | |         FOO => { }
+LL | |         _ => { }
+LL | |     }
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc1445/match-forbidden-without-eq.rs b/src/test/ui/rfc1445/match-forbidden-without-eq.rs
new file mode 100644
index 0000000..78d799e
--- /dev/null
+++ b/src/test/ui/rfc1445/match-forbidden-without-eq.rs
@@ -0,0 +1,25 @@
+use std::f32;
+
+#[derive(PartialEq)]
+struct Foo {
+    x: u32
+}
+
+const FOO: Foo = Foo { x: 0 };
+
+fn main() {
+    let y = Foo { x: 1 };
+    match y {
+        FOO => { }
+        //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+        _ => { }
+    }
+
+    let x = 0.0;
+    match x {
+        f32::INFINITY => { }
+        //~^ WARNING floating-point types cannot be used in patterns
+        //~| WARNING will become a hard error in a future release
+        _ => { }
+    }
+}
diff --git a/src/test/ui/rfc1445/match-forbidden-without-eq.stderr b/src/test/ui/rfc1445/match-forbidden-without-eq.stderr
new file mode 100644
index 0000000..ebea2f3
--- /dev/null
+++ b/src/test/ui/rfc1445/match-forbidden-without-eq.stderr
@@ -0,0 +1,18 @@
+error: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/match-forbidden-without-eq.rs:13:9
+   |
+LL |         FOO => { }
+   |         ^^^
+
+warning: floating-point types cannot be used in patterns
+  --> $DIR/match-forbidden-without-eq.rs:20:9
+   |
+LL |         f32::INFINITY => { }
+   |         ^^^^^^^^^^^^^
+   |
+   = note: #[warn(illegal_floating_point_literal_pattern)] on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc1445/match-requires-both-partialeq-and-eq.rs b/src/test/ui/rfc1445/match-requires-both-partialeq-and-eq.rs
new file mode 100644
index 0000000..6b7d946
--- /dev/null
+++ b/src/test/ui/rfc1445/match-requires-both-partialeq-and-eq.rs
@@ -0,0 +1,21 @@
+#[derive(Eq)]
+struct Foo {
+    x: u32
+}
+
+impl PartialEq for Foo {
+    fn eq(&self, _: &Foo) -> bool {
+        false // ha ha sucker!
+    }
+}
+
+const FOO: Foo = Foo { x: 0 };
+
+fn main() {
+    let y = Foo { x: 1 };
+    match y {
+        FOO => { }
+        //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+        _ => { }
+    }
+}
diff --git a/src/test/ui/rfc1445/match-requires-both-partialeq-and-eq.stderr b/src/test/ui/rfc1445/match-requires-both-partialeq-and-eq.stderr
new file mode 100644
index 0000000..4157cf6
--- /dev/null
+++ b/src/test/ui/rfc1445/match-requires-both-partialeq-and-eq.stderr
@@ -0,0 +1,8 @@
+error: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/match-requires-both-partialeq-and-eq.rs:17:9
+   |
+LL |         FOO => { }
+   |         ^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc1445/phantom-data-is-structurally-matchable.rs b/src/test/ui/rfc1445/phantom-data-is-structurally-matchable.rs
new file mode 100644
index 0000000..af025b9
--- /dev/null
+++ b/src/test/ui/rfc1445/phantom-data-is-structurally-matchable.rs
@@ -0,0 +1,53 @@
+// run-pass
+
+// This file checks that `PhantomData` is considered structurally matchable.
+
+use std::marker::PhantomData;
+
+fn main() {
+    let mut count = 0;
+
+    // A type which is not structurally matchable:
+    struct NotSM;
+
+    // And one that is:
+    #[derive(PartialEq, Eq)]
+    struct SM;
+
+    // Check that SM is #[structural_match]:
+    const CSM: SM = SM;
+    match SM {
+        CSM => count += 1,
+    };
+
+    // Check that PhantomData<T> is #[structural_match] even if T is not.
+    const CPD1: PhantomData<NotSM> = PhantomData;
+    match PhantomData {
+        CPD1 => count += 1,
+    };
+
+    // Check that PhantomData<T> is #[structural_match] when T is.
+    const CPD2: PhantomData<SM> = PhantomData;
+    match PhantomData {
+        CPD2 => count += 1,
+    };
+
+    // Check that a type which has a PhantomData is `#[structural_match]`.
+    #[derive(PartialEq, Eq, Default)]
+    struct Foo {
+        alpha: PhantomData<NotSM>,
+        beta: PhantomData<SM>,
+    }
+
+    const CFOO: Foo = Foo {
+        alpha: PhantomData,
+        beta: PhantomData,
+    };
+
+    match Foo::default() {
+        CFOO => count += 1,
+    };
+
+    // Final count must be 4 now if all
+    assert_eq!(count, 4);
+}
diff --git a/src/test/ui/rfc1598-generic-associated-types/collections.rs b/src/test/ui/rfc1598-generic-associated-types/collections.rs
new file mode 100644
index 0000000..ede6a3b
--- /dev/null
+++ b/src/test/ui/rfc1598-generic-associated-types/collections.rs
@@ -0,0 +1,88 @@
+#![feature(generic_associated_types)]
+//~^ WARNING the feature `generic_associated_types` is incomplete
+#![feature(associated_type_defaults)]
+
+// FIXME(#44265): "lifetime arguments are not allowed for this type" errors will be addressed in a
+// follow-up PR.
+
+// A Collection trait and collection families. Based on
+// http://smallcultfollowing.com/babysteps/blog/2016/11/03/
+// associated-type-constructors-part-2-family-traits/
+
+trait Collection<T> {
+    type Iter<'iter>: Iterator<Item=&'iter T>;
+    type Family: CollectionFamily;
+    // Test associated type defaults with parameters
+    type Sibling<U>: Collection<U> =
+        <<Self as Collection<T>>::Family as CollectionFamily>::Member<U>;
+    //~^ ERROR type arguments are not allowed for this type [E0109]
+
+    fn empty() -> Self;
+
+    fn add(&mut self, value: T);
+
+    fn iterate<'iter>(&'iter self) -> Self::Iter<'iter>;
+    //~^ ERROR lifetime arguments are not allowed for this type [E0109]
+}
+
+trait CollectionFamily {
+    type Member<T>: Collection<T, Family = Self>;
+}
+
+struct VecFamily;
+
+impl CollectionFamily for VecFamily {
+    type Member<T> = Vec<T>;
+}
+
+impl<T> Collection<T> for Vec<T> {
+    type Iter<'iter> = std::slice::Iter<'iter, T>;
+    type Family = VecFamily;
+
+    fn empty() -> Self {
+        Vec::new()
+    }
+
+    fn add(&mut self, value: T) {
+        self.push(value)
+    }
+
+    fn iterate<'iter>(&'iter self) -> Self::Iter<'iter> {
+    //~^ ERROR lifetime arguments are not allowed for this type [E0109]
+        self.iter()
+    }
+}
+
+fn floatify<C>(ints: &C) -> <<C as Collection<i32>>::Family as CollectionFamily>::Member<f32>
+//~^ ERROR type arguments are not allowed for this type [E0109]
+where
+    C: Collection<i32>,
+{
+    let mut res = C::Family::Member::<f32>::empty();
+    for &v in ints.iterate() {
+        res.add(v as f32);
+    }
+    res
+}
+
+fn floatify_sibling<C>(ints: &C) -> <C as Collection<i32>>::Sibling<f32>
+//~^ ERROR type arguments are not allowed for this type [E0109]
+where
+    C: Collection<i32>,
+{
+    let mut res = C::Family::Member::<f32>::empty();
+    for &v in ints.iterate() {
+        res.add(v as f32);
+    }
+    res
+}
+
+fn use_floatify() {
+    let a = vec![1i32, 2, 3];
+    let b = floatify(a);
+    println!("{}", b.iterate().next());
+    let c = floatify_sibling(a);
+    println!("{}", c.iterate().next());
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc1598-generic-associated-types/collections.stderr b/src/test/ui/rfc1598-generic-associated-types/collections.stderr
new file mode 100644
index 0000000..d0fe503
--- /dev/null
+++ b/src/test/ui/rfc1598-generic-associated-types/collections.stderr
@@ -0,0 +1,39 @@
+warning: the feature `generic_associated_types` is incomplete and may cause the compiler to crash
+  --> $DIR/collections.rs:1:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/collections.rs:56:90
+   |
+LL | fn floatify<C>(ints: &C) -> <<C as Collection<i32>>::Family as CollectionFamily>::Member<f32>
+   |                                                                                          ^^^ type argument not allowed
+
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/collections.rs:68:69
+   |
+LL | fn floatify_sibling<C>(ints: &C) -> <C as Collection<i32>>::Sibling<f32>
+   |                                                                     ^^^ type argument not allowed
+
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/collections.rs:17:71
+   |
+LL |         <<Self as Collection<T>>::Family as CollectionFamily>::Member<U>;
+   |                                                                       ^ type argument not allowed
+
+error[E0109]: lifetime arguments are not allowed for this type
+  --> $DIR/collections.rs:24:50
+   |
+LL |     fn iterate<'iter>(&'iter self) -> Self::Iter<'iter>;
+   |                                                  ^^^^^ lifetime argument not allowed
+
+error[E0109]: lifetime arguments are not allowed for this type
+  --> $DIR/collections.rs:50:50
+   |
+LL |     fn iterate<'iter>(&'iter self) -> Self::Iter<'iter> {
+   |                                                  ^^^^^ lifetime argument not allowed
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0109`.
diff --git a/src/test/ui/rfc1598-generic-associated-types/construct_with_other_type.rs b/src/test/ui/rfc1598-generic-associated-types/construct_with_other_type.rs
new file mode 100644
index 0000000..3a459a4
--- /dev/null
+++ b/src/test/ui/rfc1598-generic-associated-types/construct_with_other_type.rs
@@ -0,0 +1,29 @@
+#![feature(generic_associated_types)]
+//~^ WARNING the feature `generic_associated_types` is incomplete
+
+use std::ops::Deref;
+
+// FIXME(#44265): "lifetime arguments are not allowed for this type" errors will be addressed in a
+// follow-up PR.
+
+trait Foo {
+    type Bar<'a, 'b>;
+}
+
+trait Baz {
+    type Quux<'a>: Foo;
+
+    // This weird type tests that we can use universal function call syntax to access the Item on
+    type Baa<'a>: Deref<Target = <Self::Quux<'a> as Foo>::Bar<'a, 'static>>;
+    //~^ ERROR lifetime arguments are not allowed for this type [E0109]
+    //~| ERROR lifetime arguments are not allowed for this type [E0109]
+}
+
+impl<T> Baz for T where T: Foo {
+    type Quux<'a> = T;
+
+    type Baa<'a> = &'a <T as Foo>::Bar<'a, 'static>;
+    //~^ ERROR lifetime arguments are not allowed for this type [E0109]
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc1598-generic-associated-types/construct_with_other_type.stderr b/src/test/ui/rfc1598-generic-associated-types/construct_with_other_type.stderr
new file mode 100644
index 0000000..b2dd523
--- /dev/null
+++ b/src/test/ui/rfc1598-generic-associated-types/construct_with_other_type.stderr
@@ -0,0 +1,27 @@
+warning: the feature `generic_associated_types` is incomplete and may cause the compiler to crash
+  --> $DIR/construct_with_other_type.rs:1:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0109]: lifetime arguments are not allowed for this type
+  --> $DIR/construct_with_other_type.rs:17:46
+   |
+LL |     type Baa<'a>: Deref<Target = <Self::Quux<'a> as Foo>::Bar<'a, 'static>>;
+   |                                              ^^ lifetime argument not allowed
+
+error[E0109]: lifetime arguments are not allowed for this type
+  --> $DIR/construct_with_other_type.rs:17:63
+   |
+LL |     type Baa<'a>: Deref<Target = <Self::Quux<'a> as Foo>::Bar<'a, 'static>>;
+   |                                                               ^^ lifetime argument not allowed
+
+error[E0109]: lifetime arguments are not allowed for this type
+  --> $DIR/construct_with_other_type.rs:25:40
+   |
+LL |     type Baa<'a> = &'a <T as Foo>::Bar<'a, 'static>;
+   |                                        ^^ lifetime argument not allowed
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0109`.
diff --git a/src/test/ui/rfc1598-generic-associated-types/empty_generics.rs b/src/test/ui/rfc1598-generic-associated-types/empty_generics.rs
new file mode 100644
index 0000000..afc2770
--- /dev/null
+++ b/src/test/ui/rfc1598-generic-associated-types/empty_generics.rs
@@ -0,0 +1,9 @@
+#![feature(generic_associated_types)]
+//~^ WARNING the feature `generic_associated_types` is incomplete
+
+trait Foo {
+    type Bar<,>;
+    //~^ ERROR expected one of `>`, `const`, identifier, or lifetime, found `,`
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc1598-generic-associated-types/empty_generics.stderr b/src/test/ui/rfc1598-generic-associated-types/empty_generics.stderr
new file mode 100644
index 0000000..5b98302
--- /dev/null
+++ b/src/test/ui/rfc1598-generic-associated-types/empty_generics.stderr
@@ -0,0 +1,14 @@
+error: expected one of `>`, `const`, identifier, or lifetime, found `,`
+  --> $DIR/empty_generics.rs:5:14
+   |
+LL |     type Bar<,>;
+   |              ^ expected one of `>`, `const`, identifier, or lifetime here
+
+warning: the feature `generic_associated_types` is incomplete and may cause the compiler to crash
+  --> $DIR/empty_generics.rs:1:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc1598-generic-associated-types/gat-incomplete-warning.rs b/src/test/ui/rfc1598-generic-associated-types/gat-incomplete-warning.rs
new file mode 100644
index 0000000..3359388
--- /dev/null
+++ b/src/test/ui/rfc1598-generic-associated-types/gat-incomplete-warning.rs
@@ -0,0 +1,6 @@
+// run-pass
+
+#![feature(generic_associated_types)]
+//~^ WARNING the feature `generic_associated_types` is incomplete
+
+fn main() {}
diff --git a/src/test/ui/rfc1598-generic-associated-types/gat-incomplete-warning.stderr b/src/test/ui/rfc1598-generic-associated-types/gat-incomplete-warning.stderr
new file mode 100644
index 0000000..6953a28
--- /dev/null
+++ b/src/test/ui/rfc1598-generic-associated-types/gat-incomplete-warning.stderr
@@ -0,0 +1,6 @@
+warning: the feature `generic_associated_types` is incomplete and may cause the compiler to crash
+  --> $DIR/gat-incomplete-warning.rs:3:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+
diff --git a/src/test/ui/rfc1598-generic-associated-types/generic-associated-types-where.rs b/src/test/ui/rfc1598-generic-associated-types/generic-associated-types-where.rs
new file mode 100644
index 0000000..b0d1fa1
--- /dev/null
+++ b/src/test/ui/rfc1598-generic-associated-types/generic-associated-types-where.rs
@@ -0,0 +1,26 @@
+#![feature(generic_associated_types)] //~ WARN `generic_associated_types` is incomplete
+
+// Checking the interaction with this other feature
+#![feature(associated_type_defaults)]
+
+use std::fmt::{Display, Debug};
+
+trait Foo {
+    type Assoc where Self: Sized;
+    type Assoc2<T> where T: Display;
+    type Assoc3<T>;
+    type WithDefault<T> where T: Debug = Iterator<Item=T>;
+    type NoGenerics;
+}
+
+struct Bar;
+
+impl Foo for Bar {
+    type Assoc = usize;
+    type Assoc2<T> = Vec<T>;
+    type Assoc3<T> where T: Iterator = Vec<T>;
+    type WithDefault<'a, T> = &'a Iterator<T>;
+    type NoGenerics = ::std::cell::Cell<i32>;
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc1598-generic-associated-types/generic-associated-types-where.stderr b/src/test/ui/rfc1598-generic-associated-types/generic-associated-types-where.stderr
new file mode 100644
index 0000000..b323104
--- /dev/null
+++ b/src/test/ui/rfc1598-generic-associated-types/generic-associated-types-where.stderr
@@ -0,0 +1,6 @@
+warning: the feature `generic_associated_types` is incomplete and may cause the compiler to crash
+  --> $DIR/generic-associated-types-where.rs:1:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+
diff --git a/src/test/ui/rfc1598-generic-associated-types/generic_associated_type_undeclared_lifetimes.rs b/src/test/ui/rfc1598-generic-associated-types/generic_associated_type_undeclared_lifetimes.rs
new file mode 100644
index 0000000..150899a
--- /dev/null
+++ b/src/test/ui/rfc1598-generic-associated-types/generic_associated_type_undeclared_lifetimes.rs
@@ -0,0 +1,22 @@
+#![feature(generic_associated_types)]
+//~^ WARNING the feature `generic_associated_types` is incomplete
+
+use std::ops::Deref;
+
+// FIXME(#44265): "lifetime arguments are not allowed for this type" errors will be addressed in a
+// follow-up PR.
+
+trait Iterable {
+    type Item<'a>;
+    type Iter<'a>: Iterator<Item = Self::Item<'a>>
+    //~^ ERROR lifetime arguments are not allowed for this type [E0109]
+        + Deref<Target = Self::Item<'b>>;
+    //~^ ERROR undeclared lifetime
+    //~| ERROR lifetime arguments are not allowed for this type [E0109]
+
+    fn iter<'a>(&'a self) -> Self::Iter<'undeclared>;
+    //~^ ERROR undeclared lifetime
+    //~| ERROR lifetime arguments are not allowed for this type [E0109]
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc1598-generic-associated-types/generic_associated_type_undeclared_lifetimes.stderr b/src/test/ui/rfc1598-generic-associated-types/generic_associated_type_undeclared_lifetimes.stderr
new file mode 100644
index 0000000..d65edc6
--- /dev/null
+++ b/src/test/ui/rfc1598-generic-associated-types/generic_associated_type_undeclared_lifetimes.stderr
@@ -0,0 +1,40 @@
+warning: the feature `generic_associated_types` is incomplete and may cause the compiler to crash
+  --> $DIR/generic_associated_type_undeclared_lifetimes.rs:1:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0261]: use of undeclared lifetime name `'b`
+  --> $DIR/generic_associated_type_undeclared_lifetimes.rs:13:37
+   |
+LL |         + Deref<Target = Self::Item<'b>>;
+   |                                     ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'undeclared`
+  --> $DIR/generic_associated_type_undeclared_lifetimes.rs:17:41
+   |
+LL |     fn iter<'a>(&'a self) -> Self::Iter<'undeclared>;
+   |                                         ^^^^^^^^^^^ undeclared lifetime
+
+error[E0109]: lifetime arguments are not allowed for this type
+  --> $DIR/generic_associated_type_undeclared_lifetimes.rs:11:47
+   |
+LL |     type Iter<'a>: Iterator<Item = Self::Item<'a>>
+   |                                               ^^ lifetime argument not allowed
+
+error[E0109]: lifetime arguments are not allowed for this type
+  --> $DIR/generic_associated_type_undeclared_lifetimes.rs:13:37
+   |
+LL |         + Deref<Target = Self::Item<'b>>;
+   |                                     ^^ lifetime argument not allowed
+
+error[E0109]: lifetime arguments are not allowed for this type
+  --> $DIR/generic_associated_type_undeclared_lifetimes.rs:17:41
+   |
+LL |     fn iter<'a>(&'a self) -> Self::Iter<'undeclared>;
+   |                                         ^^^^^^^^^^^ lifetime argument not allowed
+
+error: aborting due to 5 previous errors
+
+Some errors occurred: E0109, E0261.
+For more information about an error, try `rustc --explain E0109`.
diff --git a/src/test/ui/rfc1598-generic-associated-types/iterable.rs b/src/test/ui/rfc1598-generic-associated-types/iterable.rs
new file mode 100644
index 0000000..29953b9
--- /dev/null
+++ b/src/test/ui/rfc1598-generic-associated-types/iterable.rs
@@ -0,0 +1,50 @@
+#![feature(generic_associated_types)]
+//~^ WARNING the feature `generic_associated_types` is incomplete
+
+use std::ops::Deref;
+
+// FIXME(#44265): "lifetime arguments are not allowed for this type" errors will be addressed in a
+// follow-up PR.
+
+trait Iterable {
+    type Item<'a>;
+    type Iter<'a>: Iterator<Item = Self::Item<'a>>;
+    //~^ ERROR lifetime arguments are not allowed for this type [E0109]
+
+    fn iter<'a>(&'a self) -> Self::Iter<'a>;
+    //~^ ERROR lifetime arguments are not allowed for this type [E0109]
+}
+
+// Impl for struct type
+impl<T> Iterable for Vec<T> {
+    type Item<'a> = &'a T;
+    type Iter<'a> = std::slice::Iter<'a, T>;
+
+    fn iter<'a>(&'a self) -> Self::Iter<'a> {
+    //~^ ERROR lifetime arguments are not allowed for this type [E0109]
+        self.iter()
+    }
+}
+
+// Impl for a primitive type
+impl<T> Iterable for [T] {
+    type Item<'a> = &'a T;
+    type Iter<'a> = std::slice::Iter<'a, T>;
+
+    fn iter<'a>(&'a self) -> Self::Iter<'a> {
+    //~^ ERROR lifetime arguments are not allowed for this type [E0109]
+        self.iter()
+    }
+}
+
+fn make_iter<'a, I: Iterable>(it: &'a I) -> I::Iter<'a> {
+    //~^ ERROR lifetime arguments are not allowed for this type [E0109]
+    it.iter()
+}
+
+fn get_first<'a, I: Iterable>(it: &'a I) -> Option<I::Item<'a>> {
+    //~^ ERROR lifetime arguments are not allowed for this type [E0109]
+    it.iter().next()
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc1598-generic-associated-types/iterable.stderr b/src/test/ui/rfc1598-generic-associated-types/iterable.stderr
new file mode 100644
index 0000000..6d5d0cc
--- /dev/null
+++ b/src/test/ui/rfc1598-generic-associated-types/iterable.stderr
@@ -0,0 +1,45 @@
+warning: the feature `generic_associated_types` is incomplete and may cause the compiler to crash
+  --> $DIR/iterable.rs:1:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0109]: lifetime arguments are not allowed for this type
+  --> $DIR/iterable.rs:11:47
+   |
+LL |     type Iter<'a>: Iterator<Item = Self::Item<'a>>;
+   |                                               ^^ lifetime argument not allowed
+
+error[E0109]: lifetime arguments are not allowed for this type
+  --> $DIR/iterable.rs:40:53
+   |
+LL | fn make_iter<'a, I: Iterable>(it: &'a I) -> I::Iter<'a> {
+   |                                                     ^^ lifetime argument not allowed
+
+error[E0109]: lifetime arguments are not allowed for this type
+  --> $DIR/iterable.rs:45:60
+   |
+LL | fn get_first<'a, I: Iterable>(it: &'a I) -> Option<I::Item<'a>> {
+   |                                                            ^^ lifetime argument not allowed
+
+error[E0109]: lifetime arguments are not allowed for this type
+  --> $DIR/iterable.rs:14:41
+   |
+LL |     fn iter<'a>(&'a self) -> Self::Iter<'a>;
+   |                                         ^^ lifetime argument not allowed
+
+error[E0109]: lifetime arguments are not allowed for this type
+  --> $DIR/iterable.rs:23:41
+   |
+LL |     fn iter<'a>(&'a self) -> Self::Iter<'a> {
+   |                                         ^^ lifetime argument not allowed
+
+error[E0109]: lifetime arguments are not allowed for this type
+  --> $DIR/iterable.rs:34:41
+   |
+LL |     fn iter<'a>(&'a self) -> Self::Iter<'a> {
+   |                                         ^^ lifetime argument not allowed
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0109`.
diff --git a/src/test/ui/rfc1598-generic-associated-types/parameter_number_and_kind.rs b/src/test/ui/rfc1598-generic-associated-types/parameter_number_and_kind.rs
new file mode 100644
index 0000000..aa3f4b1
--- /dev/null
+++ b/src/test/ui/rfc1598-generic-associated-types/parameter_number_and_kind.rs
@@ -0,0 +1,47 @@
+#![feature(generic_associated_types)]
+//~^ WARNING the feature `generic_associated_types` is incomplete
+#![feature(associated_type_defaults)]
+
+// FIXME(#44265): "lifetime arguments are not allowed for this type" errors will be addressed in a
+// follow-up PR.
+
+// FIXME(#44265): Update expected errors once E110 is resolved, now does not get past `trait Foo`.
+
+trait Foo {
+    type A<'a>;
+    type B<'a, 'b>;
+    type C;
+    type D<T>;
+    type E<'a, T>;
+    // Test parameters in default values
+    type FOk<T> = Self::E<'static, T>;
+    //~^ ERROR type arguments are not allowed for this type [E0109]
+    //~| ERROR lifetime arguments are not allowed for this type [E0109]
+    type FErr1 = Self::E<'static, 'static>; // Error
+    //~^ ERROR lifetime arguments are not allowed for this type [E0109]
+    type FErr2<T> = Self::E<'static, T, u32>; // Error
+    //~^ ERROR type arguments are not allowed for this type [E0109]
+    //~| ERROR lifetime arguments are not allowed for this type [E0109]
+}
+
+struct Fooy;
+
+impl Foo for Fooy {
+    type A = u32; // Error: parameter expected
+    type B<'a, T> = Vec<T>; // Error: lifetime param expected
+    type C<'a> = u32; // Error: no param expected
+    type D<'a> = u32; // Error: type param expected
+    type E<T, U> = u32; // Error: lifetime expected as the first param
+}
+
+struct Fooer;
+
+impl Foo for Fooer {
+    type A<T> = u32; // Error: lifetime parameter expected
+    type B<'a> = u32; // Error: another lifetime param expected
+    type C<T> = T; // Error: no param expected
+    type D<'b, T> = u32; // Error: unexpected lifetime param
+    type E<'a, 'b> = u32; // Error: type expected as the second param
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc1598-generic-associated-types/parameter_number_and_kind.stderr b/src/test/ui/rfc1598-generic-associated-types/parameter_number_and_kind.stderr
new file mode 100644
index 0000000..817d911
--- /dev/null
+++ b/src/test/ui/rfc1598-generic-associated-types/parameter_number_and_kind.stderr
@@ -0,0 +1,39 @@
+warning: the feature `generic_associated_types` is incomplete and may cause the compiler to crash
+  --> $DIR/parameter_number_and_kind.rs:1:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0109]: lifetime arguments are not allowed for this type
+  --> $DIR/parameter_number_and_kind.rs:17:27
+   |
+LL |     type FOk<T> = Self::E<'static, T>;
+   |                           ^^^^^^^ lifetime argument not allowed
+
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/parameter_number_and_kind.rs:17:36
+   |
+LL |     type FOk<T> = Self::E<'static, T>;
+   |                                    ^ type argument not allowed
+
+error[E0109]: lifetime arguments are not allowed for this type
+  --> $DIR/parameter_number_and_kind.rs:20:26
+   |
+LL |     type FErr1 = Self::E<'static, 'static>; // Error
+   |                          ^^^^^^^ lifetime argument not allowed
+
+error[E0109]: lifetime arguments are not allowed for this type
+  --> $DIR/parameter_number_and_kind.rs:22:29
+   |
+LL |     type FErr2<T> = Self::E<'static, T, u32>; // Error
+   |                             ^^^^^^^ lifetime argument not allowed
+
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/parameter_number_and_kind.rs:22:38
+   |
+LL |     type FErr2<T> = Self::E<'static, T, u32>; // Error
+   |                                      ^ type argument not allowed
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0109`.
diff --git a/src/test/ui/rfc1598-generic-associated-types/parse/in-trait-impl.rs b/src/test/ui/rfc1598-generic-associated-types/parse/in-trait-impl.rs
new file mode 100644
index 0000000..589e5fc
--- /dev/null
+++ b/src/test/ui/rfc1598-generic-associated-types/parse/in-trait-impl.rs
@@ -0,0 +1,10 @@
+// compile-pass
+// compile-flags: -Z parse-only
+
+#![feature(generic_associated_types)]
+
+impl<T> Baz for T where T: Foo {
+    type Quux<'a> = <T as Foo>::Bar<'a, 'static>;
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc1598-generic-associated-types/parse/in-trait.rs b/src/test/ui/rfc1598-generic-associated-types/parse/in-trait.rs
new file mode 100644
index 0000000..7fa71e4
--- /dev/null
+++ b/src/test/ui/rfc1598-generic-associated-types/parse/in-trait.rs
@@ -0,0 +1,23 @@
+// compile-pass
+// compile-flags: -Z parse-only
+
+#![feature(generic_associated_types)]
+
+use std::ops::Deref;
+
+trait Foo {
+    type Bar<'a>;
+    type Bar<'a, 'b>;
+    type Bar<'a, 'b,>;
+    type Bar<'a, 'b, T>;
+    type Bar<'a, 'b, T, U>;
+    type Bar<'a, 'b, T, U,>;
+    type Bar<'a, 'b, T: Debug, U,>;
+    type Bar<'a, 'b, T: Debug, U,>: Debug;
+    type Bar<'a, 'b, T: Debug, U,>: Deref<Target = T> + Into<U>;
+    type Bar<'a, 'b, T: Debug, U,> where T: Deref<Target = U>, U: Into<T>;
+    type Bar<'a, 'b, T: Debug, U,>: Deref<Target = T> + Into<U>
+        where T: Deref<Target = U>, U: Into<T>;
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc1598-generic-associated-types/pointer_family.rs b/src/test/ui/rfc1598-generic-associated-types/pointer_family.rs
new file mode 100644
index 0000000..edeeaba
--- /dev/null
+++ b/src/test/ui/rfc1598-generic-associated-types/pointer_family.rs
@@ -0,0 +1,41 @@
+#![feature(generic_associated_types)]
+//~^ WARNING the feature `generic_associated_types` is incomplete
+
+// FIXME(#44265): "type argument not allowed" errors will be addressed in a follow-up PR.
+
+use std::rc::Rc;
+use std::sync::Arc;
+use std::ops::Deref;
+
+trait PointerFamily {
+    type Pointer<T>: Deref<Target = T>;
+    fn new<T>(value: T) -> Self::Pointer<T>;
+    //~^ ERROR type arguments are not allowed for this type [E0109]
+}
+
+struct ArcFamily;
+
+impl PointerFamily for ArcFamily {
+    type Pointer<T> = Arc<T>;
+    fn new<T>(value: T) -> Self::Pointer<T> {
+    //~^ ERROR type arguments are not allowed for this type [E0109]
+        Arc::new(value)
+    }
+}
+
+struct RcFamily;
+
+impl PointerFamily for RcFamily {
+    type Pointer<T> = Rc<T>;
+    fn new<T>(value: T) -> Self::Pointer<T> {
+    //~^ ERROR type arguments are not allowed for this type [E0109]
+        Rc::new(value)
+    }
+}
+
+struct Foo<P: PointerFamily> {
+    bar: P::Pointer<String>,
+    //~^ ERROR type arguments are not allowed for this type [E0109]
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc1598-generic-associated-types/pointer_family.stderr b/src/test/ui/rfc1598-generic-associated-types/pointer_family.stderr
new file mode 100644
index 0000000..0966f8f
--- /dev/null
+++ b/src/test/ui/rfc1598-generic-associated-types/pointer_family.stderr
@@ -0,0 +1,33 @@
+warning: the feature `generic_associated_types` is incomplete and may cause the compiler to crash
+  --> $DIR/pointer_family.rs:1:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/pointer_family.rs:37:21
+   |
+LL |     bar: P::Pointer<String>,
+   |                     ^^^^^^ type argument not allowed
+
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/pointer_family.rs:12:42
+   |
+LL |     fn new<T>(value: T) -> Self::Pointer<T>;
+   |                                          ^ type argument not allowed
+
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/pointer_family.rs:20:42
+   |
+LL |     fn new<T>(value: T) -> Self::Pointer<T> {
+   |                                          ^ type argument not allowed
+
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/pointer_family.rs:30:42
+   |
+LL |     fn new<T>(value: T) -> Self::Pointer<T> {
+   |                                          ^ type argument not allowed
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0109`.
diff --git a/src/test/ui/rfc1598-generic-associated-types/shadowing.rs b/src/test/ui/rfc1598-generic-associated-types/shadowing.rs
new file mode 100644
index 0000000..82a7c25
--- /dev/null
+++ b/src/test/ui/rfc1598-generic-associated-types/shadowing.rs
@@ -0,0 +1,32 @@
+#![feature(generic_associated_types)]
+
+//FIXME(#44265): The lifetime shadowing and type parameter shadowing
+// should cause an error. Now it compiles (erroneously) and this will be addressed
+// by a future PR. Then remove the following:
+// compile-pass
+
+trait Shadow<'a> {
+    type Bar<'a>; // Error: shadowed lifetime
+}
+
+trait NoShadow<'a> {
+    type Bar<'b>; // OK
+}
+
+impl<'a> NoShadow<'a> for &'a u32 {
+    type Bar<'a> = i32; // Error: shadowed lifetime
+}
+
+trait ShadowT<T> {
+    type Bar<T>; // Error: shadowed type parameter
+}
+
+trait NoShadowT<T> {
+    type Bar<U>; // OK
+}
+
+impl<T> NoShadowT<T> for Option<T> {
+    type Bar<T> = i32; // Error: shadowed type parameter
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc1598-generic-associated-types/shadowing.stderr b/src/test/ui/rfc1598-generic-associated-types/shadowing.stderr
new file mode 100644
index 0000000..cba6bbd
--- /dev/null
+++ b/src/test/ui/rfc1598-generic-associated-types/shadowing.stderr
@@ -0,0 +1,6 @@
+warning: the feature `generic_associated_types` is incomplete and may cause the compiler to crash
+  --> $DIR/shadowing.rs:1:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+
diff --git a/src/test/ui/rfc1598-generic-associated-types/streaming_iterator.rs b/src/test/ui/rfc1598-generic-associated-types/streaming_iterator.rs
new file mode 100644
index 0000000..4e177fb
--- /dev/null
+++ b/src/test/ui/rfc1598-generic-associated-types/streaming_iterator.rs
@@ -0,0 +1,73 @@
+#![feature(generic_associated_types)]
+//~^ WARNING the feature `generic_associated_types` is incomplete
+
+// FIXME(#44265): "lifetime argument not allowed on this type" errors will be addressed in a
+// follow-up PR
+
+use std::fmt::Display;
+
+trait StreamingIterator {
+    type Item<'a>;
+    // Applying the lifetime parameter `'a` to `Self::Item` inside the trait.
+    fn next<'a>(&'a self) -> Option<Self::Item<'a>>;
+    //~^ ERROR lifetime arguments are not allowed for this type [E0109]
+}
+
+struct Foo<T: StreamingIterator> {
+    // Applying a concrete lifetime to the constructor outside the trait.
+    bar: <T as StreamingIterator>::Item<'static>,
+    //~^ ERROR lifetime arguments are not allowed for this type [E0109]
+}
+
+// Users can bound parameters by the type constructed by that trait's associated type constructor
+// of a trait using HRTB. Both type equality bounds and trait bounds of this kind are valid:
+//FIXME(sunjay): This next line should parse and be valid
+//fn foo<T: for<'a> StreamingIterator<Item<'a>=&'a [i32]>>(iter: T) { /* ... */ }
+fn foo<T>(iter: T) where T: StreamingIterator, for<'a> T::Item<'a>: Display { /* ... */ }
+//~^ ERROR lifetime arguments are not allowed for this type [E0109]
+
+// Full example of enumerate iterator
+
+#[must_use = "iterators are lazy and do nothing unless consumed"]
+struct StreamEnumerate<I> {
+    iter: I,
+    count: usize,
+}
+
+impl<I: StreamingIterator> StreamingIterator for StreamEnumerate<I> {
+    type Item<'a> = (usize, I::Item<'a>);
+    //~^ ERROR lifetime arguments are not allowed for this type [E0109]
+    fn next<'a>(&'a self) -> Option<Self::Item<'a>> {
+        //~^ ERROR lifetime arguments are not allowed for this type [E0109]
+        match self.iter.next() {
+            None => None,
+            Some(val) => {
+                let r = Some((self.count, val));
+                self.count += 1;
+                r
+            }
+        }
+    }
+}
+
+impl<I> StreamEnumerate<I> {
+    pub fn new(iter: I) -> Self {
+        StreamEnumerate {
+            count: 0,
+            iter: iter,
+        }
+    }
+}
+
+fn test_stream_enumerate() {
+    let v = vec!["a", "b", "c"];
+    let se = StreamEnumerate::new(v.iter());
+    let a: &str = se.next().unwrap().1;
+    for (i, s) in se {
+        println!("{} {}", i, s);
+    }
+    println!("{}", a);
+}
+
+
+fn main() {}
diff --git a/src/test/ui/rfc1598-generic-associated-types/streaming_iterator.stderr b/src/test/ui/rfc1598-generic-associated-types/streaming_iterator.stderr
new file mode 100644
index 0000000..5fc1e3d
--- /dev/null
+++ b/src/test/ui/rfc1598-generic-associated-types/streaming_iterator.stderr
@@ -0,0 +1,39 @@
+warning: the feature `generic_associated_types` is incomplete and may cause the compiler to crash
+  --> $DIR/streaming_iterator.rs:1:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0109]: lifetime arguments are not allowed for this type
+  --> $DIR/streaming_iterator.rs:18:41
+   |
+LL |     bar: <T as StreamingIterator>::Item<'static>,
+   |                                         ^^^^^^^ lifetime argument not allowed
+
+error[E0109]: lifetime arguments are not allowed for this type
+  --> $DIR/streaming_iterator.rs:26:64
+   |
+LL | fn foo<T>(iter: T) where T: StreamingIterator, for<'a> T::Item<'a>: Display { /* ... */ }
+   |                                                                ^^ lifetime argument not allowed
+
+error[E0109]: lifetime arguments are not allowed for this type
+  --> $DIR/streaming_iterator.rs:12:48
+   |
+LL |     fn next<'a>(&'a self) -> Option<Self::Item<'a>>;
+   |                                                ^^ lifetime argument not allowed
+
+error[E0109]: lifetime arguments are not allowed for this type
+  --> $DIR/streaming_iterator.rs:38:37
+   |
+LL |     type Item<'a> = (usize, I::Item<'a>);
+   |                                     ^^ lifetime argument not allowed
+
+error[E0109]: lifetime arguments are not allowed for this type
+  --> $DIR/streaming_iterator.rs:40:48
+   |
+LL |     fn next<'a>(&'a self) -> Option<Self::Item<'a>> {
+   |                                                ^^ lifetime argument not allowed
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0109`.
diff --git a/src/test/ui/rfc1623.rs b/src/test/ui/rfc1623.rs
new file mode 100644
index 0000000..5920446
--- /dev/null
+++ b/src/test/ui/rfc1623.rs
@@ -0,0 +1,93 @@
+#![allow(dead_code)]
+
+fn non_elidable<'a, 'b>(a: &'a u8, b: &'b u8) -> &'a u8 {
+    a
+}
+
+// the boundaries of elision
+static NON_ELIDABLE_FN: &fn(&u8, &u8) -> &u8 =
+//~^ ERROR missing lifetime specifier [E0106]
+    &(non_elidable as fn(&u8, &u8) -> &u8);
+    //~^ ERROR missing lifetime specifier [E0106]
+
+struct SomeStruct<'x, 'y, 'z: 'x> {
+    foo: &'x Foo<'z>,
+    bar: &'x Bar<'z>,
+    f: &'y for<'a, 'b> Fn(&'a Foo<'b>) -> &'a Bar<'b>,
+}
+
+fn id<T>(t: T) -> T {
+    t
+}
+
+static SOME_STRUCT: &SomeStruct = SomeStruct {
+    foo: &Foo { bools: &[false, true] },
+    bar: &Bar { bools: &[true, true] },
+    f: &id,
+};
+
+// very simple test for a 'static static with default lifetime
+static STATIC_STR: &'static str = "&'static str";
+const CONST_STR: &'static str = "&'static str";
+
+// this should be the same as without default:
+static EXPLICIT_STATIC_STR: &'static str = "&'static str";
+const EXPLICIT_CONST_STR: &'static str = "&'static str";
+
+// a function that elides to an unbound lifetime for both in- and output
+fn id_u8_slice(arg: &[u8]) -> &[u8] {
+    arg
+}
+
+// one with a function, argument elided
+static STATIC_SIMPLE_FN: &'static fn(&[u8]) -> &[u8] = &(id_u8_slice as fn(&[u8]) -> &[u8]);
+const CONST_SIMPLE_FN: &'static fn(&[u8]) -> &[u8] = &(id_u8_slice as fn(&[u8]) -> &[u8]);
+
+// this should be the same as without elision
+static STATIC_NON_ELIDED_fN: &'static for<'a> fn(&'a [u8]) -> &'a [u8] =
+    &(id_u8_slice as for<'a> fn(&'a [u8]) -> &'a [u8]);
+const CONST_NON_ELIDED_fN: &'static for<'a> fn(&'a [u8]) -> &'a [u8] =
+    &(id_u8_slice as for<'a> fn(&'a [u8]) -> &'a [u8]);
+
+// another function that elides, each to a different unbound lifetime
+fn multi_args(a: &u8, b: &u8, c: &u8) {}
+
+static STATIC_MULTI_FN: &'static fn(&u8, &u8, &u8) = &(multi_args as fn(&u8, &u8, &u8));
+const CONST_MULTI_FN: &'static fn(&u8, &u8, &u8) = &(multi_args as fn(&u8, &u8, &u8));
+
+struct Foo<'a> {
+    bools: &'a [bool],
+}
+
+static STATIC_FOO: Foo<'static> = Foo { bools: &[true, false] };
+const CONST_FOO: Foo<'static> = Foo { bools: &[true, false] };
+
+type Bar<'a> = Foo<'a>;
+
+static STATIC_BAR: Bar<'static> = Bar { bools: &[true, false] };
+const CONST_BAR: Bar<'static> = Bar { bools: &[true, false] };
+
+type Baz<'a> = fn(&'a [u8]) -> Option<u8>;
+
+fn baz(e: &[u8]) -> Option<u8> {
+    e.first().map(|x| *x)
+}
+
+static STATIC_BAZ: &'static Baz<'static> = &(baz as Baz);
+const CONST_BAZ: &'static Baz<'static> = &(baz as Baz);
+
+static BYTES: &'static [u8] = &[1, 2, 3];
+
+fn main() {
+    let x = &[1u8, 2, 3];
+    let y = x;
+
+    // this works, so lifetime < `'static` is valid
+    assert_eq!(Some(1), STATIC_BAZ(y));
+    assert_eq!(Some(1), CONST_BAZ(y));
+
+    let y = &[1u8, 2, 3];
+
+    STATIC_BAZ(BYTES); // BYTES has static lifetime
+    CONST_BAZ(y); // interestingly this does not get reported
+}
diff --git a/src/test/ui/rfc1623.stderr b/src/test/ui/rfc1623.stderr
new file mode 100644
index 0000000..171c00b
--- /dev/null
+++ b/src/test/ui/rfc1623.stderr
@@ -0,0 +1,19 @@
+error[E0106]: missing lifetime specifier
+  --> $DIR/rfc1623.rs:8:42
+   |
+LL | static NON_ELIDABLE_FN: &fn(&u8, &u8) -> &u8 =
+   |                                          ^ expected lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/rfc1623.rs:10:39
+   |
+LL |     &(non_elidable as fn(&u8, &u8) -> &u8);
+   |                                       ^ expected lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0106`.
diff --git a/src/test/ui/rfc1717/missing-link-attr.rs b/src/test/ui/rfc1717/missing-link-attr.rs
new file mode 100644
index 0000000..b46d851
--- /dev/null
+++ b/src/test/ui/rfc1717/missing-link-attr.rs
@@ -0,0 +1,4 @@
+// compile-flags: -l foo:bar
+// error-pattern: renaming of the library `foo` was specified
+
+#![crate_type = "lib"]
diff --git a/src/test/ui/rfc1717/missing-link-attr.stderr b/src/test/ui/rfc1717/missing-link-attr.stderr
new file mode 100644
index 0000000..30555e8
--- /dev/null
+++ b/src/test/ui/rfc1717/missing-link-attr.stderr
@@ -0,0 +1,4 @@
+error: renaming of the library `foo` was specified, however this crate contains no #[link(...)] attributes referencing this library.
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc1717/multiple-renames.rs b/src/test/ui/rfc1717/multiple-renames.rs
new file mode 100644
index 0000000..106f196b
--- /dev/null
+++ b/src/test/ui/rfc1717/multiple-renames.rs
@@ -0,0 +1,7 @@
+// compile-flags: -l foo:bar -l foo:baz
+// error-pattern: multiple renamings were specified for library
+
+#![crate_type = "lib"]
+
+#[link(name = "foo")]
+extern "C" {}
diff --git a/src/test/ui/rfc1717/multiple-renames.stderr b/src/test/ui/rfc1717/multiple-renames.stderr
new file mode 100644
index 0000000..4e5a364
--- /dev/null
+++ b/src/test/ui/rfc1717/multiple-renames.stderr
@@ -0,0 +1,4 @@
+error: multiple renamings were specified for library `foo` .
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc1717/rename-to-empty.rs b/src/test/ui/rfc1717/rename-to-empty.rs
new file mode 100644
index 0000000..9356c41
--- /dev/null
+++ b/src/test/ui/rfc1717/rename-to-empty.rs
@@ -0,0 +1,7 @@
+// compile-flags: -l foo:
+// error-pattern: an empty renaming target was specified for library
+
+#![crate_type = "lib"]
+
+#[link(name = "foo")]
+extern "C" {}
diff --git a/src/test/ui/rfc1717/rename-to-empty.stderr b/src/test/ui/rfc1717/rename-to-empty.stderr
new file mode 100644
index 0000000..aca839d
--- /dev/null
+++ b/src/test/ui/rfc1717/rename-to-empty.stderr
@@ -0,0 +1,4 @@
+error: an empty renaming target was specified for library `foo`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rmeta-lib-pass.rs b/src/test/ui/rmeta-lib-pass.rs
new file mode 100644
index 0000000..4ab4117
--- /dev/null
+++ b/src/test/ui/rmeta-lib-pass.rs
@@ -0,0 +1,14 @@
+// compile-flags: --emit=metadata
+// aux-build:rmeta-rlib.rs
+// no-prefer-dynamic
+// compile-pass
+
+// Check that building a metadata crate works with a dependent, rlib crate.
+// This is a cfail test since there is no executable to run.
+
+extern crate rmeta_rlib;
+use rmeta_rlib::Foo;
+
+pub fn main() {
+    let _ = Foo { field: 42 };
+}
diff --git a/src/test/ui/rmeta-pass.rs b/src/test/ui/rmeta-pass.rs
new file mode 100644
index 0000000..9c88de7
--- /dev/null
+++ b/src/test/ui/rmeta-pass.rs
@@ -0,0 +1,15 @@
+// compile-flags: --emit=metadata
+// aux-build:rmeta-meta.rs
+// no-prefer-dynamic
+// compile-pass
+
+// Check that building a metadata crate works with a dependent, metadata-only
+// crate.
+// This is a cfail test since there is no executable to run.
+
+extern crate rmeta_meta;
+use rmeta_meta::Foo;
+
+pub fn main() {
+    let _ = Foo { field: 42 };
+}
diff --git a/src/test/ui/rmeta-priv-warn.rs b/src/test/ui/rmeta-priv-warn.rs
new file mode 100644
index 0000000..823ce80
--- /dev/null
+++ b/src/test/ui/rmeta-priv-warn.rs
@@ -0,0 +1,11 @@
+// compile-flags: --emit=metadata
+// no-prefer-dynamic
+// compile-pass
+
+#[deny(warnings)]
+
+// Test that we don't get warnings for non-pub main when only emitting metadata.
+// (#38273)
+
+fn main() {
+}
diff --git a/src/test/ui/rmeta.rs b/src/test/ui/rmeta.rs
new file mode 100644
index 0000000..63ed236
--- /dev/null
+++ b/src/test/ui/rmeta.rs
@@ -0,0 +1,8 @@
+// no-prefer-dynamic
+// compile-flags: --emit=metadata
+
+// Check that building a metadata crate finds an error.
+
+fn main() {
+    let _ = Foo; //~ ERROR cannot find value `Foo` in this scope
+}
diff --git a/src/test/ui/rmeta.stderr b/src/test/ui/rmeta.stderr
new file mode 100644
index 0000000..d15caeb
--- /dev/null
+++ b/src/test/ui/rmeta.stderr
@@ -0,0 +1,9 @@
+error[E0425]: cannot find value `Foo` in this scope
+  --> $DIR/rmeta.rs:7:13
+   |
+LL |     let _ = Foo;
+   |             ^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/rmeta_lib.rs b/src/test/ui/rmeta_lib.rs
new file mode 100644
index 0000000..6c74aec
--- /dev/null
+++ b/src/test/ui/rmeta_lib.rs
@@ -0,0 +1,13 @@
+// aux-build:rmeta-meta.rs
+// no-prefer-dynamic
+// error-pattern: crate `rmeta_meta` required to be available in rlib format, but was not found
+
+// Check that building a non-metadata crate fails if a dependent crate is
+// metadata-only.
+
+extern crate rmeta_meta;
+use rmeta_meta::Foo;
+
+fn main() {
+    let _ = Foo { field: 42 };
+}
diff --git a/src/test/ui/rmeta_lib.stderr b/src/test/ui/rmeta_lib.stderr
new file mode 100644
index 0000000..8a9179c
--- /dev/null
+++ b/src/test/ui/rmeta_lib.stderr
@@ -0,0 +1,4 @@
+error: crate `rmeta_meta` required to be available in rlib format, but was not found in this form
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rmeta_meta_main.rs b/src/test/ui/rmeta_meta_main.rs
new file mode 100644
index 0000000..52cd0c2
--- /dev/null
+++ b/src/test/ui/rmeta_meta_main.rs
@@ -0,0 +1,14 @@
+// compile-flags: --emit=metadata
+// aux-build:rmeta-meta.rs
+// no-prefer-dynamic
+
+// Check that building a metadata crate finds an error with a dependent,
+// metadata-only crate.
+
+
+extern crate rmeta_meta;
+use rmeta_meta::Foo;
+
+fn main() {
+    let _ = Foo { field2: 42 }; //~ ERROR struct `rmeta_meta::Foo` has no field named `field2`
+}
diff --git a/src/test/ui/rmeta_meta_main.stderr b/src/test/ui/rmeta_meta_main.stderr
new file mode 100644
index 0000000..347e5e9
--- /dev/null
+++ b/src/test/ui/rmeta_meta_main.stderr
@@ -0,0 +1,9 @@
+error[E0560]: struct `rmeta_meta::Foo` has no field named `field2`
+  --> $DIR/rmeta_meta_main.rs:13:19
+   |
+LL |     let _ = Foo { field2: 42 };
+   |                   ^^^^^^ help: a field with a similar name exists: `field`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0560`.
diff --git a/src/test/ui/run-pass/traits/trait-alias.rs b/src/test/ui/run-pass/traits/trait-alias.rs
new file mode 100644
index 0000000..9be5664
--- /dev/null
+++ b/src/test/ui/run-pass/traits/trait-alias.rs
@@ -0,0 +1,7 @@
+// run-pass
+#![feature(trait_alias)]
+
+pub trait Foo {}
+pub trait FooAlias = Foo;
+
+fn main() {}
diff --git a/src/test/ui/run-pass/traits/traits-static-outlives-a-where-clause.rs b/src/test/ui/run-pass/traits/traits-static-outlives-a-where-clause.rs
new file mode 100644
index 0000000..f0c2c10
--- /dev/null
+++ b/src/test/ui/run-pass/traits/traits-static-outlives-a-where-clause.rs
@@ -0,0 +1,23 @@
+// run-pass
+
+trait Foo<'a> {
+    fn xyz(self);
+}
+impl<'a, T> Foo<'a> for T where 'static: 'a {
+    fn xyz(self) {}
+}
+
+trait Bar {
+    fn uvw(self);
+}
+impl<T> Bar for T where for<'a> T: Foo<'a> {
+    fn uvw(self) { self.xyz(); }
+}
+
+fn foo<T>(t: T) where T: Bar {
+    t.uvw();
+}
+
+fn main() {
+    foo(0);
+}
diff --git a/src/test/ui/rust-2018/async-ident-allowed.rs b/src/test/ui/rust-2018/async-ident-allowed.rs
new file mode 100644
index 0000000..9d96121
--- /dev/null
+++ b/src/test/ui/rust-2018/async-ident-allowed.rs
@@ -0,0 +1,11 @@
+// edition:2015
+
+#![deny(rust_2018_compatibility)]
+
+// Don't make a suggestion for a raw identifier replacement unless raw
+// identifiers are enabled.
+
+fn main() {
+    let async = 3; //~ ERROR: is a keyword
+    //~^ WARN previously accepted
+}
diff --git a/src/test/ui/rust-2018/async-ident-allowed.stderr b/src/test/ui/rust-2018/async-ident-allowed.stderr
new file mode 100644
index 0000000..d3e450e
--- /dev/null
+++ b/src/test/ui/rust-2018/async-ident-allowed.stderr
@@ -0,0 +1,17 @@
+error: `async` is a keyword in the 2018 edition
+  --> $DIR/async-ident-allowed.rs:9:9
+   |
+LL |     let async = 3;
+   |         ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
+   |
+note: lint level defined here
+  --> $DIR/async-ident-allowed.rs:3:9
+   |
+LL | #![deny(rust_2018_compatibility)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+   = note: #[deny(keyword_idents)] implied by #[deny(rust_2018_compatibility)]
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rust-2018/async-ident.fixed b/src/test/ui/rust-2018/async-ident.fixed
new file mode 100644
index 0000000..3d6f6ff
--- /dev/null
+++ b/src/test/ui/rust-2018/async-ident.fixed
@@ -0,0 +1,79 @@
+#![allow(dead_code, unused_variables, non_camel_case_types, non_upper_case_globals)]
+#![deny(keyword_idents)]
+
+// edition:2015
+// run-rustfix
+
+fn r#async() {} //~ ERROR async
+//~^ WARN hard error in the 2018 edition
+
+macro_rules! foo {
+    ($foo:ident) => {};
+    ($r#async:expr, r#async) => {};
+    //~^ ERROR async
+    //~| ERROR async
+    //~| WARN hard error in the 2018 edition
+    //~| WARN hard error in the 2018 edition
+}
+
+foo!(r#async);
+    //~^ ERROR async
+    //~| WARN hard error in the 2018 edition
+
+mod dont_lint_raw {
+    fn r#async() {}
+}
+
+mod async_trait {
+    trait r#async {}
+    //~^ ERROR async
+    //~| WARN hard error in the 2018 edition
+    struct MyStruct;
+    impl r#async for MyStruct {}
+    //~^ ERROR async
+    //~| WARN hard error in the 2018 edition
+}
+
+mod async_static {
+    static r#async: u32 = 0;
+    //~^ ERROR async
+    //~| WARN hard error in the 2018 edition
+}
+
+mod async_const {
+    const r#async: u32 = 0;
+    //~^ ERROR async
+    //~| WARN hard error in the 2018 edition
+}
+
+struct Foo;
+impl Foo { fn r#async() {} }
+    //~^ ERROR async
+    //~| WARN hard error in the 2018 edition
+
+fn main() {
+    struct r#async {}
+    //~^ ERROR async
+    //~| WARN hard error in the 2018 edition
+    let r#async: r#async = r#async {};
+    //~^ ERROR async
+    //~| WARN hard error in the 2018 edition
+    //~| ERROR async
+    //~| WARN hard error in the 2018 edition
+    //~| ERROR async
+    //~| WARN hard error in the 2018 edition
+}
+
+#[macro_export]
+macro_rules! produces_async {
+    () => (pub fn r#async() {})
+    //~^ ERROR async
+    //~| WARN hard error in the 2018 edition
+}
+
+#[macro_export]
+macro_rules! consumes_async {
+    (r#async) => (1)
+    //~^ ERROR async
+    //~| WARN hard error in the 2018 edition
+}
diff --git a/src/test/ui/rust-2018/async-ident.rs b/src/test/ui/rust-2018/async-ident.rs
new file mode 100644
index 0000000..6e8d33d
--- /dev/null
+++ b/src/test/ui/rust-2018/async-ident.rs
@@ -0,0 +1,79 @@
+#![allow(dead_code, unused_variables, non_camel_case_types, non_upper_case_globals)]
+#![deny(keyword_idents)]
+
+// edition:2015
+// run-rustfix
+
+fn async() {} //~ ERROR async
+//~^ WARN hard error in the 2018 edition
+
+macro_rules! foo {
+    ($foo:ident) => {};
+    ($async:expr, async) => {};
+    //~^ ERROR async
+    //~| ERROR async
+    //~| WARN hard error in the 2018 edition
+    //~| WARN hard error in the 2018 edition
+}
+
+foo!(async);
+    //~^ ERROR async
+    //~| WARN hard error in the 2018 edition
+
+mod dont_lint_raw {
+    fn r#async() {}
+}
+
+mod async_trait {
+    trait async {}
+    //~^ ERROR async
+    //~| WARN hard error in the 2018 edition
+    struct MyStruct;
+    impl async for MyStruct {}
+    //~^ ERROR async
+    //~| WARN hard error in the 2018 edition
+}
+
+mod async_static {
+    static async: u32 = 0;
+    //~^ ERROR async
+    //~| WARN hard error in the 2018 edition
+}
+
+mod async_const {
+    const async: u32 = 0;
+    //~^ ERROR async
+    //~| WARN hard error in the 2018 edition
+}
+
+struct Foo;
+impl Foo { fn async() {} }
+    //~^ ERROR async
+    //~| WARN hard error in the 2018 edition
+
+fn main() {
+    struct async {}
+    //~^ ERROR async
+    //~| WARN hard error in the 2018 edition
+    let async: async = async {};
+    //~^ ERROR async
+    //~| WARN hard error in the 2018 edition
+    //~| ERROR async
+    //~| WARN hard error in the 2018 edition
+    //~| ERROR async
+    //~| WARN hard error in the 2018 edition
+}
+
+#[macro_export]
+macro_rules! produces_async {
+    () => (pub fn async() {})
+    //~^ ERROR async
+    //~| WARN hard error in the 2018 edition
+}
+
+#[macro_export]
+macro_rules! consumes_async {
+    (async) => (1)
+    //~^ ERROR async
+    //~| WARN hard error in the 2018 edition
+}
diff --git a/src/test/ui/rust-2018/async-ident.stderr b/src/test/ui/rust-2018/async-ident.stderr
new file mode 100644
index 0000000..b149533
--- /dev/null
+++ b/src/test/ui/rust-2018/async-ident.stderr
@@ -0,0 +1,142 @@
+error: `async` is a keyword in the 2018 edition
+  --> $DIR/async-ident.rs:7:4
+   |
+LL | fn async() {}
+   |    ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
+   |
+note: lint level defined here
+  --> $DIR/async-ident.rs:2:9
+   |
+LL | #![deny(keyword_idents)]
+   |         ^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: `async` is a keyword in the 2018 edition
+  --> $DIR/async-ident.rs:12:7
+   |
+LL |     ($async:expr, async) => {};
+   |       ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: `async` is a keyword in the 2018 edition
+  --> $DIR/async-ident.rs:12:19
+   |
+LL |     ($async:expr, async) => {};
+   |                   ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: `async` is a keyword in the 2018 edition
+  --> $DIR/async-ident.rs:19:6
+   |
+LL | foo!(async);
+   |      ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: `async` is a keyword in the 2018 edition
+  --> $DIR/async-ident.rs:28:11
+   |
+LL |     trait async {}
+   |           ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: `async` is a keyword in the 2018 edition
+  --> $DIR/async-ident.rs:32:10
+   |
+LL |     impl async for MyStruct {}
+   |          ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: `async` is a keyword in the 2018 edition
+  --> $DIR/async-ident.rs:38:12
+   |
+LL |     static async: u32 = 0;
+   |            ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: `async` is a keyword in the 2018 edition
+  --> $DIR/async-ident.rs:44:11
+   |
+LL |     const async: u32 = 0;
+   |           ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: `async` is a keyword in the 2018 edition
+  --> $DIR/async-ident.rs:50:15
+   |
+LL | impl Foo { fn async() {} }
+   |               ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: `async` is a keyword in the 2018 edition
+  --> $DIR/async-ident.rs:55:12
+   |
+LL |     struct async {}
+   |            ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: `async` is a keyword in the 2018 edition
+  --> $DIR/async-ident.rs:58:9
+   |
+LL |     let async: async = async {};
+   |         ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: `async` is a keyword in the 2018 edition
+  --> $DIR/async-ident.rs:58:16
+   |
+LL |     let async: async = async {};
+   |                ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: `async` is a keyword in the 2018 edition
+  --> $DIR/async-ident.rs:58:24
+   |
+LL |     let async: async = async {};
+   |                        ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: `async` is a keyword in the 2018 edition
+  --> $DIR/async-ident.rs:69:19
+   |
+LL |     () => (pub fn async() {})
+   |                   ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: `async` is a keyword in the 2018 edition
+  --> $DIR/async-ident.rs:76:6
+   |
+LL |     (async) => (1)
+   |      ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: aborting due to 15 previous errors
+
diff --git a/src/test/ui/rust-2018/auxiliary/baz.rs b/src/test/ui/rust-2018/auxiliary/baz.rs
new file mode 100644
index 0000000..b317c8a
--- /dev/null
+++ b/src/test/ui/rust-2018/auxiliary/baz.rs
@@ -0,0 +1,5 @@
+// This file is used as part of the local-path-suggestions.rs test.
+
+pub mod foobar {
+    pub struct Baz;
+}
diff --git a/src/test/ui/rust-2018/auxiliary/edition-lint-paths.rs b/src/test/ui/rust-2018/auxiliary/edition-lint-paths.rs
new file mode 100644
index 0000000..dd22df8
--- /dev/null
+++ b/src/test/ui/rust-2018/auxiliary/edition-lint-paths.rs
@@ -0,0 +1,12 @@
+pub fn foo() {}
+
+#[macro_export]
+macro_rules! macro_2015 {
+    () => {
+        use edition_lint_paths as other_name;
+        use edition_lint_paths::foo as other_foo;
+        fn check_macro_2015() {
+            ::edition_lint_paths::foo();
+        }
+    }
+}
diff --git a/src/test/ui/rust-2018/auxiliary/macro-use-warned-against.rs b/src/test/ui/rust-2018/auxiliary/macro-use-warned-against.rs
new file mode 100644
index 0000000..b497c74
--- /dev/null
+++ b/src/test/ui/rust-2018/auxiliary/macro-use-warned-against.rs
@@ -0,0 +1,2 @@
+#[macro_export]
+macro_rules! foo { () => () }
diff --git a/src/test/ui/rust-2018/auxiliary/macro-use-warned-against2.rs b/src/test/ui/rust-2018/auxiliary/macro-use-warned-against2.rs
new file mode 100644
index 0000000..d11c69f
--- /dev/null
+++ b/src/test/ui/rust-2018/auxiliary/macro-use-warned-against2.rs
@@ -0,0 +1 @@
+// intentionally empty
diff --git a/src/test/ui/rust-2018/auxiliary/remove-extern-crate.rs b/src/test/ui/rust-2018/auxiliary/remove-extern-crate.rs
new file mode 100644
index 0000000..890af68
--- /dev/null
+++ b/src/test/ui/rust-2018/auxiliary/remove-extern-crate.rs
@@ -0,0 +1,9 @@
+#[macro_export]
+macro_rules! foo {
+    () => ()
+}
+
+#[macro_export]
+macro_rules! bar {
+    () => ()
+}
diff --git a/src/test/ui/rust-2018/auxiliary/suggestions-not-always-applicable.rs b/src/test/ui/rust-2018/auxiliary/suggestions-not-always-applicable.rs
new file mode 100644
index 0000000..7472443
--- /dev/null
+++ b/src/test/ui/rust-2018/auxiliary/suggestions-not-always-applicable.rs
@@ -0,0 +1,13 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::*;
+
+#[proc_macro_attribute]
+pub fn foo(_attr: TokenStream, _f: TokenStream) -> TokenStream {
+    "pub fn foo() -> ::Foo { ::Foo }".parse().unwrap()
+}
diff --git a/src/test/ui/rust-2018/auxiliary/trait-import-suggestions.rs b/src/test/ui/rust-2018/auxiliary/trait-import-suggestions.rs
new file mode 100644
index 0000000..d356f32
--- /dev/null
+++ b/src/test/ui/rust-2018/auxiliary/trait-import-suggestions.rs
@@ -0,0 +1,5 @@
+pub trait Baz {
+    fn baz(&self) { }
+}
+
+impl Baz for u32 { }
diff --git a/src/test/ui/rust-2018/dyn-keyword.fixed b/src/test/ui/rust-2018/dyn-keyword.fixed
new file mode 100644
index 0000000..e9cda1a
--- /dev/null
+++ b/src/test/ui/rust-2018/dyn-keyword.fixed
@@ -0,0 +1,10 @@
+// edition:2015
+// run-rustfix
+
+#![allow(unused_variables)]
+#![deny(keyword_idents)]
+
+fn main() {
+    let r#dyn = (); //~ ERROR dyn
+    //~^ WARN hard error in the 2018 edition
+}
diff --git a/src/test/ui/rust-2018/dyn-keyword.rs b/src/test/ui/rust-2018/dyn-keyword.rs
new file mode 100644
index 0000000..bdd3a90
--- /dev/null
+++ b/src/test/ui/rust-2018/dyn-keyword.rs
@@ -0,0 +1,10 @@
+// edition:2015
+// run-rustfix
+
+#![allow(unused_variables)]
+#![deny(keyword_idents)]
+
+fn main() {
+    let dyn = (); //~ ERROR dyn
+    //~^ WARN hard error in the 2018 edition
+}
diff --git a/src/test/ui/rust-2018/dyn-keyword.stderr b/src/test/ui/rust-2018/dyn-keyword.stderr
new file mode 100644
index 0000000..fa79df4
--- /dev/null
+++ b/src/test/ui/rust-2018/dyn-keyword.stderr
@@ -0,0 +1,16 @@
+error: `dyn` is a keyword in the 2018 edition
+  --> $DIR/dyn-keyword.rs:8:9
+   |
+LL |     let dyn = ();
+   |         ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
+   |
+note: lint level defined here
+  --> $DIR/dyn-keyword.rs:5:9
+   |
+LL | #![deny(keyword_idents)]
+   |         ^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rust-2018/dyn-trait-compatibility.rs b/src/test/ui/rust-2018/dyn-trait-compatibility.rs
new file mode 100644
index 0000000..377c85f
--- /dev/null
+++ b/src/test/ui/rust-2018/dyn-trait-compatibility.rs
@@ -0,0 +1,8 @@
+// edition:2018
+
+type A0 = dyn;
+type A1 = dyn::dyn; //~ERROR expected identifier, found keyword `dyn`
+type A2 = dyn<dyn, dyn>; //~ERROR expected identifier, found `<`
+type A3 = dyn<<dyn as dyn>::dyn>;
+
+fn main() {}
diff --git a/src/test/ui/rust-2018/dyn-trait-compatibility.stderr b/src/test/ui/rust-2018/dyn-trait-compatibility.stderr
new file mode 100644
index 0000000..e1f099e
--- /dev/null
+++ b/src/test/ui/rust-2018/dyn-trait-compatibility.stderr
@@ -0,0 +1,18 @@
+error: expected identifier, found keyword `dyn`
+  --> $DIR/dyn-trait-compatibility.rs:4:16
+   |
+LL | type A1 = dyn::dyn;
+   |                ^^^ expected identifier, found keyword
+help: you can escape reserved keywords to use them as identifiers
+   |
+LL | type A1 = dyn::r#dyn;
+   |                ^^^^^
+
+error: expected identifier, found `<`
+  --> $DIR/dyn-trait-compatibility.rs:5:14
+   |
+LL | type A2 = dyn<dyn, dyn>;
+   |              ^ expected identifier
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/rust-2018/edition-lint-fully-qualified-paths.fixed b/src/test/ui/rust-2018/edition-lint-fully-qualified-paths.fixed
new file mode 100644
index 0000000..76fbfa6
--- /dev/null
+++ b/src/test/ui/rust-2018/edition-lint-fully-qualified-paths.fixed
@@ -0,0 +1,27 @@
+// run-rustfix
+
+#![feature(rust_2018_preview, crate_visibility_modifier)]
+#![deny(absolute_paths_not_starting_with_crate)]
+
+mod foo {
+    crate trait Foo {
+        type Bar;
+    }
+
+    crate struct Baz { }
+
+    impl Foo for Baz {
+        type Bar = ();
+    }
+}
+
+
+fn main() {
+    let _: <foo::Baz as crate::foo::Foo>::Bar = ();
+    //~^ ERROR absolute paths must start with
+    //~| this was previously accepted
+
+    let _: <crate::foo::Baz as foo::Foo>::Bar = ();
+    //~^ ERROR absolute paths must start with
+    //~| this was previously accepted
+}
diff --git a/src/test/ui/rust-2018/edition-lint-fully-qualified-paths.rs b/src/test/ui/rust-2018/edition-lint-fully-qualified-paths.rs
new file mode 100644
index 0000000..ace90a18
--- /dev/null
+++ b/src/test/ui/rust-2018/edition-lint-fully-qualified-paths.rs
@@ -0,0 +1,27 @@
+// run-rustfix
+
+#![feature(rust_2018_preview, crate_visibility_modifier)]
+#![deny(absolute_paths_not_starting_with_crate)]
+
+mod foo {
+    crate trait Foo {
+        type Bar;
+    }
+
+    crate struct Baz { }
+
+    impl Foo for Baz {
+        type Bar = ();
+    }
+}
+
+
+fn main() {
+    let _: <foo::Baz as ::foo::Foo>::Bar = ();
+    //~^ ERROR absolute paths must start with
+    //~| this was previously accepted
+
+    let _: <::foo::Baz as foo::Foo>::Bar = ();
+    //~^ ERROR absolute paths must start with
+    //~| this was previously accepted
+}
diff --git a/src/test/ui/rust-2018/edition-lint-fully-qualified-paths.stderr b/src/test/ui/rust-2018/edition-lint-fully-qualified-paths.stderr
new file mode 100644
index 0000000..412ebe1
--- /dev/null
+++ b/src/test/ui/rust-2018/edition-lint-fully-qualified-paths.stderr
@@ -0,0 +1,25 @@
+error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
+  --> $DIR/edition-lint-fully-qualified-paths.rs:20:25
+   |
+LL |     let _: <foo::Baz as ::foo::Foo>::Bar = ();
+   |                         ^^^^^^^^^^ help: use `crate`: `crate::foo::Foo`
+   |
+note: lint level defined here
+  --> $DIR/edition-lint-fully-qualified-paths.rs:4:9
+   |
+LL | #![deny(absolute_paths_not_starting_with_crate)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
+
+error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
+  --> $DIR/edition-lint-fully-qualified-paths.rs:24:13
+   |
+LL |     let _: <::foo::Baz as foo::Foo>::Bar = ();
+   |             ^^^^^^^^^^ help: use `crate`: `crate::foo::Baz`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/rust-2018/edition-lint-infer-outlives-multispan.rs b/src/test/ui/rust-2018/edition-lint-infer-outlives-multispan.rs
new file mode 100644
index 0000000..ca6abdf
--- /dev/null
+++ b/src/test/ui/rust-2018/edition-lint-infer-outlives-multispan.rs
@@ -0,0 +1,75 @@
+#![allow(unused)]
+#![deny(explicit_outlives_requirements)]
+
+use std::fmt::{Debug, Display};
+
+// These examples should live in edition-lint-infer-outlives.rs, but are split
+// into this separate file because they can't be `rustfix`'d (and thus, can't
+// be part of a `run-rustfix` test file) until rust-lang-nursery/rustfix#141
+// is solved
+
+struct TeeOutlivesAyIsDebugBee<'a, 'b, T: 'a + Debug + 'b> {
+    //~^ ERROR outlives requirements can be inferred
+    tee: &'a &'b T
+}
+
+struct TeeWhereOutlivesAyIsDebugBee<'a, 'b, T> where T: 'a + Debug + 'b {
+    //~^ ERROR outlives requirements can be inferred
+    tee: &'a &'b T
+}
+
+struct TeeYooOutlivesAyIsDebugBee<'a, 'b, T, U: 'a + Debug + 'b> {
+    //~^ ERROR outlives requirements can be inferred
+    tee: T,
+    yoo: &'a &'b U
+}
+
+struct TeeOutlivesAyYooBeeIsDebug<'a, 'b, T: 'a, U: 'b + Debug> {
+    //~^ ERROR outlives requirements can be inferred
+    tee: &'a T,
+    yoo: &'b U
+}
+
+struct TeeOutlivesAyYooIsDebugBee<'a, 'b, T: 'a, U: Debug + 'b> {
+    //~^ ERROR outlives requirements can be inferred
+    tee: &'a T,
+    yoo: &'b U
+}
+
+struct TeeOutlivesAyYooWhereBee<'a, 'b, T: 'a, U> where U: 'b {
+    //~^ ERROR outlives requirements can be inferred
+    tee: &'a T,
+    yoo: &'b U
+}
+
+struct TeeYooWhereOutlivesAyIsDebugBee<'a, 'b, T, U> where U: 'a + Debug + 'b {
+    //~^ ERROR outlives requirements can be inferred
+    tee: T,
+    yoo: &'a &'b U
+}
+
+struct TeeOutlivesAyYooWhereBeeIsDebug<'a, 'b, T: 'a, U> where U: 'b + Debug {
+    //~^ ERROR outlives requirements can be inferred
+    tee: &'a T,
+    yoo: &'b U
+}
+
+struct TeeOutlivesAyYooWhereIsDebugBee<'a, 'b, T: 'a, U> where U: Debug + 'b {
+    //~^ ERROR outlives requirements can be inferred
+    tee: &'a T,
+    yoo: &'b U
+}
+
+struct TeeWhereOutlivesAyYooWhereBeeIsDebug<'a, 'b, T, U> where T: 'a, U: 'b + Debug {
+    //~^ ERROR outlives requirements can be inferred
+    tee: &'a T,
+    yoo: &'b U
+}
+
+struct TeeWhereOutlivesAyYooWhereIsDebugBee<'a, 'b, T, U> where T: 'a, U: Debug + 'b {
+    //~^ ERROR outlives requirements can be inferred
+    tee: &'a T,
+    yoo: &'b U
+}
+
+fn main() {}
diff --git a/src/test/ui/rust-2018/edition-lint-infer-outlives-multispan.stderr b/src/test/ui/rust-2018/edition-lint-infer-outlives-multispan.stderr
new file mode 100644
index 0000000..3c65dde
--- /dev/null
+++ b/src/test/ui/rust-2018/edition-lint-infer-outlives-multispan.stderr
@@ -0,0 +1,118 @@
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives-multispan.rs:11:43
+   |
+LL | struct TeeOutlivesAyIsDebugBee<'a, 'b, T: 'a + Debug + 'b> {
+   |                                           ^^^^^     ^^^^^
+   |
+note: lint level defined here
+  --> $DIR/edition-lint-infer-outlives-multispan.rs:2:9
+   |
+LL | #![deny(explicit_outlives_requirements)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: remove these bounds
+   |
+LL | struct TeeOutlivesAyIsDebugBee<'a, 'b, T: Debug> {
+   |                                          --   --
+
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives-multispan.rs:16:57
+   |
+LL | struct TeeWhereOutlivesAyIsDebugBee<'a, 'b, T> where T: 'a + Debug + 'b {
+   |                                                         ^^^^^     ^^^^^
+help: remove these bounds
+   |
+LL | struct TeeWhereOutlivesAyIsDebugBee<'a, 'b, T> where T: Debug {
+   |                                                        --   --
+
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives-multispan.rs:21:49
+   |
+LL | struct TeeYooOutlivesAyIsDebugBee<'a, 'b, T, U: 'a + Debug + 'b> {
+   |                                                 ^^^^^     ^^^^^
+help: remove these bounds
+   |
+LL | struct TeeYooOutlivesAyIsDebugBee<'a, 'b, T, U: Debug> {
+   |                                                --   --
+
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives-multispan.rs:27:44
+   |
+LL | struct TeeOutlivesAyYooBeeIsDebug<'a, 'b, T: 'a, U: 'b + Debug> {
+   |                                            ^^^^     ^^^^^
+help: remove these bounds
+   |
+LL | struct TeeOutlivesAyYooBeeIsDebug<'a, 'b, T, U: Debug> {
+   |                                           --   --
+
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives-multispan.rs:33:44
+   |
+LL | struct TeeOutlivesAyYooIsDebugBee<'a, 'b, T: 'a, U: Debug + 'b> {
+   |                                            ^^^^          ^^^^^
+help: remove these bounds
+   |
+LL | struct TeeOutlivesAyYooIsDebugBee<'a, 'b, T, U: Debug> {
+   |                                           --        --
+
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives-multispan.rs:39:42
+   |
+LL | struct TeeOutlivesAyYooWhereBee<'a, 'b, T: 'a, U> where U: 'b {
+   |                                          ^^^^    ^^^^^^^^^^^^
+help: remove these bounds
+   |
+LL | struct TeeOutlivesAyYooWhereBee<'a, 'b, T, U> {
+   |                                         --  --
+
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives-multispan.rs:45:63
+   |
+LL | struct TeeYooWhereOutlivesAyIsDebugBee<'a, 'b, T, U> where U: 'a + Debug + 'b {
+   |                                                               ^^^^^     ^^^^^
+help: remove these bounds
+   |
+LL | struct TeeYooWhereOutlivesAyIsDebugBee<'a, 'b, T, U> where U: Debug {
+   |                                                              --   --
+
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives-multispan.rs:51:49
+   |
+LL | struct TeeOutlivesAyYooWhereBeeIsDebug<'a, 'b, T: 'a, U> where U: 'b + Debug {
+   |                                                 ^^^^              ^^^^^
+help: remove these bounds
+   |
+LL | struct TeeOutlivesAyYooWhereBeeIsDebug<'a, 'b, T, U> where U: Debug {
+   |                                                --            --
+
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives-multispan.rs:57:49
+   |
+LL | struct TeeOutlivesAyYooWhereIsDebugBee<'a, 'b, T: 'a, U> where U: Debug + 'b {
+   |                                                 ^^^^                   ^^^^^
+help: remove these bounds
+   |
+LL | struct TeeOutlivesAyYooWhereIsDebugBee<'a, 'b, T, U> where U: Debug {
+   |                                                --                 --
+
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives-multispan.rs:63:65
+   |
+LL | struct TeeWhereOutlivesAyYooWhereBeeIsDebug<'a, 'b, T, U> where T: 'a, U: 'b + Debug {
+   |                                                                 ^^^^^^^   ^^^^^
+help: remove these bounds
+   |
+LL | struct TeeWhereOutlivesAyYooWhereBeeIsDebug<'a, 'b, T, U> where U: Debug {
+   |                                                                -- --
+
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives-multispan.rs:69:65
+   |
+LL | struct TeeWhereOutlivesAyYooWhereIsDebugBee<'a, 'b, T, U> where T: 'a, U: Debug + 'b {
+   |                                                                 ^^^^^^^        ^^^^^
+help: remove these bounds
+   |
+LL | struct TeeWhereOutlivesAyYooWhereIsDebugBee<'a, 'b, T, U> where U: Debug {
+   |                                                                --      --
+
+error: aborting due to 11 previous errors
+
diff --git a/src/test/ui/rust-2018/edition-lint-infer-outlives.fixed b/src/test/ui/rust-2018/edition-lint-infer-outlives.fixed
new file mode 100644
index 0000000..eb48933
--- /dev/null
+++ b/src/test/ui/rust-2018/edition-lint-infer-outlives.fixed
@@ -0,0 +1,202 @@
+// run-rustfix
+
+#![allow(unused)]
+#![deny(explicit_outlives_requirements)]
+
+use std::fmt::{Debug, Display};
+
+
+// Programmatically generated examples!
+//
+// Exercise outlives bounds for each of the following parameter/position
+// combinations—
+//
+// • one generic parameter (T) bound inline
+// • one parameter (T) with a where clause
+// • two parameters (T and U), both bound inline
+// • two parameters (T and U), one bound inline, one with a where clause
+// • two parameters (T and U), both with where clauses
+//
+// —and for every permutation of 0, 1, or 2 lifetimes to outlive and 0 or 1
+// trait bounds distributed among said parameters (subject to no where clause
+// being empty and the struct having at least one lifetime).
+
+
+struct TeeOutlivesAy<'a, T> {
+    //~^ ERROR outlives requirements can be inferred
+    tee: &'a T
+}
+
+struct TeeOutlivesAyIsDebug<'a, T: Debug> {
+    //~^ ERROR outlives requirements can be inferred
+    tee: &'a T
+}
+
+struct TeeIsDebugOutlivesAy<'a, T: Debug> {
+    //~^ ERROR outlives requirements can be inferred
+    tee: &'a T
+}
+
+struct TeeOutlivesAyBee<'a, 'b, T> {
+    //~^ ERROR outlives requirements can be inferred
+    tee: &'a &'b T
+}
+
+struct TeeOutlivesAyBeeIsDebug<'a, 'b, T: Debug> {
+    //~^ ERROR outlives requirements can be inferred
+    tee: &'a &'b T
+}
+
+struct TeeIsDebugOutlivesAyBee<'a, 'b, T: Debug> {
+    //~^ ERROR outlives requirements can be inferred
+    tee: &'a &'b T
+}
+
+struct TeeWhereOutlivesAy<'a, T> {
+    //~^ ERROR outlives requirements can be inferred
+    tee: &'a T
+}
+
+struct TeeWhereOutlivesAyIsDebug<'a, T> where T: Debug {
+    //~^ ERROR outlives requirements can be inferred
+    tee: &'a T
+}
+
+struct TeeWhereIsDebugOutlivesAy<'a, T> where T: Debug {
+    //~^ ERROR outlives requirements can be inferred
+    tee: &'a T
+}
+
+struct TeeWhereOutlivesAyBee<'a, 'b, T> {
+    //~^ ERROR outlives requirements can be inferred
+    tee: &'a &'b T
+}
+
+struct TeeWhereOutlivesAyBeeIsDebug<'a, 'b, T> where T: Debug {
+    //~^ ERROR outlives requirements can be inferred
+    tee: &'a &'b T
+}
+
+struct TeeWhereIsDebugOutlivesAyBee<'a, 'b, T> where T: Debug {
+    //~^ ERROR outlives requirements can be inferred
+    tee: &'a &'b T
+}
+
+struct TeeYooOutlivesAy<'a, T, U> {
+    //~^ ERROR outlives requirements can be inferred
+    tee: T,
+    yoo: &'a U
+}
+
+struct TeeYooOutlivesAyIsDebug<'a, T, U: Debug> {
+    //~^ ERROR outlives requirements can be inferred
+    tee: T,
+    yoo: &'a U
+}
+
+struct TeeYooIsDebugOutlivesAy<'a, T, U: Debug> {
+    //~^ ERROR outlives requirements can be inferred
+    tee: T,
+    yoo: &'a U
+}
+
+struct TeeOutlivesAyYooIsDebug<'a, T, U: Debug> {
+    //~^ ERROR outlives requirements can be inferred
+    tee: &'a T,
+    yoo: U
+}
+
+struct TeeYooOutlivesAyBee<'a, 'b, T, U> {
+    //~^ ERROR outlives requirements can be inferred
+    tee: T,
+    yoo: &'a &'b U
+}
+
+struct TeeYooOutlivesAyBeeIsDebug<'a, 'b, T, U: Debug> {
+    //~^ ERROR outlives requirements can be inferred
+    tee: T,
+    yoo: &'a &'b U
+}
+
+struct TeeYooIsDebugOutlivesAyBee<'a, 'b, T, U: Debug> {
+    //~^ ERROR outlives requirements can be inferred
+    tee: T,
+    yoo: &'a &'b U
+}
+
+struct TeeOutlivesAyBeeYooIsDebug<'a, 'b, T, U: Debug> {
+    //~^ ERROR outlives requirements can be inferred
+    tee: &'a &'b T,
+    yoo: U
+}
+
+struct TeeYooWhereOutlivesAy<'a, T, U> {
+    //~^ ERROR outlives requirements can be inferred
+    tee: T,
+    yoo: &'a U
+}
+
+struct TeeYooWhereOutlivesAyIsDebug<'a, T, U> where U: Debug {
+    //~^ ERROR outlives requirements can be inferred
+    tee: T,
+    yoo: &'a U
+}
+
+struct TeeYooWhereIsDebugOutlivesAy<'a, T, U> where U: Debug {
+    //~^ ERROR outlives requirements can be inferred
+    tee: T,
+    yoo: &'a U
+}
+
+struct TeeOutlivesAyYooWhereIsDebug<'a, T, U> where U: Debug {
+    //~^ ERROR outlives requirements can be inferred
+    tee: &'a T,
+    yoo: U
+}
+
+struct TeeYooWhereOutlivesAyBee<'a, 'b, T, U> {
+    //~^ ERROR outlives requirements can be inferred
+    tee: T,
+    yoo: &'a &'b U
+}
+
+struct TeeYooWhereOutlivesAyBeeIsDebug<'a, 'b, T, U> where U: Debug {
+    //~^ ERROR outlives requirements can be inferred
+    tee: T,
+    yoo: &'a &'b U
+}
+
+struct TeeYooWhereIsDebugOutlivesAyBee<'a, 'b, T, U> where U: Debug {
+    //~^ ERROR outlives requirements can be inferred
+    tee: T,
+    yoo: &'a &'b U
+}
+
+struct TeeOutlivesAyBeeYooWhereIsDebug<'a, 'b, T, U> where U: Debug {
+    //~^ ERROR outlives requirements can be inferred
+    tee: &'a &'b T,
+    yoo: U
+}
+
+struct TeeWhereOutlivesAyYooWhereIsDebug<'a, T, U> where U: Debug {
+    //~^ ERROR outlives requirements can be inferred
+    tee: &'a T,
+    yoo: U
+}
+
+struct TeeWhereOutlivesAyBeeYooWhereIsDebug<'a, 'b, T, U> where U: Debug {
+    //~^ ERROR outlives requirements can be inferred
+    tee: &'a &'b T,
+    yoo: U
+}
+
+
+// But outlives inference for 'static lifetimes is under a separate
+// feature-gate for now
+// (https://github.com/rust-lang/rust/issues/44493#issuecomment-407846046).
+struct StaticRef<T: 'static> {
+    field: &'static T
+}
+
+
+fn main() {}
diff --git a/src/test/ui/rust-2018/edition-lint-infer-outlives.rs b/src/test/ui/rust-2018/edition-lint-infer-outlives.rs
new file mode 100644
index 0000000..fd31341
--- /dev/null
+++ b/src/test/ui/rust-2018/edition-lint-infer-outlives.rs
@@ -0,0 +1,202 @@
+// run-rustfix
+
+#![allow(unused)]
+#![deny(explicit_outlives_requirements)]
+
+use std::fmt::{Debug, Display};
+
+
+// Programmatically generated examples!
+//
+// Exercise outlives bounds for each of the following parameter/position
+// combinations—
+//
+// • one generic parameter (T) bound inline
+// • one parameter (T) with a where clause
+// • two parameters (T and U), both bound inline
+// • two parameters (T and U), one bound inline, one with a where clause
+// • two parameters (T and U), both with where clauses
+//
+// —and for every permutation of 0, 1, or 2 lifetimes to outlive and 0 or 1
+// trait bounds distributed among said parameters (subject to no where clause
+// being empty and the struct having at least one lifetime).
+
+
+struct TeeOutlivesAy<'a, T: 'a> {
+    //~^ ERROR outlives requirements can be inferred
+    tee: &'a T
+}
+
+struct TeeOutlivesAyIsDebug<'a, T: 'a + Debug> {
+    //~^ ERROR outlives requirements can be inferred
+    tee: &'a T
+}
+
+struct TeeIsDebugOutlivesAy<'a, T: Debug + 'a> {
+    //~^ ERROR outlives requirements can be inferred
+    tee: &'a T
+}
+
+struct TeeOutlivesAyBee<'a, 'b, T: 'a + 'b> {
+    //~^ ERROR outlives requirements can be inferred
+    tee: &'a &'b T
+}
+
+struct TeeOutlivesAyBeeIsDebug<'a, 'b, T: 'a + 'b + Debug> {
+    //~^ ERROR outlives requirements can be inferred
+    tee: &'a &'b T
+}
+
+struct TeeIsDebugOutlivesAyBee<'a, 'b, T: Debug + 'a + 'b> {
+    //~^ ERROR outlives requirements can be inferred
+    tee: &'a &'b T
+}
+
+struct TeeWhereOutlivesAy<'a, T> where T: 'a {
+    //~^ ERROR outlives requirements can be inferred
+    tee: &'a T
+}
+
+struct TeeWhereOutlivesAyIsDebug<'a, T> where T: 'a + Debug {
+    //~^ ERROR outlives requirements can be inferred
+    tee: &'a T
+}
+
+struct TeeWhereIsDebugOutlivesAy<'a, T> where T: Debug + 'a {
+    //~^ ERROR outlives requirements can be inferred
+    tee: &'a T
+}
+
+struct TeeWhereOutlivesAyBee<'a, 'b, T> where T: 'a + 'b {
+    //~^ ERROR outlives requirements can be inferred
+    tee: &'a &'b T
+}
+
+struct TeeWhereOutlivesAyBeeIsDebug<'a, 'b, T> where T: 'a + 'b + Debug {
+    //~^ ERROR outlives requirements can be inferred
+    tee: &'a &'b T
+}
+
+struct TeeWhereIsDebugOutlivesAyBee<'a, 'b, T> where T: Debug + 'a + 'b {
+    //~^ ERROR outlives requirements can be inferred
+    tee: &'a &'b T
+}
+
+struct TeeYooOutlivesAy<'a, T, U: 'a> {
+    //~^ ERROR outlives requirements can be inferred
+    tee: T,
+    yoo: &'a U
+}
+
+struct TeeYooOutlivesAyIsDebug<'a, T, U: 'a + Debug> {
+    //~^ ERROR outlives requirements can be inferred
+    tee: T,
+    yoo: &'a U
+}
+
+struct TeeYooIsDebugOutlivesAy<'a, T, U: Debug + 'a> {
+    //~^ ERROR outlives requirements can be inferred
+    tee: T,
+    yoo: &'a U
+}
+
+struct TeeOutlivesAyYooIsDebug<'a, T: 'a, U: Debug> {
+    //~^ ERROR outlives requirements can be inferred
+    tee: &'a T,
+    yoo: U
+}
+
+struct TeeYooOutlivesAyBee<'a, 'b, T, U: 'a + 'b> {
+    //~^ ERROR outlives requirements can be inferred
+    tee: T,
+    yoo: &'a &'b U
+}
+
+struct TeeYooOutlivesAyBeeIsDebug<'a, 'b, T, U: 'a + 'b + Debug> {
+    //~^ ERROR outlives requirements can be inferred
+    tee: T,
+    yoo: &'a &'b U
+}
+
+struct TeeYooIsDebugOutlivesAyBee<'a, 'b, T, U: Debug + 'a + 'b> {
+    //~^ ERROR outlives requirements can be inferred
+    tee: T,
+    yoo: &'a &'b U
+}
+
+struct TeeOutlivesAyBeeYooIsDebug<'a, 'b, T: 'a + 'b, U: Debug> {
+    //~^ ERROR outlives requirements can be inferred
+    tee: &'a &'b T,
+    yoo: U
+}
+
+struct TeeYooWhereOutlivesAy<'a, T, U> where U: 'a {
+    //~^ ERROR outlives requirements can be inferred
+    tee: T,
+    yoo: &'a U
+}
+
+struct TeeYooWhereOutlivesAyIsDebug<'a, T, U> where U: 'a + Debug {
+    //~^ ERROR outlives requirements can be inferred
+    tee: T,
+    yoo: &'a U
+}
+
+struct TeeYooWhereIsDebugOutlivesAy<'a, T, U> where U: Debug + 'a {
+    //~^ ERROR outlives requirements can be inferred
+    tee: T,
+    yoo: &'a U
+}
+
+struct TeeOutlivesAyYooWhereIsDebug<'a, T: 'a, U> where U: Debug {
+    //~^ ERROR outlives requirements can be inferred
+    tee: &'a T,
+    yoo: U
+}
+
+struct TeeYooWhereOutlivesAyBee<'a, 'b, T, U> where U: 'a + 'b {
+    //~^ ERROR outlives requirements can be inferred
+    tee: T,
+    yoo: &'a &'b U
+}
+
+struct TeeYooWhereOutlivesAyBeeIsDebug<'a, 'b, T, U> where U: 'a + 'b + Debug {
+    //~^ ERROR outlives requirements can be inferred
+    tee: T,
+    yoo: &'a &'b U
+}
+
+struct TeeYooWhereIsDebugOutlivesAyBee<'a, 'b, T, U> where U: Debug + 'a + 'b {
+    //~^ ERROR outlives requirements can be inferred
+    tee: T,
+    yoo: &'a &'b U
+}
+
+struct TeeOutlivesAyBeeYooWhereIsDebug<'a, 'b, T: 'a + 'b, U> where U: Debug {
+    //~^ ERROR outlives requirements can be inferred
+    tee: &'a &'b T,
+    yoo: U
+}
+
+struct TeeWhereOutlivesAyYooWhereIsDebug<'a, T, U> where T: 'a, U: Debug {
+    //~^ ERROR outlives requirements can be inferred
+    tee: &'a T,
+    yoo: U
+}
+
+struct TeeWhereOutlivesAyBeeYooWhereIsDebug<'a, 'b, T, U> where T: 'a + 'b, U: Debug {
+    //~^ ERROR outlives requirements can be inferred
+    tee: &'a &'b T,
+    yoo: U
+}
+
+
+// But outlives inference for 'static lifetimes is under a separate
+// feature-gate for now
+// (https://github.com/rust-lang/rust/issues/44493#issuecomment-407846046).
+struct StaticRef<T: 'static> {
+    field: &'static T
+}
+
+
+fn main() {}
diff --git a/src/test/ui/rust-2018/edition-lint-infer-outlives.stderr b/src/test/ui/rust-2018/edition-lint-infer-outlives.stderr
new file mode 100644
index 0000000..8b95798
--- /dev/null
+++ b/src/test/ui/rust-2018/edition-lint-infer-outlives.stderr
@@ -0,0 +1,188 @@
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives.rs:25:27
+   |
+LL | struct TeeOutlivesAy<'a, T: 'a> {
+   |                           ^^^^ help: remove this bound
+   |
+note: lint level defined here
+  --> $DIR/edition-lint-infer-outlives.rs:4:9
+   |
+LL | #![deny(explicit_outlives_requirements)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives.rs:30:36
+   |
+LL | struct TeeOutlivesAyIsDebug<'a, T: 'a + Debug> {
+   |                                    ^^^^^ help: remove this bound
+
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives.rs:35:41
+   |
+LL | struct TeeIsDebugOutlivesAy<'a, T: Debug + 'a> {
+   |                                         ^^^^^ help: remove this bound
+
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives.rs:40:34
+   |
+LL | struct TeeOutlivesAyBee<'a, 'b, T: 'a + 'b> {
+   |                                  ^^^^^^^^^ help: remove these bounds
+
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives.rs:45:43
+   |
+LL | struct TeeOutlivesAyBeeIsDebug<'a, 'b, T: 'a + 'b + Debug> {
+   |                                           ^^^^^^^^^^ help: remove these bounds
+
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives.rs:50:48
+   |
+LL | struct TeeIsDebugOutlivesAyBee<'a, 'b, T: Debug + 'a + 'b> {
+   |                                                ^^^^^^^^^^ help: remove these bounds
+
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives.rs:55:33
+   |
+LL | struct TeeWhereOutlivesAy<'a, T> where T: 'a {
+   |                                 ^^^^^^^^^^^^ help: remove this bound
+
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives.rs:60:50
+   |
+LL | struct TeeWhereOutlivesAyIsDebug<'a, T> where T: 'a + Debug {
+   |                                                  ^^^^^ help: remove this bound
+
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives.rs:65:55
+   |
+LL | struct TeeWhereIsDebugOutlivesAy<'a, T> where T: Debug + 'a {
+   |                                                       ^^^^^ help: remove this bound
+
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives.rs:70:40
+   |
+LL | struct TeeWhereOutlivesAyBee<'a, 'b, T> where T: 'a + 'b {
+   |                                        ^^^^^^^^^^^^^^^^^ help: remove these bounds
+
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives.rs:75:57
+   |
+LL | struct TeeWhereOutlivesAyBeeIsDebug<'a, 'b, T> where T: 'a + 'b + Debug {
+   |                                                         ^^^^^^^^^^ help: remove these bounds
+
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives.rs:80:62
+   |
+LL | struct TeeWhereIsDebugOutlivesAyBee<'a, 'b, T> where T: Debug + 'a + 'b {
+   |                                                              ^^^^^^^^^^ help: remove these bounds
+
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives.rs:85:33
+   |
+LL | struct TeeYooOutlivesAy<'a, T, U: 'a> {
+   |                                 ^^^^ help: remove this bound
+
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives.rs:91:42
+   |
+LL | struct TeeYooOutlivesAyIsDebug<'a, T, U: 'a + Debug> {
+   |                                          ^^^^^ help: remove this bound
+
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives.rs:97:47
+   |
+LL | struct TeeYooIsDebugOutlivesAy<'a, T, U: Debug + 'a> {
+   |                                               ^^^^^ help: remove this bound
+
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives.rs:103:37
+   |
+LL | struct TeeOutlivesAyYooIsDebug<'a, T: 'a, U: Debug> {
+   |                                     ^^^^ help: remove this bound
+
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives.rs:109:40
+   |
+LL | struct TeeYooOutlivesAyBee<'a, 'b, T, U: 'a + 'b> {
+   |                                        ^^^^^^^^^ help: remove these bounds
+
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives.rs:115:49
+   |
+LL | struct TeeYooOutlivesAyBeeIsDebug<'a, 'b, T, U: 'a + 'b + Debug> {
+   |                                                 ^^^^^^^^^^ help: remove these bounds
+
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives.rs:121:54
+   |
+LL | struct TeeYooIsDebugOutlivesAyBee<'a, 'b, T, U: Debug + 'a + 'b> {
+   |                                                      ^^^^^^^^^^ help: remove these bounds
+
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives.rs:127:44
+   |
+LL | struct TeeOutlivesAyBeeYooIsDebug<'a, 'b, T: 'a + 'b, U: Debug> {
+   |                                            ^^^^^^^^^ help: remove these bounds
+
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives.rs:133:39
+   |
+LL | struct TeeYooWhereOutlivesAy<'a, T, U> where U: 'a {
+   |                                       ^^^^^^^^^^^^ help: remove this bound
+
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives.rs:139:56
+   |
+LL | struct TeeYooWhereOutlivesAyIsDebug<'a, T, U> where U: 'a + Debug {
+   |                                                        ^^^^^ help: remove this bound
+
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives.rs:145:61
+   |
+LL | struct TeeYooWhereIsDebugOutlivesAy<'a, T, U> where U: Debug + 'a {
+   |                                                             ^^^^^ help: remove this bound
+
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives.rs:151:42
+   |
+LL | struct TeeOutlivesAyYooWhereIsDebug<'a, T: 'a, U> where U: Debug {
+   |                                          ^^^^ help: remove this bound
+
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives.rs:157:46
+   |
+LL | struct TeeYooWhereOutlivesAyBee<'a, 'b, T, U> where U: 'a + 'b {
+   |                                              ^^^^^^^^^^^^^^^^^ help: remove these bounds
+
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives.rs:163:63
+   |
+LL | struct TeeYooWhereOutlivesAyBeeIsDebug<'a, 'b, T, U> where U: 'a + 'b + Debug {
+   |                                                               ^^^^^^^^^^ help: remove these bounds
+
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives.rs:169:68
+   |
+LL | struct TeeYooWhereIsDebugOutlivesAyBee<'a, 'b, T, U> where U: Debug + 'a + 'b {
+   |                                                                    ^^^^^^^^^^ help: remove these bounds
+
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives.rs:175:49
+   |
+LL | struct TeeOutlivesAyBeeYooWhereIsDebug<'a, 'b, T: 'a + 'b, U> where U: Debug {
+   |                                                 ^^^^^^^^^ help: remove these bounds
+
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives.rs:181:58
+   |
+LL | struct TeeWhereOutlivesAyYooWhereIsDebug<'a, T, U> where T: 'a, U: Debug {
+   |                                                          ^^^^^^^ help: remove this bound
+
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives.rs:187:65
+   |
+LL | struct TeeWhereOutlivesAyBeeYooWhereIsDebug<'a, 'b, T, U> where T: 'a + 'b, U: Debug {
+   |                                                                 ^^^^^^^^^^^^ help: remove these bounds
+
+error: aborting due to 30 previous errors
+
diff --git a/src/test/ui/rust-2018/edition-lint-nested-empty-paths.fixed b/src/test/ui/rust-2018/edition-lint-nested-empty-paths.fixed
new file mode 100644
index 0000000..77478e8
--- /dev/null
+++ b/src/test/ui/rust-2018/edition-lint-nested-empty-paths.fixed
@@ -0,0 +1,30 @@
+// run-rustfix
+
+#![feature(rust_2018_preview, crate_visibility_modifier)]
+#![deny(absolute_paths_not_starting_with_crate)]
+#![allow(unused_imports)]
+#![allow(dead_code)]
+
+crate mod foo {
+    crate mod bar {
+        crate mod baz { }
+        crate mod baz1 { }
+
+        crate struct XX;
+    }
+}
+
+use crate::foo::{bar::{baz::{}}};
+//~^ ERROR absolute paths must start with
+//~| WARN this was previously accepted
+
+use crate::foo::{bar::{XX, baz::{}}};
+//~^ ERROR absolute paths must start with
+//~| WARN this was previously accepted
+
+use crate::foo::{bar::{baz::{}, baz1::{}}};
+//~^ ERROR absolute paths must start with
+//~| WARN this was previously accepted
+
+fn main() {
+}
diff --git a/src/test/ui/rust-2018/edition-lint-nested-empty-paths.rs b/src/test/ui/rust-2018/edition-lint-nested-empty-paths.rs
new file mode 100644
index 0000000..69bd4e3
--- /dev/null
+++ b/src/test/ui/rust-2018/edition-lint-nested-empty-paths.rs
@@ -0,0 +1,30 @@
+// run-rustfix
+
+#![feature(rust_2018_preview, crate_visibility_modifier)]
+#![deny(absolute_paths_not_starting_with_crate)]
+#![allow(unused_imports)]
+#![allow(dead_code)]
+
+crate mod foo {
+    crate mod bar {
+        crate mod baz { }
+        crate mod baz1 { }
+
+        crate struct XX;
+    }
+}
+
+use foo::{bar::{baz::{}}};
+//~^ ERROR absolute paths must start with
+//~| WARN this was previously accepted
+
+use foo::{bar::{XX, baz::{}}};
+//~^ ERROR absolute paths must start with
+//~| WARN this was previously accepted
+
+use foo::{bar::{baz::{}, baz1::{}}};
+//~^ ERROR absolute paths must start with
+//~| WARN this was previously accepted
+
+fn main() {
+}
diff --git a/src/test/ui/rust-2018/edition-lint-nested-empty-paths.stderr b/src/test/ui/rust-2018/edition-lint-nested-empty-paths.stderr
new file mode 100644
index 0000000..742203e
--- /dev/null
+++ b/src/test/ui/rust-2018/edition-lint-nested-empty-paths.stderr
@@ -0,0 +1,34 @@
+error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
+  --> $DIR/edition-lint-nested-empty-paths.rs:17:5
+   |
+LL | use foo::{bar::{baz::{}}};
+   |     ^^^^^^^^^^^^^^^^^^^^^ help: use `crate`: `crate::foo::{bar::{baz::{}}}`
+   |
+note: lint level defined here
+  --> $DIR/edition-lint-nested-empty-paths.rs:4:9
+   |
+LL | #![deny(absolute_paths_not_starting_with_crate)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
+
+error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
+  --> $DIR/edition-lint-nested-empty-paths.rs:21:5
+   |
+LL | use foo::{bar::{XX, baz::{}}};
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `crate`: `crate::foo::{bar::{XX, baz::{}}}`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
+
+error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
+  --> $DIR/edition-lint-nested-empty-paths.rs:25:5
+   |
+LL | use foo::{bar::{baz::{}, baz1::{}}};
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `crate`: `crate::foo::{bar::{baz::{}, baz1::{}}}`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/rust-2018/edition-lint-nested-paths.fixed b/src/test/ui/rust-2018/edition-lint-nested-paths.fixed
new file mode 100644
index 0000000..da7524a
--- /dev/null
+++ b/src/test/ui/rust-2018/edition-lint-nested-paths.fixed
@@ -0,0 +1,27 @@
+// run-rustfix
+
+#![feature(rust_2018_preview, crate_visibility_modifier)]
+#![deny(absolute_paths_not_starting_with_crate)]
+
+use crate::foo::{a, b};
+//~^ ERROR absolute paths must start with
+//~| this was previously accepted
+
+mod foo {
+    crate fn a() {}
+    crate fn b() {}
+    crate fn c() {}
+}
+
+fn main() {
+    a();
+    b();
+
+    {
+        use crate::foo::{self as x, c};
+        //~^ ERROR absolute paths must start with
+        //~| this was previously accepted
+        x::a();
+        c();
+    }
+}
diff --git a/src/test/ui/rust-2018/edition-lint-nested-paths.rs b/src/test/ui/rust-2018/edition-lint-nested-paths.rs
new file mode 100644
index 0000000..e13b7d0
--- /dev/null
+++ b/src/test/ui/rust-2018/edition-lint-nested-paths.rs
@@ -0,0 +1,27 @@
+// run-rustfix
+
+#![feature(rust_2018_preview, crate_visibility_modifier)]
+#![deny(absolute_paths_not_starting_with_crate)]
+
+use foo::{a, b};
+//~^ ERROR absolute paths must start with
+//~| this was previously accepted
+
+mod foo {
+    crate fn a() {}
+    crate fn b() {}
+    crate fn c() {}
+}
+
+fn main() {
+    a();
+    b();
+
+    {
+        use foo::{self as x, c};
+        //~^ ERROR absolute paths must start with
+        //~| this was previously accepted
+        x::a();
+        c();
+    }
+}
diff --git a/src/test/ui/rust-2018/edition-lint-nested-paths.stderr b/src/test/ui/rust-2018/edition-lint-nested-paths.stderr
new file mode 100644
index 0000000..6cd8e9a
--- /dev/null
+++ b/src/test/ui/rust-2018/edition-lint-nested-paths.stderr
@@ -0,0 +1,25 @@
+error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
+  --> $DIR/edition-lint-nested-paths.rs:6:5
+   |
+LL | use foo::{a, b};
+   |     ^^^^^^^^^^^ help: use `crate`: `crate::foo::{a, b}`
+   |
+note: lint level defined here
+  --> $DIR/edition-lint-nested-paths.rs:4:9
+   |
+LL | #![deny(absolute_paths_not_starting_with_crate)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
+
+error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
+  --> $DIR/edition-lint-nested-paths.rs:21:13
+   |
+LL |         use foo::{self as x, c};
+   |             ^^^^^^^^^^^^^^^^^^^ help: use `crate`: `crate::foo::{self as x, c}`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/rust-2018/edition-lint-paths-2018.rs b/src/test/ui/rust-2018/edition-lint-paths-2018.rs
new file mode 100644
index 0000000..09b31be
--- /dev/null
+++ b/src/test/ui/rust-2018/edition-lint-paths-2018.rs
@@ -0,0 +1,10 @@
+// compile-pass
+// edition:2018
+// compile-flags:--extern edition_lint_paths
+// aux-build:edition-lint-paths.rs
+
+#![deny(absolute_paths_not_starting_with_crate)]
+
+edition_lint_paths::macro_2015!(); // OK
+
+fn main() {}
diff --git a/src/test/ui/rust-2018/edition-lint-paths.fixed b/src/test/ui/rust-2018/edition-lint-paths.fixed
new file mode 100644
index 0000000..de16291
--- /dev/null
+++ b/src/test/ui/rust-2018/edition-lint-paths.fixed
@@ -0,0 +1,71 @@
+// aux-build:edition-lint-paths.rs
+// run-rustfix
+
+#![feature(rust_2018_preview)]
+#![deny(absolute_paths_not_starting_with_crate)]
+#![allow(unused)]
+
+extern crate edition_lint_paths;
+
+pub mod foo {
+    use edition_lint_paths;
+    use crate::bar::Bar;
+    //~^ ERROR absolute
+    //~| WARN this was previously accepted
+    use super::bar::Bar2;
+    use crate::bar::Bar3;
+
+    use crate::bar;
+    //~^ ERROR absolute
+    //~| WARN this was previously accepted
+    use crate::{bar as something_else};
+
+    use crate::{Bar as SomethingElse, main};
+    //~^ ERROR absolute
+    //~| WARN this was previously accepted
+
+    use crate::{Bar as SomethingElse2, main as another_main};
+
+    pub fn test() {
+    }
+
+    pub trait SomeTrait { }
+}
+
+use crate::bar::Bar;
+//~^ ERROR absolute
+//~| WARN this was previously accepted
+
+pub mod bar {
+    use edition_lint_paths as foo;
+    pub struct Bar;
+    pub type Bar2 = Bar;
+    pub type Bar3 = Bar;
+}
+
+mod baz {
+    use crate::*;
+    //~^ ERROR absolute
+    //~| WARN this was previously accepted
+}
+
+impl crate::foo::SomeTrait for u32 { }
+//~^ ERROR absolute
+//~| WARN this was previously accepted
+
+fn main() {
+    let x = crate::bar::Bar;
+    //~^ ERROR absolute
+    //~| WARN this was previously accepted
+    let x = bar::Bar;
+    let x = crate::bar::Bar;
+    let x = self::bar::Bar;
+    foo::test();
+
+    {
+        use edition_lint_paths as bar;
+        edition_lint_paths::foo();
+        bar::foo();
+        ::edition_lint_paths::foo();
+    }
+}
diff --git a/src/test/ui/rust-2018/edition-lint-paths.rs b/src/test/ui/rust-2018/edition-lint-paths.rs
new file mode 100644
index 0000000..c5b4be5
--- /dev/null
+++ b/src/test/ui/rust-2018/edition-lint-paths.rs
@@ -0,0 +1,71 @@
+// aux-build:edition-lint-paths.rs
+// run-rustfix
+
+#![feature(rust_2018_preview)]
+#![deny(absolute_paths_not_starting_with_crate)]
+#![allow(unused)]
+
+extern crate edition_lint_paths;
+
+pub mod foo {
+    use edition_lint_paths;
+    use ::bar::Bar;
+    //~^ ERROR absolute
+    //~| WARN this was previously accepted
+    use super::bar::Bar2;
+    use crate::bar::Bar3;
+
+    use bar;
+    //~^ ERROR absolute
+    //~| WARN this was previously accepted
+    use crate::{bar as something_else};
+
+    use {Bar as SomethingElse, main};
+    //~^ ERROR absolute
+    //~| WARN this was previously accepted
+
+    use crate::{Bar as SomethingElse2, main as another_main};
+
+    pub fn test() {
+    }
+
+    pub trait SomeTrait { }
+}
+
+use bar::Bar;
+//~^ ERROR absolute
+//~| WARN this was previously accepted
+
+pub mod bar {
+    use edition_lint_paths as foo;
+    pub struct Bar;
+    pub type Bar2 = Bar;
+    pub type Bar3 = Bar;
+}
+
+mod baz {
+    use *;
+    //~^ ERROR absolute
+    //~| WARN this was previously accepted
+}
+
+impl ::foo::SomeTrait for u32 { }
+//~^ ERROR absolute
+//~| WARN this was previously accepted
+
+fn main() {
+    let x = ::bar::Bar;
+    //~^ ERROR absolute
+    //~| WARN this was previously accepted
+    let x = bar::Bar;
+    let x = crate::bar::Bar;
+    let x = self::bar::Bar;
+    foo::test();
+
+    {
+        use edition_lint_paths as bar;
+        edition_lint_paths::foo();
+        bar::foo();
+        ::edition_lint_paths::foo();
+    }
+}
diff --git a/src/test/ui/rust-2018/edition-lint-paths.stderr b/src/test/ui/rust-2018/edition-lint-paths.stderr
new file mode 100644
index 0000000..4f1904a
--- /dev/null
+++ b/src/test/ui/rust-2018/edition-lint-paths.stderr
@@ -0,0 +1,70 @@
+error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
+  --> $DIR/edition-lint-paths.rs:12:9
+   |
+LL |     use ::bar::Bar;
+   |         ^^^^^^^^^^ help: use `crate`: `crate::bar::Bar`
+   |
+note: lint level defined here
+  --> $DIR/edition-lint-paths.rs:5:9
+   |
+LL | #![deny(absolute_paths_not_starting_with_crate)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
+
+error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
+  --> $DIR/edition-lint-paths.rs:18:9
+   |
+LL |     use bar;
+   |         ^^^ help: use `crate`: `crate::bar`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
+
+error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
+  --> $DIR/edition-lint-paths.rs:23:9
+   |
+LL |     use {Bar as SomethingElse, main};
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `crate`: `crate::{Bar as SomethingElse, main}`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
+
+error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
+  --> $DIR/edition-lint-paths.rs:35:5
+   |
+LL | use bar::Bar;
+   |     ^^^^^^^^ help: use `crate`: `crate::bar::Bar`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
+
+error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
+  --> $DIR/edition-lint-paths.rs:47:9
+   |
+LL |     use *;
+   |         ^ help: use `crate`: `crate::*`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
+
+error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
+  --> $DIR/edition-lint-paths.rs:52:6
+   |
+LL | impl ::foo::SomeTrait for u32 { }
+   |      ^^^^^^^^^^^^^^^^ help: use `crate`: `crate::foo::SomeTrait`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
+
+error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
+  --> $DIR/edition-lint-paths.rs:57:13
+   |
+LL |     let x = ::bar::Bar;
+   |             ^^^^^^^^^^ help: use `crate`: `crate::bar::Bar`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
+
+error: aborting due to 7 previous errors
+
diff --git a/src/test/ui/rust-2018/edition-lint-uninferable-outlives.rs b/src/test/ui/rust-2018/edition-lint-uninferable-outlives.rs
new file mode 100644
index 0000000..323c6e1
--- /dev/null
+++ b/src/test/ui/rust-2018/edition-lint-uninferable-outlives.rs
@@ -0,0 +1,30 @@
+// compile-pass
+
+#![allow(unused)]
+#![deny(explicit_outlives_requirements)]
+
+// A case where we can't infer the outlives requirement. Example copied from
+// RFC 2093.
+// (https://rust-lang.github.io/rfcs/2093-infer-outlives.html
+// #where-explicit-annotations-would-still-be-required)
+
+
+trait MakeRef<'a> {
+    type Type;
+}
+
+impl<'a, T> MakeRef<'a> for Vec<T>
+    where T: 'a  // still required
+{
+    type Type = &'a T;
+}
+
+
+struct Foo<'a, T>
+    where T: 'a  // still required, not inferred from `field`
+{
+    field: <Vec<T> as MakeRef<'a>>::Type
+}
+
+
+fn main() {}
diff --git a/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.fixed b/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.fixed
new file mode 100644
index 0000000..a9f4a1e
--- /dev/null
+++ b/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.fixed
@@ -0,0 +1,26 @@
+// aux-build:edition-lint-paths.rs
+// run-rustfix
+// compile-flags:--extern edition_lint_paths
+// edition:2018
+
+// The "normal case". Ideally we would remove the `extern crate` here,
+// but we don't.
+
+#![deny(rust_2018_idioms)]
+#![allow(dead_code)]
+
+
+//~^ ERROR unused extern crate
+
+use edition_lint_paths as bar;
+//~^ ERROR `extern crate` is not idiomatic in the new edition
+
+fn main() {
+    // This is not considered to *use* the `extern crate` in Rust 2018:
+    use edition_lint_paths::foo;
+    foo();
+
+    // But this should be a use of the (renamed) crate:
+    crate::bar::foo();
+}
+
diff --git a/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.rs b/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.rs
new file mode 100644
index 0000000..02e3e83
--- /dev/null
+++ b/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.rs
@@ -0,0 +1,26 @@
+// aux-build:edition-lint-paths.rs
+// run-rustfix
+// compile-flags:--extern edition_lint_paths
+// edition:2018
+
+// The "normal case". Ideally we would remove the `extern crate` here,
+// but we don't.
+
+#![deny(rust_2018_idioms)]
+#![allow(dead_code)]
+
+extern crate edition_lint_paths;
+//~^ ERROR unused extern crate
+
+extern crate edition_lint_paths as bar;
+//~^ ERROR `extern crate` is not idiomatic in the new edition
+
+fn main() {
+    // This is not considered to *use* the `extern crate` in Rust 2018:
+    use edition_lint_paths::foo;
+    foo();
+
+    // But this should be a use of the (renamed) crate:
+    crate::bar::foo();
+}
+
diff --git a/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.stderr b/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.stderr
new file mode 100644
index 0000000..f3f9193
--- /dev/null
+++ b/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.stderr
@@ -0,0 +1,21 @@
+error: unused extern crate
+  --> $DIR/extern-crate-idiomatic-in-2018.rs:12:1
+   |
+LL | extern crate edition_lint_paths;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
+   |
+note: lint level defined here
+  --> $DIR/extern-crate-idiomatic-in-2018.rs:9:9
+   |
+LL | #![deny(rust_2018_idioms)]
+   |         ^^^^^^^^^^^^^^^^
+   = note: #[deny(unused_extern_crates)] implied by #[deny(rust_2018_idioms)]
+
+error: `extern crate` is not idiomatic in the new edition
+  --> $DIR/extern-crate-idiomatic-in-2018.rs:15:1
+   |
+LL | extern crate edition_lint_paths as bar;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `use`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/rust-2018/extern-crate-idiomatic.fixed b/src/test/ui/rust-2018/extern-crate-idiomatic.fixed
new file mode 100644
index 0000000..38dddf3
--- /dev/null
+++ b/src/test/ui/rust-2018/extern-crate-idiomatic.fixed
@@ -0,0 +1,19 @@
+// run-pass
+// aux-build:edition-lint-paths.rs
+// compile-flags:--extern edition_lint_paths
+// run-rustfix
+
+// The "normal case". Ideally we would remove the `extern crate` here,
+// but we don't.
+
+#![feature(rust_2018_preview)]
+#![deny(absolute_paths_not_starting_with_crate)]
+
+extern crate edition_lint_paths;
+
+use edition_lint_paths::foo;
+
+fn main() {
+    foo();
+}
+
diff --git a/src/test/ui/rust-2018/extern-crate-idiomatic.rs b/src/test/ui/rust-2018/extern-crate-idiomatic.rs
new file mode 100644
index 0000000..38dddf3
--- /dev/null
+++ b/src/test/ui/rust-2018/extern-crate-idiomatic.rs
@@ -0,0 +1,19 @@
+// run-pass
+// aux-build:edition-lint-paths.rs
+// compile-flags:--extern edition_lint_paths
+// run-rustfix
+
+// The "normal case". Ideally we would remove the `extern crate` here,
+// but we don't.
+
+#![feature(rust_2018_preview)]
+#![deny(absolute_paths_not_starting_with_crate)]
+
+extern crate edition_lint_paths;
+
+use edition_lint_paths::foo;
+
+fn main() {
+    foo();
+}
+
diff --git a/src/test/ui/rust-2018/extern-crate-referenced-by-self-path.fixed b/src/test/ui/rust-2018/extern-crate-referenced-by-self-path.fixed
new file mode 100644
index 0000000..e249c8a
--- /dev/null
+++ b/src/test/ui/rust-2018/extern-crate-referenced-by-self-path.fixed
@@ -0,0 +1,18 @@
+// run-pass
+// aux-build:edition-lint-paths.rs
+// run-rustfix
+
+// Oddball: `edition_lint_paths` is accessed via this `self` path
+// rather than being accessed directly. Unless we rewrite that path,
+// we can't drop the extern crate.
+
+#![feature(rust_2018_preview)]
+#![deny(absolute_paths_not_starting_with_crate)]
+
+extern crate edition_lint_paths;
+use self::edition_lint_paths::foo;
+
+fn main() {
+    foo();
+}
+
diff --git a/src/test/ui/rust-2018/extern-crate-referenced-by-self-path.rs b/src/test/ui/rust-2018/extern-crate-referenced-by-self-path.rs
new file mode 100644
index 0000000..e249c8a
--- /dev/null
+++ b/src/test/ui/rust-2018/extern-crate-referenced-by-self-path.rs
@@ -0,0 +1,18 @@
+// run-pass
+// aux-build:edition-lint-paths.rs
+// run-rustfix
+
+// Oddball: `edition_lint_paths` is accessed via this `self` path
+// rather than being accessed directly. Unless we rewrite that path,
+// we can't drop the extern crate.
+
+#![feature(rust_2018_preview)]
+#![deny(absolute_paths_not_starting_with_crate)]
+
+extern crate edition_lint_paths;
+use self::edition_lint_paths::foo;
+
+fn main() {
+    foo();
+}
+
diff --git a/src/test/ui/rust-2018/extern-crate-rename.fixed b/src/test/ui/rust-2018/extern-crate-rename.fixed
new file mode 100644
index 0000000..aa8b935
--- /dev/null
+++ b/src/test/ui/rust-2018/extern-crate-rename.fixed
@@ -0,0 +1,19 @@
+// aux-build:edition-lint-paths.rs
+// run-rustfix
+
+// Oddball: crate is renamed, making it harder for us to rewrite
+// paths. We don't (and we leave the `extern crate` in place).
+
+#![feature(rust_2018_preview)]
+#![deny(absolute_paths_not_starting_with_crate)]
+
+extern crate edition_lint_paths as my_crate;
+
+use crate::my_crate::foo;
+//~^ ERROR absolute paths must start
+//~| WARNING this was previously accepted
+
+fn main() {
+    foo();
+}
+
diff --git a/src/test/ui/rust-2018/extern-crate-rename.rs b/src/test/ui/rust-2018/extern-crate-rename.rs
new file mode 100644
index 0000000..98c7d34
--- /dev/null
+++ b/src/test/ui/rust-2018/extern-crate-rename.rs
@@ -0,0 +1,19 @@
+// aux-build:edition-lint-paths.rs
+// run-rustfix
+
+// Oddball: crate is renamed, making it harder for us to rewrite
+// paths. We don't (and we leave the `extern crate` in place).
+
+#![feature(rust_2018_preview)]
+#![deny(absolute_paths_not_starting_with_crate)]
+
+extern crate edition_lint_paths as my_crate;
+
+use my_crate::foo;
+//~^ ERROR absolute paths must start
+//~| WARNING this was previously accepted
+
+fn main() {
+    foo();
+}
+
diff --git a/src/test/ui/rust-2018/extern-crate-rename.stderr b/src/test/ui/rust-2018/extern-crate-rename.stderr
new file mode 100644
index 0000000..4e33b1e
--- /dev/null
+++ b/src/test/ui/rust-2018/extern-crate-rename.stderr
@@ -0,0 +1,16 @@
+error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
+  --> $DIR/extern-crate-rename.rs:12:5
+   |
+LL | use my_crate::foo;
+   |     ^^^^^^^^^^^^^ help: use `crate`: `crate::my_crate::foo`
+   |
+note: lint level defined here
+  --> $DIR/extern-crate-rename.rs:8:9
+   |
+LL | #![deny(absolute_paths_not_starting_with_crate)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rust-2018/extern-crate-submod.fixed b/src/test/ui/rust-2018/extern-crate-submod.fixed
new file mode 100644
index 0000000..0564e58
--- /dev/null
+++ b/src/test/ui/rust-2018/extern-crate-submod.fixed
@@ -0,0 +1,26 @@
+// aux-build:edition-lint-paths.rs
+// run-rustfix
+
+// Oddball: extern crate appears in a submodule, making it harder for
+// us to rewrite paths. We don't (and we leave the `extern crate` in
+// place).
+
+#![feature(rust_2018_preview)]
+#![deny(absolute_paths_not_starting_with_crate)]
+
+mod m {
+    // Because this extern crate does not appear at the root, we
+    // ignore it altogether.
+    pub extern crate edition_lint_paths;
+}
+
+// And we don't being smart about paths like this, even though you
+// *could* rewrite it to `use edition_lint_paths::foo`
+use crate::m::edition_lint_paths::foo;
+//~^ ERROR absolute paths must start
+//~| WARNING this was previously accepted
+
+fn main() {
+    foo();
+}
+
diff --git a/src/test/ui/rust-2018/extern-crate-submod.rs b/src/test/ui/rust-2018/extern-crate-submod.rs
new file mode 100644
index 0000000..206f390
--- /dev/null
+++ b/src/test/ui/rust-2018/extern-crate-submod.rs
@@ -0,0 +1,26 @@
+// aux-build:edition-lint-paths.rs
+// run-rustfix
+
+// Oddball: extern crate appears in a submodule, making it harder for
+// us to rewrite paths. We don't (and we leave the `extern crate` in
+// place).
+
+#![feature(rust_2018_preview)]
+#![deny(absolute_paths_not_starting_with_crate)]
+
+mod m {
+    // Because this extern crate does not appear at the root, we
+    // ignore it altogether.
+    pub extern crate edition_lint_paths;
+}
+
+// And we don't being smart about paths like this, even though you
+// *could* rewrite it to `use edition_lint_paths::foo`
+use m::edition_lint_paths::foo;
+//~^ ERROR absolute paths must start
+//~| WARNING this was previously accepted
+
+fn main() {
+    foo();
+}
+
diff --git a/src/test/ui/rust-2018/extern-crate-submod.stderr b/src/test/ui/rust-2018/extern-crate-submod.stderr
new file mode 100644
index 0000000..e0b61dd
--- /dev/null
+++ b/src/test/ui/rust-2018/extern-crate-submod.stderr
@@ -0,0 +1,16 @@
+error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
+  --> $DIR/extern-crate-submod.rs:19:5
+   |
+LL | use m::edition_lint_paths::foo;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `crate`: `crate::m::edition_lint_paths::foo`
+   |
+note: lint level defined here
+  --> $DIR/extern-crate-submod.rs:9:9
+   |
+LL | #![deny(absolute_paths_not_starting_with_crate)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rust-2018/future-proofing-locals.rs b/src/test/ui/rust-2018/future-proofing-locals.rs
new file mode 100644
index 0000000..2c388cf
--- /dev/null
+++ b/src/test/ui/rust-2018/future-proofing-locals.rs
@@ -0,0 +1,50 @@
+// edition:2018
+
+#![allow(non_camel_case_types)]
+#![allow(unused_imports)]
+
+mod T {
+    pub struct U;
+}
+mod x {
+    pub struct y;
+}
+
+fn type_param<T>() {
+    use T as _; //~ ERROR imports cannot refer to type parameters
+    use T::U; //~ ERROR imports cannot refer to type parameters
+    use T::*; //~ ERROR imports cannot refer to type parameters
+}
+
+fn self_import<T>() {
+    use T; //~ ERROR imports cannot refer to type parameters
+}
+
+fn let_binding() {
+    let x = 10;
+
+    use x as _; //~ ERROR imports cannot refer to local variables
+    use x::y; // OK
+    use x::*; // OK
+}
+
+fn param_binding(x: u8) {
+    use x; //~ ERROR imports cannot refer to local variables
+}
+
+fn match_binding() {
+    match 0 {
+        x => {
+            use x; //~ ERROR imports cannot refer to local variables
+        }
+    }
+}
+
+fn nested<T>() {
+    let x = 10;
+
+    use {T as _, x}; //~ ERROR imports cannot refer to type parameters
+                     //~| ERROR imports cannot refer to local variables
+}
+
+fn main() {}
diff --git a/src/test/ui/rust-2018/future-proofing-locals.stderr b/src/test/ui/rust-2018/future-proofing-locals.stderr
new file mode 100644
index 0000000..7021489
--- /dev/null
+++ b/src/test/ui/rust-2018/future-proofing-locals.stderr
@@ -0,0 +1,56 @@
+error: imports cannot refer to type parameters
+  --> $DIR/future-proofing-locals.rs:14:9
+   |
+LL |     use T as _;
+   |         ^
+
+error: imports cannot refer to type parameters
+  --> $DIR/future-proofing-locals.rs:15:9
+   |
+LL |     use T::U;
+   |         ^
+
+error: imports cannot refer to type parameters
+  --> $DIR/future-proofing-locals.rs:16:9
+   |
+LL |     use T::*;
+   |         ^
+
+error: imports cannot refer to type parameters
+  --> $DIR/future-proofing-locals.rs:20:9
+   |
+LL |     use T;
+   |         ^
+
+error: imports cannot refer to local variables
+  --> $DIR/future-proofing-locals.rs:26:9
+   |
+LL |     use x as _;
+   |         ^
+
+error: imports cannot refer to local variables
+  --> $DIR/future-proofing-locals.rs:32:9
+   |
+LL |     use x;
+   |         ^
+
+error: imports cannot refer to local variables
+  --> $DIR/future-proofing-locals.rs:38:17
+   |
+LL |             use x;
+   |                 ^
+
+error: imports cannot refer to type parameters
+  --> $DIR/future-proofing-locals.rs:46:10
+   |
+LL |     use {T as _, x};
+   |          ^
+
+error: imports cannot refer to local variables
+  --> $DIR/future-proofing-locals.rs:46:18
+   |
+LL |     use {T as _, x};
+   |                  ^
+
+error: aborting due to 9 previous errors
+
diff --git a/src/test/ui/rust-2018/issue-51008-1.rs b/src/test/ui/rust-2018/issue-51008-1.rs
new file mode 100644
index 0000000..8ae5e82
--- /dev/null
+++ b/src/test/ui/rust-2018/issue-51008-1.rs
@@ -0,0 +1,15 @@
+// Regression test for #51008 -- the anonymous lifetime in `&i32` was
+// being incorrectly considered part of the "elided lifetimes" from
+// the impl.
+//
+// run-pass
+
+#![feature(rust_2018_preview)]
+
+trait A {
+
+}
+
+impl<F> A for F where F: PartialEq<fn(&i32)> { }
+
+fn main() {}
diff --git a/src/test/ui/rust-2018/issue-51008.rs b/src/test/ui/rust-2018/issue-51008.rs
new file mode 100644
index 0000000..b62609e
--- /dev/null
+++ b/src/test/ui/rust-2018/issue-51008.rs
@@ -0,0 +1,15 @@
+// Regression test for #51008 -- the anonymous lifetime in `&i32` was
+// being incorrectly considered part of the "elided lifetimes" from
+// the impl.
+//
+// run-pass
+
+#![feature(rust_2018_preview)]
+
+trait A {
+
+}
+
+impl<F> A for F where F: FnOnce(&i32) {}
+
+fn main() {}
diff --git a/src/test/ui/rust-2018/issue-52202-use-suggestions.rs b/src/test/ui/rust-2018/issue-52202-use-suggestions.rs
new file mode 100644
index 0000000..1c04268
--- /dev/null
+++ b/src/test/ui/rust-2018/issue-52202-use-suggestions.rs
@@ -0,0 +1,13 @@
+// edition:2018
+
+// The local `use` suggestion should start with `crate::` (but the
+// standard-library suggestions should not, obviously).
+
+mod plumbing {
+    pub struct Drain;
+}
+
+fn main() {
+    let _d = Drain {};
+    //~^ ERROR cannot find struct, variant or union type `Drain` in this scope
+}
diff --git a/src/test/ui/rust-2018/issue-52202-use-suggestions.stderr b/src/test/ui/rust-2018/issue-52202-use-suggestions.stderr
new file mode 100644
index 0000000..030fa56
--- /dev/null
+++ b/src/test/ui/rust-2018/issue-52202-use-suggestions.stderr
@@ -0,0 +1,20 @@
+error[E0422]: cannot find struct, variant or union type `Drain` in this scope
+  --> $DIR/issue-52202-use-suggestions.rs:11:14
+   |
+LL |     let _d = Drain {};
+   |              ^^^^^ not found in this scope
+help: possible candidates are found in other modules, you can import them into scope
+   |
+LL | use crate::plumbing::Drain;
+   |
+LL | use std::collections::binary_heap::Drain;
+   |
+LL | use std::collections::hash_map::Drain;
+   |
+LL | use std::collections::hash_set::Drain;
+   |
+and 3 other candidates
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0422`.
diff --git a/src/test/ui/rust-2018/issue-54006.rs b/src/test/ui/rust-2018/issue-54006.rs
new file mode 100644
index 0000000..a7a4770
--- /dev/null
+++ b/src/test/ui/rust-2018/issue-54006.rs
@@ -0,0 +1,13 @@
+// edition:2018
+
+#![no_std]
+#![crate_type = "lib"]
+
+use alloc::vec;
+//~^ ERROR unresolved import `alloc`
+
+pub fn foo() {
+    let mut xs = vec![];
+    //~^ ERROR cannot determine resolution for the macro `vec`
+    xs.push(0);
+}
diff --git a/src/test/ui/rust-2018/issue-54006.stderr b/src/test/ui/rust-2018/issue-54006.stderr
new file mode 100644
index 0000000..1978138
--- /dev/null
+++ b/src/test/ui/rust-2018/issue-54006.stderr
@@ -0,0 +1,17 @@
+error[E0432]: unresolved import `alloc`
+  --> $DIR/issue-54006.rs:6:5
+   |
+LL | use alloc::vec;
+   |     ^^^^^ help: a similar path exists: `core::alloc`
+
+error: cannot determine resolution for the macro `vec`
+  --> $DIR/issue-54006.rs:10:18
+   |
+LL |     let mut xs = vec![];
+   |                  ^^^
+   |
+   = note: import resolution is stuck, try simplifying macro imports
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/rust-2018/issue-54400-unused-extern-crate-attr-span.fixed b/src/test/ui/rust-2018/issue-54400-unused-extern-crate-attr-span.fixed
new file mode 100644
index 0000000..d592438
--- /dev/null
+++ b/src/test/ui/rust-2018/issue-54400-unused-extern-crate-attr-span.fixed
@@ -0,0 +1,14 @@
+// aux-build:edition-lint-paths.rs
+// run-rustfix
+// compile-flags:--extern edition_lint_paths --cfg blandiloquence
+// edition:2018
+
+#![deny(rust_2018_idioms)]
+#![allow(dead_code)]
+
+// The suggestion span should include the attribute.
+
+
+//~^ ERROR unused extern crate
+
+fn main() {}
diff --git a/src/test/ui/rust-2018/issue-54400-unused-extern-crate-attr-span.rs b/src/test/ui/rust-2018/issue-54400-unused-extern-crate-attr-span.rs
new file mode 100644
index 0000000..a948bae
--- /dev/null
+++ b/src/test/ui/rust-2018/issue-54400-unused-extern-crate-attr-span.rs
@@ -0,0 +1,15 @@
+// aux-build:edition-lint-paths.rs
+// run-rustfix
+// compile-flags:--extern edition_lint_paths --cfg blandiloquence
+// edition:2018
+
+#![deny(rust_2018_idioms)]
+#![allow(dead_code)]
+
+// The suggestion span should include the attribute.
+
+#[cfg(blandiloquence)] //~ HELP remove it
+extern crate edition_lint_paths;
+//~^ ERROR unused extern crate
+
+fn main() {}
diff --git a/src/test/ui/rust-2018/issue-54400-unused-extern-crate-attr-span.stderr b/src/test/ui/rust-2018/issue-54400-unused-extern-crate-attr-span.stderr
new file mode 100644
index 0000000..49aaff6
--- /dev/null
+++ b/src/test/ui/rust-2018/issue-54400-unused-extern-crate-attr-span.stderr
@@ -0,0 +1,18 @@
+error: unused extern crate
+  --> $DIR/issue-54400-unused-extern-crate-attr-span.rs:12:1
+   |
+LL | / #[cfg(blandiloquence)]
+LL | | extern crate edition_lint_paths;
+   | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
+   | |________________________________|
+   |                                  help: remove it
+   |
+note: lint level defined here
+  --> $DIR/issue-54400-unused-extern-crate-attr-span.rs:6:9
+   |
+LL | #![deny(rust_2018_idioms)]
+   |         ^^^^^^^^^^^^^^^^
+   = note: #[deny(unused_extern_crates)] implied by #[deny(rust_2018_idioms)]
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rust-2018/local-path-suggestions-2015.rs b/src/test/ui/rust-2018/local-path-suggestions-2015.rs
new file mode 100644
index 0000000..32e9c0c
--- /dev/null
+++ b/src/test/ui/rust-2018/local-path-suggestions-2015.rs
@@ -0,0 +1,26 @@
+// aux-build:baz.rs
+// compile-flags:--extern baz
+// edition:2015
+
+// This test exists to demonstrate the behaviour of the import suggestions
+// from the `local-path-suggestions-2018.rs` test when not using the 2018 edition.
+
+extern crate baz as aux_baz;
+
+mod foo {
+    pub type Bar = u32;
+}
+
+mod baz {
+    use foo::Bar;
+
+    fn baz() {
+        let x: Bar = 22;
+    }
+}
+
+use foo::Bar;
+
+use foobar::Baz; //~ ERROR unresolved import `foobar`
+
+fn main() { }
diff --git a/src/test/ui/rust-2018/local-path-suggestions-2015.stderr b/src/test/ui/rust-2018/local-path-suggestions-2015.stderr
new file mode 100644
index 0000000..666864a
--- /dev/null
+++ b/src/test/ui/rust-2018/local-path-suggestions-2015.stderr
@@ -0,0 +1,12 @@
+error[E0432]: unresolved import `foobar`
+  --> $DIR/local-path-suggestions-2015.rs:24:5
+   |
+LL | use foobar::Baz;
+   |     ^^^^^^
+   |     |
+   |     unresolved import
+   |     help: a similar path exists: `aux_baz::foobar`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/rust-2018/local-path-suggestions-2018.rs b/src/test/ui/rust-2018/local-path-suggestions-2018.rs
new file mode 100644
index 0000000..5eafbb2
--- /dev/null
+++ b/src/test/ui/rust-2018/local-path-suggestions-2018.rs
@@ -0,0 +1,21 @@
+// aux-build:baz.rs
+// compile-flags:--extern baz
+// edition:2018
+
+mod foo {
+    pub type Bar = u32;
+}
+
+mod bazz {
+    use foo::Bar; //~ ERROR unresolved import `foo`
+
+    fn baz() {
+        let x: Bar = 22;
+    }
+}
+
+use foo::Bar;
+
+use foobar::Baz; //~ ERROR unresolved import `foobar`
+
+fn main() { }
diff --git a/src/test/ui/rust-2018/local-path-suggestions-2018.stderr b/src/test/ui/rust-2018/local-path-suggestions-2018.stderr
new file mode 100644
index 0000000..40f3d6b
--- /dev/null
+++ b/src/test/ui/rust-2018/local-path-suggestions-2018.stderr
@@ -0,0 +1,17 @@
+error[E0432]: unresolved import `foo`
+  --> $DIR/local-path-suggestions-2018.rs:10:9
+   |
+LL |     use foo::Bar;
+   |         ^^^ help: a similar path exists: `crate::foo`
+   |
+   = note: `use` statements changed in Rust 2018; read more at <https://doc.rust-lang.org/edition-guide/rust-2018/module-system/path-clarity.html>
+
+error[E0432]: unresolved import `foobar`
+  --> $DIR/local-path-suggestions-2018.rs:19:5
+   |
+LL | use foobar::Baz;
+   |     ^^^^^^ help: a similar path exists: `baz::foobar`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/rust-2018/macro-use-warned-against.rs b/src/test/ui/rust-2018/macro-use-warned-against.rs
new file mode 100644
index 0000000..368b8da
--- /dev/null
+++ b/src/test/ui/rust-2018/macro-use-warned-against.rs
@@ -0,0 +1,14 @@
+// aux-build:macro-use-warned-against.rs
+// aux-build:macro-use-warned-against2.rs
+// compile-pass
+
+#![warn(macro_use_extern_crate, unused)]
+
+#[macro_use] //~ WARN should be replaced at use sites with a `use` statement
+extern crate macro_use_warned_against;
+#[macro_use] //~ WARN unused `#[macro_use]`
+extern crate macro_use_warned_against2;
+
+fn main() {
+    foo!();
+}
diff --git a/src/test/ui/rust-2018/macro-use-warned-against.stderr b/src/test/ui/rust-2018/macro-use-warned-against.stderr
new file mode 100644
index 0000000..c3e4596
--- /dev/null
+++ b/src/test/ui/rust-2018/macro-use-warned-against.stderr
@@ -0,0 +1,25 @@
+warning: deprecated `#[macro_use]` directive used to import macros should be replaced at use sites with a `use` statement to import the macro instead
+  --> $DIR/macro-use-warned-against.rs:7:1
+   |
+LL | #[macro_use]
+   | ^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/macro-use-warned-against.rs:5:9
+   |
+LL | #![warn(macro_use_extern_crate, unused)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused `#[macro_use]` import
+  --> $DIR/macro-use-warned-against.rs:9:1
+   |
+LL | #[macro_use]
+   | ^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/macro-use-warned-against.rs:5:33
+   |
+LL | #![warn(macro_use_extern_crate, unused)]
+   |                                 ^^^^^^
+   = note: #[warn(unused_imports)] implied by #[warn(unused)]
+
diff --git a/src/test/ui/rust-2018/proc-macro-crate-in-paths.rs b/src/test/ui/rust-2018/proc-macro-crate-in-paths.rs
new file mode 100644
index 0000000..3311ded
--- /dev/null
+++ b/src/test/ui/rust-2018/proc-macro-crate-in-paths.rs
@@ -0,0 +1,16 @@
+// compile-pass
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+#![deny(rust_2018_compatibility)]
+#![feature(rust_2018_preview)]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(Template, attributes(template))]
+pub fn derive_template(input: TokenStream) -> TokenStream {
+    input
+}
diff --git a/src/test/ui/rust-2018/remove-extern-crate.fixed b/src/test/ui/rust-2018/remove-extern-crate.fixed
new file mode 100644
index 0000000..a977e00
--- /dev/null
+++ b/src/test/ui/rust-2018/remove-extern-crate.fixed
@@ -0,0 +1,36 @@
+// run-rustfix
+// edition:2018
+// compile-pass
+// aux-build:remove-extern-crate.rs
+// compile-flags:--extern remove_extern_crate
+
+#![feature(alloc)]
+#![warn(rust_2018_idioms)]
+
+
+use core as another_name;
+use remove_extern_crate;
+#[macro_use]
+extern crate remove_extern_crate as something_else;
+
+// Shouldn't suggest changing to `use`, as the `alloc`
+// crate is not in the extern prelude - see #54381.
+extern crate alloc;
+
+fn main() {
+    another_name::mem::drop(3);
+    another::foo();
+    remove_extern_crate::foo!();
+    bar!();
+    alloc::vec![5];
+}
+
+mod another {
+    use core;
+    use remove_extern_crate;
+
+    pub fn foo() {
+        core::mem::drop(4);
+        remove_extern_crate::foo!();
+    }
+}
diff --git a/src/test/ui/rust-2018/remove-extern-crate.rs b/src/test/ui/rust-2018/remove-extern-crate.rs
new file mode 100644
index 0000000..cafe82d
--- /dev/null
+++ b/src/test/ui/rust-2018/remove-extern-crate.rs
@@ -0,0 +1,36 @@
+// run-rustfix
+// edition:2018
+// compile-pass
+// aux-build:remove-extern-crate.rs
+// compile-flags:--extern remove_extern_crate
+
+#![feature(alloc)]
+#![warn(rust_2018_idioms)]
+
+extern crate core;
+extern crate core as another_name;
+use remove_extern_crate;
+#[macro_use]
+extern crate remove_extern_crate as something_else;
+
+// Shouldn't suggest changing to `use`, as the `alloc`
+// crate is not in the extern prelude - see #54381.
+extern crate alloc;
+
+fn main() {
+    another_name::mem::drop(3);
+    another::foo();
+    remove_extern_crate::foo!();
+    bar!();
+    alloc::vec![5];
+}
+
+mod another {
+    extern crate core;
+    use remove_extern_crate;
+
+    pub fn foo() {
+        core::mem::drop(4);
+        remove_extern_crate::foo!();
+    }
+}
diff --git a/src/test/ui/rust-2018/remove-extern-crate.stderr b/src/test/ui/rust-2018/remove-extern-crate.stderr
new file mode 100644
index 0000000..4e08b7a
--- /dev/null
+++ b/src/test/ui/rust-2018/remove-extern-crate.stderr
@@ -0,0 +1,25 @@
+warning: unused extern crate
+  --> $DIR/remove-extern-crate.rs:10:1
+   |
+LL | extern crate core;
+   | ^^^^^^^^^^^^^^^^^^ help: remove it
+   |
+note: lint level defined here
+  --> $DIR/remove-extern-crate.rs:8:9
+   |
+LL | #![warn(rust_2018_idioms)]
+   |         ^^^^^^^^^^^^^^^^
+   = note: #[warn(unused_extern_crates)] implied by #[warn(rust_2018_idioms)]
+
+warning: `extern crate` is not idiomatic in the new edition
+  --> $DIR/remove-extern-crate.rs:11:1
+   |
+LL | extern crate core as another_name;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `use`
+
+warning: `extern crate` is not idiomatic in the new edition
+  --> $DIR/remove-extern-crate.rs:29:5
+   |
+LL |     extern crate core;
+   |     ^^^^^^^^^^^^^^^^^^ help: convert it to a `use`
+
diff --git a/src/test/ui/rust-2018/suggestions-not-always-applicable.fixed b/src/test/ui/rust-2018/suggestions-not-always-applicable.fixed
new file mode 100644
index 0000000..f0ca247
--- /dev/null
+++ b/src/test/ui/rust-2018/suggestions-not-always-applicable.fixed
@@ -0,0 +1,27 @@
+// aux-build:suggestions-not-always-applicable.rs
+// edition:2015
+// run-rustfix
+// rustfix-only-machine-applicable
+// compile-pass
+
+#![feature(rust_2018_preview)]
+#![warn(rust_2018_compatibility)]
+
+extern crate suggestions_not_always_applicable as foo;
+
+pub struct Foo;
+
+mod test {
+    use crate::foo::foo;
+
+    #[foo] //~ WARN: absolute paths must start with
+    //~| WARN: previously accepted
+    //~| WARN: absolute paths
+    //~| WARN: previously accepted
+    fn main() {
+    }
+}
+
+fn main() {
+    test::foo();
+}
diff --git a/src/test/ui/rust-2018/suggestions-not-always-applicable.rs b/src/test/ui/rust-2018/suggestions-not-always-applicable.rs
new file mode 100644
index 0000000..f0ca247
--- /dev/null
+++ b/src/test/ui/rust-2018/suggestions-not-always-applicable.rs
@@ -0,0 +1,27 @@
+// aux-build:suggestions-not-always-applicable.rs
+// edition:2015
+// run-rustfix
+// rustfix-only-machine-applicable
+// compile-pass
+
+#![feature(rust_2018_preview)]
+#![warn(rust_2018_compatibility)]
+
+extern crate suggestions_not_always_applicable as foo;
+
+pub struct Foo;
+
+mod test {
+    use crate::foo::foo;
+
+    #[foo] //~ WARN: absolute paths must start with
+    //~| WARN: previously accepted
+    //~| WARN: absolute paths
+    //~| WARN: previously accepted
+    fn main() {
+    }
+}
+
+fn main() {
+    test::foo();
+}
diff --git a/src/test/ui/rust-2018/suggestions-not-always-applicable.stderr b/src/test/ui/rust-2018/suggestions-not-always-applicable.stderr
new file mode 100644
index 0000000..19e87b6
--- /dev/null
+++ b/src/test/ui/rust-2018/suggestions-not-always-applicable.stderr
@@ -0,0 +1,24 @@
+warning: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
+  --> $DIR/suggestions-not-always-applicable.rs:17:5
+   |
+LL |     #[foo]
+   |     ^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/suggestions-not-always-applicable.rs:8:9
+   |
+LL | #![warn(rust_2018_compatibility)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+   = note: #[warn(absolute_paths_not_starting_with_crate)] implied by #[warn(rust_2018_compatibility)]
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
+
+warning: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
+  --> $DIR/suggestions-not-always-applicable.rs:17:5
+   |
+LL |     #[foo]
+   |     ^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
+
diff --git a/src/test/ui/rust-2018/trait-import-suggestions.rs b/src/test/ui/rust-2018/trait-import-suggestions.rs
new file mode 100644
index 0000000..9c67c3f
--- /dev/null
+++ b/src/test/ui/rust-2018/trait-import-suggestions.rs
@@ -0,0 +1,31 @@
+// edition:2018
+// aux-build:trait-import-suggestions.rs
+// compile-flags:--extern trait-import-suggestions
+
+mod foo {
+    mod foobar {
+        pub(crate) trait Foobar {
+            fn foobar(&self) { }
+        }
+
+        impl Foobar for u32 { }
+    }
+
+    pub(crate) trait Bar {
+        fn bar(&self) { }
+    }
+
+    impl Bar for u32 { }
+
+    fn in_foo() {
+        let x: u32 = 22;
+        x.foobar(); //~ ERROR no method named `foobar`
+    }
+}
+
+fn main() {
+    let x: u32 = 22;
+    x.bar(); //~ ERROR no method named `bar`
+    x.baz(); //~ ERROR no method named `baz`
+    let y = u32::from_str("33"); //~ ERROR no function or associated item named `from_str`
+}
diff --git a/src/test/ui/rust-2018/trait-import-suggestions.stderr b/src/test/ui/rust-2018/trait-import-suggestions.stderr
new file mode 100644
index 0000000..a811812
--- /dev/null
+++ b/src/test/ui/rust-2018/trait-import-suggestions.stderr
@@ -0,0 +1,43 @@
+error[E0599]: no method named `foobar` found for type `u32` in the current scope
+  --> $DIR/trait-import-suggestions.rs:22:11
+   |
+LL |         x.foobar();
+   |           ^^^^^^
+   |
+   = help: items from traits can only be used if the trait is in scope
+   = note: the following trait is implemented but not in scope, perhaps add a `use` for it:
+           `use crate::foo::foobar::Foobar;`
+
+error[E0599]: no method named `bar` found for type `u32` in the current scope
+  --> $DIR/trait-import-suggestions.rs:28:7
+   |
+LL |     x.bar();
+   |       ^^^
+   |
+   = help: items from traits can only be used if the trait is in scope
+help: the following trait is implemented but not in scope, perhaps add a `use` for it:
+   |
+LL | use crate::foo::Bar;
+   |
+
+error[E0599]: no method named `baz` found for type `u32` in the current scope
+  --> $DIR/trait-import-suggestions.rs:29:7
+   |
+LL |     x.baz();
+   |       ^^^
+
+error[E0599]: no function or associated item named `from_str` found for type `u32` in the current scope
+  --> $DIR/trait-import-suggestions.rs:30:18
+   |
+LL |     let y = u32::from_str("33");
+   |                  ^^^^^^^^ function or associated item not found in `u32`
+   |
+   = help: items from traits can only be used if the trait is in scope
+help: the following trait is implemented but not in scope, perhaps add a `use` for it:
+   |
+LL | use std::str::FromStr;
+   |
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/rust-2018/try-ident.fixed b/src/test/ui/rust-2018/try-ident.fixed
new file mode 100644
index 0000000..5af1393
--- /dev/null
+++ b/src/test/ui/rust-2018/try-ident.fixed
@@ -0,0 +1,11 @@
+// run-rustfix
+// compile-pass
+
+#![warn(rust_2018_compatibility)]
+
+fn main() {
+    r#try();
+}
+
+fn r#try() {
+}
diff --git a/src/test/ui/rust-2018/try-ident.rs b/src/test/ui/rust-2018/try-ident.rs
new file mode 100644
index 0000000..faac13a
--- /dev/null
+++ b/src/test/ui/rust-2018/try-ident.rs
@@ -0,0 +1,11 @@
+// run-rustfix
+// compile-pass
+
+#![warn(rust_2018_compatibility)]
+
+fn main() {
+    try();
+}
+
+fn try() {
+}
diff --git a/src/test/ui/rust-2018/try-ident.stderr b/src/test/ui/rust-2018/try-ident.stderr
new file mode 100644
index 0000000..9494603
--- /dev/null
+++ b/src/test/ui/rust-2018/try-ident.stderr
@@ -0,0 +1,24 @@
+warning: `try` is a keyword in the 2018 edition
+  --> $DIR/try-ident.rs:7:5
+   |
+LL |     try();
+   |     ^^^ help: you can use a raw identifier to stay compatible: `r#try`
+   |
+note: lint level defined here
+  --> $DIR/try-ident.rs:4:9
+   |
+LL | #![warn(rust_2018_compatibility)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+   = note: #[warn(keyword_idents)] implied by #[warn(rust_2018_compatibility)]
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+warning: `try` is a keyword in the 2018 edition
+  --> $DIR/try-ident.rs:10:4
+   |
+LL | fn try() {
+   |    ^^^ help: you can use a raw identifier to stay compatible: `r#try`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
diff --git a/src/test/ui/rust-2018/try-macro.fixed b/src/test/ui/rust-2018/try-macro.fixed
new file mode 100644
index 0000000..c65f0fc
--- /dev/null
+++ b/src/test/ui/rust-2018/try-macro.fixed
@@ -0,0 +1,16 @@
+// Test that `try!` macros are rewritten.
+
+// run-rustfix
+// compile-pass
+
+#![warn(rust_2018_compatibility)]
+#![allow(unused_variables)]
+#![allow(dead_code)]
+
+fn foo() -> Result<usize, ()> {
+    let x: Result<usize, ()> = Ok(22);
+    r#try!(x);
+    Ok(44)
+}
+
+fn main() { }
diff --git a/src/test/ui/rust-2018/try-macro.rs b/src/test/ui/rust-2018/try-macro.rs
new file mode 100644
index 0000000..f435890
--- /dev/null
+++ b/src/test/ui/rust-2018/try-macro.rs
@@ -0,0 +1,16 @@
+// Test that `try!` macros are rewritten.
+
+// run-rustfix
+// compile-pass
+
+#![warn(rust_2018_compatibility)]
+#![allow(unused_variables)]
+#![allow(dead_code)]
+
+fn foo() -> Result<usize, ()> {
+    let x: Result<usize, ()> = Ok(22);
+    try!(x);
+    Ok(44)
+}
+
+fn main() { }
diff --git a/src/test/ui/rust-2018/try-macro.stderr b/src/test/ui/rust-2018/try-macro.stderr
new file mode 100644
index 0000000..40a4564
--- /dev/null
+++ b/src/test/ui/rust-2018/try-macro.stderr
@@ -0,0 +1,15 @@
+warning: `try` is a keyword in the 2018 edition
+  --> $DIR/try-macro.rs:12:5
+   |
+LL |     try!(x);
+   |     ^^^ help: you can use a raw identifier to stay compatible: `r#try`
+   |
+note: lint level defined here
+  --> $DIR/try-macro.rs:6:9
+   |
+LL | #![warn(rust_2018_compatibility)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+   = note: #[warn(keyword_idents)] implied by #[warn(rust_2018_compatibility)]
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
diff --git a/src/test/ui/rust-2018/uniform-paths/ambiguity-macros-nested.rs b/src/test/ui/rust-2018/uniform-paths/ambiguity-macros-nested.rs
new file mode 100644
index 0000000..678b477
--- /dev/null
+++ b/src/test/ui/rust-2018/uniform-paths/ambiguity-macros-nested.rs
@@ -0,0 +1,21 @@
+// edition:2018
+
+// This test is similar to `ambiguity-macros.rs`, but nested in a module.
+
+#![allow(non_camel_case_types)]
+
+mod foo {
+    pub use std::io;
+    //~^ ERROR `std` is ambiguous
+
+    macro_rules! m {
+        () => {
+            mod std {
+                pub struct io;
+            }
+        }
+    }
+    m!();
+}
+
+fn main() {}
diff --git a/src/test/ui/rust-2018/uniform-paths/ambiguity-macros-nested.stderr b/src/test/ui/rust-2018/uniform-paths/ambiguity-macros-nested.stderr
new file mode 100644
index 0000000..0414490
--- /dev/null
+++ b/src/test/ui/rust-2018/uniform-paths/ambiguity-macros-nested.stderr
@@ -0,0 +1,23 @@
+error[E0659]: `std` is ambiguous (name vs any other name during import resolution)
+  --> $DIR/ambiguity-macros-nested.rs:8:13
+   |
+LL |     pub use std::io;
+   |             ^^^ ambiguous name
+   |
+   = note: `std` could refer to a built-in extern crate
+   = help: use `::std` to refer to this extern crate unambiguously
+note: `std` could also refer to the module defined here
+  --> $DIR/ambiguity-macros-nested.rs:13:13
+   |
+LL | /             mod std {
+LL | |                 pub struct io;
+LL | |             }
+   | |_____________^
+...
+LL |       m!();
+   |       ----- in this macro invocation
+   = help: use `self::std` to refer to this module unambiguously
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0659`.
diff --git a/src/test/ui/rust-2018/uniform-paths/ambiguity-macros.rs b/src/test/ui/rust-2018/uniform-paths/ambiguity-macros.rs
new file mode 100644
index 0000000..56ea726
--- /dev/null
+++ b/src/test/ui/rust-2018/uniform-paths/ambiguity-macros.rs
@@ -0,0 +1,19 @@
+// edition:2018
+
+// This test is similar to `ambiguity.rs`, but with macros defining local items.
+
+#![allow(non_camel_case_types)]
+
+use std::io;
+//~^ ERROR `std` is ambiguous
+
+macro_rules! m {
+    () => {
+        mod std {
+            pub struct io;
+        }
+    }
+}
+m!();
+
+fn main() {}
diff --git a/src/test/ui/rust-2018/uniform-paths/ambiguity-macros.stderr b/src/test/ui/rust-2018/uniform-paths/ambiguity-macros.stderr
new file mode 100644
index 0000000..7172637
--- /dev/null
+++ b/src/test/ui/rust-2018/uniform-paths/ambiguity-macros.stderr
@@ -0,0 +1,23 @@
+error[E0659]: `std` is ambiguous (name vs any other name during import resolution)
+  --> $DIR/ambiguity-macros.rs:7:5
+   |
+LL | use std::io;
+   |     ^^^ ambiguous name
+   |
+   = note: `std` could refer to a built-in extern crate
+   = help: use `::std` to refer to this extern crate unambiguously
+note: `std` could also refer to the module defined here
+  --> $DIR/ambiguity-macros.rs:12:9
+   |
+LL | /         mod std {
+LL | |             pub struct io;
+LL | |         }
+   | |_________^
+...
+LL |   m!();
+   |   ----- in this macro invocation
+   = help: use `crate::std` to refer to this module unambiguously
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0659`.
diff --git a/src/test/ui/rust-2018/uniform-paths/ambiguity-nested.rs b/src/test/ui/rust-2018/uniform-paths/ambiguity-nested.rs
new file mode 100644
index 0000000..50c8fc8
--- /dev/null
+++ b/src/test/ui/rust-2018/uniform-paths/ambiguity-nested.rs
@@ -0,0 +1,16 @@
+// edition:2018
+
+// This test is similar to `ambiguity.rs`, but nested in a module.
+
+#![allow(non_camel_case_types)]
+
+mod foo {
+    pub use std::io;
+    //~^ ERROR `std` is ambiguous
+
+    mod std {
+        pub struct io;
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/rust-2018/uniform-paths/ambiguity-nested.stderr b/src/test/ui/rust-2018/uniform-paths/ambiguity-nested.stderr
new file mode 100644
index 0000000..1d22a39
--- /dev/null
+++ b/src/test/ui/rust-2018/uniform-paths/ambiguity-nested.stderr
@@ -0,0 +1,20 @@
+error[E0659]: `std` is ambiguous (name vs any other name during import resolution)
+  --> $DIR/ambiguity-nested.rs:8:13
+   |
+LL |     pub use std::io;
+   |             ^^^ ambiguous name
+   |
+   = note: `std` could refer to a built-in extern crate
+   = help: use `::std` to refer to this extern crate unambiguously
+note: `std` could also refer to the module defined here
+  --> $DIR/ambiguity-nested.rs:11:5
+   |
+LL | /     mod std {
+LL | |         pub struct io;
+LL | |     }
+   | |_____^
+   = help: use `self::std` to refer to this module unambiguously
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0659`.
diff --git a/src/test/ui/rust-2018/uniform-paths/ambiguity.rs b/src/test/ui/rust-2018/uniform-paths/ambiguity.rs
new file mode 100644
index 0000000..60f77a1
--- /dev/null
+++ b/src/test/ui/rust-2018/uniform-paths/ambiguity.rs
@@ -0,0 +1,12 @@
+// edition:2018
+
+#![allow(non_camel_case_types)]
+
+use std::io;
+//~^ ERROR `std` is ambiguous
+
+mod std {
+    pub struct io;
+}
+
+fn main() {}
diff --git a/src/test/ui/rust-2018/uniform-paths/ambiguity.stderr b/src/test/ui/rust-2018/uniform-paths/ambiguity.stderr
new file mode 100644
index 0000000..45751c9
--- /dev/null
+++ b/src/test/ui/rust-2018/uniform-paths/ambiguity.stderr
@@ -0,0 +1,20 @@
+error[E0659]: `std` is ambiguous (name vs any other name during import resolution)
+  --> $DIR/ambiguity.rs:5:5
+   |
+LL | use std::io;
+   |     ^^^ ambiguous name
+   |
+   = note: `std` could refer to a built-in extern crate
+   = help: use `::std` to refer to this extern crate unambiguously
+note: `std` could also refer to the module defined here
+  --> $DIR/ambiguity.rs:8:1
+   |
+LL | / mod std {
+LL | |     pub struct io;
+LL | | }
+   | |_^
+   = help: use `crate::std` to refer to this module unambiguously
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0659`.
diff --git a/src/test/ui/rust-2018/uniform-paths/auxiliary/cross-crate.rs b/src/test/ui/rust-2018/uniform-paths/auxiliary/cross-crate.rs
new file mode 100644
index 0000000..4aa5d18
--- /dev/null
+++ b/src/test/ui/rust-2018/uniform-paths/auxiliary/cross-crate.rs
@@ -0,0 +1,5 @@
+// edition:2018
+
+pub use ignore as built_in_attr;
+pub use u8 as built_in_type;
+pub use rustfmt as tool_mod;
diff --git a/src/test/ui/rust-2018/uniform-paths/auxiliary/issue-56596-2.rs b/src/test/ui/rust-2018/uniform-paths/auxiliary/issue-56596-2.rs
new file mode 100644
index 0000000..db72307
--- /dev/null
+++ b/src/test/ui/rust-2018/uniform-paths/auxiliary/issue-56596-2.rs
@@ -0,0 +1 @@
+pub extern crate core;
diff --git a/src/test/ui/rust-2018/uniform-paths/auxiliary/issue-56596.rs b/src/test/ui/rust-2018/uniform-paths/auxiliary/issue-56596.rs
new file mode 100644
index 0000000..bc010a3
--- /dev/null
+++ b/src/test/ui/rust-2018/uniform-paths/auxiliary/issue-56596.rs
@@ -0,0 +1 @@
+// Nothing here
diff --git a/src/test/ui/rust-2018/uniform-paths/block-scoped-shadow-nested.rs b/src/test/ui/rust-2018/uniform-paths/block-scoped-shadow-nested.rs
new file mode 100644
index 0000000..3f58979
--- /dev/null
+++ b/src/test/ui/rust-2018/uniform-paths/block-scoped-shadow-nested.rs
@@ -0,0 +1,20 @@
+// edition:2018
+
+mod my {
+    pub mod sub {
+        pub fn bar() {}
+    }
+}
+
+mod sub {
+    pub fn bar() {}
+}
+
+fn foo() {
+    use my::sub;
+    {
+        use sub::bar; //~ ERROR `sub` is ambiguous
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/rust-2018/uniform-paths/block-scoped-shadow-nested.stderr b/src/test/ui/rust-2018/uniform-paths/block-scoped-shadow-nested.stderr
new file mode 100644
index 0000000..db17687
--- /dev/null
+++ b/src/test/ui/rust-2018/uniform-paths/block-scoped-shadow-nested.stderr
@@ -0,0 +1,23 @@
+error[E0659]: `sub` is ambiguous (name vs any other name during import resolution)
+  --> $DIR/block-scoped-shadow-nested.rs:16:13
+   |
+LL |         use sub::bar;
+   |             ^^^ ambiguous name
+   |
+note: `sub` could refer to the module imported here
+  --> $DIR/block-scoped-shadow-nested.rs:14:9
+   |
+LL |     use my::sub;
+   |         ^^^^^^^
+note: `sub` could also refer to the module defined here
+  --> $DIR/block-scoped-shadow-nested.rs:9:1
+   |
+LL | / mod sub {
+LL | |     pub fn bar() {}
+LL | | }
+   | |_^
+   = help: use `crate::sub` to refer to this module unambiguously
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0659`.
diff --git a/src/test/ui/rust-2018/uniform-paths/block-scoped-shadow.rs b/src/test/ui/rust-2018/uniform-paths/block-scoped-shadow.rs
new file mode 100644
index 0000000..828ee4f
--- /dev/null
+++ b/src/test/ui/rust-2018/uniform-paths/block-scoped-shadow.rs
@@ -0,0 +1,21 @@
+// edition:2018
+
+#![allow(non_camel_case_types)]
+
+enum Foo {}
+
+struct std;
+
+fn main() {
+    enum Foo { A, B }
+    use Foo::*;
+    //~^ ERROR `Foo` is ambiguous
+
+    let _ = (A, B);
+
+    fn std() {}
+    enum std {}
+    use std as foo;
+    //~^ ERROR `std` is ambiguous
+    //~| ERROR `std` is ambiguous
+}
diff --git a/src/test/ui/rust-2018/uniform-paths/block-scoped-shadow.stderr b/src/test/ui/rust-2018/uniform-paths/block-scoped-shadow.stderr
new file mode 100644
index 0000000..2767d9e
--- /dev/null
+++ b/src/test/ui/rust-2018/uniform-paths/block-scoped-shadow.stderr
@@ -0,0 +1,57 @@
+error[E0659]: `Foo` is ambiguous (name vs any other name during import resolution)
+  --> $DIR/block-scoped-shadow.rs:11:9
+   |
+LL |     use Foo::*;
+   |         ^^^ ambiguous name
+   |
+note: `Foo` could refer to the enum defined here
+  --> $DIR/block-scoped-shadow.rs:10:5
+   |
+LL |     enum Foo { A, B }
+   |     ^^^^^^^^^^^^^^^^^
+note: `Foo` could also refer to the enum defined here
+  --> $DIR/block-scoped-shadow.rs:5:1
+   |
+LL | enum Foo {}
+   | ^^^^^^^^^^^
+   = help: use `crate::Foo` to refer to this enum unambiguously
+
+error[E0659]: `std` is ambiguous (name vs any other name during import resolution)
+  --> $DIR/block-scoped-shadow.rs:18:9
+   |
+LL |     use std as foo;
+   |         ^^^ ambiguous name
+   |
+note: `std` could refer to the enum defined here
+  --> $DIR/block-scoped-shadow.rs:17:5
+   |
+LL |     enum std {}
+   |     ^^^^^^^^^^^
+note: `std` could also refer to the struct defined here
+  --> $DIR/block-scoped-shadow.rs:7:1
+   |
+LL | struct std;
+   | ^^^^^^^^^^^
+   = help: use `crate::std` to refer to this struct unambiguously
+
+error[E0659]: `std` is ambiguous (name vs any other name during import resolution)
+  --> $DIR/block-scoped-shadow.rs:18:9
+   |
+LL |     use std as foo;
+   |         ^^^ ambiguous name
+   |
+note: `std` could refer to the function defined here
+  --> $DIR/block-scoped-shadow.rs:16:5
+   |
+LL |     fn std() {}
+   |     ^^^^^^^^^^^
+note: `std` could also refer to the unit struct defined here
+  --> $DIR/block-scoped-shadow.rs:7:1
+   |
+LL | struct std;
+   | ^^^^^^^^^^^
+   = help: use `crate::std` to refer to this unit struct unambiguously
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0659`.
diff --git a/src/test/ui/rust-2018/uniform-paths/cross-crate.rs b/src/test/ui/rust-2018/uniform-paths/cross-crate.rs
new file mode 100644
index 0000000..27d6dbf
--- /dev/null
+++ b/src/test/ui/rust-2018/uniform-paths/cross-crate.rs
@@ -0,0 +1,11 @@
+// edition:2018
+// aux-build:cross-crate.rs
+
+extern crate cross_crate;
+use cross_crate::*;
+
+#[built_in_attr] //~ ERROR cannot use a built-in attribute through an import
+#[tool_mod::skip] //~ ERROR cannot use a tool module through an import
+fn main() {
+    let _: built_in_type; // OK
+}
diff --git a/src/test/ui/rust-2018/uniform-paths/cross-crate.stderr b/src/test/ui/rust-2018/uniform-paths/cross-crate.stderr
new file mode 100644
index 0000000..fdde75f
--- /dev/null
+++ b/src/test/ui/rust-2018/uniform-paths/cross-crate.stderr
@@ -0,0 +1,26 @@
+error: cannot use a built-in attribute through an import
+  --> $DIR/cross-crate.rs:7:3
+   |
+LL | #[built_in_attr]
+   |   ^^^^^^^^^^^^^
+   |
+note: the built-in attribute imported here
+  --> $DIR/cross-crate.rs:5:5
+   |
+LL | use cross_crate::*;
+   |     ^^^^^^^^^^^^^^
+
+error: cannot use a tool module through an import
+  --> $DIR/cross-crate.rs:8:3
+   |
+LL | #[tool_mod::skip]
+   |   ^^^^^^^^
+   |
+note: the tool module imported here
+  --> $DIR/cross-crate.rs:5:5
+   |
+LL | use cross_crate::*;
+   |     ^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/rust-2018/uniform-paths/deadlock.rs b/src/test/ui/rust-2018/uniform-paths/deadlock.rs
new file mode 100644
index 0000000..3228d79
--- /dev/null
+++ b/src/test/ui/rust-2018/uniform-paths/deadlock.rs
@@ -0,0 +1,7 @@
+// edition:2018
+// compile-flags:--extern foo --extern bar
+
+use foo::bar; //~ ERROR unresolved import
+use bar::foo;
+
+fn main() {}
diff --git a/src/test/ui/rust-2018/uniform-paths/deadlock.stderr b/src/test/ui/rust-2018/uniform-paths/deadlock.stderr
new file mode 100644
index 0000000..b4ac15c
--- /dev/null
+++ b/src/test/ui/rust-2018/uniform-paths/deadlock.stderr
@@ -0,0 +1,9 @@
+error[E0432]: unresolved import
+  --> $DIR/deadlock.rs:4:5
+   |
+LL | use foo::bar;
+   |     ^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/rust-2018/uniform-paths/fn-local-enum.rs b/src/test/ui/rust-2018/uniform-paths/fn-local-enum.rs
new file mode 100644
index 0000000..0c2da18
--- /dev/null
+++ b/src/test/ui/rust-2018/uniform-paths/fn-local-enum.rs
@@ -0,0 +1,13 @@
+// compile-pass
+// edition:2018
+
+fn main() {
+    enum E { A, B, C }
+
+    use E::*;
+    match A {
+        A => {}
+        B => {}
+        C => {}
+    }
+}
diff --git a/src/test/ui/rust-2018/uniform-paths/from-decl-macro.rs b/src/test/ui/rust-2018/uniform-paths/from-decl-macro.rs
new file mode 100644
index 0000000..5c3c753
--- /dev/null
+++ b/src/test/ui/rust-2018/uniform-paths/from-decl-macro.rs
@@ -0,0 +1,12 @@
+// compile-pass
+// edition:2018
+
+#![feature(decl_macro)]
+
+macro check() {
+    ::std::vec::Vec::<u8>::new()
+}
+
+fn main() {
+    check!();
+}
diff --git a/src/test/ui/rust-2018/uniform-paths/issue-54253.rs b/src/test/ui/rust-2018/uniform-paths/issue-54253.rs
new file mode 100644
index 0000000..7db4699
--- /dev/null
+++ b/src/test/ui/rust-2018/uniform-paths/issue-54253.rs
@@ -0,0 +1,17 @@
+// edition:2018
+
+// Dummy import that previously introduced uniform path canaries.
+use std;
+
+// fn version() -> &'static str {""}
+
+mod foo {
+    // Error wasn't reported, despite `version` being commented out above.
+    use crate::version; //~ ERROR unresolved import `crate::version`
+
+    fn bar() {
+        version();
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/rust-2018/uniform-paths/issue-54253.stderr b/src/test/ui/rust-2018/uniform-paths/issue-54253.stderr
new file mode 100644
index 0000000..adde635
--- /dev/null
+++ b/src/test/ui/rust-2018/uniform-paths/issue-54253.stderr
@@ -0,0 +1,9 @@
+error[E0432]: unresolved import `crate::version`
+  --> $DIR/issue-54253.rs:10:9
+   |
+LL |     use crate::version;
+   |         ^^^^^^^^^^^^^^ no `version` in the root
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/rust-2018/uniform-paths/issue-56596-2.rs b/src/test/ui/rust-2018/uniform-paths/issue-56596-2.rs
new file mode 100644
index 0000000..9ec3a64
--- /dev/null
+++ b/src/test/ui/rust-2018/uniform-paths/issue-56596-2.rs
@@ -0,0 +1,11 @@
+// compile-pass
+// edition:2018
+// compile-flags: --extern issue_56596_2
+// aux-build:issue-56596-2.rs
+
+mod m {
+    use core::any;
+    pub use issue_56596_2::*;
+}
+
+fn main() {}
diff --git a/src/test/ui/rust-2018/uniform-paths/issue-56596.rs b/src/test/ui/rust-2018/uniform-paths/issue-56596.rs
new file mode 100644
index 0000000..5c40d78
--- /dev/null
+++ b/src/test/ui/rust-2018/uniform-paths/issue-56596.rs
@@ -0,0 +1,14 @@
+// edition:2018
+// compile-flags: --extern issue_56596
+// aux-build:issue-56596.rs
+
+#![feature(uniform_paths)]
+
+mod m {
+    pub mod issue_56596 {}
+}
+
+use m::*;
+use issue_56596; //~ ERROR `issue_56596` is ambiguous
+
+fn main() {}
diff --git a/src/test/ui/rust-2018/uniform-paths/issue-56596.stderr b/src/test/ui/rust-2018/uniform-paths/issue-56596.stderr
new file mode 100644
index 0000000..b1c0b46
--- /dev/null
+++ b/src/test/ui/rust-2018/uniform-paths/issue-56596.stderr
@@ -0,0 +1,18 @@
+error[E0659]: `issue_56596` is ambiguous (name vs any other name during import resolution)
+  --> $DIR/issue-56596.rs:12:5
+   |
+LL | use issue_56596;
+   |     ^^^^^^^^^^^ ambiguous name
+   |
+   = note: `issue_56596` could refer to an extern crate passed with `--extern`
+   = help: use `::issue_56596` to refer to this extern crate unambiguously
+note: `issue_56596` could also refer to the module imported here
+  --> $DIR/issue-56596.rs:11:5
+   |
+LL | use m::*;
+   |     ^^^^
+   = help: use `crate::issue_56596` to refer to this module unambiguously
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0659`.
diff --git a/src/test/ui/rust-2018/uniform-paths/macro-rules.rs b/src/test/ui/rust-2018/uniform-paths/macro-rules.rs
new file mode 100644
index 0000000..6c3f189
--- /dev/null
+++ b/src/test/ui/rust-2018/uniform-paths/macro-rules.rs
@@ -0,0 +1,43 @@
+// edition:2018
+
+#![feature(decl_macro)]
+
+mod m1 {
+    // Non-exported legacy macros are treated as `pub(crate)`.
+    macro_rules! legacy_macro { () => () }
+
+    use legacy_macro as _; // OK
+    pub(crate) use legacy_macro as _; // OK
+    pub use legacy_macro as _; //~ ERROR `legacy_macro` is private, and cannot be re-exported
+}
+
+mod m2 {
+    macro_rules! legacy_macro { () => () }
+
+    #[allow(non_camel_case_types)]
+    type legacy_macro = u8;
+
+    // Legacy macro imports don't prevent names from other namespaces from being imported.
+    use legacy_macro as _; // OK
+}
+
+mod m3 {
+    macro legacy_macro() {}
+
+    fn f() {
+        macro_rules! legacy_macro { () => () }
+
+        // Legacy macro imports create ambiguities with other names in the same namespace.
+        use legacy_macro as _; //~ ERROR `legacy_macro` is ambiguous
+    }
+}
+
+mod exported {
+    // Exported legacy macros are treated as `pub`.
+    #[macro_export]
+    macro_rules! legacy_macro { () => () }
+
+    pub use legacy_macro as _; // OK
+}
+
+fn main() {}
diff --git a/src/test/ui/rust-2018/uniform-paths/macro-rules.stderr b/src/test/ui/rust-2018/uniform-paths/macro-rules.stderr
new file mode 100644
index 0000000..e1000e5
--- /dev/null
+++ b/src/test/ui/rust-2018/uniform-paths/macro-rules.stderr
@@ -0,0 +1,34 @@
+error[E0364]: `legacy_macro` is private, and cannot be re-exported
+  --> $DIR/macro-rules.rs:11:13
+   |
+LL |     pub use legacy_macro as _;
+   |             ^^^^^^^^^^^^^^^^^
+   |
+note: consider marking `legacy_macro` as `pub` in the imported module
+  --> $DIR/macro-rules.rs:11:13
+   |
+LL |     pub use legacy_macro as _;
+   |             ^^^^^^^^^^^^^^^^^
+
+error[E0659]: `legacy_macro` is ambiguous (name vs any other name during import resolution)
+  --> $DIR/macro-rules.rs:31:13
+   |
+LL |         use legacy_macro as _;
+   |             ^^^^^^^^^^^^ ambiguous name
+   |
+note: `legacy_macro` could refer to the macro defined here
+  --> $DIR/macro-rules.rs:28:9
+   |
+LL |         macro_rules! legacy_macro { () => () }
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: `legacy_macro` could also refer to the macro defined here
+  --> $DIR/macro-rules.rs:25:5
+   |
+LL |     macro legacy_macro() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+   = help: use `self::legacy_macro` to refer to this macro unambiguously
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0364, E0659.
+For more information about an error, try `rustc --explain E0364`.
diff --git a/src/test/ui/rust-2018/uniform-paths/prelude-fail-2.rs b/src/test/ui/rust-2018/uniform-paths/prelude-fail-2.rs
new file mode 100644
index 0000000..541fc1b
--- /dev/null
+++ b/src/test/ui/rust-2018/uniform-paths/prelude-fail-2.rs
@@ -0,0 +1,19 @@
+// edition:2018
+
+// Built-in attribute
+use inline as imported_inline;
+mod builtin {
+    pub use inline as imported_inline;
+}
+
+// Tool module
+use rustfmt as imported_rustfmt;
+mod tool_mod {
+    pub use rustfmt as imported_rustfmt;
+}
+
+#[imported_inline] //~ ERROR cannot use a built-in attribute through an import
+#[builtin::imported_inline] //~ ERROR cannot use a built-in attribute through an import
+#[imported_rustfmt::skip] //~ ERROR cannot use a tool module through an import
+#[tool_mod::imported_rustfmt::skip] //~ ERROR cannot use a tool module through an import
+fn main() {}
diff --git a/src/test/ui/rust-2018/uniform-paths/prelude-fail-2.stderr b/src/test/ui/rust-2018/uniform-paths/prelude-fail-2.stderr
new file mode 100644
index 0000000..fc64531
--- /dev/null
+++ b/src/test/ui/rust-2018/uniform-paths/prelude-fail-2.stderr
@@ -0,0 +1,44 @@
+error: cannot use a built-in attribute through an import
+  --> $DIR/prelude-fail-2.rs:15:3
+   |
+LL | #[imported_inline]
+   |   ^^^^^^^^^^^^^^^
+   |
+note: the built-in attribute imported here
+  --> $DIR/prelude-fail-2.rs:4:5
+   |
+LL | use inline as imported_inline;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: cannot use a built-in attribute through an import
+  --> $DIR/prelude-fail-2.rs:16:3
+   |
+LL | #[builtin::imported_inline]
+   |   ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: cannot use a tool module through an import
+  --> $DIR/prelude-fail-2.rs:17:3
+   |
+LL | #[imported_rustfmt::skip]
+   |   ^^^^^^^^^^^^^^^^
+   |
+note: the tool module imported here
+  --> $DIR/prelude-fail-2.rs:10:5
+   |
+LL | use rustfmt as imported_rustfmt;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: cannot use a tool module through an import
+  --> $DIR/prelude-fail-2.rs:18:13
+   |
+LL | #[tool_mod::imported_rustfmt::skip]
+   |             ^^^^^^^^^^^^^^^^
+   |
+note: the tool module imported here
+  --> $DIR/prelude-fail-2.rs:12:13
+   |
+LL |     pub use rustfmt as imported_rustfmt;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/rust-2018/uniform-paths/prelude-fail.rs b/src/test/ui/rust-2018/uniform-paths/prelude-fail.rs
new file mode 100644
index 0000000..d717884
--- /dev/null
+++ b/src/test/ui/rust-2018/uniform-paths/prelude-fail.rs
@@ -0,0 +1,11 @@
+// edition:2018
+
+// Built-in macro
+use env as env_imported; //~ ERROR cannot import a built-in macro
+
+// Tool attribute
+use rustfmt::skip as imported_rustfmt_skip; //~ ERROR unresolved import `rustfmt`
+
+fn main() {
+    env_imported!("PATH");
+}
diff --git a/src/test/ui/rust-2018/uniform-paths/prelude-fail.stderr b/src/test/ui/rust-2018/uniform-paths/prelude-fail.stderr
new file mode 100644
index 0000000..a61af69
--- /dev/null
+++ b/src/test/ui/rust-2018/uniform-paths/prelude-fail.stderr
@@ -0,0 +1,15 @@
+error: cannot import a built-in macro
+  --> $DIR/prelude-fail.rs:4:5
+   |
+LL | use env as env_imported;
+   |     ^^^^^^^^^^^^^^^^^^^
+
+error[E0432]: unresolved import `rustfmt`
+  --> $DIR/prelude-fail.rs:7:5
+   |
+LL | use rustfmt::skip as imported_rustfmt_skip;
+   |     ^^^^^^^ not a module `rustfmt`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/rust-2018/uniform-paths/prelude.rs b/src/test/ui/rust-2018/uniform-paths/prelude.rs
new file mode 100644
index 0000000..9a326b4
--- /dev/null
+++ b/src/test/ui/rust-2018/uniform-paths/prelude.rs
@@ -0,0 +1,18 @@
+// compile-pass
+// edition:2018
+
+// Macro imported with `#[macro_use] extern crate`
+use vec as imported_vec;
+
+// Standard library prelude
+use Vec as ImportedVec;
+
+// Built-in type
+use u8 as imported_u8;
+
+type A = imported_u8;
+
+fn main() {
+    imported_vec![0];
+    ImportedVec::<u8>::new();
+}
diff --git a/src/test/ui/rust-2018/uniform-paths/redundant.rs b/src/test/ui/rust-2018/uniform-paths/redundant.rs
new file mode 100644
index 0000000..2d306eb
--- /dev/null
+++ b/src/test/ui/rust-2018/uniform-paths/redundant.rs
@@ -0,0 +1,20 @@
+// run-pass
+// edition:2018
+
+use std;
+use std::io;
+
+mod foo {
+    pub use std as my_std;
+}
+
+mod bar {
+    pub use std::{self};
+}
+
+fn main() {
+    io::stdout();
+    self::std::io::stdout();
+    foo::my_std::io::stdout();
+    bar::std::io::stdout();
+}
diff --git a/src/test/ui/rust-unstable-column-gated.rs b/src/test/ui/rust-unstable-column-gated.rs
new file mode 100644
index 0000000..ed5e6f2
--- /dev/null
+++ b/src/test/ui/rust-unstable-column-gated.rs
@@ -0,0 +1,4 @@
+fn main() {
+    println!("{}", __rust_unstable_column!());
+    //~^ERROR the __rust_unstable_column macro is unstable
+}
diff --git a/src/test/ui/rust-unstable-column-gated.stderr b/src/test/ui/rust-unstable-column-gated.stderr
new file mode 100644
index 0000000..b9f1df2
--- /dev/null
+++ b/src/test/ui/rust-unstable-column-gated.stderr
@@ -0,0 +1,8 @@
+error: the __rust_unstable_column macro is unstable
+  --> $DIR/rust-unstable-column-gated.rs:2:20
+   |
+LL |     println!("{}", __rust_unstable_column!());
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rustc-args-required-const.rs b/src/test/ui/rustc-args-required-const.rs
new file mode 100644
index 0000000..87f979f
--- /dev/null
+++ b/src/test/ui/rustc-args-required-const.rs
@@ -0,0 +1,27 @@
+#![feature(rustc_attrs, const_fn)]
+
+#[rustc_args_required_const(0)]
+fn foo(_a: i32) {
+}
+
+#[rustc_args_required_const(1)]
+fn bar(_a: i32, _b: i32) {
+}
+
+const A: i32 = 3;
+
+const fn baz() -> i32 {
+    3
+}
+
+fn main() {
+    foo(2);
+    foo(2 + 3);
+    const BAZ: i32 = baz();
+    foo(BAZ);
+    let a = 4;
+    foo(A);
+    foo(a); //~ ERROR: argument 1 is required to be a constant
+    bar(a, 3);
+    bar(a, a); //~ ERROR: argument 2 is required to be a constant
+}
diff --git a/src/test/ui/rustc-args-required-const.stderr b/src/test/ui/rustc-args-required-const.stderr
new file mode 100644
index 0000000..8b30269
--- /dev/null
+++ b/src/test/ui/rustc-args-required-const.stderr
@@ -0,0 +1,14 @@
+error: argument 1 is required to be a constant
+  --> $DIR/rustc-args-required-const.rs:24:5
+   |
+LL |     foo(a);
+   |     ^^^^^^
+
+error: argument 2 is required to be a constant
+  --> $DIR/rustc-args-required-const.rs:26:5
+   |
+LL |     bar(a, a);
+   |     ^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/rustc-args-required-const2.rs b/src/test/ui/rustc-args-required-const2.rs
new file mode 100644
index 0000000..5feeca6
--- /dev/null
+++ b/src/test/ui/rustc-args-required-const2.rs
@@ -0,0 +1,10 @@
+#![feature(rustc_attrs, const_fn)]
+
+#[rustc_args_required_const(0)]
+fn foo(_a: i32) {
+}
+
+fn main() {
+    let a = foo; //~ ERROR: this function can only be invoked directly
+    a(2);
+}
diff --git a/src/test/ui/rustc-args-required-const2.stderr b/src/test/ui/rustc-args-required-const2.stderr
new file mode 100644
index 0000000..a8906ad
--- /dev/null
+++ b/src/test/ui/rustc-args-required-const2.stderr
@@ -0,0 +1,8 @@
+error: this function can only be invoked directly, not through a function pointer
+  --> $DIR/rustc-args-required-const2.rs:8:13
+   |
+LL |     let a = foo;
+   |             ^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rustc-error.rs b/src/test/ui/rustc-error.rs
new file mode 100644
index 0000000..0504198
--- /dev/null
+++ b/src/test/ui/rustc-error.rs
@@ -0,0 +1,6 @@
+#![feature(rustc_attrs)]
+
+#[rustc_error]
+fn main() {
+    //~^ ERROR compilation successful
+}
diff --git a/src/test/ui/rustc-error.stderr b/src/test/ui/rustc-error.stderr
new file mode 100644
index 0000000..dcbc0e1
--- /dev/null
+++ b/src/test/ui/rustc-error.stderr
@@ -0,0 +1,10 @@
+error: compilation successful
+  --> $DIR/rustc-error.rs:4:1
+   |
+LL | / fn main() {
+LL | |
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/safe-extern-statics-mut.rs b/src/test/ui/safe-extern-statics-mut.rs
new file mode 100644
index 0000000..dbf0f52
--- /dev/null
+++ b/src/test/ui/safe-extern-statics-mut.rs
@@ -0,0 +1,15 @@
+// aux-build:extern-statics.rs
+
+extern crate extern_statics;
+use extern_statics::*;
+
+extern {
+    static mut B: u8;
+}
+
+fn main() {
+    let b = B; //~ ERROR use of mutable static is unsafe
+    let rb = &B; //~ ERROR use of mutable static is unsafe
+    let xb = XB; //~ ERROR use of mutable static is unsafe
+    let xrb = &XB; //~ ERROR use of mutable static is unsafe
+}
diff --git a/src/test/ui/safe-extern-statics-mut.stderr b/src/test/ui/safe-extern-statics-mut.stderr
new file mode 100644
index 0000000..3880388
--- /dev/null
+++ b/src/test/ui/safe-extern-statics-mut.stderr
@@ -0,0 +1,35 @@
+error[E0133]: use of mutable static is unsafe and requires unsafe function or block
+  --> $DIR/safe-extern-statics-mut.rs:11:13
+   |
+LL |     let b = B;
+   |             ^ use of mutable static
+   |
+   = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
+
+error[E0133]: use of mutable static is unsafe and requires unsafe function or block
+  --> $DIR/safe-extern-statics-mut.rs:12:14
+   |
+LL |     let rb = &B;
+   |              ^^ use of mutable static
+   |
+   = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
+
+error[E0133]: use of mutable static is unsafe and requires unsafe function or block
+  --> $DIR/safe-extern-statics-mut.rs:13:14
+   |
+LL |     let xb = XB;
+   |              ^^ use of mutable static
+   |
+   = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
+
+error[E0133]: use of mutable static is unsafe and requires unsafe function or block
+  --> $DIR/safe-extern-statics-mut.rs:14:15
+   |
+LL |     let xrb = &XB;
+   |               ^^^ use of mutable static
+   |
+   = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/safe-extern-statics.rs b/src/test/ui/safe-extern-statics.rs
new file mode 100644
index 0000000..eda3094
--- /dev/null
+++ b/src/test/ui/safe-extern-statics.rs
@@ -0,0 +1,21 @@
+// aux-build:extern-statics.rs
+
+#![allow(unused)]
+
+extern crate extern_statics;
+use extern_statics::*;
+
+extern {
+    static A: u8;
+}
+
+fn main() {
+    let a = A; //~ ERROR use of extern static is unsafe
+               //~^ WARN this was previously accepted by the compiler
+    let ra = &A; //~ ERROR use of extern static is unsafe
+                 //~^ WARN this was previously accepted by the compiler
+    let xa = XA; //~ ERROR use of extern static is unsafe
+                 //~^ WARN this was previously accepted by the compiler
+    let xra = &XA; //~ ERROR use of extern static is unsafe
+                   //~^ WARN this was previously accepted by the compiler
+}
diff --git a/src/test/ui/safe-extern-statics.stderr b/src/test/ui/safe-extern-statics.stderr
new file mode 100644
index 0000000..86976a2
--- /dev/null
+++ b/src/test/ui/safe-extern-statics.stderr
@@ -0,0 +1,43 @@
+error: use of extern static is unsafe and requires unsafe function or block (error E0133)
+  --> $DIR/safe-extern-statics.rs:13:13
+   |
+LL |     let a = A;
+   |             ^
+   |
+   = note: #[deny(safe_extern_statics)] on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #36247 <https://github.com/rust-lang/rust/issues/36247>
+   = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
+
+error: use of extern static is unsafe and requires unsafe function or block (error E0133)
+  --> $DIR/safe-extern-statics.rs:15:14
+   |
+LL |     let ra = &A;
+   |              ^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #36247 <https://github.com/rust-lang/rust/issues/36247>
+   = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
+
+error: use of extern static is unsafe and requires unsafe function or block (error E0133)
+  --> $DIR/safe-extern-statics.rs:17:14
+   |
+LL |     let xa = XA;
+   |              ^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #36247 <https://github.com/rust-lang/rust/issues/36247>
+   = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
+
+error: use of extern static is unsafe and requires unsafe function or block (error E0133)
+  --> $DIR/safe-extern-statics.rs:19:15
+   |
+LL |     let xra = &XA;
+   |               ^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #36247 <https://github.com/rust-lang/rust/issues/36247>
+   = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/save-analysis/issue-59134-0.rs b/src/test/ui/save-analysis/issue-59134-0.rs
new file mode 100644
index 0000000..3158328
--- /dev/null
+++ b/src/test/ui/save-analysis/issue-59134-0.rs
@@ -0,0 +1,12 @@
+// compile-flags: -Zsave-analysis
+
+// Check that this doesn't ICE when processing associated const (field expr).
+
+pub fn f() {
+    trait Trait {}
+    impl Trait {
+        const FLAG: u32 = bogus.field; //~ ERROR cannot find value `bogus`
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/save-analysis/issue-59134-0.stderr b/src/test/ui/save-analysis/issue-59134-0.stderr
new file mode 100644
index 0000000..4e9b2e6
--- /dev/null
+++ b/src/test/ui/save-analysis/issue-59134-0.stderr
@@ -0,0 +1,9 @@
+error[E0425]: cannot find value `bogus` in this scope
+  --> $DIR/issue-59134-0.rs:8:27
+   |
+LL |         const FLAG: u32 = bogus.field;
+   |                           ^^^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/save-analysis/issue-59134-1.rs b/src/test/ui/save-analysis/issue-59134-1.rs
new file mode 100644
index 0000000..3cb6297
--- /dev/null
+++ b/src/test/ui/save-analysis/issue-59134-1.rs
@@ -0,0 +1,12 @@
+// compile-flags: -Zsave-analysis
+
+// Check that this doesn't ICE when processing associated const (type).
+
+fn func() {
+    trait Trait {
+        type MyType;
+        const CONST: Self::MyType = bogus.field; //~ ERROR cannot find value `bogus`
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/save-analysis/issue-59134-1.stderr b/src/test/ui/save-analysis/issue-59134-1.stderr
new file mode 100644
index 0000000..bdc335e
--- /dev/null
+++ b/src/test/ui/save-analysis/issue-59134-1.stderr
@@ -0,0 +1,9 @@
+error[E0425]: cannot find value `bogus` in this scope
+  --> $DIR/issue-59134-1.rs:8:37
+   |
+LL |         const CONST: Self::MyType = bogus.field;
+   |                                     ^^^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/self/self-impl.rs b/src/test/ui/self/self-impl.rs
new file mode 100644
index 0000000..ed250ce
--- /dev/null
+++ b/src/test/ui/self/self-impl.rs
@@ -0,0 +1,30 @@
+// Test that unsupported uses of `Self` in impls don't crash
+
+struct Bar;
+
+trait Foo {
+    type Baz;
+}
+
+trait SuperFoo {
+    type SuperBaz;
+}
+
+impl Foo for Bar {
+    type Baz = bool;
+}
+
+impl SuperFoo for Bar {
+    type SuperBaz = bool;
+}
+
+impl Bar {
+    fn f() {
+        let _: <Self>::Baz = true;
+        //~^ ERROR ambiguous associated type
+        let _: Self::Baz = true;
+        //~^ ERROR ambiguous associated type
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/self/self-impl.stderr b/src/test/ui/self/self-impl.stderr
new file mode 100644
index 0000000..fb47f27
--- /dev/null
+++ b/src/test/ui/self/self-impl.stderr
@@ -0,0 +1,15 @@
+error[E0223]: ambiguous associated type
+  --> $DIR/self-impl.rs:23:16
+   |
+LL |         let _: <Self>::Baz = true;
+   |                ^^^^^^^^^^^ help: use fully-qualified syntax: `<Bar as Trait>::Baz`
+
+error[E0223]: ambiguous associated type
+  --> $DIR/self-impl.rs:25:16
+   |
+LL |         let _: Self::Baz = true;
+   |                ^^^^^^^^^ help: use fully-qualified syntax: `<Bar as Trait>::Baz`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0223`.
diff --git a/src/test/ui/self/self-infer.rs b/src/test/ui/self/self-infer.rs
new file mode 100644
index 0000000..0956f2a
--- /dev/null
+++ b/src/test/ui/self/self-infer.rs
@@ -0,0 +1,8 @@
+struct S;
+
+impl S {
+    fn f(self: _) {} //~ERROR the type placeholder `_` is not allowed within types on item sig
+    fn g(self: &_) {} //~ERROR the type placeholder `_` is not allowed within types on item sig
+}
+
+fn main() {}
diff --git a/src/test/ui/self/self-infer.stderr b/src/test/ui/self/self-infer.stderr
new file mode 100644
index 0000000..f91cfe5
--- /dev/null
+++ b/src/test/ui/self/self-infer.stderr
@@ -0,0 +1,15 @@
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/self-infer.rs:4:16
+   |
+LL |     fn f(self: _) {}
+   |                ^ not allowed in type signatures
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/self-infer.rs:5:17
+   |
+LL |     fn g(self: &_) {}
+   |                 ^ not allowed in type signatures
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0121`.
diff --git a/src/test/ui/self/self-vs-path-ambiguity.rs b/src/test/ui/self/self-vs-path-ambiguity.rs
new file mode 100644
index 0000000..5a06d56
--- /dev/null
+++ b/src/test/ui/self/self-vs-path-ambiguity.rs
@@ -0,0 +1,12 @@
+// Check that `self::foo` is parsed as a general pattern and not a self argument.
+
+struct S;
+
+impl S {
+    fn f(self::S: S) {}
+    fn g(&self::S: &S) {}
+    fn h(&mut self::S: &mut S) {}
+    fn i(&'a self::S: &S) {} //~ ERROR unexpected lifetime `'a` in pattern
+}
+
+fn main() {}
diff --git a/src/test/ui/self/self-vs-path-ambiguity.stderr b/src/test/ui/self/self-vs-path-ambiguity.stderr
new file mode 100644
index 0000000..5ce6a81
--- /dev/null
+++ b/src/test/ui/self/self-vs-path-ambiguity.stderr
@@ -0,0 +1,8 @@
+error: unexpected lifetime `'a` in pattern
+  --> $DIR/self-vs-path-ambiguity.rs:9:11
+   |
+LL |     fn i(&'a self::S: &S) {}
+   |           ^^ unexpected lifetime
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/self/self_type_keyword-2.rs b/src/test/ui/self/self_type_keyword-2.rs
new file mode 100644
index 0000000..dde5762
--- /dev/null
+++ b/src/test/ui/self/self_type_keyword-2.rs
@@ -0,0 +1,13 @@
+use self::Self as Foo; //~ ERROR unresolved import `self::Self`
+
+pub fn main() {
+    let Self = 5;
+    //~^ ERROR cannot find unit struct/variant or constant `Self` in this scope
+
+    match 15 {
+        Self => (),
+        //~^ ERROR cannot find unit struct/variant or constant `Self` in this scope
+        Foo { x: Self } => (),
+        //~^ ERROR cannot find unit struct/variant or constant `Self` in this scope
+    }
+}
diff --git a/src/test/ui/self/self_type_keyword-2.stderr b/src/test/ui/self/self_type_keyword-2.stderr
new file mode 100644
index 0000000..eedec68
--- /dev/null
+++ b/src/test/ui/self/self_type_keyword-2.stderr
@@ -0,0 +1,28 @@
+error[E0432]: unresolved import `self::Self`
+  --> $DIR/self_type_keyword-2.rs:1:5
+   |
+LL | use self::Self as Foo;
+   |     ^^^^^^^^^^^^^^^^^ no `Self` in the root
+
+error[E0531]: cannot find unit struct/variant or constant `Self` in this scope
+  --> $DIR/self_type_keyword-2.rs:4:9
+   |
+LL |     let Self = 5;
+   |         ^^^^ not found in this scope
+
+error[E0531]: cannot find unit struct/variant or constant `Self` in this scope
+  --> $DIR/self_type_keyword-2.rs:8:9
+   |
+LL |         Self => (),
+   |         ^^^^ not found in this scope
+
+error[E0531]: cannot find unit struct/variant or constant `Self` in this scope
+  --> $DIR/self_type_keyword-2.rs:10:18
+   |
+LL |         Foo { x: Self } => (),
+   |                  ^^^^ not found in this scope
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0432, E0531.
+For more information about an error, try `rustc --explain E0432`.
diff --git a/src/test/ui/self/self_type_keyword.rs b/src/test/ui/self/self_type_keyword.rs
new file mode 100644
index 0000000..4a1681e
--- /dev/null
+++ b/src/test/ui/self/self_type_keyword.rs
@@ -0,0 +1,42 @@
+// compile-flags: -Z continue-parse-after-error
+
+mod foo {
+  struct Self;
+  //~^ ERROR expected identifier, found keyword `Self`
+}
+
+struct Bar<'Self>;
+//~^ ERROR lifetimes cannot use keyword names
+//~| ERROR parameter `'Self` is never used
+
+struct Foo;
+
+pub fn main() {
+    match 15 {
+        ref Self => (),
+        //~^ ERROR expected identifier, found keyword `Self`
+        mut Self => (),
+        //~^ ERROR expected identifier, found keyword `Self`
+        ref mut Self => (),
+        //~^ ERROR expected identifier, found keyword `Self`
+        Self!() => (),
+        //~^ ERROR cannot find macro `Self!` in this scope
+        Foo { Self } => (),
+        //~^ ERROR expected identifier, found keyword `Self`
+    }
+}
+
+mod m1 {
+    extern crate core as Self;
+    //~^ ERROR expected identifier, found keyword `Self`
+}
+
+mod m2 {
+    use std::option::Option as Self;
+    //~^ ERROR expected identifier, found keyword `Self`
+}
+
+mod m3 {
+    trait Self {}
+    //~^ ERROR expected identifier, found keyword `Self`
+}
diff --git a/src/test/ui/self/self_type_keyword.stderr b/src/test/ui/self/self_type_keyword.stderr
new file mode 100644
index 0000000..f75377a
--- /dev/null
+++ b/src/test/ui/self/self_type_keyword.stderr
@@ -0,0 +1,71 @@
+error: expected identifier, found keyword `Self`
+  --> $DIR/self_type_keyword.rs:4:10
+   |
+LL |   struct Self;
+   |          ^^^^ expected identifier, found keyword
+
+error: expected identifier, found keyword `Self`
+  --> $DIR/self_type_keyword.rs:16:13
+   |
+LL |         ref Self => (),
+   |             ^^^^ expected identifier, found keyword
+
+error: expected identifier, found keyword `Self`
+  --> $DIR/self_type_keyword.rs:18:13
+   |
+LL |         mut Self => (),
+   |             ^^^^ expected identifier, found keyword
+
+error: expected identifier, found keyword `Self`
+  --> $DIR/self_type_keyword.rs:20:17
+   |
+LL |         ref mut Self => (),
+   |                 ^^^^ expected identifier, found keyword
+
+error: expected identifier, found keyword `Self`
+  --> $DIR/self_type_keyword.rs:24:15
+   |
+LL |         Foo { Self } => (),
+   |               ^^^^ expected identifier, found keyword
+
+error: expected identifier, found keyword `Self`
+  --> $DIR/self_type_keyword.rs:30:26
+   |
+LL |     extern crate core as Self;
+   |                          ^^^^ expected identifier, found keyword
+
+error: expected identifier, found keyword `Self`
+  --> $DIR/self_type_keyword.rs:35:32
+   |
+LL |     use std::option::Option as Self;
+   |                                ^^^^ expected identifier, found keyword
+
+error: expected identifier, found keyword `Self`
+  --> $DIR/self_type_keyword.rs:40:11
+   |
+LL |     trait Self {}
+   |           ^^^^ expected identifier, found keyword
+
+error: lifetimes cannot use keyword names
+  --> $DIR/self_type_keyword.rs:8:12
+   |
+LL | struct Bar<'Self>;
+   |            ^^^^^
+
+error: cannot find macro `Self!` in this scope
+  --> $DIR/self_type_keyword.rs:22:9
+   |
+LL |         Self!() => (),
+   |         ^^^^
+
+error[E0392]: parameter `'Self` is never used
+  --> $DIR/self_type_keyword.rs:8:12
+   |
+LL | struct Bar<'Self>;
+   |            ^^^^^ unused type parameter
+   |
+   = help: consider removing `'Self` or using a marker such as `std::marker::PhantomData`
+
+error: aborting due to 11 previous errors
+
+For more information about this error, try `rustc --explain E0392`.
diff --git a/src/test/ui/self/suggest-self.rs b/src/test/ui/self/suggest-self.rs
new file mode 100644
index 0000000..9d81b6fd
--- /dev/null
+++ b/src/test/ui/self/suggest-self.rs
@@ -0,0 +1,42 @@
+struct Foo {
+    x: i32,
+}
+
+impl Foo {
+    fn this1(&self) -> i32 {
+        let this = self;
+        let a = 1;
+        this.x
+    }
+
+    fn this2(&self) -> i32 {
+        let a = Foo {
+            x: 2
+        };
+        let this = a;
+        this.x
+    }
+
+    fn foo(&self) -> i32 {
+        this.x
+        //~^ ERROR cannot find value `this` in this scope
+    }
+
+    fn bar(&self) -> i32 {
+        this.foo()
+        //~^ ERROR cannot find value `this` in this scope
+    }
+
+    fn baz(&self) -> i32 {
+        my.bar()
+        //~^ ERROR cannot find value `my` in this scope
+    }
+}
+
+fn main() {
+    let this = vec![1, 2, 3];
+    let my = vec![1, 2, 3];
+    let len = this.len();
+    let len = my.len();
+}
+
diff --git a/src/test/ui/self/suggest-self.stderr b/src/test/ui/self/suggest-self.stderr
new file mode 100644
index 0000000..631e43c
--- /dev/null
+++ b/src/test/ui/self/suggest-self.stderr
@@ -0,0 +1,30 @@
+error[E0425]: cannot find value `this` in this scope
+  --> $DIR/suggest-self.rs:21:9
+   |
+LL |         this.x
+   |         ^^^^
+   |         |
+   |         not found in this scope
+   |         help: did you mean: `self`
+
+error[E0425]: cannot find value `this` in this scope
+  --> $DIR/suggest-self.rs:26:9
+   |
+LL |         this.foo()
+   |         ^^^^
+   |         |
+   |         not found in this scope
+   |         help: did you mean: `self`
+
+error[E0425]: cannot find value `my` in this scope
+  --> $DIR/suggest-self.rs:31:9
+   |
+LL |         my.bar()
+   |         ^^
+   |         |
+   |         not found in this scope
+   |         help: did you mean: `self`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/seq-args.rs b/src/test/ui/seq-args.rs
new file mode 100644
index 0000000..9bb9f12
--- /dev/null
+++ b/src/test/ui/seq-args.rs
@@ -0,0 +1,11 @@
+fn main() {
+trait Seq { }
+
+impl<T> Seq<T> for Vec<T> { //~ ERROR wrong number of type arguments
+    /* ... */
+}
+impl Seq<bool> for u32 { //~ ERROR wrong number of type arguments
+   /* Treat the integer as a sequence of bits */
+}
+
+}
diff --git a/src/test/ui/seq-args.stderr b/src/test/ui/seq-args.stderr
new file mode 100644
index 0000000..2e7d901
--- /dev/null
+++ b/src/test/ui/seq-args.stderr
@@ -0,0 +1,15 @@
+error[E0107]: wrong number of type arguments: expected 0, found 1
+  --> $DIR/seq-args.rs:4:13
+   |
+LL | impl<T> Seq<T> for Vec<T> {
+   |             ^ unexpected type argument
+
+error[E0107]: wrong number of type arguments: expected 0, found 1
+  --> $DIR/seq-args.rs:7:10
+   |
+LL | impl Seq<bool> for u32 {
+   |          ^^^^ unexpected type argument
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0107`.
diff --git a/src/test/ui/shadowed/shadowed-lifetime.rs b/src/test/ui/shadowed/shadowed-lifetime.rs
new file mode 100644
index 0000000..9487b4f
--- /dev/null
+++ b/src/test/ui/shadowed/shadowed-lifetime.rs
@@ -0,0 +1,24 @@
+// Test that shadowed lifetimes generate an error.
+
+struct Foo<'a>(&'a isize);
+
+impl<'a> Foo<'a> {
+    fn shadow_in_method<'a>(&'a self) -> &'a isize {
+        //~^ ERROR lifetime name `'a` shadows a lifetime name that is already in scope
+        self.0
+    }
+
+    fn shadow_in_type<'b>(&'b self) -> &'b isize {
+        let x: for<'b> fn(&'b isize) = panic!();
+        //~^ ERROR lifetime name `'b` shadows a lifetime name that is already in scope
+        self.0
+    }
+
+    fn not_shadow_in_item<'b>(&'b self) {
+        struct Bar<'a, 'b>(&'a isize, &'b isize); // not a shadow, separate item
+        fn foo<'a, 'b>(x: &'a isize, y: &'b isize) { } // same
+    }
+}
+
+fn main() {
+}
diff --git a/src/test/ui/shadowed/shadowed-lifetime.stderr b/src/test/ui/shadowed/shadowed-lifetime.stderr
new file mode 100644
index 0000000..5ea3d92
--- /dev/null
+++ b/src/test/ui/shadowed/shadowed-lifetime.stderr
@@ -0,0 +1,19 @@
+error[E0496]: lifetime name `'a` shadows a lifetime name that is already in scope
+  --> $DIR/shadowed-lifetime.rs:6:25
+   |
+LL | impl<'a> Foo<'a> {
+   |      -- first declared here
+LL |     fn shadow_in_method<'a>(&'a self) -> &'a isize {
+   |                         ^^ lifetime 'a already in scope
+
+error[E0496]: lifetime name `'b` shadows a lifetime name that is already in scope
+  --> $DIR/shadowed-lifetime.rs:12:20
+   |
+LL |     fn shadow_in_type<'b>(&'b self) -> &'b isize {
+   |                       -- first declared here
+LL |         let x: for<'b> fn(&'b isize) = panic!();
+   |                    ^^ lifetime 'b already in scope
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0496`.
diff --git a/src/test/ui/shadowed/shadowed-trait-methods.rs b/src/test/ui/shadowed/shadowed-trait-methods.rs
new file mode 100644
index 0000000..f9c25d9
--- /dev/null
+++ b/src/test/ui/shadowed/shadowed-trait-methods.rs
@@ -0,0 +1,14 @@
+// Test that methods from shadowed traits cannot be used
+
+mod foo {
+    pub trait T { fn f(&self) {} }
+    impl T for () {}
+}
+
+mod bar { pub use foo::T; }
+
+fn main() {
+    pub use bar::*;
+    struct T;
+    ().f() //~ ERROR no method
+}
diff --git a/src/test/ui/shadowed/shadowed-trait-methods.stderr b/src/test/ui/shadowed/shadowed-trait-methods.stderr
new file mode 100644
index 0000000..e05da17
--- /dev/null
+++ b/src/test/ui/shadowed/shadowed-trait-methods.stderr
@@ -0,0 +1,15 @@
+error[E0599]: no method named `f` found for type `()` in the current scope
+  --> $DIR/shadowed-trait-methods.rs:13:8
+   |
+LL |     ().f()
+   |        ^
+   |
+   = help: items from traits can only be used if the trait is in scope
+help: the following trait is implemented but not in scope, perhaps add a `use` for it:
+   |
+LL | use foo::T;
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/shadowed/shadowed-type-parameter.rs b/src/test/ui/shadowed/shadowed-type-parameter.rs
new file mode 100644
index 0000000..ba9f3ab
--- /dev/null
+++ b/src/test/ui/shadowed/shadowed-type-parameter.rs
@@ -0,0 +1,30 @@
+// Test that shadowed lifetimes generate an error.
+
+#![feature(box_syntax)]
+
+struct Foo<T>(T);
+
+impl<T> Foo<T> {
+    fn shadow_in_method<T>(&self) {}
+    //~^ ERROR type parameter `T` shadows another type parameter
+
+    fn not_shadow_in_item<U>(&self) {
+        struct Bar<T, U>(T,U); // not a shadow, separate item
+        fn foo<T, U>() {} // same
+    }
+}
+
+trait Bar<T> {
+    fn dummy(&self) -> T;
+
+    fn shadow_in_required<T>(&self);
+    //~^ ERROR type parameter `T` shadows another type parameter
+
+    fn shadow_in_provided<T>(&self) {}
+    //~^ ERROR type parameter `T` shadows another type parameter
+
+    fn not_shadow_in_required<U>(&self);
+    fn not_shadow_in_provided<U>(&self) {}
+}
+
+fn main() {}
diff --git a/src/test/ui/shadowed/shadowed-type-parameter.stderr b/src/test/ui/shadowed/shadowed-type-parameter.stderr
new file mode 100644
index 0000000..6b4d1fa
--- /dev/null
+++ b/src/test/ui/shadowed/shadowed-type-parameter.stderr
@@ -0,0 +1,29 @@
+error[E0194]: type parameter `T` shadows another type parameter of the same name
+  --> $DIR/shadowed-type-parameter.rs:20:27
+   |
+LL | trait Bar<T> {
+   |           - first `T` declared here
+...
+LL |     fn shadow_in_required<T>(&self);
+   |                           ^ shadows another type parameter
+
+error[E0194]: type parameter `T` shadows another type parameter of the same name
+  --> $DIR/shadowed-type-parameter.rs:23:27
+   |
+LL | trait Bar<T> {
+   |           - first `T` declared here
+...
+LL |     fn shadow_in_provided<T>(&self) {}
+   |                           ^ shadows another type parameter
+
+error[E0194]: type parameter `T` shadows another type parameter of the same name
+  --> $DIR/shadowed-type-parameter.rs:8:25
+   |
+LL | impl<T> Foo<T> {
+   |      - first `T` declared here
+LL |     fn shadow_in_method<T>(&self) {}
+   |                         ^ shadows another type parameter
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0194`.
diff --git a/src/test/ui/shadowed/shadowed-use-visibility.rs b/src/test/ui/shadowed/shadowed-use-visibility.rs
new file mode 100644
index 0000000..8185e82
--- /dev/null
+++ b/src/test/ui/shadowed/shadowed-use-visibility.rs
@@ -0,0 +1,16 @@
+mod foo {
+    pub fn f() {}
+
+    use foo as bar;
+    pub use self::f as bar;
+}
+
+mod bar {
+    use foo::bar::f as g; //~ ERROR module `bar` is private
+
+    use foo as f;
+    pub use foo::*;
+}
+
+use bar::f::f; //~ ERROR module `f` is private
+fn main() {}
diff --git a/src/test/ui/shadowed/shadowed-use-visibility.stderr b/src/test/ui/shadowed/shadowed-use-visibility.stderr
new file mode 100644
index 0000000..7c66fdf
--- /dev/null
+++ b/src/test/ui/shadowed/shadowed-use-visibility.stderr
@@ -0,0 +1,15 @@
+error[E0603]: module `bar` is private
+  --> $DIR/shadowed-use-visibility.rs:9:14
+   |
+LL |     use foo::bar::f as g;
+   |              ^^^
+
+error[E0603]: module `f` is private
+  --> $DIR/shadowed-use-visibility.rs:15:10
+   |
+LL | use bar::f::f;
+   |          ^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0603`.
diff --git a/src/test/ui/shadowed/shadowing-in-the-same-pattern.rs b/src/test/ui/shadowed/shadowing-in-the-same-pattern.rs
new file mode 100644
index 0000000..f5872f9
--- /dev/null
+++ b/src/test/ui/shadowed/shadowing-in-the-same-pattern.rs
@@ -0,0 +1,7 @@
+// Test for issue #14581.
+
+fn f((a, a): (isize, isize)) {} //~ ERROR identifier `a` is bound more than once
+
+fn main() {
+    let (a, a) = (1, 1);    //~ ERROR identifier `a` is bound more than once
+}
diff --git a/src/test/ui/shadowed/shadowing-in-the-same-pattern.stderr b/src/test/ui/shadowed/shadowing-in-the-same-pattern.stderr
new file mode 100644
index 0000000..71197ef
--- /dev/null
+++ b/src/test/ui/shadowed/shadowing-in-the-same-pattern.stderr
@@ -0,0 +1,15 @@
+error[E0416]: identifier `a` is bound more than once in the same pattern
+  --> $DIR/shadowing-in-the-same-pattern.rs:3:10
+   |
+LL | fn f((a, a): (isize, isize)) {}
+   |          ^ used in a pattern more than once
+
+error[E0416]: identifier `a` is bound more than once in the same pattern
+  --> $DIR/shadowing-in-the-same-pattern.rs:6:13
+   |
+LL |     let (a, a) = (1, 1);
+   |             ^ used in a pattern more than once
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0416`.
diff --git a/src/test/ui/shift-various-bad-types.rs b/src/test/ui/shift-various-bad-types.rs
new file mode 100644
index 0000000..f385746
--- /dev/null
+++ b/src/test/ui/shift-various-bad-types.rs
@@ -0,0 +1,31 @@
+// Test that we can do shifts by any integral type.
+
+struct Panolpy {
+    char: char,
+    str: &'static str,
+}
+
+fn foo(p: &Panolpy) {
+    22 >> p.char;
+    //~^ ERROR E0277
+
+    22 >> p.str;
+    //~^ ERROR E0277
+
+    22 >> p;
+    //~^ ERROR E0277
+
+    let x;
+    22 >> x; // ambiguity error winds up being suppressed
+
+    22 >> 1;
+    // Integer literal types are OK
+
+    // Type of the result follows the LHS, not the RHS:
+    let _: i32 = 22_i64 >> 1_i32;
+    //~^ ERROR mismatched types
+    //~| expected i32, found i64
+}
+
+fn main() {
+}
diff --git a/src/test/ui/shift-various-bad-types.stderr b/src/test/ui/shift-various-bad-types.stderr
new file mode 100644
index 0000000..1bcff65
--- /dev/null
+++ b/src/test/ui/shift-various-bad-types.stderr
@@ -0,0 +1,34 @@
+error[E0277]: no implementation for `{integer} >> char`
+  --> $DIR/shift-various-bad-types.rs:9:8
+   |
+LL |     22 >> p.char;
+   |        ^^ no implementation for `{integer} >> char`
+   |
+   = help: the trait `std::ops::Shr<char>` is not implemented for `{integer}`
+
+error[E0277]: no implementation for `{integer} >> &str`
+  --> $DIR/shift-various-bad-types.rs:12:8
+   |
+LL |     22 >> p.str;
+   |        ^^ no implementation for `{integer} >> &str`
+   |
+   = help: the trait `std::ops::Shr<&str>` is not implemented for `{integer}`
+
+error[E0277]: no implementation for `{integer} >> &Panolpy`
+  --> $DIR/shift-various-bad-types.rs:15:8
+   |
+LL |     22 >> p;
+   |        ^^ no implementation for `{integer} >> &Panolpy`
+   |
+   = help: the trait `std::ops::Shr<&Panolpy>` is not implemented for `{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/shift-various-bad-types.rs:25:18
+   |
+LL |     let _: i32 = 22_i64 >> 1_i32;
+   |                  ^^^^^^^^^^^^^^^ expected i32, found i64
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0277, E0308.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/short-error-format.rs b/src/test/ui/short-error-format.rs
new file mode 100644
index 0000000..acba467
--- /dev/null
+++ b/src/test/ui/short-error-format.rs
@@ -0,0 +1,9 @@
+// compile-flags: --error-format=short
+
+fn foo(_: u32) {}
+
+fn main() {
+    foo("Bonjour".to_owned());
+    let x = 0u32;
+    x.salut();
+}
diff --git a/src/test/ui/short-error-format.stderr b/src/test/ui/short-error-format.stderr
new file mode 100644
index 0000000..8a22d67
--- /dev/null
+++ b/src/test/ui/short-error-format.stderr
@@ -0,0 +1,3 @@
+$DIR/short-error-format.rs:6:9: error[E0308]: mismatched types
+$DIR/short-error-format.rs:8:7: error[E0599]: no method named `salut` found for type `u32` in the current scope
+error: aborting due to 2 previous errors
diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.rs b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.rs
new file mode 100644
index 0000000..65cf31f
--- /dev/null
+++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.rs
@@ -0,0 +1,38 @@
+// ignore-emscripten
+// ignore-tidy-linelength
+#![feature(repr_simd, platform_intrinsics)]
+#![allow(non_camel_case_types)]
+#[repr(simd)]
+#[derive(Copy, Clone)]
+pub struct i32x4(pub i32, pub i32, pub i32, pub i32);
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+pub struct x4<T>(pub T, pub T, pub T, pub T);
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+pub struct f32x4(pub f32, pub f32, pub f32, pub f32);
+
+extern "platform-intrinsic" {
+    fn simd_saturating_add<T>(x: T, y: T) -> T;
+    fn simd_saturating_sub<T>(x: T, y: T) -> T;
+}
+
+fn main() {
+    let x = i32x4(0, 0, 0, 0);
+    let y = x4(0_usize, 0, 0, 0);
+    let z = f32x4(0.0, 0.0, 0.0, 0.0);
+
+    unsafe {
+        simd_saturating_add(x, x);
+        simd_saturating_add(y, y);
+        simd_saturating_sub(x, x);
+        simd_saturating_sub(y, y);
+
+        simd_saturating_add(z, z);
+        //~^ ERROR expected element type `f32` of vector type `f32x4` to be a signed or unsigned integer type
+        simd_saturating_sub(z, z);
+        //~^ ERROR expected element type `f32` of vector type `f32x4` to be a signed or unsigned integer type
+    }
+}
diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.stderr b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.stderr
new file mode 100644
index 0000000..0e88540
--- /dev/null
+++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.stderr
@@ -0,0 +1,15 @@
+error[E0511]: invalid monomorphization of `simd_saturating_add` intrinsic: expected element type `f32` of vector type `f32x4` to be a signed or unsigned integer type
+  --> $DIR/simd-intrinsic-generic-arithmetic-saturating.rs:33:9
+   |
+LL |         simd_saturating_add(z, z);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_saturating_sub` intrinsic: expected element type `f32` of vector type `f32x4` to be a signed or unsigned integer type
+  --> $DIR/simd-intrinsic-generic-arithmetic-saturating.rs:35:9
+   |
+LL |         simd_saturating_sub(z, z);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0511`.
diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic.rs b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic.rs
new file mode 100644
index 0000000..7686b38
--- /dev/null
+++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic.rs
@@ -0,0 +1,93 @@
+#![feature(repr_simd, platform_intrinsics)]
+#![allow(non_camel_case_types)]
+#[repr(simd)]
+#[derive(Copy, Clone)]
+pub struct i32x4(pub i32, pub i32, pub i32, pub i32);
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+pub struct u32x4(pub u32, pub u32, pub u32, pub u32);
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+pub struct f32x4(pub f32, pub f32, pub f32, pub f32);
+
+extern "platform-intrinsic" {
+    fn simd_add<T>(x: T, y: T) -> T;
+    fn simd_sub<T>(x: T, y: T) -> T;
+    fn simd_mul<T>(x: T, y: T) -> T;
+    fn simd_div<T>(x: T, y: T) -> T;
+    fn simd_rem<T>(x: T, y: T) -> T;
+    fn simd_shl<T>(x: T, y: T) -> T;
+    fn simd_shr<T>(x: T, y: T) -> T;
+    fn simd_and<T>(x: T, y: T) -> T;
+    fn simd_or<T>(x: T, y: T) -> T;
+    fn simd_xor<T>(x: T, y: T) -> T;
+}
+
+fn main() {
+    let x = i32x4(0, 0, 0, 0);
+    let y = u32x4(0, 0, 0, 0);
+    let z = f32x4(0.0, 0.0, 0.0, 0.0);
+
+    unsafe {
+        simd_add(x, x);
+        simd_add(y, y);
+        simd_add(z, z);
+        simd_sub(x, x);
+        simd_sub(y, y);
+        simd_sub(z, z);
+        simd_mul(x, x);
+        simd_mul(y, y);
+        simd_mul(z, z);
+        simd_div(x, x);
+        simd_div(y, y);
+        simd_div(z, z);
+        simd_rem(x, x);
+        simd_rem(y, y);
+        simd_rem(z, z);
+
+        simd_shl(x, x);
+        simd_shl(y, y);
+        simd_shr(x, x);
+        simd_shr(y, y);
+        simd_and(x, x);
+        simd_and(y, y);
+        simd_or(x, x);
+        simd_or(y, y);
+        simd_xor(x, x);
+        simd_xor(y, y);
+
+
+        simd_add(0, 0);
+        //~^ ERROR expected SIMD input type, found non-SIMD `i32`
+        simd_sub(0, 0);
+        //~^ ERROR expected SIMD input type, found non-SIMD `i32`
+        simd_mul(0, 0);
+        //~^ ERROR expected SIMD input type, found non-SIMD `i32`
+        simd_div(0, 0);
+        //~^ ERROR expected SIMD input type, found non-SIMD `i32`
+        simd_shl(0, 0);
+        //~^ ERROR expected SIMD input type, found non-SIMD `i32`
+        simd_shr(0, 0);
+        //~^ ERROR expected SIMD input type, found non-SIMD `i32`
+        simd_and(0, 0);
+        //~^ ERROR expected SIMD input type, found non-SIMD `i32`
+        simd_or(0, 0);
+        //~^ ERROR expected SIMD input type, found non-SIMD `i32`
+        simd_xor(0, 0);
+        //~^ ERROR expected SIMD input type, found non-SIMD `i32`
+
+
+        simd_shl(z, z);
+//~^ ERROR unsupported operation on `f32x4` with element `f32`
+        simd_shr(z, z);
+//~^ ERROR unsupported operation on `f32x4` with element `f32`
+        simd_and(z, z);
+//~^ ERROR unsupported operation on `f32x4` with element `f32`
+        simd_or(z, z);
+//~^ ERROR unsupported operation on `f32x4` with element `f32`
+        simd_xor(z, z);
+//~^ ERROR unsupported operation on `f32x4` with element `f32`
+    }
+}
diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic.stderr b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic.stderr
new file mode 100644
index 0000000..2749395
--- /dev/null
+++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic.stderr
@@ -0,0 +1,87 @@
+error[E0511]: invalid monomorphization of `simd_add` intrinsic: expected SIMD input type, found non-SIMD `i32`
+  --> $DIR/simd-intrinsic-generic-arithmetic.rs:62:9
+   |
+LL |         simd_add(0, 0);
+   |         ^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_sub` intrinsic: expected SIMD input type, found non-SIMD `i32`
+  --> $DIR/simd-intrinsic-generic-arithmetic.rs:64:9
+   |
+LL |         simd_sub(0, 0);
+   |         ^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_mul` intrinsic: expected SIMD input type, found non-SIMD `i32`
+  --> $DIR/simd-intrinsic-generic-arithmetic.rs:66:9
+   |
+LL |         simd_mul(0, 0);
+   |         ^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_div` intrinsic: expected SIMD input type, found non-SIMD `i32`
+  --> $DIR/simd-intrinsic-generic-arithmetic.rs:68:9
+   |
+LL |         simd_div(0, 0);
+   |         ^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_shl` intrinsic: expected SIMD input type, found non-SIMD `i32`
+  --> $DIR/simd-intrinsic-generic-arithmetic.rs:70:9
+   |
+LL |         simd_shl(0, 0);
+   |         ^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_shr` intrinsic: expected SIMD input type, found non-SIMD `i32`
+  --> $DIR/simd-intrinsic-generic-arithmetic.rs:72:9
+   |
+LL |         simd_shr(0, 0);
+   |         ^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_and` intrinsic: expected SIMD input type, found non-SIMD `i32`
+  --> $DIR/simd-intrinsic-generic-arithmetic.rs:74:9
+   |
+LL |         simd_and(0, 0);
+   |         ^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_or` intrinsic: expected SIMD input type, found non-SIMD `i32`
+  --> $DIR/simd-intrinsic-generic-arithmetic.rs:76:9
+   |
+LL |         simd_or(0, 0);
+   |         ^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_xor` intrinsic: expected SIMD input type, found non-SIMD `i32`
+  --> $DIR/simd-intrinsic-generic-arithmetic.rs:78:9
+   |
+LL |         simd_xor(0, 0);
+   |         ^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_shl` intrinsic: unsupported operation on `f32x4` with element `f32`
+  --> $DIR/simd-intrinsic-generic-arithmetic.rs:82:9
+   |
+LL |         simd_shl(z, z);
+   |         ^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_shr` intrinsic: unsupported operation on `f32x4` with element `f32`
+  --> $DIR/simd-intrinsic-generic-arithmetic.rs:84:9
+   |
+LL |         simd_shr(z, z);
+   |         ^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_and` intrinsic: unsupported operation on `f32x4` with element `f32`
+  --> $DIR/simd-intrinsic-generic-arithmetic.rs:86:9
+   |
+LL |         simd_and(z, z);
+   |         ^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_or` intrinsic: unsupported operation on `f32x4` with element `f32`
+  --> $DIR/simd-intrinsic-generic-arithmetic.rs:88:9
+   |
+LL |         simd_or(z, z);
+   |         ^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_xor` intrinsic: unsupported operation on `f32x4` with element `f32`
+  --> $DIR/simd-intrinsic-generic-arithmetic.rs:90:9
+   |
+LL |         simd_xor(z, z);
+   |         ^^^^^^^^^^^^^^
+
+error: aborting due to 14 previous errors
+
+For more information about this error, try `rustc --explain E0511`.
diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-bitmask.rs b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-bitmask.rs
new file mode 100644
index 0000000..931ee9d
--- /dev/null
+++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-bitmask.rs
@@ -0,0 +1,90 @@
+// Test that the simd_bitmask intrinsic produces ok-ish error
+// messages when misused.
+
+#![feature(repr_simd, platform_intrinsics)]
+#![allow(non_camel_case_types)]
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+pub struct u32x2(pub u32, pub u32);
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+pub struct u32x4(pub u32, pub u32, pub u32, pub u32);
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+struct u8x8(
+    pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8,
+);
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+struct u8x16(
+    pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8,
+    pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8,
+);
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+struct u8x32(
+    pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8,
+    pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8,
+    pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8,
+    pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8,
+);
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+struct u8x64(
+    pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8,
+    pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8,
+    pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8,
+    pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8,
+    pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8,
+    pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8,
+    pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8,
+    pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8,
+);
+
+extern "platform-intrinsic" {
+    fn simd_bitmask<T, U>(x: T) -> U;
+}
+
+fn main() {
+    let m2 = u32x2(0, 0);
+    let m4 = u32x4(0, 0, 0, 0);
+    let m8 = u8x8(0, 0, 0, 0, 0, 0, 0, 0);
+    let m16 = u8x16(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+    let m32 = u8x32(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+    let m64 = u8x64(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+
+    unsafe {
+        let _: u8 = simd_bitmask(m2);
+        let _: u8 = simd_bitmask(m4);
+        let _: u8 = simd_bitmask(m8);
+        let _: u16 = simd_bitmask(m16);
+        let _: u32 = simd_bitmask(m32);
+        let _: u64 = simd_bitmask(m64);
+
+        let _: u16 = simd_bitmask(m2);
+        //~^ ERROR bitmask `u16`, expected `u8`
+
+        let _: u16 = simd_bitmask(m8);
+        //~^ ERROR bitmask `u16`, expected `u8`
+
+        let _: u32 = simd_bitmask(m16);
+        //~^ ERROR bitmask `u32`, expected `u16`
+
+        let _: u64 = simd_bitmask(m32);
+        //~^ ERROR bitmask `u64`, expected `u32`
+
+        let _: u128 = simd_bitmask(m64);
+        //~^ ERROR bitmask `u128`, expected `u64`
+
+   }
+}
diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-bitmask.stderr b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-bitmask.stderr
new file mode 100644
index 0000000..d016838
--- /dev/null
+++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-bitmask.stderr
@@ -0,0 +1,33 @@
+error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: bitmask `u16`, expected `u8`
+  --> $DIR/simd-intrinsic-generic-bitmask.rs:74:22
+   |
+LL |         let _: u16 = simd_bitmask(m2);
+   |                      ^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: bitmask `u16`, expected `u8`
+  --> $DIR/simd-intrinsic-generic-bitmask.rs:77:22
+   |
+LL |         let _: u16 = simd_bitmask(m8);
+   |                      ^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: bitmask `u32`, expected `u16`
+  --> $DIR/simd-intrinsic-generic-bitmask.rs:80:22
+   |
+LL |         let _: u32 = simd_bitmask(m16);
+   |                      ^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: bitmask `u64`, expected `u32`
+  --> $DIR/simd-intrinsic-generic-bitmask.rs:83:22
+   |
+LL |         let _: u64 = simd_bitmask(m32);
+   |                      ^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: bitmask `u128`, expected `u64`
+  --> $DIR/simd-intrinsic-generic-bitmask.rs:86:23
+   |
+LL |         let _: u128 = simd_bitmask(m64);
+   |                       ^^^^^^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0511`.
diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-cast.rs b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-cast.rs
new file mode 100644
index 0000000..c4016e7
--- /dev/null
+++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-cast.rs
@@ -0,0 +1,41 @@
+#![feature(repr_simd, platform_intrinsics)]
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+#[allow(non_camel_case_types)]
+struct i32x4(i32, i32, i32, i32);
+#[repr(simd)]
+#[derive(Copy, Clone)]
+#[allow(non_camel_case_types)]
+struct i32x8(i32, i32, i32, i32,
+             i32, i32, i32, i32);
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+#[allow(non_camel_case_types)]
+struct f32x4(f32, f32, f32, f32);
+#[repr(simd)]
+#[derive(Copy, Clone)]
+#[allow(non_camel_case_types)]
+struct f32x8(f32, f32, f32, f32,
+             f32, f32, f32, f32);
+
+
+extern "platform-intrinsic" {
+    fn simd_cast<T, U>(x: T) -> U;
+}
+
+fn main() {
+    let x = i32x4(0, 0, 0, 0);
+
+    unsafe {
+        simd_cast::<i32, i32>(0);
+        //~^ ERROR expected SIMD input type, found non-SIMD `i32`
+        simd_cast::<i32, i32x4>(0);
+        //~^ ERROR expected SIMD input type, found non-SIMD `i32`
+        simd_cast::<i32x4, i32>(x);
+        //~^ ERROR expected SIMD return type, found non-SIMD `i32`
+        simd_cast::<_, i32x8>(x);
+//~^ ERROR return type with length 4 (same as input type `i32x4`), found `i32x8` with length 8
+    }
+}
diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-cast.stderr b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-cast.stderr
new file mode 100644
index 0000000..6e33e3b
--- /dev/null
+++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-cast.stderr
@@ -0,0 +1,27 @@
+error[E0511]: invalid monomorphization of `simd_cast` intrinsic: expected SIMD input type, found non-SIMD `i32`
+  --> $DIR/simd-intrinsic-generic-cast.rs:32:9
+   |
+LL |         simd_cast::<i32, i32>(0);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_cast` intrinsic: expected SIMD input type, found non-SIMD `i32`
+  --> $DIR/simd-intrinsic-generic-cast.rs:34:9
+   |
+LL |         simd_cast::<i32, i32x4>(0);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_cast` intrinsic: expected SIMD return type, found non-SIMD `i32`
+  --> $DIR/simd-intrinsic-generic-cast.rs:36:9
+   |
+LL |         simd_cast::<i32x4, i32>(x);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_cast` intrinsic: expected return type with length 4 (same as input type `i32x4`), found `i32x8` with length 8
+  --> $DIR/simd-intrinsic-generic-cast.rs:38:9
+   |
+LL |         simd_cast::<_, i32x8>(x);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0511`.
diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-comparison.rs b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-comparison.rs
new file mode 100644
index 0000000..3ac47d1
--- /dev/null
+++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-comparison.rs
@@ -0,0 +1,65 @@
+#![feature(repr_simd, platform_intrinsics)]
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+#[allow(non_camel_case_types)]
+struct i32x4(i32, i32, i32, i32);
+#[repr(simd)]
+#[derive(Copy, Clone)]
+#[allow(non_camel_case_types)]
+struct i16x8(i16, i16, i16, i16,
+             i16, i16, i16, i16);
+
+extern "platform-intrinsic" {
+    fn simd_eq<T, U>(x: T, y: T) -> U;
+    fn simd_ne<T, U>(x: T, y: T) -> U;
+    fn simd_lt<T, U>(x: T, y: T) -> U;
+    fn simd_le<T, U>(x: T, y: T) -> U;
+    fn simd_gt<T, U>(x: T, y: T) -> U;
+    fn simd_ge<T, U>(x: T, y: T) -> U;
+}
+
+fn main() {
+    let x = i32x4(0, 0, 0, 0);
+
+    unsafe {
+        simd_eq::<i32, i32>(0, 0);
+        //~^ ERROR expected SIMD input type, found non-SIMD `i32`
+        simd_ne::<i32, i32>(0, 0);
+        //~^ ERROR expected SIMD input type, found non-SIMD `i32`
+        simd_lt::<i32, i32>(0, 0);
+        //~^ ERROR expected SIMD input type, found non-SIMD `i32`
+        simd_le::<i32, i32>(0, 0);
+        //~^ ERROR expected SIMD input type, found non-SIMD `i32`
+        simd_gt::<i32, i32>(0, 0);
+        //~^ ERROR expected SIMD input type, found non-SIMD `i32`
+        simd_ge::<i32, i32>(0, 0);
+        //~^ ERROR expected SIMD input type, found non-SIMD `i32`
+
+        simd_eq::<_, i32>(x, x);
+        //~^ ERROR expected SIMD return type, found non-SIMD `i32`
+        simd_ne::<_, i32>(x, x);
+        //~^ ERROR expected SIMD return type, found non-SIMD `i32`
+        simd_lt::<_, i32>(x, x);
+        //~^ ERROR expected SIMD return type, found non-SIMD `i32`
+        simd_le::<_, i32>(x, x);
+        //~^ ERROR expected SIMD return type, found non-SIMD `i32`
+        simd_gt::<_, i32>(x, x);
+        //~^ ERROR expected SIMD return type, found non-SIMD `i32`
+        simd_ge::<_, i32>(x, x);
+        //~^ ERROR expected SIMD return type, found non-SIMD `i32`
+
+        simd_eq::<_, i16x8>(x, x);
+//~^ ERROR return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8
+        simd_ne::<_, i16x8>(x, x);
+//~^ ERROR return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8
+        simd_lt::<_, i16x8>(x, x);
+//~^ ERROR return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8
+        simd_le::<_, i16x8>(x, x);
+//~^ ERROR return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8
+        simd_gt::<_, i16x8>(x, x);
+//~^ ERROR return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8
+        simd_ge::<_, i16x8>(x, x);
+//~^ ERROR return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8
+    }
+}
diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-comparison.stderr b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-comparison.stderr
new file mode 100644
index 0000000..d8da2e5
--- /dev/null
+++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-comparison.stderr
@@ -0,0 +1,111 @@
+error[E0511]: invalid monomorphization of `simd_eq` intrinsic: expected SIMD input type, found non-SIMD `i32`
+  --> $DIR/simd-intrinsic-generic-comparison.rs:26:9
+   |
+LL |         simd_eq::<i32, i32>(0, 0);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_ne` intrinsic: expected SIMD input type, found non-SIMD `i32`
+  --> $DIR/simd-intrinsic-generic-comparison.rs:28:9
+   |
+LL |         simd_ne::<i32, i32>(0, 0);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_lt` intrinsic: expected SIMD input type, found non-SIMD `i32`
+  --> $DIR/simd-intrinsic-generic-comparison.rs:30:9
+   |
+LL |         simd_lt::<i32, i32>(0, 0);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_le` intrinsic: expected SIMD input type, found non-SIMD `i32`
+  --> $DIR/simd-intrinsic-generic-comparison.rs:32:9
+   |
+LL |         simd_le::<i32, i32>(0, 0);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_gt` intrinsic: expected SIMD input type, found non-SIMD `i32`
+  --> $DIR/simd-intrinsic-generic-comparison.rs:34:9
+   |
+LL |         simd_gt::<i32, i32>(0, 0);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_ge` intrinsic: expected SIMD input type, found non-SIMD `i32`
+  --> $DIR/simd-intrinsic-generic-comparison.rs:36:9
+   |
+LL |         simd_ge::<i32, i32>(0, 0);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_eq` intrinsic: expected SIMD return type, found non-SIMD `i32`
+  --> $DIR/simd-intrinsic-generic-comparison.rs:39:9
+   |
+LL |         simd_eq::<_, i32>(x, x);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_ne` intrinsic: expected SIMD return type, found non-SIMD `i32`
+  --> $DIR/simd-intrinsic-generic-comparison.rs:41:9
+   |
+LL |         simd_ne::<_, i32>(x, x);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_lt` intrinsic: expected SIMD return type, found non-SIMD `i32`
+  --> $DIR/simd-intrinsic-generic-comparison.rs:43:9
+   |
+LL |         simd_lt::<_, i32>(x, x);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_le` intrinsic: expected SIMD return type, found non-SIMD `i32`
+  --> $DIR/simd-intrinsic-generic-comparison.rs:45:9
+   |
+LL |         simd_le::<_, i32>(x, x);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_gt` intrinsic: expected SIMD return type, found non-SIMD `i32`
+  --> $DIR/simd-intrinsic-generic-comparison.rs:47:9
+   |
+LL |         simd_gt::<_, i32>(x, x);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_ge` intrinsic: expected SIMD return type, found non-SIMD `i32`
+  --> $DIR/simd-intrinsic-generic-comparison.rs:49:9
+   |
+LL |         simd_ge::<_, i32>(x, x);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_eq` intrinsic: expected return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8
+  --> $DIR/simd-intrinsic-generic-comparison.rs:52:9
+   |
+LL |         simd_eq::<_, i16x8>(x, x);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_ne` intrinsic: expected return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8
+  --> $DIR/simd-intrinsic-generic-comparison.rs:54:9
+   |
+LL |         simd_ne::<_, i16x8>(x, x);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_lt` intrinsic: expected return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8
+  --> $DIR/simd-intrinsic-generic-comparison.rs:56:9
+   |
+LL |         simd_lt::<_, i16x8>(x, x);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_le` intrinsic: expected return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8
+  --> $DIR/simd-intrinsic-generic-comparison.rs:58:9
+   |
+LL |         simd_le::<_, i16x8>(x, x);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_gt` intrinsic: expected return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8
+  --> $DIR/simd-intrinsic-generic-comparison.rs:60:9
+   |
+LL |         simd_gt::<_, i16x8>(x, x);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_ge` intrinsic: expected return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8
+  --> $DIR/simd-intrinsic-generic-comparison.rs:62:9
+   |
+LL |         simd_ge::<_, i16x8>(x, x);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 18 previous errors
+
+For more information about this error, try `rustc --explain E0511`.
diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-elements.rs b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-elements.rs
new file mode 100644
index 0000000..28fcb6c
--- /dev/null
+++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-elements.rs
@@ -0,0 +1,87 @@
+#![feature(repr_simd, platform_intrinsics, rustc_attrs)]
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+#[allow(non_camel_case_types)]
+struct i32x2(i32, i32);
+#[repr(simd)]
+#[derive(Copy, Clone)]
+#[allow(non_camel_case_types)]
+struct i32x3(i32, i32, i32);
+#[repr(simd)]
+#[derive(Copy, Clone)]
+#[allow(non_camel_case_types)]
+struct i32x4(i32, i32, i32, i32);
+#[repr(simd)]
+#[derive(Copy, Clone)]
+#[allow(non_camel_case_types)]
+struct i32x8(i32, i32, i32, i32,
+             i32, i32, i32, i32);
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+#[allow(non_camel_case_types)]
+struct f32x2(f32, f32);
+#[repr(simd)]
+#[derive(Copy, Clone)]
+#[allow(non_camel_case_types)]
+struct f32x3(f32, f32, f32);
+#[repr(simd)]
+#[derive(Copy, Clone)]
+#[allow(non_camel_case_types)]
+struct f32x4(f32, f32, f32, f32);
+#[repr(simd)]
+#[derive(Copy, Clone)]
+#[allow(non_camel_case_types)]
+struct f32x8(f32, f32, f32, f32,
+             f32, f32, f32, f32);
+
+extern "platform-intrinsic" {
+    fn simd_insert<T, E>(x: T, idx: u32, y: E) -> T;
+    fn simd_extract<T, E>(x: T, idx: u32) -> E;
+
+    fn simd_shuffle2<T, U>(x: T, y: T, idx: [u32; 2]) -> U;
+    fn simd_shuffle3<T, U>(x: T, y: T, idx: [u32; 3]) -> U;
+    fn simd_shuffle4<T, U>(x: T, y: T, idx: [u32; 4]) -> U;
+    fn simd_shuffle8<T, U>(x: T, y: T, idx: [u32; 8]) -> U;
+}
+
+fn main() {
+    let x = i32x4(0, 0, 0, 0);
+
+    unsafe {
+        simd_insert(0, 0, 0);
+        //~^ ERROR expected SIMD input type, found non-SIMD `i32`
+        simd_insert(x, 0, 1.0);
+        //~^ ERROR expected inserted type `i32` (element of input `i32x4`), found `f64`
+        simd_extract::<_, f32>(x, 0);
+        //~^ ERROR expected return type `i32` (element of input `i32x4`), found `f32`
+
+        simd_shuffle2::<i32, i32>(0, 0, [0; 2]);
+        //~^ ERROR expected SIMD input type, found non-SIMD `i32`
+        simd_shuffle3::<i32, i32>(0, 0, [0; 3]);
+        //~^ ERROR expected SIMD input type, found non-SIMD `i32`
+        simd_shuffle4::<i32, i32>(0, 0, [0; 4]);
+        //~^ ERROR expected SIMD input type, found non-SIMD `i32`
+        simd_shuffle8::<i32, i32>(0, 0, [0; 8]);
+        //~^ ERROR expected SIMD input type, found non-SIMD `i32`
+
+        simd_shuffle2::<_, f32x2>(x, x, [0; 2]);
+//~^ ERROR element type `i32` (element of input `i32x4`), found `f32x2` with element type `f32`
+        simd_shuffle3::<_, f32x3>(x, x, [0; 3]);
+//~^ ERROR element type `i32` (element of input `i32x4`), found `f32x3` with element type `f32`
+        simd_shuffle4::<_, f32x4>(x, x, [0; 4]);
+//~^ ERROR element type `i32` (element of input `i32x4`), found `f32x4` with element type `f32`
+        simd_shuffle8::<_, f32x8>(x, x, [0; 8]);
+//~^ ERROR element type `i32` (element of input `i32x4`), found `f32x8` with element type `f32`
+
+        simd_shuffle2::<_, i32x8>(x, x, [0; 2]);
+        //~^ ERROR expected return type of length 2, found `i32x8` with length 8
+        simd_shuffle3::<_, i32x4>(x, x, [0; 3]);
+        //~^ ERROR expected return type of length 3, found `i32x4` with length 4
+        simd_shuffle4::<_, i32x3>(x, x, [0; 4]);
+        //~^ ERROR expected return type of length 4, found `i32x3` with length 3
+        simd_shuffle8::<_, i32x2>(x, x, [0; 8]);
+        //~^ ERROR expected return type of length 8, found `i32x2` with length 2
+    }
+}
diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-elements.stderr b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-elements.stderr
new file mode 100644
index 0000000..2f8ffb6
--- /dev/null
+++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-elements.stderr
@@ -0,0 +1,93 @@
+error[E0511]: invalid monomorphization of `simd_insert` intrinsic: expected SIMD input type, found non-SIMD `i32`
+  --> $DIR/simd-intrinsic-generic-elements.rs:53:9
+   |
+LL |         simd_insert(0, 0, 0);
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_insert` intrinsic: expected inserted type `i32` (element of input `i32x4`), found `f64`
+  --> $DIR/simd-intrinsic-generic-elements.rs:55:9
+   |
+LL |         simd_insert(x, 0, 1.0);
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_extract` intrinsic: expected return type `i32` (element of input `i32x4`), found `f32`
+  --> $DIR/simd-intrinsic-generic-elements.rs:57:9
+   |
+LL |         simd_extract::<_, f32>(x, 0);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_shuffle2` intrinsic: expected SIMD input type, found non-SIMD `i32`
+  --> $DIR/simd-intrinsic-generic-elements.rs:60:9
+   |
+LL |         simd_shuffle2::<i32, i32>(0, 0, [0; 2]);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_shuffle3` intrinsic: expected SIMD input type, found non-SIMD `i32`
+  --> $DIR/simd-intrinsic-generic-elements.rs:62:9
+   |
+LL |         simd_shuffle3::<i32, i32>(0, 0, [0; 3]);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_shuffle4` intrinsic: expected SIMD input type, found non-SIMD `i32`
+  --> $DIR/simd-intrinsic-generic-elements.rs:64:9
+   |
+LL |         simd_shuffle4::<i32, i32>(0, 0, [0; 4]);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_shuffle8` intrinsic: expected SIMD input type, found non-SIMD `i32`
+  --> $DIR/simd-intrinsic-generic-elements.rs:66:9
+   |
+LL |         simd_shuffle8::<i32, i32>(0, 0, [0; 8]);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_shuffle2` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x2` with element type `f32`
+  --> $DIR/simd-intrinsic-generic-elements.rs:69:9
+   |
+LL |         simd_shuffle2::<_, f32x2>(x, x, [0; 2]);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_shuffle3` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x3` with element type `f32`
+  --> $DIR/simd-intrinsic-generic-elements.rs:71:9
+   |
+LL |         simd_shuffle3::<_, f32x3>(x, x, [0; 3]);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_shuffle4` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x4` with element type `f32`
+  --> $DIR/simd-intrinsic-generic-elements.rs:73:9
+   |
+LL |         simd_shuffle4::<_, f32x4>(x, x, [0; 4]);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_shuffle8` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x8` with element type `f32`
+  --> $DIR/simd-intrinsic-generic-elements.rs:75:9
+   |
+LL |         simd_shuffle8::<_, f32x8>(x, x, [0; 8]);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_shuffle2` intrinsic: expected return type of length 2, found `i32x8` with length 8
+  --> $DIR/simd-intrinsic-generic-elements.rs:78:9
+   |
+LL |         simd_shuffle2::<_, i32x8>(x, x, [0; 2]);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_shuffle3` intrinsic: expected return type of length 3, found `i32x4` with length 4
+  --> $DIR/simd-intrinsic-generic-elements.rs:80:9
+   |
+LL |         simd_shuffle3::<_, i32x4>(x, x, [0; 3]);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_shuffle4` intrinsic: expected return type of length 4, found `i32x3` with length 3
+  --> $DIR/simd-intrinsic-generic-elements.rs:82:9
+   |
+LL |         simd_shuffle4::<_, i32x3>(x, x, [0; 4]);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_shuffle8` intrinsic: expected return type of length 8, found `i32x2` with length 2
+  --> $DIR/simd-intrinsic-generic-elements.rs:84:9
+   |
+LL |         simd_shuffle8::<_, i32x2>(x, x, [0; 8]);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 15 previous errors
+
+For more information about this error, try `rustc --explain E0511`.
diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-reduction.rs b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-reduction.rs
new file mode 100644
index 0000000..8e67c27
--- /dev/null
+++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-reduction.rs
@@ -0,0 +1,71 @@
+// ignore-emscripten
+
+// Test that the simd_reduce_{op} intrinsics produce ok-ish error
+// messages when misused.
+
+#![feature(repr_simd, platform_intrinsics)]
+#![allow(non_camel_case_types)]
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+pub struct f32x4(pub f32, pub f32, pub f32, pub f32);
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+pub struct u32x4(pub u32, pub u32, pub u32, pub u32);
+
+
+extern "platform-intrinsic" {
+    fn simd_reduce_add_ordered<T, U>(x: T, y: U) -> U;
+    fn simd_reduce_mul_ordered<T, U>(x: T, y: U) -> U;
+    fn simd_reduce_and<T, U>(x: T) -> U;
+    fn simd_reduce_or<T, U>(x: T) -> U;
+    fn simd_reduce_xor<T, U>(x: T) -> U;
+    fn simd_reduce_all<T>(x: T) -> bool;
+    fn simd_reduce_any<T>(x: T) -> bool;
+}
+
+fn main() {
+    let x = u32x4(0, 0, 0, 0);
+    let z = f32x4(0.0, 0.0, 0.0, 0.0);
+
+    unsafe {
+        simd_reduce_add_ordered(z, 0_f32);
+        simd_reduce_mul_ordered(z, 1_f32);
+
+        simd_reduce_add_ordered(z, 2_f32);
+        //~^ ERROR accumulator of simd_reduce_add_ordered is not 0.0
+        simd_reduce_mul_ordered(z, 3_f32);
+        //~^ ERROR accumulator of simd_reduce_mul_ordered is not 1.0
+
+        let _: f32 = simd_reduce_and(x);
+        //~^ ERROR expected return type `u32` (element of input `u32x4`), found `f32`
+        let _: f32 = simd_reduce_or(x);
+        //~^ ERROR expected return type `u32` (element of input `u32x4`), found `f32`
+        let _: f32 = simd_reduce_xor(x);
+        //~^ ERROR expected return type `u32` (element of input `u32x4`), found `f32`
+
+        let _: f32 = simd_reduce_and(z);
+        //~^ ERROR unsupported simd_reduce_and from `f32x4` with element `f32` to `f32`
+        let _: f32 = simd_reduce_or(z);
+        //~^ ERROR unsupported simd_reduce_or from `f32x4` with element `f32` to `f32`
+        let _: f32 = simd_reduce_xor(z);
+        //~^ ERROR unsupported simd_reduce_xor from `f32x4` with element `f32` to `f32`
+
+        let _: bool = simd_reduce_all(z);
+        //~^ ERROR unsupported simd_reduce_all from `f32x4` with element `f32` to `bool`
+        let _: bool = simd_reduce_any(z);
+        //~^ ERROR unsupported simd_reduce_any from `f32x4` with element `f32` to `bool`
+
+        foo(0_f32);
+    }
+}
+
+#[inline(never)]
+unsafe fn foo(x: f32) {
+    let z = f32x4(0.0, 0.0, 0.0, 0.0);
+    simd_reduce_add_ordered(z, x);
+    //~^ ERROR accumulator of simd_reduce_add_ordered is not a constant
+    simd_reduce_mul_ordered(z, x);
+    //~^ ERROR accumulator of simd_reduce_mul_ordered is not a constant
+}
diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-reduction.stderr b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-reduction.stderr
new file mode 100644
index 0000000..b56de96
--- /dev/null
+++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-reduction.stderr
@@ -0,0 +1,75 @@
+error[E0511]: invalid monomorphization of `simd_reduce_add_ordered` intrinsic: accumulator of simd_reduce_add_ordered is not 0.0
+  --> $DIR/simd-intrinsic-generic-reduction.rs:36:9
+   |
+LL |         simd_reduce_add_ordered(z, 2_f32);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_reduce_mul_ordered` intrinsic: accumulator of simd_reduce_mul_ordered is not 1.0
+  --> $DIR/simd-intrinsic-generic-reduction.rs:38:9
+   |
+LL |         simd_reduce_mul_ordered(z, 3_f32);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_reduce_and` intrinsic: expected return type `u32` (element of input `u32x4`), found `f32`
+  --> $DIR/simd-intrinsic-generic-reduction.rs:41:22
+   |
+LL |         let _: f32 = simd_reduce_and(x);
+   |                      ^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_reduce_or` intrinsic: expected return type `u32` (element of input `u32x4`), found `f32`
+  --> $DIR/simd-intrinsic-generic-reduction.rs:43:22
+   |
+LL |         let _: f32 = simd_reduce_or(x);
+   |                      ^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_reduce_xor` intrinsic: expected return type `u32` (element of input `u32x4`), found `f32`
+  --> $DIR/simd-intrinsic-generic-reduction.rs:45:22
+   |
+LL |         let _: f32 = simd_reduce_xor(x);
+   |                      ^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_reduce_and` intrinsic: unsupported simd_reduce_and from `f32x4` with element `f32` to `f32`
+  --> $DIR/simd-intrinsic-generic-reduction.rs:48:22
+   |
+LL |         let _: f32 = simd_reduce_and(z);
+   |                      ^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_reduce_or` intrinsic: unsupported simd_reduce_or from `f32x4` with element `f32` to `f32`
+  --> $DIR/simd-intrinsic-generic-reduction.rs:50:22
+   |
+LL |         let _: f32 = simd_reduce_or(z);
+   |                      ^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_reduce_xor` intrinsic: unsupported simd_reduce_xor from `f32x4` with element `f32` to `f32`
+  --> $DIR/simd-intrinsic-generic-reduction.rs:52:22
+   |
+LL |         let _: f32 = simd_reduce_xor(z);
+   |                      ^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_reduce_all` intrinsic: unsupported simd_reduce_all from `f32x4` with element `f32` to `bool`
+  --> $DIR/simd-intrinsic-generic-reduction.rs:55:23
+   |
+LL |         let _: bool = simd_reduce_all(z);
+   |                       ^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_reduce_any` intrinsic: unsupported simd_reduce_any from `f32x4` with element `f32` to `bool`
+  --> $DIR/simd-intrinsic-generic-reduction.rs:57:23
+   |
+LL |         let _: bool = simd_reduce_any(z);
+   |                       ^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_reduce_add_ordered` intrinsic: accumulator of simd_reduce_add_ordered is not a constant
+  --> $DIR/simd-intrinsic-generic-reduction.rs:67:5
+   |
+LL |     simd_reduce_add_ordered(z, x);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_reduce_mul_ordered` intrinsic: accumulator of simd_reduce_mul_ordered is not a constant
+  --> $DIR/simd-intrinsic-generic-reduction.rs:69:5
+   |
+LL |     simd_reduce_mul_ordered(z, x);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 12 previous errors
+
+For more information about this error, try `rustc --explain E0511`.
diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.rs b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.rs
new file mode 100644
index 0000000..72f51a8
--- /dev/null
+++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.rs
@@ -0,0 +1,62 @@
+// Test that the simd_select intrinsic produces ok-ish error
+// messages when misused.
+
+#![feature(repr_simd, platform_intrinsics)]
+#![allow(non_camel_case_types)]
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+pub struct f32x4(pub f32, pub f32, pub f32, pub f32);
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+pub struct u32x4(pub u32, pub u32, pub u32, pub u32);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq)]
+struct b8x4(pub i8, pub i8, pub i8, pub i8);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq)]
+struct b8x8(pub i8, pub i8, pub i8, pub i8,
+            pub i8, pub i8, pub i8, pub i8);
+
+extern "platform-intrinsic" {
+    fn simd_select<T, U>(x: T, a: U, b: U) -> U;
+    fn simd_select_bitmask<T, U>(x: T, a: U, b: U) -> U;
+}
+
+fn main() {
+    let m4 = b8x4(0, 0, 0, 0);
+    let m8 = b8x8(0, 0, 0, 0, 0, 0, 0, 0);
+    let x = u32x4(0, 0, 0, 0);
+    let z = f32x4(0.0, 0.0, 0.0, 0.0);
+
+    unsafe {
+        simd_select(m4, x, x);
+
+        simd_select(m8, x, x);
+        //~^ ERROR mismatched lengths: mask length `8` != other vector length `4`
+
+        simd_select(x, x, x);
+        //~^ ERROR mask element type is `u32`, expected `i_`
+
+        simd_select(z, z, z);
+        //~^ ERROR mask element type is `f32`, expected `i_`
+
+        simd_select(m4, 0u32, 1u32);
+        //~^ ERROR found non-SIMD `u32`
+
+        simd_select_bitmask(0u8, x, x);
+        //~^ ERROR mask length `8` != other vector length `4`
+        //
+        simd_select_bitmask(0u8, 1u32, 2u32);
+        //~^ ERROR found non-SIMD `u32`
+
+        simd_select_bitmask(0.0f32, x, x);
+        //~^ ERROR `f32` is not an integral type
+
+        simd_select_bitmask("x", x, x);
+        //~^ ERROR `&str` is not an integral type
+    }
+}
diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.stderr b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.stderr
new file mode 100644
index 0000000..a46352c
--- /dev/null
+++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.stderr
@@ -0,0 +1,51 @@
+error[E0511]: invalid monomorphization of `simd_select` intrinsic: mismatched lengths: mask length `8` != other vector length `4`
+  --> $DIR/simd-intrinsic-generic-select.rs:38:9
+   |
+LL |         simd_select(m8, x, x);
+   |         ^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_select` intrinsic: mask element type is `u32`, expected `i_`
+  --> $DIR/simd-intrinsic-generic-select.rs:41:9
+   |
+LL |         simd_select(x, x, x);
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_select` intrinsic: mask element type is `f32`, expected `i_`
+  --> $DIR/simd-intrinsic-generic-select.rs:44:9
+   |
+LL |         simd_select(z, z, z);
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_select` intrinsic: expected SIMD argument type, found non-SIMD `u32`
+  --> $DIR/simd-intrinsic-generic-select.rs:47:9
+   |
+LL |         simd_select(m4, 0u32, 1u32);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: mismatched lengths: mask length `8` != other vector length `4`
+  --> $DIR/simd-intrinsic-generic-select.rs:50:9
+   |
+LL |         simd_select_bitmask(0u8, x, x);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: expected SIMD argument type, found non-SIMD `u32`
+  --> $DIR/simd-intrinsic-generic-select.rs:53:9
+   |
+LL |         simd_select_bitmask(0u8, 1u32, 2u32);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: `f32` is not an integral type
+  --> $DIR/simd-intrinsic-generic-select.rs:56:9
+   |
+LL |         simd_select_bitmask(0.0f32, x, x);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: `&str` is not an integral type
+  --> $DIR/simd-intrinsic-generic-select.rs:59:9
+   |
+LL |         simd_select_bitmask("x", x, x);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0511`.
diff --git a/src/test/ui/simd-type-generic-monomorphisation.rs b/src/test/ui/simd-type-generic-monomorphisation.rs
new file mode 100644
index 0000000..68eb787
--- /dev/null
+++ b/src/test/ui/simd-type-generic-monomorphisation.rs
@@ -0,0 +1,11 @@
+#![feature(repr_simd, platform_intrinsics)]
+
+// error-pattern:monomorphising SIMD type `Simd2<X>` with a non-machine element type `X`
+
+struct X(Vec<i32>);
+#[repr(simd)]
+struct Simd2<T>(T, T);
+
+fn main() {
+    let _ = Simd2(X(vec![]), X(vec![]));
+}
diff --git a/src/test/ui/simd-type-generic-monomorphisation.stderr b/src/test/ui/simd-type-generic-monomorphisation.stderr
new file mode 100644
index 0000000..2a74506
--- /dev/null
+++ b/src/test/ui/simd-type-generic-monomorphisation.stderr
@@ -0,0 +1,4 @@
+error: monomorphising SIMD type `Simd2<X>` with a non-machine element type `X`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/simd-type.rs b/src/test/ui/simd-type.rs
new file mode 100644
index 0000000..9e4b7e7
--- /dev/null
+++ b/src/test/ui/simd-type.rs
@@ -0,0 +1,10 @@
+#![feature(repr_simd)]
+#![allow(non_camel_case_types)]
+
+#[repr(simd)]
+struct empty; //~ ERROR SIMD vector cannot be empty
+
+#[repr(simd)]
+struct i64f64(i64, f64); //~ ERROR SIMD vector should be homogeneous
+
+fn main() {}
diff --git a/src/test/ui/simd-type.stderr b/src/test/ui/simd-type.stderr
new file mode 100644
index 0000000..48b9916
--- /dev/null
+++ b/src/test/ui/simd-type.stderr
@@ -0,0 +1,16 @@
+error[E0075]: SIMD vector cannot be empty
+  --> $DIR/simd-type.rs:5:1
+   |
+LL | struct empty;
+   | ^^^^^^^^^^^^^
+
+error[E0076]: SIMD vector should be homogeneous
+  --> $DIR/simd-type.rs:8:1
+   |
+LL | struct i64f64(i64, f64);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^ SIMD elements must have the same type
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0075, E0076.
+For more information about an error, try `rustc --explain E0075`.
diff --git a/src/test/ui/similar-tokens.rs b/src/test/ui/similar-tokens.rs
new file mode 100644
index 0000000..b42f3a3
--- /dev/null
+++ b/src/test/ui/similar-tokens.rs
@@ -0,0 +1,9 @@
+mod x {
+    pub struct A;
+    pub struct B;
+}
+
+// `.` is similar to `,` so list parsing should continue to closing `}`
+use x::{A. B}; //~ ERROR expected one of `,`, `::`, `as`, or `}`, found `.`
+
+fn main() {}
diff --git a/src/test/ui/similar-tokens.stderr b/src/test/ui/similar-tokens.stderr
new file mode 100644
index 0000000..3113d4a
--- /dev/null
+++ b/src/test/ui/similar-tokens.stderr
@@ -0,0 +1,8 @@
+error: expected one of `,`, `::`, `as`, or `}`, found `.`
+  --> $DIR/similar-tokens.rs:7:10
+   |
+LL | use x::{A. B};
+   |          ^ expected one of `,`, `::`, `as`, or `}` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/single-primitive-inherent-impl.rs b/src/test/ui/single-primitive-inherent-impl.rs
new file mode 100644
index 0000000..baa2339
--- /dev/null
+++ b/src/test/ui/single-primitive-inherent-impl.rs
@@ -0,0 +1,13 @@
+// ignore-tidy-linelength
+
+#![crate_type = "lib"]
+#![feature(lang_items)]
+#![no_std]
+
+// OK
+#[lang = "str_alloc"]
+impl str {}
+
+impl str {
+//~^ error: only a single inherent implementation marked with `#[lang = "str"]` is allowed for the `str` primitive
+}
diff --git a/src/test/ui/single-primitive-inherent-impl.stderr b/src/test/ui/single-primitive-inherent-impl.stderr
new file mode 100644
index 0000000..d357afa
--- /dev/null
+++ b/src/test/ui/single-primitive-inherent-impl.stderr
@@ -0,0 +1,19 @@
+error[E0390]: only a single inherent implementation marked with `#[lang = "str"]` is allowed for the `str` primitive
+  --> $DIR/single-primitive-inherent-impl.rs:11:1
+   |
+LL | / impl str {
+LL | |
+LL | | }
+   | |_^
+   |
+help: consider using a trait to implement these methods
+  --> $DIR/single-primitive-inherent-impl.rs:11:1
+   |
+LL | / impl str {
+LL | |
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0390`.
diff --git a/src/test/ui/single-use-lifetime/fn-types.rs b/src/test/ui/single-use-lifetime/fn-types.rs
new file mode 100644
index 0000000..018535f
--- /dev/null
+++ b/src/test/ui/single-use-lifetime/fn-types.rs
@@ -0,0 +1,16 @@
+#![deny(single_use_lifetimes)]
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+// Test that we DO warn when lifetime name is used only
+// once in a fn argument.
+
+struct Foo {
+  a: for<'a> fn(&'a u32), //~ ERROR `'a` only used once
+  b: for<'a> fn(&'a u32, &'a u32), // OK, used twice.
+  c: for<'a> fn(&'a u32) -> &'a u32, // OK, used twice.
+  d: for<'a> fn() -> &'a u32, // OK, used only in return type.
+    //~^ ERROR return type references lifetime `'a`, which is not constrained by the fn input types
+}
+
+fn main() { }
diff --git a/src/test/ui/single-use-lifetime/fn-types.stderr b/src/test/ui/single-use-lifetime/fn-types.stderr
new file mode 100644
index 0000000..bec24be
--- /dev/null
+++ b/src/test/ui/single-use-lifetime/fn-types.stderr
@@ -0,0 +1,23 @@
+error: lifetime parameter `'a` only used once
+  --> $DIR/fn-types.rs:9:10
+   |
+LL |   a: for<'a> fn(&'a u32),
+   |          ^^      -- ...is used only here
+   |          |
+   |          this lifetime...
+   |
+note: lint level defined here
+  --> $DIR/fn-types.rs:1:9
+   |
+LL | #![deny(single_use_lifetimes)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error[E0581]: return type references lifetime `'a`, which is not constrained by the fn input types
+  --> $DIR/fn-types.rs:12:22
+   |
+LL |   d: for<'a> fn() -> &'a u32, // OK, used only in return type.
+   |                      ^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0581`.
diff --git a/src/test/ui/single-use-lifetime/one-use-in-fn-argument-in-band.fixed b/src/test/ui/single-use-lifetime/one-use-in-fn-argument-in-band.fixed
new file mode 100644
index 0000000..6bc07af
--- /dev/null
+++ b/src/test/ui/single-use-lifetime/one-use-in-fn-argument-in-band.fixed
@@ -0,0 +1,18 @@
+// run-rustfix
+
+#![feature(in_band_lifetimes)]
+#![deny(single_use_lifetimes)]
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+// Test that we DO warn when lifetime name is used only
+// once in a fn argument, even with in band lifetimes.
+
+fn a(x: &u32, y: &u32) {
+    //~^ ERROR `'a` only used once
+    //~| ERROR `'b` only used once
+    //~| HELP elide the single-use lifetime
+    //~| HELP elide the single-use lifetime
+}
+
+fn main() { }
diff --git a/src/test/ui/single-use-lifetime/one-use-in-fn-argument-in-band.rs b/src/test/ui/single-use-lifetime/one-use-in-fn-argument-in-band.rs
new file mode 100644
index 0000000..22c6a5a
--- /dev/null
+++ b/src/test/ui/single-use-lifetime/one-use-in-fn-argument-in-band.rs
@@ -0,0 +1,18 @@
+// run-rustfix
+
+#![feature(in_band_lifetimes)]
+#![deny(single_use_lifetimes)]
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+// Test that we DO warn when lifetime name is used only
+// once in a fn argument, even with in band lifetimes.
+
+fn a(x: &'a u32, y: &'b u32) {
+    //~^ ERROR `'a` only used once
+    //~| ERROR `'b` only used once
+    //~| HELP elide the single-use lifetime
+    //~| HELP elide the single-use lifetime
+}
+
+fn main() { }
diff --git a/src/test/ui/single-use-lifetime/one-use-in-fn-argument-in-band.stderr b/src/test/ui/single-use-lifetime/one-use-in-fn-argument-in-band.stderr
new file mode 100644
index 0000000..ef118a2
--- /dev/null
+++ b/src/test/ui/single-use-lifetime/one-use-in-fn-argument-in-band.stderr
@@ -0,0 +1,26 @@
+error: lifetime parameter `'a` only used once
+  --> $DIR/one-use-in-fn-argument-in-band.rs:11:10
+   |
+LL | fn a(x: &'a u32, y: &'b u32) {
+   |          ^^-
+   |          |
+   |          this lifetime is only used here
+   |          help: elide the single-use lifetime
+   |
+note: lint level defined here
+  --> $DIR/one-use-in-fn-argument-in-band.rs:4:9
+   |
+LL | #![deny(single_use_lifetimes)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: lifetime parameter `'b` only used once
+  --> $DIR/one-use-in-fn-argument-in-band.rs:11:22
+   |
+LL | fn a(x: &'a u32, y: &'b u32) {
+   |                      ^^-
+   |                      |
+   |                      this lifetime is only used here
+   |                      help: elide the single-use lifetime
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/single-use-lifetime/one-use-in-fn-argument.rs b/src/test/ui/single-use-lifetime/one-use-in-fn-argument.rs
new file mode 100644
index 0000000..900e843
--- /dev/null
+++ b/src/test/ui/single-use-lifetime/one-use-in-fn-argument.rs
@@ -0,0 +1,12 @@
+#![deny(single_use_lifetimes)]
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+// Test that we DO warn when lifetime name is used only
+// once in a fn argument.
+
+fn a<'a>(x: &'a u32) { //~ ERROR `'a` only used once
+    //~^ HELP elide the single-use lifetime
+}
+
+fn main() { }
diff --git a/src/test/ui/single-use-lifetime/one-use-in-fn-argument.stderr b/src/test/ui/single-use-lifetime/one-use-in-fn-argument.stderr
new file mode 100644
index 0000000..4bf0853
--- /dev/null
+++ b/src/test/ui/single-use-lifetime/one-use-in-fn-argument.stderr
@@ -0,0 +1,20 @@
+error: lifetime parameter `'a` only used once
+  --> $DIR/one-use-in-fn-argument.rs:8:6
+   |
+LL | fn a<'a>(x: &'a u32) {
+   |      ^^      -- ...is used only here
+   |      |
+   |      this lifetime...
+   |
+note: lint level defined here
+  --> $DIR/one-use-in-fn-argument.rs:1:9
+   |
+LL | #![deny(single_use_lifetimes)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+help: elide the single-use lifetime
+   |
+LL | fn a(x: &u32) {
+   |    --   --
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/single-use-lifetime/one-use-in-fn-return.rs b/src/test/ui/single-use-lifetime/one-use-in-fn-return.rs
new file mode 100644
index 0000000..876a0a5
--- /dev/null
+++ b/src/test/ui/single-use-lifetime/one-use-in-fn-return.rs
@@ -0,0 +1,20 @@
+// compile-pass
+
+#![deny(single_use_lifetimes)]
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+// Test that we DO NOT warn when lifetime name is used only
+// once in a fn return type -- using `'_` is not legal there,
+// as it must refer back to an argument.
+//
+// (Normally, using `'static` would be preferred, but there are
+// times when that is not what you want.)
+//
+// run-pass
+
+fn b<'a>() -> &'a u32 { // OK: used only in return type
+    &22
+}
+
+fn main() { }
diff --git a/src/test/ui/single-use-lifetime/one-use-in-inherent-impl-header.rs b/src/test/ui/single-use-lifetime/one-use-in-inherent-impl-header.rs
new file mode 100644
index 0000000..64f1c91
--- /dev/null
+++ b/src/test/ui/single-use-lifetime/one-use-in-inherent-impl-header.rs
@@ -0,0 +1,22 @@
+#![deny(single_use_lifetimes)]
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+// Test that we DO warn for a lifetime used only once in an impl, and that we
+// don't warn for the anonymous lifetime.
+
+struct Foo<'f> {
+    data: &'f u32
+}
+
+impl<'f> Foo<'f> { //~ ERROR `'f` only used once
+    fn inherent_a(&self) {
+    }
+}
+
+impl Foo<'_> {
+    fn inherent_b(&self) {}
+}
+
+
+fn main() { }
diff --git a/src/test/ui/single-use-lifetime/one-use-in-inherent-impl-header.stderr b/src/test/ui/single-use-lifetime/one-use-in-inherent-impl-header.stderr
new file mode 100644
index 0000000..8115a1e
--- /dev/null
+++ b/src/test/ui/single-use-lifetime/one-use-in-inherent-impl-header.stderr
@@ -0,0 +1,16 @@
+error: lifetime parameter `'f` only used once
+  --> $DIR/one-use-in-inherent-impl-header.rs:12:6
+   |
+LL | impl<'f> Foo<'f> {
+   |      ^^      -- ...is used only here
+   |      |
+   |      this lifetime...
+   |
+note: lint level defined here
+  --> $DIR/one-use-in-inherent-impl-header.rs:1:9
+   |
+LL | #![deny(single_use_lifetimes)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/single-use-lifetime/one-use-in-inherent-method-argument.rs b/src/test/ui/single-use-lifetime/one-use-in-inherent-method-argument.rs
new file mode 100644
index 0000000..e7bdbb2
--- /dev/null
+++ b/src/test/ui/single-use-lifetime/one-use-in-inherent-method-argument.rs
@@ -0,0 +1,17 @@
+#![deny(single_use_lifetimes)]
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+// Test that we DO warn for a lifetime used only once in an inherent method.
+
+struct Foo<'f> {
+    data: &'f u32
+}
+
+impl<'f> Foo<'f> { //~ ERROR `'f` only used once
+    fn inherent_a<'a>(&self, data: &'a u32) { //~ ERROR `'a` only used once
+        //~^ HELP elide the single-use lifetime
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/single-use-lifetime/one-use-in-inherent-method-argument.stderr b/src/test/ui/single-use-lifetime/one-use-in-inherent-method-argument.stderr
new file mode 100644
index 0000000..48bd9f1
--- /dev/null
+++ b/src/test/ui/single-use-lifetime/one-use-in-inherent-method-argument.stderr
@@ -0,0 +1,28 @@
+error: lifetime parameter `'a` only used once
+  --> $DIR/one-use-in-inherent-method-argument.rs:12:19
+   |
+LL |     fn inherent_a<'a>(&self, data: &'a u32) {
+   |                   ^^                -- ...is used only here
+   |                   |
+   |                   this lifetime...
+   |
+note: lint level defined here
+  --> $DIR/one-use-in-inherent-method-argument.rs:1:9
+   |
+LL | #![deny(single_use_lifetimes)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+help: elide the single-use lifetime
+   |
+LL |     fn inherent_a(&self, data: &u32) {
+   |                 --             --
+
+error: lifetime parameter `'f` only used once
+  --> $DIR/one-use-in-inherent-method-argument.rs:11:6
+   |
+LL | impl<'f> Foo<'f> {
+   |      ^^      -- ...is used only here
+   |      |
+   |      this lifetime...
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/single-use-lifetime/one-use-in-inherent-method-return.rs b/src/test/ui/single-use-lifetime/one-use-in-inherent-method-return.rs
new file mode 100644
index 0000000..c5938f4
--- /dev/null
+++ b/src/test/ui/single-use-lifetime/one-use-in-inherent-method-return.rs
@@ -0,0 +1,18 @@
+#![deny(single_use_lifetimes)]
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+// Test that we DO NOT warn for a lifetime used just once in a return type,
+// where that return type is in an inherent method.
+
+struct Foo<'f> {
+    data: &'f u32
+}
+
+impl<'f> Foo<'f> { //~ ERROR `'f` only used once
+    fn inherent_a<'a>(&self) -> &'a u32 { // OK for 'a
+        &22
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/single-use-lifetime/one-use-in-inherent-method-return.stderr b/src/test/ui/single-use-lifetime/one-use-in-inherent-method-return.stderr
new file mode 100644
index 0000000..9c93da4
--- /dev/null
+++ b/src/test/ui/single-use-lifetime/one-use-in-inherent-method-return.stderr
@@ -0,0 +1,16 @@
+error: lifetime parameter `'f` only used once
+  --> $DIR/one-use-in-inherent-method-return.rs:12:6
+   |
+LL | impl<'f> Foo<'f> {
+   |      ^^      -- ...is used only here
+   |      |
+   |      this lifetime...
+   |
+note: lint level defined here
+  --> $DIR/one-use-in-inherent-method-return.rs:1:9
+   |
+LL | #![deny(single_use_lifetimes)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/single-use-lifetime/one-use-in-struct.rs b/src/test/ui/single-use-lifetime/one-use-in-struct.rs
new file mode 100644
index 0000000..e0328c9
--- /dev/null
+++ b/src/test/ui/single-use-lifetime/one-use-in-struct.rs
@@ -0,0 +1,21 @@
+// Test that we do not warn for named lifetimes in structs,
+// even when they are only used once (since to not use a named
+// lifetime is illegal!)
+//
+// compile-pass
+
+#![deny(single_use_lifetimes)]
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+struct Foo<'f> {
+    data: &'f u32
+}
+
+enum Bar<'f> {
+    Data(&'f u32)
+}
+
+trait Baz<'f> { }
+
+fn main() { }
diff --git a/src/test/ui/single-use-lifetime/one-use-in-trait-method-argument.rs b/src/test/ui/single-use-lifetime/one-use-in-trait-method-argument.rs
new file mode 100644
index 0000000..6a66c17
--- /dev/null
+++ b/src/test/ui/single-use-lifetime/one-use-in-trait-method-argument.rs
@@ -0,0 +1,21 @@
+// Test that we DO warn for a lifetime on an impl used only in `&self`
+// in a trait method.
+
+#![deny(single_use_lifetimes)]
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+struct Foo<'f> {
+    data: &'f u32
+}
+
+impl<'f> Iterator for Foo<'f> {
+    type Item = &'f u32;
+
+    fn next<'g>(&'g mut self) -> Option<Self::Item> { //~ ERROR `'g` only used once
+        //~^ HELP elide the single-use lifetime
+        None
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/single-use-lifetime/one-use-in-trait-method-argument.stderr b/src/test/ui/single-use-lifetime/one-use-in-trait-method-argument.stderr
new file mode 100644
index 0000000..047e059
--- /dev/null
+++ b/src/test/ui/single-use-lifetime/one-use-in-trait-method-argument.stderr
@@ -0,0 +1,20 @@
+error: lifetime parameter `'g` only used once
+  --> $DIR/one-use-in-trait-method-argument.rs:15:13
+   |
+LL |     fn next<'g>(&'g mut self) -> Option<Self::Item> {
+   |             ^^   -- ...is used only here
+   |             |
+   |             this lifetime...
+   |
+note: lint level defined here
+  --> $DIR/one-use-in-trait-method-argument.rs:4:9
+   |
+LL | #![deny(single_use_lifetimes)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+help: elide the single-use lifetime
+   |
+LL |     fn next(&mut self) -> Option<Self::Item> {
+   |           ----
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/single-use-lifetime/two-uses-in-fn-argument-and-return.rs b/src/test/ui/single-use-lifetime/two-uses-in-fn-argument-and-return.rs
new file mode 100644
index 0000000..4cdf153
--- /dev/null
+++ b/src/test/ui/single-use-lifetime/two-uses-in-fn-argument-and-return.rs
@@ -0,0 +1,14 @@
+// Test that we DO NOT warn when lifetime name is used in
+// both the argument and return.
+//
+// compile-pass
+
+#![deny(single_use_lifetimes)]
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+fn c<'a>(x: &'a u32) -> &'a u32 { // OK: used twice
+    &22
+}
+
+fn main() { }
diff --git a/src/test/ui/single-use-lifetime/two-uses-in-fn-arguments.rs b/src/test/ui/single-use-lifetime/two-uses-in-fn-arguments.rs
new file mode 100644
index 0000000..375366e
--- /dev/null
+++ b/src/test/ui/single-use-lifetime/two-uses-in-fn-arguments.rs
@@ -0,0 +1,16 @@
+// Test that we DO NOT warn when lifetime name is used multiple
+// arguments, or more than once in a single argument.
+//
+// compile-pass
+
+#![deny(single_use_lifetimes)]
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+fn c<'a>(x: &'a u32, y: &'a u32) { // OK: used twice
+}
+
+fn d<'a>(x: (&'a u32, &'a u32)) { // OK: used twice
+}
+
+fn main() { }
diff --git a/src/test/ui/single-use-lifetime/two-uses-in-inherent-impl-header.rs b/src/test/ui/single-use-lifetime/two-uses-in-inherent-impl-header.rs
new file mode 100644
index 0000000..63d03a2
--- /dev/null
+++ b/src/test/ui/single-use-lifetime/two-uses-in-inherent-impl-header.rs
@@ -0,0 +1,18 @@
+// Test that we DO NOT warn for a lifetime used twice in an impl.
+//
+// compile-pass
+
+#![deny(single_use_lifetimes)]
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+struct Foo<'f> {
+    data: &'f u32
+}
+
+impl<'f> Foo<'f> {
+    fn inherent_a(&self, data: &'f u32) {
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/single-use-lifetime/two-uses-in-inherent-method-argument-and-return.rs b/src/test/ui/single-use-lifetime/two-uses-in-inherent-method-argument-and-return.rs
new file mode 100644
index 0000000..06ab6cd
--- /dev/null
+++ b/src/test/ui/single-use-lifetime/two-uses-in-inherent-method-argument-and-return.rs
@@ -0,0 +1,18 @@
+// Test that we DO NOT warn for a lifetime used twice in an impl method and
+// header.
+
+#![deny(single_use_lifetimes)]
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+struct Foo<'f> {
+    data: &'f u32
+}
+
+impl<'f> Foo<'f> { //~ ERROR `'f` only used once
+    fn inherent_a<'a>(&self, data: &'a u32) -> &'a u32{
+      data
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/single-use-lifetime/two-uses-in-inherent-method-argument-and-return.stderr b/src/test/ui/single-use-lifetime/two-uses-in-inherent-method-argument-and-return.stderr
new file mode 100644
index 0000000..6f0ba02
--- /dev/null
+++ b/src/test/ui/single-use-lifetime/two-uses-in-inherent-method-argument-and-return.stderr
@@ -0,0 +1,16 @@
+error: lifetime parameter `'f` only used once
+  --> $DIR/two-uses-in-inherent-method-argument-and-return.rs:12:6
+   |
+LL | impl<'f> Foo<'f> {
+   |      ^^      -- ...is used only here
+   |      |
+   |      this lifetime...
+   |
+note: lint level defined here
+  --> $DIR/two-uses-in-inherent-method-argument-and-return.rs:4:9
+   |
+LL | #![deny(single_use_lifetimes)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/single-use-lifetime/two-uses-in-trait-impl.rs b/src/test/ui/single-use-lifetime/two-uses-in-trait-impl.rs
new file mode 100644
index 0000000..d4a0d71
--- /dev/null
+++ b/src/test/ui/single-use-lifetime/two-uses-in-trait-impl.rs
@@ -0,0 +1,22 @@
+// Test that we DO NOT warn for a lifetime on an impl used in both
+// header and in an associated type.
+//
+// compile-pass
+
+#![deny(single_use_lifetimes)]
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+struct Foo<'f> {
+    data: &'f u32
+}
+
+impl<'f> Iterator for Foo<'f> {
+    type Item = &'f u32;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        None
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/single-use-lifetime/zero-uses-in-fn.fixed b/src/test/ui/single-use-lifetime/zero-uses-in-fn.fixed
new file mode 100644
index 0000000..89607af
--- /dev/null
+++ b/src/test/ui/single-use-lifetime/zero-uses-in-fn.fixed
@@ -0,0 +1,24 @@
+// run-rustfix
+
+// Test that we DO warn when lifetime name is not used at all.
+
+#![deny(unused_lifetimes)]
+#![allow(dead_code, unused_variables)]
+
+fn september() {}
+//~^ ERROR lifetime parameter `'a` never used
+//~| HELP elide the unused lifetime
+
+fn october<'b, T>(s: &'b T) -> &'b T {
+    //~^ ERROR lifetime parameter `'a` never used
+    //~| HELP elide the unused lifetime
+    s
+}
+
+fn november<'a>(s: &'a str) -> (&'a str) {
+    //~^ ERROR lifetime parameter `'b` never used
+    //~| HELP elide the unused lifetime
+    s
+}
+
+fn main() {}
diff --git a/src/test/ui/single-use-lifetime/zero-uses-in-fn.rs b/src/test/ui/single-use-lifetime/zero-uses-in-fn.rs
new file mode 100644
index 0000000..be0bdb9
--- /dev/null
+++ b/src/test/ui/single-use-lifetime/zero-uses-in-fn.rs
@@ -0,0 +1,24 @@
+// run-rustfix
+
+// Test that we DO warn when lifetime name is not used at all.
+
+#![deny(unused_lifetimes)]
+#![allow(dead_code, unused_variables)]
+
+fn september<'a>() {}
+//~^ ERROR lifetime parameter `'a` never used
+//~| HELP elide the unused lifetime
+
+fn october<'a, 'b, T>(s: &'b T) -> &'b T {
+    //~^ ERROR lifetime parameter `'a` never used
+    //~| HELP elide the unused lifetime
+    s
+}
+
+fn november<'a, 'b>(s: &'a str) -> (&'a str) {
+    //~^ ERROR lifetime parameter `'b` never used
+    //~| HELP elide the unused lifetime
+    s
+}
+
+fn main() {}
diff --git a/src/test/ui/single-use-lifetime/zero-uses-in-fn.stderr b/src/test/ui/single-use-lifetime/zero-uses-in-fn.stderr
new file mode 100644
index 0000000..2ccba79
--- /dev/null
+++ b/src/test/ui/single-use-lifetime/zero-uses-in-fn.stderr
@@ -0,0 +1,30 @@
+error: lifetime parameter `'a` never used
+  --> $DIR/zero-uses-in-fn.rs:8:14
+   |
+LL | fn september<'a>() {}
+   |             -^^- help: elide the unused lifetime
+   |
+note: lint level defined here
+  --> $DIR/zero-uses-in-fn.rs:5:9
+   |
+LL | #![deny(unused_lifetimes)]
+   |         ^^^^^^^^^^^^^^^^
+
+error: lifetime parameter `'a` never used
+  --> $DIR/zero-uses-in-fn.rs:12:12
+   |
+LL | fn october<'a, 'b, T>(s: &'b T) -> &'b T {
+   |            ^^--
+   |            |
+   |            help: elide the unused lifetime
+
+error: lifetime parameter `'b` never used
+  --> $DIR/zero-uses-in-fn.rs:18:17
+   |
+LL | fn november<'a, 'b>(s: &'a str) -> (&'a str) {
+   |               --^^
+   |               |
+   |               help: elide the unused lifetime
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/single-use-lifetime/zero-uses-in-impl.rs b/src/test/ui/single-use-lifetime/zero-uses-in-impl.rs
new file mode 100644
index 0000000..54803e1
--- /dev/null
+++ b/src/test/ui/single-use-lifetime/zero-uses-in-impl.rs
@@ -0,0 +1,10 @@
+// Test that we DO warn when lifetime name is not used at all.
+
+#![deny(unused_lifetimes)]
+#![allow(dead_code, unused_variables)]
+
+struct Foo {}
+
+impl<'a> Foo {} //~ ERROR `'a` never used
+
+fn main() {}
diff --git a/src/test/ui/single-use-lifetime/zero-uses-in-impl.stderr b/src/test/ui/single-use-lifetime/zero-uses-in-impl.stderr
new file mode 100644
index 0000000..650a9b4
--- /dev/null
+++ b/src/test/ui/single-use-lifetime/zero-uses-in-impl.stderr
@@ -0,0 +1,14 @@
+error: lifetime parameter `'a` never used
+  --> $DIR/zero-uses-in-impl.rs:8:6
+   |
+LL | impl<'a> Foo {}
+   |     -^^- help: elide the unused lifetime
+   |
+note: lint level defined here
+  --> $DIR/zero-uses-in-impl.rs:3:9
+   |
+LL | #![deny(unused_lifetimes)]
+   |         ^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/sized-cycle-note.rs b/src/test/ui/sized-cycle-note.rs
new file mode 100644
index 0000000..ca8be56
--- /dev/null
+++ b/src/test/ui/sized-cycle-note.rs
@@ -0,0 +1,16 @@
+// Test the error message resulting from a cycle in solving `Foo:
+// Sized`. The specifics of the message will of course but the main
+// thing we want to preserve is that:
+//
+// 1. the message should appear attached to one of the structs
+//    defined in this file;
+// 2. it should elaborate the steps that led to the cycle.
+
+struct Baz { q: Option<Foo> }
+//~^ ERROR recursive type `Baz` has infinite size
+struct Foo { q: Option<Baz> }
+//~^ ERROR recursive type `Foo` has infinite size
+
+impl Foo { fn bar(&self) {} }
+
+fn main() {}
diff --git a/src/test/ui/sized-cycle-note.stderr b/src/test/ui/sized-cycle-note.stderr
new file mode 100644
index 0000000..95bdc34
--- /dev/null
+++ b/src/test/ui/sized-cycle-note.stderr
@@ -0,0 +1,23 @@
+error[E0072]: recursive type `Baz` has infinite size
+  --> $DIR/sized-cycle-note.rs:9:1
+   |
+LL | struct Baz { q: Option<Foo> }
+   | ^^^^^^^^^^   -------------- recursive without indirection
+   | |
+   | recursive type has infinite size
+   |
+   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Baz` representable
+
+error[E0072]: recursive type `Foo` has infinite size
+  --> $DIR/sized-cycle-note.rs:11:1
+   |
+LL | struct Foo { q: Option<Baz> }
+   | ^^^^^^^^^^   -------------- recursive without indirection
+   | |
+   | recursive type has infinite size
+   |
+   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Foo` representable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0072`.
diff --git a/src/test/ui/slice-2.rs b/src/test/ui/slice-2.rs
new file mode 100644
index 0000000..5423e29
--- /dev/null
+++ b/src/test/ui/slice-2.rs
@@ -0,0 +1,11 @@
+// Test that slicing syntax gives errors if we have not implemented the trait.
+
+struct Foo;
+
+fn main() {
+    let x = Foo;
+    &x[..]; //~ ERROR cannot index into a value of type `Foo`
+    &x[Foo..]; //~ ERROR cannot index into a value of type `Foo`
+    &x[..Foo]; //~ ERROR cannot index into a value of type `Foo`
+    &x[Foo..Foo]; //~ ERROR cannot index into a value of type `Foo`
+}
diff --git a/src/test/ui/slice-2.stderr b/src/test/ui/slice-2.stderr
new file mode 100644
index 0000000..561feb9
--- /dev/null
+++ b/src/test/ui/slice-2.stderr
@@ -0,0 +1,27 @@
+error[E0608]: cannot index into a value of type `Foo`
+  --> $DIR/slice-2.rs:7:6
+   |
+LL |     &x[..];
+   |      ^^^^^
+
+error[E0608]: cannot index into a value of type `Foo`
+  --> $DIR/slice-2.rs:8:6
+   |
+LL |     &x[Foo..];
+   |      ^^^^^^^^
+
+error[E0608]: cannot index into a value of type `Foo`
+  --> $DIR/slice-2.rs:9:6
+   |
+LL |     &x[..Foo];
+   |      ^^^^^^^^
+
+error[E0608]: cannot index into a value of type `Foo`
+  --> $DIR/slice-2.rs:10:6
+   |
+LL |     &x[Foo..Foo];
+   |      ^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0608`.
diff --git a/src/test/ui/slice-mut-2.nll.stderr b/src/test/ui/slice-mut-2.nll.stderr
new file mode 100644
index 0000000..bad0268
--- /dev/null
+++ b/src/test/ui/slice-mut-2.nll.stderr
@@ -0,0 +1,12 @@
+error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
+  --> $DIR/slice-mut-2.rs:7:18
+   |
+LL |     let x: &[isize] = &[1, 2, 3, 4, 5];
+   |                       ---------------- help: consider changing this to be a mutable reference: `&mut [1, 2, 3, 4, 5]`
+...
+LL |     let _ = &mut x[2..4];
+   |                  ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/slice-mut-2.rs b/src/test/ui/slice-mut-2.rs
new file mode 100644
index 0000000..9586103
--- /dev/null
+++ b/src/test/ui/slice-mut-2.rs
@@ -0,0 +1,8 @@
+// Test mutability and slicing syntax.
+
+fn main() {
+    let x: &[isize] = &[1, 2, 3, 4, 5];
+    // Can't mutably slice an immutable slice
+    let slice: &mut [isize] = &mut [0, 1];
+    let _ = &mut x[2..4]; //~ERROR cannot borrow immutable borrowed content `*x` as mutable
+}
diff --git a/src/test/ui/slice-mut-2.stderr b/src/test/ui/slice-mut-2.stderr
new file mode 100644
index 0000000..78dbfa5
--- /dev/null
+++ b/src/test/ui/slice-mut-2.stderr
@@ -0,0 +1,9 @@
+error[E0596]: cannot borrow immutable borrowed content `*x` as mutable
+  --> $DIR/slice-mut-2.rs:7:18
+   |
+LL |     let _ = &mut x[2..4];
+   |                  ^ cannot borrow as mutable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/slice-mut.rs b/src/test/ui/slice-mut.rs
new file mode 100644
index 0000000..dc5ef58
--- /dev/null
+++ b/src/test/ui/slice-mut.rs
@@ -0,0 +1,12 @@
+// Test mutability and slicing syntax.
+
+fn main() {
+    let x: &[isize] = &[1, 2, 3, 4, 5];
+    // Immutable slices are not mutable.
+
+    let y: &mut[_] = &x[2..4];
+    //~^ ERROR mismatched types
+    //~| expected type `&mut [_]`
+    //~| found type `&[isize]`
+    //~| types differ in mutability
+}
diff --git a/src/test/ui/slice-mut.stderr b/src/test/ui/slice-mut.stderr
new file mode 100644
index 0000000..e99d83d
--- /dev/null
+++ b/src/test/ui/slice-mut.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/slice-mut.rs:7:22
+   |
+LL |     let y: &mut[_] = &x[2..4];
+   |                      ^^^^^^^^ types differ in mutability
+   |
+   = note: expected type `&mut [_]`
+              found type `&[isize]`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/slightly-nice-generic-literal-messages.rs b/src/test/ui/slightly-nice-generic-literal-messages.rs
new file mode 100644
index 0000000..cd0ee17
--- /dev/null
+++ b/src/test/ui/slightly-nice-generic-literal-messages.rs
@@ -0,0 +1,14 @@
+use std::marker;
+
+struct Foo<T,U>(T, marker::PhantomData<U>);
+
+fn main() {
+    match Foo(1.1, marker::PhantomData) {
+        1 => {}
+    //~^ ERROR mismatched types
+    //~| expected type `Foo<{float}, _>`
+    //~| found type `{integer}`
+    //~| expected struct `Foo`, found integer
+    }
+
+}
diff --git a/src/test/ui/slightly-nice-generic-literal-messages.stderr b/src/test/ui/slightly-nice-generic-literal-messages.stderr
new file mode 100644
index 0000000..76ebc00
--- /dev/null
+++ b/src/test/ui/slightly-nice-generic-literal-messages.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/slightly-nice-generic-literal-messages.rs:7:9
+   |
+LL |         1 => {}
+   |         ^ expected struct `Foo`, found integer
+   |
+   = note: expected type `Foo<{float}, _>`
+              found type `{integer}`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/span/E0046.rs b/src/test/ui/span/E0046.rs
new file mode 100644
index 0000000..9611098
--- /dev/null
+++ b/src/test/ui/span/E0046.rs
@@ -0,0 +1,11 @@
+trait Foo {
+    fn foo();
+}
+
+struct Bar;
+
+impl Foo for Bar {}
+//~^ ERROR E0046
+
+fn main() {
+}
diff --git a/src/test/ui/span/E0046.stderr b/src/test/ui/span/E0046.stderr
new file mode 100644
index 0000000..1323524
--- /dev/null
+++ b/src/test/ui/span/E0046.stderr
@@ -0,0 +1,12 @@
+error[E0046]: not all trait items implemented, missing: `foo`
+  --> $DIR/E0046.rs:7:1
+   |
+LL |     fn foo();
+   |     --------- `foo` from trait
+...
+LL | impl Foo for Bar {}
+   | ^^^^^^^^^^^^^^^^ missing `foo` in implementation
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0046`.
diff --git a/src/test/ui/span/E0057.rs b/src/test/ui/span/E0057.rs
new file mode 100644
index 0000000..83f941f
--- /dev/null
+++ b/src/test/ui/span/E0057.rs
@@ -0,0 +1,6 @@
+fn main() {
+    let f = |x| x * 3;
+    let a = f(); //~ ERROR E0057
+    let b = f(4);
+    let c = f(2, 3); //~ ERROR E0057
+}
diff --git a/src/test/ui/span/E0057.stderr b/src/test/ui/span/E0057.stderr
new file mode 100644
index 0000000..6b5890c
--- /dev/null
+++ b/src/test/ui/span/E0057.stderr
@@ -0,0 +1,15 @@
+error[E0057]: this function takes 1 parameter but 0 parameters were supplied
+  --> $DIR/E0057.rs:3:13
+   |
+LL |     let a = f();
+   |             ^^^ expected 1 parameter
+
+error[E0057]: this function takes 1 parameter but 2 parameters were supplied
+  --> $DIR/E0057.rs:5:13
+   |
+LL |     let c = f(2, 3);
+   |             ^^^^^^^ expected 1 parameter
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0057`.
diff --git a/src/test/ui/span/E0072.rs b/src/test/ui/span/E0072.rs
new file mode 100644
index 0000000..bc284cd
--- /dev/null
+++ b/src/test/ui/span/E0072.rs
@@ -0,0 +1,7 @@
+struct ListNode { //~ ERROR has infinite size
+    head: u8,
+    tail: Option<ListNode>,
+}
+
+fn main() {
+}
diff --git a/src/test/ui/span/E0072.stderr b/src/test/ui/span/E0072.stderr
new file mode 100644
index 0000000..d4a5e74
--- /dev/null
+++ b/src/test/ui/span/E0072.stderr
@@ -0,0 +1,14 @@
+error[E0072]: recursive type `ListNode` has infinite size
+  --> $DIR/E0072.rs:1:1
+   |
+LL | struct ListNode {
+   | ^^^^^^^^^^^^^^^ recursive type has infinite size
+LL |     head: u8,
+LL |     tail: Option<ListNode>,
+   |     ---------------------- recursive without indirection
+   |
+   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `ListNode` representable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0072`.
diff --git a/src/test/ui/span/E0204.rs b/src/test/ui/span/E0204.rs
new file mode 100644
index 0000000..174de8c
--- /dev/null
+++ b/src/test/ui/span/E0204.rs
@@ -0,0 +1,26 @@
+struct Foo {
+    foo: Vec<u32>,
+}
+
+impl Copy for Foo { } //~ ERROR may not be implemented for this type
+
+#[derive(Copy)] //~ ERROR may not be implemented for this type
+struct Foo2<'a> {
+    ty: &'a mut bool,
+}
+
+enum EFoo {
+    Bar { x: Vec<u32> },
+    Baz,
+}
+
+impl Copy for EFoo { } //~ ERROR may not be implemented for this type
+
+#[derive(Copy)] //~ ERROR may not be implemented for this type
+enum EFoo2<'a> {
+    Bar(&'a mut bool),
+    Baz,
+}
+
+fn main() {
+}
diff --git a/src/test/ui/span/E0204.stderr b/src/test/ui/span/E0204.stderr
new file mode 100644
index 0000000..5a981a4
--- /dev/null
+++ b/src/test/ui/span/E0204.stderr
@@ -0,0 +1,39 @@
+error[E0204]: the trait `Copy` may not be implemented for this type
+  --> $DIR/E0204.rs:5:6
+   |
+LL |     foo: Vec<u32>,
+   |     ------------- this field does not implement `Copy`
+...
+LL | impl Copy for Foo { }
+   |      ^^^^
+
+error[E0204]: the trait `Copy` may not be implemented for this type
+  --> $DIR/E0204.rs:7:10
+   |
+LL | #[derive(Copy)]
+   |          ^^^^
+LL | struct Foo2<'a> {
+LL |     ty: &'a mut bool,
+   |     ---------------- this field does not implement `Copy`
+
+error[E0204]: the trait `Copy` may not be implemented for this type
+  --> $DIR/E0204.rs:17:6
+   |
+LL |     Bar { x: Vec<u32> },
+   |           ----------- this field does not implement `Copy`
+...
+LL | impl Copy for EFoo { }
+   |      ^^^^
+
+error[E0204]: the trait `Copy` may not be implemented for this type
+  --> $DIR/E0204.rs:19:10
+   |
+LL | #[derive(Copy)]
+   |          ^^^^
+LL | enum EFoo2<'a> {
+LL |     Bar(&'a mut bool),
+   |         ------------ this field does not implement `Copy`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0204`.
diff --git a/src/test/ui/span/E0493.rs b/src/test/ui/span/E0493.rs
new file mode 100644
index 0000000..ad41002
--- /dev/null
+++ b/src/test/ui/span/E0493.rs
@@ -0,0 +1,21 @@
+struct Foo {
+    a: u32
+}
+
+impl Drop for Foo {
+    fn drop(&mut self) {}
+}
+
+struct Bar {
+    a: u32
+}
+
+impl Drop for Bar {
+    fn drop(&mut self) {}
+}
+
+const F : Foo = (Foo { a : 0 }, Foo { a : 1 }).1;
+//~^ destructors cannot be evaluated at compile-time
+
+fn main() {
+}
diff --git a/src/test/ui/span/E0493.stderr b/src/test/ui/span/E0493.stderr
new file mode 100644
index 0000000..d05e89e
--- /dev/null
+++ b/src/test/ui/span/E0493.stderr
@@ -0,0 +1,9 @@
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/E0493.rs:17:17
+   |
+LL | const F : Foo = (Foo { a : 0 }, Foo { a : 1 }).1;
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constants cannot evaluate destructors
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0493`.
diff --git a/src/test/ui/span/E0535.rs b/src/test/ui/span/E0535.rs
new file mode 100644
index 0000000..e26334e
--- /dev/null
+++ b/src/test/ui/span/E0535.rs
@@ -0,0 +1,6 @@
+#[inline(unknown)] //~ ERROR E0535
+pub fn something() {}
+
+fn main() {
+    something();
+}
diff --git a/src/test/ui/span/E0535.stderr b/src/test/ui/span/E0535.stderr
new file mode 100644
index 0000000..f52c3f9
--- /dev/null
+++ b/src/test/ui/span/E0535.stderr
@@ -0,0 +1,9 @@
+error[E0535]: invalid argument
+  --> $DIR/E0535.rs:1:10
+   |
+LL | #[inline(unknown)]
+   |          ^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0535`.
diff --git a/src/test/ui/span/E0536.rs b/src/test/ui/span/E0536.rs
new file mode 100644
index 0000000..72de7b6
--- /dev/null
+++ b/src/test/ui/span/E0536.rs
@@ -0,0 +1,4 @@
+#[cfg(not())] //~ ERROR E0536
+pub fn something() {}
+
+pub fn main() {}
diff --git a/src/test/ui/span/E0536.stderr b/src/test/ui/span/E0536.stderr
new file mode 100644
index 0000000..820b0d7
--- /dev/null
+++ b/src/test/ui/span/E0536.stderr
@@ -0,0 +1,9 @@
+error[E0536]: expected 1 cfg-pattern
+  --> $DIR/E0536.rs:1:7
+   |
+LL | #[cfg(not())]
+   |       ^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0536`.
diff --git a/src/test/ui/span/E0537.rs b/src/test/ui/span/E0537.rs
new file mode 100644
index 0000000..4088a9a
--- /dev/null
+++ b/src/test/ui/span/E0537.rs
@@ -0,0 +1,4 @@
+#[cfg(unknown())] //~ ERROR E0537
+pub fn something() {}
+
+pub fn main() {}
diff --git a/src/test/ui/span/E0537.stderr b/src/test/ui/span/E0537.stderr
new file mode 100644
index 0000000..5478c3f
--- /dev/null
+++ b/src/test/ui/span/E0537.stderr
@@ -0,0 +1,9 @@
+error[E0537]: invalid predicate `unknown`
+  --> $DIR/E0537.rs:1:7
+   |
+LL | #[cfg(unknown())]
+   |       ^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0537`.
diff --git a/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.nll.stderr b/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.nll.stderr
new file mode 100644
index 0000000..0a9bc3a
--- /dev/null
+++ b/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.nll.stderr
@@ -0,0 +1,88 @@
+error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
+  --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:53:24
+   |
+LL | fn deref_mut_field1(x: Own<Point>) {
+   |                     - help: consider changing this to be mutable: `mut x`
+LL |     let __isize = &mut x.y;
+   |                        ^ cannot borrow as mutable
+
+error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
+  --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:65: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
+   |          ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+
+error[E0499]: cannot borrow `*x` as mutable more than once at a time
+  --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:78:19
+   |
+LL |     let _x = &mut x.x;
+   |                   - first mutable borrow occurs here
+LL |     let _y = &mut x.y;
+   |                   ^ second mutable borrow occurs here
+LL |     use_mut(_x);
+   |             -- first borrow later used here
+
+error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
+  --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:88:5
+   |
+LL | fn assign_field1<'a>(x: Own<Point>) {
+   |                      - help: consider changing this to be mutable: `mut x`
+LL |     x.y = 3;
+   |     ^ cannot borrow as mutable
+
+error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
+  --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:92:5
+   |
+LL | fn assign_field2<'a>(x: &'a Own<Point>) {
+   |                         -------------- help: consider changing this to be a mutable reference: `&'a mut Own<Point>`
+LL |     x.y = 3;
+   |     ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+
+error[E0499]: cannot borrow `*x` as mutable more than once at a time
+  --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:101:5
+   |
+LL |     let _p: &mut Point = &mut **x;
+   |                                -- first mutable borrow occurs here
+LL |     x.y = 3;
+   |     ^ second mutable borrow occurs here
+LL |     use_mut(_p);
+   |             -- first borrow later used here
+
+error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
+  --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:109:5
+   |
+LL | fn deref_mut_method1(x: Own<Point>) {
+   |                      - help: consider changing this to be mutable: `mut x`
+LL |     x.set(0, 0);
+   |     ^ cannot borrow as mutable
+
+error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
+  --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:121: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()
+   |     ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+
+error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
+  --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:129:6
+   |
+LL | fn assign_method1<'a>(x: Own<Point>) {
+   |                       - help: consider changing this to be mutable: `mut x`
+LL |     *x.y_mut() = 3;
+   |      ^ cannot borrow as mutable
+
+error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
+  --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:133:6
+   |
+LL | fn assign_method2<'a>(x: &'a Own<Point>) {
+   |                          -------------- help: consider changing this to be a mutable reference: `&'a mut Own<Point>`
+LL |     *x.y_mut() = 3;
+   |      ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+
+error: aborting due to 10 previous errors
+
+Some errors occurred: E0499, E0596.
+For more information about an error, try `rustc --explain E0499`.
diff --git a/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.rs b/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.rs
new file mode 100644
index 0000000..76a1d12
--- /dev/null
+++ b/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.rs
@@ -0,0 +1,142 @@
+// Test how overloaded deref interacts with borrows when DerefMut
+// is implemented.
+
+use std::ops::{Deref, DerefMut};
+
+struct Own<T> {
+    value: *mut T
+}
+
+impl<T> Deref for Own<T> {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        unsafe { &*self.value }
+    }
+}
+
+impl<T> DerefMut for Own<T> {
+    fn deref_mut(&mut self) -> &mut T {
+        unsafe { &mut *self.value }
+    }
+}
+
+struct Point {
+    x: isize,
+    y: isize
+}
+
+impl Point {
+    fn get(&self) -> (isize, isize) {
+        (self.x, self.y)
+    }
+
+    fn set(&mut self, x: isize, y: isize) {
+        self.x = x;
+        self.y = y;
+    }
+
+    fn x_ref(&self) -> &isize {
+        &self.x
+    }
+
+    fn y_mut(&mut self) -> &mut isize {
+        &mut self.y
+    }
+}
+
+fn deref_imm_field(x: Own<Point>) {
+    let __isize = &x.y;
+}
+
+fn deref_mut_field1(x: Own<Point>) {
+    let __isize = &mut x.y; //~ ERROR cannot borrow
+}
+
+fn deref_mut_field2(mut x: Own<Point>) {
+    let __isize = &mut x.y;
+}
+
+fn deref_extend_field(x: &Own<Point>) -> &isize {
+    &x.y
+}
+
+fn deref_extend_mut_field1(x: &Own<Point>) -> &mut isize {
+    &mut x.y //~ ERROR cannot borrow
+}
+
+fn deref_extend_mut_field2(x: &mut Own<Point>) -> &mut isize {
+    &mut x.y
+}
+
+fn deref_extend_mut_field3(x: &mut Own<Point>) {
+    // Hmm, this is unfortunate, because with box it would work,
+    // but it's presently the expected outcome. See `deref_extend_mut_field4`
+    // for the workaround.
+
+    let _x = &mut x.x;
+    let _y = &mut x.y; //~ ERROR cannot borrow
+    use_mut(_x);
+}
+fn deref_extend_mut_field4<'a>(x: &'a mut Own<Point>) {
+    let p = &mut **x;
+    let _x = &mut p.x;
+    let _y = &mut p.y;
+}
+
+fn assign_field1<'a>(x: Own<Point>) {
+    x.y = 3; //~ ERROR cannot borrow
+}
+
+fn assign_field2<'a>(x: &'a Own<Point>) {
+    x.y = 3; //~ ERROR cannot borrow
+}
+
+fn assign_field3<'a>(x: &'a mut Own<Point>) {
+    x.y = 3;
+}
+
+fn assign_field4<'a>(x: &'a mut Own<Point>) {
+    let _p: &mut Point = &mut **x;
+    x.y = 3; //~ ERROR cannot borrow
+    use_mut(_p);
+}
+fn deref_imm_method(x: Own<Point>) {
+    let __isize = x.get();
+}
+
+fn deref_mut_method1(x: Own<Point>) {
+    x.set(0, 0); //~ ERROR cannot borrow
+}
+
+fn deref_mut_method2(mut x: Own<Point>) {
+    x.set(0, 0);
+}
+
+fn deref_extend_method(x: &Own<Point>) -> &isize {
+    x.x_ref()
+}
+
+fn deref_extend_mut_method1(x: &Own<Point>) -> &mut isize {
+    x.y_mut() //~ ERROR cannot borrow
+}
+
+fn deref_extend_mut_method2(x: &mut Own<Point>) -> &mut isize {
+    x.y_mut()
+}
+
+fn assign_method1<'a>(x: Own<Point>) {
+    *x.y_mut() = 3; //~ ERROR cannot borrow
+}
+
+fn assign_method2<'a>(x: &'a Own<Point>) {
+    *x.y_mut() = 3; //~ ERROR cannot borrow
+}
+
+fn assign_method3<'a>(x: &'a mut Own<Point>) {
+    *x.y_mut() = 3;
+}
+
+pub fn main() {}
+
+fn use_mut<T>(_: &mut T) {}
diff --git a/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr b/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr
new file mode 100644
index 0000000..63baa7c
--- /dev/null
+++ b/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr
@@ -0,0 +1,90 @@
+error[E0596]: cannot borrow immutable argument `x` as mutable
+  --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:53:24
+   |
+LL | fn deref_mut_field1(x: Own<Point>) {
+   |                     - help: make this binding mutable: `mut x`
+LL |     let __isize = &mut x.y;
+   |                        ^ cannot borrow mutably
+
+error[E0596]: cannot borrow immutable borrowed content `*x` as mutable
+  --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:65:10
+   |
+LL | fn deref_extend_mut_field1(x: &Own<Point>) -> &mut isize {
+   |                               ----------- use `&mut Own<Point>` here to make mutable
+LL |     &mut x.y
+   |          ^ cannot borrow as mutable
+
+error[E0499]: cannot borrow `*x` as mutable more than once at a time
+  --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:78:19
+   |
+LL |     let _x = &mut x.x;
+   |                   - first mutable borrow occurs here
+LL |     let _y = &mut x.y;
+   |                   ^ second mutable borrow occurs here
+LL |     use_mut(_x);
+LL | }
+   | - first borrow ends here
+
+error[E0596]: cannot borrow immutable argument `x` as mutable
+  --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:88:5
+   |
+LL | fn assign_field1<'a>(x: Own<Point>) {
+   |                      - help: make this binding mutable: `mut x`
+LL |     x.y = 3;
+   |     ^ cannot borrow mutably
+
+error[E0596]: cannot borrow immutable borrowed content `*x` as mutable
+  --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:92:5
+   |
+LL | fn assign_field2<'a>(x: &'a Own<Point>) {
+   |                         -------------- use `&'a mut Own<Point>` here to make mutable
+LL |     x.y = 3;
+   |     ^ cannot borrow as mutable
+
+error[E0499]: cannot borrow `*x` as mutable more than once at a time
+  --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:101:5
+   |
+LL |     let _p: &mut Point = &mut **x;
+   |                                -- first mutable borrow occurs here
+LL |     x.y = 3;
+   |     ^ second mutable borrow occurs here
+LL |     use_mut(_p);
+LL | }
+   | - first borrow ends here
+
+error[E0596]: cannot borrow immutable argument `x` as mutable
+  --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:109:5
+   |
+LL | fn deref_mut_method1(x: Own<Point>) {
+   |                      - help: make this binding mutable: `mut x`
+LL |     x.set(0, 0);
+   |     ^ cannot borrow mutably
+
+error[E0596]: cannot borrow immutable borrowed content `*x` as mutable
+  --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:121:5
+   |
+LL | fn deref_extend_mut_method1(x: &Own<Point>) -> &mut isize {
+   |                                ----------- use `&mut Own<Point>` here to make mutable
+LL |     x.y_mut()
+   |     ^ cannot borrow as mutable
+
+error[E0596]: cannot borrow immutable argument `x` as mutable
+  --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:129:6
+   |
+LL | fn assign_method1<'a>(x: Own<Point>) {
+   |                       - help: make this binding mutable: `mut x`
+LL |     *x.y_mut() = 3;
+   |      ^ cannot borrow mutably
+
+error[E0596]: cannot borrow immutable borrowed content `*x` as mutable
+  --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:133:6
+   |
+LL | fn assign_method2<'a>(x: &'a Own<Point>) {
+   |                          -------------- use `&'a mut Own<Point>` here to make mutable
+LL |     *x.y_mut() = 3;
+   |      ^ cannot borrow as mutable
+
+error: aborting due to 10 previous errors
+
+Some errors occurred: E0499, E0596.
+For more information about an error, try `rustc --explain E0499`.
diff --git a/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.nll.stderr b/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.nll.stderr
new file mode 100644
index 0000000..3ebfba7
--- /dev/null
+++ b/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.nll.stderr
@@ -0,0 +1,35 @@
+error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
+  --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:29:25
+   |
+LL | fn deref_mut1(x: Own<isize>) {
+   |               - help: consider changing this to be mutable: `mut x`
+LL |     let __isize = &mut *x;
+   |                         ^ cannot borrow as mutable
+
+error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
+  --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:41:11
+   |
+LL | fn deref_extend_mut1<'a>(x: &'a Own<isize>) -> &'a mut isize {
+   |                             -------------- help: consider changing this to be a mutable reference: `&'a mut Own<isize>`
+LL |     &mut **x
+   |           ^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+
+error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
+  --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:49:6
+   |
+LL | fn assign1<'a>(x: Own<isize>) {
+   |                - help: consider changing this to be mutable: `mut x`
+LL |     *x = 3;
+   |      ^ cannot borrow as mutable
+
+error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
+  --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:53:6
+   |
+LL | fn assign2<'a>(x: &'a Own<isize>) {
+   |                   -------------- help: consider changing this to be a mutable reference: `&'a mut Own<isize>`
+LL |     **x = 3;
+   |      ^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.rs b/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.rs
new file mode 100644
index 0000000..8d43d5d
--- /dev/null
+++ b/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.rs
@@ -0,0 +1,60 @@
+// Test how overloaded deref interacts with borrows when DerefMut
+// is implemented.
+
+use std::ops::{Deref, DerefMut};
+
+struct Own<T> {
+    value: *mut T
+}
+
+impl<T> Deref for Own<T> {
+    type Target = T;
+
+    fn deref<'a>(&'a self) -> &'a T {
+        unsafe { &*self.value }
+    }
+}
+
+impl<T> DerefMut for Own<T> {
+    fn deref_mut<'a>(&'a mut self) -> &'a mut T {
+        unsafe { &mut *self.value }
+    }
+}
+
+fn deref_imm(x: Own<isize>) {
+    let __isize = &*x;
+}
+
+fn deref_mut1(x: Own<isize>) {
+    let __isize = &mut *x; //~ ERROR cannot borrow
+}
+
+fn deref_mut2(mut x: Own<isize>) {
+    let __isize = &mut *x;
+}
+
+fn deref_extend<'a>(x: &'a Own<isize>) -> &'a isize {
+    &**x
+}
+
+fn deref_extend_mut1<'a>(x: &'a Own<isize>) -> &'a mut isize {
+    &mut **x //~ ERROR cannot borrow
+}
+
+fn deref_extend_mut2<'a>(x: &'a mut Own<isize>) -> &'a mut isize {
+    &mut **x
+}
+
+fn assign1<'a>(x: Own<isize>) {
+    *x = 3; //~ ERROR cannot borrow
+}
+
+fn assign2<'a>(x: &'a Own<isize>) {
+    **x = 3; //~ ERROR cannot borrow
+}
+
+fn assign3<'a>(x: &'a mut Own<isize>) {
+    **x = 3;
+}
+
+pub fn main() {}
diff --git a/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.stderr b/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.stderr
new file mode 100644
index 0000000..77f3982
--- /dev/null
+++ b/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.stderr
@@ -0,0 +1,35 @@
+error[E0596]: cannot borrow immutable argument `x` as mutable
+  --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:29:25
+   |
+LL | fn deref_mut1(x: Own<isize>) {
+   |               - help: make this binding mutable: `mut x`
+LL |     let __isize = &mut *x;
+   |                         ^ cannot borrow mutably
+
+error[E0596]: cannot borrow immutable borrowed content `*x` as mutable
+  --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:41:11
+   |
+LL | fn deref_extend_mut1<'a>(x: &'a Own<isize>) -> &'a mut isize {
+   |                             -------------- use `&'a mut Own<isize>` here to make mutable
+LL |     &mut **x
+   |           ^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow immutable argument `x` as mutable
+  --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:49:6
+   |
+LL | fn assign1<'a>(x: Own<isize>) {
+   |                - help: make this binding mutable: `mut x`
+LL |     *x = 3;
+   |      ^ cannot borrow mutably
+
+error[E0596]: cannot borrow immutable borrowed content `*x` as mutable
+  --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:53:6
+   |
+LL | fn assign2<'a>(x: &'a Own<isize>) {
+   |                   -------------- use `&'a mut Own<isize>` here to make mutable
+LL |     **x = 3;
+   |      ^^ cannot borrow as mutable
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr
new file mode 100644
index 0000000..4e2ab59
--- /dev/null
+++ b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr
@@ -0,0 +1,51 @@
+error[E0499]: cannot borrow `f` as mutable more than once at a time
+  --> $DIR/borrowck-call-is-borrow-issue-12224.rs:12:16
+   |
+LL |     f(Box::new(|| {
+   |     -          ^^ second mutable borrow occurs here
+   |     |
+   |     first mutable borrow occurs here
+   |     first borrow later used by call
+LL |
+LL |         f((Box::new(|| {})))
+   |         - second borrow occurs due to use of `f` in closure
+
+error[E0596]: cannot borrow `*f` as mutable, as it is behind a `&` reference
+  --> $DIR/borrowck-call-is-borrow-issue-12224.rs:25:5
+   |
+LL | fn test2<F>(f: &F) where F: FnMut() {
+   |                -- help: consider changing this to be a mutable reference: `&mut F`
+LL |     (*f)();
+   |     ^^^^ `f` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+
+error[E0596]: cannot borrow `f.f` as mutable, as it is behind a `&` reference
+  --> $DIR/borrowck-call-is-borrow-issue-12224.rs:34:5
+   |
+LL | fn test4(f: &Test) {
+   |             ----- help: consider changing this to be a mutable reference: `&mut Test<'_>`
+LL |     f.f.call_mut(())
+   |     ^^^ `f` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+
+error[E0507]: cannot move out of captured variable in an `FnMut` closure
+  --> $DIR/borrowck-call-is-borrow-issue-12224.rs:56:13
+   |
+LL |     let mut f = move |g: Box<FnMut(isize)>, b: isize| {
+   |         ----- captured outer variable
+...
+LL |         foo(f);
+   |             ^ cannot move out of captured variable in an `FnMut` closure
+
+error[E0505]: cannot move out of `f` because it is borrowed
+  --> $DIR/borrowck-call-is-borrow-issue-12224.rs:55:16
+   |
+LL |     f(Box::new(|a| {
+   |     -          ^^^ move out of `f` occurs here
+   |     |
+   |     borrow of `f` occurs here
+LL |         foo(f);
+   |             - move occurs due to use in closure
+
+error: aborting due to 5 previous errors
+
+Some errors occurred: E0499, E0505, E0507, E0596.
+For more information about an error, try `rustc --explain E0499`.
diff --git a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.rs b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.rs
new file mode 100644
index 0000000..f246f11
--- /dev/null
+++ b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.rs
@@ -0,0 +1,62 @@
+#![feature(fn_traits)]
+
+// Ensure that invoking a closure counts as a unique immutable borrow
+
+type Fn<'a> = Box<FnMut() + 'a>;
+
+struct Test<'a> {
+    f: Box<FnMut() + 'a>
+}
+
+fn call<F>(mut f: F) where F: FnMut(Fn) {
+    f(Box::new(|| {
+    //~^ ERROR: cannot borrow `f` as mutable more than once
+        f((Box::new(|| {})))
+    }));
+}
+
+fn test1() {
+    call(|mut a| {
+        a.call_mut(());
+    });
+}
+
+fn test2<F>(f: &F) where F: FnMut() {
+    (*f)();
+    //~^ ERROR cannot borrow immutable borrowed content `*f` as mutable
+}
+
+fn test3<F>(f: &mut F) where F: FnMut() {
+    (*f)();
+}
+
+fn test4(f: &Test) {
+    f.f.call_mut(())
+    //~^ ERROR: cannot borrow field `f.f` of immutable binding as mutable
+}
+
+fn test5(f: &mut Test) {
+    f.f.call_mut(())
+}
+
+fn test6() {
+    let mut f = || {};
+    (|| {
+        f();
+    })();
+}
+
+fn test7() {
+    fn foo<F>(_: F) where F: FnMut(Box<FnMut(isize)>, isize) {}
+    let s = String::new();  // Capture to make f !Copy
+    let mut f = move |g: Box<FnMut(isize)>, b: isize| {
+        let _ = s.len();
+    };
+    f(Box::new(|a| {
+        foo(f);
+        //~^ ERROR cannot move `f` into closure because it is borrowed
+        //~| ERROR cannot move out of captured outer variable in an `FnMut` closure
+    }), 3);
+}
+
+fn main() {}
diff --git a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr
new file mode 100644
index 0000000..a61ee83
--- /dev/null
+++ b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr
@@ -0,0 +1,50 @@
+error[E0499]: cannot borrow `f` as mutable more than once at a time
+  --> $DIR/borrowck-call-is-borrow-issue-12224.rs:12:16
+   |
+LL |     f(Box::new(|| {
+   |     -          ^^ second mutable borrow occurs here
+   |     |
+   |     first mutable borrow occurs here
+LL |
+LL |         f((Box::new(|| {})))
+   |         - borrow occurs due to use of `f` in closure
+LL |     }));
+   |       - first borrow ends here
+
+error[E0596]: cannot borrow immutable borrowed content `*f` as mutable
+  --> $DIR/borrowck-call-is-borrow-issue-12224.rs:25:5
+   |
+LL | fn test2<F>(f: &F) where F: FnMut() {
+   |                -- use `&mut F` here to make mutable
+LL |     (*f)();
+   |     ^^^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow field `f.f` of immutable binding as mutable
+  --> $DIR/borrowck-call-is-borrow-issue-12224.rs:34:5
+   |
+LL | fn test4(f: &Test) {
+   |             ----- use `&mut Test` here to make mutable
+LL |     f.f.call_mut(())
+   |     ^^^ cannot mutably borrow field of immutable binding
+
+error[E0504]: cannot move `f` into closure because it is borrowed
+  --> $DIR/borrowck-call-is-borrow-issue-12224.rs:56:13
+   |
+LL |     f(Box::new(|a| {
+   |     - borrow of `f` occurs here
+LL |         foo(f);
+   |             ^ move into closure occurs here
+
+error[E0507]: cannot move out of captured outer variable in an `FnMut` closure
+  --> $DIR/borrowck-call-is-borrow-issue-12224.rs:56:13
+   |
+LL |     let mut f = move |g: Box<FnMut(isize)>, b: isize| {
+   |         ----- captured outer variable
+...
+LL |         foo(f);
+   |             ^ cannot move out of captured outer variable in an `FnMut` closure
+
+error: aborting due to 5 previous errors
+
+Some errors occurred: E0499, E0504, E0507, E0596.
+For more information about an error, try `rustc --explain E0499`.
diff --git a/src/test/ui/span/borrowck-call-method-from-mut-aliasable.nll.stderr b/src/test/ui/span/borrowck-call-method-from-mut-aliasable.nll.stderr
new file mode 100644
index 0000000..6b5e077
--- /dev/null
+++ b/src/test/ui/span/borrowck-call-method-from-mut-aliasable.nll.stderr
@@ -0,0 +1,12 @@
+error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
+  --> $DIR/borrowck-call-method-from-mut-aliasable.rs:17:5
+   |
+LL | fn b(x: &Foo) {
+   |         ---- help: consider changing this to be a mutable reference: `&mut Foo`
+LL |     x.f();
+LL |     x.h();
+   |     ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/span/borrowck-call-method-from-mut-aliasable.rs b/src/test/ui/span/borrowck-call-method-from-mut-aliasable.rs
new file mode 100644
index 0000000..caf2d2a
--- /dev/null
+++ b/src/test/ui/span/borrowck-call-method-from-mut-aliasable.rs
@@ -0,0 +1,21 @@
+struct Foo {
+    x: isize,
+}
+
+impl Foo {
+    pub fn f(&self) {}
+    pub fn h(&mut self) {}
+}
+
+fn a(x: &mut Foo) {
+    x.f();
+    x.h();
+}
+
+fn b(x: &Foo) {
+    x.f();
+    x.h(); //~ ERROR cannot borrow
+}
+
+fn main() {
+}
diff --git a/src/test/ui/span/borrowck-call-method-from-mut-aliasable.stderr b/src/test/ui/span/borrowck-call-method-from-mut-aliasable.stderr
new file mode 100644
index 0000000..440c5c9
--- /dev/null
+++ b/src/test/ui/span/borrowck-call-method-from-mut-aliasable.stderr
@@ -0,0 +1,12 @@
+error[E0596]: cannot borrow immutable borrowed content `*x` as mutable
+  --> $DIR/borrowck-call-method-from-mut-aliasable.rs:17:5
+   |
+LL | fn b(x: &Foo) {
+   |         ---- use `&mut Foo` here to make mutable
+LL |     x.f();
+LL |     x.h();
+   |     ^ cannot borrow as mutable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/span/borrowck-fn-in-const-b.nll.stderr b/src/test/ui/span/borrowck-fn-in-const-b.nll.stderr
new file mode 100644
index 0000000..9133d48
--- /dev/null
+++ b/src/test/ui/span/borrowck-fn-in-const-b.nll.stderr
@@ -0,0 +1,11 @@
+error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
+  --> $DIR/borrowck-fn-in-const-b.rs:7: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"));
+   |         ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/span/borrowck-fn-in-const-b.rs b/src/test/ui/span/borrowck-fn-in-const-b.rs
new file mode 100644
index 0000000..822083e
--- /dev/null
+++ b/src/test/ui/span/borrowck-fn-in-const-b.rs
@@ -0,0 +1,14 @@
+// Check that we check fns appearing in constant declarations.
+// Issue #22382.
+
+// How about mutating an immutable vector?
+const MUTATE: fn(&Vec<String>) = {
+    fn broken(x: &Vec<String>) {
+        x.push(format!("this is broken"));
+        //~^ ERROR cannot borrow
+    }
+    broken
+};
+
+fn main() {
+}
diff --git a/src/test/ui/span/borrowck-fn-in-const-b.stderr b/src/test/ui/span/borrowck-fn-in-const-b.stderr
new file mode 100644
index 0000000..4a30bdf
--- /dev/null
+++ b/src/test/ui/span/borrowck-fn-in-const-b.stderr
@@ -0,0 +1,11 @@
+error[E0596]: cannot borrow immutable borrowed content `*x` as mutable
+  --> $DIR/borrowck-fn-in-const-b.rs:7:9
+   |
+LL |     fn broken(x: &Vec<String>) {
+   |                  ------------ use `&mut Vec<String>` here to make mutable
+LL |         x.push(format!("this is broken"));
+   |         ^ cannot borrow as mutable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/span/borrowck-let-suggestion-suffixes.nll.stderr b/src/test/ui/span/borrowck-let-suggestion-suffixes.nll.stderr
new file mode 100644
index 0000000..f5f1193
--- /dev/null
+++ b/src/test/ui/span/borrowck-let-suggestion-suffixes.nll.stderr
@@ -0,0 +1,42 @@
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/borrowck-let-suggestion-suffixes.rs:19:14
+   |
+LL |     v3.push(&id('x'));           // statement 6
+   |              ^^^^^^^ - temporary value is freed at the end of this statement
+   |              |
+   |              creates a temporary which is freed while still in use
+...
+LL |     (v1, v2, v3, /* v4 is above. */ v5).use_ref();
+   |              -- borrow later used here
+   |
+   = note: consider using a `let` binding to create a longer lived value
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/borrowck-let-suggestion-suffixes.rs:29:18
+   |
+LL |         v4.push(&id('y'));
+   |                  ^^^^^^^ - temporary value is freed at the end of this statement
+   |                  |
+   |                  creates a temporary which is freed while still in use
+...
+LL |         v4.use_ref();
+   |         -- borrow later used here
+   |
+   = note: consider using a `let` binding to create a longer lived value
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/borrowck-let-suggestion-suffixes.rs:40:14
+   |
+LL |     v5.push(&id('z'));
+   |              ^^^^^^^ - temporary value is freed at the end of this statement
+   |              |
+   |              creates a temporary which is freed while still in use
+...
+LL |     (v1, v2, v3, /* v4 is above. */ v5).use_ref();
+   |                                     -- borrow later used here
+   |
+   = note: consider using a `let` binding to create a longer lived value
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/src/test/ui/span/borrowck-let-suggestion-suffixes.rs b/src/test/ui/span/borrowck-let-suggestion-suffixes.rs
new file mode 100644
index 0000000..4b14907
--- /dev/null
+++ b/src/test/ui/span/borrowck-let-suggestion-suffixes.rs
@@ -0,0 +1,59 @@
+#![feature(rustc_attrs)]
+fn id<T>(x: T) -> T { x }
+
+fn f() {
+    let old = ['o'];         // statement 0
+    let mut v1 = Vec::new(); // statement 1
+
+    let mut v2 = Vec::new(); // statement 2
+
+    let young = ['y'];       // statement 3
+
+    v2.push(&young[0]);      // statement 4
+    //~^ ERROR `young[..]` does not live long enough
+    //~| NOTE borrowed value does not live long enough
+    //~| NOTE values in a scope are dropped in the opposite order they are created
+
+    let mut v3 = Vec::new(); // statement 5
+
+    v3.push(&id('x'));           // statement 6
+    //~^ ERROR borrowed value does not live long enough
+    //~| NOTE temporary value does not live long enough
+    //~| NOTE temporary value dropped here while still borrowed
+    //~| NOTE consider using a `let` binding to increase its lifetime
+
+    {
+
+        let mut v4 = Vec::new(); // (sub) statement 0
+
+        v4.push(&id('y'));
+        //~^ ERROR borrowed value does not live long enough
+        //~| NOTE temporary value does not live long enough
+        //~| NOTE temporary value dropped here while still borrowed
+        //~| NOTE consider using a `let` binding to increase its lifetime
+        v4.use_ref();
+    }                       // (statement 7)
+    //~^ NOTE temporary value needs to live until here
+
+    let mut v5 = Vec::new(); // statement 8
+
+    v5.push(&id('z'));
+    //~^ ERROR borrowed value does not live long enough
+    //~| NOTE temporary value does not live long enough
+    //~| NOTE temporary value dropped here while still borrowed
+    //~| NOTE consider using a `let` binding to increase its lifetime
+
+    v1.push(&old[0]);
+
+    (v1, v2, v3, /* v4 is above. */ v5).use_ref();
+}
+//~^ NOTE `young[..]` dropped here while still borrowed
+//~| NOTE temporary value needs to live until here
+//~| NOTE temporary value needs to live until here
+
+fn main() { #![rustc_error] // rust-lang/rust#49855
+    f();
+}
+
+trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { }  }
+impl<T> Fake for T { }
diff --git a/src/test/ui/span/borrowck-let-suggestion-suffixes.stderr b/src/test/ui/span/borrowck-let-suggestion-suffixes.stderr
new file mode 100644
index 0000000..8bf542e
--- /dev/null
+++ b/src/test/ui/span/borrowck-let-suggestion-suffixes.stderr
@@ -0,0 +1,53 @@
+error[E0597]: `young[..]` does not live long enough
+  --> $DIR/borrowck-let-suggestion-suffixes.rs:12:14
+   |
+LL |     v2.push(&young[0]);      // statement 4
+   |              ^^^^^^^^ borrowed value does not live long enough
+...
+LL | }
+   | - `young[..]` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/borrowck-let-suggestion-suffixes.rs:19:14
+   |
+LL |     v3.push(&id('x'));           // statement 6
+   |              ^^^^^^^ - temporary value dropped here while still borrowed
+   |              |
+   |              temporary value does not live long enough
+...
+LL | }
+   | - temporary value needs to live until here
+   |
+   = note: consider using a `let` binding to increase its lifetime
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/borrowck-let-suggestion-suffixes.rs:29:18
+   |
+LL |         v4.push(&id('y'));
+   |                  ^^^^^^^ - temporary value dropped here while still borrowed
+   |                  |
+   |                  temporary value does not live long enough
+...
+LL |     }                       // (statement 7)
+   |     - temporary value needs to live until here
+   |
+   = note: consider using a `let` binding to increase its lifetime
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/borrowck-let-suggestion-suffixes.rs:40:14
+   |
+LL |     v5.push(&id('z'));
+   |              ^^^^^^^ - temporary value dropped here while still borrowed
+   |              |
+   |              temporary value does not live long enough
+...
+LL | }
+   | - temporary value needs to live until here
+   |
+   = note: consider using a `let` binding to increase its lifetime
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/borrowck-object-mutability.nll.stderr b/src/test/ui/span/borrowck-object-mutability.nll.stderr
new file mode 100644
index 0000000..fe6014c
--- /dev/null
+++ b/src/test/ui/span/borrowck-object-mutability.nll.stderr
@@ -0,0 +1,21 @@
+error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
+  --> $DIR/borrowck-object-mutability.rs:8:5
+   |
+LL | fn borrowed_receiver(x: &Foo) {
+   |                         ---- help: consider changing this to be a mutable reference: `&mut dyn Foo`
+LL |     x.borrowed();
+LL |     x.borrowed_mut();
+   |     ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+
+error[E0596]: cannot borrow `*x` as mutable, as `x` is not declared as mutable
+  --> $DIR/borrowck-object-mutability.rs:18:5
+   |
+LL | fn owned_receiver(x: Box<Foo>) {
+   |                   - help: consider changing this to be mutable: `mut x`
+LL |     x.borrowed();
+LL |     x.borrowed_mut();
+   |     ^ cannot borrow as mutable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/span/borrowck-object-mutability.rs b/src/test/ui/span/borrowck-object-mutability.rs
new file mode 100644
index 0000000..e672c46
--- /dev/null
+++ b/src/test/ui/span/borrowck-object-mutability.rs
@@ -0,0 +1,26 @@
+trait Foo {
+    fn borrowed(&self);
+    fn borrowed_mut(&mut self);
+}
+
+fn borrowed_receiver(x: &Foo) {
+    x.borrowed();
+    x.borrowed_mut(); //~ ERROR cannot borrow
+}
+
+fn borrowed_mut_receiver(x: &mut Foo) {
+    x.borrowed();
+    x.borrowed_mut();
+}
+
+fn owned_receiver(x: Box<Foo>) {
+    x.borrowed();
+    x.borrowed_mut(); //~ ERROR cannot borrow
+}
+
+fn mut_owned_receiver(mut x: Box<Foo>) {
+    x.borrowed();
+    x.borrowed_mut();
+}
+
+fn main() {}
diff --git a/src/test/ui/span/borrowck-object-mutability.stderr b/src/test/ui/span/borrowck-object-mutability.stderr
new file mode 100644
index 0000000..073a70e
--- /dev/null
+++ b/src/test/ui/span/borrowck-object-mutability.stderr
@@ -0,0 +1,21 @@
+error[E0596]: cannot borrow immutable borrowed content `*x` as mutable
+  --> $DIR/borrowck-object-mutability.rs:8:5
+   |
+LL | fn borrowed_receiver(x: &Foo) {
+   |                         ---- use `&mut Foo` here to make mutable
+LL |     x.borrowed();
+LL |     x.borrowed_mut();
+   |     ^ cannot borrow as mutable
+
+error[E0596]: cannot borrow immutable `Box` content `*x` as mutable
+  --> $DIR/borrowck-object-mutability.rs:18:5
+   |
+LL | fn owned_receiver(x: Box<Foo>) {
+   |                   - help: make this binding mutable: `mut x`
+LL |     x.borrowed();
+LL |     x.borrowed_mut();
+   |     ^ cannot borrow as mutable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/span/borrowck-ref-into-rvalue.nll.stderr b/src/test/ui/span/borrowck-ref-into-rvalue.nll.stderr
new file mode 100644
index 0000000..4f529ce
--- /dev/null
+++ b/src/test/ui/span/borrowck-ref-into-rvalue.nll.stderr
@@ -0,0 +1,16 @@
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/borrowck-ref-into-rvalue.rs:3:11
+   |
+LL |     match Some("Hello".to_string()) {
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+...
+LL |     }
+   |     - temporary value is freed at the end of this statement
+LL |     println!("{}", *msg);
+   |                    ---- borrow later used here
+   |
+   = note: consider using a `let` binding to create a longer lived value
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/src/test/ui/span/borrowck-ref-into-rvalue.rs b/src/test/ui/span/borrowck-ref-into-rvalue.rs
new file mode 100644
index 0000000..aeaebf0
--- /dev/null
+++ b/src/test/ui/span/borrowck-ref-into-rvalue.rs
@@ -0,0 +1,11 @@
+fn main() {
+    let msg;
+    match Some("Hello".to_string()) {
+        Some(ref m) => {
+        //~^ ERROR borrowed value does not live long enough
+            msg = m;
+        },
+        None => { panic!() }
+    }
+    println!("{}", *msg);
+}
diff --git a/src/test/ui/span/borrowck-ref-into-rvalue.stderr b/src/test/ui/span/borrowck-ref-into-rvalue.stderr
new file mode 100644
index 0000000..b8e79be
--- /dev/null
+++ b/src/test/ui/span/borrowck-ref-into-rvalue.stderr
@@ -0,0 +1,17 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/borrowck-ref-into-rvalue.rs:4:14
+   |
+LL |         Some(ref m) => {
+   |              ^^^^^ borrowed value does not live long enough
+...
+LL |     }
+   |     - borrowed value dropped here while still borrowed
+LL |     println!("{}", *msg);
+LL | }
+   | - borrowed value needs to live until here
+   |
+   = note: consider using a `let` binding to increase its lifetime
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/coerce-suggestions.rs b/src/test/ui/span/coerce-suggestions.rs
new file mode 100644
index 0000000..c461f82
--- /dev/null
+++ b/src/test/ui/span/coerce-suggestions.rs
@@ -0,0 +1,23 @@
+#![feature(box_syntax)]
+
+fn test(_x: &mut String) {}
+fn test2(_x: &mut i32) {}
+
+fn main() {
+    let x: usize = String::new();
+    //~^ ERROR E0308
+    let x: &str = String::new();
+    //~^ ERROR E0308
+    let y = String::new();
+    test(&y);
+    //~^ ERROR E0308
+    test2(&y);
+    //~^ ERROR E0308
+    let f;
+    f = box f;
+    //~^ ERROR E0308
+
+    let s = &mut String::new();
+    s = format!("foo");
+    //~^ ERROR E0308
+}
diff --git a/src/test/ui/span/coerce-suggestions.stderr b/src/test/ui/span/coerce-suggestions.stderr
new file mode 100644
index 0000000..996d80a
--- /dev/null
+++ b/src/test/ui/span/coerce-suggestions.stderr
@@ -0,0 +1,61 @@
+error[E0308]: mismatched types
+  --> $DIR/coerce-suggestions.rs:7:20
+   |
+LL |     let x: usize = String::new();
+   |                    ^^^^^^^^^^^^^ expected usize, found struct `std::string::String`
+   |
+   = note: expected type `usize`
+              found type `std::string::String`
+
+error[E0308]: mismatched types
+  --> $DIR/coerce-suggestions.rs:9:19
+   |
+LL |     let x: &str = String::new();
+   |                   ^^^^^^^^^^^^^
+   |                   |
+   |                   expected &str, found struct `std::string::String`
+   |                   help: consider borrowing here: `&String::new()`
+   |
+   = note: expected type `&str`
+              found type `std::string::String`
+
+error[E0308]: mismatched types
+  --> $DIR/coerce-suggestions.rs:12:10
+   |
+LL |     test(&y);
+   |          ^^ types differ in mutability
+   |
+   = note: expected type `&mut std::string::String`
+              found type `&std::string::String`
+
+error[E0308]: mismatched types
+  --> $DIR/coerce-suggestions.rs:14:11
+   |
+LL |     test2(&y);
+   |           ^^ types differ in mutability
+   |
+   = note: expected type `&mut i32`
+              found type `&std::string::String`
+
+error[E0308]: mismatched types
+  --> $DIR/coerce-suggestions.rs:17:9
+   |
+LL |     f = box f;
+   |         ^^^^^
+   |         |
+   |         cyclic type of infinite size
+   |         help: try using a conversion method: `box f.to_string()`
+
+error[E0308]: mismatched types
+  --> $DIR/coerce-suggestions.rs:21:9
+   |
+LL |     s = format!("foo");
+   |         ^^^^^^^^^^^^^^ expected mutable reference, found struct `std::string::String`
+   |
+   = note: expected type `&mut std::string::String`
+              found type `std::string::String`
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/span/destructor-restrictions.nll.stderr b/src/test/ui/span/destructor-restrictions.nll.stderr
new file mode 100644
index 0000000..a3c6cfb
--- /dev/null
+++ b/src/test/ui/span/destructor-restrictions.nll.stderr
@@ -0,0 +1,18 @@
+error[E0597]: `*a` does not live long enough
+  --> $DIR/destructor-restrictions.rs:8:10
+   |
+LL |         *a.borrow() + 1
+   |          ^---------
+   |          |
+   |          borrowed value does not live long enough
+   |          a temporary with access to the borrow is created here ...
+LL |     };
+   |     -- ... and the borrow might be used here, when that temporary is dropped and runs the destructor for type `std::cell::Ref<'_, i32>`
+   |     |
+   |     `*a` dropped here while still borrowed
+   |
+   = note: The temporary is part of an expression at the end of a block. Consider forcing this temporary to be dropped sooner, before the block's local variables are dropped. For example, you could save the expression's value in a new local variable `x` and then make `x` be the expression at the end of the block.
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/destructor-restrictions.rs b/src/test/ui/span/destructor-restrictions.rs
new file mode 100644
index 0000000..7fb348a
--- /dev/null
+++ b/src/test/ui/span/destructor-restrictions.rs
@@ -0,0 +1,11 @@
+// Tests the new destructor semantics.
+
+use std::cell::RefCell;
+
+fn main() {
+    let b = {
+        let a = Box::new(RefCell::new(4));
+        *a.borrow() + 1
+    }; //~^ ERROR `*a` does not live long enough
+    println!("{}", b);
+}
diff --git a/src/test/ui/span/destructor-restrictions.stderr b/src/test/ui/span/destructor-restrictions.stderr
new file mode 100644
index 0000000..a82e24b
--- /dev/null
+++ b/src/test/ui/span/destructor-restrictions.stderr
@@ -0,0 +1,13 @@
+error[E0597]: `*a` does not live long enough
+  --> $DIR/destructor-restrictions.rs:8:10
+   |
+LL |         *a.borrow() + 1
+   |          ^ borrowed value does not live long enough
+LL |     };
+   |     -- borrowed value needs to live until here
+   |     |
+   |     `*a` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/dropck-object-cycle.nll.stderr b/src/test/ui/span/dropck-object-cycle.nll.stderr
new file mode 100644
index 0000000..cfaf470
--- /dev/null
+++ b/src/test/ui/span/dropck-object-cycle.nll.stderr
@@ -0,0 +1,15 @@
+error[E0597]: `*m` does not live long enough
+  --> $DIR/dropck-object-cycle.rs:27:31
+   |
+LL |     assert_eq!(object_invoke1(&*m), (4,5));
+   |                               ^^^ borrowed value does not live long enough
+...
+LL | }
+   | -
+   | |
+   | `*m` dropped here while still borrowed
+   | borrow might be used here, when `m` is dropped and runs the destructor for type `std::boxed::Box<dyn Trait<'_>>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/dropck-object-cycle.rs b/src/test/ui/span/dropck-object-cycle.rs
new file mode 100644
index 0000000..7b7f37d
--- /dev/null
+++ b/src/test/ui/span/dropck-object-cycle.rs
@@ -0,0 +1,48 @@
+// This test used to be part of a run-pass test, but revised outlives
+// rule means that it no longer compiles.
+
+#![allow(unused_variables)]
+
+trait Trait<'a> {
+    fn long(&'a self) -> isize;
+    fn short<'b>(&'b self) -> isize;
+}
+
+fn object_invoke1<'d>(x: &'d Trait<'d>) -> (isize, isize) { loop { } }
+
+trait MakerTrait {
+    fn mk() -> Self;
+}
+
+fn make_val<T:MakerTrait>() -> T {
+    MakerTrait::mk()
+}
+
+impl<'t> MakerTrait for Box<Trait<'t>+'static> {
+    fn mk() -> Box<Trait<'t>+'static> { loop { } }
+}
+
+pub fn main() {
+    let m : Box<Trait+'static> = make_val();
+    assert_eq!(object_invoke1(&*m), (4,5));
+    //~^ ERROR `*m` does not live long enough
+
+    // the problem here is that the full type of `m` is
+    //
+    //   Box<Trait<'m>+'static>
+    //
+    // Here `'m` must be exactly the lifetime of the variable `m`.
+    // This is because of two requirements:
+    // 1. First, the basic type rules require that the
+    //    type of `m`'s value outlives the lifetime of `m`. This puts a lower
+    //    bound `'m`.
+    //
+    // 2. Meanwhile, the signature of `object_invoke1` requires that
+    //    we create a reference of type `&'d Trait<'d>` for some `'d`.
+    //    `'d` cannot outlive `'m`, so that forces the lifetime to be `'m`.
+    //
+    // This then conflicts with the dropck rules, which require that
+    // the type of `m` *strictly outlives* `'m`. Hence we get an
+    // error.
+}
+
diff --git a/src/test/ui/span/dropck-object-cycle.stderr b/src/test/ui/span/dropck-object-cycle.stderr
new file mode 100644
index 0000000..3fc5285
--- /dev/null
+++ b/src/test/ui/span/dropck-object-cycle.stderr
@@ -0,0 +1,14 @@
+error[E0597]: `*m` does not live long enough
+  --> $DIR/dropck-object-cycle.rs:27:32
+   |
+LL |     assert_eq!(object_invoke1(&*m), (4,5));
+   |                                ^^ borrowed value does not live long enough
+...
+LL | }
+   | - `*m` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/dropck_arr_cycle_checked.nll.stderr b/src/test/ui/span/dropck_arr_cycle_checked.nll.stderr
new file mode 100644
index 0000000..e9caae6
--- /dev/null
+++ b/src/test/ui/span/dropck_arr_cycle_checked.nll.stderr
@@ -0,0 +1,43 @@
+error[E0597]: `b2` does not live long enough
+  --> $DIR/dropck_arr_cycle_checked.rs:93:24
+   |
+LL |     b1.a[0].v.set(Some(&b2));
+   |                        ^^^ borrowed value does not live long enough
+...
+LL | }
+   | -
+   | |
+   | `b2` dropped here while still borrowed
+   | borrow might be used here, when `b1` is dropped and runs the destructor for type `B<'_>`
+   |
+   = note: values in a scope are dropped in the opposite order they are defined
+
+error[E0597]: `b3` does not live long enough
+  --> $DIR/dropck_arr_cycle_checked.rs:95:24
+   |
+LL |     b1.a[1].v.set(Some(&b3));
+   |                        ^^^ borrowed value does not live long enough
+...
+LL | }
+   | -
+   | |
+   | `b3` dropped here while still borrowed
+   | borrow might be used here, when `b1` is dropped and runs the destructor for type `B<'_>`
+   |
+   = note: values in a scope are dropped in the opposite order they are defined
+
+error[E0597]: `b1` does not live long enough
+  --> $DIR/dropck_arr_cycle_checked.rs:101:24
+   |
+LL |     b3.a[0].v.set(Some(&b1));
+   |                        ^^^ borrowed value does not live long enough
+...
+LL | }
+   | -
+   | |
+   | `b1` dropped here while still borrowed
+   | borrow might be used here, when `b1` is dropped and runs the destructor for type `B<'_>`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/dropck_arr_cycle_checked.rs b/src/test/ui/span/dropck_arr_cycle_checked.rs
new file mode 100644
index 0000000..3514501
--- /dev/null
+++ b/src/test/ui/span/dropck_arr_cycle_checked.rs
@@ -0,0 +1,109 @@
+// Reject mixing cyclic structure and Drop when using fixed length
+// arrays.
+//
+// (Compare against compile-fail/dropck_vec_cycle_checked.rs)
+
+
+
+use std::cell::Cell;
+use id::Id;
+
+mod s {
+    use std::sync::atomic::{AtomicUsize, Ordering};
+
+    static S_COUNT: AtomicUsize = AtomicUsize::new(0);
+
+    pub fn next_count() -> usize {
+        S_COUNT.fetch_add(1, Ordering::SeqCst) + 1
+    }
+}
+
+mod id {
+    use s;
+    #[derive(Debug)]
+    pub struct Id {
+        orig_count: usize,
+        count: usize,
+    }
+
+    impl Id {
+        pub fn new() -> Id {
+            let c = s::next_count();
+            println!("building Id {}", c);
+            Id { orig_count: c, count: c }
+        }
+        pub fn count(&self) -> usize {
+            println!("Id::count on {} returns {}", self.orig_count, self.count);
+            self.count
+        }
+    }
+
+    impl Drop for Id {
+        fn drop(&mut self) {
+            println!("dropping Id {}", self.count);
+            self.count = 0;
+        }
+    }
+}
+
+trait HasId {
+    fn count(&self) -> usize;
+}
+
+#[derive(Debug)]
+struct CheckId<T:HasId> {
+    v: T
+}
+
+#[allow(non_snake_case)]
+fn CheckId<T:HasId>(t: T) -> CheckId<T> { CheckId{ v: t } }
+
+impl<T:HasId> Drop for CheckId<T> {
+    fn drop(&mut self) {
+        assert!(self.v.count() > 0);
+    }
+}
+
+#[derive(Debug)]
+struct B<'a> {
+    id: Id,
+    a: [CheckId<Cell<Option<&'a B<'a>>>>; 2]
+}
+
+impl<'a> HasId for Cell<Option<&'a B<'a>>> {
+    fn count(&self) -> usize {
+        match self.get() {
+            None => 1,
+            Some(b) => b.id.count(),
+        }
+    }
+}
+
+impl<'a> B<'a> {
+    fn new() -> B<'a> {
+        B { id: Id::new(), a: [CheckId(Cell::new(None)), CheckId(Cell::new(None))] }
+    }
+}
+
+fn f() {
+    let (b1, b2, b3);
+    b1 = B::new();
+    b2 = B::new();
+    b3 = B::new();
+    b1.a[0].v.set(Some(&b2));
+    //~^ ERROR `b2` does not live long enough
+    b1.a[1].v.set(Some(&b3));
+    //~^ ERROR `b3` does not live long enough
+    b2.a[0].v.set(Some(&b2));
+    //~^ ERROR `b2` does not live long enough
+    b2.a[1].v.set(Some(&b3));
+    //~^ ERROR `b3` does not live long enough
+    b3.a[0].v.set(Some(&b1));
+    //~^ ERROR `b1` does not live long enough
+    b3.a[1].v.set(Some(&b2));
+    //~^ ERROR `b2` does not live long enough
+}
+
+fn main() {
+    f();
+}
diff --git a/src/test/ui/span/dropck_arr_cycle_checked.stderr b/src/test/ui/span/dropck_arr_cycle_checked.stderr
new file mode 100644
index 0000000..b2bacc7
--- /dev/null
+++ b/src/test/ui/span/dropck_arr_cycle_checked.stderr
@@ -0,0 +1,69 @@
+error[E0597]: `b2` does not live long enough
+  --> $DIR/dropck_arr_cycle_checked.rs:93:25
+   |
+LL |     b1.a[0].v.set(Some(&b2));
+   |                         ^^ borrowed value does not live long enough
+...
+LL | }
+   | - `b2` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error[E0597]: `b3` does not live long enough
+  --> $DIR/dropck_arr_cycle_checked.rs:95:25
+   |
+LL |     b1.a[1].v.set(Some(&b3));
+   |                         ^^ borrowed value does not live long enough
+...
+LL | }
+   | - `b3` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error[E0597]: `b2` does not live long enough
+  --> $DIR/dropck_arr_cycle_checked.rs:97:25
+   |
+LL |     b2.a[0].v.set(Some(&b2));
+   |                         ^^ borrowed value does not live long enough
+...
+LL | }
+   | - `b2` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error[E0597]: `b3` does not live long enough
+  --> $DIR/dropck_arr_cycle_checked.rs:99:25
+   |
+LL |     b2.a[1].v.set(Some(&b3));
+   |                         ^^ borrowed value does not live long enough
+...
+LL | }
+   | - `b3` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error[E0597]: `b1` does not live long enough
+  --> $DIR/dropck_arr_cycle_checked.rs:101:25
+   |
+LL |     b3.a[0].v.set(Some(&b1));
+   |                         ^^ borrowed value does not live long enough
+...
+LL | }
+   | - `b1` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error[E0597]: `b2` does not live long enough
+  --> $DIR/dropck_arr_cycle_checked.rs:103:25
+   |
+LL |     b3.a[1].v.set(Some(&b2));
+   |                         ^^ borrowed value does not live long enough
+LL |
+LL | }
+   | - `b2` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/dropck_direct_cycle_with_drop.nll.stderr b/src/test/ui/span/dropck_direct_cycle_with_drop.nll.stderr
new file mode 100644
index 0000000..07ae138
--- /dev/null
+++ b/src/test/ui/span/dropck_direct_cycle_with_drop.nll.stderr
@@ -0,0 +1,29 @@
+error[E0597]: `d2` does not live long enough
+  --> $DIR/dropck_direct_cycle_with_drop.rs:36:19
+   |
+LL |     d1.p.set(Some(&d2));
+   |                   ^^^ borrowed value does not live long enough
+...
+LL | }
+   | -
+   | |
+   | `d2` dropped here while still borrowed
+   | borrow might be used here, when `d1` is dropped and runs the `Drop` code for type `D`
+   |
+   = note: values in a scope are dropped in the opposite order they are defined
+
+error[E0597]: `d1` does not live long enough
+  --> $DIR/dropck_direct_cycle_with_drop.rs:38:19
+   |
+LL |     d2.p.set(Some(&d1));
+   |                   ^^^ borrowed value does not live long enough
+LL |
+LL | }
+   | -
+   | |
+   | `d1` dropped here while still borrowed
+   | borrow might be used here, when `d1` is dropped and runs the `Drop` code for type `D`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/dropck_direct_cycle_with_drop.rs b/src/test/ui/span/dropck_direct_cycle_with_drop.rs
new file mode 100644
index 0000000..14d6e66
--- /dev/null
+++ b/src/test/ui/span/dropck_direct_cycle_with_drop.rs
@@ -0,0 +1,44 @@
+// A simple example of an unsound mixing of cyclic structure and Drop.
+//
+// Each `D` has a name and an optional reference to another `D`
+// sibling, but also implements a drop method that prints out its own
+// name as well as the name of its sibling.
+//
+// By setting up a cyclic structure, the drop code cannot possibly
+// work. Therefore this code must be rejected.
+//
+// (As it turns out, essentially any attempt to install a sibling here
+//  will be rejected, regardless of whether it forms a cyclic
+//  structure or not. This is because the use of the same lifetime
+//  `'a` in `&'a D<'a>` cannot be satisfied when `D<'a>` implements
+//  `Drop`.)
+
+use std::cell::Cell;
+
+struct D<'a> {
+    name: String,
+    p: Cell<Option<&'a D<'a>>>,
+}
+
+impl<'a> D<'a> {
+    fn new(name: String) -> D<'a> { D { name: name, p: Cell::new(None) } }
+}
+
+impl<'a> Drop for D<'a> {
+    fn drop(&mut self) {
+        println!("dropping {} whose sibling is {:?}",
+                 self.name, self.p.get().map(|d| &d.name));
+    }
+}
+
+fn g() {
+    let (d1, d2) = (D::new(format!("d1")), D::new(format!("d2")));
+    d1.p.set(Some(&d2));
+    //~^ ERROR `d2` does not live long enough
+    d2.p.set(Some(&d1));
+    //~^ ERROR `d1` does not live long enough
+}
+
+fn main() {
+    g();
+}
diff --git a/src/test/ui/span/dropck_direct_cycle_with_drop.stderr b/src/test/ui/span/dropck_direct_cycle_with_drop.stderr
new file mode 100644
index 0000000..4979242
--- /dev/null
+++ b/src/test/ui/span/dropck_direct_cycle_with_drop.stderr
@@ -0,0 +1,25 @@
+error[E0597]: `d2` does not live long enough
+  --> $DIR/dropck_direct_cycle_with_drop.rs:36:20
+   |
+LL |     d1.p.set(Some(&d2));
+   |                    ^^ borrowed value does not live long enough
+...
+LL | }
+   | - `d2` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error[E0597]: `d1` does not live long enough
+  --> $DIR/dropck_direct_cycle_with_drop.rs:38:20
+   |
+LL |     d2.p.set(Some(&d1));
+   |                    ^^ borrowed value does not live long enough
+LL |
+LL | }
+   | - `d1` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/dropck_misc_variants.nll.stderr b/src/test/ui/span/dropck_misc_variants.nll.stderr
new file mode 100644
index 0000000..76e9057
--- /dev/null
+++ b/src/test/ui/span/dropck_misc_variants.nll.stderr
@@ -0,0 +1,30 @@
+error[E0597]: `bomb` does not live long enough
+  --> $DIR/dropck_misc_variants.rs:23:36
+   |
+LL |     _w = Wrap::<&[&str]>(NoisyDrop(&bomb));
+   |                                    ^^^^^ borrowed value does not live long enough
+LL | }
+   | -
+   | |
+   | `bomb` dropped here while still borrowed
+   | borrow might be used here, when `_w` is dropped and runs the destructor for type `Wrap<&[&str]>`
+   |
+   = note: values in a scope are dropped in the opposite order they are defined
+
+error[E0597]: `v` does not live long enough
+  --> $DIR/dropck_misc_variants.rs:31:27
+   |
+LL |         let u = NoisyDrop(&v);
+   |                           ^^ borrowed value does not live long enough
+...
+LL | }
+   | -
+   | |
+   | `v` dropped here while still borrowed
+   | borrow might be used here, when `_w` is dropped and runs the destructor for closure
+   |
+   = note: values in a scope are dropped in the opposite order they are defined
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/dropck_misc_variants.rs b/src/test/ui/span/dropck_misc_variants.rs
new file mode 100644
index 0000000..5818a94
--- /dev/null
+++ b/src/test/ui/span/dropck_misc_variants.rs
@@ -0,0 +1,37 @@
+// check that dropck does the right thing with misc. Ty variants
+
+use std::fmt;
+struct NoisyDrop<T: fmt::Debug>(T);
+impl<T: fmt::Debug> Drop for NoisyDrop<T> {
+    fn drop(&mut self) {
+        let _ = vec!["0wned"];
+        println!("dropping {:?}", self.0)
+    }
+}
+
+trait Associator {
+    type As;
+}
+impl<T: fmt::Debug> Associator for T {
+    type As = NoisyDrop<T>;
+}
+struct Wrap<A: Associator>(<A as Associator>::As);
+
+fn projection() {
+    let (_w, bomb);
+    bomb = vec![""];
+    _w = Wrap::<&[&str]>(NoisyDrop(&bomb));
+}
+//~^^ ERROR `bomb` does not live long enough
+
+fn closure() {
+    let (_w,v);
+    v = vec![""];
+    _w = {
+        let u = NoisyDrop(&v);
+        //~^ ERROR `v` does not live long enough
+        move || u.0.len()
+    };
+}
+
+fn main() { closure(); projection() }
diff --git a/src/test/ui/span/dropck_misc_variants.stderr b/src/test/ui/span/dropck_misc_variants.stderr
new file mode 100644
index 0000000..b2de455
--- /dev/null
+++ b/src/test/ui/span/dropck_misc_variants.stderr
@@ -0,0 +1,24 @@
+error[E0597]: `bomb` does not live long enough
+  --> $DIR/dropck_misc_variants.rs:23:37
+   |
+LL |     _w = Wrap::<&[&str]>(NoisyDrop(&bomb));
+   |                                     ^^^^ borrowed value does not live long enough
+LL | }
+   | - `bomb` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error[E0597]: `v` does not live long enough
+  --> $DIR/dropck_misc_variants.rs:31:28
+   |
+LL |         let u = NoisyDrop(&v);
+   |                            ^ borrowed value does not live long enough
+...
+LL | }
+   | - `v` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/dropck_vec_cycle_checked.nll.stderr b/src/test/ui/span/dropck_vec_cycle_checked.nll.stderr
new file mode 100644
index 0000000..0569251
--- /dev/null
+++ b/src/test/ui/span/dropck_vec_cycle_checked.nll.stderr
@@ -0,0 +1,43 @@
+error[E0597]: `c2` does not live long enough
+  --> $DIR/dropck_vec_cycle_checked.rs:98:24
+   |
+LL |     c1.v[0].v.set(Some(&c2));
+   |                        ^^^ borrowed value does not live long enough
+...
+LL | }
+   | -
+   | |
+   | `c2` dropped here while still borrowed
+   | borrow might be used here, when `c1` is dropped and runs the destructor for type `C<'_>`
+   |
+   = note: values in a scope are dropped in the opposite order they are defined
+
+error[E0597]: `c3` does not live long enough
+  --> $DIR/dropck_vec_cycle_checked.rs:100:24
+   |
+LL |     c1.v[1].v.set(Some(&c3));
+   |                        ^^^ borrowed value does not live long enough
+...
+LL | }
+   | -
+   | |
+   | `c3` dropped here while still borrowed
+   | borrow might be used here, when `c1` is dropped and runs the destructor for type `C<'_>`
+   |
+   = note: values in a scope are dropped in the opposite order they are defined
+
+error[E0597]: `c1` does not live long enough
+  --> $DIR/dropck_vec_cycle_checked.rs:106:24
+   |
+LL |     c3.v[0].v.set(Some(&c1));
+   |                        ^^^ borrowed value does not live long enough
+...
+LL | }
+   | -
+   | |
+   | `c1` dropped here while still borrowed
+   | borrow might be used here, when `c1` is dropped and runs the destructor for type `C<'_>`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/dropck_vec_cycle_checked.rs b/src/test/ui/span/dropck_vec_cycle_checked.rs
new file mode 100644
index 0000000..c80e038
--- /dev/null
+++ b/src/test/ui/span/dropck_vec_cycle_checked.rs
@@ -0,0 +1,114 @@
+// Reject mixing cyclic structure and Drop when using Vec.
+//
+// (Compare against compile-fail/dropck_arr_cycle_checked.rs)
+
+use std::cell::Cell;
+use id::Id;
+
+mod s {
+    use std::sync::atomic::{AtomicUsize, Ordering};
+
+    static S_COUNT: AtomicUsize = AtomicUsize::new(0);
+
+    pub fn next_count() -> usize {
+        S_COUNT.fetch_add(1, Ordering::SeqCst) + 1
+    }
+}
+
+mod id {
+    use s;
+    #[derive(Debug)]
+    pub struct Id {
+        orig_count: usize,
+        count: usize,
+    }
+
+    impl Id {
+        pub fn new() -> Id {
+            let c = s::next_count();
+            println!("building Id {}", c);
+            Id { orig_count: c, count: c }
+        }
+        pub fn count(&self) -> usize {
+            println!("Id::count on {} returns {}", self.orig_count, self.count);
+            self.count
+        }
+    }
+
+    impl Drop for Id {
+        fn drop(&mut self) {
+            println!("dropping Id {}", self.count);
+            self.count = 0;
+        }
+    }
+}
+
+trait HasId {
+    fn count(&self) -> usize;
+}
+
+#[derive(Debug)]
+struct CheckId<T:HasId> {
+    v: T
+}
+
+#[allow(non_snake_case)]
+fn CheckId<T:HasId>(t: T) -> CheckId<T> { CheckId{ v: t } }
+
+impl<T:HasId> Drop for CheckId<T> {
+    fn drop(&mut self) {
+        assert!(self.v.count() > 0);
+    }
+}
+
+#[derive(Debug)]
+struct C<'a> {
+    id: Id,
+    v: Vec<CheckId<Cell<Option<&'a C<'a>>>>>,
+}
+
+impl<'a> HasId for Cell<Option<&'a C<'a>>> {
+    fn count(&self) -> usize {
+        match self.get() {
+            None => 1,
+            Some(c) => c.id.count(),
+        }
+    }
+}
+
+impl<'a> C<'a> {
+    fn new() -> C<'a> {
+        C { id: Id::new(), v: Vec::new() }
+    }
+}
+
+fn f() {
+    let (mut c1, mut c2, mut c3);
+    c1 = C::new();
+    c2 = C::new();
+    c3 = C::new();
+
+    c1.v.push(CheckId(Cell::new(None)));
+    c1.v.push(CheckId(Cell::new(None)));
+    c2.v.push(CheckId(Cell::new(None)));
+    c2.v.push(CheckId(Cell::new(None)));
+    c3.v.push(CheckId(Cell::new(None)));
+    c3.v.push(CheckId(Cell::new(None)));
+
+    c1.v[0].v.set(Some(&c2));
+    //~^ ERROR `c2` does not live long enough
+    c1.v[1].v.set(Some(&c3));
+    //~^ ERROR `c3` does not live long enough
+    c2.v[0].v.set(Some(&c2));
+    //~^ ERROR `c2` does not live long enough
+    c2.v[1].v.set(Some(&c3));
+    //~^ ERROR `c3` does not live long enough
+    c3.v[0].v.set(Some(&c1));
+    //~^ ERROR `c1` does not live long enough
+    c3.v[1].v.set(Some(&c2));
+    //~^ ERROR `c2` does not live long enough
+}
+
+fn main() {
+    f();
+}
diff --git a/src/test/ui/span/dropck_vec_cycle_checked.stderr b/src/test/ui/span/dropck_vec_cycle_checked.stderr
new file mode 100644
index 0000000..7f90238
--- /dev/null
+++ b/src/test/ui/span/dropck_vec_cycle_checked.stderr
@@ -0,0 +1,69 @@
+error[E0597]: `c2` does not live long enough
+  --> $DIR/dropck_vec_cycle_checked.rs:98:25
+   |
+LL |     c1.v[0].v.set(Some(&c2));
+   |                         ^^ borrowed value does not live long enough
+...
+LL | }
+   | - `c2` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error[E0597]: `c3` does not live long enough
+  --> $DIR/dropck_vec_cycle_checked.rs:100:25
+   |
+LL |     c1.v[1].v.set(Some(&c3));
+   |                         ^^ borrowed value does not live long enough
+...
+LL | }
+   | - `c3` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error[E0597]: `c2` does not live long enough
+  --> $DIR/dropck_vec_cycle_checked.rs:102:25
+   |
+LL |     c2.v[0].v.set(Some(&c2));
+   |                         ^^ borrowed value does not live long enough
+...
+LL | }
+   | - `c2` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error[E0597]: `c3` does not live long enough
+  --> $DIR/dropck_vec_cycle_checked.rs:104:25
+   |
+LL |     c2.v[1].v.set(Some(&c3));
+   |                         ^^ borrowed value does not live long enough
+...
+LL | }
+   | - `c3` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error[E0597]: `c1` does not live long enough
+  --> $DIR/dropck_vec_cycle_checked.rs:106:25
+   |
+LL |     c3.v[0].v.set(Some(&c1));
+   |                         ^^ borrowed value does not live long enough
+...
+LL | }
+   | - `c1` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error[E0597]: `c2` does not live long enough
+  --> $DIR/dropck_vec_cycle_checked.rs:108:25
+   |
+LL |     c3.v[1].v.set(Some(&c2));
+   |                         ^^ borrowed value does not live long enough
+LL |
+LL | }
+   | - `c2` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/gated-features-attr-spans.rs b/src/test/ui/span/gated-features-attr-spans.rs
new file mode 100644
index 0000000..69511ab
--- /dev/null
+++ b/src/test/ui/span/gated-features-attr-spans.rs
@@ -0,0 +1,7 @@
+#[repr(simd)] //~ ERROR are experimental
+struct Coord {
+    x: u32,
+    y: u32,
+}
+
+fn main() {}
diff --git a/src/test/ui/span/gated-features-attr-spans.stderr b/src/test/ui/span/gated-features-attr-spans.stderr
new file mode 100644
index 0000000..45d14f3
--- /dev/null
+++ b/src/test/ui/span/gated-features-attr-spans.stderr
@@ -0,0 +1,11 @@
+error[E0658]: SIMD types are experimental and possibly buggy (see issue #27731)
+  --> $DIR/gated-features-attr-spans.rs:1:1
+   |
+LL | #[repr(simd)]
+   | ^^^^^^^^^^^^^
+   |
+   = help: add #![feature(repr_simd)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/span/impl-wrong-item-for-trait.rs b/src/test/ui/span/impl-wrong-item-for-trait.rs
new file mode 100644
index 0000000..672fe8d
--- /dev/null
+++ b/src/test/ui/span/impl-wrong-item-for-trait.rs
@@ -0,0 +1,40 @@
+use std::fmt::Debug;
+
+trait Foo {
+    fn bar(&self);
+    const MY_CONST: u32;
+}
+
+pub struct FooConstForMethod;
+
+impl Foo for FooConstForMethod {
+    //~^ ERROR E0046
+    const bar: u64 = 1;
+    //~^ ERROR E0323
+    const MY_CONST: u32 = 1;
+}
+
+pub struct FooMethodForConst;
+
+impl Foo for FooMethodForConst {
+    //~^ ERROR E0046
+    fn bar(&self) {}
+    fn MY_CONST() {}
+    //~^ ERROR E0324
+}
+
+pub struct FooTypeForMethod;
+
+impl Foo for FooTypeForMethod {
+    //~^ ERROR E0046
+    type bar = u64;
+    //~^ ERROR E0325
+    //~| ERROR E0437
+    const MY_CONST: u32 = 1;
+}
+
+impl Debug for FooTypeForMethod {
+}
+//~^^ ERROR E0046
+
+fn main () {}
diff --git a/src/test/ui/span/impl-wrong-item-for-trait.stderr b/src/test/ui/span/impl-wrong-item-for-trait.stderr
new file mode 100644
index 0000000..8e08d36
--- /dev/null
+++ b/src/test/ui/span/impl-wrong-item-for-trait.stderr
@@ -0,0 +1,72 @@
+error[E0437]: type `bar` is not a member of trait `Foo`
+  --> $DIR/impl-wrong-item-for-trait.rs:30:5
+   |
+LL |     type bar = u64;
+   |     ^^^^^^^^^^^^^^^ not a member of trait `Foo`
+
+error[E0323]: item `bar` is an associated const, which doesn't match its trait `Foo`
+  --> $DIR/impl-wrong-item-for-trait.rs:12:5
+   |
+LL |     fn bar(&self);
+   |     -------------- item in trait
+...
+LL |     const bar: u64 = 1;
+   |     ^^^^^^^^^^^^^^^^^^^ does not match trait
+
+error[E0046]: not all trait items implemented, missing: `bar`
+  --> $DIR/impl-wrong-item-for-trait.rs:10:1
+   |
+LL |     fn bar(&self);
+   |     -------------- `bar` from trait
+...
+LL | impl Foo for FooConstForMethod {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `bar` in implementation
+
+error[E0324]: item `MY_CONST` is an associated method, which doesn't match its trait `Foo`
+  --> $DIR/impl-wrong-item-for-trait.rs:22:5
+   |
+LL |     const MY_CONST: u32;
+   |     -------------------- item in trait
+...
+LL |     fn MY_CONST() {}
+   |     ^^^^^^^^^^^^^^^^ does not match trait
+
+error[E0046]: not all trait items implemented, missing: `MY_CONST`
+  --> $DIR/impl-wrong-item-for-trait.rs:19:1
+   |
+LL |     const MY_CONST: u32;
+   |     -------------------- `MY_CONST` from trait
+...
+LL | impl Foo for FooMethodForConst {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `MY_CONST` in implementation
+
+error[E0325]: item `bar` is an associated type, which doesn't match its trait `Foo`
+  --> $DIR/impl-wrong-item-for-trait.rs:30:5
+   |
+LL |     fn bar(&self);
+   |     -------------- item in trait
+...
+LL |     type bar = u64;
+   |     ^^^^^^^^^^^^^^^ does not match trait
+
+error[E0046]: not all trait items implemented, missing: `bar`
+  --> $DIR/impl-wrong-item-for-trait.rs:28:1
+   |
+LL |     fn bar(&self);
+   |     -------------- `bar` from trait
+...
+LL | impl Foo for FooTypeForMethod {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `bar` in implementation
+
+error[E0046]: not all trait items implemented, missing: `fmt`
+  --> $DIR/impl-wrong-item-for-trait.rs:36:1
+   |
+LL | impl Debug for FooTypeForMethod {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `fmt` in implementation
+   |
+   = note: `fmt` from trait: `fn(&Self, &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error>`
+
+error: aborting due to 8 previous errors
+
+Some errors occurred: E0046, E0323, E0324, E0325, E0437.
+For more information about an error, try `rustc --explain E0046`.
diff --git a/src/test/ui/span/import-ty-params.rs b/src/test/ui/span/import-ty-params.rs
new file mode 100644
index 0000000..850bbd8
--- /dev/null
+++ b/src/test/ui/span/import-ty-params.rs
@@ -0,0 +1,20 @@
+mod a {
+    pub mod b {
+        pub mod c {
+            pub struct S<T>(T);
+        }
+    }
+}
+
+macro_rules! import {
+    ($p: path) => (use $p;);
+}
+
+fn f1() {
+    import! { a::b::c::S<u8> } //~ ERROR unexpected generic arguments in path
+}
+fn f2() {
+    import! { a::b::c::S<> } //~ ERROR unexpected generic arguments in path
+}
+
+fn main() {}
diff --git a/src/test/ui/span/import-ty-params.stderr b/src/test/ui/span/import-ty-params.stderr
new file mode 100644
index 0000000..a02a1ed
--- /dev/null
+++ b/src/test/ui/span/import-ty-params.stderr
@@ -0,0 +1,14 @@
+error: unexpected generic arguments in path
+  --> $DIR/import-ty-params.rs:14:15
+   |
+LL |     import! { a::b::c::S<u8> }
+   |               ^^^^^^^^^^^^^^
+
+error: unexpected generic arguments in path
+  --> $DIR/import-ty-params.rs:17:15
+   |
+LL |     import! { a::b::c::S<> }
+   |               ^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/span/issue-11925.nll.stderr b/src/test/ui/span/issue-11925.nll.stderr
new file mode 100644
index 0000000..1d317fc
--- /dev/null
+++ b/src/test/ui/span/issue-11925.nll.stderr
@@ -0,0 +1,9 @@
+error[E0515]: cannot return reference to local data `x`
+  --> $DIR/issue-11925.rs:8:35
+   |
+LL |         let f = to_fn_once(move|| &x);
+   |                                   ^^ returns a reference to data owned by the current function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/src/test/ui/span/issue-11925.rs b/src/test/ui/span/issue-11925.rs
new file mode 100644
index 0000000..276aaa1
--- /dev/null
+++ b/src/test/ui/span/issue-11925.rs
@@ -0,0 +1,13 @@
+#![feature(box_syntax, unboxed_closures)]
+
+fn to_fn_once<A,F:FnOnce<A>>(f: F) -> F { f }
+
+fn main() {
+    let r = {
+        let x: Box<_> = box 42;
+        let f = to_fn_once(move|| &x); //~ ERROR does not live long enough
+        f()
+    };
+
+    drop(r);
+}
diff --git a/src/test/ui/span/issue-11925.stderr b/src/test/ui/span/issue-11925.stderr
new file mode 100644
index 0000000..c750222
--- /dev/null
+++ b/src/test/ui/span/issue-11925.stderr
@@ -0,0 +1,15 @@
+error[E0597]: `x` does not live long enough
+  --> $DIR/issue-11925.rs:8:36
+   |
+LL |         let f = to_fn_once(move|| &x);
+   |                                    ^
+   |                                    |
+   |                                    borrowed value does not live long enough
+   |                                    `x` dropped here while still borrowed
+...
+LL | }
+   | - borrowed value needs to live until here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/issue-15480.nll.stderr b/src/test/ui/span/issue-15480.nll.stderr
new file mode 100644
index 0000000..23ee225
--- /dev/null
+++ b/src/test/ui/span/issue-15480.nll.stderr
@@ -0,0 +1,16 @@
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/issue-15480.rs:5:10
+   |
+LL |         &id(3)
+   |          ^^^^^ creates a temporary which is freed while still in use
+LL |     ];
+   |      - temporary value is freed at the end of this statement
+...
+LL |     for &&x in &v {
+   |                -- borrow later used here
+   |
+   = note: consider using a `let` binding to create a longer lived value
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/src/test/ui/span/issue-15480.rs b/src/test/ui/span/issue-15480.rs
new file mode 100644
index 0000000..c102423
--- /dev/null
+++ b/src/test/ui/span/issue-15480.rs
@@ -0,0 +1,12 @@
+fn id<T>(x: T) -> T { x }
+
+fn main() {
+    let v = vec![
+        &id(3)
+    ];
+    //~^^ ERROR borrowed value does not live long enough
+
+    for &&x in &v {
+        println!("{}", x + 3);
+    }
+}
diff --git a/src/test/ui/span/issue-15480.stderr b/src/test/ui/span/issue-15480.stderr
new file mode 100644
index 0000000..c5e3899
--- /dev/null
+++ b/src/test/ui/span/issue-15480.stderr
@@ -0,0 +1,16 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/issue-15480.rs:5:10
+   |
+LL |         &id(3)
+   |          ^^^^^ temporary value does not live long enough
+LL |     ];
+   |      - temporary value dropped here while still borrowed
+...
+LL | }
+   | - temporary value needs to live until here
+   |
+   = note: consider using a `let` binding to increase its lifetime
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.nll.stderr b/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.nll.stderr
new file mode 100644
index 0000000..4696945
--- /dev/null
+++ b/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.nll.stderr
@@ -0,0 +1,34 @@
+error[E0597]: `y` does not live long enough
+  --> $DIR/issue-23338-locals-die-before-temps-of-body.rs:10:5
+   |
+LL |     y.borrow().clone()
+   |     ^---------
+   |     |
+   |     borrowed value does not live long enough
+   |     a temporary with access to the borrow is created here ...
+LL | }
+   | -
+   | |
+   | `y` dropped here while still borrowed
+   | ... and the borrow might be used here, when that temporary is dropped and runs the destructor for type `std::cell::Ref<'_, std::string::String>`
+   |
+   = note: The temporary is part of an expression at the end of a block. Consider forcing this temporary to be dropped sooner, before the block's local variables are dropped. For example, you could save the expression's value in a new local variable `x` and then make `x` be the expression at the end of the block.
+
+error[E0597]: `y` does not live long enough
+  --> $DIR/issue-23338-locals-die-before-temps-of-body.rs:17:9
+   |
+LL |         y.borrow().clone()
+   |         ^---------
+   |         |
+   |         borrowed value does not live long enough
+   |         a temporary with access to the borrow is created here ...
+LL |     };
+   |     -- ... and the borrow might be used here, when that temporary is dropped and runs the destructor for type `std::cell::Ref<'_, std::string::String>`
+   |     |
+   |     `y` dropped here while still borrowed
+   |
+   = note: The temporary is part of an expression at the end of a block. Consider forcing this temporary to be dropped sooner, before the block's local variables are dropped. For example, you could save the expression's value in a new local variable `x` and then make `x` be the expression at the end of the block.
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.rs b/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.rs
new file mode 100644
index 0000000..a92ea4d
--- /dev/null
+++ b/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.rs
@@ -0,0 +1,28 @@
+// This is just checking that we still reject code where temp values
+// are borrowing values for longer than they will be around.
+//
+// Compare to run-pass/issue-23338-params-outlive-temps-of-body.rs
+
+use std::cell::RefCell;
+
+fn foo(x: RefCell<String>) -> String {
+    let y = x;
+    y.borrow().clone()
+}
+//~^^ ERROR `y` does not live long enough
+
+fn foo2(x: RefCell<String>) -> String {
+    let ret = {
+        let y = x;
+        y.borrow().clone()
+    };
+    //~^^ ERROR `y` does not live long enough
+    ret
+}
+
+fn main() {
+    let r = RefCell::new(format!("data"));
+    assert_eq!(foo(r), "data");
+    let r = RefCell::new(format!("data"));
+    assert_eq!(foo2(r), "data");
+}
diff --git a/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.stderr b/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.stderr
new file mode 100644
index 0000000..f18f0da
--- /dev/null
+++ b/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.stderr
@@ -0,0 +1,23 @@
+error[E0597]: `y` does not live long enough
+  --> $DIR/issue-23338-locals-die-before-temps-of-body.rs:10:5
+   |
+LL |     y.borrow().clone()
+   |     ^ borrowed value does not live long enough
+LL | }
+   | - `y` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error[E0597]: `y` does not live long enough
+  --> $DIR/issue-23338-locals-die-before-temps-of-body.rs:17:9
+   |
+LL |         y.borrow().clone()
+   |         ^ borrowed value does not live long enough
+LL |     };
+   |     -- borrowed value needs to live until here
+   |     |
+   |     `y` dropped here while still borrowed
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/issue-23729.rs b/src/test/ui/span/issue-23729.rs
new file mode 100644
index 0000000..ca33f9c
--- /dev/null
+++ b/src/test/ui/span/issue-23729.rs
@@ -0,0 +1,33 @@
+// Regression test for #23729
+
+fn main() {
+    let fib = {
+        struct Recurrence {
+            mem: [u64; 2],
+            pos: usize,
+        }
+
+        impl Iterator for Recurrence {
+            //~^ ERROR E0046
+            #[inline]
+            fn next(&mut self) -> Option<u64> {
+                if self.pos < 2 {
+                    let next_val = self.mem[self.pos];
+                    self.pos += 1;
+                    Some(next_val)
+                } else {
+                    let next_val = self.mem[0] + self.mem[1];
+                    self.mem[0] = self.mem[1];
+                    self.mem[1] = next_val;
+                    Some(next_val)
+                }
+            }
+        }
+
+        Recurrence { mem: [0, 1], pos: 0 }
+    };
+
+    for e in fib.take(10) {
+        println!("{}", e)
+    }
+}
diff --git a/src/test/ui/span/issue-23729.stderr b/src/test/ui/span/issue-23729.stderr
new file mode 100644
index 0000000..865fae9
--- /dev/null
+++ b/src/test/ui/span/issue-23729.stderr
@@ -0,0 +1,11 @@
+error[E0046]: not all trait items implemented, missing: `Item`
+  --> $DIR/issue-23729.rs:10:9
+   |
+LL |         impl Iterator for Recurrence {
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `Item` in implementation
+   |
+   = note: `Item` from trait: `type Item;`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0046`.
diff --git a/src/test/ui/span/issue-23827.rs b/src/test/ui/span/issue-23827.rs
new file mode 100644
index 0000000..22b9dde
--- /dev/null
+++ b/src/test/ui/span/issue-23827.rs
@@ -0,0 +1,33 @@
+// Regression test for #23827
+
+#![feature(core, fn_traits, unboxed_closures)]
+
+pub struct Prototype {
+    pub target: u32
+}
+
+trait Component {
+    fn apply(self, e: u32);
+}
+
+impl<C: Component> Fn<(C,)> for Prototype {
+    extern "rust-call" fn call(&self, (comp,): (C,)) -> Prototype {
+        comp.apply(self.target);
+        *self
+    }
+}
+
+impl<C: Component> FnMut<(C,)> for Prototype {
+    extern "rust-call" fn call_mut(&mut self, (comp,): (C,)) -> Prototype {
+        Fn::call(*&self, (comp,))
+    }
+}
+
+impl<C: Component> FnOnce<(C,)> for Prototype {
+    //~^ ERROR E0046
+    extern "rust-call" fn call_once(self, (comp,): (C,)) -> Prototype {
+        Fn::call(&self, (comp,))
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/span/issue-23827.stderr b/src/test/ui/span/issue-23827.stderr
new file mode 100644
index 0000000..a8e3e9b
--- /dev/null
+++ b/src/test/ui/span/issue-23827.stderr
@@ -0,0 +1,11 @@
+error[E0046]: not all trait items implemented, missing: `Output`
+  --> $DIR/issue-23827.rs:26:1
+   |
+LL | impl<C: Component> FnOnce<(C,)> for Prototype {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `Output` in implementation
+   |
+   = note: `Output` from trait: `type Output;`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0046`.
diff --git a/src/test/ui/span/issue-24356.rs b/src/test/ui/span/issue-24356.rs
new file mode 100644
index 0000000..7696bd5
--- /dev/null
+++ b/src/test/ui/span/issue-24356.rs
@@ -0,0 +1,29 @@
+// Regression test for #24356
+
+// ignore-tidy-linelength
+
+fn main() {
+    {
+        use std::ops::Deref;
+
+        struct Thing(i8);
+
+        /*
+        // Correct impl
+        impl Deref for Thing {
+            type Target = i8;
+            fn deref(&self) -> &i8 { &self.0 }
+        }
+        */
+
+        // Causes ICE
+        impl Deref for Thing {
+            //~^ ERROR E0046
+            fn deref(&self) -> i8 { self.0 }
+        }
+
+        let thing = Thing(72);
+
+        *thing
+    };
+}
diff --git a/src/test/ui/span/issue-24356.stderr b/src/test/ui/span/issue-24356.stderr
new file mode 100644
index 0000000..102cc42
--- /dev/null
+++ b/src/test/ui/span/issue-24356.stderr
@@ -0,0 +1,11 @@
+error[E0046]: not all trait items implemented, missing: `Target`
+  --> $DIR/issue-24356.rs:20:9
+   |
+LL |         impl Deref for Thing {
+   |         ^^^^^^^^^^^^^^^^^^^^ missing `Target` in implementation
+   |
+   = note: `Target` from trait: `type Target;`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0046`.
diff --git a/src/test/ui/span/issue-24690.rs b/src/test/ui/span/issue-24690.rs
new file mode 100644
index 0000000..82899fc
--- /dev/null
+++ b/src/test/ui/span/issue-24690.rs
@@ -0,0 +1,16 @@
+//! A test to ensure that helpful `note` messages aren't emitted more often
+//! than necessary.
+
+// compile-pass
+
+// Although there are three warnings, we should only get two "lint level defined
+// here" notes pointing at the `warnings` span, one for each error type.
+#![warn(unused)]
+
+
+fn main() {
+    let theTwo = 2; //~ WARN should have a snake case name
+    let theOtherTwo = 2; //~ WARN should have a snake case name
+    //~^ WARN unused variable
+    println!("{}", theTwo);
+}
diff --git a/src/test/ui/span/issue-24690.stderr b/src/test/ui/span/issue-24690.stderr
new file mode 100644
index 0000000..0864497
--- /dev/null
+++ b/src/test/ui/span/issue-24690.stderr
@@ -0,0 +1,27 @@
+warning: unused variable: `theOtherTwo`
+  --> $DIR/issue-24690.rs:13:9
+   |
+LL |     let theOtherTwo = 2;
+   |         ^^^^^^^^^^^ help: consider prefixing with an underscore: `_theOtherTwo`
+   |
+note: lint level defined here
+  --> $DIR/issue-24690.rs:8:9
+   |
+LL | #![warn(unused)]
+   |         ^^^^^^
+   = note: #[warn(unused_variables)] implied by #[warn(unused)]
+
+warning: variable `theTwo` should have a snake case name
+  --> $DIR/issue-24690.rs:12:9
+   |
+LL |     let theTwo = 2;
+   |         ^^^^^^ help: convert the identifier to snake case: `the_two`
+   |
+   = note: #[warn(non_snake_case)] on by default
+
+warning: variable `theOtherTwo` should have a snake case name
+  --> $DIR/issue-24690.rs:13:9
+   |
+LL |     let theOtherTwo = 2;
+   |         ^^^^^^^^^^^ help: convert the identifier to snake case: `the_other_two`
+
diff --git a/src/test/ui/span/issue-24805-dropck-child-has-items-via-parent.nll.stderr b/src/test/ui/span/issue-24805-dropck-child-has-items-via-parent.nll.stderr
new file mode 100644
index 0000000..809e60a
--- /dev/null
+++ b/src/test/ui/span/issue-24805-dropck-child-has-items-via-parent.nll.stderr
@@ -0,0 +1,17 @@
+error[E0597]: `d1` does not live long enough
+  --> $DIR/issue-24805-dropck-child-has-items-via-parent.rs:28:18
+   |
+LL |     _d = D_Child(&d1);
+   |                  ^^^ borrowed value does not live long enough
+...
+LL | }
+   | -
+   | |
+   | `d1` dropped here while still borrowed
+   | borrow might be used here, when `_d` is dropped and runs the `Drop` code for type `D_Child`
+   |
+   = note: values in a scope are dropped in the opposite order they are defined
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/issue-24805-dropck-child-has-items-via-parent.rs b/src/test/ui/span/issue-24805-dropck-child-has-items-via-parent.rs
new file mode 100644
index 0000000..9c77205
--- /dev/null
+++ b/src/test/ui/span/issue-24805-dropck-child-has-items-via-parent.rs
@@ -0,0 +1,37 @@
+// Check that child trait who only has items via its *parent* trait
+// does cause dropck to inject extra region constraints.
+
+#![allow(non_camel_case_types)]
+
+trait Parent { fn foo(&self); }
+trait Child: Parent { }
+
+impl Parent for i32 { fn foo(&self) { } }
+impl<'a> Parent for &'a D_Child<i32> {
+    fn foo(&self) {
+        println!("accessing child value: {}", self.0);
+    }
+}
+
+impl Child for i32 { }
+impl<'a> Child for &'a D_Child<i32> { }
+
+struct D_Child<T:Child>(T);
+impl <T:Child> Drop for D_Child<T> { fn drop(&mut self) { self.0.foo() } }
+
+fn f_child() {
+    // `_d` and `d1` are assigned the *same* lifetime by region inference ...
+    let (_d, d1);
+
+    d1 = D_Child(1);
+    // ... we store a reference to `d1` within `_d` ...
+    _d = D_Child(&d1);
+    //~^ ERROR `d1` does not live long enough
+
+    // ... dropck *should* complain, because Drop of _d could (and
+    // does) access the already dropped `d1` via the `foo` method.
+}
+
+fn main() {
+    f_child();
+}
diff --git a/src/test/ui/span/issue-24805-dropck-child-has-items-via-parent.stderr b/src/test/ui/span/issue-24805-dropck-child-has-items-via-parent.stderr
new file mode 100644
index 0000000..ad90fcd
--- /dev/null
+++ b/src/test/ui/span/issue-24805-dropck-child-has-items-via-parent.stderr
@@ -0,0 +1,14 @@
+error[E0597]: `d1` does not live long enough
+  --> $DIR/issue-24805-dropck-child-has-items-via-parent.rs:28:19
+   |
+LL |     _d = D_Child(&d1);
+   |                   ^^ borrowed value does not live long enough
+...
+LL | }
+   | - `d1` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/issue-24805-dropck-trait-has-items.nll.stderr b/src/test/ui/span/issue-24805-dropck-trait-has-items.nll.stderr
new file mode 100644
index 0000000..2e21706
--- /dev/null
+++ b/src/test/ui/span/issue-24805-dropck-trait-has-items.nll.stderr
@@ -0,0 +1,42 @@
+error[E0597]: `d1` does not live long enough
+  --> $DIR/issue-24805-dropck-trait-has-items.rs:37:26
+   |
+LL |     _d = D_HasSelfMethod(&d1);
+   |                          ^^^ borrowed value does not live long enough
+LL | }
+   | -
+   | |
+   | `d1` dropped here while still borrowed
+   | borrow might be used here, when `_d` is dropped and runs the `Drop` code for type `D_HasSelfMethod`
+   |
+   = note: values in a scope are dropped in the opposite order they are defined
+
+error[E0597]: `d1` does not live long enough
+  --> $DIR/issue-24805-dropck-trait-has-items.rs:43:33
+   |
+LL |     _d = D_HasMethodWithSelfArg(&d1);
+   |                                 ^^^ borrowed value does not live long enough
+LL | }
+   | -
+   | |
+   | `d1` dropped here while still borrowed
+   | borrow might be used here, when `_d` is dropped and runs the `Drop` code for type `D_HasMethodWithSelfArg`
+   |
+   = note: values in a scope are dropped in the opposite order they are defined
+
+error[E0597]: `d1` does not live long enough
+  --> $DIR/issue-24805-dropck-trait-has-items.rs:49:20
+   |
+LL |     _d = D_HasType(&d1);
+   |                    ^^^ borrowed value does not live long enough
+LL | }
+   | -
+   | |
+   | `d1` dropped here while still borrowed
+   | borrow might be used here, when `_d` is dropped and runs the `Drop` code for type `D_HasType`
+   |
+   = note: values in a scope are dropped in the opposite order they are defined
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/issue-24805-dropck-trait-has-items.rs b/src/test/ui/span/issue-24805-dropck-trait-has-items.rs
new file mode 100644
index 0000000..b5c410c
--- /dev/null
+++ b/src/test/ui/span/issue-24805-dropck-trait-has-items.rs
@@ -0,0 +1,57 @@
+// Check that traits with various kinds of associated items cause
+// dropck to inject extra region constraints.
+
+#![allow(non_camel_case_types)]
+
+trait HasSelfMethod { fn m1(&self) { } }
+trait HasMethodWithSelfArg { fn m2(x: &Self) { } }
+trait HasType { type Something; }
+
+impl HasSelfMethod for i32 { }
+impl HasMethodWithSelfArg for i32 { }
+impl HasType for i32 { type Something = (); }
+
+impl<'a,T> HasSelfMethod for &'a T { }
+impl<'a,T> HasMethodWithSelfArg for &'a T { }
+impl<'a,T> HasType for &'a T { type Something = (); }
+
+// e.g., `impl_drop!(Send, D_Send)` expands to:
+//   ```rust
+//   struct D_Send<T:Send>(T);
+//   impl<T:Send> Drop for D_Send<T> { fn drop(&mut self) { } }
+//   ```
+macro_rules! impl_drop {
+    ($Bound:ident, $Id:ident) => {
+        struct $Id<T:$Bound>(T);
+        impl <T:$Bound> Drop for $Id<T> { fn drop(&mut self) { } }
+    }
+}
+
+impl_drop!{HasSelfMethod,        D_HasSelfMethod}
+impl_drop!{HasMethodWithSelfArg, D_HasMethodWithSelfArg}
+impl_drop!{HasType,              D_HasType}
+
+fn f_sm() {
+    let (_d, d1);
+    d1 = D_HasSelfMethod(1);
+    _d = D_HasSelfMethod(&d1);
+}
+//~^^ ERROR `d1` does not live long enough
+fn f_mwsa() {
+    let (_d, d1);
+    d1 = D_HasMethodWithSelfArg(1);
+    _d = D_HasMethodWithSelfArg(&d1);
+}
+//~^^ ERROR `d1` does not live long enough
+fn f_t() {
+    let (_d, d1);
+    d1 = D_HasType(1);
+    _d = D_HasType(&d1);
+}
+//~^^ ERROR `d1` does not live long enough
+
+fn main() {
+    f_sm();
+    f_mwsa();
+    f_t();
+}
diff --git a/src/test/ui/span/issue-24805-dropck-trait-has-items.stderr b/src/test/ui/span/issue-24805-dropck-trait-has-items.stderr
new file mode 100644
index 0000000..3de4014
--- /dev/null
+++ b/src/test/ui/span/issue-24805-dropck-trait-has-items.stderr
@@ -0,0 +1,33 @@
+error[E0597]: `d1` does not live long enough
+  --> $DIR/issue-24805-dropck-trait-has-items.rs:37:27
+   |
+LL |     _d = D_HasSelfMethod(&d1);
+   |                           ^^ borrowed value does not live long enough
+LL | }
+   | - `d1` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error[E0597]: `d1` does not live long enough
+  --> $DIR/issue-24805-dropck-trait-has-items.rs:43:34
+   |
+LL |     _d = D_HasMethodWithSelfArg(&d1);
+   |                                  ^^ borrowed value does not live long enough
+LL | }
+   | - `d1` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error[E0597]: `d1` does not live long enough
+  --> $DIR/issue-24805-dropck-trait-has-items.rs:49:21
+   |
+LL |     _d = D_HasType(&d1);
+   |                     ^^ borrowed value does not live long enough
+LL | }
+   | - `d1` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/issue-24895-copy-clone-dropck.nll.stderr b/src/test/ui/span/issue-24895-copy-clone-dropck.nll.stderr
new file mode 100644
index 0000000..18a3dc9
--- /dev/null
+++ b/src/test/ui/span/issue-24895-copy-clone-dropck.nll.stderr
@@ -0,0 +1,16 @@
+error[E0597]: `d1` does not live long enough
+  --> $DIR/issue-24895-copy-clone-dropck.rs:27:14
+   |
+LL |     d2 = D(S(&d1, "inner"), "d2");
+   |              ^^^ borrowed value does not live long enough
+LL | }
+   | -
+   | |
+   | `d1` dropped here while still borrowed
+   | borrow might be used here, when `d2` is dropped and runs the `Drop` code for type `D`
+   |
+   = note: values in a scope are dropped in the opposite order they are defined
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/issue-24895-copy-clone-dropck.rs b/src/test/ui/span/issue-24895-copy-clone-dropck.rs
new file mode 100644
index 0000000..904cd8f
--- /dev/null
+++ b/src/test/ui/span/issue-24895-copy-clone-dropck.rs
@@ -0,0 +1,29 @@
+// Check that one cannot subvert Drop Check rule via a user-defined
+// Clone implementation.
+
+#![allow(unused_variables, unused_assignments)]
+
+struct D<T:Copy>(T, &'static str);
+
+#[derive(Copy)]
+struct S<'a>(&'a D<i32>, &'static str);
+impl<'a> Clone for S<'a> {
+    fn clone(&self) -> S<'a> {
+        println!("cloning `S(_, {})` and thus accessing: {}", self.1, (self.0).0);
+        S(self.0, self.1)
+    }
+}
+
+impl<T:Copy> Drop for D<T> {
+    fn drop(&mut self) {
+        println!("calling Drop for {}", self.1);
+        let _call = self.0.clone();
+    }
+}
+
+fn main() {
+    let (d2, d1);
+    d1 = D(34, "d1");
+    d2 = D(S(&d1, "inner"), "d2");
+}
+//~^^ ERROR `d1` does not live long enough
diff --git a/src/test/ui/span/issue-24895-copy-clone-dropck.stderr b/src/test/ui/span/issue-24895-copy-clone-dropck.stderr
new file mode 100644
index 0000000..9185919
--- /dev/null
+++ b/src/test/ui/span/issue-24895-copy-clone-dropck.stderr
@@ -0,0 +1,13 @@
+error[E0597]: `d1` does not live long enough
+  --> $DIR/issue-24895-copy-clone-dropck.rs:27:15
+   |
+LL |     d2 = D(S(&d1, "inner"), "d2");
+   |               ^^ borrowed value does not live long enough
+LL | }
+   | - `d1` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/issue-25199.nll.stderr b/src/test/ui/span/issue-25199.nll.stderr
new file mode 100644
index 0000000..d70a4af
--- /dev/null
+++ b/src/test/ui/span/issue-25199.nll.stderr
@@ -0,0 +1,15 @@
+error[E0597]: `container` does not live long enough
+  --> $DIR/issue-25199.rs:70:27
+   |
+LL |     let test = Test{test: &container};
+   |                           ^^^^^^^^^^ borrowed value does not live long enough
+...
+LL | }
+   | -
+   | |
+   | `container` dropped here while still borrowed
+   | borrow might be used here, when `container` is dropped and runs the destructor for type `Container<'_>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/issue-25199.rs b/src/test/ui/span/issue-25199.rs
new file mode 100644
index 0000000..4ef5745
--- /dev/null
+++ b/src/test/ui/span/issue-25199.rs
@@ -0,0 +1,75 @@
+// Regression test for Issue 25199: Check that one cannot hide a
+// destructor's access to borrowed data behind a boxed trait object.
+//
+// Prior to fixing Issue 25199, this example was able to be compiled
+// with rustc, and thus when you ran it, you would see the `Drop` impl
+// for `Test` accessing state that had already been dropping (which is
+// marked explicitly here with checking code within the `Drop` impl
+// for `VecHolder`, but in the general case could just do unsound
+// things like accessing memory that has been freed).
+//
+// Note that I would have liked to encode my go-to example of cyclic
+// structure that accesses its neighbors in drop (and thus is
+// fundamentally unsound) via this trick, but the closest I was able
+// to come was dropck_trait_cycle_checked.rs, which is not quite as
+// "good" as this regression test because the encoding of that example
+// was forced to attach a lifetime to the trait definition itself
+// (`trait Obj<'a>`) while *this* example is solely
+
+use std::cell::RefCell;
+
+trait Obj { }
+
+struct VecHolder {
+    v: Vec<(bool, &'static str)>,
+}
+
+impl Drop for VecHolder {
+    fn drop(&mut self) {
+        println!("Dropping Vec");
+        self.v[30].0 = false;
+        self.v[30].1 = "invalid access: VecHolder dropped already";
+    }
+}
+
+struct Container<'a> {
+    v: VecHolder,
+    d: RefCell<Vec<Box<Obj+'a>>>,
+}
+
+impl<'a> Container<'a> {
+    fn new() -> Container<'a> {
+        Container {
+            d: RefCell::new(Vec::new()),
+            v: VecHolder {
+                v: vec![(true, "valid"); 100]
+            }
+        }
+    }
+
+    fn store<T: Obj+'a>(&'a self, val: T) {
+        self.d.borrow_mut().push(Box::new(val));
+    }
+}
+
+struct Test<'a> {
+    test: &'a Container<'a>,
+}
+
+impl<'a> Obj for Test<'a> { }
+impl<'a> Drop for Test<'a> {
+    fn drop(&mut self) {
+        for e in &self.test.v.v {
+            assert!(e.0, e.1);
+        }
+    }
+}
+
+fn main() {
+    let container = Container::new();
+    let test = Test{test: &container};
+    //~^ ERROR `container` does not live long enough
+    println!("container.v[30]: {:?}", container.v.v[30]);
+    container.store(test);
+    //~^ ERROR `container` does not live long enough
+}
diff --git a/src/test/ui/span/issue-25199.stderr b/src/test/ui/span/issue-25199.stderr
new file mode 100644
index 0000000..6d8320b
--- /dev/null
+++ b/src/test/ui/span/issue-25199.stderr
@@ -0,0 +1,25 @@
+error[E0597]: `container` does not live long enough
+  --> $DIR/issue-25199.rs:70:28
+   |
+LL |     let test = Test{test: &container};
+   |                            ^^^^^^^^^ borrowed value does not live long enough
+...
+LL | }
+   | - `container` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error[E0597]: `container` does not live long enough
+  --> $DIR/issue-25199.rs:73:5
+   |
+LL |     container.store(test);
+   |     ^^^^^^^^^ borrowed value does not live long enough
+LL |
+LL | }
+   | - `container` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/issue-26656.nll.stderr b/src/test/ui/span/issue-26656.nll.stderr
new file mode 100644
index 0000000..1e939c4
--- /dev/null
+++ b/src/test/ui/span/issue-26656.nll.stderr
@@ -0,0 +1,16 @@
+error[E0597]: `ticking` does not live long enough
+  --> $DIR/issue-26656.rs:40:35
+   |
+LL |     zook.button = B::BigRedButton(&ticking);
+   |                                   ^^^^^^^^ borrowed value does not live long enough
+LL | }
+   | -
+   | |
+   | `ticking` dropped here while still borrowed
+   | borrow might be used here, when `zook` is dropped and runs the `Drop` code for type `Zook`
+   |
+   = note: values in a scope are dropped in the opposite order they are defined
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/issue-26656.rs b/src/test/ui/span/issue-26656.rs
new file mode 100644
index 0000000..c5a70c8
--- /dev/null
+++ b/src/test/ui/span/issue-26656.rs
@@ -0,0 +1,42 @@
+// Issue #26656: Verify that trait objects cannot bypass dropck.
+
+// Using this instead of Fn etc. to take HRTB out of the equation.
+trait Trigger<B> { fn fire(&self, b: &mut B); }
+impl<B: Button> Trigger<B> for () {
+    fn fire(&self, b: &mut B) {
+        b.push();
+    }
+}
+
+// Still unsound Zook
+trait Button { fn push(&self); }
+struct Zook<B> { button: B, trigger: Box<Trigger<B>+'static> }
+
+impl<B> Drop for Zook<B> {
+    fn drop(&mut self) {
+        self.trigger.fire(&mut self.button);
+    }
+}
+
+// AND
+struct Bomb { usable: bool }
+impl Drop for Bomb { fn drop(&mut self) { self.usable = false; } }
+impl Bomb { fn activate(&self) { assert!(self.usable) } }
+
+enum B<'a> { HarmlessButton, BigRedButton(&'a Bomb) }
+impl<'a> Button for B<'a> {
+    fn push(&self) {
+        if let B::BigRedButton(borrowed) = *self {
+            borrowed.activate();
+        }
+    }
+}
+
+fn main() {
+    let (mut zook, ticking);
+    zook = Zook { button: B::HarmlessButton,
+                  trigger: Box::new(()) };
+    ticking = Bomb { usable: true };
+    zook.button = B::BigRedButton(&ticking);
+}
+//~^^ ERROR `ticking` does not live long enough
diff --git a/src/test/ui/span/issue-26656.stderr b/src/test/ui/span/issue-26656.stderr
new file mode 100644
index 0000000..ba2befb
--- /dev/null
+++ b/src/test/ui/span/issue-26656.stderr
@@ -0,0 +1,13 @@
+error[E0597]: `ticking` does not live long enough
+  --> $DIR/issue-26656.rs:40:36
+   |
+LL |     zook.button = B::BigRedButton(&ticking);
+   |                                    ^^^^^^^ borrowed value does not live long enough
+LL | }
+   | - `ticking` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/issue-27522.rs b/src/test/ui/span/issue-27522.rs
new file mode 100644
index 0000000..5c9893f
--- /dev/null
+++ b/src/test/ui/span/issue-27522.rs
@@ -0,0 +1,9 @@
+// Point at correct span for self type
+
+struct SomeType {}
+
+trait Foo {
+    fn handler(self: &SomeType); //~ ERROR invalid method receiver type
+}
+
+fn main() {}
diff --git a/src/test/ui/span/issue-27522.stderr b/src/test/ui/span/issue-27522.stderr
new file mode 100644
index 0000000..c99231a
--- /dev/null
+++ b/src/test/ui/span/issue-27522.stderr
@@ -0,0 +1,12 @@
+error[E0307]: invalid method receiver type: &SomeType
+  --> $DIR/issue-27522.rs:6:22
+   |
+LL |     fn handler(self: &SomeType);
+   |                      ^^^^^^^^^
+   |
+   = note: type must be `Self` or a type that dereferences to it
+   = help: consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0307`.
diff --git a/src/test/ui/span/issue-29106.nll.stderr b/src/test/ui/span/issue-29106.nll.stderr
new file mode 100644
index 0000000..3b403de
--- /dev/null
+++ b/src/test/ui/span/issue-29106.nll.stderr
@@ -0,0 +1,29 @@
+error[E0597]: `x` does not live long enough
+  --> $DIR/issue-29106.rs:16:26
+   |
+LL |         y = Arc::new(Foo(&x));
+   |                          ^^ borrowed value does not live long enough
+LL |     }
+   |     -
+   |     |
+   |     `x` dropped here while still borrowed
+   |     borrow might be used here, when `y` is dropped and runs the `Drop` code for type `std::sync::Arc`
+   |
+   = note: values in a scope are dropped in the opposite order they are defined
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/issue-29106.rs:23:25
+   |
+LL |         y = Rc::new(Foo(&x));
+   |                         ^^ borrowed value does not live long enough
+LL |     }
+   |     -
+   |     |
+   |     `x` dropped here while still borrowed
+   |     borrow might be used here, when `y` is dropped and runs the `Drop` code for type `std::rc::Rc`
+   |
+   = note: values in a scope are dropped in the opposite order they are defined
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/issue-29106.rs b/src/test/ui/span/issue-29106.rs
new file mode 100644
index 0000000..1be8d4c
--- /dev/null
+++ b/src/test/ui/span/issue-29106.rs
@@ -0,0 +1,26 @@
+use std::rc::Rc;
+use std::sync::Arc;
+
+struct Foo<'a>(&'a String);
+
+impl<'a> Drop for Foo<'a> {
+    fn drop(&mut self) {
+        println!("{:?}", self.0);
+    }
+}
+
+fn main() {
+    {
+        let (y, x);
+        x = "alive".to_string();
+        y = Arc::new(Foo(&x));
+    }
+    //~^^ ERROR `x` does not live long enough
+
+    {
+        let (y, x);
+        x = "alive".to_string();
+        y = Rc::new(Foo(&x));
+    }
+    //~^^ ERROR `x` does not live long enough
+}
diff --git a/src/test/ui/span/issue-29106.stderr b/src/test/ui/span/issue-29106.stderr
new file mode 100644
index 0000000..bb2f846
--- /dev/null
+++ b/src/test/ui/span/issue-29106.stderr
@@ -0,0 +1,23 @@
+error[E0597]: `x` does not live long enough
+  --> $DIR/issue-29106.rs:16:27
+   |
+LL |         y = Arc::new(Foo(&x));
+   |                           ^ borrowed value does not live long enough
+LL |     }
+   |     - `x` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/issue-29106.rs:23:26
+   |
+LL |         y = Rc::new(Foo(&x));
+   |                          ^ borrowed value does not live long enough
+LL |     }
+   |     - `x` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/issue-29595.rs b/src/test/ui/span/issue-29595.rs
new file mode 100644
index 0000000..87d7c4c
--- /dev/null
+++ b/src/test/ui/span/issue-29595.rs
@@ -0,0 +1,7 @@
+trait Tr {
+    const C: Self;
+}
+
+fn main() {
+    let a: u8 = Tr::C; //~ ERROR the trait bound `u8: Tr` is not satisfied
+}
diff --git a/src/test/ui/span/issue-29595.stderr b/src/test/ui/span/issue-29595.stderr
new file mode 100644
index 0000000..24dfdf8
--- /dev/null
+++ b/src/test/ui/span/issue-29595.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `u8: Tr` is not satisfied
+  --> $DIR/issue-29595.rs:6:17
+   |
+LL |     let a: u8 = Tr::C;
+   |                 ^^^^^ the trait `Tr` is not implemented for `u8`
+   |
+note: required by `Tr::C`
+  --> $DIR/issue-29595.rs:2:5
+   |
+LL |     const C: Self;
+   |     ^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/span/issue-33884.rs b/src/test/ui/span/issue-33884.rs
new file mode 100644
index 0000000..cef123d
--- /dev/null
+++ b/src/test/ui/span/issue-33884.rs
@@ -0,0 +1,20 @@
+// ignore-cloudabi no std::net support
+
+use std::net::TcpListener;
+use std::net::TcpStream;
+use std::io::{self, Read, Write};
+
+fn handle_client(stream: TcpStream) -> io::Result<()> {
+    stream.write_fmt(format!("message received"))
+    //~^ ERROR mismatched types
+}
+
+fn main() {
+    if let Ok(listener) = TcpListener::bind("127.0.0.1:8080") {
+        for incoming in listener.incoming() {
+            if let Ok(stream) = incoming {
+                handle_client(stream);
+            }
+        }
+    }
+}
diff --git a/src/test/ui/span/issue-33884.stderr b/src/test/ui/span/issue-33884.stderr
new file mode 100644
index 0000000..e59440b
--- /dev/null
+++ b/src/test/ui/span/issue-33884.stderr
@@ -0,0 +1,13 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-33884.rs:8:22
+   |
+LL |     stream.write_fmt(format!("message received"))
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `std::fmt::Arguments`, found struct `std::string::String`
+   |
+   = note: expected type `std::fmt::Arguments<'_>`
+              found type `std::string::String`
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/span/issue-34264.rs b/src/test/ui/span/issue-34264.rs
new file mode 100644
index 0000000..5b8fc71
--- /dev/null
+++ b/src/test/ui/span/issue-34264.rs
@@ -0,0 +1,11 @@
+fn foo(Option<i32>, String) {} //~ ERROR expected one of
+//~^ ERROR expected one of
+fn bar(x, y: usize) {} //~ ERROR expected one of
+
+fn main() {
+    foo(Some(42), 2);
+    foo(Some(42), 2, ""); //~ ERROR this function takes
+    bar("", ""); //~ ERROR mismatched types
+    bar(1, 2);
+    bar(1, 2, 3); //~ ERROR this function takes
+}
diff --git a/src/test/ui/span/issue-34264.stderr b/src/test/ui/span/issue-34264.stderr
new file mode 100644
index 0000000..c5b6245
--- /dev/null
+++ b/src/test/ui/span/issue-34264.stderr
@@ -0,0 +1,49 @@
+error: expected one of `:` or `@`, found `<`
+  --> $DIR/issue-34264.rs:1:14
+   |
+LL | fn foo(Option<i32>, String) {}
+   |              ^ expected one of `:` or `@` here
+
+error: expected one of `:` or `@`, found `)`
+  --> $DIR/issue-34264.rs:1:27
+   |
+LL | fn foo(Option<i32>, String) {}
+   |                           ^ expected one of `:` or `@` here
+
+error: expected one of `:` or `@`, found `,`
+  --> $DIR/issue-34264.rs:3:9
+   |
+LL | fn bar(x, y: usize) {}
+   |         ^ expected one of `:` or `@` here
+
+error[E0061]: this function takes 2 parameters but 3 parameters were supplied
+  --> $DIR/issue-34264.rs:7:5
+   |
+LL | fn foo(Option<i32>, String) {}
+   | --------------------------- defined here
+...
+LL |     foo(Some(42), 2, "");
+   |     ^^^^^^^^^^^^^^^^^^^^ expected 2 parameters
+
+error[E0308]: mismatched types
+  --> $DIR/issue-34264.rs:8:13
+   |
+LL |     bar("", "");
+   |             ^^ expected usize, found reference
+   |
+   = note: expected type `usize`
+              found type `&'static str`
+
+error[E0061]: this function takes 2 parameters but 3 parameters were supplied
+  --> $DIR/issue-34264.rs:10:5
+   |
+LL | fn bar(x, y: usize) {}
+   | ------------------- defined here
+...
+LL |     bar(1, 2, 3);
+   |     ^^^^^^^^^^^^ expected 2 parameters
+
+error: aborting due to 6 previous errors
+
+Some errors occurred: E0061, E0308.
+For more information about an error, try `rustc --explain E0061`.
diff --git a/src/test/ui/span/issue-35987.rs b/src/test/ui/span/issue-35987.rs
new file mode 100644
index 0000000..3a6e6ff
--- /dev/null
+++ b/src/test/ui/span/issue-35987.rs
@@ -0,0 +1,14 @@
+struct Foo<T: Clone>(T);
+
+use std::ops::Add;
+
+impl<T: Clone, Add> Add for Foo<T> {
+//~^ ERROR expected trait, found type parameter
+    type Output = usize;
+
+    fn add(self, rhs: Self) -> Self::Output {
+        unimplemented!();
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/span/issue-35987.stderr b/src/test/ui/span/issue-35987.stderr
new file mode 100644
index 0000000..f73bf27
--- /dev/null
+++ b/src/test/ui/span/issue-35987.stderr
@@ -0,0 +1,13 @@
+error[E0404]: expected trait, found type parameter `Add`
+  --> $DIR/issue-35987.rs:5:21
+   |
+LL | impl<T: Clone, Add> Add for Foo<T> {
+   |                     ^^^ not a trait
+help: possible better candidate is found in another module, you can import it into scope
+   |
+LL | use std::ops::Add;
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0404`.
diff --git a/src/test/ui/span/issue-36530.rs b/src/test/ui/span/issue-36530.rs
new file mode 100644
index 0000000..e11be9e
--- /dev/null
+++ b/src/test/ui/span/issue-36530.rs
@@ -0,0 +1,9 @@
+// gate-test-custom_inner_attributes
+
+#[foo] //~ ERROR is currently unknown to the compiler
+mod foo {
+    #![foo] //~ ERROR is currently unknown to the compiler
+            //~| ERROR non-builtin inner attributes are unstable
+}
+
+fn main() {}
diff --git a/src/test/ui/span/issue-36530.stderr b/src/test/ui/span/issue-36530.stderr
new file mode 100644
index 0000000..05b2ca9
--- /dev/null
+++ b/src/test/ui/span/issue-36530.stderr
@@ -0,0 +1,27 @@
+error[E0658]: The attribute `foo` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/issue-36530.rs:3:3
+   |
+LL | #[foo]
+   |   ^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error[E0658]: non-builtin inner attributes are unstable (see issue #54726)
+  --> $DIR/issue-36530.rs:5:5
+   |
+LL |     #![foo]
+   |     ^^^^^^^
+   |
+   = help: add #![feature(custom_inner_attributes)] to the crate attributes to enable
+
+error[E0658]: The attribute `foo` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/issue-36530.rs:5:8
+   |
+LL |     #![foo]
+   |        ^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/span/issue-36537.nll.stderr b/src/test/ui/span/issue-36537.nll.stderr
new file mode 100644
index 0000000..edb804e
--- /dev/null
+++ b/src/test/ui/span/issue-36537.nll.stderr
@@ -0,0 +1,14 @@
+error[E0597]: `a` does not live long enough
+  --> $DIR/issue-36537.rs:5:9
+   |
+LL |         p = &a;
+   |         ^^^^^^ borrowed value does not live long enough
+...
+LL |     }
+   |     - `a` dropped here while still borrowed
+LL |     p.use_ref();
+   |     - borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/issue-36537.rs b/src/test/ui/span/issue-36537.rs
new file mode 100644
index 0000000..a5546cc
--- /dev/null
+++ b/src/test/ui/span/issue-36537.rs
@@ -0,0 +1,14 @@
+fn main() {
+    let p;
+    {
+        let a = 42;
+        p = &a;
+        //~^ ERROR `a` does not live long enough
+
+    }
+    p.use_ref();
+
+}
+
+trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { }  }
+impl<T> Fake for T { }
diff --git a/src/test/ui/span/issue-36537.stderr b/src/test/ui/span/issue-36537.stderr
new file mode 100644
index 0000000..d3bcbb2
--- /dev/null
+++ b/src/test/ui/span/issue-36537.stderr
@@ -0,0 +1,15 @@
+error[E0597]: `a` does not live long enough
+  --> $DIR/issue-36537.rs:5:14
+   |
+LL |         p = &a;
+   |              ^ borrowed value does not live long enough
+...
+LL |     }
+   |     - `a` dropped here while still borrowed
+...
+LL | }
+   | - borrowed value needs to live until here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/issue-37767.rs b/src/test/ui/span/issue-37767.rs
new file mode 100644
index 0000000..9e34c2c
--- /dev/null
+++ b/src/test/ui/span/issue-37767.rs
@@ -0,0 +1,41 @@
+trait A {
+    fn foo(&mut self) {}
+}
+
+trait B : A {
+    fn foo(&mut self) {}
+}
+
+fn bar<T: B>(a: &T) {
+    a.foo() //~ ERROR multiple applicable items
+}
+
+trait C {
+    fn foo(&self) {}
+}
+
+trait D : C {
+    fn foo(&self) {}
+}
+
+fn quz<T: D>(a: &T) {
+    a.foo() //~ ERROR multiple applicable items
+}
+
+trait E : Sized {
+    fn foo(self) {}
+}
+
+trait F : E {
+    fn foo(self) {}
+}
+
+fn foo<T: F>(a: T) {
+    a.foo() //~ ERROR multiple applicable items
+}
+
+fn pass<T: C>(a: &T) {
+    a.foo()
+}
+
+fn main() {}
diff --git a/src/test/ui/span/issue-37767.stderr b/src/test/ui/span/issue-37767.stderr
new file mode 100644
index 0000000..0bbff45
--- /dev/null
+++ b/src/test/ui/span/issue-37767.stderr
@@ -0,0 +1,60 @@
+error[E0034]: multiple applicable items in scope
+  --> $DIR/issue-37767.rs:10:7
+   |
+LL |     a.foo()
+   |       ^^^ multiple `foo` found
+   |
+note: candidate #1 is defined in the trait `A`
+  --> $DIR/issue-37767.rs:2:5
+   |
+LL |     fn foo(&mut self) {}
+   |     ^^^^^^^^^^^^^^^^^
+   = help: to disambiguate the method call, write `A::foo(&a)` instead
+note: candidate #2 is defined in the trait `B`
+  --> $DIR/issue-37767.rs:6:5
+   |
+LL |     fn foo(&mut self) {}
+   |     ^^^^^^^^^^^^^^^^^
+   = help: to disambiguate the method call, write `B::foo(&a)` instead
+
+error[E0034]: multiple applicable items in scope
+  --> $DIR/issue-37767.rs:22:7
+   |
+LL |     a.foo()
+   |       ^^^ multiple `foo` found
+   |
+note: candidate #1 is defined in the trait `C`
+  --> $DIR/issue-37767.rs:14:5
+   |
+LL |     fn foo(&self) {}
+   |     ^^^^^^^^^^^^^
+   = help: to disambiguate the method call, write `C::foo(&a)` instead
+note: candidate #2 is defined in the trait `D`
+  --> $DIR/issue-37767.rs:18:5
+   |
+LL |     fn foo(&self) {}
+   |     ^^^^^^^^^^^^^
+   = help: to disambiguate the method call, write `D::foo(&a)` instead
+
+error[E0034]: multiple applicable items in scope
+  --> $DIR/issue-37767.rs:34:7
+   |
+LL |     a.foo()
+   |       ^^^ multiple `foo` found
+   |
+note: candidate #1 is defined in the trait `E`
+  --> $DIR/issue-37767.rs:26:5
+   |
+LL |     fn foo(self) {}
+   |     ^^^^^^^^^^^^
+   = help: to disambiguate the method call, write `E::foo(a)` instead
+note: candidate #2 is defined in the trait `F`
+  --> $DIR/issue-37767.rs:30:5
+   |
+LL |     fn foo(self) {}
+   |     ^^^^^^^^^^^^
+   = help: to disambiguate the method call, write `F::foo(a)` instead
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0034`.
diff --git a/src/test/ui/span/issue-39018.rs b/src/test/ui/span/issue-39018.rs
new file mode 100644
index 0000000..6dbc8d3
--- /dev/null
+++ b/src/test/ui/span/issue-39018.rs
@@ -0,0 +1,18 @@
+pub fn main() {
+    let x = "Hello " + "World!";
+    //~^ ERROR cannot be applied to type
+
+    // Make sure that the span outputs a warning
+    // for not having an implementation for std::ops::Add
+    // that won't output for the above string concatenation
+    let y = World::Hello + World::Goodbye;
+    //~^ ERROR cannot be applied to type
+
+    let x = "Hello " + "World!".to_owned();
+    //~^ ERROR cannot be applied to type
+}
+
+enum World {
+    Hello,
+    Goodbye,
+}
diff --git a/src/test/ui/span/issue-39018.stderr b/src/test/ui/span/issue-39018.stderr
new file mode 100644
index 0000000..a5b91f0
--- /dev/null
+++ b/src/test/ui/span/issue-39018.stderr
@@ -0,0 +1,40 @@
+error[E0369]: binary operation `+` cannot be applied to type `&str`
+  --> $DIR/issue-39018.rs:2:22
+   |
+LL |     let x = "Hello " + "World!";
+   |             -------- ^ -------- &str
+   |             |        |
+   |             |        `+` can't be used to concatenate two `&str` strings
+   |             &str
+help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left
+   |
+LL |     let x = "Hello ".to_owned() + "World!";
+   |             ^^^^^^^^^^^^^^^^^^^
+
+error[E0369]: binary operation `+` cannot be applied to type `World`
+  --> $DIR/issue-39018.rs:8:26
+   |
+LL |     let y = World::Hello + World::Goodbye;
+   |             ------------ ^ -------------- World
+   |             |
+   |             World
+   |
+   = note: an implementation of `std::ops::Add` might be missing for `World`
+
+error[E0369]: binary operation `+` cannot be applied to type `&str`
+  --> $DIR/issue-39018.rs:11:22
+   |
+LL |     let x = "Hello " + "World!".to_owned();
+   |             ---------^--------------------
+   |             |          |
+   |             |          std::string::String
+   |             &str
+   |             `+` can't be used to concatenate a `&str` with a `String`
+help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left
+   |
+LL |     let x = "Hello ".to_owned() + &"World!".to_owned();
+   |             ^^^^^^^^^^^^^^^^^^^   ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0369`.
diff --git a/src/test/ui/span/issue-39698.rs b/src/test/ui/span/issue-39698.rs
new file mode 100644
index 0000000..1079bae
--- /dev/null
+++ b/src/test/ui/span/issue-39698.rs
@@ -0,0 +1,16 @@
+enum T {
+    T1(i32, i32),
+    T2(i32, i32),
+    T3(i32),
+    T4(i32),
+}
+
+fn main() {
+    match T::T1(123, 456) {
+        T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
+        //~^ ERROR is not bound in all patterns
+        //~| ERROR is not bound in all patterns
+        //~| ERROR is not bound in all patterns
+        //~| ERROR is not bound in all patterns
+    }
+}
diff --git a/src/test/ui/span/issue-39698.stderr b/src/test/ui/span/issue-39698.stderr
new file mode 100644
index 0000000..7fa5d24
--- /dev/null
+++ b/src/test/ui/span/issue-39698.stderr
@@ -0,0 +1,43 @@
+error[E0408]: variable `a` is not bound in all patterns
+  --> $DIR/issue-39698.rs:10:23
+   |
+LL |         T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
+   |               -       ^^^^^^^^^^^   ^^^^^^^^         - variable not in all patterns
+   |               |       |             |
+   |               |       |             pattern doesn't bind `a`
+   |               |       pattern doesn't bind `a`
+   |               variable not in all patterns
+
+error[E0408]: variable `d` is not bound in all patterns
+  --> $DIR/issue-39698.rs:10:37
+   |
+LL |         T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
+   |                  -          -       ^^^^^^^^   ^^^^^^^^ pattern doesn't bind `d`
+   |                  |          |       |
+   |                  |          |       pattern doesn't bind `d`
+   |                  |          variable not in all patterns
+   |                  variable not in all patterns
+
+error[E0408]: variable `b` is not bound in all patterns
+  --> $DIR/issue-39698.rs:10:9
+   |
+LL |         T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
+   |         ^^^^^^^^^^^            -    ^^^^^^^^   ^^^^^^^^ pattern doesn't bind `b`
+   |         |                      |    |
+   |         |                      |    pattern doesn't bind `b`
+   |         |                      variable not in all patterns
+   |         pattern doesn't bind `b`
+
+error[E0408]: variable `c` is not bound in all patterns
+  --> $DIR/issue-39698.rs:10:9
+   |
+LL |         T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
+   |         ^^^^^^^^^^^   ^^^^^^^^^^^         -    ^^^^^^^^ pattern doesn't bind `c`
+   |         |             |                   |
+   |         |             |                   variable not in all patterns
+   |         |             pattern doesn't bind `c`
+   |         pattern doesn't bind `c`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0408`.
diff --git a/src/test/ui/span/issue-40157.nll.stderr b/src/test/ui/span/issue-40157.nll.stderr
new file mode 100644
index 0000000..0b365c3
--- /dev/null
+++ b/src/test/ui/span/issue-40157.nll.stderr
@@ -0,0 +1,13 @@
+error[E0597]: `foo` does not live long enough
+  --> $DIR/issue-40157.rs:2:53
+   |
+LL |     {println!("{:?}", match { let foo = vec![1, 2]; foo.get(1) } { x => x });}
+   |                             ------------------------^^^---------
+   |                             |                       |          |
+   |                             |                       |          `foo` dropped here while still borrowed
+   |                             |                       borrowed value does not live long enough
+   |                             borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/issue-40157.rs b/src/test/ui/span/issue-40157.rs
new file mode 100644
index 0000000..03ad21a
--- /dev/null
+++ b/src/test/ui/span/issue-40157.rs
@@ -0,0 +1,4 @@
+fn main () {
+    {println!("{:?}", match { let foo = vec![1, 2]; foo.get(1) } { x => x });}
+     //~^ ERROR does not live long enough
+}
diff --git a/src/test/ui/span/issue-40157.stderr b/src/test/ui/span/issue-40157.stderr
new file mode 100644
index 0000000..55fc8d8
--- /dev/null
+++ b/src/test/ui/span/issue-40157.stderr
@@ -0,0 +1,15 @@
+error[E0597]: `foo` does not live long enough
+  --> $DIR/issue-40157.rs:2:53
+   |
+LL |     {println!("{:?}", match { let foo = vec![1, 2]; foo.get(1) } { x => x });}
+   |      -----------------------------------------------^^^----------------------
+   |      |                                              |          |
+   |      |                                              |          `foo` dropped here while still borrowed
+   |      |                                              borrowed value does not live long enough
+   |      borrowed value needs to live until here
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/issue-42234-unknown-receiver-type.rs b/src/test/ui/span/issue-42234-unknown-receiver-type.rs
new file mode 100644
index 0000000..58138e2
--- /dev/null
+++ b/src/test/ui/span/issue-42234-unknown-receiver-type.rs
@@ -0,0 +1,17 @@
+// When the type of a method call's receiver is unknown, the span should point
+// to the receiver (and not the entire call, as was previously the case before
+// the fix of which this tests).
+
+fn shines_a_beacon_through_the_darkness() {
+    let x: Option<_> = None;
+    x.unwrap().method_that_could_exist_on_some_type();
+    //~^ ERROR type annotations needed
+}
+
+fn courier_to_des_moines_and_points_west(data: &[u32]) -> String {
+    data.iter() //~ ERROR type annotations needed
+        .sum::<_>()
+        .to_string()
+}
+
+fn main() {}
diff --git a/src/test/ui/span/issue-42234-unknown-receiver-type.stderr b/src/test/ui/span/issue-42234-unknown-receiver-type.stderr
new file mode 100644
index 0000000..8923de5
--- /dev/null
+++ b/src/test/ui/span/issue-42234-unknown-receiver-type.stderr
@@ -0,0 +1,22 @@
+error[E0282]: type annotations needed
+  --> $DIR/issue-42234-unknown-receiver-type.rs:7:5
+   |
+LL |     let x: Option<_> = None;
+   |         - consider giving `x` a type
+LL |     x.unwrap().method_that_could_exist_on_some_type();
+   |     ^^^^^^^^^^ cannot infer type for `T`
+   |
+   = note: type must be known at this point
+
+error[E0282]: type annotations needed
+  --> $DIR/issue-42234-unknown-receiver-type.rs:12:5
+   |
+LL | /     data.iter()
+LL | |         .sum::<_>()
+   | |___________________^ cannot infer type
+   |
+   = note: type must be known at this point
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/span/issue-43927-non-ADT-derive.rs b/src/test/ui/span/issue-43927-non-ADT-derive.rs
new file mode 100644
index 0000000..add1758
--- /dev/null
+++ b/src/test/ui/span/issue-43927-non-ADT-derive.rs
@@ -0,0 +1,7 @@
+#![allow(dead_code)]
+
+#![derive(Debug, PartialEq, Eq)] // should be an outer attribute!
+//~^ ERROR `derive` may only be applied to structs, enums and unions
+struct DerivedOn;
+
+fn main() {}
diff --git a/src/test/ui/span/issue-43927-non-ADT-derive.stderr b/src/test/ui/span/issue-43927-non-ADT-derive.stderr
new file mode 100644
index 0000000..e09a8a0
--- /dev/null
+++ b/src/test/ui/span/issue-43927-non-ADT-derive.stderr
@@ -0,0 +1,8 @@
+error: `derive` may only be applied to structs, enums and unions
+  --> $DIR/issue-43927-non-ADT-derive.rs:3:1
+   |
+LL | #![derive(Debug, PartialEq, Eq)] // should be an outer attribute!
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try an outer attribute: `#[derive(Debug, PartialEq, Eq)]`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/span/issue-7575.rs b/src/test/ui/span/issue-7575.rs
new file mode 100644
index 0000000..c33398c
--- /dev/null
+++ b/src/test/ui/span/issue-7575.rs
@@ -0,0 +1,77 @@
+// Test the mechanism for warning about possible missing `self` declarations.
+// ignore-tidy-linelength
+
+trait CtxtFn {
+    fn f8(self, _: usize) -> usize;
+    fn f9(_: usize) -> usize;
+}
+
+trait OtherTrait {
+    fn f9(_: usize) -> usize;
+}
+
+// Note: this trait is not implemented, but we can't really tell
+// whether or not an impl would match anyhow without a self
+// declaration to match against, so we wind up prisizeing it as a
+// candidate. This seems not unreasonable -- perhaps the user meant to
+// implement it, after all.
+trait UnusedTrait {
+    fn f9(_: usize) -> usize;
+}
+
+impl CtxtFn for usize {
+    fn f8(self, i: usize) -> usize {
+        i * 4
+    }
+
+    fn f9(i: usize) -> usize {
+        i * 4
+    }
+}
+
+impl OtherTrait for usize {
+    fn f9(i: usize) -> usize {
+        i * 8
+    }
+}
+
+struct Myisize(isize);
+
+impl Myisize {
+    fn fff(i: isize) -> isize {
+        i
+    }
+}
+
+trait ManyImplTrait {
+    fn is_str() -> bool {
+        false
+    }
+}
+
+impl ManyImplTrait for String {
+    fn is_str() -> bool {
+        true
+    }
+}
+
+impl ManyImplTrait for usize {}
+impl ManyImplTrait for isize {}
+impl ManyImplTrait for char {}
+impl ManyImplTrait for Myisize {}
+
+fn no_param_bound(u: usize, m: Myisize) -> usize {
+    u.f8(42) + u.f9(342) + m.fff(42)
+            //~^ ERROR no method named `f9` found for type `usize` in the current scope
+            //~| ERROR no method named `fff` found for type `Myisize` in the current scope
+
+
+}
+
+fn param_bound<T: ManyImplTrait>(t: T) -> bool {
+    t.is_str()
+    //~^ ERROR no method named `is_str` found for type `T` in the current scope
+}
+
+fn main() {
+}
diff --git a/src/test/ui/span/issue-7575.stderr b/src/test/ui/span/issue-7575.stderr
new file mode 100644
index 0000000..b2c9e50
--- /dev/null
+++ b/src/test/ui/span/issue-7575.stderr
@@ -0,0 +1,70 @@
+error[E0599]: no method named `f9` found for type `usize` in the current scope
+  --> $DIR/issue-7575.rs:64:18
+   |
+LL |     u.f8(42) + u.f9(342) + m.fff(42)
+   |                  ^^ this is an associated function, not a method
+   |
+   = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
+note: candidate #1 is defined in the trait `CtxtFn`
+  --> $DIR/issue-7575.rs:6:5
+   |
+LL |     fn f9(_: usize) -> usize;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: to disambiguate the method call, write `CtxtFn::f9(u, 342)` instead
+note: candidate #2 is defined in the trait `OtherTrait`
+  --> $DIR/issue-7575.rs:10:5
+   |
+LL |     fn f9(_: usize) -> usize;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: to disambiguate the method call, write `OtherTrait::f9(u, 342)` instead
+note: candidate #3 is defined in the trait `UnusedTrait`
+  --> $DIR/issue-7575.rs:19:5
+   |
+LL |     fn f9(_: usize) -> usize;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: to disambiguate the method call, write `UnusedTrait::f9(u, 342)` instead
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following traits define an item `f9`, perhaps you need to implement one of them:
+           candidate #1: `CtxtFn`
+           candidate #2: `OtherTrait`
+           candidate #3: `UnusedTrait`
+
+error[E0599]: no method named `fff` found for type `Myisize` in the current scope
+  --> $DIR/issue-7575.rs:64:30
+   |
+LL | struct Myisize(isize);
+   | ---------------------- method `fff` not found for this
+...
+LL |     u.f8(42) + u.f9(342) + m.fff(42)
+   |                            --^^^
+   |                            | |
+   |                            | this is an associated function, not a method
+   |                            help: use associated function syntax instead: `Myisize::fff`
+   |
+   = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
+note: the candidate is defined in an impl for the type `Myisize`
+  --> $DIR/issue-7575.rs:41:5
+   |
+LL |     fn fff(i: isize) -> isize {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0599]: no method named `is_str` found for type `T` in the current scope
+  --> $DIR/issue-7575.rs:72:7
+   |
+LL |     t.is_str()
+   |       ^^^^^^ this is an associated function, not a method
+   |
+   = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
+note: the candidate is defined in the trait `ManyImplTrait`
+  --> $DIR/issue-7575.rs:47:5
+   |
+LL |     fn is_str() -> bool {
+   |     ^^^^^^^^^^^^^^^^^^^
+   = help: to disambiguate the method call, write `ManyImplTrait::is_str(t)` instead
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following trait defines an item `is_str`, perhaps you need to implement it:
+           candidate #1: `ManyImplTrait`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/span/issue28498-reject-ex1.nll.stderr b/src/test/ui/span/issue28498-reject-ex1.nll.stderr
new file mode 100644
index 0000000..86e2d8c
--- /dev/null
+++ b/src/test/ui/span/issue28498-reject-ex1.nll.stderr
@@ -0,0 +1,17 @@
+error[E0713]: borrow may still be in use when destructor runs
+  --> $DIR/issue28498-reject-ex1.rs:34:29
+   |
+LL |     foo.data[0].1.set(Some(&foo.data[1]));
+   |                             ^^^^^^^^
+...
+LL | }
+   | -
+   | |
+   | here, drop of `foo` needs exclusive access to `foo.data`, because the type `Foo<Concrete<'_>>` implements the `Drop` trait
+   | borrow might be used here, when `foo` is dropped and runs the `Drop` code for type `Foo`
+   |
+   = note: consider using a `let` binding to create a longer lived value
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0713`.
diff --git a/src/test/ui/span/issue28498-reject-ex1.rs b/src/test/ui/span/issue28498-reject-ex1.rs
new file mode 100644
index 0000000..05104d1
--- /dev/null
+++ b/src/test/ui/span/issue28498-reject-ex1.rs
@@ -0,0 +1,38 @@
+// Example taken from RFC 1238 text
+
+// https://github.com/rust-lang/rfcs/blob/master/text/1238-nonparametric-dropck.md
+//     #examples-of-code-that-will-start-to-be-rejected
+
+// Compare against test/run-pass/issue28498-must-work-ex2.rs
+
+use std::cell::Cell;
+
+struct Concrete<'a>(u32, Cell<Option<&'a Concrete<'a>>>);
+
+struct Foo<T> { data: Vec<T> }
+
+fn potentially_specialized_wrt_t<T>(t: &T) {
+    // Hypothetical code that does one thing for generic T and then is
+    // specialized for T == Concrete (and the specialized form can
+    // then access a reference held in concrete tuple).
+    //
+    // (We don't have specialization yet, but we want to allow for it
+    // in the future.)
+}
+
+impl<T> Drop for Foo<T> {
+    fn drop(&mut self) {
+        potentially_specialized_wrt_t(&self.data[0])
+    }
+}
+
+fn main() {
+    let mut foo = Foo {  data: Vec::new() };
+    foo.data.push(Concrete(0, Cell::new(None)));
+    foo.data.push(Concrete(0, Cell::new(None)));
+
+    foo.data[0].1.set(Some(&foo.data[1]));
+    //~^ ERROR `foo.data` does not live long enough
+    foo.data[1].1.set(Some(&foo.data[0]));
+    //~^ ERROR `foo.data` does not live long enough
+}
diff --git a/src/test/ui/span/issue28498-reject-ex1.stderr b/src/test/ui/span/issue28498-reject-ex1.stderr
new file mode 100644
index 0000000..1438b95
--- /dev/null
+++ b/src/test/ui/span/issue28498-reject-ex1.stderr
@@ -0,0 +1,25 @@
+error[E0597]: `foo.data` does not live long enough
+  --> $DIR/issue28498-reject-ex1.rs:34:29
+   |
+LL |     foo.data[0].1.set(Some(&foo.data[1]));
+   |                             ^^^^^^^^ borrowed value does not live long enough
+...
+LL | }
+   | - `foo.data` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error[E0597]: `foo.data` does not live long enough
+  --> $DIR/issue28498-reject-ex1.rs:36:29
+   |
+LL |     foo.data[1].1.set(Some(&foo.data[0]));
+   |                             ^^^^^^^^ borrowed value does not live long enough
+LL |
+LL | }
+   | - `foo.data` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/issue28498-reject-lifetime-param.nll.stderr b/src/test/ui/span/issue28498-reject-lifetime-param.nll.stderr
new file mode 100644
index 0000000..3273b51
--- /dev/null
+++ b/src/test/ui/span/issue28498-reject-lifetime-param.nll.stderr
@@ -0,0 +1,17 @@
+error[E0597]: `first_dropped` does not live long enough
+  --> $DIR/issue28498-reject-lifetime-param.rs:34:19
+   |
+LL |     foo1 = Foo(1, &first_dropped);
+   |                   ^^^^^^^^^^^^^^ borrowed value does not live long enough
+...
+LL | }
+   | -
+   | |
+   | `first_dropped` dropped here while still borrowed
+   | borrow might be used here, when `foo1` is dropped and runs the `Drop` code for type `Foo`
+   |
+   = note: values in a scope are dropped in the opposite order they are defined
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/issue28498-reject-lifetime-param.rs b/src/test/ui/span/issue28498-reject-lifetime-param.rs
new file mode 100644
index 0000000..062636a
--- /dev/null
+++ b/src/test/ui/span/issue28498-reject-lifetime-param.rs
@@ -0,0 +1,38 @@
+// Demonstrate that having a lifetime param causes dropck to reject code
+// that might indirectly access previously dropped value.
+//
+// Compare with run-pass/issue28498-ugeh-with-lifetime-param.rs
+
+#[derive(Debug)]
+struct ScribbleOnDrop(String);
+
+impl Drop for ScribbleOnDrop {
+    fn drop(&mut self) {
+        self.0 = format!("DROPPED");
+    }
+}
+
+struct Foo<'a>(u32, &'a ScribbleOnDrop);
+
+impl<'a> Drop for Foo<'a> {
+    fn drop(&mut self) {
+        // Use of `unsafe_destructor_blind_to_params` is unsound,
+        // because destructor accesses borrowed data in `self.1`
+        // and we must force that to strictly outlive `self`.
+        println!("Dropping Foo({}, {:?})", self.0, self.1);
+    }
+}
+
+fn main() {
+    let (last_dropped, foo0);
+    let (foo1, first_dropped);
+
+    last_dropped = ScribbleOnDrop(format!("last"));
+    first_dropped = ScribbleOnDrop(format!("first"));
+    foo0 = Foo(0, &last_dropped);
+    //~^ ERROR `last_dropped` does not live long enough
+    foo1 = Foo(1, &first_dropped);
+    //~^ ERROR `first_dropped` does not live long enough
+
+    println!("foo0.1: {:?} foo1.1: {:?}", foo0.1, foo1.1);
+}
diff --git a/src/test/ui/span/issue28498-reject-lifetime-param.stderr b/src/test/ui/span/issue28498-reject-lifetime-param.stderr
new file mode 100644
index 0000000..0e51729
--- /dev/null
+++ b/src/test/ui/span/issue28498-reject-lifetime-param.stderr
@@ -0,0 +1,25 @@
+error[E0597]: `last_dropped` does not live long enough
+  --> $DIR/issue28498-reject-lifetime-param.rs:32:20
+   |
+LL |     foo0 = Foo(0, &last_dropped);
+   |                    ^^^^^^^^^^^^ borrowed value does not live long enough
+...
+LL | }
+   | - `last_dropped` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error[E0597]: `first_dropped` does not live long enough
+  --> $DIR/issue28498-reject-lifetime-param.rs:34:20
+   |
+LL |     foo1 = Foo(1, &first_dropped);
+   |                    ^^^^^^^^^^^^^ borrowed value does not live long enough
+...
+LL | }
+   | - `first_dropped` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/issue28498-reject-passed-to-fn.nll.stderr b/src/test/ui/span/issue28498-reject-passed-to-fn.nll.stderr
new file mode 100644
index 0000000..ae08e3e
--- /dev/null
+++ b/src/test/ui/span/issue28498-reject-passed-to-fn.nll.stderr
@@ -0,0 +1,17 @@
+error[E0597]: `first_dropped` does not live long enough
+  --> $DIR/issue28498-reject-passed-to-fn.rs:36:19
+   |
+LL |     foo1 = Foo(1, &first_dropped, Box::new(callback));
+   |                   ^^^^^^^^^^^^^^ borrowed value does not live long enough
+...
+LL | }
+   | -
+   | |
+   | `first_dropped` dropped here while still borrowed
+   | borrow might be used here, when `foo1` is dropped and runs the `Drop` code for type `Foo`
+   |
+   = note: values in a scope are dropped in the opposite order they are defined
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/issue28498-reject-passed-to-fn.rs b/src/test/ui/span/issue28498-reject-passed-to-fn.rs
new file mode 100644
index 0000000..27a757e
--- /dev/null
+++ b/src/test/ui/span/issue28498-reject-passed-to-fn.rs
@@ -0,0 +1,40 @@
+// Demonstrate that a type param in negative position causes dropck to reject code
+// that might indirectly access previously dropped value.
+//
+// Compare with run-pass/issue28498-ugeh-with-passed-to-fn.rs
+
+#[derive(Debug)]
+struct ScribbleOnDrop(String);
+
+impl Drop for ScribbleOnDrop {
+    fn drop(&mut self) {
+        self.0 = format!("DROPPED");
+    }
+}
+
+struct Foo<T>(u32, T, Box<for <'r> fn(&'r T) -> String>);
+
+impl<T> Drop for Foo<T> {
+    fn drop(&mut self) {
+        // Use of `unsafe_destructor_blind_to_params` is unsound,
+        // because we pass `T` to the callback in `self.2`
+        // below, and thus potentially read from borrowed data.
+        println!("Dropping Foo({}, {})", self.0, (self.2)(&self.1));
+    }
+}
+
+fn callback(s: & &ScribbleOnDrop) -> String { format!("{:?}", s) }
+
+fn main() {
+    let (last_dropped, foo0);
+    let (foo1, first_dropped);
+
+    last_dropped = ScribbleOnDrop(format!("last"));
+    first_dropped = ScribbleOnDrop(format!("first"));
+    foo0 = Foo(0, &last_dropped, Box::new(callback));
+    //~^ ERROR `last_dropped` does not live long enough
+    foo1 = Foo(1, &first_dropped, Box::new(callback));
+    //~^ ERROR `first_dropped` does not live long enough
+
+    println!("foo0.1: {:?} foo1.1: {:?}", foo0.1, foo1.1);
+}
diff --git a/src/test/ui/span/issue28498-reject-passed-to-fn.stderr b/src/test/ui/span/issue28498-reject-passed-to-fn.stderr
new file mode 100644
index 0000000..80533c7
--- /dev/null
+++ b/src/test/ui/span/issue28498-reject-passed-to-fn.stderr
@@ -0,0 +1,25 @@
+error[E0597]: `last_dropped` does not live long enough
+  --> $DIR/issue28498-reject-passed-to-fn.rs:34:20
+   |
+LL |     foo0 = Foo(0, &last_dropped, Box::new(callback));
+   |                    ^^^^^^^^^^^^ borrowed value does not live long enough
+...
+LL | }
+   | - `last_dropped` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error[E0597]: `first_dropped` does not live long enough
+  --> $DIR/issue28498-reject-passed-to-fn.rs:36:20
+   |
+LL |     foo1 = Foo(1, &first_dropped, Box::new(callback));
+   |                    ^^^^^^^^^^^^^ borrowed value does not live long enough
+...
+LL | }
+   | - `first_dropped` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/issue28498-reject-trait-bound.nll.stderr b/src/test/ui/span/issue28498-reject-trait-bound.nll.stderr
new file mode 100644
index 0000000..600fd53
--- /dev/null
+++ b/src/test/ui/span/issue28498-reject-trait-bound.nll.stderr
@@ -0,0 +1,17 @@
+error[E0597]: `first_dropped` does not live long enough
+  --> $DIR/issue28498-reject-trait-bound.rs:36:19
+   |
+LL |     foo1 = Foo(1, &first_dropped);
+   |                   ^^^^^^^^^^^^^^ borrowed value does not live long enough
+...
+LL | }
+   | -
+   | |
+   | `first_dropped` dropped here while still borrowed
+   | borrow might be used here, when `foo1` is dropped and runs the `Drop` code for type `Foo`
+   |
+   = note: values in a scope are dropped in the opposite order they are defined
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/issue28498-reject-trait-bound.rs b/src/test/ui/span/issue28498-reject-trait-bound.rs
new file mode 100644
index 0000000..3ea67d1
--- /dev/null
+++ b/src/test/ui/span/issue28498-reject-trait-bound.rs
@@ -0,0 +1,40 @@
+// Demonstrate that having a trait bound causes dropck to reject code
+// that might indirectly access previously dropped value.
+//
+// Compare with run-pass/issue28498-ugeh-with-trait-bound.rs
+
+use std::fmt;
+
+#[derive(Debug)]
+struct ScribbleOnDrop(String);
+
+impl Drop for ScribbleOnDrop {
+    fn drop(&mut self) {
+        self.0 = format!("DROPPED");
+    }
+}
+
+struct Foo<T:fmt::Debug>(u32, T);
+
+impl<T:fmt::Debug> Drop for Foo<T> {
+    fn drop(&mut self) {
+        // Use of `unsafe_destructor_blind_to_params` is unsound,
+        // because we access `T` fmt method when we pass `self.1`
+        // below, and thus potentially read from borrowed data.
+        println!("Dropping Foo({}, {:?})", self.0, self.1);
+    }
+}
+
+fn main() {
+    let (last_dropped, foo0);
+    let (foo1, first_dropped);
+
+    last_dropped = ScribbleOnDrop(format!("last"));
+    first_dropped = ScribbleOnDrop(format!("first"));
+    foo0 = Foo(0, &last_dropped);
+    //~^ ERROR `last_dropped` does not live long enough
+    foo1 = Foo(1, &first_dropped);
+    //~^ ERROR `first_dropped` does not live long enough
+
+    println!("foo0.1: {:?} foo1.1: {:?}", foo0.1, foo1.1);
+}
diff --git a/src/test/ui/span/issue28498-reject-trait-bound.stderr b/src/test/ui/span/issue28498-reject-trait-bound.stderr
new file mode 100644
index 0000000..3ce4dd9
--- /dev/null
+++ b/src/test/ui/span/issue28498-reject-trait-bound.stderr
@@ -0,0 +1,25 @@
+error[E0597]: `last_dropped` does not live long enough
+  --> $DIR/issue28498-reject-trait-bound.rs:34:20
+   |
+LL |     foo0 = Foo(0, &last_dropped);
+   |                    ^^^^^^^^^^^^ borrowed value does not live long enough
+...
+LL | }
+   | - `last_dropped` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error[E0597]: `first_dropped` does not live long enough
+  --> $DIR/issue28498-reject-trait-bound.rs:36:20
+   |
+LL |     foo1 = Foo(1, &first_dropped);
+   |                    ^^^^^^^^^^^^^ borrowed value does not live long enough
+...
+LL | }
+   | - `first_dropped` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/lint-unused-unsafe.rs b/src/test/ui/span/lint-unused-unsafe.rs
new file mode 100644
index 0000000..338fbb9
--- /dev/null
+++ b/src/test/ui/span/lint-unused-unsafe.rs
@@ -0,0 +1,56 @@
+// Exercise the unused_unsafe attribute in some positive and negative cases
+
+#![allow(dead_code)]
+#![deny(unused_unsafe)]
+
+
+mod foo {
+    extern {
+        pub fn bar();
+    }
+}
+
+fn callback<T, F>(_f: F) -> T where F: FnOnce() -> T { panic!() }
+unsafe fn unsf() {}
+
+fn bad1() { unsafe {} }                  //~ ERROR: unnecessary `unsafe` block
+fn bad2() { unsafe { bad1() } }          //~ ERROR: unnecessary `unsafe` block
+unsafe fn bad3() { unsafe {} }           //~ ERROR: unnecessary `unsafe` block
+fn bad4() { unsafe { callback(||{}) } }  //~ ERROR: unnecessary `unsafe` block
+unsafe fn bad5() { unsafe { unsf() } }   //~ ERROR: unnecessary `unsafe` block
+fn bad6() {
+    unsafe {                             // don't put the warning here
+        unsafe {                         //~ ERROR: unnecessary `unsafe` block
+            unsf()
+        }
+    }
+}
+unsafe fn bad7() {
+    unsafe {                             //~ ERROR: unnecessary `unsafe` block
+        unsafe {                         //~ ERROR: unnecessary `unsafe` block
+            unsf()
+        }
+    }
+}
+
+unsafe fn good0() { unsf() }
+fn good1() { unsafe { unsf() } }
+fn good2() {
+    /* bug uncovered when implementing warning about unused unsafe blocks. Be
+       sure that when purity is inherited that the source of the unsafe-ness
+       is tracked correctly */
+    unsafe {
+        unsafe fn what() -> Vec<String> { panic!() }
+
+        callback(|| {
+            what();
+        });
+    }
+}
+
+unsafe fn good3() { foo::bar() }
+fn good4() { unsafe { foo::bar() } }
+
+#[allow(unused_unsafe)] fn allowed() { unsafe {} }
+
+fn main() {}
diff --git a/src/test/ui/span/lint-unused-unsafe.stderr b/src/test/ui/span/lint-unused-unsafe.stderr
new file mode 100644
index 0000000..ac81079
--- /dev/null
+++ b/src/test/ui/span/lint-unused-unsafe.stderr
@@ -0,0 +1,67 @@
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:16:13
+   |
+LL | fn bad1() { unsafe {} }
+   |             ^^^^^^ unnecessary `unsafe` block
+   |
+note: lint level defined here
+  --> $DIR/lint-unused-unsafe.rs:4:9
+   |
+LL | #![deny(unused_unsafe)]
+   |         ^^^^^^^^^^^^^
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:17:13
+   |
+LL | fn bad2() { unsafe { bad1() } }
+   |             ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:18:20
+   |
+LL | unsafe fn bad3() { unsafe {} }
+   | ----------------   ^^^^^^ unnecessary `unsafe` block
+   | |
+   | because it's nested under this `unsafe` fn
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:19:13
+   |
+LL | fn bad4() { unsafe { callback(||{}) } }
+   |             ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:20:20
+   |
+LL | unsafe fn bad5() { unsafe { unsf() } }
+   | ----------------   ^^^^^^ unnecessary `unsafe` block
+   | |
+   | because it's nested under this `unsafe` fn
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:23:9
+   |
+LL |     unsafe {                             // don't put the warning here
+   |     ------ because it's nested under this `unsafe` block
+LL |         unsafe {
+   |         ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:29:5
+   |
+LL | unsafe fn bad7() {
+   | ---------------- because it's nested under this `unsafe` fn
+LL |     unsafe {
+   |     ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:30:9
+   |
+LL | unsafe fn bad7() {
+   | ---------------- because it's nested under this `unsafe` fn
+LL |     unsafe {
+LL |         unsafe {
+   |         ^^^^^^ unnecessary `unsafe` block
+
+error: aborting due to 8 previous errors
+
diff --git a/src/test/ui/span/macro-span-replacement.rs b/src/test/ui/span/macro-span-replacement.rs
new file mode 100644
index 0000000..c5998c1
--- /dev/null
+++ b/src/test/ui/span/macro-span-replacement.rs
@@ -0,0 +1,13 @@
+// compile-pass
+
+#![warn(unused)]
+
+macro_rules! m {
+    ($a:tt $b:tt) => {
+        $b $a; //~ WARN struct is never constructed
+    }
+}
+
+fn main() {
+    m!(S struct);
+}
diff --git a/src/test/ui/span/macro-span-replacement.stderr b/src/test/ui/span/macro-span-replacement.stderr
new file mode 100644
index 0000000..128e4ec
--- /dev/null
+++ b/src/test/ui/span/macro-span-replacement.stderr
@@ -0,0 +1,16 @@
+warning: struct is never constructed: `S`
+  --> $DIR/macro-span-replacement.rs:7:14
+   |
+LL |         $b $a;
+   |              ^
+...
+LL |     m!(S struct);
+   |     ------------- in this macro invocation
+   |
+note: lint level defined here
+  --> $DIR/macro-span-replacement.rs:3:9
+   |
+LL | #![warn(unused)]
+   |         ^^^^^^
+   = note: #[warn(dead_code)] implied by #[warn(unused)]
+
diff --git a/src/test/ui/span/macro-ty-params.rs b/src/test/ui/span/macro-ty-params.rs
new file mode 100644
index 0000000..b077d59
--- /dev/null
+++ b/src/test/ui/span/macro-ty-params.rs
@@ -0,0 +1,14 @@
+macro_rules! m {
+    ($p1: path) => {
+        #[derive($p1)] struct U;
+    }
+}
+
+macro_rules! foo { () => () }
+
+fn main() {
+    foo::<T>!(); //~ ERROR generic arguments in macro path
+    foo::<>!(); //~ ERROR generic arguments in macro path
+    m!(Default<>); //~ ERROR generic arguments in macro path
+    //~^ ERROR unexpected generic arguments in path
+}
diff --git a/src/test/ui/span/macro-ty-params.stderr b/src/test/ui/span/macro-ty-params.stderr
new file mode 100644
index 0000000..39b3edc
--- /dev/null
+++ b/src/test/ui/span/macro-ty-params.stderr
@@ -0,0 +1,26 @@
+error: generic arguments in macro path
+  --> $DIR/macro-ty-params.rs:10:10
+   |
+LL |     foo::<T>!();
+   |          ^^^
+
+error: generic arguments in macro path
+  --> $DIR/macro-ty-params.rs:11:10
+   |
+LL |     foo::<>!();
+   |          ^^
+
+error: unexpected generic arguments in path
+  --> $DIR/macro-ty-params.rs:12:8
+   |
+LL |     m!(Default<>);
+   |        ^^^^^^^^^
+
+error: generic arguments in macro path
+  --> $DIR/macro-ty-params.rs:12:15
+   |
+LL |     m!(Default<>);
+   |               ^^
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/span/method-and-field-eager-resolution.rs b/src/test/ui/span/method-and-field-eager-resolution.rs
new file mode 100644
index 0000000..a38f07d
--- /dev/null
+++ b/src/test/ui/span/method-and-field-eager-resolution.rs
@@ -0,0 +1,15 @@
+// Test that spans get only base in eager type resolution (structurally_resolve_type).
+
+fn main() {
+    let mut x = Default::default();
+    x.0;
+    //~^ ERROR type annotations needed
+    x = 1;
+}
+
+fn foo() {
+    let mut x = Default::default();
+    x[0];
+    //~^ ERROR type annotations needed
+    x = 1;
+}
diff --git a/src/test/ui/span/method-and-field-eager-resolution.stderr b/src/test/ui/span/method-and-field-eager-resolution.stderr
new file mode 100644
index 0000000..0ecbe4c
--- /dev/null
+++ b/src/test/ui/span/method-and-field-eager-resolution.stderr
@@ -0,0 +1,23 @@
+error[E0282]: type annotations needed
+  --> $DIR/method-and-field-eager-resolution.rs:5:5
+   |
+LL |     let mut x = Default::default();
+   |         ----- consider giving `x` a type
+LL |     x.0;
+   |     ^ cannot infer type
+   |
+   = note: type must be known at this point
+
+error[E0282]: type annotations needed
+  --> $DIR/method-and-field-eager-resolution.rs:12:5
+   |
+LL |     let mut x = Default::default();
+   |         ----- consider giving `x` a type
+LL |     x[0];
+   |     ^ cannot infer type
+   |
+   = note: type must be known at this point
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/span/missing-unit-argument.rs b/src/test/ui/span/missing-unit-argument.rs
new file mode 100644
index 0000000..b8fb332
--- /dev/null
+++ b/src/test/ui/span/missing-unit-argument.rs
@@ -0,0 +1,17 @@
+fn foo(():(), ():()) {}
+fn bar(():()) {}
+
+struct S;
+impl S {
+    fn baz(self, (): ()) { }
+    fn generic<T>(self, _: T) { }
+}
+
+fn main() {
+    let _: Result<(), String> = Ok(); //~ ERROR this function takes
+    foo(); //~ ERROR this function takes
+    foo(()); //~ ERROR this function takes
+    bar(); //~ ERROR this function takes
+    S.baz(); //~ ERROR this function takes
+    S.generic::<()>(); //~ ERROR this function takes
+}
diff --git a/src/test/ui/span/missing-unit-argument.stderr b/src/test/ui/span/missing-unit-argument.stderr
new file mode 100644
index 0000000..f1a29be
--- /dev/null
+++ b/src/test/ui/span/missing-unit-argument.stderr
@@ -0,0 +1,70 @@
+error[E0061]: this function takes 1 parameter but 0 parameters were supplied
+  --> $DIR/missing-unit-argument.rs:11:33
+   |
+LL |     let _: Result<(), String> = Ok();
+   |                                 ^^^^
+help: expected the unit value `()`; create it with empty parentheses
+   |
+LL |     let _: Result<(), String> = Ok(());
+   |                                    ^^
+
+error[E0061]: this function takes 2 parameters but 0 parameters were supplied
+  --> $DIR/missing-unit-argument.rs:12:5
+   |
+LL | fn foo(():(), ():()) {}
+   | -------------------- defined here
+...
+LL |     foo();
+   |     ^^^^^ expected 2 parameters
+
+error[E0061]: this function takes 2 parameters but 1 parameter was supplied
+  --> $DIR/missing-unit-argument.rs:13:5
+   |
+LL | fn foo(():(), ():()) {}
+   | -------------------- defined here
+...
+LL |     foo(());
+   |     ^^^^^^^ expected 2 parameters
+
+error[E0061]: this function takes 1 parameter but 0 parameters were supplied
+  --> $DIR/missing-unit-argument.rs:14:5
+   |
+LL | fn bar(():()) {}
+   | ------------- defined here
+...
+LL |     bar();
+   |     ^^^^^
+help: expected the unit value `()`; create it with empty parentheses
+   |
+LL |     bar(());
+   |         ^^
+
+error[E0061]: this function takes 1 parameter but 0 parameters were supplied
+  --> $DIR/missing-unit-argument.rs:15:7
+   |
+LL |     fn baz(self, (): ()) { }
+   |     -------------------- defined here
+...
+LL |     S.baz();
+   |       ^^^
+help: expected the unit value `()`; create it with empty parentheses
+   |
+LL |     S.baz(());
+   |           ^^
+
+error[E0061]: this function takes 1 parameter but 0 parameters were supplied
+  --> $DIR/missing-unit-argument.rs:16:7
+   |
+LL |     fn generic<T>(self, _: T) { }
+   |     ------------------------- defined here
+...
+LL |     S.generic::<()>();
+   |       ^^^^^^^
+help: expected the unit value `()`; create it with empty parentheses
+   |
+LL |     S.generic::<()>(());
+   |                     ^^
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0061`.
diff --git a/src/test/ui/span/move-closure.rs b/src/test/ui/span/move-closure.rs
new file mode 100644
index 0000000..bdd7951
--- /dev/null
+++ b/src/test/ui/span/move-closure.rs
@@ -0,0 +1,6 @@
+// Regression test for issue #24986
+// Make sure that the span of a closure marked `move` begins at the `move` keyword.
+
+fn main() {
+    let x: () = move || (); //~ ERROR mismatched types
+}
diff --git a/src/test/ui/span/move-closure.stderr b/src/test/ui/span/move-closure.stderr
new file mode 100644
index 0000000..e2226b1
--- /dev/null
+++ b/src/test/ui/span/move-closure.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/move-closure.rs:5:17
+   |
+LL |     let x: () = move || ();
+   |                 ^^^^^^^^^^ expected (), found closure
+   |
+   = note: expected type `()`
+              found type `[closure@$DIR/move-closure.rs:5:17: 5:27]`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/span/multiline-span-E0072.rs b/src/test/ui/span/multiline-span-E0072.rs
new file mode 100644
index 0000000..728b47d
--- /dev/null
+++ b/src/test/ui/span/multiline-span-E0072.rs
@@ -0,0 +1,10 @@
+// It should just use the entire body instead of pointing at the next two lines
+struct //~ ERROR has infinite size
+ListNode
+{
+    head: u8,
+    tail: Option<ListNode>,
+}
+
+fn main() {
+}
diff --git a/src/test/ui/span/multiline-span-E0072.stderr b/src/test/ui/span/multiline-span-E0072.stderr
new file mode 100644
index 0000000..dd322fe
--- /dev/null
+++ b/src/test/ui/span/multiline-span-E0072.stderr
@@ -0,0 +1,17 @@
+error[E0072]: recursive type `ListNode` has infinite size
+  --> $DIR/multiline-span-E0072.rs:2:1
+   |
+LL | / struct
+LL | | ListNode
+LL | | {
+LL | |     head: u8,
+LL | |     tail: Option<ListNode>,
+   | |     ---------------------- recursive without indirection
+LL | | }
+   | |_^ recursive type has infinite size
+   |
+   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `ListNode` representable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0072`.
diff --git a/src/test/ui/span/multiline-span-simple.rs b/src/test/ui/span/multiline-span-simple.rs
new file mode 100644
index 0000000..204a7f6
--- /dev/null
+++ b/src/test/ui/span/multiline-span-simple.rs
@@ -0,0 +1,20 @@
+fn foo(a: u32, b: u32) {
+    a + b;
+}
+
+fn bar(a: u32, b: u32) {
+    a + b;
+}
+
+fn main() {
+    let x = 1;
+    let y = 2;
+    let z = 3;
+    foo(1 as u32 + //~ ERROR cannot add `()` to `u32`
+
+        bar(x,
+
+            y),
+
+        z)
+}
diff --git a/src/test/ui/span/multiline-span-simple.stderr b/src/test/ui/span/multiline-span-simple.stderr
new file mode 100644
index 0000000..6495d9b
--- /dev/null
+++ b/src/test/ui/span/multiline-span-simple.stderr
@@ -0,0 +1,11 @@
+error[E0277]: cannot add `()` to `u32`
+  --> $DIR/multiline-span-simple.rs:13:18
+   |
+LL |     foo(1 as u32 +
+   |                  ^ no implementation for `u32 + ()`
+   |
+   = help: the trait `std::ops::Add<()>` is not implemented for `u32`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/span/multispan-import-lint.rs b/src/test/ui/span/multispan-import-lint.rs
new file mode 100644
index 0000000..753c359
--- /dev/null
+++ b/src/test/ui/span/multispan-import-lint.rs
@@ -0,0 +1,10 @@
+// compile-pass
+
+#![warn(unused)]
+
+use std::cmp::{Eq, Ord, min, PartialEq, PartialOrd};
+//~^ WARN unused imports
+
+fn main() {
+    let _ = min(1, 2);
+}
diff --git a/src/test/ui/span/multispan-import-lint.stderr b/src/test/ui/span/multispan-import-lint.stderr
new file mode 100644
index 0000000..a730d08
--- /dev/null
+++ b/src/test/ui/span/multispan-import-lint.stderr
@@ -0,0 +1,13 @@
+warning: unused imports: `Eq`, `Ord`, `PartialEq`, `PartialOrd`
+  --> $DIR/multispan-import-lint.rs:5:16
+   |
+LL | use std::cmp::{Eq, Ord, min, PartialEq, PartialOrd};
+   |                ^^  ^^^       ^^^^^^^^^  ^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/multispan-import-lint.rs:3:9
+   |
+LL | #![warn(unused)]
+   |         ^^^^^^
+   = note: #[warn(unused_imports)] implied by #[warn(unused)]
+
diff --git a/src/test/ui/span/mut-arg-hint.nll.stderr b/src/test/ui/span/mut-arg-hint.nll.stderr
new file mode 100644
index 0000000..8027cf6
--- /dev/null
+++ b/src/test/ui/span/mut-arg-hint.nll.stderr
@@ -0,0 +1,27 @@
+error[E0596]: cannot borrow `*a` as mutable, as it is behind a `&` reference
+  --> $DIR/mut-arg-hint.rs:3: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");
+   |         ^ `a` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+
+error[E0596]: cannot borrow `*a` as mutable, as it is behind a `&` reference
+  --> $DIR/mut-arg-hint.rs:8:5
+   |
+LL | pub fn foo<'a>(mut a: &'a String) {
+   |                       ---------- help: consider changing this to be a mutable reference: `&'a mut String`
+LL |     a.push_str("foo");
+   |     ^ `a` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+
+error[E0596]: cannot borrow `*a` as mutable, as it is behind a `&` reference
+  --> $DIR/mut-arg-hint.rs:15: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");
+   |         ^ `a` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/span/mut-arg-hint.rs b/src/test/ui/span/mut-arg-hint.rs
new file mode 100644
index 0000000..3d46613
--- /dev/null
+++ b/src/test/ui/span/mut-arg-hint.rs
@@ -0,0 +1,22 @@
+trait B {
+    fn foo(mut a: &String) {
+        a.push_str("bar"); //~ ERROR cannot borrow immutable borrowed content
+    }
+}
+
+pub fn foo<'a>(mut a: &'a String) {
+    a.push_str("foo"); //~ ERROR cannot borrow immutable borrowed content
+}
+
+struct A {}
+
+impl A {
+    pub fn foo(mut a: &String) {
+        a.push_str("foo"); //~ ERROR cannot borrow immutable borrowed content
+    }
+}
+
+fn main() {
+    foo(&"a".to_string());
+    A::foo(&"a".to_string());
+}
diff --git a/src/test/ui/span/mut-arg-hint.stderr b/src/test/ui/span/mut-arg-hint.stderr
new file mode 100644
index 0000000..ce57861
--- /dev/null
+++ b/src/test/ui/span/mut-arg-hint.stderr
@@ -0,0 +1,27 @@
+error[E0596]: cannot borrow immutable borrowed content `*a` as mutable
+  --> $DIR/mut-arg-hint.rs:3:9
+   |
+LL |     fn foo(mut a: &String) {
+   |                   ------- use `&mut String` here to make mutable
+LL |         a.push_str("bar");
+   |         ^ cannot borrow as mutable
+
+error[E0596]: cannot borrow immutable borrowed content `*a` as mutable
+  --> $DIR/mut-arg-hint.rs:8:5
+   |
+LL | pub fn foo<'a>(mut a: &'a String) {
+   |                       ---------- use `&'a mut String` here to make mutable
+LL |     a.push_str("foo");
+   |     ^ cannot borrow as mutable
+
+error[E0596]: cannot borrow immutable borrowed content `*a` as mutable
+  --> $DIR/mut-arg-hint.rs:15:9
+   |
+LL |     pub fn foo(mut a: &String) {
+   |                       ------- use `&mut String` here to make mutable
+LL |         a.push_str("foo");
+   |         ^ cannot borrow as mutable
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/span/mut-ptr-cant-outlive-ref.nll.stderr b/src/test/ui/span/mut-ptr-cant-outlive-ref.nll.stderr
new file mode 100644
index 0000000..21b2946
--- /dev/null
+++ b/src/test/ui/span/mut-ptr-cant-outlive-ref.nll.stderr
@@ -0,0 +1,14 @@
+error[E0597]: `b` does not live long enough
+  --> $DIR/mut-ptr-cant-outlive-ref.rs:8:15
+   |
+LL |         p = &*b;
+   |               ^ borrowed value does not live long enough
+LL |     }
+   |     - `b` dropped here while still borrowed
+LL |
+LL |     p.use_ref();
+   |     - borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/mut-ptr-cant-outlive-ref.rs b/src/test/ui/span/mut-ptr-cant-outlive-ref.rs
new file mode 100644
index 0000000..b8c752d
--- /dev/null
+++ b/src/test/ui/span/mut-ptr-cant-outlive-ref.rs
@@ -0,0 +1,15 @@
+use std::cell::RefCell;
+
+fn main() {
+    let m = RefCell::new(0);
+    let p;
+    {
+        let b = m.borrow();
+        p = &*b;
+    }
+    //~^^ ERROR `b` does not live long enough
+    p.use_ref();
+}
+
+trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { }  }
+impl<T> Fake for T { }
diff --git a/src/test/ui/span/mut-ptr-cant-outlive-ref.stderr b/src/test/ui/span/mut-ptr-cant-outlive-ref.stderr
new file mode 100644
index 0000000..f6cf568
--- /dev/null
+++ b/src/test/ui/span/mut-ptr-cant-outlive-ref.stderr
@@ -0,0 +1,14 @@
+error[E0597]: `b` does not live long enough
+  --> $DIR/mut-ptr-cant-outlive-ref.rs:8:15
+   |
+LL |         p = &*b;
+   |               ^ borrowed value does not live long enough
+LL |     }
+   |     - `b` dropped here while still borrowed
+...
+LL | }
+   | - borrowed value needs to live until here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/non-existing-module-import.rs b/src/test/ui/span/non-existing-module-import.rs
new file mode 100644
index 0000000..d2ce7ec
--- /dev/null
+++ b/src/test/ui/span/non-existing-module-import.rs
@@ -0,0 +1,3 @@
+use std::bar::{foo1, foo2}; //~ ERROR unresolved import
+
+fn main() {}
diff --git a/src/test/ui/span/non-existing-module-import.stderr b/src/test/ui/span/non-existing-module-import.stderr
new file mode 100644
index 0000000..25c0995
--- /dev/null
+++ b/src/test/ui/span/non-existing-module-import.stderr
@@ -0,0 +1,9 @@
+error[E0432]: unresolved import `std::bar`
+  --> $DIR/non-existing-module-import.rs:1:10
+   |
+LL | use std::bar::{foo1, foo2};
+   |          ^^^ could not find `bar` in `std`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/span/pub-struct-field.rs b/src/test/ui/span/pub-struct-field.rs
new file mode 100644
index 0000000..e149b9d
--- /dev/null
+++ b/src/test/ui/span/pub-struct-field.rs
@@ -0,0 +1,10 @@
+// Regression test for issue #26083 and #35435
+// Test that span for public struct fields start at `pub`
+
+struct Foo {
+    bar: u8,
+    pub bar: u8, //~ ERROR is already declared
+    pub(crate) bar: u8, //~ ERROR is already declared
+}
+
+fn main() {}
diff --git a/src/test/ui/span/pub-struct-field.stderr b/src/test/ui/span/pub-struct-field.stderr
new file mode 100644
index 0000000..065340f
--- /dev/null
+++ b/src/test/ui/span/pub-struct-field.stderr
@@ -0,0 +1,20 @@
+error[E0124]: field `bar` is already declared
+  --> $DIR/pub-struct-field.rs:6:5
+   |
+LL |     bar: u8,
+   |     ------- `bar` first declared here
+LL |     pub bar: u8,
+   |     ^^^^^^^^^^^ field already declared
+
+error[E0124]: field `bar` is already declared
+  --> $DIR/pub-struct-field.rs:7:5
+   |
+LL |     bar: u8,
+   |     ------- `bar` first declared here
+LL |     pub bar: u8,
+LL |     pub(crate) bar: u8,
+   |     ^^^^^^^^^^^^^^^^^^ field already declared
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0124`.
diff --git a/src/test/ui/span/range-2.nll.stderr b/src/test/ui/span/range-2.nll.stderr
new file mode 100644
index 0000000..8ca8156
--- /dev/null
+++ b/src/test/ui/span/range-2.nll.stderr
@@ -0,0 +1,25 @@
+error[E0597]: `a` does not live long enough
+  --> $DIR/range-2.rs:7:9
+   |
+LL |     let r = {
+   |         - borrow later stored here
+...
+LL |         &a..&b
+   |         ^^ borrowed value does not live long enough
+LL |     };
+   |     - `a` dropped here while still borrowed
+
+error[E0597]: `b` does not live long enough
+  --> $DIR/range-2.rs:7:13
+   |
+LL |     let r = {
+   |         - borrow later stored here
+...
+LL |         &a..&b
+   |             ^^ borrowed value does not live long enough
+LL |     };
+   |     - `b` dropped here while still borrowed
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/range-2.rs b/src/test/ui/span/range-2.rs
new file mode 100644
index 0000000..c4bb16f
--- /dev/null
+++ b/src/test/ui/span/range-2.rs
@@ -0,0 +1,15 @@
+// Test range syntax - borrow errors.
+#![feature(rustc_attrs)]
+pub fn main() { #![rustc_error] // rust-lang/rust#49855
+    let r = {
+        let a = 42;
+        let b = 42;
+        &a..&b
+    };
+    //~^^ ERROR `a` does not live long enough
+    //~| ERROR `b` does not live long enough
+    r.use_ref();
+}
+
+trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { }  }
+impl<T> Fake for T { }
diff --git a/src/test/ui/span/range-2.stderr b/src/test/ui/span/range-2.stderr
new file mode 100644
index 0000000..7d0edd6
--- /dev/null
+++ b/src/test/ui/span/range-2.stderr
@@ -0,0 +1,25 @@
+error[E0597]: `a` does not live long enough
+  --> $DIR/range-2.rs:7:10
+   |
+LL |         &a..&b
+   |          ^ borrowed value does not live long enough
+LL |     };
+   |     - `a` dropped here while still borrowed
+...
+LL | }
+   | - borrowed value needs to live until here
+
+error[E0597]: `b` does not live long enough
+  --> $DIR/range-2.rs:7:14
+   |
+LL |         &a..&b
+   |              ^ borrowed value does not live long enough
+LL |     };
+   |     - `b` dropped here while still borrowed
+...
+LL | }
+   | - borrowed value needs to live until here
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/recursive-type-field.rs b/src/test/ui/span/recursive-type-field.rs
new file mode 100644
index 0000000..58ea81b
--- /dev/null
+++ b/src/test/ui/span/recursive-type-field.rs
@@ -0,0 +1,18 @@
+use std::rc::Rc;
+
+struct Foo<'a> { //~ ERROR recursive type
+    bar: Bar<'a>,
+    b: Rc<Bar<'a>>,
+}
+
+struct Bar<'a> { //~ ERROR recursive type
+    y: (Foo<'a>, Foo<'a>),
+    z: Option<Bar<'a>>,
+    a: &'a Foo<'a>,
+    c: &'a [Bar<'a>],
+    d: [Bar<'a>; 1],
+    e: Foo<'a>,
+    x: Bar<'a>,
+}
+
+fn main() {}
diff --git a/src/test/ui/span/recursive-type-field.stderr b/src/test/ui/span/recursive-type-field.stderr
new file mode 100644
index 0000000..d240872
--- /dev/null
+++ b/src/test/ui/span/recursive-type-field.stderr
@@ -0,0 +1,32 @@
+error[E0072]: recursive type `Foo` has infinite size
+  --> $DIR/recursive-type-field.rs:3:1
+   |
+LL | struct Foo<'a> {
+   | ^^^^^^^^^^^^^^ recursive type has infinite size
+LL |     bar: Bar<'a>,
+   |     ------------ recursive without indirection
+   |
+   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Foo` representable
+
+error[E0072]: recursive type `Bar` has infinite size
+  --> $DIR/recursive-type-field.rs:8:1
+   |
+LL | struct Bar<'a> {
+   | ^^^^^^^^^^^^^^ recursive type has infinite size
+LL |     y: (Foo<'a>, Foo<'a>),
+   |     --------------------- recursive without indirection
+LL |     z: Option<Bar<'a>>,
+   |     ------------------ recursive without indirection
+...
+LL |     d: [Bar<'a>; 1],
+   |     --------------- recursive without indirection
+LL |     e: Foo<'a>,
+   |     ---------- recursive without indirection
+LL |     x: Bar<'a>,
+   |     ---------- recursive without indirection
+   |
+   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Bar` representable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0072`.
diff --git a/src/test/ui/span/regionck-unboxed-closure-lifetimes.nll.stderr b/src/test/ui/span/regionck-unboxed-closure-lifetimes.nll.stderr
new file mode 100644
index 0000000..8e9cd59
--- /dev/null
+++ b/src/test/ui/span/regionck-unboxed-closure-lifetimes.nll.stderr
@@ -0,0 +1,14 @@
+error[E0597]: `c` does not live long enough
+  --> $DIR/regionck-unboxed-closure-lifetimes.rs:8:21
+   |
+LL |         let c_ref = &c;
+   |                     ^^ borrowed value does not live long enough
+...
+LL |     }
+   |     - `c` dropped here while still borrowed
+LL |     f.use_mut();
+   |     - borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/regionck-unboxed-closure-lifetimes.rs b/src/test/ui/span/regionck-unboxed-closure-lifetimes.rs
new file mode 100644
index 0000000..60ccaa8
--- /dev/null
+++ b/src/test/ui/span/regionck-unboxed-closure-lifetimes.rs
@@ -0,0 +1,16 @@
+#![feature(rustc_attrs)]
+use std::ops::FnMut;
+
+fn main() { #![rustc_error] // rust-lang/rust#49855
+    let mut f;
+    {
+        let c = 1;
+        let c_ref = &c;
+        //~^ ERROR `c` does not live long enough
+        f = move |a: isize, b: isize| { a + b + *c_ref };
+    }
+    f.use_mut();
+}
+
+trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { }  }
+impl<T> Fake for T { }
diff --git a/src/test/ui/span/regionck-unboxed-closure-lifetimes.stderr b/src/test/ui/span/regionck-unboxed-closure-lifetimes.stderr
new file mode 100644
index 0000000..b3f0966
--- /dev/null
+++ b/src/test/ui/span/regionck-unboxed-closure-lifetimes.stderr
@@ -0,0 +1,15 @@
+error[E0597]: `c` does not live long enough
+  --> $DIR/regionck-unboxed-closure-lifetimes.rs:8:22
+   |
+LL |         let c_ref = &c;
+   |                      ^ borrowed value does not live long enough
+...
+LL |     }
+   |     - `c` dropped here while still borrowed
+LL |     f.use_mut();
+LL | }
+   | - borrowed value needs to live until here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.nll.stderr b/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.nll.stderr
new file mode 100644
index 0000000..2be2d0f
--- /dev/null
+++ b/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.nll.stderr
@@ -0,0 +1,16 @@
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/regions-close-over-borrowed-ref-in-obj.rs:12:27
+   |
+LL |         let ss: &isize = &id(1);
+   |                           ^^^^^ creates a temporary which is freed while still in use
+...
+LL |     }
+   |     - temporary value is freed at the end of this statement
+LL | }
+   | - borrow might be used here, when `blah` is dropped and runs the destructor for type `std::boxed::Box<dyn Foo>`
+   |
+   = note: consider using a `let` binding to create a longer lived value
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.rs b/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.rs
new file mode 100644
index 0000000..9ca352a
--- /dev/null
+++ b/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.rs
@@ -0,0 +1,16 @@
+#![feature(box_syntax)]
+
+fn id<T>(x: T) -> T { x }
+
+trait Foo { }
+
+impl<'a> Foo for &'a isize { }
+
+fn main() {
+    let blah;
+    {
+        let ss: &isize = &id(1);
+        //~^ ERROR borrowed value does not live long enough
+        blah = box ss as Box<Foo>;
+    }
+}
diff --git a/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.stderr b/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.stderr
new file mode 100644
index 0000000..8a853e7
--- /dev/null
+++ b/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.stderr
@@ -0,0 +1,14 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/regions-close-over-borrowed-ref-in-obj.rs:12:27
+   |
+LL |         let ss: &isize = &id(1);
+   |                           ^^^^^ temporary value does not live long enough
+...
+LL |     }
+   |     - temporary value dropped here while still borrowed
+LL | }
+   | - temporary value needs to live until here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/regions-close-over-type-parameter-2.nll.stderr b/src/test/ui/span/regions-close-over-type-parameter-2.nll.stderr
new file mode 100644
index 0000000..2e584d9
--- /dev/null
+++ b/src/test/ui/span/regions-close-over-type-parameter-2.nll.stderr
@@ -0,0 +1,13 @@
+error[E0597]: `tmp0` does not live long enough
+  --> $DIR/regions-close-over-type-parameter-2.rs:23:20
+   |
+LL |         let tmp1 = &tmp0;
+   |                    ^^^^^ borrowed value does not live long enough
+LL |         repeater3(tmp1)
+   |         --------------- borrow later captured here by trait object
+LL |     };
+   |     - `tmp0` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/regions-close-over-type-parameter-2.rs b/src/test/ui/span/regions-close-over-type-parameter-2.rs
new file mode 100644
index 0000000..11187b7
--- /dev/null
+++ b/src/test/ui/span/regions-close-over-type-parameter-2.rs
@@ -0,0 +1,27 @@
+#![feature(box_syntax)]
+
+// Test for what happens when a type parameter `A` is closed over into
+// an object. This should yield errors unless `A` (and the object)
+// both have suitable bounds.
+
+trait Foo { fn get(&self); }
+
+impl<A> Foo for A {
+    fn get(&self) { }
+}
+
+fn repeater3<'a,A:'a>(v: A) -> Box<Foo+'a> {
+    box v as Box<Foo+'a>
+}
+
+fn main() {
+    // Error results because the type of is inferred to be
+    // ~Repeat<&'blk isize> where blk is the lifetime of the block below.
+
+    let _ = {
+        let tmp0 = 3;
+        let tmp1 = &tmp0;
+        repeater3(tmp1)
+    };
+    //~^^^ ERROR `tmp0` does not live long enough
+}
diff --git a/src/test/ui/span/regions-close-over-type-parameter-2.stderr b/src/test/ui/span/regions-close-over-type-parameter-2.stderr
new file mode 100644
index 0000000..5ee155c
--- /dev/null
+++ b/src/test/ui/span/regions-close-over-type-parameter-2.stderr
@@ -0,0 +1,14 @@
+error[E0597]: `tmp0` does not live long enough
+  --> $DIR/regions-close-over-type-parameter-2.rs:23:21
+   |
+LL |         let tmp1 = &tmp0;
+   |                     ^^^^ borrowed value does not live long enough
+LL |         repeater3(tmp1)
+LL |     };
+   |     -- borrowed value needs to live until here
+   |     |
+   |     `tmp0` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/regions-escape-loop-via-variable.nll.stderr b/src/test/ui/span/regions-escape-loop-via-variable.nll.stderr
new file mode 100644
index 0000000..42df668
--- /dev/null
+++ b/src/test/ui/span/regions-escape-loop-via-variable.nll.stderr
@@ -0,0 +1,13 @@
+error[E0597]: `x` does not live long enough
+  --> $DIR/regions-escape-loop-via-variable.rs:11:13
+   |
+LL |         let x = 1 + *p;
+   |                     -- borrow later used here
+LL |         p = &x;
+   |             ^^ borrowed value does not live long enough
+LL |     }
+   |     - `x` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/regions-escape-loop-via-variable.rs b/src/test/ui/span/regions-escape-loop-via-variable.rs
new file mode 100644
index 0000000..ad46889
--- /dev/null
+++ b/src/test/ui/span/regions-escape-loop-via-variable.rs
@@ -0,0 +1,14 @@
+fn main() {
+    let x = 3;
+
+    // Here, the variable `p` gets inferred to a type with a lifetime
+    // of the loop body.  The regionck then determines that this type
+    // is invalid.
+    let mut p = &x;
+
+    loop {
+        let x = 1 + *p;
+        p = &x;
+    }
+    //~^^ ERROR `x` does not live long enough
+}
diff --git a/src/test/ui/span/regions-escape-loop-via-variable.stderr b/src/test/ui/span/regions-escape-loop-via-variable.stderr
new file mode 100644
index 0000000..ef36b81
--- /dev/null
+++ b/src/test/ui/span/regions-escape-loop-via-variable.stderr
@@ -0,0 +1,14 @@
+error[E0597]: `x` does not live long enough
+  --> $DIR/regions-escape-loop-via-variable.rs:11:14
+   |
+LL |         p = &x;
+   |              ^ borrowed value does not live long enough
+LL |     }
+   |     - `x` dropped here while still borrowed
+LL |
+LL | }
+   | - borrowed value needs to live until here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/regions-escape-loop-via-vec.nll.stderr b/src/test/ui/span/regions-escape-loop-via-vec.nll.stderr
new file mode 100644
index 0000000..284981e
--- /dev/null
+++ b/src/test/ui/span/regions-escape-loop-via-vec.nll.stderr
@@ -0,0 +1,49 @@
+error[E0503]: cannot use `x` because it was mutably borrowed
+  --> $DIR/regions-escape-loop-via-vec.rs:5:11
+   |
+LL |     let mut _y = vec![&mut x];
+   |                       ------ borrow of `x` occurs here
+LL |     while x < 10 {
+   |           ^ use of borrowed `x`
+LL |         let mut z = x;
+LL |         _y.push(&mut z);
+   |         -- borrow later used here
+
+error[E0503]: cannot use `x` because it was mutably borrowed
+  --> $DIR/regions-escape-loop-via-vec.rs:6:21
+   |
+LL |     let mut _y = vec![&mut x];
+   |                       ------ borrow of `x` occurs here
+LL |     while x < 10 {
+LL |         let mut z = x;
+   |                     ^ use of borrowed `x`
+LL |         _y.push(&mut z);
+   |         -- borrow later used here
+
+error[E0597]: `z` does not live long enough
+  --> $DIR/regions-escape-loop-via-vec.rs:7:17
+   |
+LL |         _y.push(&mut z);
+   |         --      ^^^^^^ borrowed value does not live long enough
+   |         |
+   |         borrow later used here
+...
+LL |     }
+   |     - `z` dropped here while still borrowed
+
+error[E0503]: cannot use `x` because it was mutably borrowed
+  --> $DIR/regions-escape-loop-via-vec.rs:9:9
+   |
+LL |     let mut _y = vec![&mut x];
+   |                       ------ borrow of `x` occurs here
+...
+LL |         _y.push(&mut z);
+   |         -- borrow later used here
+LL |
+LL |         x += 1;
+   |         ^^^^^^ use of borrowed `x`
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0503, E0597.
+For more information about an error, try `rustc --explain E0503`.
diff --git a/src/test/ui/span/regions-escape-loop-via-vec.rs b/src/test/ui/span/regions-escape-loop-via-vec.rs
new file mode 100644
index 0000000..52f3dc3
--- /dev/null
+++ b/src/test/ui/span/regions-escape-loop-via-vec.rs
@@ -0,0 +1,13 @@
+// The type of `y` ends up getting inferred to the type of the block.
+fn broken() {
+    let mut x = 3;
+    let mut _y = vec![&mut x];
+    while x < 10 { //~ ERROR cannot use `x` because it was mutably borrowed
+        let mut z = x; //~ ERROR cannot use `x` because it was mutably borrowed
+        _y.push(&mut z);
+        //~^ ERROR `z` does not live long enough
+        x += 1; //~ ERROR cannot assign
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/span/regions-escape-loop-via-vec.stderr b/src/test/ui/span/regions-escape-loop-via-vec.stderr
new file mode 100644
index 0000000..1d604b5
--- /dev/null
+++ b/src/test/ui/span/regions-escape-loop-via-vec.stderr
@@ -0,0 +1,41 @@
+error[E0597]: `z` does not live long enough
+  --> $DIR/regions-escape-loop-via-vec.rs:7:22
+   |
+LL |         _y.push(&mut z);
+   |                      ^ borrowed value does not live long enough
+...
+LL |     }
+   |     - `z` dropped here while still borrowed
+LL | }
+   | - borrowed value needs to live until here
+
+error[E0503]: cannot use `x` because it was mutably borrowed
+  --> $DIR/regions-escape-loop-via-vec.rs:5:11
+   |
+LL |     let mut _y = vec![&mut x];
+   |                            - borrow of `x` occurs here
+LL |     while x < 10 {
+   |           ^ use of borrowed `x`
+
+error[E0503]: cannot use `x` because it was mutably borrowed
+  --> $DIR/regions-escape-loop-via-vec.rs:6:13
+   |
+LL |     let mut _y = vec![&mut x];
+   |                            - borrow of `x` occurs here
+LL |     while x < 10 {
+LL |         let mut z = x;
+   |             ^^^^^ use of borrowed `x`
+
+error[E0506]: cannot assign to `x` because it is borrowed
+  --> $DIR/regions-escape-loop-via-vec.rs:9:9
+   |
+LL |     let mut _y = vec![&mut x];
+   |                            - borrow of `x` occurs here
+...
+LL |         x += 1;
+   |         ^^^^^^ assignment to borrowed `x` occurs here
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0503, E0506, E0597.
+For more information about an error, try `rustc --explain E0503`.
diff --git a/src/test/ui/span/regions-infer-borrow-scope-within-loop.nll.stderr b/src/test/ui/span/regions-infer-borrow-scope-within-loop.nll.stderr
new file mode 100644
index 0000000..fd67c65
--- /dev/null
+++ b/src/test/ui/span/regions-infer-borrow-scope-within-loop.nll.stderr
@@ -0,0 +1,14 @@
+error[E0597]: `*x` does not live long enough
+  --> $DIR/regions-infer-borrow-scope-within-loop.rs:13:20
+   |
+LL |         y = borrow(&*x);
+   |                    ^^^ borrowed value does not live long enough
+...
+LL |     }
+   |     - `*x` dropped here while still borrowed
+LL |     assert!(*y != 0);
+   |             -- borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/regions-infer-borrow-scope-within-loop.rs b/src/test/ui/span/regions-infer-borrow-scope-within-loop.rs
new file mode 100644
index 0000000..3b20285
--- /dev/null
+++ b/src/test/ui/span/regions-infer-borrow-scope-within-loop.rs
@@ -0,0 +1,22 @@
+fn borrow<T>(x: &T) -> &T {x}
+
+fn foo<C, M>(mut cond: C, mut make_box: M) where
+    C: FnMut() -> bool,
+    M: FnMut() -> Box<isize>,
+{
+    let mut y: &isize;
+    loop {
+        let x = make_box();
+
+        // Here we complain because the resulting region
+        // of this borrow is the fn body as a whole.
+        y = borrow(&*x);
+        //~^ ERROR `*x` does not live long enough
+
+        assert_eq!(*x, *y);
+        if cond() { break; }
+    }
+    assert!(*y != 0);
+}
+
+fn main() {}
diff --git a/src/test/ui/span/regions-infer-borrow-scope-within-loop.stderr b/src/test/ui/span/regions-infer-borrow-scope-within-loop.stderr
new file mode 100644
index 0000000..94abbce
--- /dev/null
+++ b/src/test/ui/span/regions-infer-borrow-scope-within-loop.stderr
@@ -0,0 +1,15 @@
+error[E0597]: `*x` does not live long enough
+  --> $DIR/regions-infer-borrow-scope-within-loop.rs:13:21
+   |
+LL |         y = borrow(&*x);
+   |                     ^^ borrowed value does not live long enough
+...
+LL |     }
+   |     - `*x` dropped here while still borrowed
+LL |     assert!(*y != 0);
+LL | }
+   | - borrowed value needs to live until here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/send-is-not-static-ensures-scoping.nll.stderr b/src/test/ui/span/send-is-not-static-ensures-scoping.nll.stderr
new file mode 100644
index 0000000..65d10c1
--- /dev/null
+++ b/src/test/ui/span/send-is-not-static-ensures-scoping.nll.stderr
@@ -0,0 +1,29 @@
+error[E0597]: `x` does not live long enough
+  --> $DIR/send-is-not-static-ensures-scoping.rs:16:17
+   |
+LL |     let bad = {
+   |         --- borrow later stored here
+LL |         let x = 1;
+LL |         let y = &x;
+   |                 ^^ borrowed value does not live long enough
+...
+LL |     };
+   |     - `x` dropped here while still borrowed
+
+error[E0597]: `y` does not live long enough
+  --> $DIR/send-is-not-static-ensures-scoping.rs:20:22
+   |
+LL |     let bad = {
+   |         --- borrow later stored here
+...
+LL |         scoped(|| {
+   |                -- value captured here
+LL |             let _z = y;
+   |                      ^ borrowed value does not live long enough
+...
+LL |     };
+   |     - `y` dropped here while still borrowed
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/send-is-not-static-ensures-scoping.rs b/src/test/ui/span/send-is-not-static-ensures-scoping.rs
new file mode 100644
index 0000000..ac07420
--- /dev/null
+++ b/src/test/ui/span/send-is-not-static-ensures-scoping.rs
@@ -0,0 +1,26 @@
+struct Guard<'a> {
+    f: Box<Fn() + Send + 'a>,
+}
+
+fn scoped<'a, F: Fn() + Send + 'a>(f: F) -> Guard<'a> {
+    Guard { f: Box::new(f) }
+}
+
+impl<'a> Guard<'a> {
+    fn join(self) {}
+}
+
+fn main() {
+    let bad = {
+        let x = 1;
+        let y = &x;
+        //~^ ERROR `x` does not live long enough
+
+        scoped(|| {
+            let _z = y;
+            //~^ ERROR `y` does not live long enough
+        })
+    };
+
+    bad.join();
+}
diff --git a/src/test/ui/span/send-is-not-static-ensures-scoping.stderr b/src/test/ui/span/send-is-not-static-ensures-scoping.stderr
new file mode 100644
index 0000000..4702628
--- /dev/null
+++ b/src/test/ui/span/send-is-not-static-ensures-scoping.stderr
@@ -0,0 +1,29 @@
+error[E0597]: `x` does not live long enough
+  --> $DIR/send-is-not-static-ensures-scoping.rs:16:18
+   |
+LL |         let y = &x;
+   |                  ^ borrowed value does not live long enough
+...
+LL |     };
+   |     - `x` dropped here while still borrowed
+...
+LL | }
+   | - borrowed value needs to live until here
+
+error[E0597]: `y` does not live long enough
+  --> $DIR/send-is-not-static-ensures-scoping.rs:20:22
+   |
+LL |         scoped(|| {
+   |                -- capture occurs here
+LL |             let _z = y;
+   |                      ^ borrowed value does not live long enough
+...
+LL |     };
+   |     - borrowed value only lives until here
+...
+LL | }
+   | - borrowed value needs to live until here
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/send-is-not-static-std-sync-2.nll.stderr b/src/test/ui/span/send-is-not-static-std-sync-2.nll.stderr
new file mode 100644
index 0000000..bcd07e1
--- /dev/null
+++ b/src/test/ui/span/send-is-not-static-std-sync-2.nll.stderr
@@ -0,0 +1,37 @@
+error[E0597]: `x` does not live long enough
+  --> $DIR/send-is-not-static-std-sync-2.rs:11:20
+   |
+LL |     let lock = {
+   |         ---- borrow later stored here
+LL |         let x = 1;
+LL |         Mutex::new(&x)
+   |                    ^^ borrowed value does not live long enough
+LL |     };
+   |     - `x` dropped here while still borrowed
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/send-is-not-static-std-sync-2.rs:21:21
+   |
+LL |     let lock = {
+   |         ---- borrow later stored here
+LL |         let x = 1;
+LL |         RwLock::new(&x)
+   |                     ^^ borrowed value does not live long enough
+LL |     };
+   |     - `x` dropped here while still borrowed
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/send-is-not-static-std-sync-2.rs:31:25
+   |
+LL |     let (_tx, rx) = {
+   |          --- borrow later used here
+...
+LL |         let _ = tx.send(&x);
+   |                         ^^ borrowed value does not live long enough
+LL |         (tx, rx)
+LL |     };
+   |     - `x` dropped here while still borrowed
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/send-is-not-static-std-sync-2.rs b/src/test/ui/span/send-is-not-static-std-sync-2.rs
new file mode 100644
index 0000000..38746d4
--- /dev/null
+++ b/src/test/ui/span/send-is-not-static-std-sync-2.rs
@@ -0,0 +1,39 @@
+// basic tests to see that certain "obvious" errors are caught by
+// these types no longer requiring `'static` (RFC 458)
+
+#![allow(dead_code)]
+
+use std::sync::{Mutex, RwLock, mpsc};
+
+fn mutex() {
+    let lock = {
+        let x = 1;
+        Mutex::new(&x)
+    };
+    //~^^ ERROR `x` does not live long enough
+
+    let _dangling = *lock.lock().unwrap();
+}
+
+fn rwlock() {
+    let lock = {
+        let x = 1;
+        RwLock::new(&x)
+    };
+    //~^^ ERROR `x` does not live long enough
+    let _dangling = *lock.read().unwrap();
+}
+
+fn channel() {
+    let (_tx, rx) = {
+        let x = 1;
+        let (tx, rx) = mpsc::channel();
+        let _ = tx.send(&x);
+        (tx, rx)
+    };
+    //~^^^ ERROR `x` does not live long enough
+
+    let _dangling = rx.recv();
+}
+
+fn main() {}
diff --git a/src/test/ui/span/send-is-not-static-std-sync-2.stderr b/src/test/ui/span/send-is-not-static-std-sync-2.stderr
new file mode 100644
index 0000000..4172731
--- /dev/null
+++ b/src/test/ui/span/send-is-not-static-std-sync-2.stderr
@@ -0,0 +1,37 @@
+error[E0597]: `x` does not live long enough
+  --> $DIR/send-is-not-static-std-sync-2.rs:11:21
+   |
+LL |         Mutex::new(&x)
+   |                     ^ borrowed value does not live long enough
+LL |     };
+   |     - `x` dropped here while still borrowed
+...
+LL | }
+   | - borrowed value needs to live until here
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/send-is-not-static-std-sync-2.rs:21:22
+   |
+LL |         RwLock::new(&x)
+   |                      ^ borrowed value does not live long enough
+LL |     };
+   |     - `x` dropped here while still borrowed
+...
+LL | }
+   | - borrowed value needs to live until here
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/send-is-not-static-std-sync-2.rs:31:26
+   |
+LL |         let _ = tx.send(&x);
+   |                          ^ borrowed value does not live long enough
+LL |         (tx, rx)
+LL |     };
+   |     - `x` dropped here while still borrowed
+...
+LL | }
+   | - borrowed value needs to live until here
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/send-is-not-static-std-sync.nll.stderr b/src/test/ui/span/send-is-not-static-std-sync.nll.stderr
new file mode 100644
index 0000000..93473a8
--- /dev/null
+++ b/src/test/ui/span/send-is-not-static-std-sync.nll.stderr
@@ -0,0 +1,72 @@
+error[E0505]: cannot move out of `y` because it is borrowed
+  --> $DIR/send-is-not-static-std-sync.rs:13:10
+   |
+LL |     *lock.lock().unwrap() = &*y;
+   |                             --- borrow of `*y` occurs here
+LL |     drop(y);
+   |          ^ move out of `y` occurs here
+...
+LL |         *lock.lock().unwrap() = &z;
+   |          ---- borrow later used here
+
+error[E0597]: `z` does not live long enough
+  --> $DIR/send-is-not-static-std-sync.rs:16:33
+   |
+LL |         *lock.lock().unwrap() = &z;
+   |                                 ^^ borrowed value does not live long enough
+LL |     }
+   |     - `z` dropped here while still borrowed
+LL |
+LL |     lock.use_ref(); // (Mutex is #[may_dangle] so its dtor does not use `z` => needs explicit use)
+   |     ---- borrow later used here
+
+error[E0505]: cannot move out of `y` because it is borrowed
+  --> $DIR/send-is-not-static-std-sync.rs:27:10
+   |
+LL |     *lock.write().unwrap() = &*y;
+   |                              --- borrow of `*y` occurs here
+LL |     drop(y);
+   |          ^ move out of `y` occurs here
+...
+LL |         *lock.write().unwrap() = &z;
+   |          ---- borrow later used here
+
+error[E0597]: `z` does not live long enough
+  --> $DIR/send-is-not-static-std-sync.rs:30:34
+   |
+LL |         *lock.write().unwrap() = &z;
+   |                                  ^^ borrowed value does not live long enough
+LL |     }
+   |     - `z` dropped here while still borrowed
+LL |
+LL |     lock.use_ref(); // (RwLock is #[may_dangle] so its dtor does not use `z` => needs explicit use)
+   |     ---- borrow later used here
+
+error[E0505]: cannot move out of `y` because it is borrowed
+  --> $DIR/send-is-not-static-std-sync.rs:43:10
+   |
+LL |     tx.send(&*y);
+   |             --- borrow of `*y` occurs here
+LL |     drop(y);
+   |          ^ move out of `y` occurs here
+...
+LL |         tx.send(&z).unwrap();
+   |         -- borrow later used here
+
+error[E0597]: `z` does not live long enough
+  --> $DIR/send-is-not-static-std-sync.rs:46:17
+   |
+LL |         tx.send(&z).unwrap();
+   |                 ^^ borrowed value does not live long enough
+LL |     }
+   |     - `z` dropped here while still borrowed
+...
+LL | }
+   | - borrow might be used here, when `tx` is dropped and runs the `Drop` code for type `std::sync::mpsc::Sender`
+   |
+   = note: values in a scope are dropped in the opposite order they are defined
+
+error: aborting due to 6 previous errors
+
+Some errors occurred: E0505, E0597.
+For more information about an error, try `rustc --explain E0505`.
diff --git a/src/test/ui/span/send-is-not-static-std-sync.rs b/src/test/ui/span/send-is-not-static-std-sync.rs
new file mode 100644
index 0000000..f8ab524
--- /dev/null
+++ b/src/test/ui/span/send-is-not-static-std-sync.rs
@@ -0,0 +1,55 @@
+// basic tests to see that certain "obvious" errors are caught by
+// these types no longer requiring `'static` (RFC 458)
+
+#![allow(dead_code)]
+
+use std::sync::{Mutex, RwLock, mpsc};
+
+fn mutex() {
+    let x = 1;
+    let y = Box::new(1);
+    let lock = Mutex::new(&x);
+    *lock.lock().unwrap() = &*y;
+    drop(y); //~ ERROR cannot move out
+    {
+        let z = 2;
+        *lock.lock().unwrap() = &z;
+    }
+    //~^^ ERROR `z` does not live long enough
+    lock.use_ref(); // (Mutex is #[may_dangle] so its dtor does not use `z` => needs explicit use)
+}
+
+fn rwlock() {
+    let x = 1;
+    let y = Box::new(1);
+    let lock = RwLock::new(&x);
+    *lock.write().unwrap() = &*y;
+    drop(y); //~ ERROR cannot move out
+    {
+        let z = 2;
+        *lock.write().unwrap() = &z;
+    }
+    //~^^ ERROR `z` does not live long enough
+    lock.use_ref(); // (RwLock is #[may_dangle] so its dtor does not use `z` => needs explicit use)
+}
+
+fn channel() {
+    let x = 1;
+    let y = Box::new(1);
+    let (tx, rx) = mpsc::channel();
+
+    tx.send(&x).unwrap();
+    tx.send(&*y);
+    drop(y); //~ ERROR cannot move out
+    {
+        let z = 2;
+        tx.send(&z).unwrap();
+    }
+    //~^^ ERROR `z` does not live long enough
+    // (channels lack #[may_dangle], thus their dtors are implicit uses of `z`)
+}
+
+fn main() {}
+
+trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { }  }
+impl<T> Fake for T { }
diff --git a/src/test/ui/span/send-is-not-static-std-sync.stderr b/src/test/ui/span/send-is-not-static-std-sync.stderr
new file mode 100644
index 0000000..aa9e1c2
--- /dev/null
+++ b/src/test/ui/span/send-is-not-static-std-sync.stderr
@@ -0,0 +1,61 @@
+error[E0597]: `z` does not live long enough
+  --> $DIR/send-is-not-static-std-sync.rs:16:34
+   |
+LL |         *lock.lock().unwrap() = &z;
+   |                                  ^ borrowed value does not live long enough
+LL |     }
+   |     - `z` dropped here while still borrowed
+...
+LL | }
+   | - borrowed value needs to live until here
+
+error[E0505]: cannot move out of `y` because it is borrowed
+  --> $DIR/send-is-not-static-std-sync.rs:13:10
+   |
+LL |     *lock.lock().unwrap() = &*y;
+   |                              -- borrow of `*y` occurs here
+LL |     drop(y);
+   |          ^ move out of `y` occurs here
+
+error[E0597]: `z` does not live long enough
+  --> $DIR/send-is-not-static-std-sync.rs:30:35
+   |
+LL |         *lock.write().unwrap() = &z;
+   |                                   ^ borrowed value does not live long enough
+LL |     }
+   |     - `z` dropped here while still borrowed
+...
+LL | }
+   | - borrowed value needs to live until here
+
+error[E0505]: cannot move out of `y` because it is borrowed
+  --> $DIR/send-is-not-static-std-sync.rs:27:10
+   |
+LL |     *lock.write().unwrap() = &*y;
+   |                               -- borrow of `*y` occurs here
+LL |     drop(y);
+   |          ^ move out of `y` occurs here
+
+error[E0597]: `z` does not live long enough
+  --> $DIR/send-is-not-static-std-sync.rs:46:18
+   |
+LL |         tx.send(&z).unwrap();
+   |                  ^ borrowed value does not live long enough
+LL |     }
+   |     - `z` dropped here while still borrowed
+...
+LL | }
+   | - borrowed value needs to live until here
+
+error[E0505]: cannot move out of `y` because it is borrowed
+  --> $DIR/send-is-not-static-std-sync.rs:43:10
+   |
+LL |     tx.send(&*y);
+   |              -- borrow of `*y` occurs here
+LL |     drop(y);
+   |          ^ move out of `y` occurs here
+
+error: aborting due to 6 previous errors
+
+Some errors occurred: E0505, E0597.
+For more information about an error, try `rustc --explain E0505`.
diff --git a/src/test/ui/span/slice-borrow.nll.stderr b/src/test/ui/span/slice-borrow.nll.stderr
new file mode 100644
index 0000000..84d0c84
--- /dev/null
+++ b/src/test/ui/span/slice-borrow.nll.stderr
@@ -0,0 +1,17 @@
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/slice-borrow.rs:6:28
+   |
+LL |         let x: &[isize] = &vec![1, 2, 3, 4, 5];
+   |                            ^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+...
+LL |     }
+   |     - temporary value is freed at the end of this statement
+LL |     y.use_ref();
+   |     - borrow later used here
+   |
+   = note: consider using a `let` binding to create a longer lived value
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/src/test/ui/span/slice-borrow.rs b/src/test/ui/span/slice-borrow.rs
new file mode 100644
index 0000000..23e5303
--- /dev/null
+++ b/src/test/ui/span/slice-borrow.rs
@@ -0,0 +1,14 @@
+// Test slicing expressions doesn't defeat the borrow checker.
+
+fn main() {
+    let y;
+    {
+        let x: &[isize] = &vec![1, 2, 3, 4, 5];
+        //~^ ERROR borrowed value does not live long enough
+        y = &x[1..];
+    }
+    y.use_ref();
+}
+
+trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { }  }
+impl<T> Fake for T { }
diff --git a/src/test/ui/span/slice-borrow.stderr b/src/test/ui/span/slice-borrow.stderr
new file mode 100644
index 0000000..a03cac5
--- /dev/null
+++ b/src/test/ui/span/slice-borrow.stderr
@@ -0,0 +1,17 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/slice-borrow.rs:6:28
+   |
+LL |         let x: &[isize] = &vec![1, 2, 3, 4, 5];
+   |                            ^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+...
+LL |     }
+   |     - temporary value dropped here while still borrowed
+LL |     y.use_ref();
+LL | }
+   | - temporary value needs to live until here
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/suggestion-non-ascii.rs b/src/test/ui/span/suggestion-non-ascii.rs
new file mode 100644
index 0000000..74032cf
--- /dev/null
+++ b/src/test/ui/span/suggestion-non-ascii.rs
@@ -0,0 +1,5 @@
+fn main() {
+    let tup = (1,);
+    println!("☃{}", tup[0]); //~ ERROR cannot index into a value of type
+}
+
diff --git a/src/test/ui/span/suggestion-non-ascii.stderr b/src/test/ui/span/suggestion-non-ascii.stderr
new file mode 100644
index 0000000..b14632d
--- /dev/null
+++ b/src/test/ui/span/suggestion-non-ascii.stderr
@@ -0,0 +1,9 @@
+error[E0608]: cannot index into a value of type `({integer},)`
+  --> $DIR/suggestion-non-ascii.rs:3:21
+   |
+LL |     println!("☃{}", tup[0]);
+   |                     ^^^^^^ help: to access tuple elements, use: `tup.0`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0608`.
diff --git a/src/test/ui/span/type-binding.rs b/src/test/ui/span/type-binding.rs
new file mode 100644
index 0000000..32016e1
--- /dev/null
+++ b/src/test/ui/span/type-binding.rs
@@ -0,0 +1,9 @@
+// Regression test for issue #28158
+// Test the type binding span doesn't include >>
+
+use std::ops::Deref;
+
+fn homura<T: Deref<Trget = i32>>(_: T) {}
+//~^ ERROR not found
+
+fn main() {}
diff --git a/src/test/ui/span/type-binding.stderr b/src/test/ui/span/type-binding.stderr
new file mode 100644
index 0000000..421af67
--- /dev/null
+++ b/src/test/ui/span/type-binding.stderr
@@ -0,0 +1,9 @@
+error[E0220]: associated type `Trget` not found for `std::ops::Deref`
+  --> $DIR/type-binding.rs:6:20
+   |
+LL | fn homura<T: Deref<Trget = i32>>(_: T) {}
+   |                    ^^^^^^^^^^^ associated type `Trget` not found
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0220`.
diff --git a/src/test/ui/span/typo-suggestion.rs b/src/test/ui/span/typo-suggestion.rs
new file mode 100644
index 0000000..e9d7bc6
--- /dev/null
+++ b/src/test/ui/span/typo-suggestion.rs
@@ -0,0 +1,9 @@
+fn main() {
+    let foo = 1;
+
+    // `foo` shouldn't be suggested, it is too dissimilar from `bar`.
+    println!("Hello {}", bar); //~ ERROR cannot find value
+
+    // But this is close enough.
+    println!("Hello {}", fob); //~ ERROR cannot find value
+}
diff --git a/src/test/ui/span/typo-suggestion.stderr b/src/test/ui/span/typo-suggestion.stderr
new file mode 100644
index 0000000..61d4e06
--- /dev/null
+++ b/src/test/ui/span/typo-suggestion.stderr
@@ -0,0 +1,15 @@
+error[E0425]: cannot find value `bar` in this scope
+  --> $DIR/typo-suggestion.rs:5:26
+   |
+LL |     println!("Hello {}", bar);
+   |                          ^^^ not found in this scope
+
+error[E0425]: cannot find value `fob` in this scope
+  --> $DIR/typo-suggestion.rs:8:26
+   |
+LL |     println!("Hello {}", fob);
+   |                          ^^^ help: a local variable with a similar name exists: `foo`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/span/unused-warning-point-at-signature.rs b/src/test/ui/span/unused-warning-point-at-signature.rs
new file mode 100644
index 0000000..3af272a
--- /dev/null
+++ b/src/test/ui/span/unused-warning-point-at-signature.rs
@@ -0,0 +1,30 @@
+// run-pass
+
+#![warn(unused)]
+
+enum Enum { //~ WARN enum is never used
+    A,
+    B,
+    C,
+    D,
+}
+
+struct Struct { //~ WARN struct is never constructed
+    a: usize,
+    b: usize,
+    c: usize,
+    d: usize,
+}
+
+fn func() -> usize { //~ WARN function is never used
+    3
+}
+
+fn //~ WARN function is never used
+func_complete_span()
+-> usize
+{
+    3
+}
+
+fn main() {}
diff --git a/src/test/ui/span/unused-warning-point-at-signature.stderr b/src/test/ui/span/unused-warning-point-at-signature.stderr
new file mode 100644
index 0000000..3007d90
--- /dev/null
+++ b/src/test/ui/span/unused-warning-point-at-signature.stderr
@@ -0,0 +1,36 @@
+warning: enum is never used: `Enum`
+  --> $DIR/unused-warning-point-at-signature.rs:5:1
+   |
+LL | enum Enum {
+   | ^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/unused-warning-point-at-signature.rs:3:9
+   |
+LL | #![warn(unused)]
+   |         ^^^^^^
+   = note: #[warn(dead_code)] implied by #[warn(unused)]
+
+warning: struct is never constructed: `Struct`
+  --> $DIR/unused-warning-point-at-signature.rs:12:1
+   |
+LL | struct Struct {
+   | ^^^^^^^^^^^^^
+
+warning: function is never used: `func`
+  --> $DIR/unused-warning-point-at-signature.rs:19:1
+   |
+LL | fn func() -> usize {
+   | ^^^^^^^^^^^^^^^^^^
+
+warning: function is never used: `func_complete_span`
+  --> $DIR/unused-warning-point-at-signature.rs:23:1
+   |
+LL | / fn
+LL | | func_complete_span()
+LL | | -> usize
+LL | | {
+LL | |     3
+LL | | }
+   | |_^
+
diff --git a/src/test/ui/span/vec-must-not-hide-type-from-dropck.nll.stderr b/src/test/ui/span/vec-must-not-hide-type-from-dropck.nll.stderr
new file mode 100644
index 0000000..f87c32d
--- /dev/null
+++ b/src/test/ui/span/vec-must-not-hide-type-from-dropck.nll.stderr
@@ -0,0 +1,29 @@
+error[E0597]: `c2` does not live long enough
+  --> $DIR/vec-must-not-hide-type-from-dropck.rs:117:24
+   |
+LL |     c1.v[0].v.set(Some(&c2));
+   |                        ^^^ borrowed value does not live long enough
+...
+LL | }
+   | -
+   | |
+   | `c2` dropped here while still borrowed
+   | borrow might be used here, when `c1` is dropped and runs the destructor for type `C<'_>`
+   |
+   = note: values in a scope are dropped in the opposite order they are defined
+
+error[E0597]: `c1` does not live long enough
+  --> $DIR/vec-must-not-hide-type-from-dropck.rs:119:24
+   |
+LL |     c2.v[0].v.set(Some(&c1));
+   |                        ^^^ borrowed value does not live long enough
+LL |
+LL | }
+   | -
+   | |
+   | `c1` dropped here while still borrowed
+   | borrow might be used here, when `c1` is dropped and runs the destructor for type `C<'_>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/vec-must-not-hide-type-from-dropck.rs b/src/test/ui/span/vec-must-not-hide-type-from-dropck.rs
new file mode 100644
index 0000000..9bfbfab
--- /dev/null
+++ b/src/test/ui/span/vec-must-not-hide-type-from-dropck.rs
@@ -0,0 +1,125 @@
+// Checking that `Vec<T>` cannot hide lifetimes within `T` when `T`
+// implements `Drop` and might access methods of values that have
+// since been deallocated.
+//
+// In this case, the values in question hold (non-zero) unique-ids
+// that zero themselves out when dropped, and are wrapped in another
+// type with a destructor that asserts that the ids it references are
+// indeed non-zero (i.e., effectively checking that the id's are not
+// dropped while there are still any outstanding references).
+//
+// However, the values in question are also formed into a
+// cyclic-structure, ensuring that there is no way for all of the
+// conditions above to be satisfied, meaning that if the dropck is
+// sound, it should reject this code.
+
+
+
+use std::cell::Cell;
+use id::Id;
+
+mod s {
+    use std::sync::atomic::{AtomicUsize, Ordering};
+
+    static S_COUNT: AtomicUsize = AtomicUsize::new(0);
+
+    /// generates globally unique count (global across the current
+    /// process, that is)
+    pub fn next_count() -> usize {
+        S_COUNT.fetch_add(1, Ordering::SeqCst) + 1
+    }
+}
+
+mod id {
+    use s;
+
+    /// Id represents a globally unique identifier (global across the
+    /// current process, that is). When dropped, it automatically
+    /// clears its `count` field, but leaves `orig_count` untouched,
+    /// so that if there are subsequent (erroneous) invocations of its
+    /// method (which is unsound), we can observe it by seeing that
+    /// the `count` is 0 while the `orig_count` is non-zero.
+    #[derive(Debug)]
+    pub struct Id {
+        orig_count: usize,
+        count: usize,
+    }
+
+    impl Id {
+        /// Creates an `Id` with a globally unique count.
+        pub fn new() -> Id {
+            let c = s::next_count();
+            println!("building Id {}", c);
+            Id { orig_count: c, count: c }
+        }
+        /// returns the `count` of self; should be non-zero if
+        /// everything is working.
+        pub fn count(&self) -> usize {
+            println!("Id::count on {} returns {}", self.orig_count, self.count);
+            self.count
+        }
+    }
+
+    impl Drop for Id {
+        fn drop(&mut self) {
+            println!("dropping Id {}", self.count);
+            self.count = 0;
+        }
+    }
+}
+
+trait HasId {
+    fn count(&self) -> usize;
+}
+
+#[derive(Debug)]
+struct CheckId<T:HasId> {
+    v: T
+}
+
+#[allow(non_snake_case)]
+fn CheckId<T:HasId>(t: T) -> CheckId<T> { CheckId{ v: t } }
+
+impl<T:HasId> Drop for CheckId<T> {
+    fn drop(&mut self) {
+        assert!(self.v.count() > 0);
+    }
+}
+
+#[derive(Debug)]
+struct C<'a> {
+    id: Id,
+    v: Vec<CheckId<Cell<Option<&'a C<'a>>>>>,
+}
+
+impl<'a> HasId for Cell<Option<&'a C<'a>>> {
+    fn count(&self) -> usize {
+        match self.get() {
+            None => 1,
+            Some(c) => c.id.count(),
+        }
+    }
+}
+
+impl<'a> C<'a> {
+    fn new() -> C<'a> {
+        C { id: Id::new(), v: Vec::new() }
+    }
+}
+
+fn f() {
+    let (mut c1, mut c2);
+    c1 = C::new();
+    c2 = C::new();
+
+    c1.v.push(CheckId(Cell::new(None)));
+    c2.v.push(CheckId(Cell::new(None)));
+    c1.v[0].v.set(Some(&c2));
+    //~^ ERROR `c2` does not live long enough
+    c2.v[0].v.set(Some(&c1));
+    //~^ ERROR `c1` does not live long enough
+}
+
+fn main() {
+    f();
+}
diff --git a/src/test/ui/span/vec-must-not-hide-type-from-dropck.stderr b/src/test/ui/span/vec-must-not-hide-type-from-dropck.stderr
new file mode 100644
index 0000000..b957243
--- /dev/null
+++ b/src/test/ui/span/vec-must-not-hide-type-from-dropck.stderr
@@ -0,0 +1,25 @@
+error[E0597]: `c2` does not live long enough
+  --> $DIR/vec-must-not-hide-type-from-dropck.rs:117:25
+   |
+LL |     c1.v[0].v.set(Some(&c2));
+   |                         ^^ borrowed value does not live long enough
+...
+LL | }
+   | - `c2` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error[E0597]: `c1` does not live long enough
+  --> $DIR/vec-must-not-hide-type-from-dropck.rs:119:25
+   |
+LL |     c2.v[0].v.set(Some(&c1));
+   |                         ^^ borrowed value does not live long enough
+LL |
+LL | }
+   | - `c1` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/vec_refs_data_with_early_death.nll.stderr b/src/test/ui/span/vec_refs_data_with_early_death.nll.stderr
new file mode 100644
index 0000000..684e784
--- /dev/null
+++ b/src/test/ui/span/vec_refs_data_with_early_death.nll.stderr
@@ -0,0 +1,31 @@
+error[E0597]: `x` does not live long enough
+  --> $DIR/vec_refs_data_with_early_death.rs:17:12
+   |
+LL |     v.push(&x);
+   |            ^^ borrowed value does not live long enough
+...
+LL | }
+   | -
+   | |
+   | `x` dropped here while still borrowed
+   | borrow might be used here, when `v` is dropped and runs the `Drop` code for type `Bag`
+   |
+   = note: values in a scope are dropped in the opposite order they are defined
+
+error[E0597]: `y` does not live long enough
+  --> $DIR/vec_refs_data_with_early_death.rs:19:12
+   |
+LL |     v.push(&y);
+   |            ^^ borrowed value does not live long enough
+...
+LL | }
+   | -
+   | |
+   | `y` dropped here while still borrowed
+   | borrow might be used here, when `v` is dropped and runs the `Drop` code for type `Bag`
+   |
+   = note: values in a scope are dropped in the opposite order they are defined
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/vec_refs_data_with_early_death.rs b/src/test/ui/span/vec_refs_data_with_early_death.rs
new file mode 100644
index 0000000..c23c521
--- /dev/null
+++ b/src/test/ui/span/vec_refs_data_with_early_death.rs
@@ -0,0 +1,33 @@
+// This test is a simple example of code that violates the dropck
+// rules: it pushes `&x` and `&y` into a bag (with dtor), but the
+// referenced data will be dropped before the bag is.
+
+
+
+
+
+
+
+fn main() {
+    let mut v = Bag::new();
+
+    let x: i8 = 3;
+    let y: i8 = 4;
+
+    v.push(&x);
+    //~^ ERROR `x` does not live long enough
+    v.push(&y);
+    //~^ ERROR `y` does not live long enough
+
+    assert_eq!(v.0, [&3, &4]);
+}
+
+//`Vec<T>` is #[may_dangle] w.r.t. `T`; putting a bag over its head
+// forces borrowck to treat dropping the bag as a potential use.
+struct Bag<T>(Vec<T>);
+impl<T> Drop for Bag<T> { fn drop(&mut self) { } }
+
+impl<T> Bag<T> {
+    fn new() -> Self { Bag(Vec::new()) }
+    fn push(&mut self, t: T) { self.0.push(t); }
+}
diff --git a/src/test/ui/span/vec_refs_data_with_early_death.stderr b/src/test/ui/span/vec_refs_data_with_early_death.stderr
new file mode 100644
index 0000000..65fd6b5
--- /dev/null
+++ b/src/test/ui/span/vec_refs_data_with_early_death.stderr
@@ -0,0 +1,25 @@
+error[E0597]: `x` does not live long enough
+  --> $DIR/vec_refs_data_with_early_death.rs:17:13
+   |
+LL |     v.push(&x);
+   |             ^ borrowed value does not live long enough
+...
+LL | }
+   | - `x` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error[E0597]: `y` does not live long enough
+  --> $DIR/vec_refs_data_with_early_death.rs:19:13
+   |
+LL |     v.push(&y);
+   |             ^ borrowed value does not live long enough
+...
+LL | }
+   | - `y` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/visibility-ty-params.rs b/src/test/ui/span/visibility-ty-params.rs
new file mode 100644
index 0000000..d77febe
--- /dev/null
+++ b/src/test/ui/span/visibility-ty-params.rs
@@ -0,0 +1,13 @@
+macro_rules! m {
+    ($p: path) => (pub(in $p) struct Z;)
+}
+
+struct S<T>(T);
+m!{ S<u8> } //~ ERROR unexpected generic arguments in path
+            //~| ERROR expected module, found struct `S`
+
+mod m {
+    m!{ m<> } //~ ERROR unexpected generic arguments in path
+}
+
+fn main() {}
diff --git a/src/test/ui/span/visibility-ty-params.stderr b/src/test/ui/span/visibility-ty-params.stderr
new file mode 100644
index 0000000..ddc13bb
--- /dev/null
+++ b/src/test/ui/span/visibility-ty-params.stderr
@@ -0,0 +1,23 @@
+error: unexpected generic arguments in path
+  --> $DIR/visibility-ty-params.rs:6:5
+   |
+LL | m!{ S<u8> }
+   |     ^^^^^
+
+error: unexpected generic arguments in path
+  --> $DIR/visibility-ty-params.rs:10:9
+   |
+LL |     m!{ m<> }
+   |         ^^^
+
+error[E0577]: expected module, found struct `S`
+  --> $DIR/visibility-ty-params.rs:6:5
+   |
+LL | m!{ S<u8> }
+   |     -^^^^
+   |     |
+   |     help: a module with a similar name exists: `m`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0577`.
diff --git a/src/test/ui/span/wf-method-late-bound-regions.nll.stderr b/src/test/ui/span/wf-method-late-bound-regions.nll.stderr
new file mode 100644
index 0000000..6b0b008
--- /dev/null
+++ b/src/test/ui/span/wf-method-late-bound-regions.nll.stderr
@@ -0,0 +1,14 @@
+error[E0597]: `pointer` does not live long enough
+  --> $DIR/wf-method-late-bound-regions.rs:20:18
+   |
+LL |     let dangling = {
+   |         -------- borrow later stored here
+LL |         let pointer = Box::new(42);
+LL |         f2.xmute(&pointer)
+   |                  ^^^^^^^^ borrowed value does not live long enough
+LL |     };
+   |     - `pointer` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/wf-method-late-bound-regions.rs b/src/test/ui/span/wf-method-late-bound-regions.rs
new file mode 100644
index 0000000..ca9f73d
--- /dev/null
+++ b/src/test/ui/span/wf-method-late-bound-regions.rs
@@ -0,0 +1,24 @@
+// A method's receiver must be well-formed, even if it has late-bound regions.
+// Because of this, a method's substs being well-formed does not imply that
+// the method's implied bounds are met.
+
+struct Foo<'b>(Option<&'b ()>);
+
+trait Bar<'b> {
+    fn xmute<'a>(&'a self, u: &'b u32) -> &'a u32;
+}
+
+impl<'b> Bar<'b> for Foo<'b> {
+    fn xmute<'a>(&'a self, u: &'b u32) -> &'a u32 { u }
+}
+
+fn main() {
+    let f = Foo(None);
+    let f2 = f;
+    let dangling = {
+        let pointer = Box::new(42);
+        f2.xmute(&pointer)
+    };
+    //~^^ ERROR `pointer` does not live long enough
+    println!("{}", dangling);
+}
diff --git a/src/test/ui/span/wf-method-late-bound-regions.stderr b/src/test/ui/span/wf-method-late-bound-regions.stderr
new file mode 100644
index 0000000..a30e0f4
--- /dev/null
+++ b/src/test/ui/span/wf-method-late-bound-regions.stderr
@@ -0,0 +1,14 @@
+error[E0597]: `pointer` does not live long enough
+  --> $DIR/wf-method-late-bound-regions.rs:20:19
+   |
+LL |         f2.xmute(&pointer)
+   |                   ^^^^^^^ borrowed value does not live long enough
+LL |     };
+   |     - `pointer` dropped here while still borrowed
+...
+LL | }
+   | - borrowed value needs to live until here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/specialization/README.md b/src/test/ui/specialization/README.md
new file mode 100644
index 0000000..f2b4bf9
--- /dev/null
+++ b/src/test/ui/specialization/README.md
@@ -0,0 +1,21 @@
+This directory contains the test for incorrect usage of specialization that
+should lead to compile failure. Those tests break down into a few categories:
+
+- Feature gating
+  - [On use of the `default` keyword](specialization-feature-gate-default.rs)
+  - [On overlapping impls](specialization-feature-gate-overlap.rs)
+
+- Overlap checking with specialization enabled
+  - [Basic overlap scenarios](specialization-overlap.rs)
+    - Includes purely structural overlap
+    - Includes purely trait-based overlap
+    - Includes mix
+  - [Overlap with differing polarity](specialization-overlap-negative.rs)
+
+- [Attempt to specialize without using `default`](specialization-no-default.rs)
+
+- [Attempt to change impl polarity in a specialization](specialization-polarity.rs)
+
+- Attempt to rely on projection of a `default` type
+  - [Rely on it externally in both generic and monomorphic contexts](specialization-default-projection.rs)
+  - [Rely on it both within an impl and outside it](specialization-default-types.rs)
diff --git a/src/test/ui/specialization/defaultimpl/specialization-feature-gate-default.rs b/src/test/ui/specialization/defaultimpl/specialization-feature-gate-default.rs
new file mode 100644
index 0000000..89158b6
--- /dev/null
+++ b/src/test/ui/specialization/defaultimpl/specialization-feature-gate-default.rs
@@ -0,0 +1,11 @@
+// Check that specialization must be ungated to use the `default` keyword
+
+trait Foo {
+    fn foo(&self);
+}
+
+default impl<T> Foo for T { //~ ERROR specialization is unstable
+    fn foo(&self) {}
+}
+
+fn main() {}
diff --git a/src/test/ui/specialization/defaultimpl/specialization-feature-gate-default.stderr b/src/test/ui/specialization/defaultimpl/specialization-feature-gate-default.stderr
new file mode 100644
index 0000000..0b20a19
--- /dev/null
+++ b/src/test/ui/specialization/defaultimpl/specialization-feature-gate-default.stderr
@@ -0,0 +1,13 @@
+error[E0658]: specialization is unstable (see issue #31844)
+  --> $DIR/specialization-feature-gate-default.rs:7:1
+   |
+LL | / default impl<T> Foo for T {
+LL | |     fn foo(&self) {}
+LL | | }
+   | |_^
+   |
+   = help: add #![feature(specialization)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/specialization/defaultimpl/specialization-no-default.rs b/src/test/ui/specialization/defaultimpl/specialization-no-default.rs
new file mode 100644
index 0000000..7ea79a9
--- /dev/null
+++ b/src/test/ui/specialization/defaultimpl/specialization-no-default.rs
@@ -0,0 +1,85 @@
+#![feature(specialization)]
+
+// Check a number of scenarios in which one impl tries to override another,
+// without correctly using `default`.
+
+////////////////////////////////////////////////////////////////////////////////
+// Test 1: one layer of specialization, multiple methods, missing `default`
+////////////////////////////////////////////////////////////////////////////////
+
+trait Foo {
+    fn foo(&self);
+    fn bar(&self);
+}
+
+impl<T> Foo for T {
+    fn foo(&self) {}
+    fn bar(&self) {}
+}
+
+impl Foo for u8 {}
+impl Foo for u16 {
+    fn foo(&self) {} //~ ERROR E0520
+}
+impl Foo for u32 {
+    fn bar(&self) {} //~ ERROR E0520
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Test 2: one layer of specialization, missing `default` on associated type
+////////////////////////////////////////////////////////////////////////////////
+
+trait Bar {
+    type T;
+}
+
+impl<T> Bar for T {
+    type T = u8;
+}
+
+impl Bar for u8 {
+    type T = (); //~ ERROR E0520
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Test 3a: multiple layers of specialization, missing interior `default`
+////////////////////////////////////////////////////////////////////////////////
+
+trait Baz {
+    fn baz(&self);
+}
+
+default impl<T> Baz for T {
+    fn baz(&self) {}
+}
+
+impl<T: Clone> Baz for T {
+    fn baz(&self) {}
+}
+
+impl Baz for i32 {
+    fn baz(&self) {} //~ ERROR E0520
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Test 3b: multiple layers of specialization, missing interior `default`,
+// redundant `default` in bottom layer.
+////////////////////////////////////////////////////////////////////////////////
+
+trait Redundant {
+    fn redundant(&self);
+}
+
+default impl<T> Redundant for T {
+    fn redundant(&self) {}
+}
+
+impl<T: Clone> Redundant for T {
+    fn redundant(&self) {}
+}
+
+default impl Redundant for i32 {
+    fn redundant(&self) {} //~ ERROR E0520
+}
+
+fn main() {}
diff --git a/src/test/ui/specialization/defaultimpl/specialization-no-default.stderr b/src/test/ui/specialization/defaultimpl/specialization-no-default.stderr
new file mode 100644
index 0000000..91690f6
--- /dev/null
+++ b/src/test/ui/specialization/defaultimpl/specialization-no-default.stderr
@@ -0,0 +1,70 @@
+error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default`
+  --> $DIR/specialization-no-default.rs:22:5
+   |
+LL | / impl<T> Foo for T {
+LL | |     fn foo(&self) {}
+LL | |     fn bar(&self) {}
+LL | | }
+   | |_- parent `impl` is here
+...
+LL |       fn foo(&self) {}
+   |       ^^^^^^^^^^^^^^^^ cannot specialize default item `foo`
+   |
+   = note: to specialize, `foo` in the parent `impl` must be marked `default`
+
+error[E0520]: `bar` specializes an item from a parent `impl`, but that item is not marked `default`
+  --> $DIR/specialization-no-default.rs:25:5
+   |
+LL | / impl<T> Foo for T {
+LL | |     fn foo(&self) {}
+LL | |     fn bar(&self) {}
+LL | | }
+   | |_- parent `impl` is here
+...
+LL |       fn bar(&self) {}
+   |       ^^^^^^^^^^^^^^^^ cannot specialize default item `bar`
+   |
+   = note: to specialize, `bar` in the parent `impl` must be marked `default`
+
+error[E0520]: `T` specializes an item from a parent `impl`, but that item is not marked `default`
+  --> $DIR/specialization-no-default.rs:41:5
+   |
+LL | / impl<T> Bar for T {
+LL | |     type T = u8;
+LL | | }
+   | |_- parent `impl` is here
+...
+LL |       type T = ();
+   |       ^^^^^^^^^^^^ cannot specialize default item `T`
+   |
+   = note: to specialize, `T` in the parent `impl` must be marked `default`
+
+error[E0520]: `baz` specializes an item from a parent `impl`, but that item is not marked `default`
+  --> $DIR/specialization-no-default.rs:61:5
+   |
+LL | / impl<T: Clone> Baz for T {
+LL | |     fn baz(&self) {}
+LL | | }
+   | |_- parent `impl` is here
+...
+LL |       fn baz(&self) {}
+   |       ^^^^^^^^^^^^^^^^ cannot specialize default item `baz`
+   |
+   = note: to specialize, `baz` in the parent `impl` must be marked `default`
+
+error[E0520]: `redundant` specializes an item from a parent `impl`, but that item is not marked `default`
+  --> $DIR/specialization-no-default.rs:82:5
+   |
+LL | / impl<T: Clone> Redundant for T {
+LL | |     fn redundant(&self) {}
+LL | | }
+   | |_- parent `impl` is here
+...
+LL |       fn redundant(&self) {}
+   |       ^^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `redundant`
+   |
+   = note: to specialize, `redundant` in the parent `impl` must be marked `default`
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0520`.
diff --git a/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.rs b/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.rs
new file mode 100644
index 0000000..2a121e6
--- /dev/null
+++ b/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.rs
@@ -0,0 +1,23 @@
+// Tests that default impls do not have to supply all items but regular impls do.
+
+#![feature(specialization)]
+
+trait Foo {
+    fn foo_one(&self) -> &'static str;
+    fn foo_two(&self) -> &'static str;
+}
+
+struct MyStruct;
+
+default impl<T> Foo for T {
+    fn foo_one(&self) -> &'static str {
+        "generic"
+    }
+}
+
+impl Foo for MyStruct {}
+//~^ ERROR not all trait items implemented, missing: `foo_two` [E0046]
+
+fn main() {
+    println!("{}", MyStruct.foo_one());
+}
diff --git a/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.stderr b/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.stderr
new file mode 100644
index 0000000..b862a93
--- /dev/null
+++ b/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.stderr
@@ -0,0 +1,12 @@
+error[E0046]: not all trait items implemented, missing: `foo_two`
+  --> $DIR/specialization-trait-item-not-implemented.rs:18:1
+   |
+LL |     fn foo_two(&self) -> &'static str;
+   |     ---------------------------------- `foo_two` from trait
+...
+LL | impl Foo for MyStruct {}
+   | ^^^^^^^^^^^^^^^^^^^^^ missing `foo_two` in implementation
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0046`.
diff --git a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.rs b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.rs
new file mode 100644
index 0000000..34a1416
--- /dev/null
+++ b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.rs
@@ -0,0 +1,24 @@
+// Tests that:
+// - default impls do not have to supply all items and
+// - a default impl does not count as an impl (in this case, an incomplete default impl).
+
+#![feature(specialization)]
+
+trait Foo {
+    fn foo_one(&self) -> &'static str;
+    fn foo_two(&self) -> &'static str;
+}
+
+struct MyStruct;
+
+default impl<T> Foo for T {
+    fn foo_one(&self) -> &'static str {
+        "generic"
+    }
+}
+
+
+fn main() {
+    println!("{}", MyStruct.foo_one());
+    //~^ ERROR no method named `foo_one` found for type `MyStruct` in the current scope
+}
diff --git a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr
new file mode 100644
index 0000000..c14fc04
--- /dev/null
+++ b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr
@@ -0,0 +1,18 @@
+error[E0599]: no method named `foo_one` found for type `MyStruct` in the current scope
+  --> $DIR/specialization-trait-not-implemented.rs:22:29
+   |
+LL | struct MyStruct;
+   | ---------------- method `foo_one` not found for this
+...
+LL |     println!("{}", MyStruct.foo_one());
+   |                             ^^^^^^^
+   |
+   = note: the method `foo_one` exists but the following trait bounds were not satisfied:
+           `MyStruct : Foo`
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following trait defines an item `foo_one`, perhaps you need to implement it:
+           candidate #1: `Foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/specialization/defaultimpl/specialization-wfcheck.rs b/src/test/ui/specialization/defaultimpl/specialization-wfcheck.rs
new file mode 100644
index 0000000..232338d
--- /dev/null
+++ b/src/test/ui/specialization/defaultimpl/specialization-wfcheck.rs
@@ -0,0 +1,10 @@
+// Tests that a default impl still has to have a WF trait ref.
+
+#![feature(specialization)]
+
+trait Foo<'a, T: Eq + 'a> { }
+
+default impl<U> Foo<'static, U> for () {}
+//~^ ERROR the trait bound `U: std::cmp::Eq` is not satisfied
+
+fn main(){}
diff --git a/src/test/ui/specialization/defaultimpl/specialization-wfcheck.stderr b/src/test/ui/specialization/defaultimpl/specialization-wfcheck.stderr
new file mode 100644
index 0000000..4595156
--- /dev/null
+++ b/src/test/ui/specialization/defaultimpl/specialization-wfcheck.stderr
@@ -0,0 +1,11 @@
+error[E0277]: the trait bound `U: std::cmp::Eq` is not satisfied
+  --> $DIR/specialization-wfcheck.rs:7:17
+   |
+LL | default impl<U> Foo<'static, U> for () {}
+   |                 ^^^^^^^^^^^^^^^ the trait `std::cmp::Eq` is not implemented for `U`
+   |
+   = help: consider adding a `where U: std::cmp::Eq` bound
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/specialization/defaultimpl/validation.rs b/src/test/ui/specialization/defaultimpl/validation.rs
new file mode 100644
index 0000000..cf5d662
--- /dev/null
+++ b/src/test/ui/specialization/defaultimpl/validation.rs
@@ -0,0 +1,15 @@
+#![feature(optin_builtin_traits)]
+#![feature(specialization)]
+
+struct S;
+struct Z;
+
+default impl S {} //~ ERROR inherent impls cannot be default
+
+default unsafe impl Send for S {} //~ ERROR impls of auto traits cannot be default
+default impl !Send for Z {} //~ ERROR impls of auto traits cannot be default
+
+trait Tr {}
+default impl !Tr for S {} //~ ERROR negative impls are only allowed for auto traits
+
+fn main() {}
diff --git a/src/test/ui/specialization/defaultimpl/validation.stderr b/src/test/ui/specialization/defaultimpl/validation.stderr
new file mode 100644
index 0000000..14a06c3
--- /dev/null
+++ b/src/test/ui/specialization/defaultimpl/validation.stderr
@@ -0,0 +1,29 @@
+error: inherent impls cannot be default
+  --> $DIR/validation.rs:7:1
+   |
+LL | default impl S {}
+   | ^^^^^^^^^^^^^^^^^
+   |
+   = note: only trait implementations may be annotated with default
+
+error: impls of auto traits cannot be default
+  --> $DIR/validation.rs:9:1
+   |
+LL | default unsafe impl Send for S {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: impls of auto traits cannot be default
+  --> $DIR/validation.rs:10:1
+   |
+LL | default impl !Send for Z {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0192]: negative impls are only allowed for auto traits (e.g., `Send` and `Sync`)
+  --> $DIR/validation.rs:13:1
+   |
+LL | default impl !Tr for S {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0192`.
diff --git a/src/test/ui/specialization/issue-39448.rs b/src/test/ui/specialization/issue-39448.rs
new file mode 100644
index 0000000..8ac6d8e
--- /dev/null
+++ b/src/test/ui/specialization/issue-39448.rs
@@ -0,0 +1,50 @@
+#![feature(specialization)]
+
+// Regression test for a specialization-related ICE (#39448).
+
+trait A: Sized {
+    fn foo(self, _: Self) -> Self {
+        self
+    }
+}
+
+impl A for u8 {}
+impl A for u16 {}
+
+impl FromA<u8> for u16 {
+    fn from(x: u8) -> u16 {
+        x as u16
+    }
+}
+
+trait FromA<T> {
+    fn from(T) -> Self;
+}
+
+impl<T: A, U: A + FromA<T>> FromA<T> for U {
+    default fn from(x: T) -> Self {
+        ToA::to(x)
+    }
+}
+
+trait ToA<T> {
+    fn to(self) -> T;
+}
+
+impl<T, U> ToA<U> for T
+where
+    U: FromA<T>,
+{
+    fn to(self) -> U {
+        U::from(self)
+    }
+}
+
+#[allow(dead_code)]
+fn foo<T: A, U: A>(x: T, y: U) -> U {
+    x.foo(y.to()).to() //~ ERROR overflow evaluating the requirement
+}
+
+fn main() {
+    let z = foo(8u8, 1u16);
+}
diff --git a/src/test/ui/specialization/issue-39448.stderr b/src/test/ui/specialization/issue-39448.stderr
new file mode 100644
index 0000000..861a1d9
--- /dev/null
+++ b/src/test/ui/specialization/issue-39448.stderr
@@ -0,0 +1,12 @@
+error[E0275]: overflow evaluating the requirement `T: FromA<U>`
+  --> $DIR/issue-39448.rs:45:13
+   |
+LL |     x.foo(y.to()).to()
+   |             ^^
+   |
+   = note: required because of the requirements on the impl of `FromA<U>` for `T`
+   = note: required because of the requirements on the impl of `ToA<T>` for `U`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/src/test/ui/specialization/issue-52050.rs b/src/test/ui/specialization/issue-52050.rs
new file mode 100644
index 0000000..1e1bfe9
--- /dev/null
+++ b/src/test/ui/specialization/issue-52050.rs
@@ -0,0 +1,32 @@
+#![feature(specialization)]
+
+// Regression test for #52050: when inserting the blanket impl `I`
+// into the tree, we had to replace the child node for `Foo`, which
+// led to the structure of the tree being messed up.
+
+use std::iter::Iterator;
+
+trait IntoPyDictPointer { }
+
+struct Foo { }
+
+impl Iterator for Foo {
+    type Item = ();
+    fn next(&mut self) -> Option<()> {
+        None
+    }
+}
+
+impl IntoPyDictPointer for Foo { }
+
+impl<I> IntoPyDictPointer for I
+where
+    I: Iterator,
+{
+}
+
+impl IntoPyDictPointer for () //~ ERROR conflicting implementations
+{
+}
+
+fn main() { }
diff --git a/src/test/ui/specialization/issue-52050.stderr b/src/test/ui/specialization/issue-52050.stderr
new file mode 100644
index 0000000..dcb34f3
--- /dev/null
+++ b/src/test/ui/specialization/issue-52050.stderr
@@ -0,0 +1,18 @@
+error[E0119]: conflicting implementations of trait `IntoPyDictPointer` for type `()`:
+  --> $DIR/issue-52050.rs:28:1
+   |
+LL | / impl<I> IntoPyDictPointer for I
+LL | | where
+LL | |     I: Iterator,
+LL | | {
+LL | | }
+   | |_- first implementation here
+LL | 
+LL |   impl IntoPyDictPointer for ()
+   |   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()`
+   |
+   = note: upstream crates may add new impl of trait `std::iter::Iterator` for type `()` in future versions
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/specialization/specialization-default-projection.rs b/src/test/ui/specialization/specialization-default-projection.rs
new file mode 100644
index 0000000..e9343f2
--- /dev/null
+++ b/src/test/ui/specialization/specialization-default-projection.rs
@@ -0,0 +1,36 @@
+#![feature(specialization)]
+
+// Make sure we can't project defaulted associated types
+
+trait Foo {
+    type Assoc;
+}
+
+impl<T> Foo for T {
+    default type Assoc = ();
+}
+
+impl Foo for u8 {
+    type Assoc = String;
+}
+
+fn generic<T>() -> <T as Foo>::Assoc {
+    // `T` could be some downstream crate type that specializes (or,
+    // for that matter, `u8`).
+
+    () //~ ERROR mismatched types
+}
+
+fn monomorphic() -> () {
+    // Even though we know that `()` is not specialized in a
+    // downstream crate, typeck refuses to project here.
+
+    generic::<()>() //~ ERROR mismatched types
+}
+
+fn main() {
+    // No error here, we CAN project from `u8`, as there is no `default`
+    // in that impl.
+    let s: String = generic::<u8>();
+    println!("{}", s); // bad news if this all compiles
+}
diff --git a/src/test/ui/specialization/specialization-default-projection.stderr b/src/test/ui/specialization/specialization-default-projection.stderr
new file mode 100644
index 0000000..ab0bdc4
--- /dev/null
+++ b/src/test/ui/specialization/specialization-default-projection.stderr
@@ -0,0 +1,29 @@
+error[E0308]: mismatched types
+  --> $DIR/specialization-default-projection.rs:21:5
+   |
+LL | fn generic<T>() -> <T as Foo>::Assoc {
+   |                    ----------------- expected `<T as Foo>::Assoc` because of return type
+...
+LL |     ()
+   |     ^^ expected associated type, found ()
+   |
+   = note: expected type `<T as Foo>::Assoc`
+              found type `()`
+
+error[E0308]: mismatched types
+  --> $DIR/specialization-default-projection.rs:28:5
+   |
+LL | fn monomorphic() -> () {
+   |                     -- expected `()` because of return type
+...
+LL |     generic::<()>()
+   |     ^^^^^^^^^^^^^^^- help: try adding a semicolon: `;`
+   |     |
+   |     expected (), found associated type
+   |
+   = note: expected type `()`
+              found type `<() as Foo>::Assoc`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/specialization/specialization-default-types.rs b/src/test/ui/specialization/specialization-default-types.rs
new file mode 100644
index 0000000..acb86d8
--- /dev/null
+++ b/src/test/ui/specialization/specialization-default-types.rs
@@ -0,0 +1,35 @@
+// It should not be possible to use the concrete value of a defaulted
+// associated type in the impl defining it -- otherwise, what happens
+// if it's overridden?
+
+#![feature(specialization)]
+
+trait Example {
+    type Output;
+    fn generate(self) -> Self::Output;
+}
+
+impl<T> Example for T {
+    default type Output = Box<T>;
+    default fn generate(self) -> Self::Output {
+        Box::new(self) //~ ERROR mismatched types
+    }
+}
+
+impl Example for bool {
+    type Output = bool;
+    fn generate(self) -> bool { self }
+}
+
+fn trouble<T>(t: T) -> Box<T> {
+    Example::generate(t) //~ ERROR mismatched types
+}
+
+fn weaponize() -> bool {
+    let b: Box<bool> = trouble(true);
+    *b
+}
+
+fn main() {
+    weaponize();
+}
diff --git a/src/test/ui/specialization/specialization-default-types.stderr b/src/test/ui/specialization/specialization-default-types.stderr
new file mode 100644
index 0000000..1192b0e
--- /dev/null
+++ b/src/test/ui/specialization/specialization-default-types.stderr
@@ -0,0 +1,25 @@
+error[E0308]: mismatched types
+  --> $DIR/specialization-default-types.rs:15:9
+   |
+LL |     default fn generate(self) -> Self::Output {
+   |                                  ------------ expected `<T as Example>::Output` because of return type
+LL |         Box::new(self)
+   |         ^^^^^^^^^^^^^^ expected associated type, found struct `std::boxed::Box`
+   |
+   = note: expected type `<T as Example>::Output`
+              found type `std::boxed::Box<T>`
+
+error[E0308]: mismatched types
+  --> $DIR/specialization-default-types.rs:25:5
+   |
+LL | fn trouble<T>(t: T) -> Box<T> {
+   |                        ------ expected `std::boxed::Box<T>` because of return type
+LL |     Example::generate(t)
+   |     ^^^^^^^^^^^^^^^^^^^^ expected struct `std::boxed::Box`, found associated type
+   |
+   = note: expected type `std::boxed::Box<T>`
+              found type `<T as Example>::Output`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/specialization/specialization-feature-gate-default.rs b/src/test/ui/specialization/specialization-feature-gate-default.rs
new file mode 100644
index 0000000..8bad3ac
--- /dev/null
+++ b/src/test/ui/specialization/specialization-feature-gate-default.rs
@@ -0,0 +1,13 @@
+// Check that specialization must be ungated to use the `default` keyword
+
+// gate-test-specialization
+
+trait Foo {
+    fn foo(&self);
+}
+
+impl<T> Foo for T {
+    default fn foo(&self) {} //~ ERROR specialization is unstable
+}
+
+fn main() {}
diff --git a/src/test/ui/specialization/specialization-feature-gate-default.stderr b/src/test/ui/specialization/specialization-feature-gate-default.stderr
new file mode 100644
index 0000000..ad33908
--- /dev/null
+++ b/src/test/ui/specialization/specialization-feature-gate-default.stderr
@@ -0,0 +1,11 @@
+error[E0658]: specialization is unstable (see issue #31844)
+  --> $DIR/specialization-feature-gate-default.rs:10:5
+   |
+LL |     default fn foo(&self) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(specialization)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/specialization/specialization-feature-gate-overlap.rs b/src/test/ui/specialization/specialization-feature-gate-overlap.rs
new file mode 100644
index 0000000..b83c84a
--- /dev/null
+++ b/src/test/ui/specialization/specialization-feature-gate-overlap.rs
@@ -0,0 +1,17 @@
+// Check that writing an overlapping impl is not allow unless specialization is ungated.
+
+// gate-test-specialization
+
+trait Foo {
+    fn foo(&self);
+}
+
+impl<T> Foo for T {
+    fn foo(&self) {}
+}
+
+impl Foo for u8 { //~ ERROR E0119
+    fn foo(&self) {}
+}
+
+fn main() {}
diff --git a/src/test/ui/specialization/specialization-feature-gate-overlap.stderr b/src/test/ui/specialization/specialization-feature-gate-overlap.stderr
new file mode 100644
index 0000000..baaf7aa
--- /dev/null
+++ b/src/test/ui/specialization/specialization-feature-gate-overlap.stderr
@@ -0,0 +1,12 @@
+error[E0119]: conflicting implementations of trait `Foo` for type `u8`:
+  --> $DIR/specialization-feature-gate-overlap.rs:13:1
+   |
+LL | impl<T> Foo for T {
+   | ----------------- first implementation here
+...
+LL | impl Foo for u8 {
+   | ^^^^^^^^^^^^^^^ conflicting implementation for `u8`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/specialization/specialization-no-default.rs b/src/test/ui/specialization/specialization-no-default.rs
new file mode 100644
index 0000000..29afbbd9
--- /dev/null
+++ b/src/test/ui/specialization/specialization-no-default.rs
@@ -0,0 +1,85 @@
+#![feature(specialization)]
+
+// Check a number of scenarios in which one impl tries to override another,
+// without correctly using `default`.
+
+////////////////////////////////////////////////////////////////////////////////
+// Test 1: one layer of specialization, multiple methods, missing `default`
+////////////////////////////////////////////////////////////////////////////////
+
+trait Foo {
+    fn foo(&self);
+    fn bar(&self);
+}
+
+impl<T> Foo for T {
+    fn foo(&self) {}
+    fn bar(&self) {}
+}
+
+impl Foo for u8 {}
+impl Foo for u16 {
+    fn foo(&self) {} //~ ERROR E0520
+}
+impl Foo for u32 {
+    fn bar(&self) {} //~ ERROR E0520
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Test 2: one layer of specialization, missing `default` on associated type
+////////////////////////////////////////////////////////////////////////////////
+
+trait Bar {
+    type T;
+}
+
+impl<T> Bar for T {
+    type T = u8;
+}
+
+impl Bar for u8 {
+    type T = (); //~ ERROR E0520
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Test 3a: multiple layers of specialization, missing interior `default`
+////////////////////////////////////////////////////////////////////////////////
+
+trait Baz {
+    fn baz(&self);
+}
+
+impl<T> Baz for T {
+    default fn baz(&self) {}
+}
+
+impl<T: Clone> Baz for T {
+    fn baz(&self) {}
+}
+
+impl Baz for i32 {
+    fn baz(&self) {} //~ ERROR E0520
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Test 3b: multiple layers of specialization, missing interior `default`,
+// redundant `default` in bottom layer.
+////////////////////////////////////////////////////////////////////////////////
+
+trait Redundant {
+    fn redundant(&self);
+}
+
+impl<T> Redundant for T {
+    default fn redundant(&self) {}
+}
+
+impl<T: Clone> Redundant for T {
+    fn redundant(&self) {}
+}
+
+impl Redundant for i32 {
+    default fn redundant(&self) {} //~ ERROR E0520
+}
+
+fn main() {}
diff --git a/src/test/ui/specialization/specialization-no-default.stderr b/src/test/ui/specialization/specialization-no-default.stderr
new file mode 100644
index 0000000..c39986d
--- /dev/null
+++ b/src/test/ui/specialization/specialization-no-default.stderr
@@ -0,0 +1,70 @@
+error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default`
+  --> $DIR/specialization-no-default.rs:22:5
+   |
+LL | / impl<T> Foo for T {
+LL | |     fn foo(&self) {}
+LL | |     fn bar(&self) {}
+LL | | }
+   | |_- parent `impl` is here
+...
+LL |       fn foo(&self) {}
+   |       ^^^^^^^^^^^^^^^^ cannot specialize default item `foo`
+   |
+   = note: to specialize, `foo` in the parent `impl` must be marked `default`
+
+error[E0520]: `bar` specializes an item from a parent `impl`, but that item is not marked `default`
+  --> $DIR/specialization-no-default.rs:25:5
+   |
+LL | / impl<T> Foo for T {
+LL | |     fn foo(&self) {}
+LL | |     fn bar(&self) {}
+LL | | }
+   | |_- parent `impl` is here
+...
+LL |       fn bar(&self) {}
+   |       ^^^^^^^^^^^^^^^^ cannot specialize default item `bar`
+   |
+   = note: to specialize, `bar` in the parent `impl` must be marked `default`
+
+error[E0520]: `T` specializes an item from a parent `impl`, but that item is not marked `default`
+  --> $DIR/specialization-no-default.rs:41:5
+   |
+LL | / impl<T> Bar for T {
+LL | |     type T = u8;
+LL | | }
+   | |_- parent `impl` is here
+...
+LL |       type T = ();
+   |       ^^^^^^^^^^^^ cannot specialize default item `T`
+   |
+   = note: to specialize, `T` in the parent `impl` must be marked `default`
+
+error[E0520]: `baz` specializes an item from a parent `impl`, but that item is not marked `default`
+  --> $DIR/specialization-no-default.rs:61:5
+   |
+LL | / impl<T: Clone> Baz for T {
+LL | |     fn baz(&self) {}
+LL | | }
+   | |_- parent `impl` is here
+...
+LL |       fn baz(&self) {}
+   |       ^^^^^^^^^^^^^^^^ cannot specialize default item `baz`
+   |
+   = note: to specialize, `baz` in the parent `impl` must be marked `default`
+
+error[E0520]: `redundant` specializes an item from a parent `impl`, but that item is not marked `default`
+  --> $DIR/specialization-no-default.rs:82:5
+   |
+LL | / impl<T: Clone> Redundant for T {
+LL | |     fn redundant(&self) {}
+LL | | }
+   | |_- parent `impl` is here
+...
+LL |       default fn redundant(&self) {}
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `redundant`
+   |
+   = note: to specialize, `redundant` in the parent `impl` must be marked `default`
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0520`.
diff --git a/src/test/ui/specialization/specialization-overlap-hygiene.rs b/src/test/ui/specialization/specialization-overlap-hygiene.rs
new file mode 100644
index 0000000..93e7c83
--- /dev/null
+++ b/src/test/ui/specialization/specialization-overlap-hygiene.rs
@@ -0,0 +1,23 @@
+#![feature(decl_macro)]
+
+struct X;
+
+macro_rules! define_f_legacy { () => {
+    fn f() {}
+}}
+macro define_g_modern() {
+    fn g() {}
+}
+
+impl X {
+   fn f() {} //~ ERROR duplicate definitions with name `f`
+   fn g() {} // OK
+}
+impl X {
+    define_f_legacy!();
+}
+impl X {
+    define_g_modern!();
+}
+
+fn main() {}
diff --git a/src/test/ui/specialization/specialization-overlap-hygiene.stderr b/src/test/ui/specialization/specialization-overlap-hygiene.stderr
new file mode 100644
index 0000000..6adf16d
--- /dev/null
+++ b/src/test/ui/specialization/specialization-overlap-hygiene.stderr
@@ -0,0 +1,12 @@
+error[E0592]: duplicate definitions with name `f`
+  --> $DIR/specialization-overlap-hygiene.rs:13:4
+   |
+LL |     fn f() {}
+   |     --------- other definition for `f`
+...
+LL |    fn f() {}
+   |    ^^^^^^^^^ duplicate definitions for `f`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0592`.
diff --git a/src/test/ui/specialization/specialization-overlap-negative.rs b/src/test/ui/specialization/specialization-overlap-negative.rs
new file mode 100644
index 0000000..af80d66
--- /dev/null
+++ b/src/test/ui/specialization/specialization-overlap-negative.rs
@@ -0,0 +1,11 @@
+#![feature(optin_builtin_traits)]
+#![feature(specialization)]
+
+trait MyTrait {}
+
+struct TestType<T>(::std::marker::PhantomData<T>);
+
+unsafe impl<T: Clone> Send for TestType<T> {}
+impl<T: MyTrait> !Send for TestType<T> {} //~ ERROR E0119
+
+fn main() {}
diff --git a/src/test/ui/specialization/specialization-overlap-negative.stderr b/src/test/ui/specialization/specialization-overlap-negative.stderr
new file mode 100644
index 0000000..947aad8
--- /dev/null
+++ b/src/test/ui/specialization/specialization-overlap-negative.stderr
@@ -0,0 +1,11 @@
+error[E0119]: conflicting implementations of trait `std::marker::Send` for type `TestType<_>`:
+  --> $DIR/specialization-overlap-negative.rs:9:1
+   |
+LL | unsafe impl<T: Clone> Send for TestType<T> {}
+   | ------------------------------------------ first implementation here
+LL | impl<T: MyTrait> !Send for TestType<T> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `TestType<_>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/specialization/specialization-overlap.rs b/src/test/ui/specialization/specialization-overlap.rs
new file mode 100644
index 0000000..c8ef8d6
--- /dev/null
+++ b/src/test/ui/specialization/specialization-overlap.rs
@@ -0,0 +1,19 @@
+#![feature(specialization)]
+
+trait Foo { fn foo() {} }
+impl<T: Clone> Foo for T {}
+impl<T> Foo for Vec<T> {} //~ ERROR E0119
+
+trait Bar { fn bar() {} }
+impl<T> Bar for (T, u8) {}
+impl<T> Bar for (u8, T) {} //~ ERROR E0119
+
+trait Baz<U> { fn baz() {} }
+impl<T> Baz<T> for u8 {}
+impl<T> Baz<u8> for T {} //~ ERROR E0119
+
+trait Qux { fn qux() {} }
+impl<T: Clone> Qux for T {}
+impl<T: Eq> Qux for T {} //~ ERROR E0119
+
+fn main() {}
diff --git a/src/test/ui/specialization/specialization-overlap.stderr b/src/test/ui/specialization/specialization-overlap.stderr
new file mode 100644
index 0000000..4275e7b
--- /dev/null
+++ b/src/test/ui/specialization/specialization-overlap.stderr
@@ -0,0 +1,35 @@
+error[E0119]: conflicting implementations of trait `Foo` for type `std::vec::Vec<_>`:
+  --> $DIR/specialization-overlap.rs:5:1
+   |
+LL | impl<T: Clone> Foo for T {}
+   | ------------------------ first implementation here
+LL | impl<T> Foo for Vec<T> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `std::vec::Vec<_>`
+
+error[E0119]: conflicting implementations of trait `Bar` for type `(u8, u8)`:
+  --> $DIR/specialization-overlap.rs:9:1
+   |
+LL | impl<T> Bar for (T, u8) {}
+   | ----------------------- first implementation here
+LL | impl<T> Bar for (u8, T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(u8, u8)`
+
+error[E0119]: conflicting implementations of trait `Baz<u8>` for type `u8`:
+  --> $DIR/specialization-overlap.rs:13:1
+   |
+LL | impl<T> Baz<T> for u8 {}
+   | --------------------- first implementation here
+LL | impl<T> Baz<u8> for T {}
+   | ^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u8`
+
+error[E0119]: conflicting implementations of trait `Qux`:
+  --> $DIR/specialization-overlap.rs:17:1
+   |
+LL | impl<T: Clone> Qux for T {}
+   | ------------------------ first implementation here
+LL | impl<T: Eq> Qux for T {}
+   | ^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/specialization/specialization-polarity.rs b/src/test/ui/specialization/specialization-polarity.rs
new file mode 100644
index 0000000..d574480
--- /dev/null
+++ b/src/test/ui/specialization/specialization-polarity.rs
@@ -0,0 +1,16 @@
+// Make sure specialization cannot change impl polarity
+
+#![feature(optin_builtin_traits)]
+#![feature(specialization)]
+
+auto trait Foo {}
+
+impl<T> Foo for T {}
+impl !Foo for u8 {} //~ ERROR E0119
+
+auto trait Bar {}
+
+impl<T> !Bar for T {}
+impl Bar for u8 {} //~ ERROR E0119
+
+fn main() {}
diff --git a/src/test/ui/specialization/specialization-polarity.stderr b/src/test/ui/specialization/specialization-polarity.stderr
new file mode 100644
index 0000000..bc1b2ae
--- /dev/null
+++ b/src/test/ui/specialization/specialization-polarity.stderr
@@ -0,0 +1,19 @@
+error[E0119]: conflicting implementations of trait `Foo` for type `u8`:
+  --> $DIR/specialization-polarity.rs:9:1
+   |
+LL | impl<T> Foo for T {}
+   | ----------------- first implementation here
+LL | impl !Foo for u8 {}
+   | ^^^^^^^^^^^^^^^^ conflicting implementation for `u8`
+
+error[E0119]: conflicting implementations of trait `Bar` for type `u8`:
+  --> $DIR/specialization-polarity.rs:14:1
+   |
+LL | impl<T> !Bar for T {}
+   | ------------------ first implementation here
+LL | impl Bar for u8 {}
+   | ^^^^^^^^^^^^^^^ conflicting implementation for `u8`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/stability-attribute/auxiliary/stability_attribute_issue.rs b/src/test/ui/stability-attribute/auxiliary/stability_attribute_issue.rs
new file mode 100644
index 0000000..4e53332
--- /dev/null
+++ b/src/test/ui/stability-attribute/auxiliary/stability_attribute_issue.rs
@@ -0,0 +1,9 @@
+#![feature(staged_api)]
+#![stable(feature = "stable_test_feature", since = "1.2.0")]
+
+
+#[unstable(feature = "unstable_test_feature", issue = "1")]
+pub fn unstable() {}
+
+#[unstable(feature = "unstable_test_feature", reason = "message", issue = "2")]
+pub fn unstable_msg() {}
diff --git a/src/test/ui/stability-attribute/missing-stability-attr-at-top-level.rs b/src/test/ui/stability-attribute/missing-stability-attr-at-top-level.rs
new file mode 100644
index 0000000..8f750ae
--- /dev/null
+++ b/src/test/ui/stability-attribute/missing-stability-attr-at-top-level.rs
@@ -0,0 +1,4 @@
+#![feature(staged_api)]
+//~^ ERROR crate has missing stability attribute
+
+fn main() {}
diff --git a/src/test/ui/stability-attribute/missing-stability-attr-at-top-level.stderr b/src/test/ui/stability-attribute/missing-stability-attr-at-top-level.stderr
new file mode 100644
index 0000000..b6c9564
--- /dev/null
+++ b/src/test/ui/stability-attribute/missing-stability-attr-at-top-level.stderr
@@ -0,0 +1,11 @@
+error: crate has missing stability attribute
+  --> $DIR/missing-stability-attr-at-top-level.rs:1:1
+   |
+LL | / #![feature(staged_api)]
+LL | |
+LL | |
+LL | | fn main() {}
+   | |____________^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/stability-attribute/stability-attribute-issue-43027.rs b/src/test/ui/stability-attribute/stability-attribute-issue-43027.rs
new file mode 100644
index 0000000..0b243bb
--- /dev/null
+++ b/src/test/ui/stability-attribute/stability-attribute-issue-43027.rs
@@ -0,0 +1,10 @@
+#![feature(staged_api)]
+#![stable(feature = "test", since = "0")]
+
+#[stable(feature = "test", since = "0")]
+pub struct Reverse<T>(pub T); //~ ERROR field has missing stability attribute
+
+fn main() {
+    // Make sure the field is used to fill the stability cache
+    Reverse(0).0;
+}
diff --git a/src/test/ui/stability-attribute/stability-attribute-issue-43027.stderr b/src/test/ui/stability-attribute/stability-attribute-issue-43027.stderr
new file mode 100644
index 0000000..280c72a
--- /dev/null
+++ b/src/test/ui/stability-attribute/stability-attribute-issue-43027.stderr
@@ -0,0 +1,8 @@
+error: field has missing stability attribute
+  --> $DIR/stability-attribute-issue-43027.rs:5:23
+   |
+LL | pub struct Reverse<T>(pub T);
+   |                       ^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/stability-attribute/stability-attribute-issue.rs b/src/test/ui/stability-attribute/stability-attribute-issue.rs
new file mode 100644
index 0000000..fc4a7da
--- /dev/null
+++ b/src/test/ui/stability-attribute/stability-attribute-issue.rs
@@ -0,0 +1,14 @@
+// aux-build:stability_attribute_issue.rs
+// ignore-tidy-linelength
+
+#![deny(deprecated)]
+
+extern crate stability_attribute_issue;
+use stability_attribute_issue::*;
+
+fn main() {
+    unstable();
+    //~^ ERROR use of unstable library feature 'unstable_test_feature' (see issue #1)
+    unstable_msg();
+    //~^ ERROR use of unstable library feature 'unstable_test_feature': message (see issue #2)
+}
diff --git a/src/test/ui/stability-attribute/stability-attribute-issue.stderr b/src/test/ui/stability-attribute/stability-attribute-issue.stderr
new file mode 100644
index 0000000..94fdc0d
--- /dev/null
+++ b/src/test/ui/stability-attribute/stability-attribute-issue.stderr
@@ -0,0 +1,19 @@
+error[E0658]: use of unstable library feature 'unstable_test_feature' (see issue #1)
+  --> $DIR/stability-attribute-issue.rs:10:5
+   |
+LL |     unstable();
+   |     ^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature': message (see issue #2)
+  --> $DIR/stability-attribute-issue.rs:12:5
+   |
+LL |     unstable_msg();
+   |     ^^^^^^^^^^^^
+   |
+   = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/stability-attribute/stability-attribute-non-staged-force-unstable.rs b/src/test/ui/stability-attribute/stability-attribute-non-staged-force-unstable.rs
new file mode 100644
index 0000000..1f0a7a8
--- /dev/null
+++ b/src/test/ui/stability-attribute/stability-attribute-non-staged-force-unstable.rs
@@ -0,0 +1,6 @@
+// compile-flags:-Zforce-unstable-if-unmarked
+
+#[unstable()] //~ ERROR: stability attributes may not be used
+#[stable()] //~ ERROR: stability attributes may not be used
+#[rustc_deprecated()] //~ ERROR: stability attributes may not be used
+fn main() { }
diff --git a/src/test/ui/stability-attribute/stability-attribute-non-staged-force-unstable.stderr b/src/test/ui/stability-attribute/stability-attribute-non-staged-force-unstable.stderr
new file mode 100644
index 0000000..77f896a
--- /dev/null
+++ b/src/test/ui/stability-attribute/stability-attribute-non-staged-force-unstable.stderr
@@ -0,0 +1,20 @@
+error: stability attributes may not be used outside of the standard library
+  --> $DIR/stability-attribute-non-staged-force-unstable.rs:3:1
+   |
+LL | #[unstable()]
+   | ^^^^^^^^^^^^^
+
+error: stability attributes may not be used outside of the standard library
+  --> $DIR/stability-attribute-non-staged-force-unstable.rs:4:1
+   |
+LL | #[stable()]
+   | ^^^^^^^^^^^
+
+error: stability attributes may not be used outside of the standard library
+  --> $DIR/stability-attribute-non-staged-force-unstable.rs:5:1
+   |
+LL | #[rustc_deprecated()]
+   | ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/stability-attribute/stability-attribute-non-staged.rs b/src/test/ui/stability-attribute/stability-attribute-non-staged.rs
new file mode 100644
index 0000000..fc2c2b5
--- /dev/null
+++ b/src/test/ui/stability-attribute/stability-attribute-non-staged.rs
@@ -0,0 +1,4 @@
+#[unstable()] //~ ERROR: stability attributes may not be used
+#[stable()] //~ ERROR: stability attributes may not be used
+#[rustc_deprecated()] //~ ERROR: stability attributes may not be used
+fn main() { }
diff --git a/src/test/ui/stability-attribute/stability-attribute-non-staged.stderr b/src/test/ui/stability-attribute/stability-attribute-non-staged.stderr
new file mode 100644
index 0000000..e98f789
--- /dev/null
+++ b/src/test/ui/stability-attribute/stability-attribute-non-staged.stderr
@@ -0,0 +1,20 @@
+error: stability attributes may not be used outside of the standard library
+  --> $DIR/stability-attribute-non-staged.rs:1:1
+   |
+LL | #[unstable()]
+   | ^^^^^^^^^^^^^
+
+error: stability attributes may not be used outside of the standard library
+  --> $DIR/stability-attribute-non-staged.rs:2:1
+   |
+LL | #[stable()]
+   | ^^^^^^^^^^^
+
+error: stability attributes may not be used outside of the standard library
+  --> $DIR/stability-attribute-non-staged.rs:3:1
+   |
+LL | #[rustc_deprecated()]
+   | ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/stability-attribute/stability-attribute-sanity-2.rs b/src/test/ui/stability-attribute/stability-attribute-sanity-2.rs
new file mode 100644
index 0000000..5a67ca0
--- /dev/null
+++ b/src/test/ui/stability-attribute/stability-attribute-sanity-2.rs
@@ -0,0 +1,16 @@
+// More checks that stability attributes are used correctly
+
+#![feature(staged_api)]
+
+#![stable(feature = "stable_test_feature", since = "1.0.0")]
+
+#[stable(feature = "a", feature = "b", since = "1.0.0")] //~ ERROR multiple 'feature' items
+fn f1() { }
+
+#[stable(feature = "a", sinse = "1.0.0")] //~ ERROR unknown meta item 'sinse'
+fn f2() { }
+
+#[unstable(feature = "a", issue = "no")] //~ ERROR incorrect 'issue'
+fn f3() { }
+
+fn main() { }
diff --git a/src/test/ui/stability-attribute/stability-attribute-sanity-2.stderr b/src/test/ui/stability-attribute/stability-attribute-sanity-2.stderr
new file mode 100644
index 0000000..2bc544d
--- /dev/null
+++ b/src/test/ui/stability-attribute/stability-attribute-sanity-2.stderr
@@ -0,0 +1,22 @@
+error[E0538]: multiple 'feature' items
+  --> $DIR/stability-attribute-sanity-2.rs:7:25
+   |
+LL | #[stable(feature = "a", feature = "b", since = "1.0.0")]
+   |                         ^^^^^^^^^^^^^
+
+error[E0541]: unknown meta item 'sinse'
+  --> $DIR/stability-attribute-sanity-2.rs:10:25
+   |
+LL | #[stable(feature = "a", sinse = "1.0.0")]
+   |                         ^^^^^^^^^^^^^^^ expected one of `since`, `note`
+
+error[E0545]: incorrect 'issue'
+  --> $DIR/stability-attribute-sanity-2.rs:13:1
+   |
+LL | #[unstable(feature = "a", issue = "no")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0538, E0541, E0545.
+For more information about an error, try `rustc --explain E0538`.
diff --git a/src/test/ui/stability-attribute/stability-attribute-sanity-3.rs b/src/test/ui/stability-attribute/stability-attribute-sanity-3.rs
new file mode 100644
index 0000000..13ef3d3
--- /dev/null
+++ b/src/test/ui/stability-attribute/stability-attribute-sanity-3.rs
@@ -0,0 +1,12 @@
+// More checks that stability attributes are used correctly
+
+#![feature(staged_api)]
+
+#![stable(feature = "stable_test_feature", since = "1.0.0")]
+
+#[macro_export]
+macro_rules! mac { //~ ERROR macro has missing stability attribute
+    () => ()
+}
+
+fn main() { }
diff --git a/src/test/ui/stability-attribute/stability-attribute-sanity-3.stderr b/src/test/ui/stability-attribute/stability-attribute-sanity-3.stderr
new file mode 100644
index 0000000..b1c56ef
--- /dev/null
+++ b/src/test/ui/stability-attribute/stability-attribute-sanity-3.stderr
@@ -0,0 +1,10 @@
+error: macro has missing stability attribute
+  --> $DIR/stability-attribute-sanity-3.rs:8:1
+   |
+LL | / macro_rules! mac {
+LL | |     () => ()
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/stability-attribute/stability-attribute-sanity-4.rs b/src/test/ui/stability-attribute/stability-attribute-sanity-4.rs
new file mode 100644
index 0000000..3fd54bc
--- /dev/null
+++ b/src/test/ui/stability-attribute/stability-attribute-sanity-4.rs
@@ -0,0 +1,29 @@
+// Various checks that stability attributes are used correctly, per RFC 507
+
+#![feature(staged_api)]
+
+#![stable(feature = "rust1", since = "1.0.0")]
+
+mod bogus_attribute_types_2 {
+    #[unstable] //~ ERROR attribute must be of the form
+    fn f1() { }
+
+    #[unstable = "b"] //~ ERROR attribute must be of the form
+    fn f2() { }
+
+    #[stable] //~ ERROR attribute must be of the form
+    fn f3() { }
+
+    #[stable = "a"] //~ ERROR attribute must be of the form
+    fn f4() { }
+
+    #[stable(feature = "a", since = "b")]
+    #[rustc_deprecated] //~ ERROR attribute must be of the form
+    fn f5() { }
+
+    #[stable(feature = "a", since = "b")]
+    #[rustc_deprecated = "a"] //~ ERROR attribute must be of the form
+    fn f6() { }
+}
+
+fn main() { }
diff --git a/src/test/ui/stability-attribute/stability-attribute-sanity-4.stderr b/src/test/ui/stability-attribute/stability-attribute-sanity-4.stderr
new file mode 100644
index 0000000..d85b628
--- /dev/null
+++ b/src/test/ui/stability-attribute/stability-attribute-sanity-4.stderr
@@ -0,0 +1,38 @@
+error: attribute must be of the form `#[unstable(feature = "name", reason = "...", issue = "N")]`
+  --> $DIR/stability-attribute-sanity-4.rs:8:5
+   |
+LL |     #[unstable]
+   |     ^^^^^^^^^^^
+
+error: attribute must be of the form `#[unstable(feature = "name", reason = "...", issue = "N")]`
+  --> $DIR/stability-attribute-sanity-4.rs:11:5
+   |
+LL |     #[unstable = "b"]
+   |     ^^^^^^^^^^^^^^^^^
+
+error: attribute must be of the form `#[stable(feature = "name", since = "version")]`
+  --> $DIR/stability-attribute-sanity-4.rs:14:5
+   |
+LL |     #[stable]
+   |     ^^^^^^^^^
+
+error: attribute must be of the form `#[stable(feature = "name", since = "version")]`
+  --> $DIR/stability-attribute-sanity-4.rs:17:5
+   |
+LL |     #[stable = "a"]
+   |     ^^^^^^^^^^^^^^^
+
+error: attribute must be of the form `#[rustc_deprecated(since = "version", reason = "...")]`
+  --> $DIR/stability-attribute-sanity-4.rs:21:5
+   |
+LL |     #[rustc_deprecated]
+   |     ^^^^^^^^^^^^^^^^^^^
+
+error: attribute must be of the form `#[rustc_deprecated(since = "version", reason = "...")]`
+  --> $DIR/stability-attribute-sanity-4.rs:25:5
+   |
+LL |     #[rustc_deprecated = "a"]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/stability-attribute/stability-attribute-sanity.rs b/src/test/ui/stability-attribute/stability-attribute-sanity.rs
new file mode 100644
index 0000000..aebdb3b
--- /dev/null
+++ b/src/test/ui/stability-attribute/stability-attribute-sanity.rs
@@ -0,0 +1,69 @@
+// Various checks that stability attributes are used correctly, per RFC 507
+
+#![feature(const_fn, staged_api, rustc_const_unstable)]
+
+#![stable(feature = "rust1", since = "1.0.0")]
+
+mod bogus_attribute_types_1 {
+    #[stable(feature = "a", since = "b", reason)] //~ ERROR unknown meta item 'reason' [E0541]
+    fn f1() { }
+
+    #[stable(feature = "a", since)] //~ ERROR incorrect meta item [E0539]
+    fn f2() { }
+
+    #[stable(feature, since = "a")] //~ ERROR incorrect meta item [E0539]
+    fn f3() { }
+
+    #[stable(feature = "a", since(b))] //~ ERROR incorrect meta item [E0539]
+    fn f5() { }
+
+    #[stable(feature(b), since = "a")] //~ ERROR incorrect meta item [E0539]
+    fn f6() { }
+}
+
+mod missing_feature_names {
+    #[unstable(issue = "0")] //~ ERROR missing 'feature' [E0546]
+    fn f1() { }
+
+    #[unstable(feature = "b")] //~ ERROR missing 'issue' [E0547]
+    fn f2() { }
+
+    #[stable(since = "a")] //~ ERROR missing 'feature' [E0546]
+    fn f3() { }
+}
+
+mod missing_version {
+    #[stable(feature = "a")] //~ ERROR missing 'since' [E0542]
+    fn f1() { }
+
+    #[stable(feature = "a", since = "b")]
+    #[rustc_deprecated(reason = "a")] //~ ERROR missing 'since' [E0542]
+    fn f2() { }
+}
+
+#[unstable(feature = "b", issue = "0")]
+#[stable(feature = "a", since = "b")] //~ ERROR multiple stability levels [E0544]
+fn multiple1() { }
+
+#[unstable(feature = "b", issue = "0")]
+#[unstable(feature = "b", issue = "0")] //~ ERROR multiple stability levels [E0544]
+fn multiple2() { }
+
+#[stable(feature = "a", since = "b")]
+#[stable(feature = "a", since = "b")] //~ ERROR multiple stability levels [E0544]
+fn multiple3() { }
+
+#[stable(feature = "a", since = "b")]
+#[rustc_deprecated(since = "b", reason = "text")]
+#[rustc_deprecated(since = "b", reason = "text")]
+#[rustc_const_unstable(feature = "c")]
+#[rustc_const_unstable(feature = "d")]
+pub const fn multiple4() { } //~ ERROR multiple rustc_deprecated attributes [E0540]
+//~^ ERROR Invalid stability or deprecation version found
+//~| ERROR multiple rustc_const_unstable attributes
+
+#[rustc_deprecated(since = "a", reason = "text")]
+fn deprecated_without_unstable_or_stable() { }
+//~^ ERROR rustc_deprecated attribute must be paired with either stable or unstable attribute
+
+fn main() { }
diff --git a/src/test/ui/stability-attribute/stability-attribute-sanity.stderr b/src/test/ui/stability-attribute/stability-attribute-sanity.stderr
new file mode 100644
index 0000000..5343e3b
--- /dev/null
+++ b/src/test/ui/stability-attribute/stability-attribute-sanity.stderr
@@ -0,0 +1,106 @@
+error[E0541]: unknown meta item 'reason'
+  --> $DIR/stability-attribute-sanity.rs:8:42
+   |
+LL |     #[stable(feature = "a", since = "b", reason)]
+   |                                          ^^^^^^ expected one of `since`, `note`
+
+error[E0539]: incorrect meta item
+  --> $DIR/stability-attribute-sanity.rs:11:29
+   |
+LL |     #[stable(feature = "a", since)]
+   |                             ^^^^^
+
+error[E0539]: incorrect meta item
+  --> $DIR/stability-attribute-sanity.rs:14:14
+   |
+LL |     #[stable(feature, since = "a")]
+   |              ^^^^^^^
+
+error[E0539]: incorrect meta item
+  --> $DIR/stability-attribute-sanity.rs:17:29
+   |
+LL |     #[stable(feature = "a", since(b))]
+   |                             ^^^^^^^^
+
+error[E0539]: incorrect meta item
+  --> $DIR/stability-attribute-sanity.rs:20:14
+   |
+LL |     #[stable(feature(b), since = "a")]
+   |              ^^^^^^^^^^
+
+error[E0546]: missing 'feature'
+  --> $DIR/stability-attribute-sanity.rs:25:5
+   |
+LL |     #[unstable(issue = "0")]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0547]: missing 'issue'
+  --> $DIR/stability-attribute-sanity.rs:28:5
+   |
+LL |     #[unstable(feature = "b")]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0546]: missing 'feature'
+  --> $DIR/stability-attribute-sanity.rs:31:5
+   |
+LL |     #[stable(since = "a")]
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0542]: missing 'since'
+  --> $DIR/stability-attribute-sanity.rs:36:5
+   |
+LL |     #[stable(feature = "a")]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0542]: missing 'since'
+  --> $DIR/stability-attribute-sanity.rs:40:5
+   |
+LL |     #[rustc_deprecated(reason = "a")]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0544]: multiple stability levels
+  --> $DIR/stability-attribute-sanity.rs:45:1
+   |
+LL | #[stable(feature = "a", since = "b")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0544]: multiple stability levels
+  --> $DIR/stability-attribute-sanity.rs:49:1
+   |
+LL | #[unstable(feature = "b", issue = "0")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0544]: multiple stability levels
+  --> $DIR/stability-attribute-sanity.rs:53:1
+   |
+LL | #[stable(feature = "a", since = "b")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0540]: multiple rustc_deprecated attributes
+  --> $DIR/stability-attribute-sanity.rs:61:1
+   |
+LL | pub const fn multiple4() { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0553]: multiple rustc_const_unstable attributes
+  --> $DIR/stability-attribute-sanity.rs:61:1
+   |
+LL | pub const fn multiple4() { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: Invalid stability or deprecation version found
+  --> $DIR/stability-attribute-sanity.rs:61:1
+   |
+LL | pub const fn multiple4() { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0549]: rustc_deprecated attribute must be paired with either stable or unstable attribute
+  --> $DIR/stability-attribute-sanity.rs:66:1
+   |
+LL | fn deprecated_without_unstable_or_stable() { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 17 previous errors
+
+Some errors occurred: E0539, E0540, E0541, E0542, E0544, E0546, E0547, E0549, E0553.
+For more information about an error, try `rustc --explain E0539`.
diff --git a/src/test/ui/stability-in-private-module.rs b/src/test/ui/stability-in-private-module.rs
new file mode 100644
index 0000000..f12e919
--- /dev/null
+++ b/src/test/ui/stability-in-private-module.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let _ = std::thread::thread_info::current_thread();
+    //~^ERROR module `thread_info` is private
+}
diff --git a/src/test/ui/stability-in-private-module.stderr b/src/test/ui/stability-in-private-module.stderr
new file mode 100644
index 0000000..c3edd62
--- /dev/null
+++ b/src/test/ui/stability-in-private-module.stderr
@@ -0,0 +1,9 @@
+error[E0603]: module `thread_info` is private
+  --> $DIR/stability-in-private-module.rs:2:26
+   |
+LL |     let _ = std::thread::thread_info::current_thread();
+   |                          ^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0603`.
diff --git a/src/test/ui/stable-features.rs b/src/test/ui/stable-features.rs
new file mode 100644
index 0000000..ed7f089
--- /dev/null
+++ b/src/test/ui/stable-features.rs
@@ -0,0 +1,14 @@
+// Testing that the stable_features lint catches use of stable
+// language and lib features.
+
+#![deny(stable_features)]
+
+#![feature(test_accepted_feature)]
+//~^ ERROR the feature `test_accepted_feature` has been stable since 1.0.0
+
+#![feature(rust1)]
+//~^ ERROR the feature `rust1` has been stable since 1.0.0
+
+fn main() {
+    let _foo: Vec<()> = Vec::new();
+}
diff --git a/src/test/ui/stable-features.stderr b/src/test/ui/stable-features.stderr
new file mode 100644
index 0000000..537c3f0
--- /dev/null
+++ b/src/test/ui/stable-features.stderr
@@ -0,0 +1,20 @@
+error: the feature `test_accepted_feature` has been stable since 1.0.0 and no longer requires an attribute to enable
+  --> $DIR/stable-features.rs:6:12
+   |
+LL | #![feature(test_accepted_feature)]
+   |            ^^^^^^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/stable-features.rs:4:9
+   |
+LL | #![deny(stable_features)]
+   |         ^^^^^^^^^^^^^^^
+
+error: the feature `rust1` has been stable since 1.0.0 and no longer requires an attribute to enable
+  --> $DIR/stable-features.rs:9:12
+   |
+LL | #![feature(rust1)]
+   |            ^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/static/auxiliary/static-priv-by-default.rs b/src/test/ui/static/auxiliary/static-priv-by-default.rs
new file mode 100644
index 0000000..41f368f
--- /dev/null
+++ b/src/test/ui/static/auxiliary/static-priv-by-default.rs
@@ -0,0 +1,27 @@
+// aux-build:static_priv_by_default.rs
+
+extern crate static_priv_by_default;
+
+mod child {
+    pub mod childs_child {
+        static private: isize = 0;
+        pub static public: isize = 0;
+    }
+}
+
+fn foo(_: isize) {}
+
+fn full_ref() {
+    foo(static_priv_by_default::private); //~ ERROR: static `private` is private
+    foo(static_priv_by_default::public);
+    foo(child::childs_child::private); //~ ERROR: static `private` is private
+    foo(child::childs_child::public);
+}
+
+fn medium_ref() {
+    use child::childs_child;
+    foo(childs_child::private); //~ ERROR: static `private` is private
+    foo(childs_child::public);
+}
+
+fn main() {}
diff --git a/src/test/ui/static/auxiliary/static_priv_by_default.rs b/src/test/ui/static/auxiliary/static_priv_by_default.rs
new file mode 100644
index 0000000..39f9120
--- /dev/null
+++ b/src/test/ui/static/auxiliary/static_priv_by_default.rs
@@ -0,0 +1,51 @@
+#![crate_type = "lib"]
+
+static private: isize = 0;
+pub static public: isize = 0;
+
+pub struct A(());
+
+impl A {
+    fn foo() {}
+}
+
+mod foo {
+    pub static a: isize = 0;
+    pub fn b() {}
+    pub struct c;
+    pub enum d {}
+    pub type e = isize;
+
+    pub struct A(());
+
+    impl A {
+        fn foo() {}
+    }
+
+    // these are public so the parent can re-export them.
+    pub static reexported_a: isize = 0;
+    pub fn reexported_b() {}
+    pub struct reexported_c;
+    pub enum reexported_d {}
+    pub type reexported_e = isize;
+}
+
+pub mod bar {
+    pub use foo::reexported_a as e;
+    pub use foo::reexported_b as f;
+    pub use foo::reexported_c as g;
+    pub use foo::reexported_d as h;
+    pub use foo::reexported_e as i;
+}
+
+pub static a: isize = 0;
+pub fn b() {}
+pub struct c;
+pub enum d {}
+pub type e = isize;
+
+static j: isize = 0;
+fn k() {}
+struct l;
+enum m {}
+type n = isize;
diff --git a/src/test/ui/static/static-closures.rs b/src/test/ui/static/static-closures.rs
new file mode 100644
index 0000000..1bd518d
--- /dev/null
+++ b/src/test/ui/static/static-closures.rs
@@ -0,0 +1,4 @@
+fn main() {
+    static || {};
+    //~^ ERROR closures cannot be static
+}
diff --git a/src/test/ui/static/static-closures.stderr b/src/test/ui/static/static-closures.stderr
new file mode 100644
index 0000000..99235e2
--- /dev/null
+++ b/src/test/ui/static/static-closures.stderr
@@ -0,0 +1,9 @@
+error[E0697]: closures cannot be static
+  --> $DIR/static-closures.rs:2:5
+   |
+LL |     static || {};
+   |     ^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0697`.
diff --git a/src/test/ui/static/static-drop-scope.nll.stderr b/src/test/ui/static/static-drop-scope.nll.stderr
new file mode 100644
index 0000000..df6383b
--- /dev/null
+++ b/src/test/ui/static/static-drop-scope.nll.stderr
@@ -0,0 +1,72 @@
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/static-drop-scope.rs:9:60
+   |
+LL | static PROMOTION_FAIL_S: Option<&'static WithDtor> = Some(&WithDtor);
+   |                                                            ^^^^^^^^ statics cannot evaluate destructors
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/static-drop-scope.rs:9:60
+   |
+LL | static PROMOTION_FAIL_S: Option<&'static WithDtor> = Some(&WithDtor);
+   |                                                      ------^^^^^^^^-
+   |                                                      |     |       |
+   |                                                      |     |       temporary value is freed at the end of this statement
+   |                                                      |     creates a temporary which is freed while still in use
+   |                                                      using this value as a static requires that borrow lasts for `'static`
+
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/static-drop-scope.rs:13:59
+   |
+LL | const PROMOTION_FAIL_C: Option<&'static WithDtor> = Some(&WithDtor);
+   |                                                           ^^^^^^^^ constants cannot evaluate destructors
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/static-drop-scope.rs:13:59
+   |
+LL | const PROMOTION_FAIL_C: Option<&'static WithDtor> = Some(&WithDtor);
+   |                                                     ------^^^^^^^^-
+   |                                                     |     |       |
+   |                                                     |     |       temporary value is freed at the end of this statement
+   |                                                     |     creates a temporary which is freed while still in use
+   |                                                     using this value as a constant requires that borrow lasts for `'static`
+
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/static-drop-scope.rs:17:28
+   |
+LL | static EARLY_DROP_S: i32 = (WithDtor, 0).1;
+   |                            ^^^^^^^^^^^^^ statics cannot evaluate destructors
+
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/static-drop-scope.rs:20:27
+   |
+LL | const EARLY_DROP_C: i32 = (WithDtor, 0).1;
+   |                           ^^^^^^^^^^^^^ constants cannot evaluate destructors
+
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/static-drop-scope.rs:23:24
+   |
+LL | const fn const_drop<T>(_: T) {}
+   |                        ^ constant functions cannot evaluate destructors
+
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/static-drop-scope.rs:27:5
+   |
+LL |     (x, ()).1
+   |     ^^^^^^^ constant functions cannot evaluate destructors
+
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/static-drop-scope.rs:31:34
+   |
+LL | const EARLY_DROP_C_OPTION: i32 = (Some(WithDtor), 0).1;
+   |                                  ^^^^^^^^^^^^^^^^^^^ constants cannot evaluate destructors
+
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/static-drop-scope.rs:36:43
+   |
+LL | const EARLY_DROP_C_OPTION_CONSTANT: i32 = (HELPER, 0).1;
+   |                                           ^^^^^^^^^^^ constants cannot evaluate destructors
+
+error: aborting due to 10 previous errors
+
+Some errors occurred: E0493, E0716.
+For more information about an error, try `rustc --explain E0493`.
diff --git a/src/test/ui/static/static-drop-scope.rs b/src/test/ui/static/static-drop-scope.rs
new file mode 100644
index 0000000..e5a9f2a
--- /dev/null
+++ b/src/test/ui/static/static-drop-scope.rs
@@ -0,0 +1,39 @@
+#![feature(const_fn)]
+
+struct WithDtor;
+
+impl Drop for WithDtor {
+    fn drop(&mut self) {}
+}
+
+static PROMOTION_FAIL_S: Option<&'static WithDtor> = Some(&WithDtor);
+//~^ ERROR destructors cannot be evaluated at compile-time
+//~| ERROR borrowed value does not live long enoug
+
+const PROMOTION_FAIL_C: Option<&'static WithDtor> = Some(&WithDtor);
+//~^ ERROR destructors cannot be evaluated at compile-time
+//~| ERROR borrowed value does not live long enoug
+
+static EARLY_DROP_S: i32 = (WithDtor, 0).1;
+//~^ ERROR destructors cannot be evaluated at compile-time
+
+const EARLY_DROP_C: i32 = (WithDtor, 0).1;
+//~^ ERROR destructors cannot be evaluated at compile-time
+
+const fn const_drop<T>(_: T) {}
+//~^ ERROR destructors cannot be evaluated at compile-time
+
+const fn const_drop2<T>(x: T) {
+    (x, ()).1
+    //~^ ERROR destructors cannot be evaluated at compile-time
+}
+
+const EARLY_DROP_C_OPTION: i32 = (Some(WithDtor), 0).1;
+//~^ ERROR destructors cannot be evaluated at compile-time
+
+const HELPER: Option<WithDtor> = Some(WithDtor);
+
+const EARLY_DROP_C_OPTION_CONSTANT: i32 = (HELPER, 0).1;
+//~^ ERROR destructors cannot be evaluated at compile-time
+
+fn main () {}
diff --git a/src/test/ui/static/static-drop-scope.stderr b/src/test/ui/static/static-drop-scope.stderr
new file mode 100644
index 0000000..3e3032e
--- /dev/null
+++ b/src/test/ui/static/static-drop-scope.stderr
@@ -0,0 +1,72 @@
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/static-drop-scope.rs:9:60
+   |
+LL | static PROMOTION_FAIL_S: Option<&'static WithDtor> = Some(&WithDtor);
+   |                                                            ^^^^^^^^ statics cannot evaluate destructors
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/static-drop-scope.rs:9:60
+   |
+LL | static PROMOTION_FAIL_S: Option<&'static WithDtor> = Some(&WithDtor);
+   |                                                            ^^^^^^^^- temporary value only lives until here
+   |                                                            |
+   |                                                            temporary value does not live long enough
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/static-drop-scope.rs:13:59
+   |
+LL | const PROMOTION_FAIL_C: Option<&'static WithDtor> = Some(&WithDtor);
+   |                                                           ^^^^^^^^ constants cannot evaluate destructors
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/static-drop-scope.rs:13:59
+   |
+LL | const PROMOTION_FAIL_C: Option<&'static WithDtor> = Some(&WithDtor);
+   |                                                           ^^^^^^^^- temporary value only lives until here
+   |                                                           |
+   |                                                           temporary value does not live long enough
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/static-drop-scope.rs:17:28
+   |
+LL | static EARLY_DROP_S: i32 = (WithDtor, 0).1;
+   |                            ^^^^^^^^^^^^^ statics cannot evaluate destructors
+
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/static-drop-scope.rs:20:27
+   |
+LL | const EARLY_DROP_C: i32 = (WithDtor, 0).1;
+   |                           ^^^^^^^^^^^^^ constants cannot evaluate destructors
+
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/static-drop-scope.rs:23:24
+   |
+LL | const fn const_drop<T>(_: T) {}
+   |                        ^ constant functions cannot evaluate destructors
+
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/static-drop-scope.rs:27:5
+   |
+LL |     (x, ()).1
+   |     ^^^^^^^ constant functions cannot evaluate destructors
+
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/static-drop-scope.rs:31:34
+   |
+LL | const EARLY_DROP_C_OPTION: i32 = (Some(WithDtor), 0).1;
+   |                                  ^^^^^^^^^^^^^^^^^^^ constants cannot evaluate destructors
+
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/static-drop-scope.rs:36:43
+   |
+LL | const EARLY_DROP_C_OPTION_CONSTANT: i32 = (HELPER, 0).1;
+   |                                           ^^^^^^^^^^^ constants cannot evaluate destructors
+
+error: aborting due to 10 previous errors
+
+Some errors occurred: E0493, E0597.
+For more information about an error, try `rustc --explain E0493`.
diff --git a/src/test/ui/static/static-extern-type.rs b/src/test/ui/static/static-extern-type.rs
new file mode 100644
index 0000000..3666982
--- /dev/null
+++ b/src/test/ui/static/static-extern-type.rs
@@ -0,0 +1,27 @@
+// compile-pass
+#![feature(extern_types)]
+
+pub mod a {
+    extern "C" {
+        pub type StartFn;
+        pub static start: StartFn;
+    }
+}
+
+pub mod b {
+    #[repr(transparent)]
+    pub struct TransparentType(::a::StartFn);
+    extern "C" {
+        pub static start: TransparentType;
+    }
+}
+
+pub mod c {
+    #[repr(C)]
+    pub struct CType(u32, ::b::TransparentType);
+    extern "C" {
+        pub static start: CType;
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/static/static-items-cant-move.rs b/src/test/ui/static/static-items-cant-move.rs
new file mode 100644
index 0000000..3e7aaa0
--- /dev/null
+++ b/src/test/ui/static/static-items-cant-move.rs
@@ -0,0 +1,19 @@
+// Verifies that static items can't be moved
+
+struct B;
+
+struct Foo {
+    foo: isize,
+    b: B,
+}
+
+static BAR: Foo = Foo { foo: 5, b: B };
+
+
+fn test(f: Foo) {
+    let _f = Foo{foo: 4, ..f};
+}
+
+fn main() {
+    test(BAR); //~ ERROR cannot move out of static item
+}
diff --git a/src/test/ui/static/static-items-cant-move.stderr b/src/test/ui/static/static-items-cant-move.stderr
new file mode 100644
index 0000000..fc1ed9b
--- /dev/null
+++ b/src/test/ui/static/static-items-cant-move.stderr
@@ -0,0 +1,9 @@
+error[E0507]: cannot move out of static item
+  --> $DIR/static-items-cant-move.rs:18:10
+   |
+LL |     test(BAR);
+   |          ^^^ cannot move out of static item
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/static/static-lifetime-bound.nll.stderr b/src/test/ui/static/static-lifetime-bound.nll.stderr
new file mode 100644
index 0000000..90d7282
--- /dev/null
+++ b/src/test/ui/static/static-lifetime-bound.nll.stderr
@@ -0,0 +1,22 @@
+warning: unnecessary lifetime parameter `'a`
+  --> $DIR/static-lifetime-bound.rs:1:6
+   |
+LL | fn f<'a: 'static>(_: &'a i32) {}
+   |      ^^^^^^^^^^^
+   |
+   = help: you can use the `'static` lifetime directly, in place of `'a`
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/static-lifetime-bound.rs:5:7
+   |
+LL |     f(&x);
+   |     --^^-
+   |     | |
+   |     | borrowed value does not live long enough
+   |     argument requires that `x` is borrowed for `'static`
+LL | }
+   | - `x` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/static/static-lifetime-bound.rs b/src/test/ui/static/static-lifetime-bound.rs
new file mode 100644
index 0000000..b5da91e
--- /dev/null
+++ b/src/test/ui/static/static-lifetime-bound.rs
@@ -0,0 +1,6 @@
+fn f<'a: 'static>(_: &'a i32) {} //~WARN unnecessary lifetime parameter `'a`
+
+fn main() {
+    let x = 0;
+    f(&x); //~ERROR does not live long enough
+}
diff --git a/src/test/ui/static/static-lifetime-bound.stderr b/src/test/ui/static/static-lifetime-bound.stderr
new file mode 100644
index 0000000..b9aa4d8
--- /dev/null
+++ b/src/test/ui/static/static-lifetime-bound.stderr
@@ -0,0 +1,21 @@
+warning: unnecessary lifetime parameter `'a`
+  --> $DIR/static-lifetime-bound.rs:1:6
+   |
+LL | fn f<'a: 'static>(_: &'a i32) {}
+   |      ^^^^^^^^^^^
+   |
+   = help: you can use the `'static` lifetime directly, in place of `'a`
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/static-lifetime-bound.rs:5:8
+   |
+LL |     f(&x);
+   |        ^ borrowed value does not live long enough
+LL | }
+   | - borrowed value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/static/static-lifetime.rs b/src/test/ui/static/static-lifetime.rs
new file mode 100644
index 0000000..ce1eeb6
--- /dev/null
+++ b/src/test/ui/static/static-lifetime.rs
@@ -0,0 +1,6 @@
+pub trait Arbitrary: Sized + 'static {}
+
+impl<'a, A: Clone> Arbitrary for ::std::borrow::Cow<'a, A> {} //~ ERROR lifetime bound
+
+fn main() {
+}
diff --git a/src/test/ui/static/static-lifetime.stderr b/src/test/ui/static/static-lifetime.stderr
new file mode 100644
index 0000000..8516ac0
--- /dev/null
+++ b/src/test/ui/static/static-lifetime.stderr
@@ -0,0 +1,16 @@
+error[E0478]: lifetime bound not satisfied
+  --> $DIR/static-lifetime.rs:3:20
+   |
+LL | impl<'a, A: Clone> Arbitrary for ::std::borrow::Cow<'a, A> {}
+   |                    ^^^^^^^^^
+   |
+note: lifetime parameter instantiated with the lifetime 'a as defined on the impl at 3:6
+  --> $DIR/static-lifetime.rs:3:6
+   |
+LL | impl<'a, A: Clone> Arbitrary for ::std::borrow::Cow<'a, A> {}
+   |      ^^
+   = note: but lifetime parameter must outlive the static lifetime
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0478`.
diff --git a/src/test/ui/static/static-method-privacy.rs b/src/test/ui/static/static-method-privacy.rs
new file mode 100644
index 0000000..b637037
--- /dev/null
+++ b/src/test/ui/static/static-method-privacy.rs
@@ -0,0 +1,10 @@
+mod a {
+    pub struct S;
+    impl S {
+        fn new() -> S { S }
+    }
+}
+
+fn main() {
+    let _ = a::S::new();    //~ ERROR method `new` is private
+}
diff --git a/src/test/ui/static/static-method-privacy.stderr b/src/test/ui/static/static-method-privacy.stderr
new file mode 100644
index 0000000..14ca9f5
--- /dev/null
+++ b/src/test/ui/static/static-method-privacy.stderr
@@ -0,0 +1,9 @@
+error[E0624]: method `new` is private
+  --> $DIR/static-method-privacy.rs:9:13
+   |
+LL |     let _ = a::S::new();
+   |             ^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0624`.
diff --git a/src/test/ui/static/static-mut-bad-types.rs b/src/test/ui/static/static-mut-bad-types.rs
new file mode 100644
index 0000000..8a98b1b
--- /dev/null
+++ b/src/test/ui/static/static-mut-bad-types.rs
@@ -0,0 +1,7 @@
+static mut a: isize = 3;
+
+fn main() {
+    unsafe {
+        a = true; //~ ERROR: mismatched types
+    }
+}
diff --git a/src/test/ui/static/static-mut-bad-types.stderr b/src/test/ui/static/static-mut-bad-types.stderr
new file mode 100644
index 0000000..88d6201
--- /dev/null
+++ b/src/test/ui/static/static-mut-bad-types.stderr
@@ -0,0 +1,9 @@
+error[E0308]: mismatched types
+  --> $DIR/static-mut-bad-types.rs:5:13
+   |
+LL |         a = true;
+   |             ^^^^ expected isize, found bool
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/static/static-mut-foreign-requires-unsafe.rs b/src/test/ui/static/static-mut-foreign-requires-unsafe.rs
new file mode 100644
index 0000000..535f6bc
--- /dev/null
+++ b/src/test/ui/static/static-mut-foreign-requires-unsafe.rs
@@ -0,0 +1,9 @@
+extern {
+    static mut a: i32;
+}
+
+fn main() {
+    a += 3;     //~ ERROR: requires unsafe
+    a = 4;      //~ ERROR: requires unsafe
+    let _b = a; //~ ERROR: requires unsafe
+}
diff --git a/src/test/ui/static/static-mut-foreign-requires-unsafe.stderr b/src/test/ui/static/static-mut-foreign-requires-unsafe.stderr
new file mode 100644
index 0000000..e7ed0b7
--- /dev/null
+++ b/src/test/ui/static/static-mut-foreign-requires-unsafe.stderr
@@ -0,0 +1,27 @@
+error[E0133]: use of mutable static is unsafe and requires unsafe function or block
+  --> $DIR/static-mut-foreign-requires-unsafe.rs:6:5
+   |
+LL |     a += 3;
+   |     ^^^^^^ use of mutable static
+   |
+   = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
+
+error[E0133]: use of mutable static is unsafe and requires unsafe function or block
+  --> $DIR/static-mut-foreign-requires-unsafe.rs:7:5
+   |
+LL |     a = 4;
+   |     ^^^^^ use of mutable static
+   |
+   = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
+
+error[E0133]: use of mutable static is unsafe and requires unsafe function or block
+  --> $DIR/static-mut-foreign-requires-unsafe.rs:8:14
+   |
+LL |     let _b = a;
+   |              ^ use of mutable static
+   |
+   = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/static/static-mut-not-constant.rs b/src/test/ui/static/static-mut-not-constant.rs
new file mode 100644
index 0000000..84d401c
--- /dev/null
+++ b/src/test/ui/static/static-mut-not-constant.rs
@@ -0,0 +1,7 @@
+#![feature(box_syntax)]
+
+static mut a: Box<isize> = box 3;
+//~^ ERROR allocations are not allowed in statics
+//~| ERROR static contains unimplemented expression type
+
+fn main() {}
diff --git a/src/test/ui/static/static-mut-not-constant.stderr b/src/test/ui/static/static-mut-not-constant.stderr
new file mode 100644
index 0000000..d2c6ba6
--- /dev/null
+++ b/src/test/ui/static/static-mut-not-constant.stderr
@@ -0,0 +1,16 @@
+error[E0010]: allocations are not allowed in statics
+  --> $DIR/static-mut-not-constant.rs:3:28
+   |
+LL | static mut a: Box<isize> = box 3;
+   |                            ^^^^^ allocation not allowed in statics
+
+error[E0019]: static contains unimplemented expression type
+  --> $DIR/static-mut-not-constant.rs:3:32
+   |
+LL | static mut a: Box<isize> = box 3;
+   |                                ^
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0010, E0019.
+For more information about an error, try `rustc --explain E0010`.
diff --git a/src/test/ui/static/static-mut-not-pat.rs b/src/test/ui/static/static-mut-not-pat.rs
new file mode 100644
index 0000000..ce5ae16
--- /dev/null
+++ b/src/test/ui/static/static-mut-not-pat.rs
@@ -0,0 +1,43 @@
+// Constants (static variables) can be used to match in patterns, but mutable
+// statics cannot. This ensures that there's some form of error if this is
+// attempted.
+
+static mut a: isize = 3;
+
+fn main() {
+    // If they can't be matched against, then it's possible to capture the same
+    // name as a variable, hence this should be an unreachable pattern situation
+    // instead of spitting out a custom error about some identifier collisions
+    // (we should allow shadowing)
+    match 4 {
+        a => {} //~ ERROR match bindings cannot shadow statics
+        _ => {}
+    }
+}
+
+struct NewBool(bool);
+enum Direction {
+    North,
+    East,
+    South,
+    West
+}
+const NEW_FALSE: NewBool = NewBool(false);
+struct Foo {
+    bar: Option<Direction>,
+    baz: NewBool
+}
+
+static mut STATIC_MUT_FOO: Foo = Foo { bar: Some(Direction::West), baz: NEW_FALSE };
+
+fn mutable_statics() {
+    match (Foo { bar: Some(Direction::North), baz: NewBool(true) }) {
+        Foo { bar: None, baz: NewBool(true) } => (),
+        STATIC_MUT_FOO => (),
+        //~^ ERROR match bindings cannot shadow statics
+        Foo { bar: Some(Direction::South), .. } => (),
+        Foo { bar: Some(EAST), .. } => (),
+        Foo { bar: Some(Direction::North), baz: NewBool(true) } => (),
+        Foo { bar: Some(EAST), baz: NewBool(false) } => ()
+    }
+}
diff --git a/src/test/ui/static/static-mut-not-pat.stderr b/src/test/ui/static/static-mut-not-pat.stderr
new file mode 100644
index 0000000..33c1cd6
--- /dev/null
+++ b/src/test/ui/static/static-mut-not-pat.stderr
@@ -0,0 +1,21 @@
+error[E0530]: match bindings cannot shadow statics
+  --> $DIR/static-mut-not-pat.rs:13:9
+   |
+LL | static mut a: isize = 3;
+   | ------------------------ the static `a` is defined here
+...
+LL |         a => {}
+   |         ^ cannot be named the same as a static
+
+error[E0530]: match bindings cannot shadow statics
+  --> $DIR/static-mut-not-pat.rs:36:9
+   |
+LL | static mut STATIC_MUT_FOO: Foo = Foo { bar: Some(Direction::West), baz: NEW_FALSE };
+   | ------------------------------------------------------------------------------------ the static `STATIC_MUT_FOO` is defined here
+...
+LL |         STATIC_MUT_FOO => (),
+   |         ^^^^^^^^^^^^^^ cannot be named the same as a static
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0530`.
diff --git a/src/test/ui/static/static-mut-requires-unsafe.rs b/src/test/ui/static/static-mut-requires-unsafe.rs
new file mode 100644
index 0000000..413b97e
--- /dev/null
+++ b/src/test/ui/static/static-mut-requires-unsafe.rs
@@ -0,0 +1,7 @@
+static mut a: isize = 3;
+
+fn main() {
+    a += 3;         //~ ERROR: requires unsafe
+    a = 4;          //~ ERROR: requires unsafe
+    let _b = a;     //~ ERROR: requires unsafe
+}
diff --git a/src/test/ui/static/static-mut-requires-unsafe.stderr b/src/test/ui/static/static-mut-requires-unsafe.stderr
new file mode 100644
index 0000000..85e468b
--- /dev/null
+++ b/src/test/ui/static/static-mut-requires-unsafe.stderr
@@ -0,0 +1,27 @@
+error[E0133]: use of mutable static is unsafe and requires unsafe function or block
+  --> $DIR/static-mut-requires-unsafe.rs:4:5
+   |
+LL |     a += 3;
+   |     ^^^^^^ use of mutable static
+   |
+   = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
+
+error[E0133]: use of mutable static is unsafe and requires unsafe function or block
+  --> $DIR/static-mut-requires-unsafe.rs:5:5
+   |
+LL |     a = 4;
+   |     ^^^^^ use of mutable static
+   |
+   = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
+
+error[E0133]: use of mutable static is unsafe and requires unsafe function or block
+  --> $DIR/static-mut-requires-unsafe.rs:6:14
+   |
+LL |     let _b = a;
+   |              ^ use of mutable static
+   |
+   = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/static/static-priv-by-default2.rs b/src/test/ui/static/static-priv-by-default2.rs
new file mode 100644
index 0000000..bbbdb25
--- /dev/null
+++ b/src/test/ui/static/static-priv-by-default2.rs
@@ -0,0 +1,30 @@
+// aux-build:static_priv_by_default.rs
+
+extern crate static_priv_by_default;
+
+mod child {
+    pub mod childs_child {
+        static private: isize = 0;
+        pub static public: isize = 0;
+    }
+}
+
+fn foo<T>(_: T) {}
+
+fn test1() {
+    use child::childs_child::private;
+    //~^ ERROR: static `private` is private
+    use child::childs_child::public;
+
+    foo(private);
+}
+
+fn test2() {
+    use static_priv_by_default::private;
+    //~^ ERROR: static `private` is private
+    use static_priv_by_default::public;
+
+    foo(private);
+}
+
+fn main() {}
diff --git a/src/test/ui/static/static-priv-by-default2.stderr b/src/test/ui/static/static-priv-by-default2.stderr
new file mode 100644
index 0000000..95bcf07
--- /dev/null
+++ b/src/test/ui/static/static-priv-by-default2.stderr
@@ -0,0 +1,15 @@
+error[E0603]: static `private` is private
+  --> $DIR/static-priv-by-default2.rs:15:30
+   |
+LL |     use child::childs_child::private;
+   |                              ^^^^^^^
+
+error[E0603]: static `private` is private
+  --> $DIR/static-priv-by-default2.rs:23:33
+   |
+LL |     use static_priv_by_default::private;
+   |                                 ^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0603`.
diff --git a/src/test/ui/static/static-reference-to-fn-1.rs b/src/test/ui/static/static-reference-to-fn-1.rs
new file mode 100644
index 0000000..c15634d
--- /dev/null
+++ b/src/test/ui/static/static-reference-to-fn-1.rs
@@ -0,0 +1,24 @@
+struct A<'a> {
+    func: &'a fn() -> Option<isize>
+}
+
+impl<'a> A<'a> {
+    fn call(&self) -> Option<isize> {
+        (*self.func)()
+    }
+}
+
+fn foo() -> Option<isize> {
+    None
+}
+
+fn create() -> A<'static> {
+    A {
+        func: &foo, //~ ERROR mismatched types
+    }
+}
+
+fn main() {
+    let a = create();
+    a.call();
+}
diff --git a/src/test/ui/static/static-reference-to-fn-1.stderr b/src/test/ui/static/static-reference-to-fn-1.stderr
new file mode 100644
index 0000000..f6d2385
--- /dev/null
+++ b/src/test/ui/static/static-reference-to-fn-1.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/static-reference-to-fn-1.rs:17:15
+   |
+LL |         func: &foo,
+   |               ^^^^ expected fn pointer, found fn item
+   |
+   = note: expected type `&fn() -> std::option::Option<isize>`
+              found type `&fn() -> std::option::Option<isize> {foo}`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/static/static-reference-to-fn-2.nll.stderr b/src/test/ui/static/static-reference-to-fn-2.nll.stderr
new file mode 100644
index 0000000..07c8b48
--- /dev/null
+++ b/src/test/ui/static/static-reference-to-fn-2.nll.stderr
@@ -0,0 +1,47 @@
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/static-reference-to-fn-2.rs:18:22
+   |
+LL | fn state1(self_: &mut StateMachineIter) -> Option<&'static str> {
+   |           ----- has type `&mut StateMachineIter<'1>`
+LL |     self_.statefn = &id(state2 as StateMachineFunc);
+   |     -----------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- temporary value is freed at the end of this statement
+   |     |                |
+   |     |                creates a temporary which is freed while still in use
+   |     assignment requires that borrow lasts for `'1`
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/static-reference-to-fn-2.rs:24:22
+   |
+LL | fn state2(self_: &mut StateMachineIter) -> Option<(&'static str)> {
+   |           ----- has type `&mut StateMachineIter<'1>`
+LL |     self_.statefn = &id(state3 as StateMachineFunc);
+   |     -----------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- temporary value is freed at the end of this statement
+   |     |                |
+   |     |                creates a temporary which is freed while still in use
+   |     assignment requires that borrow lasts for `'1`
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/static-reference-to-fn-2.rs:30:22
+   |
+LL | fn state3(self_: &mut StateMachineIter) -> Option<(&'static str)> {
+   |           ----- has type `&mut StateMachineIter<'1>`
+LL |     self_.statefn = &id(finished as StateMachineFunc);
+   |     -----------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- temporary value is freed at the end of this statement
+   |     |                |
+   |     |                creates a temporary which is freed while still in use
+   |     assignment requires that borrow lasts for `'1`
+
+error[E0515]: cannot return value referencing temporary value
+  --> $DIR/static-reference-to-fn-2.rs:40:5
+   |
+LL | /     StateMachineIter {
+LL | |         statefn: &id(state1 as StateMachineFunc)
+   | |                   ------------------------------ temporary value created here
+LL | |
+LL | |     }
+   | |_____^ returns a value referencing data owned by the current function
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0515, E0716.
+For more information about an error, try `rustc --explain E0515`.
diff --git a/src/test/ui/static/static-reference-to-fn-2.rs b/src/test/ui/static/static-reference-to-fn-2.rs
new file mode 100644
index 0000000..8e66532
--- /dev/null
+++ b/src/test/ui/static/static-reference-to-fn-2.rs
@@ -0,0 +1,54 @@
+fn id<T>(x: T) -> T { x }
+
+struct StateMachineIter<'a> {
+    statefn: &'a StateMachineFunc<'a>
+}
+
+type StateMachineFunc<'a> = fn(&mut StateMachineIter<'a>) -> Option<&'static str>;
+
+impl<'a> Iterator for StateMachineIter<'a> {
+    type Item = &'static str;
+
+    fn next(&mut self) -> Option<&'static str> {
+        return  (*self.statefn)(self);
+    }
+}
+
+fn state1(self_: &mut StateMachineIter) -> Option<&'static str> {
+    self_.statefn = &id(state2 as StateMachineFunc);
+    //~^ ERROR borrowed value does not live long enough
+    return Some("state1");
+}
+
+fn state2(self_: &mut StateMachineIter) -> Option<(&'static str)> {
+    self_.statefn = &id(state3 as StateMachineFunc);
+    //~^ ERROR borrowed value does not live long enough
+    return Some("state2");
+}
+
+fn state3(self_: &mut StateMachineIter) -> Option<(&'static str)> {
+    self_.statefn = &id(finished as StateMachineFunc);
+    //~^ ERROR borrowed value does not live long enough
+    return Some("state3");
+}
+
+fn finished(_: &mut StateMachineIter) -> Option<(&'static str)> {
+    return None;
+}
+
+fn state_iter() -> StateMachineIter<'static> {
+    StateMachineIter {
+        statefn: &id(state1 as StateMachineFunc)
+        //~^ ERROR borrowed value does not live long enough
+    }
+}
+
+
+fn main() {
+    let mut it = state_iter();
+    println!("{:?}",it.next());
+    println!("{:?}",it.next());
+    println!("{:?}",it.next());
+    println!("{:?}",it.next());
+    println!("{:?}",it.next());
+}
diff --git a/src/test/ui/static/static-reference-to-fn-2.stderr b/src/test/ui/static/static-reference-to-fn-2.stderr
new file mode 100644
index 0000000..17d4a36
--- /dev/null
+++ b/src/test/ui/static/static-reference-to-fn-2.stderr
@@ -0,0 +1,71 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/static-reference-to-fn-2.rs:18:22
+   |
+LL |     self_.statefn = &id(state2 as StateMachineFunc);
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- temporary value only lives until here
+   |                      |
+   |                      temporary value does not live long enough
+   |
+note: borrowed value must be valid for the anonymous lifetime #2 defined on the function body at 17:1...
+  --> $DIR/static-reference-to-fn-2.rs:17:1
+   |
+LL | / fn state1(self_: &mut StateMachineIter) -> Option<&'static str> {
+LL | |     self_.statefn = &id(state2 as StateMachineFunc);
+LL | |
+LL | |     return Some("state1");
+LL | | }
+   | |_^
+   = note: consider using a `let` binding to increase its lifetime
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/static-reference-to-fn-2.rs:24:22
+   |
+LL |     self_.statefn = &id(state3 as StateMachineFunc);
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- temporary value only lives until here
+   |                      |
+   |                      temporary value does not live long enough
+   |
+note: borrowed value must be valid for the anonymous lifetime #2 defined on the function body at 23:1...
+  --> $DIR/static-reference-to-fn-2.rs:23:1
+   |
+LL | / fn state2(self_: &mut StateMachineIter) -> Option<(&'static str)> {
+LL | |     self_.statefn = &id(state3 as StateMachineFunc);
+LL | |
+LL | |     return Some("state2");
+LL | | }
+   | |_^
+   = note: consider using a `let` binding to increase its lifetime
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/static-reference-to-fn-2.rs:30:22
+   |
+LL |     self_.statefn = &id(finished as StateMachineFunc);
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- temporary value only lives until here
+   |                      |
+   |                      temporary value does not live long enough
+   |
+note: borrowed value must be valid for the anonymous lifetime #2 defined on the function body at 29:1...
+  --> $DIR/static-reference-to-fn-2.rs:29:1
+   |
+LL | / fn state3(self_: &mut StateMachineIter) -> Option<(&'static str)> {
+LL | |     self_.statefn = &id(finished as StateMachineFunc);
+LL | |
+LL | |     return Some("state3");
+LL | | }
+   | |_^
+   = note: consider using a `let` binding to increase its lifetime
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/static-reference-to-fn-2.rs:41:19
+   |
+LL |         statefn: &id(state1 as StateMachineFunc)
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+...
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/static/static-region-bound.nll.stderr b/src/test/ui/static/static-region-bound.nll.stderr
new file mode 100644
index 0000000..1526125
--- /dev/null
+++ b/src/test/ui/static/static-region-bound.nll.stderr
@@ -0,0 +1,13 @@
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/static-region-bound.rs:10:14
+   |
+LL |     let x = &id(3);
+   |              ^^^^^ creates a temporary which is freed while still in use
+LL |     f(x);
+   |     ---- argument requires that borrow lasts for `'static`
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/src/test/ui/static/static-region-bound.rs b/src/test/ui/static/static-region-bound.rs
new file mode 100644
index 0000000..ee41137
--- /dev/null
+++ b/src/test/ui/static/static-region-bound.rs
@@ -0,0 +1,12 @@
+#![feature(box_syntax)]
+
+fn id<T>(x: T) -> T { x }
+
+fn f<T:'static>(_: T) {}
+
+fn main() {
+    let x: Box<_> = box 3;
+    f(x);
+    let x = &id(3); //~ ERROR borrowed value does not live long enough
+    f(x);
+}
diff --git a/src/test/ui/static/static-region-bound.stderr b/src/test/ui/static/static-region-bound.stderr
new file mode 100644
index 0000000..f6bbfce
--- /dev/null
+++ b/src/test/ui/static/static-region-bound.stderr
@@ -0,0 +1,14 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/static-region-bound.rs:10:14
+   |
+LL |     let x = &id(3);
+   |              ^^^^^ temporary value does not live long enough
+LL |     f(x);
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/static/static-vec-repeat-not-constant.rs b/src/test/ui/static/static-vec-repeat-not-constant.rs
new file mode 100644
index 0000000..61c87b1
--- /dev/null
+++ b/src/test/ui/static/static-vec-repeat-not-constant.rs
@@ -0,0 +1,6 @@
+fn foo() -> isize { 23 }
+
+static a: [isize; 2] = [foo(); 2];
+//~^ ERROR: E0015
+
+fn main() {}
diff --git a/src/test/ui/static/static-vec-repeat-not-constant.stderr b/src/test/ui/static/static-vec-repeat-not-constant.stderr
new file mode 100644
index 0000000..ef98aa5
--- /dev/null
+++ b/src/test/ui/static/static-vec-repeat-not-constant.stderr
@@ -0,0 +1,9 @@
+error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
+  --> $DIR/static-vec-repeat-not-constant.rs:3:25
+   |
+LL | static a: [isize; 2] = [foo(); 2];
+   |                         ^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0015`.
diff --git a/src/test/ui/static_sized_requirement.rs b/src/test/ui/static_sized_requirement.rs
new file mode 100644
index 0000000..0ee0637
--- /dev/null
+++ b/src/test/ui/static_sized_requirement.rs
@@ -0,0 +1,12 @@
+// compile-pass
+
+#![feature(no_core, lang_items)]
+#![no_core]
+#![crate_type = "lib"]
+
+#[lang = "sized"]
+trait Sized {}
+
+extern {
+    pub static A: u32;
+}
diff --git a/src/test/ui/staticness-mismatch.rs b/src/test/ui/staticness-mismatch.rs
new file mode 100644
index 0000000..8710d01
--- /dev/null
+++ b/src/test/ui/staticness-mismatch.rs
@@ -0,0 +1,11 @@
+trait Foo {
+    fn dummy(&self) { }
+    fn bar();
+}
+
+impl Foo for isize {
+    fn bar(&self) {}
+    //~^ ERROR method `bar` has a `&self` declaration in the impl, but not in the trait
+}
+
+fn main() {}
diff --git a/src/test/ui/staticness-mismatch.stderr b/src/test/ui/staticness-mismatch.stderr
new file mode 100644
index 0000000..b67ac5a
--- /dev/null
+++ b/src/test/ui/staticness-mismatch.stderr
@@ -0,0 +1,12 @@
+error[E0185]: method `bar` has a `&self` declaration in the impl, but not in the trait
+  --> $DIR/staticness-mismatch.rs:7:5
+   |
+LL |     fn bar();
+   |     --------- trait method declared without `&self`
+...
+LL |     fn bar(&self) {}
+   |     ^^^^^^^^^^^^^ `&self` used in impl
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0185`.
diff --git a/src/test/ui/std-uncopyable-atomics.nll.stderr b/src/test/ui/std-uncopyable-atomics.nll.stderr
new file mode 100644
index 0000000..8241f6f
--- /dev/null
+++ b/src/test/ui/std-uncopyable-atomics.nll.stderr
@@ -0,0 +1,39 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/std-uncopyable-atomics.rs:9:13
+   |
+LL |     let x = *&x;
+   |             ^^^
+   |             |
+   |             cannot move out of borrowed content
+   |             help: consider removing the `*`: `&x`
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/std-uncopyable-atomics.rs:11:13
+   |
+LL |     let x = *&x;
+   |             ^^^
+   |             |
+   |             cannot move out of borrowed content
+   |             help: consider removing the `*`: `&x`
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/std-uncopyable-atomics.rs:13:13
+   |
+LL |     let x = *&x;
+   |             ^^^
+   |             |
+   |             cannot move out of borrowed content
+   |             help: consider removing the `*`: `&x`
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/std-uncopyable-atomics.rs:15:13
+   |
+LL |     let x = *&x;
+   |             ^^^
+   |             |
+   |             cannot move out of borrowed content
+   |             help: consider removing the `*`: `&x`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/std-uncopyable-atomics.rs b/src/test/ui/std-uncopyable-atomics.rs
new file mode 100644
index 0000000..2c79a9c
--- /dev/null
+++ b/src/test/ui/std-uncopyable-atomics.rs
@@ -0,0 +1,16 @@
+// Issue #8380
+
+
+use std::sync::atomic::*;
+use std::ptr;
+
+fn main() {
+    let x = AtomicBool::new(false);
+    let x = *&x; //~ ERROR: cannot move out of borrowed content
+    let x = AtomicIsize::new(0);
+    let x = *&x; //~ ERROR: cannot move out of borrowed content
+    let x = AtomicUsize::new(0);
+    let x = *&x; //~ ERROR: cannot move out of borrowed content
+    let x: AtomicPtr<usize> = AtomicPtr::new(ptr::null_mut());
+    let x = *&x; //~ ERROR: cannot move out of borrowed content
+}
diff --git a/src/test/ui/std-uncopyable-atomics.stderr b/src/test/ui/std-uncopyable-atomics.stderr
new file mode 100644
index 0000000..7f01434
--- /dev/null
+++ b/src/test/ui/std-uncopyable-atomics.stderr
@@ -0,0 +1,39 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/std-uncopyable-atomics.rs:9:13
+   |
+LL |     let x = *&x;
+   |             ^^^
+   |             |
+   |             cannot move out of borrowed content
+   |             help: consider using a reference instead: `&*&x`
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/std-uncopyable-atomics.rs:11:13
+   |
+LL |     let x = *&x;
+   |             ^^^
+   |             |
+   |             cannot move out of borrowed content
+   |             help: consider using a reference instead: `&*&x`
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/std-uncopyable-atomics.rs:13:13
+   |
+LL |     let x = *&x;
+   |             ^^^
+   |             |
+   |             cannot move out of borrowed content
+   |             help: consider using a reference instead: `&*&x`
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/std-uncopyable-atomics.rs:15:13
+   |
+LL |     let x = *&x;
+   |             ^^^
+   |             |
+   |             cannot move out of borrowed content
+   |             help: consider using a reference instead: `&*&x`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/stmt_expr_attrs_no_feature.rs b/src/test/ui/stmt_expr_attrs_no_feature.rs
new file mode 100644
index 0000000..0a71d8d
--- /dev/null
+++ b/src/test/ui/stmt_expr_attrs_no_feature.rs
@@ -0,0 +1,140 @@
+#![feature(custom_attribute)]
+
+macro_rules! stmt_mac {
+    () => {
+        fn b() {}
+    }
+}
+
+fn main() {
+    #[attr]
+    fn a() {}
+
+    #[attr] //~ ERROR attributes on expressions are experimental
+    {
+
+    }
+
+    #[attr]
+    5;
+
+    #[attr]
+    stmt_mac!();
+}
+
+// Check that cfg works right
+
+#[cfg(unset)]
+fn c() {
+    #[attr]
+    5;
+}
+
+#[cfg(not(unset))]
+fn j() {
+    #[attr]
+    5;
+}
+
+#[cfg_attr(not(unset), cfg(unset))]
+fn d() {
+    #[attr]
+    8;
+}
+
+#[cfg_attr(not(unset), cfg(not(unset)))]
+fn i() {
+    #[attr]
+    8;
+}
+
+// check that macro expansion and cfg works right
+
+macro_rules! item_mac {
+    ($e:ident) => {
+        fn $e() {
+            #[attr]
+            42;
+
+            #[cfg(unset)]
+            fn f() {
+                #[attr]
+                5;
+            }
+
+            #[cfg(not(unset))]
+            fn k() {
+                #[attr]
+                5;
+            }
+
+            #[cfg_attr(not(unset), cfg(unset))]
+            fn g() {
+                #[attr]
+                8;
+            }
+
+            #[cfg_attr(not(unset), cfg(not(unset)))]
+            fn h() {
+                #[attr]
+                8;
+            }
+
+        }
+    }
+}
+
+item_mac!(e);
+
+// check that the gate visitor works right:
+
+extern {
+    #[cfg(unset)]
+    fn x(a: [u8; #[attr] 5]);
+    fn y(a: [u8; #[attr] 5]); //~ ERROR 15701
+}
+
+struct Foo;
+impl Foo {
+    #[cfg(unset)]
+    const X: u8 = #[attr] 5;
+    const Y: u8 = #[attr] 5; //~ ERROR 15701
+}
+
+trait Bar {
+    #[cfg(unset)]
+    const X: [u8; #[attr] 5];
+    const Y: [u8; #[attr] 5]; //~ ERROR 15701
+}
+
+struct Joyce {
+    #[cfg(unset)]
+    field: [u8; #[attr] 5],
+    field2: [u8; #[attr] 5] //~ ERROR 15701
+}
+
+struct Walky(
+    #[cfg(unset)] [u8; #[attr] 5],
+    [u8; #[attr] 5] //~ ERROR 15701
+);
+
+enum Mike {
+    Happy(
+        #[cfg(unset)] [u8; #[attr] 5],
+        [u8; #[attr] 5] //~ ERROR 15701
+    ),
+    Angry {
+        #[cfg(unset)]
+        field: [u8; #[attr] 5],
+        field2: [u8; #[attr] 5] //~ ERROR 15701
+    }
+}
+
+fn pat() {
+    match 5 {
+        #[cfg(unset)]
+        5 => #[attr] (),
+        6 => #[attr] (), //~ ERROR 15701
+        _ => (),
+    }
+}
diff --git a/src/test/ui/stmt_expr_attrs_no_feature.stderr b/src/test/ui/stmt_expr_attrs_no_feature.stderr
new file mode 100644
index 0000000..c644126
--- /dev/null
+++ b/src/test/ui/stmt_expr_attrs_no_feature.stderr
@@ -0,0 +1,75 @@
+error[E0658]: attributes on expressions are experimental. (see issue #15701)
+  --> $DIR/stmt_expr_attrs_no_feature.rs:13:5
+   |
+LL |     #[attr]
+   |     ^^^^^^^
+   |
+   = help: add #![feature(stmt_expr_attributes)] to the crate attributes to enable
+
+error[E0658]: attributes on expressions are experimental. (see issue #15701)
+  --> $DIR/stmt_expr_attrs_no_feature.rs:94:18
+   |
+LL |     fn y(a: [u8; #[attr] 5]);
+   |                  ^^^^^^^
+   |
+   = help: add #![feature(stmt_expr_attributes)] to the crate attributes to enable
+
+error[E0658]: attributes on expressions are experimental. (see issue #15701)
+  --> $DIR/stmt_expr_attrs_no_feature.rs:101:19
+   |
+LL |     const Y: u8 = #[attr] 5;
+   |                   ^^^^^^^
+   |
+   = help: add #![feature(stmt_expr_attributes)] to the crate attributes to enable
+
+error[E0658]: attributes on expressions are experimental. (see issue #15701)
+  --> $DIR/stmt_expr_attrs_no_feature.rs:107:19
+   |
+LL |     const Y: [u8; #[attr] 5];
+   |                   ^^^^^^^
+   |
+   = help: add #![feature(stmt_expr_attributes)] to the crate attributes to enable
+
+error[E0658]: attributes on expressions are experimental. (see issue #15701)
+  --> $DIR/stmt_expr_attrs_no_feature.rs:113:18
+   |
+LL |     field2: [u8; #[attr] 5]
+   |                  ^^^^^^^
+   |
+   = help: add #![feature(stmt_expr_attributes)] to the crate attributes to enable
+
+error[E0658]: attributes on expressions are experimental. (see issue #15701)
+  --> $DIR/stmt_expr_attrs_no_feature.rs:118:10
+   |
+LL |     [u8; #[attr] 5]
+   |          ^^^^^^^
+   |
+   = help: add #![feature(stmt_expr_attributes)] to the crate attributes to enable
+
+error[E0658]: attributes on expressions are experimental. (see issue #15701)
+  --> $DIR/stmt_expr_attrs_no_feature.rs:124:14
+   |
+LL |         [u8; #[attr] 5]
+   |              ^^^^^^^
+   |
+   = help: add #![feature(stmt_expr_attributes)] to the crate attributes to enable
+
+error[E0658]: attributes on expressions are experimental. (see issue #15701)
+  --> $DIR/stmt_expr_attrs_no_feature.rs:129:22
+   |
+LL |         field2: [u8; #[attr] 5]
+   |                      ^^^^^^^
+   |
+   = help: add #![feature(stmt_expr_attributes)] to the crate attributes to enable
+
+error[E0658]: attributes on expressions are experimental. (see issue #15701)
+  --> $DIR/stmt_expr_attrs_no_feature.rs:137:14
+   |
+LL |         6 => #[attr] (),
+   |              ^^^^^^^
+   |
+   = help: add #![feature(stmt_expr_attributes)] to the crate attributes to enable
+
+error: aborting due to 9 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/str/str-array-assignment.rs b/src/test/ui/str/str-array-assignment.rs
new file mode 100644
index 0000000..4a78ed5
--- /dev/null
+++ b/src/test/ui/str/str-array-assignment.rs
@@ -0,0 +1,11 @@
+fn main() {
+  let s = "abc";
+  let t = if true { s[..2] } else { s };
+  //~^ ERROR if and else have incompatible types
+  let u: &str = if true { s[..2] } else { s };
+  //~^ ERROR mismatched types
+  let v = s[..2];
+  //~^ ERROR the size for values of type
+  let w: &str = s[..2];
+  //~^ ERROR mismatched types
+}
diff --git a/src/test/ui/str/str-array-assignment.stderr b/src/test/ui/str/str-array-assignment.stderr
new file mode 100644
index 0000000..87809d2
--- /dev/null
+++ b/src/test/ui/str/str-array-assignment.stderr
@@ -0,0 +1,52 @@
+error[E0308]: if and else have incompatible types
+  --> $DIR/str-array-assignment.rs:3:37
+   |
+LL |   let t = if true { s[..2] } else { s };
+   |                     ------          ^ expected str, found &str
+   |                     |
+   |                     expected because of this
+   |
+   = note: expected type `str`
+              found type `&str`
+
+error[E0308]: mismatched types
+  --> $DIR/str-array-assignment.rs:5:27
+   |
+LL |   let u: &str = if true { s[..2] } else { s };
+   |                           ^^^^^^
+   |                           |
+   |                           expected &str, found str
+   |                           help: consider borrowing here: `&s[..2]`
+   |
+   = note: expected type `&str`
+              found type `str`
+
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+  --> $DIR/str-array-assignment.rs:7:7
+   |
+LL |   let v = s[..2];
+   |       ^   ------ help: consider borrowing here: `&s[..2]`
+   |       |
+   |       doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `str`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: all local variables must have a statically known size
+   = help: unsized locals are gated as an unstable feature
+
+error[E0308]: mismatched types
+  --> $DIR/str-array-assignment.rs:9:17
+   |
+LL |   let w: &str = s[..2];
+   |                 ^^^^^^
+   |                 |
+   |                 expected &str, found str
+   |                 help: consider borrowing here: `&s[..2]`
+   |
+   = note: expected type `&str`
+              found type `str`
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0277, E0308.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/str/str-as-char.fixed b/src/test/ui/str/str-as-char.fixed
new file mode 100644
index 0000000..accead5
--- /dev/null
+++ b/src/test/ui/str/str-as-char.fixed
@@ -0,0 +1,6 @@
+// run-rustfix
+
+fn main() {
+    println!("{}", "●●"); //~ ERROR character literal may only contain one codepoint
+    //~^ ERROR format argument must be a string literal
+}
diff --git a/src/test/ui/str/str-as-char.rs b/src/test/ui/str/str-as-char.rs
new file mode 100644
index 0000000..fb179ec
--- /dev/null
+++ b/src/test/ui/str/str-as-char.rs
@@ -0,0 +1,6 @@
+// run-rustfix
+
+fn main() {
+    println!('●●'); //~ ERROR character literal may only contain one codepoint
+    //~^ ERROR format argument must be a string literal
+}
diff --git a/src/test/ui/str/str-as-char.stderr b/src/test/ui/str/str-as-char.stderr
new file mode 100644
index 0000000..162f088
--- /dev/null
+++ b/src/test/ui/str/str-as-char.stderr
@@ -0,0 +1,22 @@
+error: character literal may only contain one codepoint
+  --> $DIR/str-as-char.rs:4:14
+   |
+LL |     println!('●●');
+   |              ^^^^
+help: if you meant to write a `str` literal, use double quotes
+   |
+LL |     println!("●●");
+   |              ^^^^
+
+error: format argument must be a string literal
+  --> $DIR/str-as-char.rs:4:14
+   |
+LL |     println!('●●');
+   |              ^^^^
+help: you might be missing a string literal to format with
+   |
+LL |     println!("{}", '●●');
+   |              ^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/str/str-concat-on-double-ref.rs b/src/test/ui/str/str-concat-on-double-ref.rs
new file mode 100644
index 0000000..a671b6e
--- /dev/null
+++ b/src/test/ui/str/str-concat-on-double-ref.rs
@@ -0,0 +1,7 @@
+fn main() {
+    let a: &String = &"1".to_owned();
+    let b: &str = &"2";
+    let c = a + b;
+    //~^ ERROR binary operation `+` cannot be applied to type `&std::string::String`
+    println!("{:?}", c);
+}
diff --git a/src/test/ui/str/str-concat-on-double-ref.stderr b/src/test/ui/str/str-concat-on-double-ref.stderr
new file mode 100644
index 0000000..61ebcfd
--- /dev/null
+++ b/src/test/ui/str/str-concat-on-double-ref.stderr
@@ -0,0 +1,13 @@
+error[E0369]: binary operation `+` cannot be applied to type `&std::string::String`
+  --> $DIR/str-concat-on-double-ref.rs:4:15
+   |
+LL |     let c = a + b;
+   |             - ^ - &str
+   |             |
+   |             &std::string::String
+   |
+   = note: an implementation of `std::ops::Add` might be missing for `&std::string::String`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0369`.
diff --git a/src/test/ui/str/str-idx.rs b/src/test/ui/str/str-idx.rs
new file mode 100644
index 0000000..1b32ed5
--- /dev/null
+++ b/src/test/ui/str/str-idx.rs
@@ -0,0 +1,7 @@
+pub fn main() {
+    let s: &str = "hello";
+    let _: u8 = s[4]; //~ ERROR the type `str` cannot be indexed by `{integer}`
+    let _ = s.get(4); //~ ERROR the type `str` cannot be indexed by `{integer}`
+    let _ = s.get_unchecked(4); //~ ERROR the type `str` cannot be indexed by `{integer}`
+    let _: u8 = s['c']; //~ ERROR the type `str` cannot be indexed by `char`
+}
diff --git a/src/test/ui/str/str-idx.stderr b/src/test/ui/str/str-idx.stderr
new file mode 100644
index 0000000..e388534
--- /dev/null
+++ b/src/test/ui/str/str-idx.stderr
@@ -0,0 +1,43 @@
+error[E0277]: the type `str` cannot be indexed by `{integer}`
+  --> $DIR/str-idx.rs:3:17
+   |
+LL |     let _: u8 = s[4];
+   |                 ^^^^ string indices are ranges of `usize`
+   |
+   = help: the trait `std::slice::SliceIndex<str>` is not implemented for `{integer}`
+   = note: you can use `.chars().nth()` or `.bytes().nth()`
+           see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
+   = note: required because of the requirements on the impl of `std::ops::Index<{integer}>` for `str`
+
+error[E0277]: the type `str` cannot be indexed by `{integer}`
+  --> $DIR/str-idx.rs:4:15
+   |
+LL |     let _ = s.get(4);
+   |               ^^^ string indices are ranges of `usize`
+   |
+   = help: the trait `std::slice::SliceIndex<str>` is not implemented for `{integer}`
+   = note: you can use `.chars().nth()` or `.bytes().nth()`
+           see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
+
+error[E0277]: the type `str` cannot be indexed by `{integer}`
+  --> $DIR/str-idx.rs:5:15
+   |
+LL |     let _ = s.get_unchecked(4);
+   |               ^^^^^^^^^^^^^ string indices are ranges of `usize`
+   |
+   = help: the trait `std::slice::SliceIndex<str>` is not implemented for `{integer}`
+   = note: you can use `.chars().nth()` or `.bytes().nth()`
+           see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
+
+error[E0277]: the type `str` cannot be indexed by `char`
+  --> $DIR/str-idx.rs:6:17
+   |
+LL |     let _: u8 = s['c'];
+   |                 ^^^^^^ string indices are ranges of `usize`
+   |
+   = help: the trait `std::slice::SliceIndex<str>` is not implemented for `char`
+   = note: required because of the requirements on the impl of `std::ops::Index<char>` for `str`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/str/str-lit-type-mismatch.rs b/src/test/ui/str/str-lit-type-mismatch.rs
new file mode 100644
index 0000000..12637c7
--- /dev/null
+++ b/src/test/ui/str/str-lit-type-mismatch.rs
@@ -0,0 +1,5 @@
+fn main() {
+    let x: &[u8] = "foo"; //~ ERROR mismatched types
+    let y: &[u8; 4] = "baaa"; //~ ERROR mismatched types
+    let z: &str = b"foo"; //~ ERROR mismatched types
+}
diff --git a/src/test/ui/str/str-lit-type-mismatch.stderr b/src/test/ui/str/str-lit-type-mismatch.stderr
new file mode 100644
index 0000000..ef40faa
--- /dev/null
+++ b/src/test/ui/str/str-lit-type-mismatch.stderr
@@ -0,0 +1,39 @@
+error[E0308]: mismatched types
+  --> $DIR/str-lit-type-mismatch.rs:2:20
+   |
+LL |     let x: &[u8] = "foo";
+   |                    ^^^^^
+   |                    |
+   |                    expected slice, found str
+   |                    help: consider adding a leading `b`: `b"foo"`
+   |
+   = note: expected type `&[u8]`
+              found type `&'static str`
+
+error[E0308]: mismatched types
+  --> $DIR/str-lit-type-mismatch.rs:3:23
+   |
+LL |     let y: &[u8; 4] = "baaa";
+   |                       ^^^^^^
+   |                       |
+   |                       expected array of 4 elements, found str
+   |                       help: consider adding a leading `b`: `b"baaa"`
+   |
+   = note: expected type `&[u8; 4]`
+              found type `&'static str`
+
+error[E0308]: mismatched types
+  --> $DIR/str-lit-type-mismatch.rs:4:19
+   |
+LL |     let z: &str = b"foo";
+   |                   ^^^^^^
+   |                   |
+   |                   expected str, found array of 3 elements
+   |                   help: consider removing the leading `b`: `"foo"`
+   |
+   = note: expected type `&str`
+              found type `&'static [u8; 3]`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/str/str-mut-idx.rs b/src/test/ui/str/str-mut-idx.rs
new file mode 100644
index 0000000..575a9ea
--- /dev/null
+++ b/src/test/ui/str/str-mut-idx.rs
@@ -0,0 +1,17 @@
+fn bot<T>() -> T { loop {} }
+
+fn mutate(s: &mut str) {
+    s[1..2] = bot();
+    //~^ ERROR the size for values of type
+    //~| ERROR the size for values of type
+    s[1usize] = bot();
+    //~^ ERROR the type `str` cannot be indexed by `usize`
+    s.get_mut(1);
+    //~^ ERROR the type `str` cannot be indexed by `{integer}`
+    s.get_unchecked_mut(1);
+    //~^ ERROR the type `str` cannot be indexed by `{integer}`
+    s['c'];
+    //~^ ERROR the type `str` cannot be indexed by `char`
+}
+
+pub fn main() {}
diff --git a/src/test/ui/str/str-mut-idx.stderr b/src/test/ui/str/str-mut-idx.stderr
new file mode 100644
index 0000000..beb2272
--- /dev/null
+++ b/src/test/ui/str/str-mut-idx.stderr
@@ -0,0 +1,65 @@
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+  --> $DIR/str-mut-idx.rs:4:15
+   |
+LL |     s[1..2] = bot();
+   |               ^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `str`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+note: required by `bot`
+  --> $DIR/str-mut-idx.rs:1:1
+   |
+LL | fn bot<T>() -> T { loop {} }
+   | ^^^^^^^^^^^^^^^^
+
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+  --> $DIR/str-mut-idx.rs:4:5
+   |
+LL |     s[1..2] = bot();
+   |     ^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `str`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: the left-hand-side of an assignment must have a statically known size
+
+error[E0277]: the type `str` cannot be indexed by `usize`
+  --> $DIR/str-mut-idx.rs:7:5
+   |
+LL |     s[1usize] = bot();
+   |     ^^^^^^^^^ string indices are ranges of `usize`
+   |
+   = help: the trait `std::slice::SliceIndex<str>` is not implemented for `usize`
+   = note: required because of the requirements on the impl of `std::ops::Index<usize>` for `str`
+
+error[E0277]: the type `str` cannot be indexed by `{integer}`
+  --> $DIR/str-mut-idx.rs:9:7
+   |
+LL |     s.get_mut(1);
+   |       ^^^^^^^ string indices are ranges of `usize`
+   |
+   = help: the trait `std::slice::SliceIndex<str>` is not implemented for `{integer}`
+   = note: you can use `.chars().nth()` or `.bytes().nth()`
+           see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
+
+error[E0277]: the type `str` cannot be indexed by `{integer}`
+  --> $DIR/str-mut-idx.rs:11:7
+   |
+LL |     s.get_unchecked_mut(1);
+   |       ^^^^^^^^^^^^^^^^^ string indices are ranges of `usize`
+   |
+   = help: the trait `std::slice::SliceIndex<str>` is not implemented for `{integer}`
+   = note: you can use `.chars().nth()` or `.bytes().nth()`
+           see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
+
+error[E0277]: the type `str` cannot be indexed by `char`
+  --> $DIR/str-mut-idx.rs:13:5
+   |
+LL |     s['c'];
+   |     ^^^^^^ string indices are ranges of `usize`
+   |
+   = help: the trait `std::slice::SliceIndex<str>` is not implemented for `char`
+   = note: required because of the requirements on the impl of `std::ops::Index<char>` for `str`
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/structs/auxiliary/struct_field_privacy.rs b/src/test/ui/structs/auxiliary/struct_field_privacy.rs
new file mode 100644
index 0000000..9765af1
--- /dev/null
+++ b/src/test/ui/structs/auxiliary/struct_field_privacy.rs
@@ -0,0 +1,9 @@
+pub struct A {
+    a: isize,
+    pub b: isize,
+}
+
+pub struct B {
+    pub a: isize,
+    b: isize,
+}
diff --git a/src/test/ui/structs/auxiliary/struct_variant_privacy.rs b/src/test/ui/structs/auxiliary/struct_variant_privacy.rs
new file mode 100644
index 0000000..425ec0e
--- /dev/null
+++ b/src/test/ui/structs/auxiliary/struct_variant_privacy.rs
@@ -0,0 +1,3 @@
+enum Bar {
+    Baz { a: isize }
+}
diff --git a/src/test/ui/structs/struct-base-wrong-type-2.rs b/src/test/ui/structs/struct-base-wrong-type-2.rs
new file mode 100644
index 0000000..562f75b
--- /dev/null
+++ b/src/test/ui/structs/struct-base-wrong-type-2.rs
@@ -0,0 +1,19 @@
+// Check that `base` in `Fru { field: expr, ..base }` must have right type.
+//
+// See also struct-base-wrong-type.rs, which tests same condition
+// within a const expression.
+
+struct Foo { a: isize, b: isize }
+struct Bar { x: isize }
+
+fn main() {
+    let b = Bar { x: 5 };
+    let f = Foo { a: 2, ..b }; //~  ERROR mismatched types
+                               //~| expected type `Foo`
+                               //~| found type `Bar`
+                               //~| expected struct `Foo`, found struct `Bar`
+    let f__isize = Foo { a: 2, ..4 }; //~  ERROR mismatched types
+                                 //~| expected type `Foo`
+                                 //~| found type `{integer}`
+                                 //~| expected struct `Foo`, found integer
+}
diff --git a/src/test/ui/structs/struct-base-wrong-type-2.stderr b/src/test/ui/structs/struct-base-wrong-type-2.stderr
new file mode 100644
index 0000000..d02ed20
--- /dev/null
+++ b/src/test/ui/structs/struct-base-wrong-type-2.stderr
@@ -0,0 +1,21 @@
+error[E0308]: mismatched types
+  --> $DIR/struct-base-wrong-type-2.rs:11:27
+   |
+LL |     let f = Foo { a: 2, ..b };
+   |                           ^ expected struct `Foo`, found struct `Bar`
+   |
+   = note: expected type `Foo`
+              found type `Bar`
+
+error[E0308]: mismatched types
+  --> $DIR/struct-base-wrong-type-2.rs:15:34
+   |
+LL |     let f__isize = Foo { a: 2, ..4 };
+   |                                  ^ expected struct `Foo`, found integer
+   |
+   = note: expected type `Foo`
+              found type `{integer}`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/structs/struct-base-wrong-type.rs b/src/test/ui/structs/struct-base-wrong-type.rs
new file mode 100644
index 0000000..6252673
--- /dev/null
+++ b/src/test/ui/structs/struct-base-wrong-type.rs
@@ -0,0 +1,27 @@
+// Check that `base` in `Fru { field: expr, ..base }` must have right type.
+//
+// See also struct-base-wrong-type-2.rs, which tests same condition
+// within a function body.
+
+struct Foo { a: isize, b: isize }
+struct Bar { x: isize }
+
+static bar: Bar = Bar { x: 5 };
+static foo: Foo = Foo { a: 2, ..bar }; //~  ERROR mismatched types
+                                       //~| expected type `Foo`
+                                       //~| found type `Bar`
+                                       //~| expected struct `Foo`, found struct `Bar`
+static foo_i: Foo = Foo { a: 2, ..4 }; //~  ERROR mismatched types
+                                       //~| expected type `Foo`
+                                       //~| found type `{integer}`
+                                       //~| expected struct `Foo`, found integer
+
+fn main() {
+    let b = Bar { x: 5 };
+    // errors below are no longer caught since error above causes
+    // compilation to abort before we bother checking function bodies.
+    // See also struct-base-wrong-type-2.rs, which checks that we
+    // would catch these errors eventually.
+    let f = Foo { a: 2, ..b };
+    let f__isize = Foo { a: 2, ..4 };
+}
diff --git a/src/test/ui/structs/struct-base-wrong-type.stderr b/src/test/ui/structs/struct-base-wrong-type.stderr
new file mode 100644
index 0000000..2491296
--- /dev/null
+++ b/src/test/ui/structs/struct-base-wrong-type.stderr
@@ -0,0 +1,21 @@
+error[E0308]: mismatched types
+  --> $DIR/struct-base-wrong-type.rs:10:33
+   |
+LL | static foo: Foo = Foo { a: 2, ..bar };
+   |                                 ^^^ expected struct `Foo`, found struct `Bar`
+   |
+   = note: expected type `Foo`
+              found type `Bar`
+
+error[E0308]: mismatched types
+  --> $DIR/struct-base-wrong-type.rs:14:35
+   |
+LL | static foo_i: Foo = Foo { a: 2, ..4 };
+   |                                   ^ expected struct `Foo`, found integer
+   |
+   = note: expected type `Foo`
+              found type `{integer}`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/structs/struct-duplicate-comma.rs b/src/test/ui/structs/struct-duplicate-comma.rs
new file mode 100644
index 0000000..ff0d58a
--- /dev/null
+++ b/src/test/ui/structs/struct-duplicate-comma.rs
@@ -0,0 +1,14 @@
+// Issue #50974
+
+struct Foo {
+    a: u8,
+    b: u8
+}
+
+fn main() {
+    let bar = Foo {
+        a: 0,,
+          //~^ ERROR expected identifier
+        b: 42
+    };
+}
diff --git a/src/test/ui/structs/struct-duplicate-comma.stderr b/src/test/ui/structs/struct-duplicate-comma.stderr
new file mode 100644
index 0000000..2297fea
--- /dev/null
+++ b/src/test/ui/structs/struct-duplicate-comma.stderr
@@ -0,0 +1,13 @@
+error: expected identifier, found `,`
+  --> $DIR/struct-duplicate-comma.rs:10:14
+   |
+LL |     let bar = Foo {
+   |               --- while parsing this struct
+LL |         a: 0,,
+   |              ^
+   |              |
+   |              expected identifier
+   |              help: remove this comma
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/structs/struct-field-cfg.rs b/src/test/ui/structs/struct-field-cfg.rs
new file mode 100644
index 0000000..42cab8a
--- /dev/null
+++ b/src/test/ui/structs/struct-field-cfg.rs
@@ -0,0 +1,18 @@
+struct Foo {
+    present: (),
+}
+
+fn main() {
+    let foo = Foo { #[cfg(all())] present: () };
+    let _ = Foo { #[cfg(any())] present: () };
+    //~^ ERROR missing field `present` in initializer of `Foo`
+    let _ = Foo { present: (), #[cfg(any())] absent: () };
+    let _ = Foo { present: (), #[cfg(all())] absent: () };
+    //~^ ERROR struct `Foo` has no field named `absent`
+    let Foo { #[cfg(all())] present: () } = foo;
+    let Foo { #[cfg(any())] present: () } = foo;
+    //~^ ERROR pattern does not mention field `present`
+    let Foo { present: (), #[cfg(any())] absent: () } = foo;
+    let Foo { present: (), #[cfg(all())] absent: () } = foo;
+    //~^ ERROR struct `Foo` does not have a field named `absent`
+}
diff --git a/src/test/ui/structs/struct-field-cfg.stderr b/src/test/ui/structs/struct-field-cfg.stderr
new file mode 100644
index 0000000..565866a
--- /dev/null
+++ b/src/test/ui/structs/struct-field-cfg.stderr
@@ -0,0 +1,30 @@
+error[E0063]: missing field `present` in initializer of `Foo`
+  --> $DIR/struct-field-cfg.rs:7:13
+   |
+LL |     let _ = Foo { #[cfg(any())] present: () };
+   |             ^^^ missing `present`
+
+error[E0560]: struct `Foo` has no field named `absent`
+  --> $DIR/struct-field-cfg.rs:10:46
+   |
+LL |     let _ = Foo { present: (), #[cfg(all())] absent: () };
+   |                                              ^^^^^^ `Foo` does not have this field
+   |
+   = note: available fields are: `present`
+
+error[E0027]: pattern does not mention field `present`
+  --> $DIR/struct-field-cfg.rs:13:9
+   |
+LL |     let Foo { #[cfg(any())] present: () } = foo;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing field `present`
+
+error[E0026]: struct `Foo` does not have a field named `absent`
+  --> $DIR/struct-field-cfg.rs:16:42
+   |
+LL |     let Foo { present: (), #[cfg(all())] absent: () } = foo;
+   |                                          ^^^^^^ struct `Foo` does not have this field
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0026, E0027, E0063, E0560.
+For more information about an error, try `rustc --explain E0026`.
diff --git a/src/test/ui/structs/struct-field-init-syntax.rs b/src/test/ui/structs/struct-field-init-syntax.rs
new file mode 100644
index 0000000..161f7e9
--- /dev/null
+++ b/src/test/ui/structs/struct-field-init-syntax.rs
@@ -0,0 +1,20 @@
+// issue #41834
+
+#[derive(Default)]
+struct Foo {
+    one: u8,
+}
+
+fn main() {
+    let foo = Foo {
+        one: 111,
+        ..Foo::default(),
+        //~^ ERROR cannot use a comma after the base struct
+    };
+
+    let foo = Foo {
+        ..Foo::default(),
+        //~^ ERROR cannot use a comma after the base struct
+        one: 111,
+    };
+}
diff --git a/src/test/ui/structs/struct-field-init-syntax.stderr b/src/test/ui/structs/struct-field-init-syntax.stderr
new file mode 100644
index 0000000..0b72c5c
--- /dev/null
+++ b/src/test/ui/structs/struct-field-init-syntax.stderr
@@ -0,0 +1,18 @@
+error: cannot use a comma after the base struct
+  --> $DIR/struct-field-init-syntax.rs:11:9
+   |
+LL |         ..Foo::default(),
+   |         ^^^^^^^^^^^^^^^^- help: remove this comma
+   |
+   = note: the base struct must always be the last field
+
+error: cannot use a comma after the base struct
+  --> $DIR/struct-field-init-syntax.rs:16:9
+   |
+LL |         ..Foo::default(),
+   |         ^^^^^^^^^^^^^^^^- help: remove this comma
+   |
+   = note: the base struct must always be the last field
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/structs/struct-field-privacy.rs b/src/test/ui/structs/struct-field-privacy.rs
new file mode 100644
index 0000000..5c35c04
--- /dev/null
+++ b/src/test/ui/structs/struct-field-privacy.rs
@@ -0,0 +1,38 @@
+// aux-build:struct_field_privacy.rs
+
+extern crate struct_field_privacy as xc;
+
+struct A {
+    a: isize,
+}
+
+mod inner {
+    pub struct A {
+        a: isize,
+        pub b: isize,
+    }
+    pub struct B {
+        pub a: isize,
+        b: isize,
+    }
+    pub struct Z(pub isize, isize);
+}
+
+fn test(a: A, b: inner::A, c: inner::B, d: xc::A, e: xc::B, z: inner::Z) {
+    a.a;
+    b.a; //~ ERROR: field `a` of struct `inner::A` is private
+    b.b;
+    c.a;
+    c.b; //~ ERROR: field `b` of struct `inner::B` is private
+
+    d.a; //~ ERROR: field `a` of struct `xc::A` is private
+    d.b;
+
+    e.a;
+    e.b; //~ ERROR: field `b` of struct `xc::B` is private
+
+    z.0;
+    z.1; //~ ERROR: field `1` of struct `inner::Z` is private
+}
+
+fn main() {}
diff --git a/src/test/ui/structs/struct-field-privacy.stderr b/src/test/ui/structs/struct-field-privacy.stderr
new file mode 100644
index 0000000..91d000b
--- /dev/null
+++ b/src/test/ui/structs/struct-field-privacy.stderr
@@ -0,0 +1,33 @@
+error[E0616]: field `a` of struct `inner::A` is private
+  --> $DIR/struct-field-privacy.rs:23:5
+   |
+LL |     b.a;
+   |     ^^^
+
+error[E0616]: field `b` of struct `inner::B` is private
+  --> $DIR/struct-field-privacy.rs:26:5
+   |
+LL |     c.b;
+   |     ^^^
+
+error[E0616]: field `a` of struct `xc::A` is private
+  --> $DIR/struct-field-privacy.rs:28:5
+   |
+LL |     d.a;
+   |     ^^^
+
+error[E0616]: field `b` of struct `xc::B` is private
+  --> $DIR/struct-field-privacy.rs:32:5
+   |
+LL |     e.b;
+   |     ^^^
+
+error[E0616]: field `1` of struct `inner::Z` is private
+  --> $DIR/struct-field-privacy.rs:35:5
+   |
+LL |     z.1;
+   |     ^^^
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0616`.
diff --git a/src/test/ui/structs/struct-fields-decl-dupe.rs b/src/test/ui/structs/struct-fields-decl-dupe.rs
new file mode 100644
index 0000000..6ddf3d9
--- /dev/null
+++ b/src/test/ui/structs/struct-fields-decl-dupe.rs
@@ -0,0 +1,8 @@
+struct BuildData {
+    foo: isize,
+    foo: isize,
+    //~^ ERROR field `foo` is already declared [E0124]
+}
+
+fn main() {
+}
diff --git a/src/test/ui/structs/struct-fields-decl-dupe.stderr b/src/test/ui/structs/struct-fields-decl-dupe.stderr
new file mode 100644
index 0000000..d7ce9bb
--- /dev/null
+++ b/src/test/ui/structs/struct-fields-decl-dupe.stderr
@@ -0,0 +1,11 @@
+error[E0124]: field `foo` is already declared
+  --> $DIR/struct-fields-decl-dupe.rs:3:5
+   |
+LL |     foo: isize,
+   |     ---------- `foo` first declared here
+LL |     foo: isize,
+   |     ^^^^^^^^^^ field already declared
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0124`.
diff --git a/src/test/ui/structs/struct-fields-dupe.rs b/src/test/ui/structs/struct-fields-dupe.rs
new file mode 100644
index 0000000..2fa25a3
--- /dev/null
+++ b/src/test/ui/structs/struct-fields-dupe.rs
@@ -0,0 +1,10 @@
+struct BuildData {
+    foo: isize,
+}
+
+fn main() {
+    let foo = BuildData {
+        foo: 0,
+        foo: 0 //~ ERROR field `foo` specified more than once
+    };
+}
diff --git a/src/test/ui/structs/struct-fields-dupe.stderr b/src/test/ui/structs/struct-fields-dupe.stderr
new file mode 100644
index 0000000..aaf2533
--- /dev/null
+++ b/src/test/ui/structs/struct-fields-dupe.stderr
@@ -0,0 +1,11 @@
+error[E0062]: field `foo` specified more than once
+  --> $DIR/struct-fields-dupe.rs:8:9
+   |
+LL |         foo: 0,
+   |         ------ first use of `foo`
+LL |         foo: 0
+   |         ^^^ used more than once
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0062`.
diff --git a/src/test/ui/structs/struct-fields-hints-no-dupe.rs b/src/test/ui/structs/struct-fields-hints-no-dupe.rs
new file mode 100644
index 0000000..987cf72
--- /dev/null
+++ b/src/test/ui/structs/struct-fields-hints-no-dupe.rs
@@ -0,0 +1,14 @@
+struct A {
+    foo : i32,
+    car : i32,
+    barr : i32
+}
+
+fn main() {
+    let a = A {
+        foo : 5,
+        bar : 42,
+        //~^ ERROR struct `A` has no field named `bar`
+        car : 9,
+    };
+}
diff --git a/src/test/ui/structs/struct-fields-hints-no-dupe.stderr b/src/test/ui/structs/struct-fields-hints-no-dupe.stderr
new file mode 100644
index 0000000..1a88f26
--- /dev/null
+++ b/src/test/ui/structs/struct-fields-hints-no-dupe.stderr
@@ -0,0 +1,9 @@
+error[E0560]: struct `A` has no field named `bar`
+  --> $DIR/struct-fields-hints-no-dupe.rs:10:9
+   |
+LL |         bar : 42,
+   |         ^^^ help: a field with a similar name exists: `barr`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0560`.
diff --git a/src/test/ui/structs/struct-fields-hints.rs b/src/test/ui/structs/struct-fields-hints.rs
new file mode 100644
index 0000000..08df093
--- /dev/null
+++ b/src/test/ui/structs/struct-fields-hints.rs
@@ -0,0 +1,13 @@
+struct A {
+    foo : i32,
+    car : i32,
+    barr : i32
+}
+
+fn main() {
+    let a = A {
+        foo : 5,
+        bar : 42,
+        //~^ ERROR struct `A` has no field named `bar`
+    };
+}
diff --git a/src/test/ui/structs/struct-fields-hints.stderr b/src/test/ui/structs/struct-fields-hints.stderr
new file mode 100644
index 0000000..3b8a2b5
--- /dev/null
+++ b/src/test/ui/structs/struct-fields-hints.stderr
@@ -0,0 +1,9 @@
+error[E0560]: struct `A` has no field named `bar`
+  --> $DIR/struct-fields-hints.rs:10:9
+   |
+LL |         bar : 42,
+   |         ^^^ help: a field with a similar name exists: `car`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0560`.
diff --git a/src/test/ui/structs/struct-fields-missing.rs b/src/test/ui/structs/struct-fields-missing.rs
new file mode 100644
index 0000000..0c7919d
--- /dev/null
+++ b/src/test/ui/structs/struct-fields-missing.rs
@@ -0,0 +1,10 @@
+struct BuildData {
+    foo: isize,
+    bar: Box<isize>,
+}
+
+fn main() {
+    let foo = BuildData { //~ ERROR missing field `bar` in initializer of `BuildData`
+        foo: 0
+    };
+}
diff --git a/src/test/ui/structs/struct-fields-missing.stderr b/src/test/ui/structs/struct-fields-missing.stderr
new file mode 100644
index 0000000..b3e42a9
--- /dev/null
+++ b/src/test/ui/structs/struct-fields-missing.stderr
@@ -0,0 +1,9 @@
+error[E0063]: missing field `bar` in initializer of `BuildData`
+  --> $DIR/struct-fields-missing.rs:7:15
+   |
+LL |     let foo = BuildData {
+   |               ^^^^^^^^^ missing `bar`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0063`.
diff --git a/src/test/ui/structs/struct-fields-shorthand-unresolved.rs b/src/test/ui/structs/struct-fields-shorthand-unresolved.rs
new file mode 100644
index 0000000..caad149
--- /dev/null
+++ b/src/test/ui/structs/struct-fields-shorthand-unresolved.rs
@@ -0,0 +1,12 @@
+struct Foo {
+    x: i32,
+    y: i32
+}
+
+fn main() {
+    let x = 0;
+    let foo = Foo {
+        x,
+        y //~ ERROR cannot find value `y` in this scope
+    };
+}
diff --git a/src/test/ui/structs/struct-fields-shorthand-unresolved.stderr b/src/test/ui/structs/struct-fields-shorthand-unresolved.stderr
new file mode 100644
index 0000000..09fc4f7
--- /dev/null
+++ b/src/test/ui/structs/struct-fields-shorthand-unresolved.stderr
@@ -0,0 +1,9 @@
+error[E0425]: cannot find value `y` in this scope
+  --> $DIR/struct-fields-shorthand-unresolved.rs:10:9
+   |
+LL |         y
+   |         ^ help: a local variable with a similar name exists: `x`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/structs/struct-fields-shorthand.rs b/src/test/ui/structs/struct-fields-shorthand.rs
new file mode 100644
index 0000000..45e3014
--- /dev/null
+++ b/src/test/ui/structs/struct-fields-shorthand.rs
@@ -0,0 +1,12 @@
+struct Foo {
+    x: i32,
+    y: i32
+}
+
+fn main() {
+    let (x, y, z) = (0, 1, 2);
+    let foo = Foo {
+        x, y, z //~ ERROR struct `Foo` has no field named `z`
+    };
+}
+
diff --git a/src/test/ui/structs/struct-fields-shorthand.stderr b/src/test/ui/structs/struct-fields-shorthand.stderr
new file mode 100644
index 0000000..a285a39
--- /dev/null
+++ b/src/test/ui/structs/struct-fields-shorthand.stderr
@@ -0,0 +1,11 @@
+error[E0560]: struct `Foo` has no field named `z`
+  --> $DIR/struct-fields-shorthand.rs:9:15
+   |
+LL |         x, y, z
+   |               ^ `Foo` does not have this field
+   |
+   = note: available fields are: `x`, `y`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0560`.
diff --git a/src/test/ui/structs/struct-fields-too-many.rs b/src/test/ui/structs/struct-fields-too-many.rs
new file mode 100644
index 0000000..8be8dcb
--- /dev/null
+++ b/src/test/ui/structs/struct-fields-too-many.rs
@@ -0,0 +1,11 @@
+struct BuildData {
+    foo: isize,
+}
+
+fn main() {
+    let foo = BuildData {
+        foo: 0,
+        bar: 0
+        //~^ ERROR struct `BuildData` has no field named `bar`
+    };
+}
diff --git a/src/test/ui/structs/struct-fields-too-many.stderr b/src/test/ui/structs/struct-fields-too-many.stderr
new file mode 100644
index 0000000..a1b7a7a
--- /dev/null
+++ b/src/test/ui/structs/struct-fields-too-many.stderr
@@ -0,0 +1,11 @@
+error[E0560]: struct `BuildData` has no field named `bar`
+  --> $DIR/struct-fields-too-many.rs:8:9
+   |
+LL |         bar: 0
+   |         ^^^ `BuildData` does not have this field
+   |
+   = note: available fields are: `foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0560`.
diff --git a/src/test/ui/structs/struct-fields-typo.rs b/src/test/ui/structs/struct-fields-typo.rs
new file mode 100644
index 0000000..0e9b2ae
--- /dev/null
+++ b/src/test/ui/structs/struct-fields-typo.rs
@@ -0,0 +1,15 @@
+struct BuildData {
+    foo: isize,
+    bar: f32
+}
+
+fn main() {
+    let foo = BuildData {
+        foo: 0,
+        bar: 0.5,
+    };
+    let x = foo.baa; //~ ERROR no field `baa` on type `BuildData`
+                     //~| HELP a field with a similar name exists
+                     //~| SUGGESTION bar
+    println!("{}", x);
+}
diff --git a/src/test/ui/structs/struct-fields-typo.stderr b/src/test/ui/structs/struct-fields-typo.stderr
new file mode 100644
index 0000000..6949a0a
--- /dev/null
+++ b/src/test/ui/structs/struct-fields-typo.stderr
@@ -0,0 +1,9 @@
+error[E0609]: no field `baa` on type `BuildData`
+  --> $DIR/struct-fields-typo.rs:11:17
+   |
+LL |     let x = foo.baa;
+   |                 ^^^ help: a field with a similar name exists: `bar`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0609`.
diff --git a/src/test/ui/structs/struct-like-enum-nonexhaustive.rs b/src/test/ui/structs/struct-like-enum-nonexhaustive.rs
new file mode 100644
index 0000000..b1fc0f5
--- /dev/null
+++ b/src/test/ui/structs/struct-like-enum-nonexhaustive.rs
@@ -0,0 +1,12 @@
+enum A {
+    B { x: Option<isize> },
+    C
+}
+
+fn main() {
+    let x = A::B { x: Some(3) };
+    match x {   //~ ERROR non-exhaustive patterns
+        A::C => {}
+        A::B { x: None } => {}
+    }
+}
diff --git a/src/test/ui/structs/struct-like-enum-nonexhaustive.stderr b/src/test/ui/structs/struct-like-enum-nonexhaustive.stderr
new file mode 100644
index 0000000..d6b5af1
--- /dev/null
+++ b/src/test/ui/structs/struct-like-enum-nonexhaustive.stderr
@@ -0,0 +1,18 @@
+error[E0004]: non-exhaustive patterns: `B { x: Some(_) }` not covered
+  --> $DIR/struct-like-enum-nonexhaustive.rs:8:11
+   |
+LL | / enum A {
+LL | |     B { x: Option<isize> },
+   | |     - not covered
+LL | |     C
+LL | | }
+   | |_- `A` defined here
+...
+LL |       match x {
+   |             ^ pattern `B { x: Some(_) }` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/structs/struct-missing-comma.rs b/src/test/ui/structs/struct-missing-comma.rs
new file mode 100644
index 0000000..4c3cac3
--- /dev/null
+++ b/src/test/ui/structs/struct-missing-comma.rs
@@ -0,0 +1,11 @@
+// Issue #50636
+
+struct S {
+    foo: u32 //~ expected `,`, or `}`, found `bar`
+    //     ~^ HELP try adding a comma: ','
+    bar: u32
+}
+
+fn main() {
+    let s = S { foo: 5, bar: 6 };
+}
diff --git a/src/test/ui/structs/struct-missing-comma.stderr b/src/test/ui/structs/struct-missing-comma.stderr
new file mode 100644
index 0000000..f5b79f5
--- /dev/null
+++ b/src/test/ui/structs/struct-missing-comma.stderr
@@ -0,0 +1,8 @@
+error: expected `,`, or `}`, found `bar`
+  --> $DIR/struct-missing-comma.rs:4:13
+   |
+LL |     foo: u32
+   |             ^ help: try adding a comma: `,`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/structs/struct-pat-derived-error.rs b/src/test/ui/structs/struct-pat-derived-error.rs
new file mode 100644
index 0000000..f49a8ff
--- /dev/null
+++ b/src/test/ui/structs/struct-pat-derived-error.rs
@@ -0,0 +1,14 @@
+struct A {
+    b: usize,
+    c: usize
+}
+
+impl A {
+    fn foo(&self) {
+        let A { x, y } = self.d; //~ ERROR no field `d` on type `&A`
+        //~^ ERROR struct `A` does not have fields named `x`, `y`
+        //~| ERROR pattern does not mention fields `b`, `c`
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/structs/struct-pat-derived-error.stderr b/src/test/ui/structs/struct-pat-derived-error.stderr
new file mode 100644
index 0000000..92a88de
--- /dev/null
+++ b/src/test/ui/structs/struct-pat-derived-error.stderr
@@ -0,0 +1,22 @@
+error[E0609]: no field `d` on type `&A`
+  --> $DIR/struct-pat-derived-error.rs:8:31
+   |
+LL |         let A { x, y } = self.d;
+   |                               ^
+
+error[E0026]: struct `A` does not have fields named `x`, `y`
+  --> $DIR/struct-pat-derived-error.rs:8:17
+   |
+LL |         let A { x, y } = self.d;
+   |                 ^  ^ struct `A` does not have these fields
+
+error[E0027]: pattern does not mention fields `b`, `c`
+  --> $DIR/struct-pat-derived-error.rs:8:13
+   |
+LL |         let A { x, y } = self.d;
+   |             ^^^^^^^^^^ missing fields `b`, `c`
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0026, E0027, E0609.
+For more information about an error, try `rustc --explain E0026`.
diff --git a/src/test/ui/structs/struct-path-alias-bounds.rs b/src/test/ui/structs/struct-path-alias-bounds.rs
new file mode 100644
index 0000000..ae6ca80
--- /dev/null
+++ b/src/test/ui/structs/struct-path-alias-bounds.rs
@@ -0,0 +1,11 @@
+// issue #36286
+
+struct S<T: Clone> { a: T }
+
+struct NoClone;
+type A = S<NoClone>;
+
+fn main() {
+    let s = A { a: NoClone };
+    //~^ ERROR the trait bound `NoClone: std::clone::Clone` is not satisfied
+}
diff --git a/src/test/ui/structs/struct-path-alias-bounds.stderr b/src/test/ui/structs/struct-path-alias-bounds.stderr
new file mode 100644
index 0000000..70eb261
--- /dev/null
+++ b/src/test/ui/structs/struct-path-alias-bounds.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `NoClone: std::clone::Clone` is not satisfied
+  --> $DIR/struct-path-alias-bounds.rs:9:13
+   |
+LL |     let s = A { a: NoClone };
+   |             ^ the trait `std::clone::Clone` is not implemented for `NoClone`
+   |
+note: required by `S`
+  --> $DIR/struct-path-alias-bounds.rs:3:1
+   |
+LL | struct S<T: Clone> { a: T }
+   | ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/structs/struct-path-associated-type.rs b/src/test/ui/structs/struct-path-associated-type.rs
new file mode 100644
index 0000000..15b37fa
--- /dev/null
+++ b/src/test/ui/structs/struct-path-associated-type.rs
@@ -0,0 +1,38 @@
+struct S;
+
+trait Tr {
+    type A;
+}
+
+impl Tr for S {
+    type A = S;
+}
+
+fn f<T: Tr>() {
+    let s = T::A {};
+    //~^ ERROR expected struct, variant or union type, found associated type
+    let z = T::A::<u8> {};
+    //~^ ERROR expected struct, variant or union type, found associated type
+    //~| ERROR type arguments are not allowed for this type
+    match S {
+        T::A {} => {}
+        //~^ ERROR expected struct, variant or union type, found associated type
+    }
+}
+
+fn g<T: Tr<A = S>>() {
+    let s = T::A {}; // OK
+    let z = T::A::<u8> {}; //~ ERROR type arguments are not allowed for this type
+    match S {
+        T::A {} => {} // OK
+    }
+}
+
+fn main() {
+    let s = S::A {}; //~ ERROR ambiguous associated type
+    let z = S::A::<u8> {}; //~ ERROR ambiguous associated type
+    //~^ ERROR type arguments are not allowed for this type
+    match S {
+        S::A {} => {} //~ ERROR ambiguous associated type
+    }
+}
diff --git a/src/test/ui/structs/struct-path-associated-type.stderr b/src/test/ui/structs/struct-path-associated-type.stderr
new file mode 100644
index 0000000..f054bd3
--- /dev/null
+++ b/src/test/ui/structs/struct-path-associated-type.stderr
@@ -0,0 +1,58 @@
+error[E0071]: expected struct, variant or union type, found associated type
+  --> $DIR/struct-path-associated-type.rs:12:13
+   |
+LL |     let s = T::A {};
+   |             ^^^^ not a struct
+
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/struct-path-associated-type.rs:14:20
+   |
+LL |     let z = T::A::<u8> {};
+   |                    ^^ type argument not allowed
+
+error[E0071]: expected struct, variant or union type, found associated type
+  --> $DIR/struct-path-associated-type.rs:14:13
+   |
+LL |     let z = T::A::<u8> {};
+   |             ^^^^^^^^^^ not a struct
+
+error[E0071]: expected struct, variant or union type, found associated type
+  --> $DIR/struct-path-associated-type.rs:18:9
+   |
+LL |         T::A {} => {}
+   |         ^^^^ not a struct
+
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/struct-path-associated-type.rs:25:20
+   |
+LL |     let z = T::A::<u8> {};
+   |                    ^^ type argument not allowed
+
+error[E0223]: ambiguous associated type
+  --> $DIR/struct-path-associated-type.rs:32:13
+   |
+LL |     let s = S::A {};
+   |             ^^^^ help: use fully-qualified syntax: `<S as Trait>::A`
+
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/struct-path-associated-type.rs:33:20
+   |
+LL |     let z = S::A::<u8> {};
+   |                    ^^ type argument not allowed
+
+error[E0223]: ambiguous associated type
+  --> $DIR/struct-path-associated-type.rs:33:13
+   |
+LL |     let z = S::A::<u8> {};
+   |             ^^^^^^^^^^ help: use fully-qualified syntax: `<S as Trait>::A`
+
+error[E0223]: ambiguous associated type
+  --> $DIR/struct-path-associated-type.rs:36:9
+   |
+LL |         S::A {} => {}
+   |         ^^^^ help: use fully-qualified syntax: `<S as Trait>::A`
+
+error: aborting due to 9 previous errors
+
+Some errors occurred: E0071, E0109, E0223.
+For more information about an error, try `rustc --explain E0071`.
diff --git a/src/test/ui/structs/struct-path-self-type-mismatch.rs b/src/test/ui/structs/struct-path-self-type-mismatch.rs
new file mode 100644
index 0000000..c0c557e
--- /dev/null
+++ b/src/test/ui/structs/struct-path-self-type-mismatch.rs
@@ -0,0 +1,21 @@
+struct Foo<A> { inner: A }
+
+trait Bar { fn bar(); }
+
+impl Bar for Foo<i32> {
+    fn bar() {
+        Self { inner: 1.5f32 }; //~ ERROR mismatched types
+    }
+}
+
+impl<T> Foo<T> {
+    fn new<U>(u: U) -> Foo<U> {
+        Self {
+        //~^ ERROR mismatched types
+            inner: u
+            //~^ ERROR mismatched types
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/structs/struct-path-self-type-mismatch.stderr b/src/test/ui/structs/struct-path-self-type-mismatch.stderr
new file mode 100644
index 0000000..72c6d7a
--- /dev/null
+++ b/src/test/ui/structs/struct-path-self-type-mismatch.stderr
@@ -0,0 +1,33 @@
+error[E0308]: mismatched types
+  --> $DIR/struct-path-self-type-mismatch.rs:7:23
+   |
+LL |         Self { inner: 1.5f32 };
+   |                       ^^^^^^ expected i32, found f32
+
+error[E0308]: mismatched types
+  --> $DIR/struct-path-self-type-mismatch.rs:15:20
+   |
+LL |             inner: u
+   |                    ^ expected type parameter, found a different type parameter
+   |
+   = note: expected type `T`
+              found type `U`
+
+error[E0308]: mismatched types
+  --> $DIR/struct-path-self-type-mismatch.rs:13:9
+   |
+LL |       fn new<U>(u: U) -> Foo<U> {
+   |                          ------ expected `Foo<U>` because of return type
+LL | /         Self {
+LL | |
+LL | |             inner: u
+LL | |
+LL | |         }
+   | |_________^ expected type parameter, found a different type parameter
+   |
+   = note: expected type `Foo<U>`
+              found type `Foo<T>`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/structs/struct-path-self.rs b/src/test/ui/structs/struct-path-self.rs
new file mode 100644
index 0000000..77880bf
--- /dev/null
+++ b/src/test/ui/structs/struct-path-self.rs
@@ -0,0 +1,37 @@
+struct S;
+
+trait Tr {
+    fn f() {
+        let s = Self {};
+        //~^ ERROR expected struct, variant or union type, found Self
+        let z = Self::<u8> {};
+        //~^ ERROR expected struct, variant or union type, found Self
+        //~| ERROR type arguments are not allowed for this type
+        match s {
+            Self { .. } => {}
+            //~^ ERROR expected struct, variant or union type, found Self
+        }
+    }
+}
+
+impl Tr for S {
+    fn f() {
+        let s = Self {}; // OK
+        let z = Self::<u8> {}; //~ ERROR type arguments are not allowed for this type
+        match s {
+            Self { .. } => {} // OK
+        }
+    }
+}
+
+impl S {
+    fn g() {
+        let s = Self {}; // OK
+        let z = Self::<u8> {}; //~ ERROR type arguments are not allowed for this type
+        match s {
+            Self { .. } => {} // OK
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/structs/struct-path-self.stderr b/src/test/ui/structs/struct-path-self.stderr
new file mode 100644
index 0000000..d9e84ac
--- /dev/null
+++ b/src/test/ui/structs/struct-path-self.stderr
@@ -0,0 +1,40 @@
+error[E0071]: expected struct, variant or union type, found Self
+  --> $DIR/struct-path-self.rs:5:17
+   |
+LL |         let s = Self {};
+   |                 ^^^^ not a struct
+
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/struct-path-self.rs:7:24
+   |
+LL |         let z = Self::<u8> {};
+   |                        ^^ type argument not allowed
+
+error[E0071]: expected struct, variant or union type, found Self
+  --> $DIR/struct-path-self.rs:7:17
+   |
+LL |         let z = Self::<u8> {};
+   |                 ^^^^^^^^^^ not a struct
+
+error[E0071]: expected struct, variant or union type, found Self
+  --> $DIR/struct-path-self.rs:11:13
+   |
+LL |             Self { .. } => {}
+   |             ^^^^ not a struct
+
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/struct-path-self.rs:20:24
+   |
+LL |         let z = Self::<u8> {};
+   |                        ^^ type argument not allowed
+
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/struct-path-self.rs:30:24
+   |
+LL |         let z = Self::<u8> {};
+   |                        ^^ type argument not allowed
+
+error: aborting due to 6 previous errors
+
+Some errors occurred: E0071, E0109.
+For more information about an error, try `rustc --explain E0071`.
diff --git a/src/test/ui/structs/struct-pattern-match-useless.rs b/src/test/ui/structs/struct-pattern-match-useless.rs
new file mode 100644
index 0000000..93f0a93
--- /dev/null
+++ b/src/test/ui/structs/struct-pattern-match-useless.rs
@@ -0,0 +1,15 @@
+#![deny(unreachable_patterns)]
+
+struct Foo {
+    x: isize,
+    y: isize,
+}
+
+pub fn main() {
+    let a = Foo { x: 1, y: 2 };
+    match a {
+        Foo { x: _x, y: _y } => (),
+        Foo { .. } => () //~ ERROR unreachable pattern
+    }
+
+}
diff --git a/src/test/ui/structs/struct-pattern-match-useless.stderr b/src/test/ui/structs/struct-pattern-match-useless.stderr
new file mode 100644
index 0000000..5b0c930
--- /dev/null
+++ b/src/test/ui/structs/struct-pattern-match-useless.stderr
@@ -0,0 +1,14 @@
+error: unreachable pattern
+  --> $DIR/struct-pattern-match-useless.rs:12:9
+   |
+LL |         Foo { .. } => ()
+   |         ^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/struct-pattern-match-useless.rs:1:9
+   |
+LL | #![deny(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/structs/struct-variant-privacy-xc.rs b/src/test/ui/structs/struct-variant-privacy-xc.rs
new file mode 100644
index 0000000..10e9639
--- /dev/null
+++ b/src/test/ui/structs/struct-variant-privacy-xc.rs
@@ -0,0 +1,10 @@
+// aux-build:struct_variant_privacy.rs
+extern crate struct_variant_privacy;
+
+fn f(b: struct_variant_privacy::Bar) { //~ ERROR enum `Bar` is private
+    match b {
+        struct_variant_privacy::Bar::Baz { a: _a } => {} //~ ERROR enum `Bar` is private
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/structs/struct-variant-privacy-xc.stderr b/src/test/ui/structs/struct-variant-privacy-xc.stderr
new file mode 100644
index 0000000..39241b6
--- /dev/null
+++ b/src/test/ui/structs/struct-variant-privacy-xc.stderr
@@ -0,0 +1,15 @@
+error[E0603]: enum `Bar` is private
+  --> $DIR/struct-variant-privacy-xc.rs:4:33
+   |
+LL | fn f(b: struct_variant_privacy::Bar) {
+   |                                 ^^^
+
+error[E0603]: enum `Bar` is private
+  --> $DIR/struct-variant-privacy-xc.rs:6:33
+   |
+LL |         struct_variant_privacy::Bar::Baz { a: _a } => {}
+   |                                 ^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0603`.
diff --git a/src/test/ui/structs/struct-variant-privacy.rs b/src/test/ui/structs/struct-variant-privacy.rs
new file mode 100644
index 0000000..8355879
--- /dev/null
+++ b/src/test/ui/structs/struct-variant-privacy.rs
@@ -0,0 +1,13 @@
+mod foo {
+    enum Bar {
+        Baz { a: isize }
+    }
+}
+
+fn f(b: foo::Bar) { //~ ERROR enum `Bar` is private
+    match b {
+        foo::Bar::Baz { a: _a } => {} //~ ERROR enum `Bar` is private
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/structs/struct-variant-privacy.stderr b/src/test/ui/structs/struct-variant-privacy.stderr
new file mode 100644
index 0000000..127a650
--- /dev/null
+++ b/src/test/ui/structs/struct-variant-privacy.stderr
@@ -0,0 +1,15 @@
+error[E0603]: enum `Bar` is private
+  --> $DIR/struct-variant-privacy.rs:7:14
+   |
+LL | fn f(b: foo::Bar) {
+   |              ^^^
+
+error[E0603]: enum `Bar` is private
+  --> $DIR/struct-variant-privacy.rs:9:14
+   |
+LL |         foo::Bar::Baz { a: _a } => {}
+   |              ^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0603`.
diff --git a/src/test/ui/structs/structure-constructor-type-mismatch.rs b/src/test/ui/structs/structure-constructor-type-mismatch.rs
new file mode 100644
index 0000000..8850f6ea
--- /dev/null
+++ b/src/test/ui/structs/structure-constructor-type-mismatch.rs
@@ -0,0 +1,73 @@
+struct Point<T> {
+    x: T,
+    y: T,
+}
+
+type PointF = Point<f32>;
+
+struct Pair<T,U> {
+    x: T,
+    y: U,
+}
+
+type PairF<U> = Pair<f32,U>;
+
+fn main() {
+    let pt = PointF {
+        x: 1,
+        //~^ ERROR mismatched types
+        //~| expected f32, found integer
+        y: 2,
+        //~^ ERROR mismatched types
+        //~| expected f32, found integer
+    };
+
+    let pt2 = Point::<f32> {
+        x: 3,
+        //~^ ERROR mismatched types
+        //~| expected f32, found integer
+        y: 4,
+        //~^ ERROR mismatched types
+        //~| expected f32, found integer
+    };
+
+    let pair = PairF {
+        x: 5,
+        //~^ ERROR mismatched types
+        //~| expected f32, found integer
+        y: 6,
+    };
+
+    let pair2 = PairF::<i32> {
+        x: 7,
+        //~^ ERROR mismatched types
+        //~| expected f32, found integer
+        y: 8,
+    };
+
+    let pt3 = PointF::<i32> { //~ ERROR wrong number of type arguments
+        x: 9,  //~ ERROR mismatched types
+        y: 10, //~ ERROR mismatched types
+    };
+
+    match (Point { x: 1, y: 2 }) {
+        PointF::<u32> { .. } => {} //~ ERROR wrong number of type arguments
+        //~^ ERROR mismatched types
+    }
+
+    match (Point { x: 1, y: 2 }) {
+        PointF { .. } => {} //~ ERROR mismatched types
+    }
+
+    match (Point { x: 1.0, y: 2.0 }) {
+        PointF { .. } => {} // ok
+    }
+
+    match (Pair { x: 1, y: 2 }) {
+        PairF::<u32> { .. } => {} //~ ERROR mismatched types
+    }
+
+    match (Pair { x: 1.0, y: 2 }) {
+        PairF::<u32> { .. } => {} // ok
+    }
+}
diff --git a/src/test/ui/structs/structure-constructor-type-mismatch.stderr b/src/test/ui/structs/structure-constructor-type-mismatch.stderr
new file mode 100644
index 0000000..375678b7
--- /dev/null
+++ b/src/test/ui/structs/structure-constructor-type-mismatch.stderr
@@ -0,0 +1,145 @@
+error[E0308]: mismatched types
+  --> $DIR/structure-constructor-type-mismatch.rs:17:12
+   |
+LL |         x: 1,
+   |            ^
+   |            |
+   |            expected f32, found integer
+   |            help: use a float literal: `1.0`
+   |
+   = note: expected type `f32`
+              found type `{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/structure-constructor-type-mismatch.rs:20:12
+   |
+LL |         y: 2,
+   |            ^
+   |            |
+   |            expected f32, found integer
+   |            help: use a float literal: `2.0`
+   |
+   = note: expected type `f32`
+              found type `{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/structure-constructor-type-mismatch.rs:26:12
+   |
+LL |         x: 3,
+   |            ^
+   |            |
+   |            expected f32, found integer
+   |            help: use a float literal: `3.0`
+   |
+   = note: expected type `f32`
+              found type `{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/structure-constructor-type-mismatch.rs:29:12
+   |
+LL |         y: 4,
+   |            ^
+   |            |
+   |            expected f32, found integer
+   |            help: use a float literal: `4.0`
+   |
+   = note: expected type `f32`
+              found type `{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/structure-constructor-type-mismatch.rs:35:12
+   |
+LL |         x: 5,
+   |            ^
+   |            |
+   |            expected f32, found integer
+   |            help: use a float literal: `5.0`
+   |
+   = note: expected type `f32`
+              found type `{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/structure-constructor-type-mismatch.rs:42:12
+   |
+LL |         x: 7,
+   |            ^
+   |            |
+   |            expected f32, found integer
+   |            help: use a float literal: `7.0`
+   |
+   = note: expected type `f32`
+              found type `{integer}`
+
+error[E0107]: wrong number of type arguments: expected 0, found 1
+  --> $DIR/structure-constructor-type-mismatch.rs:48:24
+   |
+LL |     let pt3 = PointF::<i32> {
+   |                        ^^^ unexpected type argument
+
+error[E0308]: mismatched types
+  --> $DIR/structure-constructor-type-mismatch.rs:49:12
+   |
+LL |         x: 9,
+   |            ^
+   |            |
+   |            expected f32, found integer
+   |            help: use a float literal: `9.0`
+   |
+   = note: expected type `f32`
+              found type `{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/structure-constructor-type-mismatch.rs:50:12
+   |
+LL |         y: 10,
+   |            ^^
+   |            |
+   |            expected f32, found integer
+   |            help: use a float literal: `10.0`
+   |
+   = note: expected type `f32`
+              found type `{integer}`
+
+error[E0107]: wrong number of type arguments: expected 0, found 1
+  --> $DIR/structure-constructor-type-mismatch.rs:54:18
+   |
+LL |         PointF::<u32> { .. } => {}
+   |                  ^^^ unexpected type argument
+
+error[E0308]: mismatched types
+  --> $DIR/structure-constructor-type-mismatch.rs:54:9
+   |
+LL |     match (Point { x: 1, y: 2 }) {
+   |           ---------------------- this match expression has type `Point<{integer}>`
+LL |         PointF::<u32> { .. } => {}
+   |         ^^^^^^^^^^^^^^^^^^^^ expected integer, found f32
+   |
+   = note: expected type `Point<{integer}>`
+              found type `Point<f32>`
+
+error[E0308]: mismatched types
+  --> $DIR/structure-constructor-type-mismatch.rs:59:9
+   |
+LL |     match (Point { x: 1, y: 2 }) {
+   |           ---------------------- this match expression has type `Point<{integer}>`
+LL |         PointF { .. } => {}
+   |         ^^^^^^^^^^^^^ expected integer, found f32
+   |
+   = note: expected type `Point<{integer}>`
+              found type `Point<f32>`
+
+error[E0308]: mismatched types
+  --> $DIR/structure-constructor-type-mismatch.rs:67:9
+   |
+LL |     match (Pair { x: 1, y: 2 }) {
+   |           --------------------- this match expression has type `Pair<{integer}, {integer}>`
+LL |         PairF::<u32> { .. } => {}
+   |         ^^^^^^^^^^^^^^^^^^^ expected integer, found f32
+   |
+   = note: expected type `Pair<{integer}, {integer}>`
+              found type `Pair<f32, u32>`
+
+error: aborting due to 13 previous errors
+
+Some errors occurred: E0107, E0308.
+For more information about an error, try `rustc --explain E0107`.
diff --git a/src/test/ui/substs-ppaux.normal.stderr b/src/test/ui/substs-ppaux.normal.stderr
new file mode 100644
index 0000000..567b4d9
--- /dev/null
+++ b/src/test/ui/substs-ppaux.normal.stderr
@@ -0,0 +1,55 @@
+error[E0308]: mismatched types
+  --> $DIR/substs-ppaux.rs:16:17
+   |
+LL |     let x: () = <i8 as Foo<'static, 'static,  u8>>::bar::<'static, char>;
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found fn item
+   |
+   = note: expected type `()`
+              found type `fn() {<i8 as Foo<'static, 'static, u8>>::bar::<'static, char>}`
+
+error[E0308]: mismatched types
+  --> $DIR/substs-ppaux.rs:25:17
+   |
+LL |     let x: () = <i8 as Foo<'static, 'static,  u32>>::bar::<'static, char>;
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found fn item
+   |
+   = note: expected type `()`
+              found type `fn() {<i8 as Foo<'static, 'static>>::bar::<'static, char>}`
+
+error[E0308]: mismatched types
+  --> $DIR/substs-ppaux.rs:33:17
+   |
+LL |     let x: () = <i8 as Foo<'static, 'static,  u8>>::baz;
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found fn item
+   |
+   = note: expected type `()`
+              found type `fn() {<i8 as Foo<'static, 'static, u8>>::baz}`
+
+error[E0308]: mismatched types
+  --> $DIR/substs-ppaux.rs:41:17
+   |
+LL |     let x: () = foo::<'static>;
+   |                 ^^^^^^^^^^^^^^ expected (), found fn item
+   |
+   = note: expected type `()`
+              found type `fn() {foo::<'static>}`
+
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+  --> $DIR/substs-ppaux.rs:49:5
+   |
+LL |     <str as Foo<u8>>::bar;
+   |     ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `str`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: required because of the requirements on the impl of `Foo<'_, '_, u8>` for `str`
+note: required by `Foo::bar`
+  --> $DIR/substs-ppaux.rs:7:5
+   |
+LL |     fn bar<'a, T>() where T: 'a {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
+
+Some errors occurred: E0277, E0308.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/substs-ppaux.rs b/src/test/ui/substs-ppaux.rs
new file mode 100644
index 0000000..129ebd4
--- /dev/null
+++ b/src/test/ui/substs-ppaux.rs
@@ -0,0 +1,52 @@
+//
+// revisions: verbose normal
+//
+//[verbose] compile-flags: -Z verbose
+
+trait Foo<'b, 'c, S=u32> {
+    fn bar<'a, T>() where T: 'a {}
+    fn baz() {}
+}
+
+impl<'a,'b,T,S> Foo<'a, 'b, S> for T {}
+
+fn main() {}
+
+fn foo<'z>() where &'z (): Sized {
+    let x: () = <i8 as Foo<'static, 'static,  u8>>::bar::<'static, char>;
+    //[verbose]~^ ERROR mismatched types
+    //[verbose]~| expected type `()`
+    //[verbose]~| found type `fn() {<i8 as Foo<ReStatic, ReStatic, u8>>::bar::<ReStatic, char>}`
+    //[normal]~^^^^ ERROR mismatched types
+    //[normal]~| expected type `()`
+    //[normal]~| found type `fn() {<i8 as Foo<'static, 'static, u8>>::bar::<'static, char>}`
+
+
+    let x: () = <i8 as Foo<'static, 'static,  u32>>::bar::<'static, char>;
+    //[verbose]~^ ERROR mismatched types
+    //[verbose]~| expected type `()`
+    //[verbose]~| found type `fn() {<i8 as Foo<ReStatic, ReStatic>>::bar::<ReStatic, char>}`
+    //[normal]~^^^^ ERROR mismatched types
+    //[normal]~| expected type `()`
+    //[normal]~| found type `fn() {<i8 as Foo<'static, 'static>>::bar::<'static, char>}`
+
+    let x: () = <i8 as Foo<'static, 'static,  u8>>::baz;
+    //[verbose]~^ ERROR mismatched types
+    //[verbose]~| expected type `()`
+    //[verbose]~| found type `fn() {<i8 as Foo<ReStatic, ReStatic, u8>>::baz}`
+    //[normal]~^^^^ ERROR mismatched types
+    //[normal]~| expected type `()`
+    //[normal]~| found type `fn() {<i8 as Foo<'static, 'static, u8>>::baz}`
+
+    let x: () = foo::<'static>;
+    //[verbose]~^ ERROR mismatched types
+    //[verbose]~| expected type `()`
+    //[verbose]~| found type `fn() {foo::<ReStatic>}`
+    //[normal]~^^^^ ERROR mismatched types
+    //[normal]~| expected type `()`
+    //[normal]~| found type `fn() {foo::<'static>}`
+
+    <str as Foo<u8>>::bar;
+    //[verbose]~^ ERROR the size for values of type
+    //[normal]~^^ ERROR the size for values of type
+}
diff --git a/src/test/ui/substs-ppaux.verbose.stderr b/src/test/ui/substs-ppaux.verbose.stderr
new file mode 100644
index 0000000..8693647
--- /dev/null
+++ b/src/test/ui/substs-ppaux.verbose.stderr
@@ -0,0 +1,55 @@
+error[E0308]: mismatched types
+  --> $DIR/substs-ppaux.rs:16:17
+   |
+LL |     let x: () = <i8 as Foo<'static, 'static,  u8>>::bar::<'static, char>;
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found fn item
+   |
+   = note: expected type `()`
+              found type `fn() {<i8 as Foo<ReStatic, ReStatic, u8>>::bar::<ReStatic, char>}`
+
+error[E0308]: mismatched types
+  --> $DIR/substs-ppaux.rs:25:17
+   |
+LL |     let x: () = <i8 as Foo<'static, 'static,  u32>>::bar::<'static, char>;
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found fn item
+   |
+   = note: expected type `()`
+              found type `fn() {<i8 as Foo<ReStatic, ReStatic>>::bar::<ReStatic, char>}`
+
+error[E0308]: mismatched types
+  --> $DIR/substs-ppaux.rs:33:17
+   |
+LL |     let x: () = <i8 as Foo<'static, 'static,  u8>>::baz;
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found fn item
+   |
+   = note: expected type `()`
+              found type `fn() {<i8 as Foo<ReStatic, ReStatic, u8>>::baz}`
+
+error[E0308]: mismatched types
+  --> $DIR/substs-ppaux.rs:41:17
+   |
+LL |     let x: () = foo::<'static>;
+   |                 ^^^^^^^^^^^^^^ expected (), found fn item
+   |
+   = note: expected type `()`
+              found type `fn() {foo::<ReStatic>}`
+
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+  --> $DIR/substs-ppaux.rs:49:5
+   |
+LL |     <str as Foo<u8>>::bar;
+   |     ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `str`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: required because of the requirements on the impl of `Foo<'_#0r, '_#1r, u8>` for `str`
+note: required by `Foo::bar`
+  --> $DIR/substs-ppaux.rs:7:5
+   |
+LL |     fn bar<'a, T>() where T: 'a {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
+
+Some errors occurred: E0277, E0308.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/suffixed-literal-meta.rs b/src/test/ui/suffixed-literal-meta.rs
new file mode 100644
index 0000000..bd2d662
--- /dev/null
+++ b/src/test/ui/suffixed-literal-meta.rs
@@ -0,0 +1,15 @@
+#![feature(custom_attribute)]
+
+#[my_attr = 1usize] //~ ERROR: suffixed literals are not allowed in attributes
+#[my_attr = 1u8] //~ ERROR: suffixed literals are not allowed in attributes
+#[my_attr = 1u16] //~ ERROR: suffixed literals are not allowed in attributes
+#[my_attr = 1u32] //~ ERROR: suffixed literals are not allowed in attributes
+#[my_attr = 1u64] //~ ERROR: suffixed literals are not allowed in attributes
+#[my_attr = 1isize] //~ ERROR: suffixed literals are not allowed in attributes
+#[my_attr = 1i8] //~ ERROR: suffixed literals are not allowed in attributes
+#[my_attr = 1i16] //~ ERROR: suffixed literals are not allowed in attributes
+#[my_attr = 1i32] //~ ERROR: suffixed literals are not allowed in attributes
+#[my_attr = 1i64] //~ ERROR: suffixed literals are not allowed in attributes
+#[my_attr = 1.0f32] //~ ERROR: suffixed literals are not allowed in attributes
+#[my_attr = 1.0f64] //~ ERROR: suffixed literals are not allowed in attributes
+fn main() { }
diff --git a/src/test/ui/suffixed-literal-meta.stderr b/src/test/ui/suffixed-literal-meta.stderr
new file mode 100644
index 0000000..495404a
--- /dev/null
+++ b/src/test/ui/suffixed-literal-meta.stderr
@@ -0,0 +1,98 @@
+error: suffixed literals are not allowed in attributes
+  --> $DIR/suffixed-literal-meta.rs:3:13
+   |
+LL | #[my_attr = 1usize]
+   |             ^^^^^^
+   |
+   = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
+
+error: suffixed literals are not allowed in attributes
+  --> $DIR/suffixed-literal-meta.rs:4:13
+   |
+LL | #[my_attr = 1u8]
+   |             ^^^
+   |
+   = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
+
+error: suffixed literals are not allowed in attributes
+  --> $DIR/suffixed-literal-meta.rs:5:13
+   |
+LL | #[my_attr = 1u16]
+   |             ^^^^
+   |
+   = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
+
+error: suffixed literals are not allowed in attributes
+  --> $DIR/suffixed-literal-meta.rs:6:13
+   |
+LL | #[my_attr = 1u32]
+   |             ^^^^
+   |
+   = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
+
+error: suffixed literals are not allowed in attributes
+  --> $DIR/suffixed-literal-meta.rs:7:13
+   |
+LL | #[my_attr = 1u64]
+   |             ^^^^
+   |
+   = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
+
+error: suffixed literals are not allowed in attributes
+  --> $DIR/suffixed-literal-meta.rs:8:13
+   |
+LL | #[my_attr = 1isize]
+   |             ^^^^^^
+   |
+   = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
+
+error: suffixed literals are not allowed in attributes
+  --> $DIR/suffixed-literal-meta.rs:9:13
+   |
+LL | #[my_attr = 1i8]
+   |             ^^^
+   |
+   = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
+
+error: suffixed literals are not allowed in attributes
+  --> $DIR/suffixed-literal-meta.rs:10:13
+   |
+LL | #[my_attr = 1i16]
+   |             ^^^^
+   |
+   = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
+
+error: suffixed literals are not allowed in attributes
+  --> $DIR/suffixed-literal-meta.rs:11:13
+   |
+LL | #[my_attr = 1i32]
+   |             ^^^^
+   |
+   = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
+
+error: suffixed literals are not allowed in attributes
+  --> $DIR/suffixed-literal-meta.rs:12:13
+   |
+LL | #[my_attr = 1i64]
+   |             ^^^^
+   |
+   = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
+
+error: suffixed literals are not allowed in attributes
+  --> $DIR/suffixed-literal-meta.rs:13:13
+   |
+LL | #[my_attr = 1.0f32]
+   |             ^^^^^^
+   |
+   = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
+
+error: suffixed literals are not allowed in attributes
+  --> $DIR/suffixed-literal-meta.rs:14:13
+   |
+LL | #[my_attr = 1.0f64]
+   |             ^^^^^^
+   |
+   = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
+
+error: aborting due to 12 previous errors
+
diff --git a/src/test/ui/suggestions/as-ref.rs b/src/test/ui/suggestions/as-ref.rs
new file mode 100644
index 0000000..03f04c3
--- /dev/null
+++ b/src/test/ui/suggestions/as-ref.rs
@@ -0,0 +1,25 @@
+struct Foo;
+fn takes_ref(_: &Foo) {}
+
+fn main() {
+  let ref opt = Some(Foo);
+  opt.map(|arg| takes_ref(arg));
+  //~^ ERROR mismatched types [E0308]
+  opt.and_then(|arg| Some(takes_ref(arg)));
+  //~^ ERROR mismatched types [E0308]
+  let ref opt: Result<_, ()> = Ok(Foo);
+  opt.map(|arg| takes_ref(arg));
+  //~^ ERROR mismatched types [E0308]
+  opt.and_then(|arg| Ok(takes_ref(arg)));
+  //~^ ERROR mismatched types [E0308]
+  let x: &Option<usize> = &Some(3);
+  let y: Option<&usize> = x;
+  //~^ ERROR mismatched types [E0308]
+  let x: &Result<usize, usize> = &Ok(3);
+  let y: Result<&usize, &usize> = x;
+  //~^ ERROR mismatched types [E0308]
+  // note: do not suggest because of `E: usize`
+  let x: &Result<usize, usize> = &Ok(3);
+  let y: Result<&usize, usize> = x;
+  //~^ ERROR mismatched types [E0308]
+}
diff --git a/src/test/ui/suggestions/as-ref.stderr b/src/test/ui/suggestions/as-ref.stderr
new file mode 100644
index 0000000..8143acc
--- /dev/null
+++ b/src/test/ui/suggestions/as-ref.stderr
@@ -0,0 +1,81 @@
+error[E0308]: mismatched types
+  --> $DIR/as-ref.rs:6:27
+   |
+LL |   opt.map(|arg| takes_ref(arg));
+   |       ---                 ^^^ expected &Foo, found struct `Foo`
+   |       |
+   |       help: consider using `as_ref` instead: `as_ref().map`
+   |
+   = note: expected type `&Foo`
+              found type `Foo`
+
+error[E0308]: mismatched types
+  --> $DIR/as-ref.rs:8:37
+   |
+LL |   opt.and_then(|arg| Some(takes_ref(arg)));
+   |       --------                      ^^^ expected &Foo, found struct `Foo`
+   |       |
+   |       help: consider using `as_ref` instead: `as_ref().and_then`
+   |
+   = note: expected type `&Foo`
+              found type `Foo`
+
+error[E0308]: mismatched types
+  --> $DIR/as-ref.rs:11:27
+   |
+LL |   opt.map(|arg| takes_ref(arg));
+   |       ---                 ^^^ expected &Foo, found struct `Foo`
+   |       |
+   |       help: consider using `as_ref` instead: `as_ref().map`
+   |
+   = note: expected type `&Foo`
+              found type `Foo`
+
+error[E0308]: mismatched types
+  --> $DIR/as-ref.rs:13:35
+   |
+LL |   opt.and_then(|arg| Ok(takes_ref(arg)));
+   |       --------                    ^^^ expected &Foo, found struct `Foo`
+   |       |
+   |       help: consider using `as_ref` instead: `as_ref().and_then`
+   |
+   = note: expected type `&Foo`
+              found type `Foo`
+
+error[E0308]: mismatched types
+  --> $DIR/as-ref.rs:16:27
+   |
+LL |   let y: Option<&usize> = x;
+   |                           ^
+   |                           |
+   |                           expected enum `std::option::Option`, found reference
+   |                           help: you can convert from `&Option<T>` to `Option<&T>` using `.as_ref()`: `x.as_ref()`
+   |
+   = note: expected type `std::option::Option<&usize>`
+              found type `&std::option::Option<usize>`
+
+error[E0308]: mismatched types
+  --> $DIR/as-ref.rs:19:35
+   |
+LL |   let y: Result<&usize, &usize> = x;
+   |                                   ^ expected enum `std::result::Result`, found reference
+   |
+   = note: expected type `std::result::Result<&usize, &usize>`
+              found type `&std::result::Result<usize, usize>`
+help: you can convert from `&Result<T, E>` to `Result<&T, &E>` using `.as_ref()`
+   |
+LL |   let y: Result<&usize, &usize> = x.as_ref();
+   |                                   ^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/as-ref.rs:23:34
+   |
+LL |   let y: Result<&usize, usize> = x;
+   |                                  ^ expected enum `std::result::Result`, found reference
+   |
+   = note: expected type `std::result::Result<&usize, usize>`
+              found type `&std::result::Result<usize, usize>`
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/suggestions/assoc-const-as-field.rs b/src/test/ui/suggestions/assoc-const-as-field.rs
new file mode 100644
index 0000000..678b589
--- /dev/null
+++ b/src/test/ui/suggestions/assoc-const-as-field.rs
@@ -0,0 +1,13 @@
+pub mod Mod {
+    pub struct Foo {}
+    impl Foo {
+        pub const BAR: usize = 42;
+    }
+}
+
+fn foo(_: usize) {}
+
+fn main() {
+    foo(Mod::Foo.Bar);
+    //~^ ERROR expected value, found
+}
diff --git a/src/test/ui/suggestions/assoc-const-as-field.stderr b/src/test/ui/suggestions/assoc-const-as-field.stderr
new file mode 100644
index 0000000..5e746ec
--- /dev/null
+++ b/src/test/ui/suggestions/assoc-const-as-field.stderr
@@ -0,0 +1,11 @@
+error[E0423]: expected value, found struct `Mod::Foo`
+  --> $DIR/assoc-const-as-field.rs:11:9
+   |
+LL |     foo(Mod::Foo.Bar);
+   |         ^^^^^^^^----
+   |         |
+   |         help: use the path separator to refer to an item: `Mod::Foo::Bar`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0423`.
diff --git a/src/test/ui/suggestions/attribute-typos.rs b/src/test/ui/suggestions/attribute-typos.rs
new file mode 100644
index 0000000..13c6308
--- /dev/null
+++ b/src/test/ui/suggestions/attribute-typos.rs
@@ -0,0 +1,13 @@
+#[deprcated]    //~ ERROR E0658
+fn foo() {}     //~| HELP a built-in attribute with a similar name exists
+                //~| SUGGESTION deprecated
+                //~| HELP add #![feature(custom_attribute)] to the crate attributes to enable
+
+#[tests]        //~ ERROR E0658
+fn bar() {}     //~| HELP a built-in attribute with a similar name exists
+                //~| SUGGESTION test
+                //~| HELP add #![feature(custom_attribute)] to the crate attributes to enable
+
+#[rustc_err]    //~ ERROR E0658
+fn main() {}    //~| HELP add #![feature(rustc_attrs)] to the crate attributes to enable
+                // don't suggest rustc attributes
diff --git a/src/test/ui/suggestions/attribute-typos.stderr b/src/test/ui/suggestions/attribute-typos.stderr
new file mode 100644
index 0000000..077c955
--- /dev/null
+++ b/src/test/ui/suggestions/attribute-typos.stderr
@@ -0,0 +1,27 @@
+error[E0658]: unless otherwise specified, attributes with the prefix `rustc_` are reserved for internal compiler diagnostics (see issue #29642)
+  --> $DIR/attribute-typos.rs:11:3
+   |
+LL | #[rustc_err]
+   |   ^^^^^^^^^
+   |
+   = help: add #![feature(rustc_attrs)] to the crate attributes to enable
+
+error[E0658]: The attribute `tests` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/attribute-typos.rs:6:3
+   |
+LL | #[tests]
+   |   ^^^^^ help: a built-in attribute with a similar name exists: `test`
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error[E0658]: The attribute `deprcated` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/attribute-typos.rs:1:3
+   |
+LL | #[deprcated]
+   |   ^^^^^^^^^ help: a built-in attribute with a similar name exists: `deprecated`
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/suggestions/auxiliary/foo.rs b/src/test/ui/suggestions/auxiliary/foo.rs
new file mode 100644
index 0000000..e90bbef
--- /dev/null
+++ b/src/test/ui/suggestions/auxiliary/foo.rs
@@ -0,0 +1,3 @@
+//! Contains a struct with almost the same name as itself, to trigger Levenshtein suggestions.
+
+pub struct Foo;
diff --git a/src/test/ui/suggestions/auxiliary/struct_field_privacy.rs b/src/test/ui/suggestions/auxiliary/struct_field_privacy.rs
new file mode 100644
index 0000000..9765af1
--- /dev/null
+++ b/src/test/ui/suggestions/auxiliary/struct_field_privacy.rs
@@ -0,0 +1,9 @@
+pub struct A {
+    a: isize,
+    pub b: isize,
+}
+
+pub struct B {
+    pub a: isize,
+    b: isize,
+}
diff --git a/src/test/ui/suggestions/borrow-for-loop-head.nll.stderr b/src/test/ui/suggestions/borrow-for-loop-head.nll.stderr
new file mode 100644
index 0000000..96dbdec
--- /dev/null
+++ b/src/test/ui/suggestions/borrow-for-loop-head.nll.stderr
@@ -0,0 +1,25 @@
+error[E0505]: cannot move out of `a` because it is borrowed
+  --> $DIR/borrow-for-loop-head.rs:4:18
+   |
+LL |     for i in &a {
+   |              -- borrow of `a` occurs here
+LL |         for j in a {
+   |                  ^ move out of `a` occurs here
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrow-for-loop-head.rs:4:18
+   |
+LL |     let a = vec![1, 2, 3];
+   |         - move occurs because `a` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
+LL |     for i in &a {
+LL |         for j in a {
+   |                  ^ value moved here, in previous iteration of loop
+help: consider borrowing this to avoid moving it into the for loop
+   |
+LL |         for j in &a {
+   |                  ^^
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0382, E0505.
+For more information about an error, try `rustc --explain E0382`.
diff --git a/src/test/ui/suggestions/borrow-for-loop-head.rs b/src/test/ui/suggestions/borrow-for-loop-head.rs
new file mode 100644
index 0000000..c2bda55
--- /dev/null
+++ b/src/test/ui/suggestions/borrow-for-loop-head.rs
@@ -0,0 +1,10 @@
+fn main() {
+    let a = vec![1, 2, 3];
+    for i in &a {
+        for j in a {
+        //~^ ERROR cannot move out of `a` because it is borrowed
+        //~| ERROR use of moved value: `a`
+            println!("{} * {} = {}", i, j, i * j);
+        }
+    }
+}
diff --git a/src/test/ui/suggestions/borrow-for-loop-head.stderr b/src/test/ui/suggestions/borrow-for-loop-head.stderr
new file mode 100644
index 0000000..17ac3fe
--- /dev/null
+++ b/src/test/ui/suggestions/borrow-for-loop-head.stderr
@@ -0,0 +1,24 @@
+error[E0505]: cannot move out of `a` because it is borrowed
+  --> $DIR/borrow-for-loop-head.rs:4:18
+   |
+LL |     for i in &a {
+   |               - borrow of `a` occurs here
+LL |         for j in a {
+   |                  ^ move out of `a` occurs here
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrow-for-loop-head.rs:4:18
+   |
+LL |         for j in a {
+   |                  ^ value moved here in previous iteration of loop
+   |
+   = note: move occurs because `a` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
+help: consider borrowing this to avoid moving it into the for loop
+   |
+LL |         for j in &a {
+   |                  ^^
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0382, E0505.
+For more information about an error, try `rustc --explain E0382`.
diff --git a/src/test/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.rs b/src/test/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.rs
new file mode 100644
index 0000000..ef1c09d2
--- /dev/null
+++ b/src/test/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.rs
@@ -0,0 +1,14 @@
+fn warn(_: &str) {}
+
+macro_rules! intrinsic_match {
+    ($intrinsic:expr) => {
+        warn(format!("unsupported intrinsic {}", $intrinsic));
+        //~^ ERROR mismatched types
+    };
+}
+
+fn main() {
+    intrinsic_match! {
+        "abc"
+    };
+}
diff --git a/src/test/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.stderr b/src/test/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.stderr
new file mode 100644
index 0000000..bc7a724
--- /dev/null
+++ b/src/test/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.stderr
@@ -0,0 +1,18 @@
+error[E0308]: mismatched types
+  --> $DIR/dont-suggest-deref-inside-macro-issue-58298.rs:11:5
+   |
+LL | /     intrinsic_match! {
+LL | |         "abc"
+LL | |     };
+   | |      ^
+   | |      |
+   | |______expected &str, found struct `std::string::String`
+   |        in this macro invocation
+   |
+   = note: expected type `&str`
+              found type `std::string::String`
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/suggestions/dont-suggest-ref/duplicate-suggestions.rs b/src/test/ui/suggestions/dont-suggest-ref/duplicate-suggestions.rs
new file mode 100644
index 0000000..4faede3
--- /dev/null
+++ b/src/test/ui/suggestions/dont-suggest-ref/duplicate-suggestions.rs
@@ -0,0 +1,152 @@
+#![feature(nll)]
+
+#[derive(Clone)]
+enum Either {
+    One(X),
+    Two(X),
+}
+
+#[derive(Clone)]
+struct X(Y);
+
+#[derive(Clone)]
+struct Y;
+
+
+pub fn main() {
+    let e = Either::One(X(Y));
+    let mut em = Either::One(X(Y));
+
+    let r = &e;
+    let rm = &mut Either::One(X(Y));
+
+    let x = X(Y);
+    let mut xm = X(Y);
+
+    let s = &x;
+    let sm = &mut X(Y);
+
+    let ve = vec![Either::One(X(Y))];
+
+    let vr = &ve;
+    let vrm = &mut vec![Either::One(X(Y))];
+
+    let vx = vec![X(Y)];
+
+    let vs = &vx;
+    let vsm = &mut vec![X(Y)];
+
+    // -------- test for duplicate suggestions --------
+
+    let &(X(_t), X(_u)) = &(x.clone(), x.clone());
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&`
+    //~| SUGGESTION (X(_t), X(_u))
+    if let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&`
+    //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+    while let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&`
+    //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+    match &(e.clone(), e.clone()) {
+        //~^ ERROR cannot move
+        &(Either::One(_t), Either::Two(_u)) => (),
+        //~^ HELP consider removing the `&`
+        //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+        &(Either::Two(_t), Either::One(_u)) => (),
+        //~^ HELP consider removing the `&`
+        //~| SUGGESTION (Either::Two(_t), Either::One(_u))
+        _ => (),
+    }
+    match &(e.clone(), e.clone()) {
+        //~^ ERROR cannot move
+        &(Either::One(_t), Either::Two(_u))
+        //~^ HELP consider removing the `&`
+        //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+        | &(Either::Two(_t), Either::One(_u)) => (),
+        // FIXME: would really like a suggestion here too
+        _ => (),
+    }
+    match &(e.clone(), e.clone()) {
+        //~^ ERROR cannot move
+        &(Either::One(_t), Either::Two(_u)) => (),
+        //~^ HELP consider removing the `&`
+        //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+        &(Either::Two(ref _t), Either::One(ref _u)) => (),
+        _ => (),
+    }
+    match &(e.clone(), e.clone()) {
+        //~^ ERROR cannot move
+        &(Either::One(_t), Either::Two(_u)) => (),
+        //~^ HELP consider removing the `&`
+        //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+        (Either::Two(_t), Either::One(_u)) => (),
+        _ => (),
+    }
+    fn f5(&(X(_t), X(_u)): &(X, X)) { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&`
+    //~| SUGGESTION (X(_t), X(_u))
+
+    let &mut (X(_t), X(_u)) = &mut (xm.clone(), xm.clone());
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&mut`
+    //~| SUGGESTION (X(_t), X(_u))
+    if let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&mut`
+    //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+    while let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&mut`
+    //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+    match &mut (em.clone(), em.clone()) {
+        //~^ ERROR cannot move
+        &mut (Either::One(_t), Either::Two(_u)) => (),
+        //~^ HELP consider removing the `&mut`
+        //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+        &mut (Either::Two(_t), Either::One(_u)) => (),
+        //~^ HELP consider removing the `&mut`
+        //~| SUGGESTION (Either::Two(_t), Either::One(_u))
+        _ => (),
+    }
+    match &mut (em.clone(), em.clone()) {
+        //~^ ERROR cannot move
+        &mut (Either::One(_t), Either::Two(_u))
+        //~^ HELP consider removing the `&mut`
+        //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+        | &mut (Either::Two(_t), Either::One(_u)) => (),
+        // FIXME: would really like a suggestion here too
+        _ => (),
+    }
+    match &mut (em.clone(), em.clone()) {
+        //~^ ERROR cannot move
+        &mut (Either::One(_t), Either::Two(_u)) => (),
+        //~^ HELP consider removing the `&mut`
+        //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+        &mut (Either::Two(ref _t), Either::One(ref _u)) => (),
+        _ => (),
+    }
+    match &mut (em.clone(), em.clone()) {
+        //~^ ERROR cannot move
+        &mut (Either::One(_t), Either::Two(_u)) => (),
+        //~^ HELP consider removing the `&mut`
+        //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+        &mut (Either::Two(ref mut _t), Either::One(ref mut _u)) => (),
+        _ => (),
+    }
+    match &mut (em.clone(), em.clone()) {
+        //~^ ERROR cannot move
+        &mut (Either::One(_t), Either::Two(_u)) => (),
+        //~^ HELP consider removing the `&mut`
+        //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+        (Either::Two(_t), Either::One(_u)) => (),
+        _ => (),
+    }
+    fn f6(&mut (X(_t), X(_u)): &mut (X, X)) { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&mut`
+    //~| SUGGESTION (X(_t), X(_u))
+}
diff --git a/src/test/ui/suggestions/dont-suggest-ref/duplicate-suggestions.stderr b/src/test/ui/suggestions/dont-suggest-ref/duplicate-suggestions.stderr
new file mode 100644
index 0000000..b1aaab6
--- /dev/null
+++ b/src/test/ui/suggestions/dont-suggest-ref/duplicate-suggestions.stderr
@@ -0,0 +1,328 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/duplicate-suggestions.rs:41:27
+   |
+LL |     let &(X(_t), X(_u)) = &(x.clone(), x.clone());
+   |         ---------------   ^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+   |         |   |      |
+   |         |   |      ...and here
+   |         |   data moved here
+   |         help: consider removing the `&`: `(X(_t), X(_u))`
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/duplicate-suggestions.rs:41:13
+   |
+LL |     let &(X(_t), X(_u)) = &(x.clone(), x.clone());
+   |             ^^     ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/duplicate-suggestions.rs:45:50
+   |
+LL |     if let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
+   |            -----------------------------------   ^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+   |            |             |                |
+   |            |             |                ...and here
+   |            |             data moved here
+   |            help: consider removing the `&`: `(Either::One(_t), Either::Two(_u))`
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/duplicate-suggestions.rs:45:26
+   |
+LL |     if let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
+   |                          ^^               ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/duplicate-suggestions.rs:49:53
+   |
+LL |     while let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
+   |               -----------------------------------   ^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+   |               |             |                |
+   |               |             |                ...and here
+   |               |             data moved here
+   |               help: consider removing the `&`: `(Either::One(_t), Either::Two(_u))`
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/duplicate-suggestions.rs:49:29
+   |
+LL |     while let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
+   |                             ^^               ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/duplicate-suggestions.rs:53:11
+   |
+LL |     match &(e.clone(), e.clone()) {
+   |           ^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+LL |
+LL |         &(Either::One(_t), Either::Two(_u)) => (),
+   |                       --               -- ...and here
+   |                       |
+   |                       data moved here
+...
+LL |         &(Either::Two(_t), Either::One(_u)) => (),
+   |                       -- ...and here   -- ...and here
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/duplicate-suggestions.rs:55:23
+   |
+LL |         &(Either::One(_t), Either::Two(_u)) => (),
+   |                       ^^               ^^
+...
+LL |         &(Either::Two(_t), Either::One(_u)) => (),
+   |                       ^^               ^^
+help: consider removing the `&`
+   |
+LL |         (Either::One(_t), Either::Two(_u)) => (),
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: consider removing the `&`
+   |
+LL |         (Either::Two(_t), Either::One(_u)) => (),
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/duplicate-suggestions.rs:63:11
+   |
+LL |     match &(e.clone(), e.clone()) {
+   |           ^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+LL |
+LL |         &(Either::One(_t), Either::Two(_u))
+   |         -----------------------------------
+   |         |             |                |
+   |         |             |                ...and here
+   |         |             data moved here
+   |         help: consider removing the `&`: `(Either::One(_t), Either::Two(_u))`
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/duplicate-suggestions.rs:65:23
+   |
+LL |         &(Either::One(_t), Either::Two(_u))
+   |                       ^^               ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/duplicate-suggestions.rs:72:11
+   |
+LL |     match &(e.clone(), e.clone()) {
+   |           ^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+LL |
+LL |         &(Either::One(_t), Either::Two(_u)) => (),
+   |         -----------------------------------
+   |         |             |                |
+   |         |             |                ...and here
+   |         |             data moved here
+   |         help: consider removing the `&`: `(Either::One(_t), Either::Two(_u))`
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/duplicate-suggestions.rs:74:23
+   |
+LL |         &(Either::One(_t), Either::Two(_u)) => (),
+   |                       ^^               ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/duplicate-suggestions.rs:80:11
+   |
+LL |     match &(e.clone(), e.clone()) {
+   |           ^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+LL |
+LL |         &(Either::One(_t), Either::Two(_u)) => (),
+   |         -----------------------------------
+   |         |             |                |
+   |         |             |                ...and here
+   |         |             data moved here
+   |         help: consider removing the `&`: `(Either::One(_t), Either::Two(_u))`
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/duplicate-suggestions.rs:82:23
+   |
+LL |         &(Either::One(_t), Either::Two(_u)) => (),
+   |                       ^^               ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/duplicate-suggestions.rs:93:31
+   |
+LL |     let &mut (X(_t), X(_u)) = &mut (xm.clone(), xm.clone());
+   |         -------------------   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+   |         |       |      |
+   |         |       |      ...and here
+   |         |       data moved here
+   |         help: consider removing the `&mut`: `(X(_t), X(_u))`
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/duplicate-suggestions.rs:93:17
+   |
+LL |     let &mut (X(_t), X(_u)) = &mut (xm.clone(), xm.clone());
+   |                 ^^     ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/duplicate-suggestions.rs:97:54
+   |
+LL |     if let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
+   |            ---------------------------------------   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+   |            |                 |                |
+   |            |                 |                ...and here
+   |            |                 data moved here
+   |            help: consider removing the `&mut`: `(Either::One(_t), Either::Two(_u))`
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/duplicate-suggestions.rs:97:30
+   |
+LL |     if let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
+   |                              ^^               ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/duplicate-suggestions.rs:101:57
+   |
+LL |     while let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
+   |               ---------------------------------------   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+   |               |                 |                |
+   |               |                 |                ...and here
+   |               |                 data moved here
+   |               help: consider removing the `&mut`: `(Either::One(_t), Either::Two(_u))`
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/duplicate-suggestions.rs:101:33
+   |
+LL |     while let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
+   |                                 ^^               ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/duplicate-suggestions.rs:105:11
+   |
+LL |     match &mut (em.clone(), em.clone()) {
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+LL |
+LL |         &mut (Either::One(_t), Either::Two(_u)) => (),
+   |                           --               -- ...and here
+   |                           |
+   |                           data moved here
+...
+LL |         &mut (Either::Two(_t), Either::One(_u)) => (),
+   |                           -- ...and here   -- ...and here
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/duplicate-suggestions.rs:107:27
+   |
+LL |         &mut (Either::One(_t), Either::Two(_u)) => (),
+   |                           ^^               ^^
+...
+LL |         &mut (Either::Two(_t), Either::One(_u)) => (),
+   |                           ^^               ^^
+help: consider removing the `&mut`
+   |
+LL |         (Either::One(_t), Either::Two(_u)) => (),
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: consider removing the `&mut`
+   |
+LL |         (Either::Two(_t), Either::One(_u)) => (),
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/duplicate-suggestions.rs:115:11
+   |
+LL |     match &mut (em.clone(), em.clone()) {
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+LL |
+LL |         &mut (Either::One(_t), Either::Two(_u))
+   |         ---------------------------------------
+   |         |                 |                |
+   |         |                 |                ...and here
+   |         |                 data moved here
+   |         help: consider removing the `&mut`: `(Either::One(_t), Either::Two(_u))`
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/duplicate-suggestions.rs:117:27
+   |
+LL |         &mut (Either::One(_t), Either::Two(_u))
+   |                           ^^               ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/duplicate-suggestions.rs:124:11
+   |
+LL |     match &mut (em.clone(), em.clone()) {
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+LL |
+LL |         &mut (Either::One(_t), Either::Two(_u)) => (),
+   |         ---------------------------------------
+   |         |                 |                |
+   |         |                 |                ...and here
+   |         |                 data moved here
+   |         help: consider removing the `&mut`: `(Either::One(_t), Either::Two(_u))`
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/duplicate-suggestions.rs:126:27
+   |
+LL |         &mut (Either::One(_t), Either::Two(_u)) => (),
+   |                           ^^               ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/duplicate-suggestions.rs:132:11
+   |
+LL |     match &mut (em.clone(), em.clone()) {
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+LL |
+LL |         &mut (Either::One(_t), Either::Two(_u)) => (),
+   |         ---------------------------------------
+   |         |                 |                |
+   |         |                 |                ...and here
+   |         |                 data moved here
+   |         help: consider removing the `&mut`: `(Either::One(_t), Either::Two(_u))`
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/duplicate-suggestions.rs:134:27
+   |
+LL |         &mut (Either::One(_t), Either::Two(_u)) => (),
+   |                           ^^               ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/duplicate-suggestions.rs:140:11
+   |
+LL |     match &mut (em.clone(), em.clone()) {
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+LL |
+LL |         &mut (Either::One(_t), Either::Two(_u)) => (),
+   |         ---------------------------------------
+   |         |                 |                |
+   |         |                 |                ...and here
+   |         |                 data moved here
+   |         help: consider removing the `&mut`: `(Either::One(_t), Either::Two(_u))`
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/duplicate-suggestions.rs:142:27
+   |
+LL |         &mut (Either::One(_t), Either::Two(_u)) => (),
+   |                           ^^               ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/duplicate-suggestions.rs:88:11
+   |
+LL |     fn f5(&(X(_t), X(_u)): &(X, X)) { }
+   |           ^^^^--^^^^^--^^
+   |           |   |      |
+   |           |   |      ...and here
+   |           |   data moved here
+   |           cannot move out of borrowed content
+   |           help: consider removing the `&`: `(X(_t), X(_u))`
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/duplicate-suggestions.rs:88:15
+   |
+LL |     fn f5(&(X(_t), X(_u)): &(X, X)) { }
+   |               ^^     ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/duplicate-suggestions.rs:148:11
+   |
+LL |     fn f6(&mut (X(_t), X(_u)): &mut (X, X)) { }
+   |           ^^^^^^^^--^^^^^--^^
+   |           |       |      |
+   |           |       |      ...and here
+   |           |       data moved here
+   |           cannot move out of borrowed content
+   |           help: consider removing the `&mut`: `(X(_t), X(_u))`
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/duplicate-suggestions.rs:148:19
+   |
+LL |     fn f6(&mut (X(_t), X(_u)): &mut (X, X)) { }
+   |                   ^^     ^^
+
+error: aborting due to 17 previous errors
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/suggestions/dont-suggest-ref/move-into-closure.rs b/src/test/ui/suggestions/dont-suggest-ref/move-into-closure.rs
new file mode 100644
index 0000000..90a9fe4
--- /dev/null
+++ b/src/test/ui/suggestions/dont-suggest-ref/move-into-closure.rs
@@ -0,0 +1,161 @@
+#![feature(nll)]
+
+#[derive(Clone)]
+enum Either {
+    One(X),
+    Two(X),
+}
+
+#[derive(Clone)]
+struct X(Y);
+
+#[derive(Clone)]
+struct Y;
+
+fn consume_fn<F: Fn()>(_f: F) { }
+
+fn consume_fnmut<F: FnMut()>(_f: F) { }
+
+pub fn main() { }
+
+fn move_into_fn() {
+    let e = Either::One(X(Y));
+    let mut em = Either::One(X(Y));
+
+    let x = X(Y);
+
+    // -------- move into Fn --------
+
+    consume_fn(|| {
+        let X(_t) = x;
+        //~^ ERROR cannot move
+        //~| HELP consider borrowing here
+        //~| SUGGESTION &x
+        if let Either::One(_t) = e { }
+        //~^ ERROR cannot move
+        //~| HELP consider borrowing here
+        //~| SUGGESTION &e
+        while let Either::One(_t) = e { }
+        //~^ ERROR cannot move
+        //~| HELP consider borrowing here
+        //~| SUGGESTION &e
+        match e {
+            //~^ ERROR cannot move
+            //~| HELP consider borrowing here
+            //~| SUGGESTION &e
+            Either::One(_t)
+            | Either::Two(_t) => (),
+        }
+        match e {
+            //~^ ERROR cannot move
+            //~| HELP consider borrowing here
+            //~| SUGGESTION &e
+            Either::One(_t) => (),
+            Either::Two(ref _t) => (),
+            // FIXME: should suggest removing `ref` too
+        }
+
+        let X(mut _t) = x;
+        //~^ ERROR cannot move
+        //~| HELP consider borrowing here
+        //~| SUGGESTION &x
+        if let Either::One(mut _t) = em { }
+        //~^ ERROR cannot move
+        //~| HELP consider borrowing here
+        //~| SUGGESTION &em
+        while let Either::One(mut _t) = em { }
+        //~^ ERROR cannot move
+        //~| HELP consider borrowing here
+        //~| SUGGESTION &em
+        match em {
+            //~^ ERROR cannot move
+            //~| HELP consider borrowing here
+            //~| SUGGESTION &em
+            Either::One(mut _t)
+            | Either::Two(mut _t) => (),
+        }
+        match em {
+            //~^ ERROR cannot move
+            //~| HELP consider borrowing here
+            //~| SUGGESTION &em
+            Either::One(mut _t) => (),
+            Either::Two(ref _t) => (),
+            // FIXME: should suggest removing `ref` too
+        }
+    });
+}
+
+fn move_into_fnmut() {
+    let e = Either::One(X(Y));
+    let mut em = Either::One(X(Y));
+
+    let x = X(Y);
+
+    // -------- move into FnMut --------
+
+    consume_fnmut(|| {
+        let X(_t) = x;
+        //~^ ERROR cannot move
+        //~| HELP consider borrowing here
+        //~| SUGGESTION &x
+        if let Either::One(_t) = e { }
+        //~^ ERROR cannot move
+        //~| HELP consider borrowing here
+        //~| SUGGESTION &e
+        while let Either::One(_t) = e { }
+        //~^ ERROR cannot move
+        //~| HELP consider borrowing here
+        //~| SUGGESTION &e
+        match e {
+            //~^ ERROR cannot move
+            //~| HELP consider borrowing here
+            //~| SUGGESTION &e
+            Either::One(_t)
+            | Either::Two(_t) => (),
+        }
+        match e {
+            //~^ ERROR cannot move
+            //~| HELP consider borrowing here
+            //~| SUGGESTION &e
+            Either::One(_t) => (),
+            Either::Two(ref _t) => (),
+            // FIXME: should suggest removing `ref` too
+        }
+
+        let X(mut _t) = x;
+        //~^ ERROR cannot move
+        //~| HELP consider borrowing here
+        //~| SUGGESTION &x
+        if let Either::One(mut _t) = em { }
+        //~^ ERROR cannot move
+        //~| HELP consider borrowing here
+        //~| SUGGESTION &em
+        while let Either::One(mut _t) = em { }
+        //~^ ERROR cannot move
+        //~| HELP consider borrowing here
+        //~| SUGGESTION &em
+        match em {
+            //~^ ERROR cannot move
+            //~| HELP consider borrowing here
+            //~| SUGGESTION &em
+            Either::One(mut _t)
+            | Either::Two(mut _t) => (),
+        }
+        match em {
+            //~^ ERROR cannot move
+            //~| HELP consider borrowing here
+            //~| SUGGESTION &em
+            Either::One(mut _t) => (),
+            Either::Two(ref _t) => (),
+            // FIXME: should suggest removing `ref` too
+        }
+        match em {
+            //~^ ERROR cannot move
+            //~| HELP consider borrowing here
+            //~| SUGGESTION &em
+            Either::One(mut _t) => (),
+            Either::Two(ref mut _t) => (),
+            // FIXME: should suggest removing `ref` too
+        }
+    });
+}
diff --git a/src/test/ui/suggestions/dont-suggest-ref/move-into-closure.stderr b/src/test/ui/suggestions/dont-suggest-ref/move-into-closure.stderr
new file mode 100644
index 0000000..f1d515e
--- /dev/null
+++ b/src/test/ui/suggestions/dont-suggest-ref/move-into-closure.stderr
@@ -0,0 +1,420 @@
+error[E0507]: cannot move out of captured variable in an `Fn` closure
+  --> $DIR/move-into-closure.rs:30:21
+   |
+LL |     let x = X(Y);
+   |         - captured outer variable
+...
+LL |         let X(_t) = x;
+   |               --    ^
+   |               |     |
+   |               |     cannot move out of captured variable in an `Fn` closure
+   |               |     help: consider borrowing here: `&x`
+   |               data moved here
+   |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:30:15
+   |
+LL |         let X(_t) = x;
+   |               ^^
+
+error[E0507]: cannot move out of captured variable in an `Fn` closure
+  --> $DIR/move-into-closure.rs:34:34
+   |
+LL |     let e = Either::One(X(Y));
+   |         - captured outer variable
+...
+LL |         if let Either::One(_t) = e { }
+   |                            --    ^
+   |                            |     |
+   |                            |     cannot move out of captured variable in an `Fn` closure
+   |                            |     help: consider borrowing here: `&e`
+   |                            data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:34:28
+   |
+LL |         if let Either::One(_t) = e { }
+   |                            ^^
+
+error[E0507]: cannot move out of captured variable in an `Fn` closure
+  --> $DIR/move-into-closure.rs:38:37
+   |
+LL |     let e = Either::One(X(Y));
+   |         - captured outer variable
+...
+LL |         while let Either::One(_t) = e { }
+   |                               --    ^
+   |                               |     |
+   |                               |     cannot move out of captured variable in an `Fn` closure
+   |                               |     help: consider borrowing here: `&e`
+   |                               data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:38:31
+   |
+LL |         while let Either::One(_t) = e { }
+   |                               ^^
+
+error[E0507]: cannot move out of captured variable in an `Fn` closure
+  --> $DIR/move-into-closure.rs:42:15
+   |
+LL |     let e = Either::One(X(Y));
+   |         - captured outer variable
+...
+LL |         match e {
+   |               ^
+   |               |
+   |               cannot move out of captured variable in an `Fn` closure
+   |               help: consider borrowing here: `&e`
+...
+LL |             Either::One(_t)
+   |                         -- data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:46:25
+   |
+LL |             Either::One(_t)
+   |                         ^^
+
+error[E0507]: cannot move out of captured variable in an `Fn` closure
+  --> $DIR/move-into-closure.rs:49:15
+   |
+LL |     let e = Either::One(X(Y));
+   |         - captured outer variable
+...
+LL |         match e {
+   |               ^
+   |               |
+   |               cannot move out of captured variable in an `Fn` closure
+   |               help: consider borrowing here: `&e`
+...
+LL |             Either::One(_t) => (),
+   |                         -- data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:53:25
+   |
+LL |             Either::One(_t) => (),
+   |                         ^^
+
+error[E0507]: cannot move out of captured variable in an `Fn` closure
+  --> $DIR/move-into-closure.rs:58:25
+   |
+LL |     let x = X(Y);
+   |         - captured outer variable
+...
+LL |         let X(mut _t) = x;
+   |               ------    ^
+   |               |         |
+   |               |         cannot move out of captured variable in an `Fn` closure
+   |               |         help: consider borrowing here: `&x`
+   |               data moved here
+   |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:58:15
+   |
+LL |         let X(mut _t) = x;
+   |               ^^^^^^
+
+error[E0507]: cannot move out of captured variable in an `Fn` closure
+  --> $DIR/move-into-closure.rs:62:38
+   |
+LL |     let mut em = Either::One(X(Y));
+   |         ------ captured outer variable
+...
+LL |         if let Either::One(mut _t) = em { }
+   |                            ------    ^^
+   |                            |         |
+   |                            |         cannot move out of captured variable in an `Fn` closure
+   |                            |         help: consider borrowing here: `&em`
+   |                            data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:62:28
+   |
+LL |         if let Either::One(mut _t) = em { }
+   |                            ^^^^^^
+
+error[E0507]: cannot move out of captured variable in an `Fn` closure
+  --> $DIR/move-into-closure.rs:66:41
+   |
+LL |     let mut em = Either::One(X(Y));
+   |         ------ captured outer variable
+...
+LL |         while let Either::One(mut _t) = em { }
+   |                               ------    ^^
+   |                               |         |
+   |                               |         cannot move out of captured variable in an `Fn` closure
+   |                               |         help: consider borrowing here: `&em`
+   |                               data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:66:31
+   |
+LL |         while let Either::One(mut _t) = em { }
+   |                               ^^^^^^
+
+error[E0507]: cannot move out of captured variable in an `Fn` closure
+  --> $DIR/move-into-closure.rs:70:15
+   |
+LL |     let mut em = Either::One(X(Y));
+   |         ------ captured outer variable
+...
+LL |         match em {
+   |               ^^
+   |               |
+   |               cannot move out of captured variable in an `Fn` closure
+   |               help: consider borrowing here: `&em`
+...
+LL |             Either::One(mut _t)
+   |                         ------ data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:74:25
+   |
+LL |             Either::One(mut _t)
+   |                         ^^^^^^
+
+error[E0507]: cannot move out of captured variable in an `Fn` closure
+  --> $DIR/move-into-closure.rs:77:15
+   |
+LL |     let mut em = Either::One(X(Y));
+   |         ------ captured outer variable
+...
+LL |         match em {
+   |               ^^
+   |               |
+   |               cannot move out of captured variable in an `Fn` closure
+   |               help: consider borrowing here: `&em`
+...
+LL |             Either::One(mut _t) => (),
+   |                         ------ data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:81:25
+   |
+LL |             Either::One(mut _t) => (),
+   |                         ^^^^^^
+
+error[E0507]: cannot move out of captured variable in an `FnMut` closure
+  --> $DIR/move-into-closure.rs:97:21
+   |
+LL |     let x = X(Y);
+   |         - captured outer variable
+...
+LL |         let X(_t) = x;
+   |               --    ^
+   |               |     |
+   |               |     cannot move out of captured variable in an `FnMut` closure
+   |               |     help: consider borrowing here: `&x`
+   |               data moved here
+   |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:97:15
+   |
+LL |         let X(_t) = x;
+   |               ^^
+
+error[E0507]: cannot move out of captured variable in an `FnMut` closure
+  --> $DIR/move-into-closure.rs:101:34
+   |
+LL |     let e = Either::One(X(Y));
+   |         - captured outer variable
+...
+LL |         if let Either::One(_t) = e { }
+   |                            --    ^
+   |                            |     |
+   |                            |     cannot move out of captured variable in an `FnMut` closure
+   |                            |     help: consider borrowing here: `&e`
+   |                            data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:101:28
+   |
+LL |         if let Either::One(_t) = e { }
+   |                            ^^
+
+error[E0507]: cannot move out of captured variable in an `FnMut` closure
+  --> $DIR/move-into-closure.rs:105:37
+   |
+LL |     let e = Either::One(X(Y));
+   |         - captured outer variable
+...
+LL |         while let Either::One(_t) = e { }
+   |                               --    ^
+   |                               |     |
+   |                               |     cannot move out of captured variable in an `FnMut` closure
+   |                               |     help: consider borrowing here: `&e`
+   |                               data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:105:31
+   |
+LL |         while let Either::One(_t) = e { }
+   |                               ^^
+
+error[E0507]: cannot move out of captured variable in an `FnMut` closure
+  --> $DIR/move-into-closure.rs:109:15
+   |
+LL |     let e = Either::One(X(Y));
+   |         - captured outer variable
+...
+LL |         match e {
+   |               ^
+   |               |
+   |               cannot move out of captured variable in an `FnMut` closure
+   |               help: consider borrowing here: `&e`
+...
+LL |             Either::One(_t)
+   |                         -- data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:113:25
+   |
+LL |             Either::One(_t)
+   |                         ^^
+
+error[E0507]: cannot move out of captured variable in an `FnMut` closure
+  --> $DIR/move-into-closure.rs:116:15
+   |
+LL |     let e = Either::One(X(Y));
+   |         - captured outer variable
+...
+LL |         match e {
+   |               ^
+   |               |
+   |               cannot move out of captured variable in an `FnMut` closure
+   |               help: consider borrowing here: `&e`
+...
+LL |             Either::One(_t) => (),
+   |                         -- data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:120:25
+   |
+LL |             Either::One(_t) => (),
+   |                         ^^
+
+error[E0507]: cannot move out of captured variable in an `FnMut` closure
+  --> $DIR/move-into-closure.rs:125:25
+   |
+LL |     let x = X(Y);
+   |         - captured outer variable
+...
+LL |         let X(mut _t) = x;
+   |               ------    ^
+   |               |         |
+   |               |         cannot move out of captured variable in an `FnMut` closure
+   |               |         help: consider borrowing here: `&x`
+   |               data moved here
+   |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:125:15
+   |
+LL |         let X(mut _t) = x;
+   |               ^^^^^^
+
+error[E0507]: cannot move out of captured variable in an `FnMut` closure
+  --> $DIR/move-into-closure.rs:129:38
+   |
+LL |     let mut em = Either::One(X(Y));
+   |         ------ captured outer variable
+...
+LL |         if let Either::One(mut _t) = em { }
+   |                            ------    ^^
+   |                            |         |
+   |                            |         cannot move out of captured variable in an `FnMut` closure
+   |                            |         help: consider borrowing here: `&em`
+   |                            data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:129:28
+   |
+LL |         if let Either::One(mut _t) = em { }
+   |                            ^^^^^^
+
+error[E0507]: cannot move out of captured variable in an `FnMut` closure
+  --> $DIR/move-into-closure.rs:133:41
+   |
+LL |     let mut em = Either::One(X(Y));
+   |         ------ captured outer variable
+...
+LL |         while let Either::One(mut _t) = em { }
+   |                               ------    ^^
+   |                               |         |
+   |                               |         cannot move out of captured variable in an `FnMut` closure
+   |                               |         help: consider borrowing here: `&em`
+   |                               data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:133:31
+   |
+LL |         while let Either::One(mut _t) = em { }
+   |                               ^^^^^^
+
+error[E0507]: cannot move out of captured variable in an `FnMut` closure
+  --> $DIR/move-into-closure.rs:137:15
+   |
+LL |     let mut em = Either::One(X(Y));
+   |         ------ captured outer variable
+...
+LL |         match em {
+   |               ^^
+   |               |
+   |               cannot move out of captured variable in an `FnMut` closure
+   |               help: consider borrowing here: `&em`
+...
+LL |             Either::One(mut _t)
+   |                         ------ data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:141:25
+   |
+LL |             Either::One(mut _t)
+   |                         ^^^^^^
+
+error[E0507]: cannot move out of captured variable in an `FnMut` closure
+  --> $DIR/move-into-closure.rs:144:15
+   |
+LL |     let mut em = Either::One(X(Y));
+   |         ------ captured outer variable
+...
+LL |         match em {
+   |               ^^
+   |               |
+   |               cannot move out of captured variable in an `FnMut` closure
+   |               help: consider borrowing here: `&em`
+...
+LL |             Either::One(mut _t) => (),
+   |                         ------ data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:148:25
+   |
+LL |             Either::One(mut _t) => (),
+   |                         ^^^^^^
+
+error[E0507]: cannot move out of captured variable in an `FnMut` closure
+  --> $DIR/move-into-closure.rs:152:15
+   |
+LL |     let mut em = Either::One(X(Y));
+   |         ------ captured outer variable
+...
+LL |         match em {
+   |               ^^
+   |               |
+   |               cannot move out of captured variable in an `FnMut` closure
+   |               help: consider borrowing here: `&em`
+...
+LL |             Either::One(mut _t) => (),
+   |                         ------ data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:156:25
+   |
+LL |             Either::One(mut _t) => (),
+   |                         ^^^^^^
+
+error: aborting due to 21 previous errors
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/suggestions/dont-suggest-ref/simple.rs b/src/test/ui/suggestions/dont-suggest-ref/simple.rs
new file mode 100644
index 0000000..58aab85
--- /dev/null
+++ b/src/test/ui/suggestions/dont-suggest-ref/simple.rs
@@ -0,0 +1,366 @@
+#![feature(nll)]
+
+#[derive(Clone)]
+enum Either {
+    One(X),
+    Two(X),
+}
+
+#[derive(Clone)]
+struct X(Y);
+
+#[derive(Clone)]
+struct Y;
+
+pub fn main() {
+    let e = Either::One(X(Y));
+    let mut em = Either::One(X(Y));
+
+    let r = &e;
+    let rm = &mut Either::One(X(Y));
+
+    let x = X(Y);
+    let mut xm = X(Y);
+
+    let s = &x;
+    let sm = &mut X(Y);
+
+    let ve = vec![Either::One(X(Y))];
+
+    let vr = &ve;
+    let vrm = &mut vec![Either::One(X(Y))];
+
+    let vx = vec![X(Y)];
+
+    let vs = &vx;
+    let vsm = &mut vec![X(Y)];
+
+    // -------- move from Either/X place --------
+
+    let X(_t) = *s;
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `*`
+    //~| SUGGESTION s
+    if let Either::One(_t) = *r { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `*`
+    //~| SUGGESTION r
+    while let Either::One(_t) = *r { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `*`
+    //~| SUGGESTION r
+    match *r {
+        //~^ ERROR cannot move
+        //~| HELP consider removing the `*`
+        //~| SUGGESTION r
+        Either::One(_t)
+        | Either::Two(_t) => (),
+    }
+    match *r {
+        //~^ ERROR cannot move
+        //~| HELP consider removing the `*`
+        //~| SUGGESTION r
+        Either::One(_t) => (),
+        Either::Two(ref _t) => (),
+        // FIXME: should suggest removing `ref` too
+    }
+
+    let X(_t) = *sm;
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `*`
+    //~| SUGGESTION sm
+    if let Either::One(_t) = *rm { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `*`
+    //~| SUGGESTION rm
+    while let Either::One(_t) = *rm { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `*`
+    //~| SUGGESTION rm
+    match *rm {
+        //~^ ERROR cannot move
+        //~| HELP consider removing the `*`
+        //~| SUGGESTION rm
+        Either::One(_t)
+        | Either::Two(_t) => (),
+    }
+    match *rm {
+        //~^ ERROR cannot move
+        //~| HELP consider removing the `*`
+        //~| SUGGESTION rm
+        Either::One(_t) => (),
+        Either::Two(ref _t) => (),
+        // FIXME: should suggest removing `ref` too
+    }
+    match *rm {
+        //~^ ERROR cannot move
+        //~| HELP consider removing the `*`
+        //~| SUGGESTION rm
+        Either::One(_t) => (),
+        Either::Two(ref mut _t) => (),
+        // FIXME: should suggest removing `ref` too
+    }
+
+    let X(_t) = vs[0];
+    //~^ ERROR cannot move
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &vs[0]
+    if let Either::One(_t) = vr[0] { }
+    //~^ ERROR cannot move
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &vr[0]
+    while let Either::One(_t) = vr[0] { }
+    //~^ ERROR cannot move
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &vr[0]
+    match vr[0] {
+        //~^ ERROR cannot move
+        //~| HELP consider borrowing here
+        //~| SUGGESTION &vr[0]
+        Either::One(_t)
+        | Either::Two(_t) => (),
+    }
+    match vr[0] {
+        //~^ ERROR cannot move
+        //~| HELP consider borrowing here
+        //~| SUGGESTION &vr[0]
+        Either::One(_t) => (),
+        Either::Two(ref _t) => (),
+        // FIXME: should suggest removing `ref` too
+    }
+
+    let X(_t) = vsm[0];
+    //~^ ERROR cannot move
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &vsm[0]
+    if let Either::One(_t) = vrm[0] { }
+    //~^ ERROR cannot move
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &vrm[0]
+    while let Either::One(_t) = vrm[0] { }
+    //~^ ERROR cannot move
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &vrm[0]
+    match vrm[0] {
+        //~^ ERROR cannot move
+        //~| HELP consider borrowing here
+        //~| SUGGESTION &vrm[0]
+        Either::One(_t)
+        | Either::Two(_t) => (),
+    }
+    match vrm[0] {
+        //~^ ERROR cannot move
+        //~| HELP consider borrowing here
+        //~| SUGGESTION &vrm[0]
+        Either::One(_t) => (),
+        Either::Two(ref _t) => (),
+        // FIXME: should suggest removing `ref` too
+    }
+    match vrm[0] {
+        //~^ ERROR cannot move
+        //~| HELP consider borrowing here
+        //~| SUGGESTION &vrm[0]
+        Either::One(_t) => (),
+        Either::Two(ref mut _t) => (),
+        // FIXME: should suggest removing `ref` too
+    }
+
+    // -------- move from &Either/&X place --------
+
+    let &X(_t) = s;
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&`
+    //~| SUGGESTION X(_t)
+    if let &Either::One(_t) = r { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&`
+    //~| SUGGESTION Either::One(_t)
+    while let &Either::One(_t) = r { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&`
+    //~| SUGGESTION Either::One(_t)
+    match r {
+        //~^ ERROR cannot move
+        &Either::One(_t)
+        //~^ HELP consider removing the `&`
+        //~| SUGGESTION Either::One(_t)
+        | &Either::Two(_t) => (),
+        // FIXME: would really like a suggestion here too
+    }
+    match r {
+        //~^ ERROR cannot move
+        &Either::One(_t) => (),
+        //~^ HELP consider removing the `&`
+        //~| SUGGESTION Either::One(_t)
+        &Either::Two(ref _t) => (),
+    }
+    match r {
+        //~^ ERROR cannot move
+        &Either::One(_t) => (),
+        //~^ HELP consider removing the `&`
+        //~| SUGGESTION Either::One(_t)
+        Either::Two(_t) => (),
+    }
+    fn f1(&X(_t): &X) { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&`
+    //~| SUGGESTION X(_t)
+
+    let &mut X(_t) = sm;
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&mut`
+    //~| SUGGESTION X(_t)
+    if let &mut Either::One(_t) = rm { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&mut`
+    //~| SUGGESTION Either::One(_t)
+    while let &mut Either::One(_t) = rm { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&mut`
+    //~| SUGGESTION Either::One(_t)
+    match rm {
+        //~^ ERROR cannot move
+        &mut Either::One(_t) => (),
+        //~^ HELP consider removing the `&mut`
+        //~| SUGGESTION Either::One(_t)
+        &mut Either::Two(_t) => (),
+        //~^ HELP consider removing the `&mut`
+        //~| SUGGESTION Either::Two(_t)
+    }
+    match rm {
+        //~^ ERROR cannot move
+        &mut Either::One(_t) => (),
+        //~^ HELP consider removing the `&mut`
+        //~| SUGGESTION Either::One(_t)
+        &mut Either::Two(ref _t) => (),
+    }
+    match rm {
+        //~^ ERROR cannot move
+        &mut Either::One(_t) => (),
+        //~^ HELP consider removing the `&mut`
+        //~| SUGGESTION Either::One(_t)
+        &mut Either::Two(ref mut _t) => (),
+    }
+    match rm {
+        //~^ ERROR cannot move
+        &mut Either::One(_t) => (),
+        //~^ HELP consider removing the `&mut`
+        //~| SUGGESTION Either::One(_t)
+        Either::Two(_t) => (),
+    }
+    fn f2(&mut X(_t): &mut X) { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&mut`
+    //~| SUGGESTION X(_t)
+
+    // -------- move from tuple of &Either/&X --------
+
+    // FIXME: These should have suggestions.
+
+    let (&X(_t),) = (&x.clone(),);
+    //~^ ERROR cannot move
+    if let (&Either::One(_t),) = (&e.clone(),) { }
+    //~^ ERROR cannot move
+    while let (&Either::One(_t),) = (&e.clone(),) { }
+    //~^ ERROR cannot move
+    match (&e.clone(),) {
+        //~^ ERROR cannot move
+        (&Either::One(_t),)
+        | (&Either::Two(_t),) => (),
+    }
+    fn f3((&X(_t),): (&X,)) { }
+    //~^ ERROR cannot move
+
+    let (&mut X(_t),) = (&mut xm.clone(),);
+    //~^ ERROR cannot move
+    if let (&mut Either::One(_t),) = (&mut em.clone(),) { }
+    //~^ ERROR cannot move
+    while let (&mut Either::One(_t),) = (&mut em.clone(),) { }
+    //~^ ERROR cannot move
+    match (&mut em.clone(),) {
+        //~^ ERROR cannot move
+        (&mut Either::One(_t),) => (),
+        (&mut Either::Two(_t),) => (),
+    }
+    fn f4((&mut X(_t),): (&mut X,)) { }
+    //~^ ERROR cannot move
+
+    // -------- move from &Either/&X value --------
+
+    let &X(_t) = &x;
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&`
+    //~| SUGGESTION X(_t)
+    if let &Either::One(_t) = &e { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&`
+    //~| SUGGESTION Either::One(_t)
+    while let &Either::One(_t) = &e { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&`
+    //~| SUGGESTION Either::One(_t)
+    match &e {
+        //~^ ERROR cannot move
+        &Either::One(_t)
+        //~^ HELP consider removing the `&`
+        //~| SUGGESTION Either::One(_t)
+        | &Either::Two(_t) => (),
+        // FIXME: would really like a suggestion here too
+    }
+    match &e {
+        //~^ ERROR cannot move
+        &Either::One(_t) => (),
+        //~^ HELP consider removing the `&`
+        //~| SUGGESTION Either::One(_t)
+        &Either::Two(ref _t) => (),
+    }
+    match &e {
+        //~^ ERROR cannot move
+        &Either::One(_t) => (),
+        //~^ HELP consider removing the `&`
+        //~| SUGGESTION Either::One(_t)
+        Either::Two(_t) => (),
+    }
+
+    let &mut X(_t) = &mut xm;
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&mut`
+    //~| SUGGESTION X(_t)
+    if let &mut Either::One(_t) = &mut em { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&mut`
+    //~| SUGGESTION Either::One(_t)
+    while let &mut Either::One(_t) = &mut em { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&mut`
+    //~| SUGGESTION Either::One(_t)
+    match &mut em {
+        //~^ ERROR cannot move
+        &mut Either::One(_t)
+        //~^ HELP consider removing the `&mut`
+        //~| SUGGESTION Either::One(_t)
+        | &mut Either::Two(_t) => (),
+        // FIXME: would really like a suggestion here too
+    }
+    match &mut em {
+        //~^ ERROR cannot move
+        &mut Either::One(_t) => (),
+        //~^ HELP consider removing the `&mut`
+        //~| SUGGESTION Either::One(_t)
+        &mut Either::Two(ref _t) => (),
+    }
+    match &mut em {
+        //~^ ERROR cannot move
+        &mut Either::One(_t) => (),
+        //~^ HELP consider removing the `&mut`
+        //~| SUGGESTION Either::One(_t)
+        &mut Either::Two(ref mut _t) => (),
+    }
+    match &mut em {
+        //~^ ERROR cannot move
+        &mut Either::One(_t) => (),
+        //~^ HELP consider removing the `&mut`
+        //~| SUGGESTION Either::One(_t)
+        Either::Two(_t) => (),
+    }
+}
diff --git a/src/test/ui/suggestions/dont-suggest-ref/simple.stderr b/src/test/ui/suggestions/dont-suggest-ref/simple.stderr
new file mode 100644
index 0000000..6a8b17c
--- /dev/null
+++ b/src/test/ui/suggestions/dont-suggest-ref/simple.stderr
@@ -0,0 +1,998 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:40:17
+   |
+LL |     let X(_t) = *s;
+   |           --    ^^
+   |           |     |
+   |           |     cannot move out of borrowed content
+   |           |     help: consider removing the `*`: `s`
+   |           data moved here
+   |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:40:11
+   |
+LL |     let X(_t) = *s;
+   |           ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:44:30
+   |
+LL |     if let Either::One(_t) = *r { }
+   |                        --    ^^
+   |                        |     |
+   |                        |     cannot move out of borrowed content
+   |                        |     help: consider removing the `*`: `r`
+   |                        data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:44:24
+   |
+LL |     if let Either::One(_t) = *r { }
+   |                        ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:48:33
+   |
+LL |     while let Either::One(_t) = *r { }
+   |                           --    ^^
+   |                           |     |
+   |                           |     cannot move out of borrowed content
+   |                           |     help: consider removing the `*`: `r`
+   |                           data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:48:27
+   |
+LL |     while let Either::One(_t) = *r { }
+   |                           ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:52:11
+   |
+LL |     match *r {
+   |           ^^
+   |           |
+   |           cannot move out of borrowed content
+   |           help: consider removing the `*`: `r`
+...
+LL |         Either::One(_t)
+   |                     -- data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:56:21
+   |
+LL |         Either::One(_t)
+   |                     ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:59:11
+   |
+LL |     match *r {
+   |           ^^
+   |           |
+   |           cannot move out of borrowed content
+   |           help: consider removing the `*`: `r`
+...
+LL |         Either::One(_t) => (),
+   |                     -- data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:63:21
+   |
+LL |         Either::One(_t) => (),
+   |                     ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:68:17
+   |
+LL |     let X(_t) = *sm;
+   |           --    ^^^
+   |           |     |
+   |           |     cannot move out of borrowed content
+   |           |     help: consider removing the `*`: `sm`
+   |           data moved here
+   |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:68:11
+   |
+LL |     let X(_t) = *sm;
+   |           ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:72:30
+   |
+LL |     if let Either::One(_t) = *rm { }
+   |                        --    ^^^
+   |                        |     |
+   |                        |     cannot move out of borrowed content
+   |                        |     help: consider removing the `*`: `rm`
+   |                        data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:72:24
+   |
+LL |     if let Either::One(_t) = *rm { }
+   |                        ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:76:33
+   |
+LL |     while let Either::One(_t) = *rm { }
+   |                           --    ^^^
+   |                           |     |
+   |                           |     cannot move out of borrowed content
+   |                           |     help: consider removing the `*`: `rm`
+   |                           data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:76:27
+   |
+LL |     while let Either::One(_t) = *rm { }
+   |                           ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:80:11
+   |
+LL |     match *rm {
+   |           ^^^
+   |           |
+   |           cannot move out of borrowed content
+   |           help: consider removing the `*`: `rm`
+...
+LL |         Either::One(_t)
+   |                     -- data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:84:21
+   |
+LL |         Either::One(_t)
+   |                     ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:87:11
+   |
+LL |     match *rm {
+   |           ^^^
+   |           |
+   |           cannot move out of borrowed content
+   |           help: consider removing the `*`: `rm`
+...
+LL |         Either::One(_t) => (),
+   |                     -- data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:91:21
+   |
+LL |         Either::One(_t) => (),
+   |                     ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:95:11
+   |
+LL |     match *rm {
+   |           ^^^
+   |           |
+   |           cannot move out of borrowed content
+   |           help: consider removing the `*`: `rm`
+...
+LL |         Either::One(_t) => (),
+   |                     -- data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:99:21
+   |
+LL |         Either::One(_t) => (),
+   |                     ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:104:17
+   |
+LL |     let X(_t) = vs[0];
+   |           --    ^^^^^
+   |           |     |
+   |           |     cannot move out of borrowed content
+   |           |     help: consider borrowing here: `&vs[0]`
+   |           data moved here
+   |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:104:11
+   |
+LL |     let X(_t) = vs[0];
+   |           ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:108:30
+   |
+LL |     if let Either::One(_t) = vr[0] { }
+   |                        --    ^^^^^
+   |                        |     |
+   |                        |     cannot move out of borrowed content
+   |                        |     help: consider borrowing here: `&vr[0]`
+   |                        data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:108:24
+   |
+LL |     if let Either::One(_t) = vr[0] { }
+   |                        ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:112:33
+   |
+LL |     while let Either::One(_t) = vr[0] { }
+   |                           --    ^^^^^
+   |                           |     |
+   |                           |     cannot move out of borrowed content
+   |                           |     help: consider borrowing here: `&vr[0]`
+   |                           data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:112:27
+   |
+LL |     while let Either::One(_t) = vr[0] { }
+   |                           ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:116:11
+   |
+LL |     match vr[0] {
+   |           ^^^^^
+   |           |
+   |           cannot move out of borrowed content
+   |           help: consider borrowing here: `&vr[0]`
+...
+LL |         Either::One(_t)
+   |                     -- data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:120:21
+   |
+LL |         Either::One(_t)
+   |                     ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:123:11
+   |
+LL |     match vr[0] {
+   |           ^^^^^
+   |           |
+   |           cannot move out of borrowed content
+   |           help: consider borrowing here: `&vr[0]`
+...
+LL |         Either::One(_t) => (),
+   |                     -- data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:127:21
+   |
+LL |         Either::One(_t) => (),
+   |                     ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:132:17
+   |
+LL |     let X(_t) = vsm[0];
+   |           --    ^^^^^^
+   |           |     |
+   |           |     cannot move out of borrowed content
+   |           |     help: consider borrowing here: `&vsm[0]`
+   |           data moved here
+   |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:132:11
+   |
+LL |     let X(_t) = vsm[0];
+   |           ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:136:30
+   |
+LL |     if let Either::One(_t) = vrm[0] { }
+   |                        --    ^^^^^^
+   |                        |     |
+   |                        |     cannot move out of borrowed content
+   |                        |     help: consider borrowing here: `&vrm[0]`
+   |                        data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:136:24
+   |
+LL |     if let Either::One(_t) = vrm[0] { }
+   |                        ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:140:33
+   |
+LL |     while let Either::One(_t) = vrm[0] { }
+   |                           --    ^^^^^^
+   |                           |     |
+   |                           |     cannot move out of borrowed content
+   |                           |     help: consider borrowing here: `&vrm[0]`
+   |                           data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:140:27
+   |
+LL |     while let Either::One(_t) = vrm[0] { }
+   |                           ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:144:11
+   |
+LL |     match vrm[0] {
+   |           ^^^^^^
+   |           |
+   |           cannot move out of borrowed content
+   |           help: consider borrowing here: `&vrm[0]`
+...
+LL |         Either::One(_t)
+   |                     -- data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:148:21
+   |
+LL |         Either::One(_t)
+   |                     ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:151:11
+   |
+LL |     match vrm[0] {
+   |           ^^^^^^
+   |           |
+   |           cannot move out of borrowed content
+   |           help: consider borrowing here: `&vrm[0]`
+...
+LL |         Either::One(_t) => (),
+   |                     -- data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:155:21
+   |
+LL |         Either::One(_t) => (),
+   |                     ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:159:11
+   |
+LL |     match vrm[0] {
+   |           ^^^^^^
+   |           |
+   |           cannot move out of borrowed content
+   |           help: consider borrowing here: `&vrm[0]`
+...
+LL |         Either::One(_t) => (),
+   |                     -- data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:163:21
+   |
+LL |         Either::One(_t) => (),
+   |                     ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:170:18
+   |
+LL |     let &X(_t) = s;
+   |         ------   ^ cannot move out of borrowed content
+   |         |  |
+   |         |  data moved here
+   |         help: consider removing the `&`: `X(_t)`
+   |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:170:12
+   |
+LL |     let &X(_t) = s;
+   |            ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:174:31
+   |
+LL |     if let &Either::One(_t) = r { }
+   |            ----------------   ^ cannot move out of borrowed content
+   |            |            |
+   |            |            data moved here
+   |            help: consider removing the `&`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:174:25
+   |
+LL |     if let &Either::One(_t) = r { }
+   |                         ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:178:34
+   |
+LL |     while let &Either::One(_t) = r { }
+   |               ----------------   ^ cannot move out of borrowed content
+   |               |            |
+   |               |            data moved here
+   |               help: consider removing the `&`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:178:28
+   |
+LL |     while let &Either::One(_t) = r { }
+   |                            ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:182:11
+   |
+LL |     match r {
+   |           ^ cannot move out of borrowed content
+LL |
+LL |         &Either::One(_t)
+   |         ----------------
+   |         |            |
+   |         |            data moved here
+   |         help: consider removing the `&`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:184:22
+   |
+LL |         &Either::One(_t)
+   |                      ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:190:11
+   |
+LL |     match r {
+   |           ^ cannot move out of borrowed content
+LL |
+LL |         &Either::One(_t) => (),
+   |         ----------------
+   |         |            |
+   |         |            data moved here
+   |         help: consider removing the `&`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:192:22
+   |
+LL |         &Either::One(_t) => (),
+   |                      ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:197:11
+   |
+LL |     match r {
+   |           ^ cannot move out of borrowed content
+LL |
+LL |         &Either::One(_t) => (),
+   |         ----------------
+   |         |            |
+   |         |            data moved here
+   |         help: consider removing the `&`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:199:22
+   |
+LL |         &Either::One(_t) => (),
+   |                      ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:209:22
+   |
+LL |     let &mut X(_t) = sm;
+   |         ----------   ^^ cannot move out of borrowed content
+   |         |      |
+   |         |      data moved here
+   |         help: consider removing the `&mut`: `X(_t)`
+   |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:209:16
+   |
+LL |     let &mut X(_t) = sm;
+   |                ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:213:35
+   |
+LL |     if let &mut Either::One(_t) = rm { }
+   |            --------------------   ^^ cannot move out of borrowed content
+   |            |                |
+   |            |                data moved here
+   |            help: consider removing the `&mut`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:213:29
+   |
+LL |     if let &mut Either::One(_t) = rm { }
+   |                             ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:217:38
+   |
+LL |     while let &mut Either::One(_t) = rm { }
+   |               --------------------   ^^ cannot move out of borrowed content
+   |               |                |
+   |               |                data moved here
+   |               help: consider removing the `&mut`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:217:32
+   |
+LL |     while let &mut Either::One(_t) = rm { }
+   |                                ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:221:11
+   |
+LL |     match rm {
+   |           ^^ cannot move out of borrowed content
+LL |
+LL |         &mut Either::One(_t) => (),
+   |                          -- data moved here
+...
+LL |         &mut Either::Two(_t) => (),
+   |                          -- ...and here
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/simple.rs:223:26
+   |
+LL |         &mut Either::One(_t) => (),
+   |                          ^^
+...
+LL |         &mut Either::Two(_t) => (),
+   |                          ^^
+help: consider removing the `&mut`
+   |
+LL |         Either::One(_t) => (),
+   |         ^^^^^^^^^^^^^^^
+help: consider removing the `&mut`
+   |
+LL |         Either::Two(_t) => (),
+   |         ^^^^^^^^^^^^^^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:230:11
+   |
+LL |     match rm {
+   |           ^^ cannot move out of borrowed content
+LL |
+LL |         &mut Either::One(_t) => (),
+   |         --------------------
+   |         |                |
+   |         |                data moved here
+   |         help: consider removing the `&mut`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:232:26
+   |
+LL |         &mut Either::One(_t) => (),
+   |                          ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:237:11
+   |
+LL |     match rm {
+   |           ^^ cannot move out of borrowed content
+LL |
+LL |         &mut Either::One(_t) => (),
+   |         --------------------
+   |         |                |
+   |         |                data moved here
+   |         help: consider removing the `&mut`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:239:26
+   |
+LL |         &mut Either::One(_t) => (),
+   |                          ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:244:11
+   |
+LL |     match rm {
+   |           ^^ cannot move out of borrowed content
+LL |
+LL |         &mut Either::One(_t) => (),
+   |         --------------------
+   |         |                |
+   |         |                data moved here
+   |         help: consider removing the `&mut`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:246:26
+   |
+LL |         &mut Either::One(_t) => (),
+   |                          ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:260:21
+   |
+LL |     let (&X(_t),) = (&x.clone(),);
+   |             --      ^^^^^^^^^^^^^ cannot move out of borrowed content
+   |             |
+   |             data moved here
+   |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:260:13
+   |
+LL |     let (&X(_t),) = (&x.clone(),);
+   |             ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:262:34
+   |
+LL |     if let (&Either::One(_t),) = (&e.clone(),) { }
+   |                          --      ^^^^^^^^^^^^^ cannot move out of borrowed content
+   |                          |
+   |                          data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:262:26
+   |
+LL |     if let (&Either::One(_t),) = (&e.clone(),) { }
+   |                          ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:264:37
+   |
+LL |     while let (&Either::One(_t),) = (&e.clone(),) { }
+   |                             --      ^^^^^^^^^^^^^ cannot move out of borrowed content
+   |                             |
+   |                             data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:264:29
+   |
+LL |     while let (&Either::One(_t),) = (&e.clone(),) { }
+   |                             ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:266:11
+   |
+LL |     match (&e.clone(),) {
+   |           ^^^^^^^^^^^^^ cannot move out of borrowed content
+LL |
+LL |         (&Either::One(_t),)
+   |                       -- data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:268:23
+   |
+LL |         (&Either::One(_t),)
+   |                       ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:274:25
+   |
+LL |     let (&mut X(_t),) = (&mut xm.clone(),);
+   |                 --      ^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+   |                 |
+   |                 data moved here
+   |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:274:17
+   |
+LL |     let (&mut X(_t),) = (&mut xm.clone(),);
+   |                 ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:276:38
+   |
+LL |     if let (&mut Either::One(_t),) = (&mut em.clone(),) { }
+   |                              --      ^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+   |                              |
+   |                              data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:276:30
+   |
+LL |     if let (&mut Either::One(_t),) = (&mut em.clone(),) { }
+   |                              ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:278:41
+   |
+LL |     while let (&mut Either::One(_t),) = (&mut em.clone(),) { }
+   |                                 --      ^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+   |                                 |
+   |                                 data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:278:33
+   |
+LL |     while let (&mut Either::One(_t),) = (&mut em.clone(),) { }
+   |                                 ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:280:11
+   |
+LL |     match (&mut em.clone(),) {
+   |           ^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+LL |
+LL |         (&mut Either::One(_t),) => (),
+   |                           -- data moved here
+LL |         (&mut Either::Two(_t),) => (),
+   |                           -- ...and here
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/simple.rs:282:27
+   |
+LL |         (&mut Either::One(_t),) => (),
+   |                           ^^
+LL |         (&mut Either::Two(_t),) => (),
+   |                           ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:290:18
+   |
+LL |     let &X(_t) = &x;
+   |         ------   ^^ cannot move out of borrowed content
+   |         |  |
+   |         |  data moved here
+   |         help: consider removing the `&`: `X(_t)`
+   |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:290:12
+   |
+LL |     let &X(_t) = &x;
+   |            ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:294:31
+   |
+LL |     if let &Either::One(_t) = &e { }
+   |            ----------------   ^^ cannot move out of borrowed content
+   |            |            |
+   |            |            data moved here
+   |            help: consider removing the `&`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:294:25
+   |
+LL |     if let &Either::One(_t) = &e { }
+   |                         ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:298:34
+   |
+LL |     while let &Either::One(_t) = &e { }
+   |               ----------------   ^^ cannot move out of borrowed content
+   |               |            |
+   |               |            data moved here
+   |               help: consider removing the `&`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:298:28
+   |
+LL |     while let &Either::One(_t) = &e { }
+   |                            ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:302:11
+   |
+LL |     match &e {
+   |           ^^ cannot move out of borrowed content
+LL |
+LL |         &Either::One(_t)
+   |         ----------------
+   |         |            |
+   |         |            data moved here
+   |         help: consider removing the `&`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:304:22
+   |
+LL |         &Either::One(_t)
+   |                      ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:310:11
+   |
+LL |     match &e {
+   |           ^^ cannot move out of borrowed content
+LL |
+LL |         &Either::One(_t) => (),
+   |         ----------------
+   |         |            |
+   |         |            data moved here
+   |         help: consider removing the `&`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:312:22
+   |
+LL |         &Either::One(_t) => (),
+   |                      ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:317:11
+   |
+LL |     match &e {
+   |           ^^ cannot move out of borrowed content
+LL |
+LL |         &Either::One(_t) => (),
+   |         ----------------
+   |         |            |
+   |         |            data moved here
+   |         help: consider removing the `&`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:319:22
+   |
+LL |         &Either::One(_t) => (),
+   |                      ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:325:22
+   |
+LL |     let &mut X(_t) = &mut xm;
+   |         ----------   ^^^^^^^ cannot move out of borrowed content
+   |         |      |
+   |         |      data moved here
+   |         help: consider removing the `&mut`: `X(_t)`
+   |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:325:16
+   |
+LL |     let &mut X(_t) = &mut xm;
+   |                ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:329:35
+   |
+LL |     if let &mut Either::One(_t) = &mut em { }
+   |            --------------------   ^^^^^^^ cannot move out of borrowed content
+   |            |                |
+   |            |                data moved here
+   |            help: consider removing the `&mut`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:329:29
+   |
+LL |     if let &mut Either::One(_t) = &mut em { }
+   |                             ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:333:38
+   |
+LL |     while let &mut Either::One(_t) = &mut em { }
+   |               --------------------   ^^^^^^^ cannot move out of borrowed content
+   |               |                |
+   |               |                data moved here
+   |               help: consider removing the `&mut`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:333:32
+   |
+LL |     while let &mut Either::One(_t) = &mut em { }
+   |                                ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:337:11
+   |
+LL |     match &mut em {
+   |           ^^^^^^^ cannot move out of borrowed content
+LL |
+LL |         &mut Either::One(_t)
+   |         --------------------
+   |         |                |
+   |         |                data moved here
+   |         help: consider removing the `&mut`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:339:26
+   |
+LL |         &mut Either::One(_t)
+   |                          ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:345:11
+   |
+LL |     match &mut em {
+   |           ^^^^^^^ cannot move out of borrowed content
+LL |
+LL |         &mut Either::One(_t) => (),
+   |         --------------------
+   |         |                |
+   |         |                data moved here
+   |         help: consider removing the `&mut`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:347:26
+   |
+LL |         &mut Either::One(_t) => (),
+   |                          ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:352:11
+   |
+LL |     match &mut em {
+   |           ^^^^^^^ cannot move out of borrowed content
+LL |
+LL |         &mut Either::One(_t) => (),
+   |         --------------------
+   |         |                |
+   |         |                data moved here
+   |         help: consider removing the `&mut`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:354:26
+   |
+LL |         &mut Either::One(_t) => (),
+   |                          ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:359:11
+   |
+LL |     match &mut em {
+   |           ^^^^^^^ cannot move out of borrowed content
+LL |
+LL |         &mut Either::One(_t) => (),
+   |         --------------------
+   |         |                |
+   |         |                data moved here
+   |         help: consider removing the `&mut`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:361:26
+   |
+LL |         &mut Either::One(_t) => (),
+   |                          ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:204:11
+   |
+LL |     fn f1(&X(_t): &X) { }
+   |           ^^^--^
+   |           |  |
+   |           |  data moved here
+   |           cannot move out of borrowed content
+   |           help: consider removing the `&`: `X(_t)`
+   |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:204:14
+   |
+LL |     fn f1(&X(_t): &X) { }
+   |              ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:251:11
+   |
+LL |     fn f2(&mut X(_t): &mut X) { }
+   |           ^^^^^^^--^
+   |           |      |
+   |           |      data moved here
+   |           cannot move out of borrowed content
+   |           help: consider removing the `&mut`: `X(_t)`
+   |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:251:18
+   |
+LL |     fn f2(&mut X(_t): &mut X) { }
+   |                  ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:271:11
+   |
+LL |     fn f3((&X(_t),): (&X,)) { }
+   |           ^^^^--^^^
+   |           |   |
+   |           |   data moved here
+   |           cannot move out of borrowed content
+   |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:271:15
+   |
+LL |     fn f3((&X(_t),): (&X,)) { }
+   |               ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:285:11
+   |
+LL |     fn f4((&mut X(_t),): (&mut X,)) { }
+   |           ^^^^^^^^--^^^
+   |           |       |
+   |           |       data moved here
+   |           cannot move out of borrowed content
+   |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:285:19
+   |
+LL |     fn f4((&mut X(_t),): (&mut X,)) { }
+   |                   ^^
+
+error: aborting due to 60 previous errors
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/suggestions/format-borrow.rs b/src/test/ui/suggestions/format-borrow.rs
new file mode 100644
index 0000000..63930e7
--- /dev/null
+++ b/src/test/ui/suggestions/format-borrow.rs
@@ -0,0 +1,6 @@
+fn main() {
+    let a: String = &String::from("a");
+    //~^ ERROR mismatched types
+    let b: String = &format!("b");
+    //~^ ERROR mismatched types
+}
diff --git a/src/test/ui/suggestions/format-borrow.stderr b/src/test/ui/suggestions/format-borrow.stderr
new file mode 100644
index 0000000..44bb11f
--- /dev/null
+++ b/src/test/ui/suggestions/format-borrow.stderr
@@ -0,0 +1,27 @@
+error[E0308]: mismatched types
+  --> $DIR/format-borrow.rs:2:21
+   |
+LL |     let a: String = &String::from("a");
+   |                     ^^^^^^^^^^^^^^^^^^
+   |                     |
+   |                     expected struct `std::string::String`, found reference
+   |                     help: consider removing the borrow: `String::from("a")`
+   |
+   = note: expected type `std::string::String`
+              found type `&std::string::String`
+
+error[E0308]: mismatched types
+  --> $DIR/format-borrow.rs:4:21
+   |
+LL |     let b: String = &format!("b");
+   |                     ^^^^^^^^^^^^^
+   |                     |
+   |                     expected struct `std::string::String`, found reference
+   |                     help: consider removing the borrow: `format!("b")`
+   |
+   = note: expected type `std::string::String`
+              found type `&std::string::String`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/suggestions/impl-trait-return-trailing-semicolon.rs b/src/test/ui/suggestions/impl-trait-return-trailing-semicolon.rs
new file mode 100644
index 0000000..e72a2d8
--- /dev/null
+++ b/src/test/ui/suggestions/impl-trait-return-trailing-semicolon.rs
@@ -0,0 +1,7 @@
+trait Bar {}
+impl Bar for u8 {}
+fn foo() -> impl Bar {
+    5; //~^ ERROR the trait bound `(): Bar` is not satisfied
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/impl-trait-return-trailing-semicolon.stderr b/src/test/ui/suggestions/impl-trait-return-trailing-semicolon.stderr
new file mode 100644
index 0000000..cc3a2b9
--- /dev/null
+++ b/src/test/ui/suggestions/impl-trait-return-trailing-semicolon.stderr
@@ -0,0 +1,13 @@
+error[E0277]: the trait bound `(): Bar` is not satisfied
+  --> $DIR/impl-trait-return-trailing-semicolon.rs:3:13
+   |
+LL | fn foo() -> impl Bar {
+   |             ^^^^^^^^ the trait `Bar` is not implemented for `()`
+LL |     5;
+   |      - consider removing this semicolon
+   |
+   = note: the return type of a function must have a statically known size
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/suggestions/into-str.rs b/src/test/ui/suggestions/into-str.rs
new file mode 100644
index 0000000..9793ee8
--- /dev/null
+++ b/src/test/ui/suggestions/into-str.rs
@@ -0,0 +1,6 @@
+fn foo<'a, T>(_t: T) where T: Into<&'a str> {}
+
+fn main() {
+    foo(String::new());
+    //~^ ERROR the trait bound `&str: std::convert::From<std::string::String>` is not satisfied
+}
diff --git a/src/test/ui/suggestions/into-str.stderr b/src/test/ui/suggestions/into-str.stderr
new file mode 100644
index 0000000..3e28700
--- /dev/null
+++ b/src/test/ui/suggestions/into-str.stderr
@@ -0,0 +1,17 @@
+error[E0277]: the trait bound `&str: std::convert::From<std::string::String>` is not satisfied
+  --> $DIR/into-str.rs:4:5
+   |
+LL |     foo(String::new());
+   |     ^^^ the trait `std::convert::From<std::string::String>` is not implemented for `&str`
+   |
+   = note: to coerce a `std::string::String` into a `&str`, use `&*` as a prefix
+   = note: required because of the requirements on the impl of `std::convert::Into<&str>` for `std::string::String`
+note: required by `foo`
+  --> $DIR/into-str.rs:1:1
+   |
+LL | fn foo<'a, T>(_t: T) where T: Into<&'a str> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.rs b/src/test/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.rs
new file mode 100644
index 0000000..37f0782
--- /dev/null
+++ b/src/test/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.rs
@@ -0,0 +1,8 @@
+fn vindictive() -> bool { true }
+
+fn perfidy() -> (i32, i32) {
+    vindictive() //~ ERROR expected function, found `bool`
+    (1, 2)
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.stderr b/src/test/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.stderr
new file mode 100644
index 0000000..f81c45e
--- /dev/null
+++ b/src/test/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.stderr
@@ -0,0 +1,16 @@
+error[E0618]: expected function, found `bool`
+  --> $DIR/issue-51055-missing-semicolon-between-call-and-tuple.rs:4:5
+   |
+LL |   fn vindictive() -> bool { true }
+   |   -------------------------------- `vindictive` defined here returns `bool`
+...
+LL |       vindictive()
+   |       -^^^^^^^^^^^- help: try adding a semicolon: `;`
+   |  _____|
+   | |
+LL | |     (1, 2)
+   | |__________- call expression requires function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0618`.
diff --git a/src/test/ui/suggestions/no-extern-crate-in-type.rs b/src/test/ui/suggestions/no-extern-crate-in-type.rs
new file mode 100644
index 0000000..bb93ef4
--- /dev/null
+++ b/src/test/ui/suggestions/no-extern-crate-in-type.rs
@@ -0,0 +1,7 @@
+// aux-build:foo.rs
+
+extern crate foo;
+
+type Output = Option<Foo>; //~ ERROR cannot find type `Foo`
+
+fn main() {}
diff --git a/src/test/ui/suggestions/no-extern-crate-in-type.stderr b/src/test/ui/suggestions/no-extern-crate-in-type.stderr
new file mode 100644
index 0000000..d4a5a95
--- /dev/null
+++ b/src/test/ui/suggestions/no-extern-crate-in-type.stderr
@@ -0,0 +1,13 @@
+error[E0412]: cannot find type `Foo` in this scope
+  --> $DIR/no-extern-crate-in-type.rs:5:22
+   |
+LL | type Output = Option<Foo>;
+   |                      ^^^ not found in this scope
+help: possible candidate is found in another module, you can import it into scope
+   |
+LL | use foo::Foo;
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/src/test/ui/suggestions/path-by-value.rs b/src/test/ui/suggestions/path-by-value.rs
new file mode 100644
index 0000000..c875ca6
--- /dev/null
+++ b/src/test/ui/suggestions/path-by-value.rs
@@ -0,0 +1,6 @@
+use std::path::Path;
+
+fn f(p: Path) { }
+//~^ ERROR E0277
+
+fn main() {}
diff --git a/src/test/ui/suggestions/path-by-value.stderr b/src/test/ui/suggestions/path-by-value.stderr
new file mode 100644
index 0000000..b073e10
--- /dev/null
+++ b/src/test/ui/suggestions/path-by-value.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/path-by-value.rs:3:6
+   |
+LL | fn f(p: Path) { }
+   |      ^ borrow the `Path` instead
+   |
+   = help: within `std::path::Path`, the trait `std::marker::Sized` is not implemented for `[u8]`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: required because it appears within the type `std::path::Path`
+   = note: all local variables must have a statically known size
+   = help: unsized locals are gated as an unstable feature
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/suggestions/path-display.rs b/src/test/ui/suggestions/path-display.rs
new file mode 100644
index 0000000..62fc9e7
--- /dev/null
+++ b/src/test/ui/suggestions/path-display.rs
@@ -0,0 +1,7 @@
+use std::path::Path;
+
+fn main() {
+    let path = Path::new("/tmp/foo/bar.txt");
+    println!("{}", path);
+    //~^ ERROR E0277
+}
diff --git a/src/test/ui/suggestions/path-display.stderr b/src/test/ui/suggestions/path-display.stderr
new file mode 100644
index 0000000..39d236a
--- /dev/null
+++ b/src/test/ui/suggestions/path-display.stderr
@@ -0,0 +1,14 @@
+error[E0277]: `std::path::Path` doesn't implement `std::fmt::Display`
+  --> $DIR/path-display.rs:5:20
+   |
+LL |     println!("{}", path);
+   |                    ^^^^ `std::path::Path` cannot be formatted with the default formatter; call `.display()` on it
+   |
+   = help: the trait `std::fmt::Display` is not implemented for `std::path::Path`
+   = note: call `.display()` or `.to_string_lossy()` to safely print paths, as they may contain non-Unicode data
+   = note: required because of the requirements on the impl of `std::fmt::Display` for `&std::path::Path`
+   = note: required by `std::fmt::Display::fmt`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/suggestions/recover-from-semicolon-trailing-item.rs b/src/test/ui/suggestions/recover-from-semicolon-trailing-item.rs
new file mode 100644
index 0000000..82935af
--- /dev/null
+++ b/src/test/ui/suggestions/recover-from-semicolon-trailing-item.rs
@@ -0,0 +1,16 @@
+// verify that after encountering a semicolon after an item the parser recovers
+mod M {};
+//~^ ERROR expected item, found `;`
+struct S {};
+//~^ ERROR expected item, found `;`
+fn foo(a: usize) {};
+//~^ ERROR expected item, found `;`
+fn main() {
+    struct X {};  // ok
+    let _: usize = S {};
+    //~^ ERROR mismatched types
+    let _: usize = X {};
+    //~^ ERROR mismatched types
+    foo("");
+    //~^ ERROR mismatched types
+}
diff --git a/src/test/ui/suggestions/recover-from-semicolon-trailing-item.stderr b/src/test/ui/suggestions/recover-from-semicolon-trailing-item.stderr
new file mode 100644
index 0000000..9a47a1e
--- /dev/null
+++ b/src/test/ui/suggestions/recover-from-semicolon-trailing-item.stderr
@@ -0,0 +1,50 @@
+error: expected item, found `;`
+  --> $DIR/recover-from-semicolon-trailing-item.rs:2:9
+   |
+LL | mod M {};
+   |         ^ help: remove this semicolon
+
+error: expected item, found `;`
+  --> $DIR/recover-from-semicolon-trailing-item.rs:4:12
+   |
+LL | struct S {};
+   |            ^ help: remove this semicolon
+   |
+   = help: braced struct declarations are not followed by a semicolon
+
+error: expected item, found `;`
+  --> $DIR/recover-from-semicolon-trailing-item.rs:6:20
+   |
+LL | fn foo(a: usize) {};
+   |                    ^ help: remove this semicolon
+
+error[E0308]: mismatched types
+  --> $DIR/recover-from-semicolon-trailing-item.rs:10:20
+   |
+LL |     let _: usize = S {};
+   |                    ^^^^ expected usize, found struct `S`
+   |
+   = note: expected type `usize`
+              found type `S`
+
+error[E0308]: mismatched types
+  --> $DIR/recover-from-semicolon-trailing-item.rs:12:20
+   |
+LL |     let _: usize = X {};
+   |                    ^^^^ expected usize, found struct `main::X`
+   |
+   = note: expected type `usize`
+              found type `main::X`
+
+error[E0308]: mismatched types
+  --> $DIR/recover-from-semicolon-trailing-item.rs:14:9
+   |
+LL |     foo("");
+   |         ^^ expected usize, found reference
+   |
+   = note: expected type `usize`
+              found type `&'static str`
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/suggestions/recover-invalid-float.rs b/src/test/ui/suggestions/recover-invalid-float.rs
new file mode 100644
index 0000000..506ef89
--- /dev/null
+++ b/src/test/ui/suggestions/recover-invalid-float.rs
@@ -0,0 +1,11 @@
+fn main() {
+    let _: usize = .3;
+    //~^ ERROR float literals must have an integer part
+    //~| ERROR mismatched types
+    let _: usize = .42f32;
+    //~^ ERROR float literals must have an integer part
+    //~| ERROR mismatched types
+    let _: usize = .5f64;
+    //~^ ERROR float literals must have an integer part
+    //~| ERROR mismatched types
+}
diff --git a/src/test/ui/suggestions/recover-invalid-float.stderr b/src/test/ui/suggestions/recover-invalid-float.stderr
new file mode 100644
index 0000000..c464676
--- /dev/null
+++ b/src/test/ui/suggestions/recover-invalid-float.stderr
@@ -0,0 +1,42 @@
+error: float literals must have an integer part
+  --> $DIR/recover-invalid-float.rs:2:20
+   |
+LL |     let _: usize = .3;
+   |                    ^^ help: must have an integer part: `0.3`
+
+error: float literals must have an integer part
+  --> $DIR/recover-invalid-float.rs:5:20
+   |
+LL |     let _: usize = .42f32;
+   |                    ^^^^^^ help: must have an integer part: `0.42f32`
+
+error: float literals must have an integer part
+  --> $DIR/recover-invalid-float.rs:8:20
+   |
+LL |     let _: usize = .5f64;
+   |                    ^^^^^ help: must have an integer part: `0.5f64`
+
+error[E0308]: mismatched types
+  --> $DIR/recover-invalid-float.rs:2:20
+   |
+LL |     let _: usize = .3;
+   |                    ^^ expected usize, found floating-point number
+   |
+   = note: expected type `usize`
+              found type `{float}`
+
+error[E0308]: mismatched types
+  --> $DIR/recover-invalid-float.rs:5:20
+   |
+LL |     let _: usize = .42f32;
+   |                    ^^^^^^ expected usize, found f32
+
+error[E0308]: mismatched types
+  --> $DIR/recover-invalid-float.rs:8:20
+   |
+LL |     let _: usize = .5f64;
+   |                    ^^^^^ expected usize, found f64
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/suggestions/return-without-lifetime.rs b/src/test/ui/suggestions/return-without-lifetime.rs
new file mode 100644
index 0000000..9bfce11
--- /dev/null
+++ b/src/test/ui/suggestions/return-without-lifetime.rs
@@ -0,0 +1,10 @@
+struct Thing<'a>(&'a ());
+struct Foo<'a>(&usize);
+//~^ ERROR missing lifetime specifier
+
+fn func1<'a>(_arg: &'a Thing) -> &() { unimplemented!() }
+//~^ ERROR missing lifetime specifier
+fn func2<'a>(_arg: &Thing<'a>) -> &() { unimplemented!() }
+//~^ ERROR missing lifetime specifier
+
+fn main() {}
diff --git a/src/test/ui/suggestions/return-without-lifetime.stderr b/src/test/ui/suggestions/return-without-lifetime.stderr
new file mode 100644
index 0000000..7f5ff95
--- /dev/null
+++ b/src/test/ui/suggestions/return-without-lifetime.stderr
@@ -0,0 +1,25 @@
+error[E0106]: missing lifetime specifier
+  --> $DIR/return-without-lifetime.rs:2:16
+   |
+LL | struct Foo<'a>(&usize);
+   |                ^ help: consider using the named lifetime: `&'a`
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/return-without-lifetime.rs:5:34
+   |
+LL | fn func1<'a>(_arg: &'a Thing) -> &() { unimplemented!() }
+   |                                  ^ help: consider using the named lifetime: `&'a`
+   |
+   = help: this function's return type contains a borrowed value, but the signature does not say which one of `_arg`'s 2 lifetimes it is borrowed from
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/return-without-lifetime.rs:7:35
+   |
+LL | fn func2<'a>(_arg: &Thing<'a>) -> &() { unimplemented!() }
+   |                                   ^ help: consider using the named lifetime: `&'a`
+   |
+   = help: this function's return type contains a borrowed value, but the signature does not say which one of `_arg`'s 2 lifetimes it is borrowed from
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0106`.
diff --git a/src/test/ui/suggestions/suggest-impl-trait-lifetime.fixed b/src/test/ui/suggestions/suggest-impl-trait-lifetime.fixed
new file mode 100644
index 0000000..8592af1
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-impl-trait-lifetime.fixed
@@ -0,0 +1,18 @@
+// run-rustfix
+
+use std::fmt::Debug;
+
+fn foo(d: impl Debug + 'static) {
+//~^ HELP consider adding an explicit lifetime bound  `'static` to `impl Debug`
+    bar(d);
+//~^ ERROR the parameter type `impl Debug` may not live long enough
+//~| NOTE ...so that the type `impl Debug` will meet its required lifetime bounds
+}
+
+fn bar(d: impl Debug + 'static) {
+    println!("{:?}", d)
+}
+
+fn main() {
+  foo("hi");
+}
diff --git a/src/test/ui/suggestions/suggest-impl-trait-lifetime.rs b/src/test/ui/suggestions/suggest-impl-trait-lifetime.rs
new file mode 100644
index 0000000..c67d78e
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-impl-trait-lifetime.rs
@@ -0,0 +1,18 @@
+// run-rustfix
+
+use std::fmt::Debug;
+
+fn foo(d: impl Debug) {
+//~^ HELP consider adding an explicit lifetime bound  `'static` to `impl Debug`
+    bar(d);
+//~^ ERROR the parameter type `impl Debug` may not live long enough
+//~| NOTE ...so that the type `impl Debug` will meet its required lifetime bounds
+}
+
+fn bar(d: impl Debug + 'static) {
+    println!("{:?}", d)
+}
+
+fn main() {
+  foo("hi");
+}
diff --git a/src/test/ui/suggestions/suggest-impl-trait-lifetime.stderr b/src/test/ui/suggestions/suggest-impl-trait-lifetime.stderr
new file mode 100644
index 0000000..cba231d
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-impl-trait-lifetime.stderr
@@ -0,0 +1,19 @@
+error[E0310]: the parameter type `impl Debug` may not live long enough
+  --> $DIR/suggest-impl-trait-lifetime.rs:7:5
+   |
+LL |     bar(d);
+   |     ^^^
+   |
+note: ...so that the type `impl Debug` will meet its required lifetime bounds
+  --> $DIR/suggest-impl-trait-lifetime.rs:7:5
+   |
+LL |     bar(d);
+   |     ^^^
+help: consider adding an explicit lifetime bound  `'static` to `impl Debug`...
+   |
+LL | fn foo(d: impl Debug + 'static) {
+   |           ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0310`.
diff --git a/src/test/ui/suggestions/suggest-labels.rs b/src/test/ui/suggestions/suggest-labels.rs
new file mode 100644
index 0000000..159f458
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-labels.rs
@@ -0,0 +1,16 @@
+#[allow(unreachable_code, unused_labels)]
+fn main() {
+    'foo: loop {
+        break 'fo; //~ ERROR use of undeclared label
+    }
+
+    'bar: loop {
+        continue 'bor; //~ ERROR use of undeclared label
+    }
+
+    'longlabel: loop {
+        'longlabel1: loop {
+            break 'longlable; //~ ERROR use of undeclared label
+        }
+    }
+}
diff --git a/src/test/ui/suggestions/suggest-labels.stderr b/src/test/ui/suggestions/suggest-labels.stderr
new file mode 100644
index 0000000..ead8f94
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-labels.stderr
@@ -0,0 +1,21 @@
+error[E0426]: use of undeclared label `'fo`
+  --> $DIR/suggest-labels.rs:4:15
+   |
+LL |         break 'fo;
+   |               ^^^ did you mean `'foo`?
+
+error[E0426]: use of undeclared label `'bor`
+  --> $DIR/suggest-labels.rs:8:18
+   |
+LL |         continue 'bor;
+   |                  ^^^^ did you mean `'bar`?
+
+error[E0426]: use of undeclared label `'longlable`
+  --> $DIR/suggest-labels.rs:13:19
+   |
+LL |             break 'longlable;
+   |                   ^^^^^^^^^^ did you mean `'longlabel1`?
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0426`.
diff --git a/src/test/ui/suggestions/suggest-methods.rs b/src/test/ui/suggestions/suggest-methods.rs
new file mode 100644
index 0000000..f40b9ed
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-methods.rs
@@ -0,0 +1,30 @@
+struct Foo;
+
+impl Foo {
+    fn bar(self) {}
+    fn baz(&self, x: f64) {}
+}
+
+trait FooT {
+    fn bag(&self);
+}
+
+impl FooT for Foo {
+    fn bag(&self) {}
+}
+
+fn main() {
+    let f = Foo;
+    f.bat(1.0); //~ ERROR no method named
+
+    let s = "foo".to_string();
+    let _ = s.is_emtpy(); //~ ERROR no method named
+
+    // Generates a warning for `count_zeros()`. `count_ones()` is also a close
+    // match, but the former is closer.
+    let _ = 63u32.count_eos(); //~ ERROR no method named
+
+    // Does not generate a warning
+    let _ = 63u32.count_o(); //~ ERROR no method named
+
+}
diff --git a/src/test/ui/suggestions/suggest-methods.stderr b/src/test/ui/suggestions/suggest-methods.stderr
new file mode 100644
index 0000000..09d5857
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-methods.stderr
@@ -0,0 +1,30 @@
+error[E0599]: no method named `bat` found for type `Foo` in the current scope
+  --> $DIR/suggest-methods.rs:18:7
+   |
+LL | struct Foo;
+   | ----------- method `bat` not found for this
+...
+LL |     f.bat(1.0);
+   |       ^^^ help: did you mean: `bar`
+
+error[E0599]: no method named `is_emtpy` found for type `std::string::String` in the current scope
+  --> $DIR/suggest-methods.rs:21:15
+   |
+LL |     let _ = s.is_emtpy();
+   |               ^^^^^^^^ help: did you mean: `is_empty`
+
+error[E0599]: no method named `count_eos` found for type `u32` in the current scope
+  --> $DIR/suggest-methods.rs:25:19
+   |
+LL |     let _ = 63u32.count_eos();
+   |                   ^^^^^^^^^ help: did you mean: `count_zeros`
+
+error[E0599]: no method named `count_o` found for type `u32` in the current scope
+  --> $DIR/suggest-methods.rs:28:19
+   |
+LL |     let _ = 63u32.count_o();
+   |                   ^^^^^^^
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/suggestions/suggest-move-lifetimes.rs b/src/test/ui/suggestions/suggest-move-lifetimes.rs
new file mode 100644
index 0000000..6b26f12
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-move-lifetimes.rs
@@ -0,0 +1,21 @@
+struct A<T, 'a> { //~ ERROR lifetime parameters must be declared
+    t: &'a T,
+}
+
+struct B<T, 'a, U> { //~ ERROR lifetime parameters must be declared
+    t: &'a T,
+    u: U,
+}
+
+struct C<T, U, 'a> { //~ ERROR lifetime parameters must be declared
+    t: &'a T,
+    u: U,
+}
+
+struct D<T, U, 'a, 'b, V, 'c> { //~ ERROR lifetime parameters must be declared
+    t: &'a T,
+    u: &'b U,
+    v: &'c V,
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/suggest-move-lifetimes.stderr b/src/test/ui/suggestions/suggest-move-lifetimes.stderr
new file mode 100644
index 0000000..1851c8d
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-move-lifetimes.stderr
@@ -0,0 +1,26 @@
+error: lifetime parameters must be declared prior to type parameters
+  --> $DIR/suggest-move-lifetimes.rs:1:13
+   |
+LL | struct A<T, 'a> {
+   |         ----^^- help: reorder the parameters: lifetimes, then types: `<'a, T>`
+
+error: lifetime parameters must be declared prior to type parameters
+  --> $DIR/suggest-move-lifetimes.rs:5:13
+   |
+LL | struct B<T, 'a, U> {
+   |         ----^^---- help: reorder the parameters: lifetimes, then types: `<'a, T, U>`
+
+error: lifetime parameters must be declared prior to type parameters
+  --> $DIR/suggest-move-lifetimes.rs:10:16
+   |
+LL | struct C<T, U, 'a> {
+   |         -------^^- help: reorder the parameters: lifetimes, then types: `<'a, T, U>`
+
+error: lifetime parameters must be declared prior to type parameters
+  --> $DIR/suggest-move-lifetimes.rs:15:16
+   |
+LL | struct D<T, U, 'a, 'b, V, 'c> {
+   |         -------^^--^^-----^^- help: reorder the parameters: lifetimes, then types: `<'a, 'b, 'c, T, U, V>`
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/suggestions/suggest-move-types.rs b/src/test/ui/suggestions/suggest-move-types.rs
new file mode 100644
index 0000000..890950e
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-move-types.rs
@@ -0,0 +1,89 @@
+// ignore-tidy-linelength
+
+#![allow(warnings)]
+
+// This test verifies that the suggestion to move types before associated type bindings
+// is correct.
+
+trait One<T> {
+  type A;
+}
+
+trait OneWithLifetime<'a, T> {
+  type A;
+}
+
+trait Three<T, U, V> {
+  type A;
+  type B;
+  type C;
+}
+
+trait ThreeWithLifetime<'a, 'b, 'c, T, U, V> {
+  type A;
+  type B;
+  type C;
+}
+
+struct A<T, M: One<A=(), T>> { //~ ERROR associated type bindings must be declared after generic parameters
+    m: M,
+    t: T,
+}
+
+
+struct Al<'a, T, M: OneWithLifetime<A=(), T, 'a>> {
+//~^ ERROR associated type bindings must be declared after generic parameters
+//~^^ ERROR lifetime arguments must be declared prior to type arguments
+    m: M,
+    t: &'a T,
+}
+
+struct B<T, U, V, M: Three<A=(), B=(), C=(), T, U, V>> { //~ ERROR associated type bindings must be declared after generic parameters
+    m: M,
+    t: T,
+    u: U,
+    v: V,
+}
+
+struct Bl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<A=(), B=(), C=(), T, U, V, 'a, 'b, 'c>> {
+//~^ ERROR associated type bindings must be declared after generic parameters
+//~^^ ERROR lifetime arguments must be declared prior to type arguments
+    m: M,
+    t: &'a T,
+    u: &'b U,
+    v: &'c V,
+}
+
+struct C<T, U, V, M: Three<T, A=(), B=(), C=(), U, V>> { //~ ERROR associated type bindings must be declared after generic parameters
+    m: M,
+    t: T,
+    u: U,
+    v: V,
+}
+
+struct Cl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<T, 'a, A=(), B=(), C=(), U, 'b, V, 'c>> {
+//~^ ERROR associated type bindings must be declared after generic parameters
+//~^^ ERROR lifetime arguments must be declared prior to type arguments
+    m: M,
+    t: &'a T,
+    u: &'b U,
+    v: &'c V,
+}
+
+struct D<T, U, V, M: Three<T, A=(), B=(), U, C=(), V>> { //~ ERROR associated type bindings must be declared after generic parameters
+    m: M,
+    t: T,
+    u: U,
+    v: V,
+}
+
+struct Dl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<T, 'a, A=(), B=(), U, 'b, C=(), V, 'c>> {
+//~^ ERROR associated type bindings must be declared after generic parameters
+//~^^ ERROR lifetime arguments must be declared prior to type arguments
+    m: M,
+    t: &'a T,
+    u: &'b U,
+    v: &'c V,
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/suggest-move-types.stderr b/src/test/ui/suggestions/suggest-move-types.stderr
new file mode 100644
index 0000000..552fb78
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-move-types.stderr
@@ -0,0 +1,102 @@
+error: associated type bindings must be declared after generic parameters
+  --> $DIR/suggest-move-types.rs:28:20
+   |
+LL | struct A<T, M: One<A=(), T>> {
+   |                    ----^^^
+   |                    |
+   |                    this associated type binding should be moved after the generic parameters
+
+error: associated type bindings must be declared after generic parameters
+  --> $DIR/suggest-move-types.rs:34:37
+   |
+LL | struct Al<'a, T, M: OneWithLifetime<A=(), T, 'a>> {
+   |                                     ----^^^^^^^
+   |                                     |
+   |                                     this associated type binding should be moved after the generic parameters
+
+error: associated type bindings must be declared after generic parameters
+  --> $DIR/suggest-move-types.rs:41:28
+   |
+LL | struct B<T, U, V, M: Three<A=(), B=(), C=(), T, U, V>> {
+   |                            ----^^----^^----^^^^^^^^^
+   |                            |     |     |
+   |                            |     |     this associated type binding should be moved after the generic parameters
+   |                            |     this associated type binding should be moved after the generic parameters
+   |                            this associated type binding should be moved after the generic parameters
+
+error: associated type bindings must be declared after generic parameters
+  --> $DIR/suggest-move-types.rs:48:53
+   |
+LL | struct Bl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<A=(), B=(), C=(), T, U, V, 'a, 'b, 'c>> {
+   |                                                     ----^^----^^----^^^^^^^^^^^^^^^^^^^^^
+   |                                                     |     |     |
+   |                                                     |     |     this associated type binding should be moved after the generic parameters
+   |                                                     |     this associated type binding should be moved after the generic parameters
+   |                                                     this associated type binding should be moved after the generic parameters
+
+error: associated type bindings must be declared after generic parameters
+  --> $DIR/suggest-move-types.rs:57:28
+   |
+LL | struct C<T, U, V, M: Three<T, A=(), B=(), C=(), U, V>> {
+   |                            ^^^----^^----^^----^^^^^^
+   |                               |     |     |
+   |                               |     |     this associated type binding should be moved after the generic parameters
+   |                               |     this associated type binding should be moved after the generic parameters
+   |                               this associated type binding should be moved after the generic parameters
+
+error: associated type bindings must be declared after generic parameters
+  --> $DIR/suggest-move-types.rs:64:53
+   |
+LL | struct Cl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<T, 'a, A=(), B=(), C=(), U, 'b, V, 'c>> {
+   |                                                     ^^^^^^^----^^----^^----^^^^^^^^^^^^^^
+   |                                                            |     |     |
+   |                                                            |     |     this associated type binding should be moved after the generic parameters
+   |                                                            |     this associated type binding should be moved after the generic parameters
+   |                                                            this associated type binding should be moved after the generic parameters
+
+error: associated type bindings must be declared after generic parameters
+  --> $DIR/suggest-move-types.rs:73:28
+   |
+LL | struct D<T, U, V, M: Three<T, A=(), B=(), U, C=(), V>> {
+   |                            ^^^----^^----^^^^^----^^^
+   |                               |     |        |
+   |                               |     |        this associated type binding should be moved after the generic parameters
+   |                               |     this associated type binding should be moved after the generic parameters
+   |                               this associated type binding should be moved after the generic parameters
+
+error: associated type bindings must be declared after generic parameters
+  --> $DIR/suggest-move-types.rs:80:53
+   |
+LL | struct Dl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<T, 'a, A=(), B=(), U, 'b, C=(), V, 'c>> {
+   |                                                     ^^^^^^^----^^----^^^^^^^^^----^^^^^^^
+   |                                                            |     |            |
+   |                                                            |     |            this associated type binding should be moved after the generic parameters
+   |                                                            |     this associated type binding should be moved after the generic parameters
+   |                                                            this associated type binding should be moved after the generic parameters
+
+error: lifetime arguments must be declared prior to type arguments
+  --> $DIR/suggest-move-types.rs:34:46
+   |
+LL | struct Al<'a, T, M: OneWithLifetime<A=(), T, 'a>> {
+   |                                              ^^
+
+error: lifetime arguments must be declared prior to type arguments
+  --> $DIR/suggest-move-types.rs:48:80
+   |
+LL | struct Bl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<A=(), B=(), C=(), T, U, V, 'a, 'b, 'c>> {
+   |                                                                                ^^  ^^  ^^
+
+error: lifetime arguments must be declared prior to type arguments
+  --> $DIR/suggest-move-types.rs:64:56
+   |
+LL | struct Cl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<T, 'a, A=(), B=(), C=(), U, 'b, V, 'c>> {
+   |                                                        ^^                       ^^     ^^
+
+error: lifetime arguments must be declared prior to type arguments
+  --> $DIR/suggest-move-types.rs:80:56
+   |
+LL | struct Dl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<T, 'a, A=(), B=(), U, 'b, C=(), V, 'c>> {
+   |                                                        ^^                 ^^           ^^
+
+error: aborting due to 12 previous errors
+
diff --git a/src/test/ui/suggestions/suggest-on-bare-closure-call.rs b/src/test/ui/suggestions/suggest-on-bare-closure-call.rs
new file mode 100644
index 0000000..355708c
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-on-bare-closure-call.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let _ = ||{}();
+    //~^ ERROR expected function, found `()`
+}
diff --git a/src/test/ui/suggestions/suggest-on-bare-closure-call.stderr b/src/test/ui/suggestions/suggest-on-bare-closure-call.stderr
new file mode 100644
index 0000000..17001e3
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-on-bare-closure-call.stderr
@@ -0,0 +1,15 @@
+error[E0618]: expected function, found `()`
+  --> $DIR/suggest-on-bare-closure-call.rs:2:15
+   |
+LL |     let _ = ||{}();
+   |               ^^--
+   |               |
+   |               call expression requires function
+help: if you meant to create this closure and immediately call it, surround the closure with parenthesis
+   |
+LL |     let _ = (||{})();
+   |             ^    ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0618`.
diff --git a/src/test/ui/suggestions/suggest-private-fields.rs b/src/test/ui/suggestions/suggest-private-fields.rs
new file mode 100644
index 0000000..347c8ae
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-private-fields.rs
@@ -0,0 +1,27 @@
+// aux-build:struct_field_privacy.rs
+
+extern crate struct_field_privacy as xc;
+
+use xc::B;
+
+struct A {
+    pub a: u32,
+    b: u32,
+}
+
+fn main () {
+    // external crate struct
+    let k = B {
+        aa: 20,
+        //~^ ERROR struct `xc::B` has no field named `aa`
+        bb: 20,
+        //~^ ERROR struct `xc::B` has no field named `bb`
+    };
+    // local crate struct
+    let l = A {
+        aa: 20,
+        //~^ ERROR struct `A` has no field named `aa`
+        bb: 20,
+        //~^ ERROR struct `A` has no field named `bb`
+    };
+}
diff --git a/src/test/ui/suggestions/suggest-private-fields.stderr b/src/test/ui/suggestions/suggest-private-fields.stderr
new file mode 100644
index 0000000..524558e
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-private-fields.stderr
@@ -0,0 +1,29 @@
+error[E0560]: struct `xc::B` has no field named `aa`
+  --> $DIR/suggest-private-fields.rs:15:9
+   |
+LL |         aa: 20,
+   |         ^^ help: a field with a similar name exists: `a`
+
+error[E0560]: struct `xc::B` has no field named `bb`
+  --> $DIR/suggest-private-fields.rs:17:9
+   |
+LL |         bb: 20,
+   |         ^^ `xc::B` does not have this field
+   |
+   = note: available fields are: `a`
+
+error[E0560]: struct `A` has no field named `aa`
+  --> $DIR/suggest-private-fields.rs:22:9
+   |
+LL |         aa: 20,
+   |         ^^ help: a field with a similar name exists: `a`
+
+error[E0560]: struct `A` has no field named `bb`
+  --> $DIR/suggest-private-fields.rs:24:9
+   |
+LL |         bb: 20,
+   |         ^^ help: a field with a similar name exists: `b`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0560`.
diff --git a/src/test/ui/suggestions/suggest-ref-mut.rs b/src/test/ui/suggestions/suggest-ref-mut.rs
new file mode 100644
index 0000000..b4a6fa3
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-ref-mut.rs
@@ -0,0 +1,32 @@
+#![feature(nll)]
+
+struct X(usize);
+
+impl X {
+    fn zap(&self) {
+        //~^ HELP
+        //~| SUGGESTION &mut self
+        self.0 = 32;
+        //~^ ERROR
+    }
+}
+
+fn main() {
+    let ref foo = 16;
+    //~^ HELP
+    //~| SUGGESTION ref mut foo
+    *foo = 32;
+    //~^ ERROR
+    if let Some(ref bar) = Some(16) {
+        //~^ HELP
+        //~| SUGGESTION ref mut bar
+        *bar = 32;
+        //~^ ERROR
+    }
+    match 16 {
+        ref quo => { *quo = 32; },
+        //~^ ERROR
+        //~| HELP
+        //~| SUGGESTION ref mut quo
+    }
+}
diff --git a/src/test/ui/suggestions/suggest-ref-mut.stderr b/src/test/ui/suggestions/suggest-ref-mut.stderr
new file mode 100644
index 0000000..9f00967
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-ref-mut.stderr
@@ -0,0 +1,38 @@
+error[E0594]: cannot assign to `self.0` which is behind a `&` reference
+  --> $DIR/suggest-ref-mut.rs:9:9
+   |
+LL |     fn zap(&self) {
+   |            ----- help: consider changing this to be a mutable reference: `&mut self`
+...
+LL |         self.0 = 32;
+   |         ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be written
+
+error[E0594]: cannot assign to `*foo` which is behind a `&` reference
+  --> $DIR/suggest-ref-mut.rs:18:5
+   |
+LL |     let ref foo = 16;
+   |         ------- help: consider changing this to be a mutable reference: `ref mut foo`
+...
+LL |     *foo = 32;
+   |     ^^^^^^^^^ `foo` is a `&` reference, so the data it refers to cannot be written
+
+error[E0594]: cannot assign to `*bar` which is behind a `&` reference
+  --> $DIR/suggest-ref-mut.rs:23:9
+   |
+LL |     if let Some(ref bar) = Some(16) {
+   |                 ------- help: consider changing this to be a mutable reference: `ref mut bar`
+...
+LL |         *bar = 32;
+   |         ^^^^^^^^^ `bar` is a `&` reference, so the data it refers to cannot be written
+
+error[E0594]: cannot assign to `*quo` which is behind a `&` reference
+  --> $DIR/suggest-ref-mut.rs:27:22
+   |
+LL |         ref quo => { *quo = 32; },
+   |         -------      ^^^^^^^^^ `quo` is a `&` reference, so the data it refers to cannot be written
+   |         |
+   |         help: consider changing this to be a mutable reference: `ref mut quo`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/suggestions/suggest-remove-refs-1.rs b/src/test/ui/suggestions/suggest-remove-refs-1.rs
new file mode 100644
index 0000000..792cd6c
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-remove-refs-1.rs
@@ -0,0 +1,8 @@
+fn main() {
+    let v = vec![0, 1, 2, 3];
+
+    for (i, n) in &v.iter().enumerate() {
+        //~^ ERROR `&std::iter::Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator
+        println!("{}", i);
+    }
+}
diff --git a/src/test/ui/suggestions/suggest-remove-refs-1.stderr b/src/test/ui/suggestions/suggest-remove-refs-1.stderr
new file mode 100644
index 0000000..bfc313c
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-remove-refs-1.stderr
@@ -0,0 +1,15 @@
+error[E0277]: `&std::iter::Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator
+  --> $DIR/suggest-remove-refs-1.rs:4:19
+   |
+LL |     for (i, n) in &v.iter().enumerate() {
+   |                   -^^^^^^^^^^^^^^^^^^^^
+   |                   |
+   |                   `&std::iter::Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator
+   |                   help: consider removing 1 leading `&`-references
+   |
+   = help: the trait `std::iter::Iterator` is not implemented for `&std::iter::Enumerate<std::slice::Iter<'_, {integer}>>`
+   = note: required by `std::iter::IntoIterator::into_iter`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/suggestions/suggest-remove-refs-2.rs b/src/test/ui/suggestions/suggest-remove-refs-2.rs
new file mode 100644
index 0000000..52d9401
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-remove-refs-2.rs
@@ -0,0 +1,8 @@
+fn main() {
+    let v = vec![0, 1, 2, 3];
+
+    for (i, n) in & & & & &v.iter().enumerate() {
+        //~^ ERROR `&&&&&std::iter::Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator
+        println!("{}", i);
+    }
+}
diff --git a/src/test/ui/suggestions/suggest-remove-refs-2.stderr b/src/test/ui/suggestions/suggest-remove-refs-2.stderr
new file mode 100644
index 0000000..fe1b0f1
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-remove-refs-2.stderr
@@ -0,0 +1,15 @@
+error[E0277]: `&&&&&std::iter::Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator
+  --> $DIR/suggest-remove-refs-2.rs:4:19
+   |
+LL |     for (i, n) in & & & & &v.iter().enumerate() {
+   |                   ---------^^^^^^^^^^^^^^^^^^^^
+   |                   |
+   |                   `&&&&&std::iter::Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator
+   |                   help: consider removing 5 leading `&`-references
+   |
+   = help: the trait `std::iter::Iterator` is not implemented for `&&&&&std::iter::Enumerate<std::slice::Iter<'_, {integer}>>`
+   = note: required by `std::iter::IntoIterator::into_iter`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/suggestions/suggest-remove-refs-3.rs b/src/test/ui/suggestions/suggest-remove-refs-3.rs
new file mode 100644
index 0000000..981924d
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-remove-refs-3.rs
@@ -0,0 +1,11 @@
+fn main() {
+    let v = vec![0, 1, 2, 3];
+
+    for (i, n) in & & &
+        & &v
+        .iter()
+        .enumerate() {
+        //~^^^^ ERROR `&&&&&std::iter::Enumerate<std::slice::Iter<'_, {integer}>>` is not an
+        println!("{}", i);
+    }
+}
diff --git a/src/test/ui/suggestions/suggest-remove-refs-3.stderr b/src/test/ui/suggestions/suggest-remove-refs-3.stderr
new file mode 100644
index 0000000..a6c16e1
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-remove-refs-3.stderr
@@ -0,0 +1,19 @@
+error[E0277]: `&&&&&std::iter::Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator
+  --> $DIR/suggest-remove-refs-3.rs:4:19
+   |
+LL |        for (i, n) in & & &
+   |   ___________________^
+   |  |___________________|
+   | ||
+LL | ||         & &v
+   | ||___________- help: consider removing 5 leading `&`-references
+LL | |          .iter()
+LL | |          .enumerate() {
+   | |_____________________^ `&&&&&std::iter::Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator
+   |
+   = help: the trait `std::iter::Iterator` is not implemented for `&&&&&std::iter::Enumerate<std::slice::Iter<'_, {integer}>>`
+   = note: required by `std::iter::IntoIterator::into_iter`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/suggestions/suggest-variants.rs b/src/test/ui/suggestions/suggest-variants.rs
new file mode 100644
index 0000000..6d6e280
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-variants.rs
@@ -0,0 +1,15 @@
+#[derive(Debug)]
+enum Shape {
+  Square { size: i32 },
+  Circle { radius: i32 },
+}
+
+struct S {
+  x: usize,
+}
+
+fn main() {
+    println!("My shape is {:?}", Shape::Squareee { size: 5});  //~ ERROR no variant `Squareee`
+    println!("My shape is {:?}", Shape::Circl { size: 5}); //~ ERROR no variant `Circl`
+    println!("My shape is {:?}", Shape::Rombus{ size: 5}); //~ ERROR no variant `Rombus`
+}
diff --git a/src/test/ui/suggestions/suggest-variants.stderr b/src/test/ui/suggestions/suggest-variants.stderr
new file mode 100644
index 0000000..08ae68e
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-variants.stderr
@@ -0,0 +1,20 @@
+error: no variant `Squareee` on enum `Shape`
+  --> $DIR/suggest-variants.rs:12:34
+   |
+LL |     println!("My shape is {:?}", Shape::Squareee { size: 5});
+   |                                  ^^^^^^^^^^^^^^^ help: did you mean: `Shape::Square`
+
+error: no variant `Circl` on enum `Shape`
+  --> $DIR/suggest-variants.rs:13:34
+   |
+LL |     println!("My shape is {:?}", Shape::Circl { size: 5});
+   |                                  ^^^^^^^^^^^^ help: did you mean: `Shape::Circle`
+
+error: no variant `Rombus` on enum `Shape`
+  --> $DIR/suggest-variants.rs:14:34
+   |
+LL |     println!("My shape is {:?}", Shape::Rombus{ size: 5});
+   |                                  ^^^^^^^^^^^^^ unknown variant
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/suggestions/type-ascription-instead-of-let.rs b/src/test/ui/suggestions/type-ascription-instead-of-let.rs
new file mode 100644
index 0000000..0e1c307
--- /dev/null
+++ b/src/test/ui/suggestions/type-ascription-instead-of-let.rs
@@ -0,0 +1,10 @@
+fn fun(x: i32) -> i32 { x }
+
+fn main() {
+    let closure_annotated = |value: i32| -> i32 {
+        temp: i32 = fun(5i32);
+        //~^ ERROR cannot find value `temp` in this scope
+        temp + value + 1
+        //~^ ERROR cannot find value `temp` in this scope
+    };
+}
diff --git a/src/test/ui/suggestions/type-ascription-instead-of-let.stderr b/src/test/ui/suggestions/type-ascription-instead-of-let.stderr
new file mode 100644
index 0000000..92e4b57
--- /dev/null
+++ b/src/test/ui/suggestions/type-ascription-instead-of-let.stderr
@@ -0,0 +1,18 @@
+error[E0425]: cannot find value `temp` in this scope
+  --> $DIR/type-ascription-instead-of-let.rs:5:9
+   |
+LL |         temp: i32 = fun(5i32);
+   |         ^^^^
+   |         |
+   |         not found in this scope
+   |         help: maybe you meant to write an assignment here: `let temp`
+
+error[E0425]: cannot find value `temp` in this scope
+  --> $DIR/type-ascription-instead-of-let.rs:7:9
+   |
+LL |         temp + value + 1
+   |         ^^^^ not found in this scope
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/suggestions/type-ascription-instead-of-method.rs b/src/test/ui/suggestions/type-ascription-instead-of-method.rs
new file mode 100644
index 0000000..361729d
--- /dev/null
+++ b/src/test/ui/suggestions/type-ascription-instead-of-method.rs
@@ -0,0 +1,4 @@
+fn main() {
+    Box:new("foo".to_string())
+    //~^ ERROR expected type, found
+}
diff --git a/src/test/ui/suggestions/type-ascription-instead-of-method.stderr b/src/test/ui/suggestions/type-ascription-instead-of-method.stderr
new file mode 100644
index 0000000..15ec087b
--- /dev/null
+++ b/src/test/ui/suggestions/type-ascription-instead-of-method.stderr
@@ -0,0 +1,10 @@
+error: expected type, found `"foo"`
+  --> $DIR/type-ascription-instead-of-method.rs:2:13
+   |
+LL |     Box:new("foo".to_string())
+   |        -    ^^^^^ expecting a type here because of type ascription
+   |        |
+   |        help: maybe you meant to write a path separator here: `::`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/suggestions/type-ascription-instead-of-path.rs b/src/test/ui/suggestions/type-ascription-instead-of-path.rs
new file mode 100644
index 0000000..4c0fe6d
--- /dev/null
+++ b/src/test/ui/suggestions/type-ascription-instead-of-path.rs
@@ -0,0 +1,5 @@
+fn main() {
+    std:io::stdin();
+    //~^ ERROR failed to resolve: use of undeclared type or module `io`
+    //~| ERROR expected value, found module
+}
diff --git a/src/test/ui/suggestions/type-ascription-instead-of-path.stderr b/src/test/ui/suggestions/type-ascription-instead-of-path.stderr
new file mode 100644
index 0000000..1beb822
--- /dev/null
+++ b/src/test/ui/suggestions/type-ascription-instead-of-path.stderr
@@ -0,0 +1,18 @@
+error[E0433]: failed to resolve: use of undeclared type or module `io`
+  --> $DIR/type-ascription-instead-of-path.rs:2:9
+   |
+LL |     std:io::stdin();
+   |         ^^ use of undeclared type or module `io`
+
+error[E0423]: expected value, found module `std`
+  --> $DIR/type-ascription-instead-of-path.rs:2:5
+   |
+LL |     std:io::stdin();
+   |     ^^^- help: maybe you meant to write a path separator here: `::`
+   |     |
+   |     not a value
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0423, E0433.
+For more information about an error, try `rustc --explain E0423`.
diff --git a/src/test/ui/suggestions/type-ascription-instead-of-variant.rs b/src/test/ui/suggestions/type-ascription-instead-of-variant.rs
new file mode 100644
index 0000000..b90867f
--- /dev/null
+++ b/src/test/ui/suggestions/type-ascription-instead-of-variant.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let _ = Option:Some("");
+    //~^ ERROR expected type, found
+}
diff --git a/src/test/ui/suggestions/type-ascription-instead-of-variant.stderr b/src/test/ui/suggestions/type-ascription-instead-of-variant.stderr
new file mode 100644
index 0000000..5719a66
--- /dev/null
+++ b/src/test/ui/suggestions/type-ascription-instead-of-variant.stderr
@@ -0,0 +1,10 @@
+error: expected type, found `""`
+  --> $DIR/type-ascription-instead-of-variant.rs:2:25
+   |
+LL |     let _ = Option:Some("");
+   |                   -     ^^ expecting a type here because of type ascription
+   |                   |
+   |                   help: maybe you meant to write a path separator here: `::`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/suggestions/type-mismatch-struct-field-shorthand-2.rs b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand-2.rs
new file mode 100644
index 0000000..2ce1222
--- /dev/null
+++ b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand-2.rs
@@ -0,0 +1,9 @@
+struct RGB { r: f64, g: f64, b: f64 }
+
+fn main() {
+    let (r, g, c): (f32, f32, f32) = (0., 0., 0.);
+    let _ = RGB { r, g, c };
+    //~^ ERROR mismatched types
+    //~| ERROR mismatched types
+    //~| ERROR struct `RGB` has no field named `c`
+}
diff --git a/src/test/ui/suggestions/type-mismatch-struct-field-shorthand-2.stderr b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand-2.stderr
new file mode 100644
index 0000000..d0f9e1f
--- /dev/null
+++ b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand-2.stderr
@@ -0,0 +1,30 @@
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch-struct-field-shorthand-2.rs:5:19
+   |
+LL |     let _ = RGB { r, g, c };
+   |                   ^ expected f64, found f32
+help: you can cast an `f32` to `f64` in a lossless way
+   |
+LL |     let _ = RGB { r: r.into(), g, c };
+   |                   ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch-struct-field-shorthand-2.rs:5:22
+   |
+LL |     let _ = RGB { r, g, c };
+   |                      ^ expected f64, found f32
+help: you can cast an `f32` to `f64` in a lossless way
+   |
+LL |     let _ = RGB { r, g: g.into(), c };
+   |                      ^^^^^^^^^^^
+
+error[E0560]: struct `RGB` has no field named `c`
+  --> $DIR/type-mismatch-struct-field-shorthand-2.rs:5:25
+   |
+LL |     let _ = RGB { r, g, c };
+   |                         ^ help: a field with a similar name exists: `b`
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0308, E0560.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.fixed b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.fixed
new file mode 100644
index 0000000..91758c0
--- /dev/null
+++ b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.fixed
@@ -0,0 +1,12 @@
+// run-rustfix
+#![allow(dead_code)]
+
+struct RGB { r: f64, g: f64, b: f64 }
+
+fn main() {
+    let (r, g, b): (f32, f32, f32) = (0., 0., 0.);
+    let _ = RGB { r: r.into(), g: g.into(), b: b.into() };
+    //~^ ERROR mismatched types
+    //~| ERROR mismatched types
+    //~| ERROR mismatched types
+}
diff --git a/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.rs b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.rs
new file mode 100644
index 0000000..9d3a17a
--- /dev/null
+++ b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.rs
@@ -0,0 +1,12 @@
+// run-rustfix
+#![allow(dead_code)]
+
+struct RGB { r: f64, g: f64, b: f64 }
+
+fn main() {
+    let (r, g, b): (f32, f32, f32) = (0., 0., 0.);
+    let _ = RGB { r, g, b };
+    //~^ ERROR mismatched types
+    //~| ERROR mismatched types
+    //~| ERROR mismatched types
+}
diff --git a/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.stderr b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.stderr
new file mode 100644
index 0000000..6bc16ba
--- /dev/null
+++ b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.stderr
@@ -0,0 +1,33 @@
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch-struct-field-shorthand.rs:8:19
+   |
+LL |     let _ = RGB { r, g, b };
+   |                   ^ expected f64, found f32
+help: you can cast an `f32` to `f64` in a lossless way
+   |
+LL |     let _ = RGB { r: r.into(), g, b };
+   |                   ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch-struct-field-shorthand.rs:8:22
+   |
+LL |     let _ = RGB { r, g, b };
+   |                      ^ expected f64, found f32
+help: you can cast an `f32` to `f64` in a lossless way
+   |
+LL |     let _ = RGB { r, g: g.into(), b };
+   |                      ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch-struct-field-shorthand.rs:8:25
+   |
+LL |     let _ = RGB { r, g, b };
+   |                         ^ expected f64, found f32
+help: you can cast an `f32` to `f64` in a lossless way
+   |
+LL |     let _ = RGB { r, g, b: b.into() };
+   |                         ^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/suggestions/unused-closure-argument.rs b/src/test/ui/suggestions/unused-closure-argument.rs
new file mode 100644
index 0000000..677003e
--- /dev/null
+++ b/src/test/ui/suggestions/unused-closure-argument.rs
@@ -0,0 +1,20 @@
+#![deny(unused_variables)]
+
+struct Point {
+    x: i32,
+    y: i32,
+}
+
+fn main() {
+    let points = vec!(Point { x: 1, y: 2 }, Point { x: 3, y: 4 });
+
+    let _: i32 = points.iter()
+        .map(|Point { x, y }| y)
+        //~^ ERROR unused variable
+        .sum();
+
+    let _: i32 = points.iter()
+        .map(|x| 4)
+        //~^ ERROR unused variable
+        .sum();
+}
diff --git a/src/test/ui/suggestions/unused-closure-argument.stderr b/src/test/ui/suggestions/unused-closure-argument.stderr
new file mode 100644
index 0000000..5cfdd79
--- /dev/null
+++ b/src/test/ui/suggestions/unused-closure-argument.stderr
@@ -0,0 +1,20 @@
+error: unused variable: `x`
+  --> $DIR/unused-closure-argument.rs:12:23
+   |
+LL |         .map(|Point { x, y }| y)
+   |                       ^ help: try ignoring the field: `x: _`
+   |
+note: lint level defined here
+  --> $DIR/unused-closure-argument.rs:1:9
+   |
+LL | #![deny(unused_variables)]
+   |         ^^^^^^^^^^^^^^^^
+
+error: unused variable: `x`
+  --> $DIR/unused-closure-argument.rs:17:15
+   |
+LL |         .map(|x| 4)
+   |               ^ help: consider prefixing with an underscore: `_x`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/suggestions/use-type-argument-instead-of-assoc-type.rs b/src/test/ui/suggestions/use-type-argument-instead-of-assoc-type.rs
new file mode 100644
index 0000000..a3cc53e
--- /dev/null
+++ b/src/test/ui/suggestions/use-type-argument-instead-of-assoc-type.rs
@@ -0,0 +1,13 @@
+pub trait T<X, Y> {
+    type A;
+    type B;
+    type C;
+}
+pub struct Foo {
+    i: Box<T<usize, usize, usize, usize, B=usize>>,
+    //~^ ERROR must be specified
+    //~| ERROR wrong number of type arguments
+}
+
+
+fn main() {}
diff --git a/src/test/ui/suggestions/use-type-argument-instead-of-assoc-type.stderr b/src/test/ui/suggestions/use-type-argument-instead-of-assoc-type.stderr
new file mode 100644
index 0000000..16e9fa9
--- /dev/null
+++ b/src/test/ui/suggestions/use-type-argument-instead-of-assoc-type.stderr
@@ -0,0 +1,31 @@
+error[E0107]: wrong number of type arguments: expected 2, found 4
+  --> $DIR/use-type-argument-instead-of-assoc-type.rs:7:28
+   |
+LL |     i: Box<T<usize, usize, usize, usize, B=usize>>,
+   |                            ^^^^^  ^^^^^ unexpected type argument
+   |                            |
+   |                            unexpected type argument
+
+error[E0191]: the value of the associated types `A` (from the trait `T`), `C` (from the trait `T`) must be specified
+  --> $DIR/use-type-argument-instead-of-assoc-type.rs:7:12
+   |
+LL |     type A;
+   |     ------- `A` defined here
+LL |     type B;
+LL |     type C;
+   |     ------- `C` defined here
+...
+LL |     i: Box<T<usize, usize, usize, usize, B=usize>>,
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |            |
+   |            associated type `A` must be specified
+   |            associated type `C` must be specified
+help: if you meant to specify the associated types, write
+   |
+LL |     i: Box<T<usize, usize, A = usize, C = usize, B=usize>>,
+   |                            ^^^^^^^^^  ^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0107, E0191.
+For more information about an error, try `rustc --explain E0107`.
diff --git a/src/test/ui/super-at-top-level.rs b/src/test/ui/super-at-top-level.rs
new file mode 100644
index 0000000..41360df
--- /dev/null
+++ b/src/test/ui/super-at-top-level.rs
@@ -0,0 +1,4 @@
+use super::f; //~ ERROR there are too many initial `super`s
+
+fn main() {
+}
diff --git a/src/test/ui/super-at-top-level.stderr b/src/test/ui/super-at-top-level.stderr
new file mode 100644
index 0000000..d04ce38
--- /dev/null
+++ b/src/test/ui/super-at-top-level.stderr
@@ -0,0 +1,9 @@
+error[E0433]: failed to resolve: there are too many initial `super`s.
+  --> $DIR/super-at-top-level.rs:1:5
+   |
+LL | use super::f;
+   |     ^^^^^ there are too many initial `super`s.
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/suppressed-error.rs b/src/test/ui/suppressed-error.rs
new file mode 100644
index 0000000..cf3dce8
--- /dev/null
+++ b/src/test/ui/suppressed-error.rs
@@ -0,0 +1,8 @@
+fn main() {
+    let (x, y) = ();
+//~^ ERROR mismatched types
+//~| expected type `()`
+//~| found type `(_, _)`
+//~| expected (), found tuple
+    return x;
+}
diff --git a/src/test/ui/suppressed-error.stderr b/src/test/ui/suppressed-error.stderr
new file mode 100644
index 0000000..85e1deb
--- /dev/null
+++ b/src/test/ui/suppressed-error.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/suppressed-error.rs:2:9
+   |
+LL |     let (x, y) = ();
+   |         ^^^^^^ expected (), found tuple
+   |
+   = note: expected type `()`
+              found type `(_, _)`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/svh/auxiliary/svh-a-base.rs b/src/test/ui/svh/auxiliary/svh-a-base.rs
new file mode 100644
index 0000000..36b41fc
--- /dev/null
+++ b/src/test/ui/svh/auxiliary/svh-a-base.rs
@@ -0,0 +1,25 @@
+//! The `svh-a-*.rs` files are all deviations from the base file
+//! svh-a-base.rs with some difference (usually in `fn foo`) that
+//! should not affect the strict version hash (SVH) computation
+//! (#14132).
+
+#![crate_name = "a"]
+
+macro_rules! three {
+    () => { 3 }
+}
+
+pub trait U {}
+pub trait V {}
+impl U for () {}
+impl V for () {}
+
+static A_CONSTANT : isize = 2;
+
+pub fn foo<T:U>(_: isize) -> isize {
+    3
+}
+
+pub fn an_unused_name() -> isize {
+    4
+}
diff --git a/src/test/ui/svh/auxiliary/svh-a-change-lit.rs b/src/test/ui/svh/auxiliary/svh-a-change-lit.rs
new file mode 100644
index 0000000..c76f2c9
--- /dev/null
+++ b/src/test/ui/svh/auxiliary/svh-a-change-lit.rs
@@ -0,0 +1,25 @@
+//! The `svh-a-*.rs` files are all deviations from the base file
+//! svh-a-base.rs with some difference (usually in `fn foo`) that
+//! should not affect the strict version hash (SVH) computation
+//! (#14132).
+
+#![crate_name = "a"]
+
+macro_rules! three {
+    () => { 3 }
+}
+
+pub trait U {}
+pub trait V {}
+impl U for () {}
+impl V for () {}
+
+static A_CONSTANT : isize = 2;
+
+pub fn foo<T:U>(_: isize) -> isize {
+    0
+}
+
+pub fn an_unused_name() -> isize {
+    4
+}
diff --git a/src/test/ui/svh/auxiliary/svh-a-change-significant-cfg.rs b/src/test/ui/svh/auxiliary/svh-a-change-significant-cfg.rs
new file mode 100644
index 0000000..37f59c9
--- /dev/null
+++ b/src/test/ui/svh/auxiliary/svh-a-change-significant-cfg.rs
@@ -0,0 +1,27 @@
+//! The `svh-a-*.rs` files are all deviations from the base file
+//! svh-a-base.rs with some difference (usually in `fn foo`) that
+//! should not affect the strict version hash (SVH) computation
+//! (#14132).
+
+#![crate_name = "a"]
+
+macro_rules! three {
+    () => { 3 }
+}
+
+pub trait U {}
+pub trait V {}
+impl U for () {}
+impl V for () {}
+
+static A_CONSTANT : isize = 2;
+
+#[cfg(some_flag)]
+pub fn foo<T:U>(_: isize) -> isize {
+    3
+}
+
+#[cfg(not(some_flag))]
+pub fn an_unused_name() -> isize {
+    4
+}
diff --git a/src/test/ui/svh/auxiliary/svh-a-change-trait-bound.rs b/src/test/ui/svh/auxiliary/svh-a-change-trait-bound.rs
new file mode 100644
index 0000000..be24b1e
--- /dev/null
+++ b/src/test/ui/svh/auxiliary/svh-a-change-trait-bound.rs
@@ -0,0 +1,25 @@
+//! The `svh-a-*.rs` files are all deviations from the base file
+//! svh-a-base.rs with some difference (usually in `fn foo`) that
+//! should not affect the strict version hash (SVH) computation
+//! (#14132).
+
+#![crate_name = "a"]
+
+macro_rules! three {
+    () => { 3 }
+}
+
+pub trait U {}
+pub trait V {}
+impl U for () {}
+impl V for () {}
+
+static A_CONSTANT : isize = 2;
+
+pub fn foo<T:V>(_: isize) -> isize {
+    3
+}
+
+pub fn an_unused_name() -> isize {
+    4
+}
diff --git a/src/test/ui/svh/auxiliary/svh-a-change-type-arg.rs b/src/test/ui/svh/auxiliary/svh-a-change-type-arg.rs
new file mode 100644
index 0000000..3fe1022
--- /dev/null
+++ b/src/test/ui/svh/auxiliary/svh-a-change-type-arg.rs
@@ -0,0 +1,25 @@
+//! The `svh-a-*.rs` files are all deviations from the base file
+//! svh-a-base.rs with some difference (usually in `fn foo`) that
+//! should not affect the strict version hash (SVH) computation
+//! (#14132).
+
+#![crate_name = "a"]
+
+macro_rules! three {
+    () => { 3 }
+}
+
+pub trait U {}
+pub trait V {}
+impl U for () {}
+impl V for () {}
+
+static A_CONSTANT : isize = 2;
+
+pub fn foo<T:U>(_: i32) -> isize {
+    3
+}
+
+pub fn an_unused_name() -> isize {
+    4
+}
diff --git a/src/test/ui/svh/auxiliary/svh-a-change-type-ret.rs b/src/test/ui/svh/auxiliary/svh-a-change-type-ret.rs
new file mode 100644
index 0000000..06e4fad
--- /dev/null
+++ b/src/test/ui/svh/auxiliary/svh-a-change-type-ret.rs
@@ -0,0 +1,25 @@
+//! The `svh-a-*.rs` files are all deviations from the base file
+//! svh-a-base.rs with some difference (usually in `fn foo`) that
+//! should not affect the strict version hash (SVH) computation
+//! (#14132).
+
+#![crate_name = "a"]
+
+macro_rules! three {
+    () => { 3 }
+}
+
+pub trait U {}
+pub trait V {}
+impl U for () {}
+impl V for () {}
+
+static A_CONSTANT : isize = 2;
+
+pub fn foo<T:U>(_: isize) -> i64 {
+    3
+}
+
+pub fn an_unused_name() -> i32 {
+    4
+}
diff --git a/src/test/ui/svh/auxiliary/svh-a-change-type-static.rs b/src/test/ui/svh/auxiliary/svh-a-change-type-static.rs
new file mode 100644
index 0000000..440cb32
--- /dev/null
+++ b/src/test/ui/svh/auxiliary/svh-a-change-type-static.rs
@@ -0,0 +1,25 @@
+//! The `svh-a-*.rs` files are all deviations from the base file
+//! svh-a-base.rs with some difference (usually in `fn foo`) that
+//! should not affect the strict version hash (SVH) computation
+//! (#14132).
+
+#![crate_name = "a"]
+
+macro_rules! three {
+    () => { 3 }
+}
+
+pub trait U {}
+pub trait V {}
+impl U for () {}
+impl V for () {}
+
+static A_CONSTANT : i32 = 2;
+
+pub fn foo<T:U>(_: isize) -> isize {
+    3
+}
+
+pub fn an_unused_name() -> isize {
+    4
+}
diff --git a/src/test/ui/svh/auxiliary/svh-b.rs b/src/test/ui/svh/auxiliary/svh-b.rs
new file mode 100644
index 0000000..57029f7
--- /dev/null
+++ b/src/test/ui/svh/auxiliary/svh-b.rs
@@ -0,0 +1,13 @@
+//! This is a client of the `a` crate defined in `svn-a-base.rs`. The
+//! rpass and cfail tests (such as `run-pass/svh-add-comment.rs`) use
+//! it by swapping in a different object code library crate built from
+//! some variant of `svn-a-base.rs`, and then we are checking if the
+//! compiler properly ignores or accepts the change, based on whether
+//! the change could affect the downstream crate content or not
+//! (#14132).
+
+#![crate_name = "b"]
+
+extern crate a;
+
+pub fn foo() { assert_eq!(a::foo::<()>(0), 3); }
diff --git a/src/test/ui/svh/auxiliary/svh-uta-base.rs b/src/test/ui/svh/auxiliary/svh-uta-base.rs
new file mode 100644
index 0000000..c138f1a
--- /dev/null
+++ b/src/test/ui/svh/auxiliary/svh-uta-base.rs
@@ -0,0 +1,22 @@
+//! "compile-fail/svh-uta-trait.rs" is checking that we detect a
+//! change from `use foo::TraitB` to use `foo::TraitB` in the hash
+//! (SVH) computation (#14132), since that will affect method
+//! resolution.
+//!
+//! This is the upstream crate.
+
+#![crate_name = "uta"]
+
+mod traits {
+    pub trait TraitA { fn val(&self) -> isize { 2 } }
+    pub trait TraitB { fn val(&self) -> isize { 3 } }
+}
+
+impl traits::TraitA for () {}
+impl traits::TraitB for () {}
+
+pub fn foo<T>(_: isize) -> isize {
+    use traits::TraitA;
+    let v = ();
+    v.val()
+}
diff --git a/src/test/ui/svh/auxiliary/svh-uta-change-use-trait.rs b/src/test/ui/svh/auxiliary/svh-uta-change-use-trait.rs
new file mode 100644
index 0000000..76a472b
--- /dev/null
+++ b/src/test/ui/svh/auxiliary/svh-uta-change-use-trait.rs
@@ -0,0 +1,22 @@
+//! "compile-fail/svh-uta-trait.rs" is checking that we detect a
+//! change from `use foo::TraitB` to use `foo::TraitB` in the hash
+//! (SVH) computation (#14132), since that will affect method
+//! resolution.
+//!
+//! This is the upstream crate.
+
+#![crate_name = "uta"]
+
+mod traits {
+    pub trait TraitA { fn val(&self) -> isize { 2 } }
+    pub trait TraitB { fn val(&self) -> isize { 3 } }
+}
+
+impl traits::TraitA for () {}
+impl traits::TraitB for () {}
+
+pub fn foo<T>(_: isize) -> isize {
+    use traits::TraitB;
+    let v = ();
+    v.val()
+}
diff --git a/src/test/ui/svh/auxiliary/svh-utb.rs b/src/test/ui/svh/auxiliary/svh-utb.rs
new file mode 100644
index 0000000..2f27e99
--- /dev/null
+++ b/src/test/ui/svh/auxiliary/svh-utb.rs
@@ -0,0 +1,12 @@
+//! "compile-fail/svh-uta-trait.rs" is checking that we detect a
+//! change from `use foo::TraitB` to use `foo::TraitB` in the hash
+//! (SVH) computation (#14132), since that will affect method
+//! resolution.
+//!
+//! This is the downstream crate.
+
+#![crate_name = "utb"]
+
+extern crate uta;
+
+pub fn foo() { assert_eq!(uta::foo::<()>(0), 3); }
diff --git a/src/test/ui/svh/svh-change-lit.rs b/src/test/ui/svh/svh-change-lit.rs
new file mode 100644
index 0000000..7d991cc
--- /dev/null
+++ b/src/test/ui/svh/svh-change-lit.rs
@@ -0,0 +1,14 @@
+// ignore-msvc FIXME #31306
+
+// note that these aux-build directives must be in this order
+// aux-build:svh-a-base.rs
+// aux-build:svh-b.rs
+// aux-build:svh-a-change-lit.rs
+// normalize-stderr-test: "(crate `(\w+)`:) .*" -> "$1 $$PATH_$2"
+
+extern crate a;
+extern crate b; //~ ERROR: found possibly newer version of crate `a` which `b` depends on
+
+fn main() {
+    b::foo()
+}
diff --git a/src/test/ui/svh/svh-change-lit.stderr b/src/test/ui/svh/svh-change-lit.stderr
new file mode 100644
index 0000000..1b15013
--- /dev/null
+++ b/src/test/ui/svh/svh-change-lit.stderr
@@ -0,0 +1,14 @@
+error[E0460]: found possibly newer version of crate `a` which `b` depends on
+  --> $DIR/svh-change-lit.rs:10:1
+   |
+LL | extern crate b;
+   | ^^^^^^^^^^^^^^^
+   |
+   = note: perhaps that crate needs to be recompiled?
+   = note: the following crate versions were found:
+           crate `a`: $PATH_a
+           crate `b`: $PATH_b
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0460`.
diff --git a/src/test/ui/svh/svh-change-significant-cfg.rs b/src/test/ui/svh/svh-change-significant-cfg.rs
new file mode 100644
index 0000000..8cf0d9c
--- /dev/null
+++ b/src/test/ui/svh/svh-change-significant-cfg.rs
@@ -0,0 +1,14 @@
+// ignore-msvc FIXME #31306
+
+// note that these aux-build directives must be in this order
+// aux-build:svh-a-base.rs
+// aux-build:svh-b.rs
+// aux-build:svh-a-change-significant-cfg.rs
+// normalize-stderr-test: "(crate `(\w+)`:) .*" -> "$1 $$PATH_$2"
+
+extern crate a;
+extern crate b; //~ ERROR: found possibly newer version of crate `a` which `b` depends on
+
+fn main() {
+    b::foo()
+}
diff --git a/src/test/ui/svh/svh-change-significant-cfg.stderr b/src/test/ui/svh/svh-change-significant-cfg.stderr
new file mode 100644
index 0000000..2357a43
--- /dev/null
+++ b/src/test/ui/svh/svh-change-significant-cfg.stderr
@@ -0,0 +1,14 @@
+error[E0460]: found possibly newer version of crate `a` which `b` depends on
+  --> $DIR/svh-change-significant-cfg.rs:10:1
+   |
+LL | extern crate b;
+   | ^^^^^^^^^^^^^^^
+   |
+   = note: perhaps that crate needs to be recompiled?
+   = note: the following crate versions were found:
+           crate `a`: $PATH_a
+           crate `b`: $PATH_b
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0460`.
diff --git a/src/test/ui/svh/svh-change-trait-bound.rs b/src/test/ui/svh/svh-change-trait-bound.rs
new file mode 100644
index 0000000..ddd10ac
--- /dev/null
+++ b/src/test/ui/svh/svh-change-trait-bound.rs
@@ -0,0 +1,14 @@
+// ignore-msvc FIXME #31306
+
+// note that these aux-build directives must be in this order
+// aux-build:svh-a-base.rs
+// aux-build:svh-b.rs
+// aux-build:svh-a-change-trait-bound.rs
+// normalize-stderr-test: "(crate `(\w+)`:) .*" -> "$1 $$PATH_$2"
+
+extern crate a;
+extern crate b; //~ ERROR: found possibly newer version of crate `a` which `b` depends on
+
+fn main() {
+    b::foo()
+}
diff --git a/src/test/ui/svh/svh-change-trait-bound.stderr b/src/test/ui/svh/svh-change-trait-bound.stderr
new file mode 100644
index 0000000..9fe949b
--- /dev/null
+++ b/src/test/ui/svh/svh-change-trait-bound.stderr
@@ -0,0 +1,14 @@
+error[E0460]: found possibly newer version of crate `a` which `b` depends on
+  --> $DIR/svh-change-trait-bound.rs:10:1
+   |
+LL | extern crate b;
+   | ^^^^^^^^^^^^^^^
+   |
+   = note: perhaps that crate needs to be recompiled?
+   = note: the following crate versions were found:
+           crate `a`: $PATH_a
+           crate `b`: $PATH_b
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0460`.
diff --git a/src/test/ui/svh/svh-change-type-arg.rs b/src/test/ui/svh/svh-change-type-arg.rs
new file mode 100644
index 0000000..f845ab5
--- /dev/null
+++ b/src/test/ui/svh/svh-change-type-arg.rs
@@ -0,0 +1,14 @@
+// ignore-msvc FIXME #31306
+
+// note that these aux-build directives must be in this order
+// aux-build:svh-a-base.rs
+// aux-build:svh-b.rs
+// aux-build:svh-a-change-type-arg.rs
+// normalize-stderr-test: "(crate `(\w+)`:) .*" -> "$1 $$PATH_$2"
+
+extern crate a;
+extern crate b; //~ ERROR: found possibly newer version of crate `a` which `b` depends on
+
+fn main() {
+    b::foo()
+}
diff --git a/src/test/ui/svh/svh-change-type-arg.stderr b/src/test/ui/svh/svh-change-type-arg.stderr
new file mode 100644
index 0000000..a8b35d2
--- /dev/null
+++ b/src/test/ui/svh/svh-change-type-arg.stderr
@@ -0,0 +1,14 @@
+error[E0460]: found possibly newer version of crate `a` which `b` depends on
+  --> $DIR/svh-change-type-arg.rs:10:1
+   |
+LL | extern crate b;
+   | ^^^^^^^^^^^^^^^
+   |
+   = note: perhaps that crate needs to be recompiled?
+   = note: the following crate versions were found:
+           crate `a`: $PATH_a
+           crate `b`: $PATH_b
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0460`.
diff --git a/src/test/ui/svh/svh-change-type-ret.rs b/src/test/ui/svh/svh-change-type-ret.rs
new file mode 100644
index 0000000..fb3e996
--- /dev/null
+++ b/src/test/ui/svh/svh-change-type-ret.rs
@@ -0,0 +1,14 @@
+// ignore-msvc FIXME #31306
+
+// note that these aux-build directives must be in this order
+// aux-build:svh-a-base.rs
+// aux-build:svh-b.rs
+// aux-build:svh-a-change-type-ret.rs
+// normalize-stderr-test: "(crate `(\w+)`:) .*" -> "$1 $$PATH_$2"
+
+extern crate a;
+extern crate b; //~ ERROR: found possibly newer version of crate `a` which `b` depends on
+
+fn main() {
+    b::foo()
+}
diff --git a/src/test/ui/svh/svh-change-type-ret.stderr b/src/test/ui/svh/svh-change-type-ret.stderr
new file mode 100644
index 0000000..ebe44a7
--- /dev/null
+++ b/src/test/ui/svh/svh-change-type-ret.stderr
@@ -0,0 +1,14 @@
+error[E0460]: found possibly newer version of crate `a` which `b` depends on
+  --> $DIR/svh-change-type-ret.rs:10:1
+   |
+LL | extern crate b;
+   | ^^^^^^^^^^^^^^^
+   |
+   = note: perhaps that crate needs to be recompiled?
+   = note: the following crate versions were found:
+           crate `a`: $PATH_a
+           crate `b`: $PATH_b
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0460`.
diff --git a/src/test/ui/svh/svh-change-type-static.rs b/src/test/ui/svh/svh-change-type-static.rs
new file mode 100644
index 0000000..0dfcaa0
--- /dev/null
+++ b/src/test/ui/svh/svh-change-type-static.rs
@@ -0,0 +1,14 @@
+// ignore-msvc FIXME #31306
+
+// note that these aux-build directives must be in this order
+// aux-build:svh-a-base.rs
+// aux-build:svh-b.rs
+// aux-build:svh-a-change-type-static.rs
+// normalize-stderr-test: "(crate `(\w+)`:) .*" -> "$1 $$PATH_$2"
+
+extern crate a;
+extern crate b; //~ ERROR: found possibly newer version of crate `a` which `b` depends on
+
+fn main() {
+    b::foo()
+}
diff --git a/src/test/ui/svh/svh-change-type-static.stderr b/src/test/ui/svh/svh-change-type-static.stderr
new file mode 100644
index 0000000..da09c32
--- /dev/null
+++ b/src/test/ui/svh/svh-change-type-static.stderr
@@ -0,0 +1,14 @@
+error[E0460]: found possibly newer version of crate `a` which `b` depends on
+  --> $DIR/svh-change-type-static.rs:10:1
+   |
+LL | extern crate b;
+   | ^^^^^^^^^^^^^^^
+   |
+   = note: perhaps that crate needs to be recompiled?
+   = note: the following crate versions were found:
+           crate `a`: $PATH_a
+           crate `b`: $PATH_b
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0460`.
diff --git a/src/test/ui/svh/svh-use-trait.rs b/src/test/ui/svh/svh-use-trait.rs
new file mode 100644
index 0000000..93daca0
--- /dev/null
+++ b/src/test/ui/svh/svh-use-trait.rs
@@ -0,0 +1,19 @@
+// ignore-msvc FIXME #31306
+
+// note that these aux-build directives must be in this order
+// aux-build:svh-uta-base.rs
+// aux-build:svh-utb.rs
+// aux-build:svh-uta-change-use-trait.rs
+// normalize-stderr-test: "(crate `(\w+)`:) .*" -> "$1 $$PATH_$2"
+
+//! "compile-fail/svh-uta-trait.rs" is checking that we detect a
+//! change from `use foo::TraitB` to use `foo::TraitB` in the hash
+//! (SVH) computation (#14132), since that will affect method
+//! resolution.
+
+extern crate uta;
+extern crate utb; //~ ERROR: found possibly newer version of crate `uta` which `utb` depends
+
+fn main() {
+    utb::foo()
+}
diff --git a/src/test/ui/svh/svh-use-trait.stderr b/src/test/ui/svh/svh-use-trait.stderr
new file mode 100644
index 0000000..4676143
--- /dev/null
+++ b/src/test/ui/svh/svh-use-trait.stderr
@@ -0,0 +1,14 @@
+error[E0460]: found possibly newer version of crate `uta` which `utb` depends on
+  --> $DIR/svh-use-trait.rs:15:1
+   |
+LL | extern crate utb;
+   | ^^^^^^^^^^^^^^^^^
+   |
+   = note: perhaps that crate needs to be recompiled?
+   = note: the following crate versions were found:
+           crate `uta`: $PATH_uta
+           crate `utb`: $PATH_utb
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0460`.
diff --git a/src/test/ui/switched-expectations.rs b/src/test/ui/switched-expectations.rs
new file mode 100644
index 0000000..c5bc84d
--- /dev/null
+++ b/src/test/ui/switched-expectations.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let var = 10i32;
+    let ref string: String = var; //~ ERROR mismatched types [E0308]
+}
diff --git a/src/test/ui/switched-expectations.stderr b/src/test/ui/switched-expectations.stderr
new file mode 100644
index 0000000..043d130
--- /dev/null
+++ b/src/test/ui/switched-expectations.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/switched-expectations.rs:3:30
+   |
+LL |     let ref string: String = var;
+   |                              ^^^ expected struct `std::string::String`, found i32
+   |
+   = note: expected type `std::string::String`
+              found type `i32`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/symbol-names/basic.rs b/src/test/ui/symbol-names/basic.rs
new file mode 100644
index 0000000..086b903
--- /dev/null
+++ b/src/test/ui/symbol-names/basic.rs
@@ -0,0 +1,6 @@
+#![feature(rustc_attrs)]
+
+#[rustc_symbol_name] //~ ERROR _ZN5basic4main
+#[rustc_def_path] //~ ERROR def-path(main)
+fn main() {
+}
diff --git a/src/test/ui/symbol-names/basic.stderr b/src/test/ui/symbol-names/basic.stderr
new file mode 100644
index 0000000..6ddd93d
--- /dev/null
+++ b/src/test/ui/symbol-names/basic.stderr
@@ -0,0 +1,14 @@
+error: symbol-name(_ZN5basic4main17h08bcaf310214ed52E)
+  --> $DIR/basic.rs:3:1
+   |
+LL | #[rustc_symbol_name]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: def-path(main)
+  --> $DIR/basic.rs:4:1
+   |
+LL | #[rustc_def_path]
+   | ^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/symbol-names/impl1.rs b/src/test/ui/symbol-names/impl1.rs
new file mode 100644
index 0000000..c712137
--- /dev/null
+++ b/src/test/ui/symbol-names/impl1.rs
@@ -0,0 +1,25 @@
+#![feature(rustc_attrs)]
+#![allow(dead_code)]
+
+mod foo {
+    pub struct Foo { x: u32 }
+
+    impl Foo {
+        #[rustc_symbol_name] //~ ERROR _ZN5impl13foo3Foo3bar
+        #[rustc_def_path] //~ ERROR def-path(foo::Foo::bar)
+        fn bar() { }
+    }
+}
+
+mod bar {
+    use foo::Foo;
+
+    impl Foo {
+        #[rustc_symbol_name] //~ ERROR _ZN5impl13bar33_$LT$impl$u20$impl1..foo..Foo$GT$3baz
+        #[rustc_def_path] //~ ERROR def-path(bar::<impl foo::Foo>::baz)
+        fn baz() { }
+    }
+}
+
+fn main() {
+}
diff --git a/src/test/ui/symbol-names/impl1.stderr b/src/test/ui/symbol-names/impl1.stderr
new file mode 100644
index 0000000..eda8646
--- /dev/null
+++ b/src/test/ui/symbol-names/impl1.stderr
@@ -0,0 +1,26 @@
+error: symbol-name(_ZN5impl13foo3Foo3bar17hc487d6ec13fe9124E)
+  --> $DIR/impl1.rs:8:9
+   |
+LL |         #[rustc_symbol_name]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: def-path(foo::Foo::bar)
+  --> $DIR/impl1.rs:9:9
+   |
+LL |         #[rustc_def_path]
+   |         ^^^^^^^^^^^^^^^^^
+
+error: symbol-name(_ZN5impl13bar33_$LT$impl$u20$impl1..foo..Foo$GT$3baz17h38577281258e1527E)
+  --> $DIR/impl1.rs:18:9
+   |
+LL |         #[rustc_symbol_name]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: def-path(bar::<impl foo::Foo>::baz)
+  --> $DIR/impl1.rs:19:9
+   |
+LL |         #[rustc_def_path]
+   |         ^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/syntax-extension-minor.rs b/src/test/ui/syntax-extension-minor.rs
new file mode 100644
index 0000000..0206a76
--- /dev/null
+++ b/src/test/ui/syntax-extension-minor.rs
@@ -0,0 +1,14 @@
+#![feature(concat_idents)]
+
+pub fn main() {
+    struct Foo;
+    let _: concat_idents!(F, oo) = Foo; // Test that `concat_idents!` can be used in type positions
+
+    let asdf_fdsa = "<.<".to_string();
+    // this now fails (correctly, I claim) because hygiene prevents
+    // the assembled identifier from being a reference to the binding.
+    assert!(concat_idents!(asd, f_f, dsa) == "<.<".to_string());
+    //~^ ERROR cannot find value `asdf_fdsa` in this scope
+
+    assert_eq!(stringify!(use_mention_distinction), "use_mention_distinction");
+}
diff --git a/src/test/ui/syntax-extension-minor.stderr b/src/test/ui/syntax-extension-minor.stderr
new file mode 100644
index 0000000..2d8056d
--- /dev/null
+++ b/src/test/ui/syntax-extension-minor.stderr
@@ -0,0 +1,9 @@
+error[E0425]: cannot find value `asdf_fdsa` in this scope
+  --> $DIR/syntax-extension-minor.rs:10:13
+   |
+LL |     assert!(concat_idents!(asd, f_f, dsa) == "<.<".to_string());
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/syntax-trait-polarity-feature-gate.rs b/src/test/ui/syntax-trait-polarity-feature-gate.rs
new file mode 100644
index 0000000..4a3b243
--- /dev/null
+++ b/src/test/ui/syntax-trait-polarity-feature-gate.rs
@@ -0,0 +1,10 @@
+use std::marker::Send;
+
+struct TestType;
+
+trait TestTrait {}
+
+impl !Send for TestType {}
+//~^ ERROR negative trait bounds
+
+fn main() {}
diff --git a/src/test/ui/syntax-trait-polarity-feature-gate.stderr b/src/test/ui/syntax-trait-polarity-feature-gate.stderr
new file mode 100644
index 0000000..7b9c3da
--- /dev/null
+++ b/src/test/ui/syntax-trait-polarity-feature-gate.stderr
@@ -0,0 +1,11 @@
+error[E0658]: negative trait bounds are not yet fully implemented; use marker types for now (see issue #13231)
+  --> $DIR/syntax-trait-polarity-feature-gate.rs:7:1
+   |
+LL | impl !Send for TestType {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(optin_builtin_traits)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/syntax-trait-polarity.rs b/src/test/ui/syntax-trait-polarity.rs
new file mode 100644
index 0000000..1b7fc15
--- /dev/null
+++ b/src/test/ui/syntax-trait-polarity.rs
@@ -0,0 +1,27 @@
+#![feature(optin_builtin_traits)]
+
+use std::marker::Send;
+
+struct TestType;
+
+impl !TestType {}
+//~^ ERROR inherent impls cannot be negative
+
+trait TestTrait {}
+
+unsafe impl !Send for TestType {}
+//~^ ERROR negative impls cannot be unsafe
+impl !TestTrait for TestType {}
+//~^ ERROR negative impls are only allowed for auto traits
+
+struct TestType2<T>(T);
+
+impl<T> !TestType2<T> {}
+//~^ ERROR inherent impls cannot be negative
+
+unsafe impl<T> !Send for TestType2<T> {}
+//~^ ERROR negative impls cannot be unsafe
+impl<T> !TestTrait for TestType2<T> {}
+//~^ ERROR negative impls are only allowed for auto traits
+
+fn main() {}
diff --git a/src/test/ui/syntax-trait-polarity.stderr b/src/test/ui/syntax-trait-polarity.stderr
new file mode 100644
index 0000000..689e24b
--- /dev/null
+++ b/src/test/ui/syntax-trait-polarity.stderr
@@ -0,0 +1,40 @@
+error: inherent impls cannot be negative
+  --> $DIR/syntax-trait-polarity.rs:7:1
+   |
+LL | impl !TestType {}
+   | ^^^^^^^^^^^^^^^^^
+
+error[E0198]: negative impls cannot be unsafe
+  --> $DIR/syntax-trait-polarity.rs:12:1
+   |
+LL | unsafe impl !Send for TestType {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: inherent impls cannot be negative
+  --> $DIR/syntax-trait-polarity.rs:19:1
+   |
+LL | impl<T> !TestType2<T> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0198]: negative impls cannot be unsafe
+  --> $DIR/syntax-trait-polarity.rs:22:1
+   |
+LL | unsafe impl<T> !Send for TestType2<T> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0192]: negative impls are only allowed for auto traits (e.g., `Send` and `Sync`)
+  --> $DIR/syntax-trait-polarity.rs:14:1
+   |
+LL | impl !TestTrait for TestType {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0192]: negative impls are only allowed for auto traits (e.g., `Send` and `Sync`)
+  --> $DIR/syntax-trait-polarity.rs:24:1
+   |
+LL | impl<T> !TestTrait for TestType2<T> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
+Some errors occurred: E0192, E0198.
+For more information about an error, try `rustc --explain E0192`.
diff --git a/src/test/ui/synthetic-param.rs b/src/test/ui/synthetic-param.rs
new file mode 100644
index 0000000..e53e3ba
--- /dev/null
+++ b/src/test/ui/synthetic-param.rs
@@ -0,0 +1,28 @@
+#![feature(rustc_attrs)]
+
+fn func<#[rustc_synthetic] T>(_: T) {}
+
+struct Foo;
+
+impl Foo {
+    pub fn func<#[rustc_synthetic] T>(_: T) {}
+}
+
+struct Bar<S> {
+    t: S
+}
+
+impl<S> Bar<S> {
+    pub fn func<#[rustc_synthetic] T>(_: T) {}
+}
+
+fn main() {
+    func::<u8>(42); //~ ERROR cannot provide explicit type parameters
+    func(42); // Ok
+
+    Foo::func::<u8>(42); //~ ERROR cannot provide explicit type parameters
+    Foo::func(42); // Ok
+
+    Bar::<i8>::func::<u8>(42); //~ ERROR cannot provide explicit type parameters
+    Bar::<i8>::func(42); // Ok
+}
diff --git a/src/test/ui/synthetic-param.stderr b/src/test/ui/synthetic-param.stderr
new file mode 100644
index 0000000..b63a57a
--- /dev/null
+++ b/src/test/ui/synthetic-param.stderr
@@ -0,0 +1,21 @@
+error[E0632]: cannot provide explicit type parameters when `impl Trait` is used in argument position.
+  --> $DIR/synthetic-param.rs:20:5
+   |
+LL |     func::<u8>(42);
+   |     ^^^^^^^^^^
+
+error[E0632]: cannot provide explicit type parameters when `impl Trait` is used in argument position.
+  --> $DIR/synthetic-param.rs:23:5
+   |
+LL |     Foo::func::<u8>(42);
+   |     ^^^^^^^^^^^^^^^
+
+error[E0632]: cannot provide explicit type parameters when `impl Trait` is used in argument position.
+  --> $DIR/synthetic-param.rs:26:5
+   |
+LL |     Bar::<i8>::func::<u8>(42);
+   |     ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0632`.
diff --git a/src/test/ui/tag-that-dare-not-speak-its-name.rs b/src/test/ui/tag-that-dare-not-speak-its-name.rs
new file mode 100644
index 0000000..9f47b2e
--- /dev/null
+++ b/src/test/ui/tag-that-dare-not-speak-its-name.rs
@@ -0,0 +1,16 @@
+// Issue #876
+
+use std::vec::Vec;
+
+fn last<T>(v: Vec<&T> ) -> std::option::Option<T> {
+    ::std::panic!();
+}
+
+fn main() {
+    let y;
+    let x : char = last(y);
+    //~^ ERROR mismatched types
+    //~| expected type `char`
+    //~| found type `std::option::Option<_>`
+    //~| expected char, found enum `std::option::Option`
+}
diff --git a/src/test/ui/tag-that-dare-not-speak-its-name.stderr b/src/test/ui/tag-that-dare-not-speak-its-name.stderr
new file mode 100644
index 0000000..23e3d66
--- /dev/null
+++ b/src/test/ui/tag-that-dare-not-speak-its-name.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/tag-that-dare-not-speak-its-name.rs:11:20
+   |
+LL |     let x : char = last(y);
+   |                    ^^^^^^^ expected char, found enum `std::option::Option`
+   |
+   = note: expected type `char`
+              found type `std::option::Option<_>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/tag-type-args.rs b/src/test/ui/tag-type-args.rs
new file mode 100644
index 0000000..4f546fc
--- /dev/null
+++ b/src/test/ui/tag-type-args.rs
@@ -0,0 +1,5 @@
+enum Quux<T> { Bar }
+
+fn foo(c: Quux) { assert!((false)); } //~ ERROR wrong number of type arguments
+
+fn main() { panic!(); }
diff --git a/src/test/ui/tag-type-args.stderr b/src/test/ui/tag-type-args.stderr
new file mode 100644
index 0000000..ac44dad
--- /dev/null
+++ b/src/test/ui/tag-type-args.stderr
@@ -0,0 +1,9 @@
+error[E0107]: wrong number of type arguments: expected 1, found 0
+  --> $DIR/tag-type-args.rs:3:11
+   |
+LL | fn foo(c: Quux) { assert!((false)); }
+   |           ^^^^ expected 1 type argument
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0107`.
diff --git a/src/test/ui/tag-variant-cast-non-nullary.rs b/src/test/ui/tag-variant-cast-non-nullary.rs
new file mode 100644
index 0000000..bb34e82
--- /dev/null
+++ b/src/test/ui/tag-variant-cast-non-nullary.rs
@@ -0,0 +1,9 @@
+enum NonNullary {
+    Nullary,
+    Other(isize),
+}
+
+fn main() {
+    let v = NonNullary::Nullary;
+    let val = v as isize; //~ ERROR non-primitive cast: `NonNullary` as `isize` [E0605]
+}
diff --git a/src/test/ui/tag-variant-cast-non-nullary.stderr b/src/test/ui/tag-variant-cast-non-nullary.stderr
new file mode 100644
index 0000000..87ec20f2
--- /dev/null
+++ b/src/test/ui/tag-variant-cast-non-nullary.stderr
@@ -0,0 +1,11 @@
+error[E0605]: non-primitive cast: `NonNullary` as `isize`
+  --> $DIR/tag-variant-cast-non-nullary.rs:8:15
+   |
+LL |     let val = v as isize;
+   |               ^^^^^^^^^^
+   |
+   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0605`.
diff --git a/src/test/ui/tag-variant-disr-dup.rs b/src/test/ui/tag-variant-disr-dup.rs
new file mode 100644
index 0000000..d2a38e0
--- /dev/null
+++ b/src/test/ui/tag-variant-disr-dup.rs
@@ -0,0 +1,11 @@
+// Black and White have the same discriminator value ...
+
+enum Color {
+    Red = 0xff0000,
+    Green = 0x00ff00,
+    Blue = 0x0000ff,
+    Black = 0x000000,
+    White = 0x000000, //~ ERROR discriminant value `0` already exists
+}
+
+fn main() { }
diff --git a/src/test/ui/tag-variant-disr-dup.stderr b/src/test/ui/tag-variant-disr-dup.stderr
new file mode 100644
index 0000000..ca12894
--- /dev/null
+++ b/src/test/ui/tag-variant-disr-dup.stderr
@@ -0,0 +1,11 @@
+error[E0081]: discriminant value `0` already exists
+  --> $DIR/tag-variant-disr-dup.rs:8:13
+   |
+LL |     Black = 0x000000,
+   |             -------- first use of `0`
+LL |     White = 0x000000,
+   |             ^^^^^^^^ enum already has `0`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0081`.
diff --git a/src/test/ui/tail-typeck.rs b/src/test/ui/tail-typeck.rs
new file mode 100644
index 0000000..37a7694
--- /dev/null
+++ b/src/test/ui/tail-typeck.rs
@@ -0,0 +1,7 @@
+// error-pattern: mismatched types
+
+fn f() -> isize { return g(); }
+
+fn g() -> usize { return 0; }
+
+fn main() { let y = f(); }
diff --git a/src/test/ui/tail-typeck.stderr b/src/test/ui/tail-typeck.stderr
new file mode 100644
index 0000000..1170f5c
--- /dev/null
+++ b/src/test/ui/tail-typeck.stderr
@@ -0,0 +1,11 @@
+error[E0308]: mismatched types
+  --> $DIR/tail-typeck.rs:3:26
+   |
+LL | fn f() -> isize { return g(); }
+   |           -----          ^^^ expected isize, found usize
+   |           |
+   |           expected `isize` because of return type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/target-feature-gate.rs b/src/test/ui/target-feature-gate.rs
new file mode 100644
index 0000000..8430030
--- /dev/null
+++ b/src/test/ui/target-feature-gate.rs
@@ -0,0 +1,33 @@
+// ignore-arm
+// ignore-aarch64
+// ignore-wasm
+// ignore-emscripten
+// ignore-mips
+// ignore-mips64
+// ignore-powerpc
+// ignore-powerpc64
+// ignore-powerpc64le
+// ignore-sparc
+// ignore-sparc64
+// ignore-s390x
+// gate-test-sse4a_target_feature
+// gate-test-powerpc_target_feature
+// gate-test-avx512_target_feature
+// gate-test-tbm_target_feature
+// gate-test-arm_target_feature
+// gate-test-aarch64_target_feature
+// gate-test-hexagon_target_feature
+// gate-test-mips_target_feature
+// gate-test-mmx_target_feature
+// gate-test-wasm_target_feature
+// gate-test-adx_target_feature
+// gate-test-cmpxchg16b_target_feature
+// gate-test-movbe_target_feature
+// min-llvm-version 6.0
+
+#[target_feature(enable = "avx512bw")]
+//~^ ERROR: currently unstable
+unsafe fn foo() {
+}
+
+fn main() {}
diff --git a/src/test/ui/target-feature-gate.stderr b/src/test/ui/target-feature-gate.stderr
new file mode 100644
index 0000000..24141d0
--- /dev/null
+++ b/src/test/ui/target-feature-gate.stderr
@@ -0,0 +1,11 @@
+error[E0658]: the target feature `avx512bw` is currently unstable (see issue #44839)
+  --> $DIR/target-feature-gate.rs:28:18
+   |
+LL | #[target_feature(enable = "avx512bw")]
+   |                  ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(avx512_target_feature)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/target-feature-wrong.rs b/src/test/ui/target-feature-wrong.rs
new file mode 100644
index 0000000..ddae887
--- /dev/null
+++ b/src/test/ui/target-feature-wrong.rs
@@ -0,0 +1,44 @@
+// ignore-arm
+// ignore-aarch64
+// ignore-wasm
+// ignore-emscripten
+// ignore-mips
+// ignore-mips64
+// ignore-powerpc
+// ignore-powerpc64
+// ignore-powerpc64le
+// ignore-s390x
+// ignore-sparc
+// ignore-sparc64
+
+#![feature(target_feature)]
+
+#[target_feature = "+sse2"]
+//~^ ERROR: must be of the form
+#[target_feature(enable = "foo")]
+//~^ ERROR: not valid for this target
+#[target_feature(bar)]
+//~^ ERROR: only accepts sub-keys
+#[target_feature(disable = "baz")]
+//~^ ERROR: only accepts sub-keys
+unsafe fn foo() {}
+
+#[target_feature(enable = "sse2")]
+//~^ ERROR: can only be applied to `unsafe` function
+fn bar() {}
+
+#[target_feature(enable = "sse2")]
+//~^ ERROR: should be applied to a function
+mod another {}
+
+#[inline(always)]
+//~^ ERROR: cannot use #[inline(always)]
+#[target_feature(enable = "sse2")]
+unsafe fn test() {}
+
+fn main() {
+    unsafe {
+        foo();
+        bar();
+    }
+}
diff --git a/src/test/ui/target-feature-wrong.stderr b/src/test/ui/target-feature-wrong.stderr
new file mode 100644
index 0000000..3662ea9
--- /dev/null
+++ b/src/test/ui/target-feature-wrong.stderr
@@ -0,0 +1,47 @@
+error: attribute must be of the form `#[target_feature(enable = "name")]`
+  --> $DIR/target-feature-wrong.rs:16:1
+   |
+LL | #[target_feature = "+sse2"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: the feature named `foo` is not valid for this target
+  --> $DIR/target-feature-wrong.rs:18:18
+   |
+LL | #[target_feature(enable = "foo")]
+   |                  ^^^^^^^^^^^^^^
+
+error: #[target_feature(..)] only accepts sub-keys of `enable` currently
+  --> $DIR/target-feature-wrong.rs:20:18
+   |
+LL | #[target_feature(bar)]
+   |                  ^^^
+
+error: #[target_feature(..)] only accepts sub-keys of `enable` currently
+  --> $DIR/target-feature-wrong.rs:22:18
+   |
+LL | #[target_feature(disable = "baz")]
+   |                  ^^^^^^^^^^^^^^^
+
+error: #[target_feature(..)] can only be applied to `unsafe` function
+  --> $DIR/target-feature-wrong.rs:26:1
+   |
+LL | #[target_feature(enable = "sse2")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: attribute should be applied to a function
+  --> $DIR/target-feature-wrong.rs:30:1
+   |
+LL | #[target_feature(enable = "sse2")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |
+LL | mod another {}
+   | -------------- not a function
+
+error: cannot use #[inline(always)] with #[target_feature]
+  --> $DIR/target-feature-wrong.rs:34:1
+   |
+LL | #[inline(always)]
+   | ^^^^^^^^^^^^^^^^^
+
+error: aborting due to 7 previous errors
+
diff --git a/src/test/ui/terr-in-field.rs b/src/test/ui/terr-in-field.rs
new file mode 100644
index 0000000..388c13d
--- /dev/null
+++ b/src/test/ui/terr-in-field.rs
@@ -0,0 +1,19 @@
+struct Foo {
+    a: isize,
+    b: isize,
+}
+
+struct Bar {
+    a: isize,
+    b: usize,
+}
+
+fn want_foo(f: Foo) {}
+fn have_bar(b: Bar) {
+    want_foo(b); //~  ERROR mismatched types
+                 //~| expected type `Foo`
+                 //~| found type `Bar`
+                 //~| expected struct `Foo`, found struct `Bar`
+}
+
+fn main() {}
diff --git a/src/test/ui/terr-in-field.stderr b/src/test/ui/terr-in-field.stderr
new file mode 100644
index 0000000..91c3b30
--- /dev/null
+++ b/src/test/ui/terr-in-field.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/terr-in-field.rs:13:14
+   |
+LL |     want_foo(b);
+   |              ^ expected struct `Foo`, found struct `Bar`
+   |
+   = note: expected type `Foo`
+              found type `Bar`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/terr-sorts.rs b/src/test/ui/terr-sorts.rs
new file mode 100644
index 0000000..4bec561
--- /dev/null
+++ b/src/test/ui/terr-sorts.rs
@@ -0,0 +1,15 @@
+struct Foo {
+    a: isize,
+    b: isize,
+}
+
+type Bar = Box<Foo>;
+
+fn want_foo(f: Foo) {}
+fn have_bar(b: Bar) {
+    want_foo(b); //~  ERROR mismatched types
+                 //~| expected type `Foo`
+                 //~| found type `std::boxed::Box<Foo>`
+}
+
+fn main() {}
diff --git a/src/test/ui/terr-sorts.stderr b/src/test/ui/terr-sorts.stderr
new file mode 100644
index 0000000..05b9fb4
--- /dev/null
+++ b/src/test/ui/terr-sorts.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/terr-sorts.rs:10:14
+   |
+LL |     want_foo(b);
+   |              ^ expected struct `Foo`, found struct `std::boxed::Box`
+   |
+   = note: expected type `Foo`
+              found type `std::boxed::Box<Foo>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/test-attr-non-associated-functions.rs b/src/test/ui/test-attr-non-associated-functions.rs
new file mode 100644
index 0000000..5ed85ab
--- /dev/null
+++ b/src/test/ui/test-attr-non-associated-functions.rs
@@ -0,0 +1,19 @@
+// #[test] attribute is not allowed on associated functions or methods
+// reworded error message
+// compile-flags:--test
+
+struct A {}
+
+impl A {
+    #[test]
+    fn new() -> A { //~ ERROR #[test] attribute is only allowed on non associated functions
+        A {}
+    }
+}
+
+#[test]
+fn test() {
+    let _ = A::new();
+}
+
+fn main() {}
diff --git a/src/test/ui/test-attr-non-associated-functions.stderr b/src/test/ui/test-attr-non-associated-functions.stderr
new file mode 100644
index 0000000..6176aa0
--- /dev/null
+++ b/src/test/ui/test-attr-non-associated-functions.stderr
@@ -0,0 +1,10 @@
+error: #[test] attribute is only allowed on non associated functions
+  --> $DIR/test-attr-non-associated-functions.rs:9:5
+   |
+LL | /     fn new() -> A {
+LL | |         A {}
+LL | |     }
+   | |_____^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/test-cfg.rs b/src/test/ui/test-cfg.rs
new file mode 100644
index 0000000..8750bae
--- /dev/null
+++ b/src/test/ui/test-cfg.rs
@@ -0,0 +1,8 @@
+// compile-flags: --cfg foo
+
+#[cfg(all(foo, bar))] // foo AND bar
+fn foo() {}
+
+fn main() {
+    foo(); //~ ERROR cannot find function `foo` in this scope
+}
diff --git a/src/test/ui/test-cfg.stderr b/src/test/ui/test-cfg.stderr
new file mode 100644
index 0000000..c35fe2f
--- /dev/null
+++ b/src/test/ui/test-cfg.stderr
@@ -0,0 +1,9 @@
+error[E0425]: cannot find function `foo` in this scope
+  --> $DIR/test-cfg.rs:7:5
+   |
+LL |     foo();
+   |     ^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/test-on-macro.rs b/src/test/ui/test-on-macro.rs
new file mode 100644
index 0000000..ad7424a
--- /dev/null
+++ b/src/test/ui/test-on-macro.rs
@@ -0,0 +1,13 @@
+// compile-pass
+// compile-flags:--test
+
+#![deny(warnings)]
+
+macro_rules! foo {
+    () => (fn foo(){})
+}
+
+#[test]
+foo!();
+
+fn main(){}
diff --git a/src/test/ui/test-on-macro.stderr b/src/test/ui/test-on-macro.stderr
new file mode 100644
index 0000000..1af3882
--- /dev/null
+++ b/src/test/ui/test-on-macro.stderr
@@ -0,0 +1,6 @@
+warning: #[test] attribute should not be used on macros. Use #[cfg(test)] instead.
+  --> $DIR/test-on-macro.rs:11:1
+   |
+LL | foo!();
+   | ^^^^^^^
+
diff --git a/src/test/ui/test-shadowing/auxiliary/test_macro.rs b/src/test/ui/test-shadowing/auxiliary/test_macro.rs
new file mode 100644
index 0000000..60a98ab
--- /dev/null
+++ b/src/test/ui/test-shadowing/auxiliary/test_macro.rs
@@ -0,0 +1,4 @@
+#[macro_export]
+macro_rules! test {
+    () => {};
+}
diff --git a/src/test/ui/test-shadowing/test-cant-be-shadowed.rs b/src/test/ui/test-shadowing/test-cant-be-shadowed.rs
new file mode 100644
index 0000000..b1c2a00
--- /dev/null
+++ b/src/test/ui/test-shadowing/test-cant-be-shadowed.rs
@@ -0,0 +1,13 @@
+// compile-pass
+// aux-build:test_macro.rs
+// compile-flags:--test
+
+#[macro_use] extern crate test_macro;
+
+#[test]
+fn foo(){}
+
+macro_rules! test { () => () }
+
+#[test]
+fn bar() {}
diff --git a/src/test/ui/test-should-panic-attr.rs b/src/test/ui/test-should-panic-attr.rs
new file mode 100644
index 0000000..f936dd5
--- /dev/null
+++ b/src/test/ui/test-should-panic-attr.rs
@@ -0,0 +1,36 @@
+// compile-pass
+// compile-flags: --test
+
+#[test]
+#[should_panic = "foo"]
+fn test1() {
+    panic!();
+}
+
+#[test]
+#[should_panic(expected)]
+//~^ WARN: argument must be of the form:
+fn test2() {
+    panic!();
+}
+
+#[test]
+#[should_panic(expect)]
+//~^ WARN: argument must be of the form:
+fn test3() {
+    panic!();
+}
+
+#[test]
+#[should_panic(expected(foo, bar))]
+//~^ WARN: argument must be of the form:
+fn test4() {
+    panic!();
+}
+
+#[test]
+#[should_panic(expected = "foo", bar)]
+//~^ WARN: argument must be of the form:
+fn test5() {
+    panic!();
+}
diff --git a/src/test/ui/test-should-panic-attr.stderr b/src/test/ui/test-should-panic-attr.stderr
new file mode 100644
index 0000000..4b032eb
--- /dev/null
+++ b/src/test/ui/test-should-panic-attr.stderr
@@ -0,0 +1,32 @@
+warning: argument must be of the form: `expected = "error message"`
+  --> $DIR/test-should-panic-attr.rs:11:1
+   |
+LL | #[should_panic(expected)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: Errors in this attribute were erroneously allowed and will become a hard error in a future release.
+
+warning: argument must be of the form: `expected = "error message"`
+  --> $DIR/test-should-panic-attr.rs:18:1
+   |
+LL | #[should_panic(expect)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: Errors in this attribute were erroneously allowed and will become a hard error in a future release.
+
+warning: argument must be of the form: `expected = "error message"`
+  --> $DIR/test-should-panic-attr.rs:25:1
+   |
+LL | #[should_panic(expected(foo, bar))]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: Errors in this attribute were erroneously allowed and will become a hard error in a future release.
+
+warning: argument must be of the form: `expected = "error message"`
+  --> $DIR/test-should-panic-attr.rs:32:1
+   |
+LL | #[should_panic(expected = "foo", bar)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: Errors in this attribute were erroneously allowed and will become a hard error in a future release.
+
diff --git a/src/test/ui/test-warns-dead-code.rs b/src/test/ui/test-warns-dead-code.rs
new file mode 100644
index 0000000..936461f
--- /dev/null
+++ b/src/test/ui/test-warns-dead-code.rs
@@ -0,0 +1,7 @@
+// compile-flags: --test
+
+#![deny(dead_code)]
+
+fn dead() {} //~ error: function is never used: `dead`
+
+fn main() {}
diff --git a/src/test/ui/test-warns-dead-code.stderr b/src/test/ui/test-warns-dead-code.stderr
new file mode 100644
index 0000000..62e9922
--- /dev/null
+++ b/src/test/ui/test-warns-dead-code.stderr
@@ -0,0 +1,14 @@
+error: function is never used: `dead`
+  --> $DIR/test-warns-dead-code.rs:5:1
+   |
+LL | fn dead() {}
+   | ^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/test-warns-dead-code.rs:3:9
+   |
+LL | #![deny(dead_code)]
+   |         ^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/thread-local-in-ctfe.nll.stderr b/src/test/ui/thread-local-in-ctfe.nll.stderr
new file mode 100644
index 0000000..c5cca9d
--- /dev/null
+++ b/src/test/ui/thread-local-in-ctfe.nll.stderr
@@ -0,0 +1,56 @@
+error[E0625]: thread-local statics cannot be accessed at compile-time
+  --> $DIR/thread-local-in-ctfe.rs:6:17
+   |
+LL | static B: u32 = A;
+   |                 ^
+
+error[E0625]: thread-local statics cannot be accessed at compile-time
+  --> $DIR/thread-local-in-ctfe.rs:9:18
+   |
+LL | static C: &u32 = &A;
+   |                  ^^
+
+warning[E0712]: thread-local variable borrowed past end of function
+  --> $DIR/thread-local-in-ctfe.rs:9:18
+   |
+LL | static C: &u32 = &A;
+   |                  ^^- end of enclosing function is here
+   |                  |
+   |                  thread-local variables cannot be borrowed beyond the end of the function
+   |
+   = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
+   = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+
+error[E0625]: thread-local statics cannot be accessed at compile-time
+  --> $DIR/thread-local-in-ctfe.rs:12:16
+   |
+LL | const D: u32 = A;
+   |                ^
+
+error[E0625]: thread-local statics cannot be accessed at compile-time
+  --> $DIR/thread-local-in-ctfe.rs:15:17
+   |
+LL | const E: &u32 = &A;
+   |                 ^^
+
+warning[E0712]: thread-local variable borrowed past end of function
+  --> $DIR/thread-local-in-ctfe.rs:15:17
+   |
+LL | const E: &u32 = &A;
+   |                 ^^- end of enclosing function is here
+   |                 |
+   |                 thread-local variables cannot be borrowed beyond the end of the function
+   |
+   = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
+   = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+
+error[E0625]: thread-local statics cannot be accessed at compile-time
+  --> $DIR/thread-local-in-ctfe.rs:19:5
+   |
+LL |     A
+   |     ^
+
+error: aborting due to 5 previous errors
+
+Some errors occurred: E0625, E0712.
+For more information about an error, try `rustc --explain E0625`.
diff --git a/src/test/ui/thread-local-in-ctfe.rs b/src/test/ui/thread-local-in-ctfe.rs
new file mode 100644
index 0000000..313d39d
--- /dev/null
+++ b/src/test/ui/thread-local-in-ctfe.rs
@@ -0,0 +1,23 @@
+#![feature(const_fn, thread_local)]
+
+#[thread_local]
+static A: u32 = 1;
+
+static B: u32 = A;
+//~^ ERROR thread-local statics cannot be accessed at compile-time
+
+static C: &u32 = &A;
+//~^ ERROR thread-local statics cannot be accessed at compile-time
+
+const D: u32 = A;
+//~^ ERROR thread-local statics cannot be accessed at compile-time
+
+const E: &u32 = &A;
+//~^ ERROR thread-local statics cannot be accessed at compile-time
+
+const fn f() -> u32 {
+    A
+    //~^ ERROR thread-local statics cannot be accessed at compile-time
+}
+
+fn main() {}
diff --git a/src/test/ui/thread-local-in-ctfe.stderr b/src/test/ui/thread-local-in-ctfe.stderr
new file mode 100644
index 0000000..abeb2a3
--- /dev/null
+++ b/src/test/ui/thread-local-in-ctfe.stderr
@@ -0,0 +1,33 @@
+error[E0625]: thread-local statics cannot be accessed at compile-time
+  --> $DIR/thread-local-in-ctfe.rs:6:17
+   |
+LL | static B: u32 = A;
+   |                 ^
+
+error[E0625]: thread-local statics cannot be accessed at compile-time
+  --> $DIR/thread-local-in-ctfe.rs:9:18
+   |
+LL | static C: &u32 = &A;
+   |                  ^^
+
+error[E0625]: thread-local statics cannot be accessed at compile-time
+  --> $DIR/thread-local-in-ctfe.rs:12:16
+   |
+LL | const D: u32 = A;
+   |                ^
+
+error[E0625]: thread-local statics cannot be accessed at compile-time
+  --> $DIR/thread-local-in-ctfe.rs:15:17
+   |
+LL | const E: &u32 = &A;
+   |                 ^^
+
+error[E0625]: thread-local statics cannot be accessed at compile-time
+  --> $DIR/thread-local-in-ctfe.rs:19:5
+   |
+LL |     A
+   |     ^
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0625`.
diff --git a/src/test/ui/thread-local-mutation.nll.stderr b/src/test/ui/thread-local-mutation.nll.stderr
new file mode 100644
index 0000000..e5dc0e7
--- /dev/null
+++ b/src/test/ui/thread-local-mutation.nll.stderr
@@ -0,0 +1,9 @@
+error[E0594]: cannot assign to immutable static item `S`
+  --> $DIR/thread-local-mutation.rs:11:5
+   |
+LL |     S = "after";
+   |     ^^^^^^^^^^^ cannot assign
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/thread-local-mutation.rs b/src/test/ui/thread-local-mutation.rs
new file mode 100644
index 0000000..e738225
--- /dev/null
+++ b/src/test/ui/thread-local-mutation.rs
@@ -0,0 +1,18 @@
+// Regression test for #54901: immutable thread locals could be mutated. See:
+// https://github.com/rust-lang/rust/issues/29594#issuecomment-328177697
+// https://github.com/rust-lang/rust/issues/54901
+
+#![feature(thread_local)]
+
+#[thread_local]
+static S: &str = "before";
+
+fn set_s() {
+    S = "after"; //~ ERROR cannot assign to immutable
+}
+
+fn main() {
+    println!("{}", S);
+    set_s();
+    println!("{}", S);
+}
diff --git a/src/test/ui/thread-local-mutation.stderr b/src/test/ui/thread-local-mutation.stderr
new file mode 100644
index 0000000..685e7c6
--- /dev/null
+++ b/src/test/ui/thread-local-mutation.stderr
@@ -0,0 +1,9 @@
+error[E0594]: cannot assign to immutable thread-local static item
+  --> $DIR/thread-local-mutation.rs:11:5
+   |
+LL |     S = "after";
+   |     ^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/tool-attributes/tool-attributes-misplaced-1.rs b/src/test/ui/tool-attributes/tool-attributes-misplaced-1.rs
new file mode 100644
index 0000000..33cffce
--- /dev/null
+++ b/src/test/ui/tool-attributes/tool-attributes-misplaced-1.rs
@@ -0,0 +1,18 @@
+#![feature(custom_attribute)]
+
+type A = rustfmt; //~ ERROR expected type, found tool module `rustfmt`
+type B = rustfmt::skip; //~ ERROR expected type, found tool attribute `rustfmt::skip`
+
+#[derive(rustfmt)] //~ ERROR cannot find derive macro `rustfmt` in this scope
+struct S;
+
+#[rustfmt] // OK, interpreted as a custom attribute
+fn check() {}
+
+#[rustfmt::skip] // OK
+fn main() {
+    rustfmt; //~ ERROR expected value, found tool module `rustfmt`
+    rustfmt!(); //~ ERROR cannot find macro `rustfmt!` in this scope
+
+    rustfmt::skip; //~ ERROR expected value, found tool attribute `rustfmt::skip`
+}
diff --git a/src/test/ui/tool-attributes/tool-attributes-misplaced-1.stderr b/src/test/ui/tool-attributes/tool-attributes-misplaced-1.stderr
new file mode 100644
index 0000000..1e9d160
--- /dev/null
+++ b/src/test/ui/tool-attributes/tool-attributes-misplaced-1.stderr
@@ -0,0 +1,40 @@
+error: cannot find derive macro `rustfmt` in this scope
+  --> $DIR/tool-attributes-misplaced-1.rs:6:10
+   |
+LL | #[derive(rustfmt)]
+   |          ^^^^^^^
+
+error: cannot find macro `rustfmt!` in this scope
+  --> $DIR/tool-attributes-misplaced-1.rs:15:5
+   |
+LL |     rustfmt!();
+   |     ^^^^^^^
+
+error[E0573]: expected type, found tool module `rustfmt`
+  --> $DIR/tool-attributes-misplaced-1.rs:3:10
+   |
+LL | type A = rustfmt;
+   |          ^^^^^^^ not a type
+
+error[E0573]: expected type, found tool attribute `rustfmt::skip`
+  --> $DIR/tool-attributes-misplaced-1.rs:4:10
+   |
+LL | type B = rustfmt::skip;
+   |          ^^^^^^^^^^^^^ not a type
+
+error[E0423]: expected value, found tool module `rustfmt`
+  --> $DIR/tool-attributes-misplaced-1.rs:14:5
+   |
+LL |     rustfmt;
+   |     ^^^^^^^ not a value
+
+error[E0423]: expected value, found tool attribute `rustfmt::skip`
+  --> $DIR/tool-attributes-misplaced-1.rs:17:5
+   |
+LL |     rustfmt::skip;
+   |     ^^^^^^^^^^^^^ not a value
+
+error: aborting due to 6 previous errors
+
+Some errors occurred: E0423, E0573.
+For more information about an error, try `rustc --explain E0423`.
diff --git a/src/test/ui/tool-attributes/tool-attributes-misplaced-2.rs b/src/test/ui/tool-attributes/tool-attributes-misplaced-2.rs
new file mode 100644
index 0000000..56b908d
--- /dev/null
+++ b/src/test/ui/tool-attributes/tool-attributes-misplaced-2.rs
@@ -0,0 +1,6 @@
+#[derive(rustfmt::skip)] //~ ERROR expected a macro, found tool attribute
+struct S;
+
+fn main() {
+    rustfmt::skip!(); //~ ERROR expected a macro, found tool attribute
+}
diff --git a/src/test/ui/tool-attributes/tool-attributes-misplaced-2.stderr b/src/test/ui/tool-attributes/tool-attributes-misplaced-2.stderr
new file mode 100644
index 0000000..c5f5f59
--- /dev/null
+++ b/src/test/ui/tool-attributes/tool-attributes-misplaced-2.stderr
@@ -0,0 +1,14 @@
+error: expected a macro, found tool attribute
+  --> $DIR/tool-attributes-misplaced-2.rs:1:10
+   |
+LL | #[derive(rustfmt::skip)]
+   |          ^^^^^^^^^^^^^
+
+error: expected a macro, found tool attribute
+  --> $DIR/tool-attributes-misplaced-2.rs:5:5
+   |
+LL |     rustfmt::skip!();
+   |     ^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/tool-attributes/tool-attributes-shadowing.rs b/src/test/ui/tool-attributes/tool-attributes-shadowing.rs
new file mode 100644
index 0000000..21bbaa3
--- /dev/null
+++ b/src/test/ui/tool-attributes/tool-attributes-shadowing.rs
@@ -0,0 +1,4 @@
+mod rustfmt {}
+
+#[rustfmt::skip] //~ ERROR failed to resolve: could not find `skip` in `rustfmt`
+fn main() {}
diff --git a/src/test/ui/tool-attributes/tool-attributes-shadowing.stderr b/src/test/ui/tool-attributes/tool-attributes-shadowing.stderr
new file mode 100644
index 0000000..98ad109
--- /dev/null
+++ b/src/test/ui/tool-attributes/tool-attributes-shadowing.stderr
@@ -0,0 +1,9 @@
+error[E0433]: failed to resolve: could not find `skip` in `rustfmt`
+  --> $DIR/tool-attributes-shadowing.rs:3:12
+   |
+LL | #[rustfmt::skip]
+   |            ^^^^ could not find `skip` in `rustfmt`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/tool_lints-fail.rs b/src/test/ui/tool_lints-fail.rs
new file mode 100644
index 0000000..5cbd63b
--- /dev/null
+++ b/src/test/ui/tool_lints-fail.rs
@@ -0,0 +1,8 @@
+// Don't allow tool_lints, which aren't scoped
+
+
+#![deny(unknown_lints)]
+
+#![deny(clippy)] //~ ERROR: unknown lint: `clippy`
+
+fn main() {}
diff --git a/src/test/ui/tool_lints-fail.stderr b/src/test/ui/tool_lints-fail.stderr
new file mode 100644
index 0000000..a61157f
--- /dev/null
+++ b/src/test/ui/tool_lints-fail.stderr
@@ -0,0 +1,14 @@
+error: unknown lint: `clippy`
+  --> $DIR/tool_lints-fail.rs:6:9
+   |
+LL | #![deny(clippy)]
+   |         ^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/tool_lints-fail.rs:4:9
+   |
+LL | #![deny(unknown_lints)]
+   |         ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/tool_lints.rs b/src/test/ui/tool_lints.rs
new file mode 100644
index 0000000..fa8f041
--- /dev/null
+++ b/src/test/ui/tool_lints.rs
@@ -0,0 +1,3 @@
+#[warn(foo::bar)]
+//~^ ERROR an unknown tool name found in scoped lint: `foo::bar`
+fn main() {}
diff --git a/src/test/ui/tool_lints.stderr b/src/test/ui/tool_lints.stderr
new file mode 100644
index 0000000..2484b10
--- /dev/null
+++ b/src/test/ui/tool_lints.stderr
@@ -0,0 +1,9 @@
+error[E0710]: an unknown tool name found in scoped lint: `foo::bar`
+  --> $DIR/tool_lints.rs:1:8
+   |
+LL | #[warn(foo::bar)]
+   |        ^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0710`.
diff --git a/src/test/ui/trace_macros-format.rs b/src/test/ui/trace_macros-format.rs
new file mode 100644
index 0000000..afca45c
--- /dev/null
+++ b/src/test/ui/trace_macros-format.rs
@@ -0,0 +1,18 @@
+#![feature(trace_macros)]
+
+fn main() {
+    trace_macros!(); //~ ERROR trace_macros! accepts only `true` or `false`
+    trace_macros!(1); //~ ERROR trace_macros! accepts only `true` or `false`
+    trace_macros!(ident); //~ ERROR trace_macros! accepts only `true` or `false`
+    trace_macros!(for); //~ ERROR trace_macros! accepts only `true` or `false`
+    trace_macros!(true,); //~ ERROR trace_macros! accepts only `true` or `false`
+    trace_macros!(false 1); //~ ERROR trace_macros! accepts only `true` or `false`
+
+
+    // should be fine:
+    macro_rules! expando {
+        ($x: ident) => { trace_macros!($x) }
+    }
+
+    expando!(true);
+}
diff --git a/src/test/ui/trace_macros-format.stderr b/src/test/ui/trace_macros-format.stderr
new file mode 100644
index 0000000..650b870
--- /dev/null
+++ b/src/test/ui/trace_macros-format.stderr
@@ -0,0 +1,38 @@
+error: trace_macros! accepts only `true` or `false`
+  --> $DIR/trace_macros-format.rs:4:5
+   |
+LL |     trace_macros!();
+   |     ^^^^^^^^^^^^^^^^
+
+error: trace_macros! accepts only `true` or `false`
+  --> $DIR/trace_macros-format.rs:5:5
+   |
+LL |     trace_macros!(1);
+   |     ^^^^^^^^^^^^^^^^^
+
+error: trace_macros! accepts only `true` or `false`
+  --> $DIR/trace_macros-format.rs:6:5
+   |
+LL |     trace_macros!(ident);
+   |     ^^^^^^^^^^^^^^^^^^^^^
+
+error: trace_macros! accepts only `true` or `false`
+  --> $DIR/trace_macros-format.rs:7:5
+   |
+LL |     trace_macros!(for);
+   |     ^^^^^^^^^^^^^^^^^^^
+
+error: trace_macros! accepts only `true` or `false`
+  --> $DIR/trace_macros-format.rs:8:5
+   |
+LL |     trace_macros!(true,);
+   |     ^^^^^^^^^^^^^^^^^^^^^
+
+error: trace_macros! accepts only `true` or `false`
+  --> $DIR/trace_macros-format.rs:9:5
+   |
+LL |     trace_macros!(false 1);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/trace_macros-gate.rs b/src/test/ui/trace_macros-gate.rs
new file mode 100644
index 0000000..c9af047
--- /dev/null
+++ b/src/test/ui/trace_macros-gate.rs
@@ -0,0 +1,14 @@
+// Test that the trace_macros feature gate is on.
+
+fn main() {
+    trace_macros!(); //~ ERROR `trace_macros` is not stable
+                     //~| ERROR trace_macros! accepts only `true` or `false`
+    trace_macros!(true); //~ ERROR `trace_macros` is not stable
+    trace_macros!(false); //~ ERROR `trace_macros` is not stable
+
+    macro_rules! expando {
+        ($x: ident) => { trace_macros!($x) } //~ ERROR `trace_macros` is not stable
+    }
+
+    expando!(true);
+}
diff --git a/src/test/ui/trace_macros-gate.stderr b/src/test/ui/trace_macros-gate.stderr
new file mode 100644
index 0000000..4d2fd55
--- /dev/null
+++ b/src/test/ui/trace_macros-gate.stderr
@@ -0,0 +1,44 @@
+error[E0658]: `trace_macros` is not stable enough for use and is subject to change (see issue #29598)
+  --> $DIR/trace_macros-gate.rs:4:5
+   |
+LL |     trace_macros!();
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(trace_macros)] to the crate attributes to enable
+
+error: trace_macros! accepts only `true` or `false`
+  --> $DIR/trace_macros-gate.rs:4:5
+   |
+LL |     trace_macros!();
+   |     ^^^^^^^^^^^^^^^^
+
+error[E0658]: `trace_macros` is not stable enough for use and is subject to change (see issue #29598)
+  --> $DIR/trace_macros-gate.rs:6:5
+   |
+LL |     trace_macros!(true);
+   |     ^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(trace_macros)] to the crate attributes to enable
+
+error[E0658]: `trace_macros` is not stable enough for use and is subject to change (see issue #29598)
+  --> $DIR/trace_macros-gate.rs:7:5
+   |
+LL |     trace_macros!(false);
+   |     ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(trace_macros)] to the crate attributes to enable
+
+error[E0658]: `trace_macros` is not stable enough for use and is subject to change (see issue #29598)
+  --> $DIR/trace_macros-gate.rs:10:26
+   |
+LL |         ($x: ident) => { trace_macros!($x) }
+   |                          ^^^^^^^^^^^^^^^^^
+...
+LL |     expando!(true);
+   |     --------------- in this macro invocation
+   |
+   = help: add #![feature(trace_macros)] to the crate attributes to enable
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/trait-method-number-parameters.rs b/src/test/ui/trait-method-number-parameters.rs
new file mode 100644
index 0000000..719005d
--- /dev/null
+++ b/src/test/ui/trait-method-number-parameters.rs
@@ -0,0 +1,13 @@
+trait Foo {
+    fn foo(&mut self, x: i32, y: i32) -> i32;
+}
+
+impl Foo for i32 {
+    fn foo(
+        &mut self, //~ ERROR
+        x: i32,
+    ) {
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/trait-method-number-parameters.stderr b/src/test/ui/trait-method-number-parameters.stderr
new file mode 100644
index 0000000..e47fe1a
--- /dev/null
+++ b/src/test/ui/trait-method-number-parameters.stderr
@@ -0,0 +1,13 @@
+error[E0050]: method `foo` has 2 parameters but the declaration in trait `Foo::foo` has 3
+  --> $DIR/trait-method-number-parameters.rs:7:9
+   |
+LL |       fn foo(&mut self, x: i32, y: i32) -> i32;
+   |              ------------------------- trait requires 3 parameters
+...
+LL | /         &mut self,
+LL | |         x: i32,
+   | |______________^ expected 3 parameters, found 2
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0050`.
diff --git a/src/test/ui/traits/auxiliary/crate_a1.rs b/src/test/ui/traits/auxiliary/crate_a1.rs
new file mode 100644
index 0000000..e2e1850
--- /dev/null
+++ b/src/test/ui/traits/auxiliary/crate_a1.rs
@@ -0,0 +1,11 @@
+pub struct Foo;
+
+pub trait Bar{}
+
+pub fn bar() -> Box<Bar> {
+    unimplemented!()
+}
+
+
+pub fn try_foo(x: Foo){}
+pub fn try_bar(x: Box<Bar>){}
diff --git a/src/test/ui/traits/auxiliary/trait_alias.rs b/src/test/ui/traits/auxiliary/trait_alias.rs
new file mode 100644
index 0000000..9e56b87
--- /dev/null
+++ b/src/test/ui/traits/auxiliary/trait_alias.rs
@@ -0,0 +1,3 @@
+#![feature(trait_alias)]
+
+pub trait SendSync = Send + Sync;
diff --git a/src/test/ui/traits/auxiliary/trait_bounds_on_structs_and_enums_xc.rs b/src/test/ui/traits/auxiliary/trait_bounds_on_structs_and_enums_xc.rs
new file mode 100644
index 0000000..7e9592e
--- /dev/null
+++ b/src/test/ui/traits/auxiliary/trait_bounds_on_structs_and_enums_xc.rs
@@ -0,0 +1,13 @@
+pub trait Trait {
+    fn dummy(&self) { }
+}
+
+pub struct Foo<T:Trait> {
+    pub x: T,
+}
+
+pub enum Bar<T:Trait> {
+    ABar(isize),
+    BBar(T),
+    CBar(usize),
+}
diff --git a/src/test/ui/traits/auxiliary/trait_safety_lib.rs b/src/test/ui/traits/auxiliary/trait_safety_lib.rs
new file mode 100644
index 0000000..6fc432e
--- /dev/null
+++ b/src/test/ui/traits/auxiliary/trait_safety_lib.rs
@@ -0,0 +1,9 @@
+// Simple smoke test that unsafe traits can be compiled etc.
+
+pub unsafe trait Foo {
+    fn foo(&self) -> isize;
+}
+
+unsafe impl Foo for isize {
+    fn foo(&self) -> isize { *self }
+}
diff --git a/src/test/ui/traits/conservative_impl_trait.rs b/src/test/ui/traits/conservative_impl_trait.rs
new file mode 100644
index 0000000..964e217
--- /dev/null
+++ b/src/test/ui/traits/conservative_impl_trait.rs
@@ -0,0 +1,8 @@
+// compile-pass
+// #39665
+
+fn batches(n: &u32) -> impl Iterator<Item=&u32> {
+    std::iter::once(n)
+}
+
+fn main() {}
diff --git a/src/test/ui/traits/trait-alias-ambiguous.rs b/src/test/ui/traits/trait-alias-ambiguous.rs
new file mode 100644
index 0000000..28409e0
--- /dev/null
+++ b/src/test/ui/traits/trait-alias-ambiguous.rs
@@ -0,0 +1,24 @@
+#![feature(trait_alias)]
+
+mod inner {
+    pub trait A { fn foo(&self); }
+    pub trait B { fn foo(&self); }
+
+    impl A for u8 {
+        fn foo(&self) {}
+    }
+    impl B for u8 {
+        fn foo(&self) {}
+    }
+
+    pub trait C = A + B;
+}
+
+use inner::C;
+
+fn main() {
+    let t = 1u8;
+    t.foo(); //~ ERROR E0034
+
+    inner::A::foo(&t); // ok
+}
diff --git a/src/test/ui/traits/trait-alias-ambiguous.stderr b/src/test/ui/traits/trait-alias-ambiguous.stderr
new file mode 100644
index 0000000..b744326
--- /dev/null
+++ b/src/test/ui/traits/trait-alias-ambiguous.stderr
@@ -0,0 +1,20 @@
+error[E0034]: multiple applicable items in scope
+  --> $DIR/trait-alias-ambiguous.rs:21:7
+   |
+LL |     t.foo();
+   |       ^^^ multiple `foo` found
+   |
+note: candidate #1 is defined in an impl of the trait `inner::A` for the type `u8`
+  --> $DIR/trait-alias-ambiguous.rs:8:9
+   |
+LL |         fn foo(&self) {}
+   |         ^^^^^^^^^^^^^
+note: candidate #2 is defined in an impl of the trait `inner::B` for the type `u8`
+  --> $DIR/trait-alias-ambiguous.rs:11:9
+   |
+LL |         fn foo(&self) {}
+   |         ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0034`.
diff --git a/src/test/ui/traits/trait-alias-cross-crate.rs b/src/test/ui/traits/trait-alias-cross-crate.rs
new file mode 100644
index 0000000..259fc4f
--- /dev/null
+++ b/src/test/ui/traits/trait-alias-cross-crate.rs
@@ -0,0 +1,17 @@
+// aux-build:trait_alias.rs
+
+#![feature(trait_alias)]
+
+extern crate trait_alias;
+
+use std::rc::Rc;
+use trait_alias::SendSync;
+
+fn use_alias<T: SendSync>() {}
+
+fn main() {
+    use_alias::<u32>();
+    use_alias::<Rc<u32>>();
+    //~^ ERROR `std::rc::Rc<u32>` cannot be sent between threads safely [E0277]
+    //~^^ ERROR `std::rc::Rc<u32>` cannot be shared between threads safely [E0277]
+}
diff --git a/src/test/ui/traits/trait-alias-cross-crate.stderr b/src/test/ui/traits/trait-alias-cross-crate.stderr
new file mode 100644
index 0000000..972d213
--- /dev/null
+++ b/src/test/ui/traits/trait-alias-cross-crate.stderr
@@ -0,0 +1,29 @@
+error[E0277]: `std::rc::Rc<u32>` cannot be sent between threads safely
+  --> $DIR/trait-alias-cross-crate.rs:14:5
+   |
+LL |     use_alias::<Rc<u32>>();
+   |     ^^^^^^^^^^^^^^^^^^^^ `std::rc::Rc<u32>` cannot be sent between threads safely
+   |
+   = help: the trait `std::marker::Send` is not implemented for `std::rc::Rc<u32>`
+note: required by `use_alias`
+  --> $DIR/trait-alias-cross-crate.rs:10:1
+   |
+LL | fn use_alias<T: SendSync>() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: `std::rc::Rc<u32>` cannot be shared between threads safely
+  --> $DIR/trait-alias-cross-crate.rs:14:5
+   |
+LL |     use_alias::<Rc<u32>>();
+   |     ^^^^^^^^^^^^^^^^^^^^ `std::rc::Rc<u32>` cannot be shared between threads safely
+   |
+   = help: the trait `std::marker::Sync` is not implemented for `std::rc::Rc<u32>`
+note: required by `use_alias`
+  --> $DIR/trait-alias-cross-crate.rs:10:1
+   |
+LL | fn use_alias<T: SendSync>() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/traits/trait-alias-impl.rs b/src/test/ui/traits/trait-alias-impl.rs
new file mode 100644
index 0000000..6e35793
--- /dev/null
+++ b/src/test/ui/traits/trait-alias-impl.rs
@@ -0,0 +1,7 @@
+#![feature(trait_alias)]
+
+trait DefaultAlias = Default;
+
+impl DefaultAlias for () {} //~ ERROR expected trait, found trait alias
+
+fn main() {}
diff --git a/src/test/ui/traits/trait-alias-impl.stderr b/src/test/ui/traits/trait-alias-impl.stderr
new file mode 100644
index 0000000..301db4f
--- /dev/null
+++ b/src/test/ui/traits/trait-alias-impl.stderr
@@ -0,0 +1,9 @@
+error[E0404]: expected trait, found trait alias `DefaultAlias`
+  --> $DIR/trait-alias-impl.rs:5:6
+   |
+LL | impl DefaultAlias for () {}
+   |      ^^^^^^^^^^^^ not a trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0404`.
diff --git a/src/test/ui/traits/trait-alias-object.rs b/src/test/ui/traits/trait-alias-object.rs
new file mode 100644
index 0000000..3796374
--- /dev/null
+++ b/src/test/ui/traits/trait-alias-object.rs
@@ -0,0 +1,9 @@
+#![feature(trait_alias)]
+
+trait EqAlias = Eq;
+trait IteratorAlias = Iterator;
+
+fn main() {
+    let _: &dyn EqAlias = &123; //~ ERROR `EqAlias` cannot be made into an object
+    let _: &dyn IteratorAlias = &vec![123].into_iter(); //~ ERROR must be specified
+}
diff --git a/src/test/ui/traits/trait-alias-object.stderr b/src/test/ui/traits/trait-alias-object.stderr
new file mode 100644
index 0000000..c6b61ea
--- /dev/null
+++ b/src/test/ui/traits/trait-alias-object.stderr
@@ -0,0 +1,18 @@
+error[E0038]: the trait `EqAlias` cannot be made into an object
+  --> $DIR/trait-alias-object.rs:7:13
+   |
+LL |     let _: &dyn EqAlias = &123;
+   |             ^^^^^^^^^^^ the trait `EqAlias` cannot be made into an object
+   |
+   = note: the trait cannot use `Self` as a type parameter in the supertraits or where-clauses
+
+error[E0191]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) must be specified
+  --> $DIR/trait-alias-object.rs:8:13
+   |
+LL |     let _: &dyn IteratorAlias = &vec![123].into_iter();
+   |             ^^^^^^^^^^^^^^^^^ associated type `Item` must be specified
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0038, E0191.
+For more information about an error, try `rustc --explain E0038`.
diff --git a/src/test/ui/traits/trait-alias-syntax.rs b/src/test/ui/traits/trait-alias-syntax.rs
new file mode 100644
index 0000000..5948d45
--- /dev/null
+++ b/src/test/ui/traits/trait-alias-syntax.rs
@@ -0,0 +1,7 @@
+#![feature(trait_alias)]
+
+trait Foo {}
+auto trait A = Foo; //~ ERROR trait aliases cannot be `auto`
+unsafe trait B = Foo; //~ ERROR trait aliases cannot be `unsafe`
+
+fn main() {}
diff --git a/src/test/ui/traits/trait-alias-syntax.stderr b/src/test/ui/traits/trait-alias-syntax.stderr
new file mode 100644
index 0000000..f99cc45
--- /dev/null
+++ b/src/test/ui/traits/trait-alias-syntax.stderr
@@ -0,0 +1,14 @@
+error: trait aliases cannot be `auto`
+  --> $DIR/trait-alias-syntax.rs:4:19
+   |
+LL | auto trait A = Foo;
+   |                   ^ trait aliases cannot be `auto`
+
+error: trait aliases cannot be `unsafe`
+  --> $DIR/trait-alias-syntax.rs:5:21
+   |
+LL | unsafe trait B = Foo;
+   |                     ^ trait aliases cannot be `unsafe`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/traits/trait-alias-wf.rs b/src/test/ui/traits/trait-alias-wf.rs
new file mode 100644
index 0000000..d10e2ab
--- /dev/null
+++ b/src/test/ui/traits/trait-alias-wf.rs
@@ -0,0 +1,7 @@
+#![feature(trait_alias)]
+
+trait Foo {}
+trait A<T: Foo> {}
+trait B<T> = A<T>; //~ ERROR `T: Foo` is not satisfied
+
+fn main() {}
diff --git a/src/test/ui/traits/trait-alias-wf.stderr b/src/test/ui/traits/trait-alias-wf.stderr
new file mode 100644
index 0000000..ee2dd5b
--- /dev/null
+++ b/src/test/ui/traits/trait-alias-wf.stderr
@@ -0,0 +1,16 @@
+error[E0277]: the trait bound `T: Foo` is not satisfied
+  --> $DIR/trait-alias-wf.rs:5:1
+   |
+LL | trait B<T> = A<T>;
+   | ^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `T`
+   |
+   = help: consider adding a `where T: Foo` bound
+note: required by `A`
+  --> $DIR/trait-alias-wf.rs:4:1
+   |
+LL | trait A<T: Foo> {}
+   | ^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/traits/trait-as-struct-constructor.rs b/src/test/ui/traits/trait-as-struct-constructor.rs
new file mode 100644
index 0000000..13ebf9d
--- /dev/null
+++ b/src/test/ui/traits/trait-as-struct-constructor.rs
@@ -0,0 +1,6 @@
+trait TraitNotAStruct {}
+
+fn main() {
+    TraitNotAStruct{ value: 0 };
+    //~^ ERROR expected struct, variant or union type, found trait `TraitNotAStruct`
+}
diff --git a/src/test/ui/traits/trait-as-struct-constructor.stderr b/src/test/ui/traits/trait-as-struct-constructor.stderr
new file mode 100644
index 0000000..e1d54fb
--- /dev/null
+++ b/src/test/ui/traits/trait-as-struct-constructor.stderr
@@ -0,0 +1,9 @@
+error[E0574]: expected struct, variant or union type, found trait `TraitNotAStruct`
+  --> $DIR/trait-as-struct-constructor.rs:4:5
+   |
+LL |     TraitNotAStruct{ value: 0 };
+   |     ^^^^^^^^^^^^^^^ not a struct, variant or union type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0574`.
diff --git a/src/test/ui/traits/trait-bounds-not-on-bare-trait.rs b/src/test/ui/traits/trait-bounds-not-on-bare-trait.rs
new file mode 100644
index 0000000..fd3af6f
--- /dev/null
+++ b/src/test/ui/traits/trait-bounds-not-on-bare-trait.rs
@@ -0,0 +1,11 @@
+trait Foo {
+    fn dummy(&self) { }
+}
+
+// This should emit the less confusing error, not the more confusing one.
+
+fn foo(_x: Foo + Send) {
+    //~^ ERROR the size for values of type
+}
+
+fn main() { }
diff --git a/src/test/ui/traits/trait-bounds-not-on-bare-trait.stderr b/src/test/ui/traits/trait-bounds-not-on-bare-trait.stderr
new file mode 100644
index 0000000..5aee1e7
--- /dev/null
+++ b/src/test/ui/traits/trait-bounds-not-on-bare-trait.stderr
@@ -0,0 +1,14 @@
+error[E0277]: the size for values of type `(dyn Foo + std::marker::Send + 'static)` cannot be known at compilation time
+  --> $DIR/trait-bounds-not-on-bare-trait.rs:7:8
+   |
+LL | fn foo(_x: Foo + Send) {
+   |        ^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `(dyn Foo + std::marker::Send + 'static)`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: all local variables must have a statically known size
+   = help: unsized locals are gated as an unstable feature
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/traits/trait-bounds-not-on-struct.rs b/src/test/ui/traits/trait-bounds-not-on-struct.rs
new file mode 100644
index 0000000..c6e93e7
--- /dev/null
+++ b/src/test/ui/traits/trait-bounds-not-on-struct.rs
@@ -0,0 +1,9 @@
+#![allow(bare_trait_objects)]
+
+struct Foo;
+
+fn foo(_x: Box<Foo + Send>) { } //~ ERROR expected trait, found struct `Foo`
+
+type A<T> = Box<dyn Vec<T>>; //~ ERROR expected trait, found struct `Vec`
+
+fn main() { }
diff --git a/src/test/ui/traits/trait-bounds-not-on-struct.stderr b/src/test/ui/traits/trait-bounds-not-on-struct.stderr
new file mode 100644
index 0000000..a649a4e
--- /dev/null
+++ b/src/test/ui/traits/trait-bounds-not-on-struct.stderr
@@ -0,0 +1,15 @@
+error[E0404]: expected trait, found struct `Foo`
+  --> $DIR/trait-bounds-not-on-struct.rs:5:16
+   |
+LL | fn foo(_x: Box<Foo + Send>) { }
+   |                ^^^ not a trait
+
+error[E0404]: expected trait, found struct `Vec`
+  --> $DIR/trait-bounds-not-on-struct.rs:7:21
+   |
+LL | type A<T> = Box<dyn Vec<T>>;
+   |                     ^^^^^^ not a trait
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0404`.
diff --git a/src/test/ui/traits/trait-bounds-on-structs-and-enums-in-fns.rs b/src/test/ui/traits/trait-bounds-on-structs-and-enums-in-fns.rs
new file mode 100644
index 0000000..6a6fcf5
--- /dev/null
+++ b/src/test/ui/traits/trait-bounds-on-structs-and-enums-in-fns.rs
@@ -0,0 +1,20 @@
+trait Trait {}
+
+struct Foo<T:Trait> {
+    x: T,
+}
+
+enum Bar<T:Trait> {
+    ABar(isize),
+    BBar(T),
+    CBar(usize),
+}
+
+fn explode(x: Foo<u32>) {}
+//~^ ERROR E0277
+
+fn kaboom(y: Bar<f32>) {}
+//~^ ERROR E0277
+
+fn main() {
+}
diff --git a/src/test/ui/traits/trait-bounds-on-structs-and-enums-in-fns.stderr b/src/test/ui/traits/trait-bounds-on-structs-and-enums-in-fns.stderr
new file mode 100644
index 0000000..6fdd2ce
--- /dev/null
+++ b/src/test/ui/traits/trait-bounds-on-structs-and-enums-in-fns.stderr
@@ -0,0 +1,27 @@
+error[E0277]: the trait bound `u32: Trait` is not satisfied
+  --> $DIR/trait-bounds-on-structs-and-enums-in-fns.rs:13:1
+   |
+LL | fn explode(x: Foo<u32>) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `u32`
+   |
+note: required by `Foo`
+  --> $DIR/trait-bounds-on-structs-and-enums-in-fns.rs:3:1
+   |
+LL | struct Foo<T:Trait> {
+   | ^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `f32: Trait` is not satisfied
+  --> $DIR/trait-bounds-on-structs-and-enums-in-fns.rs:16:1
+   |
+LL | fn kaboom(y: Bar<f32>) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `f32`
+   |
+note: required by `Bar`
+  --> $DIR/trait-bounds-on-structs-and-enums-in-fns.rs:7:1
+   |
+LL | enum Bar<T:Trait> {
+   | ^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/traits/trait-bounds-on-structs-and-enums-in-impls.rs b/src/test/ui/traits/trait-bounds-on-structs-and-enums-in-impls.rs
new file mode 100644
index 0000000..d379499
--- /dev/null
+++ b/src/test/ui/traits/trait-bounds-on-structs-and-enums-in-impls.rs
@@ -0,0 +1,25 @@
+trait Trait {}
+
+struct Foo<T:Trait> {
+    x: T,
+}
+
+enum Bar<T:Trait> {
+    ABar(isize),
+    BBar(T),
+    CBar(usize),
+}
+
+trait PolyTrait<T>
+{
+    fn whatever(&self, t: T) {}
+}
+
+struct Struct;
+
+impl PolyTrait<Foo<u16>> for Struct {
+//~^ ERROR E0277
+}
+
+fn main() {
+}
diff --git a/src/test/ui/traits/trait-bounds-on-structs-and-enums-in-impls.stderr b/src/test/ui/traits/trait-bounds-on-structs-and-enums-in-impls.stderr
new file mode 100644
index 0000000..15441b5
--- /dev/null
+++ b/src/test/ui/traits/trait-bounds-on-structs-and-enums-in-impls.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `u16: Trait` is not satisfied
+  --> $DIR/trait-bounds-on-structs-and-enums-in-impls.rs:20:6
+   |
+LL | impl PolyTrait<Foo<u16>> for Struct {
+   |      ^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `u16`
+   |
+note: required by `Foo`
+  --> $DIR/trait-bounds-on-structs-and-enums-in-impls.rs:3:1
+   |
+LL | struct Foo<T:Trait> {
+   | ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/traits/trait-bounds-on-structs-and-enums-locals.rs b/src/test/ui/traits/trait-bounds-on-structs-and-enums-locals.rs
new file mode 100644
index 0000000..21c0ce8
--- /dev/null
+++ b/src/test/ui/traits/trait-bounds-on-structs-and-enums-locals.rs
@@ -0,0 +1,17 @@
+trait Trait {
+    fn dummy(&self) { }
+}
+
+struct Foo<T:Trait> {
+    x: T,
+}
+
+fn main() {
+    let foo = Foo {
+    //~^ ERROR E0277
+        x: 3
+    };
+
+    let baz: Foo<usize> = loop { };
+    //~^ ERROR E0277
+}
diff --git a/src/test/ui/traits/trait-bounds-on-structs-and-enums-locals.stderr b/src/test/ui/traits/trait-bounds-on-structs-and-enums-locals.stderr
new file mode 100644
index 0000000..cdcfff9
--- /dev/null
+++ b/src/test/ui/traits/trait-bounds-on-structs-and-enums-locals.stderr
@@ -0,0 +1,27 @@
+error[E0277]: the trait bound `usize: Trait` is not satisfied
+  --> $DIR/trait-bounds-on-structs-and-enums-locals.rs:15:14
+   |
+LL |     let baz: Foo<usize> = loop { };
+   |              ^^^^^^^^^^ the trait `Trait` is not implemented for `usize`
+   |
+note: required by `Foo`
+  --> $DIR/trait-bounds-on-structs-and-enums-locals.rs:5:1
+   |
+LL | struct Foo<T:Trait> {
+   | ^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `{integer}: Trait` is not satisfied
+  --> $DIR/trait-bounds-on-structs-and-enums-locals.rs:10:15
+   |
+LL |     let foo = Foo {
+   |               ^^^ the trait `Trait` is not implemented for `{integer}`
+   |
+note: required by `Foo`
+  --> $DIR/trait-bounds-on-structs-and-enums-locals.rs:5:1
+   |
+LL | struct Foo<T:Trait> {
+   | ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/traits/trait-bounds-on-structs-and-enums-static.rs b/src/test/ui/traits/trait-bounds-on-structs-and-enums-static.rs
new file mode 100644
index 0000000..df3f8b8
--- /dev/null
+++ b/src/test/ui/traits/trait-bounds-on-structs-and-enums-static.rs
@@ -0,0 +1,15 @@
+trait Trait {
+    fn dummy(&self) { }
+}
+
+struct Foo<T:Trait> {
+    x: T,
+}
+
+static X: Foo<usize> = Foo {
+//~^ ERROR E0277
+    x: 1,
+};
+
+fn main() {
+}
diff --git a/src/test/ui/traits/trait-bounds-on-structs-and-enums-static.stderr b/src/test/ui/traits/trait-bounds-on-structs-and-enums-static.stderr
new file mode 100644
index 0000000..b019c29
--- /dev/null
+++ b/src/test/ui/traits/trait-bounds-on-structs-and-enums-static.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `usize: Trait` is not satisfied
+  --> $DIR/trait-bounds-on-structs-and-enums-static.rs:9:11
+   |
+LL | static X: Foo<usize> = Foo {
+   |           ^^^^^^^^^^ the trait `Trait` is not implemented for `usize`
+   |
+note: required by `Foo`
+  --> $DIR/trait-bounds-on-structs-and-enums-static.rs:5:1
+   |
+LL | struct Foo<T:Trait> {
+   | ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/traits/trait-bounds-on-structs-and-enums-xc.rs b/src/test/ui/traits/trait-bounds-on-structs-and-enums-xc.rs
new file mode 100644
index 0000000..901a2c4
--- /dev/null
+++ b/src/test/ui/traits/trait-bounds-on-structs-and-enums-xc.rs
@@ -0,0 +1,14 @@
+// aux-build:trait_bounds_on_structs_and_enums_xc.rs
+
+extern crate trait_bounds_on_structs_and_enums_xc;
+
+use trait_bounds_on_structs_and_enums_xc::{Bar, Foo, Trait};
+
+fn explode(x: Foo<usize>) {}
+//~^ ERROR E0277
+
+fn kaboom(y: Bar<f32>) {}
+//~^ ERROR E0277
+
+fn main() {
+}
diff --git a/src/test/ui/traits/trait-bounds-on-structs-and-enums-xc.stderr b/src/test/ui/traits/trait-bounds-on-structs-and-enums-xc.stderr
new file mode 100644
index 0000000..2f2c903
--- /dev/null
+++ b/src/test/ui/traits/trait-bounds-on-structs-and-enums-xc.stderr
@@ -0,0 +1,19 @@
+error[E0277]: the trait bound `usize: trait_bounds_on_structs_and_enums_xc::Trait` is not satisfied
+  --> $DIR/trait-bounds-on-structs-and-enums-xc.rs:7:1
+   |
+LL | fn explode(x: Foo<usize>) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `trait_bounds_on_structs_and_enums_xc::Trait` is not implemented for `usize`
+   |
+   = note: required by `trait_bounds_on_structs_and_enums_xc::Foo`
+
+error[E0277]: the trait bound `f32: trait_bounds_on_structs_and_enums_xc::Trait` is not satisfied
+  --> $DIR/trait-bounds-on-structs-and-enums-xc.rs:10:1
+   |
+LL | fn kaboom(y: Bar<f32>) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `trait_bounds_on_structs_and_enums_xc::Trait` is not implemented for `f32`
+   |
+   = note: required by `trait_bounds_on_structs_and_enums_xc::Bar`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/traits/trait-bounds-on-structs-and-enums-xc1.rs b/src/test/ui/traits/trait-bounds-on-structs-and-enums-xc1.rs
new file mode 100644
index 0000000..2a4ba96
--- /dev/null
+++ b/src/test/ui/traits/trait-bounds-on-structs-and-enums-xc1.rs
@@ -0,0 +1,15 @@
+// aux-build:trait_bounds_on_structs_and_enums_xc.rs
+
+extern crate trait_bounds_on_structs_and_enums_xc;
+
+use trait_bounds_on_structs_and_enums_xc::{Bar, Foo, Trait};
+
+fn main() {
+    let foo = Foo {
+    //~^ ERROR E0277
+        x: 3
+    };
+    let bar: Bar<f64> = return;
+    //~^ ERROR E0277
+    let _ = bar;
+}
diff --git a/src/test/ui/traits/trait-bounds-on-structs-and-enums-xc1.stderr b/src/test/ui/traits/trait-bounds-on-structs-and-enums-xc1.stderr
new file mode 100644
index 0000000..57db65d
--- /dev/null
+++ b/src/test/ui/traits/trait-bounds-on-structs-and-enums-xc1.stderr
@@ -0,0 +1,19 @@
+error[E0277]: the trait bound `f64: trait_bounds_on_structs_and_enums_xc::Trait` is not satisfied
+  --> $DIR/trait-bounds-on-structs-and-enums-xc1.rs:12:14
+   |
+LL |     let bar: Bar<f64> = return;
+   |              ^^^^^^^^ the trait `trait_bounds_on_structs_and_enums_xc::Trait` is not implemented for `f64`
+   |
+   = note: required by `trait_bounds_on_structs_and_enums_xc::Bar`
+
+error[E0277]: the trait bound `{integer}: trait_bounds_on_structs_and_enums_xc::Trait` is not satisfied
+  --> $DIR/trait-bounds-on-structs-and-enums-xc1.rs:8:15
+   |
+LL |     let foo = Foo {
+   |               ^^^ the trait `trait_bounds_on_structs_and_enums_xc::Trait` is not implemented for `{integer}`
+   |
+   = note: required by `trait_bounds_on_structs_and_enums_xc::Foo`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/traits/trait-bounds-on-structs-and-enums.rs b/src/test/ui/traits/trait-bounds-on-structs-and-enums.rs
new file mode 100644
index 0000000..024084f
--- /dev/null
+++ b/src/test/ui/traits/trait-bounds-on-structs-and-enums.rs
@@ -0,0 +1,43 @@
+trait Trait {}
+
+struct Foo<T:Trait> {
+    x: T,
+}
+
+enum Bar<T:Trait> {
+    ABar(isize),
+    BBar(T),
+    CBar(usize),
+}
+
+impl<T> Foo<T> {
+//~^ ERROR `T: Trait` is not satisfied
+    fn uhoh() {}
+}
+
+struct Baz {
+    a: Foo<isize>, //~ ERROR E0277
+}
+
+enum Boo {
+    Quux(Bar<usize>), //~ ERROR E0277
+}
+
+struct Badness<U> {
+    b: Foo<U>, //~ ERROR E0277
+}
+
+enum MoreBadness<V> {
+    EvenMoreBadness(Bar<V>), //~ ERROR E0277
+}
+
+struct TupleLike(
+    Foo<i32>, //~ ERROR E0277
+);
+
+enum Enum {
+    DictionaryLike { field: Bar<u8> }, //~ ERROR E0277
+}
+
+fn main() {
+}
diff --git a/src/test/ui/traits/trait-bounds-on-structs-and-enums.stderr b/src/test/ui/traits/trait-bounds-on-structs-and-enums.stderr
new file mode 100644
index 0000000..9a4cc90
--- /dev/null
+++ b/src/test/ui/traits/trait-bounds-on-structs-and-enums.stderr
@@ -0,0 +1,90 @@
+error[E0277]: the trait bound `T: Trait` is not satisfied
+  --> $DIR/trait-bounds-on-structs-and-enums.rs:13:9
+   |
+LL | impl<T> Foo<T> {
+   |         ^^^^^^ the trait `Trait` is not implemented for `T`
+   |
+   = help: consider adding a `where T: Trait` bound
+note: required by `Foo`
+  --> $DIR/trait-bounds-on-structs-and-enums.rs:3:1
+   |
+LL | struct Foo<T:Trait> {
+   | ^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `isize: Trait` is not satisfied
+  --> $DIR/trait-bounds-on-structs-and-enums.rs:19:5
+   |
+LL |     a: Foo<isize>,
+   |     ^^^^^^^^^^^^^ the trait `Trait` is not implemented for `isize`
+   |
+note: required by `Foo`
+  --> $DIR/trait-bounds-on-structs-and-enums.rs:3:1
+   |
+LL | struct Foo<T:Trait> {
+   | ^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `usize: Trait` is not satisfied
+  --> $DIR/trait-bounds-on-structs-and-enums.rs:23:10
+   |
+LL |     Quux(Bar<usize>),
+   |          ^^^^^^^^^^ the trait `Trait` is not implemented for `usize`
+   |
+note: required by `Bar`
+  --> $DIR/trait-bounds-on-structs-and-enums.rs:7:1
+   |
+LL | enum Bar<T:Trait> {
+   | ^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `U: Trait` is not satisfied
+  --> $DIR/trait-bounds-on-structs-and-enums.rs:27:5
+   |
+LL |     b: Foo<U>,
+   |     ^^^^^^^^^ the trait `Trait` is not implemented for `U`
+   |
+   = help: consider adding a `where U: Trait` bound
+note: required by `Foo`
+  --> $DIR/trait-bounds-on-structs-and-enums.rs:3:1
+   |
+LL | struct Foo<T:Trait> {
+   | ^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `V: Trait` is not satisfied
+  --> $DIR/trait-bounds-on-structs-and-enums.rs:31:21
+   |
+LL |     EvenMoreBadness(Bar<V>),
+   |                     ^^^^^^ the trait `Trait` is not implemented for `V`
+   |
+   = help: consider adding a `where V: Trait` bound
+note: required by `Bar`
+  --> $DIR/trait-bounds-on-structs-and-enums.rs:7:1
+   |
+LL | enum Bar<T:Trait> {
+   | ^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `i32: Trait` is not satisfied
+  --> $DIR/trait-bounds-on-structs-and-enums.rs:35:5
+   |
+LL |     Foo<i32>,
+   |     ^^^^^^^^ the trait `Trait` is not implemented for `i32`
+   |
+note: required by `Foo`
+  --> $DIR/trait-bounds-on-structs-and-enums.rs:3:1
+   |
+LL | struct Foo<T:Trait> {
+   | ^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `u8: Trait` is not satisfied
+  --> $DIR/trait-bounds-on-structs-and-enums.rs:39:22
+   |
+LL |     DictionaryLike { field: Bar<u8> },
+   |                      ^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `u8`
+   |
+note: required by `Bar`
+  --> $DIR/trait-bounds-on-structs-and-enums.rs:7:1
+   |
+LL | enum Bar<T:Trait> {
+   | ^^^^^^^^^^^^^^^^^
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/traits/trait-bounds-sugar.rs b/src/test/ui/traits/trait-bounds-sugar.rs
new file mode 100644
index 0000000..0892153
--- /dev/null
+++ b/src/test/ui/traits/trait-bounds-sugar.rs
@@ -0,0 +1,19 @@
+// Tests for "default" bounds inferred for traits with no bounds list.
+
+trait Foo {}
+
+fn a(_x: Box<Foo+Send>) {
+}
+
+fn b(_x: &'static (Foo+'static)) {
+}
+
+fn c(x: Box<Foo+Sync>) {
+    a(x); //~ ERROR mismatched types
+}
+
+fn d(x: &'static (Foo+Sync)) {
+    b(x);
+}
+
+fn main() {}
diff --git a/src/test/ui/traits/trait-bounds-sugar.stderr b/src/test/ui/traits/trait-bounds-sugar.stderr
new file mode 100644
index 0000000..2aa025c
--- /dev/null
+++ b/src/test/ui/traits/trait-bounds-sugar.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/trait-bounds-sugar.rs:12:7
+   |
+LL |     a(x);
+   |       ^ expected trait `Foo + std::marker::Send`, found trait `Foo + std::marker::Sync`
+   |
+   = note: expected type `std::boxed::Box<(dyn Foo + std::marker::Send + 'static)>`
+              found type `std::boxed::Box<(dyn Foo + std::marker::Sync + 'static)>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/traits/trait-coercion-generic-bad.rs b/src/test/ui/traits/trait-coercion-generic-bad.rs
new file mode 100644
index 0000000..5aa2183
--- /dev/null
+++ b/src/test/ui/traits/trait-coercion-generic-bad.rs
@@ -0,0 +1,19 @@
+struct Struct {
+    person: &'static str
+}
+
+trait Trait<T> {
+    fn f(&self, x: T);
+}
+
+impl Trait<&'static str> for Struct {
+    fn f(&self, x: &'static str) {
+        println!("Hello, {}!", x);
+    }
+}
+
+fn main() {
+    let s: Box<Trait<isize>> = Box::new(Struct { person: "Fred" });
+    //~^ ERROR `Struct: Trait<isize>` is not satisfied
+    s.f(1);
+}
diff --git a/src/test/ui/traits/trait-coercion-generic-bad.stderr b/src/test/ui/traits/trait-coercion-generic-bad.stderr
new file mode 100644
index 0000000..7f3b46b
--- /dev/null
+++ b/src/test/ui/traits/trait-coercion-generic-bad.stderr
@@ -0,0 +1,13 @@
+error[E0277]: the trait bound `Struct: Trait<isize>` is not satisfied
+  --> $DIR/trait-coercion-generic-bad.rs:16:32
+   |
+LL |     let s: Box<Trait<isize>> = Box::new(Struct { person: "Fred" });
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait<isize>` is not implemented for `Struct`
+   |
+   = help: the following implementations were found:
+             <Struct as Trait<&'static str>>
+   = note: required for the cast to the object type `dyn Trait<isize>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/traits/trait-coercion-generic-regions.nll.stderr b/src/test/ui/traits/trait-coercion-generic-regions.nll.stderr
new file mode 100644
index 0000000..4ee3e4c
--- /dev/null
+++ b/src/test/ui/traits/trait-coercion-generic-regions.nll.stderr
@@ -0,0 +1,15 @@
+error[E0597]: `person` does not live long enough
+  --> $DIR/trait-coercion-generic-regions.rs:17:24
+   |
+LL |     let person: &str = &person;
+   |                        ^^^^^^^
+   |                        |
+   |                        borrowed value does not live long enough
+   |                        assignment requires that `person` is borrowed for `'static`
+LL |     let s: Box<Trait<&'static str>> = Box::new(Struct { person: person });
+LL | }
+   | - `person` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/traits/trait-coercion-generic-regions.rs b/src/test/ui/traits/trait-coercion-generic-regions.rs
new file mode 100644
index 0000000..148b7dd
--- /dev/null
+++ b/src/test/ui/traits/trait-coercion-generic-regions.rs
@@ -0,0 +1,19 @@
+struct Struct {
+    person: &'static str
+}
+
+trait Trait<T> {
+    fn f(&self, x: T);
+}
+
+impl Trait<&'static str> for Struct {
+    fn f(&self, x: &'static str) {
+        println!("Hello, {}!", x);
+    }
+}
+
+fn main() {
+    let person = "Fred".to_string();
+    let person: &str = &person;  //~ ERROR `person` does not live long enough
+    let s: Box<Trait<&'static str>> = Box::new(Struct { person: person });
+}
diff --git a/src/test/ui/traits/trait-coercion-generic-regions.stderr b/src/test/ui/traits/trait-coercion-generic-regions.stderr
new file mode 100644
index 0000000..2a9ca4f
--- /dev/null
+++ b/src/test/ui/traits/trait-coercion-generic-regions.stderr
@@ -0,0 +1,14 @@
+error[E0597]: `person` does not live long enough
+  --> $DIR/trait-coercion-generic-regions.rs:17:25
+   |
+LL |     let person: &str = &person;
+   |                         ^^^^^^ borrowed value does not live long enough
+LL |     let s: Box<Trait<&'static str>> = Box::new(Struct { person: person });
+LL | }
+   | - borrowed value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/traits/trait-duplicate-methods.rs b/src/test/ui/traits/trait-duplicate-methods.rs
new file mode 100644
index 0000000..1f9bdf5
--- /dev/null
+++ b/src/test/ui/traits/trait-duplicate-methods.rs
@@ -0,0 +1,6 @@
+trait Foo {
+    fn orange(&self);
+    fn orange(&self); //~ ERROR the name `orange` is defined multiple times
+}
+
+fn main() {}
diff --git a/src/test/ui/traits/trait-duplicate-methods.stderr b/src/test/ui/traits/trait-duplicate-methods.stderr
new file mode 100644
index 0000000..7cba4cb
--- /dev/null
+++ b/src/test/ui/traits/trait-duplicate-methods.stderr
@@ -0,0 +1,13 @@
+error[E0428]: the name `orange` is defined multiple times
+  --> $DIR/trait-duplicate-methods.rs:3:5
+   |
+LL |     fn orange(&self);
+   |     ----------------- previous definition of the value `orange` here
+LL |     fn orange(&self);
+   |     ^^^^^^^^^^^^^^^^^ `orange` redefined here
+   |
+   = note: `orange` must be defined only once in the value namespace of this trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0428`.
diff --git a/src/test/ui/traits/trait-impl-1.rs b/src/test/ui/traits/trait-impl-1.rs
new file mode 100644
index 0000000..29f58a6
--- /dev/null
+++ b/src/test/ui/traits/trait-impl-1.rs
@@ -0,0 +1,16 @@
+// Test calling methods on an impl for a bare trait. This test checks that the
+// trait impl is only applied to a trait object, not concrete types which implement
+// the trait.
+
+trait T {}
+
+impl<'a> T+'a {
+    fn foo(&self) {}
+}
+
+impl T for i32 {}
+
+fn main() {
+    let x = &42i32;
+    x.foo(); //~ERROR: no method named `foo` found for type `&i32` in the current scope
+}
diff --git a/src/test/ui/traits/trait-impl-1.stderr b/src/test/ui/traits/trait-impl-1.stderr
new file mode 100644
index 0000000..71d5cc2
--- /dev/null
+++ b/src/test/ui/traits/trait-impl-1.stderr
@@ -0,0 +1,9 @@
+error[E0599]: no method named `foo` found for type `&i32` in the current scope
+  --> $DIR/trait-impl-1.rs:15:7
+   |
+LL |     x.foo();
+   |       ^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/traits/trait-impl-can-not-have-untraitful-items.rs b/src/test/ui/traits/trait-impl-can-not-have-untraitful-items.rs
new file mode 100644
index 0000000..0c88544
--- /dev/null
+++ b/src/test/ui/traits/trait-impl-can-not-have-untraitful-items.rs
@@ -0,0 +1,9 @@
+trait A { }
+
+impl A for isize {
+    const BAR: () = (); //~ ERROR const `BAR` is not a member of trait `A`
+    type Baz = (); //~ ERROR type `Baz` is not a member of trait `A`
+    fn foo(&self) { } //~ ERROR method `foo` is not a member of trait `A`
+}
+
+fn main() { }
diff --git a/src/test/ui/traits/trait-impl-can-not-have-untraitful-items.stderr b/src/test/ui/traits/trait-impl-can-not-have-untraitful-items.stderr
new file mode 100644
index 0000000..84565bd
--- /dev/null
+++ b/src/test/ui/traits/trait-impl-can-not-have-untraitful-items.stderr
@@ -0,0 +1,22 @@
+error[E0438]: const `BAR` is not a member of trait `A`
+  --> $DIR/trait-impl-can-not-have-untraitful-items.rs:4:5
+   |
+LL |     const BAR: () = ();
+   |     ^^^^^^^^^^^^^^^^^^^ not a member of trait `A`
+
+error[E0437]: type `Baz` is not a member of trait `A`
+  --> $DIR/trait-impl-can-not-have-untraitful-items.rs:5:5
+   |
+LL |     type Baz = ();
+   |     ^^^^^^^^^^^^^^ not a member of trait `A`
+
+error[E0407]: method `foo` is not a member of trait `A`
+  --> $DIR/trait-impl-can-not-have-untraitful-items.rs:6:5
+   |
+LL |     fn foo(&self) { }
+   |     ^^^^^^^^^^^^^^^^^ not a member of trait `A`
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0407, E0437, E0438.
+For more information about an error, try `rustc --explain E0407`.
diff --git a/src/test/ui/traits/trait-impl-different-num-params.rs b/src/test/ui/traits/trait-impl-different-num-params.rs
new file mode 100644
index 0000000..5340062
--- /dev/null
+++ b/src/test/ui/traits/trait-impl-different-num-params.rs
@@ -0,0 +1,12 @@
+trait Foo {
+    fn bar(&self, x: usize) -> Self;
+}
+impl Foo for isize {
+    fn bar(&self) -> isize {
+        //~^ ERROR method `bar` has 1 parameter but the declaration in trait `Foo::bar` has 2
+        *self
+    }
+}
+
+fn main() {
+}
diff --git a/src/test/ui/traits/trait-impl-different-num-params.stderr b/src/test/ui/traits/trait-impl-different-num-params.stderr
new file mode 100644
index 0000000..5ab9361
--- /dev/null
+++ b/src/test/ui/traits/trait-impl-different-num-params.stderr
@@ -0,0 +1,12 @@
+error[E0050]: method `bar` has 1 parameter but the declaration in trait `Foo::bar` has 2
+  --> $DIR/trait-impl-different-num-params.rs:5:12
+   |
+LL |     fn bar(&self, x: usize) -> Self;
+   |            --------------- trait requires 2 parameters
+...
+LL |     fn bar(&self) -> isize {
+   |            ^^^^^ expected 2 parameters, found 1
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0050`.
diff --git a/src/test/ui/traits/trait-impl-for-module.rs b/src/test/ui/traits/trait-impl-for-module.rs
new file mode 100644
index 0000000..9004627
--- /dev/null
+++ b/src/test/ui/traits/trait-impl-for-module.rs
@@ -0,0 +1,11 @@
+mod a {
+}
+
+trait A {
+}
+
+impl A for a { //~ ERROR expected type, found module
+}
+
+fn main() {
+}
diff --git a/src/test/ui/traits/trait-impl-for-module.stderr b/src/test/ui/traits/trait-impl-for-module.stderr
new file mode 100644
index 0000000..c62bcfc
--- /dev/null
+++ b/src/test/ui/traits/trait-impl-for-module.stderr
@@ -0,0 +1,9 @@
+error[E0573]: expected type, found module `a`
+  --> $DIR/trait-impl-for-module.rs:7:12
+   |
+LL | impl A for a {
+   |            ^ help: a trait with a similar name exists: `A`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0573`.
diff --git a/src/test/ui/traits/trait-impl-method-mismatch.rs b/src/test/ui/traits/trait-impl-method-mismatch.rs
new file mode 100644
index 0000000..886e926
--- /dev/null
+++ b/src/test/ui/traits/trait-impl-method-mismatch.rs
@@ -0,0 +1,13 @@
+trait Mumbo {
+    fn jumbo(&self, x: &usize) -> usize;
+}
+
+impl Mumbo for usize {
+    // Cannot have a larger effect than the trait:
+    unsafe fn jumbo(&self, x: &usize) { *self + *x; }
+    //~^ ERROR method `jumbo` has an incompatible type for trait
+    //~| expected type `fn
+    //~| found type `unsafe fn
+}
+
+fn main() {}
diff --git a/src/test/ui/traits/trait-impl-method-mismatch.stderr b/src/test/ui/traits/trait-impl-method-mismatch.stderr
new file mode 100644
index 0000000..3e86c97
--- /dev/null
+++ b/src/test/ui/traits/trait-impl-method-mismatch.stderr
@@ -0,0 +1,15 @@
+error[E0053]: method `jumbo` has an incompatible type for trait
+  --> $DIR/trait-impl-method-mismatch.rs:7:5
+   |
+LL |     fn jumbo(&self, x: &usize) -> usize;
+   |     ------------------------------------ type in trait
+...
+LL |     unsafe fn jumbo(&self, x: &usize) { *self + *x; }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected normal fn, found unsafe fn
+   |
+   = note: expected type `fn(&usize, &usize) -> usize`
+              found type `unsafe fn(&usize, &usize)`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0053`.
diff --git a/src/test/ui/traits/trait-impl-of-supertrait-has-wrong-lifetime-parameters.rs b/src/test/ui/traits/trait-impl-of-supertrait-has-wrong-lifetime-parameters.rs
new file mode 100644
index 0000000..05b9db9
--- /dev/null
+++ b/src/test/ui/traits/trait-impl-of-supertrait-has-wrong-lifetime-parameters.rs
@@ -0,0 +1,31 @@
+// Check that when we test the supertrait we ensure consistent use of
+// lifetime parameters. In this case, implementing T2<'a,'b> requires
+// an impl of T1<'a>, but we have an impl of T1<'b>.
+
+trait T1<'x> {
+    fn x(&self) -> &'x isize;
+}
+
+trait T2<'x, 'y> : T1<'x> {
+    fn y(&self) -> &'y isize;
+}
+
+struct S<'a, 'b> {
+    a: &'a isize,
+    b: &'b isize
+}
+
+impl<'a,'b> T1<'b> for S<'a, 'b> {
+    fn x(&self) -> &'b isize {
+        self.b
+    }
+}
+
+impl<'a,'b> T2<'a, 'b> for S<'a, 'b> { //~ ERROR cannot infer an appropriate lifetime
+    fn y(&self) -> &'b isize {
+        self.b
+    }
+}
+
+pub fn main() {
+}
diff --git a/src/test/ui/traits/trait-impl-of-supertrait-has-wrong-lifetime-parameters.stderr b/src/test/ui/traits/trait-impl-of-supertrait-has-wrong-lifetime-parameters.stderr
new file mode 100644
index 0000000..4c63d60
--- /dev/null
+++ b/src/test/ui/traits/trait-impl-of-supertrait-has-wrong-lifetime-parameters.stderr
@@ -0,0 +1,23 @@
+error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'b` due to conflicting requirements
+  --> $DIR/trait-impl-of-supertrait-has-wrong-lifetime-parameters.rs:24:13
+   |
+LL | impl<'a,'b> T2<'a, 'b> for S<'a, 'b> {
+   |             ^^^^^^^^^^
+   |
+note: first, the lifetime cannot outlive the lifetime 'a as defined on the impl at 24:6...
+  --> $DIR/trait-impl-of-supertrait-has-wrong-lifetime-parameters.rs:24:6
+   |
+LL | impl<'a,'b> T2<'a, 'b> for S<'a, 'b> {
+   |      ^^
+note: ...but the lifetime must also be valid for the lifetime 'b as defined on the impl at 24:9...
+  --> $DIR/trait-impl-of-supertrait-has-wrong-lifetime-parameters.rs:24:9
+   |
+LL | impl<'a,'b> T2<'a, 'b> for S<'a, 'b> {
+   |         ^^
+   = note: ...so that the types are compatible:
+           expected T1<'a>
+              found T1<'_>
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0495`.
diff --git a/src/test/ui/traits/trait-item-privacy.rs b/src/test/ui/traits/trait-item-privacy.rs
new file mode 100644
index 0000000..dfc8c8f
--- /dev/null
+++ b/src/test/ui/traits/trait-item-privacy.rs
@@ -0,0 +1,134 @@
+#![feature(associated_type_defaults)]
+
+struct S;
+
+mod method {
+    trait A {
+        fn a(&self) { }
+    }
+
+    pub trait B {
+        fn b(&self) { }
+    }
+
+    pub trait C: A + B {
+        fn c(&self) { }
+    }
+
+    impl A for ::S {}
+    impl B for ::S {}
+    impl C for ::S {}
+}
+
+mod assoc_const {
+    trait A {
+        const A: u8 = 0;
+    }
+
+    pub trait B {
+        const B: u8 = 0;
+    }
+
+    pub trait C: A + B {
+        const C: u8 = 0;
+    }
+
+    impl A for ::S {}
+    impl B for ::S {}
+    impl C for ::S {}
+}
+
+mod assoc_ty {
+    trait A {
+        type A = u8;
+    }
+
+    pub trait B {
+        type B = u8;
+    }
+
+    pub trait C: A + B {
+        type C = u8;
+    }
+
+    impl A for ::S {}
+    impl B for ::S {}
+    impl C for ::S {}
+}
+
+fn check_method() {
+    // A is private
+    // B is pub, not in scope
+    // C : A + B is pub, in scope
+    use method::C;
+
+    // Methods, method call
+    // a, b, c are resolved as trait items, their traits need to be in scope
+    S.a(); //~ ERROR no method named `a` found for type `S` in the current scope
+    S.b(); //~ ERROR no method named `b` found for type `S` in the current scope
+    S.c(); // OK
+    // a, b, c are resolved as inherent items, their traits don't need to be in scope
+    let c = &S as &C;
+    c.a(); //~ ERROR method `a` is private
+    c.b(); // OK
+    c.c(); // OK
+
+    // Methods, UFCS
+    // a, b, c are resolved as trait items, their traits need to be in scope
+    S::a(&S);
+    //~^ ERROR no function or associated item named `a` found for type `S`
+    S::b(&S);
+    //~^ ERROR no function or associated item named `b` found for type `S`
+    S::c(&S); // OK
+    // a, b, c are resolved as inherent items, their traits don't need to be in scope
+    C::a(&S); //~ ERROR method `a` is private
+    C::b(&S); // OK
+    C::c(&S); // OK
+}
+
+fn check_assoc_const() {
+    // A is private
+    // B is pub, not in scope
+    // C : A + B is pub, in scope
+    use assoc_const::C;
+
+    // Associated constants
+    // A, B, C are resolved as trait items, their traits need to be in scope
+    S::A; //~ ERROR no associated item named `A` found for type `S` in the current scope
+    S::B; //~ ERROR no associated item named `B` found for type `S` in the current scope
+    S::C; // OK
+    // A, B, C are resolved as inherent items, their traits don't need to be in scope
+    C::A; //~ ERROR associated constant `A` is private
+          //~^ ERROR the trait `assoc_const::C` cannot be made into an object
+    C::B; // ERROR the trait `assoc_const::C` cannot be made into an object
+    C::C; // OK
+}
+
+fn check_assoc_ty<T: assoc_ty::C>() {
+    // A is private
+    // B is pub, not in scope
+    // C : A + B is pub, in scope
+    use assoc_ty::C;
+
+    // Associated types
+    // A, B, C are resolved as trait items, their traits need to be in scope, not implemented yet
+    let _: S::A; //~ ERROR ambiguous associated type
+    let _: S::B; //~ ERROR ambiguous associated type
+    let _: S::C; //~ ERROR ambiguous associated type
+    // A, B, C are resolved as inherent items, their traits don't need to be in scope
+    let _: T::A; //~ ERROR associated type `A` is private
+    let _: T::B; // OK
+    let _: T::C; // OK
+
+    // Associated types, bindings
+    let _: assoc_ty::B<
+        B = u8, // OK
+    >;
+    let _: C<
+        A = u8, //~ ERROR associated type `A` is private
+        B = u8, // OK
+        C = u8, // OK
+    >;
+}
+
+fn main() {}
diff --git a/src/test/ui/traits/trait-item-privacy.stderr b/src/test/ui/traits/trait-item-privacy.stderr
new file mode 100644
index 0000000..3bf5309
--- /dev/null
+++ b/src/test/ui/traits/trait-item-privacy.stderr
@@ -0,0 +1,146 @@
+error[E0599]: no method named `a` found for type `S` in the current scope
+  --> $DIR/trait-item-privacy.rs:67:7
+   |
+LL | struct S;
+   | --------- method `a` not found for this
+...
+LL |     S.a();
+   |       ^
+   |
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following trait defines an item `a`, perhaps you need to implement it:
+           candidate #1: `method::A`
+
+error[E0599]: no method named `b` found for type `S` in the current scope
+  --> $DIR/trait-item-privacy.rs:68:7
+   |
+LL | struct S;
+   | --------- method `b` not found for this
+...
+LL |     S.b();
+   |       ^
+   |
+   = help: items from traits can only be used if the trait is in scope
+help: the following trait is implemented but not in scope, perhaps add a `use` for it:
+   |
+LL | use method::B;
+   |
+
+error[E0624]: method `a` is private
+  --> $DIR/trait-item-privacy.rs:72:7
+   |
+LL |     c.a();
+   |       ^
+
+error[E0599]: no function or associated item named `a` found for type `S` in the current scope
+  --> $DIR/trait-item-privacy.rs:78:8
+   |
+LL | struct S;
+   | --------- function or associated item `a` not found for this
+...
+LL |     S::a(&S);
+   |        ^ function or associated item not found in `S`
+   |
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following trait defines an item `a`, perhaps you need to implement it:
+           candidate #1: `method::A`
+
+error[E0599]: no function or associated item named `b` found for type `S` in the current scope
+  --> $DIR/trait-item-privacy.rs:80:8
+   |
+LL | struct S;
+   | --------- function or associated item `b` not found for this
+...
+LL |     S::b(&S);
+   |        ^ function or associated item not found in `S`
+   |
+   = help: items from traits can only be used if the trait is in scope
+help: the following trait is implemented but not in scope, perhaps add a `use` for it:
+   |
+LL | use method::B;
+   |
+
+error[E0624]: method `a` is private
+  --> $DIR/trait-item-privacy.rs:84:5
+   |
+LL |     C::a(&S);
+   |     ^^^^
+
+error[E0599]: no associated item named `A` found for type `S` in the current scope
+  --> $DIR/trait-item-privacy.rs:97:8
+   |
+LL | struct S;
+   | --------- associated item `A` not found for this
+...
+LL |     S::A;
+   |        ^ associated item not found in `S`
+   |
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following trait defines an item `A`, perhaps you need to implement it:
+           candidate #1: `assoc_const::A`
+
+error[E0599]: no associated item named `B` found for type `S` in the current scope
+  --> $DIR/trait-item-privacy.rs:98:8
+   |
+LL | struct S;
+   | --------- associated item `B` not found for this
+...
+LL |     S::B;
+   |        ^ associated item not found in `S`
+   |
+   = help: items from traits can only be used if the trait is in scope
+help: the following trait is implemented but not in scope, perhaps add a `use` for it:
+   |
+LL | use assoc_const::B;
+   |
+
+error[E0624]: associated constant `A` is private
+  --> $DIR/trait-item-privacy.rs:101:5
+   |
+LL |     C::A;
+   |     ^^^^
+
+error[E0038]: the trait `assoc_const::C` cannot be made into an object
+  --> $DIR/trait-item-privacy.rs:101:5
+   |
+LL |     C::A;
+   |     ^^^^ the trait `assoc_const::C` cannot be made into an object
+   |
+   = note: the trait cannot contain associated consts like `C`
+   = note: the trait cannot contain associated consts like `B`
+   = note: the trait cannot contain associated consts like `A`
+
+error[E0223]: ambiguous associated type
+  --> $DIR/trait-item-privacy.rs:115:12
+   |
+LL |     let _: S::A;
+   |            ^^^^ help: use fully-qualified syntax: `<S as Trait>::A`
+
+error[E0223]: ambiguous associated type
+  --> $DIR/trait-item-privacy.rs:116:12
+   |
+LL |     let _: S::B;
+   |            ^^^^ help: use fully-qualified syntax: `<S as Trait>::B`
+
+error[E0223]: ambiguous associated type
+  --> $DIR/trait-item-privacy.rs:117:12
+   |
+LL |     let _: S::C;
+   |            ^^^^ help: use fully-qualified syntax: `<S as Trait>::C`
+
+error: associated type `A` is private
+  --> $DIR/trait-item-privacy.rs:119:12
+   |
+LL |     let _: T::A;
+   |            ^^^^
+
+error: associated type `A` is private
+  --> $DIR/trait-item-privacy.rs:128:9
+   |
+LL |         A = u8,
+   |         ^^^^^^
+
+error: aborting due to 15 previous errors
+
+Some errors occurred: E0038, E0223, E0599, E0624.
+For more information about an error, try `rustc --explain E0038`.
diff --git a/src/test/ui/traits/trait-matching-lifetimes.rs b/src/test/ui/traits/trait-matching-lifetimes.rs
new file mode 100644
index 0000000..1430dc6
--- /dev/null
+++ b/src/test/ui/traits/trait-matching-lifetimes.rs
@@ -0,0 +1,20 @@
+// Tests that the trait matching code takes lifetime parameters into account.
+// (Issue #15517.)
+
+struct Foo<'a,'b> {
+    x: &'a isize,
+    y: &'b isize,
+}
+
+trait Tr : Sized {
+    fn foo(x: Self) {}
+}
+
+impl<'a,'b> Tr for Foo<'a,'b> {
+    fn foo(x: Foo<'b,'a>) {
+        //~^ ERROR method not compatible with trait
+        //~^^ ERROR method not compatible with trait
+    }
+}
+
+fn main(){}
diff --git a/src/test/ui/traits/trait-matching-lifetimes.stderr b/src/test/ui/traits/trait-matching-lifetimes.stderr
new file mode 100644
index 0000000..80c5776
--- /dev/null
+++ b/src/test/ui/traits/trait-matching-lifetimes.stderr
@@ -0,0 +1,41 @@
+error[E0308]: method not compatible with trait
+  --> $DIR/trait-matching-lifetimes.rs:14:5
+   |
+LL |     fn foo(x: Foo<'b,'a>) {
+   |     ^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
+   |
+   = note: expected type `fn(Foo<'a, 'b>)`
+              found type `fn(Foo<'b, 'a>)`
+note: the lifetime 'b as defined on the impl at 13:9...
+  --> $DIR/trait-matching-lifetimes.rs:13:9
+   |
+LL | impl<'a,'b> Tr for Foo<'a,'b> {
+   |         ^^
+note: ...does not necessarily outlive the lifetime 'a as defined on the impl at 13:6
+  --> $DIR/trait-matching-lifetimes.rs:13:6
+   |
+LL | impl<'a,'b> Tr for Foo<'a,'b> {
+   |      ^^
+
+error[E0308]: method not compatible with trait
+  --> $DIR/trait-matching-lifetimes.rs:14:5
+   |
+LL |     fn foo(x: Foo<'b,'a>) {
+   |     ^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
+   |
+   = note: expected type `fn(Foo<'a, 'b>)`
+              found type `fn(Foo<'b, 'a>)`
+note: the lifetime 'a as defined on the impl at 13:6...
+  --> $DIR/trait-matching-lifetimes.rs:13:6
+   |
+LL | impl<'a,'b> Tr for Foo<'a,'b> {
+   |      ^^
+note: ...does not necessarily outlive the lifetime 'b as defined on the impl at 13:9
+  --> $DIR/trait-matching-lifetimes.rs:13:9
+   |
+LL | impl<'a,'b> Tr for Foo<'a,'b> {
+   |         ^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/traits/trait-method-private.rs b/src/test/ui/traits/trait-method-private.rs
new file mode 100644
index 0000000..4cd1848
--- /dev/null
+++ b/src/test/ui/traits/trait-method-private.rs
@@ -0,0 +1,20 @@
+mod inner {
+    pub trait Bar {
+        fn method(&self);
+    }
+
+    pub struct Foo;
+
+    impl Foo {
+        fn method(&self) {}
+    }
+
+    impl Bar for Foo {
+        fn method(&self) {}
+    }
+}
+
+fn main() {
+    let foo = inner::Foo;
+    foo.method(); //~ ERROR is private
+}
diff --git a/src/test/ui/traits/trait-method-private.stderr b/src/test/ui/traits/trait-method-private.stderr
new file mode 100644
index 0000000..c1dd938
--- /dev/null
+++ b/src/test/ui/traits/trait-method-private.stderr
@@ -0,0 +1,15 @@
+error[E0624]: method `method` is private
+  --> $DIR/trait-method-private.rs:19:9
+   |
+LL |     foo.method();
+   |         ^^^^^^
+   |
+   = help: items from traits can only be used if the trait is in scope
+help: the following trait is implemented but not in scope, perhaps add a `use` for it:
+   |
+LL | use inner::Bar;
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0624`.
diff --git a/src/test/ui/traits/trait-object-auto-dedup-in-impl.rs b/src/test/ui/traits/trait-object-auto-dedup-in-impl.rs
new file mode 100644
index 0000000..6ba5d28
--- /dev/null
+++ b/src/test/ui/traits/trait-object-auto-dedup-in-impl.rs
@@ -0,0 +1,19 @@
+// Checks to make sure that `dyn Trait + Send` and `dyn Trait + Send + Send` are the same type.
+// Issue: #47010
+
+struct Struct;
+impl Trait for Struct {}
+trait Trait {}
+
+type Send1 = Trait + Send;
+type Send2 = Trait + Send + Send;
+
+fn main () {}
+
+impl Trait + Send {
+    fn test(&self) { println!("one"); } //~ ERROR duplicate definitions with name `test`
+}
+
+impl Trait + Send + Send {
+    fn test(&self) { println!("two"); }
+}
diff --git a/src/test/ui/traits/trait-object-auto-dedup-in-impl.stderr b/src/test/ui/traits/trait-object-auto-dedup-in-impl.stderr
new file mode 100644
index 0000000..2570db0
--- /dev/null
+++ b/src/test/ui/traits/trait-object-auto-dedup-in-impl.stderr
@@ -0,0 +1,12 @@
+error[E0592]: duplicate definitions with name `test`
+  --> $DIR/trait-object-auto-dedup-in-impl.rs:14:5
+   |
+LL |     fn test(&self) { println!("one"); }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ duplicate definitions for `test`
+...
+LL |     fn test(&self) { println!("two"); }
+   |     ----------------------------------- other definition for `test`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0592`.
diff --git a/src/test/ui/traits/trait-object-macro-matcher.rs b/src/test/ui/traits/trait-object-macro-matcher.rs
new file mode 100644
index 0000000..0f55e2d
--- /dev/null
+++ b/src/test/ui/traits/trait-object-macro-matcher.rs
@@ -0,0 +1,11 @@
+// `ty` matcher accepts trait object types
+
+macro_rules! m {
+    ($t: ty) => ( let _: $t; )
+}
+
+fn main() {
+    m!(Copy + Send + 'static); //~ ERROR the trait `std::marker::Copy` cannot be made into an object
+    m!('static + Send);
+    m!('static +); //~ ERROR at least one non-builtin trait is required for an object type
+}
diff --git a/src/test/ui/traits/trait-object-macro-matcher.stderr b/src/test/ui/traits/trait-object-macro-matcher.stderr
new file mode 100644
index 0000000..3a6bf3d
--- /dev/null
+++ b/src/test/ui/traits/trait-object-macro-matcher.stderr
@@ -0,0 +1,18 @@
+error[E0224]: at least one non-builtin trait is required for an object type
+  --> $DIR/trait-object-macro-matcher.rs:10:8
+   |
+LL |     m!('static +);
+   |        ^^^^^^^^^
+
+error[E0038]: the trait `std::marker::Copy` cannot be made into an object
+  --> $DIR/trait-object-macro-matcher.rs:8:8
+   |
+LL |     m!(Copy + Send + 'static);
+   |        ^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` cannot be made into an object
+   |
+   = note: the trait cannot require that `Self : Sized`
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0038, E0224.
+For more information about an error, try `rustc --explain E0038`.
diff --git a/src/test/ui/traits/trait-object-safety.rs b/src/test/ui/traits/trait-object-safety.rs
new file mode 100644
index 0000000..e333bf6
--- /dev/null
+++ b/src/test/ui/traits/trait-object-safety.rs
@@ -0,0 +1,17 @@
+// Check that static methods are not object-safe.
+
+trait Tr {
+    fn foo();
+    fn bar(&self) { }
+}
+
+struct St;
+
+impl Tr for St {
+    fn foo() {}
+}
+
+fn main() {
+    let _: &Tr = &St; //~ ERROR E0038
+    //~^ ERROR E0038
+}
diff --git a/src/test/ui/traits/trait-object-safety.stderr b/src/test/ui/traits/trait-object-safety.stderr
new file mode 100644
index 0000000..a7fe83c
--- /dev/null
+++ b/src/test/ui/traits/trait-object-safety.stderr
@@ -0,0 +1,20 @@
+error[E0038]: the trait `Tr` cannot be made into an object
+  --> $DIR/trait-object-safety.rs:15:18
+   |
+LL |     let _: &Tr = &St;
+   |                  ^^^ the trait `Tr` cannot be made into an object
+   |
+   = note: method `foo` has no receiver
+   = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Tr>` for `&St`
+
+error[E0038]: the trait `Tr` cannot be made into an object
+  --> $DIR/trait-object-safety.rs:15:12
+   |
+LL |     let _: &Tr = &St;
+   |            ^^^ the trait `Tr` cannot be made into an object
+   |
+   = note: method `foo` has no receiver
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/traits/trait-object-vs-lifetime-2.rs b/src/test/ui/traits/trait-object-vs-lifetime-2.rs
new file mode 100644
index 0000000..2579a00
--- /dev/null
+++ b/src/test/ui/traits/trait-object-vs-lifetime-2.rs
@@ -0,0 +1,13 @@
+// A few contrived examples where lifetime should (or should not) be parsed as an object type.
+// Lifetimes parsed as types are still rejected later by semantic checks.
+
+// compile-flags: -Z continue-parse-after-error
+
+// `'static` is a lifetime, `'static +` is a type, `'a` is a type
+fn g() where
+    'static: 'static,
+    'static +: 'static + Copy,
+    //~^ ERROR at least one non-builtin trait is required for an object type
+{}
+
+fn main() {}
diff --git a/src/test/ui/traits/trait-object-vs-lifetime-2.stderr b/src/test/ui/traits/trait-object-vs-lifetime-2.stderr
new file mode 100644
index 0000000..70ad839
--- /dev/null
+++ b/src/test/ui/traits/trait-object-vs-lifetime-2.stderr
@@ -0,0 +1,9 @@
+error[E0224]: at least one non-builtin trait is required for an object type
+  --> $DIR/trait-object-vs-lifetime-2.rs:9:5
+   |
+LL |     'static +: 'static + Copy,
+   |     ^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0224`.
diff --git a/src/test/ui/traits/trait-object-vs-lifetime.rs b/src/test/ui/traits/trait-object-vs-lifetime.rs
new file mode 100644
index 0000000..36dec21
--- /dev/null
+++ b/src/test/ui/traits/trait-object-vs-lifetime.rs
@@ -0,0 +1,17 @@
+// A few contrived examples where lifetime should (or should not) be parsed as an object type.
+// Lifetimes parsed as types are still rejected later by semantic checks.
+
+struct S<'a, T>(&'a u8, T);
+
+fn main() {
+    // `'static` is a lifetime argument, `'static +` is a type argument
+    let _: S<'static, u8>;
+    let _: S<'static, 'static +>;
+    //~^ at least one non-builtin trait is required for an object type
+    let _: S<'static, 'static>;
+    //~^ ERROR wrong number of lifetime arguments: expected 1, found 2
+    //~| ERROR wrong number of type arguments: expected 1, found 0
+    let _: S<'static +, 'static>;
+    //~^ ERROR lifetime arguments must be declared prior to type arguments
+    //~| ERROR at least one non-builtin trait is required for an object type
+}
diff --git a/src/test/ui/traits/trait-object-vs-lifetime.stderr b/src/test/ui/traits/trait-object-vs-lifetime.stderr
new file mode 100644
index 0000000..e0c52a7
--- /dev/null
+++ b/src/test/ui/traits/trait-object-vs-lifetime.stderr
@@ -0,0 +1,34 @@
+error: lifetime arguments must be declared prior to type arguments
+  --> $DIR/trait-object-vs-lifetime.rs:14:25
+   |
+LL |     let _: S<'static +, 'static>;
+   |                         ^^^^^^^
+
+error[E0224]: at least one non-builtin trait is required for an object type
+  --> $DIR/trait-object-vs-lifetime.rs:9:23
+   |
+LL |     let _: S<'static, 'static +>;
+   |                       ^^^^^^^^^
+
+error[E0107]: wrong number of lifetime arguments: expected 1, found 2
+  --> $DIR/trait-object-vs-lifetime.rs:11:23
+   |
+LL |     let _: S<'static, 'static>;
+   |                       ^^^^^^^ unexpected lifetime argument
+
+error[E0107]: wrong number of type arguments: expected 1, found 0
+  --> $DIR/trait-object-vs-lifetime.rs:11:12
+   |
+LL |     let _: S<'static, 'static>;
+   |            ^^^^^^^^^^^^^^^^^^^ expected 1 type argument
+
+error[E0224]: at least one non-builtin trait is required for an object type
+  --> $DIR/trait-object-vs-lifetime.rs:14:14
+   |
+LL |     let _: S<'static +, 'static>;
+   |              ^^^^^^^^^
+
+error: aborting due to 5 previous errors
+
+Some errors occurred: E0107, E0224.
+For more information about an error, try `rustc --explain E0107`.
diff --git a/src/test/ui/traits/trait-object-with-self-in-projection-output-bad.rs b/src/test/ui/traits/trait-object-with-self-in-projection-output-bad.rs
new file mode 100644
index 0000000..766bd14
--- /dev/null
+++ b/src/test/ui/traits/trait-object-with-self-in-projection-output-bad.rs
@@ -0,0 +1,50 @@
+// Regression test for #56288. Checks that if a supertrait defines an associated type
+// projection that references `Self`, then that associated type must still be explicitly
+// specified in the `dyn Trait` variant, since we don't know what `Self` is anymore.
+
+trait Base {
+    type Output;
+}
+
+trait Helper: Base<Output=<Self as Helper>::Target> {
+    type Target;
+}
+
+impl Base for u32
+{
+    type Output = i32;
+}
+
+impl Helper for u32
+{
+    type Target = i32;
+}
+
+trait ConstI32 {
+    type Out;
+}
+
+impl<T: ?Sized> ConstI32 for T {
+    type Out = i32;
+}
+
+// Test that you still need to manually give a projection type if the Output type
+// is normalizable.
+trait NormalizableHelper:
+    Base<Output=<Self as ConstI32>::Out>
+{
+    type Target;
+}
+
+impl NormalizableHelper for u32
+{
+    type Target = i32;
+}
+
+fn main() {
+    let _x: Box<dyn Helper<Target=i32>> = Box::new(2u32);
+    //~^ ERROR the value of the associated type `Output` (from the trait `Base`) must be specified
+
+    let _y: Box<dyn NormalizableHelper<Target=i32>> = Box::new(2u32);
+    //~^ ERROR the value of the associated type `Output` (from the trait `Base`) must be specified
+}
diff --git a/src/test/ui/traits/trait-object-with-self-in-projection-output-bad.stderr b/src/test/ui/traits/trait-object-with-self-in-projection-output-bad.stderr
new file mode 100644
index 0000000..350f8ea
--- /dev/null
+++ b/src/test/ui/traits/trait-object-with-self-in-projection-output-bad.stderr
@@ -0,0 +1,21 @@
+error[E0191]: the value of the associated type `Output` (from the trait `Base`) must be specified
+  --> $DIR/trait-object-with-self-in-projection-output-bad.rs:45:17
+   |
+LL |     type Output;
+   |     ------------ `Output` defined here
+...
+LL |     let _x: Box<dyn Helper<Target=i32>> = Box::new(2u32);
+   |                 ^^^^^^^^^^^^^^^^^^^^^^ associated type `Output` must be specified
+
+error[E0191]: the value of the associated type `Output` (from the trait `Base`) must be specified
+  --> $DIR/trait-object-with-self-in-projection-output-bad.rs:48:17
+   |
+LL |     type Output;
+   |     ------------ `Output` defined here
+...
+LL |     let _y: Box<dyn NormalizableHelper<Target=i32>> = Box::new(2u32);
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ associated type `Output` must be specified
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0191`.
diff --git a/src/test/ui/traits/trait-object-with-self-in-projection-output-good.rs b/src/test/ui/traits/trait-object-with-self-in-projection-output-good.rs
new file mode 100644
index 0000000..793d556
--- /dev/null
+++ b/src/test/ui/traits/trait-object-with-self-in-projection-output-good.rs
@@ -0,0 +1,28 @@
+// compile-pass
+
+// Regression test related to #56288. Check that a supertrait projection (of
+// `Output`) that references `Self` can be ok if it is referencing a projection (of
+// `Self::Target`, in this case). Note that we still require the user to manually
+// specify both `Target` and `Output` for now.
+
+trait Base {
+    type Output;
+}
+
+trait Helper: Base<Output=<Self as Helper>::Target> {
+    type Target;
+}
+
+impl Base for u32
+{
+    type Output = i32;
+}
+
+impl Helper for u32
+{
+    type Target = i32;
+}
+
+fn main() {
+    let _x: Box<dyn Helper<Target=i32, Output=i32>> = Box::new(2u32);
+}
diff --git a/src/test/ui/traits/trait-object-with-self-in-projection-output-repeated-supertrait.rs b/src/test/ui/traits/trait-object-with-self-in-projection-output-repeated-supertrait.rs
new file mode 100644
index 0000000..46c083f
--- /dev/null
+++ b/src/test/ui/traits/trait-object-with-self-in-projection-output-repeated-supertrait.rs
@@ -0,0 +1,48 @@
+// compile-pass
+
+// Regression test related to #56288. Check that a supertrait projection (of
+// `Output`) that references `Self` is ok if there is another occurence of
+// the same supertrait that specifies the projection explicitly, even if
+// the projection's associated type is not explicitly specified in the object type.
+//
+// Note that in order for this to compile, we need the `Self`-referencing projection
+// to normalize fairly directly to a concrete type, otherwise the trait resolver
+// will hate us.
+//
+// There is a test in `trait-object-with-self-in-projection-output-bad.rs` that
+// having a normalizing, but `Self`-containing projection does not *by itself*
+// allow you to avoid writing the projected type (`Output`, in this example)
+// explicitly.
+
+trait ConstI32 {
+    type Out;
+}
+
+impl<T: ?Sized> ConstI32 for T {
+    type Out = i32;
+}
+
+trait Base {
+    type Output;
+}
+
+trait NormalizingHelper: Base<Output=<Self as ConstI32>::Out> + Base<Output=i32> {
+    type Target;
+}
+
+impl Base for u32
+{
+    type Output = i32;
+}
+
+impl NormalizingHelper for u32
+{
+    type Target = i32;
+}
+
+fn main() {
+    // Make sure this works both with and without the associated type
+    // being specified.
+    let _x: Box<dyn NormalizingHelper<Target=i32>> = Box::new(2u32);
+    let _y: Box<dyn NormalizingHelper<Target=i32, Output=i32>> = Box::new(2u32);
+}
diff --git a/src/test/ui/traits/trait-or-new-type-instead.rs b/src/test/ui/traits/trait-or-new-type-instead.rs
new file mode 100644
index 0000000..572b03e
--- /dev/null
+++ b/src/test/ui/traits/trait-or-new-type-instead.rs
@@ -0,0 +1,6 @@
+impl<T> Option<T> {
+//~^ ERROR cannot define inherent `impl` for a type outside of the crate where the type is defined
+    pub fn foo(&self) { }
+}
+
+fn main() { }
diff --git a/src/test/ui/traits/trait-or-new-type-instead.stderr b/src/test/ui/traits/trait-or-new-type-instead.stderr
new file mode 100644
index 0000000..4726b06
--- /dev/null
+++ b/src/test/ui/traits/trait-or-new-type-instead.stderr
@@ -0,0 +1,14 @@
+error[E0116]: cannot define inherent `impl` for a type outside of the crate where the type is defined
+  --> $DIR/trait-or-new-type-instead.rs:1:1
+   |
+LL | / impl<T> Option<T> {
+LL | |
+LL | |     pub fn foo(&self) { }
+LL | | }
+   | |_^ impl for type defined outside of crate.
+   |
+   = note: define and implement a trait or new type instead
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0116`.
diff --git a/src/test/ui/traits/trait-privacy.rs b/src/test/ui/traits/trait-privacy.rs
new file mode 100644
index 0000000..6254157
--- /dev/null
+++ b/src/test/ui/traits/trait-privacy.rs
@@ -0,0 +1,24 @@
+// compile-pass
+#![allow(dead_code)]
+mod foo {
+    pub use self::bar::T;
+    mod bar {
+        pub trait T {
+            fn f(&self) {}
+        }
+        impl T for () {}
+    }
+}
+
+fn g() {
+    use foo::T;
+    ().f(); // Check that this does not trigger a privacy error
+}
+
+fn f() {
+    let error = ::std::thread::spawn(|| {}).join().unwrap_err();
+    error.type_id(); // Regression test for #21670
+}
+
+
+fn main() {}
diff --git a/src/test/ui/traits/trait-resolution-in-overloaded-op.rs b/src/test/ui/traits/trait-resolution-in-overloaded-op.rs
new file mode 100644
index 0000000..96f81a2
--- /dev/null
+++ b/src/test/ui/traits/trait-resolution-in-overloaded-op.rs
@@ -0,0 +1,11 @@
+// #12402 Operator overloading only considers the method name, not which trait is implemented
+
+trait MyMul<Rhs, Res> {
+    fn mul(&self, rhs: &Rhs) -> Res;
+}
+
+fn foo<T: MyMul<f64, f64>>(a: &T, b: f64) -> f64 {
+    a * b //~ ERROR binary operation `*` cannot be applied to type `&T`
+}
+
+fn main() {}
diff --git a/src/test/ui/traits/trait-resolution-in-overloaded-op.stderr b/src/test/ui/traits/trait-resolution-in-overloaded-op.stderr
new file mode 100644
index 0000000..d11562e
--- /dev/null
+++ b/src/test/ui/traits/trait-resolution-in-overloaded-op.stderr
@@ -0,0 +1,13 @@
+error[E0369]: binary operation `*` cannot be applied to type `&T`
+  --> $DIR/trait-resolution-in-overloaded-op.rs:8:7
+   |
+LL |     a * b
+   |     - ^ - f64
+   |     |
+   |     &T
+   |
+   = note: an implementation of `std::ops::Mul` might be missing for `&T`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0369`.
diff --git a/src/test/ui/traits/trait-safety-fn-body.rs b/src/test/ui/traits/trait-safety-fn-body.rs
new file mode 100644
index 0000000..df52774
--- /dev/null
+++ b/src/test/ui/traits/trait-safety-fn-body.rs
@@ -0,0 +1,16 @@
+// Check that an unsafe impl does not imply that unsafe actions are
+// legal in the methods.
+
+unsafe trait UnsafeTrait : Sized {
+    fn foo(self) { }
+}
+
+unsafe impl UnsafeTrait for *mut isize {
+    fn foo(self) {
+        // Unsafe actions are not made legal by taking place in an unsafe trait:
+        *self += 1;
+        //~^ ERROR E0133
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/traits/trait-safety-fn-body.stderr b/src/test/ui/traits/trait-safety-fn-body.stderr
new file mode 100644
index 0000000..a27cd86
--- /dev/null
+++ b/src/test/ui/traits/trait-safety-fn-body.stderr
@@ -0,0 +1,11 @@
+error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
+  --> $DIR/trait-safety-fn-body.rs:11:9
+   |
+LL |         *self += 1;
+   |         ^^^^^^^^^^ dereference of raw pointer
+   |
+   = note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/traits/trait-safety-inherent-impl.rs b/src/test/ui/traits/trait-safety-inherent-impl.rs
new file mode 100644
index 0000000..50e15f0
--- /dev/null
+++ b/src/test/ui/traits/trait-safety-inherent-impl.rs
@@ -0,0 +1,9 @@
+// Check that inherent impls cannot be unsafe.
+
+struct SomeStruct;
+
+unsafe impl SomeStruct { //~ ERROR inherent impls cannot be unsafe
+    fn foo(self) { }
+}
+
+fn main() { }
diff --git a/src/test/ui/traits/trait-safety-inherent-impl.stderr b/src/test/ui/traits/trait-safety-inherent-impl.stderr
new file mode 100644
index 0000000..3911261
--- /dev/null
+++ b/src/test/ui/traits/trait-safety-inherent-impl.stderr
@@ -0,0 +1,11 @@
+error[E0197]: inherent impls cannot be unsafe
+  --> $DIR/trait-safety-inherent-impl.rs:5:1
+   |
+LL | / unsafe impl SomeStruct {
+LL | |     fn foo(self) { }
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0197`.
diff --git a/src/test/ui/traits/trait-safety-trait-impl-cc.rs b/src/test/ui/traits/trait-safety-trait-impl-cc.rs
new file mode 100644
index 0000000..6f125e5
--- /dev/null
+++ b/src/test/ui/traits/trait-safety-trait-impl-cc.rs
@@ -0,0 +1,15 @@
+// aux-build:trait_safety_lib.rs
+
+// Check that unsafe traits require unsafe impls and that inherent
+// impls cannot be unsafe.
+
+extern crate trait_safety_lib as lib;
+
+struct Bar;
+impl lib::Foo for Bar { //~ ERROR requires an `unsafe impl` declaration
+    fn foo(&self) -> isize {
+        panic!();
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/traits/trait-safety-trait-impl-cc.stderr b/src/test/ui/traits/trait-safety-trait-impl-cc.stderr
new file mode 100644
index 0000000..5234e20
--- /dev/null
+++ b/src/test/ui/traits/trait-safety-trait-impl-cc.stderr
@@ -0,0 +1,13 @@
+error[E0200]: the trait `lib::Foo` requires an `unsafe impl` declaration
+  --> $DIR/trait-safety-trait-impl-cc.rs:9:1
+   |
+LL | / impl lib::Foo for Bar {
+LL | |     fn foo(&self) -> isize {
+LL | |         panic!();
+LL | |     }
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0200`.
diff --git a/src/test/ui/traits/trait-safety-trait-impl.rs b/src/test/ui/traits/trait-safety-trait-impl.rs
new file mode 100644
index 0000000..45258b7
--- /dev/null
+++ b/src/test/ui/traits/trait-safety-trait-impl.rs
@@ -0,0 +1,18 @@
+// Check that unsafe traits require unsafe impls and that inherent
+// impls cannot be unsafe.
+
+trait SafeTrait {
+    fn foo(&self) { }
+}
+
+unsafe trait UnsafeTrait {
+    fn foo(&self) { }
+}
+
+unsafe impl UnsafeTrait for u8 { } // OK
+
+impl UnsafeTrait for u16 { } //~ ERROR requires an `unsafe impl` declaration
+
+unsafe impl SafeTrait for u32 { } //~ ERROR the trait `SafeTrait` is not unsafe
+
+fn main() { }
diff --git a/src/test/ui/traits/trait-safety-trait-impl.stderr b/src/test/ui/traits/trait-safety-trait-impl.stderr
new file mode 100644
index 0000000..c83a2cd
--- /dev/null
+++ b/src/test/ui/traits/trait-safety-trait-impl.stderr
@@ -0,0 +1,16 @@
+error[E0200]: the trait `UnsafeTrait` requires an `unsafe impl` declaration
+  --> $DIR/trait-safety-trait-impl.rs:14:1
+   |
+LL | impl UnsafeTrait for u16 { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0199]: implementing the trait `SafeTrait` is not unsafe
+  --> $DIR/trait-safety-trait-impl.rs:16:1
+   |
+LL | unsafe impl SafeTrait for u32 { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0199, E0200.
+For more information about an error, try `rustc --explain E0199`.
diff --git a/src/test/ui/traits/trait-static-method-generic-inference.rs b/src/test/ui/traits/trait-static-method-generic-inference.rs
new file mode 100644
index 0000000..c08bd5c
--- /dev/null
+++ b/src/test/ui/traits/trait-static-method-generic-inference.rs
@@ -0,0 +1,28 @@
+// Issue #3902. We are (at least currently) unable to infer `Self`
+// based on `T`, even though there is only a single impl, because of
+// the possibility of associated types and other things (basically: no
+// constraints on `Self` here at all).
+
+mod base {
+    pub trait HasNew<T> {
+        fn new() -> T;
+        fn dummy(&self) { }
+    }
+
+    pub struct Foo {
+        dummy: (),
+    }
+
+    impl HasNew<Foo> for Foo {
+        fn new() -> Foo {
+            Foo { dummy: () }
+        }
+    }
+}
+
+pub fn foo() {
+    let _f: base::Foo = base::HasNew::new();
+    //~^ ERROR type annotations required
+}
+
+fn main() { }
diff --git a/src/test/ui/traits/trait-static-method-generic-inference.stderr b/src/test/ui/traits/trait-static-method-generic-inference.stderr
new file mode 100644
index 0000000..390d21c
--- /dev/null
+++ b/src/test/ui/traits/trait-static-method-generic-inference.stderr
@@ -0,0 +1,15 @@
+error[E0283]: type annotations required: cannot resolve `_: base::HasNew<base::Foo>`
+  --> $DIR/trait-static-method-generic-inference.rs:24:25
+   |
+LL |     let _f: base::Foo = base::HasNew::new();
+   |                         ^^^^^^^^^^^^^^^^^
+   |
+note: required by `base::HasNew::new`
+  --> $DIR/trait-static-method-generic-inference.rs:8:9
+   |
+LL |         fn new() -> T;
+   |         ^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0283`.
diff --git a/src/test/ui/traits/trait-suggest-where-clause.rs b/src/test/ui/traits/trait-suggest-where-clause.rs
new file mode 100644
index 0000000..8405e5f
--- /dev/null
+++ b/src/test/ui/traits/trait-suggest-where-clause.rs
@@ -0,0 +1,36 @@
+use std::mem;
+
+struct Misc<T:?Sized>(T);
+
+fn check<T: Iterator, U: ?Sized>() {
+    // suggest a where-clause, if needed
+    mem::size_of::<U>();
+    //~^ ERROR the size for values of type
+
+    mem::size_of::<Misc<U>>();
+    //~^ ERROR the size for values of type
+
+    // ... even if T occurs as a type parameter
+
+    <u64 as From<T>>::from;
+    //~^ ERROR `u64: std::convert::From<T>` is not satisfied
+
+    <u64 as From<<T as Iterator>::Item>>::from;
+    //~^ ERROR `u64: std::convert::From<<T as std::iter::Iterator>::Item>` is not satisfied
+
+    // ... but not if there are inference variables
+
+    <Misc<_> as From<T>>::from;
+    //~^ ERROR `Misc<_>: std::convert::From<T>` is not satisfied
+
+    // ... and also not if the error is not related to the type
+
+    mem::size_of::<[T]>();
+    //~^ ERROR the size for values of type
+
+    mem::size_of::<[&U]>();
+    //~^ ERROR the size for values of type
+}
+
+fn main() {
+}
diff --git a/src/test/ui/traits/trait-suggest-where-clause.stderr b/src/test/ui/traits/trait-suggest-where-clause.stderr
new file mode 100644
index 0000000..f88dae3
--- /dev/null
+++ b/src/test/ui/traits/trait-suggest-where-clause.stderr
@@ -0,0 +1,72 @@
+error[E0277]: the size for values of type `U` cannot be known at compilation time
+  --> $DIR/trait-suggest-where-clause.rs:7:5
+   |
+LL |     mem::size_of::<U>();
+   |     ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `U`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = help: consider adding a `where U: std::marker::Sized` bound
+   = note: required by `std::mem::size_of`
+
+error[E0277]: the size for values of type `U` cannot be known at compilation time
+  --> $DIR/trait-suggest-where-clause.rs:10:5
+   |
+LL |     mem::size_of::<Misc<U>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: within `Misc<U>`, the trait `std::marker::Sized` is not implemented for `U`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = help: consider adding a `where U: std::marker::Sized` bound
+   = note: required because it appears within the type `Misc<U>`
+   = note: required by `std::mem::size_of`
+
+error[E0277]: the trait bound `u64: std::convert::From<T>` is not satisfied
+  --> $DIR/trait-suggest-where-clause.rs:15:5
+   |
+LL |     <u64 as From<T>>::from;
+   |     ^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::From<T>` is not implemented for `u64`
+   |
+   = help: consider adding a `where u64: std::convert::From<T>` bound
+   = note: required by `std::convert::From::from`
+
+error[E0277]: the trait bound `u64: std::convert::From<<T as std::iter::Iterator>::Item>` is not satisfied
+  --> $DIR/trait-suggest-where-clause.rs:18:5
+   |
+LL |     <u64 as From<<T as Iterator>::Item>>::from;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::From<<T as std::iter::Iterator>::Item>` is not implemented for `u64`
+   |
+   = help: consider adding a `where u64: std::convert::From<<T as std::iter::Iterator>::Item>` bound
+   = note: required by `std::convert::From::from`
+
+error[E0277]: the trait bound `Misc<_>: std::convert::From<T>` is not satisfied
+  --> $DIR/trait-suggest-where-clause.rs:23:5
+   |
+LL |     <Misc<_> as From<T>>::from;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::From<T>` is not implemented for `Misc<_>`
+   |
+   = note: required by `std::convert::From::from`
+
+error[E0277]: the size for values of type `[T]` cannot be known at compilation time
+  --> $DIR/trait-suggest-where-clause.rs:28:5
+   |
+LL |     mem::size_of::<[T]>();
+   |     ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `[T]`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: required by `std::mem::size_of`
+
+error[E0277]: the size for values of type `[&U]` cannot be known at compilation time
+  --> $DIR/trait-suggest-where-clause.rs:31:5
+   |
+LL |     mem::size_of::<[&U]>();
+   |     ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `[&U]`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: required by `std::mem::size_of`
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/traits/trait-test-2.rs b/src/test/ui/traits/trait-test-2.rs
new file mode 100644
index 0000000..20d979d
--- /dev/null
+++ b/src/test/ui/traits/trait-test-2.rs
@@ -0,0 +1,14 @@
+#![feature(box_syntax)]
+
+#[allow(non_camel_case_types)]
+trait bar { fn dup(&self) -> Self; fn blah<X>(&self); }
+impl bar for i32 { fn dup(&self) -> i32 { *self } fn blah<X>(&self) {} }
+impl bar for u32 { fn dup(&self) -> u32 { *self } fn blah<X>(&self) {} }
+
+fn main() {
+    10.dup::<i32>(); //~ ERROR wrong number of type arguments: expected 0, found 1
+    10.blah::<i32, i32>(); //~ ERROR wrong number of type arguments: expected 1, found 2
+    (box 10 as Box<bar>).dup();
+    //~^ ERROR E0038
+    //~| ERROR E0038
+}
diff --git a/src/test/ui/traits/trait-test-2.stderr b/src/test/ui/traits/trait-test-2.stderr
new file mode 100644
index 0000000..4d61ac6
--- /dev/null
+++ b/src/test/ui/traits/trait-test-2.stderr
@@ -0,0 +1,35 @@
+error[E0107]: wrong number of type arguments: expected 0, found 1
+  --> $DIR/trait-test-2.rs:9:14
+   |
+LL |     10.dup::<i32>();
+   |              ^^^ unexpected type argument
+
+error[E0107]: wrong number of type arguments: expected 1, found 2
+  --> $DIR/trait-test-2.rs:10:20
+   |
+LL |     10.blah::<i32, i32>();
+   |                    ^^^ unexpected type argument
+
+error[E0038]: the trait `bar` cannot be made into an object
+  --> $DIR/trait-test-2.rs:11:16
+   |
+LL |     (box 10 as Box<bar>).dup();
+   |                ^^^^^^^^ the trait `bar` cannot be made into an object
+   |
+   = note: method `dup` references the `Self` type in its arguments or return type
+   = note: method `blah` has generic type parameters
+
+error[E0038]: the trait `bar` cannot be made into an object
+  --> $DIR/trait-test-2.rs:11:6
+   |
+LL |     (box 10 as Box<bar>).dup();
+   |      ^^^^^^ the trait `bar` cannot be made into an object
+   |
+   = note: method `dup` references the `Self` type in its arguments or return type
+   = note: method `blah` has generic type parameters
+   = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<std::boxed::Box<dyn bar>>` for `std::boxed::Box<{integer}>`
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0038, E0107.
+For more information about an error, try `rustc --explain E0038`.
diff --git a/src/test/ui/traits/trait-test.rs b/src/test/ui/traits/trait-test.rs
new file mode 100644
index 0000000..72fc66f
--- /dev/null
+++ b/src/test/ui/traits/trait-test.rs
@@ -0,0 +1,6 @@
+#[allow(non_camel_case_types)]
+trait foo { fn foo(&self); }
+
+impl isize for usize { fn foo(&self) {} } //~ ERROR trait
+
+fn main() {}
diff --git a/src/test/ui/traits/trait-test.stderr b/src/test/ui/traits/trait-test.stderr
new file mode 100644
index 0000000..f5e47e5
--- /dev/null
+++ b/src/test/ui/traits/trait-test.stderr
@@ -0,0 +1,9 @@
+error[E0404]: expected trait, found builtin type `isize`
+  --> $DIR/trait-test.rs:4:6
+   |
+LL | impl isize for usize { fn foo(&self) {} }
+   |      ^^^^^ not a trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0404`.
diff --git a/src/test/ui/traits/traits-assoc-type-in-supertrait-bad.rs b/src/test/ui/traits/traits-assoc-type-in-supertrait-bad.rs
new file mode 100644
index 0000000..47d7075
--- /dev/null
+++ b/src/test/ui/traits/traits-assoc-type-in-supertrait-bad.rs
@@ -0,0 +1,16 @@
+// Test case where an associated type is referenced from within the
+// supertrait definition, and the impl makes the wrong
+// associations. Issue #20220.
+
+use std::vec::IntoIter;
+
+pub trait Foo: Iterator<Item=<Self as Foo>::Key> {
+    type Key;
+}
+
+impl Foo for IntoIter<i32> { //~ ERROR type mismatch
+    type Key = u32;
+}
+
+fn main() {
+}
diff --git a/src/test/ui/traits/traits-assoc-type-in-supertrait-bad.stderr b/src/test/ui/traits/traits-assoc-type-in-supertrait-bad.stderr
new file mode 100644
index 0000000..44643e8
--- /dev/null
+++ b/src/test/ui/traits/traits-assoc-type-in-supertrait-bad.stderr
@@ -0,0 +1,12 @@
+error[E0271]: type mismatch resolving `<std::vec::IntoIter<i32> as std::iter::Iterator>::Item == u32`
+  --> $DIR/traits-assoc-type-in-supertrait-bad.rs:11:6
+   |
+LL | impl Foo for IntoIter<i32> {
+   |      ^^^ expected i32, found u32
+   |
+   = note: expected type `i32`
+              found type `u32`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/traits/traits-inductive-overflow-simultaneous.rs b/src/test/ui/traits/traits-inductive-overflow-simultaneous.rs
new file mode 100644
index 0000000..40ac921
--- /dev/null
+++ b/src/test/ui/traits/traits-inductive-overflow-simultaneous.rs
@@ -0,0 +1,20 @@
+// Regression test for #33344, initial version. This example allowed
+// arbitrary trait bounds to be synthesized.
+
+trait Tweedledum: IntoIterator {}
+trait Tweedledee: IntoIterator {}
+
+impl<T: Tweedledum> Tweedledee for T {}
+impl<T: Tweedledee> Tweedledum for T {}
+
+trait Combo: IntoIterator {}
+impl<T: Tweedledee + Tweedledum> Combo for T {}
+
+fn is_ee<T: Combo>(t: T) {
+    t.into_iter();
+}
+
+fn main() {
+    is_ee(4);
+    //~^ ERROR overflow evaluating the requirement `{integer}: Tweedle
+}
diff --git a/src/test/ui/traits/traits-inductive-overflow-simultaneous.stderr b/src/test/ui/traits/traits-inductive-overflow-simultaneous.stderr
new file mode 100644
index 0000000..cd8501e
--- /dev/null
+++ b/src/test/ui/traits/traits-inductive-overflow-simultaneous.stderr
@@ -0,0 +1,16 @@
+error[E0275]: overflow evaluating the requirement `{integer}: Tweedledum`
+  --> $DIR/traits-inductive-overflow-simultaneous.rs:18:5
+   |
+LL |     is_ee(4);
+   |     ^^^^^
+   |
+   = note: required because of the requirements on the impl of `Combo` for `{integer}`
+note: required by `is_ee`
+  --> $DIR/traits-inductive-overflow-simultaneous.rs:13:1
+   |
+LL | fn is_ee<T: Combo>(t: T) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.rs b/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.rs
new file mode 100644
index 0000000..c65242b
--- /dev/null
+++ b/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.rs
@@ -0,0 +1,17 @@
+// OIBIT-based version of #29859, supertrait version. Test that using
+// a simple OIBIT `..` impl alone still doesn't allow arbitrary bounds
+// to be synthesized.
+
+#![feature(optin_builtin_traits)]
+
+auto trait Magic: Copy {} //~ ERROR E0568
+
+fn copy<T: Magic>(x: T) -> (T, T) { (x, x) }
+
+#[derive(Debug)]
+struct NoClone;
+
+fn main() {
+    let (a, b) = copy(NoClone); //~ ERROR
+    println!("{:?} {:?}", a, b);
+}
diff --git a/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.stderr b/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.stderr
new file mode 100644
index 0000000..a91be8e
--- /dev/null
+++ b/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.stderr
@@ -0,0 +1,23 @@
+error[E0568]: auto traits cannot have super traits
+  --> $DIR/traits-inductive-overflow-supertrait-oibit.rs:7:1
+   |
+LL | auto trait Magic: Copy {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `NoClone: std::marker::Copy` is not satisfied
+  --> $DIR/traits-inductive-overflow-supertrait-oibit.rs:15:18
+   |
+LL |     let (a, b) = copy(NoClone);
+   |                  ^^^^ the trait `std::marker::Copy` is not implemented for `NoClone`
+   |
+   = note: required because of the requirements on the impl of `Magic` for `NoClone`
+note: required by `copy`
+  --> $DIR/traits-inductive-overflow-supertrait-oibit.rs:9:1
+   |
+LL | fn copy<T: Magic>(x: T) -> (T, T) { (x, x) }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0277, E0568.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/traits/traits-inductive-overflow-supertrait.rs b/src/test/ui/traits/traits-inductive-overflow-supertrait.rs
new file mode 100644
index 0000000..c7aa4d9
--- /dev/null
+++ b/src/test/ui/traits/traits-inductive-overflow-supertrait.rs
@@ -0,0 +1,15 @@
+// Regression test for #29859, supertrait version. This example
+// allowed arbitrary trait bounds to be synthesized.
+
+trait Magic: Copy {}
+impl<T: Magic> Magic for T {}
+
+fn copy<T: Magic>(x: T) -> (T, T) { (x, x) }
+
+#[derive(Debug)]
+struct NoClone;
+
+fn main() {
+    let (a, b) = copy(NoClone); //~ ERROR E0275
+    println!("{:?} {:?}", a, b);
+}
diff --git a/src/test/ui/traits/traits-inductive-overflow-supertrait.stderr b/src/test/ui/traits/traits-inductive-overflow-supertrait.stderr
new file mode 100644
index 0000000..769582a
--- /dev/null
+++ b/src/test/ui/traits/traits-inductive-overflow-supertrait.stderr
@@ -0,0 +1,16 @@
+error[E0275]: overflow evaluating the requirement `NoClone: Magic`
+  --> $DIR/traits-inductive-overflow-supertrait.rs:13:18
+   |
+LL |     let (a, b) = copy(NoClone);
+   |                  ^^^^
+   |
+   = note: required because of the requirements on the impl of `Magic` for `NoClone`
+note: required by `copy`
+  --> $DIR/traits-inductive-overflow-supertrait.rs:7:1
+   |
+LL | fn copy<T: Magic>(x: T) -> (T, T) { (x, x) }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/src/test/ui/traits/traits-inductive-overflow-two-traits.rs b/src/test/ui/traits/traits-inductive-overflow-two-traits.rs
new file mode 100644
index 0000000..63dd141
--- /dev/null
+++ b/src/test/ui/traits/traits-inductive-overflow-two-traits.rs
@@ -0,0 +1,21 @@
+// Regression test for #29859, initial version. This example allowed
+// arbitrary trait bounds to be synthesized.
+
+// Trait that you want all types to implement.
+use std::marker::{Sync as Trait};
+
+pub trait Magic {
+    type X: Trait;
+}
+impl<T: Magic> Magic for T {
+    type X = Self;
+}
+
+fn check<T: Trait>() {}
+
+fn wizard<T: Magic>() { check::<<T as Magic>::X>(); }
+
+fn main() {
+    wizard::<*mut ()>(); //~ ERROR E0275
+    // check::<*mut ()>();
+}
diff --git a/src/test/ui/traits/traits-inductive-overflow-two-traits.stderr b/src/test/ui/traits/traits-inductive-overflow-two-traits.stderr
new file mode 100644
index 0000000..61adbf0
--- /dev/null
+++ b/src/test/ui/traits/traits-inductive-overflow-two-traits.stderr
@@ -0,0 +1,15 @@
+error[E0275]: overflow evaluating the requirement `*mut (): Magic`
+  --> $DIR/traits-inductive-overflow-two-traits.rs:19:5
+   |
+LL |     wizard::<*mut ()>();
+   |     ^^^^^^^^^^^^^^^^^
+   |
+note: required by `wizard`
+  --> $DIR/traits-inductive-overflow-two-traits.rs:16:1
+   |
+LL | fn wizard<T: Magic>() { check::<<T as Magic>::X>(); }
+   | ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/src/test/ui/traits/traits-issue-23003-overflow.rs b/src/test/ui/traits/traits-issue-23003-overflow.rs
new file mode 100644
index 0000000..06aa698
--- /dev/null
+++ b/src/test/ui/traits/traits-issue-23003-overflow.rs
@@ -0,0 +1,29 @@
+// A variant of traits-issue-23003 in which an infinite series of
+// types are required. This test now just compiles fine, since the
+// relevant rules that triggered the overflow were removed.
+
+// compile-pass
+#![allow(dead_code)]
+
+use std::marker::PhantomData;
+
+trait Async {
+    type Cancel;
+}
+
+struct Receipt<A:Async> {
+    marker: PhantomData<A>,
+}
+
+struct Complete<B> {
+    core: Option<B>,
+}
+
+impl<B> Async for Complete<B> {
+    type Cancel = Receipt<Complete<Option<B>>>;
+}
+
+fn foo(_: Receipt<Complete<()>>) { }
+
+
+fn main() { }
diff --git a/src/test/ui/traits/traits-multidispatch-bad.rs b/src/test/ui/traits/traits-multidispatch-bad.rs
new file mode 100644
index 0000000..b625b96
--- /dev/null
+++ b/src/test/ui/traits/traits-multidispatch-bad.rs
@@ -0,0 +1,22 @@
+// Test that we detect an illegal combination of types.
+
+trait Convert<Target> {
+    fn convert(&self) -> Target;
+}
+
+impl Convert<u32> for i32 {
+    fn convert(&self) -> u32 {
+        *self as u32
+    }
+}
+
+fn test<T,U>(_: T, _: U)
+where T : Convert<U>
+{
+}
+
+fn a() {
+    test(22i32, 44i32); //~ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/src/test/ui/traits/traits-multidispatch-bad.stderr b/src/test/ui/traits/traits-multidispatch-bad.stderr
new file mode 100644
index 0000000..5b80011
--- /dev/null
+++ b/src/test/ui/traits/traits-multidispatch-bad.stderr
@@ -0,0 +1,9 @@
+error[E0308]: mismatched types
+  --> $DIR/traits-multidispatch-bad.rs:19:17
+   |
+LL |     test(22i32, 44i32);
+   |                 ^^^^^ expected u32, found i32
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/traits/traits-multidispatch-convert-ambig-dest.rs b/src/test/ui/traits/traits-multidispatch-convert-ambig-dest.rs
new file mode 100644
index 0000000..58cb69a
--- /dev/null
+++ b/src/test/ui/traits/traits-multidispatch-convert-ambig-dest.rs
@@ -0,0 +1,30 @@
+// Check that we get an error in a multidisptach scenario where the
+// set of impls is ambiguous.
+
+trait Convert<Target> {
+    fn convert(&self) -> Target;
+}
+
+impl Convert<i8> for i32 {
+    fn convert(&self) -> i8 {
+        *self as i8
+    }
+}
+
+impl Convert<i16> for i32 {
+    fn convert(&self) -> i16 {
+        *self as i16
+    }
+}
+
+fn test<T,U>(_: T, _: U)
+where T : Convert<U>
+{
+}
+
+fn a() {
+    test(22, std::default::Default::default());
+    //~^ ERROR type annotations needed [E0282]
+}
+
+fn main() {}
diff --git a/src/test/ui/traits/traits-multidispatch-convert-ambig-dest.stderr b/src/test/ui/traits/traits-multidispatch-convert-ambig-dest.stderr
new file mode 100644
index 0000000..d7d2704
--- /dev/null
+++ b/src/test/ui/traits/traits-multidispatch-convert-ambig-dest.stderr
@@ -0,0 +1,9 @@
+error[E0282]: type annotations needed
+  --> $DIR/traits-multidispatch-convert-ambig-dest.rs:26:5
+   |
+LL |     test(22, std::default::Default::default());
+   |     ^^^^ cannot infer type for `U`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/traits/traits-negative-impls.rs b/src/test/ui/traits/traits-negative-impls.rs
new file mode 100644
index 0000000..fb9a3a9
--- /dev/null
+++ b/src/test/ui/traits/traits-negative-impls.rs
@@ -0,0 +1,68 @@
+// The dummy functions are used to avoid adding new cfail files.
+// What happens is that the compiler attempts to squash duplicates and some
+// errors are not reported. This way, we make sure that, for each function, different
+// typeck phases are involved and all errors are reported.
+
+#![feature(optin_builtin_traits)]
+
+use std::marker::Send;
+
+struct Outer<T: Send>(T);
+
+struct Outer2<T>(T);
+
+unsafe impl<T: Send> Sync for Outer2<T> {}
+
+fn is_send<T: Send>(_: T) {}
+fn is_sync<T: Sync>(_: T) {}
+
+fn dummy() {
+    struct TestType;
+    impl !Send for TestType {}
+
+    Outer(TestType);
+    //~^ ERROR `dummy::TestType` cannot be sent between threads safely
+    //~| ERROR `dummy::TestType` cannot be sent between threads safely
+}
+
+fn dummy1b() {
+    struct TestType;
+    impl !Send for TestType {}
+
+    is_send(TestType);
+    //~^ ERROR `dummy1b::TestType` cannot be sent between threads safely
+}
+
+fn dummy1c() {
+    struct TestType;
+    impl !Send for TestType {}
+
+    is_send((8, TestType));
+    //~^ ERROR `dummy1c::TestType` cannot be sent between threads safely
+}
+
+fn dummy2() {
+    struct TestType;
+    impl !Send for TestType {}
+
+    is_send(Box::new(TestType));
+    //~^ ERROR `dummy2::TestType` cannot be sent between threads safely
+}
+
+fn dummy3() {
+    struct TestType;
+    impl !Send for TestType {}
+
+    is_send(Box::new(Outer2(TestType)));
+    //~^ ERROR `dummy3::TestType` cannot be sent between threads safely
+}
+
+fn main() {
+    struct TestType;
+    impl !Send for TestType {}
+
+    // This will complain about a missing Send impl because `Sync` is implement *just*
+    // for T that are `Send`. Look at #20366 and #19950
+    is_sync(Outer2(TestType));
+    //~^ ERROR `main::TestType` cannot be sent between threads safely
+}
diff --git a/src/test/ui/traits/traits-negative-impls.stderr b/src/test/ui/traits/traits-negative-impls.stderr
new file mode 100644
index 0000000..1bdd73e
--- /dev/null
+++ b/src/test/ui/traits/traits-negative-impls.stderr
@@ -0,0 +1,101 @@
+error[E0277]: `dummy::TestType` cannot be sent between threads safely
+  --> $DIR/traits-negative-impls.rs:23:5
+   |
+LL |     Outer(TestType);
+   |     ^^^^^ `dummy::TestType` cannot be sent between threads safely
+   |
+   = help: the trait `std::marker::Send` is not implemented for `dummy::TestType`
+note: required by `Outer`
+  --> $DIR/traits-negative-impls.rs:10:1
+   |
+LL | struct Outer<T: Send>(T);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: `dummy::TestType` cannot be sent between threads safely
+  --> $DIR/traits-negative-impls.rs:23:5
+   |
+LL |     Outer(TestType);
+   |     ^^^^^^^^^^^^^^^ `dummy::TestType` cannot be sent between threads safely
+   |
+   = help: the trait `std::marker::Send` is not implemented for `dummy::TestType`
+note: required by `Outer`
+  --> $DIR/traits-negative-impls.rs:10:1
+   |
+LL | struct Outer<T: Send>(T);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: `dummy1b::TestType` cannot be sent between threads safely
+  --> $DIR/traits-negative-impls.rs:32:5
+   |
+LL |     is_send(TestType);
+   |     ^^^^^^^ `dummy1b::TestType` cannot be sent between threads safely
+   |
+   = help: the trait `std::marker::Send` is not implemented for `dummy1b::TestType`
+note: required by `is_send`
+  --> $DIR/traits-negative-impls.rs:16:1
+   |
+LL | fn is_send<T: Send>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: `dummy1c::TestType` cannot be sent between threads safely
+  --> $DIR/traits-negative-impls.rs:40:5
+   |
+LL |     is_send((8, TestType));
+   |     ^^^^^^^ `dummy1c::TestType` cannot be sent between threads safely
+   |
+   = help: within `({integer}, dummy1c::TestType)`, the trait `std::marker::Send` is not implemented for `dummy1c::TestType`
+   = note: required because it appears within the type `({integer}, dummy1c::TestType)`
+note: required by `is_send`
+  --> $DIR/traits-negative-impls.rs:16:1
+   |
+LL | fn is_send<T: Send>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: `dummy2::TestType` cannot be sent between threads safely
+  --> $DIR/traits-negative-impls.rs:48:5
+   |
+LL |     is_send(Box::new(TestType));
+   |     ^^^^^^^ `dummy2::TestType` cannot be sent between threads safely
+   |
+   = help: the trait `std::marker::Send` is not implemented for `dummy2::TestType`
+   = note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique<dummy2::TestType>`
+   = note: required because it appears within the type `std::boxed::Box<dummy2::TestType>`
+note: required by `is_send`
+  --> $DIR/traits-negative-impls.rs:16:1
+   |
+LL | fn is_send<T: Send>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: `dummy3::TestType` cannot be sent between threads safely
+  --> $DIR/traits-negative-impls.rs:56:5
+   |
+LL |     is_send(Box::new(Outer2(TestType)));
+   |     ^^^^^^^ `dummy3::TestType` cannot be sent between threads safely
+   |
+   = help: within `Outer2<dummy3::TestType>`, the trait `std::marker::Send` is not implemented for `dummy3::TestType`
+   = note: required because it appears within the type `Outer2<dummy3::TestType>`
+   = note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique<Outer2<dummy3::TestType>>`
+   = note: required because it appears within the type `std::boxed::Box<Outer2<dummy3::TestType>>`
+note: required by `is_send`
+  --> $DIR/traits-negative-impls.rs:16:1
+   |
+LL | fn is_send<T: Send>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: `main::TestType` cannot be sent between threads safely
+  --> $DIR/traits-negative-impls.rs:66:5
+   |
+LL |     is_sync(Outer2(TestType));
+   |     ^^^^^^^ `main::TestType` cannot be sent between threads safely
+   |
+   = help: the trait `std::marker::Send` is not implemented for `main::TestType`
+   = note: required because of the requirements on the impl of `std::marker::Sync` for `Outer2<main::TestType>`
+note: required by `is_sync`
+  --> $DIR/traits-negative-impls.rs:17:1
+   |
+LL | fn is_sync<T: Sync>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/traits/traits-repeated-supertrait-ambig.rs b/src/test/ui/traits/traits-repeated-supertrait-ambig.rs
new file mode 100644
index 0000000..5fa7e87
--- /dev/null
+++ b/src/test/ui/traits/traits-repeated-supertrait-ambig.rs
@@ -0,0 +1,43 @@
+// Test a case of a trait which extends the same supertrait twice, but
+// with difference type parameters. Test then that when we don't give
+// enough information to pick between these, no selection is made. In
+// this particular case, the two choices are i64/u64 -- so when we use
+// an integer literal, we wind up falling this literal back to i32.
+// See also `run-pass/trait-repeated-supertrait.rs`.
+
+trait CompareTo<T> {
+    fn same_as(&self, t: T) -> bool;
+}
+
+trait CompareToInts : CompareTo<i64> + CompareTo<u64> {
+}
+
+impl CompareTo<i64> for i64 {
+    fn same_as(&self, t: i64) -> bool { *self == t }
+}
+
+impl CompareTo<u64> for i64 {
+    fn same_as(&self, t: u64) -> bool { *self == (t as i64) }
+}
+
+impl CompareToInts for i64 { }
+
+fn with_obj(c: &CompareToInts) -> bool {
+    c.same_as(22) //~ ERROR `dyn CompareToInts: CompareTo<i32>` is not satisfied
+}
+
+fn with_trait<C:CompareToInts>(c: &C) -> bool {
+    c.same_as(22) //~ ERROR `C: CompareTo<i32>` is not satisfied
+}
+
+fn with_ufcs1<C:CompareToInts>(c: &C) -> bool {
+    CompareToInts::same_as(c, 22) //~ ERROR `dyn CompareToInts: CompareTo<i32>` is not satisfied
+}
+
+fn with_ufcs2<C:CompareToInts>(c: &C) -> bool {
+    CompareTo::same_as(c, 22) //~ ERROR `C: CompareTo<i32>` is not satisfied
+}
+
+fn main() {
+    assert_eq!(22_i64.same_as(22), true); //~ ERROR `i64: CompareTo<i32>` is not satisfied
+}
diff --git a/src/test/ui/traits/traits-repeated-supertrait-ambig.stderr b/src/test/ui/traits/traits-repeated-supertrait-ambig.stderr
new file mode 100644
index 0000000..5d1c913
--- /dev/null
+++ b/src/test/ui/traits/traits-repeated-supertrait-ambig.stderr
@@ -0,0 +1,52 @@
+error[E0277]: the trait bound `dyn CompareToInts: CompareTo<i32>` is not satisfied
+  --> $DIR/traits-repeated-supertrait-ambig.rs:26:7
+   |
+LL |     c.same_as(22)
+   |       ^^^^^^^ the trait `CompareTo<i32>` is not implemented for `dyn CompareToInts`
+
+error[E0277]: the trait bound `C: CompareTo<i32>` is not satisfied
+  --> $DIR/traits-repeated-supertrait-ambig.rs:30:7
+   |
+LL |     c.same_as(22)
+   |       ^^^^^^^ the trait `CompareTo<i32>` is not implemented for `C`
+   |
+   = help: consider adding a `where C: CompareTo<i32>` bound
+
+error[E0277]: the trait bound `dyn CompareToInts: CompareTo<i32>` is not satisfied
+  --> $DIR/traits-repeated-supertrait-ambig.rs:34:5
+   |
+LL |     CompareToInts::same_as(c, 22)
+   |     ^^^^^^^^^^^^^^^^^^^^^^ the trait `CompareTo<i32>` is not implemented for `dyn CompareToInts`
+   |
+note: required by `CompareTo::same_as`
+  --> $DIR/traits-repeated-supertrait-ambig.rs:9:5
+   |
+LL |     fn same_as(&self, t: T) -> bool;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `C: CompareTo<i32>` is not satisfied
+  --> $DIR/traits-repeated-supertrait-ambig.rs:38:5
+   |
+LL |     CompareTo::same_as(c, 22)
+   |     ^^^^^^^^^^^^^^^^^^ the trait `CompareTo<i32>` is not implemented for `C`
+   |
+   = help: consider adding a `where C: CompareTo<i32>` bound
+note: required by `CompareTo::same_as`
+  --> $DIR/traits-repeated-supertrait-ambig.rs:9:5
+   |
+LL |     fn same_as(&self, t: T) -> bool;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `i64: CompareTo<i32>` is not satisfied
+  --> $DIR/traits-repeated-supertrait-ambig.rs:42:23
+   |
+LL |     assert_eq!(22_i64.same_as(22), true);
+   |                       ^^^^^^^ the trait `CompareTo<i32>` is not implemented for `i64`
+   |
+   = help: the following implementations were found:
+             <i64 as CompareTo<i64>>
+             <i64 as CompareTo<u64>>
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/transmute-equal-assoc-types.rs b/src/test/ui/transmute-equal-assoc-types.rs
new file mode 100644
index 0000000..6f35754
--- /dev/null
+++ b/src/test/ui/transmute-equal-assoc-types.rs
@@ -0,0 +1,9 @@
+trait Foo {
+    type Bar;
+}
+
+unsafe fn noop<F: Foo>(foo: F::Bar) -> F::Bar {
+    ::std::mem::transmute(foo) //~ ERROR cannot transmute between types of different sizes
+}
+
+fn main() {}
diff --git a/src/test/ui/transmute-equal-assoc-types.stderr b/src/test/ui/transmute-equal-assoc-types.stderr
new file mode 100644
index 0000000..ce7657f
--- /dev/null
+++ b/src/test/ui/transmute-equal-assoc-types.stderr
@@ -0,0 +1,11 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/transmute-equal-assoc-types.rs:6:5
+   |
+LL |     ::std::mem::transmute(foo)
+   |     ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `<F as Foo>::Bar` does not have a fixed size
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0512`.
diff --git a/src/test/ui/transmute/main.rs b/src/test/ui/transmute/main.rs
new file mode 100644
index 0000000..ea233a4
--- /dev/null
+++ b/src/test/ui/transmute/main.rs
@@ -0,0 +1,32 @@
+// normalize-stderr-32bit: "`&str` \(64 bits\)" -> "`&str` ($$STR bits)"
+// normalize-stderr-64bit: "`&str` \(128 bits\)" -> "`&str` ($$STR bits)"
+
+
+
+#![feature(untagged_unions)]
+use std::mem::transmute;
+
+pub trait TypeConstructor<'a> {
+    type T;
+}
+
+unsafe fn transmute_lifetime<'a, 'b, C>(x: <C as TypeConstructor<'a>>::T)
+                                        -> <C as TypeConstructor<'b>>::T
+where for<'z> C: TypeConstructor<'z> {
+    transmute(x) //~ ERROR cannot transmute between types of different sizes
+}
+
+unsafe fn sizes() {
+    let x: u8 = transmute(10u16); //~ ERROR cannot transmute between types of different sizes
+}
+
+unsafe fn ptrs() {
+    let x: u8 = transmute("test"); //~ ERROR cannot transmute between types of different sizes
+}
+
+union Foo { x: () }
+unsafe fn vary() {
+    let x: Foo = transmute(10); //~ ERROR cannot transmute between types of different sizes
+}
+
+fn main() {}
diff --git a/src/test/ui/transmute/main.stderr b/src/test/ui/transmute/main.stderr
new file mode 100644
index 0000000..c72876e
--- /dev/null
+++ b/src/test/ui/transmute/main.stderr
@@ -0,0 +1,39 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/main.rs:16:5
+   |
+LL |     transmute(x)
+   |     ^^^^^^^^^
+   |
+   = note: source type: `<C as TypeConstructor<'a>>::T` (size can vary because of <C as TypeConstructor>::T)
+   = note: target type: `<C as TypeConstructor<'b>>::T` (size can vary because of <C as TypeConstructor>::T)
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/main.rs:20:17
+   |
+LL |     let x: u8 = transmute(10u16);
+   |                 ^^^^^^^^^
+   |
+   = note: source type: `u16` (16 bits)
+   = note: target type: `u8` (8 bits)
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/main.rs:24:17
+   |
+LL |     let x: u8 = transmute("test");
+   |                 ^^^^^^^^^
+   |
+   = note: source type: `&str` ($STR bits)
+   = note: target type: `u8` (8 bits)
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/main.rs:29:18
+   |
+LL |     let x: Foo = transmute(10);
+   |                  ^^^^^^^^^
+   |
+   = note: source type: `i32` (32 bits)
+   = note: target type: `Foo` (0 bits)
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0512`.
diff --git a/src/test/ui/transmute/transmute-different-sizes.rs b/src/test/ui/transmute/transmute-different-sizes.rs
new file mode 100644
index 0000000..690decf
--- /dev/null
+++ b/src/test/ui/transmute/transmute-different-sizes.rs
@@ -0,0 +1,31 @@
+// normalize-stderr-test "\d+ bits" -> "N bits"
+
+// Tests that `transmute` cannot be called on types of different size.
+
+#![allow(warnings)]
+#![feature(specialization)]
+
+use std::mem::transmute;
+
+unsafe fn f() {
+    let _: i8 = transmute(16i16);
+    //~^ ERROR cannot transmute between types of different sizes, or dependently-sized types
+}
+
+unsafe fn g<T>(x: &T) {
+    let _: i8 = transmute(x);
+    //~^ ERROR cannot transmute between types of different sizes, or dependently-sized types
+}
+
+trait Specializable { type Output; }
+
+impl<T> Specializable for T {
+    default type Output = u16;
+}
+
+unsafe fn specializable<T>(x: u16) -> <T as Specializable>::Output {
+    transmute(x)
+    //~^ ERROR cannot transmute between types of different sizes, or dependently-sized types
+}
+
+fn main() {}
diff --git a/src/test/ui/transmute/transmute-different-sizes.stderr b/src/test/ui/transmute/transmute-different-sizes.stderr
new file mode 100644
index 0000000..07a38df
--- /dev/null
+++ b/src/test/ui/transmute/transmute-different-sizes.stderr
@@ -0,0 +1,30 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/transmute-different-sizes.rs:11:17
+   |
+LL |     let _: i8 = transmute(16i16);
+   |                 ^^^^^^^^^
+   |
+   = note: source type: `i16` (N bits)
+   = note: target type: `i8` (N bits)
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/transmute-different-sizes.rs:16:17
+   |
+LL |     let _: i8 = transmute(x);
+   |                 ^^^^^^^^^
+   |
+   = note: source type: `&T` (N bits)
+   = note: target type: `i8` (N bits)
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/transmute-different-sizes.rs:27:5
+   |
+LL |     transmute(x)
+   |     ^^^^^^^^^
+   |
+   = note: source type: `u16` (N bits)
+   = note: target type: `<T as Specializable>::Output` (this type does not have a fixed size)
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0512`.
diff --git a/src/test/ui/transmute/transmute-fat-pointers.rs b/src/test/ui/transmute/transmute-fat-pointers.rs
new file mode 100644
index 0000000..7c1beff
--- /dev/null
+++ b/src/test/ui/transmute/transmute-fat-pointers.rs
@@ -0,0 +1,33 @@
+// normalize-stderr-test "\d+ bits" -> "N bits"
+
+// Tests that are conservative around thin/fat pointer mismatches.
+
+#![allow(dead_code)]
+
+use std::mem::transmute;
+
+fn a<T, U: ?Sized>(x: &[T]) -> &U {
+    unsafe { transmute(x) } //~ ERROR cannot transmute between types of different sizes
+}
+
+fn b<T: ?Sized, U: ?Sized>(x: &T) -> &U {
+    unsafe { transmute(x) } //~ ERROR cannot transmute between types of different sizes
+}
+
+fn c<T, U>(x: &T) -> &U {
+    unsafe { transmute(x) }
+}
+
+fn d<T, U>(x: &[T]) -> &[U] {
+    unsafe { transmute(x) }
+}
+
+fn e<T: ?Sized, U>(x: &T) -> &U {
+    unsafe { transmute(x) } //~ ERROR cannot transmute between types of different sizes
+}
+
+fn f<T, U: ?Sized>(x: &T) -> &U {
+    unsafe { transmute(x) } //~ ERROR cannot transmute between types of different sizes
+}
+
+fn main() { }
diff --git a/src/test/ui/transmute/transmute-fat-pointers.stderr b/src/test/ui/transmute/transmute-fat-pointers.stderr
new file mode 100644
index 0000000..e8335fc
--- /dev/null
+++ b/src/test/ui/transmute/transmute-fat-pointers.stderr
@@ -0,0 +1,39 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/transmute-fat-pointers.rs:10:14
+   |
+LL |     unsafe { transmute(x) }
+   |              ^^^^^^^^^
+   |
+   = note: source type: `&[T]` (N bits)
+   = note: target type: `&U` (pointer to `U`)
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/transmute-fat-pointers.rs:14:14
+   |
+LL |     unsafe { transmute(x) }
+   |              ^^^^^^^^^
+   |
+   = note: source type: `&T` (pointer to `T`)
+   = note: target type: `&U` (pointer to `U`)
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/transmute-fat-pointers.rs:26:14
+   |
+LL |     unsafe { transmute(x) }
+   |              ^^^^^^^^^
+   |
+   = note: source type: `&T` (pointer to `T`)
+   = note: target type: `&U` (N bits)
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/transmute-fat-pointers.rs:30:14
+   |
+LL |     unsafe { transmute(x) }
+   |              ^^^^^^^^^
+   |
+   = note: source type: `&T` (N bits)
+   = note: target type: `&U` (pointer to `U`)
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0512`.
diff --git a/src/test/ui/transmute/transmute-from-fn-item-types-error.rs b/src/test/ui/transmute/transmute-from-fn-item-types-error.rs
new file mode 100644
index 0000000..f858a19
--- /dev/null
+++ b/src/test/ui/transmute/transmute-from-fn-item-types-error.rs
@@ -0,0 +1,60 @@
+use std::mem;
+
+unsafe fn foo() -> (i8, *const (), Option<fn()>) {
+    let i = mem::transmute(bar);
+    //~^ ERROR cannot transmute between types of different sizes, or dependently-sized types
+
+
+    let p = mem::transmute(foo);
+    //~^ ERROR can't transmute zero-sized type
+
+
+    let of = mem::transmute(main);
+    //~^ ERROR can't transmute zero-sized type
+
+
+    (i, p, of)
+}
+
+unsafe fn bar() {
+    // Error as usual if the resulting type is not pointer-sized.
+    mem::transmute::<_, u8>(main);
+    //~^ ERROR cannot transmute between types of different sizes, or dependently-sized types
+
+
+    mem::transmute::<_, *mut ()>(foo);
+    //~^ ERROR can't transmute zero-sized type
+
+
+    mem::transmute::<_, fn()>(bar);
+    //~^ ERROR can't transmute zero-sized type
+
+
+    // No error if a coercion would otherwise occur.
+    mem::transmute::<fn(), usize>(main);
+}
+
+unsafe fn baz() {
+    mem::transmute::<_, *mut ()>(Some(foo));
+    //~^ ERROR can't transmute zero-sized type
+
+
+    mem::transmute::<_, fn()>(Some(bar));
+    //~^ ERROR can't transmute zero-sized type
+
+
+    mem::transmute::<_, Option<fn()>>(Some(baz));
+    //~^ ERROR can't transmute zero-sized type
+
+
+    // No error if a coercion would otherwise occur.
+    mem::transmute::<Option<fn()>, usize>(Some(main));
+}
+
+fn main() {
+    unsafe {
+        foo();
+        bar();
+        baz();
+    }
+}
diff --git a/src/test/ui/transmute/transmute-from-fn-item-types-error.stderr b/src/test/ui/transmute/transmute-from-fn-item-types-error.stderr
new file mode 100644
index 0000000..d08078b
--- /dev/null
+++ b/src/test/ui/transmute/transmute-from-fn-item-types-error.stderr
@@ -0,0 +1,92 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/transmute-from-fn-item-types-error.rs:4:13
+   |
+LL |     let i = mem::transmute(bar);
+   |             ^^^^^^^^^^^^^^
+   |
+   = note: source type: `unsafe fn() {bar}` (0 bits)
+   = note: target type: `i8` (8 bits)
+
+error[E0591]: can't transmute zero-sized type
+  --> $DIR/transmute-from-fn-item-types-error.rs:8:13
+   |
+LL |     let p = mem::transmute(foo);
+   |             ^^^^^^^^^^^^^^
+   |
+   = note: source type: unsafe fn() -> (i8, *const (), std::option::Option<fn()>) {foo}
+   = note: target type: *const ()
+   = help: cast with `as` to a pointer instead
+
+error[E0591]: can't transmute zero-sized type
+  --> $DIR/transmute-from-fn-item-types-error.rs:12:14
+   |
+LL |     let of = mem::transmute(main);
+   |              ^^^^^^^^^^^^^^
+   |
+   = note: source type: fn() {main}
+   = note: target type: std::option::Option<fn()>
+   = help: cast with `as` to a pointer instead
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/transmute-from-fn-item-types-error.rs:21:5
+   |
+LL |     mem::transmute::<_, u8>(main);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: source type: `fn() {main}` (0 bits)
+   = note: target type: `u8` (8 bits)
+
+error[E0591]: can't transmute zero-sized type
+  --> $DIR/transmute-from-fn-item-types-error.rs:25:5
+   |
+LL |     mem::transmute::<_, *mut ()>(foo);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: source type: unsafe fn() -> (i8, *const (), std::option::Option<fn()>) {foo}
+   = note: target type: *mut ()
+   = help: cast with `as` to a pointer instead
+
+error[E0591]: can't transmute zero-sized type
+  --> $DIR/transmute-from-fn-item-types-error.rs:29:5
+   |
+LL |     mem::transmute::<_, fn()>(bar);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: source type: unsafe fn() {bar}
+   = note: target type: fn()
+   = help: cast with `as` to a pointer instead
+
+error[E0591]: can't transmute zero-sized type
+  --> $DIR/transmute-from-fn-item-types-error.rs:38:5
+   |
+LL |     mem::transmute::<_, *mut ()>(Some(foo));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: source type: unsafe fn() -> (i8, *const (), std::option::Option<fn()>) {foo}
+   = note: target type: *mut ()
+   = help: cast with `as` to a pointer instead
+
+error[E0591]: can't transmute zero-sized type
+  --> $DIR/transmute-from-fn-item-types-error.rs:42:5
+   |
+LL |     mem::transmute::<_, fn()>(Some(bar));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: source type: unsafe fn() {bar}
+   = note: target type: fn()
+   = help: cast with `as` to a pointer instead
+
+error[E0591]: can't transmute zero-sized type
+  --> $DIR/transmute-from-fn-item-types-error.rs:46:5
+   |
+LL |     mem::transmute::<_, Option<fn()>>(Some(baz));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: source type: unsafe fn() {baz}
+   = note: target type: std::option::Option<fn()>
+   = help: cast with `as` to a pointer instead
+
+error: aborting due to 9 previous errors
+
+Some errors occurred: E0512, E0591.
+For more information about an error, try `rustc --explain E0512`.
diff --git a/src/test/ui/transmute/transmute-impl.rs b/src/test/ui/transmute/transmute-impl.rs
new file mode 100644
index 0000000..df422bd
--- /dev/null
+++ b/src/test/ui/transmute/transmute-impl.rs
@@ -0,0 +1,25 @@
+// normalize-stderr-test "\d+ bits" -> "N bits"
+
+// Tests that are conservative around thin/fat pointer mismatches.
+
+#![allow(dead_code)]
+
+use std::mem::transmute;
+
+struct Foo<T: ?Sized> {
+    t: Box<T>
+}
+
+impl<T: ?Sized> Foo<T> {
+    fn m(x: &T) -> &isize where T : Sized {
+        // OK here, because T : Sized is in scope.
+        unsafe { transmute(x) }
+    }
+
+    fn n(x: &T) -> &isize {
+        // Not OK here, because T : Sized is not in scope.
+        unsafe { transmute(x) } //~ ERROR cannot transmute between types of different sizes
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/transmute/transmute-impl.stderr b/src/test/ui/transmute/transmute-impl.stderr
new file mode 100644
index 0000000..dd19bcd
--- /dev/null
+++ b/src/test/ui/transmute/transmute-impl.stderr
@@ -0,0 +1,12 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/transmute-impl.rs:21:18
+   |
+LL |         unsafe { transmute(x) }
+   |                  ^^^^^^^^^
+   |
+   = note: source type: `&T` (pointer to `T`)
+   = note: target type: `&isize` (N bits)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0512`.
diff --git a/src/test/ui/transmute/transmute-imut-to-mut.rs b/src/test/ui/transmute/transmute-imut-to-mut.rs
new file mode 100644
index 0000000..94361a2
--- /dev/null
+++ b/src/test/ui/transmute/transmute-imut-to-mut.rs
@@ -0,0 +1,9 @@
+// Tests that transmuting from &T to &mut T is Undefined Behavior.
+
+use std::mem::transmute;
+
+fn main() {
+    let _a: &mut u8 = unsafe { transmute(&1u8) };
+    //~^ ERROR mutating transmuted &mut T from &T may cause undefined behavior
+}
+
diff --git a/src/test/ui/transmute/transmute-imut-to-mut.stderr b/src/test/ui/transmute/transmute-imut-to-mut.stderr
new file mode 100644
index 0000000..d2445f0
--- /dev/null
+++ b/src/test/ui/transmute/transmute-imut-to-mut.stderr
@@ -0,0 +1,10 @@
+error: mutating transmuted &mut T from &T may cause undefined behavior, consider instead using an UnsafeCell
+  --> $DIR/transmute-imut-to-mut.rs:6:32
+   |
+LL |     let _a: &mut u8 = unsafe { transmute(&1u8) };
+   |                                ^^^^^^^^^
+   |
+   = note: #[deny(mutable_transmutes)] on by default
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/transmute/transmute-type-parameters.rs b/src/test/ui/transmute/transmute-type-parameters.rs
new file mode 100644
index 0000000..5f44b2d
--- /dev/null
+++ b/src/test/ui/transmute/transmute-type-parameters.rs
@@ -0,0 +1,44 @@
+// Tests that `transmute` cannot be called on type parameters.
+
+use std::mem::transmute;
+
+unsafe fn f<T>(x: T) {
+    let _: i32 = transmute(x);
+//~^ ERROR cannot transmute between types of different sizes, or dependently-sized types
+}
+
+unsafe fn g<T>(x: (T, i32)) {
+    let _: i32 = transmute(x);
+//~^ ERROR cannot transmute between types of different sizes, or dependently-sized types
+}
+
+unsafe fn h<T>(x: [T; 10]) {
+    let _: i32 = transmute(x);
+//~^ ERROR cannot transmute between types of different sizes, or dependently-sized types
+}
+
+struct Bad<T> {
+    f: T,
+}
+
+unsafe fn i<T>(x: Bad<T>) {
+    let _: i32 = transmute(x);
+//~^ ERROR cannot transmute between types of different sizes, or dependently-sized types
+}
+
+enum Worse<T> {
+    A(T),
+    B,
+}
+
+unsafe fn j<T>(x: Worse<T>) {
+    let _: i32 = transmute(x);
+//~^ ERROR cannot transmute between types of different sizes, or dependently-sized types
+}
+
+unsafe fn k<T>(x: Option<T>) {
+    let _: i32 = transmute(x);
+//~^ ERROR cannot transmute between types of different sizes, or dependently-sized types
+}
+
+fn main() {}
diff --git a/src/test/ui/transmute/transmute-type-parameters.stderr b/src/test/ui/transmute/transmute-type-parameters.stderr
new file mode 100644
index 0000000..a355a1b
--- /dev/null
+++ b/src/test/ui/transmute/transmute-type-parameters.stderr
@@ -0,0 +1,57 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/transmute-type-parameters.rs:6:18
+   |
+LL |     let _: i32 = transmute(x);
+   |                  ^^^^^^^^^
+   |
+   = note: source type: `T` (this type does not have a fixed size)
+   = note: target type: `i32` (32 bits)
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/transmute-type-parameters.rs:11:18
+   |
+LL |     let _: i32 = transmute(x);
+   |                  ^^^^^^^^^
+   |
+   = note: source type: `(T, i32)` (size can vary because of T)
+   = note: target type: `i32` (32 bits)
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/transmute-type-parameters.rs:16:18
+   |
+LL |     let _: i32 = transmute(x);
+   |                  ^^^^^^^^^
+   |
+   = note: source type: `[T; 10]` (size can vary because of T)
+   = note: target type: `i32` (32 bits)
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/transmute-type-parameters.rs:25:18
+   |
+LL |     let _: i32 = transmute(x);
+   |                  ^^^^^^^^^
+   |
+   = note: source type: `Bad<T>` (size can vary because of T)
+   = note: target type: `i32` (32 bits)
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/transmute-type-parameters.rs:35:18
+   |
+LL |     let _: i32 = transmute(x);
+   |                  ^^^^^^^^^
+   |
+   = note: source type: `Worse<T>` (size can vary because of T)
+   = note: target type: `i32` (32 bits)
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/transmute-type-parameters.rs:40:18
+   |
+LL |     let _: i32 = transmute(x);
+   |                  ^^^^^^^^^
+   |
+   = note: source type: `std::option::Option<T>` (size can vary because of T)
+   = note: target type: `i32` (32 bits)
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0512`.
diff --git a/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-associated-functions.rs b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-associated-functions.rs
new file mode 100644
index 0000000..6450ddd1
--- /dev/null
+++ b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-associated-functions.rs
@@ -0,0 +1,19 @@
+// run-pass
+// Inconsistent bounds with trait implementations
+
+#![feature(trivial_bounds)]
+#![allow(unused)]
+
+trait A {
+    fn foo(&self) -> Self where Self: Copy;
+}
+
+impl A for str {
+    fn foo(&self) -> Self where Self: Copy { *"" }
+}
+
+impl A for i32 {
+    fn foo(&self) -> Self { 3 }
+}
+
+fn main() {}
diff --git a/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-copy-reborrow.nll.stderr b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-copy-reborrow.nll.stderr
new file mode 100644
index 0000000..aac119a
--- /dev/null
+++ b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-copy-reborrow.nll.stderr
@@ -0,0 +1,19 @@
+error[E0596]: cannot borrow `**t` as mutable, as it is behind a `&` reference
+  --> $DIR/trivial-bounds-inconsistent-copy-reborrow.rs:6: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: `&'a mut &'a mut i32`
+LL |     *t
+   |     ^^ `t` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+
+error[E0596]: cannot borrow `**t` as mutable, as it is behind a `&` reference
+  --> $DIR/trivial-bounds-inconsistent-copy-reborrow.rs:10: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: `&'a mut &'a mut i32`
+LL |     {*t}
+   |      ^^ `t` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-copy-reborrow.rs b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-copy-reborrow.rs
new file mode 100644
index 0000000..b1ff23f
--- /dev/null
+++ b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-copy-reborrow.rs
@@ -0,0 +1,13 @@
+// Check that reborrows are still illegal with Copy mutable references
+#![feature(trivial_bounds)]
+#![allow(unused)]
+
+fn reborrow_mut<'a>(t: &'a &'a mut i32) -> &'a mut i32 where &'a mut i32: Copy {
+    *t //~ ERROR
+}
+
+fn copy_reborrow_mut<'a>(t: &'a &'a mut i32) -> &'a mut i32 where &'a mut i32: Copy {
+    {*t} //~ ERROR
+}
+
+fn main() {}
diff --git a/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-copy-reborrow.stderr b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-copy-reborrow.stderr
new file mode 100644
index 0000000..adaeb9b
--- /dev/null
+++ b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-copy-reborrow.stderr
@@ -0,0 +1,19 @@
+error[E0389]: cannot borrow data mutably in a `&` reference
+  --> $DIR/trivial-bounds-inconsistent-copy-reborrow.rs:6:5
+   |
+LL | fn reborrow_mut<'a>(t: &'a &'a mut i32) -> &'a mut i32 where &'a mut i32: Copy {
+   |                        --------------- use `&'a mut &'a mut i32` here to make mutable
+LL |     *t
+   |     ^^ assignment into an immutable reference
+
+error[E0389]: cannot borrow data mutably in a `&` reference
+  --> $DIR/trivial-bounds-inconsistent-copy-reborrow.rs:10:6
+   |
+LL | fn copy_reborrow_mut<'a>(t: &'a &'a mut i32) -> &'a mut i32 where &'a mut i32: Copy {
+   |                             --------------- use `&'a mut &'a mut i32` here to make mutable
+LL |     {*t}
+   |      ^^ assignment into an immutable reference
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0389`.
diff --git a/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-copy.rs b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-copy.rs
new file mode 100644
index 0000000..bdbd641
--- /dev/null
+++ b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-copy.rs
@@ -0,0 +1,33 @@
+// run-pass
+// Check tautalogically false `Copy` bounds
+#![feature(trivial_bounds)]
+#![allow(unused)]
+
+fn copy_string(t: String) -> String where String: Copy {
+    is_copy(&t);
+    let x = t;
+    drop(t);
+    t
+}
+
+fn copy_out_string(t: &String) -> String where String: Copy {
+    *t
+}
+
+fn copy_string_with_param<T>(x: String) where String: Copy {
+    let y = x;
+    let z = x;
+}
+
+// Check that no reborrowing occurs
+fn copy_mut<'a>(t: &&'a mut i32) -> &'a mut i32 where for<'b> &'b mut i32: Copy {
+    is_copy(t);
+    let x = *t;
+    drop(x);
+    x
+}
+
+fn is_copy<T: Copy>(t: &T) {}
+
+
+fn main() {}
diff --git a/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-copy.stderr b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-copy.stderr
new file mode 100644
index 0000000..12d61fc
--- /dev/null
+++ b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-copy.stderr
@@ -0,0 +1,26 @@
+warning: Trait bound std::string::String: std::marker::Copy does not depend on any type or lifetime parameters
+  --> $DIR/trivial-bounds-inconsistent-copy.rs:6:51
+   |
+LL | fn copy_string(t: String) -> String where String: Copy {
+   |                                                   ^^^^
+   |
+   = note: #[warn(trivial_bounds)] on by default
+
+warning: Trait bound std::string::String: std::marker::Copy does not depend on any type or lifetime parameters
+  --> $DIR/trivial-bounds-inconsistent-copy.rs:13:56
+   |
+LL | fn copy_out_string(t: &String) -> String where String: Copy {
+   |                                                        ^^^^
+
+warning: Trait bound std::string::String: std::marker::Copy does not depend on any type or lifetime parameters
+  --> $DIR/trivial-bounds-inconsistent-copy.rs:17:55
+   |
+LL | fn copy_string_with_param<T>(x: String) where String: Copy {
+   |                                                       ^^^^
+
+warning: Trait bound for<'b> &'b mut i32: std::marker::Copy does not depend on any type or lifetime parameters
+  --> $DIR/trivial-bounds-inconsistent-copy.rs:23:76
+   |
+LL | fn copy_mut<'a>(t: &&'a mut i32) -> &'a mut i32 where for<'b> &'b mut i32: Copy {
+   |                                                                            ^^^^
+
diff --git a/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-projection-error.rs b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-projection-error.rs
new file mode 100644
index 0000000..e0f2996
--- /dev/null
+++ b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-projection-error.rs
@@ -0,0 +1,23 @@
+#![feature(trivial_bounds)]
+#![allow(unused)]
+
+struct B;
+
+trait A {
+    type X;
+    fn get_x() -> Self::X;
+}
+
+impl A for B {
+    type X = u8;
+    fn get_x() -> u8 { 0 }
+}
+
+fn global_bound_is_hidden() -> u8
+where
+    B: A<X = i32>
+{
+    B::get_x() //~ ERROR
+}
+
+fn main () {}
diff --git a/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-projection-error.stderr b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-projection-error.stderr
new file mode 100644
index 0000000..7c1a833
--- /dev/null
+++ b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-projection-error.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/trivial-bounds-inconsistent-projection-error.rs:20:5
+   |
+LL | fn global_bound_is_hidden() -> u8
+   |                                -- expected `u8` because of return type
+...
+LL |     B::get_x()
+   |     ^^^^^^^^^^ expected u8, found i32
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-projection.rs b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-projection.rs
new file mode 100644
index 0000000..fa2daeb
--- /dev/null
+++ b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-projection.rs
@@ -0,0 +1,54 @@
+// run-pass
+// Check that global bounds result in the expected choice of associated type
+
+#![feature(trivial_bounds)]
+#![allow(unused)]
+
+struct B;
+
+trait A {
+    type X;
+    fn get_x() -> Self::X;
+}
+
+impl A for B {
+    type X = u8;
+    fn get_x() -> u8 { 0 }
+}
+
+fn underspecified_bound() -> u8
+where
+    B: A
+{
+    B::get_x()
+}
+
+fn inconsistent_bound() -> i32
+where
+    B: A<X = i32>
+{
+    B::get_x()
+}
+
+fn redundant_bound() -> u8
+where
+    B: A<X = u8>
+{
+    B::get_x()
+}
+
+fn inconsistent_dup_bound() -> i32
+where
+    B: A<X = i32> + A
+{
+    B::get_x()
+}
+
+fn redundant_dup_bound() -> u8
+where
+    B: A<X = u8> + A
+{
+    B::get_x()
+}
+
+fn main () {}
diff --git a/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-projection.stderr b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-projection.stderr
new file mode 100644
index 0000000..561614d
--- /dev/null
+++ b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-projection.stderr
@@ -0,0 +1,44 @@
+warning: Trait bound B: A does not depend on any type or lifetime parameters
+  --> $DIR/trivial-bounds-inconsistent-projection.rs:21:8
+   |
+LL |     B: A
+   |        ^
+   |
+   = note: #[warn(trivial_bounds)] on by default
+
+warning: Trait bound B: A does not depend on any type or lifetime parameters
+  --> $DIR/trivial-bounds-inconsistent-projection.rs:28:8
+   |
+LL |     B: A<X = i32>
+   |        ^^^^^^^^^^
+
+warning: Trait bound B: A does not depend on any type or lifetime parameters
+  --> $DIR/trivial-bounds-inconsistent-projection.rs:35:8
+   |
+LL |     B: A<X = u8>
+   |        ^^^^^^^^^
+
+warning: Trait bound B: A does not depend on any type or lifetime parameters
+  --> $DIR/trivial-bounds-inconsistent-projection.rs:42:8
+   |
+LL |     B: A<X = i32> + A
+   |        ^^^^^^^^^^
+
+warning: Trait bound B: A does not depend on any type or lifetime parameters
+  --> $DIR/trivial-bounds-inconsistent-projection.rs:42:21
+   |
+LL |     B: A<X = i32> + A
+   |                     ^
+
+warning: Trait bound B: A does not depend on any type or lifetime parameters
+  --> $DIR/trivial-bounds-inconsistent-projection.rs:49:8
+   |
+LL |     B: A<X = u8> + A
+   |        ^^^^^^^^^
+
+warning: Trait bound B: A does not depend on any type or lifetime parameters
+  --> $DIR/trivial-bounds-inconsistent-projection.rs:49:20
+   |
+LL |     B: A<X = u8> + A
+   |                    ^
+
diff --git a/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-sized.rs b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-sized.rs
new file mode 100644
index 0000000..a5d5b93
--- /dev/null
+++ b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-sized.rs
@@ -0,0 +1,24 @@
+// run-pass
+// Check tautalogically false `Sized` bounds
+#![feature(trivial_bounds)]
+#![allow(unused)]
+
+trait A {}
+
+impl A for i32 {}
+
+struct T<X: ?Sized> {
+    x: X,
+}
+
+struct S(str, str) where str: Sized;
+
+fn unsized_local() where for<'a> T<A + 'a>: Sized {
+    let x: T<A> = *(Box::new(T { x: 1 }) as Box<T<A>>);
+}
+
+fn return_str() -> str where str: Sized {
+    *"Sized".to_string().into_boxed_str()
+}
+
+fn main() {}
diff --git a/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-sized.stderr b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-sized.stderr
new file mode 100644
index 0000000..a9d2634
--- /dev/null
+++ b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-sized.stderr
@@ -0,0 +1,20 @@
+warning: Trait bound str: std::marker::Sized does not depend on any type or lifetime parameters
+  --> $DIR/trivial-bounds-inconsistent-sized.rs:14:31
+   |
+LL | struct S(str, str) where str: Sized;
+   |                               ^^^^^
+   |
+   = note: #[warn(trivial_bounds)] on by default
+
+warning: Trait bound for<'a> T<(dyn A + 'a)>: std::marker::Sized does not depend on any type or lifetime parameters
+  --> $DIR/trivial-bounds-inconsistent-sized.rs:16:45
+   |
+LL | fn unsized_local() where for<'a> T<A + 'a>: Sized {
+   |                                             ^^^^^
+
+warning: Trait bound str: std::marker::Sized does not depend on any type or lifetime parameters
+  --> $DIR/trivial-bounds-inconsistent-sized.rs:20:35
+   |
+LL | fn return_str() -> str where str: Sized {
+   |                                   ^^^^^
+
diff --git a/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-well-formed.rs b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-well-formed.rs
new file mode 100644
index 0000000..cab2423
--- /dev/null
+++ b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-well-formed.rs
@@ -0,0 +1,12 @@
+// run-pass
+// Test that inconsistent bounds are used in well-formedness checks
+#![feature(trivial_bounds)]
+
+use std::fmt::Debug;
+
+pub fn foo() where Vec<str>: Debug, str: Copy {
+    let x = vec![*"1"];
+    println!("{:?}", x);
+}
+
+fn main() {}
diff --git a/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-well-formed.stderr b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-well-formed.stderr
new file mode 100644
index 0000000..a72e3f7
--- /dev/null
+++ b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-well-formed.stderr
@@ -0,0 +1,14 @@
+warning: Trait bound std::vec::Vec<str>: std::fmt::Debug does not depend on any type or lifetime parameters
+  --> $DIR/trivial-bounds-inconsistent-well-formed.rs:7:30
+   |
+LL | pub fn foo() where Vec<str>: Debug, str: Copy {
+   |                              ^^^^^
+   |
+   = note: #[warn(trivial_bounds)] on by default
+
+warning: Trait bound str: std::marker::Copy does not depend on any type or lifetime parameters
+  --> $DIR/trivial-bounds-inconsistent-well-formed.rs:7:42
+   |
+LL | pub fn foo() where Vec<str>: Debug, str: Copy {
+   |                                          ^^^^
+
diff --git a/src/test/ui/trivial-bounds/trivial-bounds-inconsistent.rs b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent.rs
new file mode 100644
index 0000000..fdbaec9
--- /dev/null
+++ b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent.rs
@@ -0,0 +1,71 @@
+// run-pass
+
+// Check that tautalogically false bounds are accepted, and are used
+// in type inference.
+#![feature(trivial_bounds)]
+#![allow(unused)]
+
+pub trait Foo {
+    fn test(&self);
+}
+
+fn generic_function<X: Foo>(x: X) {}
+
+enum E where i32: Foo { V }
+
+struct S where i32: Foo;
+
+trait T where i32: Foo {}
+
+union U where i32: Foo { f: i32 }
+
+type Y where i32: Foo = ();
+
+impl Foo for () where i32: Foo {
+    fn test(&self) {
+        3i32.test();
+        Foo::test(&4i32);
+        generic_function(5i32);
+    }
+}
+
+fn f() where i32: Foo {
+    let s = S;
+    3i32.test();
+    Foo::test(&4i32);
+    generic_function(5i32);
+}
+
+fn g() where &'static str: Foo {
+    "Foo".test();
+    Foo::test(&"Foo");
+    generic_function("Foo");
+}
+
+trait A {}
+
+impl A for i32 {}
+
+struct Dst<X: ?Sized> {
+    x: X,
+}
+
+struct TwoStrs(str, str) where str: Sized;
+
+fn unsized_local() where for<'a> Dst<A + 'a>: Sized {
+    let x: Dst<A> = *(Box::new(Dst { x: 1 }) as Box<Dst<A>>);
+}
+
+fn return_str() -> str where str: Sized {
+    *"Sized".to_string().into_boxed_str()
+}
+
+fn use_op(s: String) -> String where String: ::std::ops::Neg<Output=String> {
+    -s
+}
+
+fn use_for() where i32: Iterator {
+    for _ in 2i32 {}
+}
+
+fn main() {}
diff --git a/src/test/ui/trivial-bounds/trivial-bounds-inconsistent.stderr b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent.stderr
new file mode 100644
index 0000000..744e146
--- /dev/null
+++ b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent.stderr
@@ -0,0 +1,89 @@
+warning: Trait bound i32: Foo does not depend on any type or lifetime parameters
+  --> $DIR/trivial-bounds-inconsistent.rs:14:19
+   |
+LL | enum E where i32: Foo { V }
+   |                   ^^^
+   |
+   = note: #[warn(trivial_bounds)] on by default
+
+warning: Trait bound i32: Foo does not depend on any type or lifetime parameters
+  --> $DIR/trivial-bounds-inconsistent.rs:16:21
+   |
+LL | struct S where i32: Foo;
+   |                     ^^^
+
+warning: Trait bound i32: Foo does not depend on any type or lifetime parameters
+  --> $DIR/trivial-bounds-inconsistent.rs:18:20
+   |
+LL | trait T where i32: Foo {}
+   |                    ^^^
+
+warning: Trait bound i32: Foo does not depend on any type or lifetime parameters
+  --> $DIR/trivial-bounds-inconsistent.rs:20:20
+   |
+LL | union U where i32: Foo { f: i32 }
+   |                    ^^^
+
+warning: where clauses are not enforced in type aliases
+  --> $DIR/trivial-bounds-inconsistent.rs:22:14
+   |
+LL | type Y where i32: Foo = ();
+   |              ^^^^^^^^
+   |
+   = note: #[warn(type_alias_bounds)] on by default
+   = help: the clause will not be checked when the type alias is used, and should be removed
+
+warning: Trait bound i32: Foo does not depend on any type or lifetime parameters
+  --> $DIR/trivial-bounds-inconsistent.rs:22:19
+   |
+LL | type Y where i32: Foo = ();
+   |                   ^^^
+
+warning: Trait bound i32: Foo does not depend on any type or lifetime parameters
+  --> $DIR/trivial-bounds-inconsistent.rs:24:28
+   |
+LL | impl Foo for () where i32: Foo {
+   |                            ^^^
+
+warning: Trait bound i32: Foo does not depend on any type or lifetime parameters
+  --> $DIR/trivial-bounds-inconsistent.rs:32:19
+   |
+LL | fn f() where i32: Foo {
+   |                   ^^^
+
+warning: Trait bound &'static str: Foo does not depend on any type or lifetime parameters
+  --> $DIR/trivial-bounds-inconsistent.rs:39:28
+   |
+LL | fn g() where &'static str: Foo {
+   |                            ^^^
+
+warning: Trait bound str: std::marker::Sized does not depend on any type or lifetime parameters
+  --> $DIR/trivial-bounds-inconsistent.rs:53:37
+   |
+LL | struct TwoStrs(str, str) where str: Sized;
+   |                                     ^^^^^
+
+warning: Trait bound for<'a> Dst<(dyn A + 'a)>: std::marker::Sized does not depend on any type or lifetime parameters
+  --> $DIR/trivial-bounds-inconsistent.rs:55:47
+   |
+LL | fn unsized_local() where for<'a> Dst<A + 'a>: Sized {
+   |                                               ^^^^^
+
+warning: Trait bound str: std::marker::Sized does not depend on any type or lifetime parameters
+  --> $DIR/trivial-bounds-inconsistent.rs:59:35
+   |
+LL | fn return_str() -> str where str: Sized {
+   |                                   ^^^^^
+
+warning: Trait bound std::string::String: std::ops::Neg does not depend on any type or lifetime parameters
+  --> $DIR/trivial-bounds-inconsistent.rs:63:46
+   |
+LL | fn use_op(s: String) -> String where String: ::std::ops::Neg<Output=String> {
+   |                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: Trait bound i32: std::iter::Iterator does not depend on any type or lifetime parameters
+  --> $DIR/trivial-bounds-inconsistent.rs:67:25
+   |
+LL | fn use_for() where i32: Iterator {
+   |                         ^^^^^^^^
+
diff --git a/src/test/ui/trivial-bounds/trivial-bounds-leak-copy.rs b/src/test/ui/trivial-bounds/trivial-bounds-leak-copy.rs
new file mode 100644
index 0000000..cecc0b2
--- /dev/null
+++ b/src/test/ui/trivial-bounds/trivial-bounds-leak-copy.rs
@@ -0,0 +1,12 @@
+// Check that false Copy bounds don't leak
+#![feature(trivial_bounds)]
+
+fn copy_out_string(t: &String) -> String where String: Copy {
+    *t
+}
+
+fn move_out_string(t: &String) -> String {
+    *t //~ ERROR
+}
+
+fn main() {}
diff --git a/src/test/ui/trivial-bounds/trivial-bounds-leak-copy.stderr b/src/test/ui/trivial-bounds/trivial-bounds-leak-copy.stderr
new file mode 100644
index 0000000..68d8129
--- /dev/null
+++ b/src/test/ui/trivial-bounds/trivial-bounds-leak-copy.stderr
@@ -0,0 +1,9 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/trivial-bounds-leak-copy.rs:9:5
+   |
+LL |     *t
+   |     ^^ cannot move out of borrowed content
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/trivial-bounds/trivial-bounds-leak.rs b/src/test/ui/trivial-bounds/trivial-bounds-leak.rs
new file mode 100644
index 0000000..dc4f1c7
--- /dev/null
+++ b/src/test/ui/trivial-bounds/trivial-bounds-leak.rs
@@ -0,0 +1,32 @@
+// Check that false bounds don't leak
+#![feature(trivial_bounds)]
+
+pub trait Foo {
+    fn test(&self);
+}
+
+fn return_str() -> str where str: Sized {
+    *"Sized".to_string().into_boxed_str()
+}
+
+fn cant_return_str() -> str { //~ ERROR
+    *"Sized".to_string().into_boxed_str()
+}
+
+fn my_function() where i32: Foo
+{
+    3i32.test();
+    Foo::test(&4i32);
+    generic_function(5i32);
+}
+
+fn foo() {
+    3i32.test(); //~ ERROR
+    Foo::test(&4i32); //~ ERROR
+    generic_function(5i32); //~ ERROR
+}
+
+fn generic_function<T: Foo>(t: T) {}
+
+fn main() {}
+
diff --git a/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr b/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr
new file mode 100644
index 0000000..3de683e
--- /dev/null
+++ b/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr
@@ -0,0 +1,48 @@
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+  --> $DIR/trivial-bounds-leak.rs:12:25
+   |
+LL | fn cant_return_str() -> str {
+   |                         ^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `str`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: the return type of a function must have a statically known size
+
+error[E0599]: no method named `test` found for type `i32` in the current scope
+  --> $DIR/trivial-bounds-leak.rs:24:10
+   |
+LL |     3i32.test();
+   |          ^^^^
+   |
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following trait defines an item `test`, perhaps you need to implement it:
+           candidate #1: `Foo`
+
+error[E0277]: the trait bound `i32: Foo` is not satisfied
+  --> $DIR/trivial-bounds-leak.rs:25:5
+   |
+LL |     Foo::test(&4i32);
+   |     ^^^^^^^^^ the trait `Foo` is not implemented for `i32`
+   |
+note: required by `Foo::test`
+  --> $DIR/trivial-bounds-leak.rs:5:5
+   |
+LL |     fn test(&self);
+   |     ^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `i32: Foo` is not satisfied
+  --> $DIR/trivial-bounds-leak.rs:26:5
+   |
+LL |     generic_function(5i32);
+   |     ^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `i32`
+   |
+note: required by `generic_function`
+  --> $DIR/trivial-bounds-leak.rs:29:1
+   |
+LL | fn generic_function<T: Foo>(t: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0277, E0599.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/trivial-bounds/trivial-bounds-lint.rs b/src/test/ui/trivial-bounds/trivial-bounds-lint.rs
new file mode 100644
index 0000000..0785783
--- /dev/null
+++ b/src/test/ui/trivial-bounds/trivial-bounds-lint.rs
@@ -0,0 +1,40 @@
+#![feature(trivial_bounds)]
+#![allow(unused)]
+#![deny(trivial_bounds)]
+
+struct A where i32: Copy; //~ ERROR
+
+trait X<T: Copy> {}
+
+trait Y<T>: Copy {}
+
+trait Z {
+    type S: Copy;
+}
+
+// Check only the bound the user writes trigger the lint
+fn trivial_elaboration<T>() where T: X<i32> + Z<S = i32>, i32: Y<T> {} // OK
+
+fn global_param() where i32: X<()> {} //~ ERROR
+
+// Should only error on the trait bound, not the implicit
+// projection bound <i32 as Z>::S == i32.
+fn global_projection() where i32: Z<S = i32> {} //~ ERROR
+
+impl A {
+    fn new() -> A { A }
+}
+
+// Lifetime bounds should be linted as well
+fn global_lifetimes() where i32: 'static, &'static str: 'static {}
+//~^ ERROR
+//~| ERROR
+
+fn local_lifetimes<'a>() where i32: 'a, &'a str: 'a {} // OK
+
+fn global_outlives() where 'static: 'static {} //~ ERROR
+
+// Check that each bound is checked individually
+fn mixed_bounds<T: Copy>() where i32: X<T> + Copy {} //~ ERROR
+
+fn main() {}
diff --git a/src/test/ui/trivial-bounds/trivial-bounds-lint.stderr b/src/test/ui/trivial-bounds/trivial-bounds-lint.stderr
new file mode 100644
index 0000000..2f4b2df
--- /dev/null
+++ b/src/test/ui/trivial-bounds/trivial-bounds-lint.stderr
@@ -0,0 +1,50 @@
+error: Trait bound i32: std::marker::Copy does not depend on any type or lifetime parameters
+  --> $DIR/trivial-bounds-lint.rs:5:21
+   |
+LL | struct A where i32: Copy;
+   |                     ^^^^
+   |
+note: lint level defined here
+  --> $DIR/trivial-bounds-lint.rs:3:9
+   |
+LL | #![deny(trivial_bounds)]
+   |         ^^^^^^^^^^^^^^
+
+error: Trait bound i32: X<()> does not depend on any type or lifetime parameters
+  --> $DIR/trivial-bounds-lint.rs:18:30
+   |
+LL | fn global_param() where i32: X<()> {}
+   |                              ^^^^^
+
+error: Trait bound i32: Z does not depend on any type or lifetime parameters
+  --> $DIR/trivial-bounds-lint.rs:22:35
+   |
+LL | fn global_projection() where i32: Z<S = i32> {}
+   |                                   ^^^^^^^^^^
+
+error: Lifetime bound i32 : 'static does not depend on any type or lifetime parameters
+  --> $DIR/trivial-bounds-lint.rs:29:34
+   |
+LL | fn global_lifetimes() where i32: 'static, &'static str: 'static {}
+   |                                  ^^^^^^^
+
+error: Lifetime bound &'static str : 'static does not depend on any type or lifetime parameters
+  --> $DIR/trivial-bounds-lint.rs:29:57
+   |
+LL | fn global_lifetimes() where i32: 'static, &'static str: 'static {}
+   |                                                         ^^^^^^^
+
+error: Lifetime bound 'static : 'static does not depend on any type or lifetime parameters
+  --> $DIR/trivial-bounds-lint.rs:35:37
+   |
+LL | fn global_outlives() where 'static: 'static {}
+   |                                     ^^^^^^^
+
+error: Trait bound i32: std::marker::Copy does not depend on any type or lifetime parameters
+  --> $DIR/trivial-bounds-lint.rs:38:46
+   |
+LL | fn mixed_bounds<T: Copy>() where i32: X<T> + Copy {}
+   |                                              ^^^^
+
+error: aborting due to 7 previous errors
+
diff --git a/src/test/ui/trivial-bounds/trivial-bounds-object.rs b/src/test/ui/trivial-bounds/trivial-bounds-object.rs
new file mode 100644
index 0000000..f5feeea
--- /dev/null
+++ b/src/test/ui/trivial-bounds/trivial-bounds-object.rs
@@ -0,0 +1,18 @@
+// run-pass
+// Check that the object bound dyn A + 'a: A is preferred over the
+// where clause bound dyn A + 'static: A.
+
+#![allow(unused)]
+
+trait A {
+    fn test(&self);
+}
+
+fn foo(x: &dyn A)
+where
+    dyn A + 'static: A, // Using this bound would lead to a lifetime error.
+{
+    x.test();
+}
+
+fn main () {}
diff --git a/src/test/ui/trivial_casts.rs b/src/test/ui/trivial_casts.rs
new file mode 100644
index 0000000..c1f5441
--- /dev/null
+++ b/src/test/ui/trivial_casts.rs
@@ -0,0 +1,85 @@
+// Test the trivial_casts and trivial_numeric_casts lints. For each error we also
+// check that the cast can be done using just coercion.
+
+#![deny(trivial_casts, trivial_numeric_casts)]
+
+trait Foo {
+    fn foo(&self) {}
+}
+
+pub struct Bar;
+
+impl Foo for Bar {}
+
+pub fn main() {
+    // Numeric
+    let _ = 42_i32 as i32; //~ ERROR trivial numeric cast: `i32` as `i32`
+    let _: i32 = 42_i32;
+
+    let _ = 42_u8 as u8; //~ ERROR trivial numeric cast: `u8` as `u8`
+    let _: u8 = 42_u8;
+
+    // & to * pointers
+    let x: &u32 = &42;
+    let _ = x as *const u32; //~ERROR trivial cast: `&u32` as `*const u32`
+    let _: *const u32 = x;
+
+    let x: &mut u32 = &mut 42;
+    let _ = x as *mut u32; //~ERROR trivial cast: `&mut u32` as `*mut u32`
+    let _: *mut u32 = x;
+
+    // unsize array
+    let x: &[u32; 3] = &[42, 43, 44];
+    let _ = x as &[u32]; //~ERROR trivial cast: `&[u32; 3]` as `&[u32]`
+    let _ = x as *const [u32]; //~ERROR trivial cast: `&[u32; 3]` as `*const [u32]`
+    let _: &[u32] = x;
+    let _: *const [u32] = x;
+
+    let x: &mut [u32; 3] = &mut [42, 43, 44];
+    let _ = x as &mut [u32]; //~ERROR trivial cast: `&mut [u32; 3]` as `&mut [u32]`
+    let _ = x as *mut [u32]; //~ERROR trivial cast: `&mut [u32; 3]` as `*mut [u32]`
+    let _: &mut [u32] = x;
+    let _: *mut [u32] = x;
+
+    let x: Box<[u32; 3]> = Box::new([42, 43, 44]);
+    let _ = x as Box<[u32]>;
+    //~^ ERROR trivial cast: `std::boxed::Box<[u32; 3]>` as `std::boxed::Box<[u32]>`
+    let x: Box<[u32; 3]> = Box::new([42, 43, 44]);
+    let _: Box<[u32]> = x;
+
+    // unsize trait
+    let x: &Bar = &Bar;
+    let _ = x as &Foo; //~ERROR trivial cast: `&Bar` as `&dyn Foo`
+    let _ = x as *const Foo; //~ERROR trivial cast: `&Bar` as `*const dyn Foo`
+    let _: &Foo = x;
+    let _: *const Foo = x;
+
+    let x: &mut Bar = &mut Bar;
+    let _ = x as &mut Foo; //~ERROR trivial cast: `&mut Bar` as `&mut dyn Foo`
+    let _ = x as *mut Foo; //~ERROR trivial cast: `&mut Bar` as `*mut dyn Foo`
+    let _: &mut Foo = x;
+    let _: *mut Foo = x;
+
+    let x: Box<Bar> = Box::new(Bar);
+    let _ = x as Box<Foo>; //~ERROR `std::boxed::Box<Bar>` as `std::boxed::Box<dyn Foo>`
+    let x: Box<Bar> = Box::new(Bar);
+    let _: Box<Foo> = x;
+
+    // functions
+    fn baz(_x: i32) {}
+    let _ = &baz as &Fn(i32); //~ERROR `&fn(i32) {main::baz}` as `&dyn std::ops::Fn(i32)`
+    let _: &Fn(i32) = &baz;
+    let x = |_x: i32| {};
+    let _ = &x as &Fn(i32); //~ERROR trivial cast
+    let _: &Fn(i32) = &x;
+}
+
+// subtyping
+pub fn test_subtyping<'a, 'b: 'a>(a: &'a Bar, b: &'b Bar) {
+    let _ = a as &'a Bar; //~ERROR trivial cast
+    let _: &'a Bar = a;
+    let _ = b as &'a Bar; //~ERROR trivial cast
+    let _: &'a Bar = b;
+    let _ = b as &'b Bar; //~ERROR trivial cast
+    let _: &'b Bar = b;
+}
diff --git a/src/test/ui/trivial_casts.stderr b/src/test/ui/trivial_casts.stderr
new file mode 100644
index 0000000..524eb7f
--- /dev/null
+++ b/src/test/ui/trivial_casts.stderr
@@ -0,0 +1,164 @@
+error: trivial numeric cast: `i32` as `i32`
+  --> $DIR/trivial_casts.rs:16:13
+   |
+LL |     let _ = 42_i32 as i32;
+   |             ^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/trivial_casts.rs:4:24
+   |
+LL | #![deny(trivial_casts, trivial_numeric_casts)]
+   |                        ^^^^^^^^^^^^^^^^^^^^^
+   = help: cast can be replaced by coercion; this might require a temporary variable
+
+error: trivial numeric cast: `u8` as `u8`
+  --> $DIR/trivial_casts.rs:19:13
+   |
+LL |     let _ = 42_u8 as u8;
+   |             ^^^^^^^^^^^
+   |
+   = help: cast can be replaced by coercion; this might require a temporary variable
+
+error: trivial cast: `&u32` as `*const u32`
+  --> $DIR/trivial_casts.rs:24:13
+   |
+LL |     let _ = x as *const u32;
+   |             ^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/trivial_casts.rs:4:9
+   |
+LL | #![deny(trivial_casts, trivial_numeric_casts)]
+   |         ^^^^^^^^^^^^^
+   = help: cast can be replaced by coercion; this might require a temporary variable
+
+error: trivial cast: `&mut u32` as `*mut u32`
+  --> $DIR/trivial_casts.rs:28:13
+   |
+LL |     let _ = x as *mut u32;
+   |             ^^^^^^^^^^^^^
+   |
+   = help: cast can be replaced by coercion; this might require a temporary variable
+
+error: trivial cast: `&[u32; 3]` as `&[u32]`
+  --> $DIR/trivial_casts.rs:33:13
+   |
+LL |     let _ = x as &[u32];
+   |             ^^^^^^^^^^^
+   |
+   = help: cast can be replaced by coercion; this might require a temporary variable
+
+error: trivial cast: `&[u32; 3]` as `*const [u32]`
+  --> $DIR/trivial_casts.rs:34:13
+   |
+LL |     let _ = x as *const [u32];
+   |             ^^^^^^^^^^^^^^^^^
+   |
+   = help: cast can be replaced by coercion; this might require a temporary variable
+
+error: trivial cast: `&mut [u32; 3]` as `&mut [u32]`
+  --> $DIR/trivial_casts.rs:39:13
+   |
+LL |     let _ = x as &mut [u32];
+   |             ^^^^^^^^^^^^^^^
+   |
+   = help: cast can be replaced by coercion; this might require a temporary variable
+
+error: trivial cast: `&mut [u32; 3]` as `*mut [u32]`
+  --> $DIR/trivial_casts.rs:40:13
+   |
+LL |     let _ = x as *mut [u32];
+   |             ^^^^^^^^^^^^^^^
+   |
+   = help: cast can be replaced by coercion; this might require a temporary variable
+
+error: trivial cast: `std::boxed::Box<[u32; 3]>` as `std::boxed::Box<[u32]>`
+  --> $DIR/trivial_casts.rs:45:13
+   |
+LL |     let _ = x as Box<[u32]>;
+   |             ^^^^^^^^^^^^^^^
+   |
+   = help: cast can be replaced by coercion; this might require a temporary variable
+
+error: trivial cast: `&Bar` as `&dyn Foo`
+  --> $DIR/trivial_casts.rs:52:13
+   |
+LL |     let _ = x as &Foo;
+   |             ^^^^^^^^^
+   |
+   = help: cast can be replaced by coercion; this might require a temporary variable
+
+error: trivial cast: `&Bar` as `*const dyn Foo`
+  --> $DIR/trivial_casts.rs:53:13
+   |
+LL |     let _ = x as *const Foo;
+   |             ^^^^^^^^^^^^^^^
+   |
+   = help: cast can be replaced by coercion; this might require a temporary variable
+
+error: trivial cast: `&mut Bar` as `&mut dyn Foo`
+  --> $DIR/trivial_casts.rs:58:13
+   |
+LL |     let _ = x as &mut Foo;
+   |             ^^^^^^^^^^^^^
+   |
+   = help: cast can be replaced by coercion; this might require a temporary variable
+
+error: trivial cast: `&mut Bar` as `*mut dyn Foo`
+  --> $DIR/trivial_casts.rs:59:13
+   |
+LL |     let _ = x as *mut Foo;
+   |             ^^^^^^^^^^^^^
+   |
+   = help: cast can be replaced by coercion; this might require a temporary variable
+
+error: trivial cast: `std::boxed::Box<Bar>` as `std::boxed::Box<dyn Foo>`
+  --> $DIR/trivial_casts.rs:64:13
+   |
+LL |     let _ = x as Box<Foo>;
+   |             ^^^^^^^^^^^^^
+   |
+   = help: cast can be replaced by coercion; this might require a temporary variable
+
+error: trivial cast: `&fn(i32) {main::baz}` as `&dyn std::ops::Fn(i32)`
+  --> $DIR/trivial_casts.rs:70:13
+   |
+LL |     let _ = &baz as &Fn(i32);
+   |             ^^^^^^^^^^^^^^^^
+   |
+   = help: cast can be replaced by coercion; this might require a temporary variable
+
+error: trivial cast: `&[closure@$DIR/trivial_casts.rs:72:13: 72:25]` as `&dyn std::ops::Fn(i32)`
+  --> $DIR/trivial_casts.rs:73:13
+   |
+LL |     let _ = &x as &Fn(i32);
+   |             ^^^^^^^^^^^^^^
+   |
+   = help: cast can be replaced by coercion; this might require a temporary variable
+
+error: trivial cast: `&'a Bar` as `&'a Bar`
+  --> $DIR/trivial_casts.rs:79:13
+   |
+LL |     let _ = a as &'a Bar;
+   |             ^^^^^^^^^^^^
+   |
+   = help: cast can be replaced by coercion; this might require a temporary variable
+
+error: trivial cast: `&'b Bar` as `&'a Bar`
+  --> $DIR/trivial_casts.rs:81:13
+   |
+LL |     let _ = b as &'a Bar;
+   |             ^^^^^^^^^^^^
+   |
+   = help: cast can be replaced by coercion; this might require a temporary variable
+
+error: trivial cast: `&'b Bar` as `&'b Bar`
+  --> $DIR/trivial_casts.rs:83:13
+   |
+LL |     let _ = b as &'b Bar;
+   |             ^^^^^^^^^^^^
+   |
+   = help: cast can be replaced by coercion; this might require a temporary variable
+
+error: aborting due to 19 previous errors
+
diff --git a/src/test/ui/try-block/try-block-bad-lifetime.rs b/src/test/ui/try-block/try-block-bad-lifetime.rs
new file mode 100644
index 0000000..872604f
--- /dev/null
+++ b/src/test/ui/try-block/try-block-bad-lifetime.rs
@@ -0,0 +1,38 @@
+// compile-flags: --edition 2018
+
+#![feature(try_blocks)]
+
+#![inline(never)]
+fn do_something_with<T>(_x: T) {}
+
+// This test checks that borrows made and returned inside try blocks are properly constrained
+pub fn main() {
+    {
+        // Test that borrows returned from a try block must be valid for the lifetime of the
+        // result variable
+        let result: Result<(), &str> = try {
+            let my_string = String::from("");
+            let my_str: & str = & my_string;
+            //~^ ERROR `my_string` does not live long enough
+            Err(my_str) ?;
+            Err("") ?;
+        };
+        do_something_with(result);
+    }
+
+    {
+        // Test that borrows returned from try blocks freeze their referent
+        let mut i = 5;
+        let k = &mut i;
+        let mut j: Result<(), &mut i32> = try {
+            Err(k) ?;
+            i = 10; //~ ERROR cannot assign to `i` because it is borrowed
+        };
+        ::std::mem::drop(k); //~ ERROR use of moved value: `k`
+        i = 40; //~ ERROR cannot assign to `i` because it is borrowed
+
+        let i_ptr = if let Err(i_ptr) = j { i_ptr } else { panic ! ("") };
+        *i_ptr = 50;
+    }
+}
+
diff --git a/src/test/ui/try-block/try-block-bad-lifetime.stderr b/src/test/ui/try-block/try-block-bad-lifetime.stderr
new file mode 100644
index 0000000..a236cb9
--- /dev/null
+++ b/src/test/ui/try-block/try-block-bad-lifetime.stderr
@@ -0,0 +1,52 @@
+error[E0597]: `my_string` does not live long enough
+  --> $DIR/try-block-bad-lifetime.rs:15:33
+   |
+LL |         let result: Result<(), &str> = try {
+   |             ------ borrow later stored here
+LL |             let my_string = String::from("");
+LL |             let my_str: & str = & my_string;
+   |                                 ^^^^^^^^^^^ borrowed value does not live long enough
+...
+LL |         };
+   |         - `my_string` dropped here while still borrowed
+
+error[E0506]: cannot assign to `i` because it is borrowed
+  --> $DIR/try-block-bad-lifetime.rs:29:13
+   |
+LL |         let k = &mut i;
+   |                 ------ borrow of `i` occurs here
+...
+LL |             i = 10;
+   |             ^^^^^^ assignment to borrowed `i` occurs here
+LL |         };
+LL |         ::std::mem::drop(k);
+   |                          - borrow later used here
+
+error[E0382]: use of moved value: `k`
+  --> $DIR/try-block-bad-lifetime.rs:31:26
+   |
+LL |         let k = &mut i;
+   |             - move occurs because `k` has type `&mut i32`, which does not implement the `Copy` trait
+LL |         let mut j: Result<(), &mut i32> = try {
+LL |             Err(k) ?;
+   |                 - value moved here
+...
+LL |         ::std::mem::drop(k);
+   |                          ^ value used here after move
+
+error[E0506]: cannot assign to `i` because it is borrowed
+  --> $DIR/try-block-bad-lifetime.rs:32:9
+   |
+LL |         let k = &mut i;
+   |                 ------ borrow of `i` occurs here
+...
+LL |         i = 40;
+   |         ^^^^^^ assignment to borrowed `i` occurs here
+LL | 
+LL |         let i_ptr = if let Err(i_ptr) = j { i_ptr } else { panic ! ("") };
+   |                                         - borrow later used here
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0382, E0506, E0597.
+For more information about an error, try `rustc --explain E0382`.
diff --git a/src/test/ui/try-block/try-block-bad-type.rs b/src/test/ui/try-block/try-block-bad-type.rs
new file mode 100644
index 0000000..0e297dd
--- /dev/null
+++ b/src/test/ui/try-block/try-block-bad-type.rs
@@ -0,0 +1,20 @@
+// compile-flags: --edition 2018
+
+#![feature(try_blocks)]
+
+pub fn main() {
+    let res: Result<u32, i32> = try {
+        Err("")?; //~ ERROR the trait bound `i32: std::convert::From<&str>` is not satisfied
+        5
+    };
+
+    let res: Result<i32, i32> = try {
+        "" //~ ERROR type mismatch
+    };
+
+    let res: Result<i32, i32> = try { }; //~ ERROR type mismatch
+
+    let res: () = try { }; //~ the trait bound `(): std::ops::Try` is not satisfied
+
+    let res: i32 = try { 5 }; //~ ERROR the trait bound `i32: std::ops::Try` is not satisfied
+}
diff --git a/src/test/ui/try-block/try-block-bad-type.stderr b/src/test/ui/try-block/try-block-bad-type.stderr
new file mode 100644
index 0000000..07e7149
--- /dev/null
+++ b/src/test/ui/try-block/try-block-bad-type.stderr
@@ -0,0 +1,52 @@
+error[E0277]: the trait bound `i32: std::convert::From<&str>` is not satisfied
+  --> $DIR/try-block-bad-type.rs:7:9
+   |
+LL |         Err("")?;
+   |         ^^^^^^^^ the trait `std::convert::From<&str>` is not implemented for `i32`
+   |
+   = help: the following implementations were found:
+             <i32 as std::convert::From<bool>>
+             <i32 as std::convert::From<i16>>
+             <i32 as std::convert::From<i8>>
+             <i32 as std::convert::From<std::num::NonZeroI32>>
+           and 2 others
+   = note: required by `std::convert::From::from`
+
+error[E0271]: type mismatch resolving `<std::result::Result<i32, i32> as std::ops::Try>::Ok == &str`
+  --> $DIR/try-block-bad-type.rs:12:9
+   |
+LL |         ""
+   |         ^^ expected i32, found &str
+   |
+   = note: expected type `i32`
+              found type `&str`
+
+error[E0271]: type mismatch resolving `<std::result::Result<i32, i32> as std::ops::Try>::Ok == ()`
+  --> $DIR/try-block-bad-type.rs:15:39
+   |
+LL |     let res: Result<i32, i32> = try { };
+   |                                       ^ expected i32, found ()
+   |
+   = note: expected type `i32`
+              found type `()`
+
+error[E0277]: the trait bound `(): std::ops::Try` is not satisfied
+  --> $DIR/try-block-bad-type.rs:17:23
+   |
+LL |     let res: () = try { };
+   |                       ^^^ the trait `std::ops::Try` is not implemented for `()`
+   |
+   = note: required by `std::ops::Try::from_ok`
+
+error[E0277]: the trait bound `i32: std::ops::Try` is not satisfied
+  --> $DIR/try-block-bad-type.rs:19:24
+   |
+LL |     let res: i32 = try { 5 };
+   |                        ^^^^^ the trait `std::ops::Try` is not implemented for `i32`
+   |
+   = note: required by `std::ops::Try::from_ok`
+
+error: aborting due to 5 previous errors
+
+Some errors occurred: E0271, E0277.
+For more information about an error, try `rustc --explain E0271`.
diff --git a/src/test/ui/try-block/try-block-in-edition2015.rs b/src/test/ui/try-block/try-block-in-edition2015.rs
new file mode 100644
index 0000000..0096429
--- /dev/null
+++ b/src/test/ui/try-block/try-block-in-edition2015.rs
@@ -0,0 +1,10 @@
+// compile-flags: --edition 2015
+
+pub fn main() {
+    let try_result: Option<_> = try {
+    //~^ ERROR expected struct, variant or union type, found macro `try`
+        let x = 5; //~ ERROR expected identifier, found keyword
+        x
+    };
+    assert_eq!(try_result, Some(5));
+}
diff --git a/src/test/ui/try-block/try-block-in-edition2015.stderr b/src/test/ui/try-block/try-block-in-edition2015.stderr
new file mode 100644
index 0000000..c94e431
--- /dev/null
+++ b/src/test/ui/try-block/try-block-in-edition2015.stderr
@@ -0,0 +1,24 @@
+error: expected identifier, found keyword `let`
+  --> $DIR/try-block-in-edition2015.rs:6:9
+   |
+LL |     let try_result: Option<_> = try {
+   |                                 --- while parsing this struct
+LL |
+LL |         let x = 5;
+   |         ^^^ expected identifier, found keyword
+help: you can escape reserved keywords to use them as identifiers
+   |
+LL |         r#let x = 5;
+   |         ^^^^^
+
+error[E0574]: expected struct, variant or union type, found macro `try`
+  --> $DIR/try-block-in-edition2015.rs:4:33
+   |
+LL |     let try_result: Option<_> = try {
+   |                                 ^^^ help: use `!` to invoke the macro: `try!`
+   |
+   = note: if you want the `try` keyword, you need to be in the 2018 edition
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0574`.
diff --git a/src/test/ui/try-block/try-block-in-match.rs b/src/test/ui/try-block/try-block-in-match.rs
new file mode 100644
index 0000000..bce0d03
--- /dev/null
+++ b/src/test/ui/try-block/try-block-in-match.rs
@@ -0,0 +1,7 @@
+// compile-flags: --edition 2018
+
+#![feature(try_blocks)]
+
+fn main() {
+    match try { false } { _ => {} } //~ ERROR expected expression, found reserved keyword `try`
+}
diff --git a/src/test/ui/try-block/try-block-in-match.stderr b/src/test/ui/try-block/try-block-in-match.stderr
new file mode 100644
index 0000000..936e0fe
--- /dev/null
+++ b/src/test/ui/try-block/try-block-in-match.stderr
@@ -0,0 +1,10 @@
+error: expected expression, found reserved keyword `try`
+  --> $DIR/try-block-in-match.rs:6:11
+   |
+LL |     match try { false } { _ => {} }
+   |     ----- ^^^ expected expression
+   |     |
+   |     while parsing this match expression
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/try-block/try-block-in-while.rs b/src/test/ui/try-block/try-block-in-while.rs
new file mode 100644
index 0000000..98af796
--- /dev/null
+++ b/src/test/ui/try-block/try-block-in-while.rs
@@ -0,0 +1,7 @@
+// compile-flags: --edition 2018
+
+#![feature(try_blocks)]
+
+fn main() {
+    while try { false } {} //~ ERROR expected expression, found reserved keyword `try`
+}
diff --git a/src/test/ui/try-block/try-block-in-while.stderr b/src/test/ui/try-block/try-block-in-while.stderr
new file mode 100644
index 0000000..026df15
--- /dev/null
+++ b/src/test/ui/try-block/try-block-in-while.stderr
@@ -0,0 +1,8 @@
+error: expected expression, found reserved keyword `try`
+  --> $DIR/try-block-in-while.rs:6:11
+   |
+LL |     while try { false } {}
+   |           ^^^ expected expression
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/try-block/try-block-maybe-bad-lifetime.rs b/src/test/ui/try-block/try-block-maybe-bad-lifetime.rs
new file mode 100644
index 0000000..113d089
--- /dev/null
+++ b/src/test/ui/try-block/try-block-maybe-bad-lifetime.rs
@@ -0,0 +1,45 @@
+// compile-flags: --edition 2018
+
+#![feature(try_blocks)]
+
+#![inline(never)]
+fn do_something_with<T>(_x: T) {}
+
+// This test checks that borrows made and returned inside try blocks are properly constrained
+pub fn main() {
+    {
+        // Test that a borrow which *might* be returned still freezes its referent
+        let mut i = 222;
+        let x: Result<&i32, ()> = try {
+            Err(())?;
+            &i
+        };
+        i = 0; //~ ERROR cannot assign to `i` because it is borrowed
+        let _ = i;
+        do_something_with(x);
+    }
+
+    {
+        let x = String::new();
+        let _y: Result<(), ()> = try {
+            Err(())?;
+            ::std::mem::drop(x);
+        };
+        println!("{}", x); //~ ERROR borrow of moved value: `x`
+    }
+
+    {
+        // Test that a borrow which *might* be assigned to an outer variable still freezes
+        // its referent
+        let mut i = 222;
+        let mut j = &-1;
+        let _x: Result<(), ()> = try {
+            Err(())?;
+            j = &i;
+        };
+        i = 0; //~ ERROR cannot assign to `i` because it is borrowed
+        let _ = i;
+        do_something_with(j);
+    }
+}
+
diff --git a/src/test/ui/try-block/try-block-maybe-bad-lifetime.stderr b/src/test/ui/try-block/try-block-maybe-bad-lifetime.stderr
new file mode 100644
index 0000000..665a626
--- /dev/null
+++ b/src/test/ui/try-block/try-block-maybe-bad-lifetime.stderr
@@ -0,0 +1,40 @@
+error[E0506]: cannot assign to `i` because it is borrowed
+  --> $DIR/try-block-maybe-bad-lifetime.rs:17:9
+   |
+LL |             &i
+   |             -- borrow of `i` occurs here
+LL |         };
+LL |         i = 0;
+   |         ^^^^^ assignment to borrowed `i` occurs here
+LL |         let _ = i;
+LL |         do_something_with(x);
+   |                           - borrow later used here
+
+error[E0382]: borrow of moved value: `x`
+  --> $DIR/try-block-maybe-bad-lifetime.rs:28:24
+   |
+LL |         let x = String::new();
+   |             - move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
+...
+LL |             ::std::mem::drop(x);
+   |                              - value moved here
+LL |         };
+LL |         println!("{}", x);
+   |                        ^ value borrowed here after move
+
+error[E0506]: cannot assign to `i` because it is borrowed
+  --> $DIR/try-block-maybe-bad-lifetime.rs:40:9
+   |
+LL |             j = &i;
+   |                 -- borrow of `i` occurs here
+LL |         };
+LL |         i = 0;
+   |         ^^^^^ assignment to borrowed `i` occurs here
+LL |         let _ = i;
+LL |         do_something_with(j);
+   |                           - borrow later used here
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0382, E0506.
+For more information about an error, try `rustc --explain E0382`.
diff --git a/src/test/ui/try-block/try-block-opt-init.rs b/src/test/ui/try-block/try-block-opt-init.rs
new file mode 100644
index 0000000..ef55922
--- /dev/null
+++ b/src/test/ui/try-block/try-block-opt-init.rs
@@ -0,0 +1,17 @@
+// compile-flags: --edition 2018
+
+#![feature(try_blocks)]
+
+fn use_val<T: Sized>(_x: T) {}
+
+pub fn main() {
+    let cfg_res;
+    let _: Result<(), ()> = try {
+        Err(())?;
+        cfg_res = 5;
+        Ok::<(), ()>(())?;
+        use_val(cfg_res);
+    };
+    assert_eq!(cfg_res, 5); //~ ERROR borrow of possibly uninitialized variable: `cfg_res`
+}
+
diff --git a/src/test/ui/try-block/try-block-opt-init.stderr b/src/test/ui/try-block/try-block-opt-init.stderr
new file mode 100644
index 0000000..ec0128d
--- /dev/null
+++ b/src/test/ui/try-block/try-block-opt-init.stderr
@@ -0,0 +1,11 @@
+error[E0381]: borrow of possibly uninitialized variable: `cfg_res`
+  --> $DIR/try-block-opt-init.rs:15:5
+   |
+LL |     assert_eq!(cfg_res, 5);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ use of possibly uninitialized `cfg_res`
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/try-block/try-block-type-error.rs b/src/test/ui/try-block/try-block-type-error.rs
new file mode 100644
index 0000000..fe1993a
--- /dev/null
+++ b/src/test/ui/try-block/try-block-type-error.rs
@@ -0,0 +1,18 @@
+// compile-flags: --edition 2018
+
+#![feature(try_blocks)]
+
+fn foo() -> Option<()> { Some(()) }
+
+fn main() {
+    let _: Option<f32> = try {
+        foo()?;
+        42
+        //~^ ERROR type mismatch
+    };
+
+    let _: Option<i32> = try {
+        foo()?;
+    };
+    //~^ ERROR type mismatch
+}
diff --git a/src/test/ui/try-block/try-block-type-error.stderr b/src/test/ui/try-block/try-block-type-error.stderr
new file mode 100644
index 0000000..0cbd737
--- /dev/null
+++ b/src/test/ui/try-block/try-block-type-error.stderr
@@ -0,0 +1,24 @@
+error[E0271]: type mismatch resolving `<std::option::Option<f32> as std::ops::Try>::Ok == {integer}`
+  --> $DIR/try-block-type-error.rs:10:9
+   |
+LL |         42
+   |         ^^
+   |         |
+   |         expected f32, found integer
+   |         help: use a float literal: `42.0`
+   |
+   = note: expected type `f32`
+              found type `{integer}`
+
+error[E0271]: type mismatch resolving `<std::option::Option<i32> as std::ops::Try>::Ok == ()`
+  --> $DIR/try-block-type-error.rs:16:5
+   |
+LL |     };
+   |     ^ expected i32, found ()
+   |
+   = note: expected type `i32`
+              found type `()`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/try-on-option.rs b/src/test/ui/try-on-option.rs
new file mode 100644
index 0000000..9c8e8b3
--- /dev/null
+++ b/src/test/ui/try-on-option.rs
@@ -0,0 +1,15 @@
+#![feature(try_trait)]
+
+fn main() {}
+
+fn foo() -> Result<u32, ()> {
+    let x: Option<u32> = None;
+    x?; //~ the trait bound
+    Ok(22)
+}
+
+fn bar() -> u32 {
+    let x: Option<u32> = None;
+    x?; //~ the `?` operator
+    22
+}
diff --git a/src/test/ui/try-on-option.stderr b/src/test/ui/try-on-option.stderr
new file mode 100644
index 0000000..7dfa1a7
--- /dev/null
+++ b/src/test/ui/try-on-option.stderr
@@ -0,0 +1,20 @@
+error[E0277]: the trait bound `(): std::convert::From<std::option::NoneError>` is not satisfied
+  --> $DIR/try-on-option.rs:7:5
+   |
+LL |     x?;
+   |     ^^ the trait `std::convert::From<std::option::NoneError>` is not implemented for `()`
+   |
+   = note: required by `std::convert::From::from`
+
+error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `std::ops::Try`)
+  --> $DIR/try-on-option.rs:13:5
+   |
+LL |     x?;
+   |     ^^ cannot use the `?` operator in a function that returns `u32`
+   |
+   = help: the trait `std::ops::Try` is not implemented for `u32`
+   = note: required by `std::ops::Try::from_error`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/try-operator-on-main.rs b/src/test/ui/try-operator-on-main.rs
new file mode 100644
index 0000000..3b48194
--- /dev/null
+++ b/src/test/ui/try-operator-on-main.rs
@@ -0,0 +1,25 @@
+// ignore-cloudabi no std::fs support
+
+#![feature(try_trait)]
+
+use std::ops::Try;
+
+fn main() {
+    // error for a `Try` type on a non-`Try` fn
+    std::fs::File::open("foo")?; //~ ERROR the `?` operator can only
+
+    // a non-`Try` type on a non-`Try` fn
+    ()?; //~ ERROR the `?` operator can only
+
+    // an unrelated use of `Try`
+    try_trait_generic::<()>(); //~ ERROR the trait bound
+}
+
+
+
+fn try_trait_generic<T: Try>() -> T {
+    // and a non-`Try` object on a `Try` fn.
+    ()?; //~ ERROR the `?` operator can only
+
+    loop {}
+}
diff --git a/src/test/ui/try-operator-on-main.stderr b/src/test/ui/try-operator-on-main.stderr
new file mode 100644
index 0000000..9f120e0
--- /dev/null
+++ b/src/test/ui/try-operator-on-main.stderr
@@ -0,0 +1,42 @@
+error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `std::ops::Try`)
+  --> $DIR/try-operator-on-main.rs:9:5
+   |
+LL |     std::fs::File::open("foo")?;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot use the `?` operator in a function that returns `()`
+   |
+   = help: the trait `std::ops::Try` is not implemented for `()`
+   = note: required by `std::ops::Try::from_error`
+
+error[E0277]: the `?` operator can only be applied to values that implement `std::ops::Try`
+  --> $DIR/try-operator-on-main.rs:12:5
+   |
+LL |     ()?;
+   |     ^^^ the `?` operator cannot be applied to type `()`
+   |
+   = help: the trait `std::ops::Try` is not implemented for `()`
+   = note: required by `std::ops::Try::into_result`
+
+error[E0277]: the trait bound `(): std::ops::Try` is not satisfied
+  --> $DIR/try-operator-on-main.rs:15:5
+   |
+LL |     try_trait_generic::<()>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Try` is not implemented for `()`
+   |
+note: required by `try_trait_generic`
+  --> $DIR/try-operator-on-main.rs:20:1
+   |
+LL | fn try_trait_generic<T: Try>() -> T {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the `?` operator can only be applied to values that implement `std::ops::Try`
+  --> $DIR/try-operator-on-main.rs:22:5
+   |
+LL |     ()?;
+   |     ^^^ the `?` operator cannot be applied to type `()`
+   |
+   = help: the trait `std::ops::Try` is not implemented for `()`
+   = note: required by `std::ops::Try::into_result`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/try-poll.rs b/src/test/ui/try-poll.rs
new file mode 100644
index 0000000..3d7115c
--- /dev/null
+++ b/src/test/ui/try-poll.rs
@@ -0,0 +1,51 @@
+// compile-pass
+
+#![allow(dead_code, unused)]
+#![feature(futures_api)]
+
+use std::task::Poll;
+
+struct K;
+struct E;
+
+fn as_result() -> Result<(), E> {
+    // From Result
+    let K = Ok::<K, E>(K)?;
+
+    // From Poll<Result>
+    let _: Poll<K> = Poll::Ready::<Result<K, E>>(Ok(K))?;
+
+    // From Poll<Option<Result>>
+    let _: Poll<Option<K>> = Poll::Ready::<Option<Result<K, E>>>(None)?;
+
+    Ok(())
+}
+
+fn as_poll_result() -> Poll<Result<(), E>> {
+    // From Result
+    let K = Ok::<K, E>(K)?;
+
+    // From Poll<Result>
+    let _: Poll<K> = Poll::Ready::<Result<K, E>>(Ok(K))?;
+
+    // From Poll<Option<Result>>
+    let _: Poll<Option<K>> = Poll::Ready::<Option<Result<K, E>>>(None)?;
+
+    Poll::Ready(Ok(()))
+}
+
+fn as_poll_option_result() -> Poll<Option<Result<(), E>>> {
+    // From Result
+    let K = Ok::<K, E>(K)?;
+
+    // From Poll<Result>
+    let _: Poll<K> = Poll::Ready::<Result<K, E>>(Ok(K))?;
+
+    // From Poll<Option<Result>>
+    let _: Poll<Option<K>> = Poll::Ready::<Option<Result<K, E>>>(None)?;
+
+    Poll::Ready(Some(Ok(())))
+}
+
+fn main() {
+}
diff --git a/src/test/ui/tuple/tuple-arity-mismatch.rs b/src/test/ui/tuple/tuple-arity-mismatch.rs
new file mode 100644
index 0000000..1c8b881
--- /dev/null
+++ b/src/test/ui/tuple/tuple-arity-mismatch.rs
@@ -0,0 +1,17 @@
+// Issue #6155
+
+fn first((value, _): (isize, f64)) -> isize { value }
+
+fn main() {
+    let y = first ((1,2.0,3));
+    //~^ ERROR mismatched types
+    //~| expected type `(isize, f64)`
+    //~| found type `(isize, f64, {integer})`
+    //~| expected a tuple with 2 elements, found one with 3 elements
+
+    let y = first ((1,));
+    //~^ ERROR mismatched types
+    //~| expected type `(isize, f64)`
+    //~| found type `(isize,)`
+    //~| expected a tuple with 2 elements, found one with 1 elements
+}
diff --git a/src/test/ui/tuple/tuple-arity-mismatch.stderr b/src/test/ui/tuple/tuple-arity-mismatch.stderr
new file mode 100644
index 0000000..650f4c5
--- /dev/null
+++ b/src/test/ui/tuple/tuple-arity-mismatch.stderr
@@ -0,0 +1,21 @@
+error[E0308]: mismatched types
+  --> $DIR/tuple-arity-mismatch.rs:6:20
+   |
+LL |     let y = first ((1,2.0,3));
+   |                    ^^^^^^^^^ expected a tuple with 2 elements, found one with 3 elements
+   |
+   = note: expected type `(isize, f64)`
+              found type `(isize, f64, {integer})`
+
+error[E0308]: mismatched types
+  --> $DIR/tuple-arity-mismatch.rs:12:20
+   |
+LL |     let y = first ((1,));
+   |                    ^^^^ expected a tuple with 2 elements, found one with 1 elements
+   |
+   = note: expected type `(isize, f64)`
+              found type `(isize,)`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/tuple/tuple-float-index.fixed b/src/test/ui/tuple/tuple-float-index.fixed
new file mode 100644
index 0000000..cd1a85a
--- /dev/null
+++ b/src/test/ui/tuple/tuple-float-index.fixed
@@ -0,0 +1,5 @@
+// run-rustfix
+
+fn main () {
+    ((1, (2, 3)).1).1; //~ ERROR unexpected token: `1.1`
+}
diff --git a/src/test/ui/tuple/tuple-float-index.rs b/src/test/ui/tuple/tuple-float-index.rs
new file mode 100644
index 0000000..1faabac
--- /dev/null
+++ b/src/test/ui/tuple/tuple-float-index.rs
@@ -0,0 +1,5 @@
+// run-rustfix
+
+fn main () {
+    (1, (2, 3)).1.1; //~ ERROR unexpected token: `1.1`
+}
diff --git a/src/test/ui/tuple/tuple-float-index.stderr b/src/test/ui/tuple/tuple-float-index.stderr
new file mode 100644
index 0000000..a0ea0e0
--- /dev/null
+++ b/src/test/ui/tuple/tuple-float-index.stderr
@@ -0,0 +1,11 @@
+error: unexpected token: `1.1`
+  --> $DIR/tuple-float-index.rs:4:17
+   |
+LL |     (1, (2, 3)).1.1;
+   |     ------------^^^
+   |     |           |
+   |     |           unexpected token
+   |     help: try parenthesizing the first index: `((1, (2, 3)).1).1`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/tuple/tuple-index-not-tuple.rs b/src/test/ui/tuple/tuple-index-not-tuple.rs
new file mode 100644
index 0000000..c478e1c
--- /dev/null
+++ b/src/test/ui/tuple/tuple-index-not-tuple.rs
@@ -0,0 +1,10 @@
+struct Point { x: isize, y: isize }
+struct Empty;
+
+fn main() {
+    let origin = Point { x: 0, y: 0 };
+    origin.0;
+    //~^ ERROR no field `0` on type `Point`
+    Empty.0;
+    //~^ ERROR no field `0` on type `Empty`
+}
diff --git a/src/test/ui/tuple/tuple-index-not-tuple.stderr b/src/test/ui/tuple/tuple-index-not-tuple.stderr
new file mode 100644
index 0000000..a1bcdfa
--- /dev/null
+++ b/src/test/ui/tuple/tuple-index-not-tuple.stderr
@@ -0,0 +1,15 @@
+error[E0609]: no field `0` on type `Point`
+  --> $DIR/tuple-index-not-tuple.rs:6:12
+   |
+LL |     origin.0;
+   |            ^ help: a field with a similar name exists: `x`
+
+error[E0609]: no field `0` on type `Empty`
+  --> $DIR/tuple-index-not-tuple.rs:8:11
+   |
+LL |     Empty.0;
+   |           ^ unknown field
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0609`.
diff --git a/src/test/ui/tuple/tuple-index-out-of-bounds.rs b/src/test/ui/tuple/tuple-index-out-of-bounds.rs
new file mode 100644
index 0000000..c772c0d
--- /dev/null
+++ b/src/test/ui/tuple/tuple-index-out-of-bounds.rs
@@ -0,0 +1,14 @@
+struct Point(i32, i32);
+
+fn main() {
+    let origin = Point(0, 0);
+    origin.0;
+    origin.1;
+    origin.2;
+    //~^ ERROR no field `2` on type `Point`
+    let tuple = (0, 0);
+    tuple.0;
+    tuple.1;
+    tuple.2;
+    //~^ ERROR no field `2` on type `({integer}, {integer})`
+}
diff --git a/src/test/ui/tuple/tuple-index-out-of-bounds.stderr b/src/test/ui/tuple/tuple-index-out-of-bounds.stderr
new file mode 100644
index 0000000..7d7c5cd
--- /dev/null
+++ b/src/test/ui/tuple/tuple-index-out-of-bounds.stderr
@@ -0,0 +1,15 @@
+error[E0609]: no field `2` on type `Point`
+  --> $DIR/tuple-index-out-of-bounds.rs:7:12
+   |
+LL |     origin.2;
+   |            ^ help: a field with a similar name exists: `0`
+
+error[E0609]: no field `2` on type `({integer}, {integer})`
+  --> $DIR/tuple-index-out-of-bounds.rs:12:11
+   |
+LL |     tuple.2;
+   |           ^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0609`.
diff --git a/src/test/ui/tuple/tuple-struct-fields/test.rs b/src/test/ui/tuple/tuple-struct-fields/test.rs
new file mode 100644
index 0000000..0067709
--- /dev/null
+++ b/src/test/ui/tuple/tuple-struct-fields/test.rs
@@ -0,0 +1,9 @@
+mod foo {
+    type T = ();
+    struct S1(pub(in foo) (), pub(T), pub(crate) (), pub(((), T)));
+    struct S2(pub((foo)) ());
+    //~^ ERROR expected one of `)` or `,`, found `(`
+    //~| ERROR cannot find type `foo` in this scope
+}
+
+fn main() {}
diff --git a/src/test/ui/tuple/tuple-struct-fields/test.stderr b/src/test/ui/tuple/tuple-struct-fields/test.stderr
new file mode 100644
index 0000000..295f0b1
--- /dev/null
+++ b/src/test/ui/tuple/tuple-struct-fields/test.stderr
@@ -0,0 +1,15 @@
+error: expected one of `)` or `,`, found `(`
+  --> $DIR/test.rs:4:26
+   |
+LL |     struct S2(pub((foo)) ());
+   |                          ^ expected one of `)` or `,` here
+
+error[E0412]: cannot find type `foo` in this scope
+  --> $DIR/test.rs:4:20
+   |
+LL |     struct S2(pub((foo)) ());
+   |                    ^^^ not found in this scope
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/src/test/ui/tuple/tuple-struct-fields/test2.rs b/src/test/ui/tuple/tuple-struct-fields/test2.rs
new file mode 100644
index 0000000..fc0f78b
--- /dev/null
+++ b/src/test/ui/tuple/tuple-struct-fields/test2.rs
@@ -0,0 +1,14 @@
+macro_rules! define_struct {
+    ($t:ty) => {
+        struct S1(pub $t);
+        struct S2(pub (in foo) ());
+        struct S3(pub $t ());
+        //~^ ERROR expected one of `)` or `,`, found `(`
+    }
+}
+
+mod foo {
+    define_struct! { (foo) } //~ ERROR cannot find type `foo` in this scope
+}
+
+fn main() {}
diff --git a/src/test/ui/tuple/tuple-struct-fields/test2.stderr b/src/test/ui/tuple/tuple-struct-fields/test2.stderr
new file mode 100644
index 0000000..78176c6
--- /dev/null
+++ b/src/test/ui/tuple/tuple-struct-fields/test2.stderr
@@ -0,0 +1,18 @@
+error: expected one of `)` or `,`, found `(`
+  --> $DIR/test2.rs:5:26
+   |
+LL |         struct S3(pub $t ());
+   |                          ^ expected one of `)` or `,` here
+...
+LL |     define_struct! { (foo) }
+   |     ------------------------ in this macro invocation
+
+error[E0412]: cannot find type `foo` in this scope
+  --> $DIR/test2.rs:11:23
+   |
+LL |     define_struct! { (foo) }
+   |                       ^^^ not found in this scope
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/src/test/ui/tuple/tuple-struct-fields/test3.rs b/src/test/ui/tuple/tuple-struct-fields/test3.rs
new file mode 100644
index 0000000..6b8534b
--- /dev/null
+++ b/src/test/ui/tuple/tuple-struct-fields/test3.rs
@@ -0,0 +1,14 @@
+macro_rules! define_struct {
+    ($t:ty) => {
+        struct S1(pub($t));
+        struct S2(pub (in foo) ());
+        struct S3(pub($t) ());
+        //~^ ERROR expected one of `)` or `,`, found `(`
+    }
+}
+
+mod foo {
+    define_struct! { foo } //~ ERROR cannot find type `foo` in this scope
+}
+
+fn main() {}
diff --git a/src/test/ui/tuple/tuple-struct-fields/test3.stderr b/src/test/ui/tuple/tuple-struct-fields/test3.stderr
new file mode 100644
index 0000000..e105aad
--- /dev/null
+++ b/src/test/ui/tuple/tuple-struct-fields/test3.stderr
@@ -0,0 +1,18 @@
+error: expected one of `)` or `,`, found `(`
+  --> $DIR/test3.rs:5:27
+   |
+LL |         struct S3(pub($t) ());
+   |                           ^ expected one of `)` or `,` here
+...
+LL |     define_struct! { foo }
+   |     ---------------------- in this macro invocation
+
+error[E0412]: cannot find type `foo` in this scope
+  --> $DIR/test3.rs:11:22
+   |
+LL |     define_struct! { foo }
+   |                      ^^^ not found in this scope
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/src/test/ui/tuple/tuple-struct-nonexhaustive.rs b/src/test/ui/tuple/tuple-struct-nonexhaustive.rs
new file mode 100644
index 0000000..76bcf3f
--- /dev/null
+++ b/src/test/ui/tuple/tuple-struct-nonexhaustive.rs
@@ -0,0 +1,9 @@
+struct Foo(isize, isize);
+
+fn main() {
+    let x = Foo(1, 2);
+    match x {   //~ ERROR non-exhaustive
+        Foo(1, b) => println!("{}", b),
+        Foo(2, b) => println!("{}", b)
+    }
+}
diff --git a/src/test/ui/tuple/tuple-struct-nonexhaustive.stderr b/src/test/ui/tuple/tuple-struct-nonexhaustive.stderr
new file mode 100644
index 0000000..bbdf9ce
--- /dev/null
+++ b/src/test/ui/tuple/tuple-struct-nonexhaustive.stderr
@@ -0,0 +1,14 @@
+error[E0004]: non-exhaustive patterns: `Foo(_, _)` not covered
+  --> $DIR/tuple-struct-nonexhaustive.rs:5:11
+   |
+LL | struct Foo(isize, isize);
+   | ------------------------- `Foo` defined here
+...
+LL |     match x {
+   |           ^ pattern `Foo(_, _)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/tutorial-suffix-inference-test.rs b/src/test/ui/tutorial-suffix-inference-test.rs
new file mode 100644
index 0000000..2477c63
--- /dev/null
+++ b/src/test/ui/tutorial-suffix-inference-test.rs
@@ -0,0 +1,24 @@
+fn main() {
+    let x = 3;
+    let y: i32 = 3;
+
+    fn identity_u8(n: u8) -> u8 { n }
+    fn identity_u16(n: u16) -> u16 { n }
+
+    identity_u8(x);  // after this, `x` is assumed to have type `u8`
+    identity_u16(x);
+    //~^ ERROR mismatched types
+    //~| expected u16, found u8
+    identity_u16(y);
+    //~^ ERROR mismatched types
+    //~| expected u16, found i32
+
+    let a = 3;
+
+    fn identity_i(n: isize) -> isize { n }
+
+    identity_i(a); // ok
+    identity_u16(a);
+    //~^ ERROR mismatched types
+    //~| expected u16, found isize
+}
diff --git a/src/test/ui/tutorial-suffix-inference-test.stderr b/src/test/ui/tutorial-suffix-inference-test.stderr
new file mode 100644
index 0000000..6ba1b09
--- /dev/null
+++ b/src/test/ui/tutorial-suffix-inference-test.stderr
@@ -0,0 +1,25 @@
+error[E0308]: mismatched types
+  --> $DIR/tutorial-suffix-inference-test.rs:9:18
+   |
+LL |     identity_u16(x);
+   |                  ^ expected u16, found u8
+help: you can cast an `u8` to `u16`, which will zero-extend the source value
+   |
+LL |     identity_u16(x.into());
+   |                  ^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/tutorial-suffix-inference-test.rs:12:18
+   |
+LL |     identity_u16(y);
+   |                  ^ expected u16, found i32
+
+error[E0308]: mismatched types
+  --> $DIR/tutorial-suffix-inference-test.rs:21:18
+   |
+LL |     identity_u16(a);
+   |                  ^ expected u16, found isize
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/type-alias-enum-variants-panic.rs b/src/test/ui/type-alias-enum-variants-panic.rs
new file mode 100644
index 0000000..f97592f
--- /dev/null
+++ b/src/test/ui/type-alias-enum-variants-panic.rs
@@ -0,0 +1,17 @@
+// ignore-tidy-linelength
+
+#![feature(type_alias_enum_variants)]
+
+#![allow(unreachable_code)]
+
+enum Enum { Variant {} }
+type Alias = Enum;
+
+fn main() {
+    Alias::Variant;
+    //~^ ERROR expected unit struct/variant or constant, found struct variant `<Alias>::Variant` [E0533]
+    let Alias::Variant = panic!();
+    //~^ ERROR expected unit struct/variant or constant, found struct variant `<Alias>::Variant` [E0533]
+    let Alias::Variant(..) = panic!();
+    //~^ ERROR expected tuple struct/variant, found struct variant `<Alias>::Variant` [E0164]
+}
diff --git a/src/test/ui/type-alias-enum-variants-panic.stderr b/src/test/ui/type-alias-enum-variants-panic.stderr
new file mode 100644
index 0000000..3480d11
--- /dev/null
+++ b/src/test/ui/type-alias-enum-variants-panic.stderr
@@ -0,0 +1,22 @@
+error[E0533]: expected unit struct/variant or constant, found struct variant `<Alias>::Variant`
+  --> $DIR/type-alias-enum-variants-panic.rs:11:5
+   |
+LL |     Alias::Variant;
+   |     ^^^^^^^^^^^^^^
+
+error[E0533]: expected unit struct/variant or constant, found struct variant `<Alias>::Variant`
+  --> $DIR/type-alias-enum-variants-panic.rs:13:9
+   |
+LL |     let Alias::Variant = panic!();
+   |         ^^^^^^^^^^^^^^
+
+error[E0164]: expected tuple struct/variant, found struct variant `<Alias>::Variant`
+  --> $DIR/type-alias-enum-variants-panic.rs:15:9
+   |
+LL |     let Alias::Variant(..) = panic!();
+   |         ^^^^^^^^^^^^^^^^^^ not a tuple variant or struct
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0164, E0533.
+For more information about an error, try `rustc --explain E0164`.
diff --git a/src/test/ui/type-alias-enum-variants-priority-2.rs b/src/test/ui/type-alias-enum-variants-priority-2.rs
new file mode 100644
index 0000000..295f8ac
--- /dev/null
+++ b/src/test/ui/type-alias-enum-variants-priority-2.rs
@@ -0,0 +1,13 @@
+#![feature(type_alias_enum_variants)]
+
+enum E {
+    V(u8)
+}
+
+impl E {
+    fn V() {}
+}
+
+fn main() {
+    <E>::V(); //~ ERROR this function takes 1 parameter but 0 parameters were supplied
+}
diff --git a/src/test/ui/type-alias-enum-variants-priority-2.stderr b/src/test/ui/type-alias-enum-variants-priority-2.stderr
new file mode 100644
index 0000000..10a4b44
--- /dev/null
+++ b/src/test/ui/type-alias-enum-variants-priority-2.stderr
@@ -0,0 +1,12 @@
+error[E0061]: this function takes 1 parameter but 0 parameters were supplied
+  --> $DIR/type-alias-enum-variants-priority-2.rs:12:5
+   |
+LL |     V(u8)
+   |     ----- defined here
+...
+LL |     <E>::V();
+   |     ^^^^^^^^ expected 1 parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0061`.
diff --git a/src/test/ui/type-alias-enum-variants-priority-3.rs b/src/test/ui/type-alias-enum-variants-priority-3.rs
new file mode 100644
index 0000000..33f9655
--- /dev/null
+++ b/src/test/ui/type-alias-enum-variants-priority-3.rs
@@ -0,0 +1,10 @@
+#![feature(type_alias_enum_variants)]
+
+enum E {
+    V
+}
+
+fn check() -> <E>::V {}
+//~^ ERROR expected type, found variant `V`
+
+fn main() {}
diff --git a/src/test/ui/type-alias-enum-variants-priority-3.stderr b/src/test/ui/type-alias-enum-variants-priority-3.stderr
new file mode 100644
index 0000000..b345154
--- /dev/null
+++ b/src/test/ui/type-alias-enum-variants-priority-3.stderr
@@ -0,0 +1,8 @@
+error: expected type, found variant `V`
+  --> $DIR/type-alias-enum-variants-priority-3.rs:7:15
+   |
+LL | fn check() -> <E>::V {}
+   |               ^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/type-alias-enum-variants-priority.rs b/src/test/ui/type-alias-enum-variants-priority.rs
new file mode 100644
index 0000000..db1da2b
--- /dev/null
+++ b/src/test/ui/type-alias-enum-variants-priority.rs
@@ -0,0 +1,20 @@
+#![feature(type_alias_enum_variants)]
+#![deny(ambiguous_associated_items)]
+
+enum E {
+    V
+}
+
+trait Tr {
+    type V;
+    fn f() -> Self::V;
+}
+
+impl Tr for E {
+    type V = u8;
+    fn f() -> Self::V { 0 }
+    //~^ ERROR ambiguous associated item
+    //~| WARN this was previously accepted
+}
+
+fn main() {}
diff --git a/src/test/ui/type-alias-enum-variants-priority.stderr b/src/test/ui/type-alias-enum-variants-priority.stderr
new file mode 100644
index 0000000..dcf7dc7
--- /dev/null
+++ b/src/test/ui/type-alias-enum-variants-priority.stderr
@@ -0,0 +1,26 @@
+error: ambiguous associated item
+  --> $DIR/type-alias-enum-variants-priority.rs:15:15
+   |
+LL |     fn f() -> Self::V { 0 }
+   |               ^^^^^^^ help: use fully-qualified syntax: `<E as Trait>::V`
+   |
+note: lint level defined here
+  --> $DIR/type-alias-enum-variants-priority.rs:2:9
+   |
+LL | #![deny(ambiguous_associated_items)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #57644 <https://github.com/rust-lang/rust/issues/57644>
+note: `V` could refer to variant defined here
+  --> $DIR/type-alias-enum-variants-priority.rs:5:5
+   |
+LL |     V
+   |     ^
+note: `V` could also refer to associated type defined here
+  --> $DIR/type-alias-enum-variants-priority.rs:9:5
+   |
+LL |     type V;
+   |     ^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/type-alias-enum-variants.rs b/src/test/ui/type-alias-enum-variants.rs
new file mode 100644
index 0000000..c5974e5
--- /dev/null
+++ b/src/test/ui/type-alias-enum-variants.rs
@@ -0,0 +1,11 @@
+#![feature(type_alias_enum_variants)]
+
+type Alias<T> = Option<T>;
+
+fn main() {
+    let _ = Option::<u8>::None; // OK
+    let _ = Option::None::<u8>; // OK (Lint in future!)
+    let _ = Alias::<u8>::None; // OK
+    let _ = Alias::None::<u8>; // Error
+    //~^ type arguments are not allowed for this type
+}
diff --git a/src/test/ui/type-alias-enum-variants.stderr b/src/test/ui/type-alias-enum-variants.stderr
new file mode 100644
index 0000000..55f250f
--- /dev/null
+++ b/src/test/ui/type-alias-enum-variants.stderr
@@ -0,0 +1,9 @@
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/type-alias-enum-variants.rs:9:27
+   |
+LL |     let _ = Alias::None::<u8>; // Error
+   |                           ^^ type argument not allowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0109`.
diff --git a/src/test/ui/type/auxiliary/crate_a1.rs b/src/test/ui/type/auxiliary/crate_a1.rs
new file mode 100644
index 0000000..e2e1850
--- /dev/null
+++ b/src/test/ui/type/auxiliary/crate_a1.rs
@@ -0,0 +1,11 @@
+pub struct Foo;
+
+pub trait Bar{}
+
+pub fn bar() -> Box<Bar> {
+    unimplemented!()
+}
+
+
+pub fn try_foo(x: Foo){}
+pub fn try_bar(x: Box<Bar>){}
diff --git a/src/test/ui/type/auxiliary/crate_a2.rs b/src/test/ui/type/auxiliary/crate_a2.rs
new file mode 100644
index 0000000..d16a4ac
--- /dev/null
+++ b/src/test/ui/type/auxiliary/crate_a2.rs
@@ -0,0 +1,7 @@
+pub struct Foo;
+
+pub trait Bar{}
+
+pub fn bar() -> Box<Bar> {
+    unimplemented!()
+}
diff --git a/src/test/ui/type/type-alias-bounds.rs b/src/test/ui/type/type-alias-bounds.rs
new file mode 100644
index 0000000..e2be2b9
--- /dev/null
+++ b/src/test/ui/type/type-alias-bounds.rs
@@ -0,0 +1,59 @@
+// Test ignored_generic_bounds lint warning about bounds in type aliases
+
+// compile-pass
+#![allow(dead_code)]
+
+use std::rc::Rc;
+
+type SVec<T: Send+Send> = Vec<T>;
+//~^ WARN bounds on generic parameters are not enforced in type aliases [type_alias_bounds]
+type S2Vec<T> where T: Send = Vec<T>;
+//~^ WARN where clauses are not enforced in type aliases [type_alias_bounds]
+type VVec<'b, 'a: 'b+'b> = (&'b u32, Vec<&'a i32>);
+//~^ WARN bounds on generic parameters are not enforced in type aliases [type_alias_bounds]
+type WVec<'b, T: 'b+'b> = (&'b u32, Vec<T>);
+//~^ WARN bounds on generic parameters are not enforced in type aliases [type_alias_bounds]
+type W2Vec<'b, T> where T: 'b, T: 'b = (&'b u32, Vec<T>);
+//~^ WARN where clauses are not enforced in type aliases [type_alias_bounds]
+
+static STATIC : u32 = 0;
+
+fn foo<'a>(y: &'a i32) {
+    // If any of the bounds above would matter, the code below would be rejected.
+    // This can be seen when replacing the type aliases above by newtype structs.
+    // (The type aliases have no unused parameters to make that a valid transformation.)
+    let mut x : SVec<_> = Vec::new();
+    x.push(Rc::new(42)); // is not send
+
+    let mut x : S2Vec<_> = Vec::new();
+    x.push(Rc::new(42)); // is not send
+
+    let mut x : VVec<'static, 'a> = (&STATIC, Vec::new());
+    x.1.push(y); // 'a: 'static does not hold
+
+    let mut x : WVec<'static, &'a i32> = (&STATIC, Vec::new());
+    x.1.push(y); // &'a i32: 'static does not hold
+
+    let mut x : W2Vec<'static, &'a i32> = (&STATIC, Vec::new());
+    x.1.push(y); // &'a i32: 'static does not hold
+}
+
+// Bounds are not checked either, i.e., the definition is not necessarily well-formed
+struct Sendable<T: Send>(T);
+type MySendable<T> = Sendable<T>; // no error here!
+
+// However, bounds *are* taken into account when accessing associated types
+trait Bound { type Assoc; }
+type T1<U: Bound> = U::Assoc; //~ WARN not enforced in type aliases
+type T2<U> where U: Bound = U::Assoc;  //~ WARN not enforced in type aliases
+
+// This errors
+// type T3<U> = U::Assoc;
+// Do this instead
+type T4<U> = <U as Bound>::Assoc;
+
+// Make sure the help about associatd types is not shown incorrectly
+type T5<U: Bound> = <U as Bound>::Assoc;  //~ WARN not enforced in type aliases
+type T6<U: Bound> = ::std::vec::Vec<U>;  //~ WARN not enforced in type aliases
+
+fn main() {}
diff --git a/src/test/ui/type/type-alias-bounds.stderr b/src/test/ui/type/type-alias-bounds.stderr
new file mode 100644
index 0000000..3cc8443
--- /dev/null
+++ b/src/test/ui/type/type-alias-bounds.stderr
@@ -0,0 +1,83 @@
+warning: bounds on generic parameters are not enforced in type aliases
+  --> $DIR/type-alias-bounds.rs:8:14
+   |
+LL | type SVec<T: Send+Send> = Vec<T>;
+   |              ^^^^ ^^^^
+   |
+   = note: #[warn(type_alias_bounds)] on by default
+   = help: the bound will not be checked when the type alias is used, and should be removed
+
+warning: where clauses are not enforced in type aliases
+  --> $DIR/type-alias-bounds.rs:10:21
+   |
+LL | type S2Vec<T> where T: Send = Vec<T>;
+   |                     ^^^^^^^
+   |
+   = help: the clause will not be checked when the type alias is used, and should be removed
+
+warning: bounds on generic parameters are not enforced in type aliases
+  --> $DIR/type-alias-bounds.rs:12:19
+   |
+LL | type VVec<'b, 'a: 'b+'b> = (&'b u32, Vec<&'a i32>);
+   |                   ^^ ^^
+   |
+   = help: the bound will not be checked when the type alias is used, and should be removed
+
+warning: bounds on generic parameters are not enforced in type aliases
+  --> $DIR/type-alias-bounds.rs:14:18
+   |
+LL | type WVec<'b, T: 'b+'b> = (&'b u32, Vec<T>);
+   |                  ^^ ^^
+   |
+   = help: the bound will not be checked when the type alias is used, and should be removed
+
+warning: where clauses are not enforced in type aliases
+  --> $DIR/type-alias-bounds.rs:16:25
+   |
+LL | type W2Vec<'b, T> where T: 'b, T: 'b = (&'b u32, Vec<T>);
+   |                         ^^^^^  ^^^^^
+   |
+   = help: the clause will not be checked when the type alias is used, and should be removed
+
+warning: bounds on generic parameters are not enforced in type aliases
+  --> $DIR/type-alias-bounds.rs:47:12
+   |
+LL | type T1<U: Bound> = U::Assoc;
+   |            ^^^^^
+   |
+   = help: the bound will not be checked when the type alias is used, and should be removed
+help: use fully disambiguated paths (i.e., `<T as Trait>::Assoc`) to refer to associated types in type aliases
+  --> $DIR/type-alias-bounds.rs:47:21
+   |
+LL | type T1<U: Bound> = U::Assoc;
+   |                     ^^^^^^^^
+
+warning: where clauses are not enforced in type aliases
+  --> $DIR/type-alias-bounds.rs:48:18
+   |
+LL | type T2<U> where U: Bound = U::Assoc;
+   |                  ^^^^^^^^
+   |
+   = help: the clause will not be checked when the type alias is used, and should be removed
+help: use fully disambiguated paths (i.e., `<T as Trait>::Assoc`) to refer to associated types in type aliases
+  --> $DIR/type-alias-bounds.rs:48:29
+   |
+LL | type T2<U> where U: Bound = U::Assoc;
+   |                             ^^^^^^^^
+
+warning: bounds on generic parameters are not enforced in type aliases
+  --> $DIR/type-alias-bounds.rs:56:12
+   |
+LL | type T5<U: Bound> = <U as Bound>::Assoc;
+   |            ^^^^^
+   |
+   = help: the bound will not be checked when the type alias is used, and should be removed
+
+warning: bounds on generic parameters are not enforced in type aliases
+  --> $DIR/type-alias-bounds.rs:57:12
+   |
+LL | type T6<U: Bound> = ::std::vec::Vec<U>;
+   |            ^^^^^
+   |
+   = help: the bound will not be checked when the type alias is used, and should be removed
+
diff --git a/src/test/ui/type/type-annotation-needed.rs b/src/test/ui/type/type-annotation-needed.rs
new file mode 100644
index 0000000..ff2342c
--- /dev/null
+++ b/src/test/ui/type/type-annotation-needed.rs
@@ -0,0 +1,7 @@
+fn foo<T: Into<String>>(x: i32) {}
+//~^ NOTE required by
+
+fn main() {
+    foo(42);
+    //~^ ERROR type annotations required
+}
diff --git a/src/test/ui/type/type-annotation-needed.stderr b/src/test/ui/type/type-annotation-needed.stderr
new file mode 100644
index 0000000..92ae974
--- /dev/null
+++ b/src/test/ui/type/type-annotation-needed.stderr
@@ -0,0 +1,15 @@
+error[E0283]: type annotations required: cannot resolve `_: std::convert::Into<std::string::String>`
+  --> $DIR/type-annotation-needed.rs:5:5
+   |
+LL |     foo(42);
+   |     ^^^
+   |
+note: required by `foo`
+  --> $DIR/type-annotation-needed.rs:1:1
+   |
+LL | fn foo<T: Into<String>>(x: i32) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0283`.
diff --git a/src/test/ui/type/type-arg-out-of-scope.rs b/src/test/ui/type/type-arg-out-of-scope.rs
new file mode 100644
index 0000000..d5b815f
--- /dev/null
+++ b/src/test/ui/type/type-arg-out-of-scope.rs
@@ -0,0 +1,5 @@
+// error-pattern:can't use generic parameters from outer function
+fn foo<T>(x: T) {
+    fn bar(f: Box<FnMut(T) -> T>) { }
+}
+fn main() { foo(1); }
diff --git a/src/test/ui/type/type-arg-out-of-scope.stderr b/src/test/ui/type/type-arg-out-of-scope.stderr
new file mode 100644
index 0000000..645cbb3
--- /dev/null
+++ b/src/test/ui/type/type-arg-out-of-scope.stderr
@@ -0,0 +1,23 @@
+error[E0401]: can't use generic parameters from outer function
+  --> $DIR/type-arg-out-of-scope.rs:3:25
+   |
+LL | fn foo<T>(x: T) {
+   |        - type variable from outer function
+LL |     fn bar(f: Box<FnMut(T) -> T>) { }
+   |        ---              ^ use of generic parameter from outer function
+   |        |
+   |        help: try using a local generic parameter instead: `bar<T>`
+
+error[E0401]: can't use generic parameters from outer function
+  --> $DIR/type-arg-out-of-scope.rs:3:31
+   |
+LL | fn foo<T>(x: T) {
+   |        - type variable from outer function
+LL |     fn bar(f: Box<FnMut(T) -> T>) { }
+   |        ---                    ^ use of generic parameter from outer function
+   |        |
+   |        help: try using a local generic parameter instead: `bar<T>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0401`.
diff --git a/src/test/ui/type/type-ascription-instead-of-initializer.rs b/src/test/ui/type/type-ascription-instead-of-initializer.rs
new file mode 100644
index 0000000..aef2525
--- /dev/null
+++ b/src/test/ui/type/type-ascription-instead-of-initializer.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let x: Vec::with_capacity(10, 20);  //~ ERROR expected type, found `10`
+    //~^ ERROR this function takes 1 parameter
+}
diff --git a/src/test/ui/type/type-ascription-instead-of-initializer.stderr b/src/test/ui/type/type-ascription-instead-of-initializer.stderr
new file mode 100644
index 0000000..a22d256
--- /dev/null
+++ b/src/test/ui/type/type-ascription-instead-of-initializer.stderr
@@ -0,0 +1,18 @@
+error: expected type, found `10`
+  --> $DIR/type-ascription-instead-of-initializer.rs:2:31
+   |
+LL |     let x: Vec::with_capacity(10, 20);
+   |         --                    ^^
+   |         ||
+   |         |help: use `=` if you meant to assign
+   |         while parsing the type for `x`
+
+error[E0061]: this function takes 1 parameter but 2 parameters were supplied
+  --> $DIR/type-ascription-instead-of-initializer.rs:2:12
+   |
+LL |     let x: Vec::with_capacity(10, 20);
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 1 parameter
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0061`.
diff --git a/src/test/ui/type/type-ascription-instead-of-statement-end.rs b/src/test/ui/type/type-ascription-instead-of-statement-end.rs
new file mode 100644
index 0000000..1d5565a
--- /dev/null
+++ b/src/test/ui/type/type-ascription-instead-of-statement-end.rs
@@ -0,0 +1,10 @@
+#![feature(type_ascription)]
+
+fn main() {
+    println!("test"):
+    0; //~ ERROR expected type, found `0`
+}
+
+fn foo() {
+    println!("test"): 0; //~ ERROR expected type, found `0`
+}
diff --git a/src/test/ui/type/type-ascription-instead-of-statement-end.stderr b/src/test/ui/type/type-ascription-instead-of-statement-end.stderr
new file mode 100644
index 0000000..2084cbc
--- /dev/null
+++ b/src/test/ui/type/type-ascription-instead-of-statement-end.stderr
@@ -0,0 +1,24 @@
+error: expected type, found `0`
+  --> $DIR/type-ascription-instead-of-statement-end.rs:5:5
+   |
+LL |     println!("test"):
+   |                     - help: try using a semicolon: `;`
+LL |     0;
+   |     ^ expecting a type here because of type ascription
+
+error: expected type, found `0`
+  --> $DIR/type-ascription-instead-of-statement-end.rs:9:23
+   |
+LL |     println!("test"): 0;
+   |                       ^ expecting a type here because of type ascription
+   |
+   = note: type ascription is a nightly-only feature that lets you annotate an expression with a type: `<expr>: <type>`
+note: this expression expects an ascribed type after the colon
+  --> $DIR/type-ascription-instead-of-statement-end.rs:9:5
+   |
+LL |     println!("test"): 0;
+   |     ^^^^^^^^^^^^^^^^
+   = help: this might be indicative of a syntax error elsewhere
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/type/type-ascription-precedence.rs b/src/test/ui/type/type-ascription-precedence.rs
new file mode 100644
index 0000000..d3aef92
--- /dev/null
+++ b/src/test/ui/type/type-ascription-precedence.rs
@@ -0,0 +1,54 @@
+// Operator precedence of type ascription
+// Type ascription has very high precedence, the same as operator `as`
+
+#![feature(type_ascription)]
+
+use std::ops::*;
+
+struct S;
+struct Z;
+
+impl Add<Z> for S {
+    type Output = S;
+    fn add(self, _rhs: Z) -> S { panic!() }
+}
+impl Mul<Z> for S {
+    type Output = S;
+    fn mul(self, _rhs: Z) -> S { panic!() }
+}
+impl Neg for S {
+    type Output = Z;
+    fn neg(self) -> Z { panic!() }
+}
+impl Deref for S {
+    type Target = Z;
+    fn deref(&self) -> &Z { panic!() }
+}
+
+fn main() {
+    &S: &S; // OK
+    (&S): &S; // OK
+    &(S: &S); //~ ERROR mismatched types
+
+    *S: Z; // OK
+    (*S): Z; // OK
+    *(S: Z); //~ ERROR mismatched types
+    //~^ ERROR type `Z` cannot be dereferenced
+
+    -S: Z; // OK
+    (-S): Z; // OK
+    -(S: Z); //~ ERROR mismatched types
+    //~^ ERROR cannot apply unary operator `-` to type `Z`
+
+    S + Z: Z; // OK
+    S + (Z: Z); // OK
+    (S + Z): Z; //~ ERROR mismatched types
+
+    S * Z: Z; // OK
+    S * (Z: Z); // OK
+    (S * Z): Z; //~ ERROR mismatched types
+
+    S .. S: S; // OK
+    S .. (S: S); // OK
+    (S .. S): S; //~ ERROR mismatched types
+}
diff --git a/src/test/ui/type/type-ascription-precedence.stderr b/src/test/ui/type/type-ascription-precedence.stderr
new file mode 100644
index 0000000..992974e
--- /dev/null
+++ b/src/test/ui/type/type-ascription-precedence.stderr
@@ -0,0 +1,72 @@
+error[E0308]: mismatched types
+  --> $DIR/type-ascription-precedence.rs:31:7
+   |
+LL |     &(S: &S);
+   |       ^ expected &S, found struct `S`
+   |
+   = note: expected type `&S`
+              found type `S`
+
+error[E0308]: mismatched types
+  --> $DIR/type-ascription-precedence.rs:35:7
+   |
+LL |     *(S: Z);
+   |       ^ expected struct `Z`, found struct `S`
+   |
+   = note: expected type `Z`
+              found type `S`
+
+error[E0614]: type `Z` cannot be dereferenced
+  --> $DIR/type-ascription-precedence.rs:35:5
+   |
+LL |     *(S: Z);
+   |     ^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/type-ascription-precedence.rs:40:7
+   |
+LL |     -(S: Z);
+   |       ^ expected struct `Z`, found struct `S`
+   |
+   = note: expected type `Z`
+              found type `S`
+
+error[E0600]: cannot apply unary operator `-` to type `Z`
+  --> $DIR/type-ascription-precedence.rs:40:5
+   |
+LL |     -(S: Z);
+   |     ^^^^^^^ cannot apply unary operator `-`
+   |
+   = note: an implementation of `std::ops::Neg` might be missing for `Z`
+
+error[E0308]: mismatched types
+  --> $DIR/type-ascription-precedence.rs:45:5
+   |
+LL |     (S + Z): Z;
+   |     ^^^^^^^ expected struct `Z`, found struct `S`
+   |
+   = note: expected type `Z`
+              found type `S`
+
+error[E0308]: mismatched types
+  --> $DIR/type-ascription-precedence.rs:49:5
+   |
+LL |     (S * Z): Z;
+   |     ^^^^^^^ expected struct `Z`, found struct `S`
+   |
+   = note: expected type `Z`
+              found type `S`
+
+error[E0308]: mismatched types
+  --> $DIR/type-ascription-precedence.rs:53:5
+   |
+LL |     (S .. S): S;
+   |     ^^^^^^^^ expected struct `S`, found struct `std::ops::Range`
+   |
+   = note: expected type `S`
+              found type `std::ops::Range<S>`
+
+error: aborting due to 8 previous errors
+
+Some errors occurred: E0308, E0600, E0614.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/type/type-ascription-soundness.rs b/src/test/ui/type/type-ascription-soundness.rs
new file mode 100644
index 0000000..d583fc2
--- /dev/null
+++ b/src/test/ui/type/type-ascription-soundness.rs
@@ -0,0 +1,13 @@
+// Type ascription doesn't lead to unsoundness
+
+#![feature(type_ascription)]
+
+fn main() {
+    let arr = &[1u8, 2, 3];
+    let ref x = arr: &[u8]; //~ ERROR mismatched types
+    let ref mut x = arr: &[u8]; //~ ERROR mismatched types
+    match arr: &[u8] { //~ ERROR mismatched types
+        ref x => {}
+    }
+    let _len = (arr: &[u8]).len(); //~ ERROR mismatched types
+}
diff --git a/src/test/ui/type/type-ascription-soundness.stderr b/src/test/ui/type/type-ascription-soundness.stderr
new file mode 100644
index 0000000..150e190
--- /dev/null
+++ b/src/test/ui/type/type-ascription-soundness.stderr
@@ -0,0 +1,39 @@
+error[E0308]: mismatched types
+  --> $DIR/type-ascription-soundness.rs:7:17
+   |
+LL |     let ref x = arr: &[u8];
+   |                 ^^^ expected slice, found array of 3 elements
+   |
+   = note: expected type `&[u8]`
+              found type `&[u8; 3]`
+
+error[E0308]: mismatched types
+  --> $DIR/type-ascription-soundness.rs:8:21
+   |
+LL |     let ref mut x = arr: &[u8];
+   |                     ^^^ expected slice, found array of 3 elements
+   |
+   = note: expected type `&[u8]`
+              found type `&[u8; 3]`
+
+error[E0308]: mismatched types
+  --> $DIR/type-ascription-soundness.rs:9:11
+   |
+LL |     match arr: &[u8] {
+   |           ^^^ expected slice, found array of 3 elements
+   |
+   = note: expected type `&[u8]`
+              found type `&[u8; 3]`
+
+error[E0308]: mismatched types
+  --> $DIR/type-ascription-soundness.rs:12:17
+   |
+LL |     let _len = (arr: &[u8]).len();
+   |                 ^^^ expected slice, found array of 3 elements
+   |
+   = note: expected type `&[u8]`
+              found type `&[u8; 3]`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/type/type-ascription-with-fn-call.rs b/src/test/ui/type/type-ascription-with-fn-call.rs
new file mode 100644
index 0000000..2bd2efa
--- /dev/null
+++ b/src/test/ui/type/type-ascription-with-fn-call.rs
@@ -0,0 +1,8 @@
+#![feature(type_ascription)]
+
+fn main() {
+    f()  :
+    f(); //~ ERROR expected type, found function
+}
+
+fn f() {}
diff --git a/src/test/ui/type/type-ascription-with-fn-call.stderr b/src/test/ui/type/type-ascription-with-fn-call.stderr
new file mode 100644
index 0000000..eeaca53
--- /dev/null
+++ b/src/test/ui/type/type-ascription-with-fn-call.stderr
@@ -0,0 +1,14 @@
+error[E0573]: expected type, found function `f`
+  --> $DIR/type-ascription-with-fn-call.rs:5:5
+   |
+LL |     f()  :
+   |          - help: did you mean to use `;` here instead?
+LL |     f();
+   |     ^^^
+   |     |
+   |     not a type
+   |     expecting a type here because of type ascription
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0573`.
diff --git a/src/test/ui/type/type-check-defaults.rs b/src/test/ui/type/type-check-defaults.rs
new file mode 100644
index 0000000..5748c9b
--- /dev/null
+++ b/src/test/ui/type/type-check-defaults.rs
@@ -0,0 +1,27 @@
+use std::iter::FromIterator;
+use std::vec::IntoIter;
+use std::ops::Add;
+
+struct Foo<T, U: FromIterator<T>>(T, U);
+struct WellFormed<Z = Foo<i32, i32>>(Z);
+//~^ ERROR a collection of type `i32` cannot be built from an iterator over elements of type `i32`
+struct WellFormedNoBounds<Z:?Sized = Foo<i32, i32>>(Z);
+//~^ ERROR a collection of type `i32` cannot be built from an iterator over elements of type `i32`
+
+struct Bounds<T:Copy=String>(T);
+//~^ ERROR the trait bound `std::string::String: std::marker::Copy` is not satisfied [E0277]
+
+struct WhereClause<T=String>(T) where T: Copy;
+//~^ ERROR the trait bound `std::string::String: std::marker::Copy` is not satisfied [E0277]
+
+trait TraitBound<T:Copy=String> {}
+//~^ ERROR the trait bound `std::string::String: std::marker::Copy` is not satisfied [E0277]
+
+trait Super<T: Copy> { }
+trait Base<T = String>: Super<T> { }
+//~^ ERROR the trait bound `T: std::marker::Copy` is not satisfied [E0277]
+
+trait ProjectionPred<T:Iterator = IntoIter<i32>> where T::Item : Add<u8> {}
+//~^ ERROR cannot add `u8` to `i32` [E0277]
+
+fn main() { }
diff --git a/src/test/ui/type/type-check-defaults.stderr b/src/test/ui/type/type-check-defaults.stderr
new file mode 100644
index 0000000..a46d79e
--- /dev/null
+++ b/src/test/ui/type/type-check-defaults.stderr
@@ -0,0 +1,91 @@
+error[E0277]: a collection of type `i32` cannot be built from an iterator over elements of type `i32`
+  --> $DIR/type-check-defaults.rs:6:19
+   |
+LL | struct WellFormed<Z = Foo<i32, i32>>(Z);
+   |                   ^ a collection of type `i32` cannot be built from `std::iter::Iterator<Item=i32>`
+   |
+   = help: the trait `std::iter::FromIterator<i32>` is not implemented for `i32`
+note: required by `Foo`
+  --> $DIR/type-check-defaults.rs:5:1
+   |
+LL | struct Foo<T, U: FromIterator<T>>(T, U);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: a collection of type `i32` cannot be built from an iterator over elements of type `i32`
+  --> $DIR/type-check-defaults.rs:8:27
+   |
+LL | struct WellFormedNoBounds<Z:?Sized = Foo<i32, i32>>(Z);
+   |                           ^ a collection of type `i32` cannot be built from `std::iter::Iterator<Item=i32>`
+   |
+   = help: the trait `std::iter::FromIterator<i32>` is not implemented for `i32`
+note: required by `Foo`
+  --> $DIR/type-check-defaults.rs:5:1
+   |
+LL | struct Foo<T, U: FromIterator<T>>(T, U);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied
+  --> $DIR/type-check-defaults.rs:11:1
+   |
+LL | struct Bounds<T:Copy=String>(T);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String`
+   |
+note: required by `Bounds`
+  --> $DIR/type-check-defaults.rs:11:1
+   |
+LL | struct Bounds<T:Copy=String>(T);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied
+  --> $DIR/type-check-defaults.rs:14:1
+   |
+LL | struct WhereClause<T=String>(T) where T: Copy;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String`
+   |
+note: required by `WhereClause`
+  --> $DIR/type-check-defaults.rs:14:1
+   |
+LL | struct WhereClause<T=String>(T) where T: Copy;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied
+  --> $DIR/type-check-defaults.rs:17:1
+   |
+LL | trait TraitBound<T:Copy=String> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String`
+   |
+note: required by `TraitBound`
+  --> $DIR/type-check-defaults.rs:17:1
+   |
+LL | trait TraitBound<T:Copy=String> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
+  --> $DIR/type-check-defaults.rs:21:1
+   |
+LL | trait Base<T = String>: Super<T> { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
+   |
+   = help: consider adding a `where T: std::marker::Copy` bound
+note: required by `Super`
+  --> $DIR/type-check-defaults.rs:20:1
+   |
+LL | trait Super<T: Copy> { }
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: cannot add `u8` to `i32`
+  --> $DIR/type-check-defaults.rs:24:1
+   |
+LL | trait ProjectionPred<T:Iterator = IntoIter<i32>> where T::Item : Add<u8> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `i32 + u8`
+   |
+   = help: the trait `std::ops::Add<u8>` is not implemented for `i32`
+note: required by `ProjectionPred`
+  --> $DIR/type-check-defaults.rs:24:1
+   |
+LL | trait ProjectionPred<T:Iterator = IntoIter<i32>> where T::Item : Add<u8> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/type/type-check/assignment-expected-bool.rs b/src/test/ui/type/type-check/assignment-expected-bool.rs
new file mode 100644
index 0000000..03830fe
--- /dev/null
+++ b/src/test/ui/type/type-check/assignment-expected-bool.rs
@@ -0,0 +1,34 @@
+// The purpose of this text is to ensure that we get good
+// diagnostics when a `bool` is expected but that due to
+// an assignment expression `x = y` the type is `()`.
+
+fn main() {
+    let _: bool = 0 = 0; //~ ERROR mismatched types [E0308]
+
+    let _: bool = match 0 {
+        0 => 0 = 0, //~ ERROR mismatched types [E0308]
+        _ => 0 = 0, //~ ERROR mismatched types [E0308]
+    };
+
+    let _: bool = match true {
+        true => 0 = 0, //~ ERROR mismatched types [E0308]
+        _ => (),
+    };
+
+    if 0 = 0 {} //~ ERROR mismatched types [E0308]
+
+    let _: bool = if { 0 = 0 } { //~ ERROR mismatched types [E0308]
+        0 = 0 //~ ERROR mismatched types [E0308]
+    } else {
+        0 = 0 //~ ERROR mismatched types [E0308]
+    };
+
+    let _ = (0 = 0) //~ ERROR mismatched types [E0308]
+        && { 0 = 0 } //~ ERROR mismatched types [E0308]
+        || (0 = 0); //~ ERROR mismatched types [E0308]
+
+    // A test to check that not expecting `bool` behaves well:
+    let _: usize = 0 = 0;
+    //~^ ERROR mismatched types [E0308]
+    //~| ERROR invalid left-hand side expression [E0070]
+}
diff --git a/src/test/ui/type/type-check/assignment-expected-bool.stderr b/src/test/ui/type/type-check/assignment-expected-bool.stderr
new file mode 100644
index 0000000..fed8b91
--- /dev/null
+++ b/src/test/ui/type/type-check/assignment-expected-bool.stderr
@@ -0,0 +1,151 @@
+error[E0308]: mismatched types
+  --> $DIR/assignment-expected-bool.rs:6:19
+   |
+LL |     let _: bool = 0 = 0;
+   |                   ^^^^^
+   |                   |
+   |                   expected bool, found ()
+   |                   help: try comparing for equality: `0 == 0`
+   |
+   = note: expected type `bool`
+              found type `()`
+
+error[E0308]: mismatched types
+  --> $DIR/assignment-expected-bool.rs:9:14
+   |
+LL |         0 => 0 = 0,
+   |              ^^^^^
+   |              |
+   |              expected bool, found ()
+   |              help: try comparing for equality: `0 == 0`
+   |
+   = note: expected type `bool`
+              found type `()`
+
+error[E0308]: mismatched types
+  --> $DIR/assignment-expected-bool.rs:10:14
+   |
+LL |         _ => 0 = 0,
+   |              ^^^^^
+   |              |
+   |              expected bool, found ()
+   |              help: try comparing for equality: `0 == 0`
+   |
+   = note: expected type `bool`
+              found type `()`
+
+error[E0308]: mismatched types
+  --> $DIR/assignment-expected-bool.rs:14:17
+   |
+LL |         true => 0 = 0,
+   |                 ^^^^^
+   |                 |
+   |                 expected bool, found ()
+   |                 help: try comparing for equality: `0 == 0`
+   |
+   = note: expected type `bool`
+              found type `()`
+
+error[E0308]: mismatched types
+  --> $DIR/assignment-expected-bool.rs:18:8
+   |
+LL |     if 0 = 0 {}
+   |        ^^^^^
+   |        |
+   |        expected bool, found ()
+   |        help: try comparing for equality: `0 == 0`
+   |
+   = note: expected type `bool`
+              found type `()`
+
+error[E0308]: mismatched types
+  --> $DIR/assignment-expected-bool.rs:20:24
+   |
+LL |     let _: bool = if { 0 = 0 } {
+   |                        ^^^^^
+   |                        |
+   |                        expected bool, found ()
+   |                        help: try comparing for equality: `0 == 0`
+   |
+   = note: expected type `bool`
+              found type `()`
+
+error[E0308]: mismatched types
+  --> $DIR/assignment-expected-bool.rs:21:9
+   |
+LL |         0 = 0
+   |         ^^^^^
+   |         |
+   |         expected bool, found ()
+   |         help: try comparing for equality: `0 == 0`
+   |
+   = note: expected type `bool`
+              found type `()`
+
+error[E0308]: mismatched types
+  --> $DIR/assignment-expected-bool.rs:23:9
+   |
+LL |         0 = 0
+   |         ^^^^^
+   |         |
+   |         expected bool, found ()
+   |         help: try comparing for equality: `0 == 0`
+   |
+   = note: expected type `bool`
+              found type `()`
+
+error[E0308]: mismatched types
+  --> $DIR/assignment-expected-bool.rs:26:13
+   |
+LL |     let _ = (0 = 0)
+   |             ^^^^^^^
+   |             |
+   |             expected bool, found ()
+   |             help: try comparing for equality: `0 == 0`
+   |
+   = note: expected type `bool`
+              found type `()`
+
+error[E0308]: mismatched types
+  --> $DIR/assignment-expected-bool.rs:27:14
+   |
+LL |         && { 0 = 0 }
+   |              ^^^^^
+   |              |
+   |              expected bool, found ()
+   |              help: try comparing for equality: `0 == 0`
+   |
+   = note: expected type `bool`
+              found type `()`
+
+error[E0308]: mismatched types
+  --> $DIR/assignment-expected-bool.rs:28:12
+   |
+LL |         || (0 = 0);
+   |            ^^^^^^^
+   |            |
+   |            expected bool, found ()
+   |            help: try comparing for equality: `0 == 0`
+   |
+   = note: expected type `bool`
+              found type `()`
+
+error[E0070]: invalid left-hand side expression
+  --> $DIR/assignment-expected-bool.rs:31:20
+   |
+LL |     let _: usize = 0 = 0;
+   |                    ^^^^^ left-hand of expression not valid
+
+error[E0308]: mismatched types
+  --> $DIR/assignment-expected-bool.rs:31:20
+   |
+LL |     let _: usize = 0 = 0;
+   |                    ^^^^^ expected usize, found ()
+   |
+   = note: expected type `usize`
+              found type `()`
+
+error: aborting due to 13 previous errors
+
+Some errors occurred: E0070, E0308.
+For more information about an error, try `rustc --explain E0070`.
diff --git a/src/test/ui/type/type-check/assignment-in-if.rs b/src/test/ui/type/type-check/assignment-in-if.rs
new file mode 100644
index 0000000..77b122b
--- /dev/null
+++ b/src/test/ui/type/type-check/assignment-in-if.rs
@@ -0,0 +1,43 @@
+// Test that the parser does not attempt to parse struct literals
+// within assignments in if expressions.
+
+#![allow(unused_parens)]
+
+struct Foo {
+    foo: usize
+}
+
+fn main() {
+    let x = 1;
+    let y: Foo;
+
+    // `x { ... }` should not be interpreted as a struct literal here
+    if x = x {
+        //~^ ERROR mismatched types
+        println!("{}", x);
+    }
+    // Explicit parentheses on the left should match behavior of above
+    if (x = x) {
+        //~^ ERROR mismatched types
+        println!("{}", x);
+    }
+    // The struct literal interpretation is fine with explicit parentheses on the right
+    if y = (Foo { foo: x }) {
+        //~^ ERROR mismatched types
+        println!("{}", x);
+    }
+    // "invalid left-hand side expression" error is suppresed
+    if 3 = x {
+        //~^ ERROR mismatched types
+        println!("{}", x);
+    }
+    if (
+        if true {
+            x = 4 //~ ERROR mismatched types
+        } else {
+            x = 5 //~ ERROR mismatched types
+        }
+    ) {
+        println!("{}", x);
+    }
+}
diff --git a/src/test/ui/type/type-check/assignment-in-if.stderr b/src/test/ui/type/type-check/assignment-in-if.stderr
new file mode 100644
index 0000000..87b8d17
--- /dev/null
+++ b/src/test/ui/type/type-check/assignment-in-if.stderr
@@ -0,0 +1,75 @@
+error[E0308]: mismatched types
+  --> $DIR/assignment-in-if.rs:15:8
+   |
+LL |     if x = x {
+   |        ^^^^^
+   |        |
+   |        expected bool, found ()
+   |        help: try comparing for equality: `x == x`
+   |
+   = note: expected type `bool`
+              found type `()`
+
+error[E0308]: mismatched types
+  --> $DIR/assignment-in-if.rs:20:8
+   |
+LL |     if (x = x) {
+   |        ^^^^^^^
+   |        |
+   |        expected bool, found ()
+   |        help: try comparing for equality: `x == x`
+   |
+   = note: expected type `bool`
+              found type `()`
+
+error[E0308]: mismatched types
+  --> $DIR/assignment-in-if.rs:25:8
+   |
+LL |     if y = (Foo { foo: x }) {
+   |        ^^^^^^^^^^^^^^^^^^^^
+   |        |
+   |        expected bool, found ()
+   |        help: try comparing for equality: `y == (Foo { foo: x })`
+   |
+   = note: expected type `bool`
+              found type `()`
+
+error[E0308]: mismatched types
+  --> $DIR/assignment-in-if.rs:30:8
+   |
+LL |     if 3 = x {
+   |        ^^^^^
+   |        |
+   |        expected bool, found ()
+   |        help: try comparing for equality: `3 == x`
+   |
+   = note: expected type `bool`
+              found type `()`
+
+error[E0308]: mismatched types
+  --> $DIR/assignment-in-if.rs:36:13
+   |
+LL |             x = 4
+   |             ^^^^^
+   |             |
+   |             expected bool, found ()
+   |             help: try comparing for equality: `x == 4`
+   |
+   = note: expected type `bool`
+              found type `()`
+
+error[E0308]: mismatched types
+  --> $DIR/assignment-in-if.rs:38:13
+   |
+LL |             x = 5
+   |             ^^^^^
+   |             |
+   |             expected bool, found ()
+   |             help: try comparing for equality: `x == 5`
+   |
+   = note: expected type `bool`
+              found type `()`
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/type/type-check/cannot_infer_local_or_array.rs b/src/test/ui/type/type-check/cannot_infer_local_or_array.rs
new file mode 100644
index 0000000..af75525
--- /dev/null
+++ b/src/test/ui/type/type-check/cannot_infer_local_or_array.rs
@@ -0,0 +1,3 @@
+fn main() {
+    let x = []; //~ ERROR type annotations needed
+}
diff --git a/src/test/ui/type/type-check/cannot_infer_local_or_array.stderr b/src/test/ui/type/type-check/cannot_infer_local_or_array.stderr
new file mode 100644
index 0000000..17be67c
--- /dev/null
+++ b/src/test/ui/type/type-check/cannot_infer_local_or_array.stderr
@@ -0,0 +1,11 @@
+error[E0282]: type annotations needed
+  --> $DIR/cannot_infer_local_or_array.rs:2:13
+   |
+LL |     let x = [];
+   |         -   ^^ cannot infer type
+   |         |
+   |         consider giving `x` a type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/type/type-check/cannot_infer_local_or_vec.rs b/src/test/ui/type/type-check/cannot_infer_local_or_vec.rs
new file mode 100644
index 0000000..e72ddab
--- /dev/null
+++ b/src/test/ui/type/type-check/cannot_infer_local_or_vec.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let x = vec![];
+    //~^ ERROR type annotations needed
+}
diff --git a/src/test/ui/type/type-check/cannot_infer_local_or_vec.stderr b/src/test/ui/type/type-check/cannot_infer_local_or_vec.stderr
new file mode 100644
index 0000000..8215947
--- /dev/null
+++ b/src/test/ui/type/type-check/cannot_infer_local_or_vec.stderr
@@ -0,0 +1,13 @@
+error[E0282]: type annotations needed
+  --> $DIR/cannot_infer_local_or_vec.rs:2:13
+   |
+LL |     let x = vec![];
+   |         -   ^^^^^^ cannot infer type for `T`
+   |         |
+   |         consider giving `x` a type
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/type/type-check/cannot_infer_local_or_vec_in_tuples.rs b/src/test/ui/type/type-check/cannot_infer_local_or_vec_in_tuples.rs
new file mode 100644
index 0000000..d214564
--- /dev/null
+++ b/src/test/ui/type/type-check/cannot_infer_local_or_vec_in_tuples.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let (x, ) = (vec![], );
+    //~^ ERROR type annotations needed
+}
diff --git a/src/test/ui/type/type-check/cannot_infer_local_or_vec_in_tuples.stderr b/src/test/ui/type/type-check/cannot_infer_local_or_vec_in_tuples.stderr
new file mode 100644
index 0000000..1065d49
--- /dev/null
+++ b/src/test/ui/type/type-check/cannot_infer_local_or_vec_in_tuples.stderr
@@ -0,0 +1,13 @@
+error[E0282]: type annotations needed
+  --> $DIR/cannot_infer_local_or_vec_in_tuples.rs:2:18
+   |
+LL |     let (x, ) = (vec![], );
+   |         -----    ^^^^^^ cannot infer type for `T`
+   |         |
+   |         consider giving the pattern a type
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/type/type-check/issue-22897.rs b/src/test/ui/type/type-check/issue-22897.rs
new file mode 100644
index 0000000..8171a0e
--- /dev/null
+++ b/src/test/ui/type/type-check/issue-22897.rs
@@ -0,0 +1,5 @@
+fn main() { }
+
+fn unconstrained_type() {
+    []; //~ ERROR type annotations needed
+}
diff --git a/src/test/ui/type/type-check/issue-22897.stderr b/src/test/ui/type/type-check/issue-22897.stderr
new file mode 100644
index 0000000..2b3f069
--- /dev/null
+++ b/src/test/ui/type/type-check/issue-22897.stderr
@@ -0,0 +1,9 @@
+error[E0282]: type annotations needed
+  --> $DIR/issue-22897.rs:4:5
+   |
+LL |     [];
+   |     ^^ cannot infer type for `[_; 0]`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/type/type-check/issue-40294.rs b/src/test/ui/type/type-check/issue-40294.rs
new file mode 100644
index 0000000..c73acdc
--- /dev/null
+++ b/src/test/ui/type/type-check/issue-40294.rs
@@ -0,0 +1,13 @@
+trait Foo: Sized {
+    fn foo(self);
+}
+
+fn foo<'a,'b,T>(x: &'a T, y: &'b T) //~ ERROR type annotations required
+    where &'a T : Foo,
+          &'b T : Foo
+{
+    x.foo();
+    y.foo();
+}
+
+fn main() { }
diff --git a/src/test/ui/type/type-check/issue-40294.stderr b/src/test/ui/type/type-check/issue-40294.stderr
new file mode 100644
index 0000000..254875f
--- /dev/null
+++ b/src/test/ui/type/type-check/issue-40294.stderr
@@ -0,0 +1,21 @@
+error[E0283]: type annotations required: cannot resolve `&'a T: Foo`
+  --> $DIR/issue-40294.rs:5:1
+   |
+LL | / fn foo<'a,'b,T>(x: &'a T, y: &'b T)
+LL | |     where &'a T : Foo,
+LL | |           &'b T : Foo
+LL | | {
+LL | |     x.foo();
+LL | |     y.foo();
+LL | | }
+   | |_^
+   |
+note: required by `Foo`
+  --> $DIR/issue-40294.rs:1:1
+   |
+LL | trait Foo: Sized {
+   | ^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0283`.
diff --git a/src/test/ui/type/type-check/issue-41314.rs b/src/test/ui/type/type-check/issue-41314.rs
new file mode 100644
index 0000000..856d4ff
--- /dev/null
+++ b/src/test/ui/type/type-check/issue-41314.rs
@@ -0,0 +1,10 @@
+enum X {
+    Y(u32)
+}
+
+fn main() {
+    match X::Y(0) {
+        X::Y { number } => {} //~ ERROR does not have a field named `number`
+        //~^ ERROR pattern does not mention field `0`
+    }
+}
diff --git a/src/test/ui/type/type-check/issue-41314.stderr b/src/test/ui/type/type-check/issue-41314.stderr
new file mode 100644
index 0000000..3461ab4
--- /dev/null
+++ b/src/test/ui/type/type-check/issue-41314.stderr
@@ -0,0 +1,18 @@
+error[E0026]: variant `X::Y` does not have a field named `number`
+  --> $DIR/issue-41314.rs:7:16
+   |
+LL |         X::Y { number } => {}
+   |                ^^^^^^ variant `X::Y` does not have this field
+
+error[E0027]: pattern does not mention field `0`
+  --> $DIR/issue-41314.rs:7:9
+   |
+LL |         X::Y { number } => {}
+   |         ^^^^^^^^^^^^^^^ missing field `0`
+   |
+   = note: trying to match a tuple variant with a struct variant pattern
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0026, E0027.
+For more information about an error, try `rustc --explain E0026`.
diff --git a/src/test/ui/type/type-check/missing_trait_impl.rs b/src/test/ui/type/type-check/missing_trait_impl.rs
new file mode 100644
index 0000000..dcca96b
--- /dev/null
+++ b/src/test/ui/type/type-check/missing_trait_impl.rs
@@ -0,0 +1,10 @@
+fn main() {
+}
+
+fn foo<T>(x: T, y: T) {
+    let z = x + y; //~ ERROR binary operation `+` cannot be applied to type `T`
+}
+
+fn bar<T>(x: T) {
+    x += x; //~ ERROR binary assignment operation `+=` cannot be applied to type `T`
+}
diff --git a/src/test/ui/type/type-check/missing_trait_impl.stderr b/src/test/ui/type/type-check/missing_trait_impl.stderr
new file mode 100644
index 0000000..b0e3c35
--- /dev/null
+++ b/src/test/ui/type/type-check/missing_trait_impl.stderr
@@ -0,0 +1,24 @@
+error[E0369]: binary operation `+` cannot be applied to type `T`
+  --> $DIR/missing_trait_impl.rs:5:15
+   |
+LL |     let z = x + y;
+   |             - ^ - T
+   |             |
+   |             T
+   |
+   = note: `T` might need a bound for `std::ops::Add`
+
+error[E0368]: binary assignment operation `+=` cannot be applied to type `T`
+  --> $DIR/missing_trait_impl.rs:9:5
+   |
+LL |     x += x;
+   |     -^^^^^
+   |     |
+   |     cannot use `+=` on type `T`
+   |
+   = note: `T` might need a bound for `std::ops::AddAssign`
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0368, E0369.
+For more information about an error, try `rustc --explain E0368`.
diff --git a/src/test/ui/type/type-check/unknown_type_for_closure.rs b/src/test/ui/type/type-check/unknown_type_for_closure.rs
new file mode 100644
index 0000000..0dbf8245
--- /dev/null
+++ b/src/test/ui/type/type-check/unknown_type_for_closure.rs
@@ -0,0 +1,3 @@
+fn main() {
+    let x = |_| {    }; //~ ERROR type annotations needed
+}
diff --git a/src/test/ui/type/type-check/unknown_type_for_closure.stderr b/src/test/ui/type/type-check/unknown_type_for_closure.stderr
new file mode 100644
index 0000000..5971f56
--- /dev/null
+++ b/src/test/ui/type/type-check/unknown_type_for_closure.stderr
@@ -0,0 +1,9 @@
+error[E0282]: type annotations needed
+  --> $DIR/unknown_type_for_closure.rs:2:14
+   |
+LL |     let x = |_| {    };
+   |              ^ consider giving this closure parameter a type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/type/type-dependent-def-issue-49241.rs b/src/test/ui/type/type-dependent-def-issue-49241.rs
new file mode 100644
index 0000000..51bd116
--- /dev/null
+++ b/src/test/ui/type/type-dependent-def-issue-49241.rs
@@ -0,0 +1,6 @@
+fn main() {
+    let v = vec![0];
+    const l: usize = v.count(); //~ ERROR attempt to use a non-constant value in a constant
+    let s: [u32; l] = v.into_iter().collect();
+    //~^ ERROR evaluation of constant value failed
+}
diff --git a/src/test/ui/type/type-dependent-def-issue-49241.stderr b/src/test/ui/type/type-dependent-def-issue-49241.stderr
new file mode 100644
index 0000000..5040b72
--- /dev/null
+++ b/src/test/ui/type/type-dependent-def-issue-49241.stderr
@@ -0,0 +1,16 @@
+error[E0435]: attempt to use a non-constant value in a constant
+  --> $DIR/type-dependent-def-issue-49241.rs:3:22
+   |
+LL |     const l: usize = v.count();
+   |                      ^ non-constant value
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/type-dependent-def-issue-49241.rs:4:18
+   |
+LL |     let s: [u32; l] = v.into_iter().collect();
+   |                  ^ referenced constant has errors
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0080, E0435.
+For more information about an error, try `rustc --explain E0080`.
diff --git a/src/test/ui/type/type-mismatch-multiple.rs b/src/test/ui/type/type-mismatch-multiple.rs
new file mode 100644
index 0000000..1904ccf
--- /dev/null
+++ b/src/test/ui/type/type-mismatch-multiple.rs
@@ -0,0 +1,10 @@
+// Checking that the compiler reports multiple type errors at once
+
+fn main() { let a: bool = 1; let b: i32 = true; }
+//~^ ERROR mismatched types
+//~| expected type `bool`
+//~| found type `{integer}`
+//~| expected bool, found integer
+//~| ERROR mismatched types
+//~| expected i32, found bool
+
diff --git a/src/test/ui/type/type-mismatch-multiple.stderr b/src/test/ui/type/type-mismatch-multiple.stderr
new file mode 100644
index 0000000..8f6b23e
--- /dev/null
+++ b/src/test/ui/type/type-mismatch-multiple.stderr
@@ -0,0 +1,18 @@
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch-multiple.rs:3:27
+   |
+LL | fn main() { let a: bool = 1; let b: i32 = true; }
+   |                           ^ expected bool, found integer
+   |
+   = note: expected type `bool`
+              found type `{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch-multiple.rs:3:43
+   |
+LL | fn main() { let a: bool = 1; let b: i32 = true; }
+   |                                           ^^^^ expected i32, found bool
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/type/type-mismatch-same-crate-name.rs b/src/test/ui/type/type-mismatch-same-crate-name.rs
new file mode 100644
index 0000000..61e6bd21
--- /dev/null
+++ b/src/test/ui/type/type-mismatch-same-crate-name.rs
@@ -0,0 +1,29 @@
+// aux-build:crate_a1.rs
+// aux-build:crate_a2.rs
+
+// This tests the extra note reported when a type error deals with
+// seemingly identical types.
+// The main use case of this error is when there are two crates
+// (generally different versions of the same crate) with the same name
+// causing a type mismatch. Here, we simulate that error using block-scoped
+// aliased `extern crate` declarations.
+
+fn main() {
+    let foo2 = {extern crate crate_a2 as a; a::Foo};
+    let bar2 = {extern crate crate_a2 as a; a::bar()};
+    {
+        extern crate crate_a1 as a;
+        a::try_foo(foo2);
+        //~^ ERROR mismatched types
+        //~| Perhaps two different versions of crate `crate_a1`
+        //~| expected struct `main::a::Foo`
+        //~| expected type `main::a::Foo`
+        //~| found type `main::a::Foo`
+        a::try_bar(bar2);
+        //~^ ERROR mismatched types
+        //~| Perhaps two different versions of crate `crate_a1`
+        //~| expected trait `main::a::Bar`
+        //~| expected type `std::boxed::Box<(dyn main::a::Bar + 'static)>`
+        //~| found type `std::boxed::Box<dyn main::a::Bar>`
+    }
+}
diff --git a/src/test/ui/type/type-mismatch-same-crate-name.stderr b/src/test/ui/type/type-mismatch-same-crate-name.stderr
new file mode 100644
index 0000000..ed07b60
--- /dev/null
+++ b/src/test/ui/type/type-mismatch-same-crate-name.stderr
@@ -0,0 +1,31 @@
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch-same-crate-name.rs:16:20
+   |
+LL |         a::try_foo(foo2);
+   |                    ^^^^ expected struct `main::a::Foo`, found a different struct `main::a::Foo`
+   |
+   = note: expected type `main::a::Foo` (struct `main::a::Foo`)
+              found type `main::a::Foo` (struct `main::a::Foo`)
+note: Perhaps two different versions of crate `crate_a1` are being used?
+  --> $DIR/type-mismatch-same-crate-name.rs:16:20
+   |
+LL |         a::try_foo(foo2);
+   |                    ^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch-same-crate-name.rs:22:20
+   |
+LL |         a::try_bar(bar2);
+   |                    ^^^^ expected trait `main::a::Bar`, found a different trait `main::a::Bar`
+   |
+   = note: expected type `std::boxed::Box<(dyn main::a::Bar + 'static)>`
+              found type `std::boxed::Box<dyn main::a::Bar>`
+note: Perhaps two different versions of crate `crate_a1` are being used?
+  --> $DIR/type-mismatch-same-crate-name.rs:22:20
+   |
+LL |         a::try_bar(bar2);
+   |                    ^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/type/type-mismatch.rs b/src/test/ui/type/type-mismatch.rs
new file mode 100644
index 0000000..11bfa3a
--- /dev/null
+++ b/src/test/ui/type/type-mismatch.rs
@@ -0,0 +1,78 @@
+#![allow(non_camel_case_types)]
+
+trait Qux {}
+struct A;
+struct B;
+impl Qux for A {}
+impl Qux for B {}
+
+struct Foo<T, U: Qux = A, V: Qux = B>(T, U, V);
+
+struct foo;
+struct bar;
+
+fn want<T>(t: T) {}
+
+fn have_usize(f: usize) {
+    want::<foo>(f); //~ ERROR mismatched types
+    want::<bar>(f); //~ ERROR mismatched types
+    want::<Foo<usize>>(f); //~ ERROR mismatched types
+    want::<Foo<usize, B>>(f); //~ ERROR mismatched types
+    want::<Foo<foo>>(f); //~ ERROR mismatched types
+    want::<Foo<foo, B>>(f); //~ ERROR mismatched types
+    want::<Foo<bar>>(f); //~ ERROR mismatched types
+    want::<Foo<bar, B>>(f); //~ ERROR mismatched types
+}
+
+fn have_foo(f: foo) {
+    want::<usize>(f); //~ ERROR mismatched types
+    want::<bar>(f); //~ ERROR mismatched types
+    want::<Foo<usize>>(f); //~ ERROR mismatched types
+    want::<Foo<usize, B>>(f); //~ ERROR mismatched types
+    want::<Foo<foo>>(f); //~ ERROR mismatched types
+    want::<Foo<foo, B>>(f); //~ ERROR mismatched types
+    want::<Foo<bar>>(f); //~ ERROR mismatched types
+    want::<Foo<bar, B>>(f); //~ ERROR mismatched types
+}
+
+fn have_foo_foo(f: Foo<foo>) {
+    want::<usize>(f); //~ ERROR mismatched types
+    want::<foo>(f); //~ ERROR mismatched types
+    want::<bar>(f); //~ ERROR mismatched types
+    want::<Foo<usize>>(f); //~ ERROR mismatched types
+    want::<Foo<usize, B>>(f); //~ ERROR mismatched types
+    want::<Foo<foo, B>>(f); //~ ERROR mismatched types
+    want::<Foo<bar>>(f); //~ ERROR mismatched types
+    want::<Foo<bar, B>>(f); //~ ERROR mismatched types
+    want::<&Foo<foo>>(f); //~ ERROR mismatched types
+    want::<&Foo<foo, B>>(f); //~ ERROR mismatched types
+}
+
+fn have_foo_foo_b(f: Foo<foo, B>) {
+    want::<usize>(f); //~ ERROR mismatched types
+    want::<foo>(f); //~ ERROR mismatched types
+    want::<bar>(f); //~ ERROR mismatched types
+    want::<Foo<usize>>(f); //~ ERROR mismatched types
+    want::<Foo<usize, B>>(f); //~ ERROR mismatched types
+    want::<Foo<foo>>(f); //~ ERROR mismatched types
+    want::<Foo<bar>>(f); //~ ERROR mismatched types
+    want::<Foo<bar, B>>(f); //~ ERROR mismatched types
+    want::<&Foo<foo>>(f); //~ ERROR mismatched types
+    want::<&Foo<foo, B>>(f); //~ ERROR mismatched types
+}
+
+fn have_foo_foo_b_a(f: Foo<foo, B, A>) {
+    want::<usize>(f); //~ ERROR mismatched types
+    want::<foo>(f); //~ ERROR mismatched types
+    want::<bar>(f); //~ ERROR mismatched types
+    want::<Foo<usize>>(f); //~ ERROR mismatched types
+    want::<Foo<usize, B>>(f); //~ ERROR mismatched types
+    want::<Foo<foo>>(f); //~ ERROR mismatched types
+    want::<Foo<foo, B>>(f); //~ ERROR mismatched types
+    want::<Foo<bar>>(f); //~ ERROR mismatched types
+    want::<Foo<bar, B>>(f); //~ ERROR mismatched types
+    want::<&Foo<foo>>(f); //~ ERROR mismatched types
+    want::<&Foo<foo, B>>(f); //~ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/src/test/ui/type/type-mismatch.stderr b/src/test/ui/type/type-mismatch.stderr
new file mode 100644
index 0000000..7aea9db
--- /dev/null
+++ b/src/test/ui/type/type-mismatch.stderr
@@ -0,0 +1,432 @@
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch.rs:17:17
+   |
+LL |     want::<foo>(f);
+   |                 ^ expected struct `foo`, found usize
+   |
+   = note: expected type `foo`
+              found type `usize`
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch.rs:18:17
+   |
+LL |     want::<bar>(f);
+   |                 ^ expected struct `bar`, found usize
+   |
+   = note: expected type `bar`
+              found type `usize`
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch.rs:19:24
+   |
+LL |     want::<Foo<usize>>(f);
+   |                        ^ expected struct `Foo`, found usize
+   |
+   = note: expected type `Foo<usize>`
+              found type `usize`
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch.rs:20:27
+   |
+LL |     want::<Foo<usize, B>>(f);
+   |                           ^ expected struct `Foo`, found usize
+   |
+   = note: expected type `Foo<usize, B>`
+              found type `usize`
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch.rs:21:22
+   |
+LL |     want::<Foo<foo>>(f);
+   |                      ^ expected struct `Foo`, found usize
+   |
+   = note: expected type `Foo<foo>`
+              found type `usize`
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch.rs:22:25
+   |
+LL |     want::<Foo<foo, B>>(f);
+   |                         ^ expected struct `Foo`, found usize
+   |
+   = note: expected type `Foo<foo, B>`
+              found type `usize`
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch.rs:23:22
+   |
+LL |     want::<Foo<bar>>(f);
+   |                      ^ expected struct `Foo`, found usize
+   |
+   = note: expected type `Foo<bar>`
+              found type `usize`
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch.rs:24:25
+   |
+LL |     want::<Foo<bar, B>>(f);
+   |                         ^ expected struct `Foo`, found usize
+   |
+   = note: expected type `Foo<bar, B>`
+              found type `usize`
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch.rs:28:19
+   |
+LL |     want::<usize>(f);
+   |                   ^ expected usize, found struct `foo`
+   |
+   = note: expected type `usize`
+              found type `foo`
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch.rs:29:17
+   |
+LL |     want::<bar>(f);
+   |                 ^ expected struct `bar`, found struct `foo`
+   |
+   = note: expected type `bar`
+              found type `foo`
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch.rs:30:24
+   |
+LL |     want::<Foo<usize>>(f);
+   |                        ^ expected struct `Foo`, found struct `foo`
+   |
+   = note: expected type `Foo<usize>`
+              found type `foo`
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch.rs:31:27
+   |
+LL |     want::<Foo<usize, B>>(f);
+   |                           ^ expected struct `Foo`, found struct `foo`
+   |
+   = note: expected type `Foo<usize, B>`
+              found type `foo`
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch.rs:32:22
+   |
+LL |     want::<Foo<foo>>(f);
+   |                      ^ expected struct `Foo`, found struct `foo`
+   |
+   = note: expected type `Foo<foo>`
+              found type `foo`
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch.rs:33:25
+   |
+LL |     want::<Foo<foo, B>>(f);
+   |                         ^ expected struct `Foo`, found struct `foo`
+   |
+   = note: expected type `Foo<foo, B>`
+              found type `foo`
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch.rs:34:22
+   |
+LL |     want::<Foo<bar>>(f);
+   |                      ^ expected struct `Foo`, found struct `foo`
+   |
+   = note: expected type `Foo<bar>`
+              found type `foo`
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch.rs:35:25
+   |
+LL |     want::<Foo<bar, B>>(f);
+   |                         ^ expected struct `Foo`, found struct `foo`
+   |
+   = note: expected type `Foo<bar, B>`
+              found type `foo`
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch.rs:39:19
+   |
+LL |     want::<usize>(f);
+   |                   ^ expected usize, found struct `Foo`
+   |
+   = note: expected type `usize`
+              found type `Foo<foo>`
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch.rs:40:17
+   |
+LL |     want::<foo>(f);
+   |                 ^ expected struct `foo`, found struct `Foo`
+   |
+   = note: expected type `foo`
+              found type `Foo<foo>`
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch.rs:41:17
+   |
+LL |     want::<bar>(f);
+   |                 ^ expected struct `bar`, found struct `Foo`
+   |
+   = note: expected type `bar`
+              found type `Foo<foo>`
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch.rs:42:24
+   |
+LL |     want::<Foo<usize>>(f);
+   |                        ^ expected usize, found struct `foo`
+   |
+   = note: expected type `Foo<usize>`
+              found type `Foo<foo>`
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch.rs:43:27
+   |
+LL |     want::<Foo<usize, B>>(f);
+   |                           ^ expected usize, found struct `foo`
+   |
+   = note: expected type `Foo<usize, B>`
+              found type `Foo<foo, A>`
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch.rs:44:25
+   |
+LL |     want::<Foo<foo, B>>(f);
+   |                         ^ expected struct `B`, found struct `A`
+   |
+   = note: expected type `Foo<_, B>`
+              found type `Foo<_, A>`
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch.rs:45:22
+   |
+LL |     want::<Foo<bar>>(f);
+   |                      ^ expected struct `bar`, found struct `foo`
+   |
+   = note: expected type `Foo<bar>`
+              found type `Foo<foo>`
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch.rs:46:25
+   |
+LL |     want::<Foo<bar, B>>(f);
+   |                         ^ expected struct `bar`, found struct `foo`
+   |
+   = note: expected type `Foo<bar, B>`
+              found type `Foo<foo, A>`
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch.rs:47:23
+   |
+LL |     want::<&Foo<foo>>(f);
+   |                       ^
+   |                       |
+   |                       expected &Foo<foo>, found struct `Foo`
+   |                       help: consider borrowing here: `&f`
+   |
+   = note: expected type `&Foo<foo>`
+              found type `Foo<foo>`
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch.rs:48:26
+   |
+LL |     want::<&Foo<foo, B>>(f);
+   |                          ^ expected reference, found struct `Foo`
+   |
+   = note: expected type `&Foo<foo, B>`
+              found type `Foo<foo>`
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch.rs:52:19
+   |
+LL |     want::<usize>(f);
+   |                   ^ expected usize, found struct `Foo`
+   |
+   = note: expected type `usize`
+              found type `Foo<foo, B>`
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch.rs:53:17
+   |
+LL |     want::<foo>(f);
+   |                 ^ expected struct `foo`, found struct `Foo`
+   |
+   = note: expected type `foo`
+              found type `Foo<foo, B>`
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch.rs:54:17
+   |
+LL |     want::<bar>(f);
+   |                 ^ expected struct `bar`, found struct `Foo`
+   |
+   = note: expected type `bar`
+              found type `Foo<foo, B>`
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch.rs:55:24
+   |
+LL |     want::<Foo<usize>>(f);
+   |                        ^ expected usize, found struct `foo`
+   |
+   = note: expected type `Foo<usize, A>`
+              found type `Foo<foo, B>`
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch.rs:56:27
+   |
+LL |     want::<Foo<usize, B>>(f);
+   |                           ^ expected usize, found struct `foo`
+   |
+   = note: expected type `Foo<usize, _>`
+              found type `Foo<foo, _>`
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch.rs:57:22
+   |
+LL |     want::<Foo<foo>>(f);
+   |                      ^ expected struct `A`, found struct `B`
+   |
+   = note: expected type `Foo<_, A>`
+              found type `Foo<_, B>`
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch.rs:58:22
+   |
+LL |     want::<Foo<bar>>(f);
+   |                      ^ expected struct `bar`, found struct `foo`
+   |
+   = note: expected type `Foo<bar, A>`
+              found type `Foo<foo, B>`
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch.rs:59:25
+   |
+LL |     want::<Foo<bar, B>>(f);
+   |                         ^ expected struct `bar`, found struct `foo`
+   |
+   = note: expected type `Foo<bar, _>`
+              found type `Foo<foo, _>`
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch.rs:60:23
+   |
+LL |     want::<&Foo<foo>>(f);
+   |                       ^ expected &Foo<foo>, found struct `Foo`
+   |
+   = note: expected type `&Foo<foo>`
+              found type `Foo<foo, B>`
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch.rs:61:26
+   |
+LL |     want::<&Foo<foo, B>>(f);
+   |                          ^
+   |                          |
+   |                          expected reference, found struct `Foo`
+   |                          help: consider borrowing here: `&f`
+   |
+   = note: expected type `&Foo<foo, B>`
+              found type `Foo<foo, B>`
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch.rs:65:19
+   |
+LL |     want::<usize>(f);
+   |                   ^ expected usize, found struct `Foo`
+   |
+   = note: expected type `usize`
+              found type `Foo<foo, B, A>`
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch.rs:66:17
+   |
+LL |     want::<foo>(f);
+   |                 ^ expected struct `foo`, found struct `Foo`
+   |
+   = note: expected type `foo`
+              found type `Foo<foo, B, A>`
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch.rs:67:17
+   |
+LL |     want::<bar>(f);
+   |                 ^ expected struct `bar`, found struct `Foo`
+   |
+   = note: expected type `bar`
+              found type `Foo<foo, B, A>`
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch.rs:68:24
+   |
+LL |     want::<Foo<usize>>(f);
+   |                        ^ expected usize, found struct `foo`
+   |
+   = note: expected type `Foo<usize, A, B>`
+              found type `Foo<foo, B, A>`
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch.rs:69:27
+   |
+LL |     want::<Foo<usize, B>>(f);
+   |                           ^ expected usize, found struct `foo`
+   |
+   = note: expected type `Foo<usize, _, B>`
+              found type `Foo<foo, _, A>`
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch.rs:70:22
+   |
+LL |     want::<Foo<foo>>(f);
+   |                      ^ expected struct `A`, found struct `B`
+   |
+   = note: expected type `Foo<_, A, B>`
+              found type `Foo<_, B, A>`
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch.rs:71:25
+   |
+LL |     want::<Foo<foo, B>>(f);
+   |                         ^ expected struct `B`, found struct `A`
+   |
+   = note: expected type `Foo<_, _, B>`
+              found type `Foo<_, _, A>`
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch.rs:72:22
+   |
+LL |     want::<Foo<bar>>(f);
+   |                      ^ expected struct `bar`, found struct `foo`
+   |
+   = note: expected type `Foo<bar, A, B>`
+              found type `Foo<foo, B, A>`
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch.rs:73:25
+   |
+LL |     want::<Foo<bar, B>>(f);
+   |                         ^ expected struct `bar`, found struct `foo`
+   |
+   = note: expected type `Foo<bar, _, B>`
+              found type `Foo<foo, _, A>`
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch.rs:74:23
+   |
+LL |     want::<&Foo<foo>>(f);
+   |                       ^ expected &Foo<foo>, found struct `Foo`
+   |
+   = note: expected type `&Foo<foo>`
+              found type `Foo<foo, B, A>`
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch.rs:75:26
+   |
+LL |     want::<&Foo<foo, B>>(f);
+   |                          ^ expected reference, found struct `Foo`
+   |
+   = note: expected type `&Foo<foo, B>`
+              found type `Foo<foo, B, A>`
+
+error: aborting due to 47 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/type/type-parameter-defaults-referencing-Self-ppaux.rs b/src/test/ui/type/type-parameter-defaults-referencing-Self-ppaux.rs
new file mode 100644
index 0000000..3e1c876
--- /dev/null
+++ b/src/test/ui/type/type-parameter-defaults-referencing-Self-ppaux.rs
@@ -0,0 +1,17 @@
+// Test a default that references `Self` which is then used in an
+// object type. Issue #18956. In this case, the value is supplied by
+// the user, but pretty-printing the type during the error message
+// caused an ICE.
+
+trait MyAdd<Rhs=Self> { fn add(&self, other: &Rhs) -> Self; }
+
+impl MyAdd for i32 {
+    fn add(&self, other: &i32) -> i32 { *self + *other }
+}
+
+fn main() {
+    let x: i32 = 5;
+    let y = x as MyAdd<i32>;
+    //~^ ERROR E0038
+    //~| ERROR cast to unsized type: `i32` as `dyn MyAdd<i32>`
+}
diff --git a/src/test/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr b/src/test/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr
new file mode 100644
index 0000000..7306929
--- /dev/null
+++ b/src/test/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr
@@ -0,0 +1,24 @@
+error[E0620]: cast to unsized type: `i32` as `dyn MyAdd<i32>`
+  --> $DIR/type-parameter-defaults-referencing-Self-ppaux.rs:14:13
+   |
+LL |     let y = x as MyAdd<i32>;
+   |             ^^^^^^^^^^^^^^^
+   |
+help: consider using a box or reference as appropriate
+  --> $DIR/type-parameter-defaults-referencing-Self-ppaux.rs:14:13
+   |
+LL |     let y = x as MyAdd<i32>;
+   |             ^
+
+error[E0038]: the trait `MyAdd` cannot be made into an object
+  --> $DIR/type-parameter-defaults-referencing-Self-ppaux.rs:14:18
+   |
+LL |     let y = x as MyAdd<i32>;
+   |                  ^^^^^^^^^^ the trait `MyAdd` cannot be made into an object
+   |
+   = note: method `add` references the `Self` type in its arguments or return type
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0038, E0620.
+For more information about an error, try `rustc --explain E0038`.
diff --git a/src/test/ui/type/type-parameter-defaults-referencing-Self.rs b/src/test/ui/type/type-parameter-defaults-referencing-Self.rs
new file mode 100644
index 0000000..721bf96
--- /dev/null
+++ b/src/test/ui/type/type-parameter-defaults-referencing-Self.rs
@@ -0,0 +1,13 @@
+// Test a default that references `Self` which is then used in an object type.
+// Issue #18956.
+
+#![feature(default_type_params)]
+
+trait Foo<T=Self> {
+    fn method(&self);
+}
+
+fn foo(x: &Foo) { }
+//~^ ERROR the type parameter `T` must be explicitly specified
+
+fn main() { }
diff --git a/src/test/ui/type/type-parameter-defaults-referencing-Self.stderr b/src/test/ui/type/type-parameter-defaults-referencing-Self.stderr
new file mode 100644
index 0000000..70093b6
--- /dev/null
+++ b/src/test/ui/type/type-parameter-defaults-referencing-Self.stderr
@@ -0,0 +1,11 @@
+error[E0393]: the type parameter `T` must be explicitly specified
+  --> $DIR/type-parameter-defaults-referencing-Self.rs:10:12
+   |
+LL | fn foo(x: &Foo) { }
+   |            ^^^ missing reference to `T`
+   |
+   = note: because of the default `Self` reference, type parameters must be specified on object types
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0393`.
diff --git a/src/test/ui/type/type-parameter-names.rs b/src/test/ui/type/type-parameter-names.rs
new file mode 100644
index 0000000..b6b3795
--- /dev/null
+++ b/src/test/ui/type/type-parameter-names.rs
@@ -0,0 +1,12 @@
+// Test that we print out the names of type parameters correctly in
+// our error messages.
+
+fn foo<Foo, Bar>(x: Foo) -> Bar {
+    x
+//~^ ERROR mismatched types
+//~| expected type `Bar`
+//~| found type `Foo`
+//~| expected type parameter, found a different type parameter
+}
+
+fn main() {}
diff --git a/src/test/ui/type/type-parameter-names.stderr b/src/test/ui/type/type-parameter-names.stderr
new file mode 100644
index 0000000..9acae5c
--- /dev/null
+++ b/src/test/ui/type/type-parameter-names.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/type-parameter-names.rs:5:5
+   |
+LL | fn foo<Foo, Bar>(x: Foo) -> Bar {
+   |                             --- expected `Bar` because of return type
+LL |     x
+   |     ^ expected type parameter, found a different type parameter
+   |
+   = note: expected type `Bar`
+              found type `Foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/type/type-params-in-different-spaces-1.rs b/src/test/ui/type/type-params-in-different-spaces-1.rs
new file mode 100644
index 0000000..449a26e
--- /dev/null
+++ b/src/test/ui/type/type-params-in-different-spaces-1.rs
@@ -0,0 +1,18 @@
+use std::ops::Add;
+
+trait BrokenAdd: Copy + Add<Output=Self> {
+    fn broken_add<T>(&self, rhs: T) -> Self {
+        *self + rhs //~  ERROR mismatched types
+                    //~| expected type `Self`
+                    //~| found type `T`
+                    //~| expected Self, found type parameter
+    }
+}
+
+impl<T: Copy + Add<Output=T>> BrokenAdd for T {}
+
+pub fn main() {
+    let foo: u8 = 0;
+    let x: u8 = foo.broken_add("hello darkness my old friend".to_string());
+    println!("{}", x);
+}
diff --git a/src/test/ui/type/type-params-in-different-spaces-1.stderr b/src/test/ui/type/type-params-in-different-spaces-1.stderr
new file mode 100644
index 0000000..b3b7842
--- /dev/null
+++ b/src/test/ui/type/type-params-in-different-spaces-1.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/type-params-in-different-spaces-1.rs:5:17
+   |
+LL |         *self + rhs
+   |                 ^^^ expected Self, found type parameter
+   |
+   = note: expected type `Self`
+              found type `T`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/type/type-params-in-different-spaces-2.rs b/src/test/ui/type/type-params-in-different-spaces-2.rs
new file mode 100644
index 0000000..1211e46
--- /dev/null
+++ b/src/test/ui/type/type-params-in-different-spaces-2.rs
@@ -0,0 +1,21 @@
+// Test static calls to make sure that we align the Self and input
+// type parameters on a trait correctly.
+
+trait Tr<T> : Sized {
+    fn op(_: T) -> Self;
+}
+
+trait A:    Tr<Self> {
+    fn test<U>(u: U) -> Self {
+        Tr::op(u)   //~ ERROR E0277
+    }
+}
+
+trait B<T>: Tr<T> {
+    fn test<U>(u: U) -> Self {
+        Tr::op(u)   //~ ERROR E0277
+    }
+}
+
+fn main() {
+}
diff --git a/src/test/ui/type/type-params-in-different-spaces-2.stderr b/src/test/ui/type/type-params-in-different-spaces-2.stderr
new file mode 100644
index 0000000..15db94e
--- /dev/null
+++ b/src/test/ui/type/type-params-in-different-spaces-2.stderr
@@ -0,0 +1,29 @@
+error[E0277]: the trait bound `Self: Tr<U>` is not satisfied
+  --> $DIR/type-params-in-different-spaces-2.rs:10:9
+   |
+LL |         Tr::op(u)
+   |         ^^^^^^ the trait `Tr<U>` is not implemented for `Self`
+   |
+   = help: consider adding a `where Self: Tr<U>` bound
+note: required by `Tr::op`
+  --> $DIR/type-params-in-different-spaces-2.rs:5:5
+   |
+LL |     fn op(_: T) -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `Self: Tr<U>` is not satisfied
+  --> $DIR/type-params-in-different-spaces-2.rs:16:9
+   |
+LL |         Tr::op(u)
+   |         ^^^^^^ the trait `Tr<U>` is not implemented for `Self`
+   |
+   = help: consider adding a `where Self: Tr<U>` bound
+note: required by `Tr::op`
+  --> $DIR/type-params-in-different-spaces-2.rs:5:5
+   |
+LL |     fn op(_: T) -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/type/type-params-in-different-spaces-3.rs b/src/test/ui/type/type-params-in-different-spaces-3.rs
new file mode 100644
index 0000000..ac7b0c1
--- /dev/null
+++ b/src/test/ui/type/type-params-in-different-spaces-3.rs
@@ -0,0 +1,7 @@
+trait Tr : Sized {
+    fn test<X>(u: X) -> Self {
+        u   //~ ERROR mismatched types
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/type/type-params-in-different-spaces-3.stderr b/src/test/ui/type/type-params-in-different-spaces-3.stderr
new file mode 100644
index 0000000..4e8134d
--- /dev/null
+++ b/src/test/ui/type/type-params-in-different-spaces-3.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/type-params-in-different-spaces-3.rs:3:9
+   |
+LL |     fn test<X>(u: X) -> Self {
+   |                         ---- expected `Self` because of return type
+LL |         u
+   |         ^ expected Self, found type parameter
+   |
+   = note: expected type `Self`
+              found type `X`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/type/type-path-err-node-types.rs b/src/test/ui/type/type-path-err-node-types.rs
new file mode 100644
index 0000000..a2cc507
--- /dev/null
+++ b/src/test/ui/type/type-path-err-node-types.rs
@@ -0,0 +1,26 @@
+// Type arguments in unresolved entities (reporting errors before type checking)
+// should have their types recorded.
+
+trait Tr<T> {}
+
+fn local_type() {
+    let _: Nonexistent<u8, Assoc = u16>; //~ ERROR cannot find type `Nonexistent` in this scope
+}
+
+fn ufcs_trait() {
+    <u8 as Tr<u8>>::nonexistent(); //~ ERROR cannot find method or associated constant `nonexistent`
+}
+
+fn ufcs_item() {
+    NonExistent::Assoc::<u8>; //~ ERROR undeclared type or module `NonExistent`
+}
+
+fn method() {
+    nonexistent.nonexistent::<u8>(); //~ ERROR cannot find value `nonexistent`
+}
+
+fn closure() {
+    let _ = |a, b: _| -> _ { 0 }; // OK
+}
+
+fn main() {}
diff --git a/src/test/ui/type/type-path-err-node-types.stderr b/src/test/ui/type/type-path-err-node-types.stderr
new file mode 100644
index 0000000..29a438a
--- /dev/null
+++ b/src/test/ui/type/type-path-err-node-types.stderr
@@ -0,0 +1,28 @@
+error[E0433]: failed to resolve: use of undeclared type or module `NonExistent`
+  --> $DIR/type-path-err-node-types.rs:15:5
+   |
+LL |     NonExistent::Assoc::<u8>;
+   |     ^^^^^^^^^^^ use of undeclared type or module `NonExistent`
+
+error[E0412]: cannot find type `Nonexistent` in this scope
+  --> $DIR/type-path-err-node-types.rs:7:12
+   |
+LL |     let _: Nonexistent<u8, Assoc = u16>;
+   |            ^^^^^^^^^^^ not found in this scope
+
+error[E0576]: cannot find method or associated constant `nonexistent` in trait `Tr`
+  --> $DIR/type-path-err-node-types.rs:11:21
+   |
+LL |     <u8 as Tr<u8>>::nonexistent();
+   |                     ^^^^^^^^^^^ not found in `Tr`
+
+error[E0425]: cannot find value `nonexistent` in this scope
+  --> $DIR/type-path-err-node-types.rs:19:5
+   |
+LL |     nonexistent.nonexistent::<u8>();
+   |     ^^^^^^^^^^^ not found in this scope
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0412, E0425, E0433, E0576.
+For more information about an error, try `rustc --explain E0412`.
diff --git a/src/test/ui/type/type-recursive.rs b/src/test/ui/type/type-recursive.rs
new file mode 100644
index 0000000..8558f76
--- /dev/null
+++ b/src/test/ui/type/type-recursive.rs
@@ -0,0 +1,6 @@
+struct T1 { //~ ERROR E0072
+    foo: isize,
+    foolish: T1
+}
+
+fn main() { }
diff --git a/src/test/ui/type/type-recursive.stderr b/src/test/ui/type/type-recursive.stderr
new file mode 100644
index 0000000..72bf372
--- /dev/null
+++ b/src/test/ui/type/type-recursive.stderr
@@ -0,0 +1,14 @@
+error[E0072]: recursive type `T1` has infinite size
+  --> $DIR/type-recursive.rs:1:1
+   |
+LL | struct T1 {
+   | ^^^^^^^^^ recursive type has infinite size
+LL |     foo: isize,
+LL |     foolish: T1
+   |     ----------- recursive without indirection
+   |
+   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `T1` representable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0072`.
diff --git a/src/test/ui/type/type-shadow.rs b/src/test/ui/type/type-shadow.rs
new file mode 100644
index 0000000..48a68a3
--- /dev/null
+++ b/src/test/ui/type/type-shadow.rs
@@ -0,0 +1,8 @@
+fn main() {
+    type X = isize;
+    type Y = X;
+    if true {
+        type X = &'static str;
+        let y: Y = "hello"; //~ ERROR mismatched types
+    }
+}
diff --git a/src/test/ui/type/type-shadow.stderr b/src/test/ui/type/type-shadow.stderr
new file mode 100644
index 0000000..f15bdc1
--- /dev/null
+++ b/src/test/ui/type/type-shadow.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/type-shadow.rs:6:20
+   |
+LL |         let y: Y = "hello";
+   |                    ^^^^^^^ expected isize, found reference
+   |
+   = note: expected type `isize`
+              found type `&'static str`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/type_length_limit.rs b/src/test/ui/type_length_limit.rs
new file mode 100644
index 0000000..cd15f81
--- /dev/null
+++ b/src/test/ui/type_length_limit.rs
@@ -0,0 +1,27 @@
+// ignore-musl
+// ignore-x86
+// error-pattern: reached the type-length limit while instantiating
+
+// Test that the type length limit can be changed.
+
+#![allow(dead_code)]
+#![type_length_limit="256"]
+
+macro_rules! link {
+    ($id:ident, $t:ty) => {
+        pub type $id = ($t, $t, $t);
+    }
+}
+
+link! { A, B }
+link! { B, C }
+link! { C, D }
+link! { D, E }
+link! { E, F }
+link! { F, G }
+
+pub struct G;
+
+fn main() {
+    drop::<Option<A>>(None);
+}
diff --git a/src/test/ui/type_length_limit.stderr b/src/test/ui/type_length_limit.stderr
new file mode 100644
index 0000000..9d07c86
--- /dev/null
+++ b/src/test/ui/type_length_limit.stderr
@@ -0,0 +1,10 @@
+error: reached the type-length limit while instantiating `std::mem::drop::<std::option::Op... G), (G, G, G), (G, G, G))))))>>`
+  --> $SRC_DIR/libcore/mem.rs:LL:COL
+   |
+LL | pub fn drop<T>(_x: T) { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: consider adding a `#![type_length_limit="1094"]` attribute to your crate
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/typeck/auxiliary/tdticc_coherence_lib.rs b/src/test/ui/typeck/auxiliary/tdticc_coherence_lib.rs
new file mode 100644
index 0000000..d00025b
--- /dev/null
+++ b/src/test/ui/typeck/auxiliary/tdticc_coherence_lib.rs
@@ -0,0 +1,6 @@
+#![feature(optin_builtin_traits, core)]
+#![crate_type = "rlib"]
+
+pub auto trait DefaultedTrait { }
+
+pub struct Something<T> { t: T }
diff --git a/src/test/ui/typeck/issue-55810-must-typeck-match-pats-before-guards.rs b/src/test/ui/typeck/issue-55810-must-typeck-match-pats-before-guards.rs
new file mode 100644
index 0000000..9eed80a
--- /dev/null
+++ b/src/test/ui/typeck/issue-55810-must-typeck-match-pats-before-guards.rs
@@ -0,0 +1,23 @@
+// compile-pass
+
+// rust-lang/rust#55810: types for a binding in a match arm can be
+// inferred from arms that come later in the match.
+
+struct S;
+
+impl S {
+    fn method(&self) -> bool {
+        unimplemented!()
+    }
+}
+
+fn get<T>() -> T {
+    unimplemented!()
+}
+
+fn main() {
+    match get() {
+        x if x.method() => {}
+        &S => {}
+    }
+}
diff --git a/src/test/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.rs b/src/test/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.rs
new file mode 100644
index 0000000..0a4e7da
--- /dev/null
+++ b/src/test/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.rs
@@ -0,0 +1,7 @@
+//extern crate has_assoc_type;
+
+//fn ice(x: Box<dyn has_assoc_type::Foo<Assoc=()>>) {
+fn ice(x: Box<dyn Iterator<Item=()>>) {
+    *x //~ ERROR mismatched types [E0308]
+}
+fn main() {}
diff --git a/src/test/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.stderr b/src/test/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.stderr
new file mode 100644
index 0000000..d410861
--- /dev/null
+++ b/src/test/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-57673-ice-on-deref-of-boxed-trait.rs:5:5
+   |
+LL | fn ice(x: Box<dyn Iterator<Item=()>>) {
+   |                                       - possibly return type missing here?
+LL |     *x
+   |     ^^ expected (), found trait std::iter::Iterator
+   |
+   = note: expected type `()`
+              found type `(dyn std::iter::Iterator<Item = ()> + 'static)`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.rs b/src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.rs
new file mode 100644
index 0000000..92d8ba8
--- /dev/null
+++ b/src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.rs
@@ -0,0 +1,14 @@
+#![feature(optin_builtin_traits)]
+
+auto trait Magic : Sized where Option<Self> : Magic {} //~ ERROR E0568
+impl<T:Magic> Magic for T {}
+
+fn copy<T: Magic>(x: T) -> (T, T) { (x, x) }
+
+#[derive(Debug)]
+struct NoClone;
+
+fn main() {
+    let (a, b) = copy(NoClone);
+    println!("{:?} {:?}", a, b);
+}
diff --git a/src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.stderr b/src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.stderr
new file mode 100644
index 0000000..8755bcd
--- /dev/null
+++ b/src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.stderr
@@ -0,0 +1,9 @@
+error[E0568]: auto traits cannot have super traits
+  --> $DIR/typeck-auto-trait-no-supertraits-2.rs:3:1
+   |
+LL | auto trait Magic : Sized where Option<Self> : Magic {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0568`.
diff --git a/src/test/ui/typeck/typeck-auto-trait-no-supertraits.rs b/src/test/ui/typeck/typeck-auto-trait-no-supertraits.rs
new file mode 100644
index 0000000..e48017a
--- /dev/null
+++ b/src/test/ui/typeck/typeck-auto-trait-no-supertraits.rs
@@ -0,0 +1,38 @@
+// This test is for #29859, we need to ensure auto traits,
+// (also known previously as default traits), do not have
+// supertraits. Since the compiler synthesizes these
+// instances on demand, we are essentially enabling
+// users to write axioms if we view trait selection,
+// as a proof system.
+//
+// For example the below test allows us to add the rule:
+//  forall (T : Type), T : Copy
+//
+// Providing a copy instance for *any* type, which
+// is most definitely unsound. Imagine copying a
+// type that contains a mutable reference, enabling
+// mutable aliasing.
+//
+// You can imagine an even more dangerous test,
+// which currently compiles on nightly.
+//
+// fn main() {
+//    let mut i = 10;
+//    let (a, b) = copy(&mut i);
+//    println!("{:?} {:?}", a, b);
+// }
+
+#![feature(optin_builtin_traits)]
+
+auto trait Magic: Copy {} //~ ERROR E0568
+impl<T:Magic> Magic for T {}
+
+fn copy<T: Magic>(x: T) -> (T, T) { (x, x) }
+
+#[derive(Debug)]
+struct NoClone;
+
+fn main() {
+    let (a, b) = copy(NoClone);
+    println!("{:?} {:?}", a, b);
+}
diff --git a/src/test/ui/typeck/typeck-auto-trait-no-supertraits.stderr b/src/test/ui/typeck/typeck-auto-trait-no-supertraits.stderr
new file mode 100644
index 0000000..5a38883
--- /dev/null
+++ b/src/test/ui/typeck/typeck-auto-trait-no-supertraits.stderr
@@ -0,0 +1,9 @@
+error[E0568]: auto traits cannot have super traits
+  --> $DIR/typeck-auto-trait-no-supertraits.rs:27:1
+   |
+LL | auto trait Magic: Copy {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0568`.
diff --git a/src/test/ui/typeck/typeck-builtin-bound-type-parameters.rs b/src/test/ui/typeck/typeck-builtin-bound-type-parameters.rs
new file mode 100644
index 0000000..7760866
--- /dev/null
+++ b/src/test/ui/typeck/typeck-builtin-bound-type-parameters.rs
@@ -0,0 +1,19 @@
+fn foo1<T:Copy<U>, U>(x: T) {}
+//~^ ERROR wrong number of type arguments: expected 0, found 1 [E0107]
+
+trait Trait: Copy<Send> {}
+//~^ ERROR wrong number of type arguments: expected 0, found 1 [E0107]
+
+struct MyStruct1<T: Copy<T>>;
+//~^ ERROR wrong number of type arguments: expected 0, found 1 [E0107]
+
+struct MyStruct2<'a, T: Copy<'a>>;
+//~^ ERROR: wrong number of lifetime arguments: expected 0, found 1 [E0107]
+
+
+fn foo2<'a, T:Copy<'a, U>, U>(x: T) {}
+//~^ ERROR wrong number of type arguments: expected 0, found 1 [E0107]
+//~| ERROR: wrong number of lifetime arguments: expected 0, found 1
+
+fn main() {
+}
diff --git a/src/test/ui/typeck/typeck-builtin-bound-type-parameters.stderr b/src/test/ui/typeck/typeck-builtin-bound-type-parameters.stderr
new file mode 100644
index 0000000..0242287
--- /dev/null
+++ b/src/test/ui/typeck/typeck-builtin-bound-type-parameters.stderr
@@ -0,0 +1,39 @@
+error[E0107]: wrong number of type arguments: expected 0, found 1
+  --> $DIR/typeck-builtin-bound-type-parameters.rs:1:16
+   |
+LL | fn foo1<T:Copy<U>, U>(x: T) {}
+   |                ^ unexpected type argument
+
+error[E0107]: wrong number of type arguments: expected 0, found 1
+  --> $DIR/typeck-builtin-bound-type-parameters.rs:4:19
+   |
+LL | trait Trait: Copy<Send> {}
+   |                   ^^^^ unexpected type argument
+
+error[E0107]: wrong number of type arguments: expected 0, found 1
+  --> $DIR/typeck-builtin-bound-type-parameters.rs:7:26
+   |
+LL | struct MyStruct1<T: Copy<T>>;
+   |                          ^ unexpected type argument
+
+error[E0107]: wrong number of lifetime arguments: expected 0, found 1
+  --> $DIR/typeck-builtin-bound-type-parameters.rs:10:30
+   |
+LL | struct MyStruct2<'a, T: Copy<'a>>;
+   |                              ^^ unexpected lifetime argument
+
+error[E0107]: wrong number of lifetime arguments: expected 0, found 1
+  --> $DIR/typeck-builtin-bound-type-parameters.rs:14:20
+   |
+LL | fn foo2<'a, T:Copy<'a, U>, U>(x: T) {}
+   |                    ^^ unexpected lifetime argument
+
+error[E0107]: wrong number of type arguments: expected 0, found 1
+  --> $DIR/typeck-builtin-bound-type-parameters.rs:14:24
+   |
+LL | fn foo2<'a, T:Copy<'a, U>, U>(x: T) {}
+   |                        ^ unexpected type argument
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0107`.
diff --git a/src/test/ui/typeck/typeck-cast-pointer-to-float.rs b/src/test/ui/typeck/typeck-cast-pointer-to-float.rs
new file mode 100644
index 0000000..2af7a3c
--- /dev/null
+++ b/src/test/ui/typeck/typeck-cast-pointer-to-float.rs
@@ -0,0 +1,5 @@
+fn main() {
+    let x : i16 = 22;
+    ((&x) as *const i16) as f32;
+    //~^ ERROR casting `*const i16` as `f32` is invalid
+}
diff --git a/src/test/ui/typeck/typeck-cast-pointer-to-float.stderr b/src/test/ui/typeck/typeck-cast-pointer-to-float.stderr
new file mode 100644
index 0000000..81d9684
--- /dev/null
+++ b/src/test/ui/typeck/typeck-cast-pointer-to-float.stderr
@@ -0,0 +1,9 @@
+error[E0606]: casting `*const i16` as `f32` is invalid
+  --> $DIR/typeck-cast-pointer-to-float.rs:3:5
+   |
+LL |     ((&x) as *const i16) as f32;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0606`.
diff --git a/src/test/ui/typeck/typeck-default-trait-impl-assoc-type.rs b/src/test/ui/typeck/typeck-default-trait-impl-assoc-type.rs
new file mode 100644
index 0000000..d648353
--- /dev/null
+++ b/src/test/ui/typeck/typeck-default-trait-impl-assoc-type.rs
@@ -0,0 +1,15 @@
+// Test that we do not consider associated types to be sendable without
+// some applicable trait bound (and we don't ICE).
+
+trait Trait {
+    type AssocType;
+    fn dummy(&self) { }
+}
+fn bar<T:Trait+Send>() {
+    is_send::<T::AssocType>(); //~ ERROR E0277
+}
+
+fn is_send<T:Send>() {
+}
+
+fn main() { }
diff --git a/src/test/ui/typeck/typeck-default-trait-impl-assoc-type.stderr b/src/test/ui/typeck/typeck-default-trait-impl-assoc-type.stderr
new file mode 100644
index 0000000..a31ee83
--- /dev/null
+++ b/src/test/ui/typeck/typeck-default-trait-impl-assoc-type.stderr
@@ -0,0 +1,17 @@
+error[E0277]: `<T as Trait>::AssocType` cannot be sent between threads safely
+  --> $DIR/typeck-default-trait-impl-assoc-type.rs:9:5
+   |
+LL |     is_send::<T::AssocType>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ `<T as Trait>::AssocType` cannot be sent between threads safely
+   |
+   = help: the trait `std::marker::Send` is not implemented for `<T as Trait>::AssocType`
+   = help: consider adding a `where <T as Trait>::AssocType: std::marker::Send` bound
+note: required by `is_send`
+  --> $DIR/typeck-default-trait-impl-assoc-type.rs:12:1
+   |
+LL | fn is_send<T:Send>() {
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/typeck/typeck-default-trait-impl-constituent-types-2.rs b/src/test/ui/typeck/typeck-default-trait-impl-constituent-types-2.rs
new file mode 100644
index 0000000..6c170fb
--- /dev/null
+++ b/src/test/ui/typeck/typeck-default-trait-impl-constituent-types-2.rs
@@ -0,0 +1,18 @@
+#![feature(optin_builtin_traits)]
+
+auto trait MyTrait {}
+
+struct MyS;
+
+struct MyS2;
+
+impl !MyTrait for MyS2 {}
+
+fn is_mytrait<T: MyTrait>() {}
+
+fn main() {
+    is_mytrait::<MyS>();
+
+    is_mytrait::<(MyS2, MyS)>();
+    //~^ ERROR `MyS2: MyTrait` is not satisfied
+}
diff --git a/src/test/ui/typeck/typeck-default-trait-impl-constituent-types-2.stderr b/src/test/ui/typeck/typeck-default-trait-impl-constituent-types-2.stderr
new file mode 100644
index 0000000..db1d7d8
--- /dev/null
+++ b/src/test/ui/typeck/typeck-default-trait-impl-constituent-types-2.stderr
@@ -0,0 +1,18 @@
+error[E0277]: the trait bound `MyS2: MyTrait` is not satisfied in `(MyS2, MyS)`
+  --> $DIR/typeck-default-trait-impl-constituent-types-2.rs:16:5
+   |
+LL |     is_mytrait::<(MyS2, MyS)>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ within `(MyS2, MyS)`, the trait `MyTrait` is not implemented for `MyS2`
+   |
+   = help: the following implementations were found:
+             <MyS2 as MyTrait>
+   = note: required because it appears within the type `(MyS2, MyS)`
+note: required by `is_mytrait`
+  --> $DIR/typeck-default-trait-impl-constituent-types-2.rs:11:1
+   |
+LL | fn is_mytrait<T: MyTrait>() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/typeck/typeck-default-trait-impl-constituent-types.rs b/src/test/ui/typeck/typeck-default-trait-impl-constituent-types.rs
new file mode 100644
index 0000000..d72f676
--- /dev/null
+++ b/src/test/ui/typeck/typeck-default-trait-impl-constituent-types.rs
@@ -0,0 +1,22 @@
+#![feature(optin_builtin_traits)]
+
+auto trait MyTrait {}
+
+impl<T> !MyTrait for *mut T {}
+
+struct MyS;
+
+struct MyS2;
+
+impl !MyTrait for MyS2 {}
+
+struct MyS3;
+
+fn is_mytrait<T: MyTrait>() {}
+
+fn main() {
+    is_mytrait::<MyS>();
+
+    is_mytrait::<MyS2>();
+    //~^ ERROR `MyS2: MyTrait` is not satisfied
+}
diff --git a/src/test/ui/typeck/typeck-default-trait-impl-constituent-types.stderr b/src/test/ui/typeck/typeck-default-trait-impl-constituent-types.stderr
new file mode 100644
index 0000000..0f90518
--- /dev/null
+++ b/src/test/ui/typeck/typeck-default-trait-impl-constituent-types.stderr
@@ -0,0 +1,17 @@
+error[E0277]: the trait bound `MyS2: MyTrait` is not satisfied
+  --> $DIR/typeck-default-trait-impl-constituent-types.rs:20:5
+   |
+LL |     is_mytrait::<MyS2>();
+   |     ^^^^^^^^^^^^^^^^^^ the trait `MyTrait` is not implemented for `MyS2`
+   |
+   = help: the following implementations were found:
+             <MyS2 as MyTrait>
+note: required by `is_mytrait`
+  --> $DIR/typeck-default-trait-impl-constituent-types.rs:15:1
+   |
+LL | fn is_mytrait<T: MyTrait>() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.rs b/src/test/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.rs
new file mode 100644
index 0000000..212e165
--- /dev/null
+++ b/src/test/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.rs
@@ -0,0 +1,24 @@
+// aux-build:tdticc_coherence_lib.rs
+
+// Test that we do not consider associated types to be sendable without
+// some applicable trait bound (and we don't ICE).
+
+#![feature(optin_builtin_traits)]
+
+extern crate tdticc_coherence_lib as lib;
+
+use lib::DefaultedTrait;
+
+struct A;
+impl DefaultedTrait for (A,) { } //~ ERROR E0117
+
+struct B;
+impl !DefaultedTrait for (B,) { } //~ ERROR E0117
+
+struct C;
+struct D<T>(T);
+impl DefaultedTrait for Box<C> { } //~ ERROR E0321
+impl DefaultedTrait for lib::Something<C> { } //~ ERROR E0117
+impl DefaultedTrait for D<C> { } // OK
+
+fn main() { }
diff --git a/src/test/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.stderr b/src/test/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.stderr
new file mode 100644
index 0000000..154b404
--- /dev/null
+++ b/src/test/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.stderr
@@ -0,0 +1,37 @@
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/typeck-default-trait-impl-cross-crate-coherence.rs:13:1
+   |
+LL | impl DefaultedTrait for (A,) { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/typeck-default-trait-impl-cross-crate-coherence.rs:16:1
+   |
+LL | impl !DefaultedTrait for (B,) { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error[E0321]: cross-crate traits with a default impl, like `lib::DefaultedTrait`, can only be implemented for a struct/enum type defined in the current crate
+  --> $DIR/typeck-default-trait-impl-cross-crate-coherence.rs:20:1
+   |
+LL | impl DefaultedTrait for Box<C> { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait for type in another crate
+
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/typeck-default-trait-impl-cross-crate-coherence.rs:21:1
+   |
+LL | impl DefaultedTrait for lib::Something<C> { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0117, E0321.
+For more information about an error, try `rustc --explain E0117`.
diff --git a/src/test/ui/typeck/typeck-default-trait-impl-negation-send.rs b/src/test/ui/typeck/typeck-default-trait-impl-negation-send.rs
new file mode 100644
index 0000000..617d0f3
--- /dev/null
+++ b/src/test/ui/typeck/typeck-default-trait-impl-negation-send.rs
@@ -0,0 +1,21 @@
+#![feature(optin_builtin_traits)]
+
+struct MySendable {
+   t: *mut u8
+}
+
+unsafe impl Send for MySendable {}
+
+struct MyNotSendable {
+   t: *mut u8
+}
+
+impl !Send for MyNotSendable {}
+
+fn is_send<T: Send>() {}
+
+fn main() {
+    is_send::<MySendable>();
+    is_send::<MyNotSendable>();
+    //~^ ERROR `MyNotSendable` cannot be sent between threads safely
+}
diff --git a/src/test/ui/typeck/typeck-default-trait-impl-negation-send.stderr b/src/test/ui/typeck/typeck-default-trait-impl-negation-send.stderr
new file mode 100644
index 0000000..8442f47
--- /dev/null
+++ b/src/test/ui/typeck/typeck-default-trait-impl-negation-send.stderr
@@ -0,0 +1,16 @@
+error[E0277]: `MyNotSendable` cannot be sent between threads safely
+  --> $DIR/typeck-default-trait-impl-negation-send.rs:19:5
+   |
+LL |     is_send::<MyNotSendable>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ `MyNotSendable` cannot be sent between threads safely
+   |
+   = help: the trait `std::marker::Send` is not implemented for `MyNotSendable`
+note: required by `is_send`
+  --> $DIR/typeck-default-trait-impl-negation-send.rs:15:1
+   |
+LL | fn is_send<T: Send>() {}
+   | ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/typeck/typeck-default-trait-impl-negation-sync.rs b/src/test/ui/typeck/typeck-default-trait-impl-negation-sync.rs
new file mode 100644
index 0000000..f31dac2
--- /dev/null
+++ b/src/test/ui/typeck/typeck-default-trait-impl-negation-sync.rs
@@ -0,0 +1,43 @@
+// ignore-tidy-linelength
+
+#![feature(optin_builtin_traits)]
+
+struct Managed;
+impl !Send for Managed {}
+impl !Sync for Managed {}
+
+use std::cell::UnsafeCell;
+
+struct MySync {
+   t: *mut u8
+}
+
+unsafe impl Sync for MySync {}
+
+struct MyNotSync {
+   t: *mut u8
+}
+
+impl !Sync for MyNotSync {}
+
+struct MyTypeWUnsafe {
+   t: UnsafeCell<u8>
+}
+
+struct MyTypeManaged {
+   t: Managed
+}
+
+fn is_sync<T: Sync>() {}
+
+fn main() {
+    is_sync::<MySync>();
+    is_sync::<MyNotSync>();
+    //~^ ERROR `MyNotSync` cannot be shared between threads safely [E0277]
+
+    is_sync::<MyTypeWUnsafe>();
+    //~^ ERROR `std::cell::UnsafeCell<u8>` cannot be shared between threads safely [E0277]
+
+    is_sync::<MyTypeManaged>();
+    //~^ ERROR `Managed` cannot be shared between threads safely [E0277]
+}
diff --git a/src/test/ui/typeck/typeck-default-trait-impl-negation-sync.stderr b/src/test/ui/typeck/typeck-default-trait-impl-negation-sync.stderr
new file mode 100644
index 0000000..5330c04
--- /dev/null
+++ b/src/test/ui/typeck/typeck-default-trait-impl-negation-sync.stderr
@@ -0,0 +1,44 @@
+error[E0277]: `MyNotSync` cannot be shared between threads safely
+  --> $DIR/typeck-default-trait-impl-negation-sync.rs:35:5
+   |
+LL |     is_sync::<MyNotSync>();
+   |     ^^^^^^^^^^^^^^^^^^^^ `MyNotSync` cannot be shared between threads safely
+   |
+   = help: the trait `std::marker::Sync` is not implemented for `MyNotSync`
+note: required by `is_sync`
+  --> $DIR/typeck-default-trait-impl-negation-sync.rs:31:1
+   |
+LL | fn is_sync<T: Sync>() {}
+   | ^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: `std::cell::UnsafeCell<u8>` cannot be shared between threads safely
+  --> $DIR/typeck-default-trait-impl-negation-sync.rs:38:5
+   |
+LL |     is_sync::<MyTypeWUnsafe>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ `std::cell::UnsafeCell<u8>` cannot be shared between threads safely
+   |
+   = help: within `MyTypeWUnsafe`, the trait `std::marker::Sync` is not implemented for `std::cell::UnsafeCell<u8>`
+   = note: required because it appears within the type `MyTypeWUnsafe`
+note: required by `is_sync`
+  --> $DIR/typeck-default-trait-impl-negation-sync.rs:31:1
+   |
+LL | fn is_sync<T: Sync>() {}
+   | ^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: `Managed` cannot be shared between threads safely
+  --> $DIR/typeck-default-trait-impl-negation-sync.rs:41:5
+   |
+LL |     is_sync::<MyTypeManaged>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ `Managed` cannot be shared between threads safely
+   |
+   = help: within `MyTypeManaged`, the trait `std::marker::Sync` is not implemented for `Managed`
+   = note: required because it appears within the type `MyTypeManaged`
+note: required by `is_sync`
+  --> $DIR/typeck-default-trait-impl-negation-sync.rs:31:1
+   |
+LL | fn is_sync<T: Sync>() {}
+   | ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/typeck/typeck-default-trait-impl-negation.rs b/src/test/ui/typeck/typeck-default-trait-impl-negation.rs
new file mode 100644
index 0000000..0b6e13b
--- /dev/null
+++ b/src/test/ui/typeck/typeck-default-trait-impl-negation.rs
@@ -0,0 +1,28 @@
+#![feature(optin_builtin_traits)]
+
+auto trait MyTrait {}
+
+unsafe auto trait MyUnsafeTrait {}
+
+struct ThisImplsTrait;
+
+impl !MyUnsafeTrait for ThisImplsTrait {}
+
+
+struct ThisImplsUnsafeTrait;
+
+impl !MyTrait for ThisImplsUnsafeTrait {}
+
+fn is_my_trait<T: MyTrait>() {}
+fn is_my_unsafe_trait<T: MyUnsafeTrait>() {}
+
+fn main() {
+    is_my_trait::<ThisImplsTrait>();
+    is_my_trait::<ThisImplsUnsafeTrait>();
+    //~^ ERROR `ThisImplsUnsafeTrait: MyTrait` is not satisfied
+
+    is_my_unsafe_trait::<ThisImplsTrait>();
+    //~^ ERROR `ThisImplsTrait: MyUnsafeTrait` is not satisfied
+
+    is_my_unsafe_trait::<ThisImplsUnsafeTrait>();
+}
diff --git a/src/test/ui/typeck/typeck-default-trait-impl-negation.stderr b/src/test/ui/typeck/typeck-default-trait-impl-negation.stderr
new file mode 100644
index 0000000..751083d
--- /dev/null
+++ b/src/test/ui/typeck/typeck-default-trait-impl-negation.stderr
@@ -0,0 +1,31 @@
+error[E0277]: the trait bound `ThisImplsUnsafeTrait: MyTrait` is not satisfied
+  --> $DIR/typeck-default-trait-impl-negation.rs:21:5
+   |
+LL |     is_my_trait::<ThisImplsUnsafeTrait>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `MyTrait` is not implemented for `ThisImplsUnsafeTrait`
+   |
+   = help: the following implementations were found:
+             <ThisImplsUnsafeTrait as MyTrait>
+note: required by `is_my_trait`
+  --> $DIR/typeck-default-trait-impl-negation.rs:16:1
+   |
+LL | fn is_my_trait<T: MyTrait>() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `ThisImplsTrait: MyUnsafeTrait` is not satisfied
+  --> $DIR/typeck-default-trait-impl-negation.rs:24:5
+   |
+LL |     is_my_unsafe_trait::<ThisImplsTrait>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `MyUnsafeTrait` is not implemented for `ThisImplsTrait`
+   |
+   = help: the following implementations were found:
+             <ThisImplsTrait as MyUnsafeTrait>
+note: required by `is_my_unsafe_trait`
+  --> $DIR/typeck-default-trait-impl-negation.rs:17:1
+   |
+LL | fn is_my_unsafe_trait<T: MyUnsafeTrait>() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/typeck/typeck-default-trait-impl-precedence.rs b/src/test/ui/typeck/typeck-default-trait-impl-precedence.rs
new file mode 100644
index 0000000..9b228f7
--- /dev/null
+++ b/src/test/ui/typeck/typeck-default-trait-impl-precedence.rs
@@ -0,0 +1,20 @@
+// Test that declaring that `&T` is `Defaulted` if `T:Signed` implies
+// that other `&T` is NOT `Defaulted` if `T:Signed` does not hold. In
+// other words, the auto impl only applies if there are no existing
+// impls whose types unify.
+
+#![feature(optin_builtin_traits)]
+
+auto trait Defaulted { }
+impl<'a,T:Signed> Defaulted for &'a T { }
+impl<'a,T:Signed> Defaulted for &'a mut T { }
+fn is_defaulted<T:Defaulted>() { }
+
+trait Signed { }
+impl Signed for i32 { }
+
+fn main() {
+    is_defaulted::<&'static i32>();
+    is_defaulted::<&'static u32>();
+    //~^ ERROR `u32: Signed` is not satisfied
+}
diff --git a/src/test/ui/typeck/typeck-default-trait-impl-precedence.stderr b/src/test/ui/typeck/typeck-default-trait-impl-precedence.stderr
new file mode 100644
index 0000000..d45cbb2
--- /dev/null
+++ b/src/test/ui/typeck/typeck-default-trait-impl-precedence.stderr
@@ -0,0 +1,16 @@
+error[E0277]: the trait bound `u32: Signed` is not satisfied
+  --> $DIR/typeck-default-trait-impl-precedence.rs:18:5
+   |
+LL |     is_defaulted::<&'static u32>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Signed` is not implemented for `u32`
+   |
+   = note: required because of the requirements on the impl of `Defaulted` for `&'static u32`
+note: required by `is_defaulted`
+  --> $DIR/typeck-default-trait-impl-precedence.rs:11:1
+   |
+LL | fn is_defaulted<T:Defaulted>() { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/typeck/typeck-default-trait-impl-send-param.rs b/src/test/ui/typeck/typeck-default-trait-impl-send-param.rs
new file mode 100644
index 0000000..7948cd1
--- /dev/null
+++ b/src/test/ui/typeck/typeck-default-trait-impl-send-param.rs
@@ -0,0 +1,11 @@
+// Test that we do not consider parameter types to be sendable without
+// an explicit trait bound.
+
+fn foo<T>() {
+    is_send::<T>() //~ ERROR E0277
+}
+
+fn is_send<T:Send>() {
+}
+
+fn main() { }
diff --git a/src/test/ui/typeck/typeck-default-trait-impl-send-param.stderr b/src/test/ui/typeck/typeck-default-trait-impl-send-param.stderr
new file mode 100644
index 0000000..a850cc7
--- /dev/null
+++ b/src/test/ui/typeck/typeck-default-trait-impl-send-param.stderr
@@ -0,0 +1,17 @@
+error[E0277]: `T` cannot be sent between threads safely
+  --> $DIR/typeck-default-trait-impl-send-param.rs:5:5
+   |
+LL |     is_send::<T>()
+   |     ^^^^^^^^^^^^ `T` cannot be sent between threads safely
+   |
+   = help: the trait `std::marker::Send` is not implemented for `T`
+   = help: consider adding a `where T: std::marker::Send` bound
+note: required by `is_send`
+  --> $DIR/typeck-default-trait-impl-send-param.rs:8:1
+   |
+LL | fn is_send<T:Send>() {
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/typeck/typeck-negative-impls-builtin.rs b/src/test/ui/typeck/typeck-negative-impls-builtin.rs
new file mode 100644
index 0000000..7bdd103
--- /dev/null
+++ b/src/test/ui/typeck/typeck-negative-impls-builtin.rs
@@ -0,0 +1,12 @@
+#![feature(optin_builtin_traits)]
+
+struct TestType;
+
+trait TestTrait {
+    fn dummy(&self) { }
+}
+
+impl !TestTrait for TestType {}
+//~^ ERROR negative impls are only allowed for auto traits (e.g., `Send` and `Sync`)
+
+fn main() {}
diff --git a/src/test/ui/typeck/typeck-negative-impls-builtin.stderr b/src/test/ui/typeck/typeck-negative-impls-builtin.stderr
new file mode 100644
index 0000000..4e3d054
--- /dev/null
+++ b/src/test/ui/typeck/typeck-negative-impls-builtin.stderr
@@ -0,0 +1,9 @@
+error[E0192]: negative impls are only allowed for auto traits (e.g., `Send` and `Sync`)
+  --> $DIR/typeck-negative-impls-builtin.rs:9:1
+   |
+LL | impl !TestTrait for TestType {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0192`.
diff --git a/src/test/ui/typeck/typeck-unsafe-always-share.rs b/src/test/ui/typeck/typeck-unsafe-always-share.rs
new file mode 100644
index 0000000..7d1ff73
--- /dev/null
+++ b/src/test/ui/typeck/typeck-unsafe-always-share.rs
@@ -0,0 +1,32 @@
+// Verify that UnsafeCell is *always* !Sync regardless if `T` is sync.
+
+#![feature(optin_builtin_traits)]
+
+use std::cell::UnsafeCell;
+use std::marker::Sync;
+
+struct MySync<T> {
+    u: UnsafeCell<T>
+}
+
+struct NoSync;
+impl !Sync for NoSync {}
+
+fn test<T: Sync>(s: T) {}
+
+fn main() {
+    let us = UnsafeCell::new(MySync{u: UnsafeCell::new(0)});
+    test(us);
+    //~^ ERROR `std::cell::UnsafeCell<MySync<{integer}>>` cannot be shared between threads safely
+
+    let uns = UnsafeCell::new(NoSync);
+    test(uns);
+    //~^ ERROR `std::cell::UnsafeCell<NoSync>` cannot be shared between threads safely [E0277]
+
+    let ms = MySync{u: uns};
+    test(ms);
+    //~^ ERROR `std::cell::UnsafeCell<NoSync>` cannot be shared between threads safely [E0277]
+
+    test(NoSync);
+    //~^ ERROR `NoSync` cannot be shared between threads safely [E0277]
+}
diff --git a/src/test/ui/typeck/typeck-unsafe-always-share.stderr b/src/test/ui/typeck/typeck-unsafe-always-share.stderr
new file mode 100644
index 0000000..ff351af
--- /dev/null
+++ b/src/test/ui/typeck/typeck-unsafe-always-share.stderr
@@ -0,0 +1,56 @@
+error[E0277]: `std::cell::UnsafeCell<MySync<{integer}>>` cannot be shared between threads safely
+  --> $DIR/typeck-unsafe-always-share.rs:19:5
+   |
+LL |     test(us);
+   |     ^^^^ `std::cell::UnsafeCell<MySync<{integer}>>` cannot be shared between threads safely
+   |
+   = help: the trait `std::marker::Sync` is not implemented for `std::cell::UnsafeCell<MySync<{integer}>>`
+note: required by `test`
+  --> $DIR/typeck-unsafe-always-share.rs:15:1
+   |
+LL | fn test<T: Sync>(s: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: `std::cell::UnsafeCell<NoSync>` cannot be shared between threads safely
+  --> $DIR/typeck-unsafe-always-share.rs:23:5
+   |
+LL |     test(uns);
+   |     ^^^^ `std::cell::UnsafeCell<NoSync>` cannot be shared between threads safely
+   |
+   = help: the trait `std::marker::Sync` is not implemented for `std::cell::UnsafeCell<NoSync>`
+note: required by `test`
+  --> $DIR/typeck-unsafe-always-share.rs:15:1
+   |
+LL | fn test<T: Sync>(s: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: `std::cell::UnsafeCell<NoSync>` cannot be shared between threads safely
+  --> $DIR/typeck-unsafe-always-share.rs:27:5
+   |
+LL |     test(ms);
+   |     ^^^^ `std::cell::UnsafeCell<NoSync>` cannot be shared between threads safely
+   |
+   = help: within `MySync<NoSync>`, the trait `std::marker::Sync` is not implemented for `std::cell::UnsafeCell<NoSync>`
+   = note: required because it appears within the type `MySync<NoSync>`
+note: required by `test`
+  --> $DIR/typeck-unsafe-always-share.rs:15:1
+   |
+LL | fn test<T: Sync>(s: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: `NoSync` cannot be shared between threads safely
+  --> $DIR/typeck-unsafe-always-share.rs:30:5
+   |
+LL |     test(NoSync);
+   |     ^^^^ `NoSync` cannot be shared between threads safely
+   |
+   = help: the trait `std::marker::Sync` is not implemented for `NoSync`
+note: required by `test`
+  --> $DIR/typeck-unsafe-always-share.rs:15:1
+   |
+LL | fn test<T: Sync>(s: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.rs b/src/test/ui/typeck/typeck_type_placeholder_item.rs
new file mode 100644
index 0000000..46a5b85
--- /dev/null
+++ b/src/test/ui/typeck/typeck_type_placeholder_item.rs
@@ -0,0 +1,109 @@
+// This test checks that it is not possible to enable global type
+// inference by using the `_` type placeholder.
+
+fn test() -> _ { 5 }
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+
+fn test2() -> (_, _) { (5, 5) }
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+//~^^ ERROR the type placeholder `_` is not allowed within types on item signatures
+
+static TEST3: _ = "test";
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+
+static TEST4: _ = 145;
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+
+static TEST5: (_, _) = (1, 2);
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+//~^^ ERROR the type placeholder `_` is not allowed within types on item signatures
+
+fn test6(_: _) { }
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+
+fn test7(x: _) { let _x: usize = x; }
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+
+fn test8(_f: fn() -> _) { }
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+
+struct Test9;
+
+impl Test9 {
+    fn test9(&self) -> _ { () }
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+
+    fn test10(&self, _x : _) { }
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+}
+
+impl Clone for Test9 {
+    fn clone(&self) -> _ { Test9 }
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+
+    fn clone_from(&mut self, other: _) { *self = Test9; }
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+}
+
+struct Test10 {
+    a: _,
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+    b: (_, _),
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+    //~^^ ERROR the type placeholder `_` is not allowed within types on item signatures
+}
+
+pub fn main() {
+    fn fn_test() -> _ { 5 }
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+
+    fn fn_test2() -> (_, _) { (5, 5) }
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+    //~^^ ERROR the type placeholder `_` is not allowed within types on item signatures
+
+    static FN_TEST3: _ = "test";
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+
+    static FN_TEST4: _ = 145;
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+
+    static FN_TEST5: (_, _) = (1, 2);
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+    //~^^ ERROR the type placeholder `_` is not allowed within types on item signatures
+
+    fn fn_test6(_: _) { }
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+
+    fn fn_test7(x: _) { let _x: usize = x; }
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+
+    fn fn_test8(_f: fn() -> _) { }
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+
+    struct FnTest9;
+
+    impl FnTest9 {
+        fn fn_test9(&self) -> _ { () }
+        //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+
+        fn fn_test10(&self, _x : _) { }
+        //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+    }
+
+    impl Clone for FnTest9 {
+        fn clone(&self) -> _ { FnTest9 }
+        //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+
+        fn clone_from(&mut self, other: _) { *self = FnTest9; }
+        //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+    }
+
+    struct FnTest10 {
+        a: _,
+        //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+        b: (_, _),
+        //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+        //~^^ ERROR the type placeholder `_` is not allowed within types on item signatures
+    }
+
+}
diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.stderr b/src/test/ui/typeck/typeck_type_placeholder_item.stderr
new file mode 100644
index 0000000..9ae104c
--- /dev/null
+++ b/src/test/ui/typeck/typeck_type_placeholder_item.stderr
@@ -0,0 +1,207 @@
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:4:14
+   |
+LL | fn test() -> _ { 5 }
+   |              ^ not allowed in type signatures
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:7:16
+   |
+LL | fn test2() -> (_, _) { (5, 5) }
+   |                ^ not allowed in type signatures
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:7:19
+   |
+LL | fn test2() -> (_, _) { (5, 5) }
+   |                   ^ not allowed in type signatures
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:11:15
+   |
+LL | static TEST3: _ = "test";
+   |               ^ not allowed in type signatures
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:14:15
+   |
+LL | static TEST4: _ = 145;
+   |               ^ not allowed in type signatures
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:17:16
+   |
+LL | static TEST5: (_, _) = (1, 2);
+   |                ^ not allowed in type signatures
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:17:19
+   |
+LL | static TEST5: (_, _) = (1, 2);
+   |                   ^ not allowed in type signatures
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:21:13
+   |
+LL | fn test6(_: _) { }
+   |             ^ not allowed in type signatures
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:24:13
+   |
+LL | fn test7(x: _) { let _x: usize = x; }
+   |             ^ not allowed in type signatures
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:27:22
+   |
+LL | fn test8(_f: fn() -> _) { }
+   |                      ^ not allowed in type signatures
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:49:8
+   |
+LL |     a: _,
+   |        ^ not allowed in type signatures
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:51:9
+   |
+LL |     b: (_, _),
+   |         ^ not allowed in type signatures
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:51:12
+   |
+LL |     b: (_, _),
+   |            ^ not allowed in type signatures
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:102:12
+   |
+LL |         a: _,
+   |            ^ not allowed in type signatures
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:104:13
+   |
+LL |         b: (_, _),
+   |             ^ not allowed in type signatures
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:104:16
+   |
+LL |         b: (_, _),
+   |                ^ not allowed in type signatures
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:57:21
+   |
+LL |     fn fn_test() -> _ { 5 }
+   |                     ^ not allowed in type signatures
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:60:23
+   |
+LL |     fn fn_test2() -> (_, _) { (5, 5) }
+   |                       ^ not allowed in type signatures
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:60:26
+   |
+LL |     fn fn_test2() -> (_, _) { (5, 5) }
+   |                          ^ not allowed in type signatures
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:64:22
+   |
+LL |     static FN_TEST3: _ = "test";
+   |                      ^ not allowed in type signatures
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:67:22
+   |
+LL |     static FN_TEST4: _ = 145;
+   |                      ^ not allowed in type signatures
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:70:23
+   |
+LL |     static FN_TEST5: (_, _) = (1, 2);
+   |                       ^ not allowed in type signatures
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:70:26
+   |
+LL |     static FN_TEST5: (_, _) = (1, 2);
+   |                          ^ not allowed in type signatures
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:74:20
+   |
+LL |     fn fn_test6(_: _) { }
+   |                    ^ not allowed in type signatures
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:77:20
+   |
+LL |     fn fn_test7(x: _) { let _x: usize = x; }
+   |                    ^ not allowed in type signatures
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:80:29
+   |
+LL |     fn fn_test8(_f: fn() -> _) { }
+   |                             ^ not allowed in type signatures
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:33:24
+   |
+LL |     fn test9(&self) -> _ { () }
+   |                        ^ not allowed in type signatures
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:36:27
+   |
+LL |     fn test10(&self, _x : _) { }
+   |                           ^ not allowed in type signatures
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:41:24
+   |
+LL |     fn clone(&self) -> _ { Test9 }
+   |                        ^ not allowed in type signatures
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:44:37
+   |
+LL |     fn clone_from(&mut self, other: _) { *self = Test9; }
+   |                                     ^ not allowed in type signatures
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:86:31
+   |
+LL |         fn fn_test9(&self) -> _ { () }
+   |                               ^ not allowed in type signatures
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:89:34
+   |
+LL |         fn fn_test10(&self, _x : _) { }
+   |                                  ^ not allowed in type signatures
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:94:28
+   |
+LL |         fn clone(&self) -> _ { FnTest9 }
+   |                            ^ not allowed in type signatures
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:97:41
+   |
+LL |         fn clone_from(&mut self, other: _) { *self = FnTest9; }
+   |                                         ^ not allowed in type signatures
+
+error: aborting due to 34 previous errors
+
+For more information about this error, try `rustc --explain E0121`.
diff --git a/src/test/ui/typeck/typeck_type_placeholder_lifetime_1.rs b/src/test/ui/typeck/typeck_type_placeholder_lifetime_1.rs
new file mode 100644
index 0000000..57ab7de
--- /dev/null
+++ b/src/test/ui/typeck/typeck_type_placeholder_lifetime_1.rs
@@ -0,0 +1,11 @@
+// This test checks that the `_` type placeholder does not react
+// badly if put as a lifetime parameter.
+
+struct Foo<'a, T:'a> {
+    r: &'a T
+}
+
+pub fn main() {
+    let c: Foo<_, _> = Foo { r: &5 };
+    //~^ ERROR wrong number of type arguments: expected 1, found 2 [E0107]
+}
diff --git a/src/test/ui/typeck/typeck_type_placeholder_lifetime_1.stderr b/src/test/ui/typeck/typeck_type_placeholder_lifetime_1.stderr
new file mode 100644
index 0000000..8186d75
--- /dev/null
+++ b/src/test/ui/typeck/typeck_type_placeholder_lifetime_1.stderr
@@ -0,0 +1,9 @@
+error[E0107]: wrong number of type arguments: expected 1, found 2
+  --> $DIR/typeck_type_placeholder_lifetime_1.rs:9:19
+   |
+LL |     let c: Foo<_, _> = Foo { r: &5 };
+   |                   ^ unexpected type argument
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0107`.
diff --git a/src/test/ui/typeck/typeck_type_placeholder_lifetime_2.rs b/src/test/ui/typeck/typeck_type_placeholder_lifetime_2.rs
new file mode 100644
index 0000000..b68d283
--- /dev/null
+++ b/src/test/ui/typeck/typeck_type_placeholder_lifetime_2.rs
@@ -0,0 +1,11 @@
+// This test checks that the `_` type placeholder does not react
+// badly if put as a lifetime parameter.
+
+struct Foo<'a, T:'a> {
+    r: &'a T
+}
+
+pub fn main() {
+    let c: Foo<_, usize> = Foo { r: &5 };
+    //~^ ERROR wrong number of type arguments: expected 1, found 2 [E0107]
+}
diff --git a/src/test/ui/typeck/typeck_type_placeholder_lifetime_2.stderr b/src/test/ui/typeck/typeck_type_placeholder_lifetime_2.stderr
new file mode 100644
index 0000000..9b0f969
--- /dev/null
+++ b/src/test/ui/typeck/typeck_type_placeholder_lifetime_2.stderr
@@ -0,0 +1,9 @@
+error[E0107]: wrong number of type arguments: expected 1, found 2
+  --> $DIR/typeck_type_placeholder_lifetime_2.rs:9:19
+   |
+LL |     let c: Foo<_, usize> = Foo { r: &5 };
+   |                   ^^^^^ unexpected type argument
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0107`.
diff --git a/src/test/ui/typeck/typeck_type_placeholder_mismatch.rs b/src/test/ui/typeck/typeck_type_placeholder_mismatch.rs
new file mode 100644
index 0000000..ec978e4
--- /dev/null
+++ b/src/test/ui/typeck/typeck_type_placeholder_mismatch.rs
@@ -0,0 +1,27 @@
+// This test checks that genuine type errors with partial
+// type hints are understandable.
+
+use std::marker::PhantomData;
+
+struct Foo<T>(PhantomData<T>);
+struct Bar<U>(PhantomData<U>);
+
+pub fn main() {
+}
+
+fn test1() {
+    let x: Foo<_> = Bar::<usize>(PhantomData);
+    //~^ ERROR mismatched types
+    //~| expected type `Foo<_>`
+    //~| found type `Bar<usize>`
+    //~| expected struct `Foo`, found struct `Bar`
+    let y: Foo<usize> = x;
+}
+
+fn test2() {
+    let x: Foo<_> = Bar::<usize>(PhantomData);
+    //~^ ERROR mismatched types
+    //~| expected type `Foo<_>`
+    //~| found type `Bar<usize>`
+    //~| expected struct `Foo`, found struct `Bar`
+}
diff --git a/src/test/ui/typeck/typeck_type_placeholder_mismatch.stderr b/src/test/ui/typeck/typeck_type_placeholder_mismatch.stderr
new file mode 100644
index 0000000..8911487
--- /dev/null
+++ b/src/test/ui/typeck/typeck_type_placeholder_mismatch.stderr
@@ -0,0 +1,21 @@
+error[E0308]: mismatched types
+  --> $DIR/typeck_type_placeholder_mismatch.rs:13:21
+   |
+LL |     let x: Foo<_> = Bar::<usize>(PhantomData);
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `Foo`, found struct `Bar`
+   |
+   = note: expected type `Foo<_>`
+              found type `Bar<usize>`
+
+error[E0308]: mismatched types
+  --> $DIR/typeck_type_placeholder_mismatch.rs:22:21
+   |
+LL |     let x: Foo<_> = Bar::<usize>(PhantomData);
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `Foo`, found struct `Bar`
+   |
+   = note: expected type `Foo<_>`
+              found type `Bar<usize>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/ufcs/ufcs-explicit-self-bad.rs b/src/test/ui/ufcs/ufcs-explicit-self-bad.rs
new file mode 100644
index 0000000..c6ff94a
--- /dev/null
+++ b/src/test/ui/ufcs/ufcs-explicit-self-bad.rs
@@ -0,0 +1,59 @@
+#![feature(box_syntax)]
+
+struct Foo {
+    f: isize,
+}
+
+impl Foo {
+    fn foo(self: isize, x: isize) -> isize {
+        //~^ ERROR invalid method receiver type
+        self.f + x
+    }
+}
+
+struct Bar<T> {
+    f: T,
+}
+
+impl<T> Bar<T> {
+    fn foo(self: Bar<isize>, x: isize) -> isize {
+        //~^ ERROR invalid method receiver type
+        x
+    }
+    fn bar(self: &Bar<usize>, x: isize) -> isize {
+        //~^ ERROR invalid method receiver type
+        x
+    }
+}
+
+trait SomeTrait {
+    fn dummy1(&self);
+    fn dummy2(&self);
+    fn dummy3(&self);
+}
+
+impl<'a, T> SomeTrait for &'a Bar<T> {
+    fn dummy1(self: &&'a Bar<T>) { }
+    fn dummy2(self: &Bar<T>) {} //~ ERROR mismatched method receiver
+    //~^ ERROR mismatched method receiver
+    fn dummy3(self: &&Bar<T>) {}
+    //~^ ERROR mismatched method receiver
+    //~| expected type `&'a Bar<T>`
+    //~| found type `&Bar<T>`
+    //~| lifetime mismatch
+    //~| ERROR mismatched method receiver
+    //~| expected type `&'a Bar<T>`
+    //~| found type `&Bar<T>`
+    //~| lifetime mismatch
+}
+
+fn main() {
+    let foo = box Foo {
+        f: 1,
+    };
+    println!("{}", foo.foo(2));
+    let bar = box Bar {
+        f: 1,
+    };
+    println!("{} {}", bar.foo(2), bar.bar(2));
+}
diff --git a/src/test/ui/ufcs/ufcs-explicit-self-bad.stderr b/src/test/ui/ufcs/ufcs-explicit-self-bad.stderr
new file mode 100644
index 0000000..2187c61
--- /dev/null
+++ b/src/test/ui/ufcs/ufcs-explicit-self-bad.stderr
@@ -0,0 +1,107 @@
+error[E0307]: invalid method receiver type: isize
+  --> $DIR/ufcs-explicit-self-bad.rs:8:18
+   |
+LL |     fn foo(self: isize, x: isize) -> isize {
+   |                  ^^^^^
+   |
+   = note: type must be `Self` or a type that dereferences to it
+   = help: consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`
+
+error[E0307]: invalid method receiver type: Bar<isize>
+  --> $DIR/ufcs-explicit-self-bad.rs:19:18
+   |
+LL |     fn foo(self: Bar<isize>, x: isize) -> isize {
+   |                  ^^^^^^^^^^
+   |
+   = note: type must be `Self` or a type that dereferences to it
+   = help: consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`
+
+error[E0307]: invalid method receiver type: &Bar<usize>
+  --> $DIR/ufcs-explicit-self-bad.rs:23:18
+   |
+LL |     fn bar(self: &Bar<usize>, x: isize) -> isize {
+   |                  ^^^^^^^^^^^
+   |
+   = note: type must be `Self` or a type that dereferences to it
+   = help: consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`
+
+error[E0308]: mismatched method receiver
+  --> $DIR/ufcs-explicit-self-bad.rs:37:21
+   |
+LL |     fn dummy2(self: &Bar<T>) {}
+   |                     ^^^^^^^ lifetime mismatch
+   |
+   = note: expected type `&'a Bar<T>`
+              found type `&Bar<T>`
+note: the anonymous lifetime #1 defined on the method body at 37:5...
+  --> $DIR/ufcs-explicit-self-bad.rs:37:5
+   |
+LL |     fn dummy2(self: &Bar<T>) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...does not necessarily outlive the lifetime 'a as defined on the impl at 35:6
+  --> $DIR/ufcs-explicit-self-bad.rs:35:6
+   |
+LL | impl<'a, T> SomeTrait for &'a Bar<T> {
+   |      ^^
+
+error[E0308]: mismatched method receiver
+  --> $DIR/ufcs-explicit-self-bad.rs:37:21
+   |
+LL |     fn dummy2(self: &Bar<T>) {}
+   |                     ^^^^^^^ lifetime mismatch
+   |
+   = note: expected type `&'a Bar<T>`
+              found type `&Bar<T>`
+note: the lifetime 'a as defined on the impl at 35:6...
+  --> $DIR/ufcs-explicit-self-bad.rs:35:6
+   |
+LL | impl<'a, T> SomeTrait for &'a Bar<T> {
+   |      ^^
+note: ...does not necessarily outlive the anonymous lifetime #1 defined on the method body at 37:5
+  --> $DIR/ufcs-explicit-self-bad.rs:37:5
+   |
+LL |     fn dummy2(self: &Bar<T>) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched method receiver
+  --> $DIR/ufcs-explicit-self-bad.rs:39:21
+   |
+LL |     fn dummy3(self: &&Bar<T>) {}
+   |                     ^^^^^^^^ lifetime mismatch
+   |
+   = note: expected type `&'a Bar<T>`
+              found type `&Bar<T>`
+note: the anonymous lifetime #2 defined on the method body at 39:5...
+  --> $DIR/ufcs-explicit-self-bad.rs:39:5
+   |
+LL |     fn dummy3(self: &&Bar<T>) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...does not necessarily outlive the lifetime 'a as defined on the impl at 35:6
+  --> $DIR/ufcs-explicit-self-bad.rs:35:6
+   |
+LL | impl<'a, T> SomeTrait for &'a Bar<T> {
+   |      ^^
+
+error[E0308]: mismatched method receiver
+  --> $DIR/ufcs-explicit-self-bad.rs:39:21
+   |
+LL |     fn dummy3(self: &&Bar<T>) {}
+   |                     ^^^^^^^^ lifetime mismatch
+   |
+   = note: expected type `&'a Bar<T>`
+              found type `&Bar<T>`
+note: the lifetime 'a as defined on the impl at 35:6...
+  --> $DIR/ufcs-explicit-self-bad.rs:35:6
+   |
+LL | impl<'a, T> SomeTrait for &'a Bar<T> {
+   |      ^^
+note: ...does not necessarily outlive the anonymous lifetime #2 defined on the method body at 39:5
+  --> $DIR/ufcs-explicit-self-bad.rs:39:5
+   |
+LL |     fn dummy3(self: &&Bar<T>) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 7 previous errors
+
+Some errors occurred: E0307, E0308.
+For more information about an error, try `rustc --explain E0307`.
diff --git a/src/test/ui/ufcs/ufcs-partially-resolved.rs b/src/test/ui/ufcs/ufcs-partially-resolved.rs
new file mode 100644
index 0000000..4efded8
--- /dev/null
+++ b/src/test/ui/ufcs/ufcs-partially-resolved.rs
@@ -0,0 +1,56 @@
+#![feature(associated_type_defaults)]
+
+trait Tr {
+    type Y = u16;
+    fn Y() {}
+}
+impl Tr for u8 {}
+
+trait Dr {
+    type X = u16;
+    fn Z() {}
+}
+impl Dr for u8 {}
+
+enum E { Y }
+type A = u32;
+
+fn main() {
+    let _: <u8 as Tr>::N; //~ ERROR cannot find associated type `N` in trait `Tr`
+    let _: <u8 as E>::N; //~ ERROR cannot find associated type `N` in enum `E`
+    let _: <u8 as A>::N; //~ ERROR cannot find associated type `N` in `A`
+    <u8 as Tr>::N; //~ ERROR cannot find method or associated constant `N` in trait `Tr`
+    <u8 as E>::N; //~ ERROR cannot find method or associated constant `N` in enum `E`
+    <u8 as A>::N; //~ ERROR cannot find method or associated constant `N` in `A`
+    let _: <u8 as Tr>::Y; // OK
+    let _: <u8 as E>::Y; //~ ERROR expected associated type, found variant `E::Y`
+    <u8 as Tr>::Y; // OK
+    <u8 as E>::Y; //~ ERROR expected method or associated constant, found unit variant `E::Y`
+
+    let _: <u8 as Tr>::N::NN; //~ ERROR cannot find associated type `N` in trait `Tr`
+    let _: <u8 as E>::N::NN; //~ ERROR cannot find associated type `N` in enum `E`
+    let _: <u8 as A>::N::NN; //~ ERROR cannot find associated type `N` in `A`
+    <u8 as Tr>::N::NN; //~ ERROR cannot find associated type `N` in trait `Tr`
+    <u8 as E>::N::NN; //~ ERROR cannot find associated type `N` in enum `E`
+    <u8 as A>::N::NN; //~ ERROR cannot find associated type `N` in `A`
+    let _: <u8 as Tr>::Y::NN; //~ ERROR ambiguous associated type
+    let _: <u8 as E>::Y::NN; //~ ERROR expected associated type, found variant `E::Y`
+    <u8 as Tr>::Y::NN; //~ ERROR no associated item named `NN` found for type `<u8 as Tr>::Y`
+    <u8 as E>::Y::NN; //~ ERROR expected associated type, found variant `E::Y`
+
+    let _: <u8 as Tr::N>::NN; //~ ERROR cannot find associated type `NN` in `Tr::N`
+    let _: <u8 as E::N>::NN; //~ ERROR cannot find associated type `NN` in `E::N`
+    let _: <u8 as A::N>::NN; //~ ERROR cannot find associated type `NN` in `A::N`
+    <u8 as Tr::N>::NN; //~ ERROR cannot find method or associated constant `NN` in `Tr::N`
+    <u8 as E::N>::NN; //~ ERROR cannot find method or associated constant `NN` in `E::N`
+    <u8 as A::N>::NN; //~ ERROR cannot find method or associated constant `NN` in `A::N`
+    let _: <u8 as Tr::Y>::NN; //~ ERROR cannot find associated type `NN` in `Tr::Y`
+    let _: <u8 as E::Y>::NN; //~ ERROR failed to resolve: not a module `Y`
+    <u8 as Tr::Y>::NN; //~ ERROR cannot find method or associated constant `NN` in `Tr::Y`
+    <u8 as E::Y>::NN; //~ ERROR failed to resolve: not a module `Y`
+
+    let _: <u8 as Dr>::Z; //~ ERROR expected associated type, found method `Dr::Z`
+    <u8 as Dr>::X; //~ ERROR expected method or associated constant, found associated type `Dr::X`
+    let _: <u8 as Dr>::Z::N; //~ ERROR expected associated type, found method `Dr::Z`
+    <u8 as Dr>::X::N; //~ ERROR no associated item named `N` found for type `<u8 as Dr>::X`
+}
diff --git a/src/test/ui/ufcs/ufcs-partially-resolved.stderr b/src/test/ui/ufcs/ufcs-partially-resolved.stderr
new file mode 100644
index 0000000..900c729
--- /dev/null
+++ b/src/test/ui/ufcs/ufcs-partially-resolved.stderr
@@ -0,0 +1,204 @@
+error[E0433]: failed to resolve: not a module `Y`
+  --> $DIR/ufcs-partially-resolved.rs:48:22
+   |
+LL |     let _: <u8 as E::Y>::NN;
+   |                      ^ not a module `Y`
+
+error[E0433]: failed to resolve: not a module `Y`
+  --> $DIR/ufcs-partially-resolved.rs:50:15
+   |
+LL |     <u8 as E::Y>::NN;
+   |               ^ not a module `Y`
+
+error[E0576]: cannot find associated type `N` in trait `Tr`
+  --> $DIR/ufcs-partially-resolved.rs:19:24
+   |
+LL |     let _: <u8 as Tr>::N;
+   |                        ^ help: an associated type with a similar name exists: `Y`
+
+error[E0576]: cannot find associated type `N` in enum `E`
+  --> $DIR/ufcs-partially-resolved.rs:20:23
+   |
+LL |     let _: <u8 as E>::N;
+   |                       ^ not found in `E`
+
+error[E0576]: cannot find associated type `N` in `A`
+  --> $DIR/ufcs-partially-resolved.rs:21:23
+   |
+LL |     let _: <u8 as A>::N;
+   |                       ^ not found in `A`
+
+error[E0576]: cannot find method or associated constant `N` in trait `Tr`
+  --> $DIR/ufcs-partially-resolved.rs:22:17
+   |
+LL |     <u8 as Tr>::N;
+   |                 ^ help: a method with a similar name exists: `Y`
+
+error[E0576]: cannot find method or associated constant `N` in enum `E`
+  --> $DIR/ufcs-partially-resolved.rs:23:16
+   |
+LL |     <u8 as E>::N;
+   |                ^ not found in `E`
+
+error[E0576]: cannot find method or associated constant `N` in `A`
+  --> $DIR/ufcs-partially-resolved.rs:24:16
+   |
+LL |     <u8 as A>::N;
+   |                ^ not found in `A`
+
+error[E0575]: expected associated type, found variant `E::Y`
+  --> $DIR/ufcs-partially-resolved.rs:26:12
+   |
+LL |     let _: <u8 as E>::Y;
+   |            ^^^^^^^^^^^^ not a associated type
+
+error[E0575]: expected method or associated constant, found unit variant `E::Y`
+  --> $DIR/ufcs-partially-resolved.rs:28:5
+   |
+LL |     <u8 as E>::Y;
+   |     ^^^^^^^^^^^^ not a method or associated constant
+
+error[E0576]: cannot find associated type `N` in trait `Tr`
+  --> $DIR/ufcs-partially-resolved.rs:30:24
+   |
+LL |     let _: <u8 as Tr>::N::NN;
+   |                        ^ help: an associated type with a similar name exists: `Y`
+
+error[E0576]: cannot find associated type `N` in enum `E`
+  --> $DIR/ufcs-partially-resolved.rs:31:23
+   |
+LL |     let _: <u8 as E>::N::NN;
+   |                       ^ not found in `E`
+
+error[E0576]: cannot find associated type `N` in `A`
+  --> $DIR/ufcs-partially-resolved.rs:32:23
+   |
+LL |     let _: <u8 as A>::N::NN;
+   |                       ^ not found in `A`
+
+error[E0576]: cannot find associated type `N` in trait `Tr`
+  --> $DIR/ufcs-partially-resolved.rs:33:17
+   |
+LL |     <u8 as Tr>::N::NN;
+   |                 ^ help: an associated type with a similar name exists: `Y`
+
+error[E0576]: cannot find associated type `N` in enum `E`
+  --> $DIR/ufcs-partially-resolved.rs:34:16
+   |
+LL |     <u8 as E>::N::NN;
+   |                ^ not found in `E`
+
+error[E0576]: cannot find associated type `N` in `A`
+  --> $DIR/ufcs-partially-resolved.rs:35:16
+   |
+LL |     <u8 as A>::N::NN;
+   |                ^ not found in `A`
+
+error[E0575]: expected associated type, found variant `E::Y`
+  --> $DIR/ufcs-partially-resolved.rs:37:12
+   |
+LL |     let _: <u8 as E>::Y::NN;
+   |            ^^^^^^^^^^^^^^^^ not a associated type
+
+error[E0575]: expected associated type, found variant `E::Y`
+  --> $DIR/ufcs-partially-resolved.rs:39:5
+   |
+LL |     <u8 as E>::Y::NN;
+   |     ^^^^^^^^^^^^^^^^ not a associated type
+
+error[E0576]: cannot find associated type `NN` in `Tr::N`
+  --> $DIR/ufcs-partially-resolved.rs:41:27
+   |
+LL |     let _: <u8 as Tr::N>::NN;
+   |                           ^^ not found in `Tr::N`
+
+error[E0576]: cannot find associated type `NN` in `E::N`
+  --> $DIR/ufcs-partially-resolved.rs:42:26
+   |
+LL |     let _: <u8 as E::N>::NN;
+   |                          ^^ not found in `E::N`
+
+error[E0576]: cannot find associated type `NN` in `A::N`
+  --> $DIR/ufcs-partially-resolved.rs:43:26
+   |
+LL |     let _: <u8 as A::N>::NN;
+   |                          ^^ not found in `A::N`
+
+error[E0576]: cannot find method or associated constant `NN` in `Tr::N`
+  --> $DIR/ufcs-partially-resolved.rs:44:20
+   |
+LL |     <u8 as Tr::N>::NN;
+   |                    ^^ not found in `Tr::N`
+
+error[E0576]: cannot find method or associated constant `NN` in `E::N`
+  --> $DIR/ufcs-partially-resolved.rs:45:19
+   |
+LL |     <u8 as E::N>::NN;
+   |                   ^^ not found in `E::N`
+
+error[E0576]: cannot find method or associated constant `NN` in `A::N`
+  --> $DIR/ufcs-partially-resolved.rs:46:19
+   |
+LL |     <u8 as A::N>::NN;
+   |                   ^^ not found in `A::N`
+
+error[E0576]: cannot find associated type `NN` in `Tr::Y`
+  --> $DIR/ufcs-partially-resolved.rs:47:27
+   |
+LL |     let _: <u8 as Tr::Y>::NN;
+   |                           ^^ not found in `Tr::Y`
+
+error[E0576]: cannot find method or associated constant `NN` in `Tr::Y`
+  --> $DIR/ufcs-partially-resolved.rs:49:20
+   |
+LL |     <u8 as Tr::Y>::NN;
+   |                    ^^ not found in `Tr::Y`
+
+error[E0575]: expected associated type, found method `Dr::Z`
+  --> $DIR/ufcs-partially-resolved.rs:52:12
+   |
+LL |     let _: <u8 as Dr>::Z;
+   |            ^^^^^^^^^^^^-
+   |                        |
+   |                        help: an associated type with a similar name exists: `X`
+
+error[E0575]: expected method or associated constant, found associated type `Dr::X`
+  --> $DIR/ufcs-partially-resolved.rs:53:5
+   |
+LL |     <u8 as Dr>::X;
+   |     ^^^^^^^^^^^^-
+   |                 |
+   |                 help: a method with a similar name exists: `Z`
+   |
+   = note: can't use a type alias as a constructor
+
+error[E0575]: expected associated type, found method `Dr::Z`
+  --> $DIR/ufcs-partially-resolved.rs:54:12
+   |
+LL |     let _: <u8 as Dr>::Z::N;
+   |            ^^^^^^^^^^^^-^^^
+   |                        |
+   |                        help: an associated type with a similar name exists: `X`
+
+error[E0223]: ambiguous associated type
+  --> $DIR/ufcs-partially-resolved.rs:36:12
+   |
+LL |     let _: <u8 as Tr>::Y::NN;
+   |            ^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<<u8 as Tr>::Y as Trait>::NN`
+
+error[E0599]: no associated item named `NN` found for type `<u8 as Tr>::Y` in the current scope
+  --> $DIR/ufcs-partially-resolved.rs:38:20
+   |
+LL |     <u8 as Tr>::Y::NN;
+   |                    ^^ associated item not found in `<u8 as Tr>::Y`
+
+error[E0599]: no associated item named `N` found for type `<u8 as Dr>::X` in the current scope
+  --> $DIR/ufcs-partially-resolved.rs:55:20
+   |
+LL |     <u8 as Dr>::X::N;
+   |                    ^ associated item not found in `<u8 as Dr>::X`
+
+error: aborting due to 32 previous errors
+
+Some errors occurred: E0223, E0433, E0575, E0576, E0599.
+For more information about an error, try `rustc --explain E0223`.
diff --git a/src/test/ui/ufcs/ufcs-qpath-missing-params.rs b/src/test/ui/ufcs/ufcs-qpath-missing-params.rs
new file mode 100644
index 0000000..8b66a8f
--- /dev/null
+++ b/src/test/ui/ufcs/ufcs-qpath-missing-params.rs
@@ -0,0 +1,16 @@
+use std::borrow::Cow;
+
+pub trait IntoCow<'a, B: ?Sized> where B: ToOwned {
+    fn into_cow(self) -> Cow<'a, B>;
+}
+
+impl<'a> IntoCow<'a, str> for String {
+    fn into_cow(self) -> Cow<'a, str> {
+        Cow::Owned(self)
+    }
+}
+
+fn main() {
+    <String as IntoCow>::into_cow("foo".to_string());
+    //~^ ERROR wrong number of type arguments: expected 1, found 0
+}
diff --git a/src/test/ui/ufcs/ufcs-qpath-missing-params.stderr b/src/test/ui/ufcs/ufcs-qpath-missing-params.stderr
new file mode 100644
index 0000000..1145f1e
--- /dev/null
+++ b/src/test/ui/ufcs/ufcs-qpath-missing-params.stderr
@@ -0,0 +1,9 @@
+error[E0107]: wrong number of type arguments: expected 1, found 0
+  --> $DIR/ufcs-qpath-missing-params.rs:14:5
+   |
+LL |     <String as IntoCow>::into_cow("foo".to_string());
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 1 type argument
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0107`.
diff --git a/src/test/ui/ufcs/ufcs-qpath-self-mismatch.rs b/src/test/ui/ufcs/ufcs-qpath-self-mismatch.rs
new file mode 100644
index 0000000..939b3c5
--- /dev/null
+++ b/src/test/ui/ufcs/ufcs-qpath-self-mismatch.rs
@@ -0,0 +1,10 @@
+use std::ops::Add;
+
+fn main() {
+    <i32 as Add<u32>>::add(1, 2);
+    //~^ ERROR cannot add `u32` to `i32`
+    <i32 as Add<i32>>::add(1u32, 2);
+    //~^ ERROR mismatched types
+    <i32 as Add<i32>>::add(1, 2u32);
+    //~^ ERROR mismatched types
+}
diff --git a/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr b/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr
new file mode 100644
index 0000000..e3027ee
--- /dev/null
+++ b/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr
@@ -0,0 +1,24 @@
+error[E0277]: cannot add `u32` to `i32`
+  --> $DIR/ufcs-qpath-self-mismatch.rs:4:5
+   |
+LL |     <i32 as Add<u32>>::add(1, 2);
+   |     ^^^^^^^^^^^^^^^^^^^^^^ no implementation for `i32 + u32`
+   |
+   = help: the trait `std::ops::Add<u32>` is not implemented for `i32`
+
+error[E0308]: mismatched types
+  --> $DIR/ufcs-qpath-self-mismatch.rs:6:28
+   |
+LL |     <i32 as Add<i32>>::add(1u32, 2);
+   |                            ^^^^ expected i32, found u32
+
+error[E0308]: mismatched types
+  --> $DIR/ufcs-qpath-self-mismatch.rs:8:31
+   |
+LL |     <i32 as Add<i32>>::add(1, 2u32);
+   |                               ^^^^ expected i32, found u32
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0277, E0308.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/ui-testing-optout.rs b/src/test/ui/ui-testing-optout.rs
new file mode 100644
index 0000000..041c0b0
--- /dev/null
+++ b/src/test/ui/ui-testing-optout.rs
@@ -0,0 +1,97 @@
+// disable-ui-testing-normalization
+
+// Line number < 10
+type A = B; //~ ERROR
+
+// http://rust-lang.org/COPYRIGHT.
+//
+
+// Line number >=10, <100
+type C = D; //~ ERROR
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+// Line num >=100
+type E = F; //~ ERROR
+
+fn main() {}
diff --git a/src/test/ui/ui-testing-optout.stderr b/src/test/ui/ui-testing-optout.stderr
new file mode 100644
index 0000000..313e198
--- /dev/null
+++ b/src/test/ui/ui-testing-optout.stderr
@@ -0,0 +1,21 @@
+error[E0412]: cannot find type `B` in this scope
+ --> $DIR/ui-testing-optout.rs:4:10
+  |
+4 | type A = B;
+  |          ^ help: a type alias with a similar name exists: `A`
+
+error[E0412]: cannot find type `D` in this scope
+  --> $DIR/ui-testing-optout.rs:10:10
+   |
+10 | type C = D;
+   |          ^ help: a type alias with a similar name exists: `A`
+
+error[E0412]: cannot find type `F` in this scope
+  --> $DIR/ui-testing-optout.rs:95:10
+   |
+95 | type E = F;
+   |          ^ help: a type alias with a similar name exists: `A`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-feature-gate.rs b/src/test/ui/unboxed-closures/unboxed-closure-feature-gate.rs
new file mode 100644
index 0000000..1eb9de7
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closure-feature-gate.rs
@@ -0,0 +1,20 @@
+// Check that parenthetical notation is feature-gated except with the
+// `Fn` traits.
+
+use std::marker;
+
+trait Foo<A> {
+    type Output;
+
+    fn dummy(&self, a: A) { }
+}
+
+fn main() {
+    let x: Box<Foo(isize)>;
+    //~^ ERROR parenthetical notation is only stable when used with `Fn`-family
+
+    // No errors with these:
+    let x: Box<Fn(isize)>;
+    let x: Box<FnMut(isize)>;
+    let x: Box<FnOnce(isize)>;
+}
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-feature-gate.stderr b/src/test/ui/unboxed-closures/unboxed-closure-feature-gate.stderr
new file mode 100644
index 0000000..038167a
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closure-feature-gate.stderr
@@ -0,0 +1,11 @@
+error[E0658]: parenthetical notation is only stable when used with `Fn`-family traits (see issue #29625)
+  --> $DIR/unboxed-closure-feature-gate.rs:13:16
+   |
+LL |     let x: Box<Foo(isize)>;
+   |                ^^^^^^^^^^
+   |
+   = help: add #![feature(unboxed_closures)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-illegal-move.nll.stderr b/src/test/ui/unboxed-closures/unboxed-closure-illegal-move.nll.stderr
new file mode 100644
index 0000000..934d057
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closure-illegal-move.nll.stderr
@@ -0,0 +1,35 @@
+error[E0507]: cannot move out of captured variable in an `Fn` closure
+  --> $DIR/unboxed-closure-illegal-move.rs:15:31
+   |
+LL |         let x = Box::new(0);
+   |             - captured outer variable
+LL |         let f = to_fn(|| drop(x));
+   |                               ^ cannot move out of captured variable in an `Fn` closure
+
+error[E0507]: cannot move out of captured variable in an `FnMut` closure
+  --> $DIR/unboxed-closure-illegal-move.rs:19:35
+   |
+LL |         let x = Box::new(0);
+   |             - captured outer variable
+LL |         let f = to_fn_mut(|| drop(x));
+   |                                   ^ cannot move out of captured variable in an `FnMut` closure
+
+error[E0507]: cannot move out of captured variable in an `Fn` closure
+  --> $DIR/unboxed-closure-illegal-move.rs:28:36
+   |
+LL |         let x = Box::new(0);
+   |             - captured outer variable
+LL |         let f = to_fn(move || drop(x));
+   |                                    ^ cannot move out of captured variable in an `Fn` closure
+
+error[E0507]: cannot move out of captured variable in an `FnMut` closure
+  --> $DIR/unboxed-closure-illegal-move.rs:32:40
+   |
+LL |         let x = Box::new(0);
+   |             - captured outer variable
+LL |         let f = to_fn_mut(move || drop(x));
+   |                                        ^ cannot move out of captured variable in an `FnMut` closure
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-illegal-move.rs b/src/test/ui/unboxed-closures/unboxed-closure-illegal-move.rs
new file mode 100644
index 0000000..ed8d721
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closure-illegal-move.rs
@@ -0,0 +1,38 @@
+#![feature(unboxed_closures)]
+
+// Tests that we can't move out of an unboxed closure environment
+// if the upvar is captured by ref or the closure takes self by
+// reference.
+
+fn to_fn<A,F:Fn<A>>(f: F) -> F { f }
+fn to_fn_mut<A,F:FnMut<A>>(f: F) -> F { f }
+fn to_fn_once<A,F:FnOnce<A>>(f: F) -> F { f }
+
+fn main() {
+    // By-ref cases
+    {
+        let x = Box::new(0);
+        let f = to_fn(|| drop(x)); //~ ERROR cannot move
+    }
+    {
+        let x = Box::new(0);
+        let f = to_fn_mut(|| drop(x)); //~ ERROR cannot move
+    }
+    {
+        let x = Box::new(0);
+        let f = to_fn_once(|| drop(x)); // OK -- FnOnce
+    }
+    // By-value cases
+    {
+        let x = Box::new(0);
+        let f = to_fn(move || drop(x)); //~ ERROR cannot move
+    }
+    {
+        let x = Box::new(0);
+        let f = to_fn_mut(move || drop(x)); //~ ERROR cannot move
+    }
+    {
+        let x = Box::new(0);
+        let f = to_fn_once(move || drop(x)); // this one is ok
+    }
+}
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-illegal-move.stderr b/src/test/ui/unboxed-closures/unboxed-closure-illegal-move.stderr
new file mode 100644
index 0000000..7620f6a
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closure-illegal-move.stderr
@@ -0,0 +1,35 @@
+error[E0507]: cannot move out of captured outer variable in an `Fn` closure
+  --> $DIR/unboxed-closure-illegal-move.rs:15:31
+   |
+LL |         let x = Box::new(0);
+   |             - captured outer variable
+LL |         let f = to_fn(|| drop(x));
+   |                               ^ cannot move out of captured outer variable in an `Fn` closure
+
+error[E0507]: cannot move out of captured outer variable in an `FnMut` closure
+  --> $DIR/unboxed-closure-illegal-move.rs:19:35
+   |
+LL |         let x = Box::new(0);
+   |             - captured outer variable
+LL |         let f = to_fn_mut(|| drop(x));
+   |                                   ^ cannot move out of captured outer variable in an `FnMut` closure
+
+error[E0507]: cannot move out of captured outer variable in an `Fn` closure
+  --> $DIR/unboxed-closure-illegal-move.rs:28:36
+   |
+LL |         let x = Box::new(0);
+   |             - captured outer variable
+LL |         let f = to_fn(move || drop(x));
+   |                                    ^ cannot move out of captured outer variable in an `Fn` closure
+
+error[E0507]: cannot move out of captured outer variable in an `FnMut` closure
+  --> $DIR/unboxed-closure-illegal-move.rs:32:40
+   |
+LL |         let x = Box::new(0);
+   |             - captured outer variable
+LL |         let f = to_fn_mut(move || drop(x));
+   |                                        ^ cannot move out of captured outer variable in an `FnMut` closure
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-immutable-capture.nll.stderr b/src/test/ui/unboxed-closures/unboxed-closure-immutable-capture.nll.stderr
new file mode 100644
index 0000000..3e7f790
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closure-immutable-capture.nll.stderr
@@ -0,0 +1,75 @@
+error[E0594]: cannot assign to `x`, as it is not declared as mutable
+  --> $DIR/unboxed-closure-immutable-capture.rs:9:13
+   |
+LL |     let x = 0;
+   |         - help: consider changing this to be mutable: `mut x`
+LL |     move || x = 1;
+   |             ^^^^^ cannot assign
+
+error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
+  --> $DIR/unboxed-closure-immutable-capture.rs:10:17
+   |
+LL |     let x = 0;
+   |         - help: consider changing this to be mutable: `mut x`
+LL |     move || x = 1;
+LL |     move || set(&mut x);
+   |                 ^^^^^^ cannot borrow as mutable
+
+error[E0594]: cannot assign to `x`, as it is not declared as mutable
+  --> $DIR/unboxed-closure-immutable-capture.rs:11:13
+   |
+LL |     let x = 0;
+   |         - help: consider changing this to be mutable: `mut x`
+...
+LL |     move || x = 1;
+   |             ^^^^^ cannot assign
+
+error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
+  --> $DIR/unboxed-closure-immutable-capture.rs:12:17
+   |
+LL |     let x = 0;
+   |         - help: consider changing this to be mutable: `mut x`
+...
+LL |     move || set(&mut x);
+   |                 ^^^^^^ cannot borrow as mutable
+
+error[E0594]: cannot assign to `x`, as it is not declared as mutable
+  --> $DIR/unboxed-closure-immutable-capture.rs:13:8
+   |
+LL |     let x = 0;
+   |         - help: consider changing this to be mutable: `mut x`
+...
+LL |     || x = 1;
+   |        ^^^^^ cannot assign
+
+error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
+  --> $DIR/unboxed-closure-immutable-capture.rs:15:12
+   |
+LL |     let x = 0;
+   |         - help: consider changing this to be mutable: `mut x`
+...
+LL |     || set(&mut x);
+   |            ^^^^^^ cannot borrow as mutable
+
+error[E0594]: cannot assign to `x`, as it is not declared as mutable
+  --> $DIR/unboxed-closure-immutable-capture.rs:16:8
+   |
+LL |     let x = 0;
+   |         - help: consider changing this to be mutable: `mut x`
+...
+LL |     || x = 1;
+   |        ^^^^^ cannot assign
+
+error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
+  --> $DIR/unboxed-closure-immutable-capture.rs:18:12
+   |
+LL |     let x = 0;
+   |         - help: consider changing this to be mutable: `mut x`
+...
+LL |     || set(&mut x);
+   |            ^^^^^^ cannot borrow as mutable
+
+error: aborting due to 8 previous errors
+
+Some errors occurred: E0594, E0596.
+For more information about an error, try `rustc --explain E0594`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-immutable-capture.rs b/src/test/ui/unboxed-closures/unboxed-closure-immutable-capture.rs
new file mode 100644
index 0000000..5d59cec
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closure-immutable-capture.rs
@@ -0,0 +1,19 @@
+// Test that even unboxed closures that are capable of mutating their
+// environment cannot mutate captured variables that have not been
+// declared mutable (#18335)
+
+fn set(x: &mut usize) { *x = 0; }
+
+fn main() {
+    let x = 0;
+    move || x = 1; //~ ERROR cannot assign
+    move || set(&mut x); //~ ERROR cannot borrow
+    move || x = 1; //~ ERROR cannot assign
+    move || set(&mut x); //~ ERROR cannot borrow
+    || x = 1; //~ ERROR cannot assign
+    // FIXME: this should be `cannot borrow` (issue #18330)
+    || set(&mut x); //~ ERROR cannot assign
+    || x = 1; //~ ERROR cannot assign
+    // FIXME: this should be `cannot borrow` (issue #18330)
+    || set(&mut x); //~ ERROR cannot assign
+}
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-immutable-capture.stderr b/src/test/ui/unboxed-closures/unboxed-closure-immutable-capture.stderr
new file mode 100644
index 0000000..e4aa540
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closure-immutable-capture.stderr
@@ -0,0 +1,69 @@
+error[E0595]: closure cannot assign to immutable local variable `x`
+  --> $DIR/unboxed-closure-immutable-capture.rs:13:5
+   |
+LL |     let x = 0;
+   |         - help: make this binding mutable: `mut x`
+...
+LL |     || x = 1;
+   |     ^^ cannot borrow mutably
+
+error[E0595]: closure cannot assign to immutable local variable `x`
+  --> $DIR/unboxed-closure-immutable-capture.rs:15:5
+   |
+LL |     let x = 0;
+   |         - help: make this binding mutable: `mut x`
+...
+LL |     || set(&mut x);
+   |     ^^ cannot borrow mutably
+
+error[E0595]: closure cannot assign to immutable local variable `x`
+  --> $DIR/unboxed-closure-immutable-capture.rs:16:5
+   |
+LL |     let x = 0;
+   |         - help: make this binding mutable: `mut x`
+...
+LL |     || x = 1;
+   |     ^^ cannot borrow mutably
+
+error[E0595]: closure cannot assign to immutable local variable `x`
+  --> $DIR/unboxed-closure-immutable-capture.rs:18:5
+   |
+LL |     let x = 0;
+   |         - help: make this binding mutable: `mut x`
+...
+LL |     || set(&mut x);
+   |     ^^ cannot borrow mutably
+
+error[E0594]: cannot assign to captured outer variable in an `FnMut` closure
+  --> $DIR/unboxed-closure-immutable-capture.rs:9:13
+   |
+LL |     let x = 0;
+   |         - help: consider making `x` mutable: `mut x`
+LL |     move || x = 1;
+   |             ^^^^^
+
+error[E0596]: cannot borrow captured outer variable in an `FnMut` closure as mutable
+  --> $DIR/unboxed-closure-immutable-capture.rs:10:22
+   |
+LL |     move || set(&mut x);
+   |                      ^
+
+error[E0594]: cannot assign to captured outer variable in an `FnMut` closure
+  --> $DIR/unboxed-closure-immutable-capture.rs:11:13
+   |
+LL |     let x = 0;
+   |         - help: consider making `x` mutable: `mut x`
+...
+LL |     move || x = 1;
+   |             ^^^^^
+
+error[E0596]: cannot borrow captured outer variable in an `FnMut` closure as mutable
+  --> $DIR/unboxed-closure-immutable-capture.rs:12:22
+   |
+LL |     move || set(&mut x);
+   |                      ^
+
+error: aborting due to 8 previous errors
+
+Some errors occurred: E0594, E0595, E0596.
+For more information about an error, try `rustc --explain E0594`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-no-cyclic-sig.rs b/src/test/ui/unboxed-closures/unboxed-closure-no-cyclic-sig.rs
new file mode 100644
index 0000000..9d0aa41
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closure-no-cyclic-sig.rs
@@ -0,0 +1,9 @@
+// Test that unboxed closures cannot capture their own type.
+//
+// Also regression test for issue #21410.
+
+fn g<F>(_: F) where F: FnOnce(Option<F>) {}
+
+fn main() {
+    g(|_| {  }); //~ ERROR closure/generator type that references itself
+}
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-no-cyclic-sig.stderr b/src/test/ui/unboxed-closures/unboxed-closure-no-cyclic-sig.stderr
new file mode 100644
index 0000000..0d37664
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closure-no-cyclic-sig.stderr
@@ -0,0 +1,13 @@
+error[E0644]: closure/generator type that references itself
+  --> $DIR/unboxed-closure-no-cyclic-sig.rs:8:7
+   |
+LL |     g(|_| {  });
+   |       ^^^^^^^^ cyclic type of infinite size
+   |
+   = note: closures cannot capture themselves or take themselves as argument;
+           this error may be the result of a recent compiler bug-fix,
+           see https://github.com/rust-lang/rust/issues/46062 for more details
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0644`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-region.nll.stderr b/src/test/ui/unboxed-closures/unboxed-closure-region.nll.stderr
new file mode 100644
index 0000000..b40b2f6
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closure-region.nll.stderr
@@ -0,0 +1,16 @@
+error[E0597]: `x` does not live long enough
+  --> $DIR/unboxed-closure-region.rs:8:12
+   |
+LL |     let _f = {
+   |         -- borrow later stored here
+LL |         let x = 0;
+LL |         || x
+   |         -- ^ borrowed value does not live long enough
+   |         |
+   |         value captured here
+LL |     };
+   |     - `x` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-region.rs b/src/test/ui/unboxed-closures/unboxed-closure-region.rs
new file mode 100644
index 0000000..f202492
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closure-region.rs
@@ -0,0 +1,11 @@
+// Test that an unboxed closure that captures a free variable by
+// reference cannot escape the region of that variable.
+
+
+fn main() {
+    let _f = {
+        let x = 0;
+        || x //~ ERROR `x` does not live long enough
+    };
+    _f;
+}
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-region.stderr b/src/test/ui/unboxed-closures/unboxed-closure-region.stderr
new file mode 100644
index 0000000..f710342
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closure-region.stderr
@@ -0,0 +1,16 @@
+error[E0597]: `x` does not live long enough
+  --> $DIR/unboxed-closure-region.rs:8:12
+   |
+LL |         || x
+   |         -- ^ borrowed value does not live long enough
+   |         |
+   |         capture occurs here
+LL |     };
+   |     - borrowed value only lives until here
+LL |     _f;
+LL | }
+   | - borrowed value needs to live until here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-default.rs b/src/test/ui/unboxed-closures/unboxed-closure-sugar-default.rs
new file mode 100644
index 0000000..044859d
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-default.rs
@@ -0,0 +1,28 @@
+// Test interaction between unboxed closure sugar and default type
+// parameters (should be exactly as if angle brackets were used).
+
+#![feature(unboxed_closures)]
+#![allow(dead_code)]
+
+trait Foo<T,V=T> {
+    type Output;
+    fn dummy(&self, t: T, v: V);
+}
+
+trait Eq<X: ?Sized> { fn same_types(&self, x: &X) -> bool { true } }
+impl<X: ?Sized> Eq<X> for X { }
+fn eq<A: ?Sized,B: ?Sized>() where A : Eq<B> { }
+
+fn test<'a,'b>() {
+    // Parens are equivalent to omitting default in angle.
+    eq::< Foo<(isize,),Output=()>,                   Foo(isize)                      >();
+
+    // In angle version, we supply something other than the default
+    eq::< Foo<(isize,),isize,Output=()>,      Foo(isize)                      >();
+    //~^ ERROR E0277
+
+    // Supply default explicitly.
+    eq::< Foo<(isize,),(isize,),Output=()>,   Foo(isize)                      >();
+}
+
+fn main() { }
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-default.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-default.stderr
new file mode 100644
index 0000000..ce90f5b
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-default.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `dyn Foo<(isize,), isize, Output = ()>: Eq<dyn Foo<(isize,), Output = ()>>` is not satisfied
+  --> $DIR/unboxed-closure-sugar-default.rs:21:5
+   |
+LL |     eq::< Foo<(isize,),isize,Output=()>,      Foo(isize)                      >();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Eq<dyn Foo<(isize,), Output = ()>>` is not implemented for `dyn Foo<(isize,), isize, Output = ()>`
+   |
+note: required by `eq`
+  --> $DIR/unboxed-closure-sugar-default.rs:14:1
+   |
+LL | fn eq<A: ?Sized,B: ?Sized>() where A : Eq<B> { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-equiv.rs b/src/test/ui/unboxed-closures/unboxed-closure-sugar-equiv.rs
new file mode 100644
index 0000000..95bd391
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-equiv.rs
@@ -0,0 +1,48 @@
+// Test that the unboxed closure sugar can be used with an arbitrary
+// struct type and that it is equivalent to the same syntax using
+// angle brackets. This test covers only simple types and in
+// particular doesn't test bound regions.
+
+#![feature(unboxed_closures)]
+#![allow(dead_code)]
+
+trait Foo<T> {
+    type Output;
+    fn dummy(&self, t: T, u: Self::Output);
+}
+
+trait Eq<X: ?Sized> { }
+impl<X: ?Sized> Eq<X> for X { }
+fn eq<A: ?Sized,B: ?Sized +Eq<A>>() { }
+
+fn test<'a,'b>() {
+    // No errors expected:
+    eq::< Foo<(),Output=()>,                       Foo()                         >();
+    eq::< Foo<(isize,),Output=()>,                 Foo(isize)                      >();
+    eq::< Foo<(isize,usize),Output=()>,            Foo(isize,usize)                 >();
+    eq::< Foo<(isize,usize),Output=usize>,         Foo(isize,usize) -> usize         >();
+    eq::< Foo<(&'a isize,&'b usize),Output=usize>, Foo(&'a isize,&'b usize) -> usize >();
+
+    // Test that anonymous regions in `()` form are equivalent
+    // to fresh bound regions, and that we can intermingle
+    // named and anonymous as we choose:
+    eq::< for<'x,'y> Foo<(&'x isize,&'y usize),Output=usize>,
+          for<'x,'y> Foo(&'x isize,&'y usize) -> usize            >();
+    eq::< for<'x,'y> Foo<(&'x isize,&'y usize),Output=usize>,
+          for<'x> Foo(&'x isize,&usize) -> usize                  >();
+    eq::< for<'x,'y> Foo<(&'x isize,&'y usize),Output=usize>,
+          for<'y> Foo(&isize,&'y usize) -> usize                  >();
+    eq::< for<'x,'y> Foo<(&'x isize,&'y usize),Output=usize>,
+          Foo(&isize,&usize) -> usize                             >();
+
+    // lifetime elision
+    eq::< for<'x> Foo<(&'x isize,), Output=&'x isize>,
+          Foo(&isize) -> &isize                                   >();
+
+    // Errors expected:
+    eq::< Foo<(),Output=()>,
+          Foo(char)                                               >();
+    //~^^ ERROR E0277
+}
+
+fn main() { }
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-equiv.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-equiv.stderr
new file mode 100644
index 0000000..857a32c
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-equiv.stderr
@@ -0,0 +1,16 @@
+error[E0277]: the trait bound `dyn Foo<(char,), Output = ()>: Eq<dyn Foo<(), Output = ()>>` is not satisfied
+  --> $DIR/unboxed-closure-sugar-equiv.rs:43:5
+   |
+LL | /     eq::< Foo<(),Output=()>,
+LL | |           Foo(char)                                               >();
+   | |___________________________________________________________________^ the trait `Eq<dyn Foo<(), Output = ()>>` is not implemented for `dyn Foo<(char,), Output = ()>`
+   |
+note: required by `eq`
+  --> $DIR/unboxed-closure-sugar-equiv.rs:16:1
+   |
+LL | fn eq<A: ?Sized,B: ?Sized +Eq<A>>() { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.rs b/src/test/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.rs
new file mode 100644
index 0000000..b61d8b8
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.rs
@@ -0,0 +1,27 @@
+// Test that the unboxed closure sugar can be used with an arbitrary
+// struct type and that it is equivalent to the same syntax using
+// angle brackets. This test covers only simple types and in
+// particular doesn't test bound regions.
+
+#![feature(unboxed_closures)]
+#![allow(dead_code)]
+
+use std::marker;
+
+trait Foo<T> {
+    type Output;
+    fn dummy(&self, t: T);
+}
+
+trait Eq<X: ?Sized> { }
+impl<X: ?Sized> Eq<X> for X { }
+fn eq<A: ?Sized,B: ?Sized +Eq<A>>() { }
+
+fn main() {
+    eq::< for<'a> Foo<(&'a isize,), Output=&'a isize>,
+          Foo(&isize) -> &isize                                   >();
+    eq::< for<'a> Foo<(&'a isize,), Output=(&'a isize, &'a isize)>,
+          Foo(&isize) -> (&isize, &isize)                           >();
+
+    let _: Foo(&isize, &usize) -> &usize; //~ ERROR missing lifetime specifier
+}
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.stderr
new file mode 100644
index 0000000..8c34807
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.stderr
@@ -0,0 +1,11 @@
+error[E0106]: missing lifetime specifier
+  --> $DIR/unboxed-closure-sugar-lifetime-elision.rs:26:35
+   |
+LL |     let _: Foo(&isize, &usize) -> &usize;
+   |                                   ^ expected lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0106`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-not-used-on-fn.rs b/src/test/ui/unboxed-closures/unboxed-closure-sugar-not-used-on-fn.rs
new file mode 100644
index 0000000..09927a9
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-not-used-on-fn.rs
@@ -0,0 +1,11 @@
+// Test that the `Fn` traits require `()` form without a feature gate.
+
+fn bar1(x: &Fn<(), Output=()>) {
+    //~^ ERROR of `Fn`-family traits' type parameters is subject to change
+}
+
+fn bar2<T>(x: &T) where T: Fn<()> {
+    //~^ ERROR of `Fn`-family traits' type parameters is subject to change
+}
+
+fn main() { }
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-not-used-on-fn.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-not-used-on-fn.stderr
new file mode 100644
index 0000000..90f04a5
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-not-used-on-fn.stderr
@@ -0,0 +1,19 @@
+error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change. Use parenthetical notation (Fn(Foo, Bar) -> Baz) instead (see issue #29625)
+  --> $DIR/unboxed-closure-sugar-not-used-on-fn.rs:3:13
+   |
+LL | fn bar1(x: &Fn<(), Output=()>) {
+   |             ^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unboxed_closures)] to the crate attributes to enable
+
+error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change. Use parenthetical notation (Fn(Foo, Bar) -> Baz) instead (see issue #29625)
+  --> $DIR/unboxed-closure-sugar-not-used-on-fn.rs:7:28
+   |
+LL | fn bar2<T>(x: &T) where T: Fn<()> {
+   |                            ^^^^^^
+   |
+   = help: add #![feature(unboxed_closures)] to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-region.rs b/src/test/ui/unboxed-closures/unboxed-closure-sugar-region.rs
new file mode 100644
index 0000000..799d9f3
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-region.rs
@@ -0,0 +1,36 @@
+// Test interaction between unboxed closure sugar and region
+// parameters (should be exactly as if angle brackets were used
+// and regions omitted).
+
+#![feature(unboxed_closures)]
+#![allow(dead_code)]
+
+use std::marker;
+
+trait Foo<'a,T> {
+    type Output;
+    fn dummy(&'a self) -> &'a (T,Self::Output);
+}
+
+trait Eq<X: ?Sized> { fn is_of_eq_type(&self, x: &X) -> bool { true } }
+impl<X: ?Sized> Eq<X> for X { }
+fn eq<A: ?Sized,B: ?Sized +Eq<A>>() { }
+
+fn same_type<A,B:Eq<A>>(a: A, b: B) { }
+
+fn test<'a,'b>() {
+    // Parens are equivalent to omitting default in angle.
+    eq::< Foo<(isize,),Output=()>,               Foo(isize)                      >();
+
+    // Here we specify 'static explicitly in angle-bracket version.
+    // Parenthesized winds up getting inferred.
+    eq::< Foo<'static, (isize,),Output=()>,      Foo(isize)                      >();
+}
+
+fn test2(x: &Foo<(isize,),Output=()>, y: &Foo(isize)) {
+//~^ ERROR wrong number of lifetime arguments: expected 1, found 0
+    // Here, the omitted lifetimes are expanded to distinct things.
+    same_type(x, y)
+}
+
+fn main() { }
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-region.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-region.stderr
new file mode 100644
index 0000000..8eed7d5
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-region.stderr
@@ -0,0 +1,9 @@
+error[E0107]: wrong number of lifetime arguments: expected 1, found 0
+  --> $DIR/unboxed-closure-sugar-region.rs:30:43
+   |
+LL | fn test2(x: &Foo<(isize,),Output=()>, y: &Foo(isize)) {
+   |                                           ^^^^^^^^^^ expected 1 lifetime argument
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0107`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.rs b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.rs
new file mode 100644
index 0000000..c96a6fa
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.rs
@@ -0,0 +1,13 @@
+// Test that parentheses form doesn't work with struct types appearing in local variables.
+
+struct Bar<A> {
+    f: A
+}
+
+fn bar() {
+    let x: Box<Bar()> = panic!();
+    //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
+    //~| ERROR wrong number of type arguments: expected 1, found 0
+}
+
+fn main() { }
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.stderr
new file mode 100644
index 0000000..fa52e66
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.stderr
@@ -0,0 +1,16 @@
+error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
+  --> $DIR/unboxed-closure-sugar-used-on-struct-1.rs:8:19
+   |
+LL |     let x: Box<Bar()> = panic!();
+   |                   ^^ only `Fn` traits may use parentheses
+
+error[E0107]: wrong number of type arguments: expected 1, found 0
+  --> $DIR/unboxed-closure-sugar-used-on-struct-1.rs:8:16
+   |
+LL |     let x: Box<Bar()> = panic!();
+   |                ^^^^^ expected 1 type argument
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0107, E0214.
+For more information about an error, try `rustc --explain E0107`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-3.rs b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-3.rs
new file mode 100644
index 0000000..79ced1e
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-3.rs
@@ -0,0 +1,18 @@
+// Test that parentheses form parses in expression paths.
+
+struct Bar<A,R> {
+    f: A, r: R
+}
+
+impl<A,B> Bar<A,B> {
+    fn new() -> Bar<A,B> { panic!() }
+}
+
+fn bar() {
+    let b = Bar::<isize, usize>::new(); // OK
+
+    let b = Bar::(isize, usize)::new(); // OK too (for the parser)
+    //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
+}
+
+fn main() {}
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-3.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-3.stderr
new file mode 100644
index 0000000..7d05ca5
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-3.stderr
@@ -0,0 +1,12 @@
+error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
+  --> $DIR/unboxed-closure-sugar-used-on-struct-3.rs:14:18
+   |
+LL |     let b = Bar::(isize, usize)::new(); // OK too (for the parser)
+   |                  ^^^^^^^^^^^^^^
+   |                  |
+   |                  only `Fn` traits may use parentheses
+   |                  help: use angle brackets instead: `<isize, usize>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0214`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.rs b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.rs
new file mode 100644
index 0000000..1af7f55
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.rs
@@ -0,0 +1,12 @@
+// Test that parentheses form doesn't work with struct types appearing in argument types.
+
+struct Bar<A> {
+    f: A
+}
+
+fn foo(b: Box<Bar()>) {
+    //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
+    //~| ERROR wrong number of type arguments: expected 1, found 0
+}
+
+fn main() { }
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.stderr
new file mode 100644
index 0000000..b342379
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.stderr
@@ -0,0 +1,16 @@
+error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
+  --> $DIR/unboxed-closure-sugar-used-on-struct.rs:7:18
+   |
+LL | fn foo(b: Box<Bar()>) {
+   |                  ^^ only `Fn` traits may use parentheses
+
+error[E0107]: wrong number of type arguments: expected 1, found 0
+  --> $DIR/unboxed-closure-sugar-used-on-struct.rs:7:15
+   |
+LL | fn foo(b: Box<Bar()>) {
+   |               ^^^^^ expected 1 type argument
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0107, E0214.
+For more information about an error, try `rustc --explain E0107`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-1.rs b/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-1.rs
new file mode 100644
index 0000000..df0c495
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-1.rs
@@ -0,0 +1,8 @@
+#![feature(unboxed_closures)]
+
+trait One<A> { fn foo(&self) -> A; }
+
+fn foo(_: &One()) //~ ERROR associated type `Output` not found for `One<()>`
+{}
+
+fn main() { }
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-1.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-1.stderr
new file mode 100644
index 0000000..304339c
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-1.stderr
@@ -0,0 +1,9 @@
+error[E0220]: associated type `Output` not found for `One<()>`
+  --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters-1.rs:5:15
+   |
+LL | fn foo(_: &One())
+   |               ^^ associated type `Output` not found
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0220`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.rs b/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.rs
new file mode 100644
index 0000000..5f5ad79
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.rs
@@ -0,0 +1,10 @@
+#![feature(unboxed_closures)]
+
+trait Three<A,B,C> { fn dummy(&self) -> (A,B,C); }
+
+fn foo(_: &Three())
+//~^ ERROR wrong number of type arguments
+//~| ERROR associated type `Output` not found
+{}
+
+fn main() { }
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.stderr
new file mode 100644
index 0000000..3a9fff3
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.stderr
@@ -0,0 +1,16 @@
+error[E0107]: wrong number of type arguments: expected 3, found 1
+  --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters-3.rs:5:12
+   |
+LL | fn foo(_: &Three())
+   |            ^^^^^^^ expected 3 type arguments
+
+error[E0220]: associated type `Output` not found for `Three<(), [type error], [type error]>`
+  --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters-3.rs:5:17
+   |
+LL | fn foo(_: &Three())
+   |                 ^^ associated type `Output` not found
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0107, E0220.
+For more information about an error, try `rustc --explain E0107`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters.rs b/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters.rs
new file mode 100644
index 0000000..2e87d91
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters.rs
@@ -0,0 +1,10 @@
+#![feature(unboxed_closures)]
+
+trait Zero { fn dummy(&self); }
+
+fn foo(_: Zero())
+    //~^ ERROR wrong number of type arguments
+    //~| ERROR associated type `Output` not found for `Zero`
+{}
+
+fn main() { }
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters.stderr
new file mode 100644
index 0000000..3f80197
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters.stderr
@@ -0,0 +1,16 @@
+error[E0107]: wrong number of type arguments: expected 0, found 1
+  --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:5:15
+   |
+LL | fn foo(_: Zero())
+   |               ^^ unexpected type argument
+
+error[E0220]: associated type `Output` not found for `Zero`
+  --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:5:15
+   |
+LL | fn foo(_: Zero())
+   |               ^^ associated type `Output` not found
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0107, E0220.
+For more information about an error, try `rustc --explain E0107`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-trait.rs b/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-trait.rs
new file mode 100644
index 0000000..3e5342c
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-trait.rs
@@ -0,0 +1,9 @@
+#![feature(unboxed_closures)]
+
+trait Trait {}
+
+fn f<F:Trait(isize) -> isize>(x: F) {}
+//~^ ERROR wrong number of type arguments: expected 0, found 1 [E0107]
+//~| ERROR E0220
+
+fn main() {}
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-trait.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-trait.stderr
new file mode 100644
index 0000000..a04062e
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-trait.stderr
@@ -0,0 +1,16 @@
+error[E0107]: wrong number of type arguments: expected 0, found 1
+  --> $DIR/unboxed-closure-sugar-wrong-trait.rs:5:13
+   |
+LL | fn f<F:Trait(isize) -> isize>(x: F) {}
+   |             ^^^^^^^ unexpected type argument
+
+error[E0220]: associated type `Output` not found for `Trait`
+  --> $DIR/unboxed-closure-sugar-wrong-trait.rs:5:24
+   |
+LL | fn f<F:Trait(isize) -> isize>(x: F) {}
+   |                        ^^^^^ associated type `Output` not found
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0107, E0220.
+For more information about an error, try `rustc --explain E0107`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-borrow-conflict.nll.stderr b/src/test/ui/unboxed-closures/unboxed-closures-borrow-conflict.nll.stderr
new file mode 100644
index 0000000..21d6b4f
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closures-borrow-conflict.nll.stderr
@@ -0,0 +1,15 @@
+error[E0503]: cannot use `x` because it was mutably borrowed
+  --> $DIR/unboxed-closures-borrow-conflict.rs:9:14
+   |
+LL |     let f = || x += 1;
+   |             -- - borrow occurs due to use of `x` in closure
+   |             |
+   |             borrow of `x` occurs here
+LL |     let _y = x;
+   |              ^ use of borrowed `x`
+LL |     f;
+   |     - borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0503`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-borrow-conflict.rs b/src/test/ui/unboxed-closures/unboxed-closures-borrow-conflict.rs
new file mode 100644
index 0000000..835a1f5
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closures-borrow-conflict.rs
@@ -0,0 +1,11 @@
+// Test that an unboxed closure that mutates a free variable will
+// cause borrow conflicts.
+
+
+
+fn main() {
+    let mut x = 0;
+    let f = || x += 1;
+    let _y = x; //~ ERROR cannot use `x` because it was mutably borrowed
+    f;
+}
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-borrow-conflict.stderr b/src/test/ui/unboxed-closures/unboxed-closures-borrow-conflict.stderr
new file mode 100644
index 0000000..ac0e4ff
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closures-borrow-conflict.stderr
@@ -0,0 +1,11 @@
+error[E0503]: cannot use `x` because it was mutably borrowed
+  --> $DIR/unboxed-closures-borrow-conflict.rs:9:9
+   |
+LL |     let f = || x += 1;
+   |             -- borrow of `x` occurs here
+LL |     let _y = x;
+   |         ^^ use of borrowed `x`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0503`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-1.nll.stderr b/src/test/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-1.nll.stderr
new file mode 100644
index 0000000..19cb2cb
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-1.nll.stderr
@@ -0,0 +1,62 @@
+error[E0597]: `factorial` does not live long enough
+  --> $DIR/unboxed-closures-failed-recursive-fn-1.rs:15:17
+   |
+LL |     let f = |x: u32| -> u32 {
+   |             --------------- value captured here
+LL |         let g = factorial.as_ref().unwrap();
+   |                 ^^^^^^^^^ borrowed value does not live long enough
+...
+LL | }
+   | -
+   | |
+   | `factorial` dropped here while still borrowed
+   | borrow might be used here, when `factorial` is dropped and runs the destructor for type `std::option::Option<std::boxed::Box<dyn std::ops::Fn(u32) -> u32>>`
+
+error[E0506]: cannot assign to `factorial` because it is borrowed
+  --> $DIR/unboxed-closures-failed-recursive-fn-1.rs:20:5
+   |
+LL |     let f = |x: u32| -> u32 {
+   |             --------------- borrow of `factorial` occurs here
+LL |         let g = factorial.as_ref().unwrap();
+   |                 --------- borrow occurs due to use in closure
+...
+LL |     factorial = Some(Box::new(f));
+   |     ^^^^^^^^^
+   |     |
+   |     assignment to borrowed `factorial` occurs here
+   |     borrow later used here
+
+error[E0597]: `factorial` does not live long enough
+  --> $DIR/unboxed-closures-failed-recursive-fn-1.rs:28:17
+   |
+LL |     let mut factorial: Option<Box<Fn(u32) -> u32 + 'static>> = None;
+   |                        ------------------------------------- type annotation requires that `factorial` is borrowed for `'static`
+LL | 
+LL |     let f = |x: u32| -> u32 {
+   |             --------------- value captured here
+LL |
+LL |         let g = factorial.as_ref().unwrap();
+   |                 ^^^^^^^^^ borrowed value does not live long enough
+...
+LL | }
+   | - `factorial` dropped here while still borrowed
+
+error[E0506]: cannot assign to `factorial` because it is borrowed
+  --> $DIR/unboxed-closures-failed-recursive-fn-1.rs:32:5
+   |
+LL |     let mut factorial: Option<Box<Fn(u32) -> u32 + 'static>> = None;
+   |                        ------------------------------------- type annotation requires that `factorial` is borrowed for `'static`
+LL | 
+LL |     let f = |x: u32| -> u32 {
+   |             --------------- borrow of `factorial` occurs here
+LL |
+LL |         let g = factorial.as_ref().unwrap();
+   |                 --------- borrow occurs due to use in closure
+...
+LL |     factorial = Some(Box::new(f));
+   |     ^^^^^^^^^ assignment to borrowed `factorial` occurs here
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0506, E0597.
+For more information about an error, try `rustc --explain E0506`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-1.rs b/src/test/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-1.rs
new file mode 100644
index 0000000..b72482a
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-1.rs
@@ -0,0 +1,35 @@
+// Various unsuccessful attempts to put the unboxed closure kind
+// inference into an awkward position that might require fixed point
+// iteration (basically where inferring the kind of a closure `c`
+// would require knowing the kind of `c`). I currently believe this is
+// impossible.
+
+fn a() {
+    // This case of recursion wouldn't even require fixed-point
+    // iteration, but it still doesn't work. The weird structure with
+    // the `Option` is to avoid giving any useful hints about the `Fn`
+    // kind via the expected type.
+    let mut factorial: Option<Box<Fn(u32) -> u32>> = None;
+
+    let f = |x: u32| -> u32 {
+        let g = factorial.as_ref().unwrap();
+        //~^ ERROR `factorial` does not live long enough
+        if x == 0 {1} else {x * g(x-1)}
+    };
+
+    factorial = Some(Box::new(f));
+}
+
+fn b() {
+    let mut factorial: Option<Box<Fn(u32) -> u32 + 'static>> = None;
+
+    let f = |x: u32| -> u32 {
+        //~^ ERROR closure may outlive the current function, but it borrows `factorial`
+        let g = factorial.as_ref().unwrap();
+        if x == 0 {1} else {x * g(x-1)}
+    };
+
+    factorial = Some(Box::new(f));
+}
+
+fn main() { }
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-1.stderr b/src/test/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-1.stderr
new file mode 100644
index 0000000..47fe0ee
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-1.stderr
@@ -0,0 +1,30 @@
+error[E0597]: `factorial` does not live long enough
+  --> $DIR/unboxed-closures-failed-recursive-fn-1.rs:15:17
+   |
+LL |     let f = |x: u32| -> u32 {
+   |             --------------- capture occurs here
+LL |         let g = factorial.as_ref().unwrap();
+   |                 ^^^^^^^^^ borrowed value does not live long enough
+...
+LL | }
+   | - borrowed value dropped before borrower
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error[E0373]: closure may outlive the current function, but it borrows `factorial`, which is owned by the current function
+  --> $DIR/unboxed-closures-failed-recursive-fn-1.rs:26:13
+   |
+LL |     let f = |x: u32| -> u32 {
+   |             ^^^^^^^^^^^^^^^ may outlive borrowed value `factorial`
+LL |
+LL |         let g = factorial.as_ref().unwrap();
+   |                 --------- `factorial` is borrowed here
+help: to force the closure to take ownership of `factorial` (and any other referenced variables), use the `move` keyword
+   |
+LL |     let f = move |x: u32| -> u32 {
+   |             ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0373, E0597.
+For more information about an error, try `rustc --explain E0373`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-2.rs b/src/test/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-2.rs
new file mode 100644
index 0000000..d03001f
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-2.rs
@@ -0,0 +1,29 @@
+// Various unsuccessful attempts to put the unboxed closure kind
+// inference into an awkward position that might require fixed point
+// iteration (basically where inferring the kind of a closure `c`
+// would require knowing the kind of `c`). I currently believe this is
+// impossible.
+
+fn a() {
+    let mut closure0 = None;
+    let vec = vec![1, 2, 3];
+
+    loop {
+        {
+            let closure1 = || {
+                match closure0.take() {
+                    Some(c) => {
+                        return c();
+                        //~^ ERROR type annotations needed
+                    }
+                    None => { }
+                }
+            };
+            closure1();
+        }
+
+        closure0 = || vec;
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-2.stderr b/src/test/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-2.stderr
new file mode 100644
index 0000000..bd58e24
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-2.stderr
@@ -0,0 +1,14 @@
+error[E0282]: type annotations needed
+  --> $DIR/unboxed-closures-failed-recursive-fn-2.rs:16:32
+   |
+LL |     let mut closure0 = None;
+   |         ------------ consider giving `closure0` a type
+...
+LL |                         return c();
+   |                                ^^^ cannot infer type
+   |
+   = note: type must be known at this point
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.rs b/src/test/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.rs
new file mode 100644
index 0000000..9f1c4c1
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.rs
@@ -0,0 +1,30 @@
+// Checks that the Fn trait hierarchy rules do not permit
+// Fn to be used where FnMut is implemented.
+
+#![feature(fn_traits, unboxed_closures)]
+#![feature(overloaded_calls)]
+
+use std::ops::{Fn,FnMut,FnOnce};
+
+struct S;
+
+impl FnMut<(isize,)> for S {
+    extern "rust-call" fn call_mut(&mut self, (x,): (isize,)) -> isize {
+        x * x
+    }
+}
+
+impl FnOnce<(isize,)> for S {
+    type Output = isize;
+
+    extern "rust-call" fn call_once(mut self, args: (isize,)) -> isize { self.call_mut(args) }
+}
+
+fn call_it<F:Fn(isize)->isize>(f: &F, x: isize) -> isize {
+    f.call((x,))
+}
+
+fn main() {
+    let x = call_it(&S, 22);
+    //~^ ERROR E0277
+}
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.stderr b/src/test/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.stderr
new file mode 100644
index 0000000..fcf11290
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.stderr
@@ -0,0 +1,16 @@
+error[E0277]: expected a `std::ops::Fn<(isize,)>` closure, found `S`
+  --> $DIR/unboxed-closures-fnmut-as-fn.rs:28:13
+   |
+LL |     let x = call_it(&S, 22);
+   |             ^^^^^^^ expected an `Fn<(isize,)>` closure, found `S`
+   |
+   = help: the trait `std::ops::Fn<(isize,)>` is not implemented for `S`
+note: required by `call_it`
+  --> $DIR/unboxed-closures-fnmut-as-fn.rs:23:1
+   |
+LL | fn call_it<F:Fn(isize)->isize>(f: &F, x: isize) -> isize {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.rs b/src/test/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.rs
new file mode 100644
index 0000000..a1364b9
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.rs
@@ -0,0 +1,19 @@
+#![feature(fn_traits)]
+
+// That a closure whose expected argument types include two distinct
+// bound regions.
+
+use std::cell::Cell;
+
+fn doit<T,F>(val: T, f: &F)
+    where F : Fn(&Cell<&T>, &T)
+{
+    let x = Cell::new(&val);
+    f.call((&x,&val))
+}
+
+pub fn main() {
+    doit(0, &|x, y| {
+        x.set(y); //~ ERROR E0312
+    });
+}
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.stderr b/src/test/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.stderr
new file mode 100644
index 0000000..526055b
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.stderr
@@ -0,0 +1,26 @@
+error[E0312]: lifetime of reference outlives lifetime of borrowed content...
+  --> $DIR/unboxed-closures-infer-argument-types-two-region-pointers.rs:17:15
+   |
+LL |         x.set(y);
+   |               ^
+   |
+note: ...the reference is valid for the anonymous lifetime #3 defined on the body at 16:14...
+  --> $DIR/unboxed-closures-infer-argument-types-two-region-pointers.rs:16:14
+   |
+LL |       doit(0, &|x, y| {
+   |  ______________^
+LL | |         x.set(y);
+LL | |     });
+   | |_____^
+note: ...but the borrowed content is only valid for the anonymous lifetime #4 defined on the body at 16:14
+  --> $DIR/unboxed-closures-infer-argument-types-two-region-pointers.rs:16:14
+   |
+LL |       doit(0, &|x, y| {
+   |  ______________^
+LL | |         x.set(y);
+LL | |     });
+   | |_____^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0312`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-infer-fn-once-move-from-projection.rs b/src/test/ui/unboxed-closures/unboxed-closures-infer-fn-once-move-from-projection.rs
new file mode 100644
index 0000000..6e404c6
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closures-infer-fn-once-move-from-projection.rs
@@ -0,0 +1,16 @@
+#![allow(unused)]
+
+fn foo<F>(f: F)
+    where F: Fn()
+{
+}
+
+fn main() {
+    // Test that this closure is inferred to `FnOnce` because it moves
+    // from `y.0`. This affects the error output (the error is that
+    // the closure implements `FnOnce`, not that it moves from inside
+    // a `Fn` closure.)
+    let y = (vec![1, 2, 3], 0);
+    let c = || drop(y.0); //~ ERROR expected a closure that implements the `Fn` trait
+    foo(c);
+}
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-infer-fn-once-move-from-projection.stderr b/src/test/ui/unboxed-closures/unboxed-closures-infer-fn-once-move-from-projection.stderr
new file mode 100644
index 0000000..9287353
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closures-infer-fn-once-move-from-projection.stderr
@@ -0,0 +1,14 @@
+error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce`
+  --> $DIR/unboxed-closures-infer-fn-once-move-from-projection.rs:14:13
+   |
+LL |     let c = || drop(y.0);
+   |             ^^^^^^^^-^^^
+   |             |       |
+   |             |       closure is `FnOnce` because it moves the variable `y` out of its environment
+   |             this closure implements `FnOnce`, not `Fn`
+LL |     foo(c);
+   |     --- the requirement to implement `Fn` derives from here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0525`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.nll.stderr b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.nll.stderr
new file mode 100644
index 0000000..1e1172c
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.nll.stderr
@@ -0,0 +1,21 @@
+error[E0596]: cannot borrow `tick1` as mutable, as it is not declared as mutable
+  --> $DIR/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.rs:17:9
+   |
+LL |     let tick1 = || {
+   |         ----- help: consider changing this to be mutable: `mut tick1`
+...
+LL |         tick1();
+   |         ^^^^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow `tick2` as mutable, as it is not declared as mutable
+  --> $DIR/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.rs:20:5
+   |
+LL |     let tick2 = || {
+   |         ----- help: consider changing this to be mutable: `mut tick2`
+...
+LL |     tick2();
+   |     ^^^^^ cannot borrow as mutable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.rs b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.rs
new file mode 100644
index 0000000..aaa692c
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.rs
@@ -0,0 +1,21 @@
+// Test that we are able to infer a suitable kind for this closure
+// that is just called (`FnMut`).
+
+fn main() {
+    let mut counter = 0;
+
+    // Here this must be inferred to FnMut so that it can mutate counter,
+    // but we forgot the mut.
+    let tick1 = || {
+        counter += 1;
+    };
+
+    // In turn, tick2 must be inferred to FnMut so that it can call
+    // tick1, but we forgot the mut. The error message we currently
+    // get seems... suboptimal.
+    let tick2 = || { //~ ERROR closure cannot assign to immutable local variable `tick1`
+        tick1();
+    };
+
+    tick2(); //~ ERROR cannot borrow
+}
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.stderr b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.stderr
new file mode 100644
index 0000000..c90c150
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.stderr
@@ -0,0 +1,22 @@
+error[E0595]: closure cannot assign to immutable local variable `tick1`
+  --> $DIR/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.rs:16:17
+   |
+LL |     let tick1 = || {
+   |         ----- help: make this binding mutable: `mut tick1`
+...
+LL |     let tick2 = || {
+   |                 ^^ cannot borrow mutably
+
+error[E0596]: cannot borrow immutable local variable `tick2` as mutable
+  --> $DIR/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.rs:20:5
+   |
+LL |     let tick2 = || {
+   |         ----- help: make this binding mutable: `mut tick2`
+...
+LL |     tick2();
+   |     ^^^^^ cannot borrow mutably
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0595, E0596.
+For more information about an error, try `rustc --explain E0595`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-missing-mut.nll.stderr b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-missing-mut.nll.stderr
new file mode 100644
index 0000000..eb39862
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-missing-mut.nll.stderr
@@ -0,0 +1,11 @@
+error[E0596]: cannot borrow `tick` as mutable, as it is not declared as mutable
+  --> $DIR/unboxed-closures-infer-fnmut-missing-mut.rs:7:5
+   |
+LL |     let tick = || counter += 1;
+   |         ---- help: consider changing this to be mutable: `mut tick`
+LL |     tick();
+   |     ^^^^ cannot borrow as mutable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-missing-mut.rs b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-missing-mut.rs
new file mode 100644
index 0000000..de3f9839
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-missing-mut.rs
@@ -0,0 +1,8 @@
+// Test that we are able to infer a suitable kind for this closure
+// that is just called (`FnMut`).
+
+fn main() {
+    let mut counter = 0;
+    let tick = || counter += 1;
+    tick(); //~ ERROR cannot borrow immutable local variable `tick` as mutable
+}
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-missing-mut.stderr b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-missing-mut.stderr
new file mode 100644
index 0000000..33e2154
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-missing-mut.stderr
@@ -0,0 +1,11 @@
+error[E0596]: cannot borrow immutable local variable `tick` as mutable
+  --> $DIR/unboxed-closures-infer-fnmut-missing-mut.rs:7:5
+   |
+LL |     let tick = || counter += 1;
+   |         ---- help: make this binding mutable: `mut tick`
+LL |     tick();
+   |     ^^^^ cannot borrow mutably
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-move-missing-mut.nll.stderr b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-move-missing-mut.nll.stderr
new file mode 100644
index 0000000..b9d76d9
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-move-missing-mut.nll.stderr
@@ -0,0 +1,11 @@
+error[E0596]: cannot borrow `tick` as mutable, as it is not declared as mutable
+  --> $DIR/unboxed-closures-infer-fnmut-move-missing-mut.rs:7:5
+   |
+LL |     let tick = move || counter += 1;
+   |         ---- help: consider changing this to be mutable: `mut tick`
+LL |     tick();
+   |     ^^^^ cannot borrow as mutable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-move-missing-mut.rs b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-move-missing-mut.rs
new file mode 100644
index 0000000..b011c5a
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-move-missing-mut.rs
@@ -0,0 +1,8 @@
+// Test that we are able to infer a suitable kind for this closure
+// that is just called (`FnMut`).
+
+fn main() {
+    let mut counter = 0;
+    let tick = move || counter += 1;
+    tick(); //~ ERROR cannot borrow immutable local variable `tick` as mutable
+}
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-move-missing-mut.stderr b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-move-missing-mut.stderr
new file mode 100644
index 0000000..585577a
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-move-missing-mut.stderr
@@ -0,0 +1,11 @@
+error[E0596]: cannot borrow immutable local variable `tick` as mutable
+  --> $DIR/unboxed-closures-infer-fnmut-move-missing-mut.rs:7:5
+   |
+LL |     let tick = move || counter += 1;
+   |         ---- help: make this binding mutable: `mut tick`
+LL |     tick();
+   |     ^^^^ cannot borrow mutably
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnonce-call-twice.rs b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnonce-call-twice.rs
new file mode 100644
index 0000000..a98a01c
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnonce-call-twice.rs
@@ -0,0 +1,11 @@
+// Test that we are able to infer a suitable kind for this closure
+// that is just called (`FnMut`).
+
+use std::mem;
+
+fn main() {
+    let mut counter: Vec<i32> = Vec::new();
+    let tick = || mem::drop(counter);
+    tick();
+    tick(); //~ ERROR use of moved value: `tick`
+}
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnonce-call-twice.stderr b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnonce-call-twice.stderr
new file mode 100644
index 0000000..0b9aa61
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnonce-call-twice.stderr
@@ -0,0 +1,17 @@
+error[E0382]: use of moved value: `tick`
+  --> $DIR/unboxed-closures-infer-fnonce-call-twice.rs:10:5
+   |
+LL |     tick();
+   |     ---- value moved here
+LL |     tick();
+   |     ^^^^ value used here after move
+   |
+note: closure cannot be invoked more than once because it moves the variable `counter` out of its environment
+  --> $DIR/unboxed-closures-infer-fnonce-call-twice.rs:8:29
+   |
+LL |     let tick = || mem::drop(counter);
+   |                             ^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnonce-move-call-twice.rs b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnonce-move-call-twice.rs
new file mode 100644
index 0000000..f87be4a
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnonce-move-call-twice.rs
@@ -0,0 +1,11 @@
+// Test that we are able to infer a suitable kind for this closure
+// that is just called (`FnMut`).
+
+use std::mem;
+
+fn main() {
+    let mut counter: Vec<i32> = Vec::new();
+    let tick = move || mem::drop(counter);
+    tick();
+    tick(); //~ ERROR use of moved value: `tick`
+}
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnonce-move-call-twice.stderr b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnonce-move-call-twice.stderr
new file mode 100644
index 0000000..20773d5
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnonce-move-call-twice.stderr
@@ -0,0 +1,17 @@
+error[E0382]: use of moved value: `tick`
+  --> $DIR/unboxed-closures-infer-fnonce-move-call-twice.rs:10:5
+   |
+LL |     tick();
+   |     ---- value moved here
+LL |     tick();
+   |     ^^^^ value used here after move
+   |
+note: closure cannot be invoked more than once because it moves the variable `counter` out of its environment
+  --> $DIR/unboxed-closures-infer-fnonce-move-call-twice.rs:8:34
+   |
+LL |     let tick = move || mem::drop(counter);
+   |                                  ^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-mutate-upvar.nll.stderr b/src/test/ui/unboxed-closures/unboxed-closures-mutate-upvar.nll.stderr
new file mode 100644
index 0000000..6bba385
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closures-mutate-upvar.nll.stderr
@@ -0,0 +1,45 @@
+error[E0594]: cannot assign to `n`, as it is not declared as mutable
+  --> $DIR/unboxed-closures-mutate-upvar.rs:15:9
+   |
+LL |     let n = 0;
+   |         - help: consider changing this to be mutable: `mut n`
+LL |     let mut f = to_fn_mut(|| {
+LL |         n += 1;
+   |         ^^^^^^ cannot assign
+
+error[E0594]: cannot assign to `n`, as it is not declared as mutable
+  --> $DIR/unboxed-closures-mutate-upvar.rs:32:9
+   |
+LL |     let n = 0;
+   |         - help: consider changing this to be mutable: `mut n`
+...
+LL |         n += 1;
+   |         ^^^^^^ cannot assign
+
+error[E0594]: cannot assign to `n`, as it is not declared as mutable
+  --> $DIR/unboxed-closures-mutate-upvar.rs:46:9
+   |
+LL |     let n = 0;
+   |         - help: consider changing this to be mutable: `mut n`
+LL |     let mut f = to_fn(move || {
+LL |         n += 1;
+   |         ^^^^^^ cannot assign
+
+error[E0594]: cannot assign to `n`, as it is a captured variable in a `Fn` closure
+  --> $DIR/unboxed-closures-mutate-upvar.rs:53:9
+   |
+LL |         n += 1;
+   |         ^^^^^^ cannot assign
+   |
+help: consider changing this to accept closures that implement `FnMut`
+  --> $DIR/unboxed-closures-mutate-upvar.rs:52:23
+   |
+LL |       let mut f = to_fn(move || {
+   |  _______________________^
+LL | |         n += 1;
+LL | |     });
+   | |_____^
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-mutate-upvar.rs b/src/test/ui/unboxed-closures/unboxed-closures-mutate-upvar.rs
new file mode 100644
index 0000000..3bea922
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closures-mutate-upvar.rs
@@ -0,0 +1,57 @@
+// Test that we cannot mutate an outer variable that is not declared
+// as `mut` through a closure. Also test that we CAN mutate a moved copy,
+// unless this is a `Fn` closure. Issue #16749.
+
+#![feature(unboxed_closures)]
+
+use std::mem;
+
+fn to_fn<A,F:Fn<A>>(f: F) -> F { f }
+fn to_fn_mut<A,F:FnMut<A>>(f: F) -> F { f }
+
+fn a() {
+    let n = 0;
+    let mut f = to_fn_mut(|| { //~ ERROR closure cannot assign
+        n += 1;
+    });
+}
+
+fn b() {
+    let mut n = 0;
+    let mut f = to_fn_mut(|| {
+        n += 1; // OK
+    });
+}
+
+fn c() {
+    let n = 0;
+    let mut f = to_fn_mut(move || {
+        // If we just did a straight-forward desugaring, this would
+        // compile, but we do something a bit more subtle, and hence
+        // we get an error.
+        n += 1; //~ ERROR cannot assign
+    });
+}
+
+fn d() {
+    let mut n = 0;
+    let mut f = to_fn_mut(move || {
+        n += 1; // OK
+    });
+}
+
+fn e() {
+    let n = 0;
+    let mut f = to_fn(move || {
+        n += 1; //~ ERROR cannot assign
+    });
+}
+
+fn f() {
+    let mut n = 0;
+    let mut f = to_fn(move || {
+        n += 1; //~ ERROR cannot assign
+    });
+}
+
+fn main() { }
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-mutate-upvar.stderr b/src/test/ui/unboxed-closures/unboxed-closures-mutate-upvar.stderr
new file mode 100644
index 0000000..055a174
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closures-mutate-upvar.stderr
@@ -0,0 +1,53 @@
+error[E0595]: closure cannot assign to immutable local variable `n`
+  --> $DIR/unboxed-closures-mutate-upvar.rs:14:27
+   |
+LL |     let n = 0;
+   |         - help: make this binding mutable: `mut n`
+LL |     let mut f = to_fn_mut(|| {
+   |                           ^^ cannot borrow mutably
+
+error[E0594]: cannot assign to captured outer variable in an `FnMut` closure
+  --> $DIR/unboxed-closures-mutate-upvar.rs:32:9
+   |
+LL |     let n = 0;
+   |         - help: consider making `n` mutable: `mut n`
+...
+LL |         n += 1;
+   |         ^^^^^^
+
+error[E0594]: cannot assign to captured outer variable in an `Fn` closure
+  --> $DIR/unboxed-closures-mutate-upvar.rs:46:9
+   |
+LL |         n += 1;
+   |         ^^^^^^
+   |
+   = note: `Fn` closures cannot capture their enclosing environment for modifications
+help: consider changing this closure to take self by mutable reference
+  --> $DIR/unboxed-closures-mutate-upvar.rs:45:23
+   |
+LL |       let mut f = to_fn(move || {
+   |  _______________________^
+LL | |         n += 1;
+LL | |     });
+   | |_____^
+
+error[E0594]: cannot assign to captured outer variable in an `Fn` closure
+  --> $DIR/unboxed-closures-mutate-upvar.rs:53:9
+   |
+LL |         n += 1;
+   |         ^^^^^^
+   |
+   = note: `Fn` closures cannot capture their enclosing environment for modifications
+help: consider changing this closure to take self by mutable reference
+  --> $DIR/unboxed-closures-mutate-upvar.rs:52:23
+   |
+LL |       let mut f = to_fn(move || {
+   |  _______________________^
+LL | |         n += 1;
+LL | |     });
+   | |_____^
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0594, E0595.
+For more information about an error, try `rustc --explain E0594`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-mutated-upvar-from-fn-closure.ast.nll.stderr b/src/test/ui/unboxed-closures/unboxed-closures-mutated-upvar-from-fn-closure.ast.nll.stderr
new file mode 100644
index 0000000..3440ede
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closures-mutated-upvar-from-fn-closure.ast.nll.stderr
@@ -0,0 +1,20 @@
+error[E0594]: cannot assign to `counter`, as it is a captured variable in a `Fn` closure
+  --> $DIR/unboxed-closures-mutated-upvar-from-fn-closure.rs:14:9
+   |
+LL |         counter += 1;
+   |         ^^^^^^^^^^^^ cannot assign
+   |
+help: consider changing this to accept closures that implement `FnMut`
+  --> $DIR/unboxed-closures-mutated-upvar-from-fn-closure.rs:13:10
+   |
+LL |       call(|| {
+   |  __________^
+LL | |         counter += 1;
+LL | |
+LL | |
+LL | |     });
+   | |_____^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-mutated-upvar-from-fn-closure.ast.stderr b/src/test/ui/unboxed-closures/unboxed-closures-mutated-upvar-from-fn-closure.ast.stderr
new file mode 100644
index 0000000..0788350
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closures-mutated-upvar-from-fn-closure.ast.stderr
@@ -0,0 +1,20 @@
+error[E0387]: cannot assign to data in a captured outer variable in an `Fn` closure
+  --> $DIR/unboxed-closures-mutated-upvar-from-fn-closure.rs:14:9
+   |
+LL |         counter += 1;
+   |         ^^^^^^^^^^^^
+   |
+help: consider changing this closure to take self by mutable reference
+  --> $DIR/unboxed-closures-mutated-upvar-from-fn-closure.rs:13:10
+   |
+LL |       call(|| {
+   |  __________^
+LL | |         counter += 1;
+LL | |
+LL | |
+LL | |     });
+   | |_____^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0387`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-mutated-upvar-from-fn-closure.mir.stderr b/src/test/ui/unboxed-closures/unboxed-closures-mutated-upvar-from-fn-closure.mir.stderr
new file mode 100644
index 0000000..3440ede
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closures-mutated-upvar-from-fn-closure.mir.stderr
@@ -0,0 +1,20 @@
+error[E0594]: cannot assign to `counter`, as it is a captured variable in a `Fn` closure
+  --> $DIR/unboxed-closures-mutated-upvar-from-fn-closure.rs:14:9
+   |
+LL |         counter += 1;
+   |         ^^^^^^^^^^^^ cannot assign
+   |
+help: consider changing this to accept closures that implement `FnMut`
+  --> $DIR/unboxed-closures-mutated-upvar-from-fn-closure.rs:13:10
+   |
+LL |       call(|| {
+   |  __________^
+LL | |         counter += 1;
+LL | |
+LL | |
+LL | |     });
+   | |_____^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-mutated-upvar-from-fn-closure.rs b/src/test/ui/unboxed-closures/unboxed-closures-mutated-upvar-from-fn-closure.rs
new file mode 100644
index 0000000..a5dcb57
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closures-mutated-upvar-from-fn-closure.rs
@@ -0,0 +1,18 @@
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+// Test that a by-ref `FnMut` closure gets an error when it tries to
+// mutate a value.
+
+fn call<F>(f: F) where F : Fn() {
+    f();
+}
+
+fn main() {
+    let mut counter = 0;
+    call(|| {
+        counter += 1;
+        //[ast]~^ ERROR cannot assign to data in a captured outer variable in an `Fn` closure
+        //[mir]~^^ ERROR cannot assign to `counter`
+    });
+}
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-recursive-fn-using-fn-mut.nll.stderr b/src/test/ui/unboxed-closures/unboxed-closures-recursive-fn-using-fn-mut.nll.stderr
new file mode 100644
index 0000000..830f6bc
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closures-recursive-fn-using-fn-mut.nll.stderr
@@ -0,0 +1,12 @@
+error[E0499]: cannot borrow `*self` as mutable more than once at a time
+  --> $DIR/unboxed-closures-recursive-fn-using-fn-mut.rs:22:21
+   |
+LL |         (self.func)(self, arg)
+   |         ----------- ^^^^ second mutable borrow occurs here
+   |         |
+   |         first mutable borrow occurs here
+   |         first borrow later used by call
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-recursive-fn-using-fn-mut.rs b/src/test/ui/unboxed-closures/unboxed-closures-recursive-fn-using-fn-mut.rs
new file mode 100644
index 0000000..0beead1
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closures-recursive-fn-using-fn-mut.rs
@@ -0,0 +1,43 @@
+#![feature(core, fn_traits, unboxed_closures)]
+
+use std::marker::PhantomData;
+
+// An erroneous variant of `run-pass/unboxed_closures-infer-recursive-fn.rs`
+// where we attempt to perform mutation in the recursive function. This fails to compile
+// because it winds up requiring `FnMut` which enforces linearity.
+
+struct YCombinator<F,A,R> {
+    func: F,
+    marker: PhantomData<(A,R)>,
+}
+
+impl<F,A,R> YCombinator<F,A,R> {
+    fn new(f: F) -> YCombinator<F,A,R> {
+        YCombinator { func: f, marker: PhantomData }
+    }
+}
+
+impl<A,R,F : FnMut(&mut FnMut(A) -> R, A) -> R> FnMut<(A,)> for YCombinator<F,A,R> {
+    extern "rust-call" fn call_mut(&mut self, (arg,): (A,)) -> R {
+        (self.func)(self, arg)
+            //~^ ERROR cannot borrow `*self` as mutable more than once at a time
+    }
+}
+
+impl<A,R,F : FnMut(&mut FnMut(A) -> R, A) -> R> FnOnce<(A,)> for YCombinator<F,A,R> {
+    type Output = R;
+    extern "rust-call" fn call_once(mut self, args: (A,)) -> R {
+        self.call_mut(args)
+    }
+}
+
+fn main() {
+    let mut counter = 0;
+    let factorial = |recur: &mut FnMut(u32) -> u32, arg: u32| -> u32 {
+        counter += 1;
+        if arg == 0 {1} else {arg * recur(arg-1)}
+    };
+    let mut factorial: YCombinator<_,u32,u32> = YCombinator::new(factorial);
+    let mut r = factorial(10);
+    assert_eq!(3628800, r);
+}
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-recursive-fn-using-fn-mut.stderr b/src/test/ui/unboxed-closures/unboxed-closures-recursive-fn-using-fn-mut.stderr
new file mode 100644
index 0000000..f881d19
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closures-recursive-fn-using-fn-mut.stderr
@@ -0,0 +1,12 @@
+error[E0499]: cannot borrow `*self` as mutable more than once at a time
+  --> $DIR/unboxed-closures-recursive-fn-using-fn-mut.rs:22:21
+   |
+LL |         (self.func)(self, arg)
+   |         ----------- ^^^^     - first borrow ends here
+   |         |           |
+   |         |           second mutable borrow occurs here
+   |         first mutable borrow occurs here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.rs b/src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.rs
new file mode 100644
index 0000000..0e727b1
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.rs
@@ -0,0 +1,8 @@
+#![feature(unboxed_closures)]
+
+fn to_fn_mut<A,F:FnMut<A>>(f: F) -> F { f }
+
+fn main() {
+    let mut_ = to_fn_mut(|x| x);
+    mut_.call((0, )); //~ ERROR no method named `call` found
+}
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr b/src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr
new file mode 100644
index 0000000..2e18458
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr
@@ -0,0 +1,11 @@
+error[E0599]: no method named `call` found for type `[closure@$DIR/unboxed-closures-static-call-wrong-trait.rs:6:26: 6:31]` in the current scope
+  --> $DIR/unboxed-closures-static-call-wrong-trait.rs:7:10
+   |
+LL |     mut_.call((0, ));
+   |          ^^^^
+   |
+   = note: mut_ is a function, perhaps you wish to call it
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-type-mismatch.rs b/src/test/ui/unboxed-closures/unboxed-closures-type-mismatch.rs
new file mode 100644
index 0000000..9f76849
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closures-type-mismatch.rs
@@ -0,0 +1,7 @@
+use std::ops::FnMut;
+
+pub fn main() {
+    let mut f = |x: isize, y: isize| -> isize { x + y };
+    let z = f(1_usize, 2);    //~ ERROR mismatched types
+    println!("{}", z);
+}
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-type-mismatch.stderr b/src/test/ui/unboxed-closures/unboxed-closures-type-mismatch.stderr
new file mode 100644
index 0000000..df31a8d
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closures-type-mismatch.stderr
@@ -0,0 +1,9 @@
+error[E0308]: mismatched types
+  --> $DIR/unboxed-closures-type-mismatch.rs:5:15
+   |
+LL |     let z = f(1_usize, 2);
+   |               ^^^^^^^ expected isize, found usize
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.rs b/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.rs
new file mode 100644
index 0000000..a6e2661
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.rs
@@ -0,0 +1,28 @@
+// Tests that unsafe extern fn pointers do not implement any Fn traits.
+
+use std::ops::{Fn,FnMut,FnOnce};
+
+unsafe fn square(x: &isize) -> isize { (*x) * (*x) }
+
+fn call_it<F:Fn(&isize)->isize>(_: &F, _: isize) -> isize { 0 }
+fn call_it_mut<F:FnMut(&isize)->isize>(_: &mut F, _: isize) -> isize { 0 }
+fn call_it_once<F:FnOnce(&isize)->isize>(_: F, _: isize) -> isize { 0 }
+
+fn a() {
+    let x = call_it(&square, 22);
+    //~^ ERROR E0277
+    //~| ERROR expected
+}
+
+fn b() {
+    let y = call_it_mut(&mut square, 22);
+    //~^ ERROR E0277
+    //~| ERROR expected
+}
+
+fn c() {
+    let z = call_it_once(square, 22);
+    //~^ ERROR E0277
+}
+
+fn main() { }
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr b/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr
new file mode 100644
index 0000000..ca02982
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr
@@ -0,0 +1,68 @@
+error[E0277]: expected a `std::ops::Fn<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}`
+  --> $DIR/unboxed-closures-unsafe-extern-fn.rs:12:13
+   |
+LL |     let x = call_it(&square, 22);
+   |             ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}`
+   |
+   = help: the trait `for<'r> std::ops::Fn<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}`
+note: required by `call_it`
+  --> $DIR/unboxed-closures-unsafe-extern-fn.rs:7:1
+   |
+LL | fn call_it<F:Fn(&isize)->isize>(_: &F, _: isize) -> isize { 0 }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}`
+  --> $DIR/unboxed-closures-unsafe-extern-fn.rs:12:13
+   |
+LL |     let x = call_it(&square, 22);
+   |             ^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}`
+   |
+   = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}`
+note: required by `call_it`
+  --> $DIR/unboxed-closures-unsafe-extern-fn.rs:7:1
+   |
+LL | fn call_it<F:Fn(&isize)->isize>(_: &F, _: isize) -> isize { 0 }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: expected a `std::ops::FnMut<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}`
+  --> $DIR/unboxed-closures-unsafe-extern-fn.rs:18:13
+   |
+LL |     let y = call_it_mut(&mut square, 22);
+   |             ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}`
+   |
+   = help: the trait `for<'r> std::ops::FnMut<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}`
+note: required by `call_it_mut`
+  --> $DIR/unboxed-closures-unsafe-extern-fn.rs:8:1
+   |
+LL | fn call_it_mut<F:FnMut(&isize)->isize>(_: &mut F, _: isize) -> isize { 0 }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}`
+  --> $DIR/unboxed-closures-unsafe-extern-fn.rs:18:13
+   |
+LL |     let y = call_it_mut(&mut square, 22);
+   |             ^^^^^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}`
+   |
+   = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}`
+note: required by `call_it_mut`
+  --> $DIR/unboxed-closures-unsafe-extern-fn.rs:8:1
+   |
+LL | fn call_it_mut<F:FnMut(&isize)->isize>(_: &mut F, _: isize) -> isize { 0 }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}`
+  --> $DIR/unboxed-closures-unsafe-extern-fn.rs:24:13
+   |
+LL |     let z = call_it_once(square, 22);
+   |             ^^^^^^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}`
+   |
+   = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}`
+note: required by `call_it_once`
+  --> $DIR/unboxed-closures-unsafe-extern-fn.rs:9:1
+   |
+LL | fn call_it_once<F:FnOnce(&isize)->isize>(_: F, _: isize) -> isize { 0 }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.rs b/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.rs
new file mode 100644
index 0000000..dd3b1af
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.rs
@@ -0,0 +1,28 @@
+// Tests that unsafe extern fn pointers do not implement any Fn traits.
+
+use std::ops::{Fn,FnMut,FnOnce};
+
+extern "C" fn square(x: &isize) -> isize { (*x) * (*x) }
+
+fn call_it<F:Fn(&isize)->isize>(_: &F, _: isize) -> isize { 0 }
+fn call_it_mut<F:FnMut(&isize)->isize>(_: &mut F, _: isize) -> isize { 0 }
+fn call_it_once<F:FnOnce(&isize)->isize>(_: F, _: isize) -> isize { 0 }
+
+fn a() {
+    let x = call_it(&square, 22);
+    //~^ ERROR E0277
+    //~| ERROR expected
+}
+
+fn b() {
+    let y = call_it_mut(&mut square, 22);
+    //~^ ERROR E0277
+    //~| ERROR expected
+}
+
+fn c() {
+    let z = call_it_once(square, 22);
+    //~^ ERROR E0277
+}
+
+fn main() { }
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr b/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr
new file mode 100644
index 0000000..0abc58a
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr
@@ -0,0 +1,68 @@
+error[E0277]: expected a `std::ops::Fn<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+  --> $DIR/unboxed-closures-wrong-abi.rs:12:13
+   |
+LL |     let x = call_it(&square, 22);
+   |             ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+   |
+   = help: the trait `for<'r> std::ops::Fn<(&'r isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+note: required by `call_it`
+  --> $DIR/unboxed-closures-wrong-abi.rs:7:1
+   |
+LL | fn call_it<F:Fn(&isize)->isize>(_: &F, _: isize) -> isize { 0 }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+  --> $DIR/unboxed-closures-wrong-abi.rs:12:13
+   |
+LL |     let x = call_it(&square, 22);
+   |             ^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+   |
+   = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+note: required by `call_it`
+  --> $DIR/unboxed-closures-wrong-abi.rs:7:1
+   |
+LL | fn call_it<F:Fn(&isize)->isize>(_: &F, _: isize) -> isize { 0 }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: expected a `std::ops::FnMut<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+  --> $DIR/unboxed-closures-wrong-abi.rs:18:13
+   |
+LL |     let y = call_it_mut(&mut square, 22);
+   |             ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+   |
+   = help: the trait `for<'r> std::ops::FnMut<(&'r isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+note: required by `call_it_mut`
+  --> $DIR/unboxed-closures-wrong-abi.rs:8:1
+   |
+LL | fn call_it_mut<F:FnMut(&isize)->isize>(_: &mut F, _: isize) -> isize { 0 }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+  --> $DIR/unboxed-closures-wrong-abi.rs:18:13
+   |
+LL |     let y = call_it_mut(&mut square, 22);
+   |             ^^^^^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+   |
+   = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+note: required by `call_it_mut`
+  --> $DIR/unboxed-closures-wrong-abi.rs:8:1
+   |
+LL | fn call_it_mut<F:FnMut(&isize)->isize>(_: &mut F, _: isize) -> isize { 0 }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+  --> $DIR/unboxed-closures-wrong-abi.rs:24:13
+   |
+LL |     let z = call_it_once(square, 22);
+   |             ^^^^^^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+   |
+   = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+note: required by `call_it_once`
+  --> $DIR/unboxed-closures-wrong-abi.rs:9:1
+   |
+LL | fn call_it_once<F:FnOnce(&isize)->isize>(_: F, _: isize) -> isize { 0 }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.rs b/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.rs
new file mode 100644
index 0000000..c689d79
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.rs
@@ -0,0 +1,29 @@
+// Tests that unsafe extern fn pointers do not implement any Fn traits.
+
+use std::ops::{Fn,FnMut,FnOnce};
+
+unsafe fn square(x: isize) -> isize { x * x }
+// note: argument type here is `isize`, not `&isize`
+
+fn call_it<F:Fn(&isize)->isize>(_: &F, _: isize) -> isize { 0 }
+fn call_it_mut<F:FnMut(&isize)->isize>(_: &mut F, _: isize) -> isize { 0 }
+fn call_it_once<F:FnOnce(&isize)->isize>(_: F, _: isize) -> isize { 0 }
+
+fn a() {
+    let x = call_it(&square, 22);
+    //~^ ERROR E0277
+    //~| ERROR expected
+}
+
+fn b() {
+    let y = call_it_mut(&mut square, 22);
+    //~^ ERROR E0277
+    //~| ERROR expected
+}
+
+fn c() {
+    let z = call_it_once(square, 22);
+    //~^ ERROR E0277
+}
+
+fn main() { }
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr b/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr
new file mode 100644
index 0000000..19b87ad
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr
@@ -0,0 +1,68 @@
+error[E0277]: expected a `std::ops::Fn<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}`
+  --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:13:13
+   |
+LL |     let x = call_it(&square, 22);
+   |             ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}`
+   |
+   = help: the trait `for<'r> std::ops::Fn<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}`
+note: required by `call_it`
+  --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:8:1
+   |
+LL | fn call_it<F:Fn(&isize)->isize>(_: &F, _: isize) -> isize { 0 }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}`
+  --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:13:13
+   |
+LL |     let x = call_it(&square, 22);
+   |             ^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}`
+   |
+   = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}`
+note: required by `call_it`
+  --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:8:1
+   |
+LL | fn call_it<F:Fn(&isize)->isize>(_: &F, _: isize) -> isize { 0 }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: expected a `std::ops::FnMut<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}`
+  --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:19:13
+   |
+LL |     let y = call_it_mut(&mut square, 22);
+   |             ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}`
+   |
+   = help: the trait `for<'r> std::ops::FnMut<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}`
+note: required by `call_it_mut`
+  --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:9:1
+   |
+LL | fn call_it_mut<F:FnMut(&isize)->isize>(_: &mut F, _: isize) -> isize { 0 }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}`
+  --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:19:13
+   |
+LL |     let y = call_it_mut(&mut square, 22);
+   |             ^^^^^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}`
+   |
+   = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}`
+note: required by `call_it_mut`
+  --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:9:1
+   |
+LL | fn call_it_mut<F:FnMut(&isize)->isize>(_: &mut F, _: isize) -> isize { 0 }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}`
+  --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:25:13
+   |
+LL |     let z = call_it_once(square, 22);
+   |             ^^^^^^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}`
+   |
+   = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}`
+note: required by `call_it_once`
+  --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:10:1
+   |
+LL | fn call_it_once<F:FnOnce(&isize)->isize>(_: F, _: isize) -> isize { 0 }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/unconstrained-none.rs b/src/test/ui/unconstrained-none.rs
new file mode 100644
index 0000000..e180b31
--- /dev/null
+++ b/src/test/ui/unconstrained-none.rs
@@ -0,0 +1,5 @@
+// Issue #5062
+
+fn main() {
+    None; //~ ERROR type annotations needed [E0282]
+}
diff --git a/src/test/ui/unconstrained-none.stderr b/src/test/ui/unconstrained-none.stderr
new file mode 100644
index 0000000..eb918b2
--- /dev/null
+++ b/src/test/ui/unconstrained-none.stderr
@@ -0,0 +1,9 @@
+error[E0282]: type annotations needed
+  --> $DIR/unconstrained-none.rs:4:5
+   |
+LL |     None;
+   |     ^^^^ cannot infer type for `T`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/unconstrained-ref.rs b/src/test/ui/unconstrained-ref.rs
new file mode 100644
index 0000000..473ca95
--- /dev/null
+++ b/src/test/ui/unconstrained-ref.rs
@@ -0,0 +1,7 @@
+struct S<'a, T:'a> {
+    o: &'a Option<T>
+}
+
+fn main() {
+    S { o: &None }; //~ ERROR type annotations needed [E0282]
+}
diff --git a/src/test/ui/unconstrained-ref.stderr b/src/test/ui/unconstrained-ref.stderr
new file mode 100644
index 0000000..d9a129a
--- /dev/null
+++ b/src/test/ui/unconstrained-ref.stderr
@@ -0,0 +1,9 @@
+error[E0282]: type annotations needed
+  --> $DIR/unconstrained-ref.rs:6:5
+   |
+LL |     S { o: &None };
+   |     ^ cannot infer type for `T`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/underscore-ident-matcher.rs b/src/test/ui/underscore-ident-matcher.rs
new file mode 100644
index 0000000..bddc8c8
--- /dev/null
+++ b/src/test/ui/underscore-ident-matcher.rs
@@ -0,0 +1,9 @@
+macro_rules! identity {
+    ($i: ident) => (
+        $i
+    )
+}
+
+fn main() {
+    let identity!(_) = 10; //~ ERROR no rules expected the token `_`
+}
diff --git a/src/test/ui/underscore-ident-matcher.stderr b/src/test/ui/underscore-ident-matcher.stderr
new file mode 100644
index 0000000..241c3d3
--- /dev/null
+++ b/src/test/ui/underscore-ident-matcher.stderr
@@ -0,0 +1,11 @@
+error: no rules expected the token `_`
+  --> $DIR/underscore-ident-matcher.rs:8:19
+   |
+LL | macro_rules! identity {
+   | --------------------- when calling this macro
+...
+LL |     let identity!(_) = 10;
+   |                   ^ no rules expected this token in macro call
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.rs b/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.rs
new file mode 100644
index 0000000..37c87db
--- /dev/null
+++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.rs
@@ -0,0 +1,13 @@
+// Check that the `'_` in `dyn Trait + '_` acts like ordinary elision,
+// and not like an object lifetime default.
+//
+// cc #48468
+
+use std::fmt::Debug;
+
+struct Foo {
+    x: Box<dyn Debug + '_>, //~ ERROR missing lifetime specifier
+    //~^ ERROR E0228
+}
+
+fn main() { }
diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.stderr
new file mode 100644
index 0000000..1ea9c42
--- /dev/null
+++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.stderr
@@ -0,0 +1,16 @@
+error[E0106]: missing lifetime specifier
+  --> $DIR/dyn-trait-underscore-in-struct.rs:9:24
+   |
+LL |     x: Box<dyn Debug + '_>,
+   |                        ^^ expected lifetime parameter
+
+error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound
+  --> $DIR/dyn-trait-underscore-in-struct.rs:9:12
+   |
+LL |     x: Box<dyn Debug + '_>,
+   |            ^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0106, E0228.
+For more information about an error, try `rustc --explain E0106`.
diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.rs b/src/test/ui/underscore-lifetime/dyn-trait-underscore.rs
new file mode 100644
index 0000000..d5aa18e
--- /dev/null
+++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.rs
@@ -0,0 +1,19 @@
+// Check that the `'_` in `dyn Trait + '_` acts like ordinary elision,
+// and not like an object lifetime default.
+//
+// cc #48468
+
+fn a<T>(items: &[T]) -> Box<dyn Iterator<Item=&T>> {
+    //                      ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static`
+    Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime
+}
+
+fn b<T>(items: &[T]) -> Box<dyn Iterator<Item=&T> + '_> {
+    Box::new(items.iter()) // OK, equivalent to c
+}
+
+fn c<'a, T>(items: &'a [T]) -> Box<dyn Iterator<Item=&'a T> + 'a> {
+    Box::new(items.iter()) // OK, equivalent to b
+}
+
+fn main() { }
diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr
new file mode 100644
index 0000000..d0475bf
--- /dev/null
+++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr
@@ -0,0 +1,27 @@
+error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
+  --> $DIR/dyn-trait-underscore.rs:8:20
+   |
+LL |     Box::new(items.iter())
+   |                    ^^^^
+   |
+note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the function body at 6:1...
+  --> $DIR/dyn-trait-underscore.rs:6:1
+   |
+LL | / fn a<T>(items: &[T]) -> Box<dyn Iterator<Item=&T>> {
+LL | |     //                      ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static`
+LL | |     Box::new(items.iter())
+LL | | }
+   | |_^
+note: ...so that reference does not outlive borrowed content
+  --> $DIR/dyn-trait-underscore.rs:8:14
+   |
+LL |     Box::new(items.iter())
+   |              ^^^^^
+   = note: but, the lifetime must be valid for the static lifetime...
+   = note: ...so that the expression is assignable:
+           expected std::boxed::Box<(dyn std::iter::Iterator<Item = &T> + 'static)>
+              found std::boxed::Box<dyn std::iter::Iterator<Item = &T>>
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0495`.
diff --git a/src/test/ui/underscore-lifetime/in-binder.rs b/src/test/ui/underscore-lifetime/in-binder.rs
new file mode 100644
index 0000000..e4ee5e8
--- /dev/null
+++ b/src/test/ui/underscore-lifetime/in-binder.rs
@@ -0,0 +1,35 @@
+// Check that we error when `'_` appears as the name of a lifetime parameter.
+//
+// Regression test for #52098.
+
+struct IceCube<'a> {
+    v: Vec<&'a char>
+}
+
+impl<'_> IceCube<'_> {}
+//~^ ERROR `'_` cannot be used here
+
+struct Struct<'_> {
+//~^ ERROR `'_` cannot be used here
+    v: Vec<&'static char>
+}
+
+enum Enum<'_> {
+//~^ ERROR `'_` cannot be used here
+    Variant
+}
+
+union Union<'_> {
+//~^ ERROR `'_` cannot be used here
+    a: u32
+}
+
+trait Trait<'_> {
+//~^ ERROR `'_` cannot be used here
+}
+
+fn foo<'_>() {
+    //~^ ERROR `'_` cannot be used here
+}
+
+fn main() {}
diff --git a/src/test/ui/underscore-lifetime/in-binder.stderr b/src/test/ui/underscore-lifetime/in-binder.stderr
new file mode 100644
index 0000000..fcd7edd
--- /dev/null
+++ b/src/test/ui/underscore-lifetime/in-binder.stderr
@@ -0,0 +1,39 @@
+error[E0637]: `'_` cannot be used here
+  --> $DIR/in-binder.rs:9:6
+   |
+LL | impl<'_> IceCube<'_> {}
+   |      ^^ `'_` is a reserved lifetime name
+
+error[E0637]: `'_` cannot be used here
+  --> $DIR/in-binder.rs:12:15
+   |
+LL | struct Struct<'_> {
+   |               ^^ `'_` is a reserved lifetime name
+
+error[E0637]: `'_` cannot be used here
+  --> $DIR/in-binder.rs:17:11
+   |
+LL | enum Enum<'_> {
+   |           ^^ `'_` is a reserved lifetime name
+
+error[E0637]: `'_` cannot be used here
+  --> $DIR/in-binder.rs:22:13
+   |
+LL | union Union<'_> {
+   |             ^^ `'_` is a reserved lifetime name
+
+error[E0637]: `'_` cannot be used here
+  --> $DIR/in-binder.rs:27:13
+   |
+LL | trait Trait<'_> {
+   |             ^^ `'_` is a reserved lifetime name
+
+error[E0637]: `'_` cannot be used here
+  --> $DIR/in-binder.rs:31:8
+   |
+LL | fn foo<'_>() {
+   |        ^^ `'_` is a reserved lifetime name
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0637`.
diff --git a/src/test/ui/underscore-lifetime/in-fn-return-illegal.rs b/src/test/ui/underscore-lifetime/in-fn-return-illegal.rs
new file mode 100644
index 0000000..a46ece7
--- /dev/null
+++ b/src/test/ui/underscore-lifetime/in-fn-return-illegal.rs
@@ -0,0 +1,7 @@
+// Check that the `'_` used in structs/enums gives an error.
+
+use std::fmt::Debug;
+
+fn foo(x: &u32, y: &u32) -> &'_ u32 { loop { } } //~ ERROR missing lifetime specifier
+
+fn main() { }
diff --git a/src/test/ui/underscore-lifetime/in-fn-return-illegal.stderr b/src/test/ui/underscore-lifetime/in-fn-return-illegal.stderr
new file mode 100644
index 0000000..ed61bdf
--- /dev/null
+++ b/src/test/ui/underscore-lifetime/in-fn-return-illegal.stderr
@@ -0,0 +1,11 @@
+error[E0106]: missing lifetime specifier
+  --> $DIR/in-fn-return-illegal.rs:5:30
+   |
+LL | fn foo(x: &u32, y: &u32) -> &'_ u32 { loop { } }
+   |                              ^^ expected lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `x` or `y`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0106`.
diff --git a/src/test/ui/underscore-lifetime/in-struct.rs b/src/test/ui/underscore-lifetime/in-struct.rs
new file mode 100644
index 0000000..bed89c7
--- /dev/null
+++ b/src/test/ui/underscore-lifetime/in-struct.rs
@@ -0,0 +1,13 @@
+// Check that the `'_` used in structs/enums gives an error.
+
+use std::fmt::Debug;
+
+struct Foo {
+    x: &'_ u32, //~ ERROR missing lifetime specifier
+}
+
+enum Bar {
+    Variant(&'_ u32), //~ ERROR missing lifetime specifier
+}
+
+fn main() { }
diff --git a/src/test/ui/underscore-lifetime/in-struct.stderr b/src/test/ui/underscore-lifetime/in-struct.stderr
new file mode 100644
index 0000000..6bbdc71
--- /dev/null
+++ b/src/test/ui/underscore-lifetime/in-struct.stderr
@@ -0,0 +1,15 @@
+error[E0106]: missing lifetime specifier
+  --> $DIR/in-struct.rs:6:9
+   |
+LL |     x: &'_ u32,
+   |         ^^ expected lifetime parameter
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/in-struct.rs:10:14
+   |
+LL |     Variant(&'_ u32),
+   |              ^^ expected lifetime parameter
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0106`.
diff --git a/src/test/ui/underscore-lifetime/underscore-lifetime-binders.rs b/src/test/ui/underscore-lifetime/underscore-lifetime-binders.rs
new file mode 100644
index 0000000..614f7e4
--- /dev/null
+++ b/src/test/ui/underscore-lifetime/underscore-lifetime-binders.rs
@@ -0,0 +1,22 @@
+struct Foo<'a>(&'a u8);
+struct Baz<'a>(&'_ &'a u8); //~ ERROR missing lifetime specifier
+
+fn foo<'_> //~ ERROR cannot be used here
+(_: Foo<'_>) {}
+
+trait Meh<'a> {}
+impl<'a> Meh<'a> for u8 {}
+
+fn meh() -> Box<for<'_> Meh<'_>> //~ ERROR cannot be used here
+//~^ ERROR missing lifetime specifier
+{
+  Box::new(5u8)
+}
+
+fn foo2(_: &'_ u8, y: &'_ u8) -> &'_ u8 { y } //~ ERROR missing lifetime specifier
+
+fn main() {
+    let x = 5;
+    foo(Foo(&x));
+    let _ = meh();
+}
diff --git a/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr b/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr
new file mode 100644
index 0000000..104e638
--- /dev/null
+++ b/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr
@@ -0,0 +1,38 @@
+error[E0637]: `'_` cannot be used here
+  --> $DIR/underscore-lifetime-binders.rs:4:8
+   |
+LL | fn foo<'_>
+   |        ^^ `'_` is a reserved lifetime name
+
+error[E0637]: `'_` cannot be used here
+  --> $DIR/underscore-lifetime-binders.rs:10:21
+   |
+LL | fn meh() -> Box<for<'_> Meh<'_>>
+   |                     ^^ `'_` is a reserved lifetime name
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/underscore-lifetime-binders.rs:2:17
+   |
+LL | struct Baz<'a>(&'_ &'a u8);
+   |                 ^^ expected lifetime parameter
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/underscore-lifetime-binders.rs:10:29
+   |
+LL | fn meh() -> Box<for<'_> Meh<'_>>
+   |                             ^^ help: consider giving it a 'static lifetime: `'static`
+   |
+   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/underscore-lifetime-binders.rs:16:35
+   |
+LL | fn foo2(_: &'_ u8, y: &'_ u8) -> &'_ u8 { y }
+   |                                   ^^ expected lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `_` or `y`
+
+error: aborting due to 5 previous errors
+
+Some errors occurred: E0106, E0637.
+For more information about an error, try `rustc --explain E0106`.
diff --git a/src/test/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.rs b/src/test/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.rs
new file mode 100644
index 0000000..f465a80
--- /dev/null
+++ b/src/test/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.rs
@@ -0,0 +1,3 @@
+fn foo(x: &mut Vec<&'_ u8>, y: &'_ u8) { x.push(y); } //~ ERROR lifetime mismatch
+
+fn main() {}
diff --git a/src/test/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.stderr b/src/test/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.stderr
new file mode 100644
index 0000000..76c14cc
--- /dev/null
+++ b/src/test/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.stderr
@@ -0,0 +1,11 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/underscore-lifetime-elison-mismatch.rs:1:49
+   |
+LL | fn foo(x: &mut Vec<&'_ u8>, y: &'_ u8) { x.push(y); }
+   |                    ------      ------           ^ ...but data from `y` flows into `x` here
+   |                                |
+   |                                these two types are declared with different lifetimes...
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/underscore-lifetime/underscore-outlives-bounds.rs b/src/test/ui/underscore-lifetime/underscore-outlives-bounds.rs
new file mode 100644
index 0000000..567cc7a
--- /dev/null
+++ b/src/test/ui/underscore-lifetime/underscore-outlives-bounds.rs
@@ -0,0 +1,8 @@
+// Regression test to check that `'b: '_` gets an error, because it's
+// basically useless.
+//
+// #54902
+
+trait Foo<'a> {}
+impl<'b: '_> Foo<'b> for i32 {} //~ ERROR `'_` cannot be used here
+fn main() { }
diff --git a/src/test/ui/underscore-lifetime/underscore-outlives-bounds.stderr b/src/test/ui/underscore-lifetime/underscore-outlives-bounds.stderr
new file mode 100644
index 0000000..4b38a26
--- /dev/null
+++ b/src/test/ui/underscore-lifetime/underscore-outlives-bounds.stderr
@@ -0,0 +1,9 @@
+error[E0637]: `'_` cannot be used here
+  --> $DIR/underscore-outlives-bounds.rs:7:10
+   |
+LL | impl<'b: '_> Foo<'b> for i32 {}
+   |          ^^ `'_` is a reserved lifetime name
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0637`.
diff --git a/src/test/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rs b/src/test/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rs
new file mode 100644
index 0000000..43de309
--- /dev/null
+++ b/src/test/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rs
@@ -0,0 +1,18 @@
+// revisions: rust2015 rust2018
+//[rust2018] edition:2018
+
+trait WithType<T> {}
+trait WithRegion<'a> { }
+
+struct Foo<T> {
+    t: T
+}
+
+impl<T> Foo<T>
+where
+    T: WithType<&u32>
+//[rust2015]~^ ERROR `&` without an explicit lifetime name cannot be used here
+//[rust2018]~^^ ERROR `&` without an explicit lifetime name cannot be used here
+{ }
+
+fn main() {}
diff --git a/src/test/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2015.stderr b/src/test/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2015.stderr
new file mode 100644
index 0000000..fe726cb
--- /dev/null
+++ b/src/test/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2015.stderr
@@ -0,0 +1,9 @@
+error[E0637]: `&` without an explicit lifetime name cannot be used here
+  --> $DIR/where-clause-inherent-impl-ampersand.rs:13:17
+   |
+LL |     T: WithType<&u32>
+   |                 ^ explicit lifetime name needed here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0637`.
diff --git a/src/test/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2018.stderr b/src/test/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2018.stderr
new file mode 100644
index 0000000..fe726cb
--- /dev/null
+++ b/src/test/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2018.stderr
@@ -0,0 +1,9 @@
+error[E0637]: `&` without an explicit lifetime name cannot be used here
+  --> $DIR/where-clause-inherent-impl-ampersand.rs:13:17
+   |
+LL |     T: WithType<&u32>
+   |                 ^ explicit lifetime name needed here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0637`.
diff --git a/src/test/ui/underscore-lifetime/where-clause-inherent-impl-underscore.rs b/src/test/ui/underscore-lifetime/where-clause-inherent-impl-underscore.rs
new file mode 100644
index 0000000..b50cce3
--- /dev/null
+++ b/src/test/ui/underscore-lifetime/where-clause-inherent-impl-underscore.rs
@@ -0,0 +1,18 @@
+// revisions: rust2015 rust2018
+//[rust2018] edition:2018
+
+trait WithType<T> {}
+trait WithRegion<'a> { }
+
+struct Foo<T> {
+    t: T
+}
+
+impl<T> Foo<T>
+where
+    T: WithRegion<'_>
+//[rust2015]~^ ERROR `'_` cannot be used here
+//[rust2018]~^^ ERROR `'_` cannot be used here
+{ }
+
+fn main() {}
diff --git a/src/test/ui/underscore-lifetime/where-clause-inherent-impl-underscore.rust2015.stderr b/src/test/ui/underscore-lifetime/where-clause-inherent-impl-underscore.rust2015.stderr
new file mode 100644
index 0000000..95939fd
--- /dev/null
+++ b/src/test/ui/underscore-lifetime/where-clause-inherent-impl-underscore.rust2015.stderr
@@ -0,0 +1,9 @@
+error[E0637]: `'_` cannot be used here
+  --> $DIR/where-clause-inherent-impl-underscore.rs:13:19
+   |
+LL |     T: WithRegion<'_>
+   |                   ^^ `'_` is a reserved lifetime name
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0637`.
diff --git a/src/test/ui/underscore-lifetime/where-clause-inherent-impl-underscore.rust2018.stderr b/src/test/ui/underscore-lifetime/where-clause-inherent-impl-underscore.rust2018.stderr
new file mode 100644
index 0000000..95939fd
--- /dev/null
+++ b/src/test/ui/underscore-lifetime/where-clause-inherent-impl-underscore.rust2018.stderr
@@ -0,0 +1,9 @@
+error[E0637]: `'_` cannot be used here
+  --> $DIR/where-clause-inherent-impl-underscore.rs:13:19
+   |
+LL |     T: WithRegion<'_>
+   |                   ^^ `'_` is a reserved lifetime name
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0637`.
diff --git a/src/test/ui/underscore-lifetime/where-clause-trait-impl-region.rs b/src/test/ui/underscore-lifetime/where-clause-trait-impl-region.rs
new file mode 100644
index 0000000..f2d483e
--- /dev/null
+++ b/src/test/ui/underscore-lifetime/where-clause-trait-impl-region.rs
@@ -0,0 +1,16 @@
+// revisions: rust2015 rust2018
+//[rust2018] edition:2018
+
+trait WithType<T> {}
+trait WithRegion<'a> { }
+
+trait Foo { }
+
+impl<T> Foo for Vec<T>
+where
+    T: WithType<&u32>
+//[rust2015]~^ ERROR `&` without an explicit lifetime name cannot be used here
+//[rust2018]~^^ ERROR `&` without an explicit lifetime name cannot be used here
+{ }
+
+fn main() {}
diff --git a/src/test/ui/underscore-lifetime/where-clause-trait-impl-region.rust2015.stderr b/src/test/ui/underscore-lifetime/where-clause-trait-impl-region.rust2015.stderr
new file mode 100644
index 0000000..fbd14de
--- /dev/null
+++ b/src/test/ui/underscore-lifetime/where-clause-trait-impl-region.rust2015.stderr
@@ -0,0 +1,9 @@
+error[E0637]: `&` without an explicit lifetime name cannot be used here
+  --> $DIR/where-clause-trait-impl-region.rs:11:17
+   |
+LL |     T: WithType<&u32>
+   |                 ^ explicit lifetime name needed here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0637`.
diff --git a/src/test/ui/underscore-lifetime/where-clause-trait-impl-region.rust2018.stderr b/src/test/ui/underscore-lifetime/where-clause-trait-impl-region.rust2018.stderr
new file mode 100644
index 0000000..fbd14de
--- /dev/null
+++ b/src/test/ui/underscore-lifetime/where-clause-trait-impl-region.rust2018.stderr
@@ -0,0 +1,9 @@
+error[E0637]: `&` without an explicit lifetime name cannot be used here
+  --> $DIR/where-clause-trait-impl-region.rs:11:17
+   |
+LL |     T: WithType<&u32>
+   |                 ^ explicit lifetime name needed here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0637`.
diff --git a/src/test/ui/underscore-lifetime/where-clause-trait-impl-underscore.rs b/src/test/ui/underscore-lifetime/where-clause-trait-impl-underscore.rs
new file mode 100644
index 0000000..94e4426
--- /dev/null
+++ b/src/test/ui/underscore-lifetime/where-clause-trait-impl-underscore.rs
@@ -0,0 +1,16 @@
+// revisions: rust2015 rust2018
+//[rust2018] edition:2018
+
+trait WithType<T> {}
+trait WithRegion<'a> { }
+
+trait Foo { }
+
+impl<T> Foo for Vec<T>
+where
+    T: WithRegion<'_>
+//[rust2015]~^ ERROR `'_` cannot be used here
+//[rust2018]~^^ ERROR `'_` cannot be used here
+{ }
+
+fn main() {}
diff --git a/src/test/ui/underscore-lifetime/where-clause-trait-impl-underscore.rust2015.stderr b/src/test/ui/underscore-lifetime/where-clause-trait-impl-underscore.rust2015.stderr
new file mode 100644
index 0000000..92caff0
--- /dev/null
+++ b/src/test/ui/underscore-lifetime/where-clause-trait-impl-underscore.rust2015.stderr
@@ -0,0 +1,9 @@
+error[E0637]: `'_` cannot be used here
+  --> $DIR/where-clause-trait-impl-underscore.rs:11:19
+   |
+LL |     T: WithRegion<'_>
+   |                   ^^ `'_` is a reserved lifetime name
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0637`.
diff --git a/src/test/ui/underscore-lifetime/where-clause-trait-impl-underscore.rust2018.stderr b/src/test/ui/underscore-lifetime/where-clause-trait-impl-underscore.rust2018.stderr
new file mode 100644
index 0000000..92caff0
--- /dev/null
+++ b/src/test/ui/underscore-lifetime/where-clause-trait-impl-underscore.rust2018.stderr
@@ -0,0 +1,9 @@
+error[E0637]: `'_` cannot be used here
+  --> $DIR/where-clause-trait-impl-underscore.rs:11:19
+   |
+LL |     T: WithRegion<'_>
+   |                   ^^ `'_` is a reserved lifetime name
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0637`.
diff --git a/src/test/ui/underscore-lifetime/where-clauses.rs b/src/test/ui/underscore-lifetime/where-clauses.rs
new file mode 100644
index 0000000..ee6823b
--- /dev/null
+++ b/src/test/ui/underscore-lifetime/where-clauses.rs
@@ -0,0 +1,7 @@
+trait Foo<'a> {}
+
+impl<'b: '_> Foo<'b> for i32 {} //~ ERROR `'_` cannot be used here
+
+impl<T: '_> Foo<'static> for Vec<T> {} //~ ERROR `'_` cannot be used here
+
+fn main() { }
diff --git a/src/test/ui/underscore-lifetime/where-clauses.stderr b/src/test/ui/underscore-lifetime/where-clauses.stderr
new file mode 100644
index 0000000..1a3ea4a
--- /dev/null
+++ b/src/test/ui/underscore-lifetime/where-clauses.stderr
@@ -0,0 +1,15 @@
+error[E0637]: `'_` cannot be used here
+  --> $DIR/where-clauses.rs:3:10
+   |
+LL | impl<'b: '_> Foo<'b> for i32 {}
+   |          ^^ `'_` is a reserved lifetime name
+
+error[E0637]: `'_` cannot be used here
+  --> $DIR/where-clauses.rs:5:9
+   |
+LL | impl<T: '_> Foo<'static> for Vec<T> {}
+   |         ^^ `'_` is a reserved lifetime name
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0637`.
diff --git a/src/test/ui/underscore_const_names.rs b/src/test/ui/underscore_const_names.rs
new file mode 100644
index 0000000..1db022e
--- /dev/null
+++ b/src/test/ui/underscore_const_names.rs
@@ -0,0 +1,32 @@
+// compile-pass
+
+#![feature(underscore_const_names)]
+
+trait Trt {}
+struct Str {}
+impl Trt for Str {}
+
+macro_rules! check_impl {
+    ($struct:ident,$trait:ident) => {
+        const _ : () = {
+            use std::marker::PhantomData;
+            struct ImplementsTrait<T: $trait>(PhantomData<T>);
+            let _ = ImplementsTrait::<$struct>(PhantomData);
+            ()
+        };
+    }
+}
+
+#[deny(unused)]
+const _ : () = ();
+
+const _ : i32 = 42;
+const _ : Str = Str{};
+
+check_impl!(Str, Trt);
+check_impl!(Str, Trt);
+
+fn main() {
+  check_impl!(Str, Trt);
+  check_impl!(Str, Trt);
+}
diff --git a/src/test/ui/unevaluated_fixed_size_array_len.rs b/src/test/ui/unevaluated_fixed_size_array_len.rs
new file mode 100644
index 0000000..6c54591
--- /dev/null
+++ b/src/test/ui/unevaluated_fixed_size_array_len.rs
@@ -0,0 +1,13 @@
+// https://github.com/rust-lang/rust/issues/49208
+
+trait Foo {
+    fn foo();
+}
+
+impl Foo for [(); 1] {
+    fn foo() {}
+}
+
+fn main() {
+    <[(); 0] as Foo>::foo() //~ ERROR E0277
+}
diff --git a/src/test/ui/unevaluated_fixed_size_array_len.stderr b/src/test/ui/unevaluated_fixed_size_array_len.stderr
new file mode 100644
index 0000000..be6ed8d
--- /dev/null
+++ b/src/test/ui/unevaluated_fixed_size_array_len.stderr
@@ -0,0 +1,17 @@
+error[E0277]: the trait bound `[(); 0]: Foo` is not satisfied
+  --> $DIR/unevaluated_fixed_size_array_len.rs:12:5
+   |
+LL |     <[(); 0] as Foo>::foo()
+   |     ^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `[(); 0]`
+   |
+   = help: the following implementations were found:
+             <[(); 1] as Foo>
+note: required by `Foo::foo`
+  --> $DIR/unevaluated_fixed_size_array_len.rs:4:5
+   |
+LL |     fn foo();
+   |     ^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/uninhabited/privately-uninhabited-dead-code.rs b/src/test/ui/uninhabited/privately-uninhabited-dead-code.rs
new file mode 100644
index 0000000..9fe8a5c
--- /dev/null
+++ b/src/test/ui/uninhabited/privately-uninhabited-dead-code.rs
@@ -0,0 +1,20 @@
+// compile-pass
+
+#![deny(unused_variables)]
+
+mod foo {
+    enum Bar {}
+
+    #[allow(dead_code)]
+    pub struct Foo {
+        value: Bar, // "privately" uninhabited
+    }
+
+    pub fn give_foo() -> Foo { panic!() }
+}
+
+fn main() {
+    let a = 42;
+    foo::give_foo();
+    println!("Hello, {}", a); // ok: we can't tell that this code is dead
+}
diff --git a/src/test/ui/uninhabited/uninhabited-enum-cast.rs b/src/test/ui/uninhabited/uninhabited-enum-cast.rs
new file mode 100644
index 0000000..7e178e0
--- /dev/null
+++ b/src/test/ui/uninhabited/uninhabited-enum-cast.rs
@@ -0,0 +1,7 @@
+enum E {}
+
+fn f(e: E) {
+    println!("{}", (e as isize).to_string());   //~ ERROR non-primitive cast
+}
+
+fn main() {}
diff --git a/src/test/ui/uninhabited/uninhabited-enum-cast.stderr b/src/test/ui/uninhabited/uninhabited-enum-cast.stderr
new file mode 100644
index 0000000..a39af78
--- /dev/null
+++ b/src/test/ui/uninhabited/uninhabited-enum-cast.stderr
@@ -0,0 +1,11 @@
+error[E0605]: non-primitive cast: `E` as `isize`
+  --> $DIR/uninhabited-enum-cast.rs:4:20
+   |
+LL |     println!("{}", (e as isize).to_string());
+   |                    ^^^^^^^^^^^^
+   |
+   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0605`.
diff --git a/src/test/ui/uninhabited/uninhabited-irrefutable.rs b/src/test/ui/uninhabited/uninhabited-irrefutable.rs
new file mode 100644
index 0000000..c32d3a4
--- /dev/null
+++ b/src/test/ui/uninhabited/uninhabited-irrefutable.rs
@@ -0,0 +1,29 @@
+#![feature(never_type)]
+#![feature(exhaustive_patterns)]
+
+mod foo {
+    pub struct SecretlyEmpty {
+        _priv: !,
+    }
+
+    pub struct NotSoSecretlyEmpty {
+        pub _pub: !,
+    }
+}
+
+struct NotSoSecretlyEmpty {
+    _priv: !,
+}
+
+enum Foo {
+    A(foo::SecretlyEmpty),
+    B(foo::NotSoSecretlyEmpty),
+    C(NotSoSecretlyEmpty),
+    D(u32),
+}
+
+fn main() {
+    let x: Foo = Foo::D(123);
+    let Foo::D(_y) = x; //~ ERROR refutable pattern in local binding: `A(_)` not covered
+}
+
diff --git a/src/test/ui/uninhabited/uninhabited-irrefutable.stderr b/src/test/ui/uninhabited/uninhabited-irrefutable.stderr
new file mode 100644
index 0000000..45976f8
--- /dev/null
+++ b/src/test/ui/uninhabited/uninhabited-irrefutable.stderr
@@ -0,0 +1,17 @@
+error[E0005]: refutable pattern in local binding: `A(_)` not covered
+  --> $DIR/uninhabited-irrefutable.rs:27:9
+   |
+LL | / enum Foo {
+LL | |     A(foo::SecretlyEmpty),
+LL | |     B(foo::NotSoSecretlyEmpty),
+LL | |     C(NotSoSecretlyEmpty),
+LL | |     D(u32),
+LL | | }
+   | |_- `Foo` defined here
+...
+LL |       let Foo::D(_y) = x;
+   |           ^^^^^^^^^^ pattern `A(_)` not covered
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0005`.
diff --git a/src/test/ui/uninhabited/uninhabited-matches-feature-gated.rs b/src/test/ui/uninhabited/uninhabited-matches-feature-gated.rs
new file mode 100644
index 0000000..38a52d5
--- /dev/null
+++ b/src/test/ui/uninhabited/uninhabited-matches-feature-gated.rs
@@ -0,0 +1,34 @@
+enum Void {}
+
+fn main() {
+    let x: Result<u32, &'static Void> = Ok(23);
+    let _ = match x {   //~ ERROR non-exhaustive
+        Ok(n) => n,
+    };
+
+    let x: &Void = unsafe { std::mem::uninitialized() };
+    let _ = match x {}; //~ ERROR non-exhaustive
+
+    let x: (Void,) = unsafe { std::mem::uninitialized() };
+    let _ = match x {}; //~ ERROR non-exhaustive
+
+    let x: [Void; 1] = unsafe { std::mem::uninitialized() };
+    let _ = match x {}; //~ ERROR non-exhaustive
+
+    let x: &[Void] = unsafe { std::mem::uninitialized() };
+    let _ = match x {   //~ ERROR non-exhaustive
+        &[] => (),
+    };
+
+    let x: Void = unsafe { std::mem::uninitialized() };
+    let _ = match x {}; // okay
+
+    let x: Result<u32, Void> = Ok(23);
+    let _ = match x {   //~ ERROR non-exhaustive
+        Ok(x) => x,
+    };
+
+    let x: Result<u32, Void> = Ok(23);
+    let Ok(x) = x;
+    //~^ ERROR refutable
+}
diff --git a/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr b/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr
new file mode 100644
index 0000000..533cf59
--- /dev/null
+++ b/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr
@@ -0,0 +1,58 @@
+error[E0004]: non-exhaustive patterns: `Err(_)` not covered
+  --> $DIR/uninhabited-matches-feature-gated.rs:5:19
+   |
+LL |     let _ = match x {
+   |                   ^ pattern `Err(_)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: type `&Void` is non-empty
+  --> $DIR/uninhabited-matches-feature-gated.rs:10:19
+   |
+LL |     let _ = match x {};
+   |                   ^
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: type `(Void,)` is non-empty
+  --> $DIR/uninhabited-matches-feature-gated.rs:13:19
+   |
+LL |     let _ = match x {};
+   |                   ^
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: type `[Void; 1]` is non-empty
+  --> $DIR/uninhabited-matches-feature-gated.rs:16:19
+   |
+LL |     let _ = match x {};
+   |                   ^
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `&[_]` not covered
+  --> $DIR/uninhabited-matches-feature-gated.rs:19:19
+   |
+LL |     let _ = match x {
+   |                   ^ pattern `&[_]` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `Err(_)` not covered
+  --> $DIR/uninhabited-matches-feature-gated.rs:27:19
+   |
+LL |     let _ = match x {
+   |                   ^ pattern `Err(_)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0005]: refutable pattern in local binding: `Err(_)` not covered
+  --> $DIR/uninhabited-matches-feature-gated.rs:32:9
+   |
+LL |     let Ok(x) = x;
+   |         ^^^^^ pattern `Err(_)` not covered
+
+error: aborting due to 7 previous errors
+
+Some errors occurred: E0004, E0005.
+For more information about an error, try `rustc --explain E0004`.
diff --git a/src/test/ui/uninhabited/uninhabited-patterns.rs b/src/test/ui/uninhabited/uninhabited-patterns.rs
new file mode 100644
index 0000000..609ed3d
--- /dev/null
+++ b/src/test/ui/uninhabited/uninhabited-patterns.rs
@@ -0,0 +1,48 @@
+#![feature(box_patterns)]
+#![feature(box_syntax)]
+#![feature(never_type)]
+#![feature(exhaustive_patterns)]
+#![feature(slice_patterns)]
+#![deny(unreachable_patterns)]
+
+mod foo {
+    pub struct SecretlyEmpty {
+        _priv: !,
+    }
+}
+
+struct NotSoSecretlyEmpty {
+    _priv: !,
+}
+
+fn foo() -> Option<NotSoSecretlyEmpty> {
+    None
+}
+
+fn main() {
+    let x: &[!] = &[];
+
+    match x {
+        &[]   => (),
+        &[..] => (),    //~ ERROR unreachable pattern
+    };
+
+    let x: Result<Box<NotSoSecretlyEmpty>, &[Result<!, !>]> = Err(&[]);
+    match x {
+        Ok(box _) => (),    //~ ERROR unreachable pattern
+        Err(&[]) => (),
+        Err(&[..]) => (),   //~ ERROR unreachable pattern
+    }
+
+    let x: Result<foo::SecretlyEmpty, Result<NotSoSecretlyEmpty, u32>> = Err(Err(123));
+    match x {
+        Ok(_y) => (),
+        Err(Err(_y)) => (),
+        Err(Ok(_y)) => (),  //~ ERROR unreachable pattern
+    }
+
+    while let Some(_y) = foo() {
+        //~^ ERROR unreachable pattern
+    }
+}
+
diff --git a/src/test/ui/uninhabited/uninhabited-patterns.stderr b/src/test/ui/uninhabited/uninhabited-patterns.stderr
new file mode 100644
index 0000000..3e5329c
--- /dev/null
+++ b/src/test/ui/uninhabited/uninhabited-patterns.stderr
@@ -0,0 +1,38 @@
+error: unreachable pattern
+  --> $DIR/uninhabited-patterns.rs:27:9
+   |
+LL |         &[..] => (),
+   |         ^^^^^
+   |
+note: lint level defined here
+  --> $DIR/uninhabited-patterns.rs:6:9
+   |
+LL | #![deny(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/uninhabited-patterns.rs:32:9
+   |
+LL |         Ok(box _) => (),
+   |         ^^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/uninhabited-patterns.rs:34:9
+   |
+LL |         Err(&[..]) => (),
+   |         ^^^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/uninhabited-patterns.rs:41:9
+   |
+LL |         Err(Ok(_y)) => (),
+   |         ^^^^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/uninhabited-patterns.rs:44:15
+   |
+LL |     while let Some(_y) = foo() {
+   |               ^^^^^^^^
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/ui/union/union-borrow-move-parent-sibling.nll.stderr b/src/test/ui/union/union-borrow-move-parent-sibling.nll.stderr
new file mode 100644
index 0000000..70860c8
--- /dev/null
+++ b/src/test/ui/union/union-borrow-move-parent-sibling.nll.stderr
@@ -0,0 +1,70 @@
+error[E0502]: cannot borrow `u` (via `u.y`) as immutable because it is also borrowed as mutable (via `u.x.0`)
+  --> $DIR/union-borrow-move-parent-sibling.rs:15:13
+   |
+LL |     let a = &mut u.x.0;
+   |             ---------- mutable borrow occurs here (via `u.x.0`)
+LL |     let b = &u.y;
+   |             ^^^^ immutable borrow of `u.y` -- which overlaps with `u.x.0` -- occurs here
+LL |     use_borrow(a);
+   |                - mutable borrow later used here
+   |
+   = note: `u.y` is a field of the union `U`, so it overlaps the field `u.x.0`
+
+error[E0382]: use of moved value: `u`
+  --> $DIR/union-borrow-move-parent-sibling.rs:22:13
+   |
+LL |     let u = U { x: ((Vec::new(), Vec::new()), Vec::new()) };
+   |         - move occurs because `u` has type `U`, which does not implement the `Copy` trait
+LL |     let a = u.x.0;
+   |             ----- value moved here
+LL |     let b = u.y;
+   |             ^^^ value used here after move
+
+error[E0502]: cannot borrow `u` (via `u.y`) as immutable because it is also borrowed as mutable (via `u.x.0.0`)
+  --> $DIR/union-borrow-move-parent-sibling.rs:28:13
+   |
+LL |     let a = &mut (u.x.0).0;
+   |             -------------- mutable borrow occurs here (via `u.x.0.0`)
+LL |     let b = &u.y;
+   |             ^^^^ immutable borrow of `u.y` -- which overlaps with `u.x.0.0` -- occurs here
+LL |     use_borrow(a);
+   |                - mutable borrow later used here
+   |
+   = note: `u.y` is a field of the union `U`, so it overlaps the field `u.x.0.0`
+
+error[E0382]: use of moved value: `u`
+  --> $DIR/union-borrow-move-parent-sibling.rs:35:13
+   |
+LL |     let u = U { x: ((Vec::new(), Vec::new()), Vec::new()) };
+   |         - move occurs because `u` has type `U`, which does not implement the `Copy` trait
+LL |     let a = (u.x.0).0;
+   |             --------- value moved here
+LL |     let b = u.y;
+   |             ^^^ value used here after move
+
+error[E0502]: cannot borrow `u` (via `u.x`) as immutable because it is also borrowed as mutable (via `*u.y`)
+  --> $DIR/union-borrow-move-parent-sibling.rs:41:13
+   |
+LL |     let a = &mut *u.y;
+   |             --------- mutable borrow occurs here (via `*u.y`)
+LL |     let b = &u.x;
+   |             ^^^^ immutable borrow of `u.x` -- which overlaps with `*u.y` -- occurs here
+LL |     use_borrow(a);
+   |                - mutable borrow later used here
+   |
+   = note: `u.x` is a field of the union `U`, so it overlaps the field `*u.y`
+
+error[E0382]: use of moved value: `u`
+  --> $DIR/union-borrow-move-parent-sibling.rs:48:13
+   |
+LL |     let u = U { x: ((Vec::new(), Vec::new()), Vec::new()) };
+   |         - move occurs because `u` has type `U`, which does not implement the `Copy` trait
+LL |     let a = *u.y;
+   |             ---- value moved here
+LL |     let b = u.x;
+   |             ^^^ value used here after move
+
+error: aborting due to 6 previous errors
+
+Some errors occurred: E0382, E0502.
+For more information about an error, try `rustc --explain E0382`.
diff --git a/src/test/ui/union/union-borrow-move-parent-sibling.rs b/src/test/ui/union/union-borrow-move-parent-sibling.rs
new file mode 100644
index 0000000..43abbd3
--- /dev/null
+++ b/src/test/ui/union/union-borrow-move-parent-sibling.rs
@@ -0,0 +1,52 @@
+#![feature(untagged_unions)]
+#![allow(unused)]
+
+#[allow(unions_with_drop_fields)]
+union U {
+    x: ((Vec<u8>, Vec<u8>), Vec<u8>),
+    y: Box<Vec<u8>>,
+}
+
+fn use_borrow<T>(_: &T) {}
+
+unsafe fn parent_sibling_borrow() {
+    let mut u = U { x: ((Vec::new(), Vec::new()), Vec::new()) };
+    let a = &mut u.x.0;
+    let b = &u.y; //~ ERROR cannot borrow `u.y`
+    use_borrow(a);
+}
+
+unsafe fn parent_sibling_move() {
+    let u = U { x: ((Vec::new(), Vec::new()), Vec::new()) };
+    let a = u.x.0;
+    let b = u.y; //~ ERROR use of moved value: `u.y`
+}
+
+unsafe fn grandparent_sibling_borrow() {
+    let mut u = U { x: ((Vec::new(), Vec::new()), Vec::new()) };
+    let a = &mut (u.x.0).0;
+    let b = &u.y; //~ ERROR cannot borrow `u.y`
+    use_borrow(a);
+}
+
+unsafe fn grandparent_sibling_move() {
+    let u = U { x: ((Vec::new(), Vec::new()), Vec::new()) };
+    let a = (u.x.0).0;
+    let b = u.y; //~ ERROR use of moved value: `u.y`
+}
+
+unsafe fn deref_sibling_borrow() {
+    let mut u = U { y: Box::default() };
+    let a = &mut *u.y;
+    let b = &u.x; //~ ERROR cannot borrow `u` (via `u.x`)
+    use_borrow(a);
+}
+
+unsafe fn deref_sibling_move() {
+    let u = U { x: ((Vec::new(), Vec::new()), Vec::new()) };
+    let a = *u.y;
+    let b = u.x; //~ ERROR use of moved value: `u.x`
+}
+
+
+fn main() {}
diff --git a/src/test/ui/union/union-borrow-move-parent-sibling.stderr b/src/test/ui/union/union-borrow-move-parent-sibling.stderr
new file mode 100644
index 0000000..c1c6932
--- /dev/null
+++ b/src/test/ui/union/union-borrow-move-parent-sibling.stderr
@@ -0,0 +1,67 @@
+error[E0502]: cannot borrow `u.y` as immutable because `u.x.0` is also borrowed as mutable
+  --> $DIR/union-borrow-move-parent-sibling.rs:15:14
+   |
+LL |     let a = &mut u.x.0;
+   |                  ----- mutable borrow occurs here
+LL |     let b = &u.y;
+   |              ^^^ immutable borrow occurs here
+LL |     use_borrow(a);
+LL | }
+   | - mutable borrow ends here
+
+error[E0382]: use of moved value: `u.y`
+  --> $DIR/union-borrow-move-parent-sibling.rs:22:9
+   |
+LL |     let a = u.x.0;
+   |         - value moved here
+LL |     let b = u.y;
+   |         ^ value used here after move
+   |
+   = note: move occurs because `u.y` has type `[type error]`, which does not implement the `Copy` trait
+
+error[E0502]: cannot borrow `u.y` as immutable because `u.x.0.0` is also borrowed as mutable
+  --> $DIR/union-borrow-move-parent-sibling.rs:28:14
+   |
+LL |     let a = &mut (u.x.0).0;
+   |                  --------- mutable borrow occurs here
+LL |     let b = &u.y;
+   |              ^^^ immutable borrow occurs here
+LL |     use_borrow(a);
+LL | }
+   | - mutable borrow ends here
+
+error[E0382]: use of moved value: `u.y`
+  --> $DIR/union-borrow-move-parent-sibling.rs:35:9
+   |
+LL |     let a = (u.x.0).0;
+   |         - value moved here
+LL |     let b = u.y;
+   |         ^ value used here after move
+   |
+   = note: move occurs because `u.y` has type `[type error]`, which does not implement the `Copy` trait
+
+error[E0502]: cannot borrow `u` (via `u.x`) as immutable because `u` is also borrowed as mutable (via `*u.y`)
+  --> $DIR/union-borrow-move-parent-sibling.rs:41:14
+   |
+LL |     let a = &mut *u.y;
+   |                  ---- mutable borrow occurs here (via `*u.y`)
+LL |     let b = &u.x;
+   |              ^^^ immutable borrow of `u.x` -- which overlaps with `*u.y` -- occurs here
+LL |     use_borrow(a);
+LL | }
+   | - mutable borrow ends here
+
+error[E0382]: use of moved value: `u.x`
+  --> $DIR/union-borrow-move-parent-sibling.rs:48:9
+   |
+LL |     let a = *u.y;
+   |         - value moved here
+LL |     let b = u.x;
+   |         ^ value used here after move
+   |
+   = note: move occurs because `u.x` has type `[type error]`, which does not implement the `Copy` trait
+
+error: aborting due to 6 previous errors
+
+Some errors occurred: E0382, E0502.
+For more information about an error, try `rustc --explain E0382`.
diff --git a/src/test/ui/union/union-const-eval.rs b/src/test/ui/union/union-const-eval.rs
new file mode 100644
index 0000000..05e849a
--- /dev/null
+++ b/src/test/ui/union/union-const-eval.rs
@@ -0,0 +1,14 @@
+// compile-pass
+#![feature(const_fn_union)]
+
+union U {
+    a: usize,
+    b: usize,
+}
+
+const C: U = U { a: 10 };
+
+fn main() {
+    let a: [u8; unsafe { C.a }];
+    let b: [u8; unsafe { C.b }];
+}
diff --git a/src/test/ui/union/union-const-pat.rs b/src/test/ui/union/union-const-pat.rs
new file mode 100644
index 0000000..e7cb248
--- /dev/null
+++ b/src/test/ui/union/union-const-pat.rs
@@ -0,0 +1,13 @@
+union U {
+    a: usize,
+    b: usize,
+}
+
+const C: U = U { a: 10 };
+
+fn main() {
+    match C {
+        C => {} //~ ERROR cannot use unions in constant patterns
+        _ => {}
+    }
+}
diff --git a/src/test/ui/union/union-const-pat.stderr b/src/test/ui/union/union-const-pat.stderr
new file mode 100644
index 0000000..dc87f4d
--- /dev/null
+++ b/src/test/ui/union/union-const-pat.stderr
@@ -0,0 +1,8 @@
+error: cannot use unions in constant patterns
+  --> $DIR/union-const-pat.rs:10:9
+   |
+LL |         C => {}
+   |         ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/union/union-copy.rs b/src/test/ui/union/union-copy.rs
new file mode 100644
index 0000000..8318f96
--- /dev/null
+++ b/src/test/ui/union/union-copy.rs
@@ -0,0 +1,16 @@
+#![feature(untagged_unions)]
+
+#[derive(Clone)]
+union U {
+    a: u8
+}
+
+#[derive(Clone)]
+union W {
+    a: String
+}
+
+impl Copy for U {} // OK
+impl Copy for W {} //~ ERROR the trait `Copy` may not be implemented for this type
+
+fn main() {}
diff --git a/src/test/ui/union/union-copy.stderr b/src/test/ui/union/union-copy.stderr
new file mode 100644
index 0000000..a875ff6
--- /dev/null
+++ b/src/test/ui/union/union-copy.stderr
@@ -0,0 +1,12 @@
+error[E0204]: the trait `Copy` may not be implemented for this type
+  --> $DIR/union-copy.rs:14:6
+   |
+LL |     a: String
+   |     --------- this field does not implement `Copy`
+...
+LL | impl Copy for W {}
+   |      ^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0204`.
diff --git a/src/test/ui/union/union-derive-clone.rs b/src/test/ui/union/union-derive-clone.rs
new file mode 100644
index 0000000..64c3cae
--- /dev/null
+++ b/src/test/ui/union/union-derive-clone.rs
@@ -0,0 +1,31 @@
+#![feature(untagged_unions)]
+
+#[derive(Clone)] //~ ERROR the trait bound `U1: std::marker::Copy` is not satisfied
+union U1 {
+    a: u8,
+}
+
+#[derive(Clone)]
+union U2 {
+    a: u8, // OK
+}
+
+impl Copy for U2 {}
+
+#[derive(Clone, Copy)]
+union U3 {
+    a: u8, // OK
+}
+
+#[derive(Clone, Copy)]
+union U4<T> {
+    a: T, // OK
+}
+
+#[derive(Clone)]
+struct CloneNoCopy;
+
+fn main() {
+    let u = U4 { a: CloneNoCopy };
+    let w = u.clone(); //~ ERROR no method named `clone` found for type `U4<CloneNoCopy>`
+}
diff --git a/src/test/ui/union/union-derive-clone.stderr b/src/test/ui/union/union-derive-clone.stderr
new file mode 100644
index 0000000..7421bb7
--- /dev/null
+++ b/src/test/ui/union/union-derive-clone.stderr
@@ -0,0 +1,27 @@
+error[E0277]: the trait bound `U1: std::marker::Copy` is not satisfied
+  --> $DIR/union-derive-clone.rs:3:10
+   |
+LL | #[derive(Clone)]
+   |          ^^^^^ the trait `std::marker::Copy` is not implemented for `U1`
+   |
+   = note: required by `std::clone::AssertParamIsCopy`
+
+error[E0599]: no method named `clone` found for type `U4<CloneNoCopy>` in the current scope
+  --> $DIR/union-derive-clone.rs:30:15
+   |
+LL | union U4<T> {
+   | ----------- method `clone` not found for this
+...
+LL |     let w = u.clone();
+   |               ^^^^^
+   |
+   = note: the method `clone` exists but the following trait bounds were not satisfied:
+           `U4<CloneNoCopy> : std::clone::Clone`
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following trait defines an item `clone`, perhaps you need to implement it:
+           candidate #1: `std::clone::Clone`
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0277, E0599.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/union/union-derive-eq.rs b/src/test/ui/union/union-derive-eq.rs
new file mode 100644
index 0000000..698c38f
--- /dev/null
+++ b/src/test/ui/union/union-derive-eq.rs
@@ -0,0 +1,20 @@
+#![feature(untagged_unions)]
+
+#[derive(Eq)] // OK
+union U1 {
+    a: u8,
+}
+
+impl PartialEq for U1 { fn eq(&self, rhs: &Self) -> bool { true } }
+
+#[derive(PartialEq)]
+struct PartialEqNotEq;
+
+#[derive(Eq)]
+union U2 {
+    a: PartialEqNotEq, //~ ERROR the trait bound `PartialEqNotEq: std::cmp::Eq` is not satisfied
+}
+
+impl PartialEq for U2 { fn eq(&self, rhs: &Self) -> bool { true } }
+
+fn main() {}
diff --git a/src/test/ui/union/union-derive-eq.stderr b/src/test/ui/union/union-derive-eq.stderr
new file mode 100644
index 0000000..f63ab17
--- /dev/null
+++ b/src/test/ui/union/union-derive-eq.stderr
@@ -0,0 +1,11 @@
+error[E0277]: the trait bound `PartialEqNotEq: std::cmp::Eq` is not satisfied
+  --> $DIR/union-derive-eq.rs:15:5
+   |
+LL |     a: PartialEqNotEq,
+   |     ^^^^^^^^^^^^^^^^^ the trait `std::cmp::Eq` is not implemented for `PartialEqNotEq`
+   |
+   = note: required by `std::cmp::AssertParamIsEq`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/union/union-derive.rs b/src/test/ui/union/union-derive.rs
new file mode 100644
index 0000000..652a6b2
--- /dev/null
+++ b/src/test/ui/union/union-derive.rs
@@ -0,0 +1,16 @@
+// Most traits cannot be derived for unions.
+
+#[derive(
+    PartialEq, //~ ERROR this trait cannot be derived for unions
+    PartialOrd, //~ ERROR this trait cannot be derived for unions
+    Ord, //~ ERROR this trait cannot be derived for unions
+    Hash, //~ ERROR this trait cannot be derived for unions
+    Default, //~ ERROR this trait cannot be derived for unions
+    Debug, //~ ERROR this trait cannot be derived for unions
+)]
+union U {
+    a: u8,
+    b: u16,
+}
+
+fn main() {}
diff --git a/src/test/ui/union/union-derive.stderr b/src/test/ui/union/union-derive.stderr
new file mode 100644
index 0000000..919c6d5
--- /dev/null
+++ b/src/test/ui/union/union-derive.stderr
@@ -0,0 +1,38 @@
+error: this trait cannot be derived for unions
+  --> $DIR/union-derive.rs:9:5
+   |
+LL |     Debug,
+   |     ^^^^^
+
+error: this trait cannot be derived for unions
+  --> $DIR/union-derive.rs:8:5
+   |
+LL |     Default,
+   |     ^^^^^^^
+
+error: this trait cannot be derived for unions
+  --> $DIR/union-derive.rs:7:5
+   |
+LL |     Hash,
+   |     ^^^^
+
+error: this trait cannot be derived for unions
+  --> $DIR/union-derive.rs:6:5
+   |
+LL |     Ord,
+   |     ^^^
+
+error: this trait cannot be derived for unions
+  --> $DIR/union-derive.rs:5:5
+   |
+LL |     PartialOrd,
+   |     ^^^^^^^^^^
+
+error: this trait cannot be derived for unions
+  --> $DIR/union-derive.rs:4:5
+   |
+LL |     PartialEq,
+   |     ^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/union/union-empty.rs b/src/test/ui/union/union-empty.rs
new file mode 100644
index 0000000..79b7e68
--- /dev/null
+++ b/src/test/ui/union/union-empty.rs
@@ -0,0 +1,3 @@
+union U {} //~ ERROR unions cannot have zero fields
+
+fn main() {}
diff --git a/src/test/ui/union/union-empty.stderr b/src/test/ui/union/union-empty.stderr
new file mode 100644
index 0000000..a80b27e
--- /dev/null
+++ b/src/test/ui/union/union-empty.stderr
@@ -0,0 +1,8 @@
+error: unions cannot have zero fields
+  --> $DIR/union-empty.rs:1:1
+   |
+LL | union U {}
+   | ^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/union/union-fields-1.rs b/src/test/ui/union/union-fields-1.rs
new file mode 100644
index 0000000..6d76e18
--- /dev/null
+++ b/src/test/ui/union/union-fields-1.rs
@@ -0,0 +1,32 @@
+#![deny(dead_code)]
+
+union U1 {
+    a: u8, // should not be reported
+    b: u8, // should not be reported
+    c: u8, //~ ERROR field is never used
+}
+union U2 {
+    a: u8, //~ ERROR field is never used
+    b: u8, // should not be reported
+    c: u8, // should not be reported
+}
+union NoDropLike { a: u8 } //~ ERROR field is never used
+
+union U {
+    a: u8, // should not be reported
+    b: u8, // should not be reported
+    c: u8, //~ ERROR field is never used
+}
+type A = U;
+
+fn main() {
+    let u = U1 { a: 0 };
+    let _a = unsafe { u.b };
+
+    let u = U2 { c: 0 };
+    let _b = unsafe { u.b };
+
+    let _u = NoDropLike { a: 10 };
+    let u = A { a: 0 };
+    let _b = unsafe { u.b };
+}
diff --git a/src/test/ui/union/union-fields-1.stderr b/src/test/ui/union/union-fields-1.stderr
new file mode 100644
index 0000000..f848db7
--- /dev/null
+++ b/src/test/ui/union/union-fields-1.stderr
@@ -0,0 +1,32 @@
+error: field is never used: `c`
+  --> $DIR/union-fields-1.rs:6:5
+   |
+LL |     c: u8,
+   |     ^^^^^
+   |
+note: lint level defined here
+  --> $DIR/union-fields-1.rs:1:9
+   |
+LL | #![deny(dead_code)]
+   |         ^^^^^^^^^
+
+error: field is never used: `a`
+  --> $DIR/union-fields-1.rs:9:5
+   |
+LL |     a: u8,
+   |     ^^^^^
+
+error: field is never used: `a`
+  --> $DIR/union-fields-1.rs:13:20
+   |
+LL | union NoDropLike { a: u8 }
+   |                    ^^^^^
+
+error: field is never used: `c`
+  --> $DIR/union-fields-1.rs:18:5
+   |
+LL |     c: u8,
+   |     ^^^^^
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/union/union-fields-2.rs b/src/test/ui/union/union-fields-2.rs
new file mode 100644
index 0000000..71b204f
--- /dev/null
+++ b/src/test/ui/union/union-fields-2.rs
@@ -0,0 +1,23 @@
+union U {
+    a: u8,
+    b: u16,
+}
+
+fn main() {
+    let u = U {}; //~ ERROR union expressions should have exactly one field
+    let u = U { a: 0 }; // OK
+    let u = U { a: 0, b: 1 }; //~ ERROR union expressions should have exactly one field
+    let u = U { a: 0, b: 1, c: 2 }; //~ ERROR union expressions should have exactly one field
+                                    //~^ ERROR union `U` has no field named `c`
+    let u = U { ..u }; //~ ERROR union expressions should have exactly one field
+                       //~^ ERROR functional record update syntax requires a struct
+
+    let U {} = u; //~ ERROR union patterns should have exactly one field
+    let U { a } = u; // OK
+    let U { a, b } = u; //~ ERROR union patterns should have exactly one field
+    let U { a, b, c } = u; //~ ERROR union patterns should have exactly one field
+                           //~^ ERROR union `U` does not have a field named `c`
+    let U { .. } = u; //~ ERROR union patterns should have exactly one field
+                      //~^ ERROR `..` cannot be used in union patterns
+    let U { a, .. } = u; //~ ERROR `..` cannot be used in union patterns
+}
diff --git a/src/test/ui/union/union-fields-2.stderr b/src/test/ui/union/union-fields-2.stderr
new file mode 100644
index 0000000..b4d6ed9
--- /dev/null
+++ b/src/test/ui/union/union-fields-2.stderr
@@ -0,0 +1,84 @@
+error: union expressions should have exactly one field
+  --> $DIR/union-fields-2.rs:7:13
+   |
+LL |     let u = U {};
+   |             ^
+
+error: union expressions should have exactly one field
+  --> $DIR/union-fields-2.rs:9:13
+   |
+LL |     let u = U { a: 0, b: 1 };
+   |             ^
+
+error[E0560]: union `U` has no field named `c`
+  --> $DIR/union-fields-2.rs:10:29
+   |
+LL |     let u = U { a: 0, b: 1, c: 2 };
+   |                             ^ `U` does not have this field
+   |
+   = note: available fields are: `a`, `b`
+
+error: union expressions should have exactly one field
+  --> $DIR/union-fields-2.rs:10:13
+   |
+LL |     let u = U { a: 0, b: 1, c: 2 };
+   |             ^
+
+error: union expressions should have exactly one field
+  --> $DIR/union-fields-2.rs:12:13
+   |
+LL |     let u = U { ..u };
+   |             ^
+
+error[E0436]: functional record update syntax requires a struct
+  --> $DIR/union-fields-2.rs:12:19
+   |
+LL |     let u = U { ..u };
+   |                   ^
+
+error: union patterns should have exactly one field
+  --> $DIR/union-fields-2.rs:15:9
+   |
+LL |     let U {} = u;
+   |         ^^^^
+
+error: union patterns should have exactly one field
+  --> $DIR/union-fields-2.rs:17:9
+   |
+LL |     let U { a, b } = u;
+   |         ^^^^^^^^^^
+
+error[E0026]: union `U` does not have a field named `c`
+  --> $DIR/union-fields-2.rs:18:19
+   |
+LL |     let U { a, b, c } = u;
+   |                   ^ union `U` does not have this field
+
+error: union patterns should have exactly one field
+  --> $DIR/union-fields-2.rs:18:9
+   |
+LL |     let U { a, b, c } = u;
+   |         ^^^^^^^^^^^^^
+
+error: union patterns should have exactly one field
+  --> $DIR/union-fields-2.rs:20:9
+   |
+LL |     let U { .. } = u;
+   |         ^^^^^^^^
+
+error: `..` cannot be used in union patterns
+  --> $DIR/union-fields-2.rs:20:9
+   |
+LL |     let U { .. } = u;
+   |         ^^^^^^^^
+
+error: `..` cannot be used in union patterns
+  --> $DIR/union-fields-2.rs:22:9
+   |
+LL |     let U { a, .. } = u;
+   |         ^^^^^^^^^^^
+
+error: aborting due to 13 previous errors
+
+Some errors occurred: E0026, E0436, E0560.
+For more information about an error, try `rustc --explain E0026`.
diff --git a/src/test/ui/union/union-generic.rs b/src/test/ui/union/union-generic.rs
new file mode 100644
index 0000000..4b2ccbd
--- /dev/null
+++ b/src/test/ui/union/union-generic.rs
@@ -0,0 +1,12 @@
+use std::rc::Rc;
+
+union U<T: Copy> {
+    a: T
+}
+
+fn main() {
+    let u = U { a: Rc::new(0u32) };
+    //~^ ERROR  the trait bound `std::rc::Rc<u32>: std::marker::Copy` is not satisfied
+    let u = U::<Rc<u32>> { a: Default::default() };
+    //~^ ERROR  the trait bound `std::rc::Rc<u32>: std::marker::Copy` is not satisfied
+}
diff --git a/src/test/ui/union/union-generic.stderr b/src/test/ui/union/union-generic.stderr
new file mode 100644
index 0000000..6a3216d
--- /dev/null
+++ b/src/test/ui/union/union-generic.stderr
@@ -0,0 +1,27 @@
+error[E0277]: the trait bound `std::rc::Rc<u32>: std::marker::Copy` is not satisfied
+  --> $DIR/union-generic.rs:8:13
+   |
+LL |     let u = U { a: Rc::new(0u32) };
+   |             ^ the trait `std::marker::Copy` is not implemented for `std::rc::Rc<u32>`
+   |
+note: required by `U`
+  --> $DIR/union-generic.rs:3:1
+   |
+LL | union U<T: Copy> {
+   | ^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `std::rc::Rc<u32>: std::marker::Copy` is not satisfied
+  --> $DIR/union-generic.rs:10:13
+   |
+LL |     let u = U::<Rc<u32>> { a: Default::default() };
+   |             ^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::rc::Rc<u32>`
+   |
+note: required by `U`
+  --> $DIR/union-generic.rs:3:1
+   |
+LL | union U<T: Copy> {
+   | ^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/union/union-lint-dead-code.rs b/src/test/ui/union/union-lint-dead-code.rs
new file mode 100644
index 0000000..cb6415c
--- /dev/null
+++ b/src/test/ui/union/union-lint-dead-code.rs
@@ -0,0 +1,15 @@
+#![deny(dead_code)]
+
+union Foo {
+    x: usize,
+    b: bool, //~ ERROR: field is never used
+    _unused: u16,
+}
+
+fn field_read(f: Foo) -> usize {
+    unsafe { f.x }
+}
+
+fn main() {
+    let _ = field_read(Foo { x: 2 });
+}
diff --git a/src/test/ui/union/union-lint-dead-code.stderr b/src/test/ui/union/union-lint-dead-code.stderr
new file mode 100644
index 0000000..79c38a4
--- /dev/null
+++ b/src/test/ui/union/union-lint-dead-code.stderr
@@ -0,0 +1,14 @@
+error: field is never used: `b`
+  --> $DIR/union-lint-dead-code.rs:5:5
+   |
+LL |     b: bool,
+   |     ^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/union-lint-dead-code.rs:1:9
+   |
+LL | #![deny(dead_code)]
+   |         ^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/union/union-nonrepresentable.rs b/src/test/ui/union/union-nonrepresentable.rs
new file mode 100644
index 0000000..4dbd97e
--- /dev/null
+++ b/src/test/ui/union/union-nonrepresentable.rs
@@ -0,0 +1,8 @@
+#![feature(untagged_unions)]
+
+union U { //~ ERROR recursive type `U` has infinite size
+    a: u8,
+    b: U,
+}
+
+fn main() {}
diff --git a/src/test/ui/union/union-nonrepresentable.stderr b/src/test/ui/union/union-nonrepresentable.stderr
new file mode 100644
index 0000000..746c103
--- /dev/null
+++ b/src/test/ui/union/union-nonrepresentable.stderr
@@ -0,0 +1,14 @@
+error[E0072]: recursive type `U` has infinite size
+  --> $DIR/union-nonrepresentable.rs:3:1
+   |
+LL | union U {
+   | ^^^^^^^ recursive type has infinite size
+LL |     a: u8,
+LL |     b: U,
+   |     ---- recursive without indirection
+   |
+   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `U` representable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0072`.
diff --git a/src/test/ui/union/union-repr-c.rs b/src/test/ui/union/union-repr-c.rs
new file mode 100644
index 0000000..658452d
--- /dev/null
+++ b/src/test/ui/union/union-repr-c.rs
@@ -0,0 +1,18 @@
+#![allow(unused)]
+#![deny(improper_ctypes)]
+
+#[repr(C)]
+union U {
+    a: u8,
+}
+
+union W {
+    a: u8,
+}
+
+extern "C" {
+    static FOREIGN1: U; // OK
+    static FOREIGN2: W; //~ ERROR union has unspecified layout
+}
+
+fn main() {}
diff --git a/src/test/ui/union/union-repr-c.stderr b/src/test/ui/union/union-repr-c.stderr
new file mode 100644
index 0000000..40d9a50
--- /dev/null
+++ b/src/test/ui/union/union-repr-c.stderr
@@ -0,0 +1,22 @@
+error: `extern` block uses type `W` which is not FFI-safe: this union has unspecified layout
+  --> $DIR/union-repr-c.rs:15:22
+   |
+LL |     static FOREIGN2: W;
+   |                      ^
+   |
+note: lint level defined here
+  --> $DIR/union-repr-c.rs:2:9
+   |
+LL | #![deny(improper_ctypes)]
+   |         ^^^^^^^^^^^^^^^
+   = help: consider adding a #[repr(C)] attribute to this union
+note: type defined here
+  --> $DIR/union-repr-c.rs:9:1
+   |
+LL | / union W {
+LL | |     a: u8,
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/union/union-sized-field.rs b/src/test/ui/union/union-sized-field.rs
new file mode 100644
index 0000000..b84cb3e
--- /dev/null
+++ b/src/test/ui/union/union-sized-field.rs
@@ -0,0 +1,19 @@
+#![feature(untagged_unions)]
+
+union Foo<T: ?Sized> {
+    value: T,
+    //~^ ERROR the size for values of type
+}
+
+struct Foo2<T: ?Sized> {
+    value: T,
+    //~^ ERROR the size for values of type
+    t: u32,
+}
+
+enum Foo3<T: ?Sized> {
+    Value(T),
+    //~^ ERROR the size for values of type
+}
+
+fn main() {}
diff --git a/src/test/ui/union/union-sized-field.stderr b/src/test/ui/union/union-sized-field.stderr
new file mode 100644
index 0000000..8914003
--- /dev/null
+++ b/src/test/ui/union/union-sized-field.stderr
@@ -0,0 +1,36 @@
+error[E0277]: the size for values of type `T` cannot be known at compilation time
+  --> $DIR/union-sized-field.rs:4:5
+   |
+LL |     value: T,
+   |     ^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `T`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = help: consider adding a `where T: std::marker::Sized` bound
+   = note: no field of a union may have a dynamically sized type
+
+error[E0277]: the size for values of type `T` cannot be known at compilation time
+  --> $DIR/union-sized-field.rs:9:5
+   |
+LL |     value: T,
+   |     ^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `T`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = help: consider adding a `where T: std::marker::Sized` bound
+   = note: only the last field of a struct may have a dynamically sized type
+
+error[E0277]: the size for values of type `T` cannot be known at compilation time
+  --> $DIR/union-sized-field.rs:15:11
+   |
+LL |     Value(T),
+   |           ^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `T`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = help: consider adding a `where T: std::marker::Sized` bound
+   = note: no field of an enum variant may have a dynamically sized type
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/union/union-suggest-field.rs b/src/test/ui/union/union-suggest-field.rs
new file mode 100644
index 0000000..d84a22c
--- /dev/null
+++ b/src/test/ui/union/union-suggest-field.rs
@@ -0,0 +1,21 @@
+union U {
+    principal: u8,
+}
+
+impl U {
+    fn calculate(&self) {}
+}
+
+fn main() {
+    let u = U { principle: 0 };
+    //~^ ERROR union `U` has no field named `principle`
+    //~| HELP a field with a similar name exists
+    //~| SUGGESTION principal
+    let w = u.principial; //~ ERROR no field `principial` on type `U`
+                          //~| HELP a field with a similar name exists
+                          //~| SUGGESTION principal
+
+    let y = u.calculate; //~ ERROR attempted to take value of method `calculate` on type `U`
+                         //~| HELP use parentheses to call the method
+                         //~| SUGGESTION calculate()
+}
diff --git a/src/test/ui/union/union-suggest-field.stderr b/src/test/ui/union/union-suggest-field.stderr
new file mode 100644
index 0000000..c737bc2
--- /dev/null
+++ b/src/test/ui/union/union-suggest-field.stderr
@@ -0,0 +1,22 @@
+error[E0560]: union `U` has no field named `principle`
+  --> $DIR/union-suggest-field.rs:10:17
+   |
+LL |     let u = U { principle: 0 };
+   |                 ^^^^^^^^^ help: a field with a similar name exists: `principal`
+
+error[E0609]: no field `principial` on type `U`
+  --> $DIR/union-suggest-field.rs:14:15
+   |
+LL |     let w = u.principial;
+   |               ^^^^^^^^^^ help: a field with a similar name exists: `principal`
+
+error[E0615]: attempted to take value of method `calculate` on type `U`
+  --> $DIR/union-suggest-field.rs:18:15
+   |
+LL |     let y = u.calculate;
+   |               ^^^^^^^^^ help: use parentheses to call the method: `calculate()`
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0560, E0609, E0615.
+For more information about an error, try `rustc --explain E0560`.
diff --git a/src/test/ui/union/union-unsafe.rs b/src/test/ui/union/union-unsafe.rs
new file mode 100644
index 0000000..6cfde35
--- /dev/null
+++ b/src/test/ui/union/union-unsafe.rs
@@ -0,0 +1,45 @@
+#![feature(untagged_unions)]
+
+union U1 {
+    a: u8
+}
+
+union U2 {
+    a: String
+}
+
+union U3<T> {
+    a: T
+}
+
+union U4<T: Copy> {
+    a: T
+}
+
+fn generic_noncopy<T: Default>() {
+    let mut u3 = U3 { a: T::default() };
+    u3.a = T::default(); //~ ERROR assignment to non-`Copy` union field is unsafe
+}
+
+fn generic_copy<T: Copy + Default>() {
+    let mut u3 = U3 { a: T::default() };
+    u3.a = T::default(); // OK
+    let mut u4 = U4 { a: T::default() };
+    u4.a = T::default(); // OK
+}
+
+fn main() {
+    let mut u1 = U1 { a: 10 }; // OK
+    let a = u1.a; //~ ERROR access to union field is unsafe
+    u1.a = 11; // OK
+    let U1 { a } = u1; //~ ERROR access to union field is unsafe
+    if let U1 { a: 12 } = u1 {} //~ ERROR access to union field is unsafe
+    // let U1 { .. } = u1; // OK
+
+    let mut u2 = U2 { a: String::from("old") }; // OK
+    u2.a = String::from("new"); //~ ERROR assignment to non-`Copy` union field is unsafe
+    let mut u3 = U3 { a: 0 }; // OK
+    u3.a = 1; // OK
+    let mut u3 = U3 { a: String::from("old") }; // OK
+    u3.a = String::from("new"); //~ ERROR assignment to non-`Copy` union field is unsafe
+}
diff --git a/src/test/ui/union/union-unsafe.stderr b/src/test/ui/union/union-unsafe.stderr
new file mode 100644
index 0000000..ab62508f
--- /dev/null
+++ b/src/test/ui/union/union-unsafe.stderr
@@ -0,0 +1,51 @@
+error[E0133]: assignment to non-`Copy` union field is unsafe and requires unsafe function or block
+  --> $DIR/union-unsafe.rs:21:5
+   |
+LL |     u3.a = T::default();
+   |     ^^^^ assignment to non-`Copy` union field
+   |
+   = note: the previous content of the field will be dropped, which causes undefined behavior if the field was not properly initialized
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/union-unsafe.rs:33:13
+   |
+LL |     let a = u1.a;
+   |             ^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/union-unsafe.rs:35:14
+   |
+LL |     let U1 { a } = u1;
+   |              ^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/union-unsafe.rs:36:20
+   |
+LL |     if let U1 { a: 12 } = u1 {}
+   |                    ^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: assignment to non-`Copy` union field is unsafe and requires unsafe function or block
+  --> $DIR/union-unsafe.rs:40:5
+   |
+LL |     u2.a = String::from("new");
+   |     ^^^^ assignment to non-`Copy` union field
+   |
+   = note: the previous content of the field will be dropped, which causes undefined behavior if the field was not properly initialized
+
+error[E0133]: assignment to non-`Copy` union field is unsafe and requires unsafe function or block
+  --> $DIR/union-unsafe.rs:44:5
+   |
+LL |     u3.a = String::from("new");
+   |     ^^^^ assignment to non-`Copy` union field
+   |
+   = note: the previous content of the field will be dropped, which causes undefined behavior if the field was not properly initialized
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/union/union-unsized.rs b/src/test/ui/union/union-unsized.rs
new file mode 100644
index 0000000..16f2a73
--- /dev/null
+++ b/src/test/ui/union/union-unsized.rs
@@ -0,0 +1,16 @@
+#![feature(untagged_unions)]
+
+union U {
+    a: str,
+    //~^ ERROR the size for values of type
+
+    b: u8,
+}
+
+union W {
+    a: u8,
+    b: str,
+    //~^ ERROR the size for values of type
+}
+
+fn main() {}
diff --git a/src/test/ui/union/union-unsized.stderr b/src/test/ui/union/union-unsized.stderr
new file mode 100644
index 0000000..e702f2c
--- /dev/null
+++ b/src/test/ui/union/union-unsized.stderr
@@ -0,0 +1,23 @@
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+  --> $DIR/union-unsized.rs:4:5
+   |
+LL |     a: str,
+   |     ^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `str`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: no field of a union may have a dynamically sized type
+
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+  --> $DIR/union-unsized.rs:12:5
+   |
+LL |     b: str,
+   |     ^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `str`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: no field of a union may have a dynamically sized type
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/union/union-with-drop-fields-lint.rs b/src/test/ui/union/union-with-drop-fields-lint.rs
new file mode 100644
index 0000000..8e502aa
--- /dev/null
+++ b/src/test/ui/union/union-with-drop-fields-lint.rs
@@ -0,0 +1,30 @@
+#![feature(untagged_unions)]
+#![allow(dead_code)]
+#![deny(unions_with_drop_fields)]
+
+union U {
+    a: u8, // OK
+}
+
+union W {
+    a: String, //~ ERROR union contains a field with possibly non-trivial drop code
+    b: String, // OK, only one field is reported
+}
+
+struct S(String);
+
+// `S` doesn't implement `Drop` trait, but still has non-trivial destructor
+union Y {
+    a: S, //~ ERROR union contains a field with possibly non-trivial drop code
+}
+
+// We don't know if `T` is trivially-destructable or not until trans
+union J<T> {
+    a: T, //~ ERROR union contains a field with possibly non-trivial drop code
+}
+
+union H<T: Copy> {
+    a: T, // OK, `T` is `Copy`, no destructor
+}
+
+fn main() {}
diff --git a/src/test/ui/union/union-with-drop-fields-lint.stderr b/src/test/ui/union/union-with-drop-fields-lint.stderr
new file mode 100644
index 0000000..2f90f24
--- /dev/null
+++ b/src/test/ui/union/union-with-drop-fields-lint.stderr
@@ -0,0 +1,26 @@
+error: union contains a field with possibly non-trivial drop code, drop code of union fields is ignored when dropping the union
+  --> $DIR/union-with-drop-fields-lint.rs:10:5
+   |
+LL |     a: String,
+   |     ^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/union-with-drop-fields-lint.rs:3:9
+   |
+LL | #![deny(unions_with_drop_fields)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: union contains a field with possibly non-trivial drop code, drop code of union fields is ignored when dropping the union
+  --> $DIR/union-with-drop-fields-lint.rs:18:5
+   |
+LL |     a: S,
+   |     ^^^^
+
+error: union contains a field with possibly non-trivial drop code, drop code of union fields is ignored when dropping the union
+  --> $DIR/union-with-drop-fields-lint.rs:23:5
+   |
+LL |     a: T,
+   |     ^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/unique-object-noncopyable.rs b/src/test/ui/unique-object-noncopyable.rs
new file mode 100644
index 0000000..1c467a2
--- /dev/null
+++ b/src/test/ui/unique-object-noncopyable.rs
@@ -0,0 +1,25 @@
+#![feature(box_syntax)]
+
+trait Foo {
+    fn f(&self);
+}
+
+struct Bar {
+    x: isize,
+}
+
+impl Drop for Bar {
+    fn drop(&mut self) {}
+}
+
+impl Foo for Bar {
+    fn f(&self) {
+        println!("hi");
+    }
+}
+
+fn main() {
+    let x = box Bar { x: 10 };
+    let y: Box<Foo> = x as Box<Foo>;
+    let _z = y.clone(); //~ ERROR no method named `clone` found
+}
diff --git a/src/test/ui/unique-object-noncopyable.stderr b/src/test/ui/unique-object-noncopyable.stderr
new file mode 100644
index 0000000..407905f
--- /dev/null
+++ b/src/test/ui/unique-object-noncopyable.stderr
@@ -0,0 +1,15 @@
+error[E0599]: no method named `clone` found for type `std::boxed::Box<dyn Foo>` in the current scope
+  --> $DIR/unique-object-noncopyable.rs:24:16
+   |
+LL |     let _z = y.clone();
+   |                ^^^^^
+   |
+   = note: the method `clone` exists but the following trait bounds were not satisfied:
+           `std::boxed::Box<dyn Foo> : std::clone::Clone`
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following trait defines an item `clone`, perhaps you need to implement it:
+           candidate #1: `std::clone::Clone`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/unique-pinned-nocopy.rs b/src/test/ui/unique-pinned-nocopy.rs
new file mode 100644
index 0000000..4c30450
--- /dev/null
+++ b/src/test/ui/unique-pinned-nocopy.rs
@@ -0,0 +1,14 @@
+#[derive(Debug)]
+struct R {
+  b: bool,
+}
+
+impl Drop for R {
+    fn drop(&mut self) {}
+}
+
+fn main() {
+    let i = Box::new(R { b: true });
+    let _j = i.clone(); //~ ERROR no method named `clone` found
+    println!("{:?}", i);
+}
diff --git a/src/test/ui/unique-pinned-nocopy.stderr b/src/test/ui/unique-pinned-nocopy.stderr
new file mode 100644
index 0000000..0f6ba90
--- /dev/null
+++ b/src/test/ui/unique-pinned-nocopy.stderr
@@ -0,0 +1,15 @@
+error[E0599]: no method named `clone` found for type `std::boxed::Box<R>` in the current scope
+  --> $DIR/unique-pinned-nocopy.rs:12:16
+   |
+LL |     let _j = i.clone();
+   |                ^^^^^
+   |
+   = note: the method `clone` exists but the following trait bounds were not satisfied:
+           `std::boxed::Box<R> : std::clone::Clone`
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following trait defines an item `clone`, perhaps you need to implement it:
+           candidate #1: `std::clone::Clone`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/unknown-language-item.rs b/src/test/ui/unknown-language-item.rs
new file mode 100644
index 0000000..20ffef7
--- /dev/null
+++ b/src/test/ui/unknown-language-item.rs
@@ -0,0 +1,10 @@
+#![allow(unused)]
+#![feature(lang_items)]
+
+#[lang = "foo"]
+fn bar() -> ! {
+//~^^ ERROR definition of an unknown language item: `foo`
+    loop {}
+}
+
+fn main() {}
diff --git a/src/test/ui/unknown-language-item.stderr b/src/test/ui/unknown-language-item.stderr
new file mode 100644
index 0000000..c5fe9b8
--- /dev/null
+++ b/src/test/ui/unknown-language-item.stderr
@@ -0,0 +1,9 @@
+error[E0522]: definition of an unknown language item: `foo`
+  --> $DIR/unknown-language-item.rs:4:1
+   |
+LL | #[lang = "foo"]
+   | ^^^^^^^^^^^^^^^ definition of unknown language item `foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0522`.
diff --git a/src/test/ui/unknown-lint-tool-name.rs b/src/test/ui/unknown-lint-tool-name.rs
new file mode 100644
index 0000000..c92a71e
--- /dev/null
+++ b/src/test/ui/unknown-lint-tool-name.rs
@@ -0,0 +1,4 @@
+#![deny(foo::bar)] //~ ERROR an unknown tool name found in scoped lint: `foo::bar`
+
+#[allow(foo::bar)] //~ ERROR an unknown tool name found in scoped lint: `foo::bar`
+fn main() {}
diff --git a/src/test/ui/unknown-lint-tool-name.stderr b/src/test/ui/unknown-lint-tool-name.stderr
new file mode 100644
index 0000000..a127af6
--- /dev/null
+++ b/src/test/ui/unknown-lint-tool-name.stderr
@@ -0,0 +1,15 @@
+error[E0710]: an unknown tool name found in scoped lint: `foo::bar`
+  --> $DIR/unknown-lint-tool-name.rs:1:9
+   |
+LL | #![deny(foo::bar)]
+   |         ^^^
+
+error[E0710]: an unknown tool name found in scoped lint: `foo::bar`
+  --> $DIR/unknown-lint-tool-name.rs:3:9
+   |
+LL | #[allow(foo::bar)]
+   |         ^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0710`.
diff --git a/src/test/ui/unknown-tool-name.rs b/src/test/ui/unknown-tool-name.rs
new file mode 100644
index 0000000..05f99ce
--- /dev/null
+++ b/src/test/ui/unknown-tool-name.rs
@@ -0,0 +1,2 @@
+#[foo::bar] //~ ERROR failed to resolve: use of undeclared type or module `foo`
+fn main() {}
diff --git a/src/test/ui/unknown-tool-name.stderr b/src/test/ui/unknown-tool-name.stderr
new file mode 100644
index 0000000..7a6ed57
--- /dev/null
+++ b/src/test/ui/unknown-tool-name.stderr
@@ -0,0 +1,9 @@
+error[E0433]: failed to resolve: use of undeclared type or module `foo`
+  --> $DIR/unknown-tool-name.rs:1:3
+   |
+LL | #[foo::bar]
+   |   ^^^ use of undeclared type or module `foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/unnecessary-extern-crate.rs b/src/test/ui/unnecessary-extern-crate.rs
new file mode 100644
index 0000000..e25b99b
--- /dev/null
+++ b/src/test/ui/unnecessary-extern-crate.rs
@@ -0,0 +1,71 @@
+// edition:2018
+
+#![deny(unused_extern_crates)]
+#![feature(alloc, test, rustc_private, crate_visibility_modifier)]
+
+extern crate libc;
+//~^ ERROR unused extern crate
+//~| HELP remove
+extern crate libc as x;
+//~^ ERROR unused extern crate
+//~| HELP remove
+
+extern crate proc_macro;
+
+#[macro_use]
+extern crate test;
+
+pub extern crate test as y;
+
+pub extern crate alloc;
+
+pub(crate) extern crate alloc as a;
+
+crate extern crate alloc as b;
+
+mod foo {
+    pub(in crate::foo) extern crate alloc as c;
+
+    pub(super) extern crate alloc as d;
+
+    extern crate libc;
+    //~^ ERROR unused extern crate
+    //~| HELP remove
+
+    extern crate libc as x;
+    //~^ ERROR unused extern crate
+    //~| HELP remove
+
+    pub extern crate test;
+
+    pub extern crate test as y;
+
+    mod bar {
+        extern crate libc;
+        //~^ ERROR unused extern crate
+        //~| HELP remove
+
+        extern crate libc as x;
+        //~^ ERROR unused extern crate
+        //~| HELP remove
+
+        pub(in crate::foo::bar) extern crate alloc as e;
+
+        fn dummy() {
+            e::string::String::new();
+        }
+    }
+
+    fn dummy() {
+        c::string::String::new();
+        d::string::String::new();
+    }
+}
+
+
+fn main() {
+    a::string::String::new();
+    b::string::String::new();
+
+    proc_macro::TokenStream::new();
+}
diff --git a/src/test/ui/unnecessary-extern-crate.stderr b/src/test/ui/unnecessary-extern-crate.stderr
new file mode 100644
index 0000000..1e6d7552
--- /dev/null
+++ b/src/test/ui/unnecessary-extern-crate.stderr
@@ -0,0 +1,44 @@
+error: unused extern crate
+  --> $DIR/unnecessary-extern-crate.rs:6:1
+   |
+LL | extern crate libc;
+   | ^^^^^^^^^^^^^^^^^^ help: remove it
+   |
+note: lint level defined here
+  --> $DIR/unnecessary-extern-crate.rs:3:9
+   |
+LL | #![deny(unused_extern_crates)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: unused extern crate
+  --> $DIR/unnecessary-extern-crate.rs:9:1
+   |
+LL | extern crate libc as x;
+   | ^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
+
+error: unused extern crate
+  --> $DIR/unnecessary-extern-crate.rs:31:5
+   |
+LL |     extern crate libc;
+   |     ^^^^^^^^^^^^^^^^^^ help: remove it
+
+error: unused extern crate
+  --> $DIR/unnecessary-extern-crate.rs:35:5
+   |
+LL |     extern crate libc as x;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
+
+error: unused extern crate
+  --> $DIR/unnecessary-extern-crate.rs:44:9
+   |
+LL |         extern crate libc;
+   |         ^^^^^^^^^^^^^^^^^^ help: remove it
+
+error: unused extern crate
+  --> $DIR/unnecessary-extern-crate.rs:48:9
+   |
+LL |         extern crate libc as x;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/unop-move-semantics.nll.stderr b/src/test/ui/unop-move-semantics.nll.stderr
new file mode 100644
index 0000000..c11445c
--- /dev/null
+++ b/src/test/ui/unop-move-semantics.nll.stderr
@@ -0,0 +1,52 @@
+error[E0382]: borrow of moved value: `x`
+  --> $DIR/unop-move-semantics.rs:8:5
+   |
+LL | fn move_then_borrow<T: Not<Output=T> + Clone>(x: T) {
+   |                     -                         - move occurs because `x` has type `T`, which does not implement the `Copy` trait
+   |                     |
+   |                     consider adding a `Copy` constraint to this type argument
+LL |     !x;
+   |      - value moved here
+LL | 
+LL |     x.clone();
+   |     ^ value borrowed here after move
+
+error[E0505]: cannot move out of `x` because it is borrowed
+  --> $DIR/unop-move-semantics.rs:15:6
+   |
+LL |     let m = &x;
+   |             -- borrow of `x` occurs here
+...
+LL |     !x;
+   |      ^ move out of `x` occurs here
+...
+LL |     use_mut(n); use_imm(m);
+   |                         - borrow later used here
+
+error[E0505]: cannot move out of `y` because it is borrowed
+  --> $DIR/unop-move-semantics.rs:17:6
+   |
+LL |     let n = &mut y;
+   |             ------ borrow of `y` occurs here
+...
+LL |     !y;
+   |      ^ move out of `y` occurs here
+LL |     use_mut(n); use_imm(m);
+   |             - borrow later used here
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/unop-move-semantics.rs:24:6
+   |
+LL |     !*m;
+   |      ^^ cannot move out of borrowed content
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/unop-move-semantics.rs:26:6
+   |
+LL |     !*n;
+   |      ^^ cannot move out of borrowed content
+
+error: aborting due to 5 previous errors
+
+Some errors occurred: E0382, E0505, E0507.
+For more information about an error, try `rustc --explain E0382`.
diff --git a/src/test/ui/unop-move-semantics.rs b/src/test/ui/unop-move-semantics.rs
new file mode 100644
index 0000000..24bd89d
--- /dev/null
+++ b/src/test/ui/unop-move-semantics.rs
@@ -0,0 +1,32 @@
+// Test that move restrictions are enforced on overloaded unary operations
+
+use std::ops::Not;
+
+fn move_then_borrow<T: Not<Output=T> + Clone>(x: T) {
+    !x;
+
+    x.clone();  //~ ERROR: use of moved value
+}
+
+fn move_borrowed<T: Not<Output=T>>(x: T, mut y: T) {
+    let m = &x;
+    let n = &mut y;
+
+    !x;  //~ ERROR: cannot move out of `x` because it is borrowed
+
+    !y;  //~ ERROR: cannot move out of `y` because it is borrowed
+    use_mut(n); use_imm(m);
+}
+fn illegal_dereference<T: Not<Output=T>>(mut x: T, y: T) {
+    let m = &mut x;
+    let n = &y;
+
+    !*m;  //~ ERROR: cannot move out of borrowed content
+
+    !*n;  //~ ERROR: cannot move out of borrowed content
+    use_imm(n); use_mut(m);
+}
+fn main() {}
+
+fn use_mut<T>(_: &mut T) { }
+fn use_imm<T>(_: &T) { }
diff --git a/src/test/ui/unop-move-semantics.stderr b/src/test/ui/unop-move-semantics.stderr
new file mode 100644
index 0000000..e2fb425
--- /dev/null
+++ b/src/test/ui/unop-move-semantics.stderr
@@ -0,0 +1,45 @@
+error[E0382]: use of moved value: `x`
+  --> $DIR/unop-move-semantics.rs:8:5
+   |
+LL |     !x;
+   |      - value moved here
+LL | 
+LL |     x.clone();
+   |     ^ value used here after move
+   |
+   = note: move occurs because `x` has type `T`, which does not implement the `Copy` trait
+
+error[E0505]: cannot move out of `x` because it is borrowed
+  --> $DIR/unop-move-semantics.rs:15:6
+   |
+LL |     let m = &x;
+   |              - borrow of `x` occurs here
+...
+LL |     !x;
+   |      ^ move out of `x` occurs here
+
+error[E0505]: cannot move out of `y` because it is borrowed
+  --> $DIR/unop-move-semantics.rs:17:6
+   |
+LL |     let n = &mut y;
+   |                  - borrow of `y` occurs here
+...
+LL |     !y;
+   |      ^ move out of `y` occurs here
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/unop-move-semantics.rs:24:6
+   |
+LL |     !*m;
+   |      ^^ cannot move out of borrowed content
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/unop-move-semantics.rs:26:6
+   |
+LL |     !*n;
+   |      ^^ cannot move out of borrowed content
+
+error: aborting due to 5 previous errors
+
+Some errors occurred: E0382, E0505, E0507.
+For more information about an error, try `rustc --explain E0382`.
diff --git a/src/test/ui/unop-neg-bool.rs b/src/test/ui/unop-neg-bool.rs
new file mode 100644
index 0000000..6f1f1ab
--- /dev/null
+++ b/src/test/ui/unop-neg-bool.rs
@@ -0,0 +1,3 @@
+fn main() {
+    -true; //~ ERROR cannot apply unary operator `-` to type `bool`
+}
diff --git a/src/test/ui/unop-neg-bool.stderr b/src/test/ui/unop-neg-bool.stderr
new file mode 100644
index 0000000..1827301
--- /dev/null
+++ b/src/test/ui/unop-neg-bool.stderr
@@ -0,0 +1,11 @@
+error[E0600]: cannot apply unary operator `-` to type `bool`
+  --> $DIR/unop-neg-bool.rs:2:5
+   |
+LL |     -true;
+   |     ^^^^^ cannot apply unary operator `-`
+   |
+   = note: an implementation of `std::ops::Neg` might be missing for `bool`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0600`.
diff --git a/src/test/ui/unreachable/auxiliary/unreachable_variant.rs b/src/test/ui/unreachable/auxiliary/unreachable_variant.rs
new file mode 100644
index 0000000..4e94a4b
--- /dev/null
+++ b/src/test/ui/unreachable/auxiliary/unreachable_variant.rs
@@ -0,0 +1,5 @@
+mod super_sekrit {
+    pub enum sooper_sekrit {
+        quux, baz
+    }
+}
diff --git a/src/test/ui/unreachable/unreachable-arm.rs b/src/test/ui/unreachable/unreachable-arm.rs
new file mode 100644
index 0000000..9f1a5a3
--- /dev/null
+++ b/src/test/ui/unreachable/unreachable-arm.rs
@@ -0,0 +1,15 @@
+#![feature(box_patterns)]
+#![feature(box_syntax)]
+#![allow(dead_code)]
+#![deny(unreachable_patterns)]
+
+enum Foo { A(Box<Foo>, isize), B(usize), }
+
+fn main() {
+    match Foo::B(1) {
+        Foo::B(_) | Foo::A(box _, 1) => { }
+        Foo::A(_, 1) => { } //~ ERROR unreachable pattern
+        _ => { }
+    }
+}
+
diff --git a/src/test/ui/unreachable/unreachable-arm.stderr b/src/test/ui/unreachable/unreachable-arm.stderr
new file mode 100644
index 0000000..8e65745
--- /dev/null
+++ b/src/test/ui/unreachable/unreachable-arm.stderr
@@ -0,0 +1,14 @@
+error: unreachable pattern
+  --> $DIR/unreachable-arm.rs:11:9
+   |
+LL |         Foo::A(_, 1) => { }
+   |         ^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/unreachable-arm.rs:4:9
+   |
+LL | #![deny(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/unreachable/unreachable-code.rs b/src/test/ui/unreachable/unreachable-code.rs
new file mode 100644
index 0000000..ad0dc8a
--- /dev/null
+++ b/src/test/ui/unreachable/unreachable-code.rs
@@ -0,0 +1,8 @@
+#![deny(unreachable_code)]
+#![allow(unused_variables)]
+
+fn main() {
+  loop{}
+
+  let a = 3; //~ ERROR: unreachable statement
+}
diff --git a/src/test/ui/unreachable/unreachable-code.stderr b/src/test/ui/unreachable/unreachable-code.stderr
new file mode 100644
index 0000000..803bb96
--- /dev/null
+++ b/src/test/ui/unreachable/unreachable-code.stderr
@@ -0,0 +1,14 @@
+error: unreachable statement
+  --> $DIR/unreachable-code.rs:7:3
+   |
+LL |   let a = 3;
+   |   ^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/unreachable-code.rs:1:9
+   |
+LL | #![deny(unreachable_code)]
+   |         ^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/unreachable/unreachable-in-call.rs b/src/test/ui/unreachable/unreachable-in-call.rs
new file mode 100644
index 0000000..25f849d
--- /dev/null
+++ b/src/test/ui/unreachable/unreachable-in-call.rs
@@ -0,0 +1,22 @@
+#![allow(dead_code)]
+#![deny(unreachable_code)]
+
+fn diverge() -> ! { panic!() }
+
+fn get_u8() -> u8 {
+    1
+}
+fn call(_: u8, _: u8) {
+
+}
+fn diverge_first() {
+    call(diverge(),
+         get_u8()); //~ ERROR unreachable expression
+}
+fn diverge_second() {
+    call( //~ ERROR unreachable expression
+        get_u8(),
+        diverge());
+}
+
+fn main() {}
diff --git a/src/test/ui/unreachable/unreachable-in-call.stderr b/src/test/ui/unreachable/unreachable-in-call.stderr
new file mode 100644
index 0000000..f8dd545
--- /dev/null
+++ b/src/test/ui/unreachable/unreachable-in-call.stderr
@@ -0,0 +1,22 @@
+error: unreachable expression
+  --> $DIR/unreachable-in-call.rs:14:10
+   |
+LL |          get_u8());
+   |          ^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/unreachable-in-call.rs:2:9
+   |
+LL | #![deny(unreachable_code)]
+   |         ^^^^^^^^^^^^^^^^
+
+error: unreachable expression
+  --> $DIR/unreachable-in-call.rs:17:5
+   |
+LL | /     call(
+LL | |         get_u8(),
+LL | |         diverge());
+   | |__________________^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/unreachable/unreachable-loop-patterns.rs b/src/test/ui/unreachable/unreachable-loop-patterns.rs
new file mode 100644
index 0000000..9794806
--- /dev/null
+++ b/src/test/ui/unreachable/unreachable-loop-patterns.rs
@@ -0,0 +1,23 @@
+// compile-fail
+
+#![feature(never_type)]
+#![feature(exhaustive_patterns)]
+
+#![allow(unreachable_code)]
+#![deny(unreachable_patterns)]
+
+enum Void {}
+
+impl Iterator for Void {
+    type Item = Void;
+
+    fn next(&mut self) -> Option<Void> {
+        None
+    }
+}
+
+fn main() {
+    for _ in unimplemented!() as Void {}
+    //~^ ERROR unreachable pattern
+}
+
diff --git a/src/test/ui/unreachable/unreachable-loop-patterns.stderr b/src/test/ui/unreachable/unreachable-loop-patterns.stderr
new file mode 100644
index 0000000..d2f255c
--- /dev/null
+++ b/src/test/ui/unreachable/unreachable-loop-patterns.stderr
@@ -0,0 +1,14 @@
+error: unreachable pattern
+  --> $DIR/unreachable-loop-patterns.rs:20:9
+   |
+LL |     for _ in unimplemented!() as Void {}
+   |         ^
+   |
+note: lint level defined here
+  --> $DIR/unreachable-loop-patterns.rs:7:9
+   |
+LL | #![deny(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/unreachable/unreachable-try-pattern.rs b/src/test/ui/unreachable/unreachable-try-pattern.rs
new file mode 100644
index 0000000..1c1e01f
--- /dev/null
+++ b/src/test/ui/unreachable/unreachable-try-pattern.rs
@@ -0,0 +1,42 @@
+// compile-pass
+#![feature(never_type, exhaustive_patterns)]
+#![warn(unreachable_code)]
+#![warn(unreachable_patterns)]
+
+enum Void {}
+
+impl From<Void> for i32 {
+    fn from(v: Void) -> i32 {
+        match v {}
+    }
+}
+
+fn bar(x: Result<!, i32>) -> Result<u32, i32> {
+    x?
+}
+
+fn foo(x: Result<!, i32>) -> Result<u32, i32> {
+    let y = (match x { Ok(n) => Ok(n as u32), Err(e) => Err(e) })?;
+    //~^ WARN unreachable pattern
+    //~| WARN unreachable expression
+    Ok(y)
+}
+
+fn qux(x: Result<u32, Void>) -> Result<u32, i32> {
+    Ok(x?)
+}
+
+fn vom(x: Result<u32, Void>) -> Result<u32, i32> {
+    let y = (match x { Ok(n) => Ok(n), Err(e) => Err(e) })?;
+    //~^ WARN unreachable pattern
+    Ok(y)
+}
+
+
+fn main() {
+    let _ = bar(Err(123));
+    let _ = foo(Err(123));
+    let _ = qux(Ok(123));
+    let _ = vom(Ok(123));
+}
+
diff --git a/src/test/ui/unreachable/unreachable-try-pattern.stderr b/src/test/ui/unreachable/unreachable-try-pattern.stderr
new file mode 100644
index 0000000..758aa5a
--- /dev/null
+++ b/src/test/ui/unreachable/unreachable-try-pattern.stderr
@@ -0,0 +1,30 @@
+warning: unreachable expression
+  --> $DIR/unreachable-try-pattern.rs:19:36
+   |
+LL |     let y = (match x { Ok(n) => Ok(n as u32), Err(e) => Err(e) })?;
+   |                                    ^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/unreachable-try-pattern.rs:3:9
+   |
+LL | #![warn(unreachable_code)]
+   |         ^^^^^^^^^^^^^^^^
+
+warning: unreachable pattern
+  --> $DIR/unreachable-try-pattern.rs:19:24
+   |
+LL |     let y = (match x { Ok(n) => Ok(n as u32), Err(e) => Err(e) })?;
+   |                        ^^^^^
+   |
+note: lint level defined here
+  --> $DIR/unreachable-try-pattern.rs:4:9
+   |
+LL | #![warn(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+warning: unreachable pattern
+  --> $DIR/unreachable-try-pattern.rs:30:40
+   |
+LL |     let y = (match x { Ok(n) => Ok(n), Err(e) => Err(e) })?;
+   |                                        ^^^^^^
+
diff --git a/src/test/ui/unreachable/unreachable-variant.rs b/src/test/ui/unreachable/unreachable-variant.rs
new file mode 100644
index 0000000..008c2d4
--- /dev/null
+++ b/src/test/ui/unreachable/unreachable-variant.rs
@@ -0,0 +1,7 @@
+// aux-build:unreachable_variant.rs
+
+extern crate unreachable_variant as other;
+
+fn main() {
+    let _x = other::super_sekrit::sooper_sekrit::baz; //~ ERROR is private
+}
diff --git a/src/test/ui/unreachable/unreachable-variant.stderr b/src/test/ui/unreachable/unreachable-variant.stderr
new file mode 100644
index 0000000..276c77f
--- /dev/null
+++ b/src/test/ui/unreachable/unreachable-variant.stderr
@@ -0,0 +1,9 @@
+error[E0603]: module `super_sekrit` is private
+  --> $DIR/unreachable-variant.rs:6:21
+   |
+LL |     let _x = other::super_sekrit::sooper_sekrit::baz;
+   |                     ^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0603`.
diff --git a/src/test/ui/unreachable/unwarned-match-on-never.rs b/src/test/ui/unreachable/unwarned-match-on-never.rs
new file mode 100644
index 0000000..71f8fe3
--- /dev/null
+++ b/src/test/ui/unreachable/unwarned-match-on-never.rs
@@ -0,0 +1,24 @@
+#![deny(unreachable_code)]
+#![allow(dead_code)]
+
+#![feature(never_type)]
+
+fn foo(x: !) -> bool {
+    // Explicit matches on the never type are unwarned.
+    match x {}
+    // But matches in unreachable code are warned.
+    match x {} //~ ERROR unreachable expression
+}
+
+fn bar() {
+    match (return) {
+        () => () //~ ERROR unreachable arm
+    }
+}
+
+fn main() {
+    return;
+    match () { //~ ERROR unreachable expression
+        () => (),
+    }
+}
diff --git a/src/test/ui/unreachable/unwarned-match-on-never.stderr b/src/test/ui/unreachable/unwarned-match-on-never.stderr
new file mode 100644
index 0000000..ccb70d7
--- /dev/null
+++ b/src/test/ui/unreachable/unwarned-match-on-never.stderr
@@ -0,0 +1,28 @@
+error: unreachable expression
+  --> $DIR/unwarned-match-on-never.rs:10:5
+   |
+LL |     match x {}
+   |     ^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/unwarned-match-on-never.rs:1:9
+   |
+LL | #![deny(unreachable_code)]
+   |         ^^^^^^^^^^^^^^^^
+
+error: unreachable arm
+  --> $DIR/unwarned-match-on-never.rs:15:15
+   |
+LL |         () => ()
+   |               ^^
+
+error: unreachable expression
+  --> $DIR/unwarned-match-on-never.rs:21:5
+   |
+LL | /     match () {
+LL | |         () => (),
+LL | |     }
+   | |_____^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/unresolved/unresolved-extern-mod-suggestion.rs b/src/test/ui/unresolved/unresolved-extern-mod-suggestion.rs
new file mode 100644
index 0000000..a1bf0f2
--- /dev/null
+++ b/src/test/ui/unresolved/unresolved-extern-mod-suggestion.rs
@@ -0,0 +1,5 @@
+extern crate core;
+use core;
+//~^ ERROR the name `core` is defined multiple times
+
+fn main() {}
diff --git a/src/test/ui/unresolved/unresolved-extern-mod-suggestion.stderr b/src/test/ui/unresolved/unresolved-extern-mod-suggestion.stderr
new file mode 100644
index 0000000..2833322
--- /dev/null
+++ b/src/test/ui/unresolved/unresolved-extern-mod-suggestion.stderr
@@ -0,0 +1,13 @@
+error[E0254]: the name `core` is defined multiple times
+  --> $DIR/unresolved-extern-mod-suggestion.rs:2:5
+   |
+LL | extern crate core;
+   | ------------------ previous import of the extern crate `core` here
+LL | use core;
+   |     ^^^^ `core` reimported here
+   |
+   = note: `core` must be defined only once in the type namespace of this module
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0254`.
diff --git a/src/test/ui/unresolved/unresolved-import-recovery.rs b/src/test/ui/unresolved/unresolved-import-recovery.rs
new file mode 100644
index 0000000..0b06533
--- /dev/null
+++ b/src/test/ui/unresolved/unresolved-import-recovery.rs
@@ -0,0 +1,17 @@
+// Check that unresolved imports do not create additional errors and ICEs
+
+mod m {
+    pub use unresolved; //~ ERROR unresolved import `unresolved`
+
+    fn f() {
+        let unresolved = 0; // OK
+    }
+}
+
+fn main() {
+    match 0u8 {
+        m::unresolved => {} // OK
+        m::unresolved(..) => {} // OK
+        m::unresolved{..} => {} // OK
+    }
+}
diff --git a/src/test/ui/unresolved/unresolved-import-recovery.stderr b/src/test/ui/unresolved/unresolved-import-recovery.stderr
new file mode 100644
index 0000000..5e371b7
--- /dev/null
+++ b/src/test/ui/unresolved/unresolved-import-recovery.stderr
@@ -0,0 +1,9 @@
+error[E0432]: unresolved import `unresolved`
+  --> $DIR/unresolved-import-recovery.rs:4:13
+   |
+LL |     pub use unresolved;
+   |             ^^^^^^^^^^ no `unresolved` in the root
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/unresolved/unresolved-import.rs b/src/test/ui/unresolved/unresolved-import.rs
new file mode 100644
index 0000000..4c7d4bb
--- /dev/null
+++ b/src/test/ui/unresolved/unresolved-import.rs
@@ -0,0 +1,55 @@
+use foo::bar; //~ ERROR unresolved import `foo` [E0432]
+              //~^ maybe a missing `extern crate foo;`?
+
+use bar::Baz as x; //~ ERROR unresolved import `bar::Baz` [E0432]
+                   //~| no `Baz` in `bar`
+                   //~| HELP a similar name exists in the module
+                   //~| SUGGESTION Bar
+
+use food::baz; //~ ERROR unresolved import `food::baz`
+               //~| no `baz` in `food`
+               //~| HELP a similar name exists in the module
+               //~| SUGGESTION bag
+
+use food::{beens as Foo}; //~ ERROR unresolved import `food::beens` [E0432]
+                          //~| no `beens` in `food`
+                          //~| HELP a similar name exists in the module
+                          //~| SUGGESTION beans
+
+mod bar {
+    pub struct Bar;
+}
+
+mod food {
+    pub use self::zug::baz::{self as bag, Foobar as beans};
+
+    mod zug {
+        pub mod baz {
+            pub struct Foobar;
+        }
+    }
+}
+
+mod m {
+    enum MyEnum {
+        MyVariant
+    }
+
+    use MyEnum::*; //~ ERROR unresolved import `MyEnum` [E0432]
+                   //~| HELP a similar path exists
+                   //~| SUGGESTION self::MyEnum
+}
+
+mod items {
+    enum Enum {
+        Variant
+    }
+
+    use Enum::*; //~ ERROR unresolved import `Enum` [E0432]
+                 //~| HELP a similar path exists
+                 //~| SUGGESTION self::Enum
+
+    fn item() {}
+}
+
+fn main() {}
diff --git a/src/test/ui/unresolved/unresolved-import.stderr b/src/test/ui/unresolved/unresolved-import.stderr
new file mode 100644
index 0000000..fb5c076
--- /dev/null
+++ b/src/test/ui/unresolved/unresolved-import.stderr
@@ -0,0 +1,48 @@
+error[E0432]: unresolved import `foo`
+  --> $DIR/unresolved-import.rs:1:5
+   |
+LL | use foo::bar;
+   |     ^^^ maybe a missing `extern crate foo;`?
+
+error[E0432]: unresolved import `bar::Baz`
+  --> $DIR/unresolved-import.rs:4:5
+   |
+LL | use bar::Baz as x;
+   |     ^^^^^---^^^^^
+   |     |    |
+   |     |    help: a similar name exists in the module: `Bar`
+   |     no `Baz` in `bar`
+
+error[E0432]: unresolved import `food::baz`
+  --> $DIR/unresolved-import.rs:9:5
+   |
+LL | use food::baz;
+   |     ^^^^^^---
+   |     |     |
+   |     |     help: a similar name exists in the module: `bag`
+   |     no `baz` in `food`
+
+error[E0432]: unresolved import `food::beens`
+  --> $DIR/unresolved-import.rs:14:12
+   |
+LL | use food::{beens as Foo};
+   |            -----^^^^^^^
+   |            |
+   |            no `beens` in `food`
+   |            help: a similar name exists in the module: `beans`
+
+error[E0432]: unresolved import `MyEnum`
+  --> $DIR/unresolved-import.rs:38:9
+   |
+LL |     use MyEnum::*;
+   |         ^^^^^^ help: a similar path exists: `self::MyEnum`
+
+error[E0432]: unresolved import `Enum`
+  --> $DIR/unresolved-import.rs:48:9
+   |
+LL |     use Enum::*;
+   |         ^^^^ help: a similar path exists: `self::Enum`
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/unrestricted-attribute-tokens.rs b/src/test/ui/unrestricted-attribute-tokens.rs
new file mode 100644
index 0000000..4798f7b
--- /dev/null
+++ b/src/test/ui/unrestricted-attribute-tokens.rs
@@ -0,0 +1,8 @@
+// compile-pass
+
+#![feature(custom_attribute)]
+
+#[my_attr(a b c d)]
+#[my_attr[a b c d]]
+#[my_attr{a b c d}]
+fn main() {}
diff --git a/src/test/ui/unsafe/ranged_ints.rs b/src/test/ui/unsafe/ranged_ints.rs
new file mode 100644
index 0000000..0fa2da9
--- /dev/null
+++ b/src/test/ui/unsafe/ranged_ints.rs
@@ -0,0 +1,8 @@
+#![feature(rustc_attrs)]
+
+#[rustc_layout_scalar_valid_range_start(1)]
+#[repr(transparent)]
+pub(crate) struct NonZero<T>(pub(crate) T);
+fn main() {
+    let _x = NonZero(0); //~ ERROR initializing type with `rustc_layout_scalar_valid_range` attr
+}
diff --git a/src/test/ui/unsafe/ranged_ints.stderr b/src/test/ui/unsafe/ranged_ints.stderr
new file mode 100644
index 0000000..4e43df4
--- /dev/null
+++ b/src/test/ui/unsafe/ranged_ints.stderr
@@ -0,0 +1,11 @@
+error[E0133]: initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe function or block
+  --> $DIR/ranged_ints.rs:7:14
+   |
+LL |     let _x = NonZero(0);
+   |              ^^^^^^^^^^ initializing type with `rustc_layout_scalar_valid_range` attr
+   |
+   = note: initializing a layout restricted type's field with a value outside the valid range is undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/ranged_ints2.rs b/src/test/ui/unsafe/ranged_ints2.rs
new file mode 100644
index 0000000..68ba120
--- /dev/null
+++ b/src/test/ui/unsafe/ranged_ints2.rs
@@ -0,0 +1,9 @@
+#![feature(rustc_attrs)]
+
+#[rustc_layout_scalar_valid_range_start(1)]
+#[repr(transparent)]
+pub(crate) struct NonZero<T>(pub(crate) T);
+fn main() {
+    let mut x = unsafe { NonZero(1) };
+    let y = &mut x.0; //~ ERROR mutation of layout constrained field is unsafe
+}
diff --git a/src/test/ui/unsafe/ranged_ints2.stderr b/src/test/ui/unsafe/ranged_ints2.stderr
new file mode 100644
index 0000000..ee1d1f1
--- /dev/null
+++ b/src/test/ui/unsafe/ranged_ints2.stderr
@@ -0,0 +1,11 @@
+error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block
+  --> $DIR/ranged_ints2.rs:8:13
+   |
+LL |     let y = &mut x.0;
+   |             ^^^^^^^^ mutation of layout constrained field
+   |
+   = note: mutating layout constrained fields cannot statically be checked for valid values
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/ranged_ints2_const.rs b/src/test/ui/unsafe/ranged_ints2_const.rs
new file mode 100644
index 0000000..788f49f
--- /dev/null
+++ b/src/test/ui/unsafe/ranged_ints2_const.rs
@@ -0,0 +1,20 @@
+#![feature(rustc_attrs)]
+
+#[rustc_layout_scalar_valid_range_start(1)]
+#[repr(transparent)]
+pub(crate) struct NonZero<T>(pub(crate) T);
+fn main() {
+}
+
+const fn foo() -> NonZero<u32> {
+    let mut x = unsafe { NonZero(1) };
+    let y = &mut x.0; //~ ERROR references in const fn are unstable
+    //~^ ERROR mutation of layout constrained field is unsafe
+    unsafe { NonZero(1) }
+}
+
+const fn bar() -> NonZero<u32> {
+    let mut x = unsafe { NonZero(1) };
+    let y = unsafe { &mut x.0 }; //~ ERROR mutable references in const fn are unstable
+    unsafe { NonZero(1) }
+}
diff --git a/src/test/ui/unsafe/ranged_ints2_const.stderr b/src/test/ui/unsafe/ranged_ints2_const.stderr
new file mode 100644
index 0000000..7d3e141
--- /dev/null
+++ b/src/test/ui/unsafe/ranged_ints2_const.stderr
@@ -0,0 +1,28 @@
+error[E0723]: mutable references in const fn are unstable (see issue #57563)
+  --> $DIR/ranged_ints2_const.rs:11:9
+   |
+LL |     let y = &mut x.0;
+   |         ^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0723]: mutable references in const fn are unstable (see issue #57563)
+  --> $DIR/ranged_ints2_const.rs:18:9
+   |
+LL |     let y = unsafe { &mut x.0 };
+   |         ^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block
+  --> $DIR/ranged_ints2_const.rs:11:13
+   |
+LL |     let y = &mut x.0;
+   |             ^^^^^^^^ mutation of layout constrained field
+   |
+   = note: mutating layout constrained fields cannot statically be checked for valid values
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0133, E0723.
+For more information about an error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/ranged_ints3.rs b/src/test/ui/unsafe/ranged_ints3.rs
new file mode 100644
index 0000000..47d67fa
--- /dev/null
+++ b/src/test/ui/unsafe/ranged_ints3.rs
@@ -0,0 +1,11 @@
+#![feature(rustc_attrs)]
+
+use std::cell::Cell;
+
+#[rustc_layout_scalar_valid_range_start(1)]
+#[repr(transparent)]
+pub(crate) struct NonZero<T>(pub(crate) T);
+fn main() {
+    let mut x = unsafe { NonZero(Cell::new(1)) };
+    let y = &x.0; //~ ERROR borrow of layout constrained field with interior mutability
+}
diff --git a/src/test/ui/unsafe/ranged_ints3.stderr b/src/test/ui/unsafe/ranged_ints3.stderr
new file mode 100644
index 0000000..4d4c916
--- /dev/null
+++ b/src/test/ui/unsafe/ranged_ints3.stderr
@@ -0,0 +1,11 @@
+error[E0133]: borrow of layout constrained field with interior mutability is unsafe and requires unsafe function or block
+  --> $DIR/ranged_ints3.rs:10:13
+   |
+LL |     let y = &x.0;
+   |             ^^^^ borrow of layout constrained field with interior mutability
+   |
+   = note: references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/ranged_ints3_const.rs b/src/test/ui/unsafe/ranged_ints3_const.rs
new file mode 100644
index 0000000..7b03d8e
--- /dev/null
+++ b/src/test/ui/unsafe/ranged_ints3_const.rs
@@ -0,0 +1,21 @@
+#![feature(rustc_attrs)]
+
+use std::cell::Cell;
+
+#[rustc_layout_scalar_valid_range_start(1)]
+#[repr(transparent)]
+pub(crate) struct NonZero<T>(pub(crate) T);
+fn main() {}
+
+const fn foo() -> NonZero<Cell<u32>> {
+    let mut x = unsafe { NonZero(Cell::new(1)) };
+    let y = &x.0; //~ ERROR cannot borrow a constant which may contain interior mutability
+    //~^ ERROR borrow of layout constrained field with interior mutability
+    unsafe { NonZero(Cell::new(1)) }
+}
+
+const fn bar() -> NonZero<Cell<u32>> {
+    let mut x = unsafe { NonZero(Cell::new(1)) };
+    let y = unsafe { &x.0 }; //~ ERROR cannot borrow a constant which may contain interior mut
+    unsafe { NonZero(Cell::new(1)) }
+}
diff --git a/src/test/ui/unsafe/ranged_ints3_const.stderr b/src/test/ui/unsafe/ranged_ints3_const.stderr
new file mode 100644
index 0000000..ea15cd5
--- /dev/null
+++ b/src/test/ui/unsafe/ranged_ints3_const.stderr
@@ -0,0 +1,24 @@
+error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
+  --> $DIR/ranged_ints3_const.rs:12:13
+   |
+LL |     let y = &x.0;
+   |             ^^^^
+
+error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
+  --> $DIR/ranged_ints3_const.rs:19:22
+   |
+LL |     let y = unsafe { &x.0 };
+   |                      ^^^^
+
+error[E0133]: borrow of layout constrained field with interior mutability is unsafe and requires unsafe function or block
+  --> $DIR/ranged_ints3_const.rs:12:13
+   |
+LL |     let y = &x.0;
+   |             ^^^^ borrow of layout constrained field with interior mutability
+   |
+   = note: references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0133, E0492.
+For more information about an error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/ranged_ints4.rs b/src/test/ui/unsafe/ranged_ints4.rs
new file mode 100644
index 0000000..d8632c4
--- /dev/null
+++ b/src/test/ui/unsafe/ranged_ints4.rs
@@ -0,0 +1,9 @@
+#![feature(rustc_attrs)]
+
+#[rustc_layout_scalar_valid_range_start(1)]
+#[repr(transparent)]
+pub(crate) struct NonZero<T>(pub(crate) T);
+fn main() {
+    let mut x = unsafe { NonZero(1) };
+    x.0 = 0; //~ ERROR mutation of layout constrained field is unsafe
+}
diff --git a/src/test/ui/unsafe/ranged_ints4.stderr b/src/test/ui/unsafe/ranged_ints4.stderr
new file mode 100644
index 0000000..68c2258
--- /dev/null
+++ b/src/test/ui/unsafe/ranged_ints4.stderr
@@ -0,0 +1,11 @@
+error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block
+  --> $DIR/ranged_ints4.rs:8:5
+   |
+LL |     x.0 = 0;
+   |     ^^^^^^^ mutation of layout constrained field
+   |
+   = note: mutating layout constrained fields cannot statically be checked for valid values
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/ranged_ints4_const.rs b/src/test/ui/unsafe/ranged_ints4_const.rs
new file mode 100644
index 0000000..f09168c
--- /dev/null
+++ b/src/test/ui/unsafe/ranged_ints4_const.rs
@@ -0,0 +1,19 @@
+#![feature(rustc_attrs)]
+
+#[rustc_layout_scalar_valid_range_start(1)]
+#[repr(transparent)]
+pub(crate) struct NonZero<T>(pub(crate) T);
+fn main() {}
+
+const fn foo() -> NonZero<u32> {
+    let mut x = unsafe { NonZero(1) };
+    x.0 = 0;
+    //~^ ERROR mutation of layout constrained field is unsafe
+    x
+}
+
+const fn bar() -> NonZero<u32> {
+    let mut x = unsafe { NonZero(1) };
+    unsafe { x.0 = 0 }; // this is UB
+    x
+}
diff --git a/src/test/ui/unsafe/ranged_ints4_const.stderr b/src/test/ui/unsafe/ranged_ints4_const.stderr
new file mode 100644
index 0000000..fe83b15
--- /dev/null
+++ b/src/test/ui/unsafe/ranged_ints4_const.stderr
@@ -0,0 +1,11 @@
+error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block
+  --> $DIR/ranged_ints4_const.rs:10:5
+   |
+LL |     x.0 = 0;
+   |     ^^^^^^^ mutation of layout constrained field
+   |
+   = note: mutating layout constrained fields cannot statically be checked for valid values
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/ranged_ints_const.rs b/src/test/ui/unsafe/ranged_ints_const.rs
new file mode 100644
index 0000000..8477772
--- /dev/null
+++ b/src/test/ui/unsafe/ranged_ints_const.rs
@@ -0,0 +1,11 @@
+#![feature(rustc_attrs)]
+
+#[rustc_layout_scalar_valid_range_start(1)]
+#[repr(transparent)]
+pub(crate) struct NonZero<T>(pub(crate) T);
+fn main() {}
+
+const fn foo() -> NonZero<u32> { NonZero(0) }
+//~^ ERROR initializing type with `rustc_layout_scalar_valid_range` attr is unsafe
+
+const fn bar() -> NonZero<u32> { unsafe { NonZero(0) } }
diff --git a/src/test/ui/unsafe/ranged_ints_const.stderr b/src/test/ui/unsafe/ranged_ints_const.stderr
new file mode 100644
index 0000000..584ad40
--- /dev/null
+++ b/src/test/ui/unsafe/ranged_ints_const.stderr
@@ -0,0 +1,11 @@
+error[E0133]: initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe function or block
+  --> $DIR/ranged_ints_const.rs:8:34
+   |
+LL | const fn foo() -> NonZero<u32> { NonZero(0) }
+   |                                  ^^^^^^^^^^ initializing type with `rustc_layout_scalar_valid_range` attr
+   |
+   = note: initializing a layout restricted type's field with a value outside the valid range is undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/unsafe-around-compiler-generated-unsafe.rs b/src/test/ui/unsafe/unsafe-around-compiler-generated-unsafe.rs
new file mode 100644
index 0000000..817939e
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-around-compiler-generated-unsafe.rs
@@ -0,0 +1,7 @@
+// issue #12418
+
+#![deny(unused_unsafe)]
+
+fn main() {
+    unsafe { println!("foo"); } //~ ERROR unnecessary `unsafe`
+}
diff --git a/src/test/ui/unsafe/unsafe-around-compiler-generated-unsafe.stderr b/src/test/ui/unsafe/unsafe-around-compiler-generated-unsafe.stderr
new file mode 100644
index 0000000..28b18d5
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-around-compiler-generated-unsafe.stderr
@@ -0,0 +1,14 @@
+error: unnecessary `unsafe` block
+  --> $DIR/unsafe-around-compiler-generated-unsafe.rs:6:5
+   |
+LL |     unsafe { println!("foo"); }
+   |     ^^^^^^ unnecessary `unsafe` block
+   |
+note: lint level defined here
+  --> $DIR/unsafe-around-compiler-generated-unsafe.rs:3:9
+   |
+LL | #![deny(unused_unsafe)]
+   |         ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/unsafe/unsafe-block-without-braces.rs b/src/test/ui/unsafe/unsafe-block-without-braces.rs
new file mode 100644
index 0000000..a291eb2
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-block-without-braces.rs
@@ -0,0 +1,6 @@
+fn main() {
+    unsafe //{
+        std::mem::transmute::<f32, u32>(1.0);
+    //}
+}
+//~^^^ ERROR expected one of `extern`, `fn`, or `{`, found `std`
diff --git a/src/test/ui/unsafe/unsafe-block-without-braces.stderr b/src/test/ui/unsafe/unsafe-block-without-braces.stderr
new file mode 100644
index 0000000..34a9035
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-block-without-braces.stderr
@@ -0,0 +1,10 @@
+error: expected one of `extern`, `fn`, or `{`, found `std`
+  --> $DIR/unsafe-block-without-braces.rs:3:9
+   |
+LL |     unsafe //{
+   |           - expected one of `extern`, `fn`, or `{` here
+LL |         std::mem::transmute::<f32, u32>(1.0);
+   |         ^^^ unexpected token
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/unsafe/unsafe-const-fn.rs b/src/test/ui/unsafe/unsafe-const-fn.rs
new file mode 100644
index 0000000..cadfdd0
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-const-fn.rs
@@ -0,0 +1,13 @@
+// A quick test of 'unsafe const fn' functionality
+
+const unsafe fn dummy(v: u32) -> u32 {
+    !v
+}
+
+const VAL: u32 = dummy(0xFFFF);
+//~^ ERROR E0133
+
+fn main() {
+    assert_eq!(VAL, 0xFFFF0000);
+}
+
diff --git a/src/test/ui/unsafe/unsafe-const-fn.stderr b/src/test/ui/unsafe/unsafe-const-fn.stderr
new file mode 100644
index 0000000..370e1e6
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-const-fn.stderr
@@ -0,0 +1,11 @@
+error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
+  --> $DIR/unsafe-const-fn.rs:7:18
+   |
+LL | const VAL: u32 = dummy(0xFFFF);
+   |                  ^^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/unsafe-fn-assign-deref-ptr.rs b/src/test/ui/unsafe/unsafe-fn-assign-deref-ptr.rs
new file mode 100644
index 0000000..64bdca5
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-fn-assign-deref-ptr.rs
@@ -0,0 +1,11 @@
+// http://rust-lang.org/COPYRIGHT.
+//
+
+
+fn f(p: *mut u8) {
+    *p = 0; //~ ERROR dereference of raw pointer is unsafe
+    return;
+}
+
+fn main() {
+}
diff --git a/src/test/ui/unsafe/unsafe-fn-assign-deref-ptr.stderr b/src/test/ui/unsafe/unsafe-fn-assign-deref-ptr.stderr
new file mode 100644
index 0000000..8f621d6
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-fn-assign-deref-ptr.stderr
@@ -0,0 +1,11 @@
+error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
+  --> $DIR/unsafe-fn-assign-deref-ptr.rs:6:5
+   |
+LL |     *p = 0;
+   |     ^^^^^^ dereference of raw pointer
+   |
+   = note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/unsafe-fn-autoderef.rs b/src/test/ui/unsafe/unsafe-fn-autoderef.rs
new file mode 100644
index 0000000..60460fc
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-fn-autoderef.rs
@@ -0,0 +1,23 @@
+struct Rec {
+    f: isize
+}
+
+fn f(p: *const Rec) -> isize {
+
+    // Test that * ptrs do not autoderef.  There is a deeper reason for
+    // prohibiting this, beyond making unsafe things annoying (which doesn't
+    // actually seem desirable to me).  The deeper reason is that if you
+    // have a type like:
+    //
+    //    enum foo = *foo;
+    //
+    // you end up with an infinite auto-deref chain, which is
+    // currently impossible (in all other cases, infinite auto-derefs
+    // are prohibited by various checks, such as that the enum is
+    // instantiable and so forth).
+
+    return p.f; //~ ERROR no field `f` on type `*const Rec`
+}
+
+fn main() {
+}
diff --git a/src/test/ui/unsafe/unsafe-fn-autoderef.stderr b/src/test/ui/unsafe/unsafe-fn-autoderef.stderr
new file mode 100644
index 0000000..20a88c35
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-fn-autoderef.stderr
@@ -0,0 +1,11 @@
+error[E0609]: no field `f` on type `*const Rec`
+  --> $DIR/unsafe-fn-autoderef.rs:19:14
+   |
+LL |     return p.f;
+   |            --^
+   |            |
+   |            help: `p` is a raw pointer; try dereferencing it: `(*p).f`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0609`.
diff --git a/src/test/ui/unsafe/unsafe-fn-called-from-safe.rs b/src/test/ui/unsafe/unsafe-fn-called-from-safe.rs
new file mode 100644
index 0000000..5487a8e
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-fn-called-from-safe.rs
@@ -0,0 +1,5 @@
+unsafe fn f() { return; }
+
+fn main() {
+    f(); //~ ERROR call to unsafe function is unsafe
+}
diff --git a/src/test/ui/unsafe/unsafe-fn-called-from-safe.stderr b/src/test/ui/unsafe/unsafe-fn-called-from-safe.stderr
new file mode 100644
index 0000000..80d2c6c
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-fn-called-from-safe.stderr
@@ -0,0 +1,11 @@
+error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
+  --> $DIR/unsafe-fn-called-from-safe.rs:4:5
+   |
+LL |     f();
+   |     ^^^ call to unsafe function
+   |
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/unsafe-fn-deref-ptr.rs b/src/test/ui/unsafe/unsafe-fn-deref-ptr.rs
new file mode 100644
index 0000000..46445aa
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-fn-deref-ptr.rs
@@ -0,0 +1,6 @@
+fn f(p: *const u8) -> u8 {
+    return *p; //~ ERROR dereference of raw pointer is unsafe
+}
+
+fn main() {
+}
diff --git a/src/test/ui/unsafe/unsafe-fn-deref-ptr.stderr b/src/test/ui/unsafe/unsafe-fn-deref-ptr.stderr
new file mode 100644
index 0000000..e8e82de
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-fn-deref-ptr.stderr
@@ -0,0 +1,11 @@
+error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
+  --> $DIR/unsafe-fn-deref-ptr.rs:2:12
+   |
+LL |     return *p;
+   |            ^^ dereference of raw pointer
+   |
+   = note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/unsafe-fn-used-as-value.rs b/src/test/ui/unsafe/unsafe-fn-used-as-value.rs
new file mode 100644
index 0000000..59b8147
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-fn-used-as-value.rs
@@ -0,0 +1,6 @@
+unsafe fn f() { return; }
+
+fn main() {
+    let x = f;
+    x();    //~ ERROR call to unsafe function is unsafe
+}
diff --git a/src/test/ui/unsafe/unsafe-fn-used-as-value.stderr b/src/test/ui/unsafe/unsafe-fn-used-as-value.stderr
new file mode 100644
index 0000000..a7b73ec
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-fn-used-as-value.stderr
@@ -0,0 +1,11 @@
+error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
+  --> $DIR/unsafe-fn-used-as-value.rs:5:5
+   |
+LL |     x();
+   |     ^^^ call to unsafe function
+   |
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/unsafe-move-val-init.rs b/src/test/ui/unsafe/unsafe-move-val-init.rs
new file mode 100644
index 0000000..24249a7
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-move-val-init.rs
@@ -0,0 +1,10 @@
+#![feature(core_intrinsics)]
+
+use std::intrinsics;
+
+// `move_val_init` has an odd desugaring, check that it is still treated
+// as unsafe.
+fn main() {
+    intrinsics::move_val_init(1 as *mut u32, 1);
+    //~^ ERROR dereference of raw pointer is unsafe
+}
diff --git a/src/test/ui/unsafe/unsafe-move-val-init.stderr b/src/test/ui/unsafe/unsafe-move-val-init.stderr
new file mode 100644
index 0000000..44c2aae
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-move-val-init.stderr
@@ -0,0 +1,11 @@
+error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
+  --> $DIR/unsafe-move-val-init.rs:8:5
+   |
+LL |     intrinsics::move_val_init(1 as *mut u32, 1);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereference of raw pointer
+   |
+   = note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/unsafe-subtyping.rs b/src/test/ui/unsafe/unsafe-subtyping.rs
new file mode 100644
index 0000000..a4b748a
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-subtyping.rs
@@ -0,0 +1,11 @@
+// Check that safe fns are not a subtype of unsafe fns.
+
+fn foo(x: Option<fn(i32)>) -> Option<unsafe fn(i32)> {
+    x //~ ERROR mismatched types
+}
+
+fn bar(x: fn(i32)) -> unsafe fn(i32) {
+    x // OK, coercion!
+}
+
+fn main() { }
diff --git a/src/test/ui/unsafe/unsafe-subtyping.stderr b/src/test/ui/unsafe/unsafe-subtyping.stderr
new file mode 100644
index 0000000..cac5ee0
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-subtyping.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/unsafe-subtyping.rs:4:5
+   |
+LL | fn foo(x: Option<fn(i32)>) -> Option<unsafe fn(i32)> {
+   |                               ---------------------- expected `std::option::Option<unsafe fn(i32)>` because of return type
+LL |     x
+   |     ^ expected unsafe fn, found normal fn
+   |
+   = note: expected type `std::option::Option<unsafe fn(i32)>`
+              found type `std::option::Option<fn(i32)>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/unsafe/unsafe-trait-impl.rs b/src/test/ui/unsafe/unsafe-trait-impl.rs
new file mode 100644
index 0000000..7b76e00
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-trait-impl.rs
@@ -0,0 +1,14 @@
+// Check that safe fns are not a subtype of unsafe fns.
+
+trait Foo {
+    unsafe fn len(&self) -> u32;
+}
+
+impl Foo for u32 {
+    fn len(&self) -> u32 { *self }
+    //~^ ERROR method `len` has an incompatible type for trait
+    //~| expected type `unsafe fn(&u32) -> u32`
+    //~| found type `fn(&u32) -> u32`
+}
+
+fn main() { }
diff --git a/src/test/ui/unsafe/unsafe-trait-impl.stderr b/src/test/ui/unsafe/unsafe-trait-impl.stderr
new file mode 100644
index 0000000..4e93d23
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-trait-impl.stderr
@@ -0,0 +1,15 @@
+error[E0053]: method `len` has an incompatible type for trait
+  --> $DIR/unsafe-trait-impl.rs:8:5
+   |
+LL |     unsafe fn len(&self) -> u32;
+   |     ---------------------------- type in trait
+...
+LL |     fn len(&self) -> u32 { *self }
+   |     ^^^^^^^^^^^^^^^^^^^^ expected unsafe fn, found normal fn
+   |
+   = note: expected type `unsafe fn(&u32) -> u32`
+              found type `fn(&u32) -> u32`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0053`.
diff --git a/src/test/ui/unsized-locals/auxiliary/ufuncs.rs b/src/test/ui/unsized-locals/auxiliary/ufuncs.rs
new file mode 100644
index 0000000..065563d
--- /dev/null
+++ b/src/test/ui/unsized-locals/auxiliary/ufuncs.rs
@@ -0,0 +1,3 @@
+#![feature(unsized_locals)]
+
+pub fn udrop<T: ?Sized>(_x: T) {}
diff --git a/src/test/ui/unsized-locals/borrow-after-move.nll.stderr b/src/test/ui/unsized-locals/borrow-after-move.nll.stderr
new file mode 100644
index 0000000..010e182
--- /dev/null
+++ b/src/test/ui/unsized-locals/borrow-after-move.nll.stderr
@@ -0,0 +1,57 @@
+error[E0382]: borrow of moved value: `x`
+  --> $DIR/borrow-after-move.rs:20:24
+   |
+LL |         let y = *x;
+   |                 -- value moved here
+LL |         drop_unsized(y);
+LL |         println!("{}", &x);
+   |                        ^^ value borrowed here after partial move
+   |
+   = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait
+
+error[E0382]: borrow of moved value: `y`
+  --> $DIR/borrow-after-move.rs:22:24
+   |
+LL |         let y = *x;
+   |             - move occurs because `y` has type `str`, which does not implement the `Copy` trait
+LL |         drop_unsized(y);
+   |                      - value moved here
+...
+LL |         println!("{}", &y);
+   |                        ^^ value borrowed here after move
+
+error[E0382]: borrow of moved value: `x`
+  --> $DIR/borrow-after-move.rs:30:24
+   |
+LL |         let y = *x;
+   |                 -- value moved here
+LL |         y.foo();
+LL |         println!("{}", &x);
+   |                        ^^ value borrowed here after partial move
+   |
+   = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait
+
+error[E0382]: borrow of moved value: `y`
+  --> $DIR/borrow-after-move.rs:32:24
+   |
+LL |         let y = *x;
+   |             - move occurs because `y` has type `str`, which does not implement the `Copy` trait
+LL |         y.foo();
+   |         - value moved here
+...
+LL |         println!("{}", &y);
+   |                        ^^ value borrowed here after move
+
+error[E0382]: borrow of moved value: `x`
+  --> $DIR/borrow-after-move.rs:39:24
+   |
+LL |         x.foo();
+   |         - value moved here
+LL |         println!("{}", &x);
+   |                        ^^ value borrowed here after partial move
+   |
+   = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/unsized-locals/borrow-after-move.rs b/src/test/ui/unsized-locals/borrow-after-move.rs
new file mode 100644
index 0000000..587a218
--- /dev/null
+++ b/src/test/ui/unsized-locals/borrow-after-move.rs
@@ -0,0 +1,42 @@
+#![feature(unsized_locals)]
+
+pub trait Foo {
+    fn foo(self) -> String;
+}
+
+impl Foo for str {
+    fn foo(self) -> String {
+        self.to_owned()
+    }
+}
+
+fn drop_unsized<T: ?Sized>(_: T) {}
+
+fn main() {
+    {
+        let x = "hello".to_owned().into_boxed_str();
+        let y = *x;
+        drop_unsized(y);
+        println!("{}", &x);
+        //~^ERROR use of moved value
+        println!("{}", &y);
+        //~^ERROR use of moved value
+    }
+
+    {
+        let x = "hello".to_owned().into_boxed_str();
+        let y = *x;
+        y.foo();
+        println!("{}", &x);
+        //~^ERROR use of moved value
+        println!("{}", &y);
+        //~^ERROR use of moved value
+    }
+
+    {
+        let x = "hello".to_owned().into_boxed_str();
+        x.foo();
+        println!("{}", &x);
+        //~^ERROR use of moved value
+    }
+}
diff --git a/src/test/ui/unsized-locals/borrow-after-move.stderr b/src/test/ui/unsized-locals/borrow-after-move.stderr
new file mode 100644
index 0000000..8eea01f
--- /dev/null
+++ b/src/test/ui/unsized-locals/borrow-after-move.stderr
@@ -0,0 +1,57 @@
+error[E0382]: use of moved value: `x`
+  --> $DIR/borrow-after-move.rs:20:25
+   |
+LL |         let y = *x;
+   |             - value moved here
+LL |         drop_unsized(y);
+LL |         println!("{}", &x);
+   |                         ^ value used here after move
+   |
+   = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `y`
+  --> $DIR/borrow-after-move.rs:22:25
+   |
+LL |         drop_unsized(y);
+   |                      - value moved here
+...
+LL |         println!("{}", &y);
+   |                         ^ value used here after move
+   |
+   = note: move occurs because `y` has type `str`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `x`
+  --> $DIR/borrow-after-move.rs:30:25
+   |
+LL |         let y = *x;
+   |             - value moved here
+LL |         y.foo();
+LL |         println!("{}", &x);
+   |                         ^ value used here after move
+   |
+   = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `y`
+  --> $DIR/borrow-after-move.rs:32:25
+   |
+LL |         y.foo();
+   |         - value moved here
+...
+LL |         println!("{}", &y);
+   |                         ^ value used here after move
+   |
+   = note: move occurs because `y` has type `str`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `x`
+  --> $DIR/borrow-after-move.rs:39:25
+   |
+LL |         x.foo();
+   |         - value moved here
+LL |         println!("{}", &x);
+   |                         ^ value used here after move
+   |
+   = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/unsized-locals/by-value-trait-object-safety.rs b/src/test/ui/unsized-locals/by-value-trait-object-safety.rs
new file mode 100644
index 0000000..8b24328
--- /dev/null
+++ b/src/test/ui/unsized-locals/by-value-trait-object-safety.rs
@@ -0,0 +1,20 @@
+#![feature(unsized_locals)]
+
+pub trait Foo {
+    fn foo(self) -> String where Self: Sized;
+}
+
+struct A;
+
+impl Foo for A {
+    fn foo(self) -> String {
+        format!("hello")
+    }
+}
+
+
+fn main() {
+    let x = *(Box::new(A) as Box<dyn Foo>);
+    x.foo();
+    //~^ERROR the `foo` method cannot be invoked on a trait object
+}
diff --git a/src/test/ui/unsized-locals/by-value-trait-object-safety.stderr b/src/test/ui/unsized-locals/by-value-trait-object-safety.stderr
new file mode 100644
index 0000000..7e9a231
--- /dev/null
+++ b/src/test/ui/unsized-locals/by-value-trait-object-safety.stderr
@@ -0,0 +1,8 @@
+error: the `foo` method cannot be invoked on a trait object
+  --> $DIR/by-value-trait-object-safety.rs:18:7
+   |
+LL |     x.foo();
+   |       ^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/unsized-locals/double-move.nll.stderr b/src/test/ui/unsized-locals/double-move.nll.stderr
new file mode 100644
index 0000000..47fa0d4
--- /dev/null
+++ b/src/test/ui/unsized-locals/double-move.nll.stderr
@@ -0,0 +1,63 @@
+error[E0382]: use of moved value: `y`
+  --> $DIR/double-move.rs:20:22
+   |
+LL |         let y = *x;
+   |             - move occurs because `y` has type `str`, which does not implement the `Copy` trait
+LL |         drop_unsized(y);
+   |                      - value moved here
+LL |         drop_unsized(y);
+   |                      ^ value used here after move
+
+error[E0382]: use of moved value: `x`
+  --> $DIR/double-move.rs:26:22
+   |
+LL |         let _y = *x;
+   |                  -- value moved here
+LL |         drop_unsized(x);
+   |                      ^ value used here after partial move
+   |
+   = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `*x`
+  --> $DIR/double-move.rs:32:18
+   |
+LL |         let x = "hello".to_owned().into_boxed_str();
+   |             - move occurs because `x` has type `std::boxed::Box<str>`, which does not implement the `Copy` trait
+LL |         drop_unsized(x);
+   |                      - value moved here
+LL |         let _y = *x;
+   |                  ^^ value used here after move
+
+error[E0382]: use of moved value: `y`
+  --> $DIR/double-move.rs:39:9
+   |
+LL |         let y = *x;
+   |             - move occurs because `y` has type `str`, which does not implement the `Copy` trait
+LL |         y.foo();
+   |         - value moved here
+LL |         y.foo();
+   |         ^ value used here after move
+
+error[E0382]: use of moved value: `*x`
+  --> $DIR/double-move.rs:45:9
+   |
+LL |         let _y = *x;
+   |                  -- value moved here
+LL |         x.foo();
+   |         ^ value used here after move
+   |
+   = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `*x`
+  --> $DIR/double-move.rs:51:18
+   |
+LL |         x.foo();
+   |         - value moved here
+LL |         let _y = *x;
+   |                  ^^ value used here after move
+   |
+   = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/unsized-locals/double-move.rs b/src/test/ui/unsized-locals/double-move.rs
new file mode 100644
index 0000000..c3a5034
--- /dev/null
+++ b/src/test/ui/unsized-locals/double-move.rs
@@ -0,0 +1,53 @@
+#![feature(unsized_locals)]
+
+pub trait Foo {
+    fn foo(self) -> String;
+}
+
+impl Foo for str {
+    fn foo(self) -> String {
+        self.to_owned()
+    }
+}
+
+fn drop_unsized<T: ?Sized>(_: T) {}
+
+fn main() {
+    {
+        let x = "hello".to_owned().into_boxed_str();
+        let y = *x;
+        drop_unsized(y);
+        drop_unsized(y); //~ERROR use of moved value
+    }
+
+    {
+        let x = "hello".to_owned().into_boxed_str();
+        let _y = *x;
+        drop_unsized(x); //~ERROR use of moved value
+    }
+
+    {
+        let x = "hello".to_owned().into_boxed_str();
+        drop_unsized(x);
+        let _y = *x; //~ERROR use of moved value
+    }
+
+    {
+        let x = "hello".to_owned().into_boxed_str();
+        let y = *x;
+        y.foo();
+        y.foo(); //~ERROR use of moved value
+    }
+
+    {
+        let x = "hello".to_owned().into_boxed_str();
+        let _y = *x;
+        x.foo(); //~ERROR use of moved value
+    }
+
+    {
+        let x = "hello".to_owned().into_boxed_str();
+        x.foo();
+        let _y = *x; //~ERROR use of moved value
+    }
+}
diff --git a/src/test/ui/unsized-locals/double-move.stderr b/src/test/ui/unsized-locals/double-move.stderr
new file mode 100644
index 0000000..e6573af
--- /dev/null
+++ b/src/test/ui/unsized-locals/double-move.stderr
@@ -0,0 +1,63 @@
+error[E0382]: use of moved value: `y`
+  --> $DIR/double-move.rs:20:22
+   |
+LL |         drop_unsized(y);
+   |                      - value moved here
+LL |         drop_unsized(y);
+   |                      ^ value used here after move
+   |
+   = note: move occurs because `y` has type `str`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `x`
+  --> $DIR/double-move.rs:26:22
+   |
+LL |         let _y = *x;
+   |             -- value moved here
+LL |         drop_unsized(x);
+   |                      ^ value used here after move
+   |
+   = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `*x`
+  --> $DIR/double-move.rs:32:13
+   |
+LL |         drop_unsized(x);
+   |                      - value moved here
+LL |         let _y = *x;
+   |             ^^ value used here after move
+   |
+   = note: move occurs because `x` has type `std::boxed::Box<str>`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `y`
+  --> $DIR/double-move.rs:39:9
+   |
+LL |         y.foo();
+   |         - value moved here
+LL |         y.foo();
+   |         ^ value used here after move
+   |
+   = note: move occurs because `y` has type `str`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `*x`
+  --> $DIR/double-move.rs:45:9
+   |
+LL |         let _y = *x;
+   |             -- value moved here
+LL |         x.foo();
+   |         ^ value used here after move
+   |
+   = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `*x`
+  --> $DIR/double-move.rs:51:13
+   |
+LL |         x.foo();
+   |         - value moved here
+LL |         let _y = *x;
+   |             ^^ value used here after move
+   |
+   = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/unsized-locals/issue-50940-with-feature.rs b/src/test/ui/unsized-locals/issue-50940-with-feature.rs
new file mode 100644
index 0000000..3e5d39a
--- /dev/null
+++ b/src/test/ui/unsized-locals/issue-50940-with-feature.rs
@@ -0,0 +1,7 @@
+#![feature(unsized_locals)]
+
+fn main() {
+    struct A<X: ?Sized>(X);
+    A as fn(str) -> A<str>;
+    //~^ERROR the size for values of type `str` cannot be known at compilation time
+}
diff --git a/src/test/ui/unsized-locals/issue-50940-with-feature.stderr b/src/test/ui/unsized-locals/issue-50940-with-feature.stderr
new file mode 100644
index 0000000..7b6c2d1
--- /dev/null
+++ b/src/test/ui/unsized-locals/issue-50940-with-feature.stderr
@@ -0,0 +1,14 @@
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+  --> $DIR/issue-50940-with-feature.rs:5:5
+   |
+LL |     A as fn(str) -> A<str>;
+   |     ^ doesn't have a size known at compile-time
+   |
+   = help: within `main::A<str>`, the trait `std::marker::Sized` is not implemented for `str`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: required because it appears within the type `main::A<str>`
+   = note: the return type of a function must have a statically known size
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/unsized-locals/issue-50940.rs b/src/test/ui/unsized-locals/issue-50940.rs
new file mode 100644
index 0000000..7ba809b
--- /dev/null
+++ b/src/test/ui/unsized-locals/issue-50940.rs
@@ -0,0 +1,5 @@
+fn main() {
+    struct A<X: ?Sized>(X);
+    A as fn(str) -> A<str>;
+    //~^ERROR the size for values of type `str` cannot be known at compilation time
+}
diff --git a/src/test/ui/unsized-locals/issue-50940.stderr b/src/test/ui/unsized-locals/issue-50940.stderr
new file mode 100644
index 0000000..be006c0
--- /dev/null
+++ b/src/test/ui/unsized-locals/issue-50940.stderr
@@ -0,0 +1,14 @@
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+  --> $DIR/issue-50940.rs:3:5
+   |
+LL |     A as fn(str) -> A<str>;
+   |     ^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `str`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: all function arguments must have a statically known size
+   = help: unsized locals are gated as an unstable feature
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/unsized-locals/unsized-exprs.rs b/src/test/ui/unsized-locals/unsized-exprs.rs
new file mode 100644
index 0000000..8ca88ed
--- /dev/null
+++ b/src/test/ui/unsized-locals/unsized-exprs.rs
@@ -0,0 +1,28 @@
+#![feature(unsized_tuple_coercion, unsized_locals)]
+
+struct A<X: ?Sized>(X);
+
+fn udrop<T: ?Sized>(_x: T) {}
+fn foo() -> Box<[u8]> {
+    Box::new(*b"foo")
+}
+fn tfoo() -> Box<(i32, [u8])> {
+    Box::new((42, *b"foo"))
+}
+fn afoo() -> Box<A<[u8]>> {
+    Box::new(A(*b"foo"))
+}
+
+impl std::ops::Add<i32> for A<[u8]> {
+    type Output = ();
+    fn add(self, _rhs: i32) -> Self::Output {}
+}
+
+fn main() {
+    udrop::<(i32, [u8])>((42, *foo()));
+    //~^ERROR E0277
+    udrop::<A<[u8]>>(A { 0: *foo() });
+    //~^ERROR E0277
+    udrop::<A<[u8]>>(A(*foo()));
+    //~^ERROR E0277
+}
diff --git a/src/test/ui/unsized-locals/unsized-exprs.stderr b/src/test/ui/unsized-locals/unsized-exprs.stderr
new file mode 100644
index 0000000..43c35cd
--- /dev/null
+++ b/src/test/ui/unsized-locals/unsized-exprs.stderr
@@ -0,0 +1,36 @@
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/unsized-exprs.rs:22:26
+   |
+LL |     udrop::<(i32, [u8])>((42, *foo()));
+   |                          ^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: within `({integer}, [u8])`, the trait `std::marker::Sized` is not implemented for `[u8]`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: required because it appears within the type `({integer}, [u8])`
+   = note: tuples must have a statically known size to be initialized
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/unsized-exprs.rs:24:22
+   |
+LL |     udrop::<A<[u8]>>(A { 0: *foo() });
+   |                      ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: within `A<[u8]>`, the trait `std::marker::Sized` is not implemented for `[u8]`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: required because it appears within the type `A<[u8]>`
+   = note: structs must have a statically known size to be initialized
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/unsized-exprs.rs:26:22
+   |
+LL |     udrop::<A<[u8]>>(A(*foo()));
+   |                      ^ doesn't have a size known at compile-time
+   |
+   = help: within `A<[u8]>`, the trait `std::marker::Sized` is not implemented for `[u8]`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: required because it appears within the type `A<[u8]>`
+   = note: the return type of a function must have a statically known size
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/unsized-locals/unsized-exprs2.nll.stderr b/src/test/ui/unsized-locals/unsized-exprs2.nll.stderr
new file mode 100644
index 0000000..a94414e
--- /dev/null
+++ b/src/test/ui/unsized-locals/unsized-exprs2.nll.stderr
@@ -0,0 +1,9 @@
+error[E0508]: cannot move out of type `[u8]`, a non-copy slice
+  --> $DIR/unsized-exprs2.rs:22:19
+   |
+LL |     udrop::<[u8]>(foo()[..]);
+   |                   ^^^^^^^^^ cannot move out of here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0508`.
diff --git a/src/test/ui/unsized-locals/unsized-exprs2.rs b/src/test/ui/unsized-locals/unsized-exprs2.rs
new file mode 100644
index 0000000..3fb5a00
--- /dev/null
+++ b/src/test/ui/unsized-locals/unsized-exprs2.rs
@@ -0,0 +1,24 @@
+#![feature(unsized_tuple_coercion, unsized_locals)]
+
+struct A<X: ?Sized>(X);
+
+fn udrop<T: ?Sized>(_x: T) {}
+fn foo() -> Box<[u8]> {
+    Box::new(*b"foo")
+}
+fn tfoo() -> Box<(i32, [u8])> {
+    Box::new((42, *b"foo"))
+}
+fn afoo() -> Box<A<[u8]>> {
+    Box::new(A(*b"foo"))
+}
+
+impl std::ops::Add<i32> for A<[u8]> {
+    type Output = ();
+    fn add(self, _rhs: i32) -> Self::Output {}
+}
+
+fn main() {
+    udrop::<[u8]>(foo()[..]);
+    //~^ERROR cannot move out of indexed content
+}
diff --git a/src/test/ui/unsized-locals/unsized-exprs2.stderr b/src/test/ui/unsized-locals/unsized-exprs2.stderr
new file mode 100644
index 0000000..d7cb4bf
--- /dev/null
+++ b/src/test/ui/unsized-locals/unsized-exprs2.stderr
@@ -0,0 +1,9 @@
+error[E0507]: cannot move out of indexed content
+  --> $DIR/unsized-exprs2.rs:22:19
+   |
+LL |     udrop::<[u8]>(foo()[..]);
+   |                   ^^^^^^^^^ cannot move out of indexed content
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/unsized-locals/unsized-exprs3.rs b/src/test/ui/unsized-locals/unsized-exprs3.rs
new file mode 100644
index 0000000..2133b01
--- /dev/null
+++ b/src/test/ui/unsized-locals/unsized-exprs3.rs
@@ -0,0 +1,10 @@
+// aux-build:ufuncs.rs
+
+extern crate ufuncs;
+
+use ufuncs::udrop;
+
+fn main() {
+    udrop as fn([u8]);
+    //~^ERROR E0277
+}
diff --git a/src/test/ui/unsized-locals/unsized-exprs3.stderr b/src/test/ui/unsized-locals/unsized-exprs3.stderr
new file mode 100644
index 0000000..f9a7452
--- /dev/null
+++ b/src/test/ui/unsized-locals/unsized-exprs3.stderr
@@ -0,0 +1,14 @@
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/unsized-exprs3.rs:8:5
+   |
+LL |     udrop as fn([u8]);
+   |     ^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `[u8]`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: all function arguments must have a statically known size
+   = help: unsized locals are gated as an unstable feature
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/unsized/unsized-bare-typaram.rs b/src/test/ui/unsized/unsized-bare-typaram.rs
new file mode 100644
index 0000000..e611da9
--- /dev/null
+++ b/src/test/ui/unsized/unsized-bare-typaram.rs
@@ -0,0 +1,4 @@
+fn bar<T: Sized>() { }
+fn foo<T: ?Sized>() { bar::<T>() }
+//~^ ERROR the size for values of type
+fn main() { }
diff --git a/src/test/ui/unsized/unsized-bare-typaram.stderr b/src/test/ui/unsized/unsized-bare-typaram.stderr
new file mode 100644
index 0000000..cee1459
--- /dev/null
+++ b/src/test/ui/unsized/unsized-bare-typaram.stderr
@@ -0,0 +1,18 @@
+error[E0277]: the size for values of type `T` cannot be known at compilation time
+  --> $DIR/unsized-bare-typaram.rs:2:23
+   |
+LL | fn foo<T: ?Sized>() { bar::<T>() }
+   |                       ^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `T`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = help: consider adding a `where T: std::marker::Sized` bound
+note: required by `bar`
+  --> $DIR/unsized-bare-typaram.rs:1:1
+   |
+LL | fn bar<T: Sized>() { }
+   | ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/unsized/unsized-enum.rs b/src/test/ui/unsized/unsized-enum.rs
new file mode 100644
index 0000000..02ad1c8
--- /dev/null
+++ b/src/test/ui/unsized/unsized-enum.rs
@@ -0,0 +1,11 @@
+fn is_sized<T:Sized>() { }
+fn not_sized<T: ?Sized>() { }
+
+enum Foo<U> { FooSome(U), FooNone }
+fn foo1<T>() { not_sized::<Foo<T>>() } // Hunky dory.
+fn foo2<T: ?Sized>() { not_sized::<Foo<T>>() }
+//~^ ERROR the size for values of type
+//
+// Not OK: `T` is not sized.
+
+fn main() { }
diff --git a/src/test/ui/unsized/unsized-enum.stderr b/src/test/ui/unsized/unsized-enum.stderr
new file mode 100644
index 0000000..20857a1
--- /dev/null
+++ b/src/test/ui/unsized/unsized-enum.stderr
@@ -0,0 +1,18 @@
+error[E0277]: the size for values of type `T` cannot be known at compilation time
+  --> $DIR/unsized-enum.rs:6:36
+   |
+LL | fn foo2<T: ?Sized>() { not_sized::<Foo<T>>() }
+   |                                    ^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `T`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = help: consider adding a `where T: std::marker::Sized` bound
+note: required by `Foo`
+  --> $DIR/unsized-enum.rs:4:1
+   |
+LL | enum Foo<U> { FooSome(U), FooNone }
+   | ^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/unsized/unsized-enum2.rs b/src/test/ui/unsized/unsized-enum2.rs
new file mode 100644
index 0000000..0fe4a3a
--- /dev/null
+++ b/src/test/ui/unsized/unsized-enum2.rs
@@ -0,0 +1,75 @@
+use std::ops::Deref;
+
+// Due to aggressive error message deduplication, we require 20 *different*
+// unsized types (even Path and [u8] are considered the "same").
+
+trait Foo {}
+trait Bar {}
+trait FooBar {}
+trait BarFoo {}
+
+trait PathHelper1 {}
+trait PathHelper2 {}
+trait PathHelper3 {}
+trait PathHelper4 {}
+
+struct Path1(PathHelper1);
+struct Path2(PathHelper2);
+struct Path3(PathHelper3);
+struct Path4(PathHelper4);
+
+enum E<W: ?Sized, X: ?Sized, Y: ?Sized, Z: ?Sized> {
+    // parameter
+    VA(W),
+    //~^ ERROR the size for values of type
+    VB{x: X},
+    //~^ ERROR the size for values of type
+    VC(isize, Y),
+    //~^ ERROR the size for values of type
+    VD{u: isize, x: Z},
+    //~^ ERROR the size for values of type
+
+    // slice / str
+    VE([u8]),
+    //~^ ERROR the size for values of type
+    VF{x: str},
+    //~^ ERROR the size for values of type
+    VG(isize, [f32]),
+    //~^ ERROR the size for values of type
+    VH{u: isize, x: [u32]},
+    //~^ ERROR the size for values of type
+
+    // unsized struct
+    VI(Path1),
+    //~^ ERROR the size for values of type
+    VJ{x: Path2},
+    //~^ ERROR the size for values of type
+    VK(isize, Path3),
+    //~^ ERROR the size for values of type
+    VL{u: isize, x: Path4},
+    //~^ ERROR the size for values of type
+
+    // plain trait
+    VM(Foo),
+    //~^ ERROR the size for values of type
+    VN{x: Bar},
+    //~^ ERROR the size for values of type
+    VO(isize, FooBar),
+    //~^ ERROR the size for values of type
+    VP{u: isize, x: BarFoo},
+    //~^ ERROR the size for values of type
+
+    // projected
+    VQ(<&'static [i8] as Deref>::Target),
+    //~^ ERROR the size for values of type
+    VR{x: <&'static [char] as Deref>::Target},
+    //~^ ERROR the size for values of type
+    VS(isize, <&'static [f64] as Deref>::Target),
+    //~^ ERROR the size for values of type
+    VT{u: isize, x: <&'static [i32] as Deref>::Target},
+    //~^ ERROR the size for values of type
+}
+
+
+fn main() { }
+
diff --git a/src/test/ui/unsized/unsized-enum2.stderr b/src/test/ui/unsized/unsized-enum2.stderr
new file mode 100644
index 0000000..9109366
--- /dev/null
+++ b/src/test/ui/unsized/unsized-enum2.stderr
@@ -0,0 +1,211 @@
+error[E0277]: the size for values of type `W` cannot be known at compilation time
+  --> $DIR/unsized-enum2.rs:23:8
+   |
+LL |     VA(W),
+   |        ^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `W`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = help: consider adding a `where W: std::marker::Sized` bound
+   = note: no field of an enum variant may have a dynamically sized type
+
+error[E0277]: the size for values of type `X` cannot be known at compilation time
+  --> $DIR/unsized-enum2.rs:25:8
+   |
+LL |     VB{x: X},
+   |        ^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `X`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = help: consider adding a `where X: std::marker::Sized` bound
+   = note: no field of an enum variant may have a dynamically sized type
+
+error[E0277]: the size for values of type `Y` cannot be known at compilation time
+  --> $DIR/unsized-enum2.rs:27:15
+   |
+LL |     VC(isize, Y),
+   |               ^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `Y`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = help: consider adding a `where Y: std::marker::Sized` bound
+   = note: no field of an enum variant may have a dynamically sized type
+
+error[E0277]: the size for values of type `Z` cannot be known at compilation time
+  --> $DIR/unsized-enum2.rs:29:18
+   |
+LL |     VD{u: isize, x: Z},
+   |                  ^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `Z`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = help: consider adding a `where Z: std::marker::Sized` bound
+   = note: no field of an enum variant may have a dynamically sized type
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/unsized-enum2.rs:33:8
+   |
+LL |     VE([u8]),
+   |        ^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `[u8]`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: no field of an enum variant may have a dynamically sized type
+
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+  --> $DIR/unsized-enum2.rs:35:8
+   |
+LL |     VF{x: str},
+   |        ^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `str`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: no field of an enum variant may have a dynamically sized type
+
+error[E0277]: the size for values of type `[f32]` cannot be known at compilation time
+  --> $DIR/unsized-enum2.rs:37:15
+   |
+LL |     VG(isize, [f32]),
+   |               ^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `[f32]`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: no field of an enum variant may have a dynamically sized type
+
+error[E0277]: the size for values of type `[u32]` cannot be known at compilation time
+  --> $DIR/unsized-enum2.rs:39:18
+   |
+LL |     VH{u: isize, x: [u32]},
+   |                  ^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `[u32]`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: no field of an enum variant may have a dynamically sized type
+
+error[E0277]: the size for values of type `(dyn Foo + 'static)` cannot be known at compilation time
+  --> $DIR/unsized-enum2.rs:53:8
+   |
+LL |     VM(Foo),
+   |        ^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `(dyn Foo + 'static)`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: no field of an enum variant may have a dynamically sized type
+
+error[E0277]: the size for values of type `(dyn Bar + 'static)` cannot be known at compilation time
+  --> $DIR/unsized-enum2.rs:55:8
+   |
+LL |     VN{x: Bar},
+   |        ^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `(dyn Bar + 'static)`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: no field of an enum variant may have a dynamically sized type
+
+error[E0277]: the size for values of type `(dyn FooBar + 'static)` cannot be known at compilation time
+  --> $DIR/unsized-enum2.rs:57:15
+   |
+LL |     VO(isize, FooBar),
+   |               ^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `(dyn FooBar + 'static)`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: no field of an enum variant may have a dynamically sized type
+
+error[E0277]: the size for values of type `(dyn BarFoo + 'static)` cannot be known at compilation time
+  --> $DIR/unsized-enum2.rs:59:18
+   |
+LL |     VP{u: isize, x: BarFoo},
+   |                  ^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `(dyn BarFoo + 'static)`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: no field of an enum variant may have a dynamically sized type
+
+error[E0277]: the size for values of type `[i8]` cannot be known at compilation time
+  --> $DIR/unsized-enum2.rs:63:8
+   |
+LL |     VQ(<&'static [i8] as Deref>::Target),
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `[i8]`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: no field of an enum variant may have a dynamically sized type
+
+error[E0277]: the size for values of type `[char]` cannot be known at compilation time
+  --> $DIR/unsized-enum2.rs:65:8
+   |
+LL |     VR{x: <&'static [char] as Deref>::Target},
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `[char]`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: no field of an enum variant may have a dynamically sized type
+
+error[E0277]: the size for values of type `[f64]` cannot be known at compilation time
+  --> $DIR/unsized-enum2.rs:67:15
+   |
+LL |     VS(isize, <&'static [f64] as Deref>::Target),
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `[f64]`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: no field of an enum variant may have a dynamically sized type
+
+error[E0277]: the size for values of type `[i32]` cannot be known at compilation time
+  --> $DIR/unsized-enum2.rs:69:18
+   |
+LL |     VT{u: isize, x: <&'static [i32] as Deref>::Target},
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `[i32]`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: no field of an enum variant may have a dynamically sized type
+
+error[E0277]: the size for values of type `(dyn PathHelper1 + 'static)` cannot be known at compilation time
+  --> $DIR/unsized-enum2.rs:43:8
+   |
+LL |     VI(Path1),
+   |        ^^^^^ doesn't have a size known at compile-time
+   |
+   = help: within `Path1`, the trait `std::marker::Sized` is not implemented for `(dyn PathHelper1 + 'static)`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: required because it appears within the type `Path1`
+   = note: no field of an enum variant may have a dynamically sized type
+
+error[E0277]: the size for values of type `(dyn PathHelper2 + 'static)` cannot be known at compilation time
+  --> $DIR/unsized-enum2.rs:45:8
+   |
+LL |     VJ{x: Path2},
+   |        ^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: within `Path2`, the trait `std::marker::Sized` is not implemented for `(dyn PathHelper2 + 'static)`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: required because it appears within the type `Path2`
+   = note: no field of an enum variant may have a dynamically sized type
+
+error[E0277]: the size for values of type `(dyn PathHelper3 + 'static)` cannot be known at compilation time
+  --> $DIR/unsized-enum2.rs:47:15
+   |
+LL |     VK(isize, Path3),
+   |               ^^^^^ doesn't have a size known at compile-time
+   |
+   = help: within `Path3`, the trait `std::marker::Sized` is not implemented for `(dyn PathHelper3 + 'static)`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: required because it appears within the type `Path3`
+   = note: no field of an enum variant may have a dynamically sized type
+
+error[E0277]: the size for values of type `(dyn PathHelper4 + 'static)` cannot be known at compilation time
+  --> $DIR/unsized-enum2.rs:49:18
+   |
+LL |     VL{u: isize, x: Path4},
+   |                  ^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: within `Path4`, the trait `std::marker::Sized` is not implemented for `(dyn PathHelper4 + 'static)`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: required because it appears within the type `Path4`
+   = note: no field of an enum variant may have a dynamically sized type
+
+error: aborting due to 20 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/unsized/unsized-inherent-impl-self-type.rs b/src/test/ui/unsized/unsized-inherent-impl-self-type.rs
new file mode 100644
index 0000000..8bdf80c
--- /dev/null
+++ b/src/test/ui/unsized/unsized-inherent-impl-self-type.rs
@@ -0,0 +1,11 @@
+// Test sized-ness checking in substitution in impls.
+
+// impl - struct
+
+struct S5<Y>(Y);
+
+impl<X: ?Sized> S5<X> {
+    //~^ ERROR the size for values of type
+}
+
+fn main() { }
diff --git a/src/test/ui/unsized/unsized-inherent-impl-self-type.stderr b/src/test/ui/unsized/unsized-inherent-impl-self-type.stderr
new file mode 100644
index 0000000..98eecab
--- /dev/null
+++ b/src/test/ui/unsized/unsized-inherent-impl-self-type.stderr
@@ -0,0 +1,18 @@
+error[E0277]: the size for values of type `X` cannot be known at compilation time
+  --> $DIR/unsized-inherent-impl-self-type.rs:7:17
+   |
+LL | impl<X: ?Sized> S5<X> {
+   |                 ^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `X`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = help: consider adding a `where X: std::marker::Sized` bound
+note: required by `S5`
+  --> $DIR/unsized-inherent-impl-self-type.rs:5:1
+   |
+LL | struct S5<Y>(Y);
+   | ^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/unsized/unsized-struct.rs b/src/test/ui/unsized/unsized-struct.rs
new file mode 100644
index 0000000..bfa5aa0a
--- /dev/null
+++ b/src/test/ui/unsized/unsized-struct.rs
@@ -0,0 +1,18 @@
+fn is_sized<T:Sized>() { }
+fn not_sized<T: ?Sized>() { }
+
+struct Foo<T> { data: T }
+fn foo1<T>() { not_sized::<Foo<T>>() } // Hunky dory.
+fn foo2<T: ?Sized>() { not_sized::<Foo<T>>() }
+//~^ ERROR the size for values of type
+//
+// Not OK: `T` is not sized.
+
+struct Bar<T: ?Sized> { data: T }
+fn bar1<T: ?Sized>() { not_sized::<Bar<T>>() }
+fn bar2<T: ?Sized>() { is_sized::<Bar<T>>() }
+//~^ ERROR the size for values of type
+//
+// Not OK: `Bar<T>` is not sized, but it should be.
+
+fn main() { }
diff --git a/src/test/ui/unsized/unsized-struct.stderr b/src/test/ui/unsized/unsized-struct.stderr
new file mode 100644
index 0000000..7add65c
--- /dev/null
+++ b/src/test/ui/unsized/unsized-struct.stderr
@@ -0,0 +1,34 @@
+error[E0277]: the size for values of type `T` cannot be known at compilation time
+  --> $DIR/unsized-struct.rs:6:36
+   |
+LL | fn foo2<T: ?Sized>() { not_sized::<Foo<T>>() }
+   |                                    ^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `T`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = help: consider adding a `where T: std::marker::Sized` bound
+note: required by `Foo`
+  --> $DIR/unsized-struct.rs:4:1
+   |
+LL | struct Foo<T> { data: T }
+   | ^^^^^^^^^^^^^
+
+error[E0277]: the size for values of type `T` cannot be known at compilation time
+  --> $DIR/unsized-struct.rs:13:24
+   |
+LL | fn bar2<T: ?Sized>() { is_sized::<Bar<T>>() }
+   |                        ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: within `Bar<T>`, the trait `std::marker::Sized` is not implemented for `T`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = help: consider adding a `where T: std::marker::Sized` bound
+   = note: required because it appears within the type `Bar<T>`
+note: required by `is_sized`
+  --> $DIR/unsized-struct.rs:1:1
+   |
+LL | fn is_sized<T:Sized>() { }
+   | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/unsized/unsized-trait-impl-self-type.rs b/src/test/ui/unsized/unsized-trait-impl-self-type.rs
new file mode 100644
index 0000000..df571a8
--- /dev/null
+++ b/src/test/ui/unsized/unsized-trait-impl-self-type.rs
@@ -0,0 +1,14 @@
+// Test sized-ness checking in substitution in impls.
+
+// impl - struct
+trait T3<Z: ?Sized> {
+    fn foo(&self, z: &Z);
+}
+
+struct S5<Y>(Y);
+
+impl<X: ?Sized> T3<X> for S5<X> {
+    //~^ ERROR the size for values of type
+}
+
+fn main() { }
diff --git a/src/test/ui/unsized/unsized-trait-impl-self-type.stderr b/src/test/ui/unsized/unsized-trait-impl-self-type.stderr
new file mode 100644
index 0000000..c39f365
--- /dev/null
+++ b/src/test/ui/unsized/unsized-trait-impl-self-type.stderr
@@ -0,0 +1,18 @@
+error[E0277]: the size for values of type `X` cannot be known at compilation time
+  --> $DIR/unsized-trait-impl-self-type.rs:10:17
+   |
+LL | impl<X: ?Sized> T3<X> for S5<X> {
+   |                 ^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `X`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = help: consider adding a `where X: std::marker::Sized` bound
+note: required by `S5`
+  --> $DIR/unsized-trait-impl-self-type.rs:8:1
+   |
+LL | struct S5<Y>(Y);
+   | ^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/unsized/unsized-trait-impl-trait-arg.rs b/src/test/ui/unsized/unsized-trait-impl-trait-arg.rs
new file mode 100644
index 0000000..96e7e37
--- /dev/null
+++ b/src/test/ui/unsized/unsized-trait-impl-trait-arg.rs
@@ -0,0 +1,12 @@
+// Test sized-ness checking in substitution in impls.
+
+// impl - unbounded
+trait T2<Z> {
+    fn foo(&self, z: Z);
+}
+struct S4<Y: ?Sized>(Box<Y>);
+impl<X: ?Sized> T2<X> for S4<X> {
+    //~^ ERROR the size for values of type
+}
+
+fn main() { }
diff --git a/src/test/ui/unsized/unsized-trait-impl-trait-arg.stderr b/src/test/ui/unsized/unsized-trait-impl-trait-arg.stderr
new file mode 100644
index 0000000..ee0d5cc
--- /dev/null
+++ b/src/test/ui/unsized/unsized-trait-impl-trait-arg.stderr
@@ -0,0 +1,13 @@
+error[E0277]: the size for values of type `X` cannot be known at compilation time
+  --> $DIR/unsized-trait-impl-trait-arg.rs:8:17
+   |
+LL | impl<X: ?Sized> T2<X> for S4<X> {
+   |                 ^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `X`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = help: consider adding a `where X: std::marker::Sized` bound
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/unsized3.rs b/src/test/ui/unsized3.rs
new file mode 100644
index 0000000..f5b5d02
--- /dev/null
+++ b/src/test/ui/unsized3.rs
@@ -0,0 +1,51 @@
+// Test sized-ness checking in substitution within fn bodies..
+
+use std::marker;
+
+// Unbounded.
+fn f1<X: ?Sized>(x: &X) {
+    f2::<X>(x);
+    //~^ ERROR the size for values of type
+}
+fn f2<X>(x: &X) {
+}
+
+// Bounded.
+trait T {
+    fn foo(&self) { }
+}
+fn f3<X: ?Sized + T>(x: &X) {
+    f4::<X>(x);
+    //~^ ERROR the size for values of type
+}
+fn f4<X: T>(x: &X) {
+}
+
+fn f5<Y>(x: &Y) {}
+fn f6<X: ?Sized>(x: &X) {}
+
+// Test with unsized struct.
+struct S<X: ?Sized> {
+    x: X,
+}
+
+fn f8<X: ?Sized>(x1: &S<X>, x2: &S<X>) {
+    f5(x1);
+    //~^ ERROR the size for values of type
+    f6(x2); // ok
+}
+
+// Test some tuples.
+fn f9<X: ?Sized>(x1: Box<S<X>>) {
+    f5(&(*x1, 34));
+    //~^ ERROR the size for values of type
+}
+
+fn f10<X: ?Sized>(x1: Box<S<X>>) {
+    f5(&(32, *x1));
+    //~^ ERROR the size for values of type
+    //~| ERROR the size for values of type
+}
+
+pub fn main() {
+}
diff --git a/src/test/ui/unsized3.stderr b/src/test/ui/unsized3.stderr
new file mode 100644
index 0000000..2c7b86c
--- /dev/null
+++ b/src/test/ui/unsized3.stderr
@@ -0,0 +1,91 @@
+error[E0277]: the size for values of type `X` cannot be known at compilation time
+  --> $DIR/unsized3.rs:7:5
+   |
+LL |     f2::<X>(x);
+   |     ^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `X`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = help: consider adding a `where X: std::marker::Sized` bound
+note: required by `f2`
+  --> $DIR/unsized3.rs:10:1
+   |
+LL | fn f2<X>(x: &X) {
+   | ^^^^^^^^^^^^^^^
+
+error[E0277]: the size for values of type `X` cannot be known at compilation time
+  --> $DIR/unsized3.rs:18:5
+   |
+LL |     f4::<X>(x);
+   |     ^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `X`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = help: consider adding a `where X: std::marker::Sized` bound
+note: required by `f4`
+  --> $DIR/unsized3.rs:21:1
+   |
+LL | fn f4<X: T>(x: &X) {
+   | ^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the size for values of type `X` cannot be known at compilation time
+  --> $DIR/unsized3.rs:33:5
+   |
+LL |     f5(x1);
+   |     ^^ doesn't have a size known at compile-time
+   |
+   = help: within `S<X>`, the trait `std::marker::Sized` is not implemented for `X`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = help: consider adding a `where X: std::marker::Sized` bound
+   = note: required because it appears within the type `S<X>`
+note: required by `f5`
+  --> $DIR/unsized3.rs:24:1
+   |
+LL | fn f5<Y>(x: &Y) {}
+   | ^^^^^^^^^^^^^^^
+
+error[E0277]: the size for values of type `X` cannot be known at compilation time
+  --> $DIR/unsized3.rs:40:5
+   |
+LL |     f5(&(*x1, 34));
+   |     ^^ doesn't have a size known at compile-time
+   |
+   = help: within `S<X>`, the trait `std::marker::Sized` is not implemented for `X`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = help: consider adding a `where X: std::marker::Sized` bound
+   = note: required because it appears within the type `S<X>`
+   = note: only the last element of a tuple may have a dynamically sized type
+
+error[E0277]: the size for values of type `X` cannot be known at compilation time
+  --> $DIR/unsized3.rs:45:9
+   |
+LL |     f5(&(32, *x1));
+   |         ^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: within `({integer}, S<X>)`, the trait `std::marker::Sized` is not implemented for `X`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = help: consider adding a `where X: std::marker::Sized` bound
+   = note: required because it appears within the type `S<X>`
+   = note: required because it appears within the type `({integer}, S<X>)`
+   = note: tuples must have a statically known size to be initialized
+
+error[E0277]: the size for values of type `X` cannot be known at compilation time
+  --> $DIR/unsized3.rs:45:5
+   |
+LL |     f5(&(32, *x1));
+   |     ^^ doesn't have a size known at compile-time
+   |
+   = help: within `({integer}, S<X>)`, the trait `std::marker::Sized` is not implemented for `X`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = help: consider adding a `where X: std::marker::Sized` bound
+   = note: required because it appears within the type `S<X>`
+   = note: required because it appears within the type `({integer}, S<X>)`
+note: required by `f5`
+  --> $DIR/unsized3.rs:24:1
+   |
+LL | fn f5<Y>(x: &Y) {}
+   | ^^^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/unsized5.rs b/src/test/ui/unsized5.rs
new file mode 100644
index 0000000..befd224
--- /dev/null
+++ b/src/test/ui/unsized5.rs
@@ -0,0 +1,34 @@
+// Test `?Sized` types not allowed in fields (except the last one).
+
+struct S1<X: ?Sized> {
+    f1: X,
+    //~^ ERROR the size for values of type
+    f2: isize,
+}
+struct S2<X: ?Sized> {
+    f: isize,
+    g: X,
+    //~^ ERROR the size for values of type
+    h: isize,
+}
+struct S3 {
+    f: str,
+    //~^ ERROR the size for values of type
+    g: [usize]
+}
+struct S4 {
+    f: [u8],
+    //~^ ERROR the size for values of type
+    g: usize
+}
+enum E<X: ?Sized> {
+    V1(X, isize),
+    //~^ ERROR the size for values of type
+}
+enum F<X: ?Sized> {
+    V2{f1: X, f: isize},
+    //~^ ERROR the size for values of type
+}
+
+pub fn main() {
+}
diff --git a/src/test/ui/unsized5.stderr b/src/test/ui/unsized5.stderr
new file mode 100644
index 0000000..6dce9a0
--- /dev/null
+++ b/src/test/ui/unsized5.stderr
@@ -0,0 +1,67 @@
+error[E0277]: the size for values of type `X` cannot be known at compilation time
+  --> $DIR/unsized5.rs:4:5
+   |
+LL |     f1: X,
+   |     ^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `X`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = help: consider adding a `where X: std::marker::Sized` bound
+   = note: only the last field of a struct may have a dynamically sized type
+
+error[E0277]: the size for values of type `X` cannot be known at compilation time
+  --> $DIR/unsized5.rs:10:5
+   |
+LL |     g: X,
+   |     ^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `X`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = help: consider adding a `where X: std::marker::Sized` bound
+   = note: only the last field of a struct may have a dynamically sized type
+
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+  --> $DIR/unsized5.rs:15:5
+   |
+LL |     f: str,
+   |     ^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `str`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: only the last field of a struct may have a dynamically sized type
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/unsized5.rs:20:5
+   |
+LL |     f: [u8],
+   |     ^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `[u8]`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: only the last field of a struct may have a dynamically sized type
+
+error[E0277]: the size for values of type `X` cannot be known at compilation time
+  --> $DIR/unsized5.rs:25:8
+   |
+LL |     V1(X, isize),
+   |        ^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `X`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = help: consider adding a `where X: std::marker::Sized` bound
+   = note: no field of an enum variant may have a dynamically sized type
+
+error[E0277]: the size for values of type `X` cannot be known at compilation time
+  --> $DIR/unsized5.rs:29:8
+   |
+LL |     V2{f1: X, f: isize},
+   |        ^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `X`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = help: consider adding a `where X: std::marker::Sized` bound
+   = note: no field of an enum variant may have a dynamically sized type
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/unsized6.rs b/src/test/ui/unsized6.rs
new file mode 100644
index 0000000..7913355
--- /dev/null
+++ b/src/test/ui/unsized6.rs
@@ -0,0 +1,44 @@
+// Test `?Sized` local variables.
+
+trait T {}
+
+fn f1<W: ?Sized, X: ?Sized, Y: ?Sized, Z: ?Sized>(x: &X) {
+    let _: W; // <-- this is OK, no bindings created, no initializer.
+    let _: (isize, (X, isize));
+    //~^ ERROR the size for values of type
+    let y: Y;
+    //~^ ERROR the size for values of type
+    let y: (isize, (Z, usize));
+    //~^ ERROR the size for values of type
+}
+fn f2<X: ?Sized, Y: ?Sized>(x: &X) {
+    let y: X;
+    //~^ ERROR the size for values of type
+    let y: (isize, (Y, isize));
+    //~^ ERROR the size for values of type
+}
+
+fn f3<X: ?Sized>(x1: Box<X>, x2: Box<X>, x3: Box<X>) {
+    let y: X = *x1;
+    //~^ ERROR the size for values of type
+    let y = *x2;
+    //~^ ERROR the size for values of type
+    let (y, z) = (*x3, 4);
+    //~^ ERROR the size for values of type
+}
+fn f4<X: ?Sized + T>(x1: Box<X>, x2: Box<X>, x3: Box<X>) {
+    let y: X = *x1;
+    //~^ ERROR the size for values of type
+    let y = *x2;
+    //~^ ERROR the size for values of type
+    let (y, z) = (*x3, 4);
+    //~^ ERROR the size for values of type
+}
+
+fn g1<X: ?Sized>(x: X) {}
+//~^ ERROR the size for values of type
+fn g2<X: ?Sized + T>(x: X) {}
+//~^ ERROR the size for values of type
+
+pub fn main() {
+}
diff --git a/src/test/ui/unsized6.stderr b/src/test/ui/unsized6.stderr
new file mode 100644
index 0000000..a6a26573
--- /dev/null
+++ b/src/test/ui/unsized6.stderr
@@ -0,0 +1,156 @@
+error[E0277]: the size for values of type `Y` cannot be known at compilation time
+  --> $DIR/unsized6.rs:9:9
+   |
+LL |     let y: Y;
+   |         ^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `Y`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = help: consider adding a `where Y: std::marker::Sized` bound
+   = note: all local variables must have a statically known size
+   = help: unsized locals are gated as an unstable feature
+
+error[E0277]: the size for values of type `X` cannot be known at compilation time
+  --> $DIR/unsized6.rs:7:12
+   |
+LL |     let _: (isize, (X, isize));
+   |            ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `X`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = help: consider adding a `where X: std::marker::Sized` bound
+   = note: only the last element of a tuple may have a dynamically sized type
+
+error[E0277]: the size for values of type `Z` cannot be known at compilation time
+  --> $DIR/unsized6.rs:11:12
+   |
+LL |     let y: (isize, (Z, usize));
+   |            ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `Z`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = help: consider adding a `where Z: std::marker::Sized` bound
+   = note: only the last element of a tuple may have a dynamically sized type
+
+error[E0277]: the size for values of type `X` cannot be known at compilation time
+  --> $DIR/unsized6.rs:15:9
+   |
+LL |     let y: X;
+   |         ^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `X`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = help: consider adding a `where X: std::marker::Sized` bound
+   = note: all local variables must have a statically known size
+   = help: unsized locals are gated as an unstable feature
+
+error[E0277]: the size for values of type `Y` cannot be known at compilation time
+  --> $DIR/unsized6.rs:17:12
+   |
+LL |     let y: (isize, (Y, isize));
+   |            ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `Y`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = help: consider adding a `where Y: std::marker::Sized` bound
+   = note: only the last element of a tuple may have a dynamically sized type
+
+error[E0277]: the size for values of type `X` cannot be known at compilation time
+  --> $DIR/unsized6.rs:22:9
+   |
+LL |     let y: X = *x1;
+   |         ^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `X`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = help: consider adding a `where X: std::marker::Sized` bound
+   = note: all local variables must have a statically known size
+   = help: unsized locals are gated as an unstable feature
+
+error[E0277]: the size for values of type `X` cannot be known at compilation time
+  --> $DIR/unsized6.rs:24:9
+   |
+LL |     let y = *x2;
+   |         ^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `X`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = help: consider adding a `where X: std::marker::Sized` bound
+   = note: all local variables must have a statically known size
+   = help: unsized locals are gated as an unstable feature
+
+error[E0277]: the size for values of type `X` cannot be known at compilation time
+  --> $DIR/unsized6.rs:26:10
+   |
+LL |     let (y, z) = (*x3, 4);
+   |          ^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `X`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = help: consider adding a `where X: std::marker::Sized` bound
+   = note: all local variables must have a statically known size
+   = help: unsized locals are gated as an unstable feature
+
+error[E0277]: the size for values of type `X` cannot be known at compilation time
+  --> $DIR/unsized6.rs:30:9
+   |
+LL |     let y: X = *x1;
+   |         ^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `X`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = help: consider adding a `where X: std::marker::Sized` bound
+   = note: all local variables must have a statically known size
+   = help: unsized locals are gated as an unstable feature
+
+error[E0277]: the size for values of type `X` cannot be known at compilation time
+  --> $DIR/unsized6.rs:32:9
+   |
+LL |     let y = *x2;
+   |         ^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `X`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = help: consider adding a `where X: std::marker::Sized` bound
+   = note: all local variables must have a statically known size
+   = help: unsized locals are gated as an unstable feature
+
+error[E0277]: the size for values of type `X` cannot be known at compilation time
+  --> $DIR/unsized6.rs:34:10
+   |
+LL |     let (y, z) = (*x3, 4);
+   |          ^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `X`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = help: consider adding a `where X: std::marker::Sized` bound
+   = note: all local variables must have a statically known size
+   = help: unsized locals are gated as an unstable feature
+
+error[E0277]: the size for values of type `X` cannot be known at compilation time
+  --> $DIR/unsized6.rs:38:18
+   |
+LL | fn g1<X: ?Sized>(x: X) {}
+   |                  ^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `X`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = help: consider adding a `where X: std::marker::Sized` bound
+   = note: all local variables must have a statically known size
+   = help: unsized locals are gated as an unstable feature
+
+error[E0277]: the size for values of type `X` cannot be known at compilation time
+  --> $DIR/unsized6.rs:40:22
+   |
+LL | fn g2<X: ?Sized + T>(x: X) {}
+   |                      ^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `X`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = help: consider adding a `where X: std::marker::Sized` bound
+   = note: all local variables must have a statically known size
+   = help: unsized locals are gated as an unstable feature
+
+error: aborting due to 13 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/unsized7.rs b/src/test/ui/unsized7.rs
new file mode 100644
index 0000000..422a784
--- /dev/null
+++ b/src/test/ui/unsized7.rs
@@ -0,0 +1,16 @@
+// Test sized-ness checking in substitution in impls.
+
+trait T {}
+
+// I would like these to fail eventually.
+// impl - bounded
+trait T1<Z: T> {
+    fn dummy(&self) -> Z;
+}
+
+struct S3<Y: ?Sized>(Box<Y>);
+impl<X: ?Sized + T> T1<X> for S3<X> {
+    //~^ ERROR the size for values of type
+}
+
+fn main() { }
diff --git a/src/test/ui/unsized7.stderr b/src/test/ui/unsized7.stderr
new file mode 100644
index 0000000..bb83b18
--- /dev/null
+++ b/src/test/ui/unsized7.stderr
@@ -0,0 +1,13 @@
+error[E0277]: the size for values of type `X` cannot be known at compilation time
+  --> $DIR/unsized7.rs:12:21
+   |
+LL | impl<X: ?Sized + T> T1<X> for S3<X> {
+   |                     ^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `X`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = help: consider adding a `where X: std::marker::Sized` bound
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/unspecified-self-in-trait-ref.rs b/src/test/ui/unspecified-self-in-trait-ref.rs
new file mode 100644
index 0000000..74a9af8
--- /dev/null
+++ b/src/test/ui/unspecified-self-in-trait-ref.rs
@@ -0,0 +1,20 @@
+pub trait Foo<A=Self> {
+    fn foo(&self);
+}
+
+pub trait Bar<X=usize, A=Self> {
+    fn foo(&self);
+}
+
+fn main() {
+    let a = Foo::lol();
+    //~^ ERROR no function or associated item named
+    let b = Foo::<_>::lol();
+    //~^ ERROR no function or associated item named
+    let c = Bar::lol();
+    //~^ ERROR no function or associated item named
+    let d = Bar::<usize, _>::lol();
+    //~^ ERROR no function or associated item named
+    let e = Bar::<usize>::lol();
+    //~^ ERROR must be explicitly specified
+}
diff --git a/src/test/ui/unspecified-self-in-trait-ref.stderr b/src/test/ui/unspecified-self-in-trait-ref.stderr
new file mode 100644
index 0000000..f894cd3
--- /dev/null
+++ b/src/test/ui/unspecified-self-in-trait-ref.stderr
@@ -0,0 +1,36 @@
+error[E0599]: no function or associated item named `lol` found for type `dyn Foo<_>` in the current scope
+  --> $DIR/unspecified-self-in-trait-ref.rs:10:18
+   |
+LL |     let a = Foo::lol();
+   |                  ^^^ function or associated item not found in `dyn Foo<_>`
+
+error[E0599]: no function or associated item named `lol` found for type `dyn Foo<_>` in the current scope
+  --> $DIR/unspecified-self-in-trait-ref.rs:12:23
+   |
+LL |     let b = Foo::<_>::lol();
+   |                       ^^^ function or associated item not found in `dyn Foo<_>`
+
+error[E0599]: no function or associated item named `lol` found for type `dyn Bar<_, _>` in the current scope
+  --> $DIR/unspecified-self-in-trait-ref.rs:14:18
+   |
+LL |     let c = Bar::lol();
+   |                  ^^^ function or associated item not found in `dyn Bar<_, _>`
+
+error[E0599]: no function or associated item named `lol` found for type `dyn Bar<usize, _>` in the current scope
+  --> $DIR/unspecified-self-in-trait-ref.rs:16:30
+   |
+LL |     let d = Bar::<usize, _>::lol();
+   |                              ^^^ function or associated item not found in `dyn Bar<usize, _>`
+
+error[E0393]: the type parameter `A` must be explicitly specified
+  --> $DIR/unspecified-self-in-trait-ref.rs:18:13
+   |
+LL |     let e = Bar::<usize>::lol();
+   |             ^^^^^^^^^^^^^^^^^ missing reference to `A`
+   |
+   = note: because of the default `Self` reference, type parameters must be specified on object types
+
+error: aborting due to 5 previous errors
+
+Some errors occurred: E0393, E0599.
+For more information about an error, try `rustc --explain E0393`.
diff --git a/src/test/ui/unsupported-cast.rs b/src/test/ui/unsupported-cast.rs
new file mode 100644
index 0000000..cb6a57a
--- /dev/null
+++ b/src/test/ui/unsupported-cast.rs
@@ -0,0 +1,7 @@
+// error-pattern:casting
+
+struct A;
+
+fn main() {
+  println!("{:?}", 1.0 as *const A); // Can't cast float to foreign.
+}
diff --git a/src/test/ui/unsupported-cast.stderr b/src/test/ui/unsupported-cast.stderr
new file mode 100644
index 0000000..63e7713
--- /dev/null
+++ b/src/test/ui/unsupported-cast.stderr
@@ -0,0 +1,9 @@
+error[E0606]: casting `f64` as `*const A` is invalid
+  --> $DIR/unsupported-cast.rs:6:20
+   |
+LL |   println!("{:?}", 1.0 as *const A); // Can't cast float to foreign.
+   |                    ^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0606`.
diff --git a/src/test/ui/unused/unused-attr.rs b/src/test/ui/unused/unused-attr.rs
new file mode 100644
index 0000000..810732a
--- /dev/null
+++ b/src/test/ui/unused/unused-attr.rs
@@ -0,0 +1,50 @@
+#![deny(unused_attributes)]
+#![allow(dead_code, unused_imports, unused_extern_crates)]
+#![feature(custom_attribute)]
+
+#![foo] //~ ERROR unused attribute
+
+#[foo] //~ ERROR unused attribute
+extern crate core;
+
+#[foo] //~ ERROR unused attribute
+use std::collections;
+
+#[foo] //~ ERROR unused attribute
+extern "C" {
+    #[foo] //~ ERROR unused attribute
+    fn foo();
+}
+
+#[foo] //~ ERROR unused attribute
+mod foo {
+    #[foo] //~ ERROR unused attribute
+    pub enum Foo {
+        #[foo] //~ ERROR unused attribute
+        Bar,
+    }
+}
+
+#[foo] //~ ERROR unused attribute
+fn bar(f: foo::Foo) {
+    match f {
+        #[foo] //~ ERROR unused attribute
+        foo::Foo::Bar => {}
+    }
+}
+
+#[foo] //~ ERROR unused attribute
+struct Foo {
+    #[foo] //~ ERROR unused attribute
+    a: isize
+}
+
+#[foo] //~ ERROR unused attribute
+trait Baz {
+    #[foo] //~ ERROR unused attribute
+    fn blah(&self);
+    #[foo] //~ ERROR unused attribute
+    fn blah2(&self) {}
+}
+
+fn main() {}
diff --git a/src/test/ui/unused/unused-attr.stderr b/src/test/ui/unused/unused-attr.stderr
new file mode 100644
index 0000000..6f096d7
--- /dev/null
+++ b/src/test/ui/unused/unused-attr.stderr
@@ -0,0 +1,98 @@
+error: unused attribute
+  --> $DIR/unused-attr.rs:7:1
+   |
+LL | #[foo]
+   | ^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/unused-attr.rs:1:9
+   |
+LL | #![deny(unused_attributes)]
+   |         ^^^^^^^^^^^^^^^^^
+
+error: unused attribute
+  --> $DIR/unused-attr.rs:10:1
+   |
+LL | #[foo]
+   | ^^^^^^
+
+error: unused attribute
+  --> $DIR/unused-attr.rs:15:5
+   |
+LL |     #[foo]
+   |     ^^^^^^
+
+error: unused attribute
+  --> $DIR/unused-attr.rs:13:1
+   |
+LL | #[foo]
+   | ^^^^^^
+
+error: unused attribute
+  --> $DIR/unused-attr.rs:23:9
+   |
+LL |         #[foo]
+   |         ^^^^^^
+
+error: unused attribute
+  --> $DIR/unused-attr.rs:21:5
+   |
+LL |     #[foo]
+   |     ^^^^^^
+
+error: unused attribute
+  --> $DIR/unused-attr.rs:19:1
+   |
+LL | #[foo]
+   | ^^^^^^
+
+error: unused attribute
+  --> $DIR/unused-attr.rs:31:9
+   |
+LL |         #[foo]
+   |         ^^^^^^
+
+error: unused attribute
+  --> $DIR/unused-attr.rs:28:1
+   |
+LL | #[foo]
+   | ^^^^^^
+
+error: unused attribute
+  --> $DIR/unused-attr.rs:38:5
+   |
+LL |     #[foo]
+   |     ^^^^^^
+
+error: unused attribute
+  --> $DIR/unused-attr.rs:36:1
+   |
+LL | #[foo]
+   | ^^^^^^
+
+error: unused attribute
+  --> $DIR/unused-attr.rs:44:5
+   |
+LL |     #[foo]
+   |     ^^^^^^
+
+error: unused attribute
+  --> $DIR/unused-attr.rs:46:5
+   |
+LL |     #[foo]
+   |     ^^^^^^
+
+error: unused attribute
+  --> $DIR/unused-attr.rs:42:1
+   |
+LL | #[foo]
+   | ^^^^^^
+
+error: unused attribute
+  --> $DIR/unused-attr.rs:5:1
+   |
+LL | #![foo]
+   | ^^^^^^^
+
+error: aborting due to 15 previous errors
+
diff --git a/src/test/ui/unused/unused-macro-rules.rs b/src/test/ui/unused/unused-macro-rules.rs
new file mode 100644
index 0000000..1a714b8
--- /dev/null
+++ b/src/test/ui/unused/unused-macro-rules.rs
@@ -0,0 +1,29 @@
+#![deny(unused_macros)]
+
+// Most simple case
+macro_rules! unused { //~ ERROR: unused macro definition
+    () => {};
+}
+
+// Test macros created by macros
+macro_rules! create_macro {
+    () => {
+        macro_rules! m { //~ ERROR: unused macro definition
+            () => {};
+        }
+    };
+}
+create_macro!();
+
+#[allow(unused_macros)]
+mod bar {
+    // Test that putting the #[deny] close to the macro's definition
+    // works.
+
+    #[deny(unused_macros)]
+    macro_rules! unused { //~ ERROR: unused macro definition
+        () => {};
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/unused/unused-macro-rules.stderr b/src/test/ui/unused/unused-macro-rules.stderr
new file mode 100644
index 0000000..5c0b9f2
--- /dev/null
+++ b/src/test/ui/unused/unused-macro-rules.stderr
@@ -0,0 +1,41 @@
+error: unused macro definition
+  --> $DIR/unused-macro-rules.rs:4:1
+   |
+LL | / macro_rules! unused {
+LL | |     () => {};
+LL | | }
+   | |_^
+   |
+note: lint level defined here
+  --> $DIR/unused-macro-rules.rs:1:9
+   |
+LL | #![deny(unused_macros)]
+   |         ^^^^^^^^^^^^^
+
+error: unused macro definition
+  --> $DIR/unused-macro-rules.rs:11:9
+   |
+LL | /         macro_rules! m {
+LL | |             () => {};
+LL | |         }
+   | |_________^
+...
+LL |   create_macro!();
+   |   ---------------- in this macro invocation
+
+error: unused macro definition
+  --> $DIR/unused-macro-rules.rs:24:5
+   |
+LL | /     macro_rules! unused {
+LL | |         () => {};
+LL | |     }
+   | |_____^
+   |
+note: lint level defined here
+  --> $DIR/unused-macro-rules.rs:23:12
+   |
+LL |     #[deny(unused_macros)]
+   |            ^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/unused/unused-macro-with-bad-frag-spec.rs b/src/test/ui/unused/unused-macro-with-bad-frag-spec.rs
new file mode 100644
index 0000000..ce18704
--- /dev/null
+++ b/src/test/ui/unused/unused-macro-with-bad-frag-spec.rs
@@ -0,0 +1,9 @@
+#![allow(unused_macros)]
+
+// Issue #21370
+
+macro_rules! test {
+    ($wrong:t_ty) => () //~ ERROR invalid fragment specifier `t_ty`
+}
+
+fn main() { }
diff --git a/src/test/ui/unused/unused-macro-with-bad-frag-spec.stderr b/src/test/ui/unused/unused-macro-with-bad-frag-spec.stderr
new file mode 100644
index 0000000..6edf0a2
--- /dev/null
+++ b/src/test/ui/unused/unused-macro-with-bad-frag-spec.stderr
@@ -0,0 +1,10 @@
+error: invalid fragment specifier `t_ty`
+  --> $DIR/unused-macro-with-bad-frag-spec.rs:6:6
+   |
+LL |     ($wrong:t_ty) => ()
+   |      ^^^^^^^^^^^
+   |
+   = help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/unused/unused-macro-with-follow-violation.rs b/src/test/ui/unused/unused-macro-with-follow-violation.rs
new file mode 100644
index 0000000..1666dae
--- /dev/null
+++ b/src/test/ui/unused/unused-macro-with-follow-violation.rs
@@ -0,0 +1,7 @@
+#![allow(unused_macros)]
+
+macro_rules! test {
+    ($e:expr +) => () //~ ERROR not allowed for `expr` fragments
+}
+
+fn main() { }
diff --git a/src/test/ui/unused/unused-macro-with-follow-violation.stderr b/src/test/ui/unused/unused-macro-with-follow-violation.stderr
new file mode 100644
index 0000000..5eced4f
--- /dev/null
+++ b/src/test/ui/unused/unused-macro-with-follow-violation.stderr
@@ -0,0 +1,10 @@
+error: `$e:expr` is followed by `+`, which is not allowed for `expr` fragments
+  --> $DIR/unused-macro-with-follow-violation.rs:4:14
+   |
+LL |     ($e:expr +) => ()
+   |              ^ not allowed after `expr` fragments
+   |
+   = note: allowed there are: `=>`, `,` or `;`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/unused/unused-macro.rs b/src/test/ui/unused/unused-macro.rs
new file mode 100644
index 0000000..302b072
--- /dev/null
+++ b/src/test/ui/unused/unused-macro.rs
@@ -0,0 +1,26 @@
+#![feature(decl_macro)]
+#![deny(unused_macros)]
+
+// Most simple case
+macro unused { //~ ERROR: unused macro definition
+    () => {}
+}
+
+#[allow(unused_macros)]
+mod bar {
+    // Test that putting the #[deny] close to the macro's definition
+    // works.
+
+    #[deny(unused_macros)]
+    macro unused { //~ ERROR: unused macro definition
+        () => {}
+    }
+}
+
+mod boo {
+    pub(crate) macro unused { //~ ERROR: unused macro definition
+        () => {}
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/unused/unused-macro.stderr b/src/test/ui/unused/unused-macro.stderr
new file mode 100644
index 0000000..d18fe82
--- /dev/null
+++ b/src/test/ui/unused/unused-macro.stderr
@@ -0,0 +1,38 @@
+error: unused macro definition
+  --> $DIR/unused-macro.rs:5:1
+   |
+LL | / macro unused {
+LL | |     () => {}
+LL | | }
+   | |_^
+   |
+note: lint level defined here
+  --> $DIR/unused-macro.rs:2:9
+   |
+LL | #![deny(unused_macros)]
+   |         ^^^^^^^^^^^^^
+
+error: unused macro definition
+  --> $DIR/unused-macro.rs:15:5
+   |
+LL | /     macro unused {
+LL | |         () => {}
+LL | |     }
+   | |_____^
+   |
+note: lint level defined here
+  --> $DIR/unused-macro.rs:14:12
+   |
+LL |     #[deny(unused_macros)]
+   |            ^^^^^^^^^^^^^
+
+error: unused macro definition
+  --> $DIR/unused-macro.rs:21:5
+   |
+LL | /     pub(crate) macro unused {
+LL | |         () => {}
+LL | |     }
+   | |_____^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/unused/unused-mut-warning-captured-var.rs b/src/test/ui/unused/unused-mut-warning-captured-var.rs
new file mode 100644
index 0000000..c945969
--- /dev/null
+++ b/src/test/ui/unused/unused-mut-warning-captured-var.rs
@@ -0,0 +1,7 @@
+#![forbid(unused_mut)]
+
+fn main() {
+    let mut x = 1;
+    //~^ ERROR: variable does not need to be mutable
+    move|| { println!("{}", x); };
+}
diff --git a/src/test/ui/unused/unused-mut-warning-captured-var.stderr b/src/test/ui/unused/unused-mut-warning-captured-var.stderr
new file mode 100644
index 0000000..d5b7314
--- /dev/null
+++ b/src/test/ui/unused/unused-mut-warning-captured-var.stderr
@@ -0,0 +1,16 @@
+error: variable does not need to be mutable
+  --> $DIR/unused-mut-warning-captured-var.rs:4:9
+   |
+LL |     let mut x = 1;
+   |         ----^
+   |         |
+   |         help: remove this `mut`
+   |
+note: lint level defined here
+  --> $DIR/unused-mut-warning-captured-var.rs:1:11
+   |
+LL | #![forbid(unused_mut)]
+   |           ^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/unused/unused-result.rs b/src/test/ui/unused/unused-result.rs
new file mode 100644
index 0000000..538d309
--- /dev/null
+++ b/src/test/ui/unused/unused-result.rs
@@ -0,0 +1,42 @@
+#![allow(dead_code)]
+#![deny(unused_results, unused_must_use)]
+//~^ NOTE: lint level defined here
+//~| NOTE: lint level defined here
+
+#[must_use]
+enum MustUse { Test }
+
+#[must_use = "some message"]
+enum MustUseMsg { Test2 }
+
+fn foo<T>() -> T { panic!() }
+
+fn bar() -> isize { return foo::<isize>(); }
+fn baz() -> MustUse { return foo::<MustUse>(); }
+fn qux() -> MustUseMsg { return foo::<MustUseMsg>(); }
+
+#[allow(unused_results)]
+fn test() {
+    foo::<isize>();
+    foo::<MustUse>(); //~ ERROR: unused `MustUse` that must be used
+    foo::<MustUseMsg>(); //~ ERROR: unused `MustUseMsg` that must be used
+    //~^ NOTE: some message
+}
+
+#[allow(unused_results, unused_must_use)]
+fn test2() {
+    foo::<isize>();
+    foo::<MustUse>();
+    foo::<MustUseMsg>();
+}
+
+fn main() {
+    foo::<isize>(); //~ ERROR: unused result
+    foo::<MustUse>(); //~ ERROR: unused `MustUse` that must be used
+    foo::<MustUseMsg>(); //~ ERROR: unused `MustUseMsg` that must be used
+    //~^ NOTE: some message
+
+    let _ = foo::<isize>();
+    let _ = foo::<MustUse>();
+    let _ = foo::<MustUseMsg>();
+}
diff --git a/src/test/ui/unused/unused-result.stderr b/src/test/ui/unused/unused-result.stderr
new file mode 100644
index 0000000..e2aee75
--- /dev/null
+++ b/src/test/ui/unused/unused-result.stderr
@@ -0,0 +1,48 @@
+error: unused `MustUse` that must be used
+  --> $DIR/unused-result.rs:21:5
+   |
+LL |     foo::<MustUse>();
+   |     ^^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/unused-result.rs:2:25
+   |
+LL | #![deny(unused_results, unused_must_use)]
+   |                         ^^^^^^^^^^^^^^^
+
+error: unused `MustUseMsg` that must be used
+  --> $DIR/unused-result.rs:22:5
+   |
+LL |     foo::<MustUseMsg>();
+   |     ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: some message
+
+error: unused result
+  --> $DIR/unused-result.rs:34:5
+   |
+LL |     foo::<isize>();
+   |     ^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/unused-result.rs:2:9
+   |
+LL | #![deny(unused_results, unused_must_use)]
+   |         ^^^^^^^^^^^^^^
+
+error: unused `MustUse` that must be used
+  --> $DIR/unused-result.rs:35:5
+   |
+LL |     foo::<MustUse>();
+   |     ^^^^^^^^^^^^^^^^^
+
+error: unused `MustUseMsg` that must be used
+  --> $DIR/unused-result.rs:36:5
+   |
+LL |     foo::<MustUseMsg>();
+   |     ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: some message
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/ui/use-self-in-inner-fn.rs b/src/test/ui/use-self-in-inner-fn.rs
new file mode 100644
index 0000000..eccb315
--- /dev/null
+++ b/src/test/ui/use-self-in-inner-fn.rs
@@ -0,0 +1,14 @@
+struct A;
+
+impl A {
+//~^ NOTE `Self` type implicitly declared here, by this `impl`
+    fn banana(&mut self) {
+        fn peach(this: &Self) {
+        //~^ ERROR can't use generic parameters from outer function
+        //~| NOTE use of generic parameter from outer function
+        //~| NOTE use a type here instead
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/use-self-in-inner-fn.stderr b/src/test/ui/use-self-in-inner-fn.stderr
new file mode 100644
index 0000000..9660934
--- /dev/null
+++ b/src/test/ui/use-self-in-inner-fn.stderr
@@ -0,0 +1,15 @@
+error[E0401]: can't use generic parameters from outer function
+  --> $DIR/use-self-in-inner-fn.rs:6:25
+   |
+LL | impl A {
+   | ---- `Self` type implicitly declared here, by this `impl`
+...
+LL |         fn peach(this: &Self) {
+   |                         ^^^^
+   |                         |
+   |                         use of generic parameter from outer function
+   |                         use a type here instead
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0401`.
diff --git a/src/test/ui/use/auxiliary/use-from-trait-xc.rs b/src/test/ui/use/auxiliary/use-from-trait-xc.rs
new file mode 100644
index 0000000..4abe119
--- /dev/null
+++ b/src/test/ui/use/auxiliary/use-from-trait-xc.rs
@@ -0,0 +1,29 @@
+pub use self::sub::{Bar, Baz};
+
+pub trait Trait {
+    fn foo(&self);
+    type Assoc;
+    const CONST: u32;
+}
+
+struct Foo;
+
+impl Foo {
+    pub fn new() {}
+
+    pub const C: u32 = 0;
+}
+
+mod sub {
+    pub struct Bar;
+
+    impl Bar {
+        pub fn new() {}
+    }
+
+    pub enum Baz {}
+
+    impl Baz {
+        pub fn new() {}
+    }
+}
diff --git a/src/test/ui/use/issue-18986.rs b/src/test/ui/use/issue-18986.rs
new file mode 100644
index 0000000..f0b292f
--- /dev/null
+++ b/src/test/ui/use/issue-18986.rs
@@ -0,0 +1,10 @@
+// aux-build:use-from-trait-xc.rs
+
+extern crate use_from_trait_xc;
+pub use use_from_trait_xc::Trait;
+
+fn main() {
+    match () {
+        Trait { x: 42 } => () //~ ERROR expected struct, variant or union type, found trait `Trait`
+    }
+}
diff --git a/src/test/ui/use/issue-18986.stderr b/src/test/ui/use/issue-18986.stderr
new file mode 100644
index 0000000..6c23178
--- /dev/null
+++ b/src/test/ui/use/issue-18986.stderr
@@ -0,0 +1,9 @@
+error[E0574]: expected struct, variant or union type, found trait `Trait`
+  --> $DIR/issue-18986.rs:8:9
+   |
+LL |         Trait { x: 42 } => ()
+   |         ^^^^^ not a struct, variant or union type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0574`.
diff --git a/src/test/ui/use/use-after-move-based-on-type.nll.stderr b/src/test/ui/use/use-after-move-based-on-type.nll.stderr
new file mode 100644
index 0000000..520f88f
--- /dev/null
+++ b/src/test/ui/use/use-after-move-based-on-type.nll.stderr
@@ -0,0 +1,13 @@
+error[E0382]: borrow of moved value: `x`
+  --> $DIR/use-after-move-based-on-type.rs:4:20
+   |
+LL |     let x = "Hello!".to_string();
+   |         - move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
+LL |     let _y = x;
+   |              - value moved here
+LL |     println!("{}", x);
+   |                    ^ value borrowed here after move
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/use/use-after-move-based-on-type.rs b/src/test/ui/use/use-after-move-based-on-type.rs
new file mode 100644
index 0000000..fc8ea6f
--- /dev/null
+++ b/src/test/ui/use/use-after-move-based-on-type.rs
@@ -0,0 +1,5 @@
+fn main() {
+    let x = "Hello!".to_string();
+    let _y = x;
+    println!("{}", x); //~ ERROR use of moved value
+}
diff --git a/src/test/ui/use/use-after-move-based-on-type.stderr b/src/test/ui/use/use-after-move-based-on-type.stderr
new file mode 100644
index 0000000..b9e0aaf
--- /dev/null
+++ b/src/test/ui/use/use-after-move-based-on-type.stderr
@@ -0,0 +1,13 @@
+error[E0382]: use of moved value: `x`
+  --> $DIR/use-after-move-based-on-type.rs:4:20
+   |
+LL |     let _y = x;
+   |         -- value moved here
+LL |     println!("{}", x);
+   |                    ^ value used here after move
+   |
+   = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/use/use-after-move-implicity-coerced-object.nll.stderr b/src/test/ui/use/use-after-move-implicity-coerced-object.nll.stderr
new file mode 100644
index 0000000..e16bca3
--- /dev/null
+++ b/src/test/ui/use/use-after-move-implicity-coerced-object.nll.stderr
@@ -0,0 +1,14 @@
+error[E0382]: borrow of moved value: `n`
+  --> $DIR/use-after-move-implicity-coerced-object.rs:28:13
+   |
+LL |     let n: Box<_> = box Number { n: 42 };
+   |         - move occurs because `n` has type `std::boxed::Box<Number>`, which does not implement the `Copy` trait
+LL |     let mut l: Box<_> = box List { list: Vec::new() };
+LL |     l.push(n);
+   |            - value moved here
+LL |     let x = n.to_string();
+   |             ^ value borrowed here after move
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/use/use-after-move-implicity-coerced-object.rs b/src/test/ui/use/use-after-move-implicity-coerced-object.rs
new file mode 100644
index 0000000..e435069
--- /dev/null
+++ b/src/test/ui/use/use-after-move-implicity-coerced-object.rs
@@ -0,0 +1,30 @@
+#![feature(box_syntax)]
+
+use std::fmt;
+
+struct Number {
+    n: i64
+}
+
+impl fmt::Display for Number {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{}", self.n)
+    }
+}
+
+struct List {
+    list: Vec<Box<ToString+'static>> }
+
+impl List {
+    fn push(&mut self, n: Box<ToString+'static>) {
+        self.list.push(n);
+    }
+}
+
+fn main() {
+    let n: Box<_> = box Number { n: 42 };
+    let mut l: Box<_> = box List { list: Vec::new() };
+    l.push(n);
+    let x = n.to_string();
+    //~^ ERROR: use of moved value: `n`
+}
diff --git a/src/test/ui/use/use-after-move-implicity-coerced-object.stderr b/src/test/ui/use/use-after-move-implicity-coerced-object.stderr
new file mode 100644
index 0000000..babff9b
--- /dev/null
+++ b/src/test/ui/use/use-after-move-implicity-coerced-object.stderr
@@ -0,0 +1,13 @@
+error[E0382]: use of moved value: `n`
+  --> $DIR/use-after-move-implicity-coerced-object.rs:28:13
+   |
+LL |     l.push(n);
+   |            - value moved here
+LL |     let x = n.to_string();
+   |             ^ value used here after move
+   |
+   = note: move occurs because `n` has type `std::boxed::Box<Number>`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/use/use-after-move-self-based-on-type.nll.stderr b/src/test/ui/use/use-after-move-self-based-on-type.nll.stderr
new file mode 100644
index 0000000..9bf1175
--- /dev/null
+++ b/src/test/ui/use/use-after-move-self-based-on-type.nll.stderr
@@ -0,0 +1,13 @@
+error[E0382]: use of moved value: `self`
+  --> $DIR/use-after-move-self-based-on-type.rs:12:16
+   |
+LL |     pub fn foo(self) -> isize {
+   |                ---- move occurs because `self` has type `S`, which does not implement the `Copy` trait
+LL |         self.bar();
+   |         ---- value moved here
+LL |         return self.x;
+   |                ^^^^^^ value used here after move
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/use/use-after-move-self-based-on-type.rs b/src/test/ui/use/use-after-move-self-based-on-type.rs
new file mode 100644
index 0000000..4d84ae9
--- /dev/null
+++ b/src/test/ui/use/use-after-move-self-based-on-type.rs
@@ -0,0 +1,21 @@
+struct S {
+    x: isize,
+}
+
+impl Drop for S {
+    fn drop(&mut self) {}
+}
+
+impl S {
+    pub fn foo(self) -> isize {
+        self.bar();
+        return self.x;  //~ ERROR use of moved value: `self.x`
+    }
+
+    pub fn bar(self) {}
+}
+
+fn main() {
+    let x = S { x: 1 };
+    println!("{}", x.foo());
+}
diff --git a/src/test/ui/use/use-after-move-self-based-on-type.stderr b/src/test/ui/use/use-after-move-self-based-on-type.stderr
new file mode 100644
index 0000000..d1d2606
--- /dev/null
+++ b/src/test/ui/use/use-after-move-self-based-on-type.stderr
@@ -0,0 +1,13 @@
+error[E0382]: use of moved value: `self.x`
+  --> $DIR/use-after-move-self-based-on-type.rs:12:16
+   |
+LL |         self.bar();
+   |         ---- value moved here
+LL |         return self.x;
+   |                ^^^^^^ value used here after move
+   |
+   = note: move occurs because `self` has type `S`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/use/use-after-move-self.nll.stderr b/src/test/ui/use/use-after-move-self.nll.stderr
new file mode 100644
index 0000000..3be0a65
--- /dev/null
+++ b/src/test/ui/use/use-after-move-self.nll.stderr
@@ -0,0 +1,13 @@
+error[E0382]: use of moved value: `self`
+  --> $DIR/use-after-move-self.rs:10:16
+   |
+LL |     pub fn foo(self) -> isize {
+   |                ---- move occurs because `self` has type `S`, which does not implement the `Copy` trait
+LL |         self.bar();
+   |         ---- value moved here
+LL |         return *self.x;
+   |                ^^^^^^^ value used here after move
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/use/use-after-move-self.rs b/src/test/ui/use/use-after-move-self.rs
new file mode 100644
index 0000000..1337d61
--- /dev/null
+++ b/src/test/ui/use/use-after-move-self.rs
@@ -0,0 +1,19 @@
+#![feature(box_syntax)]
+
+struct S {
+    x: Box<isize>,
+}
+
+impl S {
+    pub fn foo(self) -> isize {
+        self.bar();
+        return *self.x;  //~ ERROR use of moved value: `*self.x`
+    }
+
+    pub fn bar(self) {}
+}
+
+fn main() {
+    let x = S { x: box 1 };
+    println!("{}", x.foo());
+}
diff --git a/src/test/ui/use/use-after-move-self.stderr b/src/test/ui/use/use-after-move-self.stderr
new file mode 100644
index 0000000..2c4bd20
--- /dev/null
+++ b/src/test/ui/use/use-after-move-self.stderr
@@ -0,0 +1,13 @@
+error[E0382]: use of moved value: `*self.x`
+  --> $DIR/use-after-move-self.rs:10:16
+   |
+LL |         self.bar();
+   |         ---- value moved here
+LL |         return *self.x;
+   |                ^^^^^^^ value used here after move
+   |
+   = note: move occurs because `self` has type `S`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/use/use-from-trait-xc.rs b/src/test/ui/use/use-from-trait-xc.rs
new file mode 100644
index 0000000..695ed66
--- /dev/null
+++ b/src/test/ui/use/use-from-trait-xc.rs
@@ -0,0 +1,26 @@
+// aux-build:use-from-trait-xc.rs
+
+extern crate use_from_trait_xc;
+
+use use_from_trait_xc::Trait::foo;
+//~^ ERROR `foo` is not directly importable
+
+use use_from_trait_xc::Trait::Assoc;
+//~^ ERROR `Assoc` is not directly importable
+
+use use_from_trait_xc::Trait::CONST;
+//~^ ERROR `CONST` is not directly importable
+
+use use_from_trait_xc::Foo::new; //~ ERROR struct `Foo` is private
+//~^ ERROR unresolved import `use_from_trait_xc::Foo`
+
+use use_from_trait_xc::Foo::C; //~ ERROR struct `Foo` is private
+//~^ ERROR unresolved import `use_from_trait_xc::Foo`
+
+use use_from_trait_xc::Bar::new as bnew;
+//~^ ERROR unresolved import `use_from_trait_xc::Bar`
+
+use use_from_trait_xc::Baz::new as baznew;
+//~^ ERROR unresolved import `use_from_trait_xc::Baz::new`
+
+fn main() {}
diff --git a/src/test/ui/use/use-from-trait-xc.stderr b/src/test/ui/use/use-from-trait-xc.stderr
new file mode 100644
index 0000000..97dc603
--- /dev/null
+++ b/src/test/ui/use/use-from-trait-xc.stderr
@@ -0,0 +1,58 @@
+error[E0253]: `foo` is not directly importable
+  --> $DIR/use-from-trait-xc.rs:5:5
+   |
+LL | use use_from_trait_xc::Trait::foo;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot be imported directly
+
+error[E0253]: `Assoc` is not directly importable
+  --> $DIR/use-from-trait-xc.rs:8:5
+   |
+LL | use use_from_trait_xc::Trait::Assoc;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot be imported directly
+
+error[E0253]: `CONST` is not directly importable
+  --> $DIR/use-from-trait-xc.rs:11:5
+   |
+LL | use use_from_trait_xc::Trait::CONST;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot be imported directly
+
+error[E0432]: unresolved import `use_from_trait_xc::Foo`
+  --> $DIR/use-from-trait-xc.rs:14:24
+   |
+LL | use use_from_trait_xc::Foo::new;
+   |                        ^^^ not a module `Foo`
+
+error[E0432]: unresolved import `use_from_trait_xc::Foo`
+  --> $DIR/use-from-trait-xc.rs:17:24
+   |
+LL | use use_from_trait_xc::Foo::C;
+   |                        ^^^ not a module `Foo`
+
+error[E0432]: unresolved import `use_from_trait_xc::Bar`
+  --> $DIR/use-from-trait-xc.rs:20:24
+   |
+LL | use use_from_trait_xc::Bar::new as bnew;
+   |                        ^^^ not a module `Bar`
+
+error[E0432]: unresolved import `use_from_trait_xc::Baz::new`
+  --> $DIR/use-from-trait-xc.rs:23:5
+   |
+LL | use use_from_trait_xc::Baz::new as baznew;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no `new` in `Baz`
+
+error[E0603]: struct `Foo` is private
+  --> $DIR/use-from-trait-xc.rs:14:24
+   |
+LL | use use_from_trait_xc::Foo::new;
+   |                        ^^^
+
+error[E0603]: struct `Foo` is private
+  --> $DIR/use-from-trait-xc.rs:17:24
+   |
+LL | use use_from_trait_xc::Foo::C;
+   |                        ^^^
+
+error: aborting due to 9 previous errors
+
+Some errors occurred: E0253, E0432, E0603.
+For more information about an error, try `rustc --explain E0253`.
diff --git a/src/test/ui/use/use-from-trait.rs b/src/test/ui/use/use-from-trait.rs
new file mode 100644
index 0000000..fe57872
--- /dev/null
+++ b/src/test/ui/use/use-from-trait.rs
@@ -0,0 +1,29 @@
+use Trait::foo;
+//~^ ERROR `foo` is not directly importable
+use Trait::Assoc;
+//~^ ERROR `Assoc` is not directly importable
+use Trait::C;
+//~^ ERROR `C` is not directly importable
+
+use Foo::new;
+//~^ ERROR unresolved import `Foo` [E0432]
+//~| not a module `Foo`
+
+use Foo::C2;
+//~^ ERROR unresolved import `Foo` [E0432]
+//~| not a module `Foo`
+
+pub trait Trait {
+    fn foo();
+    type Assoc;
+    const C: u32;
+}
+
+struct Foo;
+
+impl Foo {
+    fn new() {}
+    const C2: u32 = 0;
+}
+
+fn main() {}
diff --git a/src/test/ui/use/use-from-trait.stderr b/src/test/ui/use/use-from-trait.stderr
new file mode 100644
index 0000000..9e13842
--- /dev/null
+++ b/src/test/ui/use/use-from-trait.stderr
@@ -0,0 +1,34 @@
+error[E0253]: `foo` is not directly importable
+  --> $DIR/use-from-trait.rs:1:5
+   |
+LL | use Trait::foo;
+   |     ^^^^^^^^^^ cannot be imported directly
+
+error[E0253]: `Assoc` is not directly importable
+  --> $DIR/use-from-trait.rs:3:5
+   |
+LL | use Trait::Assoc;
+   |     ^^^^^^^^^^^^ cannot be imported directly
+
+error[E0253]: `C` is not directly importable
+  --> $DIR/use-from-trait.rs:5:5
+   |
+LL | use Trait::C;
+   |     ^^^^^^^^ cannot be imported directly
+
+error[E0432]: unresolved import `Foo`
+  --> $DIR/use-from-trait.rs:8:5
+   |
+LL | use Foo::new;
+   |     ^^^ not a module `Foo`
+
+error[E0432]: unresolved import `Foo`
+  --> $DIR/use-from-trait.rs:12:5
+   |
+LL | use Foo::C2;
+   |     ^^^ not a module `Foo`
+
+error: aborting due to 5 previous errors
+
+Some errors occurred: E0253, E0432.
+For more information about an error, try `rustc --explain E0253`.
diff --git a/src/test/ui/use/use-keyword.rs b/src/test/ui/use/use-keyword.rs
new file mode 100644
index 0000000..c30c2e0
--- /dev/null
+++ b/src/test/ui/use/use-keyword.rs
@@ -0,0 +1,17 @@
+// Check that imports with nakes super and self don't fail during parsing
+// FIXME: this shouldn't fail during name resolution either
+
+mod a {
+    mod b {
+        use self as A;
+        //~^ ERROR `self` imports are only allowed within a { } list
+        use super as B;
+        //~^ ERROR unresolved import `super` [E0432]
+        //~| no `super` in the root
+        use super::{self as C};
+        //~^ ERROR unresolved import `super` [E0432]
+        //~| no `super` in the root
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/use/use-keyword.stderr b/src/test/ui/use/use-keyword.stderr
new file mode 100644
index 0000000..1cb30fa
--- /dev/null
+++ b/src/test/ui/use/use-keyword.stderr
@@ -0,0 +1,22 @@
+error[E0429]: `self` imports are only allowed within a { } list
+  --> $DIR/use-keyword.rs:6:13
+   |
+LL |         use self as A;
+   |             ^^^^^^^^^
+
+error[E0432]: unresolved import `super`
+  --> $DIR/use-keyword.rs:8:13
+   |
+LL |         use super as B;
+   |             ^^^^^^^^^^ no `super` in the root
+
+error[E0432]: unresolved import `super`
+  --> $DIR/use-keyword.rs:11:21
+   |
+LL |         use super::{self as C};
+   |                     ^^^^^^^^^ no `super` in the root
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0429, E0432.
+For more information about an error, try `rustc --explain E0429`.
diff --git a/src/test/ui/use/use-meta-mismatch.rs b/src/test/ui/use/use-meta-mismatch.rs
new file mode 100644
index 0000000..459216a
--- /dev/null
+++ b/src/test/ui/use/use-meta-mismatch.rs
@@ -0,0 +1,5 @@
+// error-pattern:can't find crate for `extra`
+
+extern crate fake_crate as extra;
+
+fn main() { }
diff --git a/src/test/ui/use/use-meta-mismatch.stderr b/src/test/ui/use/use-meta-mismatch.stderr
new file mode 100644
index 0000000..877ac46
--- /dev/null
+++ b/src/test/ui/use/use-meta-mismatch.stderr
@@ -0,0 +1,9 @@
+error[E0463]: can't find crate for `extra`
+  --> $DIR/use-meta-mismatch.rs:3:1
+   |
+LL | extern crate fake_crate as extra;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't find crate
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0463`.
diff --git a/src/test/ui/use/use-mod.rs b/src/test/ui/use/use-mod.rs
new file mode 100644
index 0000000..87064c6
--- /dev/null
+++ b/src/test/ui/use/use-mod.rs
@@ -0,0 +1,19 @@
+use foo::bar::{
+    self,
+//~^ ERROR `self` import can only appear once in an import list
+    Bar,
+    self
+//~^ ERROR the name `bar` is defined multiple times
+};
+
+use {self};
+//~^ ERROR `self` import can only appear in an import list with a non-empty prefix
+
+mod foo {
+    pub mod bar {
+        pub struct Bar;
+        pub struct Baz;
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/use/use-mod.stderr b/src/test/ui/use/use-mod.stderr
new file mode 100644
index 0000000..c23ab34
--- /dev/null
+++ b/src/test/ui/use/use-mod.stderr
@@ -0,0 +1,33 @@
+error[E0430]: `self` import can only appear once in an import list
+  --> $DIR/use-mod.rs:2:5
+   |
+LL |     self,
+   |     ^^^^ can only appear once in an import list
+...
+LL |     self
+   |     ---- another `self` import appears here
+
+error[E0431]: `self` import can only appear in an import list with a non-empty prefix
+  --> $DIR/use-mod.rs:9:6
+   |
+LL | use {self};
+   |      ^^^^ can only appear in an import list with a non-empty prefix
+
+error[E0252]: the name `bar` is defined multiple times
+  --> $DIR/use-mod.rs:5:5
+   |
+LL |     self,
+   |     ---- previous import of the module `bar` here
+...
+LL |     self
+   |     ^^^^
+   |     |
+   |     `bar` reimported here
+   |     help: remove unnecessary import
+   |
+   = note: `bar` must be defined only once in the type namespace of this module
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0252, E0430, E0431.
+For more information about an error, try `rustc --explain E0252`.
diff --git a/src/test/ui/use/use-mod/use-mod-2.rs b/src/test/ui/use/use-mod/use-mod-2.rs
new file mode 100644
index 0000000..9373a62
--- /dev/null
+++ b/src/test/ui/use/use-mod/use-mod-2.rs
@@ -0,0 +1,11 @@
+mod foo {
+    use self::{self};
+    //~^ ERROR unresolved import `self` [E0432]
+    //~| no `self` in the root
+
+    use super::{self};
+    //~^ ERROR unresolved import `super` [E0432]
+    //~| no `super` in the root
+}
+
+fn main() {}
diff --git a/src/test/ui/use/use-mod/use-mod-2.stderr b/src/test/ui/use/use-mod/use-mod-2.stderr
new file mode 100644
index 0000000..8437678
--- /dev/null
+++ b/src/test/ui/use/use-mod/use-mod-2.stderr
@@ -0,0 +1,15 @@
+error[E0432]: unresolved import `self`
+  --> $DIR/use-mod-2.rs:2:16
+   |
+LL |     use self::{self};
+   |                ^^^^ no `self` in the root
+
+error[E0432]: unresolved import `super`
+  --> $DIR/use-mod-2.rs:6:17
+   |
+LL |     use super::{self};
+   |                 ^^^^ no `super` in the root
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/use/use-mod/use-mod-3.rs b/src/test/ui/use/use-mod/use-mod-3.rs
new file mode 100644
index 0000000..0afa486
--- /dev/null
+++ b/src/test/ui/use/use-mod/use-mod-3.rs
@@ -0,0 +1,12 @@
+use foo::bar::{ //~ ERROR module `bar` is private
+    self
+};
+use foo::bar::{ //~ ERROR module `bar` is private
+    Bar
+};
+
+mod foo {
+    mod bar { pub type Bar = isize; }
+}
+
+fn main() {}
diff --git a/src/test/ui/use/use-mod/use-mod-3.stderr b/src/test/ui/use/use-mod/use-mod-3.stderr
new file mode 100644
index 0000000..0c800ec
--- /dev/null
+++ b/src/test/ui/use/use-mod/use-mod-3.stderr
@@ -0,0 +1,15 @@
+error[E0603]: module `bar` is private
+  --> $DIR/use-mod-3.rs:1:10
+   |
+LL | use foo::bar::{
+   |          ^^^
+
+error[E0603]: module `bar` is private
+  --> $DIR/use-mod-3.rs:4:10
+   |
+LL | use foo::bar::{
+   |          ^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0603`.
diff --git a/src/test/ui/use/use-mod/use-mod-4.rs b/src/test/ui/use/use-mod/use-mod-4.rs
new file mode 100644
index 0000000..46ae8dd
--- /dev/null
+++ b/src/test/ui/use/use-mod/use-mod-4.rs
@@ -0,0 +1,7 @@
+use foo::self; //~ ERROR unresolved import `foo`
+//~^ ERROR `self` imports are only allowed within a { } list
+
+use std::mem::self;
+//~^ ERROR `self` imports are only allowed within a { } list
+
+fn main() {}
diff --git a/src/test/ui/use/use-mod/use-mod-4.stderr b/src/test/ui/use/use-mod/use-mod-4.stderr
new file mode 100644
index 0000000..99f5c35
--- /dev/null
+++ b/src/test/ui/use/use-mod/use-mod-4.stderr
@@ -0,0 +1,22 @@
+error[E0429]: `self` imports are only allowed within a { } list
+  --> $DIR/use-mod-4.rs:1:5
+   |
+LL | use foo::self;
+   |     ^^^^^^^^^
+
+error[E0429]: `self` imports are only allowed within a { } list
+  --> $DIR/use-mod-4.rs:4:5
+   |
+LL | use std::mem::self;
+   |     ^^^^^^^^^^^^^^
+
+error[E0432]: unresolved import `foo`
+  --> $DIR/use-mod-4.rs:1:5
+   |
+LL | use foo::self;
+   |     ^^^ maybe a missing `extern crate foo;`?
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0429, E0432.
+For more information about an error, try `rustc --explain E0429`.
diff --git a/src/test/ui/use/use-nested-groups-error.rs b/src/test/ui/use/use-nested-groups-error.rs
new file mode 100644
index 0000000..d8b189d
--- /dev/null
+++ b/src/test/ui/use/use-nested-groups-error.rs
@@ -0,0 +1,15 @@
+mod a {
+    pub mod b1 {
+        pub enum C2 {}
+    }
+
+    pub enum B2 {}
+}
+
+use a::{b1::{C1, C2}, B2};
+//~^ ERROR unresolved import `a::b1::C1`
+
+fn main() {
+    let _: C2;
+    let _: B2;
+}
diff --git a/src/test/ui/use/use-nested-groups-error.stderr b/src/test/ui/use/use-nested-groups-error.stderr
new file mode 100644
index 0000000..7234c8e
--- /dev/null
+++ b/src/test/ui/use/use-nested-groups-error.stderr
@@ -0,0 +1,12 @@
+error[E0432]: unresolved import `a::b1::C1`
+  --> $DIR/use-nested-groups-error.rs:9:14
+   |
+LL | use a::{b1::{C1, C2}, B2};
+   |              ^^
+   |              |
+   |              no `C1` in `a::b1`
+   |              help: a similar name exists in the module: `C2`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/use/use-nested-groups-unused-imports.rs b/src/test/ui/use/use-nested-groups-unused-imports.rs
new file mode 100644
index 0000000..5fe8595
--- /dev/null
+++ b/src/test/ui/use/use-nested-groups-unused-imports.rs
@@ -0,0 +1,25 @@
+#![feature(use_nested_groups)]
+#![allow(dead_code)]
+#![deny(unused_imports)]
+
+mod foo {
+    pub mod bar {
+        pub mod baz {
+            pub struct Bar();
+        }
+        pub mod foobar {}
+    }
+
+    pub struct Foo();
+}
+
+use foo::{Foo, bar::{baz::{}, foobar::*}, *};
+    //~^ ERROR unused imports: `*`, `Foo`, `baz::{}`, `foobar::*`
+use foo::bar::baz::{*, *};
+    //~^ ERROR unused import: `*`
+use foo::{};
+    //~^ ERROR unused import: `foo::{}`
+
+fn main() {
+    let _: Bar;
+}
diff --git a/src/test/ui/use/use-nested-groups-unused-imports.stderr b/src/test/ui/use/use-nested-groups-unused-imports.stderr
new file mode 100644
index 0000000..c8df6cb
--- /dev/null
+++ b/src/test/ui/use/use-nested-groups-unused-imports.stderr
@@ -0,0 +1,26 @@
+error: unused imports: `*`, `Foo`, `baz::{}`, `foobar::*`
+  --> $DIR/use-nested-groups-unused-imports.rs:16:11
+   |
+LL | use foo::{Foo, bar::{baz::{}, foobar::*}, *};
+   |           ^^^        ^^^^^^^  ^^^^^^^^^   ^
+   |
+note: lint level defined here
+  --> $DIR/use-nested-groups-unused-imports.rs:3:9
+   |
+LL | #![deny(unused_imports)]
+   |         ^^^^^^^^^^^^^^
+
+error: unused import: `*`
+  --> $DIR/use-nested-groups-unused-imports.rs:18:24
+   |
+LL | use foo::bar::baz::{*, *};
+   |                        ^
+
+error: unused import: `foo::{}`
+  --> $DIR/use-nested-groups-unused-imports.rs:20:5
+   |
+LL | use foo::{};
+   |     ^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/use/use-paths-as-items.rs b/src/test/ui/use/use-paths-as-items.rs
new file mode 100644
index 0000000..7b5eb56
--- /dev/null
+++ b/src/test/ui/use/use-paths-as-items.rs
@@ -0,0 +1,9 @@
+// Each path node in a `use` declaration must be treated as an item. If not, the following code
+// will trigger an ICE.
+//
+// Related issue: #25763
+
+use std::{mem, ptr};
+use std::mem; //~ ERROR the name `mem` is defined multiple times
+
+fn main() {}
diff --git a/src/test/ui/use/use-paths-as-items.stderr b/src/test/ui/use/use-paths-as-items.stderr
new file mode 100644
index 0000000..b09001a
--- /dev/null
+++ b/src/test/ui/use/use-paths-as-items.stderr
@@ -0,0 +1,13 @@
+error[E0252]: the name `mem` is defined multiple times
+  --> $DIR/use-paths-as-items.rs:7:5
+   |
+LL | use std::{mem, ptr};
+   |           --- previous import of the module `mem` here
+LL | use std::mem;
+   |     ^^^^^^^^ `mem` reimported here
+   |
+   = note: `mem` must be defined only once in the type namespace of this module
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0252`.
diff --git a/src/test/ui/use/use-self-type.rs b/src/test/ui/use/use-self-type.rs
new file mode 100644
index 0000000..3e5c7bf
--- /dev/null
+++ b/src/test/ui/use/use-self-type.rs
@@ -0,0 +1,11 @@
+struct S;
+
+impl S {
+    fn f() {}
+    fn g() {
+        use Self::f; //~ ERROR unresolved import
+        pub(in Self::f) struct Z; //~ ERROR use of undeclared type or module `Self`
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/use/use-self-type.stderr b/src/test/ui/use/use-self-type.stderr
new file mode 100644
index 0000000..38c09c2
--- /dev/null
+++ b/src/test/ui/use/use-self-type.stderr
@@ -0,0 +1,16 @@
+error[E0433]: failed to resolve: use of undeclared type or module `Self`
+  --> $DIR/use-self-type.rs:7:16
+   |
+LL |         pub(in Self::f) struct Z;
+   |                ^^^^ use of undeclared type or module `Self`
+
+error[E0432]: unresolved import `Self`
+  --> $DIR/use-self-type.rs:6:13
+   |
+LL |         use Self::f;
+   |             ^^^^ use of undeclared type or module `Self`
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0432, E0433.
+For more information about an error, try `rustc --explain E0432`.
diff --git a/src/test/ui/use/use-super-global-path.rs b/src/test/ui/use/use-super-global-path.rs
new file mode 100644
index 0000000..3e0ebcc
--- /dev/null
+++ b/src/test/ui/use/use-super-global-path.rs
@@ -0,0 +1,15 @@
+#![allow(unused)]
+
+struct S;
+struct Z;
+
+mod foo {
+    use ::super::{S, Z}; //~ ERROR global paths cannot start with `super`
+
+    pub fn g() {
+        use ::super::main; //~ ERROR global paths cannot start with `super`
+        main(); //~ ERROR cannot find function `main` in this scope
+    }
+}
+
+fn main() { foo::g(); }
diff --git a/src/test/ui/use/use-super-global-path.stderr b/src/test/ui/use/use-super-global-path.stderr
new file mode 100644
index 0000000..a513d37
--- /dev/null
+++ b/src/test/ui/use/use-super-global-path.stderr
@@ -0,0 +1,26 @@
+error[E0433]: failed to resolve: global paths cannot start with `super`
+  --> $DIR/use-super-global-path.rs:7:11
+   |
+LL |     use ::super::{S, Z};
+   |           ^^^^^ global paths cannot start with `super`
+
+error[E0433]: failed to resolve: global paths cannot start with `super`
+  --> $DIR/use-super-global-path.rs:10:15
+   |
+LL |         use ::super::main;
+   |               ^^^^^ global paths cannot start with `super`
+
+error[E0425]: cannot find function `main` in this scope
+  --> $DIR/use-super-global-path.rs:11:9
+   |
+LL |         main();
+   |         ^^^^ not found in this scope
+help: possible candidate is found in another module, you can import it into scope
+   |
+LL |     use main;
+   |
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0425, E0433.
+For more information about an error, try `rustc --explain E0425`.
diff --git a/src/test/ui/used.rs b/src/test/ui/used.rs
new file mode 100644
index 0000000..f008724
--- /dev/null
+++ b/src/test/ui/used.rs
@@ -0,0 +1,16 @@
+#[used]
+static FOO: u32 = 0; // OK
+
+#[used] //~ ERROR attribute must be applied to a `static` variable
+fn foo() {}
+
+#[used] //~ ERROR attribute must be applied to a `static` variable
+struct Foo {}
+
+#[used] //~ ERROR attribute must be applied to a `static` variable
+trait Bar {}
+
+#[used] //~ ERROR attribute must be applied to a `static` variable
+impl Bar for Foo {}
+
+fn main() {}
diff --git a/src/test/ui/used.stderr b/src/test/ui/used.stderr
new file mode 100644
index 0000000..ea77f12
--- /dev/null
+++ b/src/test/ui/used.stderr
@@ -0,0 +1,26 @@
+error: attribute must be applied to a `static` variable
+  --> $DIR/used.rs:4:1
+   |
+LL | #[used]
+   | ^^^^^^^
+
+error: attribute must be applied to a `static` variable
+  --> $DIR/used.rs:7:1
+   |
+LL | #[used]
+   | ^^^^^^^
+
+error: attribute must be applied to a `static` variable
+  --> $DIR/used.rs:10:1
+   |
+LL | #[used]
+   | ^^^^^^^
+
+error: attribute must be applied to a `static` variable
+  --> $DIR/used.rs:13:1
+   |
+LL | #[used]
+   | ^^^^^^^
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/useless-comment.rs b/src/test/ui/useless-comment.rs
new file mode 100644
index 0000000..7d2e5ab
--- /dev/null
+++ b/src/test/ui/useless-comment.rs
@@ -0,0 +1,45 @@
+#![feature(stmt_expr_attributes)]
+
+#![deny(unused_doc_comments)]
+
+macro_rules! mac {
+    () => {}
+}
+
+/// foo //~ ERROR unused doc comment
+mac!();
+
+fn foo() {
+    /// a //~ ERROR unused doc comment
+    let x = 12;
+
+    /// multi-line //~ unused doc comment
+    /// doc comment
+    /// that is unused
+    match x {
+        /// c //~ ERROR unused doc comment
+        1 => {},
+        _ => {}
+    }
+
+    /// foo //~ ERROR unused doc comment
+    unsafe {}
+
+    #[doc = "foo"] //~ ERROR unused doc comment
+    #[doc = "bar"] //~ ERROR unused doc comment
+    3;
+
+    /// bar //~ ERROR unused doc comment
+    mac!();
+
+    let x = /** comment */ 47; //~ ERROR unused doc comment
+
+    /// dox //~ ERROR unused doc comment
+    {
+
+    }
+}
+
+fn main() {
+    foo();
+}
diff --git a/src/test/ui/useless-comment.stderr b/src/test/ui/useless-comment.stderr
new file mode 100644
index 0000000..925e307
--- /dev/null
+++ b/src/test/ui/useless-comment.stderr
@@ -0,0 +1,98 @@
+error: unused doc comment
+  --> $DIR/useless-comment.rs:9:1
+   |
+LL | /// foo
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | mac!();
+   | ------- rustdoc does not generate documentation for macro expansions
+   |
+note: lint level defined here
+  --> $DIR/useless-comment.rs:3:9
+   |
+LL | #![deny(unused_doc_comments)]
+   |         ^^^^^^^^^^^^^^^^^^^
+   = help: to document an item produced by a macro, the macro must produce the documentation as part of its expansion
+
+error: unused doc comment
+  --> $DIR/useless-comment.rs:13:5
+   |
+LL |     /// a
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     let x = 12;
+   |     ----------- rustdoc does not generate documentation for statements
+
+error: unused doc comment
+  --> $DIR/useless-comment.rs:16:5
+   |
+LL | /     /// multi-line
+LL | |     /// doc comment
+LL | |     /// that is unused
+   | |______________________^
+LL | /     match x {
+LL | |         /// c
+LL | |         1 => {},
+LL | |         _ => {}
+LL | |     }
+   | |_____- rustdoc does not generate documentation for expressions
+
+error: unused doc comment
+  --> $DIR/useless-comment.rs:20:9
+   |
+LL |         /// c
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |         1 => {},
+   |         ------- rustdoc does not generate documentation for match arms
+
+error: unused doc comment
+  --> $DIR/useless-comment.rs:25:5
+   |
+LL |     /// foo
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     unsafe {}
+   |     --------- rustdoc does not generate documentation for expressions
+
+error: unused doc comment
+  --> $DIR/useless-comment.rs:28:5
+   |
+LL |     #[doc = "foo"]
+   |     ^^^^^^^^^^^^^^
+LL |     #[doc = "bar"]
+LL |     3;
+   |     - rustdoc does not generate documentation for expressions
+
+error: unused doc comment
+  --> $DIR/useless-comment.rs:29:5
+   |
+LL |     #[doc = "bar"]
+   |     ^^^^^^^^^^^^^^
+LL |     3;
+   |     - rustdoc does not generate documentation for expressions
+
+error: unused doc comment
+  --> $DIR/useless-comment.rs:32:5
+   |
+LL |     /// bar
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     mac!();
+   |     ------- rustdoc does not generate documentation for macro expansions
+   |
+   = help: to document an item produced by a macro, the macro must produce the documentation as part of its expansion
+
+error: unused doc comment
+  --> $DIR/useless-comment.rs:35:13
+   |
+LL |     let x = /** comment */ 47;
+   |             ^^^^^^^^^^^^^^ -- rustdoc does not generate documentation for expressions
+
+error: unused doc comment
+  --> $DIR/useless-comment.rs:37:5
+   |
+LL |       /// dox
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | /     {
+LL | |
+LL | |     }
+   | |_____- rustdoc does not generate documentation for expressions
+
+error: aborting due to 10 previous errors
+
diff --git a/src/test/ui/useless-pub.rs b/src/test/ui/useless-pub.rs
new file mode 100644
index 0000000..fde7cd5
--- /dev/null
+++ b/src/test/ui/useless-pub.rs
@@ -0,0 +1,16 @@
+struct A { pub i: isize }
+
+pub trait E {
+    fn foo(&self);
+}
+
+impl E for A {
+    pub fn foo(&self) {} //~ ERROR: unnecessary visibility qualifier
+}
+
+enum Foo {
+    V1 { pub f: i32 }, //~ ERROR unnecessary visibility qualifier
+    V2(pub i32), //~ ERROR unnecessary visibility qualifier
+}
+
+fn main() {}
diff --git a/src/test/ui/useless-pub.stderr b/src/test/ui/useless-pub.stderr
new file mode 100644
index 0000000..14c4983
--- /dev/null
+++ b/src/test/ui/useless-pub.stderr
@@ -0,0 +1,21 @@
+error[E0449]: unnecessary visibility qualifier
+  --> $DIR/useless-pub.rs:8:5
+   |
+LL |     pub fn foo(&self) {}
+   |     ^^^ `pub` not permitted here because it's implied
+
+error[E0449]: unnecessary visibility qualifier
+  --> $DIR/useless-pub.rs:12:10
+   |
+LL |     V1 { pub f: i32 },
+   |          ^^^ `pub` not permitted here because it's implied
+
+error[E0449]: unnecessary visibility qualifier
+  --> $DIR/useless-pub.rs:13:8
+   |
+LL |     V2(pub i32),
+   |        ^^^ `pub` not permitted here because it's implied
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0449`.
diff --git a/src/test/ui/user-defined-macro-rules.rs b/src/test/ui/user-defined-macro-rules.rs
new file mode 100644
index 0000000..31bfdd0
--- /dev/null
+++ b/src/test/ui/user-defined-macro-rules.rs
@@ -0,0 +1,5 @@
+#![allow(unused_macros)]
+
+macro_rules! macro_rules { () => {} } //~ ERROR user-defined macros may not be named `macro_rules`
+
+fn main() {}
diff --git a/src/test/ui/user-defined-macro-rules.stderr b/src/test/ui/user-defined-macro-rules.stderr
new file mode 100644
index 0000000..0575152
--- /dev/null
+++ b/src/test/ui/user-defined-macro-rules.stderr
@@ -0,0 +1,8 @@
+error: user-defined macros may not be named `macro_rules`
+  --> $DIR/user-defined-macro-rules.rs:3:1
+   |
+LL | macro_rules! macro_rules { () => {} }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/utf8_idents.rs b/src/test/ui/utf8_idents.rs
new file mode 100644
index 0000000..f59d550
--- /dev/null
+++ b/src/test/ui/utf8_idents.rs
@@ -0,0 +1,13 @@
+fn foo<
+    'β, //~ ERROR non-ascii idents are not fully supported
+    γ  //~ ERROR non-ascii idents are not fully supported
+       //~^ WARN type parameter `γ` should have an upper camel case name
+>() {}
+
+struct X {
+    δ: usize //~ ERROR non-ascii idents are not fully supported
+}
+
+pub fn main() {
+    let α = 0.00001f64; //~ ERROR non-ascii idents are not fully supported
+}
diff --git a/src/test/ui/utf8_idents.stderr b/src/test/ui/utf8_idents.stderr
new file mode 100644
index 0000000..330ba3e
--- /dev/null
+++ b/src/test/ui/utf8_idents.stderr
@@ -0,0 +1,43 @@
+error[E0658]: non-ascii idents are not fully supported. (see issue #55467)
+  --> $DIR/utf8_idents.rs:2:5
+   |
+LL |     'β,
+   |     ^^
+   |
+   = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
+
+error[E0658]: non-ascii idents are not fully supported. (see issue #55467)
+  --> $DIR/utf8_idents.rs:3:5
+   |
+LL |     γ
+   |     ^
+   |
+   = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
+
+error[E0658]: non-ascii idents are not fully supported. (see issue #55467)
+  --> $DIR/utf8_idents.rs:8:5
+   |
+LL |     δ: usize
+   |     ^
+   |
+   = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
+
+error[E0658]: non-ascii idents are not fully supported. (see issue #55467)
+  --> $DIR/utf8_idents.rs:12:9
+   |
+LL |     let α = 0.00001f64;
+   |         ^
+   |
+   = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
+
+warning: type parameter `γ` should have an upper camel case name
+  --> $DIR/utf8_idents.rs:3:5
+   |
+LL |     γ
+   |     ^ help: convert the identifier to upper camel case: `Γ`
+   |
+   = note: #[warn(non_camel_case_types)] on by default
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/variance/variance-associated-types.rs b/src/test/ui/variance/variance-associated-types.rs
new file mode 100644
index 0000000..1165fb5
--- /dev/null
+++ b/src/test/ui/variance/variance-associated-types.rs
@@ -0,0 +1,22 @@
+// Test that the variance computation considers types/regions that
+// appear in projections to be invariant.
+
+#![feature(rustc_attrs)]
+
+trait Trait<'a> {
+    type Type;
+
+    fn method(&'a self) { }
+}
+
+#[rustc_variance]
+struct Foo<'a, T : Trait<'a>> { //~ ERROR [-, +]
+    field: (T, &'a ())
+}
+
+#[rustc_variance]
+struct Bar<'a, T : Trait<'a>> { //~ ERROR [o, o]
+    field: <T as Trait<'a>>::Type
+}
+
+fn main() { }
diff --git a/src/test/ui/variance/variance-associated-types.stderr b/src/test/ui/variance/variance-associated-types.stderr
new file mode 100644
index 0000000..c0231ae
--- /dev/null
+++ b/src/test/ui/variance/variance-associated-types.stderr
@@ -0,0 +1,19 @@
+error[E0208]: [-, +]
+  --> $DIR/variance-associated-types.rs:13:1
+   |
+LL | / struct Foo<'a, T : Trait<'a>> {
+LL | |     field: (T, &'a ())
+LL | | }
+   | |_^
+
+error[E0208]: [o, o]
+  --> $DIR/variance-associated-types.rs:18:1
+   |
+LL | / struct Bar<'a, T : Trait<'a>> {
+LL | |     field: <T as Trait<'a>>::Type
+LL | | }
+   | |_^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0208`.
diff --git a/src/test/ui/variance/variance-btree-invariant-types.rs b/src/test/ui/variance/variance-btree-invariant-types.rs
new file mode 100644
index 0000000..2e5dc67
--- /dev/null
+++ b/src/test/ui/variance/variance-btree-invariant-types.rs
@@ -0,0 +1,51 @@
+use std::collections::btree_map::{IterMut, OccupiedEntry, VacantEntry};
+
+fn iter_cov_key<'a, 'new>(v: IterMut<'a, &'static (), ()>) -> IterMut<'a, &'new (), ()> {
+    v //~ ERROR mismatched types
+}
+fn iter_cov_val<'a, 'new>(v: IterMut<'a, (), &'static ()>) -> IterMut<'a, (), &'new ()> {
+    v //~ ERROR mismatched types
+}
+fn iter_contra_key<'a, 'new>(v: IterMut<'a, &'new (), ()>) -> IterMut<'a, &'static (), ()> {
+    v //~ ERROR mismatched types
+}
+fn iter_contra_val<'a, 'new>(v: IterMut<'a, (), &'new ()>) -> IterMut<'a, (), &'static ()> {
+    v //~ ERROR mismatched types
+}
+
+fn occ_cov_key<'a, 'new>(v: OccupiedEntry<'a, &'static (), ()>)
+                         -> OccupiedEntry<'a, &'new (), ()> {
+    v //~ ERROR mismatched types
+}
+fn occ_cov_val<'a, 'new>(v: OccupiedEntry<'a, (), &'static ()>)
+                         -> OccupiedEntry<'a, (), &'new ()> {
+    v //~ ERROR mismatched types
+}
+fn occ_contra_key<'a, 'new>(v: OccupiedEntry<'a, &'new (), ()>)
+                            -> OccupiedEntry<'a, &'static (), ()> {
+    v //~ ERROR mismatched types
+}
+fn occ_contra_val<'a, 'new>(v: OccupiedEntry<'a, (), &'new ()>)
+                            -> OccupiedEntry<'a, (), &'static ()> {
+    v //~ ERROR mismatched types
+}
+
+fn vac_cov_key<'a, 'new>(v: VacantEntry<'a, &'static (), ()>)
+                         -> VacantEntry<'a, &'new (), ()> {
+    v //~ ERROR mismatched types
+}
+fn vac_cov_val<'a, 'new>(v: VacantEntry<'a, (), &'static ()>)
+                         -> VacantEntry<'a, (), &'new ()> {
+    v //~ ERROR mismatched types
+}
+fn vac_contra_key<'a, 'new>(v: VacantEntry<'a, &'new (), ()>)
+                            -> VacantEntry<'a, &'static (), ()> {
+    v //~ ERROR mismatched types
+}
+fn vac_contra_val<'a, 'new>(v: VacantEntry<'a, (), &'new ()>)
+                            -> VacantEntry<'a, (), &'static ()> {
+    v //~ ERROR mismatched types
+}
+
+
+fn main() { }
diff --git a/src/test/ui/variance/variance-btree-invariant-types.stderr b/src/test/ui/variance/variance-btree-invariant-types.stderr
new file mode 100644
index 0000000..49222fc
--- /dev/null
+++ b/src/test/ui/variance/variance-btree-invariant-types.stderr
@@ -0,0 +1,183 @@
+error[E0308]: mismatched types
+  --> $DIR/variance-btree-invariant-types.rs:4:5
+   |
+LL |     v
+   |     ^ lifetime mismatch
+   |
+   = note: expected type `std::collections::btree_map::IterMut<'_, &'new (), _>`
+              found type `std::collections::btree_map::IterMut<'_, &'static (), _>`
+note: the lifetime 'new as defined on the function body at 3:21...
+  --> $DIR/variance-btree-invariant-types.rs:3:21
+   |
+LL | fn iter_cov_key<'a, 'new>(v: IterMut<'a, &'static (), ()>) -> IterMut<'a, &'new (), ()> {
+   |                     ^^^^
+   = note: ...does not necessarily outlive the static lifetime
+
+error[E0308]: mismatched types
+  --> $DIR/variance-btree-invariant-types.rs:7:5
+   |
+LL |     v
+   |     ^ lifetime mismatch
+   |
+   = note: expected type `std::collections::btree_map::IterMut<'_, _, &'new ()>`
+              found type `std::collections::btree_map::IterMut<'_, _, &'static ()>`
+note: the lifetime 'new as defined on the function body at 6:21...
+  --> $DIR/variance-btree-invariant-types.rs:6:21
+   |
+LL | fn iter_cov_val<'a, 'new>(v: IterMut<'a, (), &'static ()>) -> IterMut<'a, (), &'new ()> {
+   |                     ^^^^
+   = note: ...does not necessarily outlive the static lifetime
+
+error[E0308]: mismatched types
+  --> $DIR/variance-btree-invariant-types.rs:10:5
+   |
+LL |     v
+   |     ^ lifetime mismatch
+   |
+   = note: expected type `std::collections::btree_map::IterMut<'_, &'static (), _>`
+              found type `std::collections::btree_map::IterMut<'_, &'new (), _>`
+note: the lifetime 'new as defined on the function body at 9:24...
+  --> $DIR/variance-btree-invariant-types.rs:9:24
+   |
+LL | fn iter_contra_key<'a, 'new>(v: IterMut<'a, &'new (), ()>) -> IterMut<'a, &'static (), ()> {
+   |                        ^^^^
+   = note: ...does not necessarily outlive the static lifetime
+
+error[E0308]: mismatched types
+  --> $DIR/variance-btree-invariant-types.rs:13:5
+   |
+LL |     v
+   |     ^ lifetime mismatch
+   |
+   = note: expected type `std::collections::btree_map::IterMut<'_, _, &'static ()>`
+              found type `std::collections::btree_map::IterMut<'_, _, &'new ()>`
+note: the lifetime 'new as defined on the function body at 12:24...
+  --> $DIR/variance-btree-invariant-types.rs:12:24
+   |
+LL | fn iter_contra_val<'a, 'new>(v: IterMut<'a, (), &'new ()>) -> IterMut<'a, (), &'static ()> {
+   |                        ^^^^
+   = note: ...does not necessarily outlive the static lifetime
+
+error[E0308]: mismatched types
+  --> $DIR/variance-btree-invariant-types.rs:18:5
+   |
+LL |     v
+   |     ^ lifetime mismatch
+   |
+   = note: expected type `std::collections::btree_map::OccupiedEntry<'_, &'new (), _>`
+              found type `std::collections::btree_map::OccupiedEntry<'_, &'static (), _>`
+note: the lifetime 'new as defined on the function body at 16:20...
+  --> $DIR/variance-btree-invariant-types.rs:16:20
+   |
+LL | fn occ_cov_key<'a, 'new>(v: OccupiedEntry<'a, &'static (), ()>)
+   |                    ^^^^
+   = note: ...does not necessarily outlive the static lifetime
+
+error[E0308]: mismatched types
+  --> $DIR/variance-btree-invariant-types.rs:22:5
+   |
+LL |     v
+   |     ^ lifetime mismatch
+   |
+   = note: expected type `std::collections::btree_map::OccupiedEntry<'_, _, &'new ()>`
+              found type `std::collections::btree_map::OccupiedEntry<'_, _, &'static ()>`
+note: the lifetime 'new as defined on the function body at 20:20...
+  --> $DIR/variance-btree-invariant-types.rs:20:20
+   |
+LL | fn occ_cov_val<'a, 'new>(v: OccupiedEntry<'a, (), &'static ()>)
+   |                    ^^^^
+   = note: ...does not necessarily outlive the static lifetime
+
+error[E0308]: mismatched types
+  --> $DIR/variance-btree-invariant-types.rs:26:5
+   |
+LL |     v
+   |     ^ lifetime mismatch
+   |
+   = note: expected type `std::collections::btree_map::OccupiedEntry<'_, &'static (), _>`
+              found type `std::collections::btree_map::OccupiedEntry<'_, &'new (), _>`
+note: the lifetime 'new as defined on the function body at 24:23...
+  --> $DIR/variance-btree-invariant-types.rs:24:23
+   |
+LL | fn occ_contra_key<'a, 'new>(v: OccupiedEntry<'a, &'new (), ()>)
+   |                       ^^^^
+   = note: ...does not necessarily outlive the static lifetime
+
+error[E0308]: mismatched types
+  --> $DIR/variance-btree-invariant-types.rs:30:5
+   |
+LL |     v
+   |     ^ lifetime mismatch
+   |
+   = note: expected type `std::collections::btree_map::OccupiedEntry<'_, _, &'static ()>`
+              found type `std::collections::btree_map::OccupiedEntry<'_, _, &'new ()>`
+note: the lifetime 'new as defined on the function body at 28:23...
+  --> $DIR/variance-btree-invariant-types.rs:28:23
+   |
+LL | fn occ_contra_val<'a, 'new>(v: OccupiedEntry<'a, (), &'new ()>)
+   |                       ^^^^
+   = note: ...does not necessarily outlive the static lifetime
+
+error[E0308]: mismatched types
+  --> $DIR/variance-btree-invariant-types.rs:35:5
+   |
+LL |     v
+   |     ^ lifetime mismatch
+   |
+   = note: expected type `std::collections::btree_map::VacantEntry<'_, &'new (), _>`
+              found type `std::collections::btree_map::VacantEntry<'_, &'static (), _>`
+note: the lifetime 'new as defined on the function body at 33:20...
+  --> $DIR/variance-btree-invariant-types.rs:33:20
+   |
+LL | fn vac_cov_key<'a, 'new>(v: VacantEntry<'a, &'static (), ()>)
+   |                    ^^^^
+   = note: ...does not necessarily outlive the static lifetime
+
+error[E0308]: mismatched types
+  --> $DIR/variance-btree-invariant-types.rs:39:5
+   |
+LL |     v
+   |     ^ lifetime mismatch
+   |
+   = note: expected type `std::collections::btree_map::VacantEntry<'_, _, &'new ()>`
+              found type `std::collections::btree_map::VacantEntry<'_, _, &'static ()>`
+note: the lifetime 'new as defined on the function body at 37:20...
+  --> $DIR/variance-btree-invariant-types.rs:37:20
+   |
+LL | fn vac_cov_val<'a, 'new>(v: VacantEntry<'a, (), &'static ()>)
+   |                    ^^^^
+   = note: ...does not necessarily outlive the static lifetime
+
+error[E0308]: mismatched types
+  --> $DIR/variance-btree-invariant-types.rs:43:5
+   |
+LL |     v
+   |     ^ lifetime mismatch
+   |
+   = note: expected type `std::collections::btree_map::VacantEntry<'_, &'static (), _>`
+              found type `std::collections::btree_map::VacantEntry<'_, &'new (), _>`
+note: the lifetime 'new as defined on the function body at 41:23...
+  --> $DIR/variance-btree-invariant-types.rs:41:23
+   |
+LL | fn vac_contra_key<'a, 'new>(v: VacantEntry<'a, &'new (), ()>)
+   |                       ^^^^
+   = note: ...does not necessarily outlive the static lifetime
+
+error[E0308]: mismatched types
+  --> $DIR/variance-btree-invariant-types.rs:47:5
+   |
+LL |     v
+   |     ^ lifetime mismatch
+   |
+   = note: expected type `std::collections::btree_map::VacantEntry<'_, _, &'static ()>`
+              found type `std::collections::btree_map::VacantEntry<'_, _, &'new ()>`
+note: the lifetime 'new as defined on the function body at 45:23...
+  --> $DIR/variance-btree-invariant-types.rs:45:23
+   |
+LL | fn vac_contra_val<'a, 'new>(v: VacantEntry<'a, (), &'new ()>)
+   |                       ^^^^
+   = note: ...does not necessarily outlive the static lifetime
+
+error: aborting due to 12 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/variance/variance-cell-is-invariant.rs b/src/test/ui/variance/variance-cell-is-invariant.rs
new file mode 100644
index 0000000..ff9ad66
--- /dev/null
+++ b/src/test/ui/variance/variance-cell-is-invariant.rs
@@ -0,0 +1,18 @@
+// Test that Cell is considered invariant with respect to its
+// type.
+
+use std::cell::Cell;
+
+struct Foo<'a> {
+    x: Cell<Option<&'a isize>>,
+}
+
+fn use_<'short,'long>(c: Foo<'short>,
+                      s: &'short isize,
+                      l: &'long isize,
+                      _where:Option<&'short &'long ()>) {
+    let _: Foo<'long> = c; //~ ERROR E0623
+}
+
+fn main() {
+}
diff --git a/src/test/ui/variance/variance-cell-is-invariant.stderr b/src/test/ui/variance/variance-cell-is-invariant.stderr
new file mode 100644
index 0000000..6fcd646
--- /dev/null
+++ b/src/test/ui/variance/variance-cell-is-invariant.stderr
@@ -0,0 +1,15 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/variance-cell-is-invariant.rs:14:25
+   |
+LL | fn use_<'short,'long>(c: Foo<'short>,
+   |                          ----------- these two types are declared with different lifetimes...
+LL |                       s: &'short isize,
+LL |                       l: &'long isize,
+   |                          ------------
+LL |                       _where:Option<&'short &'long ()>) {
+LL |     let _: Foo<'long> = c;
+   |                         ^ ...but data from `c` flows into `l` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/variance/variance-contravariant-arg-object.rs b/src/test/ui/variance/variance-contravariant-arg-object.rs
new file mode 100644
index 0000000..27e5675
--- /dev/null
+++ b/src/test/ui/variance/variance-contravariant-arg-object.rs
@@ -0,0 +1,25 @@
+#![allow(dead_code)]
+
+// Test that even when `T` is only used in contravariant position, it
+// is treated as invariant.
+
+trait Get<T> : 'static {
+    fn get(&self, t: T);
+}
+
+fn get_min_from_max<'min, 'max>(v: Box<Get<&'max i32>>)
+                                -> Box<Get<&'min i32>>
+    where 'max : 'min
+{
+    v //~ ERROR mismatched types
+}
+
+fn get_max_from_min<'min, 'max, G>(v: Box<Get<&'min i32>>)
+                                   -> Box<Get<&'max i32>>
+    where 'max : 'min
+{
+    // Previously OK:
+    v //~ ERROR mismatched types
+}
+
+fn main() { }
diff --git a/src/test/ui/variance/variance-contravariant-arg-object.stderr b/src/test/ui/variance/variance-contravariant-arg-object.stderr
new file mode 100644
index 0000000..beac05e
--- /dev/null
+++ b/src/test/ui/variance/variance-contravariant-arg-object.stderr
@@ -0,0 +1,41 @@
+error[E0308]: mismatched types
+  --> $DIR/variance-contravariant-arg-object.rs:14:5
+   |
+LL |     v
+   |     ^ lifetime mismatch
+   |
+   = note: expected type `dyn Get<&'min i32>`
+              found type `dyn Get<&'max i32>`
+note: the lifetime 'min as defined on the function body at 10:21...
+  --> $DIR/variance-contravariant-arg-object.rs:10:21
+   |
+LL | fn get_min_from_max<'min, 'max>(v: Box<Get<&'max i32>>)
+   |                     ^^^^
+note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 10:27
+  --> $DIR/variance-contravariant-arg-object.rs:10:27
+   |
+LL | fn get_min_from_max<'min, 'max>(v: Box<Get<&'max i32>>)
+   |                           ^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/variance-contravariant-arg-object.rs:22:5
+   |
+LL |     v
+   |     ^ lifetime mismatch
+   |
+   = note: expected type `dyn Get<&'max i32>`
+              found type `dyn Get<&'min i32>`
+note: the lifetime 'min as defined on the function body at 17:21...
+  --> $DIR/variance-contravariant-arg-object.rs:17:21
+   |
+LL | fn get_max_from_min<'min, 'max, G>(v: Box<Get<&'min i32>>)
+   |                     ^^^^
+note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 17:27
+  --> $DIR/variance-contravariant-arg-object.rs:17:27
+   |
+LL | fn get_max_from_min<'min, 'max, G>(v: Box<Get<&'min i32>>)
+   |                           ^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/variance/variance-contravariant-arg-trait-match.rs b/src/test/ui/variance/variance-contravariant-arg-trait-match.rs
new file mode 100644
index 0000000..904d931
--- /dev/null
+++ b/src/test/ui/variance/variance-contravariant-arg-trait-match.rs
@@ -0,0 +1,26 @@
+#![allow(dead_code)]
+
+// Test that even when `T` is only used in contravariant position, it
+// is treated as invariant.
+
+trait Get<T> {
+    fn get(&self, t: T);
+}
+
+fn get_min_from_max<'min, 'max, G>()
+    where 'max : 'min, G : Get<&'max i32>
+{
+    impls_get::<G,&'min i32>() //~ ERROR mismatched types
+}
+
+fn get_max_from_min<'min, 'max, G>()
+    where 'max : 'min, G : Get<&'min i32>
+{
+    // Previously OK, but now an error because traits are invariant:
+
+    impls_get::<G,&'max i32>() //~ ERROR mismatched types
+}
+
+fn impls_get<G,T>() where G : Get<T> { }
+
+fn main() { }
diff --git a/src/test/ui/variance/variance-contravariant-arg-trait-match.stderr b/src/test/ui/variance/variance-contravariant-arg-trait-match.stderr
new file mode 100644
index 0000000..ffe690d
--- /dev/null
+++ b/src/test/ui/variance/variance-contravariant-arg-trait-match.stderr
@@ -0,0 +1,41 @@
+error[E0308]: mismatched types
+  --> $DIR/variance-contravariant-arg-trait-match.rs:13:5
+   |
+LL |     impls_get::<G,&'min i32>()
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
+   |
+   = note: expected type `Get<&'min i32>`
+              found type `Get<&'max i32>`
+note: the lifetime 'min as defined on the function body at 10:21...
+  --> $DIR/variance-contravariant-arg-trait-match.rs:10:21
+   |
+LL | fn get_min_from_max<'min, 'max, G>()
+   |                     ^^^^
+note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 10:27
+  --> $DIR/variance-contravariant-arg-trait-match.rs:10:27
+   |
+LL | fn get_min_from_max<'min, 'max, G>()
+   |                           ^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/variance-contravariant-arg-trait-match.rs:21:5
+   |
+LL |     impls_get::<G,&'max i32>()
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
+   |
+   = note: expected type `Get<&'max i32>`
+              found type `Get<&'min i32>`
+note: the lifetime 'min as defined on the function body at 16:21...
+  --> $DIR/variance-contravariant-arg-trait-match.rs:16:21
+   |
+LL | fn get_max_from_min<'min, 'max, G>()
+   |                     ^^^^
+note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 16:27
+  --> $DIR/variance-contravariant-arg-trait-match.rs:16:27
+   |
+LL | fn get_max_from_min<'min, 'max, G>()
+   |                           ^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/variance/variance-contravariant-self-trait-match.rs b/src/test/ui/variance/variance-contravariant-self-trait-match.rs
new file mode 100644
index 0000000..e173758
--- /dev/null
+++ b/src/test/ui/variance/variance-contravariant-self-trait-match.rs
@@ -0,0 +1,27 @@
+#![allow(dead_code)]
+
+// Test that even when `Self` is only used in contravariant position, it
+// is treated as invariant.
+
+trait Get {
+    fn get(&self);
+}
+
+fn get_min_from_max<'min, 'max, G>()
+    where 'max : 'min, G : 'max, &'max G : Get
+{
+    impls_get::<&'min G>(); //~ ERROR mismatched types
+}
+
+fn get_max_from_min<'min, 'max, G>()
+    where 'max : 'min, G : 'max, &'min G : Get
+{
+    // Previously OK, but now error because traits are invariant with
+    // respect to all inputs.
+
+    impls_get::<&'max G>(); //~ ERROR mismatched types
+}
+
+fn impls_get<G>() where G : Get { }
+
+fn main() { }
diff --git a/src/test/ui/variance/variance-contravariant-self-trait-match.stderr b/src/test/ui/variance/variance-contravariant-self-trait-match.stderr
new file mode 100644
index 0000000..6f445d7
--- /dev/null
+++ b/src/test/ui/variance/variance-contravariant-self-trait-match.stderr
@@ -0,0 +1,41 @@
+error[E0308]: mismatched types
+  --> $DIR/variance-contravariant-self-trait-match.rs:13:5
+   |
+LL |     impls_get::<&'min G>();
+   |     ^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
+   |
+   = note: expected type `Get`
+              found type `Get`
+note: the lifetime 'min as defined on the function body at 10:21...
+  --> $DIR/variance-contravariant-self-trait-match.rs:10:21
+   |
+LL | fn get_min_from_max<'min, 'max, G>()
+   |                     ^^^^
+note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 10:27
+  --> $DIR/variance-contravariant-self-trait-match.rs:10:27
+   |
+LL | fn get_min_from_max<'min, 'max, G>()
+   |                           ^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/variance-contravariant-self-trait-match.rs:22:5
+   |
+LL |     impls_get::<&'max G>();
+   |     ^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
+   |
+   = note: expected type `Get`
+              found type `Get`
+note: the lifetime 'min as defined on the function body at 16:21...
+  --> $DIR/variance-contravariant-self-trait-match.rs:16:21
+   |
+LL | fn get_max_from_min<'min, 'max, G>()
+   |                     ^^^^
+note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 16:27
+  --> $DIR/variance-contravariant-self-trait-match.rs:16:27
+   |
+LL | fn get_max_from_min<'min, 'max, G>()
+   |                           ^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/variance/variance-covariant-arg-object.rs b/src/test/ui/variance/variance-covariant-arg-object.rs
new file mode 100644
index 0000000..4b37184
--- /dev/null
+++ b/src/test/ui/variance/variance-covariant-arg-object.rs
@@ -0,0 +1,25 @@
+#![allow(dead_code)]
+
+// Test that even when `T` is only used in covariant position, it
+// is treated as invariant.
+
+trait Get<T> : 'static {
+    fn get(&self) -> T;
+}
+
+fn get_min_from_max<'min, 'max>(v: Box<Get<&'max i32>>)
+                                -> Box<Get<&'min i32>>
+    where 'max : 'min
+{
+    // Previously OK, now an error as traits are invariant.
+    v //~ ERROR mismatched types
+}
+
+fn get_max_from_min<'min, 'max, G>(v: Box<Get<&'min i32>>)
+                                   -> Box<Get<&'max i32>>
+    where 'max : 'min
+{
+    v //~ ERROR mismatched types
+}
+
+fn main() { }
diff --git a/src/test/ui/variance/variance-covariant-arg-object.stderr b/src/test/ui/variance/variance-covariant-arg-object.stderr
new file mode 100644
index 0000000..cdcc7a6
--- /dev/null
+++ b/src/test/ui/variance/variance-covariant-arg-object.stderr
@@ -0,0 +1,41 @@
+error[E0308]: mismatched types
+  --> $DIR/variance-covariant-arg-object.rs:15:5
+   |
+LL |     v
+   |     ^ lifetime mismatch
+   |
+   = note: expected type `dyn Get<&'min i32>`
+              found type `dyn Get<&'max i32>`
+note: the lifetime 'min as defined on the function body at 10:21...
+  --> $DIR/variance-covariant-arg-object.rs:10:21
+   |
+LL | fn get_min_from_max<'min, 'max>(v: Box<Get<&'max i32>>)
+   |                     ^^^^
+note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 10:27
+  --> $DIR/variance-covariant-arg-object.rs:10:27
+   |
+LL | fn get_min_from_max<'min, 'max>(v: Box<Get<&'max i32>>)
+   |                           ^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/variance-covariant-arg-object.rs:22:5
+   |
+LL |     v
+   |     ^ lifetime mismatch
+   |
+   = note: expected type `dyn Get<&'max i32>`
+              found type `dyn Get<&'min i32>`
+note: the lifetime 'min as defined on the function body at 18:21...
+  --> $DIR/variance-covariant-arg-object.rs:18:21
+   |
+LL | fn get_max_from_min<'min, 'max, G>(v: Box<Get<&'min i32>>)
+   |                     ^^^^
+note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 18:27
+  --> $DIR/variance-covariant-arg-object.rs:18:27
+   |
+LL | fn get_max_from_min<'min, 'max, G>(v: Box<Get<&'min i32>>)
+   |                           ^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/variance/variance-covariant-arg-trait-match.rs b/src/test/ui/variance/variance-covariant-arg-trait-match.rs
new file mode 100644
index 0000000..2d4f0ea
--- /dev/null
+++ b/src/test/ui/variance/variance-covariant-arg-trait-match.rs
@@ -0,0 +1,25 @@
+#![allow(dead_code)]
+
+// Test that even when `T` is only used in covariant position, it
+// is treated as invariant.
+
+trait Get<T> {
+    fn get(&self) -> T;
+}
+
+fn get_min_from_max<'min, 'max, G>()
+    where 'max : 'min, G : Get<&'max i32>
+{
+    // Previously OK, now an error as traits are invariant.
+    impls_get::<G,&'min i32>() //~ ERROR mismatched types
+}
+
+fn get_max_from_min<'min, 'max, G>()
+    where 'max : 'min, G : Get<&'min i32>
+{
+    impls_get::<G,&'max i32>() //~ ERROR mismatched types
+}
+
+fn impls_get<G,T>() where G : Get<T> { }
+
+fn main() { }
diff --git a/src/test/ui/variance/variance-covariant-arg-trait-match.stderr b/src/test/ui/variance/variance-covariant-arg-trait-match.stderr
new file mode 100644
index 0000000..c0209ed
--- /dev/null
+++ b/src/test/ui/variance/variance-covariant-arg-trait-match.stderr
@@ -0,0 +1,41 @@
+error[E0308]: mismatched types
+  --> $DIR/variance-covariant-arg-trait-match.rs:14:5
+   |
+LL |     impls_get::<G,&'min i32>()
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
+   |
+   = note: expected type `Get<&'min i32>`
+              found type `Get<&'max i32>`
+note: the lifetime 'min as defined on the function body at 10:21...
+  --> $DIR/variance-covariant-arg-trait-match.rs:10:21
+   |
+LL | fn get_min_from_max<'min, 'max, G>()
+   |                     ^^^^
+note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 10:27
+  --> $DIR/variance-covariant-arg-trait-match.rs:10:27
+   |
+LL | fn get_min_from_max<'min, 'max, G>()
+   |                           ^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/variance-covariant-arg-trait-match.rs:20:5
+   |
+LL |     impls_get::<G,&'max i32>()
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
+   |
+   = note: expected type `Get<&'max i32>`
+              found type `Get<&'min i32>`
+note: the lifetime 'min as defined on the function body at 17:21...
+  --> $DIR/variance-covariant-arg-trait-match.rs:17:21
+   |
+LL | fn get_max_from_min<'min, 'max, G>()
+   |                     ^^^^
+note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 17:27
+  --> $DIR/variance-covariant-arg-trait-match.rs:17:27
+   |
+LL | fn get_max_from_min<'min, 'max, G>()
+   |                           ^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/variance/variance-covariant-self-trait-match.rs b/src/test/ui/variance/variance-covariant-self-trait-match.rs
new file mode 100644
index 0000000..e86a5fc
--- /dev/null
+++ b/src/test/ui/variance/variance-covariant-self-trait-match.rs
@@ -0,0 +1,25 @@
+#![allow(dead_code)]
+
+// Test that even when `Self` is only used in covariant position, it
+// is treated as invariant.
+
+trait Get {
+    fn get() -> Self;
+}
+
+fn get_min_from_max<'min, 'max, G>()
+    where 'max : 'min, G : 'max, &'max G : Get
+{
+    // Previously OK, now an error as traits are invariant.
+    impls_get::<&'min G>(); //~ ERROR mismatched types
+}
+
+fn get_max_from_min<'min, 'max, G>()
+    where 'max : 'min, G : 'max, &'min G : Get
+{
+    impls_get::<&'max G>(); //~ ERROR mismatched types
+}
+
+fn impls_get<G>() where G : Get { }
+
+fn main() { }
diff --git a/src/test/ui/variance/variance-covariant-self-trait-match.stderr b/src/test/ui/variance/variance-covariant-self-trait-match.stderr
new file mode 100644
index 0000000..fe5fe10
--- /dev/null
+++ b/src/test/ui/variance/variance-covariant-self-trait-match.stderr
@@ -0,0 +1,41 @@
+error[E0308]: mismatched types
+  --> $DIR/variance-covariant-self-trait-match.rs:14:5
+   |
+LL |     impls_get::<&'min G>();
+   |     ^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
+   |
+   = note: expected type `Get`
+              found type `Get`
+note: the lifetime 'min as defined on the function body at 10:21...
+  --> $DIR/variance-covariant-self-trait-match.rs:10:21
+   |
+LL | fn get_min_from_max<'min, 'max, G>()
+   |                     ^^^^
+note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 10:27
+  --> $DIR/variance-covariant-self-trait-match.rs:10:27
+   |
+LL | fn get_min_from_max<'min, 'max, G>()
+   |                           ^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/variance-covariant-self-trait-match.rs:20:5
+   |
+LL |     impls_get::<&'max G>();
+   |     ^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
+   |
+   = note: expected type `Get`
+              found type `Get`
+note: the lifetime 'min as defined on the function body at 17:21...
+  --> $DIR/variance-covariant-self-trait-match.rs:17:21
+   |
+LL | fn get_max_from_min<'min, 'max, G>()
+   |                     ^^^^
+note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 17:27
+  --> $DIR/variance-covariant-self-trait-match.rs:17:27
+   |
+LL | fn get_max_from_min<'min, 'max, G>()
+   |                           ^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/variance/variance-invariant-arg-object.rs b/src/test/ui/variance/variance-invariant-arg-object.rs
new file mode 100644
index 0000000..91f5982
--- /dev/null
+++ b/src/test/ui/variance/variance-invariant-arg-object.rs
@@ -0,0 +1,21 @@
+#![allow(dead_code)]
+
+trait Get<T> : 'static {
+    fn get(&self, t: T) -> T;
+}
+
+fn get_min_from_max<'min, 'max>(v: Box<Get<&'max i32>>)
+                                -> Box<Get<&'min i32>>
+    where 'max : 'min
+{
+    v //~ ERROR mismatched types
+}
+
+fn get_max_from_min<'min, 'max, G>(v: Box<Get<&'min i32>>)
+                                   -> Box<Get<&'max i32>>
+    where 'max : 'min
+{
+    v //~ ERROR mismatched types
+}
+
+fn main() { }
diff --git a/src/test/ui/variance/variance-invariant-arg-object.stderr b/src/test/ui/variance/variance-invariant-arg-object.stderr
new file mode 100644
index 0000000..e2ee35d
--- /dev/null
+++ b/src/test/ui/variance/variance-invariant-arg-object.stderr
@@ -0,0 +1,41 @@
+error[E0308]: mismatched types
+  --> $DIR/variance-invariant-arg-object.rs:11:5
+   |
+LL |     v
+   |     ^ lifetime mismatch
+   |
+   = note: expected type `dyn Get<&'min i32>`
+              found type `dyn Get<&'max i32>`
+note: the lifetime 'min as defined on the function body at 7:21...
+  --> $DIR/variance-invariant-arg-object.rs:7:21
+   |
+LL | fn get_min_from_max<'min, 'max>(v: Box<Get<&'max i32>>)
+   |                     ^^^^
+note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 7:27
+  --> $DIR/variance-invariant-arg-object.rs:7:27
+   |
+LL | fn get_min_from_max<'min, 'max>(v: Box<Get<&'max i32>>)
+   |                           ^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/variance-invariant-arg-object.rs:18:5
+   |
+LL |     v
+   |     ^ lifetime mismatch
+   |
+   = note: expected type `dyn Get<&'max i32>`
+              found type `dyn Get<&'min i32>`
+note: the lifetime 'min as defined on the function body at 14:21...
+  --> $DIR/variance-invariant-arg-object.rs:14:21
+   |
+LL | fn get_max_from_min<'min, 'max, G>(v: Box<Get<&'min i32>>)
+   |                     ^^^^
+note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 14:27
+  --> $DIR/variance-invariant-arg-object.rs:14:27
+   |
+LL | fn get_max_from_min<'min, 'max, G>(v: Box<Get<&'min i32>>)
+   |                           ^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/variance/variance-invariant-arg-trait-match.rs b/src/test/ui/variance/variance-invariant-arg-trait-match.rs
new file mode 100644
index 0000000..97d0fdd
--- /dev/null
+++ b/src/test/ui/variance/variance-invariant-arg-trait-match.rs
@@ -0,0 +1,21 @@
+#![allow(dead_code)]
+
+trait Get<T> {
+    fn get(&self, t: T) -> T;
+}
+
+fn get_min_from_max<'min, 'max, G>()
+    where 'max : 'min, G : Get<&'max i32>
+{
+    impls_get::<G,&'min i32>() //~ ERROR mismatched types
+}
+
+fn get_max_from_min<'min, 'max, G>()
+    where 'max : 'min, G : Get<&'min i32>
+{
+    impls_get::<G,&'max i32>() //~ ERROR mismatched types
+}
+
+fn impls_get<G,T>() where G : Get<T> { }
+
+fn main() { }
diff --git a/src/test/ui/variance/variance-invariant-arg-trait-match.stderr b/src/test/ui/variance/variance-invariant-arg-trait-match.stderr
new file mode 100644
index 0000000..c8a1111
--- /dev/null
+++ b/src/test/ui/variance/variance-invariant-arg-trait-match.stderr
@@ -0,0 +1,41 @@
+error[E0308]: mismatched types
+  --> $DIR/variance-invariant-arg-trait-match.rs:10:5
+   |
+LL |     impls_get::<G,&'min i32>()
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
+   |
+   = note: expected type `Get<&'min i32>`
+              found type `Get<&'max i32>`
+note: the lifetime 'min as defined on the function body at 7:21...
+  --> $DIR/variance-invariant-arg-trait-match.rs:7:21
+   |
+LL | fn get_min_from_max<'min, 'max, G>()
+   |                     ^^^^
+note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 7:27
+  --> $DIR/variance-invariant-arg-trait-match.rs:7:27
+   |
+LL | fn get_min_from_max<'min, 'max, G>()
+   |                           ^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/variance-invariant-arg-trait-match.rs:16:5
+   |
+LL |     impls_get::<G,&'max i32>()
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
+   |
+   = note: expected type `Get<&'max i32>`
+              found type `Get<&'min i32>`
+note: the lifetime 'min as defined on the function body at 13:21...
+  --> $DIR/variance-invariant-arg-trait-match.rs:13:21
+   |
+LL | fn get_max_from_min<'min, 'max, G>()
+   |                     ^^^^
+note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 13:27
+  --> $DIR/variance-invariant-arg-trait-match.rs:13:27
+   |
+LL | fn get_max_from_min<'min, 'max, G>()
+   |                           ^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/variance/variance-invariant-self-trait-match.rs b/src/test/ui/variance/variance-invariant-self-trait-match.rs
new file mode 100644
index 0000000..678eefa
--- /dev/null
+++ b/src/test/ui/variance/variance-invariant-self-trait-match.rs
@@ -0,0 +1,21 @@
+#![allow(dead_code)]
+
+trait Get {
+    fn get(&self) -> Self;
+}
+
+fn get_min_from_max<'min, 'max, G>()
+    where 'max : 'min, &'max G : Get, G : 'max
+{
+    impls_get::<&'min G>(); //~ ERROR mismatched types
+}
+
+fn get_max_from_min<'min, 'max, G>()
+    where 'max : 'min, &'min G : Get, G : 'min
+{
+    impls_get::<&'max G>(); //~ ERROR mismatched types
+}
+
+fn impls_get<G>() where G : Get { }
+
+fn main() { }
diff --git a/src/test/ui/variance/variance-invariant-self-trait-match.stderr b/src/test/ui/variance/variance-invariant-self-trait-match.stderr
new file mode 100644
index 0000000..cb03d95
--- /dev/null
+++ b/src/test/ui/variance/variance-invariant-self-trait-match.stderr
@@ -0,0 +1,41 @@
+error[E0308]: mismatched types
+  --> $DIR/variance-invariant-self-trait-match.rs:10:5
+   |
+LL |     impls_get::<&'min G>();
+   |     ^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
+   |
+   = note: expected type `Get`
+              found type `Get`
+note: the lifetime 'min as defined on the function body at 7:21...
+  --> $DIR/variance-invariant-self-trait-match.rs:7:21
+   |
+LL | fn get_min_from_max<'min, 'max, G>()
+   |                     ^^^^
+note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 7:27
+  --> $DIR/variance-invariant-self-trait-match.rs:7:27
+   |
+LL | fn get_min_from_max<'min, 'max, G>()
+   |                           ^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/variance-invariant-self-trait-match.rs:16:5
+   |
+LL |     impls_get::<&'max G>();
+   |     ^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
+   |
+   = note: expected type `Get`
+              found type `Get`
+note: the lifetime 'min as defined on the function body at 13:21...
+  --> $DIR/variance-invariant-self-trait-match.rs:13:21
+   |
+LL | fn get_max_from_min<'min, 'max, G>()
+   |                     ^^^^
+note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 13:27
+  --> $DIR/variance-invariant-self-trait-match.rs:13:27
+   |
+LL | fn get_max_from_min<'min, 'max, G>()
+   |                           ^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/variance/variance-issue-20533.nll.stderr b/src/test/ui/variance/variance-issue-20533.nll.stderr
new file mode 100644
index 0000000..008e2a0
--- /dev/null
+++ b/src/test/ui/variance/variance-issue-20533.nll.stderr
@@ -0,0 +1,33 @@
+error[E0505]: cannot move out of `a` because it is borrowed
+  --> $DIR/variance-issue-20533.rs:28:14
+   |
+LL |         let x = foo(&a);
+   |                     -- borrow of `a` occurs here
+LL |         drop(a);
+   |              ^ move out of `a` occurs here
+LL |         drop(x);
+   |              - borrow later used here
+
+error[E0505]: cannot move out of `a` because it is borrowed
+  --> $DIR/variance-issue-20533.rs:34:14
+   |
+LL |         let x = bar(&a);
+   |                     -- borrow of `a` occurs here
+LL |         drop(a);
+   |              ^ move out of `a` occurs here
+LL |         drop(x);
+   |              - borrow later used here
+
+error[E0505]: cannot move out of `a` because it is borrowed
+  --> $DIR/variance-issue-20533.rs:40:14
+   |
+LL |         let x = baz(&a);
+   |                     -- borrow of `a` occurs here
+LL |         drop(a);
+   |              ^ move out of `a` occurs here
+LL |         drop(x);
+   |              - borrow later used here
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0505`.
diff --git a/src/test/ui/variance/variance-issue-20533.rs b/src/test/ui/variance/variance-issue-20533.rs
new file mode 100644
index 0000000..a2459f8
--- /dev/null
+++ b/src/test/ui/variance/variance-issue-20533.rs
@@ -0,0 +1,43 @@
+// Regression test for issue #20533. At some point, only 1 out of the
+// 3 errors below were being reported.
+
+use std::marker::PhantomData;
+
+fn foo<'a, T>(_x: &'a T) -> PhantomData<&'a ()> {
+    PhantomData
+}
+
+struct Wrap<T>(T);
+
+fn bar<'a, T>(_x: &'a T) -> Wrap<PhantomData<&'a ()>> {
+    Wrap(PhantomData)
+}
+
+struct Baked<'a>(PhantomData<&'a ()>);
+
+fn baz<'a, T>(_x: &'a T) -> Baked<'a> {
+    Baked(PhantomData)
+}
+
+struct AffineU32(u32);
+
+fn main() {
+    {
+        let a = AffineU32(1);
+        let x = foo(&a);
+        drop(a); //~ ERROR cannot move out of `a`
+        drop(x);
+    }
+    {
+        let a = AffineU32(1);
+        let x = bar(&a);
+        drop(a); //~ ERROR cannot move out of `a`
+        drop(x);
+    }
+    {
+        let a = AffineU32(1);
+        let x = baz(&a);
+        drop(a); //~ ERROR cannot move out of `a`
+        drop(x);
+    }
+}
diff --git a/src/test/ui/variance/variance-issue-20533.stderr b/src/test/ui/variance/variance-issue-20533.stderr
new file mode 100644
index 0000000..bcf99bc
--- /dev/null
+++ b/src/test/ui/variance/variance-issue-20533.stderr
@@ -0,0 +1,27 @@
+error[E0505]: cannot move out of `a` because it is borrowed
+  --> $DIR/variance-issue-20533.rs:28:14
+   |
+LL |         let x = foo(&a);
+   |                      - borrow of `a` occurs here
+LL |         drop(a);
+   |              ^ move out of `a` occurs here
+
+error[E0505]: cannot move out of `a` because it is borrowed
+  --> $DIR/variance-issue-20533.rs:34:14
+   |
+LL |         let x = bar(&a);
+   |                      - borrow of `a` occurs here
+LL |         drop(a);
+   |              ^ move out of `a` occurs here
+
+error[E0505]: cannot move out of `a` because it is borrowed
+  --> $DIR/variance-issue-20533.rs:40:14
+   |
+LL |         let x = baz(&a);
+   |                      - borrow of `a` occurs here
+LL |         drop(a);
+   |              ^ move out of `a` occurs here
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0505`.
diff --git a/src/test/ui/variance/variance-object-types.rs b/src/test/ui/variance/variance-object-types.rs
new file mode 100644
index 0000000..12af7ae
--- /dev/null
+++ b/src/test/ui/variance/variance-object-types.rs
@@ -0,0 +1,16 @@
+// Test that Cell is considered invariant with respect to its
+// type.
+
+#![feature(rustc_attrs)]
+
+use std::cell::Cell;
+
+// For better or worse, associated types are invariant, and hence we
+// get an invariant result for `'a`.
+#[rustc_variance]
+struct Foo<'a> { //~ ERROR [o]
+    x: Box<Fn(i32) -> &'a i32 + 'static>
+}
+
+fn main() {
+}
diff --git a/src/test/ui/variance/variance-object-types.stderr b/src/test/ui/variance/variance-object-types.stderr
new file mode 100644
index 0000000..385d8dc
--- /dev/null
+++ b/src/test/ui/variance/variance-object-types.stderr
@@ -0,0 +1,11 @@
+error[E0208]: [o]
+  --> $DIR/variance-object-types.rs:11:1
+   |
+LL | / struct Foo<'a> {
+LL | |     x: Box<Fn(i32) -> &'a i32 + 'static>
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0208`.
diff --git a/src/test/ui/variance/variance-regions-direct.rs b/src/test/ui/variance/variance-regions-direct.rs
new file mode 100644
index 0000000..3f34e76
--- /dev/null
+++ b/src/test/ui/variance/variance-regions-direct.rs
@@ -0,0 +1,65 @@
+// Test that we correctly infer variance for region parameters in
+// various self-contained types.
+
+#![feature(rustc_attrs)]
+
+// Regions that just appear in normal spots are contravariant:
+
+#[rustc_variance]
+struct Test2<'a, 'b, 'c> { //~ ERROR [-, -, -]
+    x: &'a isize,
+    y: &'b [isize],
+    c: &'c str
+}
+
+// Those same annotations in function arguments become covariant:
+
+#[rustc_variance]
+struct Test3<'a, 'b, 'c> { //~ ERROR [+, +, +]
+    x: extern "Rust" fn(&'a isize),
+    y: extern "Rust" fn(&'b [isize]),
+    c: extern "Rust" fn(&'c str),
+}
+
+// Mutability induces invariance:
+
+#[rustc_variance]
+struct Test4<'a, 'b:'a> { //~ ERROR [-, o]
+    x: &'a mut &'b isize,
+}
+
+// Mutability induces invariance, even when in a
+// contravariant context:
+
+#[rustc_variance]
+struct Test5<'a, 'b:'a> { //~ ERROR [+, o]
+    x: extern "Rust" fn(&'a mut &'b isize),
+}
+
+// Invariance is a trap from which NO ONE CAN ESCAPE.
+// In other words, even though the `&'b isize` occurs in
+// an argument list (which is contravariant), that
+// argument list occurs in an invariant context.
+
+#[rustc_variance]
+struct Test6<'a, 'b:'a> { //~ ERROR [-, o]
+    x: &'a mut extern "Rust" fn(&'b isize),
+}
+
+// No uses at all is bivariant:
+
+#[rustc_variance]
+struct Test7<'a> { //~ ERROR [*]
+    x: isize
+}
+
+// Try enums too.
+
+#[rustc_variance]
+enum Test8<'a, 'b, 'c:'b> { //~ ERROR [+, -, o]
+    Test8A(extern "Rust" fn(&'a isize)),
+    Test8B(&'b [isize]),
+    Test8C(&'b mut &'c str),
+}
+
+fn main() {}
diff --git a/src/test/ui/variance/variance-regions-direct.stderr b/src/test/ui/variance/variance-regions-direct.stderr
new file mode 100644
index 0000000..bbc3479
--- /dev/null
+++ b/src/test/ui/variance/variance-regions-direct.stderr
@@ -0,0 +1,65 @@
+error[E0208]: [-, -, -]
+  --> $DIR/variance-regions-direct.rs:9:1
+   |
+LL | / struct Test2<'a, 'b, 'c> {
+LL | |     x: &'a isize,
+LL | |     y: &'b [isize],
+LL | |     c: &'c str
+LL | | }
+   | |_^
+
+error[E0208]: [+, +, +]
+  --> $DIR/variance-regions-direct.rs:18:1
+   |
+LL | / struct Test3<'a, 'b, 'c> {
+LL | |     x: extern "Rust" fn(&'a isize),
+LL | |     y: extern "Rust" fn(&'b [isize]),
+LL | |     c: extern "Rust" fn(&'c str),
+LL | | }
+   | |_^
+
+error[E0208]: [-, o]
+  --> $DIR/variance-regions-direct.rs:27:1
+   |
+LL | / struct Test4<'a, 'b:'a> {
+LL | |     x: &'a mut &'b isize,
+LL | | }
+   | |_^
+
+error[E0208]: [+, o]
+  --> $DIR/variance-regions-direct.rs:35:1
+   |
+LL | / struct Test5<'a, 'b:'a> {
+LL | |     x: extern "Rust" fn(&'a mut &'b isize),
+LL | | }
+   | |_^
+
+error[E0208]: [-, o]
+  --> $DIR/variance-regions-direct.rs:45:1
+   |
+LL | / struct Test6<'a, 'b:'a> {
+LL | |     x: &'a mut extern "Rust" fn(&'b isize),
+LL | | }
+   | |_^
+
+error[E0208]: [*]
+  --> $DIR/variance-regions-direct.rs:52:1
+   |
+LL | / struct Test7<'a> {
+LL | |     x: isize
+LL | | }
+   | |_^
+
+error[E0208]: [+, -, o]
+  --> $DIR/variance-regions-direct.rs:59:1
+   |
+LL | / enum Test8<'a, 'b, 'c:'b> {
+LL | |     Test8A(extern "Rust" fn(&'a isize)),
+LL | |     Test8B(&'b [isize]),
+LL | |     Test8C(&'b mut &'c str),
+LL | | }
+   | |_^
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0208`.
diff --git a/src/test/ui/variance/variance-regions-indirect.rs b/src/test/ui/variance/variance-regions-indirect.rs
new file mode 100644
index 0000000..f84f25a
--- /dev/null
+++ b/src/test/ui/variance/variance-regions-indirect.rs
@@ -0,0 +1,34 @@
+// Test that we correctly infer variance for region parameters in
+// case that involve multiple intricate types.
+// Try enums too.
+
+#![feature(rustc_attrs)]
+
+#[rustc_variance]
+enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR [+, -, o, *]
+    Test8A(extern "Rust" fn(&'a isize)),
+    Test8B(&'b [isize]),
+    Test8C(&'b mut &'c str),
+}
+
+#[rustc_variance]
+struct Derived1<'w, 'x:'y, 'y, 'z> { //~ ERROR [*, o, -, +]
+    f: Base<'z, 'y, 'x, 'w>
+}
+
+#[rustc_variance] // Combine - and + to yield o
+struct Derived2<'a, 'b:'a, 'c> { //~ ERROR [o, o, *]
+    f: Base<'a, 'a, 'b, 'c>
+}
+
+#[rustc_variance] // Combine + and o to yield o (just pay attention to 'a here)
+struct Derived3<'a:'b, 'b, 'c> { //~ ERROR [o, -, *]
+    f: Base<'a, 'b, 'a, 'c>
+}
+
+#[rustc_variance] // Combine + and * to yield + (just pay attention to 'a here)
+struct Derived4<'a, 'b, 'c:'b> { //~ ERROR [+, -, o]
+    f: Base<'a, 'b, 'c, 'a>
+}
+
+fn main() {}
diff --git a/src/test/ui/variance/variance-regions-indirect.stderr b/src/test/ui/variance/variance-regions-indirect.stderr
new file mode 100644
index 0000000..ccd4335
--- /dev/null
+++ b/src/test/ui/variance/variance-regions-indirect.stderr
@@ -0,0 +1,45 @@
+error[E0208]: [+, -, o, *]
+  --> $DIR/variance-regions-indirect.rs:8:1
+   |
+LL | / enum Base<'a, 'b, 'c:'b, 'd> {
+LL | |     Test8A(extern "Rust" fn(&'a isize)),
+LL | |     Test8B(&'b [isize]),
+LL | |     Test8C(&'b mut &'c str),
+LL | | }
+   | |_^
+
+error[E0208]: [*, o, -, +]
+  --> $DIR/variance-regions-indirect.rs:15:1
+   |
+LL | / struct Derived1<'w, 'x:'y, 'y, 'z> {
+LL | |     f: Base<'z, 'y, 'x, 'w>
+LL | | }
+   | |_^
+
+error[E0208]: [o, o, *]
+  --> $DIR/variance-regions-indirect.rs:20:1
+   |
+LL | / struct Derived2<'a, 'b:'a, 'c> {
+LL | |     f: Base<'a, 'a, 'b, 'c>
+LL | | }
+   | |_^
+
+error[E0208]: [o, -, *]
+  --> $DIR/variance-regions-indirect.rs:25:1
+   |
+LL | / struct Derived3<'a:'b, 'b, 'c> {
+LL | |     f: Base<'a, 'b, 'a, 'c>
+LL | | }
+   | |_^
+
+error[E0208]: [+, -, o]
+  --> $DIR/variance-regions-indirect.rs:30:1
+   |
+LL | / struct Derived4<'a, 'b, 'c:'b> {
+LL | |     f: Base<'a, 'b, 'c, 'a>
+LL | | }
+   | |_^
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0208`.
diff --git a/src/test/ui/variance/variance-regions-unused-direct.rs b/src/test/ui/variance/variance-regions-unused-direct.rs
new file mode 100644
index 0000000..2afe012
--- /dev/null
+++ b/src/test/ui/variance/variance-regions-unused-direct.rs
@@ -0,0 +1,15 @@
+// Test that disallow lifetime parameters that are unused.
+
+use std::marker;
+
+struct Bivariant<'a>; //~ ERROR parameter `'a` is never used
+
+struct Struct<'a, 'd> { //~ ERROR parameter `'d` is never used
+    field: &'a [i32]
+}
+
+trait Trait<'a, 'd> { // OK on traits
+    fn method(&'a self);
+}
+
+fn main() {}
diff --git a/src/test/ui/variance/variance-regions-unused-direct.stderr b/src/test/ui/variance/variance-regions-unused-direct.stderr
new file mode 100644
index 0000000..ab5dce0
--- /dev/null
+++ b/src/test/ui/variance/variance-regions-unused-direct.stderr
@@ -0,0 +1,19 @@
+error[E0392]: parameter `'a` is never used
+  --> $DIR/variance-regions-unused-direct.rs:5:18
+   |
+LL | struct Bivariant<'a>;
+   |                  ^^ unused type parameter
+   |
+   = help: consider removing `'a` or using a marker such as `std::marker::PhantomData`
+
+error[E0392]: parameter `'d` is never used
+  --> $DIR/variance-regions-unused-direct.rs:7:19
+   |
+LL | struct Struct<'a, 'd> {
+   |                   ^^ unused type parameter
+   |
+   = help: consider removing `'d` or using a marker such as `std::marker::PhantomData`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0392`.
diff --git a/src/test/ui/variance/variance-regions-unused-indirect.rs b/src/test/ui/variance/variance-regions-unused-indirect.rs
new file mode 100644
index 0000000..1514e39
--- /dev/null
+++ b/src/test/ui/variance/variance-regions-unused-indirect.rs
@@ -0,0 +1,11 @@
+// Test that disallow lifetime parameters that are unused.
+
+enum Foo<'a> { //~ ERROR parameter `'a` is never used
+    Foo1(Bar<'a>)
+}
+
+enum Bar<'a> { //~ ERROR parameter `'a` is never used
+    Bar1(Foo<'a>)
+}
+
+fn main() {}
diff --git a/src/test/ui/variance/variance-regions-unused-indirect.stderr b/src/test/ui/variance/variance-regions-unused-indirect.stderr
new file mode 100644
index 0000000..69631b4
--- /dev/null
+++ b/src/test/ui/variance/variance-regions-unused-indirect.stderr
@@ -0,0 +1,19 @@
+error[E0392]: parameter `'a` is never used
+  --> $DIR/variance-regions-unused-indirect.rs:3:10
+   |
+LL | enum Foo<'a> {
+   |          ^^ unused type parameter
+   |
+   = help: consider removing `'a` or using a marker such as `std::marker::PhantomData`
+
+error[E0392]: parameter `'a` is never used
+  --> $DIR/variance-regions-unused-indirect.rs:7:10
+   |
+LL | enum Bar<'a> {
+   |          ^^ unused type parameter
+   |
+   = help: consider removing `'a` or using a marker such as `std::marker::PhantomData`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0392`.
diff --git a/src/test/ui/variance/variance-trait-bounds.rs b/src/test/ui/variance/variance-trait-bounds.rs
new file mode 100644
index 0000000..ad53346
--- /dev/null
+++ b/src/test/ui/variance/variance-trait-bounds.rs
@@ -0,0 +1,35 @@
+#![allow(dead_code)]
+#![feature(rustc_attrs)]
+
+// Check that bounds on type parameters (other than `Self`) do not
+// influence variance.
+
+trait Getter<T> {
+    fn get(&self) -> T;
+}
+
+trait Setter<T> {
+    fn get(&self, _: T);
+}
+
+#[rustc_variance]
+struct TestStruct<U,T:Setter<U>> { //~ ERROR [+, +]
+    t: T, u: U
+}
+
+#[rustc_variance]
+enum TestEnum<U,T:Setter<U>> { //~ ERROR [*, +]
+    Foo(T)
+}
+
+#[rustc_variance]
+struct TestContraStruct<U,T:Setter<U>> { //~ ERROR [*, +]
+    t: T
+}
+
+#[rustc_variance]
+struct TestBox<U,T:Getter<U>+Setter<U>> { //~ ERROR [*, +]
+    t: T
+}
+
+pub fn main() { }
diff --git a/src/test/ui/variance/variance-trait-bounds.stderr b/src/test/ui/variance/variance-trait-bounds.stderr
new file mode 100644
index 0000000..f136bd1
--- /dev/null
+++ b/src/test/ui/variance/variance-trait-bounds.stderr
@@ -0,0 +1,35 @@
+error[E0208]: [+, +]
+  --> $DIR/variance-trait-bounds.rs:16:1
+   |
+LL | / struct TestStruct<U,T:Setter<U>> {
+LL | |     t: T, u: U
+LL | | }
+   | |_^
+
+error[E0208]: [*, +]
+  --> $DIR/variance-trait-bounds.rs:21:1
+   |
+LL | / enum TestEnum<U,T:Setter<U>> {
+LL | |     Foo(T)
+LL | | }
+   | |_^
+
+error[E0208]: [*, +]
+  --> $DIR/variance-trait-bounds.rs:26:1
+   |
+LL | / struct TestContraStruct<U,T:Setter<U>> {
+LL | |     t: T
+LL | | }
+   | |_^
+
+error[E0208]: [*, +]
+  --> $DIR/variance-trait-bounds.rs:31:1
+   |
+LL | / struct TestBox<U,T:Getter<U>+Setter<U>> {
+LL | |     t: T
+LL | | }
+   | |_^
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0208`.
diff --git a/src/test/ui/variance/variance-trait-matching.rs b/src/test/ui/variance/variance-trait-matching.rs
new file mode 100644
index 0000000..b4efee7
--- /dev/null
+++ b/src/test/ui/variance/variance-trait-matching.rs
@@ -0,0 +1,38 @@
+#![allow(dead_code)]
+
+// Get<T> is covariant in T
+trait Get<T> {
+    fn get(&self) -> T;
+}
+
+struct Cloner<T:Clone> {
+    t: T
+}
+
+impl<T:Clone> Get<T> for Cloner<T> {
+    fn get(&self) -> T {
+        self.t.clone()
+    }
+}
+
+fn get<'a, G>(get: &G) -> i32
+    where G : Get<&'a i32>
+{
+    // This fails to type-check because, without variance, we can't
+    // use `G : Get<&'a i32>` as evidence that `G : Get<&'b i32>`,
+    // even if `'a : 'b`.
+    pick(get, &22) //~ ERROR explicit lifetime required in the type of `get` [E0621]
+}
+
+fn pick<'b, G>(get: &'b G, if_odd: &'b i32) -> i32
+    where G : Get<&'b i32>
+{
+    let v = *get.get();
+    if v % 2 != 0 { v } else { *if_odd }
+}
+
+fn main() {
+    let x = Cloner { t: &23 };
+    let y = get(&x);
+    assert_eq!(y, 23);
+}
diff --git a/src/test/ui/variance/variance-trait-matching.stderr b/src/test/ui/variance/variance-trait-matching.stderr
new file mode 100644
index 0000000..5141531
--- /dev/null
+++ b/src/test/ui/variance/variance-trait-matching.stderr
@@ -0,0 +1,12 @@
+error[E0621]: explicit lifetime required in the type of `get`
+  --> $DIR/variance-trait-matching.rs:24:5
+   |
+LL | fn get<'a, G>(get: &G) -> i32
+   |                    -- help: add explicit lifetime `'a` to the type of `get`: `&'a G`
+...
+LL |     pick(get, &22)
+   |     ^^^^ lifetime `'a` required
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/variance/variance-trait-object-bound.rs b/src/test/ui/variance/variance-trait-object-bound.rs
new file mode 100644
index 0000000..ada93b7
--- /dev/null
+++ b/src/test/ui/variance/variance-trait-object-bound.rs
@@ -0,0 +1,18 @@
+// Checks that regions which appear in a trait object type are
+// observed by the variance inference algorithm (and hence
+// `TOption` is contavariant w/r/t `'a` and not bivariant).
+//
+// Issue #18262.
+
+#![feature(rustc_attrs)]
+
+use std::mem;
+
+trait T { fn foo(&self); }
+
+#[rustc_variance]
+struct TOption<'a> { //~ ERROR [-]
+    v: Option<Box<T + 'a>>,
+}
+
+fn main() { }
diff --git a/src/test/ui/variance/variance-trait-object-bound.stderr b/src/test/ui/variance/variance-trait-object-bound.stderr
new file mode 100644
index 0000000..4fa4a2e
--- /dev/null
+++ b/src/test/ui/variance/variance-trait-object-bound.stderr
@@ -0,0 +1,11 @@
+error[E0208]: [-]
+  --> $DIR/variance-trait-object-bound.rs:14:1
+   |
+LL | / struct TOption<'a> {
+LL | |     v: Option<Box<T + 'a>>,
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0208`.
diff --git a/src/test/ui/variance/variance-types-bounds.rs b/src/test/ui/variance/variance-types-bounds.rs
new file mode 100644
index 0000000..5cbda10
--- /dev/null
+++ b/src/test/ui/variance/variance-types-bounds.rs
@@ -0,0 +1,43 @@
+// Test that we correctly infer variance for type parameters in
+// various types and traits.
+
+#![feature(rustc_attrs)]
+
+#[rustc_variance]
+struct TestImm<A, B> { //~ ERROR [+, +]
+    x: A,
+    y: B,
+}
+
+#[rustc_variance]
+struct TestMut<A, B:'static> { //~ ERROR [+, o]
+    x: A,
+    y: &'static mut B,
+}
+
+#[rustc_variance]
+struct TestIndirect<A:'static, B:'static> { //~ ERROR [+, o]
+    m: TestMut<A, B>
+}
+
+#[rustc_variance]
+struct TestIndirect2<A:'static, B:'static> { //~ ERROR [o, o]
+    n: TestMut<A, B>,
+    m: TestMut<B, A>
+}
+
+trait Getter<A> {
+    fn get(&self) -> A;
+}
+
+trait Setter<A> {
+    fn set(&mut self, a: A);
+}
+
+#[rustc_variance]
+struct TestObject<A, R> { //~ ERROR [o, o]
+    n: Box<Setter<A>+Send>,
+    m: Box<Getter<R>+Send>,
+}
+
+fn main() {}
diff --git a/src/test/ui/variance/variance-types-bounds.stderr b/src/test/ui/variance/variance-types-bounds.stderr
new file mode 100644
index 0000000..991bfd3
--- /dev/null
+++ b/src/test/ui/variance/variance-types-bounds.stderr
@@ -0,0 +1,47 @@
+error[E0208]: [+, +]
+  --> $DIR/variance-types-bounds.rs:7:1
+   |
+LL | / struct TestImm<A, B> {
+LL | |     x: A,
+LL | |     y: B,
+LL | | }
+   | |_^
+
+error[E0208]: [+, o]
+  --> $DIR/variance-types-bounds.rs:13:1
+   |
+LL | / struct TestMut<A, B:'static> {
+LL | |     x: A,
+LL | |     y: &'static mut B,
+LL | | }
+   | |_^
+
+error[E0208]: [+, o]
+  --> $DIR/variance-types-bounds.rs:19:1
+   |
+LL | / struct TestIndirect<A:'static, B:'static> {
+LL | |     m: TestMut<A, B>
+LL | | }
+   | |_^
+
+error[E0208]: [o, o]
+  --> $DIR/variance-types-bounds.rs:24:1
+   |
+LL | / struct TestIndirect2<A:'static, B:'static> {
+LL | |     n: TestMut<A, B>,
+LL | |     m: TestMut<B, A>
+LL | | }
+   | |_^
+
+error[E0208]: [o, o]
+  --> $DIR/variance-types-bounds.rs:38:1
+   |
+LL | / struct TestObject<A, R> {
+LL | |     n: Box<Setter<A>+Send>,
+LL | |     m: Box<Getter<R>+Send>,
+LL | | }
+   | |_^
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0208`.
diff --git a/src/test/ui/variance/variance-types.rs b/src/test/ui/variance/variance-types.rs
new file mode 100644
index 0000000..b9b6d9c
--- /dev/null
+++ b/src/test/ui/variance/variance-types.rs
@@ -0,0 +1,41 @@
+#![allow(dead_code)]
+#![feature(rustc_attrs)]
+
+use std::cell::Cell;
+
+// Check that a type parameter which is only used in a trait bound is
+// not considered bivariant.
+
+#[rustc_variance]
+struct InvariantMut<'a,A:'a,B:'a> { //~ ERROR [-, o, o]
+    t: &'a mut (A,B)
+}
+
+#[rustc_variance]
+struct InvariantCell<A> { //~ ERROR [o]
+    t: Cell<A>
+}
+
+#[rustc_variance]
+struct InvariantIndirect<A> { //~ ERROR [o]
+    t: InvariantCell<A>
+}
+
+#[rustc_variance]
+struct Covariant<A> { //~ ERROR [+]
+    t: A, u: fn() -> A
+}
+
+#[rustc_variance]
+struct Contravariant<A> { //~ ERROR [-]
+    t: fn(A)
+}
+
+#[rustc_variance]
+enum Enum<A,B,C> { //~ ERROR [+, -, o]
+    Foo(Covariant<A>),
+    Bar(Contravariant<B>),
+    Zed(Covariant<C>,Contravariant<C>)
+}
+
+pub fn main() { }
diff --git a/src/test/ui/variance/variance-types.stderr b/src/test/ui/variance/variance-types.stderr
new file mode 100644
index 0000000..f68a266
--- /dev/null
+++ b/src/test/ui/variance/variance-types.stderr
@@ -0,0 +1,53 @@
+error[E0208]: [-, o, o]
+  --> $DIR/variance-types.rs:10:1
+   |
+LL | / struct InvariantMut<'a,A:'a,B:'a> {
+LL | |     t: &'a mut (A,B)
+LL | | }
+   | |_^
+
+error[E0208]: [o]
+  --> $DIR/variance-types.rs:15:1
+   |
+LL | / struct InvariantCell<A> {
+LL | |     t: Cell<A>
+LL | | }
+   | |_^
+
+error[E0208]: [o]
+  --> $DIR/variance-types.rs:20:1
+   |
+LL | / struct InvariantIndirect<A> {
+LL | |     t: InvariantCell<A>
+LL | | }
+   | |_^
+
+error[E0208]: [+]
+  --> $DIR/variance-types.rs:25:1
+   |
+LL | / struct Covariant<A> {
+LL | |     t: A, u: fn() -> A
+LL | | }
+   | |_^
+
+error[E0208]: [-]
+  --> $DIR/variance-types.rs:30:1
+   |
+LL | / struct Contravariant<A> {
+LL | |     t: fn(A)
+LL | | }
+   | |_^
+
+error[E0208]: [+, -, o]
+  --> $DIR/variance-types.rs:35:1
+   |
+LL | / enum Enum<A,B,C> {
+LL | |     Foo(Covariant<A>),
+LL | |     Bar(Contravariant<B>),
+LL | |     Zed(Covariant<C>,Contravariant<C>)
+LL | | }
+   | |_^
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0208`.
diff --git a/src/test/ui/variance/variance-unused-region-param.rs b/src/test/ui/variance/variance-unused-region-param.rs
new file mode 100644
index 0000000..f0e4e03
--- /dev/null
+++ b/src/test/ui/variance/variance-unused-region-param.rs
@@ -0,0 +1,7 @@
+// Test that we report an error for unused type parameters in types.
+
+struct SomeStruct<'a> { x: u32 } //~ ERROR parameter `'a` is never used
+enum SomeEnum<'a> { Nothing } //~ ERROR parameter `'a` is never used
+trait SomeTrait<'a> { fn foo(&self); } // OK on traits.
+
+fn main() {}
diff --git a/src/test/ui/variance/variance-unused-region-param.stderr b/src/test/ui/variance/variance-unused-region-param.stderr
new file mode 100644
index 0000000..6c103f1
--- /dev/null
+++ b/src/test/ui/variance/variance-unused-region-param.stderr
@@ -0,0 +1,19 @@
+error[E0392]: parameter `'a` is never used
+  --> $DIR/variance-unused-region-param.rs:3:19
+   |
+LL | struct SomeStruct<'a> { x: u32 }
+   |                   ^^ unused type parameter
+   |
+   = help: consider removing `'a` or using a marker such as `std::marker::PhantomData`
+
+error[E0392]: parameter `'a` is never used
+  --> $DIR/variance-unused-region-param.rs:4:15
+   |
+LL | enum SomeEnum<'a> { Nothing }
+   |               ^^ unused type parameter
+   |
+   = help: consider removing `'a` or using a marker such as `std::marker::PhantomData`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0392`.
diff --git a/src/test/ui/variance/variance-unused-type-param.rs b/src/test/ui/variance/variance-unused-type-param.rs
new file mode 100644
index 0000000..1e0e403
--- /dev/null
+++ b/src/test/ui/variance/variance-unused-type-param.rs
@@ -0,0 +1,19 @@
+#![allow(dead_code)]
+
+// Test that we report an error for unused type parameters in types and traits,
+// and that we offer a helpful suggestion.
+
+struct SomeStruct<A> { x: u32 }
+//~^ ERROR parameter `A` is never used
+
+enum SomeEnum<A> { Nothing }
+//~^ ERROR parameter `A` is never used
+
+// Here T might *appear* used, but in fact it isn't.
+enum ListCell<T> {
+//~^ ERROR parameter `T` is never used
+    Cons(Box<ListCell<T>>),
+    Nil
+}
+
+fn main() {}
diff --git a/src/test/ui/variance/variance-unused-type-param.stderr b/src/test/ui/variance/variance-unused-type-param.stderr
new file mode 100644
index 0000000..34c430f
--- /dev/null
+++ b/src/test/ui/variance/variance-unused-type-param.stderr
@@ -0,0 +1,27 @@
+error[E0392]: parameter `A` is never used
+  --> $DIR/variance-unused-type-param.rs:6:19
+   |
+LL | struct SomeStruct<A> { x: u32 }
+   |                   ^ unused type parameter
+   |
+   = help: consider removing `A` or using a marker such as `std::marker::PhantomData`
+
+error[E0392]: parameter `A` is never used
+  --> $DIR/variance-unused-type-param.rs:9:15
+   |
+LL | enum SomeEnum<A> { Nothing }
+   |               ^ unused type parameter
+   |
+   = help: consider removing `A` or using a marker such as `std::marker::PhantomData`
+
+error[E0392]: parameter `T` is never used
+  --> $DIR/variance-unused-type-param.rs:13:15
+   |
+LL | enum ListCell<T> {
+   |               ^ unused type parameter
+   |
+   = help: consider removing `T` or using a marker such as `std::marker::PhantomData`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0392`.
diff --git a/src/test/ui/variance/variance-use-contravariant-struct-1.rs b/src/test/ui/variance/variance-use-contravariant-struct-1.rs
new file mode 100644
index 0000000..8a02ef4
--- /dev/null
+++ b/src/test/ui/variance/variance-use-contravariant-struct-1.rs
@@ -0,0 +1,16 @@
+// Test various uses of structs with distint variances to make sure
+// they permit lifetimes to be approximated as expected.
+
+
+
+struct SomeStruct<T>(fn(T));
+
+fn foo<'min,'max>(v: SomeStruct<&'max ()>)
+                  -> SomeStruct<&'min ()>
+    where 'max : 'min
+{
+    v //~ ERROR mismatched types
+}
+
+
+fn main() { }
diff --git a/src/test/ui/variance/variance-use-contravariant-struct-1.stderr b/src/test/ui/variance/variance-use-contravariant-struct-1.stderr
new file mode 100644
index 0000000..7c43337
--- /dev/null
+++ b/src/test/ui/variance/variance-use-contravariant-struct-1.stderr
@@ -0,0 +1,22 @@
+error[E0308]: mismatched types
+  --> $DIR/variance-use-contravariant-struct-1.rs:12:5
+   |
+LL |     v
+   |     ^ lifetime mismatch
+   |
+   = note: expected type `SomeStruct<&'min ()>`
+              found type `SomeStruct<&'max ()>`
+note: the lifetime 'min as defined on the function body at 8:8...
+  --> $DIR/variance-use-contravariant-struct-1.rs:8:8
+   |
+LL | fn foo<'min,'max>(v: SomeStruct<&'max ()>)
+   |        ^^^^
+note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 8:13
+  --> $DIR/variance-use-contravariant-struct-1.rs:8:13
+   |
+LL | fn foo<'min,'max>(v: SomeStruct<&'max ()>)
+   |             ^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/variance/variance-use-contravariant-struct-2.rs b/src/test/ui/variance/variance-use-contravariant-struct-2.rs
new file mode 100644
index 0000000..77bd2b7
--- /dev/null
+++ b/src/test/ui/variance/variance-use-contravariant-struct-2.rs
@@ -0,0 +1,17 @@
+// Test various uses of structs with distint variances to make sure
+// they permit lifetimes to be approximated as expected.
+
+#![allow(dead_code)]
+// compile-pass
+
+struct SomeStruct<T>(fn(T));
+
+fn bar<'min,'max>(v: SomeStruct<&'min ()>)
+                  -> SomeStruct<&'max ()>
+    where 'max : 'min
+{
+    v
+}
+
+
+fn main() { }
diff --git a/src/test/ui/variance/variance-use-covariant-struct-1.rs b/src/test/ui/variance/variance-use-covariant-struct-1.rs
new file mode 100644
index 0000000..e19a35b
--- /dev/null
+++ b/src/test/ui/variance/variance-use-covariant-struct-1.rs
@@ -0,0 +1,13 @@
+// Test that a covariant struct does not permit the lifetime of a
+// reference to be enlarged.
+
+struct SomeStruct<T>(T);
+
+fn foo<'min,'max>(v: SomeStruct<&'min ()>)
+                  -> SomeStruct<&'max ()>
+    where 'max : 'min
+{
+    v //~ ERROR mismatched types
+}
+
+fn main() { }
diff --git a/src/test/ui/variance/variance-use-covariant-struct-1.stderr b/src/test/ui/variance/variance-use-covariant-struct-1.stderr
new file mode 100644
index 0000000..6ae7d12
--- /dev/null
+++ b/src/test/ui/variance/variance-use-covariant-struct-1.stderr
@@ -0,0 +1,22 @@
+error[E0308]: mismatched types
+  --> $DIR/variance-use-covariant-struct-1.rs:10:5
+   |
+LL |     v
+   |     ^ lifetime mismatch
+   |
+   = note: expected type `SomeStruct<&'max ()>`
+              found type `SomeStruct<&'min ()>`
+note: the lifetime 'min as defined on the function body at 6:8...
+  --> $DIR/variance-use-covariant-struct-1.rs:6:8
+   |
+LL | fn foo<'min,'max>(v: SomeStruct<&'min ()>)
+   |        ^^^^
+note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 6:13
+  --> $DIR/variance-use-covariant-struct-1.rs:6:13
+   |
+LL | fn foo<'min,'max>(v: SomeStruct<&'min ()>)
+   |             ^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/variance/variance-use-covariant-struct-2.rs b/src/test/ui/variance/variance-use-covariant-struct-2.rs
new file mode 100644
index 0000000..cb8159d
--- /dev/null
+++ b/src/test/ui/variance/variance-use-covariant-struct-2.rs
@@ -0,0 +1,16 @@
+// Test that a covariant struct permits the lifetime of a reference to
+// be shortened.
+
+#![allow(dead_code)]
+// compile-pass
+
+struct SomeStruct<T>(T);
+
+fn foo<'min,'max>(v: SomeStruct<&'max ()>)
+                  -> SomeStruct<&'min ()>
+    where 'max : 'min
+{
+    v
+}
+
+fn main() { }
diff --git a/src/test/ui/variance/variance-use-invariant-struct-1.rs b/src/test/ui/variance/variance-use-invariant-struct-1.rs
new file mode 100644
index 0000000..4772a9f
--- /dev/null
+++ b/src/test/ui/variance/variance-use-invariant-struct-1.rs
@@ -0,0 +1,23 @@
+// Test various uses of structs with distint variances to make sure
+// they permit lifetimes to be approximated as expected.
+
+
+
+struct SomeStruct<T>(*mut T);
+
+fn foo<'min,'max>(v: SomeStruct<&'max ()>)
+                  -> SomeStruct<&'min ()>
+    where 'max : 'min
+{
+    v //~ ERROR mismatched types
+}
+
+fn bar<'min,'max>(v: SomeStruct<&'min ()>)
+                  -> SomeStruct<&'max ()>
+    where 'max : 'min
+{
+    v //~ ERROR mismatched types
+}
+
+
+fn main() { }
diff --git a/src/test/ui/variance/variance-use-invariant-struct-1.stderr b/src/test/ui/variance/variance-use-invariant-struct-1.stderr
new file mode 100644
index 0000000..793954e
--- /dev/null
+++ b/src/test/ui/variance/variance-use-invariant-struct-1.stderr
@@ -0,0 +1,41 @@
+error[E0308]: mismatched types
+  --> $DIR/variance-use-invariant-struct-1.rs:12:5
+   |
+LL |     v
+   |     ^ lifetime mismatch
+   |
+   = note: expected type `SomeStruct<&'min ()>`
+              found type `SomeStruct<&'max ()>`
+note: the lifetime 'min as defined on the function body at 8:8...
+  --> $DIR/variance-use-invariant-struct-1.rs:8:8
+   |
+LL | fn foo<'min,'max>(v: SomeStruct<&'max ()>)
+   |        ^^^^
+note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 8:13
+  --> $DIR/variance-use-invariant-struct-1.rs:8:13
+   |
+LL | fn foo<'min,'max>(v: SomeStruct<&'max ()>)
+   |             ^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/variance-use-invariant-struct-1.rs:19:5
+   |
+LL |     v
+   |     ^ lifetime mismatch
+   |
+   = note: expected type `SomeStruct<&'max ()>`
+              found type `SomeStruct<&'min ()>`
+note: the lifetime 'min as defined on the function body at 15:8...
+  --> $DIR/variance-use-invariant-struct-1.rs:15:8
+   |
+LL | fn bar<'min,'max>(v: SomeStruct<&'min ()>)
+   |        ^^^^
+note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 15:13
+  --> $DIR/variance-use-invariant-struct-1.rs:15:13
+   |
+LL | fn bar<'min,'max>(v: SomeStruct<&'min ()>)
+   |             ^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/variants/auxiliary/variant-namespacing.rs b/src/test/ui/variants/auxiliary/variant-namespacing.rs
new file mode 100644
index 0000000..7ba601a
--- /dev/null
+++ b/src/test/ui/variants/auxiliary/variant-namespacing.rs
@@ -0,0 +1,5 @@
+pub enum XE {
+    XStruct { a: u8 },
+    XTuple(u8),
+    XUnit,
+}
diff --git a/src/test/ui/variants/variant-namespacing.rs b/src/test/ui/variants/variant-namespacing.rs
new file mode 100644
index 0000000..ceb7d27
--- /dev/null
+++ b/src/test/ui/variants/variant-namespacing.rs
@@ -0,0 +1,33 @@
+// aux-build:variant-namespacing.rs
+
+enum E {
+    Struct { a: u8 },
+    Tuple(u8),
+    Unit,
+}
+
+type Struct = u8;
+type Tuple = u8;
+type Unit = u8;
+type XStruct = u8;
+type XTuple = u8;
+type XUnit = u8;
+
+const Struct: u8 = 0;
+const Tuple: u8 = 0;
+const Unit: u8 = 0;
+const XStruct: u8 = 0;
+const XTuple: u8 = 0;
+const XUnit: u8 = 0;
+
+extern crate variant_namespacing;
+pub use variant_namespacing::XE::{XStruct, XTuple, XUnit};
+//~^ ERROR the name `XStruct` is defined multiple times
+//~| ERROR the name `XTuple` is defined multiple times
+//~| ERROR the name `XUnit` is defined multiple times
+pub use E::{Struct, Tuple, Unit};
+//~^ ERROR the name `Struct` is defined multiple times
+//~| ERROR the name `Tuple` is defined multiple times
+//~| ERROR the name `Unit` is defined multiple times
+
+fn main() {}
diff --git a/src/test/ui/variants/variant-namespacing.stderr b/src/test/ui/variants/variant-namespacing.stderr
new file mode 100644
index 0000000..3954da4
--- /dev/null
+++ b/src/test/ui/variants/variant-namespacing.stderr
@@ -0,0 +1,93 @@
+error[E0255]: the name `XStruct` is defined multiple times
+  --> $DIR/variant-namespacing.rs:24:35
+   |
+LL | type XStruct = u8;
+   | ------------------ previous definition of the type `XStruct` here
+...
+LL | pub use variant_namespacing::XE::{XStruct, XTuple, XUnit};
+   |                                   ^^^^^^^ `XStruct` reimported here
+   |
+   = note: `XStruct` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | pub use variant_namespacing::XE::{XStruct as OtherXStruct, XTuple, XUnit};
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0255]: the name `XTuple` is defined multiple times
+  --> $DIR/variant-namespacing.rs:24:44
+   |
+LL | type XTuple = u8;
+   | ----------------- previous definition of the type `XTuple` here
+...
+LL | pub use variant_namespacing::XE::{XStruct, XTuple, XUnit};
+   |                                            ^^^^^^ `XTuple` reimported here
+   |
+   = note: `XTuple` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | pub use variant_namespacing::XE::{XStruct, XTuple as OtherXTuple, XUnit};
+   |                                            ^^^^^^^^^^^^^^^^^^^^^
+
+error[E0255]: the name `XUnit` is defined multiple times
+  --> $DIR/variant-namespacing.rs:24:52
+   |
+LL | type XUnit = u8;
+   | ---------------- previous definition of the type `XUnit` here
+...
+LL | pub use variant_namespacing::XE::{XStruct, XTuple, XUnit};
+   |                                                    ^^^^^ `XUnit` reimported here
+   |
+   = note: `XUnit` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | pub use variant_namespacing::XE::{XStruct, XTuple, XUnit as OtherXUnit};
+   |                                                    ^^^^^^^^^^^^^^^^^^^
+
+error[E0255]: the name `Struct` is defined multiple times
+  --> $DIR/variant-namespacing.rs:28:13
+   |
+LL | type Struct = u8;
+   | ----------------- previous definition of the type `Struct` here
+...
+LL | pub use E::{Struct, Tuple, Unit};
+   |             ^^^^^^ `Struct` reimported here
+   |
+   = note: `Struct` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | pub use E::{Struct as OtherStruct, Tuple, Unit};
+   |             ^^^^^^^^^^^^^^^^^^^^^
+
+error[E0255]: the name `Tuple` is defined multiple times
+  --> $DIR/variant-namespacing.rs:28:21
+   |
+LL | type Tuple = u8;
+   | ---------------- previous definition of the type `Tuple` here
+...
+LL | pub use E::{Struct, Tuple, Unit};
+   |                     ^^^^^ `Tuple` reimported here
+   |
+   = note: `Tuple` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | pub use E::{Struct, Tuple as OtherTuple, Unit};
+   |                     ^^^^^^^^^^^^^^^^^^^
+
+error[E0255]: the name `Unit` is defined multiple times
+  --> $DIR/variant-namespacing.rs:28:28
+   |
+LL | type Unit = u8;
+   | --------------- previous definition of the type `Unit` here
+...
+LL | pub use E::{Struct, Tuple, Unit};
+   |                            ^^^^ `Unit` reimported here
+   |
+   = note: `Unit` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | pub use E::{Struct, Tuple, Unit as OtherUnit};
+   |                            ^^^^^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0255`.
diff --git a/src/test/ui/variants/variant-size-differences.rs b/src/test/ui/variants/variant-size-differences.rs
new file mode 100644
index 0000000..2198199
--- /dev/null
+++ b/src/test/ui/variants/variant-size-differences.rs
@@ -0,0 +1,8 @@
+#![deny(variant_size_differences)]
+
+enum _En {
+    V0(u8),
+    VBig([u8; 1024]),   //~ ERROR variant is more than three times larger
+}
+
+fn main() {}
diff --git a/src/test/ui/variants/variant-size-differences.stderr b/src/test/ui/variants/variant-size-differences.stderr
new file mode 100644
index 0000000..c82c253
--- /dev/null
+++ b/src/test/ui/variants/variant-size-differences.stderr
@@ -0,0 +1,14 @@
+error: enum variant is more than three times larger (1024 bytes) than the next largest
+  --> $DIR/variant-size-differences.rs:5:5
+   |
+LL |     VBig([u8; 1024]),
+   |     ^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/variant-size-differences.rs:1:9
+   |
+LL | #![deny(variant_size_differences)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/variants/variant-used-as-type.rs b/src/test/ui/variants/variant-used-as-type.rs
new file mode 100644
index 0000000..f27db10
--- /dev/null
+++ b/src/test/ui/variants/variant-used-as-type.rs
@@ -0,0 +1,20 @@
+// Test error message when enum variants are used as types
+
+
+// issue 21225
+enum Ty {
+    A,
+    B(Ty::A),
+    //~^ ERROR expected type, found variant `Ty::A`
+}
+
+
+// issue 19197
+enum E {
+    A
+}
+
+impl E::A {}
+//~^ ERROR expected type, found variant `E::A`
+
+fn main() {}
diff --git a/src/test/ui/variants/variant-used-as-type.stderr b/src/test/ui/variants/variant-used-as-type.stderr
new file mode 100644
index 0000000..fdfc044
--- /dev/null
+++ b/src/test/ui/variants/variant-used-as-type.stderr
@@ -0,0 +1,27 @@
+error[E0573]: expected type, found variant `Ty::A`
+  --> $DIR/variant-used-as-type.rs:7:7
+   |
+LL |     B(Ty::A),
+   |       ^^^^^ not a type
+help: try using the variant's enum
+   |
+LL |     B(E),
+   |       ^
+LL |     B(Ty),
+   |       ^^
+
+error[E0573]: expected type, found variant `E::A`
+  --> $DIR/variant-used-as-type.rs:17:6
+   |
+LL | impl E::A {}
+   |      ^^^^ not a type
+help: try using the variant's enum
+   |
+LL | impl E {}
+   |      ^
+LL | impl Ty {}
+   |      ^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0573`.
diff --git a/src/test/ui/vec/vec-macro-with-comma-only.rs b/src/test/ui/vec/vec-macro-with-comma-only.rs
new file mode 100644
index 0000000..574a53c
--- /dev/null
+++ b/src/test/ui/vec/vec-macro-with-comma-only.rs
@@ -0,0 +1,3 @@
+pub fn main() {
+    vec![,]; //~ ERROR no rules expected the token `,`
+}
diff --git a/src/test/ui/vec/vec-macro-with-comma-only.stderr b/src/test/ui/vec/vec-macro-with-comma-only.stderr
new file mode 100644
index 0000000..abbee34
--- /dev/null
+++ b/src/test/ui/vec/vec-macro-with-comma-only.stderr
@@ -0,0 +1,8 @@
+error: no rules expected the token `,`
+  --> $DIR/vec-macro-with-comma-only.rs:2:10
+   |
+LL |     vec![,];
+   |          ^ no rules expected this token in macro call
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/vec/vec-mut-iter-borrow.nll.stderr b/src/test/ui/vec/vec-mut-iter-borrow.nll.stderr
new file mode 100644
index 0000000..679fd89
--- /dev/null
+++ b/src/test/ui/vec/vec-mut-iter-borrow.nll.stderr
@@ -0,0 +1,14 @@
+error[E0499]: cannot borrow `xs` as mutable more than once at a time
+  --> $DIR/vec-mut-iter-borrow.rs:5:9
+   |
+LL |     for x in &mut xs {
+   |              -------
+   |              |
+   |              first mutable borrow occurs here
+   |              first borrow later used here
+LL |         xs.push(1)
+   |         ^^ second mutable borrow occurs here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/vec/vec-mut-iter-borrow.rs b/src/test/ui/vec/vec-mut-iter-borrow.rs
new file mode 100644
index 0000000..4aa7374
--- /dev/null
+++ b/src/test/ui/vec/vec-mut-iter-borrow.rs
@@ -0,0 +1,7 @@
+fn main() {
+    let mut xs: Vec<isize> = vec![];
+
+    for x in &mut xs {
+        xs.push(1) //~ ERROR cannot borrow `xs`
+    }
+}
diff --git a/src/test/ui/vec/vec-mut-iter-borrow.stderr b/src/test/ui/vec/vec-mut-iter-borrow.stderr
new file mode 100644
index 0000000..ec16d2b
--- /dev/null
+++ b/src/test/ui/vec/vec-mut-iter-borrow.stderr
@@ -0,0 +1,14 @@
+error[E0499]: cannot borrow `xs` as mutable more than once at a time
+  --> $DIR/vec-mut-iter-borrow.rs:5:9
+   |
+LL |     for x in &mut xs {
+   |                   --
+   |                   ||
+   |                   |first borrow ends here
+   |                   first mutable borrow occurs here
+LL |         xs.push(1)
+   |         ^^ second mutable borrow occurs here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/vec/vec-res-add.rs b/src/test/ui/vec/vec-res-add.rs
new file mode 100644
index 0000000..ea2aa6c
--- /dev/null
+++ b/src/test/ui/vec/vec-res-add.rs
@@ -0,0 +1,19 @@
+#[derive(Debug)]
+struct R {
+  i:isize
+}
+
+fn r(i:isize) -> R { R { i: i } }
+
+impl Drop for R {
+    fn drop(&mut self) {}
+}
+
+fn main() {
+    // This can't make sense as it would copy the classes
+    let i = vec![r(0)];
+    let j = vec![r(1)];
+    let k = i + j;
+    //~^ ERROR binary operation `+` cannot be applied to type
+    println!("{:?}", j);
+}
diff --git a/src/test/ui/vec/vec-res-add.stderr b/src/test/ui/vec/vec-res-add.stderr
new file mode 100644
index 0000000..78b70f0
--- /dev/null
+++ b/src/test/ui/vec/vec-res-add.stderr
@@ -0,0 +1,13 @@
+error[E0369]: binary operation `+` cannot be applied to type `std::vec::Vec<R>`
+  --> $DIR/vec-res-add.rs:16:15
+   |
+LL |     let k = i + j;
+   |             - ^ - std::vec::Vec<R>
+   |             |
+   |             std::vec::Vec<R>
+   |
+   = note: an implementation of `std::ops::Add` might be missing for `std::vec::Vec<R>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0369`.
diff --git a/src/test/ui/vector-cast-weirdness.rs b/src/test/ui/vector-cast-weirdness.rs
new file mode 100644
index 0000000..79b9243
--- /dev/null
+++ b/src/test/ui/vector-cast-weirdness.rs
@@ -0,0 +1,24 @@
+// Issue #14893. Tests that casts from vectors don't behave strangely in the
+// presence of the `_` type shorthand notation.
+// Update: after a change to the way casts are done, we have more type information
+// around and so the errors here are no longer exactly the same.
+
+struct X {
+    y: [u8; 2],
+}
+
+fn main() {
+    let x1 = X { y: [0, 0] };
+
+    // No longer a type mismatch - the `_` can be fully resolved by type inference.
+    let p1: *const u8 = &x1.y as *const _;
+    let t1: *const [u8; 2] = &x1.y as *const _;
+    let h1: *const [u8; 2] = &x1.y as *const [u8; 2];
+
+    let mut x1 = X { y: [0, 0] };
+
+    // This is still an error since we don't allow casts from &mut [T; n] to *mut T.
+    let p1: *mut u8 = &mut x1.y as *mut _;  //~ ERROR casting
+    let t1: *mut [u8; 2] = &mut x1.y as *mut _;
+    let h1: *mut [u8; 2] = &mut x1.y as *mut [u8; 2];
+}
diff --git a/src/test/ui/vector-cast-weirdness.stderr b/src/test/ui/vector-cast-weirdness.stderr
new file mode 100644
index 0000000..37055bb
--- /dev/null
+++ b/src/test/ui/vector-cast-weirdness.stderr
@@ -0,0 +1,9 @@
+error[E0606]: casting `&mut [u8; 2]` as `*mut u8` is invalid
+  --> $DIR/vector-cast-weirdness.rs:21:23
+   |
+LL |     let p1: *mut u8 = &mut x1.y as *mut _;
+   |                       ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0606`.
diff --git a/src/test/ui/vector-no-ann.rs b/src/test/ui/vector-no-ann.rs
new file mode 100644
index 0000000..200364a
--- /dev/null
+++ b/src/test/ui/vector-no-ann.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let _foo = Vec::new();
+    //~^ ERROR type annotations needed [E0282]
+}
diff --git a/src/test/ui/vector-no-ann.stderr b/src/test/ui/vector-no-ann.stderr
new file mode 100644
index 0000000..01b569f
--- /dev/null
+++ b/src/test/ui/vector-no-ann.stderr
@@ -0,0 +1,11 @@
+error[E0282]: type annotations needed
+  --> $DIR/vector-no-ann.rs:2:16
+   |
+LL |     let _foo = Vec::new();
+   |         ----   ^^^^^^^^ cannot infer type for `T`
+   |         |
+   |         consider giving `_foo` a type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/vtable-res-trait-param.rs b/src/test/ui/vtable-res-trait-param.rs
new file mode 100644
index 0000000..3d7c2eb
--- /dev/null
+++ b/src/test/ui/vtable-res-trait-param.rs
@@ -0,0 +1,23 @@
+trait TraitA {
+    fn method_a(&self) -> isize;
+}
+
+trait TraitB {
+    fn gimme_an_a<A:TraitA>(&self, a: A) -> isize;
+}
+
+impl TraitB for isize {
+    fn gimme_an_a<A:TraitA>(&self, a: A) -> isize {
+        a.method_a() + *self
+    }
+}
+
+fn call_it<B:TraitB>(b: B)  -> isize {
+    let y = 4;
+    b.gimme_an_a(y) //~ ERROR `{integer}: TraitA` is not satisfied
+}
+
+fn main() {
+    let x = 3;
+    assert_eq!(call_it(x), 22);
+}
diff --git a/src/test/ui/vtable-res-trait-param.stderr b/src/test/ui/vtable-res-trait-param.stderr
new file mode 100644
index 0000000..58a8897
--- /dev/null
+++ b/src/test/ui/vtable-res-trait-param.stderr
@@ -0,0 +1,9 @@
+error[E0277]: the trait bound `{integer}: TraitA` is not satisfied
+  --> $DIR/vtable-res-trait-param.rs:17:7
+   |
+LL |     b.gimme_an_a(y)
+   |       ^^^^^^^^^^ the trait `TraitA` is not implemented for `{integer}`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/walk-struct-literal-with.nll.stderr b/src/test/ui/walk-struct-literal-with.nll.stderr
new file mode 100644
index 0000000..eeb594a
--- /dev/null
+++ b/src/test/ui/walk-struct-literal-with.nll.stderr
@@ -0,0 +1,13 @@
+error[E0382]: borrow of moved value: `start`
+  --> $DIR/walk-struct-literal-with.rs:16:20
+   |
+LL |     let start = Mine{test:"Foo".to_string(), other_val:0};
+   |         ----- move occurs because `start` has type `Mine`, which does not implement the `Copy` trait
+LL |     let end = Mine{other_val:1, ..start.make_string_bar()};
+   |                                   ----- value moved here
+LL |     println!("{}", start.test);
+   |                    ^^^^^^^^^^ value borrowed here after move
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/walk-struct-literal-with.rs b/src/test/ui/walk-struct-literal-with.rs
new file mode 100644
index 0000000..31dfd58
--- /dev/null
+++ b/src/test/ui/walk-struct-literal-with.rs
@@ -0,0 +1,17 @@
+struct Mine{
+    test: String,
+    other_val: isize
+}
+
+impl Mine{
+    fn make_string_bar(mut self) -> Mine{
+        self.test = "Bar".to_string();
+        self
+    }
+}
+
+fn main(){
+    let start = Mine{test:"Foo".to_string(), other_val:0};
+    let end = Mine{other_val:1, ..start.make_string_bar()};
+    println!("{}", start.test); //~ ERROR use of moved value: `start.test`
+}
diff --git a/src/test/ui/walk-struct-literal-with.stderr b/src/test/ui/walk-struct-literal-with.stderr
new file mode 100644
index 0000000..d5351eb
--- /dev/null
+++ b/src/test/ui/walk-struct-literal-with.stderr
@@ -0,0 +1,13 @@
+error[E0382]: use of moved value: `start.test`
+  --> $DIR/walk-struct-literal-with.rs:16:20
+   |
+LL |     let end = Mine{other_val:1, ..start.make_string_bar()};
+   |                                   ----- value moved here
+LL |     println!("{}", start.test);
+   |                    ^^^^^^^^^^ value used here after move
+   |
+   = note: move occurs because `start` has type `Mine`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/warn-path-statement.rs b/src/test/ui/warn-path-statement.rs
new file mode 100644
index 0000000..e8525f8
--- /dev/null
+++ b/src/test/ui/warn-path-statement.rs
@@ -0,0 +1,6 @@
+// compile-flags: -D path-statements
+fn main() {
+
+    let x = 10;
+    x; //~ ERROR path statement with no effect
+}
diff --git a/src/test/ui/warn-path-statement.stderr b/src/test/ui/warn-path-statement.stderr
new file mode 100644
index 0000000..30afb99
--- /dev/null
+++ b/src/test/ui/warn-path-statement.stderr
@@ -0,0 +1,10 @@
+error: path statement with no effect
+  --> $DIR/warn-path-statement.rs:5:5
+   |
+LL |     x;
+   |     ^^
+   |
+   = note: requested on the command line with `-D path-statements`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/wasm-custom-section-relocations.rs b/src/test/ui/wasm-custom-section-relocations.rs
new file mode 100644
index 0000000..c3cca3a
--- /dev/null
+++ b/src/test/ui/wasm-custom-section-relocations.rs
@@ -0,0 +1,15 @@
+// only-wasm32
+
+#[link_section = "test"]
+pub static A: &[u8] = &[1]; //~ ERROR: no extra levels of indirection
+
+#[link_section = "test"]
+pub static B: [u8; 3] = [1, 2, 3];
+
+#[link_section = "test"]
+pub static C: usize = 3;
+
+#[link_section = "test"]
+pub static D: &usize = &C; //~ ERROR: no extra levels of indirection
+
+fn main() {}
diff --git a/src/test/ui/wasm-custom-section-relocations.stderr b/src/test/ui/wasm-custom-section-relocations.stderr
new file mode 100644
index 0000000..eb8ab26
--- /dev/null
+++ b/src/test/ui/wasm-custom-section-relocations.stderr
@@ -0,0 +1,14 @@
+error: statics with a custom `#[link_section]` must be a simple list of bytes on the wasm target with no extra levels of indirection such as references
+  --> $DIR/wasm-custom-section-relocations.rs:4:1
+   |
+LL | pub static A: &[u8] = &[1];
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: statics with a custom `#[link_section]` must be a simple list of bytes on the wasm target with no extra levels of indirection such as references
+  --> $DIR/wasm-custom-section-relocations.rs:13:1
+   |
+LL | pub static D: &usize = &C;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/wasm-import-module.rs b/src/test/ui/wasm-import-module.rs
new file mode 100644
index 0000000..618bf19
--- /dev/null
+++ b/src/test/ui/wasm-import-module.rs
@@ -0,0 +1,11 @@
+#[link(name = "...", wasm_import_module)] //~ ERROR: must be of the form
+extern {}
+
+#[link(name = "...", wasm_import_module(x))] //~ ERROR: must be of the form
+extern {}
+
+#[link(name = "...", wasm_import_module())] //~ ERROR: must be of the form
+extern {}
+
+fn main() {}
+
diff --git a/src/test/ui/wasm-import-module.stderr b/src/test/ui/wasm-import-module.stderr
new file mode 100644
index 0000000..20eec4c
--- /dev/null
+++ b/src/test/ui/wasm-import-module.stderr
@@ -0,0 +1,20 @@
+error: must be of the form #[link(wasm_import_module = "...")]
+  --> $DIR/wasm-import-module.rs:1:22
+   |
+LL | #[link(name = "...", wasm_import_module)]
+   |                      ^^^^^^^^^^^^^^^^^^
+
+error: must be of the form #[link(wasm_import_module = "...")]
+  --> $DIR/wasm-import-module.rs:4:22
+   |
+LL | #[link(name = "...", wasm_import_module(x))]
+   |                      ^^^^^^^^^^^^^^^^^^^^^
+
+error: must be of the form #[link(wasm_import_module = "...")]
+  --> $DIR/wasm-import-module.rs:7:22
+   |
+LL | #[link(name = "...", wasm_import_module())]
+   |                      ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/wf/wf-array-elem-sized.rs b/src/test/ui/wf/wf-array-elem-sized.rs
new file mode 100644
index 0000000..41c2d3c
--- /dev/null
+++ b/src/test/ui/wf/wf-array-elem-sized.rs
@@ -0,0 +1,11 @@
+// Check that array elemen types must be Sized. Issue #25692.
+
+
+#![allow(dead_code)]
+
+struct Foo {
+    foo: [[u8]], //~ ERROR E0277
+}
+
+
+fn main() { }
diff --git a/src/test/ui/wf/wf-array-elem-sized.stderr b/src/test/ui/wf/wf-array-elem-sized.stderr
new file mode 100644
index 0000000..b222d07
--- /dev/null
+++ b/src/test/ui/wf/wf-array-elem-sized.stderr
@@ -0,0 +1,13 @@
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/wf-array-elem-sized.rs:7:5
+   |
+LL |     foo: [[u8]],
+   |     ^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `[u8]`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: slice and array elements must have `Sized` type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/wf/wf-const-type.rs b/src/test/ui/wf/wf-const-type.rs
new file mode 100644
index 0000000..df79aa2
--- /dev/null
+++ b/src/test/ui/wf/wf-const-type.rs
@@ -0,0 +1,14 @@
+// Test that we check the types of constants are well-formed.
+
+#![feature(associated_type_defaults)]
+
+#![allow(dead_code)]
+
+struct IsCopy<T:Copy> { t: T }
+struct NotCopy;
+
+const FOO: IsCopy<Option<NotCopy>> = IsCopy { t: None };
+//~^ ERROR E0277
+
+
+fn main() { }
diff --git a/src/test/ui/wf/wf-const-type.stderr b/src/test/ui/wf/wf-const-type.stderr
new file mode 100644
index 0000000..4df4292
--- /dev/null
+++ b/src/test/ui/wf/wf-const-type.stderr
@@ -0,0 +1,16 @@
+error[E0277]: the trait bound `NotCopy: std::marker::Copy` is not satisfied
+  --> $DIR/wf-const-type.rs:10:12
+   |
+LL | const FOO: IsCopy<Option<NotCopy>> = IsCopy { t: None };
+   |            ^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `NotCopy`
+   |
+   = note: required because of the requirements on the impl of `std::marker::Copy` for `std::option::Option<NotCopy>`
+note: required by `IsCopy`
+  --> $DIR/wf-const-type.rs:7:1
+   |
+LL | struct IsCopy<T:Copy> { t: T }
+   | ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/wf/wf-enum-bound.rs b/src/test/ui/wf/wf-enum-bound.rs
new file mode 100644
index 0000000..c9eb9d8
--- /dev/null
+++ b/src/test/ui/wf/wf-enum-bound.rs
@@ -0,0 +1,16 @@
+// Test that we check enum bounds for WFedness.
+
+#![feature(associated_type_defaults)]
+
+#![allow(dead_code)]
+
+trait ExtraCopy<T:Copy> { }
+
+enum SomeEnum<T,U> //~ ERROR E0277
+    where T: ExtraCopy<U>
+{
+    SomeVariant(T,U)
+}
+
+
+fn main() { }
diff --git a/src/test/ui/wf/wf-enum-bound.stderr b/src/test/ui/wf/wf-enum-bound.stderr
new file mode 100644
index 0000000..de28a88
--- /dev/null
+++ b/src/test/ui/wf/wf-enum-bound.stderr
@@ -0,0 +1,20 @@
+error[E0277]: the trait bound `U: std::marker::Copy` is not satisfied
+  --> $DIR/wf-enum-bound.rs:9:1
+   |
+LL | / enum SomeEnum<T,U>
+LL | |     where T: ExtraCopy<U>
+LL | | {
+LL | |     SomeVariant(T,U)
+LL | | }
+   | |_^ the trait `std::marker::Copy` is not implemented for `U`
+   |
+   = help: consider adding a `where U: std::marker::Copy` bound
+note: required by `ExtraCopy`
+  --> $DIR/wf-enum-bound.rs:7:1
+   |
+LL | trait ExtraCopy<T:Copy> { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/wf/wf-enum-fields-struct-variant.rs b/src/test/ui/wf/wf-enum-fields-struct-variant.rs
new file mode 100644
index 0000000..c25622f
--- /dev/null
+++ b/src/test/ui/wf/wf-enum-fields-struct-variant.rs
@@ -0,0 +1,18 @@
+// Test that we check struct fields for WFedness.
+
+#![feature(associated_type_defaults)]
+
+#![allow(dead_code)]
+
+struct IsCopy<T:Copy> {
+    value: T
+}
+
+enum AnotherEnum<A> {
+    AnotherVariant {
+        f: IsCopy<A> //~ ERROR E0277
+    }
+}
+
+
+fn main() { }
diff --git a/src/test/ui/wf/wf-enum-fields-struct-variant.stderr b/src/test/ui/wf/wf-enum-fields-struct-variant.stderr
new file mode 100644
index 0000000..6c1267c
--- /dev/null
+++ b/src/test/ui/wf/wf-enum-fields-struct-variant.stderr
@@ -0,0 +1,16 @@
+error[E0277]: the trait bound `A: std::marker::Copy` is not satisfied
+  --> $DIR/wf-enum-fields-struct-variant.rs:13:9
+   |
+LL |         f: IsCopy<A>
+   |         ^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `A`
+   |
+   = help: consider adding a `where A: std::marker::Copy` bound
+note: required by `IsCopy`
+  --> $DIR/wf-enum-fields-struct-variant.rs:7:1
+   |
+LL | struct IsCopy<T:Copy> {
+   | ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/wf/wf-enum-fields.rs b/src/test/ui/wf/wf-enum-fields.rs
new file mode 100644
index 0000000..a465ffe
--- /dev/null
+++ b/src/test/ui/wf/wf-enum-fields.rs
@@ -0,0 +1,16 @@
+// Test that we check struct fields for WFedness.
+
+#![feature(associated_type_defaults)]
+
+#![allow(dead_code)]
+
+struct IsCopy<T:Copy> {
+    value: T
+}
+
+enum SomeEnum<A> {
+    SomeVariant(IsCopy<A>) //~ ERROR E0277
+}
+
+
+fn main() { }
diff --git a/src/test/ui/wf/wf-enum-fields.stderr b/src/test/ui/wf/wf-enum-fields.stderr
new file mode 100644
index 0000000..9c4eec6
--- /dev/null
+++ b/src/test/ui/wf/wf-enum-fields.stderr
@@ -0,0 +1,16 @@
+error[E0277]: the trait bound `A: std::marker::Copy` is not satisfied
+  --> $DIR/wf-enum-fields.rs:12:17
+   |
+LL |     SomeVariant(IsCopy<A>)
+   |                 ^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `A`
+   |
+   = help: consider adding a `where A: std::marker::Copy` bound
+note: required by `IsCopy`
+  --> $DIR/wf-enum-fields.rs:7:1
+   |
+LL | struct IsCopy<T:Copy> {
+   | ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/wf/wf-fn-where-clause.rs b/src/test/ui/wf/wf-fn-where-clause.rs
new file mode 100644
index 0000000..5fd567b
--- /dev/null
+++ b/src/test/ui/wf/wf-fn-where-clause.rs
@@ -0,0 +1,17 @@
+// Test that we check where-clauses on fn items.
+
+
+#![allow(dead_code)]
+
+trait ExtraCopy<T:Copy> { }
+
+fn foo<T,U>() where T: ExtraCopy<U> //~ ERROR E0277
+{
+}
+
+fn bar() where Vec<dyn Copy>:, {}
+//~^ ERROR E0277
+//~| ERROR E0038
+
+
+fn main() { }
diff --git a/src/test/ui/wf/wf-fn-where-clause.stderr b/src/test/ui/wf/wf-fn-where-clause.stderr
new file mode 100644
index 0000000..f1648aa
--- /dev/null
+++ b/src/test/ui/wf/wf-fn-where-clause.stderr
@@ -0,0 +1,37 @@
+error[E0277]: the trait bound `U: std::marker::Copy` is not satisfied
+  --> $DIR/wf-fn-where-clause.rs:8:1
+   |
+LL | / fn foo<T,U>() where T: ExtraCopy<U>
+LL | | {
+LL | | }
+   | |_^ the trait `std::marker::Copy` is not implemented for `U`
+   |
+   = help: consider adding a `where U: std::marker::Copy` bound
+note: required by `ExtraCopy`
+  --> $DIR/wf-fn-where-clause.rs:6:1
+   |
+LL | trait ExtraCopy<T:Copy> { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the size for values of type `(dyn std::marker::Copy + 'static)` cannot be known at compilation time
+  --> $DIR/wf-fn-where-clause.rs:12:1
+   |
+LL | fn bar() where Vec<dyn Copy>:, {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `(dyn std::marker::Copy + 'static)`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: required by `std::vec::Vec`
+
+error[E0038]: the trait `std::marker::Copy` cannot be made into an object
+  --> $DIR/wf-fn-where-clause.rs:12:1
+   |
+LL | fn bar() where Vec<dyn Copy>:, {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` cannot be made into an object
+   |
+   = note: the trait cannot require that `Self : Sized`
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0038, E0277.
+For more information about an error, try `rustc --explain E0038`.
diff --git a/src/test/ui/wf/wf-impl-associated-type-region.rs b/src/test/ui/wf/wf-impl-associated-type-region.rs
new file mode 100644
index 0000000..1bf8d36
--- /dev/null
+++ b/src/test/ui/wf/wf-impl-associated-type-region.rs
@@ -0,0 +1,14 @@
+// Check that we require that associated types in an impl are well-formed.
+
+
+
+pub trait Foo<'a> {
+    type Bar;
+}
+
+impl<'a, T> Foo<'a> for T {
+    type Bar = &'a T; //~ ERROR E0309
+}
+
+
+fn main() { }
diff --git a/src/test/ui/wf/wf-impl-associated-type-region.stderr b/src/test/ui/wf/wf-impl-associated-type-region.stderr
new file mode 100644
index 0000000..9cc3602
--- /dev/null
+++ b/src/test/ui/wf/wf-impl-associated-type-region.stderr
@@ -0,0 +1,17 @@
+error[E0309]: the parameter type `T` may not live long enough
+  --> $DIR/wf-impl-associated-type-region.rs:10:5
+   |
+LL | impl<'a, T> Foo<'a> for T {
+   |          - help: consider adding an explicit lifetime bound `T: 'a`...
+LL |     type Bar = &'a T;
+   |     ^^^^^^^^^^^^^^^^^
+   |
+note: ...so that the reference type `&'a T` does not outlive the data it points at
+  --> $DIR/wf-impl-associated-type-region.rs:10:5
+   |
+LL |     type Bar = &'a T;
+   |     ^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0309`.
diff --git a/src/test/ui/wf/wf-impl-associated-type-trait.rs b/src/test/ui/wf/wf-impl-associated-type-trait.rs
new file mode 100644
index 0000000..84e628e
--- /dev/null
+++ b/src/test/ui/wf/wf-impl-associated-type-trait.rs
@@ -0,0 +1,22 @@
+// Check that we require that associated types in an impl are well-formed.
+
+
+#![allow(dead_code)]
+
+pub trait MyHash { }
+
+pub struct MySet<T:MyHash> {
+    data: Vec<T>
+}
+
+pub trait Foo {
+    type Bar;
+}
+
+impl<T> Foo for T {
+    type Bar = MySet<T>;
+    //~^ ERROR the trait bound `T: MyHash` is not satisfied
+}
+
+
+fn main() { }
diff --git a/src/test/ui/wf/wf-impl-associated-type-trait.stderr b/src/test/ui/wf/wf-impl-associated-type-trait.stderr
new file mode 100644
index 0000000..158b55a
--- /dev/null
+++ b/src/test/ui/wf/wf-impl-associated-type-trait.stderr
@@ -0,0 +1,16 @@
+error[E0277]: the trait bound `T: MyHash` is not satisfied
+  --> $DIR/wf-impl-associated-type-trait.rs:17:5
+   |
+LL |     type Bar = MySet<T>;
+   |     ^^^^^^^^^^^^^^^^^^^^ the trait `MyHash` is not implemented for `T`
+   |
+   = help: consider adding a `where T: MyHash` bound
+note: required by `MySet`
+  --> $DIR/wf-impl-associated-type-trait.rs:8:1
+   |
+LL | pub struct MySet<T:MyHash> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/wf/wf-in-fn-arg.rs b/src/test/ui/wf/wf-in-fn-arg.rs
new file mode 100644
index 0000000..18df723
--- /dev/null
+++ b/src/test/ui/wf/wf-in-fn-arg.rs
@@ -0,0 +1,14 @@
+// Check that we enforce WF conditions also for argument types in fn items.
+
+#![feature(rustc_attrs)]
+#![allow(dead_code)]
+
+struct MustBeCopy<T:Copy> {
+    t: T
+}
+
+fn bar<T>(_: &MustBeCopy<T>) //~ ERROR E0277
+{
+}
+
+fn main() { }
diff --git a/src/test/ui/wf/wf-in-fn-arg.stderr b/src/test/ui/wf/wf-in-fn-arg.stderr
new file mode 100644
index 0000000..8635dad
--- /dev/null
+++ b/src/test/ui/wf/wf-in-fn-arg.stderr
@@ -0,0 +1,18 @@
+error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
+  --> $DIR/wf-in-fn-arg.rs:10:1
+   |
+LL | / fn bar<T>(_: &MustBeCopy<T>)
+LL | | {
+LL | | }
+   | |_^ the trait `std::marker::Copy` is not implemented for `T`
+   |
+   = help: consider adding a `where T: std::marker::Copy` bound
+note: required by `MustBeCopy`
+  --> $DIR/wf-in-fn-arg.rs:6:1
+   |
+LL | struct MustBeCopy<T:Copy> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/wf/wf-in-fn-ret.rs b/src/test/ui/wf/wf-in-fn-ret.rs
new file mode 100644
index 0000000..4c95351
--- /dev/null
+++ b/src/test/ui/wf/wf-in-fn-ret.rs
@@ -0,0 +1,14 @@
+// Check that we enforce WF conditions also for return types in fn items.
+
+#![feature(rustc_attrs)]
+#![allow(dead_code)]
+
+struct MustBeCopy<T:Copy> {
+    t: T
+}
+
+fn bar<T>() -> MustBeCopy<T> //~ ERROR E0277
+{
+}
+
+fn main() { }
diff --git a/src/test/ui/wf/wf-in-fn-ret.stderr b/src/test/ui/wf/wf-in-fn-ret.stderr
new file mode 100644
index 0000000..3879f7b
--- /dev/null
+++ b/src/test/ui/wf/wf-in-fn-ret.stderr
@@ -0,0 +1,18 @@
+error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
+  --> $DIR/wf-in-fn-ret.rs:10:1
+   |
+LL | / fn bar<T>() -> MustBeCopy<T>
+LL | | {
+LL | | }
+   | |_^ the trait `std::marker::Copy` is not implemented for `T`
+   |
+   = help: consider adding a `where T: std::marker::Copy` bound
+note: required by `MustBeCopy`
+  --> $DIR/wf-in-fn-ret.rs:6:1
+   |
+LL | struct MustBeCopy<T:Copy> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/wf/wf-in-fn-type-arg.rs b/src/test/ui/wf/wf-in-fn-type-arg.rs
new file mode 100644
index 0000000..2917a8a
--- /dev/null
+++ b/src/test/ui/wf/wf-in-fn-type-arg.rs
@@ -0,0 +1,12 @@
+// Check that we enforce WF conditions also for types in fns.
+
+struct MustBeCopy<T:Copy> {
+    t: T
+}
+
+struct Bar<T> {
+    // needs T: Copy
+    x: fn(MustBeCopy<T>) //~ ERROR E0277
+}
+
+fn main() { }
diff --git a/src/test/ui/wf/wf-in-fn-type-arg.stderr b/src/test/ui/wf/wf-in-fn-type-arg.stderr
new file mode 100644
index 0000000..40cb4a7
--- /dev/null
+++ b/src/test/ui/wf/wf-in-fn-type-arg.stderr
@@ -0,0 +1,16 @@
+error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
+  --> $DIR/wf-in-fn-type-arg.rs:9:5
+   |
+LL |     x: fn(MustBeCopy<T>)
+   |     ^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
+   |
+   = help: consider adding a `where T: std::marker::Copy` bound
+note: required by `MustBeCopy`
+  --> $DIR/wf-in-fn-type-arg.rs:3:1
+   |
+LL | struct MustBeCopy<T:Copy> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/wf/wf-in-fn-type-ret.rs b/src/test/ui/wf/wf-in-fn-type-ret.rs
new file mode 100644
index 0000000..ab8e697
--- /dev/null
+++ b/src/test/ui/wf/wf-in-fn-type-ret.rs
@@ -0,0 +1,12 @@
+// Check that we enforce WF conditions also for types in fns.
+
+struct MustBeCopy<T:Copy> {
+    t: T
+}
+
+struct Foo<T> {
+    // needs T: 'static
+    x: fn() -> MustBeCopy<T> //~ ERROR E0277
+}
+
+fn main() { }
diff --git a/src/test/ui/wf/wf-in-fn-type-ret.stderr b/src/test/ui/wf/wf-in-fn-type-ret.stderr
new file mode 100644
index 0000000..059f164
--- /dev/null
+++ b/src/test/ui/wf/wf-in-fn-type-ret.stderr
@@ -0,0 +1,16 @@
+error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
+  --> $DIR/wf-in-fn-type-ret.rs:9:5
+   |
+LL |     x: fn() -> MustBeCopy<T>
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
+   |
+   = help: consider adding a `where T: std::marker::Copy` bound
+note: required by `MustBeCopy`
+  --> $DIR/wf-in-fn-type-ret.rs:3:1
+   |
+LL | struct MustBeCopy<T:Copy> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/wf/wf-in-fn-type-static.rs b/src/test/ui/wf/wf-in-fn-type-static.rs
new file mode 100644
index 0000000..73071dd
--- /dev/null
+++ b/src/test/ui/wf/wf-in-fn-type-static.rs
@@ -0,0 +1,22 @@
+// Check that we enforce WF conditions related to regions also for
+// types in fns.
+
+#![allow(dead_code)]
+
+
+struct MustBeCopy<T:Copy> {
+    t: T
+}
+
+struct Foo<T> {
+    // needs T: 'static
+    x: fn() -> &'static T //~ ERROR E0310
+}
+
+struct Bar<T> {
+    // needs T: Copy
+    x: fn(&'static T) //~ ERROR E0310
+}
+
+
+fn main() { }
diff --git a/src/test/ui/wf/wf-in-fn-type-static.stderr b/src/test/ui/wf/wf-in-fn-type-static.stderr
new file mode 100644
index 0000000..8952c78
--- /dev/null
+++ b/src/test/ui/wf/wf-in-fn-type-static.stderr
@@ -0,0 +1,33 @@
+error[E0310]: the parameter type `T` may not live long enough
+  --> $DIR/wf-in-fn-type-static.rs:13:5
+   |
+LL | struct Foo<T> {
+   |            - help: consider adding an explicit lifetime bound `T: 'static`...
+LL |     // needs T: 'static
+LL |     x: fn() -> &'static T
+   |     ^^^^^^^^^^^^^^^^^^^^^
+   |
+note: ...so that the reference type `&'static T` does not outlive the data it points at
+  --> $DIR/wf-in-fn-type-static.rs:13:5
+   |
+LL |     x: fn() -> &'static T
+   |     ^^^^^^^^^^^^^^^^^^^^^
+
+error[E0310]: the parameter type `T` may not live long enough
+  --> $DIR/wf-in-fn-type-static.rs:18:5
+   |
+LL | struct Bar<T> {
+   |            - help: consider adding an explicit lifetime bound `T: 'static`...
+LL |     // needs T: Copy
+LL |     x: fn(&'static T)
+   |     ^^^^^^^^^^^^^^^^^
+   |
+note: ...so that the reference type `&'static T` does not outlive the data it points at
+  --> $DIR/wf-in-fn-type-static.rs:18:5
+   |
+LL |     x: fn(&'static T)
+   |     ^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0310`.
diff --git a/src/test/ui/wf/wf-in-fn-where-clause.rs b/src/test/ui/wf/wf-in-fn-where-clause.rs
new file mode 100644
index 0000000..65a1771
--- /dev/null
+++ b/src/test/ui/wf/wf-in-fn-where-clause.rs
@@ -0,0 +1,15 @@
+// Check that we enforce WF conditions also for where clauses in fn items.
+
+
+#![allow(dead_code)]
+
+trait MustBeCopy<T:Copy> {
+}
+
+fn bar<T,U>() //~ ERROR E0277
+    where T: MustBeCopy<U>
+{
+}
+
+
+fn main() { }
diff --git a/src/test/ui/wf/wf-in-fn-where-clause.stderr b/src/test/ui/wf/wf-in-fn-where-clause.stderr
new file mode 100644
index 0000000..1e732a3
--- /dev/null
+++ b/src/test/ui/wf/wf-in-fn-where-clause.stderr
@@ -0,0 +1,19 @@
+error[E0277]: the trait bound `U: std::marker::Copy` is not satisfied
+  --> $DIR/wf-in-fn-where-clause.rs:9:1
+   |
+LL | / fn bar<T,U>()
+LL | |     where T: MustBeCopy<U>
+LL | | {
+LL | | }
+   | |_^ the trait `std::marker::Copy` is not implemented for `U`
+   |
+   = help: consider adding a `where U: std::marker::Copy` bound
+note: required by `MustBeCopy`
+  --> $DIR/wf-in-fn-where-clause.rs:6:1
+   |
+LL | trait MustBeCopy<T:Copy> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/wf/wf-in-obj-type-static.rs b/src/test/ui/wf/wf-in-obj-type-static.rs
new file mode 100644
index 0000000..858a75a
--- /dev/null
+++ b/src/test/ui/wf/wf-in-obj-type-static.rs
@@ -0,0 +1,18 @@
+// Check that we enforce WF conditions also for types in fns.
+
+
+#![allow(dead_code)]
+
+trait Object<T> { }
+
+struct MustBeCopy<T:Copy> {
+    t: T
+}
+
+struct Foo<T> {
+    // needs T: 'static
+    x: Object<&'static T> //~ ERROR E0310
+}
+
+
+fn main() { }
diff --git a/src/test/ui/wf/wf-in-obj-type-static.stderr b/src/test/ui/wf/wf-in-obj-type-static.stderr
new file mode 100644
index 0000000..cc06b92
--- /dev/null
+++ b/src/test/ui/wf/wf-in-obj-type-static.stderr
@@ -0,0 +1,18 @@
+error[E0310]: the parameter type `T` may not live long enough
+  --> $DIR/wf-in-obj-type-static.rs:14:5
+   |
+LL | struct Foo<T> {
+   |            - help: consider adding an explicit lifetime bound `T: 'static`...
+LL |     // needs T: 'static
+LL |     x: Object<&'static T>
+   |     ^^^^^^^^^^^^^^^^^^^^^
+   |
+note: ...so that the reference type `&'static T` does not outlive the data it points at
+  --> $DIR/wf-in-obj-type-static.rs:14:5
+   |
+LL |     x: Object<&'static T>
+   |     ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0310`.
diff --git a/src/test/ui/wf/wf-in-obj-type-trait.rs b/src/test/ui/wf/wf-in-obj-type-trait.rs
new file mode 100644
index 0000000..fad1da1
--- /dev/null
+++ b/src/test/ui/wf/wf-in-obj-type-trait.rs
@@ -0,0 +1,14 @@
+// Check that we enforce WF conditions also for types in fns.
+
+trait Object<T> { }
+
+struct MustBeCopy<T:Copy> {
+    t: T
+}
+
+struct Bar<T> {
+    // needs T: Copy
+    x: Object<MustBeCopy<T>> //~ ERROR E0277
+}
+
+fn main() { }
diff --git a/src/test/ui/wf/wf-in-obj-type-trait.stderr b/src/test/ui/wf/wf-in-obj-type-trait.stderr
new file mode 100644
index 0000000..94b3de7
--- /dev/null
+++ b/src/test/ui/wf/wf-in-obj-type-trait.stderr
@@ -0,0 +1,16 @@
+error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
+  --> $DIR/wf-in-obj-type-trait.rs:11:5
+   |
+LL |     x: Object<MustBeCopy<T>>
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
+   |
+   = help: consider adding a `where T: std::marker::Copy` bound
+note: required by `MustBeCopy`
+  --> $DIR/wf-in-obj-type-trait.rs:5:1
+   |
+LL | struct MustBeCopy<T:Copy> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/wf/wf-inherent-impl-method-where-clause.rs b/src/test/ui/wf/wf-inherent-impl-method-where-clause.rs
new file mode 100644
index 0000000..eb50fc0
--- /dev/null
+++ b/src/test/ui/wf/wf-inherent-impl-method-where-clause.rs
@@ -0,0 +1,17 @@
+// Test that we check where-clauses on inherent impl methods.
+
+#![feature(associated_type_defaults)]
+
+#![allow(dead_code)]
+
+trait ExtraCopy<T:Copy> { }
+
+struct Foo<T,U>(T,U);
+
+impl<T,U> Foo<T,U> {
+    fn foo(self) where T: ExtraCopy<U> //~ ERROR E0277
+    {}
+}
+
+
+fn main() { }
diff --git a/src/test/ui/wf/wf-inherent-impl-method-where-clause.stderr b/src/test/ui/wf/wf-inherent-impl-method-where-clause.stderr
new file mode 100644
index 0000000..b79093f
--- /dev/null
+++ b/src/test/ui/wf/wf-inherent-impl-method-where-clause.stderr
@@ -0,0 +1,17 @@
+error[E0277]: the trait bound `U: std::marker::Copy` is not satisfied
+  --> $DIR/wf-inherent-impl-method-where-clause.rs:12:5
+   |
+LL | /     fn foo(self) where T: ExtraCopy<U>
+LL | |     {}
+   | |______^ the trait `std::marker::Copy` is not implemented for `U`
+   |
+   = help: consider adding a `where U: std::marker::Copy` bound
+note: required by `ExtraCopy`
+  --> $DIR/wf-inherent-impl-method-where-clause.rs:7:1
+   |
+LL | trait ExtraCopy<T:Copy> { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/wf/wf-inherent-impl-where-clause.rs b/src/test/ui/wf/wf-inherent-impl-where-clause.rs
new file mode 100644
index 0000000..ac194fb
--- /dev/null
+++ b/src/test/ui/wf/wf-inherent-impl-where-clause.rs
@@ -0,0 +1,16 @@
+// Test that we check where-clauses on inherent impls.
+
+#![feature(associated_type_defaults)]
+
+#![allow(dead_code)]
+
+trait ExtraCopy<T:Copy> { }
+
+struct Foo<T,U>(T,U);
+
+impl<T,U> Foo<T,U> where T: ExtraCopy<U> //~ ERROR E0277
+{
+}
+
+
+fn main() { }
diff --git a/src/test/ui/wf/wf-inherent-impl-where-clause.stderr b/src/test/ui/wf/wf-inherent-impl-where-clause.stderr
new file mode 100644
index 0000000..f10ff84
--- /dev/null
+++ b/src/test/ui/wf/wf-inherent-impl-where-clause.stderr
@@ -0,0 +1,18 @@
+error[E0277]: the trait bound `U: std::marker::Copy` is not satisfied
+  --> $DIR/wf-inherent-impl-where-clause.rs:11:1
+   |
+LL | / impl<T,U> Foo<T,U> where T: ExtraCopy<U>
+LL | | {
+LL | | }
+   | |_^ the trait `std::marker::Copy` is not implemented for `U`
+   |
+   = help: consider adding a `where U: std::marker::Copy` bound
+note: required by `ExtraCopy`
+  --> $DIR/wf-inherent-impl-where-clause.rs:7:1
+   |
+LL | trait ExtraCopy<T:Copy> { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/wf/wf-misc-methods-issue-28609.nll.stderr b/src/test/ui/wf/wf-misc-methods-issue-28609.nll.stderr
new file mode 100644
index 0000000..fc58984
--- /dev/null
+++ b/src/test/ui/wf/wf-misc-methods-issue-28609.nll.stderr
@@ -0,0 +1,55 @@
+error[E0515]: cannot return value referencing temporary value
+  --> $DIR/wf-misc-methods-issue-28609.rs:22:5
+   |
+LL |     s.transmute_inherent(&mut 42)
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^--^
+   |     |                         |
+   |     |                         temporary value created here
+   |     returns a value referencing data owned by the current function
+
+error[E0515]: cannot return value referencing local variable `four`
+  --> $DIR/wf-misc-methods-issue-28609.rs:36:5
+   |
+LL |     s.bomb = Some(&four);
+   |                   ----- `four` is borrowed here
+LL |     &s
+   |     ^^ returns a value referencing data owned by the current function
+
+error[E0515]: cannot return value referencing local variable `four`
+  --> $DIR/wf-misc-methods-issue-28609.rs:43:5
+   |
+LL |     s.bomb = Some(&four);
+   |                   ----- `four` is borrowed here
+LL |     &*s
+   |     ^^^ returns a value referencing data owned by the current function
+
+error[E0515]: cannot return value referencing temporary value
+  --> $DIR/wf-misc-methods-issue-28609.rs:53:5
+   |
+LL |     s << &mut 3
+   |     ^^^^^^^^^^-
+   |     |         |
+   |     |         temporary value created here
+   |     returns a value referencing data owned by the current function
+
+error[E0515]: cannot return value referencing temporary value
+  --> $DIR/wf-misc-methods-issue-28609.rs:58:5
+   |
+LL |     s.shl(&mut 3)
+   |     ^^^^^^^^^^^-^
+   |     |          |
+   |     |          temporary value created here
+   |     returns a value referencing data owned by the current function
+
+error[E0515]: cannot return value referencing temporary value
+  --> $DIR/wf-misc-methods-issue-28609.rs:63:5
+   |
+LL |     S2::shl(s, &mut 3)
+   |     ^^^^^^^^^^^^^^^^-^
+   |     |               |
+   |     |               temporary value created here
+   |     returns a value referencing data owned by the current function
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/src/test/ui/wf/wf-misc-methods-issue-28609.rs b/src/test/ui/wf/wf-misc-methods-issue-28609.rs
new file mode 100644
index 0000000..505d7d7
--- /dev/null
+++ b/src/test/ui/wf/wf-misc-methods-issue-28609.rs
@@ -0,0 +1,74 @@
+// check that misc. method calls are well-formed
+
+use std::marker::PhantomData;
+use std::ops::{Deref, Shl};
+
+#[derive(Copy, Clone)]
+struct S<'a, 'b: 'a> {
+    marker: PhantomData<&'a &'b ()>,
+    bomb: Option<&'b u32>
+}
+
+type S2<'a> = S<'a, 'a>;
+
+impl<'a, 'b> S<'a, 'b> {
+    fn transmute_inherent(&self, a: &'b u32) -> &'a u32 {
+        a
+    }
+}
+
+fn return_dangling_pointer_inherent(s: S2) -> &u32 {
+    let s = s;
+    s.transmute_inherent(&mut 42) //~ ERROR does not live long enough
+}
+
+impl<'a, 'b> Deref for S<'a, 'b> {
+    type Target = &'a u32;
+    fn deref(&self) -> &&'a u32 {
+        self.bomb.as_ref().unwrap()
+    }
+}
+
+fn return_dangling_pointer_coerce(s: S2) -> &u32 {
+    let four = 4;
+    let mut s = s;
+    s.bomb = Some(&four); //~ ERROR does not live long enough
+    &s
+}
+
+fn return_dangling_pointer_unary_op(s: S2) -> &u32 {
+    let four = 4;
+    let mut s = s;
+    s.bomb = Some(&four); //~ ERROR does not live long enough
+    &*s
+}
+
+impl<'a, 'b> Shl<&'b u32> for S<'a, 'b> {
+    type Output = &'a u32;
+    fn shl(self, t: &'b u32) -> &'a u32 { t }
+}
+
+fn return_dangling_pointer_binary_op(s: S2) -> &u32 {
+    let s = s;
+    s << &mut 3 //~ ERROR does not live long enough
+}
+
+fn return_dangling_pointer_method(s: S2) -> &u32 {
+    let s = s;
+    s.shl(&mut 3) //~ ERROR does not live long enough
+}
+
+fn return_dangling_pointer_ufcs(s: S2) -> &u32 {
+    let s = s;
+    S2::shl(s, &mut 3) //~ ERROR does not live long enough
+}
+
+fn main() {
+    let s = S { marker: PhantomData, bomb: None };
+    let _inherent_dp = return_dangling_pointer_inherent(s);
+    let _coerce_dp = return_dangling_pointer_coerce(s);
+    let _unary_dp = return_dangling_pointer_unary_op(s);
+    let _binary_dp = return_dangling_pointer_binary_op(s);
+    let _method_dp = return_dangling_pointer_method(s);
+    let _ufcs_dp = return_dangling_pointer_ufcs(s);
+}
diff --git a/src/test/ui/wf/wf-misc-methods-issue-28609.stderr b/src/test/ui/wf/wf-misc-methods-issue-28609.stderr
new file mode 100644
index 0000000..d470aec
--- /dev/null
+++ b/src/test/ui/wf/wf-misc-methods-issue-28609.stderr
@@ -0,0 +1,111 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/wf-misc-methods-issue-28609.rs:22:31
+   |
+LL |     s.transmute_inherent(&mut 42)
+   |                               ^^ temporary value does not live long enough
+LL | }
+   | - temporary value only lives until here
+   |
+note: borrowed value must be valid for the anonymous lifetime #1 defined on the function body at 20:1...
+  --> $DIR/wf-misc-methods-issue-28609.rs:20:1
+   |
+LL | / fn return_dangling_pointer_inherent(s: S2) -> &u32 {
+LL | |     let s = s;
+LL | |     s.transmute_inherent(&mut 42)
+LL | | }
+   | |_^
+
+error[E0597]: `four` does not live long enough
+  --> $DIR/wf-misc-methods-issue-28609.rs:35:20
+   |
+LL |     s.bomb = Some(&four);
+   |                    ^^^^ borrowed value does not live long enough
+LL |     &s
+LL | }
+   | - borrowed value only lives until here
+   |
+note: borrowed value must be valid for the anonymous lifetime #1 defined on the function body at 32:1...
+  --> $DIR/wf-misc-methods-issue-28609.rs:32:1
+   |
+LL | / fn return_dangling_pointer_coerce(s: S2) -> &u32 {
+LL | |     let four = 4;
+LL | |     let mut s = s;
+LL | |     s.bomb = Some(&four);
+LL | |     &s
+LL | | }
+   | |_^
+
+error[E0597]: `four` does not live long enough
+  --> $DIR/wf-misc-methods-issue-28609.rs:42:20
+   |
+LL |     s.bomb = Some(&four);
+   |                    ^^^^ borrowed value does not live long enough
+LL |     &*s
+LL | }
+   | - borrowed value only lives until here
+   |
+note: borrowed value must be valid for the anonymous lifetime #1 defined on the function body at 39:1...
+  --> $DIR/wf-misc-methods-issue-28609.rs:39:1
+   |
+LL | / fn return_dangling_pointer_unary_op(s: S2) -> &u32 {
+LL | |     let four = 4;
+LL | |     let mut s = s;
+LL | |     s.bomb = Some(&four);
+LL | |     &*s
+LL | | }
+   | |_^
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/wf-misc-methods-issue-28609.rs:53:15
+   |
+LL |     s << &mut 3
+   |               ^ temporary value does not live long enough
+LL | }
+   | - temporary value only lives until here
+   |
+note: borrowed value must be valid for the anonymous lifetime #1 defined on the function body at 51:1...
+  --> $DIR/wf-misc-methods-issue-28609.rs:51:1
+   |
+LL | / fn return_dangling_pointer_binary_op(s: S2) -> &u32 {
+LL | |     let s = s;
+LL | |     s << &mut 3
+LL | | }
+   | |_^
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/wf-misc-methods-issue-28609.rs:58:16
+   |
+LL |     s.shl(&mut 3)
+   |                ^ temporary value does not live long enough
+LL | }
+   | - temporary value only lives until here
+   |
+note: borrowed value must be valid for the anonymous lifetime #1 defined on the function body at 56:1...
+  --> $DIR/wf-misc-methods-issue-28609.rs:56:1
+   |
+LL | / fn return_dangling_pointer_method(s: S2) -> &u32 {
+LL | |     let s = s;
+LL | |     s.shl(&mut 3)
+LL | | }
+   | |_^
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/wf-misc-methods-issue-28609.rs:63:21
+   |
+LL |     S2::shl(s, &mut 3)
+   |                     ^ temporary value does not live long enough
+LL | }
+   | - temporary value only lives until here
+   |
+note: borrowed value must be valid for the anonymous lifetime #1 defined on the function body at 61:1...
+  --> $DIR/wf-misc-methods-issue-28609.rs:61:1
+   |
+LL | / fn return_dangling_pointer_ufcs(s: S2) -> &u32 {
+LL | |     let s = s;
+LL | |     S2::shl(s, &mut 3)
+LL | | }
+   | |_^
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/wf/wf-object-safe.rs b/src/test/ui/wf/wf-object-safe.rs
new file mode 100644
index 0000000..08f68f6
--- /dev/null
+++ b/src/test/ui/wf/wf-object-safe.rs
@@ -0,0 +1,10 @@
+// Check that object-safe traits are not WF when used as object types.
+// Issue #21953.
+
+trait A {
+    fn foo(&self, _x: &Self);
+}
+
+fn main() {
+    let _x: &A; //~ ERROR E0038
+}
diff --git a/src/test/ui/wf/wf-object-safe.stderr b/src/test/ui/wf/wf-object-safe.stderr
new file mode 100644
index 0000000..87e8105
--- /dev/null
+++ b/src/test/ui/wf/wf-object-safe.stderr
@@ -0,0 +1,11 @@
+error[E0038]: the trait `A` cannot be made into an object
+  --> $DIR/wf-object-safe.rs:9:13
+   |
+LL |     let _x: &A;
+   |             ^^ the trait `A` cannot be made into an object
+   |
+   = note: method `foo` references the `Self` type in its arguments or return type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/wf/wf-outlives-ty-in-fn-or-trait.rs b/src/test/ui/wf/wf-outlives-ty-in-fn-or-trait.rs
new file mode 100644
index 0000000..1c4cda2
--- /dev/null
+++ b/src/test/ui/wf/wf-outlives-ty-in-fn-or-trait.rs
@@ -0,0 +1,23 @@
+#![feature(rustc_attrs)]
+#![allow(dead_code)]
+
+trait Trait<'a, T> {
+    type Out;
+}
+
+impl<'a, T> Trait<'a, T> for usize {
+    type Out = &'a fn(T); //~ ERROR `T` may not live long enough
+}
+
+struct Foo<'a,T> {
+    f: &'a fn(T),
+}
+
+trait Baz<T> { }
+
+impl<'a, T> Trait<'a, T> for u32 {
+    type Out = &'a Baz<T>; //~ ERROR `T` may not live long enough
+}
+
+fn main() { }
+
diff --git a/src/test/ui/wf/wf-outlives-ty-in-fn-or-trait.stderr b/src/test/ui/wf/wf-outlives-ty-in-fn-or-trait.stderr
new file mode 100644
index 0000000..8649506
--- /dev/null
+++ b/src/test/ui/wf/wf-outlives-ty-in-fn-or-trait.stderr
@@ -0,0 +1,31 @@
+error[E0309]: the parameter type `T` may not live long enough
+  --> $DIR/wf-outlives-ty-in-fn-or-trait.rs:9:5
+   |
+LL | impl<'a, T> Trait<'a, T> for usize {
+   |          - help: consider adding an explicit lifetime bound `T: 'a`...
+LL |     type Out = &'a fn(T);
+   |     ^^^^^^^^^^^^^^^^^^^^^
+   |
+note: ...so that the reference type `&'a fn(T)` does not outlive the data it points at
+  --> $DIR/wf-outlives-ty-in-fn-or-trait.rs:9:5
+   |
+LL |     type Out = &'a fn(T);
+   |     ^^^^^^^^^^^^^^^^^^^^^
+
+error[E0309]: the parameter type `T` may not live long enough
+  --> $DIR/wf-outlives-ty-in-fn-or-trait.rs:19:5
+   |
+LL | impl<'a, T> Trait<'a, T> for u32 {
+   |          - help: consider adding an explicit lifetime bound `T: 'a`...
+LL |     type Out = &'a Baz<T>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: ...so that the reference type `&'a (dyn Baz<T> + 'a)` does not outlive the data it points at
+  --> $DIR/wf-outlives-ty-in-fn-or-trait.rs:19:5
+   |
+LL |     type Out = &'a Baz<T>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0309`.
diff --git a/src/test/ui/wf/wf-packed-on-proj-of-type-as-unimpl-trait.rs b/src/test/ui/wf/wf-packed-on-proj-of-type-as-unimpl-trait.rs
new file mode 100644
index 0000000..d0167c8
--- /dev/null
+++ b/src/test/ui/wf/wf-packed-on-proj-of-type-as-unimpl-trait.rs
@@ -0,0 +1,31 @@
+// rust-lang/rust#58158: We have special-case code to deal with case
+// when a type is both packed and needs drop glue, (we move the fields
+// out of their potentially unaligned locations before dropping them,
+// which requires they be Sized; see PR #44884).
+//
+// So, we need to check if a given type needs drop-glue. That requires
+// that we actually know that the concrete type, and we guard against
+// the type having unknown parts (i.e. type variables) by ICE'ing in
+// that scenario.
+//
+// But in a case where we have a projection (`Type as Trait::Assoc`)
+// where `Type` does not actually implement `Trait`, we of course
+// cannot have a concrete type, because there is no impl to look up
+// the concrete type for the associated type `Assoc`.
+//
+// So, this test is just making sure that in such a case that we do
+// not immediately ICE, and instead allow the underlying type error to
+// surface.
+
+pub struct Matrix<S>(S);
+pub struct DefaultAllocator;
+
+pub trait Allocator { type Buffer; }
+
+// impl Allocator for DefaultAllocator { type Buffer = (); }
+
+#[repr(packed)]
+struct Foo(Matrix<<DefaultAllocator as Allocator>::Buffer>);
+//~^ ERROR the trait bound `DefaultAllocator: Allocator` is not satisfied
+
+fn main() { }
diff --git a/src/test/ui/wf/wf-packed-on-proj-of-type-as-unimpl-trait.stderr b/src/test/ui/wf/wf-packed-on-proj-of-type-as-unimpl-trait.stderr
new file mode 100644
index 0000000..e460cdc
--- /dev/null
+++ b/src/test/ui/wf/wf-packed-on-proj-of-type-as-unimpl-trait.stderr
@@ -0,0 +1,9 @@
+error[E0277]: the trait bound `DefaultAllocator: Allocator` is not satisfied
+  --> $DIR/wf-packed-on-proj-of-type-as-unimpl-trait.rs:28:12
+   |
+LL | struct Foo(Matrix<<DefaultAllocator as Allocator>::Buffer>);
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Allocator` is not implemented for `DefaultAllocator`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/wf/wf-static-method.rs b/src/test/ui/wf/wf-static-method.rs
new file mode 100644
index 0000000..e5a1092
--- /dev/null
+++ b/src/test/ui/wf/wf-static-method.rs
@@ -0,0 +1,54 @@
+// check that static methods don't get to assume their trait-ref
+// is well-formed.
+// FIXME(#27579): this is just a bug. However, our checking with
+// static inherent methods isn't quite working - need to
+// fix that before removing the check.
+
+trait Foo<'a, 'b, T>: Sized {
+    fn make_me() -> Self { loop {} }
+    fn static_evil(u: &'b u32) -> &'a u32;
+}
+
+struct Evil<'a, 'b: 'a>(Option<&'a &'b ()>);
+
+impl<'a, 'b> Foo<'a, 'b, Evil<'a, 'b>> for () {
+    fn make_me() -> Self { }
+    fn static_evil(u: &'b u32) -> &'a u32 {
+        u //~ ERROR E0312
+    }
+}
+
+struct IndirectEvil<'a, 'b: 'a>(Option<&'a &'b ()>);
+
+impl<'a, 'b> Foo<'a, 'b, ()> for IndirectEvil<'a, 'b> {
+    fn make_me() -> Self { IndirectEvil(None) }
+    fn static_evil(u: &'b u32) -> &'a u32 {
+        let me = Self::make_me(); //~ ERROR lifetime bound not satisfied
+        loop {} // (`me` could be used for the lifetime transmute).
+    }
+}
+
+impl<'a, 'b> Evil<'a, 'b> {
+    fn inherent_evil(u: &'b u32) -> &'a u32 {
+        u //~ ERROR E0312
+    }
+}
+
+// while static methods don't get to *assume* this, we still
+// *check* that they hold.
+
+fn evil<'a, 'b>(b: &'b u32) -> &'a u32 {
+    <()>::static_evil(b) //~ ERROR cannot infer an appropriate lifetime
+}
+
+fn indirect_evil<'a, 'b>(b: &'b u32) -> &'a u32 {
+    <IndirectEvil>::static_evil(b)
+    //~^ ERROR cannot infer an appropriate lifetime
+}
+
+fn inherent_evil<'a, 'b>(b: &'b u32) -> &'a u32 {
+    <Evil>::inherent_evil(b) // bug? shouldn't this be an error
+}
+
+
+fn main() {}
diff --git a/src/test/ui/wf/wf-static-method.stderr b/src/test/ui/wf/wf-static-method.stderr
new file mode 100644
index 0000000..32832ce
--- /dev/null
+++ b/src/test/ui/wf/wf-static-method.stderr
@@ -0,0 +1,109 @@
+error[E0312]: lifetime of reference outlives lifetime of borrowed content...
+  --> $DIR/wf-static-method.rs:17:9
+   |
+LL |         u
+   |         ^
+   |
+note: ...the reference is valid for the lifetime 'a as defined on the impl at 14:6...
+  --> $DIR/wf-static-method.rs:14:6
+   |
+LL | impl<'a, 'b> Foo<'a, 'b, Evil<'a, 'b>> for () {
+   |      ^^
+note: ...but the borrowed content is only valid for the lifetime 'b as defined on the impl at 14:10
+  --> $DIR/wf-static-method.rs:14:10
+   |
+LL | impl<'a, 'b> Foo<'a, 'b, Evil<'a, 'b>> for () {
+   |          ^^
+
+error[E0478]: lifetime bound not satisfied
+  --> $DIR/wf-static-method.rs:26:18
+   |
+LL |         let me = Self::make_me();
+   |                  ^^^^^^^^^^^^^
+   |
+note: lifetime parameter instantiated with the lifetime 'b as defined on the impl at 23:10
+  --> $DIR/wf-static-method.rs:23:10
+   |
+LL | impl<'a, 'b> Foo<'a, 'b, ()> for IndirectEvil<'a, 'b> {
+   |          ^^
+note: but lifetime parameter must outlive the lifetime 'a as defined on the impl at 23:6
+  --> $DIR/wf-static-method.rs:23:6
+   |
+LL | impl<'a, 'b> Foo<'a, 'b, ()> for IndirectEvil<'a, 'b> {
+   |      ^^
+
+error[E0312]: lifetime of reference outlives lifetime of borrowed content...
+  --> $DIR/wf-static-method.rs:33:9
+   |
+LL |         u
+   |         ^
+   |
+note: ...the reference is valid for the lifetime 'a as defined on the impl at 31:6...
+  --> $DIR/wf-static-method.rs:31:6
+   |
+LL | impl<'a, 'b> Evil<'a, 'b> {
+   |      ^^
+note: ...but the borrowed content is only valid for the lifetime 'b as defined on the impl at 31:10
+  --> $DIR/wf-static-method.rs:31:10
+   |
+LL | impl<'a, 'b> Evil<'a, 'b> {
+   |          ^^
+
+error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'b` due to conflicting requirements
+  --> $DIR/wf-static-method.rs:41:5
+   |
+LL |     <()>::static_evil(b)
+   |     ^^^^^^^^^^^^^^^^^
+   |
+note: first, the lifetime cannot outlive the lifetime 'b as defined on the function body at 40:13...
+  --> $DIR/wf-static-method.rs:40:13
+   |
+LL | fn evil<'a, 'b>(b: &'b u32) -> &'a u32 {
+   |             ^^
+note: ...so that reference does not outlive borrowed content
+  --> $DIR/wf-static-method.rs:41:23
+   |
+LL |     <()>::static_evil(b)
+   |                       ^
+note: but, the lifetime must be valid for the lifetime 'a as defined on the function body at 40:9...
+  --> $DIR/wf-static-method.rs:40:9
+   |
+LL | fn evil<'a, 'b>(b: &'b u32) -> &'a u32 {
+   |         ^^
+note: ...so that reference does not outlive borrowed content
+  --> $DIR/wf-static-method.rs:41:5
+   |
+LL |     <()>::static_evil(b)
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'b` due to conflicting requirements
+  --> $DIR/wf-static-method.rs:45:5
+   |
+LL |     <IndirectEvil>::static_evil(b)
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: first, the lifetime cannot outlive the lifetime 'b as defined on the function body at 44:22...
+  --> $DIR/wf-static-method.rs:44:22
+   |
+LL | fn indirect_evil<'a, 'b>(b: &'b u32) -> &'a u32 {
+   |                      ^^
+note: ...so that reference does not outlive borrowed content
+  --> $DIR/wf-static-method.rs:45:33
+   |
+LL |     <IndirectEvil>::static_evil(b)
+   |                                 ^
+note: but, the lifetime must be valid for the lifetime 'a as defined on the function body at 44:18...
+  --> $DIR/wf-static-method.rs:44:18
+   |
+LL | fn indirect_evil<'a, 'b>(b: &'b u32) -> &'a u32 {
+   |                  ^^
+note: ...so that reference does not outlive borrowed content
+  --> $DIR/wf-static-method.rs:45:5
+   |
+LL |     <IndirectEvil>::static_evil(b)
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
+
+Some errors occurred: E0312, E0478, E0495.
+For more information about an error, try `rustc --explain E0312`.
diff --git a/src/test/ui/wf/wf-static-type.rs b/src/test/ui/wf/wf-static-type.rs
new file mode 100644
index 0000000..1c35e1d
--- /dev/null
+++ b/src/test/ui/wf/wf-static-type.rs
@@ -0,0 +1,14 @@
+// Test that we check the types of statics are well-formed.
+
+#![feature(associated_type_defaults)]
+
+#![allow(dead_code)]
+
+struct IsCopy<T:Copy> { t: T }
+struct NotCopy;
+
+static FOO: IsCopy<Option<NotCopy>> = IsCopy { t: None };
+//~^ ERROR E0277
+
+
+fn main() { }
diff --git a/src/test/ui/wf/wf-static-type.stderr b/src/test/ui/wf/wf-static-type.stderr
new file mode 100644
index 0000000..4234c71
--- /dev/null
+++ b/src/test/ui/wf/wf-static-type.stderr
@@ -0,0 +1,16 @@
+error[E0277]: the trait bound `NotCopy: std::marker::Copy` is not satisfied
+  --> $DIR/wf-static-type.rs:10:13
+   |
+LL | static FOO: IsCopy<Option<NotCopy>> = IsCopy { t: None };
+   |             ^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `NotCopy`
+   |
+   = note: required because of the requirements on the impl of `std::marker::Copy` for `std::option::Option<NotCopy>`
+note: required by `IsCopy`
+  --> $DIR/wf-static-type.rs:7:1
+   |
+LL | struct IsCopy<T:Copy> { t: T }
+   | ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/wf/wf-struct-bound.rs b/src/test/ui/wf/wf-struct-bound.rs
new file mode 100644
index 0000000..69be71c
--- /dev/null
+++ b/src/test/ui/wf/wf-struct-bound.rs
@@ -0,0 +1,16 @@
+// Test that we check struct bounds for WFedness.
+
+#![feature(associated_type_defaults)]
+
+#![allow(dead_code)]
+
+trait ExtraCopy<T:Copy> { }
+
+struct SomeStruct<T,U> //~ ERROR E0277
+    where T: ExtraCopy<U>
+{
+    data: (T,U)
+}
+
+
+fn main() { }
diff --git a/src/test/ui/wf/wf-struct-bound.stderr b/src/test/ui/wf/wf-struct-bound.stderr
new file mode 100644
index 0000000..1fdcced
--- /dev/null
+++ b/src/test/ui/wf/wf-struct-bound.stderr
@@ -0,0 +1,20 @@
+error[E0277]: the trait bound `U: std::marker::Copy` is not satisfied
+  --> $DIR/wf-struct-bound.rs:9:1
+   |
+LL | / struct SomeStruct<T,U>
+LL | |     where T: ExtraCopy<U>
+LL | | {
+LL | |     data: (T,U)
+LL | | }
+   | |_^ the trait `std::marker::Copy` is not implemented for `U`
+   |
+   = help: consider adding a `where U: std::marker::Copy` bound
+note: required by `ExtraCopy`
+  --> $DIR/wf-struct-bound.rs:7:1
+   |
+LL | trait ExtraCopy<T:Copy> { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/wf/wf-struct-field.rs b/src/test/ui/wf/wf-struct-field.rs
new file mode 100644
index 0000000..63f8b43
--- /dev/null
+++ b/src/test/ui/wf/wf-struct-field.rs
@@ -0,0 +1,16 @@
+// Test that we check struct fields for WFedness.
+
+#![feature(associated_type_defaults)]
+
+#![allow(dead_code)]
+
+struct IsCopy<T:Copy> {
+    value: T
+}
+
+struct SomeStruct<A> {
+    data: IsCopy<A> //~ ERROR E0277
+}
+
+
+fn main() { }
diff --git a/src/test/ui/wf/wf-struct-field.stderr b/src/test/ui/wf/wf-struct-field.stderr
new file mode 100644
index 0000000..e609f93
--- /dev/null
+++ b/src/test/ui/wf/wf-struct-field.stderr
@@ -0,0 +1,16 @@
+error[E0277]: the trait bound `A: std::marker::Copy` is not satisfied
+  --> $DIR/wf-struct-field.rs:12:5
+   |
+LL |     data: IsCopy<A>
+   |     ^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `A`
+   |
+   = help: consider adding a `where A: std::marker::Copy` bound
+note: required by `IsCopy`
+  --> $DIR/wf-struct-field.rs:7:1
+   |
+LL | struct IsCopy<T:Copy> {
+   | ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/wf/wf-trait-associated-type-bound.rs b/src/test/ui/wf/wf-trait-associated-type-bound.rs
new file mode 100644
index 0000000..29e30557
--- /dev/null
+++ b/src/test/ui/wf/wf-trait-associated-type-bound.rs
@@ -0,0 +1,14 @@
+// Test that we check associated type bounds for WFedness.
+
+#![feature(associated_type_defaults)]
+
+#![allow(dead_code)]
+
+trait ExtraCopy<T:Copy> { }
+
+trait SomeTrait<T> { //~ ERROR E0277
+    type Type1: ExtraCopy<T>;
+}
+
+
+fn main() { }
diff --git a/src/test/ui/wf/wf-trait-associated-type-bound.stderr b/src/test/ui/wf/wf-trait-associated-type-bound.stderr
new file mode 100644
index 0000000..658d412
--- /dev/null
+++ b/src/test/ui/wf/wf-trait-associated-type-bound.stderr
@@ -0,0 +1,18 @@
+error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
+  --> $DIR/wf-trait-associated-type-bound.rs:9:1
+   |
+LL | / trait SomeTrait<T> {
+LL | |     type Type1: ExtraCopy<T>;
+LL | | }
+   | |_^ the trait `std::marker::Copy` is not implemented for `T`
+   |
+   = help: consider adding a `where T: std::marker::Copy` bound
+note: required by `ExtraCopy`
+  --> $DIR/wf-trait-associated-type-bound.rs:7:1
+   |
+LL | trait ExtraCopy<T:Copy> { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/wf/wf-trait-associated-type-region.rs b/src/test/ui/wf/wf-trait-associated-type-region.rs
new file mode 100644
index 0000000..0dfc9f0
--- /dev/null
+++ b/src/test/ui/wf/wf-trait-associated-type-region.rs
@@ -0,0 +1,14 @@
+// Test that we check associated type default values for WFedness.
+
+#![feature(associated_type_defaults)]
+
+#![allow(dead_code)]
+
+trait SomeTrait<'a> {
+    type Type1;
+    type Type2 = &'a Self::Type1;
+    //~^ ERROR E0309
+}
+
+
+fn main() { }
diff --git a/src/test/ui/wf/wf-trait-associated-type-region.stderr b/src/test/ui/wf/wf-trait-associated-type-region.stderr
new file mode 100644
index 0000000..9bbfad9
--- /dev/null
+++ b/src/test/ui/wf/wf-trait-associated-type-region.stderr
@@ -0,0 +1,16 @@
+error[E0309]: the associated type `<Self as SomeTrait<'a>>::Type1` may not live long enough
+  --> $DIR/wf-trait-associated-type-region.rs:9:5
+   |
+LL |     type Type2 = &'a Self::Type1;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding an explicit lifetime bound `<Self as SomeTrait<'a>>::Type1: 'a`...
+note: ...so that the reference type `&'a <Self as SomeTrait<'a>>::Type1` does not outlive the data it points at
+  --> $DIR/wf-trait-associated-type-region.rs:9:5
+   |
+LL |     type Type2 = &'a Self::Type1;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0309`.
diff --git a/src/test/ui/wf/wf-trait-associated-type-trait.rs b/src/test/ui/wf/wf-trait-associated-type-trait.rs
new file mode 100644
index 0000000..ddc0b32
--- /dev/null
+++ b/src/test/ui/wf/wf-trait-associated-type-trait.rs
@@ -0,0 +1,16 @@
+// Test that we check associated type default values for WFedness.
+
+#![feature(associated_type_defaults)]
+
+#![allow(dead_code)]
+
+struct IsCopy<T:Copy> { x: T }
+
+trait SomeTrait {
+    type Type1;
+    type Type2 = IsCopy<Self::Type1>;
+    //~^ ERROR E0277
+}
+
+
+fn main() { }
diff --git a/src/test/ui/wf/wf-trait-associated-type-trait.stderr b/src/test/ui/wf/wf-trait-associated-type-trait.stderr
new file mode 100644
index 0000000..70fabcd
--- /dev/null
+++ b/src/test/ui/wf/wf-trait-associated-type-trait.stderr
@@ -0,0 +1,16 @@
+error[E0277]: the trait bound `<Self as SomeTrait>::Type1: std::marker::Copy` is not satisfied
+  --> $DIR/wf-trait-associated-type-trait.rs:11:5
+   |
+LL |     type Type2 = IsCopy<Self::Type1>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `<Self as SomeTrait>::Type1`
+   |
+   = help: consider adding a `where <Self as SomeTrait>::Type1: std::marker::Copy` bound
+note: required by `IsCopy`
+  --> $DIR/wf-trait-associated-type-trait.rs:7:1
+   |
+LL | struct IsCopy<T:Copy> { x: T }
+   | ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/wf/wf-trait-bound.rs b/src/test/ui/wf/wf-trait-bound.rs
new file mode 100644
index 0000000..d8746ba
--- /dev/null
+++ b/src/test/ui/wf/wf-trait-bound.rs
@@ -0,0 +1,15 @@
+// Test that we check supertrait bounds for WFedness.
+
+#![feature(associated_type_defaults)]
+
+#![allow(dead_code)]
+
+trait ExtraCopy<T:Copy> { }
+
+trait SomeTrait<T,U> //~ ERROR E0277
+    where T: ExtraCopy<U>
+{
+}
+
+
+fn main() { }
diff --git a/src/test/ui/wf/wf-trait-bound.stderr b/src/test/ui/wf/wf-trait-bound.stderr
new file mode 100644
index 0000000..5cc9451
--- /dev/null
+++ b/src/test/ui/wf/wf-trait-bound.stderr
@@ -0,0 +1,19 @@
+error[E0277]: the trait bound `U: std::marker::Copy` is not satisfied
+  --> $DIR/wf-trait-bound.rs:9:1
+   |
+LL | / trait SomeTrait<T,U>
+LL | |     where T: ExtraCopy<U>
+LL | | {
+LL | | }
+   | |_^ the trait `std::marker::Copy` is not implemented for `U`
+   |
+   = help: consider adding a `where U: std::marker::Copy` bound
+note: required by `ExtraCopy`
+  --> $DIR/wf-trait-bound.rs:7:1
+   |
+LL | trait ExtraCopy<T:Copy> { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/wf/wf-trait-default-fn-arg.rs b/src/test/ui/wf/wf-trait-default-fn-arg.rs
new file mode 100644
index 0000000..64fc35a
--- /dev/null
+++ b/src/test/ui/wf/wf-trait-default-fn-arg.rs
@@ -0,0 +1,19 @@
+// Check that we test WF conditions for fn arguments. Because the
+// current code is so goofy, this is only a warning for now.
+
+
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+struct Bar<T:Eq+?Sized> { value: Box<T> }
+
+trait Foo {
+    fn bar(&self, x: &Bar<Self>) {
+        //~^ ERROR E0277
+        //
+        // Here, Eq ought to be implemented.
+    }
+}
+
+
+fn main() { }
diff --git a/src/test/ui/wf/wf-trait-default-fn-arg.stderr b/src/test/ui/wf/wf-trait-default-fn-arg.stderr
new file mode 100644
index 0000000..e713389
--- /dev/null
+++ b/src/test/ui/wf/wf-trait-default-fn-arg.stderr
@@ -0,0 +1,20 @@
+error[E0277]: the trait bound `Self: std::cmp::Eq` is not satisfied
+  --> $DIR/wf-trait-default-fn-arg.rs:11:5
+   |
+LL | /     fn bar(&self, x: &Bar<Self>) {
+LL | |
+LL | |         //
+LL | |         // Here, Eq ought to be implemented.
+LL | |     }
+   | |_____^ the trait `std::cmp::Eq` is not implemented for `Self`
+   |
+   = help: consider adding a `where Self: std::cmp::Eq` bound
+note: required by `Bar`
+  --> $DIR/wf-trait-default-fn-arg.rs:8:1
+   |
+LL | struct Bar<T:Eq+?Sized> { value: Box<T> }
+   | ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/wf/wf-trait-default-fn-ret.rs b/src/test/ui/wf/wf-trait-default-fn-ret.rs
new file mode 100644
index 0000000..2103dae
--- /dev/null
+++ b/src/test/ui/wf/wf-trait-default-fn-ret.rs
@@ -0,0 +1,19 @@
+// Check that we test WF conditions for fn arguments. Because the
+// current code is so goofy, this is only a warning for now.
+
+#![feature(rustc_attrs)]
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+struct Bar<T:Eq+?Sized> { value: Box<T> }
+
+trait Foo {
+    fn bar(&self) -> Bar<Self> {
+        //~^ ERROR E0277
+        //
+        // Here, Eq ought to be implemented.
+        loop { }
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/wf/wf-trait-default-fn-ret.stderr b/src/test/ui/wf/wf-trait-default-fn-ret.stderr
new file mode 100644
index 0000000..5a310a8
--- /dev/null
+++ b/src/test/ui/wf/wf-trait-default-fn-ret.stderr
@@ -0,0 +1,21 @@
+error[E0277]: the trait bound `Self: std::cmp::Eq` is not satisfied
+  --> $DIR/wf-trait-default-fn-ret.rs:11:5
+   |
+LL | /     fn bar(&self) -> Bar<Self> {
+LL | |
+LL | |         //
+LL | |         // Here, Eq ought to be implemented.
+LL | |         loop { }
+LL | |     }
+   | |_____^ the trait `std::cmp::Eq` is not implemented for `Self`
+   |
+   = help: consider adding a `where Self: std::cmp::Eq` bound
+note: required by `Bar`
+  --> $DIR/wf-trait-default-fn-ret.rs:8:1
+   |
+LL | struct Bar<T:Eq+?Sized> { value: Box<T> }
+   | ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/wf/wf-trait-default-fn-where-clause.rs b/src/test/ui/wf/wf-trait-default-fn-where-clause.rs
new file mode 100644
index 0000000..ded9721
--- /dev/null
+++ b/src/test/ui/wf/wf-trait-default-fn-where-clause.rs
@@ -0,0 +1,19 @@
+// Check that we test WF conditions for fn arguments. Because the
+// current code is so goofy, this is only a warning for now.
+
+
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+trait Bar<T:Eq+?Sized> { }
+
+trait Foo {
+    fn bar<A>(&self) where A: Bar<Self> {
+        //~^ ERROR E0277
+        //
+        // Here, Eq ought to be implemented.
+    }
+}
+
+
+fn main() { }
diff --git a/src/test/ui/wf/wf-trait-default-fn-where-clause.stderr b/src/test/ui/wf/wf-trait-default-fn-where-clause.stderr
new file mode 100644
index 0000000..d5a00be
--- /dev/null
+++ b/src/test/ui/wf/wf-trait-default-fn-where-clause.stderr
@@ -0,0 +1,20 @@
+error[E0277]: the trait bound `Self: std::cmp::Eq` is not satisfied
+  --> $DIR/wf-trait-default-fn-where-clause.rs:11:5
+   |
+LL | /     fn bar<A>(&self) where A: Bar<Self> {
+LL | |
+LL | |         //
+LL | |         // Here, Eq ought to be implemented.
+LL | |     }
+   | |_____^ the trait `std::cmp::Eq` is not implemented for `Self`
+   |
+   = help: consider adding a `where Self: std::cmp::Eq` bound
+note: required by `Bar`
+  --> $DIR/wf-trait-default-fn-where-clause.rs:8:1
+   |
+LL | trait Bar<T:Eq+?Sized> { }
+   | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/wf/wf-trait-fn-arg.rs b/src/test/ui/wf/wf-trait-fn-arg.rs
new file mode 100644
index 0000000..0445699
--- /dev/null
+++ b/src/test/ui/wf/wf-trait-fn-arg.rs
@@ -0,0 +1,16 @@
+// Check that we test WF conditions for fn arguments in a trait definition.
+
+#![feature(rustc_attrs)]
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+struct Bar<T:Eq+?Sized> { value: Box<T> }
+
+trait Foo {
+    fn bar(&self, x: &Bar<Self>);
+        //~^ ERROR E0277
+        //
+        // Here, Eq ought to be implemented.
+}
+
+fn main() { }
diff --git a/src/test/ui/wf/wf-trait-fn-arg.stderr b/src/test/ui/wf/wf-trait-fn-arg.stderr
new file mode 100644
index 0000000..2b26eac
--- /dev/null
+++ b/src/test/ui/wf/wf-trait-fn-arg.stderr
@@ -0,0 +1,16 @@
+error[E0277]: the trait bound `Self: std::cmp::Eq` is not satisfied
+  --> $DIR/wf-trait-fn-arg.rs:10:5
+   |
+LL |     fn bar(&self, x: &Bar<Self>);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::cmp::Eq` is not implemented for `Self`
+   |
+   = help: consider adding a `where Self: std::cmp::Eq` bound
+note: required by `Bar`
+  --> $DIR/wf-trait-fn-arg.rs:7:1
+   |
+LL | struct Bar<T:Eq+?Sized> { value: Box<T> }
+   | ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/wf/wf-trait-fn-ret.rs b/src/test/ui/wf/wf-trait-fn-ret.rs
new file mode 100644
index 0000000..f49e430
--- /dev/null
+++ b/src/test/ui/wf/wf-trait-fn-ret.rs
@@ -0,0 +1,16 @@
+// Check that we test WF conditions for fn return types in a trait definition.
+
+#![feature(rustc_attrs)]
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+struct Bar<T:Eq+?Sized> { value: Box<T> }
+
+trait Foo {
+    fn bar(&self) -> &Bar<Self>;
+        //~^ ERROR E0277
+        //
+        // Here, Eq ought to be implemented.
+}
+
+fn main() { }
diff --git a/src/test/ui/wf/wf-trait-fn-ret.stderr b/src/test/ui/wf/wf-trait-fn-ret.stderr
new file mode 100644
index 0000000..70f07f0
--- /dev/null
+++ b/src/test/ui/wf/wf-trait-fn-ret.stderr
@@ -0,0 +1,16 @@
+error[E0277]: the trait bound `Self: std::cmp::Eq` is not satisfied
+  --> $DIR/wf-trait-fn-ret.rs:10:5
+   |
+LL |     fn bar(&self) -> &Bar<Self>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::cmp::Eq` is not implemented for `Self`
+   |
+   = help: consider adding a `where Self: std::cmp::Eq` bound
+note: required by `Bar`
+  --> $DIR/wf-trait-fn-ret.rs:7:1
+   |
+LL | struct Bar<T:Eq+?Sized> { value: Box<T> }
+   | ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/wf/wf-trait-fn-where-clause.rs b/src/test/ui/wf/wf-trait-fn-where-clause.rs
new file mode 100644
index 0000000..1d2427f
--- /dev/null
+++ b/src/test/ui/wf/wf-trait-fn-where-clause.rs
@@ -0,0 +1,17 @@
+// Check that we test WF conditions for fn where clauses in a trait definition.
+
+
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+struct Bar<T:Eq+?Sized> { value: Box<T> }
+
+trait Foo {
+    fn bar(&self) where Self: Sized, Bar<Self>: Copy;
+        //~^ ERROR E0277
+        //
+        // Here, Eq ought to be implemented.
+}
+
+
+fn main() { }
diff --git a/src/test/ui/wf/wf-trait-fn-where-clause.stderr b/src/test/ui/wf/wf-trait-fn-where-clause.stderr
new file mode 100644
index 0000000..2d6223e
--- /dev/null
+++ b/src/test/ui/wf/wf-trait-fn-where-clause.stderr
@@ -0,0 +1,16 @@
+error[E0277]: the trait bound `Self: std::cmp::Eq` is not satisfied
+  --> $DIR/wf-trait-fn-where-clause.rs:10:5
+   |
+LL |     fn bar(&self) where Self: Sized, Bar<Self>: Copy;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::cmp::Eq` is not implemented for `Self`
+   |
+   = help: consider adding a `where Self: std::cmp::Eq` bound
+note: required by `Bar`
+  --> $DIR/wf-trait-fn-where-clause.rs:7:1
+   |
+LL | struct Bar<T:Eq+?Sized> { value: Box<T> }
+   | ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/wf/wf-trait-superbound.rs b/src/test/ui/wf/wf-trait-superbound.rs
new file mode 100644
index 0000000..8905a88
--- /dev/null
+++ b/src/test/ui/wf/wf-trait-superbound.rs
@@ -0,0 +1,12 @@
+// Test that we check supertrait bounds for WFedness.
+
+#![feature(associated_type_defaults)]
+#![feature(rustc_attrs)]
+#![allow(dead_code)]
+
+trait ExtraCopy<T:Copy> { }
+
+trait SomeTrait<T>: ExtraCopy<T> { //~ ERROR E0277
+}
+
+fn main() { }
diff --git a/src/test/ui/wf/wf-trait-superbound.stderr b/src/test/ui/wf/wf-trait-superbound.stderr
new file mode 100644
index 0000000..a3c4ab5
--- /dev/null
+++ b/src/test/ui/wf/wf-trait-superbound.stderr
@@ -0,0 +1,17 @@
+error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
+  --> $DIR/wf-trait-superbound.rs:9:1
+   |
+LL | / trait SomeTrait<T>: ExtraCopy<T> {
+LL | | }
+   | |_^ the trait `std::marker::Copy` is not implemented for `T`
+   |
+   = help: consider adding a `where T: std::marker::Copy` bound
+note: required by `ExtraCopy`
+  --> $DIR/wf-trait-superbound.rs:7:1
+   |
+LL | trait ExtraCopy<T:Copy> { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.rs b/src/test/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.rs
new file mode 100644
index 0000000..e55316b
--- /dev/null
+++ b/src/test/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.rs
@@ -0,0 +1,18 @@
+fn require_copy<T: Copy>(x: T) {}
+
+struct Foo<T> { x: T }
+
+// Ensure constraints are only attached to methods locally
+impl<T> Foo<T> {
+    fn needs_copy(self) where T: Copy {
+        require_copy(self.x);
+
+    }
+
+    fn fails_copy(self) {
+        require_copy(self.x);
+        //~^ ERROR the trait bound `T: std::marker::Copy` is not satisfied
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr b/src/test/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr
new file mode 100644
index 0000000..125b65b
--- /dev/null
+++ b/src/test/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr
@@ -0,0 +1,16 @@
+error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
+  --> $DIR/where-clause-constraints-are-local-for-inherent-impl.rs:13:9
+   |
+LL |         require_copy(self.x);
+   |         ^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
+   |
+   = help: consider adding a `where T: std::marker::Copy` bound
+note: required by `require_copy`
+  --> $DIR/where-clause-constraints-are-local-for-inherent-impl.rs:1:1
+   |
+LL | fn require_copy<T: Copy>(x: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.rs b/src/test/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.rs
new file mode 100644
index 0000000..b628a2a
--- /dev/null
+++ b/src/test/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.rs
@@ -0,0 +1,23 @@
+fn require_copy<T: Copy>(x: T) {}
+
+struct Bar<T> { x: T }
+
+trait Foo<T> {
+    fn needs_copy(self) where T: Copy;
+    fn fails_copy(self);
+}
+
+// Ensure constraints are only attached to methods locally
+impl<T> Foo<T> for Bar<T> {
+    fn needs_copy(self) where T: Copy {
+        require_copy(self.x);
+
+    }
+
+    fn fails_copy(self) {
+        require_copy(self.x);
+        //~^ ERROR the trait bound `T: std::marker::Copy` is not satisfied
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr b/src/test/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr
new file mode 100644
index 0000000..eb555b1
--- /dev/null
+++ b/src/test/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr
@@ -0,0 +1,16 @@
+error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
+  --> $DIR/where-clause-constraints-are-local-for-trait-impl.rs:18:9
+   |
+LL |         require_copy(self.x);
+   |         ^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
+   |
+   = help: consider adding a `where T: std::marker::Copy` bound
+note: required by `require_copy`
+  --> $DIR/where-clause-constraints-are-local-for-trait-impl.rs:1:1
+   |
+LL | fn require_copy<T: Copy>(x: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/where-clauses/where-clause-method-substituion.rs b/src/test/ui/where-clauses/where-clause-method-substituion.rs
new file mode 100644
index 0000000..4607783
--- /dev/null
+++ b/src/test/ui/where-clauses/where-clause-method-substituion.rs
@@ -0,0 +1,22 @@
+trait Foo<T> {
+    fn dummy(&self, t: T) { }
+}
+
+trait Bar<A> {
+    fn method<B>(&self) where A: Foo<B>;
+}
+
+struct S;
+struct X;
+
+// Remove this impl causing the below resolution to fail // impl Foo<S> for X {}
+
+impl Bar<X> for isize {
+    fn method<U>(&self) where X: Foo<U> {
+    }
+}
+
+fn main() {
+    1.method::<X>();
+    //~^ ERROR the trait bound `X: Foo<X>` is not satisfied
+}
diff --git a/src/test/ui/where-clauses/where-clause-method-substituion.stderr b/src/test/ui/where-clauses/where-clause-method-substituion.stderr
new file mode 100644
index 0000000..cb381d2
--- /dev/null
+++ b/src/test/ui/where-clauses/where-clause-method-substituion.stderr
@@ -0,0 +1,9 @@
+error[E0277]: the trait bound `X: Foo<X>` is not satisfied
+  --> $DIR/where-clause-method-substituion.rs:20:7
+   |
+LL |     1.method::<X>();
+   |       ^^^^^^ the trait `Foo<X>` is not implemented for `X`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/where-clauses/where-clauses-method-unsatisfied.rs b/src/test/ui/where-clauses/where-clauses-method-unsatisfied.rs
new file mode 100644
index 0000000..d63f37a
--- /dev/null
+++ b/src/test/ui/where-clauses/where-clauses-method-unsatisfied.rs
@@ -0,0 +1,20 @@
+// Test that a where clause attached to a method allows us to add
+// additional constraints to a parameter out of scope.
+
+struct Foo<T> {
+    value: T
+}
+
+struct Bar; // does not implement Eq
+
+impl<T> Foo<T> {
+    fn equals(&self, u: &Foo<T>) -> bool where T : Eq {
+        self.value == u.value
+    }
+}
+
+fn main() {
+    let x = Foo { value: Bar };
+    x.equals(&x);
+    //~^ ERROR `Bar: std::cmp::Eq` is not satisfied
+}
diff --git a/src/test/ui/where-clauses/where-clauses-method-unsatisfied.stderr b/src/test/ui/where-clauses/where-clauses-method-unsatisfied.stderr
new file mode 100644
index 0000000..60bcba0
--- /dev/null
+++ b/src/test/ui/where-clauses/where-clauses-method-unsatisfied.stderr
@@ -0,0 +1,9 @@
+error[E0277]: the trait bound `Bar: std::cmp::Eq` is not satisfied
+  --> $DIR/where-clauses-method-unsatisfied.rs:18:7
+   |
+LL |     x.equals(&x);
+   |       ^^^^^^ the trait `std::cmp::Eq` is not implemented for `Bar`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/where-clauses/where-clauses-unsatisfied.rs b/src/test/ui/where-clauses/where-clauses-unsatisfied.rs
new file mode 100644
index 0000000..83620e5
--- /dev/null
+++ b/src/test/ui/where-clauses/where-clauses-unsatisfied.rs
@@ -0,0 +1,8 @@
+fn equal<T>(a: &T, b: &T) -> bool where T : Eq { a == b }
+
+struct Struct;
+
+fn main() {
+    drop(equal(&Struct, &Struct))
+    //~^ ERROR the trait bound `Struct: std::cmp::Eq` is not satisfied
+}
diff --git a/src/test/ui/where-clauses/where-clauses-unsatisfied.stderr b/src/test/ui/where-clauses/where-clauses-unsatisfied.stderr
new file mode 100644
index 0000000..fb69e2d
--- /dev/null
+++ b/src/test/ui/where-clauses/where-clauses-unsatisfied.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `Struct: std::cmp::Eq` is not satisfied
+  --> $DIR/where-clauses-unsatisfied.rs:6:10
+   |
+LL |     drop(equal(&Struct, &Struct))
+   |          ^^^^^ the trait `std::cmp::Eq` is not implemented for `Struct`
+   |
+note: required by `equal`
+  --> $DIR/where-clauses-unsatisfied.rs:1:1
+   |
+LL | fn equal<T>(a: &T, b: &T) -> bool where T : Eq { a == b }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/where-clauses/where-equality-constraints.rs b/src/test/ui/where-clauses/where-equality-constraints.rs
new file mode 100644
index 0000000..f234914
--- /dev/null
+++ b/src/test/ui/where-clauses/where-equality-constraints.rs
@@ -0,0 +1,6 @@
+fn f() where u8 = u16 {}
+//~^ ERROR equality constraints are not yet supported in where clauses
+fn g() where for<'a> &'static (u8,) == u16, {}
+//~^ ERROR equality constraints are not yet supported in where clauses
+
+fn main() {}
diff --git a/src/test/ui/where-clauses/where-equality-constraints.stderr b/src/test/ui/where-clauses/where-equality-constraints.stderr
new file mode 100644
index 0000000..2204470
--- /dev/null
+++ b/src/test/ui/where-clauses/where-equality-constraints.stderr
@@ -0,0 +1,14 @@
+error: equality constraints are not yet supported in where clauses (see #20041)
+  --> $DIR/where-equality-constraints.rs:1:14
+   |
+LL | fn f() where u8 = u16 {}
+   |              ^^^^^^^^
+
+error: equality constraints are not yet supported in where clauses (see #20041)
+  --> $DIR/where-equality-constraints.rs:3:14
+   |
+LL | fn g() where for<'a> &'static (u8,) == u16, {}
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/where-clauses/where-for-self-2.rs b/src/test/ui/where-clauses/where-for-self-2.rs
new file mode 100644
index 0000000..31174fd
--- /dev/null
+++ b/src/test/ui/where-clauses/where-for-self-2.rs
@@ -0,0 +1,22 @@
+// Test that we can quantify lifetimes outside a constraint (i.e., including
+// the self type) in a where clause. Specifically, test that implementing for a
+// specific lifetime is not enough to satisfy the `for<'a> ...` constraint, which
+// should require *all* lifetimes.
+
+static X: &'static u32 = &42;
+
+trait Bar {
+    fn bar(&self);
+}
+
+impl Bar for &'static u32 {
+    fn bar(&self) {}
+}
+
+fn foo<T>(x: &T)
+    where for<'a> &'a T: Bar
+{}
+
+fn main() {
+    foo(&X); //~ ERROR trait bound
+}
diff --git a/src/test/ui/where-clauses/where-for-self-2.stderr b/src/test/ui/where-clauses/where-for-self-2.stderr
new file mode 100644
index 0000000..dbe68b8
--- /dev/null
+++ b/src/test/ui/where-clauses/where-for-self-2.stderr
@@ -0,0 +1,19 @@
+error[E0277]: the trait bound `for<'a> &'a _: Bar` is not satisfied
+  --> $DIR/where-for-self-2.rs:21:5
+   |
+LL |     foo(&X);
+   |     ^^^ the trait `for<'a> Bar` is not implemented for `&'a _`
+   |
+   = help: the following implementations were found:
+             <&'static u32 as Bar>
+note: required by `foo`
+  --> $DIR/where-for-self-2.rs:16:1
+   |
+LL | / fn foo<T>(x: &T)
+LL | |     where for<'a> &'a T: Bar
+LL | | {}
+   | |__^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/where-clauses/where-for-self.rs b/src/test/ui/where-clauses/where-for-self.rs
new file mode 100644
index 0000000..9380e72
--- /dev/null
+++ b/src/test/ui/where-clauses/where-for-self.rs
@@ -0,0 +1,19 @@
+// Test that we can quantify lifetimes outside a constraint (i.e., including
+// the self type) in a where clause. Specifically, test that we cannot nest
+// quantification in constraints (to be clear, there is no reason this should not
+// we're testing we don't crash or do something stupid).
+
+trait Bar<'a> {
+    fn bar(&self);
+}
+
+impl<'a, 'b> Bar<'b> for &'a u32 {
+    fn bar(&self) {}
+}
+
+fn foo<T>(x: &T)
+    where for<'a> &'a T: for<'b> Bar<'b>
+    //~^ error: nested quantification of lifetimes
+{}
+
+fn main() {}
diff --git a/src/test/ui/where-clauses/where-for-self.stderr b/src/test/ui/where-clauses/where-for-self.stderr
new file mode 100644
index 0000000..d06afc1
--- /dev/null
+++ b/src/test/ui/where-clauses/where-for-self.stderr
@@ -0,0 +1,9 @@
+error[E0316]: nested quantification of lifetimes
+  --> $DIR/where-for-self.rs:15:26
+   |
+LL |     where for<'a> &'a T: for<'b> Bar<'b>
+   |                          ^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0316`.
diff --git a/src/test/ui/where-clauses/where-lifetime-resolution.rs b/src/test/ui/where-clauses/where-lifetime-resolution.rs
new file mode 100644
index 0000000..4c46a77
--- /dev/null
+++ b/src/test/ui/where-clauses/where-lifetime-resolution.rs
@@ -0,0 +1,13 @@
+trait Trait1<'a> {}
+trait Trait2<'a, 'b> {}
+
+fn f() where
+    for<'a> Trait1<'a>: Trait1<'a>, // OK
+    (for<'a> Trait1<'a>): Trait1<'a>,
+    //~^ ERROR use of undeclared lifetime name `'a`
+    for<'a> for<'b> Trait2<'a, 'b>: Trait2<'a, 'b>,
+    //~^ ERROR use of undeclared lifetime name `'b`
+    //~| ERROR nested quantification of lifetimes
+{}
+
+fn main() {}
diff --git a/src/test/ui/where-clauses/where-lifetime-resolution.stderr b/src/test/ui/where-clauses/where-lifetime-resolution.stderr
new file mode 100644
index 0000000..ce6354b
--- /dev/null
+++ b/src/test/ui/where-clauses/where-lifetime-resolution.stderr
@@ -0,0 +1,22 @@
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/where-lifetime-resolution.rs:6:34
+   |
+LL |     (for<'a> Trait1<'a>): Trait1<'a>,
+   |                                  ^^ undeclared lifetime
+
+error[E0316]: nested quantification of lifetimes
+  --> $DIR/where-lifetime-resolution.rs:8:13
+   |
+LL |     for<'a> for<'b> Trait2<'a, 'b>: Trait2<'a, 'b>,
+   |             ^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0261]: use of undeclared lifetime name `'b`
+  --> $DIR/where-lifetime-resolution.rs:8:48
+   |
+LL |     for<'a> for<'b> Trait2<'a, 'b>: Trait2<'a, 'b>,
+   |                                                ^^ undeclared lifetime
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0261, E0316.
+For more information about an error, try `rustc --explain E0261`.
diff --git a/src/test/ui/while-let.rs b/src/test/ui/while-let.rs
new file mode 100644
index 0000000..69f9de9
--- /dev/null
+++ b/src/test/ui/while-let.rs
@@ -0,0 +1,28 @@
+// run-pass
+
+fn macros() {
+    macro_rules! foo{
+        ($p:pat, $e:expr, $b:block) => {{
+            while let $p = $e $b
+        }}
+    }
+    macro_rules! bar{
+        ($p:pat, $e:expr, $b:block) => {{
+            foo!($p, $e, $b)
+        }}
+    }
+
+    foo!(a, 1, { //~ WARN irrefutable while-let
+        println!("irrefutable pattern");
+    });
+    bar!(a, 1, { //~ WARN irrefutable while-let
+        println!("irrefutable pattern");
+    });
+}
+
+pub fn main() {
+    while let a = 1 { //~ WARN irrefutable while-let
+        println!("irrefutable pattern");
+        break;
+    }
+}
diff --git a/src/test/ui/while-let.stderr b/src/test/ui/while-let.stderr
new file mode 100644
index 0000000..156d0e6
--- /dev/null
+++ b/src/test/ui/while-let.stderr
@@ -0,0 +1,33 @@
+warning: irrefutable while-let pattern
+  --> $DIR/while-let.rs:6:13
+   |
+LL |               while let $p = $e $b
+   |               ^^^^^
+...
+LL | /     foo!(a, 1, {
+LL | |         println!("irrefutable pattern");
+LL | |     });
+   | |_______- in this macro invocation
+   |
+   = note: #[warn(irrefutable_let_patterns)] on by default
+
+warning: irrefutable while-let pattern
+  --> $DIR/while-let.rs:6:13
+   |
+LL |               while let $p = $e $b
+   |               ^^^^^
+...
+LL | /     bar!(a, 1, {
+LL | |         println!("irrefutable pattern");
+LL | |     });
+   | |_______- in this macro invocation
+
+warning: irrefutable while-let pattern
+  --> $DIR/while-let.rs:24:5
+   |
+LL | /     while let a = 1 {
+LL | |         println!("irrefutable pattern");
+LL | |         break;
+LL | |     }
+   | |_____^
+
diff --git a/src/test/ui/while-type-error.rs b/src/test/ui/while-type-error.rs
new file mode 100644
index 0000000..8098bfc
--- /dev/null
+++ b/src/test/ui/while-type-error.rs
@@ -0,0 +1,3 @@
+// error-pattern: mismatched types
+
+fn main() { while main { } }
diff --git a/src/test/ui/while-type-error.stderr b/src/test/ui/while-type-error.stderr
new file mode 100644
index 0000000..1516967
--- /dev/null
+++ b/src/test/ui/while-type-error.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/while-type-error.rs:3:19
+   |
+LL | fn main() { while main { } }
+   |                   ^^^^ expected bool, found fn item
+   |
+   = note: expected type `bool`
+              found type `fn() {main}`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/windows-subsystem-invalid.rs b/src/test/ui/windows-subsystem-invalid.rs
new file mode 100644
index 0000000..0336678
--- /dev/null
+++ b/src/test/ui/windows-subsystem-invalid.rs
@@ -0,0 +1,5 @@
+// error-pattern: invalid windows subsystem `wrong`, only `windows` and `console` are allowed
+
+#![windows_subsystem = "wrong"]
+
+fn main() {}
diff --git a/src/test/ui/windows-subsystem-invalid.stderr b/src/test/ui/windows-subsystem-invalid.stderr
new file mode 100644
index 0000000..0cb843c
--- /dev/null
+++ b/src/test/ui/windows-subsystem-invalid.stderr
@@ -0,0 +1,4 @@
+error: invalid windows subsystem `wrong`, only `windows` and `console` are allowed
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/write-to-static-mut-in-static.rs b/src/test/ui/write-to-static-mut-in-static.rs
new file mode 100644
index 0000000..43c63fe
--- /dev/null
+++ b/src/test/ui/write-to-static-mut-in-static.rs
@@ -0,0 +1,10 @@
+pub static mut A: u32 = 0;
+pub static mut B: () = unsafe { A = 1; };
+//~^ ERROR could not evaluate static initializer
+
+pub static mut C: u32 = unsafe { C = 1; 0 };
+//~^ ERROR cycle detected
+
+pub static D: u32 = D;
+
+fn main() {}
diff --git a/src/test/ui/write-to-static-mut-in-static.stderr b/src/test/ui/write-to-static-mut-in-static.stderr
new file mode 100644
index 0000000..eba1c60
--- /dev/null
+++ b/src/test/ui/write-to-static-mut-in-static.stderr
@@ -0,0 +1,28 @@
+error[E0080]: could not evaluate static initializer
+  --> $DIR/write-to-static-mut-in-static.rs:2:33
+   |
+LL | pub static mut B: () = unsafe { A = 1; };
+   |                                 ^^^^^ tried to modify a static's initial value from another static's initializer
+
+error[E0391]: cycle detected when const-evaluating `C`
+  --> $DIR/write-to-static-mut-in-static.rs:5:34
+   |
+LL | pub static mut C: u32 = unsafe { C = 1; 0 };
+   |                                  ^^^^^
+   |
+note: ...which requires const-evaluating `C`...
+  --> $DIR/write-to-static-mut-in-static.rs:5:1
+   |
+LL | pub static mut C: u32 = unsafe { C = 1; 0 };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: ...which again requires const-evaluating `C`, completing the cycle
+note: cycle used when const-evaluating + checking `C`
+  --> $DIR/write-to-static-mut-in-static.rs:5:1
+   |
+LL | pub static mut C: u32 = unsafe { C = 1; 0 };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0080, E0391.
+For more information about an error, try `rustc --explain E0080`.
diff --git a/src/test/ui/writing-to-immutable-vec.nll.stderr b/src/test/ui/writing-to-immutable-vec.nll.stderr
new file mode 100644
index 0000000..a65765c
--- /dev/null
+++ b/src/test/ui/writing-to-immutable-vec.nll.stderr
@@ -0,0 +1,11 @@
+error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable
+  --> $DIR/writing-to-immutable-vec.rs:3:5
+   |
+LL |     let v: Vec<isize> = vec![1, 2, 3];
+   |         - help: consider changing this to be mutable: `mut v`
+LL |     v[1] = 4;
+   |     ^ cannot borrow as mutable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/writing-to-immutable-vec.rs b/src/test/ui/writing-to-immutable-vec.rs
new file mode 100644
index 0000000..ad2bf33
--- /dev/null
+++ b/src/test/ui/writing-to-immutable-vec.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let v: Vec<isize> = vec![1, 2, 3];
+    v[1] = 4; //~ ERROR cannot borrow immutable local variable `v` as mutable
+}
diff --git a/src/test/ui/writing-to-immutable-vec.stderr b/src/test/ui/writing-to-immutable-vec.stderr
new file mode 100644
index 0000000..9bc82df
--- /dev/null
+++ b/src/test/ui/writing-to-immutable-vec.stderr
@@ -0,0 +1,11 @@
+error[E0596]: cannot borrow immutable local variable `v` as mutable
+  --> $DIR/writing-to-immutable-vec.rs:3:5
+   |
+LL |     let v: Vec<isize> = vec![1, 2, 3];
+   |         - help: make this binding mutable: `mut v`
+LL |     v[1] = 4;
+   |     ^ cannot borrow mutably
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/wrong-mul-method-signature.rs b/src/test/ui/wrong-mul-method-signature.rs
new file mode 100644
index 0000000..54e2af5
--- /dev/null
+++ b/src/test/ui/wrong-mul-method-signature.rs
@@ -0,0 +1,69 @@
+// This test is to make sure we don't just ICE if the trait
+// method for an operator is not implemented properly.
+// (In this case the mul method should take &f64 and not f64)
+// See: #11450
+
+use std::ops::Mul;
+
+struct Vec1 {
+    x: f64
+}
+
+// Expecting value in input signature
+impl Mul<f64> for Vec1 {
+    type Output = Vec1;
+
+    fn mul(self, s: &f64) -> Vec1 {
+    //~^ ERROR method `mul` has an incompatible type for trait
+        Vec1 {
+            x: self.x * *s
+        }
+    }
+}
+
+struct Vec2 {
+    x: f64,
+    y: f64
+}
+
+// Wrong type parameter ordering
+impl Mul<Vec2> for Vec2 {
+    type Output = f64;
+
+    fn mul(self, s: f64) -> Vec2 {
+    //~^ ERROR method `mul` has an incompatible type for trait
+        Vec2 {
+            x: self.x * s,
+            y: self.y * s
+        }
+    }
+}
+
+struct Vec3 {
+    x: f64,
+    y: f64,
+    z: f64
+}
+
+// Unexpected return type
+impl Mul<f64> for Vec3 {
+    type Output = i32;
+
+    fn mul(self, s: f64) -> f64 {
+    //~^ ERROR method `mul` has an incompatible type for trait
+        s
+    }
+}
+
+pub fn main() {
+    // Check that the usage goes from the trait declaration:
+
+    let x: Vec1 = Vec1 { x: 1.0 } * 2.0; // this is OK
+
+    let x: Vec2 = Vec2 { x: 1.0, y: 2.0 } * 2.0; // trait had reversed order
+    // (we no longer signal a compile error here, since the
+    //  error in the trait signature will cause compilation to
+    //  abort before we bother looking at function bodies.)
+
+    let x: i32 = Vec3 { x: 1.0, y: 2.0, z: 3.0 } * 2.0;
+}
diff --git a/src/test/ui/wrong-mul-method-signature.stderr b/src/test/ui/wrong-mul-method-signature.stderr
new file mode 100644
index 0000000..8630ebc
--- /dev/null
+++ b/src/test/ui/wrong-mul-method-signature.stderr
@@ -0,0 +1,30 @@
+error[E0053]: method `mul` has an incompatible type for trait
+  --> $DIR/wrong-mul-method-signature.rs:16:5
+   |
+LL |     fn mul(self, s: &f64) -> Vec1 {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected f64, found &f64
+   |
+   = note: expected type `fn(Vec1, f64) -> Vec1`
+              found type `fn(Vec1, &f64) -> Vec1`
+
+error[E0053]: method `mul` has an incompatible type for trait
+  --> $DIR/wrong-mul-method-signature.rs:33:5
+   |
+LL |     fn mul(self, s: f64) -> Vec2 {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `Vec2`, found f64
+   |
+   = note: expected type `fn(Vec2, Vec2) -> f64`
+              found type `fn(Vec2, f64) -> Vec2`
+
+error[E0053]: method `mul` has an incompatible type for trait
+  --> $DIR/wrong-mul-method-signature.rs:52:5
+   |
+LL |     fn mul(self, s: f64) -> f64 {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected i32, found f64
+   |
+   = note: expected type `fn(Vec3, f64) -> i32`
+              found type `fn(Vec3, f64) -> f64`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0053`.
diff --git a/src/test/ui/wrong-ret-type.rs b/src/test/ui/wrong-ret-type.rs
new file mode 100644
index 0000000..cbff8db
--- /dev/null
+++ b/src/test/ui/wrong-ret-type.rs
@@ -0,0 +1,3 @@
+// error-pattern: mismatched types
+fn mk_int() -> usize { let i: isize = 3; return i; }
+fn main() { }
diff --git a/src/test/ui/wrong-ret-type.stderr b/src/test/ui/wrong-ret-type.stderr
new file mode 100644
index 0000000..cf59f42
--- /dev/null
+++ b/src/test/ui/wrong-ret-type.stderr
@@ -0,0 +1,11 @@
+error[E0308]: mismatched types
+  --> $DIR/wrong-ret-type.rs:2:49
+   |
+LL | fn mk_int() -> usize { let i: isize = 3; return i; }
+   |                -----                            ^ expected usize, found isize
+   |                |
+   |                expected `usize` because of return type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/xc-private-method.rs b/src/test/ui/xc-private-method.rs
new file mode 100644
index 0000000..e95cab9
--- /dev/null
+++ b/src/test/ui/xc-private-method.rs
@@ -0,0 +1,11 @@
+// aux-build:xc-private-method-lib.rs
+
+extern crate xc_private_method_lib;
+
+fn main() {
+    let _ = xc_private_method_lib::Struct::static_meth_struct();
+    //~^ ERROR: method `static_meth_struct` is private
+
+    let _ = xc_private_method_lib::Enum::static_meth_enum();
+    //~^ ERROR: method `static_meth_enum` is private
+}
diff --git a/src/test/ui/xc-private-method.stderr b/src/test/ui/xc-private-method.stderr
new file mode 100644
index 0000000..91bec25
--- /dev/null
+++ b/src/test/ui/xc-private-method.stderr
@@ -0,0 +1,15 @@
+error[E0624]: method `static_meth_struct` is private
+  --> $DIR/xc-private-method.rs:6:13
+   |
+LL |     let _ = xc_private_method_lib::Struct::static_meth_struct();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0624]: method `static_meth_enum` is private
+  --> $DIR/xc-private-method.rs:9:13
+   |
+LL |     let _ = xc_private_method_lib::Enum::static_meth_enum();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0624`.
diff --git a/src/test/ui/xc-private-method2.rs b/src/test/ui/xc-private-method2.rs
new file mode 100644
index 0000000..f11b251
--- /dev/null
+++ b/src/test/ui/xc-private-method2.rs
@@ -0,0 +1,11 @@
+// aux-build:xc-private-method-lib.rs
+
+extern crate xc_private_method_lib;
+
+fn main() {
+    let _ = xc_private_method_lib::Struct{ x: 10 }.meth_struct();
+    //~^ ERROR method `meth_struct` is private
+
+    let _ = xc_private_method_lib::Enum::Variant1(20).meth_enum();
+    //~^ ERROR method `meth_enum` is private
+}
diff --git a/src/test/ui/xc-private-method2.stderr b/src/test/ui/xc-private-method2.stderr
new file mode 100644
index 0000000..36ad850
--- /dev/null
+++ b/src/test/ui/xc-private-method2.stderr
@@ -0,0 +1,15 @@
+error[E0624]: method `meth_struct` is private
+  --> $DIR/xc-private-method2.rs:6:52
+   |
+LL |     let _ = xc_private_method_lib::Struct{ x: 10 }.meth_struct();
+   |                                                    ^^^^^^^^^^^
+
+error[E0624]: method `meth_enum` is private
+  --> $DIR/xc-private-method2.rs:9:55
+   |
+LL |     let _ = xc_private_method_lib::Enum::Variant1(20).meth_enum();
+   |                                                       ^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0624`.
diff --git a/src/test/ui/xcrate/auxiliary/static_priv_by_default.rs b/src/test/ui/xcrate/auxiliary/static_priv_by_default.rs
new file mode 100644
index 0000000..39f9120
--- /dev/null
+++ b/src/test/ui/xcrate/auxiliary/static_priv_by_default.rs
@@ -0,0 +1,51 @@
+#![crate_type = "lib"]
+
+static private: isize = 0;
+pub static public: isize = 0;
+
+pub struct A(());
+
+impl A {
+    fn foo() {}
+}
+
+mod foo {
+    pub static a: isize = 0;
+    pub fn b() {}
+    pub struct c;
+    pub enum d {}
+    pub type e = isize;
+
+    pub struct A(());
+
+    impl A {
+        fn foo() {}
+    }
+
+    // these are public so the parent can re-export them.
+    pub static reexported_a: isize = 0;
+    pub fn reexported_b() {}
+    pub struct reexported_c;
+    pub enum reexported_d {}
+    pub type reexported_e = isize;
+}
+
+pub mod bar {
+    pub use foo::reexported_a as e;
+    pub use foo::reexported_b as f;
+    pub use foo::reexported_c as g;
+    pub use foo::reexported_d as h;
+    pub use foo::reexported_e as i;
+}
+
+pub static a: isize = 0;
+pub fn b() {}
+pub struct c;
+pub enum d {}
+pub type e = isize;
+
+static j: isize = 0;
+fn k() {}
+struct l;
+enum m {}
+type n = isize;
diff --git a/src/test/ui/xcrate/auxiliary/xcrate_unit_struct.rs b/src/test/ui/xcrate/auxiliary/xcrate_unit_struct.rs
new file mode 100644
index 0000000..69ed498
--- /dev/null
+++ b/src/test/ui/xcrate/auxiliary/xcrate_unit_struct.rs
@@ -0,0 +1,28 @@
+#![crate_type = "lib"]
+
+// used by the rpass test
+
+#[derive(Copy, Clone)]
+pub struct Struct;
+
+#[derive(Copy, Clone)]
+pub enum Unit {
+    UnitVariant,
+    Argument(Struct)
+}
+
+#[derive(Copy, Clone)]
+pub struct TupleStruct(pub usize, pub &'static str);
+
+// used by the cfail test
+
+#[derive(Copy, Clone)]
+pub struct StructWithFields {
+    foo: isize,
+}
+
+#[derive(Copy, Clone)]
+pub enum EnumWithVariants {
+    EnumVariant,
+    EnumVariantArg(isize)
+}
diff --git a/src/test/ui/xcrate/xcrate-private-by-default.rs b/src/test/ui/xcrate/xcrate-private-by-default.rs
new file mode 100644
index 0000000..299cff5
--- /dev/null
+++ b/src/test/ui/xcrate/xcrate-private-by-default.rs
@@ -0,0 +1,45 @@
+// aux-build:static_priv_by_default.rs
+
+extern crate static_priv_by_default;
+
+fn foo<T>() {}
+
+fn main() {
+    // Actual public items should be public
+    static_priv_by_default::a;
+    static_priv_by_default::b;
+    static_priv_by_default::c;
+    foo::<static_priv_by_default::d>();
+    foo::<static_priv_by_default::e>();
+
+    // publicly re-exported items should be available
+    static_priv_by_default::bar::e;
+    static_priv_by_default::bar::f;
+    static_priv_by_default::bar::g;
+    foo::<static_priv_by_default::bar::h>();
+    foo::<static_priv_by_default::bar::i>();
+
+    // private items at the top should be inaccessible
+    static_priv_by_default::j;
+    //~^ ERROR: static `j` is private
+    static_priv_by_default::k;
+    //~^ ERROR: function `k` is private
+    static_priv_by_default::l;
+    //~^ ERROR: struct `l` is private
+    foo::<static_priv_by_default::m>();
+    //~^ ERROR: enum `m` is private
+    foo::<static_priv_by_default::n>();
+    //~^ ERROR: type alias `n` is private
+
+    // public items in a private mod should be inaccessible
+    static_priv_by_default::foo::a;
+    //~^ ERROR: module `foo` is private
+    static_priv_by_default::foo::b;
+    //~^ ERROR: module `foo` is private
+    static_priv_by_default::foo::c;
+    //~^ ERROR: module `foo` is private
+    foo::<static_priv_by_default::foo::d>();
+    //~^ ERROR: module `foo` is private
+    foo::<static_priv_by_default::foo::e>();
+    //~^ ERROR: module `foo` is private
+}
diff --git a/src/test/ui/xcrate/xcrate-private-by-default.stderr b/src/test/ui/xcrate/xcrate-private-by-default.stderr
new file mode 100644
index 0000000..da52b42
--- /dev/null
+++ b/src/test/ui/xcrate/xcrate-private-by-default.stderr
@@ -0,0 +1,63 @@
+error[E0603]: static `j` is private
+  --> $DIR/xcrate-private-by-default.rs:23:29
+   |
+LL |     static_priv_by_default::j;
+   |                             ^
+
+error[E0603]: function `k` is private
+  --> $DIR/xcrate-private-by-default.rs:25:29
+   |
+LL |     static_priv_by_default::k;
+   |                             ^
+
+error[E0603]: unit struct `l` is private
+  --> $DIR/xcrate-private-by-default.rs:27:29
+   |
+LL |     static_priv_by_default::l;
+   |                             ^
+
+error[E0603]: enum `m` is private
+  --> $DIR/xcrate-private-by-default.rs:29:35
+   |
+LL |     foo::<static_priv_by_default::m>();
+   |                                   ^
+
+error[E0603]: type alias `n` is private
+  --> $DIR/xcrate-private-by-default.rs:31:35
+   |
+LL |     foo::<static_priv_by_default::n>();
+   |                                   ^
+
+error[E0603]: module `foo` is private
+  --> $DIR/xcrate-private-by-default.rs:35:29
+   |
+LL |     static_priv_by_default::foo::a;
+   |                             ^^^
+
+error[E0603]: module `foo` is private
+  --> $DIR/xcrate-private-by-default.rs:37:29
+   |
+LL |     static_priv_by_default::foo::b;
+   |                             ^^^
+
+error[E0603]: module `foo` is private
+  --> $DIR/xcrate-private-by-default.rs:39:29
+   |
+LL |     static_priv_by_default::foo::c;
+   |                             ^^^
+
+error[E0603]: module `foo` is private
+  --> $DIR/xcrate-private-by-default.rs:41:35
+   |
+LL |     foo::<static_priv_by_default::foo::d>();
+   |                                   ^^^
+
+error[E0603]: module `foo` is private
+  --> $DIR/xcrate-private-by-default.rs:43:35
+   |
+LL |     foo::<static_priv_by_default::foo::e>();
+   |                                   ^^^
+
+error: aborting due to 10 previous errors
+
+For more information about this error, try `rustc --explain E0603`.
diff --git a/src/test/ui/xcrate/xcrate-unit-struct.rs b/src/test/ui/xcrate/xcrate-unit-struct.rs
new file mode 100644
index 0000000..c99cf77
--- /dev/null
+++ b/src/test/ui/xcrate/xcrate-unit-struct.rs
@@ -0,0 +1,12 @@
+// aux-build:xcrate_unit_struct.rs
+
+// Make sure that when we have cross-crate unit structs we don't accidentally
+// make values out of cross-crate structs that aren't unit.
+
+extern crate xcrate_unit_struct;
+
+fn main() {
+    let _ = xcrate_unit_struct::StructWithFields;
+    //~^ ERROR expected value, found struct `xcrate_unit_struct::StructWithFields`
+    let _ = xcrate_unit_struct::Struct;
+}
diff --git a/src/test/ui/xcrate/xcrate-unit-struct.stderr b/src/test/ui/xcrate/xcrate-unit-struct.stderr
new file mode 100644
index 0000000..e4a4b9c
--- /dev/null
+++ b/src/test/ui/xcrate/xcrate-unit-struct.stderr
@@ -0,0 +1,9 @@
+error[E0423]: expected value, found struct `xcrate_unit_struct::StructWithFields`
+  --> $DIR/xcrate-unit-struct.rs:9:13
+   |
+LL |     let _ = xcrate_unit_struct::StructWithFields;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ did you mean `xcrate_unit_struct::StructWithFields { /* fields */ }`?
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0423`.